diff --git a/@file_array/size.m b/@file_array/size.m index b6e7d8c..1bb756f 100644 --- a/@file_array/size.m +++ b/@file_array/size.m @@ -4,13 +4,14 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % -% $Id: size.m 1143 2008-02-07 19:33:33Z spm $ +% $Id: size.m 3730 2010-02-17 13:24:26Z john $ sa = struct(a); nd = 0; for i=1:numel(sa), nd = max(nd,numel(sa(i).dim)); + nd = max(nd,max(find(sa(i).pos==1))); end nd = nd+1; diff --git a/@file_array/subsref.m b/@file_array/subsref.m index b82b5a8..e59bcdd 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 3418 2009-09-25 11:06:39Z guillaume $ +% $Id: subsref.m 3958 2010-06-30 16:24:46Z guillaume $ if isempty(subs), return; end @@ -156,7 +156,11 @@ dt = datatypes; dt = dt([dt.code]==sobj.dtype); sz = dt.size; -mem = 400*1024*1024; % in bytes, has to be a multiple of 16 (max([dt.size])) +try + mem = spm('Memory'); % in bytes, has to be a multiple of 16 (max([dt.size])) +catch + mem = 200 * 1024 * 1024; +end s = ceil(prod(sobj.dim) * sz / mem); % Assign indices to partitions diff --git a/@gifti/gifti.m b/@gifti/gifti.m index a15ac60..554550a 100644 --- a/@gifti/gifti.m +++ b/@gifti/gifti.m @@ -8,7 +8,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Guillaume Flandin -% $Id: gifti.m 2587 2009-01-05 12:11:39Z vladimir $ +% $Id: gifti.m 3999 2010-07-19 10:54:18Z guillaume $ switch nargin @@ -38,6 +38,14 @@ error('[GIFTI] Invalid structure.'); end + elseif ishandle(varargin{1}) + this = struct('vertices',get(varargin{1},'Vertices'), ... + 'faces', get(varargin{1},'Faces')); + if ~isempty(get(varargin{1},'FaceVertexCData')); + this.cdata = get(varargin{1},'FaceVertexCData'); + end + this = gifti(this); + elseif isnumeric(varargin{1}) this = gifti; this = subsasgn(this,... diff --git a/@gifti/private/isintent.m b/@gifti/private/isintent.m index 2bc7be8..cba42b9 100644 --- a/@gifti/private/isintent.m +++ b/@gifti/private/isintent.m @@ -9,7 +9,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Guillaume Flandin -% $Id: isintent.m 3556 2009-11-11 18:20:34Z guillaume $ +% $Id: isintent.m 3999 2010-07-19 10:54:18Z guillaume $ a = []; b = []; @@ -51,11 +51,11 @@ fprintf('Intent %s is ignored.\n',this.data{i}.attributes.Intent); end end -[d,i] = unique(a); +[d,i] = unique(a,'first'); if length(d) < length(a) - warning('Several fields match intent type. Using first.'); + %warning('Several fields match intent type. Using first.'); a = a(i); - b = b(i); + %b = b(i); end function c = cdata diff --git a/@gifti/private/read_gifti_file.m b/@gifti/private/read_gifti_file.m index ab98fe4..74861b3 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 2076 2008-09-10 12:34:08Z guillaume $ +% $Id: read_gifti_file.m 3999 2010-07-19 10:54:18Z guillaume $ % Import XML-based GIfTI file %-------------------------------------------------------------------------- @@ -23,8 +23,8 @@ error('[GIFTI] %s is not a GIFTI 1.0 file.', filename); end attr = cell2mat(attributes(t,'get',root(t))); -attr = cell2struct({attr.val},{attr.key},2); -if ~isempty(setxor(fieldnames(attr),{'Version','NumberOfDataArrays'})) +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 if str2double(attr.Version) ~= 1 diff --git a/@gifti/save.m b/@gifti/save.m index 4efb4ae..4ecffb7 100644 --- a/@gifti/save.m +++ b/@gifti/save.m @@ -5,12 +5,12 @@ function save(this,filename,encoding) % filename - name of GIfTI file that will be created % encoding - optional argument to specify encoding format, among % ASCII, Base64Binary, GZipBase64Binary, ExternalFileBinary, -% Collada (.dae) +% Collada (.dae), IDTF (.idtf). %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Guillaume Flandin -% $Id: save.m 3556 2009-11-11 18:20:34Z guillaume $ +% $Id: save.m 3999 2010-07-19 10:54:18Z guillaume $ error(nargchk(1,3,nargin)); @@ -23,6 +23,9 @@ function save(this,filename,encoding) if nargin == 3 && strcmpi(encoding,'collada') ext = '.dae'; end + if nargin == 3 && strcmpi(encoding,'idtf') + ext = '.idtf'; + end [p,f,e] = fileparts(filename); if ~ismember(lower(e),{ext}) e = ext; @@ -45,6 +48,8 @@ function save(this,filename,encoding) fid = save_gii(fid,this,encoding); case '.dae' fid = save_dae(fid,this); + case '.idtf' + fid = save_idtf(fid,this); otherwise error('Unknown file format.'); end @@ -105,12 +110,12 @@ function save(this,filename,encoding) case {'ASCII', 'Base64Binary','GZipBase64Binary' } case 'ExternalFileBinary' extfilename = this.data{i}.attributes.ExternalFileName; - [p,f] = fileparts(filename); if isempty(extfilename) + [p,f] = fileparts(fopen(fid)); extfilename = [f '.dat']; end [p,f,e] = fileparts(extfilename); - this.data{i}.attributes.ExternalFileName = fullfile(fileparts(filename),[f e]); + this.data{i}.attributes.ExternalFileName = fullfile(fileparts(fopen(fid)),[f e]); this.data{i}.attributes.ExternalFileOffset = num2str(def.offset); otherwise error('[GIFTI] Unknown data encoding: %s.',this.data{i}.attributes.Encoding); @@ -123,7 +128,7 @@ function save(this,filename,encoding) fprintf(fid,'\n'); fprintf(fid,'\n',numel(this.data)); -o = inline('blanks(x*3)'); +o = @(x) blanks(x*3); % MetaData %-------------------------------------------------------------------------- @@ -379,3 +384,148 @@ function save(this,filename,encoding) % End of XML %-------------------------------------------------------------------------- fprintf(fid,'\n'); + +%========================================================================== +% function fid = save_idtf(fid,this) +%========================================================================== +function fid = save_idtf(fid,this) + +o = inline('blanks(x*3)'); + +s = struct(this); + +% Compute normals +%-------------------------------------------------------------------------- +if ~isfield(s,'normals') + try + s.normals = spm_mesh_normals(... + struct('vertices',s.vertices,'faces',s.faces),true); + catch + s.normals = []; + end +end + +% Split the mesh into connected components +%-------------------------------------------------------------------------- +try + C = spm_mesh_label(s.faces); + d = []; + try + if size(s.cdata,2) == 1 && (any(s.cdata>1) || any(s.cdata<0)) + mi = min(s.cdata); ma = max(s.cdata); + s.cdata = (s.cdata-mi)/ (ma-mi); + else + end + end + for i=1:numel(unique(C)) + d(i).faces = s.faces(C==i,:); + u = unique(d(i).faces); + d(i).vertices = s.vertices(u,:); + d(i).normals = s.normals(u,:); + a = 1:max(d(i).faces(:)); + a(u) = 1:size(d(i).vertices,1); + %a = sparse(1,double(u),1:1:size(d(i).vertices,1)); + d(i).faces = a(d(i).faces); + d(i).mat = s.mat; + try + d(i).cdata = s.cdata(u,:); + if size(d(i).cdata,2) == 1 + d(i).cdata = repmat(d(i).cdata,1,3); + end + end + end + s = d; +end + +% FILE_HEADER +%-------------------------------------------------------------------------- +fprintf(fid,'FILE_FORMAT "IDTF"\n'); +fprintf(fid,'FORMAT_VERSION 100\n\n'); + +% NODES +%-------------------------------------------------------------------------- +for i=1:numel(s) + fprintf(fid,'NODE "MODEL" {\n'); + fprintf(fid,'%sNODE_NAME "%s"\n',o(1),sprintf('Mesh%04d',i)); + fprintf(fid,'%sPARENT_LIST {\n',o(1)); + fprintf(fid,'%sPARENT_COUNT %d\n',o(2),1); + fprintf(fid,'%sPARENT %d {\n',o(2),0); + fprintf(fid,'%sPARENT_NAME "%s"\n',o(3),''); + fprintf(fid,'%sPARENT_TM {\n',o(3)); + I = s(i).mat; % eye(4); + for j=1:size(I,2) + fprintf(fid,'%s',o(4)); fprintf(fid,'%f ',I(:,j)'); fprintf(fid,'\n'); + end + fprintf(fid,'%s}\n',o(3)); + fprintf(fid,'%s}\n',o(2)); + fprintf(fid,'%s}\n',o(1)); + fprintf(fid,'%sRESOURCE_NAME "%s"\n',o(1),sprintf('Mesh%04d',i)); + %fprintf(fid,'%sMODEL_VISIBILITY "BOTH"\n',o(1)); + fprintf(fid,'}\n\n'); +end + +% NODE_RESOURCES +%-------------------------------------------------------------------------- +for i=1:numel(s) + fprintf(fid,'RESOURCE_LIST "MODEL" {\n'); + fprintf(fid,'%sRESOURCE_COUNT %d\n',o(1),1); + fprintf(fid,'%sRESOURCE %d {\n',o(1),0); + fprintf(fid,'%sRESOURCE_NAME "%s"\n',o(2),sprintf('Mesh%04d',i)); + fprintf(fid,'%sMODEL_TYPE "MESH"\n',o(2)); + fprintf(fid,'%sMESH {\n',o(2)); + fprintf(fid,'%sFACE_COUNT %d\n',o(3),size(s(i).faces,1)); + fprintf(fid,'%sMODEL_POSITION_COUNT %d\n',o(3),size(s(i).vertices,1)); + fprintf(fid,'%sMODEL_NORMAL_COUNT %d\n',o(3),size(s(i).normals,1)); + if ~isfield(s(i),'cdata') || isempty(s(i).cdata) + c = 0; + else + c = size(s(i).cdata,1); + end + fprintf(fid,'%sMODEL_DIFFUSE_COLOR_COUNT %d\n',o(3),c); + fprintf(fid,'%sMODEL_SPECULAR_COLOR_COUNT %d\n',o(3),0); + fprintf(fid,'%sMODEL_TEXTURE_COORD_COUNT %d\n',o(3),0); + fprintf(fid,'%sMODEL_BONE_COUNT %d\n',o(3),0); + fprintf(fid,'%sMODEL_SHADING_COUNT %d\n',o(3),1); + fprintf(fid,'%sMODEL_SHADING_DESCRIPTION_LIST {\n',o(3)); + fprintf(fid,'%sSHADING_DESCRIPTION %d {\n',o(4),0); + fprintf(fid,'%sTEXTURE_LAYER_COUNT %d\n',o(5),0); + fprintf(fid,'%sSHADER_ID %d\n',o(5),0); + fprintf(fid,'%s}\n',o(4)); + fprintf(fid,'%s}\n',o(3)); + + fprintf(fid,'%sMESH_FACE_POSITION_LIST {\n',o(3)); + fprintf(fid,'%d %d %d\n',s(i).faces'-1); + fprintf(fid,'%s}\n',o(3)); + + fprintf(fid,'%sMESH_FACE_NORMAL_LIST {\n',o(3)); + fprintf(fid,'%d %d %d\n',s(i).faces'-1); + fprintf(fid,'%s}\n',o(3)); + + fprintf(fid,'%sMESH_FACE_SHADING_LIST {\n',o(3)); + fprintf(fid,'%d\n',zeros(size(s(i).faces,1),1)); + fprintf(fid,'%s}\n',o(3)); + + if c + fprintf(fid,'%sMESH_FACE_DIFFUSE_COLOR_LIST {\n',o(3)); + fprintf(fid,'%d %d %d\n',s(i).faces'-1); + fprintf(fid,'%s}\n',o(3)); + end + + fprintf(fid,'%sMODEL_POSITION_LIST {\n',o(3)); + fprintf(fid,'%f %f %f\n',s(i).vertices'); + fprintf(fid,'%s}\n',o(3)); + + fprintf(fid,'%sMODEL_NORMAL_LIST {\n',o(3)); + fprintf(fid,'%f %f %f\n',s(i).normals'); + fprintf(fid,'%s}\n',o(3)); + + if c + fprintf(fid,'%sMODEL_DIFFUSE_COLOR_LIST {\n',o(3)); + fprintf(fid,'%f %f %f\n',s(i).cdata'); + fprintf(fid,'%s}\n',o(3)); + end + + fprintf(fid,'%s}\n',o(2)); + fprintf(fid,'%s}\n',o(1)); + fprintf(fid,'}\n'); +end diff --git a/@gifti/subsasgn.m b/@gifti/subsasgn.m index 3376d10..25e9c94 100644 --- a/@gifti/subsasgn.m +++ b/@gifti/subsasgn.m @@ -4,16 +4,16 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Guillaume Flandin -% $Id: subsasgn.m 3556 2009-11-11 18:20:34Z guillaume $ +% $Id: subsasgn.m 3999 2010-07-19 10:54:18Z guillaume $ switch subs(1).type case '.' - if ~ismember(subs(1).subs, {'vertices' 'faces' 'normals' 'cdata','mat'}) + if ~ismember(subs(1).subs, {'vertices' 'faces' 'normals' 'cdata','mat','private'}) error('Reference to non-existent field ''%s''.',subs(1).subs); else % TODO % handle cases when length(subs) > 1 [i,n] = isintent(this,subs(1).subs); - if isempty(i) + if isempty(i) && ~strcmp(subs(1).subs,'private') n = length(this.data) + 1; % TODO % Initialise data field appropriately this.data{n}.metadata = struct([]); @@ -54,6 +54,8 @@ this.data{n}.space(1).MatrixData = A; end end + elseif strcmp(subs(1).subs,'private') + this = builtin('subsasgn',this,subs(2:end),A); else if strcmp(subs(1).subs,'faces') if length(subs) > 1 diff --git a/@gifti/subsref.m b/@gifti/subsref.m index 9bef0fa..7671693 100644 --- a/@gifti/subsref.m +++ b/@gifti/subsref.m @@ -4,7 +4,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Guillaume Flandin -% $Id: subsref.m 2076 2008-09-10 12:34:08Z guillaume $ +% $Id: subsref.m 3999 2010-07-19 10:54:18Z guillaume $ if length(this) > 1 warning('Not implemented.'); @@ -26,7 +26,16 @@ if strcmp(subs(1).subs,'mat') varargout{1} = this.data{j}.space.MatrixData; else - varargout{1} = this.data{j}.data; + if length(j) == 1 + varargout{1} = this.data{j}.data; + else + a = [this.data{j}]; + try + varargout{1} = [a.data]; + catch + error('Data arrays are of different sizes.'); + end + end end end if strcmp(subs(1).subs,'faces') diff --git a/@meeg/badchannels.m b/@meeg/badchannels.m index 9b169b9..f1b9388 100644 --- a/@meeg/badchannels.m +++ b/@meeg/badchannels.m @@ -1,13 +1,13 @@ function res = badchannels(this, varargin) -% Method for getting/setting bad channels +% Method for getting/setting bad channels % FORMAT res = badchannels(this) % _______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Stefan Kiebel -% $Id: badchannels.m 1673 2008-05-16 15:32:22Z vladimir $ +% $Id: badchannels.m 3942 2010-06-21 14:03:28Z vladimir $ + - if length(varargin) == 2 % make sure that the two inputs for set are the same length if ~(length(varargin{2}) == 1 | (length(varargin{1}) == length(varargin{2}))) @@ -15,18 +15,25 @@ end end -if length(varargin) >= 1 +if numel(varargin) >= 1 if ~(varargin{1} >= 1 & varargin{1} <= nchannels(this)) error('Channel number of out range.'); end end +if numel(varargin) >= 2 + ubad = unique(varargin{2}); + if isempty(ubad) | ~all(ismember(ubad, [0 1])) + error('Illegal bad flags (should be 0 or 1)'); + end +end + res = getset(this, 'channels', 'bad', varargin{:}); if isempty(varargin) if iscell(res) - res = [res{:}]; + res = [res{:}]; end res = find(res); diff --git a/@meeg/clone.m b/@meeg/clone.m index 94b4a7f..d138cbf 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 3350 2009-09-03 13:19:20Z vladimir $ +% $Id: clone.m 3807 2010-04-06 19:29:08Z vladimir $ if nargin < 4 reset = 0; @@ -33,8 +33,10 @@ pth = this.path; end newFileName = [fullfile(pth,fname),ext]; -% initialise new file_array -d = file_array(newFileName, dim, dtype(this)); +% copy the file_array +d = this.data.y; % +d.fname = newFileName; +d.dim = dim; % physically initialise file if length(dim) == 3 diff --git a/@meeg/indsample.m b/@meeg/indsample.m index 5c521fb..b0103b6 100644 --- a/@meeg/indsample.m +++ b/@meeg/indsample.m @@ -9,16 +9,24 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Stefan Kiebel -% $Id: indsample.m 2921 2009-03-23 17:59:50Z guillaume $ +% $Id: indsample.m 3742 2010-03-02 15:15:43Z vladimir $ res = NaN(1,length(t)); if this.Nsamples > 0 T = time(this); for i = 1:length(t) - [m,res(i)] = min(abs(T-t(i))); - if m > (1/this.Fsample) - warning('Could not find an index matching the requested time %d sec', t(i)); - res(i) = NaN; + if isfinite(t(i)) + [m,res(i)] = min(abs(T-t(i))); + if m > (1/this.Fsample) + warning('Could not find an index matching the requested time %d sec', t(i)); + res(i) = NaN; + end + elseif ~isnan(t(i)) % This allows to specify the time window as [-Inf Inf] + if t(i) < 0 + res(i) = 1; + else + res(i) = this.Nsamples; + end end end end diff --git a/@meeg/meeg.m b/@meeg/meeg.m index 28c6693..09ae2eb 100644 --- a/@meeg/meeg.m +++ b/@meeg/meeg.m @@ -22,7 +22,6 @@ % Subfields of .data % .y - reference to the data file_array % .fnamedat - name of the .dat file -% .scale - scaling coefficients for file_array % .datatype - type of the data for file_array % % @@ -102,7 +101,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Vladimir Litvak -% $Id: meeg.m 2209 2008-09-26 18:58:41Z karl $ +% $Id: meeg.m 3940 2010-06-21 12:51:19Z christophe $ if nargin == 1 if isstruct(varargin{1}) diff --git a/@meeg/private/checkmeeg.m b/@meeg/private/checkmeeg.m index c6132bc..46386d4 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 3679 2010-01-14 10:49:35Z vladimir $ +% $Id: checkmeeg.m 3978 2010-07-08 14:26:39Z vladimir $ if nargin==1 option = 'basic'; @@ -40,7 +40,7 @@ meegstruct.timeOnset = 0; % This is to enable creation of empty meeg objects end end - + if ~isfield(meegstruct, 'trials') && (Nsamples~=0) disp('checkmeeg: no trials description'); @@ -62,11 +62,11 @@ if ~isfield(meegstruct.trials, 'events') [meegstruct.trials.events] = deal([]); end - + for k = 1:Ntrials if isnumeric(meegstruct.trials(k).label) - meegstruct.trials(k).label = num2str(meegstruct.trials(k).label); - end + meegstruct.trials(k).label = num2str(meegstruct.trials(k).label); + 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.']); @@ -74,7 +74,7 @@ end event = meegstruct.trials(k).events; - + if ~isempty(event) && ~(numel(event) == 1 && isequal(event.type, 'no events')) % make sure that all required elements are present if ~isfield(event, 'type'), error('type field not defined for each event'); end @@ -106,9 +106,11 @@ meegstruct.trials(k).events = event; end - + if ~isfield(meegstruct.trials, 'onset') [meegstruct.trials.onset] = deal(0); + else + [meegstruct.trials(find(cellfun('isempty', {meegstruct.trials.onset}))).onset] = deal(0); end if ~isfield(meegstruct.trials, 'repl') [meegstruct.trials.repl] = deal(1); @@ -130,17 +132,19 @@ end if ~isfield(meegstruct.channels, 'bad') [meegstruct.channels.bad] = deal(0); + else + [meegstruct.channels(find(cellfun('isempty', {meegstruct.channels.bad}))).bad] = deal(0); end if ~isfield(meegstruct.channels, 'type') disp('checkmeeg: no channel type, assigning default'); [meegstruct.channels.type] = deal('Other'); end - + % This is for backward compatibility with early SPM8b. Can be removed % after a while. ind = strmatch('MEGREF', {meegstruct.channels.type}, 'exact'); [meegstruct.channels(ind).type] = deal('REF'); - + if ~isfield(meegstruct.channels, 'X_plot2D') [meegstruct.channels.X_plot2D] = deal([]); [meegstruct.channels.Y_plot2D] = deal([]); @@ -177,43 +181,36 @@ if ~isfield(meegstruct.data, 'fnamedat') disp('checkmeeg: data file name missing'); return; - else - [junk, fnamedat] = fileparts(meegstruct.data.fnamedat); - meegstruct.data.fnamedat = [fnamedat '.dat']; + else + [junk, fnamedat, ext] = fileparts(meegstruct.data.fnamedat); + if isempty(ext) + meegstruct.data.fnamedat = [fnamedat '.dat']; + else + meegstruct.data.fnamedat = [fnamedat ext]; + end end if ~isfield(meegstruct.data, 'datatype') disp('checkmeeg: data type missing, assigning default'); - meegstruct.data.datatype = 'float32-le'; + meegstruct.data.datatype = 'float32'; end - - if ~isfield(meegstruct.data, 'scale') - if strcmp(meegstruct.data.datatype, 'float32-le') || ... - strcmp(meegstruct.data.datatype, 'float64-le') - disp('checkmeeg: data scale missing, assigning default'); - meegstruct.data.scale = ones(Nchannels, 1, Ntrials); - else - % Jump out if datascale missing and not in float format - disp('checkmeeg: data scale missing'); - return - end - end - + if ~isfield(meegstruct.data, 'y') meegstruct.data.y=[]; end - + if isa(meegstruct.data.y, 'file_array') try % Try reading data, i.e. check if it's a "good" filearray meegstruct.data.y(1, 1, 1); catch - % save original scale, just in case + % save original file_array scale, just in case sav_sc = meegstruct.data.y.scl_slope; meegstruct.data.y = []; end end - - if ~isa(meegstruct.data.y, 'file_array') || isempty(fileparts(meegstruct.data.y.fname)) ... + + if ~isa(meegstruct.data.y, 'file_array') ... + || isempty(fileparts(meegstruct.data.y.fname)) ... || ~exist(meegstruct.data.y.fname, 'file') if isfield(meegstruct, 'path') filepath = meegstruct.path; @@ -221,14 +218,10 @@ filepath = pwd; end switch(meegstruct.transform.ID) - % note: scale no longer used, must insure data is in some float - % format - % still re-introduce the scaling if it is available, allowing - % the use of copied (raw) integer data files case 'time' meegstruct.data.y = file_array(fullfile(filepath, meegstruct.data.fnamedat), ... [Nchannels Nsamples Ntrials], meegstruct.data.datatype); - + case {'TF', 'TFphase'} meegstruct.data.y = file_array(fullfile(filepath, meegstruct.data.fnamedat), ... [Nchannels Nfrequencies Nsamples Ntrials], meegstruct.data.datatype); @@ -237,17 +230,17 @@ else expected_size = [Nchannels Nfrequencies Nsamples]; end - + otherwise error('Unknown transform type'); end - % and restore original scale, if available (exist) & useful (~=[]) + % and restore original file_array scale, if available (exist) & useful (~=[]) if exist('sav_sc','var') && ~isempty(sav_sc) meegstruct.data.y.scl_slope = sav_sc; end - + end - + switch(meegstruct.transform.ID) case 'time' if Ntrials>1 @@ -261,12 +254,12 @@ else expected_size = [Nchannels Nfrequencies Nsamples]; end - - + + otherwise error('Unknown transform type'); end - + if any(size(meegstruct.data.y) ~= expected_size) disp('checkmeeg: data size does not match the header'); return; @@ -275,8 +268,9 @@ if ~isfield(meegstruct, 'type') ||... (strcmp(meegstruct.type, 'continuous') && Ntrials>1) ||... - strcmp(meegstruct.type, 'evoked') && (numel(unique({meegstruct.trials.label})) ~= Ntrials) ||... - (strcmp(meegstruct.type, 'continuous') && strncmp(meegstruct.transform.ID, 'TF', 2)) + (strcmp(meegstruct.type, 'evoked') && (numel(unique({meegstruct.trials.label})) ~= Ntrials)) ||... + (strcmp(meegstruct.type, 'continuous') && strncmp(meegstruct.transform.ID, 'TF', 2)) ||... + strcmp(meegstruct.type, 'grandmean') disp('checkmeeg: data type is missing or incorrect, assigning default'); % rule of thumb - 10 sec if Nsamples == 0 @@ -291,11 +285,18 @@ end end +try + [pdat, fdat] = fileparts(meegstruct.data.y.fname); +catch + fdat = 'spm8'; +end + if ~isfield(meegstruct, 'fname') - try - [p, f] = fileparts(meegstruct.data.y.fname); - catch - f = 'spm8'; + meegstruct.fname = [fdat '.mat']; +else + [p, f] = fileparts(meegstruct.fname); + if isempty(f) + f = fdat; end meegstruct.fname = [f '.mat']; end @@ -406,14 +407,14 @@ lfpind = strmatch('LFP', chantypes, 'exact'); % Allow DCM on a pure LFP dataset -if strcmp(option, 'dcm') && isempty([eegind megind])... +if strcmp(option, 'dcm') && isempty([eegind(:); megind(:)])... && ~isempty(lfpind)&& strcmp(meegstruct.transform.ID, 'time') result = 1; return; end if strcmp(option, 'sensfid') || strcmp(option, '3d') ||... - (strcmp(option, 'dcm') && ~isempty([eegind megind])) + (strcmp(option, 'dcm') && ~isempty([eegind(:); megind(:)])) if ~strcmp(meegstruct.transform.ID, 'time') disp('checkmeeg: incorrect data type for source reconstruction'); @@ -424,7 +425,7 @@ disp('checkmeeg: no sensor positions are defined'); return; end - + if ~isempty(eegind) if ~isfield(meegstruct.sensors, 'eeg') || isempty(meegstruct.sensors.eeg) disp('checkmeeg: EEG channel locations are not specified'); @@ -436,7 +437,7 @@ end end end - + if ~isempty(megind) if ~isfield(meegstruct.sensors, 'meg') || isempty(meegstruct.sensors.meg) disp('checkmeeg: MEG channel locations are not specified'); @@ -448,12 +449,12 @@ end end end - + if isempty(meegstruct.fiducials) disp('checkmeeg: no fiducials are defined'); return; end - + if ~isfield(meegstruct.fiducials, 'pnt') || isempty(meegstruct.fiducials.pnt) if ~isempty(eegind) % Copy EEG sensors to fiducials. @@ -462,7 +463,7 @@ meegstruct.fiducials.pnt = sparse(0, 3); end end - + if ~isfield(meegstruct.fiducials, 'fid') || ... ~all(isfield(meegstruct.fiducials.fid, {'pnt', 'label'})) ||... (length(meegstruct.fiducials.fid.label) ~= size(meegstruct.fiducials.fid.pnt, 1)) || ... @@ -470,37 +471,37 @@ disp('checkmeeg: at least 3 fiducials with labels are required'); return end - + nzlbl = {'fidnz', 'nz', 'nas', 'nasion', 'spmnas'}; lelbl = {'fidle', 'fidt9', 'lpa', 'lear', 'earl', 'le', 'l', 't9', 'spmlpa'}; relbl = {'fidre', 'fidt10', 'rpa', 'rear', 'earr', 're', 'r', 't10', 'spmrpa'}; - + [sel1, nzind] = match_str(nzlbl, lower(meegstruct.fiducials.fid.label)); if isempty(nzind) disp('checkmeeg: could not find the nasion fiducial'); else nzind = nzind(1); end - + [sel1, leind] = match_str(lelbl, lower(meegstruct.fiducials.fid.label)); if isempty(leind) disp('checkmeeg: could not find the left fiducial'); else leind = leind(1); end - + [sel1, reind] = match_str(relbl, lower(meegstruct.fiducials.fid.label)); if isempty(reind) disp('checkmeeg: could not find the right fiducial'); else reind = reind(1); end - + restind = setdiff(1:length(meegstruct.fiducials.fid.label), [nzind(:)', leind(:)', reind(:)']); - + meegstruct.fiducials.fid.label = meegstruct.fiducials.fid.label([nzind(:)', leind(:)', reind(:)', restind(:)']); meegstruct.fiducials.fid.pnt = meegstruct.fiducials.fid.pnt([nzind(:)', leind(:)', reind(:)', restind(:)'], :); - + result = 1; end diff --git a/@meeg/selectchannels.m b/@meeg/selectchannels.m new file mode 100644 index 0000000..de3b61b --- /dev/null +++ b/@meeg/selectchannels.m @@ -0,0 +1,38 @@ +function chanind = selectchannels(this, channels) +% Method for getting channel indices based on labels and/or types +% FORMAT res = selectchannels(this, label) +% this - MEEG object +% channels - string or cell array of labels that may also include +% 'all', or types ('EEG', 'MEG' etc.) +% +% res - vector of channel indices matching labels +%__________________________________________________________________________ +% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging + +% Vladimir Litvak +% $Id: selectchannels.m 3798 2010-03-24 12:00:07Z vladimir $ + +if ischar(channels) + channels = {channels}; +end + +chanind = []; + +for i = 1:numel(channels) + switch upper(channels{i}) + case 'ALL' + chanind = [chanind 1:nchannels(this)]; + case 'EOG' + chanind = [chanind eogchannels(this)]; + case 'ECG' + chanind = [chanind ecgchannels(this)]; + case 'EMG' + chanind = [chanind emgchannels(this)]; + case {'EEG', 'MEG', 'MEGMAG', 'MEGGRAD', 'MEGPLANAR', 'REF', 'REFMAG', 'REFGRAD', 'LFP'} + chanind = [chanind meegchannels(this, upper(channels{i}))]; + otherwise + chanind = [chanind indchannel(this, channels{i})]; + end +end + +chanind = unique(chanind); \ No newline at end of file diff --git a/@meeg/size.m b/@meeg/size.m index 1d1ee8b..01b6ec3 100644 --- a/@meeg/size.m +++ b/@meeg/size.m @@ -5,10 +5,10 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Vladimir Litvak -% $Id: size.m 3350 2009-09-03 13:19:20Z vladimir $ +% $Id: size.m 3767 2010-03-09 22:49:30Z vladimir $ res = size(this.data.y, varargin{:}); -if ntrials(this) == 1 +if ntrials(this) == 1 && isempty(varargin) res = [res 1]; end diff --git a/@slover/add_spm.m b/@slover/add_spm.m index 63b5988..47ac289 100644 --- a/@slover/add_spm.m +++ b/@slover/add_spm.m @@ -8,7 +8,7 @@ [XYZ Z M] = pr_get_spm_results; if isempty(XYZ) - warning('No SPM results to add'); + warning('slover:noSPM', 'No SPM results to add'); return end diff --git a/@slover/display.m b/@slover/display.m index 0906bee..30b0a2a 100644 --- a/@slover/display.m +++ b/@slover/display.m @@ -4,7 +4,7 @@ function display(obj) % $Id: display.m,v 1.1 2005/04/20 15:05:36 matthewbrett Exp $ X = struct(obj); -src = ['[slice overlay object]']; +src = '[slice overlay object]'; if isequal(get(0,'FormatSpacing'),'compact') disp([inputname(1) ' =']); disp(src); diff --git a/@slover/fill_defaults.m b/@slover/fill_defaults.m index e28e1f6..74362a6 100644 --- a/@slover/fill_defaults.m +++ b/@slover/fill_defaults.m @@ -50,17 +50,17 @@ end % orientation; string or 4x4 matrix -orientn = []; if ischar(obj.transform) orientn = find(strcmpi(obj.transform, {'axial', ... 'coronal', ... 'sagittal', ... 'saggital'})); if isempty(orientn) - error(sprintf('Unexpected orientation %s', obj.transform)); + error('Unexpected orientation %s', obj.transform); end if orientn == 4 - warning('Goofy spelling of sagittal, but we''ll let you off'); + warning('fill_defaults:spelling', ... + 'Goofy spelling of sagittal, but we''ll let you off'); end ts = [0 0 0 0 0 0 1 1 1;... 0 0 0 pi/2 0 0 1 -1 1;... @@ -69,8 +69,8 @@ end % default slice size, slice matrix depends on orientation -if (isempty(obj.slicedef) | isempty(obj.slices)) ... - & ~isempty(obj.img) +if (isempty(obj.slicedef) || isempty(obj.slices)) ... + && ~isempty(obj.img) % take image sizes from first image V = obj.img(1).vol; D = V.dim(1:3); @@ -78,20 +78,20 @@ vcorners = [1 1 1; D(1) 1 1; 1 D(2) 1; D(1:2) 1; ... 1 1 D(3); D(1) 1 D(3); 1 D(2:3) ; D(1:3)]'; corners = T * [vcorners; ones(1,8)]; - SC = sort(corners'); + SC = sort(corners, 2); vxsz = sqrt(sum(T(1:3,1:3).^2)); if isempty(obj.slicedef) - obj.slicedef = [SC(1,1) vxsz(1) SC(8,1);SC(1,2) vxsz(2) SC(8,2)]; + obj.slicedef = [SC(1,1) vxsz(1) SC(1,8);SC(2,1) vxsz(2) SC(2,8)]; end if isempty(obj.slices) - obj.slices = [SC(1,3):vxsz(3):SC(8,3)]; + obj.slices = SC(3,1):vxsz(3):SC(3,8); end end % labels if ischar(obj.labels) - if ~strcmp(lower(obj.labels), 'none') + if ~strcmpi(obj.labels, 'none') error('If labels is string, should be ''none'''); end else @@ -113,80 +113,76 @@ % set colour intensities as we go remcol = 1; for i = 1:length(obj.img) - img = obj.img(i); - if ~mars_struct('isthere', img, 'type') + if ~mars_struct('isthere', obj.img(i), 'type') % default is true colour, unless prop is Inf - img.type = 'truecolour'; - if mars_struct('isthere', img, 'prop') - if img.prop == Inf - img.type = 'split'; - img.prop = 1; + obj.img(i).type = 'truecolour'; + if mars_struct('isthere', obj.img(i), 'prop') + if obj.img(i).prop == Inf + obj.img(i).type = 'split'; + obj.img(i).prop = 1; end end end - if ~mars_struct('isthere', img, 'hold') - if ~mars_struct('isthere', img.vol, 'imgdata') + if ~mars_struct('isthere', obj.img(i), 'hold') + if ~mars_struct('isthere', obj.img(i).vol, 'imgdata') % normal file vol struct - img.hold = 1; + obj.img(i).hold = 1; else % 3d matrix vol struct - img.hold = 0; + obj.img(i).hold = 0; end end - if ~mars_struct('isthere', img, 'background') - img.background = NaN; + if ~mars_struct('isthere', obj.img(i), 'background') + obj.img(i).background = NaN; end - if ~mars_struct('isthere', img, 'prop') + if ~mars_struct('isthere', obj.img(i), 'prop') % default is true colour - if strcmpi(img.type, 'truecolour') - img.prop = remcol/(length(obj.img)-i+1); - remcol = remcol - img.prop; + if strcmpi(obj.img(i).type, 'truecolour') + obj.img(i).prop = remcol/(length(obj.img)-i+1); + remcol = remcol - obj.img(i).prop; else - img.prop = 1; + obj.img(i).prop = 1; end end - if ~mars_struct('isthere', img, 'range') - [mx mn] = pr_volmaxmin(img.vol); - img.range = [mn mx]; + if ~mars_struct('isthere', obj.img(i), 'range') + [mx mn] = pr_volmaxmin(obj.img(i).vol); + obj.img(i).range = [mn mx]; end - if ~mars_struct('isthere', img, 'cmap') - if strcmpi(img.type, 'split') + if ~mars_struct('isthere', obj.img(i), 'cmap') + if strcmpi(obj.img(i).type, 'split') if obj.range(1)max(thisimg.range))=max(thisimg.range); + if ~any(diff(i1(isfinite(i1)))), continue, end % skip empty planes if mars_struct('isthere', thisimg, 'linespec') linespec = thisimg.linespec; else linespec = 'w-'; end - axes(axisd(i)); set(axisd(i),'NextPlot','add'); if mars_struct('isthere', thisimg, 'contours') - [c h] = contour(i1, thisimg.contours, linespec); + [c h] = contour(axisd(i), i1, thisimg.contours, linespec); else - [c h] = contour(i1, linespec); + [c h] = contour(axisd(i), i1, linespec); end if ~isempty(h) if ~mars_struct('isthere', thisimg, 'linespec') - % need to reset colours - % assumes contour value is in line UserData - % as seemed to be the case - convals = get(h, 'UserData'); - if ~iscell(convals),convals = {convals};end + % need to reset colours; contour assumes you just set the figure's + % colormap, but to overlay coloured contours on a greyscale image, + % one needs to have everything in truecolour, setting individual + % contour lines to their appropriate colour. + % (updated for MATLAB 7 and above) + convals = get(h, 'LevelList'); if ~isempty(convals) - [csdata badvals] = pr_scaletocmap(... - cat(1, convals{:}), ... + csdata = pr_scaletocmap(... + convals,... thisimg.range(1),... thisimg.range(2),... thisimg.cmap,... [1 size(thisimg.cmap,1) 1]); colvals = thisimg.cmap(csdata(:),:)*thisimg.prop; - set(h, {'Color'}, num2cell(colvals, 2)); + for ch = get(h, 'Children')' % (NB: transpose needed to loop) + CData = get(ch, 'CData'); % (CData is constant with final NaN) + colval = colvals(find(convals == CData(1), 1), :); + set(ch, 'EdgeColor', colval) + end end end if mars_struct('isthere', thisimg, 'linewidth') @@ -338,7 +342,7 @@ 'Box', 'off',... 'Position',[p(1)+pc(1)-cw/2,p(2)+pc(2)-ch/2,cw,ch]... ); - ih = image('Parent', a,... + image('Parent', a,... 'YData', axlims(idxs),... 'CData', reshape(cbari.cmap,[cml,1,3])); end % colourbars @@ -353,7 +357,7 @@ function i1 = sf_slice2panel(img, xyzmm, transform, vdims) % to voxel space of image -vixyz = inv(transform*img.vol.mat)*xyzmm; +vixyz = (transform*img.vol.mat) \ xyzmm; % raw data if mars_struct('isthere', img.vol, 'imgdata') V = img.vol.imgdata; diff --git a/@slover/print_fig.m b/@slover/print_fig.m index 825159a..858249e 100644 --- a/@slover/print_fig.m +++ b/@slover/print_fig.m @@ -38,9 +38,9 @@ function print_fig(obj, filename, printstr) %-Print %----------------------------------------------------------------------- -err = 0; -try, eval([printstr ' ' filename]), catch, err=1; end -if err +try + eval([printstr ' ' filename]) +catch errstr = lasterr; tmp = [find(abs(errstr)==10),length(errstr)+1]; str = {errstr(1:tmp(1)-1)}; @@ -49,9 +49,9 @@ function print_fig(obj, filename, printstr) str = [str, {errstr(tmp(i)+1:tmp(i+1)-1)}]; end end - str = {str{:}, '','- print command is:',[' ',printstr ' ' filename],... + str = [str, '','- print command is:',[' ',printstr ' ' filename],... '','- current directory is:',[' ',pwd],... - '',' * nothing has been printed *'}; + '',' * nothing has been printed *']; for i=1:length(str) disp(str{i});end end diff --git a/@slover/slover.m b/@slover/slover.m index 8a00075..ce5a194 100644 --- a/@slover/slover.m +++ b/@slover/slover.m @@ -216,7 +216,7 @@ % Could these just be image vol structs? if isfield(params, 'fname') - for i = 1:prod(size(params)) + for i = 1:numel(params) obj.img(i).vol = params(i); end params = obj; diff --git a/@xmltree/convert.m b/@xmltree/convert.m index 23bf72b..bd6a92f 100644 --- a/@xmltree/convert.m +++ b/@xmltree/convert.m @@ -16,7 +16,7 @@ % Copyright (C) 2002-2008 http://www.artefact.tk/ % Guillaume Flandin -% $Id: convert.m 1460 2008-04-21 17:43:18Z guillaume $ +% $Id: convert.m 3756 2010-03-05 18:43:37Z guillaume $ % Exemple: % tree: field1field2field3 @@ -133,7 +133,7 @@ for i = 1:length(varargin)-1 if (isa(varargin{i}, 'cell')) types{i} = '{}'; - elseif isstr(varargin{i}) + elseif ischar(varargin{i}) types{i} = '.'; subs{i} = varargin{i}; %strrep(varargin{i},' ',''); % deblank field name else diff --git a/@xmltree/find.m b/@xmltree/find.m index 04b8978..fc956ab 100644 --- a/@xmltree/find.m +++ b/@xmltree/find.m @@ -23,7 +23,7 @@ % Copyright (C) 2002-2008 http://www.artefact.tk/ % Guillaume Flandin -% $Id: find.m 1460 2008-04-21 17:43:18Z guillaume $ +% $Id: find.m 3934 2010-06-17 14:58:25Z guillaume $ % TODO: % - clean up subroutines @@ -105,7 +105,7 @@ %======================================================================= function list = sub_pathfinder(tree,pth) %- Search for the delimiter '/' in the path - i = findstr(pth,'/'); + i = strfind(pth,'/'); %- Begin search by root list = root(tree); %- Walk through the tree diff --git a/@xmltree/save.m b/@xmltree/save.m index 4e67d5e..71e9a7c 100644 --- a/@xmltree/save.m +++ b/@xmltree/save.m @@ -13,7 +13,7 @@ % Copyright (C) 2002-2008 http://www.artefact.tk/ % Guillaume Flandin -% $Id: save.m 1460 2008-04-21 17:43:18Z guillaume $ +% $Id: save.m 3756 2010-03-05 18:43:37Z guillaume $ error(nargchk(1,2,nargin)); @@ -26,7 +26,7 @@ %- Output specified else %- Filename provided - if isstr(filename) + if ischar(filename) [fid, msg] = fopen(filename,'w'); if fid==-1, error(msg); end if isempty(tree.filename), tree.filename = filename; end diff --git a/Contents.m b/Contents.m index fb8ea72..dde85d3 100644 --- a/Contents.m +++ b/Contents.m @@ -1,5 +1,5 @@ % Statistical Parametric Mapping -% Version 3684 (SPM8) 14-Jan-10 +% Version 4010 (SPM8) 21-Jul-10 %__________________________________________________________________________ % ___ ____ __ __ % / __)( _ \( \/ ) @@ -42,7 +42,7 @@ %__________________________________________________________________________ % Copyright (C) 1991,1994-2003,2005-2010 Wellcome Trust Centre for Neuroimaging -% $Id: Contents.m 3683 2010-01-14 15:40:20Z guillaume $ +% $Id: Contents.m 4008 2010-07-21 12:57:02Z guillaume $ %========================================================================== % PROGRAMMERS NOTE: diff --git a/EEGtemplates/biosemi128.sfp b/EEGtemplates/biosemi128.sfp index fbcc1fc..2c49547 100644 --- a/EEGtemplates/biosemi128.sfp +++ b/EEGtemplates/biosemi128.sfp @@ -1,131 +1,131 @@ -spmnas 1 85 -41 -spmlpa -83 -20 -65 -spmrpa 83 -20 -65 -A1 7.4426 -28.2776 102.9433 -A2 5.9663 -46.1946 99.138 -A3 6.1069 -61.6393 91.6259 -A4 4.616 -76.8153 80.0204 -A5 -26.6499 -84.7557 68.6028 -A6 -45.2234 -72.1023 72.8266 -A7 -55.3206 -78.0188 57.8527 -A8 -54.206 -92.3135 37.0932 -A9 -58.7243 -96.5535 18.8847 -A10 -59.4391 -99.6035 -3.057 -A11 -58.1189 -98.5577 -23.5039 -A12 -55.9478 -96.3632 -44.1064 -A13 -32.935 -113.6817 -44.841 -A14 -34.2849 -116.4856 -23.5582 -A15 -36.2093 -115.7834 -2.5125 -A16 -34.5444 -111.893 17.8906 -A17 -30.2937 -105.8642 35.0372 -A18 -34.0115 -95.0397 53.5568 -A19 2.4132 -89.1473 65.5643 -A20 0.2418 -102.2434 49.5309 -A21 -1.2917 -110.8703 31.3747 -A22 -1.8865 -115.7964 13.0992 -A23 -2.5421 -118.6861 -6.9534 -A24 -2.9843 -120.3623 -29.5152 -A25 -3.4083 -118.2461 -48.4193 -A26 25.4608 -114.1403 -51.3555 -A27 27.695 -115.6273 -32.8353 -A28 27.7909 -115.0047 -11.3983 -A29 27.0979 -112.2233 9.8157 -A30 28.891 -106.8681 27.8609 -A31 31.9036 -97.2395 46.5431 -A32 30.869 -86.3303 65.1532 -B1 24.7663 -35.0872 98.5511 -B2 32.76 -53.1995 91.1154 -B3 52.5055 -72.9942 65.0434 -B4 60.621 -80.4112 45.244 -B5 54.6391 -95.8332 29.3155 -B6 55.1373 -99.0623 6.7378 -B7 55.9026 -102.1645 -13.2275 -B8 54.007 -99.9428 -33.5392 -B9 51.262 -95.7837 -52.8957 -B10 70.1774 -76.1955 -35.8327 -B11 71.5265 -77.302 -14.2123 -B12 71.8898 -77.6988 5.1186 -B13 71.0088 -74.6335 26.1768 -B14 81.0669 -49.7158 -15.4222 -B15 80.6923 -52.3296 5.3311 -B16 80.0769 -50.9282 27.6421 -B17 74.956 -55.8919 45.2708 -B18 66.89 -52.9321 64.4562 -B19 51.8796 -53.9852 80.0609 -B20 42.0745 -30.0193 89.7813 -B21 58.7033 -28.4232 77.9235 -B22 70.9647 -28.3874 64.9512 -B23 79.9633 -28.2272 47.7598 -B24 83.8179 -26.9327 27.3413 -B25 85.4251 -25.8788 7.3872 -B26 84.3946 -23.7821 -13.158 -B27 82.2937 2.2418 -8.3678 -B28 84.0381 0.5065 11.5001 -B29 82.4838 -1.6282 31.0567 -B30 75.4422 -0.2205 51.0612 -B31 64.9991 -4.6397 66.4047 -B32 50.551 -5.0747 81.874 -C1 20.0164 -15.0087 100.9801 -C2 31.9838 -3.5163 92.3425 -C3 53.317 18.9302 72.6099 -C4 62.4956 26.9818 57.7773 -C5 75.2884 22.1757 36.803 -C6 77.4531 26.2379 17.7623 -C7 77.2055 28.5963 -2.7632 -C8 66.289 55.4377 6.436 -C9 65.6089 51.1455 27.0928 -C10 61.4005 44.2351 46.708 -C11 34.898 14.9372 87.3279 -C12 32.4325 34.2823 79.7901 -C13 38.8438 45.6294 67.37 -C14 37.166 58.5457 52.3843 -C15 38.2928 66.4153 34.9246 -C16 39.0041 73.3611 14.3713 -C17 3.4209 79.7912 16.9555 -C18 4.6444 72.0457 39.0973 -C19 5.8392 64.0022 56.2911 -C20 6.5798 52.861 72.2157 -C21 8.1288 39.4293 83.4137 -C22 6.8078 22.6384 92.2659 -C23 6.7513 7.2272 97.8383 -C24 -18.5288 15.9493 90.7607 -C25 -18.6423 34.1584 81.9718 -C26 -24.5531 47.9069 69.5502 -C27 -24.1275 58.9232 54.82 -C28 -28.5158 66.7101 38.8199 -C29 -30.8659 74.2231 18.9699 -C30 -61.033 56.6667 14.7309 -C31 -55.8355 52.5048 34.5867 -C32 -48.1838 45.2409 51.7693 -D1 -1.1458 -13.8674 102.8308 -D2 -16.214 -2.8675 96.4337 -D3 -38.9767 19.2185 79.4194 -D4 -48.1695 27.7929 65.8435 -D5 -64.0575 25.725 46.6083 -D6 -69.66 28.0966 28.451 -D7 -72.5805 31.3076 8.1638 -D8 -80.3473 5.1168 5.4974 -D9 -78.3454 2.9947 23.6748 -D10 -73.4104 3.3976 44.4614 -D11 -62.696 2.937 60.9163 -D12 -51.8508 -1.6881 74.2128 -D13 -36.8111 -2.0919 89.4193 -D14 -27.2048 -28.0954 96.3603 -D15 -9.6753 -31.9082 102.127 -D16 -19.6713 -52.056 96.0235 -D17 -37.9206 -52.4797 87.7234 -D18 -45.2333 -24.6087 86.0456 -D19 -57.9712 -25.2873 75.1095 -D20 -70.487 -25.2383 58.7162 -D21 -78.0065 -23.221 42.1479 -D22 -80.9289 -22.984 21.5033 -D23 -83.165 -23.2974 1.409 -D24 -79.7226 -49.8384 -1.9222 -D25 -77.5175 -49.0328 19.7357 -D26 -77.2115 -49.0539 39.9852 -D27 -68.5245 -53.0251 57.4991 -D28 -57.9042 -49.7601 75.072 -D29 -66.4246 -72.1055 38.5192 -D30 -69.3217 -74.2295 15.8219 -D31 -70.6943 -74.9638 -3.9144 -D32 -71.6414 -75.7952 -23.5687 +spmnas 1 85 -41 +spmlpa -83 -20 -65 +spmrpa 83 -20 -65 +A1 7.4426 -28.2776 102.9433 +A2 5.9663 -46.1946 99.138 +A3 6.1069 -61.6393 91.6259 +A4 4.616 -76.8153 80.0204 +A5 -26.6499 -84.7557 68.6028 +A6 -45.2234 -72.1023 72.8266 +A7 -55.3206 -78.0188 57.8527 +A8 -54.206 -92.3135 37.0932 +A9 -58.7243 -96.5535 18.8847 +A10 -59.4391 -99.6035 -3.057 +A11 -58.1189 -98.5577 -23.5039 +A12 -55.9478 -96.3632 -44.1064 +A13 -32.935 -113.6817 -44.841 +A14 -34.2849 -116.4856 -23.5582 +A15 -36.2093 -115.7834 -2.5125 +A16 -34.5444 -111.893 17.8906 +A17 -30.2937 -105.8642 35.0372 +A18 -34.0115 -95.0397 53.5568 +A19 2.4132 -89.1473 65.5643 +A20 0.2418 -102.2434 49.5309 +A21 -1.2917 -110.8703 31.3747 +A22 -1.8865 -115.7964 13.0992 +A23 -2.5421 -118.6861 -6.9534 +A24 -2.9843 -120.3623 -29.5152 +A25 -3.4083 -118.2461 -48.4193 +A26 25.4608 -114.1403 -51.3555 +A27 27.695 -115.6273 -32.8353 +A28 27.7909 -115.0047 -11.3983 +A29 27.0979 -112.2233 9.8157 +A30 28.891 -106.8681 27.8609 +A31 31.9036 -97.2395 46.5431 +A32 30.869 -86.3303 65.1532 +B1 24.7663 -35.0872 98.5511 +B2 32.76 -53.1995 91.1154 +B3 52.5055 -72.9942 65.0434 +B4 60.621 -80.4112 45.244 +B5 54.6391 -95.8332 29.3155 +B6 55.1373 -99.0623 6.7378 +B7 55.9026 -102.1645 -13.2275 +B8 54.007 -99.9428 -33.5392 +B9 51.262 -95.7837 -52.8957 +B10 70.1774 -76.1955 -35.8327 +B11 71.5265 -77.302 -14.2123 +B12 71.8898 -77.6988 5.1186 +B13 71.0088 -74.6335 26.1768 +B14 81.0669 -49.7158 -15.4222 +B15 80.6923 -52.3296 5.3311 +B16 80.0769 -50.9282 27.6421 +B17 74.956 -55.8919 45.2708 +B18 66.89 -52.9321 64.4562 +B19 51.8796 -53.9852 80.0609 +B20 42.0745 -30.0193 89.7813 +B21 58.7033 -28.4232 77.9235 +B22 70.9647 -28.3874 64.9512 +B23 79.9633 -28.2272 47.7598 +B24 83.8179 -26.9327 27.3413 +B25 85.4251 -25.8788 7.3872 +B26 84.3946 -23.7821 -13.158 +B27 82.2937 2.2418 -8.3678 +B28 84.0381 0.5065 11.5001 +B29 82.4838 -1.6282 31.0567 +B30 75.4422 -0.2205 51.0612 +B31 64.9991 -4.6397 66.4047 +B32 50.551 -5.0747 81.874 +C1 20.0164 -15.0087 100.9801 +C2 31.9838 -3.5163 92.3425 +C3 53.317 18.9302 72.6099 +C4 62.4956 26.9818 57.7773 +C5 75.2884 22.1757 36.803 +C6 77.4531 26.2379 17.7623 +C7 77.2055 28.5963 -2.7632 +C8 66.289 55.4377 6.436 +C9 65.6089 51.1455 27.0928 +C10 61.4005 44.2351 46.708 +C11 34.898 14.9372 87.3279 +C12 32.4325 34.2823 79.7901 +C13 38.8438 45.6294 67.37 +C14 37.166 58.5457 52.3843 +C15 38.2928 66.4153 34.9246 +C16 39.0041 73.3611 14.3713 +C17 3.4209 79.7912 16.9555 +C18 4.6444 72.0457 39.0973 +C19 5.8392 64.0022 56.2911 +C20 6.5798 52.861 72.2157 +C21 8.1288 39.4293 83.4137 +C22 6.8078 22.6384 92.2659 +C23 6.7513 7.2272 97.8383 +C24 -18.5288 15.9493 90.7607 +C25 -18.6423 34.1584 81.9718 +C26 -24.5531 47.9069 69.5502 +C27 -24.1275 58.9232 54.82 +C28 -28.5158 66.7101 38.8199 +C29 -30.8659 74.2231 18.9699 +C30 -61.033 56.6667 14.7309 +C31 -55.8355 52.5048 34.5867 +C32 -48.1838 45.2409 51.7693 +D1 -1.1458 -13.8674 102.8308 +D2 -16.214 -2.8675 96.4337 +D3 -38.9767 19.2185 79.4194 +D4 -48.1695 27.7929 65.8435 +D5 -64.0575 25.725 46.6083 +D6 -69.66 28.0966 28.451 +D7 -72.5805 31.3076 8.1638 +D8 -80.3473 5.1168 5.4974 +D9 -78.3454 2.9947 23.6748 +D10 -73.4104 3.3976 44.4614 +D11 -62.696 2.937 60.9163 +D12 -51.8508 -1.6881 74.2128 +D13 -36.8111 -2.0919 89.4193 +D14 -27.2048 -28.0954 96.3603 +D15 -9.6753 -31.9082 102.127 +D16 -19.6713 -52.056 96.0235 +D17 -37.9206 -52.4797 87.7234 +D18 -45.2333 -24.6087 86.0456 +D19 -57.9712 -25.2873 75.1095 +D20 -70.487 -25.2383 58.7162 +D21 -78.0065 -23.221 42.1479 +D22 -80.9289 -22.984 21.5033 +D23 -83.165 -23.2974 1.409 +D24 -79.7226 -49.8384 -1.9222 +D25 -77.5175 -49.0328 19.7357 +D26 -77.2115 -49.0539 39.9852 +D27 -68.5245 -53.0251 57.4991 +D28 -57.9042 -49.7601 75.072 +D29 -66.4246 -72.1055 38.5192 +D30 -69.3217 -74.2295 15.8219 +D31 -70.6943 -74.9638 -3.9144 +D32 -71.6414 -75.7952 -23.5687 diff --git a/EEGtemplates/biosemi64.sfp b/EEGtemplates/biosemi64.sfp index d472626..c24a7dd 100644 --- a/EEGtemplates/biosemi64.sfp +++ b/EEGtemplates/biosemi64.sfp @@ -1,67 +1,67 @@ -spmnas 1 85 -41 -spmlpa -83 -20 -65 -spmrpa 83 -20 -65 -A1 -29.2644 82.1011 -0.1681 -A2 -54.9914 67.5738 -5.8804 -A3 -32.8795 71.8452 30.1284 -A4 -25.7835 47.4288 69.8291 -A5 -49.1339 46.0206 49.8831 -A6 -64.1055 44.0763 21.4442 -A7 -70.6916 41.8958 -10.8395 -A8 -81.4433 13.7802 -15.1615 -A9 -76.9277 14.1172 25.097 -A10 -58.9898 14.3544 59.7085 -A11 -32.0939 14.4686 86.4236 -A12 -34.1983 -22.4568 90.9388 -A13 -64.2027 -20.782 63.5856 -A14 -80.1105 -18.6349 24.6594 -A15 -85.0072 -16.3778 -18.4196 -A16 -85.8268 -46.4935 -21.2067 -A17 -79.5982 -51.4848 20.7615 -A18 -62.6018 -56.1594 58.5984 -A19 -33.7659 -59.7753 85.984 -A20 -27.4707 -91.1008 62.1009 -A21 -52.4644 -86.8018 41.7174 -A22 -67.4857 -80.9442 12.0896 -A23 -73.4404 -74.4816 -21.5311 -A24 -75.0014 -70.3299 -64.4026 -A25 -55.7888 -99.2792 -20.6777 -A26 -36.5153 -106.8019 16.2198 -A27 -30.1827 -115.1564 -17.6531 -A28 -1.4725 -117.9297 -55.4479 -A29 -0.3825 -118.6416 -12.82 -A30 0.7288 -110.1495 29.4389 -A31 1.798 -92.892 68.8025 -A32 2.5193 -61.2034 93.5467 -B1 0.5966 85.4186 5.2724 -B2 30.3458 82.3208 -2.5084 -B3 56.1483 67.2462 -10.3733 -B4 36.9056 71.7503 28.2715 -B5 1.6107 73.6809 45.2343 -B6 2.3304 47.9355 75.787 -B7 31.496 47.454 66.7353 -B8 53.4301 46.0515 44.4067 -B9 68.9352 44.219 15.7579 -B10 73.3302 42.0529 -16.9723 -B11 81.9645 12.9962 -21.7677 -B12 80.6141 13.3845 18.9204 -B13 64.1073 13.7668 54.9967 -B14 37.0696 14.142 82.3849 -B15 2.747 14.3924 94.9242 -B16 2.8165 -23.3292 101.2672 -B17 39.9696 -22.8958 86.5061 -B18 68.9216 -21.6725 57.4563 -B19 84.453 -19.7733 18.2209 -B20 85.084 -17.5501 -25.2931 -B21 85.4063 -48.208 -28.142 -B22 84.1409 -53.1682 14.4935 -B23 68.2191 -57.4632 53.3152 -B24 40.4866 -60.4388 82.3243 -B25 33.4052 -91.992 61.0662 -B26 56.7709 -88.0486 38.0235 -B27 68.346 -82.269 6.331 -B28 72.7791 -75.9692 -27.446 -B29 72.628 -72.8203 -70.7433 -B30 55.269 -100.7939 -25.2641 -B31 37.125 -107.6542 12.3793 -B32 29.3709 -115.6245 -20.0571 +spmnas 1 85 -41 +spmlpa -83 -20 -65 +spmrpa 83 -20 -65 +A1 -29.2644 82.1011 -0.1681 +A2 -54.9914 67.5738 -5.8804 +A3 -32.8795 71.8452 30.1284 +A4 -25.7835 47.4288 69.8291 +A5 -49.1339 46.0206 49.8831 +A6 -64.1055 44.0763 21.4442 +A7 -70.6916 41.8958 -10.8395 +A8 -81.4433 13.7802 -15.1615 +A9 -76.9277 14.1172 25.097 +A10 -58.9898 14.3544 59.7085 +A11 -32.0939 14.4686 86.4236 +A12 -34.1983 -22.4568 90.9388 +A13 -64.2027 -20.782 63.5856 +A14 -80.1105 -18.6349 24.6594 +A15 -85.0072 -16.3778 -18.4196 +A16 -85.8268 -46.4935 -21.2067 +A17 -79.5982 -51.4848 20.7615 +A18 -62.6018 -56.1594 58.5984 +A19 -33.7659 -59.7753 85.984 +A20 -27.4707 -91.1008 62.1009 +A21 -52.4644 -86.8018 41.7174 +A22 -67.4857 -80.9442 12.0896 +A23 -73.4404 -74.4816 -21.5311 +A24 -75.0014 -70.3299 -64.4026 +A25 -55.7888 -99.2792 -20.6777 +A26 -36.5153 -106.8019 16.2198 +A27 -30.1827 -115.1564 -17.6531 +A28 -1.4725 -117.9297 -55.4479 +A29 -0.3825 -118.6416 -12.82 +A30 0.7288 -110.1495 29.4389 +A31 1.798 -92.892 68.8025 +A32 2.5193 -61.2034 93.5467 +B1 0.5966 85.4186 5.2724 +B2 30.3458 82.3208 -2.5084 +B3 56.1483 67.2462 -10.3733 +B4 36.9056 71.7503 28.2715 +B5 1.6107 73.6809 45.2343 +B6 2.3304 47.9355 75.787 +B7 31.496 47.454 66.7353 +B8 53.4301 46.0515 44.4067 +B9 68.9352 44.219 15.7579 +B10 73.3302 42.0529 -16.9723 +B11 81.9645 12.9962 -21.7677 +B12 80.6141 13.3845 18.9204 +B13 64.1073 13.7668 54.9967 +B14 37.0696 14.142 82.3849 +B15 2.747 14.3924 94.9242 +B16 2.8165 -23.3292 101.2672 +B17 39.9696 -22.8958 86.5061 +B18 68.9216 -21.6725 57.4563 +B19 84.453 -19.7733 18.2209 +B20 85.084 -17.5501 -25.2931 +B21 85.4063 -48.208 -28.142 +B22 84.1409 -53.1682 14.4935 +B23 68.2191 -57.4632 53.3152 +B24 40.4866 -60.4388 82.3243 +B25 33.4052 -91.992 61.0662 +B26 56.7709 -88.0486 38.0235 +B27 68.346 -82.269 6.331 +B28 72.7791 -75.9692 -27.446 +B29 72.628 -72.8203 -70.7433 +B30 55.269 -100.7939 -25.2641 +B31 37.125 -107.6542 12.3793 +B32 29.3709 -115.6245 -20.0571 diff --git a/EEGtemplates/egi128_GSN.sfp b/EEGtemplates/egi128_GSN.sfp index aa4f8cb..f497401 100644 --- a/EEGtemplates/egi128_GSN.sfp +++ b/EEGtemplates/egi128_GSN.sfp @@ -1,131 +1,131 @@ -spmnas 1 85 -41 -spmlpa -83 -20 -65 -spmrpa 83 -20 -65 -e1 61.9607 52.6874 -15.7766 -e2 58.8985 59.9742 10.7082 -e3 46.5986 64.7811 38.532 -e4 28.9544 56.1581 65.1144 -e5 17.313 35.9969 81.5986 -e6 -0.6138 8.5199 91.2079 -e7 -15.925 -15.1289 92.2102 -e8 45.7826 76.9476 -9.455 -e9 37.2067 79.8158 17.6034 -e10 26.1752 74.8727 47.0885 -e11 -0.3328 61.6465 71.2435 -e12 -18.2641 35.9034 80.849 -e13 -29.5364 6.3675 85.0985 -e14 22.7219 90.1477 -3.4829 -e15 13.7605 88.2108 23.2711 -e16 0.122 81.11 47.2291 -e17 1.5117 90.6935 -19.9296 -e18 -12.5325 88.1418 22.7171 -e19 -25.8691 74.736 45.9921 -e20 -29.3067 56.0051 63.887 -e21 -40.8389 29.5022 71.3694 -e22 -20.3693 90.0345 -4.3907 -e23 -35.6748 79.6244 16.068 -e24 -45.8607 64.5382 36.5842 -e25 -51.2208 45.0553 51.3321 -e26 -43.0884 76.7141 -11.3272 -e27 -56.9525 59.6699 8.2676 -e28 -63.3105 40.9944 26.3714 -e29 -65.8003 19.6754 46.0534 -e30 -56.3512 0.7169 67.8611 -e31 -42.7617 -22.6457 81.5108 -e32 -25.2615 -47.1355 88.0646 -e33 -58.8582 52.37 -18.3219 -e34 -67.05 35.4952 -0.2055 -e35 -74.5702 12.2174 22.5845 -e36 -75.202 -5.3745 41.4384 -e37 -67.295 -28.6408 61.9169 -e38 -51.696 -52.7555 74.4367 -e39 -69.3366 25.7621 -34.2186 -e40 -76.5866 3.5105 -9.2297 -e41 -81.2507 -12.7042 12.6409 -e42 -81.09 -30.695 29.5123 -e43 -70.3363 -58.746 51.9313 -e44 -68.6953 12.624 -66.4603 -e45 -74.2516 -6.3438 -37.8431 -e46 -80.4885 -22.5219 -13.9549 -e47 -81.3097 -42.9608 7.4416 -e48 -78.4873 -59.0226 23.2413 -e49 -71.6265 -10.7411 -72.8854 -e50 -77.9463 -55.9437 -20.0482 -e51 -75.3437 -69.6328 -0.0429 -e52 -69.6632 -82.5474 26.744 -e53 -54.7698 -83.5326 53.7373 -e54 -27.3564 -78.5886 76.866 -e55 -0.3005 -68.4022 85.9262 -e56 -63.8883 -58.3602 -80.5522 -e57 -72.5632 -66.2491 -44.4042 -e58 -68.308 -80.8969 -24.3623 -e59 -63.4539 -95.1238 0.289 -e60 -51.343 -103.9452 29.9809 -e61 -29.4853 -101.7246 54.2142 -e62 0.082 -93.501 70.9003 -e63 -55.4604 -74.0745 -78.1898 -e64 -61.1611 -89.2929 -45.0392 -e65 -51.2197 -105.9992 -25.618 -e66 -41.1763 -117.9638 1.1365 -e67 -26.3539 -118.1127 29.3307 -e68 0.4952 -109.5628 53.2904 -e69 -40.5947 -95.1407 -76.3115 -e70 -37.6384 -112.8398 -45.8633 -e71 -28.7622 -123.9143 -24.2221 -e72 -20.0146 -127.7929 1.1799 -e73 1.2012 -124.4095 21.6281 -e74 -20.3542 -111.076 -78.4567 -e75 -20.0042 -120.605 -52.9312 -e76 2.0949 -129.9883 -20.0985 -e77 23.2769 -127.6792 2.0919 -e78 28.3741 -117.9689 30.4837 -e79 30.3686 -101.5674 55.4752 -e80 27.1661 -78.4453 78.0146 -e81 24.4363 -47.005 89.1116 -e82 3.2223 -116.7764 -75.2575 -e83 25.5076 -120.4855 -51.9724 -e84 33.066 -123.7519 -22.9195 -e85 44.3697 -117.7391 2.9387 -e86 53.2389 -103.6705 32.1841 -e87 55.5549 -83.2429 56.0615 -e88 51.4505 -52.4846 76.6097 -e89 26.8823 -110.952 -77.4616 -e90 42.7875 -112.6285 -44.1689 -e91 55.468 -105.719 -23.3704 -e92 66.543 -94.7823 3.0277 -e93 71.5665 -82.1764 29.7193 -e94 71.0532 -58.3747 54.9099 -e95 46.9306 -94.9108 -74.4676 -e96 66.1306 -88.9586 -42.3575 -e97 72.3562 -80.5274 -21.3989 -e98 78.3022 -69.2292 3.1939 -e99 80.4066 -58.6052 26.5888 -e100 61.7513 -73.7666 -75.7205 -e101 77.3748 -65.8553 -41.2454 -e102 81.6731 -55.5244 -16.6855 -e103 83.8075 -42.5271 10.9202 -e104 82.5941 -30.2651 32.9607 -e105 67.436 -28.2869 64.7553 -e106 42.0682 -22.4229 83.2979 -e107 14.7655 -15.0483 92.8568 -e108 70.1886 -58.0081 -77.7276 -e109 83.7808 -22.0904 -10.4942 -e110 83.3707 -12.2718 16.109 -e111 76.0761 -4.9772 44.6254 -e112 56.0975 1.0123 70.2301 -e113 28.5513 6.5201 86.3222 -e114 77.3469 -10.3498 -69.747 -e115 78.4706 -5.9426 -34.6257 -e116 79.5468 3.9206 -5.9404 -e117 76.1466 12.6133 25.7597 -e118 66.357 20.0225 48.8376 -e119 40.3003 29.7153 73.0788 -e120 74.025 12.9989 -63.4536 -e121 73.2388 26.1366 -31.215 -e122 69.4707 35.8538 2.6706 -e123 64.5865 41.3304 29.0658 -e124 51.4351 45.3249 53.4947 -e125 67.5932 39.7247 -56.052 -e126 39.1839 59.5757 -80.5023 -e127 -33.4122 59.385 -82.0317 -e128 -62.7214 39.3824 -58.7973 +spmnas 1 85 -41 +spmlpa -83 -20 -65 +spmrpa 83 -20 -65 +e1 61.9607 52.6874 -15.7766 +e2 58.8985 59.9742 10.7082 +e3 46.5986 64.7811 38.532 +e4 28.9544 56.1581 65.1144 +e5 17.313 35.9969 81.5986 +e6 -0.6138 8.5199 91.2079 +e7 -15.925 -15.1289 92.2102 +e8 45.7826 76.9476 -9.455 +e9 37.2067 79.8158 17.6034 +e10 26.1752 74.8727 47.0885 +e11 -0.3328 61.6465 71.2435 +e12 -18.2641 35.9034 80.849 +e13 -29.5364 6.3675 85.0985 +e14 22.7219 90.1477 -3.4829 +e15 13.7605 88.2108 23.2711 +e16 0.122 81.11 47.2291 +e17 1.5117 90.6935 -19.9296 +e18 -12.5325 88.1418 22.7171 +e19 -25.8691 74.736 45.9921 +e20 -29.3067 56.0051 63.887 +e21 -40.8389 29.5022 71.3694 +e22 -20.3693 90.0345 -4.3907 +e23 -35.6748 79.6244 16.068 +e24 -45.8607 64.5382 36.5842 +e25 -51.2208 45.0553 51.3321 +e26 -43.0884 76.7141 -11.3272 +e27 -56.9525 59.6699 8.2676 +e28 -63.3105 40.9944 26.3714 +e29 -65.8003 19.6754 46.0534 +e30 -56.3512 0.7169 67.8611 +e31 -42.7617 -22.6457 81.5108 +e32 -25.2615 -47.1355 88.0646 +e33 -58.8582 52.37 -18.3219 +e34 -67.05 35.4952 -0.2055 +e35 -74.5702 12.2174 22.5845 +e36 -75.202 -5.3745 41.4384 +e37 -67.295 -28.6408 61.9169 +e38 -51.696 -52.7555 74.4367 +e39 -69.3366 25.7621 -34.2186 +e40 -76.5866 3.5105 -9.2297 +e41 -81.2507 -12.7042 12.6409 +e42 -81.09 -30.695 29.5123 +e43 -70.3363 -58.746 51.9313 +e44 -68.6953 12.624 -66.4603 +e45 -74.2516 -6.3438 -37.8431 +e46 -80.4885 -22.5219 -13.9549 +e47 -81.3097 -42.9608 7.4416 +e48 -78.4873 -59.0226 23.2413 +e49 -71.6265 -10.7411 -72.8854 +e50 -77.9463 -55.9437 -20.0482 +e51 -75.3437 -69.6328 -0.0429 +e52 -69.6632 -82.5474 26.744 +e53 -54.7698 -83.5326 53.7373 +e54 -27.3564 -78.5886 76.866 +e55 -0.3005 -68.4022 85.9262 +e56 -63.8883 -58.3602 -80.5522 +e57 -72.5632 -66.2491 -44.4042 +e58 -68.308 -80.8969 -24.3623 +e59 -63.4539 -95.1238 0.289 +e60 -51.343 -103.9452 29.9809 +e61 -29.4853 -101.7246 54.2142 +e62 0.082 -93.501 70.9003 +e63 -55.4604 -74.0745 -78.1898 +e64 -61.1611 -89.2929 -45.0392 +e65 -51.2197 -105.9992 -25.618 +e66 -41.1763 -117.9638 1.1365 +e67 -26.3539 -118.1127 29.3307 +e68 0.4952 -109.5628 53.2904 +e69 -40.5947 -95.1407 -76.3115 +e70 -37.6384 -112.8398 -45.8633 +e71 -28.7622 -123.9143 -24.2221 +e72 -20.0146 -127.7929 1.1799 +e73 1.2012 -124.4095 21.6281 +e74 -20.3542 -111.076 -78.4567 +e75 -20.0042 -120.605 -52.9312 +e76 2.0949 -129.9883 -20.0985 +e77 23.2769 -127.6792 2.0919 +e78 28.3741 -117.9689 30.4837 +e79 30.3686 -101.5674 55.4752 +e80 27.1661 -78.4453 78.0146 +e81 24.4363 -47.005 89.1116 +e82 3.2223 -116.7764 -75.2575 +e83 25.5076 -120.4855 -51.9724 +e84 33.066 -123.7519 -22.9195 +e85 44.3697 -117.7391 2.9387 +e86 53.2389 -103.6705 32.1841 +e87 55.5549 -83.2429 56.0615 +e88 51.4505 -52.4846 76.6097 +e89 26.8823 -110.952 -77.4616 +e90 42.7875 -112.6285 -44.1689 +e91 55.468 -105.719 -23.3704 +e92 66.543 -94.7823 3.0277 +e93 71.5665 -82.1764 29.7193 +e94 71.0532 -58.3747 54.9099 +e95 46.9306 -94.9108 -74.4676 +e96 66.1306 -88.9586 -42.3575 +e97 72.3562 -80.5274 -21.3989 +e98 78.3022 -69.2292 3.1939 +e99 80.4066 -58.6052 26.5888 +e100 61.7513 -73.7666 -75.7205 +e101 77.3748 -65.8553 -41.2454 +e102 81.6731 -55.5244 -16.6855 +e103 83.8075 -42.5271 10.9202 +e104 82.5941 -30.2651 32.9607 +e105 67.436 -28.2869 64.7553 +e106 42.0682 -22.4229 83.2979 +e107 14.7655 -15.0483 92.8568 +e108 70.1886 -58.0081 -77.7276 +e109 83.7808 -22.0904 -10.4942 +e110 83.3707 -12.2718 16.109 +e111 76.0761 -4.9772 44.6254 +e112 56.0975 1.0123 70.2301 +e113 28.5513 6.5201 86.3222 +e114 77.3469 -10.3498 -69.747 +e115 78.4706 -5.9426 -34.6257 +e116 79.5468 3.9206 -5.9404 +e117 76.1466 12.6133 25.7597 +e118 66.357 20.0225 48.8376 +e119 40.3003 29.7153 73.0788 +e120 74.025 12.9989 -63.4536 +e121 73.2388 26.1366 -31.215 +e122 69.4707 35.8538 2.6706 +e123 64.5865 41.3304 29.0658 +e124 51.4351 45.3249 53.4947 +e125 67.5932 39.7247 -56.052 +e126 39.1839 59.5757 -80.5023 +e127 -33.4122 59.385 -82.0317 +e128 -62.7214 39.3824 -58.7973 diff --git a/EEGtemplates/egi128_GSN_HydroCel.sfp b/EEGtemplates/egi128_GSN_HydroCel.sfp index 3c1e2e5..21e0e87 100644 --- a/EEGtemplates/egi128_GSN_HydroCel.sfp +++ b/EEGtemplates/egi128_GSN_HydroCel.sfp @@ -1,131 +1,131 @@ -spmnas 1 85 -41 -spmlpa -83 -20 -65 -spmrpa 83 -20 -65 -e1 66.4574 46.7101 -28.4211 -e2 60.2831 57.3885 5.9018 -e3 43.4522 64.8292 38.4999 -e4 32.1273 56.9859 60.0942 -e5 16.6042 37.9375 79.597 -e6 0.2021 14.7435 90.1184 -e7 -13.1141 -12.0759 94.203 -e8 47.4865 73.4515 -12.0078 -e9 29.5322 80.7153 16.899 -e10 19.6021 76.3404 40.8383 -e11 -1.2714 65.2974 61.4116 -e12 -17.5365 36.8773 79.4824 -e13 -27.7043 7.7932 86.2367 -e14 12.8924 89.0168 -5.9943 -e15 -1.6455 81.8408 19.8104 -e16 -1.6565 79.991 40.1854 -e17 -1.6819 87.4013 -20.7901 -e18 -22.6515 75.0282 40.6964 -e19 -34.0805 54.9298 59.8719 -e20 -44.4017 30.3866 68.8337 -e21 -16.4273 88.1063 -6.0928 -e22 -32.6731 78.7835 16.6902 -e23 -45.7252 62.0598 38.2005 -e24 -52.0237 42.0368 51.5361 -e25 -49.9478 70.4256 -12.3349 -e26 -61.8428 53.5959 5.4918 -e27 -65.9204 36.5573 33.3505 -e28 -63.9008 19.9674 52.7002 -e29 -54.3366 1.8365 70.5231 -e30 -41.4128 -19.0523 84.1775 -e31 -20.7464 -38.2522 93.4255 -e32 -67.1123 42.562 -28.8696 -e33 -73.684 24.1588 -4.7025 -e34 -78.1925 7.9712 26.2147 -e35 -72.9541 -11.1296 51.3868 -e36 -61.7406 -26.2474 69.1354 -e37 -42.9946 -47.7709 83.3271 -e38 -75.2228 21.0895 -39.6783 -e39 -81.6438 -13.2946 -13.9706 -e40 -83.6858 -25.7153 20.0434 -e41 -77.7882 -37.5095 47.5104 -e42 -66.2952 -56.2193 62.1983 -e43 -74.4102 9.218 -62.7005 -e44 -77.7266 -5.6435 -44.2837 -e45 -81.9711 -44.8147 -13.6962 -e46 -81.9318 -52.721 20.5609 -e47 -75.0525 -62.4601 40.5172 -e48 -67.5755 9.8468 -93.7012 -e49 -71.1338 -12.9134 -74.0182 -e50 -75.172 -69.8184 -11.2061 -e51 -72.3752 -80.0383 22.4833 -e52 -64.0693 -79.943 48.0486 -e53 -45.3534 -76.0646 71.8817 -e54 -23.4008 -69.4099 86.6143 -e55 2.3368 -54.4902 94.6995 -e56 -68.6804 -46.3439 -71.8407 -e57 -72.9197 -63.7973 -42.6598 -e58 -65.922 -89.7446 -9.5935 -e59 -56.1205 -100.1422 23.5115 -e60 -43.7265 -97.7425 51.3134 -e61 -23.5024 -92.0786 71.4105 -e62 3.1447 -79.4477 84.9223 -e63 -58.3036 -67.2692 -73.326 -e64 -58.5787 -87.9721 -43.5414 -e65 -49.3402 -106.8549 -10.1211 -e66 -37.2605 -113.8274 24.0537 -e67 -17.0392 -111.6557 48.514 -e68 -39.6844 -91.1902 -71.2399 -e69 -36.3162 -107.2946 -44.3062 -e70 -26.8638 -121.5408 -10.0809 -e71 -11.559 -122.0578 25.0838 -e72 4.4223 -115.9401 41.9529 -e73 -17.8815 -103.2493 -70.8156 -e74 -8.2808 -116.4123 -42.911 -e75 4.8781 -125.2707 -7.493 -e76 20.8652 -121.0508 25.1926 -e77 25.5321 -110.3337 48.6569 -e78 30.6143 -90.398 71.5922 -e79 29.0043 -67.7825 86.7903 -e80 24.376 -36.8509 93.577 -e81 4.5138 -106.9031 -68.8907 -e82 17.6992 -115.6055 -42.8237 -e83 36.3439 -119.5779 -9.8687 -e84 46.0128 -111.2414 24.3333 -e85 51.2852 -94.7918 51.6324 -e86 51.4259 -73.0591 72.2066 -e87 47.2393 -44.9687 83.6301 -e88 26.6516 -101.8663 -70.6661 -e89 45.1236 -104.7655 -44.0328 -e90 57.8655 -103.5256 -9.7611 -e91 63.9905 -96.4121 23.9148 -e92 70.5058 -75.7637 48.5005 -e93 71.1604 -51.9506 62.6598 -e94 47.6666 -88.4775 -70.9466 -e95 66.1385 -84.099 -43.1226 -e96 73.3497 -85.4195 -9.1259 -e97 78.973 -75.3381 22.9914 -e98 80.4333 -57.6314 41.0392 -e99 64.7791 -63.4468 -72.9128 -e100 78.9456 -59.0811 -42.1499 -e101 81.3561 -64.9574 -10.6805 -e102 86.8287 -47.4801 21.1275 -e103 81.5686 -32.5607 48.0454 -e104 64.7084 -22.3205 69.56 -e105 43.8729 -16.4037 84.4638 -e106 15.1292 -11.1988 94.2978 -e107 73.8274 -41.9182 -71.3623 -e108 86.6072 -39.5795 -13.1303 -e109 86.9071 -20.4175 20.6161 -e110 75.081 -6.5323 51.8838 -e111 55.5669 5.2496 70.8921 -e112 28.5115 9.539 86.4255 -e113 74.2162 -8.3995 -73.5302 -e114 80.1456 -0.7407 -43.7537 -e115 84.3266 -8.1403 -13.4134 -e116 79.2929 12.862 26.7434 -e117 64.107 23.9427 53.1299 -e118 43.8912 33.1286 69.1301 -e119 69.3846 14.1002 -93.2413 -e120 76.0371 13.8902 -62.1954 -e121 75.957 25.7845 -39.1707 -e122 73.9961 28.7451 -4.2067 -e123 65.2231 40.63 33.7908 -e124 50.8914 45.2329 51.8816 -e125 70.649 37.1469 -50.4488 -e126 42.4961 62.7965 -72.8751 -e127 -43.8976 60.1135 -73.1652 -e128 -70.5546 32.7617 -50.9229 +spmnas 1 85 -41 +spmlpa -83 -20 -65 +spmrpa 83 -20 -65 +e1 66.4574 46.7101 -28.4211 +e2 60.2831 57.3885 5.9018 +e3 43.4522 64.8292 38.4999 +e4 32.1273 56.9859 60.0942 +e5 16.6042 37.9375 79.597 +e6 0.2021 14.7435 90.1184 +e7 -13.1141 -12.0759 94.203 +e8 47.4865 73.4515 -12.0078 +e9 29.5322 80.7153 16.899 +e10 19.6021 76.3404 40.8383 +e11 -1.2714 65.2974 61.4116 +e12 -17.5365 36.8773 79.4824 +e13 -27.7043 7.7932 86.2367 +e14 12.8924 89.0168 -5.9943 +e15 -1.6455 81.8408 19.8104 +e16 -1.6565 79.991 40.1854 +e17 -1.6819 87.4013 -20.7901 +e18 -22.6515 75.0282 40.6964 +e19 -34.0805 54.9298 59.8719 +e20 -44.4017 30.3866 68.8337 +e21 -16.4273 88.1063 -6.0928 +e22 -32.6731 78.7835 16.6902 +e23 -45.7252 62.0598 38.2005 +e24 -52.0237 42.0368 51.5361 +e25 -49.9478 70.4256 -12.3349 +e26 -61.8428 53.5959 5.4918 +e27 -65.9204 36.5573 33.3505 +e28 -63.9008 19.9674 52.7002 +e29 -54.3366 1.8365 70.5231 +e30 -41.4128 -19.0523 84.1775 +e31 -20.7464 -38.2522 93.4255 +e32 -67.1123 42.562 -28.8696 +e33 -73.684 24.1588 -4.7025 +e34 -78.1925 7.9712 26.2147 +e35 -72.9541 -11.1296 51.3868 +e36 -61.7406 -26.2474 69.1354 +e37 -42.9946 -47.7709 83.3271 +e38 -75.2228 21.0895 -39.6783 +e39 -81.6438 -13.2946 -13.9706 +e40 -83.6858 -25.7153 20.0434 +e41 -77.7882 -37.5095 47.5104 +e42 -66.2952 -56.2193 62.1983 +e43 -74.4102 9.218 -62.7005 +e44 -77.7266 -5.6435 -44.2837 +e45 -81.9711 -44.8147 -13.6962 +e46 -81.9318 -52.721 20.5609 +e47 -75.0525 -62.4601 40.5172 +e48 -67.5755 9.8468 -93.7012 +e49 -71.1338 -12.9134 -74.0182 +e50 -75.172 -69.8184 -11.2061 +e51 -72.3752 -80.0383 22.4833 +e52 -64.0693 -79.943 48.0486 +e53 -45.3534 -76.0646 71.8817 +e54 -23.4008 -69.4099 86.6143 +e55 2.3368 -54.4902 94.6995 +e56 -68.6804 -46.3439 -71.8407 +e57 -72.9197 -63.7973 -42.6598 +e58 -65.922 -89.7446 -9.5935 +e59 -56.1205 -100.1422 23.5115 +e60 -43.7265 -97.7425 51.3134 +e61 -23.5024 -92.0786 71.4105 +e62 3.1447 -79.4477 84.9223 +e63 -58.3036 -67.2692 -73.326 +e64 -58.5787 -87.9721 -43.5414 +e65 -49.3402 -106.8549 -10.1211 +e66 -37.2605 -113.8274 24.0537 +e67 -17.0392 -111.6557 48.514 +e68 -39.6844 -91.1902 -71.2399 +e69 -36.3162 -107.2946 -44.3062 +e70 -26.8638 -121.5408 -10.0809 +e71 -11.559 -122.0578 25.0838 +e72 4.4223 -115.9401 41.9529 +e73 -17.8815 -103.2493 -70.8156 +e74 -8.2808 -116.4123 -42.911 +e75 4.8781 -125.2707 -7.493 +e76 20.8652 -121.0508 25.1926 +e77 25.5321 -110.3337 48.6569 +e78 30.6143 -90.398 71.5922 +e79 29.0043 -67.7825 86.7903 +e80 24.376 -36.8509 93.577 +e81 4.5138 -106.9031 -68.8907 +e82 17.6992 -115.6055 -42.8237 +e83 36.3439 -119.5779 -9.8687 +e84 46.0128 -111.2414 24.3333 +e85 51.2852 -94.7918 51.6324 +e86 51.4259 -73.0591 72.2066 +e87 47.2393 -44.9687 83.6301 +e88 26.6516 -101.8663 -70.6661 +e89 45.1236 -104.7655 -44.0328 +e90 57.8655 -103.5256 -9.7611 +e91 63.9905 -96.4121 23.9148 +e92 70.5058 -75.7637 48.5005 +e93 71.1604 -51.9506 62.6598 +e94 47.6666 -88.4775 -70.9466 +e95 66.1385 -84.099 -43.1226 +e96 73.3497 -85.4195 -9.1259 +e97 78.973 -75.3381 22.9914 +e98 80.4333 -57.6314 41.0392 +e99 64.7791 -63.4468 -72.9128 +e100 78.9456 -59.0811 -42.1499 +e101 81.3561 -64.9574 -10.6805 +e102 86.8287 -47.4801 21.1275 +e103 81.5686 -32.5607 48.0454 +e104 64.7084 -22.3205 69.56 +e105 43.8729 -16.4037 84.4638 +e106 15.1292 -11.1988 94.2978 +e107 73.8274 -41.9182 -71.3623 +e108 86.6072 -39.5795 -13.1303 +e109 86.9071 -20.4175 20.6161 +e110 75.081 -6.5323 51.8838 +e111 55.5669 5.2496 70.8921 +e112 28.5115 9.539 86.4255 +e113 74.2162 -8.3995 -73.5302 +e114 80.1456 -0.7407 -43.7537 +e115 84.3266 -8.1403 -13.4134 +e116 79.2929 12.862 26.7434 +e117 64.107 23.9427 53.1299 +e118 43.8912 33.1286 69.1301 +e119 69.3846 14.1002 -93.2413 +e120 76.0371 13.8902 -62.1954 +e121 75.957 25.7845 -39.1707 +e122 73.9961 28.7451 -4.2067 +e123 65.2231 40.63 33.7908 +e124 50.8914 45.2329 51.8816 +e125 70.649 37.1469 -50.4488 +e126 42.4961 62.7965 -72.8751 +e127 -43.8976 60.1135 -73.1652 +e128 -70.5546 32.7617 -50.9229 diff --git a/EEGtemplates/egi256_GSN.sfp b/EEGtemplates/egi256_GSN.sfp index ee9d90b..549fd08 100644 --- a/EEGtemplates/egi256_GSN.sfp +++ b/EEGtemplates/egi256_GSN.sfp @@ -1,259 +1,259 @@ -spmnas 1 85 -41 -spmlpa -83 -20 -65 -spmrpa 83 -20 -65 -e1 63.1436 42.9579 -0.7497 -e2 59.9592 47.9723 18.2181 -e3 49.9144 57.222 37.1932 -e4 37.4096 61.8401 51.1832 -e5 28.0124 54.5754 65.8478 -e6 18.7504 42.5862 79.2927 -e7 9.9347 25.6372 89.8303 -e8 -0.039 3.8303 97.0937 -e9 -10.9955 -9.6084 98.9154 -e10 46.9529 67.2291 3.097 -e11 38.8115 71.4389 22.3149 -e12 28.7795 73.9588 38.8297 -e13 19.1956 68.8017 54.6552 -e14 10.1174 58.0983 70.2094 -e15 -0.0237 43.068 82.7636 -e16 -10.0125 25.5218 89.5083 -e17 -21.7223 5.901 92.7844 -e18 28.2529 78.8883 4.5041 -e19 20.7414 79.339 24.9994 -e20 9.7323 77.0734 42.4118 -e21 0.2238 70.417 58.051 -e22 -9.92 57.9824 69.886 -e23 -18.67 42.3697 78.6886 -e24 -30.2384 20.9232 84.4799 -e25 11.355 83.7746 7.2683 -e26 -8.8494 76.9658 42.1118 -e27 -18.6102 68.583 54.0449 -e28 -27.6258 54.2536 64.9497 -e29 -34.5166 39.6491 72.4685 -e30 1.2484 82.0175 -9.6223 -e31 -9.4147 83.6544 6.933 -e32 -19.317 79.1072 24.3527 -e33 -27.7361 73.6318 37.9174 -e34 -36.6256 61.4117 49.9881 -e35 -40.9315 50.1702 57.5999 -e36 -26.1603 78.5735 3.6257 -e37 -37.2037 70.9991 21.0878 -e38 -48.6227 56.6519 35.6025 -e39 -51.7733 46.7566 46.8215 -e40 -52.4953 33.3262 58.0612 -e41 -46.6506 18.0101 74.0459 -e42 -41.0126 1.3278 84.1793 -e43 -29.6601 -16.1746 93.9354 -e44 -20.8863 -29.2413 98.6739 -e45 -44.6764 66.699 1.6179 -e46 -57.9501 47.2901 16.3147 -e47 -61.56 36.0554 29.1765 -e48 -62.614 24.6784 45.2129 -e49 -60.2924 12.3169 59.8469 -e50 -55.2764 -2.7728 73.3339 -e51 -44.3599 -17.7823 85.7129 -e52 -36.9577 -33.7582 93.2416 -e53 -60.4679 42.2427 -2.7451 -e54 -64.3967 32.1912 13.5816 -e55 -68.6736 18.071 28.5082 -e56 -69.6224 4.2051 43.5383 -e57 -66.0493 -8.0355 60.5994 -e58 -59.0774 -22.2327 73.6169 -e59 -52.0771 -38.0758 82.9708 -e60 -65.9301 26.8134 -5.5548 -e61 -73.0635 5.0165 10.2972 -e62 -75.1505 -6.5433 27.836 -e63 -74.3792 -18.5536 43.3582 -e64 -70.8442 -28.4396 57.4913 -e65 -64.1434 -42.4165 71.0556 -e66 -70.862 -0.0478 -35.0689 -e67 -72.9295 -4.4484 -10.8677 -e68 -76.5337 -20.0026 9.5415 -e69 -76.561 -29.4789 26.9923 -e70 -75.1204 -36.6292 43.3777 -e71 -71.5751 -46.8548 55.3891 -e72 -70.0464 -13.5306 -53.443 -e73 -75.5537 -42.5167 9.0799 -e74 -74.6081 -51.704 26.2949 -e75 -70.8383 -59.1448 45.4339 -e76 -64.4235 -61.0594 61.5487 -e77 -52.4902 -60.9675 77.6967 -e78 -37.8293 -54.7473 89.8754 -e79 -20.9081 -49.828 98.0887 -e80 0.1173 -41.5647 102.8501 -e81 -67.5378 -21.4386 -71.2279 -e82 -71.3868 -52.0524 -9.2811 -e83 -71.3284 -63.2834 10.5273 -e84 -67.0571 -72.1287 30.9877 -e85 -61.5225 -75.9202 50.2893 -e86 -50.7168 -79.3713 66.5856 -e87 -34.4827 -73.1951 83.9094 -e88 -19.0563 -67.9245 93.1513 -e89 0.3209 -62.616 97.3614 -e90 -62.6532 -31.104 -84.4747 -e91 -63.3934 -39.4884 -71.3661 -e92 -63.693 -51.4885 -52.0473 -e93 -64.8909 -61.5873 -32.7058 -e94 -65.2969 -72.9592 -9.3381 -e95 -62.4369 -82.7105 13.454 -e96 -56.234 -88.8753 35.7429 -e97 -46.4375 -90.8501 53.8383 -e98 -32.1625 -88.6884 70.4792 -e99 -18.9647 -84.604 82.1748 -e100 0.5456 -79.0294 88.9872 -e101 -58.3365 -34.8547 -103.5455 -e102 -57.3352 -53.5707 -85.6558 -e103 -55.5926 -65.1831 -67.3518 -e104 -55.2261 -72.9311 -50.1961 -e105 -54.1307 -82.6811 -31.0795 -e106 -53.5307 -90.3221 -4.8706 -e107 -47.6362 -98.7543 19.0393 -e108 -39.1783 -101.4774 39.8872 -e109 -29.4015 -100.0108 56.2179 -e110 -15.8041 -96.8739 68.7071 -e111 0.7709 -89.9137 78.6875 -e112 -49.2294 -70.3302 -83.3054 -e113 -48.6022 -78.3688 -63.6095 -e114 -46.0509 -89.7785 -44.6602 -e115 -43.0506 -98.0865 -25.5439 -e116 -37.445 -104.6703 -0.2502 -e117 -29.3125 -109.8536 22.0491 -e118 -21.3577 -110.8386 39.0483 -e119 -13.7451 -105.0025 55.549 -e120 1.0582 -100.9825 64.593 -e121 -36.9188 -85.9956 -82.0032 -e122 -33.6689 -93.5728 -60.9364 -e123 -33.0087 -101.4238 -41.3186 -e124 -27.5891 -107.3749 -22.3023 -e125 -22.7879 -112.9468 1.3573 -e126 -16.6228 -115.405 22.9997 -e127 1.5205 -112.5152 39.7767 -e128 16.1877 -104.8293 56.0322 -e129 17.7334 -96.6799 69.2485 -e130 20.3246 -84.3767 82.809 -e131 19.8804 -67.6992 93.7798 -e132 21.3741 -49.5834 98.7712 -e133 21.1077 -28.9984 99.3518 -e134 -23.5235 -96.2343 -81.1719 -e135 -20.2186 -102.5902 -61.811 -e136 -17.7146 -108.1642 -45.9145 -e137 -14.1675 -112.3 -23.5808 -e138 2.147 -116.3343 2.1205 -e139 20.2243 -115.1919 23.5945 -e140 24.3904 -110.574 39.7868 -e141 31.7588 -99.6569 57.2052 -e142 33.9355 -88.306 71.5462 -e143 35.6527 -72.7894 85.0415 -e144 38.6033 -54.3051 91.1092 -e145 37.394 -33.3281 94.4418 -e146 -12.5298 -101.9268 -79.4819 -e147 -11.8752 -105.1069 -61.1438 -e148 2.8391 -106.8607 -44.1522 -e149 19.2341 -112.1067 -23.0417 -e150 27.0547 -112.6585 2.1619 -e151 32.8763 -109.4939 23.0529 -e152 42.071 -101.0074 41.1988 -e153 48.761 -90.2993 55.375 -e154 52.502 -78.7742 68.2519 -e155 53.7155 -60.353 79.4112 -e156 52.8822 -37.4686 84.6652 -e157 18.072 -104.9336 -60.6604 -e158 23.4518 -107.926 -45.25 -e159 32.5527 -107.0269 -21.3315 -e160 41.6643 -104.2126 1.0268 -e161 51.1645 -98.1827 20.6342 -e162 59.1119 -88.208 37.6049 -e163 63.7876 -75.1953 52.3122 -e164 66.162 -60.3039 63.6567 -e165 65.3721 -41.6672 73.1463 -e166 19.2809 -101.7427 -78.9684 -e167 26.4044 -102.3205 -61.0584 -e168 38.5154 -101.01 -40.164 -e169 48.0076 -97.5597 -24.074 -e170 57.7319 -89.6784 -3.0745 -e171 65.9603 -81.9676 15.5267 -e172 69.8981 -71.3364 33.1985 -e173 73.0703 -58.3122 47.757 -e174 73.3518 -46.0164 57.7286 -e175 30.2602 -95.9231 -80.3037 -e176 39.7199 -93.1482 -59.7517 -e177 51.5298 -89.214 -43.085 -e178 59.0904 -82.0261 -29.2519 -e179 69.4445 -72.1796 -7.163 -e180 74.7277 -62.4384 12.8851 -e181 77.3716 -50.8248 28.7483 -e182 77.1691 -35.7481 45.8361 -e183 72.3519 -27.6111 59.8028 -e184 60.0054 -21.5437 75.5392 -e185 44.8588 -17.2661 87.1531 -e186 29.8856 -15.8301 94.8966 -e187 10.9998 -9.4812 99.2705 -e188 43.5622 -85.53 -80.704 -e189 54.5638 -77.772 -61.9442 -e190 60.6929 -72.2605 -48.3249 -e191 69.6655 -60.8089 -30.5337 -e192 75.2999 -51.2037 -6.9132 -e193 78.7695 -41.6239 11.5711 -e194 79.0574 -28.5786 29.5044 -e195 76.2309 -17.6822 45.7895 -e196 67.2362 -7.2644 62.751 -e197 56.0025 -2.129 75.1302 -e198 41.3534 1.8043 85.5089 -e199 21.7475 6.1525 93.4861 -e200 55.7358 -69.723 -81.611 -e201 61.5259 -64.5055 -65.4612 -e202 68.9794 -50.7209 -49.9056 -e203 79.4873 -19.1 12.0601 -e204 77.3692 -5.661 30.2981 -e205 71.2216 5.0199 45.8119 -e206 61.2838 13.0203 61.8094 -e207 47.131 18.5527 75.5598 -e208 30.3609 21.2738 85.4581 -e209 63.7287 -52.8703 -83.7015 -e210 69.1696 -38.7215 -69.2262 -e211 76.3709 -3.5846 -8.4576 -e212 75.7206 5.8773 12.6989 -e213 70.6046 18.8767 30.7566 -e214 63.939 25.4105 47.2558 -e215 53.3183 33.9383 59.7693 -e216 34.8175 40.0503 73.5877 -e217 65.0995 -34.1406 -101.553 -e218 68.7593 -30.3437 -82.3534 -e219 73.1093 -20.6249 -68.9575 -e220 74.9579 -12.6917 -51.1023 -e221 75.0345 0.7962 -32.7138 -e222 68.8621 27.5932 -3.3789 -e223 66.6554 32.9494 15.6971 -e224 63.2766 36.7777 31.1917 -e225 52.8109 47.3617 48.5098 -e226 41.5914 50.6477 58.932 -e227 70.1588 34.3158 -29.1413 -e228 74.1693 18.2802 -37.8948 -e229 75.0314 6.7954 -55.4711 -e230 73.6635 -5.2058 -70.8925 -e231 70.7363 -19.9592 -87.7119 -e232 65.9199 -19.6207 -104.6183 -e233 69.8814 25.3784 -63.1355 -e234 70.1207 14.7797 -77.8829 -e235 67.4785 4.7565 -93.3141 -e236 62.4597 3.022 -106.2172 -e237 64.5381 41.4398 -53.9242 -e238 62.7393 37.7534 -72.3428 -e239 63.1323 28.9537 -86.2255 -e240 61.059 20.6736 -99.9603 -e241 45.2809 60.1243 -64.9764 -e242 -40.7387 59.6266 -66.365 -e243 -60.1353 40.7185 -55.9367 -e244 -57.7049 37.0566 -74.2871 -e245 -57.5549 28.2555 -88.1737 -e246 -54.9504 20.0025 -101.833 -e247 -65.0033 24.598 -65.3129 -e248 -64.6521 14 -80.0585 -e249 -61.4054 4.0108 -95.3946 -e250 -55.9556 2.3369 -108.1287 -e251 -66.4714 33.5253 -31.3469 -e252 -70.0224 17.446 -40.2224 -e253 -70.193 5.9552 -57.8154 -e254 -68.1985 -6.0265 -73.1825 -e255 -64.5706 -20.742 -89.8961 -e256 -59.2171 -20.3447 -106.6383 +spmnas 1 85 -41 +spmlpa -83 -20 -65 +spmrpa 83 -20 -65 +e1 63.1436 42.9579 -0.7497 +e2 59.9592 47.9723 18.2181 +e3 49.9144 57.222 37.1932 +e4 37.4096 61.8401 51.1832 +e5 28.0124 54.5754 65.8478 +e6 18.7504 42.5862 79.2927 +e7 9.9347 25.6372 89.8303 +e8 -0.039 3.8303 97.0937 +e9 -10.9955 -9.6084 98.9154 +e10 46.9529 67.2291 3.097 +e11 38.8115 71.4389 22.3149 +e12 28.7795 73.9588 38.8297 +e13 19.1956 68.8017 54.6552 +e14 10.1174 58.0983 70.2094 +e15 -0.0237 43.068 82.7636 +e16 -10.0125 25.5218 89.5083 +e17 -21.7223 5.901 92.7844 +e18 28.2529 78.8883 4.5041 +e19 20.7414 79.339 24.9994 +e20 9.7323 77.0734 42.4118 +e21 0.2238 70.417 58.051 +e22 -9.92 57.9824 69.886 +e23 -18.67 42.3697 78.6886 +e24 -30.2384 20.9232 84.4799 +e25 11.355 83.7746 7.2683 +e26 -8.8494 76.9658 42.1118 +e27 -18.6102 68.583 54.0449 +e28 -27.6258 54.2536 64.9497 +e29 -34.5166 39.6491 72.4685 +e30 1.2484 82.0175 -9.6223 +e31 -9.4147 83.6544 6.933 +e32 -19.317 79.1072 24.3527 +e33 -27.7361 73.6318 37.9174 +e34 -36.6256 61.4117 49.9881 +e35 -40.9315 50.1702 57.5999 +e36 -26.1603 78.5735 3.6257 +e37 -37.2037 70.9991 21.0878 +e38 -48.6227 56.6519 35.6025 +e39 -51.7733 46.7566 46.8215 +e40 -52.4953 33.3262 58.0612 +e41 -46.6506 18.0101 74.0459 +e42 -41.0126 1.3278 84.1793 +e43 -29.6601 -16.1746 93.9354 +e44 -20.8863 -29.2413 98.6739 +e45 -44.6764 66.699 1.6179 +e46 -57.9501 47.2901 16.3147 +e47 -61.56 36.0554 29.1765 +e48 -62.614 24.6784 45.2129 +e49 -60.2924 12.3169 59.8469 +e50 -55.2764 -2.7728 73.3339 +e51 -44.3599 -17.7823 85.7129 +e52 -36.9577 -33.7582 93.2416 +e53 -60.4679 42.2427 -2.7451 +e54 -64.3967 32.1912 13.5816 +e55 -68.6736 18.071 28.5082 +e56 -69.6224 4.2051 43.5383 +e57 -66.0493 -8.0355 60.5994 +e58 -59.0774 -22.2327 73.6169 +e59 -52.0771 -38.0758 82.9708 +e60 -65.9301 26.8134 -5.5548 +e61 -73.0635 5.0165 10.2972 +e62 -75.1505 -6.5433 27.836 +e63 -74.3792 -18.5536 43.3582 +e64 -70.8442 -28.4396 57.4913 +e65 -64.1434 -42.4165 71.0556 +e66 -70.862 -0.0478 -35.0689 +e67 -72.9295 -4.4484 -10.8677 +e68 -76.5337 -20.0026 9.5415 +e69 -76.561 -29.4789 26.9923 +e70 -75.1204 -36.6292 43.3777 +e71 -71.5751 -46.8548 55.3891 +e72 -70.0464 -13.5306 -53.443 +e73 -75.5537 -42.5167 9.0799 +e74 -74.6081 -51.704 26.2949 +e75 -70.8383 -59.1448 45.4339 +e76 -64.4235 -61.0594 61.5487 +e77 -52.4902 -60.9675 77.6967 +e78 -37.8293 -54.7473 89.8754 +e79 -20.9081 -49.828 98.0887 +e80 0.1173 -41.5647 102.8501 +e81 -67.5378 -21.4386 -71.2279 +e82 -71.3868 -52.0524 -9.2811 +e83 -71.3284 -63.2834 10.5273 +e84 -67.0571 -72.1287 30.9877 +e85 -61.5225 -75.9202 50.2893 +e86 -50.7168 -79.3713 66.5856 +e87 -34.4827 -73.1951 83.9094 +e88 -19.0563 -67.9245 93.1513 +e89 0.3209 -62.616 97.3614 +e90 -62.6532 -31.104 -84.4747 +e91 -63.3934 -39.4884 -71.3661 +e92 -63.693 -51.4885 -52.0473 +e93 -64.8909 -61.5873 -32.7058 +e94 -65.2969 -72.9592 -9.3381 +e95 -62.4369 -82.7105 13.454 +e96 -56.234 -88.8753 35.7429 +e97 -46.4375 -90.8501 53.8383 +e98 -32.1625 -88.6884 70.4792 +e99 -18.9647 -84.604 82.1748 +e100 0.5456 -79.0294 88.9872 +e101 -58.3365 -34.8547 -103.5455 +e102 -57.3352 -53.5707 -85.6558 +e103 -55.5926 -65.1831 -67.3518 +e104 -55.2261 -72.9311 -50.1961 +e105 -54.1307 -82.6811 -31.0795 +e106 -53.5307 -90.3221 -4.8706 +e107 -47.6362 -98.7543 19.0393 +e108 -39.1783 -101.4774 39.8872 +e109 -29.4015 -100.0108 56.2179 +e110 -15.8041 -96.8739 68.7071 +e111 0.7709 -89.9137 78.6875 +e112 -49.2294 -70.3302 -83.3054 +e113 -48.6022 -78.3688 -63.6095 +e114 -46.0509 -89.7785 -44.6602 +e115 -43.0506 -98.0865 -25.5439 +e116 -37.445 -104.6703 -0.2502 +e117 -29.3125 -109.8536 22.0491 +e118 -21.3577 -110.8386 39.0483 +e119 -13.7451 -105.0025 55.549 +e120 1.0582 -100.9825 64.593 +e121 -36.9188 -85.9956 -82.0032 +e122 -33.6689 -93.5728 -60.9364 +e123 -33.0087 -101.4238 -41.3186 +e124 -27.5891 -107.3749 -22.3023 +e125 -22.7879 -112.9468 1.3573 +e126 -16.6228 -115.405 22.9997 +e127 1.5205 -112.5152 39.7767 +e128 16.1877 -104.8293 56.0322 +e129 17.7334 -96.6799 69.2485 +e130 20.3246 -84.3767 82.809 +e131 19.8804 -67.6992 93.7798 +e132 21.3741 -49.5834 98.7712 +e133 21.1077 -28.9984 99.3518 +e134 -23.5235 -96.2343 -81.1719 +e135 -20.2186 -102.5902 -61.811 +e136 -17.7146 -108.1642 -45.9145 +e137 -14.1675 -112.3 -23.5808 +e138 2.147 -116.3343 2.1205 +e139 20.2243 -115.1919 23.5945 +e140 24.3904 -110.574 39.7868 +e141 31.7588 -99.6569 57.2052 +e142 33.9355 -88.306 71.5462 +e143 35.6527 -72.7894 85.0415 +e144 38.6033 -54.3051 91.1092 +e145 37.394 -33.3281 94.4418 +e146 -12.5298 -101.9268 -79.4819 +e147 -11.8752 -105.1069 -61.1438 +e148 2.8391 -106.8607 -44.1522 +e149 19.2341 -112.1067 -23.0417 +e150 27.0547 -112.6585 2.1619 +e151 32.8763 -109.4939 23.0529 +e152 42.071 -101.0074 41.1988 +e153 48.761 -90.2993 55.375 +e154 52.502 -78.7742 68.2519 +e155 53.7155 -60.353 79.4112 +e156 52.8822 -37.4686 84.6652 +e157 18.072 -104.9336 -60.6604 +e158 23.4518 -107.926 -45.25 +e159 32.5527 -107.0269 -21.3315 +e160 41.6643 -104.2126 1.0268 +e161 51.1645 -98.1827 20.6342 +e162 59.1119 -88.208 37.6049 +e163 63.7876 -75.1953 52.3122 +e164 66.162 -60.3039 63.6567 +e165 65.3721 -41.6672 73.1463 +e166 19.2809 -101.7427 -78.9684 +e167 26.4044 -102.3205 -61.0584 +e168 38.5154 -101.01 -40.164 +e169 48.0076 -97.5597 -24.074 +e170 57.7319 -89.6784 -3.0745 +e171 65.9603 -81.9676 15.5267 +e172 69.8981 -71.3364 33.1985 +e173 73.0703 -58.3122 47.757 +e174 73.3518 -46.0164 57.7286 +e175 30.2602 -95.9231 -80.3037 +e176 39.7199 -93.1482 -59.7517 +e177 51.5298 -89.214 -43.085 +e178 59.0904 -82.0261 -29.2519 +e179 69.4445 -72.1796 -7.163 +e180 74.7277 -62.4384 12.8851 +e181 77.3716 -50.8248 28.7483 +e182 77.1691 -35.7481 45.8361 +e183 72.3519 -27.6111 59.8028 +e184 60.0054 -21.5437 75.5392 +e185 44.8588 -17.2661 87.1531 +e186 29.8856 -15.8301 94.8966 +e187 10.9998 -9.4812 99.2705 +e188 43.5622 -85.53 -80.704 +e189 54.5638 -77.772 -61.9442 +e190 60.6929 -72.2605 -48.3249 +e191 69.6655 -60.8089 -30.5337 +e192 75.2999 -51.2037 -6.9132 +e193 78.7695 -41.6239 11.5711 +e194 79.0574 -28.5786 29.5044 +e195 76.2309 -17.6822 45.7895 +e196 67.2362 -7.2644 62.751 +e197 56.0025 -2.129 75.1302 +e198 41.3534 1.8043 85.5089 +e199 21.7475 6.1525 93.4861 +e200 55.7358 -69.723 -81.611 +e201 61.5259 -64.5055 -65.4612 +e202 68.9794 -50.7209 -49.9056 +e203 79.4873 -19.1 12.0601 +e204 77.3692 -5.661 30.2981 +e205 71.2216 5.0199 45.8119 +e206 61.2838 13.0203 61.8094 +e207 47.131 18.5527 75.5598 +e208 30.3609 21.2738 85.4581 +e209 63.7287 -52.8703 -83.7015 +e210 69.1696 -38.7215 -69.2262 +e211 76.3709 -3.5846 -8.4576 +e212 75.7206 5.8773 12.6989 +e213 70.6046 18.8767 30.7566 +e214 63.939 25.4105 47.2558 +e215 53.3183 33.9383 59.7693 +e216 34.8175 40.0503 73.5877 +e217 65.0995 -34.1406 -101.553 +e218 68.7593 -30.3437 -82.3534 +e219 73.1093 -20.6249 -68.9575 +e220 74.9579 -12.6917 -51.1023 +e221 75.0345 0.7962 -32.7138 +e222 68.8621 27.5932 -3.3789 +e223 66.6554 32.9494 15.6971 +e224 63.2766 36.7777 31.1917 +e225 52.8109 47.3617 48.5098 +e226 41.5914 50.6477 58.932 +e227 70.1588 34.3158 -29.1413 +e228 74.1693 18.2802 -37.8948 +e229 75.0314 6.7954 -55.4711 +e230 73.6635 -5.2058 -70.8925 +e231 70.7363 -19.9592 -87.7119 +e232 65.9199 -19.6207 -104.6183 +e233 69.8814 25.3784 -63.1355 +e234 70.1207 14.7797 -77.8829 +e235 67.4785 4.7565 -93.3141 +e236 62.4597 3.022 -106.2172 +e237 64.5381 41.4398 -53.9242 +e238 62.7393 37.7534 -72.3428 +e239 63.1323 28.9537 -86.2255 +e240 61.059 20.6736 -99.9603 +e241 45.2809 60.1243 -64.9764 +e242 -40.7387 59.6266 -66.365 +e243 -60.1353 40.7185 -55.9367 +e244 -57.7049 37.0566 -74.2871 +e245 -57.5549 28.2555 -88.1737 +e246 -54.9504 20.0025 -101.833 +e247 -65.0033 24.598 -65.3129 +e248 -64.6521 14 -80.0585 +e249 -61.4054 4.0108 -95.3946 +e250 -55.9556 2.3369 -108.1287 +e251 -66.4714 33.5253 -31.3469 +e252 -70.0224 17.446 -40.2224 +e253 -70.193 5.9552 -57.8154 +e254 -68.1985 -6.0265 -73.1825 +e255 -64.5706 -20.742 -89.8961 +e256 -59.2171 -20.3447 -106.6383 diff --git a/EEGtemplates/egi256_GSN_HydroCel.sfp b/EEGtemplates/egi256_GSN_HydroCel.sfp index 7527f18..c942158 100644 --- a/EEGtemplates/egi256_GSN_HydroCel.sfp +++ b/EEGtemplates/egi256_GSN_HydroCel.sfp @@ -1,259 +1,259 @@ -spmnas 1 85 -41 -spmlpa -83 -20 -65 -spmrpa 83 -20 -65 -e1 71.9872 33.5519 -12.4579 -e2 66.5644 42.5133 8.59 -e3 58.0961 49.3772 28.2045 -e4 48.6026 53.9002 46.916 -e5 36.05 49.8077 64.9877 -e6 21.8467 38.7535 78.4805 -e7 10.7682 25.583 89.0865 -e8 -1.3975 8.9851 93.8693 -e9 -13.1647 -12.1274 96.6725 -e10 61.5573 53.2255 -4.7359 -e11 52.3 61.959 14.8732 -e12 39.6349 67.3205 36.0606 -e13 26.2733 65.6068 54.4194 -e14 11.9321 55.9521 70.1803 -e15 -0.8647 42.1566 81.1926 -e16 -13.1036 25.6825 88.3434 -e17 -24.4005 2.363 90.7837 -e18 42.5764 73.1806 2.2186 -e19 30.0226 78.2286 19.6983 -e20 14.8743 77.5092 39.2769 -e21 0.0176 69.804 56.5523 -e22 -12.8364 56.0554 69.4094 -e23 -23.3909 38.9421 77.0724 -e24 -34.6222 17.9589 82.5333 -e25 15.7138 85.6183 4.9794 -e26 1.1949 85.0222 20.7678 -e27 -13.6712 77.6282 38.3884 -e28 -26.0887 65.8251 52.7895 -e29 -36.635 50.1107 62.7252 -e30 -45.7434 30.7668 69.0533 -e31 2.1536 85.6989 -9.9396 -e32 -12.3084 85.7351 4.1072 -e33 -27.566 78.4686 17.9057 -e34 -38.2678 67.6453 33.6356 -e35 -48.0048 54.3029 43.9089 -e36 -51.3387 39.991 54.2574 -e37 -39.0499 73.5208 -0.3222 -e38 -49.635 62.3839 11.7002 -e39 -56.3535 49.8542 24.642 -e40 -61.574 37.9399 38.8814 -e41 -60.531 25.1736 53.8308 -e42 -54.2404 12.8149 68.0377 -e43 -47.6294 -0.2957 79.3179 -e44 -36.8835 -16.002 88.3827 -e45 -21.6855 -33.4393 95.957 -e46 -57.7271 53.7227 -8.449 -e47 -63.6424 43.0561 4.537 -e48 -69.0538 31.6015 18.2175 -e49 -70.8422 19.3762 33.6133 -e50 -69.0879 7.4547 51.5356 -e51 -62.0285 -5.7442 65.7286 -e52 -54.4197 -20.0184 77.6474 -e53 -38.8374 -38.2922 88.0442 -e54 -67.82 34.1346 -16.8098 -e55 -71.8924 23.0121 -1.7381 -e56 -75.928 11.1946 14.0571 -e57 -76.11 0.0998 31.2115 -e58 -74.0971 -10.6531 48.5772 -e59 -67.9854 -24.5887 64.362 -e60 -55.3657 -42.1938 76.0642 -e61 -73.5787 11.0171 -21.7665 -e62 -76.4444 0.0144 -5.3127 -e63 -79.0176 -9.6877 11.9231 -e64 -80.5793 -18.9186 29.54 -e65 -76.5672 -29.8091 47.2408 -e66 -69.0629 -44.4906 59.9509 -e67 -74.6126 -1.082 -39.3048 -e68 -75.6833 -9.0589 -22.6141 -e69 -78.1137 -19.8358 -8.2611 -e70 -79.2173 -29.2484 9.3539 -e71 -80.5478 -37.9958 28.1492 -e72 -76.0784 -47.0968 43.1782 -e73 -72.4016 -10.0791 -57.7182 -e74 -76.4617 -39.0533 -8.9971 -e75 -77.3728 -49.2668 10.745 -e76 -74.6521 -58.0939 28.9923 -e77 -69.3177 -62.3691 48.3714 -e78 -57.6157 -63.9704 65.0226 -e79 -42.717 -61.9566 80.0486 -e80 -24.0512 -56.7381 90.7393 -e81 -1.7418 -46.9478 97.4385 -e82 -67.9915 -21.4725 -72.2903 -e83 -72.204 -54.8711 -22.5174 -e84 -74.1656 -57.9639 -5.9659 -e85 -71.1152 -69.4042 13.8673 -e86 -65.0735 -75.1549 33.3834 -e87 -56.1031 -79.5268 53.8203 -e88 -41.599 -78.3258 69.887 -e89 -24.4773 -75.5716 82.9624 -e90 -1.6459 -64.7557 91.9748 -e91 -64.5643 -34.3896 -86.5432 -e92 -64.3411 -45.4959 -67.6343 -e93 -65.3458 -58.3165 -51.061 -e94 -68.3241 -63.5803 -36.6986 -e95 -68.4279 -70.3117 -20.4031 -e96 -65.909 -78.7986 -0.8173 -e97 -59.4331 -88 18.2447 -e98 -51.3943 -91.4482 37.2956 -e99 -38.3171 -91.8728 54.9586 -e100 -22.6743 -89.0141 70.5083 -e101 -1.0686 -97.6091 69.0286 -e102 -60.1829 -54.3722 -82.7602 -e103 -59.4692 -63.4617 -66.0936 -e104 -58.5943 -74.531 -48.4668 -e105 -61.23 -79.4547 -34.5644 -e106 -58.5144 -88.0093 -16.3299 -e107 -51.6195 -97.5152 2.1098 -e108 -42.7354 -104.1792 21.2829 -e109 -32.7893 -105.7871 39.9809 -e110 -18.0708 -101.6289 55.5438 -e111 -52.9998 -74.5331 -79.2039 -e112 -51.0153 -82.0458 -63.6896 -e113 -48.5595 -91.9992 -45.6554 -e114 -50.9249 -94.3075 -31.3117 -e115 -40.1136 -107.0107 -13.3504 -e116 -30.6411 -113.4896 5.3057 -e117 -19.2803 -115.6653 23.6772 -e118 -11.193 -111.7214 39.4554 -e119 -0.5817 -106.0184 52.2625 -e120 -43.765 -88.9071 -77.6195 -e121 -39.2687 -95.9321 -60.9462 -e122 -34.0109 -104.9387 -43.2126 -e123 -28.7093 -114.9108 -22.7014 -e124 -20.8409 -118.3467 -9.3604 -e125 -9.447 -119.4818 6.9597 -e126 0.2721 -115.6783 23.5385 -e127 10.7577 -111.8129 40.1387 -e128 16.7053 -101.7739 56.6263 -e129 20.4741 -89.194 71.8515 -e130 21.611 -75.7637 84.397 -e131 20.8589 -56.9253 92.1373 -e132 18.3673 -33.6063 97.2038 -e133 -31.4671 -102.9747 -71.0456 -e134 -24.436 -107.5564 -58.2978 -e135 -18.2514 -115.0888 -37.3942 -e136 -7.4658 -116.582 -24.6694 -e137 1.3442 -117.0396 -11.086 -e138 10.9715 -119.5669 7.5953 -e139 19.7775 -115.8281 24.8929 -e140 32.3281 -106.0586 42.0079 -e141 37.0294 -92.1868 57.304 -e142 39.4892 -78.6638 72.4111 -e143 40.1093 -62.3018 82.6268 -e144 35.9371 -38.6039 90.3718 -e145 -15.7174 -109.5457 -70.6892 -e146 -7.872 -113.5766 -57.1472 -e147 2.2762 -114.1391 -40.6387 -e148 10.9855 -116.6589 -24.0951 -e149 23.3674 -118.531 -7.9843 -e150 32.2767 -113.7518 7.2642 -e151 43.431 -104.5384 23.9651 -e152 51.1829 -91.8757 40.4886 -e153 54.954 -79.9897 57.2773 -e154 55.8964 -64.4435 68.556 -e155 53.1454 -42.6461 79.4419 -e156 13.4359 -113.6654 -56.484 -e157 22.5538 -115.2589 -36.124 -e158 32.0787 -115.1642 -20.8092 -e159 42.9447 -107.3569 -10.765 -e160 53.5455 -97.9536 5.3834 -e161 60.4194 -88.4996 21.9754 -e162 65.2142 -75.6979 37.4389 -e163 68.6243 -62.9441 52.6652 -e164 67.7987 -45.061 64.2111 -e165 22.1416 -109.7035 -69.5108 -e166 30.089 -107.7837 -56.6006 -e167 38.7286 -105.2419 -40.9484 -e168 54.9576 -94.7488 -28.0158 -e169 61.6528 -88.5102 -12.5894 -e170 68.1447 -79.3574 3.3555 -e171 72.5056 -70.0028 18.3378 -e172 75.1891 -58.7185 33.6565 -e173 75.8219 -47.7299 47.9065 -e174 37.9372 -103.264 -68.8852 -e175 45.154 -96.284 -58.3183 -e176 53.5082 -92.4246 -42.4783 -e177 65.5684 -79.9832 -30.6174 -e178 71.9475 -70.8968 -16.0335 -e179 76.8788 -58.5935 -1.2642 -e180 79.1128 -49.9191 15.616 -e181 81.2929 -38.6704 33.1869 -e182 76.201 -30.4459 51.9961 -e183 66.6147 -25.1498 68.5518 -e184 52.2875 -20.4631 80.9689 -e185 34.1516 -16.2981 90.5939 -e186 9.9963 -12.224 97.3934 -e187 50.7369 -89.301 -74.6779 -e188 57.1637 -82.4967 -60.3223 -e189 63.8436 -75.0413 -44.6556 -e190 72.9135 -64.169 -32.3022 -e191 75.9763 -55.4887 -17.9049 -e192 79.5164 -39.7034 -4.1418 -e193 81.2069 -29.9171 14.3475 -e194 81.3968 -19.5937 34.5819 -e195 73.8122 -11.2696 53.1813 -e196 60.7415 -6.2559 69.5501 -e197 45.571 -0.6841 82.219 -e198 21.6968 2.1709 92.2186 -e199 60.1717 -75.0049 -75.6812 -e200 65.9052 -63.9843 -62.191 -e201 70.8782 -58.8843 -46.8206 -e202 81.2794 -20.5001 -3.2995 -e203 81.0107 -10.3548 16.9044 -e204 76.9907 -0.5383 35.9771 -e205 68.7797 6.88 55.8271 -e206 52.9797 12.368 71.3752 -e207 32.5415 17.679 84.624 -e208 67.7297 -54.9054 -78.7786 -e209 71.013 -46.0601 -63.4211 -e210 79.8362 -9.7071 -17.7731 -e211 79.5953 -0.636 -0.4555 -e212 77.9684 10.5531 18.8475 -e213 71.7444 18.7819 38.0517 -e214 60.2444 24.6702 57.5903 -e215 44.5857 30.3903 71.8651 -e216 72.5043 -34.9609 -82.2766 -e217 75.1458 -22.0691 -67.8347 -e218 78.7358 -10.7091 -53.0137 -e219 79.8721 -1.7259 -34.4961 -e220 77.8503 10.3859 -17.0529 -e221 75.0215 22.3998 2.835 -e222 71.0189 31.0176 22.5777 -e223 62.3214 37.4235 42.7379 -e224 51.1671 39.5637 57.4482 -e225 79.3065 13.5308 -35.7965 -e226 75.6101 29.353 -38.6076 -e227 79.1695 7.4866 -54.9622 -e228 77.8761 -3.2226 -71.591 -e229 73.0385 -17.4029 -85.7303 -e230 70.9309 41.9734 -48.6336 -e231 76.0721 24.1555 -60.2421 -e232 77.4399 15.5937 -76.3863 -e233 75.5783 1.1137 -90.7508 -e234 62.6075 54.8537 -55.2766 -e235 70.6713 39.625 -67.1663 -e236 72.0051 30.3047 -81.5461 -e237 70.6903 18.2789 -96.1096 -e238 50.6947 65.0832 -57.3711 -e239 62.5078 48.1113 -76.8843 -e240 65.1617 38.3127 -89.1377 -e241 -43.5136 65.4759 -60.3036 -e242 -54.2312 48.5979 -80.5181 -e243 -56.1993 38.8186 -92.9154 -e244 -55.6183 55.3465 -58.9567 -e245 -63.0536 40.1823 -71.3288 -e246 -63.5681 30.8697 -85.7661 -e247 -61.4503 18.8297 -100.2228 -e248 -64.4457 42.5377 -52.8475 -e249 -69.0033 24.7602 -64.7579 -e250 -69.4356 16.2059 -80.9582 -e251 -66.8049 1.7071 -95.1828 -e252 -69.8444 29.9592 -43.1352 -e253 -73.8402 14.1691 -40.5636 -e254 -72.5617 8.119 -59.6852 -e255 -70.3259 -2.6048 -76.2042 -e256 -64.7365 -16.8286 -90.0189 +spmnas 1 85 -41 +spmlpa -83 -20 -65 +spmrpa 83 -20 -65 +e1 71.9872 33.5519 -12.4579 +e2 66.5644 42.5133 8.59 +e3 58.0961 49.3772 28.2045 +e4 48.6026 53.9002 46.916 +e5 36.05 49.8077 64.9877 +e6 21.8467 38.7535 78.4805 +e7 10.7682 25.583 89.0865 +e8 -1.3975 8.9851 93.8693 +e9 -13.1647 -12.1274 96.6725 +e10 61.5573 53.2255 -4.7359 +e11 52.3 61.959 14.8732 +e12 39.6349 67.3205 36.0606 +e13 26.2733 65.6068 54.4194 +e14 11.9321 55.9521 70.1803 +e15 -0.8647 42.1566 81.1926 +e16 -13.1036 25.6825 88.3434 +e17 -24.4005 2.363 90.7837 +e18 42.5764 73.1806 2.2186 +e19 30.0226 78.2286 19.6983 +e20 14.8743 77.5092 39.2769 +e21 0.0176 69.804 56.5523 +e22 -12.8364 56.0554 69.4094 +e23 -23.3909 38.9421 77.0724 +e24 -34.6222 17.9589 82.5333 +e25 15.7138 85.6183 4.9794 +e26 1.1949 85.0222 20.7678 +e27 -13.6712 77.6282 38.3884 +e28 -26.0887 65.8251 52.7895 +e29 -36.635 50.1107 62.7252 +e30 -45.7434 30.7668 69.0533 +e31 2.1536 85.6989 -9.9396 +e32 -12.3084 85.7351 4.1072 +e33 -27.566 78.4686 17.9057 +e34 -38.2678 67.6453 33.6356 +e35 -48.0048 54.3029 43.9089 +e36 -51.3387 39.991 54.2574 +e37 -39.0499 73.5208 -0.3222 +e38 -49.635 62.3839 11.7002 +e39 -56.3535 49.8542 24.642 +e40 -61.574 37.9399 38.8814 +e41 -60.531 25.1736 53.8308 +e42 -54.2404 12.8149 68.0377 +e43 -47.6294 -0.2957 79.3179 +e44 -36.8835 -16.002 88.3827 +e45 -21.6855 -33.4393 95.957 +e46 -57.7271 53.7227 -8.449 +e47 -63.6424 43.0561 4.537 +e48 -69.0538 31.6015 18.2175 +e49 -70.8422 19.3762 33.6133 +e50 -69.0879 7.4547 51.5356 +e51 -62.0285 -5.7442 65.7286 +e52 -54.4197 -20.0184 77.6474 +e53 -38.8374 -38.2922 88.0442 +e54 -67.82 34.1346 -16.8098 +e55 -71.8924 23.0121 -1.7381 +e56 -75.928 11.1946 14.0571 +e57 -76.11 0.0998 31.2115 +e58 -74.0971 -10.6531 48.5772 +e59 -67.9854 -24.5887 64.362 +e60 -55.3657 -42.1938 76.0642 +e61 -73.5787 11.0171 -21.7665 +e62 -76.4444 0.0144 -5.3127 +e63 -79.0176 -9.6877 11.9231 +e64 -80.5793 -18.9186 29.54 +e65 -76.5672 -29.8091 47.2408 +e66 -69.0629 -44.4906 59.9509 +e67 -74.6126 -1.082 -39.3048 +e68 -75.6833 -9.0589 -22.6141 +e69 -78.1137 -19.8358 -8.2611 +e70 -79.2173 -29.2484 9.3539 +e71 -80.5478 -37.9958 28.1492 +e72 -76.0784 -47.0968 43.1782 +e73 -72.4016 -10.0791 -57.7182 +e74 -76.4617 -39.0533 -8.9971 +e75 -77.3728 -49.2668 10.745 +e76 -74.6521 -58.0939 28.9923 +e77 -69.3177 -62.3691 48.3714 +e78 -57.6157 -63.9704 65.0226 +e79 -42.717 -61.9566 80.0486 +e80 -24.0512 -56.7381 90.7393 +e81 -1.7418 -46.9478 97.4385 +e82 -67.9915 -21.4725 -72.2903 +e83 -72.204 -54.8711 -22.5174 +e84 -74.1656 -57.9639 -5.9659 +e85 -71.1152 -69.4042 13.8673 +e86 -65.0735 -75.1549 33.3834 +e87 -56.1031 -79.5268 53.8203 +e88 -41.599 -78.3258 69.887 +e89 -24.4773 -75.5716 82.9624 +e90 -1.6459 -64.7557 91.9748 +e91 -64.5643 -34.3896 -86.5432 +e92 -64.3411 -45.4959 -67.6343 +e93 -65.3458 -58.3165 -51.061 +e94 -68.3241 -63.5803 -36.6986 +e95 -68.4279 -70.3117 -20.4031 +e96 -65.909 -78.7986 -0.8173 +e97 -59.4331 -88 18.2447 +e98 -51.3943 -91.4482 37.2956 +e99 -38.3171 -91.8728 54.9586 +e100 -22.6743 -89.0141 70.5083 +e101 -1.0686 -97.6091 69.0286 +e102 -60.1829 -54.3722 -82.7602 +e103 -59.4692 -63.4617 -66.0936 +e104 -58.5943 -74.531 -48.4668 +e105 -61.23 -79.4547 -34.5644 +e106 -58.5144 -88.0093 -16.3299 +e107 -51.6195 -97.5152 2.1098 +e108 -42.7354 -104.1792 21.2829 +e109 -32.7893 -105.7871 39.9809 +e110 -18.0708 -101.6289 55.5438 +e111 -52.9998 -74.5331 -79.2039 +e112 -51.0153 -82.0458 -63.6896 +e113 -48.5595 -91.9992 -45.6554 +e114 -50.9249 -94.3075 -31.3117 +e115 -40.1136 -107.0107 -13.3504 +e116 -30.6411 -113.4896 5.3057 +e117 -19.2803 -115.6653 23.6772 +e118 -11.193 -111.7214 39.4554 +e119 -0.5817 -106.0184 52.2625 +e120 -43.765 -88.9071 -77.6195 +e121 -39.2687 -95.9321 -60.9462 +e122 -34.0109 -104.9387 -43.2126 +e123 -28.7093 -114.9108 -22.7014 +e124 -20.8409 -118.3467 -9.3604 +e125 -9.447 -119.4818 6.9597 +e126 0.2721 -115.6783 23.5385 +e127 10.7577 -111.8129 40.1387 +e128 16.7053 -101.7739 56.6263 +e129 20.4741 -89.194 71.8515 +e130 21.611 -75.7637 84.397 +e131 20.8589 -56.9253 92.1373 +e132 18.3673 -33.6063 97.2038 +e133 -31.4671 -102.9747 -71.0456 +e134 -24.436 -107.5564 -58.2978 +e135 -18.2514 -115.0888 -37.3942 +e136 -7.4658 -116.582 -24.6694 +e137 1.3442 -117.0396 -11.086 +e138 10.9715 -119.5669 7.5953 +e139 19.7775 -115.8281 24.8929 +e140 32.3281 -106.0586 42.0079 +e141 37.0294 -92.1868 57.304 +e142 39.4892 -78.6638 72.4111 +e143 40.1093 -62.3018 82.6268 +e144 35.9371 -38.6039 90.3718 +e145 -15.7174 -109.5457 -70.6892 +e146 -7.872 -113.5766 -57.1472 +e147 2.2762 -114.1391 -40.6387 +e148 10.9855 -116.6589 -24.0951 +e149 23.3674 -118.531 -7.9843 +e150 32.2767 -113.7518 7.2642 +e151 43.431 -104.5384 23.9651 +e152 51.1829 -91.8757 40.4886 +e153 54.954 -79.9897 57.2773 +e154 55.8964 -64.4435 68.556 +e155 53.1454 -42.6461 79.4419 +e156 13.4359 -113.6654 -56.484 +e157 22.5538 -115.2589 -36.124 +e158 32.0787 -115.1642 -20.8092 +e159 42.9447 -107.3569 -10.765 +e160 53.5455 -97.9536 5.3834 +e161 60.4194 -88.4996 21.9754 +e162 65.2142 -75.6979 37.4389 +e163 68.6243 -62.9441 52.6652 +e164 67.7987 -45.061 64.2111 +e165 22.1416 -109.7035 -69.5108 +e166 30.089 -107.7837 -56.6006 +e167 38.7286 -105.2419 -40.9484 +e168 54.9576 -94.7488 -28.0158 +e169 61.6528 -88.5102 -12.5894 +e170 68.1447 -79.3574 3.3555 +e171 72.5056 -70.0028 18.3378 +e172 75.1891 -58.7185 33.6565 +e173 75.8219 -47.7299 47.9065 +e174 37.9372 -103.264 -68.8852 +e175 45.154 -96.284 -58.3183 +e176 53.5082 -92.4246 -42.4783 +e177 65.5684 -79.9832 -30.6174 +e178 71.9475 -70.8968 -16.0335 +e179 76.8788 -58.5935 -1.2642 +e180 79.1128 -49.9191 15.616 +e181 81.2929 -38.6704 33.1869 +e182 76.201 -30.4459 51.9961 +e183 66.6147 -25.1498 68.5518 +e184 52.2875 -20.4631 80.9689 +e185 34.1516 -16.2981 90.5939 +e186 9.9963 -12.224 97.3934 +e187 50.7369 -89.301 -74.6779 +e188 57.1637 -82.4967 -60.3223 +e189 63.8436 -75.0413 -44.6556 +e190 72.9135 -64.169 -32.3022 +e191 75.9763 -55.4887 -17.9049 +e192 79.5164 -39.7034 -4.1418 +e193 81.2069 -29.9171 14.3475 +e194 81.3968 -19.5937 34.5819 +e195 73.8122 -11.2696 53.1813 +e196 60.7415 -6.2559 69.5501 +e197 45.571 -0.6841 82.219 +e198 21.6968 2.1709 92.2186 +e199 60.1717 -75.0049 -75.6812 +e200 65.9052 -63.9843 -62.191 +e201 70.8782 -58.8843 -46.8206 +e202 81.2794 -20.5001 -3.2995 +e203 81.0107 -10.3548 16.9044 +e204 76.9907 -0.5383 35.9771 +e205 68.7797 6.88 55.8271 +e206 52.9797 12.368 71.3752 +e207 32.5415 17.679 84.624 +e208 67.7297 -54.9054 -78.7786 +e209 71.013 -46.0601 -63.4211 +e210 79.8362 -9.7071 -17.7731 +e211 79.5953 -0.636 -0.4555 +e212 77.9684 10.5531 18.8475 +e213 71.7444 18.7819 38.0517 +e214 60.2444 24.6702 57.5903 +e215 44.5857 30.3903 71.8651 +e216 72.5043 -34.9609 -82.2766 +e217 75.1458 -22.0691 -67.8347 +e218 78.7358 -10.7091 -53.0137 +e219 79.8721 -1.7259 -34.4961 +e220 77.8503 10.3859 -17.0529 +e221 75.0215 22.3998 2.835 +e222 71.0189 31.0176 22.5777 +e223 62.3214 37.4235 42.7379 +e224 51.1671 39.5637 57.4482 +e225 79.3065 13.5308 -35.7965 +e226 75.6101 29.353 -38.6076 +e227 79.1695 7.4866 -54.9622 +e228 77.8761 -3.2226 -71.591 +e229 73.0385 -17.4029 -85.7303 +e230 70.9309 41.9734 -48.6336 +e231 76.0721 24.1555 -60.2421 +e232 77.4399 15.5937 -76.3863 +e233 75.5783 1.1137 -90.7508 +e234 62.6075 54.8537 -55.2766 +e235 70.6713 39.625 -67.1663 +e236 72.0051 30.3047 -81.5461 +e237 70.6903 18.2789 -96.1096 +e238 50.6947 65.0832 -57.3711 +e239 62.5078 48.1113 -76.8843 +e240 65.1617 38.3127 -89.1377 +e241 -43.5136 65.4759 -60.3036 +e242 -54.2312 48.5979 -80.5181 +e243 -56.1993 38.8186 -92.9154 +e244 -55.6183 55.3465 -58.9567 +e245 -63.0536 40.1823 -71.3288 +e246 -63.5681 30.8697 -85.7661 +e247 -61.4503 18.8297 -100.2228 +e248 -64.4457 42.5377 -52.8475 +e249 -69.0033 24.7602 -64.7579 +e250 -69.4356 16.2059 -80.9582 +e251 -66.8049 1.7071 -95.1828 +e252 -69.8444 29.9592 -43.1352 +e253 -73.8402 14.1691 -40.5636 +e254 -72.5617 8.119 -59.6852 +e255 -70.3259 -2.6048 -76.2042 +e256 -64.7365 -16.8286 -90.0189 diff --git a/EEGtemplates/egi32.sfp b/EEGtemplates/egi32.sfp index 48fdd1d..3a6acfd 100644 --- a/EEGtemplates/egi32.sfp +++ b/EEGtemplates/egi32.sfp @@ -1,35 +1,35 @@ -spmnas 1 85 -41 -spmlpa -83 -20 -65 -spmrpa 83 -20 -65 -e1 -36.1179 82.0141 5.8289 -e2 26.9276 84.3237 7.3029 -e3 -56.3314 45.0214 41.1443 -e4 50.3298 51.093 45.5897 -e5 -68.8578 -25.1822 61.826 -e6 65.7271 -20.6282 66.0259 -e7 -67.7307 -78.8166 38.4086 -e8 68.6621 -73.82 41.5974 -e9 -28.5893 -121.3041 -19.3765 -e10 35.4722 -118.9573 -17.8788 -e11 -78.3611 26.6871 -16.5027 -e12 78.2923 34.1196 -13.6809 -e13 -85.0663 -43.9918 -24.949 -e14 86.0769 -37.6007 -20.8795 -e15 -68.3669 -89.2804 -19.9737 -e16 72.7858 -84.1094 -16.6737 -e17 -5.2155 70.0155 52.7602 -e18 -3.9746 90.5907 -31.6061 -e19 1.0795 -103.1033 55.7167 -e20 3.5557 -124.8847 -16.0663 -e21 -76.4139 10.5368 -74.8799 -e22 77.9195 16.5157 -73.0533 -e23 -70.1153 -45.8477 -83.5246 -e24 76.3493 -41.6655 -82.3393 -e25 -41.2035 -92.7569 -83.3572 -e26 48.4978 -88.7425 -80.6023 -e27 -4.8469 87.151 9.8091 -e28 -4.3863 19.8667 90.3553 -e29 -45.5424 62.2181 -85.3211 -e30 42.0182 65.4257 -83.274 -e31 -74.8651 35.4777 -64.7962 -e32 70.2349 39.7777 -59.7287 +spmnas 1 85 -41 +spmlpa -83 -20 -65 +spmrpa 83 -20 -65 +e1 -36.1179 82.0141 5.8289 +e2 26.9276 84.3237 7.3029 +e3 -56.3314 45.0214 41.1443 +e4 50.3298 51.093 45.5897 +e5 -68.8578 -25.1822 61.826 +e6 65.7271 -20.6282 66.0259 +e7 -67.7307 -78.8166 38.4086 +e8 68.6621 -73.82 41.5974 +e9 -28.5893 -121.3041 -19.3765 +e10 35.4722 -118.9573 -17.8788 +e11 -78.3611 26.6871 -16.5027 +e12 78.2923 34.1196 -13.6809 +e13 -85.0663 -43.9918 -24.949 +e14 86.0769 -37.6007 -20.8795 +e15 -68.3669 -89.2804 -19.9737 +e16 72.7858 -84.1094 -16.6737 +e17 -5.2155 70.0155 52.7602 +e18 -3.9746 90.5907 -31.6061 +e19 1.0795 -103.1033 55.7167 +e20 3.5557 -124.8847 -16.0663 +e21 -76.4139 10.5368 -74.8799 +e22 77.9195 16.5157 -73.0533 +e23 -70.1153 -45.8477 -83.5246 +e24 76.3493 -41.6655 -82.3393 +e25 -41.2035 -92.7569 -83.3572 +e26 48.4978 -88.7425 -80.6023 +e27 -4.8469 87.151 9.8091 +e28 -4.3863 19.8667 90.3553 +e29 -45.5424 62.2181 -85.3211 +e30 42.0182 65.4257 -83.274 +e31 -74.8651 35.4777 -64.7962 +e32 70.2349 39.7777 -59.7287 diff --git a/EEGtemplates/egi64_GSN_HydroCel_v1_0.sfp b/EEGtemplates/egi64_GSN_HydroCel_v1_0.sfp index 414634c..0d33126 100644 --- a/EEGtemplates/egi64_GSN_HydroCel_v1_0.sfp +++ b/EEGtemplates/egi64_GSN_HydroCel_v1_0.sfp @@ -1,67 +1,67 @@ -spmnas 1 85 -41 -spmlpa -83 -20 -65 -spmrpa 83 -20 -65 -e1 68.5906 48.6073 -37.5117 -e2 46.0261 63.8596 33.7454 -e3 34.5545 54.5356 56.0385 -e4 1.4443 9.0167 85.5752 -e5 31.2079 81.7591 12.4047 -e6 -0.2208 63.3768 58.5488 -e7 -27.8277 2.1992 81.6885 -e8 -0.9099 79.9103 37.2617 -e9 -34.5952 52.8992 57.007 -e10 -33.7614 80.2216 13.3147 -e11 -47.1137 61.6555 35.0499 -e12 -53.6017 40.0645 47.9406 -e13 -68.5116 35.4908 28.9458 -e14 -66.1684 17.0747 48.1362 -e15 -55.9907 -2.9176 65.4973 -e16 -42.4099 -25.5733 78.2886 -e17 -70.914 45.306 -35.5579 -e18 -77.4629 24.7888 -11.2772 -e19 -81.7076 6.1819 20.1259 -e20 -63.988 -32.0669 62.6018 -e21 -44.3231 -55.4585 75.8015 -e22 -81.2598 -42.4581 39.7354 -e23 -82.7074 -4.0013 -54.1566 -e24 -86.879 -46.5569 -24.4087 -e25 -86.2396 -56.7529 10.8567 -e26 -78.7522 -68.0965 30.9721 -e27 -76.4574 -85.4182 11.1183 -e28 -67.2875 -86.8374 37.6121 -e29 -78.1533 -64.7678 -55.864 -e30 -70.4258 -93.7599 -23.0039 -e31 -46.136 -105.7354 39.5996 -e32 -63.4033 -90.0323 -58.4423 -e33 -18.4449 -120.283 35.3594 -e34 3.6117 -88.9242 74.7464 -e35 -29.9259 -127.1785 -26.0962 -e36 3.799 -124.5369 27.8486 -e37 3.2343 -131.4524 -24.2415 -e38 26.018 -119.2308 34.7367 -e39 36.0903 -125.6162 -27.0208 -e40 53.0974 -103.3871 38.2097 -e41 49.9201 -53.2283 74.4815 -e42 73.2672 -83.5113 35.6435 -e43 66.8555 -86.9498 -60.2667 -e44 75.0342 -90.3176 -25.0412 -e45 81.6156 -81.6774 8.9043 -e46 83.6422 -64.2535 28.6976 -e47 80.4598 -61.0143 -58.0855 -e48 90.0194 -52.5818 8.388 -e49 85.1778 -38.5194 37.4043 -e50 68.0795 -28.9415 60.752 -e51 46.6652 -23.4654 77.0411 -e52 89.1898 -42.3903 -26.8747 -e53 58.796 -0.2013 63.8896 -e54 30.8859 3.5886 80.8661 -e55 82.1795 -0.0993 -56.4659 -e56 82.7754 10.0743 17.8221 -e57 67.5271 20.2386 46.2637 -e58 76.779 28.4389 -13.4375 -e59 68.459 38.7322 27.0274 -e60 53.8862 42.6081 46.4351 -e61 72.4574 39.8592 -61.104 -e62 42.8459 68.0927 -82.4673 -e63 -47.3866 65.9574 -81.2035 -e64 -75.0203 36.3692 -59.0385 +spmnas 1 85 -41 +spmlpa -83 -20 -65 +spmrpa 83 -20 -65 +e1 68.5906 48.6073 -37.5117 +e2 46.0261 63.8596 33.7454 +e3 34.5545 54.5356 56.0385 +e4 1.4443 9.0167 85.5752 +e5 31.2079 81.7591 12.4047 +e6 -0.2208 63.3768 58.5488 +e7 -27.8277 2.1992 81.6885 +e8 -0.9099 79.9103 37.2617 +e9 -34.5952 52.8992 57.007 +e10 -33.7614 80.2216 13.3147 +e11 -47.1137 61.6555 35.0499 +e12 -53.6017 40.0645 47.9406 +e13 -68.5116 35.4908 28.9458 +e14 -66.1684 17.0747 48.1362 +e15 -55.9907 -2.9176 65.4973 +e16 -42.4099 -25.5733 78.2886 +e17 -70.914 45.306 -35.5579 +e18 -77.4629 24.7888 -11.2772 +e19 -81.7076 6.1819 20.1259 +e20 -63.988 -32.0669 62.6018 +e21 -44.3231 -55.4585 75.8015 +e22 -81.2598 -42.4581 39.7354 +e23 -82.7074 -4.0013 -54.1566 +e24 -86.879 -46.5569 -24.4087 +e25 -86.2396 -56.7529 10.8567 +e26 -78.7522 -68.0965 30.9721 +e27 -76.4574 -85.4182 11.1183 +e28 -67.2875 -86.8374 37.6121 +e29 -78.1533 -64.7678 -55.864 +e30 -70.4258 -93.7599 -23.0039 +e31 -46.136 -105.7354 39.5996 +e32 -63.4033 -90.0323 -58.4423 +e33 -18.4449 -120.283 35.3594 +e34 3.6117 -88.9242 74.7464 +e35 -29.9259 -127.1785 -26.0962 +e36 3.799 -124.5369 27.8486 +e37 3.2343 -131.4524 -24.2415 +e38 26.018 -119.2308 34.7367 +e39 36.0903 -125.6162 -27.0208 +e40 53.0974 -103.3871 38.2097 +e41 49.9201 -53.2283 74.4815 +e42 73.2672 -83.5113 35.6435 +e43 66.8555 -86.9498 -60.2667 +e44 75.0342 -90.3176 -25.0412 +e45 81.6156 -81.6774 8.9043 +e46 83.6422 -64.2535 28.6976 +e47 80.4598 -61.0143 -58.0855 +e48 90.0194 -52.5818 8.388 +e49 85.1778 -38.5194 37.4043 +e50 68.0795 -28.9415 60.752 +e51 46.6652 -23.4654 77.0411 +e52 89.1898 -42.3903 -26.8747 +e53 58.796 -0.2013 63.8896 +e54 30.8859 3.5886 80.8661 +e55 82.1795 -0.0993 -56.4659 +e56 82.7754 10.0743 17.8221 +e57 67.5271 20.2386 46.2637 +e58 76.779 28.4389 -13.4375 +e59 68.459 38.7322 27.0274 +e60 53.8862 42.6081 46.4351 +e61 72.4574 39.8592 -61.104 +e62 42.8459 68.0927 -82.4673 +e63 -47.3866 65.9574 -81.2035 +e64 -75.0203 36.3692 -59.0385 diff --git a/EEGtemplates/egi64_GSN_v1_0.sfp b/EEGtemplates/egi64_GSN_v1_0.sfp index affeab8..1a4acaf 100644 --- a/EEGtemplates/egi64_GSN_v1_0.sfp +++ b/EEGtemplates/egi64_GSN_v1_0.sfp @@ -1,67 +1,67 @@ -spmnas 1 85 -41 -spmlpa -83 -20 -65 -spmrpa 83 -20 -65 -e1 46.8606 78.9276 -6.5954 -e2 37.304 75.7964 35.6438 -e3 21.6096 56.6606 66.0984 -e4 -0.5145 31.9637 82.738 -e5 -18.1259 -4.3764 87.2468 -e6 1.1439 91.0605 -27.9644 -e7 0.5681 93.3886 10.6806 -e8 0.0471 82.8412 45.5304 -e9 -22.126 56.6665 65.4465 -e10 -36.3397 26.1709 72.283 -e11 -45.1927 78.9401 -7.9675 -e12 -36.9004 75.8065 34.5377 -e13 -52.9114 48.0976 43.9995 -e14 -67.3488 45.4054 11.2803 -e15 -70.4938 17.4539 36.4852 -e16 -56.9631 -14.8227 65.9902 -e17 -33.539 -42.2035 80.4834 -e18 -69.0735 31.5272 -27.5846 -e19 -80.1939 3.7704 2.0407 -e20 -79.7573 -18.9484 29.8622 -e21 -67.1664 -52.4395 57.8125 -e22 -72.6864 10.1646 -60.409 -e23 -79.6192 -12.9141 -32.9508 -e24 -86.1729 -33.8403 0.9913 -e25 -82.3604 -54.0371 24.2507 -e26 -79.3433 -73.3883 -9.5253 -e27 -65.62 -90.6777 31.4284 -e28 -40.7116 -87.8804 62.0892 -e29 -0.4976 -73.8719 80.6335 -e30 -66.0561 -70.5058 -76.8333 -e31 -67.9655 -87.4206 -43.7078 -e32 -59.8629 -110.4035 -5.2083 -e33 -35.4059 -116.1704 29.1424 -e34 -0.1224 -110.2171 55.1365 -e35 -35.8618 -125.011 -43.878 -e36 -22.2994 -135.0631 -7.0329 -e37 0.3667 -129.3749 22.1508 -e38 1.4408 -132.3752 -49.9242 -e39 23.8912 -135.0693 -6.3444 -e40 35.9187 -116.1801 30.2056 -e41 40.2476 -87.8914 63.296 -e42 32.5423 -42.2125 81.4683 -e43 38.5486 -125.0211 -42.7689 -e44 61.3903 -110.42 -3.4009 -e45 66.0581 -90.6956 33.3912 -e46 66.8278 -52.4577 59.8097 -e47 70.6432 -87.4395 -41.6418 -e48 81.0009 -73.4101 -7.1353 -e49 83.015 -54.0596 26.7157 -e50 69.7267 -70.5243 -74.8094 -e51 87.5247 -33.8639 3.5803 -e52 80.2554 -18.9701 32.2473 -e53 56.3955 -14.8381 67.6798 -e54 16.9447 -4.3811 87.7695 -e55 81.9914 -12.936 -30.542 -e56 81.5273 3.7485 4.4513 -e57 70.8085 17.4347 38.5913 -e58 35.6049 26.1611 73.3554 -e59 75.8865 10.1444 -58.1944 -e60 71.3025 31.5081 -25.4922 -e61 68.4239 45.387 13.3041 -e62 53.0183 48.0832 45.5784 -e63 44.8303 66.7561 -71.7549 -e64 -41.2244 66.7678 -73.0376 +spmnas 1 85 -41 +spmlpa -83 -20 -65 +spmrpa 83 -20 -65 +e1 46.8606 78.9276 -6.5954 +e2 37.304 75.7964 35.6438 +e3 21.6096 56.6606 66.0984 +e4 -0.5145 31.9637 82.738 +e5 -18.1259 -4.3764 87.2468 +e6 1.1439 91.0605 -27.9644 +e7 0.5681 93.3886 10.6806 +e8 0.0471 82.8412 45.5304 +e9 -22.126 56.6665 65.4465 +e10 -36.3397 26.1709 72.283 +e11 -45.1927 78.9401 -7.9675 +e12 -36.9004 75.8065 34.5377 +e13 -52.9114 48.0976 43.9995 +e14 -67.3488 45.4054 11.2803 +e15 -70.4938 17.4539 36.4852 +e16 -56.9631 -14.8227 65.9902 +e17 -33.539 -42.2035 80.4834 +e18 -69.0735 31.5272 -27.5846 +e19 -80.1939 3.7704 2.0407 +e20 -79.7573 -18.9484 29.8622 +e21 -67.1664 -52.4395 57.8125 +e22 -72.6864 10.1646 -60.409 +e23 -79.6192 -12.9141 -32.9508 +e24 -86.1729 -33.8403 0.9913 +e25 -82.3604 -54.0371 24.2507 +e26 -79.3433 -73.3883 -9.5253 +e27 -65.62 -90.6777 31.4284 +e28 -40.7116 -87.8804 62.0892 +e29 -0.4976 -73.8719 80.6335 +e30 -66.0561 -70.5058 -76.8333 +e31 -67.9655 -87.4206 -43.7078 +e32 -59.8629 -110.4035 -5.2083 +e33 -35.4059 -116.1704 29.1424 +e34 -0.1224 -110.2171 55.1365 +e35 -35.8618 -125.011 -43.878 +e36 -22.2994 -135.0631 -7.0329 +e37 0.3667 -129.3749 22.1508 +e38 1.4408 -132.3752 -49.9242 +e39 23.8912 -135.0693 -6.3444 +e40 35.9187 -116.1801 30.2056 +e41 40.2476 -87.8914 63.296 +e42 32.5423 -42.2125 81.4683 +e43 38.5486 -125.0211 -42.7689 +e44 61.3903 -110.42 -3.4009 +e45 66.0581 -90.6956 33.3912 +e46 66.8278 -52.4577 59.8097 +e47 70.6432 -87.4395 -41.6418 +e48 81.0009 -73.4101 -7.1353 +e49 83.015 -54.0596 26.7157 +e50 69.7267 -70.5243 -74.8094 +e51 87.5247 -33.8639 3.5803 +e52 80.2554 -18.9701 32.2473 +e53 56.3955 -14.8381 67.6798 +e54 16.9447 -4.3811 87.7695 +e55 81.9914 -12.936 -30.542 +e56 81.5273 3.7485 4.4513 +e57 70.8085 17.4347 38.5913 +e58 35.6049 26.1611 73.3554 +e59 75.8865 10.1444 -58.1944 +e60 71.3025 31.5081 -25.4922 +e61 68.4239 45.387 13.3041 +e62 53.0183 48.0832 45.5784 +e63 44.8303 66.7561 -71.7549 +e64 -41.2244 66.7678 -73.0376 diff --git a/EEGtemplates/egi64_GSN_v2_0.sfp b/EEGtemplates/egi64_GSN_v2_0.sfp index 757bbb8..481fde9 100644 --- a/EEGtemplates/egi64_GSN_v2_0.sfp +++ b/EEGtemplates/egi64_GSN_v2_0.sfp @@ -1,67 +1,67 @@ -spmnas 1 85 -41 -spmlpa -83 -20 -65 -spmrpa 83 -20 -65 -e1 55.3459 70.4967 -6.951 -e2 40.2962 74.7109 27.878 -e3 23.2854 55.8323 65.5038 -e4 2.025 27.0789 83.8932 -e5 -17.4443 -3.9658 85.8937 -e6 19.0794 93.1408 1.7385 -e7 1.535 83.3324 41.08 -e8 -19.6453 55.8519 66.0249 -e9 -37.0219 24.1791 73.2026 -e10 0.7704 91.4233 -22.3104 -e11 -16.9481 93.1572 2.1758 -e12 -37.5439 74.7465 28.8228 -e13 -52.2933 46.8042 45.0351 -e14 -53.4382 70.5464 -5.6305 -e15 -67.495 43.018 11.0001 -e16 -69.6467 13.3724 38.8428 -e17 -57.8962 -15.6549 63.9432 -e18 -30.7142 -48.4362 78.4877 -e19 -72.6453 30.5213 -29.3654 -e20 -80.8802 3.7689 0.6584 -e21 -81.5758 -24.1637 24.5254 -e22 -65.423 -57.055 53.3553 -e23 -75.4618 6.0566 -68.1931 -e24 -85.4143 -38.2692 -9.5794 -e25 -80.5887 -59.5398 16.1157 -e26 -79.2786 -58.9127 -44.9053 -e27 -75.8265 -76.4809 -18.271 -e28 -66.3413 -91.9934 16.7612 -e29 -36.5819 -96.0694 53.2265 -e30 1.8688 -77.1821 75.4731 -e31 -63.39 -90.0695 -56.5428 -e32 -54.4058 -110.8195 -22.4274 -e33 -34.6122 -118.7477 16.2084 -e34 1.5113 -110.1051 47.4013 -e35 -48.3546 -94.6965 -89.2098 -e36 -34.5593 -118.4169 -59.2149 -e37 -19.6623 -130.6042 -23.245 -e38 1.0315 -128.1188 8.611 -e39 0.1533 -124.1363 -63.9753 -e40 20.944 -130.6228 -23.7379 -e41 36.8586 -118.7804 15.3409 -e42 39.749 -96.1043 52.2999 -e43 34.5451 -48.4659 77.6956 -e44 34.977 -118.4486 -60.059 -e45 55.7176 -110.8698 -23.7641 -e46 68.6195 -92.055 15.123 -e47 68.6252 -57.1162 51.7281 -e48 63.8935 -90.1276 -58.0878 -e49 77.2685 -76.5508 -20.1294 -e50 82.8808 -59.6144 14.1315 -e51 80.0919 -58.9854 -46.8399 -e52 87.1039 -38.3479 -11.6735 -e53 84.1083 -24.2393 22.5142 -e54 61.4004 -15.7093 62.4952 -e55 21.5048 -3.9836 85.4209 -e56 82.863 3.6942 -1.3292 -e57 72.5688 13.3075 37.1165 -e58 40.7982 24.1436 72.2579 -e59 75.7789 5.9876 -70.0289 -e60 73.9302 30.4544 -31.1446 -e61 69.7733 42.9554 9.3339 -e62 55.4054 46.7551 43.7278 -e63 43.1232 70.059 -85.993 -e64 -43.1364 70.0984 -84.9459 +spmnas 1 85 -41 +spmlpa -83 -20 -65 +spmrpa 83 -20 -65 +e1 55.3459 70.4967 -6.951 +e2 40.2962 74.7109 27.878 +e3 23.2854 55.8323 65.5038 +e4 2.025 27.0789 83.8932 +e5 -17.4443 -3.9658 85.8937 +e6 19.0794 93.1408 1.7385 +e7 1.535 83.3324 41.08 +e8 -19.6453 55.8519 66.0249 +e9 -37.0219 24.1791 73.2026 +e10 0.7704 91.4233 -22.3104 +e11 -16.9481 93.1572 2.1758 +e12 -37.5439 74.7465 28.8228 +e13 -52.2933 46.8042 45.0351 +e14 -53.4382 70.5464 -5.6305 +e15 -67.495 43.018 11.0001 +e16 -69.6467 13.3724 38.8428 +e17 -57.8962 -15.6549 63.9432 +e18 -30.7142 -48.4362 78.4877 +e19 -72.6453 30.5213 -29.3654 +e20 -80.8802 3.7689 0.6584 +e21 -81.5758 -24.1637 24.5254 +e22 -65.423 -57.055 53.3553 +e23 -75.4618 6.0566 -68.1931 +e24 -85.4143 -38.2692 -9.5794 +e25 -80.5887 -59.5398 16.1157 +e26 -79.2786 -58.9127 -44.9053 +e27 -75.8265 -76.4809 -18.271 +e28 -66.3413 -91.9934 16.7612 +e29 -36.5819 -96.0694 53.2265 +e30 1.8688 -77.1821 75.4731 +e31 -63.39 -90.0695 -56.5428 +e32 -54.4058 -110.8195 -22.4274 +e33 -34.6122 -118.7477 16.2084 +e34 1.5113 -110.1051 47.4013 +e35 -48.3546 -94.6965 -89.2098 +e36 -34.5593 -118.4169 -59.2149 +e37 -19.6623 -130.6042 -23.245 +e38 1.0315 -128.1188 8.611 +e39 0.1533 -124.1363 -63.9753 +e40 20.944 -130.6228 -23.7379 +e41 36.8586 -118.7804 15.3409 +e42 39.749 -96.1043 52.2999 +e43 34.5451 -48.4659 77.6956 +e44 34.977 -118.4486 -60.059 +e45 55.7176 -110.8698 -23.7641 +e46 68.6195 -92.055 15.123 +e47 68.6252 -57.1162 51.7281 +e48 63.8935 -90.1276 -58.0878 +e49 77.2685 -76.5508 -20.1294 +e50 82.8808 -59.6144 14.1315 +e51 80.0919 -58.9854 -46.8399 +e52 87.1039 -38.3479 -11.6735 +e53 84.1083 -24.2393 22.5142 +e54 61.4004 -15.7093 62.4952 +e55 21.5048 -3.9836 85.4209 +e56 82.863 3.6942 -1.3292 +e57 72.5688 13.3075 37.1165 +e58 40.7982 24.1436 72.2579 +e59 75.7789 5.9876 -70.0289 +e60 73.9302 30.4544 -31.1446 +e61 69.7733 42.9554 9.3339 +e62 55.4054 46.7551 43.7278 +e63 43.1232 70.059 -85.993 +e64 -43.1364 70.0984 -84.9459 diff --git a/EEGtemplates/ext1020.sfp b/EEGtemplates/ext1020.sfp index 776a20d..4947d75 100644 --- a/EEGtemplates/ext1020.sfp +++ b/EEGtemplates/ext1020.sfp @@ -1,346 +1,346 @@ -spmnas 1 85 -41 -spmlpa -83 -20 -65 -spmrpa 83 -20 -65 -Fp1 -29.2644 82.1011 -0.1681 -Fpz 0.5966 85.4186 5.2724 -Fp2 30.3458 82.3208 -2.5084 -AF9 -50.0686 67.3263 -48.1825 -AF7 -54.9914 67.5738 -5.8804 -AF5 -45.0839 69.805 12.933 -AF3 -32.8795 71.8452 30.1284 -AF1 -17.2597 73.3677 42.8765 -AFz 1.6107 73.6809 45.2343 -AF2 21.227 73.2684 41.4016 -AF4 36.9056 71.7503 28.2715 -AF6 47.3996 69.5529 9.4173 -AF8 56.1483 67.2462 -10.3733 -AF10 49.8252 65.8653 -52.6275 -F9 -71.517 45.5339 -53.8552 -F7 -70.6916 41.8958 -10.8395 -F5 -64.1055 44.0763 21.4442 -F3 -49.1339 46.0206 49.8831 -F1 -25.7835 47.4288 69.8291 -Fz 2.3304 47.9355 75.787 -F2 31.496 47.454 66.7353 -F4 53.4301 46.0515 44.4067 -F6 68.9352 44.219 15.7579 -F8 73.3302 42.0529 -16.9723 -F10 71.4009 44.1701 -60.1286 -FT9 -85.7586 18.814 -58.6571 -FT7 -81.4433 13.7802 -15.1615 -FC5 -76.9277 14.1172 25.097 -FC3 -58.9898 14.3544 59.7085 -FC1 -32.0939 14.4686 86.4236 -FCz 2.747 14.3924 94.9242 -FC2 37.0696 14.142 82.3849 -FC4 64.1073 13.7668 54.9967 -FC6 80.6141 13.3845 18.9204 -FT8 81.9645 12.9962 -21.7677 -FT10 83.2681 16.456 -65.6635 -T9 -87.7394 -11.6613 -61.6278 -T7 -85.0072 -16.3778 -18.4196 -C5 -80.1105 -18.6349 24.6594 -C3 -64.2027 -20.782 63.5856 -C1 -34.1983 -22.4568 90.9388 -Cz 2.8165 -23.3292 101.2672 -C2 39.9696 -22.8958 86.5061 -C4 68.9216 -21.6725 57.4563 -C6 84.453 -19.7733 18.2209 -T8 85.084 -17.5501 -25.2931 -T10 84.5694 -14.4038 -68.6915 -TP9 -87.6077 -42.502 -64.2573 -TP7 -85.8268 -46.4935 -21.2067 -CP5 -79.5982 -51.4848 20.7615 -CP3 -62.6018 -56.1594 58.5984 -CP1 -33.7659 -59.7753 85.984 -CPz 2.5193 -61.2034 93.5467 -CP2 40.4866 -60.4388 82.3243 -CP4 68.2191 -57.4632 53.3152 -CP6 84.1409 -53.1682 14.4935 -TP8 85.4063 -48.208 -28.142 -TP10 85.0254 -45.2166 -71.5258 -P9 -75.0014 -70.3299 -64.4026 -P7 -73.4404 -74.4816 -21.5311 -P5 -67.4857 -80.9442 12.0896 -P3 -52.4644 -86.8018 41.7174 -P1 -27.4707 -91.1008 62.1009 -Pz 1.798 -92.892 68.8025 -P2 33.4052 -91.992 61.0662 -P4 56.7709 -88.0486 38.0235 -P6 68.346 -82.269 6.331 -P8 72.7791 -75.9692 -27.446 -P10 72.628 -72.8203 -70.7433 -PO9 -56.8372 -95.3663 -63.3236 -PO7 -55.7888 -99.2792 -20.6777 -PO5 -48.8741 -103.3422 -0.3424 -PO3 -36.5153 -106.8019 16.2198 -PO1 -18.6561 -109.0228 25.7639 -POz 0.7288 -110.1495 29.4389 -PO2 20.3845 -109.5322 24.0183 -PO4 37.125 -107.6542 12.3793 -PO6 49.8642 -104.7288 -4.2195 -PO8 55.269 -100.7939 -25.2641 -PO10 53.6086 -96.8209 -67.8917 -O1 -30.1827 -115.1564 -17.6531 -Oz -0.3825 -118.6416 -12.82 -O2 29.3709 -115.6245 -20.0571 -I1 -31.5736 -112.859 -60.3473 -Iz -1.4725 -117.9297 -55.4479 -I2 28.2856 -113.314 -62.7618 -AFp9h -43.7834 76.7156 -24.6872 -AFp7h -38.4014 78.0429 1.7139 -AFp5h -27.5693 79.51 10.2935 -AFp3h -16.5213 80.9018 18.4293 -AFp1h -5.0308 82.0616 25.2 -AFp2h 8.0797 82.0574 25.0034 -AFp4h 19.8187 81.0165 18.6673 -AFp6h 29.3509 79.2794 8.2199 -AFp8h 39.8723 77.7375 -1.0257 -AFp10h 43.7677 76.2828 -28.1819 -AFF9h -64.0508 55.3202 -30.1103 -AFF7h -61.3094 56.6025 5.4161 -AFF5h -50.1044 59.1157 30.6092 -AFF3h -33.047 61.1401 50.8486 -AFF1h -9.8029 62.1369 60.5286 -AFF2h 15.2609 62.1626 60.5135 -AFF4h 37.8118 60.9774 48.1866 -AFF6h 53.6104 58.8358 26.3383 -AFF8h 63.5803 56.2705 0.2814 -AFF10h 64.1776 54.4286 -35.3156 -FFT9h -80.1435 29.98 -35.115 -FFT7h -74.6121 28.9479 5.4301 -FFC5h -64.4714 30.3106 40.7846 -FFC3h -42.8586 31.3995 69.1279 -FFC1h -13.3003 32.0593 86.2546 -FFC2h 19.8863 32.0134 85.0984 -FFC4h 47.8355 31.2127 64.4458 -FFC6h 68.5449 30.0668 34.6963 -FFT8h 78.7068 28.696 -0.8854 -FFT10h 79.8179 28.3676 -41.6137 -FTT9h -85.3947 0.0917 -38.6344 -FTT7h -82.6201 -1.7108 4.4566 -FCC5h -73.9594 -2.5987 45.6214 -FCC3h -49.4398 -3.4069 77.5092 -FCC1h -15.9681 -4.0228 96.7068 -FCC2h 21.1996 -4.2351 94.1516 -FCC4h 53.9935 -4.0161 72.4607 -FCC6h 78.502 -3.5325 39.6766 -FTT8h 84.4606 -2.7316 -2.1998 -FTT10h 83.6996 -2.0579 -45.3053 -TTP9h -88.4155 -30.3203 -41.7809 -TTP7h -85.9961 -33.2715 1.8294 -CCP5h -75.8166 -36.9 43.9586 -CCP3h -51.4226 -39.9787 77.7305 -CCP1h -16.2152 -41.9164 96.3563 -CCP2h 22.5519 -42.2353 94.7632 -CCP4h 57.1681 -40.8745 73.6128 -CCP6h 80.3898 -38.2109 38.2201 -TTP8h 86.4355 -34.6905 -4.9069 -TTP10h 88.0571 -32.6235 -49.1107 -TPP9h -79.6515 -59.3039 -42.764 -TPP7h -77.2297 -63.6443 -2.0088 -CPP5h -67.7609 -69.8644 35.4942 -CPP3h -45.7512 -75.0904 65.5198 -CPP1h -14.1036 -78.2321 81.7424 -CPP2h 21.3444 -78.8253 81.6887 -CPP4h 52.3479 -76.2378 62.5108 -CPP6h 72.1512 -71.3197 29.9724 -TPP8h 78.7504 -65.2508 -8.233 -TPP10h 78.1967 -61.5292 -49.1742 -PPO9h -66.0824 -86.8056 -42.7728 -PPO7h -63.6209 -90.373 -7.2538 -PPO5h -54.0225 -95.6937 19.0735 -PPO3h -35.3582 -99.7896 38.2337 -PPO1h -11.1504 -102.19 48.2232 -PPO2h 14.9859 -102.7794 48.763 -PPO4h 38.7282 -100.8444 36.6069 -PPO6h 55.1343 -96.8027 14.3662 -PPO8h 63.0805 -91.7144 -12.4453 -PPO10h 64.1779 -88.6339 -48.0087 -POO9h -44.2292 -108.0837 -40.7847 -POO7h -40.8248 -110.0966 -12.6823 -POO5h -32.3428 -112.5907 -0.995 -POO3h -20.027 -114.21 5.8568 -POO1h -6.9463 -115.0347 8.5544 -POO2h 6.8173 -114.9846 6.7582 -POO4h 20.3094 -114.6056 3.3189 -POO6h 32.085 -113.326 -4.4874 -POO8h 40.8008 -111.2684 -15.9247 -POO10h 42.9543 -110.2492 -44.527 -OI1h -15.9862 -119.0324 -36.7658 -OI2h 14.1081 -119.4479 -38.0052 -Fp1h -14.4785 84.9238 2.6247 -Fp2h 15.6485 85.3977 1.4748 -AF9h -55.4831 67.6365 -27.5287 -AF7h -51.0685 68.7575 4.2028 -AF5h -39.055 70.8347 21.6208 -AF3h -26.1702 72.7976 38.1502 -AF1h -7.8738 73.6702 45.2727 -AF2h 11.9122 73.6489 44.7691 -AF4h 29.9146 72.658 36.0898 -AF6h 41.9399 70.6431 18.6979 -AF8h 52.6558 68.4514 -0.0028 -AF10h 55.6565 66.9773 -32.0302 -F9h -72.4472 42.8119 -32.649 -F7h -68.5894 43.0017 5.6359 -F5h -57.7415 45.088 36.4344 -F3h -38.5387 46.8226 61.4268 -F1h -11.4926 47.7516 73.8664 -F2h 17.8922 47.8495 73.5097 -F4h 43.6232 46.8566 57.0447 -F6h 61.3637 45.1378 30.2091 -F8h 72.6285 43.1488 -0.3315 -F10h 72.5815 41.67 -38.5911 -FT9h -84.1417 15.2883 -37.0995 -FT7h -80.3052 13.9499 5.2234 -FC5h -70.4482 14.2551 44.0007 -FC3h -46.9028 14.4356 74.6768 -FC1h -15.1086 14.4587 93.6393 -FC2h 20.8217 14.2993 91.6865 -FC4h 51.6349 13.958 70.0249 -FC6h 74.7111 13.5764 38.3013 -FT8h 82.1996 13.185 -1.448 -FT10h 83.0208 13.3629 -43.7663 -T9h -86.4839 -15.1545 -40.1289 -T7h -83.2853 -17.5024 3.2641 -C5h -74.6144 -19.7533 45.507 -C3h -50.0023 -21.6694 78.3953 -C1h -16.0323 -23.0178 98.768 -C2h 22.0735 -23.1892 95.4097 -C4h 55.9086 -22.3855 73.8737 -C6h 79.577 -20.8243 39.35 -T8h 85.6426 -18.6845 -3.5384 -T10h 85.6042 -17.3922 -47.1353 -TP9h -86.3032 -45.4946 -42.7439 -TP7h -83.2073 -48.9974 -0.174 -CP5h -72.8147 -53.9069 40.6631 -CP3h -49.6667 -58.1521 74.0686 -CP1h -15.3612 -60.7645 92.0156 -CP2h 22.8808 -61.2223 91.2228 -CP4h 55.9085 -59.2296 69.9099 -CP6h 77.7899 -55.4265 34.6701 -TP8h 85.5437 -50.6894 -6.7813 -TP10h 84.8032 -47.671 -49.6236 -P9h -73.6754 -73.4503 -42.9413 -P7h -70.723 -77.7116 -4.6522 -P5h -61.55 -84.037 27.9175 -P3h -40.8058 -89.1551 53.0693 -P1h -12.5998 -92.4097 67.6111 -P2h 18.8321 -92.8648 67.0518 -P4h 46.0726 -90.2373 50.6211 -P6h 64.4369 -85.344 22.9715 -P8h 72.209 -79.182 -10.3487 -P10h 72.5076 -75.769 -48.9895 -PO9h -56.217 -98.5254 -42.0579 -PO7h -52.6262 -101.3289 -10.379 -PO5h -43.5581 -105.199 8.6588 -PO3h -27.8394 -108.0203 21.5804 -PO1h -9.0683 -109.769 28.532 -PO2h 10.7576 -109.9376 27.2043 -PO4h 29.0928 -108.752 19 -PO6h 44.4377 -106.3608 4.8595 -PO8h 52.6631 -102.7654 -14.7219 -PO10h 54.965 -100.8633 -46.7437 -O1h -15.4436 -118.3291 -15.3957 -O2h 14.6568 -118.8064 -16.6272 -I1h -16.7847 -117.069 -58.0765 -I2h 13.6537 -117.3652 -59.3302 -AFp9 -37.0548 75.202 -45.1868 -AFp7 -43.5037 77.2316 -3.0515 -AFp5 -33.0012 78.7768 6.0117 -AFp3 -21.8137 80.1452 14.0088 -AFp1 -11.4283 81.6951 23.0966 -AFpz 1.1364 82.281 26.4124 -AFp2 14.5974 81.7938 23.3833 -AFp4 24.9121 80.1995 13.7778 -AFp6 34.5399 78.5 3.5002 -AFp8 44.3974 76.8228 -6.5519 -AFp10 37.1415 74.0785 -48.6153 -AFF9 -60.5954 56.2334 -51.0079 -AFF7 -63.5566 55.2301 -8.4341 -AFF5 -55.4531 57.8445 17.8767 -AFF3 -42.3856 60.21 41.5374 -AFF1 -22.0933 61.812 57.475 -AFFz 2.0157 62.3054 62.0853 -AFF2 27.3106 61.7522 56.1821 -AFF4 46.5956 59.9808 38.0053 -AFF6 58.9453 57.5727 13.4747 -AFF8 65.0202 54.8889 -13.7341 -AFF10 59.9363 54.3063 -56.2641 -FFT9 -80.0437 32.8876 -56.4501 -FFT7 -77.1723 28.2331 -13.1487 -FFC5 -71.1738 29.6545 23.7391 -FFC3 -54.7636 30.8891 55.9922 -FFC1 -28.7853 31.7853 79.2639 -FFCz 2.5936 32.0991 87.3091 -FFC2 34.8299 31.6799 76.5363 -FFC4 59.2312 30.6693 50.4887 -FFC6 75.3069 29.4116 17.403 -FFT8 79.2548 27.9647 -19.7288 -FFT10 79.1444 31.0608 -63.306 -FTT9 -89.1493 3.7781 -60.56 -FTT7 -83.4273 -1.2838 -16.8294 -FCC5 -79.8978 -2.1563 25.5187 -FCC3 -62.9684 -3.0163 62.7943 -FCC1 -33.7713 -3.76 89.4158 -FCCz 2.8152 -4.2016 99.3945 -FCC2 38.3681 -4.1567 84.7426 -FCC4 66.988 -3.8029 56.7423 -FCC6 82.593 -3.1552 19.0042 -FTT8 83.2444 -2.2951 -23.4708 -FTT10 84.4754 1.0781 -67.3204 -TTP9 -88.5585 -27.1149 -63.1223 -TTP7 -86.8691 -31.4577 -20.0713 -CCP5 -81.4639 -35.0818 23.0158 -CCP3 -65.0583 -38.5297 62.1734 -CCP1 -35.0511 -41.1732 89.8536 -CCPz 2.7074 -42.3528 99.0129 -CCP2 40.7797 -41.7156 85.9987 -CCP4 70.6169 -39.6774 57.3634 -CCP6 85.4843 -36.5032 17.0671 -TTP8 85.931 -32.8709 -26.8841 -TTP10 85.6981 -29.8335 -70.3548 -TPP9 -82.7221 -56.873 -64.6319 -TPP7 -79.5999 -60.4761 -21.3529 -CPP5 -73.7603 -66.7938 17.14 -CPP3 -58.6271 -72.7063 52.1229 -CPP1 -31.2274 -77.1315 76.6743 -CPPz 2.2361 -78.9251 84.2757 -CPP2 37.7383 -77.8396 73.9525 -CPP4 63.6522 -73.9727 47.276 -CPP6 77.3339 -68.3787 11.2664 -TPP8 79.1092 -62.0848 -27.7996 -TPP10 80.356 -59.5088 -71.5709 -PPO9 -66.5388 -83.3536 -64.0352 -PPO7 -65.5733 -87.5824 -21.3296 -PPO5 -59.0491 -93.0403 5.9751 -PPO3 -45.8824 -97.9494 29.8277 -PPO1 -23.8997 -101.3169 44.9749 -PPOz 1.277 -102.7115 49.7346 -PPO2 27.4696 -102.1088 44.1433 -PPO4 47.8957 -99.0048 26.3176 -PPO6 61.0875 -94.4363 1.6654 -PPO8 64.8118 -88.9733 -26.6095 -PPO10 63.7128 -85.2957 -69.5022 -POO9 -44.9827 -105.3003 -62.0721 -POO7 -43.8509 -108.6993 -19.447 -POO5 -36.7785 -111.3892 -6.6171 -POO3 -26.2593 -113.4345 2.587 -POO1 -13.7214 -114.9706 8.9905 -POOz 0.1781 -115.1513 8.352 -POO2 13.6826 -114.9415 5.771 -POO4 26.6485 -114.1503 0.2903 -POO6 37.5338 -112.5029 -9.2952 -POO8 43.2268 -109.9167 -23.0466 -POO10 41.7528 -106.3328 -65.6582 -OI1 -30.6551 -115.0268 -39.0009 -OIz -0.942 -120.9193 -34.2957 -OI2 28.5891 -114.9126 -41.2793 -T3 -85.0072 -16.3778 -18.4196 -T5 -73.4404 -74.4816 -21.5311 -T4 85.084 -17.5501 -25.2931 -T6 72.7791 -75.9692 -27.446 -M1 -88.6239 -38.4007 -88.7489 -M2 84.105 -40.6314 -95.8013 -A1 -88.4869 -18.4964 -85.1748 -A2 84.242 -20.7272 -92.2272 +spmnas 1 85 -41 +spmlpa -83 -20 -65 +spmrpa 83 -20 -65 +Fp1 -29.2644 82.1011 -0.1681 +Fpz 0.5966 85.4186 5.2724 +Fp2 30.3458 82.3208 -2.5084 +AF9 -50.0686 67.3263 -48.1825 +AF7 -54.9914 67.5738 -5.8804 +AF5 -45.0839 69.805 12.933 +AF3 -32.8795 71.8452 30.1284 +AF1 -17.2597 73.3677 42.8765 +AFz 1.6107 73.6809 45.2343 +AF2 21.227 73.2684 41.4016 +AF4 36.9056 71.7503 28.2715 +AF6 47.3996 69.5529 9.4173 +AF8 56.1483 67.2462 -10.3733 +AF10 49.8252 65.8653 -52.6275 +F9 -71.517 45.5339 -53.8552 +F7 -70.6916 41.8958 -10.8395 +F5 -64.1055 44.0763 21.4442 +F3 -49.1339 46.0206 49.8831 +F1 -25.7835 47.4288 69.8291 +Fz 2.3304 47.9355 75.787 +F2 31.496 47.454 66.7353 +F4 53.4301 46.0515 44.4067 +F6 68.9352 44.219 15.7579 +F8 73.3302 42.0529 -16.9723 +F10 71.4009 44.1701 -60.1286 +FT9 -85.7586 18.814 -58.6571 +FT7 -81.4433 13.7802 -15.1615 +FC5 -76.9277 14.1172 25.097 +FC3 -58.9898 14.3544 59.7085 +FC1 -32.0939 14.4686 86.4236 +FCz 2.747 14.3924 94.9242 +FC2 37.0696 14.142 82.3849 +FC4 64.1073 13.7668 54.9967 +FC6 80.6141 13.3845 18.9204 +FT8 81.9645 12.9962 -21.7677 +FT10 83.2681 16.456 -65.6635 +T9 -87.7394 -11.6613 -61.6278 +T7 -85.0072 -16.3778 -18.4196 +C5 -80.1105 -18.6349 24.6594 +C3 -64.2027 -20.782 63.5856 +C1 -34.1983 -22.4568 90.9388 +Cz 2.8165 -23.3292 101.2672 +C2 39.9696 -22.8958 86.5061 +C4 68.9216 -21.6725 57.4563 +C6 84.453 -19.7733 18.2209 +T8 85.084 -17.5501 -25.2931 +T10 84.5694 -14.4038 -68.6915 +TP9 -87.6077 -42.502 -64.2573 +TP7 -85.8268 -46.4935 -21.2067 +CP5 -79.5982 -51.4848 20.7615 +CP3 -62.6018 -56.1594 58.5984 +CP1 -33.7659 -59.7753 85.984 +CPz 2.5193 -61.2034 93.5467 +CP2 40.4866 -60.4388 82.3243 +CP4 68.2191 -57.4632 53.3152 +CP6 84.1409 -53.1682 14.4935 +TP8 85.4063 -48.208 -28.142 +TP10 85.0254 -45.2166 -71.5258 +P9 -75.0014 -70.3299 -64.4026 +P7 -73.4404 -74.4816 -21.5311 +P5 -67.4857 -80.9442 12.0896 +P3 -52.4644 -86.8018 41.7174 +P1 -27.4707 -91.1008 62.1009 +Pz 1.798 -92.892 68.8025 +P2 33.4052 -91.992 61.0662 +P4 56.7709 -88.0486 38.0235 +P6 68.346 -82.269 6.331 +P8 72.7791 -75.9692 -27.446 +P10 72.628 -72.8203 -70.7433 +PO9 -56.8372 -95.3663 -63.3236 +PO7 -55.7888 -99.2792 -20.6777 +PO5 -48.8741 -103.3422 -0.3424 +PO3 -36.5153 -106.8019 16.2198 +PO1 -18.6561 -109.0228 25.7639 +POz 0.7288 -110.1495 29.4389 +PO2 20.3845 -109.5322 24.0183 +PO4 37.125 -107.6542 12.3793 +PO6 49.8642 -104.7288 -4.2195 +PO8 55.269 -100.7939 -25.2641 +PO10 53.6086 -96.8209 -67.8917 +O1 -30.1827 -115.1564 -17.6531 +Oz -0.3825 -118.6416 -12.82 +O2 29.3709 -115.6245 -20.0571 +I1 -31.5736 -112.859 -60.3473 +Iz -1.4725 -117.9297 -55.4479 +I2 28.2856 -113.314 -62.7618 +AFp9h -43.7834 76.7156 -24.6872 +AFp7h -38.4014 78.0429 1.7139 +AFp5h -27.5693 79.51 10.2935 +AFp3h -16.5213 80.9018 18.4293 +AFp1h -5.0308 82.0616 25.2 +AFp2h 8.0797 82.0574 25.0034 +AFp4h 19.8187 81.0165 18.6673 +AFp6h 29.3509 79.2794 8.2199 +AFp8h 39.8723 77.7375 -1.0257 +AFp10h 43.7677 76.2828 -28.1819 +AFF9h -64.0508 55.3202 -30.1103 +AFF7h -61.3094 56.6025 5.4161 +AFF5h -50.1044 59.1157 30.6092 +AFF3h -33.047 61.1401 50.8486 +AFF1h -9.8029 62.1369 60.5286 +AFF2h 15.2609 62.1626 60.5135 +AFF4h 37.8118 60.9774 48.1866 +AFF6h 53.6104 58.8358 26.3383 +AFF8h 63.5803 56.2705 0.2814 +AFF10h 64.1776 54.4286 -35.3156 +FFT9h -80.1435 29.98 -35.115 +FFT7h -74.6121 28.9479 5.4301 +FFC5h -64.4714 30.3106 40.7846 +FFC3h -42.8586 31.3995 69.1279 +FFC1h -13.3003 32.0593 86.2546 +FFC2h 19.8863 32.0134 85.0984 +FFC4h 47.8355 31.2127 64.4458 +FFC6h 68.5449 30.0668 34.6963 +FFT8h 78.7068 28.696 -0.8854 +FFT10h 79.8179 28.3676 -41.6137 +FTT9h -85.3947 0.0917 -38.6344 +FTT7h -82.6201 -1.7108 4.4566 +FCC5h -73.9594 -2.5987 45.6214 +FCC3h -49.4398 -3.4069 77.5092 +FCC1h -15.9681 -4.0228 96.7068 +FCC2h 21.1996 -4.2351 94.1516 +FCC4h 53.9935 -4.0161 72.4607 +FCC6h 78.502 -3.5325 39.6766 +FTT8h 84.4606 -2.7316 -2.1998 +FTT10h 83.6996 -2.0579 -45.3053 +TTP9h -88.4155 -30.3203 -41.7809 +TTP7h -85.9961 -33.2715 1.8294 +CCP5h -75.8166 -36.9 43.9586 +CCP3h -51.4226 -39.9787 77.7305 +CCP1h -16.2152 -41.9164 96.3563 +CCP2h 22.5519 -42.2353 94.7632 +CCP4h 57.1681 -40.8745 73.6128 +CCP6h 80.3898 -38.2109 38.2201 +TTP8h 86.4355 -34.6905 -4.9069 +TTP10h 88.0571 -32.6235 -49.1107 +TPP9h -79.6515 -59.3039 -42.764 +TPP7h -77.2297 -63.6443 -2.0088 +CPP5h -67.7609 -69.8644 35.4942 +CPP3h -45.7512 -75.0904 65.5198 +CPP1h -14.1036 -78.2321 81.7424 +CPP2h 21.3444 -78.8253 81.6887 +CPP4h 52.3479 -76.2378 62.5108 +CPP6h 72.1512 -71.3197 29.9724 +TPP8h 78.7504 -65.2508 -8.233 +TPP10h 78.1967 -61.5292 -49.1742 +PPO9h -66.0824 -86.8056 -42.7728 +PPO7h -63.6209 -90.373 -7.2538 +PPO5h -54.0225 -95.6937 19.0735 +PPO3h -35.3582 -99.7896 38.2337 +PPO1h -11.1504 -102.19 48.2232 +PPO2h 14.9859 -102.7794 48.763 +PPO4h 38.7282 -100.8444 36.6069 +PPO6h 55.1343 -96.8027 14.3662 +PPO8h 63.0805 -91.7144 -12.4453 +PPO10h 64.1779 -88.6339 -48.0087 +POO9h -44.2292 -108.0837 -40.7847 +POO7h -40.8248 -110.0966 -12.6823 +POO5h -32.3428 -112.5907 -0.995 +POO3h -20.027 -114.21 5.8568 +POO1h -6.9463 -115.0347 8.5544 +POO2h 6.8173 -114.9846 6.7582 +POO4h 20.3094 -114.6056 3.3189 +POO6h 32.085 -113.326 -4.4874 +POO8h 40.8008 -111.2684 -15.9247 +POO10h 42.9543 -110.2492 -44.527 +OI1h -15.9862 -119.0324 -36.7658 +OI2h 14.1081 -119.4479 -38.0052 +Fp1h -14.4785 84.9238 2.6247 +Fp2h 15.6485 85.3977 1.4748 +AF9h -55.4831 67.6365 -27.5287 +AF7h -51.0685 68.7575 4.2028 +AF5h -39.055 70.8347 21.6208 +AF3h -26.1702 72.7976 38.1502 +AF1h -7.8738 73.6702 45.2727 +AF2h 11.9122 73.6489 44.7691 +AF4h 29.9146 72.658 36.0898 +AF6h 41.9399 70.6431 18.6979 +AF8h 52.6558 68.4514 -0.0028 +AF10h 55.6565 66.9773 -32.0302 +F9h -72.4472 42.8119 -32.649 +F7h -68.5894 43.0017 5.6359 +F5h -57.7415 45.088 36.4344 +F3h -38.5387 46.8226 61.4268 +F1h -11.4926 47.7516 73.8664 +F2h 17.8922 47.8495 73.5097 +F4h 43.6232 46.8566 57.0447 +F6h 61.3637 45.1378 30.2091 +F8h 72.6285 43.1488 -0.3315 +F10h 72.5815 41.67 -38.5911 +FT9h -84.1417 15.2883 -37.0995 +FT7h -80.3052 13.9499 5.2234 +FC5h -70.4482 14.2551 44.0007 +FC3h -46.9028 14.4356 74.6768 +FC1h -15.1086 14.4587 93.6393 +FC2h 20.8217 14.2993 91.6865 +FC4h 51.6349 13.958 70.0249 +FC6h 74.7111 13.5764 38.3013 +FT8h 82.1996 13.185 -1.448 +FT10h 83.0208 13.3629 -43.7663 +T9h -86.4839 -15.1545 -40.1289 +T7h -83.2853 -17.5024 3.2641 +C5h -74.6144 -19.7533 45.507 +C3h -50.0023 -21.6694 78.3953 +C1h -16.0323 -23.0178 98.768 +C2h 22.0735 -23.1892 95.4097 +C4h 55.9086 -22.3855 73.8737 +C6h 79.577 -20.8243 39.35 +T8h 85.6426 -18.6845 -3.5384 +T10h 85.6042 -17.3922 -47.1353 +TP9h -86.3032 -45.4946 -42.7439 +TP7h -83.2073 -48.9974 -0.174 +CP5h -72.8147 -53.9069 40.6631 +CP3h -49.6667 -58.1521 74.0686 +CP1h -15.3612 -60.7645 92.0156 +CP2h 22.8808 -61.2223 91.2228 +CP4h 55.9085 -59.2296 69.9099 +CP6h 77.7899 -55.4265 34.6701 +TP8h 85.5437 -50.6894 -6.7813 +TP10h 84.8032 -47.671 -49.6236 +P9h -73.6754 -73.4503 -42.9413 +P7h -70.723 -77.7116 -4.6522 +P5h -61.55 -84.037 27.9175 +P3h -40.8058 -89.1551 53.0693 +P1h -12.5998 -92.4097 67.6111 +P2h 18.8321 -92.8648 67.0518 +P4h 46.0726 -90.2373 50.6211 +P6h 64.4369 -85.344 22.9715 +P8h 72.209 -79.182 -10.3487 +P10h 72.5076 -75.769 -48.9895 +PO9h -56.217 -98.5254 -42.0579 +PO7h -52.6262 -101.3289 -10.379 +PO5h -43.5581 -105.199 8.6588 +PO3h -27.8394 -108.0203 21.5804 +PO1h -9.0683 -109.769 28.532 +PO2h 10.7576 -109.9376 27.2043 +PO4h 29.0928 -108.752 19 +PO6h 44.4377 -106.3608 4.8595 +PO8h 52.6631 -102.7654 -14.7219 +PO10h 54.965 -100.8633 -46.7437 +O1h -15.4436 -118.3291 -15.3957 +O2h 14.6568 -118.8064 -16.6272 +I1h -16.7847 -117.069 -58.0765 +I2h 13.6537 -117.3652 -59.3302 +AFp9 -37.0548 75.202 -45.1868 +AFp7 -43.5037 77.2316 -3.0515 +AFp5 -33.0012 78.7768 6.0117 +AFp3 -21.8137 80.1452 14.0088 +AFp1 -11.4283 81.6951 23.0966 +AFpz 1.1364 82.281 26.4124 +AFp2 14.5974 81.7938 23.3833 +AFp4 24.9121 80.1995 13.7778 +AFp6 34.5399 78.5 3.5002 +AFp8 44.3974 76.8228 -6.5519 +AFp10 37.1415 74.0785 -48.6153 +AFF9 -60.5954 56.2334 -51.0079 +AFF7 -63.5566 55.2301 -8.4341 +AFF5 -55.4531 57.8445 17.8767 +AFF3 -42.3856 60.21 41.5374 +AFF1 -22.0933 61.812 57.475 +AFFz 2.0157 62.3054 62.0853 +AFF2 27.3106 61.7522 56.1821 +AFF4 46.5956 59.9808 38.0053 +AFF6 58.9453 57.5727 13.4747 +AFF8 65.0202 54.8889 -13.7341 +AFF10 59.9363 54.3063 -56.2641 +FFT9 -80.0437 32.8876 -56.4501 +FFT7 -77.1723 28.2331 -13.1487 +FFC5 -71.1738 29.6545 23.7391 +FFC3 -54.7636 30.8891 55.9922 +FFC1 -28.7853 31.7853 79.2639 +FFCz 2.5936 32.0991 87.3091 +FFC2 34.8299 31.6799 76.5363 +FFC4 59.2312 30.6693 50.4887 +FFC6 75.3069 29.4116 17.403 +FFT8 79.2548 27.9647 -19.7288 +FFT10 79.1444 31.0608 -63.306 +FTT9 -89.1493 3.7781 -60.56 +FTT7 -83.4273 -1.2838 -16.8294 +FCC5 -79.8978 -2.1563 25.5187 +FCC3 -62.9684 -3.0163 62.7943 +FCC1 -33.7713 -3.76 89.4158 +FCCz 2.8152 -4.2016 99.3945 +FCC2 38.3681 -4.1567 84.7426 +FCC4 66.988 -3.8029 56.7423 +FCC6 82.593 -3.1552 19.0042 +FTT8 83.2444 -2.2951 -23.4708 +FTT10 84.4754 1.0781 -67.3204 +TTP9 -88.5585 -27.1149 -63.1223 +TTP7 -86.8691 -31.4577 -20.0713 +CCP5 -81.4639 -35.0818 23.0158 +CCP3 -65.0583 -38.5297 62.1734 +CCP1 -35.0511 -41.1732 89.8536 +CCPz 2.7074 -42.3528 99.0129 +CCP2 40.7797 -41.7156 85.9987 +CCP4 70.6169 -39.6774 57.3634 +CCP6 85.4843 -36.5032 17.0671 +TTP8 85.931 -32.8709 -26.8841 +TTP10 85.6981 -29.8335 -70.3548 +TPP9 -82.7221 -56.873 -64.6319 +TPP7 -79.5999 -60.4761 -21.3529 +CPP5 -73.7603 -66.7938 17.14 +CPP3 -58.6271 -72.7063 52.1229 +CPP1 -31.2274 -77.1315 76.6743 +CPPz 2.2361 -78.9251 84.2757 +CPP2 37.7383 -77.8396 73.9525 +CPP4 63.6522 -73.9727 47.276 +CPP6 77.3339 -68.3787 11.2664 +TPP8 79.1092 -62.0848 -27.7996 +TPP10 80.356 -59.5088 -71.5709 +PPO9 -66.5388 -83.3536 -64.0352 +PPO7 -65.5733 -87.5824 -21.3296 +PPO5 -59.0491 -93.0403 5.9751 +PPO3 -45.8824 -97.9494 29.8277 +PPO1 -23.8997 -101.3169 44.9749 +PPOz 1.277 -102.7115 49.7346 +PPO2 27.4696 -102.1088 44.1433 +PPO4 47.8957 -99.0048 26.3176 +PPO6 61.0875 -94.4363 1.6654 +PPO8 64.8118 -88.9733 -26.6095 +PPO10 63.7128 -85.2957 -69.5022 +POO9 -44.9827 -105.3003 -62.0721 +POO7 -43.8509 -108.6993 -19.447 +POO5 -36.7785 -111.3892 -6.6171 +POO3 -26.2593 -113.4345 2.587 +POO1 -13.7214 -114.9706 8.9905 +POOz 0.1781 -115.1513 8.352 +POO2 13.6826 -114.9415 5.771 +POO4 26.6485 -114.1503 0.2903 +POO6 37.5338 -112.5029 -9.2952 +POO8 43.2268 -109.9167 -23.0466 +POO10 41.7528 -106.3328 -65.6582 +OI1 -30.6551 -115.0268 -39.0009 +OIz -0.942 -120.9193 -34.2957 +OI2 28.5891 -114.9126 -41.2793 +T3 -85.0072 -16.3778 -18.4196 +T5 -73.4404 -74.4816 -21.5311 +T4 85.084 -17.5501 -25.2931 +T6 72.7791 -75.9692 -27.446 +M1 -88.6239 -38.4007 -88.7489 +M2 84.105 -40.6314 -95.8013 +A1 -88.4869 -18.4964 -85.1748 +A2 84.242 -20.7272 -92.2272 diff --git a/EEGtemplates/fiducials.sfp b/EEGtemplates/fiducials.sfp new file mode 100644 index 0000000..1d98d6f --- /dev/null +++ b/EEGtemplates/fiducials.sfp @@ -0,0 +1,6 @@ +nas 1 85 -41 +lpa -83 -20 -65 +rpa 83 -20 -65 +FIL_CTF_L -87 -11 -62 +FIL_CTF_R 87 -11 -62 + \ No newline at end of file diff --git a/config/spm_cfg.m b/config/spm_cfg.m index c0e582b..8142f93 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 3465 2009-10-14 15:14:29Z guillaume $ +% $Id: spm_cfg.m 3881 2010-05-07 21:02:57Z vladimir $ %_______________________________________________________________________ % temporal Temporal @@ -30,13 +30,37 @@ stats.help = {'Various analysis utilities.'}; stats.values = { spm_cfg_fmri_spec spm_cfg_fmri_design spm_cfg_fmri_data spm_cfg_factorial_design spm_cfg_fmri_est spm_cfg_con spm_cfg_results spm_cfg_bms spm_cfg_ppi}; % --------------------------------------------------------------------- +% meeg preprocessing +% --------------------------------------------------------------------- +meegprep = cfg_choice; +meegprep.tag = 'preproc'; +meegprep.name = 'M/EEG Preprocessing'; +meegprep.help = {'M/EEG preprocessing.'}; +meegprep.values = {spm_cfg_eeg_montage spm_cfg_eeg_filter spm_cfg_eeg_bc spm_cfg_eeg_artefact spm_cfg_eeg_downsample spm_cfg_eeg_merge spm_cfg_eeg_fuse}; +% --------------------------------------------------------------------- +% meeg time-frequency +% --------------------------------------------------------------------- +meegtf = cfg_choice; +meegtf.tag = 'tf'; +meegtf.name = 'M/EEG Time-frequency'; +meegtf.help = {'M/EEG time-frequency.'}; +meegtf.values = {spm_cfg_eeg_tf spm_cfg_eeg_tf_rescale}; +% --------------------------------------------------------------------- +% meeg source reconstruction +% --------------------------------------------------------------------- +source = cfg_choice; +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}; +% --------------------------------------------------------------------- % meeg Meeg % --------------------------------------------------------------------- meeg = cfg_choice; meeg.tag = 'meeg'; meeg.name = 'M/EEG'; meeg.help = {'M/EEG functions.'}; -meeg.values = { spm_cfg_eeg_convert spm_cfg_eeg_montage spm_cfg_eeg_epochs spm_cfg_eeg_filter spm_cfg_eeg_bc spm_cfg_eeg_artefact spm_cfg_eeg_average spm_cfg_eeg_downsample spm_cfg_eeg_merge spm_cfg_eeg_fuse spm_cfg_eeg_contrast spm_cfg_eeg_grandmean spm_cfg_eeg_tf_rescale spm_cfg_eeg_convert2images}; +meeg.values = { spm_cfg_eeg_convert spm_cfg_eeg_epochs meegprep spm_cfg_eeg_average spm_cfg_eeg_review spm_cfg_eeg_contrast spm_cfg_eeg_grandmean spm_cfg_eeg_convert2images meegtf source}; % --------------------------------------------------------------------- % util Util % --------------------------------------------------------------------- @@ -61,7 +85,9 @@ ['See spm_cfg.m or MATLABBATCH documentation ' ... 'for information about the form of SPM''s configuration ' ... 'files.']}; -if ~isdeployed +if isdeployed + tools.values = spm_cfg_static_tools; +else %-Toolbox autodetection % In compiled mode, cfg_master will take care of this % Disable warnings when converting SPM5 toolboxes - set this to 'on' to diff --git a/config/spm_cfg_bms.m b/config/spm_cfg_bms.m index 024bbd7..a3d5d2c 100644 --- a/config/spm_cfg_bms.m +++ b/config/spm_cfg_bms.m @@ -4,7 +4,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Maria Joao Rosa -% $Id: spm_cfg_bms.m 3632 2009-12-11 09:58:31Z maria $ +% $Id: spm_cfg_bms.m 3955 2010-06-29 17:26:29Z maria $ % --------------------------------------------------------------------- % dir Directory @@ -354,8 +354,7 @@ bma = cfg_choice; bma.tag = 'bma'; bma.name = 'BMA'; -bma.help = {['Optional field to compute Bayesian Model Averaging (BMA). '... - 'Only available for DCM for fMRI!']}; +bma.help = {'Optional field to compute Bayesian Model Averaging (BMA).'}; bma.val = {bma_no }; bma.values = {bma_no bma_yes }; diff --git a/config/spm_cfg_con.m b/config/spm_cfg_con.m index 19fb7b0..e5501fa 100644 --- a/config/spm_cfg_con.m +++ b/config/spm_cfg_con.m @@ -1,12 +1,11 @@ function con = spm_cfg_con -% SPM Configuration file -% automatically generated by the MATLABBATCH utility function GENCODE +% SPM Configuration file for contrast specification %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_cfg_con.m 3430 2009-09-29 16:55:38Z guillaume $ +% $Id: spm_cfg_con.m 3993 2010-07-13 11:59:32Z volkmar $ -rev = '$Rev: 3430 $'; +rev = '$Rev: 3993 $'; % --------------------------------------------------------------------- % spmmat Select SPM.mat % --------------------------------------------------------------------- @@ -44,19 +43,23 @@ sessrep.val = {'none'}; sessrep.help = { 'If there are multiple sessions with identical conditions, one might want to specify contrasts which are identical over sessions. This can be done automatically based on the contrast spec for one session.' - 'Contrasts can be either replicated (thus testing average effects over sessions) or created per session. In both cases, zero padding up to the length of each session and the block effects is done automatically.' + 'Contrasts can be either replicated (thus testing average effects over sessions) or created per session. In both cases, zero padding up to the length of each session and the block effects is done automatically. In addition, weights of replicated contrasts can be scaled by the number of sessions. This allows to use the same contrast manager batch for fMRI analyses with a variable number of sessions. The scaled contrasts can then be compared in a 2nd level model without a need for further adjustment of effect sizes.' }'; sessrep.labels = { 'Don''t replicate' 'Replicate' + 'Replicate&Scale' 'Create per session' - 'Both' + 'Both: Replicate + Create per session' + 'Both: Replicate&Scale + Create per session' }'; sessrep.values = { 'none' 'repl' + 'replsc' 'sess' 'both' + 'bothsc' }'; % --------------------------------------------------------------------- % tcon T-contrast @@ -429,7 +432,7 @@ 'No' }'; delete.values = {1 0}; -delete.def = @(val)spm_get_defaults('stats.con.delete', val{:}); +delete.val = {0}; % --------------------------------------------------------------------- % con Contrast Manager % --------------------------------------------------------------------- diff --git a/config/spm_cfg_defs.m b/config/spm_cfg_defs.m index f9dfea1..a360b5a 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 3600 2009-11-26 14:12:49Z volkmar $ +% $Id: spm_cfg_defs.m 3804 2010-03-31 16:16:21Z ged $ hsummary = {[... 'This is a utility for working with deformation fields. ',... @@ -93,11 +93,11 @@ matname.help = hmatname; vox = entry('Voxel sizes','vox','e',[1 3]); -vox.def = @(val)spm_get_defaults('defs.vox',val{:}); +vox.val = {[NaN NaN NaN]}; vox.help = hvox; bb = entry('Bounding box','bb','e',[2 3]); -bb.def = @(val)spm_get_defaults('defs.bb',val{:}); +bb.val = {[NaN NaN NaN;NaN NaN NaN]}; bb.help = hbb; sn2def = branch('Imported _sn.mat','sn2def',{matname,vox,bb}); @@ -106,7 +106,13 @@ img = files('Image to base Id on','space','image',[1 1]); img.help = himg; -id = branch('Identity','id',{img}); +id = branch('Identity (Reference Image)','id',{img}); +id.help = hid; + +voxid = entry('Voxel sizes','vox','e',[1 3]); +bbid = entry('Bounding box','bb','e',[2 3]); + +idbbvox = branch('Identity (Bounding Box and Voxel Size)','idbbvox',{voxid, bbid}); id.help = hid; ffield = files('Flow field','flowfield','nifti',[1 1]); @@ -127,7 +133,7 @@ K = mnu('Time Steps','K',... {'1','2','4','8','16','32','64','128','256','512'},... {0,1,2,3,4,5,6,7,8,9}); -K.def = @(val)spm_get_defaults('defs.K',val{:}); +K.val = {6}; K.help = {... ['The number of time points used for solving the '... 'partial differential equations. A single time point would be '... @@ -140,7 +146,7 @@ drtl = branch('DARTEL flow','dartel',{ffield,forbak,K}); drtl.help = {'Imported DARTEL flow field.'}; %------------------------------------------------------------------------ -other = {sn2def,drtl,def,id}; +other = {sn2def,drtl,def,id,idbbvox}; img = files('Image to base inverse on','space','image',[1 1]); img.help = himg; @@ -219,19 +225,22 @@ '6th Degree B-Spline','7th Degree B-Spline'}; interp.values = {0,1,2,3,4,5,6,7}; interp.def = @(val)spm_get_defaults('normalise.write.interp',val{:}); -interp.help = {... -['The method by which the images are sampled when being written in a ',... -'different space.'],... -[' Nearest Neighbour: ',... -' - Fastest, but not normally recommended.'],... -[' Bilinear Interpolation: ',... -' - OK for PET, or realigned fMRI.'],... -[' B-spline Interpolation: ',... -' - Better quality (but slower) interpolation/* \cite{thevenaz00a}*/, especially ',... -' with higher degree splines. Do not use B-splines when ',... -' there is any region of NaN or Inf in the images. '],... -}; - +interp.help = { + ['The method by which the images are sampled when ' ... + 'being written in a different space. ' ... + '(Note that Inf or NaN values are treated as zero, ' ... + 'rather than as missing data)'] + ' Nearest Neighbour:' + ' - Fastest, but not normally recommended.' + ' Bilinear Interpolation:' + ' - OK for PET, realigned fMRI, or segmentations' + ' B-spline Interpolation:' + [' - Better quality (but slower) interpolation' ... + '/* \cite{thevenaz00a}*/, especially with higher ' ... + 'degree splines. Can produce values outside the ' ... + 'original range (e.g. small negative values from an ' ... + 'originally all positive image).'] +}'; conf = exbranch('Deformations','defs',{comp,saveas,applyto,savedir,interp}); conf.prog = @spm_defs; diff --git a/config/spm_cfg_dicom.m b/config/spm_cfg_dicom.m index 7e91aec..6c6f876 100644 --- a/config/spm_cfg_dicom.m +++ b/config/spm_cfg_dicom.m @@ -1,12 +1,10 @@ function dicom = spm_cfg_dicom -% SPM Configuration file -% automatically generated by the MATLABBATCH utility function GENCODE +% SPM Configuration file for DICOM Import %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_cfg_dicom.m 2222 2008-09-29 11:08:47Z volkmar $ +% $Id: spm_cfg_dicom.m 3697 2010-01-22 17:07:18Z guillaume $ -rev = '$Rev: 2222 $'; % --------------------------------------------------------------------- % data DICOM files % --------------------------------------------------------------------- @@ -14,7 +12,7 @@ data.tag = 'data'; data.name = 'DICOM files'; data.help = {'Select the DICOM files to convert.'}; -data.filter = 'any'; +data.filter = 'any'; data.ufilter = '.*'; data.num = [1 Inf]; % --------------------------------------------------------------------- @@ -23,31 +21,25 @@ root = cfg_menu; root.tag = 'root'; root.name = 'Directory structure for converted files'; -root.help = { - 'Choose root directory of converted file tree. The options are:' +root.help = {'Choose root directory of converted file tree. The options are:' '' '* Output directory: ./: Automatically determine the project name and try to convert into the output directory, starting with a StudyDate-StudyTime subdirectory. This option is useful if automatic project recognition fails and one wants to convert data into a project directory.' '' '* Output directory: ./: Convert into the output directory, starting with a PatientID subdirectory.' '' '* 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: ./' - 'No directory hierarchy' -}'; -root.values = { - 'date_time' - 'patid' - 'patid_date' - 'patname' - 'flat' -}'; -root.def = @(val)spm_get_defaults('dicom.root', val{:}); + '* No directory hierarchy: Convert all files into the output directory, without sequence/series subdirectories'}'; +root.labels = {'Output directory: ./' + 'Output directory: ./' + 'Output directory: .//' + 'Output directory: ./' + 'No directory hierarchy'}'; +root.values = {'date_time' + 'patid' + 'patid_date' + 'patname' + 'flat'}'; +root.def = @(val)spm_get_defaults('dicom.root', val{:}); % --------------------------------------------------------------------- % outdir Output directory % --------------------------------------------------------------------- @@ -55,7 +47,7 @@ outdir.tag = 'outdir'; outdir.name = 'Output directory'; outdir.help = {'Select a directory where files are written.'}; -outdir.filter = 'dir'; +outdir.filter = 'dir'; outdir.ufilter = '.*'; outdir.num = [1 1]; % --------------------------------------------------------------------- @@ -64,50 +56,40 @@ format = cfg_menu; format.tag = 'format'; format.name = 'Output image format'; -format.help = { - 'DICOM conversion can create separate img and hdr files or combine them in one file. The single file option will help you save space on your hard disk, but may be incompatible with programs that are not NIfTI-aware.' - 'In any case, only 3D image files will be produced.' -}'; -format.labels = { - 'Two file (img+hdr) NIfTI' - 'Single file (nii) NIfTI' -}'; -format.values = { - 'img' - 'nii' -}'; -format.def = @(val)spm_get_defaults('dicom.format', val{:}); +format.help = {'DICOM conversion can create separate img and hdr files or combine them in one file. The single file option will help you save space on your hard disk, but may be incompatible with programs that are not NIfTI-aware.' + 'In any case, only 3D image files will be produced.'}'; +format.labels = {'Two file (img+hdr) NIfTI' + 'Single file (nii) NIfTI'}'; +format.values = {'img' 'nii'}; +format.def = @(val)spm_get_defaults('images.format', val{:}); % --------------------------------------------------------------------- % icedims Use ICEDims in filename % --------------------------------------------------------------------- -icedims = cfg_menu; -icedims.tag = 'icedims'; -icedims.name = 'Use ICEDims in filename'; -icedims.help = {'If image sorting fails, one can try using the additional SIEMENS ICEDims information to create unique filenames. Use this only if there would be multiple volumes with exactly the same file names.'}; -icedims.labels = { - 'No' - 'Yes' -}'; +icedims = cfg_menu; +icedims.tag = 'icedims'; +icedims.name = 'Use ICEDims in filename'; +icedims.help = {'If image sorting fails, one can try using the additional SIEMENS ICEDims information to create unique filenames. Use this only if there would be multiple volumes with exactly the same file names.'}; +icedims.labels = {'No' 'Yes'}; icedims.values = {0 1}; -icedims.def = @(val)spm_get_defaults('dicom.icedims', val{:}); +icedims.val = {0}; % --------------------------------------------------------------------- % convopts Conversion options % --------------------------------------------------------------------- -convopts = cfg_branch; -convopts.tag = 'convopts'; -convopts.name = 'Conversion options'; -convopts.val = {format icedims }; -convopts.help = {''}; +convopts = cfg_branch; +convopts.tag = 'convopts'; +convopts.name = 'Conversion options'; +convopts.val = {format icedims}; +convopts.help = {''}; % --------------------------------------------------------------------- % dicom DICOM Import % --------------------------------------------------------------------- -dicom = cfg_exbranch; -dicom.tag = 'dicom'; -dicom.name = 'DICOM Import'; -dicom.val = {data root outdir convopts }; -dicom.help = {'DICOM Conversion. Most scanners produce data in DICOM format. This routine attempts to convert DICOM files into SPM compatible image volumes, which are written into the current directory by default. Note that not all flavours of DICOM can be handled, as DICOM is a very complicated format, and some scanner manufacturers use their own fields, which are not in the official documentation at http://medical.nema.org/'}; -dicom.prog = @spm_run_dicom; -dicom.vout = @vout; +dicom = cfg_exbranch; +dicom.tag = 'dicom'; +dicom.name = 'DICOM Import'; +dicom.val = {data root outdir convopts}; +dicom.help = {'DICOM Conversion. Most scanners produce data in DICOM format. This routine attempts to convert DICOM files into SPM compatible image volumes, which are written into the current directory by default. Note that not all flavours of DICOM can be handled, as DICOM is a very complicated format, and some scanner manufacturers use their own fields, which are not in the official documentation at http://medical.nema.org/'}; +dicom.prog = @spm_run_dicom; +dicom.vout = @vout; % --------------------------------------------------------------------- % --------------------------------------------------------------------- diff --git a/config/spm_cfg_ecat.m b/config/spm_cfg_ecat.m index 815db0d..b054248 100644 --- a/config/spm_cfg_ecat.m +++ b/config/spm_cfg_ecat.m @@ -1,12 +1,11 @@ function ecat = spm_cfg_ecat -% SPM Configuration file -% automatically generated by the MATLABBATCH utility function GENCODE +% SPM Configuration file for ECAT Import %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_cfg_ecat.m 1775 2008-06-02 09:18:18Z volkmar $ +% $Id: spm_cfg_ecat.m 3691 2010-01-20 17:08:30Z guillaume $ -rev = '$Rev: 1775 $'; +rev = '$Rev: 3691 $'; % --------------------------------------------------------------------- % data ECAT files % --------------------------------------------------------------------- @@ -18,21 +17,21 @@ data.ufilter = '.*v'; data.num = [1 Inf]; % --------------------------------------------------------------------- -% ext NIFTI Type +% ext Output image format % --------------------------------------------------------------------- ext = cfg_menu; ext.tag = 'ext'; -ext.name = 'NIFTI Type'; +ext.name = 'Output image format'; ext.help = {'Output files can be written as .img + .hdr, or the two can be combined into a .nii file.'}; ext.labels = { - '.nii only' - '.img + .hdr' + 'Two file (img+hdr) NIfTI' + 'Single file (nii) NIfTI' }'; ext.values = { - '.nii' - '.img' + 'img' + 'nii' }'; -ext.def = @(val)spm_get_defaults('ecat.ext', val{:}); +ext.def = @(val)spm_get_defaults('images.format', val{:}); % --------------------------------------------------------------------- % opts Options % --------------------------------------------------------------------- diff --git a/config/spm_cfg_eeg_artefact.m b/config/spm_cfg_eeg_artefact.m index a54c981..3728bdc 100644 --- a/config/spm_cfg_eeg_artefact.m +++ b/config/spm_cfg_eeg_artefact.m @@ -4,9 +4,9 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Vladimir Litvak -% $Id: spm_cfg_eeg_artefact.m 3258 2009-07-08 17:46:54Z vladimir $ +% $Id: spm_cfg_eeg_artefact.m 3881 2010-05-07 21:02:57Z vladimir $ -rev = '$Rev: 3258 $'; +rev = '$Rev: 3881 $'; D = cfg_files; D.tag = 'D'; @@ -24,57 +24,6 @@ badchanthresh.help = {'Fraction of trials with artefacts ', ... 'above which an M/EEG channel is declared as bad.'}; -chanall = cfg_const; -chanall.tag = 'type'; -chanall.name = 'All'; -chanall.val = {'all'}; - -chanmeg = cfg_const; -chanmeg.tag = 'type'; -chanmeg.name = 'MEG'; -chanmeg.val = {'MEG'}; - -chanmegplanar = cfg_const; -chanmegplanar.tag = 'type'; -chanmegplanar.name = 'MEGPLANAR'; -chanmegplanar.val = {'MEGPLANAR'}; - -chaneeg = cfg_const; -chaneeg.tag = 'type'; -chaneeg.name = 'EEG'; -chaneeg.val = {'EEG'}; - -chaneog = cfg_const; -chaneog.tag = 'type'; -chaneog.name = 'EOG'; -chaneog.val = {'EOG'}; - -chanecg = cfg_const; -chanecg.tag = 'type'; -chanecg.name = 'ECG'; -chanecg.val = {'ECG'}; - -chanemg = cfg_const; -chanemg.tag = 'type'; -chanemg.name = 'EMG'; -chanemg.val = {'EMG'}; - -chanlfp = cfg_const; -chanlfp.tag = 'type'; -chanlfp.name = 'LFP'; -chanlfp.val = {'LFP'}; - -chanfile = cfg_files; -chanfile.tag = 'file'; -chanfile.name = 'Channel file'; -chanfile.filter = 'mat'; -chanfile.num = [1 1]; - -channels = cfg_choice; -channels.tag = 'channels'; -channels.name = 'Channel selection'; -channels.values = {chanall, chanmeg, chanmegplanar, chaneeg, chaneog, chanecg, chanemg, chanlfp, chanfile}; -channels.val = {chanall}; artefact_funs = dir(fullfile(spm('dir'), 'spm_eeg_artefact_*.m')); artefact_funs = {artefact_funs(:).name}; @@ -89,7 +38,7 @@ methods = cfg_branch; methods.tag = 'methods'; methods.name = 'Method'; -methods.val = {channels, fun}; +methods.val = {spm_cfg_eeg_channel_selector, fun}; methodsrep = cfg_repeat; methodsrep.tag = 'methodsrep'; @@ -98,9 +47,8 @@ methodsrep.values = {methods}; methodsrep.num = [1 Inf]; - S = cfg_exbranch; -S.tag = 'eeg_artefact'; +S.tag = 'artefact'; S.name = 'M/EEG Artefact detection'; S.val = {D, badchanthresh, methodsrep}; S.help = {'Detect artefacts in epoched M/EEG data.'}; @@ -115,11 +63,7 @@ S.badchanthresh = job.badchanthresh; for i = 1:numel(job.methods) - if isfield(job.methods(i).channels, 'type') - S.methods(i).channels = job.methods(i).channels.type; - else - S.methods(i).channels = getfield(load(job.methods(i).channels.file{1}), 'label'); - end + S.methods(i).channels = spm_cfg_eeg_channel_selector(job.methods(i).channels); fun = fieldnames(job.methods(i).fun); fun = fun{1}; @@ -129,7 +73,7 @@ end out.D = spm_eeg_artefact(S); -out.Dfname = {out.D.fname}; +out.Dfname = {fullfile(out.D.path, out.D.fname)}; function dep = vout_eeg_artefact(job) % Output is always in field "D", no matter how job is structured diff --git a/config/spm_cfg_eeg_average.m b/config/spm_cfg_eeg_average.m index 769ef97..c69cb03 100644 --- a/config/spm_cfg_eeg_average.m +++ b/config/spm_cfg_eeg_average.m @@ -4,9 +4,9 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Stefan Kiebel -% $Id: spm_cfg_eeg_average.m 3258 2009-07-08 17:46:54Z vladimir $ +% $Id: spm_cfg_eeg_average.m 3881 2010-05-07 21:02:57Z vladimir $ -rev = '$Rev: 3258 $'; +rev = '$Rev: 3881 $'; D = cfg_files; D.tag = 'D'; D.name = 'File Name'; @@ -56,10 +56,19 @@ userobust.values = {standard, robust}; userobust.val = {standard}; +plv = cfg_menu; +plv.tag = 'plv'; +plv.name = 'Compute phase-locking value'; +plv.help = {'Compute phase-locking value rather than average the phase',... + 'This option is only relevant for TF-phase datasets'}; +plv.labels = {'Yes', 'No'}; +plv.values = {true, false}; +plv.val = {false}; + S = cfg_exbranch; -S.tag = 'eeg_average'; +S.tag = 'average'; S.name = 'M/EEG Averaging'; -S.val = {D, userobust}; +S.val = {D, userobust, plv}; S.help = {'Average epoched EEG/MEG data.'}; S.prog = @eeg_average; S.vout = @vout_eeg_average; @@ -75,8 +84,10 @@ end S.review = false; +S.circularise = job.plv; + out.D = spm_eeg_average(S); -out.Dfname = {out.D.fname}; +out.Dfname = {fullfile(out.D.path, out.D.fname)}; function dep = vout_eeg_average(job) % Output is always in field "D", no matter how job is structured diff --git a/config/spm_cfg_eeg_bc.m b/config/spm_cfg_eeg_bc.m index 02bb456..dbe18f4 100644 --- a/config/spm_cfg_eeg_bc.m +++ b/config/spm_cfg_eeg_bc.m @@ -4,7 +4,7 @@ % Copyright (C) 2009 Wellcome Trust Centre for Neuroimaging % Vladimir Litvak -% $Id: spm_cfg_eeg_bc.m 3250 2009-07-06 09:31:13Z vladimir $ +% $Id: spm_cfg_eeg_bc.m 3818 2010-04-13 14:36:31Z vladimir $ %-------------------------------------------------------------------------- % D @@ -30,7 +30,7 @@ % S %-------------------------------------------------------------------------- S = cfg_exbranch; -S.tag = 'eeg_bc'; +S.tag = 'bc'; S.name = 'M/EEG Baseline correction'; S.val = {D, time}; S.help = {'Baseline correction of M/EEG time data'}'; diff --git a/config/spm_cfg_eeg_channel_selector.m b/config/spm_cfg_eeg_channel_selector.m new file mode 100644 index 0000000..d3aa401 --- /dev/null +++ b/config/spm_cfg_eeg_channel_selector.m @@ -0,0 +1,54 @@ +function channels = spm_cfg_eeg_channel_selector(jobtree) +% generic M/EEG channel selector based on label and type +%_______________________________________________________________________ +% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging + +% Vladimir Litvak +% $Id: spm_cfg_eeg_channel_selector.m 3798 2010-03-24 12:00:07Z vladimir $ + +if nargin == 0 + chanall = cfg_const; + chanall.tag = 'all'; + chanall.name = 'All'; + chanall.val = {'all'}; + + type = cfg_menu; + type.tag = 'type'; + type.name = 'Select channels by type'; + type.help = {'Select channels by type'}; + type.labels = {'MEG', 'MEGPLANAR', 'MEGMAG', 'MEGGRAD', 'EEG', 'EOG', 'ECG', 'EMG', 'LFP', 'Other', 'REF', 'REFMAG', 'REFGRAD'}; + type.values = {'MEG', 'MEGPLANAR', 'MEGMAG', 'MEGGRAD', 'EEG', 'EOG', 'ECG', 'EMG', 'LFP', 'Other', 'REF', 'REFMAG', 'REFGRAD'}; + + chan = cfg_entry; + chan.tag = 'chan'; + chan.name = 'Custom channel'; + chan.strtype = 's'; + chan.num = [1 Inf]; + chan.help = {'Enter a single channel name.'}; + + chanfile = cfg_files; + chanfile.tag = 'chanfile'; + chanfile.name = 'Channel file'; + chanfile.filter = 'mat'; + chanfile.num = [1 1]; + + channels = cfg_repeat; + channels.tag = 'channels'; + channels.name = 'Channel selection'; + channels.values = {chanall, type, chan, chanfile}; + channels.num = [1 Inf]; + channels.val = {chanall}; +else + channels = {}; + for j = 1:numel(jobtree) + if isfield(jobtree{j}, 'type') + channels = [channels {jobtree{j}.type}]; + elseif isfield(jobtree{j}, 'all') + channels = [channels {'all'}]; + elseif isfield(jobtree{j}, 'chan') + channels = [channels {jobtree{j}.chan}]; + elseif isfield(jobtree{j}, 'chanfile') + channels = [channels getfield(load(jobtree{j}.chanfile.file{1}), 'label')]; + end + end +end \ No newline at end of file diff --git a/config/spm_cfg_eeg_contrast.m b/config/spm_cfg_eeg_contrast.m index 65ac3df..0d4428f 100644 --- a/config/spm_cfg_eeg_contrast.m +++ b/config/spm_cfg_eeg_contrast.m @@ -4,7 +4,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Stefan Kiebel -% $Id: spm_cfg_eeg_contrast.m 2200 2008-09-26 10:09:45Z stefan $ +% $Id: spm_cfg_eeg_contrast.m 3881 2010-05-07 21:02:57Z vladimir $ D = cfg_files; D.tag = 'D'; @@ -15,33 +15,42 @@ c = cfg_entry; c.tag = 'c'; -c.name = 'Contrast vector/matrix'; +c.name = 'Contrast coefficients'; c.strtype = 'r'; -c.num = [inf inf]; -c.help = {'Enter each contrast vector in a row. Each row must have ''number of epochs'' entries.'}; +c.num = [1 inf]; +c.help = {'Enter the contrast vector.'}; -yes = cfg_const; -yes.tag = 'yes'; -yes.name = 'Weight average by repetition numbers'; -yes.val = {1}; +label = cfg_entry; +label.tag = 'label'; +label.name = 'New condition label'; +label.strtype = 's'; +label.help = {'Enter the label for the condition derived by applying the contrast.'}; -no = cfg_const; -no.tag = 'no'; -no.name = 'Don''t weight averager by repetition numbers'; -no.val = {1}; +contrast = cfg_branch; +contrast.tag = 'contrast'; +contrast.name = 'Contrast'; +contrast.val = {c label}; -WeightAve = cfg_choice; -WeightAve.tag = 'WeightAve'; -WeightAve.name = 'Weight averages'; -WeightAve.values = {yes,no}; -WeightAve.val = {yes}; -WeightAve.help = {'This option will weight averages by the number of their occurences in the data set. This is only important when there are multiple occurences of a trial type, e.g. in single trial data.'}; +contrasts = cfg_repeat; +contrasts.tag = 'contrasts'; +contrasts.name = 'Contrasts'; +contrasts.help = {'Each contrast defines a new condition in the output file.'}; +contrasts.values = {contrast}; +contrasts.num = [1 Inf]; + +weight = cfg_menu; +weight.tag = 'weight'; +weight.name = 'Weight average by repetition numbers'; +weight.labels = {'yes', 'no'}; +weight.values = {1 , 0}; +weight.val = {1}; +weight.help = {'This option will weight averages by the number of their occurences in the data set. This is only important when there are multiple occurences of a trial type, e.g. in single trial data.'}; S = cfg_exbranch; -S.tag = 'eeg_contrast'; +S.tag = 'contrast'; S.name = 'M/EEG Contrast over epochs'; -S.val = {D c WeightAve}; +S.val = {D contrasts weight}; S.help = {'Computes contrasts over EEG/MEG epochs.'}; S.prog = @eeg_contrast; S.vout = @vout_eeg_contrast; @@ -50,15 +59,13 @@ function out = eeg_contrast(job) % construct the S struct S.D = job.D{1}; -S.c = job.c; -if isfield(job.WeightAve, 'yes') - S.WeightAve = 1; -else - S.WeightAve = 0; -end +S.c = cat(1, job.contrast(:).c); +S.label = {job.contrast.label}; + +S.WeightAve = job.weight; out.D = spm_eeg_weight_epochs(S); -out.Dfname = {out.D.fname}; +out.Dfname = {fullfile(out.D.path, out.D.fname)}; function dep = vout_eeg_contrast(job) % Output is always in field "D", no matter how job is structured diff --git a/config/spm_cfg_eeg_convert.m b/config/spm_cfg_eeg_convert.m index 84eabe3..0428169 100644 --- a/config/spm_cfg_eeg_convert.m +++ b/config/spm_cfg_eeg_convert.m @@ -4,7 +4,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Stefan Kiebel -% $Id: spm_cfg_eeg_convert.m 3383 2009-09-10 17:53:49Z vladimir $ +% $Id: spm_cfg_eeg_convert.m 3881 2010-05-07 21:02:57Z vladimir $ dataset = cfg_files; dataset.tag = 'dataset'; @@ -115,8 +115,9 @@ outfile.tag = 'outfile'; outfile.name = 'Output filename'; outfile.strtype = 's'; -outfile.num = [1 inf]; -outfile.help = {'Choose filename'}; +outfile.num = [0 inf]; +outfile.val = {''}; +outfile.help = {'Choose filename. Leave empty to add ''spm8_'' to the input file name.'}; datatype = cfg_menu; datatype.tag = 'datatype'; @@ -125,7 +126,7 @@ datatype.val = {'float32-le'}; datatype.values = {'float32-le','float64-le'}; datatype.help = {'Determine data type to save data in.'}; - + eventpadding = cfg_entry; eventpadding.tag = 'eventpadding'; eventpadding.name = 'Event padding'; @@ -133,10 +134,10 @@ eventpadding.val = {0}; eventpadding.num = [1 1]; eventpadding.help = {'in sec - the additional time period around each trial',... - 'for which the events are saved with the trial (to let the',... - 'user keep and use for analysis events which are outside',... - 'trial borders). Default - 0'}; - + 'for which the events are saved with the trial (to let the',... + 'user keep and use for analysis events which are outside',... + 'trial borders). Default - 0'}; + blocksize = cfg_entry; blocksize.tag = 'blocksize'; blocksize.name = 'Block size'; @@ -152,19 +153,19 @@ checkboundary.val = {1}; checkboundary.values = {1,0}; checkboundary.help = {'1 - check if there are breaks in the file and do not read',... - 'across those breaks (default).',... - '0 - ignore breaks (not recommended)'}; - + 'across those breaks (default).',... + '0 - ignore breaks (not recommended)'}; + inputformat = cfg_entry; inputformat.tag = 'inputformat'; inputformat.name = 'Input data format'; inputformat.strtype = 's'; inputformat.val = {'autodetect'}; inputformat.num = [1 inf]; -inputformat.help = {'Force the reader to assume a particular data format (usually not necessary)'}; - +inputformat.help = {'Force the reader to assume a particular data format (usually not necessary)'}; + S = cfg_exbranch; -S.tag = 'eeg_convert'; +S.tag = 'convert'; S.name = 'M/EEG Conversion'; S.val = {dataset continuous channels outfile datatype eventpadding blocksize checkboundary inputformat}; S.help = {'Converts EEG/MEG data.'}; @@ -177,7 +178,9 @@ S.dataset = job.dataset{1}; S.continuous = job.continuous; S.channels = job.channels; -S.outfile = job.outfile; +if ~isempty(job.outfile) + S.outfile = job.outfile; +end S.datatype = job.datatype; S.eventpadding = job.eventpadding; S.blocksize = job.blocksize; @@ -220,7 +223,8 @@ elseif isfield(S.channels, 'chanall') S.channels = 'all'; elseif isfield(S.channels, 'chanfile') - S.chanfile = S.channels.chanfile; + S.chanfile = S.channels.chanfile{1}; + S.channels = 'file'; end S.save = 0; S.review = 0; @@ -230,7 +234,7 @@ S = rmfield(S, 'review'); out.D = spm_eeg_convert(S); -out.Dfname = {out.D.fname}; +out.Dfname = {fullfile(out.D.path, out.D.fname)}; function dep = vout_eeg_convert(job) % Output is always in field "D", no matter how job is structured diff --git a/config/spm_cfg_eeg_convert2images.m b/config/spm_cfg_eeg_convert2images.m index c8ebd51..b5c7f0a 100644 --- a/config/spm_cfg_eeg_convert2images.m +++ b/config/spm_cfg_eeg_convert2images.m @@ -5,7 +5,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Stefan Kiebel -% $Id: spm_cfg_eeg_convert2images.m 2843 2009-03-09 16:01:44Z guillaume $ +% $Id: spm_cfg_eeg_convert2images.m 3818 2010-04-13 14:36:31Z vladimir $ Fname = cfg_files; Fname.tag = 'Fname'; @@ -40,7 +40,7 @@ Interpolate.help = {'Interpolate bad channels'}; S = cfg_exbranch; -S.tag = 'eeg_convert2images'; +S.tag = 'convert2images'; S.name = 'M/EEG Convert2Images'; S.val = {Fname n Interpolate}; S.help = {'Convert SPM M/EEG data to voxel-based images, as a time-series of 2D images'}; diff --git a/config/spm_cfg_eeg_downsample.m b/config/spm_cfg_eeg_downsample.m index 91db2db..04dcfd5 100644 --- a/config/spm_cfg_eeg_downsample.m +++ b/config/spm_cfg_eeg_downsample.m @@ -4,9 +4,9 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Stefan Kiebel -% $Id: spm_cfg_eeg_downsample.m 2225 2008-09-29 12:25:27Z stefan $ +% $Id: spm_cfg_eeg_downsample.m 3881 2010-05-07 21:02:57Z vladimir $ -rev = '$Rev: 2225 $'; +rev = '$Rev: 3881 $'; D = cfg_files; D.tag = 'D'; D.name = 'File Name'; @@ -22,7 +22,7 @@ fsample_new.help = {'Input the new sampling rate [Hz].'}; S = cfg_exbranch; -S.tag = 'eeg_downsample'; +S.tag = 'downsample'; S.name = 'M/EEG Downsampling'; S.val = {D fsample_new}; S.help = {'Downsample EEG/MEG data.'}; @@ -37,7 +37,7 @@ S.fsample_new = job.fsample_new; out.D = spm_eeg_downsample(S); -out.Dfname = {out.D.fname}; +out.Dfname = {fullfile(out.D.path, out.D.fname)}; function dep = vout_eeg_downsample(job) % Output is always in field "D", no matter how job is structured diff --git a/config/spm_cfg_eeg_epochs.m b/config/spm_cfg_eeg_epochs.m index ab1713f..935225b 100644 --- a/config/spm_cfg_eeg_epochs.m +++ b/config/spm_cfg_eeg_epochs.m @@ -4,9 +4,9 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Stefan Kiebel -% $Id: spm_cfg_eeg_epochs.m 2867 2009-03-12 10:54:56Z guillaume $ +% $Id: spm_cfg_eeg_epochs.m 3881 2010-05-07 21:02:57Z vladimir $ -rev = '$Rev: 2867 $'; +rev = '$Rev: 3881 $'; D = cfg_files; D.tag = 'D'; D.name = 'File Name'; @@ -82,7 +82,7 @@ S = cfg_exbranch; -S.tag = 'eeg_epochs'; +S.tag = 'epoch'; S.name = 'M/EEG Epoching'; S.val = {D trlchoice}; S.help = {'Epoch continuous EEG/MEG data.'}; @@ -109,7 +109,7 @@ S.save = 0; out.D = spm_eeg_epochs(S); -out.Dfname = {out.D.fname}; +out.Dfname = {fullfile(out.D.path, out.D.fname)}; function dep = vout_eeg_epochs(job) % Output is always in field "D", no matter how job is structured diff --git a/config/spm_cfg_eeg_filter.m b/config/spm_cfg_eeg_filter.m index 620d083..1069a64 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 2200 2008-09-26 10:09:45Z stefan $ +% $Id: spm_cfg_eeg_filter.m 3881 2010-05-07 21:02:57Z vladimir $ -rev = '$Rev: 2200 $'; +rev = '$Rev: 3881 $'; D = cfg_files; D.tag = 'D'; D.name = 'File Name'; @@ -17,8 +17,8 @@ typ = cfg_menu; typ.tag = 'type'; typ.name = 'Filter type'; -typ.labels = {'Butterworth'}; -typ.values = {'butterworth'}; +typ.labels = {'Butterworth', 'FIR'}; +typ.values = {'butterworth', 'fir'}; typ.val = {'butterworth'}; typ.help = {'Select the filter type.'}; @@ -37,13 +37,29 @@ PHz.num = [1 inf]; PHz.help = {'Enter the filter cutoff'}; +dir = cfg_menu; +dir.tag = 'dir'; +dir.name = 'Filter direction'; +dir.labels = {'Zero phase', 'Forward', 'Backward'}; +dir.values = {'twopass', 'onepass', 'onepass-reverse'}; +dir.val = {'twopass'}; +dir.help = {'Select the filter direction.'}; + +order = cfg_entry; +order.tag = 'order'; +order.name = 'Filter order'; +order.val = {[]}; +order.strtype = 'n'; +order.num = [0 1]; +order.help = {'Enter the filter order (leave empty for default)'}; + flt = cfg_branch; flt.tag = 'filter'; flt.name = 'Filter'; -flt.val = {typ band PHz}; +flt.val = {typ band PHz dir order}; S = cfg_exbranch; -S.tag = 'eeg_filter'; +S.tag = 'filter'; S.name = 'M/EEG Filter'; S.val = {D flt}; S.help = {'Low-pass filters EEG/MEG epoched data.'}; @@ -57,7 +73,7 @@ S.filter = job.filter; out.D = spm_eeg_filter(S); -out.Dfname = {out.D.fname}; +out.Dfname = {fullfile(out.D.path, out.D.fname)}; function dep = vout_eeg_filter(job) % Output is always in field "D", no matter how job is structured diff --git a/config/spm_cfg_eeg_fuse.m b/config/spm_cfg_eeg_fuse.m index 98e1003..56485b7 100644 --- a/config/spm_cfg_eeg_fuse.m +++ b/config/spm_cfg_eeg_fuse.m @@ -4,9 +4,9 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Vladimir Litvak -% $Id: spm_cfg_eeg_fuse.m 3447 2009-10-07 07:52:29Z vladimir $ +% $Id: spm_cfg_eeg_fuse.m 3881 2010-05-07 21:02:57Z vladimir $ -rev = '$Rev: 3447 $'; +rev = '$Rev: 3881 $'; D = cfg_files; D.tag = 'D'; D.name = 'File Names'; @@ -16,7 +16,7 @@ S = cfg_exbranch; -S.tag = 'eeg_fuse'; +S.tag = 'fuse'; S.name = 'M/EEG Fusion'; S.val = {D}; S.help = {'Fuse EEG/MEG data.'}; @@ -29,7 +29,7 @@ S.D = strvcat(job.D{:}); out.D = spm_eeg_fuse(S); -out.Dfname = {out.D.fname}; +out.Dfname = {fullfile(out.D.path, out.D.fname)}; function dep = vout_eeg_fuse(job) % Output is always in field "D", no matter how job is structured diff --git a/config/spm_cfg_eeg_grandmean.m b/config/spm_cfg_eeg_grandmean.m index 2c5a10a..a823035 100644 --- a/config/spm_cfg_eeg_grandmean.m +++ b/config/spm_cfg_eeg_grandmean.m @@ -4,7 +4,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Stefan Kiebel -% $Id: spm_cfg_eeg_grandmean.m 3531 2009-11-04 14:58:54Z guillaume $ +% $Id: spm_cfg_eeg_grandmean.m 3881 2010-05-07 21:02:57Z vladimir $ % ------------------------------------------------------------------------- % weighted Weighted average @@ -40,7 +40,7 @@ % S Grandmean %-------------------------------------------------------------------------- S = cfg_exbranch; -S.tag = 'eeg_grandmean'; +S.tag = 'grandmean'; S.name = 'M/EEG Grandmean'; S.val = {D Dout weighted}; S.help = {'Average multiple evoked responses'}; @@ -56,7 +56,7 @@ S.weighted = job.weighted; out.D = spm_eeg_grandmean(S); -out.Dfname = {out.D.fname}; +out.Dfname = {fullfile(out.D.path, out.D.fname)}; %========================================================================== function dep = vout_eeg_grandmean(job) diff --git a/config/spm_cfg_eeg_inv_headmodel.m b/config/spm_cfg_eeg_inv_headmodel.m new file mode 100644 index 0000000..fb6b2ac --- /dev/null +++ b/config/spm_cfg_eeg_inv_headmodel.m @@ -0,0 +1,262 @@ +function headmodel = spm_cfg_eeg_inv_headmodel +% configuration file for specifying the head model for source +% reconstruction +%_______________________________________________________________________ +% 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 $ + +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 results will be stored.'}; +val.val = {1}; + +comment = cfg_entry; +comment.tag = 'comment'; +comment.name = 'Comment'; +comment.strtype = 's'; +comment.help = {'User-specified information about this inversion'}; +comment.val = {''}; + +template = cfg_const; +template.tag = 'template'; +template.name = 'Template'; +template.val = {1}; + +mri = cfg_files; +mri.tag = 'mri'; +mri.name = 'Individual structural image'; +mri.filter = 'image'; +mri.ufilter = '.*'; +mri.num = [1 1]; +mri.help = {'Select the subject''s structural image'}; + +meshes = cfg_choice; +meshes.tag = 'meshes'; +meshes.name = 'Mesh source'; +meshes.values = {template, mri}; +meshes.val = {template}; + +meshres = cfg_menu; +meshres.tag = 'meshres'; +meshres.name = 'Mesh resolution'; +meshres.help = {'Specify the resolution of the cortical mesh'}; +meshres.labels = {'coarse', 'normal', 'fine'}; +meshres.values = {1, 2, 3}; +meshres.val = {2}; + +meshing = cfg_branch; +meshing.tag = 'meshing'; +meshing.name = 'Meshes'; +meshing.help = {'Create head meshes for building the head model'}; +meshing.val = {meshes, meshres}; + +fidname = cfg_entry; +fidname.tag = 'fidname'; +fidname.name = 'M/EEG fiducial label'; +fidname.strtype = 's'; +fidname.help = {'Label of a fiducial point (as specified in the M/EEG dataset)'}; + +type = cfg_entry; +type.tag = 'type'; +type.name = 'Type MNI coordinates'; +type.strtype = 'r'; +type.num = [1 3]; +type.help = {'Type the coordinates corresponding to the fiducial in the structural image.'}; + +fid = fopen(fullfile(spm('dir'), 'EEGtemplates', 'fiducials.sfp') ,'rt'); +fidtable =textscan(fid ,'%s %f %f %f'); +fclose(fid); + +select = cfg_menu; +select.tag = 'select'; +select.name = 'Select from a list'; +select.help = {'Select the corresponding fiducial point from a pre-specified list.'}; +select.labels = fidtable{1}'; +select.values = fidtable{1}'; + +specification = cfg_choice; +specification.tag = 'specification'; +specification.name = 'How to specify?'; +specification.values = {select, type}; + +fiducial = cfg_branch; +fiducial.tag = 'fiducial'; +fiducial.name = 'Fiducial'; +fiducial.help = {'Specify fiducial for coregistration'}; +fiducial.val = {fidname, specification}; + +fiducials = cfg_repeat; +fiducials.tag = 'fiducials'; +fiducials.name = 'Fiducials'; +fiducials.help = {'Specify fiducials for coregistration (at least 3 fiducials need to be specified)'}; +fiducials.num = [3 Inf]; +fiducials.values = {fiducial}; +fiducials.val = {fiducial fiducial fiducial}; + +useheadshape = cfg_menu; +useheadshape.tag = 'useheadshape'; +useheadshape.name = 'Use headshape points?'; +useheadshape.help = {'Use headshape points (if available)'}; +useheadshape.labels = {'yes', 'no'}; +useheadshape.values = {1, 0}; +useheadshape.val = {0}; + +coregspecify = cfg_branch; +coregspecify.tag = 'coregspecify'; +coregspecify.name = 'Specify coregistration parameters'; +coregspecify.val = {fiducials, useheadshape}; + +coregdefault = cfg_const; +coregdefault.tag = 'coregdefault'; +coregdefault.name = 'Sensor locations are in MNI space already'; +coregdefault.help = {'No coregistration is necessary because default EEG sensor locations were used'}; +coregdefault.val = {1}; + +coregistration = cfg_choice; +coregistration.tag = 'coregistration'; +coregistration.name = 'Coregistration'; +coregistration.values = {coregspecify, coregdefault}; +coregistration.val = {coregspecify}; + +eeg = cfg_menu; +eeg.tag = 'eeg'; +eeg.name = 'EEG head model'; +eeg.help = {'Select the head model type to use for EEG (if present)'}; +eeg.labels = {'EEG BEM', '3-Shell Sphere (experimental)'}; +eeg.values = {'EEG BEM', '3-Shell Sphere (experimental)'}; +eeg.val = {'EEG BEM'}; + +meg = cfg_menu; +meg.tag = 'meg'; +meg.name = 'MEG head model'; +meg.help = {'Select the head model type to use for MEG (if present)'}; +meg.labels = {'Single Sphere', 'MEG Local Spheres', 'Single Shell'}; +meg.values = {'Single Sphere', 'MEG Local Spheres', 'Single Shell'}; +meg.val = {'Single Sphere'}; + +forward = cfg_branch; +forward.tag = 'forward'; +forward.name = 'Forward model'; +forward.val = {eeg, meg}; + +headmodel = cfg_exbranch; +headmodel.tag = 'headmodel'; +headmodel.name = 'M/EEG head model specification'; +headmodel.val = {D, val, comment, meshing, coregistration, forward}; +headmodel.help = {'Specify M/EEG head model for forward computation'}; +headmodel.prog = @specify_headmodel; +headmodel.vout = @vout_specify_headmodel; +headmodel.modality = {'EEG'}; + +function out = specify_headmodel(job) + +mesh = spm_eeg_inv_mesh; +out.D = {}; + +%- Loop over input datasets +%-------------------------------------------------------------------------- +for i = 1:numel(job.D) + D = spm_eeg_load(job.D{i}); + + if ~isfield(D,'inv') + val = 1; + elseif numel(D.inv)1 && isfield(D{i}.inv{D{i}.val-1}, 'forward') + D{i}.inv{D{i}.val} = D{i}.inv{D{i}.val-1}; + warning(sprintf('Duplicating the last forward model for subject %d', i)); + else + error(sprintf('Forward model is missing for subject %d', i)); + end + end + + D{i}.inv{D{i}.val}.inverse = inverse; +end + +D = spm_eeg_invert(D); + +if ~iscell(D) + D = {D}; +end + +for i = 1:numel(D) + save(D{i}); +end + +out.D = job.D; + +function dep = vout_inversion(job) +% Output is always in field "D", no matter how job is structured +dep = cfg_dep; +dep.sname = 'M/EEG dataset(s) after imaging source reconstruction'; +% 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_results.m b/config/spm_cfg_eeg_inv_results.m new file mode 100644 index 0000000..f7b3f4b --- /dev/null +++ b/config/spm_cfg_eeg_inv_results.m @@ -0,0 +1,121 @@ +function results = spm_cfg_eeg_inv_results +% configuration file for creating images from results of source +% reconstruction +%_______________________________________________________________________ +% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging + +% Vladimir Litvak +% $Id: spm_cfg_eeg_inv_results.m 3976 2010-07-08 14:12:31Z karl $ + +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}; + +woi = cfg_entry; +woi.tag = 'woi'; +woi.name = 'Time window of interest'; +woi.strtype = 'r'; +woi.num = [Inf 2]; +woi.val = {[-Inf Inf]}; +woi.help = {'Time window to average over (ms)'}; + +foi = cfg_entry; +foi.tag = 'foi'; +foi.name = 'Frequency window of interest'; +foi.strtype = 'r'; +foi.num = [1 2]; +foi.val = {[0 0]}; +foi.help = {'Frequency window (Hz)'}; + +ctype = cfg_menu; +ctype.tag = 'ctype'; +ctype.name = 'Contrast type'; +ctype.help = {'Contrast type: evoked activity, induced activity or single trials.'}; +ctype.labels = {'Evoked', 'Induced', 'Single trials'}; +ctype.values = {'evoked', 'induced', 'trials'}; +ctype.val = {'evoked'}; + +space = cfg_menu; +space.tag = 'space'; +space.name = 'Image space'; +space.help = {'Image space to wrote the results in.'}; +space.labels = {'MNI', 'Native'}; +space.values = {1, 0}; +space.val = {1}; + +smoothing = cfg_entry; +smoothing.tag = 'smoothing'; +smoothing.name = 'Smoothing kernel width (mm)'; +smoothing.strtype = 'r'; +smoothing.num = [1 1]; +smoothing.val = {8}; + +results = cfg_exbranch; +results.tag = 'results'; +results.name = 'M/EEG inversion results'; +results.val = {D, val, woi, foi, ctype, space, smoothing}; +results.help = {'Generate images from the results of imaging source reconstruction'}; +results.prog = @run_results; +results.vout = @vout_results; +results.modality = {'EEG'}; + +function out = run_results(job) + +contrast = []; +contrast.fboi = job.foi; +contrast.type = job.ctype; +contrast.space = job.space; +contrast.smoothing = job.smoothing; + +files = {}; + +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 + + contrast.woi = fix(sort(job.woi,2)); + + D.inv{D.val}.contrast = contrast; + + D = spm_eeg_inv_results(D); + D = spm_eeg_inv_Mesh2Voxels(D); + + save(D); + + fname = D.inv{D.val}.contrast.fname; + for j = 1:numel(fname) + if iscell(fname{j}) + for k = 1:numel(fname{j}) + files = [files; fname{j}(k)]; + end + else + files = [files; fname(j)]; + end + end +end + +out.files = files; + +function dep = vout_results(job) +% Output is always in field "D", no matter how job is structured +dep = cfg_dep; +dep(1) = cfg_dep; +dep(1).sname = 'Exported smoothed images'; +dep(1).src_output = substruct('.','files'); +dep(1).tgt_spec = cfg_findspec({{'filter','image','strtype','e'}}); + diff --git a/config/spm_cfg_eeg_merge.m b/config/spm_cfg_eeg_merge.m index 86dfd4c..5af8d1c 100644 --- a/config/spm_cfg_eeg_merge.m +++ b/config/spm_cfg_eeg_merge.m @@ -4,9 +4,9 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Stefan Kiebel, Volkmar Glauche -% $Id: spm_cfg_eeg_merge.m 3188 2009-06-08 08:47:46Z vladimir $ +% $Id: spm_cfg_eeg_merge.m 3881 2010-05-07 21:02:57Z vladimir $ -rev = '$Rev: 3188 $'; +rev = '$Rev: 3881 $'; D = cfg_files; D.tag = 'D'; D.name = 'File Names'; @@ -55,7 +55,7 @@ 'rules have precedence. Trials not matched by any of the rules will keep their original labels.']}; S = cfg_exbranch; -S.tag = 'eeg_merge'; +S.tag = 'merge'; S.name = 'M/EEG Merging'; S.val = {D, rules}; S.help = {'Merge EEG/MEG data.'}; @@ -69,7 +69,7 @@ S.recode = job.rule; out.D = spm_eeg_merge(S); -out.Dfname = {out.D.fname}; +out.Dfname = {fullfile(out.D.path, out.D.fname)}; function dep = vout_eeg_merge(job) % Output is always in field "D", no matter how job is structured diff --git a/config/spm_cfg_eeg_montage.m b/config/spm_cfg_eeg_montage.m index 16ee9ec..94af3c3 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 2225 2008-09-29 12:25:27Z stefan $ +% $Id: spm_cfg_eeg_montage.m 3881 2010-05-07 21:02:57Z vladimir $ D = cfg_files; D.tag = 'D'; @@ -38,7 +38,7 @@ keepothers.help = {'Specify whether you want to keep channels that are not contributing to the new channels'}; S = cfg_exbranch; -S.tag = 'eeg_montage'; +S.tag = 'montage'; S.name = 'M/EEG Montage'; S.val = {D montage keepothers}; S.help = {'Apply a montage (linear transformation) to EEG/MEG data.'}; @@ -57,7 +57,7 @@ end out.D = spm_eeg_montage(S); -out.Dfname = {out.D.fname}; +out.Dfname = {fullfile(out.D.path, out.D.fname)}; function dep = vout_eeg_montage(job) % Output is always in field "D", no matter how job is structured diff --git a/config/spm_cfg_eeg_review.m b/config/spm_cfg_eeg_review.m new file mode 100644 index 0000000..456442c --- /dev/null +++ b/config/spm_cfg_eeg_review.m @@ -0,0 +1,32 @@ +function S = spm_cfg_eeg_review +% configuration file for M/EEG reviewing tool +%__________________________________________________________________________ +% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging + +% Vladimir Litvak +% $Id: spm_cfg_eeg_review.m 3881 2010-05-07 21:02:57Z vladimir $ + +rev = '$Rev: 3881 $'; + +D = cfg_files; +D.tag = 'D'; +D.name = 'File Name'; +D.filter = 'mat'; +D.num = [1 1]; +D.help = {'Select the EEG mat file.'}; + + +S = cfg_exbranch; +S.tag = 'review'; +S.name = 'M/EEG Display'; +S.val = {D}; +S.help = {'Run the reviewing tool with the given dataset as input.'}; +S.prog = @eeg_review; +S.modality = {'EEG'}; + +%========================================================================== +function eeg_review(job) + +spm_eeg_review(spm_eeg_load(job.D{1})); + + diff --git a/config/spm_cfg_eeg_tf.m b/config/spm_cfg_eeg_tf.m new file mode 100644 index 0000000..e12f75d --- /dev/null +++ b/config/spm_cfg_eeg_tf.m @@ -0,0 +1,113 @@ +function S = spm_cfg_eeg_tf +% configuration file for M/EEG time-frequency analysis +%__________________________________________________________________________ +% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging + +% Vladimir Litvak +% $Id: spm_cfg_eeg_tf.m 3818 2010-04-13 14:36:31Z vladimir $ + +rev = '$Rev: 3818 $'; + +D = cfg_files; +D.tag = 'D'; +D.name = 'File Name'; +D.filter = 'mat'; +D.num = [1 1]; +D.help = {'Select the EEG mat file.'}; + +timewin = cfg_entry; +timewin.tag = 'timewin'; +timewin.name = 'Time window'; +timewin.strtype = 'r'; +timewin.num = [1 2]; +timewin.val = {[-Inf Inf]}; +timewin.help = {'Time window (ms)'}; + +frequencies = cfg_entry; +frequencies.tag = 'frequencies'; +frequencies.name = 'Frequencies of interest'; +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'}; + +specest_funs = dir(fullfile(spm('dir'), 'spm_eeg_specest_*.m')); +specest_funs = {specest_funs(:).name}; + +phase = cfg_menu; +phase.tag = 'phase'; +phase.name = 'Save phase'; +phase.help = {'Save phase as well as power'}; +phase.labels = {'yes', 'no'}; +phase.values = {1, 0}; +phase.val = {0}; + +method = cfg_choice; +method.tag = 'method'; +method.name = 'Spectral estimation '; +for i = 1:numel(specest_funs) + method.values{i} = feval(spm_str_manip(specest_funs{i}, 'r')); +end + +S = cfg_exbranch; +S.tag = 'analysis'; +S.name = 'M/EEG Time-Frequency analysis'; +S.val = {D, spm_cfg_eeg_channel_selector, frequencies, timewin, method, phase}; +S.help = {'Perform time-frequency analysis of epoched M/EEG data.'}; +S.prog = @eeg_tf; +S.vout = @vout_eeg_tf; +S.modality = {'EEG'}; + +%========================================================================== +function out = eeg_tf(job) +% construct the S struct +S = []; +S.D = job.D{1}; + +S.channels = spm_cfg_eeg_channel_selector(job.channels); + +S.frequencies = job.frequencies; +S.timewin = job.timewin; +S.phase = job.phase; + +S.method = cell2mat(fieldnames(job.method)); +S.settings = getfield(job.method, S.method); + +[Dtf, Dtph] = spm_eeg_tf(S); + +out.Dtf = Dtf; +out.Dtfname = {Dtf.fname}; + +out.Dtph = Dtph; +if ~isempty(Dtph) + out.Dtphname = {Dtph.fname}; +else + out.Dtphname = {''}; +end + +%========================================================================== +function dep = vout_eeg_tf(job) +% return dependencies +dep(1) = cfg_dep; +dep(1).sname = 'M/EEG time-frequency power dataset'; +dep(1).src_output = substruct('.','Dtf'); +% this can be entered into any evaluated input +dep(1).tgt_spec = cfg_findspec({{'strtype','e'}}); + +dep(2) = cfg_dep; +dep(2).sname = 'M/EEG time-frequency power dataset'; +dep(2).src_output = substruct('.','Dtfname'); +% this can be entered into any file selector +dep(2).tgt_spec = cfg_findspec({{'filter','mat'}}); + +dep(3) = cfg_dep; +dep(3).sname = 'M/EEG time-frequency phase dataset'; +dep(3).src_output = substruct('.','Dtph'); +% this can be entered into any evaluated input +dep(3).tgt_spec = cfg_findspec({{'strtype','e'}}); + +dep(4) = cfg_dep; +dep(4).sname = 'M/EEG time-frequency phase dataset'; +dep(4).src_output = substruct('.','Dtphname'); +% this can be entered into any file selector +dep(4).tgt_spec = cfg_findspec({{'filter','mat'}}); diff --git a/config/spm_cfg_eeg_tf_rescale.m b/config/spm_cfg_eeg_tf_rescale.m index 357c166..a494105 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 3204 2009-06-15 14:45:25Z guillaume $ +% $Id: spm_cfg_eeg_tf_rescale.m 3931 2010-06-16 15:28:54Z vladimir $ %-------------------------------------------------------------------------- % D @@ -16,6 +16,17 @@ D.num = [1 1]; D.help = {'Select the M/EEG mat file.'}; +%-------------------------------------------------------------------------- +% Db +%-------------------------------------------------------------------------- +Db = cfg_files; +Db.tag = 'Db'; +Db.name = 'External baseline dataset'; +Db.filter = 'mat'; +Db.num = [0 1]; +Db.val = {[]}; +Db.help = {'Select the baseline M/EEG mat file. Leave empty to use the input dataset'}; + %-------------------------------------------------------------------------- % Sbaseline %-------------------------------------------------------------------------- @@ -26,13 +37,22 @@ Sbaseline.strtype = 'e'; Sbaseline.num = [1 2]; +%-------------------------------------------------------------------------- +% baseline +%-------------------------------------------------------------------------- +baseline = cfg_branch; +baseline.tag = 'baseline'; +baseline.name = 'Baseline'; +baseline.help = {'Baseline parameters.'}; +baseline.val = {Sbaseline, Db}; + %-------------------------------------------------------------------------- % method_logr %-------------------------------------------------------------------------- method_logr = cfg_branch; method_logr.tag = 'LogR'; method_logr.name = 'Log Ratio'; -method_logr.val = {Sbaseline}; +method_logr.val = {baseline}; method_logr.help = {'Log Ratio.'}; %-------------------------------------------------------------------------- @@ -41,7 +61,7 @@ method_diff = cfg_branch; method_diff.tag = 'Diff'; method_diff.name = 'Difference'; -method_diff.val = {Sbaseline}; +method_diff.val = {baseline}; method_diff.help = {'Difference.'}; %-------------------------------------------------------------------------- @@ -50,7 +70,7 @@ method_rel = cfg_branch; method_rel.tag = 'Rel'; method_rel.name = 'Relative'; -method_rel.val = {Sbaseline}; +method_rel.val = {baseline}; method_rel.help = {'Relative.'}; %-------------------------------------------------------------------------- @@ -85,7 +105,7 @@ % S %-------------------------------------------------------------------------- S = cfg_exbranch; -S.tag = 'eeg_tf_rescale'; +S.tag = 'rescale'; S.name = 'M/EEG Time-Frequency Rescale'; S.val = {D, method}; S.help = {'Rescale (avg) spectrogram with nonlinear and/or difference operator.' @@ -107,7 +127,10 @@ S.tf.method = S.tf.method{1}; switch lower(S.tf.method) case {'logr','diff', 'rel'} - S.tf.Sbaseline = job.method.(S.tf.method).Sbaseline; + 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}; + end case {'log', 'sqrt'} end diff --git a/config/spm_cfg_factorial_design.m b/config/spm_cfg_factorial_design.m index 5337518..b2a51d6 100644 --- a/config/spm_cfg_factorial_design.m +++ b/config/spm_cfg_factorial_design.m @@ -4,7 +4,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Will Penny -% $Id: spm_cfg_factorial_design.m 3589 2009-11-20 17:17:41Z guillaume $ +% $Id: spm_cfg_factorial_design.m 3900 2010-05-25 16:17:13Z guillaume $ % --------------------------------------------------------------------- % dir Directory @@ -70,12 +70,32 @@ 'Restricted Maximum Likelihood (REML): The ensuing covariance components will be estimated using ReML in spm_spm (assuming the same for all responsive voxels) and used to adjust the statistics and degrees of freedom during inference. By default spm_spm will use weighted least squares to produce Gauss-Markov or Maximum likelihood estimators using the non-sphericity structure specified at this stage. The components will be found in SPM.xVi and enter the estimation procedure exactly as the serial correlations in fMRI models.' '' }'; -dept.labels = { +dept.labels = { 'Yes' 'No' }'; -dept.values = {0 1}; -dept.def = @(val)spm_get_defaults('stats.fact.dept', val{:}); +dept.values = {0 1}; +dept.val = {0}; +% --------------------------------------------------------------------- +% deptn Independence (default is 'No') +% --------------------------------------------------------------------- +deptn = cfg_menu; +deptn.tag = 'dept'; +deptn.name = 'Independence'; +deptn.help = { + 'By default, the measurements are assumed to be dependent between levels. ' + '' + 'If you change this option to allow for dependencies, this will violate the assumption of sphericity. It would therefore be an example of non-sphericity. One such example would be where you had repeated measurements from the same subjects - it may then be the case that, over subjects, measure 1 is correlated to measure 2. ' + '' + 'Restricted Maximum Likelihood (REML): The ensuing covariance components will be estimated using ReML in spm_spm (assuming the same for all responsive voxels) and used to adjust the statistics and degrees of freedom during inference. By default spm_spm will use weighted least squares to produce Gauss-Markov or Maximum likelihood estimators using the non-sphericity structure specified at this stage. The components will be found in SPM.xVi and enter the estimation procedure exactly as the serial correlations in fMRI models.' + '' +}'; +deptn.labels = { + 'Yes' + 'No' +}'; +deptn.values = {0 1}; +deptn.val = {1}; % --------------------------------------------------------------------- % variance Variance @@ -98,7 +118,7 @@ 'Unequal' }'; variance.values = {0 1}; -variance.def = @(val)spm_get_defaults('stats.fact.variance', val{:}); +variance.val = {1}; % --------------------------------------------------------------------- % gmsca Grand mean scaling % --------------------------------------------------------------------- @@ -118,7 +138,7 @@ 'Yes' }'; gmsca.values = {0 1}; -gmsca.def = @(val)spm_get_defaults('stats.fact.t2.gmsca', val{:}); +gmsca.val = {0}; % --------------------------------------------------------------------- % ancova ANCOVA % --------------------------------------------------------------------- @@ -136,7 +156,7 @@ 'Yes' }'; ancova.values = {0 1}; -ancova.def = @(val)spm_get_defaults('stats.fact.ancova', val{:}); +ancova.val = {0}; % --------------------------------------------------------------------- % t2 Two-sample t-test % --------------------------------------------------------------------- @@ -222,7 +242,7 @@ 'No centering' }'; iCC.values = {1 5}; -iCC.def = @(val)spm_get_defaults('stats.fact.mcov.iCC', val{:}); +iCC.val = {1}; % --------------------------------------------------------------------- % mcov Covariate % --------------------------------------------------------------------- @@ -251,7 +271,7 @@ 'intercept may be omitted.']}; incint.labels = {'Include Intercept','Omit Intercept'}; incint.values = {1,0}; -incint.def = @(val)spm_get_defaults('stats.fact.mreg_int', val{:}); +incint.val = {1}; % --------------------------------------------------------------------- % mreg Multiple regression % --------------------------------------------------------------------- @@ -331,6 +351,14 @@ icell.val = {levels scans }; icell.help = {'Enter data for a cell in your design'}; % --------------------------------------------------------------------- +% scell Cell +% --------------------------------------------------------------------- +scell = cfg_branch; +scell.tag = 'icell'; +scell.name = 'Cell'; +scell.val = {scans }; +scell.help = {'Enter data for a cell in your design'}; +% --------------------------------------------------------------------- % generic Specify cells % --------------------------------------------------------------------- generic1 = cfg_repeat; @@ -343,6 +371,28 @@ generic1.values = {icell }; generic1.num = [1 Inf]; % --------------------------------------------------------------------- +% generic Specify cells +% --------------------------------------------------------------------- +generic2 = cfg_repeat; +generic2.tag = 'generic'; +generic2.name = 'Specify cells'; +generic2.help = { + 'Enter the scans a cell at a time' + '' +}'; +generic2.values = {scell }; +generic2.num = [1 Inf]; +% --------------------------------------------------------------------- +% anova ANOVA +% --------------------------------------------------------------------- +anova = cfg_branch; +anova.tag = 'anova'; +anova.name = 'One-way ANOVA'; +anova.val = {generic2 dept variance gmsca ancova}; +anova.help = { + 'One-way Analysis of Variance (ANOVA)' +}'; +% --------------------------------------------------------------------- % fd Full factorial % --------------------------------------------------------------------- fd = cfg_branch; @@ -445,7 +495,7 @@ imatrix = cfg_entry; imatrix.tag = 'imatrix'; imatrix.name = 'Factor matrix'; -imatrix.help = {'Specify factor/level matrix as a nscan-by-4 matrix. Note that the first row of I is reserved for the internal replication factor and must not be used for experimental factors.'}; +imatrix.help = {'Specify factor/level matrix as a nscan-by-4 matrix. Note that the first column of I is reserved for the internal replication factor and must not be used for experimental factors.'}; imatrix.strtype = 'e'; imatrix.num = [Inf Inf]; % --------------------------------------------------------------------- @@ -515,6 +565,16 @@ maininters.values = {fmain inter }; maininters.num = [1 Inf]; % --------------------------------------------------------------------- +% anovaw ANOVA within subject +% --------------------------------------------------------------------- +anovaw = cfg_branch; +anovaw.tag = 'anovaw'; +anovaw.name = 'One-way ANOVA - within subject'; +anovaw.val = {generic1 deptn variance gmsca ancova}; +anovaw.help = { + 'One-way Analysis of Variance (ANOVA) - within subject' +}'; +% --------------------------------------------------------------------- % fblock Flexible factorial % --------------------------------------------------------------------- fblock = cfg_branch; @@ -541,14 +601,17 @@ des.name = 'Design'; des.val = {t1 }; des.help = {''}; -des.values = {t1 t2 pt mreg fd fblock }; +des.values = {t1 t2 pt mreg anova anovaw fd fblock }; % --------------------------------------------------------------------- % c Vector % --------------------------------------------------------------------- c = cfg_entry; c.tag = 'c'; c.name = 'Vector'; -c.help = {'Vector of covariate values'}; +c.help = { + 'Vector of covariate values.' + 'Enter the covariate values ''''per subject'''' (i.e. all for subject 1, then all for subject 2, etc). Importantly, the ordering of the cells of a factorial design has to be the same for all subjects in order to be consistent with the ordering of the covariate values.' +}'; c.strtype = 'e'; c.num = [Inf 1]; % --------------------------------------------------------------------- @@ -577,7 +640,7 @@ 'With Factor 3' }'; iCFI.values = {1 2 3 4}; -iCFI.def = @(val)spm_get_defaults('stats.fact.iCFI', val{:}); +iCFI.val = {1}; % --------------------------------------------------------------------- % iCC Centering % --------------------------------------------------------------------- @@ -599,7 +662,7 @@ 'GM' }'; iCC.values = {1 2 3 4 5 6 7 8}; -iCC.def = @(val)spm_get_defaults('stats.fact.iCC', val{:}); +iCC.val = {1}; % --------------------------------------------------------------------- % cov Covariate % --------------------------------------------------------------------- @@ -640,7 +703,7 @@ }'; athresh.strtype = 'e'; athresh.num = [1 1]; -athresh.def = @(val)spm_get_defaults('stats.fact.athresh', val{:}); +athresh.val = {100}; % --------------------------------------------------------------------- % tma Absolute % --------------------------------------------------------------------- @@ -666,7 +729,7 @@ }'; rthresh.strtype = 'e'; rthresh.num = [1 1]; -rthresh.def = @(val)spm_get_defaults('stats.fact.rthresh', val{:}); +rthresh.val = {.8}; % --------------------------------------------------------------------- % tmr Relative % --------------------------------------------------------------------- @@ -713,7 +776,7 @@ 'No' }'; im.values = {1 0}; -im.def = @(val)spm_get_defaults('stats.fact.imask', val{:}); +im.val = {1}; % --------------------------------------------------------------------- % em Explicit Mask % --------------------------------------------------------------------- @@ -821,7 +884,7 @@ }'; gmscv.strtype = 'e'; gmscv.num = [Inf 1]; -gmscv.def = @(val)spm_get_defaults('stats.fact.gmsca', val{:}); +gmscv.val = {50}; % --------------------------------------------------------------------- % gmsca_yes Yes % --------------------------------------------------------------------- @@ -869,7 +932,7 @@ 'ANCOVA' }'; glonorm.values = {1 2 3}; -glonorm.def = @(val)spm_get_defaults('stats.fact.glonorm', val{:}); +glonorm.val = {1}; % --------------------------------------------------------------------- % globalm Global normalisation % --------------------------------------------------------------------- diff --git a/config/spm_cfg_fmri_design.m b/config/spm_cfg_fmri_design.m index d2cb3d2..4ae5498 100644 --- a/config/spm_cfg_fmri_design.m +++ b/config/spm_cfg_fmri_design.m @@ -1,12 +1,11 @@ function fmri_design = spm_cfg_fmri_design -% SPM Configuration file -% automatically generated by the MATLABBATCH utility function GENCODE +% SPM Configuration file for fMRI model specification (design only) %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_cfg_fmri_design.m 2222 2008-09-29 11:08:47Z volkmar $ +% $Id: spm_cfg_fmri_design.m 3691 2010-01-20 17:08:30Z guillaume $ -rev = '$Rev: 2222 $'; +rev = '$Rev: 3691 $'; % --------------------------------------------------------------------- % dir Directory % --------------------------------------------------------------------- @@ -138,7 +137,7 @@ '6th order Time Modulation' }'; tmod.values = {0 1 2 3 4 5 6}; -tmod.def = @(val)spm_get_defaults('stats.fmri.cond.tmod', val{:}); +tmod.val = {0}; % --------------------------------------------------------------------- % name Name % --------------------------------------------------------------------- @@ -392,7 +391,7 @@ 'Time and Dispersion derivatives' }'; derivs.values = {[0 0] [1 0] [1 1]}; -derivs.def = @(val)spm_get_defaults('stats.fmri.hrf.derivs', val{:}); +derivs.val = {[0 0]}; % --------------------------------------------------------------------- % hrf Canonical HRF % --------------------------------------------------------------------- @@ -531,7 +530,7 @@ 'Model Interactions' }'; volt.values = {1 2}; -volt.def = @(val)spm_get_defaults('stats.fmri.volt', val{:}); +volt.val = {1}; % --------------------------------------------------------------------- % global Global normalisation % --------------------------------------------------------------------- @@ -547,7 +546,7 @@ 'Scaling' 'None' }'; -xGlobal.def = @(val)spm_get_defaults('stats.fmri.global', val{:}); +xGlobal.val = {'None'}; % --------------------------------------------------------------------- % cvi Serial correlations % --------------------------------------------------------------------- diff --git a/config/spm_cfg_fmri_est.m b/config/spm_cfg_fmri_est.m index ad468d4..801f4b3 100644 --- a/config/spm_cfg_fmri_est.m +++ b/config/spm_cfg_fmri_est.m @@ -1,12 +1,10 @@ function fmri_est = spm_cfg_fmri_est -% SPM Configuration file -% automatically generated by the MATLABBATCH utility function GENCODE +% SPM Configuration file for Model Estimation %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_cfg_fmri_est.m 2928 2009-03-24 08:54:32Z lee $ +% $Id: spm_cfg_fmri_est.m 3753 2010-03-05 13:06:47Z guillaume $ -rev = '$Rev: 2928 $'; % --------------------------------------------------------------------- % spmmat Select SPM.mat % --------------------------------------------------------------------- @@ -17,7 +15,7 @@ 'Select the SPM.mat file that contains the design specification. ' 'The directory containing this file is known as the input directory.' }'; -spmmat.filter = 'mat'; +spmmat.filter = 'mat'; spmmat.ufilter = '^SPM\.mat$'; spmmat.num = [1 1]; % --------------------------------------------------------------------- @@ -149,7 +147,7 @@ 'Global' 'Uninformative' }'; -signal.def = @(val)spm_get_defaults('stats.est.signal', val{:}); +signal.val = {'UGL'}; % --------------------------------------------------------------------- % ARP AR model order % --------------------------------------------------------------------- @@ -165,7 +163,7 @@ }'; ARP.strtype = 'e'; ARP.num = [Inf 1]; -ARP.def = @(val)spm_get_defaults('stats.est.ARP', val{:}); +ARP.val = {3}; % --------------------------------------------------------------------- % UGL UGL % --------------------------------------------------------------------- @@ -353,24 +351,21 @@ '' 'To use option (3) you must have already estimated the model using option (1). That is, for second-level models you must run a ReML estimation before running a Bayesian estimation. This is not necessary for option (2). Bayesian estimation of 1st-level models using VB does not require a prior ReML estimation.' }'; -method.values = {Classical Bayesian Bayesian2 }; +method.values = {Classical Bayesian Bayesian2}; % --------------------------------------------------------------------- % fmri_est Model estimation % --------------------------------------------------------------------- -fmri_est = cfg_exbranch; -fmri_est.tag = 'fmri_est'; -fmri_est.name = 'Model estimation'; -fmri_est.val = {spmmat method }; -fmri_est.help = {'Model parameters can be estimated using classical (ReML - Restricted Maximum Likelihood) or Bayesian algorithms. After parameter estimation, the RESULTS button can be used to specify contrasts that will produce Statistical Parametric Maps (SPMs) or Posterior Probability Maps (PPMs) and tables of statistics.'}; -fmri_est.prog = @spm_run_fmri_est; -fmri_est.vout = @vout_stats; -fmri_est.modality = { - 'FMRI' - 'PET' -}'; -%------------------------------------------------------------------------- +fmri_est = cfg_exbranch; +fmri_est.tag = 'fmri_est'; +fmri_est.name = 'Model estimation'; +fmri_est.val = {spmmat method }; +fmri_est.help = {'Model parameters can be estimated using classical (ReML - Restricted Maximum Likelihood) or Bayesian algorithms. After parameter estimation, the RESULTS button can be used to specify contrasts that will produce Statistical Parametric Maps (SPMs) or Posterior Probability Maps (PPMs) and tables of statistics.'}; +fmri_est.prog = @spm_run_fmri_est; +fmri_est.vout = @vout_stats; +fmri_est.modality = {'FMRI' 'PET' 'EEG'}; + -%------------------------------------------------------------------------- +%========================================================================== function dep = vout_stats(job) dep(1) = cfg_dep; dep(1).sname = 'SPM.mat File'; diff --git a/config/spm_cfg_fmri_spec.m b/config/spm_cfg_fmri_spec.m index 6de4114..099accc 100644 --- a/config/spm_cfg_fmri_spec.m +++ b/config/spm_cfg_fmri_spec.m @@ -1,12 +1,11 @@ function fmri_spec = spm_cfg_fmri_spec -% SPM Configuration file -% automatically generated by the MATLABBATCH utility function GENCODE +% SPM Configuration file for fMRI model specification %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_cfg_fmri_spec.m 2222 2008-09-29 11:08:47Z volkmar $ +% $Id: spm_cfg_fmri_spec.m 3691 2010-01-20 17:08:30Z guillaume $ -rev = '$Rev: 2222 $'; +rev = '$Rev: 3691 $'; % --------------------------------------------------------------------- % dir Directory % --------------------------------------------------------------------- @@ -139,7 +138,7 @@ '6th order Time Modulation' }'; tmod.values = {0 1 2 3 4 5 6}; -tmod.def = @(val)spm_get_defaults('stats.fmri.cond.tmod', val{:}); +tmod.val = {0}; % --------------------------------------------------------------------- % name Name % --------------------------------------------------------------------- @@ -393,7 +392,7 @@ 'Time and Dispersion derivatives' }'; derivs.values = {[0 0] [1 0] [1 1]}; -derivs.def = @(val)spm_get_defaults('stats.fmri.hrf.derivs', val{:}); +derivs.val = {[0 0]}; % --------------------------------------------------------------------- % hrf Canonical HRF % --------------------------------------------------------------------- @@ -532,7 +531,7 @@ 'Model Interactions' }'; volt.values = {1 2}; -volt.def = @(val)spm_get_defaults('stats.fmri.volt', val{:}); +volt.val = {1}; % --------------------------------------------------------------------- % global Global normalisation % --------------------------------------------------------------------- @@ -548,7 +547,7 @@ 'Scaling' 'None' }'; -xGlobal.def = @(val)spm_get_defaults('stats.fmri.global', val{:}); +xGlobal.val = {'None'}; % --------------------------------------------------------------------- % mask Explicit mask % --------------------------------------------------------------------- diff --git a/config/spm_cfg_imcalc.m b/config/spm_cfg_imcalc.m index f9050d1..0c878f4 100644 --- a/config/spm_cfg_imcalc.m +++ b/config/spm_cfg_imcalc.m @@ -1,12 +1,10 @@ function imcalc = spm_cfg_imcalc -% SPM Configuration file -% automatically generated by the MATLABBATCH utility function GENCODE +% SPM Configuration file for ImCalc %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_cfg_imcalc.m 2021 2008-08-27 10:05:32Z volkmar $ +% $Id: spm_cfg_imcalc.m 3736 2010-02-23 15:08:55Z guillaume $ -rev = '$Rev: 2021 $'; % --------------------------------------------------------------------- % input Input Images % --------------------------------------------------------------------- @@ -26,7 +24,7 @@ output.help = {'The output image is written to current working directory unless a valid full pathname is given. If a path name is given here, the output directory setting will be ignored.'}; output.strtype = 's'; output.num = [1 Inf]; -output.def = @(val)spm_get_defaults('imcalc.output', val{:}); +output.val = {'output.img'}; % --------------------------------------------------------------------- % outdir Output Directory % --------------------------------------------------------------------- @@ -67,12 +65,12 @@ dmtx.tag = 'dmtx'; dmtx.name = 'Data Matrix'; dmtx.help = {'If the dmtx flag is set, then images are read into a data matrix X (rather than into separate variables i1, i2, i3,...). The data matrix should be referred to as X, and contains images in rows. Computation is plane by plane, so in data-matrix mode, X is a NxK matrix, where N is the number of input images [prod(size(Vi))], and K is the number of voxels per plane [prod(Vi(1).dim(1:2))].'}; -dmtx.labels = { +dmtx.labels = { 'No - don''t read images into data matrix' 'Yes - read images into data matrix' }'; dmtx.values = {0 1}; -dmtx.def = @(val)spm_get_defaults('imcalc.dmtx', val{:}); +dmtx.val = {0}; % --------------------------------------------------------------------- % mask Masking % --------------------------------------------------------------------- @@ -86,7 +84,7 @@ 'NaNs should be zeroed' }'; mask.values = {0 1 -1}; -mask.def = @(val)spm_get_defaults('imcalc.mask', val{:}); +mask.val = {0}; % --------------------------------------------------------------------- % interp Interpolation % --------------------------------------------------------------------- @@ -116,7 +114,7 @@ '7th Degree Sinc' }'; interp.values = {0 1 -2 -3 -4 -5 -6 -7}; -interp.def = @(val)spm_get_defaults('imcalc.interp', val{:}); +interp.val = {1}; % --------------------------------------------------------------------- % dtype Data Type % --------------------------------------------------------------------- @@ -124,7 +122,7 @@ dtype.tag = 'dtype'; dtype.name = 'Data Type'; dtype.help = {'Data-type of output image'}; -dtype.labels = { +dtype.labels = { 'UINT8 - unsigned char' 'INT16 - signed short' 'INT32 - signed int' @@ -133,7 +131,7 @@ }'; dtype.values = {spm_type('uint8') spm_type('int16') spm_type('int32') ... spm_type('float32') spm_type('float64')}; -dtype.def = @(val)spm_get_defaults('imcalc.dtype', val{:}); +dtype.val = {spm_type('int16')}; % --------------------------------------------------------------------- % options Options % --------------------------------------------------------------------- @@ -150,17 +148,38 @@ imcalc.name = 'Image Calculator'; imcalc.val = {input output outdir expression options }; imcalc.help = {'The image calculator is for performing user-specified algebraic manipulations on a set of images, with the result being written out as an image. The user is prompted to supply images to work on, a filename for the output image, and the expression to evaluate. The expression should be a standard MATLAB expression, within which the images should be referred to as i1, i2, i3,... etc.'}; -imcalc.prog = @spm_imcalc_ui; +imcalc.prog = @my_spm_imcalc_ui; imcalc.vout = @vout; -% --------------------------------------------------------------------- -% --------------------------------------------------------------------- +% ===================================================================== +function out = my_spm_imcalc_ui(job) +%-Decompose job structure and run spm_imcalc_ui with arguments +%---------------------------------------------------------------------- +flags = {job.options.dmtx, job.options.mask, job.options.dtype, job.options.interp}; +[p,nam,ext,num] = spm_fileparts(job.output); +if isempty(p) + if isempty(job.outdir{1}) + p = pwd; + else + p = job.outdir{1}; + end +end +if isempty(ext) + ext = ['.' spm_get_defaults('images.format')]; +end +if isempty(strfind(ext,',')) + ext = [ext ',1']; +end +out.files{1} = fullfile(p,[nam ext num]); +spm_imcalc_ui(strvcat(job.input{:}),out.files{1},job.expression,flags); + +% ===================================================================== function dep = vout(job) dep = cfg_dep; if ~ischar(job.output) || strcmp(job.output, '') - dep.sname = 'Imcalc Computed Image'; + dep.sname = 'Imcalc Computed Image'; else - dep.sname = sprintf('Imcalc Computed Image: %s', job.output); + dep.sname = sprintf('Imcalc Computed Image: %s', job.output); end dep.src_output = substruct('.','files'); dep.tgt_spec = cfg_findspec({{'filter','image','strtype','e'}}); diff --git a/config/spm_cfg_minc.m b/config/spm_cfg_minc.m index 255b1b8..47f9e6e 100644 --- a/config/spm_cfg_minc.m +++ b/config/spm_cfg_minc.m @@ -1,12 +1,11 @@ function minc = spm_cfg_minc -% SPM Configuration file -% automatically generated by the MATLABBATCH utility function GENCODE +% SPM Configuration file for MINC Import %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_cfg_minc.m 1987 2008-08-08 10:42:23Z volkmar $ +% $Id: spm_cfg_minc.m 3691 2010-01-20 17:08:30Z guillaume $ -rev = '$Rev: 1987 $'; +rev = '$Rev: 3691 $'; % --------------------------------------------------------------------- % data MINC files % --------------------------------------------------------------------- @@ -33,23 +32,23 @@ }'; dtype.values = {spm_type('uint8') spm_type('int16') spm_type('int32') ... spm_type('float32') spm_type('float64')}; -dtype.def = @(val)spm_get_defaults('minc.dtype', val{:}); +dtype.val = {spm_type('int16')}; % --------------------------------------------------------------------- -% ext NIFTI Type +% ext Output image format % --------------------------------------------------------------------- ext = cfg_menu; ext.tag = 'ext'; -ext.name = 'NIFTI Type'; +ext.name = 'Output image format'; ext.help = {'Output files can be written as .img + .hdr, or the two can be combined into a .nii file.'}; ext.labels = { - '.nii only' - '.img + .hdr' + 'Two file (img+hdr) NIfTI' + 'Single file (nii) NIfTI' }'; ext.values = { - '.nii' - '.img' + 'img' + 'nii' }'; -ext.def = @(val)spm_get_defaults('minc.ext', val{:}); +ext.def = @(val)spm_get_defaults('images.format', val{:}); % --------------------------------------------------------------------- % opts Options % --------------------------------------------------------------------- diff --git a/config/spm_cfg_normalise.m b/config/spm_cfg_normalise.m index 60a4f16..8c04866 100644 --- a/config/spm_cfg_normalise.m +++ b/config/spm_cfg_normalise.m @@ -4,9 +4,9 @@ %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_cfg_normalise.m 3577 2009-11-18 16:13:00Z volkmar $ +% $Id: spm_cfg_normalise.m 3804 2010-03-31 16:16:21Z ged $ -rev = '$Rev: 3577 $'; +rev = '$Rev: 3804 $'; % --------------------------------------------------------------------- % source Source Image % --------------------------------------------------------------------- @@ -238,10 +238,20 @@ interp.tag = 'interp'; interp.name = 'Interpolation'; interp.help = { - 'The method by which the images are sampled when being written in a different space.' - ' Nearest Neighbour: - Fastest, but not normally recommended.' - ' Bilinear Interpolation: - OK for PET, or realigned fMRI.' - ' B-spline Interpolation: - Better quality (but slower) interpolation/* \cite{thevenaz00a}*/, especially with higher degree splines. Do not use B-splines when there is any region of NaN or Inf in the images. ' + ['The method by which the images are sampled when ' ... + 'being written in a different space. ' ... + '(Note that Inf or NaN values are treated as zero, ' ... + 'rather than as missing data)'] + ' Nearest Neighbour:' + ' - Fastest, but not normally recommended.' + ' Bilinear Interpolation:' + ' - OK for PET, realigned fMRI, or segmentations' + ' B-spline Interpolation:' + [' - Better quality (but slower) interpolation' ... + '/* \cite{thevenaz00a}*/, especially with higher ' ... + 'degree splines. Can produce values outside the ' ... + 'original range (e.g. small negative values from an ' ... + 'originally all positive image).'] }'; interp.labels = { 'Nearest neighbour' @@ -263,8 +273,8 @@ wrap.name = 'Wrapping'; wrap.help = { 'These are typically:' - ' No wrapping: for PET or images that have already been spatially transformed. ' - ' Wrap in Y: for (un-resliced) MRI where phase encoding is in the Y direction (voxel space).' + ' No wrapping: for PET or images that have already been spatially transformed. ' + ' Wrap in Y: for (un-resliced) MRI where phase encoding is in the Y direction (voxel space).' }'; wrap.labels = { 'No wrap' diff --git a/config/spm_cfg_realign.m b/config/spm_cfg_realign.m index 4c17cd3..3ec1905 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 2342 2008-10-15 11:41:13Z volkmar $ +% $Id: spm_cfg_realign.m 3804 2010-03-31 16:16:21Z ged $ -rev = '$Rev: 2342 $'; +rev = '$Rev: 3804 $'; % --------------------------------------------------------------------- % data Session % --------------------------------------------------------------------- @@ -196,7 +196,7 @@ interp = cfg_menu; interp.tag = 'interp'; interp.name = 'Interpolation'; -interp.help = {'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. Fourier Interpolation/* \cite{eddy96,cox99}*/ is another option, but note that it is only implemented for purely rigid body transformations. Voxel sizes must all be identical and isotropic.'}; +interp.help = {'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. Fourier Interpolation/* \cite{eddy96,cox99}*/ is another option, but note that it is only implemented for purely rigid body transformations. Voxel sizes must all be identical and isotropic.'}; interp.labels = { 'Nearest neighbour' 'Trilinear' diff --git a/config/spm_cfg_realignunwarp.m b/config/spm_cfg_realignunwarp.m index f3c5916..6e2d1df 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 2086 2008-09-12 10:30:21Z volkmar $ +% $Id: spm_cfg_realignunwarp.m 3804 2010-03-31 16:16:21Z ged $ -rev = '$Rev: 2086 $'; +rev = '$Rev: 3804 $'; % --------------------------------------------------------------------- % scans Images % --------------------------------------------------------------------- @@ -114,12 +114,7 @@ einterp = cfg_menu; einterp.tag = 'einterp'; einterp.name = 'Interpolation'; -einterp.help = { - 'The method by which the images are sampled when being written in a different space. ' - ' Nearest Neighbour - Fastest, but not normally recommended. ' - ' Bilinear Interpolation - OK for PET, or realigned fMRI. ' - ' B-spline Interpolation/* \cite{thevenaz00a}*/ - Better quality (but slower) interpolation, especially with higher degree splines. Do not use B-splines when there is any region of NaN or Inf in the images. ' -}'; +einterp.help = {'The method by which the images are sampled when estimating the optimum transformation. Higher degree interpolation methods provide the better interpolation, but they are slower because they use more neighbouring voxels /* \cite{thevenaz00a,unser93a,unser93b}*/. '}; einterp.labels = { 'Nearest neighbour' 'Trilinear' @@ -140,10 +135,10 @@ ewrap.name = 'Wrapping'; ewrap.help = { 'These are typically: ' - ' No wrapping - for images that have already ' - ' been spatially transformed. ' - ' Wrap in Y - for (un-resliced) MRI where phase encoding ' - ' is in the Y direction (voxel space).' + ['* No wrapping - for images that have already been ' ... + 'spatially transformed.'] + ['* Wrap in Y - for (un-resliced) MRI where phase ' ... + 'encoding is in the Y direction (voxel space).'] }'; ewrap.labels = { 'No wrap' @@ -370,12 +365,7 @@ rinterp = cfg_menu; rinterp.tag = 'rinterp'; rinterp.name = 'Interpolation'; -rinterp.help = { - 'The method by which the images are sampled when being written in a different space. ' - ' Nearest Neighbour - Fastest, but not normally recommended.' - ' Bilinear Interpolation - OK for PET, or realigned fMRI. B-spline Interpolation/*\cite{thevenaz00a}*/' - ' - Better quality (but slower) interpolation, especially with higher degree splines. Do not use B-splines when there is any region of NaN or Inf in the images. ' -}'; +rinterp.help = {'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.'}; rinterp.labels = { 'Nearest neighbour' 'Trilinear' @@ -395,9 +385,11 @@ wrap.tag = 'wrap'; wrap.name = 'Wrapping'; wrap.help = { - 'These are typically: ' - ' No wrapping - for PET or images that have already been spatially transformed. ' - ' Wrap in Y - for (un-resliced) MRI where phase encoding is in the Y direction (voxel space).' + 'These are typically: ' + ['* No wrapping - for images that have already been ' ... + 'spatially transformed.'] + ['* Wrap in Y - for (un-resliced) MRI where phase ' ... + 'encoding is in the Y direction (voxel space).'] }'; wrap.labels = { 'No wrap' diff --git a/config/spm_cfg_reorient.m b/config/spm_cfg_reorient.m index 7dc984f..f671c2e 100644 --- a/config/spm_cfg_reorient.m +++ b/config/spm_cfg_reorient.m @@ -4,9 +4,9 @@ %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_cfg_reorient.m 3130 2009-05-18 14:41:31Z volkmar $ +% $Id: spm_cfg_reorient.m 3804 2010-03-31 16:16:21Z ged $ -rev = '$Rev: 3130 $'; +rev = '$Rev: 3804 $'; % --------------------------------------------------------------------- % srcfiles Images to reorient % --------------------------------------------------------------------- @@ -56,7 +56,7 @@ '' 'Example: This will L-R flip the images (extra spaces are inserted between each group for illustration purposes).' '' - ' 0 0 0 0 0 0 -1 0 0 0 0 0' + ' 0 0 0 0 0 0 -1 1 1 0 0 0' '' }'; transprm.strtype = 'e'; diff --git a/config/spm_cfg_results.m b/config/spm_cfg_results.m index 81e7240..7c28201 100644 --- a/config/spm_cfg_results.m +++ b/config/spm_cfg_results.m @@ -3,9 +3,9 @@ %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_cfg_results.m 3433 2009-09-30 10:32:02Z guillaume $ +% $Id: spm_cfg_results.m 3691 2010-01-20 17:08:30Z guillaume $ -rev = '$Rev: 3433 $'; +rev = '$Rev: 3691 $'; % --------------------------------------------------------------------- % spmmat Select SPM.mat % --------------------------------------------------------------------- @@ -48,7 +48,7 @@ threshdesc.help = {''}; threshdesc.labels = {'FWE' 'none'}; threshdesc.values = {'FWE' 'none'}; -threshdesc.def = @(val)spm_get_defaults('stats.results.threshtype', val{:}); +threshdesc.val = {'FWE'}; % --------------------------------------------------------------------- % thresh Threshold % --------------------------------------------------------------------- @@ -58,7 +58,7 @@ thresh.help = {''}; thresh.strtype = 'e'; thresh.num = [1 1]; -thresh.def = @(val)spm_get_defaults('stats.results.thresh', val{:}); +thresh.val = {0.05}; % --------------------------------------------------------------------- % extent Extent (voxels) % --------------------------------------------------------------------- @@ -68,7 +68,7 @@ extent.help = {''}; extent.strtype = 'e'; extent.num = [1 1]; -extent.def = @(val)spm_get_defaults('stats.results.extent', val{:}); +extent.val = {0}; % --------------------------------------------------------------------- % contrasts Contrast(s) % --------------------------------------------------------------------- @@ -87,7 +87,7 @@ thresh1.help = {''}; thresh1.strtype = 'e'; thresh1.num = [1 1]; -thresh1.def = @(val)spm_get_defaults('stats.results.maskthresh', val{:}); +thresh1.val = {0.05}; % --------------------------------------------------------------------- % mtype Nature of mask % --------------------------------------------------------------------- @@ -155,7 +155,7 @@ print.help = {''}; print.labels = {'Yes' 'No'}; print.values = {true false}; -print.def = @(val)spm_get_defaults('stats.results.print', val{:}); +print.val = {true}; % --------------------------------------------------------------------- % results Results Report % --------------------------------------------------------------------- diff --git a/config/spm_cfg_smooth.m b/config/spm_cfg_smooth.m index 090fe35..62b7e7e 100644 --- a/config/spm_cfg_smooth.m +++ b/config/spm_cfg_smooth.m @@ -1,11 +1,11 @@ function smooth = spm_cfg_smooth -% SPM Configuration file +% SPM Configuration file for Smooth %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_cfg_smooth.m 3663 2010-01-07 12:26:48Z guillaume $ +% $Id: spm_cfg_smooth.m 3691 2010-01-20 17:08:30Z guillaume $ -rev = '$Rev: 3663 $'; +rev = '$Rev: 3691 $'; % --------------------------------------------------------------------- % data Images to Smooth % --------------------------------------------------------------------- @@ -33,7 +33,7 @@ dtype.tag = 'dtype'; dtype.name = 'Data Type'; dtype.help = {'Data-type of output images. SAME indicates the same datatype as the original images.'}; -dtype.labels = { +dtype.labels = { 'SAME' 'UINT8 - unsigned char' 'INT16 - signed short' @@ -41,8 +41,8 @@ 'FLOAT32 - single prec. float' 'FLOAT64 - double prec. float' }'; -dtype.values = {0 spm_type('uint8') spm_type('int16') spm_type('int32') spm_type('float32') spm_type('float64')}; -dtype.def = @(val)spm_get_defaults('smooth.dtype', val{:}); +dtype.values = {0 spm_type('uint8') spm_type('int16') spm_type('int32') spm_type('float32') spm_type('float64')}; +dtype.val = {0}; % --------------------------------------------------------------------- % im Implicit masking % --------------------------------------------------------------------- diff --git a/config/spm_cfg_st.m b/config/spm_cfg_st.m index 53f3519..3b57c0e 100644 --- a/config/spm_cfg_st.m +++ b/config/spm_cfg_st.m @@ -1,12 +1,10 @@ function st = spm_cfg_st -% SPM Configuration file -% automatically generated by the MATLABBATCH utility function GENCODE +% SPM Configuration file for Slice Timing Correction %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_cfg_st.m 3135 2009-05-19 14:49:42Z guillaume $ +% $Id: spm_cfg_st.m 4005 2010-07-21 10:54:55Z guillaume $ -rev = '$Rev: 3135 $'; % --------------------------------------------------------------------- % scans Session % --------------------------------------------------------------------- @@ -104,7 +102,6 @@ st.name = 'Slice Timing'; st.val = {generic nslices tr ta so refslice prefix }; st.help = { - 'Note that this option is likely to be removed in future. 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.' 'Correct differences in image acquisition time between slices. Slice-time corrected files are prepended with an ''a''.' '' 'Note: The sliceorder arg that specifies slice acquisition order is a vector of N numbers, where N is the number of slices per volume. Each number refers to the position of a slice within the image file. The order of numbers within the vector is the temporal order in which those slices were acquired. To check the order of slices within an image file, use the SPM Display option and move the cross-hairs to a voxel co-ordinate of z=1. This corresponds to a point in the first slice of the volume.' @@ -118,7 +115,9 @@ '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.' -}'; + '' + '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.' + }'; st.prog = @spm_run_st; st.vout = @vout; st.modality = {'FMRI'}; @@ -126,10 +125,10 @@ % --------------------------------------------------------------------- function dep = vout(job) -for k=1:numel(job.scans), +for k=1:numel(job.scans) dep(k) = cfg_dep; dep(k).sname = sprintf('Slice Timing Corr. Images (Sess %d)', k); dep(k).src_output = substruct('()',{k}, '.','files'); dep(k).tgt_spec = cfg_findspec({{'filter','image','strtype','e'}}); -end; +end return; diff --git a/config/spm_cfg_voi.m b/config/spm_cfg_voi.m index a961e91..62863dc 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 3465 2009-10-14 15:14:29Z guillaume $ +% $Id: spm_cfg_voi.m 3919 2010-06-04 16:45:16Z guillaume $ % ------------------------------------------------------------------------- % spmmat Select SPM.mat @@ -24,9 +24,23 @@ contrast = cfg_entry; contrast.tag = 'contrast'; contrast.name = 'Contrast'; -contrast.help = {'Index of contrast'}'; +contrast.help = {'Index of contrast. If more than one index is entered, a conjunction analysis is performed.'}; contrast.strtype = 'e'; -contrast.num = [1 1]; +contrast.num = [1 Inf]; + +% ------------------------------------------------------------------------- +% conjunction Conjunction Number +% ------------------------------------------------------------------------- +conjunction = cfg_entry; +conjunction.tag = 'conjunction'; +conjunction.name = 'Conjunction number'; +conjunction.help = {'Conjunction number. Unused if a simple contrast is entered.' + 'For Conjunction Null, enter 1.' + 'For Global Null, enter the number of selected contrasts.' + 'For Intermediate, enter the number of selected contrasts minus the number of effects under the Null.'}'; +conjunction.strtype = 'e'; +conjunction.num = [1 1]; +conjunction.val = {1}; % ------------------------------------------------------------------------- % threshdesc Threshold type @@ -61,6 +75,27 @@ extent.num = [1 1]; extent.val = {0}; +% ------------------------------------------------------------------------- +% contrast Contrast +% ------------------------------------------------------------------------- +contrastm = cfg_entry; +contrastm.tag = 'contrast'; +contrastm.name = 'Contrast'; +contrastm.help = {'Indices of contrast(s).'}; +contrastm.strtype = 'e'; +contrastm.num = [1 Inf]; + +% ------------------------------------------------------------------------- +% threshm Threshold +% ------------------------------------------------------------------------- +threshm = cfg_entry; +threshm.tag = 'thresh'; +threshm.name = 'Uncorrected mask p-value'; +threshm.help = {''}; +threshm.strtype = 'e'; +threshm.num = [1 1]; +threshm.val = {0.05}; + % ------------------------------------------------------------------------- % mtype Nature of mask % ------------------------------------------------------------------------- @@ -77,7 +112,7 @@ mask = cfg_branch; mask.tag = 'mask'; mask.name = 'Mask definition'; -mask.val = {contrast thresh mtype}; +mask.val = {contrastm threshm mtype}; mask.help = {''}; % ------------------------------------------------------------------------- @@ -96,7 +131,7 @@ map = cfg_branch; map.tag = 'spm'; map.name = 'Thresholded SPM'; -map.val = {spmmat contrast threshdesc thresh extent generic}; +map.val = {spmmat contrast conjunction threshdesc thresh extent generic}; map.help = {'Thresholded SPM'}'; % ------------------------------------------------------------------------- diff --git a/config/spm_latex_cfg.m b/config/spm_latex_cfg.m index ab22212..8ea619e 100644 --- a/config/spm_latex_cfg.m +++ b/config/spm_latex_cfg.m @@ -1,10 +1,10 @@ function spm_latex_cfg(c) % Convert a job configuration tree into a series of LaTeX documents -%____________________________________________________________________________ +%__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % John Ashburner -% $Id: spm_latex_cfg.m 1791 2008-06-05 13:50:14Z guillaume $ +% $Id: spm_latex_cfg.m 3934 2010-06-17 14:58:25Z guillaume $ if ~nargin, c = spm_cfg; end if nargin && ischar(c), clean_latex_compile; return; end @@ -57,6 +57,7 @@ function spm_latex_cfg(c) fclose(fp); return; +%========================================================================== function part(c,fp) % this is always false, and each cfg_item has a tag %if isstruct(c) && isfield(c,'tag'), @@ -82,8 +83,13 @@ function part(c,fp) %end; return; +%========================================================================== function sts = chapter(c) -fp = fopen([c.tag '.tex'],'w'); +bn = c.tag; +if strcmp(bn,'preproc') && ~isempty(strfind(c.name,'EEG')) + bn = ['MEEG_' bn]; % fix for name clash with other 'preproc' +end +fp = fopen([bn '.tex'],'w'); if fp==-1, sts = false; return; end; fprintf(fp,'\\chapter{%s \\label{Chap:%s}}\n\\minitoc\n\n\\vskip 1.5cm\n\n',texify(c.name),c.tag); @@ -103,6 +109,7 @@ function part(c,fp) sts = true; return; +%========================================================================== function section(c,fp,lev) if nargin<3, lev = 1; end; sec = {'section','subsection','subsubsection','paragraph','subparagraph','textbf','textsc','textsl','textit'}; @@ -124,6 +131,7 @@ function section(c,fp,lev) end; return; +%========================================================================== function write_help(hlp,fp) if isa(hlp, 'cfg_item'), if ~isempty(hlp.help), @@ -142,9 +150,10 @@ function write_help(hlp,fp) fprintf(fp,'%s\n\n',str); return; +%========================================================================== function str = texify(str0) -st1 = findstr(str0,'/*'); -en1 = findstr(str0,'*/'); +st1 = strfind(str0,'/*'); +en1 = strfind(str0,'*/'); st = []; en = []; for i=1:numel(st1), @@ -165,6 +174,7 @@ function write_help(hlp,fp) str = [str clean_latex(str0(pen:numel(str0)))]; return; +%========================================================================== function str = clean_latex(str) str = strrep(str,'$','\$'); str = strrep(str,'&','\&'); @@ -177,14 +187,16 @@ function write_help(hlp,fp) str = strrep(str,'<','$<$'); return; +%========================================================================== function bibcstr = get_bib(bibdir) biblist = dir(fullfile(bibdir,'*.bib')); bibcstr={}; for k = 1:numel(biblist) - [p n e v] = fileparts(biblist(k).name); + [p n e v] = spm_fileparts(biblist(k).name); bibcstr{k} = fullfile(bibdir,n); -end; +end +%========================================================================== function clean_latex_compile p = fullfile(spm('Dir'),'man'); [f, d] = spm_select('FPlist',p,'.*\.aux$'); diff --git a/config/spm_run_bms_dcm.m b/config/spm_run_bms_dcm.m index 50f474d..0c26527 100644 --- a/config/spm_run_bms_dcm.m +++ b/config/spm_run_bms_dcm.m @@ -17,25 +17,26 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % CC Chen & Maria Joao Rosa -% $Id: spm_run_bms_dcm.m 3669 2010-01-11 11:17:20Z maria $ +% $Id: spm_run_bms_dcm.m 3955 2010-06-29 17:26:29Z maria $ % input % ------------------------------------------------------------------------- job = varargin{1}; -fname = 'BMS.mat'; % Output filename -fname = fullfile(job.dir{1},fname);% Output filename (including directory) -ld_f = ~isempty(job.load_f{1}); -ld_msp = ~isempty(job.model_sp{1}); -bma_do = isfield(job.bma,'bma_yes'); -data_se = ~isempty(job.sess_dcm); + +fname = 'BMS.mat'; % Output filename +fname = fullfile(job.dir{1},fname); % Output filename (inc. directory) +ld_f = ~isempty(job.load_f{1}); % Log-evidence file +ld_msp = ~isempty(job.model_sp{1}); % Model space file +bma_do = isfield(job.bma,'bma_yes'); % Compute BMA +data_se = ~isempty(job.sess_dcm); % DCM files % method % ------------------------------------------------------------------------- if strcmp(job.method,'FFX'); - method = 'FFX'; + method = 'FFX'; % Fixed-effects else - method = 'RFX'; + method = 'RFX'; % Random-effects end % check DCM.mat files and BMA @@ -55,16 +56,10 @@ error('Plase specify DCM.mat files to do BMA!') end end - - n = size(DCM.a,2); - m = size(DCM.c,2); - mi = size(DCM.c,2); - bma.nsamp = 1e4; - bma.odds_ratio = 1/20; - bma.a = zeros(n,n,bma.nsamp); - bma.b = zeros(n,n,m,bma.nsamp); - bma.c = zeros(n,mi,bma.nsamp); - + + nsamp = 1e4; + odds_ratio = 1/20; + if isfield(job.bma.bma_yes,'bma_famwin') do_bma_famwin = 1; else @@ -75,35 +70,36 @@ end end else - if ld_msp + if ld_msp disp('Loading model space') load(job.model_sp{1}); - if ~exist('subj','var') - error('Incorrect model space file! File must contain ''subj'' structure.') - end + if ~exist('subj','var') + error('Incorrect model space file! File must contain ''subj'' structure.') + end end end -F = []; -N = {}; -nonLin = 0; +% initialise +% ------------------------------------------------------------------------- +F = []; % Free energy +N = {}; % Models % prepare the data % ------------------------------------------------------------------------- if ld_f - data = job.load_f{1}; + data = job.load_f{1}; load(data); - nm = size(F,2); % No of Models - ns = size(F,1); % No of Models + nm = size(F,2); % No of Models + ns = size(F,1); % No of Models N = 1:nm; - subj = []; - f_fname = data; - fname_msp = []; - + subj = []; % subj structure + f_fname = data; % LogE file name + fname_msp = []; % Model space + else - - f_fname = []; - + + f_fname = []; % LogE file name + % Verify dimensions of data and model space if ld_msp ns = length(subj); % No of Subjects @@ -116,18 +112,18 @@ nm = size(job.sess_dcm{1}(1).mod_dcm,1); % No of Models fname_msp = [job.dir{1} 'model_space.mat']; end - + F = zeros(ns,nm); N = cell(nm); - + % Check if No of models > 2 if nm < 2 msgbox('Please select more than one file') return end - + for k=1:ns - + % Verify dimensions of data and model space for current session if ld_msp nsess_now = length(subj(k).sess); @@ -137,81 +133,86 @@ nsess_now = size(job.sess_dcm{k},2); nmodels = size(job.sess_dcm{k}(1).mod_dcm,1); end - + if (nsess_now == nsess && nmodels== nm) % Check no of sess/mods - - ID = zeros(nsess, nm); - + + ID = zeros(nm,nsess); + for j=1:nm - + F_sess = []; - + for h = 1:nsess_now - + if ~ld_msp - + clear DCM - + % Load DCM (model) tmp = job.sess_dcm{k}(h).mod_dcm{j}; - DCM = load(tmp); - + if ~job.verify_id + warning off MATLAB:load:variableNotFound + DCM.DCM = load(tmp, 'F', 'Ep', 'Cp'); + warning on MATLAB:load:variableNotFound + if ~isfield(DCM.DCM, 'F') + DCM = load(tmp); + end + else + DCM = load(tmp); + end + % Free energy for sessions F_sess = [F_sess,DCM.DCM.F]; - - % Create model space - subj(k).sess(h).model(j).fname = tmp; - subj(k).sess(h).model(j).F = DCM.DCM.F; - subj(k).sess(h).model(j).Ep = DCM.DCM.Ep; - subj(k).sess(h).model(j).Cp = DCM.DCM.Cp; - subj(k).sess(h).model(j).nonLin = 0; - if isfield(DCM.DCM,'D') - subj(k).sess(h).model(j).nonLin = 1; - nonLin = 1; - nPnonLin = length(DCM.DCM.Ep); - end + % Create model space + subj(k).sess(h).model(j).fname = tmp; + subj(k).sess(h).model(j).F = DCM.DCM.F; + subj(k).sess(h).model(j).Ep = DCM.DCM.Ep; + subj(k).sess(h).model(j).Cp = DCM.DCM.Cp; else - + F_sess = [F_sess,subj(k).sess(h).model(j).F]; - + end - + % Data ID verification. At least for now we'll % re-compute the IDs rather than use the ones stored % with the DCM. if job.verify_id - M = DCM.DCM.M; - + + disp(sprintf('Identifying data: model %d', j)); + + M = DCM.DCM.M; + if isfield(DCM.DCM, 'xY') Y = DCM.DCM.xY; % not fMRI else Y = DCM.DCM.Y; % fMRI end - + if isfield(M,'FS') try - ID(h,j) = spm_data_id(feval(M.FS,Y.y,M)); + ID(j,h) = spm_data_id(feval(M.FS,Y.y,M)); catch - ID(h,j) = spm_data_id(feval(M.FS,Y.y)); + ID(j,h) = spm_data_id(feval(M.FS,Y.y)); end else - ID(h,j) = spm_data_id(Y.y); + ID(j,h) = spm_data_id(Y.y); end - + end end - + % Sum over sessions F_mod = sum(F_sess); F(k,j) = F_mod; N{j} = sprintf('model%d',j); - + end - + if job.verify_id - failind = find(max(abs(diff(ID))) > eps); + failind = find(max(abs(diff(ID)),[],1) > eps); if ~isempty(failind) out.files{1} = []; msgbox(['Error: the models for subject ' num2str(k) ... @@ -223,9 +224,9 @@ out.files{1} = []; msgbox('Error: the number of sessions/models should be the same for all subjects!') return - + end - + end end @@ -239,18 +240,18 @@ % family or model level % ------------------------------------------------------------------------- if isfield(job.family_level,'family_file') - + if ~isempty(job.family_level.family_file{1}) - + load(job.family_level.family_file{1}); do_family = 1; family.infer = method; - + nfam = size(family.names,2); npart = length(unique(family.partition)); maxpart = max(family.partition); m_indx = 1:nm; - + if nfam ~= npart || npart == 1 || maxpart > npart error('Invalid family file!') out.files{1} = []; @@ -258,15 +259,15 @@ else do_family = 0; end - + else - + if isempty(job.family_level.family) do_family = 0; else do_family = 1; nfam = size(job.family_level.family,2); - + names_fam = {}; models_fam = []; m_indx = []; @@ -275,30 +276,30 @@ m_indx = [m_indx,job.family_level.family(f).family_models']; models_fam(job.family_level.family(f).family_models) = f; end - + family.names = names_fam; family.partition = models_fam; - + npart = length(unique(family.partition)); maxpart = max(family.partition); nmodfam = length(m_indx); - + if nfam ~= npart || npart == 1 || maxpart > npart || nmodfam > nm error('Invalid family!') out.files{1} = []; return end - + family.infer = method; - + end - + end % single subject BMS or 1st level( fixed effects) group BMS % ------------------------------------------------------------------------- if strcmp(method,'FFX'); - + disp('Computing FFX model/family posteriors ...'); if ~do_family family = []; @@ -308,67 +309,43 @@ [family,model] = spm_compare_families (Ffam,family); P = spm_api_bmc(sumF,N,[],[],family); end - + if bma_do, if do_family if do_bma_famwin [fam_max,fam_max_i] = max(family.post); - bma.indx = find(family.partition==fam_max_i); - bma.post = model.post(bma.indx); + indx = find(family.partition==fam_max_i); + post = model.post(indx); else if do_bma_all - bma.post = model.post; - bma.indx = 1:nm; + post = model.post; + indx = 1:nm; else if bma_fam <= nfam && bma_fam > 0 && rem(bma_fam,1) == 0 - bma.indx = find(family.partition==bma_fam); - bma.post = model.post(bma.indx); + indx = find(family.partition==bma_fam); + post = model.post(indx); else error('Incorrect family for BMA!'); end end end else - bma.post = model.post; - bma.indx = 1:nm; + post = model.post; + indx = 1:nm; end - + disp('FFX Bayesian model averaging ...'); % bayesian model averaging - % ------------------------------------------------------------------ - [theta, theta_sbj] = spm_dcm_bma(bma.post,bma.indx,subj,... - bma.nsamp,bma.odds_ratio); - - % reshape parameters - % ------------------------------------------------------------------ - disp('Reshaping parameters ...'); - for i = 1:bma.nsamp, - if (nonLin && size(theta,1)==nPnonLin) - [A,B,C,H,D] = spm_dcm_reshape(theta(:,i),m,n,1); - bma.d(:,:,:,i) = D(:,:,:); - else - [A,B,C] = spm_dcm_reshape(theta(:,i),m,n,1); - end - bma.a(:,:,i) = A(:,:); - bma.b(:,:,:,i) = B(:,:,:); - bma.c(:,:,i) = C(:,:); - end - bma.ma = mean(bma.a,3); - bma.mb = mean(bma.b,4); - bma.mc = mean(bma.c,3); - if (nonLin && size(theta,1)==nPnonLin) - bma.md = mean(bma.d,4); - end - bma.theta_sbj = theta_sbj; - bma.mtheta_sbj = mean(theta_sbj,3); - bma.stheta_sbj = std(theta_sbj,0,3); + % ----------------------------------------------------------------- + bma = spm_dcm_bma(post,indx,subj,nsamp,odds_ratio); + else - + bma = []; - + end - + if exist(fullfile(job.dir{1},'BMS.mat'),'file') load(fname); if isfield(BMS,'DCM') && isfield(BMS.DCM,'ffx') @@ -383,20 +360,20 @@ BMS.DCM.ffx.model = model; BMS.DCM.ffx.family = family; BMS.DCM.ffx.bma = bma; - + disp('Saving BMS.mat file...') if spm_matlab_version_chk('7') >= 0 save(fname,'-V6','BMS'); else save(fname,'BMS'); end - + out.files{1} = fname; - + % 2nd-level (random effects) BMS - % ------------------------------------------------------------------------- + % --------------------------------------------------------------------- else - + disp('Computing RFX model/family posteriors...'); if ~do_family [exp_r,xp,r_samp,g_post] = spm_BMS_gibbs(F); @@ -407,80 +384,54 @@ model.xp = xp; family = []; else - + Ffam = F(:,sort(m_indx)); [family,model] = spm_compare_families(Ffam,family); - + end - + % display the result if do_family P = spm_api_bmc(sumF,N,model.exp_r,model.xp,family); else P = spm_api_bmc(sumF,N,model.exp_r,model.xp); end - + if bma_do, if do_family if do_bma_famwin [fam_max,fam_max_i] = max(family.exp_r); - bma.indx = find(family.partition==fam_max_i); - bma.post = model.g_post(:,bma.indx); + indx = find(family.partition==fam_max_i); + post = model.g_post(:,indx); else if do_bma_all - bma.post = model.g_post; - bma.indx = 1:nm; + post = model.g_post; + indx = 1:nm; else if bma_fam <= nfam && bma_fam > 0 && rem(bma_fam,1) == 0 - bma.indx = find(family.partition==bma_fam); - bma.post = model.g_post(:,bma.indx); + indx = find(family.partition==bma_fam); + post = model.g_post(:,indx); else error('Incorrect family for BMA!'); end end end else - bma.post = model.g_post; - bma.indx = 1:nm; - end - - disp('RFX Bayesian model averaging ...'); - % bayesian model averaging - % ------------------------------------------------------------------ - [theta,theta_sbj] = spm_dcm_bma(bma.post,bma.indx,subj,... - bma.nsamp,bma.odds_ratio); - - % reshape parameters - % ------------------------------------------------------------------ - disp('Reshaping parameters ...'); - for i = 1:bma.nsamp, - if (nonLin && size(theta,1)==nPnonLin) - [A,B,C,H,D] = spm_dcm_reshape(theta(:,i),m,n,1); - bma.d(:,:,:,i) = D(:,:,:); - else - [A,B,C] = spm_dcm_reshape(theta(:,i),m,n,1); - end - bma.a(:,:,i) = A(:,:); - bma.b(:,:,:,i) = B(:,:,:); - bma.c(:,:,i) = C(:,:); - end - bma.ma = mean(bma.a,3); - bma.mb = mean(bma.b,4); - bma.mc = mean(bma.c,3); - if (nonLin && size(theta,1)==nPnonLin) - bma.md = mean(bma.d,4); - end - - bma.theta_sbj = theta_sbj; - bma.mtheta_sbj = mean(theta_sbj,3); - bma.stheta_sbj = std(theta_sbj,0,3); - + post = model.g_post; + indx = 1:nm; + end + + disp('RFX Bayesian model averaging ...'); + % bayesian model averaging + % ------------------------------------------------------------------ + bma = spm_dcm_bma(post,indx,subj,nsamp,odds_ratio); + else - + bma = []; - + end - + if exist(fullfile(job.dir{1},'BMS.mat'),'file') load(fname); if isfield(BMS,'DCM') && isfield(BMS.DCM,'rfx') @@ -495,7 +446,7 @@ BMS.DCM.rfx.model = model; BMS.DCM.rfx.family = family; BMS.DCM.rfx.bma = bma; - + disp('Saving BMS.mat file...') if spm_matlab_version_chk('7') >= 0 save(fname,'-V6','BMS'); @@ -503,7 +454,7 @@ save(fname,'BMS'); end out.files{1}= fname; - + end % Save model_space diff --git a/config/spm_run_con.m b/config/spm_run_con.m index 07789a7..0de8f46 100644 --- a/config/spm_run_con.m +++ b/config/spm_run_con.m @@ -9,7 +9,7 @@ %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_run_con.m 3083 2009-04-24 16:43:05Z volkmar $ +% $Id: spm_run_con.m 3993 2010-07-13 11:59:32Z volkmar $ wd = pwd; @@ -29,15 +29,20 @@ % Load SPM.mat file %----------------------------------------------------------------------- -tmp=load(job.spmmat{:}); -SPM=tmp.SPM; +load(job.spmmat{:},'SPM'); + +try + SPM.xVol.XYZ; +catch + error('This model has not been estimated.'); +end if ~strcmp(pth,SPM.swd) warning(['Path to SPM.mat: %s\n and SPM.swd: %s\n differ, using current ' ... 'SPM.mat location as new working directory.'], pth, ... SPM.swd); SPM.swd = pth; -end; +end if job.delete && isfield(SPM,'xCon') for k=1:numel(SPM.xCon) @@ -160,13 +165,16 @@ % assume identical sessions, no check! nsessions=numel(SPM.Sess); switch sessrep - case 'repl', + case {'repl','replsc'} % within-session zero padding, replication over sessions cons = {zeros(size(con,1),size(SPM.xX.X,2))}; for sess=1:nsessions sfirst=SPM.Sess(sess).col(1); cons{1}(:,sfirst:sfirst+size(con,2)-1)=con; end + if strcmp(sessrep,'replsc') + cons{1} = cons{1}/nsessions; + end names = {sprintf('%s - All Sessions', name)}; case 'replna', % within-session zero padding, new rows per session @@ -183,7 +191,7 @@ cons{k} = [zeros(size(con,1),SPM.Sess(k).col(1)-1) con]; names{k} = sprintf('%s - Session %d', name, k); end; - case 'both' + case {'both','bothsc'} cons = cell(1,numel(SPM.Sess)); names = cell(1,numel(SPM.Sess)); for k=1:numel(SPM.Sess) @@ -197,6 +205,9 @@ sfirst=SPM.Sess(sess).col(1); cons{end}(:,sfirst:sfirst+size(con,2)-1)=con; end + if strcmp(sessrep,'bothsc') + cons{end} = cons{end}/nsessions; + end names{end+1} = sprintf('%s - All Sessions', name); end; end; diff --git a/config/spm_run_factorial_design.m b/config/spm_run_factorial_design.m index 7d384af..4d31a81 100644 --- a/config/spm_run_factorial_design.m +++ b/config/spm_run_factorial_design.m @@ -1,34 +1,32 @@ function out = spm_run_factorial_design(job) -% SPM job execution function -% takes a harvested job data structure and call SPM functions to perform -% computations on the data. +% SPM job execution function - factorial design specification % Input: % job - harvested job data structure (see matlabbatch help) % Output: -% out - computation results, usually a struct variable. -%_______________________________________________________________________ +% out - struct variable containing the path of the saved SPM.mat +%__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Will Penny -% $Id: spm_run_factorial_design.m 3067 2009-04-20 13:58:07Z guillaume $ +% $Id: spm_run_factorial_design.m 3860 2010-05-04 15:59:25Z guillaume $ +%-------------------------------------------------------------------------- % This function configures the design matrix (describing the general % linear model), data specification, and other parameters necessary for % the statistical analysis. These parameters are saved in a % configuration file (SPM.mat) in the current directory, and are -% passed on to spm_spm.m (via the Estimate button) which estimates the design. -% Inference on these estimated parameters is then handled by the SPM -% results section. +% passed on to spm_spm.m (via the Estimate button) which estimates the +% design. Inference on these estimated parameters is then handled by the +% SPM results section. % -% This function comprises two parts. The first defines -% the user interface and the second sets up the necessary SPM structures. -% The second part has been largely cannibalised from spm_spm_ui.m which -% we have retained for developmental continuity. +% This function, that sets up the necessary SPM structures, has been +% largely cannibalised from spm_spm_ui.m which we have retained for +% developmental continuity. % % It has in common with spm_spm_ui.m its use of the I factor matrix, % the H,C,B,G design matrix partitions, the sF,sCFI,CFIforms,sCC,CCforms, % sGXcalc,sGloNorm,sGMsca option definition variables and use of the -% functions spm_DesMtx.m, spm_meanby.m and spm_non_sphericity.m. +% functions spm_DesMtx.m, spm_meanby.m and spm_get_vc.m. % % It departs from spm_spm_ui.m in that it does not use the design % definition data structure D. Also, it uses the new SPM.factor field, @@ -42,37 +40,36 @@ % Two facilities are provided for specifying more complicated designs % (5) Full-factorial and (6) Flexible-factorial. These should be able to % specify all design options (and more) that were available in SPM2. -% For each of these design types one can additionally specify regressors using the -% `covariates' option. +% For each of these design types one can additionally specify regressors +% using the `covariates' option. % -% Options (5) and (6) differ in the -% efficiency (eg. number of key strokes/button presses) with which a given -% design can be specified. For example, one-way ANOVAs can be specified -% using either option, but (5) is usually more efficient. +% Options (5) and (6) differ in the efficiency (eg. number of key +% strokes/button presses) with which a given design can be specified. For +% example, one-way ANOVAs can be specified using either option, but (5) is +% usually more efficient. % % Full-factorial designs % ______________________ % -% This option is best used when you wish to test for all -% main effects and interactions in one-way, two-way or three-way ANOVAs. +% This option is best used when you wish to test for all main effects and +% interactions in one-way, two-way or three-way ANOVAs. % % Design specification proceeds in 2 stages. Firstly, by creating new -% factors and specifying the -% number of levels and name for each. Nonsphericity, ANOVA-by-factor (for PET data) -% and -% scaling options (for PET data) can also be specified at this stage. Secondly, -% scans are assigned separately to each cell. This accomodates unbalanced designs. +% factors and specifying the number of levels and name for each. +% Nonsphericity, ANOVA-by-factor (for PET data) and scaling options (for +% PET data) can also be specified at this stage. Secondly, scans are +% assigned separately to each cell. This accomodates unbalanced designs. % % For example, if you wish to test for a main effect in the population -% from which your subjects are drawn -% and have modelled that effect at the first level using K basis functions -% (eg. K=3 informed basis functions) you can use a one-way ANOVA with K-levels. -% Create a single factor with K levels and then assign the data to each -% cell eg. canonical, temporal derivative and dispersion derivative cells, -% where each cell is assigned scans from multiple subjects. +% from which your subjects are drawn and have modelled that effect at the +% first level using K basis functions (eg. K=3 informed basis functions) +% you can use a one-way ANOVA with K-levels. Create a single factor with K +% levels and then assign the data to each cell eg. canonical, temporal +% derivative and dispersion derivative cells, where each cell is assigned +% scans from multiple subjects. % % SPM will automatically generate the contrasts necessary to test for all -% main effects and interactions +% main effects and interactions. % % Flexible-factorial designs % __________________________ @@ -81,42 +78,40 @@ % decide whether you wish each block to be a main effect or a (two-way) % interaction. % -% This option is best used for one-way, two-way or -% three-way ANOVAs but where you do not wish to test for all possible -% main effects and interactions. This is perhaps most useful for PET -% where there is usually not enough data to test for all possible -% effects. Or for 3-way ANOVAs where you do not wish to test for all -% of the two-way interactions. A typical example here would be a -% group-by-drug-by-task analysis where, perhaps, only (i) group-by-drug or -% (ii) group-by-task interactions are of interest. In this case it is only -% necessary to have two-blocks in the design matrix - one for each -% interaction. The three-way interaction can then be tested for using a -% contrast that computes the difference between (i) and (ii). +% This option is best used for one-way, two-way or three-way ANOVAs but +% where you do not wish to test for all possible main effects and +% interactions. This is perhaps most useful for PET where there is usually +% not enough data to test for all possible effects. Or for 3-way ANOVAs +% where you do not wish to test for all of the two-way interactions. A +% typical example here would be a group-by-drug-by-task analysis where, +% perhaps, only (i) group-by-drug or (ii) group-by-task interactions are +% of interest. In this case it is only necessary to have two-blocks in the +% design matrix - one for each interaction. The three-way interaction can +% then be tested for using a contrast that computes the difference between +% (i) and (ii). % -% Design specification then proceeds in 3 stages. Firstly, factors -% are created and names specified for each. Nonsphericity, ANOVA-by-factor and +% Design specification then proceeds in 3 stages. Firstly, factors are +% created and names specified for each. Nonsphericity, ANOVA-by-factor and % scaling options can also be specified at this stage. % -% Secondly, a list of -% scans is produced along with a factor matrix, I. This is an nscan x 4 matrix -% of factor level indicators (see xX.I below). The first factor must be -% 'replication' but the other factors can be anything. Specification of I and -% the scan list can be achieved in -% one of two ways (a) the 'Specify All' option allows I -% to be typed in at the user interface or (more likely) loaded in from the matlab -% workspace. All of the scans are then selected in one go. (b) the -% 'Subjects' option allows you to enter scans a subject at a time. The -% corresponding experimental conditions (ie. levels of factors) are entered -% at the same time. SPM will then create the factor matrix I. This style of -% interface is similar to that available in SPM2. +% Secondly, a list of scans is produced along with a factor matrix, I. +% This is an nscan x 4 matrix of factor level indicators (see xX.I below). +% The first factor must be 'replication' but the other factors can be +% anything. Specification of I and the scan list can be achieved in one +% of two ways (a) the 'Specify All' option allows I to be typed in at the +% user interface or (more likely) loaded in from the matlab workspace. +% All of the scans are then selected in one go. (b) the 'Subjects' option +% allows you to enter scans a subject at a time. The corresponding +% experimental conditions (ie. levels of factors) are entered at the same +% time. SPM will then create the factor matrix I. This style of interface +% is similar to that available in SPM2. % % Thirdly, the design matrix is built up a block at a time. Each block % can be a main effect or a (two-way) interaction. % +%-------------------------------------------------------------------------- % -% ---------------------------------------------------------------------- -% -% Variables saved in the SPM stucture +% Variables saved in the SPM stucture: % % xY.VY - nScan x 1 struct array of memory mapped images % (see spm_vol for definition of the map structure) @@ -128,11 +123,11 @@ % xX.X - design matrix % xX.xVi - correlation constraints for non-spericity correction % xX.iH - vector of H partition (condition effects) indices, -% identifying columns of X correspoding to H +% identifying columns of X corresponding to H % xX.iC - vector of C partition (covariates of interest) indices % xX.iB - vector of B partition (block effects) indices % xX.iG - vector of G partition (nuisance variables) indices -% xX.name - p x 1 cellstr of effect names corresponding to columns +% xX.name - p x 1 cellstr of effect names corresponding to columns % of the design matrix % % xC - structure array of covariate details @@ -163,8 +158,8 @@ % xGX.sGloNorm - string describing global normalisation option % % xM - structure describing masking options -% xM.T - Threshold masking value (-Inf=>None, -% real=>absolute, complex=>proportional (i.e. times global) ) +% xM.T - Threshold masking value (-Inf=>None, real=>absolute, +% complex=>proportional (i.e. times global)) % xM.TH - nScan x 1 vector of analysis thresholds, one per image % xM.I - Implicit masking (0=>none, 1=>implicit zero/NaN mask) % xM.VM - struct array of explicit mask images @@ -180,17 +175,16 @@ % of the design, displaying the fieldnames (with "_"'s % converted to spaces) in bold as topics, with % the corresponding text to the right +% +%-------------------------------------------------------------------------- -global defaults -if isempty(defaults) - spm_defaults; -end - +%-Change directory +%-------------------------------------------------------------------------- original_dir = pwd; cd(job.dir{1}); %-Ask about overwriting files from previous analyses... -%------------------------------------------------------------------- +%-------------------------------------------------------------------------- if exist(fullfile(job.dir{1},'SPM.mat'),'file') str = { 'Current directory contains existing SPM file:',... 'Continuing will overwrite existing file!'}; @@ -203,7 +197,7 @@ % If we've gotten to this point we're committed to overwriting files. % Delete them so we don't get stuck in spm_spm -%------------------------------------------------------------------------ +%-------------------------------------------------------------------------- files = {'^mask\..{3}$','^ResMS\..{3}$','^RPV\..{3}$',... '^beta_.{4}\..{3}$','^con_.{4}\..{3}$','^ResI_.{4}\..{3}$',... '^ess_.{4}\..{3}$', '^spm\w{1}_.{4}\..{3}$'}; @@ -215,10 +209,11 @@ end end - %-Option definitions -%------------------------------------------------------------------- +%========================================================================== + %-Generic factor names +%-------------------------------------------------------------------------- sF = {'sF1','sF2','sF3','sF4'}; %-Covariate by factor interaction options @@ -228,164 +223,181 @@ %-DesMtx argument components for covariate by factor interaction options % (Used for CFI's Covariate Centering (CC), GMscale & Global normalisation) -CFIforms = { '[]', 'C', '{}';... %-1 - 'I(:,1)', 'FxC', '{sF{1}}';... %-2 - 'I(:,2)', 'FxC', '{sF{2}}';... %-3 - 'I(:,3)', 'FxC', '{sF{3}}';... %-4 - 'I(:,4)', 'FxC', '{sF{4}}';... %-5 - 'I(:,[4,2])', 'FxC', '{sF{4},sF{2}}';... %-6 - 'I(:,[4,3])', 'FxC', '{sF{4},sF{3}}' }; %-7 +%-------------------------------------------------------------------------- +CFIforms = {'[]', 'C', '{}';... %-1 + 'I(:,1)', 'FxC', '{sF{1}}';... %-2 + 'I(:,2)', 'FxC', '{sF{2}}';... %-3 + 'I(:,3)', 'FxC', '{sF{3}}';... %-4 + 'I(:,4)', 'FxC', '{sF{4}}';... %-5 + 'I(:,[4,2])', 'FxC', '{sF{4},sF{2}}';... %-6 + 'I(:,[4,3])', 'FxC', '{sF{4},sF{3}}' }; %-7 %-Centre (mean correction) options for covariates & globals (CC) % (options 9-12 are for centering of global when using AnCova GloNorm) (GC) -sCC = { 'around overall mean';... %-1 - 'around sF1 means';... %-2 - 'around sF2 means';... %-3 - 'around sF3 means';... %-4 - 'around sF4 means';... %-5 - 'around sF2 (within sF4) means';... %-6 - 'around sF3 (within sF4) means';... %-7 - '';... %-8 - 'around user specified value';... %-9 - '(as implied by AnCova)';... %-10 - 'GM';... %-11 - '(redundant: not doing AnCova)'}'; %-12 +%-------------------------------------------------------------------------- +sCC = {'around overall mean';... %-1 + 'around sF1 means';... %-2 + 'around sF2 means';... %-3 + 'around sF3 means';... %-4 + 'around sF4 means';... %-5 + 'around sF2 (within sF4) means';... %-6 + 'around sF3 (within sF4) means';... %-7 + '';... %-8 + 'around user specified value';... %-9 + '(as implied by AnCova)';... %-10 + 'GM';... %-11 + '(redundant: not doing AnCova)'}'; %-12 + %-DesMtx I forms for covariate centering options +%-------------------------------------------------------------------------- CCforms = {'ones(nScan,1)',CFIforms{2:end,1},''}'; %-Global calculation options (GXcalc) -sGXcalc = { 'omit';... %-1 +%-------------------------------------------------------------------------- +sGXcalc = {'omit';... %-1 'user specified';... %-2 'mean voxel value (within per image fullmean/8 mask)'}; %-3 - %-Global normalization options (GloNorm) -sGloNorm = { 'AnCova';... %-1 - 'AnCova by sF1';... %-2 - 'AnCova by sF2';... %-3 - 'AnCova by sF3';... %-4 - 'AnCova by sF4';... %-5 - 'AnCova by sF2 (within sF4)';... %-6 - 'AnCova by sF3 (within sF4)';... %-7 - 'proportional scaling';... %-8 - ''}; %-9 +%-------------------------------------------------------------------------- +sGloNorm = {'AnCova';... %-1 + 'AnCova by sF1';... %-2 + 'AnCova by sF2';... %-3 + 'AnCova by sF3';... %-4 + 'AnCova by sF4';... %-5 + 'AnCova by sF2 (within sF4)';... %-6 + 'AnCova by sF3 (within sF4)';... %-7 + 'proportional scaling';... %-8 + ''}; %-9 %-Grand mean scaling options (GMsca) -sGMsca = { 'scaling of overall grand mean';... %-1 - 'scaling of sF1 grand means';... %-2 - 'scaling of sF2 grand means';... %-3 - 'scaling of sF3 grand means';... %-4 - 'scaling of sF4 grand means';... %-5 - 'scaling of sF2 (within sF4) grand means';... %-6 - 'scaling of sF3 (within sF4) grand means';... %-7 - '(implicit in PropSca global normalisation)';... %-8 - '' }; %-9 -%-NB: Grand mean scaling by subject is redundent for proportional scaling - -% Conditions of no interest defaults -B=[]; -Bnames={}; - -switch strvcat(fieldnames(job.des)), +% (NB: Grand mean scaling by subject is redundent for proportional scaling) +%-------------------------------------------------------------------------- +sGMsca = {'scaling of overall grand mean';... %-1 + 'scaling of sF1 grand means';... %-2 + 'scaling of sF2 grand means';... %-3 + 'scaling of sF3 grand means';... %-4 + 'scaling of sF4 grand means';... %-5 + 'scaling of sF2 (within sF4) grand means';... %-6 + 'scaling of sF3 (within sF4) grand means';... %-7 + '(implicit in PropSca global normalisation)';... %-8 + '' }; %-9 + +%-Conditions of no interest defaults +%-------------------------------------------------------------------------- +B = []; +Bnames = {}; + +switch char(fieldnames(job.des)) + + %-One sample t-test + %====================================================================== case 't1', - % One sample t-test - DesName='One sample t-test'; - - P=job.des.t1.scans; - n=length(P); - I=[1:n]'; - I=[I,ones(n,3)]; - - [H,Hnames]=spm_DesMtx(I(:,2),'-','mean'); - - SPM.factor(1).name='Group'; - SPM.factor(1).levels=1; - SPM.factor(1).variance=0; - SPM.factor(1).dept=0; + + DesName = 'One sample t-test'; + + P = job.des.t1.scans; + n = length(P); + I = [1:n]'; + I = [I,ones(n,3)]; + + [H,Hnames] = spm_DesMtx(I(:,2),'-','mean'); + + SPM.factor(1).name = 'Group'; + SPM.factor(1).levels = 1; + SPM.factor(1).variance = 0; + SPM.factor(1).dept = 0; + + %-Two-sample t-test + %====================================================================== case 't2', - % Two-sample t-test - DesName='Two-sample t-test'; + + DesName = 'Two-sample t-test'; - P=job.des.t2.scans1; - n1=length(job.des.t2.scans1); - P=[P;job.des.t2.scans2]; - n2=length(job.des.t2.scans2); + P = job.des.t2.scans1; + n1 = length(job.des.t2.scans1); + P = [P; job.des.t2.scans2]; + n2 = length(job.des.t2.scans2); - I=[]; - I=[1:n1]'; - I=[I;[1:n2]']; - I=[I,[ones(n1,1);2*ones(n2,1)]]; - I=[I,ones(n1+n2,2)]; + I = []; + I = [1:n1]'; + I = [I;[1:n2]']; + I = [I,[ones(n1,1);2*ones(n2,1)]]; + I = [I,ones(n1+n2,2)]; - [H,Hnames]=spm_DesMtx(I(:,2),'-','Group'); + [H,Hnames] = spm_DesMtx(I(:,2),'-','Group'); % Names and levels - SPM.factor(1).name='Group'; - SPM.factor(1).levels=2; + SPM.factor(1).name = 'Group'; + SPM.factor(1).levels = 2; % Ancova options - SPM.factor(1).gmsca=job.des.t2.gmsca; - SPM.factor(1).ancova=job.des.t2.ancova; + SPM.factor(1).gmsca = job.des.t2.gmsca; + SPM.factor(1).ancova = job.des.t2.ancova; % Nonsphericity options - SPM.factor(1).variance=job.des.t2.variance; - SPM.factor(1).dept=job.des.t2.dept; + SPM.factor(1).variance = job.des.t2.variance; + SPM.factor(1).dept = job.des.t2.dept; + %-Paired t-test + %====================================================================== case 'pt', - % Paired t-test - DesName='Paired t-test'; + + DesName = 'Paired t-test'; - Npairs=length(job.des.pt.pair); - P=[]; - for p=1:Npairs, - P=[P;job.des.pt.pair(p).scans]; + Npairs = length(job.des.pt.pair); + P = []; + for p = 1:Npairs, + P = [P;job.des.pt.pair(p).scans]; end - I=ones(Npairs*2,1); - I(:,2)=kron([1:Npairs]',ones(2,1)); - I(:,3)=kron(ones(Npairs,1),[1 2]'); - I(:,4)=I(:,1); + I = ones(Npairs*2,1); + I(:,2) = kron([1:Npairs]',ones(2,1)); + 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'); + [H,Hnames] = spm_DesMtx(I(:,2),'-','Subject'); + [B,Bnames] = spm_DesMtx(I(:,3),'-','Condition'); % Names and levels - SPM.factor(1).name='Subject'; - SPM.factor(1).levels=Npairs; - SPM.factor(2).name='Condition'; - SPM.factor(2).levels=2; + SPM.factor(1).name = 'Subject'; + SPM.factor(1).levels = Npairs; + SPM.factor(2).name = 'Condition'; + SPM.factor(2).levels = 2; % Ancova options - SPM.factor(1).gmsca=0; - SPM.factor(1).ancova=0; - SPM.factor(2).gmsca=job.des.pt.gmsca; - SPM.factor(2).ancova=job.des.pt.ancova; + SPM.factor(1).gmsca = 0; + SPM.factor(1).ancova = 0; + SPM.factor(2).gmsca = job.des.pt.gmsca; + SPM.factor(2).ancova = job.des.pt.ancova; % Nonsphericity options - SPM.factor(1).variance=0; - SPM.factor(1).dept=0; - SPM.factor(2).variance=0; - SPM.factor(2).dept=0; + SPM.factor(1).variance = 0; + SPM.factor(1).dept = 0; + SPM.factor(2).variance = 0; + SPM.factor(2).dept = 0; + %-Multiple regression + %====================================================================== case 'mreg', - % Multiple regression - DesName='Multiple regression'; + + DesName = 'Multiple regression'; - P=job.des.mreg.scans; - n=length(P); - I=[1:n]'; - I=[I,ones(n,3)]; + P = job.des.mreg.scans; + n = length(P); + I = [1:n]'; + I = [I,ones(n,3)]; % Names and levels - SPM.factor(1).name=''; - SPM.factor(1).levels=1; + SPM.factor(1).name = ''; + SPM.factor(1).levels = 1; % Nonsphericity options - SPM.factor(1).variance=0; - SPM.factor(1).dept=0; + SPM.factor(1).variance = 0; + SPM.factor(1).dept = 0; - H=[];Hnames=[]; + H = []; Hnames = []; if job.des.mreg.incint==0 B = []; Bnames = ''; else @@ -399,207 +411,148 @@ job.cov(end).iCFI = 1; end + %-ANOVA + %====================================================================== + case 'anova', + + DesName = 'ANOVA'; + + job.des.anova.fact.name='Groups'; + + % Automatically number cells 1 to levels, so user does'nt have to + levels=length(job.des.anova.icell); + job.des.anova.fact.levels=levels; + for i=1:levels, + job.des.anova.icell(i).levels=i; + end + [I,P,H,Hnames] = spm_design_factorial(job.des.anova); + + + % Names and levels + SPM.factor(1).name = 'Groups'; + SPM.factor(1).levels = levels; + + % Ancova options + SPM.factor(1).gmsca = job.des.anova.gmsca; + SPM.factor(1).ancova = job.des.anova.ancova; + + % Nonsphericity options + SPM.factor(1).variance = job.des.anova.variance; + SPM.factor(1).dept = job.des.anova.dept; + + %-ANOVA: within-subject + %====================================================================== + case 'anovaw', + + 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.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; + + % Main effect of subject and group + 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); + + for i=1:2, + SPM.factor(i)=anovaw.fac(i); + end + SPM.factor(1).levels = length(job.des.anovaw.fsubject); + + %-Full Factorial Design + %====================================================================== case 'fd', - % Full Factorial Design - DesName='Full factorial'; + + DesName = 'Full factorial'; - [I,P,H,Hnames] = spm_set_factorial_design (job); + [I,P,H,Hnames] = spm_design_factorial(job.des.fd); - Nfactors=length(job.des.fd.fact); - for i=1:Nfactors, + Nfactors = length(job.des.fd.fact); + for i=1:Nfactors % Names and levels - SPM.factor(i).name=job.des.fd.fact(i).name; - SPM.factor(i).levels=job.des.fd.fact(i).levels; + SPM.factor(i).name = job.des.fd.fact(i).name; + SPM.factor(i).levels = job.des.fd.fact(i).levels; % Ancova options - SPM.factor(i).gmsca=job.des.fd.fact(i).gmsca; - SPM.factor(i).ancova=job.des.fd.fact(i).ancova; + SPM.factor(i).gmsca = job.des.fd.fact(i).gmsca; + SPM.factor(i).ancova = job.des.fd.fact(i).ancova; % Nonsphericity options - SPM.factor(i).variance=job.des.fd.fact(i).variance; - SPM.factor(i).dept=job.des.fd.fact(i).dept; - + SPM.factor(i).variance = job.des.fd.fact(i).variance; + SPM.factor(i).dept = job.des.fd.fact(i).dept; end - + + %-Flexible factorial design + %====================================================================== case 'fblock', - % Flexible factorial design - DesName='Flexible factorial'; - + + DesName = 'Flexible factorial'; + if isfield(job.des.fblock.fsuball,'fsubject') - nsub=length(job.des.fblock.fsuball.fsubject); - % Specify design subject-by-subject - P=[];I=[]; - subj=[]; - for s=1:nsub, - P = [P; job.des.fblock.fsuball.fsubject(s).scans]; - ns = length(job.des.fblock.fsuball.fsubject(s).scans); - cc = job.des.fblock.fsuball.fsubject(s).conds; - - [ccr,ccc] = size(cc); - if ~(ccr==ns) && ~(ccc==ns) - disp(sprintf('Error for subject %d: conditions not specified for each scan',s)); - return - elseif ~(ccr==ccc) && (ccc==ns) - %warning('spm:transposingConditions',['Condition matrix ',... - % 'appears to be transposed. Transposing back to fix.\n',... - % 'Alert developers if it is not actually transposed.']) - cc=cc'; - end - subj=[subj;s*ones(ns,1)]; - % get real replications within each subject cell - [unused cci ccj] = unique(cc,'rows'); - repl = zeros(ns, 1); - for k=1:max(ccj) - repl(ccj==k) = 1:sum(ccj==k); - end; - I = [I; [repl cc]]; - end - + % Data has been entered subject by subject nf=length(job.des.fblock.fac); - subject_factor=0; - for i=1:nf, - if strcmpi(job.des.fblock.fac(i).name,'repl') - % Copy `replications' column to create explicit `replications' factor - nI=I(:,1:i); - nI=[nI,I(:,1)]; - nI=[nI,I(:,i+1:end)]; - I=nI; - end - if strcmpi(job.des.fblock.fac(i).name,'subject') - % Create explicit `subject' factor - nI=I(:,1:i); - nI=[nI,subj]; - nI=[nI,I(:,i+1:end)]; - I=nI; - subject_factor=1; - end - - end - - % Re-order scans conditions and covariates into standard format - % This is to ensure compatibility with how variance components are created - if subject_factor - U=unique(I(:,2:nf+1),'rows'); - Un=length(U); - Uc=zeros(Un,1); - r=1;rj=[]; - for k=1:Un, - for j=1:size(I,1), - match=sum(I(j,2:nf+1)==U(k,:))==nf; - if match - Uc(k)=Uc(k)+1; - Ir(r,:)=[Uc(k),I(j,2:end)]; - r=r+1; - rj=[rj;j]; - end - end - end - P=P(rj); % -scans - I=Ir; % -conditions - for k=1:numel(job.cov) % -covariates - job.cov(k).c = job.cov(k).c(rj); - end; - end - - else % specify all scans and factor matrix + [I,P,job.cov] = spm_design_within_subject(job.des.fblock,job.cov); + else + % Specify all scans and factor matrix [ns,nc]=size(job.des.fblock.fsuball.specall.imatrix); if ~(nc==4) disp('Error: factor matrix must have four columns'); return end I=job.des.fblock.fsuball.specall.imatrix; - + % Pad out factorial matrix to cover the four canonical factors + [ns,nI]=size(I); + if nI < 4 + I = [I, ones(ns,4-nI)]; + end % Get number of factors nf=length(job.des.fblock.fac); - % nf=0; - % for i=1:4, - % if length(unique(I(:,i)))>1 - % nf=nf+1; - % end - % end - P=job.des.fblock.fsuball.specall.scans; + end - % Pad out factorial matrix to cover the four canonical factors - [ns,nI]=size(I); - if nI < 4 - I = [I, ones(ns,4-nI)]; - end - - % Sort main effects and interactions - fmain = struct('fnum',{}); - inter = struct('fnums',{}); - for k=1:numel(job.des.fblock.maininters) - if isfield(job.des.fblock.maininters{k},'fmain') - fmain(end+1)=job.des.fblock.maininters{k}.fmain; - elseif isfield(job.des.fblock.maininters{k},'inter') - inter(end+1)=job.des.fblock.maininters{k}.inter; - end; - end; - - % Create main effects - H=[];Hnames=[]; - nmain=length(fmain); - for f=1:nmain, - fcol=fmain(f).fnum; - fname=job.des.fblock.fac(fcol).name; - - % Augment H partition - explicit factor numbers are 1 lower than in I matrix - [Hf,Hfnames]=spm_DesMtx(I(:,fcol+1),'-',fname); - H=[H,Hf]; - Hnames=[Hnames;Hfnames]; - end - - % Create interactions - ni=length(inter); - for i=1:ni, - % Get the two factors for this interaction - fnums=inter(i).fnums; - f1=fnums(1);f2=fnums(2); - - % Names - iname{1}=job.des.fblock.fac(f1).name; - iname{2}=job.des.fblock.fac(f2).name; - - % Augment H partition - explicit factor numbers are 1 lower than in I matrix - Isub=[I(:,f1+1),I(:,f2+1)]; - [Hf,Hfnames]=spm_DesMtx(Isub,'-',iname); - H=[H,Hf]; - Hnames=[Hnames;Hfnames]; - - end - - if nmain==0 && ni==0 - disp('Error in design specification: You have not specified any main effects or interactions'); - return - end - - for i=1:nf, + [H,Hnames] = spm_design_flexible(job.des.fblock,I); + + for i=1:nf % Names and levels - SPM.factor(i).name=job.des.fblock.fac(i).name; - SPM.factor(i).levels=length(unique(I(:,i+1))); + SPM.factor(i).name = job.des.fblock.fac(i).name; + SPM.factor(i).levels = length(unique(I(:,i+1))); % Ancova options - SPM.factor(i).gmsca=job.des.fblock.fac(i).gmsca; - SPM.factor(i).ancova=job.des.fblock.fac(i).ancova; + SPM.factor(i).gmsca = job.des.fblock.fac(i).gmsca; + SPM.factor(i).ancova = job.des.fblock.fac(i).ancova; % Nonsphericity options - SPM.factor(i).variance=job.des.fblock.fac(i).variance; - SPM.factor(i).dept=job.des.fblock.fac(i).dept; + SPM.factor(i).variance = job.des.fblock.fac(i).variance; + SPM.factor(i).dept = job.des.fblock.fac(i).dept; end - end -nScan=size(I,1); %-#obs % Set up data structures for non-sphericity routine -SPM.xVi.I=I; +%========================================================================== +nScan = size(I,1); +SPM.xVi.I = I; SPM = spm_get_vc(SPM); %-Covariate partition(s): interest (C) & nuisance (G) excluding global -%=================================================================== +%========================================================================== dstr = {'covariate','nuisance variable'}; C = []; Cnames = []; %-Covariate DesMtx partitions & names G = []; Gnames = []; @@ -636,7 +589,7 @@ end %-Do any interaction (only for single covariate vectors) - %----------------------------------------------------------- + %---------------------------------------------------------------------- if iCFI > 1 %-(NB:iCFI=1 if size(c,2)>1) tI = [eval(CFIforms{iCFI,1}),c]; tConst = CFIforms{iCFI,2}; @@ -650,7 +603,7 @@ %-Store raw covariate details in xC struct for reference %-Pack c into appropriate DesMtx partition - %----------------------------------------------------------- + %---------------------------------------------------------------------- %-Construct description string for covariate str = {sprintf('%s',rcname)}; if size(rc,2)>1, str = {sprintf('%s (block of %d covariates)',... @@ -659,65 +612,60 @@ if iCFI> 1, str=[str;{['fitted as interaction ',sCFI{iCFI}]}]; end typ = 1; - tmp = struct( 'rc',rc, 'rcname',rcname,... - 'c',c, 'cname',{cname},... - 'iCC',iCC, 'iCFI',iCFI,... - 'type',typ,... - 'cols',[1:size(c,2)] + ... - size([H,C],2) + ... - size([B,G],2)*min(typ-1,1),... - 'descrip',{str} ); - if isempty(xC), xC = tmp; else, xC = [xC,tmp]; end + tmp = struct(... + 'rc', rc, 'rcname', rcname,... + 'c', c, 'cname', {cname},... + 'iCC', iCC, 'iCFI', iCFI,... + 'type', typ,... + 'cols', [1:size(c,2)] + size([H,C],2) + size([B,G],2)*min(typ-1,1),... + 'descrip', {str}); + if isempty(xC), xC = tmp; else xC = [xC,tmp]; end C = [C,c]; Cnames = [Cnames; cname]; end clear c tI tConst tFnames -xGX=[]; -xM=[]; - - -%=================================================================== +%========================================================================== % - C O N F I G U R E D E S I G N - -%=================================================================== +%========================================================================== %-Images & image info: Map Y image files and check consistency of % dimensions and orientation / voxel size -%=================================================================== -fprintf('%-40s: ','Mapping files') %-# -VY = spm_vol(char(P)); +%========================================================================== +fprintf('%-40s: ','Mapping files') %-# +VY = spm_vol(char(P)); -%-Check compatability of images (Bombs for single image) -%------------------------------------------------------------------- +%-Check compatibility of images +%-------------------------------------------------------------------------- spm_check_orientations(VY); -fprintf('%30s\n','...done') %-# +fprintf('%30s\n','...done') %-# %-Global values, scaling and global normalisation -%=================================================================== +%========================================================================== %-Compute global values -%------------------------------------------------------------------- -switch strvcat(fieldnames(job.globalc)) +%-------------------------------------------------------------------------- +switch char(fieldnames(job.globalc)) case 'g_omit', - iGXcalc=1; + iGXcalc = 1; case 'g_user', - iGXcalc=2; + iGXcalc = 2; case 'g_mean', - iGXcalc=3; + iGXcalc = 3; end switch job.globalm.glonorm case 1, - iGloNorm=9; + iGloNorm = 9; case 2, - iGloNorm=8; + iGloNorm = 8; case 3, - iGloNorm=1; + iGloNorm = 1; end if SPM.factor(1).levels > 1 - % Over-ride if factor-specific ANCOVA has been specified + % Override if factor-specific ANCOVA has been specified for i=1:length(SPM.factor), if SPM.factor(i).ancova iGloNorm=i+2; @@ -726,11 +674,11 @@ end %-Analysis threshold mask -%------------------------------------------------------------------- +%-------------------------------------------------------------------------- %-Work out available options: % -Inf=>None, real=>absolute, complex=>proportional, (i.e. times global) M_T = -Inf; -switch strvcat(fieldnames(job.masking.tm)), +switch char(fieldnames(job.masking.tm)), case 'tma', % Absolute M_T = job.masking.tm.tma.athresh; @@ -766,26 +714,26 @@ case 3 %-Compute as mean voxel value (within per image fullmean/8 mask) g = zeros(nScan,1 ); - fprintf('%-40s: %30s','Calculating globals',' ') %-# + fprintf('%-40s: %30s','Calculating globals',' ') %-# for i = 1:nScan str = sprintf('%3d/%-3d',i,nScan); - fprintf('%s%30s',repmat(sprintf('\b'),1,30),str)%-# + fprintf('%s%30s',repmat(sprintf('\b'),1,30),str) %-# g(i) = spm_global(VY(i)); end - fprintf('%s%30s\n',repmat(sprintf('\b'),1,30),'...done') %-# + fprintf('%s%30s\n',repmat(sprintf('\b'),1,30),'...done') %-# otherwise error('illegal iGXcalc') end rg = g; -fprintf('%-40s: ','Design configuration') %-# +fprintf('%-40s: ','Design configuration') %-# -%-Grand mean scaling options (GMsca) -%------------------------------------------------------------------- +%-Grand mean scaling options (GMsca) +%-------------------------------------------------------------------------- if iGloNorm==8 iGMsca=8; %-grand mean scaling implicit in PropSca GloNorm else - switch strvcat(fieldnames(job.globalm.gmsca)) + switch char(fieldnames(job.globalm.gmsca)) case 'gmsca_yes', iGMsca=1; case 'gmsca_no', @@ -801,16 +749,16 @@ end end -%-Value for PropSca / GMsca (GM) -%------------------------------------------------------------------- +%-Value for PropSca / GMsca (GM) +%-------------------------------------------------------------------------- switch iGMsca, - case 9 %-Not scaling (GMsca or PropSca) - GM = 0; %-Set GM to zero when not scaling + case 9 %-Not scaling (GMsca or PropSca) + GM = 0; %-Set GM to zero when not scaling case 1 %-Ask user value of GM GM = job.globalm.gmsca.gmsca_yes.gmscv; otherwise if iGloNorm==8 - switch strvcat(fieldnames(job.globalm.gmsca)) + switch char(fieldnames(job.globalm.gmsca)) case 'gmsca_yes', % Proportionally scale to this value GM = job.globalm.gmsca.gmsca_yes.gmscv; @@ -833,7 +781,7 @@ end %-Sort out description strings for GloNorm and GMsca -%------------------------------------------------------------------- +%-------------------------------------------------------------------------- sGloNorm = sGloNorm{iGloNorm}; sGMsca = sGMsca{iGMsca}; if iGloNorm==8 @@ -845,7 +793,7 @@ %-Scaling: compute global scaling factors gSF required to implement % proportional scaling global normalisation (PropSca) or grand mean % scaling (GMsca), as specified by iGMsca (& iGloNorm) -%------------------------------------------------------------------- +%-------------------------------------------------------------------------- switch iGMsca, case 8 %-Proportional scaling global normalisation @@ -865,13 +813,14 @@ %-Apply gSF to memory-mapped scalefactors to implement scaling -%------------------------------------------------------------------- +%-------------------------------------------------------------------------- for i = 1:nScan VY(i).pinfo(1:2,:) = VY(i).pinfo(1:2,:)*gSF(i); end -%-Global centering (for AnCova GloNorm) (GC) +%-Global centering (for AnCova GloNorm) (GC) %-If not doing AnCova then GC is irrelevant +%-------------------------------------------------------------------------- if ~any(iGloNorm == [1:7]) iGC = 12; gc = []; @@ -881,11 +830,11 @@ end %-AnCova: Construct global nuisance covariates partition (if AnCova) -%------------------------------------------------------------------- +%-------------------------------------------------------------------------- if any(iGloNorm == [1:7]) %-Centre global covariate as requested - %--------------------------------------------------------------- + %---------------------------------------------------------------------- switch iGC, case {1,2,3,4,5,6,7} %-Standard sCC options gc = spm_meanby(g,eval(CCforms{iGC})); case 8 %-No centering @@ -901,7 +850,7 @@ end %-AnCova - add scaled centred global to DesMtx `G' partition - %--------------------------------------------------------------- + %---------------------------------------------------------------------- rcname = 'global'; tI = [eval(CFIforms{iGloNorm,1}),g - gc]; tConst = CFIforms{iGloNorm,2}; @@ -910,7 +859,7 @@ clear tI tConst tFnames %-Save GX info in xC struct for reference - %--------------------------------------------------------------- + %---------------------------------------------------------------------- str = {sprintf('%s: %s',dstr{2},rcname)}; if any(iGMsca==[1:7]), str=[str;{['(after ',sGMsca,')']}]; end if iGC ~= 8, str=[str;{['used centered ',sCC{iGC}]}]; end @@ -925,13 +874,13 @@ 'descrip', {str} ); G = [G,f]; Gnames = [Gnames; gnames]; - if isempty(xC), xC = tmp; else, xC = [xC,tmp]; end + if isempty(xC), xC = tmp; else xC = [xC,tmp]; end elseif iGloNorm==8 || iGXcalc>1 %-Globals calculated, but not AnCova: Make a note of globals - %--------------------------------------------------------------- + %---------------------------------------------------------------------- if iGloNorm==8 str = { 'global values: (used for proportional scaling)';... '("raw" unscaled globals shown)'}; @@ -942,27 +891,27 @@ end rcname ='global'; - tmp = struct( 'rc',rg, 'rcname',rcname,... + tmp = struct('rc',rg, 'rcname',rcname,... 'c',{[]}, 'cname' ,{{}},... 'iCC',0, 'iCFI' ,0,... 'type', 3,... 'cols', {[]},... 'descrip', {str} ); - if isempty(xC), xC = tmp; else, xC = [xC,tmp]; end + if isempty(xC), xC = tmp; else xC = [xC,tmp]; end end %-Save info on global calculation in xGX structure -%------------------------------------------------------------------- +%-------------------------------------------------------------------------- xGX = struct(... - 'iGXcalc',iGXcalc, 'sGXcalc',sGXcalc, 'rg',rg,... - 'iGMsca',iGMsca, 'sGMsca',sGMsca, 'GM',GM,'gSF',gSF,... - 'iGC', iGC, 'sGC', sCC{iGC}, 'gc', gc,... - 'iGloNorm',iGloNorm, 'sGloNorm',sGloNorm); + 'iGXcalc', iGXcalc, 'sGXcalc', sGXcalc, 'rg',rg,... + 'iGMsca', iGMsca, 'sGMsca', sGMsca, 'GM',GM, 'gSF',gSF,... + 'iGC', iGC, 'sGC', sCC{iGC}, 'gc',gc,... + 'iGloNorm',iGloNorm, 'sGloNorm',sGloNorm); %-Make a description string -%------------------------------------------------------------------- +%-------------------------------------------------------------------------- if isinf(M_T) xsM.Analysis_threshold = 'None (-Inf)'; elseif isreal(M_T) @@ -974,7 +923,7 @@ %-Construct masking information structure and compute actual analysis % threshold using scaled globals (rg.*gSF) -%------------------------------------------------------------------- +%-------------------------------------------------------------------------- if isreal(M_T), M_TH = M_T * ones(nScan,1); %-NB: -Inf is real else @@ -982,14 +931,14 @@ end %-Implicit masking: Ignore zero voxels in low data-types? -%------------------------------------------------------------------- +%-------------------------------------------------------------------------- % (Implicit mask is NaN in higher data-types.) type = getfield(spm_vol(P{1,1}),'dt')*[1,0]'; if ~spm_type(type,'nanrep') M_I = job.masking.im; % Implicit mask ? if M_I, xsM.Implicit_masking = 'Yes: zero''s treated as missing'; - else, + else xsM.Implicit_masking = 'No'; end else @@ -998,7 +947,7 @@ end %-Explicit masking -%------------------------------------------------------------------- +%-------------------------------------------------------------------------- if isempty(job.masking.em{:}) VM = []; xsM.Explicit_masking = 'No'; @@ -1010,7 +959,7 @@ xM = struct('T',M_T, 'TH',M_TH, 'I',M_I, 'VM',{VM}, 'xs',xsM); %-Construct full design matrix (X), parameter names and structure (xX) -%=================================================================== +%========================================================================== X = [H C B G]; tmp = cumsum([size(H,2), size(C,2), size(B,2), size(G,2)]); xX = struct( 'X', X,... @@ -1024,24 +973,24 @@ %-Design description (an nx2 cellstr) - for saving and display -%=================================================================== -tmp = { sprintf('%d condition, +%d covariate, +%d block, +%d nuisance',... +%========================================================================== +tmp = {sprintf('%d condition, +%d covariate, +%d block, +%d nuisance',... size(H,2),size(C,2),size(B,2),size(G,2));... sprintf('%d total, having %d degrees of freedom',... size(X,2),rank(X));... sprintf('leaving %d degrees of freedom from %d images',... - size(X,1)-rank(X),size(X,1)) }; -xsDes = struct( 'Design', {DesName},... - 'Global_calculation', {sGXcalc},... - 'Grand_mean_scaling', {sGMsca},... - 'Global_normalisation', {sGloNorm},... - 'Parameters', {tmp} ); + size(X,1)-rank(X),size(X,1))}; +xsDes = struct('Design', {DesName},... + 'Global_calculation', {sGXcalc},... + 'Grand_mean_scaling', {sGMsca},... + 'Global_normalisation', {sGloNorm},... + 'Parameters', {tmp}); -fprintf('%30s\n','...done') %-# +fprintf('%30s\n','...done') %-# %-Assemble SPM structure -%=================================================================== +%========================================================================== SPM.xY.P = P; % filenames SPM.xY.VY = VY; % mapped data SPM.nscan = size(xX.X,1); % scan number @@ -1053,28 +1002,28 @@ % Automatic contrast generation only works for 'Full factorials' if ~strcmp(DesName,'Full factorial') - % Remove the .factor field to prevent attempted automatic contrast generation - SPM=rmfield(SPM,'factor'); + SPM = rmfield(SPM,'factor'); end %-Save SPM.mat and set output argument -%------------------------------------------------------------------- -fprintf('%-40s: ','Saving SPM configuration') %-# +%-------------------------------------------------------------------------- +fprintf('%-40s: ','Saving SPM configuration') %-# if spm_matlab_version_chk('7') >= 0 save('SPM', 'SPM', '-V6'); else save('SPM', 'SPM'); -end; -fprintf('%30s\n','...SPM.mat saved') %-# +end +fprintf('%30s\n','...SPM.mat saved') %-# + +out.spmmat{1} = fullfile(pwd, 'SPM.mat'); %-Display Design report -%=================================================================== -fprintf('%-40s: ','Design reporting') %-# +%========================================================================== +fprintf('%-40s: ','Design reporting') %-# fname = cat(1,{SPM.xY.VY.fname}'); spm_DesRep('DesMtx',SPM.xX,fname,SPM.xsDes) -fprintf('%30s\n','...done') %-# +fprintf('%30s\n','...done') %-# -out.spmmat{1} = fullfile(pwd, 'SPM.mat'); cd(original_dir); % Change back dir -fprintf('Done\n') %-# +fprintf('Done\n') %-# diff --git a/config/spm_run_fmri_data.m b/config/spm_run_fmri_data.m index 4fef910..0ee139c 100644 --- a/config/spm_run_fmri_data.m +++ b/config/spm_run_fmri_data.m @@ -10,13 +10,13 @@ %_________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_run_fmri_data.m 2080 2008-09-11 11:39:36Z guillaume $ +% $Id: spm_run_fmri_data.m 3756 2010-03-05 18:43:37Z guillaume $ spm('defaults','FMRI'); original_dir = pwd; -[p n e v] = fileparts(job.spmmat{1}); +[p n e v] = spm_fileparts(job.spmmat{1}); my_cd(p); load(job.spmmat{1}); diff --git a/config/spm_run_fmri_design.m b/config/spm_run_fmri_design.m index 24df888..737ca59 100644 --- a/config/spm_run_fmri_design.m +++ b/config/spm_run_fmri_design.m @@ -10,12 +10,9 @@ %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_run_fmri_design.m 2948 2009-03-25 11:27:40Z volkmar $ +% $Id: spm_run_fmri_design.m 3692 2010-01-21 21:43:31Z guillaume $ -spm('defaults','FMRI'); -global defaults - original_dir = pwd; my_cd(job.dir); @@ -56,10 +53,10 @@ % spm_hrf.m. The original values are saved here and restored at the end % of this function, after the design has been specified. The original % values may not be restored if this function crashes. -olddefs.stats.fmri.fmri_t=spm_get_defaults('stats.fmri.fmri_t'); -olddefs.stats.fmri.fmri_t0=spm_get_defaults('stats.fmri.fmri_t0'); -defaults.stats.fmri.t=job.timing.fmri_t; -defaults.stats.fmri.t0=job.timing.fmri_t0; +olddefs.stats.fmri.fmri_t = spm_get_defaults('stats.fmri.fmri_t'); +olddefs.stats.fmri.fmri_t0 = spm_get_defaults('stats.fmri.fmri_t0'); +spm_get_defaults('stats.fmri.t', job.timing.fmri_t); +spm_get_defaults('stats.fmri.t0', job.timing.fmri_t0); % Basis function variables %------------------------------------------------------------- diff --git a/config/spm_run_fmri_est.m b/config/spm_run_fmri_est.m index 20df6d3..5e617f1 100644 --- a/config/spm_run_fmri_est.m +++ b/config/spm_run_fmri_est.m @@ -1,5 +1,5 @@ function out = spm_run_fmri_est(job) -% Set up the design matrix and run a design. +% Estimate parameters of a specified model % SPM job execution function % takes a harvested job data structure and call SPM functions to perform % computations on the data. @@ -7,65 +7,77 @@ % 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_fmri_est.m 3327 2009-08-18 08:27:32Z volkmar $ - - -global defaults -if isempty(defaults) - spm_defaults; -end; -if ~isfield(defaults,'modality') - defaults.modality = 'FMRI'; -end; +% $Id: spm_run_fmri_est.m 3691 2010-01-20 17:08:30Z guillaume $ %-Load SPM.mat file -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- SPM = []; load(job.spmmat{:}); -% pre-set output out.spmmat = job.spmmat; -original_dir = pwd; - %-Move to the directory where the SPM.mat file is -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- +original_dir = pwd; cd(fileparts(job.spmmat{:})); -%======================================================================= -% B A Y E S I A N 2nd L E V E L E S T I M A T I O N -%======================================================================= -if isfield(job.method,'Bayesian2') - SPM = spm_spm_Bayes(SPM); - %out.spmvar = SPM; - cd(original_dir); % Change back - fprintf('Done\n'); - return -end - -%======================================================================= -% R E M L E S T I M A T I O N -%======================================================================= -if isfield(job.method,'Classical'), +%========================================================================== +% R E M L E S T I M A T I O N +%========================================================================== +if isfield(job.method,'Classical') + %-ReML estimation of the model + %---------------------------------------------------------------------- SPM = spm_spm(SPM); %-Automatically set up contrasts for factorial designs - %------------------------------------------------------------------- - if isfield(SPM,'factor') - if SPM.factor(1).levels > 1 - % don't both if you've only got 1 level and 1 factor - cons = spm_design_contrasts(SPM); - - %-Create F-contrasts - %----------------------------------------------------------- - for i=1:length(cons) - con = cons(i).c; - name = cons(i).name; - STAT = 'F'; - [c,I,emsg,imsg] = spm_conman('ParseCon',con,SPM.xX.xKXs,STAT); + %---------------------------------------------------------------------- + if isfield(SPM,'factor') && SPM.factor(1).levels > 1 + + %-Generate contrasts + %------------------------------------------------------------------ + cons = spm_design_contrasts(SPM); + + %-Create F-contrasts + %------------------------------------------------------------------ + for i=1:length(cons) + con = cons(i).c; + name = cons(i).name; + STAT = 'F'; + [c,I] = spm_conman('ParseCon',con,SPM.xX.xKXs,STAT); + if all(I) + DxCon = spm_FcUtil('Set',name,STAT,'c',c,SPM.xX.xKXs); + else + DxCon = []; + end + if isempty(SPM.xCon), + SPM.xCon = DxCon; + else + SPM.xCon(end+1) = DxCon; + end + SPM = spm_contrasts(SPM,length(SPM.xCon)); + end + + %-Create t-contrasts + %------------------------------------------------------------------ + for i=1:length(cons) + % Create a t-contrast for each row of each F-contrast + % The resulting contrast image can be used in a 2nd-level analysis + Fcon = cons(i).c; + STAT = 'T'; + for r=1:size(Fcon,1) + con = Fcon(r,:); + str = cons(i).name; + if ~isempty(strmatch('Interaction',str)) + name = ['Positive ',str,'_',int2str(r)]; + else + sp1 = find(isspace(str), 1); + name = ['Positive',str(sp1:end),'_',int2str(r)]; + end + + [c,I] = spm_conman('ParseCon',con,SPM.xX.xKXs,STAT); if all(I) DxCon = spm_FcUtil('Set',name,STAT,'c',c,SPM.xX.xKXs); else @@ -76,188 +88,159 @@ else SPM.xCon(end+1) = DxCon; end - SPM = spm_contrasts(SPM,length(SPM.xCon)); - end - - %-Create t-contrasts - %----------------------------------------------------------- - for i=1:length(cons) - % Create a t-contrast for each row of each F-contrast - % The resulting contrast image can be used in a 2nd-level analysis - Fcon = cons(i).c; - nrows = size(Fcon,1); - STAT = 'T'; - for r=1:nrows, - con = Fcon(r,:); - str = cons(i).name; - if ~isempty(strmatch('Interaction',str)) - name = ['Positive ',str,'_',int2str(r)]; - else - sp1 = min(find(isspace(str))); - name = ['Positive',str(sp1:end),'_',int2str(r)]; - end - - [c,I,emsg,imsg] = spm_conman('ParseCon',con,SPM.xX.xKXs,STAT); - if all(I) - DxCon = spm_FcUtil('Set',name,STAT,'c',c,SPM.xX.xKXs); - else - DxCon = []; - end - if isempty(SPM.xCon), - SPM.xCon = DxCon; - else - SPM.xCon(end+1) = DxCon; - end - SPM = spm_contrasts(SPM,length(SPM.xCon)); - end + SPM = spm_contrasts(SPM,length(SPM.xCon)); end - end % if SPM.factor(1).levels > 1 - end % if isfield(SPM,'factor') + end + + end + %-Computation results + %---------------------------------------------------------------------- %out.spmvar = SPM; out.beta = cellfun(@(fn)fullfile(SPM.swd,fn), cellstr(char(SPM.Vbeta(:).fname)),'UniformOutput',false); out.mask = {fullfile(SPM.swd,SPM.VM.fname)}; out.resms = {fullfile(SPM.swd,SPM.VResMS.fname)}; - cd(original_dir); % Change back + cd(original_dir); + fprintf('Done\n'); + return +end + + +%========================================================================== +% B A Y E S I A N 2nd L E V E L E S T I M A T I O N +%========================================================================== +if isfield(job.method,'Bayesian2') + + SPM = spm_spm_Bayes(SPM); + + %out.spmvar = SPM; + cd(original_dir); fprintf('Done\n'); return end -%======================================================================= -% B A Y E S I A N 1st L E V E L E S T I M A T I O N -%======================================================================= + +%========================================================================== +% B A Y E S I A N 1st L E V E L E S T I M A T I O N +%========================================================================== %-Analyse specific slices or whole volume -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- switch char(fieldnames(job.method.Bayesian.space)) case 'volume' - SPM.PPM.space_type = 'volume'; - SPM.PPM.block_type = lower(job.method.Bayesian.space.volume.block_type); + SPM.PPM.space_type = 'volume'; + SPM.PPM.block_type = lower(job.method.Bayesian.space.volume.block_type); case 'slices' - SPM.PPM.space_type = 'slices'; - SPM.PPM.AN_slices = job.method.Bayesian.space.slices.numbers; - SPM.PPM.block_type = lower(job.method.Bayesian.space.slices.block_type); + SPM.PPM.space_type = 'slices'; + SPM.PPM.AN_slices = job.method.Bayesian.space.slices.numbers; + SPM.PPM.block_type = lower(job.method.Bayesian.space.slices.block_type); case 'clusters' - SPM.PPM.space_type = 'clusters'; - SPM.PPM.clustermask = job.method.Bayesian.space.clusters.mask; - SPM.PPM.block_type = lower(job.method.Bayesian.space.clusters.block_type); + SPM.PPM.space_type = 'clusters'; + SPM.PPM.clustermask = job.method.Bayesian.space.clusters.mask; + SPM.PPM.block_type = lower(job.method.Bayesian.space.clusters.block_type); otherwise - SPM.PPM.space_type = 'volume'; - SPM.PPM.block_type = 'slices'; + SPM.PPM.space_type = 'volume'; + SPM.PPM.block_type = 'slices'; end + %-Regression coefficient priors -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- switch job.method.Bayesian.signal case 'UGL', - SPM.PPM.priors.W = 'Spatial - UGL'; + SPM.PPM.priors.W = 'Spatial - UGL'; case 'GMRF', - SPM.PPM.priors.W = 'Spatial - GMRF'; + SPM.PPM.priors.W = 'Spatial - GMRF'; case 'LORETA', - SPM.PPM.priors.W = 'Spatial - LORETA'; + SPM.PPM.priors.W = 'Spatial - LORETA'; case 'WGL', - SPM.PPM.priors.W = 'Spatial - WGL'; + SPM.PPM.priors.W = 'Spatial - WGL'; case 'Global', - SPM.PPM.priors.W = 'Voxel - Shrinkage'; + SPM.PPM.priors.W = 'Voxel - Shrinkage'; case 'Uninformative', - SPM.PPM.priors.W = 'Voxel - Uninformative'; + SPM.PPM.priors.W = 'Voxel - Uninformative'; otherwise - error('Unkown prior for W in spm_config_fmri_est'); + error('Unknown prior for W in Bayesian 1st level estimation.'); end %-Number of AR coefficients -%----------------------------------------------------------------------- -SPM.PPM.AR_P = job.method.Bayesian.ARP; +%-------------------------------------------------------------------------- +SPM.PPM.AR_P = job.method.Bayesian.ARP; %-AR coefficient priors -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- if isfield(job.method.Bayesian.noise,'UGL') - SPM.PPM.priors.A = 'Spatial - UGL'; + SPM.PPM.priors.A = 'Spatial - UGL'; elseif isfield(job.method.Bayesian.noise,'GMRF') - SPM.PPM.priors.A = 'Spatial - GMRF'; + SPM.PPM.priors.A = 'Spatial - GMRF'; elseif isfield(job.method.Bayesian.noise,'LORETA') - SPM.PPM.priors.A = 'Spatial - LORETA'; + SPM.PPM.priors.A = 'Spatial - LORETA'; elseif isfield(job.method.Bayesian.noise,'tissue_type') - SPM.PPM.priors.A = 'Discrete'; - SPM.PPM.priors.SY = char(job.method.Bayesian.noise.tissue_type); + SPM.PPM.priors.A = 'Discrete'; + SPM.PPM.priors.SY = char(job.method.Bayesian.noise.tissue_type); elseif isfield(job.method.Bayesian.noise,'Robust') - SPM.PPM.priors.A = 'Robust'; - SPM.PPM.AR_P=0; - SPM.PPM.update_F=1; + SPM.PPM.priors.A = 'Robust'; + SPM.PPM.AR_P = 0; + SPM.PPM.update_F = 1; end %-Define an empty contrast -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- NullCon = spm_FcUtil('Set','','P','c',[],1); NullCon.X0 = []; NullCon.iX0 = []; NullCon.X1o = []; NullCon.eidf = 1; -SPM.xCon = []; +SPM.xCon = []; %-Set up contrasts for 2nd-level ANOVA -%----------------------------------------------------------------------- -if strcmp(job.method.Bayesian.anova.second,'Yes') - if isfield(SPM,'factor') - cons=spm_design_contrasts(SPM); - for i=1:length(cons), - % Create a simple contrast for each row of each F-contrast - % The resulting contrast image can be used in a 2nd-level analysis - Fcon=cons(i).c; - nrows=size(Fcon,1); - STAT='P'; - for r=1:nrows, - con=Fcon(r,:); - - % Normalise contrast st. sum of positive elements is 1 - % and sum of negative elements is 1 - s1=length(find(con==1)); - con=con./s1; - - % Change name - str=cons(i).name; - sp1=min(find(str==' ')); - if strcmp(str(1:11),'Interaction') - name=['Positive ',str,'_',int2str(r)]; - else - name=['Positive',str(sp1:end),'_',int2str(r)]; - end - - DxCon=NullCon; - DxCon.name=name; - DxCon.c=con'; - - if isempty(SPM.xCon), - SPM.xCon = DxCon; - else - SPM.xCon(end+1) = DxCon; - end +%-------------------------------------------------------------------------- +if strcmp(job.method.Bayesian.anova.second,'Yes') && isfield(SPM,'factor') + cons = spm_design_contrasts(SPM); + for i=1:length(cons) + % Create a simple contrast for each row of each F-contrast + % The resulting contrast image can be used in a 2nd-level analysis + Fcon = cons(i).c; + for r=1:size(Fcon,1) + % Normalise contrast st. sum of positive elements is 1 + % and sum of negative elements is 1 + con = Fcon(r,:); + con = con / length(find(con==1)); + + % Change name + str = cons(i).name; + sp1 = find(str==' ', 1); + if strcmp(str(1:11),'Interaction') + name = ['Positive ',str,'_',int2str(r)]; + else + name = ['Positive',str(sp1:end),'_',int2str(r)]; + end + + DxCon = NullCon; + DxCon.name = name; + DxCon.c = con'; + + if isempty(SPM.xCon), + SPM.xCon = DxCon; + else + SPM.xCon(end+1) = DxCon; end end end end -%-Compute F -%----------------------------------------------------------------------- -if strcmp(job.method.Bayesian.LogEv,'Yes') - SPM.PPM.update_F = 1; - SPM.PPM.compute_det_D = 1; -end - %-Set up user-specified simple contrasts -%----------------------------------------------------------------------- -ncon = length(job.method.Bayesian.gcon); -K = size(SPM.xX.X,2); -for c = 1:ncon - DxCon = NullCon; - DxCon.name = job.method.Bayesian.gcon(c).name; - convec = job.method.Bayesian.gcon(c).convec(:); +%-------------------------------------------------------------------------- +K = size(SPM.xX.X,2); +for c = 1:length(job.method.Bayesian.gcon) + DxCon = NullCon; + DxCon.name = job.method.Bayesian.gcon(c).name; + convec = job.method.Bayesian.gcon(c).convec(:); if length(convec) == K DxCon.c = convec; else - str = ['Error in contrast specification:' ... - sprintf('\n contrast has %d entries ', length(convec)) ... - sprintf('but there are %d regressors !\n', K)]; - error(str); + warning(['User-specified contrast nb %d has %d entries '... + 'but there are %d regressors - ignored.'], c,length(convec),K); + DxCon = []; end if isempty(SPM.xCon), @@ -266,9 +249,16 @@ SPM.xCon(end+1) = DxCon; end end - + +%-Compute log evidence maps +%-------------------------------------------------------------------------- +if strcmp(job.method.Bayesian.LogEv,'Yes') + SPM.PPM.update_F = 1; + SPM.PPM.compute_det_D = 1; +end + %-1st level Bayesian ANOVA ? -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- bayes_anova = 0; if strcmp(job.method.Bayesian.anova.first,'Yes') bayes_anova = 1; @@ -277,11 +267,11 @@ end %-Variational Bayes estimation -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- SPM = spm_spm_vb(SPM); %-Bayesian ANOVA using model comparison -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- if bayes_anova % We don't want to estimate contrasts for each different model SPM.xCon = []; @@ -289,6 +279,6 @@ end %out.spmvar = SPM; -cd(original_dir); % Change back +cd(original_dir); fprintf('Done\n') return diff --git a/config/spm_run_fmri_spec.m b/config/spm_run_fmri_spec.m index 33c2d20..22efede 100644 --- a/config/spm_run_fmri_spec.m +++ b/config/spm_run_fmri_spec.m @@ -7,20 +7,17 @@ % 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_fmri_spec.m 2948 2009-03-25 11:27:40Z volkmar $ +% $Id: spm_run_fmri_spec.m 3757 2010-03-08 11:41:53Z guillaume $ -spm('defaults','FMRI'); -global defaults - original_dir = pwd; my_cd(job.dir); -%-Ask about overwriting files from previous analyses... -%------------------------------------------------------------------- +%-Ask about overwriting files from previous analyses +%-------------------------------------------------------------------------- if exist(fullfile(job.dir{1},'SPM.mat'),'file') str = { 'Current directory contains existing SPM file:',... 'Continuing will overwrite existing file!'}; @@ -33,7 +30,7 @@ % If we've gotten to this point we're committed to overwriting files. % Delete them so we don't get stuck in spm_spm -%------------------------------------------------------------------------ +%-------------------------------------------------------------------------- files = {'^mask\..{3}$','^ResMS\..{3}$','^RPV\..{3}$',... '^beta_.{4}\..{3}$','^con_.{4}\..{3}$','^ResI_.{4}\..{3}$',... '^ess_.{4}\..{3}$', '^spm\w{1}_.{4}\..{3}$'}; @@ -46,31 +43,31 @@ end % Variables -%------------------------------------------------------------- +%-------------------------------------------------------------------------- SPM.xY.RT = job.timing.RT; SPM.xY.P = []; % Slice timing -%------------------------------------------------------------- +%-------------------------------------------------------------------------- % The following lines have the side effect of modifying the global % defaults variable. This is necessary to pass job.timing.fmri_t to % spm_hrf.m. The original values are saved here and restored at the end % of this function, after the design has been specified. The original % values may not be restored if this function crashes. -olddefs.stats.fmri.fmri_t=spm_get_defaults('stats.fmri.fmri_t'); -olddefs.stats.fmri.fmri_t0=spm_get_defaults('stats.fmri.fmri_t0'); -defaults.stats.fmri.t=job.timing.fmri_t; -defaults.stats.fmri.t0=job.timing.fmri_t0; +olddefs.stats.fmri.fmri_t = spm_get_defaults('stats.fmri.fmri_t'); +olddefs.stats.fmri.fmri_t0 = spm_get_defaults('stats.fmri.fmri_t0'); +spm_get_defaults('stats.fmri.t', job.timing.fmri_t); +spm_get_defaults('stats.fmri.t0', job.timing.fmri_t0); % Basis function variables -%------------------------------------------------------------- +%-------------------------------------------------------------------------- SPM.xBF.UNITS = job.timing.units; SPM.xBF.dt = job.timing.RT/job.timing.fmri_t; SPM.xBF.T = job.timing.fmri_t; SPM.xBF.T0 = job.timing.fmri_t0; % Basis functions -%------------------------------------------------------------- +%-------------------------------------------------------------------------- if strcmp(fieldnames(job.bases),'hrf') if all(job.bases.hrf.derivs == [0 0]) SPM.xBF.name = 'hrf'; @@ -108,20 +105,20 @@ SPM.xBF.Volterra = false; else SPM.xBF.Volterra = job.volt; -end; +end for i = 1:numel(job.sess), sess = job.sess(i); % Image filenames - %------------------------------------------------------------- + %---------------------------------------------------------------------- SPM.nscan(i) = numel(sess.scans); SPM.xY.P = strvcat(SPM.xY.P,sess.scans{:}); U = []; % Augment the singly-specified conditions with the multiple % conditions specified in a .mat file provided by the user - %------------------------------------------------------------ + %---------------------------------------------------------------------- if ~isempty(sess.multi{1}) try multicond = load(sess.multi{1}); @@ -129,9 +126,9 @@ error('Cannot load %s',sess.multi{1}); end if ~(isfield(multicond,'names')&&isfield(multicond,'onsets')&&... - isfield(multicond,'durations')) || ... - ~all([numel(multicond.names),numel(multicond.onsets), ... - numel(multicond.durations)]==numel(multicond.names)) + isfield(multicond,'durations')) || ... + ~all([numel(multicond.names),numel(multicond.onsets), ... + numel(multicond.durations)]==numel(multicond.names)) error(['Multiple conditions MAT-file ''%s'' is invalid.\n',... 'File must contain names, onsets, and durations '... 'cell arrays of equal length.\n'],sess.multi{1}); @@ -143,10 +140,9 @@ cond.onset = multicond.onsets{j}; cond.duration = multicond.durations{j}; - % ADDED BY DGITELMAN % Mutiple Conditions Time Modulation - %------------------------------------------------------ - % initialize the variable. + %-------------------------------------------------------------- + % initialise the variable. cond.tmod = 0; if isfield(multicond,'tmod'); try @@ -157,8 +153,8 @@ end % Mutiple Conditions Parametric Modulation - %------------------------------------------------------ - % initialize the parametric modulation variable. + %-------------------------------------------------------------- + % initialise the parametric modulation variable. cond.pmod = []; if isfield(multicond,'pmod') % only access existing modulators @@ -186,7 +182,7 @@ end % Configure the input structure array - %------------------------------------------------------------- + %---------------------------------------------------------------------- for j = 1:length(sess.cond), cond = sess.cond(j); U(j).name = {cond.name}; @@ -228,19 +224,19 @@ % User specified regressors - %------------------------------------------------------------- - C = []; + %---------------------------------------------------------------------- + C = []; Cname = cell(1,numel(sess.regress)); for q = 1:numel(sess.regress), Cname{q} = sess.regress(q).name; - C = [C, sess.regress(q).val(:)]; + C = [C, sess.regress(q).val(:)]; end % Augment the singly-specified regressors with the multiple regressors % specified in the regressors.mat file - %------------------------------------------------------------ + %---------------------------------------------------------------------- if ~strcmp(sess.multi_reg,'') - tmp=load(char(sess.multi_reg{:})); + tmp = load(char(sess.multi_reg{:})); if isstruct(tmp) && isfield(tmp,'R') R = tmp.R; elseif isnumeric(tmp) @@ -252,11 +248,11 @@ R = []; end - C=[C, R]; - nr=size(R,2); - nq=length(Cname); + C = [C, R]; + nr = size(R,2); + nq = length(Cname); for inr=1:nr, - Cname{inr+nq}=['R',int2str(inr)]; + Cname{inr+nq} = ['R',int2str(inr)]; end end SPM.Sess(i).C.C = C; @@ -265,7 +261,7 @@ end % Factorial design -%------------------------------------------------------------- +%-------------------------------------------------------------------------- if isfield(job,'fact') if ~isempty(job.fact) NC=length(SPM.Sess(1).U); % Number of conditions @@ -285,23 +281,23 @@ end % Globals -%------------------------------------------------------------- +%-------------------------------------------------------------------------- SPM.xGX.iGXcalc = job.global; SPM.xGX.sGXcalc = 'mean voxel value'; SPM.xGX.sGMsca = 'session specific'; % High Pass filter -%------------------------------------------------------------- +%-------------------------------------------------------------------------- for i = 1:numel(job.sess), SPM.xX.K(i).HParam = job.sess(i).hpf; end % Autocorrelation -%------------------------------------------------------------- +%-------------------------------------------------------------------------- SPM.xVi.form = job.cvi; % Let SPM configure the design -%------------------------------------------------------------- +%-------------------------------------------------------------------------- SPM = spm_fmri_spm_ui(SPM); if ~isempty(job.mask)&&~isempty(job.mask{1}) @@ -310,15 +306,15 @@ end %-Save SPM.mat -%----------------------------------------------------------------------- -fprintf('%-40s: ','Saving SPM configuration') %-# +%-------------------------------------------------------------------------- +fprintf('%-40s: ','Saving SPM configuration') %-# if spm_matlab_version_chk('7') >= 0 save('SPM','-V6','SPM'); else save('SPM','SPM'); end; -fprintf('%30s\n','...SPM.mat saved') %-# +fprintf('%30s\n','...SPM.mat saved') %-# out.spmmat{1} = fullfile(pwd, 'SPM.mat'); my_cd(original_dir); % Change back dir @@ -326,18 +322,13 @@ spm_get_defaults('stats.fmri.fmri_t0',olddefs.stats.fmri.fmri_t0); % parameters fprintf('Done\n') return -%------------------------------------------------------------------------- -%------------------------------------------------------------------------- -function my_cd(varargin) -% jobDir must be the actual directory to change to, NOT the job structure. -jobDir = varargin{1}; +%========================================================================== +function my_cd(jobDir) if ~isempty(jobDir) try cd(char(jobDir)); - fprintf('Changing directory to: %s\n',char(jobDir)); catch error('Failed to change directory. Aborting run.') end end -return; diff --git a/config/spm_run_minc.m b/config/spm_run_minc.m index 7eb903e..f0bd0b6 100644 --- a/config/spm_run_minc.m +++ b/config/spm_run_minc.m @@ -9,12 +9,12 @@ %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_run_minc.m 2312 2008-10-07 17:02:46Z volkmar $ +% $Id: spm_run_minc.m 3691 2010-01-20 17:08:30Z guillaume $ +if job.opts.ext(1) ~= '.', job.opts.ext = ['.' job.opts.ext]; end out.files = cell(size(job.data)); for i=1:length(job.data), spm_mnc2nifti(job.data{i},job.opts); [pth,nam,ext,num] = spm_fileparts(job.data{i}); out.files{i} = fullfile(pth,[nam job.opts.ext num]); -end; -return; +end diff --git a/config/spm_run_results.m b/config/spm_run_results.m index 3c89bc1..87a3ba0 100644 --- a/config/spm_run_results.m +++ b/config/spm_run_results.m @@ -6,58 +6,59 @@ function spm_run_results(job) % 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_results.m 3433 2009-09-30 10:32:02Z guillaume $ +% $Id: spm_run_results.m 3753 2010-03-05 13:06:47Z guillaume $ cspec = job.conspec; for k = 1:numel(cspec) job.conspec=cspec(k); if (numel(cspec(k).contrasts) == 1) && isinf(cspec(k).contrasts) - tmp=load(job.spmmat{1}); + tmp = load(job.spmmat{1}); cspec1 = repmat(cspec(k),size(tmp.SPM.xCon)); for l=1:numel(tmp.SPM.xCon) cspec1(l).contrasts = l; - end; - job1=job; - job1.print = 1; - job1.conspec = cspec1; + end + job1 = job; + job1.print = 1; + job1.conspec = cspec1; spm_run_results(job1); else - xSPM.swd = spm_str_manip(job.spmmat{1},'H'); - xSPM.Ic = job.conspec.contrasts; - xSPM.u = job.conspec.thresh; - xSPM.Im = []; + xSPM.swd = spm_str_manip(job.spmmat{1},'H'); + xSPM.Ic = job.conspec.contrasts; + xSPM.u = job.conspec.thresh; + xSPM.Im = []; if ~isempty(job.conspec.mask) - xSPM.Im = job.conspec.mask.contrasts; - xSPM.pm = job.conspec.mask.thresh; - xSPM.Ex = job.conspec.mask.mtype; + xSPM.Im = job.conspec.mask.contrasts; + xSPM.pm = job.conspec.mask.thresh; + xSPM.Ex = job.conspec.mask.mtype; end - xSPM.thresDesc = job.conspec.threshdesc; - xSPM.title = job.conspec.titlestr; - xSPM.k = job.conspec.extent; + xSPM.thresDesc = job.conspec.threshdesc; + xSPM.title = job.conspec.titlestr; + xSPM.k = job.conspec.extent; switch job.units case 1 - xSPM.units = {'mm' 'mm' 'mm'}; + xSPM.units = {'mm' 'mm' 'mm'}; case 2 - xSPM.units = {'mm' 'mm' 'ms'}; + xSPM.units = {'mm' 'mm' 'ms'}; case 3 - xSPM.units = {'mm' 'mm' 'Hz'}; + xSPM.units = {'mm' 'mm' 'Hz'}; case 4 - xSPM.units = {'Hz' 'ms' ''}; + xSPM.units = {'Hz' 'ms' ''}; case 5 - xSPM.units = {'Hz' 'Hz' ''}; + xSPM.units = {'Hz' 'Hz' ''}; otherwise error('Unknown data type.'); end [hReg xSPM SPM] = spm_results_ui('Setup',xSPM); + TabDat = spm_list('List',xSPM,hReg); if job.print - spm_list('List',xSPM,hReg); spm_figure('Print'); - end; - assignin('base','hReg',hReg); - assignin('base','xSPM',xSPM); - assignin('base','SPM',SPM); - end; -end; + end + assignin('base','TabDat',TabDat); + assignin('base', 'hReg', hReg); + assignin('base', 'xSPM', xSPM); + assignin('base', 'SPM', SPM); + end +end diff --git a/config/spm_run_smooth.m b/config/spm_run_smooth.m index 38c9f01..5d4a170 100644 --- a/config/spm_run_smooth.m +++ b/config/spm_run_smooth.m @@ -9,7 +9,7 @@ %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% $Id: spm_run_smooth.m 3534 2009-11-05 12:34:21Z guillaume $ +% $Id: spm_run_smooth.m 3915 2010-06-02 17:09:10Z guillaume $ job = varargin{1}; out.files = cell(size(job.data)); @@ -19,15 +19,18 @@ out.files{i} = fullfile(pth,[job.prefix nam ext num]); spm_smooth(job.data{i},out.files{i},job.fwhm,job.dtype); if job.im - vi = spm_read_vols(spm_vol(job.data{i}),1); - v = spm_vol(out.files{i}); - vo = spm_read_vols(v); - if spm_type(v.dt(1),'nanrep') - vo(isnan(vi)) = NaN; - else - vo(isnan(vi)) = 0; + vi = spm_vol(job.data{i}); + vo = spm_vol(out.files{i}); + for j=1:numel(vi) + vvi = spm_read_vols(vi(j),1); + vvo = spm_read_vols(vo(j)); + if spm_type(vo(j).dt(1),'nanrep') + vvo(isnan(vvi)) = NaN; + else + vvo(isnan(vvi)) = 0; + end + spm_write_vol(vo(j),vvo); end - spm_write_vol(v,vo); end spm_progress_bar('Set',i); end diff --git a/config/spm_run_voi.m b/config/spm_run_voi.m index 8150322..f7cbe36 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 3531 2009-11-04 14:58:54Z guillaume $ +% $Id: spm_run_voi.m 3780 2010-03-15 17:15:00Z guillaume $ fprintf('## Note: this VOI facility is in a beta version. ##\n'); fprintf('## Interface and features might change in the future. ##\n'); @@ -40,7 +40,7 @@ %-Save VOI as image %-------------------------------------------------------------------------- -V = struct('fname', fullfile(swd, ['VOI_' job.name '.img']), ... +V = struct('fname', fullfile(swd, ['VOI_' job.name '.' spm_get_defaults('images.format')]), ... 'dim', SPM.xVol.DIM', ... 'dt', [spm_type('uint8') spm_platform('bigend')], ... 'mat', SPM.xVol.M, ... @@ -151,6 +151,7 @@ function [SPM, xSPM] = getSPM(s) xSPM.swd = spm_str_manip(s.spmmat{1},'H'); xSPM.Ic = s.contrast; +xSPM.n = s.conjunction; xSPM.u = s.thresh; xSPM.thresDesc = s.threshdesc; xSPM.k = s.extent; @@ -181,7 +182,7 @@ job.roi{m}.spm.spmmat = job.spmmat; end catch - error('The SPM index does not correspond to a Tresholded SPM ROI.'); + 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))]; diff --git a/exec/exec_jobman.m b/exec/exec_jobman.m deleted file mode 100644 index 9115abc..0000000 --- a/exec/exec_jobman.m +++ /dev/null @@ -1,12 +0,0 @@ -function exec_jobman(arg1) -% A function to be compiled, which will run a batch job saved in job.xml -%_______________________________________________________________________ -% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging - -% John Ashburner -% $Id: exec_jobman.m 1143 2008-02-07 19:33:33Z spm $ - -spm_defaults -path(path,spm('Dir')); -if nargin==0, arg1 = 'job.xml'; end; -spm_jobman('run',arg1); diff --git a/exec/exec_spm.m b/exec/exec_spm.m index c5ef252..680baee 100644 --- a/exec/exec_spm.m +++ b/exec/exec_spm.m @@ -1,13 +1,33 @@ -function exec_spm(arg1) -%_______________________________________________________________________ -% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging +function exec_spm(varargin) +% A function to be compiled, which will run a standalone SPM. +% +% See http://www.mathworks.com/products/compiler/ +%__________________________________________________________________________ +% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging % John Ashburner -% $Id: exec_spm.m 1143 2008-02-07 19:33:33Z spm $ +% $Id: exec_spm.m 3789 2010-03-19 17:05:36Z guillaume $ -path(path,spm('Dir')); -if nargin==0, - spm; +[v,r] = spm('Ver'); +fprintf('%s (%s): %s\n',v,r,spm('Dir')); + +if nargin && strcmpi(varargin{1},'run') + spm('asciiwelcome'); + %spm('defaults','fmri'); + spm_jobman('initcfg'); + if nargin == 1 + h = spm_jobman; + waitfor(h,'Visible','off'); + else + for i=2:nargin + try + spm_jobman('run',varargin{i}); + catch + fprintf('Execution of batch file ''%s'' failed.\n',varargin{i}); + end + end + end + spm('Quit'); else - spm(arg1); -end; + spm(varargin{:}); +end diff --git a/exec/make_exec.m b/exec/make_exec.m index 49410b1..83c647e 100644 --- a/exec/make_exec.m +++ b/exec/make_exec.m @@ -1,137 +1,97 @@ -function make_exec -% SPM can be compiled using Matlab 7. +function make_exec(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 license. -% The executable needs to be dynamically linked with runtime libraries -% bundled with the Matlab package. Before executing, ensure that your -% LD_LIBRARY_PATH is set appropriately, so that $MATLAB/bin/$arch -% is included. LD_LIBRARY_PATH or PATH should also contain the directory -% containing the *.ctf files +% outside MATLAB, and therefore does not use up a MATLAB licence. +% +% On Windows: +% spm8_wxx.exe +% spm8_wxx.exe run % -% Software compiled with later MATLAB versions may need -% LD_LIBRARY_PATH=$MATLAB/bin/$arch:$MATLAB/sys/os/$arch +% On Linux: +% ./run_spm8.sh +% ./run_spm8.sh run % -% Note that when compiling, it is important to be careful with your -% startup.m file. See the following link for more information: -% http://www.mathworks.com/support/solutions/data/1-QXFMQ.html?1-QXFMQ -%_______________________________________________________________________ -% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging +% 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: make_exec.m 3226 2009-06-25 18:13:11Z volkmar $ - -%======================================================================= -%-Files to include explicitly -%======================================================================= -% Matlab compiler will include all files that are referenced explicitly -% in the compiled code. If there is a file missing (e.g. data file, -% (f)eval'ed file), add it to the 'includefiles' list with its full -% path. If you want to add a directory and all of its contents, add it to -% the 'includedirs' list with its full path. -% By default, all files in spm('dir') are included and all subdirectories -% except matlabbatch, config and exec. Selected files from these -% directories will be included if they are referenced from any compiled -% function. Including spm('dir') instead would cause unwanted side -% effects during batch initialisation. - -%-List of files -%----------------------------------------------------------------------- -[includefiles includedirs] = cfg_getfile('FPList',spm('dir'),'.*'); - -%-Clean up list of directories -%----------------------------------------------------------------------- -includedirs = includedirs(~(strcmp(includedirs,fullfile(spm('dir'),'config'))| ... - strcmp(includedirs,fullfile(spm('dir'),'exec'))| ... - strcmp(includedirs,fullfile(spm('dir'),'matlabbatch')))); +% $Id: make_exec.m 3789 2010-03-19 17:05:36Z guillaume $ -includefiles = [includefiles; includedirs]; -%-Add '-a' switch for each file to include -%----------------------------------------------------------------------- -sw = cell(size(includefiles)); -[sw{:}] = deal('-a'); -tmp = [sw includefiles]'; -includefiles = tmp(:); +%-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 -%======================================================================= -%-Configuration management -%======================================================================= -% 1) locate all currently used batch configs -% 2) copy them to fullfile(spm('dir'),'exec') with unique names -% 3) create fullfile(spm('dir'),'exec','cfg_master.m') which calls the -% configs at runtime -% compiled spm_jobman will execute this file and add the applications +if ~nargin, outdir = fullfile(spm('dir'),'exec'); end -%-Locate batch configs and copy them -%----------------------------------------------------------------------- -apps = which('cfg_mlbatch_appcfg','-all'); -cfgfiles = cell(1,2*numel(apps)+2); -for k = 1:numel(apps) - cfgfiles{2*k-1} = '-a'; - cfgfiles{2*k} = fullfile(spm('dir'),'exec',sprintf('cfg_mlbatch_appcfg_%d.m',k)); - copyfile(apps{k}, cfgfiles{2*k}); +%========================================================================== +%-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 - -%-Create code for cfg_master.m -%----------------------------------------------------------------------- -cfgfiles{end-1} ='-a'; -cfgfiles{end} = fullfile(spm('dir'),'exec','cfg_master.m'); -fid = fopen(cfgfiles{end},'w'); -fprintf(fid,'function cfg_master\n'); -for k = 1:numel(apps) - fprintf(fid,'[cfg, def] = cfg_mlbatch_appcfg_%d;\n', k); - if strcmp(apps{k},... - fullfile(spm('dir'),'config','cfg_mlbatch_appcfg.m')) - % 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 - % assume that tools are the last thing in SPM config - fprintf(fid,'cfg.values{end}.values = {%s %s};\n', ftstr, ftcstr); - end +if ~isempty(ft)||~isempty(ftc) + if isempty(ft) + ftstr = ''; + else + ft = cellfun(@(cft)strtok(cft,'.'),ft,'UniformOutput',false); + ftstr = sprintf('%s ', ft{:}); end - fprintf(fid,'cfg_util(''addapp'', cfg, def);\n'); + 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); -%======================================================================= -%-Compile -%======================================================================= -mcc('-m','-v','-o',['spm_' computer],'exec_spm.m' ,'spm_load.m', '-I',spm('Dir'),includefiles{:},cfgfiles{:}) -mcc('-m','-v','-o',['jobman_' computer],'exec_jobman.m','spm_load.m', '-I',spm('Dir'),includefiles{:},cfgfiles{:}) +%========================================================================== +%-Static listing of batch application initialisation files +%========================================================================== +cfg_util('dumpcfg'); + +%========================================================================== +%-Compilation +%========================================================================== +mcc('-m', '-C', '-v', '-o',lower(spm('Ver')), 'exec_spm.m',... + '-d',outdir,... + '-N','-p',fullfile(matlabroot,'toolbox','signal'),... + '-a',spm('Dir')) diff --git a/external/Makefile b/external/Makefile index 8a9e46f..789bb16 100644 --- a/external/Makefile +++ b/external/Makefile @@ -3,37 +3,30 @@ # # Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging # -# $Id: Makefile 2990 2009-03-28 17:33:52Z guillaume $ +# $Id: Makefile 3890 2010-05-17 11:17:19Z guillaume $ include ../src/Makefile.var FIELDTRIPMEX =\ - fieldtrip/@config/private/deepcopy.$(SUF) fieldtrip/@config/private/increment.$(SUF) \ - fieldtrip/@config/private/reset.$(SUF) \ - fieldtrip/@uint64/max.$(SUF) fieldtrip/@uint64/min.$(SUF) \ - fieldtrip/@uint64/minus.$(SUF) fieldtrip/@uint64/plus.$(SUF) \ - fieldtrip/@uint64/rdivide.$(SUF) fieldtrip/@uint64/times.$(SUF) \ - fieldtrip/@uint64/abs.$(SUF) \ + fieldtrip/fileio/private/mxDeserialize.$(SUF) fieldtrip/fileio/private/mxSerialize.$(SUF) \ + fieldtrip/fileio/private/read_16bit.$(SUF) fieldtrip/fileio/private/read_24bit.$(SUF) \ + fieldtrip/fileio/@uint64/max.$(SUF) fieldtrip/fileio/@uint64/min.$(SUF) \ + fieldtrip/fileio/@uint64/minus.$(SUF) fieldtrip/fileio/@uint64/plus.$(SUF) \ + fieldtrip/fileio/@uint64/rdivide.$(SUF) fieldtrip/fileio/@uint64/times.$(SUF) \ + fieldtrip/fileio/@uint64/abs.$(SUF) \ + \ + fieldtrip/forward/private/lmoutr.$(SUF) fieldtrip/forward/private/meg_leadfield1.$(SUF) \ + fieldtrip/forward/private/plgndr.$(SUF) fieldtrip/forward/private/ptriproj.$(SUF) \ + fieldtrip/forward/private/solid_angle.$(SUF) \ + \ + fieldtrip/inverse/private/solid_angle.$(SUF) \ + \ fieldtrip/private/lmoutr.$(SUF) fieldtrip/private/ltrisect.$(SUF) \ - fieldtrip/private/meg_leadfield1.$(SUF) fieldtrip/private/plgndr.$(SUF) \ - fieldtrip/private/plinproj.$(SUF) fieldtrip/private/ptriproj.$(SUF) \ - fieldtrip/private/read_24bit.$(SUF) fieldtrip/private/routlm.$(SUF) \ - fieldtrip/private/solid_angle.$(SUF) fieldtrip/private/splint_gh.$(SUF) - -FILEIOMEX =\ - fileio/@uint64/max.$(SUF) fileio/@uint64/min.$(SUF) \ - fileio/@uint64/minus.$(SUF) fileio/@uint64/plus.$(SUF) \ - fileio/@uint64/rdivide.$(SUF) fileio/@uint64/times.$(SUF) \ - fileio/@uint64/abs.$(SUF) \ - fileio/private/read_24bit.$(SUF) \ - fileio/private/mxSerialize.$(SUF) fileio/private/mxDeserialize.$(SUF) \ - fileio/private/read_ctf_shm.$(SUF) fileio/private/write_ctf_shm.$(SUF) # Unix only - -FORWINVMEX =\ - forwinv/private/lmoutr.$(SUF) forwinv/private/ltrisect.$(SUF) \ - forwinv/private/meg_leadfield1.$(SUF) forwinv/private/plgndr.$(SUF) \ - forwinv/private/plinproj.$(SUF) forwinv/private/ptriproj.$(SUF) \ - forwinv/private/routlm.$(SUF) forwinv/private/solid_angle.$(SUF) + fieldtrip/private/plgndr.$(SUF) fieldtrip/private/plinproj.$(SUF) \ + fieldtrip/private/ptriproj.$(SUF) fieldtrip/private/routlm.$(SUF) \ + fieldtrip/private/solid_angle.$(SUF) fieldtrip/private/splint_gh.$(SUF) \ + \ + fieldtrip/fileio/private/read_ctf_shm.$(SUF) fieldtrip/fileio/private/write_ctf_shm.$(SUF) # Unix only BEMCP = bemcp @@ -56,6 +49,25 @@ bemcp bemcp-all bemcp-clean bemcp-distclean bemcp-install bemcp-tarball: %.$(SUF) : %.c $(MEX) $< -outdir $(shell dirname $<) $(MEXEND) +fieldtrip/forward/private/lmoutr.$(SUF): fieldtrip/forward/private/lmoutr.c fieldtrip/forward/private/geometry.c fieldtrip/forward/private/geometry.h + $(MEX) $< -outdir $(shell dirname $<) fieldtrip/forward/private/geometry.c $(MEXEND) + +fieldtrip/forward/private/ltrisect.$(SUF): fieldtrip/forward/private/ltrisect.c fieldtrip/forward/private/geometry.c fieldtrip/forward/private/geometry.h + $(MEX) $< -outdir $(shell dirname $<) fieldtrip/forward/private/geometry.c $(MEXEND) + +fieldtrip/forward/private/plinproj.$(SUF): fieldtrip/forward/private/plinproj.c fieldtrip/forward/private/geometry.c fieldtrip/forward/private/geometry.h + $(MEX) $< -outdir $(shell dirname $<) fieldtrip/forward/private/geometry.c $(MEXEND) + +fieldtrip/forward/private/ptriproj.$(SUF): fieldtrip/forward/private/ptriproj.c fieldtrip/forward/private/geometry.c fieldtrip/forward/private/geometry.h + $(MEX) $< -outdir $(shell dirname $<) fieldtrip/forward/private/geometry.c $(MEXEND) + +fieldtrip/forward/private/routlm.$(SUF): fieldtrip/forward/private/routlm.c fieldtrip/forward/private/geometry.c fieldtrip/forward/private/geometry.h + $(MEX) $< -outdir $(shell dirname $<) fieldtrip/forward/private/geometry.c $(MEXEND) + +fieldtrip/forward/private/solid_angle.$(SUF): fieldtrip/forward/private/solid_angle.c fieldtrip/forward/private/geometry.c fieldtrip/forward/private/geometry.h + $(MEX) $< -outdir $(shell dirname $<) fieldtrip/forward/private/geometry.c $(MEXEND) + + fieldtrip/private/lmoutr.$(SUF): fieldtrip/private/lmoutr.c fieldtrip/private/geometry.c fieldtrip/private/geometry.h $(MEX) $< -outdir $(shell dirname $<) fieldtrip/private/geometry.c $(MEXEND) @@ -73,22 +85,3 @@ fieldtrip/private/routlm.$(SUF): fieldtrip/private/routlm.c fieldtrip/private/ge fieldtrip/private/solid_angle.$(SUF): fieldtrip/private/solid_angle.c fieldtrip/private/geometry.c fieldtrip/private/geometry.h $(MEX) $< -outdir $(shell dirname $<) fieldtrip/private/geometry.c $(MEXEND) - - -forwinv/private/lmoutr.$(SUF): forwinv/private/lmoutr.c forwinv/private/geometry.c forwinv/private/geometry.h - $(MEX) $< -outdir $(shell dirname $<) forwinv/private/geometry.c $(MEXEND) - -forwinv/private/ltrisect.$(SUF): forwinv/private/ltrisect.c forwinv/private/geometry.c forwinv/private/geometry.h - $(MEX) $< -outdir $(shell dirname $<) forwinv/private/geometry.c $(MEXEND) - -forwinv/private/plinproj.$(SUF): forwinv/private/plinproj.c forwinv/private/geometry.c forwinv/private/geometry.h - $(MEX) $< -outdir $(shell dirname $<) forwinv/private/geometry.c $(MEXEND) - -forwinv/private/ptriproj.$(SUF): forwinv/private/ptriproj.c forwinv/private/geometry.c forwinv/private/geometry.h - $(MEX) $< -outdir $(shell dirname $<) forwinv/private/geometry.c $(MEXEND) - -forwinv/private/routlm.$(SUF): forwinv/private/routlm.c forwinv/private/geometry.c forwinv/private/geometry.h - $(MEX) $< -outdir $(shell dirname $<) forwinv/private/geometry.c $(MEXEND) - -forwinv/private/solid_angle.$(SUF): forwinv/private/solid_angle.c forwinv/private/geometry.c forwinv/private/geometry.h - $(MEX) $< -outdir $(shell dirname $<) forwinv/private/geometry.c $(MEXEND) diff --git a/external/ctf/COPYING b/external/ctf/COPYING new file mode 100644 index 0000000..187eebc --- /dev/null +++ b/external/ctf/COPYING @@ -0,0 +1,24 @@ +MATLAB Import/Export Routines +Version 1.3 + +The MATLAB functions in this directory are written by Dr. +Harold Wilson and provided courtesy of MEG International +Services Ltd. (MISL) (formerly VSM MedTech Ltd., manufacturer +of CTF MEG systems). + +Explicit permission to use, modify and redistribute this code +with FieldTrip and SPM is granted by MISL, with the following +caveats: + +1. These programs are not validated and must not be used for +clinical applications. The user assumes all responsibility +with their use. If CTF MEG data are processed by this tool, +they should not be later employed for clinical and/or +diagnostic purposes. + +2. MISL does not support these utilities, and any feedback +should go through the usual FieldTrip/SPM channels, e.g. +the email lists. + +These functions are not part of FieldTrip nor SPM and the +copyrights belong to the manufacturer. diff --git a/external/ctf/CTF_MATLAB_v13.pdf b/external/ctf/CTF_MATLAB_v13.pdf new file mode 100644 index 0000000..a100bea Binary files /dev/null and b/external/ctf/CTF_MATLAB_v13.pdf differ diff --git a/external/ctf/CTF_MatlabImportExportRoutines.pdf b/external/ctf/CTF_MatlabImportExportRoutines.pdf deleted file mode 100644 index ad735f7..0000000 Binary files a/external/ctf/CTF_MatlabImportExportRoutines.pdf and /dev/null differ diff --git a/external/ctf/README b/external/ctf/README index 27a3e04..96e0ef5 100644 --- a/external/ctf/README +++ b/external/ctf/README @@ -1,5 +1,11 @@ -The MATLAB functions in this directory are provided courtesy of -the manufacturer. The precompiled/compiled functions are released -in combination with FieldTrip and SPM with explicit permission of -the manufacturer. The code is not part of FieldTrip nor SPM and the -copyrights belong to the manufacturer. +MATLAB Import/Export Routines +Version 1.3 + +The MATLAB functions in this directory are provided courtesy of +Dr. Harold Wilson, MEG International Services Ltd. (MISL) +(formerly VSM MedTech Ltd., manufacturer of CTF MEG systems). +Although these functions are released in conjunction with +FieldTrip and SPM, they are not part of the FieldTrip or SPM +projects. + +For copyright information, see the file COPYING in this directory. \ No newline at end of file diff --git a/external/ctf/VERSION b/external/ctf/VERSION new file mode 100644 index 0000000..b9214a9 --- /dev/null +++ b/external/ctf/VERSION @@ -0,0 +1 @@ +1.3 diff --git a/external/ctf/addCTFtrial.m b/external/ctf/addCTFtrial.m new file mode 100644 index 0000000..7f998ba --- /dev/null +++ b/external/ctf/addCTFtrial.m @@ -0,0 +1,1273 @@ +function cntrl=addCTFtrial(datasetname,data,unit,mrk,cls,badSegments); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% This program creates datasets that can be analyzed by CTF software. % +% % +% Datasets created by this program MUST NOT BE USED FOR CLINICAL APPLICATIONS. % +% % +% Please do not redistribute it without permission from VSM MedTech Ltd. % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +% addCTFtrial.m Version 1.1 Adds trial(s) to a a CTF-format data set previously +% created from MATLAB by writeCTFds.m. The purpose of addCTFtrial is to allow +% users to write CTF data sets that are too large for the computer's memory. + +% Date : 18 April 2007 +% Author : Harold Wilson + +% Operation : +% 1. Use writeCTFds to create a dataset (name = DATASET) consisting of one or +% more trials. size(data)= [SAMPLES, CHANNELS, TRIALS]. +% 2. Later, a trial is to be added to DATASET. This program adds the new information +% to the .res4, .mrk, .cls and badSegements files and appends the new data to the +% existing .meg4 file. + +% Inputs : datasetname : Dataset including path. Extension '.ds' is optional. +% data : MEG data array. size(data)=[no_samples no_channels no_trials_added] +% Array data may be single or double. +% unit : Determines the unit of the SQUID and EEG signals: +% If unit is missing or unit==[], the unit is set to 'fT'. +% 'ft' or 'fT' : Convert to fT (MEG), uV (EEG) +% 't' or 'T' : Convert to T (MEG), V (EEG) +% 'phi0' : Convert to phi0 (MEG), uV (EEG) +% 'int': Read plain integers from *.meg4-file +% mrk,cls,badSegments : Structures describing the markers, trial classes and bad +% segments of the new trials. Trial numbering refers to the new trials +% being added to the dataset, starting at trial=1. Markers are updated +% only when there is already as .mrk file in the dataset. + +% Outputs : - Dataset with trial(s) added. +% - cntrl : 0 - failure. The dataset is not modified. +% 1 - success. The new data is added to the dataset + +% Function calls +% Included in this listing: +% - combineMarkers: Combines marker specifications in structures ds.mrk and mrk. +% - combineClasses: Combines trial class specifications in structures +% ds.TrialClass and cls. +% - writeBadSegments: Creates the new bad.segments file. +% - writeClassFile: Creates the new ClassFile.cls file. +% - updateCreatorSoftware: Adds non-clinical-use and creation software messages to +% infods, res4, newds and hist fields of ds. +% - updateHLC: Adds head-coil movement information from the trials being added to an +% existing ds.infods. +% - getArrayField : Extracts one field of a structure array to make it easier to +% manipulate. + +% Not included in this listing: +% - writeRes4: Writes the new .res4 file. +% - writeMarkerFile: Creates the new MarkerFile.mrk file. +% - writeCPersist: Creates the new .acq and .infods files. + +% Output files are opened with 'w' permission and 'ieee-be' machine format in order +% to be compatible with the Linux acquisition and analysis software. Do not open files +% with 'wt' permission because this will add an extra byte (char(13)) at the end of each +% line of text. + +%persistent printWarning % No clinical-use warning with addCTFtrial. +%printWarning=1; +delim=filesep; + +if nargin==0 & nargout==0 % Print a version number + fprintf(['\taddCTFtrial: Version 1.1 18 April 2007 ',... + 'Adds trials to v4.1 and v4.2 CTF data sets.\n',... + '\tCall: cntrl=addCTFtrial(datasetname,data,unit,mrk,cls,badSegments);\n',... + '\t\tdatasetname = Name of existing dataset including the path.\n',... + '\t\tdata = Data that will be written to the new dataset .meg4 file.\n',... + '\t\tunit = Physical units of the data.\n',... + '\t\tmrk,cls,badSegments = descriptions of markers, trial classes and',... + ' bad segments of data.\n\n']); + return +end +% Indicate failure on an early return. +cntrl=0; + +% Allowed 8-byte headers for res4 and meg4 files. +res4_headers=strvcat(['MEG41RS',char(0)],['MEG42RS',char(0)]); +meg4_headers=strvcat(['MEG41CP',char(0)],['MEG42CP',char(0)]); + +MAX_COILS=8; % Parameter that determines the size of the ds.res4.senres structure. +maxMEG4Size=2^31; % Maximum MEG$ file in bytes. (Limit set by Linux software) + +% addCTFds will add trials to datasets only if they were created by writeCTFds. +originalCreatorSoftware='writeCTFds'; +creatorSoftware='addCTFtrial'; % Added to .infods file +meg4ChunkSize=2^20; % Write new .meg4 file in chunks of 4*meg4ChunkSize bytes. + +clinical_use_message='NOT FOR CLINICAL USE'; + +if ~exist('clinical_use_message'); + clinical_use_message=char([]); +end + +% Check number of inputs +if nargin<2 + fprintf(['addCTFtrial: Must supply inputs datasetname,data. ',... + 'Only %d input arguments are present.\n'],nargin); + return +end + +% Check input argument unit. Convert unit to lower case. +if exist('unit')~=1 + unit='ft'; % default +elseif isempty(unit) + unit='ft'; % default +elseif ischar(unit) + unit=lower(unit); + if ~strcmp(unit,'int') & ~strcmp(unit,'ft') & ~strcmp(unit,'t') & ~strcmp(unit,'phi0') + fprintf(['addCTFtrial : unit=%s Not a valid option. Must be ',... + '''fT'', ''T'', ''phi0'' or ''int''\n'],unit); + ds=-1; % Force an error in the calling program. + return + end +end + +% Check argument type +if ~isnumeric(data) + fprintf('\naddCTFtrial: Input data is not numeric.\n'); + return +elseif ~ischar(unit) + fprintf('\naddCTFtrial: Input unit is not char.\n'); + return +elseif~ischar(datasetname) + fprintf('\naddCTFtrial: Input datasetname is not char.\n'); + return +end +if exist('mrk')==1 + if ~isstruct(mrk) + fprintf('\naddCTFtrial: Input mrk is not a structure.\n\n'); + return + end +else + mrk=struct([]); +end +if exist('cls')==1 + if ~isstruct(cls) + fprintf('\naddCTFtrial: Input cls is not a structure.\n\n'); + return + end +else + cls=struct([]); +end +if exist('badSegments')==1 + if ~isstruct(badSegments) + fprintf('\naddCTFtrial: Input badSegments is not a structure.\n\n'); + return + end +else + badSegments=struct([]); +end + +% Does the dataset exist? +if exist(datasetname)~=7 + fprintf('addCTFtrial: Dataset %s does not exist.\n',datasetname); + return +end + +% Separate datasetname into a path and the baseName +datasetname=deblank(datasetname); +ksep=max([0 findstr(datasetname,delim)]); +baseName=datasetname((ksep+1):length(datasetname)); +path=datasetname(1:ksep); % String path is terminated by the file delimiter (or path=[]). +% Remove the last .ds from baseName. +kdot=max(findstr(baseName,'.ds')); +if kdot==(length(baseName)-2) + baseName=baseName(1:(max(kdot)-1)); +else + datasetname=[datasetname,'.ds']; +end +clear ksep kdot; + +% Get the ds structure of the dataset +ds=readCTFds(datasetname); + +% Update text fields of res4,infods, newds. +ds=updateCreatorSoftware(ds,creatorSoftware,originalCreatorSoftware); +if isempty(ds);return;end + +nSample=ds.res4.no_samples; +fSample=ds.res4.sample_rate; +nChan=ds.res4.no_channels; + +% Check that the new data and the existing data have the same number of channels +% and points per trial. +if size(data,1)~=nSample | size(data,2)~=nChan | size(data,3)==0 + fprintf(['addCTFtrial: size(data)=[%d %d %d], but existing data has no_samples=%d,',... + ' no_channels=%d\n'],[size(data,1) size(data,2) size(data,3)],... + nSample,nChan); + return +end + +% Update ds.res4 fields to match the size of array data. +nTrialNew=size(data,3); +nTrialOld=ds.res4.no_trials; +ds.res4.no_trials=nTrialOld+nTrialNew; +ds.res4.epoch_time=nSample*ds.res4.no_trials/fSample; + +% Before converting data to integers, save the HLC channels for motion analysis in function +% function updateHLC. +if isempty(strmatch('HLC',ds.res4.chanNames)) + HLCdata=[]; +else + % Make a list of head-coil channels + coil=0; + HLClist=[]; + while ~isempty(strmatch(['HLC00',int2str(coil+1)],ds.res4.chanNames)) + coil=coil+1; + for k=1:3 + HLClist=[HLClist strmatch(['HLC00',int2str(coil),int2str(k)],ds.res4.chanNames)]; + end + end + HLCdata=reshape(double(data(:,HLClist,:)),nSample,3,coil,nTrialNew); + clear coil k HLClist; +end + +% Convert data to integers because CTF data sets are stored as raw numbers and +% not as physical qunatities. The res4 file contains the calibrations for +% converting back to physical units. Array data may be single precision, so +% convert to double before doing any adjustments to the data. +% Already checked that unit is valid. + +if strcmp(unit,'int') + data=reshape(data,nSample,nChan*nTrialNew); + for k=1:nChan*nTrialNew + if strcmp(class(data),'single') + data(:,k)=single(round(double(data(:,k)))); + else + data(:,k)=round(double(data(:,k))); + end + end + data=reshape(data,nSample,nChan,nTrialNew); + clear k; +else + for chan=1:nChan % Convert EEGs from uV to V, SQUIDs from fT to T + SQUIDtype=any(ds.res4.senres(chan).sensorTypeIndex==[0:7]); + EEGtype=any(ds.res4.senres(chan).sensorTypeIndex==[8 9]); + if EEGtype & (strcmp(unit,'ft') | strtcmp(unit,'phi0')) + alphaG=1e-6; + elseif SQUIDtype & strcmp(unit,'ft') + alphaG=1e-15; + elseif SQUIDtype & strcmp(unit,'phi0') + alphaG=1./(ds.res4.senres(chan).properGain*ds.res4.senres(chan).ioGain); + else + alphaG=1; + end + % Convert from physical units to integers using the gains in the senres table. + for kt=1:nTrialNew + buff=round(double(data(:,chan,kt))*(alphaG*... + (ds.res4.senres(chan).properGain*ds.res4.senres(chan).qGain*ds.res4.senres(chan).ioGain))); + if strcmp(class(data),'single') + data(:,chan,kt)=single(buff); + else + data(:,chan,kt)=buff; + end + end + end + clear chan alphaG SQUIDtype EEGtype buff kt; +end + +% Check the meg4 file header. + +fidMeg4=fopen([path,baseName,'.ds\',baseName,'.meg4'],'r','ieee-be'); +fileHeader=fread(fidMeg4,8,'char')'; +fclose(fidMeg4); + +if isempty(strmatch(fileHeader(1:7),meg4_headers(:,1:7),'exact')) + ds.meg4.header=meg4_headers(1,1:7); + fprintf('addCTFtrial: meg4 header=%s ?\n',fileHeader); + return +end + +% Create the .res4 file in the output dataset. +ds.res4=writeRes4([path,baseName,'.ds\',baseName,'.res4'],ds.res4,MAX_COILS); + +if ds.res4.numcoef<0 + fprintf('addCTFtrial: writeRes4 returned ds.res4.numcoef=%d (<0??)\n',ds.res4.numcoef); + fprintf(' Deleting dataset %s\n',baseName); + rmdir([path,baseName,'.ds'],'s'); + return +end + +% Add trial(s) to the existing meg4 file. Complicated coding in case the use requests +% writing several trials, which fill up one meg4 file and start the next one. + +ptsPerTrial=nSample*nChan; +data=reshape(data,ptsPerTrial,nTrialNew); +maxTrialPerFile=floor((maxMEG4Size-8)/(4*ptsPerTrial)); +maxPtsPerFile=ptsPerTrial*maxTrialPerFile; + +nExt=-1; +trial=0; +pt=0; +while trial0 + fidMeg4=fopen(meg4File,'a','ieee-be'); + endPt=pt+nWrite*ptsPerTrial; + while pt=1 & ... + maxMarkerTime<=(res4.no_samples/res4.sample_rate) & ... + minMarkerTime>=(-res4.preTrigPts/res4.sample_rate)); + if ~MarkerFileOK + fprintf(['addCTFtrial: Structure mrk cannot possibly be a set of markers ',... + 'for %d trial(s) in array(data).\n'],nTrialNew); + fprintf([' minMarkerTrial=%d (must be >=1) ',... + 'maxMarkerTrial=%d (must be <=%d)\n'],... + minMarkerTrial,maxMarkerTrial,ds.res4.no_trials); + fprintf([' minMarkerTime=%7.4f (must be >=%7.4f) ',... + 'maxMarkerTrial=%7.4f (must be <=%7.4f )\n'],... + minMarkerTime,-res4.preTrigPts/res4.sample_rate,... + maxMarkerTime,res4.no_samples/res4.sample_rate); + fprintf(' MarkerFile.mrk will not be updated.\n'); + end + end +end + +if MarkerFileOK==0 + mrkNew=struct([]); % return an empty marker structure + % Check mrkOld to see if each existing trial had at least one marker. + if isequal(unique([mrkOld.trial]),[1:nTrialOld]) + fprintf(['addCTFtrial: All of the trials in the existing data have at least one\n',... + ' marked point,but the new trials have no marker points?\n']); + end + return +end + +% There are valid new markers. Add the new markers to the existing marker structure, +% and extend the marker definition if new markers have been defined. +% Check the Name +mrkNew=mrkOld; +maxClassId=max([mrkNew.ClassId]); +for k=1:length(mrk) + addq=1; + % Check if the marker is already defined. + for q=1:length(mrkOld) + if strcmp(mrkOld(q).Name,mrk(k).Name) + mrkNew(q).trial=[mrkNew(q).trial mrk(k).trial+nTrialOld]; + mrkNew(q).time=[mrkNew(q).time mrk(k).time]; + addq=0; + break; + end + end + if addq % Create a new marker class + newClassId=~isfield(mrk(k),'ClassId'); + if ~newClassId + newClassId=any(mrk(k).ClassId==[mrkNew.ClassId]); + end + if newClassId + mrk(k).ClassId=max([mrkNew.ClassId])+1; + end + if ~isfield(mrk(k),'Color');mrk(k).Color='Red';end + if ~isfield(mrk(k),'Comment');mrk(k).Comment=char([]);end + if ~isfield(mrk(k),'ClassGroupId');mrk(k).ClassGroupId=3;end + if mrk(k).ClassGroupId==0 + if ~isfield(mrk(k),'BitNumber') | ~isfield(mrk(k),'Polarity') | ... + ~isfield(mrk(k),'Source') | ~isfield(mrk(k),'Threshold') + fprintf(['addCTFtrial: Structure mrk defines ClassGroupId=0 marker %s, ',... + 'but not fields BitNumber, Polarity, Source or Threshold.\n'],mrk(k).Name); + fprintf(' Marker set %s will be defined with ClassGroupId=3.\n',... + mrk(k).Name); + mrk(k).ClassGroupId=3; + end + end + % ClassGroupId : make 4 fields empty. + if mrk(k).ClassGroupId==3 + mrk(k).BitNumber=[]; + mrk(k).Polarity=[]; + mrk(k).Source=[]; + mrk(k).Threshold=[]; + end + q0=length(mrkNew)+1; + mrkNew(q0)=mrk(k); + mrkNew(q0).trial=mrk(k).trial+nTrialOld; + mrkNew(q0).time=mrk(k).time; + end + clear addq; +end +return +%%%%%%%%%%%%%% end of combineMarkers %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%% Function writeBadSegments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function writeBadSegments(badSegmentsFile,badSegments,nTrial,tTrial); + +% Creates a bad.segments file in a CTF data set from the information in structure +% badSegments which is created by read_badSegments, or by the user. +% If structure badSegments is empty, then the file is not created. + +% badSegments structure: +% badSegments.trial = List of trial numbers +% badSegments.StartTime = List of bad segment start times (relative to trial). +% badSegments.EndTime = List of bad segment end times. + +% Check badSegmentsFile +if exist('badSegmentsFile')~=1;badSegmentsFile=char([]);end +if isempty(badSegmentsFile) | ~ischar(badSegmentsFile) + fprintf('addCTFtrial(writeBadSegments): Bad file name.\n'); + badSegmentsFile + return +end + +% Check that structure badSegments is defined correctly +if exist('badSegments')~=1 | exist('nTrial')~=1 + return +elseif ~isstruct(badSegments) | isempty(badSegments) + return +elseif ~isfield(badSegments,'trial') | ~isfield(badSegments,'StartTime') | ... + ~isfield(badSegments,'EndTime') + return +elseif isempty(badSegments.trial) | isempty(badSegments.StartTime) | ... + isempty(badSegments.EndTime) + return +elseif ~isequal(size(badSegments.trial),size(badSegments.StartTime),... + size(badSegments.EndTime)) + fprintf(['\naddCTFtrial (writeBadSegments): ',... + 'The fields of structure badSegments do not all have the same size.\n']); + return +elseif any(badSegments.trial>nTrial) | any(badSegments.trial<1) | ... + any(badSegments.StartTime<0) | any(badSegments.EndTime>tTrial) + fprintf(['\naddCTFtrial (writeBadSegments): badSegments cannot possibly describe ',... + 'bad segments for these data.\n',... + '\tmin(badSegments.trial)=%d max(badSegments.trial)=%d ',... + 'min(badSegments.StartTime)=%0.4f max(badSegments.EndTime)=%0.4f s\n\t\tDataset:',... + ' nTrial=%d tTrial=%0.4f s\n'],... + min(badSegments.trial),max(badSegments.trial),min(badSegments.StartTime),... + max(badSegments.EndTime),nTrial,tTrial); + fprintf('\t\tNew bad.segments file will not be created.\n\n'); + return +end + +% Convert all fields to simple vectors +nSeg=prod(size(badSegments.trial)); +trial=reshape(badSegments.trial,1,nSeg); +StartTime=reshape(badSegments.StartTime,1,nSeg); +EndTime=reshape(badSegments.EndTime,1,nSeg); + +fid=fopen(badSegmentsFile,'w','ieee-be'); +if fid<0 + fprintf('writeCTFds (writeBadSegments): Could not open file %s\n',badSegmentsFile); + return +end +% Extra tabs are inserted to reproduce the format of bad.segments files produced by +% DataEditor (5.3.0-experimental-linux-20060918). +fprintf(fid,'%0.6g\t\t%0.6g\t\t%0.6g\t\t\n',[trial;StartTime;EndTime]); +fclose(fid); +return +%%%%%%%%% End of writeBadSegments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%Function checkCls %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function ClassFileOK=checkCls(ds); + +% Examines structure ds to see if a sensible ClassFile can be created from ds.TrialClass. + +ClassFileOK=isfield(ds,'TrialClass'); +if ClassFileOK + ClassFileOK=~isempty(ds.TrialClass); +end +if ClassFileOK + % Are the class trials appropriate? + minClassTrial=[]; + maxClassTrial=[]; + for k=1:length(ds.TrialClass) + maxClassTrial=max([maxClassTrial max(ds.TrialClass(k).trial)]); + minClassTrial=min([minClassTrial min(ds.TrialClass(k).trial)]); + end + % Create ClassFile.cls even when the trail classes are empty. + if ~isempty(maxClassTrial) + ClassFileOK=(maxClassTrial<=ds.res4.no_trials & minClassTrial>=1); + if ~ClassFileOK + fprintf(['\nwriteCTFds (checkCls): ds.TrialClass cannot possibly be a set of ',... + 'trial classes for array(data).\n minClassTrial=%d (must be >=1) ',... + 'maxClassTrial=%d (must be <=%d)\n'],... + minClassTrial,maxClassTrial,ds.res4.no_trials); + fprintf(' ClassFile.cls will not be created.\n'); + end + end +end +return +%%%%%%%%%%%%%% end of checkCls %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%Function combineClasses %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function clsNew=combineClasses(clsOld,nTrialOld,cls,nTrialNew); +% Combines existing trial class information with classes for new trial(s) that are +% being added to the dataset by addCTFtral. + +% Start by examining the new markers defined in structure mrk. +% Examines structure ds to see if a sensible CLassFile can be created from clsOld and cls. +% Output: clsNew : New class structure. If the new classes are invalid, or empty, then +% clsNew=struct([]) is returned. + +ClassFileOK=~isempty(cls); +if ClassFileOK + if isempty([cls.trial]) + ClassFileOK=0; % Do not create ClassFile.cls if all of the trial classes are empty. + else + % Are the markers appropriate? + minClassTrial=min(min([cls.trial])); + maxClassTrial=max(max([cls.trial])); + ClassFileOK=(maxClassTrial<=nTrialNew & minClassTrial>=1); + if ~ClassFileOK + fprintf(['addCTFtrial: Structure cls cannot possibly be a set of classes ',... + 'for %d trial(s) in array data .\n'],nTrialNew); + fprintf([' minClassTrial=%d (must be >=1) ',... + 'maxClassTrial=%d (must be <=%d)\n'],... + minClassTrial,maxClassTrial,nTrialNew); + fprintf(' ClassFile.cls will not be updated.\n'); + end + end +end + +if ClassFileOK==0 + clsNew=struct([]); % return an empty class structure + % Check clsOld to see if each existing trial had at least one class. + if isequal(unique([clsOld.trial]),[1:nTrialOld]) + fprintf(['addCTFtrial: All of the trials in the existing data are assigned to at ',... + 'least one class\n',... + ' but the new trials have no classes?\n']); + end + return +end + +% There are valid new classes. Add the new classes to the existing class structure, +% and extend the class definition if new classes have been defined. +clsNew=clsOld; +maxClassId=max([clsNew.ClassId]); +for k=1:length(cls) + addq=1; + % Check if the class is already defined. + for q=1:length(clsOld) + if strcmp(clsOld(q).Name,cls(k).Name) + clsNew(q).trial=[clsNew(q).trial cls(k).trial+nTrialOld]; + addq=0; + break; + end + end + if addq % Create a new trial class + newClassId=~isfield(cls(k),'ClassId'); + if ~newClassId % Check if cls(k).ClassId is already in use. + newClassId=any(cls(k).ClassId==[clsNew.ClassId]); + end + if newClassId + cls(k).ClassId=max([clsNew.ClassId])+1; + end + if ~isfield(cls(k),'Color');cls(k).Color='Red';end + if ~isfield(cls(k),'Comment');cls(k).Comment=char([]);end + if ~isfield(cls(k),'ClassGroupId');cls(k).ClassGroupId=3;end + q0=length(clsNew)+1; + clsNew(q0)=cls(k); + clsNew(q0).trial=cls(k).trial+nTrialOld; + end + clear addq; +end +return +%%%%%%%%%%%%%% end of combineClasses %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%% Function writeClassFile %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function writeClassFile(ClassFile,TrialClass); + +% Write the ClassFile of a CTF data set. +% The CLassFile allows a user to store a list of trial classifications in a data set. +% The ClassFile format is defined in document CTF MEG File Formats, PN900-0088. +% This format is rigid. + +% Inputs : +% ClassFile : marker file including the full path and extension .mrk. +% TrialClass : Structure creted by read_ClassFile. + +% Output : ClassFile.cls. + +% Check input TrialClass. +if exist('TrialClass')~=1;TrialClass=[];end +if isempty(TrialClass) | ~isstruct(TrialClass) + fprintf('writeCTFds (writeClassFile): TrialClass is empty or is not a structure.\n'); + TrialClass + return +end + +% Check ClassFile +if exist('ClassFile')~=1;ClassFile=char([]);end +if isempty(ClassFile) | ~ischar(ClassFile) + fprintf('writeCTFds (writeClassFile): Bad file name.\n'); + ClassFile +end + +fid=fopen(ClassFile,'w','ieee-be'); +if fid<0 + fprintf('writeCTFds (writeClassFile): Could not open file %s\n',ClassFile); + return +end + +nClass=length(TrialClass); + +% Generate datasetname from ClassFIle. +ksep=max([0 strfind(ClassFile,filesep)]); +datasetname=ClassFile(1:ksep-1); +if isempty(datasetname);datasetname=cd;end + +fprintf(fid,'PATH OF DATASET:\n%s\n\n\n',datasetname); +fprintf(fid,'NUMBER OF CLASSES:\n%d\n\n\n',nClass); + +for k=1:nClass + if k==1 % Add sign character to make output match the output of Acq. + sgn=char([]); % There should be no real significance to this. + else % Why does DataEditor places the + sign only on ClassID 2,3,...? + sgn='+'; + end + No_of_Trials=prod(size(TrialClass(k).trial)); + fprintf(fid,'CLASSGROUPID:\n%s%d\nNAME:\n%s\nCOMMENT:\n%s\n',... + sgn,TrialClass(k).ClassGroupId,TrialClass(k).Name,TrialClass(k).Comment); + fprintf(fid,'COLOR:\n%s\nEDITABLE:\n%s\nCLASSID:\n%s%d\nNUMBER OF TRIALS:\n%d\n',... + TrialClass(k).Color,TrialClass(k).Editable,sgn,TrialClass(k).ClassId,No_of_Trials); + fprintf(fid,'LIST OF TRIALS:\nTRIAL NUMBER\n'); + % Subtract one so trial numbering starts at 0 in ClassFile.cls + fprintf(fid,'%20d\n',reshape(TrialClass(k).trial,1,No_of_Trials)-1); + fprintf(fid,'\n\n'); +end +fclose(fid); +return +%%%%%%%%%%%%%% end of writeClassFile %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%% Function updateCreatorSoftware %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function ds=updateCreatorSoftware(ds,creatorSoftware,originalCreatorSoftware); + +% Changes the creator software fields of the ds structure, and returns ds=struct([]) if +% field infods is missing from structure ds, or if it thinks that the dataset was not +% created by the MATLAB code specified by originalCreatorSoftware (i.e. writeCTFds). + +% Makes sure that creatorSoftware info is changed in structure infods, newds and res4. + +% Inputs: ds : ds structure produced by readCTFds. +% creatorSoftware : Character string indicating that the data set was +% modified by addCTFtrial. Added to infods tags listed in addCreatorTag and +% appName field of res4. +% originalCreatorSoftware : Character string indicating that the data set was +% created by writeCTFds. Added to infods tags listed in addCreatorTag and +% appName field of res4. + +% Output: ds : ds structure with changes to ds.infids, ds.res4, ds.newds. +% If the input ds structure does not indicate that iot was created by +% writeCTFds (originalCreatorSoftware), ds=struct([]) is returned. + +% Adds comment (clinical use message) and creator software name to infods, newds and hist files. + +if ~isfield(ds,'infods'); + fprintf(['addCTFtrial (updateCreatorSoftware): Structure ds does not include',... + ' field infods.\n']); + whos ds + ds=struct([]); % Force an error in the calling program + return +end + +% The infods tags and red4 fields that display creator software must also indicate that +% the dataset was created by originalCreatorSoftware. + +% infods tags that will display the creator software. +addCreatorTag=strvcat('_PROCEDURE_COMMENTS','_DATASET_STATUS',... + '_DATASET_COLLECTIONSOFTWARE','_DATASET_CREATORSOFTWARE'); +% res4 text fields that will display the creator software. +addCreatorField=strvcat('appName','run_description'); +addCreatorLength=[256 -1]'; % -1 indicates variable length + +if exist('creatorSoftware')~=1; + creatorSoftware=char([]); +elseif ~ischar(creatorSoftware) + creatorSoftware=char([]); +else + creatorSoftware=deblank(creatorSoftware); +end + +if exist('originalCreatorSoftware')~=1; + originalCreatorSoftware=char([]); +elseif ~ischar(originalCreatorSoftware) + originalCreatorSoftware=char([]); +else + originalCreatorSoftware=deblank(originalCreatorSoftware); +end +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Check that the string originalCreatorSoftware appears in the infods and res4 files. + +tagName=getArrayField(ds.infods,'name')'; +if length(ds.infods)==1;tagName=tagName';end + +% Update the infods fields. +for k=1:size(addCreatorTag,1) + q=strmatch(deblank(addCreatorTag(k,:)),tagName); + if isempty(q); + fprintf('addCTFtrial (updateCreatorSoftware): Tag %s is missing from ds.infods.\n',... + deblank(addCreatorTag(k,:))); + ds=struct([]); + return + elseif length(q)>1 + fprintf(['addCTFtrial (updateCreatorSoftware): Tag %s appears %d times in ',... + 'ds.infods.\n'],deblank(addCreatorTag(k,:)),length(q)); + ds=struct([]); + return + else + strng=ds.infods(q).data; + % Strng must contain originalCreatorSoftware + nChar=length(strng); + if length(originalCreatorSoftware)>0 + qpos=strfind(strng,originalCreatorSoftware); + if isempty(qpos) + fprintf(['addCTFtrial (updateCreatorSoftware): String %s does not appear in',... + ' ds.infods tag %s\n'],originalCreatorSoftware,addCreatorTag(k,:)); + fprintf([' This dataset was not created ',... + 'by CTF MATLAB Export software.\n']); + ds=struct([]); + return + end + qpos=qpos+length(originalCreatorSoftware)-1; + else + qpos=length(strng); + end + % Add creatorSoftware string if it is not already present. + if isempty(strfind(strng,creatorSoftware)) + ds.infods(q).data=[strng(1:qpos) ' ' creatorSoftware ' ' strng(qpos+1:nChar)]; + end + end +end + +% Update the res4 fields: add creatorSoftware message. +% Don't check field length. Truncate later. +for q=1:size(addCreatorField,1); + strng=deblank(getfield(ds.res4,deblank(addCreatorField(q,:)))); + nChar=length(strng); + if length(originalCreatorSoftware)>0 + qpos=strfind(strng,originalCreatorSoftware); + if isempty(qpos) + fprintf(['addCTFtrial (updateCreatorSoftware): String %s does not appear in',... + ' ds.res4.%s\n'],originalCreatorSoftware,deblank(addCreatorField(q,:))); + fprintf([' This dataset was not created ',... + 'by CTF MATLAB Export software.\n']); + ds=struct([]); + return + end + qpos=qpos+length(originalCreatorSoftware); + else + qpos=nChar; + end + % Add creatorSoftware string if it is not already present. + if isempty(strfind(strng,creatorSoftware)) + newStrng=[strng(1:qpos) ' ' creatorSoftware ' ' strng(qpos+1:nChar)]; + ds.res4=setfield(ds.res4,deblank(addCreatorField(q,:)),newStrng); + end +end +clear q strng nChar strng0 ns newStrng; + +% Update res4.run_description +ds.res4.run_description=[deblank(ds.res4.run_description),char(0)]; +ds.res4.rdlen=length(ds.res4.run_description); + +% Truncate the .res4. fields. Leave room for a final char(0). +for q=1:size(addCreatorField,1); + strng=deblank(getfield(ds.res4,deblank(addCreatorField(q,:)))); + if length(strng)>addCreatorLength(q)-1 & addCreatorLength(q)>0 + ds.res4=setfield(ds.res4,deblank(addCreatorField(q,:)),... + strng(length(strng)+[-addCreatorLength(q)+2:0])); + end +end +clear q strng; + +% Add the creator and comment information to the newds file +if isfield(ds,'newds'); + nChar=length(ds.newds); + % Keyword positions + aNpos=max(strfind(ds.newds,[char(9) 'appName:' char(9)])); + if isempty(aNpos) + fprintf(['addCTFtrial (updateCreatorSoftware): Keyword ''appName'' ',... + 'does not appear in ds.newds.\n',... + ' set ds.newds=[].\n']); + ds.newds=char([]); + else + eol=max([11 min(strfind(ds.newds(aNpos+1:length(ds.newds)),char(10)))]); + wPos=min(strfind(ds.newds(aNpos+[1:eol]),originalCreatorSoftware)); + addPos=min(strfind(ds.newds(aNpos+[1:eol]),creatorSoftware)); + if isempty(addPos) + if isempty(wPos) + ds.newds=[ds.newds(1:(aNpos+eol-1)) ' ' creatorSoftware ... + ds.newds((aNpos+eol):length(ds.newds))]; + else + ds.newds=[ds.newds(1:(aNpos+wPos+length(originalCreatorSoftware)-1)) ', ' ... + creatorSoftware ... + ds.newds((aNpos+wPos+length(originalCreatorSoftware)):length(ds.newds))]; + end + end + clear eol wPos addPos; + end + clear nChar aNpos; +end + +return +%%%%%%%%%%%%%% End of update_creatorSoftware %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%% Function updateHLC %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [infods,status]=updateHLC(infods,HLCdata,HLC0,nTrial0); +% Adds notes and continuous-head-localization tags to .infods file. +% Updates MAXHEADMOTION tags when called from addCTFtrial + +% Inputs : infods : Structure of tags to be written to output infods file. +% HLCdata : 0 or [] or not defined - There are no HLC channels +% (head-coil position) in the data. Just pass the existing tags to +% the output dataset. +% HLCdata : real array : size(HLCdata)=[samplesPerTrial 3 Ncoil nTrial] +% Calculate the head motion tags. +% HLC0 : Head coil positions (m) in dewar coordinates at the start of the run. +% size(HLC0)=[3 Ncoil] +% nTrial0=No. of trials of data already written to the dataset. + + +% Outputs : status : 0: Everything looks OK +% 1: Couldn't find _DATASET tags. +% <0: There is a problem with the new infods file. + +% Calls: +% - getArrayField: Extracts field names from structure array S. + +% Defaults for the head localization tags. +% Might do this better with a structure. + +HZ_MODE_UNKNOWN=2^31-1; % Bug in DataEditor and acquisition software, Oct. 2006 +% Should be -1. + +% New dataset tags for HLC specification. +addTag=strvcat('_DATASET_HZ_MODE',... + '_DATASET_MOTIONTOLERANCE',... + '_DATASET_MAXHEADMOTION',... + '_DATASET_MAXHEADMOTIONTRIAL',... + '_DATASET_MAXHEADMOTIONCOIL'); +addTagType=[5 4 4 7 10]'; + +if exist('nTrial0')~=1 + nTrial0=0; +elseif isempty(nTrial0) + nTrial0=0; +elseif min(nTrial0)<0 + nTrial0=0; +end +% Check HLCdata array. HLCdata=[] indicates no continuous head localization. +if exist('HLCdata')~=1 + HLCdata=[]; +elseif ~isempty(HLCdata) + [samplesPerTrial nDim Ncoil nTrial]=size(HLCdata); + if nDim~=3; + fprintf('addCTFtrial (updateHLC): size(HLCdata)=[');fprintf(' %d',size(HLCdata)); + fprintf(']\n'); + fprintf(' nDim=%d?? Setting HLCdata=[].\n',nDim); + HLCdata=[]; + end +end +if exist('HLC0')~=1 + HLC0=[]; +elseif ~isequal(size(HLC0),[3 size(HLCdata,3)]) + HLC0=[]; +end +if isempty(HLC0) & ~isempty(HLCdata) + HLC0=squeeze(HLCdata(1,:,:,1)); +end + +% Assume that all the tag names are different. There is no checking when a tag listed in +% addTag matches more than one entry in array name. +name=getArrayField(infods,'name')'; %size(name)=[nTag lengthTag] +DATASET_tags=strmatch('_DATASET',name)'; % size(DATASET_tags)=[1 nTag] +if isempty(DATASET_tags) + status=1; % No _DATASET tags. Don't add anything. +else + status=0; + if isempty(HLCdata) + TagValue(1)=HZ_MODE_UNKNOWN; + TextTagValue=char(0); + addTag=addTag(1,:); % Remove the other HLC tags + addTagType=addTagType(1); + else % ~isempty(HLCdata) + % Remove HLC offsets. + for q=1:Ncoil + for k=1:3 + HLCdata(:,k,q,:)=HLCdata(:,k,q,:)-HLC0(k,q); + end + end + % Calculate motions as displacement from the start of the dataset. + absMotion=squeeze(sqrt(sum(HLCdata.^2,2))); %size(absMotion)=[samplesPerTrial Ncoil nTrial] + maxCoilMotion=squeeze(max(absMotion,[],1)); % size(maxCoilMovement)=[Ncoil nTrial] + maxHeadMotion=max(max(maxCoilMotion)); + [mx maxHeadMotionCoil]=max(max(maxCoilMotion,[],2)); + [mx maxHeadMotionTrial]=max(max(maxCoilMotion,[],1)); + % Create a list of head motion tag values + TagValue(1)=5; % Indicates continuous head localization + TagValue(2)=max(2*maxHeadMotion,0.02); % _DATASET_MOTIONTOLERANCE + TagValue(3)=maxHeadMotion; + TagValue(4)=maxHeadMotionTrial-1+nTrial0; % _DATASET_MAXHEADMOTIONTRIAL + TextTagValue=strvcat(char(zeros(4,1)),sprintf('%d',maxHeadMotionCoil)); + + % Does the existing infods have the head-motion tags? + TagNo2=strmatch(deblank(addTag(2,:)),name,'exact'); + TagNo3=strmatch(deblank(addTag(3,:)),name,'exact'); + TagNo4=strmatch(deblank(addTag(4,:)),name,'exact'); + TagNo5=strmatch(deblank(addTag(5,:)),name,'exact'); + if ~isempty(TagNo2) & ~isempty(TagNo3) & ~isempty(TagNo4) & ... + ~isempty(TagNo5) & nTrial0>0 + % Structure infods already has the head-motions tags from previous data. + TagValue(2)=max(TagValue(2),infods(TagNo2).data); + if TagValue(3)<=infods(TagNo3).data + TagValue(3)=infods(TagNo3).data; + TagValue(4)=infods(TagNo4).data; + TextTagValue=strvcat(char(zeros(4,1)),infods(TagNo5).data); + end + elseif (~isempty(TagNo2) | ~isempty(TagNo3) | ~isempty(TagNo4) | ... + ~isempty(TagNo5)) & nTrial0>0 + fprintf(['addCTFtrial (updateHLC): Some, but not all, of the ds.infods CHL ',... + 'tags are defined.\n',... + ' Infods will be defines with information from the %d new ',... + 'trial(s) being added.\n'],size(HLCdata,4)); + end + TagValue=[TagValue 0]; % Placeholder only since the 5th tag is a text string. + end + + % Add or insert tags. + for q=1:size(addTag,1) + nTag=length(infods); + tagName=deblank(addTag(q,:)); + TagNo=strmatch(tagName,name,'exact')'; + if isempty(TagNo) % Insert a tag at the end of the _DATASET tags. + TagNo=max(DATASET_tags)+1; + infods((TagNo+1):(nTag+1))=infods(TagNo:nTag); + name=strvcat(name(1:TagNo-1,:),tagName,name(TagNo:nTag,:)); + DATASET_tags=[DATASET_tags TagNo]; + end + if addTagType(q)~=10 + infods(TagNo)=struct('name',tagName,'type',addTagType(q),'data',TagValue(q)); + else + infods(TagNo)=struct('name',tagName,'type',addTagType(q),... + 'data',deblank(TextTagValue(q,:))); + end + end % End loop over head position and head motion tags. + clear q TagNo TextTagValue TagValue; +end % End section add _DATASET tags + +return +%%%%%%%%%%%%%% End of updateHLC %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%% Function getArrayField %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function x=getArrayField(S,yfield) + +% Extracts one field of a structure array. +% Inputs: S : structure array. +% yfield: name of field of S (string) + +% Output: x. x(:,n)=S(n).yfield; size(x)=[size(yfield) length(S)] + +% Field sizes: Two options: +% 1. size(S(n).yfield) is the same for all n. Any size allowed. +% 2. S(n).yfield is a 2-D array for all structure elements S(n). +% Then yfield of different array elements S(n) can have different sizes. +% The array returned will be large enough to accomodate all of the data. + +sizeS=size(S); +nS=prod(sizeS); +S=reshape(S,1,nS); + +% Determine which array-size option to use. +sizey=size(getfield(S,{1},yfield)); +option1=1; +option2=(length(sizey)==2); +for n=2:nS + sizeyn=size(getfield(S,{n},yfield)); + option1=option1 & isequal(sizey,sizeyn); + option2=option2 & length(sizeyn)==2; + if option2 + sizey=max([sizey;sizeyn],[],1); + end +end + +if option1 % All fields have the same size + nY=prod(sizey); + if isnumeric(getfield(S,{1},yfield)) + x=zeros(nY,nS); + elseif ischar(getfield(S,{1},yfield)) + x=char(zeros(nY,nS)); + end + for n=1:nS + x(:,n)=reshape(getfield(S,{n},yfield),nY,1); + end + x=reshape(x,[sizey nS]); +elseif option2 % All fields have only two dimensions + if isnumeric(getfield(S,{1},yfield)) + x=zeros([sizey nS]); + elseif ischar(getfield(S,{1},yfield)) + x=char(zeros([sizey nS])); + end + for n=1:nS + y=getfield(S,{n},yfield); + sizeyn=size(y); + x(1:sizeyn(1),1:sizeyn(2),n)=y; + end +else + fprintf(['getArrayField: Field %s of the structure array has >2 dimensions ',... + 'and not all field have the same size.\n'],yfield); + x=[]; +end +x=squeeze(x); +return +%%%%%%%% End of getArrayField %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/external/ctf/addCTFtrial.p b/external/ctf/addCTFtrial.p deleted file mode 100644 index c9616c2..0000000 Binary files a/external/ctf/addCTFtrial.p and /dev/null differ diff --git a/external/ctf/getCTFBalanceCoefs.m b/external/ctf/getCTFBalanceCoefs.m new file mode 100644 index 0000000..1a6a4de --- /dev/null +++ b/external/ctf/getCTFBalanceCoefs.m @@ -0,0 +1,490 @@ +function [alphaMEG,MEGindex,MEGbalanceindex,alphaGref,Grefindex,Gbalanceindex]=... + getCTFBalanceCoefs(ds,balanceType,unit); + +% Reads balance coefficients for SQUID data in phi0's, and converts to coefficients +% for data in physical units. + +% Input : ds : (1) ds structure from readCTFds +% balanceType : 'NONE' : No balancing +% 'G1BR' : 1st order balancing +% 'G2BR' : 2nd order balancing +% 'G3BR' : 3rd order balancing +% 'G3AR' : 3rd order balancing + adaptive +% If only MEG balance table is requested, size(balanceType)=[1 5] +% If Gref balance table is requested also, size(balanceType)=[2 4] +% unit: Type of units. Option: 'fT','T','phi0','int'. +% If unit is not entered, of unit=[], the default is unit='fT'. + +% Outputs : +% alphaMEG,MEGindex,MEGbalanceindex : MEG balancing coefficients for data in fT or T. +% Suppose data array returned by getTrial2 has size(data)=[npt nchan]. +% nMEG = number of MEG channels in the data set. +% MEG channels have sensorTypeIndex==5. +% +% MEGindex = list of MEG channels referred to the channel numbering in +% the complete dataset (i.e. it is not referred to only the list of +% SQUID sensors). +% by looking for sensors with ds.res4.senres.sensorTypeIndex==5 +% size(MEGindex)=[1 nMEG] +% MEG data = data(:,MEGindex) + +% MEGbalanceindex = list of reference channels for MEG balancing. +% size(MEGbalanceindex)=[1 nRef] +% Reference data for MEG balancing = data(:,MEGbalanceindex) + +% alphaMEG = balance coefficients. size(alphaMEG)=[nRef nMEG] +% +% Balancing MEG data : +% - Start with data AFTER converting to physical units. +% (I.e. SQUID data must be in fT or T.) +% - balanced_data(:,MEGindex)=data(:,MEGindex)-data(:,MEGbalanceindex)*alphaMEG + +% If user specifies balanceType=[], ' ' or 'none', then getCTFBalanceCoefs returns +% alphaMEG=zeros(0,nMEG), MEGindex=list of MEG sensor channels, +% MEGbalanceindex=[], alphaGref=zeros(0,nGef), Grefindex=list of Gref channels +% and Gbalanceindex=[]; + +% alphaGref,Grefindex,Gbalanceindex : Reference-gradiometer balancing coeficients. +% These output arrays are optional. If the calling statement includes +% them, then this program extracts a table of balance coefficients for +% the reference gradiometers from the G1BR table in the coefficient files. +% nGref = no. of reference gradiometers channels in the data set +% (sensorTypeIndex=1) +% Grefindex = list of reference channels. size(Grefindex)=[1 nGref] +% Gradient reference data = data(:,Grefindex) +% Gbalanceindex = list of channels for balancing reference +% gradiometers. size(Gbalanceindex)=[1 nGbalcoef] +% Balancing reference data = data(:,Gbalanceindex) + +% alphaGref = balance coefficients for ref. grads. +% size(alphaGref)=[nGbalcoef nGref] +% +% Balancing ref. gradiometer data : +% - Use data AFTER converting to physical units. (I.e. data in fT or T.) +% balanced_data(:,Grefindex)=data(:,Grefindex)-data(:,Gbalanceindex)*alphaGref + +% Calls function getRawCTFBalanceCoefs (included in this listing). + +if nargout==0 & nargin==0 + fprintf(['\ngetCTFBalanceCoefs: Version 1.1 17 April 2007 ',... + 'Reads balance coefficients from ds.res4.scrr.\n\n',... + '\tMEG balancing : [alphaMEG,MEGindex,MEGbalanceindex]=',... + 'getCTFBalanceCoefs(ds,balanceType,unit);\n\n',... + '\tMEG & Gref balancing : [alphaMEG,MEGindex,MEGbalanceindex,',... + 'alphaGref,Grefindex,Gbalanceindex]=\n',... + '\t ',... + 'getCTFBalanceCoefs(ds,balanceType,unit);\n\n']); + return +end + +balanceOptions=strvcat('NONE','G1BR','G2BR','G3BR', 'G3AR'); +balanceOptionsEnds = [size(balanceOptions, 1), 2]; % Which options are available for MEGs and Grefs. +physical_options=strvcat('fT','T'); +raw_options=strvcat('phi0','int'); +unit_options=strvcat(physical_options,raw_options); +default_unit='fT'; + +% Specify outputs in case of an early return due to an error. +MEGindex=[]; +Grefindex=[]; +alphaMEG=[]; +MEGbalanceindex=[]; +alphaGref=[]; +Gbalanceindex=[]; + +% Check that the inputs are sensible. +if nargin<2 + fprintf(['\ngetCTFBalanceCoefs: Only %d input arguments? ',... + 'Must specify at least ds and balanceType.\n\n'],nargin); + return +elseif ~isstruct(ds) | isempty(ds) | ~ischar(balanceType) | isempty(balanceType) + fprintf('\ngetCTFBalanceCoefs: Wrong argument types or sizes.\n\n'); + whos ds balanceType + return +elseif ~isfield(ds,'res4') + fprintf('\ngetCTFBalanceCoefs: Field res4 is missing from structure ds.\n\n'); + ds + return +elseif size(balanceType,1)>2 + fprintf('\ngetCTFBalanceCoefs: size(balanceType)=[');fprintf(' %d',size(balanceType));... + fprintf('] Must be[1 4] or [2 4].\n\n'); + return +end +% Must have 3 or 6 output arguments. Set balanceType(2,:)='NONE' if necessary. +if ~any(nargout==[3 6]); + fprintf(['\ngetCTFBalanceCoefs: Called with %d output arguments. ',... + 'Must be 3 or 6.\n\n'],nargout); + return +elseif (nargout==3 & size(balanceType,1)>1) | (nargout==6 & size(balanceType,1)==1) + balanceType=strvcat(deblank(balanceType(1,:)),'NONE'); +end + +% At this point, size(balanceType,1)=2. + +% Check that balanceType has allowed values +for k=1:size(balanceType,1) % k=1:MEGs, k=2:Grefs + if isempty(strmatch(balanceType(k,:),balanceOptions(1:balanceOptionsEnds(k),:))) + fprintf('\ngetCTFBalanceCoefs: balanceType(%d,:)=%s Not an allowed option.\n\n',... + k,balanceType(k,:)); + return + end +end + +% Check the data units, convert to lower case and flag incorrect unit specification +if ~exist('unit'); + unit=default_unit; +elseif isempty(unit); + unit=default_unit; +elseif ~ischar(unit) + fprintf('\ngetCTFBalanceCoefs: Input unit has the wrong type: class(unit)=%s\n\n',... + class(unit)); + return +end +unit=lower(unit); +if isempty(strmatch(unit,lower(strvcat(physical_options,raw_options)))) + fprintf('\ngetCTFBalanceCoefs: unit=%s. Must be one of ',unit); + for k=1:size(unit_options,1);fprintf(' %s,',deblank(unit_options(k,:)));end; + fprintf('\n\n'); + return +end +physical=~isempty(strmatch(unit,lower(physical_options))); + +balanceType=upper(deblank(balanceType)); + +[betaMEG,MEGindex,MEGbalanceindex,betaGref,Grefindex,Gbalanceindex]=... + getRawCTFBalanceCoefs(ds,balanceType); + +% No balancing is requested, just return lists of MEGindex and Grefindex. +if isempty(MEGbalanceindex) + alphaMEG=zeros(0,length(MEGindex)); + MEGbalanceindex=[]; % force size=[0 0] +end +if isempty(Gbalanceindex) + alphaGref=zeros(0,length(Grefindex)); + Gbalanceindex=[]; % force size=[0 0] +end +if isempty(MEGbalanceindex) & isempty(Gbalanceindex) + return +end + +% betaMEG and betaGref are the balance coefficients when signals are in phi0's. +% Convert to balance coefficients when signals are in physical units (T or fT). +% invproperGain is introduced to take care of situations where bad channels +% are labelled by setting their gain to zero. + +if physical + properGain=zeros(1,ds.res4.no_channels); + invproperGain=zeros(1,ds.res4.no_channels); + for k=1:ds.res4.no_channels + if any(ds.res4.senres(k).sensorTypeIndex==[0 1 5:7]) % SQUIDs only + properGain(k)=ds.res4.senres(k).properGain; % properGain = phi0/T + if properGain(k)~=0 + invproperGain(k)=1/properGain(k); + end + end + end +end + +if ~isempty(MEGbalanceindex) + if physical + alphaMEG=betaMEG.*(properGain(MEGbalanceindex)'*invproperGain(MEGindex)); + else + alphaMEG=betaMEG; + end +end + +if ~isempty(Gbalanceindex) + if physical + alphaGref=betaGref.*(properGain(Gbalanceindex)'*invproperGain(Grefindex)); + else + alphaGref=betaGref; + end +end +return +%%%%%%%%%%% End of getBalanceCoef %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%% Function getRawCTFBalanceCoefs %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [betaMEG,MEGindex,Refindex,betaGref,Grefindex,Gbalanceindex]=... + getRawCTFBalanceCoefs(ds,balanceType); + +% getRawCTFBalanceCoefs. Extracts raw-data (i.e. integer data) gradiometer balancing +% coefficients from structure array ds.res4.scrr (ds is produced +% by readCTFds). + +% Date : 24 OCt 2006 +% Author : Harold Wilson + +% Inputs : ds : Structure returned by readCTFds. +% balanceType : 'NONE' : No balancing +% 'G1BR' : 1st order balancing +% 'G2BR' : 2nd order balancing +% 'G3BR' : 3rd order balancing +% 'G3AR' : 3rd order balancing + adaptive +% If only MEG balance table is requested, size(balanceType)=[1 4] +% If Gref balance table is requested also, size(balanceType)=[2 4] +% If balancing 'NONE' is specified, getRawCTFBalanceCoefs returns lists MEGindex and +% Grefindex, and sets Refindex=[], Gbalanceindex=[]. +% The reference gradiometers have only G1BR balancing coefficients. + +% Outputs : +% betaMEG,MEGindex,Refindex : MEG balancing coefficients. +% Suppose data array returned by getCTFdata has size(data)=[npt nchan]. +% nMEG = number of MEG channels in the data set. +% MEG channels have sensorTypeIndex==5. +% +% MEGindex = list of MEG channels in the data set. It is assembled +% by looking for sensors with ds.res4.senres.sensorTypeIndex==5 +% size(MEGindex)=[1 nMEG] +% MEG data = data(:,MEGindex) + +% Refindex = list of reference channels for MEG balancing. +% size(Refindex)=[1 nRef] +% Reference data = data(:,Refindex) + +% betaMEG = balance coefficients. size(betaMEG)=[nRef nMEG] +% +% Balancing MEG data : +% - Start with data BEFORE converting to physical units. +% (I.e. SQUID data must be in phi0's or raw integers.) +% - balanced_data(:,MEGindex)=data(:,MEGindex)-data(:,Refindex)*betaMEG + +% If user specifies balanceType=[] or ' ', then getRawCTFBalanceCoefs returns +% betaMEG=zeros(1,nMEG),Refindex=3 and nRef=1; + + +% betaGref,Grefindex,Gbalanceindex : Reference-gradiometer balancing coeficients. +% These output arrays are optional. If the calling statement includes +% them, then this program extracts a table of balance coefficients for +% the reference gradiometers from the G1BR table in the coefficient files. +% nGref = no. of reference gradiometers channels in the data set +% (sensorTypeIndex=1) +% Grefindex = list of reference channels. size(Grefindex)=[1 nGref] +% Gradient reference data = data(:,Grefindex) +% Gbalanceindex = list of channels for balancing reference +% gradiometers. size(Gbalanceindex)=[1 nGbalcoef] +% Balancing reference data = data(:,Gbalanceindex) + +% betaGref = balance coefficients for ref. grads. +% size(betaGref)=[nGbalcoef nGref] +% +% Balancing ref. gradiometer data : +% balanced_data(:,Grefindex)=data(:,Grefindex)-data(:,Gbalanceindex)*betaGref + +% No function calls. +missingMEGMessage=0; +missingGrefMessage=0; +balanceOptions=strvcat('NONE','G1BR','G2BR','G3BR', 'G3AR'); +balanceOptionsEnds = [size(balanceOptions, 1), 2]; % Which options are available for MEGs and Grefs. +common_mode_only=0; + +Brefindex=[]; % Index list of reference magnetometers in the data arrays +Grefindex=[]; % Index list of reference gradiometers in the data arrays +MEGindex=[]; % Index list of MEG sensors in the data arrays +Gbalanceindex=[]; % Index list of sensors used as references to balance the reference +% gradiometers +Refindex=[]; % Index list of sensors used to balance the MEG sensors +betaMEG=[]; +betaGref=[]; + +% Check that the inputs are sensible. +if nargin<2 + fprintf(['\ngetRawCTFBalanceCoefs: Only %d input arguments? ',... + 'Must specify at least ds and balance.\n\n'],nargin); + return +elseif ~isstruct(ds) | isempty(ds) | ~ischar(balanceType) | isempty(balanceType) + fprintf('\ngetRawCTFBalanceCoefs: Wrong argument types or sizes.\n\n'); + whos ds balanceType + return +elseif ~isfield(ds,'res4') + fprintf('\ngetRawCTFBalanceCoefs: Field res4 is missing from structure ds.\n\n'); + ds + return +end + +% Check that the output list is OK. +if nargout~=3 & nargout~=6 + fprintf('\ngetRawCTFBalanceCoefs : Call specifies %d output arguments.\n',nargout); + fprintf('\t\tMust have 3 output arguments (MEG balance coefficients)\n'); + fprintf('\t\tor 6 output arguments (reference gradiometer balancing also).\n\n'); + return +elseif nargout==3 + if size(balanceType,1)>1;balanceType=balanceType(1,:);end +else + if size(balanceType,1)==1;balanceType=strvcat(balanceType,'NONE');end +end + +% Check that balanceType has allowed values +for k=1:size(balanceType,1) % k=1:MEGs, k=2:Grefs + if isempty(strmatch(balanceType(k,:),balanceOptions(1:balanceOptionsEnds(k),:))) + fprintf('\ngetRawCTFBalanceCoefs: balance(%d,:)=%s Not an allowed option.\n\n',... + k,balanceType(k,:)); + return + end +end + +% Make lists of reference magnetometers, reference gradiometers and MEG sensors. +for q=1:length(ds.res4.senres) + if ds.res4.senres(q).sensorTypeIndex==0 + Brefindex=[Brefindex q]; + elseif ds.res4.senres(q).sensorTypeIndex==1 + Grefindex=[Grefindex q]; + elseif ds.res4.senres(q).sensorTypeIndex==5 % Allow other MEG sensors? + MEGindex=[MEGindex q]; + end +end +nBref=length(Brefindex); % Don't currently use Brefindex or nBref +nGref=length(Grefindex); +nMEG=length(MEGindex); + +nGbalcoef=0; % Set to zero until we know the number by examining ds.res4.scrr +if nargout==6 & strcmp(balanceType(2,:),'NONE') + Gbalanceindex=[]; + betaGref=zeros(0,nGref); +elseif nargout==6 & ~strcmp(balanceType(2,:),'NONE') + m1=1; % Get coefficients for balancing the reference gradiometers. + mtot=size(ds.res4.scrr,2); + for n=1:nGref + Gname=strtok(ds.res4.chanNames(Grefindex(n),:),['- ',char(0)]); + nGchar=length(Gname); + for m=[m1:mtot 1:(m1-1)] + if strncmp(Gname,char(ds.res4.scrr(m).sensorName),nGchar) & ... + strcmp('G1BR',char(ds.res4.scrr(m).coefType)); + if nGbalcoef<=0 % 1st match. Initialize table and get list of references + nGbalcoef=ds.res4.scrr(m).numcoefs; + betaGref=zeros(nGbalcoef,nGref); + % Assemble index array for balancing the reference gradiometers + for q=1:nGbalcoef + Refname=strtok(char(ds.res4.scrr(m).sensor(:,q))',['- ',char(0)]); + pRef=strmatch(Refname,ds.res4.chanNames); + if isempty(pRef) + fprintf(['getRawCTFBalanceCoefs : Sensor %s appears in ',... + 'ds.res4.scrr, but not in ds.res4.chanNames\n'],Refname); + return + end + Gbalanceindex=[Gbalanceindex pRef]; + end + end % end setup of balancing table for Ref. gradiometers + if ds.res4.scrr(m).numcoefs~=nGbalcoef + fprintf('\ngetRawCTFBalanceCoefs : %s has %d coefficients\n',... + ds.res4.chanNames(Grefindex(1),1:nGchar),nGbalcoef); + fprintf(' %s " %d " ????\n\n',... + ds.res4.chanNames(Grefindex(n),1:nGchar),ds.res4.scrr(m).numcoefs); + betaGref=[]; % Force useless output. + return + end + betaGref(:,n)=reshape(ds.res4.scrr(m).coefs(1:nGbalcoef),nGbalcoef,1); + m1=m+1; + break; % Break out of m-loop. Go to nect n value. + end + if (m==m1-1 & m1>1) | (m==mtot & m1==1) + if missingGrefMessage==0 + if strncmp(balanceType(2,:), balanceOptions(5,:), 4) + % Avoid warning for all sensors for adaptive coefficients. + fprintf('\ngetRawCTFBalanceCoefs: Failed to find %s balance coefficients for reference sensors.\n',... + balanceType(2,:)); + else + fprintf(['\ngetRawCTFBalanceCoefs: Failed to find %s balance coefficients',... + ' for sensor(s)'],balanceType(2,:)); + fprintf('\n\t\t\t\t'); + end + end + missingGrefMessage=missingGrefMessage+1; + if ~strncmp(balanceType(2,:), balanceOptions(5,:), 4) + if missingGrefMessage==10*round(missingGrefMessage/10) + fprintf('\n\t\t\t\t'); + end + fprintf(' %s',Gname); + end + betaGRef(:,n)=zeros(nGbalcoef,1); + return + end + end % End loop over m (searching for scrr(m).sensorName) + end % End loop over n (list of reference gradiometers) +end % End of section getting coefficients to balance the reference gradiometers. +if missingGrefMessage>0;fprintf('\n');end + +if strcmp(balanceType(1,:),'NONE') + Refindex=[]; + betaMEG=zeros(0,nMEG); + return +end + +% Get balance coefficients for the MEG sensors +nRef=0; +% Pointers for search through ds.res4.scrr structure array. +m1=1; +mtot=size(ds.res4.scrr,2); + +for n=1:nMEG + MEGname=strtok(ds.res4.chanNames(MEGindex(n),:),['- ',char(0)]); + nChar=length(MEGname); + for m=[m1:mtot 1:(m1-1)] + if strncmp(MEGname,char(ds.res4.scrr(m).sensorName),nChar) & ... + strcmp(balanceType(1,:),char(ds.res4.scrr(m).coefType)); + if nRef<=0 + nRef=ds.res4.scrr(m).numcoefs; + betaMEG=zeros(nRef,nMEG); + for q=1:nRef % Assemble index array for balancing the MEG sensors + Refname=strtok(char(ds.res4.scrr(m).sensor(:,q))',['- ',char(0)]); + pRef=strmatch(Refname,ds.res4.chanNames); + if isempty(pRef) + fprintf(['\ngetRawCTFBalanceCoefs : Sensor %s appears in ',... + 'ds.res4.scrr, but not in ds.res4.chanNames\n\n'],Refname); + return + end + Refindex=[Refindex pRef]; + end + end % end setup of balancing table for MEG sensors + if ds.res4.scrr(m).numcoefs~=nRef + fprintf('\ngetRawCTFBalanceCoefs : %s - %s has %d coefficients\n',... + ds.res4.chanNames(MEGindex(1),1:nChar),balanceType,nRef); + fprintf(' %s - %s " %d " ????\n\n',... + ds.res4.chanNames(MEGindex(n),1:nChar),balanceType,... + ds.res4.scrr(m).numcoefs); + betaMEG=[]; % An output that will force an error in the calling program. + return + end + betaMEG(:,n)=reshape(ds.res4.scrr(m).coefs(1:nRef),nRef,1); + m1=m+1; + break; + end + if (m==m1-1 & m1>1) | (m==mtot & m1==1) + if missingMEGMessage==0 + if strncmp(balanceType(2,:), balanceOptions(5,:), 4) + % Avoid warning for all sensors for adaptive coefficients. + fprintf('\ngetRawCTFBalanceCoefs: Failed to find %s balance coefficients for sensors.\n',... + balanceType(2,:)); + else + fprintf(['\ngetRawCTFBalanceCoefs: Failed to find %s balance coefficients',... + ' for sensor(s)'],balanceType(1,:)); + fprintf('\n\t\t\t\t'); + end + end + missingMEGMessage=missingMEGMessage+1; + if ~strncmp(balanceType(2,:), balanceOptions(5,:), 4) + if missingMEGMessage==10*round(missingMEGMessage/10) + fprintf('\n\t\t\t\t'); + end + fprintf(' %s',MEGname); + end + betaMEG(:,n)=zeros(nRef,1); + end + end % End of loop over m (ds.res4.scrr table) +end % End of loop over MEG sensors +if missingMEGMessage>0;fprintf('\n');end + +if common_mode_only + if size(betaMEG,1)>3 & nMEG>0 + betaMEG=betaMEG(1:3,:); + Refindex=Refindex(1:3); + end + if size(betaGref,1)>3 & nGref>0 + betaGref=betaGref(1:3,:); + Gbalanceindex=Gbalanceindex(1:3); + end +end + +return diff --git a/external/ctf/getCTFBalanceCoefs.p b/external/ctf/getCTFBalanceCoefs.p deleted file mode 100644 index 2eed28b..0000000 Binary files a/external/ctf/getCTFBalanceCoefs.p and /dev/null differ diff --git a/external/ctf/getCTFdata.m b/external/ctf/getCTFdata.m new file mode 100644 index 0000000..b01c8e7 --- /dev/null +++ b/external/ctf/getCTFdata.m @@ -0,0 +1,351 @@ +function data=getCTFdata(ds,dataList,chanList,unit,prec); + +% getCTFdata.m Reads specified trials from .meg4 files in CTF-format data set. + +% ************************************************************************ +% +% This program is provided to users of CTF MEG systems as a courtesy only. +% It's operation has not been verified for clinical use. +% Please do not redistribute it without permission from VSM MedTech Ltd. +% +% ************************************************************************ + +% Version: 1.1 13 April 2007 +% Author : Harold Wilson + +% Reads trials(s) from CTF data sets and converts to physical units. +% Modified to handle cases where the amount of data is so large (>2^31-8 bytes) +% that additional meg4 files ( .1_meg4,.2_meg4,...) are required. + +% getCTFdata does not apply the fact that Acq creates multiple .meg4 files that are the +% largest number of trials that fit into 2GB. Rather, getCTFdata simply checks all of the +% MEG4 files and makes a list of which trials are in which file. + +% Inputs : ds : Structure containing all of the res4 information on a file. +% getCTFdata uses dtructure ds to get the meg4 filename , trial-size +% information (ds.res4.no_samples, ds.res4.no_channels, ds.res4.no_trials) +% and the gain information contained in the sensor resource table +% ds.res4.senres. + +% dataList : Tells getCTFdata which data to read. Trial numbering starts at 1. +% (1) dataList<=0 or []. Read the complete data set. +% (2) size(dataList)=[1 N]. Read the N trials listed in row vector dataList. +% (3) size(dataList)=[3 1]. Read points dataList(1):dataList(2) +% from trial dataList(3). + +% unit : Determines the unit of the signals: +% 'ft' or 'fT' : Convert to fT (MEG), uV (EEG) and V (ADC) (default) +% 't' or 'T' : Convert to T (MEG), V (EEG) and V (ADC) +% 'phi0' : Convert to phi0 (MEG), uV (EEG) and V (ADC) +% 'int': Read plain integers from *.meg4-file + +% chanList: List of channels to read. Default : read all channels. +% Options : (1) chanList<=0 or []. Read all the channels +% (2) List of channel numbers. Channel numbers are +% referred to the data set, NOT just the SQUID channels. +% Fail if any(chanList>ds.res4.no_channels) +% (3) A list of channel names. chanList(n,:) is the name of +% the nth channel to be returned in array data. getCTFdata +% compares the characters preceding the first blank or '-' +% character to the rows of ds.res4.chanNames. +% Fail if any channel name dows not appear in ds.res4.chanNames. +% + +% prec : Precision of output. Default='double'. +% User may select 'single' to reduce memory demands. + +% Output : data : Array of data. Precision = double or single. +% size(data)=[nSample nChan nTrial] where +% nChan=ds.res4.no_channels or length(chanList) or size(chanList,1) +% If an error is detected, data is set to []; + +% Call to getCTFdata without arguments prints command format. +if nargout==0 & nargin==0 + fprintf(['\ngetCTFData: Version 1.1 13 April 2007 ',... + 'Reads a CTF dataset into array data.\n',... + '\tCall : data=getCTFdata(ds,dataList,chanList,unit,prec);\n'... + '\t\t - dataList: <=0, [] or missing. Read the complete data set.\n',... + '\t\t size(dataList)=[1 N]. Read the N trials listed.\n',... + '\t\t dataList=[pt1 pt2 Tr]''. Read points pt1:pt2',... + ' of trial Tr.\n']); + return +end + +% Allowed 8-byte headers for meg4 files. +allowedMeg4Headers=strvcat(['MEG41CP',char(0)],['MEG42CP',char(0)]); + +data=[]; % If an error causes in an early return. +delim=filesep; + +if exist('ds')~=1 + fprintf('\ngetCTFdata: No input arguments.\n\n'); + return +elseif isempty(ds) + fprintf('\ngetCTFdata: ds is empty.\n\n'); + return +elseif ~isstruct(ds) + fprintf('\ngetCTFdata: Input class(ds)=%s. Must be a structure.\n\n',class(ds)); + return +end + +% Create the list of trials and range of points to read. +% Set dataList=-1 to read all trials. +if exist('dataList')~=1; + dataList=-1; +elseif isempty(dataList) + dataList=-1; +elseif ~isnumeric(dataList) + fprintf('getCTFdata: Input dataList has class=%s. Must be numeric.\n',class(dataList)); + return +elseif ((any(dataList<=0) | any(dataList)>ds.res4.no_trials) & length(dataList)>1) |... + sum(size(dataList)>1)>1 + fprintf('\ngetCTFdata: Size(dataList)=[');fprintf(' %d',size(dataList));fprintf(']\n'); + fprintf('\t\tmin(dataList)=%d max(dataList)=%d nTrial=%d\n',... + min(reshape(dataList,1,prod(size(dataList)))),... + max(reshape(dataList,1,prod(size(dataList)))),ds.res4.no_trials); + fprintf(['\t\tdata_list must have size=[1 N] or [3 1]. ',... + 'No elements<=0 when dataList is not scalar.\n\n']); + return +elseif isequal(size(dataList),[1 1]) + if dataList<=0;dataList=-1;end +end + +if isequal(dataList,-1) + trials=1:ds.res4.no_trials; % read all trials + point=[1 ds.res4.no_samples]; % read all points from each trial +elseif size(dataList,1)==1 % dataList is a list of trials + if max(dataList)>ds.res4.no_trials | min(dataList)<=0 + fprintf(['\ngetCTFdata: min(dataList)=%d max(dataList)=%d. ',... + 'ds.res4.no_trials=%d ??\n\n'],min(dataList),max(dataList),ds.res4.no_trials); + return + end + trials=dataList; % read listed trials + point=[1 ds.res4.no_samples]; % read all points from each trial +elseif isequal(size(dataList),[3 1]) % dataList specifies points from a single trial + if dataList(1)<=0 | dataList(1)>dataList(2) | dataList(2)>ds.res4.no_samples | ... + dataList(3)<=0 | dataList(3)>ds.res4.no_trials + fprintf('getCTFdata: dataList error: points=%d:%d trial=%d\n',dataList); + fprintf(' points/trial=%d No. of trials=%d\n',... + ds.res4.no_samples,ds.res4.no_trials); + return + end + point=dataList(1:2)'; + trials=dataList(3); % read only one trial +else + fprintf('\ngetCTFdata: size(dataList)=[');fprintf(' %d',size(dataList)); + fprintf('] ??\n\n'); + return +end +clear dataList; + +% Check the specified signal unit. Convert unit to lower case. +if exist('unit')~=1 + unit='ft'; % default +elseif isempty(unit) + unit='ft'; % default +elseif ~ischar(unit); + fprintf('\ngetCTFdata: Input unit has class=%s. Must be char.\n\n',class(unit)); + return +else + unit=lower(unit); + if ~strcmp(unit,'int') & ~strcmp(unit,'ft') & ~strcmp(unit,'t') & ~strcmp(unit,'phi0') + fprintf(['\ngetCTFdata : unit=%s Not a valid option. Must be ',... + '''fT'', ''T'', ''phi0'' or ''int''\n\n'],unit); + return + end +end + +% Make a list of channels to read. +if exist('chanList')~=1;chanList=-1;end +if isempty(chanList);chanList=-1;end +if isnumeric(chanList) % Channels listed by number + chanList=reshape(chanList,1,prod(size(chanList))); + if isequal(size(chanList),[1 1]) & chanList<=0; % chanList<=0 + chanList=[1:ds.res4.no_channels]; + elseif max(chanList)>ds.res4.no_channels | min(chanList)<1 % error + fprintf(['\ngetCTFdata: chanList specifies channels %d,%d but data set ',... + 'has only %d channels.\n\n'],min(chanList),max(chanList),ds.res4.no_channels); + return + end +elseif ischar(chanList) % Channels listed by name + name_list=chanList; + nChan=size(name_list,1); + chanList=zeros(1,nChan); + for k=1:nChan + kx=strmatch(strtok(name_list(k,:),'- '),ds.res4.chanNames); + if isempty(kx) + fprintf(['\ngetCTFdata: Channel %s does not appear in the list of channel ',... + 'names (See ds.res4.chanNames)\n\n'],deblank(name_list(k,:))); + return + end + chanList(k)=kx; + end + clear name_list kx k; +else + fprintf('getCTFdata: Cannot interpret chanList.\n'); + return +end + +% Sort the channels into increasing number, and keep track of the original order. +% C_list = Sorted list of channels read into array data. The sorted list is used so +% the meg4 file is read in increaing channel number order. +% chan_index : C_list(p)=chanList(chan_index(p)). +% data(:,k,:) is from dataset channel chanList(k). + +[C_list chan_index]=sort(chanList); +nChan=length(chanList); + +% data array precision +if exist('prec')~=1; + prec='double'; +elseif isempty(prec) + prec='double'; +elseif ~ischar(prec) + fprintf('\ngetCTFdata: Input prec has class=%s\n\n',class(prec)); + return +elseif ~strcmp(prec,'single') & ~strcmp(prec,'double') + fprintf('\ngetCTFdata : prec=%s Must be ''single'' or ''double''.\n\n',prec); + return +end + +% Data are stored in the meg4 file as 4-byte words. +trial_size=ds.res4.no_samples*ds.res4.no_channels; +bytes_per_trial=4*trial_size; +bytes_per_channel=4*ds.res4.no_samples; + +nSavepts=point(2)-point(1)+1; +ntot=length(trials)*nChan*nSavepts; % Total points to read. + +% Make a list of which trials are in which .meg4 file. In almost all cases, only the .meg4 +% file is present. +qFile=-1; +while 1 + qFile=qFile+1; + if qFile==0 + meg4Ext='.meg4'; + meg4Trial=0; + else + meg4Ext=['.',int2str(qFile),'_meg4']; + end + D=dir([ds.path,ds.baseName,'.ds',delim,ds.baseName,meg4Ext]); + if isempty(D);break;end + % No of trials in this file. + nFileTrial=round((D.bytes-8)/bytes_per_trial); + if nFileTrial*bytes_per_trial~=D.bytes-8 + fprintf('\ngetCTFdata: File %s%s does not contain a whole number of trials.\n',... + ds.baseName,meg4Ext); + fprintf([' File size (bytes)=%0.9d header=8 bytes trial size ',... + '(bytes)=%d\n\n'],D.bytes,bytes_per_trial); + return + end + meg4Trial=[meg4Trial round((D.bytes-8)/bytes_per_trial)]; +end + +% meg4Trial(2)=last trial in file .meg4, meg4Trial(3)=last trial in file .1_meg4,... +meg4Trial=cumsum(meg4Trial); +nMEG4=length(meg4Trial)-1; + +% Open .meg4 with big-endian option for compatibility with the data-acquisition computer. +meg4Fid=fopen([ds.path,ds.baseName,'.ds',delim,ds.baseName,'.meg4'],'r','ieee-be'); +openFile=1; + +% Check that the header of the .meg4 file is OK. Don't bother to check the other +% meg4 files (.1_meg4,...) +meg4Header=char(fread(meg4Fid,8,'uint8')'); +if isempty(strmatch(meg4Header,allowedMeg4Headers,'exact')) + fclose(meg4Fid); + fprintf(['\ngetCTFdata: meg4 file header = %s. ',... + 'A valid meg4 file, must have one of'],meg4Header); + for k=1:size(allowedMeg4Headers,1) + fprintf(' %s',allowedMeg4Headers(k,:)); + end + fprintf('\n\n'); + return +end + +% Reserve memory for the data. +if prec=='single' % Funny coding to minimize the maximum memory required. + data=single([]); + while length(data)meg4Trial(openFile+1) + fclose(meg4Fid); + openFile=min(find(meg4Trial>=trials(kt)))-1; + if isempty(openFile) + fprintf(['\ngetCTFdata: Trying to read trial %d, but the last trial in ',... + 'the dataset is %d.\n',... + ' Dataset = %s\n\n'],trials(kt),max(meg4Trial),ds.baseName); + data=[]; + return + elseif openFile==1 + meg4Ext='.meg4'; + else + meg4Ext=['.',int2str(openFile-1),'_meg4']; + end + meg4Fid=fopen([ds.path,ds.baseName,'.ds',delim,ds.baseName,meg4Ext],'r','ieee-be'); + end + firstTrial=meg4Trial(openFile)+1; + for kch=1:nChan + % Move to the start of trial kt, channel C_list(kch), point(1) + fseek(meg4Fid,8+(trials(kt)-firstTrial)*bytes_per_trial+... + (C_list(kch)-1)*bytes_per_channel+(point(1)-1)*4,'bof'); + % Read and save nSavepts of data. + if prec=='double' + data(:,chan_index(kch),kt)=fread(meg4Fid,nSavepts,'int32'); + else + data(:,chan_index(kch),kt)=single(fread(meg4Fid,nSavepts,'int32')); + end + end +end +fclose(meg4Fid); +clear kt kch meg4Fid; +clear openFile meg4Ext firstTrial; + +if strcmp(unit,'int');return;end + +% Convert to specified signal unit. +for kx=1:nChan + sens=chanList(kx); + SQUIDtype=any(ds.res4.senres(sens).sensorTypeIndex==[0:7]); + EEGtype=any(ds.res4.senres(sens).sensorTypeIndex==[8 9]); + if SQUIDtype & strcmp(unit,'phi0') + invgain=ds.res4.senres(sens).ioGain*ds.res4.senres(sens).qGain; + else + invgain=ds.res4.senres(sens).ioGain*... + ds.res4.senres(sens).properGain*ds.res4.senres(sens).qGain; + end + if strcmp(unit,'ft') & SQUIDtype + pGain=1e15; % Convert SQUIDs to fT + elseif (strcmp(unit,'phi0') | strcmp(unit,'ft')) & EEGtype + pGain=1e6; % Convert from EEG to uV + else + pGain=1; + end + % Trap case with invgain==0 which may be used to mark bad channels. + if invgain~=0 + gainx=pGain/invgain; + else + gainx=0; + end + if abs(gainx-1)>1e-7 + for kt=1:length(trials) + if prec=='single' + data(:,kx,kt)=single(gainx*double(data(:,kx,kt))); + else + data(:,kx,kt)=gainx*data(:,kx,kt); + end + end + end +end +clear kx kt sens SQUIDtype EEGtype pGain invGain gainx; + +return diff --git a/external/ctf/getCTFdata.p b/external/ctf/getCTFdata.p deleted file mode 100644 index 8186a74..0000000 Binary files a/external/ctf/getCTFdata.p and /dev/null differ diff --git a/external/ctf/readCPersist.m b/external/ctf/readCPersist.m new file mode 100644 index 0000000..2e62d3d --- /dev/null +++ b/external/ctf/readCPersist.m @@ -0,0 +1,259 @@ +function Tag=readCPersist(CPfile,printtags) + +% Version 1.2 24 April 2007 Modified to close the CPersist file if a really huge +% taglength is encountered. Recently discovered .acq files with the string 'ssss' added +% at the end of the file after the final 'EndofParameters' string. + +% Reads a CTF CPersist file. See document CTF MEG File Format, PN900-0066 +% printtags=1 : Print a list of tags and values. If not supplied, default=0; +% Recognizes data types 1,...,17. If other types appear in the file, an error +% message is printed. + +% Input : CPfile: Name of a CPersist file including the full path. +% printtags: 0 : Do not print the tags as they are read. +% 1 : Do print the tags. + +% Output : Tag : Structure array containing all of the tags, types, and data. +% +% Adds 2 tag types: 0 marks start string('WS1_') +% -1 marks 'EndofParameters' + +EOPcountMessage=0; +% A reading error could give a huge tagLength which would result in an +% out-of-memory error when executing command tagName=fread(fid,tagLength,'uint8'); +% Limit acceptable values of tagLength so this will not happen. +maxNameLength=2000; % Do not accept tags with names exceeding maxNameLength characters. + +if nargin==0 + fprintf(['readCPersist: Version 1.2 24 April 2007 Reads a CTF CPersist file.\n\n'... + '\tTag=readCPersist(filename) or Tag=readCPersist(filename,0) reads\n',... + '\ta CPersist file and stores the contents in structure array Tag.\n\n',... + '\tTag=readCPersist(filename,1) reads a CPersist file and prints ',... + 'the contents.\n\n',... + '\tTag types are defined in document CTF MEG File Formats, PN900-0088,',... + ' Appendix B.\n',... + '\treadCPersist also creates type=0 tags to mark the beginning and type=-1\n',... + '\ttags to mark the end of CPersist objects within the file.\n\n']); + if nargout>1;Tag=[];end + return +end + +startString='WS1_'; +EOPstring='EndOfParameters'; + +startVal=256.^[3:-1:0]*double(startString)'; + +D=dir(CPfile); +if isempty(D) + fprintf('readCPersist: Could not find file %s.\n',CPfile); + Tag=struct([]); + return +elseif D.bytes==0 + fprintf('readCPersist: File %s contains 0 bytes.\n',CPfile); + Tag=struct([]); + return +end + +totalBytes=D.bytes; +clear D; + +if ~exist('printtags');printtags=[];end +if ~isnumeric(printtags) | ~isequal(size(printtags),[1 1]);printtags=0;end + +fid=fopen(CPfile,'r','ieee-be'); + +% Step through tags and info. +tagCount=0; +bytePtr=0; % No. of bytes read so far. +% Compare bytePtr to totalBytes to decide if an impossible read request is being made. +% This is necessary because some .acq files have junk string 'ssss' appended after the +% final EOPstring. +EOPcount=0; % Counts end-of-object markers. +% EOPcount is incremented at the start of an object (when startString is read). +% EOP is decremented at the end of an object (EOPstring is read). + +while 1 + tagCount=tagCount+1; + % tagLength = number of characters in the tagName. + tagLength=fread(fid,1,'int32'); + bytePtr=bytePtr+4; + if isempty(tagLength) | bytePtr>=(totalBytes-8) + break; + elseif tagCount==1 & tagLength~=startVal % Is this a CPersist file? + fprintf(['readCPersist: File %s does not start with %s',... + ' (required for a CPersist file).\n'],CPfile,startString); + fclose(fid); + Tag=[]; + return + elseif tagLength==startVal % Start of embedded CPersist object + tagName=startString; + buff=[]; + type=0; + EOPcount=EOPcount+1; + if printtags; + fprintf('%4d: %s EOPcount=%d bytePtr=%5d',tagCount,tagName,EOPcount,bytePtr); + end + elseif tagLength<=0 | tagLength>maxNameLength | (bytePtr+tagLength)>totalBytes + % Should never come here, but some versions of Acq add junk bytes after the final + % EOPstring, and they may be interpreted as the number of bytes in the next tag. + if tagLength<0 + fprintf('readCPersist: tagCount=%d bytePtr=%d tagLength=%d??\n',tagCount,bytePtr,tagLength); + end + break; + else + % Read the tagName + tagName=char(fread(fid,tagLength,'uint8'))'; + bytePtr=bytePtr+tagLength; + if length(tagName)~=tagLength + fprintf(['readCPersist: tagCount=%d tagLength=%d tagName=%s',... + ' (length~=tagLength)\n'],tagCount,tagLength,tagName); + break; + elseif strcmp(EOPstring,tagName) % end of CPersist object + EOPcount=EOPcount-1; + if EOPcountMessage==0 & EOPcount<0 & printtags==0 + % Error in the file structure, but keep reading because it may help user to see + % partial results from reading a bad file. + fprintf('%s\n',' ',['readCPersist: More end-of-object marks (',EOPstring,... + ') than start-of-object marks (',startString,') have been read so far.'],... + [' File ',CPfile,' has a format error.'],' '); + EOPcountMessage=1; + end + buff=[]; + type=-1; + if printtags~=0; + fprintf('%4d: %s EOPcount=%d',tagCount,tagName,EOPcount); + end + else + type=fread(fid,1,'int32'); + bytePtr=bytePtr+4; + if isempty(type) + fprintf('readCPersist: tagCount=%d tagName=%s type=[]??\n',tagCount,tagName); + break; + end + if printtags;fprintf('%4d: %s type=%d',tagCount,tagName,type);end + if type==1 % custom type Assume zero length except for DatasetFiles + if strcmp(tagName,'DatasetFiles'); + buff=fread(fid,1,'int32'); + bytePtr=bytePtr+4; + else + buff=[]; + end + elseif type==2 % nested CPersist object + buff=[]; + elseif type==3 % binary list + bufflength=fread(fid,1,'int32'); % buffer in bytes. + bytePtr=bytePtr+4; + if bufflength~=2*round(bufflength/2) + fprintf(['readCPersist: ERROR : tagName=%s bufflength=%d',... + ' MUST BE EVEN.\n'],round(bufflength)); + break; + end + buff=int16(fread(fid,round(bufflength/2),'int16')'); + bytePtr=bytePtr+bufflength; + if printtags;fprintf(' %d entries',round(bufflength/2));end + elseif type==4 % double + buff=fread(fid,1,'float64'); + bytePtr=bytePtr+8; + if printtags;fprintf(' %f',buff);end + elseif type==5 % integer + buff=fread(fid,1,'int32'); + bytePtr=bytePtr+4; + if printtags;fprintf(' %d',buff);end + elseif type==6 % short integer + buff=fread(fid,1,'int16'); + bytePtr=bytePtr+2; + if printtags;fprintf(' %d',buff);end + elseif type==7 % unsigned short integer + buff=fread(fid,1,'uint16'); + bytePtr=bytePtr+2; + if printtags;fprintf(' %d',buff);end + elseif type==8 % Boolean byte + buff=char(fread(fid,1,'uint8')'); + bytePtr=bytePtr+1; + if printtags;fprintf(' %d',buff);end + elseif type==9 % CStr32 32-character string + fprintf('\ttype=9 bytePtr=%d tagLength=%d\n',bytePtr,tagLength); + buff=char(fread(fid,32,'uint8')'); + bytePtr=bytePtr+32; + if printtags;fprintf(' %s',buff);end + elseif type==10; % CString + %fprintf('\ttype=10 bytePtr=%d tagLength=%d\n',bytePtr,tagLength); + stringlength=fread(fid,1,'int32'); + bytePtr=bytePtr+4; + buff=char(fread(fid,stringlength,'uint8')'); + bytePtr=bytePtr+stringlength; + if printtags; + fprintf(' %d chars',stringlength); + if stringlength<80;fprintf(' %s',buff);end + end + elseif type==11; % Cstring list. + nList=fread(fid,1,'int32'); + %fprintf('\ttype=11 bytePtr=%d tagLength=%d nList=%d\n',bytePtr,tagLength,nList); + bytePtr=bytePtr+4; + buff=[]; + for k=1:nList + nLen=fread(fid,1,'int32'); + buff=strvcat(buff,char(fread(fid,nLen,'uint8')')); + bytePtr=bytePtr+4+nLen; + end + if printtags;fprintf(' List of %d strings.',nList);end + elseif type==12; % CStr32 list. + nList=fread(fid,1,'int32'); + fprintf('\ttype=12 bytePtr=%d tagLength=%d nList=%d\n',bytePtr,tagLength,nList); + buff=reshape(char(fread(fid,32*nList,'uint8')),32,nList)'; %size(buff)=[nList 32] + bytePtr=bytePtr+4+32*nList; + if printtags;fprintf(' List of %d strings.',nList);end + elseif type==13; % SensorClass list. + nList=fread(fid,1,'int32'); + buff=fread(fid,nList,'int32'); + bytePtr=bytePtr+4+4*nList; + if printtags; + fprintf(' %d-element list.',nList); + if nList<10; + fprintf(' %d',buff); + end + fprintf('\n'); + end + elseif type==14 % long integer + buff=fread(fid,1,'int32'); + bytePtr=bytePtr+4; + if printtags;fprintf(' %d',buff);end + elseif type==15 % unsigned longinteger + buff=fread(fid,1,'uint32'); + bytePtr=bytePtr+4; + if printtags;fprintf(' %d',buff);end + elseif type==16 % unsigned integer + buff=fread(fid,1,'uint32'); + bytePtr=bytePtr+4; + if printtags;fprintf(' %d',buff);end + elseif type==17 % Boolean + buff=fread(fid,1,'int32'); + bytePtr=bytePtr+4; + if buff~=0 & buff~=1 + fprintf('readCPersist: tagName=%s type=%d value=%d? (Must =0 or 1)\n',... + tagName,type,buff); + buff=(buff~=0); + fprintf(' Set value=%d.\n',buff); + end + else + % Should never come here. + fprintf('readCPersist: tagName=%s type=%d',tagName,type); + fprintf('\t\t UNRECOGNIZED type.\n'); + break; + end + end + end + % Assemble the next element in the structure array. + Tag(tagCount)=struct('name',tagName,'type',type,'data',buff); + clear tagName type buff; + if printtags;fprintf('\n');end +end +fclose(fid); + +% EOPcount should be zero at the end of the file +if EOPcount~=0; + fprintf(['readCPersist: Stop strings (',EOPstring,') do not balance start strings (',... + startString,').\n (No. of start strings)-(No. of stop strings)=',... + int2str(EOPcount),'.\n']); +end +return \ No newline at end of file diff --git a/external/ctf/readCPersist.p b/external/ctf/readCPersist.p deleted file mode 100644 index 6da60aa..0000000 Binary files a/external/ctf/readCPersist.p and /dev/null differ diff --git a/external/ctf/readCTFMRI.m b/external/ctf/readCTFMRI.m new file mode 100644 index 0000000..8367f5b --- /dev/null +++ b/external/ctf/readCTFMRI.m @@ -0,0 +1,106 @@ +function [MRItag,MRIdata]=readCTFMRI(fileName); + +% Version 1.2: 25 April 2007 Module readCPersist changed and removed from this listing. +% Version 1.1: 19 April 2007 No changes since v1.0 + +% Reads a CTFMRI v4 file. +% For file format and a defineition fo CPersist objects, see document +% "CTF MEG FIle Formats", PN900-0088 + +% Input: fileName : Name of MRI file including path and extension. + +% Outputs: MRItags : CPersist tags describing the MRI. +% The start and stop tags have been removed. +% name='WS1_', type=0, data=[] +% name='EndOfParmaters', type -1, data=[] + +% MRIdata: 256x256x256: int16 array. +% MRIdata(j,k,n) = pixel(j,k) of slice n. +% j = coronal slice. j=1:anterior, j=256:posterior +% k = axial slice. k=1:superior, k=256:inferior +% n = sagittal slice. n=1:left, n=256:right + +% Calls function readCPersist (not included in this listing). + +persistent printWarning + + +if nargin==0 & nargout==0 + fprintf(['readCTFMRI: Version 1.2 25 April 2007 Reads MRIs in CTFMRI v4 format.\n',... + '\t[MRItag,MRIdata]=readCTFMRI(MRIfilename);\n',... + '\t\tMRIfilename = complete name including path and extension .mri\n',... + '\t\tMRItag= list of File descriptors. See document "CTF MEG FIle Formats", PN900-0088\n',... + '\t\tMRIdata = MRI data array. Precision=int16 (2 bytes per pixel)\n\n']); + return +end + +MRItag=struct([]); % Force failure in calling routines +MRIdata=int16([]); + +if nargin~=1 | nargout~=2 + fprintf(['readCTFMRI: Found %d input arguments and %d outputs. ',... + 'Must have 1 inputs (fileName) and 2 outputs [MRItags,MRIdata].\n'],nargin,nargout); + return +elseif ~ischar(fileName) | isempty(fileName) + fprintf('readCTFMRI : Filename is not character or is empty.\n'); + whos fileName; + return +elseif exist(fileName)~=2 + fprintf('readCTFMRI: Cannot find file %s.\n',fileName); + return +end + +MRItag=readCPersist(fileName); +if isempty(MRItag) + fprintf('readCTFMRI: File %s\n\t\t\t cannot be read by readCPersist.\n',fileName); + fprintf('\t\t\tIs it in CPersist format?\n\n'); + MRItag=struct([]); + MRIdata=int16([]); + return +end + +% DO some checks to verify that this really is a CTF MRI. +name=char([]); +for k=1:length(MRItag); + name=strvcat(name,MRItag(k).name); +end +isCTFMRI=(~isempty(strmatch('_CTFMRI_',name))); +if isCTFMRI + sizeTag=strmatch('_CTFMRI_SIZE',name,'exact'); + if length(sizeTag)~=1 + isCTFMRI=0; + else + MRIsize=MRItag(sizeTag).data; + nSlice=MRIsize; + end + clear sizeTag; +end +if isCTFMRI + sliceTag=strmatch('_CTFMRI_SLICE_DATA#',name)'; + isCTFMRI=(length(sliceTag)==nSlice); +end +if ~isCTFMRI + fprintf(['readCTFMRI: File %s is a CPersist file\n',... + '\t\t\tbut it is not in CTFMRI format.\n'],fileName); + MRIdata=int16([]); + return +end +clear isCTFMRI; + +if isempty(printWarning) + fprintf(['\nreadCTFMRI: You are reading a CTF-format MRI for use with a software-application\n',... + '\ttool that is not manufactured by VSM MedTech Ltd. and has not received marketing\n',... + '\tclearance for clinical applications. If the MRI is processed by this tool,\n',... + '\tit should not be later employed for clinical and/or diagnostic purposes.\n']); + printWarning=1; +end + +MRIdata=int16(zeros(MRIsize,MRIsize,1)); +for k=1:nSlice + MRIdata(:,:,k)=reshape(int16(MRItag(sliceTag(k)).data),MRIsize,MRIsize); +end +% Keep only the useful tag information. +MRItag=MRItag(2:(sliceTag(1)-1)); +return +%%%%%%%%%%%%%% end of readCTFMRI %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \ No newline at end of file diff --git a/external/ctf/readCTFMRI.p b/external/ctf/readCTFMRI.p deleted file mode 100644 index 48d5276..0000000 Binary files a/external/ctf/readCTFMRI.p and /dev/null differ diff --git a/external/ctf/readCTFds.m b/external/ctf/readCTFds.m new file mode 100644 index 0000000..4424943 --- /dev/null +++ b/external/ctf/readCTFds.m @@ -0,0 +1,1003 @@ +function ds=readCTFds(datasetname) + +% ************************************************************************ +% +% This program is provided to users of CTF MEG systems as a courtesy only. +% It's operation has not been verified for clinical use. +% Please do not redistribute it without permission from CTF Systems Inc. +% +% ************************************************************************ + +% readCTFds opens a CTF data set and creates a MATLAB structure with the information +% in the .res4, .infods, .newds, .acq, .hc, .hist, .EEG, bad.segments, BadChannels, +% ClassFile.cls andMarkerFile.mrk files. It confirms the existence of a .meg4 file +% with the correct size. + +% See document CTF MEG File Formats, PN900-0088 for a description of the formats of +% dataset files. + +% Author : Harold Wilson + +% ***************** Revisions and bug fixes ************************************** +% Version 1.3 4 October 2007 +% 1. readCTFds v1.2 failed when run in MATLAB 7.2, but ran correctly in +% MATLAB 6.5 and 7.3. The failure occurred when calls to fscanf with a +% final '\n' in the format string were followed by fgetl. In MATLAB 6.5 and 7.3, +% this returns the next line of a text file, but in MATLAB 7.2, this +% returns an empty charatcer string. +% Changes were made to subprograms +% - readHc, +% - readClassFile +% - readMarkerFile. +% 2. In v1.1 and 1.2, if any of the head coil positions exceeded 100 cm, readHc +% reported an error and returned hc=struct([]). In v1.3, is reports the error, +% and returns the erroneaous values. + + +% Version 1.2: 24 April 2007 +% - readHc modified to read fMEG .hc files. +% - readCPersist modified to handle extra bytes that appear in some .acq files. + +% Version 1.1: 13 April 2007 +% readCTFds is modified to handle cases where the data files exceed a total of 2^31-8 +% bytes. In these cases files .1_meg4,.2_meg4,... appear in the dataset. +% *********************************************************************************** + +% Inputs : datasetname : Complete name of the data set directory. Includes the complete +% path and the .ds extension. + +% Output: ds : A structure that gives data set parameters. + +% Function calls included in this listing: +% - readRes4 +% - readHc +% - readEEG +% - readMarkerFile +% - readClassFile +% - readBadSegments +% - readVirtualChannels +% External functions: - readCPersist Reads infods and acq files. + +% - The data directory is datasetname. +% - path is the complete path to the directory including the last file delimiter. +% - baseName is the directory name, less the last file extension. +% - datasetname=[path,baseName,'.ds']; + +persistent printWarning multipleMeg4Files + +if nargin==0 & nargout==0 % Print a version number + fprintf(['\treadCTFds: Version 1.3 4 October 2007 ',... + 'Reads v4.1 and v4.2 CTF data sets including fMEG .hc files.\n',... + '\tCall: ds=readCTFds(datasetname)\n',... + '\t\tdatasetname = Name of the dataset including the path.\n',... + '\t\tds = Structure containing all dataset information except for data in ',... + 'the .meg4 file.\n\n']); + return +end + +MAX_COILS=8; +MAX_BALANCING=50; % max. no. of balancing coefficients +SENSOR_LABEL=31; % No. of characters in sensor labels in the balancing +% coefficient tables +len_sensor_name=32; + +% length of sensor coefficient records in bytes. See listing for MEGDefs.h +%senres_lenrec=len_sensor_name+8+2+MAX_BALANCING*SENSOR_LABEL+8*MAX_BALANCING; + +% Allowed 8-byte headers for res4 and meg4 files. +res4Headers=strvcat(['MEG41RS',char(0)],['MEG42RS',char(0)]); +meg4Headers=strvcat(['MEG41CP',char(0)],['MEG42CP',char(0)]); + +delim=filesep; +ds=struct([]); + +% Check that the data set exists. +if exist('datasetname')~=1 + fprintf('\nreadCTFds: No input datasetname specified.\n\n'); + return +elseif ~ischar(datasetname) | isempty(datasetname) | size(datasetname,1)~=1 + fprintf('\nreadCTFds: Dataset name is not a string, or is empty, or is an array.\n\n'); + whos datasetname + return +else + % Separate datasetname into a path and the baseName and add extension .ds. + datasetname=deblank(datasetname); + ksep=max([0 findstr(datasetname,delim)]); + baseName=datasetname((ksep+1):length(datasetname)); + path=datasetname(1:ksep); % String path is terminated by the file delimiter (or path=[]). + % Remove the last .ds from baseName. + kdot=max(findstr(baseName,'.ds')); + if kdot==(length(baseName)-2) + baseName=baseName(1:(max(kdot)-1)); + else + datasetname=[datasetname,'.ds']; + end + clear ksep kdot; + if exist(datasetname)~=7 + fprintf('\nreadCTFds: Cannot find dataset %s.\n\n',datasetname); + return + end +end + +% Check that the res4 and meg4 files exist. +res4File=[datasetname,delim,baseName,'.res4']; +meg4File=[datasetname,delim,baseName,'.meg4']; + +if exist(res4File)~=2 | exist(meg4File)~=2 + fprintf('readCTFds: In directory %s, cannot find .res4 and/or .meg4 files.\n',... + datasetname); + return +end + +% Check the headers on .meg4, .1_meg4, ... +qFile=0; +meg4Ext='.meg4'; +meg4Size=[]; +while 1 + if qFile>0; + meg4Ext=['.',int2str(qFile),'_meg4']; + meg4File=[datasetname,delim,baseName,meg4Ext]; + end + if qFile>1 & isempty(multipleMeg4Files) + fprintf('readCTFds: This dataset has multiple meg4 files.\n'); + multipleMeg4Files=1; + end + fid=fopen(meg4File,'r','ieee-be'); + if fid<=0;break;end + D=dir([datasetname,delim,baseName,meg4Ext]); + meg4Size=[meg4Size D.bytes]; + meg4Header=char(fread(fid,8,'uint8')'); + fclose(fid); + if isempty(strmatch(meg4Header,meg4Headers,'exact')) + fprintf('\nreadCTFds: %s file header=%s Valid header options:',meg4Ext,meg4Header); + for k=1:size(meg4Headers,1);fprintf(' %s',meg4Headers(k,:));end + fprintf('\n\n'); + ds=struct([]); + return + end + qFile=qFile+1; +end +Nmeg4=length(meg4Size); +clear D fid qFile; +% Add baseName and path to structure ds. +ds=struct('baseName',baseName,'path',path); + +% Read the res4 file +ds.res4=readRes4(res4File,res4Headers,... + MAX_COILS,MAX_BALANCING,SENSOR_LABEL,len_sensor_name); +if isempty(ds.res4);ds=struct([]);return;end + +dataBytes=4*ds.res4.no_trials*ds.res4.no_channels*ds.res4.no_samples; + +% Assemble ds.meg4. +ds.meg4.fileSize=sum(meg4Size); +ds.meg4.header=meg4Header; +clear meg4Header meg4Size; + +% Does the size of the .meg4 file match the size specified by the .res4 file? +if ds.meg4.fileSize~=8*Nmeg4+dataBytes + fprintf(['\nreadCTFds: Data set error : size of meg4 file(s)\n\t\t',... + '%10d bytes (from dir command)\n'],ds.meg4.fileSize); + fprintf('\t\t%10d bytes (from res4 file)\n\n',8*Nmeg4+dataBytes); + return +end + +if isempty(printWarning) + fprintf(['\nreadCTFds: You are reading CTF data for use with a software-application tool\n',... + '\tthat is not manufactured by VSM MedTech Ltd. and has not received marketing\n',... + '\tclearance for clinical applications. If CTF MEG data are processed by this tool,\n',... + '\tthey should not be later employed for clinical and/or diagnostic purposes.\n\n']); + printWarning=1; +end + +% .infods file +if exist([datasetname,delim,baseName,'.infods'])==2 + ds.infods=readCPersist([datasetname,delim,baseName,'.infods']); +end + +% .newds file +if exist([datasetname,delim,baseName,'.newds'])==2 + fid=fopen([datasetname,delim,baseName,'.newds'],'r','ieee-be'); + ds.newds=char(fread(fid,'uint8'))'; + fclose(fid); + clear fid; +end + +% .acq file +if exist([datasetname,delim,baseName,'.acq'])==2 + ds.acq=readCPersist([datasetname,delim,baseName,'.acq']); +end + +% .hist file +if exist([datasetname,delim,baseName,'.hist'])==2 + fid=fopen([datasetname,delim,baseName,'.hist'],'r','ieee-be'); + ds.hist=char(fread(fid,'uint8'))'; + fclose(fid); +end + +% .hc file +if exist([datasetname,delim,baseName,'.hc'])==2 + ds.hc=readHc([datasetname,delim,baseName,'.hc']); +end + +% .eeg file +if exist([datasetname,delim,baseName,'.eeg'])==2 + ds.eeg=readEEG([datasetname,delim,baseName,'.eeg']); + if isempty(ds.eeg);ds=rmfield(ds,'eeg');end +end + +% marker file +if exist([datasetname,delim,'MarkerFile.mrk'])==2 + ds.mrk=readMarkerFile([datasetname,delim,'MarkerFile.mrk']); +end + +% ClassFile +if exist([datasetname,delim,'ClassFile.cls'])==2 + ds.TrialClass=readClassFile([datasetname,delim,'ClassFile.cls']); +end + +% bad.segments +if exist([datasetname,delim,'bad.segments'])==2 + ds.badSegments=readBadSegments([datasetname,delim,'bad.segments']); +end + +% BadChannels +if exist([datasetname,delim,'BadChannels'])==2 + fid=fopen([datasetname,delim,'BadChannels'],'r','ieee-be'); + ds.BadChannels=char([]); + while 1 + strng=fscanf(fid,'%s\n',1); + if isempty(strng);break;end + ds.BadChannels=strvcat(ds.BadChannels,strng); + end + fclose(fid); + clear fid; +end + +% VirtualChannels Assume this is the name of the file. Modify to accept *.vc? +if exist([datasetname,delim,'VirtualChannels'])==2 + ds.Virtual=readVirtualChannels([datasetname,delim,'VirtualChannels']); +end + +% processing.cfg +if exist([datasetname,delim,'processing.cfg'])==2 + fid=fopen([datasetname,delim,'processing.cfg']); + ds.processing=char(fread(fid,'uint8'))'; + fclose(fid); + clear fid; +end + +return +%%%%%%%%%%%%%%%%% End of readCTFds %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%% Function readRes4 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function res4=readRes4(res4File,res4Headers,... + MAX_COILS,MAX_BALANCING,SENSOR_LABEL,len_sensor_name); + +% Open the res4 file +fid=fopen(res4File,'r','ieee-be'); + +% Check header. +res4.header=char(fread(fid,8,'uint8')'); +if isempty(strmatch(res4.header,res4Headers,'exact')) + fprintf(['\nreadCTFds (readRes4):res4 file header = %s. ',... + 'Valid header options:'],res4.header); + for k=1:size(res4Headers,1);fprintf(' %s',res4Headers(k,:));end;fprintf('\n\n'); + res4=struct([]); + fclose(fid); + return +end + +% Remove trailing blanks, but include a final null (char(0)). +res4.appName=[deblank(char(fread(fid,256,'uint8')')) char(0)]; +res4.dataOrigin=[deblank(char(fread(fid,256,'uint8')')) char(0)]; +res4.dataDescription=[deblank(char(fread(fid,256,'uint8')')) char(0)]; +res4.no_trials_avgd=fread(fid,1,'int16'); +res4.data_time=[deblank(char(fread(fid,255,'uint8')')) char(0)]; +res4.data_date=[deblank(char(fread(fid,255,'uint8')')) char(0)]; + +% new_general_setup_rec_ext part of meg41GeneralResRec +res4.no_samples=fread(fid,1,'int32'); +temp=fread(fid,2,'int16'); +res4.no_channels=temp(1); +res4.sample_rate=fread(fid,1,'float64'); +res4.epoch_time=fread(fid,1,'float64'); +temp=fread(fid,2,'int16'); +res4.no_trials=temp(1); +res4.preTrigPts=fread(fid,1,'int32'); +res4.no_trials_done=fread(fid,1,'int16'); +res4.no_trials_display=fread(fid,1,'int16'); +res4.save_trials=fread(fid,1,'int32'); + +% meg41TriggerData part of new_general_setup_rec_ext 10 bytes total +res4.primaryTrigger=fread(fid,1,'int32'); +res4.triggerPolarityMask=fread(fid,1,'int32'); +temp=fread(fid,1,'int16'); %Skip 2 bytes of padding +% end of meg41TriggerData part of new_general_setup_rec_ext + +temp=fread(fid,3,'int16'); %Skip 2 bytes of padding +res4.trigger_mode=temp(2); +res4.accept_reject_Flag=fread(fid,1,'int32'); + +temp=fread(fid,2,'int16'); %Skip 2 bytes of padding +res4.run_time_display=temp(1); +res4.zero_Head_Flag=fread(fid,1,'int32'); +res4.artifact_mode=fread(fid,1,'int32'); +% end of new_general_setup_rec_ext part of meg41GeneralResRec + +% meg4FileSetup part of meg41GeneralResRec +% Remove trailing blanks, but include a final null (char(0)) +res4.nf_run_name=[deblank(char(fread(fid,32,'uint8')')) char(0)]; +res4.nf_run_title=[deblank(char(fread(fid,256,'uint8')')) char(0)]; +res4.nf_instruments=[deblank(char(fread(fid,32,'uint8')')) char(0)]; +res4.nf_collect_descriptor=[deblank(char(fread(fid,32,'uint8')')) char(0)]; +res4.nf_subject_id=[deblank(char(fread(fid,32,'uint8')')) char(0)]; +res4.nf_operator=[deblank(char(fread(fid,32,'uint8')')) char(0)]; +res4.nf_sensorFileName=[deblank(char(fread(fid,56,'uint8')')) char(0)]; +temp=fread(fid,3,'int32'); +res4.rdlen=temp(2); + +res4.run_description=[deblank(char(fread(fid,res4.rdlen,'uint8')')) char(0)]; +% end of meg4FileSetup part of meg41GeneralResRec + +% Filter descriptions. Set field res4.filters=[] if no filters are +% defined. +res4.num_filters=fread(fid,1,'int16'); +if res4.num_filters==0 + res4.filters=[]; +else + for kfilt=1:res4.num_filters + res4.filters(kfilt).freq=fread(fid,1,'float64'); + res4.filters(kfilt).fClass=fread(fid,1,'int32'); + res4.filters(kfilt).fType=fread(fid,1,'int32'); + res4.filters(kfilt).numParam=fread(fid,1,'int16'); + for kparm=1:res4.filters(kfilt).numParam + res4.filters(kfilt).Param(kparm)=fread(fid,1,'float64'); + end + end + clear kfilt kparm; +end +% Read channel names. Must have size(res4.chanNames)=[channels 32] +% Clean up the channel names. The MEG system software leaves junk +% bytes in the channel name following the first zero. + +res4.chanNames=char(zeros(res4.no_channels,32)); +for kchan=1:res4.no_channels + xname=strtok(char(fread(fid,32,'uint8')'),char(0)); + res4.chanNames(kchan,1:length(xname))=xname; +end +clear kchan xname; + +% Read sensor resource table. Floating point values are 'double' +% but the code could be changed to convert to 'single' to save memory. +for kchan=1:res4.no_channels + res4.senres(kchan).sensorTypeIndex=fread(fid,1,'int16'); + res4.senres(kchan).originalRunNum=fread(fid,1,'int16'); + res4.senres(kchan).coilShape=fread(fid,1,'int32'); + res4.senres(kchan).properGain=fread(fid,1,'double'); + res4.senres(kchan).qGain=fread(fid,1,'double'); + res4.senres(kchan).ioGain=fread(fid,1,'double'); + res4.senres(kchan).ioOffset=fread(fid,1,'double'); + res4.senres(kchan).numCoils=fread(fid,1,'int16'); + numCoils=res4.senres(kchan).numCoils; + temp=fread(fid,3,'int16'); + res4.senres(kchan).grad_order_no=temp(1); + + % Special code to take care of situations where someone wants to label bad channels + % by setting their gain to zero. + invgain=(res4.senres(kchan).ioGain*... + res4.senres(kchan).properGain*res4.senres(kchan).qGain); + if abs(invgain)>1e-50 + res4.senres(kchan).gain=1/invgain; + else + res4.senres(kchan).gain=sign(invgain)*1e50; + end + if res4.senres(kchan).sensorTypeIndex>=0 & res4.senres(kchan).sensorTypeIndex<=7 + % Nominal gain (fT/integer step) + res4.senres(kchan).gain=1e15*res4.senres(kchan).gain; + end + + % Data that was included in res4.senres(kchan).coilTbl in earlier versions of readCTFds + + res4.senres(kchan).pos0=zeros(3,res4.senres(kchan).numCoils); + res4.senres(kchan).ori0=zeros(3,res4.senres(kchan).numCoils); + res4.senres(kchan).area=zeros(1,res4.senres(kchan).numCoils); + res4.senres(kchan).numturns=zeros(1,res4.senres(kchan).numCoils); + for qx=1:numCoils + buff=fread(fid,8,'double'); + res4.senres(kchan).pos0(:,qx)=buff(1:3); + res4.senres(kchan).ori0(:,qx)=buff(5:7); + temp=fread(fid,4,'int16'); + res4.senres(kchan).numturns(qx)=temp(1); + res4.senres(kchan).area(qx)=fread(fid,1,'double'); + end + if numCoils maxRCoil cm. +printWarning=1; +hc=struct([]); % Return in event of an error. + +if exist(hcFile)~=2 + return +end + +prec=1e-6; % Round positions. +% Decide if this is a MEG or an fMEG system. Find the first line that contains the +% string 'coil position relative to'. +% MEG system: This line contains 'nasion'. +% fMEG system: This line does not contains 'nasion'. + +fhc=fopen(hcFile,'rt','ieee-be'); + +% Decide system type and generate arrays for strings A and C. +% Search for first line. Allow for the posibility that extra text lines migt be added at +% the start of the file. +strngA=char([]); + +while 1 + textline=fgetl(fhc); + if isequal(textline,-1) + break + elseif strfind(textline,'coil position relative to'); + stringA=strtok(textline); + % Fix typographic error in some releases of Acq, not in all coils. + if strcmp(stringA,'stadard') + stringA = 'standard'; + end + if ~strcmp(stringA,'standard') + break + end + stringA=strvcat(stringA,'measured','measured'); + break; + end +end + +if isequal(textline,-1) | size(stringA,1)<3 + fprintf('readHc: File %s does not have the head position file format.\n',hcFile); + fclose(fhc); + return +end + +% Set stringC(3,:)='head' or 'abdomen' later. +stringC=strvcat('dewar','dewar'); + +% textline is the first useful line of the head coil file. + +coilLabel=char([]); % Names given to the coils +rhc=zeros(3,0); % Coil positions (cm) +coil=0; +nCoil=0; +lastPositionSet=1; + +while ~isequal(textline,-1) + % Parse the line + [A,R]=strtok(textline); + % Fix typographic error in some releases of Acq, not in all coils. + if strcmp(A,'stadard') + A = 'standard'; + end + kpos=strfind(R,basicString); + coilName=deblank(R(2:kpos-1)); + [C,R]=strtok(R(kpos+length(basicString):length(R))); + if strmatch(C,C3options) + stringC=strvcat(stringC,C); + end + [unit,R]=strtok(R); + positionSet=intersect(strmatch(A,stringA),strmatch(C,stringC)); + if isempty(positionSet) | ~strcmp(unit,unitString) | ~isempty(R) + break; + end + if positionSet==lastPositionSet + coil=coil+1; + else + coil=1; + end + if positionSet==1 + % Assemble list of coil names + coilLabel=strvcat(coilLabel,coilName); + nCoil=coil; + elseif ~strcmp(coilName,deblank(coilLabel(coil,:))); + break; + end + % The line describing the coil and coordinate frame is OK. + % Get the coordinates by reading 3 lines. + buff=fscanf(fhc,'%s%s%f',9); + if ~isequal(size(buff),[9 1]) + break + end + rhc=[rhc prec*round(buff(3:3:9)/prec)]; + fgetl(fhc); % Skip to the start of the next line. + textline=fgetl(fhc); + lastPositionSet=positionSet; +end +fclose(fhc); + +clear lastPositionSet coil textline fhc; +clear stringA A C R kpos coilName unit buff; + +if size(rhc,2)~=positionSet*nCoil + fprintf('readHc: File %s does not have %d complete sets of %d coils.\n',... + hcFile,positionSet,nCoil); + return +end + +if max(max(abs(rhc)))>maxRCoil & printWarning + fprintf('readHc: Head Coil file %s\n max(coil position)>%d.\n',... + hcFile,round(maxRCoil)); +end + +% Assemble structure hc. +hc=struct('names',coilLabel); +coilCoords=deblank(strvcat('standard','dewar',stringC(3,:))); +for q=1:positionSet + hc=setfield(hc,deblank(coilCoords(q,:)),rhc(:,nCoil*(q-1)+[1:nCoil])); +end +return +%%%%%%%%% End of readHc %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%% Function readEEG %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function EEG=readEEG(EEGfile); + +% Reads the EEG file of a dataset and stores the infoemation in strucure array EEG. +% EEG(k).chanName = channel name in the dataset (EEGmmm where mmm=channel number) +% EEG(k).name = channel name given by the user (e.g. Fp4) +% EEG(k).pos = electrode position in cm in CTF head coordinates + +if exist(EEGfile)~=2 + EEG=struct([]); + return +end + +fid=fopen(EEGfile,'r'); +EEG=struct('chanNum',[],'name',char([]),'pos',[]); +nEEG=0; +while 1 + chanNum=fscanf(fid,'%d',1); + name=fscanf(fid,'%s',1); + pos=fscanf(fid,'%f',3); + if isempty(pos);break;end + nEEG=nEEG+1; + EEG(nEEG)=struct('chanNum',chanNum,'name',name,'pos',pos); +end +fclose(fid); +return +%%%%%%%%% End of readEEG %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%% Function readClassFile %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function TrialClass=readClassFile(ClassFileName); + +% Reads a CTF ClassFile and stores information in a structure. +% The class file allows a user to store a list of classsified trials in a data set. +% The ClassFile format is defined in document CTF MEG File Formats, PN900-0088. +% This format is rigid and readClassFile assumes that the ClassFile has the format +% current in October 2006. + +% Inputs : +% ClassFileName : marker file including the full path and extension .mrk. +% trialList : List of trials to read. Trial numbering : 1,2,... +% If omitted or empty, read all markers. + +% Output : Structure array marker. Output trial numbering starts at 1. +% See CTF MEG File Formats, (PN900-0088) for the meaning of the structure +% fields. A trial mat=y start before the t=0 point, so it is possible to have +% markers with time<0 (see ds.res4.preTrigPts). + +TrialClass=struct([]); + +if exist(ClassFileName)~=2 + return % File doesn't exist. +end + +fid=fopen(ClassFileName,'r','ieee-be'); + +for k=1:5;fgetl(fid);end % Skip 5 lines (including path info) +nClass=sscanf(fgetl(fid),'%d',1); %Read value and skip to the start of the next non-blank line. +if nClass<=0 + fprintf('readClassFile: File %s has %d classes.\n',nClass); + return +end + +TrialClass=struct('ClassGroupId',[],'Name',char([]),... + 'Comment',char([]),'Color',char([]),'Editable',char([]),'ClassId',[],'trial',[]); + +for k=1:nClass + % Find the start of the next class identification + % There is no need to check for end of file because the loop ends before an attempt + % is made to read class nClass+1. + while ~strcmp('CLASSGROUPID:',fgetl(fid));end + ClassGroupId=sscanf(fgetl(fid),'%d',1); + fgetl(fid); + Name=deblank(fgetl(fid)); + fgetl(fid); + Comment=deblank(fgetl(fid)); + fgetl(fid); + Color=deblank(fgetl(fid)); + fgetl(fid); + Editable=deblank(fgetl(fid)); + fgetl(fid); + ClassId=sscanf(fgetl(fid),'%d',1); + fgetl(fid); + No_of_Trials=sscanf(fgetl(fid),'%d',1); + fgetl(fid);fgetl(fid); + if No_of_Trials>0 + trial=reshape(fscanf(fid,'%d',No_of_Trials),1,No_of_Trials); + else + trial=[]; + end + % Adjust trial numbering so it starts at 1. + TrialClass(k)=struct('ClassGroupId',ClassGroupId,'Name',Name,... + 'Comment',Comment,'Color',Color,'Editable',Editable,'ClassId',ClassId,... + 'trial',trial+1); +end +fclose(fid); +return +%%%%%%%%% End of readClassFile %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%% Function readBadSegments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function badSegments=readBadSegments(badSegmentsFile); + +% Reads the bad.segements file of a CTF data set and stores the information in structure +% bad_segments. +% badSegments.trial = List of trial numbers +% badSegments.StartTime = List of bad segment start times (relative to trial). +% badSegments.EndTime = List of bad segment end times. + +% Reads the file one line at a time. Each line has three numbers. +% 1st: Trial number=integer. Trial numbering for bad.segments starts at 1. +% 2nd,3rd : Start, End times (s). + +if exist(badSegmentsFile)~=2 + badSegments=struct([]); + return +end + +fid=fopen(badSegmentsFile,'r','ieee-be'); +badSegments=struct('chanName',char([]),'name',char([]),'pos',[]); +nLine=0; +data=zeros(3,0); +while 1 + txt=fgetl(fid); + if isequal(txt,-1);break;end + nLine=nLine+1; + [buff,count]=sscanf(txt,'%f'); + % Are the data good? + badline=(count~=3); + if ~badline;badline=(abs((buff(1)-round(buff(1)))>0.0001) | buff(3)=#2.\n'); + badSegments=struct([]); + return + end + data=[data buff]; +end +fclose(fid); +badSegments=struct('trial',data(1,:),'StartTime',data(2,:),'EndTime',data(3,:)); + +return +%%%%%%%%% End of readBadSegments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%% Function readVirtualChannels %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function Virtual=readVirtualChannels(VirtualChannelsName); + +% Reads the Virtual channels file associated with a data set + +Virtual=struct([]); +% Check VirtualChannelsName +if exist('VirtualChannelsName')~=1;VirtualChannelsName=char([]);end +if isempty(VirtualChannelsName) + fprintf('readVirtualChannels: Must specify a VirtualChannels file.\n'); + return +elseif ~ischar(VirtualChannelsName) + fprintf('readVirtualChannels: VirtualChannelsName must be a character string.\n'); + return +elseif exist(VirtualChannelsName)~=2 + fprintf('readVirtualChannels: Cannot find file %s\n',VirtualChannelsName); + return +end + +fid=fopen(VirtualChannelsName,'r'); +count=0; +Virtual=struct('Name',char([]),'Unit',char([]),'chan',char([]),'wt',[]); + +strng=textread(VirtualChannelsName,'%s','delimiter',',\t'); +k=0; +while k0.1) | any(round(trialList)<=0) + fprintf('readMarkerFile: trialList must have only positive integers.\n'); + return + end +end + +fid=fopen(MarkerFileName,'r','ieee-be'); + +for k=1:5;fgetl(fid);end % Skip 5 lines (including path info) +nMarker=sscanf(fgetl(fid),'%d',1); %Read value and skip to the start of the next non-blank line. +if nMarker<=0 + fprintf('readMarkerFile: File %s has %d markers.\n',nMarker); + fclose(fid); + return +end + +marker=struct('ClassGroupId',[],'Name',char([]),... + 'Comment',char([]),'Color',char([]),'Editable',char([]),'ClassId',[],... + 'BitNumber',[],'Polarity',char([]),'Source',char([]),'Threshold',[],... + 'trial',[],'time',[]); + +for k=1:nMarker + % Find the start of the next marker identification + % There is no need to check for end of file because the loop ends before an attempt + % is made to read marker class nClass+1. + while ~strcmp('CLASSGROUPID:',fgetl(fid));end + ClassGroupId=sscanf(fgetl(fid),'%d',1); + if ~any(ClassGroupId==[0 3]) + fprintf('read_MarkerFile: Skipping a marker with CLASSGROUPID=%d\n',ClassGroupId); + continue; + end + fgetl(fid); + Name=deblank(fgetl(fid)); + fgetl(fid); + Comment=deblank(fgetl(fid)); + fgetl(fid); + Color=deblank(fgetl(fid)); + fgetl(fid); + Editable=deblank(fgetl(fid)); + fgetl(fid); + ClassId=sscanf(fgetl(fid),'%d',1); + if ClassGroupId==0 + fgetl(fid); + BitNumber=sscanf(fgetl(fid),'%d',1); + fgetl(fid); + Polarity=deblank(fgetl(fid)); + fgetl(fid); + Source=deblank(fgetl(fid)); + fgetl(fid); + Threshold=sscanf(fgetl(fid),'%f',1); + else + BitNumber=[]; + Polarity=char([]); + Source=char([]); + Threshold=[]; + end + fgetl(fid); + No_of_Samples=sscanf(fgetl(fid),'%d',1); + fgetl(fid);fgetl(fid); + trial=zeros(1,No_of_Samples); + time=zeros(1,No_of_Samples); + if No_of_Samples>0 + buff=fscanf(fid,'%d %f\n',2*No_of_Samples); + trial=reshape(buff(1:2:2*No_of_Samples-1),1,No_of_Samples)+1; % Trial numbering starts at 1. + time=reshape(buff(2:2:2*No_of_Samples),1,No_of_Samples); + clear buff; + end + % Keep only the specified trials. + if ~isempty(trialList) + index=[]; + for q=trialList; + index=[index find(trial==q)]; + end + trial=trial(index); + time=time(index); + No_of_Samples=length(index); + clear q index; + end + marker(k)=struct('ClassGroupId',ClassGroupId,'Name',Name,... + 'Comment',Comment,'Color',Color,'Editable',Editable,'ClassId',ClassId,... + 'BitNumber',BitNumber,'Polarity',Polarity,'Source',Source,'Threshold',Threshold,... + 'trial',trial,'time',time); +end +fclose(fid); +%clear k ClassGroupId Name Comment Color Editable ClassID No_of_Samples trial time; +return +%%%%%%%%%%%% End of readMarkerFile %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/external/ctf/readCTFds.p b/external/ctf/readCTFds.p deleted file mode 100644 index 05d3689..0000000 Binary files a/external/ctf/readCTFds.p and /dev/null differ diff --git a/external/ctf/readCTFhdm.m b/external/ctf/readCTFhdm.m new file mode 100644 index 0000000..f16e162 --- /dev/null +++ b/external/ctf/readCTFhdm.m @@ -0,0 +1,186 @@ +function hdm=readCTFhdm(fileName); + +% Version 1.1 19 April 2007 - Test date. +% 21 March 2007. Modified to read v6.0 .hdm files that have additional +% fields in MultiSphere_Data +% Reads a head model file and returns the contents as a structure. The purpose is +% to make localSpheres head models available in the MATLAB environment. +% Head Model File format is a "Config Reader" file. It is defined in document +% "CTF MEG FIle Formats', PN900-0088. + +% Input : fileName: Name of a .hdm file + +% Output: hdm: A structure with a field for comments, and a field for each +% class in the .hdm file. Within each class field, there is a field for +% each tag found in the class, except for the MultiSphere_Data where +% the information is repackaged as SQUIDname, sphereOrigin and radius. + +% NOTE : In ths Config reader file format, white space can be spaces or tabs or +% multiple spaces or multiple tabs. Therefore cannot know where the '{' and '}' +% characters appear. + +persistent printWarning + +% Create a list of characters that are allowed in classnames. +% his wil be used to decide if the file is not in "Config Reader" format. +allowedChars=char(['A':'Z' 'a':'z' '0':'9' '_']); +forbiddenChars=setdiff(char(0:255),allowedChars); + +% Check inputs and print messages. +if nargin==0 & nargout==0 + fprintf('readCTFhdm Version 1.1 19 April 2007\n'); + fprintf(['\thdm=readCTFhdm(fileName) creates a structure containing the contents of ',... + 'a CTF-format head model file.\n',... + '\t\t\tfileName is the name of a head model file including path and ',... + 'extension .hdm\n',... + '\t\t\thdm is a MATLAB structure containing the head model (comments,source \n',... + '\t\t\t\tinformation, single-sphere model, multiple local Sphere model).\n',... + '\t\t\tThe head model file format is described in document ',... + '"CTF MEG File Formats", PN900-0088.\n\n']); + return +end + +hdm=struct([]); % Force error in calling program with an early return + +if nargout~=1 | nargin~=1 + fprintf(['\nreadCTFhdm: %d input and %d output arguments.\n',... + ' readCTFhdm must have 1 input and 1 output.\n\n'],nargin,nargout); + if nargout==0;clear hdm;end + return +elseif ~ischar(fileName) | isempty(fileName) | ndims(fileName)>2 | min(size(fileName))~=1 + fprintf('readCTFhdm: Input argument is not character string, or is empty.\n'); + return +elseif exist(fileName)~=2 + fprintf('readCTFhdm: Cannot find file %s\n',fileName); + return +end + +fid=fopen(fileName,'r','ieee-be'); + +hdm=struct('note',char([])); +classOpen=0; +className=char([]); +while 1 + txtline=fgetl(fid); + if isequal(txtline,-1);break;end % eof of file + txtline=deblank(txtline); + if isempty(deblank(txtline)) % Empty line + continue + end + % Remove leading white space + txtline=deblank(txtline(length(txtline):-1:1)); + txtline=txtline(length(txtline):-1:1); + + % Is this line a comment? If yes it will be added to a note field. + comment=strcmp('//',sscanf(txtline,'%s',1)); + if comment & classOpen==0; % Comment + hdm.note=strvcat(hdm.note,txtline); + elseif strcmp(txtline,'{') % Start of new class + if isempty(className); + fprintf('readCTFhdm: Error decoding file %s.\n',filename); + fprintf('\tEncountered ''{'' without first finding a class name.\n'); + hdm=struct([]); % Force an error in the calling program. + break + end + classOpen=1; + elseif strcmp(txtline,'}') % Close the class + className=char([]); + classOpen=0; + elseif classOpen==0 % Create a new class. + className=txtline; + if ~strcmp(className,strtok(className,forbiddenChars)) + fprintf('\nreadCTFhdm : File %s\n',fileName); + fprintf([' Encountered className ''%s'' which includes characters ',... + 'that are not allowed in a class name.\n\n'],className); + break + end + % Create an empty note field + eval(['hdm.',className,'.note=char([]);']); + elseif comment + eval(['hdm.',className,'.note=strvcat(hdm.',className,'.note,txtline);']); + else + [tag,txtline]=strtok(txtline,':'); + % Special code for the case where a user has managed to get the first one or two + % characters of the coefficient set into a channel name. + tag=deblank(strtok(tag,'-')); + % Remove leading ':' and leading and trailing white spaces + txtline=deblank(txtline(length(txtline):-1:2)); + txtline=deblank(txtline(length(txtline):-1:1)); + + % Identify text fields + if strcmp(className,'MultiSphere_Data') & strcmp(tag,'HEADPOS') + % This line has both numerical and text fields delimited by tabs, + lasttab=max(strfind(txtline,char(9))); + value=struct('HEADPOS',sscanf(txtline(1:lasttab),'%g'),... + 'NOMINAL',txtline((lasttab+1):length(txtline))); + %headpos=sscanf(txtline(1:lasttab),'%g'); + %nominal=txtline((lasttab+1):length(txtline)); + %hdm.MultiSphere_Data.HEADPOS=struct('HEADPOS',headpos,'NOMINAL',nominal); + elseif strcmp(className,'File_Info') | strcmp(className,'Model') | ... + (strcmp(className,'MultiSphere_Data') & ... + (strcmp(tag,'HEADSHAPE_FILE') | strcmp(tag,'SURFACE_TYPE'))) + % Remove leading and trailing blanks and the ':' terminator of the tag name. + value=txtline; + else + value=sscanf(txtline,'%g'); + end + eval(['hdm.',className,'.',tag,'=value;']); + end +end +fclose(fid); +if classOpen + fprintf(['readCTFhdm : End-of file with class open?\n',... + '\t\tThere must be an error in %s\n'],fileName); +end +clear txtline tag value classOpen className comment fid; + +if isfield(hdm,'MultiSphere_Data'); + % Convert to a more convenient way to interpret info. + SQUIDname=char(fieldnames(hdm.MultiSphere_Data)); + % v6.0 .hdm files define SURFACE_TYPE and HEADPOS + nonSQUIDname=strvcat('note','SEARCH_RADIUS','HEADSHAPE_FILE','SURFACE_TYPE','HEADPOS'); + + % Remove tags referring to something else + for k=1:size(nonSQUIDname,1) + index=strmatch(deblank(nonSQUIDname(k,:)),SQUIDname,'exact'); + if ~isempty(index) + SQUIDname=SQUIDname(setdiff(1:length(SQUIDname),index),:); + end + end + clear k index; + + SQUIDname=deblank(SQUIDname); + sphereOrigin=zeros(3,size(SQUIDname,1)); + radius=zeros(1,size(SQUIDname,1)); + + for k=size(SQUIDname,1):-1:1 + buff=getfield(hdm.MultiSphere_Data,deblank(SQUIDname(k,:))); + sphereOrigin(:,k)=buff(1:3); + radius(k)=buff(4); + hdm.MultiSphere_Data=rmfield(hdm.MultiSphere_Data,deblank(SQUIDname(k,:))); + end + clear k buff; + + hdm.MultiSphere_Data.SQUIDname=SQUIDname; + hdm.MultiSphere_Data.sphereOrigin=sphereOrigin; + hdm.MultiSphere_Data.radius=radius; +end + +% If there is no head-shape information in the file, print a warning. +if ~isfield(hdm,'Model') | (~isfield(hdm,'MultiSphere_Data') & ~isfield(hdm,'MEG_Sphere')) + fprintf(['\nreadCTFhdm: Structure hdm is missing fields Model, MEG_sphere, or ',... + 'MultiSphere_Data.\n\t\t\t Is file %s a head model file?\n\n'],fileName); + missingField=1; +else + missingField=0; +end + +if isempty(printWarning) + fprintf(['\nreadCTFhdm: You are reading a CTF head model for use with a software-application\n',... + '\ttool that is not manufactured by VSM MedTech Ltd. and has not received marketing\n',... + '\tclearance for clinical applications. If CTF MEG data are processed by this tool,\n',... + '\tthey should not be later employed for clinical and/or diagnostic purposes.\n']); + if missingField==0;printWarning=1;end +end + +return \ No newline at end of file diff --git a/external/ctf/readCTFhdm.p b/external/ctf/readCTFhdm.p deleted file mode 100644 index 03aa28e..0000000 Binary files a/external/ctf/readCTFhdm.p and /dev/null differ diff --git a/external/ctf/setCTFDataBalance.m b/external/ctf/setCTFDataBalance.m new file mode 100644 index 0000000..416dd78 --- /dev/null +++ b/external/ctf/setCTFDataBalance.m @@ -0,0 +1,794 @@ +function [data,ds]=setCTFDataBalance(data,ds,balance1,unit,chanList,messages); + +% Version 1.1 13 April 2007 Mod to chanList: If chanList is omitted and +% size(data,2)ds.res4.no_channels + fprintf('\nsetCTFDataBalance: ds.res4.no_channels=%d, but size data=[',... + ds.res4.no_channels); + fprintf(' %d',size(data));fprintf(']\n\n'); + data=[];ds=-1; + return +end +if exist('chanList')~=1;chanList=[];end +if ~isempty(chanList) % chanList~=[]. Check chanList + if ~isnumeric(chanList) + fprintf('\nsetCTFDataBalance: chanList has the wrong type.\n\n'); + whos data ds balance1 chanList + data=[];ds=-1; + return + else % chanList is numeric and non-empty + % Check that chanList is a vector + if sum(size(chanList)>1)>1 + fprintf('\nsetCTFDataBalance: size(chanList)=[');fprintf(' %d',size(chanList)); + fprintf('] Not a vector.\n\n'); + data=[];ds=-1; % Force an error in the calling program + return + else + chanList=reshape(chanList,1,length(chanList)); % chanList is a row vector. + if any(chanList<=0) | any(chanList>ds.res4.no_channels) | ... + length(chanList)~=size(data,2) + fprintf('setCTFDataBalance: Error in input chanList:\n'); + fprintf(' min(chanList)=%d max(chanList)=%d Dataset has %d channels.\n',... + min(chanList),max(chanList),ds.res4.no_channels); + fprintf('length(chanList)=%d size(data)=[',length(chanList)); + fprintf(' %d',size(data)); + fprintf('] Must have length(chanList)=size(data,2)\n'); + data=[];ds=-1; % Force an error in the calling program + return + end + end + end + +else % chanList=[]. Array data must include all of the channels. + if size(data,2)2 + fprintf('\nsetCTFDataBalance: Input messages=%d. Must be [], 0, 1 or 2.\n\n',messages); + data=[];ds=-1; + return +end + +% Process data in blocks of nChBlock channels to reduce virtual memory demand. +nChBlock=max(1,floor(buffsize/size(data,1))); + +% badGref = list of bad reference gradiometers referred to dataset channel numbering. +% badGMEG = list of bad MEG gradiometers referred to dataset channel numbering. +% These gradiometers are considered bad because their grad_order_no is wrong, not +% because thay are listed in ds.BadChannels +[balance0,badGref,badGMEG,Greflist,GMEGlist]=getDsBalance(ds); +if strmatch('BAD',balance0) + fprintf(['\nsetCTFDataBalance: The balance order of the Grefs and/or the MEG ',... + 'channels cannot be determined.\n',... + ' Check ds.res4.senres().grad_order_no.\n\n']); + data=[];ds=-1; % Force an error in the calling program + return +end + +% Check balance1 and put in a standard form. +balance1=check_balance(balance1); +if isempty(balance1) | isempty(balance0) + fprintf(['\nsetCTFDataBalance: size(ds balance) =[%d %d] (after call to ',... + 'getDsBalance.)\n',... + ' size(new balance)=[%d %d] (after call to check_balance.)\n\n'],... + size(balance0),size(balance1)); + data=[];ds=-1; % Force an error in the calling program + return +end + +% Print a message? +chanset=strvcat('MEGs','Grefs'); +for k=1:2 + if messages==2 | (messages==1 & ~strcmp(balance0(k,:),balance1(k,:))) + fprintf('setCTFDataBalance: Adjusting %s from balance=%s to balance=%s.\n',... + chanset(k,:),balance0(k,:),balance1(k,:)); + end +end +clear k chanset; + +if isequal(balance0,balance1) + return +end + + +% Convert from balance0 to unbalanced. +if ~isequal(balance0,strvcat('NONE','NONE')); + data=unbalance_data(data,ds,balance0,unit,nChBlock,chanList,badGref); + % unbalance_data returns data=[] when list badGref includes a Gref that is required for + % balancing. + if isempty(data);ds=-1;return;end +end + +% Convert from unbalanced to balance1. +if ~isequal(balance1,strvcat('NONE','NONE')); + % balance_data returns data=[] when badGref includes a Gref that is required for + % balancing. + data=balance_data(data,ds,balance1,unit,nChBlock,chanList,badGref,messages); + if isempty(data);ds=-1;return;end +end + +% Mark the balance order in structure ds. +% Make sure that the bad channels are marked with a different order. This will force +% errors if these data are used later. Set the data in the bad channels to zero, and add +% the bad channels to ds.BadChannels. +Gorder=strmatch(balance1(2,:),balanceOptions)-1; +MEGorder=strmatch(balance1(1,:),balanceOptions)-1; +for k=setdiff(Greflist,badGref) + ds.res4.senres(k).grad_order_no=Gorder; +end +for k=setdiff(GMEGlist,badGMEG) + ds.res4.senres(k).grad_order_no=MEGorder; +end +for k=badGref + ds.res4.senres(k).grad_order_no=0; +end +for k=badGMEG + ds.res4.senres(k).grad_order_no=round(3-MEGorder); +end +% Set channels with bad balance order parameter to zero. +kBad=[badGref badGMEG]; +if ~isempty(chanList) + kBad=reindex(chanList,intersect(chanList,kBad)); +end +for k=kBad + if strcmp(prec,'single') + data(:,k,:)=single(zeros(size(data,1),1,size(data,3))); + else + data(:,k,:)=zeros(size(data,1),1,size(data,3)); + end +end +clear k Gorder MEGorder; + +if isempty([badGref badGMEG]);return;end +% Add bad channels to ds.BadChannels + +if ~isfield(ds,'BadChannels');ds.BadChannels=char([]);end +BadList=union(badGref,badGMEG); +if ~isempty(ds.BadChannels) + for k=1:size(ds.BadChannels,1) + BadList=[BadList strmatch(deblank(ds.BadChannels(k,:)),ds.res4.chanNames)]; + end + ds.BadChannels=char([]); +end +for k=sort(BadList) + ds.BadChannels=strvcat(ds.BadChannels,strtok(ds.res4.chanNames(k,:),'- ')); +end +return +% ************** End of function setCTFDataBalance ********************************** +% ********************************************************************************** + +% ******************************************************************************** +% ******************* function getDsBalance ************************************** +function [dsbalance,badGref,badGMEG,Greflist,GMEGlist]=getDsBalance(ds); +% Get the current balance state from structure ds. Check for channels that are marked +% as bad by having a different grad_order_no. +% Check whether things make sense. + +% Return the balance and lists of bad gradiometers. +% Also return the complete list of reference gradiometers and MEG gradiometers since +% setCTFDataBalance uses them. + +% In normal operation, getDsBalance will return badGref=[], badGMEG=[]; +balanceOptions=strvcat('NONE','G1BR','G2BR','G3BR'); +Greflist=[]; % List of reference gradiometers (sensorTypeIndex=1) +Greforder=[]; +GMEGlist=[]; % List of MEG gradiometers (sensorTypeIndex=5) +GMEGorder=[]; + +% Make lists of sensors and gradient balancing. +for k=1:ds.res4.no_channels + if ds.res4.senres(k).sensorTypeIndex==1 + Greflist=[Greflist k]; + Greforder=[Greforder ds.res4.senres(k).grad_order_no]; + elseif ds.res4.senres(k).sensorTypeIndex==5 + GMEGlist=[GMEGlist k]; + GMEGorder=[GMEGorder ds.res4.senres(k).grad_order_no]; + end +end + +% Reference balance OK? +dsbalance=char(zeros(2,4)); +if any(Greforder<0) | any(Greforder>1) + fprintf(['\nsetCTFDataBalance: The reference gradiometer balance orders make no ',... + 'sense.\n %2d Gref channels. %2d have grad_order_no=0\n'],... + length(Greflist),sum(Greforder==0)); + fprintf(' %2d have grad_order_no=1\n',sum(Greforder==1)); + fprintf(' %2d have grad_order_no<0 or >1\n',... + sum(Greforder>1)+sum(Greforder<0)); + dsbalance=strvcat(dsbalance(1,:),'BAD'); + badGref=Greflist; % Mark everything bad +elseif sum(Greforder==0)>sum(Greforder==1) + dsbalance=strvcat(dsbalance(1,:),balanceOptions(1,:)); + badGref=Greflist(find(Greforder~=0)); +else + dsbalance=strvcat(dsbalance(1,:),balanceOptions(2,:)); + badGref=Greflist(find(Greforder~=1)); +end + +% Sort MEG gradiometer balance. In correct operation, all MEG channels should have the +% same balance (0,1,2 or 3). +for bal=0:3 + nMEGbal(bal+1)=sum(GMEGorder==bal); +end + +[maxbal MEGorder]=max(nMEGbal); +MEGorder=MEGorder-1; + +if maxbal>ceil(0.5*length(GMEGlist)) & all(GMEGorder>=0) & all(GMEGorder<=3) + dsbalance(1,:)=balanceOptions(MEGorder+1,:); + badGMEG=GMEGlist(GMEGorder~=MEGorder); +else + fprintf('\nsetCTFDataBalance: The MEG-sensor balance orders make no sense.\n'); + fprintf(' %3d MEG gradiometer channels.\n',length(GMEGlist)); + fprintf(' %3d have grad_order_no=%d\n',[nMEGbal;0:3]); + if sum(nMEGbal)3\n\n',... + length(GMEGlist)-sum(nMEGbal)); + end + dsbalance=strvcat('BAD',dsbalance(2,:)); + badGMEG=GMEGlist; % Mark everything bad` +end + +return +% ************** End of function getDsBalance ********************************** +% ********************************************************************************** + +% ******************************************************************************** +% ******************* function check_balance ************************************** +function balance=check_balance(balance); + +% make sure that character array balance has the correct format. + +balance_options=strvcat('NONE','G1BR','G2BR','G3BR'); + +% Make balance into a [4 2] character array +if ~ischar(balance) & ~isempty(balance) + fprintf('setCTFDataBalance (check_balance): balance is not a character array.\n'); + balance=char([]); % Force an error. + return; +elseif isempty(deblank(balance)) + balance=strvcat('NONE','NONE'); + return +elseif size(balance,1)==1 + balance=strvcat(balance,'NONE'); % No Gref balancing +elseif size(balance,1)>2 + fprintf('setCTFDataBalance (check_balance): size(balance)=[%d %d]?\n',size(balance)); + balance=char([]); % Force an error. + return +end + +balance=upper(balance); +if size(balance,2)>4;balance=balance(:,1:4);end + +for k=1:2 % k=1:MEGs, k=2:Grefs + if isempty(deblank(balance(k,:))); + balance(k,:)='NONE'; + elseif isempty(strmatch(balance(k,:),balance_options(1:(6-2*k),:))) + fprintf('check_balance: balance(%d,:)=%s Not an allowed option.\n',k,balance(k,:)); + balance=char([]); % Force an error? + return + end +end + +return +% ************** End of function check_balance ********************************** +% ********************************************************************************** + + + +% ************************************************************************ +% ****** Convert from balanced to unbalanced data ********************** +function data=unbalance_data(data,ds,balance0,unit,nChBlock,chanList,badGref); +% Inputs: data: Data array. size(data)=[Npt Nchan Ntrial] +% ds: ds strtcuture for the data. +% balance0: balance0(1,:) = MEG balance before unbalancing +% balance0(2,:) = Gref balance before unbalancing +% unit : 'ft','t' (physical units) +% 'int', 'phi0' +% chanList: List if channels included in array data (referred to the channel +% numbering in structure ds) +% badGref: A list of gRef channels markes as bad because they seen to have the +% wrong grad_order_no. + +if ~exist('chanList');chanList=[];end +prec=class(data); + +% Read the balance tables for both MEG and reference gradiometers. +% Usually balance0(2,:)='NONE', and it returns alphaGref=[]. +[alphaMEG,MEGindex,MEGbalanceindex,alphaGref,Grefindex,Gbalanceindex]=... + getCTFBalanceCoefs(ds,balance0,unit); + +% Unbalance the Grefs first. In almost all cases, balance0(2,:)='NONE', +% so the program will skip this section. +if ~strcmp(upper(balance0(2,:)),'NONE') + % The index lists give channel numbers referred to data set channel numbering + + if isempty(Grefindex) | isempty(Gbalanceindex) + fprintf('setCTFDataBalance (unbalance_data): balance=%s\n',... + '\t\tsize(Grefindex)=[%d %d] size(Gbalanceindex)=[%d %d] ??\n',balance0(2,:),... + size(Grefindex),size(Gbalanceindex)); + data=[]; % Force an error in the calling program + return + end + + % Are there any badGref in the Gbalanceindex list? + if ~isempty(intersect(Gbalanceindex,badGref)) + fprintf(['setCTFDataBalance (unbalance_data): A reference gradiometer marked bad ',... + 'because of its grad_order_no\n',... + ' appears in the list of reference sensors required for ',... + '%s Gref balancing.\n'],balance0(2,:)); + fprintf(' Gbalanceindex=');fprintf(' %d',Gbalanceindex);fprintf('\n'); + fprintf(' badGref=');fprintf(' %d',badGref);fprintf('\n'); + data=[]; % Force an error in the calling program + return + end + + if isequal(chanList,1:max(max(Gbalanceindex),max(Grefindex)));chanList=[];end + if ~isempty(chanList) + if ~isempty(setdiff(Gbalanceindex,chanList)) + fprintf(['setCTFDataBalance (unbalance_data): List chanList does not include ',... + 'all of the reference sensors in the %s table for reference gradiometers.\n'],... + balance0(2,:)); + data=[]; + return + end + [Gbalanceindex,Grefindex,alphaGref]=... + reindex(chanList,Gbalanceindex,Grefindex,alphaGref); + end + + % Balancing reference gradiometers: + % balanced_data(:,Grefindex) + % =raw_data(:,Grefindex)-raw_data(:,Gbalanceindex)*alphaGref + % size(alphaGref)=[length(Gbalanceindex) length(Grefindex)] + % Note : not all of the sensors in list Gbalanceindex are gradiometers. + + % Rewrite as a matrix equation: + % balanced_data(:,Gindex)=raw_data(:,Gindex)*Gbalmat + % Gindex=list of all the sensors involved in balancing the reference + % gradiometers. + % size(Gbalmat)=[length(Gindex) length(Gindex)] + + [Gindex]=union(Gbalanceindex,Grefindex); + [Cx,Fbal]=intersect(Gindex,Gbalanceindex); % Gindex(Fbal)=Gbalanceindex + [Cx,Fref]=intersect(Gindex,Grefindex); % Gindex(Fref)=Grefindex + + Gbalmat=eye(length(Gindex)); + Gbalmat(Fbal,Fref)=Gbalmat(Fbal,Fref)-alphaGref; + clear Fbal Fref Cx Grefindex Gbalanceindex alphaGref; + % Convert to unbalanced reference gradiometers + for pt=1:size(data,3) + if strcmp(prec,'single') + data(:,Gindex,pt)=single(double(data(:,Gindex,pt))/Gbalmat); + else + data(:,Gindex,pt)=data(:,Gindex,pt)/Gbalmat; + end + end + clear Gbalmat pt; +end % Finished unbalancing the reference gradiometers + +if strcmp(upper(balance0(1,:)),'NONE'); + return; % No unbalancing required for MEG gradiometers +end + +% Are there any badGref in the MEGbalanceindex list? +if ~isempty(intersect(MEGbalanceindex,badGref)) + fprintf(['setCTFDataBalance (unbalance_data): A reference gradiometer marked bad ',... + 'because of its grad_order_no\n',... + ' appears in the list of reference sensors required for ',... + '%s MEG balancing.\n'],balance0(1,:)); + fprintf(' MEGbalanceindex=');fprintf(' %d',MEGbalanceindex);fprintf('\n'); + fprintf(' badGref=');fprintf(' %d',badGref);fprintf('\n'); + data=[]; % Force an error in the calling program + return +end + +% Don't bother with chanList if it obviously includes all the SQUID channels and in +% the dataset ordering. +if isequal(chanList,1:max(max(MEGindex),max(MEGbalanceindex)));chanList=[];end + +if isempty(alphaMEG) | isempty(MEGindex) | isempty(MEGbalanceindex) + return; +elseif ~isequal(size(alphaMEG),[length(MEGbalanceindex) length(MEGindex)]) + fprintf(['setCTFDataBalance (unbalance_data): size(alphaMEG)=[%d %d] ',... + 'length(MEGbalanceindex)=%d length(MEGindex)=%d\n'],... + size(alphaMEG),length(MEGbalanceindex),length(MEGindex)); + data=[]; + return +elseif all(reshape(alphaMEG,1,length(MEGbalanceindex)*length(MEGindex))==0) + return +end + +% Make the index lists refer to the entries in chanList. +if ~isempty(chanList) + if ~isempty(setdiff(MEGbalanceindex,chanList)) + fprintf(['setCTFDataBalance (unbalance_data): List chanList does not include ',... + 'all of the reference sensors in the %s table for MEG gradiometers.\n'],... + balance0(1,:)); + data=[]; + return + end + [MEGbalanceindex,MEGindex,alphaMEG]=... + reindex(chanList,MEGbalanceindex,MEGindex,alphaMEG); +end + +% Reverse the balance applied to the MEG channels. Needs unbalanced reference data. +if ~isempty(alphaMEG) & ... + ~isequal(alphaMEG,zeros(length(MEGbalanceindex),length(MEGindex))) + % Unbalance MEG data trial-by-trial and in blocks of nChBlock channels + for pt=1:size(data,3) + for m=1:nChBlock:length(MEGindex) + mptr=m:min(m+nChBlock-1,length(MEGindex)); + MEGblock=MEGindex(mptr); + if strcmp(prec,'single'); + data(:,MEGblock,pt)=single(double(data(:,MEGblock,pt))+... + double(data(:,MEGbalanceindex,pt))*alphaMEG(:,mptr)); + else + data(:,MEGblock,pt)=data(:,MEGblock,pt)+... + data(:,MEGbalanceindex,pt)*alphaMEG(:,mptr); + end + end + end + clear pt m mptr MEGblock; +end + +return +% ******************* End of function unbalance_data **************************** +% *********************************************************************************** + + + +% *********************************************************************************** +% *************** Convert from unbalanced data to balanced data ******************* +function data=balance_data(data,ds,balance,unit,nChBlock,chanList,badGref,messages); + +% Extracts the balance table from structure ds and balances data as specified in balance. +% If the balancing requires a reference gradiometer marked in the badGref list, an error +% message is printed and the data array is set to []. + +% If a MEG channel is missing from the balance table, then the channel is set to zero. + +% Inputs: data: The aray of data to be balanced. +% ds: The ds structure read by readCTFds that contains the balance table. +% balance: The desired output balance state. +% balance(1,:) = MEG balance +% balance(2,:) = Gref balance +% unit : Data units ('fT','T','phio','int') +% nChBlock : rad the data in blocks of nChBlock to reduce memory requirements. +% chanList: List of the channels that actual;ly appear in data. referred to the +% dataset channel numbering (not to te list of SQUID channels) +% badGref: List of reference gradiometer channels that cannot be used for +% balancing. + +if ~exist('chanList');chanList=[];end +prec=class(data); +[alphaMEG,MEGindex,MEGbalanceindex,alphaGref,Grefindex,Gbalanceindex]=... + getCTFBalanceCoefs(ds,balance,unit); +if ~strcmp(lower(balance(1,:)),'NONE'); + % Are there any MEG channels missing from list MEGindex (i.e. missing from the balance table)? + % Make a list of MEG channels referred to dataset channel numbering. + MEGlist=[]; + for k=1:ds.res4.no_channels + if ds.res4.senres(k).sensorTypeIndex==5;MEGlist=[MEGlist k];end + end + missingMEG=setdiff(MEGlist,MEGindex); + if ~isempty(missingMEG) & messages~=0 & ... + (isempty(chanList) | intersect(missingMEG,chanList)) + fprintf('setCTFDataBalance (balance_data): Channel(s) missing from the balance table:\n'); + for k=missingMEG + fprintf('\t%3d: %s\n',k,strtok(ds.res4.chanNames(k,:),'- ')); + end + end + clear MEGlist k; + + % Are there any badGref in the MEGbalanceindex list? + if ~isempty(intersect(MEGbalanceindex,badGref)) + fprintf(['setCTFDataBalance (unbalance_data): A reference gradiometer marked bad ',... + 'because of its grad_order_no\n',... + ' appears in the list of reference sensors required for ',... + '%s MEG balancing.\n'],balance(1,:)); + fprintf(' MEGbalanceindex=');fprintf(' %d',MEGbalanceindex);fprintf('\n'); + fprintf(' badGref=');fprintf(' %d',badGref);fprintf('\n'); + data=[]; % Force an error in the calling program + return + end + + if isequal(chanList,1:max(max(MEGindex),max(MEGbalanceindex))); + chanList=[]; + end + % Check if alphaMEG is all zeros or is improperly defined. + do_balance=~isempty(alphaMEG) & ~isempty(MEGindex) & ~isempty(MEGbalanceindex); + if do_balance + if ~isequal(size(alphaMEG),[length(MEGbalanceindex) length(MEGindex)]); + fprintf(['setCTFDataBalance (balance_data): size(alphaMEG)=[%d %d] ',... + 'length(MEGbalanceindex)=%d length(MEGindex)=%d\n'],... + size(alphaMEG),length(MEGbalanceindex),length(MEGindex)); + data=[]; + return + elseif isempty(chanList) & size(data,2)nargin-1 | nargout==0 + fprintf('reindex: %d outputs, but only %d inputs.\n',nargout,nargin); + return +end + +[X c1 c2]=intersect(chanlist,reflist); +[Y ylist]=sort(c2); +refindex=c1(ylist); + +if length(refindex)~=length(reflist) + fprintf('setCTFDataBalance (reindex): length(refindex)=%d length(reflist)=%d\n',... + length(refindex),length(reflist)); + fprintf(' Some references are not included in chanlist.\n'); + return +end + +if nargin>=3 & nargout>=2 + [X c1 c2]=intersect(chanlist,sensorlist); + [Y ylist]=sort(c2); + sensorindex=c1(ylist); +end + +if nargin>=4 & nargout>=3 + alfa2=alfa(:,Y); +end +return + +% *********************************************************************************** diff --git a/external/ctf/setCTFDataBalance.p b/external/ctf/setCTFDataBalance.p deleted file mode 100644 index c62ce02..0000000 Binary files a/external/ctf/setCTFDataBalance.p and /dev/null differ diff --git a/external/ctf/writeCPersist.m b/external/ctf/writeCPersist.m new file mode 100644 index 0000000..d02926a --- /dev/null +++ b/external/ctf/writeCPersist.m @@ -0,0 +1,131 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%% Function writeCPersist %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function writeCPersist(filename,Tag) + +% Version 1.2 24 April 2007. Removed terminating null characters from charatcer strings +% types 10,11) + +% Version 1.1 13 April 2007 +% Write a CTF CPersist file. See document CTF MEG File Format, PN900-0066 + +% Inputs : filename : Name of the output file name including path +% Tag: Structure array containing all of the tags, types, and data. + +% 31 Aug 2006: Recognizes type=1,...,17. If other data types are specified, +% writeCPersist will print an error message. + +% Delete existing file so the new file has the correct creation data/time. + +if nargin==0 + fprintf(['writeCPersist: Version 1.2 24 April 2007 Writes a CTF CPersist file.\n'... + '\twriteCPersist(filename,Tag) writes a CPersist file from the contents of\n',... + '\tstructure array Tag. Tag is in the format prepared by readCPersist.\n\n']); + Tag=[]; + return +end + +if exist(filename)==2 + delete(filename); +end + +startString='WS1_'; +EOFstring='EndOfParameters'; + +startVal=256.^[3:-1:0]*double(startString)'; % Integer version of startString + +fid=fopen(filename,'w','ieee-be'); + +EOFcount=0; % Make sure that the startString's and EOFstring's balance +count=0; +while count31; + MRItags(k).data=[MRItags(k).data(1:31) char(0)]; + end +end + +return +%%%%%%%%%%%%%% End of update_MRI_descriptors %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/external/ctf/writeCTFMRI.p b/external/ctf/writeCTFMRI.p deleted file mode 100644 index d37193d..0000000 Binary files a/external/ctf/writeCTFMRI.p and /dev/null differ diff --git a/external/ctf/writeCTFds.m b/external/ctf/writeCTFds.m new file mode 100644 index 0000000..84082f6 --- /dev/null +++ b/external/ctf/writeCTFds.m @@ -0,0 +1,1711 @@ +function ds=writeCTFds(datasetname,ds,data,unit); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% This program creates datasets that can be analyzed by CTF software. % +% % +% Datasets created by this program MUST NOT BE USED FOR CLINICAL APPLICATIONS. % +% % +% Please do not redistribute it without permission from VSM MedTech Ltd. % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Author : Harold Wilson + +% Version 1.3 5 October 2007 Spelling errors in some variables corrected. +% Version 1.2 24 April 2007 Modified to write both MEG and fMEG .hc files. + +% writeCTFds.m Version 1.1 Prepares a CTF-format data set. MATLAB to CTF conversion. +% Adds record of filter changes to hist and newds files. +% Adds no-clinical-use messages. +% Creates multiple meg4 files when the total size of the data array +% >536870910 elements. + +% Operation : +% 1. User reads a data set using readCTFds and getTrial2. +% size(data)= [SAMPLES, CHANNELS, TRIALS]. +% 2. After working on data in MATLAB, user adjusts ds structure to reflect changes. +% (writeCTFds will adjust the number of channels, channel names and trial structure.) +% 3. This program then creates a new CTF data set. +% datasetname must include the complete path description. +% If a data set with name datasetname already exists, writeCTFds will issue an error message. +% The new directory contains files for each field of structure ds. If the field is +% missing no file is created. If the field is empty, an empty file is created. +% Files default.* are not created by writeCTFds. + +% 4. The following fields of structure ds.res4 are modified based on the size of array data : +% no_samples +% no_channels +% no_trials. +% If size(ds.res4.chanNames,1)nChan + fprintf(['\nlength(chanNames)=%d, but only %d channels of data. ',... + 'writeCTFds cannot tell which channel names to remove.\n\n'],no_chanNames,nChan); + ds=-1; + return +end +clear no_chanNames len_chanNames; + +% The senres table may have been changed, especially if channels are added or removed. +% Check structure senres, print error messages, and possibly fix the errors. +[ds.res4.senres,status]=check_senres(ds.res4.senres,ds.res4.no_channels); +if status<0;ds=-1;return;end +clear status; + +% Check that ds.res4.numcoef is the size of structure array ds.res4.scrr. +if isfield(ds.res4,'scrr') + if ~isequal(size(ds.res4.scrr,2),ds.res4.numcoef) + fprintf('Error in ds.res4: ds.res4.numcoef=%d, but size(ds.res4.scrr)=[',... + ds.res4.numcoef); + fprintf(' %d',size(ds.res4.scrr));fprintf('] ?\n'); + return + end +elseif ds.res4.numcoef~=0 + fprintf(['Error in ds.res4: ds.res4.numcoef=%d,',... + ' but scrr is not a field of ds.res4\n'],ds.res4.numcoef); + return +end + +% Before converting data to integers, save HLC channels for motion analysis in function +% make_new_infods. Pass HLCdata to function make_new_infods +if isempty(strmatch('HLC',ds.res4.chanNames)) + HLCdata=[]; +else + % Make a list of head-coil channels + coil=0; + HLClist=[]; + while ~isempty(strmatch(['HLC00',int2str(coil+1)],ds.res4.chanNames)) + coil=coil+1; + for k=1:3 + HLClist=[HLClist strmatch(['HLC00',int2str(coil),int2str(k)],ds.res4.chanNames)]; + end + end + HLCdata=reshape(double(data(:,HLClist,:)),ds.res4.no_samples,3,coil,ds.res4.no_trials); + clear coil k HLClist; +end + +% Convert data to integers because CTF data sets are stored as raw numbers and +% not as physical qunatities. The res4 file contains the calibrations for +% converting back to physical units. Array data may be single precision, so +% convert to double before doing any adjustments to the data. +% Already checked that unit is valid. + +if strcmp(unit,'int') + data=reshape(data,nSample,nChan*trials); + for k=1:nChan*trials + if strcmp(class(data),'single') + data(:,k)=single(round(double(data(:,k)))); + else + data(:,k)=round(double(data(:,k))); + end + end + data=reshape(data,nSample,nChan,trials); + clear k; +else + for chan=1:nChan % Convert EEGs from uV to V, SQUIDs from fT to T + SQUIDtype=any(ds.res4.senres(chan).sensorTypeIndex==[0:7]); + EEGtype=any(ds.res4.senres(chan).sensorTypeIndex==[8 9]); + if EEGtype & (strcmp(unit,'ft') | strtcmp(unit,'phi0')) + alphaG=1e-6; + elseif SQUIDtype & strcmp(unit,'ft') + alphaG=1e-15; + elseif SQUIDtype & strcmp(unit,'phi0') + alphaG=1./(ds.res4.senres(chan).properGain*ds.res4.senres(chan).ioGain); + else + alphaG=1; + end + % Convert from physical units to integers using the gains in the senres table. + for kt=1:trials + buff=round(double(data(:,chan,kt))*(alphaG*... + (ds.res4.senres(chan).properGain*ds.res4.senres(chan).qGain*ds.res4.senres(chan).ioGain))); + if strcmp(class(data),'single') + data(:,chan,kt)=single(buff); + else + data(:,chan,kt)=buff; + end + end + end + clear chan alphaG SQUIDtype EEGtype buff kt; +end + +% Create the output dataset +[status,msg]=mkdir(path,[baseName '.ds']); +if status==0 | ~isempty(msg) + fprintf('\nwriteCTFds: Failed to create directory.\n'); + fprintf(' [status,msg]=mkdir(%s)\n',datasetname); + fprintf(' returns status=%d, msg=%s',status,msg);fprintf('\n\n'); + ds=-1; + return +end +clear msg status; + + +% Write the data file (meg4 file). Check ds.meg4.header and make sure that +% the output .meg4 file has an acceptable header. +headerMessage=1; +if ~isfield(ds.meg4,'header'); % If ds.meg4.header is missing, add it. + nChar=length(deblank(meg4_headers(1,:))); + ds.meg4.header=[meg4_headers(1,1:min(7,nChar)) char(zeros(1,7-nChar))]; +elseif isempty(strmatch(ds.meg4.header(1:7),meg4_headers(:,1:7),'exact')) + ds.meg4.header=meg4_headers(1,1:7); +else + headerMessage=0; +end +if headerMessage; + fprintf('writeCTFds: Set ds.meg4.header=%s\n',ds.meg4.header); +end +clear headerMessage; + +if isempty(printWarning) + fprintf(['\nwriteCTFds: The data you are writing have been processed by software not\n',... + '\tmanufactured by VSM MedTech Ltd. and that has not received marketing clearance\n',... + '\tfor clinical applications. These data should not be later employed for clinical\n',... + '\tand/or diagnostic purposes.\n\n']); + printWarning=1; +end + +% Write the meg4 file(s). If there are more than maxMEG4Size-8 bytes, then additional meg4 +% files will be created. +% Convert data to a 1-D array +ndata=prod(size(data)); +data=reshape(data,ndata,1); +ptsPerTrial=nSample*nChan; +maxPtsPerFile=ptsPerTrial*floor((maxMEG4Size-8)/(4*ptsPerTrial)); +pt=0; % Last point written to the output file(s). +while ptnumChan + % Channels have been removed from the data set, but can't tell which elements of the + % senres table to remove. + fprintf(['length(senres)=%d, but only %d channels of data. writeCTFds can''t',... + ' tell which channels to remove from senres table.\n'],no_senres,numChan); + return +end +no_senres=length(senres); + +% Previous version of check_senres ensures that several fields had size [1 1]. +% Seems unnecessary, so removed it. + +for k=1:no_senres + % Check the fields that define pickup loops. Force the field defining the pickup + % loops to have the correct size. It is not clear why the EEG channels and + % the type=13,28,29 HLC channels need numCoils=1, and area>0. + if any(senres(k).sensorTypeIndex==[0:7]) % SQUID channels + correct_numCoils=rem(senres(k).sensorTypeIndex,4)+1; + elseif any(senres(k).sensorTypeIndex==[13 28 29]) % HLC channels + correct_numCoils=1; + elseif any(senres(k).sensorTypeIndex==[8 9]) % EEG channels + correct_numCoils=1; + else + correct_numCoils=0; + end + if senres(k).numCoils~=correct_numCoils & any(senres(k).sensorTypeIndex==[0:7]) + fprintf('writeCTFds_test: senres(%d).sensorTypeIndex=%d but numCoils=%d??\n',... + k,senres(k).sensorTypeIndex,senres(k).numCoils); + fprintf(' Set numCoils=%d\n',correct_numCoils); + senres(k).numCoils=correct_numCoils; + end + numCoils=senres(k).numCoils; + if size(senres(k).pos0)~=[3 numCoils];pos0=zeros(3,numCoils);end + if size(senres(k).ori0)~=[3 numCoils];ori0=zeros(3,numCoils);end + if size(senres(k).pos)~=[3 numCoils];pos=zeros(3,numCoils);end + if size(senres(k).ori)~=[3 numCoils];ori=zeros(3,numCoils);end + if size(senres(k).numturns)~=[1 numCoils];numturns=zeros(1,numCoils);end + if size(senres(k).area)~=[1 numCoils];area=zeros(3,numCoils);end +end +status=1; +return +% ************* End of function check_senres********************************************* +% ************************************************************************************** + + +% ************************************************************************************** +% ************* function make_dummy_infods********************************************* +function Tag=make_dummy_infods(exist_hc,exist_HLC,sample_rate); + +% If the user does not supply ds.infos, this code makes a dummy version. It has all of +% the tags that Acq created in file Richard_SEF_20060606_04.infods. +% *********************************************************************************** +% *********************************************************************************** +DATASET_HZ_UNKNOWN=round(2^31-1); % Peculiar requirement of DataEditor as of 23 Oct. 2006 + +fprintf('writeCTDds (make_dummy_infods): Creating a dummy infods file with all the tags.\n'); +Tag(1)=struct('name','WS1_','type',0,'data',[]); +Tag(length(Tag)+1)=struct('name','_PATIENT_INFO','type',2,'data',[]); +Tag(length(Tag)+1)=struct('name','WS1_','type',0,'data',[]); +Tag(length(Tag)+1)=struct('name','_PATIENT_UID','type',10,... + 'data','2.16.124.113000.000000.00000000000000.000000000.00000000.0011'); +Tag(length(Tag)+1)=struct('name','_PATIENT_NAME_FIRST','type',10,'data',''); +Tag(length(Tag)+1)=struct('name','_PATIENT_NAME_MIDDLE','type',10,'data',''); +Tag(length(Tag)+1)=struct('name','_PATIENT_NAME_LAST','type',10,'data',''); +Tag(length(Tag)+1)=struct('name','_PATIENT_ID','type',10,'data','x'); +Tag(length(Tag)+1)=struct('name','_PATIENT_BIRTHDATE','type',10,'data','19500101000000'); +Tag(length(Tag)+1)=struct('name','_PATIENT_SEX','type',5,'data',2); +Tag(length(Tag)+1)=struct('name','_PATIENT_PACS_NAME','type',10,'data',''); +Tag(length(Tag)+1)=struct('name','_PATIENT_PACS_UID','type',10,'data',''); +Tag(length(Tag)+1)=struct('name','_PATIENT_INSTITUTE','type',10,'data',''); +Tag(length(Tag)+1)=struct('name','EndOfParameters','type',-1,'data',[]); +Tag(length(Tag)+1)=struct('name','_PROCEDURE_INFO','type',2,'data',[]); +Tag(length(Tag)+1)=struct('name','WS1_','type',0,'data',[]); +Tag(length(Tag)+1)=struct('name','_PROCEDURE_VERSION','type',5,'data',1); +Tag(length(Tag)+1)=struct('name','_PROCEDURE_UID','type',10,... + 'data','2.16.124.113000.000000.00000000000000.000000000.00000000.0041'); +Tag(length(Tag)+1)=struct('name','_PROCEDURE_ACCESSIONNUMBER','type',10,'data','0'); +Tag(length(Tag)+1)=struct('name','_PROCEDURE_TITLE','type',10,'data','0'); +Tag(length(Tag)+1)=struct('name','_PROCEDURE_SITE','type',10,'data',''); +Tag(length(Tag)+1)=struct('name','_PROCEDURE_STATUS','type',5,'data',1); +Tag(length(Tag)+1)=struct('name','_PROCEDURE_TYPE','type',5,'data',2); % Research type +Tag(length(Tag)+1)=struct('name','_PROCEDURE_STARTEDDATETIME','type',10,... + 'data','20060606164306'); +Tag(length(Tag)+1)=struct('name','_PROCEDURE_CLOSEDDATETIME','type',10,... + 'data','19000100000000'); +Tag(length(Tag)+1)=struct('name','_PROCEDURE_COMMENTS','type',10,'data',''); +Tag(length(Tag)+1)=struct('name','_PROCEDURE_LOCATION','type',10,'data',''); +Tag(length(Tag)+1)=struct('name','_PROCEDURE_ISINDB','type',5,'data',0); +Tag(length(Tag)+1)=struct('name','EndOfParameters','type',-1,'data',[]); +Tag(length(Tag)+1)=struct('name','_DATASET_INFO','type',2,'data',[]); +Tag(length(Tag)+1)=struct('name','WS1_','type',0,'data',[]); +Tag(length(Tag)+1)=struct('name','_DATASET_VERSION','type',5,'data',2); +Tag(length(Tag)+1)=struct('name','_DATASET_UID','type',10,... + 'data','2.16.124.113000.000000.00000000000000.000000000.00000000.0042'); +Tag(length(Tag)+1)=struct('name','_DATASET_PATIENTUID','type',10,... + 'data','2.16.124.113000.000000.00000000000000.000000000.00000000.0011'); +Tag(length(Tag)+1)=struct('name','_DATASET_PROCEDUREUID','type',10,... + 'data','2.16.124.113000.000000.00000000000000.000000000.00000000.0041'); +Tag(length(Tag)+1)=struct('name','_DATASET_STATUS','type',10,'data',''); +Tag(length(Tag)+1)=struct('name','_DATASET_RPFILE','type',10,'data','default.rp'); +Tag(length(Tag)+1)=struct('name','_DATASET_PROCSTEPTITLE','type',10,'data',''); +Tag(length(Tag)+1)=struct('name','_DATASET_PROCSTEPPROTOCOL','type',10,'data',''); +Tag(length(Tag)+1)=struct('name','_DATASET_PROCSTEPDESCRIPTION','type',10,... + 'data',''); +Tag(length(Tag)+1)=struct('name','_DATASET_COLLECTIONDATETIME','type',10,... + 'data','Unknown'); +Tag(length(Tag)+1)=struct('name','_DATASET_COLLECTIONSOFTWARE','type',10,... + 'data','Acq '); +Tag(length(Tag)+1)=struct('name','_DATASET_CREATORDATETIME','type',10,... + 'data',sprintf('%d',floor(clock))); +Tag(length(Tag)+1)=struct('name','_DATASET_CREATORSOFTWARE','type',10,... + 'data','Acq '); +Tag(length(Tag)+1)=struct('name','_DATASET_KEYWORDS','type',10,'data',''); +Tag(length(Tag)+1)=struct('name','_DATASET_COMMENTS','type',10,... + 'data','Dummy infods.'); +Tag(length(Tag)+1)=struct('name','_DATASET_OPERATORNAME','type',10,'data',''); +Tag(length(Tag)+1)=struct('name','_DATASET_LASTMODIFIEDDATETIME','type',10,... + 'data',sprintf('%d',floor(clock))); +if exist_hc + nominalPositions=0; % Measured +else + nominalPositions=1; % Nominal +end +Tag(length(Tag)+1)=struct('name','_DATASET_NOMINALHCPOSITIONS','type',5,... + 'data',nominalPositions); +Tag(length(Tag)+1)=struct('name','_DATASET_COEFSFILENAME','type',10,... + 'data','ds.res4.scrr'); +Tag(length(Tag)+1)=struct('name','_DATASET_SENSORSFILENAME','type',10,... + 'data','ds.res4.senres'); +%Tag(length(Tag)+1)=struct('name','_DATASET_COEFSFILENAME','type',10,... +% 'data','/opt/ctf-5.1/hardware/M015/M015_1609.coef'); +%Tag(length(Tag)+1)=struct('name','_DATASET_SENSORSFILENAME','type',10,... +% 'data','/opt/ctf-5.1/hardware/M015/M015_1609.sens'); +Tag(length(Tag)+1)=struct('name','_DATASET_SYSTEM','type',10,'data','DSQ-2010'); +Tag(length(Tag)+1)=struct('name','_DATASET_SYSTEMTYPE','type',10,'data','Untitled'); +Tag(length(Tag)+1)=struct('name','_DATASET_LOWERBANDWIDTH','type',4,'data',0); +Tag(length(Tag)+1)=struct('name','_DATASET_UPPERBANDWIDTH','type',4,'data',... + round(0.25*sample_rate)); +Tag(length(Tag)+1)=struct('name','_DATASET_ISINDB','type',5,'data',0); + +if exist_HLC + HZ_MODE=5; +elseif exist_hc + HZ_MODE=1; +else + HZ_MODE=DATASET_HZ_UNKNOWN; +end +Tag(length(Tag)+1)=struct('name','_DATASET_HZ_MODE','type',5,'data',HZ_MODE); +Tag(length(Tag)+1)=struct('name','_DATASET_MOTIONTOLERANCE','type',4,'data',0.005); +Tag(length(Tag)+1)=struct('name','_DATASET_MAXHEADMOTION','type',4,'data',0.005); +Tag(length(Tag)+1)=struct('name','_DATASET_MAXHEADMOTIONTRIAL','type',7,'data',0); +Tag(length(Tag)+1)=struct('name','_DATASET_MAXHEADMOTIONCOIL','type',10,'data','1'); +Tag(length(Tag)+1)=struct('name','EndOfParameters','type',-1,'data',[]); +Tag(length(Tag)+1)=struct('name','EndOfParameters','type',-1,'data',[]); +return +% ************* End of function make_dummy_infods********************************************* +% ************************************************************************************** + + +% ************************************************************************************** +% ************* Function writeHc********************************************* +function hc=writeHc(hcFileName,hc,HLCdata); + +% Modified for v1.2 ds.hc structures. ds.hc.names has the exact, complete names of the +% head coils. The coordinates relative to the subject may be ds.hc.head(MEG) OR +% ds.hc.abdomen (fMEG). + +% Creates a .hc file in a CTF dataset +% Inputs: hcFileName : Complete name of .hc file including path, basename and .hc ext. +% hc : structure with nasion, left, right head coil positions in dewar and +% CTF head coordinates. +% HLCdata : head coil locations at the start of 1st trial. unit=m +% coordinates=dewar. Used only if structure hc is empty and it is MEG +% data (not fMEG data). + +% Output : hc : hc structure. hc=struct([]) on failure. hc is set to the coil positions +% in array HLCdata if hc=[] on entry. + +% Check inputs +if exist('hc')~=1 + hc=struct([]); +elseif ~isstruct(hc) + hc=struct([]); +end +hcfields=fieldnames(hc); + +if exist('HLCdata')~=1 + HLCdata=[]; +elseif ~isnumeric(HLCdata) | size(HLCdata,1)~=3 | size(HLCdata,2)<3 + HLCdata=[]; +end + +% Check hc Filename +if exist('hcFileName')~=1;hcFileName=char([]);end +if ~ischar(hcFileName) | isempty(hcFileName) + fprintf('writeCTFds (writeHc): Called writeHc with bad file name.\n'); + hcFileName + return +end + +% Both hc and HLCdata bad? +if length(hcfields)~=4 & isempty(HLCdata) + fprintf('writeCTFds (writeHc): Called writeHc with bad hc and bad HLCdata.\n'); + hc=struct([]) + return +elseif length(hcfields)~=4 + rstandard=8/sqrt(2)*[1 1 0;-1 1 0;1 -1 0]'; + rstandard(3,:)=-27; + rdewar=100*HLCdata(:,1:3); + + % Convert from dewar coordinates to CTF head coordinates. + originCTF=0.5*(hc.dewar(:,2)+hc.dewar(:,3)); + % Unit vectors for the CTF coordinates + uCTF(:,1)=hc.dewar(:,1)-originCTF; + uCTF(:,3)=cross(uxCTF,hc.dewar(:,2)-hc.dewar(:,3)); + uCTF(:,2)=cross(uCTF(:,3),uCTF(:,1)); + uCTF=uCTF./(ones(3,1)*sqrt(sum(uCTF.^2,1))); + rCTF=uCTF'*(rdewar-originCTF*ones(1,3)) + hc=struct('names',strvcat('nasion','left ear','right ear'),... + 'standard',rstandard,'dewar',rdewar,'head',rCTF); + clear originCTF uCTF rstandard rdewar rCTF; +end + +% Character strings for generating the .hc text file +% Should never have both 'head' and 'abdomen' fields. +labelword=strvcat('standard','measured','measured'); +printField=[strmatch('standard',hcfields) strmatch('dewar',hcfields) ... + strmatch('head',hcfields) strmatch('abdomen',hcfields)]; + +if ~strmatch('names',hcfields) | length(printField)~=3 + fprintf(['writeCTFds (writeHc): Structure hc does not have all of the required fields.\n',... + ' No .hc file will appear in the output dataset.\n']); + hc; + hc=struct([]); + return +end + +relative=strvcat('dewar','dewar',hcfields{printField(3)}); +coilcoord=strvcat('standard','dewar',hcfields{printField(3)}); + +comp='xyz'; +coilname=hc.names; + +fid=fopen(hcFileName,'w','ieee-be'); + +for k=1:size(coilcoord,1) + rcoil=getfield(hc,coilcoord(k,:)); + for coil=1:size(hc.names,1) + clName=deblank(hc.names(coil,:)); + fwrite(fid,[labelword(k,:) ' ' clName ' coil position relative to ',... + deblank(relative(k,:)) ' (cm):' char(10)],'uint8'); + for m=1:3 + fwrite(fid,[char(9) comp(m) ' = ' num2str(rcoil(m,coil),'%7.5f') char(10)],'uint8'); + end + end +end +fclose(fid); +status=0; +return +% ************* End of function writeHc********************************************* +% ************************************************************************************** + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%Function checkMrk %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function MarkerFileOK=checkMrk(ds); + +% Examines structure ds to see if a sensible MarkerFile can be created from ds.mrk. +% Output: MarkerFileOK=1 : ds.mrk looks OK +% MarkerFileOK=0 : ds.mrk cannot be a set of valid markers for these data. + +MarkerFileOK=isfield(ds,'mrk'); +if MarkerFileOK + MarkerFileOK=~isempty(ds.mrk); +end +if MarkerFileOK + % Are the markers appropriate? + minMarkerTrial=[]; + minMarkerTime=[]; + maxMarkerTrial=[]; + maxMarkerTime=[]; + for k=1:length(ds.mrk) + maxMarkerTrial=max([maxMarkerTrial max(ds.mrk(k).trial)]); + maxMarkerTime=max([maxMarkerTime max(ds.mrk(k).time)]); + minMarkerTrial=min([minMarkerTrial min(ds.mrk(k).trial)]); + minMarkerTime=min([minMarkerTime min(ds.mrk(k).time)]); + end + if isempty(maxMarkerTrial) | isempty(maxMarkerTime) + MarkerFileOK=0; % Do not create MarkerFile.mrk if all of the marker classes are empty. + else + MarkerFileOK=(maxMarkerTrial<=ds.res4.no_trials & minMarkerTrial>=1 & ... + maxMarkerTime<=(ds.res4.no_samples/ds.res4.sample_rate) & ... + minMarkerTime>=(-ds.res4.preTrigPts/ds.res4.sample_rate)); + if ~MarkerFileOK + fprintf(['\nwriteCTFds (checkMrk): ds.mrk cannot possibly be a set of markers ',... + 'for array(data).\n']); + fprintf([' minMarkerTrial=%d (must be >=1) ',... + 'maxMarkerTrial=%d (must be <=%d)\n'],... + minMarkerTrial,maxMarkerTrial,ds.res4.no_trials); + fprintf([' minMarkerTime=%7.4f (must be >=%7.4f) ',... + 'maxMarkerTrial=%7.4f (must be <=%7.4f )\n'],... + minMarkerTime,-ds.res4.preTrigPts/ds.res4.sample_rate,... + maxMarkerTime,ds.res4.no_samples/ds.res4.sample_rate); + fprintf(' MarkerFile.mrk will not be created.\n\n'); + end + end +end +return +%%%%%%%%%%%%%% end of checkMrk %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%% Function writeEEG %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function writeEEG(eegFileName,EEG); + +% Reads the EEG file of a dtaset and stores the infoemation in strucure array EEG. +% EEG(k).chanName = channel name in the dataset (EEGmmm where mmm=channel number) +% EEG(k).name = channel name given by the user (e.g. Fp4) +% EEG(k).pos = electrode position in cm in CTF head coordinates +% Check inputs + +if exist('eegFileName')~=1;eegFileName=char([]);end +if ~ischar(eegFileName) | isempty(eegFileName) + fprintf('writeCTFds (writeEEG): Called writeEEG with bad file name.\n'); + eegFileName + EEG=struct([]); +end + +if exist('EEG')~=1 + EEG=struct([]); +elseif ~isstruct(EEG) + EEG=struct([]); +end + +if isempty(EEG);return;end + +fid=fopen(eegFileName,'w','ieee-be'); +if fid<0 + fprintf('writeCTFds (writeEEG): Could not open file %s\n',eegFileName); + return +end +nEEG=length(EEG); +for k=1:nEEG + fprintf(fid,'%d\t%s\t%7.5f\t%7.5f\t%7.5f\n',EEG(k).chanNum,EEG(k).name,EEG(k).pos); +end +fclose(fid); +return +%%%%%%%%% End of writeEEG %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%% Function writeBadSegments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function writeBadSegments(badSegmentsFile,badSegments,nTrial,tTrial); + +% Creates a bad.segements file in a CTF data set from the information in structure +% badSegments which is created by read_badSegments, or by the user. +% If structure badSegments is empty, then the file is not created. + +% badSegments structure: +% badSegments.trial = List of trial numbers +% badSegments.StartTime = List of bad segment start times (relative to trial). +% badSegments.EndTime = List of bad segment end times. + +% Check badSegmentsFile +if exist('badSegmentsFile')~=1;badSegmentsFile=char([]);end +if isempty(badSegmentsFile) | ~ischar(badSegmentsFile) + fprintf('writeCTFds(writeBadSegments): Bad file name.\n'); + badSegmentsFile + return +end + +% Check that structure badSegments is defined correctly +if exist('badSegments')~=1 | exist('nTrial')~=1 + return +elseif ~isstruct(badSegments) | isempty(badSegments) + return +elseif ~isfield(badSegments,'trial') | ~isfield(badSegments,'StartTime') | ... + ~isfield(badSegments,'EndTime') + return +elseif isempty(badSegments.trial) | isempty(badSegments.StartTime) | ... + isempty(badSegments.EndTime) + return +elseif ~isequal(size(badSegments.trial),size(badSegments.StartTime),... + size(badSegments.EndTime)) + fprintf(['\nwriteCTFds (writeBadSegments): ',... + 'The fields of structure badSegments do not all have the same size.\n']); + return +elseif any(badSegments.trial>nTrial) | any(badSegments.trial<1) | ... + any(badSegments.EndTime>tTrial) + fprintf(['\nwriteCTFds (writeBadSegments): ds.badSegments cannot possibly describe ',... + 'bad segments for these data.\n',... + '\tmin(badSegments.trial)=%d max(badSegments.trial)=%d ',... + 'max(badSegments.EndTime)=%0.4f s\n\t\tDataset: nTrial=%d tTrial=%0.4f s\n'],... + min(badSegments.trial),max(badSegments.trial),max(badSegments.EndTime),... + nTrial,tTrial); + fprintf('\t\tbad.segments file will not be created.\n\n'); + return +end + +% Convert all fields to simple vectors +nSeg=prod(size(badSegments.trial)); +trial=reshape(badSegments.trial,1,nSeg); +StartTime=reshape(badSegments.StartTime,1,nSeg); +EndTime=reshape(badSegments.EndTime,1,nSeg); + +fid=fopen(badSegmentsFile,'w','ieee-be'); +if fid<0 + fprintf('writeCTFds (writeBadSegments): Could not open file %s\n',badSegmentsFile); + return +end +% Extra tabs are inserted to reproduce the format of bad.segments files produced by +% DataEditor (5.3.0-experimental-linux-20060918). +fprintf(fid,'%0.6g\t\t%0.6g\t\t%0.6g\t\t\n',[trial;StartTime;EndTime]); +fclose(fid); +return +%%%%%%%%% End of writeBadSegments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%Function check_cls %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function ClassFileOK=check_cls(ds); + +% Examines structure ds to see if a sensible ClassFile can be created from ds.TrialClass. + +ClassFileOK=isfield(ds,'TrialClass'); +if ClassFileOK + ClassFileOK=~isempty(ds.TrialClass); +end +if ClassFileOK + % Are the class trials appropriate? + minClassTrial=[]; + maxClassTrial=[]; + for k=1:length(ds.TrialClass) + maxClassTrial=max([maxClassTrial max(ds.TrialClass(k).trial)]); + minClassTrial=min([minClassTrial min(ds.TrialClass(k).trial)]); + end + % Create ClassFile.cls even when the trail classes are empty. + if ~isempty(maxClassTrial) + ClassFileOK=(maxClassTrial<=ds.res4.no_trials & minClassTrial>=1); + if ~ClassFileOK + fprintf(['\nwriteCTFds (check_cls): ds.TrialClass cannot possibly be a set of ',... + 'trial classes for array(data).\n minClassTrial=%d (must be >=1) ',... + 'maxClassTrial=%d (must be <=%d)\n'],... + minClassTrial,maxClassTrial,ds.res4.no_trials); + fprintf(' ClassFile.cls will not be created.\n'); + end + end +end +return +%%%%%%%%%%%%%% end of check_cls %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%% Function writeClassFile %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function writeClassFile(ClassFile,TrialClass); + +% Write the ClassFile of a CTF data set. +% The CLassFile allows a user to store a list of trial classifications in a data set. +% The ClassFile format is defined in document CTF MEG File Formats, PN900-0088. +% This format is rigid. + +% Inputs : +% ClassFile : marker file including the full path and extension .mrk. +% TrialClass : Structure creted by read_ClassFile. + +% Output : ClassFile.cls. + +% Check input TrialClass. +if exist('TrialClass')~=1;TrialClass=[];end +if isempty(TrialClass) | ~isstruct(TrialClass) + fprintf('writeCTFds (writeClassFile): TrialClass is empty or is not a structure.\n'); + TrialClass + return +end + +% Check ClassFile +if exist('ClassFile')~=1;ClassFile=char([]);end +if isempty(ClassFile) | ~ischar(ClassFile) + fprintf('writeCTFds (writeClassFile): Bad file name.\n'); + ClassFile +end + +fid=fopen(ClassFile,'w','ieee-be'); +if fid<0 + fprintf('writeCTFds (writeClassFile): Could not open file %s\n',ClassFile); + return +end + +nClass=length(TrialClass); + +% Generate datasetname from ClassFIle. +ksep=max([0 strfind(ClassFile,filesep)]); +datasetname=ClassFile(1:ksep-1); +if isempty(datasetname);datasetname=cd;end + +fprintf(fid,'PATH OF DATASET:\n%s\n\n\n',datasetname); +fprintf(fid,'NUMBER OF CLASSES:\n%d\n\n\n',nClass); + +for k=1:nClass + if k==1 % Add sign character to make output match the output of Acq. + sgn=char([]); % There should be no real significance to this. + else % Why does DataEditor places the + sign only on ClassID 2,3,...? + sgn='+'; + end + No_of_Trials=prod(size(TrialClass(k).trial)); + fprintf(fid,'CLASSGROUPID:\n%s%d\nNAME:\n%s\nCOMMENT:\n%s\n',... + sgn,TrialClass(k).ClassGroupId,TrialClass(k).Name,TrialClass(k).Comment); + fprintf(fid,'COLOR:\n%s\nEDITABLE:\n%s\nCLASSID:\n%s%d\nNUMBER OF TRIALS:\n%d\n',... + TrialClass(k).Color,TrialClass(k).Editable,sgn,TrialClass(k).ClassId,No_of_Trials); + fprintf(fid,'LIST OF TRIALS:\nTRIAL NUMBER\n'); + % Subtract one so trial numbering starts at 0 in ClassFile.cls + fprintf(fid,'%20d\n',reshape(TrialClass(k).trial,1,No_of_Trials)-1); + fprintf(fid,'\n\n'); +end +fclose(fid); +return +%%%%%%%%%%%%%% end of writeClassFile %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%% Function writeVirtualChannels %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function writeVirtualChannels(VirtualChannelsFile,Virtual); + +% Writes a VirtualChannels file using the information in structure Virtual. +% S\tructure Virtual is prepared by read_VirtualChannels + +% Check VirtualChannelsFile +if exist('VirtualChannelsFile')~=1;VirtualChannelsFile=char([]);end +if isempty(VirtualChannelsFile) | ~ischar(VirtualChannelsFile) + fprintf('write_VirtualChannelsFile: Bad file name.\n'); + VirtualChannelsFile + return +end + +% Check structure array Virtual +if exist('Virtual')~=1 + fprintf('writeVirtualChannels: Must specify structure Virtual.\n'); + return +elseif isempty(Virtual) | ~isstruct(Virtual) + return +elseif ~isfield(Virtual,'Name') | ~isfield(Virtual,'wt'); + return +elseif isempty(Virtual(1).Name) + return +end + +fid=fopen(VirtualChannelsFile,'w','ieee-be'); +if fid<0 + fprintf('writeCTFds (writeVirtualChannels): Could not open file %s\n',VirtualChannelsFile); + return +end +fprintf(fid,'//Virtual channel configuration\n\n'); +for k=1:length(Virtual) + fprintf(fid,'VirtualChannel\n{\n\tName:\t%s\n\tUnit:\t%s\n',... + Virtual(k).Name,Virtual(k).Unit); + for q=1:size(Virtual(k).wt) + % Floating format chosen to match VirtualChanels file creatd by + % DataEditor (5.3.0-experimental-linux-20060918). + fprintf(fid,'\tRef:\t%s,%0.6g\n',deblank(Virtual(k).chan(q,:)),Virtual(k).wt(q)); + end + fprintf(fid,'}\n\n'); +end +fclose(fid); +return +%%%%%%%%%%%%%% end of writeVirtualChannels %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%% Function updateDescriptors %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function ds=updateDescriptors(ds,comment,creatorSoftware,HLCcntrl); + +% Makes sure that certain tags are in structure infods, and makes sure that information +% is transfered to infods and newds from res4. Updates several fields of res4 with +% clinical use message (=comment) and name of creator program. + +% Inputs: ds : ds structure produced by readCTFds. +% comment : Character string that is added to infods tags listed in addCommentTag +% and res4 fields listed in addCommentField +% creatorSoftware : Character string indicating that the data set was +% created by writeCTFds. Added to infods tags listed in addCreatorTag and +% appName field of res4. +% HLCcntrl: If ds.infods is missing or empty, HLCcntrl determines the +% _DATA_HZ_MODE tage of infods. if noit present or empty, HLCcntrl=0. +% Creates a dummy infods structure if necessary using function make_dummy_infods. + +% Changes infods and newds to match information in +% ds.res4.nf_run_title +% ds.res4.collect_descriptor +% ds.res4.nf_subject_id +% ds.res4.nf_operator + +% Adds comment (clinical use message) and creator software name to infods, newds and hist files. + +if ~isfield(ds,'infods');ds.infods=[];end + + +% infods tags that will display the comment. +addCommentTag=strvcat('_PATIENT_ID','_PATIENT_INSTITUTE','_PROCEDURE_COMMENTS',... + '_DATASET_COMMENTS','_DATASET_STATUS','_DATASET_PROCSTEPTITLE'); +% res4 text fields that will display the comment +addCommentField=strvcat('appName','dataOrigin','dataDescription',... + 'nf_run_title','nf_subject_id','run_description'); +% res4 text string lengths (from document "CTF MEG File Formats", PN900-0088) +addCommentLength=[256 256 256 256 32 -1]'; % -1 indicates variable length + +% infods tags that will display the creator software. +addCreatorTag=strvcat('_PROCEDURE_COMMENTS','_DATASET_STATUS',... + '_DATASET_COLLECTIONSOFTWARE','_DATASET_CREATORSOFTWARE'); +% res4 text fields that will display the creator software. +addCreatorField=strvcat('appName','run_description'); +addCreatorLength=[256 -1]'; + +% List of infods tags that will be set to ds.res4.fields (not necessarily fields listed in +% addCommentField or addCreatorField +addRes4Tag=strvcat('_PATIENT_ID','_DATASET_PROCSTEPTITLE',... + '_DATASET_PROCSTEPDESCRIPTION','_DATASET_OPERATORNAME'); + +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Add the Tags to infods. In most cases they will already be there, but just to be sure. +addTag=strvcat(addRes4Tag,addCommentTag,addCreatorTag); +tagClass=strvcat('_PATIENT','_PROCEDURE','_DATASET'); +% List of all the tag names as a character array +tagName=getArrayField(ds.infods,'name')'; +if length(ds.infods)==1;tagName=tagName';end +tagType=getArrayField(ds.infods,'type'); +tagPtr=1; % If a class is missing, inject the class starting at tagPtr+1. + +for k=1:size(tagClass,1) + addIndex=strmatch(deblank(tagClass(k,:)),addTag)'; + % Are there any tags to be added in this class? + if isempty(addIndex);continue;end + % List of infods tags in the tagClass, but excluding the CPerist type (which marks the + % start of a class. + infodsIndex=strmatch(deblank(tagClass(k,:)),tagName); + if isempty(infodsIndex) % Create a new class of tags. + if strcmp(deblank(tagName(tagPtr+1,:)),'EndOfParameters') & k>1; + tagPtr=tagPtr+1; + end + nTag=length(ds.infods); + tagName((tagPtr+4):(nTag+3),:)=tagName((tagPtr+1):nTag,:); + ds.infods((tagPtr+4):(nTag+3))=ds.infods((tagPtr+1):nTag); + ds.infods(tagPtr+1)=struct('name',[deblank(tagClass(k,:)),'_INFO'],'type',2,'data',[]); + ds.infods(tagPtr+2)=struct('name','WS1_','type',0,'data',[]); + ds.infods(tagPtr+3)=struct('name','EndOfParameters','type',-1,'data',[]); + tagName=strvcat(tagName(1:tagPtr,:),... + strvcat([deblank(tagClass(k,:)),'_INFO'],'WS1_','EndOfParameters'),... + tagName(tagPtr+1:nTag,:)); + nTag=nTag+3; + tagPtr=tagPtr+2; + else + if ds.infods(max(infodsIndex)).type==2 + tagPtr=max(infodsIndex)+1; % Class consists of no tags beyond the CPersist definition + else + tagPtr=max(infodsIndex); % Class contains at least one real tag. + end + clear infodsIndex; + end + for q=addIndex + if isempty(strmatch(deblank(addTag(q,:)),tagName)) + tagName=strvcat(tagName(1:tagPtr,:),deblank(addTag(q,:)),tagName(tagPtr+1:nTag,:)); + ds.infods((tagPtr+2):(nTag+1))=ds.infods((tagPtr+1):nTag); + ds.infods(tagPtr+1)=struct('name',deblank(addTag(q,:)),'type',10,'data',char([])); + tagPtr=tagPtr+1; + nTag=nTag+1; + end + end +end +clear k q nTag tagPtr infodsIndex addIndex; +% All of the tags in addTag have been added to ds.infods. +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +if exist('creatorSoftware')~=1; + creatorSoftware=char([]); +elseif ~ischar(creatorSoftware) + creatorSoftware=char([]); +else + creatorSoftware=deblank(creatorSoftware); +end + +if exist('comment')~=1; + comment=char([]); +elseif ~ischar(comment) + comment=char([]); +else + comment=deblank(comment); +end + +tagName=getArrayField(ds.infods,'name')'; + +% Update the res4 fields : add creator message. +% Don't check field length, but truncate later. +for q=1:size(addCreatorField,1); + strng=deblank(getfield(ds.res4,deblank(addCreatorField(q,:)))); + if isempty(strfind(strng,creatorSoftware)) + newStrng=creatorSoftware; + if ~isempty(strng);newStrng=[strng ' ' newStrng];end + ds.res4=setfield(ds.res4,deblank(addCreatorField(q,:)),newStrng); + end +end +clear q strng nChar strng0 ns; + +% Update the res4 fields : add comment (= clinical use message) +% Don't check field length, but truncate later. +for q=1:size(addCommentField,1); + strng=deblank(getfield(ds.res4,deblank(addCommentField(q,:)))); + if isempty(strfind(strng,comment)) + newStrng=comment; + if ~isempty(strng);newStrng=[strng ' ' newStrng];end + ds.res4=setfield(ds.res4,deblank(addCommentField(q,:)),newStrng); + end +end +clear strng newStrng q; + +% Update res4.run_description +ds.res4.run_description=[ds.res4.run_description,char(0)]; +ds.res4.rdlen=length(ds.res4.run_description); + +% Update infods entries from .res4 fields +ds.infods(strmatch('_PATIENT_ID',tagName)).data=deblank(ds.res4.nf_subject_id); +ds.infods(strmatch('_DATASET_PROCSTEPTITLE',tagName)).data=deblank(ds.res4.nf_run_title); +ds.infods(strmatch('_DATASET_PROCSTEPDESCRIPTION',tagName)).data=... + deblank(ds.res4.nf_collect_descriptor); +ds.infods(strmatch('_DATASET_OPERATORNAME',tagName)).data=deblank(ds.res4.nf_operator); + +% Truncate the .res4. fields. Leave room for a final char(0). +for q=1:size(addCreatorField,1); + strng=deblank(getfield(ds.res4,deblank(addCreatorField(q,:)))); + if length(strng)>addCreatorLength(q)-1 & addCreatorLength(q)>0 + ds.res4=setfield(ds.res4,deblank(addCreatorField(q,:)),... + strng(length(strng)+[-addCreatorLength(q)+2:0])); + end +end +for q=1:size(addCommentField,1); + strng=deblank(getfield(ds.res4,deblank(addCommentField(q,:)))); + if length(strng)>addCommentLength(q)-1 & addCommentLength(q)>0 + ds.res4=setfield(ds.res4,deblank(addCommentField(q,:)),... + strng(length(strng)+[-addCommentLength(q)+2:0])); + end +end +clear q strng; + +% Add creator software to infods tags. Have already cheked that the tags are there. +for q=1:size(addCreatorTag,1) + if isempty(strmatch(deblank(addCreatorTag(q,:)),addRes4Tag)) + k=strmatch(deblank(addCreatorTag(q,:)),tagName); + if length(k)==1 + if isempty(strfind(ds.infods(k).data,creatorSoftware)) + newStrng=creatorSoftware; + if ~isempty(deblank(ds.infods(k).data)); + newStrng=[deblank(ds.infods(k).data) ' ' newStrng]; + end + ds.infods(k).data=newStrng; + end + else + fprintf('writeCTFds: Tag %s appears %d times in ds.infods ??\n',... + deblank(addCreatorTag(q,:)),length(k)); + end + end +end +clear q k; + +% Add comment (clinical use statement) to ds.infods +for q=1:size(addCommentTag,1) + if isempty(strmatch(deblank(addCommentTag(q,:)),addRes4Tag)) + k=strmatch(deblank(addCommentTag(q,:)),tagName); + if length(k)==1 + if isempty(strfind(ds.infods(k).data,comment)) + newStrng=comment; + if ~isempty(deblank(ds.infods(k).data)); + newStrng=[deblank(ds.infods(k).data) ' ' newStrng]; + end + ds.infods(k).data=newStrng; + end + else + fprintf(['writeCTFds (updateDescriptors): Tag %s appears %d times in ',... + 'ds.infods ??\n'],deblank(addCommentTag(q,:)),length(k)); + end + end +end +clear q k; + +% Add the creator and comment information to the newds file +if isfield(ds,'newds'); + nChar=length(ds.newds); + % Keyword positions + aNpos=max(strfind(ds.newds,[char(9) 'appName:' char(9)])); + if isempty(aNpos) + fprintf(['writeCTFds (update_decsriptors): Keyword ''appName'' ',... + 'does not appear in ds.newds.\n',... + ' set ds.newds=[].\n']); + ds.newds=char([]); + else + eol=max([11 min(strfind(ds.newds(aNpos+1:length(ds.newds)),char(10)))]); + ds.newds=[ds.newds(1:(aNpos+eol-1)) ' ' creatorSoftware ' ' comment ... + ds.newds((aNpos+eol):length(ds.newds))]; + end + clear nChar aNpos eol; +end + +% Add clinical use message to hist file. +if isfield(ds,'hist') & ~isempty(comment) + ds.hist=[ds.hist char(10) comment char(10)]; +end + +return +%%%%%%%%%%%%%% End of updateDescriptors %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%% Function updateHLC %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [infods,status]=updateHLC(infods,HLCdata); +% Adds notes and continuous-head-localization tags to .infods file + +% Inputs : infods : Structure of tags to be written to output infods file. +% HLCdata : 0 or [] or not defined - There are no HLC channels +% (head-coil position) in the data. Just pass the existing tags to +% the output dataset. +% HLCdata : real array : size(HLCdata)=[samplesPerTrial 3 Ncoil nTrial] +% Calculate the head motion tags. + +% Outputs : status : 0: Everything looks OK +% 1: Couldn't find _DATASET tags. +% <0: There is a problem with the new infods file. + +% Calls: +% - getArrayField: Extracts field names from structure array S. + +% Defaults for the head localization tags. +% Might do this better with a structure. + +HZ_MODE_UNKNOWN=2^31-1; % Bug in DataEditor and acquisition software, Oct. 2006 +% Should be -1. + +% New dataset tags for HLC specification. +addTag=strvcat('_DATASET_HZ_MODE',... + '_DATASET_MOTIONTOLERANCE',... + '_DATASET_MAXHEADMOTION',... + '_DATASET_MAXHEADMOTIONTRIAL',... + '_DATASET_MAXHEADMOTIONCOIL'); +addTagType=[5 4 4 7 10]'; + +% Check HLCdata array. HLCdata=[] indicates no continuous head localization. +if ~exist('HLCdata')==1 + HLCdata=[]; +elseif ~isempty(HLCdata) + [samplesPerTrial nDim Ncoil nTrial]=size(HLCdata); + if nDim~=3; + fprintf('writeCTFds (updateHLC): size(HLCdata)=[');fprintf(' %d',size(HLCdata)); + fprintf(']\n'); + fprintf(' nDim=%d?? Setting HLCdata=[].\n',nDim); + HLCdata=[]; + end +end + +% Assume that all the tag names are different. There is no checking when a tag listed in +% addTag matches more than one entry in array name. +name=getArrayField(infods,'name')'; %size(name)=[nTag lengthTag] +DATASET_tags=strmatch('_DATASET',name)'; % size(DATASET_tags)=[1 nTag] +if isempty(DATASET_tags) + status=1; % No _DATASET tags. Don't add anything. +else + status=0; + if isempty(HLCdata) + TagValue(1)=HZ_MODE_UNKNOWN; + TextTagValue=char(0); + addTag=addTag(1,:); % Remove the other HLC tags + addTagType=addTagType(1); + else % ~isempty(HLCdata) + % Remove HLC offsets. + HLCoffset=squeeze(HLCdata(1,:,:,1)); + for q=1:Ncoil + for k=1:3 + HLCdata(:,k,q,:)=HLCdata(:,k,q,:)-HLCoffset(k,q); + end + end + % Calculate motions as displacement from the start of the dataset. + absMotion=squeeze(sqrt(sum(HLCdata.^2,2))); %size(absMotion)=[samplesPerTrial Ncoil nTrial] + maxCoilMotion=squeeze(max(absMotion,[],1)); % size(maxCoilMovement)=[Ncoil nTrial] + maxHeadMotion=max(max(maxCoilMotion)); + [mx maxHeadMotionCoil]=max(max(maxCoilMotion,[],2)); + [mx maxHeadMotionTrial]=max(max(maxCoilMotion,[],1)); + % Create a list of head motion tag values + TagValue(1)=5; % Indicates continuous head localization + TagValue(2)=max(2*maxHeadMotion,0.02); % _DATASET_MOTIONTOLERANCE + TagValue(3)=maxHeadMotion; % _DATASET_MAXHEADMOTION + % Subtract 1 from the trial so trial numbering starts at 0. + TagValue(4)=maxHeadMotionTrial-1; % _DATASET_MAXHEADMOTIONTRIAL + TextTagValue=char(zeros(4,1)); % Placeholder since tags1:4 are numerical + + % _MAXHEADMOTIONCOIL value + TextTagValue=strvcat(TextTagValue,sprintf('%d',maxHeadMotionCoil)); + TagValue=[TagValue 0]; % Placeholder only since the 5th tag is a text string. + end + + % Add or insert tags. + for q=1:size(addTag,1) + nTag=length(infods); + tagName=deblank(addTag(q,:)); + TagNo=strmatch(tagName,name,'exact')'; + if isempty(TagNo) % Insert a tag at the end of the _DATASET tags. + TagNo=max(DATASET_tags)+1; + infods((TagNo+1):(nTag+1))=infods(TagNo:nTag); + name=strvcat(name(1:TagNo-1,:),tagName,name(TagNo:nTag,:)); + DATASET_tags=[DATASET_tags TagNo]; + end + if addTagType(q)~=10 + infods(TagNo)=struct('name',tagName,'type',addTagType(q),'data',TagValue(q)); + else + infods(TagNo)=struct('name',tagName,'type',addTagType(q),... + 'data',deblank(TextTagValue(q,:))); + end + end % End loop over head position and head motion tags. + clear q TagNo TextTagValue TagValue; +end % End section add _DATASET tags + +return +%%%%%%%%%%%%%% End of updateHLC %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%% Function updateBandwidth %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function ds=updateBandwidth(ds,fhp,flp); +% Updates the bandwidth fields of infods and newds. +% 3 possible dources of bandwidth: +% 1. fhp,flp inputs (default) +% 2. newds fiels +% 3. res4.filter +% 4. infods field +% Almost always, fhp,flp will have the default values, but it could be defined in the +% fields of ds, so check. Result: lots of code to achieve a simple result. + +% read fhp,flp from newds (if it exists) +if isfield(ds,'newds') + BWpos=max(strfind(ds.newds,[char(9) 'bandwidth:' char(9)])); % Keyword position + if isempty(BWpos) + fprintf(['writeCTFds (updateBandwidth): Keyword ''bandwidth:''',... + 'does not appear in ds.newds.\n',... + ' Field newds removed from structure ds.\n']); + ds=rmfield(ds,'newds'); + else + % Get the bandwidth parameters from ds.newds. + eol=max([13 min(strfind(ds.newds(BWpos+1:length(ds.newds)),char(10)))]); + buff=sscanf(ds.newds((BWpos+13):(BWpos+eol)),'%f%c%f'); + fhp=max(fhp,buff(1)); + flp=min(flp,buff(3)); + end + clear eol buff BWpos; +end + +% Get fhp, flp from res4. +if ~isempty(ds.res4.filters) + for kq=1:ds.res4.num_filters + freq=ds.res4.filters(kq).freq; + if ds.res4.filters(kq).fType==1; + flp=min(flp,freq); + elseif ds.res4.filters(kq).fType==2; + fhp=max(fhp,freq); + end + end + clear kq freq; +end + +% Get fhp, flp from ds.infods +if isfield(ds,'infods') + name=getArrayField(ds.infods,'name')'; + TagNo=strmatch('_DATASET_LOWERBANDWIDTH',name,'exact'); + if ~isempty(TagNo);fhp=max(fhp,ds.infods(TagNo).data);end + TagNo=strmatch('_DATASET_UPPERBANDWIDTH',name,'exact'); + if ~isempty(TagNo);flp=min(flp,ds.infods(TagNo).data);end +end + +% Now have fhp,flp. Update hist. Add all the res4 filters. +if ~isempty(ds.res4.filters) + if ~isfield(ds,'hist');hist=char([]);end + ds.hist=[ds.hist 'Filters specified in res4 file :' char(10)]; + for kq=1:ds.res4.num_filters + freq=ds.res4.filters(kq).freq; + if ds.res4.filters(kq).fType==1; + ds.hist=[ds.hist ... + num2str(kq,'%8d') ' Lowpass ' num2str(freq,'%6.2f') ' Hz' char(10)]; + elseif ds.res4.filters(kq).fType==2; + ds.hist=[ds.hist ... + num2str(kq,'%8d') ' Highpass ' num2str(freq,'%6.2f') ' Hz' char(10)]; + elseif ds.res4.filters(kq).fType==3; + ds.hist=[ds.hist num2str(kq,'%8d') ' Notch ' num2str(freq,'%6.2f') ... + ' Hz width=' num2str(ds.res4.filters(kq).Param,'%6.2f') ' Hz' char(10)]; + else + ds.hist=[ds.hist ' fType=',num2str(ds.res4.filters(kq).fType,'%d') char(10)]; + end + end + ds.hist=[ds.hist ,... + 'Bandwidth: ',num2str(fhp,'%0.3g'),' - ',num2str(flp,'%0.3g'),' Hz',char(10)]; + clear kq freq; +end + +% Update newds bandwidth +if isfield(ds,'newds') + BWpos=max(strfind(ds.newds,[char(9) 'bandwidth:' char(9)])); + eol=max([12 min(strfind(ds.newds(BWpos+1:length(ds.newds)),char(10)))]); + ds.newds=[ds.newds(1:BWpos+11) num2str(fhp,'%0.6f') ', ' num2str(flp,'%0.6f') ... + ds.newds((BWpos+eol):length(ds.newds))]; + clear BWpos eol; +end + +% Update infods bandwidth tags. Lots of coding becasue it's possible that infods does +% not already have bandwidth tags. +name=getArrayField(ds.infods,'name')'; +DATASET_tags=strmatch('_DATASET_',name); +if ~isempty(DATASET_tags) + addTag=strvcat('_DATASET_LOWERBANDWIDTH','_DATASET_UPPERBANDWIDTH'); + TagValue=[fhp flp]; + % Add or update tags. + for q=1:size(addTag,1) + nTag=length(ds.infods); + TagNo=strmatch(deblank(addTag(q,:)),name,'exact')'; + if isempty(TagNo) % Insert a tag at the end of the _DATASET tags. + TagNo=max(DATASET_tags)+1; + ds.infods((TagNo+1):(nTag+1))=ds.infods(TagNo:nTag); + ds.infods(TagNo)=struct('name',deblank(addTag(q,:)),'type',4,'data',TagValue(q)); + name=strvcat(name(1:TagNo-1,:),deblank(addTag(q,:)),name(TagNo:nTag,:)); + DATASET_tags=[DATASET_tags TagNo]; + else + ds.infods(TagNo).data=TagValue(q); % Tag exists. Just update the value. + end + end % End loop over head position and head motion tags. + clear q nTag DATASET_tags; +else + fprintf(['writeCTFds (updateBandwidth): Found no _DATASET tags in infods.\n'... + '\t\t\tDid not add bandwidth tags.\n']); +end + +return +%%%%%%%%%%%%%% End of updateBandwidth %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%% Function updateDateTime %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function ds=updateDateTime(ds); +% Update the dat/time fields of res4 and and infods + +datetime=floor(clock); +if isfield(ds,'infods'); + name=getArrayField(ds.infods,'name')'; + DATASET_tags=strmatch('_DATASET_',name); + if ~isempty(DATASET_tags) + addTag=strvcat('_DATASET_CREATORDATETIME','_DATASET_LASTMODIFIEDDATETIME'); + tagData=sprintf('%d%2.2d%2.2d%2.2d%2.2d%2.2d',datetime); + tagType=10; + for q=1:size(addTag,1) + nTag=length(ds.infods); + TagNo=strmatch(deblank(addTag(q,:)),name,'exact')'; + if isempty(TagNo) % Insert a tag at the end of the _DATASET tags. + TagNo=max(DATASET_tags)+1; + ds.infods((TagNo+1):(nTag+1))=ds.infods(TagNo:nTag); + name=strvcat(name(1:TagNo-1,:),deblank(addTag(q,:)),name(TagNo:nTag,:)); + DATASET_tags=[DATASET_tags TagNo]; + end + ds.infods(TagNo)=struct('name',deblank(addTag(q,:)),'type',tagType,'data',tagData); + end + clear nTag TagNo name DATASET_tags addTag tagData tagType; + else + fprintf('writeCTFds (updateDateTime): Cannot find any _DATASET tags in ds.infods.\n'); + end % End loop over head position and head motion tags. +else + fprintf('writeCTFds (updateDateTime): Cannot find ds.infods.\n'); +end +ds.res4.data_date=sprintf('%4d/%2.2d/%2.2d',datetime(1:3)); +ds.res4.data_time=sprintf('%2.2d:%2.2d:%2.2d',datetime(4:6)); + +return +%%%%%%%%%%%%%% End of updateDateTime %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%% Function getArrayField %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function x=getArrayField(S,yfield) + +% Extracts one field of a structure array. +% Inputs: S : structure array. +% yfield: name of field of S (string) + +% Output: x. x(:,n)=S(n).yfield; size(x)=[size(yfield) length(S)] + +% Field sizes: Two options: +% 1. size(S(n).yfield) is the same for all n. Any size allowed. +% 2. S(n).yfield is a 2-D array for all structure elements S(n). +% Then yfield of different array elements S(n) can have different sizes. +% The array returned will be large enough to accomodate all of the data. + +sizeS=size(S); +nS=prod(sizeS); +S=reshape(S,1,nS); + +% Determine which array-size option to use. +sizey=size(getfield(S,{1},yfield)); +option1=1; +option2=(length(sizey)==2); +for n=2:nS + sizeyn=size(getfield(S,{n},yfield)); + option1=option1 & isequal(sizey,sizeyn); + option2=option2 & length(sizeyn)==2; + if option2 + sizey=max([sizey;sizeyn],[],1); + end +end + +if option1 % All fields have the same size + nY=prod(sizey); + if isnumeric(getfield(S,{1},yfield)) + x=zeros(nY,nS); + elseif ischar(getfield(S,{1},yfield)) + x=char(zeros(nY,nS)); + end + for n=1:nS + x(:,n)=reshape(getfield(S,{n},yfield),nY,1); + end + x=reshape(x,[sizey nS]); +elseif option2 % All fields have only two dimensions + if isnumeric(getfield(S,{1},yfield)) + x=zeros([sizey nS]); + elseif ischar(getfield(S,{1},yfield)) + x=char(zeros([sizey nS])); + end + for n=1:nS + y=getfield(S,{n},yfield); + sizeyn=size(y); + x(1:sizeyn(1),1:sizeyn(2),n)=y; + end +else + fprintf(['getArrayField: Field %s of the structure array has >2 dimensions ',... + 'and not all field have the same size.\n'],yfield); + x=[]; +end +x=squeeze(x); +return +%%%%%%%% End of getArrayField %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/external/ctf/writeCTFds.p b/external/ctf/writeCTFds.p deleted file mode 100644 index 9fcdd2a..0000000 Binary files a/external/ctf/writeCTFds.p and /dev/null differ diff --git a/external/ctf/writeCTFhdm.m b/external/ctf/writeCTFhdm.m new file mode 100644 index 0000000..7224ef5 --- /dev/null +++ b/external/ctf/writeCTFhdm.m @@ -0,0 +1,220 @@ +function writeCTFhdm(fileName,hdm); + +% Version 1.1 20 April 2007 Modified to make sure that clinical-0ise message and +% creator software are not repeated. +% Test date. +% 22 March 2007. Modified to write v6.0 .hdm files which have additional +% fields in MultiSphere_Data. Check that the .hdm version +% number is compatible with the fields included in +% MultiSphere_Data. +% Creates a CTF-compatible head model file from structure hdm +% Structure hdm is in the format produced by readCTFhdm. + +% The formal of hdm (Head Model) files is given in document "CTF MEG FIle Formats", +% PN900-0088. The head model files are text files in the "Config Reader" format. + +% The purpose is to allow MATLAB users to specify multiple-local spheres head models +% in a formatthat is compatible with CTF analysis software (DipoleFit). It also allows +% users to transfer .hdm files between datasets. + +% Head Model File format is defined in document "CTF MEG FIle Formats', PN900-0088. + +% Inputs : fileName: Name of the .hdm file to create. It must include the full path, +% including dataset specification and the extension .hdm. +% hdm: The structure containing the class information. See D + +% Output: Head model file. + +persistent printWarning +creatorSoftware='writeCTFhdm'; +versionSoftware='v1.1'; + +if nargin==0 + fprintf('writeCTFhdm Version 1.1 20 April 2007\n'); + fprintf(['\twriteCTFhdm(fileName,hdm) creates a CTF-format head model file',... + ' from the fields of structure hdm.\n',... + '\t\t\tfileName is the name of the new head model file including path and ',... + 'extension ''.hdm''.\n',... + '\t\t\thdm is a structure with the format produced by readCTFhdm.\n',... + '\t\t\tThe head model file format is described in document ',... + '"CTF MEG File Formats", PN900-0088.\n\n']); + return +elseif nargin~=2 + fprintf(['\nwriteCTFhdm: %d input argument(s). writeCTFhdm needs 2 arguments:\n',... + ' fileName and structure containing the head model.\n\n'],nargin); + return +elseif ~ischar(fileName) | isempty(fileName) | ~isstruct(hdm) | isempty(hdm) + fprintf('writeCTFhdm: Wrong argument types, or empty arguments.\n'); + whos fileName hdm; + return +elseif ndims(fileName)>2 | min(size(fileName))>1 + fprintf('\nwriteCTFhdm: size(fileName)=[');fprintf(' %d',size(fileName)); + fprintf('] Input fileName must be a character string.\n\n'); + return +elseif exist(fileName)==2 + fprintf('writeCTFhdm: File %s already exists.\n',fileName); + return +elseif isempty(strfind(fileName,'.hdm')) + fprintf('writeCTFhdm: fileName=%s does not have .hdm extension.\n',fileName); + return +elseif ~isfield(hdm,'Model') | ... + (~isfield(hdm,'MultiSphere_Data') & ~isfield(hdm,'MEG_Sphere')) + fprintf(['writeCTFhdm: Structure hdm is missing fields Multisphere_Data, ',... + 'MEG_Sphere or Model.\n']); + fprintf(' It cannot be a useful head model file.\n'); + hdm + return +elseif isfield(hdm,'MEG_Sphere') & ~isfield(hdm,'MultiSphere_Data') + fprintf(['writeCTFhdm: Creating a single-sphere model. ',... + 'No multisphere data found in structure hdm.\n']); +elseif ~isfield(hdm,'MEG_Sphere') & isfield(hdm,'MultiSphere_Data') + fprintf(['writeCTFhdm: Creating a multi-sphere model. ',... + 'No single-sphere data found in structure hdm.\n']); +end + +% Check version numbers and 'MultiSphere_Data fields. +if isfield(hdm,'File_Info') & isfield(hdm,'MultiSphere_Data') + versionText=hdm.File_Info.VERSION; + kpt=strfind(versionText,'VERSION_'); + version=sscanf(versionText(kpt+8:length(versionText)),'%g'); + if version<=5.9 + if isfield(hdm.MultiSphere_Data,'HEADPOS') | isfield(hdm.MultiSphere_Data,'SURFACE_TYPE') + fprintf('\n'); + fprintf('%s\n',['writeCTFhdm: .hdm VERSION=',num2str(version,'%0.1f'),... + ', but fields HEADPOS and/or SURFACE_TYPE appear'],... + ' in hdm.MultiSphere_data. They should appear only in v6.0 and higher.'); + return + end + elseif version>=6.0 + if ~isfield(hdm.MultiSphere_Data,'HEADPOS') | ~isfield(hdm.MultiSphere_Data,'SURFACE_TYPE') + fprintf('\n'); + fprintf('%s\n',['writeCTFhdm: .hdm VERSION=',num2str(version,'%0.1f'),... + ', but fields HEADPOS and/or SURFACE_TYPE do not appear'],... + ' in hdm.MultiSphere_data. They must appear in v6.0 and higher.'); + return + end + end +end + +if isempty(printWarning) + fprintf(['\nwriteCTFhdm: The head-model data you are writing have been processed by software\n',... + '\tnot manufactured by VSM MedTech Ltd. and that has not received marketing clearance\n',... + '\tfor clinical applications. These data should not be later employed for clinical\n',... + '\tand/or diagnostic purposes.\n']); + printWarning=1; +end + +fid=fopen(fileName,'w','ieee-be'); % Use 'w' option to ensure no char(13)'s at the end of line. + +% Add the clinical-use message if it is not already present. +addClinicalUseMessage=1; +addCreatorSoftwareMessage=1; +if isfield(hdm,'note') + addClinicalUseMessage=isempty(strfind(reshape(hdm.note',1,prod(size(hdm.note))),'NOT FOR CLINICAL USE')); + addCreatorSoftwareMessage=isempty(strfind(reshape(hdm.note',1,prod(size(hdm.note))),'writeCTFhdm')); +end +if isfield(hdm,'note') + for k=1:size(hdm.note,1) + strng=deblank(hdm.note(k,:)); + if ~strcmp(strng(1:2),'//');strng=['// ',strng];end + fprintf(fid,'%s\n',strng); + if k==3 & addClinicalUseMessage; + fprintf(fid,[... + '// *************************************\n',... + '// * NOT FOR CLINICAL USE *\n',... + '// *************************************\n\n']); + end + end + clear strng; +end +if addCreatorSoftwareMessage + fprintf(fid,'//\n// Prepared by %s %s\n//\n',creatorSoftware,versionSoftware); +end +if addClinicalUseMessage + fprintf(fid,['// *************************************\n',... + '// * NOT FOR CLINICAL USE *\n',... + '// *************************************\n\n']); +end +clear addClinicalUseMessage; + +className=char(fieldnames(hdm)); +for n=1:size(className,1) + cName=deblank(className(n,:)); + if strcmp(cName,'note'); + continue; % Already printed the notes. + end + eval(['tagName=char(fieldnames(hdm.',cName,'));']); + fprintf(fid,'%s\n{\n',cName); + if ~strcmp('MultiSphere_Data',cName); + for k=1:size(tagName,1) + tgName=deblank(tagName(k,:)); + if strcmp(tgName,'note'); + eval(['note=hdm.',cName,'.note;']); + if ~isempty(note) + for q=1:size(note,1) + strng=deblank(note(k,:)); + if ~strcmp(strng(1:2),'//');strng=['// ',strng];end + fprintf(fid,'\t%s\n',strng); + end + end + clear strng; + else + eval(['tgVal=hdm.',cName,'.',tgName,';']); + tgType=class(tgVal); + fprintf(fid,'\t%s:',tgName); + if isempty(tgVal); + fprintf(fid,'\t'); + elseif strcmp(tgType,'char') + fprintf(fid,'\t%s',tgVal); + elseif max(abs(tgVal-round(tgVal)))<1e-4 + fprintf(fid,'\t%d',round(tgVal)); + else + fprintf(fid,'\t%0.4f',tgVal); + end + fprintf(fid,'\n'); + clear tgType tgVal tgName; + end + end + else % MultiSphere_Data has a different format : + if strmatch('SEARCH_RADIUS',tagName,'exact') + fprintf(fid,'\tSEARCH_RADIUS:\t%5.3f\n',hdm.MultiSphere_Data.SEARCH_RADIUS); + else + fprintf('writeCTFhdm: tag SEARCH_RADIUS is missing from class MultiSphere_Data.\n'); + end + if strmatch('HEADSHAPE_FILE',tagName,'exact') + fprintf(fid,'\tHEADSHAPE_FILE:\t%s\n',hdm.MultiSphere_Data.HEADSHAPE_FILE); + else + fprintf('writeCTFhdm: tag HEADSHAPE_FILE is missing from class MultiSphere_Data.\n'); + end + if strmatch('SURFACE_TYPE',tagName,'exact') + fprintf(fid,'\tSURFACE_TYPE:\t%s\n',hdm.MultiSphere_Data.SURFACE_TYPE); + end + fprintf(fid,'\n'); + if strmatch('HEADPOS',tagName,'exact') + fprintf(fid,'\t%s\n','// Head Coil coordinates relative to dewar, cm',... + '// NA_x NA_y NA_z LE_x LE_y LE_z RE_x RE_y RE_z Nominals'); + fprintf(fid,'\tHEADPOS:'); + fprintf(fid,'\t%0.3f',hdm.MultiSphere_Data.HEADPOS.HEADPOS); + fprintf(fid,'\t%s\n\n',hdm.MultiSphere_Data.HEADPOS.NOMINAL); + end + + % Don't use hdm.MultiSphere_data.note + fprintf(fid,'\t%s\n','// Multiple Sphere locations in cm'); + fprintf(fid,'\t%s','//','X','Y','Z','Radius'); + fprintf(fid,'\n'); + % Create a separate tag for each SQUID channel. Be carefule to remove the + % coefficient-set identifier in case the user has generated array SQUIDname from + % ds.res4.chanNames of some dataset. + for q=1:size(hdm.MultiSphere_Data.SQUIDname,1) + fprintf(fid,'\t%s:\t%5.3f\t%5.3f\t%5.3f\t%5.3f\n',... + deblank(strtok(hdm.MultiSphere_Data.SQUIDname(q,:),'-')),... + hdm.MultiSphere_Data.sphereOrigin(:,q),... + hdm.MultiSphere_Data.radius(q)); + end + fprintf(fid,'\n'); + end + fprintf(fid,'}\n\n'); + clear cName tagName k q; +end % End of loop over classes +fclose(fid); +return \ No newline at end of file diff --git a/external/ctf/writeCTFhdm.p b/external/ctf/writeCTFhdm.p deleted file mode 100644 index 0e7e22b..0000000 Binary files a/external/ctf/writeCTFhdm.p and /dev/null differ diff --git a/external/ctf/writeMarkerFile.m b/external/ctf/writeMarkerFile.m new file mode 100644 index 0000000..cd423e4 --- /dev/null +++ b/external/ctf/writeMarkerFile.m @@ -0,0 +1,105 @@ +function writeMarkerFile(MarkerFile,marker); + +% Version 1.0 27 Oct. 2006 + +% Prepares a CTF Markerfile. +% The MarkerFile format is defined in document CTF MEG File Formats, PN900-0088. + +% Inputs : +% Structure marker in the format prepared by readMarkerFile.m. In cases where +% only some of the trials of a data set are being written from MATLAB to a data set, +% be careful to match the trial identification to the data. +% +% Trial numbering in structure marker starts at 1, but the numbering in the marker +% file starts at 0. + +% The dataset (i.e. directory) must be created before calling writeMarkerFile. + +% Output : Marker file with name datasetname\Markerfile.mrk + +% Check input marker. + +if nargin==0 + fprintf(['writeMarkerFile: Version 1.0 27 Oct. 2006\n',... + '\twriteMarkerFile(MarkerFile,marker) creates a CTF dataset MarkerFile ',... + 'from structure array marker.\n',... + '\tStructure array marker is in the format created by function ',... + 'readMarkerFile.\n\n',... + '\twriteMarkerFile decrements trial numbers by 1 so the first dataset ',... + 'trial in MarkerFile is trial 0.\n\n',... + '\tThe MarkerFile format is defined in document "CTF MEG File Formats",',... + ' PN900-0088.\n\n']); + return +end + + +if exist('marker')==0 + fprintf('writeMarkerFile: Structure marker is not defined.\n'); + return +elseif isempty(marker) + fprintf('writeMarkerFile: Structure marker is empty.\n'); + return +elseif ~isstruct(marker) + fprintf('writeMarkerFile: Input argument marker is not a structure.\n'); + return +end + +% Check MarkerFile +if exist('MarkerFile')~=1;MarkerFile=char([]);end +if isempty(MarkerFile) + fprintf('writeMarkerFile: Must specify a MarkerFile.\n'); + return +elseif ~ischar(MarkerFile) + fprintf('writeMarkerFile: MarkerFile must be a character string.\n'); + return +end + +fid=fopen(MarkerFile,'w','ieee-be'); + +% Generate datasetname from MarkerFile. +ksep=max([0 strfind(MarkerFile,filesep)]); +datasetname=MarkerFile(1:ksep-1); +if isempty(datasetname);datasetname=cd;end + +nMarker=length(marker); + +fprintf(fid,'PATH OF DATASET:\n%s\n\n\n',datasetname); +fprintf(fid,'NUMBER OF MARKERS:\n%d\n\n\n',nMarker); + +for k=1:nMarker + if ~any(marker(k).ClassGroupId==[0 3]); + fprintf('write_MarkerFile: marker(%d).ClassGroupId=%d. Only 0 and 3 are allowed.\n',... + marker(k).ClassGroutpId); + continue; + end + if k==1 % Add sign character to make output match the output of Acq. + sgn=char([]); % DataEditor (5.3.0-experimental-linux-20060918). + else % There should be no real significance to the sign. + sgn='+'; + end + No_of_Samples=prod(size(marker(k).time)); + fprintf(fid,'CLASSGROUPID:\n%s%d\nNAME:\n%s\nCOMMENT:\n%s\n',... + sgn,marker(k).ClassGroupId,marker(k).Name,marker(k).Comment); + fprintf(fid,'COLOR:\n%s\nEDITABLE:\n%s\nCLASSID:\n%s%d\n',... + marker(k).Color,marker(k).Editable,sgn,marker(k).ClassId); + if marker(k).ClassGroupId==0 + fprintf(fid,'BITNUMBER:\n%d\nPOLARITY:\n%s\nSOURCE:\n%s\nTHRESHOLD:\n%3.1f\n',... + marker(k).BitNumber,marker(k).Polarity,marker(k).Source,marker(k).Threshold); + end + fprintf(fid,'NUMBER OF SAMPLES:\n%d\n',No_of_Samples); + fprintf(fid,'LIST OF SAMPLES:\nTRIAL NUMBER\t\tTIME FROM SYNC POINT (in seconds)\n'); + marker(k).trial=reshape(marker(k).trial,1,No_of_Samples); + marker(k).time=reshape(marker(k).time,1,No_of_Samples); + + % Format with no signs on trail numbers and no signs on positive time and 1e-5s accuracy + %fprintf(fid,'%20d\t\t\t\t%20.5f\n',[marker(k).trial-1;marker(k).time]); + + % Format to match the MarkerFile generated by Acq (UCL 20060913) + % and DataEditor (5.3.0-experimental-linux-20060918). + % Unsigned trial number, signed time. + fprintf(fid,'%20d\t\t\t\t%+20.12g\n',[marker(k).trial-1;marker(k).time]); + + fprintf(fid,'\n\n'); +end +fclose(fid); +return diff --git a/external/ctf/writeMarkerFile.p b/external/ctf/writeMarkerFile.p deleted file mode 100644 index 3973f0f..0000000 Binary files a/external/ctf/writeMarkerFile.p and /dev/null differ diff --git a/external/ctf/writeRes4.m b/external/ctf/writeRes4.m new file mode 100644 index 0000000..410f1c2 --- /dev/null +++ b/external/ctf/writeRes4.m @@ -0,0 +1,204 @@ +function res4=writeRes4(res4File,res4,MAX_COILS); +% Write the new .res4 file. Use ieee-be (big endian) format +% Character-string output is done using function writeCTFstring which +% checks that strings are the correct length for the .res4 file format. + +% Function calls: - writeCTFstring (included in this listing). + +fid_res4=fopen(res4File,'w','ieee-be'); +if fid_res4<0 + fprintf('writeCTFds (writeRes4): Could not open file %s\n',res4File); + return +end + +fwrite(fid_res4,[res4.header(1:7),char(0)],'uint8'); % 8-byte header + +% meg41GeneralResRec +res4.appName=writeCTFstring(res4.appName,-256,fid_res4); +res4.dataOrigin=writeCTFstring(res4.dataOrigin,-256,fid_res4); +res4.dataDescription=writeCTFstring(res4.dataDescription,-256,fid_res4); +fwrite(fid_res4,res4.no_trials_avgd,'int16'); +res4.data_time=writeCTFstring(res4.data_time,255,fid_res4); +res4.data_date=writeCTFstring(res4.data_date,255,fid_res4); + +% new_general_setup_rec_ext part of meg41GeneralResRec + +fwrite(fid_res4,res4.no_samples,'int32'); % 4 +fwrite(fid_res4,[res4.no_channels 0],'int16'); % 2*2 +fwrite(fid_res4,res4.sample_rate,'double'); % 8 +fwrite(fid_res4,res4.epoch_time,'double'); % 8 +fwrite(fid_res4,[res4.no_trials 0],'int16'); % 2*2 +fwrite(fid_res4,res4.preTrigPts,'int32'); % 4 +fwrite(fid_res4,res4.no_trials_done,'int16'); % 2 +fwrite(fid_res4,res4.no_trials_display,'int16'); % 2 +fwrite(fid_res4,res4.save_trials,'int32'); % 4 CTFBoolean + +% meg41TriggerData part of new_general_setup_rec_ext 10 bytes total +fwrite(fid_res4,res4.primaryTrigger,'int32'); % 4 +fwrite(fid_res4,res4.triggerPolarityMask,'int32'); % 4 +fwrite(fid_res4,[0 0],'uint8'); % 2 bytes +% end of meg41TriggerData part of new_general_setup_rec_ext + +fwrite(fid_res4,[0 0],'uint8'); % 2 bytes padding +fwrite(fid_res4,[res4.trigger_mode 0],'int16'); % 2*2 +fwrite(fid_res4,res4.accept_reject_Flag,'int32'); % 4 CTFBoolean +fwrite(fid_res4,[res4.run_time_display 0],'int16');% 2*2 + +fwrite(fid_res4,res4.zero_Head_Flag,'int32'); % 4 CTFBoolean +fwrite(fid_res4,res4.artifact_mode,'int32'); % 4 CTFBoolean +% end of new_general_setup_rec_ext part of meg41GeneralResRec + +% meg4FileSetup part of meg41GeneralResRec +res4.nf_run_name=writeCTFstring(res4.nf_run_name,32,fid_res4); +res4.nf_run_title=writeCTFstring(res4.nf_run_title,-256,fid_res4); +res4.nf_instruments=writeCTFstring(res4.nf_instruments,32,fid_res4); +res4.nf_collect_descriptor=writeCTFstring(res4.nf_collect_descriptor,32,fid_res4); +res4.nf_subject_id=writeCTFstring(res4.nf_subject_id,-32,fid_res4); +res4.nf_operator=writeCTFstring(res4.nf_operator,32,fid_res4); +res4.nf_sensorFileName=writeCTFstring(res4.nf_sensorFileName,56,fid_res4); +res4.rdlen=length(res4.run_description); % Run_description may have been changed. +fwrite(fid_res4,[0 res4.rdlen 0],'int32'); % 12-byte structure of the .res4 file. +res4.run_description=writeCTFstring(res4.run_description,res4.rdlen,fid_res4); +% end of meg4FileSetup part of meg41GeneralResRec + +% filter descriptions + +fwrite(fid_res4,res4.num_filters,'int16'); +for kfilt=1:res4.num_filters + fwrite(fid_res4,res4.filters(kfilt).freq,'double'); + fwrite(fid_res4,res4.filters(kfilt).fClass,'int32'); + fwrite(fid_res4,res4.filters(kfilt).fType,'int32'); + fwrite(fid_res4,res4.filters(kfilt).numParam,'int16'); + for kparm=1:res4.filters(kfilt).numParam + fwrite(fid_res4,res4.filters(kfilt).Param(kparm),'double'); + end +end + +% Write channel names. Must have size(res4.chanNames)=[nChan 32] +[no_chanNames len_chanNames]=size(res4.chanNames); +for kchan=1:res4.no_channels + res4.chanNames(kchan,:)=writeCTFstring(res4.chanNames(kchan,:),len_chanNames,fid_res4); +end + +% Write sensor resource table +for kchan=1:res4.no_channels + fwrite(fid_res4,res4.senres(kchan).sensorTypeIndex,'int16'); + fwrite(fid_res4,res4.senres(kchan).originalRunNum,'int16'); + fwrite(fid_res4,res4.senres(kchan).coilShape,'int32'); + fwrite(fid_res4,res4.senres(kchan).properGain,'double'); + fwrite(fid_res4,res4.senres(kchan).qGain,'double'); + fwrite(fid_res4,res4.senres(kchan).ioGain,'double'); + fwrite(fid_res4,res4.senres(kchan).ioOffset,'double'); + fwrite(fid_res4,res4.senres(kchan).numCoils,'int16'); + numCoils=res4.senres(kchan).numCoils; + fwrite(fid_res4,res4.senres(kchan).grad_order_no,'int16'); + fwrite(fid_res4,0,'int32'); % Padding to 8-byte boundary + + % coilTbl + for qx=1:numCoils + fwrite(fid_res4,[res4.senres(kchan).pos0(:,qx)' 0],'double'); + fwrite(fid_res4,[res4.senres(kchan).ori0(:,qx)' 0],'double'); + fwrite(fid_res4,[res4.senres(kchan).numturns(qx) 0 0 0],'int16'); + fwrite(fid_res4,res4.senres(kchan).area(qx),'double'); + end + if numCoils0 + scrx_out=[]; + for kx=1:res4.numcoef + sName=strtok(char(res4.scrr(kx).sensorName),['- ',char(0)]); + if ~isempty(strmatch(sName,res4.chanNames)) + scrx_out=[scrx_out kx]; + end + end + % Remove the extra coefficient records + res4.scrr=res4.scrr(scrx_out); + res4.numcoef=size(res4.scrr,2); + fwrite(fid_res4,res4.numcoef,'int16'); % Number of coefficient records + % Convert res4.scrr to double before writing to output file. In MATLAB 5.3.1, + % when the 'ieee-be' option is applied, fwrite cannot write anything except + % doubles and character strings, even if fwrite does allow you to specify short + % integer formats in the output file. + for nx=1:res4.numcoef + fwrite(fid_res4,double(res4.scrr(nx).sensorName),'uint8'); + fwrite(fid_res4,[double(res4.scrr(nx).coefType) 0 0 0 0],'uint8'); + fwrite(fid_res4,double(res4.scrr(nx).numcoefs),'int16'); + fwrite(fid_res4,double(res4.scrr(nx).sensor),'uint8'); + fwrite(fid_res4,res4.scrr(nx).coefs,'double'); + end +end +fclose(fid_res4); +return + + +% ************************************************************************************* +%*************** Function writeCTFstring ************************************************ +function strng=writeCTFstring(instrng,strlen,fid) + +% Writes a character string to output unit fid. Append nulls to get the correct length. +% instrng : Character string. size(instrng)=[nLine nPerLine]. strng is reformulated as a +% long string of size [1 nChar]. Multiple lines are allowed so the user can +% easily append text. If necessary, characters are removed from +% instrng(1:nLine-1,:) so all of strng(nLine,:) can be accomodated. +% strlen: Number of characters to write. strlen<0 means remove leading characters. +% If abs(strlen)>length(strng) pad with nulls (char(0)) +% If 01 + % Concatenate lines 1:nLine-1 + for k=2:nLine-1 + if length(strng)>0 + if ~strcmp(strng(length(strng)),'.') & ~strcmp(strng(length(strng)),',') + strng=[strng '.']; % Force a period at the end of the string. + end + end + strng=[strng ' ' deblank(instrng(k,:))]; + end + + if length(strng)>0 + if ~strcmp(strng(length(strng)),'.') % Force a period at the end of the string. + strng=[strng '.']; + end + end + % Add all of the last line. + nChar=length(strng); + nLast=length(deblank(instrng(nLine,:))); + strng=[strng(1:min(nChar,abs(strlen)-nLast-4)) ' ' deblank(instrng(nLine,:))]; +end + +if length(strng)=strlen & strlen>0 + strng=[strng(1:strlen-1) char(0)]; +else + strng=[strng(nLast+[strlen+2:0]) char(0)]; +end + +fwrite(fid,strng,'char'); +return +% ************* End of function writeCTFstring *************************************** +% ************************************************************************************ + diff --git a/external/ctf/writeRes4.p b/external/ctf/writeRes4.p deleted file mode 100644 index 725ced6..0000000 Binary files a/external/ctf/writeRes4.p and /dev/null differ diff --git a/external/fieldtrip/@config/access.m b/external/fieldtrip/@config/access.m deleted file mode 100644 index 2cfb315..0000000 --- a/external/fieldtrip/@config/access.m +++ /dev/null @@ -1,30 +0,0 @@ -function y = access(x, cmd); - -% ACCESS Return the number of accesses (assignments and references) to a CONFIGURATION object. - -if nargin==1 - fprintf('----------- values -----------\n'); - disp(x.value); - - fprintf('----------- original -----------\n'); - disp(x.original); - - fprintf('----------- assignment -----------\n'); - disp(x.assign); - - fprintf('----------- reference -----------\n'); - disp(x.reference); -else - switch cmd(1) - case 'v' - y = x.value; - case 'r' - y = x.reference; - case 'a' - y = x.assign; - case 'o' - y = x.original; - otherwise - error('Incorrect command for accessing a config object.') - end -end diff --git a/external/fieldtrip/@config/cleancfg.m b/external/fieldtrip/@config/cleancfg.m deleted file mode 100644 index 659525a..0000000 --- a/external/fieldtrip/@config/cleancfg.m +++ /dev/null @@ -1,84 +0,0 @@ -function [newcfg] = cleancfg(cfg, presentused, defaultused, presentunused, defaultunused); - -% CLEANCFG Returns a structure with the config fields that were used -% and displays on screen which fields were used or not. - -% set the defaults -if nargin<2 - presentused = 0; -end -if nargin<3 - defaultused = 0; -end -if nargin<4 - presentunused = 0; -end -if nargin<5 - defaultunused = 0; -end - -r = access(cfg, 'reference'); -a = access(cfg, 'assign'); -o = access(cfg, 'original'); -v = access(cfg, 'value'); - -key = fieldnames(cfg); key = key(:)'; -used = zeros(size(key)); -modified = zeros(size(key)); -original = zeros(size(key)); - -for i=1:length(key) - used(i) = (r.(key{i})>0); - modified(i) = (a.(key{i})>0); - original(i) = (o.(key{i})>0); -end - -if presentused - fprintf('\nThe following config fields were USED as specified by you\n'); - sel = find(used & ~modified); - if numel(sel) - fprintf(' cfg.%s\n', key{sel}); - else - fprintf(' \n'); - end -end - -if defaultused - fprintf('\nThe following config fields were USED and were adjusted\n'); - sel = find(used & modified); - if numel(sel) - fprintf(' cfg.%s\n', key{sel}); - else - fprintf(' \n'); - end -end - -if presentunused - fprintf('\nThe following config fields were NOT USED and were specified by you\n'); - sel = find(~used & original); - if numel(sel) - fprintf(' cfg.%s\n', key{sel}); - else - fprintf(' \n'); - end -end - -if defaultunused - fprintf('\nThe following config fields were NOT USED and set to defaults\n'); - sel = find(~used & ~original); - if numel(sel) - fprintf(' cfg.%s\n', key{sel}); - else - fprintf(' \n'); - end -end - -if nargout - usedkey = key(find(used)); - usedval = {}; - for i=1:length(usedkey) - usedval{i} = v.(usedkey{i}); - end - newcfg = cell2struct(usedval, usedkey, 2); -end - diff --git a/external/fieldtrip/@config/config.m b/external/fieldtrip/@config/config.m deleted file mode 100644 index 390f015..0000000 --- a/external/fieldtrip/@config/config.m +++ /dev/null @@ -1,145 +0,0 @@ -function y = config(x, varargin) - -% CONFIG Construct a config object. -% -% y = CONFIG( ) creates an empty config object. -% y = CONFIG(x) creates a config object from the -% existing config object x, or from the existing -% structure x. -% y = CONFIG('field1', '..', 'field2', '..' ) creates a -% config object with the specified fields set to -% the specified values. -% The assignment and reference counters are initialized to zero. -% -% A config object is a structure-like object, but with the -% additional feature that the number of assignments and references -% to each field are being counted. -% -% The config object can be used throughout your FieldTrip function -% as if it were a plain Matlab structure. At the end of your FieldTrip -% function you can report the fields that were -% - not used (references=0) -% - locally assigned as compared to assigned by the end user (assignments>0) -% Subsequently you are able to the fields that are locally assigned but not -% being used (e.g. irrelevant default values). -% -% As an example, construct a config object with two fields -% A = config('a', 1, 'b', 2); -% A.a = 1; -% A.a = 1; -% A.a = 1; -% access(A) % this shows the values, the number of assignments and references -% disp(A.b); -% disp(A.b); -% access(A) % this shows the values, the number of assignments and references -% -% A config object can also contain structures -% A = config('a', 1, 'b', 2, 'c', struct('a', 1)); -% -% A config object can even contain nested config objects -% A = config('a', 1, 'b', 2, 'c', config('a', 1)) -% -% The nesting of config objects can be arbitrary deep -% a = 1 -% b = config('a', a) -% c = config('b', b) -% d = config('c', c) - -if nargin==1 - if isa(x, 'config') - % formally no conversion is needed, but a copy will be made in which the counters are reset - y = deepcopy(x); - key = fieldnames(x); - for i=1:length(key) - reset(y.assign .(key{i})); % reset the counter to zero - reset(y.reference.(key{i})); % reset the counter to zero - reset(y.original .(key{i})); % first set to zero and then increment with one, - increment(y.original.(key{i})); % since all fields were present in the original - end - elseif isa(x, 'struct') - % convert the input structure into a config object - key = fieldnames(x); - for j=1:numel(x) - val = {}; - for i=1:length(key) - try - val{i} = x(j).(key{i}); - catch - val{i} = []; - end - % use recursion to let some other part of the code handle the remainder - if isa(val{i}, 'struct') - val{i} = config(val{i}); - end - end - tmp = struct(); - tmp.value = struct(); - tmp.assign = struct(); - tmp.reference = struct(); - tmp.original = struct(); - for i=1:length(key) - tmp.value.(key{i}) = val{i}; - tmp.assign.(key{i}) = deepcopy(0); % ensure that a unique scalar is created for each counter - tmp.reference.(key{i}) = deepcopy(0); % ensure that a unique scalar is created for each counter - tmp.original.(key{i}) = deepcopy(1); % ensure that a unique scalar is created for each counter - end - y(j) = class(tmp,'config'); - end - if numel(x) - y = reshape(y, size(x)); - else - y = config; - end - else - error('Unsupported input class ''%s'' for constructing a config object', class(x)); - end - -elseif nargin>1 - if mod(nargin,2) - error('Incorrect number of input arguments (should be key-value pairs)') - end - varargin = {x varargin{:}}; - key = varargin(1:2:end); - val = varargin(2:2:end); - - % When having y.assign and y.reference point to the same scalars, there is - % a side effect in the increment function that reveals that the scalars - % representing the different counters all point to the same physical - % memory address. Therefore I have to ensure that there is a unique - % scalar for each individual counter. - assign = {}; - reference = {}; - original = {}; - for i=1:length(key) - assign {end+1} = key{i}; - reference{end+1} = key{i}; - original {end+1} = key{i}; - assign {end+1} = deepcopy(0); % ensure that a unique scalar is created for each counter - reference{end+1} = deepcopy(0); % ensure that a unique scalar is created for each counter - original {end+1} = deepcopy(1); % ensure that a unique scalar is created for each counter - end - - for i=1:length(val) - if isa(val{i}, 'struct') - % use recursion to convert sub-structures into sub-configs - val{i} = config(val{i}); - end - end - - y.value = struct(varargin{:}); - y.assign = struct(assign{:}); - y.reference = struct(reference{:}); - y.original = struct(original{:}); - y = class(y,'config'); - -else - % create an empty config object - y = struct(); - y.value = struct(); - y.assign = struct(); - y.reference = struct(); - y.original = struct(); - y = class(y,'config'); - -end - diff --git a/external/fieldtrip/@config/display.m b/external/fieldtrip/@config/display.m deleted file mode 100644 index aaff51f..0000000 --- a/external/fieldtrip/@config/display.m +++ /dev/null @@ -1,38 +0,0 @@ -function display(x) - -% DISPLAY Display function for a config object. - -% this flag detemines how much feedback is given -% which is usefull for debugging -fb = false; - -if ~isempty(inputname(1)) - fprintf('\n'); - fprintf('%s =\n\n', inputname(1)); -end - -if fb - fprintf('----------- value -----------\n'); -end - -if numel(x)==0 - disp('1x1 config array with no fields.'); -elseif numel(x)==1 - disp(x.value); -else - siz = sprintf('%dx', size(x)); % construct a string like 1x2x3x, the last 'x' has to be removed - siz = siz(1:(end-1)); - fprintf('%s config array with fields:\n', siz); - key = fieldnames(x); - for i=1:length(key) - fprintf(' %s\n', key{i}); - end -end - -if fb - fprintf('----------- assignment -----------\n'); - disp(x.assign); - fprintf('----------- reference -----------\n'); - disp(x.reference); -end - diff --git a/external/fieldtrip/@config/fieldnames.m b/external/fieldtrip/@config/fieldnames.m deleted file mode 100644 index 525419b..0000000 --- a/external/fieldtrip/@config/fieldnames.m +++ /dev/null @@ -1,6 +0,0 @@ -function y = fieldnames(x) - -% FIELDNAMES Get field names from a config object. - -% all elements of an array would have the same fields, hence get the fields from the first element -y = fieldnames(x(1).value); diff --git a/external/fieldtrip/@config/isfield.m b/external/fieldtrip/@config/isfield.m deleted file mode 100644 index 7304ccf..0000000 --- a/external/fieldtrip/@config/isfield.m +++ /dev/null @@ -1,7 +0,0 @@ -function y = isfield(x, key) - -% ISFIELD Get field names from a config object. - -% all elements of an array would have the same fields, hence get the fields from the first element -y = isfield(x(1).value, key); - diff --git a/external/fieldtrip/@config/private/compile.m b/external/fieldtrip/@config/private/compile.m deleted file mode 100644 index cdb2610..0000000 --- a/external/fieldtrip/@config/private/compile.m +++ /dev/null @@ -1,4 +0,0 @@ -mex deepcopy.c -mex increment.c -mex reset.c -mex mempointer.c \ No newline at end of file diff --git a/external/fieldtrip/@config/private/compile.sh b/external/fieldtrip/@config/private/compile.sh deleted file mode 100755 index a448584..0000000 --- a/external/fieldtrip/@config/private/compile.sh +++ /dev/null @@ -1,19 +0,0 @@ -# -# shell helper script to compile all mex files -# - -if [ -a /opt/matlab72/bin/mex ]; then - MEX=/opt/matlab72/bin/mex -elif [ -a /Applications/MATLAB72/bin/mex ]; then - MEX=/Applications/MATLAB75/bin/mex -elif [ -a /Applications/MATLAB-2007b/bin/mex ]; then - MEX=/Applications/MATLAB-2007b/bin/mex -else - echo could not locate mex compiler - exit 1 -fi - -$MEX increment.c -$MEX reset.c -$MEX deepcopy.c - diff --git a/external/fieldtrip/@config/private/deepcopy.c b/external/fieldtrip/@config/private/deepcopy.c deleted file mode 100644 index 8b8d5b7..0000000 --- a/external/fieldtrip/@config/private/deepcopy.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * - * Copyright (C) 2007, Robert Oostenveld - * - * This implements Y=X by making a deep copy. A deep copy refers - * to a copy in which all levels of data are copied. For example, a - * deep copy of a cell array copies each cell, and the contents of - * the each cell (if any), and so on. - * - */ - -#include -#include "mex.h" -#include "matrix.h" - -void -mexFunction (int nlhs, mxArray * plhs[], int nrhs, const mxArray * prhs[]) -{ - double *x; - - if (nlhs > 1) - mexErrMsgTxt ("Invalid number of output arguments"); - if (nrhs > 1) - mexErrMsgTxt ("Invalid number of input arguments"); - - plhs[0] = mxDuplicateArray(prhs[0]); - - return; -} - diff --git a/external/fieldtrip/@config/private/deepcopy.m b/external/fieldtrip/@config/private/deepcopy.m deleted file mode 100644 index 6ce4368..0000000 --- a/external/fieldtrip/@config/private/deepcopy.m +++ /dev/null @@ -1,48 +0,0 @@ -function [varargout] = deepcopy(varargin) - -% DEEPCOPY makes a deep copy of an array, and returns a pointer to -% the copy. A deep copy refers to a copy in which all levels of data -% are copied. For example, a deep copy of a cell array copies each -% cell, and the contents of the each cell (if any), and so on. -% -% Example -% clear a b c -% a = 1; -% b = a; % this is a regular copy -% c = deepcopy(a); % this is a deep copy -% increment(a); % increment the value of a with one, using pass by reference -% disp(a); -% disp(b); -% disp(c); - -% remember the original working directory -pwdir = pwd; - -% determine the name and full path of this function -funname = mfilename('fullpath'); -mexsrc = [funname '.c']; -[mexdir, mexname] = fileparts(funname); - -try - % try to compile the mex file on the fly - warning('trying to compile MEX file from %s', mexsrc); - cd(mexdir); - mex(mexsrc); - cd(pwdir); - success = true; - -catch - % compilation failed - disp(lasterr); - error('could not locate MEX file for %s', mexname); - cd(pwdir); - success = false; -end - -if success - % execute the mex file that was juist created - funname = mfilename; - funhandle = str2func(funname); - [varargout{1:nargout}] = funhandle(varargin{:}); -end - diff --git a/external/fieldtrip/@config/private/deepcopy.mexa64 b/external/fieldtrip/@config/private/deepcopy.mexa64 deleted file mode 100755 index 14d4c75..0000000 Binary files a/external/fieldtrip/@config/private/deepcopy.mexa64 and /dev/null differ diff --git a/external/fieldtrip/@config/private/deepcopy.mexglx b/external/fieldtrip/@config/private/deepcopy.mexglx deleted file mode 100755 index 6a876f6..0000000 Binary files a/external/fieldtrip/@config/private/deepcopy.mexglx and /dev/null differ diff --git a/external/fieldtrip/@config/private/deepcopy.mexmaci b/external/fieldtrip/@config/private/deepcopy.mexmaci deleted file mode 100755 index 4b9cd55..0000000 Binary files a/external/fieldtrip/@config/private/deepcopy.mexmaci and /dev/null differ diff --git a/external/fieldtrip/@config/private/deepcopy.mexmaci64 b/external/fieldtrip/@config/private/deepcopy.mexmaci64 deleted file mode 100755 index 68f90da..0000000 Binary files a/external/fieldtrip/@config/private/deepcopy.mexmaci64 and /dev/null differ diff --git a/external/fieldtrip/@config/private/deepcopy.mexw32 b/external/fieldtrip/@config/private/deepcopy.mexw32 deleted file mode 100644 index 1d35936..0000000 Binary files a/external/fieldtrip/@config/private/deepcopy.mexw32 and /dev/null differ diff --git a/external/fieldtrip/@config/private/deepcopy.mexw64 b/external/fieldtrip/@config/private/deepcopy.mexw64 deleted file mode 100644 index a0e329d..0000000 Binary files a/external/fieldtrip/@config/private/deepcopy.mexw64 and /dev/null differ diff --git a/external/fieldtrip/@config/private/get.m b/external/fieldtrip/@config/private/get.m deleted file mode 100644 index 4e52be0..0000000 --- a/external/fieldtrip/@config/private/get.m +++ /dev/null @@ -1,18 +0,0 @@ -function y = get(x, key, inc) - -% GET Return the value of a field in a config object. - -if nargin<3 - % the default is to increment the reference counter, an exception is when - % a structure has to be recursed to assign a value to a substructure - inc = true; -end - -if isfield(x.value, key) - y = x.value.(key); - if inc - increment(x.reference.(key)); - end -else - error(sprintf('Reference to non-existent field ''%s''.', key)); -end diff --git a/external/fieldtrip/@config/private/increment.c b/external/fieldtrip/@config/private/increment.c deleted file mode 100644 index 4ea2564..0000000 --- a/external/fieldtrip/@config/private/increment.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * - * Copyright (C) 2007, Robert Oostenveld - * - * This implements X+=1, i.e. it increments the scalar X by one. - * - */ - -#include -#include "mex.h" -#include "matrix.h" - -void -mexFunction (int nlhs, mxArray * plhs[], int nrhs, const mxArray * prhs[]) -{ - double *x; - - if (nlhs > 0) - mexErrMsgTxt ("Invalid number of output arguments"); - if (nrhs > 1) - mexErrMsgTxt ("Invalid number of input arguments"); - - if (!mxIsDouble(prhs[0])) - mexErrMsgTxt ("Invalid type of input arguments (should be double)"); - - x = mxGetData(prhs[0]); - (*x) += 1; - - return; -} - diff --git a/external/fieldtrip/@config/private/increment.m b/external/fieldtrip/@config/private/increment.m deleted file mode 100644 index cfec4e2..0000000 --- a/external/fieldtrip/@config/private/increment.m +++ /dev/null @@ -1,40 +0,0 @@ -function [varargout] = increment(varargin) - -% INCREMENT Increments the input by one, using pass-by-reference. -% -% Example -% a = 1; -% increment(a); -% disp(a); - -% remember the original working directory -pwdir = pwd; - -% determine the name and full path of this function -funname = mfilename('fullpath'); -mexsrc = [funname '.c']; -[mexdir, mexname] = fileparts(funname); - -try - % try to compile the mex file on the fly - warning('trying to compile MEX file from %s', mexsrc); - cd(mexdir); - mex(mexsrc); - cd(pwdir); - success = true; - -catch - % compilation failed - disp(lasterr); - error('could not locate MEX file for %s', mexname); - cd(pwdir); - success = false; -end - -if success - % execute the mex file that was juist created - funname = mfilename; - funhandle = str2func(funname); - [varargout{1:nargout}] = funhandle(varargin{:}); -end - diff --git a/external/fieldtrip/@config/private/increment.mexa64 b/external/fieldtrip/@config/private/increment.mexa64 deleted file mode 100755 index 6ff4207..0000000 Binary files a/external/fieldtrip/@config/private/increment.mexa64 and /dev/null differ diff --git a/external/fieldtrip/@config/private/increment.mexglx b/external/fieldtrip/@config/private/increment.mexglx deleted file mode 100755 index 908887a..0000000 Binary files a/external/fieldtrip/@config/private/increment.mexglx and /dev/null differ diff --git a/external/fieldtrip/@config/private/increment.mexmaci b/external/fieldtrip/@config/private/increment.mexmaci deleted file mode 100755 index f6fcc3b..0000000 Binary files a/external/fieldtrip/@config/private/increment.mexmaci and /dev/null differ diff --git a/external/fieldtrip/@config/private/increment.mexmaci64 b/external/fieldtrip/@config/private/increment.mexmaci64 deleted file mode 100755 index a4b3837..0000000 Binary files a/external/fieldtrip/@config/private/increment.mexmaci64 and /dev/null differ diff --git a/external/fieldtrip/@config/private/increment.mexw32 b/external/fieldtrip/@config/private/increment.mexw32 deleted file mode 100644 index b4d3f64..0000000 Binary files a/external/fieldtrip/@config/private/increment.mexw32 and /dev/null differ diff --git a/external/fieldtrip/@config/private/increment.mexw64 b/external/fieldtrip/@config/private/increment.mexw64 deleted file mode 100644 index 5ca7c58..0000000 Binary files a/external/fieldtrip/@config/private/increment.mexw64 and /dev/null differ diff --git a/external/fieldtrip/@config/private/reset.c b/external/fieldtrip/@config/private/reset.c deleted file mode 100644 index 458a845..0000000 --- a/external/fieldtrip/@config/private/reset.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * - * Copyright (C) 2007, Robert Oostenveld - * - * This implements X=0, i.e. it sets the value of the scalar X to zero. - * - */ - -#include -#include "mex.h" -#include "matrix.h" - -void -mexFunction (int nlhs, mxArray * plhs[], int nrhs, const mxArray * prhs[]) -{ - double *x; - - if (nlhs > 0) - mexErrMsgTxt ("Invalid number of output arguments"); - if (nrhs > 1) - mexErrMsgTxt ("Invalid number of input arguments"); - - if (!mxIsDouble(prhs[0])) - mexErrMsgTxt ("Invalid type of input arguments (should be double)"); - - x = mxGetData(prhs[0]); - (*x) = 0; - - return; -} - diff --git a/external/fieldtrip/@config/private/reset.m b/external/fieldtrip/@config/private/reset.m deleted file mode 100644 index 2795302..0000000 --- a/external/fieldtrip/@config/private/reset.m +++ /dev/null @@ -1,40 +0,0 @@ -function [varargout] = reset(varargin) - -% RESET Set the value of the input to zero, using pass-by-reference. -% -% Example -% a = 1; -% reset(a); -% disp(a); - -% remember the original working directory -pwdir = pwd; - -% determine the name and full path of this function -funname = mfilename('fullpath'); -mexsrc = [funname '.c']; -[mexdir, mexname] = fileparts(funname); - -try - % try to compile the mex file on the fly - warning('trying to compile MEX file from %s', mexsrc); - cd(mexdir); - mex(mexsrc); - cd(pwdir); - success = true; - -catch - % compilation failed - disp(lasterr); - error('could not locate MEX file for %s', mexname); - cd(pwdir); - success = false; -end - -if success - % execute the mex file that was juist created - funname = mfilename; - funhandle = str2func(funname); - [varargout{1:nargout}] = funhandle(varargin{:}); -end - diff --git a/external/fieldtrip/@config/private/reset.mexa64 b/external/fieldtrip/@config/private/reset.mexa64 deleted file mode 100755 index dd4735a..0000000 Binary files a/external/fieldtrip/@config/private/reset.mexa64 and /dev/null differ diff --git a/external/fieldtrip/@config/private/reset.mexglx b/external/fieldtrip/@config/private/reset.mexglx deleted file mode 100755 index 02b6739..0000000 Binary files a/external/fieldtrip/@config/private/reset.mexglx and /dev/null differ diff --git a/external/fieldtrip/@config/private/reset.mexmaci b/external/fieldtrip/@config/private/reset.mexmaci deleted file mode 100755 index 4e4d8f2..0000000 Binary files a/external/fieldtrip/@config/private/reset.mexmaci and /dev/null differ diff --git a/external/fieldtrip/@config/private/reset.mexmaci64 b/external/fieldtrip/@config/private/reset.mexmaci64 deleted file mode 100755 index 901ac5f..0000000 Binary files a/external/fieldtrip/@config/private/reset.mexmaci64 and /dev/null differ diff --git a/external/fieldtrip/@config/private/reset.mexw32 b/external/fieldtrip/@config/private/reset.mexw32 deleted file mode 100644 index fb8f314..0000000 Binary files a/external/fieldtrip/@config/private/reset.mexw32 and /dev/null differ diff --git a/external/fieldtrip/@config/private/reset.mexw64 b/external/fieldtrip/@config/private/reset.mexw64 deleted file mode 100644 index 1a7b730..0000000 Binary files a/external/fieldtrip/@config/private/reset.mexw64 and /dev/null differ diff --git a/external/fieldtrip/@config/private/set.m b/external/fieldtrip/@config/private/set.m deleted file mode 100644 index de1d184..0000000 --- a/external/fieldtrip/@config/private/set.m +++ /dev/null @@ -1,14 +0,0 @@ -function x = set(x, key, val) - -% SET Assign a new value to the field of a config object. - -if ~isfield(x.value, key) - % initialize the counters for this field - % see the explaination about side effects of the increment function in config.m - x.assign.(key) = deepcopy(0); % ensure that a unique scalar is created for each counter - x.reference.(key) = deepcopy(0); % ensure that a unique scalar is created for each counter - x.original.(key) = deepcopy(0); % ensure that a unique scalar is created for each counter -end - -x.value.(key) = val; -increment(x.assign.(key)); diff --git a/external/fieldtrip/@config/rmfield.m b/external/fieldtrip/@config/rmfield.m deleted file mode 100644 index 25ddee7..0000000 --- a/external/fieldtrip/@config/rmfield.m +++ /dev/null @@ -1,14 +0,0 @@ -function x = rmfield(x, key) - -% RMFIELD Removes specified field from a CONFIGURATION object. - -if isa(key, 'cell') - for i=1:numel(key) - x = rmfield(x, key{i}); - end -else - x.value = rmfield(x.value , key); - x.assign = rmfield(x.assign , key); - x.reference = rmfield(x.reference, key); - x.original = rmfield(x.original , key); -end diff --git a/external/fieldtrip/@config/struct.m b/external/fieldtrip/@config/struct.m deleted file mode 100644 index 265f40b..0000000 --- a/external/fieldtrip/@config/struct.m +++ /dev/null @@ -1,32 +0,0 @@ -function y = struct(x, varargin) - -% STRUCT Convert a config object into a structure object. - -if nargin==1 - % convert the config object into a regular Matlab structure - for i=1:numel(x) - y(i) = struct(x(i).value); - end - y = reshape(y, size(x)); - % recurse into the structure to convert sub-configs into sub-structures - key = fieldnames(y); - for i=1:length(key) - val = y.(key{i}); - if isa(val, 'config') - y = setfield(y, key{i}, struct(val)); - end - end -else - % mimic the behaviour of the builtin Matlab struct function - if mod(nargin,2) - error('Incorrect number of input arguments (should be key-value pairs)') - end - varargin = {x varargin{:}}; - key = varargin(1:2:end); - val = varargin(2:2:end); - - y = struct(); - for i=1:length(key) - y = setfield(y, key{i}, val{i});; - end -end diff --git a/external/fieldtrip/@config/struct2cell.m b/external/fieldtrip/@config/struct2cell.m deleted file mode 100644 index 9afbfcf..0000000 --- a/external/fieldtrip/@config/struct2cell.m +++ /dev/null @@ -1,14 +0,0 @@ -function c = struct2cell(s) - -% STRUCT2CELL Convert structure array to cell array by first converting -% the config objection into a struct and then using standard Matlab call. - -% Copyright (C) 2008, Robert Oostenveld -% -% $Log: struct2cell.m,v $ -% Revision 1.1 2008/12/09 08:49:02 roboos -% new function -% - -c = struct2cell(struct(s)); - diff --git a/external/fieldtrip/@config/subsasgn.m b/external/fieldtrip/@config/subsasgn.m deleted file mode 100644 index fec3252..0000000 --- a/external/fieldtrip/@config/subsasgn.m +++ /dev/null @@ -1,38 +0,0 @@ -function y = subsasgn(x, index, val) - -% SUBSASGN Assign a new value to a specified field in a config objects and increment its assignment counter. - -if length(index)==1 - switch index.type - case '.' - y = set(x, index.subs, val); - case '{}' - error('Cell contents reference from a non-cell array object.'); - case '()' - error('Index exceeds matrix dimensions.'); - otherwise - error('Incorrect contents reference'); - end -elseif length(index)>1 && strcmp(index(1).type, '()') - if ~isfield(x, index(2).subs) - % an empty field should be added to all elements of the array - for i=1:numel(x) - y(i) = subsasgn(x(i), index(2:end), []); - end - else - % the field is already present in the array - y = x; - end - % the value of the field should only be changed for the specific element of the array - y(index(1).subs{1}) = subsasgn(y(index(1).subs{1}), index(2:end), val); -else - % use recursion to find the subfield that is being indexed - if ~isfield(x, index(1).subs) - % the subfield does not exists, create a new config subfield - x = subsasgn(x, index(1), config()); - end - y1 = subsref(x, index(1), false); - y2 = subsasgn(y1, index(2:end), val); - y = set(x, index(1).subs, y2); -end - diff --git a/external/fieldtrip/@config/subsref.m b/external/fieldtrip/@config/subsref.m deleted file mode 100644 index 2f3131e..0000000 --- a/external/fieldtrip/@config/subsref.m +++ /dev/null @@ -1,23 +0,0 @@ -function y = subsref(x, index, inc) - -% SUBSREF Return the value of a specified field in a config objects and increment its reference counter. - -if nargin<3 - inc = true; -end - -if length(index)==1 - switch index.type - case '.' - y = get(x, index.subs, inc); - case '{}' - error('Cell contents reference from a non-cell array object.'); - case '()' - y = x(index.subs{1}); - otherwise - error('Incorrect contents reference'); - end -else - % use recursion to find the subfield that is being indexed - y = subsref(subsref(x, index(1)), index(2:end)); -end diff --git a/external/fieldtrip/@uint64/abs.mexmaci b/external/fieldtrip/@uint64/abs.mexmaci deleted file mode 100755 index 064567a..0000000 Binary files a/external/fieldtrip/@uint64/abs.mexmaci and /dev/null differ diff --git a/external/fieldtrip/@uint64/abs.mexw32 b/external/fieldtrip/@uint64/abs.mexw32 deleted file mode 100644 index 0cebd97..0000000 Binary files a/external/fieldtrip/@uint64/abs.mexw32 and /dev/null differ diff --git a/external/fieldtrip/@uint64/abs.mexw64 b/external/fieldtrip/@uint64/abs.mexw64 deleted file mode 100644 index f0763a9..0000000 Binary files a/external/fieldtrip/@uint64/abs.mexw64 and /dev/null differ diff --git a/external/fieldtrip/@uint64/max.mexmaci b/external/fieldtrip/@uint64/max.mexmaci deleted file mode 100755 index 13b2ae6..0000000 Binary files a/external/fieldtrip/@uint64/max.mexmaci and /dev/null differ diff --git a/external/fieldtrip/@uint64/max.mexw32 b/external/fieldtrip/@uint64/max.mexw32 deleted file mode 100644 index 399e426..0000000 Binary files a/external/fieldtrip/@uint64/max.mexw32 and /dev/null differ diff --git a/external/fieldtrip/@uint64/max.mexw64 b/external/fieldtrip/@uint64/max.mexw64 deleted file mode 100644 index 799000f..0000000 Binary files a/external/fieldtrip/@uint64/max.mexw64 and /dev/null differ diff --git a/external/fieldtrip/@uint64/min.mexmaci b/external/fieldtrip/@uint64/min.mexmaci deleted file mode 100755 index abcfa75..0000000 Binary files a/external/fieldtrip/@uint64/min.mexmaci and /dev/null differ diff --git a/external/fieldtrip/@uint64/min.mexw32 b/external/fieldtrip/@uint64/min.mexw32 deleted file mode 100644 index fa5afbd..0000000 Binary files a/external/fieldtrip/@uint64/min.mexw32 and /dev/null differ diff --git a/external/fieldtrip/@uint64/min.mexw64 b/external/fieldtrip/@uint64/min.mexw64 deleted file mode 100644 index 393d56b..0000000 Binary files a/external/fieldtrip/@uint64/min.mexw64 and /dev/null differ diff --git a/external/fieldtrip/@uint64/minus.mexmaci b/external/fieldtrip/@uint64/minus.mexmaci deleted file mode 100755 index 03b1f08..0000000 Binary files a/external/fieldtrip/@uint64/minus.mexmaci and /dev/null differ diff --git a/external/fieldtrip/@uint64/minus.mexw32 b/external/fieldtrip/@uint64/minus.mexw32 deleted file mode 100644 index b01afa6..0000000 Binary files a/external/fieldtrip/@uint64/minus.mexw32 and /dev/null differ diff --git a/external/fieldtrip/@uint64/minus.mexw64 b/external/fieldtrip/@uint64/minus.mexw64 deleted file mode 100644 index 76c5d08..0000000 Binary files a/external/fieldtrip/@uint64/minus.mexw64 and /dev/null differ diff --git a/external/fieldtrip/@uint64/plus.mexmaci b/external/fieldtrip/@uint64/plus.mexmaci deleted file mode 100755 index 9052272..0000000 Binary files a/external/fieldtrip/@uint64/plus.mexmaci and /dev/null differ diff --git a/external/fieldtrip/@uint64/plus.mexw32 b/external/fieldtrip/@uint64/plus.mexw32 deleted file mode 100644 index 9fd88a7..0000000 Binary files a/external/fieldtrip/@uint64/plus.mexw32 and /dev/null differ diff --git a/external/fieldtrip/@uint64/plus.mexw64 b/external/fieldtrip/@uint64/plus.mexw64 deleted file mode 100644 index 83bc500..0000000 Binary files a/external/fieldtrip/@uint64/plus.mexw64 and /dev/null differ diff --git a/external/fieldtrip/@uint64/rdivide.mexmaci b/external/fieldtrip/@uint64/rdivide.mexmaci deleted file mode 100755 index 2c612e0..0000000 Binary files a/external/fieldtrip/@uint64/rdivide.mexmaci and /dev/null differ diff --git a/external/fieldtrip/@uint64/rdivide.mexw32 b/external/fieldtrip/@uint64/rdivide.mexw32 deleted file mode 100644 index e5bd037..0000000 Binary files a/external/fieldtrip/@uint64/rdivide.mexw32 and /dev/null differ diff --git a/external/fieldtrip/@uint64/rdivide.mexw64 b/external/fieldtrip/@uint64/rdivide.mexw64 deleted file mode 100644 index 2f4ebb9..0000000 Binary files a/external/fieldtrip/@uint64/rdivide.mexw64 and /dev/null differ diff --git a/external/fieldtrip/@uint64/times.mexmaci b/external/fieldtrip/@uint64/times.mexmaci deleted file mode 100755 index fa0ac2d..0000000 Binary files a/external/fieldtrip/@uint64/times.mexmaci and /dev/null differ diff --git a/external/fieldtrip/@uint64/times.mexw32 b/external/fieldtrip/@uint64/times.mexw32 deleted file mode 100644 index efd938d..0000000 Binary files a/external/fieldtrip/@uint64/times.mexw32 and /dev/null differ diff --git a/external/fieldtrip/@uint64/times.mexw64 b/external/fieldtrip/@uint64/times.mexw64 deleted file mode 100644 index 058754f..0000000 Binary files a/external/fieldtrip/@uint64/times.mexw64 and /dev/null differ diff --git a/external/fieldtrip/Contents.m b/external/fieldtrip/Contents.m new file mode 100644 index 0000000..db7878f --- /dev/null +++ b/external/fieldtrip/Contents.m @@ -0,0 +1,129 @@ +% FieldTrip is a Matlab toolbox for MEG and EEG analysis that is being +% developed at the Centre for Cognitive Neuroimaging of the Donders +% Institute for Brain, Cognition and Behaviour together with collaborating +% institutes. The development of FieldTrip is supported by funding from the +% BrainGain consortium. The FieldTrip software is released as open source +% under the GNU general public license. +% +% The toolbox includes algorithms for simple and advanced analysis of MEG +% and EEG data, such as time-frequency analysis, source reconstruction +% using dipoles, distributed sources and beamformers and non-parametric +% statistical testing. It supports the data formats of all major MEG +% systems (CTF, Neuromag, BTi) and of the most popular EEG systems, and new +% formats can be added easily. FieldTrip contains high-level functions that +% you can use to construct your own analysis protocol in Matlab. +% Furthermore, it easily allows developers to incorporate low-level +% algorithms for new EEG/MEG analysis methods. +% +% The FieldTrip software is free but copyrighted software, distributed +% under the terms of the GNU General Public Licence as published by +% the Free Software Foundation (either version 2, or at your option +% any later version). See the file COPYING for more details. +% +% The functions in this toolbox are copyrighted by their respective authors: +% Robert Oostenveld, DCCN, FCDC, SMI, MBFYS +% Jan-Matthijs Schoffelen, CCNi, FCDC +% Pascal Fries, FCDC +% Markus Bauer, FCDC +% Ole Jensen, FCDC +% Markus Siegel, FCDC, UKE +% Jens Schwarzbach, FCDC +% Eric Maris, DCC, FCDC +% Ingrid Nieuwenhuis, DCCN, FCDC +% Saskia Haegens, DCCN, FCDC +% +% Copyrights (C) 2008-2009, Donders Institute for Brain, Cognition and Behaviour, The Netherlands (DCCN, DCC, DCN) +% Copyrights (C) 2008-2009, Centre for Cognitive Neuroimaging in Glasgow, United Kingdom (CCNi) +% Copyrights (C) 2003-2008, F.C. Donders Centre, University Nijmegen, The Netherlands (FCDC) +% Copyrights (C) 2004-2007, Nijmegen Institute for Cognition and Information, The Netherlands (NICI) +% Copyrights (C) 2004-2005, Universitatsklinikum Hamburg-Eppendorf, Germany (UKE) +% Copyrights (C) 2003-2004, Center for Sensory Motor Interaction, University Aalborg, Denmark (SMI) +% Copyrights (C) 1999-2003, Department of Medical Physics, Radboud University Nijmegen, The Netherlands (MBFYS) +% +% The FieldTrip toolbox depend on functions from other toolboxes to do a +% large part of the actual work, such as reading data from binary files and +% forward and inverse modelling of the EEG/MEG. These low-level functions +% are contained in the private subdirectory. These other toolboxes on which +% the framework depends are copyrighted by their respective authors, see +% each individual matlab file for the details. +% +% Unauthorised copying and distribution of functions that are not +% explicitely covered by the GPL is not allowed! +% +% Below is an overview of the most important FieldTrip functions, sorted by +% category. You can get more details on a function by typing "help functionname" +% in Matlab. +% +% Preprocessing and reading data +% ft_definetrial +% ft_rejectartifact +% ft_rejectvisual +% ft_preprocessing +% ft_appenddata +% ft_resampledata +% ft_channelrepair +% ft_recodeevent +% ft_redefinetrial +% ft_read_header +% ft_read_data +% ft_read_event +% ft_read_mri +% +% Event-Related Fields or Potentials +% ft_timelockanalysis +% ft_timelockgrandaverage +% ft_timelockstatistics +% ft_singleplotER +% ft_topoplotER +% ft_multiplotER +% +% Frequency and Time-Frequency analysis +% ft_freqanalysis +% ft_freqanalysis_mtmfft +% ft_freqanalysis_mtmwelch +% ft_freqanalysis_mtmconvol +% ft_freqanalysis_wltconvol +% ft_freqanalysis_tfr +% ft_freqgrandaverage +% ft_freqdescriptives +% ft_freqstatistics +% ft_singleplotTFR +% ft_topoplotTFR +% ft_multiplotTFR +% +% Source analysis +% ft_dipolefitting +% ft_dipolesimulation +% ft_sourceanalysis +% ft_sourcegrandaverage +% ft_sourcedescriptives +% ft_sourcestatistics +% ft_sourceplot +% ft_sourceinterpolate +% ft_prepare_localspheres +% ft_prepare_singleshell +% ft_prepare_bemmodel +% ft_prepare_leadfield +% ft_prepare_atlas +% ft_volumelookup +% +% Statistical analysis +% ft_timelockstatistics +% ft_freqstatistics +% ft_sourcestatistics +% +% Plotting and display of data +% ft_prepare_layout +% ft_layoutplot +% ft_topoplot +% ft_topoplotER +% ft_topoplotTFR +% ft_multiplotER +% ft_multiplotTFR +% ft_singleplotER +% ft_singleplotTFR +% ft_sourceplot +% ft_clusterplot + +% Subversion does not use the Log keyword, use 'svn log ' or 'svn -v log | less' to get detailled information + diff --git a/external/fieldtrip/README b/external/fieldtrip/README index 6c6fc08..3970b04 100644 --- a/external/fieldtrip/README +++ b/external/fieldtrip/README @@ -1,17 +1,49 @@ -This is a special release of the FieldTrip toolbox code for inclusion -in SPM8. This release has wrapper functions that adhere to the -spm_xxx function naming style. The public functions are available -as ft_xxx, whereas all dependencies are hidden in the private -directory. If you are interested in using this toolbox independent -of SPM8, I suggest that you visit http://www.ru.nl/fcdonders/fieldtrip -and download a normal and more complete version. +FieldTrip is a Matlab toolbox for MEG and EEG analysis that is being +developed at the Donders Institute for Brain, Cognition and Behaviour +together with collaborating institutes. + +The toolbox includes algorithms for simple and advanced analysis +of MEG and EEG data, such as time-frequency analysis, source +reconstruction using dipoles, distributed sources and beamformers +and non-parametric statistical testing. It supports the data formats +of all major MEG systems (CTF, Neuromag, 4D/BTi) and of the most popular +EEG systems, and new formats can be added easily. FieldTrip contains +high-level functions that you can use to construct your own analysis +protocol in Matlab. Furthermore, it easily allows developers to +incorporate low-level algorithms for new EEG/MEG analysis methods. + +For more information please visit http://www.ru.nl/neuroimaging/fieldtrip + +The following files were downloaded from http://www.mathworks.com/matlabcentral/fileexchange + uimage.m + uimagesc.m + arrow.m + keep.m The FieldTrip software is free but copyrighted software, distributed under the terms of the GNU General Public Licence as published by the Free Software Foundation (either version 2, or at your option any later version). See the file COPYING for more details. -Copyright (C) 1999-2003, Department of Medical Physics, Radboud University Nijmegen, The Netherlands -Copyright (C) 2003-2005, Center for Sensory-Motor Interaction, Aalborg University, Denmark -Copyright (C) 2003-2008, F.C. Donders Centre for Cognitive Neuroimaging, Nijmegen, The Netherlands +The functions in this toolbox are copyrighted by their respective authors: + Robert Oostenveld, DCCN, FCDC, SMI, MBFYS + Jan-Mathijs Schoffelen, CCNi, FCDC + Pascal Fries, FCDC + Markus Bauer, FCDC + Ole Jensen, FCDC + Markus Siegel, FCDC, UKE + Jens Schwarzbach, FCDC + Eric Maris, DCC, FCDC + Ingrid Nieuwenhuis, DCCN, FCDC + Saskia Haegens, DCCN, FCDC + and others ... + +Copyright (C) 2008-2009, Donders Institute for Brain, Cognition and Behaviour, The Netherlands (DCCN, DCC, DCN) +Copyright (C) 2008-2009, Centre for Cognitive Neuroimaging in Glasgow, United Kingdom (CCNi) +Copyright (C) 2009-2009, Netherlands Institute for Neuroscience (NIN) +Copyright (C) 2003-2008, F.C. Donders Centre, University Nijmegen, The Netherlands (FCDC) +Copyright (C) 2004-2007, Nijmegen Institute for Cognition and Information, The Netherlands (NICI) +Copyright (C) 2004-2005, Universitatsklinikum Hamburg-Eppendorf, Germany (UKE) +Copyright (C) 2003-2004, Center for Sensory Motor Interaction, University Aalborg, Denmark (SMI) +Copyright (C) 1999-2003, Department of Medical Physics, Radboud University Nijmegen, The Netherlands (MBFYS) diff --git a/external/fieldtrip/besa2fieldtrip.m b/external/fieldtrip/besa2fieldtrip.m new file mode 100644 index 0000000..f533cab --- /dev/null +++ b/external/fieldtrip/besa2fieldtrip.m @@ -0,0 +1,426 @@ +function [data] = besa2fieldtrip(input) + +% BESA2FIELDTRIP reads and converts various BESA datafiles into a FieldTrip +% data structure, which subsequently can be used for statistical analysis +% or other analysis methods implemented in Fieldtrip. +% +% Use as +% [data] = besa2fieldtrip(filename) +% where the filename should point to a BESA datafile (or data that +% is exported by BESA). The output is a Matlab structure that is +% compatible with FieldTrip. +% +% The format of the output structure depends on the type of datafile: +% *.avr is converted to a structure similar to the output of TIMELOCKANALYSIS +% *.mul is converted to a structure similar to the output of TIMELOCKANALYSIS +% *.swf is converted to a structure similar to the output of TIMELOCKANALYSIS (*) +% *.tfc is converted to a structure similar to the output of FREQANALYSIS (*) +% *.dat is converted to a structure similar to the output of SOURCANALYSIS +% *.dat combined with a *.gen or *.generic is converted to a structure similar to the output of PREPROCESSING +% +% Note (*): If the BESA toolbox by Karsten Hochstatter is found on your +% Matlab path, the readBESAxxx functions will be used (where xxx=tfc/swf), +% alternatively the private functions from FieldTrip will be used. +% +% See also EEGLAB2FIELDTRIP + +% Copyright (C) 2005-2010, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: besa2fieldtrip.m 948 2010-04-21 18:02:21Z roboos $ + +fieldtripdefs + +if isstruct(input) && numel(input)>1 + % use a recursive call to convert multiple inputs + data = cell(size(input)); + for i=1:numel(input) + data{i} = besa2fieldtrip(input(i)); + end + return +end + +if isstruct(input) + fprintf('besa2fieldtrip: converting structure\n'); + + %---------------------TFC-------------------------------------------------% + if strcmp(input.structtype, 'besa_tfc') + %fprintf('BESA tfc\n'); + + data.time = input.latencies; + data.freq = input.frequencies; + temp_chans = char(input.channellabels'); + Nchan = size(temp_chans,1); + %{ + if strcmp(input.type,'COHERENCE_SQUARED') + % it contains coherence between channel pairs + fprintf('reading coherence between %d channel pairs\n', Nchan); + for i=1:Nchan + tmp = tokenize(deblank(temp_chans(i,:)), '-'); + data.labelcmb{i,1} = deblank(tmp{1}); + data.labelcmb{i,2} = deblank(tmp{2}); + data.label{i,1} = deblank(temp_chans(i,:)); + end + data.cohspctrm = input.data; + else + %} + % it contains power on channels + fprintf('reading power on %d channels\n', Nchan); + for i=1:Nchan + data.label{i,1} = deblank(temp_chans(i,:)); + end + data.powspctrm = input.data; + data.dimord = 'chan_freq_time'; + data.condition = input.condition; %not original Fieldtrip fieldname + + %end + + clear temp; + + %--------------------Image------------------------------------------------% + elseif strcmp(input.structtype, 'besa_image') + %fprintf('BESA image\n'); + data.avg.pow = input.data; + xTemp = input.xcoordinates; + yTemp = input.ycoordinates; + zTemp = input.zcoordinates; + data.xgrid = xTemp; + data.ygrid = yTemp; + data.zgrid = zTemp; + nx = size(data.xgrid,2); + ny = size(data.ygrid,2); + nz = size(data.zgrid,2); + % Number of points in each dimension + data.dim = [nx ny nz]; + % Array with all possible positions (x,y,z) + data.pos = WritePosArray(xTemp,yTemp,zTemp,nx,ny,nz); + data.inside = 1:prod(data.dim);%as in Fieldtrip - not correct + data.outside = []; + + %--------------------Source Waveform--------------------------------------% + elseif strcmp(input.structtype, 'besa_sourcewaveforms') + %fprintf('BESA source waveforms\n'); + data.label = input.labels'; %not the same as Fieldtrip! + data.dimord = 'chan_time'; + data.fsample = input.samplingrate; + data.time = input.latencies / 1000.0; + data.avg = input.waveforms'; + data.cfg.filename = input.datafile; + + %--------------------Data Export------------------------------------------% + elseif strcmp(input.structtype, 'besa_channels') + %fprintf('BESA data export\n'); + + if isfield(input,'datatype') + switch input.datatype + case {'Raw_Data','Epoched_Data','Segment'} + data.fsample = input.samplingrate; + data.label = input.channellabels'; + for k=1:size(input.data,2) + data.time{1,k} = input.data(k).latencies / 1000.0'; + data.trial{1,k} = input.data(k).amplitudes'; + end + otherwise + fprintf('datatype other than Raw_Data, Epoched or Segment'); + end + else + fprintf('workspace created with earlier MATLAB version'); + end + + %--------------------else-------------------------------------------------% + else + error('unrecognized format of the input structure'); + end + +elseif ischar(input) + fprintf('besa2fieldtrip: reading from file\n'); + + % This function can either use the reading functions included in FieldTrip + % (with contributions from Karsten, Vladimir and Robert), or the official + % released functions by Karsten Hoechstetter from BESA. The functions in the + % official toolbox have precedence. + hasbesa = hastoolbox('besa',1, 1); + + type = filetype(input); + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + if strcmp(type, 'besa_avr') && hasbesa + fprintf('reading ERP/ERF\n'); + % this should be similar to the output of TIMELOCKANALYSIS + tmp = readBESAavr(input); + % convert into a TIMELOCKANALYSIS compatible data structure + data = []; + data.label = []; + if isfield(tmp, 'ChannelLabels'), + data.label = fixlabels(tmp.ChannelLabels); + end; + data.avg = tmp.Data; + data.time = tmp.Time / 1000; % convert to seconds + data.fsample = 1000/tmp.DI; + data.dimord = 'chan_time'; + elseif strcmp(type, 'besa_avr') && ~hasbesa + fprintf('reading ERP/ERF\n'); + % this should be similar to the output of TIMELOCKANALYSIS + tmp = read_besa_avr(input); + % convert into a TIMELOCKANALYSIS compatible data structure + data = []; + data.label = fixlabels(tmp.label); + data.avg = tmp.data; + data.time = (0:(tmp.npnt-1)) * tmp.di + tmp.tsb; + data.time = data.time / 1000; % convert to seconds + data.fsample = 1000/tmp.di; + data.dimord = 'chan_time'; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + elseif strcmp(type, 'besa_mul') && hasbesa + fprintf('reading ERP/ERF\n'); + % this should be similar to the output of TIMELOCKANALYSIS + tmp = readBESAmul(input); + % convert into a TIMELOCKANALYSIS compatible data structure + data = []; + data.label = tmp.ChannelLabels(:); + data.avg = tmp.data'; + data.time = (0:(tmp.Npts-1)) * tmp.DI + tmp.TSB; + data.time = data.time / 1000; %convert to seconds + data.fsample = 1000/tmp.DI; + data.dimord = 'chan_time'; + elseif strcmp(type, 'besa_mul') && ~hasbesa + fprintf('reading ERP/ERF\n'); + % this should be similar to the output of TIMELOCKANALYSIS + tmp = read_besa_mul(input); + % convert into a TIMELOCKANALYSIS compatible data structure + data = []; + data.label = tmp.label(:); + data.avg = tmp.data; + data.time = (0:(tmp.TimePoints-1)) * tmp.SamplingInterval_ms_ + tmp.BeginSweep_ms_; + data.time = data.time / 1000; % convert to seconds + data.fsample = 1000/tmp.SamplingInterval_ms_; + data.dimord = 'chan_time'; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + elseif strcmp(type, 'besa_sb') + if hasbesa + fprintf('reading preprocessed channel data using BESA toolbox\n'); + else + error('this data format requires the BESA toolbox'); + end + [p, f, x] = fileparts(input); + input = fullfile(p, [f '.dat']); + [time,buf,ntrial] = readBESAsb(input); + time = time/1000; % convert from ms to sec + nchan = size(buf,1); + ntime = size(buf,3); + + % convert into a PREPROCESSING compatible data structure + data = []; + data.trial = {}; + data.time = {}; + for i=1:ntrial + data.trial{i} = reshape(buf(:,i,:), [nchan, ntime]); + data.time{i} = time; + end + data.label = {}; + for i=1:size(buf,1) + data.label{i,1} = sprintf('chan%03d', i); + end + data.fsample = 1/(time(2)-time(1)); % time is already in seconds + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + elseif strcmp(type, 'besa_tfc') && hasbesa + fprintf('reading time-frequency representation using BESA toolbox\n'); + % this should be similar to the output of FREQANALYSIS + tfc = readBESAtfc(input); + Nchan = size(tfc.ChannelLabels,1); + % convert into a FREQANALYSIS compatible data structure + data = []; + data.time = tfc.Time(:)'; + data.freq = tfc.Frequency(:)'; + if isfield(tfc, 'DataType') && strcmp(tfc.DataType, 'COHERENCE_SQUARED') + % it contains coherence between channel pairs + fprintf('reading coherence between %d channel pairs\n', Nchan); + for i=1:Nchan + tmp = tokenize(deblank(tfc.ChannelLabels(i,:)), '-'); + data.labelcmb{i,1} = tmp{1}; + data.labelcmb{i,2} = tmp{2}; + end + data.cohspctrm = permute(tfc.Data, [1 3 2]); + else + % it contains power on channels + fprintf('reading power on %d channels\n', Nchan); + for i=1:Nchan + data.label{i,1} = deblank(tfc.ChannelLabels(i,:)); + end + data.powspctrm = permute(tfc.Data, [1 3 2]); + end + data.dimord = 'chan_freq_time'; + data.condition = tfc.ConditionName; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + elseif strcmp(type, 'besa_tfc') && ~hasbesa + fprintf('reading time-frequency representation\n'); + % this should be similar to the output of FREQANALYSIS + [ChannelLabels, Time, Frequency, Data, Info] = read_besa_tfc(input); + Nchan = size(ChannelLabels,1); + % convert into a FREQANALYSIS compatible data structure + data = []; + data.time = Time * 1e-3; % convert to seconds; + data.freq = Frequency; + if isfield(Info, 'DataType') && strcmp(Info.DataType, 'COHERENCE_SQUARED') + % it contains coherence between channel pairs + fprintf('reading coherence between %d channel pairs\n', Nchan); + for i=1:Nchan + tmp = tokenize(deblank(ChannelLabels(i,:)), '-'); + data.labelcmb{i,1} = tmp{1}; + data.labelcmb{i,2} = tmp{2}; + end + data.cohspctrm = permute(Data, [1 3 2]); + else + % it contains power on channels + fprintf('reading power on %d channels\n', Nchan); + for i=1:Nchan + data.label{i} = deblank(ChannelLabels(i,:)); + end + data.powspctrm = permute(Data, [1 3 2]); + end + data.dimord = 'chan_freq_time'; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + elseif strcmp(type, 'besa_swf') && hasbesa + fprintf('reading source waveform using BESA toolbox\n'); + swf = readBESAswf(input); + % convert into a TIMELOCKANALYSIS compatible data structure + data = []; + data.label = fixlabels(swf.waveName); + data.avg = swf.data; + data.time = swf.Time * 1e-3; % convert to seconds + data.fsample = 1/(data.time(2)-data.time(1)); + data.dimord = 'chan_time'; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + elseif strcmp(type, 'besa_swf') && ~hasbesa + fprintf('reading source waveform\n'); + % hmm, I guess that this should be similar to the output of TIMELOCKANALYSIS + tmp = read_besa_swf(input); + % convert into a TIMELOCKANALYSIS compatible data structure + data = []; + data.label = fixlabels(tmp.label); + data.avg = tmp.data; + data.time = (0:(tmp.npnt-1)) * tmp.di + tmp.tsb; + data.time = data.time / 1000; % convert to seconds + data.fsample = 1000/tmp.di; + data.dimord = 'chan_time'; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + elseif strcmp(type, 'besa_src') && hasbesa + src = readBESAimage(input); + data.xgrid = src.Coordinates.X; + data.ygrid = src.Coordinates.Y; + data.zgrid = src.Coordinates.Z; + data.avg.pow = src.Data; + data.dim = size(src.Data); + [X, Y, Z] = ndgrid(data.xgrid, data.ygrid, data.zgrid); + data.pos = [X(:) Y(:) Z(:)]; + % cannot determine which voxels are inside the brain volume + data.inside = 1:prod(data.dim); + data.outside = []; + elseif strcmp(type, 'besa_src') && ~hasbesa + src = read_besa_src(input); + data.xgrid = linspace(src.X(1), src.X(2), src.X(3)); + data.ygrid = linspace(src.Y(1), src.Y(2), src.Y(3)); + data.zgrid = linspace(src.Z(1), src.Z(2), src.Z(3)); + data.avg.pow = src.vol; + data.dim = size(src.vol); + [X, Y, Z] = ndgrid(data.xgrid, data.ygrid, data.zgrid); + data.pos = [X(:) Y(:) Z(:)]; + % cannot determine which voxels are inside the brain volume + data.inside = 1:prod(data.dim); + data.outside = []; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + elseif strcmp(type, 'besa_pdg') + % hmmm, I have to think about this one... + error('sorry, pdg is not yet supported'); + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + else + error('unrecognized file format for importing BESA data'); + end + +end % isstruct || ischar + + +% construct and add a configuration to the output +cfg = []; + +if isstruct(input) && isfield(input,'datafile') + cfg.filename = input.datafile; +elseif isstruct(input) && ~isfield(input,'datafile') + cfg.filename = 'Unknown'; +elseif ischar(input) + cfg.filename = input; +end + +% add the version details of this function call to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: besa2fieldtrip.m 948 2010-04-21 18:02:21Z roboos $'; +data.cfg = cfg; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION that fixes the channel labels, should be a cell-array +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [newlabels] = fixlabels(labels) +if iscell(labels) && length(labels)>1 + % seems to be ok + newlabels = labels; +elseif iscell(labels) && length(labels)==1 + % could be a cell with a single long string in it + if length(tokenize(labels{1}, ' '))>1 + % seems like a long string that accidentaly ended up in a single + cell + newlabels = tokenize(labels{1}, ' '); + else + % seems to be ok + newlabels = labels; + end +elseif ischar(labels) && any(size(labels)==1) + newlabels = tokenize(labels(:)', ' '); % also ensure that it is a row-string +elseif ischar(labels) && ~any(size(labels)==1) + for i=1:size(labels) + newlabels{i} = strtrim(labels(i,:)); + end +end +% convert to column +newlabels = newlabels(:); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [PArray] = WritePosArray(x,y,z,mx,my,mz) +A1 = repmat(x,1,my*mz); +A21 = repmat(y,mx,mz); +A2 = reshape(A21,1,mx*my*mz); +A31 = repmat(z,mx*my,1); +A3 = reshape(A31,1,mx*my*mz); +PArray = [A1;A2;A3]'; diff --git a/external/fieldtrip/connectivity/ft_connectivity_corr.m b/external/fieldtrip/connectivity/ft_connectivity_corr.m new file mode 100644 index 0000000..9b8f741 --- /dev/null +++ b/external/fieldtrip/connectivity/ft_connectivity_corr.m @@ -0,0 +1,139 @@ +function [c, v, n] = ft_connectivity_corr(input, varargin) + +% FIXME write documentation +% takes in a square csd or cov matrix, calculates the partialised +% csd, or partialised cov, if specified, then either normalizes by power (in +% the case of coherence) or returns the partialized csd (if the goal is to +% calculate partial granger, for example. + +%FIXME hasrpt should go, because first dim should always be rpt, which could be +%either leave one out or single observations +hasrpt = keyval('hasrpt', varargin{:}); if isempty(hasrpt), hasrpt = 0; end +hasjck = keyval('hasrpt', varargin{:}); if isempty(hasrpt), hasrpt = 0; end +cmplx = keyval('complex', varargin{:}); if isempty(cmplx), cmplx = 'abs'; end +feedback = keyval('feedback', varargin{:}); if isempty(feedback), feedback = 'none'; end +dimord = keyval('dimord', varargin{:}); +powindx = keyval('powindx', varargin{:}); +pownorm = keyval('pownorm', varargin{:}); if isempty(pownorm), pownorm = 0; end +pchanindx = keyval('pchanindx', varargin{:}); +allchanindx = keyval('allchanindx', varargin{:}); + +if isempty(dimord) + error('input parameters should contain a dimord'); +end + +siz = size(input); +if ~hasrpt, + siz = [1 siz]; + input = reshape(input, siz); +end + +% do partialisation if necessary +if ~isempty(pchanindx), + % partial spectra are computed as in Rosenberg JR et al (1998) J. + % Neuroscience Methods, equation 38 + + chan = allchanindx; + nchan = numel(chan); + pchan = pchanindx; + npchan = numel(pchan); + newsiz = siz; + newsiz(2:3) = numel(chan); % size of partialised csd + + A = zeros(newsiz); + + % FIXME this only works for data without time dimension + if numel(siz)>4, error('this only works for data without time'); end + for j = 1:siz(1) %rpt loop + AA = reshape(input(j, chan, chan, : ), [nchan nchan siz(4:end)]); + AB = reshape(input(j, chan, pchan,: ), [nchan npchan siz(4:end)]); + BA = reshape(input(j, pchan, chan, : ), [npchan nchan siz(4:end)]); + BB = reshape(input(j, pchan, pchan, :), [npchan npchan siz(4:end)]); + for k = 1:siz(4) %freq loop + A(j,:,:,k) = AA(:,:,k) - AB(:,:,k)*pinv(BB(:,:,k))*BA(:,:,k); + end + end + input = A; + siz = size(input); +else + % do nothing +end + +if (length(strfind(dimord, 'chan'))~=2 || length(strfind(dimord, 'pos'))>0) && ~isempty(powindx), + %crossterms are not described with chan_chan_therest, but are linearly indexed + outsum = zeros(siz(2:end)); + outssq = zeros(siz(2:end)); + + progress('init', feedback, 'computing metric...'); + for j = 1:siz(1) + progress(j/siz(1), 'computing metric for replicate %d from %d\n', j, siz(1)); + if pownorm + p1 = reshape(input(j,powindx(:,1),:,:,:), siz(2:end)); + p2 = reshape(input(j,powindx(:,2),:,:,:), siz(2:end)); + denom = sqrt(p1.*p2); clear p1 p2 + else + denom = 1; + end + outsum = outsum + complexeval(reshape(input(j,:,:,:,:), siz(2:end))./denom, cmplx); + outssq = outssq + complexeval(reshape(input(j,:,:,:,:), siz(2:end))./denom, cmplx).^2; + end + progress('close'); + +elseif length(strfind(dimord, 'chan'))==2 || length(strfind(dimord, 'pos'))==2, + %crossterms are described by chan_chan_therest + + outsum = zeros(siz(2:end)); + outssq = zeros(siz(2:end)); + progress('init', feedback, 'computing metric...'); + for j = 1:siz(1) + progress(j/siz(1), 'computing metric for replicate %d from %d\n', j, siz(1)); + if pownorm + p1 = zeros([siz(2) 1 siz(4:end)]); + p2 = zeros([1 siz(3) siz(4:end)]); + for k = 1:siz(2) + p1(k,1,:,:,:,:) = input(j,k,k,:,:,:,:); + p2(1,k,:,:,:,:) = input(j,k,k,:,:,:,:); + end + p1 = p1(:,ones(1,siz(3)),:,:,:,:); + p2 = p2(ones(1,siz(2)),:,:,:,:,:); + denom = sqrt(p1.*p2); clear p1 p2; + else + denom = 1; + end + outsum = outsum + complexeval(reshape(input(j,:,:,:,:,:,:), siz(2:end))./denom, cmplx); + outssq = outssq + complexeval(reshape(input(j,:,:,:,:,:,:), siz(2:end))./denom, cmplx).^2; + end + progress('close'); + +end +n = siz(1); +c = outsum./n; + +if hasrpt, + if hasjack + bias = (n-1).^2; + else + bias = 1; + end + + v = bias*(outssq - (outsum.^2)./n)./(n - 1); +else + v = []; +end + +function [c] = complexeval(c, str) + +switch str + case 'complex' + %do nothing + case 'abs' + c = abs(c); + case 'angle' + c = angle(c); + case 'imag' + c = imag(c); + case 'real' + c = real(c); + otherwise + error('complex = ''%s'' not supported', cmplx); +end diff --git a/external/fieldtrip/connectivity/ft_connectivity_dtf.m b/external/fieldtrip/connectivity/ft_connectivity_dtf.m new file mode 100644 index 0000000..d5fc4a3 --- /dev/null +++ b/external/fieldtrip/connectivity/ft_connectivity_dtf.m @@ -0,0 +1,54 @@ +function [dtf, dtfvar, n] = ft_connectivity_dtf(cfg, input, hasjack) + +siz = size(input); +n = siz(1); +ncmb = siz(2); +outsum = zeros(siz(2:end)); +outssq = zeros(siz(2:end)); + +if isempty(cfg.powindx) + % data are represented as chan_chan_therest + for j = 1:n + tmph = reshape(input(j,:,:,:,:), siz(2:end)); + den = sum(abs(tmph).^2,2); + tmpdtf = abs(tmph)./sqrt(repmat(den, [1 siz(2) 1 1 1])); + %if ~isempty(cfg.submethod), tmpdtf = baseline(tmpdtf, cfg.submethod, baselineindx); end + outsum = outsum + tmpdtf; + outssq = outssq + tmpdtf.^2; + %tmp = outsum; tmp(2,1,:,:) = outsum(1,2,:,:); tmp(1,2,:,:) = outsum(2,1,:,:); outsum = tmp; + %tmp = outssq; tmp(2,1,:,:) = outssq(1,2,:,:); tmp(1,2,:,:) = outssq(2,1,:,:); outssq = tmp; + % swap the order of the cross-terms to achieve the convention such that + % labelcmb {'a' 'b'} represents: a->b + end +else + % data are linearly indexed + sortindx = [0 0 0 0]; + for k = 1:ncmb + iauto1 = find(sum(cfg.powindx==cfg.powindx(k,1),2)==2); + iauto2 = find(sum(cfg.powindx==cfg.powindx(k,2),2)==2); + icross1 = k; + icross2 = find(sum(cfg.powindx==cfg.powindx(ones(ncmb,1)*k,[2 1]),2)==2); + indx = [iauto1 icross2 icross1 iauto2]; + + if isempty(intersect(sortindx, sort(indx), 'rows')), + sortindx = [sortindx;sort(indx)]; + for j = 1:n + tmph = reshape(input(j,indx,:,:), [2 2 siz(3:end)]); + den = sum(abs(tmph).^2,2); + tmpdtf = reshape(abs(tmph)./sqrt(repmat(den, [1 2 1 1])), [4 siz(3:end)]); + outsum(indx,:) = outsum(indx,:) + tmpdtf([1 3 2 4],:); + outssq(indx,:) = outssq(indx,:) + tmpdtf([1 3 2 4],:).^2; + % swap the order of the cross-terms to achieve the convention such that + % labelcmb {'a' 'b'} represents: a->b + end + end + end +end +dtf = outsum./n; + +if n>1, %FIXME this is strictly only true for jackknife, otherwise other bias is needed + bias = (n - 1).^2; + dtfvar = bias.*(outssq - (outsum.^2)/n)./(n-1); +else + dtfvar = []; +end diff --git a/external/fieldtrip/connectivity/ft_connectivity_granger.m b/external/fieldtrip/connectivity/ft_connectivity_granger.m new file mode 100644 index 0000000..06c6bc5 --- /dev/null +++ b/external/fieldtrip/connectivity/ft_connectivity_granger.m @@ -0,0 +1,158 @@ +function [granger, v, n] = ft_connectivity_granger(H, Z, S, fs, hasjack, powindx) + +%Usage: causality = hz2causality(H,S,Z,fs); +%Inputs: transfer = transfer function, +% crsspctrm = 3-D spectral matrix; +% noisecov = noise covariance, +% fs = sampling rate +%Outputs: granger (Granger causality between all channels) +% : auto-causality spectra are set to zero +% Reference: Brovelli, et. al., PNAS 101, 9849-9854 (2004). +%M. Dhamala, UF, August 2006. + +%FIXME speed up code and check +siz = size(H); +if numel(siz)==4, + siz(5) = 1; +end +n = siz(1); +Nc = siz(2); + +outsum = zeros(siz(2:end)); +outssq = zeros(siz(2:end)); + +if isempty(powindx), + % data are chan_chan_therest + for kk = 1:n + for ii = 1:Nc + for jj = 1:Nc + if ii ~=jj, + zc = reshape(Z(kk,jj,jj,:) - Z(kk,ii,jj,:).^2./Z(kk,ii,ii,:),[1 1 1 1 siz(5)]); + zc = repmat(zc,[1 1 1 siz(4) 1]); + numer = reshape(abs(S(kk,ii,ii,:,:)),[1 1 siz(4:end)]); + denom = reshape(abs(S(kk,ii,ii,:,:)-zc.*abs(H(kk,ii,jj,:,:)).^2./fs),[1 1 siz(4:end)]); + outsum(jj,ii,:,:) = outsum(jj,ii,:,:) + log(numer./denom); + outssq(jj,ii,:,:) = outssq(jj,ii,:,:) + (log(numer./denom)).^2; + end + end + outsum(ii,ii,:,:) = 0;%self-granger set to zero + end + end +elseif ~iscell(powindx) && ~isstruct(powindx) + % data are linearly indexed + for k = 1:Nc + for j = 1:n + iauto1 = find(sum(powindx==powindx(k,1),2)==2); + iauto2 = find(sum(powindx==powindx(k,2),2)==2); + icross1 = k; + icross2 = find(sum(powindx==powindx(ones(Nc,1)*k,[2 1]),2)==2); + zc = Z(j,iauto2,:) - Z(j,icross1,:).^2./Z(j,iauto1,:); + numer = abs(S(j,iauto1,:)); + denom = abs(S(j,iauto1,:)-zc.*abs(H(j,icross1,:)).^2./fs); + outsum(icross2,:) = outsum(icross2,:) + reshape(log(numer./denom), [1 siz(3:end)]); + outssq(icross2,:) = outssq(icross2,:) + reshape((log(numer./denom)).^2, [1 siz(3:end)]); + end + end +elseif iscell(powindx) + % blockwise granger + % H = transfer function nchan x nchan x nfreq + % Z = noise covariance nchan x nchan + % S = crosspectrum nchan x nchan x nfreq + % powindx{1} is a list of indices for block1 + % powindx{2} is a list of indices for block2 + + %FIXME rewrite to allow for multiple blocks + %FIXME change cfg.block functionality in this case + %cfg.blockindx = {{list of channel names} [list of block indices]} + block1 = powindx{1}(:); + block2 = powindx{2}(:); + + n = size(H,1); + nchan = size(H,2); + nfreq = size(H,4); + + n1 = numel(block1); + n2 = numel(block2); + + % reorder + S = S(:,[block1;block2],[block1;block2],:); + H = H(:,[block1;block2],[block1;block2],:); + Z = Z(:,[block1;block2],[block1;block2]); + + indx1 = 1:n1; + indx2 = (n1+1):(n1+n2); + + outsum = zeros(2,2,nfreq); + outssq = zeros(2,2,nfreq); + for k = 1:n + tmpZ = reshape(Z(k,:,:), [nchan nchan]); + + % projection matrix for block2 -> block1 + P1 = [eye(n1) zeros(n1,n2); + -tmpZ(indx2,indx1)/tmpZ(indx1,indx1) eye(n2)]; + + % projection matrix for block1 -> block2 + P2 = [ eye(n1) -tmpZ(indx1,indx2)/tmpZ(indx2,indx2); + zeros(n2,n1) eye(n2)]; + + % invert only once + invP1 = inv(P1); + invP2 = inv(P2); + for jj = 1:nfreq + % post multiply transfer matrix with the inverse of the projection matrix + % this is equivalent to time domain pre multiplication with P + Sj = reshape(S(k,:,:,jj), [nchan nchan]); + Zj = tmpZ(:,:); + H1 = reshape(H(k,:,:,jj), [nchan nchan])*invP1; + H2 = reshape(H(k,:,:,jj), [nchan nchan])*invP2; + num1 = abs(det(Sj(indx1,indx1))); % numerical round off leads to tiny imaginary components + num2 = abs(det(Sj(indx2,indx2))); % numerical round off leads to tiny imaginary components + denom1 = abs(det(H1(indx1,indx1)*Zj(indx1,indx1)*H1(indx1,indx1)')); + denom2 = abs(det(H2(indx2,indx2)*Zj(indx2,indx2)*H2(indx2,indx2)')); + %rH1 = real(H1(indx1,indx1)); + %rH2 = real(H2(indx2,indx2)); + %iH1 = imag(H1(indx1,indx1)); + %iH2 = imag(H2(indx2,indx2)); + %h1 = rH1*Zj(indx1,indx1)*rH1' + iH1*Zj(indx1,indx1)*iH1'; + %h2 = rH2*Zj(indx2,indx2)*rH2' + iH2*Zj(indx2,indx2)*iH2'; + %denom1 = det(h1); + %denom2 = det(h2); + + outsum(2,1,jj) = log( num1./denom1 ) + outsum(2,1,jj); + outsum(1,2,jj) = log( num2./denom2 ) + outsum(1,2,jj); + outssq(2,1,jj) = log( num1./denom1 ).^2 + outssq(2,1,jj); + outssq(1,2,jj) = log( num2./denom2 ).^2 + outssq(1,2,jj); + end + end +elseif isstruct(powindx) + %blockwise conditional + + n = size(H,1); + ncmb = size(H,2); + nfreq = size(H,3); + ncnd = size(powindx.cmbindx,1); + + outsum = zeros(ncnd, nfreq); + outssq = zeros(ncnd, nfreq); + for k = 1:n + tmpS = reshape(S, [ncmb nfreq]); + tmpH = reshape(H, [ncmb nfreq]); + tmpZ = reshape(Z, [ncmb 1]); + tmp = blockwise_conditionalgranger(tmpS,tmpH,tmpZ,powindx.cmbindx,powindx.n); + + outsum = outsum + tmp; + outssq = outssq + tmp.^2; + end +end + +granger = outsum./n; +if n>1, + if hasjack + bias = (n-1).^2; + else + bias = 1; + end + v = bias*(outssq - (outsum.^2)./n)./(n - 1); +else + v = []; +end diff --git a/external/fieldtrip/connectivity/ft_connectivity_pdc.m b/external/fieldtrip/connectivity/ft_connectivity_pdc.m new file mode 100644 index 0000000..682faa8 --- /dev/null +++ b/external/fieldtrip/connectivity/ft_connectivity_pdc.m @@ -0,0 +1,52 @@ +function [pdc, pdcvar, n] = ft_connectivity_pdc(cfg, input, hasjack) + +if nargin==2, + hasjack = 0; +end + +%crossterms are described by chan_chan_therest +siz = size(input); +n = siz(1); + +outsum = zeros(siz(2:end)); +outssq = zeros(siz(2:end)); + +%computing pdc is easiest on the inverse of the transfer function +pdim = prod(siz(4:end)); +tmpinput = reshape(input, [siz(1:3) pdim]); +progress('init', cfg.feedback, 'inverting the transfer function...'); +for k = 1:n + progress(k/n, 'inverting the transfer function for replicate %d from %d\n', k, n); + tmp = reshape(tmpinput(k,:,:,:), [siz(2:3) pdim]); + for m = 1:pdim + tmp(:,:,m) = inv(tmp(:,:,m)); + end + tmpinput(k,:,:,:) = tmp; +end +progress('close'); +input = reshape(tmpinput, siz); + +progress('init', cfg.feedback, 'computing metric...'); +for j = 1:n + progress(j/n, 'computing metric for replicate %d from %d\n', j, n); + invh = reshape(input(j,:,:,:,:), siz(2:end)); + den = sum(abs(invh).^2,1); + tmppdc = abs(invh)./sqrt(repmat(den, [siz(2) 1 1 1 1])); + %if ~isempty(cfg.submethod), tmppdc = baseline(tmppdc, cfg.submethod, baselineindx); end + outsum = outsum + tmppdc; + outssq = outssq + tmppdc.^2; +end +progress('close'); + +pdc = outsum./n; + +if n>1, + if hasjack + bias = (n-1).^2; + else + bias = 1; + end + pdcvar = bias*(outssq - (outsum.^2)./n)./(n - 1); +else + pdcvar = []; +end diff --git a/external/fieldtrip/connectivity/ft_connectivity_psi.m b/external/fieldtrip/connectivity/ft_connectivity_psi.m new file mode 100644 index 0000000..76cd01e --- /dev/null +++ b/external/fieldtrip/connectivity/ft_connectivity_psi.m @@ -0,0 +1,108 @@ +function [c, v, n] = ft_connectivity_psi(cfg, input, hasrpt, hasjack) + +if nargin==2, + hasrpt = 0; + hasjack = 0; +elseif nargin==3, + hasjack = 0; +end + +if (length(strfind(cfg.dimord, 'chan'))~=2 || length(strfind(cfg.dimord, 'pos'))>0) && isfield(cfg, 'powindx') && ~isempty(cfg.powindx), + %crossterms are not described with chan_chan_therest, but are linearly indexed + + siz = size(input); + if ~hasrpt, + siz = [1 siz]; + input = reshape(input, siz); + end + + outsum = zeros(siz(2:end)); + outssq = zeros(siz(2:end)); + pvec = [2 setdiff(1:numel(siz),2)]; + + progress('init', cfg.feedback, 'computing metric...'); + %first compute coherency and then phaseslopeindex + for j = 1:siz(1) + progress(j/siz(1), 'computing metric for replicate %d from %d\n', j, siz(1)); + c = reshape(input(j,:,:,:,:), siz(2:end)); + p1 = abs(reshape(input(j,cfg.powindx(:,1),:,:,:), siz(2:end))); + p2 = abs(reshape(input(j,cfg.powindx(:,2),:,:,:), siz(2:end))); + + p = ipermute(phaseslope(permute(c./sqrt(p1.*p2), pvec), cfg.nbin, cfg.normalize), pvec); + + outsum = outsum + p; + outssq = outssq + p.^2; + end + progress('close'); + +elseif length(strfind(cfg.dimord, 'chan'))==2 || length(strfind(cfg.dimord, 'pos'))==2, + %crossterms are described by chan_chan_therest + + siz = size(input); + if ~hasrpt, + siz = [1 siz]; + input = reshape(input, siz); + end + + outsum = zeros(siz(2:end)); + outssq = zeros(siz(2:end)); + pvec = [3 setdiff(1:numel(siz),3)]; + + progress('init', cfg.feedback, 'computing metric...'); + for j = 1:siz(1) + progress(j/siz(1), 'computing metric for replicate %d from %d\n', j, siz(1)); + p1 = zeros([siz(2) 1 siz(4:end)]); + p2 = zeros([1 siz(3) siz(4:end)]); + for k = 1:siz(2) + p1(k,1,:,:,:,:) = input(j,k,k,:,:,:,:); + p2(1,k,:,:,:,:) = input(j,k,k,:,:,:,:); + end + c = reshape(input(j,:,:,:,:,:,:), siz(2:end)); + p1 = p1(:,ones(1,siz(3)),:,:,:,:); + p2 = p2(ones(1,siz(2)),:,:,:,:,:); + p = ipermute(phaseslope(permute(c./sqrt(p1.*p2),pvec),cfg.nbin, cfg.normalize),pvec); + outsum = outsum + p; + outssq = outssq + p.^2; + end + progress('close'); + +end + +n = siz(1); +c = outsum./n; + +if hasrpt, + if hasjack + bias = (n-1).^2; + else + bias = 1; + end + + v = bias*(outssq - (outsum.^2)./n)./(n - 1); +else + v = []; +end + +%--------------------------------------- +function [y] = phaseslope(x, n, norm) + +m = size(x, 1); %total number of frequency bins +y = zeros(size(x)); +x(1:end-1,:,:,:,:) = conj(x(1:end-1,:,:,:,:)).*x(2:end,:,:,:,:); + +if strcmp(norm, 'yes') + coh = zeros(size(x)); + coh(1:end-1,:,:,:,:) = (abs(x(1:end-1,:,:,:,:)) .* abs(x(2:end,:,:,:,:))) + 1; + %FIXME why the +1? get the coherence + for k = 1:m + begindx = max(1,k-n); + endindx = min(m,k+n); + y(k,:,:,:,:) = imag(sum(x(begindx:endindx,:,:,:,:)./coh(begindx:endindx,:,:,:,:))); + end +else + for k = 1:m + begindx = max(1,k-n); + endindx = min(m,k+n); + y(k,:,:,:,:) = imag(sum(x(begindx:endindx,:,:,:,:))); + end +end diff --git a/external/fieldtrip/fieldtripdefs.m b/external/fieldtrip/fieldtripdefs.m new file mode 100644 index 0000000..b86dddc --- /dev/null +++ b/external/fieldtrip/fieldtripdefs.m @@ -0,0 +1,119 @@ +function fieldtripdefs + +% FIELDTRIPDEFS is called at the begin of all FieldTrip functions and +% contains some defaults and path settings +% +% Note that this should be a function and not a script, otherwise the +% hastoolbox function appears not be found in fieldtrip/private. + +% Copyright (C) 2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: fieldtripdefs.m 1419 2010-07-16 07:04:14Z roboos $ + +% set the global defaults, the checkconfig function will copy these into the local configurations +global ft_default +if ~isfield(ft_default, 'trackconfig'), ft_default.trackconfig = 'off'; end % cleanup, report, off +if ~isfield(ft_default, 'checkconfig'), ft_default.checkconfig = 'loose'; end % pedantic, loose, silent +if ~isfield(ft_default, 'checksize'), ft_default.checksize = 1e5; end % number in bytes, can be inf + +% this is for Matlab version specific backward compatibility support +% the version specific path should only be added once in every session +persistent versionpath +persistent signalpath + +% some people mess up their path settings with addpath(genpath(...))which +% results in different versions of SPM or other other toolboxes on the path +list = which('spm', '-all'); +if length(list)>1 + warning('multiple versions of SPM on your path will confuse FieldTrip'); + for i=1:length(list) + warning('spm is found here: %s', list{i}); + end +end + +if isempty(which('hastoolbox')) + % the fieldtrip/public directory contains the hastoolbox function + % which is required for the remainder of this script + addpath(fullfile(fileparts(which('fieldtripdefs')), 'public')); +end + +try + % this directory contains the backward compatibility wrappers for the ft_xxx function name change + hastoolbox('compat', 3, 1); % not required +end + +try + % this contains layouts and cortical meshes + hastoolbox('template', 1, 1); +end + +try + % this is used in statistics + hastoolbox('statfun', 1, 1); +end + +try + % this is used in definetrial + hastoolbox('trialfun', 1, 1); +end + +try + % this contains the low-level reading functions + hastoolbox('fileio', 1, 1); + hastoolbox('fileio/compat', 3, 1); % not required +end + +try + % this is for filtering time-series data + hastoolbox('preproc', 1, 1); + hastoolbox('preproc/compat', 3, 1); % not required +end + +try + % this contains forward models for the EEG and MEG volume conduction problem + hastoolbox('forward', 1, 1); + hastoolbox('forward/compat', 3, 1); % not required +end + +try + % numerous functions depend on this module + hastoolbox('forwinv', 1, 1); +end + +try + % numerous functions depend on this module + hastoolbox('inverse', 1, 1); +end + +try + % this contains intermediate-level plotting functions, e.g. multiplots and 3-d objects + hastoolbox('plotting', 1, 1); + hastoolbox('plotting/compat', 1, 1); +end + +try + % this contains the functions to compute connecitivy metrics + hastoolbox('connectivity', 1,1); +end + +try + % this contains specific code and examples for realtime processing + hastoolbox('realtime', 3, 1); % not required + hastoolbox('realtime/datasource', 3, 1); % not required +end diff --git a/external/fieldtrip/@uint64/abs.c b/external/fieldtrip/fileio/@uint64/abs.c similarity index 100% rename from external/fieldtrip/@uint64/abs.c rename to external/fieldtrip/fileio/@uint64/abs.c diff --git a/external/fieldtrip/@uint64/abs.m b/external/fieldtrip/fileio/@uint64/abs.m similarity index 100% rename from external/fieldtrip/@uint64/abs.m rename to external/fieldtrip/fileio/@uint64/abs.m diff --git a/external/fieldtrip/@uint64/abs.mexa64 b/external/fieldtrip/fileio/@uint64/abs.mexa64 similarity index 100% rename from external/fieldtrip/@uint64/abs.mexa64 rename to external/fieldtrip/fileio/@uint64/abs.mexa64 diff --git a/external/fieldtrip/@uint64/abs.mexglx b/external/fieldtrip/fileio/@uint64/abs.mexglx similarity index 100% rename from external/fieldtrip/@uint64/abs.mexglx rename to external/fieldtrip/fileio/@uint64/abs.mexglx diff --git a/external/fieldtrip/fileio/@uint64/abs.mexmaci b/external/fieldtrip/fileio/@uint64/abs.mexmaci new file mode 100755 index 0000000..f035e95 Binary files /dev/null and b/external/fieldtrip/fileio/@uint64/abs.mexmaci differ diff --git a/external/fieldtrip/@uint64/abs.mexmaci64 b/external/fieldtrip/fileio/@uint64/abs.mexmaci64 similarity index 100% rename from external/fieldtrip/@uint64/abs.mexmaci64 rename to external/fieldtrip/fileio/@uint64/abs.mexmaci64 diff --git a/external/fieldtrip/fileio/@uint64/abs.mexw32 b/external/fieldtrip/fileio/@uint64/abs.mexw32 new file mode 100644 index 0000000..9a21677 Binary files /dev/null and b/external/fieldtrip/fileio/@uint64/abs.mexw32 differ diff --git a/external/fieldtrip/fileio/@uint64/abs.mexw64 b/external/fieldtrip/fileio/@uint64/abs.mexw64 new file mode 100644 index 0000000..e231739 Binary files /dev/null and b/external/fieldtrip/fileio/@uint64/abs.mexw64 differ diff --git a/external/fieldtrip/@uint64/all.m b/external/fieldtrip/fileio/@uint64/all.m similarity index 100% rename from external/fieldtrip/@uint64/all.m rename to external/fieldtrip/fileio/@uint64/all.m diff --git a/external/fieldtrip/@uint64/any.m b/external/fieldtrip/fileio/@uint64/any.m similarity index 100% rename from external/fieldtrip/@uint64/any.m rename to external/fieldtrip/fileio/@uint64/any.m diff --git a/external/fieldtrip/@uint64/compile.m b/external/fieldtrip/fileio/@uint64/compile.m similarity index 100% rename from external/fieldtrip/@uint64/compile.m rename to external/fieldtrip/fileio/@uint64/compile.m diff --git a/external/fieldtrip/@uint64/diff.m b/external/fieldtrip/fileio/@uint64/diff.m similarity index 100% rename from external/fieldtrip/@uint64/diff.m rename to external/fieldtrip/fileio/@uint64/diff.m diff --git a/external/fieldtrip/@uint64/max.c b/external/fieldtrip/fileio/@uint64/max.c similarity index 100% rename from external/fieldtrip/@uint64/max.c rename to external/fieldtrip/fileio/@uint64/max.c diff --git a/external/fieldtrip/@uint64/max.m b/external/fieldtrip/fileio/@uint64/max.m similarity index 100% rename from external/fieldtrip/@uint64/max.m rename to external/fieldtrip/fileio/@uint64/max.m diff --git a/external/fieldtrip/@uint64/max.mexa64 b/external/fieldtrip/fileio/@uint64/max.mexa64 similarity index 100% rename from external/fieldtrip/@uint64/max.mexa64 rename to external/fieldtrip/fileio/@uint64/max.mexa64 diff --git a/external/fieldtrip/@uint64/max.mexglx b/external/fieldtrip/fileio/@uint64/max.mexglx similarity index 100% rename from external/fieldtrip/@uint64/max.mexglx rename to external/fieldtrip/fileio/@uint64/max.mexglx diff --git a/external/fieldtrip/fileio/@uint64/max.mexmaci b/external/fieldtrip/fileio/@uint64/max.mexmaci new file mode 100755 index 0000000..96f4997 Binary files /dev/null and b/external/fieldtrip/fileio/@uint64/max.mexmaci differ diff --git a/external/fieldtrip/@uint64/max.mexmaci64 b/external/fieldtrip/fileio/@uint64/max.mexmaci64 similarity index 100% rename from external/fieldtrip/@uint64/max.mexmaci64 rename to external/fieldtrip/fileio/@uint64/max.mexmaci64 diff --git a/external/fieldtrip/fileio/@uint64/max.mexw32 b/external/fieldtrip/fileio/@uint64/max.mexw32 new file mode 100644 index 0000000..129d2f1 Binary files /dev/null and b/external/fieldtrip/fileio/@uint64/max.mexw32 differ diff --git a/external/fieldtrip/fileio/@uint64/max.mexw64 b/external/fieldtrip/fileio/@uint64/max.mexw64 new file mode 100644 index 0000000..3e0c332 Binary files /dev/null and b/external/fieldtrip/fileio/@uint64/max.mexw64 differ diff --git a/external/fieldtrip/@uint64/min.c b/external/fieldtrip/fileio/@uint64/min.c similarity index 100% rename from external/fieldtrip/@uint64/min.c rename to external/fieldtrip/fileio/@uint64/min.c diff --git a/external/fieldtrip/@uint64/min.m b/external/fieldtrip/fileio/@uint64/min.m similarity index 100% rename from external/fieldtrip/@uint64/min.m rename to external/fieldtrip/fileio/@uint64/min.m diff --git a/external/fieldtrip/@uint64/min.mexa64 b/external/fieldtrip/fileio/@uint64/min.mexa64 similarity index 100% rename from external/fieldtrip/@uint64/min.mexa64 rename to external/fieldtrip/fileio/@uint64/min.mexa64 diff --git a/external/fieldtrip/@uint64/min.mexglx b/external/fieldtrip/fileio/@uint64/min.mexglx similarity index 100% rename from external/fieldtrip/@uint64/min.mexglx rename to external/fieldtrip/fileio/@uint64/min.mexglx diff --git a/external/fieldtrip/fileio/@uint64/min.mexmaci b/external/fieldtrip/fileio/@uint64/min.mexmaci new file mode 100755 index 0000000..2faddfc Binary files /dev/null and b/external/fieldtrip/fileio/@uint64/min.mexmaci differ diff --git a/external/fieldtrip/@uint64/min.mexmaci64 b/external/fieldtrip/fileio/@uint64/min.mexmaci64 similarity index 100% rename from external/fieldtrip/@uint64/min.mexmaci64 rename to external/fieldtrip/fileio/@uint64/min.mexmaci64 diff --git a/external/fieldtrip/fileio/@uint64/min.mexw32 b/external/fieldtrip/fileio/@uint64/min.mexw32 new file mode 100644 index 0000000..e221269 Binary files /dev/null and b/external/fieldtrip/fileio/@uint64/min.mexw32 differ diff --git a/external/fieldtrip/fileio/@uint64/min.mexw64 b/external/fieldtrip/fileio/@uint64/min.mexw64 new file mode 100644 index 0000000..19387c2 Binary files /dev/null and b/external/fieldtrip/fileio/@uint64/min.mexw64 differ diff --git a/external/fieldtrip/@uint64/minus.c b/external/fieldtrip/fileio/@uint64/minus.c similarity index 100% rename from external/fieldtrip/@uint64/minus.c rename to external/fieldtrip/fileio/@uint64/minus.c diff --git a/external/fieldtrip/@uint64/minus.m b/external/fieldtrip/fileio/@uint64/minus.m similarity index 100% rename from external/fieldtrip/@uint64/minus.m rename to external/fieldtrip/fileio/@uint64/minus.m diff --git a/external/fieldtrip/@uint64/minus.mexa64 b/external/fieldtrip/fileio/@uint64/minus.mexa64 similarity index 100% rename from external/fieldtrip/@uint64/minus.mexa64 rename to external/fieldtrip/fileio/@uint64/minus.mexa64 diff --git a/external/fieldtrip/@uint64/minus.mexglx b/external/fieldtrip/fileio/@uint64/minus.mexglx similarity index 100% rename from external/fieldtrip/@uint64/minus.mexglx rename to external/fieldtrip/fileio/@uint64/minus.mexglx diff --git a/external/fieldtrip/fileio/@uint64/minus.mexmaci b/external/fieldtrip/fileio/@uint64/minus.mexmaci new file mode 100755 index 0000000..9c64760 Binary files /dev/null and b/external/fieldtrip/fileio/@uint64/minus.mexmaci differ diff --git a/external/fieldtrip/@uint64/minus.mexmaci64 b/external/fieldtrip/fileio/@uint64/minus.mexmaci64 similarity index 100% rename from external/fieldtrip/@uint64/minus.mexmaci64 rename to external/fieldtrip/fileio/@uint64/minus.mexmaci64 diff --git a/external/fieldtrip/fileio/@uint64/minus.mexw32 b/external/fieldtrip/fileio/@uint64/minus.mexw32 new file mode 100644 index 0000000..d16182c Binary files /dev/null and b/external/fieldtrip/fileio/@uint64/minus.mexw32 differ diff --git a/external/fieldtrip/fileio/@uint64/minus.mexw64 b/external/fieldtrip/fileio/@uint64/minus.mexw64 new file mode 100644 index 0000000..a6ad809 Binary files /dev/null and b/external/fieldtrip/fileio/@uint64/minus.mexw64 differ diff --git a/external/fieldtrip/@uint64/plus.c b/external/fieldtrip/fileio/@uint64/plus.c similarity index 100% rename from external/fieldtrip/@uint64/plus.c rename to external/fieldtrip/fileio/@uint64/plus.c diff --git a/external/fieldtrip/@uint64/plus.m b/external/fieldtrip/fileio/@uint64/plus.m similarity index 100% rename from external/fieldtrip/@uint64/plus.m rename to external/fieldtrip/fileio/@uint64/plus.m diff --git a/external/fieldtrip/@uint64/plus.mexa64 b/external/fieldtrip/fileio/@uint64/plus.mexa64 similarity index 100% rename from external/fieldtrip/@uint64/plus.mexa64 rename to external/fieldtrip/fileio/@uint64/plus.mexa64 diff --git a/external/fieldtrip/@uint64/plus.mexglx b/external/fieldtrip/fileio/@uint64/plus.mexglx similarity index 100% rename from external/fieldtrip/@uint64/plus.mexglx rename to external/fieldtrip/fileio/@uint64/plus.mexglx diff --git a/external/fieldtrip/fileio/@uint64/plus.mexmaci b/external/fieldtrip/fileio/@uint64/plus.mexmaci new file mode 100755 index 0000000..cc65527 Binary files /dev/null and b/external/fieldtrip/fileio/@uint64/plus.mexmaci differ diff --git a/external/fieldtrip/@uint64/plus.mexmaci64 b/external/fieldtrip/fileio/@uint64/plus.mexmaci64 similarity index 100% rename from external/fieldtrip/@uint64/plus.mexmaci64 rename to external/fieldtrip/fileio/@uint64/plus.mexmaci64 diff --git a/external/fieldtrip/fileio/@uint64/plus.mexw32 b/external/fieldtrip/fileio/@uint64/plus.mexw32 new file mode 100644 index 0000000..975656e Binary files /dev/null and b/external/fieldtrip/fileio/@uint64/plus.mexw32 differ diff --git a/external/fieldtrip/fileio/@uint64/plus.mexw64 b/external/fieldtrip/fileio/@uint64/plus.mexw64 new file mode 100644 index 0000000..952be59 Binary files /dev/null and b/external/fieldtrip/fileio/@uint64/plus.mexw64 differ diff --git a/external/fieldtrip/@uint64/rdivide.c b/external/fieldtrip/fileio/@uint64/rdivide.c similarity index 100% rename from external/fieldtrip/@uint64/rdivide.c rename to external/fieldtrip/fileio/@uint64/rdivide.c diff --git a/external/fieldtrip/@uint64/rdivide.m b/external/fieldtrip/fileio/@uint64/rdivide.m similarity index 100% rename from external/fieldtrip/@uint64/rdivide.m rename to external/fieldtrip/fileio/@uint64/rdivide.m diff --git a/external/fieldtrip/@uint64/rdivide.mexa64 b/external/fieldtrip/fileio/@uint64/rdivide.mexa64 similarity index 100% rename from external/fieldtrip/@uint64/rdivide.mexa64 rename to external/fieldtrip/fileio/@uint64/rdivide.mexa64 diff --git a/external/fieldtrip/@uint64/rdivide.mexglx b/external/fieldtrip/fileio/@uint64/rdivide.mexglx similarity index 100% rename from external/fieldtrip/@uint64/rdivide.mexglx rename to external/fieldtrip/fileio/@uint64/rdivide.mexglx diff --git a/external/fieldtrip/fileio/@uint64/rdivide.mexmaci b/external/fieldtrip/fileio/@uint64/rdivide.mexmaci new file mode 100755 index 0000000..ff6ce3e Binary files /dev/null and b/external/fieldtrip/fileio/@uint64/rdivide.mexmaci differ diff --git a/external/fieldtrip/@uint64/rdivide.mexmaci64 b/external/fieldtrip/fileio/@uint64/rdivide.mexmaci64 similarity index 100% rename from external/fieldtrip/@uint64/rdivide.mexmaci64 rename to external/fieldtrip/fileio/@uint64/rdivide.mexmaci64 diff --git a/external/fieldtrip/fileio/@uint64/rdivide.mexw32 b/external/fieldtrip/fileio/@uint64/rdivide.mexw32 new file mode 100644 index 0000000..f14f2f1 Binary files /dev/null and b/external/fieldtrip/fileio/@uint64/rdivide.mexw32 differ diff --git a/external/fieldtrip/fileio/@uint64/rdivide.mexw64 b/external/fieldtrip/fileio/@uint64/rdivide.mexw64 new file mode 100644 index 0000000..2420c30 Binary files /dev/null and b/external/fieldtrip/fileio/@uint64/rdivide.mexw64 differ diff --git a/external/fieldtrip/fileio/@uint64/test.m b/external/fieldtrip/fileio/@uint64/test.m new file mode 100644 index 0000000..1fb7831 --- /dev/null +++ b/external/fieldtrip/fileio/@uint64/test.m @@ -0,0 +1,9 @@ +% +% perform a quick sanity check +% + +uint64(4) + uint64(2) +uint64(4) - uint64(2) +uint64(4) ./ uint64(2) +uint64(4) .* uint64(2) + diff --git a/external/fieldtrip/@uint64/times.c b/external/fieldtrip/fileio/@uint64/times.c similarity index 100% rename from external/fieldtrip/@uint64/times.c rename to external/fieldtrip/fileio/@uint64/times.c diff --git a/external/fieldtrip/@uint64/times.m b/external/fieldtrip/fileio/@uint64/times.m similarity index 100% rename from external/fieldtrip/@uint64/times.m rename to external/fieldtrip/fileio/@uint64/times.m diff --git a/external/fieldtrip/@uint64/times.mexa64 b/external/fieldtrip/fileio/@uint64/times.mexa64 similarity index 100% rename from external/fieldtrip/@uint64/times.mexa64 rename to external/fieldtrip/fileio/@uint64/times.mexa64 diff --git a/external/fieldtrip/@uint64/times.mexglx b/external/fieldtrip/fileio/@uint64/times.mexglx similarity index 100% rename from external/fieldtrip/@uint64/times.mexglx rename to external/fieldtrip/fileio/@uint64/times.mexglx diff --git a/external/fieldtrip/fileio/@uint64/times.mexmaci b/external/fieldtrip/fileio/@uint64/times.mexmaci new file mode 100755 index 0000000..82e8e97 Binary files /dev/null and b/external/fieldtrip/fileio/@uint64/times.mexmaci differ diff --git a/external/fieldtrip/@uint64/times.mexmaci64 b/external/fieldtrip/fileio/@uint64/times.mexmaci64 similarity index 100% rename from external/fieldtrip/@uint64/times.mexmaci64 rename to external/fieldtrip/fileio/@uint64/times.mexmaci64 diff --git a/external/fieldtrip/fileio/@uint64/times.mexw32 b/external/fieldtrip/fileio/@uint64/times.mexw32 new file mode 100644 index 0000000..35499d9 Binary files /dev/null and b/external/fieldtrip/fileio/@uint64/times.mexw32 differ diff --git a/external/fieldtrip/fileio/@uint64/times.mexw64 b/external/fieldtrip/fileio/@uint64/times.mexw64 new file mode 100644 index 0000000..41c6124 Binary files /dev/null and b/external/fieldtrip/fileio/@uint64/times.mexw64 differ diff --git a/external/fileio/COPYING b/external/fieldtrip/fileio/COPYING similarity index 100% rename from external/fileio/COPYING rename to external/fieldtrip/fileio/COPYING diff --git a/external/fieldtrip/fileio/README b/external/fieldtrip/fileio/README new file mode 100644 index 0000000..f06aee0 --- /dev/null +++ b/external/fieldtrip/fileio/README @@ -0,0 +1,23 @@ +This is the FieldTrip FILEIO module. It contains functions for +reading EEG and MEG data from a large variety of files. Furthermore, +additional information such as sensor positions can be read from +file. + +For more information please visit http://www.ru.nl/neuroimaging/fieldtrip + +The source code for zlib is available at http://www.zlib.net + +The following files were downloaded from http://www.koders.com + base64.c + base64.h + +The FieldTrip software is free but copyrighted software, distributed +under the terms of the GNU General Public Licence as published by +the Free Software Foundation (either version 2, or at your option +any later version). See the file COPYING for more details. + +Copyright (C) 2008-2009, Donders Institute for Brain, Cognition and Behaviour, The Netherlands (DCCN, DCC, DCN) +Copyright (C) 2003-2008, F.C. Donders Centre for Cognitive Neuroimaging, Nijmegen, The Netherlands (FCDC) +Copyright (C) 2003-2005, Center for Sensory-Motor Interaction, Aalborg University, Denmark (SMI) +Copyright (C) 1999-2003, Department of Medical Physics, Radboud University Nijmegen, The Netherlands (MBFYS) + diff --git a/external/fieldtrip/fileio/ft_chantype.m b/external/fieldtrip/fileio/ft_chantype.m new file mode 100644 index 0000000..21f1038 --- /dev/null +++ b/external/fieldtrip/fileio/ft_chantype.m @@ -0,0 +1,416 @@ +function type = ft_chantype(input, desired) + +% FT_CHANTYPE determines for each channel what type it is, e.g. planar/axial gradiometer or magnetometer +% +% Use as +% type = ft_chantype(hdr) +% type = ft_chantype(sens) +% type = ft_chantype(label) +% or as +% type = ft_chantype(hdr, desired) +% type = ft_chantype(sens, desired) +% type = ft_chantype(label, desired) + +% Copyright (C) 2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_chantype.m 1296 2010-06-29 14:20:56Z roboos $ + +% determine the type of input + +isheader = isa(input, 'struct') && isfield(input, 'label') && isfield(input, 'Fs'); +isgrad = isa(input, 'struct') && isfield(input, 'pnt') && isfield(input, 'ori'); +islabel = isa(input, 'cell') && isa(input{1}, 'char'); + +hdr = input; +grad = input; +label = input; + +if isheader + numchan = length(hdr.label); + if isfield(hdr, 'grad') + grad = hdr.grad; + end + label = hdr.label; +elseif isgrad + label = grad.label; + numchan = length(label); +elseif islabel + numchan = length(label); +else + error('the input that was provided to this function cannot be deciphered'); +end + +% start with unknown type +type = cell(numchan,1); +for i=1:length(type) + type{i} = 'unknown'; +end + +if ft_senstype(input, 'neuromag') + % channames-KI is the channel kind, 1=meg, 202=eog, 2=eeg, 3=trigger (I am nut sure, but have inferred this from a single test file) + % chaninfo-TY is the Coil type (0=magnetometer, 1=planar gradiometer) + if isfield(hdr, 'orig') && isfield(hdr.orig, 'channames') + for sel=find(hdr.orig.channames.KI(:)==202)' + type{sel} = 'eog'; + end + for sel=find(hdr.orig.channames.KI(:)==2)' + type{sel} = 'eeg'; + end + for sel=find(hdr.orig.channames.KI(:)==3)' + type{sel} = 'digital trigger'; + end + % determinge the MEG channel subtype + selmeg=find(hdr.orig.channames.KI(:)==1)'; + for i=1:length(selmeg) + if hdr.orig.chaninfo.TY(i)==0 + type{selmeg(i)} = 'megmag'; + elseif hdr.orig.chaninfo.TY(i)==1 + type{selmeg(i)} = 'megplanar'; + end + end + + elseif isfield(hdr, 'orig') && isfield(hdr.orig, 'chs') && isfield(hdr.orig.chs, 'coil_type') + %all the chs.kinds and chs.coil_types are obtained from the MNE + %manual, p.210-211 + for sel=find([hdr.orig.chs.kind]==1 & [hdr.orig.chs.coil_type]==2)' %planar gradiometers + type(sel) = {'megplanar'}; %Neuromag-122 planar gradiometer + end + for sel=find([hdr.orig.chs.kind]==1 & [hdr.orig.chs.coil_type]==3012)' %planar gradiometers + type(sel) = {'megplanar'}; %Type T1 planar grad + end + for sel=find([hdr.orig.chs.kind]==1 & [hdr.orig.chs.coil_type]==3013)' %planar gradiometers + type(sel) = {'megplanar'}; %Type T2 planar grad + end + for sel=find([hdr.orig.chs.kind]==1 & [hdr.orig.chs.coil_type]==3014)' %planar gradiometers + type(sel) = {'megplanar'}; %Type T3 planar grad + end + for sel=find([hdr.orig.chs.kind]==1 & [hdr.orig.chs.coil_type]==3022)' %magnetometers + type(sel) = {'megmag'}; %Type T1 magenetometer + end + for sel=find([hdr.orig.chs.kind]==1 & [hdr.orig.chs.coil_type]==3023)' %magnetometers + type(sel) = {'megmag'}; %Type T2 magenetometer + end + for sel=find([hdr.orig.chs.kind]==1 & [hdr.orig.chs.coil_type]==3024)' %magnetometers + type(sel) = {'megmag'}; %Type T3 magenetometer + end + for sel=find([hdr.orig.chs.kind]==301)' %MEG reference channel, located far from head + type(sel) = {'ref'}; + end + for sel=find([hdr.orig.chs.kind]==2)' %EEG channels + type(sel) = {'eeg'}; + end + for sel=find([hdr.orig.chs.kind]==201)' %MCG channels + type(sel) = {'mcg'}; + end + for sel=find([hdr.orig.chs.kind]==3)' %Stim channels + if any([hdr.orig.chs(sel).logno] == 101) %new systems: 101 (and 102, if enabled) are digital; + %low numbers are 'pseudo-analog' (if enabled) + type(sel([hdr.orig.chs(sel).logno] == 101)) = {'digital trigger'}; + type(sel([hdr.orig.chs(sel).logno] == 102)) = {'digital trigger'}; + type(sel([hdr.orig.chs(sel).logno] <= 32)) = {'analog trigger'}; + others = [hdr.orig.chs(sel).logno] > 32 & [hdr.orig.chs(sel).logno] ~= 101 & ... + [hdr.orig.chs(sel).logno] ~= 102; + type(sel(others)) = {'other trigger'}; + elseif any([hdr.orig.chs(sel).logno] == 14) %older systems: STI 014/015/016 are digital; + %lower numbers 'pseudo-analog'(if enabled) + type(sel([hdr.orig.chs(sel).logno] == 14)) = {'digital trigger'}; + type(sel([hdr.orig.chs(sel).logno] == 15)) = {'digital trigger'}; + type(sel([hdr.orig.chs(sel).logno] == 16)) = {'digital trigger'}; + type(sel([hdr.orig.chs(sel).logno] <= 13)) = {'analog trigger'}; + others = [hdr.orig.chs(sel).logno] > 16; + type(sel(others)) = {'other trigger'}; + else + warning('There does not seem to be a suitable trigger channel.'); + type(sel) = {'other trigger'}; + end + end + for sel=find([hdr.orig.chs.kind]==202)' %EOG + type(sel) = {'eog'}; + end + for sel=find([hdr.orig.chs.kind]==302)' %EMG + type(sel) = {'emg'}; + end + for sel=find([hdr.orig.chs.kind]==402)' %ECG + type(sel) = {'ecg'}; + end + for sel=find([hdr.orig.chs.kind]==502)' %MISC + type(sel) = {'misc'}; + end + for sel=find([hdr.orig.chs.kind]==602)' %Resp + type(sel) = {'respiration'}; + end + end + +elseif ft_senstype(input, 'ctf') && isheader + % meg channels are 5, refmag 0, refgrad 1, adcs 18, trigger 11, eeg 9 + if isfield(hdr, 'orig') && isfield(hdr.orig, 'sensType') + origSensType = hdr.orig.sensType; + elseif isfield(hdr, 'orig') && isfield(hdr.orig, 'res4') + origSensType = [hdr.orig.res4.senres.sensorTypeIndex]; + else + warning('could not determine channel type from the CTF header'); + origSensType = []; + end + + for sel=find(origSensType(:)==5)' + type{sel} = 'meggrad'; + end + for sel=find(origSensType(:)==0)' + type{sel} = 'refmag'; + end + for sel=find(origSensType(:)==1)' + type{sel} = 'refgrad'; + end + for sel=find(origSensType(:)==18)' + type{sel} = 'adc'; + end + for sel=find(origSensType(:)==11)' + type{sel} = 'trigger'; + end + for sel=find(origSensType(:)==9)' + type{sel} = 'eeg'; + end + for sel=find(origSensType(:)==29)' + type{sel} = 'reserved'; % these are "reserved for future use", but relate to head localization + end + for sel=find(origSensType(:)==13)' + type{sel} = 'headloc'; % these represent the x, y, z position of the head coils + end + for sel=find(origSensType(:)==28)' + type{sel} = 'headloc_gof'; % these represent the goodness of fit for the head coils + end + % for sel=find(origSensType(:)==23)' + % type{sel} = 'SPLxxxx'; % I have no idea what these are + % end + +elseif ft_senstype(input, 'ctf') && isgrad + % in principle it is possible to look at the number of coils, but here the channels are identified based on their name + sel = myregexp('^M[ZLR][A-Z][0-9][0-9]$', grad.label); + type(sel) = {'meggrad'}; % normal gradiometer channels + sel = myregexp('^B[GPR][0-9]$', grad.label); + type(sel) = {'refmag'}; % reference magnetometers + sel = myregexp('^[GPQR][0-9][0-9]$', grad.label); + type(sel) = {'refgrad'}; % reference gradiometers + +elseif ft_senstype(input, 'ctf') && islabel + % the channels have to be identified based on their name alone + sel = myregexp('^M[ZLR][A-Z][0-9][0-9]$', label); + type(sel) = {'meggrad'}; % normal gradiometer channels + sel = myregexp('^B[GPR][0-9]$', label); + type(sel) = {'refmag'}; % reference magnetometers + sel = myregexp('^[GPQR][0-9][0-9]$', label); + type(sel) = {'refgrad'}; % reference gradiometers + +elseif ft_senstype(input, 'bti') + % all 4D-BTi MEG channels start with "A" + % all 4D-BTi reference channels start with M or G + % all 4D-BTi EEG channels start with E + type(strncmp('A', label, 1)) = {'meg'}; + type(strncmp('M', label, 1)) = {'refmag'}; + type(strncmp('G', label, 1)) = {'refgrad'}; + + if isfield(grad, 'tra') + selchan = find(strcmp('mag', type)); + for k = 1:length(selchan) + ncoils = length(find(grad.tra(selchan(k),:)==1)); + if ncoils==1, + type{selchan(k)} = 'megmag'; + elseif ncoils==2, + type{selchan(k)} = 'meggrad'; + end + end + end + + % This is to allow setting additional channel types based on the names + if isheader && issubfield(hdr, 'orig.channel_data.chan_label') + tmplabel = {hdr.orig.channel_data.chan_label}; + tmplabel = tmplabel(:); + else + tmplabel = label; % might work + end + sel = strmatch('unknown', type, 'exact'); + if ~isempty(sel) + type(sel)= ft_chantype(tmplabel(sel)); + sel = strmatch('unknown', type, 'exact'); + if ~isempty(sel) + type(sel(strncmp('E', label(sel), 1))) = {'eeg'}; + end + end + +elseif ft_senstype(input, 'itab') && isheader + origtype = [input.orig.ch.type]; + type(origtype==0) = {'unknown'}; + type(origtype==1) = {'ele'}; + type(origtype==2) = {'mag'}; % might be magnetometer or gradiometer, look at the number of coils + type(origtype==4) = {'ele ref'}; + type(origtype==8) = {'mag ref'}; + type(origtype==16) = {'aux'}; + type(origtype==32) = {'param'}; + type(origtype==64) = {'digit'}; + type(origtype==128) = {'flag'}; + % these are the channels that are visible to fieldtrip + chansel = 1:input.orig.nchan; + type = type(chansel); + +elseif ft_senstype(input, 'yokogawa') && isheader + % This is to recognize Yokogawa channel types from the original header + % This is from the original documentation + NullChannel = 0; + MagnetoMeter = 1; + AxialGradioMeter = 2; + PlannerGradioMeter = 3; + RefferenceChannelMark = hex2dec('0100'); + RefferenceMagnetoMeter = bitor( RefferenceChannelMark, MagnetoMeter ); + RefferenceAxialGradioMeter = bitor( RefferenceChannelMark, AxialGradioMeter ); + RefferencePlannerGradioMeter = bitor( RefferenceChannelMark, PlannerGradioMeter); + TriggerChannel = -1; + EegChannel = -2; + EcgChannel = -3; + EtcChannel = -4; + sel = (hdr.orig.channel_info(:, 2) == NullChannel); + type(sel) = {'null'}; + sel = (hdr.orig.channel_info(:, 2) == MagnetoMeter); + type(sel) = {'megmag'}; + sel = (hdr.orig.channel_info(:, 2) == AxialGradioMeter); + type(sel) = {'meggrad'}; + sel = (hdr.orig.channel_info(:, 2) == PlannerGradioMeter); + type(sel) = {'megplanar'}; + sel = (hdr.orig.channel_info(:, 2) == RefferenceMagnetoMeter); + type(sel) = {'refmag'}; + sel = (hdr.orig.channel_info(:, 2) == RefferenceAxialGradioMeter); + type(sel) = {'refgrad'}; + sel = (hdr.orig.channel_info(:, 2) == RefferencePlannerGradioMeter); + type(sel) = {'refplanar'}; + sel = (hdr.orig.channel_info(:, 2) == TriggerChannel); + type(sel) = {'trigger'}; + sel = (hdr.orig.channel_info(:, 2) == EegChannel); + type(sel) = {'eeg'}; + sel = (hdr.orig.channel_info(:, 2) == EcgChannel); + type(sel) = {'ecg'}; + sel = (hdr.orig.channel_info(:, 2) == EtcChannel); + type(sel) = {'etc'}; + +elseif ft_senstype(input, 'yokogawa') && isgrad + % all channels in the gradiometer definition are meg + type(1:end) = {'meg'}; + +elseif ft_senstype(input, 'yokogawa') && islabel + % the yokogawa channel labels are a mess, so autodetection is not possible + type(1:end) = {'meg'}; + +elseif ft_senstype(input, 'itab') && isheader + sel = ([hdr.orig.ch.type]==0); + type(sel) = {'unknown'}; + sel = ([hdr.orig.ch.type]==1); + type(sel) = {'unknown'}; + sel = ([hdr.orig.ch.type]==2); + type(sel) = {'megmag'}; + sel = ([hdr.orig.ch.type]==8); + type(sel) = {'megref'}; + sel = ([hdr.orig.ch.type]==16); + type(sel) = {'aux'}; + sel = ([hdr.orig.ch.type]==64); + type(sel) = {'digital'}; + % not all channels are actually processed by fieldtrip, so only return + % the types fopr the ones that read_header and read_data return + type = type(hdr.orig.chansel); + +elseif ft_senstype(input, 'itab') && isgrad + % the channels have to be identified based on their name alone + sel = myregexp('^MAG_[0-9][0-9][0-9]$', label); + type(sel) = {'megmag'}; + sel = myregexp('^REF_[0-9][0-9][0-9]$', label); + type(sel) = {'megref'}; + sel = myregexp('^AUX.*$', label); + type(sel) = {'aux'}; + +elseif ft_senstype(input, 'itab') && islabel + % the channels have to be identified based on their name alone + sel = myregexp('^MAG_[0-9][0-9][0-9]$', label); + type(sel) = {'megmag'}; + sel = myregexp('^REF_[0-9][0-9][0-9]$', label); + type(sel) = {'megref'}; + sel = myregexp('^AUX.*$', label); + type(sel) = {'aux'}; + +elseif ft_senstype(input, 'eeg') && islabel + % use an external helper function to define the list with EEG channel names + type(match_str(label, ft_senslabel(ft_senstype(label)))) = {'eeg'}; + +elseif ft_senstype(input, 'eeg') && isheader + % use an external helper function to define the list with EEG channel names + type(match_str(hdr.label, ft_senslabel(ft_senstype(hdr)))) = {'eeg'}; + +elseif ft_senstype(input, 'plexon') && isheader + % this is a complete header that was read from a Plexon *.nex file using read_plexon_nex + for i=1:numchan + switch hdr.orig.VarHeader(i).Type + case 0 + type{i} = 'spike'; + case 1 + type{i} = 'event'; + case 2 + type{i} = 'interval'; % Interval variables? + case 3 + type{i} = 'waveform'; + case 4 + type{i} = 'population'; % Population variables ? + case 5 + type{i} = 'analog'; + otherwise + % keep the default 'unknown' type + end + end + +end % ft_senstype + +% if possible, set additional types based on channel labels +label2type = { + {'ecg', 'ekg'}; + {'emg'}; + {'eog', 'heog', 'veog'}; + {'lfp'}; + {'eeg'}; + }; +for i = 1:numel(label2type) + for j = 1:numel(label2type{i}) + type(intersect(strmatch(label2type{i}{j}, lower(label)),... + strmatch('unknown', type, 'exact'))) = label2type{i}(1); + end +end + +if nargin>1 + % return a boolean vector + if isequal(desired, 'meg') || isequal(desired, 'ref') + type = strncmp(desired, type, 3); + else + type = strcmp(desired, type); + end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% helper function +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function match = myregexp(pat, list) +match = false(size(list)); +for i=1:numel(list) + match(i) = ~isempty(regexp(list{i}, pat, 'once')); +end + + diff --git a/external/fieldtrip/fileio/ft_create_buffer.m b/external/fieldtrip/fileio/ft_create_buffer.m new file mode 100644 index 0000000..03bb1c5 --- /dev/null +++ b/external/fieldtrip/fileio/ft_create_buffer.m @@ -0,0 +1,47 @@ +function ft_create_buffer(port) + +% FT_CREATE_BUFFER starts the thread with the TCP server attached to the local +% Matlab instance. The TCP server will listen to the specified network +% port, and accept incoming read and write requests. +% +% Use as +% ft_create_buffer(port) +% where port is the TCP port to which the server listens. The default port +% number is 1972. +% +% See also FT_DESTROY_BUFFER + +% Copyright (C) 2010, Stefan Klanke +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_create_buffer.m 944 2010-04-21 16:08:12Z roboos $ + +if nargin<1 + port = 1972; +end + +try + buffer('tcpserver', 'init', 'localhost', port); + pause(1); +catch + if ~isempty(strfind(lasterr, 'thread is already running')) + warning('thread is already running'); + else + rethrow(lasterror); + end +end diff --git a/external/fieldtrip/fileio/ft_destroy_buffer.m b/external/fieldtrip/fileio/ft_destroy_buffer.m new file mode 100644 index 0000000..f217c48 --- /dev/null +++ b/external/fieldtrip/fileio/ft_destroy_buffer.m @@ -0,0 +1,34 @@ +function ft_destroy_buffer + +% FT_DESTROY_BUFFER stops the thread with the TCP server attached to +% the local Matlab instance and removes all data from memory. +% +% Use as +% ft_destroy_buffer +% +% See also FT_CREATE_BUFFER + +% Copyright (C) 2010, Stefan Klanke +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_destroy_buffer.m 944 2010-04-21 16:08:12Z roboos $ + +% clearing the mex file from memory will cause the function registered with +% mexAtExit to be executed. This function will then stop the threads and +% release all allocated memory to the operating system +clear buffer diff --git a/external/fieldtrip/fileio/ft_filetype.m b/external/fieldtrip/fileio/ft_filetype.m new file mode 100644 index 0000000..2ba99c7 --- /dev/null +++ b/external/fieldtrip/fileio/ft_filetype.m @@ -0,0 +1,966 @@ +function [type] = ft_filetype(filename, desired, varargin) + +% FT_FILETYPE determines the filetype of many EEG/MEG/MRI data files by +% looking at the name, extension and optionally (part of) its contents. +% It tries to determine the global type of file (which usually +% corresponds to the manufacturer, the recording system or to the +% software used to create the file) and the particular subtype (e.g. +% continuous, average). +% +% Use as +% type = ft_filetype(filename) +% type = ft_filetype(dirname) +% +% This gives you a descriptive string with the data type, and can be +% used in a switch-statement. The descriptive string that is returned +% usually is something like 'XXX_YYY'/ where XXX refers to the +% manufacturer and YYY to the type of the data. +% +% Alternatively, use as +% flag = ft_filetype(filename, type) +% flag = ft_filetype(dirname, type) +% This gives you a boolean flag (0 or 1) indicating whether the file +% is of the desired type, and can be used to check whether the +% user-supplied file is what your subsequent code expects. +% +% Alternatively, use as +% flag = ft_filetype(dirlist, type) +% where the dirlist contains a list of files contained within one +% directory. This gives you a boolean vector indicating for each file +% whether it is of the desired type. +% +% Most filetypes of the following manufacturers and/or software programs are recognized +% - 4D/BTi +% - AFNI +% - ASA +% - Analyse +% - Analyze/SPM +% - BESA +% - BrainVision +% - Curry +% - EDF +% - EEProbe +% - Elektra/Neuromag +% - LORETA +% - MINC +% - Neuralynx +% - Neuroscan +% - Plexon +% - SR Research Eyelink +% - Tucker Davis Technology +% - VSMMedtech/CTF +% - Yokogawa +% +% See also READ_XXX_YYY where XXX=manufacturer and YYY=subtype + +% Copyright (C) 2003-2010 Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_filetype.m 1429 2010-07-20 07:32:27Z roboos $ + +% these are for remembering the type on subsequent calls with the same input arguments +persistent previous_argin previous_argout previous_pwd + +if nargin<2 + % ensure that all input arguments are defined + desired = []; +end + +current_argin = {filename, desired, varargin{:}}; +current_pwd = pwd; +if isequal(current_argin, previous_argin) && isequal(current_pwd, previous_pwd) + % don't do the detection again, but return the previous value from cache + type = previous_argout{1}; + return +end + +if strcmp(class(filename), 'memmapfile'), + filename = filename.Filename; +end + +% % get the optional arguments +% checkheader = keyval('checkheader', varargin); if isempty(checkheader), checkheader=1; end +% +% if ~checkheader +% % assume that the header is always ok, e.g when the file does not yet exist +% % this replaces the normal function with a function that always returns true +% filetype_check_header = @filetype_true; +% end + +if iscell(filename) + % perform the test for each filename, return a boolean vector + type = false(size(filename)); + for i=1:length(filename) + if strcmp(filename{i}(end), '.') + % do not recurse into this directory or the parent directory + continue + else + type(i) = ft_filetype(filename{i}, desired); + end + end + return +end + +% start with unknown values +type = 'unknown'; +manufacturer = 'unknown'; +content = 'unknown'; + +[p, f, x] = fileparts(filename); + +% prevent this test if the filename resembles an URI, i.e. like "scheme://" +if isempty(strfind(filename , '://')) && isdir(filename) + % the directory listing is needed below + ls = dir(filename); + % remove the parent directory and the directory itself from the list + ls = ls(~strcmp({ls.name}, '.')); + ls = ls(~strcmp({ls.name}, '..')); + for i=1:length(ls) + % make sure that the directory listing includes the complete path + ls(i).name = fullfile(filename, ls(i).name); + end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% start determining the filetype +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% these are some streams for asynchronous BCI +if filetype_check_uri(filename, 'fifo') + type = 'fcdc_fifo'; + manufacturer = 'F.C. Donders Centre'; + content = 'stream'; +elseif filetype_check_uri(filename, 'buffer') + type = 'fcdc_buffer'; + manufacturer = 'F.C. Donders Centre'; + content = 'stream'; +elseif filetype_check_uri(filename, 'mysql') + type = 'fcdc_mysql'; + manufacturer = 'F.C. Donders Centre'; + content = 'stream'; +elseif filetype_check_uri(filename, 'tcp') + type = 'fcdc_tcp'; + manufacturer = 'F.C. Donders Centre'; + content = 'stream'; +elseif filetype_check_uri(filename, 'udp') + type = 'fcdc_udp'; + manufacturer = 'F.C. Donders Centre'; + content = 'stream'; +elseif filetype_check_uri(filename, 'rfb') + type = 'fcdc_rfb'; + manufacturer = 'F.C. Donders Centre'; + content = 'stream'; +elseif filetype_check_uri(filename, 'serial') + type = 'fcdc_serial'; + manufacturer = 'F.C. Donders Centre'; + content = 'stream'; +elseif filetype_check_uri(filename, 'global') + type = 'fcdc_global'; + manufacturer = 'F.C. Donders Centre'; + content = 'global variable'; +elseif filetype_check_uri(filename, 'shm') + type = 'ctf_shm'; + manufacturer = 'CTF'; + content = 'real-time shared memory buffer'; +elseif filetype_check_uri(filename, 'empty') + type = 'empty'; + manufacturer = 'F.C. Donders Centre'; + content = '/dev/null'; + + % known CTF file types +elseif isdir(filename) && filetype_check_extension(filename, '.ds') && exist(fullfile(filename, [f '.res4'])) + type = 'ctf_ds'; + manufacturer = 'CTF'; + content = 'MEG dataset'; +elseif isdir(filename) && ~isempty(dir(fullfile(filename, '*.res4'))) && ~isempty(dir(fullfile(filename, '*.meg4'))) + type = 'ctf_ds'; + manufacturer = 'CTF'; + content = 'MEG dataset'; +elseif filetype_check_extension(filename, '.res4') && (filetype_check_header(filename, 'MEG41RS') || filetype_check_header(filename, 'MEG42RS') || filetype_check_header(filename, 'MEG4RES')) + type = 'ctf_res4'; + manufacturer = 'CTF'; + content = 'MEG/EEG header information'; +elseif filetype_check_extension(filename, '.meg4') && filetype_check_header(filename, 'MEG41CP') + type = 'ctf_meg4'; + manufacturer = 'CTF'; + content = 'MEG/EEG'; +elseif strcmp(f, 'MarkerFile') && filetype_check_extension(filename, '.mrk') && filetype_check_header(filename, 'PATH OF DATASET:') + type = 'ctf_mrk'; + manufacturer = 'CTF'; + content = 'marker file'; +elseif filetype_check_extension(filename, '.mri') && filetype_check_header(filename, 'CTF_MRI_FORMAT VER 2.2') + type = 'ctf_mri'; + manufacturer = 'CTF'; + content = 'MRI'; +elseif filetype_check_extension(filename, '.mri') && filetype_check_header(filename, 'CTF_MRI_FORMAT VER 4', 31) + type = 'ctf_mri4'; + manufacturer = 'CTF'; + content = 'MRI'; +elseif filetype_check_extension(filename, '.hdm') + type = 'ctf_hdm'; + manufacturer = 'CTF'; + content = 'volume conduction model'; +elseif filetype_check_extension(filename, '.hc') + type = 'ctf_hc'; + manufacturer = 'CTF'; + content = 'headcoil locations'; +elseif filetype_check_extension(filename, '.shape') + type = 'ctf_shape'; + manufacturer = 'CTF'; + content = 'headshape points'; +elseif filetype_check_extension(filename, '.shape_info') + type = 'ctf_shapeinfo'; + manufacturer = 'CTF'; + content = 'headshape information'; +elseif filetype_check_extension(filename, '.wts') + type = 'ctf_wts'; + manufacturer = 'CTF'; + content = 'SAM coefficients, i.e. spatial filter weights'; +elseif filetype_check_extension(filename, '.svl') + type = 'ctf_svl'; + manufacturer = 'CTF'; + content = 'SAM (pseudo-)statistic volumes'; + + % known Micromed file types +elseif filetype_check_extension(filename, '.trc') && filetype_check_header(filename, '* MICROMED') + type = 'micromed_trc'; + manufacturer = 'Micromed'; + content = 'Electrophysiological data'; + + % known Neuromag file types +elseif filetype_check_extension(filename, '.fif') + type = 'neuromag_fif'; + manufacturer = 'Neuromag'; + content = 'MEG header and data'; +elseif filetype_check_extension(filename, '.bdip') + type = 'neuromag_bdip'; + manufacturer = 'Neuromag'; + content = 'dipole model'; + + % known Yokogawa file types +elseif filetype_check_extension(filename, '.ave') || filetype_check_extension(filename, '.sqd') + type = 'yokogawa_ave'; + manufacturer = 'Yokogawa'; + content = 'averaged MEG data'; +elseif filetype_check_extension(filename, '.con') + type = 'yokogawa_con'; + manufacturer = 'Yokogawa'; + content = 'continuous MEG data'; +elseif filetype_check_extension(filename, '.raw') && filetype_check_header(filename, char([0 0 0 0])) % FIXME, this detection should possibly be improved + type = 'yokogawa_raw'; + manufacturer = 'Yokogawa'; + content = 'evoked/trialbased MEG data'; +elseif filetype_check_extension(filename, '.mrk') && filetype_check_header(filename, char([0 0 0 0])) % FIXME, this detection should possibly be improved + type = 'yokogawa_mrk'; + manufacturer = 'Yokogawa'; + content = 'headcoil locations'; +elseif filetype_check_extension(filename, '.mri') && filetype_check_header(filename, char([0 0 0 0])) % FIXME, this detection should possibly be improved + type = 'yokogawa_mri'; + manufacturer = 'Yokogawa'; + content = 'anatomical MRI'; +elseif filetype_check_extension(filename, '.txt') && numel(strfind(filename,'-coregis')) == 1 + type = 'yokogawa_coregis'; + manufacturer = 'Yokogawa'; + content = 'exported fiducials'; +elseif filetype_check_extension(filename, '.txt') && numel(strfind(filename,'-calib')) == 1 + type = 'yokogawa_calib'; + manufacturer = 'Yokogawa'; +elseif filetype_check_extension(filename, '.txt') && numel(strfind(filename,'-channel')) == 1 + type = 'yokogawa_channel'; + manufacturer = 'Yokogawa'; +elseif filetype_check_extension(filename, '.txt') && numel(strfind(filename,'-property')) == 1 + type = 'yokogawa_property'; + manufacturer = 'Yokogawa'; +elseif filetype_check_extension(filename, '.txt') && numel(strfind(filename,'-TextData')) == 1 + type = 'yokogawa_textdata'; + manufacturer = 'Yokogawa'; +elseif filetype_check_extension(filename, '.txt') && numel(strfind(filename,'-FLL')) == 1 + type = 'yokogawa_fll'; + manufacturer = 'Yokogawa'; + + % known 4D/BTI file types +elseif filetype_check_extension(filename, '.pdf') && filetype_check_header(filename, 'E|lk') % I am not sure whether this header always applies + type = '4d_pdf'; + manufacturer = '4D/BTI'; + content = 'raw MEG data (processed data file)'; +elseif exist([filename '.m4d'], 'file') && exist([filename '.xyz'], 'file') % these two ascii header files accompany the raw data + type = '4d_pdf'; + manufacturer = '4D/BTI'; + content = 'raw MEG data (processed data file)'; +elseif filetype_check_extension(filename, '.m4d') && exist([filename(1:(end-3)) 'xyz'], 'file') % these come in pairs + type = '4d_m4d'; + manufacturer = '4D/BTI'; + content = 'MEG header information'; +elseif filetype_check_extension(filename, '.xyz') && exist([filename(1:(end-3)) 'm4d'], 'file') % these come in pairs + type = '4d_xyz'; + manufacturer = '4D/BTI'; + content = 'MEG sensor positions'; +elseif isequal(f, 'hs_file') % the filename is "hs_file" + type = '4d_hs'; + manufacturer = '4D/BTI'; + content = 'head shape'; +elseif length(filename)>=4 && ~isempty(strfind(filename,',rf')) + type = '4d'; + manufacturer = '4D/BTi'; + content = ''; + + % known EEProbe file types +elseif filetype_check_extension(filename, '.cnt') && filetype_check_header(filename, 'RIFF') + type = 'eep_cnt'; + manufacturer = 'EEProbe'; + content = 'EEG'; +elseif filetype_check_extension(filename, '.avr') && filetype_check_header(filename, char([38 0 16 0])) + type = 'eep_avr'; + manufacturer = 'EEProbe'; + content = 'ERP'; +elseif filetype_check_extension(filename, '.trg') + type = 'eep_trg'; + manufacturer = 'EEProbe'; + content = 'trigger information'; +elseif filetype_check_extension(filename, '.rej') + type = 'eep_rej'; + manufacturer = 'EEProbe'; + content = 'rejection marks'; + + % known ASA file types +elseif filetype_check_extension(filename, '.elc') + type = 'asa_elc'; + manufacturer = 'ASA'; + content = 'electrode positions'; +elseif filetype_check_extension(filename, '.vol') + type = 'asa_vol'; + manufacturer = 'ASA'; + content = 'volume conduction model'; +elseif filetype_check_extension(filename, '.bnd') + type = 'asa_bnd'; + manufacturer = 'ASA'; + content = 'boundary element model details'; +elseif filetype_check_extension(filename, '.msm') + type = 'asa_msm'; + manufacturer = 'ASA'; + content = 'ERP'; +elseif filetype_check_extension(filename, '.msr') + type = 'asa_msr'; + manufacturer = 'ASA'; + content = 'ERP'; +elseif filetype_check_extension(filename, '.dip') + % FIXME, can also be CTF dipole file + type = 'asa_dip'; + manufacturer = 'ASA'; +elseif filetype_check_extension(filename, '.mri') + % FIXME, can also be CTF mri file + type = 'asa_mri'; + manufacturer = 'ASA'; + content = 'MRI image header'; +elseif filetype_check_extension(filename, '.iso') + type = 'asa_iso'; + manufacturer = 'ASA'; + content = 'MRI image data'; + + % known BCI2000 file types +elseif filetype_check_extension(filename, '.dat') && (filetype_check_header(filename, 'BCI2000') || filetype_check_header(filename, 'HeaderLen=')) + type = 'bci2000_dat'; + manufacturer = 'BCI2000'; + content = 'continuous EEG'; + + % known Neuroscan file types +elseif filetype_check_extension(filename, '.avg') && filetype_check_header(filename, 'Version 3.0') + type = 'ns_avg'; + manufacturer = 'Neuroscan'; + content = 'averaged EEG'; +elseif filetype_check_extension(filename, '.cnt') && filetype_check_header(filename, 'Version 3.0') + type = 'ns_cnt'; + manufacturer = 'Neuroscan'; + content = 'continuous EEG'; +elseif filetype_check_extension(filename, '.eeg') && filetype_check_header(filename, 'Version 3.0') + type = 'ns_eeg'; + manufacturer = 'Neuroscan'; + content = 'epoched EEG'; + +elseif filetype_check_extension(filename, '.eeg') && filetype_check_header(filename, 'V3.0') + type = 'neuroprax_eeg'; + manufacturer = 'eldith GmbH'; + content = 'continuous EEG'; +elseif filetype_check_extension(filename, '.ee_') + type = 'neuroprax_mrk'; + manufacturer = 'eldith GmbH'; + content = 'EEG markers'; + + % known Analyze & SPM file types +elseif filetype_check_extension(filename, '.hdr') + type = 'analyze_hdr'; + manufacturer = 'Mayo Analyze'; + content = 'PET/MRI image header'; +elseif filetype_check_extension(filename, '.img') + type = 'analyze_img'; + manufacturer = 'Mayo Analyze'; + content = 'PET/MRI image data'; +elseif filetype_check_extension(filename, '.mnc') + type = 'minc'; + content = 'MRI image data'; +elseif filetype_check_extension(filename, '.nii') + type = 'nifti'; + content = 'MRI image data'; + + % known LORETA file types +elseif filetype_check_extension(filename, '.lorb') + type = 'loreta_lorb'; + manufacturer = 'old LORETA'; + content = 'source reconstruction'; +elseif filetype_check_extension(filename, '.slor') + type = 'loreta_slor'; + manufacturer = 'sLORETA'; + content = 'source reconstruction'; + + % known AFNI file types +elseif filetype_check_extension(filename, '.brik') || filetype_check_extension(filename, '.BRIK') + type = 'afni_brik'; + content = 'MRI image data'; +elseif filetype_check_extension(filename, '.head') || filetype_check_extension(filename, '.HEAD') + type = 'afni_head'; + content = 'MRI header data'; + + % known BrainVison file types +elseif filetype_check_extension(filename, '.vhdr') + type = 'brainvision_vhdr'; + manufacturer = 'BrainProducts'; + content = 'EEG header'; +elseif filetype_check_extension(filename, '.vmrk') + type = 'brainvision_vmrk'; + manufacturer = 'BrainProducts'; + content = 'EEG markers'; +elseif filetype_check_extension(filename, '.vabs') + type = 'brainvision_vabs'; + manufacturer = 'BrainProducts'; + content = 'Brain Vison Analyzer macro'; +elseif filetype_check_extension(filename, '.eeg') && exist(fullfile(p, [f '.vhdr']), 'file') + type = 'brainvision_eeg'; + manufacturer = 'BrainProducts'; + content = 'continuous EEG data'; +elseif filetype_check_extension(filename, '.seg') + type = 'brainvision_seg'; + manufacturer = 'BrainProducts'; + content = 'segmented EEG data'; +elseif filetype_check_extension(filename, '.dat') && exist(fullfile(p, [f '.vhdr']), 'file') &&... + ~filetype_check_header(filename, 'HeaderLen=') && ~filetype_check_header(filename, 'BESA_SA_IMAGE') &&... + ~(exist(fullfile(p, [f '.gen']), 'file') || exist(fullfile(p, [f '.generic']), 'file')) + % WARNING this is a very general name, it could be exported BrainVision + % data but also a BESA beamformer source reconstruction or BCI2000 + type = 'brainvision_dat'; + manufacturer = 'BrainProducts'; + content = 'exported EEG data'; +elseif filetype_check_extension(filename, '.marker') + type = 'brainvision_marker'; + manufacturer = 'BrainProducts'; + content = 'rejection markers'; + + % known Polhemus file types +elseif filetype_check_extension(filename, '.pos') + type = 'polhemus_pos'; + manufacturer = 'BrainProducts/CTF/Polhemus?'; % actually I don't know whose software it is + content = 'electrode positions'; + + % known Neuralynx file types +elseif filetype_check_extension(filename, '.nev') || filetype_check_extension(filename, '.Nev') + type = 'neuralynx_nev'; + manufacturer = 'Neuralynx'; + content = 'event information'; +elseif filetype_check_extension(filename, '.ncs') && filetype_check_header(filename, '####') + type = 'neuralynx_ncs'; + manufacturer = 'Neuralynx'; + content = 'continuous single channel recordings'; +elseif filetype_check_extension(filename, '.nse') && filetype_check_header(filename, '####') + type = 'neuralynx_nse'; + manufacturer = 'Neuralynx'; + content = 'spike waveforms'; +elseif filetype_check_extension(filename, '.nts') && filetype_check_header(filename, '####') + type = 'neuralynx_nts'; + manufacturer = 'Neuralynx'; + content = 'timestamps only'; +elseif filetype_check_extension(filename, '.nvt') + type = 'neuralynx_nvt'; + manufacturer = 'Neuralynx'; + content = 'video tracker'; +elseif filetype_check_extension(filename, '.nst') + type = 'neuralynx_nst'; + manufacturer = 'Neuralynx'; + content = 'continuous stereotrode recordings'; +elseif filetype_check_extension(filename, '.ntt') + type = 'neuralynx_ntt'; + manufacturer = 'Neuralynx'; + content = 'continuous tetrode recordings'; +elseif strcmpi(f, 'logfile') && strcmpi(x, '.txt') % case insensitive + type = 'neuralynx_log'; + manufacturer = 'Neuralynx'; + content = 'log information in ASCII format'; +elseif ~isempty(strfind(lower(f), 'dma')) && strcmpi(x, '.log') % this is not a very strong detection + type = 'neuralynx_dma'; + manufacturer = 'Neuralynx'; + content = 'raw aplifier data directly from DMA'; +elseif filetype_check_extension(filename, '.nrd') % see also above, since Cheetah 5.x the file extension has changed + type = 'neuralynx_dma'; + manufacturer = 'Neuralynx'; + content = 'raw aplifier data directly from DMA'; +elseif isdir(filename) && (any(filetype_check_extension({ls.name}, '.nev')) || any(filetype_check_extension({ls.name}, '.Nev'))) + % a regular Neuralynx dataset directory that contains an event file + type = 'neuralynx_ds'; + manufacturer = 'Neuralynx'; + content = 'dataset'; +elseif isdir(filename) && most(filetype_check_extension({ls.name}, '.ncs')) + % a directory containing continuously sampled channels in Neuralynx format + type = 'neuralynx_ds'; + manufacturer = 'Neuralynx'; + content = 'continuously sampled channels'; +elseif isdir(filename) && most(filetype_check_extension({ls.name}, '.nse')) + % a directory containing spike waveforms in Neuralynx format + type = 'neuralynx_ds'; + manufacturer = 'Neuralynx'; + content = 'spike waveforms'; +elseif isdir(filename) && most(filetype_check_extension({ls.name}, '.nte')) + % a directory containing spike timestamps in Neuralynx format + type = 'neuralynx_ds'; + manufacturer = 'Neuralynx'; + content = 'spike timestamps'; + + % these are formally not Neuralynx file formats, but at the FCDC we use them together with Neuralynx +elseif isdir(filename) && any(ft_filetype({ls.name}, 'neuralynx_ds')) + % a downsampled Neuralynx DMA file can be split into three seperate lfp/mua/spike directories + % treat them as one combined dataset + type = 'neuralynx_cds'; + manufacturer = 'F.C. Donders Centre'; + content = 'dataset containing seperate lfp/mua/spike directories'; +elseif filetype_check_extension(filename, '.tsl') && filetype_check_header(filename, 'tsl') + type = 'neuralynx_tsl'; + manufacturer = 'F.C. Donders Centre'; + content = 'timestamps from DMA log file'; +elseif filetype_check_extension(filename, '.tsh') && filetype_check_header(filename, 'tsh') + type = 'neuralynx_tsh'; + manufacturer = 'F.C. Donders Centre'; + content = 'timestamps from DMA log file'; +elseif filetype_check_extension(filename, '.ttl') && filetype_check_header(filename, 'ttl') + type = 'neuralynx_ttl'; + manufacturer = 'F.C. Donders Centre'; + content = 'Parallel_in from DMA log file'; +elseif filetype_check_extension(filename, '.bin') && filetype_check_header(filename, {'uint8', 'uint16', 'uint32', 'int8', 'int16', 'int32', 'int64', 'float32', 'float64'}) + type = 'neuralynx_bin'; + manufacturer = 'F.C. Donders Centre'; + content = 'single channel continuous data'; +elseif isdir(filename) && any(filetype_check_extension({ls.name}, '.ttl')) && any(filetype_check_extension({ls.name}, '.tsl')) && any(filetype_check_extension({ls.name}, '.tsh')) + % a directory containing the split channels from a DMA logfile + type = 'neuralynx_sdma'; + manufacturer = 'F.C. Donders Centre'; + content = 'split DMA log file'; +elseif isdir(filename) && filetype_check_extension(filename, '.sdma') + % a directory containing the split channels from a DMA logfile + type = 'neuralynx_sdma'; + manufacturer = 'F.C. Donders Centre'; + content = 'split DMA log file'; + + % known Plexon file types +elseif filetype_check_extension(filename, '.nex') && filetype_check_header(filename, 'NEX1') + type = 'plexon_nex'; + manufacturer = 'Plexon'; + content = 'electrophysiological data'; +elseif filetype_check_extension(filename, '.plx') && filetype_check_header(filename, 'PLEX') + type = 'plexon_plx'; + manufacturer = 'Plexon'; + content = 'electrophysiological data'; +elseif filetype_check_extension(filename, '.ddt') + type = 'plexon_ddt'; + manufacturer = 'Plexon'; +elseif isdir(filename) && most(filetype_check_extension({ls.name}, '.nex')) && most(filetype_check_header({ls.name}, 'NEX1')) + % a directory containing multiple plexon NEX files + type = 'plexon_ds'; + manufacturer = 'Plexon'; + content = 'electrophysiological data'; + + % known Cambridge Electronic Design file types +elseif filetype_check_extension(filename, '.smr') + type = 'ced_son'; + manufacturer = 'Cambridge Electronic Design'; + content = 'Spike2 SON filing system'; + + % known BESA file types +elseif filetype_check_extension(filename, '.avr') && strcmp(type, 'unknown') + type = 'besa_avr'; % FIXME, can also be EEProbe average EEG + manufacturer = 'BESA'; + content = 'average EEG'; +elseif filetype_check_extension(filename, '.elp') + type = 'besa_elp'; + manufacturer = 'BESA'; + content = 'electrode positions'; +elseif filetype_check_extension(filename, '.eps') + type = 'besa_eps'; + manufacturer = 'BESA'; + content = 'digitizer information'; +elseif filetype_check_extension(filename, '.sfp') + type = 'besa_sfp'; + manufacturer = 'BESA'; + content = 'sensor positions'; +elseif filetype_check_extension(filename, '.ela') + type = 'besa_ela'; + manufacturer = 'BESA'; + content = 'sensor information'; +elseif filetype_check_extension(filename, '.pdg') + type = 'besa_pdg'; + manufacturer = 'BESA'; + content = 'paradigm file'; +elseif filetype_check_extension(filename, '.tfc') + type = 'besa_tfc'; + manufacturer = 'BESA'; + content = 'time frequency coherence'; +elseif filetype_check_extension(filename, '.mul') + type = 'besa_mul'; + manufacturer = 'BESA'; + content = 'multiplexed ascii format'; +elseif filetype_check_extension(filename, '.dat') && filetype_check_header(filename, 'BESA_SA') % header can start with BESA_SA_IMAGE or BESA_SA_MN_IMAGE + type = 'besa_src'; + manufacturer = 'BESA'; + content = 'beamformer source reconstruction'; +elseif filetype_check_extension(filename, '.swf') && filetype_check_header(filename, 'Npts=') + type = 'besa_swf'; + manufacturer = 'BESA'; + content = 'beamformer source waveform'; +elseif filetype_check_extension(filename, '.bsa') + type = 'besa_bsa'; + manufacturer = 'BESA'; + content = 'beamformer source locations and orientations'; +elseif exist(fullfile(p, [f '.dat']), 'file') && (exist(fullfile(p, [f '.gen']), 'file') || exist(fullfile(p, [f '.generic']), 'file')) + type = 'besa_sb'; + manufacturer = 'BESA'; + content = 'simple binary channel data with a seperate generic ascii header'; + + % old files from Pascal Fries' PhD research at the MPI +elseif filetype_check_extension(filename, '.dap') && filetype_check_header(filename, char(1)) + type = 'mpi_dap'; + manufacturer = 'MPI Frankfurt'; + content = 'electrophysiological data'; +elseif isdir(filename) && ~isempty(cell2mat(regexp({ls.name}, '.dap$'))) + type = 'mpi_ds'; + manufacturer = 'MPI Frankfurt'; + content = 'electrophysiological data'; + + % Frankfurt SPASS format, which uses the Labview Datalog (DTLG) format +elseif filetype_check_header(filename, 'DTLG') && filetype_check_extension(filename, '.ana') + type = 'spass_ana'; + manufacturer = 'MPI Frankfurt'; + content = 'electrophysiological data'; +elseif filetype_check_header(filename, 'DTLG') && filetype_check_extension(filename, '.swa') + type = 'spass_swa'; + manufacturer = 'MPI Frankfurt'; + content = 'electrophysiological data'; +elseif filetype_check_header(filename, 'DTLG') && filetype_check_extension(filename, '.spi') + type = 'spass_spi'; + manufacturer = 'MPI Frankfurt'; + content = 'electrophysiological data'; +elseif filetype_check_header(filename, 'DTLG') && filetype_check_extension(filename, '.stm') + type = 'spass_stm'; + manufacturer = 'MPI Frankfurt'; + content = 'electrophysiological data'; +elseif filetype_check_header(filename, 'DTLG') && filetype_check_extension(filename, '.bhv') + type = 'spass_bhv'; + manufacturer = 'MPI Frankfurt'; + content = 'electrophysiological data'; + + % known Chieti ITAB file types +elseif filetype_check_extension(filename, '.raw') && (filetype_check_header(filename, 'FORMAT: ATB-BIOMAGDATA') || filetype_check_header(filename, '[HeaderType]')) + type = 'itab_raw'; + manufacturer = 'Chieti ITAB'; + content = 'MEG data, including sensor positions'; +elseif filetype_check_extension(filename, '.raw.mhd') + type = 'itab_mhd'; + manufacturer = 'Chieti ITAB'; + content = 'MEG header data, including sensor positions'; +elseif filetype_check_extension(filename, '.asc') + type = 'itab_asc'; + manufacturer = 'Chieti ITAB'; + content = 'headshape digitization file'; + + % known Nexstim file types +elseif filetype_check_extension(filename, '.nxe') + type = 'nexstim_nxe'; + manufacturer = 'Nexstim'; + content = 'electrophysiological data'; + + % known Tucker-Davis-Technology file types +elseif filetype_check_extension(filename, '.tbk') + type = 'tdt_tbk'; + manufacturer = 'Tucker-Davis-Technology'; + content = 'database/tank meta-information'; +elseif filetype_check_extension(filename, '.tdx') + type = 'tdt_tdx'; + manufacturer = 'Tucker-Davis-Technology'; + content = 'database/tank meta-information'; +elseif filetype_check_extension(filename, '.tsq') + type = 'tdt_tsq'; + manufacturer = 'Tucker-Davis-Technology'; + content = 'block header information'; +elseif filetype_check_extension(filename, '.tev') + type = 'tdt_tev'; + manufacturer = 'Tucker-Davis-Technology'; + content = 'electrophysiological data'; + + % known Curry V4 file types +elseif filetype_check_extension(filename, '.dap') + type = 'curry_dap'; % FIXME, can also be MPI Frankfurt electrophysiological data + manufacturer = 'Curry'; + content = 'data parameter file'; +elseif filetype_check_extension(filename, '.dat') + type = 'curry_dat'; + manufacturer = 'Curry'; + content = 'raw data file'; +elseif filetype_check_extension(filename, '.rs4') + type = 'curry_rs4'; + manufacturer = 'Curry'; + content = 'sensor geometry file'; +elseif filetype_check_extension(filename, '.par') + type = 'curry_par'; + manufacturer = 'Curry'; + content = 'data or image parameter file'; +elseif filetype_check_extension(filename, '.bd0') || filetype_check_extension(filename, '.bd1') || filetype_check_extension(filename, '.bd2') || filetype_check_extension(filename, '.bd3') || filetype_check_extension(filename, '.bd4') || filetype_check_extension(filename, '.bd5') || filetype_check_extension(filename, '.bd6') || filetype_check_extension(filename, '.bd7') || filetype_check_extension(filename, '.bd8') || filetype_check_extension(filename, '.bd9') + type = 'curry_bd'; + manufacturer = 'Curry'; + content = 'BEM description file'; +elseif filetype_check_extension(filename, '.bt0') || filetype_check_extension(filename, '.bt1') || filetype_check_extension(filename, '.bt2') || filetype_check_extension(filename, '.bt3') || filetype_check_extension(filename, '.bt4') || filetype_check_extension(filename, '.bt5') || filetype_check_extension(filename, '.bt6') || filetype_check_extension(filename, '.bt7') || filetype_check_extension(filename, '.bt8') || filetype_check_extension(filename, '.bt9') + type = 'curry_bt'; + manufacturer = 'Curry'; + content = 'BEM transfer matrix file'; +elseif filetype_check_extension(filename, '.bm0') || filetype_check_extension(filename, '.bm1') || filetype_check_extension(filename, '.bm2') || filetype_check_extension(filename, '.bm3') || filetype_check_extension(filename, '.bm4') || filetype_check_extension(filename, '.bm5') || filetype_check_extension(filename, '.bm6') || filetype_check_extension(filename, '.bm7') || filetype_check_extension(filename, '.bm8') || filetype_check_extension(filename, '.bm9') + type = 'curry_bm'; + manufacturer = 'Curry'; + content = 'BEM full matrix file'; +elseif filetype_check_extension(filename, '.dig') + type = 'curry_dig'; + manufacturer = 'Curry'; + content = 'digitizer file'; + + % known SR Research eyelink file formats +elseif filetype_check_extension(filename, '.asc') && filetype_check_header(filename, '**') + type = 'eyelink_asc'; + manufacturer = 'SR Research (ascii)'; + content = 'eyetracker data'; +elseif filetype_check_extension(filename, '.edf') && filetype_check_header(filename, 'SR_RESEARCH') + type = 'eyelink_edf'; + manufacturer = 'SR Research'; + content = 'eyetracker data (binary)'; + + % known Curry V2 file types +elseif filetype_check_extension(filename, '.sp0') || filetype_check_extension(filename, '.sp1') || filetype_check_extension(filename, '.sp2') || filetype_check_extension(filename, '.sp3') || filetype_check_extension(filename, '.sp4') || filetype_check_extension(filename, '.sp5') || filetype_check_extension(filename, '.sp6') || filetype_check_extension(filename, '.sp7') || filetype_check_extension(filename, '.sp8') || filetype_check_extension(filename, '.sp9') + type = 'curry_sp'; + manufacturer = 'Curry'; + content = 'point list'; +elseif filetype_check_extension(filename, '.s10') || filetype_check_extension(filename, '.s11') || filetype_check_extension(filename, '.s12') || filetype_check_extension(filename, '.s13') || filetype_check_extension(filename, '.s14') || filetype_check_extension(filename, '.s15') || filetype_check_extension(filename, '.s16') || filetype_check_extension(filename, '.s17') || filetype_check_extension(filename, '.s18') || filetype_check_extension(filename, '.s19') || filetype_check_extension(filename, '.s20') || filetype_check_extension(filename, '.s21') || filetype_check_extension(filename, '.s22') || filetype_check_extension(filename, '.s23') || filetype_check_extension(filename, '.s24') || filetype_check_extension(filename, '.s25') || filetype_check_extension(filename, '.s26') || filetype_check_extension(filename, '.s27') || filetype_check_extension(filename, '.s28') || filetype_check_extension(filename, '.s29') || filetype_check_extension(filename, '.s30') || filetype_check_extension(filename, '.s31') || filetype_check_extension(filename, '.s32') || filetype_check_extension(filename, '.s33') || filetype_check_extension(filename, '.s34') || filetype_check_extension(filename, '.s35') || filetype_check_extension(filename, '.s36') || filetype_check_extension(filename, '.s37') || filetype_check_extension(filename, '.s38') || filetype_check_extension(filename, '.s39') + type = 'curry_s'; + manufacturer = 'Curry'; + content = 'triangle or tetraedra list'; +elseif filetype_check_extension(filename, '.pom') + type = 'curry_pom'; + manufacturer = 'Curry'; + content = 'anatomical localization file'; +elseif filetype_check_extension(filename, '.res') + type = 'curry_res'; + manufacturer = 'Curry'; + content = 'functional localization file'; + + % known MBFYS file types +elseif filetype_check_extension(filename, '.tri') + type = 'mbfys_tri'; + manufacturer = 'MBFYS'; + content = 'triangulated surface'; +elseif filetype_check_extension(filename, '.ama') && filetype_check_header(filename, [10 0 0 0]) + type = 'mbfys_ama'; + manufacturer = 'MBFYS'; + content = 'BEM volume conduction model'; + + % Electrical Geodesics Incorporated format +elseif (filetype_check_extension(filename, '.egis') || filetype_check_extension(filename, '.ave') || filetype_check_extension(filename, '.gave') || filetype_check_extension(filename, '.raw')) && (filetype_check_header(filename, [char(1) char(2) char(3) char(4) char(255) char(255)]) || filetype_check_header(filename, [char(3) char(4) char(1) char(2) char(255) char(255)])) + type = 'egi_egia'; + manufacturer = 'Electrical Geodesics Incorporated'; + content = 'averaged EEG data'; +elseif (filetype_check_extension(filename, '.egis') || filetype_check_extension(filename, '.ses') || filetype_check_extension(filename, '.raw')) && (filetype_check_header(filename, [char(1) char(2) char(3) char(4) char(0) char(3)]) || filetype_check_header(filename, [char(3) char(4) char(1) char(2) char(0) char(3)])) + type = 'egi_egis'; + manufacturer = 'Electrical Geodesics Incorporated'; + content = 'raw EEG data'; +elseif (filetype_check_extension(filename, '.sbin') || filetype_check_extension(filename, '.raw')) + % note that the Chieti MEG data format also has the extension *.raw + % but that can be detected by looking at the file header + type = 'egi_sbin'; + manufacturer = 'Electrical Geodesics Incorporated'; + content = 'averaged EEG data'; + + + % some other known file types +elseif length(filename)>4 && exist([filename(1:(end-4)) '.mat'], 'file') && exist([filename(1:(end-4)) '.bin'], 'file') + % this is a self-defined FCDC data format, consisting of two files + % there is a matlab V6 file with the header and a binary file with the data (multiplexed, ieee-le, double) + type = 'fcdc_matbin'; + manufacturer = 'F.C. Donders Centre'; + content = 'multiplexed electrophysiology data'; +elseif filetype_check_extension(filename, '.lay') + type = 'layout'; + manufacturer = 'Ole Jensen'; + content = 'layout of channels for plotting'; +elseif filetype_check_extension(filename, '.dcm') || filetype_check_extension(filename, '.ima') || filetype_check_header(filename, 'DICM', 128) + type = 'dicom'; + manufacturer = 'Dicom'; + content = 'image data'; +elseif filetype_check_extension(filename, '.trl') + type = 'fcdc_trl'; + manufacturer = 'F.C.Donders'; + content = 'trial definitions'; +elseif filetype_check_header(filename, [255 'BIOSEMI']) % filetype_check_extension(filename, '.bdf') + type = 'biosemi_bdf'; + % type = 'bham_bdf'; + manufacturer = 'Biosemi Data Format'; + content = 'electrophysiological data'; +elseif filetype_check_extension(filename, '.edf') + type = 'edf'; + manufacturer = 'European Data Format'; + content = 'electrophysiological data'; +elseif filetype_check_extension(filename, '.gdf') && filetype_check_header(filename, 'GDF') + type = 'gdf'; + manufacturer = 'BIOSIG - Alois Schloegl'; + content = 'biosignals'; +elseif filetype_check_extension(filename, '.mat') && filetype_check_header(filename, 'MATLAB') && filetype_check_spmeeg_mat(filename) + type = 'spmeeg_mat'; + manufacturer = 'Wellcome Trust Centre for Neuroimaging, UCL, UK'; + content = 'electrophysiological data'; +elseif filetype_check_extension(filename, '.mat') && filetype_check_header(filename, 'MATLAB') && filetype_check_ced_spike6mat(filename) + type = 'ced_spike6mat'; + manufacturer = 'Cambridge Electronic Design Limited'; + content = 'electrophysiological data'; +elseif filetype_check_extension(filename, '.mat') && filetype_check_header(filename, 'MATLAB') + type = 'matlab'; + manufacturer = 'Matlab'; + content = 'Matlab binary data'; +elseif filetype_check_header(filename, 'RIFF', 0) && filetype_check_header(filename, 'WAVE', 8) + type = 'riff_wave'; + manufacturer = 'Microsoft'; + content = 'audio'; +elseif filetype_check_extension(filename, '.txt') + type = 'ascii_txt'; + manufacturer = ''; + content = ''; +elseif filetype_check_extension(filename, '.pol') + type = 'polhemus_fil'; + manufacturer = 'Functional Imaging Lab, London, UK'; + content = 'headshape points'; +elseif filetype_check_extension(filename, '.set') + type = 'eeglab_set'; + manufacturer = 'Swartz Center for Computational Neuroscience, San Diego, USA'; + content = 'electrophysiological data'; +elseif filetype_check_extension(filename, '.t') && filetype_check_header(filename, '%%BEGINHEADER') + type = 'mclust_t'; + manufacturer = 'MClust'; + content = 'sorted spikes'; +elseif filetype_check_header(filename, 26) + type = 'nimh_cortex'; + manufacturer = 'NIMH Laboratory of Neuropsychology, http://www.cortex.salk.edu'; + content = 'events and eye channels'; +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% finished determining the filetype +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +if strcmp(type, 'unknown') + warning('could not determine filetype of %s', filename); +end + +if ~isempty(desired) + % return a boolean value instead of a descriptive string + type = strcmp(type, desired); +end + +% remember the current input and output arguments, so that they can be +% reused on a subsequent call in case the same input argument is given +current_argout = {type}; +if isempty(previous_argin) && ~strcmp(type, 'unknown') + previous_argin = current_argin; + previous_argout = current_argout; + previous_pwd = current_pwd; +else + % don't remember in case unknown + previous_argin = []; + previous_argout = []; + previous_pwd = []; +end + +return % filetype main() + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION that helps in deciding whether a directory with files should +% be treated as a "dataset". This function returns a logical 1 (TRUE) if more +% than half of the element of a vector are nonzero number or are 1 or TRUE. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function y = most(x) +x = x(~isnan(x(:))); +y = sum(x==0). +% +% $Id: ft_filter_event.m 944 2010-04-21 16:08:12Z roboos $ + +% get the optional input arguments +type = keyval('type', varargin); +value = keyval('value', varargin); +sample = keyval('sample', varargin); +timestamp = keyval('timestamp', varargin); +offset = keyval('offset', varargin); +duration = keyval('duration', varargin); + +% the numeric fields can also be filtered on a range +minsample = keyval('minsample', varargin); +maxsample = keyval('maxsample', varargin); +minduration = keyval('minduration', varargin); +maxduration = keyval('maxduration', varargin); +mintimestamp = keyval('mintimestamp', varargin); +maxtimestamp = keyval('maxtimestamp', varargin); +minnumber = keyval('minnumber', varargin); +maxnumber = keyval('maxnumber', varargin); + +if ~isempty(type) + % this can be specified as string or as cell-array, convert to cell-array + if ~iscell(type) + type = {type}; + end +end + +% determine which filters to apply +testtype = ~isempty(type) && isfield(event, 'type'); +testvalue = ~isempty(value) && isfield(event, 'value'); +testsample = ~isempty(sample) && isfield(event, 'sample'); +testtimestamp = ~isempty(timestamp) && isfield(event, 'timestamp'); +testoffset = ~isempty(offset) && isfield(event, 'offset'); +testduration = ~isempty(duration) && isfield(event, 'duration'); +testminsample = ~isempty(minsample) && isfield(event, 'sample'); +testmaxsample = ~isempty(maxsample) && isfield(event, 'sample'); +testminduration = ~isempty(minduration) && isfield(event, 'duration'); +testmaxduration = ~isempty(maxduration) && isfield(event, 'duration'); +testmintimestamp = ~isempty(mintimestamp) && isfield(event, 'timestamp'); +testmaxtimestamp = ~isempty(maxtimestamp) && isfield(event, 'timestamp'); +testminnumber = ~isempty(minnumber) && isfield(event, 'number'); +testmaxnumber = ~isempty(maxnumber) && isfield(event, 'number'); + +if (~isempty(minnumber) || ~isempty(maxnumber)) && ~isfield(event, 'number') + warning('the events are not numbered, assuming that the order corresponds to the original stream sequence'); + for i=1:length(event) + event(i).number = i; + end + testminnumber = ~isempty(minnumber); + testmaxnumber = ~isempty(maxnumber); +end + +% apply the filters +sel = true(length(event),1); +for i=1:length(event) + % test whether they match with the selected arrays + if testvalue, sel(i) = sel(i) && any(event(i).value == value); end + if testsample, sel(i) = sel(i) && any(event(i).sample == sample); end + if testtimestamp, sel(i) = sel(i) && any(event(i).timestamp == timestamp); end + if testoffset, sel(i) = sel(i) && any(event(i).offset == offset); end + if testduration, sel(i) = sel(i) && any(event(i).duration == duration); end + % test whether they lie within the specified range + if testminsample, sel(i) = sel(i) && (event(i).sample >= minsample); end + if testmaxsample, sel(i) = sel(i) && (event(i).sample <= maxsample); end + if testminduration, sel(i) = sel(i) && (event(i).duration >= minduration); end + if testmaxduration, sel(i) = sel(i) && (event(i).duration <= maxduration); end + if testmintimestamp, sel(i) = sel(i) && (event(i).timestamp >= mintimestamp); end + if testmaxtimestamp, sel(i) = sel(i) && (event(i).timestamp <= maxtimestamp); end + if testminnumber, sel(i) = sel(i) && (event(i).number >= minnumber); end + if testmaxnumber, sel(i) = sel(i) && (event(i).number <= maxnumber); end + % this is potentially the slowest test, hence do it the last + if testtype, sel(i) = sel(i) && any(strcmp(event(i).type, type)); end +end + +event = event(sel); diff --git a/external/fieldtrip/fileio/ft_flush_data.m b/external/fieldtrip/fileio/ft_flush_data.m new file mode 100644 index 0000000..cadf5c5 --- /dev/null +++ b/external/fieldtrip/fileio/ft_flush_data.m @@ -0,0 +1,61 @@ +function ft_flush_data(filename, varargin) + +% FT_FLUSH_DATA removes all data from the data queue +% +% Use as +% ft_flush_data(filename, ...) +% +% See also FT_FLUSH_HEADER, FT_FLUSH_EVENT + +% Copyright (C) 2007-2010 Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_flush_data.m 944 2010-04-21 16:08:12Z roboos $ + +% set the defaults +dataformat = keyval('dataformat', varargin); if isempty(dataformat), dataformat = ft_filetype(filename); end + +switch dataformat + case 'disp' + % nothing to do + + case 'fcdc_buffer' + [host, port] = filetype_check_uri(filename); + buffer('flush_dat', [], host, port); + + case 'fcdc_mysql' + % open the database + [user, password, server, port] = filetype_check_uri(filename); + if ~isempty(port) + server = sprintf('%s:%d', server, port); + end + mysql('open', server, user, password); + % remove all previous data + cmd = 'TRUNCATE TABLE fieldtrip.data'; + mysql(cmd); + mysql('close'); + + case 'matlab' + if exist(filename, 'file') + warning(sprintf('deleting existing file ''%s''', filename)); + delete(filename); + end + + otherwise + error('unsupported data format'); +end diff --git a/external/fieldtrip/fileio/ft_flush_event.m b/external/fieldtrip/fileio/ft_flush_event.m new file mode 100644 index 0000000..2c34642 --- /dev/null +++ b/external/fieldtrip/fileio/ft_flush_event.m @@ -0,0 +1,64 @@ +function ft_flush_event(filename, varargin) + +% FT_FLUSH_EVENT removes all events from the event queue +% +% Use as +% ft_flush_event(filename, ...) +% +% See also FT_FLUSH_HEADER, FT_FLUSH_DATA + +% Copyright (C) 2007-2010 Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_flush_event.m 944 2010-04-21 16:08:12Z roboos $ + +% TODO implement filtering + +% set the defaults +eventformat = keyval('eventformat', varargin); if isempty(eventformat), eventformat = ft_filetype(filename); end + +switch eventformat + case 'disp' + % nothing to do + + case 'fcdc_buffer' + [host, port] = filetype_check_uri(filename); + buffer('flush_evt', [], host, port); + + case 'fcdc_mysql' + % open the database + [user, password, server, port] = filetype_check_uri(filename); + if ~isempty(port) + server = sprintf('%s:%d', server, port); + end + mysql('open', server, user, password); + % remove all previous event information + cmd = 'TRUNCATE TABLE fieldtrip.event'; + mysql(cmd); + mysql('close'); + + case 'matlab' + if exist(filename, 'file') + warning(sprintf('deleting existing file ''%s''', filename)); + delete(filename); + end + + otherwise + error('unsupported data format'); +end + diff --git a/external/fieldtrip/fileio/ft_flush_header.m b/external/fieldtrip/fileio/ft_flush_header.m new file mode 100644 index 0000000..a2e40de --- /dev/null +++ b/external/fieldtrip/fileio/ft_flush_header.m @@ -0,0 +1,62 @@ +function ft_flush_header(filename, varargin) + +% FT_FLUSH_HEADER removes the header information from the data queue +% this also removes all data associated with the specific header. +% +% Use as +% ft_flush_header(filename, ...) +% +% See also FT_FLUSH_DATA, FT_FLUSH_EVENT + +% Copyright (C) 2007-2010 Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_flush_header.m 944 2010-04-21 16:08:12Z roboos $ + +% set the defaults +headerformat = keyval('headerformat', varargin); if isempty(headerformat), headerformat = ft_filetype(filename); end + +switch headerformat + case 'disp' + % nothing to do + + case 'fcdc_buffer' + [host, port] = filetype_check_uri(filename); + buffer('flush_hdr', [], host, port); + + case 'fcdc_mysql' + % open the database + [user, password, server, port] = filetype_check_uri(filename); + if ~isempty(port) + server = sprintf('%s:%d', server, port); + end + mysql('open', server, user, password); + % remove all previous header information + cmd = 'TRUNCATE TABLE fieldtrip.header'; + mysql(cmd); + mysql('close'); + + case 'matlab' + if exist(filename, 'file') + warning(sprintf('deleting existing file ''%s''', filename)); + delete(filename); + end + + otherwise + error('unsupported data format'); +end diff --git a/external/fieldtrip/fileio/ft_poll_buffer.m b/external/fieldtrip/fileio/ft_poll_buffer.m new file mode 100644 index 0000000..9961cdc --- /dev/null +++ b/external/fieldtrip/fileio/ft_poll_buffer.m @@ -0,0 +1,80 @@ +function numbers = ft_poll_buffer(filename, thresholds, timeout) +% FT_POLL_BUFFER polls the FieldTrip buffer described by 'filename' for +% the number of events and samples. You can also use this function to +% wait up to a given amount of milliseconds until the number of samples +% OR the number of events present in the buffer is bigger than a specified +% threshold. The output of this function is a struct with elements +% 'nsamples' and 'nevents', that always contain the current quantities. +% (So in case of timeouts, these might be smaller than the thresholds). +% +% Examples +% -------- +% The following will immediately return the two quantities: +% >> numbers = ft_poll_buffer('buffer://localhost:1972'); +% +% The following will wait up to 50 milliseconds for more than 100 samples in the buffer. +% thr = []; thr.nsamples = 100; timeout = 50; +% numbers = ft_poll_buffer('buffer://localhost:1972', thr, timeout); +% +% The following will wait up to 80 milliseconds for more than 30 events in the buffer. +% thr = []; thr.nevents = 30; timeout = 80; +% numbers = ft_poll_buffer('buffer://localhost:1972', thr, timeout); +% +% Repeatedly wait for new data (either samples or events): +% +% lastNum = []; +% lastNum.nevents = 0; +% lastNum.nsamples = 0; +% timeout = 100; +% while someCriterion +% newNum = ft_poll_buffer('buffer://localhost:1972', lastNum, timeout); +% if newNum.nsamples > lastNum.nsamples +% ... read and process samples ... +% if newNum.nevents > lastNum.nevents +% ... read and process events ... +% lastNum = newNum; +% end + +% Copyright (C) 2010, Stefan Klanke +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: $ + +threshtime = [-1 -1 0]; +if nargin>1 + if isfield(thresholds, 'nsamples') + threshtime(1) = thresholds.nsamples; + end + if isfield(thresholds, 'nevents') + threshtime(2) = thresholds.nevents; + end +end +if nargin>2 + threshtime(3) = timeout; +end + +% determine the filetype +dataformat = ft_filetype(filename); +switch dataformat + case 'fcdc_buffer' + % read from a networked buffer for realtime analysis + [host, port] = filetype_check_uri(filename); + numbers = buffer('wait_dat', threshtime, host, port); + otherwise + error 'Polling not supported for this data format.'; +end \ No newline at end of file diff --git a/external/fieldtrip/fileio/ft_read_data.m b/external/fieldtrip/fileio/ft_read_data.m new file mode 100644 index 0000000..e15c558 --- /dev/null +++ b/external/fieldtrip/fileio/ft_read_data.m @@ -0,0 +1,1009 @@ +function [dat] = ft_read_data(filename, varargin); + +% FT_READ_DATA reads electrophysiological data from a variety of EEG, +% MEG and LFP files and represents it in a common data-independent +% format. The supported formats are listed in the accompanying +% FT_READ_HEADER function. +% +% Use as +% dat = ft_read_data(filename, ...) +% +% Additional options should be specified in key-value pairs and can be +% 'header' header structure, see READ_HEADER +% 'begsample' first sample to read +% 'endsample' last sample to read +% 'begtrial' first trial to read, mutually exclusive with begsample+endsample +% 'endtrial' last trial to read, mutually exclusive with begsample+endsample +% 'chanindx' list with channel indices to read +% 'checkboundary' boolean, whether to check for reading segments over a trial boundary +% 'cache' boolean, whether to use caching for multiple reads +% 'dataformat' string +% 'headerformat' string +% 'fallback' can be empty or 'biosig' (default = []) +% +% This function returns a 2-D matrix of size Nchans*Nsamples for +% continuous data when begevent and endevent are specified, or a 3-D +% matrix of size Nchans*Nsamples*Ntrials for epoched or trial-based +% data when begtrial and endtrial are specified. +% +% See also FT_READ_HEADER, FT_READ_EVENT, FT_WRITE_DATA, FT_WRITE_EVENT + +% Copyright (C) 2003-2010 Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_read_data.m 1261 2010-06-22 15:09:23Z roboos $ + +persistent cachedata % for caching +persistent db_blob % for fcdc_mysql + +if isempty(db_blob) + db_blob = 0; +end + +% get the optional input arguments +hdr = keyval('header', varargin); +begsample = keyval('begsample', varargin); +endsample = keyval('endsample', varargin); +begtrial = keyval('begtrial', varargin); +endtrial = keyval('endtrial', varargin); +chanindx = keyval('chanindx', varargin); +checkboundary = keyval('checkboundary', varargin); +dataformat = keyval('dataformat', varargin); +headerformat = keyval('headerformat', varargin); +fallback = keyval('fallback', varargin); +cache = keyval('cache', varargin); if isempty(cache), cache = 0; end + +% determine the filetype +if isempty(dataformat) + dataformat = ft_filetype(filename); +end + +% test whether the file or directory exists +if ~exist(filename, 'file') && ~strcmp(dataformat, 'ctf_shm') && ~strcmp(dataformat, 'fcdc_mysql') && ... + ~strcmp(dataformat, 'fcdc_buffer') + error('FILEIO:InvalidFileName', 'file or directory ''%s'' does not exist', filename); +end + +% ensure that these are double precision and not integers, otherwise the subsequent computations will be messed up +begsample = double(begsample); +endsample = double(endsample); +begtrial = double(begtrial); +endtrial = double(endtrial); + +% ensure that the requested sample and trial numbers are integers +if ~isempty(begsample) && mod(begsample, 1) + warning('rounding "begsample" to the nearest integer'); + begsample = round(begsample); +end +if ~isempty(endsample) && ~isinf(endsample) && mod(endsample, 1) + warning('rounding "endsample" to the nearest integer'); + endsample = round(endsample); +end +if ~isempty(begtrial) && mod(begtrial, 1) + warning('rounding "begtrial" to the nearest integer'); + begtrial = round(begtrial); +end +if ~isempty(endtrial) && mod(endtrial, 1) + warning('rounding "endtrial" to the nearest integer'); + endtrial = round(endtrial); +end + +switch dataformat + case '4d_pdf' + datafile = filename; + headerfile = [datafile '.m4d']; + sensorfile = [datafile '.xyz']; + case {'4d_m4d', '4d_xyz'} + datafile = filename(1:(end-4)); % remove the extension + headerfile = [datafile '.m4d']; + sensorfile = [datafile '.xyz']; + case '4d' + [path, file, ext] = fileparts(filename); + datafile = fullfile(path, [file,ext]); + headerfile = fullfile(path, [file,ext]); + configfile = fullfile(path, 'config'); + case {'ctf_ds', 'ctf_old'} + % convert CTF filename into filenames + [path, file, ext] = fileparts(filename); + if any(strcmp(ext, {'.res4' '.meg4', '.1_meg4' '.2_meg4' '.3_meg4' '.4_meg4' '.5_meg4' '.6_meg4' '.7_meg4' '.8_meg4' '.9_meg4'})) + filename = path; + [path, file, ext] = fileparts(filename); + end + if isempty(path) && isempty(file) + % this means that the dataset was specified as the present working directory, i.e. only with '.' + filename = pwd; + [path, file, ext] = fileparts(filename); + end + headerfile = fullfile(filename, [file '.res4']); + datafile = fullfile(filename, [file '.meg4']); + if length(path)>3 && strcmp(path(end-2:end), '.ds') + filename = path; % this is the *.ds directory + end + case 'ctf_meg4' + [path, file, ext] = fileparts(filename); + if isempty(path) + path = pwd; + end + headerfile = fullfile(path, [file '.res4']); + datafile = fullfile(path, [file '.meg4']); + if length(path)>3 && strcmp(path(end-2:end), '.ds') + filename = path; % this is the *.ds directory + end + case 'ctf_res4' + [path, file, ext] = fileparts(filename); + if isempty(path) + path = pwd; + end + headerfile = fullfile(path, [file '.res4']); + datafile = fullfile(path, [file '.meg4']); + if length(path)>3 && strcmp(path(end-2:end), '.ds') + filename = path; % this is the *.ds directory + end + case 'brainvision_vhdr' + [path, file, ext] = fileparts(filename); + headerfile = fullfile(path, [file '.vhdr']); + if exist(fullfile(path, [file '.eeg'])) + datafile = fullfile(path, [file '.eeg']); + elseif exist(fullfile(path, [file '.seg'])) + datafile = fullfile(path, [file '.seg']); + elseif exist(fullfile(path, [file '.dat'])) + datafile = fullfile(path, [file '.dat']); + end + case 'brainvision_eeg' + [path, file, ext] = fileparts(filename); + headerfile = fullfile(path, [file '.vhdr']); + datafile = fullfile(path, [file '.eeg']); + case 'brainvision_seg' + [path, file, ext] = fileparts(filename); + headerfile = fullfile(path, [file '.vhdr']); + datafile = fullfile(path, [file '.seg']); + case 'brainvision_dat' + [path, file, ext] = fileparts(filename); + headerfile = fullfile(path, [file '.vhdr']); + datafile = fullfile(path, [file '.dat']); + case 'itab_raw' + [path, file, ext] = fileparts(filename); + headerfile = fullfile(path, [file '.raw.mhd']); + datafile = fullfile(path, [file '.raw']); + case 'fcdc_matbin' + [path, file, ext] = fileparts(filename); + headerfile = fullfile(path, [file '.mat']); + datafile = fullfile(path, [file '.bin']); + case {'tdt_tsq' 'tdt_tev'} + [path, file, ext] = fileparts(filename); + headerfile = fullfile(path, [file '.tsq']); + datafile = fullfile(path, [file '.tev']); + case 'nmc_archive_k' + [path, file, ext] = fileparts(filename); + headerfile = [path '/' file 'newparams.txt']; + if isempty(headerformat) + headerformat = 'nmc_archive_k'; + end + if isempty(hdr) + hdr = ft_read_header(headerfile, 'headerformat', headerformat); + end + datafile = filename; + otherwise + % convert filename into filenames, assume that the header and data are the same + datafile = filename; + headerfile = filename; +end + +if ~strcmp(filename, datafile) && ~ismember(dataformat, {'ctf_ds', 'ctf_old'}) + filename = datafile; % this function will read the data + dataformat = ft_filetype(filename); % update the filetype +end + +% for backward compatibility, default is to check when it is not continous +if isempty(checkboundary) + checkboundary = ~keyval('continuous', varargin); +end + +% read the header if it is not provided +if isempty(hdr) + hdr = ft_read_header(filename, 'headerformat', headerformat); +end + +% set the default channel selection, which is all channels +if isempty(chanindx) + chanindx = 1:hdr.nChans; +end + +% read untill the end of the file if the endsample is "inf" +if any(isinf(endsample)) && any(endsample>0) + endsample = hdr.nSamples*hdr.nTrials; +end + +% test whether the requested channels can be accomodated +if min(chanindx)<1 || max(chanindx)>hdr.nChans + error('FILEIO:InvalidChanIndx', 'selected channels are not present in the data'); +end + +% test whether the requested data segment is not outside the file +if any(begsample<1) + error('FILEIO:InvalidBegSample', 'cannot read data before the begin of the file'); +elseif any(endsample>(hdr.nSamples*hdr.nTrials)) + error('FILEIO:InvalidEndSample', 'cannot read data after the end of the file'); +end + +requesttrials = isempty(begsample) && isempty(endsample); +requestsamples = isempty(begtrial) && isempty(endtrial); + +if cache && requesttrials + error('caching is not supported when reading trials') +end + +if isempty(begsample) && isempty(endsample) && isempty(begtrial) && isempty(endtrial) + % neither samples nor trials are specified, set the defaults to read the complete data trial-wise (also works for continuous) + requestsamples = 0; + requesttrials = 1; + begtrial = 1; + endtrial = hdr.nTrials; +end + +% set the default, which is to assume that it is should check for boundaries when samples are requested +if isempty(checkboundary) && requesttrials + checkboundary = false; +elseif isempty(checkboundary) && requestsamples + checkboundary = true; +end + +if requesttrials && requestsamples + error('you cannot select both trials and samples at the same time'); +elseif requesttrials + % this allows for support using a continuous reader + if isinf(hdr.nSamples) && begtrial==1 + begsample = 1; % computing it here does not work (0*inf=nan) + else + begsample = (begtrial-1)*hdr.nSamples + 1; % compute it the normal way + end + endsample = (endtrial )*hdr.nSamples; +elseif requestsamples + % this allows for support using a trial-based reader + begtrial = floor((begsample-1)/hdr.nSamples)+1; + endtrial = floor((endsample-1)/hdr.nSamples)+1; +else + error('you should either specify begin/end trial or begin/end sample'); +end + +% test whether the requested data segment does not extend over a discontinuous trial boundary +if checkboundary && hdr.nTrials>1 + if begtrial~=endtrial + error('requested data segment extends over a discontinuous trial boundary'); + end +end + +if strcmp(dataformat, 'bci2000_dat') + % caching for BCI2000 is handled in the main section and in read_header +else + % implement the caching in a data-format independent way + if cache && (isempty(cachedata) || ~isequal(cachedata.label,hdr.label(chanindx))) + % create a new FieldTrip raw data structure that will hold the data + cachedata.label = hdr.label(chanindx); + cachedata.fsample = hdr.Fs; + cachedata.time = {}; + cachedata.trial = {}; + cachedata.cfg = []; + cachedata.cfg.trl = zeros(0,3); + elseif cache && ~isempty(cachedata) + % try to fetch the requested segment from the cache + try + dat = fetch_data(cachedata, 'begsample', begsample', 'endsample', endsample); + % fprintf('caching succeeded\n'); + return + catch + % fprintf('caching failed\n'); + end + end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% read the data with the low-level reading function +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +switch dataformat + + case {'4d' '4d_pdf', '4d_m4d', '4d_xyz'} + [fid,message] = fopen(datafile,'rb','ieee-be'); + % determine the type and size of the samples + sampletype = lower(hdr.orig.Format); + switch sampletype + case 'short' + samplesize = 2; + case 'long' + samplesize = 4; + case 'float' + samplesize = 4; + case 'double' + samplesize = 8; + otherwise + error('unsupported data format'); + end + % 4D/BTi MEG data is multiplexed, can be epoched/discontinuous + offset = (begsample-1)*samplesize*hdr.nChans; + numsamples = endsample-begsample+1; + gain = hdr.orig.ChannelGain; + if isfield(hdr.orig, 'ChannelUnitsPerBit') + upb = hdr.orig.ChannelUnitsPerBit; + else + warning('cannot determine ChannelUnitsPerBit'); + upb = 1; + end + % jump to the desired data + fseek(fid, offset, 'cof'); + % read the desired data + if length(chanindx)==1 + % read only one channel + fseek(fid, (chanindx-1)*samplesize, 'cof'); % seek to begin of channel + dat = fread(fid, numsamples, ['1*' sampletype], (hdr.nChans-1)*samplesize)'; % read one channel, skip the rest + else + % read all channels + dat = fread(fid, [hdr.nChans, numsamples], sampletype); + end + fclose(fid); + if length(chanindx)==1 + % only one channel was selected, which is managed by the code above + % nothing to do + elseif length(chanindx)==hdr.nChans + % all channels have been selected + % nothing to do + else + % select the desired channel(s) + dat = dat(chanindx,:); + end + % determine how to calibrate the data + switch sampletype + case {'short', 'long'} + % include both the gain values and the integer-to-double conversion in the calibration + calib = diag(gain(chanindx) .* upb(chanindx)); + case {'float', 'double'} + % only include the gain values in the calibration + calib = diag(gain(chanindx)); + otherwise + error('unsupported data format'); + end + % calibrate the data + dat = calib*dat; + + case 'bci2000_dat' + % this requires the load_bcidat mex file to be present on the path + hastoolbox('BCI2000', 1); + % this is inefficient, since it reads the complete data + if isfield(hdr.orig, 'signal') && isfield(hdr.orig, 'states') + % assume that the complete data is stored in the header, this speeds up subsequent read operations + signal = hdr.orig.signal; + states = hdr.orig.states; + parameters = hdr.orig.parameters; + total_samples = hdr.orig.total_samples; + else + [signal, states, parameters, total_samples] = load_bcidat(filename); + end + % apply the callibration from AD units to uV + dat = double(signal(begsample:endsample,chanindx)'); + for i=chanindx(:)' + dat(i,:) = dat(i,:).* parameters.SourceChGain.NumericValue(i) + parameters.SourceChOffset.NumericValue(i); + end + dimord = 'chans_samples'; + + case 'besa_avr' + % BESA average data + orig = readBESAavr(filename); + dat = orig.Data(chanindx, begsample:endsample); + + case 'besa_swf' + % BESA source waveform + orig = readBESAswf(filename); + dat = orig.data(chanindx, begsample:endsample); + + case {'biosemi_bdf', 'bham_bdf'} + % this uses a mex file for reading the 24 bit data + dat = read_biosemi_bdf(filename, hdr, begsample, endsample, chanindx); + + case {'biosemi_old'} + % this uses the openbdf and readbdf functions that I copied from the EEGLAB toolbox + epochlength = hdr.orig.Head.SampleRate(1); + % it has already been checked in read_header that all channels have the same sampling rate + begepoch = floor((begsample-1)/epochlength) + 1; + endepoch = floor((endsample-1)/epochlength) + 1; + nepochs = endepoch - begepoch + 1; + orig = openbdf(filename); + dat = zeros(length(chanindx),nepochs*epochlength); + for i=begepoch:endepoch + % read and concatenate all required data epochs + [orig, buf] = readbdf(orig, i, 0); + if size(buf,2)~=hdr.nChans || size(buf,1)~=epochlength + error('error reading selected data from bdf-file'); + else + dat(:,((i-begepoch)*epochlength+1):((i-begepoch+1)*epochlength)) = buf(:,chanindx)'; + end + end + begsample = begsample - (begepoch-1)*epochlength; % correct for the number of bytes that were skipped + endsample = endsample - (begepoch-1)*epochlength; % correct for the number of bytes that were skipped + dat = dat(:, begsample:endsample); + % close the file between seperate read operations + fclose(orig.Head.FILE.FID); + + case {'biosig', 'gdf'} + % use the biosig toolbox if available + hastoolbox('BIOSIG', 1); + dat = read_biosig_data(filename, hdr, begsample, endsample, chanindx); + + case {'brainvision_eeg', 'brainvision_dat', 'brainvision_seg'} + dat = read_brainvision_eeg(filename, hdr.orig, begsample, endsample); + dat = dat(chanindx,:); % select the desired channels + + case 'ced_son' + % chek the availability of the required low-level toolbox + hastoolbox('neuroshare', 1); + % use the reading function supplied by Gijs van Elswijk + % + % CED ADC is done in sequence, thus the analog channels + % do not share the same time axis. This is _ignored_ here. + % + % Set the READ_CED_SON parameter 'readtimestamps' to + % 'yes' to get time axis for each data channel returned. + % This time information can be used to do + % a temporal realignment of the data. + tmp = read_ced_son(filename,'readdata','yes',... + 'begsample',begsample,... + 'endsample',endsample,... + 'channels',chanindx); + dat = cell2mat(tmp.data'); + + case 'itab_raw' + if ismember(hdr.orig.data_type, [0 1 2]) + % big endian + fid = fopen(datafile, 'rb', 'ieee-be'); + elseif ismember(hdr.orig.data_type, [3 4 5]) + % little endian + fid = fopen(datafile, 'rb', 'ieee-le'); + else + error('unsuppported data_type in itab format'); + end + + % skip the ascii header + fseek(fid, hdr.orig.start_data, 'bof'); + + if ismember(hdr.orig.data_type, [0 3]) + % short + fseek(fid, (begsample-1)*hdr.orig.nchan*2, 'cof'); + dat = fread(fid, [hdr.orig.nchan endsample-begsample+1], 'int16'); + elseif ismember(hdr.orig.data_type, [1 4]) + % long + fseek(fid, (begsample-1)*hdr.orig.nchan*4, 'cof'); + dat = fread(fid, [hdr.orig.nchan endsample-begsample+1], 'int32'); + elseif ismember(hdr.orig.data_type, [2 5]) + % float + fseek(fid, (begsample-1)*hdr.orig.nchan*4, 'cof'); + dat = fread(fid, [hdr.orig.nchan endsample-begsample+1], 'float'); + else + error('unsuppported data_type in itab format'); + end + % these are the channels that are visible to fieldtrip + chansel = 1:hdr.orig.nchan; + tmp = [hdr.orig.ch(chansel).calib]; + tmp = tmp(:); + tmp(tmp==0) = 1; + dat = dat ./ tmp(:,ones(1,size(dat,2))); + % select the subset of visible channels that the user requested + dat = dat(chanindx, :); + + case 'combined_ds' + dat = read_combined_ds(filename, hdr, begsample, endsample, chanindx); + + case {'ctf_ds', 'ctf_meg4', 'ctf_res4'} + % check that the required low-level toolbox is available + hastoolbox('ctf', 1); + % this returns SQUIDs in T, EEGs in V, ADC's and DACS in V, HLC channels in m, clock channels in s. + if begtrial==endtrial + % specify selection as 3x1 vector + trlbegsample = begsample - hdr.nSamples*(begtrial-1); % within the trial + trlendsample = endsample - hdr.nSamples*(begtrial-1); % within the trial + dat = getCTFdata(hdr.orig, [trlbegsample; trlendsample; begtrial], chanindx, 'T', 'double'); + dimord = 'samples_chans'; + else + % specify selection as 1xN vector + dat = getCTFdata(hdr.orig, [begtrial:endtrial], chanindx, 'T', 'double'); + dimord = 'samples_chans_trials'; + end + + case {'ctf_old', 'read_ctf_meg4'} + % read it using the open-source matlab code that originates from CTF and that was modified by the FCDC + dat = read_ctf_meg4(datafile, hdr.orig, begsample, endsample, chanindx); + + case 'ctf_read_meg4' + % check that the required low-level toolbox is available + hastoolbox('eegsf', 1); + % read it using the CTF importer from the NIH and Daren Weber + tmp = ctf_read_meg4(filename, hdr.orig, chanindx, 'all', begtrial:endtrial); + dat = cat(3, tmp.data{:}); + % the data is shaped in a 3-D array + dimord = 'samples_chans_trials'; + + case 'ctf_shm' + % contact Robert Oostenveld if you are interested in real-time acquisition on the CTF system + % read the data from shared memory + [dat, dimord] = read_shm_data(hdr, chanindx, begtrial, endtrial); + + case 'eeglab_set' + dat = read_eeglabdata(filename, 'header', hdr, 'begtrial', begtrial, 'endtrial', endtrial, 'chanindx', chanindx); + dimord = 'chans_samples_trials'; + + case 'spmeeg_mat' + dat = read_spmeeg_data(filename, 'header', hdr, 'begsample', begsample, 'endsample', endsample, 'chanindx', chanindx); + + case 'ced_spike6mat' + dat = read_spike6mat_data(filename, 'header', hdr, 'begsample', begsample, 'endsample', endsample, 'chanindx', chanindx); + + case {'edf'} + % this reader is largely similar to the one for bdf + % it uses a mex file for reading the 16 bit data + dat = read_edf(filename, hdr, begsample, endsample, chanindx); + + case 'eep_avr' + % check that the required low-level toolbos ix available + hastoolbox('eeprobe', 1); + dat = read_eep_avr(filename); + dat = dat.data(chanindx,begsample:endsample); % select the desired channels and samples + + case 'eep_cnt' + % check that the required low-level toolbos ix available + hastoolbox('eeprobe', 1); + dat = read_eep_cnt(filename, begsample, endsample); + dat = dat.data(chanindx,:); % select the desired channels + + case 'eyelink_asc' + if isfield(hdr.orig, 'dat') + % this is inefficient, since it keeps the complete data in memory + % but it does speed up subsequent read operations without the user + % having to care about it + asc = hdr.orig; + else + asc = read_eyelink_asc(filename); + end + dat = asc.dat(chanindx,begsample:endsample); + + case 'fcdc_buffer' + % read from a networked buffer for realtime analysis + [host, port] = filetype_check_uri(filename); + dat = buffer('get_dat', [begsample-1 endsample-1], host, port); % indices should be zero-offset + dat = dat.buf(chanindx,:); % select the desired channels + + case 'fcdc_matbin' + % multiplexed data in a *.bin file, accompanied by a matlab file containing the header + offset = begsample-1; + numsamples = endsample-begsample+1; + if isfield(hdr, 'precision'), + sampletype = hdr.precision; + else + sampletype = 'double'; %original format without precision info in hdr is always in double + end + if strcmp(sampletype, 'single') + samplesize = 4; + elseif strcmp(sampletype, 'double') + samplesize = 8; + end + [fid,message] = fopen(datafile,'rb','ieee-le'); + % jump to the desired data + fseek(fid, offset*samplesize*hdr.nChans, 'cof'); + % read the desired data + if length(chanindx)==1 + % read only one channel + fseek(fid, (chanindx-1)*samplesize, 'cof'); % seek to begin of channel + dat = fread(fid, numsamples, ['1*' sampletype], (hdr.nChans-1)*samplesize)'; % read one channel, skip the rest + else + % read all channels + dat = fread(fid, [hdr.nChans, numsamples], sampletype); + end + fclose(fid); + if length(chanindx)==1 + % only one channel was selected, which is managed by the code above + % nothing to do + elseif length(chanindx)==hdr.nChans + % all channels have been selected + % nothing to do + else + % select the desired channel(s) + dat = dat(chanindx,:); + end + + case 'fcdc_mysql' + % read from a MySQL server listening somewhere else on the network + db_open(filename); + if db_blob + error('not implemented'); + else + for i=begtrial:endtrial + s = db_select('fieldtrip.data', {'nChans', 'nSamples', 'data'}, i); + dum{i-begtrial+1} = mxDeserialize(s.data); + end + dat = zeros(length(chanindx), s.nSamples, endtrial-begtrial+1); + for i=begtrial:endtrial + dat(:,:,i-begtrial+1) = dum{i-begtrial+1}(chanindx,:); + end + dimord = 'chans_samples_trials'; + end + + case {'egi_egia', 'egi_egis'} + dat = read_egis_data(filename, hdr, begtrial, endtrial, chanindx); + dimord = 'chans_samples_trials'; + + case {'egi_sbin'} + if mod(hdr.orig.header_array(1),2)==0, + %unsegmented data contains only 1 trial, don't read the whole file + dat = read_sbin_data(filename, hdr, begsample, endsample, chanindx); + requestsamples = 0; + else + %segmented data + dat = read_sbin_data(filename, hdr, begtrial, endtrial, chanindx); + end + dimord = 'chans_samples_trials'; + + case 'micromed_trc' + dat = read_micromed_trc(filename, begsample, endsample); + dat = dat(chanindx,:); + dimord = 'chans_samples'; + + case {'mpi_ds', 'mpi_dap'} + [hdr, dat] = read_mpi_ds(filename); + dat = dat(chanindx, begsample:endsample); % select the desired channels and samples + + case 'neuralynx_dma' + dat = read_neuralynx_dma(filename, begsample, endsample, chanindx); + + case 'neuralynx_sdma' + dat = read_neuralynx_sdma(filename, begsample, endsample, chanindx); + + case 'neuralynx_ncs' + NRecords = hdr.nSamples/512; + begrecord = ceil(begsample/512); + endrecord = ceil(endsample/512); + % read the records that contain the desired samples + ncs = read_neuralynx_ncs(filename, begrecord, endrecord); + % cut out the desired samples + begsample = begsample - (begrecord-1)*512; + endsample = endsample - (begrecord-1)*512; + % this also reshape the data from 512 X records into a linear array + dat = ncs.dat(begsample:endsample); + + case 'neuralynx_nse' + % read all records + nse = read_neuralynx_nse(filename); + % convert timestamps to samples + sample = round((nse.TimeStamp - hdr.FirstTimeStamp)./hdr.TimeStampPerSample + 1); + % select the timestamps that are between begin and endsample + sample = sample(sample>=begsample & sample<=endsample) - begsample + 1; + dat = zeros(1,endsample-begsample+1); + dat(sample) = 1; + + case 'neuralynx_nte' + % read all records + nte = read_neuralynx_nte(filename); + % convert timestamps to samples + sample = round((nte.TimeStamp - hdr.FirstTimeStamp)./hdr.TimeStampPerSample + 1); + % select the timestamps that are between begin and endsample + sample = sample(sample>=begsample & sample<=endsample) - begsample + 1; + dat = zeros(1,endsample-begsample+1); + dat(sample) = 1; + + case {'neuralynx_ttl', 'neuralynx_tsl', 'neuralynx_tsh'} + % single channel files + dat = read_neuralynx_ttl(filename, begsample, endsample); + + case 'neuralynx_bin' + % single channel files + dat = read_neuralynx_bin(filename, begsample, endsample); + + case 'neuralynx_ds' + dat = read_neuralynx_ds(filename, hdr, begsample, endsample, chanindx); + + case 'neuralynx_cds' + dat = read_neuralynx_cds(filename, hdr, begsample, endsample, chanindx); + + case 'nexstim_nxe' + dat = read_nexstim_nxe(filename, begsample, endsample, chanindx); + + case 'ns_avg' + % NeuroScan average data + orig = read_ns_avg(filename); + dat = orig.data(chanindx, begsample:endsample); + + case {'ns_cnt' 'ns_cnt16', 'ns_cnt32'} + % Neuroscan continuous data + sample1 = begsample-1; + ldnsamples = endsample-begsample+1; % number of samples to read + chanoi = chanindx(:)'; % channels of interest + if sample1<0 + error('begin sample cannot be for the beginning of the file'); + end + % the hdr.nsdf was the initial fieldtrip hack to get 32 bit support, now it is realized using a extended dataformat string + if isfield(hdr, 'nsdf') && hdr.nsdf==16 + dataformat = 'ns_cnt16'; + elseif isfield(hdr, 'nsdf') && hdr.nsdf==32 + dataformat = 'ns_cnt32'; + end + + if strcmp(dataformat, 'ns_cnt') + tmp = loadcnt(filename, 'sample1', sample1, 'ldnsamples', ldnsamples, 'blockread', 1); + elseif strcmp(dataformat, 'ns_cnt16') + tmp = loadcnt(filename, 'sample1', sample1, 'ldnsamples', ldnsamples, 'blockread', 1, 'dataformat', 'int16'); + elseif strcmp(dataformat, 'ns_cnt32') + tmp = loadcnt(filename, 'sample1', sample1, 'ldnsamples', ldnsamples, 'blockread', 1, 'dataformat', 'int32'); + end + dat = tmp.data(chanoi,:); + + case 'ns_eeg' + % Neuroscan epoched file + tmp = read_ns_eeg(filename, begtrial:endtrial); + siz = [(endtrial-begtrial+1) hdr.nChans hdr.nSamples]; + dat = reshape(tmp.data, siz); % ensure 3-D array + dat = dat(:,chanindx,:); % select channels + dimord = 'trials_chans_samples'; % selection using begsample and endsample will be done later + + case {'neuromag_fif' 'neuromag_mne'} + % check that the required low-level toolbox is available + hastoolbox('mne', 1); + if (hdr.orig.iscontinuous) + dat = fiff_read_raw_segment(hdr.orig.raw,begsample+hdr.orig.raw.first_samp-1,endsample+hdr.orig.raw.first_samp-1,chanindx); + dimord = 'chans_samples'; + elseif (hdr.orig.isaverage) + dat = cat(2, hdr.orig.evoked.epochs); % concatenate all epochs, this works both when they are of constant or variable length + if checkboundary + trialnumber = []; + for i = 1:numel(hdr.orig.evoked) + trialnumber = [trialnumber i*ones(size(hdr.orig.evoked(i).times))]; + end + if trialnumber(begsample) ~= trialnumber(endsample) + error('requested data segment extends over a discontinuous trial boundary'); + end + end + dat = dat(chanindx, begsample:endsample); % select the desired channels and samples + dimord = 'chans_samples'; + elseif (hdr.orig.isepoched) + error('Support for epoched *.fif data is not yet implemented.') + end + + case 'neuromag_mex' + % check that the required low-level toolbox is available + hastoolbox('meg-pd', 1); + begtime = (begsample-1)/hdr.Fs; + begepoch = floor((begsample-1)/hdr.nSamples) + 1; + endepoch = floor((endsample-1)/hdr.nSamples) + 1; + rawdata('any',filename); + rawdata('goto', begtime); + dat = []; + for i=begepoch:endepoch + [buf, status] = rawdata('next'); + if ~strcmp(status, 'ok') + error('error reading selected data from fif-file'); + else + dat(:,((i-begepoch)*hdr.nSamples+1):((i-begepoch+1)*hdr.nSamples)) = buf(chanindx,:); + end + end + rawdata('close'); + begsample = begsample - (begepoch-1)*hdr.nSamples; % correct for the number of bytes that were skipped + endsample = endsample - (begepoch-1)*hdr.nSamples; % correct for the number of bytes that were skipped + dat = dat(:, begsample:endsample); + + case 'neuroprax_eeg' + tmp = np_readdata(filename, hdr.orig, begsample - 1, endsample - begsample + 1, 'samples'); + dat = tmp.data'; + + case 'plexon_ds' + dat = read_plexon_ds(filename, hdr, begsample, endsample, chanindx); + + case 'plexon_ddt' + dat = read_plexon_ddt(filename, begsample, endsample); + dat = dat.data(chanindx,:); + + case {'read_nex_data'} % this is an alternative reader for nex files + dat = read_nex_data(filename, hdr, begsample, endsample, chanindx); + + case {'read_plexon_nex' 'plexon_nex'} % this is the default reader for nex files + dat = zeros(length(chanindx), endsample-begsample+1); + for i=1:length(chanindx) + if hdr.orig.VarHeader(chanindx(i)).Type==5 + % this is a continuous channel + if hdr.orig.VarHeader(chanindx(i)).Count==1 + [nex, chanhdr] = read_plexon_nex(filename, 'header', hdr.orig, 'channel', chanindx(i), 'tsonly', 1); + % the AD channel contains a single fragment + % determine the sample offset into this fragment + offset = round(double(nex.ts-hdr.FirstTimeStamp)./hdr.TimeStampPerSample); + chanbegsmp = begsample - offset; + chanendsmp = endsample - offset; + if chanbegsmp<1 + % the first sample of this channel is later than the beginning of the dataset + % and we are trying to read the beginning of the dataset + [nex, chanhdr] = read_plexon_nex(filename, 'header', hdr.orig, 'channel', chanindx(i), 'tsonly', 0, 'begsample', 1, 'endsample', chanendsmp); + % padd the beginning of this channel with NaNs + nex.dat = [nan(1,offset) nex.dat]; + else + [nex, chanhdr] = read_plexon_nex(filename, 'header', hdr.orig, 'channel', chanindx(i), 'tsonly', 0, 'begsample', chanbegsmp, 'endsample', chanendsmp); + end + % copy the desired samples into the output matrix + dat(i,:) = nex.dat; + else + % the AD channel contains multiple fragments + [nex, chanhdr] = read_plexon_nex(filename, 'header', hdr.orig, 'channel', chanindx(i), 'tsonly', 0); + % reconstruct the full AD timecourse with NaNs at all missing samples + offset = round(double(nex.ts-hdr.FirstTimeStamp)./hdr.TimeStampPerSample); % of each fragment, in AD samples + nsample = diff([nex.indx length(nex.dat)]); % of each fragment, in AD samples + % allocate memory to hold the complete continuous record + cnt = nan(1, offset(end)+nsample(end)); + for j=1:length(offset) + cntbegsmp = offset(j) + 1; + cntendsmp = offset(j) + nsample(j); + fragbegsmp = nex.indx(j) + 1; + fragendsmp = nex.indx(j) + nsample(j); + cnt(cntbegsmp:cntendsmp) = nex.dat(fragbegsmp:fragendsmp); + end + % copy the desired samples into the output matrix + dat(i,:) = cnt(begsample:endsample); + end + elseif any(hdr.orig.VarHeader(chanindx(i)).Type==[0 1 3]) + % it is a neuron(0), event(1) or waveform(3) channel and therefore it has timestamps + [nex, chanhdr] = read_plexon_nex(filename, 'header', hdr.orig, 'channel', chanindx(i), 'tsonly', 1); + % convert the timestamps to samples + sample = round(double(nex.ts - hdr.FirstTimeStamp)./hdr.TimeStampPerSample) + 1; + % select only timestamps that are between begin and endsample + sample = sample(sample>=begsample & sample<=endsample) - begsample + 1; + for j=sample(:)' + dat(i,j) = dat(i,j) + 1; + end + end + end + if any(isnan(dat(:))) + warning('data has been padded with NaNs'); + end + + case 'plexon_plx' + % determine the continuous channels + contlabel = {hdr.orig.SlowChannelHeader.Name}; + for i=1:length(contlabel) + contlabel{i} = deblank(contlabel{i}); + end + [contindx, contsel] = match_str(contlabel, hdr.label(chanindx)); + + % determine the channels with spike waveforms + spikelabel = {hdr.orig.ChannelHeader.Name}; + for i=1:length(spikelabel) + spikelabel{i} = deblank(spikelabel{i}); + end + [spikeindx, spikesel] = match_str(spikelabel, hdr.label(chanindx)); + + if (length(contindx)+length(spikeindx))=begsample & sample<=endsample) - begsample + 1; + for j=sample(:)' + dat(spikesel(i),j) = dat(spikesel(i),j) + 1; + end + end + + case {'yokogawa_ave', 'yokogawa_con', 'yokogawa_raw'} + % check that the required low-level toolbox is available + hastoolbox('yokogawa', 1); + dat = read_yokogawa_data(filename, hdr, begsample, endsample, chanindx); + + case 'nmc_archive_k' + dat = read_nmc_archive_k_data(filename, hdr, begsample, endsample, chanindx); + + case 'neuroshare' % NOTE: still under development + % check that the required neuroshare toolbox is available + hastoolbox('neuroshare', 1); + + tmp = read_neuroshare(filename, 'readanalog', 'yes', 'chanindx', chanindx, 'begsample', begsample, 'endsample', endsample); + dat = tmp.analog.data'; + + otherwise + if strcmp(fallback, 'biosig') && hastoolbox('BIOSIG', 1) + dat = read_biosig_data(filename, hdr, begsample, endsample, chanindx); + else + error('unsupported data format (%s)', dataformat); + end + +end + +if ~exist('dimord', 'var') + dimord = 'chans_samples'; % almost all low-level readers return the data as 2D array +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% reshape the 2-D or 3-D matrix to a common order of the dimensions +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +switch dimord + case {'chans_samples', 'chans_samples_trials'} + % nothing to do + case 'samples_chans' + dat = permute(dat, [2 1]); + dimord = 'chans_samples'; + case 'samples_chans_trials' + dat = permute(dat, [2 1 3]); + dimord = 'chans_samples_trials'; + case 'trials_samples_chans' + dat = permute(dat, [3 2 1]); + dimord = 'chans_samples_trials'; + case 'trials_chans_samples' + dat = permute(dat, [2 3 1]); + dimord = 'chans_samples_trials'; + otherwise + error('unexpected dimord'); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% convert between 3-D trial based and 2-D continuous output +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +if requesttrials && strcmp(dimord, 'chans_samples') + % reformat the continuous representation into trials + nchans = size(dat,1); + nsamples = hdr.nSamples; + ntrials = size(dat,2)/hdr.nSamples; + % in case of nchans=1 and ntrials=1, the reshaping into a 3D matrix results in the following warning + % Warning: ND-array output is being reshaped to a sparse 2D matrix. + % This behavior will change in a future release of MATLAB. + if ntrials>1 + dat = reshape(dat, [nchans nsamples ntrials]); % convert into a 3-D array + end + +elseif requestsamples && strcmp(dimord, 'chans_samples_trials') + % reformat the trials into a continuous representation + nchans = size(dat,1); + nsamples = size(dat,2); + ntrials = size(dat,3); + dat = reshape(dat, [nchans nsamples*ntrials]); % convert into a 2-D array + % determine the selection w.r.t. the data as it is on disk + begselection = (begtrial-1)*hdr.nSamples + 1; + endselection = (endtrial )*hdr.nSamples; + % determine the selection w.r.t. the data that has been read in + begselection2 = begsample - begselection + 1; + endselection2 = endsample - begselection + 1; + dat = dat(:,begselection2:endselection2); +end + +if strcmp(dataformat, 'bci2000_dat') + % caching for BCI2000 is handled in the main section and in read_header +else + % implement caching in a data independent way + if cache && requestsamples + % add the new segment to the cache + % FIMXE the cache size should be limited + cachedata.cfg.trl(end+1,:) = [begsample endsample 0]; + cachedata.trial{end+1} = dat; + cachedata.time{end+1} = (1:size(dat,2))/cachedata.fsample; + end +end diff --git a/external/fieldtrip/fileio/ft_read_event.m b/external/fieldtrip/fileio/ft_read_event.m new file mode 100644 index 0000000..0f75593 --- /dev/null +++ b/external/fieldtrip/fileio/ft_read_event.m @@ -0,0 +1,1272 @@ +function [event] = ft_read_event(filename, varargin) + +% FT_READ_EVENT reads all events from an EEG/MEG dataset and returns +% them in a well defined structure. It is a wrapper around different +% EEG/MEG file importers, directly supported formats are CTF, Neuromag, +% EEP, BrainVision, Neuroscan and Neuralynx. +% +% Use as +% [event] = ft_read_event(filename, ...) +% +% Additional options should be specified in key-value pairs and can be +% 'dataformat' string +% 'headerformat' string +% 'eventformat' string +% 'header' structure, see FT_READ_HEADER +% 'detectflank' string, can be 'up', 'down' or 'both' (default = 'up') +% 'trigshift' integer, number of samples to shift from flank to detect trigger value (default = 0) +% +% Furthermore, you can specify optional arguments as key-value pairs +% for filtering the events, e.g. to select only events of a specific +% type, of a specific value, or events between a specific begin and +% end sample. This event filtering is especially usefull for real-time +% processing. See FT_FILTER_EVENT for more details. +% +% Some data formats have trigger channels that are sampled continuously with +% the same rate as the electrophysiological data. The default is to detect +% only the up-going TTL flanks. The trigger events will correspond with the +% first sample where the TTL value is up. This behaviour can be changed +% using the 'detectflank' option, which also allows for detecting the +% down-going flank or both. In case of detecting the down-going flank, the +% sample number of the event will correspond with the first sample at which +% the TTF went down, and the value will correspond to the TTL value just +% prior to going down. +% +% This function returns an event structure with the following fields +% event.type = string +% event.sample = expressed in samples, the first sample of a recording is 1 +% event.value = number or string +% event.offset = expressed in samples +% event.duration = expressed in samples +% event.timestamp = expressed in timestamp units, which vary over systems (optional) +% +% The event type and sample fields are always defined, other fields can be empty, +% depending on the type of event file. Events are sorted by the sample on +% which they occur. After reading the event structure, you can use the +% following tricks to extract information about those events in which you +% are interested. +% +% Determine the different event types +% unique({event.type}) +% +% Get the index of all trial events +% find(strcmp('trial', {event.type})) +% +% Make a vector with all triggers that occurred on the backpanel +% [event(find(strcmp('backpanel trigger', {event.type}))).value] +% +% Find the events that occurred in trial 26 +% t=26; samples_trials = [event(find(strcmp('trial', {event.type}))).sample]; +% find([event.sample]>samples_trials(t) & [event.sample]. +% +% $Id: ft_read_event.m 1424 2010-07-19 02:21:44Z josdie $ + +persistent sock % for fcdc_tcp + +global event_queue % for fcdc_global +persistent db_blob % for fcdc_mysql +if isempty(db_blob) + db_blob = 0; +end + +if iscell(filename) + % use recursion to read from multiple event sources + event = []; + for i=1:numel(filename) + tmp = ft_read_event(filename{i}, varargin{:}); + event = appendevent(event(:), tmp(:)); + end + return +end + +% get the options +eventformat = keyval('eventformat', varargin); +hdr = keyval('header', varargin); +detectflank = keyval('detectflank', varargin); % up, down or both +trigshift = keyval('trigshift', varargin); % default is assigned in subfunction +trigindx = keyval('trigindx', varargin); % default is based on chantype helper function +headerformat = keyval('headerformat', varargin); +dataformat = keyval('dataformat', varargin); + +% this allows to read only events in a certain range, supported for selected data formats only +flt_type = keyval('type', varargin); +flt_value = keyval('value', varargin); +flt_minsample = keyval('minsample', varargin); +flt_maxsample = keyval('maxsample', varargin); +flt_mintimestamp = keyval('mintimestamp', varargin); +flt_maxtimestamp = keyval('maxtimestamp', varargin); +flt_minnumber = keyval('minnumber', varargin); +flt_maxnumber = keyval('maxnumber', varargin); + + +% determine the filetype +if isempty(eventformat) + eventformat = ft_filetype(filename); +end + +% default is to search only for rising or up-going flanks +if isempty(detectflank) + detectflank = 'up'; +end + +if ismember(eventformat, {'brainvision_eeg', 'brainvision_dat'}) + [p, f, e] = fileparts(filename); + filename = fullfile(p, [f '.vhdr']); + eventformat = 'brainvision_vhdr'; +end + +if strcmp(eventformat, 'brainvision_vhdr') + % read the headerfile belonging to the dataset and try to determine the corresponding markerfile + eventformat = 'brainvision_vmrk'; + hdr = read_brainvision_vhdr(filename); + % replace the filename with the filename of the markerfile + if ~isfield(hdr, 'MarkerFile') || isempty(hdr.MarkerFile) + filename = []; + else + [p, f, e] = fileparts(filename); + filename = fullfile(p, hdr.MarkerFile); + end +end + +% start with an empty event structure +event = []; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% read the events with the low-level reading function +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +switch eventformat + + case 'fcdc_global' + event = event_queue; + + case {'4d' '4d_pdf', '4d_m4d', '4d_xyz'} + if isempty(hdr) + hdr = ft_read_header(filename); + end + + % read the trigger channel and do flank detection + trgindx = match_str(hdr.label, 'TRIGGER'); + if isfield(hdr, 'orig') && isfield(hdr.orig, 'config_data') && strcmp(hdr.orig.config_data.site_name, 'Glasgow'), + trigger = read_trigger(filename, 'header', hdr, 'begsample', flt_minsample, 'endsample', flt_maxsample, 'chanindx', trgindx, 'detectflank', detectflank, 'trigshift', trigshift,'fix4dglasgow',1); + else + trigger = read_trigger(filename, 'header', hdr, 'begsample', flt_minsample, 'endsample', flt_maxsample, 'chanindx', trgindx, 'detectflank', detectflank, 'trigshift', trigshift,'fix4dglasgow',0); + end + event = appendevent(event, trigger); + + respindx = match_str(hdr.label, 'RESPONSE'); + if ~isempty(respindx) + response = read_trigger(filename, 'header', hdr, 'begsample', flt_minsample, 'endsample', flt_maxsample, 'chanindx', respindx, 'detectflank', detectflank, 'trigshift', trigshift); + event = appendevent(event, response); + end + + case 'bci2000_dat' + % this requires the load_bcidat mex file to be present on the path + hastoolbox('BCI2000', 1); + + if isempty(hdr) + hdr = ft_read_header(filename); + end + + if isfield(hdr.orig, 'signal') && isfield(hdr.orig, 'states') + % assume that the complete data is stored in the header, this speeds up subsequent read operations + signal = hdr.orig.signal; + states = hdr.orig.states; + parameters = hdr.orig.parameters; + total_samples = hdr.orig.total_samples; + else + [signal, states, parameters, total_samples] = load_bcidat(filename); + end + + list = fieldnames(states); + % loop over all states and detect the flanks, the following code was taken from read_trigger + for i=1:length(list) + channel = list{i}; + trig = double(getfield(states, channel)); + pad = trig(1); + trigshift = 0; + begsample = 1; + + switch detectflank + case 'up' + % convert the trigger into an event with a value at a specific sample + for j=find(diff([pad trig(:)'])>0) + event(end+1).type = channel; + event(end ).sample = j + begsample - 1; % assign the sample at which the trigger has gone down + event(end ).value = trig(j+trigshift); % assign the trigger value just _after_ going up + end + case 'down' + % convert the trigger into an event with a value at a specific sample + for j=find(diff([pad trig(:)'])<0) + event(end+1).type = channel; + event(end ).sample = j + begsample - 1; % assign the sample at which the trigger has gone down + event(end ).value = trig(j-1-trigshift); % assign the trigger value just _before_ going down + end + case 'both' + % convert the trigger into an event with a value at a specific sample + for j=find(diff([pad trig(:)'])>0) + event(end+1).type = [channel '_up']; % distinguish between up and down flank + event(end ).sample = j + begsample - 1; % assign the sample at which the trigger has gone down + event(end ).value = trig(j+trigshift); % assign the trigger value just _after_ going up + end + % convert the trigger into an event with a value at a specific sample + for j=find(diff([pad trig(:)'])<0) + event(end+1).type = [channel '_down']; % distinguish between up and down flank + event(end ).sample = j + begsample - 1; % assign the sample at which the trigger has gone down + event(end ).value = trig(j-1-trigshift); % assign the trigger value just _before_ going down + end + otherwise + error('incorrect specification of ''detectflank'''); + end + end + + case {'besa_avr', 'besa_swf'} + if isempty(hdr) + hdr = ft_read_header(filename); + end + event(end+1).type = 'average'; + event(end ).sample = 1; + event(end ).duration = hdr.nSamples; + event(end ).offset = -hdr.nSamplesPre; + event(end ).value = []; + + case {'biosemi_bdf', 'bham_bdf'} + % read the header, required to determine the stimulus channels and trial specification + if isempty(hdr) + hdr = ft_read_header(filename); + end + + % specify the range to search for triggers, default is the complete file + if ~isempty(flt_minsample) + begsample = flt_minsample; + else + begsample = 1; + end + if ~isempty(flt_maxsample) + endsample = flt_maxsample; + else + endsample = hdr.nSamples*hdr.nTrials; + end + + if ~strcmp(detectflank, 'up') + if strcmp(detectflank, 'both') + warning('only up-going flanks are supported for Biosemi'); + detectflank = 'up'; + else + error('only up-going flanks are supported for Biosemi'); + % FIXME the next section on trigger detection should be merged with the + % READ_CTF_TRIGGER (which also does masking with bit-patterns) into the + % READ_TRIGGER function + end + end + + % find the STATUS channel and read the values from it + schan = find(strcmpi(hdr.label,'STATUS')); + sdata = ft_read_data(filename, 'header', hdr, 'begsample', begsample, 'endsample', endsample, 'chanindx', schan); + + % find indices of negative numbers + bit24i = find(sdata < 0); + % make number positive and preserve bits 0-22 + sdata(bit24i) = bitcmp(abs(sdata(bit24i))-1,24); + % re-insert the sign bit on its original location, i.e. bit24 + sdata(bit24i) = sdata(bit24i)+(2^(24-1)); + % typecast the data to ensure that the status channel is represented in 32 bits + sdata = uint32(sdata); + + byte1 = 2^8 - 1; + byte2 = 2^16 - 1 - byte1; + byte3 = 2^24 - 1 - byte1 - byte2; + + % get the respective status and trigger bits + trigger = bitand(sdata, bitor(byte1, byte2)); % contained in the lower two bytes + epoch = int8(bitget(sdata, 16+1)); + cmrange = int8(bitget(sdata, 20+1)); + battery = int8(bitget(sdata, 22+1)); + + % determine when the respective status bits go up or down + flank_trigger = diff([0 trigger]); + flank_epoch = diff([0 epoch ]); + flank_cmrange = diff([0 cmrange]); + flank_battery = diff([0 battery]); + + for i=find(flank_trigger>0) + event(end+1).type = 'STATUS'; + event(end ).sample = i + begsample - 1; + event(end ).value = double(trigger(i)); + end + + for i=find(flank_epoch==1) + event(end+1).type = 'Epoch'; + event(end ).sample = i; + end + + for i=find(flank_cmrange==1) + event(end+1).type = 'CM_in_range'; + event(end ).sample = i; + end + + for i=find(flank_cmrange==-1) + event(end+1).type = 'CM_out_of_range'; + event(end ).sample = i; + end + + for i=find(flank_battery==1) + event(end+1).type = 'Battery_low'; + event(end ).sample = i; + end + + for i=find(flank_battery==-1) + event(end+1).type = 'Battery_ok'; + event(end ).sample = i; + end + + case {'biosig', 'gdf'} + % FIXME it would be nice to figure out how sopen/sread return events + % for all possible fileformats that can be processed with biosig + warning('BIOSIG does not have a consistent event representation, skipping events') + event = []; + + case 'brainvision_vmrk' + fid=fopen(filename,'rt'); + if fid==-1, + error('cannot open BrainVision marker file') + end + line = []; + while ischar(line) || isempty(line) + line = fgetl(fid); + if ~isempty(line) && ~(isnumeric(line) && line==-1) + if strncmpi(line, 'Mk', 2) + % this line contains a marker + tok = tokenize(line, '=', 0); % do not squeeze repetitions of the seperator + if length(tok)~=2 + warning('skipping unexpected formatted line in BrainVision marker file'); + else + % the line looks like "MkXXX=YYY", which is ok + % the interesting part now is in the YYY, i.e. the second token + tok = tokenize(tok{2}, ',', 0); % do not squeeze repetitions of the seperator + if isempty(tok{1}) + tok{1} = []; + end + if isempty(tok{2}) + tok{2} = []; + end + event(end+1).type = tok{1}; + event(end ).value = tok{2}; + event(end ).sample = str2num(tok{3}); + event(end ).duration = str2num(tok{4}); + end + end + end + end + fclose(fid); + + case 'ced_son' + % check that the required low-level toolbox is available + hastoolbox('neuroshare', 1); + orig = read_ced_son(filename,'readevents','yes'); + event = struct('type', {orig.events.type},... + 'sample', {orig.events.sample},... + 'value', {orig.events.value},... + 'offset', {orig.events.offset},... + 'duration', {orig.events.duration}); + + case {'ctf_ds', 'ctf_meg4', 'ctf_res4', 'ctf_old'} + % obtain the dataset name + if ft_filetype(filename, 'ctf_meg4') || ft_filetype(filename, 'ctf_res4') + filename = fileparts(filename); + end + [path, name, ext] = fileparts(filename); + headerfile = fullfile(path, [name ext], [name '.res4']); + datafile = fullfile(path, [name ext], [name '.meg4']); + classfile = fullfile(path, [name ext], 'ClassFile.cls'); + markerfile = fullfile(path, [name ext], 'MarkerFile.mrk'); + + % in case ctf_old was specified as eventformat, the other reading functions should also know about that + if strcmp(eventformat, 'ctf_old') + dataformat = 'ctf_old'; + headerformat = 'ctf_old'; + end + + % read the header, required to determine the stimulus channels and trial specification + if isempty(hdr) + hdr = ft_read_header(headerfile, 'headerformat', headerformat); + end + + try + % read the trigger codes from the STIM channel, usefull for (pseudo) continuous data + % this splits the trigger channel into the lowers and highest 16 bits, + % corresponding with the front and back panel of the electronics cabinet at the Donders Centre + [backpanel, frontpanel] = read_ctf_trigger(filename); + for i=find(backpanel(:)') + event(end+1).type = 'backpanel trigger'; + event(end ).sample = i; + event(end ).value = backpanel(i); + end + for i=find(frontpanel(:)') + event(end+1).type = 'frontpanel trigger'; + event(end ).sample = i; + event(end ).value = frontpanel(i); + end + end + + % determine the trigger channels from the header + if isfield(hdr, 'orig') && isfield(hdr.orig, 'sensType') + origSensType = hdr.orig.sensType; + elseif isfield(hdr, 'orig') && isfield(hdr.orig, 'res4') + origSensType = [hdr.orig.res4.senres.sensorTypeIndex]; + else + origSensType = []; + end + % meg channels are 5, refmag 0, refgrad 1, adcs 18, trigger 11, eeg 9 + trigchanindx = find(origSensType==11); + if ~isempty(trigchanindx) + % read the trigger channel and do flank detection + trigger = read_trigger(filename, 'header', hdr, 'begsample', flt_minsample, 'endsample', flt_maxsample, 'chanindx', trigchanindx, 'dataformat', dataformat, 'detectflank', detectflank, 'trigshift', trigshift, 'fixctf', 1); + event = appendevent(event, trigger); + end + + % read the classification file and make an event for each classified trial + [condNumbers,condLabels] = read_ctf_cls(classfile); + if ~isempty(condNumbers) + Ncond = length(condLabels); + for i=1:Ncond + for j=1:length(condNumbers{i}) + event(end+1).type = 'classification'; + event(end ).value = condLabels{i}; + event(end ).sample = (condNumbers{i}(j)-1)*hdr.nSamples + 1; + event(end ).offset = -hdr.nSamplesPre; + event(end ).duration = hdr.nSamples; + end + end + end + + if exist(markerfile,'file') + % read the marker file and make an event for each marker + % this depends on the readmarkerfile function that I got from Tom Holroyd + % I have not tested this myself extensively, since at the FCDC we + % don't use the marker files + mrk = readmarkerfile(filename); + for i=1:mrk.number_markers + for j=1:mrk.number_samples(i) + % determine the location of the marker, expressed in samples + trialnum = mrk.trial_times{i}(j,1); + synctime = mrk.trial_times{i}(j,2); + begsample = (trialnum-1)*hdr.nSamples + 1; % of the trial, relative to the start of the datafile + endsample = (trialnum )*hdr.nSamples; % of the trial, relative to the start of the datafile + offset = round(synctime*hdr.Fs); % this is the offset (in samples) relative to time t=0 for this trial + offset = offset + hdr.nSamplesPre; % and time t=0 corrsponds with the nSamplesPre'th sample + % store this marker as an event + event(end+1).type = mrk.marker_names{i}; + event(end ).value = []; + event(end ).sample = begsample + offset; + event(end ).duration = 0; + event(end ).offset = offset; + end + end + end + + case 'ctf_shm' + % contact Robert Oostenveld if you are interested in real-time acquisition on the CTF system + % read the events from shared memory + event = read_shm_event(filename, varargin{:}); + + case 'eeglab_set' + if isempty(hdr) + hdr = ft_read_header(filename); + end + event = read_eeglabevent(filename, 'header', hdr); + + case 'spmeeg_mat' + if isempty(hdr) + hdr = ft_read_header(filename); + end + event = read_spmeeg_event(filename, 'header', hdr); + + case 'eep_avr' + % check that the required low-level toolbox is available + hastoolbox('eeprobe', 1); + % the headerfile and datafile are the same + if isempty(hdr) + hdr = ft_read_header(filename); + end + event(end+1).type = 'average'; + event(end ).sample = 1; + event(end ).duration = hdr.nSamples; + event(end ).offset = -hdr.nSamplesPre; + event(end ).value = []; + + case 'eep_cnt' + % check that the required low-level toolbox is available + hastoolbox('eeprobe', 1); + % try to read external trigger file in EEP format + trgfile = [filename(1:(end-3)), 'trg']; + if exist(trgfile, 'file') + if isempty(hdr) + hdr = ft_read_header(filename); + end + tmp = read_eep_trg(trgfile); + % translate the EEProbe trigger codes to events + for i=1:length(tmp) + event(i).type = 'trigger'; + event(i).sample = round((tmp(i).time/1000) * hdr.Fs) + 1; % convert from ms to samples + event(i).value = tmp(i).code; + event(i).offset = 0; + event(i).duration = 0; + end + else + warning('no triggerfile was found'); + end + + case 'egi_egis' + if isempty(hdr) + hdr = ft_read_header(filename); + end + fhdr = hdr.orig.fhdr; + chdr = hdr.orig.chdr; + ename = hdr.orig.ename; + cnames = hdr.orig.cnames; + fcom = hdr.orig.fcom; + ftext = hdr.orig.ftext; + eventCount=0; + for cell=1:fhdr(18) + for trial=1:chdr(cell,2) + eventCount=eventCount+1; + event(eventCount).type = 'trial'; + event(eventCount).sample = (eventCount-1)*hdr.nSamples + 1; + event(eventCount).offset = -hdr.nSamplesPre; + event(eventCount).duration = hdr.nSamples; + event(eventCount).value = cnames{cell}; + end + end + + case 'egi_egia' + if isempty(hdr) + hdr = ft_read_header(filename); + end + fhdr = hdr.orig.fhdr; + chdr = hdr.orig.chdr; + ename = hdr.orig.ename; + cnames = hdr.orig.cnames; + fcom = hdr.orig.fcom; + ftext = hdr.orig.ftext; + eventCount=0; + for cell=1:fhdr(18) + for subject=1:chdr(cell,2) + eventCount=eventCount+1; + event(eventCount).type = 'trial'; + event(eventCount).sample = (eventCount-1)*hdr.nSamples + 1; + event(eventCount).offset = -hdr.nSamplesPre; + event(eventCount).duration = hdr.nSamples; + event(eventCount).value = ['Sub' sprintf('%03d',subject) cnames{cell}]; + end + end + + case 'egi_sbin' + if ~exist('segHdr','var') + [EventCodes, segHdr, eventData] = read_sbin_events(filename); + end + if ~exist('header_array','var') + [header_array, CateNames, CatLengths, preBaseline] = read_sbin_header(filename); + end + if isempty(hdr) + hdr = ft_read_header(filename,'headerformat','egi_sbin'); + end + version = header_array(1); + unsegmented = ~mod(version, 2); + + eventCount=0; + if unsegmented + [evType,sampNum] = find(eventData); + for k = 1:length(evType) + event(k).sample = sampNum(k); + event(k).offset = []; + event(k).duration = 0; + event(k).type = 'trigger'; + event(k).value = char(EventCodes(evType(k),:)); + end + else + for theEvent=1:size(eventData,1) + for segment=1:hdr.nTrials + if any(eventData(theEvent,((segment-1)*hdr.nSamples +1):segment*hdr.nSamples)) + eventCount=eventCount+1; + event(eventCount).sample = min(find(eventData(theEvent,((segment-1)*hdr.nSamples +1):segment*hdr.nSamples))) +(segment-1)*hdr.nSamples; + event(eventCount).offset = -hdr.nSamplesPre; + event(eventCount).duration = length(find(eventData(theEvent,((segment-1)*hdr.nSamples +1):segment*hdr.nSamples )>0))-1; + if event(eventCount).duration ~= hdr.nSamples + event(eventCount).type = 'trigger'; + else + event(eventCount).type = 'trial'; + end; + event(eventCount).value = char(EventCodes(theEvent,:)); + end + end + end + end + + if sum(strcmp('trial',{event.type})) ~= hdr.nTrials + for segment=1:hdr.nTrials % cell information + eventCount=eventCount+1; + event(eventCount).type = 'trial'; + event(eventCount).sample = (segment-1)*hdr.nSamples + 1; + event(eventCount).offset = -hdr.nSamplesPre; + event(eventCount).duration = hdr.nSamples; + if unsegmented, + event(eventCount).value = []; + else + event(eventCount).value = char([CateNames{segHdr(segment,1)}(1:CatLengths(segHdr(segment,1)))]); + end + end + end; + + case 'eyelink_asc' + if isempty(hdr) + hdr = ft_read_header(filename); + end + if isfield(hdr.orig, 'input') + % this is inefficient, since it keeps the complete data in memory + % but it does speed up subsequent read operations without the user + % having to care about it + asc = hdr.orig; + else + asc = read_eyelink_asc(filename); + end + timestamp = [asc.input(:).timestamp]; + value = [asc.input(:).value]; + % note that in this dataformat the first input trigger can be before + % the start of the data acquisition + for i=1:length(timestamp) + event(end+1).type = 'INPUT'; + event(end ).sample = (timestamp(i)-hdr.FirstTimeStamp)/hdr.TimeStampPerSample + 1; + event(end ).timestamp = timestamp(i); + event(end ).value = value(i); + event(end ).duration = 1; + event(end ).offset = 0; + end + + case 'fcdc_buffer' + % read from a networked buffer for realtime analysis + [host, port] = filetype_check_uri(filename); + + % SK: the following was intended to speed up, but does not work + % the buffer server will try to return exact indices, even + % if the intend here is to filter based on a maximum range. + % We could change the definition of GET_EVT to comply + % with filtering, but that might break other existing code. + + %if isempty(flt_minnumber) && isempty(flt_maxnumber) + % evtsel = []; + %else + % evtsel = [0 2^32-1]; + % if ~isempty(flt_minnumber) + % evtsel(1) = flt_minnumber-1; + % end + % if ~isempty(flt_maxnumber) + % evtsel(2) = flt_maxnumber-1; + % end + %end + + try + event = buffer('get_evt', [], host, port); + catch + if strfind(lasterr, 'the buffer returned an error') + event = []; + else + rethrow(lasterr); + end + end + + case 'fcdc_matbin' + % this is multiplexed data in a *.bin file, accompanied by a matlab file containing the header and event + [path, file, ext] = fileparts(filename); + filename = fullfile(path, [file '.mat']); + % read the events from the Matlab file + tmp = load(filename, 'event'); + event = tmp.event; + + + case 'fcdc_fifo' + + + fifo = filetype_check_uri(filename); + + if ~exist(fifo,'file') + warning('the FIFO %s does not exist; attempting to create it', fifo); + system(sprintf('mkfifo -m 0666 %s',fifo)); + end + + fid = fopen(fifo, 'r'); + msg = fread(fid, inf, 'uint8'); + fclose(fid); + + try + event = mxDeserialize(uint8(msg)); + catch + warning(lasterr); + end + + case 'fcdc_tcp' + % requires tcp/udp/ip-toolbox + hastoolbox('TCP_UDP_IP', 1); + [host, port] = filetype_check_uri(filename); + if isempty(sock) + sock=pnet('tcpsocket',port); + end + con = pnet(sock, 'tcplisten'); + if con~=-1 + try + pnet(con,'setreadtimeout',10); + % read packet + msg=pnet(con,'readline'); %,1000,'uint8','network'); + if ~isempty(msg) + event = mxDeserialize(uint8(str2num(msg))); + end + % catch + % warning(lasterr); + end + pnet(con,'close'); + end + con = []; + + case 'fcdc_udp' + % requires tcp/udp/ip-toolbox + hastoolbox('TCP_UDP_IP', 1); + [host, port] = filetype_check_uri(filename); + try + % read from localhost + udp=pnet('udpsocket',port); + % Wait/Read udp packet to read buffer + len=pnet(udp,'readpacket'); + if len>0, + % if packet larger then 1 byte then read maximum of 1000 doubles in network byte order + msg=pnet(udp,'read',1000,'uint8'); + if ~isempty(msg) + event = mxDeserialize(uint8(msg)); + end + end + catch + warning(lasterr); + end + % On break or error close connection + pnet(udp,'close'); + + case 'fcdc_serial' + % this code is moved to a seperate file + event = read_serial_event(filename); + + case 'fcdc_mysql' + % read from a MySQL server listening somewhere else on the network + db_open(filename); + if db_blob + event = db_select_blob('fieldtrip.event', 'msg'); + else + event = db_select('fieldtrip.event', {'type', 'value', 'sample', 'offset', 'duration'}); + end + + case {'itab_raw' 'itab_mhd'} + if isempty(hdr) + hdr = ft_read_header(filename); + end + for i=1:hdr.orig.nsmpl + event(end+1).type = 'trigger'; + event(end ).value = hdr.orig.smpl(i).type; + event(end ).sample = hdr.orig.smpl(i).start + 1; + event(end ).duration = hdr.orig.smpl(i).ntptot; + event(end ).offset = -hdr.orig.smpl(i).ntppre; % number of samples prior to the trigger + end + if isempty(event) + warning('no events found in the event table, reading the trigger channel(s)'); + trigsel = find(ft_chantype(hdr, 'flag')); + trigger = read_trigger(filename, 'header', hdr, 'dataformat', dataformat, 'begsample', flt_minsample, 'endsample', flt_maxsample, 'chanindx', trigsel, 'detectflank', detectflank, 'trigshift', trigshift); + event = appendevent(event, trigger); + end + + case 'matlab' + % read the events from a normal Matlab file + tmp = load(filename, 'event'); + event = tmp.event; + + case {'mpi_ds', 'mpi_dap'} + if isempty(hdr) + hdr = ft_read_header(filename); + end + % determine the DAP files that compromise this dataset + if isdir(filename) + ls = dir(filename); + dapfile = {}; + for i=1:length(ls) + if ~isempty(regexp(ls(i).name, '.dap$', 'once' )) + dapfile{end+1} = fullfile(filename, ls(i).name); + end + end + dapfile = sort(dapfile); + elseif iscell(filename) + dapfile = filename; + else + dapfile = {filename}; + end + % assume that each DAP file is accompanied by a dat file + % read the trigger values from the separate dat files + trg = []; + for i=1:length(dapfile) + datfile = [dapfile{i}(1:(end-4)) '.dat']; + trg = cat(1, trg, textread(datfile, '', 'headerlines', 1)); + end + % construct a event structure, one 'trialcode' event per trial + for i=1:length(trg) + event(i).type = 'trialcode'; % string + event(i).sample = (i-1)*hdr.nSamples + 1; % expressed in samples, first sample of file is 1 + event(i).value = trg(i); % number or string + event(i).offset = 0; % expressed in samples + event(i).duration = hdr.nSamples; % expressed in samples + end + + + case {'neuromag_fif' 'neuromag_mne' 'neuromag_mex'} + if strcmp(eventformat, 'neuromag_fif') + % the default is to use the MNE reader for fif files + eventformat = 'neuromag_mne'; + end + if strcmp(eventformat, 'neuromag_mex') + % check that the required low-level toolbox is available + hastoolbox('meg-pd', 1); + if isempty(headerformat), headerformat = eventformat; end + if isempty(dataformat), dataformat = eventformat; end + elseif strcmp(eventformat, 'neuromag_mne') + % check that the required low-level toolbox is available + hastoolbox('mne', 1); + if isempty(headerformat), headerformat = eventformat; end + if isempty(dataformat), dataformat = eventformat; end + end + + if isempty(hdr) + hdr = ft_read_header(filename, 'headerformat', headerformat); + end + + % note below we've had to include some chunks of code that are only + % called if the file is an averaged file, or if the file is continuous. + % These are defined in hdr by read_header for neuromag_mne, but do not + % exist for neuromag_fif, hence we run the code anyway if the fields do + % not exist (this is what happened previously anyway). + + if strcmp(eventformat, 'neuromag_mex') + iscontinuous = 1; + isaverage = 0; + isepoched = 0; + elseif strcmp(eventformat, 'neuromag_mne') + iscontinuous = hdr.orig.iscontinuous; + isaverage = hdr.orig.isaverage; + isepoched = hdr.orig.isepoched; + end + + + + if iscontinuous + analogindx = find(strcmp(ft_chantype(hdr), 'analog trigger')); + binaryindx = find(strcmp(ft_chantype(hdr), 'digital trigger')); + + + if isempty(binaryindx)&&isempty(analogindx) + % included in case of problems with older systems and MNE reader: + % use a predefined set of channel names + binary = {'STI 014', 'STI 015', 'STI 016'}; + binaryindx = match_str(hdr.label, binary); + end + + if ~isempty(binaryindx) + trigger = read_trigger(filename, 'header', hdr, 'dataformat', dataformat, 'begsample', flt_minsample, 'endsample', flt_maxsample, 'chanindx', binaryindx, 'detectflank', detectflank, 'trigshift', trigshift, 'fixneuromag', 0); + event = appendevent(event, trigger); + end + if ~isempty(analogindx) + % add the triggers to the event structure based on trigger channels with the name "STI xxx" + % there are some issues with noise on these analog trigger + % channels, on older systems only + % read the trigger channel and do flank detection + trigger = read_trigger(filename, 'header', hdr, 'dataformat', dataformat, 'begsample', flt_minsample, 'endsample', flt_maxsample, 'chanindx', analogindx, 'detectflank', detectflank, 'trigshift', trigshift, 'fixneuromag', 1); + event = appendevent(event, trigger); + end + + elseif isaverage + % the length of each average can be variable + nsamples = zeros(1, length(hdr.orig.evoked)); + for i=1:length(hdr.orig.evoked) + nsamples(i) = size(hdr.orig.evoked(i).epochs, 2); + end + begsample = cumsum([1 nsamples]); + for i=1:length(hdr.orig.evoked) + event(end+1).type = 'average'; + event(end ).sample = begsample(i); + event(end ).value = hdr.orig.evoked(i).comment; % this is a descriptive string + event(end ).offset = hdr.orig.evoked(i).first; + event(end ).duration = hdr.orig.evoked(i).last - hdr.orig.evoked(i).first + 1; + end + + elseif isepoched + error('Support for epoched *.fif data is not yet implemented.') + end + + + case {'neuralynx_ttl' 'neuralynx_bin' 'neuralynx_dma' 'neuralynx_sdma'} + if isempty(hdr) + hdr = ft_read_header(filename); + end + + % specify the range to search for triggers, default is the complete file + if ~isempty(flt_minsample) + begsample = flt_minsample; + else + begsample = 1; + end + if ~isempty(flt_maxsample) + endsample = flt_maxsample; + else + endsample = hdr.nSamples*hdr.nTrials; + end + + if strcmp(eventformat, 'neuralynx_dma') + % read the Parallel_in channel from the DMA log file + ttl = read_neuralynx_dma(filename, begsample, endsample, 'ttl'); + elseif strcmp(eventformat, 'neuralynx_sdma') + % determine the seperate files with the trigger and timestamp information + [p, f, x] = fileparts(filename); + ttlfile = fullfile(filename, [f '.ttl.bin']); + tslfile = fullfile(filename, [f '.tsl.bin']); + tshfile = fullfile(filename, [f '.tsh.bin']); + if ~exist(ttlfile) && ~exist(tslfile) && ~exist(tshfile) + % perhaps it is an old splitted dma dataset? + ttlfile = fullfile(filename, [f '.ttl']); + tslfile = fullfile(filename, [f '.tsl']); + tshfile = fullfile(filename, [f '.tsh']); + end + if ~exist(ttlfile) && ~exist(tslfile) && ~exist(tshfile) + % these files must be present in a splitted dma dataset + error('could not locate the individual ttl, tsl and tsh files'); + end + % read the trigger values from the seperate file + ttl = read_neuralynx_bin(ttlfile, begsample, endsample); + elseif strcmp(eventformat, 'neuralynx_ttl') + % determine the optional files with timestamp information + tslfile = [filename(1:(end-4)) '.tsl']; + tshfile = [filename(1:(end-4)) '.tsh']; + % read the triggers from a seperate *.ttl file + ttl = read_neuralynx_ttl(filename, begsample, endsample); + elseif strcmp(eventformat, 'neuralynx_bin') + % determine the optional files with timestamp information + tslfile = [filename(1:(end-8)) '.tsl.bin']; + tshfile = [filename(1:(end-8)) '.tsh.bin']; + % read the triggers from a seperate *.ttl.bin file + ttl = read_neuralynx_bin(filename, begsample, endsample); + end + + ttl = int32(ttl / (2^16)); % parallel port provides int32, but word resolution is int16. Shift the bits and typecast to signed integer. + d1 = (diff(ttl)~=0); % determine the flanks, which can be multiple samples long (this looses one sample) + d2 = (diff(d1)==1); % determine the onset of the flanks (this looses one sample) + smp = find(d2)+2; % find the onset of the flanks, add the two samples again + val = ttl(smp+5); % look some samples further for the trigger value, to avoid the flank + clear d1 d2 ttl + ind = find(val~=0); % look for triggers tith a non-zero value, this avoids downgoing flanks going to zero + smp = smp(ind); % discard triggers with a value of zero + val = val(ind); % discard triggers with a value of zero + + if ~isempty(smp) + % try reading the timestamps + if strcmp(eventformat, 'neuralynx_dma') + tsl = read_neuralynx_dma(filename, 1, max(smp), 'tsl'); + tsl = typecast(tsl(smp), 'uint32'); + tsh = read_neuralynx_dma(filename, 1, max(smp), 'tsh'); + tsh = typecast(tsh(smp), 'uint32'); + ts = timestamp_neuralynx(tsl, tsh); + elseif exist(tslfile) && exist(tshfile) + tsl = read_neuralynx_bin(tslfile, 1, max(smp)); + tsl = tsl(smp); + tsh = read_neuralynx_bin(tshfile, 1, max(smp)); + tsh = tsh(smp); + ts = timestamp_neuralynx(tsl, tsh); + else + ts = []; + end + + % reformat the values as cell array, since the struct function can work with those + type = repmat({'trigger'},size(smp)); + value = num2cell(val); + sample = num2cell(smp + begsample - 1); + duration = repmat({[]},size(smp)); + offset = repmat({[]},size(smp)); + if ~isempty(ts) + timestamp = reshape(num2cell(ts),size(smp)); + else + timestamp = repmat({[]},size(smp)); + end + % convert it into a structure array, this can be done in one go + event = struct('type', type, 'value', value, 'sample', sample, 'timestamp', timestamp, 'offset', offset, 'duration', duration); + clear type value sample timestamp offset duration + end + + if (strcmp(eventformat, 'neuralynx_bin') || strcmp(eventformat, 'neuralynx_ttl')) && isfield(hdr, 'FirstTimeStamp') + % the header was obtained from an external dataset which could be at a different sampling rate + % use the timestamps to redetermine the sample numbers + fprintf('using sample number of the downsampled file to reposition the TTL events\n'); + % convert the timestamps into samples, keeping in mind the FirstTimeStamp and TimeStampPerSample + smp = round(double(ts - uint64(hdr.FirstTimeStamp))./hdr.TimeStampPerSample + 1); + for i=1:length(event) + % update the sample number + event(i).sample = smp(i); + end + end + + case 'neuralynx_ds' + % read the header of the dataset + if isempty(hdr) + hdr = ft_read_header(filename); + end + % the event file is contained in the dataset directory + if exist(fullfile(filename, 'Events.Nev')) + filename = fullfile(filename, 'Events.Nev'); + elseif exist(fullfile(filename, 'Events.nev')) + filename = fullfile(filename, 'Events.nev'); + elseif exist(fullfile(filename, 'events.Nev')) + filename = fullfile(filename, 'events.Nev'); + elseif exist(fullfile(filename, 'events.nev')) + filename = fullfile(filename, 'events.nev'); + end + % read the events, apply filter is applicable + nev = read_neuralynx_nev(filename, 'type', flt_type, 'value', flt_value, 'mintimestamp', flt_mintimestamp, 'maxtimestamp', flt_maxtimestamp, 'minnumber', flt_minnumber, 'maxnumber', flt_maxnumber); + + % now get the values as cell array, since the struct function can work with those + value = {nev.TTLValue}; + timestamp = {nev.TimeStamp}; + number = {nev.EventNumber}; + type = repmat({'trigger'},size(value)); + duration = repmat({[]},size(value)); + offset = repmat({[]},size(value)); + sample = num2cell(round(double(cell2mat(timestamp) - hdr.FirstTimeStamp)/hdr.TimeStampPerSample + 1)); + % convert it into a structure array + event = struct('type', type, 'value', value, 'sample', sample, 'timestamp', timestamp, 'duration', duration, 'offset', offset, 'number', number); + + case 'neuralynx_cds' + % this is a combined Neuralynx dataset with seperate subdirectories for the LFP, MUA and spike channels + dirlist = dir(filename); + %haslfp = any(filetype_check_extension({dirlist.name}, 'lfp')); + %hasmua = any(filetype_check_extension({dirlist.name}, 'mua')); + %hasspike = any(filetype_check_extension({dirlist.name}, 'spike')); + %hastsl = any(filetype_check_extension({dirlist.name}, 'tsl')); % seperate file with original TimeStampLow + %hastsh = any(filetype_check_extension({dirlist.name}, 'tsh')); % seperate file with original TimeStampHi + hasttl = any(filetype_check_extension({dirlist.name}, 'ttl')); % seperate file with original Parallel_in + hasnev = any(filetype_check_extension({dirlist.name}, 'nev')); % original Events.Nev file + hasmat = 0; + if hasttl + eventfile = fullfile(filename, dirlist(find(filetype_check_extension({dirlist.name}, 'ttl'))).name); + % read the header from the combined dataset + if isempty(hdr) + hdr = ft_read_header(filename); + end + % read the events from the *.ttl file + event = ft_read_event(eventfile); + % convert the sample numbers from the dma or ttl file to the downsampled dataset + % assume that the *.ttl file is sampled at 32556Hz and is aligned with the rest of the data + for i=1:length(event) + event(i).sample = round((event(i).sample-1) * hdr.Fs/32556 + 1); + end + % elseif hasnev + % FIXME, do something here + % elseif hasmat + % FIXME, do something here + else + error('no event file found'); + end + + % The sample number is missingin the code below, since it is not available + % without looking in the continuously sampled data files. Therefore + % sorting the events (later in this function) based on the sample number + % fails and no events can be returned. + % + % case 'neuralynx_nev' + % [nev] = read_neuralynx_nev(filename); + % % select only the events with a TTL value + % ttl = [nev.TTLValue]; + % sel = find(ttl~=0); + % % now get the values as cell array, since teh struct function can work with those + % value = {nev(sel).TTLValue}; + % timestamp = {nev(sel).TimeStamp}; + % event = struct('value', value, 'timestamp', timestamp); + % for i=1:length(event) + % % assign the other fixed elements + % event(i).type = 'trigger'; + % event(i).offset = []; + % event(i).duration = []; + % event(i).sample = []; + % end + + + case {'neuroprax_eeg', 'neuroprax_mrk'} + tmp = np_readmarker (filename, 0, inf, 'samples'); + event = []; + for i = 1:numel(tmp.marker) + if isempty(tmp.marker{i}) + break; + end + event = [event struct('type', tmp.markernames(i),... + 'sample', num2cell(tmp.marker{i}),... + 'value', {tmp.markertyp(i)})]; + end + + case 'nexstim_nxe' + event = read_nexstim_event(filename); + + case 'nimh_cortex' + if isempty(hdr) + hdr = ft_read_header(filename); + end + cortex = hdr.orig.trial; + for i=1:length(cortex) + % add one 'trial' event for every trial and add the trigger events + event(end+1).type = 'trial'; + event(end ).sample = nan; + event(end ).duration = nan; + event(end ).offset = nan; + event(end ).value = i; % use the trial number as value + for j=1:length(cortex(i).event) + event(end+1).type = 'trigger'; + event(end ).sample = nan; + event(end ).duration = nan; + event(end ).offset = nan; + event(end ).value = cortex(i).event(j); + end + end + + case 'ns_avg' + if isempty(hdr) + hdr = ft_read_header(filename); + end + event(end+1).type = 'average'; + event(end ).sample = 1; + event(end ).duration = hdr.nSamples; + event(end ).offset = -hdr.nSamplesPre; + event(end ).value = []; + + case {'ns_cnt', 'ns_cnt16', 'ns_cnt32'} + % read the header, the original header includes the event table + if isempty(hdr) + hdr = ft_read_header(filename, 'headerformat', eventformat); + end + % translate the event table into known FieldTrip event types + for i=1:numel(hdr.orig.event) + event(i).type = 'trigger'; + event(i).sample = hdr.orig.event(i).offset + 1; % +1 was in EEGLAB pop_loadcnt + event(i).value = hdr.orig.event(i).stimtype; + event(i).offset = 0; + event(i).duration = 0; + end + + case 'ns_eeg' + if isempty(hdr) + hdr = ft_read_header(filename); + end + for i=1:hdr.nTrials + % the *.eeg file has a fixed trigger value for each trial + % furthermore each trial has the label 'accept' or 'reject' + tmp = read_ns_eeg(filename, i); + % create an event with the trigger value + event(end+1).type = 'trial'; + event(end ).sample = (i-1)*hdr.nSamples + 1; + event(end ).value = tmp.sweep.type; % trigger value + event(end ).offset = -hdr.nSamplesPre; + event(end ).duration = hdr.nSamples; + % create an event with the boolean accept/reject code + event(end+1).type = 'accept'; + event(end ).sample = (i-1)*hdr.nSamples + 1; + event(end ).value = tmp.sweep.accept; % boolean value indicating accept/reject + event(end ).offset = -hdr.nSamplesPre; + event(end ).duration = hdr.nSamples; + end + + case 'plexon_nex' + event = read_nex_event(filename); + + case {'yokogawa_ave', 'yokogawa_con', 'yokogawa_raw'} + % check that the required low-level toolbox is available + hastoolbox('yokogawa', 1); + % allow the user to specify custom trigger channels + event = read_yokogawa_event(filename, 'trigindx', trigindx); + + case 'nmc_archive_k' + event = read_nmc_archive_k_event(filename); + + case 'neuroshare' % NOTE: still under development + % check that the required neuroshare toolbox is available + hastoolbox('neuroshare', 1); + + tmp = read_neuroshare(filename, 'readevent', 'yes'); + for i=1:length(tmp.hdr.eventinfo) + event(i).type = tmp.hdr.eventinfo(i).EventType; + event(i).value = tmp.event.data(i); + event(i).timestamp = tmp.event.timestamp(i); + event(i).sample = tmp.event.sample(i); + end + + otherwise + error('unsupported event format (%s)', eventformat); +end + +if ~isempty(hdr) && hdr.nTrials>1 && (isempty(event) || ~any(strcmp({event.type}, 'trial'))) + % the data suggests multiple trials and trial events have not yet been defined + % make an event for each trial according to the file header + for i=1:hdr.nTrials + event(end+1).type = 'trial'; + event(end ).sample = (i-1)*hdr.nSamples + 1; + event(end ).offset = -hdr.nSamplesPre; + event(end ).duration = hdr.nSamples; + event(end ).value = []; + end +end + +if ~isempty(event) + % make sure that all required elements are present + if ~isfield(event, 'type'), error('type field not defined for each event'); end + if ~isfield(event, 'sample'), error('sample field not defined for each event'); end + if ~isfield(event, 'value'), for i=1:length(event), event(i).value = []; end; end + if ~isfield(event, 'offset'), for i=1:length(event), event(i).offset = []; end; end + if ~isfield(event, 'duration'), for i=1:length(event), event(i).duration = []; end; end +end + +% make sure that all numeric values are double +if ~isempty(event) + for i=1:length(event) + if isnumeric(event(i).value) + event(i).value = double(event(i).value); + end + event(i).sample = double(event(i).sample); + event(i).offset = double(event(i).offset); + event(i).duration = double(event(i).duration); + end +end + +if ~isempty(event) + % sort the events on the sample on which they occur + % this has the side effect that events without a sample number are discarded + [dum, indx] = sort([event.sample]); + event = event(indx); + % else + % warning(sprintf('no events found in %s', filename)); +end + +% apply the optional filters +event = ft_filter_event(event, varargin{:}); diff --git a/external/fieldtrip/fileio/ft_read_header.m b/external/fieldtrip/fileio/ft_read_header.m new file mode 100644 index 0000000..b5942a6 --- /dev/null +++ b/external/fieldtrip/fileio/ft_read_header.m @@ -0,0 +1,1362 @@ +function [hdr] = ft_read_header(filename, varargin) + +% FT_READ_HEADER reads header information from a variety of EEG, MEG and LFP +% files and represents the header information in a common data-indepentend +% format. The supported formats are listed below. +% +% Use as +% hdr = ft_read_header(filename, ...) +% +% Additional options should be specified in key-value pairs and can be +% 'headerformat' string +% 'fallback' can be empty or 'biosig' (default = []) +% +% This returns a header structure with the following elements +% hdr.Fs sampling frequency +% hdr.nChans number of channels +% hdr.nSamples number of samples per trial +% hdr.nSamplesPre number of pre-trigger samples in each trial +% hdr.nTrials number of trials +% hdr.label cell-array with labels of each channel +% hdr.FirstTimeStamp integer, only available for some subformats (mainly animal electrophisiology systems) +% hdr.TimeStampPerSample integer, only available for some subformats (mainly animal electrophisiology systems) +% +% For continuous data, nSamplesPre=0 and nTrials=1. +% +% Depending on the file format, additional header information can be +% returned in the hdr.orig subfield. +% +% The following MEG dataformats are supported +% CTF - VSM MedTech (*.ds, *.res4, *.meg4) +% Neuromag - Elektra (*.m4d, *.pdf, *.xyz) +% BTi - 4D Neuroimaging (*.m4d, *.pdf, *.xyz) +% Yokogawa (*.ave, *.con, *.raw) +% +% The following EEG dataformats are supported +% ANT - Advanced Neuro Technology, EEProbe (*.avr, *.eeg, *.cnt) +% Biosemi (*.bdf) +% CED - Cambridge Electronic Design (*. smr) +% Electrical Geodesics, Inc. (*.egis, *.ave, *.gave, *.ses, *.raw, *.sbin) +% Megis/BESA (*.avr, *.swf) +% NeuroScan (*.eeg, *.cnt, *.avg) +% Nexstim (*.nxe) +% BrainVision (*.eeg, *.seg, *.dat, *.vhdr, *.vmrk) +% +% The following spike and LFP dataformats are supported (with some limitations) +% Plextor (*.nex, *.plx, *.ddt) +% Neuralynx (*.ncs, *.nse, *.nts, *.nev, DMA log files) +% CED - Cambridge Electronic Design (*.smr) +% MPI - Max Planck Institute (*.dap) +% +% See also READ_DATA, READ_EVENT, WRITE_DATA, WRITE_EVENT + +% Copyright (C) 2003-2010 Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_read_header.m 1396 2010-07-12 13:18:31Z vlalit $ + +% TODO channel renaming should be made a general option (see bham_bdf) + +persistent cacheheader % for caching +persistent db_blob % for fcdc_mysql +persistent fakechannelwarning % this warning should be given only once + +if isempty(db_blob) + db_blob = 0; +end + +% test whether the file or directory exists +if ~exist(filename, 'file') && ~strcmp(ft_filetype(filename), 'ctf_shm') && ~strcmp(ft_filetype(filename), 'fcdc_mysql') && ~strcmp(ft_filetype(filename), 'fcdc_buffer') + error('FILEIO:InvalidFileName', 'file or directory ''%s'' does not exist', filename); +end + +% get the options +headerformat = keyval('headerformat', varargin); +fallback = keyval('fallback', varargin); +cache = keyval('cache', varargin); +retry = keyval('retry', varargin); if isempty(retry), retry = false; end % for fcdc_buffer + +% determine the filetype +if isempty(headerformat) + headerformat = ft_filetype(filename); +end + +if isempty(cache), + if strcmp(headerformat, 'bci2000_dat') || strcmp(headerformat, 'eyelink_asc') + cache = true; + else + cache = false; + end +end + +% start with an empty header +hdr = []; + +switch headerformat + case '4d_pdf' + datafile = filename; + headerfile = [datafile '.m4d']; + sensorfile = [datafile '.xyz']; + case {'4d_m4d', '4d_xyz'} + datafile = filename(1:(end-4)); % remove the extension + headerfile = [datafile '.m4d']; + sensorfile = [datafile '.xyz']; + case '4d' + [path, file, ext] = fileparts(filename); + datafile = fullfile(path, [file,ext]); + headerfile = fullfile(path, [file,ext]); + configfile = fullfile(path, 'config'); + case {'ctf_ds', 'ctf_old'} + % convert CTF filename into filenames + [path, file, ext] = fileparts(filename); + if any(strcmp(ext, {'.res4' '.meg4', '.1_meg4' '.2_meg4' '.3_meg4' '.4_meg4' '.5_meg4' '.6_meg4' '.7_meg4' '.8_meg4' '.9_meg4'})) + filename = path; + [path, file, ext] = fileparts(filename); + end + if isempty(path) && isempty(file) + % this means that the dataset was specified as the present working directory, i.e. only with '.' + filename = pwd; + [path, file, ext] = fileparts(filename); + end + headerfile = fullfile(filename, [file '.res4']); + datafile = fullfile(filename, [file '.meg4']); + if length(path)>3 && strcmp(path(end-2:end), '.ds') + filename = path; % this is the *.ds directory + end + case 'ctf_meg4' + [path, file, ext] = fileparts(filename); + if isempty(path) + path = pwd; + end + headerfile = fullfile(path, [file '.res4']); + datafile = fullfile(path, [file '.meg4']); + if length(path)>3 && strcmp(path(end-2:end), '.ds') + filename = path; % this is the *.ds directory + end + case 'ctf_res4' + [path, file, ext] = fileparts(filename); + if isempty(path) + path = pwd; + end + headerfile = fullfile(path, [file '.res4']); + datafile = fullfile(path, [file '.meg4']); + if length(path)>3 && strcmp(path(end-2:end), '.ds') + filename = path; % this is the *.ds directory + end + case 'brainvision_vhdr' + [path, file, ext] = fileparts(filename); + headerfile = fullfile(path, [file '.vhdr']); + if exist(fullfile(path, [file '.eeg'])) + datafile = fullfile(path, [file '.eeg']); + elseif exist(fullfile(path, [file '.seg'])) + datafile = fullfile(path, [file '.seg']); + elseif exist(fullfile(path, [file '.dat'])) + datafile = fullfile(path, [file '.dat']); + end + case 'brainvision_eeg' + [path, file, ext] = fileparts(filename); + headerfile = fullfile(path, [file '.vhdr']); + datafile = fullfile(path, [file '.eeg']); + case 'brainvision_seg' + [path, file, ext] = fileparts(filename); + headerfile = fullfile(path, [file '.vhdr']); + datafile = fullfile(path, [file '.seg']); + case 'brainvision_dat' + [path, file, ext] = fileparts(filename); + headerfile = fullfile(path, [file '.vhdr']); + datafile = fullfile(path, [file '.dat']); + case 'itab_raw' + [path, file, ext] = fileparts(filename); + headerfile = fullfile(path, [file '.raw.mhd']); + datafile = fullfile(path, [file '.raw']); + case 'fcdc_matbin' + [path, file, ext] = fileparts(filename); + headerfile = fullfile(path, [file '.mat']); + datafile = fullfile(path, [file '.bin']); + case {'tdt_tsq' 'tdt_tev'} + [path, file, ext] = fileparts(filename); + headerfile = fullfile(path, [file '.tsq']); + datafile = fullfile(path, [file '.tev']); + case 'nmc_archive_k' + headerfile = filename; + otherwise + % convert filename into filenames, assume that the header and data are the same + datafile = filename; + headerfile = filename; +end + +if ~strcmp(filename, headerfile) && ~ft_filetype(filename, 'ctf_ds') + filename = headerfile; % this function will read the header + headerformat = ft_filetype(filename); % update the filetype +end + +% implement the caching in a data-format independent way +if cache && exist(headerfile, 'file') && ~isempty(cacheheader) + % try to get the header from cache + details = dir(headerfile); + if isequal(details, cacheheader.details) + % the header file has not been updated, fetch it from the cache + % fprintf('got header from cache\n'); + hdr = rmfield(cacheheader, 'details'); + + switch ft_filetype(datafile) + case {'ctf_ds' 'ctf_meg4' 'ctf_old' 'read_ctf_res4'} + % for realtime analysis EOF chasing the res4 does not correctly + % estimate the number of samples, so we compute it on the fly + sz = 0; + files = dir([filename '/*.*meg4']); + for j=1:numel(files) + sz = sz + files(j).bytes; + end + hdr.nTrials = floor((sz - 8) / (hdr.nChans*4) / hdr.nSamples); + end + + return; + end % if the details correspond +end % if cache + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% read the data with the low-level reading function +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +switch headerformat + case '4d' + orig = read_4d_hdr(datafile, configfile); + hdr.Fs = orig.header_data.SampleFrequency; + hdr.nChans = orig.header_data.TotalChannels; + hdr.nSamples = orig.header_data.SlicesPerEpoch; + hdr.nSamplesPre = round(orig.header_data.FirstLatency*orig.header_data.SampleFrequency); + hdr.nTrials = orig.header_data.TotalEpochs; + %hdr.label = {orig.channel_data(:).chan_label}'; + hdr.label = orig.Channel; + hdr.grad = bti2grad(orig); + % remember original header details + hdr.orig = orig; + + case {'4d_pdf', '4d_m4d', '4d_xyz'} + orig = read_bti_m4d(filename); + hdr.Fs = orig.SampleFrequency; + hdr.nChans = orig.TotalChannels; + hdr.nSamples = orig.SlicesPerEpoch; + hdr.nSamplesPre = round(orig.FirstLatency*orig.SampleFrequency); + hdr.nTrials = orig.TotalEpochs; + hdr.label = orig.ChannelOrder(:); + hdr.grad = bti2grad(orig); + % remember original header details + hdr.orig = orig; + + case 'bci2000_dat' + % this requires the load_bcidat mex file to be present on the path + hastoolbox('BCI2000', 1); + % this is inefficient, since it reads the complete data + [signal, states, parameters, total_samples] = load_bcidat(filename); + % convert into a FieldTrip-like header + hdr = []; + hdr.nChans = size(signal,2); + hdr.nSamples = total_samples; + hdr.nSamplesPre = 0; % it is continuous + hdr.nTrials = 1; % it is continuous + hdr.Fs = parameters.SamplingRate.NumericValue; + % there are some differences in the fields that are present in the + % *.dat files, probably due to different BCI2000 versions + if isfield(parameters, 'ChannelNames') && isfield(parameters.ChannelNames, 'Value') && ~isempty(parameters.ChannelNames.Value) + hdr.label = parameters.ChannelNames.Value; + elseif isfield(parameters, 'ChannelNames') && isfield(parameters.ChannelNames, 'Values') && ~isempty(parameters.ChannelNames.Values) + hdr.label = parameters.ChannelNames.Values; + else + if isempty(fakechannelwarning) || ~fakechannelwarning + % give this warning only once + warning('creating fake channel names'); + fakechannelwarning = true; + end + for i=1:hdr.nChans + hdr.label{i} = sprintf('%d', i); + end + end + + % remember the original header details + hdr.orig.parameters = parameters; + % also remember the complete data upon request + if cache + hdr.orig.signal = signal; + hdr.orig.states = states; + hdr.orig.total_samples = total_samples; + end + + case 'besa_avr' + orig = read_besa_avr(filename); + hdr.Fs = 1000/orig.di; + hdr.nChans = size(orig.data,1); + hdr.nSamples = size(orig.data,2); + hdr.nSamplesPre = -(hdr.Fs * orig.tsb/1000); % convert from ms to samples + hdr.nTrials = 1; + if isfield(orig, 'label') && iscell(orig.label) + hdr.label = orig.label; + elseif isfield(orig, 'label') && ischar(orig.label) + hdr.label = tokenize(orig.label, ' '); + else + if isempty(fakechannelwarning) || ~fakechannelwarning + % give this warning only once + warning('creating fake channel names'); + fakechannelwarning = true; + end + for i=1:hdr.nChans + hdr.label{i} = sprintf('%d', i); + end + end + + case 'besa_swf' + orig = read_besa_swf(filename); + hdr.Fs = 1000/orig.di; + hdr.nChans = size(orig.data,1); + hdr.nSamples = size(orig.data,2); + hdr.nSamplesPre = -(hdr.Fs * orig.tsb/1000); % convert from ms to samples + hdr.nTrials = 1; + hdr.label = orig.label; + + case {'biosig' 'gdf'} + % use the biosig toolbox if available + hastoolbox('BIOSIG', 1); + hdr = read_biosig_header(filename); + + case {'biosemi_bdf', 'bham_bdf'} + hdr = read_biosemi_bdf(filename); + if any(diff(hdr.orig.SampleRate)) + error('channels with different sampling rate not supported'); + end + if ft_filetype(filename, 'bham_bdf') + % TODO channel renaming should be made a general option + % this is for the Biosemi system used at the University of Birmingham + labelold = { 'A1' 'A2' 'A3' 'A4' 'A5' 'A6' 'A7' 'A8' 'A9' 'A10' 'A11' 'A12' 'A13' 'A14' 'A15' 'A16' 'A17' 'A18' 'A19' 'A20' 'A21' 'A22' 'A23' 'A24' 'A25' 'A26' 'A27' 'A28' 'A29' 'A30' 'A31' 'A32' 'B1' 'B2' 'B3' 'B4' 'B5' 'B6' 'B7' 'B8' 'B9' 'B10' 'B11' 'B12' 'B13' 'B14' 'B15' 'B16' 'B17' 'B18' 'B19' 'B20' 'B21' 'B22' 'B23' 'B24' 'B25' 'B26' 'B27' 'B28' 'B29' 'B30' 'B31' 'B32' 'C1' 'C2' 'C3' 'C4' 'C5' 'C6' 'C7' 'C8' 'C9' 'C10' 'C11' 'C12' 'C13' 'C14' 'C15' 'C16' 'C17' 'C18' 'C19' 'C20' 'C21' 'C22' 'C23' 'C24' 'C25' 'C26' 'C27' 'C28' 'C29' 'C30' 'C31' 'C32' 'D1' 'D2' 'D3' 'D4' 'D5' 'D6' 'D7' 'D8' 'D9' 'D10' 'D11' 'D12' 'D13' 'D14' 'D15' 'D16' 'D17' 'D18' 'D19' 'D20' 'D21' 'D22' 'D23' 'D24' 'D25' 'D26' 'D27' 'D28' 'D29' 'D30' 'D31' 'D32' 'EXG1' 'EXG2' 'EXG3' 'EXG4' 'EXG5' 'EXG6' 'EXG7' 'EXG8' 'Status'}; + labelnew = { 'P9' 'PPO9h' 'PO7' 'PPO5h' 'PPO3h' 'PO5h' 'POO9h' 'PO9' 'I1' 'OI1h' 'O1' 'POO1' 'PO3h' 'PPO1h' 'PPO2h' 'POz' 'Oz' 'Iz' 'I2' 'OI2h' 'O2' 'POO2' 'PO4h' 'PPO4h' 'PO6h' 'POO10h' 'PO10' 'PO8' 'PPO6h' 'PPO10h' 'P10' 'P8' 'TPP9h' 'TP7' 'TTP7h' 'CP5' 'TPP7h' 'P7' 'P5' 'CPP5h' 'CCP5h' 'CP3' 'P3' 'CPP3h' 'CCP3h' 'CP1' 'P1' 'Pz' 'CPP1h' 'CPz' 'CPP2h' 'P2' 'CPP4h' 'CP2' 'CCP4h' 'CP4' 'P4' 'P6' 'CPP6h' 'CCP6h' 'CP6' 'TPP8h' 'TP8' 'TPP10h' 'T7' 'FTT7h' 'FT7' 'FC5' 'FCC5h' 'C5' 'C3' 'FCC3h' 'FC3' 'FC1' 'C1' 'CCP1h' 'Cz' 'FCC1h' 'FCz' 'FFC1h' 'Fz' 'FFC2h' 'FC2' 'FCC2h' 'CCP2h' 'C2' 'C4' 'FCC4h' 'FC4' 'FC6' 'FCC6h' 'C6' 'TTP8h' 'T8' 'FTT8h' 'FT8' 'FT9' 'FFT9h' 'F7' 'FFT7h' 'FFC5h' 'F5' 'AFF7h' 'AF7' 'AF5h' 'AFF5h' 'F3' 'FFC3h' 'F1' 'AF3h' 'Fp1' 'Fpz' 'Fp2' 'AFz' 'AF4h' 'F2' 'FFC4h' 'F4' 'AFF6h' 'AF6h' 'AF8' 'AFF8h' 'F6' 'FFC6h' 'FFT8h' 'F8' 'FFT10h' 'FT10'}; + % rename the channel labels + for i=1:length(labelnew) + chan = strcmp(labelold(i), hdr.label); + hdr.label(chan) = labelnew(chan); + end + end + + case {'biosemi_old'} + % this uses the openbdf and readbdf functions that I copied from the EEGLAB toolbox + orig = openbdf(filename); + if any(orig.Head.SampleRate~=orig.Head.SampleRate(1)) + error('channels with different sampling rate not supported'); + end + hdr.Fs = orig.Head.SampleRate(1); + hdr.nChans = orig.Head.NS; + hdr.label = cellstr(orig.Head.Label); + % it is continuous data, therefore append all records in one trial + hdr.nSamples = orig.Head.NRec * orig.Head.Dur * orig.Head.SampleRate(1); + hdr.nSamplesPre = 0; + hdr.nTrials = 1; + hdr.orig = orig; + % close the file between seperate read operations + fclose(orig.Head.FILE.FID); + + case {'brainvision_vhdr', 'brainvision_seg', 'brainvision_eeg', 'brainvision_dat'} + orig = read_brainvision_vhdr(filename); + hdr.Fs = orig.Fs; + hdr.nChans = orig.NumberOfChannels; + hdr.label = orig.label; + hdr.nSamples = orig.nSamples; + hdr.nSamplesPre = orig.nSamplesPre; + hdr.nTrials = orig.nTrials; + hdr.orig = orig; + + case 'ced_son' + % check that the required low-level toolbox is available + hastoolbox('neuroshare', 1); + % use the reading function supplied by Gijs van Elswijk + orig = read_ced_son(filename,'readevents','no','readdata','no'); + orig = orig.header; + % In Spike2, channels can have different sampling rates, units, length + % etc. etc. Here, channels need to have to same properties. + if length(unique([orig.samplerate]))>1, + error('channels with different sampling rates are not supported'); + else + hdr.Fs = orig(1).samplerate; + end; + hdr.nChans = length(orig); + % nsamples of the channel with least samples + hdr.nSamples = min([orig.nsamples]); + hdr.nSamplesPre = 0; + % only continuous data supported + if sum(strcmpi({orig.mode},'continuous')) < hdr.nChans, + error('not all channels contain continuous data'); + else + hdr.nTrials = 1; + end; + hdr.label = {orig.label}; + + case 'combined_ds' + hdr = read_combined_ds(filename); + + case {'ctf_ds', 'ctf_meg4', 'ctf_res4'} + % check the presence of the required low-level toolbox + hastoolbox('ctf', 1); + orig = readCTFds(filename); + hdr.Fs = orig.res4.sample_rate; + hdr.nChans = orig.res4.no_channels; + hdr.nSamples = orig.res4.no_samples; + hdr.nSamplesPre = orig.res4.preTrigPts; + hdr.nTrials = orig.res4.no_trials; + hdr.label = cellstr(orig.res4.chanNames); + for i=1:numel(hdr.label) + % remove the site-specific numbers from each channel name, e.g. 'MZC01-1706' becomes 'MZC01' + hdr.label{i} = strtok(hdr.label{i}, '-'); + end + % read the balance coefficients, these are used to compute the synthetic gradients + coeftype = cellstr(char(orig.res4.scrr(:).coefType)); + try + [alphaMEG,MEGlist,Refindex] = getCTFBalanceCoefs(orig,'NONE', 'T'); + orig.BalanceCoefs.none.alphaMEG = alphaMEG; + orig.BalanceCoefs.none.MEGlist = MEGlist; + orig.BalanceCoefs.none.Refindex = Refindex; + catch + warning('cannot read balancing coefficients for NONE'); + end + if any(~cellfun(@isempty,strfind(coeftype, 'G1BR'))) + try + [alphaMEG,MEGlist,Refindex] = getCTFBalanceCoefs(orig,'G1BR', 'T'); + orig.BalanceCoefs.G1BR.alphaMEG = alphaMEG; + orig.BalanceCoefs.G1BR.MEGlist = MEGlist; + orig.BalanceCoefs.G1BR.Refindex = Refindex; + catch + warning('cannot read balancing coefficients for G1BR'); + end + end + if any(~cellfun(@isempty,strfind(coeftype, 'G2BR'))) + try + [alphaMEG,MEGlist,Refindex] = getCTFBalanceCoefs(orig,'G2BR', 'T'); + orig.BalanceCoefs.G2BR.alphaMEG = alphaMEG; + orig.BalanceCoefs.G2BR.MEGlist = MEGlist; + orig.BalanceCoefs.G2BR.Refindex = Refindex; + catch + warning('cannot read balancing coefficients for G2BR'); + end + end + if any(~cellfun(@isempty,strfind(coeftype, 'G3BR'))) + try + [alphaMEG,MEGlist,Refindex] = getCTFBalanceCoefs(orig,'G3BR', 'T'); + orig.BalanceCoefs.G3BR.alphaMEG = alphaMEG; + orig.BalanceCoefs.G3BR.MEGlist = MEGlist; + orig.BalanceCoefs.G3BR.Refindex = Refindex; + catch + warning('cannot read balancing coefficients for G3BR'); + end + end + if any(~cellfun(@isempty,strfind(coeftype, 'G1AR'))) + try + [alphaMEG,MEGlist,Refindex] = getCTFBalanceCoefs(orig,'G3AR', 'T'); + orig.BalanceCoefs.G3AR.alphaMEG = alphaMEG; + orig.BalanceCoefs.G3AR.MEGlist = MEGlist; + orig.BalanceCoefs.G3AR.Refindex = Refindex; + catch + % May not want a warning here if these are not commonly used. + % Already get a (fprintf) warning from getCTFBalanceCoefs.m + % warning('cannot read balancing coefficients for G3AR'); + end + end + % add a gradiometer structure for forward and inverse modelling + try + hdr.grad = ctf2grad(orig); + catch + % this fails if the res4 file is not correctly closed, e.g. during realtime processing + tmp = lasterror; + disp(tmp.message); + warning('could not construct gradiometer definition from the header'); + end + + % for realtime analysis EOF chasing the res4 does not correctly + % estimate the number of samples, so we compute it on the fly from the + % meg4 file sizes. + sz = 0; + files = dir([filename '/*.*meg4']); + for j=1:numel(files) + sz = sz + files(j).bytes; + end + hdr.nTrials = floor((sz - 8) / (hdr.nChans*4) / hdr.nSamples); + + % add the original header details + hdr.orig = orig; + + case {'ctf_old', 'read_ctf_res4'} + % read it using the open-source matlab code that originates from CTF and that was modified by the FCDC + orig = read_ctf_res4(headerfile); + hdr.Fs = orig.Fs; + hdr.nChans = orig.nChans; + hdr.nSamples = orig.nSamples; + hdr.nSamplesPre = orig.nSamplesPre; + hdr.nTrials = orig.nTrials; + hdr.label = orig.label; + % add a gradiometer structure for forward and inverse modelling + try + hdr.grad = ctf2grad(orig); + catch + % this fails if the res4 file is not correctly closed, e.g. during realtime processing + tmp = lasterror; + disp(tmp.message); + warning('could not construct gradiometer definition from the header'); + end + % add the original header details + hdr.orig = orig; + + case 'ctf_read_res4' + % check that the required low-level toolbos ix available + hastoolbox('eegsf', 1); + % read it using the CTF importer from the NIH and Daren Weber + orig = ctf_read_res4(filename, 0); + % convert the header into a structure that FieldTrip understands + hdr = []; + hdr.Fs = orig.setup.sample_rate; + hdr.nChans = length(orig.sensor.info); + hdr.nSamples = orig.setup.number_samples; + hdr.nSamplesPre = orig.setup.pretrigger_samples; + hdr.nTrials = orig.setup.number_trials; + for i=1:length(orig.sensor.info) + hdr.label{i} = orig.sensor.info(i).label; + end + hdr.label = hdr.label(:); + % add a gradiometer structure for forward and inverse modelling + try + hdr.grad = ctf2grad(orig); + catch + % this fails if the res4 file is not correctly closed, e.g. during realtime processing + tmp = lasterror; + disp(tmp.message); + warning('could not construct gradiometer definition from the header'); + end + % add the original header details + hdr.orig = orig; + + case 'ctf_shm' + % contact Robert Oostenveld if you are interested in real-time acquisition on the CTF system + % read the header information from shared memory + hdr = read_shm_header(filename); + + case 'edf' + % this reader is largely similar to the bdf reader + hdr = read_edf(filename); + + case 'eep_avr' + % check that the required low-level toolbox is available + hastoolbox('eeprobe', 1); + % read the whole average and keep only header info (it is a bit silly, but the easiest to do here) + hdr = read_eep_avr(filename); + hdr.Fs = hdr.rate; + hdr.nChans = size(hdr.data,1); + hdr.nSamples = size(hdr.data,2); + hdr.nSamplesPre = hdr.xmin*hdr.rate/1000; + hdr.nTrials = 1; % it can always be interpreted as continuous data + % remove the data and variance if present + hdr = rmfield(hdr, 'data'); + try, hdr = rmfield(hdr, 'variance'); end + + case 'eeglab_set' + hdr = read_eeglabheader(filename); + + case 'eyelink_asc' + asc = read_eyelink_asc(filename); + hdr.nChans = size(asc.dat,1); + hdr.nSamples = size(asc.dat,2); + hdr.nSamplesPre = 0; + hdr.nTrials = 1; + hdr.Fs = 1000/median(diff(asc.dat(1,:))); % these timestamps are in miliseconds + hdr.FirstTimeStamp = asc.dat(1,1); + hdr.TimeStampPerSample = median(diff(asc.dat(1,:))); + if isempty(fakechannelwarning) || ~fakechannelwarning + % give this warning only once + warning('creating fake channel names'); + fakechannelwarning = true; + end + for i=1:hdr.nChans + hdr.label{i} = sprintf('%d', i); + end + + % remember the original header details + hdr.orig.header = asc.header; + % remember all header and data details upon request + if cache + hdr.orig = asc; + end + + case 'spmeeg_mat' + hdr = read_spmeeg_header(filename); + + case 'ced_spike6mat' + hdr = read_spike6mat_header(filename); + + case 'eep_cnt' + % check that the required low-level toolbox is available + hastoolbox('eeprobe', 1); + % read the first sample from the continous data, which will also return the header + hdr = read_eep_cnt(filename, 1, 1); + hdr.Fs = hdr.rate; + hdr.nSamples = hdr.nsample; + hdr.nSamplesPre = 0; + hdr.nChans = hdr.nchan; + hdr.nTrials = 1; % it can always be interpreted as continuous data + + case 'egi_egia' + [fhdr,chdr,ename,cnames,fcom,ftext] = read_egis_header(filename); + [p, f, x] = fileparts(filename); + + if any(chdr(:,4)-chdr(1,4)) + error('Sample rate not the same for all cells.'); + end; + + hdr.Fs = chdr(1,4); %making assumption that sample rate is same for all cells + hdr.nChans = fhdr(19); + for i = 1:hdr.nChans + hdr.label{i,1} = ['e' num2str(i)]; + end; + %since NetStation does not properly set the fhdr(11) field, use the number of subjects from the chdr instead + hdr.nTrials = chdr(1,2)*fhdr(18); %number of trials is numSubjects * numCells + hdr.nSamplesPre = ceil(fhdr(14)/(1000/hdr.Fs)); + + if any(chdr(:,3)-chdr(1,3)) + error('Number of samples not the same for all cells.'); + end; + + hdr.nSamples = chdr(1,3); %making assumption that number of samples is same for all cells + + % remember the original header details + hdr.orig.fhdr = fhdr; + hdr.orig.chdr = chdr; + hdr.orig.ename = ename; + hdr.orig.cnames = cnames; + hdr.orig.fcom = fcom; + hdr.orig.ftext = ftext; + + case 'egi_egis' + [fhdr,chdr,ename,cnames,fcom,ftext] = read_egis_header(filename); + [p, f, x] = fileparts(filename); + + if any(chdr(:,4)-chdr(1,4)) + error('Sample rate not the same for all cells.'); + end; + + hdr.Fs = chdr(1,4); %making assumption that sample rate is same for all cells + hdr.nChans = fhdr(19); + for i = 1:hdr.nChans + hdr.label{i,1} = ['e' num2str(i)]; + end; + hdr.nTrials = sum(chdr(:,2)); + hdr.nSamplesPre = ceil(fhdr(14)/(1000/hdr.Fs)); + % assuming that a utility was used to insert the correct baseline + % duration into the header since it is normally absent. This slot is + % actually allocated to the age of the subject, although NetStation + % does not use it when generating an EGIS session file. + + if any(chdr(:,3)-chdr(1,3)) + error('Number of samples not the same for all cells.'); + end; + + hdr.nSamples = chdr(1,3); %making assumption that number of samples is same for all cells + + % remember the original header details + hdr.orig.fhdr = fhdr; + hdr.orig.chdr = chdr; + hdr.orig.ename = ename; + hdr.orig.cnames = cnames; + hdr.orig.fcom = fcom; + hdr.orig.ftext = ftext; + + case 'egi_sbin' + % segmented type only + [header_array, CateNames, CatLengths, preBaseline] = read_sbin_header(filename); + [p, f, x] = fileparts(filename); + + hdr.Fs = header_array(9); + hdr.nChans = header_array(10); + for i = 1:hdr.nChans + hdr.label{i,1} = ['e' num2str(i)]; + end; + hdr.nTrials = header_array(15); + hdr.nSamplesPre = preBaseline; + + hdr.nSamples = header_array(16); % making assumption that number of samples is same for all cells + + % remember the original header details + hdr.orig.header_array = header_array; + hdr.orig.CateNames = CateNames; + hdr.orig.CatLengths = CatLengths; + + case 'fcdc_buffer' + % read from a networked buffer for realtime analysis + [host, port] = filetype_check_uri(filename); + if retry + orig = []; + while isempty(orig) + try + % try reading the header, catch the error and retry + orig = buffer('get_hdr', [], host, port); + catch + warning('could not read header from %s, retrying in 1 second', filename); + pause(1); + end + end % while + else + % try reading the header only once, give error if it fails + orig = buffer('get_hdr', [], host, port); + end % if retry + hdr.Fs = orig.fsample; + hdr.nChans = orig.nchans; + hdr.nSamples = orig.nsamples; + hdr.nSamplesPre = 0; % since continuous + hdr.nTrials = 1; % since continuous + hdr.orig = []; % add chunks if present + + % add the contents of attached .res4 file to the .orig field similar to offline data + if isfield(orig, 'ctf_res4') + tmp_name = tempname; + F = fopen(tmp_name, 'wb'); + fwrite(F, orig.ctf_res4, 'uint8'); + fclose(F); + R4F = read_ctf_res4(tmp_name); + delete(tmp_name); + % copy over the labels + hdr.label = R4F.label; + % copy over the 'original' header + hdr.orig = R4F; + % add the raw chunk as well + hdr.orig.ctf_res4 = orig.ctf_res4; + end + + % add the contents of attached NIFTI-1 chunk after decoding to Matlab structure + if isfield(orig, 'nifti_1') + hdr.nifti_1 = decode_nifti1(orig.nifti_1); + % add the raw chunk as well + hdr.orig.nifti_1 = orig.nifti_1; + end + + % add the contents of attached SiemensAP chunk after decoding to Matlab structure + if isfield(orig, 'siemensap') && exist('sap2matlab')==3 % only run this if MEX file is present + hdr.siemensap = sap2matlab(orig.siemensap); + % add the raw chunk as well + hdr.orig.siemensap = orig.siemensap; + end + + if ~isfield(hdr, 'label') + % prevent overwriting the labels that we might have gotten from a RES4 chunk + if isfield(orig, 'channel_names') + hdr.label = orig.channel_names; + else + if isempty(fakechannelwarning) || ~fakechannelwarning + % give this warning only once + warning('creating fake channel names'); + fakechannelwarning = true; + end + hdr.label = cell(hdr.nChans,1); + if hdr.nChans < 2000 % don't do this for fMRI etc. + for i=1:hdr.nChans + hdr.label{i} = sprintf('%d', i); + end + end + end + end + hdr.orig.bufsize = orig.bufsize; + + case 'fcdc_matbin' + % this is multiplexed data in a *.bin file, accompanied by a matlab file containing the header + load(headerfile, 'hdr'); + + case 'fcdc_mysql' + % read from a MySQL server listening somewhere else on the network + db_open(filename); + if db_blob + hdr = db_select_blob('fieldtrip.header', 'msg', 1); + else + hdr = db_select('fieldtrip.header', {'nChans', 'nSamples', 'nSamplesPre', 'Fs', 'label'}, 1); + hdr.label = mxDeserialize(hdr.label); + end + + case {'itab_raw' 'itab_mhd'} + % read the full header information frtom the binary header structure + header_info = read_itab_mhd(headerfile); + + % these are the channels that are visible to fieldtrip + chansel = 1:header_info.nchan; + + % convert the header information into a fieldtrip compatible format + hdr.nChans = length(chansel); + hdr.label = {header_info.ch(chansel).label}; + hdr.label = hdr.label(:); % should be column vector + hdr.Fs = header_info.smpfq; + % it will always be continuous data + hdr.nSamples = header_info.ntpdata; + hdr.nSamplesPre = 0; % it is a single continuous trial + hdr.nTrials = 1; % it is a single continuous trial + % keep the original details AND the list of channels as used by fieldtrip + hdr.orig = header_info; + hdr.orig.chansel = chansel; + % add the gradiometer definition + hdr.grad = itab2grad(header_info); + + case 'micromed_trc' + orig = read_micromed_trc(filename); + hdr = []; + hdr.Fs = orig.Rate_Min; % FIXME is this correct? + hdr.nChans = orig.Num_Chan; + hdr.nSamples = orig.Num_Samples; + hdr.nSamplesPre = 0; % continuous + hdr.nTrials = 1; % continuous + hdr.label = cell(1,hdr.nChans); + if isempty(fakechannelwarning) || ~fakechannelwarning + % give this warning only once + warning('creating fake channel names'); + fakechannelwarning = true; + end + for i=1:hdr.nChans + hdr.label{i} = sprintf('%3d', i); + end + % this should be a column vector + hdr.label = hdr.label(:); + % remember the original header details + hdr.orig = orig; + + case {'mpi_ds', 'mpi_dap'} + hdr = read_mpi_ds(filename); + + case 'neuralynx_dma' + hdr = read_neuralynx_dma(filename); + + case 'neuralynx_sdma' + hdr = read_neuralynx_sdma(filename); + + case 'neuralynx_ncs' + ncs = read_neuralynx_ncs(filename, 1, 0); + [p, f, x] = fileparts(filename); + hdr.Fs = ncs.hdr.SamplingFrequency; + hdr.label = {f}; + hdr.nChans = 1; + hdr.nTrials = 1; + hdr.nSamplesPre = 0; + hdr.nSamples = ncs.NRecords * 512; + hdr.orig = ncs.hdr; + FirstTimeStamp = ncs.hdr.FirstTimeStamp; % this is the first timestamp of the first block + LastTimeStamp = ncs.hdr.LastTimeStamp; % this is the first timestamp of the last block, i.e. not the timestamp of the last sample + hdr.TimeStampPerSample = double(LastTimeStamp - FirstTimeStamp) ./ ((ncs.NRecords-1)*512); + hdr.FirstTimeStamp = FirstTimeStamp; + + case 'neuralynx_nse' + nse = read_neuralynx_nse(filename, 1, 0); + [p, f, x] = fileparts(filename); + hdr.Fs = nse.hdr.SamplingFrequency; + hdr.label = {f}; + hdr.nChans = 1; + hdr.nTrials = nse.NRecords; % each record contains one waveform + hdr.nSamples = 32; % there are 32 samples in each waveform + hdr.nSamplesPre = 0; + hdr.orig = nse.hdr; + % FIXME add hdr.FirstTimeStamp and hdr.TimeStampPerSample + + case {'neuralynx_ttl', 'neuralynx_tsl', 'neuralynx_tsh'} + % these are hardcoded, they contain an 8-byte header and int32 values for a single channel + % FIXME this should be done similar as neuralynx_bin, i.e. move the hdr into the function + hdr = []; + hdr.Fs = 32556; + hdr.nChans = 1; + hdr.nSamples = (filesize(filename)-8)/4; + hdr.nSamplesPre = 1; + hdr.nTrials = 1; + hdr.label = {headerformat((end-3):end)}; + + case 'neuralynx_bin' + hdr = read_neuralynx_bin(filename); + + case 'neuralynx_ds' + hdr = read_neuralynx_ds(filename); + + case 'neuralynx_cds' + hdr = read_neuralynx_cds(filename); + + case 'nexstim_nxe' + hdr = read_nexstim_nxe(filename); + + case {'neuromag_fif' 'neuromag_mne'} + % check that the required low-level toolbox is available + hastoolbox('mne', 1); + + orig = fiff_read_meas_info(filename); + % convert to fieldtrip format header + hdr.label = orig.ch_names(:); + hdr.nChans = orig.nchan; + hdr.Fs = orig.sfreq; + % add a gradiometer structure for forward and inverse modelling + try + [hdr.grad, elec] = mne2grad(orig); + if ~isempty(elec) + hdr.elec = elec; + end + catch + disp(lasterr); + end + + for i = 1:hdr.nChans % make a cell array of units for each channel + switch orig.chs(i).unit + case 201 % defined as constants by MNE, see p. 217 of MNE manual + hdr.unit{i} = 'T/m'; + case 112 + hdr.unit{i} = 'T'; + case 107 + hdr.unit{i} = 'V'; + case 202 + hdr.unit{i} = 'Am'; + otherwise + hdr.unit{i} = 'unknown'; + end + end + + iscontinuous = 0; + isaverage = 0; + isepoched = 0; % FIXME don't know how to determine this, or whether epoched .fif data exists! + + if isempty(fiff_find_evoked(filename)) % true if file contains no evoked responses + iscontinuous = 1; + else + isaverage = 1; + end + + if iscontinuous + raw = fiff_setup_read_raw(filename); + hdr.nSamples = raw.last_samp - raw.first_samp + 1; % number of samples per trial + hdr.nSamplesPre = 0; + % otherwise conflicts will occur in read_data + hdr.nTrials = 1; + orig.raw = raw; % keep all the details + + elseif isaverage + evoked_data = fiff_read_evoked_all(filename); + vartriallength = any(diff([evoked_data.evoked.first])) || any(diff([evoked_data.evoked.last])); + if vartriallength + % there are trials averages with variable durations in the file + warning('EVOKED FILE with VARIABLE TRIAL LENGTH! - check data have been processed accurately'); + hdr.nSamples = 0; + for i=1:length(evoked_data.evoked) + hdr.nSamples = hdr.nSamples + size(evoked_data.evoked(i).epochs, 2); + end + % represent it as a continuous file with a single trial + % all trial average details will be available through read_event + hdr.nSamplesPre = 0; + hdr.nTrials = 1; + orig.evoked = evoked_data.evoked; % this is used by read_data to get the actual data, i.e. to prevent re-reading + orig.info = evoked_data.info; % keep all the details + orig.vartriallength = 1; + else + % represent it as a file with multiple trials, each trial has the same length + % all trial average details will be available through read_event + hdr.nSamples = evoked_data.evoked(1).last - evoked_data.evoked(1).first + 1; + hdr.nSamplesPre = -evoked_data.evoked(1).first; % represented as negative number in fif file + hdr.nTrials = length(evoked_data.evoked); + orig.evoked = evoked_data.evoked; % this is used by read_data to get the actual data, i.e. to prevent re-reading + orig.info = evoked_data.info; % keep all the details + orig.vartriallength = 0; + end + + elseif isepoched + error('Support for epoched *.fif data is not yet implemented.') + end + + % remember the original header details + hdr.orig = orig; + + % these are useful to know in read_event + hdr.orig.isaverage = isaverage; + hdr.orig.iscontinuous = iscontinuous; + hdr.orig.isepoched = isepoched; + + case 'neuromag_mex' + % check that the required low-level toolbox is available + hastoolbox('meg-pd', 1); + rawdata('any',filename); + rawdata('goto', 0); + megmodel('head',[0 0 0],filename); + % get the available information from the fif file + [orig.rawdata.range,orig.rawdata.calib] = rawdata('range'); + [orig.rawdata.sf] = rawdata('sf'); + [orig.rawdata.samples] = rawdata('samples'); + [orig.chaninfo.N,orig.chaninfo.S,orig.chaninfo.T] = chaninfo; % Numbers, names & places + [orig.chaninfo.TY,orig.chaninfo.NA] = chaninfo('type'); % Coil type + [orig.chaninfo.NO] = chaninfo('noise'); % Default noise level + [orig.channames.NA,orig.channames.KI,orig.channames.NU] = channames(filename); % names, kind, logical numbers + % read a single trial to determine the data size + [buf, status] = rawdata('next'); + rawdata('close'); + + % This is to solve a problem reported by Doug Davidson: The problem + % is that rawdata('samples') is not returning the number of samples + % correctly. It appears that the example script rawchannels in meg-pd + % might work, however, so I want to use rawchannels to read in one + % channel of data in order to get the number of samples in the file: + if orig.rawdata.samples<0 + tmpchannel = 1; + tmpvar = rawchannels(filename,tmpchannel); + [orig.rawdata.samples] = size(tmpvar,2); + clear tmpvar tmpchannel; + end + + % convert to fieldtrip format header + hdr.label = orig.channames.NA; + hdr.Fs = orig.rawdata.sf; + hdr.nSamplesPre = 0; % I don't know how to get this out of the file + hdr.nChans = size(buf,1); + hdr.nSamples = size(buf,2); % number of samples per trial + hdr.nTrials = orig.rawdata.samples ./ hdr.nSamples; + % add a gradiometer structure for forward and inverse modelling + hdr.grad = fif2grad(filename); + % remember the original header details + hdr.orig = orig; + + case 'neuroprax_eeg' + orig = np_readfileinfo(filename); + + hdr.Fs = orig.fa; + hdr.nChans = orig.K; + hdr.nSamples = orig.N; + hdr.nSamplesPre = 0; % continuous + hdr.nTrials = 1; % continuous + hdr.label = orig.channels(:); + hdr.unit = orig.units(:); + + % remember the original header details + hdr.orig = orig; + + case 'nimh_cortex' + cortex = read_nimh_cortex(filename, 'epp', 'no', 'eog', 'no'); + % look at the first trial to determine whether it contains data in the EPP and EOG channels + trial1 = read_nimh_cortex(filename, 'epp', 'yes', 'eog', 'yes', 'begtrial', 1, 'endtrial', 1); + hasepp = ~isempty(trial1.epp); + haseog = ~isempty(trial1.eog); + if hasepp + warning('EPP channels are not yet supported'); + end + % at the moment only the EOG channels are supported here + if haseog + hdr.label = {'EOGx' 'EOGy'}; + hdr.nChans = 2; + else + hdr.label = {}; + hdr.nChans = 0; + end + hdr.nTrials = length(cortex); + hdr.nSamples = inf; + hdr.nSamplesPre = 0; + hdr.orig.trial = cortex; + hdr.orig.hasepp = hasepp; + hdr.orig.haseog = haseog; + + case 'ns_avg' + orig = read_ns_hdr(filename); + % do some reformatting/renaming of the header items + hdr.Fs = orig.rate; + hdr.nSamples = orig.npnt; + hdr.nSamplesPre = round(-orig.rate*orig.xmin/1000); + hdr.nChans = orig.nchan; + hdr.label = orig.label(:); + hdr.nTrials = 1; % the number of trials in this datafile is only one, i.e. the average + % remember the original header details + hdr.orig = orig; + + case {'ns_cnt' 'ns_cnt16', 'ns_cnt32'} + if strcmp(headerformat, 'ns_cnt') + orig = loadcnt(filename, 'ldnsamples', 1); + elseif strcmp(headerformat, 'ns_cnt16') + orig = loadcnt(filename, 'ldnsamples', 1, 'dataformat', 'int16'); + elseif strcmp(headerformat, 'ns_cnt32') + orig = loadcnt(filename, 'ldnsamples', 1, 'dataformat', 'int32'); + end + + orig = rmfield(orig, {'data', 'ldnsamples'}); + + % do some reformatting/renaming of the header items + hdr.Fs = orig.header.rate; + hdr.nChans = orig.header.nchannels; + hdr.nSamples = orig.header.nums; + hdr.nSamplesPre = 0; + hdr.nTrials = 1; + for i=1:hdr.nChans + hdr.label{i} = deblank(orig.electloc(i).lab); + end + % remember the original header details + hdr.orig = orig; + + case 'ns_eeg' + orig = read_ns_hdr(filename); + % do some reformatting/renaming of the header items + hdr.label = orig.label; + hdr.Fs = orig.rate; + hdr.nSamples = orig.npnt; + hdr.nSamplesPre = round(-orig.rate*orig.xmin/1000); + hdr.nChans = orig.nchan; + hdr.nTrials = orig.nsweeps; + % remember the original header details + hdr.orig = orig; + + case 'plexon_ds' + hdr = read_plexon_ds(filename); + + case 'plexon_ddt' + orig = read_plexon_ddt(filename); + hdr.nChans = orig.NChannels; + hdr.Fs = orig.Freq; + hdr.nSamples = orig.NSamples; + hdr.nSamplesPre = 0; % continuous + hdr.nTrials = 1; % continuous + hdr.label = cell(1,hdr.nChans); + if isempty(fakechannelwarning) || ~fakechannelwarning + % give this warning only once + warning('creating fake channel names'); + fakechannelwarning = true; + end + for i=1:hdr.nChans + hdr.label{i} = sprintf('%d', i); + end + % also remember the original header + hdr.orig = orig; + + case {'read_nex_data'} % this is an alternative reader for nex files + orig = read_nex_header(filename); + % assign the obligatory items to the output FCDC header + numsmp = cell2mat({orig.varheader.numsmp}); + adindx = find(cell2mat({orig.varheader.typ})==5); + if isempty(adindx) + error('file does not contain continuous channels'); + end + hdr.nChans = length(orig.varheader); + hdr.Fs = orig.varheader(adindx(1)).wfrequency; % take the sampling frequency from the first A/D channel + hdr.nSamples = max(numsmp(adindx)); % take the number of samples from the longest A/D channel + hdr.nTrials = 1; % it can always be interpreted as continuous data + hdr.nSamplesPre = 0; % and therefore it is not trial based + for i=1:hdr.nChans + hdr.label{i} = deblank(char(orig.varheader(i).nam)); + end + hdr.label = hdr.label(:); + % also remember the original header details + hdr.orig = orig; + + case {'read_plexon_nex' 'plexon_nex'} % this is the default reader for nex files + orig = read_plexon_nex(filename); + numsmp = cell2mat({orig.VarHeader.NPointsWave}); + adindx = find(cell2mat({orig.VarHeader.Type})==5); + if isempty(adindx) + error('file does not contain continuous channels'); + end + hdr.nChans = length(orig.VarHeader); + hdr.Fs = orig.VarHeader(adindx(1)).WFrequency; % take the sampling frequency from the first A/D channel + hdr.nSamples = max(numsmp(adindx)); % take the number of samples from the longest A/D channel + hdr.nTrials = 1; % it can always be interpreted as continuous data + hdr.nSamplesPre = 0; % and therefore it is not trial based + for i=1:hdr.nChans + hdr.label{i} = deblank(char(orig.VarHeader(i).Name)); + end + hdr.label = hdr.label(:); + hdr.FirstTimeStamp = orig.FileHeader.Beg; + hdr.TimeStampPerSample = orig.FileHeader.Frequency ./ hdr.Fs; + % also remember the original header details + hdr.orig = orig; + + case 'plexon_plx' + orig = read_plexon_plx(filename); + if orig.NumSlowChannels==0 + error('file does not contain continuous channels'); + end + fsample = [orig.SlowChannelHeader.ADFreq]; + if any(fsample~=fsample(1)) + error('different sampling rates in continuous data not supported'); + end + for i=1:length(orig.SlowChannelHeader) + label{i} = deblank(orig.SlowChannelHeader(i).Name); + end + % continuous channels don't always contain data, remove the empty ones + sel = [orig.DataBlockHeader.Type]==5; % continuous + chan = [orig.DataBlockHeader.Channel]; + for i=1:length(label) + chansel(i) = any(chan(sel)==orig.SlowChannelHeader(i).Channel); + end + chansel = find(chansel); % this is required for timestamp selection + label = label(chansel); + % only the continuous channels are returned as visible + hdr.nChans = length(label); + hdr.Fs = fsample(1); + hdr.label = label; + % also remember the original header + hdr.orig = orig; + + % select the first continuous channel that has data + sel = ([orig.DataBlockHeader.Type]==5 & [orig.DataBlockHeader.Channel]==orig.SlowChannelHeader(chansel(1)).Channel); + % get the timestamps that correspond with the continuous data + tsl = [orig.DataBlockHeader(sel).TimeStamp]'; + tsh = [orig.DataBlockHeader(sel).UpperByteOf5ByteTimestamp]'; + ts = timestamp_plexon(tsl, tsh); % use helper function, this returns an uint64 array + + % determine the number of samples in the continuous channels + num = [orig.DataBlockHeader(sel).NumberOfWordsInWaveform]; + hdr.nSamples = sum(num); + hdr.nSamplesPre = 0; % continuous + hdr.nTrials = 1; % continuous + + % the timestamps indicate the beginning of each block, hence the timestamp of the last block corresponds with the end of the previous block + hdr.TimeStampPerSample = double(ts(end)-ts(1))/sum(num(1:(end-1))); + hdr.FirstTimeStamp = ts(1); % the timestamp of the first continuous sample + + % also make the spike channels visible + for i=1:length(orig.ChannelHeader) + hdr.label{end+1} = deblank(orig.ChannelHeader(i).Name); + end + hdr.label = hdr.label(:); + hdr.nChans = length(hdr.label); + + case {'tdt_tsq', 'tdt_tev'} + tsq = read_tdt_tsq(headerfile); + k = 0; + chan = unique([tsq.channel]); + % loop over the physical channels + for i=1:length(chan) + chansel = [tsq.channel]==chan(i); + code = unique([tsq(chansel).code]); + % loop over the logical channels + for j=1:length(code) + codesel = [tsq.code]==code(j); + % find the first instance of this logical channel + this = find(chansel & codesel, 1); + % add it to the list of channels + k = k + 1; + frequency(k) = tsq(this).frequency; + label{k} = [char(typecast(tsq(this).code, 'uint8')) num2str(tsq(this).channel)]; + tsqorig(k) = tsq(this); + end + end + % the above code is not complete + error('not yet implemented'); + + case {'yokogawa_ave', 'yokogawa_con', 'yokogawa_raw', 'yokogawa_mrk'} + % chek that the required low-level toolbox is available + hastoolbox('yokogawa', 1); + hdr = read_yokogawa_header(filename); + % add a gradiometer structure for forward and inverse modelling + hdr.grad = yokogawa2grad(hdr); + + case 'nmc_archive_k' + hdr = read_nmc_archive_k_hdr(filename); + + case 'neuroshare' % NOTE: still under development + % check that the required neuroshare toolbox is available + hastoolbox('neuroshare', 1); + + tmp = read_neuroshare(filename); + hdr.Fs = tmp.hdr.seginfo(1).SampleRate; % take the sampling freq from the first channel (assuming this is the same for all chans) + hdr.nChans = tmp.hdr.fileinfo.EntityCount; + hdr.nSamples = max([tmp.hdr.entityinfo.ItemCount]); % take the number of samples from the longest channel + hdr.nSamplesPre = 0; % continuous data + hdr.nTrials = 1; % continuous data + hdr.label = {tmp.hdr.entityinfo.EntityLabel}; %%% contains non-unique chans + hdr.orig = tmp; % remember the original header + + otherwise + if strcmp(fallback, 'biosig') && hastoolbox('BIOSIG', 1) + hdr = read_biosig_header(filename); + else + error('unsupported header format (%s)', headerformat); + end +end + +if length(hdr.label)~=length(unique(hdr.label)) + % all channels must have unique names + warning('all channels must have unique labels, creating unique labels'); + for i=1:hdr.nChans + sel = find(strcmp(hdr.label{i}, hdr.label)); + if length(sel)>1 + for j=1:length(sel) + hdr.label{sel(j)} = sprintf('%s-%d', hdr.label{sel(j)}, j); + end + end + end +end + +% ensure that these are double precision and not integers, otherwise +% subsequent computations that depend on these might be messed up +hdr.Fs = double(hdr.Fs); +hdr.nSamples = double(hdr.nSamples); +hdr.nSamplesPre = double(hdr.nSamplesPre); +hdr.nTrials = double(hdr.nTrials); +hdr.nChans = double(hdr.nChans); + +if cache && exist(headerfile, 'file') + % put the header in the cache + cacheheader = hdr; + % update the header details (including time stampp, size and name) + cacheheader.details = dir(headerfile); + % fprintf('added header to cache\n'); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION to determine the file size in bytes +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [siz] = filesize(filename) +l = dir(filename); +if l.isdir + error(sprintf('"%s" is not a file', filename)); +end +siz = l.bytes; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION to determine the file size in bytes +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [hdr] = recursive_read_header(filename) +[p, f, x] = fileparts(filename); +ls = dir(filename); +ls = ls(~strcmp({ls.name}, '.')); % exclude this directory +ls = ls(~strcmp({ls.name}, '..')); % exclude parent directory +for i=1:length(ls) + % make sure that the directory listing includes the complete path + ls(i).name = fullfile(filename, ls(i).name); +end +lst = {ls.name}; +hdr = cell(size(lst)); +sel = zeros(size(lst)); +for i=1:length(lst) + % read the header of each individual file + try + thishdr = ft_read_header(lst{i}); + if isstruct(thishdr) + thishdr.filename = lst{i}; + end + catch + thishdr = []; + warning(lasterr); + fprintf('while reading %s\n\n', lst{i}); + end + if ~isempty(thishdr) + hdr{i} = thishdr; + sel(i) = true; + else + sel(i) = false; + end +end +sel = logical(sel(:)); +hdr = hdr(sel); +tmp = {}; +for i=1:length(hdr) + if isstruct(hdr{i}) + tmp = cat(1, tmp, hdr(i)); + elseif iscell(hdr{i}) + tmp = cat(1, tmp, hdr{i}{:}); + end +end +hdr = tmp; + diff --git a/external/fieldtrip/fileio/ft_read_headshape.m b/external/fieldtrip/fileio/ft_read_headshape.m new file mode 100644 index 0000000..fceadbe --- /dev/null +++ b/external/fieldtrip/fileio/ft_read_headshape.m @@ -0,0 +1,301 @@ +function [shape] = ft_read_headshape(filename, varargin) + +% FT_READ_HEADSHAPE reads the fiducials and/or the measured headshape +% from a variety of files (like CTF and Polhemus). The headshape and +% fiducials can for example be used for coregistration. +% +% Use as +% [shape] = ft_read_headshape(filename) +% +% See also FT_READ_VOL, FT_READ_SENS + +% Copyright (C) 2008-2010 Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_read_headshape.m 1295 2010-06-29 14:19:37Z roboos $ + +% test whether the file exists +if ~exist(filename) + error(sprintf('file ''%s'' does not exist', filename)); +end + +% get the options +fileformat = keyval('fileformat', varargin); +coordinates = keyval('coordinates', varargin); if isempty(coordinates), coordinates = 'head'; end + +if isempty(fileformat) + fileformat = ft_filetype(filename); +end + +% start with an empty structure +shape = []; +shape.pnt = []; +shape.fid.pnt = []; +shape.fid.label = {}; + +switch fileformat + case {'ctf_ds', 'ctf_hc', 'ctf_meg4', 'ctf_res4', 'ctf_old'} + [p, f, x] = fileparts(filename); + + if strcmp(fileformat, 'ctf_old') + fileformat = ft_filetype(filename); + end + + if strcmp(fileformat, 'ctf_ds') + filename = fullfile(p, [f x], [f '.hc']); + elseif strcmp(fileformat, 'ctf_meg4') + filename = fullfile(p, [f '.hc']); + elseif strcmp(fileformat, 'ctf_res4') + filename = fullfile(p, [f '.hc']); + end + + orig = read_ctf_hc(filename); + switch coordinates + case 'head' + shape.fid.pnt = cell2mat(struct2cell(orig.head)); + case 'dewar' + shape.fid.pnt = cell2mat(struct2cell(orig.dewar)); + otherwise + error('incorrect coordinates specified'); + end + shape.fid.label = fieldnames(orig.head); + + case 'ctf_shape' + orig = read_ctf_shape(filename); + shape.pnt = orig.pnt; + shape.fid.label = {'NASION', 'LEFT_EAR', 'RIGHT_EAR'}; + for i = 1:numel(shape.fid.label) + shape.fid.pnt = cat(1, shape.fid.pnt, ... + getfield(orig.MRI_Info, shape.fid.label{i})); + end + + case {'4d_xyz', '4d_m4d', '4d_hs', '4d', '4d_pdf'} + [p, f, x] = fileparts(filename); + if ~strcmp(fileformat, '4d_hs') + filename = fullfile(p, 'hs_file'); + end + [shape.pnt, fid] = read_bti_hs(filename); + + % I'm making some assumptions here + % which I'm not sure will work on all 4D systems + + %fid = fid(1:3, :); + + [junk, NZ] = max(fid(1:3,1)); + [junk, L] = max(fid(1:3,2)); + [junk, R] = min(fid(1:3,2)); + rest = setdiff(1:size(fid,1),[NZ L R]); + + shape.fid.pnt = fid([NZ L R rest], :); + shape.fid.label = {'NZ', 'L', 'R'}; + if ~isempty(rest), + for i = 4:size(fid,1) + shape.fid.label{i} = ['fiducial' num2str(i)]; + %in a 5 coil configuration this corresponds with Cz and Inion + end + end + + case 'itab_asc' + shape = read_itab_asc(filename); + + case 'neuromag_mex' + [co,ki,nu] = hpipoints(filename); + fid = co(:,find(ki==1))'; + + [junk, NZ] = max(fid(:,2)); + [junk, L] = min(fid(:,1)); + [junk, R] = max(fid(:,1)); + + shape.fid.pnt = fid([NZ L R], :); + shape.fid.label = {'NZ', 'L', 'R'}; + + case {'neuromag_mne', 'neuromag_fif'} + hdr = ft_read_header(filename,'headerformat','neuromag_mne'); + nFid = size(hdr.orig.dig,2); %work out number of fiducials + switch coordinates + case 'head' % digitiser points should be stored in head coordinates by default + + fidN=1; + pntN=1; + for i=1:nFid %loop over fiducials + %check this point is in head coordinates: + if hdr.orig.dig(i).coord_frame~=4 % 4 is MNE constant for head coordinates + error(['Digitiser point (' num2str(i) ') not stored in head coordinates!']); + end + + + switch hdr.orig.dig(i).kind % constants defined in MNE - see p.215 of MNE manual + case 1 % Cardinal point (nasion, LPA or RPA) + %get location of fiducial: + shape.fid.pnt(fidN,1:3) = hdr.orig.dig(i).r*100; %multiply by 100 to convert to cm + switch hdr.orig.dig(i).ident + case 1 % LPA + shape.fid.label{fidN} = 'LPA'; + case 2 % nasion + shape.fid.label{fidN} = 'Nasion'; + case 3 % RPA + shape.fid.label{fidN} = 'RPA'; + otherwise + error('Unidentified cardinal point in file!'); + end + fidN = fidN + 1; + + case 2 % HPI coil + shape.pnt(pntN,1:3) = hdr.orig.dig(i).r*100; + pntN = pntN + 1; + case 3 % EEG electrode location (or ECG) + shape.pnt(pntN,1:3) = hdr.orig.dig(i).r*100; + pntN = pntN + 1; + case 4 % Additional head point + shape.pnt(pntN,1:3) = hdr.orig.dig(i).r*100; + pntN = pntN + 1; + otherwise + warning('Unidentified digitiser point in file!'); + end + + end + shape.fid.label=shape.fid.label'; + + case 'dewar' + error('Dewar coordinates not supported for headshape yet (MNE toolbox)'); + otherwise + error('Incorrect coordinates specified'); + end + case {'yokogawa_mrk', 'yokogawa_ave', 'yokogawa_con', 'yokogawa_raw' } + + hdr = read_yokogawa_header(filename); + marker = hdr.orig.matching_info.marker; + + % markers 1-3 identical to zero: try *.mrk file + if ~any([marker(:).meg_pos]) + [p, f, x] = fileparts(filename); + filename = fullfile(p, [f '.mrk']); + if exist(filename, 'file') + hdr = read_yokogawa_header(filename); + marker = hdr.orig.matching_info.marker; + end + end + + % non zero markers 1-3 + if any([marker(:).meg_pos]) + shape.fid.pnt = cat(1, marker(1:5).meg_pos); + sw_ind = [3 1 2]; + shape.fid.pnt(1:3,:)= shape.fid.pnt(sw_ind, :); + shape.fid.label = {'nas'; 'lpa'; 'rpa'; 'Marker4'; 'Marker5'}; + else + error('no coil information found in Yokogawa file'); + end + + % Convert to the units of the grad. + shape = ft_convert_units(shape, 'cm'); + case 'yokogawa_coregis' + + in_str = textread(filename, '%s'); + nr_items = size(in_str,1); + ind = 1; + coil_ind = 1; + while ind < nr_items + if strcmp(in_str{ind},'MEG:x=') + shape.fid.pnt = [shape.fid.pnt; str2num(strtok(in_str{ind+1},[',','['])) ... + str2num(strtok(in_str{ind+3},[',','['])) str2num(strtok(in_str{ind+5},[',','[']))]; + shape.fid.label = [shape.fid.label ; ['Marker',num2str(coil_ind)]]; + coil_ind = coil_ind + 1; + ind = ind + 6; + else + ind = ind +1; + end + end + if size(shape.fid.label,1) ~= 5 + error('Wrong number of coils'); + end + + sw_ind = [3 1 2]; + + shape.fid.pnt(1:3,:)= shape.fid.pnt(sw_ind, :); + shape.fid.label(1:3)= {'nas', 'lpa', 'rpa'}; + + case 'polhemus_fil' + [shape.fid.pnt, shape.pnt, shape.fid.label] = read_polhemus_fil(filename, 0); + + case 'spmeeg_mat' + tmp = load(filename); + if isfield(tmp.D, 'fiducials') && ~isempty(tmp.D.fiducials) + shape = tmp.D.fiducials; + else + error('no headshape found in SPM EEG file'); + end + + case 'matlab' + tmp = load(filename); + if isfield(tmp, 'shape') + shape = tmp.shape; + elseif isfield(tmp, 'elec') + shape.fid.pnt = tmp.elec.pnt; + shape.fid.label = tmp.elec.label; + else + error('no headshape found in Matlab file'); + end + + otherwise + + success = 0; + if ~success + % try reading it as electrode positions + % and treat those as fiducials + try + elec = ft_read_sens(filename); + if ~ft_senstype(elec, 'eeg') + error('headshape information can not be read from MEG gradiometer file'); + else + shape.fid.pnt = elec.pnt; + shape.fid.label = elec.label; + success = 1; + end + end + end + + if ~success + % try reading it as volume conductor + % and treat the skin surface as headshape + try + vol = ft_read_vol(filename); + if ~ft_voltype(vol, 'bem') + error('skin surface can only be extracted from boundary element model'); + else + if ~isfield(vol, 'skin') + vol.skin = find_outermost_boundary(vol.bnd); + end + shape.pnt = vol.bnd(vol.skin).pnt; + shape.tri = vol.bnd(vol.skin).tri; % also return the triangulation + success = 1; + end + end + end + + if ~success + error('unknown fileformat for head shape information'); + end +end + +if issubfield(shape, 'fid.label') + % ensure that it is a column + shape.fid.label = shape.fid.label(:); +end + +% this will add the units to the head shape +shape = ft_convert_units(shape); diff --git a/external/fieldtrip/fileio/ft_read_mri.m b/external/fieldtrip/fileio/ft_read_mri.m new file mode 100644 index 0000000..733ab58 --- /dev/null +++ b/external/fieldtrip/fileio/ft_read_mri.m @@ -0,0 +1,254 @@ +function [mri] = ft_read_mri(filename) + +% FT_READ_MRI reads anatomical and functional MRI data from different +% file formats. The output data is structured in such a way that it is +% comparable to a FieldTrip source reconstruction. +% +% Use as +% [mri] = ft_read_mri(filename) +% +% The output MRI may have a homogenous transformation matrix that converts +% the coordinates of each voxel (in xgrid/ygrid/zgrid) into head +% coordinates. +% +% See also FT_READ_DATA, FT_READ_HEADER, FT_READ_EVENT + +% Copyright (C) 2008-2010 Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_read_mri.m 1108 2010-05-20 07:43:30Z jansch $ + +% test for the presence of some external functions from other toolboxes +hasmri = hastoolbox('mri'); % from Darren Weber, see http://eeg.sourceforge.net/ +hasspm2 = hastoolbox('spm2'); % see http://www.fil.ion.ucl.ac.uk/spm/ +hasspm5 = hastoolbox('spm5'); % see http://www.fil.ion.ucl.ac.uk/spm/ +hasspm8 = hastoolbox('spm8'); % see http://www.fil.ion.ucl.ac.uk/spm/ +hasspm = (hasspm2 || hasspm5 || hasspm8); +hasafni = hastoolbox('afni'); % see http://afni.nimh.nih.gov/ + +% test whether the file exists +if ~exist(filename) + error(sprintf('file ''%s'' does not exist', filename)); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +if ft_filetype(filename, 'ctf_mri') + [img, hdr] = read_ctf_mri(filename); + transform = hdr.transformMRI2Head; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +elseif ft_filetype(filename, 'ctf_mri4') + [img, hdr] = read_ctf_mri4(filename); + transform = hdr.transformMRI2Head; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +elseif ft_filetype(filename, 'ctf_svl') + [img, hdr] = read_ctf_svl(filename); + transform = hdr.transform; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +elseif ft_filetype(filename, 'asa_mri') + [img, seg, hdr] = read_asa_mri(filename); + transform = hdr.transformMRI2Head; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +elseif ft_filetype(filename, 'minc') + if ~(hasspm2 || hasspm5) + error('the SPM2 or SPM5 toolbox is required to read *.mnc files'); + end + % use the functions from SPM + hdr = spm_vol_minc(filename); + img = spm_read_vols(hdr); + transform = hdr.mat; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +elseif ft_filetype(filename, 'nifti') + if ~(hasspm5 || hasspm8) + error('the SPM5 or SPM8 toolbox is required to read *.nii files'); + end + % use the functions from SPM + hdr = spm_vol_nifti(filename); + img = spm_read_vols(hdr); + transform = hdr.mat; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +elseif (ft_filetype(filename, 'analyze_img') || ft_filetype(filename, 'analyze_hdr')) && hasspm + % use the image file instead of the header + filename((end-2):end) = 'img'; + % use the functions from SPM to read the Analyze MRI + hdr = spm_vol(filename); + img = spm_read_vols(hdr); + transform = hdr.mat; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +elseif (ft_filetype(filename, 'analyze_hdr') || ft_filetype(filename, 'analyze_img')) && hasmri + % use the functions from Darren Weber's mri_toolbox to read the Analyze MRI + avw = avw_img_read(filename, 0); % returned volume is LAS* + img = avw.img; + hdr = avw.hdr; + % The default Analyze orientation is axial unflipped (LAS*), which means + % that the resulting volume is according to the radiological convention. + % Most other fMRI and EEG/MEG software (except Mayo/Analyze) uses + % neurological conventions and a right-handed coordinate system, hence + % the first axis of the 3D volume (right-left) should be flipped to make + % the coordinate system comparable to SPM + warning('flipping 1st dimension (L-R) to obtain volume in neurological convention'); + img = flipdim(img, 1); + % FIXME: here I should also implement a homogenous transformation matrix, + % using the voxel dimensions that are specified in hdr.dime.pixdim + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +elseif (ft_filetype(filename, 'afni_brik') || ft_filetype(filename, 'afni_head')) && hasafni + [err, img, hdr, ErrMessage] = BrikLoad(filename); + if err + error('could not read AFNI file'); + end + + % FIXME: this should be checked, but I only have a single BRIK file + % construct the homogenous transformation matrix that defines the axes + warning('homogenous transformation might be incorrect for AFNI file'); + transform = eye(4); + transform(1:3,4) = hdr.ORIGIN(:); + transform(1,1) = hdr.DELTA(1); + transform(2,2) = hdr.DELTA(2); + transform(3,3) = hdr.DELTA(3); + + % FIXME: I am not sure about the "RAI" image orientation + img = flipdim(img,1); + img = flipdim(img,2); + dim = size(img); + transform(1,4) = -dim(1) - transform(1,4); + transform(2,4) = -dim(2) - transform(2,4); + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +elseif ft_filetype(filename, 'neuromag_fif') && hastoolbox('mne') + % use the mne functions to read the Neuromag MRI + hdr = fiff_read_mri(filename); + img = cat(3, hdr.slices.data); + hdr.slices = rmfield(hdr.slices, 'data'); % remove the image data to save memory + % hmm, which transformation matrix should I use? + if isfield(hdr, 'voxel_trans') && issubfield(hdr.voxel_trans, 'trans') + transform = hdr.voxel_trans.trans; + elseif isfield(hdr, 'trans') && issubfield(hdr.trans, 'trans') + transform = hdr.trans.trans; + end + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +elseif ft_filetype(filename, 'neuromag_fif') && hastoolbox('meg_pd') + % use the meg_pd functions to read the Neuromag MRI + [img,coords] = loadmri(filename); + dev = loadtrans(filename,'MRI','HEAD'); + transform = dev*coords; + hdr.coords = coords; + hdr.dev = dev; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +elseif ft_filetype(filename, 'neuromag_fif') + error('reading MRI data from a fif file requires either the MNE toolbox or the meg_pd toolbox to be installed'); + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +elseif ft_filetype(filename, 'dicom') + % this uses the Image processing toolbox + % the DICOM file probably represents a stack of slices, possibly even multiple volumes + orig = dicominfo(filename); + dim(1) = orig.Rows; + dim(2) = orig.Columns; + + [p, f] = fileparts(filename); + + % this works for the Siemens scanners at the FCDC + tok = tokenize(f, '.'); + for i=5:length(tok) + tok{i} = '*'; + end + filename = sprintf('%s.', tok{:}); % reconstruct the filename with wildcards and '.' between the segments + filename = filename(1:end-1); % remove the last '.' + dirlist = dir(fullfile(p, filename)); + dirlist = {dirlist.name}; + + if length(dirlist)==1 + % try something else to get a list of all the slices + dirlist = dir(fullfile(p, '*')); + dirlist = {dirlist(~[dirlist.isdir]).name}; + end + + keep = false(1, length(dirlist)); + for i=1:length(dirlist) + filename = char(fullfile(p, dirlist{i})); + if ~ft_filetype(filename, 'dicom') + keep(i) = false; + fprintf('skipping ''%s'' because of incorrect filetype\n', filename); + end + % read the header information + info = dicominfo(filename); + if info.SeriesNumber~=orig.SeriesNumber + keep(i) = false; + fprintf('skipping ''%s'' because of different SeriesNumber\n', filename); + else + keep(i) = true; + hdr(i) = info; + end + end + % remove the files that were skipped + hdr = hdr(keep); + dirlist = dirlist(keep); + + % pre-allocate enough space for the subsequent slices + dim(3) = length(dirlist); + img = zeros(dim(1), dim(2), dim(3)); + for i=1:length(dirlist) + filename = char(fullfile(p, dirlist{i})); + fprintf('reading image data from ''%s''\n', filename); + img(:,:,i) = dicomread(hdr(i)); + end + + % reorder the slices + [z, indx] = sort(cell2mat({hdr.SliceLocation})); + hdr = hdr(indx); + img = img(:,:,indx); + + try + % construct a homgenous transformation matrix that performs the scaling from voxels to mm + dx = hdr(1).PixelSpacing(1); + dy = hdr(1).PixelSpacing(2); + dz = hdr(2).SliceLocation - hdr(1).SliceLocation; + transform = eye(4); + transform(1,1) = dx; + transform(2,2) = dy; + transform(3,3) = dz; + end + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +else + error(sprintf('unrecognized filetype of ''%s''', filename)); +end + +% set up the axes of the volume in voxel coordinates +nx = size(img,1); +ny = size(img,2); +nz = size(img,3); +mri.dim = [nx ny nz]; +% store the anatomical data +mri.anatomy = img; +% store the header with all fileformat specific details +mri.hdr = hdr; +try + % if present, store the homogenous transformation matrix + mri.transform = transform; +end + diff --git a/external/fieldtrip/fileio/ft_read_sens.m b/external/fieldtrip/fileio/ft_read_sens.m new file mode 100644 index 0000000..6817e85 --- /dev/null +++ b/external/fieldtrip/fileio/ft_read_sens.m @@ -0,0 +1,242 @@ +function [sens] = ft_read_sens(filename, varargin) + +% FT_READ_SENS read sensor positions from various manufacturer specific files. +% Currently supported are ASA, BESA, Polhemus and Matlab for EEG +% electrodes and CTF and Neuromag for MEG gradiometers. +% +% Use as +% grad = ft_read_sens(filename, ...) % for gradiometers +% elec = ft_read_sens(filename, ...) % for electrodes +% +% Additional options should be specified in key-value pairs and can be +% 'fileformat' string +% +% An electrode definition contain the following fields +% elec.pnt Nx3 matrix with carthesian (x,y,z) coordinates of each electrodes +% elec.label cell-array of length N with the label of each electrode +% +% A gradiometer definition generally consists of multiple coils per +% channel, e.g.two coils for a 1st order gradiometer in which the +% orientation of the coils is opposite. Each coil is described +% separately and a large "tra" matrix (can be sparse) has to be +% given that defines how the forward computed field is combined over +% the coils to generate the output of each channel. The gradiometer +% definition constsis of the following fields +% grad.pnt Mx3 matrix with the position of each coil +% grad.ori Mx3 matrix with the orientation of each coil +% grad.tra NxM matrix with the weight of each coil into each channel +% grad.label cell-array of length N with the label of each of the channels +% +% See also FT_TRANSFORM_SENS, FT_PREPARE_VOL_SENS, FT_COMPUTE_LEADFIELD + +% Copyright (C) 2005-2010 Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_read_sens.m 1059 2010-05-09 11:32:55Z roboos $ + +% test whether the file exists +if ~exist(filename) + error(sprintf('file ''%s'' does not exist', filename)); +end + +% get the options +fileformat = keyval('fileformat', varargin); + +% determine the filetype +if isempty(fileformat) + fileformat = ft_filetype(filename); +end + +switch fileformat + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % read the content from various files that contain EEG electrode positions + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + case 'asa_elc' + sens = read_asa_elc(filename); + + case 'polhemus_pos' + sens = read_brainvision_pos(filename); + + case 'besa_elp' + % the code below does not yet work + error('unknown fileformat for electrodes or gradiometers'); + + fid = fopen(filename); + % the ascii file contains: type, label, angle, angle + tmp = textscan(fid, '%s%s%f%f'); + fclose(fid); + + sel = strcmpi(tmp{1}, 'EEG'); % type can be EEG or POS + sens.label = tmp{2}(sel); + az = tmp{3}(sel) * pi/180; + el = tmp{4}(sel) * pi/180; + r = ones(size(el)); + [x, y, z] = sph2cart(az, el, r); + sens.pnt = [x y z]; + + case 'besa_pos' + tmp = importdata(filename); + if ~isnumeric(tmp) + error('unexpected file format for fileformat=besa_pos') + end + [nchan,nrow] = size(tmp); + if nrow==3 + sens.pnt = tmp; + elseif nrow==9 + pnt1 = tmp(:,1:3); % bottom coil + pnt2 = tmp(:,4:6); % top coil + ori = tmp(:,7:9); % orientation of bottom coil + sens.pnt = [pnt1; pnt2]; + sens.ori = [ori; ori]; + sens.tra = [eye(nchan) -eye(nchan)]; + else + error('unexpected file format for fileformat=besa_pos') + end + [p, f, x] = fileparts(filename); + elpfile = fullfile(p, [f '.elp']); + elafile = fullfile(p, [f '.ela']); + if exist(elpfile, 'file') + warning(sprintf('reading channel labels from %s', elpfile)); + % read the channel names from the accompanying ELP file + lbl = importdata(elpfile); + sens.label = strrep(lbl.textdata(:,2) ,'''', ''); + elseif exist(elafile, 'file') + warning(sprintf('reading channel labels from %s', elafile)); + % read the channel names from the accompanying ELA file + lbl = importdata(elafile); + lbl = strrep(lbl, 'MEG ', ''); % remove the channel type + lbl = strrep(lbl, 'EEG ', ''); % remove the channel type + sens.label = lbl; + else + % the file does not have channel labels in it + warning('creating fake channel names for besa_pos'); + for i=1:nchan + sens.label{i} = sprintf('%03d', i); + end + end + + case 'besa_sfp' + fid = fopen(filename); + tmp = textscan(fid, ' %[^ \t]%n%n%n'); + fclose(fid); + sens.label = tmp{1}; + sens.pnt = [tmp{2:4}]; + + case 'itab_raw' + hastoolbox('fileio'); + hdr = ft_read_header(filename); + sens = hdr.grad; + + case 'neuromag_mne' + hastoolbox('fileio'); + hdr = ft_read_header(filename,'headerformat','neuromag_mne'); + sens = hdr.elec; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % gradiometer information is always stored in the header of the MEG dataset + % hence uses the standard fieldtrip/fileio read_header function + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + case {'ctf_ds', 'ctf_res4', 'neuromag_fif', '4d', '4d_pdf', '4d_m4d', '4d_xyz', 'yokogawa_ave', 'yokogawa_con', 'yokogawa_raw'} + % check the availability of the required low-level toolbox + % this is required because the read_sens function is also on itself included in the forwinv toolbox + hastoolbox('fileio'); + hdr = ft_read_header(filename, 'headerformat', fileformat); + sens = hdr.grad; + + + case 'neuromag_mne_grad' + hastoolbox('fileio'); + hdr = ft_read_header(filename,'headerformat','neuromag_mne'); + sens = hdr.grad; + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % This is for EEG formats where electrode positions can be stored with the data + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + case {'spmeeg_mat', 'eeglab_set'} + % check the availability of the required low-level toolbox + % this is required because the read_sens function is also on itself included in the forwinv toolbox + hastoolbox('fileio'); + hdr = ft_read_header(filename); + + if isfield(hdr, 'grad') + sens = hdr.grad; + elseif isfield(hdr, 'elec') + sens = hdr.elec; + else + error('no electrodes or gradiometers found in the file') + end + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % these are created at the FIL in London with a polhemus tracker + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + case 'polhemus_fil' + [sens.fid, sens.pnt] = read_polhemus_fil(filename, 0); + + % the file does not have channel labels in it + warning('no channel names in polhemus file, using numbers instead'); + for i=1:size(sens.pnt, 1) + sens.label{i} = sprintf('%03d', i); + end + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % matlab files can contain either electrodes or gradiometers + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + case 'matlab' + matfile = filename; % this solves a problem with the matlab compiler v3 + warning('off', 'MATLAB:load:variableNotFound'); + tmp = load(matfile, 'elec', 'grad', 'sens', 'elc'); + warning('on', 'MATLAB:load:variableNotFound'); + if isfield(tmp, 'grad') + sens = getfield(tmp, 'grad'); + elseif isfield(tmp, 'elec') + sens = getfield(tmp, 'elec'); + elseif isfield(tmp, 'sens') + sens = getfield(tmp, 'sens'); + elseif isfield(tmp, 'elc') + sens = getfield(tmp, 'elc'); + else + error('no electrodes or gradiometers found in Matlab file'); + end + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % these are created by a Zebris tracker, at CRC in Liege at least. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + case 'zebris_sfp' + [sens.fid, sens.pnt, sens.fid_label, sens.label] = read_zebris(filename, 0); + + otherwise + error('unknown fileformat for electrodes or gradiometers'); +end + +if ft_senstype(sens, 'eeg') + % only keep positions and labels in case of EEG electrodes + dum = sens; + sens = []; + sens.pnt = dum.pnt; + sens.label = dum.label; +end + +% this will add the units to the sensor array +sens = ft_convert_units(sens); diff --git a/external/fieldtrip/fileio/ft_read_spike.m b/external/fieldtrip/fileio/ft_read_spike.m new file mode 100644 index 0000000..69e3d9b --- /dev/null +++ b/external/fieldtrip/fileio/ft_read_spike.m @@ -0,0 +1,203 @@ +function [spike] = ft_read_spike(filename, varargin); + +% READ_SPIKE reads spike timestamps and waveforms from various data +% formats. +% +% Use as +% [spike] = ft_read_spike(filename, ...) +% +% Additional options should be specified in key-value pairs and can be +% 'spikeformat' +% +% The output spike structure contains +% spike.label = 1xNchans cell-array, with channel labels +% spike.waveform = 1xNchans cell-array, each element contains a matrix (Nsamples X Nspikes) +% spike.timestamp = 1xNchans cell-array, each element contains a vector (1 X Nspikes) +% spike.unit = 1xNchans cell-array, each element contains a vector (1 X Nspikes) +% +% See also FT_READ_HEADER, FT_READ_DATA, FT_READ_EVENT + +% Copyright (C) 2007-2010 Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_read_spike.m 944 2010-04-21 16:08:12Z roboos $ + +% get the options +spikeformat = keyval('spikeformat', varargin); + +% determine the filetype +if isempty(spikeformat) + spikeformat = ft_filetype(filename); +end + +switch spikeformat + case {'neuralynx_ncs' 'plexon_ddt'} + % these files only contain continuous data + error('file does not contain spike timestamps or waveforms'); + + case 'matlab' + % plain matlab file with a single variable in it + load(filename, 'spike'); + + case 'mclust_t' + fp = fopen(filename, 'rb', 'ieee-le'); + H = ReadHeader(fp); + fclose(fp); + % read only from one file + S = LoadSpikes({filename}); + spike.hdr = H(:); + spike.timestamp = S; + [p, f, x] = fileparts(filename); + spike.label = {f}; % use the filename as label for the spike channel + spike.waveform = {}; % this is unknown + spike.unit = {}; % this is unknown + + case 'neuralynx_nse' + % single channel file, read all records + nse = read_neuralynx_nse(filename); + if isfield(nse.hdr, 'NLX_Base_Class_Name') + spike.label = {nse.hdr.NLX_Base_Class_Name}; + else + spike.label = {nse.hdr.AcqEntName}; + end + spike.timestamp = {nse.TimeStamp}; + spike.waveform = {nse.dat}; + spike.unit = {nse.CellNumber}; + spike.hdr = nse.hdr; + + case 'neuralynx_nst' + % single channel stereotrode file, read all records + nst = read_neuralynx_nst(filename, 1, inf); + if isfield(nst.hdr, 'NLX_Base_Class_Name') + spike.label = {nst.hdr.NLX_Base_Class_Name}; + else + spike.label = {nst.hdr.AcqEntName}; + end + spike.timestamp = {nst.TimeStamp}; + spike.waveform = {nst.dat}; + spike.unit = {nst.CellNumber}; + spike.hdr = nst.hdr; + + case 'neuralynx_ntt' + % single channel stereotrode file, read all records + ntt = read_neuralynx_ntt(filename); + if isfield(ntt.hdr, 'NLX_Base_Class_Name') + spike.label = {ntt.hdr.NLX_Base_Class_Name}; + else + spike.label = {ntt.hdr.AcqEntName}; + end + spike.timestamp = {ntt.TimeStamp}; + spike.waveform = {ntt.dat}; + spike.unit = {ntt.CellNumber}; + spike.hdr = ntt.hdr; + + case 'neuralynx_nts' + % single channel file, read all records + nts = read_neuralynx_nts(filename); + if isfield(nte.hdr, 'NLX_Base_Class_Name') + spike.label = {nts.hdr.NLX_Base_Class_Name}; + else + spike.label = {nts.hdr.AcqEntName}; + end + spike.timestamp = {nts.TimeStamp(:)'}; + spike.waveform = {zeros(0,length(nts.TimeStamp))}; % does not contain waveforms + spike.unit = {zeros(0,length(nts.TimeStamp))}; % does not contain units + spike.hdr = nts.hdr; + + case 'plexon_nex' + % a single file can contain multiple channels of different types + hdr = read_plexon_nex(filename); + typ = [hdr.VarHeader.Type]; + chan = 0; + + spike.label = {}; + spike.waveform = {}; + spike.unit = {}; + spike.timestamp = {}; + + for i=1:length(typ) + if typ(i)==0 + % neurons, only timestamps + nex = read_plexon_nex(filename, 'channel', i); + nspike = length(nex.ts); + chan = chan + 1; + spike.label{chan} = deblank(hdr.VarHeader(i).Name); + spike.waveform{chan} = zeros(0, nspike); + spike.unit{chan} = nan*ones(1,nspike); + spike.timestamp{chan} = nex.ts; + elseif typ(i)==3 + % neurons, timestamps and waveforms + nex = read_plexon_nex(filename, 'channel', i); + chan = chan + 1; + nspike = length(nex.ts); + spike.label{chan} = deblank(hdr.VarHeader(i).Name); + spike.waveform{chan} = nex.dat; + spike.unit{chan} = nan*ones(1,nspike); + spike.timestamp{chan} = nex.ts; + end + end + spike.hdr = hdr; + + case 'plexon_plx' + % read the header information + hdr = read_plexon_plx(filename); + nchan = length(hdr.ChannelHeader); + typ = [hdr.DataBlockHeader.Type]; + unit = [hdr.DataBlockHeader.Unit]; + chan = [hdr.DataBlockHeader.Channel]; + + for i=1:nchan + % select the data blocks that contain spike waveforms and that belong to this channel + sel = (typ==1 & chan==hdr.ChannelHeader(i).Channel); + + if any(sel) + % get the timestamps that correspond with this spike channel + tsl = [hdr.DataBlockHeader(sel).TimeStamp]; + tsh = [hdr.DataBlockHeader(sel).UpperByteOf5ByteTimestamp]; + % convert the 16 bit high timestamp into a 32 bit integer + ts = timestamp_plexon(tsl, tsh); + spike.timestamp{i} = ts; + spike.unit{i} = unit(sel); + else + % this spike channel is empty + spike.timestamp{i} = []; + spike.unit{i} = []; + end + end + for i=1:nchan + spike.label{i} = deblank(hdr.ChannelHeader(i).Name); + spike.waveform{i} = read_plexon_plx(filename, 'ChannelIndex', i, 'header', hdr); + end + spike.hdr = hdr; + + case 'neuroshare' % NOTE: still under development + % check that the required neuroshare toolbox is available + hastoolbox('neuroshare', 1); + + tmp = read_neuroshare(filename, 'readspike', 'yes'); + spike.label = {tmp.hdr.entityinfo(tmp.list.segment).EntityLabel}; + for i=1:length(spike.label) + spike.waveform{i} = tmp.spikew.data(:,:,i); + spike.timestamp{i} = tmp.spikew.timestamp(:,i)'; + spike.unit{i} = tmp.spikew.unitID(:,i)'; + end + + otherwise + error('unsupported data format'); +end + diff --git a/external/fieldtrip/fileio/ft_read_vol.m b/external/fieldtrip/fileio/ft_read_vol.m new file mode 100644 index 0000000..3255cbc --- /dev/null +++ b/external/fieldtrip/fileio/ft_read_vol.m @@ -0,0 +1,88 @@ +function [vol] = ft_read_vol(filename, varargin) + +% READ_VOL reads a volume conduction model from various manufacturer +% specific files. Currently supported are ASA, CTF, Neuromag, MBFYS +% and Matlab. +% +% Use as +% vol = ft_read_vol(filename, ...) +% +% Additional options should be specified in key-value pairs and can be +% 'fileformat' string +% +% The volume conduction model is represented as a structure, and its +% contents depend on the type of model. +% +% See also FT_TRANSFORM_VOL, FT_PREPARE_VOL_SENS, FT_COMPUTE_LEADFIELD + +% Copyright (C) 2008-2010 Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_read_vol.m 944 2010-04-21 16:08:12Z roboos $ + +% test whether the file exists +if ~exist(filename) + error(sprintf('file ''%s'' does not exist', filename)); +end + +% get the options +fileformat = keyval('fileformat', varargin); + +% determine the filetype +if isempty(fileformat) + fileformat = ft_filetype(filename); +end + +switch fileformat + case 'matlab' + matfile = filename; % this solves a problem with the matlab compiler v3 + warning('off', 'MATLAB:load:variableNotFound'); + tmp = load(matfile, 'vol'); + warning('on', 'MATLAB:load:variableNotFound'); + vol = getfield(tmp, 'vol'); + + case 'ctf_hdm' + vol = read_ctf_hdm(filename); + + case 'asa_vol' + vol = read_asa_vol(filename); + vol.type = 'asa'; + + case 'mbfys_ama' + ama = loadama(filename); + vol = ama2vol(ama); + + case 'neuromag_fif' + % do not read the volume into Matlab, but use external Neuromag toolbox + vol.type = 'neuromag'; + vol.filename = filename; + vol.chansel = []; % this is defined later based on the channels present in the data + % initialize the Neuromag toolbox, this requires a gradfile and hdmfile + fprintf('using Neuromag volume conductor from %s\n', filename); + fprintf('using Neuromag gradiometer definition from %s\n', cfg.gradfile); + megmodel('head', cfg.gradfile, filename); + % read the triangulated boundary from the neuromag BEM model + [vol.bnd.pnt, vol.bnd.tri, vol.bnd.nrm] = loadtri(vol.filename); + vol.bnd.pnt = vol.bnd.pnt*100; % convert to cm + + otherwise + error('unknown fileformat for volume conductor model'); +end + +% this will add the units to the volume conductor model +vol = ft_convert_units(vol); diff --git a/external/fieldtrip/fileio/ft_write_data.m b/external/fieldtrip/fileio/ft_write_data.m new file mode 100644 index 0000000..e515994 --- /dev/null +++ b/external/fieldtrip/fileio/ft_write_data.m @@ -0,0 +1,604 @@ +function ft_write_data(filename, dat, varargin) + +% FT_WRITE_DATA exports electrophysiological data to a file. The input data is +% assumed to be scaled in microVolt. +% +% Use as +% ft_write_data(filename, dat, ...) +% +% The specified filename can already contain the filename extention, +% but that is not required since it will be added automatically. +% +% Additional options should be specified in key-value pairs and can be +% 'header' header structure, see FT_READ_HEADER +% 'dataformat' string, see below +% 'append' boolean, not supported for all formats +% 'chanindx' 1xN array +% +% The supported dataformats are +% brainvision_eeg +% matlab +% riff_wave +% fcdc_matbin +% fcdc_mysql +% fcdc_buffer +% plexon_nex +% neuralynx_ncs +% neuralynx_sdma +% +% See also FT_READ_HEADER, FT_READ_DATA, FT_READ_EVENT, FT_WRITE_EVENT + +% Copyright (C) 2007-2010 Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_write_data.m 1371 2010-07-07 15:20:50Z stekla $ + +global data_queue % for fcdc_global +global header_queue % for fcdc_global +global db_blob % for fcdc_mysql +if isempty(db_blob) + db_blob = 0; +end + +% get the options +dataformat = keyval('dataformat', varargin); if isempty(dataformat), dataformat = ft_filetype(filename); end +append = keyval('append', varargin); if isempty(append), append = false; end +nbits = keyval('nbits', varargin); % for riff_wave +chanindx = keyval('chanindx', varargin); +hdr = keyval('header', varargin); + +% determine the data size +[nchans, nsamples] = size(dat); + +switch dataformat + + case 'empty' + [numC, numS] = size(dat); + fprintf(1,'Pretending to write %i samples from %i channes...\n',numS,numC); + % Insert a small delay to make this more realitic for testing purposes + % The time for writing to an actual location will differ and depend on + % the amount of data + pause(0.001); + + case 'fcdc_global' + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % store it in a global variable, this is only for debugging + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + if ~isempty(hdr) + header_queue = hdr; + end + if isempty(data_queue) || ~append + data_queue = dat; + else + data_queue = cat(2, data_queue, dat); + end + + case 'fcdc_buffer' + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % network transparent buffer + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + if ~isempty(chanindx) + % assume that the header corresponds to the original multichannel + % file and that the data represents a subset of channels + hdr.label = hdr.label(chanindx); + hdr.nChans = length(chanindx); + end + + [host, port] = filetype_check_uri(filename); + + type = { + 'char' + 'uint8' + 'uint16' + 'uint32' + 'uint64' + 'int8' + 'int16' + 'int32' + 'int64' + 'single' + 'double' + }; + + wordsize = { + 1 % 'char' + 1 % 'uint8' + 2 % 'uint16' + 4 % 'uint32' + 8 % 'uint64' + 1 % 'int8' + 2 % 'int16' + 4 % 'int32' + 8 % 'int64' + 4 % 'single' + 8 % 'double' + }; + + % this should only be done the first time + if ~append && ~isempty(hdr) + % reformat the header into a buffer-compatible format + packet.fsample = hdr.Fs; + packet.nchans = hdr.nChans; + packet.nsamples = 0; + packet.nevents = 0; + packet.data_type = find(strcmp(type, class(dat))) - 1; % zero-offset + if isfield(hdr,'label') && iscell(hdr.label) + packet.channel_names = hdr.label; + end + if isfield(hdr,'siemensap') + if isa(hdr.siemensap, 'uint8') + packet.siemensap = hdr.siemensap; + else + try + packet.siemensap = matlab2sap(hdr.siemensap); + catch + warning 'Ignoring field "siemensap"'; + end + end + end + if isfield(hdr,'nifti_1') + if isa(hdr.nifti_1, 'uint8') + packet.nifti_1 = hdr.nifti_1; + else + try + packet.nifti_1 = decode_nifti1(hdr.nifti_1); + catch + warning 'Ignoring field "nifti_1"'; + end + end + end + if isfield(hdr,'ctf_res4') + if isa(hdr.ctf_res4, 'uint8') + packet.ctf_res4 = hdr.ctf_res4; + else + warning 'Ignoring non-uint8 field "ctf_res4"'; + end + end + + % try to put_hdr and initialize if necessary + try + % try writing the packet + buffer('put_hdr', packet, host, port); + + catch + if ~isempty(strfind(lasterr, 'Buffer size N must be an integer-valued scalar double.')) + % this happens if the MATLAB75/toolbox/signal/signal/buffer + % function is used instead of the fieldtrip buffer + error('the FieldTrip buffer mex file was not found on your path, it should be in fieldtrip/fileio/private'); + + elseif ~isempty(strfind(lasterr, 'failed to create socket')) && (strcmp(host, 'localhost') || strcmp(host, '127.0.0.1')) + + % start a local instance of the TCP server + warning('starting fieldtrip buffer on %s:%d', host, port); + buffer('tcpserver', 'init', host, port); + pause(1); + + % rewrite the packet until success + success = false; + while ~success + try + % it may take some time before the TCP server is fully initialized + % try writing the packet again + buffer('put_hdr', packet, host, port); + success = true; + catch + success = false; + end + end + end % if strfind... + + end % try + + end % writing header + + if ~isempty(dat) + max_nsamples = 32556; + if size(dat,2)>max_nsamples + % FIXME this is a hack to split large writes into multiple smaller writes + % this is to work around a problem observed in the neuralynx proxy + % when sampling 32 channels at 32KHz + begsample = 1; + while begsample<=size(dat,2) + endsample = begsample - 1 + max_nsamples; + endsample = min(endsample, size(dat,2)); + % if append is already one of the arguments, remove it from varargin + indx = find(strcmp(varargin, 'append')); % find the "append" key + if ~isempty(indx) + indx = [indx indx+1]; % remove the key and the value + varargin(indx) = []; + end + ft_write_data(filename, dat(:,begsample:endsample), varargin{:}, 'append', false); + begsample = endsample + 1; + end + else + % FIXME this is the normal code, which will also be used recursively + % reformat the data into a buffer-compatible format + packet.nchans = size(dat,1); + packet.nsamples = size(dat,2); + packet.data_type = find(strcmp(type, class(dat))) - 1; % zero-offset + packet.bufsize = numel(dat) * wordsize{find(strcmp(type, class(dat)))}; + packet.buf = dat; + buffer('put_dat', packet, host, port); + end % if data larger than chuncksize + end + + case 'brainvision_eeg' + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % combination of *.eeg and *.vhdr file + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + if append + error('appending data is not yet supported for this data format'); + end + + if nchans~=hdr.nChans && length(chanindx)==nchans + % assume that the header corresponds to the original multichannel + % file and that the data represents a subset of channels + hdr.label = hdr.label(chanindx); + hdr.nChans = length(chanindx); + end + % the header should at least contain the following fields + % hdr.label + % hdr.nChans + % hdr.Fs + write_brainvision_eeg(filename, hdr, dat); + + case 'fcdc_matbin' + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % multiplexed data in a *.bin file (ieee-le, 64 bit floating point values), + % accompanied by a matlab V6 file containing the header + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + if append + error('appending data is not yet supported for this data format'); + end + + [path, file, ext] = fileparts(filename); + headerfile = fullfile(path, [file '.mat']); + datafile = fullfile(path, [file '.bin']); + if nchans~=hdr.nChans && length(chanindx)==nchans + % assume that the header corresponds to the original multichannel + % file and that the data represents a subset of channels + hdr.label = hdr.label(chanindx); + hdr.nChans = length(chanindx); + end + if ~isfield(hdr, 'precision') + hdr.precision = 'double'; + end + % write the header file + save(headerfile, 'hdr', '-v6'); + % write the data file + [fid,message] = fopen(datafile,'wb','ieee-le'); + fwrite(fid, dat, hdr.precision); + fclose(fid); + + case 'fcdc_mysql' + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % write to a MySQL server listening somewhere else on the network + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + db_open(filename); + if ~isempty(hdr) && isempty(dat) + % insert the header information into the database + if db_blob + % insert the structure into the database table as a binary blob + db_insert_blob('fieldtrip.header', 'msg', hdr); + else + % make a structure with the same elements as the fields in the database table + s = struct; + s.Fs = hdr.Fs; % sampling frequency + s.nChans = hdr.nChans; % number of channels + s.nSamples = hdr.nSamples; % number of samples per trial + s.nSamplesPre = hdr.nSamplesPre; % number of pre-trigger samples in each trial + s.nTrials = hdr.nTrials; % number of trials + s.label = mxSerialize(hdr.label); + try + s.msg = mxSerialize(hdr); + catch + warning(lasterr); + end + db_insert('fieldtrip.header', s); + end + + elseif isempty(hdr) && ~isempty(dat) + dim = size(dat); + if numel(dim)==2 + % ensure that the data dimensions correspond to ntrials X nchans X samples + dim = [1 dim]; + dat = reshape(dat, dim); + end + ntrials = dim(1); + for i=1:ntrials + if db_blob + % insert the data into the database table as a binary blob + db_insert_blob('fieldtrip.data', 'msg', reshape(dat(i,:,:), dim(2:end))); + else + % create a structure with the same fields as the database table + s = struct; + s.nChans = dim(2); + s.nSamples = dim(3); + try + s.data = mxSerialize(reshape(dat(i,:,:), dim(2:end))); + catch + warning(lasterr); + end + % insert the structure into the database + db_insert('fieldtrip.data', s); + end + end + + else + error('you should specify either the header or the data when writing to a MySQL database'); + end + + case 'matlab' + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % plain matlab file + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + [path, file, ext] = fileparts(filename); + filename = fullfile(path, [file '.mat']); + if append && exist(filename, 'file') + % read the previous header and data from matlab file + prev = load(filename); + if ~isempty(hdr) && ~isequal(hdr, prev.hdr) + error('inconsistent header'); + else + % append the new data to that from the matlab file + dat = cat(2, prev.dat, dat); + end + elseif append && ~exist(filename, 'file') + % file does not yet exist, which is not a problem + elseif ~append && exist(filename, 'file') + warning(sprintf('deleting existing file ''%s''', filename)); + delete(filename); + elseif ~append && ~exist(filename, 'file') + % file does not yet exist, which is not a problem + end + save(filename, 'dat', 'hdr'); + + case 'neuralynx_sdma' + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % The first version of this file format contained in the first 8 bytes the + % channel label as string. Subsequently it contained 32 bit integer values. + % + % The second version of this file format starts with 8 bytes describing (as + % a space-padded string) the data type. The channel label is contained in + % the filename as dataset.chanlabel.bin. + % + % The third version of this file format starts with 7 bytes describing (as + % a zero-padded string) the data type, followed by the 8th byte which + % describes the downscaling for the 8 and 16 bit integer representations. + % The downscaling itself is represented as uint8 and should be interpreted as + % the number of bits to shift. The channel label is contained in the + % filename as dataset.chanlabel.bin. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + statuschannel = { + 'stx' + 'pid' + 'siz' + 'tsh' + 'tsl' + 'cpu' + 'ttl' + 'x01' + 'x02' + 'x03' + 'x04' + 'x05' + 'x06' + 'x07' + 'x08' + 'x09' + 'x10' + 'crc' + }; + + dirname = filename; + clear filename + [path, file] = fileparts(dirname); + for i=1:hdr.nChans + downscale(i) = 0; + if ~isempty(strmatch(hdr.label{i}, statuschannel)) + format{i} = 'uint32'; + else + format{i} = 'int32'; + end + filename{i} = fullfile(dirname, [file '.' hdr.label{i} '.bin']); + end + + if ~isdir(dirname) + mkdir(dirname); + end + + % open and write to the output files, one for each selected channel + fid = zeros(hdr.nChans,1); + for j=1:hdr.nChans + + if append==false + fid(j) = fopen(filename{j}, 'wb', 'ieee-le'); % open the file + magic = format{j}; % this used to be the channel name + magic((end+1):8) = 0; % pad with zeros + magic(8) = downscale(j); % number of bits to shift + fwrite(fid(j), magic(1:8)); % write the 8-byte file header + else + fid(j) = fopen(filename{j}, 'ab', 'ieee-le'); % open the file for appending + end % if append + + % convert the data into the correct class + buf = dat(j,:); + if ~strcmp(class(buf), format{j}) + switch format{j} + case 'int16' + buf = int16(buf); + case 'int32' + buf = int32(buf); + case 'single' + buf = single(buf); + case 'double' + buf = double(buf); + case 'uint32' + buf = uint32(buf); + otherwise + error('unsupported format conversion'); + end + end + + % apply the scaling, this corresponds to bit shifting + buf = buf ./ (2^downscale(j)); + + % write the segment of data to the output file + fwrite(fid(j), buf, format{j}, 'ieee-le'); + + fclose(fid(j)); + end % for each channel + + case 'riff_wave' + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % This writes data Y to a Windows WAVE file specified by the file name + % WAVEFILE, with a sample rate of FS Hz and with NBITS number of bits. + % NBITS must be 8, 16, 24, or 32. For NBITS < 32, amplitude values + % outside the range [-1,+1] are clipped + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + if append + error('appending data is not yet supported for this data format'); + end + + if nchans~=hdr.nChans && length(chanindx)==nchans + % assume that the header corresponds to the original multichannel + % file and that the data represents a subset of channels + hdr.label = hdr.label(chanindx); + hdr.nChans = length(chanindx); + end + if nchans~=1 + error('this format only supports single channel continuous data'); + end + wavwrite(dat, hdr.Fs, nbits, filename); + + case 'plexon_nex' + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % single or mulitple channel Plexon NEX file + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + if append + error('appending data is not yet supported for this data format'); + end + + [path, file] = fileparts(filename); + filename = fullfile(path, [file, '.nex']); + if nchans~=1 + error('only supported for single-channel data'); + end + % construct a NEX structure with the required parts of the header + nex.hdr.VarHeader.Type = 5; % continuous + nex.hdr.VarHeader.Name = hdr.label{1}; + nex.hdr.VarHeader.WFrequency = hdr.Fs; + if isfield(hdr, 'FirstTimeStamp') + nex.hdr.FileHeader.Frequency = hdr.Fs * hdr.TimeStampPerSample; + nex.var.ts = hdr.FirstTimeStamp; + else + warning('no timestamp information available'); + nex.hdr.FileHeader.Frequency = nan; + nex.var.ts = nan; + end + nex.var.indx = 0; + nex.var.dat = dat; + + write_plexon_nex(filename, nex); + + if 0 + % the following code snippet can be used for testing + nex2 = []; + [nex2.var, nex2.hdr] = read_plexon_nex(filename, 'channel', 1); + end + + case 'neuralynx_ncs' + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % single channel Neuralynx NCS file + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + if append + error('appending data is not yet supported for this data format'); + end + + if nchans>1 + error('only supported for single-channel data'); + end + + [path, file, ext] = fileparts(filename); + filename = fullfile(path, [file, '.ncs']); + + if nchans~=hdr.nChans && length(chanindx)==nchans + % assume that the header corresponds to the original multichannel + % file and that the data represents a subset of channels + % WARNING the AD channel index assumes that the data was read from a DMA or SDMA file + % the first 17 channels contain status info, this number is zero-offset + ADCHANNEL = chanindx - 17 - 1; + LABEL = hdr.label{chanindx}; + elseif hdr.nChans==1 + ADCHANNEL = -1; % unknown + LABEL = hdr.label{1}; % single channel + else + error('cannot determine channel label'); + end + + FSAMPLE = hdr.Fs; + RECORDNSMP = 512; + RECORDSIZE = 1044; + + % cut the downsampled LFP data into record-size pieces + nrecords = ceil(nsamples/RECORDNSMP); + fprintf('construct ncs with %d records\n', nrecords); + + % construct a ncs structure with all header details and the data in it + ncs = []; + ncs.NumValidSamp = ones(1,nrecords) * RECORDNSMP; % except for the last block + ncs.ChanNumber = ones(1,nrecords) * ADCHANNEL; + ncs.SampFreq = ones(1,nrecords) * FSAMPLE; + ncs.TimeStamp = zeros(1,nrecords,'uint64'); + + if rem(nsamples, RECORDNSMP)>0 + % the data length is not an integer number of records, pad the last record with zeros + dat = cat(2, dat, zeros(nchans, nrecords*RECORDNSMP-nsamples)); + ncs.NumValidSamp(end) = rem(nsamples, RECORDNSMP); + end + + ncs.dat = reshape(dat, RECORDNSMP, nrecords); + + for i=1:nrecords + % timestamps should be 64 bit unsigned integers + ncs.TimeStamp(i) = uint64(hdr.FirstTimeStamp) + uint64((i-1)*RECORDNSMP*hdr.TimeStampPerSample); + end + + % add the elements that will go into the ascii header + ncs.hdr.CheetahRev = '4.23.0'; + ncs.hdr.NLX_Base_Class_Type = 'CscAcqEnt'; + ncs.hdr.NLX_Base_Class_Name = LABEL; + ncs.hdr.RecordSize = RECORDSIZE; + ncs.hdr.ADChannel = ADCHANNEL; + ncs.hdr.SamplingFrequency = FSAMPLE; + + % write it to a file + fprintf('writing to %s\n', filename); + write_neuralynx_ncs(filename, ncs); + + if 0 + % the following code snippet can be used for testing + ncs2 = read_neuralynx_ncs(filename, 1, inf); + end + + otherwise + error('unsupported data format'); +end % switch dataformat + diff --git a/external/fieldtrip/fileio/ft_write_event.m b/external/fieldtrip/fileio/ft_write_event.m new file mode 100644 index 0000000..902949b --- /dev/null +++ b/external/fieldtrip/fileio/ft_write_event.m @@ -0,0 +1,263 @@ +function ft_write_event(filename, event, varargin) + +% FT_WRITE_EVENT writes an event structure to a file, a message daemon +% listening on a network socked, or to another computer connected through +% the serial port. +% +% Use as +% ft_write_event(filename, event, ...) +% +% The first argument is a string containing the filename. The second +% argument is a structure with the event. Multiple events can be +% represented as a structure array. +% +% Events are represented as +% event.type string +% event.sample expressed in samples, the first sample of a recording is 1 +% event.value number or string +% event.offset expressed in samples +% event.duration expressed in samples +% event.timestamp expressed in timestamp units, which vary over systems (optional) +% +% Events can also be written to special communication streams +% by specifying the target as URI instead of a filename. Supported are +% buffer://: +% fifo:// +% tcp://: +% udp://: +% mysql://:@: +% rfb://@: +% serial:?key1=value1&key2=value2&... +% rfb://@: +% +% See also FT_READ_HEADER, FT_READ_DATA, FT_READ_EVENT, FT_WRITE_DATA + +% Copyright (C) 2007-2010 Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_write_event.m 1300 2010-06-29 14:38:51Z roboos $ + +global event_queue % for fcdc_global +global db_blob % for fcdc_mysql +if isempty(db_blob) + db_blob = 0; +end + +if iscell(filename) + % use recursion to write to multiple event targets + for i=1:numel(filename) + ft_write_event(filename{i}, event, varargin); + end + return +end + +% set the defaults +eventformat = keyval('eventformat', varargin); if isempty(eventformat), eventformat = ft_filetype(filename); end +swapping = keyval('swapping', varargin); if isempty(swapping), swapping = 'native'; end +append = keyval('append', varargin); if isempty(append), append = 'yes'; end +maxqlength = keyval('maxqlength', varargin); if isempty(maxqlength), maxqlength = Inf; end + +switch eventformat + + case 'empty' + fprintf(1,'Pretending to write %i events...\n', length(event)); + + case 'fcdc_global' + % store it in a global variable, this is only for debugging + if isempty(event_queue) || ~isstruct(event_queue) + event_queue = event; + else + event_queue = appendevent(event_queue, event); + end + + case 'fcdc_rfb' + % remote frame buffer, i.e. VNC server on another computer + [password, host, port] = filetype_check_uri(filename); + rfbevent(sprintf('%s:%d', host, port), password, event.type, event.value); + + case 'fcdc_buffer' + % read from a networked buffer for realtime analysis + [host, port] = filetype_check_uri(filename); + + if strcmp(append, 'no') + buffer('flush_evt', [], host, port); % flush event + end + + % the MEX file now can handle various Matlab types directly and respects the fields + % sample, offset, duration + % -- these must all be numeric and non-empty (only first element is of interest) + % type, value + % -- these can be strings or any numeric type (double, single, [u]int[8-64]) + % will be transmitted as if vectorised + buffer('put_evt', event, host, port); + + % SK: There was some code here for firing up a FieldTrip buffer locally, + % but this is very likely to be senseless because we have no proper header + % information here. Please explicitly use ft_create_buffer instead. + + case 'fcdc_serial' + % this code is moved to a seperate file + write_serial_event(filename, event); + + case 'fcdc_mysql' + % write to a MySQL server listening somewhere else on the network + db_open(filename); + for i=1:length(event) + if db_blob + % insert the structure into the database table as a binary blob + db_insert_blob('fieldtrip.event', 'msg', event(i)); + else + % make a structure with the same elements as the fields in the database table + s = struct; + % these fields also exist as elements in the table and as such can be used for filtering + if isa(event(i).type, 'char') + s.type = event(i).type; + end + if isa(event(i).value, 'numeric') && numel(event(i).value)==1 + s.value = event(i).value; + end + if isa(event(i).sample, 'numeric') && numel(event(i).sample)==1 + s.sample = event(i).sample; + end + if isa(event(i).sample, 'numeric') && numel(event(i).offset)==1 + s.offset = event(i).offset; + end + if isa(event(i).sample, 'numeric') && numel(event(i).duration)==1 + s.duration = event(i).duration; + end + % insert the structure into the database table + db_insert('fieldtrip.event', s); + end + end + + case 'fcdc_fifo' + + % these are opened in blocking mode, i.e. reading/writing will block until boths sides are connected + fifo = filetype_check_uri(filename); + + if ~exist(fifo,'file') + warning('the FIFO %s does not exist; attempting to create it', fifo); + system(sprintf('mkfifo -m 0666 %s',fifo)); + end + + fid = fopen(fifo, 'w'); + for i=1:length(event) + + try + % convert the event into a network message + msg = mxSerialize(event(i)); + num = fwrite(fid, msg, 'uint8'); + catch + warning(lasterr); + end + + if num~=length(msg) + error('problem writing to FIFO %s', fifo); + end + end + fclose(fid); + + case 'fcdc_tcp' + + % TCP network socket + [host, port] = filetype_check_uri(filename); + + con=pnet('tcpconnect',host,port); + + pnet(con,'setwritetimeout',1); + + if con~=-1, + + try % Failsafe + + for i=1:length(event) + + % convert the event into a network message + msg = mxSerialize(event(i)); + + % tell the message daemon that a message will be sent, and send it + pnet(con,'printf',num2str(msg)); + pnet(con,'printf','\n'); + end +% catch +% warning(lasterr); + end + + pnet(con,'close'); + end + + case 'fcdc_udp' + + % UDP network socket + + [host, port] = filetype_check_uri(filename); + udp=pnet('udpsocket',port); + + if udp~=-1, + try % Failsafe + + for i=1:length(event) + + % convert the event into a network message + msg = mxSerialize(event(i)); + + % tell the message daemon that a message will be sent, and send it + pnet(udp,'write',uint8(msg),1000); + pnet(udp,'writepacket',host,port); % Send buffer as UDP packet to host + end + + catch + warning(lasterr); + end + pnet(udp,'close'); + end + + + otherwise + % assume that it is a file. Since the file probably does not yet + % exist, determine its type by only looking at the extension + if filetype_check_extension(filename, '.mat') + % write the events to a matlab file + if exist(filename,'file') && strcmp(append, 'yes') + try + tmp = load(filename, 'event'); + event = cat(1, tmp.event(:), event(:)); + catch + event = event(:); + end + % optionally restric the length of the event queue to flush old events + if isfinite(maxqlength) && isreal(maxqlength) && (maxqlength>0) && (length(event)>maxqlength) + event = event(end-maxqlength+1:end); + % NOTE: this could be done using the filter event function, but + % then this is just a temporary solution that will probably be + % removed in a future versions of the code + end + save(filename, 'event', '-append', '-v6'); + % NOTE: the -append option in this call to the save function does + % not actually do anything useful w.r.t. the event variable since the + % events are being appended in the code above and the the save function + % will just overwrite the existing event variable in the file. + % However, if there are other variables in the file (whatever) then the + % append option preservs them + else + save(filename, 'event', '-v6'); + end + else + error('unsupported file type') + end +end diff --git a/external/fieldtrip/fileio/private/ama2vol.m b/external/fieldtrip/fileio/private/ama2vol.m new file mode 100644 index 0000000..248b014 --- /dev/null +++ b/external/fieldtrip/fileio/private/ama2vol.m @@ -0,0 +1,42 @@ +function [vol] = ama2vol(ama) + +% AMA2VOL +% +% Use as +% vol = ama2vol(ama) + +% Copyright (C) 2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ama2vol.m 945 2010-04-21 17:41:20Z roboos $ + +vol = []; +ngeo = length(ama.geo); +for i=1:ngeo + vol.bnd(i).pnt = ama.geo(i).pnt; + vol.bnd(i).tri = ama.geo(i).dhk; + vol.cond(i) = ama.geo(i).sigmam; +end +vol.mat = ama.bi; +npnt = size(vol.mat,2); +if size(vol.mat,1). +% +% $Id: appendevent.m 945 2010-04-21 17:41:20Z roboos $ + +if isempty(a) + c = b(:); +elseif isempty(b) + c = a(:); +else + c = a(:); + for i=1:numel(b) + c(end+1).type = b(i).type; + c(end ).value = b(i).value; + c(end ).sample = b(i).sample; + if isfield(b, 'timestamp') + c(end ).timestamp = b(i).timestamp; % optional + end + if isfield(b, 'offset') + c(end ).offset = b(i).offset; % optional + end + if isfield(b, 'duration') + c(end ).duration = b(i).duration; % optional + end + end +end diff --git a/external/fieldtrip/fileio/private/avw_hdr_make.m b/external/fieldtrip/fileio/private/avw_hdr_make.m new file mode 100644 index 0000000..301c5f6 --- /dev/null +++ b/external/fieldtrip/fileio/private/avw_hdr_make.m @@ -0,0 +1,118 @@ +function [ avw ] = avw_hdr_make + +% AVW_HDR_MAKE - Create Analyze format data header (avw.hdr) +% +% [ avw ] = avw_hdr_make +% +% avw.hdr - a struct, all fields returned from the header. +% For details, find a good description on the web +% or see the Analyze File Format pdf in the +% mri_toolbox doc folder or see avw_hdr_read.m +% +% See also, AVW_HDR_READ AVW_HDR_WRITE +% AVW_IMG_READ AVW_IMG_WRITE +% + +% $Revision: 883 $ $Date: 2009/01/14 09:24:45 $ + +% Licence: GNU GPL, no express or implied warranties +% History: 06/2002, Darren.Weber@flinders.edu.au +% 02/2003, Darren.Weber@flinders.edu.au +% date/time bug at lines 97-98 +% identified by Bennett.Landman@ieee.org +% +% The Analyze format is copyright +% (c) Copyright, 1986-1995 +% Biomedical Imaging Resource, Mayo Foundation +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +version = '[$Revision: 883 $]'; +fprintf('\nAVW_HDR_MAKE [v%s]\n',version(12:16)); tic; + + +% Comments +% The header format is flexible and can be extended for new +% user-defined data types. The essential structures of the header +% are the header_key and the image_dimension. See avw_hdr_read +% for more detail of the header structure +avw.hdr = make_header; + +t=toc; fprintf('...done (%5.2f sec).\n',t); + +return + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [ hdr ] = make_header + + hdr.hk = header_key; + hdr.dime = image_dimension; + hdr.hist = data_history; + +return + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [hk] = header_key + + hk.sizeof_hdr = int32(348); % must be 348! + hk.data_type(1:10) = sprintf('%10s',''); + hk.db_name(1:18) = sprintf('%18s',''); + hk.extents = int32(16384); + hk.session_error = int16(0); + hk.regular = sprintf('%1s','r'); % might be uint8 + hk.hkey_un0 = uint8(0); + +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [ dime ] = image_dimension + + dime.dim(1:8) = int16([4 256 256 256 1 0 0 0]); + dime.vox_units(1:4) = sprintf('%4s','mm'); + dime.cal_units(1:8) = sprintf('%8s',''); + dime.unused1 = int16(0); + dime.datatype = int16(2); + dime.bitpix = int16(8); + dime.dim_un0 = int16(0); + dime.pixdim(1:8) = single([0 1 1 1 1000 0 0 0]); + dime.vox_offset = single(0); + dime.funused1 = single(0); + dime.funused2 = single(0); + % Set default 8bit intensity scale (from MRIcro), otherwise funused3 + dime.roi_scale = single(1); + dime.cal_max = single(0); + dime.cal_min = single(0); + dime.compressed = int32(0); + dime.verified = int32(0); + dime.glmax = int32(255); + dime.glmin = int32(0); + +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [ hist ] = data_history + + datime = clock; + + hist.descrip(1:80) = sprintf('%-80s','mri_toolbox @ http://eeg.sf.net/'); + hist.aux_file(1:24) = sprintf('%-24s',''); + hist.orient = uint8(0); % sprintf( '%1s',''); % see notes in avw_hdr_read + hist.originator(1:10) = sprintf('%-10s',''); + hist.generated(1:10) = sprintf('%-10s','mri_toolbx'); + hist.scannum(1:10) = sprintf('%-10s',''); + hist.patient_id(1:10) = sprintf('%-10s',''); + hist.exp_date(1:10) = sprintf('%02d-%02d-%04d',datime(3),datime(2),datime(1)); + hist.exp_time(1:10) = sprintf('%02d-%02d-%04.1f',datime(4),datime(5),datime(6)); + hist.hist_un0(1:3) = sprintf( '%-3s',''); + hist.views = int32(0); + hist.vols_added = int32(0); + hist.start_field = int32(0); + hist.field_skip = int32(0); + hist.omax = int32(0); + hist.omin = int32(0); + hist.smax = int32(0); + hist.smin = int32(0); + +return diff --git a/external/fieldtrip/fileio/private/avw_hdr_read.m b/external/fieldtrip/fileio/private/avw_hdr_read.m new file mode 100644 index 0000000..10e2a65 --- /dev/null +++ b/external/fieldtrip/fileio/private/avw_hdr_read.m @@ -0,0 +1,389 @@ +function [ avw, machine ] = avw_hdr_read(fileprefix, machine, verbose) + +% avw_hdr_read - read Analyze format data header (*.hdr) +% +% [ avw, machine ] = avw_hdr_read(fileprefix, [machine], [verbose]) +% +% fileprefix - string filename (without .hdr); the file name +% can be given as a full path or relative to the +% current directory. +% +% machine - a string, see machineformat in fread for details. +% The default here is 'ieee-le' but the routine +% will automatically switch between little and big +% endian to read any such Analyze header. It +% reports the appropriate machine format and can +% return the machine value. +% +% avw.hdr - a struct, all fields returned from the header. +% For details, find a good description on the web +% or see the Analyze File Format pdf in the +% mri_toolbox doc folder or read this .m file. +% +% verbose - the default is to output processing information to the command +% window. If verbose = 0, this will not happen. +% +% This function is called by avw_img_read +% +% See also avw_hdr_write, avw_hdr_make, avw_view_hdr, avw_view +% + +% $Revision: 883 $ $Date: 2009/01/14 09:24:45 $ + +% Licence: GNU GPL, no express or implied warranties +% History: 05/2002, Darren.Weber@flinders.edu.au +% The Analyze format and c code below is copyright +% (c) Copyright, 1986-1995 +% Biomedical Imaging Resource, Mayo Foundation +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +if ~exist('verbose','var'), verbose = 1; end + +if verbose, + version = '[$Revision: 883 $]'; + fprintf('\nAVW_HDR_READ [v%s]\n',version(12:16)); tic; +end + +if ~exist('fileprefix','var'), + msg = sprintf('...no input fileprefix - see help avw_hdr_read\n\n'); + error(msg); +end +if ~exist('machine','var'), machine = 'ieee-le'; end + + +if findstr('.hdr',fileprefix), + % fprintf('...removing .hdr extension from ''%s''\n',fileprefix); + fileprefix = strrep(fileprefix,'.hdr',''); +end +if findstr('.img',fileprefix), + % fprintf('...removing .img extension from ''%s''\n',fileprefix); + fileprefix = strrep(fileprefix,'.img',''); +end +file = sprintf('%s.hdr',fileprefix); + +if exist(file), + if verbose, + fprintf('...reading %s Analyze format',machine); + end + fid = fopen(file,'r',machine); + avw.hdr = read_header(fid,verbose); + avw.fileprefix = fileprefix; + fclose(fid); + + if ~isequal(avw.hdr.hk.sizeof_hdr,348), + if verbose, fprintf('...failed.\n'); end + % first try reading the opposite endian to 'machine' + switch machine, + case 'ieee-le', machine = 'ieee-be'; + case 'ieee-be', machine = 'ieee-le'; + end + if verbose, fprintf('...reading %s Analyze format',machine); end + fid = fopen(file,'r',machine); + avw.hdr = read_header(fid,verbose); + avw.fileprefix = fileprefix; + fclose(fid); + end + if ~isequal(avw.hdr.hk.sizeof_hdr,348), + % Now throw an error + if verbose, fprintf('...failed.\n'); end + msg = sprintf('...size of header not equal to 348 bytes!\n\n'); + error(msg); + end +else + msg = sprintf('...cannot find file %s.hdr\n\n',file); + error(msg); +end + +if verbose, + t=toc; fprintf('...done (%5.2f sec).\n',t); +end + +return + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [ dsr ] = read_header(fid,verbose) + + % Original header structures - ANALYZE 7.5 + %struct dsr + % { + % struct header_key hk; /* 0 + 40 */ + % struct image_dimension dime; /* 40 + 108 */ + % struct data_history hist; /* 148 + 200 */ + % }; /* total= 348 bytes*/ + dsr.hk = header_key(fid); + dsr.dime = image_dimension(fid,verbose); + dsr.hist = data_history(fid); + +return + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [hk] = header_key(fid) + + % The required elements in the header_key substructure are: + % + % int sizeof_header Must indicate the byte size of the header file. + % int extents Should be 16384, the image file is created as + % contiguous with a minimum extent size. + % char regular Must be 'r' to indicate that all images and + % volumes are the same size. + + % Original header structures - ANALYZE 7.5 + % struct header_key /* header key */ + % { /* off + size */ + % int sizeof_hdr /* 0 + 4 */ + % char data_type[10]; /* 4 + 10 */ + % char db_name[18]; /* 14 + 18 */ + % int extents; /* 32 + 4 */ + % short int session_error; /* 36 + 2 */ + % char regular; /* 38 + 1 */ + % char hkey_un0; /* 39 + 1 */ + % }; /* total=40 bytes */ + + fseek(fid,0,'bof'); + + hk.sizeof_hdr = fread(fid, 1,'*int32'); % should be 348! + hk.data_type = fread(fid,10,'*char')'; + hk.db_name = fread(fid,18,'*char')'; + hk.extents = fread(fid, 1,'*int32'); + hk.session_error = fread(fid, 1,'*int16'); + hk.regular = fread(fid, 1,'*char')'; % might be uint8 + hk.hkey_un0 = fread(fid, 1,'*uint8')'; + + % check if this value was a char zero + if hk.hkey_un0 == 48, + hk.hkey_un0 = 0; + end + +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [ dime ] = image_dimension(fid,verbose) + + %struct image_dimension + % { /* off + size */ + % short int dim[8]; /* 0 + 16 */ + % /* + % dim[0] Number of dimensions in database; usually 4. + % dim[1] Image X dimension; number of *pixels* in an image row. + % dim[2] Image Y dimension; number of *pixel rows* in slice. + % dim[3] Volume Z dimension; number of *slices* in a volume. + % dim[4] Time points; number of volumes in database + % */ + % char vox_units[4]; /* 16 + 4 */ + % char cal_units[8]; /* 20 + 8 */ + % short int unused1; /* 28 + 2 */ + % short int datatype; /* 30 + 2 */ + % short int bitpix; /* 32 + 2 */ + % short int dim_un0; /* 34 + 2 */ + % float pixdim[8]; /* 36 + 32 */ + % /* + % pixdim[] specifies the voxel dimensions: + % pixdim[1] - voxel width, mm + % pixdim[2] - voxel height, mm + % pixdim[3] - slice thickness, mm + % pixdim[4] - volume timing, in msec + % ..etc + % */ + % float vox_offset; /* 68 + 4 */ + % float roi_scale; /* 72 + 4 */ + % float funused1; /* 76 + 4 */ + % float funused2; /* 80 + 4 */ + % float cal_max; /* 84 + 4 */ + % float cal_min; /* 88 + 4 */ + % int compressed; /* 92 + 4 */ + % int verified; /* 96 + 4 */ + % int glmax; /* 100 + 4 */ + % int glmin; /* 104 + 4 */ + % }; /* total=108 bytes */ + + dime.dim = fread(fid,8,'*int16')'; + dime.vox_units = fread(fid,4,'*char')'; + dime.cal_units = fread(fid,8,'*char')'; + dime.unused1 = fread(fid,1,'*int16'); + dime.datatype = fread(fid,1,'*int16'); + dime.bitpix = fread(fid,1,'*int16'); + dime.dim_un0 = fread(fid,1,'*int16'); + dime.pixdim = fread(fid,8,'*float')'; + dime.vox_offset = fread(fid,1,'*float'); + dime.roi_scale = fread(fid,1,'*float'); + dime.funused1 = fread(fid,1,'*float'); + dime.funused2 = fread(fid,1,'*float'); + dime.cal_max = fread(fid,1,'*float'); + dime.cal_min = fread(fid,1,'*float'); + dime.compressed = fread(fid,1,'*int32'); + dime.verified = fread(fid,1,'*int32'); + dime.glmax = fread(fid,1,'*int32'); + dime.glmin = fread(fid,1,'*int32'); + + if dime.dim(1) < 4, % Number of dimensions in database; usually 4. + if verbose, + fprintf('...ensuring 4 dimensions in avw.hdr.dime.dim\n'); + end + dime.dim(1) = int16(4); + end + if dime.dim(5) < 1, % Time points; number of volumes in database + if verbose, + fprintf('...ensuring at least 1 volume in avw.hdr.dime.dim(5)\n'); + end + dime.dim(5) = int16(1); + end + +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [ hist ] = data_history(fid) + + % Original header structures - ANALYZE 7.5 + %struct data_history + % { /* off + size */ + % char descrip[80]; /* 0 + 80 */ + % char aux_file[24]; /* 80 + 24 */ + % char orient; /* 104 + 1 */ + % char originator[10]; /* 105 + 10 */ + % char generated[10]; /* 115 + 10 */ + % char scannum[10]; /* 125 + 10 */ + % char patient_id[10]; /* 135 + 10 */ + % char exp_date[10]; /* 145 + 10 */ + % char exp_time[10]; /* 155 + 10 */ + % char hist_un0[3]; /* 165 + 3 */ + % int views /* 168 + 4 */ + % int vols_added; /* 172 + 4 */ + % int start_field; /* 176 + 4 */ + % int field_skip; /* 180 + 4 */ + % int omax; /* 184 + 4 */ + % int omin; /* 188 + 4 */ + % int smax; /* 192 + 4 */ + % int smin; /* 196 + 4 */ + % }; /* total=200 bytes */ + + hist.descrip = fread(fid,80,'*char')'; + hist.aux_file = fread(fid,24,'*char')'; + hist.orient = fread(fid, 1,'*uint8'); % see note below on char + hist.originator = fread(fid,10,'*char')'; + hist.generated = fread(fid,10,'*char')'; + hist.scannum = fread(fid,10,'*char')'; + hist.patient_id = fread(fid,10,'*char')'; + hist.exp_date = fread(fid,10,'*char')'; + hist.exp_time = fread(fid,10,'*char')'; + hist.hist_un0 = fread(fid, 3,'*char')'; + hist.views = fread(fid, 1,'*int32'); + hist.vols_added = fread(fid, 1,'*int32'); + hist.start_field = fread(fid, 1,'*int32'); + hist.field_skip = fread(fid, 1,'*int32'); + hist.omax = fread(fid, 1,'*int32'); + hist.omin = fread(fid, 1,'*int32'); + hist.smax = fread(fid, 1,'*int32'); + hist.smin = fread(fid, 1,'*int32'); + + % check if hist.orient was saved as ascii char value + switch hist.orient, + case 48, hist.orient = uint8(0); + case 49, hist.orient = uint8(1); + case 50, hist.orient = uint8(2); + case 51, hist.orient = uint8(3); + case 52, hist.orient = uint8(4); + case 53, hist.orient = uint8(5); + end + +return + + +% Note on using char: +% The 'char orient' field in the header is intended to +% hold simply an 8-bit unsigned integer value, not the ASCII representation +% of the character for that value. A single 'char' byte is often used to +% represent an integer value in Analyze if the known value range doesn't +% go beyond 0-255 - saves a byte over a short int, which may not mean +% much in today's computing environments, but given that this format +% has been around since the early 1980's, saving bytes here and there on +% older systems was important! In this case, 'char' simply provides the +% byte of storage - not an indicator of the format for what is stored in +% this byte. Generally speaking, anytime a single 'char' is used, it is +% probably meant to hold an 8-bit integer value, whereas if this has +% been dimensioned as an array, then it is intended to hold an ASCII +% character string, even if that was only a single character. +% Denny + + +% Comments +% The header format is flexible and can be extended for new +% user-defined data types. The essential structures of the header +% are the header_key and the image_dimension. +% + +% The required elements in the header_key substructure are: +% +% int sizeof_header Must indicate the byte size of the header file. +% int extents Should be 16384, the image file is created as +% contiguous with a minimum extent size. +% char regular Must be 'r' to indicate that all images and +% volumes are the same size. +% + +% The image_dimension substructure describes the organization and +% size of the images. These elements enable the database to reference +% images by volume and slice number. Explanation of each element follows: +% +% short int dim[ ]; /* Array of the image dimensions */ +% +% dim[0] Number of dimensions in database; usually 4. +% dim[1] Image X dimension; number of pixels in an image row. +% dim[2] Image Y dimension; number of pixel rows in slice. +% dim[3] Volume Z dimension; number of slices in a volume. +% dim[4] Time points; number of volumes in database. +% dim[5] Undocumented. +% dim[6] Undocumented. +% dim[7] Undocumented. +% +% char vox_units[4] Specifies the spatial units of measure for a voxel. +% char cal_units[8] Specifies the name of the calibration unit. +% short int unused1 /* Unused */ +% short int datatype /* Datatype for this image set */ +% /*Acceptable values for datatype are*/ +% #define DT_NONE 0 +% #define DT_UNKNOWN 0 /*Unknown data type*/ +% #define DT_BINARY 1 /*Binary ( 1 bit per voxel)*/ +% #define DT_UNSIGNED_CHAR 2 /*Unsigned character ( 8 bits per voxel)*/ +% #define DT_SIGNED_SHORT 4 /*Signed short (16 bits per voxel)*/ +% #define DT_SIGNED_INT 8 /*Signed integer (32 bits per voxel)*/ +% #define DT_FLOAT 16 /*Floating point (32 bits per voxel)*/ +% #define DT_COMPLEX 32 /*Complex (64 bits per voxel; 2 floating point numbers)/* +% #define DT_DOUBLE 64 /*Double precision (64 bits per voxel)*/ +% #define DT_RGB 128 /*A Red-Green-Blue datatype*/ +% #define DT_ALL 255 /*Undocumented*/ +% +% short int bitpix; /* Number of bits per pixel; 1, 8, 16, 32, or 64. */ +% short int dim_un0; /* Unused */ +% +% float pixdim[]; Parallel array to dim[], giving real world measurements in mm and ms. +% pixdim[0]; Pixel dimensions? +% pixdim[1]; Voxel width in mm. +% pixdim[2]; Voxel height in mm. +% pixdim[3]; Slice thickness in mm. +% pixdim[4]; timeslice in ms (ie, TR in fMRI). +% pixdim[5]; Undocumented. +% pixdim[6]; Undocumented. +% pixdim[7]; Undocumented. +% +% float vox_offset; Byte offset in the .img file at which voxels start. This value can be +% negative to specify that the absolute value is applied for every image +% in the file. +% +% float roi_scale; Specifies the Region Of Interest scale? +% float funused1; Undocumented. +% float funused2; Undocumented. +% +% float cal_max; Specifies the upper bound of the range of calibration values. +% float cal_min; Specifies the lower bound of the range of calibration values. +% +% int compressed; Undocumented. +% int verified; Undocumented. +% +% int glmax; The maximum pixel value for the entire database. +% int glmin; The minimum pixel value for the entire database. +% +% diff --git a/external/fieldtrip/fileio/private/avw_hdr_write.m b/external/fieldtrip/fileio/private/avw_hdr_write.m new file mode 100644 index 0000000..92239ef --- /dev/null +++ b/external/fieldtrip/fileio/private/avw_hdr_write.m @@ -0,0 +1,427 @@ +function avw_hdr_write(avw, fileprefix, machine, verbose) + +% AVW_HDR_WRITE - Write Analyze header file (*.hdr) +% +% avw_hdr_write(avw,[fileprefix],[machine],[verbose]) +% +% eg, avw_hdr_write(avw,'test'); +% +% avw - a struct with .hdr field, which itself is a struct, +% containing all fields of an Analyze header. +% For details, see avw_hdr_read.m +% +% fileprefix - a string, the filename without the .hdr extension. +% If empty, may use avw.fileprefix +% +% machine - a string, see machineformat in fread for details. +% The default here is 'ieee-le'. +% +% verbose - the default is to output processing information to the command +% window. If verbose = 0, this will not happen. +% +% See also, AVW_HDR_READ AVW_HDR_MAKE +% AVW_IMG_READ AVW_IMG_WRITE +% + +% $Revision: 883 $ $Date: 2009/01/14 09:24:45 $ + +% Licence: GNU GPL, no express or implied warranties +% History: 05/2002, Darren.Weber@flinders.edu.au +% 02/2003, Bennett.Landman@ieee.org +% - more specific data history var sizes +% - 02/2003 confirmed, Darren +% +% The Analyze format and c code below is copyright +% (c) Copyright, 1986-1995 +% Biomedical Imaging Resource, Mayo Foundation +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +if ~exist('verbose','var'), verbose = 1; end +if ~exist('machine','var'), machine = 'ieee-le'; end + +if verbose, + version = '[$Revision: 883 $]'; + fprintf('AVW_HDR_WRITE [v%s]\n',version(12:16)); tic; +end + +%---------------------------------------------------------------------------- +% Check inputs + +if ~exist('avw','var'), + warning('...no input avw - calling avw_hdr_make\n'); + avw = avw_hdr_make; +elseif isempty(avw), + warning('...empty input avw - calling avw_hdr_make\n'); + avw = avw_hdr_make; +elseif ~isfield(avw,'hdr'), + warning('...empty input avw.hdr - calling avw_hdr_make\n'); + avw = avw_hdr_make; +end +if ~isequal(avw.hdr.hk.sizeof_hdr,348), + msg = sprintf('...avw.hdr.hk.sizeof_hdr must be 348!\n'); + error(msg); +end + +quit = 0; +if ~exist('fileprefix','var'), + if isfield(avw,'fileprefix'), + if ~isempty(avw.fileprefix), + fileprefix = avw.fileprefix; + else, + quit = 1; + end + else + quit = 1; + end + if quit, + helpwin avw_hdr_write; + error('...no input fileprefix - see help avw_hdr_write\n\n'); + return; + end +end + +if findstr('.hdr',fileprefix), +% fprintf('AVW_HDR_WRITE: Removing .hdr extension from ''%s''\n',fileprefix); + fileprefix = strrep(fileprefix,'.hdr',''); +end + + + +%---------------------------------------------------------------------------- +% MAIN + +if verbose, tic; end + + +% % force volume to 4D if necessary; conforms to AVW standard. i lifted this +% % code from mri_toolbox/avw_hdr_read.m and modified it just a little bit +% % (using minDim = 4; etc) +% minDim = 4; +% currDim = double(avw.hdr.dime.dim(1)); +% if ( currDim < minDim ) +% % fprintf( 'Warning %s: Forcing %d dimensions in avw.hdr.dime.dim\n', ... +% % mfilename, minDim ); +% avw.hdr.dime.dim(1) = int16(minDim); +% avw.hdr.dime.dim(currDim+2:minDim+1) = int16(1); +% avw.hdr.dime.pixdim(1) = int16(minDim); +% avw.hdr.dime.pixdim(currDim+2:minDim+1) = int16(1); +% end; + + +fid = fopen(sprintf('%s.hdr',fileprefix),'w',machine); +if fid < 0, + msg = sprintf('Cannot write to file %s.hdr\n',fileprefix); + error(msg); +else + if verbose, fprintf('...writing %s Analyze header.\n',machine); end + write_header(fid,avw,verbose); +end + +if verbose, t=toc; fprintf('...done (%5.2f sec).\n\n',t); end + +return + + + + + +%---------------------------------------------------------------------------- + +function write_header(fid,avw,verbose) + + header_key(fid,avw.hdr.hk); + image_dimension(fid,avw.hdr.dime); + data_history(fid,avw.hdr.hist); + + % check the file size is 348 bytes + fbytes = ftell(fid); + fclose(fid); + if ~isequal(fbytes,348), + msg = sprintf('...file size is not 348 bytes!\n'); + warning(msg); + end + +return + +%---------------------------------------------------------------------------- + +function header_key(fid,hk) + + % Original header structures - ANALYZE 7.5 + % struct header_key /* header key */ + % { /* off + size */ + % int sizeof_hdr /* 0 + 4 */ + % char data_type[10]; /* 4 + 10 */ + % char db_name[18]; /* 14 + 18 */ + % int extents; /* 32 + 4 */ + % short int session_error; /* 36 + 2 */ + % char regular; /* 38 + 1 */ + % char hkey_un0; /* 39 + 1 */ + % }; /* total=40 bytes */ + + fseek(fid,0,'bof'); + + fwrite(fid, hk.sizeof_hdr(1), 'int32'); % must be 348! + + data_type = sprintf('%-10s',hk.data_type); % ensure it is 10 chars + fwrite(fid, hk.data_type(1:10), 'uchar'); + + db_name = sprintf('%-18s',hk.db_name); % ensure it is 18 chars + fwrite(fid, db_name(1:18), 'uchar'); + + fwrite(fid, hk.extents(1), 'int32'); + fwrite(fid, hk.session_error(1),'int16'); + + regular = sprintf('%1s',hk.regular); % ensure it is 1 char + fwrite(fid, regular(1), 'uchar'); % might be uint8 + + %hkey_un0 = sprintf('%1s',hk.hkey_un0); % ensure it is 1 char + %fwrite(fid, hkey_un0(1), 'uchar'); + fwrite(fid, hk.hkey_un0(1), 'uint8'); + + % >Would you set hkey_un0 as char or uint8? + % Really doesn't make any difference. As far as anyone here can remember, + % this was just to pad to an even byte boundary for that structure. I guess + % I'd suggest setting it to a uint8 value of 0 (i.e, truly zero-valued) so + % that it doesn't look like anything important! + % Denny + +return + +%---------------------------------------------------------------------------- + +function image_dimension(fid,dime) + + %struct image_dimension + % { /* off + size */ + % short int dim[8]; /* 0 + 16 */ + % char vox_units[4]; /* 16 + 4 */ + % char cal_units[8]; /* 20 + 8 */ + % short int unused1; /* 28 + 2 */ + % short int datatype; /* 30 + 2 */ + % short int bitpix; /* 32 + 2 */ + % short int dim_un0; /* 34 + 2 */ + % float pixdim[8]; /* 36 + 32 */ + % /* + % pixdim[] specifies the voxel dimensions: + % pixdim[1] - voxel width + % pixdim[2] - voxel height + % pixdim[3] - interslice distance + % ..etc + % */ + % float vox_offset; /* 68 + 4 */ + % float roi_scale; /* 72 + 4 */ + % float funused1; /* 76 + 4 */ + % float funused2; /* 80 + 4 */ + % float cal_max; /* 84 + 4 */ + % float cal_min; /* 88 + 4 */ + % int compressed; /* 92 + 4 */ + % int verified; /* 96 + 4 */ + % int glmax; /* 100 + 4 */ + % int glmin; /* 104 + 4 */ + % }; /* total=108 bytes */ + + fwrite(fid, dime.dim(1:8), 'int16'); + fwrite(fid, dime.vox_units(1:4),'uchar'); + fwrite(fid, dime.cal_units(1:8),'uchar'); + fwrite(fid, dime.unused1(1), 'int16'); + fwrite(fid, dime.datatype(1), 'int16'); + fwrite(fid, dime.bitpix(1), 'int16'); + fwrite(fid, dime.dim_un0(1), 'int16'); + fwrite(fid, dime.pixdim(1:8), 'float32'); + fwrite(fid, dime.vox_offset(1), 'float32'); + + % Ensure compatibility with SPM (according to MRIcro) + if dime.roi_scale == 0, dime.roi_scale = 0.00392157; end + fwrite(fid, dime.roi_scale(1), 'float32'); + + fwrite(fid, dime.funused1(1), 'float32'); + fwrite(fid, dime.funused2(1), 'float32'); + fwrite(fid, dime.cal_max(1), 'float32'); + fwrite(fid, dime.cal_min(1), 'float32'); + fwrite(fid, dime.compressed(1), 'int32'); + fwrite(fid, dime.verified(1), 'int32'); + fwrite(fid, dime.glmax(1), 'int32'); + fwrite(fid, dime.glmin(1), 'int32'); + +return + +%---------------------------------------------------------------------------- + +function data_history(fid,hist) + + % Original header structures - ANALYZE 7.5 + %struct data_history + % { /* off + size */ + % char descrip[80]; /* 0 + 80 */ + % char aux_file[24]; /* 80 + 24 */ + % char orient; /* 104 + 1 */ + % char originator[10]; /* 105 + 10 */ + % char generated[10]; /* 115 + 10 */ + % char scannum[10]; /* 125 + 10 */ + % char patient_id[10]; /* 135 + 10 */ + % char exp_date[10]; /* 145 + 10 */ + % char exp_time[10]; /* 155 + 10 */ + % char hist_un0[3]; /* 165 + 3 */ + % int views /* 168 + 4 */ + % int vols_added; /* 172 + 4 */ + % int start_field; /* 176 + 4 */ + % int field_skip; /* 180 + 4 */ + % int omax; /* 184 + 4 */ + % int omin; /* 188 + 4 */ + % int smax; /* 192 + 4 */ + % int smin; /* 196 + 4 */ + % }; /* total=200 bytes */ + + descrip = sprintf('%-80s', hist.descrip); % 80 chars + aux_file = sprintf('%-24s', hist.aux_file); % 24 chars + originator = sprintf('%-10s', hist.originator); % 10 chars + generated = sprintf('%-10s', hist.generated); % 10 chars + scannum = sprintf('%-10s', hist.scannum); % 10 chars + patient_id = sprintf('%-10s', hist.patient_id); % 10 chars + exp_date = sprintf('%-10s', hist.exp_date); % 10 chars + exp_time = sprintf('%-10s', hist.exp_time); % 10 chars + hist_un0 = sprintf( '%-3s', hist.hist_un0); % 3 chars + + % --- + % The following should not be necessary, but I actually + % found one instance where it was, so this totally anal + % retentive approach became necessary, despite the + % apparently elegant solution above to ensuring that variables + % are the right length. + + if length(descrip) < 80, + paddingN = 80-length(descrip); + padding = char(repmat(double(' '),1,paddingN)); + descrip = [descrip,padding]; + end + if length(aux_file) < 24, + paddingN = 24-length(aux_file); + padding = char(repmat(double(' '),1,paddingN)); + aux_file = [aux_file,padding]; + end + if length(originator) < 10, + paddingN = 10-length(originator); + padding = char(repmat(double(' '),1,paddingN)); + originator = [originator, padding]; + end + if length(generated) < 10, + paddingN = 10-length(generated); + padding = char(repmat(double(' '),1,paddingN)); + generated = [generated, padding]; + end + if length(scannum) < 10, + paddingN = 10-length(scannum); + padding = char(repmat(double(' '),1,paddingN)); + scannum = [scannum, padding]; + end + if length(patient_id) < 10, + paddingN = 10-length(patient_id); + padding = char(repmat(double(' '),1,paddingN)); + patient_id = [patient_id, padding]; + end + if length(exp_date) < 10, + paddingN = 10-length(exp_date); + padding = char(repmat(double(' '),1,paddingN)); + exp_date = [exp_date, padding]; + end + if length(exp_time) < 10, + paddingN = 10-length(exp_time); + padding = char(repmat(double(' '),1,paddingN)); + exp_time = [exp_time, padding]; + end + if length(hist_un0) < 10, + paddingN = 10-length(hist_un0); + padding = char(repmat(double(' '),1,paddingN)); + hist_un0 = [hist_un0, padding]; + end + + % -- if you thought that was anal, try this; + % -- lets check for unusual ASCII char values! + + if find(double(descrip)>128), + indexStrangeChar = find(double(descrip)>128); + descrip(indexStrangeChar) = ' '; + end + if find(double(aux_file)>128), + indexStrangeChar = find(double(aux_file)>128); + aux_file(indexStrangeChar) = ' '; + end + if find(double(originator)>128), + indexStrangeChar = find(double(originator)>128); + originator(indexStrangeChar) = ' '; + end + if find(double(generated)>128), + indexStrangeChar = find(double(generated)>128); + generated(indexStrangeChar) = ' '; + end + if find(double(scannum)>128), + indexStrangeChar = find(double(scannum)>128); + scannum(indexStrangeChar) = ' '; + end + if find(double(patient_id)>128), + indexStrangeChar = find(double(patient_id)>128); + patient_id(indexStrangeChar) = ' '; + end + if find(double(exp_date)>128), + indexStrangeChar = find(double(exp_date)>128); + exp_date(indexStrangeChar) = ' '; + end + if find(double(exp_time)>128), + indexStrangeChar = find(double(exp_time)>128); + exp_time(indexStrangeChar) = ' '; + end + if find(double(hist_un0)>128), + indexStrangeChar = find(double(hist_un0)>128); + hist_un0(indexStrangeChar) = ' '; + end + + + % --- finally, we write the fields + + fwrite(fid, descrip(1:80), 'uchar'); + fwrite(fid, aux_file(1:24), 'uchar'); + + + %orient = sprintf( '%1s', hist.orient); % 1 char + %fwrite(fid, orient(1), 'uchar'); + fwrite(fid, hist.orient(1), 'uint8'); % see note below on char + + fwrite(fid, originator(1:10), 'uchar'); + fwrite(fid, generated(1:10), 'uchar'); + fwrite(fid, scannum(1:10), 'uchar'); + fwrite(fid, patient_id(1:10), 'uchar'); + fwrite(fid, exp_date(1:10), 'uchar'); + fwrite(fid, exp_time(1:10), 'uchar'); + fwrite(fid, hist_un0(1:3), 'uchar'); + + fwrite(fid, hist.views(1), 'int32'); + fwrite(fid, hist.vols_added(1), 'int32'); + fwrite(fid, hist.start_field(1),'int32'); + fwrite(fid, hist.field_skip(1), 'int32'); + fwrite(fid, hist.omax(1), 'int32'); + fwrite(fid, hist.omin(1), 'int32'); + fwrite(fid, hist.smax(1), 'int32'); + fwrite(fid, hist.smin(1), 'int32'); + +return + + + +% Note on using char: +% The 'char orient' field in the header is intended to +% hold simply an 8-bit unsigned integer value, not the ASCII representation +% of the character for that value. A single 'char' byte is often used to +% represent an integer value in Analyze if the known value range doesn't +% go beyond 0-255 - saves a byte over a short int, which may not mean +% much in today's computing environments, but given that this format +% has been around since the early 1980's, saving bytes here and there on +% older systems was important! In this case, 'char' simply provides the +% byte of storage - not an indicator of the format for what is stored in +% this byte. Generally speaking, anytime a single 'char' is used, it is +% probably meant to hold an 8-bit integer value, whereas if this has +% been dimensioned as an array, then it is intended to hold an ASCII +% character string, even if that was only a single character. +% Denny + +% See other notes in avw_hdr_read diff --git a/external/fieldtrip/fileio/private/avw_img_read.m b/external/fieldtrip/fileio/private/avw_img_read.m new file mode 100644 index 0000000..ba17683 --- /dev/null +++ b/external/fieldtrip/fileio/private/avw_img_read.m @@ -0,0 +1,697 @@ +function [ avw, machine ] = avw_img_read(fileprefix,IMGorient,machine,verbose) + +% avw_img_read - read Analyze format data image (*.img) +% +% [ avw, machine ] = avw_img_read(fileprefix,[orient],[machine],[verbose]) +% +% fileprefix - a string, the filename without the .img extension +% +% orient - read a specified orientation, integer values: +% +% '', use header history orient field +% 0, transverse unflipped (LAS*) +% 1, coronal unflipped (LA*S) +% 2, sagittal unflipped (L*AS) +% 3, transverse flipped (LPS*) +% 4, coronal flipped (LA*I) +% 5, sagittal flipped (L*AI) +% +% where * follows the slice dimension and letters indicate +XYZ +% orientations (L left, R right, A anterior, P posterior, +% I inferior, & S superior). +% +% Some files may contain data in the 3-5 orientations, but this +% is unlikely. For more information about orientation, see the +% documentation at the end of this .m file. See also the +% AVW_FLIP function for orthogonal reorientation. +% +% machine - a string, see machineformat in fread for details. +% The default here is 'ieee-le' but the routine +% will automatically switch between little and big +% endian to read any such Analyze header. It +% reports the appropriate machine format and can +% return the machine value. +% +% verbose - the default is to output processing information to the command +% window. If verbose = 0, this will not happen. +% +% Returned values: +% +% avw.hdr - a struct with image data parameters. +% avw.img - a 3D matrix of image data (double precision). +% +% A returned 3D matrix will correspond with the +% default ANALYZE coordinate system, which +% is Left-handed: +% +% X-Y plane is Transverse +% X-Z plane is Coronal +% Y-Z plane is Sagittal +% +% X axis runs from patient right (low X) to patient Left (high X) +% Y axis runs from posterior (low Y) to Anterior (high Y) +% Z axis runs from inferior (low Z) to Superior (high Z) +% +% The function can read a 4D Analyze volume, but only if it is in the +% axial unflipped orientation. +% +% See also: avw_hdr_read (called by this function), +% avw_view, avw_write, avw_img_write, avw_flip +% + + +% $Revision: 883 $ $Date: 2009/01/14 09:24:45 $ + +% Licence: GNU GPL, no express or implied warranties +% History: 05/2002, Darren.Weber@flinders.edu.au +% The Analyze format is copyright +% (c) Copyright, 1986-1995 +% Biomedical Imaging Resource, Mayo Foundation +% 01/2003, Darren.Weber@flinders.edu.au +% - adapted for matlab v5 +% - revised all orientation information and handling +% after seeking further advice from AnalyzeDirect.com +% 03/2003, Darren.Weber@flinders.edu.au +% - adapted for -ve pixdim values (non standard Analyze) +% 07/2004, chodkowski@kennedykrieger.org, added ability to +% read volumes with dimensionality greather than 3. +% a >3D volume cannot be flipped. and error is thrown if a volume of +% greater than 3D (ie, avw.hdr.dime.dim(1) > 3) requests a data flip +% (ie, avw.hdr.hist.orient ~= 0 ). i pulled the transfer of read-in +% data (tmp) to avw.img out of any looping mechanism. looping is not +% necessary as the data is already in its correct orientation. using +% 'reshape' rather than looping should be faster but, more importantly, +% it allows the reading in of N-D volumes. See lines 270-280. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +% check if SPM2 is in path and if not add +hastoolbox('SPM2',1); + +if ~exist('IMGorient','var'), IMGorient = ''; end +if ~exist('machine','var'), machine = 'ieee-le'; end +if ~exist('verbose','var'), verbose = 1; end + +if isempty(IMGorient), IMGorient = ''; end +if isempty(machine), machine = 'ieee-le'; end +if isempty(verbose), verbose = 1; end + +if ~exist('fileprefix','var'), + msg = sprintf('...no input fileprefix - see help avw_img_read\n\n'); + error(msg); +end +if findstr('.hdr',fileprefix), + fileprefix = strrep(fileprefix,'.hdr',''); +end +if findstr('.img',fileprefix), + fileprefix = strrep(fileprefix,'.img',''); +end + +% MAIN + +% Read the file header +[ avw, machine ] = avw_hdr_read(fileprefix,machine,verbose); + +avw = read_image(avw,IMGorient,machine,verbose); + +return + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [ avw ] = read_image(avw,IMGorient,machine,verbose) + +fid = fopen(sprintf('%s.img',avw.fileprefix),'r',machine); +if fid < 0, + msg = sprintf('...cannot open file %s.img\n\n',avw.fileprefix); + error(msg); +end + +if verbose, + ver = '[$Revision: 883 $]'; + fprintf('\nAVW_IMG_READ [v%s]\n',ver(12:16)); tic; +end + +% short int bitpix; /* Number of bits per pixel; 1, 8, 16, 32, or 64. */ +% short int datatype /* Datatype for this image set */ +% /*Acceptable values for datatype are*/ +% #define DT_NONE 0 +% #define DT_UNKNOWN 0 /*Unknown data type*/ +% #define DT_BINARY 1 /*Binary ( 1 bit per voxel)*/ +% #define DT_UNSIGNED_CHAR 2 /*Unsigned character ( 8 bits per voxel)*/ +% #define DT_SIGNED_SHORT 4 /*Signed short (16 bits per voxel)*/ +% #define DT_SIGNED_INT 8 /*Signed integer (32 bits per voxel)*/ +% #define DT_FLOAT 16 /*Floating point (32 bits per voxel)*/ +% #define DT_COMPLEX 32 /*Complex (64 bits per voxel; 2 floating point numbers)/* +% #define DT_DOUBLE 64 /*Double precision (64 bits per voxel)*/ +% #define DT_RGB 128 /*A Red-Green-Blue datatype*/ +% #define DT_ALL 255 /*Undocumented*/ + +switch double(avw.hdr.dime.bitpix), + case 1, precision = 'bit1'; + case 8, precision = 'uchar'; + case 16, precision = 'int16'; + case 32, + if isequal(avw.hdr.dime.datatype, 8), precision = 'int32'; + else precision = 'single'; + end + case 64, precision = 'double'; + otherwise, + precision = 'uchar'; + if verbose, fprintf('...precision undefined in header, using ''uchar''\n'); end +end + +% read the whole .img file into matlab (faster) +if verbose, + fprintf('...reading %s Analyze %s image format.\n',machine,precision); +end +fseek(fid,0,'bof'); +% adjust for matlab version +ver = version; +ver = str2num(ver(1)); +if ver < 6, + tmp = fread(fid,inf,sprintf('%s',precision)); +else, + tmp = fread(fid,inf,sprintf('%s=>double',precision)); +end +fclose(fid); + +% Update the global min and max values +avw.hdr.dime.glmax = max(double(tmp)); +avw.hdr.dime.glmin = min(double(tmp)); + + +%--------------------------------------------------------------- +% Now partition the img data into xyz + +% --- first figure out the size of the image + +% short int dim[ ]; /* Array of the image dimensions */ +% +% dim[0] Number of dimensions in database; usually 4. +% dim[1] Image X dimension; number of pixels in an image row. +% dim[2] Image Y dimension; number of pixel rows in slice. +% dim[3] Volume Z dimension; number of slices in a volume. +% dim[4] Time points; number of volumes in database. + +PixelDim = double(avw.hdr.dime.dim(2)); +RowDim = double(avw.hdr.dime.dim(3)); +SliceDim = double(avw.hdr.dime.dim(4)); +TimeDim = double(avw.hdr.dime.dim(5)); + +PixelSz = double(avw.hdr.dime.pixdim(2)); +RowSz = double(avw.hdr.dime.pixdim(3)); +SliceSz = double(avw.hdr.dime.pixdim(4)); +TimeSz = double(avw.hdr.dime.pixdim(5)); + + + + +% ---- NON STANDARD ANALYZE... + +% Some Analyze files have been found to set -ve pixdim values, eg +% the MNI template avg152T1_brain in the FSL etc/standard folder, +% perhaps to indicate flipped orientation? If so, this code below +% will NOT handle the flip correctly! +if PixelSz < 0, + warning('X pixdim < 0 !!! resetting to abs(avw.hdr.dime.pixdim(2))'); + PixelSz = abs(PixelSz); + avw.hdr.dime.pixdim(2) = single(PixelSz); +end +if RowSz < 0, + warning('Y pixdim < 0 !!! resetting to abs(avw.hdr.dime.pixdim(3))'); + RowSz = abs(RowSz); + avw.hdr.dime.pixdim(3) = single(RowSz); +end +if SliceSz < 0, + warning('Z pixdim < 0 !!! resetting to abs(avw.hdr.dime.pixdim(4))'); + SliceSz = abs(SliceSz); + avw.hdr.dime.pixdim(4) = single(SliceSz); +end + +% ---- END OF NON STANDARD ANALYZE + + + + + +% --- check the orientation specification and arrange img accordingly +if ~isempty(IMGorient), + if ischar(IMGorient), + avw.hdr.hist.orient = uint8(str2num(IMGorient)); + else + avw.hdr.hist.orient = uint8(IMGorient); + end +end, + +if isempty(avw.hdr.hist.orient), + msg = [ '...unspecified avw.hdr.hist.orient, using default 0\n',... + ' (check image and try explicit IMGorient option).\n']; + fprintf(msg); + avw.hdr.hist.orient = uint8(0); +end + +% --- check if the orientation is to be flipped for a volume with more +% --- than 3 dimensions. this logic is currently unsupported so throw +% --- an error. volumes of any dimensionality may be read in *only* as +% --- unflipped, ie, avw.hdr.hist.orient == 0 +if ( TimeDim > 1 ) && (avw.hdr.hist.orient ~= 0 ), + msg = [ 'ERROR: This volume has more than 3 dimensions *and* ', ... + 'requires flipping the data. Flipping is not supported ', ... + 'for volumes with dimensionality greater than 3. Set ', ... + 'avw.hdr.hist.orient = 0 and flip your volume after ', ... + 'calling this function' ]; + msg = sprintf( '%s (%s).', msg, mfilename ); + error( msg ); +end + +switch double(avw.hdr.hist.orient), + + case 0, % transverse unflipped + + % orient = 0: The primary orientation of the data on disk is in the + % transverse plane relative to the object scanned. Most commonly, the fastest + % moving index through the voxels that are part of this transverse image would + % span the right-left extent of the structure imaged, with the next fastest + % moving index spanning the posterior-anterior extent of the structure. This + % 'orient' flag would indicate to Analyze that this data should be placed in + % the X-Y plane of the 3D Analyze Coordinate System, with the Z dimension + % being the slice direction. + + % For the 'transverse unflipped' type, the voxels are stored with + % Pixels in 'x' axis (varies fastest) - from patient right to left + % Rows in 'y' axis - from patient posterior to anterior + % Slices in 'z' axis - from patient inferior to superior + + if verbose, fprintf('...reading axial unflipped orientation\n'); end + + % -- This code will handle nD files + dims = double( avw.hdr.dime.dim(2:end) ); + % replace dimensions of 0 with 1 to be used in reshape + idx = find( dims == 0 ); + dims( idx ) = 1; + avw.img = reshape( tmp, dims ); + + % -- The code above replaces this + % avw.img = zeros(PixelDim,RowDim,SliceDim); + % + % n = 1; + % x = 1:PixelDim; + % for z = 1:SliceDim, + % for y = 1:RowDim, + % % load Y row of X values into Z slice avw.img + % avw.img(x,y,z) = tmp(n:n+(PixelDim-1)); + % n = n + PixelDim; + % end + % end + + + % no need to rearrange avw.hdr.dime.dim or avw.hdr.dime.pixdim + + +case 1, % coronal unflipped + + % orient = 1: The primary orientation of the data on disk is in the coronal + % plane relative to the object scanned. Most commonly, the fastest moving + % index through the voxels that are part of this coronal image would span the + % right-left extent of the structure imaged, with the next fastest moving + % index spanning the inferior-superior extent of the structure. This 'orient' + % flag would indicate to Analyze that this data should be placed in the X-Z + % plane of the 3D Analyze Coordinate System, with the Y dimension being the + % slice direction. + + % For the 'coronal unflipped' type, the voxels are stored with + % Pixels in 'x' axis (varies fastest) - from patient right to left + % Rows in 'z' axis - from patient inferior to superior + % Slices in 'y' axis - from patient posterior to anterior + + if verbose, fprintf('...reading coronal unflipped orientation\n'); end + + avw.img = zeros(PixelDim,SliceDim,RowDim); + + n = 1; + x = 1:PixelDim; + for y = 1:SliceDim, + for z = 1:RowDim, + % load Z row of X values into Y slice avw.img + avw.img(x,y,z) = tmp(n:n+(PixelDim-1)); + n = n + PixelDim; + end + end + + % rearrange avw.hdr.dime.dim or avw.hdr.dime.pixdim + avw.hdr.dime.dim(2:4) = int16([PixelDim,SliceDim,RowDim]); + avw.hdr.dime.pixdim(2:4) = single([PixelSz,SliceSz,RowSz]); + + + case 2, % sagittal unflipped + + % orient = 2: The primary orientation of the data on disk is in the sagittal + % plane relative to the object scanned. Most commonly, the fastest moving + % index through the voxels that are part of this sagittal image would span the + % posterior-anterior extent of the structure imaged, with the next fastest + % moving index spanning the inferior-superior extent of the structure. This + % 'orient' flag would indicate to Analyze that this data should be placed in + % the Y-Z plane of the 3D Analyze Coordinate System, with the X dimension + % being the slice direction. + + % For the 'sagittal unflipped' type, the voxels are stored with + % Pixels in 'y' axis (varies fastest) - from patient posterior to anterior + % Rows in 'z' axis - from patient inferior to superior + % Slices in 'x' axis - from patient right to left + + if verbose, fprintf('...reading sagittal unflipped orientation\n'); end + + avw.img = zeros(SliceDim,PixelDim,RowDim); + + n = 1; + y = 1:PixelDim; % posterior to anterior (fastest) + + for x = 1:SliceDim, % right to left (slowest) + for z = 1:RowDim, % inferior to superior + + % load Z row of Y values into X slice avw.img + avw.img(x,y,z) = tmp(n:n+(PixelDim-1)); + n = n + PixelDim; + end + end + + % rearrange avw.hdr.dime.dim or avw.hdr.dime.pixdim + avw.hdr.dime.dim(2:4) = int16([SliceDim,PixelDim,RowDim]); + avw.hdr.dime.pixdim(2:4) = single([SliceSz,PixelSz,RowSz]); + + + %-------------------------------------------------------------------------------- + % Orient values 3-5 have the second index reversed in order, essentially + % 'flipping' the images relative to what would most likely become the vertical + % axis of the displayed image. + %-------------------------------------------------------------------------------- + + case 3, % transverse/axial flipped + + % orient = 3: The primary orientation of the data on disk is in the + % transverse plane relative to the object scanned. Most commonly, the fastest + % moving index through the voxels that are part of this transverse image would + % span the right-left extent of the structure imaged, with the next fastest + % moving index spanning the *anterior-posterior* extent of the structure. This + % 'orient' flag would indicate to Analyze that this data should be placed in + % the X-Y plane of the 3D Analyze Coordinate System, with the Z dimension + % being the slice direction. + + % For the 'transverse flipped' type, the voxels are stored with + % Pixels in 'x' axis (varies fastest) - from patient right to Left + % Rows in 'y' axis - from patient anterior to Posterior * + % Slices in 'z' axis - from patient inferior to Superior + + if verbose, fprintf('...reading axial flipped (+Y from Anterior to Posterior)\n'); end + + avw.img = zeros(PixelDim,RowDim,SliceDim); + + n = 1; + x = 1:PixelDim; + for z = 1:SliceDim, + for y = RowDim:-1:1, % flip in Y, read A2P file into P2A 3D matrix + + % load a flipped Y row of X values into Z slice avw.img + avw.img(x,y,z) = tmp(n:n+(PixelDim-1)); + n = n + PixelDim; + end + end + + % no need to rearrange avw.hdr.dime.dim or avw.hdr.dime.pixdim + + + case 4, % coronal flipped + + % orient = 4: The primary orientation of the data on disk is in the coronal + % plane relative to the object scanned. Most commonly, the fastest moving + % index through the voxels that are part of this coronal image would span the + % right-left extent of the structure imaged, with the next fastest moving + % index spanning the *superior-inferior* extent of the structure. This 'orient' + % flag would indicate to Analyze that this data should be placed in the X-Z + % plane of the 3D Analyze Coordinate System, with the Y dimension being the + % slice direction. + + % For the 'coronal flipped' type, the voxels are stored with + % Pixels in 'x' axis (varies fastest) - from patient right to Left + % Rows in 'z' axis - from patient superior to Inferior* + % Slices in 'y' axis - from patient posterior to Anterior + + if verbose, fprintf('...reading coronal flipped (+Z from Superior to Inferior)\n'); end + + avw.img = zeros(PixelDim,SliceDim,RowDim); + + n = 1; + x = 1:PixelDim; + for y = 1:SliceDim, + for z = RowDim:-1:1, % flip in Z, read S2I file into I2S 3D matrix + + % load a flipped Z row of X values into Y slice avw.img + avw.img(x,y,z) = tmp(n:n+(PixelDim-1)); + n = n + PixelDim; + end + end + + % rearrange avw.hdr.dime.dim or avw.hdr.dime.pixdim + avw.hdr.dime.dim(2:4) = int16([PixelDim,SliceDim,RowDim]); + avw.hdr.dime.pixdim(2:4) = single([PixelSz,SliceSz,RowSz]); + + + case 5, % sagittal flipped + + % orient = 5: The primary orientation of the data on disk is in the sagittal + % plane relative to the object scanned. Most commonly, the fastest moving + % index through the voxels that are part of this sagittal image would span the + % posterior-anterior extent of the structure imaged, with the next fastest + % moving index spanning the *superior-inferior* extent of the structure. This + % 'orient' flag would indicate to Analyze that this data should be placed in + % the Y-Z plane of the 3D Analyze Coordinate System, with the X dimension + % being the slice direction. + + % For the 'sagittal flipped' type, the voxels are stored with + % Pixels in 'y' axis (varies fastest) - from patient posterior to Anterior + % Rows in 'z' axis - from patient superior to Inferior* + % Slices in 'x' axis - from patient right to Left + + if verbose, fprintf('...reading sagittal flipped (+Z from Superior to Inferior)\n'); end + + avw.img = zeros(SliceDim,PixelDim,RowDim); + + n = 1; + y = 1:PixelDim; + + for x = 1:SliceDim, + for z = RowDim:-1:1, % flip in Z, read S2I file into I2S 3D matrix + + % load a flipped Z row of Y values into X slice avw.img + avw.img(x,y,z) = tmp(n:n+(PixelDim-1)); + n = n + PixelDim; + end + end + + % rearrange avw.hdr.dime.dim or avw.hdr.dime.pixdim + avw.hdr.dime.dim(2:4) = int16([SliceDim,PixelDim,RowDim]); + avw.hdr.dime.pixdim(2:4) = single([SliceSz,PixelSz,RowSz]); + + otherwise + + error('unknown value in avw.hdr.hist.orient, try explicit IMGorient option.'); + +end + +if verbose, t=toc; fprintf('...done (%5.2f sec).\n\n',t); end + +return + + + + +% This function attempts to read the orientation of the +% Analyze file according to the hdr.hist.orient field of the +% header. Unfortunately, this field is optional and not +% all programs will set it correctly, so there is no guarantee, +% that the data loaded will be correctly oriented. If necessary, +% experiment with the 'orient' option to read the .img +% data into the 3D matrix of avw.img as preferred. +% + +% (Conventions gathered from e-mail with support@AnalyzeDirect.com) +% +% 0 transverse unflipped +% X direction first, progressing from patient right to left, +% Y direction second, progressing from patient posterior to anterior, +% Z direction third, progressing from patient inferior to superior. +% 1 coronal unflipped +% X direction first, progressing from patient right to left, +% Z direction second, progressing from patient inferior to superior, +% Y direction third, progressing from patient posterior to anterior. +% 2 sagittal unflipped +% Y direction first, progressing from patient posterior to anterior, +% Z direction second, progressing from patient inferior to superior, +% X direction third, progressing from patient right to left. +% 3 transverse flipped +% X direction first, progressing from patient right to left, +% Y direction second, progressing from patient anterior to posterior, +% Z direction third, progressing from patient inferior to superior. +% 4 coronal flipped +% X direction first, progressing from patient right to left, +% Z direction second, progressing from patient superior to inferior, +% Y direction third, progressing from patient posterior to anterior. +% 5 sagittal flipped +% Y direction first, progressing from patient posterior to anterior, +% Z direction second, progressing from patient superior to inferior, +% X direction third, progressing from patient right to left. + + +%---------------------------------------------------------------------------- +% From ANALYZE documentation... +% +% The ANALYZE coordinate system has an origin in the lower left +% corner. That is, with the subject lying supine, the coordinate +% origin is on the right side of the body (x), at the back (y), +% and at the feet (z). This means that: +% +% +X increases from right (R) to left (L) +% +Y increases from the back (posterior,P) to the front (anterior, A) +% +Z increases from the feet (inferior,I) to the head (superior, S) +% +% The LAS orientation is the radiological convention, where patient +% left is on the image right. The alternative neurological +% convention is RAS (also Talairach convention). +% +% A major advantage of the Analzye origin convention is that the +% coordinate origin of each orthogonal orientation (transverse, +% coronal, and sagittal) lies in the lower left corner of the +% slice as it is displayed. +% +% Orthogonal slices are numbered from one to the number of slices +% in that orientation. For example, a volume (x, y, z) dimensioned +% 128, 256, 48 has: +% +% 128 sagittal slices numbered 1 through 128 (X) +% 256 coronal slices numbered 1 through 256 (Y) +% 48 transverse slices numbered 1 through 48 (Z) +% +% Pixel coordinates are made with reference to the slice numbers from +% which the pixels come. Thus, the first pixel in the volume is +% referenced p(1,1,1) and not at p(0,0,0). +% +% Transverse slices are in the XY plane (also known as axial slices). +% Sagittal slices are in the ZY plane. +% Coronal slices are in the ZX plane. +% +%---------------------------------------------------------------------------- + + +%---------------------------------------------------------------------------- +% E-mail from support@AnalyzeDirect.com +% +% The 'orient' field in the data_history structure specifies the primary +% orientation of the data as it is stored in the file on disk. This usually +% corresponds to the orientation in the plane of acquisition, given that this +% would correspond to the order in which the data is written to disk by the +% scanner or other software application. As you know, this field will contain +% the values: +% +% orient = 0 transverse unflipped +% 1 coronal unflipped +% 2 sagittal unflipped +% 3 transverse flipped +% 4 coronal flipped +% 5 sagittal flipped +% +% It would be vary rare that you would ever encounter any old Analyze 7.5 +% files that contain values of 'orient' which indicate that the data has been +% 'flipped'. The 'flipped flag' values were really only used internal to +% Analyze to precondition data for fast display in the Movie module, where the +% images were actually flipped vertically in order to accommodate the raster +% paint order on older graphics devices. The only cases you will encounter +% will have values of 0, 1, or 2. +% +% As mentioned, the 'orient' flag only specifies the primary orientation of +% data as stored in the disk file itself. It has nothing to do with the +% representation of the data in the 3D Analyze coordinate system, which always +% has a fixed representation to the data. The meaning of the 'orient' values +% should be interpreted as follows: +% +% orient = 0: The primary orientation of the data on disk is in the +% transverse plane relative to the object scanned. Most commonly, the fastest +% moving index through the voxels that are part of this transverse image would +% span the right-left extent of the structure imaged, with the next fastest +% moving index spanning the posterior-anterior extent of the structure. This +% 'orient' flag would indicate to Analyze that this data should be placed in +% the X-Y plane of the 3D Analyze Coordinate System, with the Z dimension +% being the slice direction. +% +% orient = 1: The primary orientation of the data on disk is in the coronal +% plane relative to the object scanned. Most commonly, the fastest moving +% index through the voxels that are part of this coronal image would span the +% right-left extent of the structure imaged, with the next fastest moving +% index spanning the inferior-superior extent of the structure. This 'orient' +% flag would indicate to Analyze that this data should be placed in the X-Z +% plane of the 3D Analyze Coordinate System, with the Y dimension being the +% slice direction. +% +% orient = 2: The primary orientation of the data on disk is in the sagittal +% plane relative to the object scanned. Most commonly, the fastest moving +% index through the voxels that are part of this sagittal image would span the +% posterior-anterior extent of the structure imaged, with the next fastest +% moving index spanning the inferior-superior extent of the structure. This +% 'orient' flag would indicate to Analyze that this data should be placed in +% the Y-Z plane of the 3D Analyze Coordinate System, with the X dimension +% being the slice direction. +% +% Orient values 3-5 have the second index reversed in order, essentially +% 'flipping' the images relative to what would most likely become the vertical +% axis of the displayed image. +% +% Hopefully you understand the difference between the indication this 'orient' +% flag has relative to data stored on disk and the full 3D Analyze Coordinate +% System for data that is managed as a volume image. As mentioned previously, +% the orientation of patient anatomy in the 3D Analyze Coordinate System has a +% fixed orientation relative to each of the orthogonal axes. This orientation +% is completely described in the information that is attached, but the basics +% are: +% +% Left-handed coordinate system +% +% X-Y plane is Transverse +% X-Z plane is Coronal +% Y-Z plane is Sagittal +% +% X axis runs from patient right (low X) to patient left (high X) +% Y axis runs from posterior (low Y) to anterior (high Y) +% Z axis runs from inferior (low Z) to superior (high Z) +% +%---------------------------------------------------------------------------- + + + +%---------------------------------------------------------------------------- +% SPM2 NOTES from spm2 webpage: One thing to watch out for is the image +% orientation. The proper Analyze format uses a left-handed co-ordinate +% system, whereas Talairach uses a right-handed one. In SPM99, images were +% flipped at the spatial normalisation stage (from one co-ordinate system +% to the other). In SPM2b, a different approach is used, so that either a +% left- or right-handed co-ordinate system is used throughout. The SPM2b +% program is told about the handedness that the images are stored with by +% the spm_flip_analyze_images.m function and the defaults.analyze.flip +% parameter that is specified in the spm_defaults.m file. These files are +% intended to be customised for each site. If you previously used SPM99 +% and your images were flipped during spatial normalisation, then set +% defaults.analyze.flip=1. If no flipping took place, then set +% defaults.analyze.flip=0. Check that when using the Display facility +% (possibly after specifying some rigid-body rotations) that: +% +% 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. +%---------------------------------------------------------------------------- diff --git a/external/fieldtrip/fileio/private/avw_img_write.m b/external/fieldtrip/fileio/private/avw_img_write.m new file mode 100644 index 0000000..4d8f274 --- /dev/null +++ b/external/fieldtrip/fileio/private/avw_img_write.m @@ -0,0 +1,412 @@ +function avw_img_write(avw, fileprefix, IMGorient, machine, verbose) + +% avw_img_write - write Analyze image files (*.img) +% +% avw_img_write(avw,fileprefix,[IMGorient],[machine],[verbose]) +% +% avw.img - a 3D matrix of image data (double precision). +% avw.hdr - a struct with image data parameters. If +% not empty, this function calls avw_hdr_write. +% +% fileprefix - a string, the filename without the .img +% extension. If empty, may use avw.fileprefix +% +% IMGorient - optional int, force writing of specified +% orientation, with values: +% +% [], if empty, will use avw.hdr.hist.orient field +% 0, transverse/axial unflipped (default, radiological) +% 1, coronal unflipped +% 2, sagittal unflipped +% 3, transverse/axial flipped, left to right +% 4, coronal flipped, anterior to posterior +% 5, sagittal flipped, superior to inferior +% +% This function will set avw.hdr.hist.orient and write the +% image data in a corresponding order. This function is +% in alpha development, so it has not been exhaustively +% tested (07/2003). See avw_img_read for more information +% and documentation on the orientation option. +% Orientations 3-5 are NOT recommended! They are part +% of the Analyze format, but only used in Analyze +% for faster raster graphics during movies. +% +% machine - a string, see machineformat in fread for details. +% The default here is 'ieee-le'. +% +% verbose - the default is to output processing information to the command +% window. If verbose = 0, this will not happen. +% +% Tip: to change the data type, set avw.hdr.dime.datatype to: +% +% 1 Binary ( 1 bit per voxel) +% 2 Unsigned character ( 8 bits per voxel) +% 4 Signed short ( 16 bits per voxel) +% 8 Signed integer ( 32 bits per voxel) +% 16 Floating point ( 32 bits per voxel) +% 32 Complex, 2 floats ( 64 bits per voxel), not supported +% 64 Double precision ( 64 bits per voxel) +% 128 Red-Green-Blue (128 bits per voxel), not supported +% +% See also: avw_write, avw_hdr_write, +% avw_read, avw_hdr_read, avw_img_read, avw_view +% + +% $Revision: 883 $ $Date: 2009/01/14 09:24:45 $ + +% Licence: GNU GPL, no express or implied warranties +% History: 05/2002, Darren.Weber@flinders.edu.au +% The Analyze format is copyright +% (c) Copyright, 1986-1995 +% Biomedical Imaging Resource, Mayo Foundation +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%------------------------------------------------------------------------ +% Check inputs + +if ~exist('avw','var'), + doc avw_img_write; + error('...no input avw.'); +elseif isempty(avw), + error('...empty input avw.'); +elseif ~isfield(avw,'img'), + error('...empty input avw.img'); +end + +if ~exist('fileprefix','var'), + if isfield(avw,'fileprefix'), + if ~isempty(avw.fileprefix), + fileprefix = avw.fileprefix; + else + fileprefix = []; + end + else + fileprefix = []; + end +end +if isempty(fileprefix), + [fileprefix, pathname, filterindex] = uiputfile('*.hdr','Specify an output Analyze .hdr file'); + if pathname, cd(pathname); end + if ~fileprefix, + doc avw_img_write; + error('no output .hdr file specified'); + end +end + +if findstr('.hdr',fileprefix), +% fprintf('AVW_IMG_WRITE: Removing .hdr extension from ''%s''\n',fileprefix); + fileprefix = strrep(fileprefix,'.hdr',''); +end +if findstr('.img',fileprefix), +% fprintf('AVW_IMG_WRITE: Removing .img extension from ''%s''\n',fileprefix); + fileprefix = strrep(fileprefix,'.img',''); +end + +if ~exist('IMGorient','var'), IMGorient = ''; end +if ~exist('machine','var'), machine = 'ieee-le'; end +if ~exist('verbose','var'), verbose = 1; end + +if isempty(IMGorient), IMGorient = ''; end +if isempty(machine), machine = 'ieee-le'; end +if isempty(verbose), verbose = 1; end + + + +%------------------------------------------------------------------------ +% MAIN +if verbose, + version = '[$Revision: 883 $]'; + fprintf('\nAVW_IMG_WRITE [v%s]\n',version(12:16)); tic; +end + +fid = fopen(sprintf('%s.img',fileprefix),'w',machine); +if fid < 0, + msg = sprintf('Cannot open file %s.img\n',fileprefix); + error(msg); +else + avw = write_image(fid,avw,fileprefix,IMGorient,machine,verbose); +end + +if verbose, + t=toc; fprintf('...done (%5.2f sec).\n\n',t); +end + +% MUST write header after the image, to ensure any +% orientation changes during image write are saved +% in the header +avw_hdr_write(avw,fileprefix,machine,verbose); + +return + + + + +%----------------------------------------------------------------------------------- + +function avw = write_image(fid,avw,fileprefix,IMGorient,machine,verbose) + +% short int bitpix; /* Number of bits per pixel; 1, 8, 16, 32, or 64. */ +% short int datatype /* Datatype for this image set */ +% /*Acceptable values for datatype are*/ +% #define DT_NONE 0 +% #define DT_UNKNOWN 0 /*Unknown data type*/ +% #define DT_BINARY 1 /*Binary ( 1 bit per voxel)*/ +% #define DT_UNSIGNED_CHAR 2 /*Unsigned character ( 8 bits per voxel)*/ +% #define DT_SIGNED_SHORT 4 /*Signed short (16 bits per voxel)*/ +% #define DT_SIGNED_INT 8 /*Signed integer (32 bits per voxel)*/ +% #define DT_FLOAT 16 /*Floating point (32 bits per voxel)*/ +% #define DT_COMPLEX 32 /*Complex,2 floats (64 bits per voxel)/* +% #define DT_DOUBLE 64 /*Double precision (64 bits per voxel)*/ +% #define DT_RGB 128 /*A Red-Green-Blue datatype*/ +% #define DT_ALL 255 /*Undocumented*/ + +switch double(avw.hdr.dime.datatype), +case 1, + avw.hdr.dime.bitpix = int16( 1); precision = 'bit1'; +case 2, + avw.hdr.dime.bitpix = int16( 8); precision = 'uchar'; +case 4, + avw.hdr.dime.bitpix = int16(16); precision = 'int16'; +case 8, + avw.hdr.dime.bitpix = int16(32); precision = 'int32'; +case 16, + avw.hdr.dime.bitpix = int16(32); precision = 'single'; +case 32, + error('...complex datatype not yet supported.\n'); +case 64, + avw.hdr.dime.bitpix = int16(64); precision = 'double'; +case 128, + error('...RGB datatype not yet supported.\n'); +otherwise + warning('...unknown datatype, using type 16 (32 bit floats).\n'); + avw.hdr.dime.datatype = int16(16); + avw.hdr.dime.bitpix = int16(32); precision = 'single'; +end + + +% write the .img file, depending on the .img orientation +if verbose, + fprintf('...writing %s precision Analyze image (%s).\n',precision,machine); +end + +fseek(fid,0,'bof'); + +% The standard image orientation is axial unflipped +if isempty(avw.hdr.hist.orient), + msg = [ '...avw.hdr.hist.orient ~= 0.\n',... + ' This function assumes the input avw.img is\n',... + ' in axial unflipped orientation in memory. This is\n',... + ' created by the avw_img_read function, which converts\n',... + ' any input file image to axial unflipped in memory.\n']; + warning(msg) +end + +if isempty(IMGorient), + if verbose, + fprintf('...no IMGorient specified, using avw.hdr.hist.orient value.\n'); + end + IMGorient = double(avw.hdr.hist.orient); +end + +if ~isfinite(IMGorient), + if verbose, + fprintf('...IMGorient is not finite!\n'); + end + IMGorient = 99; +end + +switch IMGorient, + +case 0, % transverse/axial unflipped + + % For the 'transverse unflipped' type, the voxels are stored with + % Pixels in 'x' axis (varies fastest) - from patient right to left + % Rows in 'y' axis - from patient posterior to anterior + % Slices in 'z' axis - from patient inferior to superior + + if verbose, fprintf('...writing axial unflipped\n'); end + + avw.hdr.hist.orient = uint8(0); + + SliceDim = double(avw.hdr.dime.dim(4)); % z + RowDim = double(avw.hdr.dime.dim(3)); % y + PixelDim = double(avw.hdr.dime.dim(2)); % x + SliceSz = double(avw.hdr.dime.pixdim(4)); + RowSz = double(avw.hdr.dime.pixdim(3)); + PixelSz = double(avw.hdr.dime.pixdim(2)); + + x = 1:PixelDim; + for z = 1:SliceDim, + for y = 1:RowDim, + fwrite(fid,avw.img(x,y,z),precision); + end + end + +case 1, % coronal unflipped + + % For the 'coronal unflipped' type, the voxels are stored with + % Pixels in 'x' axis (varies fastest) - from patient right to left + % Rows in 'z' axis - from patient inferior to superior + % Slices in 'y' axis - from patient posterior to anterior + + if verbose, fprintf('...writing coronal unflipped\n'); end + + avw.hdr.hist.orient = uint8(1); + + SliceDim = double(avw.hdr.dime.dim(3)); % y + RowDim = double(avw.hdr.dime.dim(4)); % z + PixelDim = double(avw.hdr.dime.dim(2)); % x + SliceSz = double(avw.hdr.dime.pixdim(3)); + RowSz = double(avw.hdr.dime.pixdim(4)); + PixelSz = double(avw.hdr.dime.pixdim(2)); + + x = 1:PixelDim; + for y = 1:SliceDim, + for z = 1:RowDim, + fwrite(fid,avw.img(x,y,z),precision); + end + end + +case 2, % sagittal unflipped + + % For the 'sagittal unflipped' type, the voxels are stored with + % Pixels in 'y' axis (varies fastest) - from patient posterior to anterior + % Rows in 'z' axis - from patient inferior to superior + % Slices in 'x' axis - from patient right to left + + if verbose, fprintf('...writing sagittal unflipped\n'); end + + avw.hdr.hist.orient = uint8(2); + + SliceDim = double(avw.hdr.dime.dim(2)); % x + RowDim = double(avw.hdr.dime.dim(4)); % z + PixelDim = double(avw.hdr.dime.dim(3)); % y + SliceSz = double(avw.hdr.dime.pixdim(2)); + RowSz = double(avw.hdr.dime.pixdim(4)); + PixelSz = double(avw.hdr.dime.pixdim(3)); + + y = 1:PixelDim; + for x = 1:SliceDim, + for z = 1:RowDim, + fwrite(fid,avw.img(x,y,z),precision); + end + end + +case 3, % transverse/axial flipped + + % For the 'transverse flipped' type, the voxels are stored with + % Pixels in 'x' axis (varies fastest) - from patient right to left + % Rows in 'y' axis - from patient anterior to posterior* + % Slices in 'z' axis - from patient inferior to superior + + if verbose, + fprintf('...writing axial flipped (+Y from Anterior to Posterior)\n'); + end + + avw.hdr.hist.orient = uint8(3); + + SliceDim = double(avw.hdr.dime.dim(4)); % z + RowDim = double(avw.hdr.dime.dim(3)); % y + PixelDim = double(avw.hdr.dime.dim(2)); % x + SliceSz = double(avw.hdr.dime.pixdim(4)); + RowSz = double(avw.hdr.dime.pixdim(3)); + PixelSz = double(avw.hdr.dime.pixdim(2)); + + x = 1:PixelDim; + for z = 1:SliceDim, + for y = RowDim:-1:1, % flipped in Y + fwrite(fid,avw.img(x,y,z),precision); + end + end + +case 4, % coronal flipped + + % For the 'coronal flipped' type, the voxels are stored with + % Pixels in 'x' axis (varies fastest) - from patient right to left + % Rows in 'z' axis - from patient inferior to superior + % Slices in 'y' axis - from patient anterior to posterior + + if verbose, + fprintf('...writing coronal flipped (+Z from Superior to Inferior)\n'); + end + + avw.hdr.hist.orient = uint8(4); + + SliceDim = double(avw.hdr.dime.dim(3)); % y + RowDim = double(avw.hdr.dime.dim(4)); % z + PixelDim = double(avw.hdr.dime.dim(2)); % x + SliceSz = double(avw.hdr.dime.pixdim(3)); + RowSz = double(avw.hdr.dime.pixdim(4)); + PixelSz = double(avw.hdr.dime.pixdim(2)); + + x = 1:PixelDim; + for y = 1:SliceDim, + for z = RowDim:-1:1, + fwrite(fid,avw.img(x,y,z),precision); + end + end + +case 5, % sagittal flipped + + % For the 'sagittal flipped' type, the voxels are stored with + % Pixels in 'y' axis (varies fastest) - from patient posterior to anterior + % Rows in 'z' axis - from patient superior to inferior + % Slices in 'x' axis - from patient right to left + + if verbose, + fprintf('...writing sagittal flipped (+Z from Superior to Inferior)\n'); + end + + avw.hdr.hist.orient = uint8(5); + + SliceDim = double(avw.hdr.dime.dim(2)); % x + RowDim = double(avw.hdr.dime.dim(4)); % z + PixelDim = double(avw.hdr.dime.dim(3)); % y + SliceSz = double(avw.hdr.dime.pixdim(2)); + RowSz = double(avw.hdr.dime.pixdim(4)); + PixelSz = double(avw.hdr.dime.pixdim(3)); + + y = 1:PixelDim; + for x = 1:SliceDim, + for z = RowDim:-1:1, % superior to inferior + fwrite(fid,avw.img(x,y,z),precision); + end + end + +otherwise, % transverse/axial unflipped + + % For the 'transverse unflipped' type, the voxels are stored with + % Pixels in 'x' axis (varies fastest) - from patient right to left + % Rows in 'y' axis - from patient posterior to anterior + % Slices in 'z' axis - from patient inferior to superior + + if verbose, + fprintf('...unknown orientation specified, assuming default axial unflipped\n'); + end + + avw.hdr.hist.orient = uint8(0); + + SliceDim = double(avw.hdr.dime.dim(4)); % z + RowDim = double(avw.hdr.dime.dim(3)); % y + PixelDim = double(avw.hdr.dime.dim(2)); % x + SliceSz = double(avw.hdr.dime.pixdim(4)); + RowSz = double(avw.hdr.dime.pixdim(3)); + PixelSz = double(avw.hdr.dime.pixdim(2)); + + x = 1:PixelDim; + for z = 1:SliceDim, + for y = 1:RowDim, + fwrite(fid,avw.img(x,y,z),precision); + end + end + +end + +fclose(fid); + +% Update the header +avw.hdr.dime.dim(2:4) = int16([PixelDim,RowDim,SliceDim]); +avw.hdr.dime.pixdim(2:4) = single([PixelSz,RowSz,SliceSz]); + +return diff --git a/external/fieldtrip/fileio/private/bigendian.m b/external/fieldtrip/fileio/private/bigendian.m new file mode 100644 index 0000000..aff84b1 --- /dev/null +++ b/external/fieldtrip/fileio/private/bigendian.m @@ -0,0 +1,33 @@ +function val = bigendian; + +% BIGENDIAN returns 1 (true) on a big endian machine, e.g. with a SUN Sparc +% or Apple G4 processor, or 0 (false) otherwise +% +% Example +% if (bigendian) +% % do something, e.g. swap some bytes +% end +% +% See also LITTLEENDIAN, SWAPBYTES, TYPECAST + +% Copyrigth (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: bigendian.m 945 2010-04-21 17:41:20Z roboos $ + +val = (typecast(uint8([0 1]), 'uint16')==1); diff --git a/external/fileio/private/bti2grad.m b/external/fieldtrip/fileio/private/bti2grad.m similarity index 79% rename from external/fileio/private/bti2grad.m rename to external/fieldtrip/fileio/private/bti2grad.m index 3569a4a..e856bc8 100644 --- a/external/fileio/private/bti2grad.m +++ b/external/fieldtrip/fileio/private/bti2grad.m @@ -17,51 +17,23 @@ % Copyright (C) 2008, Jan-Mathijs Schoffelen % -% $Log: bti2grad.m,v $ -% Revision 1.5 2009/10/07 09:45:50 jansch -% restructured the handling of balancing; balancing for data in which the -% weight table is of type 1 is still disabled, and balancing is applied for -% data with weight tables of type ~= 1 +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.4 2009/04/02 10:13:15 jansch -% disabled balancing for 148-sensor system (weight table version 1) since -% channel order is not known +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.3 2009/03/26 10:20:33 jansch -% added balancing based on the weight table used during acquisition. note that -% post acquisition computed weights using 4d software are not incorporated in -% the balancing of the gradiometers +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.2 2009/01/23 16:15:31 roboos -% removed ; after function declaration -% -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.8 2008/10/20 15:16:16 jansch -% removed the explicit sorting of the channels, this could cause problems -% later on. however, the sensors and references are block-wise sorted still -% -% Revision 1.7 2008/05/15 13:20:36 roboos -% updated documentation -% -% Revision 1.6 2008/05/14 10:20:37 jansch -% included tra-computation when inputting 'm4d' and 'xyz' headers -% -% Revision 1.5 2008/05/14 09:17:04 jansch -% included check for orientation in the case of gradiometers -% -% Revision 1.4 2008/05/14 08:02:40 jansch -% transposed grad.tra (was initially incorrect) -% -% Revision 1.3 2008/05/08 11:10:20 jansch -% implementation in analogy with ctf2grad +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: bti2grad.m 1058 2010-05-09 11:21:10Z roboos $ % for backward compatibility issues FIXME check whether anyone actually uses this code if isfield(hdr, 'Meg_pos'), @@ -226,9 +198,9 @@ if balanceflag, fprintf('applying digital weights in the gradiometer balancing matrix\n'); - grad.balance = balance; + grad.balance = balance; grad.balance.current = weights.position; - grad = apply_montage(grad, getfield(grad.balance, grad.balance.current)); + grad = ft_apply_montage(grad, getfield(grad.balance, grad.balance.current)); else fprintf('not applying digital weights in the gradiometer balancing matrix\n'); end diff --git a/external/fieldtrip/fileio/private/buffer.m b/external/fieldtrip/fileio/private/buffer.m new file mode 100644 index 0000000..fe6f9b4 --- /dev/null +++ b/external/fieldtrip/fileio/private/buffer.m @@ -0,0 +1,32 @@ +function [varargout] = buffer(varargin) + +% BUFFER manages and accesses the realtime data acquisition buffer +% This function is implented as a mex file. +% +% Use as +% retval = buffer(cmd, detail, host, port) +% +% To read data from a buffer server over the network +% hdr = buffer('get_hdr', [], host, port) +% dat = buffer('get_dat', datsel, host, port) +% evt = buffer('get_evt', evtsel, host, port) +% +% The selection for data and events should be zero-offset and contain +% datsel = [begsample endsample] +% evtsel = [begevent endevent ] +% +% To write data to a buffer server over the network +% buffer('put_hdr', hdr, host, port) +% buffer('put_dat', dat, host, port) +% buffer('put_evt', evt, host, port) +% +% To implement a local buffer server and have other clients +% connect to it at a specified network port +% buffer('tcpserver', 'init', [], port) +% buffer('tcpserver', 'exit', [], port) + +% Copyright (C) 2008-2010, Robert Oostenveld +% +% Subversion does not use the Log keyword, use 'svn log ' or 'svn -v log | less' to get detailled information + +error('Could not locate mex file'); diff --git a/external/fieldtrip/fileio/private/convert_units.m b/external/fieldtrip/fileio/private/convert_units.m new file mode 100644 index 0000000..08305ed --- /dev/null +++ b/external/fieldtrip/fileio/private/convert_units.m @@ -0,0 +1,205 @@ +function [obj] = ft_convert_units(obj, target); + +% FT_CONVERT_UNITS changes the geometrical dimension to the specified SI unit. +% The units of the input object is determined from the structure field +% object.unit, or is estimated based on the spatial extend of the structure, +% e.g. a volume conduction model of the head should be approximately 20 cm large. +% +% Use as +% [object] = ft_convert_units(object, target) +% +% The following input objects are supported +% simple dipole position +% electrode definition +% gradiometer array definition +% volume conductor definition +% dipole grid definition +% anatomical mri +% +% Possible target units are 'm', 'dm', 'cm ' or 'mm'. +% +% See FT_READ_VOL, FT_READ_SENS + +% Copyright (C) 2005-2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: convert_units.m 946 2010-04-21 17:51:16Z roboos $ + +% This function consists of three parts: +% 1) determine the input units +% 2) determine the requested scaling factor to obtain the output units +% 3) try to apply the scaling to the known geometrical elements in the input object + +% determine the unit-of-dimension of the input object +if isfield(obj, 'unit') + % use the units specified in the object + unit = obj.unit; +else + % try to estimate the units from the object + type = ft_voltype(obj); + if ~strcmp(type, 'unknown') + switch type + case 'infinite' + % there is nothing to do to convert the units + unit = target; + + case 'singlesphere' + size = obj.r; + + case 'multisphere' + size = median(obj.r); + + case 'concentric' + size = max(obj.r); + + case 'nolte' + size = norm(range(obj.bnd.pnt)); + + case {'bem' 'dipoli' 'bemcp' 'asa' 'avo'} + size = norm(range(obj.bnd(1).pnt)); + + otherwise + error('cannot determine geometrical units of volume conduction model'); + end % switch + + % determine the units by looking at the size + unit = ft_estimate_units(size); + + elseif ft_senstype(obj, 'meg') + size = norm(range(obj.pnt)); + unit = ft_estimate_units(size); + + elseif ft_senstype(obj, 'eeg') + size = norm(range(obj.pnt)); + unit = ft_estimate_units(size); + + elseif isfield(obj, 'pnt') && ~isempty(obj.pnt) + size = norm(range(obj.pnt)); + unit = ft_estimate_units(size); + + elseif isfield(obj, 'pos') && ~isempty(obj.pos) + size = norm(range(obj.pos)); + unit = ft_estimate_units(size); + + elseif isfield(obj, 'transform') && ~isempty(obj.transform) + % construct the corner points of the voxel grid in head coordinates + xi = 1:obj.dim(1); + yi = 1:obj.dim(2); + zi = 1:obj.dim(3); + pos = [ + xi( 1) yi( 1) zi( 1) + xi( 1) yi( 1) zi(end) + xi( 1) yi(end) zi( 1) + xi( 1) yi(end) zi(end) + xi(end) yi( 1) zi( 1) + xi(end) yi( 1) zi(end) + xi(end) yi(end) zi( 1) + xi(end) yi(end) zi(end) + ]; + pos = warp_apply(obj.transform, pos); + size = norm(range(pos)); + unit = ft_estimate_units(size); + + elseif isfield(obj, 'fid') && isfield(obj.fid, 'pnt') && ~isempty(obj.fid.pnt) + size = norm(range(obj.fid.pnt)); + unit = ft_estimate_units(size); + + else + error('cannot determine geometrical units'); + + end % recognized type of volume conduction model or sensor array +end % determine input units + +if nargin<2 + % just remember the units in the output and return + obj.unit = unit; + return +elseif strcmp(unit, target) + % no conversion is needed + obj.unit = unit; + return +end + +% give some information about the conversion +fprintf('converting units from ''%s'' to ''%s''\n', unit, target) + +if strcmp(unit, 'm') + unit2meter = 1; +elseif strcmp(unit, 'dm') + unit2meter = 0.1; +elseif strcmp(unit, 'cm') + unit2meter = 0.01; +elseif strcmp(unit, 'mm') + unit2meter = 0.001; +end + +% determine the unit-of-dimension of the output object +if strcmp(target, 'm') + meter2target = 1; +elseif strcmp(target, 'dm') + meter2target = 10; +elseif strcmp(target, 'cm') + meter2target = 100; +elseif strcmp(target, 'mm') + meter2target = 1000; +end + +% combine the units into one scaling factor +scale = unit2meter * meter2target; + +% volume conductor model +if isfield(obj, 'r'), obj.r = scale * obj.r; end +if isfield(obj, 'o'), obj.o = scale * obj.o; end +if isfield(obj, 'bnd'), for i=1:length(obj.bnd), obj.bnd(i).pnt = scale * obj.bnd(i).pnt; end, end + +% gradiometer array +if isfield(obj, 'pnt1'), obj.pnt1 = scale * obj.pnt1; end +if isfield(obj, 'pnt2'), obj.pnt2 = scale * obj.pnt2; end +if isfield(obj, 'prj'), obj.prj = scale * obj.prj; end + +% gradiometer array, electrode array, head shape or dipole grid +if isfield(obj, 'pnt'), obj.pnt = scale * obj.pnt; end + +% fiducials +if isfield(obj, 'fid') && isfield(obj.fid, 'pnt'), obj.fid.pnt = scale * obj.fid.pnt; end + +% dipole grid +if isfield(obj, 'pos'), obj.pos = scale * obj.pos; end + +% anatomical MRI or functional volume +if isfield(obj, 'transform'), + H = diag([scale scale scale 1]); + obj.transform = H * obj.transform; +end + +% remember the unit +obj.unit = target; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +% Use as +% r = range(x) +% or you can also specify the dimension along which to look by +% r = range(x, dim) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function r = range(x, dim) +if nargin==1 + r = max(x) - min(x); +else + r = max(x, [], dim) - min(x, [], dim); +end diff --git a/external/fieldtrip/fileio/private/cstructdecode.m b/external/fieldtrip/fileio/private/cstructdecode.m new file mode 100644 index 0000000..efe6388 --- /dev/null +++ b/external/fieldtrip/fileio/private/cstructdecode.m @@ -0,0 +1,89 @@ +function varargout = cstructdecode(buf, varargin); + +% CSTRUCTDECODE decodes a structure from a uint8 buffer +% +% See READ_NEURALYNX_NEV for an example + +% Copyright (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: cstructdecode.m 945 2010-04-21 17:41:20Z roboos $ + +if ~isa(buf, 'uint8') + error('incorrect type of input data, should be uint8'); +end + +nbytes = numel(buf); +nfield = length(varargin); + +wordsize = zeros(1,nfield); +for i=1:nfield + switch varargin{i} + case 'uint8' + wordsize(i) = 1; + case 'int8' + wordsize(i) = 1; + case 'uint16' + wordsize(i) = 2; + case 'int16' + wordsize(i) = 2; + case 'uint32' + wordsize(i) = 4; + case 'int32' + wordsize(i) = 4; + case 'uint64' + wordsize(i) = 8; + case 'int64' + wordsize(i) = 8; + case {'float32' 'single'} + varargin{i} = 'single'; + wordsize(i) = 4; + case {'float64' 'double'} + varargin{i} = 'double'; + wordsize(i) = 8; + otherwise + if strncmp(varargin{i}, 'char', 4) + if length(varargin{i})>4 + % assume a string like 'char128' which means 128 characters + wordsize(i) = str2num(varargin{i}(5:end)); + varargin{i} = 'char'; + else + wordsize(i) = 1; + end + else + error('incorrect type specification'); + end + end +end + +pklen = sum(wordsize); +pknum = nbytes/sum(wordsize); + +buf = reshape(buf, pklen, pknum); + +for i=1:nfield + rowbeg = sum(wordsize(1:(i-1)))+1; + rowend = sum(wordsize(1:(i-0)))+0; + sel = buf(rowbeg:rowend,:); + if strcmp(varargin{i}, 'char') + varargout{i} = char(sel)'; + else + varargout{i} = typecast(sel(:), varargin{i}); + end +end + diff --git a/external/fileio/private/ctf2grad.m b/external/fieldtrip/fileio/private/ctf2grad.m similarity index 83% rename from external/fileio/private/ctf2grad.m rename to external/fieldtrip/fileio/private/ctf2grad.m index 7a8138d..384e77a 100644 --- a/external/fileio/private/ctf2grad.m +++ b/external/fieldtrip/fileio/private/ctf2grad.m @@ -13,52 +13,23 @@ % Copyright (C) 2004, Robert Oostenveld % -% $Log: ctf2grad.m,v $ -% Revision 1.4 2009/08/05 08:36:57 roboos -% preallocate the memory that will hold the coil positions, orientations and weights -> significant speedup +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.3 2009/03/23 21:16:03 roboos -% don't give error if balancing fails, but only warning and remove the balancing information +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.2 2009/02/04 13:29:03 roboos -% deal with missing BalanceCoefs in the file using try-catch and isfield (e.g. ArtifactMEG.ds) +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.6 2008/06/26 15:32:19 roboos -% balancing shoudl be subtracted from orig channel, hence added minus sign -% -% Revision 1.5 2008/05/20 12:24:14 roboos -% apply optional balancing to grad.tra -% -% Revision 1.4 2008/05/15 15:11:40 roboos -% add balancing coefficients to the gradiometer definition -% -% Revision 1.3 2008/05/15 13:21:13 roboos -% merged nihm impleemntation into this function -% added new implementation based on CTF p-files -% -% Revision 1.2 2007/03/07 08:57:32 roboos -% use the numeric sensor type for MEG and REF instead of hdr.rowMEG and hdr.rowREF -% -% Revision 1.1 2006/08/31 13:32:11 roboos -% moved from fieldtrip to fileio module -% -% Revision 1.2 2005/06/01 07:59:37 roboos -% added second argument which optionally causes the gradient information to be returend in dewar coordinates -% -% Revision 1.1 2005/05/26 09:55:17 roboos -% renamed the fileio/ctf_grad function to ctf2grad and moved it into fieldtrip/private for consistency with other gradiometer construction functions (nimh2grad and fif2grad) -% -% Revision 1.1 2004/07/02 11:33:47 roboos -% new function that creates a more complete gradiometer definition from the res4 header (compared to read_ctf_res4) +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: ctf2grad.m 1058 2010-05-09 11:21:10Z roboos $ % My preferred ordering in the grad structure is: % 1st 151 coils are bottom coils of MEG channels @@ -173,7 +144,7 @@ grad.label = label([selMEG selREF]); grad.unit = 'cm'; - % convert the balancing coefficients into a montage that can be used with the apply_montage function + % convert the balancing coefficients into a montage that can be used with the ft_apply_montage function if isfield(hdr.BalanceCoefs, 'G1BR') meglabel = label(hdr.BalanceCoefs.G1BR.MEGlist); reflabel = label(hdr.BalanceCoefs.G1BR.Refindex); @@ -207,6 +178,17 @@ grad.balance.G3BR = montage; end + if isfield(hdr.BalanceCoefs, 'G3AR') + meglabel = label(hdr.BalanceCoefs.G3AR.MEGlist); + reflabel = label(hdr.BalanceCoefs.G3AR.Refindex); + nmeg = length(meglabel); + nref = length(reflabel); + montage.labelorg = cat(1, meglabel, reflabel); + montage.labelnew = cat(1, meglabel, reflabel); + montage.tra = [eye(nmeg, nmeg), -hdr.BalanceCoefs.G3AR.alphaMEG'; zeros(nref, nmeg), eye(nref, nref)]; + grad.balance.G3AR = montage; + end + if all([hdr.res4.senres(selMEG).grad_order_no]==0) grad.balance.current = 'none'; elseif all([hdr.res4.senres(selMEG).grad_order_no]==1) @@ -215,6 +197,8 @@ grad.balance.current = 'G2BR'; elseif all([hdr.res4.senres(selMEG).grad_order_no]==3) grad.balance.current = 'G3BR'; + elseif all([hdr.res4.senres(selMEG).grad_order_no]==13) + grad.balance.current = 'G3AR'; else warning('cannot determine balancing of CTF gradiometers'); grad = rmfield(grad, 'balance'); @@ -223,7 +207,7 @@ % sofar the gradiometer definition was the ideal, non-balenced one if isfield(grad, 'balance') && ~strcmp(grad.balance.current, 'none') % apply the current balancing parameters to the gradiometer definition - grad = apply_montage(grad, getfield(grad.balance, grad.balance.current)); + grad = ft_apply_montage(grad, getfield(grad.balance, grad.balance.current)); end diff --git a/external/fieldtrip/fileio/private/decode_nifti1.m b/external/fieldtrip/fileio/private/decode_nifti1.m new file mode 100644 index 0000000..104ab04 --- /dev/null +++ b/external/fieldtrip/fileio/private/decode_nifti1.m @@ -0,0 +1,93 @@ +function H = decode_nifti1(blob) +% function H = decode_nifti1(blob) +% +% Decodes a NIFTI-1 header given as raw 348 bytes (uint8) into a Matlab structure +% that matches the C struct defined in nifti1.h, with the only difference that the +% variable length arrays "dim" and "pixdim" are cut off to the right size, e.g., the +% "dim" entry will only contain the relevant elements: +% dim[0..7]={3,64,64,18,x,x,x,x} in C would become dim=[64,64,18] in Matlab. +% +% WARNING: This function currently ignores endianness !!! + +% (C) 2010 S.Klanke + +if class(blob)~='uint8' + error 'Bad type for blob' +end +if length(blob)~=348 + error 'Blob must be exactly 348 bytes long' +end + +% see nift1.h for information on structure +H = []; + +magic = char(blob(345:347)); +if blob(348)~=0 | magic~='ni1' & magic~='n+1' + error 'Not a NIFTI-1 header!'; +end + +H.sizeof_hdr = typecast(blob(1:4),'int32'); +H.data_type = cstr2matlab(blob(5:14)); +H.db_name = cstr2matlab(blob(15:32)); +H.extents = typecast(blob(33:36),'int32'); +H.session_error = typecast(blob(37:38),'int16'); +H.regular = blob(39); +H.dim_info = blob(40); + +dim = typecast(blob(41:56),'int16'); +H.dim = dim(2:dim(1)+1); +H.intent_p1 = typecast(blob(57:60),'single'); +H.intent_p2 = typecast(blob(61:64),'single'); +H.intent_p3 = typecast(blob(65:68),'single'); +H.intent_code = typecast(blob(69:70),'int16'); +H.datatype = typecast(blob(71:72),'int16'); +H.bitpix = typecast(blob(73:74),'int16'); +H.slice_start = typecast(blob(75:76),'int16'); +pixdim = typecast(blob(77:108),'single'); +H.qfac = pixdim(1); +H.pixdim = pixdim(2:dim(1)+1); +H.vox_offset = typecast(blob(109:112),'single'); +H.scl_scope = typecast(blob(113:116),'single'); +H.scl_inter = typecast(blob(117:120),'single'); +H.slice_end = typecast(blob(121:122),'int16'); +H.slice_code = blob(123); +H.xyzt_units = blob(124); +H.cal_max = typecast(blob(125:128),'single'); +H.cal_min = typecast(blob(129:132),'single'); +H.slice_duration = typecast(blob(133:136),'single'); +H.toffset = typecast(blob(137:140),'single'); +H.glmax = typecast(blob(141:144),'int32'); +H.glmin = typecast(blob(145:148),'int32'); +H.descrip = cstr2matlab(blob(149:228)); +H.aux_file = cstr2matlab(blob(229:252)); +H.qform_code = typecast(blob(253:254),'int16'); +H.sform_code = typecast(blob(255:256),'int16'); +quats = typecast(blob(257:280),'single'); +H.quatern_b = quats(1); +H.quatern_c = quats(2); +H.quatern_d = quats(3); +H.quatern_x = quats(4); +H.quatern_y = quats(5); +H.quatern_z = quats(6); +trafo = typecast(blob(281:328),'single'); +H.srow_x = trafo(1:4); +H.srow_y = trafo(5:8); +H.srow_z = trafo(9:12); +%H.S = [H.srow_x; H.srow_y; H.srow_z; 0 0 0 1]; +H.intent_name = cstr2matlab(blob(329:344)); +H.magic = magic; + + +function ms = cstr2matlab(cs) +if cs(1)==0 + ms = ''; +else + ind = find(cs==0); + if isempty(ind) + ms = char(cs)'; + else + ms = char(cs(1:ind(1)-1))'; + end +end + + \ No newline at end of file diff --git a/external/fieldtrip/fileio/private/encode_nifti1.m b/external/fieldtrip/fileio/private/encode_nifti1.m new file mode 100644 index 0000000..834ec3b --- /dev/null +++ b/external/fieldtrip/fileio/private/encode_nifti1.m @@ -0,0 +1,173 @@ +function blob = encode_nifti1(H) +%function blob = encode_nifti1(H) +% +% Encodes a NIFTI-1 header (=> raw 348 bytes (uint8)) from a Matlab structure +% that matches the C struct defined in nifti1.h. +% +% WARNING: This function currently ignores endianness !!! + +% (C) 2010 S.Klanke + +blob = uint8(zeros(1,348)); + +if ~isstruct(H) + error 'Input must be a structure'; +end +% see nift1.h for information on structure + +sizeof_hdr = int32(348); +blob(1:4) = typecast(sizeof_hdr, 'uint8'); + +blob = setString(blob, 5, 14, H, 'data_type'); +blob = setString(blob, 15, 32, H, 'db_name'); +blob = setInt32( blob, 33, 36, H, 'extents'); +blob = setInt16( blob, 37, 38, H, 'session_error'); +blob = setInt8( blob, 39, 39, H, 'regular'); +blob = setInt8( blob, 40, 40, H, 'dim_info'); + +dim = int16(H.dim(:)'); +ndim = numel(dim); +if ndim<1 || ndim>7 + error 'Field "dim" must have 1..7 elements'; +end +dim = [int16(ndim) dim]; +blob(41:(42+2*ndim)) = typecast(dim,'uint8'); + +blob = setSingle(blob, 57, 60, H, 'intent_p1'); +blob = setSingle(blob, 61, 64, H, 'intent_p2'); +blob = setSingle(blob, 65, 68, H, 'intent_p3'); +blob = setInt16( blob, 69, 70, H, 'intent_code'); +blob = setInt16( blob, 71, 72, H, 'datatype'); +blob = setInt16( blob, 73, 74, H, 'bitpix'); +blob = setInt16( blob, 75, 76, H, 'slice_start'); + +blob = setSingle(blob, 77, 80, H, 'qfac'); + +if isfield(H,'pixdim') + pixdim = single(H.pixdim(:)'); + ndim = numel(pixdim); + if ndim<1 || ndim>7 + error 'Field "pixdim" must have 1..7 elements'; + end + blob(81:(80+4*ndim)) = typecast(pixdim,'uint8'); +end + +blob = setSingle(blob, 109, 112, H, 'vox_offset'); +blob = setSingle(blob, 113, 116, H, 'scl_scope'); +blob = setSingle(blob, 117, 120, H, 'scl_inter'); +blob = setInt16( blob, 121, 122, H, 'slice_end'); +blob = setInt8( blob, 123, 123, H, 'slice_code'); +blob = setInt8( blob, 124, 124, H, 'xyzt_units'); +blob = setSingle(blob, 125, 128, H, 'cal_max'); +blob = setSingle(blob, 129, 132, H, 'cal_min'); +blob = setSingle(blob, 133, 136, H, 'slice_duration'); +blob = setSingle(blob, 137, 140, H, 'toffset'); +blob = setInt32( blob, 141, 144, H, 'glmax'); +blob = setInt32( blob, 145, 148, H, 'glmin'); +blob = setString(blob, 149, 228, H, 'descrip'); +blob = setString(blob, 229, 252, H, 'aux_file'); + +blob = setInt16( blob, 253, 254, H, 'qform_code'); +blob = setInt16( blob, 255, 256, H, 'sform_code'); + +blob = setSingle(blob, 257, 260, H, 'quatern_b'); +blob = setSingle(blob, 261, 264, H, 'quatern_c'); +blob = setSingle(blob, 265, 268, H, 'quatern_d'); +blob = setSingle(blob, 269, 272, H, 'quatern_x'); +blob = setSingle(blob, 273, 276, H, 'quatern_y'); +blob = setSingle(blob, 277, 280, H, 'quatern_z'); +blob = setSingle(blob, 281, 296, H, 'srow_x'); +blob = setSingle(blob, 297, 312, H, 'srow_y'); +blob = setSingle(blob, 313, 328, H, 'srow_z'); + +blob = setString(blob, 329, 344, H, 'intent_name'); +if ~isfield(H,'magic') + blob(345:347) = uint8('ni1'); +else + blob = setString(blob, 345, 347, H, 'magic'); +end + + +function blob = setString(blob, begidx, endidx, H, fieldname) + +if ~isfield(H,fieldname) + return +end + +F = getfield(H, fieldname); +ne = numel(F); +mx = endidx - begidx +1; +if ne > 0 + if ~ischar(F) || ne > mx + errmsg = sprintf('Field "data_type" must be a string of maximally %i characters.', mx); + error(errmsg); + end + blob(begidx:(begidx+ne-1)) = uint8(F(:)'); +end + + +% set 32-bit integers (check #elements) +function blob = setInt32(blob, begidx, endidx, H, fieldname) +if ~isfield(H,fieldname) + return +end + +F = int32(getfield(H, fieldname)); +ne = numel(F); +sp = (endidx - begidx +1) / 4; +if ne~=sp + errmsg = sprintf('Field "data_type" must be an array with exactly %i elements.', sp); + error(errmsg); +end +blob(begidx:(begidx+4*ne-1)) = typecast(F(:)', 'uint8'); + + +% set 16-bit integers (check #elements) +function blob = setInt16(blob, begidx, endidx, H, fieldname) +if ~isfield(H,fieldname) + return +end + +F = int16(getfield(H, fieldname)); +ne = numel(F); +sp = (endidx - begidx +1) / 2; +if ne~=sp + errmsg = sprintf('Field "data_type" must be an array with exactly %i elements.', sp); + error(errmsg); +end +blob(begidx:(begidx+2*ne-1)) = typecast(F(:)', 'uint8'); + + +% just 8-bit integers (check #elements) +function blob = setInt8(blob, begidx, endidx, H, fieldname) +if ~isfield(H,fieldname) + return +end + +F = int8(getfield(H, fieldname)); +ne = numel(F); +sp = (endidx - begidx +1); +if ne~=sp + errmsg = sprintf('Field "data_type" must be an array with exactly %i elements.', sp); + error(errmsg); +end +blob(begidx:(begidx+ne-1)) = typecast(F(:)', 'uint8'); + + +% single precision floats +function blob = setSingle(blob, begidx, endidx, H, fieldname) +if ~isfield(H,fieldname) + return +end + +F = single(getfield(H, fieldname)); +ne = numel(F); +sp = (endidx - begidx +1) / 4; +if ne~=sp + errmsg = sprintf('Field "data_type" must be an array with exactly %i elements.', sp); + error(errmsg); +end +blob(begidx:(begidx+4*ne-1)) = typecast(F(:)', 'uint8'); + + + diff --git a/external/fieldtrip/fileio/private/estimate_units.m b/external/fieldtrip/fileio/private/estimate_units.m new file mode 100644 index 0000000..a566d76 --- /dev/null +++ b/external/fieldtrip/fileio/private/estimate_units.m @@ -0,0 +1,50 @@ +function unit = ft_estimate_units(size) + +% FT_ESTIMATE_UNITS tries to determine the units of a geometrical object by +% looking at its size and by relating this to the size of the human +% brain. +% +% Use as +% unit = ft_estimate_units(size) +% +% This function will return one of the following strings +% 'm' +% 'dm' +% 'cm' +% 'mm' + +% Copyright (C) 2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: estimate_units.m 946 2010-04-21 17:51:16Z roboos $ + +% do some magic based on the size +unit = {'m', 'dm', 'cm', 'mm'}; +indx = round(log10(size)+2-0.2); + +if indx>length(unit) + indx = length(unit); + warning('assuming that the units are "%s"', unit{indx}); +end + +if indx<1 + indx = 1; + warning('assuming that the units are "%s"', unit{indx}); +end + +unit = unit{indx}; diff --git a/external/fieldtrip/fileio/private/fetch_data.m b/external/fieldtrip/fileio/private/fetch_data.m new file mode 100644 index 0000000..e70e9d1 --- /dev/null +++ b/external/fieldtrip/fileio/private/fetch_data.m @@ -0,0 +1,164 @@ +function [dat] = fetch_data(data, varargin) + +% FETCH_DATA mimics the behaviour of READ_DATA, but for a FieldTrip +% raw data structure instead of a file on disk. +% +% Use as +% [dat] = fetch_data(data, ...) +% +% See also READ_DATA, FETCH_HEADER, FETCH_EVENT + +% Copyright (C) 2008, Esther Meeuwissen +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: fetch_data.m 1328 2010-07-01 12:39:39Z jansch $ + +% check whether input is data +data = checkdata(data, 'datatype', 'raw', 'hastrialdef', 'yes'); + +% get the options +hdr = keyval('header', varargin); +begsample = keyval('begsample', varargin); +endsample = keyval('endsample', varargin); +chanindx = keyval('chanindx', varargin); + +if isempty(hdr) + hdr = fetch_header(data); +end + +if isempty(begsample) || isempty(endsample) + error('begsample and endsample must be specified'); +end + +if isempty(chanindx) + chanindx = 1:hdr.nChans; +end + +% get trial definition according to original data file +if isfield(data, 'trialdef') + trl = data.trialdef; +else + error('data does not contain a consistent trial definition, fetching data is not possible'); +end +trlnum = length(data.trial); + +if trlnum>1, + % original implementation + + trllen = zeros(trlnum,1); + for trllop=1:trlnum + trllen(trllop) = size(data.trial{trllop},2); + end + + % check whether data.trial is consistent with trl + if size(trl,1)~=length(data.trial) + error('trial definition is not internally consistent') + elseif any(trllen~=(trl(:,2)-trl(:,1)+1)) + error('trial definition is not internally consistent') + end + + minchan = min(chanindx); + maxchan = max(chanindx); + if minchan<1 || maxchan>hdr.nChans + error('selected channels are not present in the data') + end + + % these are for bookkeeping + maxsample = max(trl(:,2)); + count = zeros(1, maxsample, 'int32'); + trialnum = zeros(1, maxsample, 'int32'); + samplenum = zeros(1, maxsample, 'int32'); + + % determine for each sample in the data where it originates from + for trllop=1:trlnum + trlbeg = trl(trllop,1); + trlend = trl(trllop,2); + if trlbeg>endsample || trlend Nan + trialnum(trlbeg:trlend) = trllop; + % make samplenum vector with samplenrs for each sample in the old trials + samplenum(trlbeg:trlend) = 1:trllen(trllop); + end + + % overlap --> NaN + %trialnum(count>1) = NaN; + %samplenum(count>1) = NaN; + + % make a subselection for the desired samples + count = count(begsample:endsample); + trialnum = trialnum(begsample:endsample); + samplenum = samplenum(begsample:endsample); + + % check if all samples are present and are not present twice or more + if any(count==0) + warning('not all requested samples are present in the data, filling with NaNs'); + elseif any(count>1) + error('some of the requested samples occur twice in the data'); + end + + % construct the output data array + %dat = nan(length(chanindx), length(samplenum)); + %for smplop=1:length(samplenum) + % if samplenum(smplop)==0 + % dat(:, smplop) = nan; + % else + % dat(:, smplop) = data.trial{trialnum(smplop)}(chanindx,samplenum(smplop)); + % end + %end + + % the following piece of code achieves the same as the commented code above, + % but much smaller. rather than looping over samples it loops over the blocks + % of samples defined by the original trials + utrl = unique(trialnum); + utrl(~isfinite(utrl)) = 0; + utrl(utrl==0) = []; + if length(utrl)==1, + ok = trialnum==utrl; + smps = samplenum(ok); + dat(:,ok) = data.trial{utrl}(chanindx,smps); + else + for xlop=1:length(utrl) + ok = trialnum==utrl(xlop); + smps = samplenum(ok); + dat(:,ok) = data.trial{utrl(xlop)}(chanindx,smps); + end + end + +else + % only 1 trial present in the input data, so it's quite simple + % and can be done fast + + % check whether the requested samples are present in the input + if endsample>trl(2) || begsample. +% +% $Id: fif2grad.m 1412 2010-07-15 10:46:19Z vlalit $ + +% this try-catch construct ensures that missing gradiometer information is +% handeled in a "graceful" way +grad = []; +try + megmodel('head',[0 0 0],filename); + [n,s,t]=chaninfo; + [TY,NA]=chaninfo('type'); + nCoils=sum(TY+1); % number of coils + nSensors=length(TY); % number of sensors + grad.pnt=zeros(nCoils,3); + grad.ori=zeros(nCoils,3); + grad.tra=zeros(nSensors,nCoils); + grad.unit='cm'; + % define coils + kCoil=1; + for k=1:nSensors, + if (TY(k)==0), %magnetometer + grad.pnt(kCoil,:)=100*(t{k}(1:3,4)); + grad.ori(kCoil,:)=t{k}(1:3,3); + grad.tra(k,kCoil)=1; + kCoil=kCoil+1; + grad.label{k}=deblank(s(k,:)); + elseif (TY(k) == 1), %planar gradiometer + grad.pnt(kCoil,:)=100*(t{k}(1:3,4)-0.008*t{k}(1:3,1)); % multiply with 100 to get cm + grad.ori(kCoil,:)=t{k}(1:3,3); + grad.tra(k,kCoil)= -1; + kCoil=kCoil+1; + grad.pnt(kCoil,:)=100*(t{k}(1:3,4)+0.008*t{k}(1:3,1)); + grad.ori(kCoil,:)=t{k}(1:3,3); + grad.tra(k,kCoil)= 1; + kCoil=kCoil+1; + grad.label{k}=deblank(s(k,:)); + else + error('unknown sensor type'); + end + end +catch + warning(['gradiometer information could not be extracted from file']); + warning(['returning an empty grad structure']); + return; +end diff --git a/external/fieldtrip/fileio/private/filetype_check_extension.m b/external/fieldtrip/fileio/private/filetype_check_extension.m new file mode 100644 index 0000000..7ad14c0 --- /dev/null +++ b/external/fieldtrip/fileio/private/filetype_check_extension.m @@ -0,0 +1,57 @@ +function [val] = filetype_check_extension(filename, ext) + +% FILETYPE_CHECK_EXTENSION helper function to determine the file type +% by performing a case insensitive string comparison of the extension. + +% Copyright (C) 2003-2006 Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: filetype_check_extension.m 1238 2010-06-16 16:03:32Z roboos $ + +% these are for remembering the type on subsequent calls with the same input arguments +persistent previous_argin previous_argout + +current_argin = {filename, ext}; +if isequal(current_argin, previous_argin) + % don't do the detection again, but return the previous value from cache + val = previous_argout; + return +end + +if iscell(filename) + % compare the extension of multiple files + val = zeros(size(filename)); + for i=1:length(filename) + val(i) = filetype_check_extension(filename{i}, ext); + end +else + % compare the extension of a single file + if numel(filename). +% +% $Id: filetype_check_header.m 1238 2010-06-16 16:03:32Z roboos $ + +% these are for remembering the type on subsequent calls with the same input arguments +persistent previous_argin previous_argout + +if nargin<3 + offset = 0; +end + +current_argin = {filename, head, offset}; +if isequal(current_argin, previous_argin) + % don't do the detection again, but return the previous value from cache + val = previous_argout; + return +end + +if iscell(filename) + % compare the header of multiple files + val = zeros(size(filename)); + for i=1:length(filename) + val(i) = filetype_check_header(filename{i}, head, offset); + end +elseif isdir(filename) + % a directory cannot have a header + val = false; +else + % read the first few bytes from the file and compare them to the desired header + fid = fopen(filename, 'rb'); + if fid<0 + warning(sprintf('could not open %s', filename)); + val = false; + else + fseek(fid, offset, 'cof'); + if iscell(head) + for i=1:length(head) + len(i) = length(head{i}); + end + [str, siz] = fread(fid, max(len), 'uint8=>char'); + fclose(fid); + for i=1:length(head) + val = strncmp(str, head{i}, len(i)); + if val + break + end + end + else + [str, siz] = fread(fid, length(head), 'uint8=>char'); + fclose(fid); + if siz~=length(head) + warning(sprintf('could not read the header from %s', filename)); + val = false; + else + val = all(str(:)==head(:)); + end + end + end +end + +% remember the current input and output arguments, so that they can be +% reused on a subsequent call in case the same input argument is given +current_argout = val; +previous_argin = current_argin; +previous_argout = current_argout; + +return % main() diff --git a/external/fieldtrip/fileio/private/filetype_check_uri.m b/external/fieldtrip/fileio/private/filetype_check_uri.m new file mode 100644 index 0000000..b48fbc6 --- /dev/null +++ b/external/fieldtrip/fileio/private/filetype_check_uri.m @@ -0,0 +1,236 @@ +function varargout = filetype_check_uri(filename, ftyp) + +% FILETYPE_CHECK_URI +% +% Supported URIs are +% buffer://: +% fifo:// +% global:// +% mysql://:@: +% rfb://@: +% serial:?key1=value1&key2=value2&... +% shm:// +% tcp://: +% udp://: +% +% The URI schemes supproted by these function are not the official schemes. +% See the documentation included inside this function for more details. +% RFC4395 defines an IANA-maintained registry of URI Schemes. See also +% http://www.iana.org/assignments/uri-schemes.html and +% http://en.wikipedia.org/wiki/URI_scheme#Generic_syntax. + +% Copyright (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: filetype_check_uri.m 1238 2010-06-16 16:03:32Z roboos $ + +% these are for remembering the type on subsequent calls with the same input arguments +persistent previous_argin previous_argout + +if nargin<2 + % ensure that all input arguments are defined + ftyp = []; +end + +current_argin = {filename, ftyp}; +if isequal(current_argin, previous_argin) + % don't do the detection again, but return the previous value from cache + varargout = previous_argout; + return +end + +sep = find(filename==':'); +if ~isempty(sep) + scheme = filename(1:(sep(1)-1)); +else + scheme = []; +end + +if nargin>1 + % only return true or false + varargout{1} = strcmp(scheme, ftyp); +else + % return the full details of this URI scheme + switch scheme + case 'shm' + % shm:// + % the filename is optional, usually it can and will be read from shared memory + if length(filename)>6 + varargout{1} = filename(7:end); + else + varargout{1} = []; + end + + case 'fifo' + % fifo:// + varargout{1} = filename(8:end); + + case 'global' + % global:// + varargout{1} = filename(10:end); + + case 'buffer' + % buffer://: + tok = tokenize(filename(10:end), ':'); + varargout{1} = tok{1}; + varargout{2} = str2num(tok{2}); + + case 'tcp' + % tcp://: + tok = tokenize(filename(7:end), ':'); + varargout{1} = tok{1}; + varargout{2} = str2num(tok{2}); + + case 'udp' + % udp://: + tok = tokenize(filename(7:end), ':'); + varargout{1} = tok{1}; + varargout{2} = str2num(tok{2}); + + case 'rfb' + % rfb://@: + tok0 = tokenize(filename(7:end), '@'); + tok1 = tokenize(tok0{2}, ':'); + varargout{1} = tok0{1}; + varargout{2} = tok1{1}; + varargout{3} = str2num(tok1{2}); + + case 'mysql' + % mysql://:@: + tok0 = tokenize(filename(9:end), '@'); + tok1 = tokenize(tok0{1}, ':'); + tok2 = tokenize(tok0{2}, ':'); + varargout{1} = tok1{1}; + varargout{2} = tok1{2}; + varargout{3} = tok2{1}; + if length(tok2)>1 + varargout{4} = str2num(tok2{2}); + else + varargout{4} = []; + end + + case 'serial' + % serial:?key1=value1&key2=value2&... + % the supported optional arguments are + % BaudRate + % DataBits + % DataTerminalReady + % FlowControl + % Parity + % Port + % ReadAsyncMode + % RequestToSend + % StopBits + % Terminator + tok0 = tokenize(filename(8:end), '?'); + varargout{1} = tok0{1}; + varargout{2} = []; + if length(tok0)>1 + tok1 = tokenize(tok0{2}, '&'); + for i=1:length(tok1) + tok2 = tokenize(tok1{i}, '='); + opt{(i-1)*2+1} = tok2{1}; + opt{(i-1)*2+2} = tok2{2}; + end + varargout{2} = opt; + end + + + otherwise + error('unsupported scheme in URI') + end +end + +% remember the current input and output arguments, so that they can be +% reused on a subsequent call in case the same input argument is given +current_argout = varargout; +previous_argin = current_argin; +previous_argout = current_argout; + +return % main() + +% RFC4395 defines an IANA-maintained registry of URI Schemes. +% see also http://www.iana.org/assignments/uri-schemes.html +% and http://en.wikipedia.org/wiki/URI_scheme#Generic_syntax +% +% Scheme Description Reference +% ------------------------------------------------------------- +% aaa Diameter Protocol [RFC3588] +% aaas Diameter Protocol with Secure Transport [RFC3588] +% acap application configuration access protocol [RFC2244] +% cap Calendar Access Protocol [RFC4324] +% cid content identifier [RFC2392] +% crid TV-Anytime Content Reference Identifier [RFC4078] +% data data [RFC2397] +% dav dav [RFC-ietf-webdav-rfc2518bis-18.txt] +% dict dictionary service protocol [RFC2229] +% dns Domain Name System [RFC4501] +% fax fax [RFC3966] +% file Host-specific file names [RFC1738] +% ftp File Transfer Protocol [RFC1738] +% go go [RFC3368] +% gopher The Gopher Protocol [RFC4266] +% h323 H.323 [RFC3508] +% http Hypertext Transfer Protocol [RFC2616] +% https Hypertext Transfer Protocol Secure [RFC2818] +% icap Internet Content Adaptation Protocol [RFC3507] +% im Instant Messaging [RFC3860] +% imap internet message access protocol [RFC2192] +% info Information Assets with Identifiers in Public Namespaces [RFC4452] +% ipp Internet Printing Protocol [RFC3510] +% iris Internet Registry Information Service [RFC3981] +% iris.beep iris.beep [RFC3983] +% iris.xpc iris.xpc [RFC-ietf-crisp-iris-xpc-06.txt] +% iris.xpcs iris.xpcs [RFC-ietf-crisp-iris-xpc-06.txt] +% iris.lwz iris.lwz [RFC-ietf-crisp-iris-lwz-08.txt] +% ldap Lightweight Directory Access Protocol [RFC4516] +% mailto Electronic mail address [RFC2368] +% mid message identifier [RFC2392] +% modem modem [RFC3966] +% msrp Message Session Relay Protocol [RFC-ietf-simple-message-sessions-19.txt] +% msrps Message Session Relay Protocol Secure [RFC-ietf-simple-message-sessions-19.txt] +% mtqp Message Tracking Query Protocol [RFC3887] +% mupdate Mailbox Update (MUPDATE) Protocol [RFC3656] +% news USENET news [RFC1738] +% nfs network file system protocol [RFC2224] +% nntp USENET news using NNTP access [RFC1738] +% opaquelocktoken opaquelocktokent [RFC-ietf-webdav-rfc2518bis-18.txt] +% pop Post Office Protocol v3 [RFC2384] +% pres Presence [RFC3859] +% rtsp real time streaming protocol [RFC2326] +% service service location [RFC2609] +% shttp Secure Hypertext Transfer Protocol [RFC2660] +% sip session initiation protocol [RFC3261] +% sips secure session initiation protocol [RFC3261] +% snmp Simple Network Management Protocol [RFC4088] +% soap.beep soap.beep [RFC3288] +% soap.beeps soap.beeps [RFC3288] +% tag tag [RFC4151] +% tel telephone [RFC3966] +% telnet Reference to interactive sessions [RFC4248] +% tftp Trivial File Transfer Protocol [RFC3617] +% thismessage multipart/related relative reference resolution [RFC2557] +% tip Transaction Internet Protocol [RFC2371] +% tv TV Broadcasts [RFC2838] +% urn Uniform Resource Names (click for registry) [RFC2141] +% vemmi versatile multimedia interface [RFC2122] +% xmlrpc.beep xmlrpc.beep [RFC3529] +% xmlrpc.beeps xmlrpc.beeps [RFC3529] +% xmpp Extensible Messaging and Presence Protocol [RFC4622] +% z39.50r Z39.50 Retrieval [RFC2056] +% z39.50s Z39.50 Session [RFC2056] diff --git a/external/fieldtrip/fileio/private/ft_apply_montage.m b/external/fieldtrip/fileio/private/ft_apply_montage.m new file mode 100644 index 0000000..9a895bf --- /dev/null +++ b/external/fieldtrip/fileio/private/ft_apply_montage.m @@ -0,0 +1,226 @@ +function [sens] = ft_apply_montage(sens, montage, varargin) + +% FT_APPLY_MONTAGE changes the montage of an electrode or gradiometer array. A +% montage can be used for EEG rereferencing, MEG synthetic gradients, MEG +% planar gradients or unmixing using ICA. This function applies the montage +% to the sensor array. The sensor array can subsequently be used for +% forward computation and source reconstruction of the data. +% +% Use as +% [sens] = ft_apply_montage(sens, montage, ...) +% [data] = ft_apply_montage(data, montage, ...) +% [montage] = ft_apply_montage(montage1, montage2, ...) +% where the input is a FieldTrip sensor definition as obtained from FT_READ_SENS +% or a FieldTrip raw data structure as obtained from FT_PREPROCESSING. +% +% A montage is specified as a structure with the fields +% montage.tra = MxN matrix +% montage.labelnew = Mx1 cell-array +% montage.labelorg = Nx1 cell-array +% +% Additional options should be specified in key-value pairs and can be +% 'keepunused' string, 'yes' or 'no' (default = 'no') +% 'inverse' string, 'yes' or 'no' (default = 'no') +% +% If the first input is a montage, then the second input montage will be +% applied to the first. In effect the resulting montage will first do +% montage1, then montage2. +% +% See also FT_READ_SENS, FT_TRANSFORM_SENS + +% Copyright (C) 2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_apply_montage.m 1139 2010-05-26 12:55:57Z roboos $ + +% get optional input arguments +keepunused = keyval('keepunused', varargin{:}); if isempty(keepunused), keepunused = 'no'; end +inverse = keyval('inverse', varargin{:}); if isempty(inverse), inverse = 'no'; end + +% check the consistency of the input sensor array or data +if isfield(sens, 'labelorg') && isfield(sens, 'labelnew') + % the input data structure is also a montage, i.e. apply the montages sequentially + sens.label = sens.labelnew; +end + +% check the consistency of the montage +if size(montage.tra,1)~=length(montage.labelnew) + error('the number of channels in the montage is inconsistent'); +elseif size(montage.tra,2)~=length(montage.labelorg) + error('the number of channels in the montage is inconsistent'); +end + +if strcmp(inverse, 'yes') + % apply the inverse montage, i.e. undo a previously applied montage + tmp.labelnew = montage.labelorg; % swap around + tmp.labelorg = montage.labelnew; % swap around + tmp.tra = full(montage.tra); + if rank(tmp.tra) < length(tmp.tra) + warning('the linear projection for the montage is not full-rank, the resulting data will have reduced dimensionality'); + tmp.tra = pinv(tmp.tra); + else + tmp.tra = inv(tmp.tra); + end + montage = tmp; +end + +% use default transfer from sensors to channels if not specified +if isfield(sens, 'pnt') && ~isfield(sens, 'tra') + nchan = size(sens.pnt,1); + sens.tra = sparse(eye(nchan)); +end + +% select and keep the columns that are non-empty, i.e. remove the empty columns +selcol = find(~all(montage.tra==0, 1)); +montage.tra = montage.tra(:,selcol); +montage.labelorg = montage.labelorg(selcol); +clear selcol + +% select and remove the columns corresponding to channels that are not present in the original data +remove = setdiff(montage.labelorg, intersect(montage.labelorg, sens.label)); +selcol = match_str(montage.labelorg, remove); +% we cannot just remove the colums, all rows that depend on it should also be removed +selrow = false(length(montage.labelnew),1); +for i=1:length(selcol) + selrow = selrow & (montage.tra(:,selcol(i))~=0); +end +% convert from indices to logical vector +selcol = indx2logical(selcol, length(montage.labelorg)); +% remove rows and columns +montage.labelorg = montage.labelorg(~selcol); +montage.labelnew = montage.labelnew(~selrow); +montage.tra = montage.tra(~selrow, ~selcol); +clear remove selcol selrow i +% add columns for the channels that are present in the data but not involved in the montage, and stick to the original order in the data +[add, ix] = setdiff(sens.label, montage.labelorg); +add = sens.label(sort(ix)); +m = size(montage.tra,1); +n = size(montage.tra,2); +k = length(add); +if strcmp(keepunused, 'yes') + % add the channels that are not rereferenced to the input and output + montage.tra((m+(1:k)),(n+(1:k))) = eye(k); + montage.labelorg = cat(1, montage.labelorg(:), add(:)); + montage.labelnew = cat(1, montage.labelnew(:), add(:)); +else + % add the channels that are not rereferenced to the input montage only + montage.tra(:,(n+(1:k))) = zeros(m,k); + montage.labelorg = cat(1, montage.labelorg(:), add(:)); +end +clear add m n k + +% determine whether all channels are unique +m = size(montage.tra,1); +n = size(montage.tra,2); +if length(unique(montage.labelnew))~=m + error('not all output channels of the montage are unique'); +end +if length(unique(montage.labelorg))~=n + error('not all input channels of the montage are unique'); +end + +% determine whether all channels that have to be rereferenced are available +if length(intersect(sens.label, montage.labelorg))~=length(montage.labelorg) + error('not all channels that are required in the montage are available in the data'); +end + +% reorder the columns of the montage matrix +[selsens, selmont] = match_str(sens.label, montage.labelorg); +montage.tra = sparse(montage.tra(:,selmont)); +montage.labelorg = montage.labelorg(selmont); + +if isfield(sens, 'labelorg') && isfield(sens, 'labelnew') + % apply the montage on top of the other montage + sens = rmfield(sens, 'label'); + sens.tra = montage.tra * sens.tra; + sens.labelnew = montage.labelnew; + +elseif isfield(sens, 'tra') + % apply the montage to the sensor array + sens.tra = montage.tra * sens.tra; + sens.label = montage.labelnew; + +elseif isfield(sens, 'trial') + % apply the montage to the raw data that was preprocessed using fieldtrip + data = sens; + clear sens + + Ntrials = numel(data.trial); + for i=1:Ntrials + fprintf('processing trial %d from %d\n', i, Ntrials); + if isa(data.trial{i}, 'single') + % sparse matrices and single precision do not match + data.trial{i} = full(montage.tra) * data.trial{i}; + else + data.trial{i} = montage.tra * data.trial{i}; + end + end + data.label = montage.labelnew; + + % rename the output variable + sens = data; + clear data + +elseif isfield(sens, 'fourierspctrm') + % apply the montage to the spectrally decomposed data + freq = sens; + clear sens + + if strcmp(freq.dimord, 'rpttap_chan_freq') + siz = size(freq.fourierspctrm); + nrpt = siz(1); + nchan = siz(2); + nfreq = siz(3); + output = zeros(nrpt, size(montage.tra,1), nfreq); + for foilop=1:nfreq + output(:,:,foilop) = freq.fourierspctrm(:,:,foilop) * montage.tra'; + end + elseif strcmp(freq.dimord, 'rpttap_chan_freq_time') + siz = size(freq.fourierspctrm); + nrpt = siz(1); + nchan = siz(2); + nfreq = siz(3); + ntime = siz(4); + output = zeros(nrpt, size(montage.tra,1), nfreq, ntime); + for foilop=1:nfreq + for toilop = 1:ntime + output(:,:,foilop,toilop) = freq.fourierspctrm(:,:,foilop,toilop) * montage.tra'; + end + end + else + error('unsupported dimord in frequency data (%s)', freq.dimord); + end + + % replace the Fourier spectrum + freq.fourierspctrm = output; + freq.label = montage.labelnew; + + % rename the output variable + sens = freq; + clear freq + +else + error('unrecognized input'); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% HELPER FUNCTION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function y = indx2logical(x, n) +y = false(1,n); +y(x) = true; diff --git a/external/fieldtrip/fileio/private/ft_convert_units.m b/external/fieldtrip/fileio/private/ft_convert_units.m new file mode 100644 index 0000000..868afe7 --- /dev/null +++ b/external/fieldtrip/fileio/private/ft_convert_units.m @@ -0,0 +1,205 @@ +function [obj] = ft_convert_units(obj, target); + +% FT_CONVERT_UNITS changes the geometrical dimension to the specified SI unit. +% The units of the input object is determined from the structure field +% object.unit, or is estimated based on the spatial extend of the structure, +% e.g. a volume conduction model of the head should be approximately 20 cm large. +% +% Use as +% [object] = ft_convert_units(object, target) +% +% The following input objects are supported +% simple dipole position +% electrode definition +% gradiometer array definition +% volume conductor definition +% dipole grid definition +% anatomical mri +% +% Possible target units are 'm', 'dm', 'cm ' or 'mm'. +% +% See FT_READ_VOL, FT_READ_SENS + +% Copyright (C) 2005-2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_convert_units.m 946 2010-04-21 17:51:16Z roboos $ + +% This function consists of three parts: +% 1) determine the input units +% 2) determine the requested scaling factor to obtain the output units +% 3) try to apply the scaling to the known geometrical elements in the input object + +% determine the unit-of-dimension of the input object +if isfield(obj, 'unit') + % use the units specified in the object + unit = obj.unit; +else + % try to estimate the units from the object + type = ft_voltype(obj); + if ~strcmp(type, 'unknown') + switch type + case 'infinite' + % there is nothing to do to convert the units + unit = target; + + case 'singlesphere' + size = obj.r; + + case 'multisphere' + size = median(obj.r); + + case 'concentric' + size = max(obj.r); + + case 'nolte' + size = norm(range(obj.bnd.pnt)); + + case {'bem' 'dipoli' 'bemcp' 'asa' 'avo'} + size = norm(range(obj.bnd(1).pnt)); + + otherwise + error('cannot determine geometrical units of volume conduction model'); + end % switch + + % determine the units by looking at the size + unit = ft_estimate_units(size); + + elseif ft_senstype(obj, 'meg') + size = norm(range(obj.pnt)); + unit = ft_estimate_units(size); + + elseif ft_senstype(obj, 'eeg') + size = norm(range(obj.pnt)); + unit = ft_estimate_units(size); + + elseif isfield(obj, 'pnt') && ~isempty(obj.pnt) + size = norm(range(obj.pnt)); + unit = ft_estimate_units(size); + + elseif isfield(obj, 'pos') && ~isempty(obj.pos) + size = norm(range(obj.pos)); + unit = ft_estimate_units(size); + + elseif isfield(obj, 'transform') && ~isempty(obj.transform) + % construct the corner points of the voxel grid in head coordinates + xi = 1:obj.dim(1); + yi = 1:obj.dim(2); + zi = 1:obj.dim(3); + pos = [ + xi( 1) yi( 1) zi( 1) + xi( 1) yi( 1) zi(end) + xi( 1) yi(end) zi( 1) + xi( 1) yi(end) zi(end) + xi(end) yi( 1) zi( 1) + xi(end) yi( 1) zi(end) + xi(end) yi(end) zi( 1) + xi(end) yi(end) zi(end) + ]; + pos = warp_apply(obj.transform, pos); + size = norm(range(pos)); + unit = ft_estimate_units(size); + + elseif isfield(obj, 'fid') && isfield(obj.fid, 'pnt') && ~isempty(obj.fid.pnt) + size = norm(range(obj.fid.pnt)); + unit = ft_estimate_units(size); + + else + error('cannot determine geometrical units'); + + end % recognized type of volume conduction model or sensor array +end % determine input units + +if nargin<2 + % just remember the units in the output and return + obj.unit = unit; + return +elseif strcmp(unit, target) + % no conversion is needed + obj.unit = unit; + return +end + +% give some information about the conversion +fprintf('converting units from ''%s'' to ''%s''\n', unit, target) + +if strcmp(unit, 'm') + unit2meter = 1; +elseif strcmp(unit, 'dm') + unit2meter = 0.1; +elseif strcmp(unit, 'cm') + unit2meter = 0.01; +elseif strcmp(unit, 'mm') + unit2meter = 0.001; +end + +% determine the unit-of-dimension of the output object +if strcmp(target, 'm') + meter2target = 1; +elseif strcmp(target, 'dm') + meter2target = 10; +elseif strcmp(target, 'cm') + meter2target = 100; +elseif strcmp(target, 'mm') + meter2target = 1000; +end + +% combine the units into one scaling factor +scale = unit2meter * meter2target; + +% volume conductor model +if isfield(obj, 'r'), obj.r = scale * obj.r; end +if isfield(obj, 'o'), obj.o = scale * obj.o; end +if isfield(obj, 'bnd'), for i=1:length(obj.bnd), obj.bnd(i).pnt = scale * obj.bnd(i).pnt; end, end + +% gradiometer array +if isfield(obj, 'pnt1'), obj.pnt1 = scale * obj.pnt1; end +if isfield(obj, 'pnt2'), obj.pnt2 = scale * obj.pnt2; end +if isfield(obj, 'prj'), obj.prj = scale * obj.prj; end + +% gradiometer array, electrode array, head shape or dipole grid +if isfield(obj, 'pnt'), obj.pnt = scale * obj.pnt; end + +% fiducials +if isfield(obj, 'fid') && isfield(obj.fid, 'pnt'), obj.fid.pnt = scale * obj.fid.pnt; end + +% dipole grid +if isfield(obj, 'pos'), obj.pos = scale * obj.pos; end + +% anatomical MRI or functional volume +if isfield(obj, 'transform'), + H = diag([scale scale scale 1]); + obj.transform = H * obj.transform; +end + +% remember the unit +obj.unit = target; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +% Use as +% r = range(x) +% or you can also specify the dimension along which to look by +% r = range(x, dim) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function r = range(x, dim) +if nargin==1 + r = max(x) - min(x); +else + r = max(x, [], dim) - min(x, [], dim); +end diff --git a/external/fieldtrip/fileio/private/ft_estimate_units.m b/external/fieldtrip/fileio/private/ft_estimate_units.m new file mode 100644 index 0000000..e0655c5 --- /dev/null +++ b/external/fieldtrip/fileio/private/ft_estimate_units.m @@ -0,0 +1,50 @@ +function unit = ft_estimate_units(size) + +% FT_ESTIMATE_UNITS tries to determine the units of a geometrical object by +% looking at its size and by relating this to the size of the human +% brain. +% +% Use as +% unit = ft_estimate_units(size) +% +% This function will return one of the following strings +% 'm' +% 'dm' +% 'cm' +% 'mm' + +% Copyright (C) 2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_estimate_units.m 946 2010-04-21 17:51:16Z roboos $ + +% do some magic based on the size +unit = {'m', 'dm', 'cm', 'mm'}; +indx = round(log10(size)+2-0.2); + +if indx>length(unit) + indx = length(unit); + warning('assuming that the units are "%s"', unit{indx}); +end + +if indx<1 + indx = 1; + warning('assuming that the units are "%s"', unit{indx}); +end + +unit = unit{indx}; diff --git a/external/fieldtrip/fileio/private/ft_senslabel.m b/external/fieldtrip/fileio/private/ft_senslabel.m new file mode 100644 index 0000000..4242fb1 --- /dev/null +++ b/external/fieldtrip/fileio/private/ft_senslabel.m @@ -0,0 +1,2808 @@ +function label = ft_senslabel(type) + +% FT_SENSLABEL returns a list of sensor labels given the MEEG system type +% +% Use as +% label = ft_senslabel(type) +% +% The input type can be any of the following +% 'biosemi64' +% 'biosemi128' +% 'biosemi256' +% 'bti148' +% 'bti148_planar' +% 'bti248' +% 'bti248_planar' +% 'btiref' +% 'ctf151' +% 'ctf151_planar' +% 'ctf275' +% 'ctf275_planar' +% 'ctfheadloc' +% 'ctfref' +% 'eeg1005' +% 'eeg1010' +% 'eeg1020' +% 'egi128' +% 'egi256' +% 'egi32' +% 'egi64' +% 'ext1020' +% 'neuromag122' +% 'neuromag122alt' +% 'neuromag306' +% 'neuromag306alt' +% 'itab153' +% 'itab153_planar' +% 'yokogawa160' +% 'yokogawa160_planar' +% 'electrode' +% +% See also FT_SENSTYPE, FT_CHANNELSELECTION + +% FIXME one channel is missing for ctf275 + +% Copyright (C) 2007-2008, Robert Oostenveld +% Copyright (C) 2008, Vladimir Litvak +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_senslabel.m 1006 2010-05-03 08:36:13Z roboos $ + +% these are for remembering the type on subsequent calls with the same input arguments +persistent previous_argin previous_argout + +if nargin<1 + % ensure that all input arguments are defined + type = []; +end + +current_argin = {type}; +if isequal(current_argin, previous_argin) + % don't do the type detection again, but return the previous values from cache + label = previous_argout{1}; + return +end + +switch type + + case 'btiref' + label = { + 'MRxA' + 'MRyA' + 'MRzA' + 'MLxA' + 'MLyA' + 'MLzA' + 'MCxA' + 'MCyA' + 'MCzA' + 'MRxaA' + 'MRyaA' + 'MRzaA' + 'MLxaA' + 'MLyaA' + 'MLzaA' + 'MCxaA' + 'MCyaA' + 'MCzaA' + 'GxxA' + 'GyxA' + 'GzxA' + 'GyyA' + 'GzyA' + }; + + case 'bti148' + label = cell(148,1); + for i=1:148 + label{i,1} = sprintf('A%d', i); + end + + case 'bti148_planar' + label = cell(148,2); + for i=1:148 + label{i,1} = sprintf('A%d_dH', i); + label{i,2} = sprintf('A%d_dV', i); + end + + case 'bti248' + label = cell(248,1); + for i=1:248 + label{i,1} = sprintf('A%d', i); + end + + case 'bti248_planar' + label = cell(248,2); + for i=1:248 + label{i,1} = sprintf('A%d_dH', i); + label{i,2} = sprintf('A%d_dV', i); + end + + case 'ctfref' + label = { + 'BG1' + 'BG2' + 'BG3' + 'BP1' + 'BP2' + 'BP3' + 'BR1' + 'BR2' + 'BR3' + 'G11' + 'G12' + 'G13' + 'G22' + 'G23' + 'P11' + 'P12' + 'P13' + 'P22' + 'P23' + 'Q11' + 'Q12' + 'Q13' + 'Q22' + 'Q23' + 'R11' + 'R12' + 'R13' + 'R22' + 'R23' + }; + + case 'ctfheadloc' + label = { + 'HLC0011' + 'HLC0012' + 'HLC0013' + 'HLC0021' + 'HLC0022' + 'HLC0023' + 'HLC0031' + 'HLC0032' + 'HLC0033' + 'HLC0018' + 'HLC0028' + 'HLC0038' + 'HLC0014' + 'HLC0015' + 'HLC0016' + 'HLC0017' + 'HLC0024' + 'HLC0025' + 'HLC0026' + 'HLC0027' + 'HLC0034' + 'HLC0035' + 'HLC0036' + 'HLC0037' + }; + + case 'ctf64' + label = { + 'SL11' + 'SL12' + 'SL13' + 'SL14' + 'SL15' + 'SL16' + 'SL17' + 'SL18' + 'SL19' + 'SL21' + 'SL22' + 'SL23' + 'SL24' + 'SL25' + 'SL26' + 'SL27' + 'SL28' + 'SL29' + 'SL31' + 'SL32' + 'SL33' + 'SL34' + 'SL35' + 'SL41' + 'SL42' + 'SL43' + 'SL44' + 'SL45' + 'SL46' + 'SL47' + 'SL51' + 'SL52' + 'SR11' + 'SR12' + 'SR13' + 'SR14' + 'SR15' + 'SR16' + 'SR17' + 'SR18' + 'SR19' + 'SR21' + 'SR22' + 'SR23' + 'SR24' + 'SR25' + 'SR26' + 'SR27' + 'SR28' + 'SR29' + 'SR31' + 'SR32' + 'SR33' + 'SR34' + 'SR35' + 'SR41' + 'SR42' + 'SR43' + 'SR44' + 'SR45' + 'SR46' + 'SR47' + 'SR51' + 'SR52' + }; + + case 'ctf151' + label = { + 'MLC11' + 'MLC12' + 'MLC13' + 'MLC14' + 'MLC15' + 'MLC21' + 'MLC22' + 'MLC23' + 'MLC24' + 'MLC31' + 'MLC32' + 'MLC33' + 'MLC41' + 'MLC42' + 'MLC43' + 'MLF11' + 'MLF12' + 'MLF21' + 'MLF22' + 'MLF23' + 'MLF31' + 'MLF32' + 'MLF33' + 'MLF34' + 'MLF41' + 'MLF42' + 'MLF43' + 'MLF44' + 'MLF45' + 'MLF51' + 'MLF52' + 'MLO11' + 'MLO12' + 'MLO21' + 'MLO22' + 'MLO31' + 'MLO32' + 'MLO33' + 'MLO41' + 'MLO42' + 'MLO43' + 'MLP11' + 'MLP12' + 'MLP13' + 'MLP21' + 'MLP22' + 'MLP31' + 'MLP32' + 'MLP33' + 'MLP34' + 'MLT11' + 'MLT12' + 'MLT13' + 'MLT14' + 'MLT15' + 'MLT16' + 'MLT21' + 'MLT22' + 'MLT23' + 'MLT24' + 'MLT25' + 'MLT26' + 'MLT31' + 'MLT32' + 'MLT33' + 'MLT34' + 'MLT35' + 'MLT41' + 'MLT42' + 'MLT43' + 'MLT44' + 'MRC11' + 'MRC12' + 'MRC13' + 'MRC14' + 'MRC15' + 'MRC21' + 'MRC22' + 'MRC23' + 'MRC24' + 'MRC31' + 'MRC32' + 'MRC33' + 'MRC41' + 'MRC42' + 'MRC43' + 'MRF11' + 'MRF12' + 'MRF21' + 'MRF22' + 'MRF23' + 'MRF31' + 'MRF32' + 'MRF33' + 'MRF34' + 'MRF41' + 'MRF42' + 'MRF43' + 'MRF44' + 'MRF45' + 'MRF51' + 'MRF52' + 'MRO11' + 'MRO12' + 'MRO21' + 'MRO22' + 'MRO31' + 'MRO32' + 'MRO33' + 'MRO41' + 'MRO42' + 'MRO43' + 'MRP11' + 'MRP12' + 'MRP13' + 'MRP21' + 'MRP22' + 'MRP31' + 'MRP32' + 'MRP33' + 'MRP34' + 'MRT11' + 'MRT12' + 'MRT13' + 'MRT14' + 'MRT15' + 'MRT16' + 'MRT21' + 'MRT22' + 'MRT23' + 'MRT24' + 'MRT25' + 'MRT26' + 'MRT31' + 'MRT32' + 'MRT33' + 'MRT34' + 'MRT35' + 'MRT41' + 'MRT42' + 'MRT43' + 'MRT44' + 'MZC01' + 'MZC02' + 'MZF01' + 'MZF02' + 'MZF03' + 'MZO01' + 'MZO02' + 'MZP01' + 'MZP02' + }; + + case 'ctf151_planar' + label = { + 'MLC11_dH' 'MLC11_dV' + 'MLC12_dH' 'MLC12_dV' + 'MLC13_dH' 'MLC13_dV' + 'MLC14_dH' 'MLC14_dV' + 'MLC15_dH' 'MLC15_dV' + 'MLC21_dH' 'MLC21_dV' + 'MLC22_dH' 'MLC22_dV' + 'MLC23_dH' 'MLC23_dV' + 'MLC24_dH' 'MLC24_dV' + 'MLC31_dH' 'MLC31_dV' + 'MLC32_dH' 'MLC32_dV' + 'MLC33_dH' 'MLC33_dV' + 'MLC41_dH' 'MLC41_dV' + 'MLC42_dH' 'MLC42_dV' + 'MLC43_dH' 'MLC43_dV' + 'MLF11_dH' 'MLF11_dV' + 'MLF12_dH' 'MLF12_dV' + 'MLF21_dH' 'MLF21_dV' + 'MLF22_dH' 'MLF22_dV' + 'MLF23_dH' 'MLF23_dV' + 'MLF31_dH' 'MLF31_dV' + 'MLF32_dH' 'MLF32_dV' + 'MLF33_dH' 'MLF33_dV' + 'MLF34_dH' 'MLF34_dV' + 'MLF41_dH' 'MLF41_dV' + 'MLF42_dH' 'MLF42_dV' + 'MLF43_dH' 'MLF43_dV' + 'MLF44_dH' 'MLF44_dV' + 'MLF45_dH' 'MLF45_dV' + 'MLF51_dH' 'MLF51_dV' + 'MLF52_dH' 'MLF52_dV' + 'MLO11_dH' 'MLO11_dV' + 'MLO12_dH' 'MLO12_dV' + 'MLO21_dH' 'MLO21_dV' + 'MLO22_dH' 'MLO22_dV' + 'MLO31_dH' 'MLO31_dV' + 'MLO32_dH' 'MLO32_dV' + 'MLO33_dH' 'MLO33_dV' + 'MLO41_dH' 'MLO41_dV' + 'MLO42_dH' 'MLO42_dV' + 'MLO43_dH' 'MLO43_dV' + 'MLP11_dH' 'MLP11_dV' + 'MLP12_dH' 'MLP12_dV' + 'MLP13_dH' 'MLP13_dV' + 'MLP21_dH' 'MLP21_dV' + 'MLP22_dH' 'MLP22_dV' + 'MLP31_dH' 'MLP31_dV' + 'MLP32_dH' 'MLP32_dV' + 'MLP33_dH' 'MLP33_dV' + 'MLP34_dH' 'MLP34_dV' + 'MLT11_dH' 'MLT11_dV' + 'MLT12_dH' 'MLT12_dV' + 'MLT13_dH' 'MLT13_dV' + 'MLT14_dH' 'MLT14_dV' + 'MLT15_dH' 'MLT15_dV' + 'MLT16_dH' 'MLT16_dV' + 'MLT21_dH' 'MLT21_dV' + 'MLT22_dH' 'MLT22_dV' + 'MLT23_dH' 'MLT23_dV' + 'MLT24_dH' 'MLT24_dV' + 'MLT25_dH' 'MLT25_dV' + 'MLT26_dH' 'MLT26_dV' + 'MLT31_dH' 'MLT31_dV' + 'MLT32_dH' 'MLT32_dV' + 'MLT33_dH' 'MLT33_dV' + 'MLT34_dH' 'MLT34_dV' + 'MLT35_dH' 'MLT35_dV' + 'MLT41_dH' 'MLT41_dV' + 'MLT42_dH' 'MLT42_dV' + 'MLT43_dH' 'MLT43_dV' + 'MLT44_dH' 'MLT44_dV' + 'MRC11_dH' 'MRC11_dV' + 'MRC12_dH' 'MRC12_dV' + 'MRC13_dH' 'MRC13_dV' + 'MRC14_dH' 'MRC14_dV' + 'MRC15_dH' 'MRC15_dV' + 'MRC21_dH' 'MRC21_dV' + 'MRC22_dH' 'MRC22_dV' + 'MRC23_dH' 'MRC23_dV' + 'MRC24_dH' 'MRC24_dV' + 'MRC31_dH' 'MRC31_dV' + 'MRC32_dH' 'MRC32_dV' + 'MRC33_dH' 'MRC33_dV' + 'MRC41_dH' 'MRC41_dV' + 'MRC42_dH' 'MRC42_dV' + 'MRC43_dH' 'MRC43_dV' + 'MRF11_dH' 'MRF11_dV' + 'MRF12_dH' 'MRF12_dV' + 'MRF21_dH' 'MRF21_dV' + 'MRF22_dH' 'MRF22_dV' + 'MRF23_dH' 'MRF23_dV' + 'MRF31_dH' 'MRF31_dV' + 'MRF32_dH' 'MRF32_dV' + 'MRF33_dH' 'MRF33_dV' + 'MRF34_dH' 'MRF34_dV' + 'MRF41_dH' 'MRF41_dV' + 'MRF42_dH' 'MRF42_dV' + 'MRF43_dH' 'MRF43_dV' + 'MRF44_dH' 'MRF44_dV' + 'MRF45_dH' 'MRF45_dV' + 'MRF51_dH' 'MRF51_dV' + 'MRF52_dH' 'MRF52_dV' + 'MRO11_dH' 'MRO11_dV' + 'MRO12_dH' 'MRO12_dV' + 'MRO21_dH' 'MRO21_dV' + 'MRO22_dH' 'MRO22_dV' + 'MRO31_dH' 'MRO31_dV' + 'MRO32_dH' 'MRO32_dV' + 'MRO33_dH' 'MRO33_dV' + 'MRO41_dH' 'MRO41_dV' + 'MRO42_dH' 'MRO42_dV' + 'MRO43_dH' 'MRO43_dV' + 'MRP11_dH' 'MRP11_dV' + 'MRP12_dH' 'MRP12_dV' + 'MRP13_dH' 'MRP13_dV' + 'MRP21_dH' 'MRP21_dV' + 'MRP22_dH' 'MRP22_dV' + 'MRP31_dH' 'MRP31_dV' + 'MRP32_dH' 'MRP32_dV' + 'MRP33_dH' 'MRP33_dV' + 'MRP34_dH' 'MRP34_dV' + 'MRT11_dH' 'MRT11_dV' + 'MRT12_dH' 'MRT12_dV' + 'MRT13_dH' 'MRT13_dV' + 'MRT14_dH' 'MRT14_dV' + 'MRT15_dH' 'MRT15_dV' + 'MRT16_dH' 'MRT16_dV' + 'MRT21_dH' 'MRT21_dV' + 'MRT22_dH' 'MRT22_dV' + 'MRT23_dH' 'MRT23_dV' + 'MRT24_dH' 'MRT24_dV' + 'MRT25_dH' 'MRT25_dV' + 'MRT26_dH' 'MRT26_dV' + 'MRT31_dH' 'MRT31_dV' + 'MRT32_dH' 'MRT32_dV' + 'MRT33_dH' 'MRT33_dV' + 'MRT34_dH' 'MRT34_dV' + 'MRT35_dH' 'MRT35_dV' + 'MRT41_dH' 'MRT41_dV' + 'MRT42_dH' 'MRT42_dV' + 'MRT43_dH' 'MRT43_dV' + 'MRT44_dH' 'MRT44_dV' + 'MZC01_dH' 'MZC01_dV' + 'MZC02_dH' 'MZC02_dV' + 'MZF01_dH' 'MZF01_dV' + 'MZF02_dH' 'MZF02_dV' + 'MZF03_dH' 'MZF03_dV' + 'MZO01_dH' 'MZO01_dV' + 'MZO02_dH' 'MZO02_dV' + 'MZP01_dH' 'MZP01_dV' + 'MZP02_dH' 'MZP02_dV' + }; + + case 'ctf275' + label = { + 'MLC11' + 'MLC12' + 'MLC13' + 'MLC14' + 'MLC15' + 'MLC16' + 'MLC17' + 'MLC21' + 'MLC22' + 'MLC23' + 'MLC24' + 'MLC25' + 'MLC31' + 'MLC32' + 'MLC41' + 'MLC42' + 'MLC51' + 'MLC52' + 'MLC53' + 'MLC54' + 'MLC55' + 'MLC61' + 'MLC62' + 'MLC63' + 'MLF11' + 'MLF12' + 'MLF13' + 'MLF14' + 'MLF21' + 'MLF22' + 'MLF23' + 'MLF24' + 'MLF25' + 'MLF31' + 'MLF32' + 'MLF33' + 'MLF34' + 'MLF35' + 'MLF41' + 'MLF42' + 'MLF43' + 'MLF44' + 'MLF45' + 'MLF46' + 'MLF51' + 'MLF52' + 'MLF53' + 'MLF54' + 'MLF55' + 'MLF56' + 'MLF61' + 'MLF62' + 'MLF63' + 'MLF64' + 'MLF65' + 'MLF66' + 'MLF67' + 'MLO11' + 'MLO12' + 'MLO13' + 'MLO14' + 'MLO21' + 'MLO22' + 'MLO23' + 'MLO24' + 'MLO31' + 'MLO32' + 'MLO33' + 'MLO34' + 'MLO41' + 'MLO42' + 'MLO43' + 'MLO44' + 'MLO51' + 'MLO52' + 'MLO53' + 'MLP11' + 'MLP12' + 'MLP21' + 'MLP22' + 'MLP23' + 'MLP31' + 'MLP32' + 'MLP33' + 'MLP34' + 'MLP35' + 'MLP41' + 'MLP42' + 'MLP43' + 'MLP44' + 'MLP45' + 'MLP51' + 'MLP52' + 'MLP53' + 'MLP54' + 'MLP55' + 'MLP56' + 'MLP57' + 'MLT11' + 'MLT12' + 'MLT13' + 'MLT14' + 'MLT15' + 'MLT16' + 'MLT21' + 'MLT22' + 'MLT23' + 'MLT24' + 'MLT25' + 'MLT26' + 'MLT27' + 'MLT31' + 'MLT32' + 'MLT33' + 'MLT34' + 'MLT35' + 'MLT36' + 'MLT37' + 'MLT41' + 'MLT42' + 'MLT43' + 'MLT44' + 'MLT45' + 'MLT46' + 'MLT47' + 'MLT51' + 'MLT52' + 'MLT53' + 'MLT54' + 'MLT55' + 'MLT56' + 'MLT57' + 'MRC11' + 'MRC12' + 'MRC13' + 'MRC14' + 'MRC15' + 'MRC16' + 'MRC17' + 'MRC21' + 'MRC22' + 'MRC23' + 'MRC24' + 'MRC25' + 'MRC31' + 'MRC32' + 'MRC41' + 'MRC42' + 'MRC51' + 'MRC52' + 'MRC53' + 'MRC54' + 'MRC55' + 'MRC61' + 'MRC62' + 'MRC63' + 'MRF11' + 'MRF12' + 'MRF13' + 'MRF14' + 'MRF21' + 'MRF22' + 'MRF23' + 'MRF24' + 'MRF25' + 'MRF31' + 'MRF32' + 'MRF33' + 'MRF34' + 'MRF35' + 'MRF41' + 'MRF42' + 'MRF43' + 'MRF44' + 'MRF45' + 'MRF46' + 'MRF51' + 'MRF52' + 'MRF53' + 'MRF54' + 'MRF55' + 'MRF56' + 'MRF61' + 'MRF62' + 'MRF63' + 'MRF64' + 'MRF65' + 'MRF66' + 'MRF67' + 'MRO11' + 'MRO12' + 'MRO13' + 'MRO14' + 'MRO21' + 'MRO22' + 'MRO23' + 'MRO24' + 'MRO31' + 'MRO32' + 'MRO33' + 'MRO34' + 'MRO41' + 'MRO42' + 'MRO43' + 'MRO44' + 'MRO51' + 'MRO52' + 'MRO53' + 'MRP11' + 'MRP12' + 'MRP21' + 'MRP22' + 'MRP23' + 'MRP32' + 'MRP33' + 'MRP34' + 'MRP35' + 'MRP41' + 'MRP42' + 'MRP43' + 'MRP44' + 'MRP45' + 'MRP51' + 'MRP52' + 'MRP53' + 'MRP54' + 'MRP55' + 'MRP56' + 'MRP57' + 'MRT11' + 'MRT12' + 'MRT13' + 'MRT14' + 'MRT15' + 'MRT16' + 'MRT21' + 'MRT22' + 'MRT23' + 'MRT24' + 'MRT25' + 'MRT26' + 'MRT27' + 'MRT31' + 'MRT32' + 'MRT33' + 'MRT34' + 'MRT35' + 'MRT36' + 'MRT37' + 'MRT41' + 'MRT42' + 'MRT43' + 'MRT44' + 'MRT45' + 'MRT46' + 'MRT47' + 'MRT51' + 'MRT52' + 'MRT53' + 'MRT54' + 'MRT55' + 'MRT56' + 'MRT57' + 'MZC01' + 'MZC02' + 'MZC03' + 'MZC04' + 'MZF01' + 'MZF02' + 'MZF03' + 'MZO01' + 'MZO02' + 'MZO03' + 'MZP01' + }; + + case 'ctf275_planar' + % FIXME one channel seems to be missing + label = { + 'MLC11_dH' 'MLC11_dV' + 'MLC12_dH' 'MLC12_dV' + 'MLC13_dH' 'MLC13_dV' + 'MLC14_dH' 'MLC14_dV' + 'MLC15_dH' 'MLC15_dV' + 'MLC16_dH' 'MLC16_dV' + 'MLC17_dH' 'MLC17_dV' + 'MLC21_dH' 'MLC21_dV' + 'MLC22_dH' 'MLC22_dV' + 'MLC23_dH' 'MLC23_dV' + 'MLC24_dH' 'MLC24_dV' + 'MLC25_dH' 'MLC25_dV' + 'MLC31_dH' 'MLC31_dV' + 'MLC32_dH' 'MLC32_dV' + 'MLC41_dH' 'MLC41_dV' + 'MLC42_dH' 'MLC42_dV' + 'MLC51_dH' 'MLC51_dV' + 'MLC52_dH' 'MLC52_dV' + 'MLC53_dH' 'MLC53_dV' + 'MLC54_dH' 'MLC54_dV' + 'MLC55_dH' 'MLC55_dV' + 'MLC61_dH' 'MLC61_dV' + 'MLC62_dH' 'MLC62_dV' + 'MLC63_dH' 'MLC63_dV' + 'MLF11_dH' 'MLF11_dV' + 'MLF12_dH' 'MLF12_dV' + 'MLF13_dH' 'MLF13_dV' + 'MLF14_dH' 'MLF14_dV' + 'MLF21_dH' 'MLF21_dV' + 'MLF22_dH' 'MLF22_dV' + 'MLF23_dH' 'MLF23_dV' + 'MLF24_dH' 'MLF24_dV' + 'MLF25_dH' 'MLF25_dV' + 'MLF31_dH' 'MLF31_dV' + 'MLF32_dH' 'MLF32_dV' + 'MLF33_dH' 'MLF33_dV' + 'MLF34_dH' 'MLF34_dV' + 'MLF35_dH' 'MLF35_dV' + 'MLF41_dH' 'MLF41_dV' + 'MLF42_dH' 'MLF42_dV' + 'MLF43_dH' 'MLF43_dV' + 'MLF44_dH' 'MLF44_dV' + 'MLF45_dH' 'MLF45_dV' + 'MLF46_dH' 'MLF46_dV' + 'MLF51_dH' 'MLF51_dV' + 'MLF52_dH' 'MLF52_dV' + 'MLF53_dH' 'MLF53_dV' + 'MLF54_dH' 'MLF54_dV' + 'MLF55_dH' 'MLF55_dV' + 'MLF56_dH' 'MLF56_dV' + 'MLF61_dH' 'MLF61_dV' + 'MLF62_dH' 'MLF62_dV' + 'MLF63_dH' 'MLF63_dV' + 'MLF64_dH' 'MLF64_dV' + 'MLF65_dH' 'MLF65_dV' + 'MLF66_dH' 'MLF66_dV' + 'MLF67_dH' 'MLF67_dV' + 'MLO11_dH' 'MLO11_dV' + 'MLO12_dH' 'MLO12_dV' + 'MLO13_dH' 'MLO13_dV' + 'MLO14_dH' 'MLO14_dV' + 'MLO21_dH' 'MLO21_dV' + 'MLO22_dH' 'MLO22_dV' + 'MLO23_dH' 'MLO23_dV' + 'MLO24_dH' 'MLO24_dV' + 'MLO31_dH' 'MLO31_dV' + 'MLO32_dH' 'MLO32_dV' + 'MLO33_dH' 'MLO33_dV' + 'MLO34_dH' 'MLO34_dV' + 'MLO41_dH' 'MLO41_dV' + 'MLO42_dH' 'MLO42_dV' + 'MLO43_dH' 'MLO43_dV' + 'MLO44_dH' 'MLO44_dV' + 'MLO51_dH' 'MLO51_dV' + 'MLO52_dH' 'MLO52_dV' + 'MLO53_dH' 'MLO53_dV' + 'MLP11_dH' 'MLP11_dV' + 'MLP12_dH' 'MLP12_dV' + 'MLP21_dH' 'MLP21_dV' + 'MLP22_dH' 'MLP22_dV' + 'MLP23_dH' 'MLP23_dV' + 'MLP31_dH' 'MLP31_dV' + 'MLP32_dH' 'MLP32_dV' + 'MLP33_dH' 'MLP33_dV' + 'MLP34_dH' 'MLP34_dV' + 'MLP35_dH' 'MLP35_dV' + 'MLP41_dH' 'MLP41_dV' + 'MLP42_dH' 'MLP42_dV' + 'MLP43_dH' 'MLP43_dV' + 'MLP44_dH' 'MLP44_dV' + 'MLP45_dH' 'MLP45_dV' + 'MLP51_dH' 'MLP51_dV' + 'MLP52_dH' 'MLP52_dV' + 'MLP53_dH' 'MLP53_dV' + 'MLP54_dH' 'MLP54_dV' + 'MLP55_dH' 'MLP55_dV' + 'MLP56_dH' 'MLP56_dV' + 'MLP57_dH' 'MLP57_dV' + 'MLT11_dH' 'MLT11_dV' + 'MLT12_dH' 'MLT12_dV' + 'MLT13_dH' 'MLT13_dV' + 'MLT14_dH' 'MLT14_dV' + 'MLT15_dH' 'MLT15_dV' + 'MLT16_dH' 'MLT16_dV' + 'MLT21_dH' 'MLT21_dV' + 'MLT22_dH' 'MLT22_dV' + 'MLT23_dH' 'MLT23_dV' + 'MLT24_dH' 'MLT24_dV' + 'MLT25_dH' 'MLT25_dV' + 'MLT26_dH' 'MLT26_dV' + 'MLT27_dH' 'MLT27_dV' + 'MLT31_dH' 'MLT31_dV' + 'MLT32_dH' 'MLT32_dV' + 'MLT33_dH' 'MLT33_dV' + 'MLT34_dH' 'MLT34_dV' + 'MLT35_dH' 'MLT35_dV' + 'MLT36_dH' 'MLT36_dV' + 'MLT37_dH' 'MLT37_dV' + 'MLT41_dH' 'MLT41_dV' + 'MLT42_dH' 'MLT42_dV' + 'MLT43_dH' 'MLT43_dV' + 'MLT44_dH' 'MLT44_dV' + 'MLT45_dH' 'MLT45_dV' + 'MLT46_dH' 'MLT46_dV' + 'MLT47_dH' 'MLT47_dV' + 'MLT51_dH' 'MLT51_dV' + 'MLT52_dH' 'MLT52_dV' + 'MLT53_dH' 'MLT53_dV' + 'MLT54_dH' 'MLT54_dV' + 'MLT55_dH' 'MLT55_dV' + 'MLT56_dH' 'MLT56_dV' + 'MLT57_dH' 'MLT57_dV' + 'MRC11_dH' 'MRC11_dV' + 'MRC12_dH' 'MRC12_dV' + 'MRC13_dH' 'MRC13_dV' + 'MRC14_dH' 'MRC14_dV' + 'MRC15_dH' 'MRC15_dV' + 'MRC16_dH' 'MRC16_dV' + 'MRC17_dH' 'MRC17_dV' + 'MRC21_dH' 'MRC21_dV' + 'MRC22_dH' 'MRC22_dV' + 'MRC23_dH' 'MRC23_dV' + 'MRC24_dH' 'MRC24_dV' + 'MRC25_dH' 'MRC25_dV' + 'MRC31_dH' 'MRC31_dV' + 'MRC32_dH' 'MRC32_dV' + 'MRC41_dH' 'MRC41_dV' + 'MRC42_dH' 'MRC42_dV' + 'MRC51_dH' 'MRC51_dV' + 'MRC52_dH' 'MRC52_dV' + 'MRC53_dH' 'MRC53_dV' + 'MRC54_dH' 'MRC54_dV' + 'MRC55_dH' 'MRC55_dV' + 'MRC61_dH' 'MRC61_dV' + 'MRC62_dH' 'MRC62_dV' + 'MRC63_dH' 'MRC63_dV' + 'MRF11_dH' 'MRF11_dV' + 'MRF12_dH' 'MRF12_dV' + 'MRF13_dH' 'MRF13_dV' + 'MRF14_dH' 'MRF14_dV' + 'MRF21_dH' 'MRF21_dV' + 'MRF22_dH' 'MRF22_dV' + 'MRF23_dH' 'MRF23_dV' + 'MRF24_dH' 'MRF24_dV' + 'MRF25_dH' 'MRF25_dV' + 'MRF31_dH' 'MRF31_dV' + 'MRF32_dH' 'MRF32_dV' + 'MRF33_dH' 'MRF33_dV' + 'MRF34_dH' 'MRF34_dV' + 'MRF35_dH' 'MRF35_dV' + 'MRF41_dH' 'MRF41_dV' + 'MRF42_dH' 'MRF42_dV' + 'MRF43_dH' 'MRF43_dV' + 'MRF44_dH' 'MRF44_dV' + 'MRF45_dH' 'MRF45_dV' + 'MRF46_dH' 'MRF46_dV' + 'MRF51_dH' 'MRF51_dV' + 'MRF52_dH' 'MRF52_dV' + 'MRF53_dH' 'MRF53_dV' + 'MRF54_dH' 'MRF54_dV' + 'MRF55_dH' 'MRF55_dV' + 'MRF56_dH' 'MRF56_dV' + 'MRF61_dH' 'MRF61_dV' + 'MRF62_dH' 'MRF62_dV' + 'MRF63_dH' 'MRF63_dV' + 'MRF64_dH' 'MRF64_dV' + 'MRF65_dH' 'MRF65_dV' + 'MRF66_dH' 'MRF66_dV' + 'MRF67_dH' 'MRF67_dV' + 'MRO11_dH' 'MRO11_dV' + 'MRO12_dH' 'MRO12_dV' + 'MRO13_dH' 'MRO13_dV' + 'MRO14_dH' 'MRO14_dV' + 'MRO21_dH' 'MRO21_dV' + 'MRO22_dH' 'MRO22_dV' + 'MRO23_dH' 'MRO23_dV' + 'MRO24_dH' 'MRO24_dV' + 'MRO31_dH' 'MRO31_dV' + 'MRO32_dH' 'MRO32_dV' + 'MRO33_dH' 'MRO33_dV' + 'MRO34_dH' 'MRO34_dV' + 'MRO41_dH' 'MRO41_dV' + 'MRO42_dH' 'MRO42_dV' + 'MRO43_dH' 'MRO43_dV' + 'MRO44_dH' 'MRO44_dV' + 'MRO51_dH' 'MRO51_dV' + 'MRO52_dH' 'MRO52_dV' + 'MRO53_dH' 'MRO53_dV' + 'MRP11_dH' 'MRP11_dV' + 'MRP12_dH' 'MRP12_dV' + 'MRP21_dH' 'MRP21_dV' + 'MRP22_dH' 'MRP22_dV' + 'MRP23_dH' 'MRP23_dV' + 'MRP32_dH' 'MRP32_dV' + 'MRP33_dH' 'MRP33_dV' + 'MRP34_dH' 'MRP34_dV' + 'MRP35_dH' 'MRP35_dV' + 'MRP41_dH' 'MRP41_dV' + 'MRP42_dH' 'MRP42_dV' + 'MRP43_dH' 'MRP43_dV' + 'MRP44_dH' 'MRP44_dV' + 'MRP45_dH' 'MRP45_dV' + 'MRP51_dH' 'MRP51_dV' + 'MRP52_dH' 'MRP52_dV' + 'MRP53_dH' 'MRP53_dV' + 'MRP54_dH' 'MRP54_dV' + 'MRP55_dH' 'MRP55_dV' + 'MRP56_dH' 'MRP56_dV' + 'MRP57_dH' 'MRP57_dV' + 'MRT11_dH' 'MRT11_dV' + 'MRT12_dH' 'MRT12_dV' + 'MRT13_dH' 'MRT13_dV' + 'MRT14_dH' 'MRT14_dV' + 'MRT15_dH' 'MRT15_dV' + 'MRT16_dH' 'MRT16_dV' + 'MRT21_dH' 'MRT21_dV' + 'MRT22_dH' 'MRT22_dV' + 'MRT23_dH' 'MRT23_dV' + 'MRT24_dH' 'MRT24_dV' + 'MRT25_dH' 'MRT25_dV' + 'MRT26_dH' 'MRT26_dV' + 'MRT27_dH' 'MRT27_dV' + 'MRT31_dH' 'MRT31_dV' + 'MRT32_dH' 'MRT32_dV' + 'MRT33_dH' 'MRT33_dV' + 'MRT34_dH' 'MRT34_dV' + 'MRT35_dH' 'MRT35_dV' + 'MRT36_dH' 'MRT36_dV' + 'MRT37_dH' 'MRT37_dV' + 'MRT41_dH' 'MRT41_dV' + 'MRT42_dH' 'MRT42_dV' + 'MRT43_dH' 'MRT43_dV' + 'MRT44_dH' 'MRT44_dV' + 'MRT45_dH' 'MRT45_dV' + 'MRT46_dH' 'MRT46_dV' + 'MRT47_dH' 'MRT47_dV' + 'MRT51_dH' 'MRT51_dV' + 'MRT52_dH' 'MRT52_dV' + 'MRT53_dH' 'MRT53_dV' + 'MRT54_dH' 'MRT54_dV' + 'MRT55_dH' 'MRT55_dV' + 'MRT56_dH' 'MRT56_dV' + 'MRT57_dH' 'MRT57_dV' + 'MZC01_dH' 'MZC01_dV' + 'MZC02_dH' 'MZC02_dV' + 'MZC03_dH' 'MZC03_dV' + 'MZC04_dH' 'MZC04_dV' + 'MZF01_dH' 'MZF01_dV' + 'MZF02_dH' 'MZF02_dV' + 'MZF03_dH' 'MZF03_dV' + 'MZO01_dH' 'MZO01_dV' + 'MZO02_dH' 'MZO02_dV' + 'MZO03_dH' 'MZO03_dV' + 'MZP01_dH' 'MZP01_dV' + }; + + + case 'neuromag122' + label = { + 'MEG 001' 'MEG 002' + 'MEG 003' 'MEG 004' + 'MEG 005' 'MEG 006' + 'MEG 007' 'MEG 008' + 'MEG 009' 'MEG 010' + 'MEG 011' 'MEG 012' + 'MEG 013' 'MEG 014' + 'MEG 015' 'MEG 016' + 'MEG 017' 'MEG 018' + 'MEG 019' 'MEG 020' + 'MEG 021' 'MEG 022' + 'MEG 023' 'MEG 024' + 'MEG 025' 'MEG 026' + 'MEG 027' 'MEG 028' + 'MEG 029' 'MEG 030' + 'MEG 031' 'MEG 032' + 'MEG 033' 'MEG 034' + 'MEG 035' 'MEG 036' + 'MEG 037' 'MEG 038' + 'MEG 039' 'MEG 040' + 'MEG 041' 'MEG 042' + 'MEG 043' 'MEG 044' + 'MEG 045' 'MEG 046' + 'MEG 047' 'MEG 048' + 'MEG 049' 'MEG 050' + 'MEG 051' 'MEG 052' + 'MEG 053' 'MEG 054' + 'MEG 055' 'MEG 056' + 'MEG 057' 'MEG 058' + 'MEG 059' 'MEG 060' + 'MEG 061' 'MEG 062' + 'MEG 063' 'MEG 064' + 'MEG 065' 'MEG 066' + 'MEG 067' 'MEG 068' + 'MEG 069' 'MEG 070' + 'MEG 071' 'MEG 072' + 'MEG 073' 'MEG 074' + 'MEG 075' 'MEG 076' + 'MEG 077' 'MEG 078' + 'MEG 079' 'MEG 080' + 'MEG 081' 'MEG 082' + 'MEG 083' 'MEG 084' + 'MEG 085' 'MEG 086' + 'MEG 087' 'MEG 088' + 'MEG 089' 'MEG 090' + 'MEG 091' 'MEG 092' + 'MEG 093' 'MEG 094' + 'MEG 095' 'MEG 096' + 'MEG 097' 'MEG 098' + 'MEG 099' 'MEG 100' + 'MEG 101' 'MEG 102' + 'MEG 103' 'MEG 104' + 'MEG 105' 'MEG 106' + 'MEG 107' 'MEG 108' + 'MEG 109' 'MEG 110' + 'MEG 111' 'MEG 112' + 'MEG 113' 'MEG 114' + 'MEG 115' 'MEG 116' + 'MEG 117' 'MEG 118' + 'MEG 119' 'MEG 120' + 'MEG 121' 'MEG 122' + }; + + case 'neuromag122alt' + % this is an alternative set of labels without a space in them + label = { + 'MEG001' 'MEG002' + 'MEG003' 'MEG004' + 'MEG005' 'MEG006' + 'MEG007' 'MEG008' + 'MEG009' 'MEG010' + 'MEG011' 'MEG012' + 'MEG013' 'MEG014' + 'MEG015' 'MEG016' + 'MEG017' 'MEG018' + 'MEG019' 'MEG020' + 'MEG021' 'MEG022' + 'MEG023' 'MEG024' + 'MEG025' 'MEG026' + 'MEG027' 'MEG028' + 'MEG029' 'MEG030' + 'MEG031' 'MEG032' + 'MEG033' 'MEG034' + 'MEG035' 'MEG036' + 'MEG037' 'MEG038' + 'MEG039' 'MEG040' + 'MEG041' 'MEG042' + 'MEG043' 'MEG044' + 'MEG045' 'MEG046' + 'MEG047' 'MEG048' + 'MEG049' 'MEG050' + 'MEG051' 'MEG052' + 'MEG053' 'MEG054' + 'MEG055' 'MEG056' + 'MEG057' 'MEG058' + 'MEG059' 'MEG060' + 'MEG061' 'MEG062' + 'MEG063' 'MEG064' + 'MEG065' 'MEG066' + 'MEG067' 'MEG068' + 'MEG069' 'MEG070' + 'MEG071' 'MEG072' + 'MEG073' 'MEG074' + 'MEG075' 'MEG076' + 'MEG077' 'MEG078' + 'MEG079' 'MEG080' + 'MEG081' 'MEG082' + 'MEG083' 'MEG084' + 'MEG085' 'MEG086' + 'MEG087' 'MEG088' + 'MEG089' 'MEG090' + 'MEG091' 'MEG092' + 'MEG093' 'MEG094' + 'MEG095' 'MEG096' + 'MEG097' 'MEG098' + 'MEG099' 'MEG100' + 'MEG101' 'MEG102' + 'MEG103' 'MEG104' + 'MEG105' 'MEG106' + 'MEG107' 'MEG108' + 'MEG109' 'MEG110' + 'MEG111' 'MEG112' + 'MEG113' 'MEG114' + 'MEG115' 'MEG116' + 'MEG117' 'MEG118' + 'MEG119' 'MEG120' + 'MEG121' 'MEG122' + }; + + case 'neuromag306' + label = { + 'MEG 0113' 'MEG 0112' 'MEG 0111' + 'MEG 0122' 'MEG 0123' 'MEG 0121' + 'MEG 0132' 'MEG 0133' 'MEG 0131' + 'MEG 0143' 'MEG 0142' 'MEG 0141' + 'MEG 0213' 'MEG 0212' 'MEG 0211' + 'MEG 0222' 'MEG 0223' 'MEG 0221' + 'MEG 0232' 'MEG 0233' 'MEG 0231' + 'MEG 0243' 'MEG 0242' 'MEG 0241' + 'MEG 0313' 'MEG 0312' 'MEG 0311' + 'MEG 0322' 'MEG 0323' 'MEG 0321' + 'MEG 0333' 'MEG 0332' 'MEG 0331' + 'MEG 0343' 'MEG 0342' 'MEG 0341' + 'MEG 0413' 'MEG 0412' 'MEG 0411' + 'MEG 0422' 'MEG 0423' 'MEG 0421' + 'MEG 0432' 'MEG 0433' 'MEG 0431' + 'MEG 0443' 'MEG 0442' 'MEG 0441' + 'MEG 0513' 'MEG 0512' 'MEG 0511' + 'MEG 0523' 'MEG 0522' 'MEG 0521' + 'MEG 0532' 'MEG 0533' 'MEG 0531' + 'MEG 0542' 'MEG 0543' 'MEG 0541' + 'MEG 0613' 'MEG 0612' 'MEG 0611' + 'MEG 0622' 'MEG 0623' 'MEG 0621' + 'MEG 0633' 'MEG 0632' 'MEG 0631' + 'MEG 0642' 'MEG 0643' 'MEG 0641' + 'MEG 0713' 'MEG 0712' 'MEG 0711' + 'MEG 0723' 'MEG 0722' 'MEG 0721' + 'MEG 0733' 'MEG 0732' 'MEG 0731' + 'MEG 0743' 'MEG 0742' 'MEG 0741' + 'MEG 0813' 'MEG 0812' 'MEG 0811' + 'MEG 0822' 'MEG 0823' 'MEG 0821' + 'MEG 0913' 'MEG 0912' 'MEG 0911' + 'MEG 0923' 'MEG 0922' 'MEG 0921' + 'MEG 0932' 'MEG 0933' 'MEG 0931' + 'MEG 0942' 'MEG 0943' 'MEG 0941' + 'MEG 1013' 'MEG 1012' 'MEG 1011' + 'MEG 1023' 'MEG 1022' 'MEG 1021' + 'MEG 1032' 'MEG 1033' 'MEG 1031' + 'MEG 1043' 'MEG 1042' 'MEG 1041' + 'MEG 1112' 'MEG 1113' 'MEG 1111' + 'MEG 1123' 'MEG 1122' 'MEG 1121' + 'MEG 1133' 'MEG 1132' 'MEG 1131' + 'MEG 1142' 'MEG 1143' 'MEG 1141' + 'MEG 1213' 'MEG 1212' 'MEG 1211' + 'MEG 1223' 'MEG 1222' 'MEG 1221' + 'MEG 1232' 'MEG 1233' 'MEG 1231' + 'MEG 1243' 'MEG 1242' 'MEG 1241' + 'MEG 1312' 'MEG 1313' 'MEG 1311' + 'MEG 1323' 'MEG 1322' 'MEG 1321' + 'MEG 1333' 'MEG 1332' 'MEG 1331' + 'MEG 1342' 'MEG 1343' 'MEG 1341' + 'MEG 1412' 'MEG 1413' 'MEG 1411' + 'MEG 1423' 'MEG 1422' 'MEG 1421' + 'MEG 1433' 'MEG 1432' 'MEG 1431' + 'MEG 1442' 'MEG 1443' 'MEG 1441' + 'MEG 1512' 'MEG 1513' 'MEG 1511' + 'MEG 1522' 'MEG 1523' 'MEG 1521' + 'MEG 1533' 'MEG 1532' 'MEG 1531' + 'MEG 1543' 'MEG 1542' 'MEG 1541' + 'MEG 1613' 'MEG 1612' 'MEG 1611' + 'MEG 1622' 'MEG 1623' 'MEG 1621' + 'MEG 1632' 'MEG 1633' 'MEG 1631' + 'MEG 1643' 'MEG 1642' 'MEG 1641' + 'MEG 1713' 'MEG 1712' 'MEG 1711' + 'MEG 1722' 'MEG 1723' 'MEG 1721' + 'MEG 1732' 'MEG 1733' 'MEG 1731' + 'MEG 1743' 'MEG 1742' 'MEG 1741' + 'MEG 1813' 'MEG 1812' 'MEG 1811' + 'MEG 1822' 'MEG 1823' 'MEG 1821' + 'MEG 1832' 'MEG 1833' 'MEG 1831' + 'MEG 1843' 'MEG 1842' 'MEG 1841' + 'MEG 1912' 'MEG 1913' 'MEG 1911' + 'MEG 1923' 'MEG 1922' 'MEG 1921' + 'MEG 1932' 'MEG 1933' 'MEG 1931' + 'MEG 1943' 'MEG 1942' 'MEG 1941' + 'MEG 2013' 'MEG 2012' 'MEG 2011' + 'MEG 2023' 'MEG 2022' 'MEG 2021' + 'MEG 2032' 'MEG 2033' 'MEG 2031' + 'MEG 2042' 'MEG 2043' 'MEG 2041' + 'MEG 2113' 'MEG 2112' 'MEG 2111' + 'MEG 2122' 'MEG 2123' 'MEG 2121' + 'MEG 2133' 'MEG 2132' 'MEG 2131' + 'MEG 2143' 'MEG 2142' 'MEG 2141' + 'MEG 2212' 'MEG 2213' 'MEG 2211' + 'MEG 2223' 'MEG 2222' 'MEG 2221' + 'MEG 2233' 'MEG 2232' 'MEG 2231' + 'MEG 2242' 'MEG 2243' 'MEG 2241' + 'MEG 2312' 'MEG 2313' 'MEG 2311' + 'MEG 2323' 'MEG 2322' 'MEG 2321' + 'MEG 2332' 'MEG 2333' 'MEG 2331' + 'MEG 2343' 'MEG 2342' 'MEG 2341' + 'MEG 2412' 'MEG 2413' 'MEG 2411' + 'MEG 2423' 'MEG 2422' 'MEG 2421' + 'MEG 2433' 'MEG 2432' 'MEG 2431' + 'MEG 2442' 'MEG 2443' 'MEG 2441' + 'MEG 2512' 'MEG 2513' 'MEG 2511' + 'MEG 2522' 'MEG 2523' 'MEG 2521' + 'MEG 2533' 'MEG 2532' 'MEG 2531' + 'MEG 2543' 'MEG 2542' 'MEG 2541' + 'MEG 2612' 'MEG 2613' 'MEG 2611' + 'MEG 2623' 'MEG 2622' 'MEG 2621' + 'MEG 2633' 'MEG 2632' 'MEG 2631' + 'MEG 2642' 'MEG 2643' 'MEG 2641' + }; + + case 'neuromag306alt' + % this is an alternative set of labels without a space in them + label = { + 'MEG0113' 'MEG0112' 'MEG0111' + 'MEG0122' 'MEG0123' 'MEG0121' + 'MEG0132' 'MEG0133' 'MEG0131' + 'MEG0143' 'MEG0142' 'MEG0141' + 'MEG0213' 'MEG0212' 'MEG0211' + 'MEG0222' 'MEG0223' 'MEG0221' + 'MEG0232' 'MEG0233' 'MEG0231' + 'MEG0243' 'MEG0242' 'MEG0241' + 'MEG0313' 'MEG0312' 'MEG0311' + 'MEG0322' 'MEG0323' 'MEG0321' + 'MEG0333' 'MEG0332' 'MEG0331' + 'MEG0343' 'MEG0342' 'MEG0341' + 'MEG0413' 'MEG0412' 'MEG0411' + 'MEG0422' 'MEG0423' 'MEG0421' + 'MEG0432' 'MEG0433' 'MEG0431' + 'MEG0443' 'MEG0442' 'MEG0441' + 'MEG0513' 'MEG0512' 'MEG0511' + 'MEG0523' 'MEG0522' 'MEG0521' + 'MEG0532' 'MEG0533' 'MEG0531' + 'MEG0542' 'MEG0543' 'MEG0541' + 'MEG0613' 'MEG0612' 'MEG0611' + 'MEG0622' 'MEG0623' 'MEG0621' + 'MEG0633' 'MEG0632' 'MEG0631' + 'MEG0642' 'MEG0643' 'MEG0641' + 'MEG0713' 'MEG0712' 'MEG0711' + 'MEG0723' 'MEG0722' 'MEG0721' + 'MEG0733' 'MEG0732' 'MEG0731' + 'MEG0743' 'MEG0742' 'MEG0741' + 'MEG0813' 'MEG0812' 'MEG0811' + 'MEG0822' 'MEG0823' 'MEG0821' + 'MEG0913' 'MEG0912' 'MEG0911' + 'MEG0923' 'MEG0922' 'MEG0921' + 'MEG0932' 'MEG0933' 'MEG0931' + 'MEG0942' 'MEG0943' 'MEG0941' + 'MEG1013' 'MEG1012' 'MEG1011' + 'MEG1023' 'MEG1022' 'MEG1021' + 'MEG1032' 'MEG1033' 'MEG1031' + 'MEG1043' 'MEG1042' 'MEG1041' + 'MEG1112' 'MEG1113' 'MEG1111' + 'MEG1123' 'MEG1122' 'MEG1121' + 'MEG1133' 'MEG1132' 'MEG1131' + 'MEG1142' 'MEG1143' 'MEG1141' + 'MEG1213' 'MEG1212' 'MEG1211' + 'MEG1223' 'MEG1222' 'MEG1221' + 'MEG1232' 'MEG1233' 'MEG1231' + 'MEG1243' 'MEG1242' 'MEG1241' + 'MEG1312' 'MEG1313' 'MEG1311' + 'MEG1323' 'MEG1322' 'MEG1321' + 'MEG1333' 'MEG1332' 'MEG1331' + 'MEG1342' 'MEG1343' 'MEG1341' + 'MEG1412' 'MEG1413' 'MEG1411' + 'MEG1423' 'MEG1422' 'MEG1421' + 'MEG1433' 'MEG1432' 'MEG1431' + 'MEG1442' 'MEG1443' 'MEG1441' + 'MEG1512' 'MEG1513' 'MEG1511' + 'MEG1522' 'MEG1523' 'MEG1521' + 'MEG1533' 'MEG1532' 'MEG1531' + 'MEG1543' 'MEG1542' 'MEG1541' + 'MEG1613' 'MEG1612' 'MEG1611' + 'MEG1622' 'MEG1623' 'MEG1621' + 'MEG1632' 'MEG1633' 'MEG1631' + 'MEG1643' 'MEG1642' 'MEG1641' + 'MEG1713' 'MEG1712' 'MEG1711' + 'MEG1722' 'MEG1723' 'MEG1721' + 'MEG1732' 'MEG1733' 'MEG1731' + 'MEG1743' 'MEG1742' 'MEG1741' + 'MEG1813' 'MEG1812' 'MEG1811' + 'MEG1822' 'MEG1823' 'MEG1821' + 'MEG1832' 'MEG1833' 'MEG1831' + 'MEG1843' 'MEG1842' 'MEG1841' + 'MEG1912' 'MEG1913' 'MEG1911' + 'MEG1923' 'MEG1922' 'MEG1921' + 'MEG1932' 'MEG1933' 'MEG1931' + 'MEG1943' 'MEG1942' 'MEG1941' + 'MEG2013' 'MEG2012' 'MEG2011' + 'MEG2023' 'MEG2022' 'MEG2021' + 'MEG2032' 'MEG2033' 'MEG2031' + 'MEG2042' 'MEG2043' 'MEG2041' + 'MEG2113' 'MEG2112' 'MEG2111' + 'MEG2122' 'MEG2123' 'MEG2121' + 'MEG2133' 'MEG2132' 'MEG2131' + 'MEG2143' 'MEG2142' 'MEG2141' + 'MEG2212' 'MEG2213' 'MEG2211' + 'MEG2223' 'MEG2222' 'MEG2221' + 'MEG2233' 'MEG2232' 'MEG2231' + 'MEG2242' 'MEG2243' 'MEG2241' + 'MEG2312' 'MEG2313' 'MEG2311' + 'MEG2323' 'MEG2322' 'MEG2321' + 'MEG2332' 'MEG2333' 'MEG2331' + 'MEG2343' 'MEG2342' 'MEG2341' + 'MEG2412' 'MEG2413' 'MEG2411' + 'MEG2423' 'MEG2422' 'MEG2421' + 'MEG2433' 'MEG2432' 'MEG2431' + 'MEG2442' 'MEG2443' 'MEG2441' + 'MEG2512' 'MEG2513' 'MEG2511' + 'MEG2522' 'MEG2523' 'MEG2521' + 'MEG2533' 'MEG2532' 'MEG2531' + 'MEG2543' 'MEG2542' 'MEG2541' + 'MEG2612' 'MEG2613' 'MEG2611' + 'MEG2623' 'MEG2622' 'MEG2621' + 'MEG2633' 'MEG2632' 'MEG2631' + 'MEG2642' 'MEG2643' 'MEG2641' + }; + + + case 'eeg1020' + label = { + 'Fp1' + 'Fpz' + 'Fp2' + 'F7' + 'F3' + 'Fz' + 'F4' + 'F8' + 'T7' + 'C3' + 'Cz' + 'C4' + 'T8' + 'P7' + 'P3' + 'Pz' + 'P4' + 'P8' + 'O1' + 'Oz' + 'O2'}; + + case 'eeg1010' + label = { + 'Fp1' + 'Fpz' + 'Fp2' + 'AF9' + 'AF7' + 'AF5' + 'AF3' + 'AF1' + 'AFz' + 'AF2' + 'AF4' + 'AF6' + 'AF8' + 'AF10' + 'F9' + 'F7' + 'F5' + 'F3' + 'F1' + 'Fz' + 'F2' + 'F4' + 'F6' + 'F8' + 'F10' + 'FT9' + 'FT7' + 'FC5' + 'FC3' + 'FC1' + 'FCz' + 'FC2' + 'FC4' + 'FC6' + 'FT8' + 'FT10' + 'T9' + 'T7' + 'C5' + 'C3' + 'C1' + 'Cz' + 'C2' + 'C4' + 'C6' + 'T8' + 'T10' + 'TP9' + 'TP7' + 'CP5' + 'CP3' + 'CP1' + 'CPz' + 'CP2' + 'CP4' + 'CP6' + 'TP8' + 'TP10' + 'P9' + 'P7' + 'P5' + 'P3' + 'P1' + 'Pz' + 'P2' + 'P4' + 'P6' + 'P8' + 'P10' + 'PO9' + 'PO7' + 'PO5' + 'PO3' + 'PO1' + 'POz' + 'PO2' + 'PO4' + 'PO6' + 'PO8' + 'PO10' + 'O1' + 'Oz' + 'O2' + 'I1' + 'Iz' + 'I2' + }; + + case 'eeg1005' + label = { + 'Fp1' + 'Fpz' + 'Fp2' + 'AF9' + 'AF7' + 'AF5' + 'AF3' + 'AF1' + 'AFz' + 'AF2' + 'AF4' + 'AF6' + 'AF8' + 'AF10' + 'F9' + 'F7' + 'F5' + 'F3' + 'F1' + 'Fz' + 'F2' + 'F4' + 'F6' + 'F8' + 'F10' + 'FT9' + 'FT7' + 'FC5' + 'FC3' + 'FC1' + 'FCz' + 'FC2' + 'FC4' + 'FC6' + 'FT8' + 'FT10' + 'T9' + 'T7' + 'C5' + 'C3' + 'C1' + 'Cz' + 'C2' + 'C4' + 'C6' + 'T8' + 'T10' + 'TP9' + 'TP7' + 'CP5' + 'CP3' + 'CP1' + 'CPz' + 'CP2' + 'CP4' + 'CP6' + 'TP8' + 'TP10' + 'P9' + 'P7' + 'P5' + 'P3' + 'P1' + 'Pz' + 'P2' + 'P4' + 'P6' + 'P8' + 'P10' + 'PO9' + 'PO7' + 'PO5' + 'PO3' + 'PO1' + 'POz' + 'PO2' + 'PO4' + 'PO6' + 'PO8' + 'PO10' + 'O1' + 'Oz' + 'O2' + 'I1' + 'Iz' + 'I2' + 'AFp9h' + 'AFp7h' + 'AFp5h' + 'AFp3h' + 'AFp1h' + 'AFp2h' + 'AFp4h' + 'AFp6h' + 'AFp8h' + 'AFp10h' + 'AFF9h' + 'AFF7h' + 'AFF5h' + 'AFF3h' + 'AFF1h' + 'AFF2h' + 'AFF4h' + 'AFF6h' + 'AFF8h' + 'AFF10h' + 'FFT9h' + 'FFT7h' + 'FFC5h' + 'FFC3h' + 'FFC1h' + 'FFC2h' + 'FFC4h' + 'FFC6h' + 'FFT8h' + 'FFT10h' + 'FTT9h' + 'FTT7h' + 'FCC5h' + 'FCC3h' + 'FCC1h' + 'FCC2h' + 'FCC4h' + 'FCC6h' + 'FTT8h' + 'FTT10h' + 'TTP9h' + 'TTP7h' + 'CCP5h' + 'CCP3h' + 'CCP1h' + 'CCP2h' + 'CCP4h' + 'CCP6h' + 'TTP8h' + 'TTP10h' + 'TPP9h' + 'TPP7h' + 'CPP5h' + 'CPP3h' + 'CPP1h' + 'CPP2h' + 'CPP4h' + 'CPP6h' + 'TPP8h' + 'TPP10h' + 'PPO9h' + 'PPO7h' + 'PPO5h' + 'PPO3h' + 'PPO1h' + 'PPO2h' + 'PPO4h' + 'PPO6h' + 'PPO8h' + 'PPO10h' + 'POO9h' + 'POO7h' + 'POO5h' + 'POO3h' + 'POO1h' + 'POO2h' + 'POO4h' + 'POO6h' + 'POO8h' + 'POO10h' + 'OI1h' + 'OI2h' + 'Fp1h' + 'Fp2h' + 'AF9h' + 'AF7h' + 'AF5h' + 'AF3h' + 'AF1h' + 'AF2h' + 'AF4h' + 'AF6h' + 'AF8h' + 'AF10h' + 'F9h' + 'F7h' + 'F5h' + 'F3h' + 'F1h' + 'F2h' + 'F4h' + 'F6h' + 'F8h' + 'F10h' + 'FT9h' + 'FT7h' + 'FC5h' + 'FC3h' + 'FC1h' + 'FC2h' + 'FC4h' + 'FC6h' + 'FT8h' + 'FT10h' + 'T9h' + 'T7h' + 'C5h' + 'C3h' + 'C1h' + 'C2h' + 'C4h' + 'C6h' + 'T8h' + 'T10h' + 'TP9h' + 'TP7h' + 'CP5h' + 'CP3h' + 'CP1h' + 'CP2h' + 'CP4h' + 'CP6h' + 'TP8h' + 'TP10h' + 'P9h' + 'P7h' + 'P5h' + 'P3h' + 'P1h' + 'P2h' + 'P4h' + 'P6h' + 'P8h' + 'P10h' + 'PO9h' + 'PO7h' + 'PO5h' + 'PO3h' + 'PO1h' + 'PO2h' + 'PO4h' + 'PO6h' + 'PO8h' + 'PO10h' + 'O1h' + 'O2h' + 'I1h' + 'I2h' + 'AFp9' + 'AFp7' + 'AFp5' + 'AFp3' + 'AFp1' + 'AFpz' + 'AFp2' + 'AFp4' + 'AFp6' + 'AFp8' + 'AFp10' + 'AFF9' + 'AFF7' + 'AFF5' + 'AFF3' + 'AFF1' + 'AFFz' + 'AFF2' + 'AFF4' + 'AFF6' + 'AFF8' + 'AFF10' + 'FFT9' + 'FFT7' + 'FFC5' + 'FFC3' + 'FFC1' + 'FFCz' + 'FFC2' + 'FFC4' + 'FFC6' + 'FFT8' + 'FFT10' + 'FTT9' + 'FTT7' + 'FCC5' + 'FCC3' + 'FCC1' + 'FCCz' + 'FCC2' + 'FCC4' + 'FCC6' + 'FTT8' + 'FTT10' + 'TTP9' + 'TTP7' + 'CCP5' + 'CCP3' + 'CCP1' + 'CCPz' + 'CCP2' + 'CCP4' + 'CCP6' + 'TTP8' + 'TTP10' + 'TPP9' + 'TPP7' + 'CPP5' + 'CPP3' + 'CPP1' + 'CPPz' + 'CPP2' + 'CPP4' + 'CPP6' + 'TPP8' + 'TPP10' + 'PPO9' + 'PPO7' + 'PPO5' + 'PPO3' + 'PPO1' + 'PPOz' + 'PPO2' + 'PPO4' + 'PPO6' + 'PPO8' + 'PPO10' + 'POO9' + 'POO7' + 'POO5' + 'POO3' + 'POO1' + 'POOz' + 'POO2' + 'POO4' + 'POO6' + 'POO8' + 'POO10' + 'OI1' + 'OIz' + 'OI2' + }; + + case 'ext1020' + % start with the eeg1005 list + label = { + 'Fp1' + 'Fpz' + 'Fp2' + 'AF9' + 'AF7' + 'AF5' + 'AF3' + 'AF1' + 'AFz' + 'AF2' + 'AF4' + 'AF6' + 'AF8' + 'AF10' + 'F9' + 'F7' + 'F5' + 'F3' + 'F1' + 'Fz' + 'F2' + 'F4' + 'F6' + 'F8' + 'F10' + 'FT9' + 'FT7' + 'FC5' + 'FC3' + 'FC1' + 'FCz' + 'FC2' + 'FC4' + 'FC6' + 'FT8' + 'FT10' + 'T9' + 'T7' + 'C5' + 'C3' + 'C1' + 'Cz' + 'C2' + 'C4' + 'C6' + 'T8' + 'T10' + 'TP9' + 'TP7' + 'CP5' + 'CP3' + 'CP1' + 'CPz' + 'CP2' + 'CP4' + 'CP6' + 'TP8' + 'TP10' + 'P9' + 'P7' + 'P5' + 'P3' + 'P1' + 'Pz' + 'P2' + 'P4' + 'P6' + 'P8' + 'P10' + 'PO9' + 'PO7' + 'PO5' + 'PO3' + 'PO1' + 'POz' + 'PO2' + 'PO4' + 'PO6' + 'PO8' + 'PO10' + 'O1' + 'Oz' + 'O2' + 'I1' + 'Iz' + 'I2' + 'AFp9h' + 'AFp7h' + 'AFp5h' + 'AFp3h' + 'AFp1h' + 'AFp2h' + 'AFp4h' + 'AFp6h' + 'AFp8h' + 'AFp10h' + 'AFF9h' + 'AFF7h' + 'AFF5h' + 'AFF3h' + 'AFF1h' + 'AFF2h' + 'AFF4h' + 'AFF6h' + 'AFF8h' + 'AFF10h' + 'FFT9h' + 'FFT7h' + 'FFC5h' + 'FFC3h' + 'FFC1h' + 'FFC2h' + 'FFC4h' + 'FFC6h' + 'FFT8h' + 'FFT10h' + 'FTT9h' + 'FTT7h' + 'FCC5h' + 'FCC3h' + 'FCC1h' + 'FCC2h' + 'FCC4h' + 'FCC6h' + 'FTT8h' + 'FTT10h' + 'TTP9h' + 'TTP7h' + 'CCP5h' + 'CCP3h' + 'CCP1h' + 'CCP2h' + 'CCP4h' + 'CCP6h' + 'TTP8h' + 'TTP10h' + 'TPP9h' + 'TPP7h' + 'CPP5h' + 'CPP3h' + 'CPP1h' + 'CPP2h' + 'CPP4h' + 'CPP6h' + 'TPP8h' + 'TPP10h' + 'PPO9h' + 'PPO7h' + 'PPO5h' + 'PPO3h' + 'PPO1h' + 'PPO2h' + 'PPO4h' + 'PPO6h' + 'PPO8h' + 'PPO10h' + 'POO9h' + 'POO7h' + 'POO5h' + 'POO3h' + 'POO1h' + 'POO2h' + 'POO4h' + 'POO6h' + 'POO8h' + 'POO10h' + 'OI1h' + 'OI2h' + 'Fp1h' + 'Fp2h' + 'AF9h' + 'AF7h' + 'AF5h' + 'AF3h' + 'AF1h' + 'AF2h' + 'AF4h' + 'AF6h' + 'AF8h' + 'AF10h' + 'F9h' + 'F7h' + 'F5h' + 'F3h' + 'F1h' + 'F2h' + 'F4h' + 'F6h' + 'F8h' + 'F10h' + 'FT9h' + 'FT7h' + 'FC5h' + 'FC3h' + 'FC1h' + 'FC2h' + 'FC4h' + 'FC6h' + 'FT8h' + 'FT10h' + 'T9h' + 'T7h' + 'C5h' + 'C3h' + 'C1h' + 'C2h' + 'C4h' + 'C6h' + 'T8h' + 'T10h' + 'TP9h' + 'TP7h' + 'CP5h' + 'CP3h' + 'CP1h' + 'CP2h' + 'CP4h' + 'CP6h' + 'TP8h' + 'TP10h' + 'P9h' + 'P7h' + 'P5h' + 'P3h' + 'P1h' + 'P2h' + 'P4h' + 'P6h' + 'P8h' + 'P10h' + 'PO9h' + 'PO7h' + 'PO5h' + 'PO3h' + 'PO1h' + 'PO2h' + 'PO4h' + 'PO6h' + 'PO8h' + 'PO10h' + 'O1h' + 'O2h' + 'I1h' + 'I2h' + 'AFp9' + 'AFp7' + 'AFp5' + 'AFp3' + 'AFp1' + 'AFpz' + 'AFp2' + 'AFp4' + 'AFp6' + 'AFp8' + 'AFp10' + 'AFF9' + 'AFF7' + 'AFF5' + 'AFF3' + 'AFF1' + 'AFFz' + 'AFF2' + 'AFF4' + 'AFF6' + 'AFF8' + 'AFF10' + 'FFT9' + 'FFT7' + 'FFC5' + 'FFC3' + 'FFC1' + 'FFCz' + 'FFC2' + 'FFC4' + 'FFC6' + 'FFT8' + 'FFT10' + 'FTT9' + 'FTT7' + 'FCC5' + 'FCC3' + 'FCC1' + 'FCCz' + 'FCC2' + 'FCC4' + 'FCC6' + 'FTT8' + 'FTT10' + 'TTP9' + 'TTP7' + 'CCP5' + 'CCP3' + 'CCP1' + 'CCPz' + 'CCP2' + 'CCP4' + 'CCP6' + 'TTP8' + 'TTP10' + 'TPP9' + 'TPP7' + 'CPP5' + 'CPP3' + 'CPP1' + 'CPPz' + 'CPP2' + 'CPP4' + 'CPP6' + 'TPP8' + 'TPP10' + 'PPO9' + 'PPO7' + 'PPO5' + 'PPO3' + 'PPO1' + 'PPOz' + 'PPO2' + 'PPO4' + 'PPO6' + 'PPO8' + 'PPO10' + 'POO9' + 'POO7' + 'POO5' + 'POO3' + 'POO1' + 'POOz' + 'POO2' + 'POO4' + 'POO6' + 'POO8' + 'POO10' + 'OI1' + 'OIz' + 'OI2' + }; + + % Add also alternative labels that are used in some systems + label = cat(1, label, {'A1' 'A2' 'M1' 'M2' 'T3' 'T4' 'T5' 'T6'}'); + + % This is to account for all variants of case in 1020 systems + label = unique(cat(1, label, upper(label), lower(label))); + + case 'biosemi64' + label = { + 'A1' + 'A2' + 'A3' + 'A4' + 'A5' + 'A6' + 'A7' + 'A8' + 'A9' + 'A10' + 'A11' + 'A12' + 'A13' + 'A14' + 'A15' + 'A16' + 'A17' + 'A18' + 'A19' + 'A20' + 'A21' + 'A22' + 'A23' + 'A24' + 'A25' + 'A26' + 'A27' + 'A28' + 'A29' + 'A30' + 'A31' + 'A32' + 'B1' + 'B2' + 'B3' + 'B4' + 'B5' + 'B6' + 'B7' + 'B8' + 'B9' + 'B10' + 'B11' + 'B12' + 'B13' + 'B14' + 'B15' + 'B16' + 'B17' + 'B18' + 'B19' + 'B20' + 'B21' + 'B22' + 'B23' + 'B24' + 'B25' + 'B26' + 'B27' + 'B28' + 'B29' + 'B30' + 'B31' + 'B32' + }; + + case 'biosemi128' + label = { + 'A1' + 'A2' + 'A3' + 'A4' + 'A5' + 'A6' + 'A7' + 'A8' + 'A9' + 'A10' + 'A11' + 'A12' + 'A13' + 'A14' + 'A15' + 'A16' + 'A17' + 'A18' + 'A19' + 'A20' + 'A21' + 'A22' + 'A23' + 'A24' + 'A25' + 'A26' + 'A27' + 'A28' + 'A29' + 'A30' + 'A31' + 'A32' + 'B1' + 'B2' + 'B3' + 'B4' + 'B5' + 'B6' + 'B7' + 'B8' + 'B9' + 'B10' + 'B11' + 'B12' + 'B13' + 'B14' + 'B15' + 'B16' + 'B17' + 'B18' + 'B19' + 'B20' + 'B21' + 'B22' + 'B23' + 'B24' + 'B25' + 'B26' + 'B27' + 'B28' + 'B29' + 'B30' + 'B31' + 'B32' + 'C1' + 'C2' + 'C3' + 'C4' + 'C5' + 'C6' + 'C7' + 'C8' + 'C9' + 'C10' + 'C11' + 'C12' + 'C13' + 'C14' + 'C15' + 'C16' + 'C17' + 'C18' + 'C19' + 'C20' + 'C21' + 'C22' + 'C23' + 'C24' + 'C25' + 'C26' + 'C27' + 'C28' + 'C29' + 'C30' + 'C31' + 'C32' + 'D1' + 'D2' + 'D3' + 'D4' + 'D5' + 'D6' + 'D7' + 'D8' + 'D9' + 'D10' + 'D11' + 'D12' + 'D13' + 'D14' + 'D15' + 'D16' + 'D17' + 'D18' + 'D19' + 'D20' + 'D21' + 'D22' + 'D23' + 'D24' + 'D25' + 'D26' + 'D27' + 'D28' + 'D29' + 'D30' + 'D31' + 'D32' + }; + + case 'biosemi256' + label = { + 'A1' + 'A2' + 'A3' + 'A4' + 'A5' + 'A6' + 'A7' + 'A8' + 'A9' + 'A10' + 'A11' + 'A12' + 'A13' + 'A14' + 'A15' + 'A16' + 'A17' + 'A18' + 'A19' + 'A20' + 'A21' + 'A22' + 'A23' + 'A24' + 'A25' + 'A26' + 'A27' + 'A28' + 'A29' + 'A30' + 'A31' + 'A32' + 'B1' + 'B2' + 'B3' + 'B4' + 'B5' + 'B6' + 'B7' + 'B8' + 'B9' + 'B10' + 'B11' + 'B12' + 'B13' + 'B14' + 'B15' + 'B16' + 'B17' + 'B18' + 'B19' + 'B20' + 'B21' + 'B22' + 'B23' + 'B24' + 'B25' + 'B26' + 'B27' + 'B28' + 'B29' + 'B30' + 'B31' + 'B32' + 'C1' + 'C2' + 'C3' + 'C4' + 'C5' + 'C6' + 'C7' + 'C8' + 'C9' + 'C10' + 'C11' + 'C12' + 'C13' + 'C14' + 'C15' + 'C16' + 'C17' + 'C18' + 'C19' + 'C20' + 'C21' + 'C22' + 'C23' + 'C24' + 'C25' + 'C26' + 'C27' + 'C28' + 'C29' + 'C30' + 'C31' + 'C32' + 'D1' + 'D2' + 'D3' + 'D4' + 'D5' + 'D6' + 'D7' + 'D8' + 'D9' + 'D10' + 'D11' + 'D12' + 'D13' + 'D14' + 'D15' + 'D16' + 'D17' + 'D18' + 'D19' + 'D20' + 'D21' + 'D22' + 'D23' + 'D24' + 'D25' + 'D26' + 'D27' + 'D28' + 'D29' + 'D30' + 'D31' + 'D32' + 'E1' + 'E2' + 'E3' + 'E4' + 'E5' + 'E6' + 'E7' + 'E8' + 'E9' + 'E10' + 'E11' + 'E12' + 'E13' + 'E14' + 'E15' + 'E16' + 'E17' + 'E18' + 'E19' + 'E20' + 'E21' + 'E22' + 'E23' + 'E24' + 'E25' + 'E26' + 'E27' + 'E28' + 'E29' + 'E30' + 'E31' + 'E32' + 'F1' + 'F2' + 'F3' + 'F4' + 'F5' + 'F6' + 'F7' + 'F8' + 'F9' + 'F10' + 'F11' + 'F12' + 'F13' + 'F14' + 'F15' + 'F16' + 'F17' + 'F18' + 'F19' + 'F20' + 'F21' + 'F22' + 'F23' + 'F24' + 'F25' + 'F26' + 'F27' + 'F28' + 'F29' + 'F30' + 'F31' + 'F32' + 'G1' + 'G2' + 'G3' + 'G4' + 'G5' + 'G6' + 'G7' + 'G8' + 'G9' + 'G10' + 'G11' + 'G12' + 'G13' + 'G14' + 'G15' + 'G16' + 'G17' + 'G18' + 'G19' + 'G20' + 'G21' + 'G22' + 'G23' + 'G24' + 'G25' + 'G26' + 'G27' + 'G28' + 'G29' + 'G30' + 'G31' + 'G32' + 'H1' + 'H2' + 'H3' + 'H4' + 'H5' + 'H6' + 'H7' + 'H8' + 'H9' + 'H10' + 'H11' + 'H12' + 'H13' + 'H14' + 'H15' + 'H16' + 'H17' + 'H18' + 'H19' + 'H20' + 'H21' + 'H22' + 'H23' + 'H24' + 'H25' + 'H26' + 'H27' + 'H28' + 'H29' + 'H30' + 'H31' + 'H32' + }; + + case 'egi32' + label = cell(32, 1); + for i = 1:32 + label{i} = sprintf('e%d', i); + end + + case 'egi64' + label = cell(64, 1); + for i = 1:64 + label{i} = sprintf('e%d', i); + end + + case 'egi128' + label = cell(128, 1); + for i = 1:128 + label{i} = sprintf('e%d', i); + end + + case 'egi256' + label = cell(256, 1); + for i = 1:256 + label{i} = sprintf('e%d', i); + end + + case 'itab153' + label = cell(153,1); + for i=1:153 + % channel names start counting at zero + label{i} = sprintf('MAG_%03d', i-1); + end + + case 'itab153_planar' + label = cell(153,2); + for i=1:153 + % channel names start counting at zero + label{i,1} = sprintf('MAG_%03d_dH', i-1); + label{i,2} = sprintf('MAG_%03d_dV', i-1); + end + + case 'yokogawa160' + % this should be consistent with read_yokogawa_header, with + % ft_channelselection and with yokogawa2grad + label = cell(160,1); + for i=1:160 + label{i} = sprintf('AG%03d', i); + end + + case 'yokogawa160_planar' + % this should be consistent with read_yokogawa_header, with + % ft_channelselection and with yokogawa2grad + label = cell(160,2); + for i=1:160 + label{i,1} = sprintf('AG%03d_dH', i); + label{i,2} = sprintf('AG%03d_dV', i); + end + + case 'electrode' + % there is no default set of electrode labels, by input type 'electrode' should not result in an error + label = {}; + + otherwise + error('the requested sensor type is not supported'); +end + +% remember the current input and output arguments, so that they can be +% reused on a subsequent call in case the same input argument is given +current_argout = {label}; +if isempty(previous_argin) + previous_argin = current_argin; + previous_argout = current_argout; +end + diff --git a/external/fieldtrip/fileio/private/ft_senstype.m b/external/fieldtrip/fileio/private/ft_senstype.m new file mode 100644 index 0000000..ade2190 --- /dev/null +++ b/external/fieldtrip/fileio/private/ft_senstype.m @@ -0,0 +1,362 @@ +function [type] = ft_senstype(input, desired) + +% FT_SENSTYPE determines the type of sensors by looking at the channel names +% and comparing them with predefined lists. +% +% Use as +% [type] = ft_senstype(sens) +% to get a string describing the type, or +% [flag] = ft_senstype(sens, desired) +% to get a boolean value. +% +% The output type can be any of the following +% 'electrode' +% 'magnetometer' +% 'biosemi64' +% 'biosemi128' +% 'biosemi256' +% 'bti148' +% 'bti148_planar' +% 'bti248' +% 'bti248_planar' +% 'ctf151' +% 'ctf151_planar' +% 'ctf275' +% 'ctf275_planar' +% 'egi128' +% 'egi256' +% 'egi32' +% 'egi64' +% 'ext1020' +% 'neuromag122' +% 'neuromag306' +% 'yokogawa160' +% 'yokogawa160_planar' +% 'plexon' +% 'itab153' +% 'itab153_planar' +% +% The optional input argument for the desired type can be any of the above, +% or any of the following +% 'eeg' +% 'meg' +% 'meg_planar' +% 'meg_axial' +% 'ctf' +% 'bti' +% 'neuromag' +% 'yokogawa' +% +% Besides specifiying a grad or elec structure as input, also allowed is +% giving a data structure containing a grad or elec field, or giving a list +% of channel names (as cell-arrray). I.e. assuming a FieldTrip data +% structure, all of the following calls would be correct. +% ft_senstype(data) +% ft_senstype(data.label) +% ft_senstype(data.grad) +% ft_senstype(data.grad.label) +% +% See also FT_SENSLABEL, FT_CHANTYPE, FT_READ_SENS, FT_COMPUTE_LEADFIELD + +% Copyright (C) 2007-2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_senstype.m 1290 2010-06-29 14:10:50Z roboos $ + +% these are for remembering the type on subsequent calls with the same input arguments +persistent previous_argin previous_argout + +if iscell(input) && numel(input)<4 && ~all(cellfun(@ischar, input)) + % this might represent combined EEG, ECoG and/or MEG + type = cell(size(input)); + if nargin<2 + desired = cell(size(input)); % empty elements + end + for i=1:numel(input) + type{i} = ft_senstype(input{i}, desired{i}); + end + return +end + +if nargin<2 + % ensure that all input arguments are defined + desired = []; +end + +current_argin = {input, desired}; +if isequal(current_argin, previous_argin) + % don't do the type detection again, but return the previous values from + % cache + type = previous_argout{1}; + return +end + +% FIXME the detection of the type of input structure should perhaps be done using the datatype function +isdata = isa(input, 'struct') && isfield(input, 'hdr'); +isheader = isa(input, 'struct') && isfield(input, 'label') && isfield(input, 'Fs'); +isgrad = isa(input, 'struct') && isfield(input, 'label') && isfield(input, 'pnt') && isfield(input, 'ori'); +iselec = isa(input, 'struct') && isfield(input, 'label') && isfield(input, 'pnt') && ~isfield(input, 'ori'); +islabel = isa(input, 'cell') && ~isempty(input) && isa(input{1}, 'char'); + +if ~isdata && ~isheader + % timelock or freq structures don't have the header structure + % the header is also removed from raw data after megrealign + % the gradiometer definition is lost after megplanar+combineplanar + isdata = isa(input, 'struct') && (isfield(input, 'grad') || isfield(input, 'elec') || isfield(input, 'label')); +end + +% the input may be a data structure which then contains a grad/elec structure, a header or only the labels +if isdata + % preferably look at the data and not the header for the grad, because it might be re-balanced and/or planar + if isfield(input, 'grad') + sens = input.grad; + isgrad = true; + elseif issubfield(input, 'hdr.grad') + sens = input.hdr.grad; + isgrad = true; + elseif issubfield(input, 'hdr.elec') + sens = input.hdr.elec; + iselec = true; + elseif isfield(input, 'elec') + sens = input.elec; + iselec = true; + elseif issubfield(input, 'hdr.label') + sens.label = input.hdr.label; + islabel = true; + elseif isfield(input, 'label') + sens.label = input.label; + islabel = true; + end +elseif isheader + if isfield(input, 'grad') + sens = input.grad; + isgrad = true; + elseif isfield(input, 'elec') + sens = input.elec; + iselec = true; + elseif isfield(input, 'label') + sens.label = input.label; + islabel = true; + end +elseif isgrad + sens = input; +elseif iselec + sens = input; +elseif islabel + sens.label = input; +else + sens = []; +end + +if isfield(input, 'type') + % preferably the structure specifies its own type + type = input.type; + +elseif issubfield(input, 'orig.FileHeader') && issubfield(input, 'orig.VarHeader') + % this is a complete header that was read from a Plexon *.nex file using read_plexon_nex + type = 'plexon'; + +elseif issubfield(input, 'orig.stname') + % this is a complete header that was read from an ITAB dataset + type = 'itab'; + +elseif issubfield(input, 'orig.sys_name') + % this is a complete header that was read from a Yokogawa dataset + type = 'yokogawa160'; + +else + % start with unknown, then try to determine the proper type by looking at the labels + type = 'unknown'; + + if isgrad + % probably this is MEG, determine the type of magnetometer/gradiometer system + % note that the order here is important: first check whether it matches a 275 channel system, then a 151 channel system, since the 151 channels are a subset of the 275 + if (mean(ismember(ft_senslabel('ctf275'), sens.label)) > 0.8) + type = 'ctf275'; + elseif (mean(ismember(ft_senslabel('ctfheadloc'), sens.label)) > 0.8) % look at the head localization channels + type = 'ctf275'; + elseif (mean(ismember(ft_senslabel('ctf151'), sens.label)) > 0.8) + type = 'ctf151'; + elseif (mean(ismember(ft_senslabel('ctf64'), sens.label)) > 0.8) + type = 'ctf64'; + elseif (mean(ismember(ft_senslabel('ctf275_planar'), sens.label)) > 0.8) + type = 'ctf275_planar'; + elseif (mean(ismember(ft_senslabel('ctf151_planar'), sens.label)) > 0.8) + type = 'ctf151_planar'; + elseif (mean(ismember(ft_senslabel('bti248'), sens.label)) > 0.8) + type = 'bti248'; + elseif (mean(ismember(ft_senslabel('bti148'), sens.label)) > 0.8) + type = 'bti148'; + elseif (mean(ismember(ft_senslabel('bti248_planar'), sens.label)) > 0.8) + type = 'bti248_planar'; + elseif (mean(ismember(ft_senslabel('bti148_planar'), sens.label)) > 0.8) + type = 'bti148_planar'; + elseif (mean(ismember(ft_senslabel('itab153'), sens.label)) > 0.8) + type = 'itab153'; + elseif (mean(ismember(ft_senslabel('itab153_planar'), sens.label)) > 0.8) + type = 'itab153_planar'; + elseif (mean(ismember(ft_senslabel('yokogawa160'), sens.label)) > 0.4) + type = 'yokogawa160'; + elseif (mean(ismember(ft_senslabel('yokogawa160_planar'), sens.label)) > 0.4) + type = 'yokogawa160_planar'; + elseif (mean(ismember(ft_senslabel('neuromag306'), sens.label)) > 0.8) + type = 'neuromag306'; + elseif (mean(ismember(ft_senslabel('neuromag306alt'),sens.label)) > 0.8) % an alternative set without spaces in the name + type = 'neuromag306'; + elseif (mean(ismember(ft_senslabel('neuromag122'), sens.label)) > 0.8) + type = 'neuromag122'; + elseif (mean(ismember(ft_senslabel('neuromag122alt'),sens.label)) > 0.8) % an alternative set without spaces in the name + type = 'neuromag122'; + elseif any(ismember(ft_senslabel('btiref'), sens.label)) + type = 'bti'; % it might be 148 or 248 channels + elseif any(ismember(ft_senslabel('ctfref'), sens.label)) + type = 'ctf'; % it might be 151 or 275 channels + elseif isfield(sens, 'pnt') && isfield(sens, 'ori') && numel(sens.label)==size(sens.pnt,1) + warning('could be Yokogawa system'); + type = 'magnetometer'; + else + warning('could be Yokogawa system'); + type = 'meg'; + end + + elseif iselec + % probably this is EEG + if (mean(ismember(ft_senslabel('biosemi256'), sens.label)) > 0.8) + type = 'biosemi256'; + elseif (mean(ismember(ft_senslabel('biosemi128'), sens.label)) > 0.8) + type = 'biosemi128'; + elseif (mean(ismember(ft_senslabel('biosemi64'), sens.label)) > 0.8) + type = 'biosemi64'; + elseif (mean(ismember(ft_senslabel('egi256'), sens.label)) > 0.8) + type = 'egi256'; + elseif (mean(ismember(ft_senslabel('egi128'), sens.label)) > 0.8) + type = 'egi128'; + elseif (mean(ismember(ft_senslabel('egi64'), sens.label)) > 0.8) + type = 'egi64'; + elseif (mean(ismember(ft_senslabel('egi32'), sens.label)) > 0.8) + type = 'egi32'; + elseif (sum(ismember(sens.label, ft_senslabel('eeg1005'))) > 10) % Otherwise it's not even worth recognizing + type = 'ext1020'; + else + type = 'electrode'; + end + + elseif islabel + % look only at the channel labels + if (mean(ismember(ft_senslabel('ctf275'), sens.label)) > 0.8) + type = 'ctf275'; + elseif (mean(ismember(ft_senslabel('ctfheadloc'), sens.label)) > 0.8) % look at the head localization channels + type = 'ctf275'; + elseif (mean(ismember(ft_senslabel('ctf151'), sens.label)) > 0.8) + type = 'ctf151'; + elseif (mean(ismember(ft_senslabel('ctf64'), sens.label)) > 0.8) + type = 'ctf64'; + elseif (mean(ismember(ft_senslabel('ctf275_planar'), sens.label)) > 0.8) + type = 'ctf275_planar'; + elseif (mean(ismember(ft_senslabel('ctf151_planar'), sens.label)) > 0.8) + type = 'ctf151_planar'; + elseif (mean(ismember(ft_senslabel('bti248'), sens.label)) > 0.8) + type = 'bti248'; + elseif (mean(ismember(ft_senslabel('bti148'), sens.label)) > 0.8) + type = 'bti148'; + elseif (mean(ismember(ft_senslabel('bti248_planar'), sens.label)) > 0.8) + type = 'bti248_planar'; + elseif (mean(ismember(ft_senslabel('bti148_planar'), sens.label)) > 0.8) + type = 'bti148_planar'; + elseif (mean(ismember(ft_senslabel('itab153'), sens.label)) > 0.8) + type = 'itab153'; + elseif (mean(ismember(ft_senslabel('itab153_planar'), sens.label)) > 0.8) + type = 'itab153_planar'; + elseif (mean(ismember(ft_senslabel('yokogawa160'), sens.label)) > 0.4) + type = 'yokogawa160'; + elseif (mean(ismember(ft_senslabel('yokogawa160_planar'), sens.label)) > 0.4) + type = 'yokogawa160_planar'; + elseif (mean(ismember(ft_senslabel('neuromag306'), sens.label)) > 0.8) + type = 'neuromag306'; + elseif (mean(ismember(ft_senslabel('neuromag306alt'),sens.label)) > 0.8) % an alternative set without spaces in the name + type = 'neuromag306'; + elseif (mean(ismember(ft_senslabel('neuromag122'), sens.label)) > 0.8) + type = 'neuromag122'; + elseif (mean(ismember(ft_senslabel('neuromag122alt'),sens.label)) > 0.8) % an alternative set without spaces in the name + type = 'neuromag122'; + elseif (mean(ismember(ft_senslabel('biosemi256'), sens.label)) > 0.8) + type = 'biosemi256'; + elseif (mean(ismember(ft_senslabel('biosemi128'), sens.label)) > 0.8) + type = 'biosemi128'; + elseif (mean(ismember(ft_senslabel('biosemi64'), sens.label)) > 0.8) + type = 'biosemi64'; + elseif (mean(ismember(ft_senslabel('egi256'), sens.label)) > 0.8) + type = 'egi256'; + elseif (mean(ismember(ft_senslabel('egi128'), sens.label)) > 0.8) + type = 'egi128'; + elseif (mean(ismember(ft_senslabel('egi64'), sens.label)) > 0.8) + type = 'egi64'; + elseif (mean(ismember(ft_senslabel('egi32'), sens.label)) > 0.8) + type = 'egi32'; + elseif (sum(ismember(sens.label, ft_senslabel('eeg1005'))) > 10) % Otherwise it's not even worth recognizing + type = 'ext1020'; + elseif any(ismember(ft_senslabel('btiref'), sens.label)) + type = 'bti'; % it might be 148 or 248 channels + elseif any(ismember(ft_senslabel('ctfref'), sens.label)) + type = 'ctf'; % it might be 151 or 275 channels + end + + end % look at label, ori and/or pnt +end % if isfield(sens, 'type') + +if ~isempty(desired) + % return a boolean flag + switch desired + case 'eeg' + type = any(strcmp(type, {'eeg' 'electrode' 'biosemi64' 'biosemi128' 'biosemi256' 'egi32' 'egi64' 'egi128' 'egi256' 'ext1020'})); + case 'biosemi' + type = any(strcmp(type, {'biosemi64' 'biosemi128' 'biosemi256'})); + case 'egi' + type = any(strcmp(type, {'egi64' 'egi128' 'egi256'})); + case 'meg' + type = any(strcmp(type, {'meg' 'magnetometer' 'ctf' 'bti' 'ctf151' 'ctf275' 'ctf151_planar' 'ctf275_planar' 'neuromag122' 'neuromag306' 'bti148' 'bti148_planar' 'bti248' 'bti248_planar' 'yokogawa160' 'yokogawa160_planar'})); + case 'ctf' + type = any(strcmp(type, {'ctf' 'ctf151' 'ctf275' 'ctf151_planar' 'ctf275_planar'})); + case 'bti' + type = any(strcmp(type, {'bti' 'bti148' 'bti148_planar' 'bti248' 'bti248_planar'})); + case 'neuromag' + type = any(strcmp(type, {'neuromag122' 'neuromag306'})); + case 'yokogawa' + type = any(strcmp(type, {'yokogawa160' 'yokogawa160_planar'})); + case 'itab' + type = any(strcmp(type, {'itab' 'itab153' 'itab153_planar'})); + case 'meg_axial' + % note that neuromag306 is mixed planar and axial + type = any(strcmp(type, {'magnetometer' 'neuromag306' 'ctf151' 'ctf275' 'bti148' 'bti248' 'yokogawa160'})); + case 'meg_planar' + % note that neuromag306 is mixed planar and axial + type = any(strcmp(type, {'neuromag122' 'neuromag306' 'ctf151_planar' 'ctf275_planar' 'bti148_planar' 'bti248_planar' 'yokogawa160_planar'})); + otherwise + type = any(strcmp(type, desired)); + end % switch desired +end % detemine the correspondence to the desired type + +% remember the current input and output arguments, so that they can be +% reused on a subsequent call in case the same input argument is given +current_argout = {type}; +if isempty(previous_argin) + previous_argin = current_argin; + previous_argout = current_argout; +end + +return % ft_senstype main() diff --git a/external/fieldtrip/fileio/private/ft_voltype.m b/external/fieldtrip/fileio/private/ft_voltype.m new file mode 100644 index 0000000..ede027d --- /dev/null +++ b/external/fieldtrip/fileio/private/ft_voltype.m @@ -0,0 +1,107 @@ +function [type] = ft_voltype(vol, desired) + +% FT_VOLTYPE determines the type of volume conduction model +% +% Use as +% [type] = ft_voltype(vol) +% to get a string describing the type, or +% [flag] = ft_voltype(vol, desired) +% to get a boolean value. +% +% See also FT_READ_VOL, FT_COMPUTE_LEADFIELD + +% Copyright (C) 2007-2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_voltype.m 946 2010-04-21 17:51:16Z roboos $ + +% these are for remembering the type on subsequent calls with the same input arguments +persistent previous_argin previous_argout + +if iscell(vol) && numel(vol)<4 + % this might represent combined EEG, ECoG and/or MEG + type = cell(size(vol)); + if nargin<2 + desired = cell(size(vol)); % empty elements + end + for i=1:numel(vol) + type{i} = ft_voltype(vol{i}, desired{i}); + end + return +end + +if nargin<2 + % ensure that all input arguments are defined + desired = []; +end + +current_argin = {vol, desired}; +if isequal(current_argin, previous_argin) + % don't do the type detection again, but return the previous values from cache + type = previous_argout{1}; + return +end + +if isfield(vol, 'type') + % preferably the structure specifies its own type + type = vol.type; + +elseif isfield(vol, 'r') && numel(vol.r)==1 && ~isfield(vol, 'label') + type = 'singlesphere'; + +elseif isfield(vol, 'r') && isfield(vol, 'o') && isfield(vol, 'label') + % this is before the spheres have been assigned to the coils + % and every sphere is still associated with a channel + type = 'multisphere'; + +elseif isfield(vol, 'r') && isfield(vol, 'o') && size(vol.r,1)==size(vol.o,1) && size(vol.r,1)>4 + % this is after the spheres have been assigned to the coils + % note that this one is easy to confuse with the concentric one + type = 'multisphere'; + +elseif isfield(vol, 'r') && numel(vol.r)>=2 && ~isfield(vol, 'label') + type = 'concentric'; + +elseif isfield(vol, 'bnd') + type = 'bem'; + +elseif isempty(vol) + type = 'infinite'; + +else + type = 'unknown'; + +end % if isfield(vol, 'type') + +if ~isempty(desired) + % return a boolean flag + switch desired + case 'bem' + type = any(strcmp(type, {'bem', 'dipoli', 'asa', 'avo', 'bemcp', 'openmeeg'})); + otherwise + type = any(strcmp(type, desired)); + end +end + +% remember the current input and output arguments, so that they can be +% reused on a subsequent call in case the same input argument is given +current_argout = {type}; +previous_argin = current_argin; +previous_argout = current_argout; + +return % voltype main() diff --git a/external/fieldtrip/fileio/private/getsubfield.m b/external/fieldtrip/fileio/private/getsubfield.m new file mode 100644 index 0000000..690e299 --- /dev/null +++ b/external/fieldtrip/fileio/private/getsubfield.m @@ -0,0 +1,45 @@ +function [s] = getsubfield(s, f); + +% GETSUBFIELD returns a field from a structure just like the standard +% Matlab GETFIELD function, except that you can also specify nested fields +% using a '.' in the fieldname. The nesting can be arbitrary deep. +% +% Use as +% f = getsubfield(s, 'fieldname') +% or as +% f = getsubfield(s, 'fieldname.subfieldname') +% +% See also GETFIELD, ISSUBFIELD, SETSUBFIELD + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: getsubfield.m 951 2010-04-21 18:24:01Z roboos $ + +if ~isstr(f) + error('incorrect input argument for fieldname'); +end + +t = {}; +while (1) + [t{end+1}, f] = strtok(f, '.'); + if isempty(f) + break + end +end +s = getfield(s, t{:}); diff --git a/external/fieldtrip/fileio/private/hastoolbox.m b/external/fieldtrip/fileio/private/hastoolbox.m new file mode 100644 index 0000000..311bb7e --- /dev/null +++ b/external/fieldtrip/fileio/private/hastoolbox.m @@ -0,0 +1,321 @@ +function [status] = hastoolbox(toolbox, autoadd, silent) + +% HASTOOLBOX tests whether an external toolbox is installed. Optionally +% it will try to determine the path to the toolbox and install it +% automatically. +% +% Use as +% [status] = hastoolbox(toolbox, autoadd, silent) +% +% autoadd = 0 means that it will not be added +% autoadd = 1 means that give an error if it cannot be added +% autoadd = 2 means that give a warning if it cannot be added +% autoadd = 3 means that it try to add it silently + +% Copyright (C) 2005-2010, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: hastoolbox.m 1411 2010-07-14 11:00:12Z jansch $ + +% this function is called many times in FieldTrip and associated toolboxes +% use efficient handling if the same toolbox has been investigated before +persistent previous previouspath + +if ~isequal(previouspath, matlabpath) + previous = []; +end + +if isempty(previous) + previous = struct; +elseif isfield(previous, fixname(toolbox)) + status = previous.(fixname(toolbox)); + return +end + +% this points the user to the website where he/she can download the toolbox +url = { + 'AFNI' 'see http://afni.nimh.nih.gov' + 'DSS' 'see http://www.cis.hut.fi/projects/dss' + 'EEGLAB' 'see http://www.sccn.ucsd.edu/eeglab' + 'NWAY' 'see http://www.models.kvl.dk/source/nwaytoolbox' + 'SPM99' 'see http://www.fil.ion.ucl.ac.uk/spm' + 'SPM2' 'see http://www.fil.ion.ucl.ac.uk/spm' + 'SPM5' 'see http://www.fil.ion.ucl.ac.uk/spm' + 'SPM8' 'see http://www.fil.ion.ucl.ac.uk/spm' + 'MEG-PD' 'see http://www.kolumbus.fi/kuutela/programs/meg-pd' + 'MEG-CALC' 'this is a commercial toolbox from Neuromag, see http://www.neuromag.com' + 'BIOSIG' 'see http://biosig.sourceforge.net' + 'EEG' 'see http://eeg.sourceforge.net' + 'EEGSF' 'see http://eeg.sourceforge.net' % alternative name + 'MRI' 'see http://eeg.sourceforge.net' % alternative name + 'NEUROSHARE' 'see http://www.neuroshare.org' + 'BESA' 'see http://www.megis.de, or contact Karsten Hoechstetter' + 'EEPROBE' 'see http://www.ant-neuro.com, or contact Maarten van der Velde' + 'YOKOGAWA' 'see http://www.yokogawa.co.jp, or contact Nobuhiko Takahashi' + 'BEOWULF' 'see http://oostenveld.net, or contact Robert Oostenveld' + 'MENTAT' 'see http://oostenveld.net, or contact Robert Oostenveld' + 'SON2' 'see http://www.kcl.ac.uk/depsta/biomedical/cfnr/lidierth.html, or contact Malcolm Lidierth' + '4D-VERSION' 'contact Christian Wienbruch' + 'SIGNAL' 'see http://www.mathworks.com/products/signal' + 'OPTIM' 'see http://www.mathworks.com/products/optim' + 'IMAGE' 'see http://www.mathworks.com/products/image' + 'SPLINES' 'see http://www.mathworks.com/products/splines' + 'FASTICA' 'see http://www.cis.hut.fi/projects/ica/fastica' + 'BRAINSTORM' 'see http://neuroimage.ucs.edu/brainstorm' + 'FILEIO' 'see http://www.ru.nl/neuroimaging/fieldtrip' + 'FORWINV' 'see http://www.ru.nl/neuroimaging/fieldtrip' + 'PLOTTING' 'see http://www.ru.nl/neuroimaging/fieldtrip' + 'DENOISE' 'see http://lumiere.ens.fr/Audition/adc/meg, or contact Alain de Cheveigne' + 'BCI2000' 'see http://bci2000.org' + 'NLXNETCOM' 'see http://www.neuralynx.com' + 'DIPOLI' 'see ftp://ftp.fcdonders.nl/pub/fieldtrip/external' + 'MNE' 'see http://www.nmr.mgh.harvard.edu/martinos/userInfo/data/sofMNE.php' + 'TCP_UDP_IP' 'see http://www.mathworks.com/matlabcentral/fileexchange/345, or contact Peter Rydes?ter' + 'BEMCP' 'contact Christophe Phillips' + 'OPENMEEG' 'see http://gforge.inria.fr/projects/openmeeg' + 'PRTOOLS' 'see http://www.prtools.org' + 'ITAB' 'contact Stefania Della Penna' + 'BSMART' 'see http://www.brain-smart.org' + 'PEER' 'see http://fieldtrip.fcdonders.nl/development/peer' + }; + +if nargin<2 + % default is not to add the path automatically + autoadd = 0; +end + +if nargin<3 + % default is not to be silent + silent = 0; +end + +% determine whether the toolbox is installed +toolbox = upper(toolbox); +switch toolbox + case 'AFNI' + status = (exist('BrikLoad') && exist('BrikInfo')); + case 'DSS' + status = exist('dss', 'file') && exist('dss_create_state', 'file'); + case 'EEGLAB' + status = exist('runica', 'file'); + case 'NWAY' + status = exist('parafac', 'file'); + case 'SPM99' + status = exist('spm.m') && strcmp(spm('ver'),'SPM99'); + case 'SPM2' + status = exist('spm.m') && strcmp(spm('ver'),'SPM2'); + case 'SPM5' + status = exist('spm.m') && strcmp(spm('ver'),'SPM5'); + case 'SPM8' + status = exist('spm.m') && strncmp(spm('ver'),'SPM8', 4); + case 'MEG-PD' + status = (exist('rawdata') && exist('channames')); + case 'MEG-CALC' + status = (exist('megmodel') && exist('megfield') && exist('megtrans')); + case 'BIOSIG' + status = (exist('sopen') && exist('sread')); + case 'EEG' + status = (exist('ctf_read_res4') && exist('ctf_read_meg4')); + case 'EEGSF' % alternative name + status = (exist('ctf_read_res4') && exist('ctf_read_meg4')); + case 'MRI' % other functions in the mri section + status = (exist('avw_hdr_read') && exist('avw_img_read')); + case 'NEUROSHARE' + status = (exist('ns_OpenFile') && exist('ns_SetLibrary') && exist('ns_GetAnalogData')); + case 'BESA' + status = (exist('readBESAtfc') && exist('readBESAswf')); + case 'EEPROBE' + status = (exist('read_eep_avr') && exist('read_eep_cnt')); + case 'YOKOGAWA' + status = hasyokogawa('16bitBeta6'); + case 'BEOWULF' + status = (exist('evalwulf') && exist('evalwulf') && exist('evalwulf')); + case 'MENTAT' + status = (exist('pcompile') && exist('pfor') && exist('peval')); + case 'SON2' + status = (exist('SONFileHeader') && exist('SONChanList') && exist('SONGetChannel')); + case '4D-VERSION' + status = (exist('read4d') && exist('read4dhdr')); + case 'SIGNAL' + status = hasfunction('medfilt1', toolbox) && exist('butter', 'file'); % also check the availability of a toolbox license + case 'OPTIM' + status = hasfunction('fmincon', toolbox) && exist('fminunc', 'file'); % also check the availability of a toolbox license + case 'SPLINES' + status = hasfunction('bspline', toolbox) && exist('csape', 'file'); % also check the availability of a toolbox license + case 'IMAGE' + status = hasfunction('bwlabeln', toolbox); % also check the availability of a toolbox license + case 'FASTICA' + status = exist('fastica', 'file'); + case 'BRAINSTORM' + status = exist('bem_xfer'); + case 'FILEIO' + status = (exist('read_header') && exist('read_data') && exist('read_event') && exist('read_sens')); + case 'FORWINV' + status = (exist('compute_leadfield') && exist('prepare_vol_sens')); + case 'DENOISE' + status = (exist('tsr') && exist('sns')); + case 'CTF' + status = (exist('getCTFBalanceCoefs') && exist('getCTFdata')); + case 'BCI2000' + status = exist('load_bcidat'); + case 'NLXNETCOM' + status = (exist('MatlabNetComClient') && exist('NlxConnectToServer') && exist('NlxGetNewCSCData')); + case 'DIPOLI' + status = exist('dipoli.m', 'file'); + case 'MNE' + status = (exist('fiff_read_meas_info', 'file') && exist('fiff_setup_read_raw', 'file')); + case 'TCP_UDP_IP' + status = (exist('pnet', 'file') && exist('pnet_getvar', 'file') && exist('pnet_putvar', 'file')); + case 'BEMCP' + status = (exist('bem_Cij_cog', 'file') && exist('bem_Cij_lin', 'file') && exist('bem_Cij_cst', 'file')); + case 'OPENMEEG' + status = exist('openmeeg.m', 'file'); + case 'PLOTTING' + status = (exist('plot_topo', 'file') && exist('plot_mesh', 'file') && exist('plot_matrix', 'file')); + case 'PRTOOLS' + status = (exist('prversion', 'file') && exist('dataset', 'file') && exist('svc', 'file')); + case 'ITAB' + status = (exist('lcReadHeader', 'file') && exist('lcReadData', 'file')); + case 'BSMART' + status = exist('bsmart'); + case 'PEER' + status = exist('peerslave', 'file') && exist('peermaster', 'file'); + case 'CONNECTIVITY' + status = exist('ft_connectivity_corr', 'file') && exist('ft_connectivity_granger', 'file'); + otherwise + if ~silent, warning(sprintf('cannot determine whether the %s toolbox is present', toolbox)); end + status = 0; +end + +% it should be a boolean value +status = (status~=0); + +% try to determine the path of the requested toolbox +if autoadd>0 && ~status + + % for core fieldtrip modules + prefix = fileparts(which('fieldtripdefs')); + if ~status + status = myaddpath(fullfile(prefix, lower(toolbox)), silent); + end + + % for external fieldtrip modules + prefix = fullfile(fileparts(which('fieldtripdefs')), 'external'); + if ~status + status = myaddpath(fullfile(prefix, lower(toolbox)), silent); + end + + % for linux computers in the F.C. Donders Centre + prefix = '/home/common/matlab'; + if ~status && (strcmp(computer, 'GLNX86') || strcmp(computer, 'GLNXA64')) + status = myaddpath(fullfile(prefix, lower(toolbox)), silent); + end + + % for windows computers in the F.C. Donders Centre + prefix = 'h:\common\matlab'; + if ~status && (strcmp(computer, 'PCWIN') || strcmp(computer, 'PCWIN64')) + status = myaddpath(fullfile(prefix, lower(toolbox)), silent); + end + + % use the matlab subdirectory in your homedirectory, this works on unix and mac + prefix = [getenv('HOME') '/matlab']; + if ~status + status = myaddpath(fullfile(prefix, lower(toolbox)), silent); + end + + if ~status + % the toolbox is not on the path and cannot be added + sel = find(strcmp(url(:,1), toolbox)); + if ~isempty(sel) + msg = sprintf('the %s toolbox is not installed, %s', toolbox, url{sel, 2}); + else + msg = sprintf('the %s toolbox is not installed', toolbox); + end + if autoadd==1 + error(msg); + elseif autoadd==2 + warning(msg); + else + % fail silently + end + end +end + +% this function is called many times in FieldTrip and associated toolboxes +% use efficient handling if the same toolbox has been investigated before +if status + previous.(fixname(toolbox)) = status; +end + +% remember the previous path, allows us to determine on the next call +% whether the path has been modified outise of this function +previouspath = matlabpath; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% helper function +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function status = myaddpath(toolbox, silent) +if exist(toolbox, 'dir') + if ~silent, warning(sprintf('adding %s toolbox to your Matlab path', toolbox)); end + addpath(toolbox); + status = 1; +else + status = 0; +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% helper function +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function out = fixname(toolbox) +out = lower(toolbox); +out(out=='-') = '_'; % fix dashes +out(out==' ') = '_'; % fix spaces +out(out=='/') = '_'; % fix forward slashes +out(out=='\') = '_'; % fix backward slashes + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% helper function +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function status = hasfunction(funname, toolbox) +try + % call the function without any input arguments, which probably is inapropriate + feval(funname); + % it might be that the function without any input already works fine + status = true; +catch + % either the function returned an error, or the function is not available + % availability is influenced by the function being present and by having a + % license for the function, i.e. in a concurrent licensing setting it might + % be that all toolbox licenses are in use + m = lasterror; + if strcmp(m.identifier, 'MATLAB:license:checkouterror') + if nargin>1 + warning('the %s toolbox is available, but you don''t have a license for it', toolbox); + else + warning('the function ''%s'' is available, but you don''t have a license for it', funname); + end + status = false; + elseif strcmp(m.identifier, 'MATLAB:UndefinedFunction') + status = false; + else + % the function seems to be available and it gave an unknown error, + % which is to be expected with inappropriate input arguments + status = true; + end +end + diff --git a/external/fileio/private/headcoordinates.m b/external/fieldtrip/fileio/private/headcoordinates.m similarity index 75% rename from external/fileio/private/headcoordinates.m rename to external/fieldtrip/fileio/private/headcoordinates.m index 6acea46..2269b01 100644 --- a/external/fileio/private/headcoordinates.m +++ b/external/fieldtrip/fileio/private/headcoordinates.m @@ -33,10 +33,23 @@ % Copyright (C) 2003 Robert Oostenveld % -% $Log: headcoordinates.m,v $ -% Revision 1.1 2004/09/27 16:00:04 roboos -% initial submission +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: headcoordinates.m 952 2010-04-21 18:29:51Z roboos $ if nargin<4 flag=0; diff --git a/external/fieldtrip/fileio/private/issubfield.m b/external/fieldtrip/fileio/private/issubfield.m new file mode 100644 index 0000000..ff54060 --- /dev/null +++ b/external/fieldtrip/fileio/private/issubfield.m @@ -0,0 +1,42 @@ +function [r] = issubfield(s, f) + +% ISSUBFIELD tests for the presence of a field in a structure just like the standard +% Matlab ISFIELD function, except that you can also specify nested fields +% using a '.' in the fieldname. The nesting can be arbitrary deep. +% +% Use as +% f = issubfield(s, 'fieldname') +% or as +% f = issubfield(s, 'fieldname.subfieldname') +% +% This function returns true if the field is present and false if the field +% is not present. +% +% See also ISFIELD, GETSUBFIELD, SETSUBFIELD + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: issubfield.m 951 2010-04-21 18:24:01Z roboos $ + +try + getsubfield(s, f); % if this works, then the subfield must be present + r = true; +catch + r = false; % apparently the subfield is not present +end diff --git a/external/fieldtrip/fileio/private/itab2grad.m b/external/fieldtrip/fileio/private/itab2grad.m new file mode 100644 index 0000000..16de977 --- /dev/null +++ b/external/fieldtrip/fileio/private/itab2grad.m @@ -0,0 +1,50 @@ +function grad = itab2grad(header_info) + +% ITAB2GRAD converts the original Chieti ITAB header structure into a gradiometer +% definition that is compatible with FieldTrip forward and inverse computations +% +% See also READ_HEADER + +% Copyright (C) 2009, Robert Oostenveld, Donders Institute for Brain, Cognition and Behaviour +% Copyright (C) 2009, Stefania Della Penna, ITAB, University Chiety, Italy +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id$ + +grad = struct; + +chan = 0; +coil = 0; +for i=1:640 + if header_info.ch(i).type==2 + % it is a MAG channel + chan = chan+1; + grad.label{chan} = header_info.ch(i).label; + for j=1:header_info.ch(i).ncoils + coil = coil+1; + grad.pnt(coil,:) = header_info.ch(i).position(j).r_s; + grad.ori(coil,:) = header_info.ch(i).position(j).u_s; + grad.tra(chan,coil) = header_info.ch(i).wgt(j); + end + else + % skip all other channels + end +end + +grad.unit = 'mm'; +grad.label = grad.label(:); % should be column vector diff --git a/external/fieldtrip/fileio/private/keyval.m b/external/fieldtrip/fileio/private/keyval.m new file mode 100644 index 0000000..36422c0 --- /dev/null +++ b/external/fieldtrip/fileio/private/keyval.m @@ -0,0 +1,70 @@ +function [val, remaining] = keyval(key, varargin) + +% KEYVAL returns the value that corresponds to the requested key in a +% key-value pair list of variable input arguments +% +% Use as +% [val] = keyval(key, varargin) +% +% See also VARARGIN + +% Copyright (C) 2005-2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: keyval.m 1394 2010-07-10 21:02:48Z roboos $ + +if length(varargin)==1 && iscell(varargin{1}) + varargin = varargin{1}; +end + +if mod(length(varargin),2) + error('optional input arguments should come in key-value pairs, i.e. there should be an even number'); +end + +% the 1st, 3rd, etc. contain the keys, the 2nd, 4th, etc. contain the values +keys = varargin(1:2:end); +vals = varargin(2:2:end); + +% the following is faster than cellfun(@isstr, keys) +valid = false(size(keys)); +for i=1:numel(keys) + valid = ischar(keys{i}); +end + +if ~all(valid) + error('optional input arguments should come in key-value pairs, the optional input argument %d is invalid (should be a string)', i); +end + +hit = find(strcmpi(key, keys)); +if isempty(hit) + % the requested key was not found + val = []; +elseif length(hit)==1 + % the requested key was found + val = vals{hit}; +else + error('multiple input arguments with the same name'); +end + +if nargout>1 + % return the remaining input arguments with the key-value pair removed + keys(hit) = []; + vals(hit) = []; + remaining = cat(1, keys(:)', vals(:)'); + remaining = remaining(:)'; +end diff --git a/external/fieldtrip/fileio/private/littleendian.m b/external/fieldtrip/fileio/private/littleendian.m new file mode 100644 index 0000000..ad83dc5 --- /dev/null +++ b/external/fieldtrip/fileio/private/littleendian.m @@ -0,0 +1,33 @@ +function val = littleendian; + +% LITTLEENDIAN returns 1 (true) on a little endian machine, e.g. with an +% Intel or AMD, or 0 (false) otherwise +% +% Example +% if (littleendian) +% % do something, e.g. swap some bytes +% end +% +% See also BIGENDIAN, SWAPBYTES, TYPECAST + +% Copyrigth (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: littleendian.m 945 2010-04-21 17:41:20Z roboos $ + +val = (typecast(uint8([0 1]), 'uint16')==256); diff --git a/external/fieldtrip/fileio/private/loadama.m b/external/fieldtrip/fileio/private/loadama.m new file mode 100644 index 0000000..06d144d --- /dev/null +++ b/external/fieldtrip/fileio/private/loadama.m @@ -0,0 +1,111 @@ +function [ama] = loadama(filename); + +% LOADAMA read an inverted A-matrix and associated geometry information +% from an ama file that was written by Tom Oostendorp's DIPOLI +% +% Use as +% [ama] = loadama(filename) +% +% See also LOADTRI, LOADMAT + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: loadama.m 945 2010-04-21 17:41:20Z roboos $ + +fid = fopen(filename, 'rb', 'ieee-le'); + +version = fread(fid, 1, 'int'); +if version~=10 + error(sprintf('%s is either not an inverted A matrix, or one of an old version', filename)); +end + +mode = fread(fid, 1, 'int'); +ngeo = fread(fid, 1, 'int'); + +totpnt = 0; +totdhk = 0; +nrow = 0; + +% read the boundaries +geo = []; +for i=1:ngeo + geo(i).name = char(fread(fid, [1 80], 'uchar')); + geo(i).npnt = fread(fid, 1, 'int'); + geo(i).pnt = fread(fid, [3 geo(i).npnt], 'float')'; + geo(i).ndhk = fread(fid, 1, 'int'); + geo(i).dhk = fread(fid, [3 geo(i).ndhk], 'int')' + 1; % Matlab indexing starts at 1 + geo(i).sigmam = fread(fid, 1, 'float'); + geo(i).sigmap = fread(fid, 1, 'float'); + geo(i).geocon = fread(fid, ngeo, 'int'); + geo(i).deflat = fread(fid, ngeo, 'float'); + totpnt = totpnt + geo(i).npnt; + totdhk = totdhk + geo(i).ndhk; +end + +% read the electrodes +if mode~=1 + elec.name = char(fread(fid, [1 80], 'uchar')); + elec.npnt = fread(fid, 1, 'int'); + for i=1:(elec.npnt+1) + elec.el(i).dhk = fread(fid, 1, 'int') + 1; % Matlab indexing starts at 1 + elec.el(i).la = fread(fid, 1, 'float'); + elec.el(i).mu = fread(fid, 1, 'float'); + elec.el(i).name = char(fread(fid, [1 10], 'char')); + % the ELECTRODE c-structure is padded to word boundaries, i.e. to 4 bytes + dum = fread(fid, 2, 'char'); + end + elec.vertex = fread(fid, 1, 'int'); + elec.surface = fread(fid, 1, 'int'); + nrow = nrow + elec.npnt; +else + elec = []; +end + +% read the gradiometers +if mode~=0 + error('gradiometers not yet implemented'); +else + grad = []; +end + +% read the inverted A-matrix +bi = fread(fid, [totpnt nrow], 'float')'; + +% read the isolated source compartment information, if present +iso_sur = fread(fid, 1, 'int') + 1; % Matlab indexing starts at 1 +inner_only = fread(fid, 1, 'int'); +if iso_sur~=0 + iso_totpnt = geo(iso_sur).npnt; + iso_b = fread(fid, [iso_totpnt iso_totpnt], 'float')'; +else + iso_b = []; +end + +fclose(fid); + +% put all local variables into a structure, this is a bit unusual programming style +% the output structure is messy, but contains all relevant information +tmp = whos; +ama = []; +for i=1:length(tmp) + if isempty(strmatch(tmp(i).name, {'tmp', 'fid', 'ans', 'handles'})) + ama = setfield(ama, tmp(i).name, eval(tmp(i).name)); + end +end + diff --git a/external/fieldtrip/fileio/private/loadcnt.m b/external/fieldtrip/fileio/private/loadcnt.m new file mode 100644 index 0000000..922f7ba --- /dev/null +++ b/external/fieldtrip/fileio/private/loadcnt.m @@ -0,0 +1,596 @@ +% loadcnt() - Load a Neuroscan continuous signal file. +% +% Usage: +% >> cnt = loadcnt(file, varargin) +% +% Inputs: +% filename - name of the file with extension +% +% Optional inputs: +% 't1' - start at time t1, default 0 +% 'sample1' - start at sample1, default 0, overrides t1 +% 'lddur' - duration of segment to load, default = whole file +% 'ldnsamples' - number of samples to load, default = whole file, +% overrides lddur +% 'scale' - ['on'|'off'] scale data to microvolt (default:'on') +% 'dataformat' - ['int16'|'int32'] default is 'int16' for 16-bit data. +% Use 'int32' for 32-bit data. +% 'blockread' - [integer] by default it is automatically determined +% from the file header, though sometimes it finds an +% incorect value, so you may want to enter a value manually +% here (1 is the most standard value). +% 'memmapfile' - ['memmapfile_name'] use this option if the .cnt file +% is too large to read in conventially. The suffix of +% the memmapfile_name must be .fdt. The memmapfile +% functions process files based on their suffix, and an +% error will occur if you use a different suffix. +% +% Outputs: +% cnt - structure with the continuous data and other informations +% cnt.header +% cnt.electloc +% cnt.data +% cnt.tag +% +% Authors: Sean Fitzgibbon, Arnaud Delorme, 2000- +% +% Note: function original name was load_scan41.m +% +% Known limitations: +% For more see http://www.cnl.salk.edu/~arno/cntload/index.html + +%123456789012345678901234567890123456789012345678901234567890123456789012 + +% Copyright (C) 2000 Sean Fitzgibbon, +% Copyright (C) 2003 Arnaud Delorme, Salk Institute, arno@salk.edu +% +% This program is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +% + +function [f,lab,ev2p] = loadcnt(filename,varargin) + +if ~isempty(varargin) + r=struct(varargin{:}); +else r = []; +end; + +try, r.t1; catch, r.t1=0; end +try, r.sample1; catch, r.sample1=[]; end +try, r.lddur; catch, r.lddur=[]; end +try, r.ldnsamples; catch, r.ldnsamples=[]; end +try, r.scale; catch, r.scale='on'; end +try, r.blockread; catch, r.blockread = []; end +try, r.dataformat; catch, r.dataformat = 'int16'; end +try, r.memmapfile; catch, r.memmapfile = ''; end + + +sizeEvent1 = 8 ; %%% 8 bytes for Event1 +sizeEvent2 = 19 ; %%% 19 bytes for Event2 +sizeEvent3 = 19 ; %%% 19 bytes for Event3 + +type='cnt'; +if nargin ==1 + scan=0; +end + +fid = fopen(filename,'r', 'l'); +disp(['Loading file ' filename ' ...']) + +h.rev = fread(fid,12,'char'); +h.nextfile = fread(fid,1,'long'); +h.prevfile = fread(fid,1,'ulong'); +h.type = fread(fid,1,'char'); +h.id = fread(fid,20,'char'); +h.oper = fread(fid,20,'char'); +h.doctor = fread(fid,20,'char'); +h.referral = fread(fid,20,'char'); +h.hospital = fread(fid,20,'char'); +h.patient = fread(fid,20,'char'); +h.age = fread(fid,1,'short'); +h.sex = fread(fid,1,'char'); +h.hand = fread(fid,1,'char'); +h.med = fread(fid,20, 'char'); +h.category = fread(fid,20, 'char'); +h.state = fread(fid,20, 'char'); +h.label = fread(fid,20, 'char'); +h.date = fread(fid,10, 'char'); +h.time = fread(fid,12, 'char'); +h.mean_age = fread(fid,1,'float'); +h.stdev = fread(fid,1,'float'); +h.n = fread(fid,1,'short'); +h.compfile = fread(fid,38,'char'); +h.spectwincomp = fread(fid,1,'float'); +h.meanaccuracy = fread(fid,1,'float'); +h.meanlatency = fread(fid,1,'float'); +h.sortfile = fread(fid,46,'char'); +h.numevents = fread(fid,1,'int'); +h.compoper = fread(fid,1,'char'); +h.avgmode = fread(fid,1,'char'); +h.review = fread(fid,1,'char'); +h.nsweeps = fread(fid,1,'ushort'); +h.compsweeps = fread(fid,1,'ushort'); +h.acceptcnt = fread(fid,1,'ushort'); +h.rejectcnt = fread(fid,1,'ushort'); +h.pnts = fread(fid,1,'ushort'); +h.nchannels = fread(fid,1,'ushort'); +h.avgupdate = fread(fid,1,'ushort'); +h.domain = fread(fid,1,'char'); +h.variance = fread(fid,1,'char'); +h.rate = fread(fid,1,'ushort'); % A USER CLAIMS THAT SAMPLING RATE CAN BE +h.scale = fread(fid,1,'double'); % FRACTIONAL IN NEUROSCAN WHICH IS +h.veogcorrect = fread(fid,1,'char'); % OBVIOUSLY NOT POSSIBLE HERE (BUG 606) +h.heogcorrect = fread(fid,1,'char'); +h.aux1correct = fread(fid,1,'char'); +h.aux2correct = fread(fid,1,'char'); +h.veogtrig = fread(fid,1,'float'); +h.heogtrig = fread(fid,1,'float'); +h.aux1trig = fread(fid,1,'float'); +h.aux2trig = fread(fid,1,'float'); +h.heogchnl = fread(fid,1,'short'); +h.veogchnl = fread(fid,1,'short'); +h.aux1chnl = fread(fid,1,'short'); +h.aux2chnl = fread(fid,1,'short'); +h.veogdir = fread(fid,1,'char'); +h.heogdir = fread(fid,1,'char'); +h.aux1dir = fread(fid,1,'char'); +h.aux2dir = fread(fid,1,'char'); +h.veog_n = fread(fid,1,'short'); +h.heog_n = fread(fid,1,'short'); +h.aux1_n = fread(fid,1,'short'); +h.aux2_n = fread(fid,1,'short'); +h.veogmaxcnt = fread(fid,1,'short'); +h.heogmaxcnt = fread(fid,1,'short'); +h.aux1maxcnt = fread(fid,1,'short'); +h.aux2maxcnt = fread(fid,1,'short'); +h.veogmethod = fread(fid,1,'char'); +h.heogmethod = fread(fid,1,'char'); +h.aux1method = fread(fid,1,'char'); +h.aux2method = fread(fid,1,'char'); +h.ampsensitivity = fread(fid,1,'float'); +h.lowpass = fread(fid,1,'char'); +h.highpass = fread(fid,1,'char'); +h.notch = fread(fid,1,'char'); +h.autoclipadd = fread(fid,1,'char'); +h.baseline = fread(fid,1,'char'); +h.offstart = fread(fid,1,'float'); +h.offstop = fread(fid,1,'float'); +h.reject = fread(fid,1,'char'); +h.rejstart = fread(fid,1,'float'); +h.rejstop = fread(fid,1,'float'); +h.rejmin = fread(fid,1,'float'); +h.rejmax = fread(fid,1,'float'); +h.trigtype = fread(fid,1,'char'); +h.trigval = fread(fid,1,'float'); +h.trigchnl = fread(fid,1,'char'); +h.trigmask = fread(fid,1,'short'); +h.trigisi = fread(fid,1,'float'); +h.trigmin = fread(fid,1,'float'); +h.trigmax = fread(fid,1,'float'); +h.trigdir = fread(fid,1,'char'); +h.autoscale = fread(fid,1,'char'); +h.n2 = fread(fid,1,'short'); +h.dir = fread(fid,1,'char'); +h.dispmin = fread(fid,1,'float'); +h.dispmax = fread(fid,1,'float'); +h.xmin = fread(fid,1,'float'); +h.xmax = fread(fid,1,'float'); +h.automin = fread(fid,1,'float'); +h.automax = fread(fid,1,'float'); +h.zmin = fread(fid,1,'float'); +h.zmax = fread(fid,1,'float'); +h.lowcut = fread(fid,1,'float'); +h.highcut = fread(fid,1,'float'); +h.common = fread(fid,1,'char'); +h.savemode = fread(fid,1,'char'); +h.manmode = fread(fid,1,'char'); +h.ref = fread(fid,10,'char'); +h.rectify = fread(fid,1,'char'); +h.displayxmin = fread(fid,1,'float'); +h.displayxmax = fread(fid,1,'float'); +h.phase = fread(fid,1,'char'); +h.screen = fread(fid,16,'char'); +h.calmode = fread(fid,1,'short'); +h.calmethod = fread(fid,1,'short'); +h.calupdate = fread(fid,1,'short'); +h.calbaseline = fread(fid,1,'short'); +h.calsweeps = fread(fid,1,'short'); +h.calattenuator = fread(fid,1,'float'); +h.calpulsevolt = fread(fid,1,'float'); +h.calpulsestart = fread(fid,1,'float'); +h.calpulsestop = fread(fid,1,'float'); +h.calfreq = fread(fid,1,'float'); +h.taskfile = fread(fid,34,'char'); +h.seqfile = fread(fid,34,'char'); +h.spectmethod = fread(fid,1,'char'); +h.spectscaling = fread(fid,1,'char'); +h.spectwindow = fread(fid,1,'char'); +h.spectwinlength = fread(fid,1,'float'); +h.spectorder = fread(fid,1,'char'); +h.notchfilter = fread(fid,1,'char'); +h.headgain = fread(fid,1,'short'); +h.additionalfiles = fread(fid,1,'int'); +h.unused = fread(fid,5,'char'); +h.fspstopmethod = fread(fid,1,'short'); +h.fspstopmode = fread(fid,1,'short'); +h.fspfvalue = fread(fid,1,'float'); +h.fsppoint = fread(fid,1,'short'); +h.fspblocksize = fread(fid,1,'short'); +h.fspp1 = fread(fid,1,'ushort'); +h.fspp2 = fread(fid,1,'ushort'); +h.fspalpha = fread(fid,1,'float'); +h.fspnoise = fread(fid,1,'float'); +h.fspv1 = fread(fid,1,'short'); +h.montage = fread(fid,40,'char'); +h.eventfile = fread(fid,40,'char'); +h.fratio = fread(fid,1,'float'); +h.minor_rev = fread(fid,1,'char'); +h.eegupdate = fread(fid,1,'short'); +h.compressed = fread(fid,1,'char'); +h.xscale = fread(fid,1,'float'); +h.yscale = fread(fid,1,'float'); +h.xsize = fread(fid,1,'float'); +h.ysize = fread(fid,1,'float'); +h.acmode = fread(fid,1,'char'); +h.commonchnl = fread(fid,1,'uchar'); +h.xtics = fread(fid,1,'char'); +h.xrange = fread(fid,1,'char'); +h.ytics = fread(fid,1,'char'); +h.yrange = fread(fid,1,'char'); +h.xscalevalue = fread(fid,1,'float'); +h.xscaleinterval = fread(fid,1,'float'); +h.yscalevalue = fread(fid,1,'float'); +h.yscaleinterval = fread(fid,1,'float'); +h.scaletoolx1 = fread(fid,1,'float'); +h.scaletooly1 = fread(fid,1,'float'); +h.scaletoolx2 = fread(fid,1,'float'); +h.scaletooly2 = fread(fid,1,'float'); +h.port = fread(fid,1,'short'); +h.numsamples = fread(fid,1,'ulong'); +h.filterflag = fread(fid,1,'char'); +h.lowcutoff = fread(fid,1,'float'); +h.lowpoles = fread(fid,1,'short'); +h.highcutoff = fread(fid,1,'float'); +h.highpoles = fread(fid,1,'short'); +h.filtertype = fread(fid,1,'char'); +h.filterdomain = fread(fid,1,'char'); +h.snrflag = fread(fid,1,'char'); +h.coherenceflag = fread(fid,1,'char'); +h.continuoustype = fread(fid,1,'char'); +h.eventtablepos = fread(fid,1,'ulong'); +h.continuousseconds = fread(fid,1,'float'); +h.channeloffset = fread(fid,1,'long'); +h.autocorrectflag = fread(fid,1,'char'); +h.dcthreshold = fread(fid,1,'uchar'); + +for n = 1:h.nchannels + e(n).lab = deblank(char(fread(fid,10,'char')')); + e(n).reference = fread(fid,1,'char'); + e(n).skip = fread(fid,1,'char'); + e(n).reject = fread(fid,1,'char'); + e(n).display = fread(fid,1,'char'); + e(n).bad = fread(fid,1,'char'); + e(n).n = fread(fid,1,'ushort'); + e(n).avg_reference = fread(fid,1,'char'); + e(n).clipadd = fread(fid,1,'char'); + e(n).x_coord = fread(fid,1,'float'); + e(n).y_coord = fread(fid,1,'float'); + e(n).veog_wt = fread(fid,1,'float'); + e(n).veog_std = fread(fid,1,'float'); + e(n).snr = fread(fid,1,'float'); + e(n).heog_wt = fread(fid,1,'float'); + e(n).heog_std = fread(fid,1,'float'); + e(n).baseline = fread(fid,1,'short'); + e(n).filtered = fread(fid,1,'char'); + e(n).fsp = fread(fid,1,'char'); + e(n).aux1_wt = fread(fid,1,'float'); + e(n).aux1_std = fread(fid,1,'float'); + e(n).senstivity = fread(fid,1,'float'); + e(n).gain = fread(fid,1,'char'); + e(n).hipass = fread(fid,1,'char'); + e(n).lopass = fread(fid,1,'char'); + e(n).page = fread(fid,1,'uchar'); + e(n).size = fread(fid,1,'uchar'); + e(n).impedance = fread(fid,1,'uchar'); + e(n).physicalchnl = fread(fid,1,'uchar'); + e(n).rectify = fread(fid,1,'char'); + e(n).calib = fread(fid,1,'float'); +end + +% finding if 32-bits of 16-bits file +% ---------------------------------- +begdata = ftell(fid); +enddata = h.eventtablepos; % after data +if strcmpi(r.dataformat, 'int16') + nums = (enddata-begdata)/h.nchannels/2; +else nums = (enddata-begdata)/h.nchannels/4; +end; + +% number of sample to read +% ------------------------ +if ~isempty(r.sample1) + r.t1 = r.sample1/h.rate; +else + r.sample1 = r.t1*h.rate; +end; +if strcmpi(r.dataformat, 'int16') + startpos = r.t1*h.rate*2*h.nchannels; +else startpos = r.t1*h.rate*4*h.nchannels; +end; +if isempty(r.ldnsamples) + if ~isempty(r.lddur) + r.ldnsamples = round(r.lddur*h.rate); + else r.ldnsamples = nums; + end; +end; + +% VL modification 1 ========================= +h.nums = nums; + +% channel offset +% -------------- +if ~isempty(r.blockread) + h.channeloffset = r.blockread; +end; +if h.channeloffset > 1 + fprintf('WARNING: reading data in blocks of %d, if this fails, try using option "''blockread'', 1"\n', ... + h.channeloffset); +end; + +disp('Reading data .....') +if type == 'cnt' + + % while (ftell(fid) +1 < h.eventtablepos) + %d(:,i)=fread(fid,h.nchannels,'int16'); + %end + fseek(fid, startpos, 0); + % **** This marks the beginning of the code modified for reading + % large .cnt files + + % Switched to r.memmapfile for continuity. Check to see if the + % variable exists. If it does, then the user has indicated the + % file is too large to be processed in memory. If the variable + % is blank, the file is processed in memory. + if (~isempty(r.memmapfile)) + % open a file for writing + foutid = fopen(r.memmapfile, 'w') ; + + % This portion of the routine reads in a section of the EEG file + % and then writes it out to the harddisk. + samples_left = h.nchannels * r.ldnsamples ; + + % the size of the data block to be read is limited to 4M + % samples. This equates to 16MB and 32MB of memory for + % 16 and 32 bit files, respectively. + data_block = 4000000 ; + max_rows = data_block / h.nchannels ; + + ws = warning('off'); + max_written = h.nchannels * uint32(max_rows) ; + warning(ws); + + % This while look tracks the remaining samples. The + % data is processed in chunks rather than put into + % memory whole. + while (samples_left > 0) + + % Check to see if the remaining data is smaller than + % the general processing block by looking at the + % remaining number of rows. + to_read = max_rows ; + if (data_block > samples_left) + to_read = samples_left / h.nchannels ; + end ; + + % Read data in a relatively small chunk + temp_dat = fread(fid, [h.nchannels to_read], r.dataformat) ; + + % The data is then scaled using the original routine. + % In the original routine, the entire data set was scaled + % after being read in. For this version, scaling occurs + % after every chunk is read. + if strcmpi(r.scale, 'on') + disp('Scaling data .....') + %%% scaling to microvolts + for i=1:h.nchannels + bas=e(i).baseline;sen=e(i).senstivity;cal=e(i).calib; + mf=sen*(cal/204.8); + temp_dat(i,:)=(temp_dat(i,:)-bas).*mf; + end + end + + % Write out data in float32 form to the file name + % supplied by the user. + written = fwrite (foutid, temp_dat, 'float32') ; + + if (written ~= max_written) + samples_left = 0 ; + else + samples_left = samples_left - written ; + end ; + + end ; + + fclose (foutid) ; + % Set the dat variable. This gets used later by other + % EEGLAB functions. + dat = r.memmapfile ; + + % This variable tracks how the data should be read. + bReadIntoMemory = false ; + else + % The memmapfile variable is empty, read into memory. + bReadIntoMemory = true ; + end + + % This ends the modifications made to read large files. + % Everything contained within the following if statement is the + % original code. + if (bReadIntoMemory == true) + if h.channeloffset <= 1 + dat=fread(fid, [h.nchannels r.ldnsamples], r.dataformat); + else + h.channeloffset = h.channeloffset/2; + % reading data in blocks + dat = zeros( h.nchannels, r.ldnsamples); + dat(:, 1:h.channeloffset) = fread(fid, [h.channeloffset h.nchannels], r.dataformat)'; + + counter = 1; + while counter*h.channeloffset < r.ldnsamples + dat(:, counter*h.channeloffset+1:counter*h.channeloffset+h.channeloffset) = ... + fread(fid, [h.channeloffset h.nchannels], r.dataformat)'; + counter = counter + 1; + end; + end ; + + % ftell(fid) + if strcmpi(r.scale, 'on') + disp('Scaling data .....') + %%% scaling to microvolts + for i=1:h.nchannels + bas=e(i).baseline;sen=e(i).senstivity;cal=e(i).calib; + mf=sen*(cal/204.8); + dat(i,:)=(dat(i,:)-bas).*mf; + end % end for i=1:h.nchannels + end; % end if (strcmpi(r.scale, 'on') + end ; + + ET_offset = (double(h.prevfile) * (2^32)) + double(h.eventtablepos); % prevfile contains high order bits of event table offset, eventtablepos contains the low order bits + fseek(fid, ET_offset, 'bof'); + + disp('Reading Event Table...') + eT.teeg = fread(fid,1,'uchar'); + eT.size = fread(fid,1,'ulong'); + eT.offset = fread(fid,1,'ulong'); + + if eT.teeg==2 + nevents=eT.size/sizeEvent2; + if nevents > 0 + ev2(nevents).stimtype = []; + for i=1:nevents + ev2(i).stimtype = fread(fid,1,'ushort'); + ev2(i).keyboard = fread(fid,1,'char'); + temp = fread(fid,1,'uint8'); + ev2(i).keypad_accept = bitand(15,temp); + ev2(i).accept_ev1 = bitshift(temp,-4); + ev2(i).offset = fread(fid,1,'long'); + ev2(i).type = fread(fid,1,'short'); + ev2(i).code = fread(fid,1,'short'); + ev2(i).latency = fread(fid,1,'float'); + ev2(i).epochevent = fread(fid,1,'char'); + ev2(i).accept = fread(fid,1,'char'); + ev2(i).accuracy = fread(fid,1,'char'); + end + else + ev2 = []; + end; + elseif eT.teeg==3 % type 3 is similar to type 2 except the offset field encodes the global sample frame + nevents=eT.size/sizeEvent3; + if nevents > 0 + ev2(nevents).stimtype = []; + if r.dataformat == 'int32' + bytes_per_samp = 4; % I only have 32 bit data, unable to check whether this is necessary, + else % perhaps there is no type 3 file with 16 bit data + bytes_per_samp = 2; + end + for i=1:nevents + ev2(i).stimtype = fread(fid,1,'ushort'); + ev2(i).keyboard = fread(fid,1,'char'); + temp = fread(fid,1,'uint8'); + ev2(i).keypad_accept = bitand(15,temp); + ev2(i).accept_ev1 = bitshift(temp,-4); + os = fread(fid,1,'ulong'); + ev2(i).offset = os * bytes_per_samp * h.nchannels; + ev2(i).type = fread(fid,1,'short'); + ev2(i).code = fread(fid,1,'short'); + ev2(i).latency = fread(fid,1,'float'); + ev2(i).epochevent = fread(fid,1,'char'); + ev2(i).accept = fread(fid,1,'char'); + ev2(i).accuracy = fread(fid,1,'char'); + end + else + ev2 = []; + end; + elseif eT.teeg==1 + nevents=eT.size/sizeEvent1; + if nevents > 0 + ev2(nevents).stimtype = []; + for i=1:nevents + ev2(i).stimtype = fread(fid,1,'ushort'); + ev2(i).keyboard = fread(fid,1,'char'); + +% modified by Andreas Widmann 2005/05/12 14:15:00 + %ev2(i).keypad_accept = fread(fid,1,'char'); + temp = fread(fid,1,'uint8'); + ev2(i).keypad_accept = bitand(15,temp); + ev2(i).accept_ev1 = bitshift(temp,-4); +% end modification + + ev2(i).offset = fread(fid,1,'long'); + end; + else + ev2 = []; + end; + else + disp('Skipping event table (tag != 1,2,3 ; theoritically impossible)'); + ev2 = []; + end + + +fseek(fid, -1, 'eof'); +t = fread(fid,'char'); + +f.header = h; +f.electloc = e; +f.data = dat; +f.Teeg = eT; +f.event = ev2; +f.tag=t; +% Surgical addition of number of samples +f.ldnsamples = r.ldnsamples ; + +%%%% channels labels +for i=1:h.nchannels + plab=sprintf('%c',f.electloc(i).lab); + if i>1 + lab=str2mat(lab,plab); + else + lab=plab; + end +end + +%%%% to change offest in bytes to points +if ~isempty(ev2) + if r.sample1 ~= 0 + % VL modification 2 ========================= + % fprintf(2,'Warning: events imported with a time shift might be innacurate (bug 661)\n'); + end; + ev2p=ev2; + ioff=900+(h.nchannels*75); %% initial offset : header + electordes desc + if strcmpi(r.dataformat, 'int16') + for i=1:nevents + ev2p(i).offset=(ev2p(i).offset-ioff)/(2*h.nchannels) - r.sample1; %% 2 short int end + end + else % 32 bits + for i=1:nevents + ev2p(i).offset=(ev2p(i).offset-ioff)/(4*h.nchannels) - r.sample1; %% 4 short int end + end + end; + f.event = ev2p; +end; + +frewind(fid); +fclose(fid); + +end diff --git a/external/fieldtrip/fileio/private/match_str.m b/external/fieldtrip/fileio/private/match_str.m new file mode 100644 index 0000000..602b2f1 --- /dev/null +++ b/external/fieldtrip/fileio/private/match_str.m @@ -0,0 +1,75 @@ +function [sel1, sel2] = match_str(a, b); + +% MATCH_STR looks for matching labels in two listst of strings +% and returns the indices into both the 1st and 2nd list of the matches. +% They will be ordered according to the first input argument. +% +% [sel1, sel2] = match_str(strlist1, strlist2) +% +% The strings can be stored as a char matrix or as an vertical array of +% cells, the matching is done for each row. + +% Copyright (C) 2000, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: match_str.m 951 2010-04-21 18:24:01Z roboos $ + +% ensure that both are cell-arrays +if isempty(a) + a = {}; +elseif ~iscell(a) + a = cellstr(a); +end +if isempty(b) + b = {}; +elseif ~iscell(b) + b = cellstr(b); +end + +% regardless of what optimizations are implemented, the code should remain +% functionally compatible to the original, which is +% for i=1:length(a) +% for j=1:length(b) +% if strcmp(a(i),b(j)) +% sel1 = [sel1; i]; +% sel2 = [sel2; j]; +% end +% end +% end + +% ensure that both are column vectors +a = a(:); +b = b(:); +Na = numel(a); +Nb = numel(b); + +% replace all unique strings by a unique number and use the fact that +% numeric comparisons are much faster than string comparisons +[dum1, dum2, c] = unique([a; b]); +a = c(1:Na); +b = c((Na+1):end); + +sel1 = []; +sel2 = []; +for i=1:length(a) + % s = find(strcmp(a(i), b)); % for string comparison + s = find(a(i)==b); % for numeric comparison + sel2 = [sel2; s]; + s(:) = i; + sel1 = [sel1; s]; +end diff --git a/external/fileio/private/mne2grad.m b/external/fieldtrip/fileio/private/mne2grad.m similarity index 81% rename from external/fileio/private/mne2grad.m rename to external/fieldtrip/fileio/private/mne2grad.m index 74ef5fe..7ea69c3 100644 --- a/external/fileio/private/mne2grad.m +++ b/external/fieldtrip/fileio/private/mne2grad.m @@ -9,26 +9,23 @@ % Laurence Hunt 03/12/2008 (with thanks to Joachim Gross's original script based on fiff_access). lhunt@fmrib.ox.ac.uk % -% $Log: mne2grad.m,v $ -% Revision 1.8 2009/04/22 14:55:41 vlalit -% Major bug fix by Laurence who originally mixed up magnetometers and planar gradiometers -% while building the grad. +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.7 2009/04/20 17:19:01 vlalit -% Changed the MNE reader not to set hdr.elec when there are no EEG channels. +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.6 2009/02/05 18:30:44 vlalit -% Updates by Laurence to recognize additional Neuromag sensor types +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.5 2009/01/23 18:56:54 vlalit -% Another bug fix -% -% Revision 1.3 2009/01/23 16:29:40 roboos -% convert label to column -% -% Revision 1.2 2009/01/23 16:16:55 roboos -% changed the input to the function, removed unused fiff_setup_read_raw at begin of function, added cvs log +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: mne2grad.m 1412 2010-07-15 10:46:19Z vlalit $ grad = []; @@ -104,11 +101,11 @@ t=orig.chs(n).coil_trans; grad.pnt(kCoil,:)=100*(t(1:3,4)-0.008*t(1:3,1)); % multiply with 100 to get cm grad.ori(kCoil,:)=t(1:3,3); - grad.tra(k,kCoil)=1; + grad.tra(k,kCoil)= -1; kCoil=kCoil+1; grad.pnt(kCoil,:)=100*(t(1:3,4)+0.008*t(1:3,1)); grad.ori(kCoil,:)=t(1:3,3); - grad.tra(k,kCoil)=-1; + grad.tra(k,kCoil)=1; kCoil=kCoil+1; grad.label{k}=deblank(orig.ch_names{n}); k=k+1; diff --git a/external/fileio/private/mxDeserialize.c b/external/fieldtrip/fileio/private/mxDeserialize.c old mode 100755 new mode 100644 similarity index 100% rename from external/fileio/private/mxDeserialize.c rename to external/fieldtrip/fileio/private/mxDeserialize.c diff --git a/external/fieldtrip/fileio/private/mxDeserialize.m b/external/fieldtrip/fileio/private/mxDeserialize.m new file mode 100644 index 0000000..517c843 --- /dev/null +++ b/external/fieldtrip/fileio/private/mxDeserialize.m @@ -0,0 +1,55 @@ +function [varargout] = funname(varargin) + +% FUNNAME compile the missing mex file on the fly + +% Copyright (C) 2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: mxDeserialize.m 945 2010-04-21 17:41:20Z roboos $ + +% remember the original working directory +pwdir = pwd; + +% determine the name and full path of this function +funname = mfilename('fullpath'); +mexsrc = [funname '.c']; +[mexdir, mexname] = fileparts(funname); + +try + % try to compile the mex file on the fly + warning('trying to compile MEX file from %s', mexsrc); + cd(mexdir); + mex(mexsrc); + cd(pwdir); + success = true; + +catch + % compilation failed + disp(lasterr); + error('could not locate MEX file for %s', mexname); + cd(pwdir); + success = false; +end + +if success + % execute the mex file that was juist created + funname = mfilename; + funhandle = str2func(funname); + [varargout{1:nargout}] = funhandle(varargin{:}); +end + diff --git a/external/fileio/private/mxDeserialize.mexa64 b/external/fieldtrip/fileio/private/mxDeserialize.mexa64 similarity index 100% rename from external/fileio/private/mxDeserialize.mexa64 rename to external/fieldtrip/fileio/private/mxDeserialize.mexa64 diff --git a/external/fileio/private/mxDeserialize.mexglx b/external/fieldtrip/fileio/private/mxDeserialize.mexglx similarity index 100% rename from external/fileio/private/mxDeserialize.mexglx rename to external/fieldtrip/fileio/private/mxDeserialize.mexglx diff --git a/external/fileio/private/mxDeserialize.mexmaci b/external/fieldtrip/fileio/private/mxDeserialize.mexmaci similarity index 99% rename from external/fileio/private/mxDeserialize.mexmaci rename to external/fieldtrip/fileio/private/mxDeserialize.mexmaci index 97a2680..6e45ada 100755 Binary files a/external/fileio/private/mxDeserialize.mexmaci and b/external/fieldtrip/fileio/private/mxDeserialize.mexmaci differ diff --git a/external/fileio/private/mxDeserialize.mexmaci64 b/external/fieldtrip/fileio/private/mxDeserialize.mexmaci64 similarity index 100% rename from external/fileio/private/mxDeserialize.mexmaci64 rename to external/fieldtrip/fileio/private/mxDeserialize.mexmaci64 diff --git a/external/fileio/private/mxDeserialize.mexw32 b/external/fieldtrip/fileio/private/mxDeserialize.mexw32 similarity index 75% rename from external/fileio/private/mxDeserialize.mexw32 rename to external/fieldtrip/fileio/private/mxDeserialize.mexw32 index 4a1d112..f185edd 100644 Binary files a/external/fileio/private/mxDeserialize.mexw32 and b/external/fieldtrip/fileio/private/mxDeserialize.mexw32 differ diff --git a/external/fileio/private/mxDeserialize.mexw64 b/external/fieldtrip/fileio/private/mxDeserialize.mexw64 similarity index 96% rename from external/fileio/private/mxDeserialize.mexw64 rename to external/fieldtrip/fileio/private/mxDeserialize.mexw64 index 83d90e3..615bacc 100644 Binary files a/external/fileio/private/mxDeserialize.mexw64 and b/external/fieldtrip/fileio/private/mxDeserialize.mexw64 differ diff --git a/external/fileio/private/mxSerialize.c b/external/fieldtrip/fileio/private/mxSerialize.c old mode 100755 new mode 100644 similarity index 100% rename from external/fileio/private/mxSerialize.c rename to external/fieldtrip/fileio/private/mxSerialize.c diff --git a/external/fieldtrip/fileio/private/mxSerialize.m b/external/fieldtrip/fileio/private/mxSerialize.m new file mode 100644 index 0000000..bfc6bd2 --- /dev/null +++ b/external/fieldtrip/fileio/private/mxSerialize.m @@ -0,0 +1,55 @@ +function [varargout] = funname(varargin) + +% FUNNAME compile the missing mex file on the fly + +% Copyright (C) 2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: mxSerialize.m 945 2010-04-21 17:41:20Z roboos $ + +% remember the original working directory +pwdir = pwd; + +% determine the name and full path of this function +funname = mfilename('fullpath'); +mexsrc = [funname '.c']; +[mexdir, mexname] = fileparts(funname); + +try + % try to compile the mex file on the fly + warning('trying to compile MEX file from %s', mexsrc); + cd(mexdir); + mex(mexsrc); + cd(pwdir); + success = true; + +catch + % compilation failed + disp(lasterr); + error('could not locate MEX file for %s', mexname); + cd(pwdir); + success = false; +end + +if success + % execute the mex file that was juist created + funname = mfilename; + funhandle = str2func(funname); + [varargout{1:nargout}] = funhandle(varargin{:}); +end + diff --git a/external/fileio/private/mxSerialize.mexa64 b/external/fieldtrip/fileio/private/mxSerialize.mexa64 similarity index 100% rename from external/fileio/private/mxSerialize.mexa64 rename to external/fieldtrip/fileio/private/mxSerialize.mexa64 diff --git a/external/fileio/private/mxSerialize.mexglx b/external/fieldtrip/fileio/private/mxSerialize.mexglx similarity index 100% rename from external/fileio/private/mxSerialize.mexglx rename to external/fieldtrip/fileio/private/mxSerialize.mexglx diff --git a/external/fileio/private/mxSerialize.mexmaci b/external/fieldtrip/fileio/private/mxSerialize.mexmaci similarity index 98% rename from external/fileio/private/mxSerialize.mexmaci rename to external/fieldtrip/fileio/private/mxSerialize.mexmaci index 63d3369..46f21b0 100755 Binary files a/external/fileio/private/mxSerialize.mexmaci and b/external/fieldtrip/fileio/private/mxSerialize.mexmaci differ diff --git a/external/fileio/private/mxSerialize.mexmaci64 b/external/fieldtrip/fileio/private/mxSerialize.mexmaci64 similarity index 100% rename from external/fileio/private/mxSerialize.mexmaci64 rename to external/fieldtrip/fileio/private/mxSerialize.mexmaci64 diff --git a/external/fileio/private/mxSerialize.mexw32 b/external/fieldtrip/fileio/private/mxSerialize.mexw32 similarity index 76% rename from external/fileio/private/mxSerialize.mexw32 rename to external/fieldtrip/fileio/private/mxSerialize.mexw32 index c18c6fd..2d764f7 100644 Binary files a/external/fileio/private/mxSerialize.mexw32 and b/external/fieldtrip/fileio/private/mxSerialize.mexw32 differ diff --git a/external/fileio/private/mxSerialize.mexw64 b/external/fieldtrip/fileio/private/mxSerialize.mexw64 similarity index 96% rename from external/fileio/private/mxSerialize.mexw64 rename to external/fieldtrip/fileio/private/mxSerialize.mexw64 index 4f1b2df..cc3ec27 100644 Binary files a/external/fileio/private/mxSerialize.mexw64 and b/external/fieldtrip/fileio/private/mxSerialize.mexw64 differ diff --git a/external/fieldtrip/fileio/private/neuralynx_crc.m b/external/fieldtrip/fileio/private/neuralynx_crc.m new file mode 100644 index 0000000..fa5fb48 --- /dev/null +++ b/external/fieldtrip/fileio/private/neuralynx_crc.m @@ -0,0 +1,39 @@ +function crc = neuralynx_crc(dat, dim) + +% NEURALYNX_CRC computes a cyclic redundancy check +% +% Use as +% crc = neuralynx_crc(dat) +% +% Note that the CRC is computed along the first dimension. + +% Copyright (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: neuralynx_crc.m 945 2010-04-21 17:41:20Z roboos $ + + +nchans = size(dat,1); +nsamples = size(dat,2); + +crc = zeros(1,nsamples,class(dat)); + +for i=1:nchans + crc = bitxor(crc, dat(i,:)); +end + diff --git a/external/fieldtrip/fileio/private/neuralynx_getheader.m b/external/fieldtrip/fileio/private/neuralynx_getheader.m new file mode 100644 index 0000000..0f2eaf0 --- /dev/null +++ b/external/fieldtrip/fileio/private/neuralynx_getheader.m @@ -0,0 +1,76 @@ +function [hdr] = neuralynx_getheader(filename); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION for reading the 16384 byte header from any Neuralynx file +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Copyright (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: neuralynx_getheader.m 945 2010-04-21 17:41:20Z roboos $ + +fid = fopen(filename, 'rb', 'ieee-le'); +buf = fread(fid, 16*1024, 'uint8=>char'); +fclose(fid); + +buf = buf(:)'; +nl = find(buf==10); % determine the new-lines +cr = find(buf==13); % determine the carriage-returns +begchar = [1 nl(1:(end-1))]; +endchar = nl - 1; +num = length(nl); + +hdr = []; +hdr.Header = buf; % remember the full header in its original format + +for i=1:num + line = fliplr(deblank(fliplr(deblank(char(buf(begchar(i):endchar(i))))))); + if numel(line)==0 + % line is empty + continue + elseif line(1)=='#' + % line contains a comment + continue + else + % strip the '-' sign + while line(1)=='-' + line = line(2:end); + end + % replace tabs with spaces + line(find(line==9)) = ' '; + % cut into pieces + item = strread(line, '%s'); + if length(item)==2 + key = item{1}; + val = item{2}; + if any(val(1)=='-01234567989') + % try to convert to number + val = str2num(val); + if isempty(val) + % revert to the original text + val = item{2}; + end + end + % remove unuseable characters from the variable name (key) + key = key(key~=':'); + % assign the value to the header structure + hdr = setfield(hdr, key, val); + end + end +end + diff --git a/external/fieldtrip/fileio/private/neuralynx_numrecords.m b/external/fieldtrip/fileio/private/neuralynx_numrecords.m new file mode 100644 index 0000000..0f1e346 --- /dev/null +++ b/external/fieldtrip/fileio/private/neuralynx_numrecords.m @@ -0,0 +1,42 @@ +function [t] = neuralynx_numrecords(filename) + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION for determining the number of records in a single channel Neualynx file +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Copyright (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: neuralynx_numrecords.m 945 2010-04-21 17:41:20Z roboos $ + +headersize = 16384; +switch filetype(filename) + case 'neuralynx_ncs' + recordsize = 1044; % in bytes + case 'neuralynx_nse' + recordsize = 112; % in bytes + case 'neuralynx_nts' + recordsize = 8; % in bytes + otherwise + error('unsupported filetype'); +end + +fid = fopen(filename, 'rb', 'ieee-le'); +fseek(fid, 0, 'eof'); +t = floor((ftell(fid) - headersize)/recordsize); +fclose(fid); diff --git a/external/fieldtrip/fileio/private/neuralynx_timestamp.m b/external/fieldtrip/fileio/private/neuralynx_timestamp.m new file mode 100644 index 0000000..5d7d657 --- /dev/null +++ b/external/fieldtrip/fileio/private/neuralynx_timestamp.m @@ -0,0 +1,68 @@ +function [t] = neuralynx_timestamp(filename, num) + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION for reading a single timestamp of a single channel Neuralynx file +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Copyright (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: neuralynx_timestamp.m 945 2010-04-21 17:41:20Z roboos $ + +headersize = 16384; +switch filetype(filename) + case 'neuralynx_ncs' + recordsize = 1044; % in bytes + case 'neuralynx_nse' + recordsize = 112; % in bytes + case 'neuralynx_nst' + recordsize = 304; % in bytes + case 'neuralynx_nts' + recordsize = 8; % in bytes + case 'neuralynx_ntt' + recordsize = 304; % in bytes +end + +fid = fopen(filename, 'rb', 'ieee-le'); + +if (ispc) + % this is to fix a bug in the windwos version which does not want to do uint64=>uint64 + % however this code will fail if the MSB is set (only likely in very long recordings) + if ~isinf(num) + % read the timestamp of the indicated record + fseek(fid, headersize + (num-1)*recordsize, 'bof'); + t = fread(fid, 1, 'uint64=>integer*8'); + else + % read the timestamp of the last record + fseek(fid, -recordsize, 'eof'); + t = fread(fid, 1, 'uint64=>integer*8'); + end + t = uint64(t); +else + if ~isinf(num) + % read the timestamp of the indicated record + fseek(fid, headersize + (num-1)*recordsize, 'bof'); + t = fread(fid, 1, 'uint64=>uint64'); + else + % read the timestamp of the last record + fseek(fid, -recordsize, 'eof'); + t = fread(fid, 1, 'uint64=>uint64'); + end +end + +fclose(fid); diff --git a/external/fileio/private/np_read_splitted_fileinfo.m b/external/fieldtrip/fileio/private/np_read_splitted_fileinfo.m similarity index 99% rename from external/fileio/private/np_read_splitted_fileinfo.m rename to external/fieldtrip/fileio/private/np_read_splitted_fileinfo.m index 6002abf..3c21c32 100644 --- a/external/fileio/private/np_read_splitted_fileinfo.m +++ b/external/fieldtrip/fileio/private/np_read_splitted_fileinfo.m @@ -386,4 +386,4 @@ catch fclose(fid); error('Error while calculating physical minimum or maximum.'); -end \ No newline at end of file +end diff --git a/external/fileio/private/np_readdata.m b/external/fieldtrip/fileio/private/np_readdata.m similarity index 100% rename from external/fileio/private/np_readdata.m rename to external/fieldtrip/fileio/private/np_readdata.m diff --git a/external/fileio/private/np_readfileinfo.m b/external/fieldtrip/fileio/private/np_readfileinfo.m similarity index 100% rename from external/fileio/private/np_readfileinfo.m rename to external/fieldtrip/fileio/private/np_readfileinfo.m diff --git a/external/fileio/private/np_readmarker.m b/external/fieldtrip/fileio/private/np_readmarker.m similarity index 99% rename from external/fileio/private/np_readmarker.m rename to external/fieldtrip/fileio/private/np_readmarker.m index 19a3206..a6d0874 100644 --- a/external/fileio/private/np_readmarker.m +++ b/external/fieldtrip/fileio/private/np_readmarker.m @@ -272,4 +272,4 @@ last_MarkerTyp=MarkerTyp; last_SampleIndex=SampleIndex; end % if ~isempty... -end % for b=1:... \ No newline at end of file +end % for b=1:... diff --git a/external/fileio/private/openbdf.m b/external/fieldtrip/fileio/private/openbdf.m similarity index 76% rename from external/fileio/private/openbdf.m rename to external/fieldtrip/fileio/private/openbdf.m index ed418d5..97c2dbd 100644 --- a/external/fileio/private/openbdf.m +++ b/external/fieldtrip/fileio/private/openbdf.m @@ -9,13 +9,13 @@ % % See also: readedf() -% Copyright (C) 1997-1998 by Alois Schloegl -% a.schloegl@ieee.org -% Ver 2.20 18.Aug.1998 -% Ver 2.21 10.Oct.1998 -% Ver 2.30 5.Nov.1998 +% Copyright (C) 1997-1998 by Alois Schloegl +% a.schloegl@ieee.org +% Ver 2.20 18.Aug.1998 +% Ver 2.21 10.Oct.1998 +% Ver 2.30 5.Nov.1998 % -% For use under Octave define the following function +% For use under Octave define the following function % function s=upper(s); s=toupper(s); end; % V2.12 Warning for missing Header information @@ -41,7 +41,7 @@ function [DAT,H1]=openbdf(FILENAME) -SLASH='/'; % defines Seperator for Subdirectories +SLASH='/'; % defines Seperator for Subdirectories BSLASH=char(92); cname=computer; @@ -49,8 +49,8 @@ fid=fopen(FILENAME,'r','ieee-le'); if fid<0 - fprintf(2,['Error LOADEDF: File ' FILENAME ' not found\n']); - return; + fprintf(2,['Error LOADEDF: File ' FILENAME ' not found\n']); + return; end; EDF.FILE.FID=fid; @@ -62,9 +62,9 @@ EDF.FILE.Ext = FILENAME(PPos+1:length(FILENAME)); EDF.FILE.Name = FILENAME(SPos+1:PPos-1); if SPos==0 - EDF.FILE.Path = pwd; + EDF.FILE.Path = pwd; else - EDF.FILE.Path = FILENAME(1:SPos-1); + EDF.FILE.Path = FILENAME(1:SPos-1); end; EDF.FileName = [EDF.FILE.Path SLASH EDF.FILE.Name '.' EDF.FILE.Ext]; @@ -73,8 +73,8 @@ %if 0 fprintf(2,'LOADEDF: WARNING Version EDF Format %i',ver); end; EDF.PID = deblank(H1(9:88)); % 80 Byte local patient identification EDF.RID = deblank(H1(89:168)); % 80 Byte local recording identification -%EDF.H.StartDate = H1(169:176); % 8 Byte -%EDF.H.StartTime = H1(177:184); % 8 Byte +%EDF.H.StartDate = H1(169:176); % 8 Byte +%EDF.H.StartTime = H1(177:184); % 8 Byte EDF.T0=[str2num(H1(168+[7 8])) str2num(H1(168+[4 5])) str2num(H1(168+[1 2])) str2num(H1(168+[9 10])) str2num(H1(168+[12 13])) str2num(H1(168+[15 16])) ]; % Y2K compatibility until year 2090 @@ -89,19 +89,19 @@ end; EDF.HeadLen = str2num(H1(185:192)); % 8 Byte Length of Header -% reserved = H1(193:236); % 44 Byte +% reserved = H1(193:236); % 44 Byte EDF.NRec = str2num(H1(237:244)); % 8 Byte # of data records EDF.Dur = str2num(H1(245:252)); % 8 Byte # duration of data record in sec EDF.NS = str2num(H1(253:256)); % 8 Byte # of signals -EDF.Label = char(fread(EDF.FILE.FID,[16,EDF.NS],'char')'); -EDF.Transducer = char(fread(EDF.FILE.FID,[80,EDF.NS],'char')'); -EDF.PhysDim = char(fread(EDF.FILE.FID,[8,EDF.NS],'char')'); +EDF.Label = char(fread(EDF.FILE.FID,[16,EDF.NS],'char')'); +EDF.Transducer = char(fread(EDF.FILE.FID,[80,EDF.NS],'char')'); +EDF.PhysDim = char(fread(EDF.FILE.FID,[8,EDF.NS],'char')'); -EDF.PhysMin= str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); -EDF.PhysMax= str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); -EDF.DigMin = str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); % -EDF.DigMax = str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); % +EDF.PhysMin= str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); +EDF.PhysMax= str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); +EDF.DigMin = str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); % +EDF.DigMax = str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); % % check validity of DigMin and DigMax if (length(EDF.DigMin) ~= EDF.NS) @@ -129,9 +129,9 @@ EDF.PhysMin = EDF.DigMin; EDF.PhysMax = EDF.DigMax; end -EDF.PreFilt= char(fread(EDF.FILE.FID,[80,EDF.NS],'char')'); % -tmp = fread(EDF.FILE.FID,[8,EDF.NS],'char')'; % samples per data record -EDF.SPR = str2num(char(tmp)); % samples per data record +EDF.PreFilt= char(fread(EDF.FILE.FID,[80,EDF.NS],'char')'); % +tmp = fread(EDF.FILE.FID,[8,EDF.NS],'char')'; % samples per data record +EDF.SPR = str2num(char(tmp)); % samples per data record fseek(EDF.FILE.FID,32*EDF.NS,0); @@ -159,30 +159,30 @@ EDF.Chan_Select=(EDF.SPR==max(EDF.SPR)); for k=1:EDF.NS - if EDF.Chan_Select(k) - EDF.ChanTyp(k)='N'; - else - EDF.ChanTyp(k)=' '; - end; - if findstr(upper(EDF.Label(k,:)),'ECG') - EDF.ChanTyp(k)='C'; - elseif findstr(upper(EDF.Label(k,:)),'EKG') - EDF.ChanTyp(k)='C'; - elseif findstr(upper(EDF.Label(k,:)),'EEG') - EDF.ChanTyp(k)='E'; - elseif findstr(upper(EDF.Label(k,:)),'EOG') - EDF.ChanTyp(k)='O'; - elseif findstr(upper(EDF.Label(k,:)),'EMG') - EDF.ChanTyp(k)='M'; - end; + if EDF.Chan_Select(k) + EDF.ChanTyp(k)='N'; + else + EDF.ChanTyp(k)=' '; + end; + if findstr(upper(EDF.Label(k,:)),'ECG') + EDF.ChanTyp(k)='C'; + elseif findstr(upper(EDF.Label(k,:)),'EKG') + EDF.ChanTyp(k)='C'; + elseif findstr(upper(EDF.Label(k,:)),'EEG') + EDF.ChanTyp(k)='E'; + elseif findstr(upper(EDF.Label(k,:)),'EOG') + EDF.ChanTyp(k)='O'; + elseif findstr(upper(EDF.Label(k,:)),'EMG') + EDF.ChanTyp(k)='M'; + end; end; -EDF.AS.spb = sum(EDF.SPR); % Samples per Block +EDF.AS.spb = sum(EDF.SPR); % Samples per Block bi=[0;cumsum(EDF.SPR)]; idx=[];idx2=[]; for k=1:EDF.NS, - idx2=[idx2, (k-1)*max(EDF.SPR)+(1:EDF.SPR(k))]; + idx2=[idx2, (k-1)*max(EDF.SPR)+(1:EDF.SPR(k))]; end; maxspr=max(EDF.SPR); idx3=zeros(EDF.NS*maxspr,1); diff --git a/external/fieldtrip/fileio/private/pthreadGC2.dll b/external/fieldtrip/fileio/private/pthreadGC2.dll new file mode 100755 index 0000000..2b7cc67 Binary files /dev/null and b/external/fieldtrip/fileio/private/pthreadGC2.dll differ diff --git a/external/fieldtrip/fileio/private/pthreadVC2.dll b/external/fieldtrip/fileio/private/pthreadVC2.dll new file mode 100755 index 0000000..93f562b Binary files /dev/null and b/external/fieldtrip/fileio/private/pthreadVC2.dll differ diff --git a/external/fieldtrip/fileio/private/read_16bit.c b/external/fieldtrip/fileio/private/read_16bit.c new file mode 100644 index 0000000..a0f9104 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_16bit.c @@ -0,0 +1,106 @@ +#include +#include +#include "mex.h" +#include "matrix.h" + +/* + * Copyright (C) 2008, Robert Oostenveld, F.C. Donders Ccentre for Cognitive Neuroimaging + * Copyright (C) 2007, Peter Desain, Nijmegen Institute for Cognition and Information + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * + * $Log: read_16bit.c,v $ + * Revision 1.1 2009/01/14 09:43:37 roboos + * moved source code for mex file from fileio/mex to file/private + * compiling the source code from within Matlab now ensures that the mex file will be located immediately at the right position + * + * Revision 1.1 2008/04/09 10:04:37 roboos + * new code based in 24bit, not tested + * + * + * + */ + +void +mexFunction (int nlhs, mxArray * plhs[], int nrhs, const mxArray * prhs[]) +{ + FILE *fp; + mxArray *dat; + double *dat_p; + char *filename; + short int *buf; + long int offset, numwords, fnlen, i, j, num, b1, b2, b3; + + if (nrhs != 3) + mexErrMsgTxt ("Invalid number of input arguments"); + + if (mxGetM(prhs[1])!=1 || mxGetN(prhs[1])!=1) + mexErrMsgTxt ("Invalid dimension for input argument 2"); + if (mxGetM(prhs[2])!=1 || mxGetN(prhs[2])!=1) + mexErrMsgTxt ("Invalid dimension for input argument 3"); + + /* get the filename */ + fnlen = mxGetN (prhs[0]); + filename = mxCalloc(fnlen+1, sizeof(char)); + mxGetString(prhs[0], filename, fnlen+1); + + /* get values and typecast to integer */ + offset = (long int)(mxGetScalar (prhs[1])); + numwords = (long int)(mxGetScalar (prhs[2])); + + /* + printf("filename = %s\n", filename); + printf("fnlen = %d\n", fnlen); + printf("offset = %d\n", offset); + printf("numwords = %d\n", numwords); + */ + + /* open the file and read the desired bytes */ + fp = fopen(filename, "rb"); + if (fp==NULL) + { + printf("error opening file: %s\n", filename); + return; + } + fseek(fp, offset, SEEK_SET); + + buf = mxCalloc(numwords, sizeof(short)); + num = fread(buf, sizeof(short), numwords, fp); + if (num. +% +% $Id: read_16bit.m 945 2010-04-21 17:41:20Z roboos $ + +% remember the original working directory +pwdir = pwd; + +% determine the name and full path of this function +funname = mfilename('fullpath'); +mexsrc = [funname '.c']; +[mexdir, mexname] = fileparts(funname); + +try + % try to compile the mex file on the fly + warning('trying to compile MEX file from %s', mexsrc); + cd(mexdir); + mex(mexsrc); + cd(pwdir); + success = true; + +catch + % compilation failed + disp(lasterr); + error('could not locate MEX file for %s', mexname); + cd(pwdir); + success = false; +end + +if success + % execute the mex file that was juist created + funname = mfilename; + funhandle = str2func(funname); + [varargout{1:nargout}] = funhandle(varargin{:}); +end + diff --git a/external/fieldtrip/fileio/private/read_16bit.mexa64 b/external/fieldtrip/fileio/private/read_16bit.mexa64 new file mode 100755 index 0000000..8845288 Binary files /dev/null and b/external/fieldtrip/fileio/private/read_16bit.mexa64 differ diff --git a/external/fieldtrip/fileio/private/read_16bit.mexglx b/external/fieldtrip/fileio/private/read_16bit.mexglx new file mode 100755 index 0000000..d243aee Binary files /dev/null and b/external/fieldtrip/fileio/private/read_16bit.mexglx differ diff --git a/external/fieldtrip/fileio/private/read_16bit.mexmaci b/external/fieldtrip/fileio/private/read_16bit.mexmaci new file mode 100755 index 0000000..f130774 Binary files /dev/null and b/external/fieldtrip/fileio/private/read_16bit.mexmaci differ diff --git a/external/fieldtrip/fileio/private/read_16bit.mexmaci64 b/external/fieldtrip/fileio/private/read_16bit.mexmaci64 new file mode 100755 index 0000000..5028912 Binary files /dev/null and b/external/fieldtrip/fileio/private/read_16bit.mexmaci64 differ diff --git a/external/fieldtrip/fileio/private/read_16bit.mexw32 b/external/fieldtrip/fileio/private/read_16bit.mexw32 new file mode 100644 index 0000000..deb8016 Binary files /dev/null and b/external/fieldtrip/fileio/private/read_16bit.mexw32 differ diff --git a/external/fieldtrip/fileio/private/read_16bit.mexw64 b/external/fieldtrip/fileio/private/read_16bit.mexw64 new file mode 100644 index 0000000..bc5cf6c Binary files /dev/null and b/external/fieldtrip/fileio/private/read_16bit.mexw64 differ diff --git a/external/fieldtrip/private/read_24bit.c b/external/fieldtrip/fileio/private/read_24bit.c similarity index 100% rename from external/fieldtrip/private/read_24bit.c rename to external/fieldtrip/fileio/private/read_24bit.c diff --git a/external/fieldtrip/fileio/private/read_24bit.m b/external/fieldtrip/fileio/private/read_24bit.m new file mode 100644 index 0000000..628c1a1 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_24bit.m @@ -0,0 +1,62 @@ +function [varargout] = funname(varargin) + +% READ_24BIT read a stream of 24 bit values and converts them to doubles +% This function is designed for Biosemi BDF files and is implemented as mex +% file for efficiency. +% +% Use as +% [dat] = read_24bit(filename, offset, numwords); +% +% See also READ_16BIT + +% Copyright (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_24bit.m 945 2010-04-21 17:41:20Z roboos $ + +% remember the original working directory +pwdir = pwd; + +% determine the name and full path of this function +funname = mfilename('fullpath'); +mexsrc = [funname '.c']; +[mexdir, mexname] = fileparts(funname); + +try + % try to compile the mex file on the fly + warning('trying to compile MEX file from %s', mexsrc); + cd(mexdir); + mex(mexsrc); + cd(pwdir); + success = true; + +catch + % compilation failed + disp(lasterr); + error('could not locate MEX file for %s', mexname); + cd(pwdir); + success = false; +end + +if success + % execute the mex file that was juist created + funname = mfilename; + funhandle = str2func(funname); + [varargout{1:nargout}] = funhandle(varargin{:}); +end + diff --git a/external/fieldtrip/private/read_24bit.mexa64 b/external/fieldtrip/fileio/private/read_24bit.mexa64 similarity index 100% rename from external/fieldtrip/private/read_24bit.mexa64 rename to external/fieldtrip/fileio/private/read_24bit.mexa64 diff --git a/external/fieldtrip/private/read_24bit.mexglx b/external/fieldtrip/fileio/private/read_24bit.mexglx similarity index 100% rename from external/fieldtrip/private/read_24bit.mexglx rename to external/fieldtrip/fileio/private/read_24bit.mexglx diff --git a/external/fieldtrip/fileio/private/read_24bit.mexmaci b/external/fieldtrip/fileio/private/read_24bit.mexmaci new file mode 100755 index 0000000..863c4cb Binary files /dev/null and b/external/fieldtrip/fileio/private/read_24bit.mexmaci differ diff --git a/external/fieldtrip/private/read_24bit.mexmaci64 b/external/fieldtrip/fileio/private/read_24bit.mexmaci64 similarity index 100% rename from external/fieldtrip/private/read_24bit.mexmaci64 rename to external/fieldtrip/fileio/private/read_24bit.mexmaci64 diff --git a/external/fieldtrip/fileio/private/read_24bit.mexw32 b/external/fieldtrip/fileio/private/read_24bit.mexw32 new file mode 100644 index 0000000..6987d8e Binary files /dev/null and b/external/fieldtrip/fileio/private/read_24bit.mexw32 differ diff --git a/external/fieldtrip/fileio/private/read_24bit.mexw64 b/external/fieldtrip/fileio/private/read_24bit.mexw64 new file mode 100644 index 0000000..432181b Binary files /dev/null and b/external/fieldtrip/fileio/private/read_24bit.mexw64 differ diff --git a/external/fieldtrip/fileio/private/read_4d_hdr.m b/external/fieldtrip/fileio/private/read_4d_hdr.m new file mode 100644 index 0000000..16c7ca3 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_4d_hdr.m @@ -0,0 +1,496 @@ +function [header] = read_4d_hdr(datafile, configfile) + +% hdr=READ_4D_HDR(datafile, configfile) +% Collects the required Fieldtrip header data from the data file 'filename' +% and the associated 'config' file for that data. +% +% Adapted from the MSI>>Matlab code written by Eugene Kronberg + +% Copyright (C) 2008-2009, Centre for Cognitive Neuroimaging, Glasgow, Gavin Paterson & J.M.Schoffelen +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_4d_hdr.m 945 2010-04-21 17:41:20Z roboos $ + +%read header +if nargin ~= 2 + error('Wrong number of input arguments'); +end + +if ~isempty(datafile), + %always big endian + fid = fopen(datafile, 'r', 'b'); + + if fid == -1 + error('Cannot open file %s', datafile); + end + + fseek(fid, 0, 'eof'); + header_end = ftell(fid); + %last 8 bytes of the pdf is header offset + fseek(fid, -8, 'eof'); + header_offset = fread(fid,1,'uint64'); + + %first byte of the header + fseek(fid, header_offset, 'bof'); + + % read header data + align_file_pointer(fid) + header.header_data.FileType = fread(fid, 1, 'uint16=>uint16'); + file_type = char(fread(fid, 5, 'uchar'))'; + header.header_data.file_type = file_type(file_type>0); + fseek(fid, 1, 'cof'); + format = fread(fid, 1, 'int16=>int16'); + switch format + case 1 + header.header_data.Format = 'SHORT'; + case 2 + header.header_data.Format = 'LONG'; + case 3 + header.header_data.Format = 'FLOAT'; + case 4 + header.header_data.Format ='DOUBLE'; + end + header.header_data.acq_mode = fread(fid, 1, 'uint16=>uint16'); + header.header_data.TotalEpochs = fread(fid, 1, 'uint32=>double'); + header.header_data.input_epochs = fread(fid, 1, 'uint32=>uint32'); + header.header_data.TotalEvents = fread(fid, 1, 'uint32=>uint32'); + header.header_data.total_fixed_events = fread(fid, 1, 'uint32=>uint32'); + header.header_data.SamplePeriod = fread(fid, 1, 'float32=>float64'); + header.header_data.SampleFrequency = 1/header.header_data.SamplePeriod; + xaxis_label = char(fread(fid, 16, 'uchar'))'; + header.header_data.xaxis_label = xaxis_label(xaxis_label>0); + header.header_data.total_processes = fread(fid, 1, 'uint32=>uint32'); + header.header_data.TotalChannels = fread(fid, 1, 'uint16=>double'); + fseek(fid, 2, 'cof'); + header.header_data.checksum = fread(fid, 1, 'int32=>int32'); + header.header_data.total_ed_classes = fread(fid, 1, 'uint32=>uint32'); + header.header_data.total_associated_files = fread(fid, 1, 'uint16=>uint16'); + header.header_data.last_file_index = fread(fid, 1, 'uint16=>uint16'); + header.header_data.timestamp = fread(fid, 1, 'uint32=>uint32'); + header.header_data.reserved = fread(fid, 20, 'uchar')'; + fseek(fid, 4, 'cof'); + + %read epoch_data + for epoch = 1:header.header_data.TotalEpochs; + align_file_pointer(fid) + + header.epoch_data(epoch).pts_in_epoch = fread(fid, 1, 'uint32=>uint32'); + header.epoch_data(epoch).epoch_duration = fread(fid, 1, 'float32=>float32'); + header.epoch_data(epoch).expected_iti = fread(fid, 1, 'float32=>float32'); + header.epoch_data(epoch).actual_iti = fread(fid, 1, 'float32=>float32'); + header.epoch_data(epoch).total_var_events = fread(fid, 1, 'uint32=>uint32'); + header.epoch_data(epoch).checksum = fread(fid, 1, 'int32=>int32'); + header.epoch_data(epoch).epoch_timestamp = fread(fid, 1, 'int32=>int32'); + header.epoch_data(epoch).reserved = fread(fid, 28, 'uchar')'; + header.header_data.SlicesPerEpoch = double(header.epoch_data(1).pts_in_epoch); + + %read event data (var_events) + for event = 1:header.epoch_data(epoch).total_var_events + align_file_pointer(fid) + + event_name = char(fread(fid, 16, 'uchar'))'; + header.epoch_data(epoch).var_event{event}.event_name = event_name(event_name>0); + header.epoch_data(epoch).var_event{event}.start_lat = fread(fid, 1, 'float32=>float32'); + header.epoch_data(epoch).var_event{event}.end_lat = fread(fid, 1, 'float32=>float32'); + header.epoch_data(epoch).var_event{event}.step_size = fread(fid, 1, 'float32=>float32'); + header.epoch_data(epoch).var_event{event}.fixed_event = fread(fid, 1, 'uint16=>uint16'); + fseek(fid, 2, 'cof'); + header.epoch_data(epoch).var_event{event}.checksum = fread(fid, 1, 'int32=>int32'); + header.epoch_data(epoch).var_event{event}.reserved = fread(fid, 32, 'uchar')'; + fseek(fid, 4, 'cof'); + end + end + + %read channel ref data + for channel = 1:header.header_data.TotalChannels + align_file_pointer(fid) + + chan_label = (fread(fid, 16, 'uint8=>char'))'; + header.channel_data(channel).chan_label = chan_label(chan_label>0); + header.channel_data(channel).chan_no = fread(fid, 1, 'uint16=>uint16'); + header.channel_data(channel).attributes = fread(fid, 1, 'uint16=>uint16'); + header.channel_data(channel).scale = fread(fid, 1, 'float32=>float32'); + yaxis_label = char(fread(fid, 16, 'uint8=>char'))'; + header.channel_data(channel).yaxis_label = yaxis_label(yaxis_label>0); + header.channel_data(channel).valid_min_max = fread(fid, 1, 'uint16=>uint16'); + fseek(fid, 6, 'cof'); + header.channel_data(channel).ymin = fread(fid, 1, 'float64'); + header.channel_data(channel).ymax = fread(fid, 1, 'float64'); + header.channel_data(channel).index = fread(fid, 1, 'uint32=>uint32'); + header.channel_data(channel).checksum = fread(fid, 1, 'int32=>int32'); + header.channel_data(channel).whatisit = char(fread(fid, 4, 'uint8=>char'))'; + header.channel_data(channel).reserved = fread(fid, 28, 'uint8')'; + end + + %read event data + for event = 1:header.header_data.total_fixed_events + align_file_pointer(fid) + event_name = char(fread(fid, 16, 'uchar'))'; + header.event_data(event).event_name = event_name(event_name>0); + header.event_data(event).start_lat = fread(fid, 1, 'float32=>float32'); + header.event_data(event).end_lat = fread(fid, 1, 'float32=>float32'); + header.event_data(event).step_size = fread(fid, 1, 'float32=>float32'); + header.event_data(event).fixed_event = fread(fid, 1, 'uint16=>uint16'); + fseek(fid, 2, 'cof'); + header.event_data(event).checksum = fread(fid, 1, 'int32=>int32'); + header.event_data(event).reserved = fread(fid, 32, 'uchar')'; + fseek(fid, 4, 'cof'); + end + header.header_data.FirstLatency = double(header.event_data(1).start_lat); + + %experimental: read process information + for np = 1:header.header_data.total_processes + align_file_pointer(fid) + nbytes = fread(fid, 1, 'uint32=>uint32'); + fp = ftell(fid); + header.process(np).hdr.nbytes = nbytes; + type = char(fread(fid, 20, 'uchar'))'; + header.process(np).hdr.type = type(type>0); + header.process(np).hdr.checksum = fread(fid, 1, 'int32=>int32'); + user = char(fread(fid, 32, 'uchar'))'; + header.process(np).user = user(user>0); + header.process(np).timestamp = fread(fid, 1, 'uint32=>uint32'); + fname = char(fread(fid, 32, 'uchar'))'; + header.process(np).filename = fname(fname>0); + fseek(fid, 28*8, 'cof'); %dont know + header.process(np).totalsteps = fread(fid, 1, 'uint32=>uint32'); + header.process(np).checksum = fread(fid, 1, 'int32=>int32'); + header.process(np).reserved = fread(fid, 32, 'uchar')'; + for ns = 1:header.process(np).totalsteps + align_file_pointer(fid) + nbytes2 = fread(fid, 1, 'uint32=>uint32'); + header.process(np).step(ns).hdr.nbytes = nbytes2; + type = char(fread(fid, 20, 'uchar'))'; + header.process(np).step(ns).hdr.type = type(type>0); %dont know how to interpret the first two + header.process(np).step(ns).hdr.checksum = fread(fid, 1, 'int32=>int32'); + userblocksize = fread(fid, 1, 'int32=>int32'); %we are at 32 bytes here + header.process(np).step(ns).userblocksize = userblocksize; + fseek(fid, nbytes2 - 32, 'cof'); + + if strcmp(header.process(np).step(ns).hdr.type, 'PDF_Weight_Table'), + warning('reading in weight table: no warranty that this is correct. it seems to work for the Glasgow 248-magnetometer system. if you have some code yourself, and/or would like to test it on your own data, please contact Jan-Mathijs'); + tmpfp = ftell(fid); + tmp = fread(fid, 1, 'uint8'); + Nchan = fread(fid, 1, 'uint32'); + Nref = fread(fid, 1, 'uint32'); + for k = 1:Nref + name = fread(fid, 17, 'uchar'); %strange number, but seems to be true + header.process(np).step(ns).RefChan{k,1} = char(name(name>0))'; + end + fseek(fid, 152, 'cof'); + for k = 1:Nchan + name = fread(fid, 17, 'uchar'); + header.process(np).step(ns).Chan{k,1} = char(name(name>0))'; + end + %fseek(fid, 20, 'cof'); + %fseek(fid, 4216, 'cof'); + header.process(np).step(ns).stuff1 = fread(fid, 4236, 'uint8'); + name = fread(fid, 16, 'uchar'); + header.process(np).step(ns).Creator = char(name(name>0))'; + %some stuff I don't understand yet + %fseek(fid, 136, 'cof'); + header.process(np).step(ns).stuff2 = fread(fid, 136, 'uint8'); + %now something strange is going to happen: the weights are probably little-endian encoded. + %here we go: check whether this applies to the whole PDF weight table + fp = ftell(fid); + fclose(fid); + fid = fopen(datafile, 'r', 'l'); + fseek(fid, fp, 'bof'); + for k = 1:Nchan + header.process(np).step(ns).Weights(k,:) = fread(fid, 23, 'float32=>float32')'; + fseek(fid, 36, 'cof'); + end + else + if userblocksize < 1e6, + %for one reason or another userblocksize can assume strangely high values + fseek(fid, userblocksize, 'cof'); + end + end + end + end + fclose(fid); +end +%end read header + +%read config file +fid = fopen(configfile, 'r', 'b'); + +if fid == -1 + error('Cannot open config file'); +end + +header.config_data.version = fread(fid, 1, 'uint16=>uint16'); +site_name = char(fread(fid, 32, 'uchar'))'; +header.config_data.site_name = site_name(site_name>0); +dap_hostname = char(fread(fid, 16, 'uchar'))'; +header.config_data.dap_hostname = dap_hostname(dap_hostname>0); +header.config_data.sys_type = fread(fid, 1, 'uint16=>uint16'); +header.config_data.sys_options = fread(fid, 1, 'uint32=>uint32'); +header.config_data.supply_freq = fread(fid, 1, 'uint16=>uint16'); +header.config_data.total_chans = fread(fid, 1, 'uint16=>uint16'); +header.config_data.system_fixed_gain = fread(fid, 1, 'float32=>float32'); +header.config_data.volts_per_bit = fread(fid, 1, 'float32=>float32'); +header.config_data.total_sensors = fread(fid, 1, 'uint16=>uint16'); +header.config_data.total_user_blocks = fread(fid, 1, 'uint16=>uint16'); +header.config_data.next_derived_channel_number = fread(fid, 1, 'uint16=>uint16'); +fseek(fid, 2, 'cof'); +header.config_data.checksum = fread(fid, 1, 'int32=>int32'); +header.config_data.reserved = fread(fid, 32, 'uchar=>uchar')'; + +header.config.Xfm = fread(fid, [4 4], 'double'); + +%user blocks +for ub = 1:header.config_data.total_user_blocks + align_file_pointer(fid) + header.user_block_data{ub}.hdr.nbytes = fread(fid, 1, 'uint32=>uint32'); + type = char(fread(fid, 20, 'uchar'))'; + header.user_block_data{ub}.hdr.type = type(type>0); + header.user_block_data{ub}.hdr.checksum = fread(fid, 1, 'int32=>int32'); + user = char(fread(fid, 32, 'uchar'))'; + header.user_block_data{ub}.user = user(user>0); + header.user_block_data{ub}.timestamp = fread(fid, 1, 'uint32=>uint32'); + header.user_block_data{ub}.user_space_size = fread(fid, 1, 'uint32=>uint32'); + header.user_block_data{ub}.reserved = fread(fid, 32, 'uchar=>uchar')'; + fseek(fid, 4, 'cof'); + user_space_size = double(header.user_block_data{ub}.user_space_size); + if strcmp(type(type>0), 'B_weights_used'), + %warning('reading in weight table: no warranty that this is correct. it seems to work for the Glasgow 248-magnetometer system. if you have some code yourself, and/or would like to test it on your own data, please contact Jan-Mathijs'); + tmpfp = ftell(fid); + %read user_block_data weights + %there is information in the 4th and 8th byte, these might be related to the settings? + version = fread(fid, 1, 'uint32'); + header.user_block_data{ub}.version = version; + if version==1, + Nbytes = fread(fid,1,'uint32'); + Nchan = fread(fid,1,'uint32'); + Position = fread(fid, 32, 'uchar'); + header.user_block_data{ub}.position = char(Position(Position>0))'; + fseek(fid,tmpfp+user_space_size - Nbytes*Nchan, 'bof'); + Ndigital = floor((Nbytes - 4*2) / 4); + Nanalog = 3; %lucky guess? + % how to know number of analog weights vs digital weights??? + for ch = 1:Nchan + % for Konstanz -- comment for others? + header.user_block_data{ub}.aweights(ch,:) = fread(fid, [1 Nanalog], 'int16')'; + fseek(fid,2,'cof'); % alignment + header.user_block_data{ub}.dweights(ch,:) = fread(fid, [1 Ndigital], 'single=>double')'; + end + fseek(fid, tmpfp, 'bof'); + %there is no information with respect to the channels here. + %the best guess would be to assume the order identical to the order in header.config.channel_data + %for the digital weights it would be the order of the references in that list + %for the analog weights I would not know + elseif version==2, + unknown2 = fread(fid, 1, 'uint32'); + Nchan = fread(fid, 1, 'uint32'); + Position = fread(fid, 32, 'uchar'); + header.user_block_data{ub}.position = char(Position(Position>0))'; + fseek(fid, tmpfp+124, 'bof'); + Nanalog = fread(fid, 1, 'uint32'); + Ndigital = fread(fid, 1, 'uint32'); + fseek(fid, tmpfp+204, 'bof'); + for k = 1:Nchan + Name = fread(fid, 16, 'uchar'); + header.user_block_data{ub}.channames{k,1} = char(Name(Name>0))'; + end + for k = 1:Nanalog + Name = fread(fid, 16, 'uchar'); + header.user_block_data{ub}.arefnames{k,1} = char(Name(Name>0))'; + end + for k = 1:Ndigital + Name = fread(fid, 16, 'uchar'); + header.user_block_data{ub}.drefnames{k,1} = char(Name(Name>0))'; + end + + header.user_block_data{ub}.dweights = fread(fid, [Ndigital Nchan], 'single=>double')'; + header.user_block_data{ub}.aweights = fread(fid, [Nanalog Nchan], 'int16')'; + fseek(fid, tmpfp, 'bof'); + end + elseif strcmp(type(type>0), 'B_E_table_used'), + %warning('reading in weight table: no warranty that this is correct'); + %tmpfp = ftell(fid); + %fseek(fid, 4, 'cof'); %there's info here dont know how to interpret + %Nx = fread(fid, 1, 'uint32'); + %Nchan = fread(fid, 1, 'uint32'); + %type = fread(fid, 32, 'uchar'); %don't know whether correct + %header.user_block_data{ub}.type = char(type(type>0))'; + %fseek(fid, 16, 'cof'); + %for k = 1:Nchan + % name = fread(fid, 16, 'uchar'); + % header.user_block_data{ub}.name{k,1} = char(name(name>0))'; + %end + elseif strcmp(type(type>0), 'B_COH_Points'), + tmpfp = ftell(fid); + Ncoil = fread(fid, 1, 'uint32'); + N = fread(fid, 1, 'uint32'); + coils = fread(fid, [7 Ncoil], 'double'); + + header.user_block_data{ub}.pnt = coils(1:3,:)'; + header.user_block_data{ub}.ori = coils(4:6,:)'; + header.user_block_data{ub}.Ncoil = Ncoil; + header.user_block_data{ub}.N = N; + tmp = fread(fid, (904-288)/8, 'double'); + header.user_block_data{ub}.tmp = tmp; %FIXME try to find out what these bytes mean + fseek(fid, tmpfp, 'bof'); + elseif strcmp(type(type>0), 'b_ccp_xfm_block'), + tmpfp = ftell(fid); + tmp1 = fread(fid, 1, 'uint32'); + %tmp = fread(fid, [4 4], 'double'); + %tmp = fread(fid, [4 4], 'double'); + %the next part seems to be in little endian format (at least when I tried) + tmp = fread(fid, 128, 'uint8'); + tmp = uint8(reshape(tmp, [8 16])'); + xfm = zeros(4,4); + for k = 1:size(tmp,1) + xfm(k) = typecast(tmp(k,:), 'double'); + if abs(xfm(k))<1e-10 | abs(xfm(k))>1e10, xfm(k) = typecast(fliplr(tmp(k,:)), 'double');end + end + fseek(fid, tmpfp, 'bof'); %FIXME try to find out why this looks so strange + elseif strcmp(type(type>0), 'b_eeg_elec_locs'), + %this block contains the digitized coil positions + tmpfp = ftell(fid); + Npoints = user_space_size./40; + for k = 1:Npoints + tmp = fread(fid, 16, 'uchar'); + tmplabel = char(tmp(tmp>0)'); + if strmatch('Coil', tmplabel), + label{k} = tmplabel(1:5); + elseif ismember(tmplabel(1), {'L' 'R' 'C' 'N' 'I'}), + label{k} = tmplabel(1); + else + label{k} = ''; + end + tmp = fread(fid, 3, 'double'); + pnt(k,:) = tmp(:)'; + end + header.user_block_data{ub}.label = label(:); + header.user_block_data{ub}.pnt = pnt; + fseek(fid, tmpfp, 'bof'); + end + fseek(fid, user_space_size, 'cof'); +end + +%channels +for ch = 1:header.config_data.total_chans + align_file_pointer(fid) + name = char(fread(fid, 16, 'uchar'))'; + header.config.channel_data(ch).name = name(name>0); + %FIXME this is a very dirty fix to get the reading in of continuous headlocalization + %correct. At the moment, the numbering of the hmt related channels seems to start with 1000 + %which I don't understand, but seems rather nonsensical. + chan_no = fread(fid, 1, 'uint16=>uint16'); + if chan_no > header.config_data.total_chans, + + %FIXME fix the number in header.channel_data as well + sel = find([header.channel_data.chan_no]== chan_no); + if ~isempty(sel), + chan_no = ch; + header.channel_data(sel).chan_no = chan_no; + header.channel_data(sel).chan_label = header.config.channel_data(ch).name; + else + %does not matter + end + end + header.config.channel_data(ch).chan_no = chan_no; + header.config.channel_data(ch).type = fread(fid, 1, 'uint16=>uint16'); + header.config.channel_data(ch).sensor_no = fread(fid, 1, 'int16=>int16'); + fseek(fid, 2, 'cof'); + header.config.channel_data(ch).gain = fread(fid, 1, 'float32=>float32'); + header.config.channel_data(ch).units_per_bit = fread(fid, 1, 'float32=>float32'); + yaxis_label = char(fread(fid, 16, 'uchar'))'; + header.config.channel_data(ch).yaxis_label = yaxis_label(yaxis_label>0); + header.config.channel_data(ch).aar_val = fread(fid, 1, 'double'); + header.config.channel_data(ch).checksum = fread(fid, 1, 'int32=>int32'); + header.config.channel_data(ch).reserved = fread(fid, 32, 'uchar=>uchar')'; + fseek(fid, 4, 'cof'); + + align_file_pointer(fid) + header.config.channel_data(ch).device_data.hdr.size = fread(fid, 1, 'uint32=>uint32'); + header.config.channel_data(ch).device_data.hdr.checksum = fread(fid, 1, 'int32=>int32'); + header.config.channel_data(ch).device_data.hdr.reserved = fread(fid, 32, 'uchar=>uchar')'; + + switch header.config.channel_data(ch).type + case {1, 3}%meg/ref + + header.config.channel_data(ch).device_data.inductance = fread(fid, 1, 'float32=>float32'); + fseek(fid, 4, 'cof'); + header.config.channel_data(ch).device_data.Xfm = fread(fid, [4 4], 'double'); + header.config.channel_data(ch).device_data.xform_flag = fread(fid, 1, 'uint16=>uint16'); + header.config.channel_data(ch).device_data.total_loops = fread(fid, 1, 'uint16=>uint16'); + header.config.channel_data(ch).device_data.reserved = fread(fid, 32, 'uchar=>uchar')'; + fseek(fid, 4, 'cof'); + + for loop = 1:header.config.channel_data(ch).device_data.total_loops + align_file_pointer(fid) + header.config.channel_data(ch).device_data.loop_data(loop).position = fread(fid, 3, 'double'); + header.config.channel_data(ch).device_data.loop_data(loop).direction = fread(fid, 3, 'double'); + header.config.channel_data(ch).device_data.loop_data(loop).radius = fread(fid, 1, 'double'); + header.config.channel_data(ch).device_data.loop_data(loop).wire_radius = fread(fid, 1, 'double'); + header.config.channel_data(ch).device_data.loop_data(loop).turns = fread(fid, 1, 'uint16=>uint16'); + fseek(fid, 2, 'cof'); + header.config.channel_data(ch).device_data.loop_data(loop).checksum = fread(fid, 1, 'int32=>int32'); + header.config.channel_data(ch).device_data.loop_data(loop).reserved = fread(fid, 32, 'uchar=>uchar')'; + end + case 2%eeg + header.config.channel_data(ch).device_data.impedance = fread(fid, 1, 'float32=>float32'); + fseek(fid, 4, 'cof'); + header.config.channel_data(ch).device_data.Xfm = fread(fid, [4 4], 'double'); + header.config.channel_data(ch).device_data.reserved = fread(fid, 32, 'uchar=>uchar')'; + case 4%external + header.config.channel_data(ch).device_data.user_space_size = fread(fid, 1, 'uint32=>uint32'); + header.config.channel_data(ch).device_data.reserved = fread(fid, 32, 'uchar=>uchar')'; + fseek(fid, 4, 'cof'); + case 5%TRIGGER + header.config.channel_data(ch).device_data.user_space_size = fread(fid, 1, 'uint32=>uint32'); + header.config.channel_data(ch).device_data.reserved = fread(fid, 32, 'uchar=>uchar')'; + fseek(fid, 4, 'cof'); + case 6%utility + header.config.channel_data(ch).device_data.user_space_size = fread(fid, 1, 'uint32=>uint32'); + header.config.channel_data(ch).device_data.reserved = fread(fid, 32, 'uchar=>uchar')'; + fseek(fid, 4, 'cof'); + case 7%derived + header.config.channel_data(ch).device_data.user_space_size = fread(fid, 1, 'uint32=>uint32'); + header.config.channel_data(ch).device_data.reserved = fread(fid, 32, 'uchar=>uchar')'; + fseek(fid, 4, 'cof'); + case 8%shorted + header.config.channel_data(ch).device_data.reserved = fread(fid, 32, 'uchar=>uchar')'; + otherwise + error('Unknown device type: %d\n', header.config.channel_data(ch).type); + end +end + +fclose(fid); +%end read config file + +header.header_data.FileDescriptor = 0; %no obvious field to take this from +header.header_data.Events = 1;%no obvious field to take this from +header.header_data.EventCodes = 0;%no obvious field to take this from + +if isfield(header, 'channel_data'), + header.ChannelGain = double([header.config.channel_data([header.channel_data.chan_no]).gain]'); + header.ChannelUnitsPerBit = double([header.config.channel_data([header.channel_data.chan_no]).units_per_bit]'); + header.Channel = {header.config.channel_data([header.channel_data.chan_no]).name}'; + header.Format = header.header_data.Format; +end + +function align_file_pointer(fid) +current_position = ftell(fid); +if mod(current_position, 8) ~= 0 + offset = 8 - mod(current_position,8); + fseek(fid, offset, 'cof'); +end diff --git a/external/fieldtrip/fileio/private/read_asa.m b/external/fieldtrip/fileio/private/read_asa.m new file mode 100644 index 0000000..d770f57 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_asa.m @@ -0,0 +1,165 @@ +function [val] = read_asa(filename, elem, format, number, token) + +% READ_ASA reads a specified element from an ASA file +% +% val = read_asa(filename, element, type, number) +% +% where the element is a string such as +% NumberSlices +% NumberPositions +% Rows +% Columns +% etc. +% +% and format specifies the datatype according to +% %d (integer value) +% %f (floating point value) +% %s (string) +% +% number is optional to specify how many lines of data should be read +% The default is 1 for strings and Inf for numbers. +% +% token is optional to specifiy a character that separates the values from +% anything not wanted. + +% Copyright (C) 2002, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_asa.m 945 2010-04-21 17:41:20Z roboos $ + +fid = fopen(filename, 'rt'); +if fid==-1 + error(sprintf('could not open file %s', filename)); +end + +if nargin<4 + if strcmp(format, '%s') + number = 1; + else + number = Inf; + end +end + +if nargin<5 + token = ''; +end + + +val = []; +elem = strtrim(lower(elem)); + +while (1) + line = fgetl(fid); + if ~isempty(line) && isequal(line, -1) + % prematurely reached end of file + fclose(fid); + return + end + line = strtrim(line); + lower_line = lower(line); + if strmatch(elem, lower_line) + data = line((length(elem)+1):end); + break + end +end + +while isempty(data) + line = fgetl(fid); + if isequal(line, -1) + % prematurely reached end of file + fclose(fid); + return + end + data = strtrim(line); +end + +if strcmp(format, '%s') + if number==1 + % interpret the data as a single string, create char-array + val = detoken(strtrim(data), token); + fclose(fid); + return + end + % interpret the data as a single string, create cell-array + val{1} = detoken(strtrim(data), token); + count = 1; + % read the remaining strings + while count. +% +% $Id: read_asa_bnd.m 945 2010-04-21 17:41:20Z roboos $ + +Npnt = read_asa(fn, 'NumberPositions=', '%d'); +Ndhk = read_asa(fn, 'NumberPolygons=', '%d'); +Unit = read_asa(fn, 'UnitPosition', '%s'); + +pnt = read_asa(fn, 'Positions', '%f'); +if any(size(pnt)~=[Npnt,3]) + pnt_file = read_asa(fn, 'Positions', '%s'); + [path, name, ext] = fileparts(fn); + fid = fopen(fullfile(path, pnt_file), 'rb', 'ieee-le'); + pnt = fread(fid, [3,Npnt], 'float')'; + fclose(fid); +end + +dhk = read_asa(fn, 'Polygons', '%f'); +if any(size(dhk)~=[Ndhk,3]) + dhk_file = read_asa(fn, 'Polygons', '%s'); + [path, name, ext] = fileparts(fn); + fid = fopen(fullfile(path, dhk_file), 'rb', 'ieee-le'); + dhk = fread(fid, [3,Ndhk], 'int32')'; + fclose(fid); +end + +if strcmpi(Unit,'mm') + pnt = 1*pnt; +elseif strcmpi(Unit,'cm') + pnt = 100*pnt; +elseif strcmpi(Unit,'m') + pnt = 1000*pnt; +else + error(sprintf('Unknown unit of distance for triangulated boundary (%s)', Unit)); +end + +bnd.pnt = pnt; +bnd.tri = dhk + 1; % 1-offset instead of 0-offset +% bnd.tri = fliplr(bnd.tri); % invert order of triangle vertices + diff --git a/external/fieldtrip/fileio/private/read_asa_dip.m b/external/fieldtrip/fileio/private/read_asa_dip.m new file mode 100644 index 0000000..8a2a6fc --- /dev/null +++ b/external/fieldtrip/fileio/private/read_asa_dip.m @@ -0,0 +1,123 @@ +function [pos, mom, ampl, time] = read_asa_dip(fn); + +% READ_ASA_DIP reads the dipole position, moment and amplitude +% This importer is designed for fixed-dipole models and only supports +% a limited number of the options that ASA has. +% +% Use as +% [pos, mom, ampl, time] = read_asa_dip(filename) +% +% See also READ_ASA_VOL, READ_ASA_MRI + +% Copyright (C) 2000, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_asa_dip.m 945 2010-04-21 17:41:20Z roboos $ + +Npos = 0; +Ntim = 0; +pos = []; +mom = []; +ampl = []; +time = []; +fid1 = fopen(fn, 'r'); + +while ~Npos + line = fgetl(fid1); + if strncmp('NumberPositions=', line, length('NumberPositions=')) + Npos = sscanf(line, 'NumberPositions=%d'); + end +end +frewind(fid1); + +while ~Ntim + line = fgetl(fid1); + if strncmp('NumberTimeSteps=', line, length('NumberTimeSteps=')) + Ntim = sscanf(line, 'NumberTimeSteps=%d'); + end +end +frewind(fid1); + +while isempty(time) + line = fgetl(fid1); + if strncmp('TimeSteps', line, length('TimeSteps')) + t = sscanf(line, 'TimeSteps %f(%f)%f'); + time = t(1):t(2):t(3); + end +end +frewind(fid1); + +if length(time)~=Ntim + error('incorrect timescale'); +end + +while isempty(pos) + line = fgetl(fid1); + if strncmp('Positions', line, length('Positions')) + pos = zeros(3, Npos); + pos(:) = fscanf(fid1, '%f'); + pos = pos'; + end +end +frewind(fid1); + +while isempty(mom) + line = fgetl(fid1); + if strncmp('MomentsFixed', line, length('MomentsFixed')) + mom = zeros(3, Npos); + mom(:) = fscanf(fid1, '%f'); + mom = mom'; + end +end +frewind(fid1); + +while isempty(ampl) + line = fgetl(fid1); + if strncmp('Magnitudes', line, length('Magnitudes')) + ampl = zeros(Ntim, Npos); + ampl(:) = fscanf(fid1, '%f'); + ampl = ampl'; + end +end +frewind(fid1); + +fclose(fid1); + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% old output format +% pos = [x1 y1 z1 x2 y2 z2 ... ] and +% +% mom = [Qx11 Qy11 Qz11 Qx21 Qy21 Qz21 ... +% Qx12 Qy12 Qz12 Qx22 Qy22 Qz22 ... +% ... +% Qx1t Qy1t Qz1t Qx2t Qy2t Qz2t ... ] +% +% time = [T1 T2 T3 T4 .. Tt] +% +% was obtained by re-format the data according to +% +% pos = pos'; +% pos = pos(:)'; +% +% mom1 = []; +% for j=1:Npos +% mom1 = [mom1 ampl(j,:)' * mom(j,:)]; +% end +% mom = mom1; + diff --git a/external/fieldtrip/fileio/private/read_asa_elc.m b/external/fieldtrip/fileio/private/read_asa_elc.m new file mode 100644 index 0000000..256b2e8 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_asa_elc.m @@ -0,0 +1,58 @@ +function elec = read_asa_elc(fn); + +% READ_ASA_ELC reads electrodes from an ASA electrode file +% converting the units to mm + +% Copyright (C) 2002, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_asa_elc.m 1359 2010-07-06 08:36:08Z roboos $ + +% the older *.elc files have an Nx3 matrix with positions and seperate labels +% the newer *.elc files are formatted like this +% Fp1: 94.9 30.7 14.0 +% and also include Positions2D + +Npnt = read_asa(fn, 'NumberPositions=', '%d'); +Ndhk = read_asa(fn, 'NumberPolygons=', '%d'); +Unit = read_asa(fn, 'UnitPosition', '%s', 1); +pnt = read_asa(fn, 'Positions', '%f', Npnt, ':'); +prj = read_asa(fn, 'Positions2D', '%f', Npnt, ':'); % only in newer files +dhk = read_asa(fn, 'Polygons', '%d', Ndhk); +lab = read_asa(fn, 'Labels', '%s', Npnt); + +if strcmpi(Unit,'mm') + pnt = 1*pnt; +elseif strcmpi(Unit,'cm') + pnt = 100*pnt; +elseif strcmpi(Unit,'m') + pnt = 1000*pnt; +elseif ~isempty(Unit) + error('Unknown unit of distance for electrodes (%s)', Unit); +end + +tmp = tokenize(lab{1}); +if length(tmp)==size(pnt,1) + % the electrode labels were on a single line + % reformat the electrode labels into an appropriately sized cell array + lab = tmp; +end + +elec.pnt = pnt; +elec.dhk = dhk+1; +elec.label = lab(:); diff --git a/external/fieldtrip/fileio/private/read_asa_mri.m b/external/fieldtrip/fileio/private/read_asa_mri.m new file mode 100644 index 0000000..542986e --- /dev/null +++ b/external/fieldtrip/fileio/private/read_asa_mri.m @@ -0,0 +1,201 @@ +function [mri, seg, hdr] = read_asa_mri(fn); + +% READ_ASA_MRI reads an ASA format MRI file +% +% Use as +% [mri, seg, hdr] = read_asa_mri(filename) +% +% The raw image data is returned, together with the position of the +% external head markers in raw image coordinates. +% +% In the ASA default PAN (pre-auricular/nasion) coordinate system +% PointOnPositiveYAxis -> LPA +% PointOnNegativeYAxis -> RPA +% PointOnPositiveXAxis -> nasion + +% Copyright (C) 2002, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_asa_mri.m 945 2010-04-21 17:41:20Z roboos $ + +hdr.Nrows = read_asa(fn, 'NumberRows=', '%d'); +hdr.Ncolumns = read_asa(fn, 'NumberColumns=', '%d'); +hdr.Nslices = read_asa(fn, 'NumberSlices=', '%d'); +hdr.rows = read_asa(fn, 'Rows=', '%s'); +hdr.columns = read_asa(fn, 'Columns=', '%s'); +hdr.slices = read_asa(fn, 'Slices=', '%s'); +hdr.distance = read_asa(fn, 'Distance=', '%f', 3); +hdr.mrifile = read_asa(fn, 'Matrix', '%s'); +hdr.segfile = read_asa(fn, 'Segmentation', '%s'); +hdr.posy = read_asa(fn, 'PointOnPositiveYAxis', '%f', 3); +hdr.negy = read_asa(fn, 'PointOnNegativeYAxis', '%f', 3); +hdr.posx = read_asa(fn, 'PointOnPositiveXAxis', '%f', 3); +hdr.voxposy = read_asa(fn, 'VoxelOnPositiveYAxis', '%f', 3); +hdr.voxnegy = read_asa(fn, 'VoxelOnNegativeYAxis', '%f', 3); +hdr.voxposx = read_asa(fn, 'VoxelOnPositiveXAxis', '%f', 3); +hdr.segfile = read_asa(fn, 'Segmentation', '%s', 1); + +dim = [hdr.Ncolumns hdr.Nrows hdr.Nslices]; +mri = []; +seg = []; + +% the data files are at the same location as the mri file, locate path +[path, name, ext] = fileparts(fn); + +% this temporary needs 8x as much storage!!! +if ~isempty(hdr.mrifile) + mrifile = fullfile(path, hdr.mrifile); + mri = zeros(dim); + fid = fopen(mrifile, 'rb', 'ieee-le'); + mri(:) = fread(fid, prod(dim), 'uint8'); + mri = uint8(mri); + fclose(fid); +end + +% this temporary needs 8x as much storage!!! +if ~isempty(hdr.segfile) + segfile = fullfile(path, hdr.segfile); + seg = zeros(dim); + fid = fopen(segfile, 'rb', 'ieee-le'); + seg(:) = fread(fid, prod(dim), 'uint8'); + seg = uint8(seg); + fclose(fid); +end + +% flip the orientation of the MRI data, the result should be +% 'coronal(occipital-frontal)' +% 'horizontal(inferior-superior)' +% 'sagittal(right-left)' + +if strcmp(hdr.columns, 'coronal(frontal-occipital)') + hdr.columns = 'coronal(occipital-frontal)'; + mri = flipdim(mri, 1); + seg = flipdim(seg, 1); +elseif strcmp(hdr.columns, 'horizontal(superior-inferior)') + hdr.columns = 'horizontal(inferior-superior)'; + mri = flipdim(mri, 1); + seg = flipdim(seg, 1); +elseif strcmp(hdr.columns, 'sagittal(left-right)') + hdr.columns = 'sagittal(right-left)'; + mri = flipdim(mri, 1); + seg = flipdim(seg, 1); +end + +if strcmp(hdr.rows, 'coronal(frontal-occipital)') + hdr.rows = 'coronal(occipital-frontal)'; + mri = flipdim(mri, 2); + seg = flipdim(seg, 2); +elseif strcmp(hdr.rows, 'horizontal(superior-inferior)') + hdr.rows = 'horizontal(inferior-superior)'; + mri = flipdim(mri, 2); + seg = flipdim(seg, 2); +elseif strcmp(hdr.rows, 'sagittal(left-right)') + hdr.rows = 'sagittal(right-left)'; + mri = flipdim(mri, 2); + seg = flipdim(seg, 2); +end + +if strcmp(hdr.slices, 'coronal(frontal-occipital)') + hdr.slices = 'coronal(occipital-frontal)'; + mri = flipdim(mri, 3); + seg = flipdim(seg, 3); +elseif strcmp(hdr.slices, 'horizontal(superior-inferior)') + hdr.slices = 'horizontal(inferior-superior)'; + mri = flipdim(mri, 3); + seg = flipdim(seg, 3); +elseif strcmp(hdr.slices, 'sagittal(left-right)') + hdr.slices = 'sagittal(right-left)'; + mri = flipdim(mri, 3); + seg = flipdim(seg, 3); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% swap the orientations of the MRI data, the result should be fixed +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% 1st dimension corresponds to columns, which should be 'coronal(occipital-frontal)' +% 2st dimension corresponds to rows, which should be 'sagittal(right-left)' +% 3rd dimension corresponds to slices, which should be 'horizontal(inferior-superior)' + +if strcmp(hdr.columns, 'coronal(occipital-frontal)') + orientation(1) = 1; +elseif strcmp(hdr.columns, 'sagittal(right-left)') + orientation(1) = 2; +elseif strcmp(hdr.columns, 'horizontal(inferior-superior)') + orientation(1) = 3; +end + +if strcmp(hdr.rows, 'coronal(occipital-frontal)') + orientation(2) = 1; +elseif strcmp(hdr.rows, 'sagittal(right-left)') + orientation(2) = 2; +elseif strcmp(hdr.rows, 'horizontal(inferior-superior)') + orientation(2) = 3; +end + +if strcmp(hdr.slices, 'coronal(occipital-frontal)') + orientation(3) = 1; +elseif strcmp(hdr.slices, 'sagittal(right-left)') + orientation(3) = 2; +elseif strcmp(hdr.slices, 'horizontal(inferior-superior)') + orientation(3) = 3; +end + +mri = ipermute(mri, orientation); +seg = ipermute(seg, orientation); +hdr.rows = 'sagittal(right-left)'; +hdr.columns = 'coronal(occipital-frontal)'; +hdr.slices = 'horizontal(inferior-superior)'; + +% recompute the dimensions after all the swapping +hdr.Nrows = size(mri, 1); +hdr.Ncolumns = size(mri, 2); +hdr.Nslices = size(mri, 3); +dim = size(mri); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% if possible, create the accompanying homogenous coordinate transformation matrix +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +if exist('headcoordinates', 'file') + % In case of PointOn..., ASA counts voxels from the center of the MRI + % and in case of VoxelOn..., ASA counts voxels from the corner of the MRI + % In both cases, ASA starts counting at [0 0 0], which is C convention + % whereas I want to count from the 1st voxel and number that with [1 1 1] + if ~isempty(hdr.posx) & ~isempty(hdr.negy) & ~isempty(hdr.posy) + offset = (dim + [1 1 1])/2; + hdr.fiducial.mri.nas = hdr.posx + offset; + hdr.fiducial.mri.lpa = hdr.posy + offset; + hdr.fiducial.mri.rpa = hdr.negy + offset; + else + offset = [1 1 1]; + hdr.fiducial.mri.nas = hdr.voxposx + offset; + hdr.fiducial.mri.lpa = hdr.voxposy + offset; + hdr.fiducial.mri.rpa = hdr.voxnegy + offset; + end + + % use the headcoordinates function (roboos/misc) to compute the transformaton matrix + hdr.transformMRI2Head = headcoordinates(hdr.fiducial.mri.nas, hdr.fiducial.mri.lpa, hdr.fiducial.mri.rpa, 1); + hdr.transformHead2MRI = inv(hdr.transformMRI2Head); + + % compute the fiducials in head coordinates + hdr.fiducial.head.nas = warp_apply(hdr.transformMRI2Head, hdr.fiducial.mri.nas, 'homogenous'); + hdr.fiducial.head.lpa = warp_apply(hdr.transformMRI2Head, hdr.fiducial.mri.lpa, 'homogenous'); + hdr.fiducial.head.rpa = warp_apply(hdr.transformMRI2Head, hdr.fiducial.mri.rpa, 'homogenous'); +end + diff --git a/external/fieldtrip/fileio/private/read_asa_msr.m b/external/fieldtrip/fileio/private/read_asa_msr.m new file mode 100644 index 0000000..b3662c4 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_asa_msr.m @@ -0,0 +1,77 @@ +function data = read_asa_msr(fn); + +% READ_ASA_MSR reads EEG or MEG data from an ASA data file +% converting the units to uV or fT + +% Copyright (C) 2002, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_asa_msr.m 945 2010-04-21 17:41:20Z roboos $ + +Npnt = read_asa(fn, 'NumberPositions=', '%d'); +Ntime = read_asa(fn, 'NumberTimesteps=', '%d'); +UnitT = read_asa(fn, 'UnitTime', '%s'); +UnitM = read_asa(fn, 'UnitMeas', '%s'); +Timesteps = read_asa(fn, 'Timesteps', '%s'); +lab = read_asa(fn, 'Labels', '%s', Npnt); + +val = read_asa(fn, 'Values', '%f'); +if any(size(val)~=[Npnt,Ntime]) + msm_file = read_asa(fn, 'Values', '%s'); + [path, name, ext] = fileparts(fn); + fid = fopen(fullfile(path, msm_file), 'rb', 'ieee-le'); + val = fread(fid, [Ntime, Npnt], 'float32')'; + fclose(fid); +end + +tmp = sscanf(Timesteps, '%f(%f)%f'); +time = linspace(tmp(1), tmp(3), Ntime); + +if strcmpi(UnitT,'ms') + time = 1*time; +elseif strcmpi(UnitT,'s') + time = 1000*time; +elseif ~isempty(UnitT) + error(sprintf('Unknown unit of time (%s)', UnitT)); +end + +if strcmpi(UnitM,'uv') + val = 1*val; +elseif strcmpi(UnitM,'?v') + val = 1*val; +elseif strcmpi(UnitM,'mv') + val = 1000*val; +elseif strcmpi(UnitM,'v') + val = 1000000*val; +elseif strcmpi(UnitM,'ft') + val = 1*val; +elseif strcmpi(UnitM,'pt') + val = 1000*val; +elseif ~isempty(UnitM) + error(sprintf('Unknown unit of measurement (%s)', UnitM)); +end + +if length(size(lab))==2 + lab = tokenize(lab{1}); +end + +data.time = time; +data.data = val; +data.label = lab; + + diff --git a/external/fieldtrip/fileio/private/read_asa_vol.m b/external/fieldtrip/fileio/private/read_asa_vol.m new file mode 100644 index 0000000..c6482aa --- /dev/null +++ b/external/fieldtrip/fileio/private/read_asa_vol.m @@ -0,0 +1,119 @@ +function vol = read_asa_vol(fn); + +% READ_ASA_VOL reads an ASA volume conductor file +% +% all data is converted to the following units +% vertices mm +% conductivities S/m + +% Copyright (C) 2002, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_asa_vol.m 945 2010-04-21 17:41:20Z roboos $ + +Nbnd = read_asa(fn, 'NumberBoundaries=', '%d'); +UnitC = read_asa(fn, 'UnitConduct', '%s'); +UnitP = read_asa(fn, 'UnitPosition', '%s'); +cond = read_asa(fn, 'Conductivities', '%f'); +radii = read_asa(fn, 'Radii', '%f'); +pos = read_asa(fn, 'Positions', '%f'); +bnd1 = read_asa(fn, 'Boundary1', '%s'); +bnd2 = read_asa(fn, 'Boundary2', '%s'); +bnd3 = read_asa(fn, 'Boundary3', '%s'); +bnd4 = read_asa(fn, 'Boundary4', '%s'); + +if ~isempty(radii) | ~isempty(pos) + % this appears to be a spherical volume conductor + if strcmpi(UnitP,'mm') + radii = 1*radii; + pos = 1*pos; + elseif strcmpi(UnitP,'cm') + radii = 100*radii; + pos = 100*pos; + elseif strcmpi(UnitP,'m') + radii = 1000*radii; + pos = 1000*pos; + else + error(sprintf('Unknown unit of distance for volume (%s)', UnitP)); + end +end + +if strcmpi(UnitC,'s/m') + cond = cond/1; +elseif strcmpi(UnitC,'s/cm') + cond = cond/100; +elseif strcmpi(UnitC,'s/mm') + cond = cond/1000; +else + error(sprintf('Unknown unit of conductivity for volume (%s)', UnitC)); +end + +if ~isempty(radii) + % this appears to be a spherical volume conductor + vol.radius = radii; + vol.cond = cond; + vol.center = pos; +else + % this appears to be a realistical volume conductor + [path, name, ext] = fileparts(fn); + if Nbnd>=1 + vol.bnd(1) = read_asa_bnd(fullfile(path, bnd1)); + end + if Nbnd>=2 + vol.bnd(2) = read_asa_bnd(fullfile(path, bnd2)); + end + if Nbnd>=3 + vol.bnd(3) = read_asa_bnd(fullfile(path, bnd3)); + end + if Nbnd>=4 + vol.bnd(4) = read_asa_bnd(fullfile(path, bnd4)); + end + if Nbnd>=5 + error('cannot read more than 4 boundaries'); + end + + % if there is a precomputed matrix, read it from an external file + mat_file = read_asa(fn, 'Matrix', '%s'); + if ~isempty(mat_file) + nr = read_asa(fullfile(path, mat_file), 'NumberRows=', '%d'); + nc = read_asa(fullfile(path, mat_file), 'NumberColumns=', '%d'); + mab_file = read_asa(fullfile(path, mat_file), 'Matrix', '%s'); + fid = fopen(fullfile(path, mab_file), 'rb', 'ieee-le'); + if fid==-1 + error(sprintf('could not open file %s', mab_file)); + else + vol.mat = fread(fid, [nr nc], 'float32'); + fclose(fid); + % remove the factor 2 that ASA assumes in the system matrix + vol.mat = vol.mat/2; + % scale the system matrix corresponding to vertex coordinates in mm + vol.mat = vol.mat*100; + end + end + + vol.cond = cond; +end + +% remove all empty fields +field=fieldnames(vol); +for i=1:length(field) + if isempty(getfield(vol, field{i})) + vol = rmfield(vol, field{i}); + end +end + diff --git a/external/fileio/private/read_besa_avr.m b/external/fieldtrip/fileio/private/read_besa_avr.m similarity index 76% rename from external/fileio/private/read_besa_avr.m rename to external/fieldtrip/fileio/private/read_besa_avr.m index 73a6f8f..b1c2432 100644 --- a/external/fileio/private/read_besa_avr.m +++ b/external/fieldtrip/fileio/private/read_besa_avr.m @@ -18,28 +18,23 @@ % Copyright (C) 2003-2006, Robert Oostenveld % -% $Log: read_besa_avr.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.4 2008/03/25 10:57:34 roboos -% get channel names from ela file if present +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.3 2006/10/05 08:53:22 roboos -% added support for another header extension (for Vladimir) +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.2 2005/04/25 11:10:27 roboos -% changed output labels into cell-array -% added support for reading channel labels from accompanying elp file -% -% Revision 1.1 2005/03/31 07:09:37 roboos -% old implementation, but new implementation of support for avr files that contain channel names +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: read_besa_avr.m 945 2010-04-21 17:41:20Z roboos $ fid = fopen(filename, 'rt'); diff --git a/external/fieldtrip/fileio/private/read_besa_mul.m b/external/fieldtrip/fileio/private/read_besa_mul.m new file mode 100644 index 0000000..a2c922d --- /dev/null +++ b/external/fieldtrip/fileio/private/read_besa_mul.m @@ -0,0 +1,104 @@ +function [dat] = read_besa_mul(filename) + +% READ_BESA_MUL reads data from a BESA multiplexed (*.mul) file +% +% Use as +% dat = read_besa_mul(filename); + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_besa_mul.m 945 2010-04-21 17:41:20Z roboos $ + +dat = []; +fid = fopen(filename, 'rt'); + +% According to the BESA documentation, the ASCII Multiplexed Format is as +% follows: +% +% The first of two header lines contains similar information to that of the +% BESA ASCII file: +% +% TimePoints= 200 Channels= 27 BeginSweep[ms]= -500.00 +% SamplingInterval[ms]= 5.000 Bins/uV= 1.000 SegmentName=Condition1 +% +% Note that the item 'SegmentName' is missing if no segment comment is +% specified when writing a segment to file. +% +% If an epoch of a continuous EEG is exported in ASCII multiplexed format, +% the first header line contains the additional item 'Time', which +% indicates the daytime of the first sample in the exported segment: +% +% TimePoints= 200 Channels= 27 BeginSweep[ms]= 0.00 SamplingInterval[ms]= +% 5.000 Bins/uV= 1.000 Time=22:02:53 SegmentName=Segment1 + +hdr1 = fgetl(fid); +% split the first header line into separate elements +%!!! 2009/09/25 +%tmp = tokenize(hdr1, ' '); +tmp = tokenize(hdr1, ' ',1); +for i=1:length(tmp) + % extract the information from each element + dum = tokenize(tmp{i}, '='); + var = dum{1}; % this is the name of the header variable + val = dum{2}; % this is the value of the header variable + var(var=='/') = '_'; % replace characters that are not valid in a structure element name + var(var=='[') = '_'; % replace characters that are not valid in a structure element name + var(var==']') = '_'; % replace characters that are not valid in a structure element name + var(var=='.') = '_'; % replace characters that are not valid in a structure element name + num = str2num(val); + if ~isempty(num) + dat = setfield(dat, var, num); + else + dat = setfield(dat, var, val); + end +end + +% The second line of the header contains labels for each channel, which may +% be either the original channel names, or the names of the channels of the +% current montage, e.g. +% +% O1 Oz P3 T5 T3 C3 F7 F3 Fp1 Fz Cz Pz Fp2 F4 F8 C4 T4 T6 P4 Fpz O2 M2 M1 +% F10 F9 T10 T9 +% +% Each subsequent line contains values for all 'Channels' at one time +% point, in floating point or scientific format. Values are given for the +% current or the original montage, selected as described above. +% +% Labels for source montages have the following form: 'TAr-L'. +% +% The first two letters indicate the head region: +% +% The small letter indicates in part the orientation: r=radial, +% t=tangential, and in part the relative location of the basal temporal +% source: l=lateral, m=mesial. +% +% The final letter after the hyphen indicates L=left, M=middle, R=right. + +hdr2 = fgetl(fid); +% split the second header line into channel/source labels +%!!! 2009/09/25 +%dat.label = tokenize(hdr2, ' '); +dat.label = tokenize(hdr2, ' ',1); + +% read the actual data +dat.data = fscanf(fid, '%g'); +dat.data = reshape(dat.data, [dat.Channels dat.TimePoints]); + +fclose(fid); +return diff --git a/external/fileio/private/read_besa_pdg.m b/external/fieldtrip/fileio/private/read_besa_pdg.m similarity index 78% rename from external/fileio/private/read_besa_pdg.m rename to external/fieldtrip/fileio/private/read_besa_pdg.m index df25dd5..82f9446 100644 --- a/external/fileio/private/read_besa_pdg.m +++ b/external/fieldtrip/fileio/private/read_besa_pdg.m @@ -11,17 +11,23 @@ % Copyright (C) 2005, Vladimir Litvak 6/4/05 % -% $Log: read_besa_pdg.m,v $ -% Revision 1.2 2005/07/28 14:08:06 roboos -% converted from partially dos/unix into pure unix (i.e. removed CRs) +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.1 2005/07/28 13:59:09 roboos -% renamed read_pdg.m into read_besa_pdg.m +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.2 2005/07/28 13:58:10 roboos -% added copyrights, added log -% updated to latest version from Vladimir (1/7/05) +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_besa_pdg.m 945 2010-04-21 17:41:20Z roboos $ data_type=1; % needs to be 1 for EEG, 2 for MEG diff --git a/external/fieldtrip/fileio/private/read_besa_src.m b/external/fieldtrip/fileio/private/read_besa_src.m new file mode 100644 index 0000000..b13e7e7 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_besa_src.m @@ -0,0 +1,71 @@ +function [src] = read_besa_src(filename); + +% READ_BESA_SRC reads a beamformer source reconstruction from a BESA file +% +% Use as +% [src] = read_besa_src(filename) +% +% The output structure contains a minimal representation of the contents +% of the file. + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_besa_src.m 945 2010-04-21 17:41:20Z roboos $ + +src = []; +fid = fopen(filename, 'rt'); + +% read the header information +line = fgetl(fid); +while isempty(strmatch('BESA_SA_IMAGE', line)), line = fgetl(fid); check_feof(fid, filename); end +% while isempty(strmatch('sd' , line)), line = fgetl(fid); check_feof(fid, filename); end % this line contains condition information +while isempty(strmatch('Grid dimen' , line)), line = fgetl(fid); check_feof(fid, filename); end +while isempty(strmatch('X:' , line)), line = fgetl(fid); check_feof(fid, filename); end; linex = line; +while isempty(strmatch('Y:' , line)), line = fgetl(fid); check_feof(fid, filename); end; liney = line; +while isempty(strmatch('Z:' , line)), line = fgetl(fid); check_feof(fid, filename); end; linez = line; + +tok = tokenize(linex, ' '); +src.X = [str2num(tok{2}) str2num(tok{3}) str2num(tok{4})]; +tok = tokenize(liney, ' '); +src.Y = [str2num(tok{2}) str2num(tok{3}) str2num(tok{4})]; +tok = tokenize(linez, ' '); +src.Z = [str2num(tok{2}) str2num(tok{3}) str2num(tok{4})]; + +nx = src.X(3); +ny = src.Y(3); +nz = src.Z(3); + +src.vol = zeros(nx, ny, nz); + +for i=1:nz + % search up to the next slice + while isempty(strmatch(sprintf('Z: %d', i-1), line)), line = fgetl(fid); check_feof(fid, filename); end; + % read all the values for this slice + buf = fscanf(fid, '%f', [nx ny]); + src.vol(:,:,i) = buf; +end + +fclose(fid); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function check_feof(fid, filename) +if feof(fid) + error(sprintf('could not read all information from file ''%s''', filename)); +end + diff --git a/external/fieldtrip/fileio/private/read_besa_swf.m b/external/fieldtrip/fileio/private/read_besa_swf.m new file mode 100644 index 0000000..a38e930 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_besa_swf.m @@ -0,0 +1,89 @@ +function [swf] = read_besa_swf(filename); + +% READ_BESA_SWF +% +% Use as +% [swf] = read_besa_swf(filename) +% +% This will return a structure with the header information in +% swf.label cell array with labels +% swf.data data matrix, Nchan X Npnts +% swf.npnt +% swf.tsb +% swf.di +% swf.sb + +% Copyright (C) 2006, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_besa_swf.m 945 2010-04-21 17:41:20Z roboos $ + +fid = fopen(filename); +line = fgetl(fid); +head = sscanf(line,'Npts= %f TSB= %f DI= %f SB= %f'); % new BESA versions include more information in the .swf file header; skip that +Npts = head(1); +TSB = head(2); +DI = head(3); +SB = head(4); + +offset = ftell(fid); + +% try reading a label and a number +dum = textscan(fid, '%s %f', 1); +fseek(fid, offset, 'bof'); + +if isempty(dum{2}) + % first line contains all labels, each subsequent line is one timepoint for all channels + line = fgetl(fid); + line(line==' ') = []; + label = tokenize(line, ':')'; + if isempty(label{end}) + label = label(1:(end-1)); % the last one is empty + end + Nsrc = length(label); + dat = fscanf(fid, '%f', inf); + dat = reshape(dat, Nsrc, Npts); +else + % each line starts with a single label, followed by all timepoints for that channel + dat = []; + label = {}; + count = 0; + while ~feof(fid) + count = count+1; + % read one line at a time + line = fgetl(fid); + sel = find(line==':', 1); + label{count} = deblank(line(1:(sel-1))); + buf = sscanf(line((sel+1):end), '%f'); + dat(count,:) = buf(:); + end +end + +fclose(fid); + +% assign the output, should be similar as READ_BESA_AVR +swf.npnt = Npts; +swf.tsb = TSB; +swf.di = DI; +swf.sb = SB; +swf.label = label; +swf.data = dat; + +% FIXME, here combine the channels of the regional sources + + diff --git a/external/fileio/private/read_besa_tfc.m b/external/fieldtrip/fileio/private/read_besa_tfc.m similarity index 80% rename from external/fileio/private/read_besa_tfc.m rename to external/fieldtrip/fileio/private/read_besa_tfc.m index 6949420..96f71f0 100644 --- a/external/fileio/private/read_besa_tfc.m +++ b/external/fieldtrip/fileio/private/read_besa_tfc.m @@ -21,17 +21,23 @@ % Copyright (C) 2005, Vladimir Litvak % -% $Log: read_besa_tfc.m,v $ -% Revision 1.3 2006/04/05 15:36:13 roboos -% documented bug that was reported for matlab72, not yet fixed +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.2 2005/07/29 13:26:49 roboos -% removed printing of the channel number (too noisy on screen) +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.1 2005/07/28 14:09:22 roboos -% implementation done by Vladimir Litvak -% renamed from ReadBESATFC into read_besa_tfc +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_besa_tfc.m 945 2010-04-21 17:41:20Z roboos $ fp = fopen(FILENAME); diff --git a/external/fieldtrip/fileio/private/read_bham.m b/external/fieldtrip/fileio/private/read_bham.m new file mode 100644 index 0000000..c5539dc --- /dev/null +++ b/external/fieldtrip/fileio/private/read_bham.m @@ -0,0 +1,43 @@ +function [dat, lab] = read_bham(filename) + +% READ_BHAM reads the EEG data files as recorded by Praamstra in Birmingham +% the datafiles are in a particular ascii format +% +% [dat, lab] = read_bham(filename) + +% Copyright (C) 2000, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_bham.m 945 2010-04-21 17:41:20Z roboos $ + +fid = fopen(filename, 'rt'); + +lablen = 6; +line = fgetl(fid); +numelc = 0; +while ~isempty(line) + numelc = numelc + 1; + [t, r] = strtok(line); + lab(numelc,:) = [blanks(lablen-length(t)), t]; + line = r; +end + +buf = fscanf(fid, '%f'); +dat = zeros(numelc, length(buf)/numelc); +dat(:) = buf; + diff --git a/external/fieldtrip/fileio/private/read_biff.m b/external/fieldtrip/fileio/private/read_biff.m new file mode 100644 index 0000000..efb957b --- /dev/null +++ b/external/fieldtrip/fileio/private/read_biff.m @@ -0,0 +1,164 @@ +function [this] = read_biff(filename, opt) + +% READ_BIFF reads data and header information from a BIFF file +% +% This is a attemt for a reference implementation to read the BIFF +% file format as defined by the Clinical Neurophysiology department of +% the University Medical Centre, Nijmegen. +% +% read all data and information +% [data] = read_biff(filename) +% or read a selected top-level chunk +% [chunk] = read_biff(filename, chunkID) +% +% known top-level chunk id's are +% data : measured data (matrix) +% dati : information on data (struct) +% expi : information on experiment (struct) +% pati : information on patient (struct) +% evnt : event markers (struct) + +% Copyright (C) 2000, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_biff.m 945 2010-04-21 17:41:20Z roboos $ + +define_biff; +this = []; + +fid = fopen(filename, 'r'); +fseek(fid,0,'eof'); +eof = ftell(fid); +fseek(fid,0,'bof'); + +[id, siz] = chunk_header(fid); + +switch id + case 'SEMG' + child = subtree(BIFF, id); + this = read_biff_chunk(fid, id, siz, child); + + case 'LIST' + fprintf('skipping unimplemented chunk id="%s" size=%4d\n', id, siz); + + case 'CAT ' + fprintf('skipping unimplemented chunk id="%s" size=%4d\n', id, siz); + + otherwise + fprintf('skipping unrecognized chunk id="%s" size=%4d\n', id, siz); + fseek(fid, siz, 'cof'); + +end % switch +fclose(fid); % close file + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION read_biff_chunk +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function this = read_biff_chunk(fid, id, siz, chunk); + +% start with empty structure +this = []; + +if strcmp(id, 'null') % this is an empty chunk + fprintf('skipping empty chunk id="%s" size=%4d\n', id, siz); + assert(~feof(fid)); + fseek(fid, siz, 'cof'); + +elseif isempty(chunk) % this is an unrecognized chunk + fprintf('skipping unrecognized chunk id="%s" size=%4d\n', id, siz); + assert(~feof(fid)); + fseek(fid, siz, 'cof'); + +else + eoc = ftell(fid) + siz; + name = char(chunk.desc(2)); + type = char(chunk.desc(3)); + + fprintf('reading chunk id= "%s" size=%4d name="%s"\n', id, siz, name); + + switch type + case 'group' + + while ~feof(fid) & ftell(fid). +% +% $Id: read_biosemi_bdf.m 945 2010-04-21 17:41:20Z roboos $ + +if nargin==1 + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % read the header, this code is from EEGLAB's openbdf + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + FILENAME = filename; + + % defines Seperator for Subdirectories + SLASH='/'; + BSLASH=char(92); + + cname=computer; + if cname(1:2)=='PC' SLASH=BSLASH; end; + + fid=fopen(FILENAME,'r','ieee-le'); + if fid<0 + fprintf(2,['Error LOADEDF: File ' FILENAME ' not found\n']); + return; + end; + + EDF.FILE.FID=fid; + EDF.FILE.OPEN = 1; + EDF.FileName = FILENAME; + + PPos=min([max(find(FILENAME=='.')) length(FILENAME)+1]); + SPos=max([0 find((FILENAME=='/') | (FILENAME==BSLASH))]); + EDF.FILE.Ext = FILENAME(PPos+1:length(FILENAME)); + EDF.FILE.Name = FILENAME(SPos+1:PPos-1); + if SPos==0 + EDF.FILE.Path = pwd; + else + EDF.FILE.Path = FILENAME(1:SPos-1); + end; + EDF.FileName = [EDF.FILE.Path SLASH EDF.FILE.Name '.' EDF.FILE.Ext]; + + H1=char(fread(EDF.FILE.FID,256,'char')'); % + EDF.VERSION=H1(1:8); % 8 Byte Versionsnummer + %if 0 fprintf(2,'LOADEDF: WARNING Version EDF Format %i',ver); end; + EDF.PID = deblank(H1(9:88)); % 80 Byte local patient identification + EDF.RID = deblank(H1(89:168)); % 80 Byte local recording identification + %EDF.H.StartDate = H1(169:176); % 8 Byte + %EDF.H.StartTime = H1(177:184); % 8 Byte + EDF.T0=[str2num(H1(168+[7 8])) str2num(H1(168+[4 5])) str2num(H1(168+[1 2])) str2num(H1(168+[9 10])) str2num(H1(168+[12 13])) str2num(H1(168+[15 16])) ]; + + % Y2K compatibility until year 2090 + if EDF.VERSION(1)=='0' + if EDF.T0(1) < 91 + EDF.T0(1)=2000+EDF.T0(1); + else + EDF.T0(1)=1900+EDF.T0(1); + end; + else ; + % in a future version, this is hopefully not needed + end; + + EDF.HeadLen = str2num(H1(185:192)); % 8 Byte Length of Header + % reserved = H1(193:236); % 44 Byte + EDF.NRec = str2num(H1(237:244)); % 8 Byte # of data records + EDF.Dur = str2num(H1(245:252)); % 8 Byte # duration of data record in sec + EDF.NS = str2num(H1(253:256)); % 8 Byte # of signals + + EDF.Label = char(fread(EDF.FILE.FID,[16,EDF.NS],'char')'); + EDF.Transducer = char(fread(EDF.FILE.FID,[80,EDF.NS],'char')'); + EDF.PhysDim = char(fread(EDF.FILE.FID,[8,EDF.NS],'char')'); + + EDF.PhysMin= str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); + EDF.PhysMax= str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); + EDF.DigMin = str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); + EDF.DigMax = str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); + + % check validity of DigMin and DigMax + if (length(EDF.DigMin) ~= EDF.NS) + fprintf(2,'Warning OPENEDF: Failing Digital Minimum\n'); + EDF.DigMin = -(2^15)*ones(EDF.NS,1); + end + if (length(EDF.DigMax) ~= EDF.NS) + fprintf(2,'Warning OPENEDF: Failing Digital Maximum\n'); + EDF.DigMax = (2^15-1)*ones(EDF.NS,1); + end + if (any(EDF.DigMin >= EDF.DigMax)) + fprintf(2,'Warning OPENEDF: Digital Minimum larger than Maximum\n'); + end + % check validity of PhysMin and PhysMax + if (length(EDF.PhysMin) ~= EDF.NS) + fprintf(2,'Warning OPENEDF: Failing Physical Minimum\n'); + EDF.PhysMin = EDF.DigMin; + end + if (length(EDF.PhysMax) ~= EDF.NS) + fprintf(2,'Warning OPENEDF: Failing Physical Maximum\n'); + EDF.PhysMax = EDF.DigMax; + end + if (any(EDF.PhysMin >= EDF.PhysMax)) + fprintf(2,'Warning OPENEDF: Physical Minimum larger than Maximum\n'); + EDF.PhysMin = EDF.DigMin; + EDF.PhysMax = EDF.DigMax; + end + EDF.PreFilt= char(fread(EDF.FILE.FID,[80,EDF.NS],'char')'); % + tmp = fread(EDF.FILE.FID,[8,EDF.NS],'char')'; % samples per data record + EDF.SPR = str2num(char(tmp)); % samples per data record + + fseek(EDF.FILE.FID,32*EDF.NS,0); + + EDF.Cal = (EDF.PhysMax-EDF.PhysMin)./(EDF.DigMax-EDF.DigMin); + EDF.Off = EDF.PhysMin - EDF.Cal .* EDF.DigMin; + tmp = find(EDF.Cal < 0); + EDF.Cal(tmp) = ones(size(tmp)); + EDF.Off(tmp) = zeros(size(tmp)); + + EDF.Calib=[EDF.Off';(diag(EDF.Cal))]; + %EDF.Calib=sparse(diag([1; EDF.Cal])); + %EDF.Calib(1,2:EDF.NS+1)=EDF.Off'; + + EDF.SampleRate = EDF.SPR / EDF.Dur; + + EDF.FILE.POS = ftell(EDF.FILE.FID); + if EDF.NRec == -1 % unknown record size, determine correct NRec + fseek(EDF.FILE.FID, 0, 'eof'); + endpos = ftell(EDF.FILE.FID); + EDF.NRec = floor((endpos - EDF.FILE.POS) / (sum(EDF.SPR) * 2)); + fseek(EDF.FILE.FID, EDF.FILE.POS, 'bof'); + H1(237:244)=sprintf('%-8i',EDF.NRec); % write number of records + end; + + EDF.Chan_Select=(EDF.SPR==max(EDF.SPR)); + for k=1:EDF.NS + if EDF.Chan_Select(k) + EDF.ChanTyp(k)='N'; + else + EDF.ChanTyp(k)=' '; + end; + if findstr(upper(EDF.Label(k,:)),'ECG') + EDF.ChanTyp(k)='C'; + elseif findstr(upper(EDF.Label(k,:)),'EKG') + EDF.ChanTyp(k)='C'; + elseif findstr(upper(EDF.Label(k,:)),'EEG') + EDF.ChanTyp(k)='E'; + elseif findstr(upper(EDF.Label(k,:)),'EOG') + EDF.ChanTyp(k)='O'; + elseif findstr(upper(EDF.Label(k,:)),'EMG') + EDF.ChanTyp(k)='M'; + end; + end; + + EDF.AS.spb = sum(EDF.SPR); % Samples per Block + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % convert the header to Fieldtrip-style + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + if any(EDF.SampleRate~=EDF.SampleRate(1)) + error('channels with different sampling rate not supported'); + end + hdr.Fs = EDF.SampleRate(1); + hdr.nChans = EDF.NS; + hdr.label = cellstr(EDF.Label); + % it is continuous data, therefore append all records in one trial + hdr.nTrials = 1; + hdr.nSamples = EDF.NRec * EDF.Dur * EDF.SampleRate(1); + hdr.nSamplesPre = 0; + hdr.orig = EDF; + + % return the header + dat = hdr; + +else + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % read the data + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % retrieve the original header + EDF = hdr.orig; + + % determine the trial containing the begin and end sample + epochlength = EDF.Dur * EDF.SampleRate(1); + begepoch = floor((begsample-1)/epochlength) + 1; + endepoch = floor((endsample-1)/epochlength) + 1; + nepochs = endepoch - begepoch + 1; + nchans = EDF.NS; + + if nargin<5 + chanindx = 1:nchans; + end + + % allocate memory to hold the data + dat = zeros(length(chanindx),nepochs*epochlength); + + % read and concatenate all required data epochs + for i=begepoch:endepoch + offset = EDF.HeadLen + (i-1)*epochlength*nchans*3; + if length(chanindx)==1 + % this is more efficient if only one channel has to be read, e.g. the status channel + offset = offset + (chanindx-1)*epochlength*3; + buf = readLowLevel(filename, offset, epochlength); % see below in subfunction + dat(:,((i-begepoch)*epochlength+1):((i-begepoch+1)*epochlength)) = buf; + else + % read the data from all channels and then select the desired channels + buf = readLowLevel(filename, offset, epochlength*nchans); % see below in subfunction + buf = reshape(buf, epochlength, nchans); + dat(:,((i-begepoch)*epochlength+1):((i-begepoch+1)*epochlength)) = buf(:,chanindx)'; + end + end + + % select the desired samples + begsample = begsample - (begepoch-1)*epochlength; % correct for the number of bytes that were skipped + endsample = endsample - (begepoch-1)*epochlength; % correct for the number of bytes that were skipped + dat = dat(:, begsample:endsample); + + % Calibrate the data + if length(chanindx)>1 + % using a sparse matrix speeds up the multiplication + calib = sparse(diag(EDF.Cal(chanindx,:))); + dat = calib * dat; + else + % in case of one channel the calibration would result in a sparse array + calib = diag(EDF.Cal(chanindx,:)); + dat = calib * dat; + end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION for reading the 24 bit values +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function buf = readLowLevel(filename, offset, numwords); +if offset < 2*1024^3 + % use the external mex file, only works for <2GB + buf = read_24bit(filename, offset, numwords); + % this would be the only difference between the bdf and edf implementation + % buf = read_16bit(filename, offset, numwords); +else + % use plain matlab, thanks to Philip van der Broek + fp = fopen(filename,'r','ieee-le'); + status = fseek(fp, offset, 'bof'); + if status + error(['failed seeking ' filename]); + end + [buf,num] = fread(fp,numwords,'bit24=>double'); + fclose(fp); + if (num. +% +% $Id: read_biosig_data.m 945 2010-04-21 17:41:20Z roboos $ + +% open the file, read the header +% it should be the same as hdr.orig +biosig = sopen(filename,'r'); + +begtime = (begsample-1) / hdr.Fs; +endtime = (endsample ) / hdr.Fs; +duration = endtime-begtime; + +% read the selected data and close the file +dat = sread(biosig, duration, begtime); +dat = dat'; +sclose(biosig); + +if nargin>4 + % select the channels of interest + dat = dat(chanindx,:); +end diff --git a/external/fieldtrip/fileio/private/read_biosig_header.m b/external/fieldtrip/fileio/private/read_biosig_header.m new file mode 100644 index 0000000..f413dbc --- /dev/null +++ b/external/fieldtrip/fileio/private/read_biosig_header.m @@ -0,0 +1,117 @@ +function [hdr] = read_biosig_header(filename) + +% READ_BIOSIG_HEADER reads header from EEG file using the BIOSIG +% toolbox and returns it in the FCDC framework standard format +% +% Use as +% [hdr] = read_biosig_header(filename) +% +% The following data formats are supported: EDF, BKR, CNT, BDF, GDF, +% see for full documentation http://biosig.sourceforge.net/ +% +% See also READ_BIOSIG_DATA + +% Copyright (C) 2004, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_biosig_header.m 945 2010-04-21 17:41:20Z roboos $ + +% open the file, read the header and close it again +biosig = sopen(filename,'r'); +sclose(biosig); + +% the BIOSIG header is defined in full detail below +% the FCDC header should at least contain the following fields +% hdr.Fs sampling frequency +% hdr.nChans number of channels +% hdr.nSamples number of samples per trial +% hdr.nSamplesPre number of pre-trigger samples in each trial +% hdr.nTrials number of trials +% hdr.label cell-array with labels of each channel + +if length(biosig.SampleRate)>1 & any(diff(biosig.SampleRate)) + error('channels with different sampling rates are not supported'); +else + hdr.Fs = biosig.SampleRate(1); +end + +if length(biosig.SPR)>1 & any(diff(biosig.SPR)) + error('channels with different number of samples are not supported'); +else + hdr.nSamples = biosig.SPR(1); +end + +hdr.nChans = biosig.NS; +hdr.nTrials = biosig.NRec; +hdr.nSamplesPre = 0; % this one is not in the biosig header +hdr.label = {}; % start with empty labels and fill them below + +if isfield(biosig, 'Label') + hdr.label = biosig.Label; +end + +if length(hdr.label)~=hdr.nChans + % make default channel labels + hdr.label = {}; + for i=1:hdr.nChans + hdr.label{i} = sprintf('%d', i); + end +end + +% I prefer to have them as column vector +hdr.label = hdr.label(:); + +% also remember the biosig header details +hdr.orig = biosig; +return; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% the BIOSIG header always contains these elements +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% HDR.TYPE string type of data format +% HDR.VERSION string (depends on data format) +% HDR.T0 float[1..6] [yyyy mm dd hh MM ss.cc] see HELP CLOCK +% HDR.NS integer number of channels +% HDR.SampleRate integer sampling frequency in [Hz] +% HDR.NRec integer number of records or blocks; 1 for continous data +% HDR.SPR integer samples per record +% HDR.Dur float Duration (in [s]) of minimal block length +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% the BIOSIG header optinally contains the following elements +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% HDR.Filter.LowPass float [Hz] +% HDR.Filter.HighPass float [Hz] +% HDR.Filter.Notch int8 0=Off, 1=ON +% HDR.PreFilt string filter setting +% HDR.Label char-array z.B. '+C3a - C3p ' +% HDR.PhysDim string physical dimension e.g. 'uV' +% HDR.PhysMax float physical maximum +% HDR.DigMax integer digital maximum +% HDR.PhysMin float physical minimum +% HDR.DigMin integer digital minimum +% HDR.FLAG.TRIGGERED int 0=no, 1=yes +% HDR.FLAG.REFERENCE string COM, CAR: common average reference; LOC,LAR local average ref; LAP Laplacian derivation, WGT weighted average +% HDR.Classlabel int 0: left, 1: right, etc. +% HDR.ID.Doctor Identification of doctor +% HDR.ID.Hospital Identification of Hospital +% HDR.Patient.Name Name of Patient +% HDR.Patient.Age Age of Patient +% HDR.Patient.Sex Patient Gender +% HDR.Patient.Handedness Patient Handedness +% HDR.Patient.Medication Medication +% HDR.Patient.Classification Classification of Patient diff --git a/external/fieldtrip/fileio/private/read_brainvision_eeg.m b/external/fieldtrip/fileio/private/read_brainvision_eeg.m new file mode 100644 index 0000000..0a17355 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_brainvision_eeg.m @@ -0,0 +1,116 @@ +function [dat] = read_brainvision_eeg(filename, hdr, begsample, endsample); + +% READ_BRAINVISION_EEG reads raw data from an EEG file +% and returns it as a Nchans x Nsamples matrix +% +% Use as +% dat = read_brainvision_eeg(filename, hdr, begsample, endsample) +% where the header should be first read using read_brainvision_vhdr +% +% See also READ_BRAINVISION_VHDR, READ_BRAINVISION_VMRK + +% Copyright (C) 2003, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_brainvision_eeg.m 945 2010-04-21 17:41:20Z roboos $ + +if strcmpi(hdr.DataFormat, 'binary') && strcmpi(hdr.DataOrientation, 'multiplexed') && strcmpi(hdr.BinaryFormat, 'int_16') + fid = fopen(filename, 'rb', 'ieee-le'); + fseek(fid, hdr.NumberOfChannels*2*(begsample-1), 'cof'); + [dat, siz] = fread(fid, [hdr.NumberOfChannels, (endsample-begsample+1)], 'int16'); + fclose(fid); + % compute real microvolts using the calibration factor (resolution) + res = sparse(diag(hdr.resolution)); + dat = res * dat; + +elseif strcmpi(hdr.DataFormat, 'binary') && strcmpi(hdr.DataOrientation, 'multiplexed') && strcmpi(hdr.BinaryFormat, 'int_32') + fid = fopen(filename, 'rb', 'ieee-le'); + fseek(fid, hdr.NumberOfChannels*4*(begsample-1), 'cof'); + [dat, siz] = fread(fid, [hdr.NumberOfChannels, (endsample-begsample+1)], 'int32'); + fclose(fid); + % compute real microvolts using the calibration factor (resolution) + res = sparse(diag(hdr.resolution)); + dat = res * dat; + +elseif strcmpi(hdr.DataFormat, 'binary') && strcmpi(hdr.DataOrientation, 'multiplexed') && strcmpi(hdr.BinaryFormat, 'ieee_float_32') + fid = fopen(filename, 'rb', 'ieee-le'); + fseek(fid, hdr.NumberOfChannels*4*(begsample-1), 'cof'); + [dat, siz] = fread(fid, [hdr.NumberOfChannels, (endsample-begsample+1)], 'float32'); + fclose(fid); + +elseif strcmpi(hdr.DataFormat, 'binary') && strcmpi(hdr.DataOrientation, 'vectorized') && strcmpi(hdr.BinaryFormat, 'ieee_float_32') + fid = fopen(filename, 'rb', 'ieee-le'); + fseek(fid, 0, 'eof'); + hdr.nSamples = ftell(fid)/(4*hdr.NumberOfChannels); + fseek(fid, 0, 'bof'); + numsamples = (endsample-begsample+1); + for chan=1:hdr.NumberOfChannels + fseek(fid, (begsample-1)*4, 'cof'); % skip the first N samples + [tmp, siz] = fread(fid, numsamples, 'float32'); % read these samples + fseek(fid, (hdr.nSamples-endsample)*4, 'cof'); % skip the last M samples + dat(chan,:) = tmp(:)'; + end + fclose(fid); + +elseif strcmpi(hdr.DataFormat, 'ascii') && strcmpi(hdr.DataOrientation, 'multiplexed') + fid = fopen(filename, 'rt'); + for line=1:(begsample-1) + % read first lines and discard the data in them + str = fgets(fid); + end + dat = zeros(endsample-begsample+1, hdr.NumberOfChannels); + for line=1:(endsample-begsample+1) + str = fgets(fid); % read a single line with Nchan samples + str(find(str==',')) = '.'; % replace comma with point + dat(line,:) = str2num(str); + end + fclose(fid); + % transpose the data + dat = dat'; + +elseif strcmpi(hdr.DataFormat, 'ascii') && strcmpi(hdr.DataOrientation, 'vectorized') + % this is a very inefficient fileformat to read data from, since it requires to + % read in all the samples of each channel and then select only the samples of interest + fid = fopen(filename, 'rt'); + dat = zeros(hdr.NumberOfChannels, endsample-begsample+1); + for chan=1:hdr.NumberOfChannels + % this is very slow, so better give some feedback to indicate that something is happening + fprintf('reading channel %d from ascii file to get data from sample %d to %d\n', chan, begsample, endsample); + + str = fgets(fid); % read all samples of a single channel + str(find(str==',')) = '.'; % replace comma with point + + if ~isempty(regexp(str(1:10), '[a-zA-Z]', 'once')) + % the line starts with letters, not numbers: probably it is a channel label + % find the first number and remove the preceding part + sel = regexp(str(1:10), ' [-0-9]'); % find the first number, or actually the last space before the first number + label = str(1:(sel)); % this includes the space + str = str((sel+1):end); % keep only the numbers + end + + % convert the string into numbers and copy the desired samples over + % into the data matrix + tmp = str2num(str); + dat(chan,:) = tmp(begsample:endsample); + end + fclose(fid); + +else + error('unsupported sub-fileformat'); +end + diff --git a/external/fieldtrip/fileio/private/read_brainvision_marker.m b/external/fieldtrip/fileio/private/read_brainvision_marker.m new file mode 100644 index 0000000..0aca199 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_brainvision_marker.m @@ -0,0 +1,51 @@ +function [rej] = read_brainvision_marker(fn); + +% READ_BRAINVISION_MARKER reads rejection marks from a BrainVision file +% +% Use as +% [rej] = read_brainvision_marker(filename) +% +% This function returns a Nx2 matrix with the begin and end latency +% of N rejection marks. The latency is in miliseconds. + +% Copyright (C) 2004, Robert Oostenveld & Doug Davidson +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_brainvision_marker.m 945 2010-04-21 17:41:20Z roboos $ + +rej = []; + +[x y] = textread(fn, '%s%s', 1, 'delimiter', ',:' ); + +p = mat2str(cell2mat(y)); +pos = findstr('Hz', p); + +samplingrate = str2num(p(1:pos-1)); + +s = 1./samplingrate; + +[col1 col2] = textread(fn, '%*s%*s%n%n%*[^\n]',... + 'delimiter', ',',... + 'headerlines', 2 ); + +% Start and end points in msec +startp = (col1*s)*1000; +endp = ((col2*s)+(col1*s))*1000; + +rej = [startp endp]; +clear x p pos samplingrate; diff --git a/external/fieldtrip/fileio/private/read_brainvision_pos.m b/external/fieldtrip/fileio/private/read_brainvision_pos.m new file mode 100644 index 0000000..1399cce --- /dev/null +++ b/external/fieldtrip/fileio/private/read_brainvision_pos.m @@ -0,0 +1,67 @@ +function [elec] = read_brainvision_pos(filename); + +% READ_BRAINVISION_POS reads electrode positions measured with the Polhemus +% tracker in one of the F.C. Donders EEG labs. The polhemus software is actually +% not from Brainvision. +% +% Use as: +% [elec] = read_brainvision_pos(filename) +% +% This returns an electrode structure with +% elec.label cell-array with electrode labels (strings) +% elec.pnt position of each electrode + +% Copyright (C) 2004, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_brainvision_pos.m 945 2010-04-21 17:41:20Z roboos $ + +fid = fopen(filename, 'rt'); +line = fgetl(fid); +Nchan = str2double(line); + +for i=1:Nchan + line = fgetl(fid); + [t, r] = strtok(line); + elec.label{i} = char(t); + elec.pnt(i,:) = sscanf(r, '%f')'; +end +elec.label = elec.label(:); + +try + % read the fiducials + line = fgetl(fid); + [t, r] = strtok(line); + fiducial.label{1} = char(t); + fiducial.pnt(1,:) = sscanf(r, '%f')'; + line = fgetl(fid); + [t, r] = strtok(line); + fiducial.label{2} = char(t); + fiducial.pnt(2,:) = sscanf(r, '%f')'; + line = fgetl(fid); + [t, r] = strtok(line); + fiducial.label{3} = char(t); + fiducial.pnt(3,:) = sscanf(r, '%f')'; + % add the fiducials to the electrode array + elec.label = cat(1, elec.label(:), fiducial.label(:)); + elec.pnt = cat(1, elec.pnt, fiducial.pnt); +catch + % do nothing +end + +fclose(fid); diff --git a/external/fieldtrip/fileio/private/read_brainvision_vhdr.m b/external/fieldtrip/fileio/private/read_brainvision_vhdr.m new file mode 100644 index 0000000..d1227a4 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_brainvision_vhdr.m @@ -0,0 +1,105 @@ +function [hdr] = read_brainvision_vhdr(filename); + +% READ_BRAINVISION_VHDR reads the known items from the BrainVision EEG +% header file and returns them in a structure +% +% Use as +% hdr = read_brainvision_vhdr(filename) +% +% See also READ_BRAINVISION_EEG, READ_BRAINVISION_VMRK + +% Copyright (C) 2003, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_brainvision_vhdr.m 945 2010-04-21 17:41:20Z roboos $ + +hdr.DataFile = read_asa(filename, 'DataFile=', '%s'); +hdr.MarkerFile = read_asa(filename, 'MarkerFile=', '%s'); +hdr.DataFormat = read_asa(filename, 'DataFormat=', '%s'); +hdr.DataOrientation = read_asa(filename, 'DataOrientation=', '%s'); +hdr.BinaryFormat = read_asa(filename, 'BinaryFormat=', '%s'); +hdr.NumberOfChannels = read_asa(filename, 'NumberOfChannels=', '%d'); +hdr.SamplingInterval = read_asa(filename, 'SamplingInterval=', '%f'); % microseconds + +if ~isempty(hdr.NumberOfChannels) + for i=1:hdr.NumberOfChannels + chan_str = sprintf('Ch%d=', i); + chan_info = read_asa(filename, chan_str, '%s'); + t = tokenize(chan_info, ','); + hdr.label{i} = t{1}; + hdr.reference{i} = t{2}; + resolution = str2num(t{3}); % in microvolt + if ~isempty(resolution) + hdr.resolution(i) = resolution; + else + hdr.resolution(i) = nan; + end + end +end + +% compute the sampling rate in Hz +hdr.Fs = 1e6/(hdr.SamplingInterval); + +% the number of samples is unkown to start with +hdr.nSamples = Inf; + +% determine the number of samples by looking at the binary file +if strcmpi(hdr.DataFormat, 'binary') + % the data file is supposed to be located in the same directory as the header file + % but that might be on another location than the present working directory + [p, f, x] = fileparts(filename); + datafile = fullfile(p, hdr.DataFile); + info = dir(datafile); + if isempty(info) + error('cannot determine the location of the data file %s', hdr.DataFile); + end + switch lower(hdr.BinaryFormat) + case 'int_16'; + hdr.nSamples = info.bytes./(hdr.NumberOfChannels*2); + case 'int_32'; + hdr.nSamples = info.bytes./(hdr.NumberOfChannels*4); + case 'ieee_float_32'; + hdr.nSamples = info.bytes./(hdr.NumberOfChannels*4); + end +elseif strcmpi(hdr.DataFormat, 'ascii') && strcmpi(hdr.DataOrientation, 'vectorized') + % this is a very inefficient fileformat to read data from, it looks like this: + % Fp1 -2.129 -2.404 -18.646 -15.319 -4.081 -14.702 -23.590 -8.650 -3.957 + % AF3 -24.023 -23.265 -30.677 -17.053 -24.889 -35.008 -21.444 -15.896 -12.050 + % F7 -10.553 -10.288 -19.467 -15.278 -21.123 -25.066 -14.363 -10.774 -15.396 + % F3 -28.696 -26.314 -35.005 -27.244 -31.401 -39.445 -30.411 -20.194 -16.488 + % FC1 -35.627 -29.906 -38.013 -33.426 -40.532 -49.079 -38.047 -26.693 -22.852 + % ... + fid = fopen(hdr.DataFile, 'rt'); + tline = fgetl(fid); % read the complete first line + fclose(fid); + t = tokenize(tline, ' ', true); % cut the line into pieces + hdr.nSamples = length(t) - 1; % the first element is the channel label +end + +if isinf(hdr.nSamples) + warning('cannot determine number of samples for this sub-fileformat'); +end + +% the number of trials is unkown, assume continuous data +hdr.nTrials = 1; +hdr.nSamplesPre = 0; + +% ensure that the labels are in a column +hdr.label = hdr.label(:); +hdr.reference = hdr.reference(:); +hdr.resolution = hdr.resolution(:); diff --git a/external/fieldtrip/fileio/private/read_brainvision_vmrk.m b/external/fieldtrip/fileio/private/read_brainvision_vmrk.m new file mode 100644 index 0000000..a0dfb6a --- /dev/null +++ b/external/fieldtrip/fileio/private/read_brainvision_vmrk.m @@ -0,0 +1,86 @@ +function [stimulus, response, segment, timezero] = read_brainvision_vmrk(filename); + +% READ_BRAINVISION_VMRK reads the markers and latencies +% it returns the stimulus/response code and latency in ms. +% +% Use as +% [stim, resp, segment, timezero] = read_brainvision_vmrk(filename) +% +% This function needs to read the header from a separate file and +% assumes that it is located at the same location. +% +% See also READ_BRAINVISION_VHDR, READ_BRAINVISION_EEG + +% original M. Schulte 31.07.2003 +% modifications R. Oostenveld 14.08.2003 +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_brainvision_vmrk.m 945 2010-04-21 17:41:20Z roboos $ + +stimulus=[]; +response=[]; +segment=[]; +timezero=[]; + +% read the header belonging to this marker file +hdr=read_brainvision_vhdr([filename(1:(end-4)) 'vhdr']); + +fid=fopen(filename,'rt'); +if fid==-1, + error('cannot open marker file') +end + +line=1; +while line~=-1, + line=fgetl(fid); + % pause + if ~isempty(line), + if ~isempty(findstr(line,'Mk')), + if ~isempty(findstr(line,'Stimulus')) + [token,rem] = strtok(line,','); + type=sscanf(rem,',S %i'); + [token,rem] = strtok(rem,','); + time=(sscanf(rem,', %i')-1)/hdr.Fs*1000; + stimulus=[stimulus; type time(1)]; + + elseif ~isempty(findstr(line,'Response')) + [token,rem] = strtok(line,','); + type=sscanf(rem,',R %i'); + [token,rem] = strtok(rem,','); + time=(sscanf(rem,', %i')-1)/hdr.Fs*1000; + response=[response; type, time(1)]; + + elseif ~isempty(findstr(line,'New Segment')) + [token,rem] = strtok(line,','); + time=(sscanf(rem,',,%i')-1)/hdr.Fs*1000; + segment=[segment; time(1)]; + + elseif ~isempty(findstr(line,'Time 0')) + [token,rem] = strtok(line,','); + time=(sscanf(rem,',,%i')-1)/hdr.Fs*1000; + timezero=[timezero; time(1)]; + + end + end + else + line=1; + end +end + +fclose(fid); + diff --git a/external/fieldtrip/fileio/private/read_bti_ascii.m b/external/fieldtrip/fileio/private/read_bti_ascii.m new file mode 100644 index 0000000..4caff74 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_bti_ascii.m @@ -0,0 +1,76 @@ +function [file] = read_bti_ascii(filename); + +% READ_BTI_ASCII reads general data from a BTI configuration file +% +% The file should be formatted like +% Group: +% item1 : value1a value1b value1c +% item2 : value2a value2b value2c +% item3 : value3a value3b value3c +% item4 : value4a value4b value4c +% + +% Copyright (C) 2004, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_bti_ascii.m 945 2010-04-21 17:41:20Z roboos $ + +fid = fopen(filename, 'r'); +if fid==-1 + error(sprintf('could not open file %s', filename)); +end + +line = ''; +while ischar(line) + line = cleanline(fgetl(fid)) + + if isempty(line) | line==-1 | isempty(findstr(line, ':')) + continue + end + + % the line is not empty, which means that we have encountered a chunck of information + if findstr(line, ':')~=length(line) + [item, value] = strtok(line, ':'); + value(1) = ' '; % remove the : + value = strtrim(value); + item = strtrim(item); + item(findstr(item, '.')) = '_'; + item(findstr(item, ' ')) = '_'; + if ischar(item) + eval(sprintf('file.%s = ''%s'';', item, value)); + else + eval(sprintf('file.%s = %s;', item, value)); + end + else + subline = cleanline(fgetl(fid)); + error, the rest has not been implemented (yet) + + end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function line = cleanline(line) +if isempty(line) | line==-1 + return +end +comment = findstr(line, '//'); +if ~isempty(comment) + line(min(comment):end) = ' '; +end +line = strtrim(line); + diff --git a/external/fieldtrip/fileio/private/read_bti_hs.m b/external/fieldtrip/fileio/private/read_bti_hs.m new file mode 100644 index 0000000..93432d0 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_bti_hs.m @@ -0,0 +1,56 @@ +function [output, firstIndexPoint] = read_hs_file( filename, outfile) + +%read_hs_file Reads in BTI-Headshape files +% filename: file with the headshape informations +% outfile: if present, a ctf ".shape" file is written +% output: if present, a 3xN matrix containing the headshape-points +% +% (C) 2007 by Thomas Hartmann + +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_bti_hs.m 945 2010-04-21 17:41:20Z roboos $ + +if nargin == 1 + outfile = []; +end %if + +fid = fopen(filename, 'r', 'b'); +version = fread(fid, 1, '*uint32'); +timestamp = fread(fid, 1, '*int32'); +checksum = fread(fid, 1, '*int32'); +nPoints = fread(fid, 1, '*int32'); + +firstIndexPoint = fread(fid, [3, 5], 'double')'; + +points = fread(fid, [3, double(nPoints)], 'double'); + +fclose(fid); + +if(nargout > 0) + output = points'; +end %if + +if(nargin == 2) + fid = fopen(outfile, 'wt'); + fprintf(fid, '%d\n', nPoints); + for i = 1:size(points, 2) + fprintf(fid, '%.3f\t%.3f\t%.3f\n', points(1, i), points(2, i), points(3, i)); + end %for + fclose(fid); + +end %if diff --git a/external/fieldtrip/fileio/private/read_bti_m4d.m b/external/fieldtrip/fileio/private/read_bti_m4d.m new file mode 100644 index 0000000..a96a081 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_bti_m4d.m @@ -0,0 +1,173 @@ +function [msi] = read_bti_m4d(filename); + +% READ_BTI_M4D +% +% Use as +% msi = read_bti_m4d(filename) + +% Copyright (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_bti_m4d.m 945 2010-04-21 17:41:20Z roboos $ + +[p, f, x] = fileparts(filename); +if ~strcmp(x, '.m4d') + % add the extension of the header + filename = [filename '.m4d']; +end + +fid = fopen(filename, 'r'); +if fid==-1 + error(sprintf('could not open file %s', filename)); +end + +% start with an empty header structure +msi = struct; + +% these header elements contain strings and should be converted in a cell-array +strlist = { + 'MSI.ChannelOrder' + }; + +% these header elements contain numbers and should be converted in a numeric array +% 'MSI.ChannelScale' +% 'MSI.ChannelGain' +% 'MSI.FileType' +% 'MSI.TotalChannels' +% 'MSI.TotalEpochs' +% 'MSI.SamplePeriod' +% 'MSI.SampleFrequency' +% 'MSI.FirstLatency' +% 'MSI.SlicesPerEpoch' +% the conversion to numeric arrays is implemented in a general fashion +% and all the fields above are automatically converted +numlist = {}; + +line = ''; + +msi.grad.label = {}; +msi.grad.pnt = zeros(0,3); +msi.grad.ori = zeros(0,3); +while ischar(line) + line = cleanline(fgetl(fid)); + if isempty(line) || (length(line)==1 && all(line==-1)) + continue + end + + sep = strfind(line, ':'); + if length(sep)==1 + key = line(1:(sep-1)); + val = line((sep+1):end); + elseif length(sep)>1 + % assume that the first separator is the relevant one, and that the + % next ones are part of the value string (e.g. a channel with a ':' in + % its name + sep = sep(1); + key = line(1:(sep-1)); + val = line((sep+1):end); + elseif length(sep)<1 + % this is not what I would expect + error('unexpected content in m4d file'); + end + + if ~isempty(strfind(line, 'Begin')) + sep = strfind(key, '.'); + sep = sep(end); + key = key(1:(sep-1)); + + % if the key ends with begin and there is no value, then there is a block + % of numbers following that relates to the magnetometer/gradiometer information. + % All lines in that Begin-End block should be treated seperately + val = {}; + lab = {}; + num = {}; + ind = 0; + while isempty(strfind(line, 'End')) + line = cleanline(fgetl(fid)); + if isempty(line) || (length(line)==1 && all(line==-1)) || ~isempty(strfind(line, 'End')) + continue + end + ind = ind+1; + % remember the line itself, and also cut it into pieces + val{ind} = line; + % the line is tab-separated and looks like this + % A68 0.0873437 -0.075789 0.0891512 0.471135 -0.815532 0.336098 + sep = find(line==9); % the ascii value of a tab is 9 + sep = sep(1); + lab{ind} = line(1:(sep-1)); + num{ind} = str2num(line((sep+1):end)); + + end % parsing Begin-End block + val = val(:); + lab = lab(:); + num = num(:); + num = cell2mat(num); + % the following is FieldTrip specific + if size(num,2)==6 + msi.grad.label = [msi.grad.label; lab(:)]; + % the numbers represent position and orientation of each magnetometer coil + msi.grad.pnt = [msi.grad.pnt; num(:,1:3)]; + msi.grad.ori = [msi.grad.ori; num(:,4:6)]; + else + error('unknown gradiometer design') + end + end + + % the key looks like 'MSI.fieldname.subfieldname' + fieldname = key(5:end); + + % remove spaces from the begin and end of the string + val = strtrim(val); + + % try to convert the value string into something more usefull + if ~iscell(val) + % the value can contain a variety of elements, only some of which are decoded here + if ~isempty(strfind(key, 'Index')) || ~isempty(strfind(key, 'Count')) || any(strcmp(key, numlist)) + % this contains a single number or a comma-separated list of numbers + val = str2num(val); + elseif ~isempty(strfind(key, 'Names')) || any(strcmp(key, strlist)) + % this contains a comma-separated list of strings + val = tokenize(val, ','); + else + tmp = str2num(val); + if ~isempty(tmp) + val = tmp; + end + end + end + + % assign this header element to the structure + msi = setsubfield(msi, fieldname, val); + +end % while ischar(line) + +fclose(fid); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION to remove spaces from the begin and end +% and to remove comments from the lines +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function line = cleanline(line) +if isempty(line) || (length(line)==1 && all(line==-1)) + return +end +comment = findstr(line, '//'); +if ~isempty(comment) + line(min(comment):end) = ' '; +end +line = strtrim(line); diff --git a/external/fieldtrip/fileio/private/read_bv_srf.m b/external/fieldtrip/fileio/private/read_bv_srf.m new file mode 100644 index 0000000..7dd4495 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_bv_srf.m @@ -0,0 +1,107 @@ +function [pnt, tri, srf] = read_bv_srf(filename); + +% READ_BV_SRF reads a triangulated surface from a BrainVoyager *.srf file +% +% Use as +% [pnt, tri] = read_bv_srf(filename) or +% [pnt, tri, srf] = read_bv_srf(filename) + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_bv_srf.m 945 2010-04-21 17:41:20Z roboos $ + +% This documentation originates from +% http://www.brainvoyager.com/BV2000OnlineHelp/BrainVoyagerWebHelp/mergedProjects/FileFormats/BrainVoyager_File_Formats.htm +% +% BYTES DATA TYPE DEFAULT DESCRIPTION +% 4 float 3 version number +% 4 int 0 reserved, must be '0' +% 4 int NrOfVertices (number of vertices) +% 4 int NrOfTriangles (number of triangles) +% 4 float 128.0 MeshCenterX +% 4 float 128.0 MeshCenterY +% 4 float 128.0 MeshCenterZ +% NrOfVertices*4 float VertexX, sequence of X coordinates of all vertices +% NrOfVertices*4 float VertexY, sequence of Y coordinates of all vertices +% NrOfVertices*4 float VertexZ, sequence of Z coordinates of all vertices +% NrOfVertices*4 float NormalX, sequence of X components of all vertex normals +% NrOfVertices*4 float NormalY, sequence of Y components of all vertex normals +% NrOfVertices*4 float NormalZ, sequence of Z components of all vertex normals +% 4 float 0.322 R component of convex curvature color (range: 0.0 - 1-0) +% 4 float 0.733 G component of convex curvature color (range: 0.0 - 1-0) +% 4 float 0.980 B component of convex curvature color (range: 0.0 - 1-0) +% 4 float 0.500 Alpha component of convex curvature color (range: 0.0 - 1-0) +% 4 float 0.100 R component of concave curvature color (range: 0.0 - 1-0) +% 4 float 0.240 G component of concave curvature color (range: 0.0 - 1-0) +% 4 float 0.320 B component of concave curvature color (range: 0.0 - 1-0) +% 4 float 0.500 Alpha component of concave curvature color (range: 0.0 - 1-0) +% NrOfVertices*4 int MeshColor, sequence of color indices of all vertices (*1) +% 4 int N, number of nearest neighbors of vertex 1 +% 4 int Nearest neighbor 1 of vertex 1 +% : : : +% 4 int Nearest neighbor N of vertex 1 +% :: :: :: +% 4 int N, number of nearest neighbors of vertex 'NrOfVertices' +% 4 int Nearest neighbor 1 of vertex 'NrOfVertices' +% : : : +% 4 int Nearest neighbor N of vertex 'NrOfVertices' +% NrOfTriangels*3*4 int Sequence of three indices to constituting vertices of each triangle +% 4 int NrOfTriangleStripElements +% NrOfStripElements*4 int Sequence of strip elements (if NrOfStripElements > 0) + + +fid = fopen(filename, 'rb', 'ieee-le'); + +srf.version_number = fread(fid, 1, 'float'); +srf.reserved = fread(fid, 1, 'int' ); +srf.NrOfVertices = fread(fid, 1, 'int' ); +srf.NrOfTriangles = fread(fid, 1, 'int' ); +NrOfVertices = srf.NrOfVertices; +NrOfTriangles = srf.NrOfTriangles; +srf.MeshCenterX = fread(fid, 1, 'float'); +srf.MeshCenterY = fread(fid, 1, 'float'); +srf.MeshCenterZ = fread(fid, 1, 'float'); +srf.X_coordinates = fread(fid, NrOfVertices, 'float'); +srf.Y_coordinates = fread(fid, NrOfVertices, 'float'); +srf.Z_coordinates = fread(fid, NrOfVertices, 'float'); +srf.X_components = fread(fid, NrOfVertices, 'float'); +srf.Y_components = fread(fid, NrOfVertices, 'float'); +srf.Z_components = fread(fid, NrOfVertices, 'float'); +srf.R_component_of_convex_curvature_color = fread(fid, 1, 'float'); +srf.G_component_of_convex_curvature_color = fread(fid, 1, 'float'); +srf.B_component_of_convex_curvature_color = fread(fid, 1, 'float'); +srf.Alpha_component_of_convex_curvature_color = fread(fid, 1, 'float'); +srf.R_component_of_concave_curvature_color = fread(fid, 1, 'float'); +srf.G_component_of_concave_curvature_color = fread(fid, 1, 'float'); +srf.B_component_of_concave_curvature_color = fread(fid, 1, 'float'); +srf.Alpha_component_of_concave_curvature_color = fread(fid, 1, 'float'); +srf.MeshColor = fread(fid, NrOfVertices, 'int' ); +for i=1:NrOfVertices + number = fread(fid, 1, 'int' ); + srf.neighbour{i} = fread(fid, number, 'int' ); +end +srf.Triangles = fread(fid, [3 NrOfTriangles], 'int' ); +srf.NrOfTriangleStripElements = fread(fid, 1, 'int' ); +srf.sequence_of_strip_elements = fread(fid, srf.NrOfTriangleStripElements, 'int' ); + +fclose(fid); + +pnt = [srf.X_coordinates(:) srf.Y_coordinates(:) srf.Z_coordinates(:)]; +tri = srf.Triangles' + 1; + diff --git a/external/fieldtrip/fileio/private/read_ced_son.m b/external/fieldtrip/fileio/private/read_ced_son.m new file mode 100644 index 0000000..cbd5b85 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_ced_son.m @@ -0,0 +1,296 @@ +function [out] = read_ced_son(datafile,varargin); + +% READ_CED_SON +% +% [OUT] = read_ced_son(DATAFILE,VARARGIN); +% +% Reads a analog and event data from a CED SON file +% (SON files are created by Spike2 software). Currently, only +% analog channels and event data can be read. +% +% Optional parameter Default +% 'readevents' 'no' +% 'readdata' 'no' +% 'readtimestamps' 'no' +% 'begsample' -1 +% 'endsample' -1 +% 'channels' [] +% +% Please note that CED DAQ systems do a sequential ADC, thus +% channels do not share the same time axis: The timestamps of the +% analog channels differ on a subsample level. Use the 'readtimestamps' +% input parameter to get a matrix with time axes corresponding +% to the data channels. +% +% Use begsample and endsample parameters to specify the boundaries +% of the requested data chunk. Setting these parameters to -1 will +% return data from the start or until the end of the datafile, +% respectively. +% +% Specifying [1,2] for 'channels' will load the 1st and the 2nd +% analog channel, __regardless of the actual channel number__ +% If, for example channel 1,2,3 are event channels, 4 as an analog +% channel, 5 is an event channel, and 6 is and analog channel, +% specifying [1 2] for 'channels' will load analog channel 4 and 6. +% Specifying [] for channels will return all analog channels. +% +% Setting 'readtimestamps' to 'yes' will return a time vector for +% each analog channel. +% +% Depending on the input parameters, the function will return a structure +% with fields: +% 'header' Header information of the SON file +% 'event' All data from event channels are pooled +% and stored in this structure. +% 'data' Cell-array with analog data +% 'time' Cell-array with time vectors corresponding to 'data' +% +% Uses Neuroshare libraries to read Spike2 SON data +% (see: http://neuroshare.sourceforge.net) + +% Gijs van Elswijk - 2005 (v0.1) + +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_ced_son.m 945 2010-04-21 17:41:20Z roboos $ + +MODE = 'continuous'; % assume continuous now + +% process in put parameters +if ~isempty(varargin) pars=struct(varargin{:}); else pars=[]; end; +if ~isfield(pars,'readdata'), pars = setfield(pars,'readdata','no'); end; +if ~isfield(pars,'readevents'), pars = setfield(pars,'readevents','no'); end; +if ~isfield(pars,'readtimestamps'), pars = setfield(pars,'readtimestamps','no'); end; +if ~isfield(pars,'begsample'), pars = setfield(pars,'begsample',-1); end; +if ~isfield(pars,'endsample'), pars = setfield(pars,'endsample',-1); end; +if ~isfield(pars,'channels'), pars = setfield(pars,'channels',[]); end; + +% set all fields string values to lowercase +fields = fieldnames(pars); +for idx=1:length(fields) + if isstr(getfield(pars,fields{idx})), + pars=setfield(pars,fields{idx},lower(getfield(pars,fields{idx}))); + end; +end; + +% First, check if NeuroShare DLL can be loaded +if filetype(datafile, 'ced_son') + % TODO other DLLs for other binary formats could be supported here as well + ns_RESULT = ns_SetLibrary(which('nsCedSon.dll')); +end +[st,libinfo] = ns_GetLibraryInfo; +if st, + error(['Could not get NeuroShare library info, please use the NS_SETLIBRARY function.']); +else, + disp(['Loading file ' datafile ' using NeuroShare library v',... + num2str(libinfo.LibVersionMaj),'.',num2str(libinfo.LibVersionMin),' ...']); +end; + +% open file +[st,fhandle] = ns_OpenFile(datafile); +if st, + [st,mesg] = ns_GetLastErrorMsg; + error(mesg); +end; + +try, + % file header + [st,fheader] = ns_GetFileInfo(fhandle); + if st, + [st,mesg] = ns_GetLastErrorMsg; + ns_CloseFile(fhandle); + error(mesg); + end; + + % Build catalogue of entities + [st, entityinfo] = ns_GetEntityInfo(fhandle, [1:fheader.EntityCount]); + + % get the channel numbers of analogue and event channels + % Neuroshare entity types: + % Unknown entity 0 + % Event entity 1 + % Analog entity 2 + % Segment entity 3 + % Neural event entity 4 + eventlist = find([entityinfo.EntityType] == 1); + analoglist = find([entityinfo.EntityType] == 2); + + % How many of a particular entity do we have + n_event = length(eventlist); + n_analog = length(analoglist); + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % HEADER + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % Fieldtrip uses: + % hdr.Fs sampling frequency + % hdr.nChans number of channels + % hdr.nSamples number of samples per trial + % hdr.nSamplesPre number of pre-trigger samples in each trial + % hdr.nTrials number of trials + % hdr.label cell-array with labels of each channel + cnt = 0; + for channr = analoglist(:)' + cnt = cnt+1; + [st,einfo] = ns_GetEntityInfo(fhandle,channr); + [st,ainfo] = ns_GetAnalogInfo(fhandle,channr); + % Until now, I haven't found a way to check whether the SON files + % are recorded in continuous or triggered mode by using header + % information only. Therefore, mode is explicitly set to continuous now. + % When reading a segment of analog data however, the NeuroShare + % routines provide information about the continuity of the + % read segment. If a discontinuity is detected a warning will + % be given in the command window. + if strcmpi(MODE,'continuous') + out.header(cnt).label = einfo.EntityLabel; + out.header(cnt).nsamples = einfo.ItemCount; + out.header(cnt).index = cnt; + out.header(cnt).sonentityid = channr; % this is the actual channr in the SON file + out.header(cnt).ntrials = 1; + out.header(cnt).samplerate = ainfo.SampleRate; + out.header(cnt).units = ainfo.Units; + out.header(cnt).mode = 'continuous'; + elseif strcmpi(MODE,'triggered'), + warning(['Triggered channel mode not implemented yet']); + out = []; + return + else, + error(['Unknown channel mode for channel ',num2str(channr)]); + end; + end; + out.header = orderfields(out.header); + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % EVENTS + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % Fieldtrip uses: + % event.type = string + % event.sample = expressed in samples, first sample of file is 1 + % event.value = number or string + % event.offset = expressed in samples + % event.duration = expressed in samples + if strcmp(pars.readevents,'yes') + cnt = 0; + for channr = eventlist(:)' + [st,einfo] = ns_GetEntityInfo(fhandle,channr); + [st,evtime,evdata] = ns_GetEventData(fhandle,channr,[1:einfo.ItemCount]); + + for trignr = 1:einfo.ItemCount, + cnt = cnt+1; + out.events(cnt).type = einfo.EntityLabel; + out.events(cnt).timestamp = evtime(trignr); + % Convert timestamp to sample nr. First analog channel's + % sample numbers are used as the reference for all + % timestamps. + [st,tmp] = ns_GetIndexByTime(fhandle,analoglist(1),evtime(trignr),0); + out.events(cnt).sample = tmp; + if iscell(evdata(trignr)) + out.events(cnt).value = evdata{trignr}; % cell2str + else + out.events(cnt).value = evdata(trignr); + end; + out.events(cnt).offset = 0; + out.events(cnt).duration = 0; + end; + end; + out.events = orderfields(out.events); + end; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % DATA + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + if strcmp(pars.readdata,'yes') + + % if no channels specified default to all analog channels + if isempty(pars.channels), + pars.channels = analoglist; + else, % renumber requested channels to entityIDs + if length(pars.channels)>length(analoglist), + error(['Requested more analog channels than present in datafile']); + else, + pars.channels = analoglist(pars.channels); + end; + end; + + % use first analog channel as reference channel + targetchan = analoglist(1); + [st,einfo] = ns_GetEntityInfo(fhandle,targetchan); + + %if no begsample specified default to start of channel + if pars.begsample<0, begsample=1; else begsample=pars.begsample; end; + %if no endsample specified default to end of channel + if pars.endsample<0, endsample=einfo.ItemCount; else endsample=pars.endsample; end; + + % calculate number of samples needed (for all requested channels) + itemcount = endsample-begsample+1; + targetstep = out.header([out.header.sonentityid]==targetchan).samplerate; + [st,targetbegin] = ns_GetTimeByIndex(fhandle,targetchan,begsample); + + cnt = 0; + for channr = pars.channels(:)', + cnt = cnt+1; + + % Cut out the data of channels 1-N in the following way + % + % begtime itemcount + % analog 1 [x..|x..x..x..x..x..x..x..x..x..x..x|..] + % analog 2 [.x.|.x..x..x..x..x..x..x..x..x..x..x|.] + % analog N [..x|..x..x..x..x..x..x..x..x..x..x..x|] + % + % All channels will have the same number of samples, + % but timestamps of the channels are offset on subsample + % level, due to asynchronous sampling of the CED DAQ + % hardware. + + % return the sample nr occuring after and inclusive of begtime. + [st,begsample] = ns_GetIndexByTime(fhandle,channr,targetbegin,1); + % get the same number of samples as in the target channel + endsample = begsample + itemcount-1; + [st,contcount,chandata] = ns_GetAnalogData(fhandle,channr, begsample,itemcount); + if contcount~=itemcount, warning(['Discontinuity in data']); end; + + % make a time scale + [st,begtime] = ns_GetTimeByIndex(fhandle,channr,begsample); + [st,endtime] = ns_GetTimeByIndex(fhandle,channr,endsample); + sourcestep = out.header([out.header.sonentityid]==channr).samplerate; + + if sourcestep~=targetstep, warning(['Source and target channels have time steps of different size']); end; + chantime = [begtime:1/sourcestep:endtime]; + + out.data{cnt} = chandata(:)'; + if strcmp(pars.readtimestamps,'yes') out.time{cnt} = chantime(:)'; end; + end; + end; + + % close file + [st] = ns_CloseFile(fhandle); + if st, + [st,mesg] = ns_GetLastErrorMsg; + disp(mesg); + end; + +% use catch to close any opened files before terminating +catch, + % fclose(fid); + [st] = ns_CloseFile(fhandle); + if st, + [st,mesg] = ns_GetLastErrorMsg; + disp(mesg); + end; + error(lasterr); +end; + diff --git a/external/fileio/private/read_combined_ds.m b/external/fieldtrip/fileio/private/read_combined_ds.m similarity index 79% rename from external/fileio/private/read_combined_ds.m rename to external/fieldtrip/fileio/private/read_combined_ds.m index 96d9c1c..04b3f9b 100644 --- a/external/fileio/private/read_combined_ds.m +++ b/external/fieldtrip/fileio/private/read_combined_ds.m @@ -8,13 +8,23 @@ % Copyright (C) 2008, Robert Oostenveld % -% $Log: read_combined_ds.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.1 2008/07/01 16:23:02 roboos -% added read_combined_data (new implementation) +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_combined_ds.m 945 2010-04-21 17:41:20Z roboos $ needhdr = nargin==1 || isempty(hdr); needdat = nargin>1; diff --git a/external/fieldtrip/fileio/private/read_ctf_ascii.m b/external/fieldtrip/fileio/private/read_ctf_ascii.m new file mode 100644 index 0000000..4441380 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_ctf_ascii.m @@ -0,0 +1,100 @@ +function [file] = read_ctf_ascii(filename); + +% READ_CTF_ASCII reads general data from an CTF configuration file +% +% The file should be formatted like +% Group +% { +% item1 : value1a value1b value1c +% item2 : value2a value2b value2c +% item3 : value3a value3b value3c +% item4 : value4a value4b value4c +% } +% +% This fileformat structure is used in +% params.avg +% default.hdm +% multiSphere.hdm +% processing.cfg +% and maybe for other files as well. + +% Copyright (C) 2003, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_ctf_ascii.m 1362 2010-07-06 09:04:24Z roboos $ + +fid = fopen(filename, 'r'); +if fid==-1 + error(sprintf('could not open file %s', filename)); +end + +line = ''; +while ischar(line) + line = cleanline(fgetl(fid)); + if isempty(line) || (length(line)==1 && all(line==-1)) + continue + end + + % the line is not empty, which means that we have encountered a chunck of information + subline = cleanline(fgetl(fid)); % read the { + subline = cleanline(fgetl(fid)); % read the first item + while isempty(findstr(subline, '}')) + if ~isempty(subline) + [item, value] = strtok(subline, ':'); + value(1) = ' '; % remove the : + value = strtrim(value); + item = strtrim(item); + + % turn warnings off + ws = warning('off'); + + % the item name should be a real string, otherwise I cannot put it into the structure + if strcmp(sprintf('%d', str2num(deblank(item))), deblank(item)) + % add something to the start of the string to distinguish it from a number + item = ['item_' item]; + end + + % the value can be either a number or a string, and is put into the structure accordingly + if isempty(str2num(value)) + % the value appears to be a string + eval(sprintf('file.%s.%s = [ ''%s'' ];', line, item, value)); + else + % the value appears to be a number or a list of numbers + eval(sprintf('file.%s.%s = [ %s ];', line, item, value)); + end + + % revert to previous warning state + warning(ws); + end + subline = cleanline(fgetl(fid)); % read the first item + end +end + +fclose(fid); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function line = cleanline(line) + if isempty(line) || (length(line)==1 && all(line==-1)) + return + end + comment = findstr(line, '//'); + if ~isempty(comment) + line(min(comment):end) = ' '; + end + line = strtrim(line); + diff --git a/external/fieldtrip/fileio/private/read_ctf_cls.m b/external/fieldtrip/fileio/private/read_ctf_cls.m new file mode 100644 index 0000000..18e1981 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_ctf_cls.m @@ -0,0 +1,74 @@ +function [condNumbers,condLabels] = read_ctf_cls(fname) + +% READ_CTF_CLS reads the classification file from a CTF dataset + +% Copyright (C) 2003, Ole Jensen +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_ctf_cls.m 945 2010-04-21 17:41:20Z roboos $ + +condNumbers = []; +% condLabels = []; + +fid = fopen(fname,'r'); + +if fid == -1 + condNumbers = []; + condLabels = []; + return +end + +nCondition = 0; +readBad = 0; +readList = 0; +S2 = '*'; +S1 = '*'; +while ~isempty(S1) + S3 = S2; + S2 = S1; + S1 =fscanf(fid,'%s',1); + + if readList + if ~isempty(S1) & ~isempty(str2num(S1(2:end))) + k = k + 1; + condTmp = [condTmp 1+str2num(S1(2:end))]; + else + readList = 0; + end + condNumbers{nCondition} = condTmp; + end + + if strcmp(S2,'NAME:') + % New condition found! + % fprintf('%s\n',S1); + nCondition = nCondition+1; + condLabels(nCondition) = {S1} ; + end + + if strcmp(S1,'NUMBER') & strcmp(S2,'TRIAL') + if ~isempty(S1) + readList = 1; + k = 0; + condTmp = []; + else + readList = 0; + end + end + +end % ~isempty(S1) + diff --git a/external/fieldtrip/fileio/private/read_ctf_coef.m b/external/fieldtrip/fileio/private/read_ctf_coef.m new file mode 100644 index 0000000..29d3803 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_ctf_coef.m @@ -0,0 +1,882 @@ +function [coef] = read_ctf_coef + +% READ_CTF_COEF returns the spatial filter coefficients for the CTF MEG system +% that has been installed at the F.C. Donders Centre (id 1706) +% +% This function actually does not read the coefficients from a file, but the +% coefficients themselves are included in this function. +% +% The original location of the coefficients included in this file is +% odin:/opt/ctf/hardware/M016/M017_1706.coef + +% Copyright (C) 2003, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_ctf_coef.m 945 2010-04-21 17:41:20Z roboos $ + +if nargin~=0 + error('this function does not accept input parameters') +end + +% start with an empty coefficient list +coef = []; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +coef(end+1).name = 'G1BR'; +coef(end).reference = {'BP1-1706', 'BP2-1706', 'BP3-1706', 'P11-1706', 'P12-1706', 'P13-1706', 'P22-1706', 'P23-1706'}; +temp = { +'BG1-1706' 0 0 0 0 0 0 0 0 +'BG2-1706' 0 0 0 0 0 0 0 0 +'BG3-1706' 0 0 0 0 0 0 0 0 +'BP1-1706' 0 0 0 0 0 0 0 0 +'BP2-1706' 0 0 0 0 0 0 0 0 +'BP3-1706' 0 0 0 0 0 0 0 0 +'BQ1-1706' 0 0 0 0 0 0 0 0 +'BQ2-1706' 0 0 0 0 0 0 0 0 +'BQ3-1706' 0 0 0 0 0 0 0 0 +'BR1-1706' 0 0 0 0 0 0 0 0 +'BR2-1706' 0 0 0 0 0 0 0 0 +'BR3-1706' 0 0 0 0 0 0 0 0 +'G11-1706' -0.0264191384733462771 -0.09393714520816329183 0.03472106287087559084 0.003506626350611835238 -0.005880847048019656638 -0.001459855517849013157 -0.007353073326519059955 -0.003743057534581884557 +'G12-1706' -0.15631635645912062 -0.02014141111638220738 0.1436481856661243617 0.004600874792404144493 -0.004611259697450509169 0.0004752228341851168409 0.0007640003853063520676 -0.00277532679348740409 +'G13-1706' 0.04110897336270846747 -0.03452679329560731647 -0.06393676172944513791 0.001028131731276316465 0.00186284243649349735 -0.001451816271089236216 -0.001358597755574905176 0.0006910884467223846368 +'G22-1706' 0.04331969312007057094 -0.06062950945022867882 0.08408422096536792567 0.003680940988756525607 -0.001070296228248003275 0.001825104713254158345 -0.004107276586287685917 -0.006349581432787697148 +'G23-1706' -0.05915572966201160937 0.03876223332726273785 0.06908504192232067798 -0.002644022948828536352 0.002055794217374205552 0.003456284601839287179 0.004962421184143010582 -0.001541088857505202182 +'P11-1706' 0.1013730157232110296 -0.003842563929868799376 0.1390088421251277351 0.00127245842882615901 0.001513541569498277504 -0.01203161286911904118 -0.002039665399731243299 -0.0001118461525465887501 +'P12-1706' -0.02230063857995695509 -0.08339752179219198092 0.05167979193789769277 -0.001901666430778932914 -1.112991324090676032e-05 0.0009289665129036059083 0.001596662183431015163 -0.006763350544924771543 +'P13-1706' 0.01953618217372175142 -0.00841684891003604066 0.04062399459219920989 0.003293303481822240121 -0.0008279888787800854721 -4.805932113300294287e-05 -0.0001369132452980285615 0.0002111599101189122701 +'P22-1706' -0.06162852648212610585 0.002014404545876338944 -0.05876248274342443095 -0.004574372345416573976 0.003033074270561343915 0.002749808529324927059 0.002733472711775690282 -0.00184592004765981926 +'P23-1706' -0.06926180620722945103 0.07765435121154141973 0.005943320067624360305 -0.001485322407569247957 0.002372893729645904077 -8.393517856784981257e-05 0.00330296967456195599 -0.0001543974363835938306 +'Q11-1706' 0.1559525537865661948 -0.0301179071973083877 0.08454678440973048548 -0.004561199340475460481 -0.0003274266530055112284 0.005332537946052225315 -0.005159675580844180764 -0.001910276003785410168 +'Q12-1706' 0.04519943580039444131 0.01199298670693924214 -0.06012000410506595366 -0.0004658052084824485526 0.0005453884287832038791 -0.004192556702062221786 -0.0006458749810405322884 -0.002403900354036449943 +'Q13-1706' 0.02152223087935774617 0.1185191818257770868 -0.06280260960320684094 -0.001732743570825734684 0.009788679236335286193 -0.00279724962173814309 0.0007139947222094535041 0.0006292178009423591515 +'Q21-1706' 0.03511431540352640684 -0.09324176515284531008 -0.2378508183929713971 0.0001863963556231685496 -0.0047797126202589078 -0.01383469564159488067 -0.003243539629848182435 -0.0007882212657080260847 +'Q22-1706' -0.01325191191768199279 0.01569028060420297327 -0.04503484859083141389 -0.005415702823409083641 0.004773939902877517155 -0.002107258730870098257 0.003592044859670810199 0.002241853893423344235 +'Q23-1706' -0.04034452584000429443 0.03887881319097546279 -0.01411338083056289799 0.005302706624404679783 -0.002464485100338323353 0.002116497861299033566 -0.002876588871398561183 -8.164520627749203077e-05 +'R11-1706' -0.05465494247696155161 0.02699062350395145873 -0.0198390465441167195 -0.002245929791160849315 -0.003468163840904351595 0.004102981500407982748 0.005131791355486700103 -0.0001263427478631306807 +'R12-1706' 0.1739091278560166154 0.07391028779775499213 0.05744677916065434736 0.000176580815800490902 -0.002604670495164311799 -0.002866536244602645687 -0.0001556539881100017883 0.003703473197964752325 +'R13-1706' 0.0957588675733173772 0.08096465545098394112 0.07183655710790715077 -0.0008256035302983351408 -0.0002200289694127210375 0.001790966223527513078 -0.004087592449532656894 -0.001900148179563695017 +'R22-1706' -0.04994986697262312342 -0.09270927263208594837 -0.03263699661542152769 -0.003923601934597151925 0.001253183979806851483 0.001148162523333353313 0.0054274328185575536 -0.009606445303716919584 +'R23-1706' -0.03576965100617419263 -0.03376652789935699617 -0.0365169940808238655 0.001271346843492731629 -0.0005998660778820106339 0.0001397113587351274508 -0.0005725112719108759168 -0.0007844263515726342464 +'MLC11-1706' -0.08169094833952039725 -0.07778761523671674782 -0.03602817837011070001 0.001973157498682633938 -0.0009570852073294326906 -0.001941672919277036627 0.002122549758488780081 0.0001897740511579152007 +'MLC12-1706' -0.1143598681667212513 -0.04464789592974541949 -0.0497273135933348695 0.001792677112180930893 0.001568561833941606743 -0.002775683674789341301 0.002043118558131330666 -3.192655624035087736e-05 +'MLC13-1706' -0.02675515262126364202 -0.05993399388341711514 -0.1240824188186403776 -0.002302474427003269215 0.0003205276383441307852 -0.002874876832128037216 0.004490328235682608006 -0.0009827928235380146028 +'MLC14-1706' -0.01593022948195283589 0.1161792516187972191 0.05128349023491357572 -0.001314836099823023111 0.0004682101500485290942 -0.0005389841182682172157 -0.001621418941626334318 -0.002763764934209912271 +'MLC15-1706' -0.04365891434796476817 -0.005112828275713867353 0.03711797746191328184 0.0009289168132441707982 0.000554282860115148609 -0.001452804120565325333 -0.001144416911372263127 -6.832449990082212465e-06 +'MLC21-1706' 0.02932828982385538366 0.05638773587514809421 -0.05153260851931371761 -0.002663064412076631207 0.001254424973730259478 -0.0006627033082959863427 0.001270449914446846688 -0.002988101930751302805 +'MLC22-1706' -0.1303193811874465702 -0.01551791555834620452 -0.02740006384928243485 0.001966843191339693458 0.002492647514403653099 -0.002865153989623993921 -0.0005534910207995557933 0.0004929628996566032305 +'MLC23-1706' 0.06264549991388240757 0.05891663467177794822 0.0877364920707897622 0.003658963071312066381 -0.001576273532511551344 0.002127799386718442955 -0.004384102939197958952 8.593959831221818833e-05 +'MLC24-1706' 0.0886490694282748154 -0.06008059716139022705 0.0894572210640846438 0.00333470302853348206 -0.003196455331682110552 0.003946856845293355599 -0.003083204887401702881 0.002704361887335607513 +'MLC31-1706' -0.004188032385454836838 -0.009438367638259297435 0.02772370501803808271 0.0003764062181060639448 0.000529860243414346458 -0.0001969268532747479959 0.000545944359708026958 -0.000337202737926062257 +'MLC32-1706' -0.02892555588501214206 0.01816094057448786395 0.1427226447881204674 0.004033674089350164534 -0.0004173658358086427276 0.000206722794864947168 -0.003280813869518356234 0.0009126403465631925758 +'MLC33-1706' -0.03760957250429839555 0.1330770886630250061 -0.1109134405160249887 -0.002911674501802634981 0.0001662039590296551361 -0.0009504583043188576021 0.002268194506639244733 -0.002411707490049654415 +'MLC41-1706' 0.004484038158600188624 0.03207114254079498211 -0.145540551211527508 -0.001413807995355089581 -0.0004928656017118796407 -0.001659366168101239752 0.001695958091025974316 0.0008531778609591880507 +'MLC42-1706' 0.03081856381159134295 0.06951500880368327584 -0.1203999073440922829 -0.00296489572291142988 -0.0002134452125507216389 6.624333005537298854e-05 0.001781280265482826581 -0.0007521350260563572886 +'MLC43-1706' 0.0321920808795027949 0.04281961220683999647 -0.1436538778853285736 -0.002409441977414472288 0.0002222236100169890604 -0.0007767938994046890864 0.002834769034894948914 0.0001321676835478797129 +'MLF11-1706' 0.0486845482046923822 -0.05634815909642976878 0.03605598118424856863 -0.001391817542817647656 -0.002927758763471970463 0.004912599036272874593 0.002422008102513675733 0.0008733812980664337365 +'MLF12-1706' 0.03641949670982108644 0.01565833525682581995 -0.03015848431759602169 -0.002524202973409718411 -0.001239068139467321876 0.00090620191538810129 0.001138356456189477343 -0.00221020780040241541 +'MLF21-1706' -0.08437362559607890222 0.03675168392572165238 0.1267087488804320428 0.007197828423764823444 0.005312923466261385182 0.001718012609777189777 -0.004145187006278239911 0.005145921122402897195 +'MLF22-1706' 0.003666449426546053263 0.06878420312064491282 0.06485373056897690558 0.00115840366206490606 0.002957863791410553656 0.002266983421226344796 -0.003559978383786141856 0.00290003870868536448 +'MLF23-1706' -0.001766104283337611297 0.002191620637104321149 0.07503871470169515279 -0.0001397438849889657165 -0.000980983709857669332 0.0003121188549579255911 -0.0008650284150994518809 0.00103497768738134246 +'MLF31-1706' 0.05862127215467319991 -0.04720680136460211895 -0.05315630240811205359 -0.00534592739062208621 -0.004342439212181393136 -0.0005416426992542979673 0.004299323821839680371 0.0009008307410594766206 +'MLF32-1706' 0.04170433995433825425 0.03577403397096552001 0.03442132344435087227 0.0006274239791459252551 0.0001146220781466724027 0.003207747872516627033 -0.002500579466886360472 0.0005162823742417331583 +'MLF33-1706' 0.07224144575709082194 -0.05799248697109807976 0.1193261626801749853 -0.0008386642658422710809 -0.00345628328411052687 0.005766293522296093987 -0.0007209900800219163058 0.007480349471250150734 +'MLF34-1706' -0.04623778586970897497 0.02651913381776007175 -0.1211211264001189059 -0.001901332217566160769 0.003405230063653887258 -0.0006642837924313488339 0.001986179146561393039 -0.007277908574261159926 +'MLF41-1706' -0.005952984108760345054 -0.0300002530868771107 -0.104517977065195028 -0.002779416187950886456 -0.001952051692240219577 -0.003213457278739185671 0.005053509821421920366 -0.002161729698395222984 +'MLF42-1706' 0.01938890309157847644 0.0972611201679080134 0.08224929721602226851 0.003910687120174407248 0.002562919478749034214 0.002965603937278296891 -0.007749814833394774033 -0.0003513692943487557946 +'MLF43-1706' -0.05523509547259997793 -0.01212834526674348712 -0.06683058435081275228 -0.00162060294950301274 0.0007094265108195284752 -0.004344416977020417077 0.004779069704465808109 -0.0008087881775315204722 +'MLF44-1706' -0.06149572398636771881 0.008654051646542509912 -0.06884525165364401011 -0.001989818251993153743 0.002845720221727946267 -0.003118398960983834699 0.001651189326422665329 -0.002560476316490174244 +'MLF45-1706' -0.07455239819444736682 -0.04312643887730381598 0.01570213489960134087 1.15731867135759197e-05 0.0001594891684185467586 -0.001829440166051054953 0.002530474279609825749 -3.510000676300471995e-05 +'MLF51-1706' 0.1104599032276762094 0.1023363109639326696 0.2434784393728419427 0.0007421300460333978216 0.0004699027730810729142 0.008034059594279932201 -0.007750718594812190144 0.003007665055409218958 +'MLF52-1706' 0.0315025401549877751 0.04207995779152934324 0.03602312351826288117 0.002236467567895387629 0.0001019471475048513016 0.00320331235249392797 -0.00624960718857017674 0.0006667885597981402157 +'MLO11-1706' 0.02314122268608936883 -0.08361990527001375573 0.1270911413084725161 0.005143302599188393116 0.0005145727833603718285 -0.0008371162079795993081 -0.006247019539966511964 -0.0001945087097456884651 +'MLO12-1706' -0.1174636777315953284 0.1019435450856824438 -0.07472174090096674048 -0.002799574059898726156 -0.002713258320886116799 -0.003517947128114793948 0.00234264710666397041 -0.002224427175212217739 +'MLO21-1706' -0.03447047688806180454 0.04500620522302665322 0.002138697203099019541 -0.0004338134055141773201 -0.0003640155912981522367 0.0005511483414477360817 -0.0007040415156798425543 -0.0002694382562125265004 +'MLO22-1706' 0.07281409188120534226 0.004173418721493943502 0.1365910222816845432 0.007459290090986435764 -0.000589805622887046516 9.722846236602031961e-05 -0.006004115400561333207 -0.00122646357454577826 +'MLO31-1706' -0.002357501371323334621 -0.1123805701947582364 -0.08216080167334305351 -0.005093116624289911396 0.0006597203424861065651 0.001344129095256043401 0.002514485089694316108 0.01133942555914089351 +'MLO32-1706' -0.0334560583782100851 -0.07311456282523082217 0.1636041895649194 0.008086372320052081716 -0.0005989395114369598866 -0.004234944143885506843 -0.007930486259201464591 0.001588027840800883229 +'MLO33-1706' 0.08065690416624418657 0.08129573318855765063 0.1095079882767951707 0.007645175349801078442 -0.002135024888823164064 0.003910597195522389977 -0.006440567658631740633 -0.005752498015854643973 +'MLO41-1706' 0.0626825670717182093 -0.03925604868915193169 0.07864228172199665134 0.005837815341852983092 0.0006908949329460713652 0.004226961089515340886 -0.003543907457279057722 0.002720203614981867978 +'MLO42-1706' 0.03150489107474273992 -0.005192130363646422532 0.06789940483885768818 0.006442137779951049616 -0.002051857356090561364 0.002959343398706090842 -0.005841434473312411349 -0.001865818098152014284 +'MLO43-1706' -0.105017444393681908 -0.03879118782735690996 0.05267434148790881704 -0.0002048930333194926099 -0.0002766798434827620959 -0.01204192572666521778 -0.0009104394104636268211 0.003526212006333630158 +'MLP11-1706' -0.01665683945522817427 -0.01458082955110009959 -0.001717118410571721702 -0.0008058382407195099906 -0.0003952112063049105679 -0.000265328884316369377 0.0002772382041650639961 0.0002674196615851753378 +'MLP12-1706' 0.08334674643181358422 0.1462031775683859391 -0.03759622085453590001 -0.004419246049768943245 -0.0004848435753358127298 0.002215313654544366195 0.003772826635950356569 -0.003453052202966981187 +'MLP13-1706' -0.1413978500480226885 0.1162061410570211506 -0.1431007518787011934 -0.004250190066254892242 0.001124484842748748638 -0.003283929031137248263 0.002343406143426495208 -0.003137041034065265934 +'MLP21-1706' 0.0310521781998556283 0.01715180039719564273 0.1488184129943469769 0.007281852350803847893 0.001947879159909643053 0.001662601233256877451 -0.006083270462598984289 -0.002605696887711325682 +'MLP22-1706' -0.07229855724346374857 -0.002555363737419081259 -0.003438598478491566423 -0.005512381047732611491 -0.0009443738122476391357 -0.002964420858213685176 0.00316842969160179835 -0.001099456227804870845 +'MLP31-1706' 0.01973400859938471974 -0.08293197660109212499 0.1644500223297546138 0.006807980745524295878 0.0002338667421802310097 -0.0005797875849454812774 -0.00789221550859022826 0.0006403819587172882629 +'MLP32-1706' 0.08073799498754855031 -0.06003975620547930686 0.009228449346786226151 0.002994834586953030921 0.001489471388944963934 0.004021223273314469132 -0.002564271811308516807 0.001384448368804964578 +'MLP33-1706' -0.04856319683161220563 0.0141345464612201259 0.01356816981008760435 0.002516500519507202088 -0.0006689698230333984306 -0.0004843248254058340747 -0.003667588625343277432 8.147322887774581415e-05 +'MLP34-1706' 4.338742305103973233e-05 -0.02220759823796741514 0.06807469498132442953 0.001205513384094533159 0.0002079994603228527779 -0.001293848123360223082 1.256253441546337235e-05 0.0009161645481515392608 +'MLT11-1706' -0.07119135147717041423 -0.05764704672273533032 -0.08728968968067148115 0.0007050945318952128466 0.001474554514320723696 -0.003961243065413599593 0.004562958194916142025 -0.001234582376461780063 +'MLT12-1706' -0.1131044318276106936 -0.05634271214959760826 -0.09412831582017650023 -0.00117458971689575432 0.003918556622871823686 -0.002052558714322601403 0.004427591691441123793 -0.004042430364576622866 +'MLT13-1706' -0.07436579021423332658 -0.04723163126907089365 -0.01948968242544554808 -0.002375777053119673948 0.000990975693939571663 -0.002370644120056819397 0.004234419169750066117 -0.0001061545369819668678 +'MLT14-1706' 0.05794205774340786819 0.1270499567655195838 0.1374594193211001458 0.004129831578295194323 -0.002952530329313013575 -0.001215989310713602419 -0.005028798681107788347 -0.00158130994677367848 +'MLT15-1706' 0.1326511965250666836 -0.03381652123913944652 0.06779784282069752088 0.002806242428225305067 -0.0016524526660064993 0.004432219259263953451 -0.0008377102596376339574 0.001687073790903483852 +'MLT16-1706' -0.04875426598541725276 0.03389287478206472887 0.05350224143467714744 0.0004654454495571575998 -0.0007356571395929717514 -0.002440628202642887087 -0.0003349232651082225298 -0.0005072977169438921442 +'MLT21-1706' -0.1501717797510344343 -0.01043889896880097375 0.02243968818810324409 0.002569750102552477346 0.003852297018191960278 -0.009174577728081610359 0.001676096652902918762 0.0006436174186517940867 +'MLT22-1706' 0.001991509699583361107 0.06761637317345421672 0.002648187471900352325 -0.001025153177916804338 0.001578599412250763882 -0.0006893423928120410472 -0.002696316037159098965 -0.001826750479865601713 +'MLT23-1706' -0.01794186865101339221 -0.06859440818349024638 0.01008800095080463963 -0.002347713002170558408 -0.0005415664270881071201 0.0002651125668366013845 0.003499309941100396757 0.00239153471711374627 +'MLT24-1706' 0.04693035075192095174 0.05899796693030478351 -0.003378271376477684062 0.002580714528480798631 -0.0003527947059254335298 0.001243299159284090051 -0.002405588759071313788 -0.001276035870958701877 +'MLT25-1706' 0.09916325960215900681 0.0152808410209484876 0.04155238518362013717 0.002981292595810487289 -0.001769973001534464385 0.001898658697853405171 -0.001589526894059696896 0.0002384428863824039223 +'MLT26-1706' 0.1215786588670737384 -0.03147435425247940843 -0.03803587133465206882 0.001452680151748617391 0.0006815245731913477682 0.007494668280355921974 -0.0005195227264274136824 -0.0009845825491643031297 +'MLT31-1706' 0.0277145770495155 0.08508615708089016516 0.0737625545970785057 -0.0002232388156622773371 0.001330887911399056918 0.00220513339677778572 -0.006166671234359989186 -0.001623079340617667029 +'MLT32-1706' -0.06576210263306202231 -0.1042723949972844261 -0.08173267636174512407 -0.005258471527102252276 0.0003894854010517451604 -0.003411973568032630917 0.009816266375972833302 0.00237127284610463146 +'MLT33-1706' 0.05247701532802057089 0.1025483019053009537 0.02154734523881653846 0.001927605329932429454 -0.001775332314277266663 0.001723311512882435247 -0.003463121231166730284 -0.00561993043810803377 +'MLT34-1706' 0.03430466991650319569 0.06327278809233097268 0.006755227857269980631 0.002697067481351988691 -0.0003993427962760715141 0.0008996038898930002305 -0.001049023723620778155 -0.003268916470090367423 +'MLT35-1706' 0.08961015988181658676 0.03587109863180910213 0.18318100239945595 0.01103931854924236101 -0.0009129008593952861808 0.003683617138389610676 -0.008911821707427115477 -0.001087860716498573101 +'MLT41-1706' 0.1121900794750923247 0.03501854649282737375 0.0555803354178334777 -0.0007588274198073101211 -0.00327244229595591166 0.006515251659190389455 -0.003816077694025338252 0.002139163643736591291 +'MLT42-1706' 0.0003771634197455116981 -0.07576882101058936281 -0.08206390643651423344 -0.007016106621470171584 -0.0002634107999376103472 -0.000181541646441572786 0.00844110623251771372 0.002835783392186372494 +'MLT43-1706' 0.08589727633060219303 0.04754776854846856637 0.05396015690086911065 0.003816218495162844015 -0.002865759494469760985 0.004841391883276729112 -0.002594262814933909374 -0.002374908586833878159 +'MLT44-1706' -0.03880614531269225426 0.01168086900390651398 -0.08035085640332936818 -0.008125791889615803162 -0.001255245122555012248 -0.004336833616457717346 0.005279578553331631431 -0.0007364185322912057642 +'MRC11-1706' 0.04905825153194179333 0.05021553215442244728 -0.1161873431783372324 -0.005283411844977561889 0.004190274243753211968 -0.006489463089603761045 0.002134827421827209179 0.001088646833990697003 +'MRC12-1706' 0.038765513319149493 -0.06028831091843185608 -0.01683800007477901858 -0.004015554489408797514 -0.00117469770939427026 -0.001358937607160284455 0.001647334429817644665 0.002068934508305220101 +'MRC13-1706' 0.01449403421996967901 0.01266919604325178299 -0.04528591473060563505 -0.005630487298552830887 0.003674791001803843268 -0.00131273425897167101 0.004840227163619238715 0.001209112022495565991 +'MRC14-1706' -0.1309257608810071305 0.07948374963692056427 0.109917585339755472 0.01232417333508195427 0.000257771915422067802 0.0006982015370585765036 -0.004852008483657222447 -0.002323079066554080852 +'MRC15-1706' -0.1455614998216883393 -0.05126645011277587011 0.03295470527381598458 0.008847436352862067879 -0.005648358483434529412 -0.003513780630661109908 -0.003816921740647256228 0.002029066444882624606 +'MRC21-1706' -0.1181262950946457696 -0.05776720096259697207 -0.1314170306161213664 0.001022110117168670068 -0.001859368538163123355 -0.007711482513466389604 0.002682874244183034926 0.002435347213165651829 +'MRC22-1706' 0.03004418418700032997 -0.02160229914730798714 -0.1215452966207518776 -0.004795334252637433597 0.001435138509880688751 -0.004622433913632447051 0.003710077909880159924 0.00225101600599322783 +'MRC23-1706' 0.1326933601962281273 -0.001799686029024137905 -0.004594922880254277003 -0.009839516690303723445 0.005259402711640813813 0.001834948417114939468 0.004259923055308295799 -0.0008544581475162210237 +'MRC24-1706' -0.1030444064379932717 -0.1229694292493842545 0.1440635615401658076 0.007484031274591061191 -0.008862040632252196626 0.0005350760240263389674 -0.007021909707641223186 -0.000411628591045229723 +'MRC31-1706' -0.001335090457241287082 -0.02091655342978157583 -0.0903712961347432342 -0.0005962869644783134202 -0.0006111606907601909323 -0.001881149945461462738 0.001524379007802776622 0.002713905994343594839 +'MRC32-1706' 0.09932995406713381048 0.1077439435820987251 0.04774401161753110551 -0.004481345381639550984 0.007672543929189098479 0.003015247573588319616 0.004681080360663899577 -0.002440951108030150595 +'MRC33-1706' -0.04143616505395392169 -0.02061407332365062031 0.0595403742138041342 0.002437038054817142457 -0.002243296022937215153 0.001373102667297474832 -0.003021827048105957952 -0.00104075099145226036 +'MRC41-1706' 0.05340153596053777429 0.01235192694892472097 -0.1521502927781260561 -0.00250222580921827557 0.0002184060632382003571 -0.0007764978088582583831 0.001346388234322260392 0.004022353641659032544 +'MRC42-1706' -0.1308251678875679558 -0.06121244703380408769 0.01621668870635739265 0.003857724856966076969 -0.003229309708774994077 -0.0003559183806644752456 -0.001895358420277294285 0.0003408015670166281001 +'MRC43-1706' -0.008820247830537628064 -0.01410409010443540098 0.004978901877824444197 0.0003257003865880967147 -0.0001055912814816655849 0.0005820141162282079948 -0.0006839780404464143549 -0.0004314270984197458381 +'MRF11-1706' -0.05927180624303287487 0.1698647403831448355 0.02349070388399385548 0.005174611933079595327 0.01066759352216164851 0.001624143995984451364 -0.002857301605767159115 -0.006952567109497205348 +'MRF12-1706' -0.1156961786695336891 0.03139903126417253887 0.01030336632029419698 0.008384614606784839691 0.0008993967787351204481 -0.004420081528940797595 -0.0007430514111727649961 -0.001400375235163405386 +'MRF21-1706' 0.07536482991616295923 -0.05095617741978673149 0.0300090052436431283 -0.003790137430286858941 -0.003385386874246742051 0.002378283424642998849 -0.0002265281329216957689 0.001165314637045623694 +'MRF22-1706' -0.09497410800327661662 0.1514611719541867074 -0.07313452737114113644 0.00164891767321490414 0.01024679739526251562 -0.005968414744568563933 0.002447748697249224094 -0.007008070951553715087 +'MRF23-1706' 0.06750415506240187158 -0.04810977815045710398 0.07000768562149536911 -0.003497732142617483719 -0.002901560356745745868 0.005042332304732799822 0.00116697253454212395 0.001540567143372666668 +'MRF31-1706' 0.03755041253144317942 0.05042251936021212994 0.0003918437442440177144 -0.001378490605474496722 0.001982906272060441007 0.001284623507700979059 -0.001704301729835097819 -0.001758231312330221221 +'MRF32-1706' -0.08921740135827620211 0.0255206941200210799 0.03375029688523754207 0.007122396832095226511 0.0005851826770174807686 -0.0009541123811495143096 -0.002261617883304014621 -0.0008908450396267382238 +'MRF33-1706' 0.01388357405685359744 -0.006911773932703257906 -0.08195124606123098399 -0.002081204245761677629 0.0001895407612800169761 -0.00409108487776416261 0.000417171201991288639 0.002767172285945048056 +'MRF34-1706' -0.1591741172499583357 0.02643972890461294273 -0.0418869261070791421 0.008533571437607417529 -0.0004425887773276770509 -0.008400364021072373455 -0.0009472442618778351446 -0.0006326585123341227444 +'MRF41-1706' 0.008934226636687043338 -0.1246821349510704585 0.0539355831986764872 -0.00210835905638084159 -0.008108795465159924706 0.00217714790307930962 0.002404859883105429138 0.005299630618631053988 +'MRF42-1706' 0.02219229715764200334 -0.02386008771660289365 -0.1207300526725543499 -0.004029417922900853377 -0.0001965364257043537702 -0.005705865724320029371 0.0021085872967686165 0.001823024669664702726 +'MRF43-1706' -0.1199734016582196111 -0.005524728023895125045 -0.01528967679157985059 0.009073302104067249713 -0.0009730378375928919101 -0.005513288873390123114 -0.001441347067386034193 0.001915372552622523084 +'MRF44-1706' 0.01911049286834281755 0.08625057435879517065 -0.0348336447430629137 -0.003193841199669685948 0.007213966774171157344 0.0004416997950282252066 0.004097167454934042344 -0.00217954837490737241 +'MRF45-1706' 0.03267429006525768981 -0.0123880122742903772 -0.08559274144003650719 -0.003397272545011727381 0.0007521833043020785623 -0.002705146870133031886 0.0004395196201568037629 0.002829012658065854519 +'MRF51-1706' -0.04486963828819867661 0.03263503416404628377 0.1417765381672110303 0.006420450680982054022 0.001053881903977611735 0.006862393908655901008 -0.003461165306832853818 -0.002843001205936236328 +'MRF52-1706' 0.0840161711866430766 -0.05056896176359865908 -0.1363333502479064929 -0.01046921658184522992 -0.001417564895243629943 -0.004430650194079593061 0.004443712756929127719 0.001394260784154460362 +'MRO11-1706' 0.0489268523418150969 0.07043529233620775265 -0.05875944298932979371 -0.001706116523312542748 0.001483607951952967043 0.003289763667354275375 0.003582036680922548628 -0.0009428245285377184585 +'MRO12-1706' -0.1098868283857271089 0.01031943943541243844 -0.156055338186844722 -0.003441384322028810758 -0.003737846836239794822 -0.005919596439685380178 0.005507461837499515872 0.006451515186175109731 +'MRO21-1706' 0.06124648629334391442 -0.1344152643233897659 0.1157083655140577899 0.004495273242447866621 0.001458244197427900233 0.003095620997526333986 -0.009987577509252004368 -0.001043636905061555995 +'MRO22-1706' 0.02035942451991331476 0.07306095749210204937 -0.1025338157335537598 -0.007602469546580188815 0.002970999315757878387 -0.001478616739937645315 0.009556609659277712915 0.0001498316600219531979 +'MRO31-1706' -0.01842520934869511934 -0.05897768794678836385 -0.0176618050312796239 -0.0007268350708921553216 -0.0004381571913522227493 -0.0008142566825747265223 -0.001129510346025942077 0.003697154697330076734 +'MRO32-1706' -0.108015119699060802 0.04992775934758275636 -0.00766620980323388674 0.001333973175836866568 -0.003343014713466150797 -0.007254840704327543584 0.002474534892554944038 -0.00467167985526563672 +'MRO33-1706' -0.04604995813830589646 -0.08181317800527922179 -0.07971201856678399034 -0.002444308052713499435 -0.003747723289008821762 -0.005311673540943672063 0.0003173246244727370973 0.01008590777313568727 +'MRO41-1706' -0.1396447267673452675 0.01956462198692184365 -0.07442927854132301568 -0.0027880158103816533 -0.004183359022666682109 -0.008861860678774294633 0.006359551938724348 0.001481230065256445476 +'MRO42-1706' -0.08731436244733133123 -0.1898859586254274534 -0.1061605608345139312 -0.004347882126933712635 -0.008673396879751630803 -0.004599885172080419096 -0.002088211173904723494 0.0183974821236261403 +'MRO43-1706' -0.01015844501632899056 0.09080703786872038052 0.02754974753961466488 0.0008742615752022631906 0.001786074076516968234 0.001883520317054157957 0.003029565798177593586 -0.01090131499734971546 +'MRP11-1706' 0.08568603364928094324 -0.05172293645489798447 0.0381520593088977289 -0.0004589506864935068587 0.001590958599182141359 0.0006352943985494967968 -0.0006108614358327026962 0.001377458387293534941 +'MRP12-1706' -0.05401520174951638525 -0.1649083483779936188 0.1375705327125132937 0.008141710511508014683 -0.005827597171975091618 0.0008055673321375186402 -0.01333094063522897305 0.001063807059849061418 +'MRP13-1706' -0.05170672468111960768 -0.04546398718793677463 -0.03026097969430951301 0.004627665264566305919 -0.004382106746662349332 -0.00259724309315358115 -0.005712202655835688266 0.002826830100591210936 +'MRP21-1706' -0.02358425510825486876 -0.1655003835229378606 0.04263621208603748242 0.003571196378993595193 4.24043403787814036e-05 0.0002463783544003374779 -0.007653379675732863846 0.004647381567297975864 +'MRP22-1706' -0.0152693644505065302 0.1064396750856890644 -0.04915748879273994926 -0.004506612092503519719 0.001117647624786547627 -0.00238976361274184472 0.009440357167682645462 -0.002213030850561107168 +'MRP31-1706' 0.02605718797169995563 0.1008159057564364386 -0.03176540201688388826 -0.00263611762654228669 0.002021634576953478066 0.0002898946841780580797 0.005696263206697630387 -0.002858881996858541209 +'MRP32-1706' -0.04562033778394036787 -0.0191764976511411174 0.1100151740356888203 0.006057706133151600364 -0.003141236716978187266 0.0001241584817513247314 -0.005692454998138657234 -0.003046031637971305817 +'MRP33-1706' -0.05359105529443427413 -0.108030777055477395 -0.03641341663242660814 0.00235350143162603052 -0.005088681913204950308 -0.003043802832686251948 -0.003631635296101508575 0.004700500334008261838 +'MRP34-1706' 0.07383963570145232747 0.05789326739102877706 -0.04300724157919594282 -0.004382654381244953726 0.005450544115452076593 0.001879083840005240855 0.002792466282195058512 -0.001201345824202150903 +'MRT11-1706' -0.05985921631980969937 -0.009016481778594797811 -0.04346444678682877955 0.004120295390647475686 6.076521551743360294e-05 -0.004973651394235749888 -0.001545776790683258458 0.0008635627930405878529 +'MRT12-1706' -0.01759763376596451198 -0.04828758555665632612 -0.02470731770203738603 0.002671822733217408142 -0.001569204228173147735 -0.0004365625264122458644 -0.002887496094355171492 0.001314498135731895657 +'MRT13-1706' 0.08128708406894420702 0.03189288086681602713 -0.02693551162288163395 -0.003967154719136415861 0.00442724447554997385 0.001991286101900421358 0.0002609542149035969615 0.00148015053412317815 +'MRT14-1706' -0.1162962964384676168 -0.03621731485049613231 -0.1682955862496358923 -0.000535230337944536433 -0.003960393348884780861 -0.01206056499581117068 0.003538970641713494198 0.005178749704418062795 +'MRT15-1706' 0.08932965824522876019 -0.05166579748786509496 0.01161631208494163896 -0.004005325134839899347 0.0009617133710911995436 0.004230366249620202274 -0.000924770385257994449 0.002463093784220889149 +'MRT16-1706' -0.00399850202197785283 0.08835741140573125096 -0.05147703854561432729 -0.0004925097395915996844 0.002359309014294077612 -0.001081153130429976126 0.004235431494727366283 -0.00037244107846327965 +'MRT21-1706' 0.1113956198550619947 -0.03392461199470167554 0.05705166046623318804 -0.005175794672244536133 -0.001471057943205783666 0.01218851836144587558 -0.0007043289034428030409 0.0009564854292477372637 +'MRT22-1706' 0.04711068650423857335 0.05952896272395349214 -0.03096674808938605639 -0.004352989414070788758 0.004320607126882290878 0.002364897744390333147 0.002222375895663792223 -0.001883949592848320779 +'MRT23-1706' -0.08340999993678881175 -0.06747303878644381192 -0.01504468196754400397 0.002958614061142303495 -0.006189050101080968008 -0.005640230797651546793 0.0002591916738018565738 0.002917317441589548782 +'MRT24-1706' 0.03171168279119977035 0.04365824586675463165 0.04667283211934530884 0.000216492168100109177 0.00274607520382899508 0.003346553492217337576 9.575290406123761601e-05 -0.002637571559936767104 +'MRT25-1706' -0.09910903306266298507 -0.01001841365376395995 -0.07960848962092809122 0.002469112155534166145 -0.003822984385791183912 -0.008347447632039494553 0.001898502888129895627 0.003940294515481054978 +'MRT26-1706' 0.0007734276721666665444 -0.06700129664722917489 -0.04038920592138294657 0.0003854113951465349048 -0.001563770739720348911 8.564504304294472126e-05 -0.00232512996713209099 0.00269018265925205155 +'MRT31-1706' 0.04050681318299218653 0.03125316201216151585 0.001506916185139704854 -0.003533473004486763474 0.001414057153773838746 0.004750884268308786136 0.0005100418475276040104 -0.002746408068342049997 +'MRT32-1706' 0.08217026326770715539 0.02448282558704611978 -0.07416495503046548199 -0.007868065332407993967 0.003291684021555728572 0.002770759820770513863 0.002439647833194805767 9.25362291549575519e-05 +'MRT33-1706' 0.007427308952660549059 -0.01154170313289417348 0.01369371728950028247 -0.0001564389549000813249 -0.0009190814209578675002 0.0001141384526413533919 -0.0007738174915289131603 -7.83291616818462713e-05 +'MRT34-1706' 0.03811942565064375954 0.09709976587065491382 -0.1165401771927899177 -0.007682893268070568882 0.005641741760780463397 -0.001578302192996052476 0.0101381861130977538 -0.002297401560141792889 +'MRT35-1706' -0.03387641660861703125 -0.07724995311540595877 -0.01147930860206294 0.0003949886581202345583 -0.003508316223875716615 -0.003308568367685030005 -0.002868273518264801477 0.006596507278721489183 +'MRT41-1706' -0.1758567692921810532 -0.03515977917188119889 -0.01519512535015960994 0.01134698594789500248 -0.00276902816365899888 -0.01341278181279694642 6.535853401789164057e-05 0.002465644192952843282 +'MRT42-1706' -0.02152130408445456292 -0.03205011379447719744 0.0009744124587214717447 0.0006857491666887961584 -0.002992507465501631752 -0.002249384464828016027 0.0002026534437485450564 0.001707255060233871247 +'MRT43-1706' 0.09889795875194561103 0.003888088698199017312 0.01979261571006893025 -0.005854555830175177736 0.002550630691211766554 0.007814062754916960632 0.001534605528027466453 -0.001740738529028019663 +'MRT44-1706' -0.05691008159632153507 -0.1645107481226831536 -0.04779496534737437408 -0.004393966613594979531 -0.008692954536789214773 -0.00741345907509721215 -0.001635450184394400455 0.01400487427236647882 +'MZC01-1706' -0.01494286518344861876 0.09399604291418038604 0.001514042424394920847 -0.0002662129026606222925 0.00272306583656161446 -0.001462974992030099041 0.000286755318048692229 -0.002427846703108969481 +'MZC02-1706' 0.01048523110613878463 0.0009020160280337854216 -0.05016703820507201206 -0.0002998510518858664388 -0.000515313659549525337 -0.003264881453735892902 0.00102562807721430743 0.0008618217559544430603 +'MZF01-1706' 0.01968281285050175675 -0.06023107763614371502 0.06121508202898146705 0.0001622292073713806819 -0.003467093553142917405 0.00172970768133278211 0.0002289916838627152932 0.0003681591649551428712 +'MZF02-1706' 0.06678984472783246196 -0.182440558735761621 -0.09178606635743639941 -0.007584419234038608168 -0.01038819388683161551 -0.002998489417295726635 0.007930818537335527704 0.004545979240750585605 +'MZF03-1706' 0.05325156675761270192 0.1174738411772354302 0.02751730704591508897 -0.001211262822488221903 0.003903677346005184935 0.002496012419996640041 -0.003155274508161381476 -0.001828277363740007846 +'MZO01-1706' -0.02439720069461531055 0.06592929524778615158 -0.07484527118930360545 -0.001991400967305742824 -0.002043057608432549601 0.0009466362350490286834 0.002905927484150935911 0.0003895711563017285189 +'MZO02-1706' -0.004193409439129229879 -0.03588347742750992719 -0.01056765234081206463 0.000828269113155421957 6.357854193919900885e-05 0.0005194924160432156995 -0.0005895915780497043351 0.002171980319106391489 +'MZP01-1706' 0.03381324548225054377 -0.0969433821121011563 0.08366330975129604441 0.002633418695614468154 0.0001724388743565483367 0.001263530525531823259 -0.004448313057072220827 0.0004818693201072772776 +'MZP02-1706' 0.002633998031293571709 0.1230252286459674327 -0.1066414172307003361 -0.005316138877684267912 0.0008464339200343246094 0.0006126163070335105586 0.007819364143145711085 -0.001852859759265136543 +}; +coef(end).label = temp(:,1); +coef(end).value = cell2mat(temp(:,2:end)); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +coef(end+1).name = 'G2BR'; +coef(end).reference = {'BP1-1706', 'BP2-1706', 'BP3-1706', 'P11-1706', 'P12-1706', 'P13-1706', 'P22-1706', 'P23-1706'}; +temp = { +'MLC11-1706' -0.1382228139973263881 -0.0662533451338533641 -0.08514893299283234074 0.2886713463945499991 -0.03145826574391359653 -0.1032094036312776741 -0.2677078788695917422 -0.1726664652951542811 +'MLC12-1706' -0.1725242892252873694 -0.02316799131720484115 -0.09864268844080101295 0.2708002617960945102 0.004966079429890845123 0.006366494614789523429 -0.2078166773781876531 -0.2548113407111339268 +'MLC13-1706' -0.06433513939400752057 -0.02469987208653662281 -0.1547419125782673044 0.1418973878845695979 0.1154807762403902011 0.1188750122484098504 -0.02036827737249559053 -0.3102419760200211818 +'MLC14-1706' -0.0101725826309732939 0.07652184257691851954 0.06285597934187520108 0.02169242670745954657 -0.2582685301006519274 -0.1754755617201763096 -0.0770185861151197193 0.2127978003944720475 +'MLC15-1706' -0.0234806731320204784 0.02967070404938945694 0.04419021236823218041 -0.1472778785094536191 0.3208338160851761933 0.1096039676317745737 0.1155024694090843046 -0.0999885415781458925 +'MLC21-1706' 0.08743625635265907248 0.04198538522939099238 0.002595763142494787734 -0.2948187247460258842 0.008232970318121625442 0.02056178412134233163 0.2672628912666229484 0.1725954757795352679 +'MLC22-1706' -0.1860618882723089618 0.01115782510601683909 -0.07663727931105152047 0.2479503631283714593 0.04773637890704240938 0.08225074763523326782 -0.1824246449791908642 -0.2695854761088272711 +'MLC23-1706' 0.09932052461823512313 0.02459404557479431819 0.1243893787964647085 -0.1214521353695743461 -0.1467888516667933962 -0.1954673507175130331 0.0827014306951008582 0.2565056823171180667 +'MLC24-1706' 0.09542051075649532477 -0.09846890209426244212 0.1029865957655926867 0.04568292306962887933 -0.2578532484170544814 -0.212186495553021659 -0.026742951757970361 0.20175432492741463 +'MLC31-1706' 0.05360363065430327062 -0.0290658497723569817 0.08444762605308975267 -0.2746546031050620673 -0.02850152883999820461 -0.08464483138426905084 0.2478561306001653697 0.1935575302880424842 +'MLC32-1706' 0.01417751084994100727 -0.009609644382386633293 0.1893266810670302669 -0.1537872939301765385 -0.1114998313699658156 -0.2384590696179459679 0.1708144723346288196 0.2018385584725512771 +'MLC33-1706' -0.07741406054111449331 0.140602962564341849 -0.1613843832943822887 0.1657525588942669881 0.01936887116091059666 0.2843437265599630948 -0.2427637099503201223 -0.03446355440781331131 +'MLC41-1706' -0.05205615869574087978 0.04122180525868625323 -0.2040984775909389648 0.306050945666863472 -0.004845563660082926466 -0.02656975327913183027 -0.2965742741062059595 -0.1030378866416584993 +'MLC42-1706' -0.02389402919451669161 0.07844658973459740781 -0.1838052010794586355 0.2877669212562368739 0.01362667991036912302 0.1231018548508429622 -0.2956834717016642577 -0.06702306755529127691 +'MLC43-1706' -0.005209111846768275933 0.03384509470499676154 -0.198775722190652343 0.233533809231346895 -0.04116800311516879973 0.204014512418244004 -0.257621450547025066 0.1104885236548849847 +'MLF11-1706' 0.06358350010679529596 -0.0784445226147908875 0.07465856520074432012 -0.06599042869640468767 -0.2771210257315528946 -0.006568449735539011285 0.2547869704665173263 -0.02066346292026897263 +'MLF12-1706' 0.05193664472756427675 0.007433386036594913024 -0.004354256429245254717 -0.0104594934129525613 -0.1185032398077054266 -0.004922107449456929358 0.3094693534941974078 -0.03052891107477028951 +'MLF21-1706' -0.094404553516449774 0.05713796765517231008 0.08266203354542170367 0.09905781386387088605 0.3179322781523764574 0.06462239355808441221 -0.2089744688446816823 0.09630895339785545961 +'MLF22-1706' -0.005401466460099793067 0.07799861220626723435 0.03423511561012176907 0.02010940732427979327 0.1913544074894210911 0.03221201176237215025 -0.2826473303848106022 0.09805244526818387985 +'MLF23-1706' 0.01742441361442586059 0.008819523871757835309 0.09118678122227265315 -0.00035833527450891895 0.05733828285980938771 0.001937081080728298614 0.3197619531956262806 -0.02787631604312304501 +'MLF31-1706' 0.04654583340223795995 -0.047033385721240481 -0.03064091442360981216 0.01509156098077189812 -0.2121415682595462204 -0.1112084492731538476 0.1523790428804583652 -0.240462429525251653 +'MLF32-1706' 0.04746952247722049933 0.02258704023958208601 0.02194903989996015853 -0.0414873715701736534 0.0450056070330318303 0.02014421752427554557 -0.239552750474094106 0.2240642801760762137 +'MLF33-1706' 0.05869476665463646547 -0.08361178423739487608 0.1122550523316090815 0.01652918328603633635 -0.2009617190249260721 -0.03349511899062078413 -0.2660305009062145509 0.1264355272430096322 +'MLF34-1706' -0.0218949579017706196 0.04946250378941413617 -0.1116108859354522365 -0.0491185333376887856 0.2506667734195127117 0.01359099838777923404 0.2722985984247927593 -0.04207272814955062556 +'MLF41-1706' -0.03942545908135971361 -0.02407661327905865484 -0.1064493759388815408 0.1087447642448455681 -0.1595908287940409898 -0.2032976679415572085 -0.06620409544320542128 -0.2639041423904764372 +'MLF42-1706' 0.05363422328221816027 0.07967140221233734443 0.08951534003717770416 -0.128937214577220377 0.08810343302557513412 0.07615585441940531108 -0.04098182085352847226 0.3213350654240125781 +'MLF43-1706' -0.06803485675123928378 0.02096578177021040518 -0.07395732983967347185 0.05434491795285490562 0.1411017643030943458 0.07179673034290874611 0.1643525586201984023 -0.2682898473340409873 +'MLF44-1706' -0.06260930679826015588 0.04295959449824775928 -0.07156891208540423766 0.006612428169781000946 0.2081223075433809855 0.08387857375424689899 0.1932466340951884409 -0.2172583991596181707 +'MLF45-1706' -0.05273449228516488563 -0.008524618559531807471 0.02247780394187684841 -0.1073240959812722661 0.3276726083020715108 0.07029252766680937903 0.1898373308456635378 -0.09345150444010934254 +'MLF51-1706' 0.1624317912595521218 0.08610496267367034884 0.2761220436858867755 -0.2291957786065656477 0.06302140921111969163 0.1150472021390444161 0.1585149441735389519 0.2768588909419009703 +'MLF52-1706' 0.07813537475270850019 0.01258956549997311894 0.0704459322986105696 -0.1925680107901989457 -0.04418983798888989623 -0.05323237435557155728 0.0706631643303960999 0.315963044331685039 +'MLO11-1706' 0.001623072866654050317 -0.0505657566297947822 0.08349523534917566159 0.1933396783320261991 0.3210745787150182107 -0.10751155424449374 -0.1046291748235521901 -0.07963442963719634393 +'MLO12-1706' -0.0932543347501357256 0.0816296319231611528 -0.03166616724170764202 -0.270890689883850011 -0.204853914567168699 0.1259003486000364325 0.01927732627214839151 0.04117169739736232376 +'MLO21-1706' -0.01017560646354364814 0.01985941627204387133 0.05514742758507345383 -0.2571367677595031709 -0.2793730885099177663 0.02122191927113283028 0.06579356396974349319 0.01006261887051268511 +'MLO22-1706' 0.04228339699326733037 0.01212366091993068162 0.08879376494519121421 0.3260521580611809855 0.07925669214609561142 -0.01819740163416505921 -0.009591517815856168139 -0.003271903174406161872 +'MLO31-1706' 0.01883014372343630102 -0.1412157130247556902 -0.03076257068120249322 -0.2120135195069595135 -0.3234457946035887432 0.01496756686803598843 0.114501508697362378 0.0212206696608342113 +'MLO32-1706' -0.06075735201504169763 -0.05558799106456796535 0.1118396305158921855 0.3025245377843828187 0.1916345478112770895 -0.0186420866884403659 -0.03524606438421783866 -0.002627656002018843341 +'MLO33-1706' 0.04693372383741226117 0.08044034771046811028 0.0653618770327214077 0.3384757636250301793 -0.0258698388823904446 -0.009578034291444910767 -0.005871694612373942572 -0.005290584850912462972 +'MLO41-1706' 0.03923384480471365371 -0.01525029131105908736 0.02714999417571031803 0.2546115164329926239 0.2690482753680357164 -0.009767390421729766486 -0.06730807681393313757 -0.004156501435087131199 +'MLO42-1706' 0.001428077299708022108 0.003844081474509456094 0.01959334188366524537 0.3214212593155210129 0.09069845192517340948 -0.009534190431742349883 -0.01124799407868778967 -0.003469786724388063733 +'MLO43-1706' -0.07099233623833486884 -0.02880924754568231147 0.08856351332414597044 -0.3060528484596556353 0.128839616138026275 0.003165219732926745702 0.00994938826448356177 0.0006090051591933717291 +'MLP11-1706' -0.03249607645747909501 -0.03205139619401013718 -0.02829538554438305181 0.07148907765356921074 -0.1146178887559892168 0.2960008321297108447 -0.1589520302232046711 0.140935032443428615 +'MLP12-1706' 0.07426184295142532199 0.1492185896179328841 -0.05111344519783470042 -0.06136746941840764275 0.001724787166957722582 0.3282088611462577465 -0.130134171293704165 -0.004936585729251252545 +'MLP13-1706' -0.1550668393682321788 0.1438313884956307909 -0.1629892686117093148 -0.0394500456953563311 0.1701208339783343848 0.2852099729622109003 -0.08313554870547654185 -0.14560583845332567 +'MLP21-1706' 0.02654843949261885203 0.04836841501601622101 0.1462326737279008859 0.03725154422432774837 0.2241878770131820464 -0.2473136379978512212 0.02254832068650799645 -0.1907638261900793664 +'MLP22-1706' -0.0686176390587671936 -0.02320309969255752308 0.001400987193962166446 -0.09754388151307355481 -0.1665353760105017233 0.2813326097644027191 -0.06635495897286450284 0.1135272370178197487 +'MLP31-1706' 0.00410461651847717629 -0.05408423003028114961 0.1377390235016080489 0.1692504652513706909 0.2497298125801123425 -0.2136456344231150439 -0.02055520016833128211 -0.1160272495532611442 +'MLP32-1706' 0.06336749823488235789 -0.05042684966902965388 -0.01654673930951551519 0.236575211873756186 0.09534624686072780408 -0.2177310220670032048 0.03421893273639377286 -0.03397234014568384364 +'MLP33-1706' -0.03323736611209159725 0.03002182472506493074 0.02689757791333211023 -0.2207079389025662641 0.128711273619539962 0.2266871851504149993 -0.03736291801907636045 -0.05088352815167572485 +'MLP34-1706' 0.01804484165856728647 0.01031036791405627942 0.07549176520119624256 -0.1699046426367207818 0.2899420145878607857 0.1446179218179321768 0.06650532942325219909 -0.0992577900696323262 +'MLT11-1706' -0.04704491941066894084 -0.03797941156058894097 -0.07737316306722230586 -0.0371319234728271913 0.2231138592719367209 0.003212535244369423872 0.277973060208098588 -0.02185444193729014356 +'MLT12-1706' -0.08447872404705902838 -0.03003933274360280972 -0.08427636400014384965 -0.08897256645086894233 0.309660363262441618 0.007748120488902505119 0.2347308524974138499 -0.02053834692366506356 +'MLT13-1706' -0.04155250655432526918 -0.01767708282357837238 -0.005058913529922428806 -0.1744857916782741325 0.3460584289539624936 0.01625148968725365073 0.1543297160145147839 -0.01757610927126036088 +'MLT14-1706' 0.02473601543887470749 0.09954298179551401837 0.12087844240992629 0.1964107424914252886 -0.3303216413858801603 -0.01522956155732175729 -0.126241152957685121 0.009533979930416870002 +'MLT15-1706' 0.09975884082223460125 -0.05496818271985834392 0.04251169561728222746 0.2673987405566053965 -0.2452043039081176767 -0.03954824050132876162 -0.04696591748658365123 0.02039530731989156603 +'MLT16-1706' -0.01809030105728349699 0.03788238383809146292 0.0911475289757280871 -0.3155033569353283829 0.04735155161616331349 0.08297294674179991891 -0.005384807996269442947 -0.006461459956578846642 +'MLT21-1706' -0.1288538542114405494 0.002481952925272324847 0.03485703117358385922 -0.009551033352974021978 0.1422676410576970696 -0.004939041608370217835 0.3031750340360210294 -0.02265133277841845094 +'MLT22-1706' -0.0237058575720274084 0.04512844725750929376 -0.006987253626539095472 0.05103612862324776595 -0.2530604354950670154 -0.009800139935999267055 -0.2678564659799040348 0.01978457309890234092 +'MLT23-1706' 0.01363484305779106079 -0.03864465828962739685 0.02261442090285450263 -0.1509838934441197489 0.3446303859724349494 0.0201338703042538876 0.1770152141325894435 -0.01924419428211009142 +'MLT24-1706' 0.01393201296458278921 0.0305976414413392378 -0.01880820659807747042 0.1839983223451140404 -0.3361884590426196251 -0.01389905054059030476 -0.1375696812691714344 0.01182448961353790157 +'MLT25-1706' 0.06463614949607772442 -0.009091585275117273698 0.01958275607012524913 0.2400990650349234534 -0.2953646988618118252 -0.01301339264680832254 -0.08030090445001912547 0.008743103831794342071 +'MLT26-1706' 0.08681852359305899935 -0.04323256250900678332 -0.07327380800820051943 0.3092413470854838975 -0.1484321325726151719 -0.01074461506969169935 -0.0151504182588766325 0.003048914048373080506 +'MLT31-1706' 0.003035953703011757404 0.0646580228454244621 0.06415362135829164036 0.04362663534979851349 -0.2322643812263140428 -0.004476755280500705793 -0.2705967667099912766 0.01602903942775381341 +'MLT32-1706' -0.03739804724905297639 -0.07804379670670040514 -0.07195296403668691165 -0.09604611440909098519 0.3052418652000546406 0.006742533954966011857 0.2313814044002251435 -0.01405236708920687763 +'MLT33-1706' 0.01828050731997953038 0.07289809325464820244 0.00657024311860331979 0.1769381056866486668 -0.3549014141525700383 -0.009858498387001077279 -0.1586977712752264957 0.00536515252067098266 +'MLT34-1706' -0.0006301953427265624685 0.03576772048592252035 -0.01198610988375524086 0.2152738178167998007 -0.3307915708951239542 -0.01134930826208157238 -0.1127700732372116377 0.005556709078458120163 +'MLT35-1706' 0.05334568942542123465 0.01680234893714786792 0.1533550635366545123 0.2992700536244244369 -0.2357057131142628326 -0.0111909195602401014 -0.04976395803997243211 0.004429677610622913264 +'MLT41-1706' 0.08651884553088011465 0.01301954871435762398 0.0461874236875364913 0.05370947177516879889 -0.2573876221729367031 -0.0004022934679234792255 -0.2578139585112749765 0.0181297648629859115 +'MLT42-1706' 0.03185784436153658861 -0.04740810871268212601 -0.0697960927546261295 -0.1473082410533657349 0.3355281876026416366 0.01029525218719577404 0.1834483212803902363 -0.009071629251501650559 +'MLT43-1706' 0.05372747600040422844 0.02026929145742300403 0.03885607146340949031 0.1801580011202781884 -0.3276590704776112251 -0.007393763903438013881 -0.132827908291525465 0.008161154239529398377 +'MLT44-1706' -0.004786981027231705654 0.0351094683864824203 -0.05814207825039392069 -0.2452282195270626131 0.281805606880582149 0.009707600877972163977 0.07841898469102287494 -0.008444893768065512424 +'MRC11-1706' -0.0007879057259526575652 0.0562766694771630327 -0.1606509791041782764 0.2625214587867037985 -0.02943882930227824379 -0.1765816276048170208 -0.2781150695457602628 -0.1126389196907389145 +'MRC12-1706' 0.005041312833811165128 -0.06072117216660291583 -0.05206699265535509602 0.2086495590651812615 -0.003767579200974270279 -0.2391770468357752033 -0.2618243726129056981 -0.004602653674354887856 +'MRC13-1706' 0.0210067559732514085 0.01087679324347014254 -0.05049581465957574122 0.01484813121440720085 0.121673549590438107 -0.3081245755028024225 -0.1336690921949419963 0.1230624412539903928 +'MRC14-1706' -0.1626377966401037489 0.0734525194434082207 0.1031786964687588237 0.08959637570570466725 -0.2602790116005987975 0.218979276625638819 -0.02874054868554443143 -0.1788435128919033945 +'MRC15-1706' -0.1843432827081813996 -0.06793325587954066047 0.0206622197920528633 0.1270255143763397709 -0.3312232160428612571 0.1019088645291856693 -0.1542841425969307123 -0.1151075077535118479 +'MRC21-1706' -0.1624387619387309689 -0.05665387335815671999 -0.1797641205371675044 0.275760674553589713 -0.006878584310087037731 -0.180999150896493266 -0.2951779406261597072 -0.01604416014587845343 +'MRC22-1706' 0.008115207652171683994 -0.02539517701411761474 -0.1537991189617910759 0.1807428031374978261 0.04658037739398068755 -0.2681088102671762563 -0.240935352738834152 0.08616231667606881472 +'MRC23-1706' 0.1373696362710403462 -0.006754250254273726044 -0.02322382248563889875 0.08395796000441761719 0.1489590287865106 -0.2543618894601860636 -0.1241346125955813534 0.1985899454334250913 +'MRC24-1706' -0.1322683152887810243 -0.1253515894290049559 0.1446953244022337604 0.02769056553012722716 -0.2584609775592148773 0.1966702959277972507 -0.04996274691785355243 -0.2170447783805828645 +'MRC31-1706' -0.03351178862986126106 -0.02502474764367358315 -0.1354577267289230336 0.2487483637503605793 0.02800565614940635217 -0.1888168006782719177 -0.2715657568930669452 0.08482959003495658956 +'MRC32-1706' 0.09422505621642351947 0.0974268035931084575 0.01434750330881125191 0.1759475490781015061 0.1147891059968733918 -0.1882355818634162681 -0.1525823291225343881 0.2385474019058428652 +'MRC33-1706' -0.02743513551602546133 -0.001346386555345108205 0.1040961934368644787 -0.2389427230023080662 -0.0210474394704532955 0.03072307783726403035 0.160168753914748635 -0.2825274975756738027 +'MRC41-1706' 0.004069615769342165013 0.01524889356876139163 -0.2066967427690987735 0.2944317960398715739 -0.005128244934604534074 -0.1038586236046362271 -0.3021520579721332367 -0.02904603565774256657 +'MRC42-1706' -0.09261069535108770734 -0.05391463190176774833 0.07393599397715618082 -0.2967904418944345424 -0.01839631920055650668 0.0676362606430673946 0.2893330539464480933 -0.1241483698974569644 +'MRC43-1706' 0.02121592901906437303 0.002736008405995041248 0.05867749995983034123 -0.2599204191479295711 0.04181595136570286086 -0.1132943588742273827 0.2334756974634588367 -0.2026394493973507904 +'MRF11-1706' -0.08237912727941071322 0.1930170658866355027 -0.02999511644876571778 0.2560554149778885846 0.2816132118458873901 0.02238669585085677899 -0.06731832491388607675 0.003857697094186068008 +'MRF12-1706' -0.1452633744918867542 0.0413703610092215554 -0.03966250163167530512 0.3163134685732207907 0.1070690457748723207 0.02720564582295028136 -0.007841875063684807315 0.00389592610458493584 +'MRF21-1706' 0.09178898921567094082 -0.07326030686495163535 0.08279190922802177888 -0.2031894200380436055 -0.3079692909353750618 -0.0900654060700137038 0.08916715451558471228 -0.06269989707734738293 +'MRF22-1706' -0.1201093945905412491 0.1666597350767906605 -0.1266918845073792821 0.2800702632171455653 0.1963824608020995344 0.09204699582438576055 -0.01677482812683377122 0.02336377569770818619 +'MRF23-1706' 0.1020462997170876462 -0.04476148723999442275 0.1125374056494373165 -0.3225737173313791839 0.0573288654152874777 -0.02539360876236581438 0.002355324897689480695 0.004255860165688138755 +'MRF31-1706' 0.04460755158466561676 0.03889906756587595271 0.04177857900706357513 -0.1552087321145515231 -0.2052526905362134779 -0.2388507361215514435 -0.02003904756496036055 -0.110713764729872155 +'MRF32-1706' -0.1130533484546892981 0.03040892813732698485 -0.007850927498421034212 0.2429085798779209715 0.04094478195904468348 0.2200857368082461407 0.03784565422790188427 0.01452989250527078439 +'MRF33-1706' 0.05205094682228531 0.004683024081423316914 -0.04904272170391472258 -0.2709531288968970997 0.2013610811022400471 -0.1260709754696639762 0.01923096933089796581 0.04400575957673252131 +'MRF34-1706' -0.1976976839368163597 0.008096467905396718956 -0.07168205328873483717 0.2845413282209070527 -0.2524060671096146069 0.03109573688763932892 -0.0492872162319630755 -0.01768523987644998047 +'MRF41-1706' -0.01709039766296914162 -0.1242241645463833533 0.05760983901736607682 0.06728767597205795314 -0.1646797689443417756 -0.260967487800225495 -0.1096413467969140909 -0.1927757931200057839 +'MRF42-1706' 0.01785010709892954212 -0.02780013680753913585 -0.1056340188579661943 -0.04193121114594819399 -0.07854366550232408373 -0.3264883544679060834 -0.1283969803927337838 -0.06592678160634457551 +'MRF43-1706' -0.1460013779933039824 -0.008416346706667056365 -0.03687283923864802943 0.163355218596175078 -0.1412543970141160177 0.2692111348867542997 0.05720260391292623925 -0.07662781704671199623 +'MRF44-1706' 0.05257004161810163723 0.09384741603594291826 -0.011268845423295204 -0.190943968764359373 0.2101659028426117737 -0.2186085251700451426 -0.005747623259752606892 0.08681586790408382659 +'MRF45-1706' 0.07199443390726908976 0.007034553280036182424 -0.06714184252894038474 -0.1840608704768749992 0.3227559652076311125 -0.09959805645941838259 0.107333823150499913 0.07921069084164619745 +'MRF51-1706' -0.00913693632605947631 0.03027867128393653406 0.1652189968253011398 -0.168070378189555808 0.06081735921405818923 0.2681085377762136845 0.2261921790313926039 0.1069252315962646721 +'MRF52-1706' 0.07649395040977598204 -0.05309537920131012639 -0.147506915141427275 0.06143852183256792721 0.04835541207699078914 -0.3203646898990325509 -0.1854305377398010046 0.06147484919150039695 +'MRO11-1706' 0.06910029908177262037 0.03545983650013832811 -0.02158888727785019529 -0.1020278751344255996 -0.3175560286413296462 0.08403824520574382229 0.1853070260950459291 0.1048268365378309114 +'MRO12-1706' -0.08793773769676554997 -0.0171440733558369876 -0.1298907460213891141 -0.02076220236820512655 -0.2090988154049477077 0.038203607832962512 0.2714144291478555182 0.1368635910393601052 +'MRO21-1706' 0.0438694744555706076 -0.1092273371107565227 0.07793492706636623302 0.06955358762672385342 0.2774552828328116227 -0.005840745098776823144 -0.2636923358538589834 -0.01961517797204404695 +'MRO22-1706' 0.03997476187009500748 0.06355656022146444206 -0.07888175138367259365 -0.01117412174041480799 -0.08469174072528504182 0.0003682080590293678422 0.3274628421764786967 0.02126712273219566809 +'MRO31-1706' -0.03620589722182501746 -0.02987930659140425327 -0.06213334914691368005 0.118407085133361456 0.3259932373850928933 -0.01070798936638819171 -0.1976188461788445094 -0.009302204064925326948 +'MRO32-1706' -0.09094560252909791864 0.03158194181827086999 0.0230778135580117158 -0.02822735310259225777 -0.2018575532181628718 -0.003045371570343902157 0.2842089016990146377 0.01019822220958127579 +'MRO33-1706' -0.06683738042582462735 -0.08101546494756467487 -0.09737747036912622334 -0.004012321966511324216 -0.01612191771294267661 -0.004108697475914506285 -0.3127554768216350145 -0.007036500232096088228 +'MRO41-1706' -0.1225363074102404359 -0.006166923769823740714 -0.03533575305960776763 -0.07596378520017350866 -0.2911935506207178892 -0.00211488118868098391 0.2517530950482770313 0.01466944197950798695 +'MRO42-1706' -0.1056737531664330432 -0.1792631923173793884 -0.1301742665729932191 0.001986541658350563823 0.09561490736448920169 -0.0066325803334242317 -0.3050403144744178174 0.0006606828106451717586 +'MRO43-1706' 0.01417578775829909064 0.09833592717382419468 0.04164056376765437606 -0.006287842766885024318 0.1151264732907840288 -0.002040487800555591986 0.320971392498041852 0.007277238339984764409 +'MRP11-1706' 0.07937136737516901908 -0.08194471897082386547 0.00911682031052066591 0.1623852560418392044 -0.111313111170271109 0.1443868143757177369 -0.07907093939012151129 0.2945295122235159768 +'MRP12-1706' -0.06666497082207931135 -0.1396905727416886678 0.1547207712218562903 -0.1268877644416627481 -0.002864878921118730291 -0.002126475673897641316 -0.07116602560667395494 -0.3271894550938625468 +'MRP13-1706' -0.07270631909909819335 -0.03602690840902320751 -0.0164057944139923105 -0.08076570241445495124 -0.173085186979941491 0.1360476641012798305 -0.0500671400106301942 -0.290216626621441931 +'MRP21-1706' -0.0313210310086282015 -0.1285000062876426319 0.04184803149379558856 -0.01984220168867284473 0.2310851181898425089 -0.1972613619388189354 -0.03632270041376398084 -0.2445844123905571987 +'MRP22-1706' -0.002997104464619428435 0.07090456386015700496 -0.05100851650664366133 0.06356271010231347163 -0.1725637712268349444 0.1194692718967358541 0.09891304721593767446 0.2830716257311182149 +'MRP31-1706' 0.04405419856043098215 0.0641848636923310345 -0.01402512920915510719 -0.01486844389148727144 -0.2464546592395191749 0.1185010264911498246 0.1632689096493861458 0.2096961493572045143 +'MRP32-1706' -0.06877166500509926395 0.006233115323576100819 0.09947401374409642338 -0.03169758388264812266 0.0937861738658565397 -0.03664328933815391709 -0.2348250697569170542 -0.2271607089027971038 +'MRP33-1706' -0.08348282514167326696 -0.1002621734012028726 -0.03903049761368913156 -0.03219885497932736124 -0.1309134925510340997 0.04797249600258152169 -0.2240468287700749517 -0.2235606873069985734 +'MRP34-1706' 0.1102335224006878445 0.0674893320915589956 -0.0362946234611954896 -0.06044850207409657034 0.2918716097737355519 -0.1104362190697510127 0.1708385718994873403 0.166809603947957602 +'MRT11-1706' -0.09724202022874177398 -0.0266421507343533176 -0.07346252924992914546 0.2814838508913077297 -0.2369801585956532453 0.02309369494145910653 -0.04459200365448148795 -0.01055945544159708413 +'MRT12-1706' -0.05477609482914039263 -0.07194231399418909989 -0.04692024281487688908 0.2324165281391495363 -0.3111608025536575783 0.02185111493173206437 -0.09323331910843153658 -0.01289847086245934048 +'MRT13-1706' 0.1162633777079926378 0.05780624699812348527 -0.01320501685296877371 -0.150016634394035453 0.3453118415347369297 -0.01812276141472254562 0.1728871060513144653 0.02315320445571670063 +'MRT14-1706' -0.1496256195776213826 -0.06140460254194054363 -0.1801318994229649251 0.1172643247767564817 -0.3332825172831100358 0.003537356988004568964 -0.1962557573038295755 -0.01467816124316543083 +'MRT15-1706' 0.119490999552530161 -0.03599166467948063108 0.02183327665572958043 -0.04806332050793390293 0.2414056247054576221 -0.01658593971100207759 0.2664400348178166955 0.05057478668619069806 +'MRT16-1706' 0.02175309419387837923 0.084375275879240208 -0.03613428540213743656 0.005626728858434142458 0.04146685838633926147 -0.007051845557262325856 0.315299000799203144 0.08658389162536425654 +'MRT21-1706' 0.1463749447859550301 -0.0235627441911108633 0.09262713635230909737 -0.3023789453526899984 0.1428117279667904249 -0.009330073693726185363 0.01357467794683290575 0.005972394680508323096 +'MRT22-1706' 0.08422035136889689799 0.0789029994625845138 -0.003252530594576027306 -0.2693273626473119409 0.2611653767122183445 -0.02174595929537247521 0.05562229119176472641 0.009254512600153278964 +'MRT23-1706' -0.1183053200091673529 -0.09302657996608576507 -0.02983563402352337052 0.163010356482950175 -0.3414084521263605621 0.01478154579731901126 -0.152166811190382778 -0.01694922609353283899 +'MRT24-1706' 0.06583217289102817615 0.06941352606434744721 0.05945343675901655633 -0.1332480194203361223 0.3392049016656066285 -0.01362908105734855421 0.1843278244557821632 0.01700873787986762614 +'MRT25-1706' -0.1304404148548278242 -0.03214403094818506224 -0.09001738513111527673 0.07935870145132037368 -0.2986573684359518643 0.005418417012691698412 -0.241396878132969589 -0.01942165439417802356 +'MRT26-1706' -0.02448222236607095967 -0.07643637496156417688 -0.05322533974201267004 0.0127777153965803348 -0.142747401947125957 0.005982426083731508595 -0.3100952414431430437 -0.02078201285639674073 +'MRT31-1706' 0.07692244832144835842 0.04967357141473870141 0.02972370623778024593 -0.2705460344428185504 0.2444622817749315391 -0.01571775585169138401 0.04798050829488970798 0.006170086987540743598 +'MRT32-1706' 0.1183911930836422099 0.0482654932379635096 -0.05341813265657303911 -0.225417551116335324 0.3133116461414766629 -0.01760852795563047288 0.09827031357259446986 0.01382081992302661155 +'MRT33-1706' -0.02815371106508243737 -0.03849285530039202319 -0.0003594739829390451724 0.1507070338960555256 -0.3507640005420725737 0.01694738408302787561 -0.1772428377477041628 -0.01809253676490350446 +'MRT34-1706' 0.07085697799770632188 0.1218407577082802618 -0.1052834832714291263 -0.1135059758618555958 0.3284512121353261871 -0.01542467793972079546 0.2237094080081143965 0.01676752280198122794 +'MRT35-1706' -0.06178363145406416679 -0.09394381670895736447 -0.02218072427506302333 0.03809605516504455114 -0.2284367959451374108 0.004675721833080008494 -0.2860160016107772263 -0.01291155128013030118 +'MRT41-1706' -0.2115151356661075233 -0.05501128622833940246 -0.04057452668981493399 0.2597146532565894339 -0.2630025835447360461 0.006269429510887616908 -0.05873148654871722385 -0.007377544951544463651 +'MRT42-1706' -0.05579057156662327321 -0.0573997182103033049 -0.01397743666484975444 0.1638150765639064532 -0.3321591429085127833 0.01508810360484356614 -0.1442835524886325327 -0.01457792992863648704 +'MRT43-1706' 0.1319017205133816983 0.02875515346517001566 0.03197787686309716548 -0.1317679035492529682 0.3280014936254582736 -0.008766336198923136216 0.1841597090282735549 0.01790151717898413875 +'MRT44-1706' -0.08602043061594286111 -0.1848864273626642518 -0.05769059101293678299 0.05803921456863097433 -0.2768930705704691353 0.002361448403676739971 -0.2493503123000496147 -0.004156293039720317453 +'MZC01-1706' 0.03943130371279519875 0.08608602734225456743 0.05402486926618242646 -0.2954478994888347088 0.02211216073609953078 0.1005233510682451009 0.2926037510085774396 0.1107799483911513505 +'MZC02-1706' -0.04036240227242930689 0.002172785467835445725 -0.1131188116266274996 0.311275923761081208 -0.0004225813884387379874 0.02581225323545671343 -0.309727525633242462 0.009804524900259885961 +'MZF01-1706' 0.03765554150652822285 -0.08861191470414692128 0.1111432717536282172 -0.1621163164884525387 -0.3429098817724575143 -0.01286304891926058971 0.1568681701625642688 -0.01396450435145797642 +'MZF02-1706' 0.05863624296178021611 -0.1907854574863376285 -0.05986171585472097045 -0.05458698607002626657 -0.2710081004089226475 -0.2046524437756771786 0.0520159679047374271 -0.1950831797372347409 +'MZF03-1706' 0.09979508375523039876 0.1091106033374151796 0.05708088071825111187 -0.2160648488740414819 0.0803112193013833936 0.1939613448658862593 0.2095335402733197738 0.1943378312758658188 +'MZO01-1706' -0.004544257897588159512 0.03445429291455819748 -0.02651131545871721062 -0.1612147099583010612 -0.3466180529484072514 0.02485264483338892397 0.1657024739150892989 0.02461630109363294877 +'MZO02-1706' -0.02343082248434896764 -0.005805140700950898319 -0.05924557023038063558 0.1639879674010855104 0.3386338264572117396 -0.011107079871270251 -0.1554351678562210792 -0.009174248706972676012 +'MZP01-1706' 0.04525024184794872173 -0.06876050086032142739 0.1110612069001668256 -0.1171632509903119262 0.1505173826221477273 -0.2401965713993839402 0.1174918637724963466 -0.2350542652438107893 +'MZP02-1706' 0.01764883535911147827 0.08550704121382816936 -0.08569212950392161854 -0.08000835648493688501 -0.2886321565610597828 0.1867370105823364379 0.08216087195490533179 0.183650843327438501 +}; +coef(end).label = temp(:,1); +coef(end).value = cell2mat(temp(:,2:end)); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +coef(end+1).name = 'G3BR'; +coef(end).reference = {'BP1-1706', 'BP2-1706', 'BP3-1706', 'G11-1706', 'G12-1706', 'G13-1706', 'G22-1706', 'G23-1706', 'P11-1706', 'P12-1706', 'P13-1706', 'P22-1706', 'P23-1706', 'Q11-1706', 'Q13-1706', 'R11-1706', 'R12-1706', 'R13-1706', 'R22-1706', 'R23-1706'}; +temp = { +'MLC11-1706' -0.1419916047814387405 -0.0910501741939442194 -0.06916984619594829242 0.01582197324380207881 -0.1271590546758249451 -0.1267036205378564429 0.0004875643762199514692 0.1553849119195069017 0.1435702075034691605 -0.0336545736392792616 0.0870987680252153923 -0.2676172006473142018 -0.171702271802850831 0.1427442097545613131 0.194025562705910537 0.01614314639917840272 -0.1260325976584864283 0.1239975004790138113 0.0005000413491736438888 0.1596441791706937618 +'MLC12-1706' -0.1710040203261259384 -0.03600161613011888112 -0.08999022050706914633 0.01248884642270277345 -0.1124402655492882236 -0.1271574666406136978 0.03411953294031517397 0.1797227863480370669 0.1305723839664658381 0.003445429309680184127 0.1238958021446532332 -0.2078687428941256299 -0.2532174183538100642 0.1380636427649603593 0.1213546868160432501 0.01274235982149208267 -0.1114441970704661833 0.1244416533935489566 0.03499266582379075008 0.1846491808655484623 +'MLC13-1706' -0.05358832450198318387 -0.004511719082704659933 -0.1492087599811351417 0.0605016286586212565 -0.1257631569930391935 -0.1001503692237943749 0.1508299742012967071 0.1586186551447117676 0.03236862394435705004 0.1149075250070351883 0.1586322492085609215 -0.02050671303987481459 -0.306666075158129825 0.108100461701926373 0.04345065941277753002 0.06172976238646130792 -0.1246490657387545331 0.09801137018093723785 0.1546897752870647624 0.1629665627693281937 +'MLC14-1706' -0.01904650765169212112 0.03684135059771824483 0.03963929835186085632 -0.1093487419732767779 0.2181662787531701564 0.1067048750363892295 -0.1676036493778315928 -0.0481491788574822388 0.1296004142123039216 -0.2583946281296123915 -0.1329322708903828698 -0.07755973011868458333 0.2088539259955674854 -0.1068856331367264989 0.0387953152374361579 -0.1115684322707398701 0.216233620978427632 -0.1044258856792855683 -0.171892695711446053 -0.04946899954113682246 +'MLC15-1706' -0.02253020830426025189 0.06300694102370001104 0.05740826149007852153 0.1346899799479751025 -0.2169096668428487362 -0.1940277075253118433 0.1246164447953080345 -0.04906055242947692657 -0.2353330290626789167 0.322216306979711653 -0.01222330019337251536 0.1168019034866430994 -0.09661732693310091935 0.08755307115862445699 -0.1185054479409324152 0.1374240767127013485 -0.2149881409478459071 0.1898836880483890655 0.1278054308802857031 -0.05040535484115674092 +'MLC21-1706' 0.08809312315815749639 0.05424853717534677128 -0.01594022930885971578 -0.0101728981277198257 0.121266213840355408 0.08462345590423571429 -0.01073948352851232524 -0.1363452150992110479 -0.1610517699377295442 0.009949352057560777174 -0.1060700303199139383 0.2672276857395401994 0.171610521194374338 -0.131629156049414997 -0.1299899412343137883 -0.01037939966457974636 0.1201919594123496138 -0.08281607873143725929 -0.01101431132983924852 -0.1400825838202419682 +'MLC22-1706' -0.1803744424431386051 0.0103978920890233674 -0.06414299749090723868 0.01940502285778583982 -0.1162944664886920859 -0.08547578161779832706 0.05382627575887366511 0.1671455589692090737 0.1255163524403446751 0.04647349342576399811 0.1637931766816881629 -0.1825759964145527714 -0.2677786353594247548 0.1206264359005969761 0.08498991565678053195 0.01979892899865396544 -0.1152642550091573931 0.08365020057915650842 0.05520371229771226657 0.1717271981818223603 +'MLC23-1706' 0.0886981247646397436 0.003810366734521404564 0.1006580651479679622 -0.05766598589922657114 0.1607503620136247202 0.04714625615989979229 -0.09376239570743730156 -0.1282642176407829959 -0.003717136064622409645 -0.1460160007894806544 -0.2223084582313918922 0.08271621711579957292 0.2540149566740921294 -0.1161658681181572395 -0.0303098903389482574 -0.05883655839127627935 0.1593263315048136786 -0.04613931232552433842 -0.09616181398402456892 -0.1317800775460195029 +'MLC24-1706' 0.08560719286123144589 -0.1348770430057112113 0.07474551100477312693 -0.125233410786655841 0.2120418375627758645 0.08324353993831334897 -0.1262273232795047551 -0.04913717269595265641 0.1733942591603040151 -0.2581087394698355908 -0.1760874504885056036 -0.0273632921371572066 0.198453280299255741 -0.1261577865683032318 0.03218116579810925693 -0.1277755469084348727 0.2101634340428624459 -0.08146563483789175109 -0.1294575324075498135 -0.05048407535139323027 +'MLC31-1706' 0.0500987482419861796 -0.02735769807223535632 0.06579849163392478828 -0.01553865660360322608 0.1140093769461364148 0.05282887866757261103 -0.02696041553437809185 -0.1289073638937637267 -0.1592266946371354297 -0.02719249023135991705 -0.1673192911137738603 0.2479186246518885473 0.1923890980860657185 -0.1136436427442296393 -0.08565909110774679036 -0.01585407866220412548 0.1129994082653313775 -0.05170056609338087583 -0.02765034365843565406 -0.132440853128252406 +'MLC32-1706' 0.006252652104452267184 -0.02362177951341700236 0.1626513132858952715 -0.04564982324737449498 0.1440814812824977309 0.02415936296382304935 -0.05359854357986789525 -0.1113929367632070927 -0.03338708715194392551 -0.1105946824200700895 -0.2799598368290855954 0.1707939858527597332 0.2001659157595109539 -0.1186123350970336582 -0.04467681649317097048 -0.04657647743574978155 0.1428051144828784702 -0.02364337031540675316 -0.05497015235856500537 -0.1144463367472083742 +'MLC33-1706' -0.07366143465773603016 0.1469378697671210876 -0.1316998446411595525 0.01412209615379935931 -0.1333086727189825293 -0.01022295353684249224 0.01504935849746135909 0.09825060065910384832 0.0397152344821374223 0.01818839221103402473 0.3332490428679334427 -0.2427271022110076837 -0.03360985538528847572 0.124051248411041995 0.05185402936493111598 0.0144087631903537499 -0.1321277384139956657 0.01000461297554494991 0.01543447777216925415 0.1009437551013674661 +'MLC41-1706' -0.05197450335552159656 0.0359772116367608058 -0.1795926903567076627 0.01988244371992369322 -0.1252833604830689007 -0.0457079603558257358 0.01728923381336941109 0.1068298941780081585 0.1786148324828609746 -0.006489327604167107431 0.09346221358780322508 -0.2965146011277054461 -0.1020796597069024286 0.1253435150610543447 0.1231077883842362913 0.02028604111499712412 -0.12417351957609081 0.04473173546309879012 0.01773167241881449738 0.1097582162660360044 +'MLC42-1706' -0.02061507166623353232 0.08109286737385959509 -0.1580192733327846488 0.01656068058139405913 -0.1215043242229561782 -0.01901559856324408146 0.01871173732427364872 0.1030471261115278869 0.1703261759821826649 0.01234098306900308431 0.1953109368458957329 -0.2956913735010814892 -0.06611217107531766612 0.1155664856423573444 0.07502857484974280455 0.01689684889337052937 -0.1204279604594251651 0.01860946579068042256 0.01919057837972890784 0.1058717584658140781 +'MLC43-1706' 0.0004019166858968969969 0.03953790619182215998 -0.1680299932043710642 0.009868029794529609156 -0.1330787707995961244 0.0004339782093814935999 0.00624652000196958615 0.1126341307409509801 0.1139697241451518572 -0.04243691560689288877 0.2527325199116586263 -0.2576914403619168237 0.1111783942231928113 0.1177161183973081254 0.05153387254232009995 0.0100683427528199497 -0.1318998731142669023 -0.0004247093571377890168 0.006406371018410765214 0.1157215531843819867 +'MLF11-1706' 0.07735723608690792119 -0.01738528699295514846 0.01418397496548772993 0.2835141285434452096 0.4184122988313058733 0.2571801644327982306 0.1858120765438741329 -0.2505768541680257755 0.001888430616810009722 -0.2712103652738331871 -0.0681329012255057348 0.2551021571535910248 -0.01824458000799288049 -0.06936688782446175094 -0.06413765564584567036 0.2892692341712300164 0.4147057325048982834 -0.2516873426905806288 0.1905670840189512549 -0.2574454347507799112 +'MLF12-1706' 0.03442545171886030042 0.05057023427038630919 -0.05813373524098031792 0.1105977752493197269 0.3096723046656408851 0.1019871710196863235 0.2502963502036379406 -0.3123802107775209835 0.001336988275444510842 -0.1150147235061758783 -0.01036637455374727138 0.3102086813901137052 -0.02733471002058017463 -0.01362416918904570985 -0.006812063723213105867 0.1128428199038061519 0.3069290274247453709 -0.09980894179411715916 0.2567015367681494964 -0.3209428877147308401 +'MLF21-1706' -0.1268772685834627656 0.005949649736367107478 0.1736001171741426985 -0.4110326234407283841 -0.4450615448755212977 -0.1463656539008464652 -0.2004790816535191311 0.1277117342909525888 -0.04934315916644556321 0.3110554671937837967 0.08922805689597516909 -0.2090147071938114332 0.09278378168400806814 0.1481529484599651836 0.02746944518282542699 -0.419376250534446271 -0.4411189023193098913 0.1432395945959478722 -0.2056094238228236559 0.1312124500344445666 +'MLF22-1706' -0.008419324885348912837 0.0329059449847334401 0.1146971455533823125 -0.2306318545931332065 -0.3804860976050700172 -0.07221948264325320221 -0.2749268136987981226 0.1863336475619819244 -0.0229345591946356446 0.1865212757573262992 0.02534075093689022035 -0.2829871771889512777 0.0937519868574891585 0.04447681283733782159 -0.005732640550630002316 -0.2353134931807213392 -0.3771155060593904818 0.07067702797786537539 -0.2819623039562264011 0.1914412528825427395 +'MLF23-1706' -0.01363383436795023024 0.03511401238972383654 0.04905378375186592033 0.0009736977464505454025 0.14445770423352014 -0.06723844698678364817 0.2593321980587697251 -0.2848539139949683996 -0.001522812844420897262 0.05888140632615337239 0.002269152846466814151 0.3207221265656609588 -0.0242967123290697383 0.0002983252188515594884 -3.302288126234842469e-05 0.0009934630167358329735 0.1431780046080605717 0.06580237665711220763 0.2659686156869127682 -0.2926620655861580378 +'MLF31-1706' 0.06559105680007558392 -0.03063318850084134279 -0.1336171515548172373 0.3150584212980804821 0.3345864905540749112 -0.1160809081942632687 0.258151635303991156 0.03705162056756188677 0.0812891278797745892 -0.2077243533413940524 -0.003731753894028506154 0.1523439322089215342 -0.2351863727509601321 -0.06655607189077279717 0.1075807538994045243 0.3214538503470978914 0.3316225073666239642 0.1136016666952461424 0.264757841845599029 0.03806724526456315566 +'MLF32-1706' 0.04618489658673670395 -0.01020751890350296565 0.0936547318547089197 -0.1628208334954506509 -0.19843913476606026 0.1168558808876774685 -0.3248879520424387546 0.03007725148907827717 -0.03016259178434937613 0.04222910542151396551 -0.02534733042481529877 -0.2397468141885754356 0.2181413518056453393 -0.01017241039146943304 -0.04685888874544928695 -0.166125963648873276 -0.196681232771258041 -0.1143600876189334592 -0.3332019683822730061 0.03090170124221458536 +'MLF33-1706' 0.07630712987970246497 -0.1153179660474652202 0.13724466800154142 -0.03537269696642592054 0.04850038357309409409 0.1880516789263814992 -0.2803942145860950919 0.1416521462217149308 0.0410139041089336992 -0.2017949111510445315 -0.001950976326601244412 -0.2669344303698421572 0.1214960006026231665 -0.02444369317934020139 0.029947401589785521 -0.03609073387141992911 0.0480707358570207216 -0.1840352947198254374 -0.2875696178813185733 0.1455349836221378479 +'MLF34-1706' -0.04946549482269909509 0.06799469901144057637 -0.127779459208252677 0.001629783068830295729 -0.088943096646320427 -0.2191691520426225226 0.2068347099188549698 -0.2218835546124507396 -0.04870524820451053311 0.2512222555874852881 -0.03728025575272300718 0.2736337588545251776 -0.0385548765257871795 0.0002582800956461522943 -0.0500963708036415295 0.001662866336178139403 -0.0881551812625793324 0.2144881647424619064 0.2121276952299434027 -0.2279656210503254454 +'MLF41-1706' -0.02787383191243573977 -0.05226992725105554516 -0.1734064800299444098 0.2204933157085144091 0.1313506730949790535 -0.228026764928527137 0.1147121469351524287 0.1599282354340805234 0.1312692650119849924 -0.1585523657340339732 0.03627260666290946928 -0.0662904046036192629 -0.2605955023139146509 -0.02263297759094701211 0.2409629395527505269 0.2249691502238604923 0.130187084015010085 0.2231565978416937823 0.1176476779636214526 0.1643120400603453601 +'MLF42-1706' 0.04336561691321157153 0.08059668561405861076 0.1537679854761040132 -0.165354670914493268 -0.1208521787274865478 0.2045569633173106583 -0.2066159360308264803 -0.1601086322888763125 -0.08721385312678198165 0.08665433275240777555 -0.05555372412110218261 -0.04084335158716150688 0.3165980275222728957 -0.04052167173961532254 -0.1343611760383786879 -0.1687112359013936691 -0.1197815920898674114 -0.2001880613138866671 -0.2119033228281246295 -0.1644973817865984789 +'MLF43-1706' -0.06523554126838097822 0.0548510196592606053 -0.09604484617076336495 0.08426680218549760515 -0.06022131270992513163 -0.1617574179793801747 0.2742141521611269339 0.05552786011046897952 -0.019019120057566688 0.1417248160803924739 0.07654789248214588504 0.1645693699669397714 -0.2628005795767917596 0.07243710950524909209 0.00794187675569257151 0.08597734955745646446 -0.05968783343494646343 0.1583026233049865117 0.281231405116643185 0.05704993836874622942 +'MLF44-1706' -0.06261808353219436296 0.08275240888914309201 -0.07787720845941836778 0.09210766383238704058 -0.1246791214505762607 -0.151907310774808707 0.2615725997192988039 -0.0115668764637563426 -0.05682994331870962895 0.2086433283692236684 0.06361540820889420578 0.1937907870910379471 -0.2120642607603696328 0.06294595618971338125 -0.01736201366289939763 0.09397737430222227739 -0.1235746332831260674 0.1486628934564438731 0.2682663501475544554 -0.01188393696539708638 +'MLF45-1706' -0.0607371648991964011 0.02282404098053832098 0.02643764264989164128 0.09623809236747336848 -0.207882110391500452 -0.2322574879775848589 0.1782620223955120042 -0.1049212834076801021 -0.1541754446311173476 0.3286568099542159782 -0.03141747563205062044 0.1911821347090726375 -0.08949037728639576417 0.04720843316522807531 -0.09915765928942074647 0.0981916471685578135 -0.206040556420950649 0.2272969616377337743 0.1828238208791152786 -0.1077972884254795594 +'MLF51-1706' 0.1609591777651071809 0.1126299177296107706 0.2968988897071070387 -0.07281123413888339335 0.03232580924570688935 0.2033577841285824084 -0.06040591379007709955 -0.1910903584045522685 -0.1263495135440656503 0.06396991961816667072 -0.07414161571549546248 0.1585294164298887698 0.2745824900030534588 -0.1010786546019470516 -0.192654886879311954 -0.07428924282053694927 0.03203944635351016479 -0.1990144940440837229 -0.06195172597275758891 -0.1963283502759360089 +'MLF52-1706' 0.07081954892655731304 0.009071022276967530273 0.07767398954548544732 -0.04774801063907743726 0.08606836170813929321 0.1507367801952299302 -0.1258970579119070288 -0.1943506271689609821 -0.06882832497242824532 -0.04351760466414032053 -0.1316686120697501128 0.07081928798816240767 0.312671084149176437 -0.1219104814058515063 -0.08243724407450131464 -0.04871725632061100347 0.08530591258279682232 -0.1475173629223842375 -0.1291188154133360855 -0.1996779865072808302 +'MLO11-1706' 0.007022250688877448854 -0.0795926653998906275 -0.01027016298806482375 0.1878562755191815759 0.2548295426621260962 -0.2166783789925806059 0.117388835449233217 0.05435550840015292151 0.3128053875747224266 0.3233135538776563678 0.05954731289904383745 -0.104681209538808731 -0.07690453605260665071 -0.1181060813637083845 0.1660187319921619942 0.1916696047314133677 0.2525720980209348876 0.2120505893112736295 0.1203928640378697096 0.0558454512394571459 +'MLO12-1706' -0.09619806710825690166 0.1182677218979499567 0.02992458665593146494 -0.1438962338233842897 -0.1721878315302234619 0.1309354582884898199 -0.04183219727899264995 -0.006016333608517805166 -0.4446028371306636751 -0.2054136149191853888 -0.09613533608693748678 0.01947003916081320105 0.04023431708417059272 0.1710905365142074142 -0.2194251980145262293 -0.146817210034864698 -0.1706624805308629422 -0.1281389551689726403 -0.04290270041560414332 -0.006181247771639700878 +'MLO21-1706' -0.005577215601228074221 0.07442041047134057008 0.1241585583074960586 -0.1545886028960309633 -0.1416011796979842197 0.2691976267730566974 -0.03734795811754333672 -0.0642653468547197404 -0.3340926389582788425 -0.279701993322102771 -0.2536483781048549657 0.0655685606380514846 0.008515416778202312964 0.07601111135127988638 -0.2746490752453900064 -0.157726625480968996 -0.1403467850114175353 -0.2634481375752656951 -0.03830370772936070312 -0.06602692900489831596 +'MLO22-1706' 0.03574124278436890956 -0.03351124200854807555 0.07065428381431673732 0.07376064313098742997 0.03977678648937582606 -0.07578681872217876703 0.005045205805280114815 0.006742940211901614529 0.4322932474242985323 0.07710937925826136241 0.3268960193534011793 -0.009815171494333538652 -0.003207357303087278889 -0.1046431256795483794 0.3434199736797098335 0.07525792404101842858 0.03942441802939977008 0.07416817333959727088 0.005174314697251110318 0.006927771442080139092 +'MLO31-1706' 0.02335027695706177672 -0.08184121978709980871 0.06297953295131275553 -0.1571978205858913513 -0.1892721686426063199 0.3622236681314214835 -0.07510702038737752939 -0.1265939267982662819 -0.2610489784066898356 -0.3244345342798212739 -0.2426640726539950887 0.1142887483528743503 0.0186479229051942294 0.04862104026539474516 -0.2584352257722497548 -0.1603888081623384421 -0.1875954735531542017 -0.3544873403930586253 -0.07702903993538265381 -0.1300640022383471317 +'MLO32-1706' -0.06917102755867893249 -0.1160203877977356857 0.06499745363772395368 0.1293377696994272297 0.08590209897514125559 -0.2123922803917337732 0.0146880595173055923 0.03608521283023888304 0.3970715913069901015 0.1904263073945612061 0.3454274162777479229 -0.03513815240054251471 -0.001811790343358681736 -0.09322105136653607849 0.363200742477256755 0.1319632209603800455 0.0851411227124493214 0.2078560326675444325 0.01506393300248606675 0.03707434725366065553 +'MLO33-1706' 0.03906514855758928123 0.03715943036126497651 0.06784612276801420261 0.02173853060394633288 0.0194594592231374236 0.02998984578603465165 0.003445603318812817065 0.003474766925558448686 0.4448646287160821777 -0.02944331019303483843 0.400131504261086457 -0.006493778708088468465 -0.005767022449763669137 -0.1049233347731324539 0.4075424213113187366 0.02217980504928450738 0.0192870747676899025 -0.0293493264157224272 0.003533777725136923262 0.003570014017368785923 +'MLO41-1706' 0.02968258526596665586 -0.08528502534192591855 -0.04805625349816969316 0.1530178477015080862 0.134723723402018547 -0.3368410507075745297 0.03484338371611422208 0.08407067512638699558 0.3243979555234395851 0.2688077505120701205 0.3351456381247909788 -0.06700542119285950171 -0.002477196440968285843 -0.06891968780570872921 0.3450665330949023724 0.1561239852368144776 0.1335302536643340476 0.329646841733182594 0.03573504023870834045 0.08637514258675720036 +'MLO42-1706' -0.009813525708051419605 -0.05517041548606339829 -0.001480731269012075524 0.08369318087936838957 0.03908314554066603941 -0.1130734023650762504 0.005927871711646718472 0.01040278567924651787 0.424016138424608946 0.08790051950661811886 0.4266355306707683703 -0.01141097276075207605 -0.003318531062898421279 -0.1011492292646147678 0.4346660429824507621 0.08539208420655218512 0.03873692180012171943 0.1106583947988930977 0.006079568387258236367 0.0106879372027591929 +'MLO43-1706' -0.06497367018937913463 0.005357698822009322737 0.06721619353052157853 0.03814081452870590749 -0.02366229325607518627 -0.1631022490844800943 0.002705093792193812279 -0.0137182102065099322 -0.3991597116636950715 0.133307710411953162 -0.4174923294867435852 0.01105514837010679492 0.0017220870395755056 0.09211466454468868192 -0.4181292144614614514 0.03891504196304988034 -0.02345267738284792514 0.159618731675772868 0.002774318255113093854 -0.01409424107563159341 +'MLP11-1706' -0.03254907887140537359 -0.031343189015960643 0.01162562349697794477 -0.04481489544758975735 -0.1637221261562841756 -0.003644449989792582657 -0.0313657533939791025 0.09920318384683535218 -0.06585969536860916684 -0.1163234330464612276 0.3189788093004055081 -0.1589258747295231866 0.14086329016737692 0.1353490369514508129 0.02589680587528723002 -0.04572460128244197619 -0.1622717698417261156 0.003566612283348509407 -0.03216841592605935302 0.1019224496169326144 +'MLP12-1706' 0.07420168669935493788 0.1626135653591918029 -0.01161357581151663612 0.0006503848446864165687 -0.1650560746376732446 -0.009740636855120811399 0.006052426588323464238 0.06994411533537923942 -0.2411069308675658773 0.0008280259812821844437 0.3206804543421148401 -0.1297772789069849275 -0.004178645054211406126 0.1768255167663430605 -0.003703793444594739425 0.0006635871267000516965 -0.1635939013460901426 0.009532597553105218169 0.006207310674466478065 0.07186135862612773317 +'MLP13-1706' -0.1472537393590042654 0.1698745075867932885 -0.1289722917829971005 0.08954636501127397064 -0.1815010951972302888 -0.03446370320538457571 0.06322647055022191653 0.06917967305637177933 -0.197444497143178993 0.1699705841858713262 0.2744847843162597778 -0.08265853485686419644 -0.1435369710122164078 0.1555788231247704212 -0.006745237965122670432 0.09136408320356184665 -0.1798932412944094228 0.03372763174862437874 0.06484446194066885438 0.07107596216357581209 +'MLP21-1706' 0.03065305428369943103 0.04998678184158267951 0.08347290655773205448 0.1215210239110993823 0.2281643782632242767 -0.03553814460919221124 0.09987713047746586692 -0.08087828976564592764 0.1839552744870874557 0.2266761617423720399 -0.2230459482949261885 0.02251211022933336664 -0.1892567775181508427 -0.144853423111896501 0.02160539624538475659 0.1239878016064401289 0.2261431508669016766 0.03477912536749458439 0.1024330273321973211 -0.08309525051605176627 +'MLP22-1706' -0.07457784830778133034 -0.01685430435273760699 0.05613896592371505484 -0.1008948889056937026 -0.1990878771411294379 0.02379315990121987773 -0.05209375562562000572 0.06321294330035755193 -0.2756225730534200835 -0.1684282363993371556 0.2458283783038056891 -0.06615441853850734244 0.1129004881214447087 0.1754344441912255859 -0.03218934493916735667 -0.102942972879282682 -0.1973242281674533194 -0.02328498857195069466 -0.05342685626155296852 0.06494567793928966715 +'MLP31-1706' 0.01240951581111496629 -0.06797052655871625715 0.06226620494947669726 0.1665491062541684109 0.2445198134613952301 -0.09081177834893650047 0.09002874174319693001 -0.02516855560792082697 0.3486075340535446654 0.2520251052602807129 -0.1098374529835711572 -0.02073335737228252512 -0.114372507474338414 -0.1768978117412787487 0.1009622619911235142 0.1699299173045038802 0.2423536990588144313 0.08887223176040152939 0.09233261427895005091 -0.02585845273716091963 +'MLP32-1706' 0.06730412417434690486 -0.07499711696366041791 -0.06492806293250759364 0.07172379999208475243 0.1691686145398393626 -0.03211099887297767796 0.02094649814523389872 -0.02989385536553905431 0.4450973378894834132 0.09576057813882125902 -0.08030536293800243086 0.03374692119732352474 -0.03397550516256678255 -0.2051654323689691695 0.1335667039921200894 0.07317973464726831856 0.1676700097141929913 0.03142517618069180785 0.02148252764939672169 -0.03071327803404187706 +'MLP33-1706' -0.0301997206769226631 0.0599716611456580645 0.05736201770451674481 0.06991588837645240639 -0.165524104091330948 -0.05922745143604712936 0.03169309247090957432 0.02788423815925609311 -0.4195211203525940902 0.1297071527555289372 0.1012943008122802191 -0.03645650359655178141 -0.04928184303175944109 0.1956362613135718409 -0.120889271280105709 0.07133512390003669823 -0.1640577846926244698 0.05796247894603584472 0.03250413174462386118 0.02864857506268425613 +'MLP34-1706' 0.02142708564677759872 0.04222148761828281582 0.09213146860173419828 0.1420231637408337633 -0.1928328936320904408 -0.1554264662092531002 0.08993872846965687839 -0.02230082821303797092 -0.2961103254223054204 0.2914856764061067307 0.02674171626503536736 0.06774850378097202475 -0.09641422921272820024 0.1247227021563254851 -0.1140678707053414398 0.1449061181569676893 -0.1911246553413975813 0.1521068872098651215 0.09224029752871192034 -0.02291211785569865003 +'MLT11-1706' -0.08233530045752376902 -0.02447828727219286682 -0.1014393526359933517 -0.02958229687602973584 -0.04527773462767654966 -0.2230494963104258377 0.2111870063729225366 -0.2675319784798846356 -0.0288329727485090101 0.2236778367940650547 -0.03943624108943055012 0.2793902637327433935 -0.01854404305117749938 -0.007690732417338416033 -0.0423465413057005774 -0.03018279338076725743 -0.04487663521693806973 0.218285633103375204 0.216591368740646828 -0.27486531722241897 +'MLT12-1706' -0.1114444708120039818 -0.01849487989224751772 -0.09792452961550676682 0.02583722051321851038 -0.1458246707812212439 -0.2931978717395675726 0.1560182061764308903 -0.2214425097855136082 -0.0848403927824512849 0.3105837944274463802 -0.08700575886028404093 0.2364350428229961554 -0.0174784414767892686 -0.002961941039041637597 -0.09372235346856495897 0.02636169502158206002 -0.1445328616833843338 0.2869357883156186673 0.1600107762526922217 -0.2275124867111925353 +'MLT13-1706' -0.05383329550375999528 -0.00380981021998805236 -0.01632765315264699327 0.0908144486053477501 -0.1717561243681703931 -0.3085807255201218902 0.08954527229144168543 -0.1360471724394358428 -0.1917812092621452025 0.3480644017516279498 -0.1567186628871949927 0.156061174564948113 -0.01497555806176901864 0.01829121545937899621 -0.1711193688961214765 0.09265790786058103468 -0.1702345977096196561 0.3019900970317062061 0.09183677264504268301 -0.1397763714911947064 +'MLT14-1706' 0.03334052127485961914 0.08727846851640211345 0.1337573540696984642 -0.1055074212258858696 0.1400925198914803327 0.2849956143401081166 -0.05395499469257002828 0.1109506775354029418 0.2330972961545163535 -0.3327796299227183119 0.1722295147687499806 -0.1279301503386968963 0.007437001995765885054 -0.03710694895270723326 0.1853935350794390924 -0.1076491358444471719 0.1388514898876737069 -0.2789087137024304774 -0.05533572520187218097 0.1139919547191769883 +'MLT15-1706' 0.09871839735438511787 -0.07714045463308322192 0.05219836140068744718 -0.1042273170158462409 0.09197801163002736202 0.198300305442292879 -0.02672396356482748328 0.03877652626137417097 0.3613035029548977706 -0.2482918958501107443 0.2010145982418926336 -0.04831902000297656763 0.01869519582748750339 -0.09290063791491030842 0.2376949885519369365 -0.1063430465627597798 0.09116321100961051471 -0.1940650323541676658 -0.02740784078571651197 0.03983943247523755865 +'MLT16-1706' -0.015137694284533737 0.07209707496102379931 0.1038206332590150549 0.003874088488978161271 -0.07852820718152854484 -0.0415903061725510087 0.00528007797795675398 0.004592155608955979067 -0.4719628478113992998 0.04960774435547862793 -0.189838959624057807 -0.004619140748259872344 -0.005670844111562792396 0.1540051832598874626 -0.2695591179257623149 0.003952729326314908566 -0.07783255361392255045 0.04070202562216752862 0.005415197345444400581 0.004718031524165252136 +'MLT21-1706' -0.1695220056619411442 0.01938514843339033539 -0.0007782423507863810153 -0.02659917894251488321 0.05609075520668714565 -0.1653810029292919481 0.2439709046622440536 -0.3296950813646306044 -0.003400926890683688558 0.1432800487499681641 -0.01647650673444727917 0.304595137741725086 -0.01920512994132781218 -0.006285297594146315066 -0.01177099016291409915 -0.02713912058568088842 0.05559386707731669985 0.1618488161813626536 0.2502142204732934472 -0.3387323774932354259 +'MLT22-1706' 0.01253719985686441163 0.03293244308938413079 0.01255531523583442582 0.005052397400462312754 0.09561464443966852245 0.2713505700295311129 -0.1949733212451122133 0.2842238004776054261 0.0487393815794826199 -0.2538105484288438185 0.05302185428441363174 -0.2696109120444568075 0.01648506921534850789 0.001519694326976172303 0.06216639915200549565 0.005154956947891538299 0.09476762817752369672 -0.2655550985393071439 -0.1999627687406963783 0.2920146799808179261 +'MLT23-1706' -0.004754430361167108834 -0.02378388530037454929 0.01028461857033133482 0.09196490667031650967 -0.1966179352201750663 -0.3542016182441959926 0.1185664188260945745 -0.1809617825397288327 -0.1707138964970726092 0.3466278676514039647 -0.1531833728266965566 0.1790467592506942707 -0.01613109864795101225 0.02082234402610015633 -0.1712879613734991646 0.09383171928616804158 -0.1948761665869620796 0.3466366244426276055 0.1216005822577597706 -0.1859221392729948075 +'MLT24-1706' 0.02586678269583084569 0.01710795420096069414 -0.003917041659703515352 -0.1176957007984857084 0.1686647075162490128 0.3383488613902197462 -0.07370318403295750276 0.1396937168091365311 0.2212181269494159774 -0.3388481006657154126 0.1897634867790275182 -0.1395512097724121992 0.009251444612437566967 -0.03783713251572059372 0.2013466407745358455 -0.1200848275538659304 0.1671705666244078792 -0.3311224487841090136 -0.07558927883116588198 0.1435228715568635793 +'MLT25-1706' 0.06825304953278769904 -0.02586006496609506364 0.03872178135421450174 -0.1268721880940744118 0.1120982594992709497 0.2902333077321472832 -0.03271270445964546275 0.08155398098307603538 0.3082687234376009222 -0.2988903686932241621 0.2458178196993102138 -0.08206954564754399828 0.00673555467769808465 -0.06791620918030311094 0.2561261906134915667 -0.1294475900589104611 0.1111052207308852041 -0.2840345410949811633 -0.03354983602358273254 0.08378946315514863852 +'MLT26-1706' 0.08262104215029614229 -0.07113893019464671841 -0.05751161154286840715 -0.04987476942547613284 0.03235102071602020263 0.1472970077251444798 -0.005571973328459640593 0.01502889713360176967 0.4028474180133593818 -0.1521229824971006839 0.3212392533118609284 -0.01619601809869684883 0.00195337153083327119 -0.09246606463987298852 0.3294980051938202759 -0.0508871865761827899 0.03206443448433951571 -0.1441510566819111661 -0.005714562418041769024 0.0154408553384998478 +'MLT31-1706' 0.04536269821446053951 0.05543637710208089431 0.09006923830836613409 0.02296390257423754772 0.0658605352782777459 0.2810548014687349605 -0.2029959020507628165 0.3237891685553785925 0.036543353703195329 -0.2330948026272021412 0.05456119252573662232 -0.2724653032860071544 0.01277527675922108044 0.006359767533228870458 0.0586766135365817329 0.02343005107138606408 0.06527710012834667119 -0.2750520682188090094 -0.2081906506893610176 0.3326645772735130069 +'MLT32-1706' -0.07040737547028194654 -0.07010868790391346084 -0.0919325801047311264 0.03295694794073949357 -0.1505221903652836923 -0.354879798883719455 0.153931473965670973 -0.2668958203861421241 -0.09406606299642095159 0.3066220431621312636 -0.1132565363247583362 0.2334896233478791772 -0.01091877318015843298 -0.0007529988673511585091 -0.1188547122644263987 0.03362594711034984363 -0.1491887676056194711 0.3473003205849888864 0.1578706437062533385 -0.2742117213523712627 +'MLT33-1706' 0.03759154420645592631 0.06293433604215277477 0.02785939330557466592 -0.1061371672066710875 0.1865440063790075598 0.410383837180749389 -0.08840482736597141122 0.1877449635833288721 0.2002981087374888503 -0.3577055301325957615 0.2150493937769878683 -0.1610161405018594449 0.002517759247609677176 -0.02447174925164136844 0.2227025717381491965 -0.1082916651551381199 0.1848914791125554902 -0.4016189105835031858 -0.0906671432647921105 0.1928912545911712906 +'MLT34-1706' 0.01010830937860377615 0.02300220144635611863 0.01175418885146892189 -0.1309931439552913801 0.1478078965860212812 0.3750463712044744269 -0.05026462681219697609 0.1313665713175116156 0.2687998819186505628 -0.3343907771078135083 0.2557206487946995233 -0.1149472042471736399 0.003135771625174524433 -0.05384999391382537526 0.2643678739438211078 -0.1336521979638213564 0.1464985187933675881 -0.3670361777798173963 -0.05155091928935751772 0.1349674700675989047 +'MLT35-1706' 0.05302704195493749412 -0.007555412711386787217 0.1787448755649659327 -0.0992282311351058155 0.06627001854908867728 0.2644343474922813964 -0.01438336069692540235 0.05340909162285857603 0.3906858811735310355 -0.2401727388401060093 0.3504831715207544773 -0.05141044200545939052 0.002739962210585126026 -0.0906296722238528335 0.3587242843285467497 -0.1012424833149695308 0.0656829559319271894 -0.2587865918168069657 -0.01475143681395034261 0.05487309216225923908 +'MLT41-1706' 0.1293857880350949563 0.00637571676035968149 0.07136577695359848372 -0.005179597420609745144 0.1028952934831743327 0.3343091811333139263 -0.1875372043946663403 0.3359978703363776242 0.04801916603187286747 -0.2585108773865401055 0.07671975522743527953 -0.259996493698508746 0.01485932153584340262 0.004754998426423406865 0.07647673598986186316 -0.005284739024727168333 0.1019837805304340955 -0.3271690475121927788 -0.1923363586011000437 0.345207932677138507 +'MLT42-1706' 0.004773705767403838007 -0.03956184197923247325 -0.09336372858720129453 0.08206218110972902935 -0.1878686369052043892 -0.4316469045532592141 0.115278634680994016 -0.2363962694522231123 -0.1589447350970379091 0.3379995109937863895 -0.1938551071848978458 0.1858992914826183285 -0.005978616651057470921 0.0129834577410325655 -0.2022497029033333282 0.08372797647153064349 -0.1862043752061913748 0.4224278440260984535 0.1182286623639114964 -0.2428761449841677633 +'MLT43-1706' 0.07119702620511179914 0.01148867339718427638 0.06546062155324658405 -0.1162688954220271603 0.1630026811665273301 0.417495408100176435 -0.06999080869833090857 0.1733134191511145339 0.2142543027499685671 -0.3309780358394447952 0.243641597888815592 -0.1351828999414670385 0.005501391533327266471 -0.03492379500937104614 0.2486377776137869144 -0.1186290591917036341 0.1615586981602591676 -0.4085785934618999526 -0.07178190228459020716 0.1780641260328996167 +'MLT44-1706' -0.01060059760112150307 0.05279261184974405607 -0.08770762262678184762 0.1286489460236365234 -0.108358113107704393 -0.356080161954127894 0.03283024541845395994 -0.09813784237239926711 -0.3191464532929893516 0.2862178580547877771 -0.3243211846736706039 0.08049649684748082235 -0.006229524418852130235 0.07373414556936487563 -0.3310271196235037849 0.1312604147256478115 -0.1073982069711976323 0.348475046451275472 0.03367038490387921218 -0.1008279059889712198 +'MRC11-1706' -0.005660562964780430084 0.03093564647386291139 -0.1366476803393353867 0.03149288472440638087 -0.1428646582377278429 -0.09706565209807684058 0.006744921713188308833 0.1301950389802383479 0.1292700997476396163 -0.03218320200967091094 0.07363530531781213584 -0.2780291827662086934 -0.1117044033296687167 0.131025106735402963 0.2536033537948697569 0.03213216460454412782 -0.1415990708423841005 0.09499253605725488381 0.006917527034443880611 0.1337638247712473472 +'MRC12-1706' 0.001657209719117924696 -0.08621241292836676062 -0.02032110369289632373 0.005415489136256735822 -0.124468946543081882 -0.005139337647525064716 0.001096150089557285795 0.1128702813525614829 0.132144935373970096 -0.007353401404667603107 0.06365797610045072219 -0.2621644187450471453 -0.004295464814762192315 0.07515609803940684341 0.3047129122011199565 0.005525419149852170767 -0.1233663202406795334 0.005029572317709748649 0.001124201021265271898 0.115964176937779273 +'MRC13-1706' 0.01567806134576491331 -0.03576686567425289842 -0.04743607632671517638 -0.1675320574891141501 0.0557961346471095021 0.1082317265516854754 -0.04093260804039606376 0.09301617041409791786 0.167624894580672229 0.1170817167061984354 0.005894582849949414442 -0.135330212382247933 0.121112523485422674 -0.1501655102976734713 0.310447528153994512 -0.1709328216480059948 0.0553018564569024984 -0.1059201268911439675 -0.04198009031833362104 0.0955658435038559545 +'MRC14-1706' -0.1408236532932465035 0.1437399719835189549 0.1440907664891577511 0.3667402996001041249 -0.26068625812285523 -0.08012772140454960113 0.1202107523793718991 -0.04224879299289648754 -0.1334373946045232517 -0.2567361730716835599 0.06242766246245907286 -0.02682478483333718133 -0.1746168437430096476 0.2194568596232674418 -0.1504935965628990402 0.3741848286364785614 -0.2583769309142280313 0.07841636356614101189 0.1232869949830844442 -0.0434068777655675711 +'MRC15-1706' -0.1415466196240769692 0.02020267978190632557 0.105594078560044824 0.4177190730735461099 -0.382816307871402528 0.09738142075264108466 0.1621698710909499352 0.06487558913729139787 -0.06751218407339500127 -0.3300944839791737917 0.1052854051065583024 -0.1533620785578568568 -0.1102796631811167744 0.1916663244901095631 0.009215365861497617703 0.4261984296425794794 -0.3794250738184858918 -0.09530156056444240298 0.1663198648029446669 0.06665389868356871861 +'MRC21-1706' -0.1645483263218346925 -0.06940489131530748479 -0.1424274970759405179 0.01872577238450523832 -0.148397797041877777 -0.005538765983709789155 0.01377114050098533771 0.1100361958312194022 0.1458221056487790102 -0.009818289542760873581 0.05470974035509937328 -0.2952812683540666505 -0.01531456261076340544 0.1276575891519702022 0.2386784095436131348 0.01910589029463673205 -0.1470831935300668802 0.005420469713515407156 0.01412354965135108852 0.1130524060897281774 +'MRC22-1706' 0.007350299927600816713 -0.04662536045993592726 -0.1190910105663929713 -0.04209156594515547217 -0.08279258821657893563 0.09074295641062139761 0.0003863620856409030724 0.1152965948957720699 0.1429817115580201692 0.04255942258065224804 0.03736489202088946054 -0.2417822316490968737 0.08592803084441706651 0.03692211334232609055 0.3061453894366336637 -0.04294599041175175408 -0.08205915800810550942 -0.0888048797124255801 0.0003962492503477413374 0.1184569983400094034 +'MRC23-1706' 0.1340046642764439744 -0.04144836320494377224 -0.008996463796811753413 -0.1788124872672437748 0.06725340995093564977 0.1743462871326501851 -0.05619907952350092217 0.1204575310739445793 0.1371456339256297008 0.144819087650337297 0.006131711438593132925 -0.125770465034433454 0.1964531086529643367 -0.05273188814522869472 0.2584612031979672819 -0.1824422349524009723 0.06665763581772661539 -0.1706226209675350824 -0.05763723708676137675 0.1237594013194150827 +'MRC24-1706' -0.1138176828966930565 -0.0599252702223835032 0.1795681998662090328 0.3263463036260727534 -0.2772457583260635183 -0.1163327608533506752 0.1470652409259930737 -0.06757398049154753061 -0.1119816947438452004 -0.2555540976094763383 0.05145665452761891828 -0.04821044840374194562 -0.2126462493436306611 0.138009767366694569 -0.1405683727414873407 0.3329708674820410219 -0.2747897363715914865 0.1138481403167832945 0.1508287009385719524 -0.06942625584173779674 +'MRC31-1706' -0.03030764062539810511 -0.02895209766741612539 -0.09569436626421892744 0.00184434773831949287 -0.1129043021380233547 0.08292197523586969377 0.02234935690276347933 0.1161350076765614442 0.1483247473883449463 0.02501205533002289969 0.03670024877906322841 -0.2720823248176128528 0.08534663745625559184 0.09848974457835335539 0.2276114894841698433 0.001881786493498736976 -0.1119041229234537665 -0.08115093807408949034 0.02292128613961647021 0.1193183929152090289 +'MRC32-1706' 0.09912685369841618688 0.08132927740746792589 0.04133291048937849654 -0.1027786634329944243 0.01874258259204315824 0.1865765162199978233 -0.04378564074318946897 0.1531800457235129032 0.1374387834159497834 0.1115522076961573544 0.02093102885570796712 -0.1539170044932215986 0.2371980743126564095 0.03726142830899034641 0.2091948521718647591 -0.1048649864934298181 0.0185765486927060193 -0.1825916383537725118 -0.04490613330162523953 0.1573788752252050782 +'MRC33-1706' -0.04089369243021736405 -0.00161308383295192051 0.06755710509737210268 0.02058540768048557762 0.05924720742842816412 -0.1424802279592479737 0.04461174001234675252 -0.1791885335444835803 -0.1330153948348522519 -0.01903961338319410876 -0.08326488125491482428 0.1610202673483977776 -0.2819241620903628065 -0.1037757855673080154 -0.1158915693951795833 0.02100327467075113058 0.05872235740704664919 0.1394371530949919114 0.04575337279090742337 -0.1841002836190956393 +'MRC41-1706' 0.004808495888703870347 0.01280792054287886207 -0.1740545572962289289 0.03244070404921673562 -0.1387476241065075111 -0.009913414231561785972 0.028590827599259825 0.1005579916418899017 0.1627993359508683735 -0.007193955936396094486 0.05891867588529264843 -0.3021535635152705623 -0.02797872926364249058 0.1293653642299854578 0.1658607538920409408 0.03309922388878212829 -0.1375185080580100805 0.009701684771979133745 0.02932247863874982985 0.1033143941481210332 +'MRC42-1706' -0.1001818712659820615 -0.06157689018310366635 0.03385256424823168686 -0.02143174127961211539 0.1243777597910707133 -0.0752531838929455521 -0.02630914246999125142 -0.1272866685687265853 -0.16598485506785432 -0.01630864584944390072 -0.07361937969056429887 0.2896955373257253941 -0.1249853015552933461 -0.1284161673178949303 -0.1440881176063019964 -0.02186678815182689986 0.123275941279800183 0.07364593581621334262 -0.02698240424842112892 -0.1307757328044375222 +'MRC43-1706' 0.01051572342516605106 -0.005573886465091043921 0.02231890046566168198 -0.01700595089220478112 0.1306546549002026714 -0.04593449857095479455 0.003256521167696147401 -0.144430709314943867 -0.1345610541412786132 0.04324527501680675706 -0.1750576421336568211 0.2337679031398093299 -0.2031584325166854443 -0.1233057730234948107 -0.06462385529311368004 -0.01735115782841065504 0.129497231598846213 0.04495343530340120686 0.003339856883991669349 -0.1483897101127143736 +'MRF11-1706' -0.1460610777701848162 0.1225370377843743586 0.003292974800558338966 -0.3914759656339776295 -0.1993117264089305785 -0.2666611432810869764 -0.02958525882224877224 0.06581447692863147403 -0.06374779841188568663 0.2752635410150005568 0.2717012586028726417 -0.06674925331413927854 0.003226199356359232828 0.3146042658840567663 0.2551314180783957331 -0.3994226085210087485 -0.197546094433893038 0.2609658279800435854 -0.03034235776580785152 0.06761852239722450364 +'MRF12-1706' -0.1978666252348947607 -0.004246940324839718756 -0.008404965065261033041 -0.1777551380750957699 -0.05615897247615009302 -0.1006349131576794037 -0.004967777846480942242 0.007194231535034661257 -0.1003539970723780761 0.1030919117036809135 0.3400687939021461714 -0.006876828688666960891 0.003914930140392529692 0.4080310672392012394 0.3198682354164517072 -0.1813634224338307455 -0.05566148003415649637 0.09848556528616757288 -0.005094905325135224566 0.007391433144869870644 +'MRF21-1706' 0.1468485575525668163 -0.02660898146923014809 0.01082298439571230744 0.4489556698662187095 0.3172484424707289197 0.1544123396890724198 0.0921297269988990003 -0.04898630155053217833 0.1018950793831793072 -0.3015256224154518883 -0.1707156859987638553 0.08872398706265811896 -0.06072974909297342017 -0.3008291650378063231 -0.08584168000493415385 0.4580691038793566205 0.3144380509089804154 -0.1511144202768913147 0.09448736461161434674 -0.05032906866590711875 +'MRF22-1706' -0.1753734699537965458 0.1319961639025657996 -0.07758587017575943601 -0.3031220334089506641 -0.1553476163683171207 -0.1115559371568244779 -0.02654041212715628831 0.009159656794319161188 -0.1411408338101635129 0.1920495516064696928 0.2370308326963556922 -0.01584976674019302964 0.02281963895626976102 0.4133614984690955341 0.1520565620048316413 -0.3092751635169273539 -0.1539714468691728011 0.1091733394225089387 -0.0272195921912489272 0.009410732820518952907 +'MRF23-1706' 0.1277627716319828799 -0.03506348061873196947 0.07049036255540865048 -0.05095919589964797991 0.02584686254273198258 -0.05359056888835258409 -0.003287907748599090338 -0.002309859197859597674 0.1019585901104455711 0.05896635622042942226 -0.3080083839977790783 0.001283698699669189123 0.003611616205129146093 -0.4150806889987312398 -0.2898279082339914048 -0.051993626023522789 0.02561789434411121391 0.05244598822982095288 -0.003372046660411215369 -0.002373174918252017422 +'MRF31-1706' 0.08258377870033484225 0.02882409598080180879 -0.03478561157289992295 0.3345237250523870887 0.2153588278531803901 -0.05186325543676745947 0.0693964612798855518 0.04843043705848610464 0.191818203958879413 -0.2025251240757260651 -0.0826636353268593721 -0.0207706622106353482 -0.1089803201412488931 -0.3411415075314344625 0.1510093116030930271 0.341314283895318038 0.2134510402913788185 0.05075556652260274776 0.07117234527121399368 0.04975796733137858446 +'MRF32-1706' -0.140292069230588623 0.0518084379845978743 0.04625992645041328982 -0.08223499388170910085 -0.1259187845971654895 0.01472054522641652423 -0.005661619525129373692 -0.03129152352533937087 -0.2112104070428087454 0.04073682600412430188 0.1432569673872305105 0.03925861477650859771 0.01497882477466179647 0.4452362640532511184 -0.06901112308688432673 -0.08390429720186784457 -0.1248033146930692949 -0.01440614566510008826 -0.005806502697761463036 -0.03214925777858698014 +'MRF33-1706' 0.04581512633311696225 -0.03851916734220987848 -0.1121433021056573304 -0.2704492552298836117 0.1416339165348300955 -0.1072501162247365691 -0.03457846331288893377 -0.01401686321925640216 0.1539189910460826427 0.2001699628286556787 -0.2149691214471755041 0.01774882660361733894 0.04184702532194709002 -0.4159159851214078163 -0.09708104383185747754 -0.2759391545826957448 0.1403792318442233233 0.1049594816746192844 -0.03546334041338593257 -0.01440108048808023435 +'MRF34-1706' -0.1804816263940929866 0.0482547197334161071 0.00149114393265449563 0.3353531235492367979 -0.1432900075491073399 0.1985818351149147842 0.02560302013500279431 0.04157311037525023706 -0.06898630043424712477 -0.2521540703680296147 0.2528825855342297091 -0.04830650884366950726 -0.01582398468404331085 0.3456799574124652663 0.2286065383861655143 0.3421605185053499532 -0.1420206521349005879 -0.1943405491513010563 0.02625821195240731626 0.04271267396198386024 +'MRF41-1706' -0.004460773861003406934 -0.1604055877951704456 0.003142378096630205064 0.2310292917860298223 0.09826412580379421946 -0.1892634406097830069 0.07086692188108359436 0.1301887207711014127 0.1540796045597042363 -0.1644560006901570337 0.03904030390114558019 -0.1098205675145439569 -0.1904384299867170061 -0.08561206781191804671 0.2999938520169375678 0.2357189980245574801 0.09739363872486382634 0.1852211757489562183 0.07268043556409059525 0.133757333373214965 +'MRF42-1706' 0.03004480325200908908 -0.07122999434194551838 -0.1404816604715563577 0.1235229175863819667 0.06321053702925003015 -0.07769921687174238811 0.01805435270065995287 0.08657730690902729065 0.1948044818285250279 -0.08024469733894981638 0.002226204493076584627 -0.1292736570153762976 -0.06550159751628488458 -0.2324064146017385812 0.3252043815005539185 0.1260303320909570424 0.06265057727500479567 0.07603972672899494967 0.01851637101317284151 0.08895048383758648314 +'MRF43-1706' -0.142053850856965036 0.04882004860033850591 0.0002093252162574856662 0.201628475797231338 -0.1266298560996375056 -0.006719513938002405658 0.04694529932042386389 -0.04190293870243258501 -0.2008881807115901474 -0.1378154184197052379 0.070668880323283223 0.05904396586246443007 -0.0742525001907780452 0.3571554136700185733 -0.1912439638530392949 0.2057213694450500674 -0.1255080870650088221 0.006575999400879384282 0.04814664884161949654 -0.04305154323770573471 +'MRF44-1706' 0.04052347657870172815 0.03395938511220548267 -0.06296226606685161042 -0.3049314232960364524 0.1936938430041473258 -0.00547853199430812024 -0.05892261881081731212 0.02198968854998612291 0.173888331141278607 0.2071834799580361819 -0.1191120092087274984 -0.007656235063676544023 0.08385329629100289617 -0.3577793987619313776 0.09173947367047886881 -0.3111212825433174456 0.1919779778679718274 0.005361522194115560941 -0.06043047286480504598 0.02259244952045455501 +'MRF45-1706' 0.03333028018806128562 -0.07061627546691667812 -0.1533342211569757585 -0.4316641322479654597 0.3130181039474156379 -0.1472042904251516238 -0.1003939048455900207 -0.06245609999890650021 0.08833489617920510517 0.3214055386254895397 -0.1542982360874382008 0.1062539354665490848 0.07543292546338328797 -0.267342037806401811 -0.06136503392626676406 -0.4404265621472305825 0.3102451874559831735 0.1440603196263994523 -0.1029630261689838955 -0.06416808875042699645 +'MRF51-1706' -0.007265128715334814857 0.06919684443253426576 0.161788688768056077 -0.07484133460293593276 0.07707841074468414766 0.1163096828009216877 -0.01217654667726364437 -0.1264042630085773222 -0.1366166716280267646 0.06355798626457344336 -0.0657555576099347755 0.2263490905229616768 0.1060020400426279347 -0.0309284095129038622 -0.3354558912991432718 -0.07636055266863557567 0.07639560041009968439 -0.1138255551625077661 -0.012488149515722545 -0.1298691395605668097 +'MRF52-1706' 0.07238836968977092889 -0.09904856959499559743 -0.1362848755353477936 -0.07217592118370531884 -0.02348616596768675346 0.03670057000230018268 -0.02822063658828575031 0.09589625669184358159 0.1626096663820633115 0.04392102620374231658 0.0375767947370768754 -0.1865541340379883173 0.06041334171735435882 -0.09932675507893340416 0.3559667699362377147 -0.07364103353041243083 -0.0232781103437115465 -0.03591672382464094343 -0.02894281428752183694 0.09852487603842831343 +'MRO11-1706' 0.06209961816336936197 0.0469618832994443125 0.07743497040960828359 -0.1439377423882668983 -0.2549757463148236147 0.2261121631683401523 -0.2008059047286922527 -0.1024485944130896081 -0.1750551121584435488 -0.320013918835879152 -0.01343605646839339703 0.1855797110827041574 0.1006391428739244198 0.07238630623524415497 -0.0976189532015430822 -0.1468595611897677566 -0.2527170065072678051 -0.2212828879061124465 -0.2059446104349335893 -0.1052568203709602496 +'MRO12-1706' -0.1006215789754773271 -0.03889078837013267703 -0.06130458970919448747 -0.08525198542510474542 -0.1130534545083538428 0.176148990736793909 -0.3008410647741507349 -0.1452357138483714172 -0.0536640376157460422 -0.210479749195360194 0.009796322209887506349 0.2720278502013791511 0.1310533180979747692 0.0322733233593751126 -0.02977349187045847181 -0.08698253121349452943 -0.112051954005774973 -0.1723868226538754489 -0.3085397113767760491 -0.1492167806846262379 +'MRO21-1706' 0.05299930883992316072 -0.1253943442984888634 -0.008060704348819155984 0.03797736748939538332 0.1608819553919366152 -0.2740428237563288238 0.1952426672348398506 0.2545954870257767233 0.07201616767469194713 0.2784536500571362927 0.06723888940824945815 -0.2644354197546802676 -0.01521978793965386018 -0.002430446545962240863 0.07509430126772151382 0.03874827708211848326 0.1594567591440060605 0.2681898514481907969 0.200239007405100311 0.2615742226494168765 +'MRO22-1706' 0.01136950260910647714 0.03276013849721078758 -0.05313899731148753053 -0.006430042846686685569 0.04714505400198649998 0.09102279698813997566 -0.2597015444726570865 -0.3180763230458197866 -0.01028332816728782378 -0.08401308036534056722 -0.006060076790239271767 0.3289500340605445161 0.01601793786951182311 -0.001738658626476179657 -0.008799210965516061217 -0.006560567473321627339 0.04672741267043737518 -0.08907874348993724545 -0.2663474138274672942 -0.3267951365354385129 +'MRO31-1706' -0.03431694508912453562 -0.07370029867745292451 -0.1664149331400278931 0.08602719904402476858 0.2093333318024645784 -0.3682588126828165165 0.1355740691343928772 0.226981895933509592 0.1335850593161744815 0.3273626812000050013 0.1356215035999679686 -0.1979141672076910607 -0.005639567486516952437 -0.01515844377503166446 0.1481137795908643584 0.08777348103675787494 0.2074789219755522607 0.3603935870829781396 0.1390434653337753179 0.2332037133803844531 +'MRO32-1706' -0.1087741636176016158 0.03333519879229727978 0.09020687306929475735 -0.0002436270116799254225 -0.08081828468970840562 0.2290552876885150746 -0.216981546773290207 -0.324944769024212432 -0.0240884604532793957 -0.2020856418585134651 -0.0369592344382079982 0.2853976405614884193 0.005429632116573002328 -0.004528067678526469589 -0.03633638412096942827 -0.000248572441359931097 -0.08010234413675237919 -0.2241631535413881327 -0.2225341938135226294 -0.3338518539918073347 +'MRO33-1706' -0.02533887649724315613 -0.03334882922997218363 -0.08998682364949989188 0.01988763421954067162 -0.1467871015991251138 0.0155571339412026409 0.2444654391110442637 0.3613000654319142302 -0.002185657294263091896 -0.01758022063736399895 -0.008301246034923645545 -0.3146028371800014822 -0.002058524571889519192 -0.0005954442418589613387 -0.001815652475860966364 0.02029133697752391954 -0.1454867666676281923 -0.01522486662289178165 0.2507214102620719531 0.3712036881037409364 +'MRO41-1706' -0.1318835467722205557 0.02509851316335850319 0.06601022801180113364 -0.04406543436568154115 -0.1707656107408329349 0.3669737316865546162 -0.1878796017412906194 -0.3190554244422296182 -0.07454240134044072541 -0.2921773931478982012 -0.1027944273095854483 0.2525191788905997714 0.01000684716213734969 -0.001524081956684707195 -0.1032478323597157965 -0.04495992675169276087 -0.169252858691602226 -0.359135952685688542 -0.1926875180366742213 -0.3278010761522508476 +'MRO42-1706' -0.07318938945963861242 -0.1590908096926428317 -0.1672869050411737168 -0.01193371074095540656 -0.01972110418109116609 -0.1251373047666229921 0.2351644925913276563 0.3960703128377357496 0.006305162994235082724 0.09493145152750688542 -0.002161588196992130818 -0.3068127483431794533 0.005679218381249857839 -0.003308924782297256034 0.006955195658859420968 -0.01217595533807115486 -0.0195464019056528493 0.1224646378838539079 0.2411824486948452029 0.4069270253190029885 +'MRO43-1706' -0.04460931854263572305 0.02719773910218599433 -0.003728426641930664837 -0.07593844347411667084 0.2602400875255623247 -0.1422747006965756622 -0.2471334134969108975 -0.41506257810071151 0.002433305663614115238 0.1172890961571882301 -0.00804006039315415845 0.3231783102257934637 0.002124297435654079469 -0.0100204441153366481 -0.008774519017626986397 -0.077479931955302353 0.2579347127841938314 0.1392360154578551057 -0.2534576592099804238 -0.4264398889622277311 +'MRP11-1706' 0.09091342290745632604 -0.08509583464003678266 0.05410142364072195731 -0.02839194248750643787 -0.1405666560577371882 0.06987850919576898967 -0.09700962574462990151 0.1666413209526842465 0.04793745535868150498 -0.1130568192580671399 0.177015219918323391 -0.07949211126512761849 0.2933596063384565911 0.1127250224886619939 0.0349413940588477398 -0.02896827576878964125 -0.1393214258496036639 -0.06838605274808451373 -0.09949214197366111623 0.1712091384599333521 +'MRP12-1706' -0.07244204547305001241 -0.1090743396722866632 0.1292169644961305153 0.09739089495020634979 -0.03231249842259252547 -0.1466504663197842895 0.2089179425745801288 -0.1469124826604693845 -0.06647132220092623334 -0.001206703358727696795 -0.07039956611653661045 -0.07035579305218907231 -0.3234175762193998716 -0.05885811759713729246 -0.06836217779079099832 0.09936785070370793282 -0.03202625344626221227 0.1435183240269125027 0.2142642386662945986 -0.1509395115299805024 +'MRP13-1706' -0.06685284636917024348 0.01393180430551429344 -0.009030272210802998967 0.2153575925059789953 -0.2012203252896204719 -0.1704584524734704953 0.1825707165983682101 -0.1239009772266408682 -0.1031653192855565698 -0.1707604600172206166 -0.0008085777422766498614 -0.04861434372340728977 -0.2859462141145162062 0.02302053062172365605 -0.134654492496094097 0.2197291760280589423 -0.199437785713249216 0.1668178221940861961 0.1872427763390623612 -0.127297236027912819 +'MRP21-1706' -0.0321846866134685855 -0.1203327754998208265 -0.02494411870797171027 0.1052549201448559901 0.224935908466461415 -0.06439032125882331037 0.1582573289659364169 -0.09703511583425827869 0.09927980543914520506 0.2335898083980518236 -0.1815915229382112084 -0.03624206333944344355 -0.2421006006834806601 -0.1177582487392547922 0.01366474968060247056 0.1073915091973655367 0.2229432809403335269 0.06301508084174492486 0.1623071991154746985 -0.09969495253257348866 +'MRP22-1706' 0.001373885231302659354 0.05190617500167100939 0.006231894938661670935 -0.08424306106916294723 -0.1434806735565201108 0.1051964348668135429 -0.2204480265687690788 0.1038958784299011812 -0.02572005083577275433 -0.17458896117410308 0.1234028916148416644 0.09867831541313423771 0.2794316308720455888 0.08803075237259211372 0.004972999485524236783 -0.08595312651581904495 -0.1422096290996999746 -0.1029496625859317865 -0.226089382252951332 0.1067437759964230126 +'MRP31-1706' 0.03961518347503724391 0.04878567593913155087 0.06472177217925165205 -0.1266902054632001173 -0.2104101275326138165 0.1340896529867566522 -0.2499581906438838041 0.007149305199927877968 -0.100775157535556284 -0.2489673574284274604 0.08792403018124492209 0.1633858409578691495 0.2051967419307717533 0.08495421116759854785 -0.03005737017492284696 -0.1292619133290208999 -0.2085461787537994938 -0.1312257829719112312 -0.2563547235661547963 0.007345275330686571076 +'MRP32-1706' -0.05969335356130192616 0.04884364254600762068 0.06239727238831098421 0.1065206128061736562 0.001712781428890655221 -0.1203525303299126936 0.3166663456728607828 0.01914302189583558939 0.006865863683347846885 0.09497291959942964767 -0.04740770657389491854 -0.2349377722579154282 -0.2213264971115342927 -0.03752001214396780832 -0.009730552787549379828 0.1086828943876432807 0.001697608504991057407 0.1177820560603085737 0.3247699677236279836 0.01966775267723812337 +'MRP33-1706' -0.06236168639862664509 -0.02919609626726288321 -0.01653635510057613334 0.1995734623595420421 -0.2503735742719284674 -0.06969331434919955048 0.2994971187813960656 0.009959877265647461286 -0.04978464791958937818 -0.1302968380902898016 -0.003417567749370875943 -0.2236833875499582569 -0.2174361490145962361 0.01845991482130362668 -0.0487385055858143984 0.2036246409102642485 -0.2481556034761110696 0.06820481326985392001 0.3071613732532165186 0.01023288819405335573 +'MRP34-1706' 0.07451672209536142066 -0.01964245882179521674 -0.1057052840013412154 -0.3537795235039212782 0.385263812209249823 -0.0192444446037038433 -0.2179183359184919122 -0.03017081540125064743 0.06824896892857384989 0.2908878349744518643 -0.07068156199879936652 0.1699446742481623973 0.1612842353955718233 -0.1274869112653244929 0.03490003323420842046 -0.3609609593539532257 0.3818508965824700119 0.01883342416606915981 -0.2234949557783110219 -0.03099782984166633837 +'MRT11-1706' -0.08448217322366359527 0.005330033603299871511 -0.002513868483830547507 0.2970825306806210153 -0.1056530983298611115 0.2210735936133791657 0.01485774315382389077 0.04406581052119701997 -0.07826293556993635381 -0.2372353792300817554 0.2875401013398221073 -0.04377648865668318928 -0.009130838517003542903 0.3515318445110414691 0.2710547978388109791 0.3031130638079131967 -0.1047171549609784702 -0.2163519314886662437 0.01523795891306452439 0.04527370169500138236 +'MRT12-1706' -0.01826875387727217026 -0.01255893231891157258 0.04620318101849359149 0.3932227256378996727 -0.2264713585281721564 0.2811676860222742103 0.04312004367605091343 0.08728678655800681252 -0.0429147367907022001 -0.3112634655187738186 0.2353726864021187526 -0.09275144577236230092 -0.01068737625239260872 0.2693889665745742845 0.2193041172702692443 0.4012048263286764893 -0.2244651289939041949 -0.2751625417981919397 0.04422350333173622611 0.08967941108541550854 +'MRT13-1706' 0.06143658709263687123 -0.02429376303086969863 -0.1189003301768871146 -0.3886853350509835714 0.3494254567756627794 -0.290515730651019044 -0.1010536135958220727 -0.1552934388321740578 0.01229753380494272297 0.3459005945611928201 -0.1461099416469029688 0.173032970577711942 0.01989949574357055551 -0.1595660262461908174 -0.1325471050566982278 -0.3965753304127017098 0.3463300204433851226 0.2843109320605229362 -0.1036396171375145309 -0.159550198707835017 +'MRT14-1706' -0.0934989887112458451 0.02418591090685225098 -0.07546725985374881651 0.3395129292446765756 -0.3763745754767839347 0.2792411365015105007 0.1336135746180418249 0.1721410733107822388 0.005538095603431817358 -0.3343932713005484114 0.1059756921351160952 -0.1967164085420742281 -0.01106121796058463086 0.1103257244265740122 0.1062673592548190604 0.3464047648644394961 -0.3730404064490692728 -0.2732771392808077127 0.1370328009562747362 0.1768596449344968236 +'MRT15-1706' 0.06924189845566677826 -0.1207172340985713938 -0.05564500889705686903 -0.2219000834627985475 0.3618364358044361961 -0.1659958841817762709 -0.2244279148128164036 -0.2045623423771165683 0.001827107526805415386 0.2427992347298212616 -0.04551977761896566776 0.2672749549952029291 0.04563553260761370189 -0.05025887900664510743 -0.03214279317161550242 -0.2264044742164572077 0.3586310550057212887 0.1624505648770653843 -0.2301711174743449051 -0.2101696157922102459 +'MRT16-1706' -0.01144848411101582857 0.02243757269311213998 -0.04890303599169169152 -0.09077905863521555652 0.1840463484126602378 0.006589680063641904784 -0.301780045338034264 -0.216495837863997842 0.009508448440316865508 0.04223656775818457332 0.001287752289909258139 0.3163459238792002415 0.08063946759148558907 -0.004957641380678504822 0.005858728672343345607 -0.09262179950291264674 0.1824159470132986627 -0.006448938502146830606 -0.3095027208395517149 -0.2224302212017447156 +'MRT21-1706' 0.155748628331710659 -0.0267638123030705874 0.03852731274639387138 -0.1693394994845449086 0.03386935837351044004 -0.155725517569714339 -0.005131458567266230716 -0.01704573757168450013 0.08302785032164439194 0.1442048733039289765 -0.3490921117004178176 0.01273554114548543399 0.005175508193981940425 -0.3764298467609032972 -0.3463295461960160804 -0.1727769532421288556 0.03356932172641632905 0.1523995514688234743 -0.005262774702897696222 -0.01751297953819545145 +'MRT22-1706' 0.06279125836471208255 0.03876640877924443507 -0.08552350741298803127 -0.3388887099592233776 0.1449015924992736459 -0.2664522091135295701 -0.02166978958355749232 -0.05981434410406401281 0.06189547170882842009 0.261653031346809839 -0.3058614908554006528 0.05498959288208550567 0.007663555906850926663 -0.3236569477279402363 -0.290357388019215068 -0.3457678744364893753 0.1436179606249219365 0.2607613562022694786 -0.02222432841316276247 -0.06145391949041578705 +'MRT23-1706' -0.06201597286485143606 -0.01078243381468511897 0.081652924768020399 0.4086058485054042122 -0.3334910139132320483 0.3386312097769583751 0.08719325379927823916 0.1606512652001204911 -0.0245114083995646645 -0.3421008265966746231 0.1812531823087500105 -0.1523580383354619927 -0.01395603294111404796 0.183999285272995583 0.1712801867821796553 0.4169002140467635287 -0.3305367351652531704 -0.3313987668093654748 0.08942456503213008778 0.1650548888484903998 +'MRT24-1706' 0.005269852982638222744 -0.02048148614599409889 -0.05510692084162467641 -0.375595922231928725 0.3835455901131707424 -0.3292457244758767443 -0.1247889157694017787 -0.1880223463534416439 0.007076019971924291281 0.3403806789666197763 -0.1469490950926675976 0.184829122919536154 0.01345520678294684011 -0.1381895991579571159 -0.1376085915729550468 -0.3832202131867226136 0.3801478956072335547 0.3222137355278880677 -0.1279823154575548683 -0.193176240720800696 +'MRT25-1706' -0.06844079662230366512 0.06180557438681325011 0.01365980696304658348 0.2828372625993176293 -0.4038339099889616812 0.2823294657081341641 0.1891373649000410717 0.2392063259700661637 0.006722746203060924776 -0.300447124196000559 0.08157507865480070897 -0.2424441340951825619 -0.01499618368305141725 0.07239940577769447827 0.07963964750366377132 0.2885786284003633573 -0.4002564884446917493 -0.2762995083390245576 0.1939774678720549983 0.2457632281679372754 +'MRT26-1706' 0.02532067772175256373 -0.003782853576499475845 -0.001720949951281622314 0.1050888806572391476 -0.2816581855451608662 0.1292270460145213962 0.2446569367688023744 0.3044522565771751177 -0.00191761557639429309 -0.1446153014900228018 0.01474395691265615281 -0.311689257249497087 -0.01575529219852555424 0.01580749954448290931 0.01140360900008644332 0.1072220992435411746 -0.2791630754611246212 -0.1264670309503868884 0.2509178084236673434 0.3127976197785962142 +'MRT31-1706' 0.05976398660378959282 0.01687755761853252517 -0.0510291337793060823 -0.3086746709116662268 0.1125647708475518705 -0.2863311199505572668 -0.01368354888154532482 -0.05950058235337607471 0.06910680008013324327 0.2454203904794841351 -0.3439740680879053158 0.04747178602789680485 0.0049284476555383986 -0.3316876876261776186 -0.3343655254630220064 -0.3149405150332447723 0.111567599420400454 0.2802156957513127211 -0.01403371652633760708 -0.06113155719329852605 +'MRT32-1706' 0.07643614064726578228 -0.01464124375973278186 -0.1569458681881034656 -0.3964372002504353842 0.2342102872439691119 -0.3521369471898071479 -0.04624278513140918367 -0.1152329175635172787 0.03863912532424536306 0.3140767989100335389 -0.2791678693348662588 0.0981529599903037675 0.01171531186390875091 -0.2582227365812956865 -0.2670245992220527942 -0.404484552154716015 0.2321355012818414887 0.3446160503740351433 -0.04742615702551918055 -0.1183915755437158768 +'MRT33-1706' 0.03709670006858418329 0.05456972555440108008 0.1239836536421827645 0.4080911873358347708 -0.3789762305181581525 0.3934450162942331741 0.1115701114680978517 0.2083989110951881552 -0.01772536798665411487 -0.3520856768378927137 0.1918939750879667394 -0.1778581730629515412 -0.01473363111280816783 0.165486470792466589 0.17959808617072201 0.4163751056751141544 -0.375619014350108027 -0.3850418669120306281 0.1144252365164459828 0.2141113489776419465 +'MRT34-1706' 0.00283946414248180401 0.02351879575908732978 -0.2249981390990651309 -0.3397475311866878789 0.415745055615732384 -0.3585738196145702439 -0.1610164625333277144 -0.252088181049104243 -0.002809727236749775744 0.3303191632080401119 -0.1387378769354527253 0.2247596873891006819 0.01270443054485766513 -0.1094406023159156249 -0.1273232583952539909 -0.3466441290345758097 0.4120621174520598951 0.3509154448837162321 -0.1651369400458626568 -0.258998188724173295 +'MRT35-1706' 0.001388028708025478009 -0.005254980931497649221 0.06202308809091870712 0.1793780557049627633 -0.3587292706962945665 0.2494593852504861653 0.2228105507443027544 0.3269661932461752074 0.005131026113919879075 -0.230699748903987728 0.0462183602234476007 -0.2877541982900571615 -0.008131601578235942221 0.03371846888625342625 0.04449635292021266592 0.1830192839682326933 -0.355551415172512042 -0.2441314629430789973 0.2285123643939933891 0.3359286876218201545 +'MRT41-1706' -0.1854172948840371871 -0.01378932618833311752 0.05038116377072511531 0.3444910106824735641 -0.1493508287430190262 0.3315741882651958017 0.02382002289817803514 0.07862309522611271584 -0.04564831431687182278 -0.2642111881338651824 0.3502138905368340493 -0.05845392967163402093 -0.005943530913353980809 0.2981764179373116441 0.3495903171844591539 0.3514838972962219255 -0.1480277826609937286 -0.3244924682792162396 0.02442958708283209102 0.08077823867309683048 +'MRT42-1706' 0.004685209749061006873 0.0270107464450301607 0.1064786175451871431 0.405564569849272305 -0.3238440919547319607 0.414733165560908057 0.08256969496974458922 0.1896153179315436255 -0.02913211360075013828 -0.3334128690584848842 0.2277452671871685597 -0.1448190609690093444 -0.01183572498502765032 0.1890980488950824434 0.217343017245908432 0.4137971999138161383 -0.320975271870814316 -0.4058753465528367466 0.08468268743018497746 0.1948128773600135144 +'MRT43-1706' 0.06428756437833564596 -0.06615687200426181858 -0.09109689871753426371 -0.3701089625246422599 0.3802544157392230284 -0.4061641501277884481 -0.1297730590036710596 -0.2368310715350214479 0.005476788674316687353 0.3297426546219510701 -0.1757437995950493492 0.1851275828213302388 0.01440685151634308464 -0.1350429327878975572 -0.1711112029019075664 -0.3776218726715269147 0.3768858765811160527 0.3974893470781378224 -0.1330940049674840253 -0.2433228654588431294 +'MRT44-1706' -0.01523688774367132348 -0.08891689057968117649 0.04841002088626875782 0.2406435970187885964 -0.3896858672821779668 0.3442578621406999773 0.1862269920188888706 0.3260221425503641579 0.004737099873146293806 -0.2792810289515386124 0.08044012008840235872 -0.2510935518153261659 5.648181728558354653e-05 0.05345759104423266489 0.08118235994736561212 0.2455284658138934539 -0.3862337782360873439 -0.3369052458366149638 0.1909926173516527659 0.3349587594829391279 +'MZC01-1706' 0.04204025588050766538 0.09973611267435579519 0.02751996430813627784 -0.02391931916997655852 0.1417986173777720793 0.07046624507028984019 -0.01114579712558720105 -0.1187209928182630519 -0.1524031334710047869 0.0242711122943844379 -0.07478573253701592538 0.292488297364044858 0.1098190239519626077 -0.1406678154557412797 -0.1787756247308593116 -0.02440486184495763156 0.1405424736607455705 -0.06896123583340652008 -0.0114310226590058836 -0.1219752626858623124 +'MZC02-1706' -0.03607334764599564453 0.008660565657927537381 -0.08199383785160102578 0.0329860961456469523 -0.1319213007654680969 0.002158133791314099763 0.03143593947386275761 0.1017413749458724176 0.1808832834405825762 -0.001855346596270791328 0.1207378287763004043 -0.3097376284771757859 0.01094083326236182027 0.128203204180871666 0.09798964025104563158 0.03365568700004902686 -0.1307526566971197735 -0.002112040640088035885 0.03224039809659923206 0.10453021525890209 +'MZF01-1706' 0.08590626839178756857 -0.01441090509424085286 0.06102063561358359728 0.4241320184700321239 0.3634629310188698392 0.3227551601388116698 0.09622372620780363095 -0.1536188736744157901 0.02391844281582552675 -0.3356654992592253972 -0.1708291472305303871 0.1567508161884614282 -0.01246809356519270641 -0.1848060935747454225 -0.1621384487923093476 0.4327415526014029568 0.3602431416752608917 -0.3158617958510432366 0.0986861309443969742 -0.157829731921351718 +'MZF02-1706' 0.09091109253604076623 -0.1927384347315918567 -0.1619876378899409719 0.3995099705574585713 0.3205411093931799793 -0.1085954633461616997 0.1572927879771929272 0.06087473096350234231 0.1412249934014974395 -0.2666872331735322121 -0.03650186088532945267 0.05176850050408973031 -0.1913419291705447112 -0.1935688156523877324 0.1659936880197643294 0.4076196971933890301 0.3177015492616429015 0.1062760950407188459 0.1613179751260523376 0.06254337269206330929 +'MZF03-1706' 0.1013126457081718335 0.1451283779715137057 0.06648925893965323963 -0.08476145778963735389 0.05880682163312014876 0.1821951059880053125 -0.02572129604377287881 -0.1590329724559112479 -0.1318265732416555869 0.08204214584699960622 -0.07162315054781388801 0.2094715310002542574 0.1927791920019187033 -0.08276685631835581369 -0.2684877993627400317 -0.08648204626701068432 0.05828587283348588 -0.178303805732778653 -0.0263795145903372337 -0.1633922369628234006 +'MZO01-1706' -0.005308725741457413078 0.07783520895170410736 0.07396499431747347031 -0.1322184213759801108 -0.2240929329331750042 0.3304941606069153881 -0.1162130444180013294 -0.1569902555624272666 -0.2003804821685873649 -0.348283595764672993 -0.1475557273861506091 0.1657619163477621615 0.02142630600776433691 0.03896733021231457011 -0.1734157207390877309 -0.134902347517040555 -0.2221077730286595275 -0.3234355077163966752 -0.1191869840304710104 -0.1612935270063039495 +'MZO02-1706' -0.02658155735603297612 -0.06707571527719961846 -0.1683905967408728943 0.1261991479225860746 0.2127925096954688677 -0.4211122313449436882 0.1012264488089415077 0.1966053177788535389 0.1942740074706133802 0.3398634522670653801 0.2108940663187433839 -0.1554142098042013975 -0.005942282051400559276 -0.03008190739925795804 0.2235332349426182585 0.1287608877207480351 0.210907456237068941 0.4121181690487834004 0.1038168752748358376 0.2019944806073426247 +'MZP01-1706' 0.04017854860732768263 -0.06762024079843045876 0.06576559996076289383 0.0435609739308873839 0.1791420077131553323 -0.01508717018906922773 0.06297567838672223084 -0.1336379212849230502 0.009000035625792287761 0.1523863514908494199 -0.259132967100815681 0.117638510210997721 -0.2345061145769041511 -0.1244779544471104477 -0.02167437933398821265 0.04444522618141683729 0.1775550521306131224 0.01476494029771726994 0.06458725190253843118 -0.1373010801760541078 +'MZP02-1706' 0.01113696669382539112 0.08490576745599756614 0.0002751195819735569037 -0.16714673477936276 -0.274570363993646982 0.1076932575458072056 -0.1680748259937583367 0.03143321464885555361 -0.2154572990851696956 -0.2916368649096758303 0.12624924793755124 0.08224191488986806742 0.1806151731626295665 0.1339468366791077003 -0.05862429606164578505 -0.1705396772014445284 -0.272138042409766856 -0.1053931584388543147 -0.1723759299307992821 0.03229483280791303063 +}; +coef(end).label = temp(:,1); +coef(end).value = cell2mat(temp(:,2:end)); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +coef(end+1).name = 'G2OI'; +coef(end).reference = {'P11-1706', 'P12-1706', 'P13-1706', 'P22-1706', 'P23-1706'}; +temp = { +'MLC11-1706' 0.2882758246354492626 -0.03120999774279694522 -0.1054929283772120807 -0.2717653434718079186 -0.1721714336864499373 +'MLC12-1706' 0.2707115714046856025 0.002556669069641236483 0.00532606715271141673 -0.2118278906254209282 -0.2543955638270479769 +'MLC13-1706' 0.1451419226914006655 0.1144647065373022299 0.1200584513961427402 -0.02608330423637332876 -0.3099282303472095657 +'MLC14-1706' 0.02297076671314541435 -0.258266292113235707 -0.1756697927087090549 -0.07532023803989948418 0.217374120317144176 +'MLC15-1706' -0.1490165849442950108 0.3200698826228612348 0.1134730579149910434 0.1174294116552293543 -0.1023067954490225889 +'MLC21-1706' -0.2939459996674608222 0.007740420184267527044 0.02548910979135213598 0.2679113682477302638 0.1750479156274055703 +'MLC22-1706' 0.2477248366198913088 0.04435263213132555754 0.08169014209414329764 -0.1837107949230099013 -0.270008064801653902 +'MLC23-1706' -0.1264284317559201121 -0.1443622213124367559 -0.1959776700662004267 0.08823032725680611532 0.2571663009859624371 +'MLC24-1706' 0.04197965668630763286 -0.2540058346419358237 -0.2169455027664035085 -0.02352252380137997631 0.2007298166134338646 +'MLC31-1706' -0.2770222792240450982 -0.02816859258104389627 -0.0804682834726284657 0.2491618235131626835 0.1936094136902788143 +'MLC32-1706' -0.1596946199654126763 -0.1101175402019794053 -0.2363698624596247411 0.1754218964993517482 0.2012837385526677625 +'MLC33-1706' 0.1709504486010900992 0.01840543196989581631 0.2825666388593609524 -0.2461674043874238216 -0.03167648659483182638 +'MLC41-1706' 0.3092969582147505059 -0.005015433824104452779 -0.02945142491651119715 -0.3000665835747561294 -0.1033281034840016072 +'MLC42-1706' 0.2929364326540206953 0.01312174951724293104 0.1187006751311367181 -0.299092458347635648 -0.06580511760359740447 +'MLC43-1706' 0.2380185347009860786 -0.04172518187747005503 0.2011510500396395396 -0.2613833180249839905 0.1111197476859226707 +'MLF11-1706' -0.0653212325808427835 -0.2735619830659467566 -0.01025223449824854381 0.2526869886170121648 -0.020144837230313236 +'MLF12-1706' -0.009113275019503310967 -0.1164022572345058404 -0.004974738420955654265 0.3089160198733825191 -0.02809736129861412079 +'MLF21-1706' 0.09239021496591647009 0.3122958158447293742 0.06150928991830794529 -0.2047919666336068256 0.08941774473149002866 +'MLF22-1706' 0.01985237319200582398 0.1877772868271440077 0.02910331337218240513 -0.2792836678639408765 0.09438729015165442382 +'MLF23-1706' -0.001751182885548752165 0.05921801322000715129 0.002587505319376641813 0.3215048164518695128 -0.02989991938723269432 +'MLF31-1706' 0.0201767018301880971 -0.2077977888862391487 -0.1106719877716045575 0.1473312268916143197 -0.2402183497190712169 +'MLF32-1706' -0.04144600962507432457 0.04462630315221136068 0.0168058333577182778 -0.2368072568641025055 0.2236569539676231122 +'MLF33-1706' 0.01867234286082305669 -0.1979617281201427326 -0.04040957588002060813 -0.2659863553008675052 0.1207557861832349727 +'MLF34-1706' -0.04888544195959795141 0.2479072499064756963 0.01582246065609179894 0.2714256504442650875 -0.03695801831738865229 +'MLF41-1706' 0.1120229228313913972 -0.1581394049012047887 -0.2017474727665534984 -0.0727704840724649471 -0.2605534334953005238 +'MLF42-1706' -0.1332659834567252732 0.08594136762138628038 0.07475533610891614555 -0.03185955837584739103 0.3211450999577711851 +'MLF43-1706' 0.0556908724160892557 0.1402574910259281327 0.0760581144898714312 0.1592212392059628445 -0.2686722654885064787 +'MLF44-1706' 0.007955074663295390314 0.2052817685187591501 0.08763306136186609085 0.1917042781632272708 -0.2163891613977388106 +'MLF45-1706' -0.10857089237927392 0.3276269581147815968 0.0742547100966179513 0.1882389165924465146 -0.09593709909227673971 +'MLF51-1706' -0.2311641711304221747 0.06326781060489868047 0.1102874456449588758 0.1681849132640110822 0.2731198417089248376 +'MLF52-1706' -0.1959762162296030952 -0.0435567223805512771 -0.05392624319712389924 0.07850671350398787107 0.3154077620128406534 +'MLO11-1706' 0.188040483148237042 0.3204383247987012684 -0.1088987423746517191 -0.09877820864597226802 -0.08145627098427889179 +'MLO12-1706' -0.2677562350111690748 -0.2024945157288647601 0.1324892651189990278 0.0173346636823901723 0.04478467684938867294 +'MLO21-1706' -0.2567443063286396487 -0.2791827929041414413 0.0236819846256173562 0.06679491816959798323 0.01212881403351893407 +'MLO22-1706' 0.3187958652859171904 0.08032764991436761037 -0.02206570290726060993 -0.004126298369180464443 -0.002621017642216875391 +'MLO31-1706' -0.2070455860673502957 -0.3240599933700139546 0.01612034334958025589 0.1122357733597204726 0.01189052252659221487 +'MLO32-1706' 0.2945227928691284136 0.1925948181501072609 -0.01784666341710804127 -0.02770024787398775099 -0.005502997760545315017 +'MLO33-1706' 0.33123839191812815 -0.0232177786240188172 -0.01749512453759982655 -0.0001398901227021657199 0.0005783700591417944691 +'MLO41-1706' 0.2488297132318827709 0.2685303411983450128 -0.01691329256931119879 -0.06404411479800468932 -0.008604723072321249569 +'MLO42-1706' 0.315179958629739132 0.09321640608876378964 -0.01621437749271109272 -0.005922024598868695644 -0.002261818546464018208 +'MLO43-1706' -0.3064678256674615575 0.128661805661052786 0.01904556413948683274 0.0117072903063823279 -0.003770121458569130127 +'MLP11-1706' 0.07409718857426442207 -0.1145009382414202692 0.2948034262586526899 -0.1595715105173279302 0.1417686534780706609 +'MLP12-1706' -0.05533120166471061641 0.001445878194115893765 0.326275987728952499 -0.1342072209955394724 -0.001170311024293257561 +'MLP13-1706' -0.03400580237496988317 0.1681031817683860397 0.2888211829190402424 -0.08588902376493311175 -0.1433602685633046936 +'MLP21-1706' 0.02891586574946547819 0.2221234152493576086 -0.2490117769257594871 0.02841232236650191936 -0.1897393948560113786 +'MLP22-1706' -0.09074733769460201216 -0.1658980556432302356 0.2850203534834693797 -0.06944912682898449208 0.1159293529040759246 +'MLP31-1706' 0.1617014658541526817 0.2495954579377616112 -0.2147949753743080004 -0.01299138058915705676 -0.1183769167205985379 +'MLP32-1706' 0.2328450886003847198 0.09441878883438181713 -0.2243519347893738469 0.03647010210456870516 -0.03613053527368102064 +'MLP33-1706' -0.2227662276745906722 0.1286275650546016558 0.2298728808384410682 -0.0333288994312119502 -0.05169199561518745406 +'MLP34-1706' -0.1715450793661448814 0.2893093848180111061 0.148430531689724865 0.06713024264392333795 -0.1021882656228587372 +'MLT11-1706' -0.03950391512582699521 0.2223488722060107114 0.008611991530144004481 0.2745201917026739435 -0.02262069580646115102 +'MLT12-1706' -0.08948634643692650326 0.3062504395727334572 0.01179956657469517778 0.2315433758472659476 -0.0189791755608124009 +'MLT13-1706' -0.1735792143005089327 0.3451945807914174602 0.02144806843397334753 0.151345012910839738 -0.02005695760150492599 +'MLT14-1706' 0.1936338582874379544 -0.3273975321723666676 -0.01698438558071153903 -0.1224176624183875295 0.01352823502386997501 +'MLT15-1706' 0.2654214142353523709 -0.2432025609773219021 -0.04752881349927528393 -0.04711279333707184269 0.0203971923338452793 +'MLT16-1706' -0.316138268520930632 0.04750628991843062338 0.08924556488330348536 -0.00437391060919731841 -0.006212226955779655453 +'MLT21-1706' -0.01373229354245368225 0.1392472333064813106 0.00536373590988593104 0.3024935248571345991 -0.02478861110195732659 +'MLT22-1706' 0.05376274425761890657 -0.2552972057567962638 -0.01072863969528590859 -0.2663252863892679456 0.02381764726141846755 +'MLT23-1706' -0.1501734759342365499 0.3453946997867533564 0.02247798273796644541 0.1747681729769871017 -0.02426907264751922491 +'MLT24-1706' 0.1828304180809965929 -0.3359169521261648472 -0.01802964520583870411 -0.1363921888619753497 0.01559755442196450806 +'MLT25-1706' 0.2382682952782238794 -0.2934327202072343765 -0.01827096728895463706 -0.07984660874488416771 0.01060449495459777312 +'MLT26-1706' 0.308454512523014035 -0.1486619637226493096 -0.02213062658403951513 -0.0155201903306658711 0.005027649793544570686 +'MLT31-1706' 0.04551183456170396907 -0.2342756726072209861 -0.008178595482797779495 -0.2655566310817074061 0.01971694201508631186 +'MLT32-1706' -0.09243689882928650403 0.3053299196854436515 0.01216393342110120949 0.2227861278406501888 -0.01888411568809355429 +'MLT33-1706' 0.1765551656062118446 -0.3532853830266671213 -0.01446514738924366793 -0.1565397098266445852 0.01363852840618042656 +'MLT34-1706' 0.2139263630818607487 -0.3303679088139176989 -0.01544049635173570453 -0.1129543933409746376 0.01123960168364337465 +'MLT35-1706' 0.2891640624776887214 -0.2344472189545973861 -0.0186863716695061452 -0.04190466050340616727 0.007143149121790612864 +'MLT41-1706' 0.05613626424617368382 -0.2547510963067269318 -0.008532354001643182792 -0.2551553964542446762 0.01817368236061459377 +'MLT42-1706' -0.1418537546936807225 0.3360626631820053389 0.01298100207607117557 0.1762653239482036283 -0.01448485064730739569 +'MLT43-1706' 0.1777181766462496426 -0.3248761645591489167 -0.01503696086576308821 -0.1314292718158479589 0.01295087025989425343 +'MLT44-1706' -0.2382114437009178187 0.2828848830097625555 0.01737743484274609576 0.07424539005954737536 -0.00972696164839428716 +'MRC11-1706' 0.2690966272697508654 -0.03420070890509311484 -0.1741191208968008997 -0.2819736177038322245 -0.1130251679918460456 +'MRC12-1706' 0.2133678258301035802 -0.002887697478237460751 -0.2411035011349615398 -0.2646224466039233114 -0.006237398518784461471 +'MRC13-1706' 0.01971951050431900582 0.1181499308935818199 -0.3073150357727655324 -0.1382964508755176458 0.1212237092265487509 +'MRC14-1706' 0.07895830497971247086 -0.2610847331555283812 0.2170236341866025875 -0.02514173518480369504 -0.1746442564861342694 +'MRC15-1706' 0.1201571272919262634 -0.3262080053496420051 0.1032604981649825338 -0.1520414824112646113 -0.1146235957327424032 +'MRC21-1706' 0.2759113263172232045 -0.005405008568720096399 -0.1774252909518069243 -0.2992853162801875078 -0.01795604698726411749 +'MRC22-1706' 0.1858090498041023164 0.04510170942281802736 -0.2663488615075146337 -0.2453091385220129705 0.08396909421387847849 +'MRC23-1706' 0.09308424905259089777 0.1441351570512157121 -0.2575391990423077093 -0.1280129163411886095 0.1986104105891146332 +'MRC24-1706' 0.02187582370436531518 -0.2503687890967836727 0.195526407500792393 -0.04424234848579100543 -0.2147861470229526781 +'MRC31-1706' 0.2501118354072580652 0.02851724921224238138 -0.1906696193935734085 -0.2740056378769517575 0.08234765429483695276 +'MRC32-1706' 0.1801766832188144152 0.1076426705923665406 -0.1937614253997617386 -0.1570676463715844073 0.2404520703191420639 +'MRC33-1706' -0.2418711014848120844 -0.01937036393100139905 0.03271281352133925679 0.1631644674327529243 -0.2815794914457797615 +'MRC41-1706' 0.298414406084870909 -0.005808284948225599098 -0.1075088415339297693 -0.3050428955851984258 -0.03251707854280969784 +'MRC42-1706' -0.3019162954950597721 -0.0150937896165679649 0.07242118132738999126 0.292196514100403093 -0.1248581198776768791 +'MRC43-1706' -0.2617936158721271833 0.04184651262947680639 -0.1100198732120620804 0.2347470699234750491 -0.202886995201335546 +'MRF11-1706' 0.25102572866124645 0.2711331029081969213 0.01781468002146481544 -0.06468943111857271278 0.009070192571966010503 +'MRF12-1706' 0.3082383890721727693 0.1065996856314965074 0.0279936146303054155 -0.007566777779953144829 0.004560029759003688191 +'MRF21-1706' -0.1996873630900226348 -0.3046841333305525534 -0.09006890012770327192 0.08936647206025714885 -0.06195660821367301313 +'MRF22-1706' 0.2787793278732061952 0.1864871505715646749 0.09477396545008080764 -0.01946339661596619905 0.02913083089301551909 +'MRF23-1706' -0.3196962319866564206 0.05977931950319602394 -0.0265274988882367134 0.001952561942505099367 0.00233717465142020079 +'MRF31-1706' -0.1541717564570690979 -0.2075811142308803536 -0.2385042638051590169 -0.01872543504763774305 -0.1075335400377467332 +'MRF32-1706' 0.2365242339435248975 0.04069293930925910185 0.2183296177913348068 0.03981860515693522867 0.01508933335264873651 +'MRF33-1706' -0.2701382869909204065 0.2010134035111192929 -0.1184859183491530077 0.01988792064427201758 0.03984139471017113243 +'MRF34-1706' 0.277206234547004271 -0.251757135213100891 0.03579044121206432366 -0.04949802068967154578 -0.01527957803454208473 +'MRF41-1706' 0.06972356545337310418 -0.1570556779483562593 -0.2644119196520327564 -0.1133630047160334997 -0.1968371824439046069 +'MRF42-1706' -0.03815776628745096155 -0.07869509603263664943 -0.3207359241581183018 -0.1310891975871425197 -0.06702869328867649967 +'MRF43-1706' 0.1554953745709938828 -0.1402788213248585825 0.2728760518895503862 0.05796743358818410435 -0.07764922024070908257 +'MRF44-1706' -0.1891799642161861583 0.2030237471847192166 -0.2166067335230297819 -0.008839932107464349917 0.0876005084145633911 +'MRF45-1706' -0.1824240138889976492 0.3223061630363367458 -0.09410243191841580201 0.1083344043824291947 0.07399094072273164346 +'MRF51-1706' -0.1751776341806619286 0.06023851728731902111 0.2640233128343442703 0.2310622827687529302 0.1089928119661103117 +'MRF52-1706' 0.07164052372835255644 0.04970899560140586149 -0.3172626690705966923 -0.1902193112258701579 0.06001124722854464522 +'MRO11-1706' -0.1005671589023337253 -0.3184481836135348298 0.08215085066904470601 0.1822640209356397312 0.1075989749624769037 +'MRO12-1706' -0.01822304838708951533 -0.2043027395691204284 0.04487306914637103489 0.266774666951497097 0.1312926445156141209 +'MRO21-1706' 0.06577730604637746503 0.2752836806532742431 -0.01016876665559485887 -0.2541586930458559213 -0.01997064522979013004 +'MRO22-1706' -0.004893496022736055877 -0.0866546221016496615 0.002699715000534955861 0.3187184292095230354 0.02111289553308321604 +'MRO31-1706' 0.1195503184311552947 0.325986138347081289 -0.01156863996579928985 -0.1967981106213541331 -0.01485436431130437301 +'MRO32-1706' -0.03052190796262438735 -0.1976693397106427663 0.005167784966038890294 0.2823037885580250705 0.01568778171216827014 +'MRO33-1706' -8.079764946757514422e-05 -0.01336587985263110352 0.0003294383584753273701 -0.314006684307413908 -0.01644976023889444319 +'MRO41-1706' -0.07384492280286379662 -0.2863450522051803615 0.00804374953325440005 0.245806252801942321 0.01467881660550873942 +'MRO42-1706' 0.007553845574269186895 0.1033374251872434119 -0.002861038265026958922 -0.3036912924450048124 -0.01787380603422548259 +'MRO43-1706' -0.008884695967864262439 0.1143356893380604589 -0.002834788868179920294 0.3190705992750625386 0.01681408124898283937 +'MRP11-1706' 0.1636529644916352444 -0.1123118378097654191 0.141431568998499485 -0.07823527060214552353 0.2940222386631903273 +'MRP12-1706' -0.1344524497036454491 0.0018035190138875883 -0.001446774556747544831 -0.05880217978628444336 -0.3280915268834389553 +'MRP13-1706' -0.08407671474045583238 -0.1697742884644727057 0.1393912721874492333 -0.04556171358429891849 -0.2917272309729673219 +'MRP21-1706' -0.02402554041685992306 0.2304836081772463074 -0.1970541573577784256 -0.0291331444751189092 -0.2507370675528401982 +'MRP22-1706' 0.06804523203505868922 -0.1727238249174085916 0.1210981651810198456 0.09023369860717134205 0.2862600468267264553 +'MRP31-1706' -0.0124288852830982139 -0.2476026524321700562 0.1185423690638573307 0.1583258156037012365 0.2139307892448033266 +'MRP32-1706' -0.03671879484985802328 0.09567060089618774354 -0.03684938766839854218 -0.2302702342721110185 -0.2243057126641644639 +'MRP33-1706' -0.03283321225777938862 -0.1271266615553836299 0.05069962887499877141 -0.2219143248827675496 -0.2269423320523189236 +'MRP34-1706' -0.05807352504376002422 0.2873295648216210862 -0.1108917410117932212 0.1696495810992718067 0.1657119735469045063 +'MRT11-1706' 0.2784649242756098708 -0.2367940784368867124 0.02437523846682844442 -0.04414855025894403456 -0.009764492725799666512 +'MRT12-1706' 0.2311267612627858348 -0.3095602837305387878 0.0189674781959776502 -0.09160403874322066431 -0.01197020785157400409 +'MRT13-1706' -0.1477685147366601393 0.3412446774503195002 -0.01754140179891962303 0.1740133991651602874 0.01905376317115334284 +'MRT14-1706' 0.1195685582727329943 -0.3297996325490215042 0.01330056652603126693 -0.2011739297334531607 -0.01726290882101528049 +'MRT15-1706' -0.04593648998548987422 0.2413118683090362537 -0.01930341272777367362 0.2687328730280011402 0.04597751964976206501 +'MRT16-1706' 0.004475184478593583273 0.04026951520908507443 -0.005135458558074823196 0.3122573498599781061 0.08609269632732095834 +'MRT21-1706' -0.2979898783734901135 0.1439004855539918193 -0.01775737532988330356 0.01517383133724756021 0.004043605197747838532 +'MRT22-1706' -0.2661319616205501948 0.2566436408767915345 -0.02052028221081921358 0.05453519215382589963 0.009326016542110255464 +'MRT23-1706' 0.1616830465609692125 -0.335493155927043929 0.01774256636529579143 -0.1537714355642708919 -0.01732529806686393392 +'MRT24-1706' -0.1351993507670538053 0.3368658695943041459 -0.01452636730990351094 0.1856113116134285312 0.01703476785224634568 +'MRT25-1706' 0.07874111593583162094 -0.2955134698020839834 0.01187235652530052761 -0.2446673193495453591 -0.02091472215848995397 +'MRT26-1706' 0.01414206746639621107 -0.1421536790300834963 0.004746650830635270463 -0.3089435259932729605 -0.02193766761872376417 +'MRT31-1706' -0.2681039327266906969 0.2428181212324489191 -0.01688359986468553758 0.04856388096721252212 0.007209894006635116613 +'MRT32-1706' -0.2189353503320036753 0.3100210419010489549 -0.01719033450530795329 0.09707782229058130319 0.01147139082660934145 +'MRT33-1706' 0.1526067775490485279 -0.3501976804696779189 0.01418329196903104009 -0.177878232995817176 -0.01532905570521735095 +'MRT34-1706' -0.1076210753115257046 0.3233437238561964744 -0.01166089561883905563 0.2149506220699262948 0.01648828468929573743 +'MRT35-1706' 0.03952917498144791625 -0.2257756384973783337 0.006517990512011123151 -0.2844248597018838032 -0.01745638284769740131 +'MRT41-1706' 0.249519269584947051 -0.2600671751594011427 0.01627363702258671774 -0.05991343367436408746 -0.007996904994250479681 +'MRT42-1706' 0.1647009743847969443 -0.3294007709211726476 0.01464941567343870654 -0.1457941983477845371 -0.01380140457132374848 +'MRT43-1706' -0.1276092416581545153 0.3258644619749146987 -0.01423721443306406875 0.1839670022425759222 0.01710735668576828655 +'MRT44-1706' 0.06421548015713664237 -0.2688995707705105209 0.008068710371388123151 -0.2490094177243531437 -0.01588587950451505679 +'MZC01-1706' -0.2967596404124023257 0.02001082669780943762 0.10636961324527755 0.2941154377800699882 0.1125678135158421633 +'MZC02-1706' 0.3134699820933341541 -0.0003775164637455381681 0.02444472186528674068 -0.3122185721876272191 0.00949022300987163378 +'MZF01-1706' -0.1625806153583159719 -0.3392282875688631405 -0.01251892450806297609 0.1568188688576882539 -0.01231037757463507819 +'MZF02-1706' -0.04713288292349182562 -0.2608602793145025633 -0.2011839686279725259 0.04325673744016556022 -0.1979513651183880396 +'MZF03-1706' -0.2159046698706476586 0.07703254794835286134 0.194698541218714688 0.2144567561892637697 0.1952843497189999944 +'MZO01-1706' -0.1594711784599919802 -0.3442769741360834357 0.02594992692061309086 0.1631011801756426238 0.02627338333863271647 +'MZO02-1706' 0.1634084852976976643 0.3383229901496460634 -0.01370307753403180243 -0.1551049378954044433 -0.01336722097785999694 +'MZP01-1706' -0.1212316631637880143 0.1501663046130006784 -0.2394950979633920229 0.1220114500346160119 -0.2367774399422623577 +'MZP02-1706' -0.07424190874691369291 -0.2890710184374202241 0.1869301645091102082 0.07482911456239958736 0.1873395142419100046 +}; +coef(end).label = temp(:,1); +coef(end).value = cell2mat(temp(:,2:end)); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +coef(end+1).name = 'G3OI'; +coef(end).reference = {'G11-1706', 'G12-1706', 'G13-1706', 'G22-1706', 'G23-1706', 'P11-1706', 'P12-1706', 'P13-1706', 'P22-1706', 'P23-1706', 'Q11-1706', 'Q13-1706', 'R11-1706', 'R12-1706', 'R13-1706', 'R22-1706', 'R23-1706'}; +temp = { +'MLC11-1706' .01260050981901611987 -0.1278459799016925802 -0.1273419567487086013 -0.001923917025805598575 0.1587476838819164571 0.1436449445971240968 -0.03120999774279694522 0.0885395806894111459 -0.2717653434718079186 -0.1721714336864499373 0.1407632721782391405 0.1944662709505341758 0.01285628989369859247 -0.1267134376571318888 0.1246222031850210132 -0.001973150853925342233 0.1630991283227401223 +'MLC12-1706' .01055826230456967038 -0.11322357173668679 -0.1282203404228567101 0.03212822970716164295 0.1829662612023769952 0.1297597069912169443 0.002556669069641236483 0.1257031869077913644 -0.2118278906254209282 -0.2543955638270479769 0.1371826379622788916 0.1206462241773023497 0.01077258641998794786 -0.1122205642258487651 0.1254818264506671333 0.03295040432175121853 0.1879815628477200518 +'MLC13-1706' .05921228577804626969 -0.1286519791350161368 -0.1007485269384171822 0.1495548896960138818 0.1622167906772100932 0.03284560202762086545 0.1144647065373022299 0.163254184545968295 -0.02608330423637332876 -0.3099282303472095657 0.1092933787447173954 0.0432922977032507289 0.060414246896760046 -0.1275122968287849823 0.09859675251800555096 0.1533820608447684086 0.1666633270595970495 +'MLC14-1706' 0.1119402956200304944 0.2206365821810303274 0.1086716672526212291 -0.1689384254721353062 -0.05078101078293766751 0.1330209732947825185 -0.258266292113235707 -0.1359838144337361943 -0.07532023803989948418 0.217374120317144176 -0.1071073285194525798 0.03977469673140165973 -0.114212592343331254 0.2186820408633632085 -0.1063506713936881454 -0.1732616292750812637 -0.05217297280510605623 +'MLC15-1706' .136498338519072504 -0.2180032216898858122 -0.196098622699952152 0.1244876814808927451 -0.05086439510188196095 -0.2381035631101456884 0.3200698826228612348 -0.007569655402967806479 0.1174294116552293543 -0.1023067954490225889 0.08670468264988440144 -0.1213133056821717043 0.1392691434882295243 -0.21607200837990162 0.1919103728760948591 0.1276733724596860187 -0.05225864277775092021 +'MLC21-1706' 0.00644849813660345033 0.1193763834788681144 0.08614039908742214535 -0.008233430513488340305 -0.1393722730317872305 -0.1621366268976746905 0.007740420184267527044 -0.1034934932271945884 0.2679113682477302638 0.1750479156274055703 -0.1282846278050708 -0.1292709450966149642 -0.006579397390574985398 0.1183188703885335175 -0.08430062323210207875 -0.008444127387261886677 -0.143192616660487021 +'MLC22-1706' .01783256803114304997 -0.1162043681310968302 -0.08547394078432954401 0.05277688115309989852 0.1694951047295970847 0.1246356159641417716 0.04435263213132555754 0.1652785288357867532 -0.1837107949230099013 -0.270008064801653902 0.1197976632983312056 0.08377524953221679449 0.01819455462123343442 -0.1151749548009933233 0.0836483990619784068 0.05412746325229404049 0.1741411475138877341 +'MLC23-1706' 0.05610480564046715218 0.161683702347664382 0.04725551282667648373 -0.09239386774295313409 -0.129923801200800465 -0.00691276075561228498 -0.1443622213124367559 -0.2257138314563914283 0.08823032725680611532 0.2571663009859624371 -0.1163196747618713556 -0.02980263691765253076 -0.05724368744627370692 0.1602514037074841413 -0.04624623550209554929 -0.09475826482596669265 -0.1334851520730843122 +'MLC24-1706' 0.1247315711938176003 0.2142376263357548549 0.08195209366089853398 -0.124781891153038102 -0.0508745651513948377 0.1729265076011892721 -0.2540058346419358237 -0.1854399077991417399 -0.02352252380137997631 0.2007298166134338646 -0.1274451708468511968 0.03157602608363744429 -0.1272635203810694449 0.2123397711009933075 -0.08020177110832672762 -0.1279751110783687307 -0.05226909159923913417 +'MLC31-1706' 0.01242564087697576106 0.1128891670124982927 0.05362610946249397881 -0.02509412338657093441 -0.1305142353997465476 -0.1620827474007076607 -0.02816859258104389627 -0.1653864006610325232 0.2491618235131626835 0.1936094136902788143 -0.1118659071824810169 -0.08510795260653579442 -0.0126778712547255569 0.1118891218746438931 -0.05248076973283101465 -0.0257362923268414992 -0.1340917707072917242 +'MLC32-1706' 0.0436283364929993811 0.1445307537538864928 0.02537821400513018757 -0.05235003780328865985 -0.1134205983061229023 -0.03802966780833552662 -0.1101175402019794053 -0.2813820829963721848 0.1754218964993517482 0.2012837385526677625 -0.1184114814934470183 -0.04511284586841459582 -0.04451395614861127642 0.1432504070086048353 -0.0248361892888248996 -0.05368969680557332536 -0.1165295786698376385 +'MLC33-1706' .01171994421282923637 -0.1344973255356535502 -0.01034359154494013389 0.01316467304196127473 0.1011396051066888874 0.04293055998529879402 0.01840543196989581631 0.3354585767030787147 -0.2461674043874238216 -0.03167648659483182638 0.1245964791244947995 0.05301017837316902154 0.01195784952373243892 -0.1333058613764622757 0.01012267441217458257 0.01350156244057197988 0.1039119502623887248 +'MLC41-1706' .01661015058844571984 -0.1247465094591370671 -0.04577701157520800562 0.0151580878299151043 0.110258386268105274 0.1818975616105177884 -0.005015433824104452779 0.09429487595104601994 -0.3000665835747561294 -0.1033281034840016072 0.1239925798335252544 0.1240229371325291541 0.01694732310122675292 -0.1236414243251923173 0.0447993118951855937 0.01554598953296777372 0.1132806870050244857 +'MLC42-1706' .0140064507186234994 -0.1204301362490788757 -0.01927618234868750183 0.01702585007088754099 0.1055428126855424836 0.1757475496849503216 0.01312174951724293104 0.1938709340158550065 -0.299092458347635648 -0.06580511760359740447 0.1140551079082688934 0.07533830285459094944 0.01429077024714283349 -0.1193632883362609753 0.01886448406027034855 0.01746154857801604163 0.1084358544880989067 +'MLC43-1706' .008250857535456065234 -0.1333882985563539514 0.0007097149462618483531 0.005258400434502867593 0.1163558393118957618 0.1175496877973721127 -0.04172518187747005503 0.2542180805315235048 -0.2613833180249839905 0.1111197476859226707 0.1172473615675885539 0.05318566244294434947 0.008418343215553585404 -0.1322066588742825677 -0.0006945569433256512442 0.005392965064736176921 0.1195452777827445134 +'MLF11-1706' .2832149360101232083 0.4173482122493002988 0.256636966806000788 0.1859337979185545497 -0.2552991230447017035 0.00397432793753006719 -0.2735619830659467566 -0.07292230323593781871 0.2526869886170121648 -0.020144837230313236 -0.06744251188547435716 -0.06281016839011996367 0.2889639682734477244 0.4136510722889537583 -0.2511557466106650316 0.1906919202936814828 -0.262297146087018207 +'MLF12-1706' .1092948886274156123 0.3079131141982029973 0.09973094735410283074 0.2510571899889197378 -0.316852701330905151 0.002699082846878799943 -0.1164022572345058404 -0.01177476842161623988 0.3089160198733825191 -0.02809736129861412079 -0.01149648086889677213 -0.006815231545174577077 0.1115134857458705969 0.3051854210024384506 -0.09760090627100936889 0.2574818467565184732 -0.3255379740356830753 +'MLF21-1706' 0.405481851054968867 -0.4414248382406332771 -0.1478743345008416143 -0.1983162996063415895 0.131177545697185538 -0.05298740532629662991 0.3122958158447293742 0.08744022080571989264 -0.2047919666336068256 0.08941774473149002866 0.1414900436780504034 0.0259888997787456541 -0.4137128019954384173 -0.4375144119801415155 0.144716052984638438 -0.2033912952933691065 0.1347732630520888375 +'MLF22-1706' 0.2284737597543823329 -0.3764371321716458718 -0.07207459479402492097 -0.2739562584986123817 0.1903929634360497503 -0.02226328168202757266 0.1877772868271440077 0.02501636505550764236 -0.2792836678639408765 0.09438729015165442382 0.0409894303929245335 -0.004096084736184129986 -0.2331115907764864936 -0.373102408976333122 0.07053523462517487241 -0.2809669118492167383 0.195611838962649609 +'MLF23-1706' 0.001689639930778544024 0.1420180902410613233 -0.07064400490299874158 0.2591319035498976242 -0.2902381852719592703 -0.003252664361894135481 0.05921801322000715129 -0.0006521967611630608182 0.3215048164518695128 -0.02989991938723269432 0.001461330012438449193 -0.003246944471438655347 -0.001723938243615759673 0.1407600022916904448 0.06913519909387139117 0.2657631955591647777 -0.2981939255192050942 +'MLF31-1706' .3114384843575664918 0.3308012286508820732 -0.1207446355907550173 0.2573997376335220855 0.03793516019367754177 0.08401391357990173336 -0.2077977888862391487 -0.003019779669880581774 0.1473312268916143197 -0.2402183497190712169 -0.06213012608540914583 0.107892865839017596 0.3177604316384419758 0.3278707777576448934 0.1181657867860978206 0.263986702804439255 0.03897500366036598524 +'MLF32-1706' 0.1618416422571992697 -0.1948444550110768614 0.1186658136801942293 -0.3250403304524918657 0.03127266602232983 -0.0281308263781561152 0.04462630315221136068 -0.02686026193625825481 -0.2368072568641025055 0.2236569539676231122 -0.01295911884787272032 -0.04376371134733203494 -0.1651268956269325849 -0.193118397010753895 -0.1161313640935471431 -0.3333582462185222806 0.03212988337117522047 +'MLF33-1706' 0.03422249862027276768 0.05156836215563662812 0.1862296524499829076 -0.2778443508635660697 0.1450296727305530609 0.04503163341165733469 -0.1979617281201427326 -0.006699125056417287727 -0.2659863553008675052 0.1207557861832349727 -0.02565441065731719275 0.03378581092035758821 -0.03491718743672873881 0.05111153630417870908 -0.1822521828567156554 -0.284954502097209128 0.1490050917585703238 +'MLF34-1706' 0.00107550521843275391 -0.09019233962539885407 -0.2201413766859628696 0.2029366710639383675 -0.2255037992522271606 -0.04941047961680940931 0.2479072499064756963 -0.03505635944310626917 0.2714256504442650875 -0.03695801831738865229 0.0005109975036195397481 -0.05099256028100346283 -0.001097337097383950175 -0.08939335764066946854 0.2154396247336330672 0.2081299039572183096 -0.2316851004822383653 +'MLF41-1706' .2160581206354072192 0.1272567074518235475 -0.2294781029899453095 0.1116128295114007241 0.1630707284143859404 0.1327388966443867613 -0.1581394049012047887 0.03969111617520743041 -0.0727704840724649471 -0.2605534334953005238 -0.02016200315937529547 0.241978327657154324 0.2204439243072934262 0.1261293853631375306 0.2245769384065645913 0.1144690477320496197 0.16754067214690474 +'MLF42-1706' 0.1621740171854678947 -0.1156570550353058641 0.2078227827865649635 -0.2040972430566403428 -0.1632763262637005053 -0.08857170497916681817 0.08594136762138628038 -0.05900644459931643493 -0.03185955837584739103 0.3211450999577711851 -0.04349909842545013339 -0.1340608066924575403 -0.165466017495221579 -0.1146324901580239586 -0.2033841298199341452 -0.2093201754646305535 -0.167751905653991229 +'MLF43-1706' .08218561513582908762 -0.06480838331372384964 -0.1625579492363286582 0.2714671056111329639 0.05778111047295791947 -0.0204068509157986841 0.1402574910259281327 0.08089928502225260387 0.1592212392059628445 -0.2686722654885064787 0.07406277648779024947 0.004851993024243806372 0.08385391610771061877 -0.06423426880530587468 0.1590860569156090365 0.2784140605153998527 0.05936495274267693245 +'MLF44-1706' .0912936654616337967 -0.1263487289661000823 -0.1518809199292650014 0.260816941315607953 -0.01237232342513022373 -0.05732897397337718276 0.2052817685187591501 0.06860391527432835312 0.1917042781632272708 -0.2163891613977388106 0.06353827277208179414 -0.01907168596034488836 0.09314685242828914247 -0.1252294503371538525 0.1486370662632739981 0.2674913541344627887 -0.01271146209268018273 +'MLF45-1706' .09709402458949725756 -0.2112482170941605009 -0.2358345403009498298 0.1767461833888918366 -0.1061403192317468408 -0.1570723631987329116 0.3276269581147815968 -0.02866194725896517581 0.1882389165924465146 -0.09593709909227673971 0.04720448175517780176 -0.1031467287152491863 0.09906495411674891283 -0.2093768439768264322 0.2307976157255730854 0.1812691909287547642 -0.109049739330195572 +'MLF51-1706' 0.06996854093294238575 0.03662902547438628975 0.2028029198859360172 -0.05689258295535458421 -0.1956690485599958118 -0.1264130302031062358 0.06326781060489868047 -0.08147619874835063114 0.1681849132640110822 0.2731198417089248376 -0.1019499664070744049 -0.1921923342044024874 -0.07138884526048974721 0.03630454191409968057 -0.1984714805224395417 -0.05834848755671821069 -0.2010325472440521455 +'MLF52-1706' 0.04221800773222808556 0.08962559708554490578 0.1504836753331121324 -0.1198991000498791926 -0.1976688893934382407 -0.06996904624856850607 -0.0435567223805512771 -0.1336979720408882355 0.07850671350398787107 0.3154077620128406534 -0.1226375830649022586 -0.07995005945213791432 -0.04307499886399942385 0.0888316356721988859 -0.1472696638422121562 -0.1229673673422775754 -0.2030872058616941256 +'MLO11-1706' .1861799120317299827 0.2535620425213156448 -0.2190945988025922719 0.1149661634001307581 0.05183351123819172901 0.3065324340622725963 0.3204383247987012684 0.05398471083210759636 -0.09877820864597226802 -0.08145627098427889179 -0.1153233302115229536 0.1632475810215299195 0.1899592124320982345 0.2513158262148404987 0.2144152038011949979 0.117908194814431655 0.05325432342776405259 +'MLO12-1706' 0.1438844856289933638 -0.1723963022502312259 0.1303356181537212721 -0.04242604550398709068 -0.004193976882799839608 -0.4433961928709581057 -0.2024945157288647601 -0.08475733604489762985 0.0173346636823901723 0.04478467684938867294 0.1709431290678761761 -0.2177322584150830909 -0.1468052233617073155 -0.1708691044826160521 -0.1275519263446773521 -0.04351174546096370915 -0.004308938291655273721 +'MLO21-1706' 0.1534645184633245119 -0.1387016611195459881 0.272535826613681087 -0.03649574258560613765 -0.06570907301419000313 -0.331454588536091721 -0.2791827929041414413 -0.2506927966626872339 0.06679491816959798323 0.01212881403351893407 0.07271243724779878626 -0.2749881492368085878 -0.1565797230508738092 -0.1374729522408670024 -0.2667150405617766951 -0.03742968365139080072 -0.06751022924833045835 +'MLO22-1706' .07031806801288296993 0.03674257854049649968 -0.07731739734900225369 0.003274607210591818848 0.003917316203801275883 0.4236023825456401992 0.08032764991436761037 0.3181712690071258343 -0.004126298369180464443 -0.002621017642216875391 -0.1020038619081512221 0.3409975755401586373 0.0717454674551435273 0.03641708905382512462 0.07566606205980166977 0.003358405756164980095 0.004024694046432725388 +'MLO31-1706' 0.1486056070595172807 -0.1860956154444221577 0.3673530722307644103 -0.06680087649187285703 -0.1291518241755400254 -0.2533167993801668239 -0.3240599933700139546 -0.2391346552867524566 0.1122357733597204726 0.01189052252659221487 0.04503386408105534283 -0.2558256240929574488 -0.1516221797075980593 -0.1844470603144103271 -0.3595071913220643234 -0.0685103384007469951 -0.1326920143287955989 +'MLO32-1706' .1277388769672969659 0.08069504723258087708 -0.2154131143382879421 0.013929798833946282 0.03142668021599177158 0.3851157925547521454 0.1925948181501072609 0.3405554408090999963 -0.02770024787398775099 -0.005502997760545315017 -0.08817043129939775015 0.3592033162121512357 0.1303318720095484884 0.07998019839659877006 0.2108123480210030987 0.01428626811631876319 0.03228811925922935033 +'MLO33-1706' .0150435247737256677 0.01954013225976638027 0.0277966515985706257 -0.0006511827497863130476 0.0002041167332333240823 0.4396096570935431602 -0.0232177786240188172 0.3864511737469091823 -0.0001398901227021657199 0.0005783700591417944691 -0.105473284074222573 0.4048493248349855911 0.01534889605991792902 0.01936703315046700916 -0.02720297419503440658 -0.0006678467842262062609 0.0002097117920233969931 +'MLO41-1706' .1521201211852270807 0.1362084970758885016 -0.3383503102636729043 0.03524532989688156093 0.08213602096174497935 0.3206148896844249752 0.2685303411983450128 0.3231577290096785959 -0.06404411479800468932 -0.008604723072321249569 -0.06986555242334493987 0.3408312542208970508 0.1552080356042725429 0.135001874254230908 0.3311238667127043289 0.03614727238758753958 0.08438745747448943291 +'MLO42-1706' .08022918042986069975 0.03971726164992910729 -0.1169980304730939835 0.003942374694141351395 0.007510006939329620657 0.4198514502740613996 0.09321640608876378964 0.4152765353445951324 -0.005922024598868695644 -0.002261818546464018208 -0.1018724470440043328 0.4324555156873291506 0.08185776737251708457 0.03936542049941813698 0.114499201191307784 0.004043261684313762157 0.007715864292001307044 +'MLO43-1706' .0444546059681233327 -0.03284245308838265598 -0.1648903255862971817 0.005210751308679780966 -0.01552507240412293911 -0.4104443775580652876 0.128661805661052786 -0.4000908876289550609 0.0117072903063823279 -0.003770121458569130127 0.1011960908351902944 -0.4200734360800368328 0.04535699822032780021 -0.03255151343141262504 0.1613686186636062447 0.005344096578182164041 -0.01595063130586135344 +'MLP11-1706' 0.04596132649404464227 -0.1649185633370018056 -0.003790106214033653765 -0.03214946980248429426 0.1021414181560006823 -0.06515756863128974175 -0.1145009382414202692 0.3227808658807878039 -0.1595715105173279302 0.1417686534780706609 0.1355309134912667801 0.02803998350705355636 -0.04689430394432293758 -0.1634576082093158744 0.003709157600194507194 -0.03297218795985057405 0.1049412240828914572 +'MLP12-1706' 0.0008592274242542254515 -0.1655300352077557213 -0.01033290015474596507 0.004483834573653531705 0.07265767050976255914 -0.2367787204002267387 0.001445878194115893765 0.3249031524020167261 -0.1342072209955394724 -0.001170311024293257561 0.1765953886131755579 -0.001375904315944748504 -0.0008766690403397350839 -0.1640636632673899975 0.01011221136735316987 0.004598577744879529111 0.0746492952610129934 +'MLP13-1706' .08867883724308185667 -0.1836460093553235196 -0.03441823811114610998 0.0619300753246413635 0.07090030737045935338 -0.195185041816601762 0.1681031817683860397 0.2838561084891378927 -0.08588902376493311175 -0.1433602685633046936 0.1568691080700883034 -0.004976173910339043265 0.09047894532907051202 -0.1820191544178446919 0.03368313769217452791 0.06351489142797589471 0.07284376091142165388 +'MLP21-1706' .1198467967095010606 0.2289743371574221864 -0.0343122230836385364 0.0982016719213779643 -0.08556036512411803463 0.1775040410377459743 0.2221234152493576086 -0.2330851078030575507 0.02841232236650191936 -0.1897393948560113786 -0.1446147444793930148 0.01596227337291918416 0.1222795889578392192 0.2269459346221960605 0.03357938692034693334 0.1007146931024364978 -0.08790566658660189936 +'MLP22-1706' 0.1008083000688739239 -0.2005495173042529944 0.02265567886485072083 -0.05205300628041349686 0.06646758001153829643 -0.2712141221055427431 -0.1658980556432302356 0.2574129736527093759 -0.06944912682898449208 0.1159293529040759246 0.1756408803323148693 -0.02766909644280012362 -0.1028546263596813309 -0.1987729201781801291 -0.02217180171309598991 -0.05338506412383983712 0.06828952773678102772 +'MLP31-1706' .16581050962173563 0.2443761049925057549 -0.09136194201552376437 0.08859815972496630498 -0.02957360698583187675 0.3418264799460875025 0.2495954579377616112 -0.1179504917908447414 -0.01299138058915705676 -0.1183769167205985379 -0.1753082493725646174 0.09706098052950398736 0.1691763277626954221 0.242211263652339831 0.08941064510030136137 0.09086542307838357813 -0.03038425130244014685 +'MLP32-1706' .07083546623669863262 0.1695314527542970684 -0.03119865250907051177 0.02082508165766782521 -0.03117101574078156093 0.4435770974238671949 0.09441878883438181713 -0.09294125277860057488 0.03647010210456870516 -0.03613053527368102064 -0.2050967753693166695 0.1317044520870827296 0.07227336844100842872 0.168029633673449752 0.03053231559616096866 0.02135800406396750825 -0.03202544674628174382 +'MLP33-1706' .07228231375196787767 -0.1666962067082004006 -0.06051632896586048999 0.0323353420534630287 0.02741834725624891361 -0.4242720235401877815 0.1286275650546016558 0.1085980695426739112 -0.0333288994312119502 -0.05169199561518745406 0.1961172827089589787 -0.1215459225176528379 0.07374958578105660079 -0.1652195040676462945 0.05922382879098895408 0.03316281675819292979 0.02816991358986247612 +'MLP34-1706' .1449206920916428776 -0.1940479600912682068 -0.1571050011387674916 0.09052326573032641599 -0.02288000989830266466 -0.2998389350387301588 0.2893093848180111061 0.03217017999936495898 0.06713024264392333795 -0.1021882656228587372 0.1248631199647714102 -0.1165202530306865547 0.1478624639706104249 -0.192328957957269342 0.1537495722005778886 0.09283979333833934644 -0.0235071755327444093 +'MLT11-1706' 0.02941061710430426315 -0.04953292467771624324 -0.2246542970572873443 0.2083775617487515497 -0.2676898346580280919 -0.03296335039524216082 0.2223488722060107114 -0.03690080689561065636 0.2745201917026739435 -0.02262069580646115102 -0.006365661974308251154 -0.04561454280499389197 -0.03000762864966599955 -0.04909413004579045448 0.219856158716873612 0.2137100292728400519 -0.2750275004078738261 +'MLT12-1706' .02406653693109491593 -0.1476152289496073522 -0.2953007851043348841 0.1512078266795950088 -0.2227774201197675608 -0.08678040706142246818 0.3062504395727334572 -0.08359867304333283566 0.2315433758472659476 -0.0189791755608124009 -0.002633579223959338963 -0.09561150346921233611 0.02455506800658314309 -0.1463075579312892172 0.288993787920114209 0.1550772971657174149 -0.2288839883708186085 +'MLT13-1706' .09141707171244942143 -0.1727783077629869157 -0.3119253971339939757 0.08681890703404496201 -0.1365912028533433631 -0.1916503702946605048 0.3451945807914174602 -0.1517632776229305425 0.151345012910839738 -0.02005695760150492599 0.01758791102637360243 -0.17359856199376833 0.09327276372536902338 -0.1712477259438655308 0.3052633335681422255 0.0890406385791818189 -0.140335314362798308 +'MLT14-1706' 0.1079860546418236339 0.1384966246830776626 0.2872585880018046489 -0.05339696190071521048 0.1092075127277415125 0.2299118865433914805 -0.3273975321723666676 0.1674945779970780646 -0.1224176624183875295 0.01352823502386997501 -0.03530790910025199264 0.1848913684019521664 -0.110178083497613849 0.1372697321495520706 -0.2811233550560796046 -0.05476341212131945191 0.1122010078927405397 +'MLT15-1706' 0.1058068957446395841 0.09301823583701179787 0.1990832945251175545 -0.02545237949609771219 0.03887179631788453826 0.3615968643281262662 -0.2432025609773219021 0.1895132377488270015 -0.04711279333707184269 0.0203971923338452793 -0.09360360010729668057 0.2375719614534080593 -0.1079546894517356137 0.09219422023886056361 -0.1948312984542243942 -0.02610371635758457903 0.03993731398627527185 +'MLT16-1706' .006420570751482670806 -0.07800153269754098173 -0.04246600458637435349 0.005465358113195416603 0.003731525648345963581 -0.4741744781430483613 0.04750628991843062338 -0.181917944434745793 -0.00437391060919731841 -0.006212226955779655453 0.1538101267389136995 -0.2717696984314896258 0.006550903102308660089 -0.07731054475260618064 0.04155902097894257491 0.005605218875561319113 0.003833810772394539382 +'MLT21-1706' 0.0254339337657134186 0.04815597458099193928 -0.164766311671775495 0.2437658469651044768 -0.3333786386016404646 -0.0130998952064865469 0.1392472333064813106 -0.01380817708549701706 0.3024935248571345991 -0.02478861110195732659 -0.0006154872255995307668 -0.01921477202523860436 -0.02595022188194863813 0.04772937786216745193 0.1612472534227391563 0.2500039152653308339 -0.342516904988642068 +'MLT22-1706' .003637203781615106282 0.09824284691276874426 0.2779104357506039791 -0.1942274733398270392 0.2849747264372969324 0.05113473093761433663 -0.2552972057567962638 0.05489714164889791803 -0.2663252863892679456 0.02381764726141846755 0.002557737007157911448 0.06577248852580981631 0.003711036052551706065 0.09737254833599555404 -0.2719748594698795374 -0.1991978342807002866 0.2927861896272306308 +'MLT23-1706' .09297609498469261435 -0.19775263310112981 -0.3601833830603863307 0.1170863219702488883 -0.1814798374515853296 -0.1701171040457079009 0.3453946997867533564 -0.1509446833069279237 0.1747681729769871017 -0.02426907264751922491 0.01941031093313349762 -0.1738103543899987835 0.09486343389878792998 -0.1960008125813735014 0.3524906314750415603 0.1200826091145150987 -0.1864543946261497942 +'MLT24-1706' 0.1186715130442681371 0.1684293196815434546 0.3426153154995126293 -0.07181657155393512959 0.1411217154724233591 0.2196587690382618696 -0.3359169521261648472 0.1848936018071437593 -0.1363921888619753497 0.01559755442196450806 -0.03584351549475146143 0.2033768842428316792 -0.1210804479925458865 0.1669372640071402347 -0.3352977805008744427 -0.07365438716272168507 0.1449900131965574379 +'MLT25-1706' 0.1289296693053584852 0.1128593268904711372 0.292613136161860854 -0.03166624192055746828 0.08148159987594860709 0.3083379404836946724 -0.2934327202072343765 0.2381010044417077032 -0.07984660874488416771 0.01060449495459777312 -0.06819589659467406584 0.2569450941933609234 -0.1315468364610828389 0.1118595460956864629 -0.2863635414471472074 -0.03247659407764289657 0.08371509800416919445 +'MLT26-1706' 0.05372182546018941518 0.03503963177046312549 0.1487859548076093108 -0.005884589770561178199 0.01603850536345583985 0.406421369773121377 -0.1486619637226493096 0.3079434959490638946 -0.0155201903306658711 0.005027649793544570686 -0.09534710283094016692 0.3308120069933360718 -0.05481233471145389308 0.03472922808593260913 -0.1456082030190672394 -0.006035178843495702522 0.01647813801381213528 +'MLT31-1706' .02055273293205340038 0.07099233538185675818 0.2871463182699538486 -0.2020034866671847895 0.3215253353419816884 0.03975120206712119686 -0.2342756726072209861 0.05408961777373167551 -0.2655566310817074061 0.01971694201508631186 0.005606586086863958075 0.06240741455645516106 0.02096993665156924799 0.07036343943282653834 -0.281013483167100786 -0.2071728389878737253 0.3303386899613696692 +'MLT32-1706' .03299708863869348086 -0.1547248836231362445 -0.3600742513428886737 0.1505898304783163666 -0.2638001098705970993 -0.09334107510393213625 0.3053299196854436515 -0.1076501292093403617 0.2227861278406501888 -0.01888411568809355429 0.0008799974874751702401 -0.1200819083320490283 0.03366690263174096365 -0.1533542306927689336 0.3523838305790983338 0.1544434861874269538 -0.2710311540881552572 +'MLT33-1706' 0.1099997440199430854 0.187268982771912007 0.4142738853881993699 -0.08913507492947406186 0.1866698172998873806 0.2012696447471735151 -0.3532853830266671213 0.2103196686264926507 -0.1565397098266445852 0.01363852840618042656 -0.02405358353029963397 0.2252873250320789611 -0.112232649128116771 0.1856100331964292138 -0.4054258756285356036 -0.09141607816384204888 0.1917866373938635349 +'MLT34-1706' 0.135000755116522958 0.1489074201976655631 0.3796215613536432221 -0.05128349622819194931 0.1328296703181114924 0.2687351078038757723 -0.3303679088139176989 0.2498071932638179782 -0.1129543933409746376 0.01123960168364337465 -0.05334309138552047885 0.2658406538466721036 -0.137741160363760079 0.1475883021148593488 -0.3715136515907858095 -0.05259586199283353136 0.1364706741825340297 +'MLT35-1706' 0.1032074790357673938 0.0675393359422463424 0.2666475478061224869 -0.01440748404018138244 0.04902123790123995989 0.3833512633744912135 -0.2344472189545973861 0.3343947542043311238 -0.04190466050340616727 0.007143149121790612864 -0.09166851914355969577 0.353870442752071579 -0.105302506703276455 0.06694102889197391104 -0.2609525228755305015 -0.01477617748348371285 0.05036496265949417378 +'MLT41-1706' 0.004339327789664010858 0.1082769594768177718 0.3358928511631726344 -0.1831110523055304584 0.3374513073356221193 0.05456897001241389766 -0.2547510963067269318 0.07290608262066095024 -0.2551553964542446762 0.01817368236061459377 0.001525382855664386608 0.08162049317489925016 -0.004427412605441619943 0.1073177722515770843 -0.3287188937158956326 -0.1877969394592453878 0.3467012099448880669 +'MLT42-1706' .08289736379339353312 -0.1891539828210876406 -0.437786186032757485 0.1131852689211517715 -0.2330278938556159252 -0.1543954744205159046 0.3360626631820053389 -0.1880551626002880394 0.1762653239482036283 -0.01448485064730739569 0.01220633869491688159 -0.2014855833121523832 0.08458011268265315519 -0.1874783346979592147 0.4284360035006529177 0.1160817265131404707 -0.2394154385962946607 +'MLT43-1706' 0.1195810197362568023 0.1668278052319297211 0.4197158897090380592 -0.07099760113938126393 0.1732764219830687513 0.2165440840064302153 -0.3248761645591489167 0.2333942807058506097 -0.1314292718158479589 0.01295087025989425343 -0.03778765477925585814 0.2489866124416025006 -0.1220084169287566078 0.1653499368066746744 -0.4107516503026569232 -0.07281445895836478888 0.1780261147327588944 +'MLT44-1706' .1307442290410151253 -0.111985768181042139 -0.3613517170509017995 0.0314233495385638148 -0.09731985505301764261 -0.3159787758927056767 0.2828848830097625555 -0.3100734037957798006 0.07424539005954737536 -0.00972696164839428716 0.07568773795048078235 -0.3281828587177348933 0.1333982302797542541 -0.110993725933392795 0.3536340123345119713 0.03222748597967695083 -0.0999874967590044933 +'MRC11-1706' .03057431121130314844 -0.1430035554237890083 -0.09863892347482025591 0.004684366149590397932 0.1344493424118867464 0.1335871575944615197 -0.03420070890509311484 0.077411435627397579 -0.2819736177038322245 -0.1130251679918460456 0.1318857795622695173 0.252092855948062744 0.03119494479814343899 -0.1417367375874803992 0.09653220570097334474 0.004804241006336004531 0.1381347432272195253 +'MRC12-1706' .003497019502994293001 -0.1259043748687618813 -0.005750283493578489842 0.000902736791224480477 0.1165895711168080939 0.1342061630712123588 -0.002887697478237460751 0.06541078890143686708 -0.2646224466039233114 -0.006237398518784461471 0.07704478240095771757 0.3071995062227549367 0.003568006147383240897 -0.1247890326153447416 0.005627469658899193414 0.0009258381970649453164 0.1197854164273552818 +'MRC13-1706' 0.1656846953418930068 0.05149173519367507279 0.1116820670537876647 -0.03954847718963529213 0.0972599342165118147 0.1687617422748686757 0.1181499308935818199 0.008728751680269819513 -0.1382964508755176458 0.1212237092265487509 -0.1450566589321088673 0.3167503069394009274 -0.1690479595555628156 0.05103558815332689957 -0.109296775452929526 -0.04056053898972086791 0.09992593342804124978 +'MRC14-1706' .3636747657300390957 -0.2571269623579317543 -0.08285637539531157114 0.1171409741987591707 -0.0451344322454187083 -0.1379300216658054246 -0.2610847331555283812 0.05922638433937921221 -0.02514173518480369504 -0.1746442564861342694 0.2110884656706498441 -0.1581500073964554609 0.3710570669285332412 -0.2548491656895512381 0.08108673930671016217 0.1201386599160349095 -0.04637161548791660093 +'MRC15-1706' .4123706533164807064 -0.3793033815167258238 0.09304703903705804913 0.1601034970567334903 0.06401025148435419976 -0.07075990482867222653 -0.3262080053496420051 0.1066564946557981286 -0.1520414824112646113 -0.1146235957327424032 0.1858116755476573734 0.003403588279648795366 0.4207414413256269081 -0.3759432672338775538 -0.09105975203069449631 0.1642006114071616341 0.06576484119657012573 +'MRC21-1706' .01596540809033131225 -0.1494953587583078281 -0.006840851951792977122 0.01306503188608057475 0.1145948091914549688 0.1457281130939310221 -0.005405008568720096399 0.0597713216937120484 -0.2992853162801875078 -0.01795604698726411749 0.1267019537676334628 0.2377268683745890343 0.01628949285613327108 -0.1481710323360790615 0.006694745892568024909 0.01339937142652355105 0.117735975936125864 +'MRC22-1706' 0.04241520406883505373 -0.08510884897049819653 0.09101557479661256944 0.0006435740043285814943 0.1200691726388278813 0.1461303999689518851 0.04510170942281802736 0.04245863239927688548 -0.2453091385220129705 0.08396909421387847849 0.03861759387020459455 0.3094978365765182482 -0.04327619812544267891 -0.0843548998285764684 -0.08907167554907198526 0.0006600433278422506572 0.1233603975626646476 +'MRC23-1706' 0.1749051174651098384 0.0637066317942764776 0.1801363709554188453 -0.05428455943657647942 0.1257883722260832171 0.1419859402424387129 0.1441351570512157121 0.008074694845674967869 -0.1280129163411886095 0.1986104105891146332 -0.04759399973994973138 0.2662076767729228965 -0.1784555487294113008 0.06314227731225702245 -0.1762890409051782181 -0.05567372364324870565 0.129236366550527032 +'MRC24-1706' .3229435721425160666 -0.2722164008237961674 -0.1225303115396950832 0.1459966507936349411 -0.07238352715167904738 -0.1154162338419092576 -0.2503687890967836727 0.04637932958573351416 -0.04424234848579100543 -0.2147861470229526781 0.1336206988381435923 -0.14948049790641732 0.3294990633240059696 -0.2698049321657102761 0.1199133244917619245 0.1497327651451477171 -0.0743676373391742862 +'MRC31-1706' 0.0002015592274662599112 -0.1129674974829350809 0.08331198511425862152 0.02244996115923489702 0.1203431034753908307 0.1502163137972551132 0.02851724921224238138 0.03965614790932375788 -0.2740056378769517575 0.08234765429483695276 0.09722419233050288989 0.2308406631789497454 -0.0002056507154294260806 -0.1119667584431928431 -0.08153261817034136716 0.02302446490039591551 0.1236418371375397618 +'MRC32-1706' 0.10033146968031742 0.01605425853277189785 0.1921915433182271316 -0.04223352577446042033 0.1586271222133333325 0.1413229106131536073 0.1076426705923665406 0.02091224582853301595 -0.1570676463715844073 0.2404520703191420639 0.03781477487375302371 0.2151535766653063231 -0.1023681167030517369 0.0159120395438960352 -0.1880867404064746062 -0.04331429907236285237 0.1629752619293906024 +'MRC33-1706' .01979455986725166261 0.06027299581073901347 -0.1441811383131844093 0.04337358539616040926 -0.1840072500933647437 -0.1357269453402529247 -0.01937036393100139905 -0.08659556111370171616 0.1631644674327529243 -0.2815794914457797615 -0.1033057306817664889 -0.1195750898653752808 0.02019637329177765769 0.05973905869347978514 0.1411017356186141936 0.04448353328876114565 -0.1890510863617767823 +'MRC41-1706' .03018628867388630996 -0.137955618317214479 -0.01012663822241948938 0.02781968947274519877 0.1037583814758227668 0.1666134520555595244 -0.005808284948225599098 0.06026175429401210704 -0.3050428955851984258 -0.03251707854280969784 0.1282764341920848983 0.1681456489057032155 0.03079904571961640178 -0.1367335183674243115 0.009910354751544682081 0.02853160677035956189 0.1066025101032216649 +'MRC42-1706' 0.02140418101093491052 0.1240464576224376975 -0.07621935890969942784 -0.02666822430130585606 -0.1312854698877474746 -0.1712307868744430694 -0.0150937896165679649 -0.07414781835223806239 0.292196514100403093 -0.1248581198776768791 -0.1271908171674049071 -0.1468966563477286935 -0.0218386684321685981 0.1229475739997102218 0.07459147538796501165 -0.02735067513151226079 -0.1348841455605774842 +'MRC43-1706' 0.01680441244167842768 0.1296604565921741503 -0.04595174941600873447 0.00284215659716115579 -0.1473910554431897835 -0.1371354967257686353 0.04184651262947680639 -0.1756806022421203428 0.2347470699234750491 -0.202886995201335546 -0.1213246075110408356 -0.06580751433763405711 -0.017145528311676074 0.1285118405414185372 0.04497031770706700488 0.002914888553642197219 -0.1514312025064532274 +'MRF11-1706' 0.3909624068298494515 -0.1966629436094969596 -0.2616276690293469764 -0.0333362237260401012 0.06540429879971824956 -0.06501668898923340656 0.2711331029081969213 0.2729975682736562881 -0.06468943111857271278 0.009070192571966010503 0.3075910541636388551 0.2557533525052311796 -0.3988986248919204058 -0.1949207762629079077 0.2560398580409701252 -0.03418931140449750494 0.06719710084544576467 +'MRF12-1706' 0.1810151985130786234 -0.05990966650042391789 -0.1017034550152422639 -0.006173838949915151815 0.00741538186797176431 -0.1061526123317638182 0.1065996856314965074 0.3414651553147626251 -0.007566777779953144829 0.004560029759003688191 0.4033096756610932698 0.3141723098838756223 -0.1846896594404026648 -0.05937894798880982705 0.09953128536056284059 -0.006331830028335919645 0.007618645445851566882 +'MRF21-1706' .4494660512473251934 0.3188347727628673689 0.1548909176139302013 0.0936471831896307505 -0.05248414846159161345 0.1046688669347286271 -0.3046841333305525534 -0.1751613558566728623 0.08936647206025714885 -0.06195660821367301313 -0.2962173695877688417 -0.08528268088289434057 0.4585898455863270384 0.3160103284630425557 -0.1515827767943679905 0.09604365313049310904 -0.05392279531595729758 +'MRF22-1706' 0.3027428147593829166 -0.1603343142667683074 -0.1041321552298076353 -0.03069864475769192372 0.01004639714197603888 -0.1459342732771093942 0.1864871505715646749 0.2436404045537557406 -0.01946339661596619905 0.02913083089301551909 0.4133562363769067716 0.1491992317237742227 -0.308888247037993946 -0.1589139693775554196 0.101908113700120595 -0.03148423570534539945 0.0103217796730766271 +'MRF23-1706' 0.04942536722689590267 0.02470043930056848788 -0.05498403098691546226 -0.002051437466676938985 -0.002040322834149596847 0.103348738191039069 0.05977931950319602394 -0.3147225681344787973 0.001952561942505099367 0.00233717465142020079 -0.4117322266515858198 -0.2888393326058792954 -0.05042866187942061929 0.02448162685931213126 0.05380968893940260567 -0.002103934595335844437 -0.002096250273448490437 +'MRF31-1706' .3348559522644288244 0.2186712504024280745 -0.05061241474803721691 0.06948873460858513706 0.0474252247707601382 0.1947144537019051547 -0.2075811142308803536 -0.08500770620575032188 -0.01872543504763774305 -0.1075335400377467332 -0.3395565632099347142 0.1538397009021389983 0.3416532550488612374 0.2167341192627388335 0.04953144113264470322 0.071266979912352868 0.04872520109568744678 +'MRF32-1706' 0.08316329737541253153 -0.1259721001332885504 0.01439651290995311306 -0.006389550750947605232 -0.03253252650443295979 -0.2157666023689230883 0.04069293930925910185 0.1450268481992543212 0.03981860515693522867 0.01508933335264873651 0.4401960223065913835 -0.07346663876837009055 -0.08485144449954092061 -0.12485615792574567 -0.0140890339902692719 -0.006553061983092769299 -0.03342427798163223607 +'MRF33-1706' 0.2692017745492568115 0.140979940040355578 -0.1094033752311791008 -0.03405185195410588561 -0.0139078964682223874 0.1533716596449277714 0.2010134035111192929 -0.2152800158308411649 0.01988792064427201758 0.03984139471017113243 -0.4121847690665810249 -0.09701048178902450803 -0.2746663510614665293 0.139731048695832194 0.1070667516448804979 -0.03492325285330288159 -0.0142891268414177177 +'MRF34-1706' .3320356914539314697 -0.1436364267235446524 0.198415710073604562 0.02395681540492492281 0.0421650391261524024 -0.07363952629181191867 -0.251757135213100891 0.2579755010672394322 -0.04949802068967154578 -0.01527957803454208473 0.3414637130912087093 0.222681757087011406 0.3387757452435934402 -0.1423640025045958268 -0.194177972187817266 0.02456988016609809242 0.04332082811542097706 +'MRF41-1706' .2252989132717254372 0.09477020999282342872 -0.1966920575781135327 0.07106450127687112539 0.1332280996496958969 0.1546532987066245868 -0.1570556779483562593 0.03847132013309478848 -0.1133630047160334997 -0.1968371824439046069 -0.08265860758632444238 0.3035603387172922107 0.2298722974990488055 0.09393067427628942756 0.1924911332464513958 0.0728830710978932983 0.1368800248898361105 +'MRF42-1706' .122220576130128239 0.06287795152105045415 -0.07912379477149947271 0.01792023612989282824 0.09012258455386137901 0.1974821243929711645 -0.07869509603263664943 0.005740464068836104161 -0.1310891975871425197 -0.06702869328867649967 -0.2293385897887736113 0.3272062299111700434 0.1247015541650900033 0.06232093802399887861 0.07743387867238586686 0.0183788223441891177 0.09259294134874393456 +'MRF43-1706' .2023056450853150945 -0.1269884779896983951 -0.0114691936659614916 0.046997348837595182 -0.04361861875008592876 -0.2052037349053756898 -0.1402788213248585825 0.07198649532141201957 0.05796743358818410435 -0.07764922024070908257 0.3510535710507777241 -0.2013386474598358455 0.2064122847175079989 -0.1258635320507929534 0.01122423606406773577 0.04820003032734650195 -0.04481425191735564917 +'MRF44-1706' 0.3016461262471071825 0.1904893894750705752 0.001049389085828675077 -0.05872263746143031177 0.02504658074139399365 0.1752508817344972658 0.2030237471847192166 -0.1195740731936100892 -0.008839932107464349917 0.0876005084145633911 -0.3546855162957496255 0.09724957794671922062 -0.3077692966431751498 0.1888019114574826796 -0.001026976365161051544 -0.06022537391042216692 0.02573313440859489876 +'MRF45-1706' 0.429087921409202766 0.3112612550713563242 -0.1486566217366131204 -0.0990480169215538081 -0.06341326118471525553 0.08692149687532574331 0.3223061630363367458 -0.1535279624963728218 0.1083344043824291947 0.07399094072273164346 -0.2621428800796802849 -0.05955837702837864234 -0.4377980563291216098 0.3085039018817264389 0.1454816322276034635 -0.101582696419322327 -0.06515148675191145822 +'MRF51-1706' 0.07165648892676913795 0.07960048013116406695 0.1193507755665426384 -0.01115464410125674953 -0.1313315593441189422 -0.1395678309768154102 0.06023851728731902111 -0.07161652265399121031 0.2310622827687529302 0.1089928119661103117 -0.03465755320902647735 -0.3363901621632690575 -0.07311105722221321324 0.07889532767736631702 -0.1168016966497128772 -0.01144009603242214339 -0.134931498378428022 +'MRF52-1706' 0.07512822170158524326 -0.02672216954749038684 0.03762477103156019326 -0.02881561283473826202 0.1009683479162923753 0.1661857043206552698 0.04970899560140586149 0.04410357375813644953 -0.1902193112258701579 0.06001124722854464522 -0.09201692602111330443 0.3621740811802816595 -0.07665326334145543263 -0.02648544731420532719 -0.03682118588406674276 -0.0295530162208726202 0.1037359987285480928 +'MRO11-1706' 0.143276100144351215 -0.2541123251126914395 0.2304375354588815983 -0.1992797827550804868 -0.1009715781098459025 -0.1717904391127985653 -0.3184481836135348298 -0.01347342214091126755 0.1822640209356397312 0.1075989749624769037 0.06931868197881396743 -0.09583804196091520733 -0.1461844881478135127 -0.2518612340476852895 -0.2255158794369905018 -0.2043794343722261098 -0.1037393174651747435 +'MRO12-1706' 0.08030627094740680483 -0.1159084996680348062 0.1744209751266761754 -0.2954909636016306851 -0.1465166558028980492 -0.05372111750999448987 -0.2043027395691204284 0.01758580874190161444 0.266774666951497097 0.1312926445156141209 0.03454880703502136857 -0.02734826138588613426 -0.08193642276470862462 -0.1148817073318296467 -0.1706957137847386619 -0.3030526989144144978 -0.1505328346332981126 +'MRO21-1706' .0342732027805162931 0.1620929087787638667 -0.275090865364903181 0.1894644805054137848 0.2534779263145584549 0.06871914308472523714 0.2752836806532742431 0.06249021887556825 -0.2541586930458559213 -0.01997064522979013004 -0.002863168692766314503 0.07282141552085227842 0.03496892085008027756 0.1606569851237781288 0.2692155091153480839 0.1943129545003326464 0.2604260283993324876 +'MRO22-1706' .001357964157832736163 0.04225486884667223331 0.09290471355455792724 -0.2531492933423769576 -0.3188393176441711163 -0.006091288204190485091 -0.0866546221016496615 -0.003509691524755090622 0.3187184292095230354 0.02111289553308321604 0.001165761743317600364 -0.006223287724298064323 0.001385529722932521716 0.04188054793299136186 -0.09092046631802450096 -0.2596274878954057952 -0.3275790456348531832 +'MRO31-1706' .08711715795998192791 0.2076837804847151692 -0.3719424387026276646 0.1357571408978750782 0.2274215193331486085 0.1329200637795422135 0.325986138347081289 0.1371108348814457922 -0.1967981106213541331 -0.01485436431130437301 -0.01301222189154930056 0.1490118495066197757 0.08888556522994020548 0.2058439834485481235 0.3639985386796026345 0.1392312219789940131 0.2336553873293709671 +'MRO32-1706' 0.002204780672650812155 -0.08513386090556848695 0.2271558161996131142 -0.2174581476603746899 -0.3248048539011507696 -0.03033060034554384277 -0.1976693397106427663 -0.03349391549637302512 0.2823037885580250705 0.01568778171216827014 -0.0001861918157847285539 -0.03874812913412495341 -0.002249535922494594591 -0.08437969019177483931 -0.2223042507266526358 -0.2230229911133639054 -0.333708103645014964 +'MRO33-1706' .02376605782231675651 -0.1458503121580901341 0.00822758814107140031 0.2497384068779923139 0.3622341776944859038 -0.0004383955360670803263 -0.01336587985263110352 8.929494625889891732e-05 -0.314006684307413908 -0.01644976023889444319 0.0003480352786931168807 -0.0002406802555495012443 0.0242484894169119336 -0.1445582759123793526 -0.008051864343993343082 0.2561293154432830455 0.3721634053862579727 +'MRO41-1706' 0.04152203387525037204 -0.1752611798897343032 0.3656618629005881638 -0.1832182112847341449 -0.3180248248375751596 -0.07710392238485595795 -0.2863450522051803615 -0.09471444922521680965 0.245806252801942321 0.01467881660550873942 0.00317184991937523135 -0.1029879158821386947 -0.0423648973052325184 -0.1737086031860373692 -0.3578521026289516738 -0.187906840680808207 -0.326742226706019212 +'MRO42-1706' 0.0006186237104445340427 -0.01642587448840864342 -0.1369535374081572721 0.2461103410469845931 0.3925103219146011679 0.009027117582519181629 0.1033374251872434119 0.008469699455115612535 -0.3036912924450048124 -0.01787380603422548259 -0.00143387490026280367 0.01135606771336500689 -0.0006311812673315621335 -0.0162803634854324121 0.1340285009085180057 0.2524084059152057469 0.4032694512227910644 +'MRO43-1706' 0.08221783114419019267 0.2570286385302366083 -0.1371119582080091992 -0.254144306543879539 -0.4144548760409454968 -0.0004114704945558465138 0.1143356893380604589 -0.01363770164907001509 0.3190705992750625386 0.01681408124898283937 -0.008246640988500159725 -0.01082706281544928116 -0.08388678607477202676 0.254751712877812897 0.1341835381767676194 -0.2606479638940469301 -0.4258155291365972039 +'MRP11-1706' 0.02748283000027591794 -0.1405072101460464185 0.07048084432354789763 -0.09606075786900664104 0.1702560820585738155 0.04947278815567629495 -0.1123118378097654191 0.1789795646800260709 -0.07823527060214552353 0.2940222386631903273 0.1111268577960597137 0.03763193465351765549 -0.02804070903937222123 -0.13926250654818495 -0.06897552327764193414 -0.09851899217877094217 0.1749229840484087251 +'MRP12-1706' .0931295139803695049 -0.02595720028830306864 -0.1514900343153851581 0.2040307770766470741 -0.1547671122997557325 -0.07105573619661578744 0.0018035190138875883 -0.07628787395845018637 -0.05880217978628444336 -0.3280915268834389553 -0.06170140730825360992 -0.07500840753180212928 0.09501996717497693257 -0.02572725464668311826 0.1482545291353801198 0.2092520085928675777 -0.1590094450001184878 +'MRP13-1706' .2115313331810317055 -0.1979795999163342646 -0.1773300089107257282 0.1791671793914443034 -0.129942997425514073 -0.1053042416643629742 -0.1697742884644727057 -0.001526718480467759154 -0.04556171358429891849 -0.2917272309729673219 0.02065987671007081874 -0.1412330144410109678 0.2158252467588040735 -0.1962257687779685178 0.1735426167895614824 0.1837521412149221434 -0.1335048744869256621 +'MRP21-1706' .1059050275956029408 0.2259068501607105761 -0.06482051915468850511 0.157586233001309084 -0.1045439499578527526 0.09633096497930783431 0.2304836081772463074 -0.1880002055480553824 -0.0291331444751189092 -0.2507370675528401982 -0.1171380242104116121 0.009074192022111760361 0.1080548132992553423 0.2239056214060842764 0.06343609062482903627 0.1616189295290481609 -0.1074096118607012484 +'MRP22-1706' 0.08275366367863590256 -0.147092236625264855 0.1068427140129646902 -0.2173906904690626196 0.1108255042931935441 -0.0235029569255204851 -0.1727238249174085916 0.1302747969075241929 0.09023369860717134205 0.2862600468267264553 0.08910007763672668502 0.009197146191244270214 -0.08443349557274115735 -0.145789198610670051 -0.1045607807082625795 -0.2229538076647767098 0.1138633503440172889 +'MRP31-1706' 0.125147999725753245 -0.2120791308262151287 0.1368472811359962016 -0.2477252155177564197 0.01115434696923150656 -0.09848861390551283401 -0.2476026524321700562 0.09103067709860200585 0.1583258156037012365 0.2139307892448033266 0.08375838548761022073 -0.02757319466598229241 -0.1276884020726413715 -0.2102003969384926285 -0.1339245140445100291 -0.2540646056879851677 0.01146009959455097406 +'MRP32-1706' .100696815012841473 0.005598418676739944436 -0.123708774023335924 0.3127519655012597211 0.01777961042714985493 0.00368555345856103056 0.09567060089618774354 -0.05123250450519883925 -0.2302702342721110185 -0.2243057126641644639 -0.03932388627252543511 -0.01441527045830245587 0.1027408782479179994 0.005548824269007913979 0.1210666175212700563 0.3207554169532023658 0.01826696863648776675 +'MRP33-1706' .1969155068701943512 -0.2475704509676388276 -0.07645127230875255198 0.2986525259336447191 0.007838380115800350906 -0.04965970364450122965 -0.1271266615553836299 -0.002355145126734140004 -0.2219143248827675496 -0.2269423320523189236 0.01637653028347950748 -0.05317337855326999263 0.2009127310918193687 -0.2453773120481249626 0.0748184356096864428 0.3062951669270563282 0.008053238529768351472 +'MRP34-1706' 0.3502081335909552062 0.3820078347044149059 -0.01367046051229097586 -0.2174682698343872178 -0.02899932134096130931 0.06885687531330923761 0.2873295648216210862 -0.07029144813375601264 0.1696495810992718067 0.1657119735469045063 -0.123536125123628257 0.04069105529517456216 -0.357317073137918606 0.3786237626288707081 0.01337848852878420654 -0.2230333723179732941 -0.02979422387151192675 +'MRT11-1706' .2957980748847682251 -0.1050610691674800645 0.2222351434762992461 0.01458100867459895256 0.04447924162409928883 -0.07998024115311103133 -0.2367940784368867124 0.2927056643141205949 -0.04414855025894403456 -0.009764492725799666512 0.3488599002429279561 0.2689302815703668026 0.3018025346067689796 -0.1041303703752115978 -0.2174886731150887931 0.01495414268467773998 0.04569846538827848637 +'MRT12-1706' .390826910040320219 -0.2213572815071022659 0.2833093884197113721 0.04173974353899975731 0.08857216672439705007 -0.03985187575672158311 -0.3095602837305387878 0.239905408234199008 -0.09160403874322066431 -0.01197020785157400409 0.2637323345274371067 0.2214318392971479643 0.3987603776280498336 -0.2193963557694242061 -0.2772585019840553278 0.04280788074637272705 0.09100002490210296058 +'MRT13-1706' 0.3827902272225388591 0.3463004073510678182 -0.2913687386737445206 -0.09965066348789816675 -0.1585554442495373806 0.01147712910421835875 0.3412446774503195002 -0.1479004267071167833 0.1740133991651602874 0.01905376317115334284 -0.1549872191971216617 -0.1306504439930761541 -0.3905605567022985003 0.3432326547245461712 0.2851457216447313425 -0.1022007649592062972 -0.162901619195656211 +'MRT14-1706' .3371102895502340879 -0.3780659255710286382 0.2742499285884065774 0.1341557923905827565 0.1768366880577554034 0.005868339126459232169 -0.3297996325490215042 0.1170846569859600173 -0.2011739297334531607 -0.01726290882101528049 0.1106597352527435296 0.1040161009761790128 0.3439533535433480504 -0.3747167734720156518 -0.2683925329612034116 0.1375888943046636448 0.1816839715227221985 +'MRT15-1706' 0.2152357650663302702 0.3607972877972185355 -0.1660859801752261333 -0.2213257558393851576 -0.2103821977358218132 0.002030419543749620304 0.2413118683090362537 -0.0491439480729107675 0.2687328730280011402 0.04597751964976206501 -0.04668421529222619576 -0.0299072442017636643 -0.2196048755907252237 0.3576011124425654275 0.162538736611570922 -0.2269895729766683579 -0.2161489996342783049 +'MRT16-1706' 0.08716223182764745725 0.1797849274874827596 0.008304484644820366371 -0.298885496265823003 -0.2179973766508081778 0.007001523163325838045 0.04026951520908507443 0.001393035515824442121 0.3122573498599781061 0.08609269632732095834 -0.002458781276855592432 0.00654308859675637941 -0.08893155406036545862 0.1781922765064239689 -0.008127118501845905993 -0.3065340990658705356 -0.2239729187786978215 +'MRT21-1706' 0.1673890899765069495 0.04098873387037455657 -0.1566486630026843463 -0.00462520483834651195 -0.01758499894174973821 0.09126110276667848131 0.1439004855539918193 -0.3539446394773650417 0.01517383133724756021 0.004043605197747838532 -0.3788419305017089456 -0.3369388146054176358 -0.1707869520114706219 0.04062562919790108085 0.1533029804772525484 -0.004743565732800578832 -0.0180670226413451665 +'MRT22-1706' 0.3354920127807168306 0.143916804298337031 -0.2647445266487256643 -0.02229538671280962073 -0.05939535000483622817 0.06354365791657073936 0.2566436408767915345 -0.3074563998201390036 0.05453519215382589963 0.009326016542110255464 -0.320859687441135466 -0.2875775665682340776 -0.342302227074976595 0.142641896313781158 0.2590901462056753868 -0.02286593483030031904 -0.06102344031311165984 +'MRT23-1706' .4048004375153635981 -0.332811047923227743 0.3349981367351722028 0.088510549348795306 0.163077185729994939 -0.0256787243159148082 -0.335493155927043929 0.185413849509261569 -0.1537714355642708919 -0.01732529806686393392 0.1823514863682711429 0.1680461142070909797 0.4130175563166139652 -0.3298627927530659587 -0.327843288486592721 0.09077557071664665855 0.1675473064644668886 +'MRT24-1706' 0.3734840052083489015 0.3810734620099462955 -0.3287594468202453823 -0.1248391293708276811 -0.191007202675304355 0.004587655768895609887 0.3368658695943041459 -0.1526173738218654374 0.1856113116134285312 0.01703476785224634568 -0.1360489298190472318 -0.1383997105297779251 -0.3810654259696526491 0.3776976672110866629 0.321737843729523354 -0.1280338140456972473 -0.1962429151588765963 +'MRT25-1706' .2785672768022660617 -0.4040038823157319769 0.2776109728124044884 0.1897332765842290325 0.2437716367452433808 0.005967384230719477434 -0.2955134698020839834 0.08878916553368973452 -0.2446673193495453591 -0.02091472215848995397 0.07082767249095331397 0.07708875741095530532 0.2842219653734416873 -0.4004249550468345076 -0.2716817924236087922 0.1945886291813776758 0.2504536790126103418 +'MRT26-1706' .1022983664920729674 -0.2776884350535903656 0.1292094029207832562 0.2434004965123313935 0.3089813607156164932 0.001401847574857818801 -0.1421536790300834963 0.01752630158418001793 -0.3089435259932729605 -0.02193766761872376417 0.01239953072074249409 0.01280821980835544598 0.1043749399162489516 -0.2752284915828143164 -0.1264497646756350402 0.2496292153441794226 0.3174508715237502887 +'MRT31-1706' 0.3083285689478249547 0.1154818900634395906 -0.285500189410889893 -0.01586863740012325885 -0.06020566400364342485 0.07240343938744431274 0.2428181212324489191 -0.3468885592541476881 0.04856388096721252212 0.007209894006635116613 -0.3314017856138185558 -0.3307426892346994607 -0.3145873874817540772 0.1144588769105885917 0.2794025121220443664 -0.01627472235897176392 -0.06185596588854919142 +'MRT32-1706' 0.3920952672749096202 0.2330505338991125386 -0.3518439179137804462 -0.04654402162162415979 -0.1158635653696272749 0.04122362595902062665 0.3100210419010489549 -0.2779933243432904932 0.09707782229058130319 0.01147139082660934145 -0.2532020048523628275 -0.2613860178921262323 -0.4000544814802640126 0.2309860217810066618 0.3443292795805862339 -0.04773510228143647283 -0.119039510083231409 +'MRT33-1706' .4058669528527497627 -0.3753771279781216719 0.3955700004671601766 0.1111433744794785711 0.2113314665185665464 -0.01420040483235926465 -0.3501976804696779189 0.1950894183850811203 -0.177878232995817176 -0.01532905570521735095 0.1623465528842618355 0.1813105441220455027 0.4141057210456965398 -0.3720517949844367456 -0.3871214659391294943 0.1139875791527438786 0.2171242888934578064 +'MRT34-1706' 0.3342535360160707181 0.4057218011024366078 -0.3572932696566119559 -0.1584105486746239522 -0.2494793797665892932 -0.00259887151166174335 0.3233437238561964744 -0.1366350186115352361 0.2149506220699262948 0.01648828468929573743 -0.1022137807245685898 -0.1252535040680128886 -0.3410386102418806464 0.4021276553996066538 0.3496622447513816345 -0.1624643397795365873 -0.2563178773977923819 +'MRT35-1706' .1798462919634778168 -0.3556237791433183304 0.2452662005443273785 0.2249706917303061771 0.327444391677241764 0.006152157510481079394 -0.2257756384973783337 0.05121100587044737085 -0.2844248597018838032 -0.01745638284769740131 0.03248447491655015451 0.04479292710329174643 0.1834970250409888037 -0.352473434069035807 -0.240027835750711821 0.2307277842764318965 0.3364199939852583476 +'MRT41-1706' .342503416282284423 -0.1588478603759111152 0.3309627483116839852 0.02608350887476881472 0.07986763368342182645 -0.05776620403283341809 -0.2600671751594011427 0.3509531804746297556 -0.05991343367436408746 -0.007996904994250479681 0.2990682815994545329 0.3354277233831924887 0.349455956350423147 -0.1574406834551183854 -0.3238940873836535506 0.02675099659667950699 0.08205689126561106772 +'MRT42-1706' .4032976705291579367 -0.3228098410385641381 0.4144854629966301385 0.08403390349082605348 0.1929331992972388721 -0.0281426537395409182 -0.3294007709211726476 0.2321754364208655219 -0.1457941983477845371 -0.01380140457132374848 0.1876867520014548762 0.2180123026442746248 0.411484284385966903 -0.3199501830171135319 -0.4056329343889039096 0.08618436564964293556 0.1982217054158968428 +'MRT43-1706' 0.3666394628932131416 0.3803014490187239804 -0.4046003228983229283 -0.1301149689142950538 -0.2400269054143220893 0.009227176221504845843 0.3258644619749146987 -0.1806605924666062069 0.1839670022425759222 0.01710735668576828655 -0.1331772435373809738 -0.1667954193905802629 -0.3740819450266614776 0.3769324932094561542 0.3959589198747823779 -0.1334446644933701409 -0.2466063005757039572 +'MRT44-1706' .2476818659884404694 -0.3881425512609436579 0.3323773856539967708 0.1953330602348201106 0.3237058073324557972 0.004972444866466287083 -0.2688995707705105209 0.09137048577531849125 -0.2490094177243531437 -0.01588587950451505679 0.05765880356308331761 0.08348799747159392493 0.2527096059045198517 -0.3847041339047420627 -0.3252785110787811407 0.2003317135991344033 0.3325789310299764323 +'MZC01-1706' 0.02019300889983394881 0.1402188357850339961 0.07248058238809959586 -0.009326939965943793071 -0.1218544587159723636 -0.1549945219448504163 0.02001082669780943762 -0.07356499216768871974 0.2941154377800699882 0.1125678135158421633 -0.1379741446013496298 -0.1803368512726943595 -0.02060291051482008445 0.1389766867934757177 -0.07093255118706195961 -0.009565620196435626818 -0.1251946202478005365 +'MZC02-1706' .03095008230892063936 -0.1304917884832104136 0.001017510605822849251 0.03101869907137164151 0.1043926022158073591 0.1842814355617958533 -0.0003775164637455381681 0.1224178420661012068 -0.3122185721876272191 0.00949022300987163378 0.1257338856882518341 0.09819214022686766075 0.0315783437426332067 -0.1293358079577441311 -0.0009957787417386679968 0.03181248034057086727 0.1072541155145650821 +'MZF01-1706' .4238778184828426721 0.362626384987233874 0.3258691643671041138 0.09661617574480141357 -0.1584945773865845675 0.02348538437289832137 -0.3392282875688631405 -0.1763786227422756425 0.1568188688576882539 -0.01231037757463507819 -0.1810903657389125454 -0.1642260084558608835 0.4324821925617519658 0.359414006308560019 -0.3189092915670317385 0.09908862342648597221 -0.1628390839066454487 +'MZF02-1706' .3951791165152739316 0.3144966655877023953 -0.1150899148085675616 0.157488025794488673 0.06408943612263484635 0.1450594286368126484 -0.2608602793145025633 -0.03372832036102280107 0.04325673744016556022 -0.1979513651183880396 -0.1870528524445073393 0.1678299972758514336 0.4032009303455910687 0.3117106510425017296 0.1126318388221682343 0.1615182091594063729 0.06584619637079573706 +'MZF03-1706' 0.08092322409149305118 0.06162665343583644678 0.1844695886683845043 -0.02406535815245120294 -0.1622746504127902945 -0.1314510816205053945 0.07703254794835286134 -0.07238598479369670602 0.2144567561892637697 0.1952843497189999944 -0.08219519528702012856 -0.2676815965122152363 -0.08256589955454703145 0.06108072474523034562 -0.1805297102969308787 -0.02468120056718410213 -0.1667227727926455516 +'MZO01-1706' 0.1307758399349754908 -0.2212168536876731595 0.3329480808214752563 -0.1141536834264475775 -0.1566273955788392569 -0.1966640449024798232 -0.3442769741360834357 -0.1452304777154629079 0.1631011801756426238 0.02627338333863271647 0.03619828338696071124 -0.1715630803802632165 -0.1334304828490860129 -0.2192571719502987293 -0.3258370174103475403 -0.1170749231439972421 -0.16092072064101276 +'MZO02-1706' .1265628459513608028 0.2119313183642511644 -0.4246825760479908674 0.1015195125529895909 0.1979067463883590894 0.1930384919643478026 0.3383229901496460634 0.2090938523144613426 -0.1551049378954044433 -0.01336722097785999694 -0.02883766379597153817 0.2232949949226682995 0.1291319685229420366 0.210053893894764393 0.4156122587768196763 0.1041174386406498176 0.2033315827722001756 +'MZP01-1706' .0441301273643714756 0.1801505816427972639 -0.01524715863803512497 0.06289124448329069805 -0.1380465225571813059 0.006365989883024572582 0.1501663046130006784 -0.2640751640578292148 0.1220114500346160119 -0.2367774399422623577 -0.1241855346546572453 -0.02463501511214079981 0.04502593296550447266 0.1785546914611151059 0.01492151173342741444 0.06450065730078503867 -0.1418305259420956643 +'MZP02-1706' 0.1668301397608515091 -0.2756146240200646469 0.1095081489823545168 -0.1666520773266773614 0.03611928595975111983 -0.2103212184787807693 -0.2890710184374202241 0.1321399295104344895 0.07482911456239958736 0.1873395142419100046 0.1324403813939175056 -0.05491271919303714055 -0.1702166555622137145 -0.2731730517065553698 -0.1071692876514003662 -0.170916772540060713 0.03710935436423247469 +}; +coef(end).label = temp(:,1); +coef(end).value = cell2mat(temp(:,2:end)); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% remove the '-1706' part from all channel labels +for i=1:5 + for j=1:length(coef(i).reference) + coef(i).reference{j} = coef(i).reference{j}(1:(end-5)); + end + for j=1:length(coef(i).label) + coef(i).label{j} = coef(i).label{j}(1:(end-5)); + end +end diff --git a/external/fieldtrip/fileio/private/read_ctf_dat.m b/external/fieldtrip/fileio/private/read_ctf_dat.m new file mode 100644 index 0000000..af47562 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_ctf_dat.m @@ -0,0 +1,84 @@ +function [meg] = read_ctf_dat(filename); + +% READ_CTF_DAT reads MEG data from an ascii format CTF file +% +% meg = read_ctf_dat(filename) +% +% returns a structure with the following fields: +% meg.data Nchans x Ntime +% meg.time 1xNtime in miliseconds +% meg.trigger 1xNtime with trigger values +% meg.label 1xNchans cell array with channel labels (string) + +% Copyright (C) 2002, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_ctf_dat.m 945 2010-04-21 17:41:20Z roboos $ + +fid = fopen(filename, 'r'); +if fid==-1 + error(sprintf('could not open file %s', filename)); +end + +% read the sample number +line = fgetl(fid); +[tok, rem] = strtok(line, ':'); +meg.sample = str2num(rem(2:end)); + +% read the time of each sample and convert to miliseconds +line = fgetl(fid); +[tok, rem] = strtok(line, ':'); +meg.time = 1000*str2num(rem(2:end)); + +% read the trigger channel +line = fgetl(fid); +[tok, rem] = strtok(line, ':'); +meg.trigger = str2num(rem(2:end)); + +% read the rest of the data +meg.data = []; +meg.label = {}; +chan = 0; +while (1) + line = fgetl(fid); + if ~isempty(line) & line==-1 + % reached end of file + break + end + [tok, rem] = strtok(line, ':'); + if ~isempty(rem) + chan = chan + 1; + meg.data(chan, :) = str2num(rem(2:end)); + meg.label{chan} = fliplr(deblank(fliplr(deblank(tok)))); + end +end + +% convert to fT (?) +meg.data = meg.data * 1e15; + +% apparently multiple copies of the data can be stored in the file +% representing the average, the standard deviation, etc. +% keep only the first part of the data -> average +tmp = find(diff(meg.time)<0); +if ~isempty(tmp) + meg.data = meg.data(:,1:tmp(1)); + meg.time = meg.time(1:tmp(1)); + meg.trigger = meg.trigger(1:tmp(1)); + meg.sample = meg.sample(1:tmp(1)); +end + diff --git a/external/fileio/private/read_ctf_hc.m b/external/fieldtrip/fileio/private/read_ctf_hc.m similarity index 85% rename from external/fileio/private/read_ctf_hc.m rename to external/fieldtrip/fileio/private/read_ctf_hc.m index 8e3d63f..f514a30 100644 --- a/external/fileio/private/read_ctf_hc.m +++ b/external/fieldtrip/fileio/private/read_ctf_hc.m @@ -13,20 +13,20 @@ % hc = read_ctf_hc(filename) % % returns a structure with the following fields -% hc.dewar.nas marker positions relative to dewar +% hc.dewar.nas marker positions relative to dewar % hc.dewar.lpa % hc.dewar.rpa -% hc.head.nas marker positions relative to head (measured) +% hc.head.nas marker positions relative to head (measured) % hc.head.lpa % hc.head.rpa -% hc.standard.nas marker positions relative to head (expected) +% hc.standard.nas marker positions relative to head (expected) % hc.standard.lpa % hc.standard.rpa % and -% hc.affine parameter for affine transformation (1x12) -% hc.homogenous homogenous transformation matrix (4x4, see warp3d) -% hc.translation translation vector (1x3) -% hc.rotation rotation matrix (3x3) +% hc.affine parameter for affine transformation (1x12) +% hc.homogenous homogenous transformation matrix (4x4, see warp3d) +% hc.translation translation vector (1x3) +% hc.rotation rotation matrix (3x3) % % Gradiometer positions can be transformed into head coordinates using the % homogeneous transformation matrix, or using the affine parameters and @@ -34,24 +34,23 @@ % Copyright (C) 2002, Robert Oostenveld % -% $Log: read_ctf_hc.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.4 2005/06/01 08:04:24 roboos -% removed the conversion from cm to mm, output now is in mm for consistency with other ctf functions +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.3 2003/03/12 16:15:18 roberto -% added extra warning for mm units +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.2 2003/03/11 15:24:51 roberto -% updated help and copyrights +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: read_ctf_hc.m 945 2010-04-21 17:41:20Z roboos $ global fb diff --git a/external/fieldtrip/fileio/private/read_ctf_hdm.m b/external/fieldtrip/fileio/private/read_ctf_hdm.m new file mode 100644 index 0000000..667af46 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_ctf_hdm.m @@ -0,0 +1,62 @@ +function [vol] = read_ctf_hdm(filename); + +% READ_CTF_HDM reads the head volume conductor model from a *.hdm file +% +% vol = read_ctf_hdm(filename) + +% Copyright (C) 2003, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_ctf_hdm.m 945 2010-04-21 17:41:20Z roboos $ + +vol = []; +ascii = read_ctf_ascii(filename); + +% remember all original details +vol.orig = ascii; + +if isfield(ascii, 'MultiSphere_Data') + chans = fieldnames(ascii.MultiSphere_Data); + % remove the fields SEARCH_RADIUS and HEADSHAPE_FILE + chans = chans(~(strcmp(chans, 'SEARCH_RADIUS') | strcmp(chans, 'HEADSHAPE_FILE'))); + for i=1:length(chans) + tmp = getfield(ascii.MultiSphere_Data, chans{i}); + vol.label{i} = chans{i}; + vol.r(i) = tmp(4); + vol.o(i, :) = tmp(1:3); + end + vol.r = vol.r(:); % ensure column vector +elseif isfield(ascii, 'MEG_Sphere') + vol.r = ascii.MEG_Sphere.RADIUS; + vol.o(1) = ascii.MEG_Sphere.ORIGIN_X; + vol.o(2) = ascii.MEG_Sphere.ORIGIN_Y; + vol.o(3) = ascii.MEG_Sphere.ORIGIN_Z; +else + error('no headmodel information found'); +end + +% add the fiducials, these are in raw MRI coordinates +if isfield(ascii, 'Fid_Points') + vol.mri.nas = ascii.Fid_Points.NASION; + vol.mri.lpa = ascii.Fid_Points.LEFT_EAR; + vol.mri.rpa = ascii.Fid_Points.RIGHT_EAR; +end + +% add the units in which the volume conductor is defined +vol.unit = 'cm'; + diff --git a/external/fieldtrip/fileio/private/read_ctf_meg4.m b/external/fieldtrip/fileio/private/read_ctf_meg4.m new file mode 100644 index 0000000..4a345a4 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_ctf_meg4.m @@ -0,0 +1,153 @@ +function [meg] = read_ctf_meg4(fname, hdr, begsample, endsample, chanindx) + +% READ_CTF_MEG4 reads specified samples from a CTF continous datafile +% It neglects all trial boundaries as if the data was acquired in +% non-continous mode. +% +% Use as +% [meg] = read_ctf_meg4(filename, hdr, begsample, endsample, chanindx) +% where +% filename name of the datafile, including the .meg4 extension +% header with all data information (from read_ctf_meg4) +% begsample index of the first sample to read +% endsample index of the last sample to read +% chanindx index of channels to read (optional, default is all) +% +% See also READ_CTF_MEG4 + +% "VSM MedTech Ltd. authorizes the release into public domain under the +% GPL licence of the Matlab source code files "read_ctf_res4.m" and +% "read_ctf_meg4.m" by the authors of said files from the F.C. Donders +% Centre, Nijmegen, The Netherlands." + +% Author(s): Jim McKay November 1999 +% Last revision: Jim McKay +% Copyright (c) 1999-2000 CTF Systems Inc. All Rights Reserved. +% +% modifications Copyright (C) 2002, Ole Jensen +% modifications Copyright (C) 2003, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_ctf_meg4.m 945 2010-04-21 17:41:20Z roboos $ + +% use global flag for feedback +global fb +if isempty(fb) + fb = 0; +end + +nsmp = hdr.nSamples; +ntrl = hdr.nTrials; +nchn = hdr.nChans; + +if begsample<1, error('cannot read before the start of the data'); end +if endsample>nsmp*ntrl*nchn, error('cannot read beyond the end of the data'); end +if begsample>endsample, error('cannot read a negative number of samples'); end +if nargin<5, chanindx = 1:nchn; end +if isempty(chanindx), error('no channels were specified for reading CTF data'); end + +%open the .meg4 file +fid = fopen(fname,'r','ieee-be'); +if fid == -1, + error('could not open datafile'); +end + +%check whether it is a known format +CTFformat=char(fread(fid, 8, 'uint8'))'; +% This function was written for MEG41RS, but also seems to work for some other formats +if ~strcmp(CTFformat(1,1:7),'MEG41CP') && ~strcmp(CTFformat(1,1:7),'MEG4CPT') + warning('meg4 format (%s) is not supported for file %s, trying anyway...', CTFformat(1,1:7), fname); +end + +%determine size of .meg4 file +fseek(fid, 0, 'eof'); +nbytes = ftell(fid); + +%number of trials per 2GB file FIXME assumes constancy across the .meg4 files +ntrlfile = round((nbytes-8)/(4*nchn*nsmp)); +%ntrlfile = (nbytes-8)/(4*nchn*nsmp); +openfile = 0; + +%determine which trials have to be read +begtrial = ceil(begsample/nsmp); +endtrial = ceil(endsample/nsmp); +trials = begtrial:endtrial; + +%to ensure correct sample handling in the case of multiple trials +sumsmp = [(begtrial-1):(endtrial-1)]*nsmp; +rawbeg = 1; + +minchn = min(chanindx); %to ensure correct channel handling in the case of blockwise reading +maxchn = max(chanindx); +loopchn = length(trials)==1 || (maxchn-minchn+1)<=nchn; %decide whether to read in blockwise, or the specified samples per channel + +raw = zeros(endsample-begsample+1, length(chanindx)); %allocate memory +for trllop = 1:length(trials) + trlnr = trials(trllop); + filenr = floor(trlnr/(ntrlfile+0.1)); + + %ensure that the correct .meg4 file is open + if filenr~=openfile && filenr>0, + fclose(fid); + nextname = sprintf('%s.%d_meg4', fname(1:(end-5)), filenr); + if fb + fprintf('data goes beyond 2GB file boundary, continuing with %s\n', nextname); + end + fid = fopen(nextname,'r','ieee-be'); + fseek(fid, 0, 'eof'); + openfile = filenr; + end + + %this is relative to the current datafile + rawtrl = mod(trlnr-1, ntrlfile) + 1; + offset = 8 + 4*(rawtrl-1)*nsmp*nchn; + + %begin and endsamples expressed as samples with respect to the current trial + tmpbeg = max(begsample-sumsmp(trllop), 1); + tmpend = min(endsample-sumsmp(trllop), nsmp); + rawend = rawbeg+tmpend-tmpbeg; + + %either read per channel or read entire trialblock and postselect the channels + if loopchn, + for chnlop = 1:length(chanindx) + %this is relative to the current trial + chanoffset = 4*(chanindx(chnlop)-1)*nsmp; + sampoffset = 4*(tmpbeg-1); + fseek(fid, offset+chanoffset+sampoffset, 'bof'); + [tmp, count] = fread(fid,[tmpend-tmpbeg+1,1],'int32'); + raw(rawbeg:rawend, chnlop) = tmp; + end + else + %this is relative to the current trial + chanoffset = 4*(minchn-1)*nsmp; + fseek(fid, offset+chanoffset, 'bof'); + ntmpchn = maxchn - minchn + 1; + [tmp, count] = fread(fid,[nsmp,length(ntmpchn)],'int32'); + selchn = chanindx - minchn + 1; %relative to the first channel to be read + raw(rawbeg:rawend, :) = tmp(tmpbeg:tmpend, selchn); + end + rawbeg = rawend+1; +end +fclose(fid); + +% multiply the dimensionless values with the calibration value +gain = hdr.gainV(chanindx); % only for selected channels +meg = raw'; % transpose the raw data +for i=1:size(meg,1) + meg(i,:) = gain(i)*meg(i,:); +end diff --git a/external/fieldtrip/fileio/private/read_ctf_mri.m b/external/fieldtrip/fileio/private/read_ctf_mri.m new file mode 100644 index 0000000..ddf3aca --- /dev/null +++ b/external/fieldtrip/fileio/private/read_ctf_mri.m @@ -0,0 +1,197 @@ +function [mri, hdr] = read_ctf_mri(filename); + + +% READ_CTF_MRI reads header and image data from a CTF version 2.2 MRI file +% +% Use as +% [mri, hdr] = read_ctf_mri(filename) +% +% See also READ_CTF_MRI4 + +% Copyright (C) 2003-2010 Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_ctf_mri.m 1064 2010-05-12 16:19:17Z marlal $ + +% Some versions require specifying latin1 (ISO-8859-1) character encoding. +fid = fopen(filename, 'rb', 'ieee-be', 'ISO-8859-1'); + +if fid<=0 + error(sprintf('could not open MRI file: %s\n', filename)); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% READ THE IMAGE HEADER +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +ws = warning('off'); + +% general header information +hdr.identifierString = fread(fid,[1 32],'uint8=>char'); % CTF_MRI_FORMAT VER 2.2 +hdr.imageSize = fread(fid,1,'int16'); % always = 256 +hdr.dataSize = fread(fid,1,'int16'); % 1 or 2(bytes) +hdr.clippingRange = fread(fid,1,'int16'); % max.integer value of data +hdr.imageOrientation = fread(fid,1,'int16'); % eg., 0 = left on left, 1 = left on right +hdr.mmPerPixel_sagittal = fread(fid,1,'float'); % voxel dimensions in mm +hdr.mmPerPixel_coronal = fread(fid,1,'float'); % voxel dimensions in mm +hdr.mmPerPixel_axial = fread(fid,1,'float'); % voxel dimensions in mm + +% HeadModel_Info specific header items +hdr.HeadModel.Nasion_Sag = fread(fid,1,'int16'); % fid.point coordinate(in voxels) for nasion - sagittal +hdr.HeadModel.Nasion_Cor = fread(fid,1,'int16'); % nasion - coronal +hdr.HeadModel.Nasion_Axi = fread(fid,1,'int16'); % nasion - axial +hdr.HeadModel.LeftEar_Sag = fread(fid,1,'int16'); % left ear - sagittal +hdr.HeadModel.LeftEar_Cor = fread(fid,1,'int16'); % left ear - coronal +hdr.HeadModel.LeftEar_Axi = fread(fid,1,'int16'); % left ear - axial +hdr.HeadModel.RightEar_Sag = fread(fid,1,'int16'); % right ear - sagittal +hdr.HeadModel.RightEar_Cor = fread(fid,1,'int16'); % right ear - coronal +hdr.HeadModel.RightEar_Axi = fread(fid,1,'int16'); % right ear - axial +fread(fid,2,'uint8'); % padding to 4 byte boundary +hdr.HeadModel.defaultSphereX = fread(fid,1,'float'); % sphere origin x coordinate(in mm) +hdr.HeadModel.defaultSphereY = fread(fid,1,'float'); % sphere origin y coordinate(in mm) +hdr.HeadModel.defaultSphereZ = fread(fid,1,'float'); % sphere origin z coordinate(in mm) +hdr.HeadModel.defaultSphereRadius = fread(fid,1,'float'); % default sphere radius(in mm) + +% Image_Info specific header items +hdr.Image.modality = fread(fid,1,'int16'); % 0 = MRI, 1 = CT, 2 = PET, 3 = SPECT, 4 = OTHER +hdr.Image.manufacturerName = fread(fid,[1 64],'uint8=>char'); +hdr.Image.instituteName = fread(fid,[1 64],'uint8=>char'); +hdr.Image.patientID = fread(fid,[1 32],'uint8=>char'); +hdr.Image.dateAndTime = fread(fid,[1 32],'uint8=>char'); +hdr.Image.scanType = fread(fid,[1 32],'uint8=>char'); +hdr.Image.contrastAgent = fread(fid,[1 32],'uint8=>char'); +hdr.Image.imagedNucleus = fread(fid,[1 32],'uint8=>char'); +fread(fid,2,'uint8'); % padding to 4 byte boundary +hdr.Image.Frequency = fread(fid,1,'float'); +hdr.Image.FieldStrength = fread(fid,1,'float'); +hdr.Image.EchoTime = fread(fid,1,'float'); +hdr.Image.RepetitionTime = fread(fid,1,'float'); +hdr.Image.InversionTime = fread(fid,1,'float'); +hdr.Image.FlipAngle = fread(fid,1,'float'); +hdr.Image.NoExcitations = fread(fid,1,'int16'); +hdr.Image.NoAcquisitions = fread(fid,1,'int16'); +hdr.Image.commentString = fread(fid,[1 256],'uint8=>char'); +hdr.Image.forFutureUse = fread(fid,[1 64],'uint8=>char'); + +% continuation general header +hdr.headOrigin_sagittal = fread(fid,1,'float'); % voxel location of head origin +hdr.headOrigin_coronal = fread(fid,1,'float'); % voxel location of head origin +hdr.headOrigin_axial = fread(fid,1,'float'); % voxel location of head origin +% euler angles to align MR to head coordinate system(angles in degrees !) +hdr.rotate_coronal = fread(fid,1,'float'); % 1. rotate in coronal plane by this angle +hdr.rotate_sagittal = fread(fid,1,'float'); % 2. rotate in sagittal plane by this angle +hdr.rotate_axial = fread(fid,1,'float'); % 3. rotate in axial plane by this angle +hdr.orthogonalFlag = fread(fid,1,'int16'); % if set then image is orthogonal +hdr.interpolatedFlag = fread(fid,1,'int16'); % if set than image was interpolated +hdr.originalSliceThickness = fread(fid,1,'float'); % original spacing between slices before interpolation +hdr.transformMatrix = fread(fid,[4 4],'float')'; % transformation matrix head->MRI[column][row] + +% Go to image data file position. +% fread(fid,202,'uint8'); % unused, padding to 1028 bytes. +% The previous (commented) line should read 202 bytes to get to the end of +% the header (position 1028), but it seems some versions of Matlab (or +% perhaps only on some systems) doesn't read 2 bytes somewhere and end up +% in position 1026... In any case, it caused an error with some files so +% we must explicitely seek to position 1028. +fseek(fid, 1028, 'bof'); + +% turn all warnings back on +warning(ws); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% READ THE IMAGE DATA +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +if hdr.dataSize == 1 + precision = '*uint8'; +elseif hdr.dataSize == 2 + if hdr.clippingRange < 2^15 + % I think this is usually the case, i.e. data is stored as signed 16 + % bit int, even though data is only positive. + precision = '*int16'; + else + precision = '*uint16'; + end +else + error('unknown datasize (%d) in CTF mri file.', hdr.dataSize); +end +mri = fread(fid, hdr.imageSize.^3, precision); +mri = reshape(mri, [hdr.imageSize hdr.imageSize hdr.imageSize]); +fclose(fid); + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% DO POST-PROCESSING +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Data is stored in PIR order (i.e. fastest changing direction goes from +% anterior to Posterior, then from superior to Inferior, finally from left +% to Right) assuming subject position was not too oblique and proper +% conversion to .mri format. (Does this depend on hdr.imageOrientation?) +% On the other hand, the transformation matrix and fiducials are in RPI +% order so we must reorient the image data to match them. +mri = permute(mri, [3 1 2]); + +transformMatrix = hdr.transformMatrix; + +% Construct minimal transformation matrix if fiducials were not defined. +% Bring data into same orientation (head coordinates are ALS) at least. +if all(transformMatrix == 0) + transformMatrix(1, 2) = -1; + transformMatrix(2, 1) = -1; + transformMatrix(3, 3) = -1; + transformMatrix(4, 4) = 1; +end + +% determine location of fiducials in MRI voxel coordinates +% flip the fiducials in voxel coordinates to correspond to the previous flip along left-right +hdr.fiducial.mri.nas = [hdr.HeadModel.Nasion_Sag hdr.HeadModel.Nasion_Cor hdr.HeadModel.Nasion_Axi]; +hdr.fiducial.mri.lpa = [hdr.HeadModel.LeftEar_Sag hdr.HeadModel.LeftEar_Cor hdr.HeadModel.LeftEar_Axi]; +hdr.fiducial.mri.rpa = [hdr.HeadModel.RightEar_Sag hdr.HeadModel.RightEar_Cor hdr.HeadModel.RightEar_Axi]; + +% Reorient the image data, the transformation matrix and the fiducials +% along the left-right direction. +% This may have been done only for visualization? It can probably be +% "turned off" without problem. +if true + mri = flipdim(mri, 1); + flip = [-1 0 0 hdr.imageSize+1 + 0 1 0 0 + 0 0 1 0 + 0 0 0 1 ]; + transformMatrix = flip*transformMatrix; + hdr.fiducial.mri.nas = [hdr.fiducial.mri.nas, 1] * flip(1:3, :)'; + hdr.fiducial.mri.lpa = [hdr.fiducial.mri.lpa, 1] * flip(1:3, :)'; + hdr.fiducial.mri.rpa = [hdr.fiducial.mri.rpa, 1] * flip(1:3, :)'; +end + +% re-compute the homogeneous transformation matrices (apply voxel scaling) +scale = eye(4); +scale(1,1) = hdr.mmPerPixel_sagittal; +scale(2,2) = hdr.mmPerPixel_coronal; +scale(3,3) = hdr.mmPerPixel_axial; +hdr.transformHead2MRI = transformMatrix*inv(scale); +hdr.transformMRI2Head = scale*inv(transformMatrix); + +% compute location of fiducials in MRI and HEAD coordinates +hdr.fiducial.head.nas = warp_apply(hdr.transformMRI2Head, hdr.fiducial.mri.nas, 'homogenous'); +hdr.fiducial.head.lpa = warp_apply(hdr.transformMRI2Head, hdr.fiducial.mri.lpa, 'homogenous'); +hdr.fiducial.head.rpa = warp_apply(hdr.transformMRI2Head, hdr.fiducial.mri.rpa, 'homogenous'); + + diff --git a/external/fieldtrip/fileio/private/read_ctf_mri4.m b/external/fieldtrip/fileio/private/read_ctf_mri4.m new file mode 100644 index 0000000..f23434b --- /dev/null +++ b/external/fieldtrip/fileio/private/read_ctf_mri4.m @@ -0,0 +1,286 @@ +function [mri, hdr, cpersist] = read_ctf_mri4(filename); + +% READ_CTF_MRI reads header and imnage data from CTF format MRI file +% +% [mri, hdr] = read_ctf_mri(filename) +% +% See also READ_CTF_MEG4, READ_CTF_RES4 + +% Copyright (C) 2008 Ivar Clemens +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_ctf_mri4.m 1362 2010-07-06 09:04:24Z roboos $ + +fid = fopen(filename,'rb', 'ieee-be'); + +if fid<=0 + error(sprintf('could not open MRI file: %s\n', filename)); +end + +[cpersist] = read_cpersist(fid); + +% turn warnings off +ws = warning('off'); + +% general header information +hdr.identifierString = get_value(cpersist, '_CTFMRI_VERSION'); % CTF_MRI_FORMAT VER 4.1 +hdr.imageSize = get_value(cpersist, '_CTFMRI_SIZE'); % 256 +hdr.dataSize = get_value(cpersist, '_CTFMRI_DATASIZE'); % 1 or 2(bytes) +hdr.orthogonalFlag = get_value(cpersist, '_CTFMRI_ORTHOGONALFLAG'); % if set then image is orthogonal +hdr.interpolatedFlag = get_value(cpersist, '_CTFMRI_INTERPOLATEDFLAG'); % if set than image was interpolated +hdr.comment = get_value(cpersist, '_CTFMRI_COMMENT'); + +hdr.Image.modality = get_value(cpersist, '_SERIES_MODALITY'); +hdr.Image.manufacturerName = get_value(cpersist, '_EQUIP_MANUFACTURER'); +hdr.Image.instituteName = get_value(cpersist, '_EQUIP_INSTITUTION'); +hdr.Image.imagedNucleus = get_value(cpersist, '_MRIMAGE_IMAGEDNUCLEUS'); +hdr.Image.FieldStrength = get_value(cpersist, '_MRIMAGE_FIELDSTRENGTH'); +hdr.Image.EchoTime = get_value(cpersist, '_MRIMAGE_ECHOTIME'); +hdr.Image.RepetitionTime = get_value(cpersist, '_MRIMAGE_REPETITIONTIME'); +hdr.Image.InversionTime = get_value(cpersist, '_MRIMAGE_INVERSIONTIME'); +hdr.Image.FlipAngle = get_value(cpersist, '_MRIMAGE_FLIPANGLE'); + +% euler angles to align MR to head coordinate system(angles in degrees !) +rotation = split_nvalue(get_value(cpersist, '_CTFMRI_ROTATE')); +hdr.rotate_coronal = rotation(1); +hdr.rotate_sagittal = rotation(2); +hdr.rotate_axial = rotation(3); + +hdr.transformMatrix = split_nvalue(get_value(cpersist, '_CTFMRI_TRANSFORMMATRIX')); +hdr.transformMatrix = reshape(hdr.transformMatrix, 4, 4)'; + +mmPerPixel = split_nvalue(get_value(cpersist, '_CTFMRI_MMPERPIXEL')); +hdr.mmPerPixel_sagittal = mmPerPixel(1); +hdr.mmPerPixel_coronal = mmPerPixel(2); +hdr.mmPerPixel_axial = mmPerPixel(3); + +% HeadModel_Info specific header items +hmNasion = split_nvalue(get_value(cpersist, '_HDM_NASION')); +hdr.HeadModel.Nasion_Sag = hmNasion(1); +hdr.HeadModel.Nasion_Cor = hmNasion(2); +hdr.HeadModel.Nasion_Axi = hmNasion(3); + +hmLeftEar = split_nvalue(get_value(cpersist, '_HDM_LEFTEAR')); +hdr.HeadModel.LeftEar_Sag = hmLeftEar(1); +hdr.HeadModel.LeftEar_Cor = hmLeftEar(2); +hdr.HeadModel.LeftEar_Axi = hmLeftEar(3); + +hmRightEar = split_nvalue(get_value(cpersist, '_HDM_RIGHTEAR')); +hdr.HeadModel.RightEar_Sag = hmRightEar(1); +hdr.HeadModel.RightEar_Cor = hmRightEar(2); +hdr.HeadModel.RightEar_Axi = hmRightEar(3); + +hmSphere = split_nvalue(get_value(cpersist, '_HDM_DEFAULTSPHERE')); +hdr.HeadModel.defaultSphereX = hmSphere(1); +hdr.HeadModel.defaultSphereY = hmSphere(2); +hdr.HeadModel.defaultSphereZ = hmSphere(3); +hdr.HeadModel.defaultSphereRadius = hmSphere(4); + +hmOrigin = split_nvalue(get_value(cpersist, '_HDM_HEADORIGIN')); +hdr.headOrigin_sagittal = hmOrigin(1); +hdr.headOrigin_coronal = hmOrigin(2); +hdr.headOrigin_axial = hmOrigin(3); + +%fread(fid,204,'char'); % unused, padding to 1028 bytes + +% revert to previous warning state +warning(ws); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% READ THE IMAGE DATA +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +mri = zeros(256, 256, 256); + +for slice = 1:256 + name = sprintf('_CTFMRI_SLICE_DATA#%.5d', slice); + offset = get_value(cpersist, name); + + fseek(fid, offset, 'bof'); + + if(hdr.dataSize == 1) + slicedata = uint8(fread(fid, [256 256], 'uint8')); + elseif(hdr.dataSize == 2) + slicedata = uint16(fread(fid, [256 256], 'uint16')); + else + error('Unknown datasize in CTF MRI file'); + end; + + mri(:, :, slice) = slicedata; +end; + +%mri = reshape(mri, [256 256 256]); +fclose(fid); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% DO POST-PROCESSING +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Data is stored in PIR order (i.e. fastest changing direction goes from +% anterior to Posterior, then from superior to Inferior, finally from left +% to Right) assuming subject position was not too oblique and proper +% conversion to .mri format. (Does this depend on hdr.imageOrientation?) +% On the other hand, the transformation matrix and fiducials are in RPI +% order so we must reorient the image data to match them. +mri = permute(mri, [3 1 2]); + +transformMatrix = hdr.transformMatrix; + +% Construct minimal transformation matrix if fiducials were not defined. +% Bring data into same orientation (head coordinates are ALS) at least. +if all(transformMatrix == 0) + transformMatrix(1, 2) = -1; + transformMatrix(2, 1) = -1; + transformMatrix(3, 3) = -1; + transformMatrix(4, 4) = 1; +end + +% determine location of fiducials in MRI voxel coordinates +% flip the fiducials in voxel coordinates to correspond to the previous flip along left-right +hdr.fiducial.mri.nas = [hdr.HeadModel.Nasion_Sag hdr.HeadModel.Nasion_Cor hdr.HeadModel.Nasion_Axi]; +hdr.fiducial.mri.lpa = [hdr.HeadModel.LeftEar_Sag hdr.HeadModel.LeftEar_Cor hdr.HeadModel.LeftEar_Axi]; +hdr.fiducial.mri.rpa = [hdr.HeadModel.RightEar_Sag hdr.HeadModel.RightEar_Cor hdr.HeadModel.RightEar_Axi]; + +% Reorient the image data, the transformation matrix and the fiducials +% along the left-right direction. +% This may have been done only for visualization? It can probably be +% "turned off" without problem. +if true + mri = flipdim(mri, 1); + flip = [-1 0 0 hdr.imageSize+1 + 0 1 0 0 + 0 0 1 0 + 0 0 0 1 ]; + transformMatrix = flip*transformMatrix; + hdr.fiducial.mri.nas = [hdr.fiducial.mri.nas, 1] * flip(1:3, :)'; + hdr.fiducial.mri.lpa = [hdr.fiducial.mri.lpa, 1] * flip(1:3, :)'; + hdr.fiducial.mri.rpa = [hdr.fiducial.mri.rpa, 1] * flip(1:3, :)'; +end + +% re-compute the homogeneous transformation matrices (apply voxel scaling) +scale = eye(4); +scale(1,1) = hdr.mmPerPixel_sagittal; +scale(2,2) = hdr.mmPerPixel_coronal; +scale(3,3) = hdr.mmPerPixel_axial; +hdr.transformHead2MRI = transformMatrix*inv(scale); +hdr.transformMRI2Head = scale*inv(transformMatrix); + +% compute location of fiducials in MRI and HEAD coordinates +hdr.fiducial.head.nas = warp_apply(hdr.transformMRI2Head, hdr.fiducial.mri.nas, 'homogenous'); +hdr.fiducial.head.lpa = warp_apply(hdr.transformMRI2Head, hdr.fiducial.mri.lpa, 'homogenous'); +hdr.fiducial.head.rpa = warp_apply(hdr.transformMRI2Head, hdr.fiducial.mri.rpa, 'homogenous'); + + +% +% Reads a series of delimited numbers from a string +% +% @param input string Delimited string to process +% @param delim string The delimiter (default: \\) +% +% @return values matrix Array containing the numbers found +% + function [values] = split_nvalue(input, delim) + if(nargin < 2), delim = '\\'; end; + + remain = input; + values = []; + + while(numel(remain > 0)) + [value, remain] = strtok(remain, delim); + values(end + 1) = str2num(value); + end; + end + +% +% Reads a value from the CPersist structure +% +% @param cpersist struct-array The CPersist structure +% @param key string The name of the parameter +% +% @return value mixed The value of the named parameter +% + function [value] = get_value(cpersist, key) + idx = find(strcmp({cpersist.key}, key)); + + if(numel(idx) < 1), error('Specified key does not exist.'); end; + if(numel(idx) > 1), error('Specified key is not unique.'); end; + + value = cpersist(idx).value; + end + +% +% Processes the CTF CPersist structure into a struct-array +% +% @param fid numeric File handle from which to read the CPersist structure +% @return cpersist struct-array +% + function [cpersist] = read_cpersist(fid) + magic = char(fread(fid, 4, 'char'))'; + + if(~strcmp(magic, 'WS1_')), error('Invalid CPersist header'); end; + + cpersist = struct('key', {}, 'value', {}); + + while(~feof(fid)) + % Read label + lsize = fread(fid, 1, 'int32'); + ltext = char(fread(fid, lsize, 'char'))'; + + % Last label in file is always EndOfParameters + if(strcmp(ltext, 'EndOfParameters')), return; end; + + % Read value + vtype = fread(fid, 1, 'int32'); + value = read_cpersist_value(fid, vtype); + + cpersist(end + 1).key = ltext; + cpersist(end).value = value; + end + end + +% +% Reads a single value of type (vtype) from fid +% +% @param fid numeric The file to read the value from +% @param vtype numeric The type of value to read +% +% @return value mixed The read value +% + function [value] = read_cpersist_value(fid, vtype) + switch vtype + case 3 + vsize = fread(fid, 1, 'int32'); + value = ftell(fid); + fseek(fid, vsize, 'cof'); + case 4 + value = fread(fid, 1, 'double'); + case 5 + value = fread(fid, 1, 'int32'); + case 6 + value = fread(fid, 1, 'int16'); + case 10 + vsize = fread(fid, 1, 'int32'); + value = char(fread(fid, vsize, 'char'))'; + otherwise + error(['Unsupported valuetype (' num2str(vtype) ') found in CPersist object']); + return + end + end + +end + diff --git a/external/fieldtrip/fileio/private/read_ctf_res4.m b/external/fieldtrip/fileio/private/read_ctf_res4.m new file mode 100644 index 0000000..188114c --- /dev/null +++ b/external/fieldtrip/fileio/private/read_ctf_res4.m @@ -0,0 +1,204 @@ +function [hdr] = read_ctf_res4(fname) + +% READ_CTF_RES4 reads the header in RES4 format from a CTF dataset +% +% Use as +% [hdr] = read_ctf_res4(filename) +% +% See also READ_CTF_MEG4 + +% "VSM MedTech Ltd. authorizes the release into public domain under the +% GPL licence of the Matlab source code files "read_ctf_res4.m" and +% "read_ctf_meg4.m" by the authors of said files from the F.C. Donders +% Centre, Nijmegen, The Netherlands." + +% Author(s): Jim McKay November 1999 +% Last revision: Jim McKay +% Copyright (c) 1999-2000 CTF Systems Inc. All Rights Reserved. +% +% modifications Copyright (C) 2002, Ole Jensen +% modifications Copyright (C) 2003, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_ctf_res4.m 945 2010-04-21 17:41:20Z roboos $ + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% read header information +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +fid = fopen(fname,'r','ieee-be'); + +% Check if header file exist +if fid == -1 + errMsg = strcat('Could not open header file:',fname); + error(errMsg); +end + +% First 8 bytes contain filetype, check is fileformat is correct. +% This function was written for MEG41RS, but also seems to work for some other formats +CTFformat=char(fread(fid,8,'uint8'))'; +if ~strcmp(CTFformat(1,1:7),'MEG41RS') && ~strcmp(CTFformat(1,1:7),'MEG42RS') && ~strcmp(CTFformat(1,1:7),'MEG3RES') + warning('res4 format (%s) is not supported for file %s, trying anyway...', CTFformat(1,1:7), fname); +end + +% Read the initial parameters +appName = char(fread(fid,256,'uint8'))' ; +dataOrigin = char(fread(fid,256,'uint8'))' ; +dataDescrip = char(fread(fid,256,'uint8'))' ; +no_trial_avgd = fread(fid,1,'int16') ; +data_time = char(fread(fid,255,'uint8'))'; +data_date = char(fread(fid,255,'uint8'))'; + +fseek(fid,1288,'bof'); +% Read the general recording parameters +no_samples = fread(fid,1,'int32'); +no_channels = fread(fid,1,'int16'); +fseek(fid,2,'cof'); % hole of 2 bytes due to improper alignment +sample_rate = fread(fid,1,'double'); +epoch = fread(fid,1,'double'); +no_trials = fread(fid,1,'int16'); +fseek(fid,2,'cof'); % hole of 2 bytes due to improper alignment +preTrigpts=fread(fid,1,'int32'); + +fseek(fid,1360,'bof'); +% read in the meg4Filesetup structure +run_name = char(fread(fid,32,'uint8')'); +run_title = char(fread(fid,256,'uint8')'); +instruments = char(fread(fid,32,'uint8')'); +coll_desc = char(fread(fid,32,'uint8')'); +subj_id = char(fread(fid,32,'uint8')'); +operator = char(fread(fid,32,'uint8')') ; +sensFilename = char(fread(fid,60,'uint8')') ; + +% not nececssary to seek, the file pointer is already at the desired location +% fseek(fid,1836,'bof'); + +% Read in the run description length +rd_len=fread(fid,1,'uint32'); +% Go to the run description and read it in +fseek(fid,1844,'bof'); +run_desc=char(fread(fid,rd_len,'uint8')'); + +% read in the filter information +num_filt=fread(fid,1,'uint16'); +for fi=0:(num_filt-1), + %filt_info=fread(fid,18,'uint8'); + filt_freq =fread(fid,1, 'double'); + filt_class=fread(fid,1, 'uint32'); + filt_type =fread(fid,1, 'uint32'); + num_fparm=fread(fid, 1, 'uint16'); + %num_fparm=filt_info(18); + if num_fparm ~= 0, + filt_parm=fread(fid,8*num_fparm,'uint8'); + end % if +end % for fi + +% Read in the channel names +for i=1:no_channels, + temp=fread(fid,32,'uint8')'; + temp(find(temp<32 )) = ' '; % remove non-printable characters + temp(find(temp>126)) = ' '; % remove non-printable characters + endstr = findstr(temp, '-'); temp(endstr:end) = ' '; % cut off at '-' + endstr = findstr(temp, ' '); temp(endstr:end) = ' '; % cut off at ' ' + chan_name(i,:) = char(temp); % as char array + chan_label{i} = deblank(char(temp)); % as cell array +end %for + +% pre-allocate some memory space +sensGain = zeros([no_channels,1]); +qGain = zeros([no_channels,1]); +ioGain = zeros([no_channels,1]); +sensType = zeros([no_channels,1]); + +% Read in the sensor information +fp = ftell(fid); +for chan=1:no_channels, + fread(fid,1,'uint8'); % Read and ignore 1 byte from enum + sensType(chan)=fread(fid,1,'uint8'); % Read sensor type + fread(fid,2,'uint8'); % Read and ignore originalRunNum + fread(fid,4,'uint8'); % Read and ignore coilShape + sensGain(chan)=fread(fid,1,'double'); % Read sensor gain in Phi0/Tesla + qGain(chan)=fread(fid,1,'double'); % Read qxx gain (usually 2^20 for Q20) + ioGain(chan)=fread(fid,1,'double'); % Read i/o gain of special sensors (usually 1.0) + ioOffset(chan)=fread(fid,1,'double'); + numCoils(chan)=fread(fid,1,'int16'); + grad_order_no(chan)=fread(fid,1,'int16'); + fread(fid,4,'uint8'); + + % read the coil positions and orientations + for i=1:8 + Chan(chan).coil(i).pos = fread(fid,3,'double')'; + fread(fid,1,'double'); + Chan(chan).coil(i).ori = fread(fid,3,'double')'; + fread(fid,3,'double'); + end + + % read the coil positions and orientations in head coordinates(?) + for i=1:8 + Chan(chan).coilHC(i).pos = fread(fid,3,'double')'; + fread(fid,1,'double'); + Chan(chan).coilHC(i).ori = fread(fid,3,'double')'; + fread(fid,3,'double'); + end + + % jump to the next sensor info record + fseek(fid, fp+chan*1328, 'bof'); +end % for chan + +% close the header file +fclose(fid); + +% according to Tom Holroyd, the sensor types are +% +% meg channels are 5, refmag 0, refgrad 1, adcs 18. +% UPPT001 is 11 +% UTRG001 is 11 +% SCLK01 is 17 +% STIM is 11 +% SCLK01 is 17 +% EEG057 is 9 +% ADC06 is 18 +% ADC07 is 18 +% ADC16 is 18 +% V0 is 15 + +% assign all the variables that should be outputted as header information +hdr.Fs = sample_rate; +hdr.nChans = no_channels; +hdr.nSamples = no_samples; +hdr.nSamplesPre = preTrigpts; +hdr.timeVec = (1:no_samples)/sample_rate - preTrigpts/sample_rate - 1/sample_rate; +hdr.nTrials = no_trials; +hdr.gainV = ioGain./(qGain.*sensGain); +hdr.ioGain = ioGain; +hdr.qGain = qGain; +hdr.sensGain = sensGain; +hdr.sensType = sensType; + +hdr.label = chan_label(:); +hdr.nameALL = chan_name; +hdr.Chan = Chan; +% hdr.rowMEG = rowMEG; +% hdr.rowEEG = rowEEG; +% hdr.rowTRIG = rowTRIG; +% hdr.rowREF = rowREF; +% hdr.nameEEG = []; +% hdr.nameMEG = []; +% hdr.nameEOG = []; +% hdr.trigV = []; +% hdr.SwapData = []; diff --git a/external/fieldtrip/fileio/private/read_ctf_sens.m b/external/fieldtrip/fileio/private/read_ctf_sens.m new file mode 100644 index 0000000..00e19ca --- /dev/null +++ b/external/fieldtrip/fileio/private/read_ctf_sens.m @@ -0,0 +1,122 @@ +function [magn] = read_ctf_sens(filename); + +% READ_CTF_SENS reads MEG sensor information from CTF configuration file +% +% magn = read_ctf_sens(filename) +% +% where the returned structure meg has the fields +% magn.pnt position first coil +% magn.ori orientation first coil +% magn.pnt2 position second coil +% magn.ori2 orientation second coil + +% Copyright (C) 2002, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_ctf_sens.m 945 2010-04-21 17:41:20Z roboos $ + +fid = fopen(filename, 'r'); +if fid==-1 + error(sprintf('could not open file %s', filename)); +end + +% skip the first line +line = fgetl(fid); + +% read the channel parameters +chan = 0; +while (1) + line = fgetl(fid); + if ~isempty(line) & line==-1 + % reached end of file + break + end + + element = tokenize(line); + if ~isempty(element) + chan = chan+1; + + % channel label or name + name{chan} = strtok(element{1}, '-'); + + % type of channel (EEG/MEG etc.), convert to uppercase + type{chan} = upper(element{7}); + + % number of coils (magnetometer=1/gradiometer=2) + ncoils(chan) = str2num(element{2}); + + % polarity of channel + polarity(chan) = str2num(element{26}); + + % position of first coil + coil1.pnt(chan,:) = [str2num(element{17}) str2num(element{18}) str2num(element{19})]; + % direction of first coil + coil1.dir(chan,:) = [str2num(element{20}) str2num(element{21})]; + + % length of basline + baseline.length(chan) = str2num(element{16}); + % direction of baseline + baseline.dir(chan,:) = [str2num(element{22}) str2num(element{23})]; + + % direction of second coil + coil2.dir(chan,:) = [str2num(element{24}) str2num(element{25})]; + end +end + +% find the sensor gradiometer channels +indx = find(strcmp(type, 'GRAD1-SENS')); +nchan = length(indx); +label = name(indx); +pnt1 = coil1.pnt(indx,:) * 10; % convert from cm to mm + +% shift offset to origin to make triangulation +offset = [mean(pnt1(:,1)) mean(pnt1(:,2)) min(pnt1(:,3))]; +prj = elproj(pnt1 - repmat(offset, nchan, 1)); +tri = delaunay(prj(:,1), prj(:,2)); + +% compute the directional vectors of each gradiometer: bottom coil +a = coil1.dir(indx,1); +b = coil1.dir(indx,2); +[r1, r2, r3] = sph2cart(a*2*pi/360, pi/2 - b*2*pi/360, ones(nchan,1)); +r1 = -r1 .* polarity(indx)'; +r2 = -r2 .* polarity(indx)'; +r3 = -r3 .* polarity(indx)'; +ori1 = [r1 r2 r3]; + +% compute the directional vectors of each gradiometer: top coil +a = coil2.dir(indx,1); +b = coil2.dir(indx,2); +[r1, r2, r3] = sph2cart(a*2*pi/360, pi/2 - b*2*pi/360, ones(nchan,1)); +r1 = -r1 .* polarity(indx)'; +r2 = -r2 .* polarity(indx)'; +r3 = -r3 .* polarity(indx)'; +ori2 = [r1 r2 r3]; + +% compute the directional vectors of the baseline and the position of the 2nd coil +a = baseline.dir(indx,1); +b = baseline.dir(indx,2); +[r1, r2, r3] = sph2cart(a*2*pi/360, pi/2 - b*2*pi/360, ones(nchan,1)); +oriB = [r1 r2 r3]; +pnt2 = pnt1 + oriB .* repmat(baseline.length(indx)', 1, 3); + +magn.pnt = pnt1; +magn.ori = ori1; +magn.pnt2 = pnt2; +magn.ori2 = ori2; +magn.tri = tri; +magn.label = label; diff --git a/external/fieldtrip/fileio/private/read_ctf_shape.m b/external/fieldtrip/fileio/private/read_ctf_shape.m new file mode 100644 index 0000000..6b37534 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_ctf_shape.m @@ -0,0 +1,41 @@ +function [shape] = read_ctf_shape(filename); + +% READ_CTF_SHAPE reads headshape points and header information +% from a CTF *.shape teh accompanying *.shape_info file. +% +% Use as +% [shape] = read_ctf_shape(filename) +% where filename should have the .shape extension + +% Copyright (C) 2003, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_ctf_shape.m 945 2010-04-21 17:41:20Z roboos $ + +shape = read_ctf_ascii([filename '_info']); + +if ~strcmp(shape.MRI_Info.COORDINATES, 'HEAD') + warning('points on head shape are NOT in headcoordinates') +end + +fid = fopen(filename, 'rt'); +num = fscanf(fid, '%d', 1); +shape.pnt = fscanf(fid, '%f', inf); +shape.pnt = reshape(shape.pnt, [3 num])'; +fclose(fid); + diff --git a/external/fileio/private/read_ctf_shm.c b/external/fieldtrip/fileio/private/read_ctf_shm.c similarity index 100% rename from external/fileio/private/read_ctf_shm.c rename to external/fieldtrip/fileio/private/read_ctf_shm.c diff --git a/external/fieldtrip/fileio/private/read_ctf_shm.m b/external/fieldtrip/fileio/private/read_ctf_shm.m new file mode 100644 index 0000000..a762e42 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_ctf_shm.m @@ -0,0 +1,65 @@ +function [varargout] = funname(varargin) + +% READ_CTF_SHM reads metainformation or selected blocks of data from +% shared memory. This function can be used for real-time processing of +% data while it is being acquired. +% +% Use as +% [msgType msgId sampleNumber numSamples numChannels] = read_ctf_shm; +% or +% [data] = read_ctf_shm(msgNumber); +% [data] = read_ctf_shm(msgNumber, numValues); +% +% See also WRITE_CTF_SHM + +% Copyright (C) 2006, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_ctf_shm.m 945 2010-04-21 17:41:20Z roboos $ + +% remember the original working directory +pwdir = pwd; + +% determine the name and full path of this function +funname = mfilename('fullpath'); +mexsrc = [funname '.c']; +[mexdir, mexname] = fileparts(funname); + +try + % try to compile the mex file on the fly + warning('trying to compile MEX file from %s', mexsrc); + cd(mexdir); + mex(mexsrc); + cd(pwdir); + success = true; + +catch + % compilation failed + disp(lasterr); + error('could not locate MEX file for %s', mexname); + cd(pwdir); + success = false; +end + +if success + % execute the mex file that was juist created + funname = mfilename; + funhandle = str2func(funname); + [varargout{1:nargout}] = funhandle(varargin{:}); +end + diff --git a/external/fileio/private/read_ctf_shm.mexa64 b/external/fieldtrip/fileio/private/read_ctf_shm.mexa64 similarity index 100% rename from external/fileio/private/read_ctf_shm.mexa64 rename to external/fieldtrip/fileio/private/read_ctf_shm.mexa64 diff --git a/external/fileio/private/read_ctf_shm.mexglx b/external/fieldtrip/fileio/private/read_ctf_shm.mexglx similarity index 100% rename from external/fileio/private/read_ctf_shm.mexglx rename to external/fieldtrip/fileio/private/read_ctf_shm.mexglx diff --git a/external/fileio/private/read_ctf_shm.mexmaci b/external/fieldtrip/fileio/private/read_ctf_shm.mexmaci similarity index 84% rename from external/fileio/private/read_ctf_shm.mexmaci rename to external/fieldtrip/fileio/private/read_ctf_shm.mexmaci index e4d985c..3bb3ae4 100755 Binary files a/external/fileio/private/read_ctf_shm.mexmaci and b/external/fieldtrip/fileio/private/read_ctf_shm.mexmaci differ diff --git a/external/fileio/private/read_ctf_shm.mexmaci64 b/external/fieldtrip/fileio/private/read_ctf_shm.mexmaci64 similarity index 100% rename from external/fileio/private/read_ctf_shm.mexmaci64 rename to external/fieldtrip/fileio/private/read_ctf_shm.mexmaci64 diff --git a/external/fieldtrip/fileio/private/read_ctf_svl.m b/external/fieldtrip/fileio/private/read_ctf_svl.m new file mode 100644 index 0000000..8a6ebfa --- /dev/null +++ b/external/fieldtrip/fileio/private/read_ctf_svl.m @@ -0,0 +1,105 @@ +% [data, hdr] = opensvl(filename) +% +% Reads a CTF SAM (.svl) file. + +function [data, hdr] = read_ctf_svl(filename) + + fid = fopen(filename, 'rb', 'ieee-be', 'ISO-8859-1'); + + if fid <= 0 + error('Could not open SAM file: %s\n', filename); + end + + + % ---------------------------------------------------------------------- + % Read header. + hdr.identity = fread(fid, 8, '*char')'; % 'SAMIMAGE' + hdr.version = fread(fid, 1, 'int32'); % SAM file version. + hdr.setName = fread(fid, 256, '*char')'; % Dataset name. + hdr.numChans = fread(fid, 1, 'int32'); + hdr.numWeights = fread(fid, 1, 'int32'); % 0 for static image. + if(hdr.numWeights ~= 0) + warning('hdr.numWeights ~= 0'); + end + + fread(fid,1,'int32'); % Padding to next 8 byte boundary. + + hdr.xmin = fread(fid, 1, 'double'); % Bounding box coordinates (m). + hdr.xmax = fread(fid, 1, 'double'); + hdr.ymin = fread(fid, 1, 'double'); + hdr.ymax = fread(fid, 1, 'double'); + hdr.zmin = fread(fid, 1, 'double'); + hdr.zmax = fread(fid, 1, 'double'); + hdr.stepSize = fread(fid, 1, 'double'); % m + + hdr.hpFreq = fread(fid, 1, 'double'); % High pass filtering frequency (Hz). + hdr.lpFreq = fread(fid, 1, 'double'); % Low pass. + hdr.bwFreq = fread(fid, 1, 'double'); % Bandwidth + hdr.meanNoise = fread(fid, 1, 'double'); % Sensor noise (T). + + hdr.mriName = fread(fid, 256, '*char')'; + hdr.fiducial.mri.nas = fread(fid, 3, 'int32'); % CTF MRI voxel coordinates? + hdr.fiducial.mri.rpa = fread(fid, 3, 'int32'); + hdr.fiducial.mri.lpa = fread(fid, 3, 'int32'); + + hdr.SAMType = fread(fid, 1, 'int32'); % 0: image, 1: weights array, 2: weights list. + hdr.SAMUnit = fread(fid, 1, 'int32'); + % Possible values: 0 coefficients Am/T, 1 moment Am, 2 power (Am)^2, 3 Z, + % 4 F, 5 T, 6 probability, 7 MUSIC. + + fread(fid, 1, 'int32'); % Padding to next 8 byte boundary. + + if hdr.version > 1 + % Version 2 has extra fields. + hdr.fiducial.head.nas = fread(fid, 3, 'double'); % CTF head coordinates? + hdr.fiducial.head.rpa = fread(fid, 3, 'double'); + hdr.fiducial.head.lpa = fread(fid, 3, 'double'); + hdr.SAMUnitName = fread(fid, 32, '*char')'; + % Possible values: 'Am/T' SAM coefficients, 'Am' source strength, + % '(Am)^2' source power, ('Z', 'F', 'T') statistics, 'P' probability. + end + + + % ---------------------------------------------------------------------- + % Read image data. + data = fread(fid, inf, 'double'); + fclose(fid); + + % Raw image data is ordered as a C array with indices: [x][y][z], meaning + % z changes fastest and x slowest. These x, y, z axes point to ALS + % (anterior, left, superior) respectively in real world coordinates, + % which means the voxels are in SLA order. + + + % ---------------------------------------------------------------------- + % Post processing. + + % Change from m to mm. + hdr.xmin = hdr.xmin * 1000; + hdr.ymin = hdr.ymin * 1000; + hdr.zmin = hdr.zmin * 1000; + hdr.xmax = hdr.xmax * 1000; + hdr.ymax = hdr.ymax * 1000; + hdr.zmax = hdr.zmax * 1000; + hdr.stepSize = hdr.stepSize * 1000; + + % Number of voxels in each dimension. + hdr.dim = [round((hdr.xmax - hdr.xmin)/hdr.stepSize) + 1, ... + round((hdr.ymax - hdr.ymin)/hdr.stepSize) + 1, ... + round((hdr.zmax - hdr.zmin)/hdr.stepSize) + 1]; + + data = reshape(data, hdr.dim([3, 2, 1])); + + % Build transformation matrix from raw voxel coordinates (indexed from 1) + % to head coordinates in mm. Note that the bounding box is given in + % these coordinates (in m, but converted above). + % Apply scaling. + hdr.transform = diag([hdr.stepSize * ones(1, 3), 1]); + % Reorder directions. + hdr.transform = hdr.transform(:, [3, 2, 1, 4]); + % Apply translation. + hdr.transform(1:3, 4) = [hdr.xmin; hdr.ymin; hdr.zmin] - hdr.stepSize; + % -step is needed since voxels are indexed from 1. + +end + diff --git a/external/fieldtrip/fileio/private/read_ctf_trigger.m b/external/fieldtrip/fileio/private/read_ctf_trigger.m new file mode 100644 index 0000000..dbf185a --- /dev/null +++ b/external/fieldtrip/fileio/private/read_ctf_trigger.m @@ -0,0 +1,80 @@ +function [backpanel, frontpanel] = read_ctf_trigger(dataset) + +% READ_CTF_TRIGGER reads the STIM channel from a dataset and detects +% the trigger moments and values +% +% [backpanel, frontpanel] = read_ctf_trigger(dataset) +% +% This returns all samples of the STIM channel, converted to backpanel +% and frontpanel trigger values. Triggers are placed at the rising flank +% of the STIM channel. +% +% Triggers should be at least 9 samples long (for 1200Hz samplerate) and +% should not overlap each other. +% +% See also READ_CTF_MEG4, READ_CTF_RES4 + +% Copyright (C) 2003, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_ctf_trigger.m 945 2010-04-21 17:41:20Z roboos $ + +[path, file, ext] = fileparts(dataset); +datafile = fullfile(dataset, [file '.meg4']); +headerfile = fullfile(dataset, [file '.res4']); + +% read the header from the raw CTF data +hdr = read_ctf_res4(headerfile); + +% number of samples to shift the assesment of the trigger value +% this is needed because it takes some time for the rising flank to get to the correct value +trigshift = fix(hdr.Fs * 9/1200); + +% read the stimulus channel from raw CTF data: with the new electronics +% control console used at NIH, there is now no longer any channel +% named "STIM". Instead, there are a variety of channel names. The +% electronics used at FCDC still uses the "STIM" channel. +stimindx = find(strcmp(hdr.label, 'UPPT001')); +if isempty(stimindx) + stimindx = find(strcmp(hdr.label, 'USPT001')); +end +if isempty(stimindx) + stimindx = find(strcmp(hdr.label, 'UTRG001')); +end +if isempty(stimindx) + stimindx = find(strcmp(hdr.label, 'STIM')); +end +stim = read_ctf_meg4(datafile, hdr, 1, hdr.nTrials*hdr.nSamples, stimindx); + +% correct for reading stimulus channel as signed integer, whereas it should be an unsigned int +stim(find(stim<0)) = stim(find(stim<0)) + 2^32; + +% split backpanel and frontpanel data +bpstim = fix(stim / 2^16); +fpstim = double(bitand(uint32(stim), 2^16-1)); + +% determine the precise timing of the triggers +bpupflank = [0 (diff(bpstim)>0 & bpstim(1:(end-1))==0)]; +backpanel = bpupflank(1:(end-trigshift)).*bpstim((1+trigshift):end); +fpupflank = [0 (diff(fpstim)>0 & fpstim(1:(end-1))==0)]; +frontpanel = fpupflank(1:(end-trigshift)).*fpstim((1+trigshift):end); + +% pad with zeros to ensure same length as data +backpanel(length(stim)) = 0; +frontpanel(length(stim)) = 0; + diff --git a/external/fieldtrip/fileio/private/read_curry.m b/external/fieldtrip/fileio/private/read_curry.m new file mode 100644 index 0000000..5a3bef4 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_curry.m @@ -0,0 +1,97 @@ +function s = read_curry(filename) + +% READ_CURRY reads and parses Curry V2 and V4 ascii files and returns the +% content in a structure that is similar to the block-structured layout of +% the file. This function does not interpret the content of the file, but +% is intended as a helper function for READ_CURRY_XXX functions (where XXX +% is the extension of the file). +% +% Use as +% s = read_curry(filename) + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_curry.m 945 2010-04-21 17:41:20Z roboos $ + + +fid = fopen(filename, 'rt'); +if fid<0 + error(sprintf('could not open file: %s', filename)); +end + +s = []; +line = []; + +while ~feof(fid) + line = fgetl(fid); + blockname = ''; + + % search for the beginning of a block + if ~isempty(strfind(line, 'START')) + [blockname, blocktype] = strtok(line); + blockname = strtrim(blockname); + blocktype = strtrim(strtok(blocktype)); + val = {}; + + % fprintf('reading block %s\n', blockname); + while isempty(strfind(line, 'END')) + + % read the next line + line = fgetl(fid); + % process the data in the line + if strcmp(blocktype, 'START') & ~isempty(strfind(line, '=')) + % the line looks like "lhs = rhs" + [lhs, rhs] = strtok(line, '='); + lhs = strtrim(lhs); + rhs(1) = ' '; + rhs = strtrim(rhs); + val = str2double(rhs); + if isnan(val) + val = rhs; + end + s = setfield(s, blockname, lhs, val); + elseif strcmp(blocktype, 'START_LIST') + % this contains unstructured data, process this line as being part of a list + val{end+1} = line; + else + % process this line differently + % FIXME + end + + if isnumeric(line) | feof(fid) + error('unexpected end of file'); + end + + end % while ~END + end % if START of block + + % store the collected cell-array if it was part of an unstructured list + if strcmp(blocktype, 'START_LIST') + val = val(1:(end-1)); % remove the last item, which is the end of the block + val = val(:); % make it a column array + s = setfield(s, blockname, val); + end + + % clear them to prevent confusion on the next loop + blockname = ''; + blocktype = ''; + +end % while ~feof + +fclose(fid); diff --git a/external/fieldtrip/fileio/private/read_edf.m b/external/fieldtrip/fileio/private/read_edf.m new file mode 100644 index 0000000..022bb61 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_edf.m @@ -0,0 +1,352 @@ +function [dat] = read_edf(filename, hdr, begsample, endsample, chanindx); + +% READ_EDF reads specified samples from an EDF continous datafile +% It neglects all trial boundaries as if the data was acquired in +% non-continous mode. +% +% Use as +% [hdr] = read_edf(filename); +% where +% filename name of the datafile, including the .bdf extension +% This returns a header structure with the following elements +% hdr.Fs sampling frequency +% hdr.nChans number of channels +% hdr.nSamples number of samples per trial +% hdr.nSamplesPre number of pre-trigger samples in each trial +% hdr.nTrials number of trials +% hdr.label cell-array with labels of each channel +% hdr.orig detailled EDF header information +% +% Or use as +% [dat] = read_edf(filename, hdr, begsample, endsample, chanindx); +% where +% filename name of the datafile, including the .bdf extension +% hdr header structure, see above +% begsample index of the first sample to read +% endsample index of the last sample to read +% chanindx index of channels to read (optional, default is all) +% This returns a Nchans X Nsamples data matrix + +% Copyright (C) 2006, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_edf.m 1232 2010-06-14 14:33:20Z roboos $ + +if nargin==1 + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % read the header, this code is from EEGLAB's openbdf + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + FILENAME = filename; + + % defines Seperator for Subdirectories + SLASH='/'; + BSLASH=char(92); + + cname=computer; + if cname(1:2)=='PC' SLASH=BSLASH; end; + + fid=fopen(FILENAME,'r','ieee-le'); + if fid<0 + fprintf(2,['Error LOADEDF: File ' FILENAME ' not found\n']); + return; + end; + + EDF.FILE.FID=fid; + EDF.FILE.OPEN = 1; + EDF.FileName = FILENAME; + + PPos=min([max(find(FILENAME=='.')) length(FILENAME)+1]); + SPos=max([0 find((FILENAME=='/') | (FILENAME==BSLASH))]); + EDF.FILE.Ext = FILENAME(PPos+1:length(FILENAME)); + EDF.FILE.Name = FILENAME(SPos+1:PPos-1); + if SPos==0 + EDF.FILE.Path = pwd; + else + EDF.FILE.Path = FILENAME(1:SPos-1); + end; + EDF.FileName = [EDF.FILE.Path SLASH EDF.FILE.Name '.' EDF.FILE.Ext]; + + H1=char(fread(EDF.FILE.FID,256,'char')'); % + EDF.VERSION=H1(1:8); % 8 Byte Versionsnummer + %if 0 fprintf(2,'LOADEDF: WARNING Version EDF Format %i',ver); end; + EDF.PID = deblank(H1(9:88)); % 80 Byte local patient identification + EDF.RID = deblank(H1(89:168)); % 80 Byte local recording identification + %EDF.H.StartDate = H1(169:176); % 8 Byte + %EDF.H.StartTime = H1(177:184); % 8 Byte + EDF.T0=[str2num(H1(168+[7 8])) str2num(H1(168+[4 5])) str2num(H1(168+[1 2])) str2num(H1(168+[9 10])) str2num(H1(168+[12 13])) str2num(H1(168+[15 16])) ]; + + % Y2K compatibility until year 2090 + if EDF.VERSION(1)=='0' + if EDF.T0(1) < 91 + EDF.T0(1)=2000+EDF.T0(1); + else + EDF.T0(1)=1900+EDF.T0(1); + end; + else ; + % in a future version, this is hopefully not needed + end; + + EDF.HeadLen = str2num(H1(185:192)); % 8 Byte Length of Header + % reserved = H1(193:236); % 44 Byte + EDF.NRec = str2num(H1(237:244)); % 8 Byte # of data records + EDF.Dur = str2num(H1(245:252)); % 8 Byte # duration of data record in sec + EDF.NS = str2num(H1(253:256)); % 8 Byte # of signals + + EDF.Label = char(fread(EDF.FILE.FID,[16,EDF.NS],'char')'); + EDF.Transducer = char(fread(EDF.FILE.FID,[80,EDF.NS],'char')'); + EDF.PhysDim = char(fread(EDF.FILE.FID,[8,EDF.NS],'char')'); + + EDF.PhysMin= str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); + EDF.PhysMax= str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); + EDF.DigMin = str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); + EDF.DigMax = str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); + + % check validity of DigMin and DigMax + if (length(EDF.DigMin) ~= EDF.NS) + fprintf(2,'Warning OPENEDF: Failing Digital Minimum\n'); + EDF.DigMin = -(2^15)*ones(EDF.NS,1); + end + if (length(EDF.DigMax) ~= EDF.NS) + fprintf(2,'Warning OPENEDF: Failing Digital Maximum\n'); + EDF.DigMax = (2^15-1)*ones(EDF.NS,1); + end + if (any(EDF.DigMin >= EDF.DigMax)) + fprintf(2,'Warning OPENEDF: Digital Minimum larger than Maximum\n'); + end + % check validity of PhysMin and PhysMax + if (length(EDF.PhysMin) ~= EDF.NS) + fprintf(2,'Warning OPENEDF: Failing Physical Minimum\n'); + EDF.PhysMin = EDF.DigMin; + end + if (length(EDF.PhysMax) ~= EDF.NS) + fprintf(2,'Warning OPENEDF: Failing Physical Maximum\n'); + EDF.PhysMax = EDF.DigMax; + end + if (any(EDF.PhysMin >= EDF.PhysMax)) + fprintf(2,'Warning OPENEDF: Physical Minimum larger than Maximum\n'); + EDF.PhysMin = EDF.DigMin; + EDF.PhysMax = EDF.DigMax; + end + EDF.PreFilt= char(fread(EDF.FILE.FID,[80,EDF.NS],'char')'); % + tmp = fread(EDF.FILE.FID,[8,EDF.NS],'char')'; % samples per data record + EDF.SPR = str2num(char(tmp)); % samples per data record + + fseek(EDF.FILE.FID,32*EDF.NS,0); + + EDF.Cal = (EDF.PhysMax-EDF.PhysMin)./(EDF.DigMax-EDF.DigMin); + EDF.Off = EDF.PhysMin - EDF.Cal .* EDF.DigMin; + tmp = find(EDF.Cal < 0); + EDF.Cal(tmp) = ones(size(tmp)); + EDF.Off(tmp) = zeros(size(tmp)); + + EDF.Calib=[EDF.Off';(diag(EDF.Cal))]; + %EDF.Calib=sparse(diag([1; EDF.Cal])); + %EDF.Calib(1,2:EDF.NS+1)=EDF.Off'; + + EDF.SampleRate = EDF.SPR / EDF.Dur; + + EDF.FILE.POS = ftell(EDF.FILE.FID); + if EDF.NRec == -1 % unknown record size, determine correct NRec + fseek(EDF.FILE.FID, 0, 'eof'); + endpos = ftell(EDF.FILE.FID); + EDF.NRec = floor((endpos - EDF.FILE.POS) / (sum(EDF.SPR) * 2)); + fseek(EDF.FILE.FID, EDF.FILE.POS, 'bof'); + H1(237:244)=sprintf('%-8i',EDF.NRec); % write number of records + end; + + EDF.Chan_Select=(EDF.SPR==max(EDF.SPR)); + for k=1:EDF.NS + if EDF.Chan_Select(k) + EDF.ChanTyp(k)='N'; + else + EDF.ChanTyp(k)=' '; + end; + if findstr(upper(EDF.Label(k,:)),'ECG') + EDF.ChanTyp(k)='C'; + elseif findstr(upper(EDF.Label(k,:)),'EKG') + EDF.ChanTyp(k)='C'; + elseif findstr(upper(EDF.Label(k,:)),'EEG') + EDF.ChanTyp(k)='E'; + elseif findstr(upper(EDF.Label(k,:)),'EOG') + EDF.ChanTyp(k)='O'; + elseif findstr(upper(EDF.Label(k,:)),'EMG') + EDF.ChanTyp(k)='M'; + end; + end; + + EDF.AS.spb = sum(EDF.SPR); % Samples per Block + bi=[0;cumsum(EDF.SPR)]; + + idx=[];idx2=[]; + for k=1:EDF.NS, + idx2=[idx2, (k-1)*max(EDF.SPR)+(1:EDF.SPR(k))]; + end; + maxspr=max(EDF.SPR); + idx3=zeros(EDF.NS*maxspr,1); + for k=1:EDF.NS, idx3(maxspr*(k-1)+(1:maxspr))=bi(k)+ceil((1:maxspr)'/maxspr*EDF.SPR(k));end; + + %EDF.AS.bi=bi; + EDF.AS.IDX2=idx2; + %EDF.AS.IDX3=idx3; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % convert the header to Fieldtrip-style + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + if all(EDF.SampleRate==EDF.SampleRate(1)) + hdr.Fs = EDF.SampleRate(1); + hdr.nChans = EDF.NS; + hdr.label = cellstr(EDF.Label); + % it is continuous data, therefore append all records in one trial + hdr.nSamples = EDF.Dur * EDF.SampleRate(1); + hdr.nSamplesPre = 0; + hdr.nTrials = EDF.NRec; + hdr.orig = EDF; + elseif all(EDF.SampleRate(1:end-1)==EDF.SampleRate(1)) + % only the last channel has a deviant sampling frequency + % this is the case for EGI recorded datasets that have been converted + % to EDF+, in which case the annotation channel is the last + chansel = find(EDF.SampleRate==EDF.SampleRate(1)); + % continue with the subset of channels that has a consistent sampling frequency + hdr.Fs = EDF.SampleRate(chansel(1)); + hdr.nChans = length(chansel); + warning('using a subset of %d channels with a consistent sampling frequency (%g Hz)', hdr.nChans, hdr.Fs); + hdr.label = cellstr(EDF.Label); + hdr.label = hdr.label(chansel); + % it is continuous data, therefore append all records in one trial + hdr.nSamples = EDF.Dur * EDF.SampleRate(chansel(1)); + hdr.nSamplesPre = 0; + hdr.nTrials = EDF.NRec; + hdr.orig = EDF; + % this will be used on subsequent reading of data + hdr.orig.chansel = chansel; + else + error('channels with different sampling rate not supported'); + end + + % return the header + dat = hdr; + +else + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % read the data + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % retrieve the original header + EDF = hdr.orig; + + % determine whether a subset of channels should be used + % which is the case if channels have a variable sampling frequency + variableFs = isfield(EDF, 'chansel'); + + if variableFs + epochlength = EDF.Dur * EDF.SampleRate(EDF.chansel(1)); % in samples for the selected channel + blocksize = sum(EDF.Dur * EDF.SampleRate); % in samples for all channels + chanoffset = EDF.Dur * EDF.SampleRate; + chanoffset = cumsum([0; chanoffset(1:end-1)]); + % use a subset of channels + nchans = length(EDF.chansel); + else + epochlength = EDF.Dur * EDF.SampleRate(1); % in samples for a single channel + blocksize = sum(EDF.Dur * EDF.SampleRate); % in samples for all channels + % use all channels + nchans = EDF.NS; + end + + % determine the trial containing the begin and end sample + begepoch = floor((begsample-1)/epochlength) + 1; + endepoch = floor((endsample-1)/epochlength) + 1; + nepochs = endepoch - begepoch + 1; + + if nargin<5 + chanindx = 1:nchans; + end + + % allocate memory to hold the data + dat = zeros(length(chanindx),nepochs*epochlength); + + % read and concatenate all required data epochs + for i=begepoch:endepoch + if variableFs + % only a subset of channels with consistent sampling frequency is read + offset = EDF.HeadLen + (i-1)*blocksize*2; % in bytes + % read the complete data block + buf = readLowLevel(filename, offset, blocksize); % see below in subfunction + for j=1:length(chanindx) + % cut out the part that corresponds with a single channel + dat(j,((i-begepoch)*epochlength+1):((i-begepoch+1)*epochlength)) = buf((1:epochlength) + chanoffset(EDF.chansel(chanindx(j)))); + end + + elseif length(chanindx)==1 + % this is more efficient if only one channel has to be read, e.g. the status channel + offset = EDF.HeadLen + (i-1)*blocksize*2; % in bytes + offset = offset + (chanindx-1)*epochlength*2; + % read the data for a single channel + buf = readLowLevel(filename, offset, epochlength); % see below in subfunction + dat(:,((i-begepoch)*epochlength+1):((i-begepoch+1)*epochlength)) = buf; + + else + % read the data from all channels, subsequently select the desired channels + offset = EDF.HeadLen + (i-1)*blocksize*2; % in bytes + % read the complete data block + buf = readLowLevel(filename, offset, blocksize); % see below in subfunction + buf = reshape(buf, epochlength, nchans); + dat(:,((i-begepoch)*epochlength+1):((i-begepoch+1)*epochlength)) = buf(:,chanindx)'; + end + end + + % select the desired samples + begsample = begsample - (begepoch-1)*epochlength; % correct for the number of bytes that were skipped + endsample = endsample - (begepoch-1)*epochlength; % correct for the number of bytes that were skipped + dat = dat(:, begsample:endsample); + + % Calibrate the data + if variableFs + % using a sparse matrix speeds up the multiplication + calib = sparse(diag(EDF.Cal(EDF.chansel(chanindx)))); + dat = full(calib * dat); + elseif length(chanindx)==1 + % in case of one channel the calibration would result in a sparse array + calib = EDF.Cal(chanindx); + dat = calib * dat; + else + % using a sparse matrix speeds up the multiplication + calib = sparse(diag(EDF.Cal(chanindx))); + dat = calib * dat; + end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION for reading the 16 bit values +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function buf = readLowLevel(filename, offset, numwords) +if offset < 2*1024^2 + % use the external mex file, only works for <2GB + buf = read_16bit(filename, offset, numwords); +else + % use plain matlab, thanks to Philip van der Broek + fp = fopen(filename,'r','ieee-le'); + status = fseek(fp, offset, 'bof'); + if status + error(['failed seeking ' filename]); + end + [buf,num] = fread(fp,numwords,'bit16=>double'); + fclose(fp); + if (num> dat = read_eeglabdata(filename); +% +% Inputs: +% filename - [string] file name +% +% Optional inputs: +% 'begtrial' - [integer] first trial to read +% 'endtrial' - [integer] last trial to read +% 'chanindx' - [integer] list with channel indices to read +% 'header' - FILEIO structure header +% +% Outputs: +% dat - data over the specified range +% +% Author: Arnaud Delorme, SCCN, INC, UCSD, 2008- + +%123456789012345678901234567890123456789012345678901234567890123456789012 + +% Copyright (C) 2008 Arnaud Delorme, SCCN, INC, UCSD, arno@salk.edu +% +% This program is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +function dat = read_eeglabdata(filename, varargin); + +if nargin < 1 + help read_eeglabdata; + return; +end; + +header = keyval('header', varargin); +begsample = keyval('begsample', varargin); +endsample = keyval('endsample', varargin); +begtrial = keyval('begtrial', varargin); +endtrial = keyval('endtrial', varargin); +chanindx = keyval('chanindx', varargin); + +if isempty(header) + header = read_eeglabheader(filename); +end; + +if ischar(header.orig.data) + if strcmpi(header.orig.data(end-2:end), 'set'), + header.ori = load('-mat', filename); + else + + % assuming that the data file is in the current directory + fid = fopen(header.orig.data); + + % assuming the .dat and .set files are located in the same directory + if fid == -1 + pathstr = fileparts(filename); + fid = fopen(fullfile(pathstr, header.orig.data)); + end + + if fid == -1 + fid = fopen(fullfile(header.orig.filepath, header.orig.data)); % + end + +if fid == -1, error(['Cannot not find data file: ' header.orig.data]); end; + + % only read the desired trials + if strcmpi(header.orig.data(end-2:end), 'dat') + dat = fread(fid,[header.nSamples*header.nTrials header.nChans],'float32')'; + else + dat = fread(fid,[header.nChans header.nSamples*header.nTrials],'float32'); + end; + dat = reshape(dat, header.nChans, header.nSamples, header.nTrials); + fclose(fid); + end; +else + dat = header.orig.data; + dat = reshape(dat, header.nChans, header.nSamples, header.nTrials); +end; + +if isempty(begtrial), begtrial = 1; end; +if isempty(endtrial), endtrial = header.nTrials; end; +if isempty(begsample), begsample = 1; end; +if isempty(endsample), endsample = header.nSamples; end; +dat = dat(:,begsample:endsample,begtrial:endtrial); + +if ~isempty(chanindx) + % select the desired channels + dat = dat(chanindx,:,:); +end diff --git a/external/fieldtrip/fileio/private/read_eeglabevent.m b/external/fieldtrip/fileio/private/read_eeglabevent.m new file mode 100644 index 0000000..0f62498 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_eeglabevent.m @@ -0,0 +1,97 @@ +% read_eeglabevent() - import EEGLAB dataset events +% +% Usage: +% >> event = read_eeglabevent(filename, ...); +% +% Inputs: +% filename - [string] file name +% +% Optional inputs: +% 'header' - FILEIO structure header +% +% Outputs: +% event - FILEIO toolbox event structure +% +% Author: Arnaud Delorme, SCCN, INC, UCSD, 2008- + +%123456789012345678901234567890123456789012345678901234567890123456789012 + +% Copyright (C) 2008 Arnaud Delorme, SCCN, INC, UCSD, arno@salk.edu +% +% This program is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +function event = read_eeglabevent(filename, varargin) + +if nargin < 1 + help read_eeglabheader; + return; +end; + +hdr = keyval('header', varargin); + +if isempty(hdr) + hdr = read_eeglabheader(filename); +end; + +event = []; % these will be the output in FieldTrip format +oldevent = hdr.orig.event; % these are in EEGLAB format + +for index = 1:length(oldevent) + + if isfield(oldevent,'code') + type = oldevent(index).code; + elseif isfield(oldevent,'value') + type = oldevent(index).value; + else + type = 'trigger'; + end; + + % events can have a numeric or a string value + value = oldevent(index).type; + + % this is the sample number of the concatenated data to which the event corresponds + sample = oldevent(index).latency; + + % a non-zero offset only applies to trial-events, i.e. in case the data is + % segmented and each data segment needs to be represented as event. In + % that case the offset corresponds to the baseline duration (times -1). + offset = 0; + + if isfield(oldevent, 'duration') + duration = oldevent(index).duration; + else + duration = 0; + end; + + % add the current event in fieldtrip format + event(index).type = type; % this is usually a string, e.g. 'trigger' or 'trial' + event(index).value = value; % in case of a trigger, this is the value + event(index).sample = sample; % this is the sample in the datafile at which the event happens + event(index).offset = offset; % some events should be represented with a shifted time-axix, e.g. a trial with a baseline period + event(index).duration = duration; % some events have a duration, such as a trial + +end; + +if hdr.nTrials>1 + % add the trials to the event structure + for i=1:hdr.nTrials + event(end+1).type = 'trial'; + event(end ).sample = (i-1)*hdr.nSamples + 1; + event(end ).value = []; + event(end ).offset = -hdr.nSamplesPre; + event(end ).duration = hdr.nSamples; + end +end + diff --git a/external/fieldtrip/fileio/private/read_eeglabheader.m b/external/fieldtrip/fileio/private/read_eeglabheader.m new file mode 100644 index 0000000..36de300 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_eeglabheader.m @@ -0,0 +1,81 @@ +% read_eeglabheader() - import EEGLAB dataset files +% +% Usage: +% >> header = read_eeglabheader(filename); +% +% Inputs: +% filename - [string] file name +% +% Outputs: +% header - FILEIO toolbox type structure +% +% Author: Arnaud Delorme, SCCN, INC, UCSD, 2008- + +%123456789012345678901234567890123456789012345678901234567890123456789012 + +% Copyright (C) 2008 Arnaud Delorme, SCCN, INC, UCSD, arno@salk.edu +% +% This program is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +function header = read_eeglabheader(filename) + +if nargin < 1 + help read_eeglabheader; + return; +end; + +if ~isstruct(filename) + load('-mat', filename); +else + EEG = filename; +end; + +header.Fs = EEG.srate; +header.nChans = EEG.nbchan; +header.nSamples = EEG.pnts; +header.nSamplesPre = -EEG.xmin*EEG.srate; +header.nTrials = EEG.trials; +try + header.label = { EEG.chanlocs.labels }'; +catch + warning('creating default channel names'); + for i=1:header.nChans + header.label{i} = sprintf('chan%03d', i); + end +end +ind = 1; +for i = 1:length( EEG.chanlocs ) + if isfield(EEG.chanlocs(i), 'X') && ~isempty(EEG.chanlocs(i).X) + header.elec.label{ind, 1} = EEG.chanlocs(i).labels; + % this channel has a position + header.elec.pnt(ind,1) = EEG.chanlocs(i).X; + header.elec.pnt(ind,2) = EEG.chanlocs(i).Y; + header.elec.pnt(ind,3) = EEG.chanlocs(i).Z; + ind = ind+1; + end; +end; + +% remove data +% ----------- +%if isfield(EEG, 'datfile') +% if ~isempty(EEG.datfile) +% EEG.data = EEG.datfile; +% end; +%else +% EEG.data = 'in set file'; +%end; +EEG.icaact = []; + +header.orig = EEG; diff --git a/external/fieldtrip/fileio/private/read_egis_data.m b/external/fieldtrip/fileio/private/read_egis_data.m new file mode 100644 index 0000000..2905425 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_egis_data.m @@ -0,0 +1,107 @@ +function dat = read_egis_data(filename, hdr, begtrial, endtrial, chanindx); + +% READ_EGIS_DATA reads the data from an EGI EGIS format file +% +% Use as +% dat = read_egis_data(filename, hdr, begtrial, endtrial, chanindx); +% where +% filename name of the input file +% hdr header structure, see READ_HEADER +% begtrial first trial to read, mutually exclusive with begsample+endsample +% endtrial last trial to read, mutually exclusive with begsample+endsample +% chanindx list with channel indices to read +% +% This function returns a 3-D matrix of size Nchans*Nsamples*Ntrials. +% Note that EGIS session files are defined as always being epoched. +% For session files the trials are organized with the members of each cell grouped +% together. For average files the "trials" (subjects) are organized with the cells +% also grouped together (e.g., "cell1sub1, cell1sub2, ...). +%_______________________________________________________________________ +% +% +% Modified from EGI's EGI Toolbox with permission 2007-06-28 Joseph Dien + +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_egis_data.m 945 2010-04-21 17:41:20Z roboos $ + +fh=fopen([filename],'r'); +if fh==-1 + error('wrong filename') +end +fclose(fh); + +[fhdr,chdr,ename,cnames,fcom,ftext] = read_egis_header(filename); +fh=fopen([filename],'r'); +fhdr(1)=fread(fh,1,'int32'); %BytOrd +[str,maxsize,cEndian]=computer; +if fhdr(1)==16909060 + if cEndian == 'B' + endian = 'ieee-be'; + elseif cEndian == 'L' + endian = 'ieee-le'; + end; +elseif fhdr(1)==67305985 + if cEndian == 'B' + endian = 'ieee-le'; + elseif cEndian == 'L' + endian = 'ieee-be'; + end; +else + error('This is not an EGIS average file.'); +end; + +if fhdr(2) == -1 + fileType = 'ave'; +elseif fhdr(2) == 3 + fileType = 'ses'; +else + error('This is not an EGIS file.'); +end; + +dat=zeros(hdr.nChans,hdr.nSamples,endtrial-begtrial+1); + +%read to end of file header +status=fseek(fh,(130+(2*fhdr(18))+(4*fhdr(19))),'bof'); +status=fseek(fh,2,'cof'); +for loop=1:fhdr(18) + temp=fread(fh,80,'char'); + theName=strtok(temp); + theName=strtok(theName,char(0)); + cnames{loop}=deblank(char(theName))'; + status=fseek(fh,fhdr(24+(loop-1))-80,'cof'); +end +fcom=fread(fh,fhdr(20),'char'); +ftext=fread(fh,fhdr(21),'char'); +fpad=fread(fh,fhdr(22),'char'); +status=fseek(fh,-2,'cof'); + +%read to start of desired data +fseek(fh, ((begtrial-1)*hdr.nChans*hdr.nSamples*2), 'cof'); + +for segment=1:(endtrial-begtrial+1) + dat(:,:,segment) = fread(fh, [hdr.nChans, hdr.nSamples],'int16',endian); +end +dat=dat(chanindx, :,:); + +if fileType == 'ave' + dat=dat/fhdr(12); %convert to microvolts +elseif fileType == 'ses' + dat=dat/5; %convert to microvolts (EGIS sess files created by NetStation use a 5 bins per microvolt scaling) +end; + +fclose(fh); diff --git a/external/fieldtrip/fileio/private/read_egis_header.m b/external/fieldtrip/fileio/private/read_egis_header.m new file mode 100644 index 0000000..af7336b --- /dev/null +++ b/external/fieldtrip/fileio/private/read_egis_header.m @@ -0,0 +1,122 @@ +function [fhdr,chdr,ename,cnames,fcom,ftext] = read_egis_header(filename) + +% READ_EGIS_HEADER reads the header information from an EGI EGIS format file +% +% Use as +% [fhdr chdr] = read_egia_header(filename) +% with +% fhdr - the file header information +% chdr - the cell header information +% ename - experiment name +% cnames - cell names +% fcom - comments +% ftext - general text +% and +% filename - the name of the data file +%_______________________________________________________________________ +% +% +% Modified from EGI's EGI Toolbox with permission 2007-06-28 Joseph Dien + +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_egis_header.m 945 2010-04-21 17:41:20Z roboos $ + +fh=fopen([filename],'r'); +if fh==-1 + error('wrong filename') +end + +%Prep file for reading +fhdr=zeros(1,23); +status=fseek(fh,0,'bof'); + +%Read in fhdr fields. +fhdr(1)=fread(fh,1,'int32'); %BytOrd +[str,maxsize,cEndian]=computer; +if fhdr(1)==16909060 + if cEndian == 'B' + endian = 'ieee-be'; + elseif cEndian == 'L' + endian = 'ieee-le'; + end; +elseif fhdr(1)==67305985 + if cEndian == 'B' + endian = 'ieee-le'; + elseif cEndian == 'L' + endian = 'ieee-be'; + end; +else + error('This is not an EGIS average file.'); +end; + +fhdr(2)=fread(fh,1,'int16',endian); %HdrVer + +if (fhdr(2) ~= -1) && (fhdr(2) ~= 3) + error('This is not an EGIS average file.'); +end; + +fhdr(3)=fread(fh,1,'uint16',endian); %LHeader +fhdr(4)=fread(fh,1,'uint32',endian); %LData +status=fseek(fh,80,'cof'); %Skip ExptNam +fhdr(5:10)=fread(fh,6,'int16',endian); %RunDate and RunTime + +fhdr(11:23)=fread(fh,13,'int16',endian); %Everything else up to LCellHdr + +fhdr(24:(24+fhdr(18)-1))=fread(fh,fhdr(18),'uint16',endian); %LCellHdr for each cell + +%Read in chdr +chdr=zeros(fhdr(18),5); +status=fseek(fh,(4*fhdr(19)),'cof'); +for loop=1:fhdr(18) + chdr(loop,1)=fread(fh,1,'int16',endian); + status=fseek(fh,80,'cof'); + chdr(loop, 2:5)=(fread(fh,4,'int16',endian))'; + lspectot=(chdr(loop,2)*(chdr(loop,5)/2)); + lastcol=(6+lspectot-1); + if lastcol >= 6 + chdr(loop,lastcol)=0; + chdr(loop,6:lastcol)=(fread(fh,lspectot,'int16',endian))'; + end +end + +%Read experiment name +status=fseek(fh,12,'bof'); +tempstr=fread(fh,80,'char'); +ename=char(tempstr); + +%Read cellnames +status=fseek(fh,(130+(2*fhdr(18))+(4*fhdr(19))),'bof'); +status=fseek(fh,2,'cof'); +for loop=1:fhdr(18) + temp=fread(fh,80,'char'); + theName=strtok(temp,0); + cnames{loop}=deblank(char(theName))'; + status=fseek(fh,fhdr(24+(loop-1))-80,'cof'); +end + +%Read comment +%status=fseek(fh,fhdr(3),'bof'); +%status=fseek(fh,-(fhdr(22)+fhdr(21)+fhdr(20)),'cof'); +fcom=fread(fh,fhdr(20),'char'); + +%Read text +%status=fseek(fh,fhdr(3),'bof'); +%status=fseek(fh,-(fhdr(22)+fhdr(21)),'cof'); +ftext=fread(fh,fhdr(21),'char'); + +fclose(fh); diff --git a/external/fieldtrip/fileio/private/read_elec.m b/external/fieldtrip/fileio/private/read_elec.m new file mode 100644 index 0000000..4e31f8f --- /dev/null +++ b/external/fieldtrip/fileio/private/read_elec.m @@ -0,0 +1,53 @@ +function [el, lab] = read_elec(fn); + +% READ_ELEC reads "la/mu" electrode parameters from a MBF electrode file +% which are used to position them on a triangulated surface +% +% [el, lab] = read_elec(filename) +% +% where el = [dhk, la, mu] +% and lab contains the electrode labels (if present) +% +% See also READ_TRI, TRANSFER_ELEC + +% Copyright (C) 1998, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_elec.m 945 2010-04-21 17:41:20Z roboos $ + +fid = fopen(fn, 'rt'); +if fid~=-1 + + % read the number of electrodes + Nel = sscanf(fgetl(fid), '%d'); + + % read the electrode triangle, lambda and mu + for i=1:Nel + str = fgetl(fid); + el(i,:) = sscanf(str, '%f %f %f')'; + indx = find(str=='!'); + if (indx) + lab(i,:) = sprintf('%6s', str((indx+1):length(str))); + end + end + fclose(fid); + +else + error('unable to open file'); +end + diff --git a/external/fieldtrip/fileio/private/read_eyelink_asc.m b/external/fieldtrip/fileio/private/read_eyelink_asc.m new file mode 100644 index 0000000..e4dd8e7 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_eyelink_asc.m @@ -0,0 +1,108 @@ +function asc = read_eyelink_asc(filename) + +% READ_EYELINK_ASC reads the header information, input triggers, messages +% and all data points from an Eyelink *.asc file +% +% Use as +% asc = read_eyelink_asc(filename) + +% Copyright (C) 2010, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_eyelink_asc.m 945 2010-04-21 17:41:20Z roboos $ + +fid = fopen(filename, 'rt'); + +asc.header = {}; +asc.msg = {}; +asc.input = []; +asc.sfix = {}; +asc.efix = {}; +asc.ssacc = {}; +asc.esacc = {}; +asc.dat = []; +current = 0; + +while ~feof(fid) + tline = fgetl(fid); + + if regexp(tline, '^[0-9]'); + tmp = sscanf(tline, '%f'); + nchan = numel(tmp); + current = current + 1; + + if size(asc.dat,1). +% +% $Id: read_fcdc_trl.m 945 2010-04-21 17:41:20Z roboos $ + +fid = fopen(fn, 'rt'); +if fid<0 + error('could not open file'); +end + +trl = []; +while ~feof(fid) + tmp = fscanf(fid, '%f %f %f', 3); + if ~isempty(tmp) + trl = [trl; tmp']; + end +end + +fclose(fid); + diff --git a/external/fieldtrip/fileio/private/read_itab_mhd.m b/external/fieldtrip/fileio/private/read_itab_mhd.m new file mode 100644 index 0000000..2201389 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_itab_mhd.m @@ -0,0 +1,265 @@ +function mhd = read_itab_mhd(filename) + +fid = fopen(filename, 'rb'); + +% Name of structure +mhd.stname = fread(fid, [1 10], 'uint8=>char'); % Header identifier (VP_BIOMAG) +mhd.stver = fread(fid, [1 8], 'uint8=>char'); % Header version +mhd.stendian = fread(fid, [1 4], 'uint8=>char'); % LE (little endian) or BE (big endian) format + +% Subject's INFOs +mhd.first_name = fread(fid, [1 32], 'uint8=>char'); % Subject's first name +mhd.last_name = fread(fid, [1 32], 'uint8=>char'); % Subject's family name +mhd.id = fread(fid, [1 32], 'uint8=>char'); % Subject's id +mhd.notes = fread(fid, [1 256], 'uint8=>char'); % Notes on measurement + +% Other subj infos +mhd.subj_info.sex = fread(fid, [1 1], 'uint8=>char'); % Sex (M or F) +pad = fread(fid, [1 5], 'uint8'); +mhd.subj_info.notes = fread(fid, [1 256], 'uint8=>char'); % Notes on subject +mhd.subj_info.height = fread(fid, [1 1], 'float'); % Height in cm +mhd.subj_info.weight = fread(fid, [1 1], 'float'); % Weight in kg +mhd.subj_info.birthday = fread(fid, [1 1], 'int32'); % Birtday (1-31) +mhd.subj_info.birthmonth = fread(fid, [1 1], 'int32'); % Birthmonth (1-12) +mhd.subj_info.birthyear = fread(fid, [1 1], 'int32'); % Birthyear (1900-2002) + +% Data acquisition INFOs +mhd.time = fread(fid, [1 12], 'uint8=>char'); % time (ascii) +mhd.date = fread(fid, [1 16], 'uint8=>char'); % date (ascii) + +mhd.nchan = fread(fid, [1 1], 'int32'); % total number of channels +mhd.nelech = fread(fid, [1 1], 'int32'); % number of electric channels +mhd.nelerefch = fread(fid, [1 1], 'int32'); % number of electric reference channels +mhd.nmagch = fread(fid, [1 1], 'int32'); % number of magnetic channels +mhd.nmagrefch = fread(fid, [1 1], 'int32'); % number of magnetic reference channels +mhd.nauxch = fread(fid, [1 1], 'int32'); % number of auxiliary channels +mhd.nparamch = fread(fid, [1 1], 'int32'); % number of parameter channels +mhd.ndigitch = fread(fid, [1 1], 'int32'); % number of digit channels +mhd.nflagch = fread(fid, [1 1], 'int32'); % number of flag channels + +mhd.data_type = fread(fid, [1 1], 'int32'); % 0 - BE_SHORT (HP-PA, big endian) +% 1 - BE_LONG (HP-PA, big endian) +% 2 - BE_FLOAT (HP-PA, big endian) +% 3 - LE_SHORT (Intel, little endian) +% 4 - LE_LONG (Intel, little endian) +% 5 - LE_FLOAT (Intel, little endian) +% 6 - RTE_A_SHORT (HP-A900, big endian) +% 7 - RTE_A_FLOAT (HP-A900, big endian) +% 8 - ASCII + +mhd.smpfq = fread(fid, [1 1], 'single'); % sampling frequency in Hz +mhd.hw_low_fr = fread(fid, [1 1], 'single'); % hw data acquisition low pass filter +mhd.hw_hig_fr = fread(fid, [1 1], 'single'); % hw data acquisition high pass filter +mhd.hw_comb = fread(fid, [1 1], 'int32'); % hw data acquisition 50 Hz filter (1-TRUE) +mhd.sw_hig_tc = fread(fid, [1 1], 'single'); % sw data acquisition high pass time constant +mhd.compensation= fread(fid, [1 1], 'int32'); % 0 - no compensation 1 - compensation +mhd.ntpdata = fread(fid, [1 1], 'int32'); % total number of time points in data + +mhd.no_segments = fread(fid, [1 1], 'int32'); % Number of segments described in the segment structure + +% INFOs on different segments +for i=1:5 + mhd.sgmt(i).start = fread(fid, [1 1], 'int32'); % Starting time point from beginning of data + mhd.sgmt(i).ntptot = fread(fid, [1 1], 'int32'); % Total number of time points + mhd.sgmt(i).type = fread(fid, [1 1], 'int32'); + mhd.sgmt(i).no_samples = fread(fid, [1 1], 'int32'); + mhd.sgmt(i).st_sample = fread(fid, [1 1], 'int32'); +end + +mhd.nsmpl = fread(fid, [1 1], 'int32'); % Overall number of samples + +% INFOs on different samples +for i=1:4096 + mhd.smpl(i).start = fread(fid, [1 1], 'int32'); % Starting time point from beginning of data + mhd.smpl(i).ntptot = fread(fid, [1 1], 'int32'); % Total number of time points + mhd.smpl(i).ntppre = fread(fid, [1 1], 'int32'); % Number of points in pretrigger + mhd.smpl(i).type = fread(fid, [1 1], 'int32'); + mhd.smpl(i).quality = fread(fid, [1 1], 'int32'); +end + + +mhd.nrefchan = fread(fid, [1 1], 'int32'); % number of reference channels +mhd.ref_ch = fread(fid, [1 640], 'int32'); % reference channel list +mhd.ntpref = fread(fid, [1 1], 'int32'); % total number of time points in reference + +% Header INFOs +mhd.raw_header_type = fread(fid, [1 1], 'int32'); % 0 - Unknown header +% 2 - rawfile (A900) +% 3 - GE runfile header +% 31 - ATB runfile header version 1.0 +% 41 - IFN runfile header version 1.0 +% 51 - BMDSys runfile header version 1.0 + +mhd.header_type = fread(fid, [1 1], 'int32'); % 0 - Unknown header +% 2 - rawfile (A900) +% 3 - GE runfile header +% 4 - old header +% 10 - 256ch normal header +% 11 - 256ch master header +% 20 - 640ch normal header +% 21 - 640ch master header +% 31 - ATB runfile header version 1.0 +% 41 - IFN runfile header version 1.0 +% 51 - BMDSys runfile header version 1.0 + +mhd.conf_file = fread(fid, [1 64], 'uint8=>char'); % Filename used for data acquisition configuration + +mhd.header_size = fread(fid, [1 1], 'int32'); % sizeof(header) at the time of file creation +mhd.start_reference = fread(fid, [1 1], 'int32'); % start reference +mhd.start_data = fread(fid, [1 1], 'int32'); % start data + +mhd.rawfile = fread(fid, [1 1], 'int32'); % 0 - not a rawfile 1 - rawfile +mhd.multiplexed_data = fread(fid, [1 1], 'int32'); % 0 - FALSE 1 - TRUE + +mhd.isns = fread(fid, [1 1], 'int32'); % sensor code 1 - Single channel +% 28 - Original Rome 28 ch. +% 29 - .............. +% .. - .............. +% 45 - Updated Rome 28 ch. (spring 2009) +% .. - .............. +% .. - .............. +% 55 - Original Chieti 55 ch. flat +% 153 - Original Chieti 153 ch. helmet +% 154 - Chieti 153 ch. helmet from Jan 2002 + +% Channel's INFOs +for i=1:640 + mhd.ch(i).type = fread(fid, [1 1], 'uint8'); + pad = fread(fid, [1 3], 'uint8'); + % type 0 - unknown + % 1 - ele + % 2 - mag + % 4 - ele ref + % 8 - mag ref + % 16 - aux + % 32 - param + % 64 - digit + % 128 - flag + mhd.ch(i).number = fread(fid, [1 1], 'int32'); % number + mhd.ch(i).label = fixstr(fread(fid, [1 16], 'uint8=>char')); % label + mhd.ch(i).flag = fread(fid, [1 1], 'uint8'); + pad = fread(fid, [1 3], 'uint8'); + % on/off flag 0 - working channel + % 1 - noisy channel + % 2 - very noisy channel + % 3 - broken channel + mhd.ch(i).amvbit = fread(fid, [1 1], 'float'); % calibration from LSB to mV + mhd.ch(i).calib = fread(fid, [1 1], 'float'); % calibration from mV to unit + mhd.ch(i).unit = fread(fid, [1 6], 'uint8=>char'); % unit label (fT, uV, ...) + pad = fread(fid, [1 2], 'uint8'); + mhd.ch(i).ncoils = fread(fid, [1 1], 'int32'); % number of coils building up one channel + mhd.ch(i).wgt = fread(fid, [1 10], 'float'); % weight of coils + % position and orientation of coils + for j=1:10 + mhd.ch(i).position(j).r_s = fread(fid, [1 3], 'float'); + mhd.ch(i).position(j).u_s = fread(fid, [1 3], 'float'); + end +end + + +% Sensor position INFOs + +mhd.r_center = fread(fid, [1 3], 'float'); % sensor position in convenient format +mhd.u_center = fread(fid, [1 3], 'float'); +mhd.th_center = fread(fid, [1 1], 'float'); % sensor orientation as from markers fit +mhd.fi_center= fread(fid, [1 1], 'float'); +mhd.rotation_angle= fread(fid, [1 1], 'float'); +mhd.cosdir = fread(fid, [3 3], 'float'); % for compatibility only +mhd.irefsys = fread(fid, [1 1], 'int32'); % reference system 0 - sensor reference system +% 1 - Polhemus +% 2 - head3 +% 3 - MEG + +% Marker positions for MRI integration +mhd.num_markers = fread(fid, [1 1], 'int32'); % Total number of markers +mhd.i_coil = fread(fid, [1 64], 'int32'); % Markers to be used to find sensor position +mhd.marker = fread(fid, [3 64], 'int32'); % Position of all the markers +mhd.best_chi = fread(fid, [1 1], 'float'); % Best chi_square value obtained in finding sensor position + +mhd.cup_vertex_center = fread(fid, [1 1], 'float'); % dist anc sensor cente vertex (as entered +% from keyboard) +mhd.cup_fi_center = fread(fid, [1 1], 'float'); % fi angle of sensor center +mhd.cup_rotation_angle = fread(fid, [1 1], 'float'); % rotation angle of sensor center axis + +mhd.dist_a1_a2 = fread(fid, [1 1], 'float'); % head informations +% (used to find subject's head dimensions) +mhd.dist_inion_nasion = fread(fid, [1 1], 'float'); +mhd.max_circ = fread(fid, [1 1], 'float'); +mhd.nasion_vertex_inion = fread(fid, [1 1], 'float'); + +% Data analysis INFOs +mhd.security = fread(fid, [1 1], 'int32'); % security flag +mhd.ave_alignement = fread(fid, [1 1], 'int32'); % average data alignement 0 - FALSE +% 1 - TRUE + +mhd.itri = fread(fid, [1 1], 'int32'); % trigger channel number +mhd.ntpch = fread(fid, [1 1], 'int32'); % no. of time points per channel +mhd.ntppre = fread(fid, [1 1], 'int32'); % no. of time points of pretrigger +mhd.navrg = fread(fid, [1 1], 'int32'); % no. of averages +mhd.nover = fread(fid, [1 1], 'int32'); % no. of discarded averages +mhd.nave_filt = fread(fid, [1 1], 'int32'); % no. of applied filters + +% Filters used before average +for i=1:15 + mhd.ave_filt(i).type = fread(fid, [1 1], 'int32'); % type 0 - no filter + % 1 - bandpass - param[0]: highpass freq + % - param[1]: lowpass freq + % 2 - notch - param[0]: notch freq 1 + % param[1]: notch freq 2 + % param[2]: notch freq 3 + % param[3]: notch freq 4 + % param[4]: span + % 3 - artifact - param[0]: True/False + % 4 - adaptive - param[0]: True/False + % 5 - rectifier - param[0]: True/False + % 6 - heart - param[0]: True/False + % 7 - evoked - param[0]: True/False + % 8 - derivate - param[0]: True/False + % 9 - polarity - param[0]: True/False + mhd.ave_filt(i).param = fread(fid, [1 5], 'float'); % up to 5 filter parameters +end + +mhd.stdev = fread(fid, [1 1], 'int32'); % 0 - not present +mhd.bas_start = fread(fid, [1 1], 'int32'); % starting data points for baseline +mhd.bas_end = fread(fid, [1 1], 'int32'); % ending data points for baseline + +mhd.source_files = fread(fid, [1 32], 'int32'); % Progressive number of files (if more than one) + +% template INFOs +mhd.ichtpl = fread(fid, [1 1], 'int32'); +mhd.ntptpl = fread(fid, [1 1], 'int32'); +mhd.ifitpl = fread(fid, [1 1], 'int32'); +mhd.corlim = fread(fid, [1 1], 'float'); + +% Filters used before template +for i=1:15 + mhd.tpl_filt(i).type = fread(fid, [1 1], 'int32'); % type 0 - no filter + % 1 - bandpass - param[0]: highpass freq + % - param[1]: lowpass freq + % 2 - notch - param[0]: notch freq 1 + % param[1]: notch freq 2 + % param[2]: notch freq 3 + % param[3]: notch freq 4 + % param[4]: span + % 3 - artifact - param[0]: True/False + % 4 - adaptive - param[0]: True/False + % 5 - rectifier - param[0]: True/False + % 6 - heart - param[0]: True/False + % 7 - evoked - param[0]: True/False + % 8 - derivate - param[0]: True/False + % 9 - polarity - param[0]: True/False + mhd.tpl_filt(i).param = fread(fid, [1 5], 'float'); % up to 5 filter parameters +end + +% Just in case info +mhd.dummy = fread(fid, [1 64], 'int32'); +% there seems to be more dummy data at the end... + +fclose(fid); + +function str = fixstr(str) +sel = find(str==0, 1, 'first'); +if ~isempty(sel) + str = str(1:sel-1); +end + diff --git a/external/fieldtrip/fileio/private/read_labview_dtlg.m b/external/fieldtrip/fileio/private/read_labview_dtlg.m new file mode 100644 index 0000000..dd2d5de --- /dev/null +++ b/external/fieldtrip/fileio/private/read_labview_dtlg.m @@ -0,0 +1,154 @@ +function [dat] = read_labview_dtlg(filename, datatype); + +% READ_LABVIEW_DTLG +% +% Use as +% dat = read_labview_dtlg(filename, datatype) +% where datatype can be 'int32' or 'int16' +% +% The output of this function is a structure. + +% Copyright (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_labview_dtlg.m 945 2010-04-21 17:41:20Z roboos $ + + +fid = fopen(filename, 'r', 'ieee-be'); + +header = fread(fid, 4, 'uint8=>char')'; +if ~strcmp(header, 'DTLG') + error('unsupported file, header should start with DTLG'); +end + +version = fread(fid, 4, 'char')'; % clear version +nd = fread(fid, 1, 'int32'); +p = fread(fid, 1, 'int32'); + +% the following seems to work for files with version [7 0 128 0] +% but in files files with version [8 0 128 0] the length of the descriptor is not correct +ld = fread(fid, 1, 'int16'); +descriptor = fread(fid, ld, 'uint8=>char')'; + +% ROBOOS: the descriptor should ideally be decoded, since it contains the variable +% name, type and size + +% The first offset block always starts immediately after the data descriptor (at offset p, which should ideally be equal to 16+ld) +if nd<=128 + % The first offset block contains the offsets for all data sets. + % In this case P points to the start of the offset block. + fseek(fid, p, 'bof'); + offset = fread(fid, 128, 'uint32')'; +else + % The first offset block contains the offsets for the first 128 data sets. + % The entries for the remaining data sets are stored in additional offset blocks. + % The locations of those blocks are contained in a block table starting at P. + offset = []; + fseek(fid, p, 'bof'); + additional = fread(fid, 128, 'uint32'); + for i=1:sum(additional>0) + fseek(fid, additional(i), 'bof'); + tmp = fread(fid, 128, 'uint32')'; + offset = cat(2, offset, tmp); + end + clear additional i tmp +end + +% ROBOOS: remove the zeros in the offset array for non-existing datasets +offset = offset(1:nd); + +% ROBOOS: how to determine the data datatype? +switch datatype + case 'uint32' + datasize = 4; + case 'int32' + datasize = 4; + case 'uint16' + datasize = 2; + case 'int16' + datasize = 2; + otherwise + error('unsupported datatype'); +end + +% If the data sets are n-dimensional arrays, the first n u32 longwords in each data +% set contain the array dimensions, imediately followed by the data values. + +% ROBOOS: how to determine whether they are n-dimensional arrays? + +% determine the number of dimensions by looking at the first array +% assume that all subsequent arrays have the same number of dimensions +if nd>1 + estimate = (offset(2)-offset(1)); % initial estimate for the number of datasize in the array + fseek(fid, offset(1), 'bof'); + n = fread(fid, 1, 'int32'); + while mod(estimate-4*length(n), (datasize*prod(n)))~=0 + % determine the number and size of additional array dimensions + n = cat(1, n, fread(fid, 1, 'int32')); + if datasize*prod(n)>estimate + error('could not determine array size'); + end + end + ndim = length(n); + clear estimate n +else + estimate = filesize(fid)-offset; + fseek(fid, offset(1), 'bof'); + n = fread(fid, 1, 'int32'); + while mod(estimate-4*length(n), (datasize*prod(n)))~=0 + % determine the number and size of additional array dimensions + n = cat(1, n, fread(fid, 1, 'int32')); + if datasize*prod(n)>estimate + error('could not determine array size'); + end + end + ndim = length(n); + clear estimate n +end + +% read the dimensions and the data from each array +for i=1:nd + fseek(fid, offset(i), 'bof'); + n = fread(fid, ndim, 'int32')'; + % Labview uses the C-convention for storing data, and Matlab uses the Fortran convention + n = fliplr(n); + data{i} = fread(fid, n, datatype); +end +clear i n ndim + +fclose(fid); + +% put all local variables into a structure, this is a bit unusual programming style +% the output structure is messy, but contains all relevant information +tmp = whos; +dat = []; +for i=1:length(tmp) + if isempty(strmatch(tmp(i).name, {'tmp', 'fid', 'ans', 'handles'})) + dat = setfield(dat, tmp(i).name, eval(tmp(i).name)); + end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% local helper function to determine the size of the file +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function siz = filesize(fid) +fp = ftell(fid); +fseek(fid, 0, 'eof'); +siz = ftell(fid); +fseek(fid, fp, 'bof'); + diff --git a/external/fieldtrip/fileio/private/read_lay.m b/external/fieldtrip/fileio/private/read_lay.m new file mode 100644 index 0000000..0f26cfd --- /dev/null +++ b/external/fieldtrip/fileio/private/read_lay.m @@ -0,0 +1,34 @@ +function [X,Y,Width,Height,Lbl] = read_lay(layoutname); + +% READ_LAY reads an electrode or gradiometer layout file +% Layout files are used for topoplotting and multiplotting. +% +% Use as +% [X, Y, Width, Height, Lbl] = read_lay(layoutname) + +% Copyright (C) 2003, Ole Jensen +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_lay.m 945 2010-04-21 17:41:20Z roboos $ + +if ~exist(layoutname, 'file') + error(sprintf('could not open layout file: %s', layoutname)); +end + +% discard the channel number +[chNum,X,Y,Width,Height,Lbl] = textread(layoutname,'%f %f %f %f %f %q'); diff --git a/external/fieldtrip/fileio/private/read_mat.m b/external/fieldtrip/fileio/private/read_mat.m new file mode 100644 index 0000000..5c08ea1 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_mat.m @@ -0,0 +1,77 @@ +function [matrix, extra] = read_mat(fn); + +% READ_MAT reads a matrix from an ascii or binary MBF format file +% +% Usage: m = loadmat('file'); +% or [m,extra] = loadmat('file'); +% +% LOADMAT('file') returns the matrix stored in 'file' and +% the extra information stored at the bottom of that file. +% LOADMAT works for binary as well as asci matrix files. +% +% See also WRITE_MAT + +% Copyright (C) 1998, Thom Oostendorp +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_mat.m 945 2010-04-21 17:41:20Z roboos $ + +f=fopen(fn); +if (f==-1) + fprintf('\nCannot open %s\n\n', fn); + result=0; + extra=''; + return; +end + +[N,nr]=fscanf(f,'%d',2); +if (nr~=2) + fclose(f); + f=fopen(fn); + [magic ,nr]=fread(f,8,'char'); + if (char(magic')==';;mbfmat') + fread(f,1,'char'); + hs=fread(f,1,'long'); + fread(f,1,'char'); + fread(f,1,'char'); + fread(f,1,'char'); + N=fread(f,2,'long'); + M=fread(f,[N(2),N(1)],'double'); + else + fclose(f); + f=fopen(fn); + N=fread(f,2,'long'); + M=fread(f,[N(2),N(1)],'float'); + end +else + M=fscanf(f,'%f',[N(2) N(1)]); +end + +[extra,nextra]=fread(f,1000,'char'); +fclose(f); +S=sprintf('\n%s contains %d rows and %d columns\n', fn, N(1), N(2)); +disp(S); +if (nextra~=0) + S=sprintf('%s contains the following extra information:\n', fn); + disp(S); + disp(char(extra')); +end + +matrix=M'; +extra=char(extra'); + diff --git a/external/fileio/private/read_micromed_trc.m b/external/fieldtrip/fileio/private/read_micromed_trc.m similarity index 100% rename from external/fileio/private/read_micromed_trc.m rename to external/fieldtrip/fileio/private/read_micromed_trc.m diff --git a/external/fieldtrip/private/read_mpi_dap.m b/external/fieldtrip/fileio/private/read_mpi_dap.m similarity index 88% rename from external/fieldtrip/private/read_mpi_dap.m rename to external/fieldtrip/fileio/private/read_mpi_dap.m index be91f95..e618c7a 100644 --- a/external/fieldtrip/private/read_mpi_dap.m +++ b/external/fieldtrip/fileio/private/read_mpi_dap.m @@ -8,21 +8,23 @@ % Copyright (C) 2005-2007, Robert Oostenveld % -% $Log: read_mpi_dap.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.3 2007/03/19 16:53:09 roboos -% renamed local variable from dat into dap +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.2 2005/10/06 11:01:24 roboos -% added support for average mode -% only read analogsweep+hdr+data if nanalog>0 -% only read spikesweep+hdr+data if nspike>0 +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.1 2005/10/04 16:53:21 roboos -% new implementation +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: read_mpi_dap.m 945 2010-04-21 17:41:20Z roboos $ fid = fopen(filename, 'rb', 'ieee-le'); diff --git a/external/fieldtrip/fileio/private/read_mpi_ds.m b/external/fieldtrip/fileio/private/read_mpi_ds.m new file mode 100644 index 0000000..c9bc3a6 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_mpi_ds.m @@ -0,0 +1,99 @@ +function [hdr, dat] = read_mpi_ds(dirname) + +% READ_MPI_DS reads all DAP files from a directory containing files or +% alternatively a single DAP file and returns it in a simplified FieldTrip +% format. The analog channels and spike channels are both returned in a +% continuous format. +% +% Use as +% [hdr, dat] = read_mpi_ds(dirname) +% or +% [hdr, dat] = read_mpi_ds(filename) +% +% See also READ_MPI_DAP + +% Copyright (C) 2005-2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_mpi_ds.m 945 2010-04-21 17:41:20Z roboos $ + +hdr = []; +dat = []; + +if isdir(dirname) + ls = dir(dirname); + dapfile = {}; + for i=1:length(ls) + if ~isempty(regexp(ls(i).name, '.dap$')) + dapfile{end+1} = fullfile(dirname, ls(i).name); + end + end + dapfile = sort(dapfile); +elseif iscell(dirname) + dapfile = dirname; +else + dapfile = {dirname}; +end + +for i=1:length(dapfile) + dap = read_mpi_dap(dapfile{i}); + siz = size(dap.analoghdr); + nanalog = dap.filehdr.nanalog; + nspike = dap.filehdr.nspike; + nexp(i) = siz(1); + nsweep(i) = siz(2); + nsample(i) = length(dap.analog{1}); + analog = zeros(nanalog, nsample(i)*nsweep(i)*nexp(i)); + spike = zeros(nspike , nsample(i)*nsweep(i)*nexp(i)); + % only collect the data when required + if nargout>1 + % collect all analog data of all sweeps in a single matrix + for e=1:nexp(i) + for s=1:nsweep(i) + for c=1:nanalog + begsample = (e*s-1) * nsample(i) + 1; + endsample = (e*s ) * nsample(i); + analog(c,begsample:endsample) = dap.analog{e,s,c}(:)'; + end + end + end + % collect all spike data of all sweeps in a single matrix + for e=1:nexp(i) + for s=1:nsweep(i) + for c=1:nspike + spike(c,dap.spike{e,s,c} + (e*s-1) * nsample(i)) = spike(c,dap.spike{e,s,c} + (e*s-1) * nsample(i)) + 1; + end + end + end + dat = cat(1, analog, spike); + end % if nargout +end + +hdr.Fs = 1000; % sampling frequency +hdr.nChans = nanalog+nspike; % number of channels +hdr.nSamples = nsample(1); % number of samples per trial +hdr.nSamplesPre = 0; % number of pre-trigger samples in each trial +hdr.nTrials = sum(nsweep.*nexp); % number of trials +hdr.label = {}; % cell-array with labels of each channel +for i=1:nanalog + hdr.label{i} = sprintf('analog%02d', i); +end +for i=1:nspike + hdr.label{nanalog+i} = sprintf('spike%02d', i); +end + diff --git a/external/fileio/private/read_neuralynx_bin.m b/external/fieldtrip/fileio/private/read_neuralynx_bin.m similarity index 77% rename from external/fileio/private/read_neuralynx_bin.m rename to external/fieldtrip/fileio/private/read_neuralynx_bin.m index f329568..0dfbab6 100644 --- a/external/fileio/private/read_neuralynx_bin.m +++ b/external/fieldtrip/fileio/private/read_neuralynx_bin.m @@ -27,41 +27,23 @@ % Copyright (C) 2007-2008, Robert Oostenveld % -% $Log: read_neuralynx_bin.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.5 2008/09/30 08:01:04 roboos -% replaced all fread(char=>char) into uint8=>char to ensure that the -% chars are read as 8 bits and not as extended 16 bit characters. The -% 16 bit handling causes problems on some internationalized OS/Matlab -% combinations. +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% the help of fread specifies "If the precision is 'char' or 'char*1', MATLAB -% reads characters using the encoding scheme associated with the file. -% See FOPEN for more information". +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.4 2008/07/01 13:00:58 roboos -% optionally read the 16384 byte ascii header instead of hard-coded defaults -% -% Revision 1.3 2008/05/27 13:04:58 roboos -% switched to the 3rd version of the file format, which includes the downscale/calibration value to recover from int32->int16 compression -% added explicit support for version 1, 2 and 3 of the fileformat -% added original details to the output header -% -% Revision 1.2 2007/12/17 16:23:44 roboos -% fixed bug in jumping to correct begin sample -% added support for determining channel name from filename like this "dataset.chanlabel.bin" -% added support for old splitted dma files, which have an 8 byte header with the channel label and are always int32 -% -% Revision 1.1 2007/12/12 16:28:42 roboos -% first implementation +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: read_neuralynx_bin.m 945 2010-04-21 17:41:20Z roboos $ needhdr = (nargin==1); needdat = (nargin>=2); diff --git a/external/fieldtrip/fileio/private/read_neuralynx_cds.m b/external/fieldtrip/fileio/private/read_neuralynx_cds.m new file mode 100644 index 0000000..3e3e440 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_neuralynx_cds.m @@ -0,0 +1,163 @@ +function [dat] = read_neuralynx_cds(filename, hdr, begsample, endsample, chanindx); + +% READ_NEURALYNX_CDS reads selected samples and channels from a combined Neuralynx dataset with seperate subdirectories for the LFP, MUA and spike channels +% +% Use as +% hdr = read_neuralynx_cds(parentdir) +% dat = read_neuralynx_cds(parentdir, hdr, begsample, endsample, chanindx) + +% Copyright (C) 2006, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_neuralynx_cds.m 945 2010-04-21 17:41:20Z roboos $ + +needhdr = (nargin==1); +needdat = (nargin>=2); + +dirlist = dir(filename); +haslfp = any(filetype_check_extension({dirlist.name}, 'lfp')); +hasmua = any(filetype_check_extension({dirlist.name}, 'mua')); +hasspike = any(filetype_check_extension({dirlist.name}, 'spike')); +%hasttl = any(filetype_check_extension({dirlist.name}, 'ttl')); % seperate file with original Parallel_in +%hastsl = any(filetype_check_extension({dirlist.name}, 'tsl')); % seperate file with original TimeStampLow +%hastsh = any(filetype_check_extension({dirlist.name}, 'tsh')); % seperate file with original TimeStampHi + +if needhdr + % read the header from the LFP dataset + if haslfp + lfpdir = fullfile(filename, dirlist(find(filetype_check_extension({dirlist.name}, 'lfp'))).name); + lfphdr = read_header(lfpdir); + lfpfil = lfphdr.filename; + for i=1:lfphdr.nChans + lfplab{i} = sprintf('lfp_%s', lfphdr.label{i}); + end + else + lfphdr = []; + lfpfil = {}; + lfplab = {}; + end + + % read the header from the MUA dataset + if hasmua + muadir = fullfile(filename, dirlist(find(filetype_check_extension({dirlist.name}, 'mua'))).name); + muahdr = read_header(muadir); + muafil = muahdr.filename; + for i=1:muahdr.nChans + mualab{i} = sprintf('mua_%s', muahdr.label{i}); + end + else + muahdr = []; + muafil = {}; + mualab = {}; + end + + % read the header from the SPIKE dataset + if hasspike + spikedir = fullfile(filename, dirlist(find(filetype_check_extension({dirlist.name}, 'spike'))).name); + spikehdr = read_header(spikedir); + spikefil = spikehdr.filename; + for i=1:spikehdr.nChans + spikelab{i} = sprintf('spike_%s', spikehdr.label{i}); + end + else + spikehdr = []; + spikefil = {}; + spikelab = {}; + end + + if haslfp + % assume that the LFP header describes the MUA and the spikes as well + hdr = lfphdr; + else hasmua + % assume that the MUA header describes the spikes as well + hdr = muahdr; + end + + % concatenate the lfp/mua/spike channels, they have already been renamed + hdr.label = cat(1, lfplab(:), mualab(:), spikelab(:)); + hdr.filename = cat(1, lfpfil(:), muafil(:), spikefil(:)); + hdr.nChans = length(hdr.label); + % remember the original header details + hdr.orig = {}; + hdr.orig{1} = lfphdr; + hdr.orig{2} = muahdr; + hdr.orig{3} = spikehdr; + + % return the header + dat = hdr; +else + + % use the original header details + lfphdr = hdr.orig{1}; + muahdr = hdr.orig{2}; + spikehdr = hdr.orig{3}; + % the spike header does not contain these, but requires them from the LFP or MUA + spikehdr.FirstTimeStamp = hdr.FirstTimeStamp; + spikehdr.TimeStampPerSample = hdr.TimeStampPerSample; + + if ~isempty(lfphdr) + Nlfp = lfphdr.nChans; + else + Nlfp = 0; + end + + if ~isempty(muahdr) + Nmua = muahdr.nChans; + else + Nmua = 0; + end + + if ~isempty(spikehdr) + Nspike = spikehdr.nChans; + else + Nspike = 0; + end + + % determine which files should be read from each respective dataset + selchan = zeros(hdr.nChans,1); + selchan(chanindx) = 1; + sellfp = find(selchan(1:Nlfp)); + selmua = find(selchan((Nlfp+1):(Nlfp+Nmua))); + selspike = find(selchan((Nlfp+Nmua+1):(Nlfp+Nmua+Nspike))); + + if haslfp + % the header contains the relevant file names + lfpdat = read_neuralynx_ds([], lfphdr, begsample, endsample, sellfp); + else + lfpdat = []; + end + + if hasmua + % the header contains the relevant file names + muadat = read_neuralynx_ds([], muahdr, begsample, endsample, selmua); + else + muadat = []; + end + + if hasspike + % the header contains the relevant file names + spikedat = read_neuralynx_ds([], spikehdr, begsample, endsample, selspike); + else + spikedat = []; + end + + % combine all data into a single array + dat = cat(1, lfpdat, muadat, spikedat); + +end + diff --git a/external/fieldtrip/fileio/private/read_neuralynx_dma.m b/external/fieldtrip/fileio/private/read_neuralynx_dma.m new file mode 100644 index 0000000..14df813 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_neuralynx_dma.m @@ -0,0 +1,280 @@ +function [dat] = read_neuralynx_dma(filename, begsample, endsample, channel); + +% READ_NEURALYNX_DMA reads specified samples and channels data from a Neuralynx DMA log file +% +% Use as +% [hdr] = read_neuralynx_dma(filename) +% [dat] = read_neuralynx_dma(filename, begsample, endsample) +% [dat] = read_neuralynx_dma(filename, begsample, endsample, chanindx) +% +% The channel specification can be a vector with indices, or a single string with the value +% 'all', 'stx', 'pid', 'siz', 'tsh', 'tsl', +% 'cpu', 'ttl', 'x01', ..., 'x10' +% +% This function returns the electrophysiological data in AD units +% and not in uV. You should look up the details of the headstage and +% the Neuralynx amplifier and scale the values accordingly. + +% Copyright (C) 2005-2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_neuralynx_dma.m 945 2010-04-21 17:41:20Z roboos $ + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% The data is simply a stream of constant size records, the size of the +% record is dependant on the number of Input Boards in the system. 8 in your +% case, there are 32 - 32 bit integers from each Input Board. +% +% // Digital Lynx Packets look like this for a 1 board system: +% // stx (or SOP) 0x00000800 +% // Packet ID 0x00000001 +% // siz 0x0000002A (# A/D data ints + #extra wds = 32+10) +% // TimeStamp Hi 1 32 bit word +% // TimeStamp Low 1 32 bit word +% // cpu 1 32 bit word +% // ttl 1 32 bit word +% // 10 extras 10 32 bit words +% // A/D data 32 32 bit words per board +% // CRC 1 32 bit XOR of the entire packet including stx +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +needhdr = (nargin==1); +needdat = (nargin>=2); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% since Cheetah 4.80 the DMS log files have a 16384 byte header +% determine whether that is the case in this file +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +fid = fopen(filename, 'rb', 'ieee-le'); +buf = fread(fid, 10, 'uchar=>uchar'); +if all(buf(1:4)==35) + % the file starts with "####" + hdroffset = 16384; +elseif all(buf>31 & buf<127) + % the file does not start with "####" but the header seems to be ascii anyway + hdroffset = 16384; +else + hdroffset = 0; +end + +if hdroffset + % read the ascii header from the file, it does not contain much usefull information + orig = neuralynx_getheader(filename); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% since Cheetah 5.0 the DMA log file does not always start with a complete +% packet but can start with an incomplete "junk" packet after the header. +% The junk due to that incomplete packet should then also be skipped. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +if hdroffset + % skip the standard ascii header + fseek(fid, hdroffset, 'bof'); + % read a single block + buf = fread(fid, 274, 'uint32=>uint32'); + % search for the first known values of a proper packet + junk = find((buf(1:(end-1))==2048) & (buf(2:(end-0))==1), 1) - 1; + if ~isempty(junk) + % add the additional junk samples to the header offset + hdroffset = hdroffset + junk*4; + end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% since modifying our hardware from 256 to 32 channel (19 March 2007), the +% number of channels in a DMA log file can vary. Start with the assumption +% that the file is from the 256 channel system with 8 boards that we have +% in Nijmegen and verify the CRC +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +nboards = 8; +nchanboard = 32; +blocksize = nboards*nchanboard+18; % in 4 byte words +fseek(fid, hdroffset, 'bof'); +% read a single block +buf = fread(fid, blocksize, 'uint32=>uint32'); +% determine the number of boards by systematically checking the CRC value +while (nboards>0) + if neuralynx_crc(buf(1:blocksize-1))==buf(blocksize) + % the CRC is correct for this number of boards + break + else + nboards = nboards - 1; % decrease by one + blocksize = nboards*nchanboard+18; % in 4 byte words + end +end +fclose(fid); + +if ~nboards + error('could not determine the number of boards and channels'); +end + +% deal with ascii and numeric input for the channel selection +if nargin>3 && ~ischar(channel) + chanindx = channel; + channel = 'selection'; +elseif nargin>3 && ischar(channel) + switch channel + case 'stx' + chanindx = 1; + case 'pid' + chanindx = 2; + case 'siz' + chanindx = 3; + case 'tsh' + chanindx = 4; + case 'tsl' + chanindx = 5; + case 'cpu' + chanindx = 6; + case 'ttl' + chanindx = 7; + case 'x01' + chanindx = 8; + case 'x02' + chanindx = 9; + case 'x03' + chanindx = 10; + case 'x04' + chanindx = 11; + case 'x05' + chanindx = 12; + case 'x06' + chanindx = 13; + case 'x07' + chanindx = 14; + case 'x08' + chanindx = 15; + case 'x09' + chanindx = 16; + case 'x10' + chanindx = 17; + case 'crc' + chanindx = blocksize; + case 'all' + chanindx = 1:blocksize; + otherwise + error('unknown value in channel'); + end +elseif nargin<4 + channel = 'all'; + chanindx = 1:blocksize; +end + +if needhdr + % these have to be hardcoded, since the DMA logfile does not contain header information + hdr = []; + if hdroffset + % remember the ascii header from the file, it does not contain much usefull information + hdr.orig = orig; + end + hdr.Fs = 32556; % sampling frequency + hdr.nChans = nboards*nchanboard; % number of analog channels + hdr.nSamples = inf; % number of samples per trial + hdr.nSamplesPre = 0; % number of pre-trigger samples in each trial + hdr.nTrials = 1; % number of trials + hdr.label = {}; % cell-array with labels of each channel + for i=1:hdr.nChans + chanlabel{i} = sprintf('csc%03d', i); + end + statuslabel = { + 'stx' + 'pid' + 'siz' + 'tsh' + 'tsl' + 'cpu' + 'ttl' + 'x01' + 'x02' + 'x03' + 'x04' + 'x05' + 'x06' + 'x07' + 'x08' + 'x09' + 'x10' + }; + hdr.label = cat(1, statuslabel(:), chanlabel(:), {'crc'}); % concatenate all channel labels + hdr.nChans = length(hdr.label); % this includes all channels + % determine the length of the file, expressed in samples + fid = fopen(filename, 'rb', 'ieee-le'); + fseek(fid, 0, 'eof'); + hdr.nSamples = floor((ftell(fid)-hdroffset)/(blocksize*4)); + + % determine the timestamp of the first and of the last sample + datoffset = 0*blocksize; + fseek(fid, hdroffset + datoffset, 'bof'); + buf = fread(fid, blocksize, 'uint32=>uint32'); + beg_stx = buf(1); + beg_tsh = buf(4); + beg_tsl = buf(5); + datoffset = (hdr.nSamples-1)*blocksize*4; + fseek(fid, hdroffset + datoffset, 'bof'); + buf = fread(fid, blocksize, 'uint32=>uint32'); + end_stx = buf(1); + end_tsh = buf(4); + end_tsl = buf(5); + fclose(fid); + % check that the junk at the beginning was correctly detected + if (beg_stx~=2048) + error('problem with STX at the begin of the file'); + end + % check that the file is truely continuous, i.e. no gaps with junk in between + if (end_stx~=2048) + error('problem with STX at the end of the file'); + end + % combine the two uint32 words into a uint64 + hdr.FirstTimeStamp = timestamp_neuralynx(beg_tsl, beg_tsh); + hdr.LastTimeStamp = timestamp_neuralynx(end_tsl, end_tsh); + hdr.TimeStampPerSample = double(hdr.LastTimeStamp-hdr.FirstTimeStamp)./(hdr.nSamples-1); % this should be double, since it can be fractional + + % only return the header information + dat = hdr; + dat.orig.Offset = hdroffset; + +elseif length(chanindx)>1 + % read the desired samples for all channels + fid = fopen(filename, 'rb', 'ieee-le'); + datoffset = (begsample-1)*blocksize*4; + fseek(fid, hdroffset + datoffset, 'bof'); % skip the header and samples that do not have to be read + % read the data + dat = fread(fid, [blocksize (endsample-begsample+1)], 'int32=>int32'); + fclose(fid); + if size(dat,2)<(endsample-begsample+1) + error('could not read all samples'); + end + if ~strcmp(channel, 'all') + % select the subset of desired channels + dat = dat(chanindx,:); + end + +elseif length(chanindx)==1 + % read the desired samples for only one channel + fid = fopen(filename, 'rb', 'ieee-le'); + datoffset = (begsample-1)*blocksize*4; + fseek(fid, hdroffset + datoffset, 'bof'); % skip the header and samples that do not have to be read + fseek(fid, (chanindx-1)*4, 'cof'); % skip to the channel of interest + % Note that the last block with 274*4 bytes can sometimes be incomplete, which is relevant when endsample=inf + dat = fread(fid, [1 (endsample-begsample+1)], 'int32=>int32', (nboards*32+18-1)*4); + if size(dat,2)<(endsample-begsample+1) + error('could not read all samples'); + end + fclose(fid); +end + diff --git a/external/fileio/private/read_neuralynx_ds.m b/external/fieldtrip/fileio/private/read_neuralynx_ds.m similarity index 79% rename from external/fileio/private/read_neuralynx_ds.m rename to external/fieldtrip/fileio/private/read_neuralynx_ds.m index 0c1c606..ba84a59 100644 --- a/external/fileio/private/read_neuralynx_ds.m +++ b/external/fieldtrip/fileio/private/read_neuralynx_ds.m @@ -25,45 +25,23 @@ % Copyright (C) 2006-2007, Robert Oostenveld % -% $Log: read_neuralynx_ds.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.9 2008/07/01 13:36:17 roboos -% SubSamplingInterleave is not always present +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.8 2008/01/24 19:54:40 roboos -% fixed bug in begrecord, thanks to Thilo +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.7 2008/01/10 12:53:11 roboos -% small change in reading of the header of teh subfiles, use SubSamplingInterleave for downsampled fsample, implemented wortkaround for Matlab bug in comparing uint64 values -% -% Revision 1.6 2007/12/20 17:59:05 roboos -% fixed bug in determining begin record for ncs -% -% Revision 1.5 2007/12/19 09:27:39 roboos -% more explicit handling of the three different filetypes -% give error if FirstTimestamp is not the same for ncs files -% -% Revision 1.4 2007/12/12 16:46:04 roboos -% do not read records from files, get first and last timestamp from file headers -% -% Revision 1.3 2007/03/21 17:06:57 roboos -% updated the documentation -% -% Revision 1.2 2006/12/13 15:49:33 roboos -% many changes, cleaned up code, removed subfunctions, explicitely implement teh computation fo timestamp stuff using a mix of double and uint64 precision (using overloaded mex functions in @uint64 toolbox) -% -% Revision 1.1 2006/03/29 14:39:20 roboos -% New implementation, replaces the previous seperate read_neuralynx_header -% and read_neuralynx_data. Instead of reimplementing the reading code, this -% function calls the specialized subfunctions. +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: read_neuralynx_ds.m 988 2010-04-28 12:18:00Z roevdmei $ needhdr = (nargin==1); needdat = (nargin>=2); @@ -79,11 +57,11 @@ ftype = zeros(length(fname), 1); for i=1:length(fname) - if filetype(fname{i}, 'neuralynx_ncs') + if ft_filetype(fname{i}, 'neuralynx_ncs') ftype(i) = 1; - elseif filetype(fname{i}, 'neuralynx_nse') + elseif ft_filetype(fname{i}, 'neuralynx_nse') ftype(i) = 2; - elseif filetype(fname{i}, 'neuralynx_nts') + elseif ft_filetype(fname{i}, 'neuralynx_nts') ftype(i) = 3; end end @@ -216,7 +194,7 @@ for i=1:nchan thischan = chanindx(i); thisfile = hdr.filename{thischan}; - switch filetype(thisfile) + switch ft_filetype(thisfile) case 'neuralynx_ncs' % determine the records that contain the sample numbers of the requested segment begrecord = ceil(begsample/512); @@ -244,7 +222,7 @@ sample = sample(sample>=begsample & sample<=endsample) - begsample + 1; dat(i,sample) = dat(i,sample) + 1; - end % switch filetype + end % switch ft_filetype end % for nchan end % reading data diff --git a/external/fieldtrip/fileio/private/read_neuralynx_ncs.m b/external/fieldtrip/fileio/private/read_neuralynx_ncs.m new file mode 100644 index 0000000..d9bb0b9 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_neuralynx_ncs.m @@ -0,0 +1,106 @@ +function [ncs] = read_neuralynx_ncs(filename, begrecord, endrecord) + +% READ_NEURALYNX_NCS reads a single continuous channel file +% +% Use as +% [ncs] = read_neuralynx_ncs(filename) +% [ncs] = read_neuralynx_ncs(filename, begrecord, endrecord) + +% Copyright (C) 2005-2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_neuralynx_ncs.m 945 2010-04-21 17:41:20Z roboos $ + +if nargin<2 + begrecord = 1; +end +if nargin<3 + endrecord = inf; +end + +% the file starts with a 16*1024 bytes header in ascii, followed by a number of records +hdr = neuralynx_getheader(filename); +fid = fopen(filename, 'rb', 'ieee-le'); + +% determine the length of the file +fseek(fid, 0, 'eof'); +headersize = 16384; +recordsize = 1044; +NRecords = floor((ftell(fid) - headersize)/recordsize); + +if NRecords>0 + if (ispc), fclose(fid); end + % read the timestamp from the first and last record + hdr.FirstTimeStamp = neuralynx_timestamp(filename, 1); + hdr.LastTimeStamp = neuralynx_timestamp(filename, inf); + if (ispc), fid = fopen(filename, 'rb', 'ieee-le'); end +else + hdr.FirstTimeStamp = nan; + hdr.LastTimeStamp = nan; +end + +if begrecord==0 && endrecord==0 + % only read the header +elseif begrecord<1 + error('cannot read before the first record'); +elseif begrecord>NRecords + error('cannot read beyond the last record') +elseif endrecord>NRecords + endrecord = NRecords; +end + +if begrecord>=1 && endrecord>=begrecord + % rewind to the first record to be read + status = fseek(fid, headersize + (begrecord-1)*recordsize, 'bof'); + if status~=0 + error('cannot jump to the requested record'); + end + + numrecord = (endrecord-begrecord+1); + TimeStamp = zeros(1,numrecord,'uint64'); + ChanNumber = zeros(1,numrecord); + SampFreq = zeros(1,numrecord); + NumValidSamp = zeros(1,numrecord); + Samp = zeros(512,numrecord); % this allows easy reshaping into a 1xNsamples vector + + for k=1:numrecord + % read a single continuous data record + TimeStamp(k) = fread(fid, 1, 'uint64=>uint64'); + ChanNumber(k) = fread(fid, 1, 'int32'); + SampFreq(k) = fread(fid, 1, 'int32'); + NumValidSamp(k) = fread(fid, 1, 'int32'); + Samp(:,k) = fread(fid, 512, 'int16'); + % mark the invalid samples + Samp((NumValidSamp+1):end,k) = nan; + end + + % store the record data in the output structure + ncs.TimeStamp = TimeStamp; + ncs.ChanNumber = ChanNumber; + ncs.SampFreq = SampFreq; + ncs.NumValidSamp = NumValidSamp; + % apply the scaling factor from ADBitVolts and convert to uV + ncs.dat = Samp * hdr.ADBitVolts * 1e6; + +end +fclose(fid); + +% store the header info in the output structure +ncs.NRecords = NRecords; +ncs.hdr = hdr; + diff --git a/external/fileio/private/read_neuralynx_nev.m b/external/fieldtrip/fileio/private/read_neuralynx_nev.m similarity index 83% rename from external/fileio/private/read_neuralynx_nev.m rename to external/fieldtrip/fileio/private/read_neuralynx_nev.m index 761928d..e22848b 100644 --- a/external/fileio/private/read_neuralynx_nev.m +++ b/external/fieldtrip/fileio/private/read_neuralynx_nev.m @@ -19,44 +19,23 @@ % Copyright (C) 2005, Robert Oostenveld % -% $Log: read_neuralynx_nev.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.6 2008/04/29 07:52:31 roboos -% fixed windows related bug -% be consistent with begin and end timestamp in header +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.5 2008/03/04 11:17:48 roboos -% read ttl value as uint16 instead of int16 +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.4 2007/12/20 19:05:31 roboos -% implemented filtering of events based on number (minnumber and maxnumber), this speeds up the reading since the events are each exactly 184 bytes large -% -% Revision 1.3 2007/12/18 16:41:16 roboos -% reimplemented the reading, now by buffering all data in memory and using typecasting and byte swapping (largely implemented in the cstructdecode function) -% implemented filtering on timestamp and value -% -% Revision 1.2 2007/12/12 16:30:10 roboos -% keep timestamps as uint64, fixed problem with case of filename (nev/Nev) -% -% Revision 1.1 2006/12/13 15:43:49 roboos -% renamed read_neuralynx_event into xxx_nev, consistent with the file extension -% -% Revision 1.3 2005/09/05 13:08:52 roboos -% implemented a faster way of reading all events, needed in the case of many triggers (e.g. each refresh) -% -% Revision 1.2 2005/06/24 06:57:32 roboos -% added PktStart to the record header reading, this shifts all fields by two bytes (thanks to Thilo) -% -% Revision 1.1 2005/05/19 07:09:58 roboos -% new implementation +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: read_neuralynx_nev.m 945 2010-04-21 17:41:20Z roboos $ % get the optional input arguments flt_value = keyval('value', varargin); diff --git a/external/fieldtrip/fileio/private/read_neuralynx_nse.m b/external/fieldtrip/fileio/private/read_neuralynx_nse.m new file mode 100644 index 0000000..8a4d013 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_neuralynx_nse.m @@ -0,0 +1,99 @@ +function [nse] = read_neuralynx_nse(filename, begrecord, endrecord) + +% READ_NEURALYNX_NSE reads a single electrode waveform file +% +% Use as +% [nse] = read_neuralynx_nse(filename) +% [nse] = read_neuralynx_nse(filename, begrecord, endrecord) + +% Copyright (C) 2005-2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_neuralynx_nse.m 945 2010-04-21 17:41:20Z roboos $ + +if nargin<2 + begrecord = 1; +end +if nargin<3 + endrecord = inf; +end + +% the file starts with a 16*1024 bytes header in ascii, followed by a number of records +hdr = neuralynx_getheader(filename); +fid = fopen(filename, 'rb', 'ieee-le'); + +% determine the length of the file +fseek(fid, 0, 'eof'); +headersize = 16384; +recordsize = 112; +NRecords = floor((ftell(fid) - headersize)/recordsize); + +if NRecords>0 + if (ispc), fclose(fid); end + % read the timestamp from the first and last record + hdr.FirstTimeStamp = neuralynx_timestamp(filename, 1); + hdr.LastTimeStamp = neuralynx_timestamp(filename, inf); + if (ispc), fid = fopen(filename, 'rb', 'ieee-le'); end +else + hdr.FirstTimeStamp = nan; + hdr.LastTimeStamp = nan; +end + +if begrecord==0 && endrecord==0 + % only read the header +elseif begrecord<1 + error('cannot read before the first record'); +elseif begrecord>NRecords + error('cannot read beyond the last record') +elseif endrecord>NRecords + endrecord = NRecords; +end + +if begrecord>=1 && endrecord>=begrecord + % rewind to the first record to be read + fseek(fid, headersize + (begrecord-1)*recordsize, 'bof'); + + numrecord = (endrecord-begrecord+1); + TimeStamp = zeros(1,numrecord,'uint64'); + ScNumber = zeros(1,numrecord); + CellNumber = zeros(1,numrecord); + Param = zeros(8,numrecord); + Samp = zeros(32,numrecord); + + k = 1; + while (begrecord+k-1)<=endrecord + % read a single electrode record + TimeStamp(k) = fread(fid, 1, 'uint64=>uint64'); + ScNumber(k) = fread(fid, 1, 'int32'); + CellNumber(k) = fread(fid, 1, 'int32'); + Param(:,k) = fread(fid, 8, 'int32'); + Samp(:,k) = fread(fid, 32, 'int16'); + k = k + 1; + end + + nse.TimeStamp = TimeStamp; + nse.ScNumber = ScNumber; + nse.CellNumber = CellNumber; + nse.Param = Param; + % apply the scaling factor from ADBitVolts and convert to uV + nse.dat = Samp * hdr.ADBitVolts * 1e6; +end +fclose(fid); + +nse.NRecords = NRecords; +nse.hdr = hdr; diff --git a/external/fieldtrip/fileio/private/read_neuralynx_nst.m b/external/fieldtrip/fileio/private/read_neuralynx_nst.m new file mode 100644 index 0000000..84a0974 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_neuralynx_nst.m @@ -0,0 +1,117 @@ +function [nst] = read_neuralynx_nst(filename, begrecord, endrecord) + +% READ_NEURALYNX_NST reads a single stereotrode file +% +% Use as +% [nst] = read_neuralynx_nst(filename) +% [nst] = read_neuralynx_nst(filename, begrecord, endrecord) + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_neuralynx_nst.m 945 2010-04-21 17:41:20Z roboos $ + +if nargin<2 + begrecord = 1; +end +if nargin<3 + endrecord = inf; +end + +% The file starts with a 16*1024 bytes header in ascii, followed by a +% number of records (c.f. trials). + +% The format of a tetrode record is +% int64 TimeStamp +% int32 ScNumber +% int32 CellNumber +% int32 Param[0] ƒ ƒ int32 Param[7] +% int16 ChanW[0] +% int16 ChanX[0] +% int16 ChanY[0] +% int16 ChanZ[0] ƒ ƒ +% int16 ChanW[31] +% int16 ChanX[31] +% int16 ChanY[31] +% int16 ChanZ[31] + +hdr = neuralynx_getheader(filename); +fid = fopen(filename, 'rb', 'ieee-le'); + +% determine the length of the file +fseek(fid, 0, 'eof'); +headersize = 16384; +recordsize = 304; +NRecords = floor((ftell(fid) - headersize)/recordsize); + +if begrecord==0 && endrecord==0 + % only read the header +elseif begrecord<1 + error('cannot read before the first record'); +elseif begrecord>NRecords + error('cannot read beyond the last record') +elseif endrecord>NRecords + endrecord = NRecords; +end + +if NRecords>0 + if (ispc), fclose(fid); end + % read the timestamp from the first and last record + hdr.FirstTimeStamp = neuralynx_timestamp(filename, 1); + hdr.LastTimeStamp = neuralynx_timestamp(filename, inf); + if (ispc), fid = fopen(filename, 'rb', 'ieee-le'); end +else + hdr.FirstTimeStamp = nan; + hdr.LastTimeStamp = nan; +end + +if begrecord>=1 && endrecord>=begrecord + % rewind to the first record to be read + status = fseek(fid, headersize + (begrecord-1)*recordsize, 'bof'); + if status~=0 + error('cannot jump to the requested record'); + end + + numrecord = (endrecord-begrecord+1); + TimeStamp = zeros(1,numrecord,'uint64'); + ScNumber = zeros(1,numrecord); + CellNumber = zeros(1,numrecord); + Param = zeros(8,numrecord); + Samp = zeros(2,32,numrecord); + + for k=1:numrecord + TimeStamp(k) = fread(fid, 1, 'uint64=>uint64'); + ScNumber(k) = fread(fid, 1, 'int32'); + CellNumber(k) = fread(fid, 1, 'int32'); + Param(:,k) = fread(fid, 8, 'int32'); + Samp(:,:,k) = fread(fid, [2 32], 'int16'); % chan W, X + end + + nst.TimeStamp = TimeStamp; + nst.ScNumber = ScNumber; + nst.CellNumber = CellNumber; + nst.Param = Param; + % FIXME apply the scaling factor from ADBitVolts and convert to uV + % nst.dat = Samp * 1e6 * hdr.ADBitVolts; + nst.dat = Samp; +end +fclose(fid); + +% store the header info in the output structure +nst.NRecords = NRecords; +nst.hdr = hdr; diff --git a/external/fieldtrip/fileio/private/read_neuralynx_nts.m b/external/fieldtrip/fileio/private/read_neuralynx_nts.m new file mode 100644 index 0000000..9d3b5bb --- /dev/null +++ b/external/fieldtrip/fileio/private/read_neuralynx_nts.m @@ -0,0 +1,78 @@ +function [nts] = read_neuralynx_nts(filename, begrecord, endrecord); + +% READ_NEURALYNX_NTS reads spike timestamps +% +% Use as +% [nts] = read_neuralynx_nts(filename) +% [nts] = read_neuralynx_nts(filename, begrecord, endrecord) + +% Copyright (C) 2006-2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_neuralynx_nts.m 945 2010-04-21 17:41:20Z roboos $ + +if nargin<2 + begrecord = 1; +end +if nargin<3 + endrecord = inf; +end + +% the file starts with a 16*1024 bytes header in ascii, followed by a number of records +hdr = neuralynx_getheader(filename); +fid = fopen(filename, 'rb', 'ieee-le'); + +% determine the length of the file +fseek(fid, 0, 'eof'); +headersize = 16384; +recordsize = 8; +NRecords = floor((ftell(fid) - headersize)/recordsize); + +if begrecord==0 && endrecord==0 + % only read the header +elseif begrecord<1 + error('cannot read before the first record'); +elseif begrecord>NRecords + error('cannot read beyond the last record') +elseif endrecord>NRecords + endrecord = NRecords; +end + +if NRecords>0 + if (ispc), fclose(fid); end + % read the timestamp from the first and last record + hdr.FirstTimeStamp = neuralynx_timestamp(filename, 1); + hdr.LastTimeStamp = neuralynx_timestamp(filename, inf); + if (ispc), fid = fopen(filename, 'rb', 'ieee-le'); end +else + hdr.FirstTimeStamp = nan; + hdr.LastTimeStamp = nan; +end + +if begrecord>=1 && endrecord>=begrecord + % rewind to the first record to be read + fseek(fid, headersize + (begrecord-1)*recordsize, 'bof'); + numrecord = (endrecord-begrecord+1); + TimeStamp = fread(fid, numrecord, 'uint64=>uint64'); + + nts.TimeStamp = TimeStamp; +end +fclose(fid); + +nts.NRecords = NRecords; +nts.hdr = hdr; diff --git a/external/fieldtrip/fileio/private/read_neuralynx_ntt.m b/external/fieldtrip/fileio/private/read_neuralynx_ntt.m new file mode 100644 index 0000000..7447656 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_neuralynx_ntt.m @@ -0,0 +1,117 @@ +function [ntt] = read_neuralynx_ntt(filename, begrecord, endrecord) + +% READ_NEURALYNX_NTT reads a single tetrode file +% +% Use as +% [ntt] = read_neuralynx_ntt(filename) +% [ntt] = read_neuralynx_ntt(filename, begrecord, endrecord) + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_neuralynx_ntt.m 945 2010-04-21 17:41:20Z roboos $ + +if nargin<2 + begrecord = 1; +end +if nargin<3 + endrecord = inf; +end + +% The file starts with a 16*1024 bytes header in ascii, followed by a +% number of records (c.f. trials). + +% The format of a tetrode record is +% int64 TimeStamp +% int32 ScNumber +% int32 CellNumber +% int32 Param[0] ƒ ƒ int32 Param[7] +% int16 ChanW[0] +% int16 ChanX[0] +% int16 ChanY[0] +% int16 ChanZ[0] ƒ ƒ +% int16 ChanW[31] +% int16 ChanX[31] +% int16 ChanY[31] +% int16 ChanZ[31] + +hdr = neuralynx_getheader(filename); +fid = fopen(filename, 'rb', 'ieee-le'); + +% determine the length of the file +fseek(fid, 0, 'eof'); +headersize = 16384; +recordsize = 304; +NRecords = floor((ftell(fid) - headersize)/recordsize); + +if NRecords>0 + if (ispc), fclose(fid); end + % read the timestamp from the first and last record + hdr.FirstTimeStamp = neuralynx_timestamp(filename, 1); + hdr.LastTimeStamp = neuralynx_timestamp(filename, inf); + if (ispc), fid = fopen(filename, 'rb', 'ieee-le'); end +else + hdr.FirstTimeStamp = nan; + hdr.LastTimeStamp = nan; +end + +if begrecord==0 && endrecord==0 + % only read the header +elseif begrecord<1 + error('cannot read before the first record'); +elseif begrecord>NRecords + error('cannot read beyond the last record') +elseif endrecord>NRecords + endrecord = NRecords; +end + +if begrecord>=1 && endrecord>=begrecord + % rewind to the first record to be read + status = fseek(fid, headersize + (begrecord-1)*recordsize, 'bof'); + if status~=0 + error('cannot jump to the requested record'); + end + + numrecord = (endrecord-begrecord+1); + TimeStamp = zeros(1,numrecord,'uint64'); + ScNumber = zeros(1,numrecord); + CellNumber = zeros(1,numrecord); + Param = zeros(8,numrecord); + Samp = zeros(4,32,numrecord); + + for k=1:numrecord + TimeStamp(k) = fread(fid, 1, 'uint64=>uint64'); + ScNumber(k) = fread(fid, 1, 'int32'); + CellNumber(k) = fread(fid, 1, 'int32'); + Param(k,:) = fread(fid, 8, 'int32'); + Samp(:,:,k) = fread(fid, [4 32], 'int16'); % chan W, X, Y, Z + end + + ntt.TimeStamp = TimeStamp; + ntt.ScNumber = ScNumber; + ntt.CellNumber = CellNumber; + ntt.Param = Param; + % FIXME apply the scaling factor from ADBitVolts and convert to uV + % ntt.dat = Samp * 1e6 * hdr.ADBitVolts; + nst.dat = Samp; +end +fclose(fid); + +% store the header info in the output structure +ntt.NRecords = NRecords; +ntt.hdr = hdr; diff --git a/external/fieldtrip/fileio/private/read_neuralynx_sdma.m b/external/fieldtrip/fileio/private/read_neuralynx_sdma.m new file mode 100644 index 0000000..b9c9b45 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_neuralynx_sdma.m @@ -0,0 +1,448 @@ +function [dat] = read_neuralynx_sdma(dataset, begsample, endsample, chanindx); + +% READ_NEURALYNX_SDMA read specified channels and samples from a Neuralynx splitted DMA dataset +% +% Use as +% [hdr] = read_neuralynx_sdma(dataset) +% [dat] = read_neuralynx_sdma(dataset, begsample, endsample, chanindx) +% +% The splitted DMA dataset is not a formal Neuralynx format, but at +% the FCDC we use it in conjunction with SPIKEDOWNSAMPLE. The dataset +% directory contains files, one for each channel, each containing a +% 8-byte header followed by the binary values for all samples. Commonly +% the binary values are represented as int32, but it is possible to use +% int16 or other numeric representations. The 8-byte header specifies the +% numeric representation and the bitshift that should be applied (in case +% of integer representations). +% +% This function returns the electrophysiological data in AD units +% and not in uV. You should look up the details of the headstage and +% the Neuralynx amplifier and scale the values accordingly. + +% Copyright (C) 2006-2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_neuralynx_sdma.m 945 2010-04-21 17:41:20Z roboos $ + +needhdr = (nargin==1); +needdat = (nargin>=2); + +if ~isdir(dataset) + error('dataset should be a directory'); +end + +% determine the content of the dataset directory +dirlist = dir(dataset); + +% determine the correspondence between files and channels +label = cell(length(dirlist),1); +filesel = zeros(length(dirlist),1); +headerfile = []; +[pd, nd, xd] = fileparts(dataset); +for i=1:length(dirlist) + [pf, nf, x1] = fileparts(dirlist(i).name); + [pf, nf, x2] = fileparts(nf); + % compare the name of the channel with the name of the dataset and look at the file extention + % the file should be called "dataset/dataset.chanlabel" or "dataset/dataset.chanlabel.bin" + if strcmp(nf, nd) && ~isempty(x1) + if ~isempty(x2) + label{i} = x2(2:end); + filesel(i) = 1; + elseif strcmp(x1, '.txt') + % this is not a proper channel, but an ascii file with header info + label{i} = []; + filesel(i) = 0; + headerfile = fullfile(dataset, dirlist(i).name); + else + label{i} = x1(2:end); + filesel(i) = 1; + end + else + label{i} = []; + filesel(i) = 0; + end +end +label = label(filesel==1); +bytes = cell2mat({dirlist(filesel==1).bytes}); % number of bytes in each file +filelist = {dirlist(filesel==1).name}; % filename excluding the path +clear dirlist filesel pd nd xd + +for i=1:length(filelist) + % include the full path in the filename + filelist{i} = fullfile(dataset, filelist{i}); +end + +% there is a preferred ordering, which corresponds with the channel order in the non-splitted DMA file +preferred = { + 'stx' + 'pid' + 'siz' + 'tsh' + 'tsl' + 'cpu' + 'ttl' + 'x01' + 'x02' + 'x03' + 'x04' + 'x05' + 'x06' + 'x07' + 'x08' + 'x09' + 'x10' + 'csc001' + 'csc002' + 'csc003' + 'csc004' + 'csc005' + 'csc006' + 'csc007' + 'csc008' + 'csc009' + 'csc010' + 'csc011' + 'csc012' + 'csc013' + 'csc014' + 'csc015' + 'csc016' + 'csc017' + 'csc018' + 'csc019' + 'csc020' + 'csc021' + 'csc022' + 'csc023' + 'csc024' + 'csc025' + 'csc026' + 'csc027' + 'csc028' + 'csc029' + 'csc030' + 'csc031' + 'csc032' + 'csc033' + 'csc034' + 'csc035' + 'csc036' + 'csc037' + 'csc038' + 'csc039' + 'csc040' + 'csc041' + 'csc042' + 'csc043' + 'csc044' + 'csc045' + 'csc046' + 'csc047' + 'csc048' + 'csc049' + 'csc050' + 'csc051' + 'csc052' + 'csc053' + 'csc054' + 'csc055' + 'csc056' + 'csc057' + 'csc058' + 'csc059' + 'csc060' + 'csc061' + 'csc062' + 'csc063' + 'csc064' + 'csc065' + 'csc066' + 'csc067' + 'csc068' + 'csc069' + 'csc070' + 'csc071' + 'csc072' + 'csc073' + 'csc074' + 'csc075' + 'csc076' + 'csc077' + 'csc078' + 'csc079' + 'csc080' + 'csc081' + 'csc082' + 'csc083' + 'csc084' + 'csc085' + 'csc086' + 'csc087' + 'csc088' + 'csc089' + 'csc090' + 'csc091' + 'csc092' + 'csc093' + 'csc094' + 'csc095' + 'csc096' + 'csc097' + 'csc098' + 'csc099' + 'csc100' + 'csc101' + 'csc102' + 'csc103' + 'csc104' + 'csc105' + 'csc106' + 'csc107' + 'csc108' + 'csc109' + 'csc110' + 'csc111' + 'csc112' + 'csc113' + 'csc114' + 'csc115' + 'csc116' + 'csc117' + 'csc118' + 'csc119' + 'csc120' + 'csc121' + 'csc122' + 'csc123' + 'csc124' + 'csc125' + 'csc126' + 'csc127' + 'csc128' + 'csc129' + 'csc130' + 'csc131' + 'csc132' + 'csc133' + 'csc134' + 'csc135' + 'csc136' + 'csc137' + 'csc138' + 'csc139' + 'csc140' + 'csc141' + 'csc142' + 'csc143' + 'csc144' + 'csc145' + 'csc146' + 'csc147' + 'csc148' + 'csc149' + 'csc150' + 'csc151' + 'csc152' + 'csc153' + 'csc154' + 'csc155' + 'csc156' + 'csc157' + 'csc158' + 'csc159' + 'csc160' + 'csc161' + 'csc162' + 'csc163' + 'csc164' + 'csc165' + 'csc166' + 'csc167' + 'csc168' + 'csc169' + 'csc170' + 'csc171' + 'csc172' + 'csc173' + 'csc174' + 'csc175' + 'csc176' + 'csc177' + 'csc178' + 'csc179' + 'csc180' + 'csc181' + 'csc182' + 'csc183' + 'csc184' + 'csc185' + 'csc186' + 'csc187' + 'csc188' + 'csc189' + 'csc190' + 'csc191' + 'csc192' + 'csc193' + 'csc194' + 'csc195' + 'csc196' + 'csc197' + 'csc198' + 'csc199' + 'csc200' + 'csc201' + 'csc202' + 'csc203' + 'csc204' + 'csc205' + 'csc206' + 'csc207' + 'csc208' + 'csc209' + 'csc210' + 'csc211' + 'csc212' + 'csc213' + 'csc214' + 'csc215' + 'csc216' + 'csc217' + 'csc218' + 'csc219' + 'csc220' + 'csc221' + 'csc222' + 'csc223' + 'csc224' + 'csc225' + 'csc226' + 'csc227' + 'csc228' + 'csc229' + 'csc230' + 'csc231' + 'csc232' + 'csc233' + 'csc234' + 'csc235' + 'csc236' + 'csc237' + 'csc238' + 'csc239' + 'csc240' + 'csc241' + 'csc242' + 'csc243' + 'csc244' + 'csc245' + 'csc246' + 'csc247' + 'csc248' + 'csc249' + 'csc250' + 'csc251' + 'csc252' + 'csc253' + 'csc254' + 'csc255' + 'csc256' + 'crc' + }; + +[sel1, sel2] = match_str(preferred, label); +if length(sel2)==length(label) + % all reorder the labels/files + label = label(sel2); + bytes = bytes(sel2); + filelist = filelist(sel2); +else + % not all files in this SDMA dataset could be accounted for in the + % preference list, hence do not attempt to apply the preferred ordering +end + +if needhdr + % construct a general header for the complete dataset + if ~isempty(headerfile) + orig = neuralynx_getheader(headerfile); + hdr.Fs = orig.SamplingFrequency; + hdr.nSamples = []; % see below + hdr.nSamplesPre = 0; % number of pre-trigger samples in each trial + hdr.nTrials = 1; % number of trials + hdr.label = label; + hdr.nChans = length(label); + hdr.orig.dataset = orig; % keep the header details + else + % some parts of the header have to be hardcoded, since the splitted dataset does not contain all header information + hdr.Fs = 32556; % sampling frequency + hdr.nSamples = []; % see below + hdr.nSamplesPre = 0; % number of pre-trigger samples in each trial + hdr.nTrials = 1; % number of trials + hdr.label = label; + hdr.nChans = length(label); + end + + % read the header of each individual file, i.e. for each variable + clear orig + for i=1:length(filelist) + orig(i) = read_neuralynx_bin(filelist{i}); + end + + % determine the number of samples for each channel + nsamples = cell2mat({orig.nSamples}); + if any(nsamples~=nsamples(1)) + error('different number of samples over channels are not supported'); + else + hdr.nSamples = nsamples(1); + end + + % determine the sampling frequency for each channel + fsample = cell2mat({orig.Fs}); + if any(diff(fsample)) + error('different sampling rates over channels are not supported'); + elseif any(fsample~=hdr.Fs) + error('inconsistent sampling rates'); + end + + % determine the first and last timestamp, by reading them from the timestamp channels + tslfile = filelist{find(strcmp('tsl', label))}; + tshfile = filelist{find(strcmp('tsh', label))}; + beg_tsl = read_neuralynx_bin(tslfile, 1, 1); + beg_tsh = read_neuralynx_bin(tshfile, 1, 1); + end_tsl = read_neuralynx_bin(tslfile, hdr.nSamples, hdr.nSamples); + end_tsh = read_neuralynx_bin(tshfile, hdr.nSamples, hdr.nSamples); + hdr.FirstTimeStamp = timestamp_neuralynx(beg_tsl, beg_tsh); + hdr.LastTimeStamp = timestamp_neuralynx(end_tsl, end_tsh); + hdr.TimeStampPerSample = double(hdr.LastTimeStamp-hdr.FirstTimeStamp)./(hdr.nSamples-1); % this should be double, since it can be fractional + + % also remember the original header details + hdr.orig.chan = orig; + + % only return the header information + dat = hdr; + +else + % allocate memory for all data + dat = zeros(length(chanindx), endsample-begsample+1); + + % read all channels, one small chunk at at time, and write it to seperate files + for i=1:length(chanindx) + j = chanindx(i); + dat(i,:) = double(read_neuralynx_bin(filelist{j}, begsample, endsample)); + end +end diff --git a/external/fieldtrip/fileio/private/read_neuralynx_tsh.m b/external/fieldtrip/fileio/private/read_neuralynx_tsh.m new file mode 100644 index 0000000..dea692e --- /dev/null +++ b/external/fieldtrip/fileio/private/read_neuralynx_tsh.m @@ -0,0 +1,52 @@ +function [dat] = read_neuralynx_tsl(filename, begsample, endsample); + +% READ_NEURALYNX_TSL reads the TimeStampLow values from a *.tsl file +% +% Use as +% [dat] = read_neuralynx_tsl(filename, begsample, endsample); +% +% The *.tsl file is not a formal Neuralynx file format, but at the +% F.C. Donders Centre we use it in conjunction with Neuralynx and +% SPIKEDOWNSAMPLE. + +% Copyright (C) 2006, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_neuralynx_tsh.m 945 2010-04-21 17:41:20Z roboos $ + +fid = fopen(filename, 'rb', 'ieee-le'); + +if begsample<1 + begsample = 1; +end + +if isinf(endsample) + fseek(fid, 0, 'eof'); + endsample = (ftell(fid)-8)/4; + fseek(fid, 0, 'bof'); +end + +fseek(fid, 8, 'cof'); % skip the 8-byte header with the filetype identifier +fseek(fid, begsample-1, 'cof'); % skip to the beginning of the interesting data +dat = fread(fid, endsample-begsample+1, 'uint32=>uint32')'; +if length(dat)<(endsample-begsample+1) + error('could not read the requested data'); +end + +fclose(fid); + diff --git a/external/fieldtrip/fileio/private/read_neuralynx_tsl.m b/external/fieldtrip/fileio/private/read_neuralynx_tsl.m new file mode 100644 index 0000000..196adc5 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_neuralynx_tsl.m @@ -0,0 +1,52 @@ +function [dat] = read_neuralynx_tsh(filename, begsample, endsample); + +% READ_NEURALYNX_TTL reads the TimeStampHi values from a *.tsh file +% +% Use as +% [dat] = read_neuralynx_tsh(filename, begsample, endsample); +% +% The *.tsh file is not a formal Neuralynx file format, but at the +% F.C. Donders Centre we use it in conjunction with Neuralynx and +% SPIKEDOWNSAMPLE. + +% Copyright (C) 2006, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_neuralynx_tsl.m 945 2010-04-21 17:41:20Z roboos $ + +fid = fopen(filename, 'rb', 'ieee-le'); + +if begsample<1 + begsample = 1; +end + +if isinf(endsample) + fseek(fid, 0, 'eof'); + endsample = (ftell(fid)-8)/4; + fseek(fid, 0, 'bof'); +end + +fseek(fid, 8, 'cof'); % skip the 8-byte header with the filetype identifier +fseek(fid, begsample-1, 'cof'); % skip to the beginning of the interesting data +dat = fread(fid, endsample-begsample+1, 'uint32=>uint32')'; +if length(dat)<(endsample-begsample+1) + error('could not read the requested data'); +end + +fclose(fid); + diff --git a/external/fieldtrip/fileio/private/read_neuralynx_ttl.m b/external/fieldtrip/fileio/private/read_neuralynx_ttl.m new file mode 100644 index 0000000..b58c514 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_neuralynx_ttl.m @@ -0,0 +1,52 @@ +function [dat] = read_neuralynx_ttl(filename, begsample, endsample); + +% READ_NEURALYNX_TTL reads the Parallel_in values from a *.ttl file +% +% Use as +% [dat] = read_neuralynx_ttl(filename, begsample, endsample); +% +% The *.ttl file is not a formal Neuralynx file format, but at the +% F.C. Donders Centre we use it in conjunction with Neuralynx and +% SPIKEDOWNSAMPLE. + +% Copyright (C) 2006, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_neuralynx_ttl.m 945 2010-04-21 17:41:20Z roboos $ + +fid = fopen(filename, 'rb', 'ieee-le'); + +if begsample<1 + begsample = 1; +end + +if isinf(endsample) + fseek(fid, 0, 'eof'); + endsample = (ftell(fid)-8)/4; + fseek(fid, 0, 'bof'); +end + +fseek(fid, 8, 'cof'); % skip the 8-byte header with the filetype identifier +fseek(fid, begsample-1, 'cof'); % skip to the beginning of the interesting data +dat = fread(fid, endsample-begsample+1, 'uint32=>uint32')'; +if length(dat)<(endsample-begsample+1) + error('could not read the requested data'); +end + +fclose(fid); + diff --git a/external/fieldtrip/fileio/private/read_neuroshare.m b/external/fieldtrip/fileio/private/read_neuroshare.m new file mode 100644 index 0000000..0583227 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_neuroshare.m @@ -0,0 +1,232 @@ +function [nsout] = read_neuroshare(filename, varargin) + +% READ_NEUROSHARE reads header information or data from any file format +% supported by Neuroshare. The file can contain event timestamps, spike +% timestamps and waveforms, and continuous (analog) variable data. +% +% Use as: +% hdr = read_neuroshare(filename, ...) +% dat = read_neuroshare(filename, ...) +% +% Optional input arguments should be specified in key-value pairs and may include: +% 'dataformat' = string +% 'readevent' = 'yes' or 'no' (default) +% 'readspike' = 'yes' or 'no' (default) +% 'readanalog' = 'yes' or 'no' (default) +% 'chanindx' = list with channel indices to read +% 'begsample = first sample to read +% 'endsample = last sample to read +% +% NEUROSHARE: http://www.neuroshare.org is a site created to support the +% collaborative development of open library and data file format +% specifications for neurophysiology and distribute open-source data +% handling software tools for neuroscientists. +% +% Note that this is a test version, WINDOWS only + +% Copyright (C) 2009, Saskia Haegens +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id$ + +% check the availability of the required neuroshare toolbox +hastoolbox('neuroshare', 1); + +% get the optional input arguments +dataformat = keyval('dataformat', varargin); +begsample = keyval('begsample', varargin); +endsample = keyval('endsample', varargin); +chanindx = keyval('chanindx', varargin); +readevent = keyval('readevent', varargin); +readspike = keyval('readspike', varargin); +readanalog = keyval('readanalog', varargin); + +% set defaults +if isempty(readevent); readevent = 'no'; end +if isempty(readspike); readspike = 'no'; end +if isempty(readanalog); readanalog = 'no'; end + +% determine the filetype +if isempty(dataformat) + if filetype_check_extension(filename, '.nev') % to prevent confusion with neuralynx nev files + dataformat = 'nev'; + else + dataformat = filetype(filename); + end +end + +% determine the required neuroshare library +switch dataformat + case 'nev' + lib = 'nsNEVLibrary.dll'; + case 'plexon_plx' + lib = 'nsPlxLibrary.dll'; + case 'xxx' + lib = 'xxx.dll'; +end + + + +% NEUROSHARE LIBRARY % +% set the library (note: library has to be on the path) +[feedback] = ns_SetLibrary(which(lib)); +if feedback~=0, [feedback err] = ns_GetLastErrorMsg; disp(err), end + +% feedback about datafile and library +[feedback, libinfo] = ns_GetLibraryInfo; +if feedback~=0, [feedback err] = ns_GetLastErrorMsg; disp(err), end +disp(['Loading file ' filename ' using ' libinfo.Description ' from ' libinfo.Creator]); + +% open dataset +[feedback fileID] = ns_OpenFile(filename); +if feedback~=0, [feedback err] = ns_GetLastErrorMsg; disp(err), end + + + +% HEADER % +% retrieve dataset information +[feedback hdr.fileinfo] = ns_GetFileInfo(fileID); +if feedback~=0, [feedback err] = ns_GetLastErrorMsg; disp(err), end + +% retrieve entity information +[feedback hdr.entityinfo] = ns_GetEntityInfo(fileID, 1:hdr.fileinfo.EntityCount); +if feedback~=0, [feedback err] = ns_GetLastErrorMsg; disp(err), end + +% hdr.entityinfo.EntityType specifies the type of entity data recorded on that +% channel. It can be one of the following: +% 0: Unknown entity +% 1: Event entity +% 2: Analog entity +% 3: Segment entity +% 4: Neural event entity +enttyp = {'unknown'; 'event'; 'analog'; 'segment'; 'neural'}; +for i=1:5 + list.(enttyp{i}) = find([hdr.entityinfo.EntityType] == i-1); % gives channel numbers for each entity type +end + +% give warning if unkown entities are found +if ~isempty(list.unknown) + warning(['There are ' num2str(length(list.unknown)) ' unknown entities found, these will be ignored.']); +end + +% retrieve event information +if ~isempty(list.event) + [feedback hdr.eventinfo] = ns_GetEventInfo(fileID, list.event); + if feedback~=0, [feedback err] = ns_GetLastErrorMsg; disp(err), end +end + +% retrieve analog information +if ~isempty(list.analog) + [feedback hdr.analoginfo] = ns_GetAnalogInfo(fileID, list.analog); + if feedback~=0, [feedback err] = ns_GetLastErrorMsg; disp(err), end +end + +% retrieve segment information +if ~isempty(list.segment) + [feedback hdr.seginfo] = ns_GetSegmentInfo(fileID, list.segment); + if feedback~=0, [feedback err] = ns_GetLastErrorMsg; disp(err), end + [feedback hdr.segsourceinfo] = ns_GetSegmentSourceInfo(fileID, list.segment, 1); + if feedback~=0, [feedback err] = ns_GetLastErrorMsg; disp(err), end +end + +% retrieve neural information +if ~isempty(list.neural) + [feedback hdr.neuralinfo] = ns_GetNeuralInfo(fileID, list.neural); + if feedback~=0, [feedback err] = ns_GetLastErrorMsg; disp(err), end +end + + + +% EVENT % +% retrieve events +if strcmp(readevent, 'yes') && ~isempty(list.event) + [feedback event.timestamp event.data event.datasize] = ns_GetEventData(fileID, list.event, 1:max([hdr.entityinfo(list.event).ItemCount])); + if feedback~=0, [feedback err] = ns_GetLastErrorMsg; disp(err), end + for c=1:length(list.event) + if hdr.entityinfo(list.event(c)).ItemCount~=0 + for i=1:length(event.timestamp) + [feedback, event.sample(i,c)] = ns_GetIndexByTime(fileID, list.event(c), event.timestamp(i,c), 0); + if feedback~=0, [feedback err] = ns_GetLastErrorMsg; disp(err), end + end + end + end +elseif strcmp(readevent, 'yes') && isempty(list.event) + warning('no events were found in the data') +end + + + +% DATA % +% retrieve analog data +if strcmp(readanalog, 'yes') && ~isempty(list.analog) + % set defaults + if isempty(chanindx); chanindx = list.analog; end + if isempty(begsample); begsample = 1; end + if isempty(endsample); + itemcount = max([hdr.entityinfo(list.analog).ItemCount]); + else + itemcount = endsample - begsample + 1; + end + [feedback analog.contcount analog.data] = ns_GetAnalogData(fileID, chanindx, begsample, itemcount); + if feedback~=0, [feedback err] = ns_GetLastErrorMsg; disp(err), end +elseif strcmp(readanalog, 'yes') && isempty(list.analog) + warning('no analog events were found in the data') +end + + + +% SPIKE % +% retrieve segments [ (sorted) spike waveforms ] +if strcmp(readspike, 'yes') && ~isempty(list.segment) + % collect data: all chans (=list.segment) and all waveforms (=hdr.entityinfo.ItemCount) + [feedback segment.timestamp segment.data segment.samplecount segment.unitID] = ns_GetSegmentData(fileID, list.segment, 1:max([hdr.entityinfo(list.segment).ItemCount])); + if feedback~=0, [feedback err] = ns_GetLastErrorMsg; disp(err), end +elseif strcmp(readspike, 'yes') && isempty(list.segment) + warning('no spike waveforms were found in the data') +end + +% retrieve neural events [ spike timestamps ] +if strcmp(readspike, 'yes') && ~isempty(list.neural) + neural.data = nan(length(list.neural), max([hdr.entityinfo(list.neural).ItemCount])); % pre-allocate + for chan=1:length(list.neural) % get timestamps + [feedback neural.data(chan,1:hdr.entityinfo(list.neural(chan)).ItemCount)] = ns_GetNeuralData(fileID, list.neural(chan), 1, hdr.entityinfo(list.neural(chan)).ItemCount); + if feedback~=0, [feedback err] = ns_GetLastErrorMsg; disp(err), end + end +elseif strcmp(readspike, 'yes') && isempty(list.neural) + warning('no spike timestamps were found in the data') +end + + + +% close dataset +[feedback] = ns_CloseFile(fileID); +if feedback~=0, [feedback err] = ns_GetLastErrorMsg; disp(err), end + + +% collect the output +nsout = []; +nsout.hdr = hdr; +nsout.list = list; +try nsout.event = event; end +try nsout.analog = analog; end +try nsout.spikew = segment; end +try nsout.spiket = neural; end + + + + diff --git a/external/fieldtrip/fileio/private/read_nex_data.m b/external/fieldtrip/fileio/private/read_nex_data.m new file mode 100644 index 0000000..0329f85 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_nex_data.m @@ -0,0 +1,102 @@ +function [dat] = read_nex_data(filename, hdr, begsample, endsample, chanindx) + +% READ_NEX_DATA for Plexon *.nex file +% +% Use as +% [dat] = read_nex_data(filename, hdr, begsample, endsample, chanindx) +% +% See also READ_NEX_HEADER, READ_NEX_EVENT + +% Copyright (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_nex_data.m 945 2010-04-21 17:41:20Z roboos $ + +try, + % work with the original header, not the FieldTrip one + hdr = hdr.orig; +catch + % assume that we got the original header +end + +numsmp = cell2mat({hdr.varheader.numsmp}); +adindx = find(cell2mat({hdr.varheader.typ})==5); +smpfrq = hdr.varheader(adindx(1)).wfrequency; +sgn = chanindx; +nsmp = (endsample-begsample+1); +dat = zeros(length(sgn), nsmp); + +fid = fopen(filename, 'r', 'ieee-le'); +for sgnlop=1:length(sgn) + + if hdr.varheader(sgn(sgnlop)).typ == 0 + % read a spike channel + status = fseek(fid,hdr.varheader(sgn(sgnlop)).offset,'bof'); + + % read the sample indices at which spikes occurred + tim = fread(fid,hdr.varheader(sgn(sgnlop)).cnt,'int32'); + % downsample from 40kHz to the A/D sampling frequency + tim = (tim ./ hdr.filheader.frequency) * smpfrq + 1; % add one sample, since ts=0 corresponds to sample=1 + tim = round(tim); % needed because of the edges in histc + % select only samples between the desired begin and end + % tim = tim(find(tim>=begsample & tim<=endsample)); + % convert sample indices into a continuous signal + if ~isempty(tim) + dum = histc(tim-begsample, 0:(nsmp-1), 1); + dat(sgnlop,:) = dum(:)'; + end + + elseif hdr.varheader(sgn(sgnlop)).typ == 5 + % read an A/D channel + status = fseek(fid,hdr.varheader(sgn(sgnlop)).offset,'bof'); + + % this just reads the times of LFP starts + tim = fread(fid,hdr.varheader(sgn(sgnlop)).cnt,'int32'); + % this just reads the indices of LFP starts + ind = fread(fid,hdr.varheader(sgn(sgnlop)).cnt,'int32'); + if length(ind)>1 + error('multiple A/D segments are not supported'); + end + + % convert from timestamps to samples, expressed in the sampling frequency of the AD channels + tim = (tim ./ hdr.filheader.frequency) * smpfrq; + tim = round(tim); + + ch_begsample = begsample - tim; + ch_endsample = endsample - tim; + + if (ch_begsample<1) + error(sprintf('cannot read before the begin of the recorded data (channel %d)', sgn(sgnlop))); + elseif (ch_endsample>hdr.varheader(sgn(sgnlop)).numsmp) + error(sprintf('cannot read beyond the end of the recorded data (channel %d)', sgn(sgnlop))); + end + + % seek to the beginning of the interesting data, correct for the A/D card initialisation delay + fseek(fid,(ch_begsample-1)*2, 'cof'); + % read the actual data for the whole channel + dum = fread(fid,nsmp,'int16'); + % convert to mV + dat(sgnlop,:) = dum(:)' * hdr.varheader(sgn(sgnlop)).adtomv; + + else + % warning(sprintf('unsupported data format for channel %s', hdr.label{sgn(sgnlop)})); + end + +end +status = fclose(fid); + diff --git a/external/fieldtrip/fileio/private/read_nex_event.m b/external/fieldtrip/fileio/private/read_nex_event.m new file mode 100644 index 0000000..62e945a --- /dev/null +++ b/external/fieldtrip/fileio/private/read_nex_event.m @@ -0,0 +1,69 @@ +function [event] = read_nex_event(filename) + +% READ_NEX_EVENT for Plexon *.nex file +% +% Use as +% [event] = read_nex_event(filename) +% +% The sample numbers returned in event.sample correspond with the +% timestamps, correcting for the difference in sampling frequency in the +% continuous LFP channels and the system sampling frequency. Assuming 40kHz +% sampling frequency for the system and 1kHz for the LFP channels, it is +% event.sample = timestamp / (40000/1000); +% +% See also READ_NEX_HEADER, READ_NEX_DATA + +% Copyright (C) 2005-2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_nex_event.m 945 2010-04-21 17:41:20Z roboos $ + +hdr = read_nex_header(filename); +adindx = find(cell2mat({hdr.varheader.typ})==5); +smpfrq = hdr.varheader(adindx(1)).wfrequency; + +% find the channel with the strobed trigger +mrkvarnum = find([hdr.varheader.typ] == 6); + +fid=fopen(filename,'r','ieee-le'); +status = fseek(fid,hdr.varheader(mrkvarnum).offset,'bof'); + +% read the time of the triggers +dum = fread(fid,hdr.varheader(mrkvarnum).cnt,'int32'); +dum = dum ./(hdr.filheader.frequency./smpfrq); +mrk.tim = round(dum); + +% read the value of the triggers +status = fseek(fid,64,'cof'); +dum = fread(fid,[hdr.varheader(mrkvarnum).mrklen,hdr.varheader(mrkvarnum).cnt],'uchar'); +mrk.val = str2num(char(dum(1:5,:)')); + +status = fclose(fid); + +% translate into an FCDC event structure +Nevent = length(mrk.tim); +event = struct('sample', num2cell(mrk.tim), 'value', num2cell(mrk.val)); +for i=1:Nevent + % the code above with the struct and num2cell is much faster + % event(i).sample = mrk.tim(i); + % event(i).value = mrk.val(i); + event(i).type = hdr.varheader(mrkvarnum).nam; + event(i).duration = 1; + event(i).offset = 0; +end + diff --git a/external/fieldtrip/fileio/private/read_nex_header.m b/external/fieldtrip/fileio/private/read_nex_header.m new file mode 100644 index 0000000..1844765 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_nex_header.m @@ -0,0 +1,69 @@ +function [hdr] = read_nex_header(filename) + +% READ_NEX_HEADER for Plexon *.nex file +% +% Use as +% [hdr] = read_nex_header(filename) +% +% See also RAD_NEX_DATA, READ_NEX_EVENT + +% Copyright (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_nex_header.m 945 2010-04-21 17:41:20Z roboos $ + +fid = fopen(filename, 'r', 'ieee-le'); + +% reading the file header +filheader.magicnumber = fread(fid,4,'uint8=>char')'; +filheader.version = fread(fid,1,'int32'); +filheader.comment = fread(fid,256,'uint8=>char')'; +filheader.frequency = fread(fid,1,'double'); +filheader.begvar = fread(fid,1,'int32'); +filheader.endvar = fread(fid,1,'int32'); +filheader.numvar = fread(fid,1,'int32'); +filheader.nextfileheader = fread(fid,1,'int32'); +filheader.padding = fread(fid,256,'uint8=>char')'; + +% reading the variable headers +for varlop=1:filheader.numvar + varheader(varlop).typ = fread(fid,1,'int32'); + varheader(varlop).version = fread(fid,1,'int32'); + varheader(varlop).nam = fread(fid,64,'uint8=>char')'; + varheader(varlop).offset = fread(fid,1,'int32'); + varheader(varlop).cnt = fread(fid,1,'int32'); + varheader(varlop).wirenumber = fread(fid,1,'int32'); + varheader(varlop).unitnumber = fread(fid,1,'int32'); + varheader(varlop).gain = fread(fid,1,'int32'); + varheader(varlop).filter = fread(fid,1,'int32'); + varheader(varlop).xpos = fread(fid,1,'double'); + varheader(varlop).ypos = fread(fid,1,'double'); + varheader(varlop).wfrequency = fread(fid,1,'double'); + varheader(varlop).adtomv = fread(fid,1,'double'); + varheader(varlop).numsmp = fread(fid,1,'int32'); + varheader(varlop).nummrk = fread(fid,1,'int32'); + varheader(varlop).mrklen = fread(fid,1,'int32'); + padding = fread(fid,68,'uint8=>char')'; +end + +status = fclose(fid); + +% put them together into one struct +hdr.fil = filename; +hdr.filheader = filheader; +hdr.varheader = varheader; diff --git a/external/fieldtrip/fileio/private/read_nexstim_event.m b/external/fieldtrip/fileio/private/read_nexstim_event.m new file mode 100644 index 0000000..dc7a2e5 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_nexstim_event.m @@ -0,0 +1,81 @@ +function [event] = read_nexstim_event(filename) + +% Use as +% [event] = read_nexstim_event(filename) + +% Written by Vladimir Litvak based on the function nxeGetTriggers +% provided by Nexstim +% +% Copyright (C) 2007, Vladimir Litvak +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_nexstim_event.m 945 2010-04-21 17:41:20Z roboos $ + +% trigLine - either 1(GATE), 2(TRIG1) or 3(TRIG2) +% trigEdge - either 'rising' or 'falling' + +fid=fopen(filename,'r','l'); + +numChannels = 64; +blockSamples = 14500; +trigThreshold = 2000; +trigChannels = [1 2 3]; % Is fixed for the present Nexstim format. + +fseek(fid,0,'eof'); +numBytes = ftell(fid); +numSamples = (numBytes/2)/numChannels; +numBlocks = ceil(numSamples/blockSamples); + +fseek(fid,0,'bof'); +trigPos=[]; + +event=[]; +for i = 1:numBlocks + blockPos=(i-1)*blockSamples; + data = fread(fid,[numChannels blockSamples+1],'int16'); + + for trigLine=1:length(trigChannels); + trigPosRising = find(diff(data(trigChannels(trigLine),:))>trigThreshold)+blockPos; + trigPosFalling = find(diff(data(trigChannels(trigLine),:))<-trigThreshold)+blockPos; + + if ~isempty(trigPosRising) + for i=1:length(trigPosRising) + event(end+1).type = 'rising'; + event(end ).sample = trigPosRising(i); + event(end ).value = trigLine; + event(end ).offset = []; + event(end ).duration = []; + end + end + + if ~isempty(trigPosFalling) + for i=1:length(trigPosFalling) + event(end+1).type = 'falling'; + event(end ).sample = trigPosFalling(i); + event(end ).value = trigLine; + event(end ).offset = []; + event(end ).duration = []; + end + end + + end + fseek(fid,-(2*numChannels),'cof'); +end + +fclose(fid); + diff --git a/external/fieldtrip/fileio/private/read_nexstim_nxe.m b/external/fieldtrip/fileio/private/read_nexstim_nxe.m new file mode 100644 index 0000000..faf81db --- /dev/null +++ b/external/fieldtrip/fileio/private/read_nexstim_nxe.m @@ -0,0 +1,158 @@ +function [dat] = read_nexstim_nxe(filename, begsample, endsample, chanindx) + +% READ_NEXSTIM_NXE reads specified samples from a NXE continous datafile +% +% Use as +% [hdr] = read_nexstim_nxe(filename) +% where +% filename name of the datafile, including the .bdf extension +% This returns a header structure with the following elements +% hdr.Fs sampling frequency +% hdr.nChans number of channels +% hdr.nSamples number of samples per trial +% hdr.nSamplesPre number of pre-trigger samples in each trial +% hdr.nTrials number of trials +% hdr.label cell-array with labels of each channel +% +% Or use as +% [dat] = read_nexstim_nxe(filename, begsample, endsample, chanindx) +% where +% filename name of the datafile, including the .nxe extension +% begsample index of the first sample to read +% endsample index of the last sample to read +% chanindx index of channels to read (optional, default is all) +% This returns a Nchans X Nsamples data matrix + +% Written by Vladimir Litvak based on functions provided by Nexstim +% +% Copyright (C) 2007, Vladimir Litvak +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_nexstim_nxe.m 945 2010-04-21 17:41:20Z roboos $ + +if nargin==1 + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % read the header + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + hdr.Fs = 1450; + hdr.nChans = 64; + hdr.label = cell(64,1); + hdr.label(1:4)= {'GATE', 'TRIG1', 'TRIG2','EOG'}; + hdr.label(5:64) = { + 'Fp1' + 'Fpz' + 'Fp2' + 'AF1' + 'AFz' + 'AF2' + 'F7' + 'F3' + 'F1' + 'Fz' + 'F2' + 'F4' + 'F8' + 'FT9' + 'FT7' + 'FC5' + 'FC3' + 'FC1' + 'FCz' + 'FC2' + 'FC4' + 'FC6' + 'FT8' + 'FT10' + 'T7' + 'C5' + 'C3' + 'C1' + 'Cz' + 'C2' + 'C4' + 'C6' + 'T8' + 'TP9' + 'TP7' + 'CP5' + 'CP3' + 'CP1' + 'CPz' + 'CP2' + 'CP4' + 'CP6' + 'TP8' + 'TP10' + 'P9' + 'P7' + 'P3' + 'P1' + 'Pz' + 'P2' + 'P4' + 'P8' + 'P10' + 'PO3' + 'POz' + 'PO4' + 'O1' + 'Oz' + 'O2' + 'Iz'}; + + % it is continuous data, therefore append all records in one trial + hdr.nTrials = 1; + + fid=fopen(filename,'r','l'); + fseek(fid,0,'eof'); + numBytes = ftell(fid); + hdr.nSamples = (numBytes/2)/hdr.nChans; + + hdr.nSamplesPre = 0; + + fclose(fid); + + % return the header + dat = hdr; + +else + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % read the data + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + sfEEG = (1/2000) * (10/65535) * 1000000; + sfEOG = (1/400) * (10/65535) * 1000000; + sfTRIG = 10 * (10/65535); + + numChannels = 64; + + fid = fopen(filename,'r','l'); + fseek(fid, 2*numChannels*(begsample-1),'bof'); + data = fread(fid,[numChannels endsample-begsample+1],'short'); + fclose(fid); + + data(1:3,:) = sfTRIG.*data(1:3,:); + data(4,:) = sfEOG.*data(4,:); + data(5:64,:) = sfEEG.*data(5:64,:); + + if nargin<4 + chanindx = 1:numChannels; + end + + dat = data(chanindx,:); +end + diff --git a/external/fieldtrip/fileio/private/read_nimh_cortex.m b/external/fieldtrip/fileio/private/read_nimh_cortex.m new file mode 100644 index 0000000..518715f --- /dev/null +++ b/external/fieldtrip/fileio/private/read_nimh_cortex.m @@ -0,0 +1,183 @@ +function cortex = read_nimh_cortex(filename, varargin) + +% READ_NIMH_CORTEX +% +% Use as +% cortex = read_nimh_cortex(filename, ...) +% +% Optional input arguments should come in key-value pairs and may +% include +% begtrial = number (default = 1) +% endtrial = number (default = inf) +% epp = read the EPP data, 'yes' or 'no' (default = 'yes') +% eog = read the EOG data, 'yes' or 'no' (default = 'yes') +% feedback = display the progress on the screen, 'yes' or 'no' (default = 'no') +% +% The output is a structure array with one structure for every trial that was read. + +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_nimh_cortex.m 945 2010-04-21 17:41:20Z roboos $ + +% get the optional input arguments +feedback = keyval('feedback', varargin); if isempty(feedback), feedback = 'no'; end +begtrial = keyval('begtrial', varargin); if isempty(begtrial), begtrial = 1; end +endtrial = keyval('endtrial', varargin); if isempty(endtrial), endtrial = inf; end +% reading the epp and eog data is optional +epp = keyval('epp', varargin); if isempty(epp), epp = 'yes'; end +eog = keyval('eog', varargin); if isempty(eog), eog = 'yes'; end + +skipepp = strcmp(epp, 'no'); +skipeog = strcmp(eog, 'no'); +clear epp eog + +% this will hold the result +cortex = struct; + +% trials are counted with zero-offset +trial = 0; + +i_fid = fopen(filename, 'rb', 'ieee-le'); + +% read until the end of file or until the specified trial number +while ( ~feof (i_fid) && trial=begtrial + fprintf('reading trial %d\n', trial+1); + end + + % Number of bytes for each variable. + hd(1,1:8)= (fread(i_fid, 8, 'ushort'))'; + + % Convert bytes to number of float point values (4 bytes apiece in windows and FreeBSD). + hd(1,5)=hd(1,5)/4; + % Convert bytes to number of short values (2 bytes apiece in windows and FreeBSD). + hd(1,6)=hd(1,6)/2; + hd(1,7)=hd(1,7)/2; + hd(1,8)=hd(1,8)/2; + + header.cond_no = hd(1,1); + header.repeat_no = hd(1,2); + header.block_no = hd(1,3); + header.trial_no = hd(1,4); + header.isi_size = hd(1,5); + header.code_size = hd(1,6); + header.eog_size = hd(1,7); + header.epp_size = hd(1,8); + + hd(1,9:10) = (fread(i_fid, 2, 'uchar'))'; + + header.kHz_resolution = hd(1,9); + header.eye_storage_rate = hd(1,10); + + hd(1,11:13) = (fread(i_fid, 3, 'ushort'))'; + + header.expected_response = hd(1,11); + header.response = hd(1,12); + header.response_error = hd(1,13); + + if skiptrial + fseek(i_fid,header.isi_size, 'cof'); + fseek (i_fid,header.code_size, 'cof'); + else + time = (fread (i_fid,header.isi_size, 'ulong')); + event = (fread (i_fid,header.code_size, 'ushort')); + end % if skiptrial + + if skipepp || skiptrial + epp1 = []; + epp2 = []; + fseek (i_fid,header.epp_size * 2, 'cof'); + + else + epp = fread (i_fid,header.epp_size, 'short'); + epp1 = zeros(1,header.epp_size/2); + epp2 = zeros(1,header.epp_size/2); + + % fprintf(o_fid, '\nepp(x)\tepp(y)\n\n'); + + for i = 1:2:header.epp_size + % Must extract the data from the raw epp values. + % The epp value is made up of 12-bits of data, and 4-bits (the + % low-order 4 bits) of the channel number. + % To extract the data, must right shift the raw data by 4 bits (to + % get rid of the channel number and put the data value in the proper + % location). After this conversion, you must still add or subtract + % 2048, since otherwise the value is not right. (I think that this + % is because of the way that matlab handles negative values during + % the bitwise operations.) + % These calculations cause the results of ctx2txt.m to be the same as + % for cortview.exe for the EOG and EPP values. + + s = (i+1)/2; + epp1(s) = bitshift(epp(i), -4); + epp2(s) = bitshift(epp(i+1), -4); + + if (epp1(s) < 0) + epp1(s) = epp1(s) + 2047; + else + epp1(s) = epp1(s) - 2048; + end; + + if (epp2(s) < 0) + epp2(s) = epp2(s) + 2047; + else + epp2(s) = epp2(s) - 2048; + end; + end; + end; % if skipepp + + if skipeog || skiptrial + eog = []; + fseek (i_fid,header.eog_size * 2, 'cof'); + else + eog = fread (i_fid,header.eog_size, 'short'); + eog = reshape(eog, 2, header.eog_size/2); + end % if skipeog + + if ~skiptrial + % collect the headers of all trials in a structure array + cortex(trial+1).header = header; + cortex(trial+1).length = length; + cortex(trial+1).time = time; + cortex(trial+1).event = event; + cortex(trial+1).epp = [epp1; epp2]; + cortex(trial+1).eog = eog; + end + + trial = trial+1; + end; % if ~isempty(length) +end; + +fclose(i_fid); + +% remove the initial empty trials, i.e. the ones that were skipped +cortex = cortex(begtrial:end); + diff --git a/external/fieldtrip/fileio/private/read_nmc_archive_k_data.m b/external/fieldtrip/fileio/private/read_nmc_archive_k_data.m new file mode 100644 index 0000000..e85a385 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_nmc_archive_k_data.m @@ -0,0 +1,93 @@ +function [dat] = read_nmc_archive_k_data(datafile, hdr, begsample, endsample, channelsel) + +% READ_NMC_ARCHIVE_K_DATA reads data from nmc_archive_k datasets +% +% Used in read_data as +% dat = read_nmc_archive_k_data(datafile, hdr, begsample, endsample, channelsel); +% +% +% This function specifically only reads data from one of the archived +% datasets of the Neurophysiological Mechanisms of Cognition group of +% Eric Maris, at the Donders Centre for Cognition, Radboud University, +% Nijmegen, the Netherlands. It should not be used for any other data +% format. +% +% +% + +% Copyright (C) 2009, Roemer van der Meij +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_nmc_archive_k_data.m 945 2010-04-21 17:41:20Z roboos $ + + + +% Sanity checks (to be added) + + + +% Getting data-directory out of data-filename and check +datadir = datafile(1:(findstr(datafile, 'eeg.noreref')+11)); +if exist(datadir,'dir') ~= 7 + error('no proper data-directory provided, please check your paths'); +end + +% Getting session name + path out of data-filename +sessionpath = datafile(1:(end-4)); + + +% Build array containing channel file extensions to be used in reading the data +channelext = []; +% Remove the 'CH' from channel labels +chanlabnum = hdr.label; +for ichan = 1:length(chanlabnum) + chanlabnum{ichan} = chanlabnum(3:end); +end +for ichan = 1:length(channelsel) + if length(hdr.label{channelsel(ichan)}) == 3 + channelext{ichan} = ['.00' hdr.label{channelsel(ichan)}(3:end)]; + elseif length(hdr.label{channelsel(ichan)}) == 4 + channelext{ichan} = ['.0' hdr.label{channelsel(ichan)}(3:end)]; + elseif length(hdr.label{channelsel(ichan)}) == 5 + channelext{ichan} = ['.' hdr.label{channelsel(ichan)}(3:end)]; + end +end + +% Loop over channels while reading in data from file, 1 file per channel +dat = zeros(length(channelsel),(endsample-begsample+1)); +for ichan = 1:length(channelsel) + channelfile = [sessionpath channelext{ichan}]; + datafid = fopen(channelfile,'r','l'); + fseek(datafid,(hdr.nBytes*(begsample-1)),'bof'); + dat(ichan,:) = fread(datafid,(endsample-begsample+1),hdr.dataformat)'; + fclose(datafid); +end + + + + + + + + + + + + + + diff --git a/external/fileio/private/read_nmc_archive_k_event.m b/external/fieldtrip/fileio/private/read_nmc_archive_k_event.m similarity index 78% rename from external/fileio/private/read_nmc_archive_k_event.m rename to external/fieldtrip/fileio/private/read_nmc_archive_k_event.m index c322bd4..4074e6f 100644 --- a/external/fileio/private/read_nmc_archive_k_event.m +++ b/external/fieldtrip/fileio/private/read_nmc_archive_k_event.m @@ -13,8 +13,26 @@ % format. % % -% First version: 2009/09/31 - roevdmei + +% Copyright (C) 2009, Roemer van der Meij +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_nmc_archive_k_event.m 945 2010-04-21 17:41:20Z roboos $ % Checking events-file: @@ -63,7 +81,7 @@ end % ievent -% Send warning if no events are found for specified session +% Send warning if no events are found for current session if isempty(event) warning(['no events found for session: ' sessionname ' of subject: ' subjname]) -end \ No newline at end of file +end diff --git a/external/fileio/private/read_nmc_archive_k_hdr.m b/external/fieldtrip/fileio/private/read_nmc_archive_k_hdr.m similarity index 81% rename from external/fileio/private/read_nmc_archive_k_hdr.m rename to external/fieldtrip/fileio/private/read_nmc_archive_k_hdr.m index d1f96fe..dde23c7 100644 --- a/external/fileio/private/read_nmc_archive_k_hdr.m +++ b/external/fieldtrip/fileio/private/read_nmc_archive_k_hdr.m @@ -13,8 +13,26 @@ % format. % % -% First version: 2009/09/30 - roevdmei + +% Copyright (C) 2009, Roemer van der Meij +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: read_nmc_archive_k_hdr.m 945 2010-04-21 17:41:20Z roboos $ % Checking paramfile diff --git a/external/fieldtrip/fileio/private/read_ns_avg.m b/external/fieldtrip/fileio/private/read_ns_avg.m new file mode 100644 index 0000000..37007ff --- /dev/null +++ b/external/fieldtrip/fileio/private/read_ns_avg.m @@ -0,0 +1,80 @@ +function [avg] = read_ns_avg(filename) + +% READ_NS_AVG read a NeuroScan 3.x or 4.x AVG File +% +% [avg] = read_ns_avg(filename) +% +% The output data structure avg has the fields: +% avg.data - ERP signal in uV (Nchan x Npnt) +% avg.nsweeps - number of accepted trials/sweeps in avg +% avg.variance - variance of the signal (Nchan x Npnt) +% avg.label - electrode labels +% avg.nchan - number of channels +% avg.npnt - number of samplepoints in ERP waveform +% avg.rate - sample rate (Hz) +% avg.time - time for each sample OR +% avg.frequency - frequency for each sample +% hdr.domain - flag indicating time (0) or frequency (1) domain +% avg.xmin - prestimulus epoch start (e.g., -100 msec) +% avg.xmax - poststimulus epoch end (e.g., 900 msec) + +% Copyright (C) 2002, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_ns_avg.m 945 2010-04-21 17:41:20Z roboos $ + +% read the neuroscan header +avg = read_ns_hdr(filename); + +% create a time or frequency axis +if avg.domain==1 + avg.frequency = linspace(avg.xmin, avg.xmax, avg.npnt) / 1000; % in Hz instead of mili-Hz +else + avg.time = linspace(avg.xmin, avg.xmax, avg.npnt); % in ms +end + +% open the file and seek towards the place where the raw data is +fid = fopen(filename,'r','ieee-le'); +if fid<0 + error(['cannot open ', filename]); +else + fseek(fid, 900, 'cof'); % skip general header + fseek(fid, 75*avg.nchan, 'cof'); % skip channel headers +end; + +% read raw signal data and convert to uV +avg.data = zeros(avg.nchan, avg.npnt); +for elec = 1:avg.nchan + fseek(fid, 5, 'cof'); % skip sweeps header + raw = fread(fid, avg.npnt, 'float32'); + avg.data(elec,:) = (raw' - avg.baseline(elec)) * avg.calib(elec) / avg.nsweeps; +end; + +% read signal variance if present +if avg.variance + variance = zeros(avg.npnt, avg.nchan); + for elec = 1:avg.nchan, + variance(:, elec) = fread(fid, avg.npnt, 'float32'); + end; + avg.variance = variance'; +else + avg.variance = []; +end; + +fclose(fid); + diff --git a/external/fieldtrip/fileio/private/read_ns_eeg.m b/external/fieldtrip/fileio/private/read_ns_eeg.m new file mode 100644 index 0000000..bcde756 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_ns_eeg.m @@ -0,0 +1,117 @@ +function [eeg] = read_ns_eeg(filename, epoch) + +% READ_NS_EEG read a NeuroScan 3.x or 4.x EEG File +% +% [eeg] = read_ns_eeg(filename, epoch) +% +% filename input Neuroscan .eeg file (version 3.x) +% epoch which epoch to read (default is all) +% +% The output data structure eeg has the fields: +% eeg.data(..) - epoch signal in uV (size: Nepoch x Nchan x Npnt) +% and +% eeg.label - electrode labels +% eeg.nchan - number of channels +% eeg.npnt - number of samplepoints in ERP waveform +% eeg.time - time for each sample +% eeg.rate - sample rate (Hz) +% eeg.xmin - prestimulus epoch start (e.g., -100 msec) +% eeg.xmax - poststimulus epoch end (e.g., 900 msec) +% eeg.nsweeps - number of accepted trials/sweeps + +% Copyright (C) 2003, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_ns_eeg.m 945 2010-04-21 17:41:20Z roboos $ + +% read the neuroscan header +eeg = read_ns_hdr(filename); + +% clear the variance part which is empty anyway +eeg = rmfield(eeg, 'variance'); + +% create a time axis +eeg.time = linspace(eeg.xmin, eeg.xmax, eeg.npnt); + +% open the file and seek towards the place where the raw data is +fid = fopen(filename,'r','ieee-le'); +if fid<0 + error(['cannot open ', filename]); +end + +% the default is to read all epochs +if nargin<2 + epoch = 1:eeg.nsweeps; +end + +% determine whether it is 16 or 32 bit data +fseek(fid, 0, 'eof'); +header_size = 900 + 75*eeg.nchan; +file_size = ftell(fid); +sample_size = (file_size-header_size)/(eeg.nchan*eeg.npnt*eeg.nsweeps); +% note that the V4 format can have some extra information at the end of +% the file, causing the sample size to be slightly larger than 2 or 4 +if floor(sample_size)==2 + epoch_size = eeg.nchan*eeg.npnt*2 + 13; + datatype ='int16'; +elseif floor(sample_size)==4 + datatype ='int32'; + epoch_size = eeg.nchan*eeg.npnt*4 + 13; +end + +% create empty storage for the data +data = zeros(length(epoch), eeg.nchan, eeg.npnt); + +for i=1:length(epoch) + fseek(fid, 900, 'bof'); % skip general header + fseek(fid, 75*eeg.nchan, 'cof'); % skip channel headers + status = fseek(fid, (epoch(i)-1)*epoch_size, 'cof'); % skip first epochs + if status~=0 + error('seek error while reading epoch data'); + end + + % fprintf('reading epoch %d at offset %d\n', epoch(i), ftell(fid)); + + % read sweep header + sweep(i).accept = fread(fid, 1, 'uchar'); + sweep(i).type = fread(fid, 1, 'ushort'); + sweep(i).correct = fread(fid, 1, 'ushort'); + sweep(i).rt = fread(fid, 1, 'float32'); + sweep(i).response = fread(fid, 1, 'ushort'); + sweep(i).reserved = fread(fid, 1, 'ushort'); + + % read raw signal + raw = fread(fid, eeg.nchan*eeg.npnt, datatype); + if length(raw)~=eeg.nchan*eeg.npnt + error('fread error while reading epoch data'); + end + data(i,:,:) = reshape(raw, [eeg.nchan, eeg.npnt]); + +end + +% convert raw signal to uV +for chan=1:eeg.nchan + data(:,chan,:) = (data(:,chan,:) - eeg.baseline(chan)) * eeg.factor(chan); +end + +% store the epoch information and data in the output structure +eeg.data = squeeze(data); +eeg.sweep = squeeze(sweep'); + +fclose(fid); + diff --git a/external/fieldtrip/fileio/private/read_ns_hdr.m b/external/fieldtrip/fileio/private/read_ns_hdr.m new file mode 100644 index 0000000..691867f --- /dev/null +++ b/external/fieldtrip/fileio/private/read_ns_hdr.m @@ -0,0 +1,318 @@ +function [hdr] = read_ns_hdr(filename) + +% READ_NS_HDR read the header from a NeuroScan 3.x or 4.x AVG/EEG/CNT File +% +% [hdr] = read_ns_hdr(filename) +% +% The output data structure hdr has the fields: +% hdr.label - electrode labels +% hdr.nchan - number of channels +% hdr.npnt - number of samplepoints in ERP waveform +% hdr.rate - sample rate (Hz) +% hdr.xmin - prestimulus epoch start (e.g., -100 msec) +% hdr.xmax - poststimulus epoch end (e.g., 900 msec) +% hdr.nsweeps - number of accepted trials/sweeps +% hdr.domain - time (0) or frequency (1) domain + +% Copyright (C) 2002, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_ns_hdr.m 945 2010-04-21 17:41:20Z roboos $ + +fid = fopen(filename,'r','ieee-le'); + +if fid<0, + error(['cannot open ', filename]); +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% these structures are from Neuroscan sethead.h +% the first two columns are the size in bytes and the offset +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% GENERAL SETUP STRUCTURE, total 900 bytes +% 0 20 | char rev[20]; /* Revision string */ +% 20 1 | char type; /* File type AVG=1, EEG=0 */ +% 21 20 | char id[20]; /* Patient ID */ +% 41 20 | char oper[20]; /* Operator ID */ +% 61 20 | char doctor[20]; /* Doctor ID */ +% 81 20 | char referral[20]; /* Referral ID */ +% 101 20 | char hospital[20]; /* Hospital ID */ +% 121 20 | char patient[20]; /* Patient name */ +% 141 2 | short int age; /* Patient Age */ +% 143 1 | char sex; /* Patient Sex Male='M', Female='F' */ +% 144 1 | char hand; /* Handedness Mixed='M',Rt='R', lft='L' */ +% 145 20 | char med[20]; /* Medications */ +% 165 20 | char class[20]; /* Classification */ +% 185 20 | char state[20]; /* Patient wakefulness */ +% 205 20 | char label[20]; /* Session label */ +% 225 10 | char date[10]; /* Session date string */ +% 235 12 | char time[12]; /* Session time strin */ +% 247 4 | float mean_age; /* Mean age (Group files only) */ +% 251 4 | float stdev; /* Std dev of age (Group files only) */ +% 255 2 | short int n; /* Number in group file */ +% 257 38 | char compfile[38]; /* Path and name of comparison file */ +% 295 4 | float SpectWinComp; // Spectral window compensation factor +% 299 4 | float MeanAccuracy; // Average respose accuracy +% 303 4 | float MeanLatency; // Average response latency +% 307 46 | char sortfile[46]; /* Path and name of sort file */ +% 353 4 | int NumEvents; // Number of events in eventable +% 357 1 | char compoper; /* Operation used in comparison */ +% 358 1 | char avgmode; /* Set during online averaging */ +% 359 1 | char review; /* Set during review of EEG data */ +% 360 2 | short unsigned nsweeps; /* Number of expected sweeps */ +% 362 2 | short unsigned compsweeps; /* Number of actual sweeps */ +% 364 2 | short unsigned acceptcnt; /* Number of accepted sweeps */ +% 366 2 | short unsigned rejectcnt; /* Number of rejected sweeps */ +% 368 2 | short unsigned pnts; /* Number of points per waveform */ +% 370 2 | short unsigned nchannels; /* Number of active channels */ +% 372 2 | short unsigned avgupdate; /* Frequency of average update */ +% 374 1 | char domain; /* Acquisition domain TIME=0, FREQ=1 */ +% 375 1 | char variance; /* Variance data included flag */ +% 376 2 | unsigned short rate; /* D-to-A rate */ +% 378 8 | double scale; /* scale factor for calibration */ +% 386 1 | char veogcorrect; /* VEOG corrected flag */ +% 387 1 | char heogcorrect; /* HEOG corrected flag */ +% 388 1 | char aux1correct; /* AUX1 corrected flag */ +% 389 1 | char aux2correct; /* AUX2 corrected flag */ +% 390 4 | float veogtrig; /* VEOG trigger percentage */ +% 394 4 | float heogtrig; /* HEOG trigger percentage */ +% 398 4 | float aux1trig; /* AUX1 trigger percentage */ +% 402 4 | float aux2trig; /* AUX2 trigger percentage */ +% 406 2 | short int heogchnl; /* HEOG channel number */ +% 408 2 | short int veogchnl; /* VEOG channel number */ +% 410 2 | short int aux1chnl; /* AUX1 channel number */ +% 412 2 | short int aux2chnl; /* AUX2 channel number */ +% 414 1 | char veogdir; /* VEOG trigger direction flag */ +% 415 1 | char heogdir; /* HEOG trigger direction flag */ +% 416 1 | char aux1dir; /* AUX1 trigger direction flag */ +% 417 1 | char aux2dir; /* AUX2 trigger direction flag */ +% 418 2 | short int veog_n; /* Number of points per VEOG waveform */ +% 420 2 | short int heog_n; /* Number of points per HEOG waveform */ +% 422 2 | short int aux1_n; /* Number of points per AUX1 waveform */ +% 424 2 | short int aux2_n; /* Number of points per AUX2 waveform */ +% 426 2 | short int veogmaxcnt; /* Number of observations per point - VEOG */ +% 428 2 | short int heogmaxcnt; /* Number of observations per point - HEOG */ +% 430 2 | short int aux1maxcnt; /* Number of observations per point - AUX1 */ +% 432 2 | short int aux2maxcnt; /* Number of observations per point - AUX2 */ +% 434 1 | char veogmethod; /* Method used to correct VEOG */ +% 435 1 | char heogmethod; /* Method used to correct HEOG */ +% 436 1 | char aux1method; /* Method used to correct AUX1 */ +% 437 1 | char aux2method; /* Method used to correct AUX2 */ +% 438 4 | float AmpSensitivity; /* External Amplifier gain */ +% 442 1 | char LowPass; /* Toggle for Amp Low pass filter */ +% 443 1 | char HighPass; /* Toggle for Amp High pass filter */ +% 444 1 | char Notch; /* Toggle for Amp Notch state */ +% 445 1 | char AutoClipAdd; /* AutoAdd on clip */ +% 446 1 | char baseline; /* Baseline correct flag */ +% 447 4 | float offstart; /* Start point for baseline correction */ +% 451 4 | float offstop; /* Stop point for baseline correction */ +% 455 1 | char reject; /* Auto reject flag */ +% 456 4 | float rejstart; /* Auto reject start point */ +% 460 4 | float rejstop; /* Auto reject stop point */ +% 464 4 | float rejmin; /* Auto reject minimum value */ +% 468 4 | float rejmax; /* Auto reject maximum value */ +% 472 1 | char trigtype; /* Trigger type */ +% 473 4 | float trigval; /* Trigger value */ +% 477 1 | char trigchnl; /* Trigger channel */ +% 478 2 | short int trigmask; /* Wait value for LPT port */ +% 480 4 | float trigisi; /* Interstimulus interval (INT trigger) */ +% 484 4 | float trigmin; /* Min trigger out voltage (start of pulse)*/ +% 488 4 | float trigmax; /* Max trigger out voltage (during pulse) */ +% 492 1 | char trigdir; /* Duration of trigger out pulse */ +% 493 1 | char Autoscale; /* Autoscale on average */ +% 494 2 | short int n2; /* Number in group 2 (MANOVA) */ +% 496 1 | char dir; /* Negative display up or down */ +% 497 4 | float dispmin; /* Display minimum (Yaxis) */ +% 501 4 | float dispmax; /* Display maximum (Yaxis) */ +% 505 4 | float xmin; /* X axis minimum (epoch start in sec) */ +% 509 4 | float xmax; /* X axis maximum (epoch stop in sec) */ +% 513 4 | float AutoMin; /* Autoscale minimum */ +% 517 4 | float AutoMax; /* Autoscale maximum */ +% 521 4 | float zmin; /* Z axis minimum - Not currently used */ +% 525 4 | float zmax; /* Z axis maximum - Not currently used */ +% 529 4 | float lowcut; /* Archival value - low cut on external amp*/ +% 533 4 | float highcut; /* Archival value - Hi cut on external amp */ +% 537 1 | char common; /* Common mode rejection flag */ +% 538 1 | char savemode; /* Save mode EEG AVG or BOTH */ +% 539 1 | char manmode; /* Manual rejection of incomming data */ +% 540 10 | char ref[10]; /* Label for reference electode */ +% 550 1 | char Rectify; /* Rectification on external channel */ +% 551 4 | float DisplayXmin; /* Minimun for X-axis display */ +% 555 4 | float DisplayXmax; /* Maximum for X-axis display */ +% 559 1 | char phase; /* flag for phase computation */ +% 560 16 | char screen[16]; /* Screen overlay path name */ +% 576 2 | short int CalMode; /* Calibration mode */ +% 578 2 | short int CalMethod; /* Calibration method */ +% 580 2 | short int CalUpdate; /* Calibration update rate */ +% 582 2 | short int CalBaseline; /* Baseline correction during cal */ +% 584 2 | short int CalSweeps; /* Number of calibration sweeps */ +% 586 4 | float CalAttenuator; /* Attenuator value for calibration */ +% 590 4 | float CalPulseVolt; /* Voltage for calibration pulse */ +% 594 4 | float CalPulseStart; /* Start time for pulse */ +% 598 4 | float CalPulseStop; /* Stop time for pulse */ +% 602 4 | float CalFreq; /* Sweep frequency */ +% 606 34 | char taskfile[34]; /* Task file name */ +% 640 34 | char seqfile[34]; /* Sequence file path name */ +% 674 1 | char SpectMethod; // Spectral method +% 675 1 | char SpectScaling; // Scaling employed +% 676 1 | char SpectWindow; // Window employed +% 677 4 | float SpectWinLength; // Length of window % +% 681 1 | char SpectOrder; // Order of Filter for Max Entropy method +% 682 1 | char NotchFilter; // Notch Filter in or out +% 683 11 | char unused[11]; // Free space +% 694 2 | short FspStopMethod; /* FSP - Stoping mode */ +% 696 2 | short FspStopMode; /* FSP - Stoping mode */ +% 698 4 | float FspFValue; /* FSP - F value to stop terminate */ +% 702 2 | short int FspPoint; /* FSP - Single point location */ +% 704 2 | short int FspBlockSize; /* FSP - block size for averaging */ +% 706 2 | unsigned short FspP1; /* FSP - Start of window */ +% 708 2 | unsigned short FspP2; /* FSP - Stop of window */ +% 710 4 | float FspAlpha; /* FSP - Alpha value */ +% 714 4 | float FspNoise; /* FSP - Signal to ratio value */ +% 718 2 | short int FspV1; /* FSP - degrees of freedom */ +% 720 40 | char montage[40]; /* Montage file path name */ +% 760 40 | char EventFile[40]; /* Event file path name */ +% 800 4 | float fratio; /* Correction factor for spectral array */ +% 804 1 | char minor_rev; /* Current minor revision */ +% 805 2 | short int eegupdate; /* How often incomming eeg is refreshed */ +% 807 1 | char compressed; /* Data compression flag */ +% 808 4 | float xscale; /* X position for scale box - Not used */ +% 812 4 | float yscale; /* Y position for scale box - Not used */ +% 816 4 | float xsize; /* Waveform size X direction */ +% 820 4 | float ysize; /* Waveform size Y direction */ +% 824 1 | char ACmode; /* Set SYNAP into AC mode */ +% 825 1 | unsigned char CommonChnl; /* Channel for common waveform */ +% 826 1 | char Xtics; /* Scale tool- 'tic' flag in X direction */ +% 827 1 | char Xrange; /* Scale tool- range (ms,sec,Hz) flag X dir*/ +% 828 1 | char Ytics; /* Scale tool- 'tic' flag in Y direction */ +% 829 1 | char Yrange; /* Scale tool- range (uV, V) flag Y dir */ +% 830 4 | float XScaleValue; /* Scale tool- value for X dir */ +% 834 4 | float XScaleInterval; /* Scale tool- interval between tics X dir */ +% 838 4 | float YScaleValue; /* Scale tool- value for Y dir */ +% 842 4 | float YScaleInterval; /* Scale tool- interval between tics Y dir */ +% 846 4 | float ScaleToolX1; /* Scale tool- upper left hand screen pos */ +% 850 4 | float ScaleToolY1; /* Scale tool- upper left hand screen pos */ +% 854 4 | float ScaleToolX2; /* Scale tool- lower right hand screen pos */ +% 858 4 | float ScaleToolY2; /* Scale tool- lower right hand screen pos */ +% 862 2 | short int port; /* Port address for external triggering */ +% 864 4 | long NumSamples; /* Number of samples in continous file */ +% 868 1 | char FilterFlag; /* Indicates that file has been filtered */ +% 869 4 | float LowCutoff; /* Low frequency cutoff */ +% 873 2 | short int LowPoles; /* Number of poles */ +% 875 4 | float HighCutoff; /* High frequency cutoff */ +% 879 2 | short int HighPoles; /* High cutoff number of poles */ +% 881 1 | char FilterType; /* Bandpass=0 Notch=1 Highpass=2 Lowpass=3 */ +% 882 1 | char FilterDomain; /* Frequency=0 Time=1 */ +% 883 1 | char SnrFlag; /* SNR computation flag */ +% 884 1 | char CoherenceFlag; /* Coherence has been computed */ +% 885 1 | char ContinousType; /* Method used to capture events in *.cnt */ +% 886 4 | long EventTablePos; /* Position of event table */ +% 890 4 | float ContinousSeconds; // Number of seconds to displayed per page +% 894 4 | long ChannelOffset; // Block size of one channel in SYNAMPS +% 898 1 | char AutoCorrectFlag; // Autocorrect of DC values +% 899 1 | unsigned char DCThreshold; // Auto correct of DC level + +% ELECTRODE STRUCTURE, total 75 bytes +% 10 0 | char lab[10]; /* Electrode label - last bye contains NULL */ +% 1 10 | char reference; /* Reference electrode number */ +% 1 11 | char skip; /* Skip electrode flag ON=1 OFF=0 */ +% 1 12 | char reject; /* Artifact reject flag */ +% 1 13 | char display; /* Display flag for 'STACK' display */ +% 1 14 | char bad; /* Bad electrode flag */ +% 2 15 | unsigned short int n; /* Number of observations */ +% 1 17 | char avg_reference; /* Average reference status */ +% 1 18 | char ClipAdd; /* Automatically add to clipboard */ +% 4 19 | float x_coord; /* X screen coord. for 'TOP' display */ +% 4 23 | float y_coord; /* Y screen coord. for 'TOP' display */ +% 4 27 | float veog_wt; /* VEOG correction weight */ +% 4 31 | float veog_std; /* VEOG std dev. for weight */ +% 4 35 | float snr; /* signal-to-noise statistic */ +% 4 39 | float heog_wt; /* HEOG Correction weight */ +% 4 43 | float heog_std; /* HEOG Std dev. for weight */ +% 2 47 | short int baseline; /* Baseline correction value in raw ad units*/ +% 1 49 | char Filtered; /* Toggel indicating file has be filtered */ +% 1 50 | char Fsp; /* Extra data */ +% 4 51 | float aux1_wt; /* AUX1 Correction weight */ +% 4 54 | float aux1_std; /* AUX1 Std dev. for weight */ +% 4 59 | float sensitivity; /* electrode sensitivity */ +% 1 63 | char Gain; /* Amplifier gain */ +% 1 64 | char HiPass; /* Hi Pass value */ +% 1 65 | char LoPass; /* Lo Pass value */ +% 1 66 | unsigned char Page; /* Display page */ +% 1 67 | unsigned char Size; /* Electrode window display size */ +% 1 68 | unsigned char Impedance;/* Impedance test */ +% 1 69 | unsigned char PhysicalChnl; /* Physical channel used */ +% 1 70 | char Rectify; /* Free space */ +% 4 71 | float calib; /* Calibration factor */ + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% read general parameters +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +offset_type = 20; +offset_nsweeps = 364; +offset_pnts = 368; +offset_nchans = 370; +offset_domain = 374; +offset_variance = 375; +offset_rate = 376; +offset_xmin = 505; +offset_xmax = 509; +fseek(fid, offset_type, 'bof'); type = fread(fid, 1, 'ushort'); +fseek(fid, offset_nsweeps, 'bof'); hdr.nsweeps = fread(fid, 1, 'ushort'); +fseek(fid, offset_pnts, 'bof'); hdr.npnt = fread(fid, 1, 'ushort'); +fseek(fid, offset_nchans, 'bof'); hdr.nchan = fread(fid, 1, 'ushort'); +fseek(fid, offset_domain, 'bof'); hdr.domain = fread(fid, 1, 'uchar'); +fseek(fid, offset_variance, 'bof'); hdr.variance = fread(fid, 1, 'uchar'); +fseek(fid, offset_rate, 'bof'); hdr.rate = fread(fid, 1, 'ushort'); +fseek(fid, offset_xmin, 'bof'); hdr.xmin = fread(fid, 1, 'float32') * 1000; +fseek(fid, offset_xmax, 'bof'); hdr.xmax = fread(fid, 1, 'float32') * 1000; +fseek(fid, offset_xmax, 'bof'); hdr.xmax = fread(fid, 1, 'float32') * 1000; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% read electrode configuration +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +hdr.label = {}; +for elec = 1:hdr.nchan, + offset_label = 900+(elec-1)*75 + 0; + offset_baseline = 900+(elec-1)*75 + 47; + offset_sens = 900+(elec-1)*75 + 59; + offset_calib = 900+(elec-1)*75 + 71; + fseek(fid, offset_label, 'bof'); lab = fread(fid, 10, 'uchar'); lab(find(lab==0)) = ' '; + fseek(fid, offset_baseline, 'bof'); hdr.baseline(elec) = fread(fid, 1, 'ushort'); + fseek(fid, offset_sens, 'bof'); hdr.sensitivity(elec) = fread(fid, 1, 'float32'); + fseek(fid, offset_calib, 'bof'); hdr.calib(elec) = fread(fid, 1, 'float32'); + hdr.label{elec} = fliplr(deblank(fliplr(deblank(char(lab'))))); + hdr.factor(elec) = hdr.calib(elec) * hdr.sensitivity(elec) / 204.8; +end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% try to infer whether time or frequency data is represented +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +if hdr.domain==0 + % data in time domain +elseif hdr.domain==1 + % data in frequency domain +else + % probably old datafile, assume the data to be in time domain + warning(sprintf('assuming the data to be in time domain (domain was %d)', hdr.domain)); + hdr.domain=0; +end + +fclose(fid); + diff --git a/external/fieldtrip/fileio/private/read_off.m b/external/fieldtrip/fileio/private/read_off.m new file mode 100644 index 0000000..1805593 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_off.m @@ -0,0 +1,57 @@ +function [pnt, dhk] = read_off(fn); + +% READ_OFF reads vertices and triangles from a OFF format triangulation file +% +% [pnt, dhk] = read_off(filename) +% +% See also READ_TRI, READ_BND + +% Copyright (C) 1998, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_off.m 945 2010-04-21 17:41:20Z roboos $ + +fid = fopen(fn, 'rt'); +if fid~=-1 + + % scan the file type + [s, count] = fscanf(fid, '%s\n', 1); + if ~strcmp(s,'OFF') + msg = sprintf('wrong file type %s', s); + error(msg); + end + + % read the number of vertex points and triangles + [val, count] = fscanf(fid, '%d', 3); + Npnt = val(1) + Ndhk = val(2) + + % read the vertex points + pnt = fscanf(fid, '%f', [3, Npnt]); + pnt = pnt(1:3,:)'; + + % read the triangles + dhk = fscanf(fid, '%d', [4, Ndhk]); + dhk = (dhk(2:4,:)+1)'; + fclose(fid); + +else + error('unable to open file'); +end + + diff --git a/external/fileio/private/read_plexon_ddt.m b/external/fieldtrip/fileio/private/read_plexon_ddt.m similarity index 85% rename from external/fileio/private/read_plexon_ddt.m rename to external/fieldtrip/fileio/private/read_plexon_ddt.m index e625acb..2eacaa4 100644 --- a/external/fileio/private/read_plexon_ddt.m +++ b/external/fieldtrip/fileio/private/read_plexon_ddt.m @@ -14,22 +14,23 @@ % Copyright (C) 2005-2007, Robert Oostenveld % -% $Log: read_plexon_ddt.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.3 2007/01/03 16:57:58 roboos -% improved documentation +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.2 2005/09/08 16:52:51 roboos -% added support for subformat versions 101, 102 and 103 +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.1 2005/09/06 12:40:39 roboos -% renamed plextor into plexon (i.e. it had an incorrect company name) -% -% Revision 1.1 2005/09/02 16:36:04 roboos -% new implementation, only for version 100 +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: read_plexon_ddt.m 945 2010-04-21 17:41:20Z roboos $ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Version 100: Samples are assumed to be 12 bits. All channels have the same NIDAQ gain, and preamp diff --git a/external/fieldtrip/fileio/private/read_plexon_ds.m b/external/fieldtrip/fileio/private/read_plexon_ds.m new file mode 100644 index 0000000..7cb527f --- /dev/null +++ b/external/fieldtrip/fileio/private/read_plexon_ds.m @@ -0,0 +1,174 @@ +function [dat] = read_plexon_ds(dirname, hdr, begsample, endsample, chanindx) + +% READ_PLEXON_DS reads multiple single-channel Plexon files that are +% all contained in a single directory. Each file is treated as a single +% channel of a combined multi-channel dataset. +% +% Use as +% hdr = read_plexon_ds(dirname) +% dat = read_plexon_ds(dirname, hdr, begsample, endsample, chanindx) +% +% See also READ_PLEXON_NEX, READ_PLEXON_PLX, READ_PLEXON_DDT + +% Copyright (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_plexon_ds.m 945 2010-04-21 17:41:20Z roboos $ + +needhdr = (nargin==1); +needdat = (nargin>=2); + +if needhdr + % get the list of filenames + ls = dir(dirname); + ls = ls(~cell2mat({ls.isdir})); + fname = {}; + for i=1:length(ls) + fname{i} = fullfile(dirname, ls(i).name); + end + + ftype = zeros(length(fname), 1); + for i=1:length(fname) + % determine the filetype only based on the extension, not using the filetype function because that is much slower + if filetype_check_extension(fname{i}, '.nex') + ftype(i) = 1; + elseif filetype_check_extension(fname{i}, '.plx') + ftype(i) = 2; + elseif filetype_check_extension(fname{i}, '.ddt') + ftype(i) = 3; + end + end + + % only remember the filenames that are relevant + fname = fname(ftype>0); + ftype = ftype(ftype>0); + + if isempty(fname) + error('the directory contains no supported files'); + elseif any(ftype~=1) + error('only nex files are supported in a plexon dataset directory'); + end + + for i=1:length(fname) + % this will only work if all files within a dataset return a similar header structure + switch ftype(i) + case 1 + orig(i) = read_plexon_nex(fname{i}); + case 'plexon_plx' + error('plx files are not supported in plexon dataset directory'); + case 'plexon_ddt' + error('ddt files are not supported in plexon dataset directory'); + otherwise + error('unsupported file in plexon dataset directory'); + end + end + + for i=1:length(fname) + if length(orig(i).VarHeader)>1 + error('multiple channels in a single NEX file not supported'); + else + % combine the information from the different files in a single header + label{i} = deblank(orig(i).VarHeader.Name); + Type(i) = orig(i).VarHeader.Type; + WFrequency(i) = orig(i).VarHeader.WFrequency; % of the waveform + ADBitVolts(i) = orig(i).VarHeader.ADtoMV; + NPointsWave(i) = orig(i).VarHeader.NPointsWave; + Beg(i) = orig(i).FileHeader.Beg; + End(i) = orig(i).FileHeader.End; + Frequency(i) = orig(i).FileHeader.Frequency; % of the timestamps + end + end + + if any(Type~=5) + error('not all channels contain continuous data'); + end + + if any(WFrequency~=WFrequency(1)) + warning('not all channels have the same sampling rate'); + end + + if any(Frequency~=Frequency(1)) + warning('not all channels have the same timestamp rate'); + end + + if any(Beg~=Beg(1)) + warning('not all channels start at the same time'); + end + + if any(End~=End(1)) + warning('not all channels end at the same time'); + end + + if any(NPointsWave~=NPointsWave(1)) + warning('not all channels have the same number of samples'); + end + + % construct the header that applies to all channels combined + hdr.label = label; + hdr.nChans = length(label); + hdr.nSamples = NPointsWave(1); + hdr.nSamplesPre = 0; % it is continuous + hdr.nTrials = 1; % it is continuous + hdr.Fs = WFrequency(1); + hdr.FirstTimeStamp = Beg(1); + hdr.LastTimeStamp = End(1); % FIXME this is often not correct + hdr.TimeStampPerSample = Frequency(1)/WFrequency(1); + hdr.filename = fname; + + % remember the filename and filetype to speed up subsequent calls for reading the data + hdr.filetype = cell(size(fname)); + hdr.filetype(ftype==1) = {'plexon_nex'}; + hdr.filetype(ftype==2) = {'plexon_plx'}; + hdr.filetype(ftype==3) = {'plexon_ddt'}; + + % remember the original header details + hdr.orig = orig(:); + + % return the header + dat = hdr; + +else + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % read the data of the selected channels (i.e. files) + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + if nargin<5 + % select all channels + chanindx = 1:length(hdr.label); + end + nchan = length(chanindx); + nsample = endsample-begsample+1; + dat = zeros(nchan, nsample); + + for i=1:nchan + thischan = chanindx(i); + thisfile = hdr.filename{thischan}; + thistype = hdr.filetype{thischan}; + + switch thistype + case 'plexon_nex' + nex = read_plexon_nex(thisfile, 'header', hdr.orig(thischan), 'channel', 1, 'begsample', begsample, 'endsample', endsample); % always read the first and only channel + dat(i,:) = nex.dat; + case 'plexon_plx' + error('plx files are not supported in plexon dataset directory'); + case 'plexon_ddt' + error('ddt files are not supported in plexon dataset directory'); + otherwise + error('unsupported file in plexon dataset directory'); + end + end +end diff --git a/external/fieldtrip/fileio/private/read_plexon_nex.m b/external/fieldtrip/fileio/private/read_plexon_nex.m new file mode 100644 index 0000000..2a0da10 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_plexon_nex.m @@ -0,0 +1,192 @@ +function [varargout] = read_plexon_nex(filename, varargin) + +% READ_PLEXON_NEX reads header or data from a Plexon *.nex file, which +% is a file containing action-potential (spike) timestamps and waveforms +% (spike channels), event timestamps (event channels), and continuous +% variable data (continuous A/D channels). +% +% LFP and spike waveform data that is returned by this function is +% expressed in microVolt. +% +% Use as +% [hdr] = read_plexon_nex(filename) +% [dat] = read_plexon_nex(filename, ...) +% [dat1, dat2, dat3, hdr] = read_plexon_nex(filename, ...) +% +% Optional arguments should be specified in key-value pairs and can be +% header structure with header information +% feedback 0 or 1 +% tsonly 0 or 1, read only the timestamps and not the waveforms +% channel number, or list of numbers (that will result in multiple outputs) +% begsample number (for continuous only) +% endsample number (for continuous only) +% +% See also READ_PLEXON_PLX, READ_PLEXON_DDT + +% Copyright (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_plexon_nex.m 945 2010-04-21 17:41:20Z roboos $ + +% parse the optional input arguments +hdr = keyval('header', varargin); +channel = keyval('channel', varargin); +feedback = keyval('feedback', varargin); +tsonly = keyval('tsonly', varargin); +begsample = keyval('begsample', varargin); +endsample = keyval('endsample', varargin); + +% set the defaults +if isempty(feedback) + feedback=0; +end +if isempty(tsonly) + tsonly=0; +end +if isempty(begsample) + begsample=1; +end +if isempty(endsample) + endsample=Inf; +end + +% start with empty return values and empty data +varargout = {}; + +% read header info from file, use Matlabs for automatic byte-ordering +fid = fopen(filename, 'r', 'ieee-le'); +fseek(fid, 0, 'eof'); +siz = ftell(fid); +fseek(fid, 0, 'bof'); + +if isempty(hdr) + if feedback, fprintf('reading header from %s\n', filename); end + % a NEX file consists of a file header, followed by a number of variable headers + % sizeof(NexFileHeader) = 544 + % sizeof(NexVarHeader) = 208 + hdr.FileHeader = NexFileHeader(fid); + if hdr.FileHeader.NumVars<1 + error('no channels present in file'); + end + hdr.VarHeader = NexVarHeader(fid, hdr.FileHeader.NumVars); +end + +for i=1:length(channel) + chan = channel(i); + vh = hdr.VarHeader(chan); + clear buf + fseek(fid, vh.DataOffset, 'bof'); + switch vh.Type + case 0 + % Neurons, only timestamps + buf.ts = fread(fid, [1 vh.Count], 'int32=>int32'); + + case 1 + % Events, only timestamps + buf.ts = fread(fid, [1 vh.Count], 'int32=>int32'); + + case 2 + % Interval variables + buf.begs = fread(fid, [1 vh.Count], 'int32=>int32'); + buf.ends = fread(fid, [1 vh.Count], 'int32=>int32'); + + case 3 + % Waveform variables + buf.ts = fread(fid, [1 vh.Count], 'int32=>int32'); + if ~tsonly + buf.dat = fread(fid, [vh.NPointsWave vh.Count], 'int16'); + % convert the AD values to miliVolt, subsequently convert from miliVolt to microVolt + buf.dat = buf.dat * (vh.ADtoMV * 1000); + end + + case 4 + % Population vector + error('population vectors are not supported'); + + case 5 + % Continuously recorded variables + buf.ts = fread(fid, [1 vh.Count], 'int32=>int32'); + buf.indx = fread(fid, [1 vh.Count], 'int32=>int32'); + if vh.Count>1 && (begsample~=1 || endsample~=inf) + error('reading selected samples from multiple AD segments is not supported'); + end + if ~tsonly + numsample = min(endsample - begsample + 1, vh.NPointsWave); + fseek(fid, (begsample-1)*2, 'cof'); + buf.dat = fread(fid, [1 numsample], 'int16'); + % convert the AD values to miliVolt, subsequently convert from miliVolt to microVolt + buf.dat = buf.dat * (vh.ADtoMV * 1000); + end + + case 6 + % Markers + ts = fread(fid, [1 vh.Count], 'int32=>int32'); + for j=1:vh.NMarkers + buf.MarkerNames{j,1} = fread(fid, [1 64], 'uint8=>char'); + for k=1:vh.Count + buf.MarkerValues{j,k} = fread(fid, [1 vh.MarkerLength], 'uint8=>char'); + end + end + + otherwise + error('incorrect channel type'); + end % switch channel type + + % return the data of this channel + varargout{i} = buf; +end % for channel + +% always return the header as last +varargout{end+1} = hdr; + +fclose(fid); +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function hdr = NexFileHeader(fid); +hdr.NexFileHeader = fread(fid,4,'uint8=>char')'; % string NEX1 +hdr.Version = fread(fid,1,'int32'); +hdr.Comment = fread(fid,256,'uint8=>char')'; +hdr.Frequency = fread(fid,1,'double'); % timestamped freq. - tics per second +hdr.Beg = fread(fid,1,'int32'); % usually 0 +hdr.End = fread(fid,1,'int32'); % maximum timestamp + 1 +hdr.NumVars = fread(fid,1,'int32'); % number of variables in the first batch +hdr.NextFileHeader = fread(fid,1,'int32'); % position of the next file header in the file, not implemented yet +Padding = fread(fid,256,'uint8=>char')'; % future expansion + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function hdr = NexVarHeader(fid, numvar); +for varlop=1:numvar + hdr(varlop).Type = fread(fid,1,'int32'); % 0 - neuron, 1 event, 2- interval, 3 - waveform, 4 - pop. vector, 5 - continuously recorded + hdr(varlop).Version = fread(fid,1,'int32'); % 100 + hdr(varlop).Name = fread(fid,64,'uint8=>char')'; % variable name + hdr(varlop).DataOffset = fread(fid,1,'int32'); % where the data array for this variable is located in the file + hdr(varlop).Count = fread(fid,1,'int32'); % number of events, intervals, waveforms or weights + hdr(varlop).WireNumber = fread(fid,1,'int32'); % neuron only, not used now + hdr(varlop).UnitNumber = fread(fid,1,'int32'); % neuron only, not used now + hdr(varlop).Gain = fread(fid,1,'int32'); % neuron only, not used now + hdr(varlop).Filter = fread(fid,1,'int32'); % neuron only, not used now + hdr(varlop).XPos = fread(fid,1,'double'); % neuron only, electrode position in (0,100) range, used in 3D + hdr(varlop).YPos = fread(fid,1,'double'); % neuron only, electrode position in (0,100) range, used in 3D + hdr(varlop).WFrequency = fread(fid,1,'double'); % waveform and continuous vars only, w/f sampling frequency + hdr(varlop).ADtoMV = fread(fid,1,'double'); % waveform continuous vars only, coeff. to convert from A/D values to Millivolts + hdr(varlop).NPointsWave = fread(fid,1,'int32'); % waveform only, number of points in each wave + hdr(varlop).NMarkers = fread(fid,1,'int32'); % how many values are associated with each marker + hdr(varlop).MarkerLength = fread(fid,1,'int32'); % how many characters are in each marker value + Padding = fread(fid,68,'uint8=>char')'; +end diff --git a/external/fileio/private/read_plexon_plx.m b/external/fieldtrip/fileio/private/read_plexon_plx.m similarity index 91% rename from external/fileio/private/read_plexon_plx.m rename to external/fieldtrip/fileio/private/read_plexon_plx.m index 7ca346e..3edfa3e 100644 --- a/external/fileio/private/read_plexon_plx.m +++ b/external/fieldtrip/fileio/private/read_plexon_plx.m @@ -19,45 +19,23 @@ % Copyright (C) 2007, Robert Oostenveld % -% $Log: read_plexon_plx.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.8 2008/09/30 08:01:04 roboos -% replaced all fread(char=>char) into uint8=>char to ensure that the -% chars are read as 8 bits and not as extended 16 bit characters. The -% 16 bit handling causes problems on some internationalized OS/Matlab -% combinations. +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% the help of fread specifies "If the precision is 'char' or 'char*1', MATLAB -% reads characters using the encoding scheme associated with the file. -% See FOPEN for more information". +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.7 2007/03/26 12:32:13 roboos -% changed some documentation, whitespace and comments -% output in multiple output arguments instead of a single cell-array (for consistency with nex reader) -% -% Revision 1.6 2007/03/19 17:11:54 roboos -% made the datablock header reader the same for regular and memmapped files -% fixed the timestamps for memmapped files -% -% Revision 1.5 2007/03/18 22:05:28 roboos -% avoid one call to double() -% fixed bug in variable name (mixed up spike and slow channel, only in feedback) -% also deal with spike channels that do not contain any data -% -% Revision 1.4 2007/03/14 16:10:54 roboos -% do re-allocation in larger chuncks -% -% Revision 1.3 2007/01/09 09:44:10 roboos -% use multiple output arguments, made feedback optional, represent values in DataBlockHeader as int16 if possible (save some memory) -% -% Revision 1.2 2007/01/04 12:08:43 roboos -% implemented memory mapped reading of block header info, implented direct reading of data, timestamps as uint16 and uint32 -% -% Revision 1.1 2007/01/03 16:58:15 roboos -% new implementation +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: read_plexon_plx.m 945 2010-04-21 17:41:20Z roboos $ % parse the optional input arguments hdr = keyval('header', varargin); diff --git a/external/fileio/private/read_polhemus_fil.m b/external/fieldtrip/fileio/private/read_polhemus_fil.m similarity index 97% rename from external/fileio/private/read_polhemus_fil.m rename to external/fieldtrip/fileio/private/read_polhemus_fil.m index 0b5c8cb..28dad14 100644 --- a/external/fileio/private/read_polhemus_fil.m +++ b/external/fieldtrip/fileio/private/read_polhemus_fil.m @@ -27,8 +27,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Jeremie Mattout -% $Id: read_polhemus_fil.m,v 1.1 2009/01/14 09:12:15 roboos Exp $ - +% $Id: read_polhemus_fil.m 945 2010-04-21 17:41:20Z roboos $ % checks and assigments %-------------------------------------------------------------------------- @@ -40,7 +39,6 @@ return end - % --- READ Polhemus Sensor + fiducial locations --- %========================================================================== try @@ -100,4 +98,4 @@ start = nl + skip*3; for i = start:3:length(file) sens = [sens; str2num(file{i}) str2num(file{i+1}) str2num(file{i+2})]; -end \ No newline at end of file +end diff --git a/external/fieldtrip/fileio/private/read_sbin_data.m b/external/fieldtrip/fileio/private/read_sbin_data.m new file mode 100644 index 0000000..325a4c0 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_sbin_data.m @@ -0,0 +1,108 @@ +function [trialData] = read_sbin_data(filename, hdr, begtrial, endtrial, chanindx) + +% READ_SBIN_DATA reads the data from an EGI segmented simple binary format file +% +% Use as +% [trialData] = read_sbin_data(filename, hdr, begtrial, endtrial, chanindx) +% with +% filename name of the input file +% hdr header structure, see READ_HEADER +% begtrial first trial to read, mutually exclusive with begsample+endsample +% endtrial last trial to read, mutually exclusive with begsample+endsample +% chanindx list with channel indices to read +% +% This function returns a 3-D matrix of size Nchans*Nsamples*Ntrials. +%_______________________________________________________________________ +% +% +% Modified from EGI's readEGLY.m with permission 2008-03-31 Joseph Dien +% + +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_sbin_data.m 956 2010-04-23 03:23:20Z josdie $ + +fh=fopen([filename],'r'); +if fh==-1 + error('wrong filename') +end + +version = fread(fh,1,'int32'); + +%check byteorder +[str,maxsize,cEndian]=computer; +if version < 7 + if cEndian == 'B' + endian = 'ieee-be'; + elseif cEndian == 'L' + endian = 'ieee-le'; + end; +elseif (version > 6) && ~bitand(version,6) + if cEndian == 'B' + endian = 'ieee-le'; + elseif cEndian == 'L' + endian = 'ieee-be'; + end; + version = swapbytes(uint32(version)); %hdr.orig.header_array is already byte-swapped +else + error('ERROR: This is not a simple binary file. Note that NetStation does not successfully directly convert EGIS files to simple binary format.\n'); +end; + +if bitand(version,1) == 0 + unsegmented = 1; +else + unsegmented = 0; +end; + +precision = bitand(version,6); +Nevents=hdr.orig.header_array(17); + +switch precision + case 2 + trialLength=2*hdr.nSamples*(hdr.nChans+Nevents)+6; + dataType='int16'; + dataLength=2; + case 4 + trialLength=4*hdr.nSamples*(hdr.nChans+Nevents)+6; + dataType='single'; + dataLength=4; + case 6 + trialLength=8*hdr.nSamples*(hdr.nChans+Nevents)+6; + dataType='double'; + dataLength=8; +end + +if unsegmented + %interpret begtrial and endtrial as sample indices + fseek(fh, 36+Nevents*4, 'bof'); %skip over header + fseek(fh, ((begtrial-1)*(hdr.nChans+Nevents)*dataLength), 'cof'); %skip previous trials + nSamples = endtrial-begtrial+1; + trialData = fread(fh, [hdr.nChans+Nevents, nSamples],dataType,endian); +else + fseek(fh, 40+length(hdr.orig.CatLengths)+sum(hdr.orig.CatLengths)+Nevents*4, 'bof'); %skip over header + fseek(fh, (begtrial-1)*trialLength, 'cof'); %skip over initial segments + + trialData=zeros(hdr.nChans,hdr.nSamples,endtrial-begtrial+1); + + for segment=1:(endtrial-begtrial+1) + fseek(fh, 6, 'cof'); %skip over segment info + temp = fread(fh, [(hdr.nChans+Nevents), hdr.nSamples],dataType,endian); + trialData(:,:,segment) = temp(1:hdr.nChans,:); + end +end +trialData=trialData(chanindx, :,:); +fclose(fh); diff --git a/external/fieldtrip/fileio/private/read_sbin_events.m b/external/fieldtrip/fileio/private/read_sbin_events.m new file mode 100644 index 0000000..4a7f6ec --- /dev/null +++ b/external/fieldtrip/fileio/private/read_sbin_events.m @@ -0,0 +1,159 @@ +function [EventCodes, segHdr, eventData] = read_sbin_events(filename) + +% READ_SBIN_EVENTS reads the events information from an EGI segmented simple binary format file +% +% Use as +% [EventCodes, segHdr, eventData] = read_sbin_events(filename) +% with +% EventCodes - if NEvent (from header_array) != 0, then array of 4-char event names +% segHdr - condition codes and time stamps for each segment +% eventData - if NEvent != 0 then event state for each sample, else 'none' +% and +% filename - the name of the data file +%_______________________________________________________________________ +% +% +% Modified from EGI's readEGLY.m with permission 2008-03-31 Joseph Dien +% + +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_sbin_events.m 945 2010-04-21 17:41:20Z roboos $ + +fid=fopen([filename],'r'); +if fid==-1 + error('wrong filename') +end + +version = fread(fid,1,'int32'); + +%check byteorder +[str,maxsize,cEndian]=computer; +if version < 7 + if cEndian == 'B' + endian = 'ieee-be'; + elseif cEndian == 'L' + endian = 'ieee-le'; + end; +elseif (version > 6) && ~bitand(version,6) + if cEndian == 'B' + endian = 'ieee-le'; + elseif cEndian == 'L' + endian = 'ieee-be'; + end; + version = swapbytes(uint32(version)); +else + error('ERROR: This is not a simple binary file. Note that NetStation does not successfully directly convert EGIS files to simple binary format.\n'); +end; + +if bitand(version,1) == 0 + %error('ERROR: This is an unsegmented file, which is not supported.\n'); + unsegmented = 1; +else + unsegmented = 0; +end; + +precision = bitand(version,6); +if precision == 0 + error('File precision is not defined.'); +end; + +% read header... +year = fread(fid,1,'int16',endian); +month = fread(fid,1,'int16',endian); +day = fread(fid,1,'int16',endian); +hour = fread(fid,1,'int16',endian); +minute = fread(fid,1,'int16',endian); +second = fread(fid,1,'int16',endian); +millisecond = fread(fid,1,'int32',endian); +Samp_Rate = fread(fid,1,'int16',endian); +NChan = fread(fid,1,'int16',endian); +Gain = fread(fid,1,'int16',endian); +Bits = fread(fid,1,'int16',endian); +Range = fread(fid,1,'int16',endian); +if unsegmented, + NumCategors = 0; + NSegments = 1; + NSamples = fread(fid,1,'int32',endian); + NEvent = fread(fid,1,'int16',endian); + for j = 1:NEvent + EventCodes(j,1:4) = char(fread(fid,[1,4],'char',endian)); + end + CateNames = []; + CatLengths = []; + preBaseline = 0; +else + NumCategors = fread(fid,1,'int16',endian); + for j = 1:NumCategors + CatLengths(j) = fread(fid,1,'int8',endian); + for i = 1:CatLengths(j) + CateNames{j}(i) = char(fread(fid,1,'char',endian)); + end + end + NSegments = fread(fid,1,'int16',endian); + NSamples = fread(fid,1,'int32',endian); % samples per segment + NEvent = fread(fid,1,'int16',endian); % num events per segment + EventCodes = []; + for j = 1:NEvent + EventCodes(j,1:4) = char(fread(fid,[1,4],'char',endian)); + end +end + +%read the actual events +if unsegmented + %data are multiplexed + nsmp = 1; +else + %data are organized in segments + nsmp = NSamples; +end + +segHdr = zeros(NSegments,2); + +if unsegmented + eventData = logical(zeros(NEvent,NSegments*NSamples)); + switch precision + case 2 + dataType = 'int16'; + case 4 + dataType = 'single'; + case 6 + dataType = 'double'; + end + allData = fread(fid,[NChan+NEvent,NSegments*NSamples],dataType,endian); + eventData = logical(allData(NChan+1:end,:)); +else + eventData = zeros(NEvent,NSegments*NSamples); + for j = 1:NSegments*(NSamples/nsmp) + %read miniheader per segment + [segHdr(j,1), count] = fread(fid, 1,'int16',endian); %cell + [segHdr(j,2), count] = fread(fid, 1,'int32',endian); %time stamp + + switch precision + case 2 + [temp,count] = fread(fid,[NChan+NEvent, nsmp],'int16',endian); + case 4 + [temp,count] = fread(fid,[NChan+NEvent, nsmp],'single',endian); + case 6 + [temp,count] = fread(fid,[NChan+NEvent, nsmp],'double',endian); + end + if (NEvent ~= 0) + eventData(:,((j-1)*nsmp+1):j*nsmp) = temp( (NChan+1):(NChan+NEvent), 1:nsmp); + end + end +end +fclose(fid); diff --git a/external/fieldtrip/fileio/private/read_sbin_header.m b/external/fieldtrip/fileio/private/read_sbin_header.m new file mode 100644 index 0000000..bc91804 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_sbin_header.m @@ -0,0 +1,173 @@ +function [header_array, CateNames, CatLengths, preBaseline] = read_sbin_header(filename) + +% READ_SBIN_HEADER reads the header information from an EGI segmented simple binary format file +% +% Use as +% [header_array, CateNames, CatLengths, preBaseline] = read_sbin_header(filename) +% with +% header_array - differs between versions, read code for details +% CateNames - category names +% CatLengths - length of category names +% preBaseline - number of samples in the baseline prior to the baseline event +% and +% filename - the name of the data file +% +% Since there is no unique event code for the segmentation event, and hence the baseline period, +% the first event code in the list will be assumed to be the segmentation event. +% NetStation itself simply ignores possible baseline information when importing simple binary files. +%_______________________________________________________________________ +% +% +% Modified from EGI's readEGLY.m with permission 2008-03-31 Joseph Dien +% + +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_sbin_header.m 945 2010-04-21 17:41:20Z roboos $ + +fid=fopen([filename],'r'); +if fid==-1 + error('wrong filename') +end + +version = fread(fid,1,'int32'); +if isempty(version) + error('ERROR: This is not a simple binary file. Note that NetStation does not successfully directly convert EGIS files to simple binary format.'); +end; + +%check byteorder +[str,maxsize,cEndian]=computer; +if version < 7 + if cEndian == 'B' + endian = 'ieee-be'; + elseif cEndian == 'L' + endian = 'ieee-le'; + end; +elseif (version > 6) && ~bitand(version,6) + if cEndian == 'B' + endian = 'ieee-le'; + elseif cEndian == 'L' + endian = 'ieee-be'; + end; + version = swapbytes(uint32(version)); +else + error('ERROR: This is not a simple binary file. Note that NetStation does not successfully directly convert EGIS files to simple binary format.'); +end; + +if bitand(version,1) == 0 + %error('ERROR: This is an unsegmented file, which is not supported.'); + unsegmented = 1; +else + unsegmented = 0; +end; + +precision = bitand(version,6); +if precision == 0 + error('File precision is not defined.'); +end; + +% read header... +year = fread(fid,1,'int16',endian); +month = fread(fid,1,'int16',endian); +day = fread(fid,1,'int16',endian); +hour = fread(fid,1,'int16',endian); +minute = fread(fid,1,'int16',endian); +second = fread(fid,1,'int16',endian); +millisecond = fread(fid,1,'int32',endian); +Samp_Rate = fread(fid,1,'int16',endian); +NChan = fread(fid,1,'int16',endian); +Gain = fread(fid,1,'int16',endian); +Bits = fread(fid,1,'int16',endian); +Range = fread(fid,1,'int16',endian); + +if unsegmented, + NumCategors = 0; + NSegments = 1; + NSamples = fread(fid,1,'int32',endian); + NEvent = fread(fid,1,'int16',endian); + for j = 1:NEvent + EventCodes(j,1:4) = char(fread(fid,[1,4],'char',endian)); + end + CateNames = []; + CatLengths = []; + preBaseline = 0; +else + NumCategors = fread(fid,1,'int16',endian); + for j = 1:NumCategors + CatLengths(j) = fread(fid,1,'int8',endian); + for i = 1:CatLengths(j) + CateNames{j}(i) = char(fread(fid,1,'char',endian)); + end + end + NSegments = fread(fid,1,'int16',endian); + NSamples = fread(fid,1,'int32',endian); % samples per segment + NEvent = fread(fid,1,'int16',endian); % num events per segment + EventCodes = []; + for j = 1:NEvent + EventCodes(j,1:4) = char(fread(fid,[1,4],'char',endian)); + end + + + + preBaseline=0; + if NEvent > 0 + + for j = 1:NSegments + [segHdr(j,1), count] = fread(fid, 1,'int16',endian); %cell + [segHdr(j,2), count] = fread(fid, 1,'int32',endian); %time stamp + switch precision + case 2 + [temp,count] = fread(fid,[NChan+NEvent, NSamples],'int16',endian); + case 4 + [temp,count] = fread(fid,[NChan+NEvent, NSamples],'single',endian); + case 6 + [temp,count] = fread(fid,[NChan+NEvent, NSamples],'double',endian); + end + if (NEvent ~= 0) + eventData(:,((j-1)*NSamples+1):j*NSamples) = temp( (NChan+1):(NChan+NEvent), 1:NSamples); + end + end + + if NEvent == 1 + %assume this is the segmentation event + theEvent=find(eventData(1,:)>0); + theEvent=mod(theEvent(1),NSamples); + else + %assume the sample that always has an event is the baseline + %if more than one, choose the earliest one + baselineCandidates = unique(mod(find(eventData(:,:)'),NSamples)); + counters=zeros(1,length(baselineCandidates)); + totalEventSamples=mod(find(sum(eventData(:,:))'),NSamples); + for i = 1:length(totalEventSamples) + theMatch=find(ismember(baselineCandidates,totalEventSamples(i))); + counters(theMatch)=counters(theMatch)+1; + end; + theEvent=min(baselineCandidates(find(ismember(counters,NSegments)))); + end; + + preBaseline=theEvent-1; + if preBaseline == -1 + preBaseline =0; + end; + end +end + +fclose(fid); + +header_array = double([version year month day hour minute second millisecond Samp_Rate NChan Gain Bits Range NumCategors, NSegments, NSamples, NEvent]); + + diff --git a/external/fieldtrip/fileio/private/read_serial_event.m b/external/fieldtrip/fileio/private/read_serial_event.m new file mode 100644 index 0000000..25cf00a --- /dev/null +++ b/external/fieldtrip/fileio/private/read_serial_event.m @@ -0,0 +1,98 @@ +function event = read_serial_event(filename) + +% READ_SERIAL_EVENT +% +% changed A.Hadjipapas 2010 +% +% The only thing transmitted is the event.value (no info about sample) but it works + +% Copyright (C) 2007, Christian Hesse +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_serial_event.m 945 2010-04-21 17:41:20Z roboos $ + +%% serial port on windows or linux platform +[port, opt] = filetype_check_uri(filename); +% determine whether any serial port objects are already associated with the +% target serial port +temp = instrfind; +if isempty(temp)||~any(strcmpi(temp.Port,port)) + s=serial(port); + s.Baudrate =str2double(opt{2}); + fopen(s); +end + +%% try to read a message from the serial port +if ~isempty(s.BytesAvailable) && s.BytesAvailable~=0 + %% NOTE: Here I only use fread,which delivers numerical outputs. I + %% then check whether the message is longer than 3 and if it is + %% I assume it was a string to begin with and then deocde it + %% back to char + msg = fread(s,s.BytesAvailable); + if length(msg)>3 + + msg=char(msg'); + event.type='char'; + else + event.type='uint'; + end + %% The only thing transmitted is the event.value + event.value=msg; + %% FIX THIS: here sample is always at a fixed value (i.e true sample (e.g. write_event) is not + %% transmitted) + event.sample=1; + event.duration=[]; +end; + + +%% this is the old code +% +% % serial port on windows or linux platform +% [port, opt] = filetype_check_uri(filename); +% % determine whether any serial port objects are already associated with the +% % target serial port +% s = []; +% temp = instrfind; +% if isa(temp,'instrument') +% % find all serial ports +% i1 = strcmpi({temp(:).Type},'serial'); +% if any(i1) +% % find all serial ports whose name matches that of the specified port +% i2 = strmatch(lower(port),lower({temp(find(i1)).Name})); +% % set s to the (first) matching port if present (and open if necessary) +% if ~isempty(i2) +% s = temp(i2(1)); +% if ~strcmp(s.Status,'open'), fopen(s); end; +% end +% end +% end +% % create, configure a serial port object if necessary and open the port +% if ~isa(s,'serial') +% s = serial(port); +% if ~isempty(opt) && iscell(opt), s = set(s,opt); end; +% fopen(s); +% end +% % try to read a message from the serial port +% msg = []; +% % FIXME: this currently assumes that all messages are terminated by the +% % "newline" character (ascii character 10) +% try +% msg = fscanf(s,'%s\n'); +% end; +% % convert message to event structure +% event = msg2struct(msg); diff --git a/external/fieldtrip/fileio/private/read_shm_data.m b/external/fieldtrip/fileio/private/read_shm_data.m new file mode 100644 index 0000000..d6d9f38 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_shm_data.m @@ -0,0 +1,96 @@ +function [dat, dimord] = read_shm_data(hdr, chanindx, begtrial, endtrial) + +% READ_SHM_DATA reads the data in real-time from shared memory +% this is a helper function for READ_DATA + +% Copyright (C) 2007-2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_shm_data.m 945 2010-04-21 17:41:20Z roboos $ + +% this persistent variable is used for caching the 600 packets +% which inproves the throughput when reading overlapping data segments +persistent ctf_shm + +% read the data from shared memory, first the meta information only +[msgType msgId sampleNumber numSamples numChannels] = read_ctf_shm; + +if isempty(ctf_shm) + ctf_shm.msgType = nan(size(msgType)); + ctf_shm.msgId = nan(size(msgId)); + ctf_shm.sampleNumber = nan(size(sampleNumber)); + ctf_shm.numSamples = nan(size(numSamples)); + ctf_shm.numChannels = nan(size(numChannels)); + ctf_shm.data = {}; + ctf_shm.hit = 0; + ctf_shm.mis = 0; +end + +% there seems to be a bug in Acq, causing the messageId to wrap around +% hence it cannot be used as index into the packets, so construct a new trial numbering vector +trlNum = nan(size(msgId)); +trlNum(msgType==1) = sampleNumber(msgType==1)./numSamples(msgType==1) + 1; + +% allocate memory for the data, fill with NaNs +dat = nan(length(chanindx), hdr.nSamples, endtrial-begtrial+1); + +% determine which trials/packets to read +sel = find((trlNum>=begtrial) & (trlNum<=endtrial)); + +% this is for calibrating the integer values to physical values +if isfield(hdr, 'orig') && isfield(hdr.orig, 'gainV') + gain = sparse(diag(hdr.orig.gainV(chanindx))); +elseif isfield(hdr, 'orig') && isfield(hdr.orig, 'res4') + gain = sparse(diag([hdr.orig.res4.senres(chanindx).gain])); +end + +for i=1:length(sel) + % nchan = numChannels(i); + % nsmp = numSamples(i); + nchan = hdr.nChans; + nsmp = hdr.nSamples; + % buf = read_ctf_shm(sel(i)); + % buf = buf(1:nchan*nsmp); + if all([msgType(sel(i)) msgId(sel(i)) sampleNumber(sel(i)) numSamples(sel(i)) numChannels(sel(i))] == [ctf_shm.msgType(sel(i)) ctf_shm.msgId(sel(i)) ctf_shm.sampleNumber(sel(i)) ctf_shm.numSamples(sel(i)) ctf_shm.numChannels(sel(i))]) + % get the data from the cache + buf = ctf_shm.data{sel(i)}; + ctf_shm.hit = ctf_shm.hit+1; + else + % read the data from shared memory, update the cache + buf = read_ctf_shm(sel(i),nchan*nsmp); + ctf_shm.data{sel(i)} = buf; + ctf_shm.msgType(sel(i)) = msgType(sel(i)); + ctf_shm.msgId(sel(i)) = msgId(sel(i)); + ctf_shm.sampleNumber(sel(i)) = sampleNumber(sel(i)); + ctf_shm.numSamples(sel(i)) = numSamples(sel(i)); + ctf_shm.numChannels(sel(i)) = numChannels(sel(i)); + ctf_shm.mis = ctf_shm.mis+1; + end + buf = reshape(buf, nchan, nsmp); + thistrial = trlNum(sel(i)); + % apply calibration to the selected channels + dat(:,:,thistrial-begtrial+1) = gain * double(buf(chanindx,:)); +end + +% if any(isnan(dat(:))) +% warning('data has been padded with NaNs'); +% fprintf('trials present = %d - %d\n', min(trlNum), max(trlNum)); +% fprintf('trials requested = %d - %d\n', begtrial, endtrial); +% end + +dimord = 'chans_samples_trials'; diff --git a/external/fileio/private/read_shm_event.m b/external/fieldtrip/fileio/private/read_shm_event.m similarity index 77% rename from external/fileio/private/read_shm_event.m rename to external/fieldtrip/fileio/private/read_shm_event.m index ee554ac..a22a747 100644 --- a/external/fileio/private/read_shm_event.m +++ b/external/fieldtrip/fileio/private/read_shm_event.m @@ -5,24 +5,23 @@ % Copyright (C) 2007, Robert Oostenveld % -% $Log: read_shm_event.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.2 2009/01/06 09:11:45 roboos -% use new function call API for read_data +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.1 2007/08/01 12:12:06 roboos -% moved the actual code from the normal functions into these helper functions -% fixed some bugs related to reading the header from a user-specified res4 file and setting the trigger detection -% use the new trigger detection in AcqBuffer when possible, use the old trigger detection if no setup buffer is present -% implemented caching of the data packets (using global variable ctf_shm) +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_shm_event.m 945 2010-04-21 17:41:20Z roboos $ % get the optional input arguments hdr = keyval('header', varargin); @@ -72,7 +71,7 @@ trg = trg(:, trg(2,:)>=minsample); end if ~isempty(maxsample) - trg = trg(:, trg(2,:)<=maxsample) + trg = trg(:, trg(2,:)<=maxsample); end for i=1:size(trg,2) event(end+1).type = hdr.label{trg(1,i)+1}; % zero-offset diff --git a/external/fieldtrip/fileio/private/read_shm_header.m b/external/fieldtrip/fileio/private/read_shm_header.m new file mode 100644 index 0000000..ddc4b18 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_shm_header.m @@ -0,0 +1,95 @@ +function [hdr] = read_shm_header(filename) + +% READ_SHM_HEADER reads the header in real-time from shared memory +% this is a helper function for READ_HEADER + +% Copyright (C) 2007-2010, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_shm_header.m 945 2010-04-21 17:41:20Z roboos $ + +% these are for remembering the header details to speed up subsequent calls +persistent previous_headerfile previous_header + +% decode the filename, which looks like shm:// +headerfile = filetype_check_uri(filename); + +% determine the content of all chared memory packets +[msgType msgId sampleNumber numSamples numChannels] = read_ctf_shm; + +if ~isempty(headerfile) + % the headerfile has been specified by the user + buf = []; +else + % get the name of the headerfile from shared memory + sel = find(msgType==0); + if isempty(sel) + error('could not determine header file location from shared memory'); + end + buf = read_ctf_shm(sel); % this includes the headerfile as string, and the trigger information from AcqBuffer + str = char(typecast(buf(1:256), 'uint8')); % assume that the filename will not exceed 256 characters in length + pad = find(str==0, 1, 'first'); + headerfile = char(str(1:(pad-1))); +end + +if isempty(previous_header) || isempty(previous_headerfile) || ~isequal(previous_headerfile, headerfile) + + % read the header details and remember for the subsequent calls + hdr = read_header(headerfile, 'cache', true); + previous_headerfile = headerfile; + previous_header = hdr; + + % inform AcqBuffer about the trigger channels, to allow flank detection + if ~isempty(buf) + % meg channels are 5, refmag 0, refgrad 1, adcs 18, trigger 11, eeg 9 + if isfield(hdr, 'orig') && isfield(hdr.orig, 'sensType') + origSensType = hdr.orig.sensType; + elseif isfield(hdr, 'orig') && isfield(hdr.orig, 'res4') + origSensType = [hdr.orig.res4.senres.sensorTypeIndex]; + end + % do online detection of triggers inside AcqBuffer + trgchan = find(origSensType(:)'==11); + if length(trgchan)>10 + error('online detection of triggers in AcqBuffer only works with up to 10 trigger channels'); + end + % specify the channel count and the trigger channels in the setup buffer + buf(28160-9011) = hdr.nChans; % tell the number of actual channels + buf(28160-9010) = length(trgchan); % tell the number of trigger channels + for i=1:length(trgchan) + buf(28160-9010+i) = trgchan(i)-1; % tell the index of the trigger channel, zero offset + end + % the setup packet may have moved in the meantine, determine its latest location + [msgType msgId sampleNumber numSamples numChannels] = read_ctf_shm; + sel = find(msgType==0); + % write the updated setup packet, this should cause AcqBuffer to do online trigger detection + write_ctf_shm(sel, 0, 0, 0, 0, 0, buf); + else + warning('no setup in shared memory, could not enable trigger detection'); + end + +else + % don't read the header details again, only update the number of samples/trials + hdr = previous_header; +end + +% the following information is determined from shared memory +sel = find(msgType==1); % these are the data packets +hdr.nTrials = double(max(sampleNumber(sel)))/double(max(numSamples(sel))); +hdr.nSamples = double(max(numSamples(sel))); +hdr.nSamplesPre = 0; + diff --git a/external/fieldtrip/fileio/private/read_spike6mat_data.m b/external/fieldtrip/fileio/private/read_spike6mat_data.m new file mode 100644 index 0000000..2ada881 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_spike6mat_data.m @@ -0,0 +1,55 @@ +function dat = read_spike6mat_data(filename, varargin) + +% read_spike6mat_data() - read Matlab files exported from Spike 6 +% +% Usage: +% >> header = read_spike6mat_data(filename, varargin); +% +% Inputs: +% filename - [string] file name +% +% Optional inputs: +% 'begsample' first sample to read +% 'endsample' last sample to read +% 'chanindx' - list with channel indices to read +% 'header' - FILEIO structure header +% +% Outputs: +% dat - data over the specified range +% _______________________________________________________________________ +% Copyright (C) 2008 Institute of Neurology, UCL +% Vladimir Litvak + +if nargin < 1 + help read_spike6mat_data; + return; +end; + +header = keyval('header', varargin); +begsample = keyval('begsample', varargin); +endsample = keyval('endsample', varargin); +chanindx = keyval('chanindx', varargin); + + +if isempty(header) + header = read_spike6mat_header(filename); +end + +if isempty(begsample), begsample = 1; end; +if isempty(endsample), endsample = header.nSamples; end; + +try + vars = struct2cell(load(filename)); +catch + error('File not found or wrong format.'); +end + +if isempty(chanindx) + chanindx = 1:numel(vars); +end + +dat = zeros(length(chanindx), endsample-begsample+1); + +for i = 1:length(chanindx) + dat(i, :) = vars{chanindx(i)}.values(begsample:endsample); +end diff --git a/external/fieldtrip/fileio/private/read_spike6mat_header.m b/external/fieldtrip/fileio/private/read_spike6mat_header.m new file mode 100644 index 0000000..55216ca --- /dev/null +++ b/external/fieldtrip/fileio/private/read_spike6mat_header.m @@ -0,0 +1,55 @@ +function header = read_spike6mat_header(filename) + +% read_spike6mat_header() - read Matlab files exported from Spike 6 +% +% Usage: +% >> header = read_spike6mat_header(filename); +% +% Inputs: +% filename - [string] file name +% +% Outputs: +% header - FILEIO toolbox type structure +% _______________________________________________________________________ +% Copyright (C) 2008 Institute of Neurology, UCL +% Vladimir Litvak + +if nargin < 1 + help read_spike6mat_header; + return; +end; + +try + vars = struct2cell(load(filename)); +catch + error('File not found or wrong format.'); +end + +header = []; +header.nChans = length(vars); +header.label = {}; + +fsample = []; +onsets = []; +lengths = []; +for i = 1:numel(vars) + fsample(i) = round(1./vars{i}.interval); + onsets(i) = 1e-3*round(1e3*vars{i}.times(1)); + lengths(i) = vars{i}.length; + header.label{i} = vars{i}.title; +end + +if length(unique(fsample))>1 || length(unique(onsets))>1 || length(unique(lengths))>1 + error('Only files with identical channel parameters are supported'); +end + +header.Fs = unique(fsample); + +header.nSamples = unique(lengths); + +header.nSamplesPre = -round(unique(onsets)*header.Fs); + +header.nTrials = 1; + +header.label = header.label(:); + diff --git a/external/fieldtrip/fileio/private/read_spmeeg_data.m b/external/fieldtrip/fileio/private/read_spmeeg_data.m new file mode 100644 index 0000000..1362129 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_spmeeg_data.m @@ -0,0 +1,97 @@ +function dat = read_spmeeg_data(filename, varargin) + +% read_spmeeg_data() - import SPM5 and SPM8 meeg datasets +% +% Usage: +% >> header = read_spmeeg_data(filename, varargin); +% +% Inputs: +% filename - [string] file name +% +% Optional inputs: +% 'begsample' first sample to read +% 'endsample' last sample to read +% 'chanindx' - list with channel indices to read +% 'header' - FILEIO structure header +% +% Outputs: +% dat - data over the specified range +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging +% Vladimir Litvak + +if nargin < 1 + help read_spmeeg_data; + return; +end; + +typenames = {'uint8','int16','int32','float32','float64','int8','uint16','uint32'}; +typesizes = [1 2 4 4 8 1 2 4]; + +header = keyval('header', varargin); +begsample = keyval('begsample', varargin); +endsample = keyval('endsample', varargin); +chanindx = keyval('chanindx', varargin); + +if isempty(header) + header = read_spmeeg_header([filename(1:(end-3)) 'mat']); +end + +if isempty(begsample), begsample = 1; end; +if isempty(endsample), endsample = header.nSamples; end; + + + +datatype = 'float32-le'; +scale = []; +if isfield(header, 'orig') + if isfield(header.orig, 'data') && isnumeric(header.orig.data) ... + && ~isempty(header.orig.data) + try + dat = reshape(header.orig.data(chanindx, :, :), length(chanindx), []); + dat = dat(:, begsample:endsample); + return; + end + end + + if isfield(header.orig, 'datatype') + datatype = header.orig.datatype; + elseif isfield(header.orig.data, 'datatype') + datatype = header.orig.data.datatype; + end + if isfield(header.orig, 'scale') + scale = header.orig.scale; + elseif isfield(header.orig.data, 'scale') + scale = header.orig.data.scale; + end +end + +stepsize = typesizes(strmatch(strtok(datatype, '-'), typenames)); + +filename = [filename(1:(end-3)) 'dat']; + +fid = fopen(filename, 'r'); +fseek(fid, stepsize*header.nChans*(begsample-1), 'bof'); +[dat, siz] = fread(fid, [header.nChans, (endsample-begsample+1)], strtok(datatype, '-')); +fclose(fid); + +if ~isempty(chanindx) + % select the desired channels + dat = dat(chanindx,:); +end + +if ~isempty(scale) && ~ismember(strtok(datatype, '-'), {'float32', 'float64'}) + + % This is a somewhat complicated mechanism to figure out which scaling + % coefficients go with which data points in a generic way + + trlind = floor(((begsample:endsample)-1)/header.nSamples)+1; + + utrlind = unique(trlind); + + for i = 1:length(utrlind) + dat(:, trlind == utrlind(i)) = dat(:, trlind == utrlind(i)).* ... + repmat(squeeze(scale(chanindx,:,utrlind(i))), 1, sum(trlind == utrlind(i))); + end + +end diff --git a/external/fieldtrip/fileio/private/read_spmeeg_event.m b/external/fieldtrip/fileio/private/read_spmeeg_event.m new file mode 100644 index 0000000..9092878 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_spmeeg_event.m @@ -0,0 +1,78 @@ +function event = read_spmeeg_event(filename, varargin) + +% read_spmeeg_event() - import evtns from SPM5 and SPM8 meeg datasets +% +% Usage: +% >> header = read_spmeeg_event(filename); +% +% Inputs: +% filename - [string] file name +% +% Outputs: +% event - FILEIO toolbox event structure +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging +% Vladimir Litvak + +if nargin < 1 + help read_spmeeg_event; + return; +end; + +header = keyval('header', varargin); + +if isempty(header) + header = read_spmeeg_header(filename); +end; + +D = header.orig; + +event = []; + +if isfield(D, 'Radc') % SPM5 + for i = 1:D.Nevents + if isfield(D, 'events') && isfield(D.events, 'code') && length(D.events.code) == D.Nevents + value = D.events.code(i); + else + value = []; + end + + event = [event struct('type', 'trial', 'sample', (i-1)*header.nSamples + 1,... + 'value', value, 'offset', -header.nSamplesPre, 'duration', header.nSamples)]; + end + + if D.Nevents == 1 && isfield(D, 'events') && isfield(D.events, 'time') + event = [event struct('type', 'spm5_event', 'sample', num2cell(D.events.time),... + 'value', num2cell(D.events.code), 'offset', -header.nSamplesPre, 'duration', header.nSamples)]; + end + +elseif all(isfield(D, {'type', 'Nsamples', 'Fsample', 'timeOnset'})) % SPM8 + + for i = 1:numel(D.trials) + if isfield(D.trials, 'events') + cevent = D.trials(i).events; + if ~isempty(cevent) + for j = 1:numel(cevent) + if ~strcmp(cevent(j).type, 'trial') + csample = (cevent(j).time - D.trials(i).onset)*header.Fs + 1; + if csample > 0 && csample <= header.nSamples + tmp = rmfield(cevent(j), 'time'); + if strcmp(D.type, 'continuous') && (D.timeOnset ~= 0) + tmp.sample = (cevent(j).time - D.timeOnset)* header.Fs + 1; + else + tmp.sample = (i-1)*header.nSamples + 1 +(cevent(j).time - D.trials(i).onset)*header.Fs; + end + tmp.sample = round(tmp.sample); + tmp.offset = 0; + event = [event tmp]; + end + end + end + end + end + end + +else + error('Cannot recognize an SPM EEG header format'); +end + diff --git a/external/fieldtrip/private/read_spmeeg_header.m b/external/fieldtrip/fileio/private/read_spmeeg_header.m similarity index 100% rename from external/fieldtrip/private/read_spmeeg_header.m rename to external/fieldtrip/fileio/private/read_spmeeg_header.m diff --git a/external/fieldtrip/fileio/private/read_stl.m b/external/fieldtrip/fileio/private/read_stl.m new file mode 100644 index 0000000..8ec68e1 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_stl.m @@ -0,0 +1,75 @@ +function [pnt, tri, nrm] = read_stl(filename); + +% READ_STL reads a triangulation from an ascii *.stl file, which is a file +% format native to the stereolithography CAD software created by 3D Systems. +% +% Use as +% [pnt, tri, nrm] = read_stl(filename) +% +% See also WRITE_STL + +% Copyright (C) 2006, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_stl.m 945 2010-04-21 17:41:20Z roboos $ + +% solid testsphere +% facet normal -0.13 -0.13 -0.98 +% outer loop +% vertex 1.50000 1.50000 0.00000 +% vertex 1.50000 1.11177 0.05111 +% vertex 1.11177 1.50000 0.05111 +% endloop +% endfacet +% ... + +fid = fopen(filename, 'rt'); + +ntri = 0; +while ~feof(fid) + line = fgetl(fid); + ntri = ntri + ~isempty(findstr('facet normal', line)); +end +fseek(fid, 0, 'bof'); + +tri = zeros(ntri,3); +pnt = zeros(ntri*3,3); + +line = fgetl(fid); +name = sscanf(line, 'solid %s'); + +for i=1:ntri + line1 = fgetl(fid); + line2 = fgetl(fid); + line3 = fgetl(fid); + line4 = fgetl(fid); + line5 = fgetl(fid); + line6 = fgetl(fid); + line7 = fgetl(fid); + i1 = (i-1)*3+1; + i2 = (i-1)*3+2; + i3 = (i-1)*3+3; + tri(i,:) = [i1 i2 i3]; + dum = sscanf(strtrim(line1), 'facet normal %f %f %f'); nrm(i,:) = dum(:)'; + dum = sscanf(strtrim(line3), 'vertex %f %f %f'); pnt(i1,:) = dum(:)'; + dum = sscanf(strtrim(line4), 'vertex %f %f %f'); pnt(i2,:) = dum(:)'; + dum = sscanf(strtrim(line5), 'vertex %f %f %f'); pnt(i3,:) = dum(:)'; +end + +fclose(fid); + diff --git a/external/fieldtrip/fileio/private/read_tdt_tsq.m b/external/fieldtrip/fileio/private/read_tdt_tsq.m new file mode 100644 index 0000000..3fa031b --- /dev/null +++ b/external/fieldtrip/fileio/private/read_tdt_tsq.m @@ -0,0 +1,79 @@ +function tsq = read_tdt_tsq(filename, begblock, endblock) + +% READ_TDT_TSQ reads the headers from a Tucker_Davis_technologies TSQ file +% +% Use as +% tsq = read_tdt_tsq(filename, begblock, endblock) + +% Copyright (C) 2010, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id$ + +% Here are the possible values of the data format long: +% DFORM_FLOAT 0 +% DFORM_LONG 1 +% DFORM_SHORT 2 +% DFORM_BYTE 3 +% DFORM_DOUBLE 4 +% DFORM_QWORD 5 + +if nargin<2 || isempty(begblock) + begblock = 1; +end + +if nargin<3 || isempty(endblock) + endblock = inf; +end + +fid = fopen(filename, 'rb'); +offset = (begblock-1)*40; % bytes +fseek(fid, offset, 'cof'); +buf = fread(fid, [40, (endblock-begblock+1)], 'uint8=>uint8'); +fclose(fid); + +buf_size = buf(1:4,:); +buf_type = buf(5:8,:); +buf_code = buf(9:12,:); +buf_channel = buf(13:14,:); +buf_sortcode = buf(15:16,:); +buf_timestamp = buf(17:24,:); +buf_offset = buf(25:32,:); +buf_format = buf(33:36,:); +buf_frequency = buf(37:40,:); + +tsq_size = typecast(buf_size (:), 'int32'); +tsq_type = typecast(buf_type (:), 'int32'); +tsq_code = typecast(buf_code (:), 'int32'); % this can sometimes be interpreted as 4 chars +tsq_channel = typecast(buf_channel (:), 'int16'); +tsq_sortcode = typecast(buf_sortcode (:), 'int16'); +tsq_timestamp = typecast(buf_timestamp(:), 'double'); +tsq_offset = typecast(buf_offset (:), 'int64'); % or double +tsq_format = typecast(buf_format (:), 'int32'); +tsq_frequency = typecast(buf_frequency(:), 'single'); + +tsq = struct( 'size' , num2cell(tsq_size ), ... + 'type' , num2cell(tsq_type ), ... + 'code' , num2cell(tsq_code ), ... + 'channel' , num2cell(tsq_channel ), ... + 'sortcode' , num2cell(tsq_sortcode ), ... + 'timestamp' , num2cell(tsq_timestamp ), ... + 'offset' , num2cell(tsq_offset ), ... + 'format' , num2cell(tsq_format ), ... + 'frequency' , num2cell(tsq_frequency )); + diff --git a/external/fieldtrip/fileio/private/read_trigger.m b/external/fieldtrip/fileio/private/read_trigger.m new file mode 100644 index 0000000..09e58d4 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_trigger.m @@ -0,0 +1,146 @@ +function [event] = read_trigger(filename, varargin) + +% READ_TRIGGER extracts the events from a continuous trigger channel +% This function is a helper function to read_event and can be used for all +% dataformats that have one or multiple continuously sampled TTL channels +% in the data. +% +% The optional trigshift (default is 0) causes the value of the +% trigger to be obtained from a sample that is shifted N samples away +% from the actual flank. +% +% This is a helper function for READ_EVENT +% +% TODO +% - merge read_ctf_trigger into this function (requires trigshift and bitmasking option) +% - merge biosemi code into this function (requires bitmasking option) + +% Copyright (C) 2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_trigger.m 955 2010-04-22 15:21:44Z vlalit $ + +event = []; + +% get the optional input arguments +hdr = keyval('header', varargin); +dataformat = keyval('dataformat', varargin); +begsample = keyval('begsample', varargin); +endsample = keyval('endsample', varargin); +chanindx = keyval('chanindx', varargin); +detectflank = keyval('detectflank', varargin); +denoise = keyval('denoise', varargin); if isempty(denoise), denoise = 1; end +trigshift = keyval('trigshift', varargin); if isempty(trigshift), trigshift = 0; end +trigpadding = keyval('trigpadding', varargin); if isempty(trigpadding), trigpadding = 1; end +fixctf = keyval('fixctf', varargin); if isempty(fixctf), fixctf = 0; end +fixneuromag = keyval('fixneuromag', varargin); if isempty(fixneuromag), fixneuromag = 0; end +fix4dglasgow= keyval('fix4dglasgow', varargin); if isempty(fix4dglasgow), fix4dglasgow = 0; end + +if isempty(hdr) + hdr = ft_read_header(filename); +end + +if isempty(begsample) + begsample = 1; +end + +if isempty(endsample) + endsample = hdr.nSamples*hdr.nTrials; +end + +% read the trigger channel as raw data, can safely assume that it is continuous +dat = ft_read_data(filename, 'header', hdr, 'dataformat', dataformat, 'begsample', begsample, 'endsample', endsample, 'chanindx', chanindx, 'checkboundary', 0); + +if isempty(dat) + % there are no triggers to detect + return +end + +% Detect situations where the channel value changes almost at every time +% step which are likely to be noise +if denoise + for i=1:length(chanindx) + if (sum(diff(find(diff(dat(i,:))~=0)) == 1)/length(dat(i,:))) > 0.8 + warning(['trigger channel ' hdr.label{chanindx(i)} ' looks like noise and will be ignored']); + dat(i,:) = 0; + end + end +end + +if fixctf + % correct for reading the data as signed 32-bit integer, whereas it should be interpreted as an unsigned int + dat(dat<0) = dat(dat<0) + 2^32; +end + +if fixneuromag + % according to Joachim Gross, real events always have triggers > 5 + % this is probably to avoid the noisefloor + dat(dat<5) = 0; +end + +if fix4dglasgow + % synchronization pulses have a value of 8192 and are set to 0 + dat = dat - bitand(dat, 8192); + %% triggers containing the first bit assume a value of 4096 when sent by presentation + %% this does not seem to hold for matlab; check this + %dat = dat - bitand(dat, 4096)*4095/4096; +end + +for i=1:length(chanindx) + % process each trigger channel independently + channel = hdr.label{chanindx(i)}; + trig = dat(i,:); + + if trigpadding + pad = trig(1); + else + pad = 0; + end + + switch detectflank + case 'up' + % convert the trigger into an event with a value at a specific sample + for j=find(diff([pad trig(:)'])>0) + event(end+1).type = channel; + event(end ).sample = j + begsample - 1; % assign the sample at which the trigger has gone down + event(end ).value = trig(j+trigshift); % assign the trigger value just _after_ going up + end + case 'down' + % convert the trigger into an event with a value at a specific sample + for j=find(diff([pad trig(:)'])<0) + event(end+1).type = channel; + event(end ).sample = j + begsample - 1; % assign the sample at which the trigger has gone down + event(end ).value = trig(j-1-trigshift); % assign the trigger value just _before_ going down + end + case 'both' + % convert the trigger into an event with a value at a specific sample + for j=find(diff([pad trig(:)'])>0) + event(end+1).type = [channel '_up']; % distinguish between up and down flank + event(end ).sample = j + begsample - 1; % assign the sample at which the trigger has gone down + event(end ).value = trig(j+trigshift); % assign the trigger value just _after_ going up + end + % convert the trigger into an event with a value at a specific sample + for j=find(diff([pad trig(:)'])<0) + event(end+1).type = [channel '_down']; % distinguish between up and down flank + event(end ).sample = j + begsample - 1; % assign the sample at which the trigger has gone down + event(end ).value = trig(j-1-trigshift); % assign the trigger value just _before_ going down + end + otherwise + error('incorrect specification of ''detectflank'''); + end +end diff --git a/external/fieldtrip/fileio/private/read_vtk.m b/external/fieldtrip/fileio/private/read_vtk.m new file mode 100644 index 0000000..43d5f3b --- /dev/null +++ b/external/fieldtrip/fileio/private/read_vtk.m @@ -0,0 +1,54 @@ +function [pnt, dhk] = read_vtk(fn) + +% READ_VTK reads a triangulation from a VTK (Visualisation ToolKit) format file +% +% [pnt, dhk] = read_vtk(filename) +% +% See also SAVE_VTK, READ_TRI, SAVE_TRI + +% Copyright (C) 2002, Robert Oostenveld +% +% $Log: read_vtk.m,v $ +% Revision 1.1 2009/01/14 09:33:10 roboos +% moved even more files from fileio to fileio/private, see previous log entry +% +% Revision 1.2 2003/03/11 15:24:52 roberto +% updated help and copyrights +% + +fid = fopen(fn, 'rt'); +if fid~=-1 + + npnt = 0; + while (~npnt) + line = fgetl(fid); + if ~isempty(findstr(line, 'POINTS')) + npnt = sscanf(line, 'POINTS %d float'); + end + end + pnt = zeros(npnt, 3); + for i=1:npnt + pnt(i,:) = fscanf(fid, '%f', 3)'; + end + + ndhk = 0; + while (~ndhk) + line = fgetl(fid); + if ~isempty(findstr(line, 'POLYGONS')) + tmp = sscanf(line, 'POLYGONS %d %d'); + ndhk = tmp(1); + end + end + dhk = zeros(ndhk, 4); + for i=1:ndhk + dhk(i,:) = fscanf(fid, '%d', 4)'; + end + dhk = dhk(:,2:4) + 1; + + fclose(fid); + +else + error('unable to open file'); +end + + diff --git a/external/fieldtrip/fileio/private/read_yokogawa_data.m b/external/fieldtrip/fileio/private/read_yokogawa_data.m new file mode 100644 index 0000000..5c9a34c --- /dev/null +++ b/external/fieldtrip/fileio/private/read_yokogawa_data.m @@ -0,0 +1,295 @@ +function [dat] = read_yokogawa_data(filename, hdr, begsample, endsample, chanindx) + +% READ_YOKAGAWA_DATA reads continuous, epoched or averaged MEG data +% that has been generated by the Yokogawa MEG system and software +% and allows that data to be used in combination with FieldTrip. +% +% Use as +% [dat] = read_yokogawa_data(filename, hdr, begsample, endsample, chanindx) +% +% This is a wrapper function around the functions +% GetMeg160ContinuousRawDataM +% GetMeg160EvokedAverageDataM +% GetMeg160EvokedRawDataM +% +% See also READ_YOKOGAWA_HEADER, READ_YOKOGAWA_EVENT + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_yokogawa_data.m 1113 2010-05-20 08:35:15Z tilsan $ + +if ~hasyokogawa('16bitBeta6') + error('cannot determine whether Yokogawa toolbox is present'); +end + +% hdr = read_yokogawa_header(filename); +hdr = hdr.orig; % use the original Yokogawa header, not the FieldTrip header + +% default is to select all channels +if nargin<5 + chanindx = 1:hdr.channel_count; +end + +handles = definehandles; +fid = fopen(filename, 'rb', 'ieee-le'); + +switch hdr.acq_type + case handles.AcqTypeEvokedAve + % Data is returned by double. + start_sample = begsample - 1; % samples start at 0 + sample_length = endsample - begsample + 1; + epoch_count = 1; + start_epoch = 0; + dat = double(GetMeg160EvokedAverageDataM( fid, start_sample, sample_length )); + % the first extra sample is the channel number + channum = dat(:,1); + dat = dat(:,2:end); + + case handles.AcqTypeContinuousRaw + % Data is returned by int16. + start_sample = begsample - 1; % samples start at 0 + sample_length = endsample - begsample + 1; + epoch_count = 1; + start_epoch = 0; + dat = double(GetMeg160ContinuousRawDataM( fid, start_sample, sample_length )); + % the first extra sample is the channel number + channum = dat(:,1); + dat = dat(:,2:end); + + case handles.AcqTypeEvokedRaw + % Data is returned by int16. + begtrial = ceil(begsample/hdr.sample_count); + endtrial = ceil(endsample/hdr.sample_count); + if begtrial<1 + error('cannot read before the begin of the file'); + elseif endtrial>hdr.actual_epoch_count + error('cannot read beyond the end of the file'); + end + epoch_count = endtrial-begtrial+1; + start_epoch = begtrial-1; + % read all the neccessary trials that contain the desired samples + dat = double(GetMeg160EvokedRawDataM( fid, start_epoch, epoch_count )); + % the first extra sample is the channel number + channum = dat(:,1); + dat = dat(:,2:end); + if size(dat,2)~=epoch_count*hdr.sample_count + error('could not read all epochs'); + end + rawbegsample = begsample - (begtrial-1)*hdr.sample_count; + rawendsample = endsample - (begtrial-1)*hdr.sample_count; + sample_length = rawendsample - rawbegsample + 1; + % select the desired samples from the complete trials + dat = dat(:,rawbegsample:rawendsample); + + otherwise + error('unknown data type'); +end + +fclose(fid); + +if size(dat,1)~=hdr.channel_count + error('could not read all channels'); +elseif size(dat,2)~=(endsample-begsample+1) + error('could not read all samples'); +end + +% Count of AxialGradioMeter +ch_type = hdr.channel_info(:,2); +index = find(ch_type==[handles.AxialGradioMeter]); +axialgradiometer_index_tmp = index; +axialgradiometer_ch_count = length(index); + +% Count of PlannerGradioMeter +ch_type = hdr.channel_info(:,2); +index = find(ch_type==[handles.PlannerGradioMeter]); +plannergradiometer_index_tmp = index; +plannergradiometer_ch_count = length(index); + +% Count of EegChannel +ch_type = hdr.channel_info(:,2); +index = find(ch_type==[handles.EegChannel]); +eegchannel_index_tmp = index; +eegchannel_ch_count = length(index); + +% Count of NullChannel +ch_type = hdr.channel_info(:,2); +index = find(ch_type==[handles.NullChannel]); +nullchannel_index_tmp = index; +nullchannel_ch_count = length(index); + +%%% Pulling out AxialGradioMeter and value conversion to physical units. +if ~isempty(axialgradiometer_index_tmp) + % Acquisition of channel information + axialgradiometer_index = axialgradiometer_index_tmp; + ch_info = hdr.channel_info; + axialgradiometer_ch_info = ch_info(axialgradiometer_index, :); + + % Value conversion + % B = ( ADValue * VoltRange / ADRange - Offset ) * Sensitivity / FLLGain + calib = hdr.calib_info; + amp_gain = hdr.amp_gain(1); + tmp_ch_no = channum(axialgradiometer_index, 1); + tmp_data = dat(axialgradiometer_index, 1:sample_length); + tmp_offset = calib(axialgradiometer_index, 3) * ones(1,sample_length); + ad_range = 5/2^(hdr.ad_bit-1); + tmp_data = ( tmp_data * ad_range - tmp_offset ); + clear tmp_offset; + tmp_gain = calib(axialgradiometer_index, 2) * ones(1,sample_length); + tmp_data = tmp_data .* tmp_gain / amp_gain; + dat(axialgradiometer_index, 1:sample_length) = tmp_data; + clear tmp_gain; + + % Deletion of Inf row + index = find(axialgradiometer_ch_info(1,:) == Inf); + axialgradiometer_ch_info(:,index) = []; + + % Deletion of channel_type row + axialgradiometer_ch_info(:,2) = []; + + % Outputs to the global variable + handles.sqd.axialgradiometer_ch_info = axialgradiometer_ch_info; + handles.sqd.axialgradiometer_ch_no = tmp_ch_no; + handles.sqd.axialgradiometer_data = [ tmp_ch_no tmp_data]; + clear tmp_data; +end + +%%% Pulling out PlannerGradioMeter and value conversion to physical units. +if ~isempty(plannergradiometer_index_tmp) + % Acquisition of channel information + plannergradiometer_index = plannergradiometer_index_tmp; + ch_info = hdr.channel_info; + plannergradiometer_ch_info = ch_info(plannergradiometer_index, :); + + % Value conversion + % B = ( ADValue * VoltRange / ADRange - Offset ) * Sensitivity / FLLGain + calib = hdr.calib_info; + amp_gain = hdr.amp_gain(1); + tmp_ch_no = channum(plannergradiometer_index, 1); + tmp_data = dat(plannergradiometer_index, 1:sample_length); + tmp_offset = calib(plannergradiometer_index, 3) * ones(1,sample_length); + ad_range = 5/2^(hdr.ad_bit-1); + tmp_data = ( tmp_data * ad_range - tmp_offset ); + clear tmp_offset; + tmp_gain = calib(plannergradiometer_index, 2) * ones(1,sample_length); + tmp_data = tmp_data .* tmp_gain / amp_gain; + dat(plannergradiometer_index, 1:sample_length) = tmp_data; + clear tmp_gain; + + % Deletion of Inf row + index = find(plannergradiometer_ch_info(1,:) == Inf); + plannergradiometer_ch_info(:,index) = []; + + % Deletion of channel_type row + plannergradiometer_ch_info(:,2) = []; + + % Outputs to the global variable + handles.sqd.plannergradiometer_ch_info = plannergradiometer_ch_info; + handles.sqd.plannergradiometer_ch_no = tmp_ch_no; + handles.sqd.plannergradiometer_data = [ tmp_ch_no tmp_data]; + clear tmp_data; +end + +%%% Pulling out EegChannel Channel and value conversion to Volt units. +if ~isempty(eegchannel_index_tmp) + % Acquisition of channel information + eegchannel_index = eegchannel_index_tmp; + + % Value conversion + % B = ADValue * VoltRange / ADRange + tmp_ch_no = channum(eegchannel_index, 1); + tmp_data = dat(eegchannel_index, 1:sample_length); + ad_range = 5/2^(hdr.ad_bit-1); + tmp_data = tmp_data * ad_range; + dat(eegchannel_index, 1:sample_length) = tmp_data; + + % Outputs to the global variable + handles.sqd.eegchannel_ch_no = tmp_ch_no; + handles.sqd.eegchannel_data = [ tmp_ch_no tmp_data]; + clear tmp_data; +end + +%%% Pulling out Null Channel and value conversion to Volt units. +if ~isempty(nullchannel_index_tmp) + % Acquisition of channel information + nullchannel_index = nullchannel_index_tmp; + + % Value conversion + % B = ADValue * VoltRange / ADRange + tmp_ch_no = channum(nullchannel_index, 1); + tmp_data = dat(nullchannel_index, 1:sample_length); + ad_range = 5/2^(hdr.ad_bit-1); + tmp_data = tmp_data * ad_range; + dat(nullchannel_index, 1:sample_length) = tmp_data; + + % Outputs to the global variable + handles.sqd.nullchannel_ch_no = tmp_ch_no; + handles.sqd.nullchannel_data = [ tmp_ch_no tmp_data]; + clear tmp_data; +end + +% select only the desired channels +dat = dat(chanindx,:); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% this defines some usefull constants +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function handles = definehandles +handles.output = []; +handles.sqd_load_flag = false; +handles.mri_load_flag = false; +handles.NullChannel = 0; +handles.MagnetoMeter = 1; +handles.AxialGradioMeter = 2; +handles.PlannerGradioMeter = 3; +handles.RefferenceChannelMark = hex2dec('0100'); +handles.RefferenceMagnetoMeter = bitor( handles.RefferenceChannelMark, handles.MagnetoMeter ); +handles.RefferenceAxialGradioMeter = bitor( handles.RefferenceChannelMark, handles.AxialGradioMeter ); +handles.RefferencePlannerGradioMeter = bitor( handles.RefferenceChannelMark, handles.PlannerGradioMeter ); +handles.TriggerChannel = -1; +handles.EegChannel = -2; +handles.EcgChannel = -3; +handles.EtcChannel = -4; +handles.NonMegChannelNameLength = 32; +handles.DefaultMagnetometerSize = (4.0/1000.0); % Square of 4.0mm in length +handles.DefaultAxialGradioMeterSize = (15.5/1000.0); % Circle of 15.5mm in diameter +handles.DefaultPlannerGradioMeterSize = (12.0/1000.0); % Square of 12.0mm in length +handles.AcqTypeContinuousRaw = 1; +handles.AcqTypeEvokedAve = 2; +handles.AcqTypeEvokedRaw = 3; +handles.sqd = []; +handles.sqd.selected_start = []; +handles.sqd.selected_end = []; +handles.sqd.axialgradiometer_ch_no = []; +handles.sqd.axialgradiometer_ch_info = []; +handles.sqd.axialgradiometer_data = []; +handles.sqd.plannergradiometer_ch_no = []; +handles.sqd.plannergradiometer_ch_info = []; +handles.sqd.plannergradiometer_data = []; +handles.sqd.eegchannel_ch_no = []; +handles.sqd.eegchannel_data = []; +handles.sqd.nullchannel_ch_no = []; +handles.sqd.nullchannel_data = []; +handles.sqd.selected_time = []; +handles.sqd.sample_rate = []; +handles.sqd.sample_count = []; +handles.sqd.pretrigger_length = []; +handles.sqd.matching_info = []; +handles.sqd.source_info = []; +handles.sqd.mri_info = []; +handles.mri = []; diff --git a/external/fieldtrip/fileio/private/read_yokogawa_event.m b/external/fieldtrip/fileio/private/read_yokogawa_event.m new file mode 100644 index 0000000..7ebea02 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_yokogawa_event.m @@ -0,0 +1,126 @@ +function [event] = read_yokogawa_event(filename, varargin) + +% READ_YOKOGAWA_EVENT reads event information from continuous, +% epoched or averaged MEG data that has been generated by the Yokogawa +% MEG system and software and allows those events to be used in +% combination with FieldTrip. +% +% Use as +% [event] = read_yokogawa_event(filename) +% +% See also READ_YOKOGAWA_HEADER, READ_YOKOGAWA_DATA + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_yokogawa_event.m 1114 2010-05-20 08:36:03Z tilsan $ + +if ~hasyokogawa('16bitBeta6') + error('cannot determine whether Yokogawa toolbox is present'); +end + +% get the options +trigindx = keyval('trigindx', varargin); % default is based on chantype helper function + +event = []; +handles = definehandles; + +% read the dataset header +hdr = read_yokogawa_header(filename); + +if hdr.orig.acq_type==handles.AcqTypeEvokedRaw + % read the trigger id from all trials + fid = fopen(filename, 'r'); + value = GetMeg160TriggerEventM(fid); + fclose(fid); + % use the standard FieldTrip header for trial events + % make an event for each trial as defined in the header + for i=1:hdr.nTrials + event(end+1).type = 'trial'; + event(end ).sample = (i-1)*hdr.nSamples + 1; + event(end ).offset = -hdr.nSamplesPre; + event(end ).duration = hdr.nSamples; + + if ~isempty(value) + event(end ).value = value(i); + end + end + +elseif hdr.orig.acq_type==handles.AcqTypeEvokedAve + % make an event for the average + event(1).type = 'average'; + event(1).sample = 1; + event(1).offset = -hdr.nSamplesPre; + event(1).duration = hdr.nSamples; + +elseif hdr.orig.acq_type==handles.AcqTypeContinuousRaw + % read the trigger channel and detect the flanks + if isempty(trigindx) + trigindx = find(hdr.orig.channel_info(:,2)==handles.TriggerChannel); + end + event = read_trigger(filename, 'header', hdr, 'chanindx', trigindx, 'detectflank', 'both'); + +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% this defines some usefull constants +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function handles = definehandles; +handles.output = []; +handles.sqd_load_flag = false; +handles.mri_load_flag = false; +handles.NullChannel = 0; +handles.MagnetoMeter = 1; +handles.AxialGradioMeter = 2; +handles.PlannerGradioMeter = 3; +handles.RefferenceChannelMark = hex2dec('0100'); +handles.RefferenceMagnetoMeter = bitor( handles.RefferenceChannelMark, handles.MagnetoMeter ); +handles.RefferenceAxialGradioMeter = bitor( handles.RefferenceChannelMark, handles.AxialGradioMeter ); +handles.RefferencePlannerGradioMeter = bitor( handles.RefferenceChannelMark, handles.PlannerGradioMeter ); +handles.TriggerChannel = -1; +handles.EegChannel = -2; +handles.EcgChannel = -3; +handles.EtcChannel = -4; +handles.NonMegChannelNameLength = 32; +handles.DefaultMagnetometerSize = (4.0/1000.0); % Square of 4.0mm in length +handles.DefaultAxialGradioMeterSize = (15.5/1000.0); % Circle of 15.5mm in diameter +handles.DefaultPlannerGradioMeterSize = (12.0/1000.0); % Square of 12.0mm in length +handles.AcqTypeContinuousRaw = 1; +handles.AcqTypeEvokedAve = 2; +handles.AcqTypeEvokedRaw = 3; +handles.sqd = []; +handles.sqd.selected_start = []; +handles.sqd.selected_end = []; +handles.sqd.axialgradiometer_ch_no = []; +handles.sqd.axialgradiometer_ch_info = []; +handles.sqd.axialgradiometer_data = []; +handles.sqd.plannergradiometer_ch_no = []; +handles.sqd.plannergradiometer_ch_info = []; +handles.sqd.plannergradiometer_data = []; +handles.sqd.eegchannel_ch_no = []; +handles.sqd.eegchannel_data = []; +handles.sqd.nullchannel_ch_no = []; +handles.sqd.nullchannel_data = []; +handles.sqd.selected_time = []; +handles.sqd.sample_rate = []; +handles.sqd.sample_count = []; +handles.sqd.pretrigger_length = []; +handles.sqd.matching_info = []; +handles.sqd.source_info = []; +handles.sqd.mri_info = []; +handles.mri = []; diff --git a/external/fieldtrip/fileio/private/read_yokogawa_header.m b/external/fieldtrip/fileio/private/read_yokogawa_header.m new file mode 100644 index 0000000..d8ca5d5 --- /dev/null +++ b/external/fieldtrip/fileio/private/read_yokogawa_header.m @@ -0,0 +1,223 @@ +function hdr = read_yokogawa_header(filename) + + +% READ_YOKOGAWA_HEADER reads the header information from continuous, +% epoched or averaged MEG data that has been generated by the Yokogawa +% MEG system and software and allows that data to be used in combination +% with FieldTrip. +% +% Use as +% [hdr] = read_yokogawa_header(filename) +% +% This is a wrapper function around the functions +% GetMeg160SystemInfoM +% GetMeg160ChannelCountM +% GetMeg160ChannelInfoM +% GetMeg160CalibInfoM +% GetMeg160AmpGainM +% GetMeg160DataAcqTypeM +% GetMeg160ContinuousAcqCondM +% GetMeg160EvokedAcqCondM +% +% See also READ_YOKOGAWA_DATA, READ_YOKOGAWA_EVENT + +% this function also calls +% GetMeg160MriInfoM +% GetMeg160MatchingInfoM +% GetMeg160SourceInfoM +% but I don't know whether to use the information provided by those + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_yokogawa_header.m 1112 2010-05-20 08:33:18Z tilsan $ + +% FIXED +% txt -> m +% fopen iee-le + +if ~hasyokogawa('16bitBeta6') + error('cannot determine whether Yokogawa toolbox is present'); +end + +handles = definehandles; +fid = fopen(filename, 'rb', 'ieee-le'); + +% these are always present +[id ver rev sys_name] = GetMeg160SystemInfoM(fid); +channel_count = GetMeg160ChannelCountM(fid); +channel_info = GetMeg160ChannelInfoM(fid); +calib_info = GetMeg160CalibInfoM(fid); +amp_gain = GetMeg160AmpGainM(fid); +acq_type = GetMeg160DataAcqTypeM(fid); +ad_bit = GetMeg160ADbitInfoM(fid); + +% these depend on the data type +sample_rate = []; +sample_count = []; +pretrigger_length = []; +averaged_count = []; +actual_epoch_count = []; + +switch acq_type + case handles.AcqTypeContinuousRaw + [sample_rate, sample_count] = GetMeg160ContinuousAcqCondM(fid); + if isempty(sample_rate) | isempty(sample_count) + fclose(fid); + return; + end + pretrigger_length = 0; + averaged_count = 1; + + case handles.AcqTypeEvokedAve + [sample_rate, sample_count, pretrigger_length, averaged_count] = GetMeg160EvokedAcqCondM( fid ); + if isempty(sample_rate) | isempty(sample_count) | isempty(pretrigger_length) | isempty(averaged_count) + fclose(fid); + return; + end + + case handles.AcqTypeEvokedRaw + [sample_rate, sample_count, pretrigger_length, actual_epoch_count] = GetMeg160EvokedAcqCondM( fid ); + if isempty(sample_rate) | isempty(sample_count) | isempty(pretrigger_length) | isempty(actual_epoch_count) + fclose(fid); + return; + end + + otherwise + error('unknown data type'); +end + +% these are always present +mri_info = GetMeg160MriInfoM(fid); +matching_info = GetMeg160MatchingInfoM(fid); +source_info = GetMeg160SourceInfoM(fid); + +fclose(fid); + +% put all local variables into a structure, this is a bit unusual matlab programming style +tmp = whos; +orig = []; +for i=1:length(tmp) + if isempty(strmatch(tmp(i).name, {'tmp', 'fid', 'ans', 'handles'})) + orig = setfield(orig, tmp(i).name, eval(tmp(i).name)); + end +end + +% convert the original header information into something that FieldTrip understands +hdr = []; +hdr.orig = orig; % also store the original full header information +hdr.Fs = orig.sample_rate; % sampling frequency +hdr.nChans = orig.channel_count; % number of channels +hdr.nSamples = []; % number of samples per trial +hdr.nSamplesPre = []; % number of pre-trigger samples in each trial +hdr.nTrials = []; % number of trials + +switch orig.acq_type + case handles.AcqTypeEvokedAve + hdr.nSamples = orig.sample_count; + hdr.nSamplesPre = orig.pretrigger_length; + hdr.nTrials = 1; % only the average, which can be considered as a single trial + case handles.AcqTypeContinuousRaw + hdr.nSamples = orig.sample_count; + hdr.nSamplesPre = 0; % there is no fixed relation between triggers and data + hdr.nTrials = 1; % the continuous data can be considered as a single very long trial + case handles.AcqTypeEvokedRaw + hdr.nSamples = orig.sample_count; + hdr.nSamplesPre = orig.pretrigger_length; + hdr.nTrials = orig.actual_epoch_count; + otherwise + error('unknown acquisition type'); +end + +% construct a cell-array with labels of each channel +for i=1:hdr.nChans +% this should be consistent with the predefined list in ft_senslabel, +% with yokogawa2grad and with ft_channelselection + if hdr.orig.channel_info(i, 2) == handles.NullChannel + prefix = ''; + elseif hdr.orig.channel_info(i, 2) == handles.MagnetoMeter + prefix = 'M'; + elseif hdr.orig.channel_info(i, 2) == handles.AxialGradioMeter + prefix = 'AG'; + elseif hdr.orig.channel_info(i, 2) == handles.PlannerGradioMeter + prefix = 'PG'; + elseif hdr.orig.channel_info(i, 2) == handles.RefferenceMagnetoMeter + prefix = 'RM'; + elseif hdr.orig.channel_info(i, 2) == handles.RefferenceAxialGradioMeter + prefix = 'RAG'; + elseif hdr.orig.channel_info(i, 2) == handles.RefferencePlannerGradioMeter + prefix = 'RPG'; + elseif hdr.orig.channel_info(i, 2) == handles.TriggerChannel + prefix = 'TRIG'; + elseif hdr.orig.channel_info(i, 2) == handles.EegChannel + prefix = 'EEG'; + elseif hdr.orig.channel_info(i, 2) == handles.EcgChannel + prefix = 'ECG'; + elseif hdr.orig.channel_info(i, 2) == handles.EtcChannel + prefix = 'ETC'; + end + hdr.label{i} = sprintf('%s%03d', prefix, i); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% this defines some usefull constants +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function handles = definehandles; +handles.output = []; +handles.sqd_load_flag = false; +handles.mri_load_flag = false; +handles.NullChannel = 0; +handles.MagnetoMeter = 1; +handles.AxialGradioMeter = 2; +handles.PlannerGradioMeter = 3; +handles.RefferenceChannelMark = hex2dec('0100'); +handles.RefferenceMagnetoMeter = bitor( handles.RefferenceChannelMark, handles.MagnetoMeter ); +handles.RefferenceAxialGradioMeter = bitor( handles.RefferenceChannelMark, handles.AxialGradioMeter ); +handles.RefferencePlannerGradioMeter = bitor( handles.RefferenceChannelMark, handles.PlannerGradioMeter ); +handles.TriggerChannel = -1; +handles.EegChannel = -2; +handles.EcgChannel = -3; +handles.EtcChannel = -4; +handles.NonMegChannelNameLength = 32; +handles.DefaultMagnetometerSize = (4.0/1000.0); % Square of 4.0mm in length +handles.DefaultAxialGradioMeterSize = (15.5/1000.0); % Circle of 15.5mm in diameter +handles.DefaultPlannerGradioMeterSize = (12.0/1000.0); % Square of 12.0mm in length +handles.AcqTypeContinuousRaw = 1; +handles.AcqTypeEvokedAve = 2; +handles.AcqTypeEvokedRaw = 3; +handles.sqd = []; +handles.sqd.selected_start = []; +handles.sqd.selected_end = []; +handles.sqd.axialgradiometer_ch_no = []; +handles.sqd.axialgradiometer_ch_info = []; +handles.sqd.axialgradiometer_data = []; +handles.sqd.plannergradiometer_ch_no = []; +handles.sqd.plannergradiometer_ch_info = []; +handles.sqd.plannergradiometer_data = []; +handles.sqd.eegchannel_ch_no = []; +handles.sqd.eegchannel_data = []; +handles.sqd.nullchannel_ch_no = []; +handles.sqd.nullchannel_data = []; +handles.sqd.selected_time = []; +handles.sqd.sample_rate = []; +handles.sqd.sample_count = []; +handles.sqd.pretrigger_length = []; +handles.sqd.matching_info = []; +handles.sqd.source_info = []; +handles.sqd.mri_info = []; +handles.mri = []; diff --git a/external/fieldtrip/fileio/private/read_zebris.m b/external/fieldtrip/fileio/private/read_zebris.m new file mode 100644 index 0000000..1dcffaa --- /dev/null +++ b/external/fieldtrip/fileio/private/read_zebris.m @@ -0,0 +1,105 @@ +function [fid, sens, label, sens_label] = read_zebris(Fname_zeb,skip) + +% Reads Zebris files: +% fiducials locations, and +% either sensor file or headshape file or both +% +% FORMAT [fid, sens, label] = read_zebris(Fname_zeb,skip) +% Input: +% Fname_zeb - Zebris ASCII file containing sensor locations (mm) +% (headshape can also be considered here instead of sensors) +% skip - first channels to skip +% +% Output: +% fid - fiducial locations (mm) in rows +% sens - sensor/headshape locations (mm) in rows +% label - labels of the fiducials +% sens_label - labels of the surface points, electrodes + headshape +% +% IMPORTANT: Note that Zebris data files should be -ASCII files with +% extension .sfp +% It is assumed that the .sfp file contains the location (mm) of fiducials +% (possibly twice), possibly followed by some additional named points for +% the electrodes, and then so more named location starting with 'sfl' for +% headshape locations. +% In some instances the first few channel locations may pertain to +% reference channels; the skip variable allows these to be skipped if +% necessary. +% The fiducial locations are flaged with the strings 'fidt9','fidnz' and +% 'fidt10'; indicating the leaft ear, nasion, and right ear, respectively. +% _________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Christophe Phillips +% $Id: read_zebris.m 1123 2010-05-20 12:13:26Z roboos $ + + +% checks and assigments +%-------------------------------------------------------------------------- +try, skip; catch, skip = 0; end + +[pth,nam,ext] = fileparts(Fname_zeb); +if ~strcmp(ext,'.sfp') + warndlg(sprintf('Wrong input file format\n')); + return +end + + +% --- READ Zebris Sensor + fiducial locations --- +%========================================================================== +try + file = textread(Fname_zeb,'%s'); +catch + file = textread(fullfile(pwd,[nam ext]),'%s'); +end +% remove zeros at the end +bool = 0; +while bool == 0 + if strcmp(file{end},'0') + file = file(1:end-1); + else + bool = 1; + end +end + +% read fiducials +%-------------------------------------------------------------------------- +NZ = []; +LE = []; +RE = []; +temp = 0; +nl = 1; + +while temp == 0 + if strcmp(file{nl},'fidnz') + NZ = [NZ ; str2num(file{nl+1}) str2num(file{nl+2}) str2num(file{nl+3}) ]; + nl = nl + 4; + elseif strcmp(file{nl},'fidt9') + LE = [LE ; str2num(file{nl+1}) str2num(file{nl+2}) str2num(file{nl+3}) ]; + nl = nl + 4; + elseif strcmp(file{nl},'fidt10') + RE = [RE ; str2num(file{nl+1}) str2num(file{nl+2}) str2num(file{nl+3}) ]; + nl = nl + 4; + else + temp = 1; + end +end + +% convert from cm to mm +%-------------------------------------------------------------------------- +NZ = mean(NZ,1); LE = mean(LE,1); RE = mean(RE,1); +fid = [NZ; LE; RE]; + +label = [{'nas', 'lpa', 'rpa'}]; + +% read sensor locations or headshape locations +%-------------------------------------------------------------------------- +sens = []; +sens_label = []; + +start = nl + skip*3; +for ii = start:4:length(file) + sens_label = [sens_label, file(ii)]; + sens = [sens; ... + str2num(file{ii+1}) str2num(file{ii+2}) str2num(file{ii+3})]; +end diff --git a/external/fieldtrip/fileio/private/readbdf.m b/external/fieldtrip/fileio/private/readbdf.m new file mode 100644 index 0000000..28d56df --- /dev/null +++ b/external/fieldtrip/fileio/private/readbdf.m @@ -0,0 +1,96 @@ +% readbdf() - Loads selected Records of an EDF or BDF File (European Data Format +% for Biosignals) into MATLAB +% Usage: +% >> [DAT,signal] = readedf(EDF_Struct,Records,Mode); +% Notes: +% Records - List of Records for Loading +% Mode - 0 Default +% 1 No AutoCalib +% 2 Concatenated (channels with lower sampling rate +% if more than 1 record is loaded) +% Output: +% DAT - EDF data structure +% signal - output signal +% +% Author: Alois Schloegl, 03.02.1998, updated T.S. Lorig Sept 6, 2002 for BDF read +% +% See also: openbdf(), sdfopen(), sdfread(), eeglab() + +% Version 2.11 +% 03.02.1998 +% Copyright (c) 1997,98 by Alois Schloegl +% a.schloegl@ieee.org + +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% This program has been modified from the original version for .EDF files +% The modifications are to the number of bytes read on line 53 (from 2 to +% 3) and to the type of data read - line 54 (from int16 to bit24). Finally the name +% was changed from readedf to readbdf +% T.S. Lorig Sept 6, 2002 +% +% Header modified for eeglab() compatibility - Arnaud Delorme 12/02 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [DAT,S]=readbdf(DAT,Records,Mode) +if nargin<3 Mode=0; end; + +EDF=DAT.Head; +RecLen=max(EDF.SPR); + +S=NaN*zeros(RecLen,EDF.NS); +DAT.Record=zeros(length(Records)*RecLen,EDF.NS); +DAT.Valid=uint8(zeros(1,length(Records)*RecLen)); +DAT.Idx=Records(:)'; + +for nrec=1:length(Records), + + NREC=(DAT.Idx(nrec)-1); + if NREC<0 fprintf(2,'Warning READEDF: invalid Record Number %i \n',NREC);end; + + fseek(EDF.FILE.FID,(EDF.HeadLen+NREC*EDF.AS.spb*3),'bof'); + [s, count]=fread(EDF.FILE.FID,EDF.AS.spb,'bit24'); + + try, + S(EDF.AS.IDX2)=s; + catch, + error('File is incomplete (try reading begining of file)'); + end; + + %%%%% Test on Over- (Under-) Flow +% V=sum([(S'==EDF.DigMax(:,ones(RecLen,1))) + (S'==EDF.DigMin(:,ones(RecLen,1)))])==0; + V=sum([(S(:,EDF.Chan_Select)'>=EDF.DigMax(EDF.Chan_Select,ones(RecLen,1))) + ... + (S(:,EDF.Chan_Select)'<=EDF.DigMin(EDF.Chan_Select,ones(RecLen,1)))])==0; + EDF.ERROR.DigMinMax_Warning(find(sum([(S'>EDF.DigMax(:,ones(RecLen,1))) + (S'0))=1; + % invalid=[invalid; find(V==0)+l*k]; + + if floor(Mode/2)==1 + for k=1:EDF.NS, + DAT.Record(nrec*EDF.SPR(k)+(1-EDF.SPR(k):0),k)=S(1:EDF.SPR(k),k); + end; + else + DAT.Record(nrec*RecLen+(1-RecLen:0),:)=S; + end; + + DAT.Valid(nrec*RecLen+(1-RecLen:0))=V; +end; +if rem(Mode,2)==0 % Autocalib + DAT.Record=[ones(RecLen*length(Records),1) DAT.Record]*EDF.Calib; +end; + +DAT.Record=DAT.Record'; +return; + diff --git a/external/fileio/private/readmarkerfile.m b/external/fieldtrip/fileio/private/readmarkerfile.m similarity index 87% rename from external/fileio/private/readmarkerfile.m rename to external/fieldtrip/fileio/private/readmarkerfile.m index 1b60585..2faa71c 100644 --- a/external/fileio/private/readmarkerfile.m +++ b/external/fieldtrip/fileio/private/readmarkerfile.m @@ -16,7 +16,7 @@ while true l = fgetl(f); if ~isstr(l) - break + break end markfile{end + 1} = l; end @@ -36,7 +36,7 @@ for i = 1:length(nsamples) if nsamples(i) == 0 - warning('marker %s in %s has zero samples', names{i}, folder); + warning('marker %s in %s has zero samples', names{i}, folder); end end @@ -47,10 +47,10 @@ % Convert from index origin 0 to 1 if nsamples(i) ~= 0 - marks{i}(:, 1) = marks{i}(:, 1) + 1; + marks{i}(:, 1) = marks{i}(:, 1) + 1; end end data = struct('number_markers', {nmarkers}, 'number_samples', {nsamples}, ... - 'marker_names', {names}, 'trial_times', {marks}); + 'marker_names', {names}, 'trial_times', {marks}); diff --git a/external/fieldtrip/fileio/private/rmsubfield.m b/external/fieldtrip/fileio/private/rmsubfield.m new file mode 100644 index 0000000..4d8752f --- /dev/null +++ b/external/fieldtrip/fileio/private/rmsubfield.m @@ -0,0 +1,46 @@ +function [s] = rmsubfield(s, f, v); + +% RMSUBFIELD removes the contents of the specified field from a structure +% just like the standard Matlab RMFIELD function, except that you can also +% specify nested fields using a '.' in the fieldname. The nesting can be +% arbitrary deep. +% +% Use as +% s = rmsubfield(s, 'fieldname') +% or as +% s = rmsubfield(s, 'fieldname.subfieldname') +% +% See also SETFIELD, GETSUBFIELD, ISSUBFIELD + +% Copyright (C) 2006, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: rmsubfield.m 951 2010-04-21 18:24:01Z roboos $ + +if ~isstr(f) + error('incorrect input argument for fieldname'); +end + +% remove the nested subfield using recursion +[t, f] = strtok(f, '.'); +if any(f=='.') + u = rmsubfield(getfield(s, t), f); + s = setfield(s, t, u); +else + s = rmfield(s, t); +end diff --git a/external/fieldtrip/fileio/private/sap2matlab.m b/external/fieldtrip/fileio/private/sap2matlab.m new file mode 100644 index 0000000..53e64bd --- /dev/null +++ b/external/fieldtrip/fileio/private/sap2matlab.m @@ -0,0 +1,30 @@ +function SP=sap2matlab(blob) +% SAP2MATLAB parses Siemens ASCII protocol data and generates a +% corresponding MATLAB data structure. Use as +% +% SP = sap2matlab(blob) +% +% where 'blob' needs to be of type uint8 or char. This function +% is currently used for de-serialising the header information +% from a FieldTrip buffer containing fMRI data from a Siemens +% scanner. +% +% The sources for the MEX-file are in the realtime/siemens directory, +% but calling the .m-file will try to compile automatically. +% +% Copyright (C) 2010, Stefan Klanke + +warning('Trying to compile MEX file') +oldDir = pwd; +[srcDir, srcName] = fileparts(mfilename('fullpath')); +try + cd(srcDir); % we're now in private + cd('../../realtime/siemens'); + mex -outdir ../../fileio/private sap2matlab.c siemensap.c -I. + cd(oldDir); + SP = sap2matlab(blob); +catch + cd(oldDir); + rethrow(lasterror) +end + diff --git a/external/fieldtrip/fileio/private/senslabel.m b/external/fieldtrip/fileio/private/senslabel.m new file mode 100644 index 0000000..4242fb1 --- /dev/null +++ b/external/fieldtrip/fileio/private/senslabel.m @@ -0,0 +1,2808 @@ +function label = ft_senslabel(type) + +% FT_SENSLABEL returns a list of sensor labels given the MEEG system type +% +% Use as +% label = ft_senslabel(type) +% +% The input type can be any of the following +% 'biosemi64' +% 'biosemi128' +% 'biosemi256' +% 'bti148' +% 'bti148_planar' +% 'bti248' +% 'bti248_planar' +% 'btiref' +% 'ctf151' +% 'ctf151_planar' +% 'ctf275' +% 'ctf275_planar' +% 'ctfheadloc' +% 'ctfref' +% 'eeg1005' +% 'eeg1010' +% 'eeg1020' +% 'egi128' +% 'egi256' +% 'egi32' +% 'egi64' +% 'ext1020' +% 'neuromag122' +% 'neuromag122alt' +% 'neuromag306' +% 'neuromag306alt' +% 'itab153' +% 'itab153_planar' +% 'yokogawa160' +% 'yokogawa160_planar' +% 'electrode' +% +% See also FT_SENSTYPE, FT_CHANNELSELECTION + +% FIXME one channel is missing for ctf275 + +% Copyright (C) 2007-2008, Robert Oostenveld +% Copyright (C) 2008, Vladimir Litvak +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_senslabel.m 1006 2010-05-03 08:36:13Z roboos $ + +% these are for remembering the type on subsequent calls with the same input arguments +persistent previous_argin previous_argout + +if nargin<1 + % ensure that all input arguments are defined + type = []; +end + +current_argin = {type}; +if isequal(current_argin, previous_argin) + % don't do the type detection again, but return the previous values from cache + label = previous_argout{1}; + return +end + +switch type + + case 'btiref' + label = { + 'MRxA' + 'MRyA' + 'MRzA' + 'MLxA' + 'MLyA' + 'MLzA' + 'MCxA' + 'MCyA' + 'MCzA' + 'MRxaA' + 'MRyaA' + 'MRzaA' + 'MLxaA' + 'MLyaA' + 'MLzaA' + 'MCxaA' + 'MCyaA' + 'MCzaA' + 'GxxA' + 'GyxA' + 'GzxA' + 'GyyA' + 'GzyA' + }; + + case 'bti148' + label = cell(148,1); + for i=1:148 + label{i,1} = sprintf('A%d', i); + end + + case 'bti148_planar' + label = cell(148,2); + for i=1:148 + label{i,1} = sprintf('A%d_dH', i); + label{i,2} = sprintf('A%d_dV', i); + end + + case 'bti248' + label = cell(248,1); + for i=1:248 + label{i,1} = sprintf('A%d', i); + end + + case 'bti248_planar' + label = cell(248,2); + for i=1:248 + label{i,1} = sprintf('A%d_dH', i); + label{i,2} = sprintf('A%d_dV', i); + end + + case 'ctfref' + label = { + 'BG1' + 'BG2' + 'BG3' + 'BP1' + 'BP2' + 'BP3' + 'BR1' + 'BR2' + 'BR3' + 'G11' + 'G12' + 'G13' + 'G22' + 'G23' + 'P11' + 'P12' + 'P13' + 'P22' + 'P23' + 'Q11' + 'Q12' + 'Q13' + 'Q22' + 'Q23' + 'R11' + 'R12' + 'R13' + 'R22' + 'R23' + }; + + case 'ctfheadloc' + label = { + 'HLC0011' + 'HLC0012' + 'HLC0013' + 'HLC0021' + 'HLC0022' + 'HLC0023' + 'HLC0031' + 'HLC0032' + 'HLC0033' + 'HLC0018' + 'HLC0028' + 'HLC0038' + 'HLC0014' + 'HLC0015' + 'HLC0016' + 'HLC0017' + 'HLC0024' + 'HLC0025' + 'HLC0026' + 'HLC0027' + 'HLC0034' + 'HLC0035' + 'HLC0036' + 'HLC0037' + }; + + case 'ctf64' + label = { + 'SL11' + 'SL12' + 'SL13' + 'SL14' + 'SL15' + 'SL16' + 'SL17' + 'SL18' + 'SL19' + 'SL21' + 'SL22' + 'SL23' + 'SL24' + 'SL25' + 'SL26' + 'SL27' + 'SL28' + 'SL29' + 'SL31' + 'SL32' + 'SL33' + 'SL34' + 'SL35' + 'SL41' + 'SL42' + 'SL43' + 'SL44' + 'SL45' + 'SL46' + 'SL47' + 'SL51' + 'SL52' + 'SR11' + 'SR12' + 'SR13' + 'SR14' + 'SR15' + 'SR16' + 'SR17' + 'SR18' + 'SR19' + 'SR21' + 'SR22' + 'SR23' + 'SR24' + 'SR25' + 'SR26' + 'SR27' + 'SR28' + 'SR29' + 'SR31' + 'SR32' + 'SR33' + 'SR34' + 'SR35' + 'SR41' + 'SR42' + 'SR43' + 'SR44' + 'SR45' + 'SR46' + 'SR47' + 'SR51' + 'SR52' + }; + + case 'ctf151' + label = { + 'MLC11' + 'MLC12' + 'MLC13' + 'MLC14' + 'MLC15' + 'MLC21' + 'MLC22' + 'MLC23' + 'MLC24' + 'MLC31' + 'MLC32' + 'MLC33' + 'MLC41' + 'MLC42' + 'MLC43' + 'MLF11' + 'MLF12' + 'MLF21' + 'MLF22' + 'MLF23' + 'MLF31' + 'MLF32' + 'MLF33' + 'MLF34' + 'MLF41' + 'MLF42' + 'MLF43' + 'MLF44' + 'MLF45' + 'MLF51' + 'MLF52' + 'MLO11' + 'MLO12' + 'MLO21' + 'MLO22' + 'MLO31' + 'MLO32' + 'MLO33' + 'MLO41' + 'MLO42' + 'MLO43' + 'MLP11' + 'MLP12' + 'MLP13' + 'MLP21' + 'MLP22' + 'MLP31' + 'MLP32' + 'MLP33' + 'MLP34' + 'MLT11' + 'MLT12' + 'MLT13' + 'MLT14' + 'MLT15' + 'MLT16' + 'MLT21' + 'MLT22' + 'MLT23' + 'MLT24' + 'MLT25' + 'MLT26' + 'MLT31' + 'MLT32' + 'MLT33' + 'MLT34' + 'MLT35' + 'MLT41' + 'MLT42' + 'MLT43' + 'MLT44' + 'MRC11' + 'MRC12' + 'MRC13' + 'MRC14' + 'MRC15' + 'MRC21' + 'MRC22' + 'MRC23' + 'MRC24' + 'MRC31' + 'MRC32' + 'MRC33' + 'MRC41' + 'MRC42' + 'MRC43' + 'MRF11' + 'MRF12' + 'MRF21' + 'MRF22' + 'MRF23' + 'MRF31' + 'MRF32' + 'MRF33' + 'MRF34' + 'MRF41' + 'MRF42' + 'MRF43' + 'MRF44' + 'MRF45' + 'MRF51' + 'MRF52' + 'MRO11' + 'MRO12' + 'MRO21' + 'MRO22' + 'MRO31' + 'MRO32' + 'MRO33' + 'MRO41' + 'MRO42' + 'MRO43' + 'MRP11' + 'MRP12' + 'MRP13' + 'MRP21' + 'MRP22' + 'MRP31' + 'MRP32' + 'MRP33' + 'MRP34' + 'MRT11' + 'MRT12' + 'MRT13' + 'MRT14' + 'MRT15' + 'MRT16' + 'MRT21' + 'MRT22' + 'MRT23' + 'MRT24' + 'MRT25' + 'MRT26' + 'MRT31' + 'MRT32' + 'MRT33' + 'MRT34' + 'MRT35' + 'MRT41' + 'MRT42' + 'MRT43' + 'MRT44' + 'MZC01' + 'MZC02' + 'MZF01' + 'MZF02' + 'MZF03' + 'MZO01' + 'MZO02' + 'MZP01' + 'MZP02' + }; + + case 'ctf151_planar' + label = { + 'MLC11_dH' 'MLC11_dV' + 'MLC12_dH' 'MLC12_dV' + 'MLC13_dH' 'MLC13_dV' + 'MLC14_dH' 'MLC14_dV' + 'MLC15_dH' 'MLC15_dV' + 'MLC21_dH' 'MLC21_dV' + 'MLC22_dH' 'MLC22_dV' + 'MLC23_dH' 'MLC23_dV' + 'MLC24_dH' 'MLC24_dV' + 'MLC31_dH' 'MLC31_dV' + 'MLC32_dH' 'MLC32_dV' + 'MLC33_dH' 'MLC33_dV' + 'MLC41_dH' 'MLC41_dV' + 'MLC42_dH' 'MLC42_dV' + 'MLC43_dH' 'MLC43_dV' + 'MLF11_dH' 'MLF11_dV' + 'MLF12_dH' 'MLF12_dV' + 'MLF21_dH' 'MLF21_dV' + 'MLF22_dH' 'MLF22_dV' + 'MLF23_dH' 'MLF23_dV' + 'MLF31_dH' 'MLF31_dV' + 'MLF32_dH' 'MLF32_dV' + 'MLF33_dH' 'MLF33_dV' + 'MLF34_dH' 'MLF34_dV' + 'MLF41_dH' 'MLF41_dV' + 'MLF42_dH' 'MLF42_dV' + 'MLF43_dH' 'MLF43_dV' + 'MLF44_dH' 'MLF44_dV' + 'MLF45_dH' 'MLF45_dV' + 'MLF51_dH' 'MLF51_dV' + 'MLF52_dH' 'MLF52_dV' + 'MLO11_dH' 'MLO11_dV' + 'MLO12_dH' 'MLO12_dV' + 'MLO21_dH' 'MLO21_dV' + 'MLO22_dH' 'MLO22_dV' + 'MLO31_dH' 'MLO31_dV' + 'MLO32_dH' 'MLO32_dV' + 'MLO33_dH' 'MLO33_dV' + 'MLO41_dH' 'MLO41_dV' + 'MLO42_dH' 'MLO42_dV' + 'MLO43_dH' 'MLO43_dV' + 'MLP11_dH' 'MLP11_dV' + 'MLP12_dH' 'MLP12_dV' + 'MLP13_dH' 'MLP13_dV' + 'MLP21_dH' 'MLP21_dV' + 'MLP22_dH' 'MLP22_dV' + 'MLP31_dH' 'MLP31_dV' + 'MLP32_dH' 'MLP32_dV' + 'MLP33_dH' 'MLP33_dV' + 'MLP34_dH' 'MLP34_dV' + 'MLT11_dH' 'MLT11_dV' + 'MLT12_dH' 'MLT12_dV' + 'MLT13_dH' 'MLT13_dV' + 'MLT14_dH' 'MLT14_dV' + 'MLT15_dH' 'MLT15_dV' + 'MLT16_dH' 'MLT16_dV' + 'MLT21_dH' 'MLT21_dV' + 'MLT22_dH' 'MLT22_dV' + 'MLT23_dH' 'MLT23_dV' + 'MLT24_dH' 'MLT24_dV' + 'MLT25_dH' 'MLT25_dV' + 'MLT26_dH' 'MLT26_dV' + 'MLT31_dH' 'MLT31_dV' + 'MLT32_dH' 'MLT32_dV' + 'MLT33_dH' 'MLT33_dV' + 'MLT34_dH' 'MLT34_dV' + 'MLT35_dH' 'MLT35_dV' + 'MLT41_dH' 'MLT41_dV' + 'MLT42_dH' 'MLT42_dV' + 'MLT43_dH' 'MLT43_dV' + 'MLT44_dH' 'MLT44_dV' + 'MRC11_dH' 'MRC11_dV' + 'MRC12_dH' 'MRC12_dV' + 'MRC13_dH' 'MRC13_dV' + 'MRC14_dH' 'MRC14_dV' + 'MRC15_dH' 'MRC15_dV' + 'MRC21_dH' 'MRC21_dV' + 'MRC22_dH' 'MRC22_dV' + 'MRC23_dH' 'MRC23_dV' + 'MRC24_dH' 'MRC24_dV' + 'MRC31_dH' 'MRC31_dV' + 'MRC32_dH' 'MRC32_dV' + 'MRC33_dH' 'MRC33_dV' + 'MRC41_dH' 'MRC41_dV' + 'MRC42_dH' 'MRC42_dV' + 'MRC43_dH' 'MRC43_dV' + 'MRF11_dH' 'MRF11_dV' + 'MRF12_dH' 'MRF12_dV' + 'MRF21_dH' 'MRF21_dV' + 'MRF22_dH' 'MRF22_dV' + 'MRF23_dH' 'MRF23_dV' + 'MRF31_dH' 'MRF31_dV' + 'MRF32_dH' 'MRF32_dV' + 'MRF33_dH' 'MRF33_dV' + 'MRF34_dH' 'MRF34_dV' + 'MRF41_dH' 'MRF41_dV' + 'MRF42_dH' 'MRF42_dV' + 'MRF43_dH' 'MRF43_dV' + 'MRF44_dH' 'MRF44_dV' + 'MRF45_dH' 'MRF45_dV' + 'MRF51_dH' 'MRF51_dV' + 'MRF52_dH' 'MRF52_dV' + 'MRO11_dH' 'MRO11_dV' + 'MRO12_dH' 'MRO12_dV' + 'MRO21_dH' 'MRO21_dV' + 'MRO22_dH' 'MRO22_dV' + 'MRO31_dH' 'MRO31_dV' + 'MRO32_dH' 'MRO32_dV' + 'MRO33_dH' 'MRO33_dV' + 'MRO41_dH' 'MRO41_dV' + 'MRO42_dH' 'MRO42_dV' + 'MRO43_dH' 'MRO43_dV' + 'MRP11_dH' 'MRP11_dV' + 'MRP12_dH' 'MRP12_dV' + 'MRP13_dH' 'MRP13_dV' + 'MRP21_dH' 'MRP21_dV' + 'MRP22_dH' 'MRP22_dV' + 'MRP31_dH' 'MRP31_dV' + 'MRP32_dH' 'MRP32_dV' + 'MRP33_dH' 'MRP33_dV' + 'MRP34_dH' 'MRP34_dV' + 'MRT11_dH' 'MRT11_dV' + 'MRT12_dH' 'MRT12_dV' + 'MRT13_dH' 'MRT13_dV' + 'MRT14_dH' 'MRT14_dV' + 'MRT15_dH' 'MRT15_dV' + 'MRT16_dH' 'MRT16_dV' + 'MRT21_dH' 'MRT21_dV' + 'MRT22_dH' 'MRT22_dV' + 'MRT23_dH' 'MRT23_dV' + 'MRT24_dH' 'MRT24_dV' + 'MRT25_dH' 'MRT25_dV' + 'MRT26_dH' 'MRT26_dV' + 'MRT31_dH' 'MRT31_dV' + 'MRT32_dH' 'MRT32_dV' + 'MRT33_dH' 'MRT33_dV' + 'MRT34_dH' 'MRT34_dV' + 'MRT35_dH' 'MRT35_dV' + 'MRT41_dH' 'MRT41_dV' + 'MRT42_dH' 'MRT42_dV' + 'MRT43_dH' 'MRT43_dV' + 'MRT44_dH' 'MRT44_dV' + 'MZC01_dH' 'MZC01_dV' + 'MZC02_dH' 'MZC02_dV' + 'MZF01_dH' 'MZF01_dV' + 'MZF02_dH' 'MZF02_dV' + 'MZF03_dH' 'MZF03_dV' + 'MZO01_dH' 'MZO01_dV' + 'MZO02_dH' 'MZO02_dV' + 'MZP01_dH' 'MZP01_dV' + 'MZP02_dH' 'MZP02_dV' + }; + + case 'ctf275' + label = { + 'MLC11' + 'MLC12' + 'MLC13' + 'MLC14' + 'MLC15' + 'MLC16' + 'MLC17' + 'MLC21' + 'MLC22' + 'MLC23' + 'MLC24' + 'MLC25' + 'MLC31' + 'MLC32' + 'MLC41' + 'MLC42' + 'MLC51' + 'MLC52' + 'MLC53' + 'MLC54' + 'MLC55' + 'MLC61' + 'MLC62' + 'MLC63' + 'MLF11' + 'MLF12' + 'MLF13' + 'MLF14' + 'MLF21' + 'MLF22' + 'MLF23' + 'MLF24' + 'MLF25' + 'MLF31' + 'MLF32' + 'MLF33' + 'MLF34' + 'MLF35' + 'MLF41' + 'MLF42' + 'MLF43' + 'MLF44' + 'MLF45' + 'MLF46' + 'MLF51' + 'MLF52' + 'MLF53' + 'MLF54' + 'MLF55' + 'MLF56' + 'MLF61' + 'MLF62' + 'MLF63' + 'MLF64' + 'MLF65' + 'MLF66' + 'MLF67' + 'MLO11' + 'MLO12' + 'MLO13' + 'MLO14' + 'MLO21' + 'MLO22' + 'MLO23' + 'MLO24' + 'MLO31' + 'MLO32' + 'MLO33' + 'MLO34' + 'MLO41' + 'MLO42' + 'MLO43' + 'MLO44' + 'MLO51' + 'MLO52' + 'MLO53' + 'MLP11' + 'MLP12' + 'MLP21' + 'MLP22' + 'MLP23' + 'MLP31' + 'MLP32' + 'MLP33' + 'MLP34' + 'MLP35' + 'MLP41' + 'MLP42' + 'MLP43' + 'MLP44' + 'MLP45' + 'MLP51' + 'MLP52' + 'MLP53' + 'MLP54' + 'MLP55' + 'MLP56' + 'MLP57' + 'MLT11' + 'MLT12' + 'MLT13' + 'MLT14' + 'MLT15' + 'MLT16' + 'MLT21' + 'MLT22' + 'MLT23' + 'MLT24' + 'MLT25' + 'MLT26' + 'MLT27' + 'MLT31' + 'MLT32' + 'MLT33' + 'MLT34' + 'MLT35' + 'MLT36' + 'MLT37' + 'MLT41' + 'MLT42' + 'MLT43' + 'MLT44' + 'MLT45' + 'MLT46' + 'MLT47' + 'MLT51' + 'MLT52' + 'MLT53' + 'MLT54' + 'MLT55' + 'MLT56' + 'MLT57' + 'MRC11' + 'MRC12' + 'MRC13' + 'MRC14' + 'MRC15' + 'MRC16' + 'MRC17' + 'MRC21' + 'MRC22' + 'MRC23' + 'MRC24' + 'MRC25' + 'MRC31' + 'MRC32' + 'MRC41' + 'MRC42' + 'MRC51' + 'MRC52' + 'MRC53' + 'MRC54' + 'MRC55' + 'MRC61' + 'MRC62' + 'MRC63' + 'MRF11' + 'MRF12' + 'MRF13' + 'MRF14' + 'MRF21' + 'MRF22' + 'MRF23' + 'MRF24' + 'MRF25' + 'MRF31' + 'MRF32' + 'MRF33' + 'MRF34' + 'MRF35' + 'MRF41' + 'MRF42' + 'MRF43' + 'MRF44' + 'MRF45' + 'MRF46' + 'MRF51' + 'MRF52' + 'MRF53' + 'MRF54' + 'MRF55' + 'MRF56' + 'MRF61' + 'MRF62' + 'MRF63' + 'MRF64' + 'MRF65' + 'MRF66' + 'MRF67' + 'MRO11' + 'MRO12' + 'MRO13' + 'MRO14' + 'MRO21' + 'MRO22' + 'MRO23' + 'MRO24' + 'MRO31' + 'MRO32' + 'MRO33' + 'MRO34' + 'MRO41' + 'MRO42' + 'MRO43' + 'MRO44' + 'MRO51' + 'MRO52' + 'MRO53' + 'MRP11' + 'MRP12' + 'MRP21' + 'MRP22' + 'MRP23' + 'MRP32' + 'MRP33' + 'MRP34' + 'MRP35' + 'MRP41' + 'MRP42' + 'MRP43' + 'MRP44' + 'MRP45' + 'MRP51' + 'MRP52' + 'MRP53' + 'MRP54' + 'MRP55' + 'MRP56' + 'MRP57' + 'MRT11' + 'MRT12' + 'MRT13' + 'MRT14' + 'MRT15' + 'MRT16' + 'MRT21' + 'MRT22' + 'MRT23' + 'MRT24' + 'MRT25' + 'MRT26' + 'MRT27' + 'MRT31' + 'MRT32' + 'MRT33' + 'MRT34' + 'MRT35' + 'MRT36' + 'MRT37' + 'MRT41' + 'MRT42' + 'MRT43' + 'MRT44' + 'MRT45' + 'MRT46' + 'MRT47' + 'MRT51' + 'MRT52' + 'MRT53' + 'MRT54' + 'MRT55' + 'MRT56' + 'MRT57' + 'MZC01' + 'MZC02' + 'MZC03' + 'MZC04' + 'MZF01' + 'MZF02' + 'MZF03' + 'MZO01' + 'MZO02' + 'MZO03' + 'MZP01' + }; + + case 'ctf275_planar' + % FIXME one channel seems to be missing + label = { + 'MLC11_dH' 'MLC11_dV' + 'MLC12_dH' 'MLC12_dV' + 'MLC13_dH' 'MLC13_dV' + 'MLC14_dH' 'MLC14_dV' + 'MLC15_dH' 'MLC15_dV' + 'MLC16_dH' 'MLC16_dV' + 'MLC17_dH' 'MLC17_dV' + 'MLC21_dH' 'MLC21_dV' + 'MLC22_dH' 'MLC22_dV' + 'MLC23_dH' 'MLC23_dV' + 'MLC24_dH' 'MLC24_dV' + 'MLC25_dH' 'MLC25_dV' + 'MLC31_dH' 'MLC31_dV' + 'MLC32_dH' 'MLC32_dV' + 'MLC41_dH' 'MLC41_dV' + 'MLC42_dH' 'MLC42_dV' + 'MLC51_dH' 'MLC51_dV' + 'MLC52_dH' 'MLC52_dV' + 'MLC53_dH' 'MLC53_dV' + 'MLC54_dH' 'MLC54_dV' + 'MLC55_dH' 'MLC55_dV' + 'MLC61_dH' 'MLC61_dV' + 'MLC62_dH' 'MLC62_dV' + 'MLC63_dH' 'MLC63_dV' + 'MLF11_dH' 'MLF11_dV' + 'MLF12_dH' 'MLF12_dV' + 'MLF13_dH' 'MLF13_dV' + 'MLF14_dH' 'MLF14_dV' + 'MLF21_dH' 'MLF21_dV' + 'MLF22_dH' 'MLF22_dV' + 'MLF23_dH' 'MLF23_dV' + 'MLF24_dH' 'MLF24_dV' + 'MLF25_dH' 'MLF25_dV' + 'MLF31_dH' 'MLF31_dV' + 'MLF32_dH' 'MLF32_dV' + 'MLF33_dH' 'MLF33_dV' + 'MLF34_dH' 'MLF34_dV' + 'MLF35_dH' 'MLF35_dV' + 'MLF41_dH' 'MLF41_dV' + 'MLF42_dH' 'MLF42_dV' + 'MLF43_dH' 'MLF43_dV' + 'MLF44_dH' 'MLF44_dV' + 'MLF45_dH' 'MLF45_dV' + 'MLF46_dH' 'MLF46_dV' + 'MLF51_dH' 'MLF51_dV' + 'MLF52_dH' 'MLF52_dV' + 'MLF53_dH' 'MLF53_dV' + 'MLF54_dH' 'MLF54_dV' + 'MLF55_dH' 'MLF55_dV' + 'MLF56_dH' 'MLF56_dV' + 'MLF61_dH' 'MLF61_dV' + 'MLF62_dH' 'MLF62_dV' + 'MLF63_dH' 'MLF63_dV' + 'MLF64_dH' 'MLF64_dV' + 'MLF65_dH' 'MLF65_dV' + 'MLF66_dH' 'MLF66_dV' + 'MLF67_dH' 'MLF67_dV' + 'MLO11_dH' 'MLO11_dV' + 'MLO12_dH' 'MLO12_dV' + 'MLO13_dH' 'MLO13_dV' + 'MLO14_dH' 'MLO14_dV' + 'MLO21_dH' 'MLO21_dV' + 'MLO22_dH' 'MLO22_dV' + 'MLO23_dH' 'MLO23_dV' + 'MLO24_dH' 'MLO24_dV' + 'MLO31_dH' 'MLO31_dV' + 'MLO32_dH' 'MLO32_dV' + 'MLO33_dH' 'MLO33_dV' + 'MLO34_dH' 'MLO34_dV' + 'MLO41_dH' 'MLO41_dV' + 'MLO42_dH' 'MLO42_dV' + 'MLO43_dH' 'MLO43_dV' + 'MLO44_dH' 'MLO44_dV' + 'MLO51_dH' 'MLO51_dV' + 'MLO52_dH' 'MLO52_dV' + 'MLO53_dH' 'MLO53_dV' + 'MLP11_dH' 'MLP11_dV' + 'MLP12_dH' 'MLP12_dV' + 'MLP21_dH' 'MLP21_dV' + 'MLP22_dH' 'MLP22_dV' + 'MLP23_dH' 'MLP23_dV' + 'MLP31_dH' 'MLP31_dV' + 'MLP32_dH' 'MLP32_dV' + 'MLP33_dH' 'MLP33_dV' + 'MLP34_dH' 'MLP34_dV' + 'MLP35_dH' 'MLP35_dV' + 'MLP41_dH' 'MLP41_dV' + 'MLP42_dH' 'MLP42_dV' + 'MLP43_dH' 'MLP43_dV' + 'MLP44_dH' 'MLP44_dV' + 'MLP45_dH' 'MLP45_dV' + 'MLP51_dH' 'MLP51_dV' + 'MLP52_dH' 'MLP52_dV' + 'MLP53_dH' 'MLP53_dV' + 'MLP54_dH' 'MLP54_dV' + 'MLP55_dH' 'MLP55_dV' + 'MLP56_dH' 'MLP56_dV' + 'MLP57_dH' 'MLP57_dV' + 'MLT11_dH' 'MLT11_dV' + 'MLT12_dH' 'MLT12_dV' + 'MLT13_dH' 'MLT13_dV' + 'MLT14_dH' 'MLT14_dV' + 'MLT15_dH' 'MLT15_dV' + 'MLT16_dH' 'MLT16_dV' + 'MLT21_dH' 'MLT21_dV' + 'MLT22_dH' 'MLT22_dV' + 'MLT23_dH' 'MLT23_dV' + 'MLT24_dH' 'MLT24_dV' + 'MLT25_dH' 'MLT25_dV' + 'MLT26_dH' 'MLT26_dV' + 'MLT27_dH' 'MLT27_dV' + 'MLT31_dH' 'MLT31_dV' + 'MLT32_dH' 'MLT32_dV' + 'MLT33_dH' 'MLT33_dV' + 'MLT34_dH' 'MLT34_dV' + 'MLT35_dH' 'MLT35_dV' + 'MLT36_dH' 'MLT36_dV' + 'MLT37_dH' 'MLT37_dV' + 'MLT41_dH' 'MLT41_dV' + 'MLT42_dH' 'MLT42_dV' + 'MLT43_dH' 'MLT43_dV' + 'MLT44_dH' 'MLT44_dV' + 'MLT45_dH' 'MLT45_dV' + 'MLT46_dH' 'MLT46_dV' + 'MLT47_dH' 'MLT47_dV' + 'MLT51_dH' 'MLT51_dV' + 'MLT52_dH' 'MLT52_dV' + 'MLT53_dH' 'MLT53_dV' + 'MLT54_dH' 'MLT54_dV' + 'MLT55_dH' 'MLT55_dV' + 'MLT56_dH' 'MLT56_dV' + 'MLT57_dH' 'MLT57_dV' + 'MRC11_dH' 'MRC11_dV' + 'MRC12_dH' 'MRC12_dV' + 'MRC13_dH' 'MRC13_dV' + 'MRC14_dH' 'MRC14_dV' + 'MRC15_dH' 'MRC15_dV' + 'MRC16_dH' 'MRC16_dV' + 'MRC17_dH' 'MRC17_dV' + 'MRC21_dH' 'MRC21_dV' + 'MRC22_dH' 'MRC22_dV' + 'MRC23_dH' 'MRC23_dV' + 'MRC24_dH' 'MRC24_dV' + 'MRC25_dH' 'MRC25_dV' + 'MRC31_dH' 'MRC31_dV' + 'MRC32_dH' 'MRC32_dV' + 'MRC41_dH' 'MRC41_dV' + 'MRC42_dH' 'MRC42_dV' + 'MRC51_dH' 'MRC51_dV' + 'MRC52_dH' 'MRC52_dV' + 'MRC53_dH' 'MRC53_dV' + 'MRC54_dH' 'MRC54_dV' + 'MRC55_dH' 'MRC55_dV' + 'MRC61_dH' 'MRC61_dV' + 'MRC62_dH' 'MRC62_dV' + 'MRC63_dH' 'MRC63_dV' + 'MRF11_dH' 'MRF11_dV' + 'MRF12_dH' 'MRF12_dV' + 'MRF13_dH' 'MRF13_dV' + 'MRF14_dH' 'MRF14_dV' + 'MRF21_dH' 'MRF21_dV' + 'MRF22_dH' 'MRF22_dV' + 'MRF23_dH' 'MRF23_dV' + 'MRF24_dH' 'MRF24_dV' + 'MRF25_dH' 'MRF25_dV' + 'MRF31_dH' 'MRF31_dV' + 'MRF32_dH' 'MRF32_dV' + 'MRF33_dH' 'MRF33_dV' + 'MRF34_dH' 'MRF34_dV' + 'MRF35_dH' 'MRF35_dV' + 'MRF41_dH' 'MRF41_dV' + 'MRF42_dH' 'MRF42_dV' + 'MRF43_dH' 'MRF43_dV' + 'MRF44_dH' 'MRF44_dV' + 'MRF45_dH' 'MRF45_dV' + 'MRF46_dH' 'MRF46_dV' + 'MRF51_dH' 'MRF51_dV' + 'MRF52_dH' 'MRF52_dV' + 'MRF53_dH' 'MRF53_dV' + 'MRF54_dH' 'MRF54_dV' + 'MRF55_dH' 'MRF55_dV' + 'MRF56_dH' 'MRF56_dV' + 'MRF61_dH' 'MRF61_dV' + 'MRF62_dH' 'MRF62_dV' + 'MRF63_dH' 'MRF63_dV' + 'MRF64_dH' 'MRF64_dV' + 'MRF65_dH' 'MRF65_dV' + 'MRF66_dH' 'MRF66_dV' + 'MRF67_dH' 'MRF67_dV' + 'MRO11_dH' 'MRO11_dV' + 'MRO12_dH' 'MRO12_dV' + 'MRO13_dH' 'MRO13_dV' + 'MRO14_dH' 'MRO14_dV' + 'MRO21_dH' 'MRO21_dV' + 'MRO22_dH' 'MRO22_dV' + 'MRO23_dH' 'MRO23_dV' + 'MRO24_dH' 'MRO24_dV' + 'MRO31_dH' 'MRO31_dV' + 'MRO32_dH' 'MRO32_dV' + 'MRO33_dH' 'MRO33_dV' + 'MRO34_dH' 'MRO34_dV' + 'MRO41_dH' 'MRO41_dV' + 'MRO42_dH' 'MRO42_dV' + 'MRO43_dH' 'MRO43_dV' + 'MRO44_dH' 'MRO44_dV' + 'MRO51_dH' 'MRO51_dV' + 'MRO52_dH' 'MRO52_dV' + 'MRO53_dH' 'MRO53_dV' + 'MRP11_dH' 'MRP11_dV' + 'MRP12_dH' 'MRP12_dV' + 'MRP21_dH' 'MRP21_dV' + 'MRP22_dH' 'MRP22_dV' + 'MRP23_dH' 'MRP23_dV' + 'MRP32_dH' 'MRP32_dV' + 'MRP33_dH' 'MRP33_dV' + 'MRP34_dH' 'MRP34_dV' + 'MRP35_dH' 'MRP35_dV' + 'MRP41_dH' 'MRP41_dV' + 'MRP42_dH' 'MRP42_dV' + 'MRP43_dH' 'MRP43_dV' + 'MRP44_dH' 'MRP44_dV' + 'MRP45_dH' 'MRP45_dV' + 'MRP51_dH' 'MRP51_dV' + 'MRP52_dH' 'MRP52_dV' + 'MRP53_dH' 'MRP53_dV' + 'MRP54_dH' 'MRP54_dV' + 'MRP55_dH' 'MRP55_dV' + 'MRP56_dH' 'MRP56_dV' + 'MRP57_dH' 'MRP57_dV' + 'MRT11_dH' 'MRT11_dV' + 'MRT12_dH' 'MRT12_dV' + 'MRT13_dH' 'MRT13_dV' + 'MRT14_dH' 'MRT14_dV' + 'MRT15_dH' 'MRT15_dV' + 'MRT16_dH' 'MRT16_dV' + 'MRT21_dH' 'MRT21_dV' + 'MRT22_dH' 'MRT22_dV' + 'MRT23_dH' 'MRT23_dV' + 'MRT24_dH' 'MRT24_dV' + 'MRT25_dH' 'MRT25_dV' + 'MRT26_dH' 'MRT26_dV' + 'MRT27_dH' 'MRT27_dV' + 'MRT31_dH' 'MRT31_dV' + 'MRT32_dH' 'MRT32_dV' + 'MRT33_dH' 'MRT33_dV' + 'MRT34_dH' 'MRT34_dV' + 'MRT35_dH' 'MRT35_dV' + 'MRT36_dH' 'MRT36_dV' + 'MRT37_dH' 'MRT37_dV' + 'MRT41_dH' 'MRT41_dV' + 'MRT42_dH' 'MRT42_dV' + 'MRT43_dH' 'MRT43_dV' + 'MRT44_dH' 'MRT44_dV' + 'MRT45_dH' 'MRT45_dV' + 'MRT46_dH' 'MRT46_dV' + 'MRT47_dH' 'MRT47_dV' + 'MRT51_dH' 'MRT51_dV' + 'MRT52_dH' 'MRT52_dV' + 'MRT53_dH' 'MRT53_dV' + 'MRT54_dH' 'MRT54_dV' + 'MRT55_dH' 'MRT55_dV' + 'MRT56_dH' 'MRT56_dV' + 'MRT57_dH' 'MRT57_dV' + 'MZC01_dH' 'MZC01_dV' + 'MZC02_dH' 'MZC02_dV' + 'MZC03_dH' 'MZC03_dV' + 'MZC04_dH' 'MZC04_dV' + 'MZF01_dH' 'MZF01_dV' + 'MZF02_dH' 'MZF02_dV' + 'MZF03_dH' 'MZF03_dV' + 'MZO01_dH' 'MZO01_dV' + 'MZO02_dH' 'MZO02_dV' + 'MZO03_dH' 'MZO03_dV' + 'MZP01_dH' 'MZP01_dV' + }; + + + case 'neuromag122' + label = { + 'MEG 001' 'MEG 002' + 'MEG 003' 'MEG 004' + 'MEG 005' 'MEG 006' + 'MEG 007' 'MEG 008' + 'MEG 009' 'MEG 010' + 'MEG 011' 'MEG 012' + 'MEG 013' 'MEG 014' + 'MEG 015' 'MEG 016' + 'MEG 017' 'MEG 018' + 'MEG 019' 'MEG 020' + 'MEG 021' 'MEG 022' + 'MEG 023' 'MEG 024' + 'MEG 025' 'MEG 026' + 'MEG 027' 'MEG 028' + 'MEG 029' 'MEG 030' + 'MEG 031' 'MEG 032' + 'MEG 033' 'MEG 034' + 'MEG 035' 'MEG 036' + 'MEG 037' 'MEG 038' + 'MEG 039' 'MEG 040' + 'MEG 041' 'MEG 042' + 'MEG 043' 'MEG 044' + 'MEG 045' 'MEG 046' + 'MEG 047' 'MEG 048' + 'MEG 049' 'MEG 050' + 'MEG 051' 'MEG 052' + 'MEG 053' 'MEG 054' + 'MEG 055' 'MEG 056' + 'MEG 057' 'MEG 058' + 'MEG 059' 'MEG 060' + 'MEG 061' 'MEG 062' + 'MEG 063' 'MEG 064' + 'MEG 065' 'MEG 066' + 'MEG 067' 'MEG 068' + 'MEG 069' 'MEG 070' + 'MEG 071' 'MEG 072' + 'MEG 073' 'MEG 074' + 'MEG 075' 'MEG 076' + 'MEG 077' 'MEG 078' + 'MEG 079' 'MEG 080' + 'MEG 081' 'MEG 082' + 'MEG 083' 'MEG 084' + 'MEG 085' 'MEG 086' + 'MEG 087' 'MEG 088' + 'MEG 089' 'MEG 090' + 'MEG 091' 'MEG 092' + 'MEG 093' 'MEG 094' + 'MEG 095' 'MEG 096' + 'MEG 097' 'MEG 098' + 'MEG 099' 'MEG 100' + 'MEG 101' 'MEG 102' + 'MEG 103' 'MEG 104' + 'MEG 105' 'MEG 106' + 'MEG 107' 'MEG 108' + 'MEG 109' 'MEG 110' + 'MEG 111' 'MEG 112' + 'MEG 113' 'MEG 114' + 'MEG 115' 'MEG 116' + 'MEG 117' 'MEG 118' + 'MEG 119' 'MEG 120' + 'MEG 121' 'MEG 122' + }; + + case 'neuromag122alt' + % this is an alternative set of labels without a space in them + label = { + 'MEG001' 'MEG002' + 'MEG003' 'MEG004' + 'MEG005' 'MEG006' + 'MEG007' 'MEG008' + 'MEG009' 'MEG010' + 'MEG011' 'MEG012' + 'MEG013' 'MEG014' + 'MEG015' 'MEG016' + 'MEG017' 'MEG018' + 'MEG019' 'MEG020' + 'MEG021' 'MEG022' + 'MEG023' 'MEG024' + 'MEG025' 'MEG026' + 'MEG027' 'MEG028' + 'MEG029' 'MEG030' + 'MEG031' 'MEG032' + 'MEG033' 'MEG034' + 'MEG035' 'MEG036' + 'MEG037' 'MEG038' + 'MEG039' 'MEG040' + 'MEG041' 'MEG042' + 'MEG043' 'MEG044' + 'MEG045' 'MEG046' + 'MEG047' 'MEG048' + 'MEG049' 'MEG050' + 'MEG051' 'MEG052' + 'MEG053' 'MEG054' + 'MEG055' 'MEG056' + 'MEG057' 'MEG058' + 'MEG059' 'MEG060' + 'MEG061' 'MEG062' + 'MEG063' 'MEG064' + 'MEG065' 'MEG066' + 'MEG067' 'MEG068' + 'MEG069' 'MEG070' + 'MEG071' 'MEG072' + 'MEG073' 'MEG074' + 'MEG075' 'MEG076' + 'MEG077' 'MEG078' + 'MEG079' 'MEG080' + 'MEG081' 'MEG082' + 'MEG083' 'MEG084' + 'MEG085' 'MEG086' + 'MEG087' 'MEG088' + 'MEG089' 'MEG090' + 'MEG091' 'MEG092' + 'MEG093' 'MEG094' + 'MEG095' 'MEG096' + 'MEG097' 'MEG098' + 'MEG099' 'MEG100' + 'MEG101' 'MEG102' + 'MEG103' 'MEG104' + 'MEG105' 'MEG106' + 'MEG107' 'MEG108' + 'MEG109' 'MEG110' + 'MEG111' 'MEG112' + 'MEG113' 'MEG114' + 'MEG115' 'MEG116' + 'MEG117' 'MEG118' + 'MEG119' 'MEG120' + 'MEG121' 'MEG122' + }; + + case 'neuromag306' + label = { + 'MEG 0113' 'MEG 0112' 'MEG 0111' + 'MEG 0122' 'MEG 0123' 'MEG 0121' + 'MEG 0132' 'MEG 0133' 'MEG 0131' + 'MEG 0143' 'MEG 0142' 'MEG 0141' + 'MEG 0213' 'MEG 0212' 'MEG 0211' + 'MEG 0222' 'MEG 0223' 'MEG 0221' + 'MEG 0232' 'MEG 0233' 'MEG 0231' + 'MEG 0243' 'MEG 0242' 'MEG 0241' + 'MEG 0313' 'MEG 0312' 'MEG 0311' + 'MEG 0322' 'MEG 0323' 'MEG 0321' + 'MEG 0333' 'MEG 0332' 'MEG 0331' + 'MEG 0343' 'MEG 0342' 'MEG 0341' + 'MEG 0413' 'MEG 0412' 'MEG 0411' + 'MEG 0422' 'MEG 0423' 'MEG 0421' + 'MEG 0432' 'MEG 0433' 'MEG 0431' + 'MEG 0443' 'MEG 0442' 'MEG 0441' + 'MEG 0513' 'MEG 0512' 'MEG 0511' + 'MEG 0523' 'MEG 0522' 'MEG 0521' + 'MEG 0532' 'MEG 0533' 'MEG 0531' + 'MEG 0542' 'MEG 0543' 'MEG 0541' + 'MEG 0613' 'MEG 0612' 'MEG 0611' + 'MEG 0622' 'MEG 0623' 'MEG 0621' + 'MEG 0633' 'MEG 0632' 'MEG 0631' + 'MEG 0642' 'MEG 0643' 'MEG 0641' + 'MEG 0713' 'MEG 0712' 'MEG 0711' + 'MEG 0723' 'MEG 0722' 'MEG 0721' + 'MEG 0733' 'MEG 0732' 'MEG 0731' + 'MEG 0743' 'MEG 0742' 'MEG 0741' + 'MEG 0813' 'MEG 0812' 'MEG 0811' + 'MEG 0822' 'MEG 0823' 'MEG 0821' + 'MEG 0913' 'MEG 0912' 'MEG 0911' + 'MEG 0923' 'MEG 0922' 'MEG 0921' + 'MEG 0932' 'MEG 0933' 'MEG 0931' + 'MEG 0942' 'MEG 0943' 'MEG 0941' + 'MEG 1013' 'MEG 1012' 'MEG 1011' + 'MEG 1023' 'MEG 1022' 'MEG 1021' + 'MEG 1032' 'MEG 1033' 'MEG 1031' + 'MEG 1043' 'MEG 1042' 'MEG 1041' + 'MEG 1112' 'MEG 1113' 'MEG 1111' + 'MEG 1123' 'MEG 1122' 'MEG 1121' + 'MEG 1133' 'MEG 1132' 'MEG 1131' + 'MEG 1142' 'MEG 1143' 'MEG 1141' + 'MEG 1213' 'MEG 1212' 'MEG 1211' + 'MEG 1223' 'MEG 1222' 'MEG 1221' + 'MEG 1232' 'MEG 1233' 'MEG 1231' + 'MEG 1243' 'MEG 1242' 'MEG 1241' + 'MEG 1312' 'MEG 1313' 'MEG 1311' + 'MEG 1323' 'MEG 1322' 'MEG 1321' + 'MEG 1333' 'MEG 1332' 'MEG 1331' + 'MEG 1342' 'MEG 1343' 'MEG 1341' + 'MEG 1412' 'MEG 1413' 'MEG 1411' + 'MEG 1423' 'MEG 1422' 'MEG 1421' + 'MEG 1433' 'MEG 1432' 'MEG 1431' + 'MEG 1442' 'MEG 1443' 'MEG 1441' + 'MEG 1512' 'MEG 1513' 'MEG 1511' + 'MEG 1522' 'MEG 1523' 'MEG 1521' + 'MEG 1533' 'MEG 1532' 'MEG 1531' + 'MEG 1543' 'MEG 1542' 'MEG 1541' + 'MEG 1613' 'MEG 1612' 'MEG 1611' + 'MEG 1622' 'MEG 1623' 'MEG 1621' + 'MEG 1632' 'MEG 1633' 'MEG 1631' + 'MEG 1643' 'MEG 1642' 'MEG 1641' + 'MEG 1713' 'MEG 1712' 'MEG 1711' + 'MEG 1722' 'MEG 1723' 'MEG 1721' + 'MEG 1732' 'MEG 1733' 'MEG 1731' + 'MEG 1743' 'MEG 1742' 'MEG 1741' + 'MEG 1813' 'MEG 1812' 'MEG 1811' + 'MEG 1822' 'MEG 1823' 'MEG 1821' + 'MEG 1832' 'MEG 1833' 'MEG 1831' + 'MEG 1843' 'MEG 1842' 'MEG 1841' + 'MEG 1912' 'MEG 1913' 'MEG 1911' + 'MEG 1923' 'MEG 1922' 'MEG 1921' + 'MEG 1932' 'MEG 1933' 'MEG 1931' + 'MEG 1943' 'MEG 1942' 'MEG 1941' + 'MEG 2013' 'MEG 2012' 'MEG 2011' + 'MEG 2023' 'MEG 2022' 'MEG 2021' + 'MEG 2032' 'MEG 2033' 'MEG 2031' + 'MEG 2042' 'MEG 2043' 'MEG 2041' + 'MEG 2113' 'MEG 2112' 'MEG 2111' + 'MEG 2122' 'MEG 2123' 'MEG 2121' + 'MEG 2133' 'MEG 2132' 'MEG 2131' + 'MEG 2143' 'MEG 2142' 'MEG 2141' + 'MEG 2212' 'MEG 2213' 'MEG 2211' + 'MEG 2223' 'MEG 2222' 'MEG 2221' + 'MEG 2233' 'MEG 2232' 'MEG 2231' + 'MEG 2242' 'MEG 2243' 'MEG 2241' + 'MEG 2312' 'MEG 2313' 'MEG 2311' + 'MEG 2323' 'MEG 2322' 'MEG 2321' + 'MEG 2332' 'MEG 2333' 'MEG 2331' + 'MEG 2343' 'MEG 2342' 'MEG 2341' + 'MEG 2412' 'MEG 2413' 'MEG 2411' + 'MEG 2423' 'MEG 2422' 'MEG 2421' + 'MEG 2433' 'MEG 2432' 'MEG 2431' + 'MEG 2442' 'MEG 2443' 'MEG 2441' + 'MEG 2512' 'MEG 2513' 'MEG 2511' + 'MEG 2522' 'MEG 2523' 'MEG 2521' + 'MEG 2533' 'MEG 2532' 'MEG 2531' + 'MEG 2543' 'MEG 2542' 'MEG 2541' + 'MEG 2612' 'MEG 2613' 'MEG 2611' + 'MEG 2623' 'MEG 2622' 'MEG 2621' + 'MEG 2633' 'MEG 2632' 'MEG 2631' + 'MEG 2642' 'MEG 2643' 'MEG 2641' + }; + + case 'neuromag306alt' + % this is an alternative set of labels without a space in them + label = { + 'MEG0113' 'MEG0112' 'MEG0111' + 'MEG0122' 'MEG0123' 'MEG0121' + 'MEG0132' 'MEG0133' 'MEG0131' + 'MEG0143' 'MEG0142' 'MEG0141' + 'MEG0213' 'MEG0212' 'MEG0211' + 'MEG0222' 'MEG0223' 'MEG0221' + 'MEG0232' 'MEG0233' 'MEG0231' + 'MEG0243' 'MEG0242' 'MEG0241' + 'MEG0313' 'MEG0312' 'MEG0311' + 'MEG0322' 'MEG0323' 'MEG0321' + 'MEG0333' 'MEG0332' 'MEG0331' + 'MEG0343' 'MEG0342' 'MEG0341' + 'MEG0413' 'MEG0412' 'MEG0411' + 'MEG0422' 'MEG0423' 'MEG0421' + 'MEG0432' 'MEG0433' 'MEG0431' + 'MEG0443' 'MEG0442' 'MEG0441' + 'MEG0513' 'MEG0512' 'MEG0511' + 'MEG0523' 'MEG0522' 'MEG0521' + 'MEG0532' 'MEG0533' 'MEG0531' + 'MEG0542' 'MEG0543' 'MEG0541' + 'MEG0613' 'MEG0612' 'MEG0611' + 'MEG0622' 'MEG0623' 'MEG0621' + 'MEG0633' 'MEG0632' 'MEG0631' + 'MEG0642' 'MEG0643' 'MEG0641' + 'MEG0713' 'MEG0712' 'MEG0711' + 'MEG0723' 'MEG0722' 'MEG0721' + 'MEG0733' 'MEG0732' 'MEG0731' + 'MEG0743' 'MEG0742' 'MEG0741' + 'MEG0813' 'MEG0812' 'MEG0811' + 'MEG0822' 'MEG0823' 'MEG0821' + 'MEG0913' 'MEG0912' 'MEG0911' + 'MEG0923' 'MEG0922' 'MEG0921' + 'MEG0932' 'MEG0933' 'MEG0931' + 'MEG0942' 'MEG0943' 'MEG0941' + 'MEG1013' 'MEG1012' 'MEG1011' + 'MEG1023' 'MEG1022' 'MEG1021' + 'MEG1032' 'MEG1033' 'MEG1031' + 'MEG1043' 'MEG1042' 'MEG1041' + 'MEG1112' 'MEG1113' 'MEG1111' + 'MEG1123' 'MEG1122' 'MEG1121' + 'MEG1133' 'MEG1132' 'MEG1131' + 'MEG1142' 'MEG1143' 'MEG1141' + 'MEG1213' 'MEG1212' 'MEG1211' + 'MEG1223' 'MEG1222' 'MEG1221' + 'MEG1232' 'MEG1233' 'MEG1231' + 'MEG1243' 'MEG1242' 'MEG1241' + 'MEG1312' 'MEG1313' 'MEG1311' + 'MEG1323' 'MEG1322' 'MEG1321' + 'MEG1333' 'MEG1332' 'MEG1331' + 'MEG1342' 'MEG1343' 'MEG1341' + 'MEG1412' 'MEG1413' 'MEG1411' + 'MEG1423' 'MEG1422' 'MEG1421' + 'MEG1433' 'MEG1432' 'MEG1431' + 'MEG1442' 'MEG1443' 'MEG1441' + 'MEG1512' 'MEG1513' 'MEG1511' + 'MEG1522' 'MEG1523' 'MEG1521' + 'MEG1533' 'MEG1532' 'MEG1531' + 'MEG1543' 'MEG1542' 'MEG1541' + 'MEG1613' 'MEG1612' 'MEG1611' + 'MEG1622' 'MEG1623' 'MEG1621' + 'MEG1632' 'MEG1633' 'MEG1631' + 'MEG1643' 'MEG1642' 'MEG1641' + 'MEG1713' 'MEG1712' 'MEG1711' + 'MEG1722' 'MEG1723' 'MEG1721' + 'MEG1732' 'MEG1733' 'MEG1731' + 'MEG1743' 'MEG1742' 'MEG1741' + 'MEG1813' 'MEG1812' 'MEG1811' + 'MEG1822' 'MEG1823' 'MEG1821' + 'MEG1832' 'MEG1833' 'MEG1831' + 'MEG1843' 'MEG1842' 'MEG1841' + 'MEG1912' 'MEG1913' 'MEG1911' + 'MEG1923' 'MEG1922' 'MEG1921' + 'MEG1932' 'MEG1933' 'MEG1931' + 'MEG1943' 'MEG1942' 'MEG1941' + 'MEG2013' 'MEG2012' 'MEG2011' + 'MEG2023' 'MEG2022' 'MEG2021' + 'MEG2032' 'MEG2033' 'MEG2031' + 'MEG2042' 'MEG2043' 'MEG2041' + 'MEG2113' 'MEG2112' 'MEG2111' + 'MEG2122' 'MEG2123' 'MEG2121' + 'MEG2133' 'MEG2132' 'MEG2131' + 'MEG2143' 'MEG2142' 'MEG2141' + 'MEG2212' 'MEG2213' 'MEG2211' + 'MEG2223' 'MEG2222' 'MEG2221' + 'MEG2233' 'MEG2232' 'MEG2231' + 'MEG2242' 'MEG2243' 'MEG2241' + 'MEG2312' 'MEG2313' 'MEG2311' + 'MEG2323' 'MEG2322' 'MEG2321' + 'MEG2332' 'MEG2333' 'MEG2331' + 'MEG2343' 'MEG2342' 'MEG2341' + 'MEG2412' 'MEG2413' 'MEG2411' + 'MEG2423' 'MEG2422' 'MEG2421' + 'MEG2433' 'MEG2432' 'MEG2431' + 'MEG2442' 'MEG2443' 'MEG2441' + 'MEG2512' 'MEG2513' 'MEG2511' + 'MEG2522' 'MEG2523' 'MEG2521' + 'MEG2533' 'MEG2532' 'MEG2531' + 'MEG2543' 'MEG2542' 'MEG2541' + 'MEG2612' 'MEG2613' 'MEG2611' + 'MEG2623' 'MEG2622' 'MEG2621' + 'MEG2633' 'MEG2632' 'MEG2631' + 'MEG2642' 'MEG2643' 'MEG2641' + }; + + + case 'eeg1020' + label = { + 'Fp1' + 'Fpz' + 'Fp2' + 'F7' + 'F3' + 'Fz' + 'F4' + 'F8' + 'T7' + 'C3' + 'Cz' + 'C4' + 'T8' + 'P7' + 'P3' + 'Pz' + 'P4' + 'P8' + 'O1' + 'Oz' + 'O2'}; + + case 'eeg1010' + label = { + 'Fp1' + 'Fpz' + 'Fp2' + 'AF9' + 'AF7' + 'AF5' + 'AF3' + 'AF1' + 'AFz' + 'AF2' + 'AF4' + 'AF6' + 'AF8' + 'AF10' + 'F9' + 'F7' + 'F5' + 'F3' + 'F1' + 'Fz' + 'F2' + 'F4' + 'F6' + 'F8' + 'F10' + 'FT9' + 'FT7' + 'FC5' + 'FC3' + 'FC1' + 'FCz' + 'FC2' + 'FC4' + 'FC6' + 'FT8' + 'FT10' + 'T9' + 'T7' + 'C5' + 'C3' + 'C1' + 'Cz' + 'C2' + 'C4' + 'C6' + 'T8' + 'T10' + 'TP9' + 'TP7' + 'CP5' + 'CP3' + 'CP1' + 'CPz' + 'CP2' + 'CP4' + 'CP6' + 'TP8' + 'TP10' + 'P9' + 'P7' + 'P5' + 'P3' + 'P1' + 'Pz' + 'P2' + 'P4' + 'P6' + 'P8' + 'P10' + 'PO9' + 'PO7' + 'PO5' + 'PO3' + 'PO1' + 'POz' + 'PO2' + 'PO4' + 'PO6' + 'PO8' + 'PO10' + 'O1' + 'Oz' + 'O2' + 'I1' + 'Iz' + 'I2' + }; + + case 'eeg1005' + label = { + 'Fp1' + 'Fpz' + 'Fp2' + 'AF9' + 'AF7' + 'AF5' + 'AF3' + 'AF1' + 'AFz' + 'AF2' + 'AF4' + 'AF6' + 'AF8' + 'AF10' + 'F9' + 'F7' + 'F5' + 'F3' + 'F1' + 'Fz' + 'F2' + 'F4' + 'F6' + 'F8' + 'F10' + 'FT9' + 'FT7' + 'FC5' + 'FC3' + 'FC1' + 'FCz' + 'FC2' + 'FC4' + 'FC6' + 'FT8' + 'FT10' + 'T9' + 'T7' + 'C5' + 'C3' + 'C1' + 'Cz' + 'C2' + 'C4' + 'C6' + 'T8' + 'T10' + 'TP9' + 'TP7' + 'CP5' + 'CP3' + 'CP1' + 'CPz' + 'CP2' + 'CP4' + 'CP6' + 'TP8' + 'TP10' + 'P9' + 'P7' + 'P5' + 'P3' + 'P1' + 'Pz' + 'P2' + 'P4' + 'P6' + 'P8' + 'P10' + 'PO9' + 'PO7' + 'PO5' + 'PO3' + 'PO1' + 'POz' + 'PO2' + 'PO4' + 'PO6' + 'PO8' + 'PO10' + 'O1' + 'Oz' + 'O2' + 'I1' + 'Iz' + 'I2' + 'AFp9h' + 'AFp7h' + 'AFp5h' + 'AFp3h' + 'AFp1h' + 'AFp2h' + 'AFp4h' + 'AFp6h' + 'AFp8h' + 'AFp10h' + 'AFF9h' + 'AFF7h' + 'AFF5h' + 'AFF3h' + 'AFF1h' + 'AFF2h' + 'AFF4h' + 'AFF6h' + 'AFF8h' + 'AFF10h' + 'FFT9h' + 'FFT7h' + 'FFC5h' + 'FFC3h' + 'FFC1h' + 'FFC2h' + 'FFC4h' + 'FFC6h' + 'FFT8h' + 'FFT10h' + 'FTT9h' + 'FTT7h' + 'FCC5h' + 'FCC3h' + 'FCC1h' + 'FCC2h' + 'FCC4h' + 'FCC6h' + 'FTT8h' + 'FTT10h' + 'TTP9h' + 'TTP7h' + 'CCP5h' + 'CCP3h' + 'CCP1h' + 'CCP2h' + 'CCP4h' + 'CCP6h' + 'TTP8h' + 'TTP10h' + 'TPP9h' + 'TPP7h' + 'CPP5h' + 'CPP3h' + 'CPP1h' + 'CPP2h' + 'CPP4h' + 'CPP6h' + 'TPP8h' + 'TPP10h' + 'PPO9h' + 'PPO7h' + 'PPO5h' + 'PPO3h' + 'PPO1h' + 'PPO2h' + 'PPO4h' + 'PPO6h' + 'PPO8h' + 'PPO10h' + 'POO9h' + 'POO7h' + 'POO5h' + 'POO3h' + 'POO1h' + 'POO2h' + 'POO4h' + 'POO6h' + 'POO8h' + 'POO10h' + 'OI1h' + 'OI2h' + 'Fp1h' + 'Fp2h' + 'AF9h' + 'AF7h' + 'AF5h' + 'AF3h' + 'AF1h' + 'AF2h' + 'AF4h' + 'AF6h' + 'AF8h' + 'AF10h' + 'F9h' + 'F7h' + 'F5h' + 'F3h' + 'F1h' + 'F2h' + 'F4h' + 'F6h' + 'F8h' + 'F10h' + 'FT9h' + 'FT7h' + 'FC5h' + 'FC3h' + 'FC1h' + 'FC2h' + 'FC4h' + 'FC6h' + 'FT8h' + 'FT10h' + 'T9h' + 'T7h' + 'C5h' + 'C3h' + 'C1h' + 'C2h' + 'C4h' + 'C6h' + 'T8h' + 'T10h' + 'TP9h' + 'TP7h' + 'CP5h' + 'CP3h' + 'CP1h' + 'CP2h' + 'CP4h' + 'CP6h' + 'TP8h' + 'TP10h' + 'P9h' + 'P7h' + 'P5h' + 'P3h' + 'P1h' + 'P2h' + 'P4h' + 'P6h' + 'P8h' + 'P10h' + 'PO9h' + 'PO7h' + 'PO5h' + 'PO3h' + 'PO1h' + 'PO2h' + 'PO4h' + 'PO6h' + 'PO8h' + 'PO10h' + 'O1h' + 'O2h' + 'I1h' + 'I2h' + 'AFp9' + 'AFp7' + 'AFp5' + 'AFp3' + 'AFp1' + 'AFpz' + 'AFp2' + 'AFp4' + 'AFp6' + 'AFp8' + 'AFp10' + 'AFF9' + 'AFF7' + 'AFF5' + 'AFF3' + 'AFF1' + 'AFFz' + 'AFF2' + 'AFF4' + 'AFF6' + 'AFF8' + 'AFF10' + 'FFT9' + 'FFT7' + 'FFC5' + 'FFC3' + 'FFC1' + 'FFCz' + 'FFC2' + 'FFC4' + 'FFC6' + 'FFT8' + 'FFT10' + 'FTT9' + 'FTT7' + 'FCC5' + 'FCC3' + 'FCC1' + 'FCCz' + 'FCC2' + 'FCC4' + 'FCC6' + 'FTT8' + 'FTT10' + 'TTP9' + 'TTP7' + 'CCP5' + 'CCP3' + 'CCP1' + 'CCPz' + 'CCP2' + 'CCP4' + 'CCP6' + 'TTP8' + 'TTP10' + 'TPP9' + 'TPP7' + 'CPP5' + 'CPP3' + 'CPP1' + 'CPPz' + 'CPP2' + 'CPP4' + 'CPP6' + 'TPP8' + 'TPP10' + 'PPO9' + 'PPO7' + 'PPO5' + 'PPO3' + 'PPO1' + 'PPOz' + 'PPO2' + 'PPO4' + 'PPO6' + 'PPO8' + 'PPO10' + 'POO9' + 'POO7' + 'POO5' + 'POO3' + 'POO1' + 'POOz' + 'POO2' + 'POO4' + 'POO6' + 'POO8' + 'POO10' + 'OI1' + 'OIz' + 'OI2' + }; + + case 'ext1020' + % start with the eeg1005 list + label = { + 'Fp1' + 'Fpz' + 'Fp2' + 'AF9' + 'AF7' + 'AF5' + 'AF3' + 'AF1' + 'AFz' + 'AF2' + 'AF4' + 'AF6' + 'AF8' + 'AF10' + 'F9' + 'F7' + 'F5' + 'F3' + 'F1' + 'Fz' + 'F2' + 'F4' + 'F6' + 'F8' + 'F10' + 'FT9' + 'FT7' + 'FC5' + 'FC3' + 'FC1' + 'FCz' + 'FC2' + 'FC4' + 'FC6' + 'FT8' + 'FT10' + 'T9' + 'T7' + 'C5' + 'C3' + 'C1' + 'Cz' + 'C2' + 'C4' + 'C6' + 'T8' + 'T10' + 'TP9' + 'TP7' + 'CP5' + 'CP3' + 'CP1' + 'CPz' + 'CP2' + 'CP4' + 'CP6' + 'TP8' + 'TP10' + 'P9' + 'P7' + 'P5' + 'P3' + 'P1' + 'Pz' + 'P2' + 'P4' + 'P6' + 'P8' + 'P10' + 'PO9' + 'PO7' + 'PO5' + 'PO3' + 'PO1' + 'POz' + 'PO2' + 'PO4' + 'PO6' + 'PO8' + 'PO10' + 'O1' + 'Oz' + 'O2' + 'I1' + 'Iz' + 'I2' + 'AFp9h' + 'AFp7h' + 'AFp5h' + 'AFp3h' + 'AFp1h' + 'AFp2h' + 'AFp4h' + 'AFp6h' + 'AFp8h' + 'AFp10h' + 'AFF9h' + 'AFF7h' + 'AFF5h' + 'AFF3h' + 'AFF1h' + 'AFF2h' + 'AFF4h' + 'AFF6h' + 'AFF8h' + 'AFF10h' + 'FFT9h' + 'FFT7h' + 'FFC5h' + 'FFC3h' + 'FFC1h' + 'FFC2h' + 'FFC4h' + 'FFC6h' + 'FFT8h' + 'FFT10h' + 'FTT9h' + 'FTT7h' + 'FCC5h' + 'FCC3h' + 'FCC1h' + 'FCC2h' + 'FCC4h' + 'FCC6h' + 'FTT8h' + 'FTT10h' + 'TTP9h' + 'TTP7h' + 'CCP5h' + 'CCP3h' + 'CCP1h' + 'CCP2h' + 'CCP4h' + 'CCP6h' + 'TTP8h' + 'TTP10h' + 'TPP9h' + 'TPP7h' + 'CPP5h' + 'CPP3h' + 'CPP1h' + 'CPP2h' + 'CPP4h' + 'CPP6h' + 'TPP8h' + 'TPP10h' + 'PPO9h' + 'PPO7h' + 'PPO5h' + 'PPO3h' + 'PPO1h' + 'PPO2h' + 'PPO4h' + 'PPO6h' + 'PPO8h' + 'PPO10h' + 'POO9h' + 'POO7h' + 'POO5h' + 'POO3h' + 'POO1h' + 'POO2h' + 'POO4h' + 'POO6h' + 'POO8h' + 'POO10h' + 'OI1h' + 'OI2h' + 'Fp1h' + 'Fp2h' + 'AF9h' + 'AF7h' + 'AF5h' + 'AF3h' + 'AF1h' + 'AF2h' + 'AF4h' + 'AF6h' + 'AF8h' + 'AF10h' + 'F9h' + 'F7h' + 'F5h' + 'F3h' + 'F1h' + 'F2h' + 'F4h' + 'F6h' + 'F8h' + 'F10h' + 'FT9h' + 'FT7h' + 'FC5h' + 'FC3h' + 'FC1h' + 'FC2h' + 'FC4h' + 'FC6h' + 'FT8h' + 'FT10h' + 'T9h' + 'T7h' + 'C5h' + 'C3h' + 'C1h' + 'C2h' + 'C4h' + 'C6h' + 'T8h' + 'T10h' + 'TP9h' + 'TP7h' + 'CP5h' + 'CP3h' + 'CP1h' + 'CP2h' + 'CP4h' + 'CP6h' + 'TP8h' + 'TP10h' + 'P9h' + 'P7h' + 'P5h' + 'P3h' + 'P1h' + 'P2h' + 'P4h' + 'P6h' + 'P8h' + 'P10h' + 'PO9h' + 'PO7h' + 'PO5h' + 'PO3h' + 'PO1h' + 'PO2h' + 'PO4h' + 'PO6h' + 'PO8h' + 'PO10h' + 'O1h' + 'O2h' + 'I1h' + 'I2h' + 'AFp9' + 'AFp7' + 'AFp5' + 'AFp3' + 'AFp1' + 'AFpz' + 'AFp2' + 'AFp4' + 'AFp6' + 'AFp8' + 'AFp10' + 'AFF9' + 'AFF7' + 'AFF5' + 'AFF3' + 'AFF1' + 'AFFz' + 'AFF2' + 'AFF4' + 'AFF6' + 'AFF8' + 'AFF10' + 'FFT9' + 'FFT7' + 'FFC5' + 'FFC3' + 'FFC1' + 'FFCz' + 'FFC2' + 'FFC4' + 'FFC6' + 'FFT8' + 'FFT10' + 'FTT9' + 'FTT7' + 'FCC5' + 'FCC3' + 'FCC1' + 'FCCz' + 'FCC2' + 'FCC4' + 'FCC6' + 'FTT8' + 'FTT10' + 'TTP9' + 'TTP7' + 'CCP5' + 'CCP3' + 'CCP1' + 'CCPz' + 'CCP2' + 'CCP4' + 'CCP6' + 'TTP8' + 'TTP10' + 'TPP9' + 'TPP7' + 'CPP5' + 'CPP3' + 'CPP1' + 'CPPz' + 'CPP2' + 'CPP4' + 'CPP6' + 'TPP8' + 'TPP10' + 'PPO9' + 'PPO7' + 'PPO5' + 'PPO3' + 'PPO1' + 'PPOz' + 'PPO2' + 'PPO4' + 'PPO6' + 'PPO8' + 'PPO10' + 'POO9' + 'POO7' + 'POO5' + 'POO3' + 'POO1' + 'POOz' + 'POO2' + 'POO4' + 'POO6' + 'POO8' + 'POO10' + 'OI1' + 'OIz' + 'OI2' + }; + + % Add also alternative labels that are used in some systems + label = cat(1, label, {'A1' 'A2' 'M1' 'M2' 'T3' 'T4' 'T5' 'T6'}'); + + % This is to account for all variants of case in 1020 systems + label = unique(cat(1, label, upper(label), lower(label))); + + case 'biosemi64' + label = { + 'A1' + 'A2' + 'A3' + 'A4' + 'A5' + 'A6' + 'A7' + 'A8' + 'A9' + 'A10' + 'A11' + 'A12' + 'A13' + 'A14' + 'A15' + 'A16' + 'A17' + 'A18' + 'A19' + 'A20' + 'A21' + 'A22' + 'A23' + 'A24' + 'A25' + 'A26' + 'A27' + 'A28' + 'A29' + 'A30' + 'A31' + 'A32' + 'B1' + 'B2' + 'B3' + 'B4' + 'B5' + 'B6' + 'B7' + 'B8' + 'B9' + 'B10' + 'B11' + 'B12' + 'B13' + 'B14' + 'B15' + 'B16' + 'B17' + 'B18' + 'B19' + 'B20' + 'B21' + 'B22' + 'B23' + 'B24' + 'B25' + 'B26' + 'B27' + 'B28' + 'B29' + 'B30' + 'B31' + 'B32' + }; + + case 'biosemi128' + label = { + 'A1' + 'A2' + 'A3' + 'A4' + 'A5' + 'A6' + 'A7' + 'A8' + 'A9' + 'A10' + 'A11' + 'A12' + 'A13' + 'A14' + 'A15' + 'A16' + 'A17' + 'A18' + 'A19' + 'A20' + 'A21' + 'A22' + 'A23' + 'A24' + 'A25' + 'A26' + 'A27' + 'A28' + 'A29' + 'A30' + 'A31' + 'A32' + 'B1' + 'B2' + 'B3' + 'B4' + 'B5' + 'B6' + 'B7' + 'B8' + 'B9' + 'B10' + 'B11' + 'B12' + 'B13' + 'B14' + 'B15' + 'B16' + 'B17' + 'B18' + 'B19' + 'B20' + 'B21' + 'B22' + 'B23' + 'B24' + 'B25' + 'B26' + 'B27' + 'B28' + 'B29' + 'B30' + 'B31' + 'B32' + 'C1' + 'C2' + 'C3' + 'C4' + 'C5' + 'C6' + 'C7' + 'C8' + 'C9' + 'C10' + 'C11' + 'C12' + 'C13' + 'C14' + 'C15' + 'C16' + 'C17' + 'C18' + 'C19' + 'C20' + 'C21' + 'C22' + 'C23' + 'C24' + 'C25' + 'C26' + 'C27' + 'C28' + 'C29' + 'C30' + 'C31' + 'C32' + 'D1' + 'D2' + 'D3' + 'D4' + 'D5' + 'D6' + 'D7' + 'D8' + 'D9' + 'D10' + 'D11' + 'D12' + 'D13' + 'D14' + 'D15' + 'D16' + 'D17' + 'D18' + 'D19' + 'D20' + 'D21' + 'D22' + 'D23' + 'D24' + 'D25' + 'D26' + 'D27' + 'D28' + 'D29' + 'D30' + 'D31' + 'D32' + }; + + case 'biosemi256' + label = { + 'A1' + 'A2' + 'A3' + 'A4' + 'A5' + 'A6' + 'A7' + 'A8' + 'A9' + 'A10' + 'A11' + 'A12' + 'A13' + 'A14' + 'A15' + 'A16' + 'A17' + 'A18' + 'A19' + 'A20' + 'A21' + 'A22' + 'A23' + 'A24' + 'A25' + 'A26' + 'A27' + 'A28' + 'A29' + 'A30' + 'A31' + 'A32' + 'B1' + 'B2' + 'B3' + 'B4' + 'B5' + 'B6' + 'B7' + 'B8' + 'B9' + 'B10' + 'B11' + 'B12' + 'B13' + 'B14' + 'B15' + 'B16' + 'B17' + 'B18' + 'B19' + 'B20' + 'B21' + 'B22' + 'B23' + 'B24' + 'B25' + 'B26' + 'B27' + 'B28' + 'B29' + 'B30' + 'B31' + 'B32' + 'C1' + 'C2' + 'C3' + 'C4' + 'C5' + 'C6' + 'C7' + 'C8' + 'C9' + 'C10' + 'C11' + 'C12' + 'C13' + 'C14' + 'C15' + 'C16' + 'C17' + 'C18' + 'C19' + 'C20' + 'C21' + 'C22' + 'C23' + 'C24' + 'C25' + 'C26' + 'C27' + 'C28' + 'C29' + 'C30' + 'C31' + 'C32' + 'D1' + 'D2' + 'D3' + 'D4' + 'D5' + 'D6' + 'D7' + 'D8' + 'D9' + 'D10' + 'D11' + 'D12' + 'D13' + 'D14' + 'D15' + 'D16' + 'D17' + 'D18' + 'D19' + 'D20' + 'D21' + 'D22' + 'D23' + 'D24' + 'D25' + 'D26' + 'D27' + 'D28' + 'D29' + 'D30' + 'D31' + 'D32' + 'E1' + 'E2' + 'E3' + 'E4' + 'E5' + 'E6' + 'E7' + 'E8' + 'E9' + 'E10' + 'E11' + 'E12' + 'E13' + 'E14' + 'E15' + 'E16' + 'E17' + 'E18' + 'E19' + 'E20' + 'E21' + 'E22' + 'E23' + 'E24' + 'E25' + 'E26' + 'E27' + 'E28' + 'E29' + 'E30' + 'E31' + 'E32' + 'F1' + 'F2' + 'F3' + 'F4' + 'F5' + 'F6' + 'F7' + 'F8' + 'F9' + 'F10' + 'F11' + 'F12' + 'F13' + 'F14' + 'F15' + 'F16' + 'F17' + 'F18' + 'F19' + 'F20' + 'F21' + 'F22' + 'F23' + 'F24' + 'F25' + 'F26' + 'F27' + 'F28' + 'F29' + 'F30' + 'F31' + 'F32' + 'G1' + 'G2' + 'G3' + 'G4' + 'G5' + 'G6' + 'G7' + 'G8' + 'G9' + 'G10' + 'G11' + 'G12' + 'G13' + 'G14' + 'G15' + 'G16' + 'G17' + 'G18' + 'G19' + 'G20' + 'G21' + 'G22' + 'G23' + 'G24' + 'G25' + 'G26' + 'G27' + 'G28' + 'G29' + 'G30' + 'G31' + 'G32' + 'H1' + 'H2' + 'H3' + 'H4' + 'H5' + 'H6' + 'H7' + 'H8' + 'H9' + 'H10' + 'H11' + 'H12' + 'H13' + 'H14' + 'H15' + 'H16' + 'H17' + 'H18' + 'H19' + 'H20' + 'H21' + 'H22' + 'H23' + 'H24' + 'H25' + 'H26' + 'H27' + 'H28' + 'H29' + 'H30' + 'H31' + 'H32' + }; + + case 'egi32' + label = cell(32, 1); + for i = 1:32 + label{i} = sprintf('e%d', i); + end + + case 'egi64' + label = cell(64, 1); + for i = 1:64 + label{i} = sprintf('e%d', i); + end + + case 'egi128' + label = cell(128, 1); + for i = 1:128 + label{i} = sprintf('e%d', i); + end + + case 'egi256' + label = cell(256, 1); + for i = 1:256 + label{i} = sprintf('e%d', i); + end + + case 'itab153' + label = cell(153,1); + for i=1:153 + % channel names start counting at zero + label{i} = sprintf('MAG_%03d', i-1); + end + + case 'itab153_planar' + label = cell(153,2); + for i=1:153 + % channel names start counting at zero + label{i,1} = sprintf('MAG_%03d_dH', i-1); + label{i,2} = sprintf('MAG_%03d_dV', i-1); + end + + case 'yokogawa160' + % this should be consistent with read_yokogawa_header, with + % ft_channelselection and with yokogawa2grad + label = cell(160,1); + for i=1:160 + label{i} = sprintf('AG%03d', i); + end + + case 'yokogawa160_planar' + % this should be consistent with read_yokogawa_header, with + % ft_channelselection and with yokogawa2grad + label = cell(160,2); + for i=1:160 + label{i,1} = sprintf('AG%03d_dH', i); + label{i,2} = sprintf('AG%03d_dV', i); + end + + case 'electrode' + % there is no default set of electrode labels, by input type 'electrode' should not result in an error + label = {}; + + otherwise + error('the requested sensor type is not supported'); +end + +% remember the current input and output arguments, so that they can be +% reused on a subsequent call in case the same input argument is given +current_argout = {label}; +if isempty(previous_argin) + previous_argin = current_argin; + previous_argout = current_argout; +end + diff --git a/external/fieldtrip/fileio/private/senstype.m b/external/fieldtrip/fileio/private/senstype.m new file mode 100644 index 0000000..ade2190 --- /dev/null +++ b/external/fieldtrip/fileio/private/senstype.m @@ -0,0 +1,362 @@ +function [type] = ft_senstype(input, desired) + +% FT_SENSTYPE determines the type of sensors by looking at the channel names +% and comparing them with predefined lists. +% +% Use as +% [type] = ft_senstype(sens) +% to get a string describing the type, or +% [flag] = ft_senstype(sens, desired) +% to get a boolean value. +% +% The output type can be any of the following +% 'electrode' +% 'magnetometer' +% 'biosemi64' +% 'biosemi128' +% 'biosemi256' +% 'bti148' +% 'bti148_planar' +% 'bti248' +% 'bti248_planar' +% 'ctf151' +% 'ctf151_planar' +% 'ctf275' +% 'ctf275_planar' +% 'egi128' +% 'egi256' +% 'egi32' +% 'egi64' +% 'ext1020' +% 'neuromag122' +% 'neuromag306' +% 'yokogawa160' +% 'yokogawa160_planar' +% 'plexon' +% 'itab153' +% 'itab153_planar' +% +% The optional input argument for the desired type can be any of the above, +% or any of the following +% 'eeg' +% 'meg' +% 'meg_planar' +% 'meg_axial' +% 'ctf' +% 'bti' +% 'neuromag' +% 'yokogawa' +% +% Besides specifiying a grad or elec structure as input, also allowed is +% giving a data structure containing a grad or elec field, or giving a list +% of channel names (as cell-arrray). I.e. assuming a FieldTrip data +% structure, all of the following calls would be correct. +% ft_senstype(data) +% ft_senstype(data.label) +% ft_senstype(data.grad) +% ft_senstype(data.grad.label) +% +% See also FT_SENSLABEL, FT_CHANTYPE, FT_READ_SENS, FT_COMPUTE_LEADFIELD + +% Copyright (C) 2007-2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_senstype.m 1290 2010-06-29 14:10:50Z roboos $ + +% these are for remembering the type on subsequent calls with the same input arguments +persistent previous_argin previous_argout + +if iscell(input) && numel(input)<4 && ~all(cellfun(@ischar, input)) + % this might represent combined EEG, ECoG and/or MEG + type = cell(size(input)); + if nargin<2 + desired = cell(size(input)); % empty elements + end + for i=1:numel(input) + type{i} = ft_senstype(input{i}, desired{i}); + end + return +end + +if nargin<2 + % ensure that all input arguments are defined + desired = []; +end + +current_argin = {input, desired}; +if isequal(current_argin, previous_argin) + % don't do the type detection again, but return the previous values from + % cache + type = previous_argout{1}; + return +end + +% FIXME the detection of the type of input structure should perhaps be done using the datatype function +isdata = isa(input, 'struct') && isfield(input, 'hdr'); +isheader = isa(input, 'struct') && isfield(input, 'label') && isfield(input, 'Fs'); +isgrad = isa(input, 'struct') && isfield(input, 'label') && isfield(input, 'pnt') && isfield(input, 'ori'); +iselec = isa(input, 'struct') && isfield(input, 'label') && isfield(input, 'pnt') && ~isfield(input, 'ori'); +islabel = isa(input, 'cell') && ~isempty(input) && isa(input{1}, 'char'); + +if ~isdata && ~isheader + % timelock or freq structures don't have the header structure + % the header is also removed from raw data after megrealign + % the gradiometer definition is lost after megplanar+combineplanar + isdata = isa(input, 'struct') && (isfield(input, 'grad') || isfield(input, 'elec') || isfield(input, 'label')); +end + +% the input may be a data structure which then contains a grad/elec structure, a header or only the labels +if isdata + % preferably look at the data and not the header for the grad, because it might be re-balanced and/or planar + if isfield(input, 'grad') + sens = input.grad; + isgrad = true; + elseif issubfield(input, 'hdr.grad') + sens = input.hdr.grad; + isgrad = true; + elseif issubfield(input, 'hdr.elec') + sens = input.hdr.elec; + iselec = true; + elseif isfield(input, 'elec') + sens = input.elec; + iselec = true; + elseif issubfield(input, 'hdr.label') + sens.label = input.hdr.label; + islabel = true; + elseif isfield(input, 'label') + sens.label = input.label; + islabel = true; + end +elseif isheader + if isfield(input, 'grad') + sens = input.grad; + isgrad = true; + elseif isfield(input, 'elec') + sens = input.elec; + iselec = true; + elseif isfield(input, 'label') + sens.label = input.label; + islabel = true; + end +elseif isgrad + sens = input; +elseif iselec + sens = input; +elseif islabel + sens.label = input; +else + sens = []; +end + +if isfield(input, 'type') + % preferably the structure specifies its own type + type = input.type; + +elseif issubfield(input, 'orig.FileHeader') && issubfield(input, 'orig.VarHeader') + % this is a complete header that was read from a Plexon *.nex file using read_plexon_nex + type = 'plexon'; + +elseif issubfield(input, 'orig.stname') + % this is a complete header that was read from an ITAB dataset + type = 'itab'; + +elseif issubfield(input, 'orig.sys_name') + % this is a complete header that was read from a Yokogawa dataset + type = 'yokogawa160'; + +else + % start with unknown, then try to determine the proper type by looking at the labels + type = 'unknown'; + + if isgrad + % probably this is MEG, determine the type of magnetometer/gradiometer system + % note that the order here is important: first check whether it matches a 275 channel system, then a 151 channel system, since the 151 channels are a subset of the 275 + if (mean(ismember(ft_senslabel('ctf275'), sens.label)) > 0.8) + type = 'ctf275'; + elseif (mean(ismember(ft_senslabel('ctfheadloc'), sens.label)) > 0.8) % look at the head localization channels + type = 'ctf275'; + elseif (mean(ismember(ft_senslabel('ctf151'), sens.label)) > 0.8) + type = 'ctf151'; + elseif (mean(ismember(ft_senslabel('ctf64'), sens.label)) > 0.8) + type = 'ctf64'; + elseif (mean(ismember(ft_senslabel('ctf275_planar'), sens.label)) > 0.8) + type = 'ctf275_planar'; + elseif (mean(ismember(ft_senslabel('ctf151_planar'), sens.label)) > 0.8) + type = 'ctf151_planar'; + elseif (mean(ismember(ft_senslabel('bti248'), sens.label)) > 0.8) + type = 'bti248'; + elseif (mean(ismember(ft_senslabel('bti148'), sens.label)) > 0.8) + type = 'bti148'; + elseif (mean(ismember(ft_senslabel('bti248_planar'), sens.label)) > 0.8) + type = 'bti248_planar'; + elseif (mean(ismember(ft_senslabel('bti148_planar'), sens.label)) > 0.8) + type = 'bti148_planar'; + elseif (mean(ismember(ft_senslabel('itab153'), sens.label)) > 0.8) + type = 'itab153'; + elseif (mean(ismember(ft_senslabel('itab153_planar'), sens.label)) > 0.8) + type = 'itab153_planar'; + elseif (mean(ismember(ft_senslabel('yokogawa160'), sens.label)) > 0.4) + type = 'yokogawa160'; + elseif (mean(ismember(ft_senslabel('yokogawa160_planar'), sens.label)) > 0.4) + type = 'yokogawa160_planar'; + elseif (mean(ismember(ft_senslabel('neuromag306'), sens.label)) > 0.8) + type = 'neuromag306'; + elseif (mean(ismember(ft_senslabel('neuromag306alt'),sens.label)) > 0.8) % an alternative set without spaces in the name + type = 'neuromag306'; + elseif (mean(ismember(ft_senslabel('neuromag122'), sens.label)) > 0.8) + type = 'neuromag122'; + elseif (mean(ismember(ft_senslabel('neuromag122alt'),sens.label)) > 0.8) % an alternative set without spaces in the name + type = 'neuromag122'; + elseif any(ismember(ft_senslabel('btiref'), sens.label)) + type = 'bti'; % it might be 148 or 248 channels + elseif any(ismember(ft_senslabel('ctfref'), sens.label)) + type = 'ctf'; % it might be 151 or 275 channels + elseif isfield(sens, 'pnt') && isfield(sens, 'ori') && numel(sens.label)==size(sens.pnt,1) + warning('could be Yokogawa system'); + type = 'magnetometer'; + else + warning('could be Yokogawa system'); + type = 'meg'; + end + + elseif iselec + % probably this is EEG + if (mean(ismember(ft_senslabel('biosemi256'), sens.label)) > 0.8) + type = 'biosemi256'; + elseif (mean(ismember(ft_senslabel('biosemi128'), sens.label)) > 0.8) + type = 'biosemi128'; + elseif (mean(ismember(ft_senslabel('biosemi64'), sens.label)) > 0.8) + type = 'biosemi64'; + elseif (mean(ismember(ft_senslabel('egi256'), sens.label)) > 0.8) + type = 'egi256'; + elseif (mean(ismember(ft_senslabel('egi128'), sens.label)) > 0.8) + type = 'egi128'; + elseif (mean(ismember(ft_senslabel('egi64'), sens.label)) > 0.8) + type = 'egi64'; + elseif (mean(ismember(ft_senslabel('egi32'), sens.label)) > 0.8) + type = 'egi32'; + elseif (sum(ismember(sens.label, ft_senslabel('eeg1005'))) > 10) % Otherwise it's not even worth recognizing + type = 'ext1020'; + else + type = 'electrode'; + end + + elseif islabel + % look only at the channel labels + if (mean(ismember(ft_senslabel('ctf275'), sens.label)) > 0.8) + type = 'ctf275'; + elseif (mean(ismember(ft_senslabel('ctfheadloc'), sens.label)) > 0.8) % look at the head localization channels + type = 'ctf275'; + elseif (mean(ismember(ft_senslabel('ctf151'), sens.label)) > 0.8) + type = 'ctf151'; + elseif (mean(ismember(ft_senslabel('ctf64'), sens.label)) > 0.8) + type = 'ctf64'; + elseif (mean(ismember(ft_senslabel('ctf275_planar'), sens.label)) > 0.8) + type = 'ctf275_planar'; + elseif (mean(ismember(ft_senslabel('ctf151_planar'), sens.label)) > 0.8) + type = 'ctf151_planar'; + elseif (mean(ismember(ft_senslabel('bti248'), sens.label)) > 0.8) + type = 'bti248'; + elseif (mean(ismember(ft_senslabel('bti148'), sens.label)) > 0.8) + type = 'bti148'; + elseif (mean(ismember(ft_senslabel('bti248_planar'), sens.label)) > 0.8) + type = 'bti248_planar'; + elseif (mean(ismember(ft_senslabel('bti148_planar'), sens.label)) > 0.8) + type = 'bti148_planar'; + elseif (mean(ismember(ft_senslabel('itab153'), sens.label)) > 0.8) + type = 'itab153'; + elseif (mean(ismember(ft_senslabel('itab153_planar'), sens.label)) > 0.8) + type = 'itab153_planar'; + elseif (mean(ismember(ft_senslabel('yokogawa160'), sens.label)) > 0.4) + type = 'yokogawa160'; + elseif (mean(ismember(ft_senslabel('yokogawa160_planar'), sens.label)) > 0.4) + type = 'yokogawa160_planar'; + elseif (mean(ismember(ft_senslabel('neuromag306'), sens.label)) > 0.8) + type = 'neuromag306'; + elseif (mean(ismember(ft_senslabel('neuromag306alt'),sens.label)) > 0.8) % an alternative set without spaces in the name + type = 'neuromag306'; + elseif (mean(ismember(ft_senslabel('neuromag122'), sens.label)) > 0.8) + type = 'neuromag122'; + elseif (mean(ismember(ft_senslabel('neuromag122alt'),sens.label)) > 0.8) % an alternative set without spaces in the name + type = 'neuromag122'; + elseif (mean(ismember(ft_senslabel('biosemi256'), sens.label)) > 0.8) + type = 'biosemi256'; + elseif (mean(ismember(ft_senslabel('biosemi128'), sens.label)) > 0.8) + type = 'biosemi128'; + elseif (mean(ismember(ft_senslabel('biosemi64'), sens.label)) > 0.8) + type = 'biosemi64'; + elseif (mean(ismember(ft_senslabel('egi256'), sens.label)) > 0.8) + type = 'egi256'; + elseif (mean(ismember(ft_senslabel('egi128'), sens.label)) > 0.8) + type = 'egi128'; + elseif (mean(ismember(ft_senslabel('egi64'), sens.label)) > 0.8) + type = 'egi64'; + elseif (mean(ismember(ft_senslabel('egi32'), sens.label)) > 0.8) + type = 'egi32'; + elseif (sum(ismember(sens.label, ft_senslabel('eeg1005'))) > 10) % Otherwise it's not even worth recognizing + type = 'ext1020'; + elseif any(ismember(ft_senslabel('btiref'), sens.label)) + type = 'bti'; % it might be 148 or 248 channels + elseif any(ismember(ft_senslabel('ctfref'), sens.label)) + type = 'ctf'; % it might be 151 or 275 channels + end + + end % look at label, ori and/or pnt +end % if isfield(sens, 'type') + +if ~isempty(desired) + % return a boolean flag + switch desired + case 'eeg' + type = any(strcmp(type, {'eeg' 'electrode' 'biosemi64' 'biosemi128' 'biosemi256' 'egi32' 'egi64' 'egi128' 'egi256' 'ext1020'})); + case 'biosemi' + type = any(strcmp(type, {'biosemi64' 'biosemi128' 'biosemi256'})); + case 'egi' + type = any(strcmp(type, {'egi64' 'egi128' 'egi256'})); + case 'meg' + type = any(strcmp(type, {'meg' 'magnetometer' 'ctf' 'bti' 'ctf151' 'ctf275' 'ctf151_planar' 'ctf275_planar' 'neuromag122' 'neuromag306' 'bti148' 'bti148_planar' 'bti248' 'bti248_planar' 'yokogawa160' 'yokogawa160_planar'})); + case 'ctf' + type = any(strcmp(type, {'ctf' 'ctf151' 'ctf275' 'ctf151_planar' 'ctf275_planar'})); + case 'bti' + type = any(strcmp(type, {'bti' 'bti148' 'bti148_planar' 'bti248' 'bti248_planar'})); + case 'neuromag' + type = any(strcmp(type, {'neuromag122' 'neuromag306'})); + case 'yokogawa' + type = any(strcmp(type, {'yokogawa160' 'yokogawa160_planar'})); + case 'itab' + type = any(strcmp(type, {'itab' 'itab153' 'itab153_planar'})); + case 'meg_axial' + % note that neuromag306 is mixed planar and axial + type = any(strcmp(type, {'magnetometer' 'neuromag306' 'ctf151' 'ctf275' 'bti148' 'bti248' 'yokogawa160'})); + case 'meg_planar' + % note that neuromag306 is mixed planar and axial + type = any(strcmp(type, {'neuromag122' 'neuromag306' 'ctf151_planar' 'ctf275_planar' 'bti148_planar' 'bti248_planar' 'yokogawa160_planar'})); + otherwise + type = any(strcmp(type, desired)); + end % switch desired +end % detemine the correspondence to the desired type + +% remember the current input and output arguments, so that they can be +% reused on a subsequent call in case the same input argument is given +current_argout = {type}; +if isempty(previous_argin) + previous_argin = current_argin; + previous_argout = current_argout; +end + +return % ft_senstype main() diff --git a/external/fieldtrip/fileio/private/setsubfield.m b/external/fieldtrip/fileio/private/setsubfield.m new file mode 100644 index 0000000..18f4793 --- /dev/null +++ b/external/fieldtrip/fileio/private/setsubfield.m @@ -0,0 +1,46 @@ +function [s] = setsubfield(s, f, v); + +% SETSUBFIELD sets the contents of the specified field to a specified value +% just like the standard Matlab SETFIELD function, except that you can also +% specify nested fields using a '.' in the fieldname. The nesting can be +% arbitrary deep. +% +% Use as +% s = setsubfield(s, 'fieldname', value) +% or as +% s = setsubfield(s, 'fieldname.subfieldname', value) +% +% See also SETFIELD, GETSUBFIELD, ISSUBFIELD + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: setsubfield.m 951 2010-04-21 18:24:01Z roboos $ + +if ~isstr(f) + error('incorrect input argument for fieldname'); +end + +t = {}; +while (1) + [t{end+1}, f] = strtok(f, '.'); + if isempty(f) + break + end +end +s = setfield(s, t{:}, v); diff --git a/external/fieldtrip/fileio/private/timestamp_neuralynx.m b/external/fieldtrip/fileio/private/timestamp_neuralynx.m new file mode 100644 index 0000000..0c2ee64 --- /dev/null +++ b/external/fieldtrip/fileio/private/timestamp_neuralynx.m @@ -0,0 +1,42 @@ +function [ts] = timestamp_neuralynx(tsl, tsh) + +% TIMESTAMP_NEURALYNX merge the low and high part of Neuralynx timestamps +% into a single uint64 value + +% Copyright (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: timestamp_neuralynx.m 945 2010-04-21 17:41:20Z roboos $ + +if ~isa(tsl, 'uint32') && ~isa(tsl, 'int32') + error('invalid input'); +elseif ~isa(tsh, 'uint32') && ~isa(tsl, 'int32') + error('invalid input'); +end + +% convert the 32 bit low and 32 bit high timestamp into a 64 bit integer +dum = zeros(2, length(tsh), 'uint32'); +if littleendian + dum(1,:) = tsl; + dum(2,:) = tsh; +else + dum(1,:) = tsh; + dum(2,:) = tsl; +end + +ts = typecast(dum(:), 'uint64'); diff --git a/external/fieldtrip/fileio/private/timestamp_plexon.m b/external/fieldtrip/fileio/private/timestamp_plexon.m new file mode 100644 index 0000000..3bbbdd7 --- /dev/null +++ b/external/fieldtrip/fileio/private/timestamp_plexon.m @@ -0,0 +1,53 @@ +function [ts] = timestamp_plexon(tsl, tsh) + +% TIMESTAMP_PLEXON merge the low and high part of the timestamps +% into a single uint64 value + +% Copyright (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: timestamp_plexon.m 945 2010-04-21 17:41:20Z roboos $ + +if ~isa(tsl, 'uint32') + error('invalid input'); +elseif ~isa(tsh, 'uint16') + error('invalid input'); +end + +% convert the 16 bit high timestamp into a 32 bit integer +dum = zeros(2, length(tsh), 'uint16'); +if littleendian + dum(1,:) = tsh(:); +else + dum(2,:) = tsh(:); +end +tsh = typecast(dum(:), 'uint32'); + +% convert the 32 bit low and 32 bit high timestamp into a 64 bit integer +dum = zeros(2, length(tsh), 'uint32'); +if littleendian + dum(1,:) = tsl; + dum(2,:) = tsh; +else + dum(1,:) = tsh; + dum(2,:) = tsl; +end + +ts = typecast(dum(:), 'uint64'); +ts = reshape(ts, size(tsl)); + diff --git a/external/fieldtrip/fileio/private/tokenize.m b/external/fieldtrip/fileio/private/tokenize.m new file mode 100644 index 0000000..43b900e --- /dev/null +++ b/external/fieldtrip/fileio/private/tokenize.m @@ -0,0 +1,76 @@ +function [tok] = tokenize(str, sep, rep) + +% TOKENIZE cuts a string into pieces, returning the pieces in a cell array +% +% Use as +% t = tokenize(str) +% t = tokenize(str, sep) +% t = tokenize(str, sep, rep) +% where +% str = the string that you want to cut into pieces +% sep = the separator at which to cut (default is whitespace) +% rep = whether to treat repeating seperator characters as one (default is false) +% +% With the optional boolean flag "rep" you can specify whether repeated +% seperator characters should be squeezed together (e.g. multiple +% spaces between two words). The default is rep=1, i.e. repeated +% seperators are treated as one. +% +% See also STRTOK, TEXTSCAN + +% Copyright (C) 2003-2010, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: tokenize.m 1388 2010-07-10 09:12:47Z roboos $ + +% these are for remembering the type on subsequent calls with the same input arguments +persistent previous_argin previous_argout + +if nargin<2 + sep = [9:13 32]; % White space characters +end + +if nargin<3 + rep = false; +end + +current_argin = {str, sep, rep}; +if isequal(current_argin, previous_argin) + % don't do the processing again, but return the previous values from cache + tok = previous_argout; + return +end + +tok = {}; +f = find(ismember(str, sep)); +f = [0, f, length(str)+1]; +for i=1:(length(f)-1) + tok{i} = str((f(i)+1):(f(i+1)-1)); +end + +if rep + % remove empty cells, which occur if the separator is repeated (e.g. multiple spaces) + tok(cellfun('isempty', tok))=[]; +end + +% remember the current input and output arguments, so that they can be +% reused on a subsequent call in case the same input argument is given +current_argout = tok; +previous_argin = current_argin; +previous_argout = current_argout; + diff --git a/external/fieldtrip/fileio/private/voltype.m b/external/fieldtrip/fileio/private/voltype.m new file mode 100644 index 0000000..ede027d --- /dev/null +++ b/external/fieldtrip/fileio/private/voltype.m @@ -0,0 +1,107 @@ +function [type] = ft_voltype(vol, desired) + +% FT_VOLTYPE determines the type of volume conduction model +% +% Use as +% [type] = ft_voltype(vol) +% to get a string describing the type, or +% [flag] = ft_voltype(vol, desired) +% to get a boolean value. +% +% See also FT_READ_VOL, FT_COMPUTE_LEADFIELD + +% Copyright (C) 2007-2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_voltype.m 946 2010-04-21 17:51:16Z roboos $ + +% these are for remembering the type on subsequent calls with the same input arguments +persistent previous_argin previous_argout + +if iscell(vol) && numel(vol)<4 + % this might represent combined EEG, ECoG and/or MEG + type = cell(size(vol)); + if nargin<2 + desired = cell(size(vol)); % empty elements + end + for i=1:numel(vol) + type{i} = ft_voltype(vol{i}, desired{i}); + end + return +end + +if nargin<2 + % ensure that all input arguments are defined + desired = []; +end + +current_argin = {vol, desired}; +if isequal(current_argin, previous_argin) + % don't do the type detection again, but return the previous values from cache + type = previous_argout{1}; + return +end + +if isfield(vol, 'type') + % preferably the structure specifies its own type + type = vol.type; + +elseif isfield(vol, 'r') && numel(vol.r)==1 && ~isfield(vol, 'label') + type = 'singlesphere'; + +elseif isfield(vol, 'r') && isfield(vol, 'o') && isfield(vol, 'label') + % this is before the spheres have been assigned to the coils + % and every sphere is still associated with a channel + type = 'multisphere'; + +elseif isfield(vol, 'r') && isfield(vol, 'o') && size(vol.r,1)==size(vol.o,1) && size(vol.r,1)>4 + % this is after the spheres have been assigned to the coils + % note that this one is easy to confuse with the concentric one + type = 'multisphere'; + +elseif isfield(vol, 'r') && numel(vol.r)>=2 && ~isfield(vol, 'label') + type = 'concentric'; + +elseif isfield(vol, 'bnd') + type = 'bem'; + +elseif isempty(vol) + type = 'infinite'; + +else + type = 'unknown'; + +end % if isfield(vol, 'type') + +if ~isempty(desired) + % return a boolean flag + switch desired + case 'bem' + type = any(strcmp(type, {'bem', 'dipoli', 'asa', 'avo', 'bemcp', 'openmeeg'})); + otherwise + type = any(strcmp(type, desired)); + end +end + +% remember the current input and output arguments, so that they can be +% reused on a subsequent call in case the same input argument is given +current_argout = {type}; +previous_argin = current_argin; +previous_argout = current_argout; + +return % voltype main() diff --git a/external/fieldtrip/fileio/private/warp_apply.m b/external/fieldtrip/fileio/private/warp_apply.m new file mode 100644 index 0000000..290a991 --- /dev/null +++ b/external/fieldtrip/fileio/private/warp_apply.m @@ -0,0 +1,166 @@ +function [warped] = warp_apply(M, input, method); + +% WARP_APPLY performs a 3D linear or nonlinear transformation on the input +% coordinates, similar to those in AIR 3.08. You can find technical +% documentation on warping in general at http://bishopw.loni.ucla.edu/AIR3 +% +% Use as +% [warped] = warp_apply(M, input, method) +% where +% M vector or matrix with warping parameters +% input Nx3 matrix with coordinates +% warped Nx3 matrix with coordinates +% method string describing the warping method +% +% The methods 'nonlin0', 'nonlin2' ... 'nonlin5' specify a +% polynomial transformation. The size of the transformation matrix +% depends on the order of the warp +% zeroth order : 1 parameter per coordinate (translation) +% first order : 4 parameters per coordinate (total 12, affine) +% second order : 10 parameters per coordinate +% third order : 20 parameters per coordinate +% fourth order : 35 parameters per coordinate +% fifth order : 56 parameters per coordinate (total 168) +% The size of M should be 3xP, where P is the number of parameters +% per coordinate. Alternatively, you can specify the method to be +% 'nonlinear', where the order will be determined from teh size of +% the matrix M. +% +% If the method 'homogeneous' is selected, the input matrix M should be +% a 4x4 homogenous transformation matrix. +% +% If any other method is selected, it is assumed that it specifies +% the name of an auxiliary function that will, when given the input +% parameter vector M, return an 4x4 homogenous transformation +% matrix. Supplied functions in teh warping toolbox are translate, +% rotate, scale, rigidbody, globalrescale, traditional, affine, +% perspective. + +% Copyright (C) 2000-2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: warp_apply.m 945 2010-04-21 17:41:20Z roboos $ + +if nargin<3 && all(size(M)==4) + % no specific transformation mode has been selected + % it looks like a homogenous transformation matrix + method = 'homogenous'; +elseif nargin<3 + % the default method is 'nonlinear' + method = 'nonlinear'; +end + +if size(input,2)==2 + % convert the input points from 2D to 3D representation + input(:,3) = 0; + input3d = false; +else + input3d = true; +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% nonlinear warping +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +if any(strcmp(method, {'nonlinear', 'nonlin0', 'nonlin1', 'nonlin2', 'nonlin3', 'nonlin4', 'nonlin5'})) + x = input(:,1); + y = input(:,2); + z = input(:,3); + s = size(M); + + if s(1)~=3 + error('invalid size of nonlinear transformation matrix'); + elseif strcmp(method, 'nonlin0') & s(2)~=1 + error('invalid size of nonlinear transformation matrix'); + elseif strcmp(method, 'nonlin1') & s(2)~=4 + error('invalid size of nonlinear transformation matrix'); + elseif strcmp(method, 'nonlin2') & s(2)~=10 + error('invalid size of nonlinear transformation matrix'); + elseif strcmp(method, 'nonlin3') & s(2)~=20 + error('invalid size of nonlinear transformation matrix'); + elseif strcmp(method, 'nonlin4') & s(2)~=35 + error('invalid size of nonlinear transformation matrix'); + elseif strcmp(method, 'nonlin5') & s(2)~=56 + error('invalid size of nonlinear transformation matrix'); + end + + if s(2)==1 + % this is a translation, which in a strict sense is not the 0th order nonlinear transformation + xx = M(1,1) + x; + yy = M(2,1) + y; + zz = M(3,1) + z; + elseif s(2)==4 + xx = M(1,1) + M(1,2)*x + M(1,3)*y + M(1,4)*z; + yy = M(2,1) + M(2,2)*x + M(2,3)*y + M(2,4)*z; + zz = M(3,1) + M(3,2)*x + M(3,3)*y + M(3,4)*z; + elseif s(2)==10 + xx = M(1,1) + M(1,2)*x + M(1,3)*y + M(1,4)*z + M(1,5)*x.*x + M(1,6)*x.*y + M(1,7)*x.*z + M(1,8)*y.*y + M(1,9)*y.*z + M(1,10)*z.*z; + yy = M(2,1) + M(2,2)*x + M(2,3)*y + M(2,4)*z + M(2,5)*x.*x + M(2,6)*x.*y + M(2,7)*x.*z + M(2,8)*y.*y + M(2,9)*y.*z + M(2,10)*z.*z; + zz = M(3,1) + M(3,2)*x + M(3,3)*y + M(3,4)*z + M(3,5)*x.*x + M(3,6)*x.*y + M(3,7)*x.*z + M(3,8)*y.*y + M(3,9)*y.*z + M(3,10)*z.*z; + elseif s(2)==20 + xx = M(1,1) + M(1,2)*x + M(1,3)*y + M(1,4)*z + M(1,5)*x.*x + M(1,6)*x.*y + M(1,7)*x.*z + M(1,8)*y.*y + M(1,9)*y.*z + M(1,10)*z.*z + M(1,11)*x.*x.*x + M(1,12)*x.*x.*y + M(1,13)*x.*x.*z + M(1,14)*x.*y.*y + M(1,15)*x.*y.*z + M(1,16)*x.*z.*z + M(1,17)*y.*y.*y + M(1,18)*y.*y.*z + M(1,19)*y.*z.*z + M(1,20)*z.*z.*z; + yy = M(2,1) + M(2,2)*x + M(2,3)*y + M(2,4)*z + M(2,5)*x.*x + M(2,6)*x.*y + M(2,7)*x.*z + M(2,8)*y.*y + M(2,9)*y.*z + M(2,10)*z.*z + M(2,11)*x.*x.*x + M(2,12)*x.*x.*y + M(2,13)*x.*x.*z + M(2,14)*x.*y.*y + M(2,15)*x.*y.*z + M(2,16)*x.*z.*z + M(2,17)*y.*y.*y + M(2,18)*y.*y.*z + M(2,19)*y.*z.*z + M(2,20)*z.*z.*z; + zz = M(3,1) + M(3,2)*x + M(3,3)*y + M(3,4)*z + M(3,5)*x.*x + M(3,6)*x.*y + M(3,7)*x.*z + M(3,8)*y.*y + M(3,9)*y.*z + M(3,10)*z.*z + M(3,11)*x.*x.*x + M(3,12)*x.*x.*y + M(3,13)*x.*x.*z + M(3,14)*x.*y.*y + M(3,15)*x.*y.*z + M(3,16)*x.*z.*z + M(3,17)*y.*y.*y + M(3,18)*y.*y.*z + M(3,19)*y.*z.*z + M(3,20)*z.*z.*z; + elseif s(2)==35 + xx = M(1,1) + M(1,2)*x + M(1,3)*y + M(1,4)*z + M(1,5)*x.*x + M(1,6)*x.*y + M(1,7)*x.*z + M(1,8)*y.*y + M(1,9)*y.*z + M(1,10)*z.*z + M(1,11)*x.*x.*x + M(1,12)*x.*x.*y + M(1,13)*x.*x.*z + M(1,14)*x.*y.*y + M(1,15)*x.*y.*z + M(1,16)*x.*z.*z + M(1,17)*y.*y.*y + M(1,18)*y.*y.*z + M(1,19)*y.*z.*z + M(1,20)*z.*z.*z + M(1,21)*x.*x.*x.*x + M(1,22)*x.*x.*x.*y + M(1,23)*x.*x.*x.*z + M(1,24)*x.*x.*y.*y + M(1,25)*x.*x.*y.*z + M(1,26)*x.*x.*z.*z + M(1,27)*x.*y.*y.*y + M(1,28)*x.*y.*y.*z + M(1,29)*x.*y.*z.*z + M(1,30)*x.*z.*z.*z + M(1,31)*y.*y.*y.*y + M(1,32)*y.*y.*y.*z + M(1,33)*y.*y.*z.*z + M(1,34)*y.*z.*z.*z + M(1,35)*z.*z.*z.*z; + yy = M(2,1) + M(2,2)*x + M(2,3)*y + M(2,4)*z + M(2,5)*x.*x + M(2,6)*x.*y + M(2,7)*x.*z + M(2,8)*y.*y + M(2,9)*y.*z + M(2,10)*z.*z + M(2,11)*x.*x.*x + M(2,12)*x.*x.*y + M(2,13)*x.*x.*z + M(2,14)*x.*y.*y + M(2,15)*x.*y.*z + M(2,16)*x.*z.*z + M(2,17)*y.*y.*y + M(2,18)*y.*y.*z + M(2,19)*y.*z.*z + M(2,20)*z.*z.*z + M(2,21)*x.*x.*x.*x + M(2,22)*x.*x.*x.*y + M(2,23)*x.*x.*x.*z + M(2,24)*x.*x.*y.*y + M(2,25)*x.*x.*y.*z + M(2,26)*x.*x.*z.*z + M(2,27)*x.*y.*y.*y + M(2,28)*x.*y.*y.*z + M(2,29)*x.*y.*z.*z + M(2,30)*x.*z.*z.*z + M(2,31)*y.*y.*y.*y + M(2,32)*y.*y.*y.*z + M(2,33)*y.*y.*z.*z + M(2,34)*y.*z.*z.*z + M(2,35)*z.*z.*z.*z; + zz = M(3,1) + M(3,2)*x + M(3,3)*y + M(3,4)*z + M(3,5)*x.*x + M(3,6)*x.*y + M(3,7)*x.*z + M(3,8)*y.*y + M(3,9)*y.*z + M(3,10)*z.*z + M(3,11)*x.*x.*x + M(3,12)*x.*x.*y + M(3,13)*x.*x.*z + M(3,14)*x.*y.*y + M(3,15)*x.*y.*z + M(3,16)*x.*z.*z + M(3,17)*y.*y.*y + M(3,18)*y.*y.*z + M(3,19)*y.*z.*z + M(3,20)*z.*z.*z + M(3,21)*x.*x.*x.*x + M(3,22)*x.*x.*x.*y + M(3,23)*x.*x.*x.*z + M(3,24)*x.*x.*y.*y + M(3,25)*x.*x.*y.*z + M(3,26)*x.*x.*z.*z + M(3,27)*x.*y.*y.*y + M(3,28)*x.*y.*y.*z + M(3,29)*x.*y.*z.*z + M(3,30)*x.*z.*z.*z + M(3,31)*y.*y.*y.*y + M(3,32)*y.*y.*y.*z + M(3,33)*y.*y.*z.*z + M(3,34)*y.*z.*z.*z + M(3,35)*z.*z.*z.*z; + elseif s(2)==56 + xx = M(1,1) + M(1,2)*x + M(1,3)*y + M(1,4)*z + M(1,5)*x.*x + M(1,6)*x.*y + M(1,7)*x.*z + M(1,8)*y.*y + M(1,9)*y.*z + M(1,10)*z.*z + M(1,11)*x.*x.*x + M(1,12)*x.*x.*y + M(1,13)*x.*x.*z + M(1,14)*x.*y.*y + M(1,15)*x.*y.*z + M(1,16)*x.*z.*z + M(1,17)*y.*y.*y + M(1,18)*y.*y.*z + M(1,19)*y.*z.*z + M(1,20)*z.*z.*z + M(1,21)*x.*x.*x.*x + M(1,22)*x.*x.*x.*y + M(1,23)*x.*x.*x.*z + M(1,24)*x.*x.*y.*y + M(1,25)*x.*x.*y.*z + M(1,26)*x.*x.*z.*z + M(1,27)*x.*y.*y.*y + M(1,28)*x.*y.*y.*z + M(1,29)*x.*y.*z.*z + M(1,30)*x.*z.*z.*z + M(1,31)*y.*y.*y.*y + M(1,32)*y.*y.*y.*z + M(1,33)*y.*y.*z.*z + M(1,34)*y.*z.*z.*z + M(1,35)*z.*z.*z.*z + M(1,36)*x.*x.*x.*x.*x + M(1,37)*x.*x.*x.*x.*y + M(1,38)*x.*x.*x.*x.*z + M(1,39)*x.*x.*x.*y.*y + M(1,40)*x.*x.*x.*y.*z + M(1,41)*x.*x.*x.*z.*z + M(1,42)*x.*x.*y.*y.*y + M(1,43)*x.*x.*y.*y.*z + M(1,44)*x.*x.*y.*z.*z + M(1,45)*x.*x.*z.*z.*z + M(1,46)*x.*y.*y.*y.*y + M(1,47)*x.*y.*y.*y.*z + M(1,48)*x.*y.*y.*z.*z + M(1,49)*x.*y.*z.*z.*z + M(1,50)*x.*z.*z.*z.*z + M(1,51)*y.*y.*y.*y.*y + M(1,52)*y.*y.*y.*y.*z + M(1,53)*y.*y.*y.*z.*z + M(1,54)*y.*y.*z.*z.*z + M(1,55)*y.*z.*z.*z.*z + M(1,56)*z.*z.*z.*z.*z; + yy = M(2,1) + M(2,2)*x + M(2,3)*y + M(2,4)*z + M(2,5)*x.*x + M(2,6)*x.*y + M(2,7)*x.*z + M(2,8)*y.*y + M(2,9)*y.*z + M(2,10)*z.*z + M(2,11)*x.*x.*x + M(2,12)*x.*x.*y + M(2,13)*x.*x.*z + M(2,14)*x.*y.*y + M(2,15)*x.*y.*z + M(2,16)*x.*z.*z + M(2,17)*y.*y.*y + M(2,18)*y.*y.*z + M(2,19)*y.*z.*z + M(2,20)*z.*z.*z + M(2,21)*x.*x.*x.*x + M(2,22)*x.*x.*x.*y + M(2,23)*x.*x.*x.*z + M(2,24)*x.*x.*y.*y + M(2,25)*x.*x.*y.*z + M(2,26)*x.*x.*z.*z + M(2,27)*x.*y.*y.*y + M(2,28)*x.*y.*y.*z + M(2,29)*x.*y.*z.*z + M(2,30)*x.*z.*z.*z + M(2,31)*y.*y.*y.*y + M(2,32)*y.*y.*y.*z + M(2,33)*y.*y.*z.*z + M(2,34)*y.*z.*z.*z + M(2,35)*z.*z.*z.*z + M(2,36)*x.*x.*x.*x.*x + M(2,37)*x.*x.*x.*x.*y + M(2,38)*x.*x.*x.*x.*z + M(2,39)*x.*x.*x.*y.*y + M(2,40)*x.*x.*x.*y.*z + M(2,41)*x.*x.*x.*z.*z + M(2,42)*x.*x.*y.*y.*y + M(2,43)*x.*x.*y.*y.*z + M(2,44)*x.*x.*y.*z.*z + M(2,45)*x.*x.*z.*z.*z + M(2,46)*x.*y.*y.*y.*y + M(2,47)*x.*y.*y.*y.*z + M(2,48)*x.*y.*y.*z.*z + M(2,49)*x.*y.*z.*z.*z + M(2,50)*x.*z.*z.*z.*z + M(2,51)*y.*y.*y.*y.*y + M(2,52)*y.*y.*y.*y.*z + M(2,53)*y.*y.*y.*z.*z + M(2,54)*y.*y.*z.*z.*z + M(2,55)*y.*z.*z.*z.*z + M(2,56)*z.*z.*z.*z.*z; + zz = M(3,1) + M(3,2)*x + M(3,3)*y + M(3,4)*z + M(3,5)*x.*x + M(3,6)*x.*y + M(3,7)*x.*z + M(3,8)*y.*y + M(3,9)*y.*z + M(3,10)*z.*z + M(3,11)*x.*x.*x + M(3,12)*x.*x.*y + M(3,13)*x.*x.*z + M(3,14)*x.*y.*y + M(3,15)*x.*y.*z + M(3,16)*x.*z.*z + M(3,17)*y.*y.*y + M(3,18)*y.*y.*z + M(3,19)*y.*z.*z + M(3,20)*z.*z.*z + M(3,21)*x.*x.*x.*x + M(3,22)*x.*x.*x.*y + M(3,23)*x.*x.*x.*z + M(3,24)*x.*x.*y.*y + M(3,25)*x.*x.*y.*z + M(3,26)*x.*x.*z.*z + M(3,27)*x.*y.*y.*y + M(3,28)*x.*y.*y.*z + M(3,29)*x.*y.*z.*z + M(3,30)*x.*z.*z.*z + M(3,31)*y.*y.*y.*y + M(3,32)*y.*y.*y.*z + M(3,33)*y.*y.*z.*z + M(3,34)*y.*z.*z.*z + M(3,35)*z.*z.*z.*z + M(3,36)*x.*x.*x.*x.*x + M(3,37)*x.*x.*x.*x.*y + M(3,38)*x.*x.*x.*x.*z + M(3,39)*x.*x.*x.*y.*y + M(3,40)*x.*x.*x.*y.*z + M(3,41)*x.*x.*x.*z.*z + M(3,42)*x.*x.*y.*y.*y + M(3,43)*x.*x.*y.*y.*z + M(3,44)*x.*x.*y.*z.*z + M(3,45)*x.*x.*z.*z.*z + M(3,46)*x.*y.*y.*y.*y + M(3,47)*x.*y.*y.*y.*z + M(3,48)*x.*y.*y.*z.*z + M(3,49)*x.*y.*z.*z.*z + M(3,50)*x.*z.*z.*z.*z + M(3,51)*y.*y.*y.*y.*y + M(3,52)*y.*y.*y.*y.*z + M(3,53)*y.*y.*y.*z.*z + M(3,54)*y.*y.*z.*z.*z + M(3,55)*y.*z.*z.*z.*z + M(3,56)*z.*z.*z.*z.*z; + else + error('invalid size of nonlinear transformation matrix'); + end + + warped = [xx yy zz]; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % linear warping using homogenous coordinate transformation matrix + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +elseif strcmp(method, 'homogenous') || strcmp(method, 'homogeneous') + if all(size(M)==3) + % convert the 3x3 homogenous transformation matrix (corresponding with 2D) + % into a 4x4 homogenous transformation matrix (corresponding with 3D) + M = [ + M(1,1) M(1,2) 0 M(1,3) + M(2,1) M(2,2) 0 M(2,3) + 0 0 0 0 + M(3,1) M(3,2) 0 M(3,3) + ]; + end + + warped = M * [input'; ones(1, size(input, 1))]; + warped = warped(1:3,:)'; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % using external function that returns a homogenous transformation matrix + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +elseif exist(method, 'file') + % get the homogenous transformation matrix + H = feval(method, M); + warped = warp_apply(H, input, 'homogenous'); + +else + error('unrecognized transformation method'); +end + +if ~input3d + % convert from 3D back to 2D representation + warped = warped(:,1:2); +end + diff --git a/external/fieldtrip/fileio/private/write_brainvision_eeg.m b/external/fieldtrip/fileio/private/write_brainvision_eeg.m new file mode 100644 index 0000000..044ce7d --- /dev/null +++ b/external/fieldtrip/fileio/private/write_brainvision_eeg.m @@ -0,0 +1,97 @@ +function write_brainvision_eeg(filename, hdr, dat); + +% WRITE_BRAINVISION_EEG exports continuous EEG data to a BrainVision *.eeg +% and corresponding *.vhdr file. The samples in the exported file are +% multiplexed and stored in ieee-le float32 format. +% +% Use as +% write_brainvision_eeg(filename, hdr, dat) +% +% See also READ_BRAINVISION_EEG, READ_BRAINVISION_VHDR, READ_BRAINVISION_VMRK + +% Copyright (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: write_brainvision_eeg.m 1350 2010-07-05 06:59:27Z roboos $ + +if length(size(dat))>2 + ntrl = size(dat,1); + nchan = size(dat,2); + nsmp = size(dat,3); +else + nchan = size(dat,1); + nsmp = size(dat,2); +end + +if hdr.nChans~=nchan + error('number of channels in in header does not match with the data'); +end + +% this is the only supported data format +hdr.DataFormat = 'BINARY'; +hdr.DataOrientation = 'MULTIPLEXED'; +hdr.BinaryFormat = 'IEEE_FLOAT_32'; +hdr.resolution = ones(size(hdr.label)); % no additional calibration needed, since float32 + +% determine the filenames +[p, f, x] = fileparts(filename); +headerfile = fullfile(p, [f '.vhdr']); +datafile = fullfile(p, [f '.eeg']); +markerfile = ''; + +% open the data file and write the binary data +fid = fopen(datafile, 'wb', 'ieee-le'); +if length(size(dat))>2 + warning('writing segmented data as if it were continuous'); + for i=1:ntrl + fwrite(fid, squeeze(dat(i,:,:)), 'float32'); + end +else + fwrite(fid, dat, 'float32'); +end + +fclose(fid); + +% open the header file and write the ascii header information +fid = fopen(headerfile, 'wb'); +fprintf(fid, 'Brain Vision Data Exchange Header File Version 1.0\r\n'); +fprintf(fid, '; Data created by FieldTrip\r\n'); +fprintf(fid, '\r\n'); +fprintf(fid, '[Common Infos]\r\n'); +fprintf(fid, 'DataFile=%s\r\n', datafile); +if ~isempty(markerfile) + fprintf(fid, 'MarkerFile=%s\r\n', markerfile); +end +fprintf(fid, 'DataFormat=%s\r\n', hdr.DataFormat); +fprintf(fid, 'DataOrientation=%s\r\n', hdr.DataOrientation); +fprintf(fid, 'NumberOfChannels=%d\r\n', hdr.nChans); +% Sampling interval in microseconds +fprintf(fid, 'SamplingInterval=%d\r\n', round(1e6/hdr.Fs)); +fprintf(fid, '\r\n'); +fprintf(fid, '[Binary Infos]\r\n'); +fprintf(fid, 'BinaryFormat=%s\r\n', hdr.BinaryFormat); +fprintf(fid, '\r\n'); +fprintf(fid, '[Channel Infos]\r\n'); +% Each entry: Ch=,,,... +% Fields are delimited by commas, some fields might be omitted (empty). +% Commas in channel names should be coded as "\1", but are not supported here +for i=1:hdr.nChans + fprintf(fid, 'Ch%d=%s,,%g\r\n', i, hdr.label{i}, hdr.resolution(i)); +end +fclose(fid); + diff --git a/external/fileio/private/write_ctf_shm.c b/external/fieldtrip/fileio/private/write_ctf_shm.c similarity index 100% rename from external/fileio/private/write_ctf_shm.c rename to external/fieldtrip/fileio/private/write_ctf_shm.c diff --git a/external/fieldtrip/fileio/private/write_ctf_shm.m b/external/fieldtrip/fileio/private/write_ctf_shm.m new file mode 100644 index 0000000..80689c0 --- /dev/null +++ b/external/fieldtrip/fileio/private/write_ctf_shm.m @@ -0,0 +1,62 @@ +function [varargout] = funname(varargin) + +% WRITE_CTF_SHM writes metainformation and data as a packet to shared memory. +% This function can be used for real-time processing of data while it is +% being acquired. +% +% Use as +% write_ctf_shm(msgType, msgId, sampleNumber, numSamples, numChannels, data); +% +% See also READ_CTF_SHM + +% Copyright (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: write_ctf_shm.m 945 2010-04-21 17:41:20Z roboos $ + +% remember the original working directory +pwdir = pwd; + +% determine the name and full path of this function +funname = mfilename('fullpath'); +mexsrc = [funname '.c']; +[mexdir, mexname] = fileparts(funname); + +try + % try to compile the mex file on the fly + warning('trying to compile MEX file from %s', mexsrc); + cd(mexdir); + mex(mexsrc); + cd(pwdir); + success = true; + +catch + % compilation failed + disp(lasterr); + error('could not locate MEX file for %s', mexname); + cd(pwdir); + success = false; +end + +if success + % execute the mex file that was juist created + funname = mfilename; + funhandle = str2func(funname); + [varargout{1:nargout}] = funhandle(varargin{:}); +end + diff --git a/external/fileio/private/write_ctf_shm.mexa64 b/external/fieldtrip/fileio/private/write_ctf_shm.mexa64 similarity index 100% rename from external/fileio/private/write_ctf_shm.mexa64 rename to external/fieldtrip/fileio/private/write_ctf_shm.mexa64 diff --git a/external/fileio/private/write_ctf_shm.mexglx b/external/fieldtrip/fileio/private/write_ctf_shm.mexglx similarity index 100% rename from external/fileio/private/write_ctf_shm.mexglx rename to external/fieldtrip/fileio/private/write_ctf_shm.mexglx diff --git a/external/fileio/private/write_ctf_shm.mexmaci b/external/fieldtrip/fileio/private/write_ctf_shm.mexmaci similarity index 85% rename from external/fileio/private/write_ctf_shm.mexmaci rename to external/fieldtrip/fileio/private/write_ctf_shm.mexmaci index ec4eeb0..fd06f8d 100755 Binary files a/external/fileio/private/write_ctf_shm.mexmaci and b/external/fieldtrip/fileio/private/write_ctf_shm.mexmaci differ diff --git a/external/fileio/private/write_ctf_shm.mexmaci64 b/external/fieldtrip/fileio/private/write_ctf_shm.mexmaci64 similarity index 100% rename from external/fileio/private/write_ctf_shm.mexmaci64 rename to external/fieldtrip/fileio/private/write_ctf_shm.mexmaci64 diff --git a/external/fieldtrip/fileio/private/write_neuralynx_ncs.m b/external/fieldtrip/fileio/private/write_neuralynx_ncs.m new file mode 100644 index 0000000..81ff4bd --- /dev/null +++ b/external/fieldtrip/fileio/private/write_neuralynx_ncs.m @@ -0,0 +1,95 @@ +function write_neuralynx_ncs(filename, ncs); + +% WRITE_NEURALYNX_NCS writes continuous data to a NCS file +% The input data should be scaled in uV. +% +% Use as +% write_neuralynx_ncs(filename, ncs) +% +% See also READ_NEURALYNX_NCS + +% Copyright (C) 2005-2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: write_neuralynx_ncs.m 945 2010-04-21 17:41:20Z roboos $ + +if ~isa(ncs.TimeStamp, 'uint64') + error('timestamps should be uint64'); +end + +% convert the data from uV into V +ncs.dat = ncs.dat * 1e-6; +% scale the data and convert to 16 bits, +% this has to be done prior to writing the header +ADMaxValue = double(intmax('int16')); +ADMaxVolts = max(abs(ncs.dat(:))); +if ADMaxVolts>0 + ADBitVolts = ADMaxVolts / ADMaxValue; +else + ADBitVolts = 1; +end +ncs.dat = int16(ncs.dat / ADBitVolts); +% update the header with the calibration values +ncs.hdr.ADBitVolts = ADBitVolts; +ncs.hdr.ADMaxValue = ADMaxValue; + +% construct the header +buf = []; +buf = [buf sprintf('######## Neuralynx Data File Header\r\n')]; +buf = [buf sprintf('## File Name: %s\r\n', filename)]; +buf = [buf sprintf('## Time Opened: (m/d/y): %s At Time: %s\r\n', datestr(clock, 'mm/dd/yy'), datestr(clock, 'HH:MM:SS'))]; +f = fieldnames(ncs.hdr); +for i=1:length(f) + v = getfield(ncs.hdr, f{i}); + switch class(v) + case 'char' + buf = [buf sprintf('-%s\t%s\r\n', f{i}, v)]; + case 'double' + buf = [buf sprintf('-%s\t%s\r\n', f{i}, num2str(v))]; + otherwise + error('unknown class in writing header'); + end +end + +% pad the rest of the header with zeros +buf((end+1):16384) = 0; + +% open the file and write the header +fid = fopen(filename, 'wb', 'ieee-le'); +fwrite(fid, buf); + +% The format of a continuous sampled record is +% int64 TimeStamp +% int32 ChanNumber +% int32 SampFreq +% int32 NumValidSamp +% int16 Samp[0] ... int16 Samp[511] +% Note that if NumValidSamp < 512, Samp[n], where n >= NumValidSamp, will +% contain random data. + +for i=1:size(ncs.dat,2) + % write a single continuous data record + fwrite(fid, ncs.TimeStamp(i) , 'uint64'); + fwrite(fid, ncs.ChanNumber(i) , 'int32'); + fwrite(fid, ncs.SampFreq(i) , 'int32'); + fwrite(fid, ncs.NumValidSamp(i), 'int32'); + fwrite(fid, ncs.dat(:,i) , 'int16'); +end + +% close the file +fclose(fid); diff --git a/external/fieldtrip/fileio/private/write_neuralynx_nts.m b/external/fieldtrip/fileio/private/write_neuralynx_nts.m new file mode 100644 index 0000000..0052e99 --- /dev/null +++ b/external/fieldtrip/fileio/private/write_neuralynx_nts.m @@ -0,0 +1,67 @@ +function write_neuralynx_nts(filename, nts); + +% WRITE_NEURALYNX_NTS writes spike timestamps to a NTS file +% +% Use as +% write_neuralynx_nts(filename, nts) +% +% See also READ_NEURALYNX_NTS + +% Copyright (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: write_neuralynx_nts.m 945 2010-04-21 17:41:20Z roboos $ + +if ~isa(nts.TimeStamp, 'uint64') + error('timestamps should be uint64'); +end + +fid = fopen(filename, 'wb', 'ieee-le'); + +% construct the header +buf = []; +buf = [buf sprintf('######## Neuralynx Data File Header\r\n')]; +buf = [buf sprintf('## File Name: %s\r\n', filename)]; +buf = [buf sprintf('## Time Opened: (m/d/y): %s At Time: %s\r\n', datestr(clock, 'mm/dd/yy'), datestr(clock, 'HH:MM:SS'))]; +f = fieldnames(nts.hdr); +for i=1:length(f) + v = getfield(nts.hdr, f{i}); + switch class(v) + case 'char' + buf = [buf sprintf('-%s\t%s\r\n', f{i}, v)]; + case 'double' + buf = [buf sprintf('-%s\t%g\r\n', f{i}, v)]; + otherwise + error('unknown class in writing header'); + end +end + +% pad the rest of the header with zeros and write it to file +buf((end+1):16384) = 0; +fwrite(fid, buf); + +% The format of a clustered electrode record is +% int64 TimeStamp + +fwrite(fid, nts.TimeStamp, 'uint64'); + +% close the file +fclose(fid); + + + diff --git a/external/fieldtrip/fileio/private/write_plexon_nex.m b/external/fieldtrip/fileio/private/write_plexon_nex.m new file mode 100644 index 0000000..09456aa --- /dev/null +++ b/external/fieldtrip/fileio/private/write_plexon_nex.m @@ -0,0 +1,215 @@ +function write_plexon_nex(filename, nex) + +% WRITE_PLEXON_NEX writes a Plexon *.nex file, which is a file +% containing action-potential (spike) timestamps and waveforms (spike +% channels), event timestamps (event channels), and continuous variable +% data (continuous A/D channels). +% +% Use as +% write_plexon_nex(filename, nex); +% +% The data structure should contain +% nex.hdr.FileHeader.Frequency = TimeStampFreq +% nex.hdr.VarHeader.Type = type, 5 for continuous +% nex.hdr.VarHeader.Name = label, padded to length 64 +% nex.hdr.VarHeader.WFrequency = sampling rate of continuous channel +% nex.var.dat = data +% nex.var.ts = timestamps +% +% See also READ_PLEXON_NEX, READ_PLEXON_PLX, READ_PLEXON_DDT + +% Copyright (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: write_plexon_nex.m 945 2010-04-21 17:41:20Z roboos $ + +% get the optional arguments, these are all required +% FirstTimeStamp = keyval('FirstTimeStamp', varargin); +% TimeStampFreq = keyval('TimeStampFreq', varargin); + +hdr = nex.hdr; + +UVtoMV = 1/1000; + +switch hdr.VarHeader.Type + case 5 + dat = nex.var.dat; % this is in microVolt + buf = zeros(size(dat), 'int16'); + nchans = size(dat,1); + nsamples = size(dat,2); + nwaves = 1; % only one continuous datasegment is supported + if length(hdr.VarHeader)~=nchans + error('incorrect number of channels'); + end + % convert the data from floating point into int16 values + % each channel gets its own optimal calibration factor + for varlop=1:nchans + ADMaxValue = double(intmax('int16')); + ADMaxUV = max(abs(dat(varlop,:))); % this is in microVolt + ADMaxMV = ADMaxUV/1000; % this is in miliVolt + if isa(dat, 'int16') + % do not rescale data that is already 16 bit + MVtoAD = 1; + elseif ADMaxMV==0 + % do not rescale the data if the data is zero + MVtoAD = 1; + elseif ADMaxMV>0 + % rescale the data so that it fits into the 16 bits with as little loss as possible + MVtoAD = ADMaxValue / ADMaxMV; + end + buf(varlop,:) = int16(double(dat) * UVtoMV * MVtoAD); + % remember the calibration value, it should be stored in the variable header + ADtoMV(varlop) = 1/MVtoAD; + end + dat = buf; + clear buf; + + case 3 + dat = nex.var.dat; % this is in microVolt + nchans = 1; % only one channel is supported + nsamples = size(dat,1); + nwaves = size(dat,2); + if length(hdr.VarHeader)~=nchans + error('incorrect number of channels'); + end + % convert the data from floating point into int16 values + ADMaxValue = double(intmax('int16')); + ADMaxUV = max(abs(dat(:))); % this is in microVolt + ADMaxMV = ADMaxUV/1000; % this is in miliVolt + if isa(dat, 'int16') + % do not rescale data that is already 16 bit + MVtoAD = 1; + elseif ADMaxMV==0 + % do not rescale the data if the data is zero + MVtoAD = 1; + elseif ADMaxMV>0 + % rescale the data so that it fits into the 16 bits with as little loss as possible + MVtoAD = ADMaxValue / ADMaxMV; + end + dat = int16(double(dat) * UVtoMV * MVtoAD); + % remember the calibration value, it should be stored in the variable header + ADtoMV = 1/MVtoAD; + + otherwise + error('unsupported data type') +end % switch type + +% determine the first and last timestamp +ts = nex.var.ts; +ts_beg = min(ts); +ts_end = 0; % FIXME + +fid = fopen(filename, 'wb', 'ieee-le'); + +% write the file header +write_NexFileHeader; + +% write the variable headers +for varlop=1:nchans + write_NexVarHeader; +end + +% write the variable data +for varlop=1:nchans + write_NexVarData; +end + +fclose(fid); +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% nested function for writing the details +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + function write_NexFileHeader + % prepare the two char buffers + buf1 = padstr('$Id: write_plexon_nex.m 945 2010-04-21 17:41:20Z roboos $', 256); + buf2 = char(zeros(1, 256)); + % write the stuff to the file + fwrite(fid, 'NEX1' , 'char'); % NexFileHeader = string NEX1 + fwrite(fid, 100 , 'int32'); % Version = version + fwrite(fid, buf1 , 'char'); % Comment = comment, 256 bytes + fwrite(fid, hdr.FileHeader.Frequency, 'double'); % Frequency = timestamped freq. - tics per second + fwrite(fid, ts_beg, 'int32'); % Beg = usually 0, minimum of all the timestamps in the file + fwrite(fid, ts_end, 'int32'); % End = maximum timestamp + 1 + fwrite(fid, nchans, 'int32'); % NumVars = number of variables in the first batch + fwrite(fid, 0 , 'int32'); % NextFileHeader = position of the next file header in the file, not implemented yet + fwrite(fid, buf2 , 'char'); % Padding = future expansion + end % of the nested function + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% nested function for writing the details +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + function write_NexVarHeader + filheadersize = 544; + varheadersize = 208; + offset = filheadersize + nchans*varheadersize + (varlop-1)*nsamples; + calib = ADtoMV(varlop); + % prepare the two char buffers + buf1 = padstr(hdr.VarHeader(varlop).Name, 64); + buf2 = char(zeros(1, 68)); + % write the continuous variable to the file + fwrite(fid, hdr.VarHeader.Type, 'int32'); % Type = 0 - neuron, 1 event, 2- interval, 3 - waveform, 4 - pop. vector, 5 - continuously recorded + fwrite(fid, 100, 'int32'); % Version = 100 + fwrite(fid, buf1, 'char'); % Name = variable name, 1x64 char + fwrite(fid, offset, 'int32'); % DataOffset = where the data array for this variable is located in the file + fwrite(fid, nwaves, 'int32'); % Count = number of events, intervals, waveforms or weights + fwrite(fid, 0, 'int32'); % WireNumber = neuron only, not used now + fwrite(fid, 0, 'int32'); % UnitNumber = neuron only, not used now + fwrite(fid, 0, 'int32'); % Gain = neuron only, not used now + fwrite(fid, 0, 'int32'); % Filter = neuron only, not used now + fwrite(fid, 0, 'double'); % XPos = neuron only, electrode position in (0,100) range, used in 3D + fwrite(fid, 0, 'double'); % YPos = neuron only, electrode position in (0,100) range, used in 3D + fwrite(fid, hdr.VarHeader.WFrequency, 'double'); % WFrequency = waveform and continuous vars only, w/f sampling frequency + fwrite(fid, calib, 'double'); % ADtoMV = waveform continuous vars only, coeff. to convert from A/D values to Millivolts + fwrite(fid, nsamples, 'int32'); % NPointsWave = waveform only, number of points in each wave + fwrite(fid, 0, 'int32'); % NMarkers = how many values are associated with each marker + fwrite(fid, 0, 'int32'); % MarkerLength = how many characters are in each marker value + fwrite(fid, buf2, 'char'); % Padding, 1x68 char + end % of the nested function + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% nested function for writing the details +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + function write_NexVarData + switch hdr.VarHeader.Type + case 5 + % this code only supports one continuous segment + index = 0; + fwrite(fid, ts , 'int32'); % timestamps, one for each continuous segment + fwrite(fid, index , 'int32'); % where to cut the segments, zero offset + fwrite(fid, dat(varlop,:) , 'int16'); % data + case 3 + fwrite(fid, ts , 'int32'); % timestamps, one for each spike + fwrite(fid, dat , 'int16'); % waveforms, one for each spike + otherwise + error('unsupported data type'); + end % switch + end % of the nested function + +end % of the primary function + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% subfunction for zero padding a char array to fixed length +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function str = padstr(str, num); +if length(str)>num + str = str(1:num); +else + str((end+1):num) = 0; +end +end % of the padstr subfunction diff --git a/external/fieldtrip/fileio/private/write_serial_event.m b/external/fieldtrip/fileio/private/write_serial_event.m new file mode 100644 index 0000000..b808b69 --- /dev/null +++ b/external/fieldtrip/fileio/private/write_serial_event.m @@ -0,0 +1,109 @@ +function write_serial_event(filename, event) + +% WRITE_SERIAL_EVENT +% +% changed A.Hadjipapas 2010 +% +% write to phyiscal serial port +% serial port on windows or linux platform + +% Copyright (C) 2007, Christian Hesse +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: write_serial_event.m 945 2010-04-21 17:41:20Z roboos $ + +[port, opt] = filetype_check_uri(filename); +temp=instrfind; %% find isntruments including serial ports + +%% check if a serial port with the specified name is already available +if isempty(temp)||~any(strcmpi(temp.Port,port)) + %% if not make one + s=serial(port); + %% if user has specified Baudrate, apply that, %% FIX THIS: currently no + %% automatic implementation for more options + if ~isempty(opt) + s.Baudrate =str2double(opt{2}); %% set Baudrate using optional parameters + end + fopen(s); %% open serial port +end + +%% write the contents of the field event.value to the serial port as a string +if isfield(event,'value') && ~isempty(event.value) + msg = event.value; +else + msg = []; +end + +%% write the message to the serial port if it is open +if strcmp(s.Status,'open') + %% if numeric use fwrite otherwise fprintf + if isnumeric(msg) + fwrite(s,msg); + end + + if ischar(msg) + fprintf(s,'%s',msg); + end +else + error('could not write event to serial port'); +end + +%% this is the old code +% +% % serial port on windows or linux platform +% s = []; +% [port, opt] = filetype_check_uri(filename); +% +% % determine whether any serial port objects are already associated with the target serial port +% temp = instrfind; +% if isa(temp,'instrument') +% % find all serial ports +% i1 = strcmp('serial',{temp(:).Type}); +% if any(i1) +% % find all serial ports whose name matches that of the specified port +% i2 = strmatch(lower(['Serial-',port]),lower({temp(find(i1)==1).Name})); +% % set s to the (first) matching port if present (and open if necessary) +% if ~isempty(i2) +% s = temp(i2(1)); +% if ~strcmp(s.Status,'open'), fopen(s); end; +% end +% end +% end +% +% % create, configure a serial port object if necessary and open the port +% if ~isa(s,'serial') +% s = serial(port); +% if ~isempty(opt) && iscell(opt), s = set(s,opt); end; +% fopen(s); +% end +% +% % % convert the event structure into an appropriate message +% % if isfield(event,'type') && strcmp(event.type,'ctrlchar') +% % % use only a single control character +% % msg = char(event.value(1)); +% % else +% % % convert the entire event structure into a message +% % msg = struct2msg(event); +% % end +% +% % write the message to the serial port +% if isa(s,'serial') && strcmp(s.Status,'open') +% fwrite(s,char(event.value)); +% else +% error('could not write event to serial port'); +% end diff --git a/external/fieldtrip/fileio/private/write_stl.m b/external/fieldtrip/fileio/private/write_stl.m new file mode 100644 index 0000000..342b3c7 --- /dev/null +++ b/external/fieldtrip/fileio/private/write_stl.m @@ -0,0 +1,60 @@ +function write_stl(filename, pnt, tri, nrm); + +% WRITE_STL writes a triangulation to an ascii *.stl file, which is a file +% format native to the stereolithography CAD software created by 3D Systems. +% +% Use as +% write_stl(filename, pnt, tri, nrm) +% where nrm refers to the triangle normals. +% +% See also READ_STL + +% Copyright (C) 2006, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: write_stl.m 945 2010-04-21 17:41:20Z roboos $ + +% solid testsphere +% facet normal -0.13 -0.13 -0.98 +% outer loop +% vertex 1.50000 1.50000 0.00000 +% vertex 1.50000 1.11177 0.05111 +% vertex 1.11177 1.50000 0.05111 +% endloop +% endfacet +% ... + +fid = fopen(filename, 'wb'); + +ntri = size(tri,1); +fprintf(fid, 'solid unknown\n'); + +for i=1:ntri + fprintf(fid, ' facet normal %f %f %f\n', nrm(i,:)); + fprintf(fid, ' outer loop\n'); + fprintf(fid, ' vertex %f %f %f\n', pnt(tri(i,1),1), pnt(tri(i,1),2), pnt(tri(i,1),3)); + fprintf(fid, ' vertex %f %f %f\n', pnt(tri(i,2),1), pnt(tri(i,2),2), pnt(tri(i,2),3)); + fprintf(fid, ' vertex %f %f %f\n', pnt(tri(i,3),1), pnt(tri(i,3),2), pnt(tri(i,3),3)); + fprintf(fid, ' endloop\n'); + fprintf(fid, ' endfacet\n'); +end + +fprintf(fid, 'endsolid\n'); + +fclose(fid); + diff --git a/external/fieldtrip/fileio/private/write_vtk.m b/external/fieldtrip/fileio/private/write_vtk.m new file mode 100644 index 0000000..9325d57 --- /dev/null +++ b/external/fieldtrip/fileio/private/write_vtk.m @@ -0,0 +1,48 @@ +function write_tri(fn, pnt, dhk) + +% WRITE_VTK writes a triangulation to a VTK (Visualisation ToolKit) format file +% +% write_vtk(filename, pnt, dhk) +% +% See also READ_VTK, READ_TRI, WRITEE_TRI + +% Copyright (C) 2002, Robert Oostenveld +% +% $Log: write_vtk.m,v $ +% Revision 1.1 2009/01/14 09:33:10 roboos +% moved even more files from fileio to fileio/private, see previous log entry +% +% Revision 1.2 2003/03/11 15:24:52 roberto +% updated help and copyrights +% + +fid = fopen(fn, 'wt'); +if fid~=-1 + + npnt = size(pnt,1); + ndhk = size(dhk,1); + + % write the header + fprintf(fid, '# vtk DataFile Version 2.0\n'); + fprintf(fid, 'vtk output\n'); + fprintf(fid, 'ASCII\n'); + fprintf(fid, 'DATASET POLYDATA\n'); + fprintf(fid, '\n'); + + % write the vertex points + fprintf(fid, 'POINTS %d float\n', npnt); + fprintf(fid, '%f\t%f\t%f\n', pnt'); + fprintf(fid, '\n'); + + % write the triangles + fprintf(fid, 'POLYGONS %d %d\n', ndhk, 4*ndhk); + fprintf(fid, '3\t%d\t%d\t%d\n', (dhk-1)'); + fprintf(fid, '\n'); + + fclose(fid); + +else + error('unable to open file'); +end + + diff --git a/external/fieldtrip/fileio/private/yokogawa2grad.m b/external/fieldtrip/fileio/private/yokogawa2grad.m new file mode 100644 index 0000000..3431688 --- /dev/null +++ b/external/fieldtrip/fileio/private/yokogawa2grad.m @@ -0,0 +1,176 @@ +function grad = yokogawa2grad(hdr) + +% YOKOGAWA2GRAD converts the position and weights of all coils that +% compromise a gradiometer system into a structure that can be used +% by FieldTrip. +% +% See also READ_HEADER, CTF2GRAD, BTI2GRAD, FIF2GRAD + +% Copyright (C) 2005-2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: yokogawa2grad.m 1246 2010-06-17 09:35:04Z tilsan $ + +if ~hasyokogawa('16bitBeta6') + error('cannot determine whether Yokogawa toolbox is present'); +end + +if isfield(hdr, 'label') + label = hdr.label; % keep for later use +end + +if isfield(hdr, 'orig') + hdr = hdr.orig; % use the original header, not the FieldTrip header +end + +% The "channel_info" contains +% 1 channel number, zero offset +% 2 channel type, type of gradiometer +% 3 position x (in m) +% 4 position y (in m) +% 5 position z (in m) +% 6 orientation of first coil (theta in deg) +% 7 orientation of first coil (phi in deg) +% 8 orientation from the 1st to 2nd coil for gradiometer (theta in deg) +% 9 orientation from the 1st to 2nd coil for gradiometer (phi in deg) +% 10 coil size (in m) +% 11 baseline (in m) + +handles = definehandles; +isgrad = (hdr.channel_info(:,2)==handles.AxialGradioMeter | ... + hdr.channel_info(:,2)==handles.PlannerGradioMeter | hdr.channel_info(:,2)==handles.MagnetoMeter | ... + hdr.channel_info(:,2)==handles.RefferenceAxialGradioMeter | hdr.channel_info(:,2)==handles.RefferencePlannerGradioMeter | ... + hdr.channel_info(:,2)==handles.RefferenceMagnetoMeter); +isgrad_handles = hdr.channel_info(isgrad,2); +ismag = (isgrad_handles(:)==handles.MagnetoMeter | isgrad_handles(:)==handles.RefferenceMagnetoMeter); +grad.pnt = hdr.channel_info(isgrad,3:5)*100; % cm + +% Get orientation of the 1st coil +ori_1st = hdr.channel_info(find(isgrad),[6 7]); +% polar to x,y,z coordinates +ori_1st = ... + [sin(ori_1st(:,1)/180*pi).*cos(ori_1st(:,2)/180*pi) ... + sin(ori_1st(:,1)/180*pi).*sin(ori_1st(:,2)/180*pi) ... + cos(ori_1st(:,1)/180*pi)]; +grad.ori = ori_1st; + +% Get orientation from the 1st to 2nd coil for gradiometer +ori_1st_to_2nd = hdr.channel_info(find(isgrad),[8 9]); +% polar to x,y,z coordinates +ori_1st_to_2nd = ... + [sin(ori_1st_to_2nd(:,1)/180*pi).*cos(ori_1st_to_2nd(:,2)/180*pi) ... + sin(ori_1st_to_2nd(:,1)/180*pi).*sin(ori_1st_to_2nd(:,2)/180*pi) ... + cos(ori_1st_to_2nd(:,1)/180*pi)]; +% Get baseline +baseline = hdr.channel_info(isgrad,size(hdr.channel_info,2)); + +% Define the location and orientation of 2nd coil +info = hdr.channel_info(isgrad,2); +for i=1:sum(isgrad) + if (info(i) == handles.AxialGradioMeter || info(i) == handles.RefferenceAxialGradioMeter ) + grad.pnt(i+sum(isgrad),:) = [grad.pnt(i,:)+ori_1st(i,:)*baseline(i)*100]; + grad.ori(i+sum(isgrad),:) = -ori_1st(i,:); + elseif (info(i) == handles.PlannerGradioMeter || info(i) == handles.RefferencePlannerGradioMeter) + grad.pnt(i+sum(isgrad),:) = [grad.pnt(i,:)+ori_1st_to_2nd(i,:)*baseline(i)*100]; + grad.ori(i+sum(isgrad),:) = -ori_1st(i,:); + else + grad.pnt(i+sum(isgrad),:) = [0 0 0]; + grad.ori(i+sum(isgrad),:) = [0 0 0]; + end +end + +% Define the pair of 1st and 2nd coils for each gradiometer +grad.tra = repmat(diag(ones(1,size(grad.pnt,1)/2),0),1,2); + +% for mangetometers change tra as there is no second coil +if any(ismag) + sz_pnt = size(grad.pnt,1)/2; + % create logical variable + not_2nd_coil = ([diag(zeros(sz_pnt),0)' ismag']~=0); + grad.tra(ismag,not_2nd_coil) = 0; +end + +% Make the matrix sparse to speed up the multiplication in the forward +% computation with the coil-leadfield matrix to get the channel leadfield +grad.tra = sparse(grad.tra); + +% the gradiometer labels should be consistent with the channel labels in +% read_yokogawa_header, the predefined list of channel names in ft_senslabel +% and with ft_channelselection +% ONLY consistent with read_yokogawa_header as NO FIXED relation between +% channel index and type of channel exists for Yokogawa systems. Therefore +% all have individual label sequences: No useful support in ft_senslabel possible +if ~isempty(label) + grad.label = label(isgrad); +else + % this is only backup, if something goes wrong above. + label = cell(size(isgrad)); + for i=1:length(label) + label{i} = sprintf('AG%03d', i); + end + grad.label = label(isgrad); +end +grad.unit = 'cm'; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% this defines some usefull constants +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function handles = definehandles; +handles.output = []; +handles.sqd_load_flag = false; +handles.mri_load_flag = false; +handles.NullChannel = 0; +handles.MagnetoMeter = 1; +handles.AxialGradioMeter = 2; +handles.PlannerGradioMeter = 3; +handles.RefferenceChannelMark = hex2dec('0100'); +handles.RefferenceMagnetoMeter = bitor( handles.RefferenceChannelMark, handles.MagnetoMeter ); +handles.RefferenceAxialGradioMeter = bitor( handles.RefferenceChannelMark, handles.AxialGradioMeter ); +handles.RefferencePlannerGradioMeter = bitor( handles.RefferenceChannelMark, handles.PlannerGradioMeter ); +handles.TriggerChannel = -1; +handles.EegChannel = -2; +handles.EcgChannel = -3; +handles.EtcChannel = -4; +handles.NonMegChannelNameLength = 32; +handles.DefaultMagnetometerSize = (4.0/1000.0); % ????4.0mm???????` +handles.DefaultAxialGradioMeterSize = (15.5/1000.0); % ???a15.5mm???~?? +handles.DefaultPlannerGradioMeterSize = (12.0/1000.0); % ????12.0mm???????` +handles.AcqTypeContinuousRaw = 1; +handles.AcqTypeEvokedAve = 2; +handles.AcqTypeEvokedRaw = 3; +handles.sqd = []; +handles.sqd.selected_start = []; +handles.sqd.selected_end = []; +handles.sqd.axialgradiometer_ch_no = []; +handles.sqd.axialgradiometer_ch_info = []; +handles.sqd.axialgradiometer_data = []; +handles.sqd.plannergradiometer_ch_no = []; +handles.sqd.plannergradiometer_ch_info = []; +handles.sqd.plannergradiometer_data = []; +handles.sqd.nullchannel_ch_no = []; +handles.sqd.nullchannel_data = []; +handles.sqd.selected_time = []; +handles.sqd.sample_rate = []; +handles.sqd.sample_count = []; +handles.sqd.pretrigger_length = []; +handles.sqd.matching_info = []; +handles.sqd.source_info = []; +handles.sqd.mri_info = []; +handles.mri = []; + diff --git a/external/fieldtrip/fileio/private/yokogawa2vol.m b/external/fieldtrip/fileio/private/yokogawa2vol.m new file mode 100644 index 0000000..2356321 --- /dev/null +++ b/external/fieldtrip/fileio/private/yokogawa2vol.m @@ -0,0 +1,36 @@ +function [vol] = yokogawa2vol(hdr); + +% YOKOGAWA2VOL converts a spherical volume conductor model that can +% be present in the header of a datafile into a structure that can +% be used by FieldTrip. + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: yokogawa2vol.m 1234 2010-06-15 14:09:49Z roboos $ + +% hdr = read_yokogawa_header(filename); +hdr = hdr.orig; % use the original Yokogawa header, not the FieldTrip header + +if isfield(hdr.mri_info, 'model_name') && strcmp(hdr.mri_info.model_name, 'SphericalModel') + % single sphere volume conduction model + vol.r = hdr.mri_info.r; + vol.o = [hdr.mri_info.cx hdr.mri_info.cy hdr.mri_info.cz]; +else + error('unsupported volume conductor model'); +end diff --git a/external/forwinv/COPYING b/external/fieldtrip/forward/COPYING similarity index 100% rename from external/forwinv/COPYING rename to external/fieldtrip/forward/COPYING diff --git a/external/fieldtrip/forward/README b/external/fieldtrip/forward/README new file mode 100644 index 0000000..dd97c7f --- /dev/null +++ b/external/fieldtrip/forward/README @@ -0,0 +1,16 @@ +This is the FieldTrip FORWARD module. It contains functions for forward +modeling of the EEG and MEG field distributions with a choise of volume +conduction models, including spherical and realistic models. + +For more information please visit http://www.ru.nl/neuroimaging/fieldtrip + +The FieldTrip software is free but copyrighted software, distributed +under the terms of the GNU General Public Licence as published by +the Free Software Foundation (either version 2, or at your option +any later version). See the file COPYING for more details. + +Copyright (C) 2008-2009, Donders Institute for Brain, Cognition and Behaviour, The Netherlands (DCCN, DCC, DCN) +Copyright (C) 2003-2008, F.C. Donders Centre for Cognitive Neuroimaging, Nijmegen, The Netherlands (FCDC) +Copyright (C) 2003-2005, Center for Sensory-Motor Interaction, Aalborg University, Denmark (SMI) +Copyright (C) 1999-2003, Department of Medical Physics, Radboud University Nijmegen, The Netherlands (MBFYS) + diff --git a/external/fieldtrip/forward/ft_apply_montage.m b/external/fieldtrip/forward/ft_apply_montage.m new file mode 100644 index 0000000..9a895bf --- /dev/null +++ b/external/fieldtrip/forward/ft_apply_montage.m @@ -0,0 +1,226 @@ +function [sens] = ft_apply_montage(sens, montage, varargin) + +% FT_APPLY_MONTAGE changes the montage of an electrode or gradiometer array. A +% montage can be used for EEG rereferencing, MEG synthetic gradients, MEG +% planar gradients or unmixing using ICA. This function applies the montage +% to the sensor array. The sensor array can subsequently be used for +% forward computation and source reconstruction of the data. +% +% Use as +% [sens] = ft_apply_montage(sens, montage, ...) +% [data] = ft_apply_montage(data, montage, ...) +% [montage] = ft_apply_montage(montage1, montage2, ...) +% where the input is a FieldTrip sensor definition as obtained from FT_READ_SENS +% or a FieldTrip raw data structure as obtained from FT_PREPROCESSING. +% +% A montage is specified as a structure with the fields +% montage.tra = MxN matrix +% montage.labelnew = Mx1 cell-array +% montage.labelorg = Nx1 cell-array +% +% Additional options should be specified in key-value pairs and can be +% 'keepunused' string, 'yes' or 'no' (default = 'no') +% 'inverse' string, 'yes' or 'no' (default = 'no') +% +% If the first input is a montage, then the second input montage will be +% applied to the first. In effect the resulting montage will first do +% montage1, then montage2. +% +% See also FT_READ_SENS, FT_TRANSFORM_SENS + +% Copyright (C) 2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_apply_montage.m 1139 2010-05-26 12:55:57Z roboos $ + +% get optional input arguments +keepunused = keyval('keepunused', varargin{:}); if isempty(keepunused), keepunused = 'no'; end +inverse = keyval('inverse', varargin{:}); if isempty(inverse), inverse = 'no'; end + +% check the consistency of the input sensor array or data +if isfield(sens, 'labelorg') && isfield(sens, 'labelnew') + % the input data structure is also a montage, i.e. apply the montages sequentially + sens.label = sens.labelnew; +end + +% check the consistency of the montage +if size(montage.tra,1)~=length(montage.labelnew) + error('the number of channels in the montage is inconsistent'); +elseif size(montage.tra,2)~=length(montage.labelorg) + error('the number of channels in the montage is inconsistent'); +end + +if strcmp(inverse, 'yes') + % apply the inverse montage, i.e. undo a previously applied montage + tmp.labelnew = montage.labelorg; % swap around + tmp.labelorg = montage.labelnew; % swap around + tmp.tra = full(montage.tra); + if rank(tmp.tra) < length(tmp.tra) + warning('the linear projection for the montage is not full-rank, the resulting data will have reduced dimensionality'); + tmp.tra = pinv(tmp.tra); + else + tmp.tra = inv(tmp.tra); + end + montage = tmp; +end + +% use default transfer from sensors to channels if not specified +if isfield(sens, 'pnt') && ~isfield(sens, 'tra') + nchan = size(sens.pnt,1); + sens.tra = sparse(eye(nchan)); +end + +% select and keep the columns that are non-empty, i.e. remove the empty columns +selcol = find(~all(montage.tra==0, 1)); +montage.tra = montage.tra(:,selcol); +montage.labelorg = montage.labelorg(selcol); +clear selcol + +% select and remove the columns corresponding to channels that are not present in the original data +remove = setdiff(montage.labelorg, intersect(montage.labelorg, sens.label)); +selcol = match_str(montage.labelorg, remove); +% we cannot just remove the colums, all rows that depend on it should also be removed +selrow = false(length(montage.labelnew),1); +for i=1:length(selcol) + selrow = selrow & (montage.tra(:,selcol(i))~=0); +end +% convert from indices to logical vector +selcol = indx2logical(selcol, length(montage.labelorg)); +% remove rows and columns +montage.labelorg = montage.labelorg(~selcol); +montage.labelnew = montage.labelnew(~selrow); +montage.tra = montage.tra(~selrow, ~selcol); +clear remove selcol selrow i +% add columns for the channels that are present in the data but not involved in the montage, and stick to the original order in the data +[add, ix] = setdiff(sens.label, montage.labelorg); +add = sens.label(sort(ix)); +m = size(montage.tra,1); +n = size(montage.tra,2); +k = length(add); +if strcmp(keepunused, 'yes') + % add the channels that are not rereferenced to the input and output + montage.tra((m+(1:k)),(n+(1:k))) = eye(k); + montage.labelorg = cat(1, montage.labelorg(:), add(:)); + montage.labelnew = cat(1, montage.labelnew(:), add(:)); +else + % add the channels that are not rereferenced to the input montage only + montage.tra(:,(n+(1:k))) = zeros(m,k); + montage.labelorg = cat(1, montage.labelorg(:), add(:)); +end +clear add m n k + +% determine whether all channels are unique +m = size(montage.tra,1); +n = size(montage.tra,2); +if length(unique(montage.labelnew))~=m + error('not all output channels of the montage are unique'); +end +if length(unique(montage.labelorg))~=n + error('not all input channels of the montage are unique'); +end + +% determine whether all channels that have to be rereferenced are available +if length(intersect(sens.label, montage.labelorg))~=length(montage.labelorg) + error('not all channels that are required in the montage are available in the data'); +end + +% reorder the columns of the montage matrix +[selsens, selmont] = match_str(sens.label, montage.labelorg); +montage.tra = sparse(montage.tra(:,selmont)); +montage.labelorg = montage.labelorg(selmont); + +if isfield(sens, 'labelorg') && isfield(sens, 'labelnew') + % apply the montage on top of the other montage + sens = rmfield(sens, 'label'); + sens.tra = montage.tra * sens.tra; + sens.labelnew = montage.labelnew; + +elseif isfield(sens, 'tra') + % apply the montage to the sensor array + sens.tra = montage.tra * sens.tra; + sens.label = montage.labelnew; + +elseif isfield(sens, 'trial') + % apply the montage to the raw data that was preprocessed using fieldtrip + data = sens; + clear sens + + Ntrials = numel(data.trial); + for i=1:Ntrials + fprintf('processing trial %d from %d\n', i, Ntrials); + if isa(data.trial{i}, 'single') + % sparse matrices and single precision do not match + data.trial{i} = full(montage.tra) * data.trial{i}; + else + data.trial{i} = montage.tra * data.trial{i}; + end + end + data.label = montage.labelnew; + + % rename the output variable + sens = data; + clear data + +elseif isfield(sens, 'fourierspctrm') + % apply the montage to the spectrally decomposed data + freq = sens; + clear sens + + if strcmp(freq.dimord, 'rpttap_chan_freq') + siz = size(freq.fourierspctrm); + nrpt = siz(1); + nchan = siz(2); + nfreq = siz(3); + output = zeros(nrpt, size(montage.tra,1), nfreq); + for foilop=1:nfreq + output(:,:,foilop) = freq.fourierspctrm(:,:,foilop) * montage.tra'; + end + elseif strcmp(freq.dimord, 'rpttap_chan_freq_time') + siz = size(freq.fourierspctrm); + nrpt = siz(1); + nchan = siz(2); + nfreq = siz(3); + ntime = siz(4); + output = zeros(nrpt, size(montage.tra,1), nfreq, ntime); + for foilop=1:nfreq + for toilop = 1:ntime + output(:,:,foilop,toilop) = freq.fourierspctrm(:,:,foilop,toilop) * montage.tra'; + end + end + else + error('unsupported dimord in frequency data (%s)', freq.dimord); + end + + % replace the Fourier spectrum + freq.fourierspctrm = output; + freq.label = montage.labelnew; + + % rename the output variable + sens = freq; + clear freq + +else + error('unrecognized input'); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% HELPER FUNCTION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function y = indx2logical(x, n) +y = false(1,n); +y(x) = true; diff --git a/external/fieldtrip/forward/ft_compute_leadfield.m b/external/fieldtrip/forward/ft_compute_leadfield.m new file mode 100644 index 0000000..754df9a --- /dev/null +++ b/external/fieldtrip/forward/ft_compute_leadfield.m @@ -0,0 +1,497 @@ +function [lf] = ft_compute_leadfield(pos, sens, vol, varargin) + +% FT_COMPUTE_LEADFIELD computes a forward solution for a dipole in a a volume +% conductor model. The forward solution is expressed as the leadfield +% matrix (Nchan*3), where each column corresponds with the potential or field +% distributions on all sensors for one of the x,y,z-orientations of the +% dipole. +% +% Use as +% [lf] = ft_compute_leadfield(pos, sens, vol, ...) +% with input arguments +% pos position dipole (1x3 or Nx3) +% sens structure with gradiometer or electrode definition +% vol structure with volume conductor definition +% +% The vol structure represents a volume conductor model, its contents +% depend on the type of model. The sens structure represents a sensor +% arary, i.e. EEG electrodes or MEG gradiometers. +% +% It is possible to compute a simultaneous forward solution for EEG and MEG +% by specifying sens and grad as two cell-arrays, e.g. +% sens = {senseeg, sensmeg} +% vol = {voleeg, volmeg} +% This results in the computation of the leadfield of the first element of +% sens and vol, followed by the second, etc. The leadfields of the +% different imaging modalities are concatenated. +% +% Additional input arguments can be specified as key-value pairs, supported +% optional arguments are +% 'reducerank' = 'no' or number +% 'normalize' = 'no', 'yes' or 'column' +% 'normalizeparam' = parameter for depth normalization (default = 0.5) +% 'weight' = number or 1xN vector, weight for each dipole position (default = 1) +% +% The leadfield weight may be used to specify a (normalized) +% corresponding surface area for each dipole, e.g. when the dipoles +% represent a folded cortical surface with varying triangle size. +% +% Depending on the specific input arguments for the sensor and volume, this +% function will select the appropriate low-level EEG or MEG forward model. +% The leadfield matrix for EEG will have an average reference over all the +% electrodes. +% +% The supported forward solutions for MEG are +% single sphere (Cuffin and Cohen, 1977) +% multiple spheres with one sphere per channel (Huang et al, 1999) +% realistic single shell using superposition of basis functions (Nolte, 2003) +% using leadfield interpolation on precomputed grid +% Boundary Element Method (BEM) using Neuromag meg_calc toolbox +% +% The supported forward solutions for EEG are +% single sphere +% multiple concentric spheres (max. 4) +% using leadfield interpolation on precomputed grid +% Boundary Element Method (BEM) using ASA to precompute the sytem matrix +% Boundary Element Method (BEM) using Neuromag meg_calc toolbox +% +% References to implemented methods: +% Cuffin BN, Cohen D. +% Magnetic fields of a dipole in special volume conductor shapes +% IEEE Trans Biomed Eng. 1977 Jul;24(4):372-81. +% +% Nolte G. +% The magnetic lead field theorem in the quasi-static approximation and its use for magnetoencephalography forward calculation in realistic volume conductors +% Phys Med Biol. 2003 Nov 21;48(22):3637-52 +% +% Huang MX, Mosher JC, Leahy RM. +% A sensor-weighted overlapping-sphere head model and exhaustive head model comparison for MEG +% Phys Med Biol. 1999 Feb;44(2):423-40 + +% Copyright (C) 2004-2010, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_compute_leadfield.m 957 2010-04-23 08:04:06Z roboos $ + +persistent warning_issued; + +if iscell(sens) && iscell(vol) && numel(sens)==numel(vol) + % this represents combined EEG and MEG sensors, where each modality has its own volume conduction model + lf = cell(1,numel(sens)); + for i=1:length(sens) + lf{i} = ft_compute_leadfield(pos, sens{i}, vol{i}, varargin{:}); + end + lf = cat(1, lf{:}); + return; +end + +if ~isstruct(sens) && size(sens,2)==3 + % definition of electrode positions only, restructure it + sens = struct('pnt', sens); +end + +% determine whether it is EEG or MEG +iseeg = ft_senstype(sens, 'eeg'); +ismeg = ft_senstype(sens, 'meg'); + +% get the optional input arguments +reducerank = keyval('reducerank', varargin); if isempty(reducerank), reducerank = 'no'; end +normalize = keyval('normalize' , varargin); if isempty(normalize ), normalize = 'no'; end +normalizeparam = keyval('normalizeparam', varargin); if isempty(normalizeparam ), normalizeparam = 0.5; end +weight = keyval('weight', varargin); + +% multiple dipoles can be represented either as a 1x(N*3) vector or as a +% as a Nx3 matrix, i.e. [x1 y1 z1 x2 y2 z2] or [x1 y1 z1; x2 y2 z2] +Ndipoles = numel(pos)/3; +if all(size(pos)==[1 3*Ndipoles]) + pos = reshape(pos, 3, Ndipoles)'; +end + +if isfield(vol, 'unit') && isfield(sens, 'unit') && ~strcmp(vol.unit, sens.unit) + error('inconsistency in the units of the volume conductor and the sensor array'); +end + +if ismeg && iseeg + % this is something that could be implemented relatively easily + error('simultaneous EEG and MEG not supported'); + +elseif ~ismeg && ~iseeg + error('the input does not look like EEG, nor like MEG'); + +elseif ismeg + switch ft_voltype(vol) + + case 'singlesphere' + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % MEG single-sphere volume conductor model + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + pnt = sens.pnt; % position of each coil + ori = sens.ori; % orientation of each coil + + if isfield(vol, 'o') + % shift dipole and magnetometers to origin of sphere + pos = pos - repmat(vol.o, Ndipoles, 1); + pnt = pnt - repmat(vol.o, size(pnt,1), 1); + end + + if Ndipoles>1 + % loop over multiple dipoles + lf = zeros(size(pnt,1),3*Ndipoles); + for i=1:Ndipoles + lf(:,(3*i-2):(3*i)) = meg_leadfield1(pos(i,:), pnt, ori); + end + else + % only single dipole + lf = meg_leadfield1(pos, pnt, ori); + end + + if isfield(sens, 'tra') + % this appears to be the modern complex gradiometer definition + % construct the channels from a linear combination of all magnetometers + lf = sens.tra * lf; + end + + case 'multisphere' + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % MEG multi-sphere volume conductor model + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + ncoils = length(sens.pnt); + + if size(vol.r, 1)~=ncoils + error('number of spheres is not equal to the number of coils') + end + + if size(vol.o, 1)~=ncoils + error('number of spheres is not equal to the number of coils'); + end + + lf = zeros(ncoils, 3*Ndipoles); + for chan=1:ncoils + for dip=1:Ndipoles + % shift dipole and magnetometer coil to origin of sphere + dippos = pos(dip,:) - vol.o(chan,:); + chnpos = sens.pnt(chan,:) - vol.o(chan,:); + tmp = meg_leadfield1(dippos, chnpos, sens.ori(chan,:)); + lf(chan,(3*dip-2):(3*dip)) = tmp; + end + end + + if isfield(sens, 'tra') + % this appears to be the modern complex gradiometer definition + % construct the channels from a linear combination of all magnetometers + lf = sens.tra * lf; + end + + case 'neuromag' + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % use external Neuromag toolbox for forward computation + % this requires that "megmodel" is initialized, which is done in PREPARE_VOL_SENS + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % compute the forward model for all channels + % tmp1 = ones(1, Ndipoles); + % tmp2 = 0.01*pos'; %convert to cm + % lf = megfield([tmp2 tmp2 tmp2],[[1 0 0]'*tmp1 [0 1 0]'*tmp1 [0 0 1]'*tmp1]); + for dip=1:Ndipoles + R = 0.01*pos(i,:)'; % convert from cm to m + Qx = [1 0 0]; + Qy = [0 1 0]; + Qz = [0 0 1]; + lf(:,(3*(dip-1)+1)) = megfield(R, Qx); + lf(:,(3*(dip-1)+2)) = megfield(R, Qy); + lf(:,(3*(dip-1)+3)) = megfield(R, Qz); + end + % select only those channels from the forward model that are part of the gradiometer definition + lf = lf(vol.chansel,:); + + case 'nolte' + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % use code from Guido Nolte for the forward computation + % this requires that "meg_ini" is initialized, which is done in PREPARE_VOL_SENS + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % the dipole position and orientation should be combined in a single matrix + % furthermore, here I want to compute the leadfield for each of the + % orthogonzl x/y/z directions + dippar = zeros(Ndipoles*3, 6); + for i=1:Ndipoles + dippar((i-1)*3+1,:) = [pos(i,:) 1 0 0]; % single dipole, x-orientation + dippar((i-1)*3+2,:) = [pos(i,:) 0 1 0]; % single dipole, y-orientation + dippar((i-1)*3+3,:) = [pos(i,:) 0 0 1]; % single dipole, z-orientation + end + % compute the leadfield for each individual coil + lf = meg_forward(dippar,vol.forwpar); + if isfield(sens, 'tra') + % compute the leadfield for each gradiometer (linear combination of coils) + lf = sens.tra * lf; + end + + case 'openmeeg' + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % use code from OpenMEEG + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + hastoolbox('openmeeg', 1); + + dsm = openmeeg_dsm(pos,vol); + [h2mm,s2mm]= openmeeg_megm(pos,vol,sens); + + if isfield(vol,'mat') + lf = s2mm+h2mm*(vol.mat*dsm); + else + error('No system matrix is present, BEM head model not calculated yet') + end + if isfield(sens, 'tra') + % compute the leadfield for each gradiometer (linear combination of coils) + lf = sens.tra * lf; + end + + case 'infinite' + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % magnetic dipole instead of electric (current) dipole in an infinite vacuum + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + if isempty(warning_issued) + % give the warning only once + warning('assuming magnetic dipole in an infinite vacuum'); + warning_issued = 1; + end + + pnt = sens.pnt; % position of each coil + ori = sens.ori; % orientation of each coil + + if Ndipoles>1 + % loop over multiple dipoles + lf = zeros(size(pnt,1),3*Ndipoles); + for i=1:Ndipoles + lf(:,(3*i-2):(3*i)) = magnetic_dipole(pos(i,:), pnt, ori); + end + else + % only single dipole + lf = magnetic_dipole(pos, pnt, ori); + end + + if isfield(sens, 'tra') + % construct the channels from a linear combination of all magnetometer coils + lf = sens.tra * lf; + end + + otherwise + error('unsupported volume conductor model for MEG'); + end % switch voltype for MEG + +elseif iseeg + switch ft_voltype(vol) + + case 'multisphere' + % Based on the approximation of the potential due to a single dipole in + % a multishell sphere by three dipoles in a homogeneous sphere, code + % contributed by Punita Christopher + + Nelec = size(sens.pnt,1); + Nspheres = length(vol.r); + + % the center of the spherical volume conduction model does not have + % to be in the origin, therefore shift the spheres, the electrodes + % and the dipole + if isfield(vol, 'o') + center = vol.o; + else + center = [0 0 0]; + end + + % sort the spheres from the smallest to the largest + % furthermore, the radius should be one (?) + [radii, indx] = sort(vol.r/max(vol.r)); + sigma = vol.c(indx); + r = (sens.pnt-repmat(center, Nelec, 1))./max(vol.r); + pos = pos./max(vol.r); + + if Ndipoles>1 + % loop over multiple dipoles + lf = zeros(Nelec,3*Ndipoles); + for i=1:Ndipoles + rq = pos(i,:) - center; + % compute the potential for each dipole ortientation + % it would be much more efficient to change the punita function + q1 = [1 0 0]; lf(:,(3*i-2)) = multisphere(Nspheres, radii, sigma, r, rq, q1); + q1 = [0 1 0]; lf(:,(3*i-1)) = multisphere(Nspheres, radii, sigma, r, rq, q1); + q1 = [0 0 1]; lf(:,(3*i )) = multisphere(Nspheres, radii, sigma, r, rq, q1); + end + else + % only single dipole + lf = zeros(Nelec,3); + rq = pos - center; + % compute the potential for each dipole ortientation + % it would be much more efficient to change the punita function + q1 = [1 0 0] ; lf(:,1) = multisphere(Nspheres, radii, sigma, r, rq, q1); + q1 = [0 1 0] ; lf(:,2) = multisphere(Nspheres, radii, sigma, r, rq, q1); + q1 = [0 0 1] ; lf(:,3) = multisphere(Nspheres, radii, sigma, r, rq, q1); + end + + case {'singlesphere', 'concentric'} + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % EEG spherical volume conductor model + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + % FIXME, this is not consistent between spherical and BEM + % sort the spheres from the smallest to the largest + [vol.r, indx] = sort(vol.r); + vol.c = vol.c(indx); + + Nspheres = length(vol.c); + if length(vol.r)~=Nspheres + error('the number of spheres in the volume conductor model is ambiguous'); + end + + if isfield(vol, 'o') + % shift the origin of the spheres, electrodes and dipole + sens.pnt = sens.pnt - repmat(vol.o, size(sens.pnt,1), 1); + pos = pos - repmat(vol.o, Ndipoles, 1); + end + + if Nspheres==1 + if Ndipoles>1 + % loop over multiple dipoles + lf = zeros(size(sens.pnt,1),3*Ndipoles); + for i=1:Ndipoles + lf(:,(3*i-2):(3*i)) = eeg_leadfield1(pos(i,:), sens.pnt, vol); + end + else + % only single dipole + lf = eeg_leadfield1(pos, sens.pnt, vol); + end + + elseif Nspheres==2 + vol.r = [vol.r(1) vol.r(2) vol.r(2) vol.r(2)]; + vol.c = [vol.c(1) vol.c(2) vol.c(2) vol.c(2)]; + if Ndipoles>1 + % loop over multiple dipoles + lf = zeros(size(sens.pnt,1),3*Ndipoles); + for i=1:Ndipoles + lf(:,(3*i-2):(3*i)) = eeg_leadfield4(pos(i,:), sens.pnt, vol); + end + else + % only single dipole + lf = eeg_leadfield4(pos, sens.pnt, vol); + end + + elseif Nspheres==3 + vol.r = [vol.r(1) vol.r(2) vol.r(3) vol.r(3)]; + vol.c = [vol.c(1) vol.c(2) vol.c(3) vol.c(3)]; + if Ndipoles>1 + % loop over multiple dipoles + lf = zeros(size(sens.pnt,1),3*Ndipoles); + for i=1:Ndipoles + lf(:,(3*i-2):(3*i)) = eeg_leadfield4(pos(i,:), sens.pnt, vol); + end + else + % only single dipole + lf = eeg_leadfield4(pos, sens.pnt, vol); + end + + elseif Nspheres==4 + if Ndipoles>1 + % loop over multiple dipoles + lf = zeros(size(sens.pnt,1),3*Ndipoles); + for i=1:Ndipoles + lf(:,(3*i-2):(3*i)) = eeg_leadfield4(pos(i,:), sens.pnt, vol); + end + else + % only single dipole + lf = eeg_leadfield4(pos, sens.pnt, vol); + end + + else + error('more than 4 concentric spheres are not supported'); + end + + case {'bem', 'dipoli', 'asa', 'avo', 'bemcp'} + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % EEG boundary element method volume conductor model + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + lf = eeg_leadfieldb(pos, sens.pnt, vol); + + case 'openmeeg' + dsm = openmeeg_dsm(pos,vol); + if isfield(vol,'mat') + lf = vol.mat*dsm; + else + error('No system matrix is present, BEM head model not calculated yet') + end + case 'infinite' + % the conductivity of the medium is not known + if isempty(warning_issued) + % give the warning only once + warning('assuming electric dipole in an infinite medium with unit conductivity'); + warning_issued = 1; + end + lf = inf_medium_leadfield(pos, sens.pnt, 1); + + otherwise + error('unsupported volume conductor model for EEG'); + end % switch voltype for EEG + + % compute average reference for EEG leadfield + avg = mean(lf, 1); + lf = lf - repmat(avg, size(lf,1), 1); + +end % iseeg or ismeg + +% optionally apply leadfield rank reduction +if ~strcmp(reducerank, 'no') && reducerank0 + lf = lf ./ nrm; + end +case 'column' + % normalize each column of the leadfield by its norm + for j=1:size(lf,2) + nrm = sum(lf(:,j).^2)^normalizeparam; + lf(:,j) = lf(:,j)./nrm; + end +end + +% optionally apply a weight to the leadfield for each dipole location +if ~isempty(weight) + for i=1:Ndipoles + lf(:,3*(i-1)+1) = lf(:,3*(i-1)+1) * weight(i); % the leadfield for the x-direction + lf(:,3*(i-1)+2) = lf(:,3*(i-2)+1) * weight(i); % the leadfield for the y-direction + lf(:,3*(i-1)+3) = lf(:,3*(i-3)+1) * weight(i); % the leadfield for the z-direction + end +end + diff --git a/external/fieldtrip/forward/ft_convert_units.m b/external/fieldtrip/forward/ft_convert_units.m new file mode 100644 index 0000000..868afe7 --- /dev/null +++ b/external/fieldtrip/forward/ft_convert_units.m @@ -0,0 +1,205 @@ +function [obj] = ft_convert_units(obj, target); + +% FT_CONVERT_UNITS changes the geometrical dimension to the specified SI unit. +% The units of the input object is determined from the structure field +% object.unit, or is estimated based on the spatial extend of the structure, +% e.g. a volume conduction model of the head should be approximately 20 cm large. +% +% Use as +% [object] = ft_convert_units(object, target) +% +% The following input objects are supported +% simple dipole position +% electrode definition +% gradiometer array definition +% volume conductor definition +% dipole grid definition +% anatomical mri +% +% Possible target units are 'm', 'dm', 'cm ' or 'mm'. +% +% See FT_READ_VOL, FT_READ_SENS + +% Copyright (C) 2005-2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_convert_units.m 946 2010-04-21 17:51:16Z roboos $ + +% This function consists of three parts: +% 1) determine the input units +% 2) determine the requested scaling factor to obtain the output units +% 3) try to apply the scaling to the known geometrical elements in the input object + +% determine the unit-of-dimension of the input object +if isfield(obj, 'unit') + % use the units specified in the object + unit = obj.unit; +else + % try to estimate the units from the object + type = ft_voltype(obj); + if ~strcmp(type, 'unknown') + switch type + case 'infinite' + % there is nothing to do to convert the units + unit = target; + + case 'singlesphere' + size = obj.r; + + case 'multisphere' + size = median(obj.r); + + case 'concentric' + size = max(obj.r); + + case 'nolte' + size = norm(range(obj.bnd.pnt)); + + case {'bem' 'dipoli' 'bemcp' 'asa' 'avo'} + size = norm(range(obj.bnd(1).pnt)); + + otherwise + error('cannot determine geometrical units of volume conduction model'); + end % switch + + % determine the units by looking at the size + unit = ft_estimate_units(size); + + elseif ft_senstype(obj, 'meg') + size = norm(range(obj.pnt)); + unit = ft_estimate_units(size); + + elseif ft_senstype(obj, 'eeg') + size = norm(range(obj.pnt)); + unit = ft_estimate_units(size); + + elseif isfield(obj, 'pnt') && ~isempty(obj.pnt) + size = norm(range(obj.pnt)); + unit = ft_estimate_units(size); + + elseif isfield(obj, 'pos') && ~isempty(obj.pos) + size = norm(range(obj.pos)); + unit = ft_estimate_units(size); + + elseif isfield(obj, 'transform') && ~isempty(obj.transform) + % construct the corner points of the voxel grid in head coordinates + xi = 1:obj.dim(1); + yi = 1:obj.dim(2); + zi = 1:obj.dim(3); + pos = [ + xi( 1) yi( 1) zi( 1) + xi( 1) yi( 1) zi(end) + xi( 1) yi(end) zi( 1) + xi( 1) yi(end) zi(end) + xi(end) yi( 1) zi( 1) + xi(end) yi( 1) zi(end) + xi(end) yi(end) zi( 1) + xi(end) yi(end) zi(end) + ]; + pos = warp_apply(obj.transform, pos); + size = norm(range(pos)); + unit = ft_estimate_units(size); + + elseif isfield(obj, 'fid') && isfield(obj.fid, 'pnt') && ~isempty(obj.fid.pnt) + size = norm(range(obj.fid.pnt)); + unit = ft_estimate_units(size); + + else + error('cannot determine geometrical units'); + + end % recognized type of volume conduction model or sensor array +end % determine input units + +if nargin<2 + % just remember the units in the output and return + obj.unit = unit; + return +elseif strcmp(unit, target) + % no conversion is needed + obj.unit = unit; + return +end + +% give some information about the conversion +fprintf('converting units from ''%s'' to ''%s''\n', unit, target) + +if strcmp(unit, 'm') + unit2meter = 1; +elseif strcmp(unit, 'dm') + unit2meter = 0.1; +elseif strcmp(unit, 'cm') + unit2meter = 0.01; +elseif strcmp(unit, 'mm') + unit2meter = 0.001; +end + +% determine the unit-of-dimension of the output object +if strcmp(target, 'm') + meter2target = 1; +elseif strcmp(target, 'dm') + meter2target = 10; +elseif strcmp(target, 'cm') + meter2target = 100; +elseif strcmp(target, 'mm') + meter2target = 1000; +end + +% combine the units into one scaling factor +scale = unit2meter * meter2target; + +% volume conductor model +if isfield(obj, 'r'), obj.r = scale * obj.r; end +if isfield(obj, 'o'), obj.o = scale * obj.o; end +if isfield(obj, 'bnd'), for i=1:length(obj.bnd), obj.bnd(i).pnt = scale * obj.bnd(i).pnt; end, end + +% gradiometer array +if isfield(obj, 'pnt1'), obj.pnt1 = scale * obj.pnt1; end +if isfield(obj, 'pnt2'), obj.pnt2 = scale * obj.pnt2; end +if isfield(obj, 'prj'), obj.prj = scale * obj.prj; end + +% gradiometer array, electrode array, head shape or dipole grid +if isfield(obj, 'pnt'), obj.pnt = scale * obj.pnt; end + +% fiducials +if isfield(obj, 'fid') && isfield(obj.fid, 'pnt'), obj.fid.pnt = scale * obj.fid.pnt; end + +% dipole grid +if isfield(obj, 'pos'), obj.pos = scale * obj.pos; end + +% anatomical MRI or functional volume +if isfield(obj, 'transform'), + H = diag([scale scale scale 1]); + obj.transform = H * obj.transform; +end + +% remember the unit +obj.unit = target; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +% Use as +% r = range(x) +% or you can also specify the dimension along which to look by +% r = range(x, dim) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function r = range(x, dim) +if nargin==1 + r = max(x) - min(x); +else + r = max(x, [], dim) - min(x, [], dim); +end diff --git a/external/fieldtrip/forward/ft_estimate_units.m b/external/fieldtrip/forward/ft_estimate_units.m new file mode 100644 index 0000000..e0655c5 --- /dev/null +++ b/external/fieldtrip/forward/ft_estimate_units.m @@ -0,0 +1,50 @@ +function unit = ft_estimate_units(size) + +% FT_ESTIMATE_UNITS tries to determine the units of a geometrical object by +% looking at its size and by relating this to the size of the human +% brain. +% +% Use as +% unit = ft_estimate_units(size) +% +% This function will return one of the following strings +% 'm' +% 'dm' +% 'cm' +% 'mm' + +% Copyright (C) 2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_estimate_units.m 946 2010-04-21 17:51:16Z roboos $ + +% do some magic based on the size +unit = {'m', 'dm', 'cm', 'mm'}; +indx = round(log10(size)+2-0.2); + +if indx>length(unit) + indx = length(unit); + warning('assuming that the units are "%s"', unit{indx}); +end + +if indx<1 + indx = 1; + warning('assuming that the units are "%s"', unit{indx}); +end + +unit = unit{indx}; diff --git a/external/fieldtrip/forward/ft_inside_vol.m b/external/fieldtrip/forward/ft_inside_vol.m new file mode 100644 index 0000000..deefaa5 --- /dev/null +++ b/external/fieldtrip/forward/ft_inside_vol.m @@ -0,0 +1,110 @@ +function [inside] = ft_inside_vol(pos, vol) + +% FT_INSIDE_VOL locates dipole locations inside/outside the source +% compartment of a volume conductor model. +% +% [inside] = ft_inside_vol(pos, vol, ...) +% +% where the input should be +% pos Nx3 matrix with dipole positions +% vol structure with volume conductor model +% and the output is +% inside list of dipoles inside the brain compartment +% (1=inside, 0=outisde) +% +% Additional optional input arguments shoudl be given in key value pairs +% and can include +% + +% Copyright (C) 2003-2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_inside_vol.m 946 2010-04-21 17:51:16Z roboos $ + +% determine the type of volume conduction model +switch ft_voltype(vol) + + % single-sphere or multiple concentric spheres + case {'singlesphere' 'concentric'} + if ~isfield(vol, 'source') + % locate the innermost compartment and remember it + [dum, vol.source] = min(vol.r); + end + if isfield(vol, 'o') + % shift dipole positions toward origin of sphere + tmp = pos - repmat(vol.o, size(pos,1), 1); + else + tmp = pos; + end + distance = sqrt(sum(tmp.^2, 2))-vol.r(vol.source); + % positive if outside, negative if inside + inside = distance<0; + + % multi-sphere volume conductor model + case 'multisphere' + + % nspheres = size(vol.r,1); + % ndipoles = size(pos,1); + % inside = zeros(ndipoles,1); + % for sph=1:nspheres + % for dip=1:ndipoles + % if inside(dip) + % % the dipole has already been detected in one of the other spheres + % continue + % end + % inside(dip) = (norm(pos(dip,:) - vol.o(sph,:)) <= vol.r(sph)); + % end + % end + % outside = find(inside==0); + % inside = find(inside==1); + + % this is a much faster implementation + nspheres = size(vol.r,1); + ndipoles = size(pos,1); + inside = zeros(ndipoles,1); + for sph=1:nspheres + % temporary shift dipole positions toward origin + if isfield(vol, 'o') + tmp = pos - repmat(vol.o(sph,:), [ndipoles 1]); + else + tmp = pos; + end + flag = (sqrt(sum(tmp.^2,2)) <= vol.r(sph)); + inside = inside + flag; + end + inside = inside>0; + + % realistic BEM volume conductor model + case {'bem', 'dipoli', 'bemcp', 'asa', 'avo', 'nolte', 'neuromag'} + if ~isfield(vol, 'source') + % locate the innermost compartment and remember it + vol.source = find_innermost_boundary(vol.bnd); + end + % use the specified source compartment + pnt = vol.bnd(vol.source).pnt; + tri = vol.bnd(vol.source).tri; + % determine the dipole positions that are inside the brain compartment + inside = bounding_mesh(pos, pnt, tri); + + % unrecognized volume conductor model + otherwise + error('unrecognized volume conductor model'); +end + +% ensure that these are column vectors +inside = logical(inside(:)); diff --git a/external/fieldtrip/forward/ft_prepare_vol_sens.m b/external/fieldtrip/forward/ft_prepare_vol_sens.m new file mode 100644 index 0000000..df7ff7b --- /dev/null +++ b/external/fieldtrip/forward/ft_prepare_vol_sens.m @@ -0,0 +1,367 @@ +function [vol, sens] = ft_prepare_vol_sens(vol, sens, varargin) + +% FT_PREPARE_VOL_SENS does some bookkeeping to ensure that the volume +% conductor model and the sensor array are ready for subsequent forward +% leadfield computations. It takes care of some pre-computations that can +% be done efficiently prior to the leadfield calculations. +% +% Use as +% [vol, sens] = ft_prepare_vol_sens(vol, sens, ...) +% with input arguments +% sens structure with gradiometer or electrode definition +% vol structure with volume conductor definition +% +% The vol structure represents a volume conductor model, its contents +% depend on the type of model. The sens structure represents a sensor +% array, i.e. EEG electrodes or MEG gradiometers. +% +% Additional options should be specified in key-value pairs and can be +% 'channel' cell-array with strings (default = 'all') +% 'order' number, for single shell "Nolte" model (default = 10) +% +% The detailled behaviour of this function depends on whether the input +% consists of EEG or MEG and furthermoree depends on the type of volume +% conductor model: +% - in case of EEG single and concentric sphere models, the electrodes are +% projected onto the skin surface. +% - in case of EEG boundary element models, the electrodes are projected on +% the surface and a blilinear interpoaltion matrix from vertices to +% electrodes is computed. +% - in case of MEG and a multispheres model, a local sphere is determined +% for each coil in the gradiometer definition. +% - in case of MEG with a singleshell Nolte model, the volume conduction +% model is initialized +% In any case channel selection and reordering will be done. The channel +% order returned by this function corresponds to the order in the 'channel' +% option, or if not specified, to the order in the input sensor array. +% +% See also FT_READ_VOL, FT_READ_SENS, FT_TRANSFORM_VOL, FT_TRANSFORM_SENS, FT_COMPUTE_LEADFIELD + +% Copyright (C) 2004-2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_prepare_vol_sens.m 1292 2010-06-29 14:16:12Z roboos $ + +% get the options +% fileformat = keyval('fileformat', varargin); +channel = keyval('channel', varargin); % cell-array with channel labels +order = keyval('order', varargin); % order of expansion for Nolte method; 10 should be enough for real applications; in simulations it makes sense to go higher + +% set the defaults +if isempty(channel), channel = sens.label; end +if isempty(order), order = 10; end + +% determine whether the input contains EEG or MEG sensors +iseeg = ft_senstype(sens, 'eeg'); +ismeg = ft_senstype(sens, 'meg'); + +% determine the skin compartment +if ~isfield(vol, 'skin') + if isfield(vol, 'bnd') + vol.skin = find_outermost_boundary(vol.bnd); + elseif isfield(vol, 'r') && length(vol.r)<=4 + [dum, vol.skin] = max(vol.r); + end +end + +% determine the brain compartment +if ~isfield(vol, 'brain') + if isfield(vol, 'bnd') + vol.brain = find_innermost_boundary(vol.bnd); + elseif isfield(vol, 'r') && length(vol.r)<=4 + [dum, vol.brain] = min(vol.r); + end +end + +% otherwise the voltype assignment to an empty struct below won't work +if isempty(vol) + vol = []; +end + +% this makes them easier to recognise +sens.type = ft_senstype(sens); +vol.type = ft_voltype(vol); + + +if isfield(vol, 'unit') && isfield(sens, 'unit') && ~strcmp(vol.unit, sens.unit) + error('inconsistency in the units of the volume conductor and the sensor array'); +end + +if ismeg && iseeg + % this is something that could be implemented relatively easily + error('simultaneous EEG and MEG not yet supported'); + +elseif ~ismeg && ~iseeg + error('the input does not look like EEG, nor like MEG'); + +elseif ismeg + % always ensure that there is a linear transfer matrix for combining the coils into gradiometers + if ~isfield(sens, 'tra'); + sens.tra = sparse(eye(length(sens.label))); + end + + % select the desired channels from the gradiometer array + % order them according to the users specification + [selchan, selsens] = match_str(channel, sens.label); + + % first only modify the linear combination of coils into channels + sens.label = sens.label(selsens); + sens.tra = sens.tra(selsens,:); + % subsequently remove the coils that do not contribute to any sensor output + selcoil = find(sum(sens.tra,1)~=0); + sens.pnt = sens.pnt(selcoil,:); + sens.ori = sens.ori(selcoil,:); + sens.tra = sens.tra(:,selcoil); + + switch ft_voltype(vol) + case 'infinite' + % nothing to do + + case 'singlesphere' + % nothing to do + + case 'concentric' + % nothing to do + + case 'neuromag' + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % if the forward model is computed using the external Neuromag toolbox, + % we have to add a selection of the channels so that the channels + % in the forward model correspond with those in the data. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + [selchan, selsens] = match_str(channel, sens.label); + vol.chansel = selsens; + + case 'multisphere' + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % If the volume conduction model consists of multiple spheres then we + % have to match the channels in the gradiometer array and the volume + % conduction model. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + % the initial multisphere volume conductor has a single sphere per + % channel, whereas it should have a sphere for each coil + if size(vol.r,1)==size(sens.pnt,1) && ~isfield(vol, 'label') + % it appears that each coil already has a sphere, which suggests + % that the volume conductor already has been prepared to match the + % sensor array + return + elseif size(vol.r,1)==size(sens.pnt,1) && isfield(vol, 'label') + if ~isequal(vol.label(:), sens.label(:)) + % if only the order is different, it would be possible to reorder them + error('the coils in the volume conduction model do not correspond to the sensor array'); + else + % the coil-specific spheres in the volume conductor should not have a label + % because the label is already specified for the coils in the + % sensor array + vol = rmfield(vol, 'label'); + end + return + end + + % select the desired channels from the multisphere volume conductor + % order them according to the users specification + [selchan, selvol] = match_str(channel, vol.label); + vol.label = vol.label(selvol); + vol.r = vol.r(selvol); + vol.o = vol.o(selvol,:); + + % the CTF way of representing the headmodel is one-sphere-per-channel + % whereas the FieldTrip way of doing the forward computation is one-sphere-per-coil + Nchans = size(sens.tra,1); + Ncoils = size(sens.tra,2); + Nspheres = size(vol.label); + + if isfield(vol, 'orig') + % these are present in a CTF *.hdm file + singlesphere.o(1,1) = vol.orig.MEG_Sphere.ORIGIN_X; + singlesphere.o(1,2) = vol.orig.MEG_Sphere.ORIGIN_Y; + singlesphere.o(1,3) = vol.orig.MEG_Sphere.ORIGIN_Z; + singlesphere.r = vol.orig.MEG_Sphere.RADIUS; + % ensure consistent units + singlesphere = ft_convert_units(singlesphere, vol.unit); + else + singlesphere = []; + end + + if ~isempty(singlesphere) + % determine the channels that do not have a corresponding sphere + % and use the globally fitted single sphere for those + missing = setdiff(sens.label, vol.label); + if ~isempty(missing) + warning('using the global fitted single sphere for %d channels that do not have a local sphere', length(missing)); + end + for i=1:length(missing) + vol.label(end+1) = missing(i); + vol.r(end+1,:) = singlesphere.r; + vol.o(end+1,:) = singlesphere.o; + end + end + + multisphere = []; + % for each coil in the MEG helmet, determine the corresponding local sphere + for i=1:Ncoils + coilindex = find(sens.tra(:,i)~=0); % to which channel does the coil belong + if length(coilindex)>1 + % this indicates that there are multiple channels to which this coil contributes, + % which happens if the sensor array represents a synthetic higher-order gradient. + [dum, coilindex] = max(abs(sens.tra(:,i))); + end + + coillabel = sens.label{coilindex}; % what is the label of the channel + chanindex = strmatch(coillabel, vol.label, 'exact'); + multisphere.r(i,:) = vol.r(chanindex); + multisphere.o(i,:) = vol.o(chanindex,:); + end + vol = multisphere; + + case 'nolte' + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % if the forward model is computed using the code from Guido Nolte, we + % have to initialize the volume model using the gradiometer coil + % locations + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + % compute the surface normals for each vertex point + if ~isfield(vol.bnd, 'nrm') + fprintf('computing surface normals\n'); + vol.bnd.nrm = normals(vol.bnd.pnt, vol.bnd.tri); + end + + % estimate center and radius + [center,radius] = fitsphere(vol.bnd.pnt); + + % initialize the forward calculation (only if gradiometer coils are available) + if size(sens.pnt,1)>0 + vol.forwpar = meg_ini([vol.bnd.pnt vol.bnd.nrm], center', order, [sens.pnt sens.ori]); + end + + case 'openmeeg' + % nothing ? + + otherwise + error('unsupported volume conductor model for MEG'); + end + +elseif iseeg + % select the desired channels from the electrode array + % order them according to the users specification + [selchan, selsens] = match_str(channel, sens.label); + sens.label = sens.label(selsens); + sens.pnt = sens.pnt(selsens,:); + + % create a 2D projection and triangulation + sens.prj = elproj(sens.pnt); + sens.tri = delaunay(sens.prj(:,1), sens.prj(:,2)); + + switch ft_voltype(vol) + case 'infinite' + % nothing to do + + case {'singlesphere', 'concentric'} + % ensure that the electrodes ly on the skin surface + radius = max(vol.r); + pnt = sens.pnt; + if isfield(vol, 'o') + % shift the the centre of the sphere to the origin + pnt(:,1) = pnt(:,1) - vol.o(1); + pnt(:,2) = pnt(:,2) - vol.o(2); + pnt(:,3) = pnt(:,3) - vol.o(3); + end + distance = sqrt(sum(pnt.^2,2)); % to the center of the sphere + if any((abs(distance-radius)/radius)>0.005) + warning('electrodes do not lie on skin surface -> using radial projection') + end + pnt = pnt * radius ./ [distance distance distance]; + if isfield(vol, 'o') + % shift the center back to the original location + pnt(:,1) = pnt(:,1) + vol.o(1); + pnt(:,2) = pnt(:,2) + vol.o(2); + pnt(:,3) = pnt(:,3) + vol.o(3); + end + sens.pnt = pnt; + + case {'bem', 'dipoli', 'asa', 'avo', 'bemcp', 'openmeeg'} + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % do postprocessing of volume and electrodes in case of BEM model + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + % project the electrodes on the skin and determine the bilinear interpolation matrix + if ~isfield(vol, 'tra') + % determine boundary corresponding with skin and brain + if ~isfield(vol, 'skin') + vol.skin = find_outermost_boundary(vol.bnd); + fprintf('determining skin compartment (%d)\n', vol.skin); + end + if ~isfield(vol, 'source') + vol.source = find_innermost_boundary(vol.bnd); + fprintf('determining source compartment (%d)\n', vol.source); + end + if size(vol.mat,1)~=size(vol.mat,2) && size(vol.mat,1)==length(sens.pnt) + fprintf('electrode transfer and system matrix were already combined\n'); + else + fprintf('projecting electrodes on skin surface\n'); + % compute linear interpolation from triangle vertices towards electrodes + el = project_elec(sens.pnt, vol.bnd(vol.skin).pnt, vol.bnd(vol.skin).tri); + tra = transfer_elec(vol.bnd(vol.skin).pnt, vol.bnd(vol.skin).tri, el); + if size(vol.mat,1)==size(vol.bnd(vol.skin).pnt,1) + % construct the transfer from only the skin vertices towards electrodes + interp = tra; + else + % construct the transfer from all vertices (also brain/skull) towards electrodes + interp = []; + for i=1:length(vol.bnd) + if i==vol.skin + interp = [interp, tra]; + else + interp = [interp, zeros(size(el,1), size(vol.bnd(i).pnt,1))]; + end + end + end + + % incorporate the linear interpolation matrix and the system matrix into one matrix + % this speeds up the subsequent repeated leadfield computations + fprintf('combining electrode transfer and system matrix\n'); + if strcmp(ft_voltype(vol), 'openmeeg') + nb_points_external_surface = size(vol.bnd(vol.skin).pnt,1); + vol.mat = vol.mat((end-nb_points_external_surface+1):end,:); + vol.mat = interp(:,1:nb_points_external_surface) * vol.mat; + else + % convert to sparse matrix to speed up the subsequent multiplication + interp = sparse(interp); + vol.mat = interp * vol.mat; + % ensure that the model potential will be average referenced + avg = mean(vol.mat, 1); + vol.mat = vol.mat - repmat(avg, size(vol.mat,1), 1); + end + end + end + + otherwise + error('unsupported volume conductor model for EEG'); + end + + % FIXME this needs carefull thought to ensure that the average referencing which is now done here and there, and that the linear interpolation in case of BEM are all dealt with consistently + % % always ensure that there is a linear transfer matrix for + % % rereferencing the EEG potential + % if ~isfield(sens, 'tra'); + % sens.tra = sparse(eye(length(sens.label))); + % end + +end % if iseeg or ismeg + diff --git a/external/fieldtrip/forward/ft_senslabel.m b/external/fieldtrip/forward/ft_senslabel.m new file mode 100644 index 0000000..4242fb1 --- /dev/null +++ b/external/fieldtrip/forward/ft_senslabel.m @@ -0,0 +1,2808 @@ +function label = ft_senslabel(type) + +% FT_SENSLABEL returns a list of sensor labels given the MEEG system type +% +% Use as +% label = ft_senslabel(type) +% +% The input type can be any of the following +% 'biosemi64' +% 'biosemi128' +% 'biosemi256' +% 'bti148' +% 'bti148_planar' +% 'bti248' +% 'bti248_planar' +% 'btiref' +% 'ctf151' +% 'ctf151_planar' +% 'ctf275' +% 'ctf275_planar' +% 'ctfheadloc' +% 'ctfref' +% 'eeg1005' +% 'eeg1010' +% 'eeg1020' +% 'egi128' +% 'egi256' +% 'egi32' +% 'egi64' +% 'ext1020' +% 'neuromag122' +% 'neuromag122alt' +% 'neuromag306' +% 'neuromag306alt' +% 'itab153' +% 'itab153_planar' +% 'yokogawa160' +% 'yokogawa160_planar' +% 'electrode' +% +% See also FT_SENSTYPE, FT_CHANNELSELECTION + +% FIXME one channel is missing for ctf275 + +% Copyright (C) 2007-2008, Robert Oostenveld +% Copyright (C) 2008, Vladimir Litvak +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_senslabel.m 1006 2010-05-03 08:36:13Z roboos $ + +% these are for remembering the type on subsequent calls with the same input arguments +persistent previous_argin previous_argout + +if nargin<1 + % ensure that all input arguments are defined + type = []; +end + +current_argin = {type}; +if isequal(current_argin, previous_argin) + % don't do the type detection again, but return the previous values from cache + label = previous_argout{1}; + return +end + +switch type + + case 'btiref' + label = { + 'MRxA' + 'MRyA' + 'MRzA' + 'MLxA' + 'MLyA' + 'MLzA' + 'MCxA' + 'MCyA' + 'MCzA' + 'MRxaA' + 'MRyaA' + 'MRzaA' + 'MLxaA' + 'MLyaA' + 'MLzaA' + 'MCxaA' + 'MCyaA' + 'MCzaA' + 'GxxA' + 'GyxA' + 'GzxA' + 'GyyA' + 'GzyA' + }; + + case 'bti148' + label = cell(148,1); + for i=1:148 + label{i,1} = sprintf('A%d', i); + end + + case 'bti148_planar' + label = cell(148,2); + for i=1:148 + label{i,1} = sprintf('A%d_dH', i); + label{i,2} = sprintf('A%d_dV', i); + end + + case 'bti248' + label = cell(248,1); + for i=1:248 + label{i,1} = sprintf('A%d', i); + end + + case 'bti248_planar' + label = cell(248,2); + for i=1:248 + label{i,1} = sprintf('A%d_dH', i); + label{i,2} = sprintf('A%d_dV', i); + end + + case 'ctfref' + label = { + 'BG1' + 'BG2' + 'BG3' + 'BP1' + 'BP2' + 'BP3' + 'BR1' + 'BR2' + 'BR3' + 'G11' + 'G12' + 'G13' + 'G22' + 'G23' + 'P11' + 'P12' + 'P13' + 'P22' + 'P23' + 'Q11' + 'Q12' + 'Q13' + 'Q22' + 'Q23' + 'R11' + 'R12' + 'R13' + 'R22' + 'R23' + }; + + case 'ctfheadloc' + label = { + 'HLC0011' + 'HLC0012' + 'HLC0013' + 'HLC0021' + 'HLC0022' + 'HLC0023' + 'HLC0031' + 'HLC0032' + 'HLC0033' + 'HLC0018' + 'HLC0028' + 'HLC0038' + 'HLC0014' + 'HLC0015' + 'HLC0016' + 'HLC0017' + 'HLC0024' + 'HLC0025' + 'HLC0026' + 'HLC0027' + 'HLC0034' + 'HLC0035' + 'HLC0036' + 'HLC0037' + }; + + case 'ctf64' + label = { + 'SL11' + 'SL12' + 'SL13' + 'SL14' + 'SL15' + 'SL16' + 'SL17' + 'SL18' + 'SL19' + 'SL21' + 'SL22' + 'SL23' + 'SL24' + 'SL25' + 'SL26' + 'SL27' + 'SL28' + 'SL29' + 'SL31' + 'SL32' + 'SL33' + 'SL34' + 'SL35' + 'SL41' + 'SL42' + 'SL43' + 'SL44' + 'SL45' + 'SL46' + 'SL47' + 'SL51' + 'SL52' + 'SR11' + 'SR12' + 'SR13' + 'SR14' + 'SR15' + 'SR16' + 'SR17' + 'SR18' + 'SR19' + 'SR21' + 'SR22' + 'SR23' + 'SR24' + 'SR25' + 'SR26' + 'SR27' + 'SR28' + 'SR29' + 'SR31' + 'SR32' + 'SR33' + 'SR34' + 'SR35' + 'SR41' + 'SR42' + 'SR43' + 'SR44' + 'SR45' + 'SR46' + 'SR47' + 'SR51' + 'SR52' + }; + + case 'ctf151' + label = { + 'MLC11' + 'MLC12' + 'MLC13' + 'MLC14' + 'MLC15' + 'MLC21' + 'MLC22' + 'MLC23' + 'MLC24' + 'MLC31' + 'MLC32' + 'MLC33' + 'MLC41' + 'MLC42' + 'MLC43' + 'MLF11' + 'MLF12' + 'MLF21' + 'MLF22' + 'MLF23' + 'MLF31' + 'MLF32' + 'MLF33' + 'MLF34' + 'MLF41' + 'MLF42' + 'MLF43' + 'MLF44' + 'MLF45' + 'MLF51' + 'MLF52' + 'MLO11' + 'MLO12' + 'MLO21' + 'MLO22' + 'MLO31' + 'MLO32' + 'MLO33' + 'MLO41' + 'MLO42' + 'MLO43' + 'MLP11' + 'MLP12' + 'MLP13' + 'MLP21' + 'MLP22' + 'MLP31' + 'MLP32' + 'MLP33' + 'MLP34' + 'MLT11' + 'MLT12' + 'MLT13' + 'MLT14' + 'MLT15' + 'MLT16' + 'MLT21' + 'MLT22' + 'MLT23' + 'MLT24' + 'MLT25' + 'MLT26' + 'MLT31' + 'MLT32' + 'MLT33' + 'MLT34' + 'MLT35' + 'MLT41' + 'MLT42' + 'MLT43' + 'MLT44' + 'MRC11' + 'MRC12' + 'MRC13' + 'MRC14' + 'MRC15' + 'MRC21' + 'MRC22' + 'MRC23' + 'MRC24' + 'MRC31' + 'MRC32' + 'MRC33' + 'MRC41' + 'MRC42' + 'MRC43' + 'MRF11' + 'MRF12' + 'MRF21' + 'MRF22' + 'MRF23' + 'MRF31' + 'MRF32' + 'MRF33' + 'MRF34' + 'MRF41' + 'MRF42' + 'MRF43' + 'MRF44' + 'MRF45' + 'MRF51' + 'MRF52' + 'MRO11' + 'MRO12' + 'MRO21' + 'MRO22' + 'MRO31' + 'MRO32' + 'MRO33' + 'MRO41' + 'MRO42' + 'MRO43' + 'MRP11' + 'MRP12' + 'MRP13' + 'MRP21' + 'MRP22' + 'MRP31' + 'MRP32' + 'MRP33' + 'MRP34' + 'MRT11' + 'MRT12' + 'MRT13' + 'MRT14' + 'MRT15' + 'MRT16' + 'MRT21' + 'MRT22' + 'MRT23' + 'MRT24' + 'MRT25' + 'MRT26' + 'MRT31' + 'MRT32' + 'MRT33' + 'MRT34' + 'MRT35' + 'MRT41' + 'MRT42' + 'MRT43' + 'MRT44' + 'MZC01' + 'MZC02' + 'MZF01' + 'MZF02' + 'MZF03' + 'MZO01' + 'MZO02' + 'MZP01' + 'MZP02' + }; + + case 'ctf151_planar' + label = { + 'MLC11_dH' 'MLC11_dV' + 'MLC12_dH' 'MLC12_dV' + 'MLC13_dH' 'MLC13_dV' + 'MLC14_dH' 'MLC14_dV' + 'MLC15_dH' 'MLC15_dV' + 'MLC21_dH' 'MLC21_dV' + 'MLC22_dH' 'MLC22_dV' + 'MLC23_dH' 'MLC23_dV' + 'MLC24_dH' 'MLC24_dV' + 'MLC31_dH' 'MLC31_dV' + 'MLC32_dH' 'MLC32_dV' + 'MLC33_dH' 'MLC33_dV' + 'MLC41_dH' 'MLC41_dV' + 'MLC42_dH' 'MLC42_dV' + 'MLC43_dH' 'MLC43_dV' + 'MLF11_dH' 'MLF11_dV' + 'MLF12_dH' 'MLF12_dV' + 'MLF21_dH' 'MLF21_dV' + 'MLF22_dH' 'MLF22_dV' + 'MLF23_dH' 'MLF23_dV' + 'MLF31_dH' 'MLF31_dV' + 'MLF32_dH' 'MLF32_dV' + 'MLF33_dH' 'MLF33_dV' + 'MLF34_dH' 'MLF34_dV' + 'MLF41_dH' 'MLF41_dV' + 'MLF42_dH' 'MLF42_dV' + 'MLF43_dH' 'MLF43_dV' + 'MLF44_dH' 'MLF44_dV' + 'MLF45_dH' 'MLF45_dV' + 'MLF51_dH' 'MLF51_dV' + 'MLF52_dH' 'MLF52_dV' + 'MLO11_dH' 'MLO11_dV' + 'MLO12_dH' 'MLO12_dV' + 'MLO21_dH' 'MLO21_dV' + 'MLO22_dH' 'MLO22_dV' + 'MLO31_dH' 'MLO31_dV' + 'MLO32_dH' 'MLO32_dV' + 'MLO33_dH' 'MLO33_dV' + 'MLO41_dH' 'MLO41_dV' + 'MLO42_dH' 'MLO42_dV' + 'MLO43_dH' 'MLO43_dV' + 'MLP11_dH' 'MLP11_dV' + 'MLP12_dH' 'MLP12_dV' + 'MLP13_dH' 'MLP13_dV' + 'MLP21_dH' 'MLP21_dV' + 'MLP22_dH' 'MLP22_dV' + 'MLP31_dH' 'MLP31_dV' + 'MLP32_dH' 'MLP32_dV' + 'MLP33_dH' 'MLP33_dV' + 'MLP34_dH' 'MLP34_dV' + 'MLT11_dH' 'MLT11_dV' + 'MLT12_dH' 'MLT12_dV' + 'MLT13_dH' 'MLT13_dV' + 'MLT14_dH' 'MLT14_dV' + 'MLT15_dH' 'MLT15_dV' + 'MLT16_dH' 'MLT16_dV' + 'MLT21_dH' 'MLT21_dV' + 'MLT22_dH' 'MLT22_dV' + 'MLT23_dH' 'MLT23_dV' + 'MLT24_dH' 'MLT24_dV' + 'MLT25_dH' 'MLT25_dV' + 'MLT26_dH' 'MLT26_dV' + 'MLT31_dH' 'MLT31_dV' + 'MLT32_dH' 'MLT32_dV' + 'MLT33_dH' 'MLT33_dV' + 'MLT34_dH' 'MLT34_dV' + 'MLT35_dH' 'MLT35_dV' + 'MLT41_dH' 'MLT41_dV' + 'MLT42_dH' 'MLT42_dV' + 'MLT43_dH' 'MLT43_dV' + 'MLT44_dH' 'MLT44_dV' + 'MRC11_dH' 'MRC11_dV' + 'MRC12_dH' 'MRC12_dV' + 'MRC13_dH' 'MRC13_dV' + 'MRC14_dH' 'MRC14_dV' + 'MRC15_dH' 'MRC15_dV' + 'MRC21_dH' 'MRC21_dV' + 'MRC22_dH' 'MRC22_dV' + 'MRC23_dH' 'MRC23_dV' + 'MRC24_dH' 'MRC24_dV' + 'MRC31_dH' 'MRC31_dV' + 'MRC32_dH' 'MRC32_dV' + 'MRC33_dH' 'MRC33_dV' + 'MRC41_dH' 'MRC41_dV' + 'MRC42_dH' 'MRC42_dV' + 'MRC43_dH' 'MRC43_dV' + 'MRF11_dH' 'MRF11_dV' + 'MRF12_dH' 'MRF12_dV' + 'MRF21_dH' 'MRF21_dV' + 'MRF22_dH' 'MRF22_dV' + 'MRF23_dH' 'MRF23_dV' + 'MRF31_dH' 'MRF31_dV' + 'MRF32_dH' 'MRF32_dV' + 'MRF33_dH' 'MRF33_dV' + 'MRF34_dH' 'MRF34_dV' + 'MRF41_dH' 'MRF41_dV' + 'MRF42_dH' 'MRF42_dV' + 'MRF43_dH' 'MRF43_dV' + 'MRF44_dH' 'MRF44_dV' + 'MRF45_dH' 'MRF45_dV' + 'MRF51_dH' 'MRF51_dV' + 'MRF52_dH' 'MRF52_dV' + 'MRO11_dH' 'MRO11_dV' + 'MRO12_dH' 'MRO12_dV' + 'MRO21_dH' 'MRO21_dV' + 'MRO22_dH' 'MRO22_dV' + 'MRO31_dH' 'MRO31_dV' + 'MRO32_dH' 'MRO32_dV' + 'MRO33_dH' 'MRO33_dV' + 'MRO41_dH' 'MRO41_dV' + 'MRO42_dH' 'MRO42_dV' + 'MRO43_dH' 'MRO43_dV' + 'MRP11_dH' 'MRP11_dV' + 'MRP12_dH' 'MRP12_dV' + 'MRP13_dH' 'MRP13_dV' + 'MRP21_dH' 'MRP21_dV' + 'MRP22_dH' 'MRP22_dV' + 'MRP31_dH' 'MRP31_dV' + 'MRP32_dH' 'MRP32_dV' + 'MRP33_dH' 'MRP33_dV' + 'MRP34_dH' 'MRP34_dV' + 'MRT11_dH' 'MRT11_dV' + 'MRT12_dH' 'MRT12_dV' + 'MRT13_dH' 'MRT13_dV' + 'MRT14_dH' 'MRT14_dV' + 'MRT15_dH' 'MRT15_dV' + 'MRT16_dH' 'MRT16_dV' + 'MRT21_dH' 'MRT21_dV' + 'MRT22_dH' 'MRT22_dV' + 'MRT23_dH' 'MRT23_dV' + 'MRT24_dH' 'MRT24_dV' + 'MRT25_dH' 'MRT25_dV' + 'MRT26_dH' 'MRT26_dV' + 'MRT31_dH' 'MRT31_dV' + 'MRT32_dH' 'MRT32_dV' + 'MRT33_dH' 'MRT33_dV' + 'MRT34_dH' 'MRT34_dV' + 'MRT35_dH' 'MRT35_dV' + 'MRT41_dH' 'MRT41_dV' + 'MRT42_dH' 'MRT42_dV' + 'MRT43_dH' 'MRT43_dV' + 'MRT44_dH' 'MRT44_dV' + 'MZC01_dH' 'MZC01_dV' + 'MZC02_dH' 'MZC02_dV' + 'MZF01_dH' 'MZF01_dV' + 'MZF02_dH' 'MZF02_dV' + 'MZF03_dH' 'MZF03_dV' + 'MZO01_dH' 'MZO01_dV' + 'MZO02_dH' 'MZO02_dV' + 'MZP01_dH' 'MZP01_dV' + 'MZP02_dH' 'MZP02_dV' + }; + + case 'ctf275' + label = { + 'MLC11' + 'MLC12' + 'MLC13' + 'MLC14' + 'MLC15' + 'MLC16' + 'MLC17' + 'MLC21' + 'MLC22' + 'MLC23' + 'MLC24' + 'MLC25' + 'MLC31' + 'MLC32' + 'MLC41' + 'MLC42' + 'MLC51' + 'MLC52' + 'MLC53' + 'MLC54' + 'MLC55' + 'MLC61' + 'MLC62' + 'MLC63' + 'MLF11' + 'MLF12' + 'MLF13' + 'MLF14' + 'MLF21' + 'MLF22' + 'MLF23' + 'MLF24' + 'MLF25' + 'MLF31' + 'MLF32' + 'MLF33' + 'MLF34' + 'MLF35' + 'MLF41' + 'MLF42' + 'MLF43' + 'MLF44' + 'MLF45' + 'MLF46' + 'MLF51' + 'MLF52' + 'MLF53' + 'MLF54' + 'MLF55' + 'MLF56' + 'MLF61' + 'MLF62' + 'MLF63' + 'MLF64' + 'MLF65' + 'MLF66' + 'MLF67' + 'MLO11' + 'MLO12' + 'MLO13' + 'MLO14' + 'MLO21' + 'MLO22' + 'MLO23' + 'MLO24' + 'MLO31' + 'MLO32' + 'MLO33' + 'MLO34' + 'MLO41' + 'MLO42' + 'MLO43' + 'MLO44' + 'MLO51' + 'MLO52' + 'MLO53' + 'MLP11' + 'MLP12' + 'MLP21' + 'MLP22' + 'MLP23' + 'MLP31' + 'MLP32' + 'MLP33' + 'MLP34' + 'MLP35' + 'MLP41' + 'MLP42' + 'MLP43' + 'MLP44' + 'MLP45' + 'MLP51' + 'MLP52' + 'MLP53' + 'MLP54' + 'MLP55' + 'MLP56' + 'MLP57' + 'MLT11' + 'MLT12' + 'MLT13' + 'MLT14' + 'MLT15' + 'MLT16' + 'MLT21' + 'MLT22' + 'MLT23' + 'MLT24' + 'MLT25' + 'MLT26' + 'MLT27' + 'MLT31' + 'MLT32' + 'MLT33' + 'MLT34' + 'MLT35' + 'MLT36' + 'MLT37' + 'MLT41' + 'MLT42' + 'MLT43' + 'MLT44' + 'MLT45' + 'MLT46' + 'MLT47' + 'MLT51' + 'MLT52' + 'MLT53' + 'MLT54' + 'MLT55' + 'MLT56' + 'MLT57' + 'MRC11' + 'MRC12' + 'MRC13' + 'MRC14' + 'MRC15' + 'MRC16' + 'MRC17' + 'MRC21' + 'MRC22' + 'MRC23' + 'MRC24' + 'MRC25' + 'MRC31' + 'MRC32' + 'MRC41' + 'MRC42' + 'MRC51' + 'MRC52' + 'MRC53' + 'MRC54' + 'MRC55' + 'MRC61' + 'MRC62' + 'MRC63' + 'MRF11' + 'MRF12' + 'MRF13' + 'MRF14' + 'MRF21' + 'MRF22' + 'MRF23' + 'MRF24' + 'MRF25' + 'MRF31' + 'MRF32' + 'MRF33' + 'MRF34' + 'MRF35' + 'MRF41' + 'MRF42' + 'MRF43' + 'MRF44' + 'MRF45' + 'MRF46' + 'MRF51' + 'MRF52' + 'MRF53' + 'MRF54' + 'MRF55' + 'MRF56' + 'MRF61' + 'MRF62' + 'MRF63' + 'MRF64' + 'MRF65' + 'MRF66' + 'MRF67' + 'MRO11' + 'MRO12' + 'MRO13' + 'MRO14' + 'MRO21' + 'MRO22' + 'MRO23' + 'MRO24' + 'MRO31' + 'MRO32' + 'MRO33' + 'MRO34' + 'MRO41' + 'MRO42' + 'MRO43' + 'MRO44' + 'MRO51' + 'MRO52' + 'MRO53' + 'MRP11' + 'MRP12' + 'MRP21' + 'MRP22' + 'MRP23' + 'MRP32' + 'MRP33' + 'MRP34' + 'MRP35' + 'MRP41' + 'MRP42' + 'MRP43' + 'MRP44' + 'MRP45' + 'MRP51' + 'MRP52' + 'MRP53' + 'MRP54' + 'MRP55' + 'MRP56' + 'MRP57' + 'MRT11' + 'MRT12' + 'MRT13' + 'MRT14' + 'MRT15' + 'MRT16' + 'MRT21' + 'MRT22' + 'MRT23' + 'MRT24' + 'MRT25' + 'MRT26' + 'MRT27' + 'MRT31' + 'MRT32' + 'MRT33' + 'MRT34' + 'MRT35' + 'MRT36' + 'MRT37' + 'MRT41' + 'MRT42' + 'MRT43' + 'MRT44' + 'MRT45' + 'MRT46' + 'MRT47' + 'MRT51' + 'MRT52' + 'MRT53' + 'MRT54' + 'MRT55' + 'MRT56' + 'MRT57' + 'MZC01' + 'MZC02' + 'MZC03' + 'MZC04' + 'MZF01' + 'MZF02' + 'MZF03' + 'MZO01' + 'MZO02' + 'MZO03' + 'MZP01' + }; + + case 'ctf275_planar' + % FIXME one channel seems to be missing + label = { + 'MLC11_dH' 'MLC11_dV' + 'MLC12_dH' 'MLC12_dV' + 'MLC13_dH' 'MLC13_dV' + 'MLC14_dH' 'MLC14_dV' + 'MLC15_dH' 'MLC15_dV' + 'MLC16_dH' 'MLC16_dV' + 'MLC17_dH' 'MLC17_dV' + 'MLC21_dH' 'MLC21_dV' + 'MLC22_dH' 'MLC22_dV' + 'MLC23_dH' 'MLC23_dV' + 'MLC24_dH' 'MLC24_dV' + 'MLC25_dH' 'MLC25_dV' + 'MLC31_dH' 'MLC31_dV' + 'MLC32_dH' 'MLC32_dV' + 'MLC41_dH' 'MLC41_dV' + 'MLC42_dH' 'MLC42_dV' + 'MLC51_dH' 'MLC51_dV' + 'MLC52_dH' 'MLC52_dV' + 'MLC53_dH' 'MLC53_dV' + 'MLC54_dH' 'MLC54_dV' + 'MLC55_dH' 'MLC55_dV' + 'MLC61_dH' 'MLC61_dV' + 'MLC62_dH' 'MLC62_dV' + 'MLC63_dH' 'MLC63_dV' + 'MLF11_dH' 'MLF11_dV' + 'MLF12_dH' 'MLF12_dV' + 'MLF13_dH' 'MLF13_dV' + 'MLF14_dH' 'MLF14_dV' + 'MLF21_dH' 'MLF21_dV' + 'MLF22_dH' 'MLF22_dV' + 'MLF23_dH' 'MLF23_dV' + 'MLF24_dH' 'MLF24_dV' + 'MLF25_dH' 'MLF25_dV' + 'MLF31_dH' 'MLF31_dV' + 'MLF32_dH' 'MLF32_dV' + 'MLF33_dH' 'MLF33_dV' + 'MLF34_dH' 'MLF34_dV' + 'MLF35_dH' 'MLF35_dV' + 'MLF41_dH' 'MLF41_dV' + 'MLF42_dH' 'MLF42_dV' + 'MLF43_dH' 'MLF43_dV' + 'MLF44_dH' 'MLF44_dV' + 'MLF45_dH' 'MLF45_dV' + 'MLF46_dH' 'MLF46_dV' + 'MLF51_dH' 'MLF51_dV' + 'MLF52_dH' 'MLF52_dV' + 'MLF53_dH' 'MLF53_dV' + 'MLF54_dH' 'MLF54_dV' + 'MLF55_dH' 'MLF55_dV' + 'MLF56_dH' 'MLF56_dV' + 'MLF61_dH' 'MLF61_dV' + 'MLF62_dH' 'MLF62_dV' + 'MLF63_dH' 'MLF63_dV' + 'MLF64_dH' 'MLF64_dV' + 'MLF65_dH' 'MLF65_dV' + 'MLF66_dH' 'MLF66_dV' + 'MLF67_dH' 'MLF67_dV' + 'MLO11_dH' 'MLO11_dV' + 'MLO12_dH' 'MLO12_dV' + 'MLO13_dH' 'MLO13_dV' + 'MLO14_dH' 'MLO14_dV' + 'MLO21_dH' 'MLO21_dV' + 'MLO22_dH' 'MLO22_dV' + 'MLO23_dH' 'MLO23_dV' + 'MLO24_dH' 'MLO24_dV' + 'MLO31_dH' 'MLO31_dV' + 'MLO32_dH' 'MLO32_dV' + 'MLO33_dH' 'MLO33_dV' + 'MLO34_dH' 'MLO34_dV' + 'MLO41_dH' 'MLO41_dV' + 'MLO42_dH' 'MLO42_dV' + 'MLO43_dH' 'MLO43_dV' + 'MLO44_dH' 'MLO44_dV' + 'MLO51_dH' 'MLO51_dV' + 'MLO52_dH' 'MLO52_dV' + 'MLO53_dH' 'MLO53_dV' + 'MLP11_dH' 'MLP11_dV' + 'MLP12_dH' 'MLP12_dV' + 'MLP21_dH' 'MLP21_dV' + 'MLP22_dH' 'MLP22_dV' + 'MLP23_dH' 'MLP23_dV' + 'MLP31_dH' 'MLP31_dV' + 'MLP32_dH' 'MLP32_dV' + 'MLP33_dH' 'MLP33_dV' + 'MLP34_dH' 'MLP34_dV' + 'MLP35_dH' 'MLP35_dV' + 'MLP41_dH' 'MLP41_dV' + 'MLP42_dH' 'MLP42_dV' + 'MLP43_dH' 'MLP43_dV' + 'MLP44_dH' 'MLP44_dV' + 'MLP45_dH' 'MLP45_dV' + 'MLP51_dH' 'MLP51_dV' + 'MLP52_dH' 'MLP52_dV' + 'MLP53_dH' 'MLP53_dV' + 'MLP54_dH' 'MLP54_dV' + 'MLP55_dH' 'MLP55_dV' + 'MLP56_dH' 'MLP56_dV' + 'MLP57_dH' 'MLP57_dV' + 'MLT11_dH' 'MLT11_dV' + 'MLT12_dH' 'MLT12_dV' + 'MLT13_dH' 'MLT13_dV' + 'MLT14_dH' 'MLT14_dV' + 'MLT15_dH' 'MLT15_dV' + 'MLT16_dH' 'MLT16_dV' + 'MLT21_dH' 'MLT21_dV' + 'MLT22_dH' 'MLT22_dV' + 'MLT23_dH' 'MLT23_dV' + 'MLT24_dH' 'MLT24_dV' + 'MLT25_dH' 'MLT25_dV' + 'MLT26_dH' 'MLT26_dV' + 'MLT27_dH' 'MLT27_dV' + 'MLT31_dH' 'MLT31_dV' + 'MLT32_dH' 'MLT32_dV' + 'MLT33_dH' 'MLT33_dV' + 'MLT34_dH' 'MLT34_dV' + 'MLT35_dH' 'MLT35_dV' + 'MLT36_dH' 'MLT36_dV' + 'MLT37_dH' 'MLT37_dV' + 'MLT41_dH' 'MLT41_dV' + 'MLT42_dH' 'MLT42_dV' + 'MLT43_dH' 'MLT43_dV' + 'MLT44_dH' 'MLT44_dV' + 'MLT45_dH' 'MLT45_dV' + 'MLT46_dH' 'MLT46_dV' + 'MLT47_dH' 'MLT47_dV' + 'MLT51_dH' 'MLT51_dV' + 'MLT52_dH' 'MLT52_dV' + 'MLT53_dH' 'MLT53_dV' + 'MLT54_dH' 'MLT54_dV' + 'MLT55_dH' 'MLT55_dV' + 'MLT56_dH' 'MLT56_dV' + 'MLT57_dH' 'MLT57_dV' + 'MRC11_dH' 'MRC11_dV' + 'MRC12_dH' 'MRC12_dV' + 'MRC13_dH' 'MRC13_dV' + 'MRC14_dH' 'MRC14_dV' + 'MRC15_dH' 'MRC15_dV' + 'MRC16_dH' 'MRC16_dV' + 'MRC17_dH' 'MRC17_dV' + 'MRC21_dH' 'MRC21_dV' + 'MRC22_dH' 'MRC22_dV' + 'MRC23_dH' 'MRC23_dV' + 'MRC24_dH' 'MRC24_dV' + 'MRC25_dH' 'MRC25_dV' + 'MRC31_dH' 'MRC31_dV' + 'MRC32_dH' 'MRC32_dV' + 'MRC41_dH' 'MRC41_dV' + 'MRC42_dH' 'MRC42_dV' + 'MRC51_dH' 'MRC51_dV' + 'MRC52_dH' 'MRC52_dV' + 'MRC53_dH' 'MRC53_dV' + 'MRC54_dH' 'MRC54_dV' + 'MRC55_dH' 'MRC55_dV' + 'MRC61_dH' 'MRC61_dV' + 'MRC62_dH' 'MRC62_dV' + 'MRC63_dH' 'MRC63_dV' + 'MRF11_dH' 'MRF11_dV' + 'MRF12_dH' 'MRF12_dV' + 'MRF13_dH' 'MRF13_dV' + 'MRF14_dH' 'MRF14_dV' + 'MRF21_dH' 'MRF21_dV' + 'MRF22_dH' 'MRF22_dV' + 'MRF23_dH' 'MRF23_dV' + 'MRF24_dH' 'MRF24_dV' + 'MRF25_dH' 'MRF25_dV' + 'MRF31_dH' 'MRF31_dV' + 'MRF32_dH' 'MRF32_dV' + 'MRF33_dH' 'MRF33_dV' + 'MRF34_dH' 'MRF34_dV' + 'MRF35_dH' 'MRF35_dV' + 'MRF41_dH' 'MRF41_dV' + 'MRF42_dH' 'MRF42_dV' + 'MRF43_dH' 'MRF43_dV' + 'MRF44_dH' 'MRF44_dV' + 'MRF45_dH' 'MRF45_dV' + 'MRF46_dH' 'MRF46_dV' + 'MRF51_dH' 'MRF51_dV' + 'MRF52_dH' 'MRF52_dV' + 'MRF53_dH' 'MRF53_dV' + 'MRF54_dH' 'MRF54_dV' + 'MRF55_dH' 'MRF55_dV' + 'MRF56_dH' 'MRF56_dV' + 'MRF61_dH' 'MRF61_dV' + 'MRF62_dH' 'MRF62_dV' + 'MRF63_dH' 'MRF63_dV' + 'MRF64_dH' 'MRF64_dV' + 'MRF65_dH' 'MRF65_dV' + 'MRF66_dH' 'MRF66_dV' + 'MRF67_dH' 'MRF67_dV' + 'MRO11_dH' 'MRO11_dV' + 'MRO12_dH' 'MRO12_dV' + 'MRO13_dH' 'MRO13_dV' + 'MRO14_dH' 'MRO14_dV' + 'MRO21_dH' 'MRO21_dV' + 'MRO22_dH' 'MRO22_dV' + 'MRO23_dH' 'MRO23_dV' + 'MRO24_dH' 'MRO24_dV' + 'MRO31_dH' 'MRO31_dV' + 'MRO32_dH' 'MRO32_dV' + 'MRO33_dH' 'MRO33_dV' + 'MRO34_dH' 'MRO34_dV' + 'MRO41_dH' 'MRO41_dV' + 'MRO42_dH' 'MRO42_dV' + 'MRO43_dH' 'MRO43_dV' + 'MRO44_dH' 'MRO44_dV' + 'MRO51_dH' 'MRO51_dV' + 'MRO52_dH' 'MRO52_dV' + 'MRO53_dH' 'MRO53_dV' + 'MRP11_dH' 'MRP11_dV' + 'MRP12_dH' 'MRP12_dV' + 'MRP21_dH' 'MRP21_dV' + 'MRP22_dH' 'MRP22_dV' + 'MRP23_dH' 'MRP23_dV' + 'MRP32_dH' 'MRP32_dV' + 'MRP33_dH' 'MRP33_dV' + 'MRP34_dH' 'MRP34_dV' + 'MRP35_dH' 'MRP35_dV' + 'MRP41_dH' 'MRP41_dV' + 'MRP42_dH' 'MRP42_dV' + 'MRP43_dH' 'MRP43_dV' + 'MRP44_dH' 'MRP44_dV' + 'MRP45_dH' 'MRP45_dV' + 'MRP51_dH' 'MRP51_dV' + 'MRP52_dH' 'MRP52_dV' + 'MRP53_dH' 'MRP53_dV' + 'MRP54_dH' 'MRP54_dV' + 'MRP55_dH' 'MRP55_dV' + 'MRP56_dH' 'MRP56_dV' + 'MRP57_dH' 'MRP57_dV' + 'MRT11_dH' 'MRT11_dV' + 'MRT12_dH' 'MRT12_dV' + 'MRT13_dH' 'MRT13_dV' + 'MRT14_dH' 'MRT14_dV' + 'MRT15_dH' 'MRT15_dV' + 'MRT16_dH' 'MRT16_dV' + 'MRT21_dH' 'MRT21_dV' + 'MRT22_dH' 'MRT22_dV' + 'MRT23_dH' 'MRT23_dV' + 'MRT24_dH' 'MRT24_dV' + 'MRT25_dH' 'MRT25_dV' + 'MRT26_dH' 'MRT26_dV' + 'MRT27_dH' 'MRT27_dV' + 'MRT31_dH' 'MRT31_dV' + 'MRT32_dH' 'MRT32_dV' + 'MRT33_dH' 'MRT33_dV' + 'MRT34_dH' 'MRT34_dV' + 'MRT35_dH' 'MRT35_dV' + 'MRT36_dH' 'MRT36_dV' + 'MRT37_dH' 'MRT37_dV' + 'MRT41_dH' 'MRT41_dV' + 'MRT42_dH' 'MRT42_dV' + 'MRT43_dH' 'MRT43_dV' + 'MRT44_dH' 'MRT44_dV' + 'MRT45_dH' 'MRT45_dV' + 'MRT46_dH' 'MRT46_dV' + 'MRT47_dH' 'MRT47_dV' + 'MRT51_dH' 'MRT51_dV' + 'MRT52_dH' 'MRT52_dV' + 'MRT53_dH' 'MRT53_dV' + 'MRT54_dH' 'MRT54_dV' + 'MRT55_dH' 'MRT55_dV' + 'MRT56_dH' 'MRT56_dV' + 'MRT57_dH' 'MRT57_dV' + 'MZC01_dH' 'MZC01_dV' + 'MZC02_dH' 'MZC02_dV' + 'MZC03_dH' 'MZC03_dV' + 'MZC04_dH' 'MZC04_dV' + 'MZF01_dH' 'MZF01_dV' + 'MZF02_dH' 'MZF02_dV' + 'MZF03_dH' 'MZF03_dV' + 'MZO01_dH' 'MZO01_dV' + 'MZO02_dH' 'MZO02_dV' + 'MZO03_dH' 'MZO03_dV' + 'MZP01_dH' 'MZP01_dV' + }; + + + case 'neuromag122' + label = { + 'MEG 001' 'MEG 002' + 'MEG 003' 'MEG 004' + 'MEG 005' 'MEG 006' + 'MEG 007' 'MEG 008' + 'MEG 009' 'MEG 010' + 'MEG 011' 'MEG 012' + 'MEG 013' 'MEG 014' + 'MEG 015' 'MEG 016' + 'MEG 017' 'MEG 018' + 'MEG 019' 'MEG 020' + 'MEG 021' 'MEG 022' + 'MEG 023' 'MEG 024' + 'MEG 025' 'MEG 026' + 'MEG 027' 'MEG 028' + 'MEG 029' 'MEG 030' + 'MEG 031' 'MEG 032' + 'MEG 033' 'MEG 034' + 'MEG 035' 'MEG 036' + 'MEG 037' 'MEG 038' + 'MEG 039' 'MEG 040' + 'MEG 041' 'MEG 042' + 'MEG 043' 'MEG 044' + 'MEG 045' 'MEG 046' + 'MEG 047' 'MEG 048' + 'MEG 049' 'MEG 050' + 'MEG 051' 'MEG 052' + 'MEG 053' 'MEG 054' + 'MEG 055' 'MEG 056' + 'MEG 057' 'MEG 058' + 'MEG 059' 'MEG 060' + 'MEG 061' 'MEG 062' + 'MEG 063' 'MEG 064' + 'MEG 065' 'MEG 066' + 'MEG 067' 'MEG 068' + 'MEG 069' 'MEG 070' + 'MEG 071' 'MEG 072' + 'MEG 073' 'MEG 074' + 'MEG 075' 'MEG 076' + 'MEG 077' 'MEG 078' + 'MEG 079' 'MEG 080' + 'MEG 081' 'MEG 082' + 'MEG 083' 'MEG 084' + 'MEG 085' 'MEG 086' + 'MEG 087' 'MEG 088' + 'MEG 089' 'MEG 090' + 'MEG 091' 'MEG 092' + 'MEG 093' 'MEG 094' + 'MEG 095' 'MEG 096' + 'MEG 097' 'MEG 098' + 'MEG 099' 'MEG 100' + 'MEG 101' 'MEG 102' + 'MEG 103' 'MEG 104' + 'MEG 105' 'MEG 106' + 'MEG 107' 'MEG 108' + 'MEG 109' 'MEG 110' + 'MEG 111' 'MEG 112' + 'MEG 113' 'MEG 114' + 'MEG 115' 'MEG 116' + 'MEG 117' 'MEG 118' + 'MEG 119' 'MEG 120' + 'MEG 121' 'MEG 122' + }; + + case 'neuromag122alt' + % this is an alternative set of labels without a space in them + label = { + 'MEG001' 'MEG002' + 'MEG003' 'MEG004' + 'MEG005' 'MEG006' + 'MEG007' 'MEG008' + 'MEG009' 'MEG010' + 'MEG011' 'MEG012' + 'MEG013' 'MEG014' + 'MEG015' 'MEG016' + 'MEG017' 'MEG018' + 'MEG019' 'MEG020' + 'MEG021' 'MEG022' + 'MEG023' 'MEG024' + 'MEG025' 'MEG026' + 'MEG027' 'MEG028' + 'MEG029' 'MEG030' + 'MEG031' 'MEG032' + 'MEG033' 'MEG034' + 'MEG035' 'MEG036' + 'MEG037' 'MEG038' + 'MEG039' 'MEG040' + 'MEG041' 'MEG042' + 'MEG043' 'MEG044' + 'MEG045' 'MEG046' + 'MEG047' 'MEG048' + 'MEG049' 'MEG050' + 'MEG051' 'MEG052' + 'MEG053' 'MEG054' + 'MEG055' 'MEG056' + 'MEG057' 'MEG058' + 'MEG059' 'MEG060' + 'MEG061' 'MEG062' + 'MEG063' 'MEG064' + 'MEG065' 'MEG066' + 'MEG067' 'MEG068' + 'MEG069' 'MEG070' + 'MEG071' 'MEG072' + 'MEG073' 'MEG074' + 'MEG075' 'MEG076' + 'MEG077' 'MEG078' + 'MEG079' 'MEG080' + 'MEG081' 'MEG082' + 'MEG083' 'MEG084' + 'MEG085' 'MEG086' + 'MEG087' 'MEG088' + 'MEG089' 'MEG090' + 'MEG091' 'MEG092' + 'MEG093' 'MEG094' + 'MEG095' 'MEG096' + 'MEG097' 'MEG098' + 'MEG099' 'MEG100' + 'MEG101' 'MEG102' + 'MEG103' 'MEG104' + 'MEG105' 'MEG106' + 'MEG107' 'MEG108' + 'MEG109' 'MEG110' + 'MEG111' 'MEG112' + 'MEG113' 'MEG114' + 'MEG115' 'MEG116' + 'MEG117' 'MEG118' + 'MEG119' 'MEG120' + 'MEG121' 'MEG122' + }; + + case 'neuromag306' + label = { + 'MEG 0113' 'MEG 0112' 'MEG 0111' + 'MEG 0122' 'MEG 0123' 'MEG 0121' + 'MEG 0132' 'MEG 0133' 'MEG 0131' + 'MEG 0143' 'MEG 0142' 'MEG 0141' + 'MEG 0213' 'MEG 0212' 'MEG 0211' + 'MEG 0222' 'MEG 0223' 'MEG 0221' + 'MEG 0232' 'MEG 0233' 'MEG 0231' + 'MEG 0243' 'MEG 0242' 'MEG 0241' + 'MEG 0313' 'MEG 0312' 'MEG 0311' + 'MEG 0322' 'MEG 0323' 'MEG 0321' + 'MEG 0333' 'MEG 0332' 'MEG 0331' + 'MEG 0343' 'MEG 0342' 'MEG 0341' + 'MEG 0413' 'MEG 0412' 'MEG 0411' + 'MEG 0422' 'MEG 0423' 'MEG 0421' + 'MEG 0432' 'MEG 0433' 'MEG 0431' + 'MEG 0443' 'MEG 0442' 'MEG 0441' + 'MEG 0513' 'MEG 0512' 'MEG 0511' + 'MEG 0523' 'MEG 0522' 'MEG 0521' + 'MEG 0532' 'MEG 0533' 'MEG 0531' + 'MEG 0542' 'MEG 0543' 'MEG 0541' + 'MEG 0613' 'MEG 0612' 'MEG 0611' + 'MEG 0622' 'MEG 0623' 'MEG 0621' + 'MEG 0633' 'MEG 0632' 'MEG 0631' + 'MEG 0642' 'MEG 0643' 'MEG 0641' + 'MEG 0713' 'MEG 0712' 'MEG 0711' + 'MEG 0723' 'MEG 0722' 'MEG 0721' + 'MEG 0733' 'MEG 0732' 'MEG 0731' + 'MEG 0743' 'MEG 0742' 'MEG 0741' + 'MEG 0813' 'MEG 0812' 'MEG 0811' + 'MEG 0822' 'MEG 0823' 'MEG 0821' + 'MEG 0913' 'MEG 0912' 'MEG 0911' + 'MEG 0923' 'MEG 0922' 'MEG 0921' + 'MEG 0932' 'MEG 0933' 'MEG 0931' + 'MEG 0942' 'MEG 0943' 'MEG 0941' + 'MEG 1013' 'MEG 1012' 'MEG 1011' + 'MEG 1023' 'MEG 1022' 'MEG 1021' + 'MEG 1032' 'MEG 1033' 'MEG 1031' + 'MEG 1043' 'MEG 1042' 'MEG 1041' + 'MEG 1112' 'MEG 1113' 'MEG 1111' + 'MEG 1123' 'MEG 1122' 'MEG 1121' + 'MEG 1133' 'MEG 1132' 'MEG 1131' + 'MEG 1142' 'MEG 1143' 'MEG 1141' + 'MEG 1213' 'MEG 1212' 'MEG 1211' + 'MEG 1223' 'MEG 1222' 'MEG 1221' + 'MEG 1232' 'MEG 1233' 'MEG 1231' + 'MEG 1243' 'MEG 1242' 'MEG 1241' + 'MEG 1312' 'MEG 1313' 'MEG 1311' + 'MEG 1323' 'MEG 1322' 'MEG 1321' + 'MEG 1333' 'MEG 1332' 'MEG 1331' + 'MEG 1342' 'MEG 1343' 'MEG 1341' + 'MEG 1412' 'MEG 1413' 'MEG 1411' + 'MEG 1423' 'MEG 1422' 'MEG 1421' + 'MEG 1433' 'MEG 1432' 'MEG 1431' + 'MEG 1442' 'MEG 1443' 'MEG 1441' + 'MEG 1512' 'MEG 1513' 'MEG 1511' + 'MEG 1522' 'MEG 1523' 'MEG 1521' + 'MEG 1533' 'MEG 1532' 'MEG 1531' + 'MEG 1543' 'MEG 1542' 'MEG 1541' + 'MEG 1613' 'MEG 1612' 'MEG 1611' + 'MEG 1622' 'MEG 1623' 'MEG 1621' + 'MEG 1632' 'MEG 1633' 'MEG 1631' + 'MEG 1643' 'MEG 1642' 'MEG 1641' + 'MEG 1713' 'MEG 1712' 'MEG 1711' + 'MEG 1722' 'MEG 1723' 'MEG 1721' + 'MEG 1732' 'MEG 1733' 'MEG 1731' + 'MEG 1743' 'MEG 1742' 'MEG 1741' + 'MEG 1813' 'MEG 1812' 'MEG 1811' + 'MEG 1822' 'MEG 1823' 'MEG 1821' + 'MEG 1832' 'MEG 1833' 'MEG 1831' + 'MEG 1843' 'MEG 1842' 'MEG 1841' + 'MEG 1912' 'MEG 1913' 'MEG 1911' + 'MEG 1923' 'MEG 1922' 'MEG 1921' + 'MEG 1932' 'MEG 1933' 'MEG 1931' + 'MEG 1943' 'MEG 1942' 'MEG 1941' + 'MEG 2013' 'MEG 2012' 'MEG 2011' + 'MEG 2023' 'MEG 2022' 'MEG 2021' + 'MEG 2032' 'MEG 2033' 'MEG 2031' + 'MEG 2042' 'MEG 2043' 'MEG 2041' + 'MEG 2113' 'MEG 2112' 'MEG 2111' + 'MEG 2122' 'MEG 2123' 'MEG 2121' + 'MEG 2133' 'MEG 2132' 'MEG 2131' + 'MEG 2143' 'MEG 2142' 'MEG 2141' + 'MEG 2212' 'MEG 2213' 'MEG 2211' + 'MEG 2223' 'MEG 2222' 'MEG 2221' + 'MEG 2233' 'MEG 2232' 'MEG 2231' + 'MEG 2242' 'MEG 2243' 'MEG 2241' + 'MEG 2312' 'MEG 2313' 'MEG 2311' + 'MEG 2323' 'MEG 2322' 'MEG 2321' + 'MEG 2332' 'MEG 2333' 'MEG 2331' + 'MEG 2343' 'MEG 2342' 'MEG 2341' + 'MEG 2412' 'MEG 2413' 'MEG 2411' + 'MEG 2423' 'MEG 2422' 'MEG 2421' + 'MEG 2433' 'MEG 2432' 'MEG 2431' + 'MEG 2442' 'MEG 2443' 'MEG 2441' + 'MEG 2512' 'MEG 2513' 'MEG 2511' + 'MEG 2522' 'MEG 2523' 'MEG 2521' + 'MEG 2533' 'MEG 2532' 'MEG 2531' + 'MEG 2543' 'MEG 2542' 'MEG 2541' + 'MEG 2612' 'MEG 2613' 'MEG 2611' + 'MEG 2623' 'MEG 2622' 'MEG 2621' + 'MEG 2633' 'MEG 2632' 'MEG 2631' + 'MEG 2642' 'MEG 2643' 'MEG 2641' + }; + + case 'neuromag306alt' + % this is an alternative set of labels without a space in them + label = { + 'MEG0113' 'MEG0112' 'MEG0111' + 'MEG0122' 'MEG0123' 'MEG0121' + 'MEG0132' 'MEG0133' 'MEG0131' + 'MEG0143' 'MEG0142' 'MEG0141' + 'MEG0213' 'MEG0212' 'MEG0211' + 'MEG0222' 'MEG0223' 'MEG0221' + 'MEG0232' 'MEG0233' 'MEG0231' + 'MEG0243' 'MEG0242' 'MEG0241' + 'MEG0313' 'MEG0312' 'MEG0311' + 'MEG0322' 'MEG0323' 'MEG0321' + 'MEG0333' 'MEG0332' 'MEG0331' + 'MEG0343' 'MEG0342' 'MEG0341' + 'MEG0413' 'MEG0412' 'MEG0411' + 'MEG0422' 'MEG0423' 'MEG0421' + 'MEG0432' 'MEG0433' 'MEG0431' + 'MEG0443' 'MEG0442' 'MEG0441' + 'MEG0513' 'MEG0512' 'MEG0511' + 'MEG0523' 'MEG0522' 'MEG0521' + 'MEG0532' 'MEG0533' 'MEG0531' + 'MEG0542' 'MEG0543' 'MEG0541' + 'MEG0613' 'MEG0612' 'MEG0611' + 'MEG0622' 'MEG0623' 'MEG0621' + 'MEG0633' 'MEG0632' 'MEG0631' + 'MEG0642' 'MEG0643' 'MEG0641' + 'MEG0713' 'MEG0712' 'MEG0711' + 'MEG0723' 'MEG0722' 'MEG0721' + 'MEG0733' 'MEG0732' 'MEG0731' + 'MEG0743' 'MEG0742' 'MEG0741' + 'MEG0813' 'MEG0812' 'MEG0811' + 'MEG0822' 'MEG0823' 'MEG0821' + 'MEG0913' 'MEG0912' 'MEG0911' + 'MEG0923' 'MEG0922' 'MEG0921' + 'MEG0932' 'MEG0933' 'MEG0931' + 'MEG0942' 'MEG0943' 'MEG0941' + 'MEG1013' 'MEG1012' 'MEG1011' + 'MEG1023' 'MEG1022' 'MEG1021' + 'MEG1032' 'MEG1033' 'MEG1031' + 'MEG1043' 'MEG1042' 'MEG1041' + 'MEG1112' 'MEG1113' 'MEG1111' + 'MEG1123' 'MEG1122' 'MEG1121' + 'MEG1133' 'MEG1132' 'MEG1131' + 'MEG1142' 'MEG1143' 'MEG1141' + 'MEG1213' 'MEG1212' 'MEG1211' + 'MEG1223' 'MEG1222' 'MEG1221' + 'MEG1232' 'MEG1233' 'MEG1231' + 'MEG1243' 'MEG1242' 'MEG1241' + 'MEG1312' 'MEG1313' 'MEG1311' + 'MEG1323' 'MEG1322' 'MEG1321' + 'MEG1333' 'MEG1332' 'MEG1331' + 'MEG1342' 'MEG1343' 'MEG1341' + 'MEG1412' 'MEG1413' 'MEG1411' + 'MEG1423' 'MEG1422' 'MEG1421' + 'MEG1433' 'MEG1432' 'MEG1431' + 'MEG1442' 'MEG1443' 'MEG1441' + 'MEG1512' 'MEG1513' 'MEG1511' + 'MEG1522' 'MEG1523' 'MEG1521' + 'MEG1533' 'MEG1532' 'MEG1531' + 'MEG1543' 'MEG1542' 'MEG1541' + 'MEG1613' 'MEG1612' 'MEG1611' + 'MEG1622' 'MEG1623' 'MEG1621' + 'MEG1632' 'MEG1633' 'MEG1631' + 'MEG1643' 'MEG1642' 'MEG1641' + 'MEG1713' 'MEG1712' 'MEG1711' + 'MEG1722' 'MEG1723' 'MEG1721' + 'MEG1732' 'MEG1733' 'MEG1731' + 'MEG1743' 'MEG1742' 'MEG1741' + 'MEG1813' 'MEG1812' 'MEG1811' + 'MEG1822' 'MEG1823' 'MEG1821' + 'MEG1832' 'MEG1833' 'MEG1831' + 'MEG1843' 'MEG1842' 'MEG1841' + 'MEG1912' 'MEG1913' 'MEG1911' + 'MEG1923' 'MEG1922' 'MEG1921' + 'MEG1932' 'MEG1933' 'MEG1931' + 'MEG1943' 'MEG1942' 'MEG1941' + 'MEG2013' 'MEG2012' 'MEG2011' + 'MEG2023' 'MEG2022' 'MEG2021' + 'MEG2032' 'MEG2033' 'MEG2031' + 'MEG2042' 'MEG2043' 'MEG2041' + 'MEG2113' 'MEG2112' 'MEG2111' + 'MEG2122' 'MEG2123' 'MEG2121' + 'MEG2133' 'MEG2132' 'MEG2131' + 'MEG2143' 'MEG2142' 'MEG2141' + 'MEG2212' 'MEG2213' 'MEG2211' + 'MEG2223' 'MEG2222' 'MEG2221' + 'MEG2233' 'MEG2232' 'MEG2231' + 'MEG2242' 'MEG2243' 'MEG2241' + 'MEG2312' 'MEG2313' 'MEG2311' + 'MEG2323' 'MEG2322' 'MEG2321' + 'MEG2332' 'MEG2333' 'MEG2331' + 'MEG2343' 'MEG2342' 'MEG2341' + 'MEG2412' 'MEG2413' 'MEG2411' + 'MEG2423' 'MEG2422' 'MEG2421' + 'MEG2433' 'MEG2432' 'MEG2431' + 'MEG2442' 'MEG2443' 'MEG2441' + 'MEG2512' 'MEG2513' 'MEG2511' + 'MEG2522' 'MEG2523' 'MEG2521' + 'MEG2533' 'MEG2532' 'MEG2531' + 'MEG2543' 'MEG2542' 'MEG2541' + 'MEG2612' 'MEG2613' 'MEG2611' + 'MEG2623' 'MEG2622' 'MEG2621' + 'MEG2633' 'MEG2632' 'MEG2631' + 'MEG2642' 'MEG2643' 'MEG2641' + }; + + + case 'eeg1020' + label = { + 'Fp1' + 'Fpz' + 'Fp2' + 'F7' + 'F3' + 'Fz' + 'F4' + 'F8' + 'T7' + 'C3' + 'Cz' + 'C4' + 'T8' + 'P7' + 'P3' + 'Pz' + 'P4' + 'P8' + 'O1' + 'Oz' + 'O2'}; + + case 'eeg1010' + label = { + 'Fp1' + 'Fpz' + 'Fp2' + 'AF9' + 'AF7' + 'AF5' + 'AF3' + 'AF1' + 'AFz' + 'AF2' + 'AF4' + 'AF6' + 'AF8' + 'AF10' + 'F9' + 'F7' + 'F5' + 'F3' + 'F1' + 'Fz' + 'F2' + 'F4' + 'F6' + 'F8' + 'F10' + 'FT9' + 'FT7' + 'FC5' + 'FC3' + 'FC1' + 'FCz' + 'FC2' + 'FC4' + 'FC6' + 'FT8' + 'FT10' + 'T9' + 'T7' + 'C5' + 'C3' + 'C1' + 'Cz' + 'C2' + 'C4' + 'C6' + 'T8' + 'T10' + 'TP9' + 'TP7' + 'CP5' + 'CP3' + 'CP1' + 'CPz' + 'CP2' + 'CP4' + 'CP6' + 'TP8' + 'TP10' + 'P9' + 'P7' + 'P5' + 'P3' + 'P1' + 'Pz' + 'P2' + 'P4' + 'P6' + 'P8' + 'P10' + 'PO9' + 'PO7' + 'PO5' + 'PO3' + 'PO1' + 'POz' + 'PO2' + 'PO4' + 'PO6' + 'PO8' + 'PO10' + 'O1' + 'Oz' + 'O2' + 'I1' + 'Iz' + 'I2' + }; + + case 'eeg1005' + label = { + 'Fp1' + 'Fpz' + 'Fp2' + 'AF9' + 'AF7' + 'AF5' + 'AF3' + 'AF1' + 'AFz' + 'AF2' + 'AF4' + 'AF6' + 'AF8' + 'AF10' + 'F9' + 'F7' + 'F5' + 'F3' + 'F1' + 'Fz' + 'F2' + 'F4' + 'F6' + 'F8' + 'F10' + 'FT9' + 'FT7' + 'FC5' + 'FC3' + 'FC1' + 'FCz' + 'FC2' + 'FC4' + 'FC6' + 'FT8' + 'FT10' + 'T9' + 'T7' + 'C5' + 'C3' + 'C1' + 'Cz' + 'C2' + 'C4' + 'C6' + 'T8' + 'T10' + 'TP9' + 'TP7' + 'CP5' + 'CP3' + 'CP1' + 'CPz' + 'CP2' + 'CP4' + 'CP6' + 'TP8' + 'TP10' + 'P9' + 'P7' + 'P5' + 'P3' + 'P1' + 'Pz' + 'P2' + 'P4' + 'P6' + 'P8' + 'P10' + 'PO9' + 'PO7' + 'PO5' + 'PO3' + 'PO1' + 'POz' + 'PO2' + 'PO4' + 'PO6' + 'PO8' + 'PO10' + 'O1' + 'Oz' + 'O2' + 'I1' + 'Iz' + 'I2' + 'AFp9h' + 'AFp7h' + 'AFp5h' + 'AFp3h' + 'AFp1h' + 'AFp2h' + 'AFp4h' + 'AFp6h' + 'AFp8h' + 'AFp10h' + 'AFF9h' + 'AFF7h' + 'AFF5h' + 'AFF3h' + 'AFF1h' + 'AFF2h' + 'AFF4h' + 'AFF6h' + 'AFF8h' + 'AFF10h' + 'FFT9h' + 'FFT7h' + 'FFC5h' + 'FFC3h' + 'FFC1h' + 'FFC2h' + 'FFC4h' + 'FFC6h' + 'FFT8h' + 'FFT10h' + 'FTT9h' + 'FTT7h' + 'FCC5h' + 'FCC3h' + 'FCC1h' + 'FCC2h' + 'FCC4h' + 'FCC6h' + 'FTT8h' + 'FTT10h' + 'TTP9h' + 'TTP7h' + 'CCP5h' + 'CCP3h' + 'CCP1h' + 'CCP2h' + 'CCP4h' + 'CCP6h' + 'TTP8h' + 'TTP10h' + 'TPP9h' + 'TPP7h' + 'CPP5h' + 'CPP3h' + 'CPP1h' + 'CPP2h' + 'CPP4h' + 'CPP6h' + 'TPP8h' + 'TPP10h' + 'PPO9h' + 'PPO7h' + 'PPO5h' + 'PPO3h' + 'PPO1h' + 'PPO2h' + 'PPO4h' + 'PPO6h' + 'PPO8h' + 'PPO10h' + 'POO9h' + 'POO7h' + 'POO5h' + 'POO3h' + 'POO1h' + 'POO2h' + 'POO4h' + 'POO6h' + 'POO8h' + 'POO10h' + 'OI1h' + 'OI2h' + 'Fp1h' + 'Fp2h' + 'AF9h' + 'AF7h' + 'AF5h' + 'AF3h' + 'AF1h' + 'AF2h' + 'AF4h' + 'AF6h' + 'AF8h' + 'AF10h' + 'F9h' + 'F7h' + 'F5h' + 'F3h' + 'F1h' + 'F2h' + 'F4h' + 'F6h' + 'F8h' + 'F10h' + 'FT9h' + 'FT7h' + 'FC5h' + 'FC3h' + 'FC1h' + 'FC2h' + 'FC4h' + 'FC6h' + 'FT8h' + 'FT10h' + 'T9h' + 'T7h' + 'C5h' + 'C3h' + 'C1h' + 'C2h' + 'C4h' + 'C6h' + 'T8h' + 'T10h' + 'TP9h' + 'TP7h' + 'CP5h' + 'CP3h' + 'CP1h' + 'CP2h' + 'CP4h' + 'CP6h' + 'TP8h' + 'TP10h' + 'P9h' + 'P7h' + 'P5h' + 'P3h' + 'P1h' + 'P2h' + 'P4h' + 'P6h' + 'P8h' + 'P10h' + 'PO9h' + 'PO7h' + 'PO5h' + 'PO3h' + 'PO1h' + 'PO2h' + 'PO4h' + 'PO6h' + 'PO8h' + 'PO10h' + 'O1h' + 'O2h' + 'I1h' + 'I2h' + 'AFp9' + 'AFp7' + 'AFp5' + 'AFp3' + 'AFp1' + 'AFpz' + 'AFp2' + 'AFp4' + 'AFp6' + 'AFp8' + 'AFp10' + 'AFF9' + 'AFF7' + 'AFF5' + 'AFF3' + 'AFF1' + 'AFFz' + 'AFF2' + 'AFF4' + 'AFF6' + 'AFF8' + 'AFF10' + 'FFT9' + 'FFT7' + 'FFC5' + 'FFC3' + 'FFC1' + 'FFCz' + 'FFC2' + 'FFC4' + 'FFC6' + 'FFT8' + 'FFT10' + 'FTT9' + 'FTT7' + 'FCC5' + 'FCC3' + 'FCC1' + 'FCCz' + 'FCC2' + 'FCC4' + 'FCC6' + 'FTT8' + 'FTT10' + 'TTP9' + 'TTP7' + 'CCP5' + 'CCP3' + 'CCP1' + 'CCPz' + 'CCP2' + 'CCP4' + 'CCP6' + 'TTP8' + 'TTP10' + 'TPP9' + 'TPP7' + 'CPP5' + 'CPP3' + 'CPP1' + 'CPPz' + 'CPP2' + 'CPP4' + 'CPP6' + 'TPP8' + 'TPP10' + 'PPO9' + 'PPO7' + 'PPO5' + 'PPO3' + 'PPO1' + 'PPOz' + 'PPO2' + 'PPO4' + 'PPO6' + 'PPO8' + 'PPO10' + 'POO9' + 'POO7' + 'POO5' + 'POO3' + 'POO1' + 'POOz' + 'POO2' + 'POO4' + 'POO6' + 'POO8' + 'POO10' + 'OI1' + 'OIz' + 'OI2' + }; + + case 'ext1020' + % start with the eeg1005 list + label = { + 'Fp1' + 'Fpz' + 'Fp2' + 'AF9' + 'AF7' + 'AF5' + 'AF3' + 'AF1' + 'AFz' + 'AF2' + 'AF4' + 'AF6' + 'AF8' + 'AF10' + 'F9' + 'F7' + 'F5' + 'F3' + 'F1' + 'Fz' + 'F2' + 'F4' + 'F6' + 'F8' + 'F10' + 'FT9' + 'FT7' + 'FC5' + 'FC3' + 'FC1' + 'FCz' + 'FC2' + 'FC4' + 'FC6' + 'FT8' + 'FT10' + 'T9' + 'T7' + 'C5' + 'C3' + 'C1' + 'Cz' + 'C2' + 'C4' + 'C6' + 'T8' + 'T10' + 'TP9' + 'TP7' + 'CP5' + 'CP3' + 'CP1' + 'CPz' + 'CP2' + 'CP4' + 'CP6' + 'TP8' + 'TP10' + 'P9' + 'P7' + 'P5' + 'P3' + 'P1' + 'Pz' + 'P2' + 'P4' + 'P6' + 'P8' + 'P10' + 'PO9' + 'PO7' + 'PO5' + 'PO3' + 'PO1' + 'POz' + 'PO2' + 'PO4' + 'PO6' + 'PO8' + 'PO10' + 'O1' + 'Oz' + 'O2' + 'I1' + 'Iz' + 'I2' + 'AFp9h' + 'AFp7h' + 'AFp5h' + 'AFp3h' + 'AFp1h' + 'AFp2h' + 'AFp4h' + 'AFp6h' + 'AFp8h' + 'AFp10h' + 'AFF9h' + 'AFF7h' + 'AFF5h' + 'AFF3h' + 'AFF1h' + 'AFF2h' + 'AFF4h' + 'AFF6h' + 'AFF8h' + 'AFF10h' + 'FFT9h' + 'FFT7h' + 'FFC5h' + 'FFC3h' + 'FFC1h' + 'FFC2h' + 'FFC4h' + 'FFC6h' + 'FFT8h' + 'FFT10h' + 'FTT9h' + 'FTT7h' + 'FCC5h' + 'FCC3h' + 'FCC1h' + 'FCC2h' + 'FCC4h' + 'FCC6h' + 'FTT8h' + 'FTT10h' + 'TTP9h' + 'TTP7h' + 'CCP5h' + 'CCP3h' + 'CCP1h' + 'CCP2h' + 'CCP4h' + 'CCP6h' + 'TTP8h' + 'TTP10h' + 'TPP9h' + 'TPP7h' + 'CPP5h' + 'CPP3h' + 'CPP1h' + 'CPP2h' + 'CPP4h' + 'CPP6h' + 'TPP8h' + 'TPP10h' + 'PPO9h' + 'PPO7h' + 'PPO5h' + 'PPO3h' + 'PPO1h' + 'PPO2h' + 'PPO4h' + 'PPO6h' + 'PPO8h' + 'PPO10h' + 'POO9h' + 'POO7h' + 'POO5h' + 'POO3h' + 'POO1h' + 'POO2h' + 'POO4h' + 'POO6h' + 'POO8h' + 'POO10h' + 'OI1h' + 'OI2h' + 'Fp1h' + 'Fp2h' + 'AF9h' + 'AF7h' + 'AF5h' + 'AF3h' + 'AF1h' + 'AF2h' + 'AF4h' + 'AF6h' + 'AF8h' + 'AF10h' + 'F9h' + 'F7h' + 'F5h' + 'F3h' + 'F1h' + 'F2h' + 'F4h' + 'F6h' + 'F8h' + 'F10h' + 'FT9h' + 'FT7h' + 'FC5h' + 'FC3h' + 'FC1h' + 'FC2h' + 'FC4h' + 'FC6h' + 'FT8h' + 'FT10h' + 'T9h' + 'T7h' + 'C5h' + 'C3h' + 'C1h' + 'C2h' + 'C4h' + 'C6h' + 'T8h' + 'T10h' + 'TP9h' + 'TP7h' + 'CP5h' + 'CP3h' + 'CP1h' + 'CP2h' + 'CP4h' + 'CP6h' + 'TP8h' + 'TP10h' + 'P9h' + 'P7h' + 'P5h' + 'P3h' + 'P1h' + 'P2h' + 'P4h' + 'P6h' + 'P8h' + 'P10h' + 'PO9h' + 'PO7h' + 'PO5h' + 'PO3h' + 'PO1h' + 'PO2h' + 'PO4h' + 'PO6h' + 'PO8h' + 'PO10h' + 'O1h' + 'O2h' + 'I1h' + 'I2h' + 'AFp9' + 'AFp7' + 'AFp5' + 'AFp3' + 'AFp1' + 'AFpz' + 'AFp2' + 'AFp4' + 'AFp6' + 'AFp8' + 'AFp10' + 'AFF9' + 'AFF7' + 'AFF5' + 'AFF3' + 'AFF1' + 'AFFz' + 'AFF2' + 'AFF4' + 'AFF6' + 'AFF8' + 'AFF10' + 'FFT9' + 'FFT7' + 'FFC5' + 'FFC3' + 'FFC1' + 'FFCz' + 'FFC2' + 'FFC4' + 'FFC6' + 'FFT8' + 'FFT10' + 'FTT9' + 'FTT7' + 'FCC5' + 'FCC3' + 'FCC1' + 'FCCz' + 'FCC2' + 'FCC4' + 'FCC6' + 'FTT8' + 'FTT10' + 'TTP9' + 'TTP7' + 'CCP5' + 'CCP3' + 'CCP1' + 'CCPz' + 'CCP2' + 'CCP4' + 'CCP6' + 'TTP8' + 'TTP10' + 'TPP9' + 'TPP7' + 'CPP5' + 'CPP3' + 'CPP1' + 'CPPz' + 'CPP2' + 'CPP4' + 'CPP6' + 'TPP8' + 'TPP10' + 'PPO9' + 'PPO7' + 'PPO5' + 'PPO3' + 'PPO1' + 'PPOz' + 'PPO2' + 'PPO4' + 'PPO6' + 'PPO8' + 'PPO10' + 'POO9' + 'POO7' + 'POO5' + 'POO3' + 'POO1' + 'POOz' + 'POO2' + 'POO4' + 'POO6' + 'POO8' + 'POO10' + 'OI1' + 'OIz' + 'OI2' + }; + + % Add also alternative labels that are used in some systems + label = cat(1, label, {'A1' 'A2' 'M1' 'M2' 'T3' 'T4' 'T5' 'T6'}'); + + % This is to account for all variants of case in 1020 systems + label = unique(cat(1, label, upper(label), lower(label))); + + case 'biosemi64' + label = { + 'A1' + 'A2' + 'A3' + 'A4' + 'A5' + 'A6' + 'A7' + 'A8' + 'A9' + 'A10' + 'A11' + 'A12' + 'A13' + 'A14' + 'A15' + 'A16' + 'A17' + 'A18' + 'A19' + 'A20' + 'A21' + 'A22' + 'A23' + 'A24' + 'A25' + 'A26' + 'A27' + 'A28' + 'A29' + 'A30' + 'A31' + 'A32' + 'B1' + 'B2' + 'B3' + 'B4' + 'B5' + 'B6' + 'B7' + 'B8' + 'B9' + 'B10' + 'B11' + 'B12' + 'B13' + 'B14' + 'B15' + 'B16' + 'B17' + 'B18' + 'B19' + 'B20' + 'B21' + 'B22' + 'B23' + 'B24' + 'B25' + 'B26' + 'B27' + 'B28' + 'B29' + 'B30' + 'B31' + 'B32' + }; + + case 'biosemi128' + label = { + 'A1' + 'A2' + 'A3' + 'A4' + 'A5' + 'A6' + 'A7' + 'A8' + 'A9' + 'A10' + 'A11' + 'A12' + 'A13' + 'A14' + 'A15' + 'A16' + 'A17' + 'A18' + 'A19' + 'A20' + 'A21' + 'A22' + 'A23' + 'A24' + 'A25' + 'A26' + 'A27' + 'A28' + 'A29' + 'A30' + 'A31' + 'A32' + 'B1' + 'B2' + 'B3' + 'B4' + 'B5' + 'B6' + 'B7' + 'B8' + 'B9' + 'B10' + 'B11' + 'B12' + 'B13' + 'B14' + 'B15' + 'B16' + 'B17' + 'B18' + 'B19' + 'B20' + 'B21' + 'B22' + 'B23' + 'B24' + 'B25' + 'B26' + 'B27' + 'B28' + 'B29' + 'B30' + 'B31' + 'B32' + 'C1' + 'C2' + 'C3' + 'C4' + 'C5' + 'C6' + 'C7' + 'C8' + 'C9' + 'C10' + 'C11' + 'C12' + 'C13' + 'C14' + 'C15' + 'C16' + 'C17' + 'C18' + 'C19' + 'C20' + 'C21' + 'C22' + 'C23' + 'C24' + 'C25' + 'C26' + 'C27' + 'C28' + 'C29' + 'C30' + 'C31' + 'C32' + 'D1' + 'D2' + 'D3' + 'D4' + 'D5' + 'D6' + 'D7' + 'D8' + 'D9' + 'D10' + 'D11' + 'D12' + 'D13' + 'D14' + 'D15' + 'D16' + 'D17' + 'D18' + 'D19' + 'D20' + 'D21' + 'D22' + 'D23' + 'D24' + 'D25' + 'D26' + 'D27' + 'D28' + 'D29' + 'D30' + 'D31' + 'D32' + }; + + case 'biosemi256' + label = { + 'A1' + 'A2' + 'A3' + 'A4' + 'A5' + 'A6' + 'A7' + 'A8' + 'A9' + 'A10' + 'A11' + 'A12' + 'A13' + 'A14' + 'A15' + 'A16' + 'A17' + 'A18' + 'A19' + 'A20' + 'A21' + 'A22' + 'A23' + 'A24' + 'A25' + 'A26' + 'A27' + 'A28' + 'A29' + 'A30' + 'A31' + 'A32' + 'B1' + 'B2' + 'B3' + 'B4' + 'B5' + 'B6' + 'B7' + 'B8' + 'B9' + 'B10' + 'B11' + 'B12' + 'B13' + 'B14' + 'B15' + 'B16' + 'B17' + 'B18' + 'B19' + 'B20' + 'B21' + 'B22' + 'B23' + 'B24' + 'B25' + 'B26' + 'B27' + 'B28' + 'B29' + 'B30' + 'B31' + 'B32' + 'C1' + 'C2' + 'C3' + 'C4' + 'C5' + 'C6' + 'C7' + 'C8' + 'C9' + 'C10' + 'C11' + 'C12' + 'C13' + 'C14' + 'C15' + 'C16' + 'C17' + 'C18' + 'C19' + 'C20' + 'C21' + 'C22' + 'C23' + 'C24' + 'C25' + 'C26' + 'C27' + 'C28' + 'C29' + 'C30' + 'C31' + 'C32' + 'D1' + 'D2' + 'D3' + 'D4' + 'D5' + 'D6' + 'D7' + 'D8' + 'D9' + 'D10' + 'D11' + 'D12' + 'D13' + 'D14' + 'D15' + 'D16' + 'D17' + 'D18' + 'D19' + 'D20' + 'D21' + 'D22' + 'D23' + 'D24' + 'D25' + 'D26' + 'D27' + 'D28' + 'D29' + 'D30' + 'D31' + 'D32' + 'E1' + 'E2' + 'E3' + 'E4' + 'E5' + 'E6' + 'E7' + 'E8' + 'E9' + 'E10' + 'E11' + 'E12' + 'E13' + 'E14' + 'E15' + 'E16' + 'E17' + 'E18' + 'E19' + 'E20' + 'E21' + 'E22' + 'E23' + 'E24' + 'E25' + 'E26' + 'E27' + 'E28' + 'E29' + 'E30' + 'E31' + 'E32' + 'F1' + 'F2' + 'F3' + 'F4' + 'F5' + 'F6' + 'F7' + 'F8' + 'F9' + 'F10' + 'F11' + 'F12' + 'F13' + 'F14' + 'F15' + 'F16' + 'F17' + 'F18' + 'F19' + 'F20' + 'F21' + 'F22' + 'F23' + 'F24' + 'F25' + 'F26' + 'F27' + 'F28' + 'F29' + 'F30' + 'F31' + 'F32' + 'G1' + 'G2' + 'G3' + 'G4' + 'G5' + 'G6' + 'G7' + 'G8' + 'G9' + 'G10' + 'G11' + 'G12' + 'G13' + 'G14' + 'G15' + 'G16' + 'G17' + 'G18' + 'G19' + 'G20' + 'G21' + 'G22' + 'G23' + 'G24' + 'G25' + 'G26' + 'G27' + 'G28' + 'G29' + 'G30' + 'G31' + 'G32' + 'H1' + 'H2' + 'H3' + 'H4' + 'H5' + 'H6' + 'H7' + 'H8' + 'H9' + 'H10' + 'H11' + 'H12' + 'H13' + 'H14' + 'H15' + 'H16' + 'H17' + 'H18' + 'H19' + 'H20' + 'H21' + 'H22' + 'H23' + 'H24' + 'H25' + 'H26' + 'H27' + 'H28' + 'H29' + 'H30' + 'H31' + 'H32' + }; + + case 'egi32' + label = cell(32, 1); + for i = 1:32 + label{i} = sprintf('e%d', i); + end + + case 'egi64' + label = cell(64, 1); + for i = 1:64 + label{i} = sprintf('e%d', i); + end + + case 'egi128' + label = cell(128, 1); + for i = 1:128 + label{i} = sprintf('e%d', i); + end + + case 'egi256' + label = cell(256, 1); + for i = 1:256 + label{i} = sprintf('e%d', i); + end + + case 'itab153' + label = cell(153,1); + for i=1:153 + % channel names start counting at zero + label{i} = sprintf('MAG_%03d', i-1); + end + + case 'itab153_planar' + label = cell(153,2); + for i=1:153 + % channel names start counting at zero + label{i,1} = sprintf('MAG_%03d_dH', i-1); + label{i,2} = sprintf('MAG_%03d_dV', i-1); + end + + case 'yokogawa160' + % this should be consistent with read_yokogawa_header, with + % ft_channelselection and with yokogawa2grad + label = cell(160,1); + for i=1:160 + label{i} = sprintf('AG%03d', i); + end + + case 'yokogawa160_planar' + % this should be consistent with read_yokogawa_header, with + % ft_channelselection and with yokogawa2grad + label = cell(160,2); + for i=1:160 + label{i,1} = sprintf('AG%03d_dH', i); + label{i,2} = sprintf('AG%03d_dV', i); + end + + case 'electrode' + % there is no default set of electrode labels, by input type 'electrode' should not result in an error + label = {}; + + otherwise + error('the requested sensor type is not supported'); +end + +% remember the current input and output arguments, so that they can be +% reused on a subsequent call in case the same input argument is given +current_argout = {label}; +if isempty(previous_argin) + previous_argin = current_argin; + previous_argout = current_argout; +end + diff --git a/external/fieldtrip/forward/ft_senstype.m b/external/fieldtrip/forward/ft_senstype.m new file mode 100644 index 0000000..ade2190 --- /dev/null +++ b/external/fieldtrip/forward/ft_senstype.m @@ -0,0 +1,362 @@ +function [type] = ft_senstype(input, desired) + +% FT_SENSTYPE determines the type of sensors by looking at the channel names +% and comparing them with predefined lists. +% +% Use as +% [type] = ft_senstype(sens) +% to get a string describing the type, or +% [flag] = ft_senstype(sens, desired) +% to get a boolean value. +% +% The output type can be any of the following +% 'electrode' +% 'magnetometer' +% 'biosemi64' +% 'biosemi128' +% 'biosemi256' +% 'bti148' +% 'bti148_planar' +% 'bti248' +% 'bti248_planar' +% 'ctf151' +% 'ctf151_planar' +% 'ctf275' +% 'ctf275_planar' +% 'egi128' +% 'egi256' +% 'egi32' +% 'egi64' +% 'ext1020' +% 'neuromag122' +% 'neuromag306' +% 'yokogawa160' +% 'yokogawa160_planar' +% 'plexon' +% 'itab153' +% 'itab153_planar' +% +% The optional input argument for the desired type can be any of the above, +% or any of the following +% 'eeg' +% 'meg' +% 'meg_planar' +% 'meg_axial' +% 'ctf' +% 'bti' +% 'neuromag' +% 'yokogawa' +% +% Besides specifiying a grad or elec structure as input, also allowed is +% giving a data structure containing a grad or elec field, or giving a list +% of channel names (as cell-arrray). I.e. assuming a FieldTrip data +% structure, all of the following calls would be correct. +% ft_senstype(data) +% ft_senstype(data.label) +% ft_senstype(data.grad) +% ft_senstype(data.grad.label) +% +% See also FT_SENSLABEL, FT_CHANTYPE, FT_READ_SENS, FT_COMPUTE_LEADFIELD + +% Copyright (C) 2007-2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_senstype.m 1290 2010-06-29 14:10:50Z roboos $ + +% these are for remembering the type on subsequent calls with the same input arguments +persistent previous_argin previous_argout + +if iscell(input) && numel(input)<4 && ~all(cellfun(@ischar, input)) + % this might represent combined EEG, ECoG and/or MEG + type = cell(size(input)); + if nargin<2 + desired = cell(size(input)); % empty elements + end + for i=1:numel(input) + type{i} = ft_senstype(input{i}, desired{i}); + end + return +end + +if nargin<2 + % ensure that all input arguments are defined + desired = []; +end + +current_argin = {input, desired}; +if isequal(current_argin, previous_argin) + % don't do the type detection again, but return the previous values from + % cache + type = previous_argout{1}; + return +end + +% FIXME the detection of the type of input structure should perhaps be done using the datatype function +isdata = isa(input, 'struct') && isfield(input, 'hdr'); +isheader = isa(input, 'struct') && isfield(input, 'label') && isfield(input, 'Fs'); +isgrad = isa(input, 'struct') && isfield(input, 'label') && isfield(input, 'pnt') && isfield(input, 'ori'); +iselec = isa(input, 'struct') && isfield(input, 'label') && isfield(input, 'pnt') && ~isfield(input, 'ori'); +islabel = isa(input, 'cell') && ~isempty(input) && isa(input{1}, 'char'); + +if ~isdata && ~isheader + % timelock or freq structures don't have the header structure + % the header is also removed from raw data after megrealign + % the gradiometer definition is lost after megplanar+combineplanar + isdata = isa(input, 'struct') && (isfield(input, 'grad') || isfield(input, 'elec') || isfield(input, 'label')); +end + +% the input may be a data structure which then contains a grad/elec structure, a header or only the labels +if isdata + % preferably look at the data and not the header for the grad, because it might be re-balanced and/or planar + if isfield(input, 'grad') + sens = input.grad; + isgrad = true; + elseif issubfield(input, 'hdr.grad') + sens = input.hdr.grad; + isgrad = true; + elseif issubfield(input, 'hdr.elec') + sens = input.hdr.elec; + iselec = true; + elseif isfield(input, 'elec') + sens = input.elec; + iselec = true; + elseif issubfield(input, 'hdr.label') + sens.label = input.hdr.label; + islabel = true; + elseif isfield(input, 'label') + sens.label = input.label; + islabel = true; + end +elseif isheader + if isfield(input, 'grad') + sens = input.grad; + isgrad = true; + elseif isfield(input, 'elec') + sens = input.elec; + iselec = true; + elseif isfield(input, 'label') + sens.label = input.label; + islabel = true; + end +elseif isgrad + sens = input; +elseif iselec + sens = input; +elseif islabel + sens.label = input; +else + sens = []; +end + +if isfield(input, 'type') + % preferably the structure specifies its own type + type = input.type; + +elseif issubfield(input, 'orig.FileHeader') && issubfield(input, 'orig.VarHeader') + % this is a complete header that was read from a Plexon *.nex file using read_plexon_nex + type = 'plexon'; + +elseif issubfield(input, 'orig.stname') + % this is a complete header that was read from an ITAB dataset + type = 'itab'; + +elseif issubfield(input, 'orig.sys_name') + % this is a complete header that was read from a Yokogawa dataset + type = 'yokogawa160'; + +else + % start with unknown, then try to determine the proper type by looking at the labels + type = 'unknown'; + + if isgrad + % probably this is MEG, determine the type of magnetometer/gradiometer system + % note that the order here is important: first check whether it matches a 275 channel system, then a 151 channel system, since the 151 channels are a subset of the 275 + if (mean(ismember(ft_senslabel('ctf275'), sens.label)) > 0.8) + type = 'ctf275'; + elseif (mean(ismember(ft_senslabel('ctfheadloc'), sens.label)) > 0.8) % look at the head localization channels + type = 'ctf275'; + elseif (mean(ismember(ft_senslabel('ctf151'), sens.label)) > 0.8) + type = 'ctf151'; + elseif (mean(ismember(ft_senslabel('ctf64'), sens.label)) > 0.8) + type = 'ctf64'; + elseif (mean(ismember(ft_senslabel('ctf275_planar'), sens.label)) > 0.8) + type = 'ctf275_planar'; + elseif (mean(ismember(ft_senslabel('ctf151_planar'), sens.label)) > 0.8) + type = 'ctf151_planar'; + elseif (mean(ismember(ft_senslabel('bti248'), sens.label)) > 0.8) + type = 'bti248'; + elseif (mean(ismember(ft_senslabel('bti148'), sens.label)) > 0.8) + type = 'bti148'; + elseif (mean(ismember(ft_senslabel('bti248_planar'), sens.label)) > 0.8) + type = 'bti248_planar'; + elseif (mean(ismember(ft_senslabel('bti148_planar'), sens.label)) > 0.8) + type = 'bti148_planar'; + elseif (mean(ismember(ft_senslabel('itab153'), sens.label)) > 0.8) + type = 'itab153'; + elseif (mean(ismember(ft_senslabel('itab153_planar'), sens.label)) > 0.8) + type = 'itab153_planar'; + elseif (mean(ismember(ft_senslabel('yokogawa160'), sens.label)) > 0.4) + type = 'yokogawa160'; + elseif (mean(ismember(ft_senslabel('yokogawa160_planar'), sens.label)) > 0.4) + type = 'yokogawa160_planar'; + elseif (mean(ismember(ft_senslabel('neuromag306'), sens.label)) > 0.8) + type = 'neuromag306'; + elseif (mean(ismember(ft_senslabel('neuromag306alt'),sens.label)) > 0.8) % an alternative set without spaces in the name + type = 'neuromag306'; + elseif (mean(ismember(ft_senslabel('neuromag122'), sens.label)) > 0.8) + type = 'neuromag122'; + elseif (mean(ismember(ft_senslabel('neuromag122alt'),sens.label)) > 0.8) % an alternative set without spaces in the name + type = 'neuromag122'; + elseif any(ismember(ft_senslabel('btiref'), sens.label)) + type = 'bti'; % it might be 148 or 248 channels + elseif any(ismember(ft_senslabel('ctfref'), sens.label)) + type = 'ctf'; % it might be 151 or 275 channels + elseif isfield(sens, 'pnt') && isfield(sens, 'ori') && numel(sens.label)==size(sens.pnt,1) + warning('could be Yokogawa system'); + type = 'magnetometer'; + else + warning('could be Yokogawa system'); + type = 'meg'; + end + + elseif iselec + % probably this is EEG + if (mean(ismember(ft_senslabel('biosemi256'), sens.label)) > 0.8) + type = 'biosemi256'; + elseif (mean(ismember(ft_senslabel('biosemi128'), sens.label)) > 0.8) + type = 'biosemi128'; + elseif (mean(ismember(ft_senslabel('biosemi64'), sens.label)) > 0.8) + type = 'biosemi64'; + elseif (mean(ismember(ft_senslabel('egi256'), sens.label)) > 0.8) + type = 'egi256'; + elseif (mean(ismember(ft_senslabel('egi128'), sens.label)) > 0.8) + type = 'egi128'; + elseif (mean(ismember(ft_senslabel('egi64'), sens.label)) > 0.8) + type = 'egi64'; + elseif (mean(ismember(ft_senslabel('egi32'), sens.label)) > 0.8) + type = 'egi32'; + elseif (sum(ismember(sens.label, ft_senslabel('eeg1005'))) > 10) % Otherwise it's not even worth recognizing + type = 'ext1020'; + else + type = 'electrode'; + end + + elseif islabel + % look only at the channel labels + if (mean(ismember(ft_senslabel('ctf275'), sens.label)) > 0.8) + type = 'ctf275'; + elseif (mean(ismember(ft_senslabel('ctfheadloc'), sens.label)) > 0.8) % look at the head localization channels + type = 'ctf275'; + elseif (mean(ismember(ft_senslabel('ctf151'), sens.label)) > 0.8) + type = 'ctf151'; + elseif (mean(ismember(ft_senslabel('ctf64'), sens.label)) > 0.8) + type = 'ctf64'; + elseif (mean(ismember(ft_senslabel('ctf275_planar'), sens.label)) > 0.8) + type = 'ctf275_planar'; + elseif (mean(ismember(ft_senslabel('ctf151_planar'), sens.label)) > 0.8) + type = 'ctf151_planar'; + elseif (mean(ismember(ft_senslabel('bti248'), sens.label)) > 0.8) + type = 'bti248'; + elseif (mean(ismember(ft_senslabel('bti148'), sens.label)) > 0.8) + type = 'bti148'; + elseif (mean(ismember(ft_senslabel('bti248_planar'), sens.label)) > 0.8) + type = 'bti248_planar'; + elseif (mean(ismember(ft_senslabel('bti148_planar'), sens.label)) > 0.8) + type = 'bti148_planar'; + elseif (mean(ismember(ft_senslabel('itab153'), sens.label)) > 0.8) + type = 'itab153'; + elseif (mean(ismember(ft_senslabel('itab153_planar'), sens.label)) > 0.8) + type = 'itab153_planar'; + elseif (mean(ismember(ft_senslabel('yokogawa160'), sens.label)) > 0.4) + type = 'yokogawa160'; + elseif (mean(ismember(ft_senslabel('yokogawa160_planar'), sens.label)) > 0.4) + type = 'yokogawa160_planar'; + elseif (mean(ismember(ft_senslabel('neuromag306'), sens.label)) > 0.8) + type = 'neuromag306'; + elseif (mean(ismember(ft_senslabel('neuromag306alt'),sens.label)) > 0.8) % an alternative set without spaces in the name + type = 'neuromag306'; + elseif (mean(ismember(ft_senslabel('neuromag122'), sens.label)) > 0.8) + type = 'neuromag122'; + elseif (mean(ismember(ft_senslabel('neuromag122alt'),sens.label)) > 0.8) % an alternative set without spaces in the name + type = 'neuromag122'; + elseif (mean(ismember(ft_senslabel('biosemi256'), sens.label)) > 0.8) + type = 'biosemi256'; + elseif (mean(ismember(ft_senslabel('biosemi128'), sens.label)) > 0.8) + type = 'biosemi128'; + elseif (mean(ismember(ft_senslabel('biosemi64'), sens.label)) > 0.8) + type = 'biosemi64'; + elseif (mean(ismember(ft_senslabel('egi256'), sens.label)) > 0.8) + type = 'egi256'; + elseif (mean(ismember(ft_senslabel('egi128'), sens.label)) > 0.8) + type = 'egi128'; + elseif (mean(ismember(ft_senslabel('egi64'), sens.label)) > 0.8) + type = 'egi64'; + elseif (mean(ismember(ft_senslabel('egi32'), sens.label)) > 0.8) + type = 'egi32'; + elseif (sum(ismember(sens.label, ft_senslabel('eeg1005'))) > 10) % Otherwise it's not even worth recognizing + type = 'ext1020'; + elseif any(ismember(ft_senslabel('btiref'), sens.label)) + type = 'bti'; % it might be 148 or 248 channels + elseif any(ismember(ft_senslabel('ctfref'), sens.label)) + type = 'ctf'; % it might be 151 or 275 channels + end + + end % look at label, ori and/or pnt +end % if isfield(sens, 'type') + +if ~isempty(desired) + % return a boolean flag + switch desired + case 'eeg' + type = any(strcmp(type, {'eeg' 'electrode' 'biosemi64' 'biosemi128' 'biosemi256' 'egi32' 'egi64' 'egi128' 'egi256' 'ext1020'})); + case 'biosemi' + type = any(strcmp(type, {'biosemi64' 'biosemi128' 'biosemi256'})); + case 'egi' + type = any(strcmp(type, {'egi64' 'egi128' 'egi256'})); + case 'meg' + type = any(strcmp(type, {'meg' 'magnetometer' 'ctf' 'bti' 'ctf151' 'ctf275' 'ctf151_planar' 'ctf275_planar' 'neuromag122' 'neuromag306' 'bti148' 'bti148_planar' 'bti248' 'bti248_planar' 'yokogawa160' 'yokogawa160_planar'})); + case 'ctf' + type = any(strcmp(type, {'ctf' 'ctf151' 'ctf275' 'ctf151_planar' 'ctf275_planar'})); + case 'bti' + type = any(strcmp(type, {'bti' 'bti148' 'bti148_planar' 'bti248' 'bti248_planar'})); + case 'neuromag' + type = any(strcmp(type, {'neuromag122' 'neuromag306'})); + case 'yokogawa' + type = any(strcmp(type, {'yokogawa160' 'yokogawa160_planar'})); + case 'itab' + type = any(strcmp(type, {'itab' 'itab153' 'itab153_planar'})); + case 'meg_axial' + % note that neuromag306 is mixed planar and axial + type = any(strcmp(type, {'magnetometer' 'neuromag306' 'ctf151' 'ctf275' 'bti148' 'bti248' 'yokogawa160'})); + case 'meg_planar' + % note that neuromag306 is mixed planar and axial + type = any(strcmp(type, {'neuromag122' 'neuromag306' 'ctf151_planar' 'ctf275_planar' 'bti148_planar' 'bti248_planar' 'yokogawa160_planar'})); + otherwise + type = any(strcmp(type, desired)); + end % switch desired +end % detemine the correspondence to the desired type + +% remember the current input and output arguments, so that they can be +% reused on a subsequent call in case the same input argument is given +current_argout = {type}; +if isempty(previous_argin) + previous_argin = current_argin; + previous_argout = current_argout; +end + +return % ft_senstype main() diff --git a/external/fieldtrip/forward/ft_sourcedepth.m b/external/fieldtrip/forward/ft_sourcedepth.m new file mode 100644 index 0000000..9e50b10 --- /dev/null +++ b/external/fieldtrip/forward/ft_sourcedepth.m @@ -0,0 +1,89 @@ +function [depth] = ft_sourcedepth(pos, vol) + +% FT_SOURCEDEPTH computes the distance from the source to the surface of +% the source compartment (usually the brain). +% +% Use as +% depth = ft_sourcedepth(pos, vol); +% where +% pos Nx3 matrix with the position of N sources +% vol structure describing volume condition model +% +% A negative depth indicates that the source is inside the source +% compartment, positive indicates outside. +% +% See also FIND_INSIDE_VOL + +% Copyright (C) 2007-2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_sourcedepth.m 946 2010-04-21 17:51:16Z roboos $ + +% determine the type of volume conduction model +switch ft_voltype(vol) + +% single-sphere or multiple concentric spheres +case {'singlesphere', 'concentric'} + if ~isfield(vol, 'source') + % locate the innermost compartment and remember it + [dum, vol.source] = min(vol.r); + end + if isfield(vol, 'o') + % shift dipole positions toward origin of sphere + tmp = pos - repmat(vol.o, size(pos,1), 1); + else + tmp = pos; + end + depth = sqrt(sum(tmp.^2, 2))-vol.r(vol.source); % positive if outside, negative if inside + +% boundary element model +case {'bem' 'dipoli', 'bemcp', 'asa', 'avo', 'nolte', 'neuromag'} + if isfield(vol, 'source') + % use the specified source compartment + pnt = vol.bnd(vol.source).pnt; + tri = vol.bnd(vol.source).tri; + else + % locate the innermost compartment and remember it + vol.source = find_innermost_boundary(vol.bnd); + pnt = vol.bnd(vol.source).pnt; + tri = vol.bnd(vol.source).tri; + end + inside = bounding_mesh(pos, pnt, tri); + ntri = size(tri,1); + npos = size(pos,1); + dist = zeros(ntri, 1); + depth = zeros(npos, 1); + for i=1:npos + for j=1:ntri + v1 = pnt(tri(j,1),:); + v2 = pnt(tri(j,2),:); + v3 = pnt(tri(j,3),:); + [proj, dist(j)] = ptriproj(v1, v2, v3, pos(i,:), 1); + end + if inside(i) + depth(i) = -min(dist); + else + depth(i) = min(dist); + end + end + +% unsupported volume conductor model +otherwise + error('upsupported volume conductor model'); +end + diff --git a/external/fieldtrip/forward/ft_transform_headshape.m b/external/fieldtrip/forward/ft_transform_headshape.m new file mode 100644 index 0000000..ec815cb --- /dev/null +++ b/external/fieldtrip/forward/ft_transform_headshape.m @@ -0,0 +1,62 @@ +function [shape] = ft_transform_headshape(transform, shape) + +% FT_TRANSFORM_HEADSHAPE applies a homogenous coordinate transformation to a +% structure with headshape and fiducial information. +% +% Use as +% shape = ft_transform_headshape(transform, shape) +% +% See also FT_READ_HEADSHAPE + +% Copyright (C) 2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_transform_headshape.m 946 2010-04-21 17:51:16Z roboos $ + +if any(transform(4,:) ~= [0 0 0 1]) + error('invalid transformation matrix'); +end + +if isfield(shape, 'pnt') && ~isempty(shape.pnt) + % this also works if the structure describes electrode or gradiometer positions instead of a headshape + shape.pnt = apply(transform, shape.pnt); +end + +if isfield(shape, 'ori') + % gradiometer coil orientations should only be rotated and not translated + rotation = eye(4); + rotation(1:3,1:3) = transform(1:3,1:3); + if abs(det(rotation)-1)>10*eps + error('only a rigid body transformation without rescaling is allowed for MEG sensors'); + end + % apply the rotation to the coil orientations + shape.ori = apply(rotation, sens.ori); +end + +if isfield(shape, 'fid') && isfield(shape.fid, 'pnt') + % apply the same transformation on the fiducials + shape.fid.pnt = apply(transform, shape.fid.pnt); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION that applies the homogenous transformation +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [new] = apply(transform, old) +old(:,4) = 1; +new = old * transform'; +new = new(:,1:3); diff --git a/external/fieldtrip/forward/ft_transform_sens.m b/external/fieldtrip/forward/ft_transform_sens.m new file mode 100644 index 0000000..be6653a --- /dev/null +++ b/external/fieldtrip/forward/ft_transform_sens.m @@ -0,0 +1,68 @@ +function [sens] = ft_transform_sens(transform, sens) + +% FT_TRANSFORM_SENS applies a homogenous coordinate transformation to a +% structure with EEG electrodes or MEG gradiometers. For MEG gradiometers +% the homogenous transformation matrix should be limited to a rigid-body +% translation plus rotation. +% +% Use as +% sens = ft_transform_sens(transform, sens) +% +% See also FT_READ_SENS, FT_PREPARE_VOL_SENS, FT_COMPUTE_LEADFIELD + +% Copyright (C) 2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_transform_sens.m 946 2010-04-21 17:51:16Z roboos $ + +if any(transform(4,:) ~= [0 0 0 1]) + error('invalid transformation matrix'); +end + +if ft_senstype(sens, 'eeg') + + % any normal coordinate transformation is in principle fine + % apply the translation, rotation and possibly scaling to the electrode positions + sens.pnt = apply(transform, sens.pnt); + +elseif ft_senstype(sens, 'meg') + + % only a rigid body transformation (translation+rotation) without rescaling is allowed + rotation = eye(4); + rotation(1:3,1:3) = transform(1:3,1:3); + + if abs(det(rotation)-1)>10*eps + error('only a rigid body transformation without rescaling is allowed for MEG sensors'); + end + + % apply the translation and rotation to the coil positions + sens.pnt = apply(transform, sens.pnt); + % the sensor coil orientations should be rotated but not translated + sens.ori = apply(rotation, sens.ori); + +else + error('unsupported or unrecognized type of sensors'); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION that applies the homogenous transformation +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [new] = apply(transform, old) +old(:,4) = 1; +new = old * transform'; +new = new(:,1:3); diff --git a/external/fieldtrip/forward/ft_transform_vol.m b/external/fieldtrip/forward/ft_transform_vol.m new file mode 100644 index 0000000..aa87987 --- /dev/null +++ b/external/fieldtrip/forward/ft_transform_vol.m @@ -0,0 +1,82 @@ +function [vol] = ft_transform_vol(transform, vol) + +% FT_TRANSFORM_VOL applies a homogenous coordinate transformation to +% a structure with an EEG or MEG colume conduction model. The homogenous +% transformation matrix should be limited to a rigid-body translation +% plus rotation and a global rescaling. +% +% Use as +% vol = ft_transform_vol(transform, vol) +% +% See also FT_READ_VOL, FT_PREPARE_VOL_SENS, FT_COMPUTE_LEADFIELD + +% Copyright (C) 2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_transform_vol.m 946 2010-04-21 17:51:16Z roboos $ + +if any(transform(4,:) ~= [0 0 0 1]) + error('invalid transformation matrix'); +end + +% only a rigid body transformation without rescaling is allowed +rotation = eye(4); +rotation(1:3,1:3) = transform(1:3,1:3); + +% FIXME insert check for nonuniform scaling, should give an error + +% if abs(det(rotation)-1)>10*eps +% error('only a rigid body transformation without rescaling is allowed'); +% end + +switch ft_voltype(vol) + + case {'singlesphere' 'multisphere' 'concentric'} + if isfield(vol, 'o') + % shift the center of the spheres, an optional rotation does not affect them + vol.o = apply(transform, vol.o); + end + + case {'bem', 'dipoli', 'bemcp', 'asa', 'avo', 'nolte'} + for i=1:length(vol.bnd) + % apply the transformation to each of the triangulated surface descriptions + vol.bnd(i).pnt = apply(transform, vol.bnd(i).pnt); + if isfield(vol.bnd(i), 'nrm') + % also apply it to the surface normals + vol.bnd(i).nrm = apply(transform, vol.bnd(i).nrm); + end + end + + case 'infinite' + % nothing to do, since it is an infinite vacuum + + case 'neuromag' + error('not supported for neuromag forward model'); + + otherwise + error('unsupported or unrecognized type of volume conductor model'); +end % switch + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION that applies the homogenous transformation +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [new] = apply(transform, old) +old(:,4) = 1; +new = old * transform'; +new = new(:,1:3); diff --git a/external/fieldtrip/forward/ft_voltype.m b/external/fieldtrip/forward/ft_voltype.m new file mode 100644 index 0000000..ede027d --- /dev/null +++ b/external/fieldtrip/forward/ft_voltype.m @@ -0,0 +1,107 @@ +function [type] = ft_voltype(vol, desired) + +% FT_VOLTYPE determines the type of volume conduction model +% +% Use as +% [type] = ft_voltype(vol) +% to get a string describing the type, or +% [flag] = ft_voltype(vol, desired) +% to get a boolean value. +% +% See also FT_READ_VOL, FT_COMPUTE_LEADFIELD + +% Copyright (C) 2007-2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_voltype.m 946 2010-04-21 17:51:16Z roboos $ + +% these are for remembering the type on subsequent calls with the same input arguments +persistent previous_argin previous_argout + +if iscell(vol) && numel(vol)<4 + % this might represent combined EEG, ECoG and/or MEG + type = cell(size(vol)); + if nargin<2 + desired = cell(size(vol)); % empty elements + end + for i=1:numel(vol) + type{i} = ft_voltype(vol{i}, desired{i}); + end + return +end + +if nargin<2 + % ensure that all input arguments are defined + desired = []; +end + +current_argin = {vol, desired}; +if isequal(current_argin, previous_argin) + % don't do the type detection again, but return the previous values from cache + type = previous_argout{1}; + return +end + +if isfield(vol, 'type') + % preferably the structure specifies its own type + type = vol.type; + +elseif isfield(vol, 'r') && numel(vol.r)==1 && ~isfield(vol, 'label') + type = 'singlesphere'; + +elseif isfield(vol, 'r') && isfield(vol, 'o') && isfield(vol, 'label') + % this is before the spheres have been assigned to the coils + % and every sphere is still associated with a channel + type = 'multisphere'; + +elseif isfield(vol, 'r') && isfield(vol, 'o') && size(vol.r,1)==size(vol.o,1) && size(vol.r,1)>4 + % this is after the spheres have been assigned to the coils + % note that this one is easy to confuse with the concentric one + type = 'multisphere'; + +elseif isfield(vol, 'r') && numel(vol.r)>=2 && ~isfield(vol, 'label') + type = 'concentric'; + +elseif isfield(vol, 'bnd') + type = 'bem'; + +elseif isempty(vol) + type = 'infinite'; + +else + type = 'unknown'; + +end % if isfield(vol, 'type') + +if ~isempty(desired) + % return a boolean flag + switch desired + case 'bem' + type = any(strcmp(type, {'bem', 'dipoli', 'asa', 'avo', 'bemcp', 'openmeeg'})); + otherwise + type = any(strcmp(type, desired)); + end +end + +% remember the current input and output arguments, so that they can be +% reused on a subsequent call in case the same input argument is given +current_argout = {type}; +previous_argin = current_argin; +previous_argout = current_argout; + +return % voltype main() diff --git a/external/fieldtrip/forward/private/avgref.m b/external/fieldtrip/forward/private/avgref.m new file mode 100644 index 0000000..eba47f2 --- /dev/null +++ b/external/fieldtrip/forward/private/avgref.m @@ -0,0 +1,59 @@ +function [data] = avgref(data, sel); + +% AVGREF computes the average reference in each column +% [data] = avgref(data) +% +% or it computes the re-referenced data relative to the +% average over the selected channels +% [data] = avgref(data, sel) + +% Copyright (C) 1998-2002, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: avgref.m 946 2010-04-21 17:51:16Z roboos $ + +% determine the dimension of the data +if length(size(data))==3 + % multiple epochs + dim=3; +else + % single epoch with multiple channels + dim=2; +end + +if nargin==1 + % default is to use all channels for average referencing + if dim==3 + sel=1:size(data,2); + else + sel=1:size(data,1); + end +end + +if dim==3 + % the data contains multiple epochs + for epoch=1:size(data,1) + reference = mean(squeeze(data(epoch,sel,:)), 1); + data(epoch,:,:) = squeeze(data(epoch,:,:)) - repmat(reference, size(data,2), 1); + end +else + % the data contains a single epoch + reference = mean(data(sel,:), 1); + data = data - repmat(reference, size(data,1), 1); +end + diff --git a/external/fieldtrip/forward/private/bounding_mesh.m b/external/fieldtrip/forward/private/bounding_mesh.m new file mode 100644 index 0000000..c2fddd8 --- /dev/null +++ b/external/fieldtrip/forward/private/bounding_mesh.m @@ -0,0 +1,84 @@ +function [inside] = bounding_mesh(pos, pnt, tri); + +% BOUNDING_MESH determines if a point is inside/outside a triangle mesh +% whereby the bounding triangle mesh should be closed. +% +% [inside] = bounding_mesh(pos, pnt, tri) +% +% where +% pos position of point of interest (can be 1x3 or Nx3) +% pnt bounding mesh vertices +% tri bounding mesh triangles +% +% See also SOLID_ANGLE + +% Copyright (C) 2003, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: bounding_mesh.m 946 2010-04-21 17:51:16Z roboos $ + +global fb; +if isempty(fb) + fb = 0; +end + +npos = size(pos, 1); +npnt = size(pnt, 1); +ntri = size(tri, 1); + +% determine a cube that encompases the boundary triangulation +bound_min = min(pnt); +bound_max = max(pnt); + +% determine a sphere that is completely inside the boundary triangulation +bound_org = mean(pnt); +bound_rad = sqrt(min(sum((pnt - repmat(bound_org, size(pnt,1), 1)).^2, 2))); + +inside = zeros(npos, 1); +for i=1:npos + if fb + fprintf('%6.2f%%', 100*i/npos); + end + if any(pos(i,:)bound_max) + % the point is outside the bounding cube + inside(i) = 0; + if fb, fprintf(' outside the bounding cube\n'); end + elseif sqrt(sum((pos(i,:)-bound_org).^2, 2))0 + % total solid angle is (approximately) plus or minus 4*pi + inside(i) = 1; + end + if fb, fprintf(' solid angle\n'); end + end +end + diff --git a/external/fieldtrip/forward/private/eeg_leadfield1.m b/external/fieldtrip/forward/private/eeg_leadfield1.m new file mode 100644 index 0000000..4c4a840 --- /dev/null +++ b/external/fieldtrip/forward/private/eeg_leadfield1.m @@ -0,0 +1,105 @@ +function [lf, lforig] = eeg_leadfield1(R, elc, vol); + +% EEG_LEADFIELD1 electric leadfield for a dipole in a single sphere +% +% [lf] = eeg_leadfield1(R, elc, vol) +% +% with input arguments +% R position dipole (vector of length 3) +% elc position electrodes +% and vol being a structure with the elements +% vol.r radius of sphere +% vol.c conductivity of sphere + +% Copyright (C) 2002, Robert Oostenveld +% +% this implementation is adapted from +% Luetkenhoener, Habilschrift '92 +% the original reference is +% R. Kavanagh, T. M. Darccey, D. Lehmann, and D. H. Fender. Evaluation of methods for three-dimensional localization of electric sources in the human brain. IEEE Trans Biomed Eng, 25:421-429, 1978. +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: eeg_leadfield1.m 946 2010-04-21 17:51:16Z roboos $ + +Nchans = size(elc, 1); +lf = zeros(Nchans,3); + +% always take the outermost sphere, this makes comparison with the 4-sphere computation easier +[vol.r, indx] = max(vol.r); +vol.c = vol.c(indx); + +% check whether the electrode ly on the sphere, allowing 0.5% tolerance +dist = sqrt(sum(elc.^2,2)); +if any(abs(dist-vol.r)>vol.r*0.005) + warning('electrodes do not ly on sphere surface -> using projection') +end +elc = vol.r * elc ./ [dist dist dist]; + +% check whether the dipole is inside the brain [disabled for EEGLAB] +% if sqrt(sum(R.^2))>=vol.r +% error('dipole is outside the brain compartment'); +% end + +c0 = norm(R); +c1 = vol.r; +c2 = 4*pi*c0^2*vol.c; + +if c0==0 + % the dipole is in the origin, this can and should be handeled as an exception + [phi, el] = cart2sph(elc(:,1), elc(:,2), elc(:,3)); + theta = pi/2 - el; + lf(:,1) = sin(theta).*cos(phi); + lf(:,2) = sin(theta).*sin(phi); + lf(:,3) = cos(theta); + % the potential in a homogenous sphere is three times the infinite medium potential + lf = 3/(c1^2*4*pi*vol.c)*lf; + +else + for i=1:Nchans + % use another name for the electrode, in accordance with lutkenhoner1992 + r = elc(i,:); + + c3 = r-R; + c4 = norm(c3); + c5 = c1^2 * c0^2 - dot(r,R)^2; % lutkenhoner A.11 + c6 = c0^2*r - dot(r,R)*R; % lutkenhoner, just after A.17 + + % the original code reads (cf. lutkenhoner1992 equation A.17) + % lf(i,:) = ((dot(R, r/norm(r) - (r-R)/norm(r-R))/(norm(cross(r,R))^2) + 2/(norm(r-R)^3)) * cross(R, cross(r, R)) + ((norm(r)^2-norm(R)^2)/(norm(r-R)^3) - 1/norm(r)) * R) / (4*pi*vol.c(1)*norm(R)^2); + + % but more efficient execution of the code is achieved by some precomputations + if c5<1000*eps + % the dipole lies on a single line with the electrode + lf(i,:) = (2/c4^3 * c6 + ((c1^2-c0^2)/c4^3 - 1/c1) * R) / c2; + else + % nothing wrong, do the complete computation + lf(i,:) = ((dot(R, r/c1 - c3/c4)/c5 + 2/c4^3) * c6 + ((c1^2-c0^2)/c4^3 - 1/c1) * R) / c2; + end + end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% fast cross product +function [c] = cross(a,b) +c = [a(2)*b(3)-a(3)*b(2) a(3)*b(1)-a(1)*b(3) a(1)*b(2)-a(2)*b(1)]; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% fast dot product +function [c] = dot(a,b) +c = sum(a.*b); + diff --git a/external/fieldtrip/forward/private/eeg_leadfield4.m b/external/fieldtrip/forward/private/eeg_leadfield4.m new file mode 100644 index 0000000..3682582 --- /dev/null +++ b/external/fieldtrip/forward/private/eeg_leadfield4.m @@ -0,0 +1,140 @@ +function [lf, vol] = eeg_leadfield4(R, elc, vol) + +% EEG_LEADFIELD4 electric leadfield for a dipole in 4 concentric spheres +% +% [lf] = eeg_leadfield4(R, elc, vol) +% +% with input arguments +% R position of the dipole +% elc position of the electrodes +% and vol being a structure with the elements +% vol.r radius of the 4 spheres +% vol.c conductivity of the 4 spheres +% vol.t constant factors for series expansion (optional) +% +% See also EEG_LEADFIELD4_PREPARE for precomputing the constant factors, +% which can save time when multiple leadfield computations are done. + +% Copyright (C) 2002, Robert Oostenveld +% +% this implementation is adapted from +% Lutkenhoner, Habilschrift 1992. +% the original reference is +% Cuffin BN, Cohen D. Comparison of the magnetoencephalogram and electroencephalogram. Electroencephalogr Clin Neurophysiol. 1979 Aug;47(2):132-46. +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: eeg_leadfield4.m 946 2010-04-21 17:51:16Z roboos $ + +% sort the spheres from the smallest to the largest +[vol.r, indx] = sort(vol.r); +[vol.c] = vol.c(indx); + +% use more convenient names for the radii and conductivity +r1 = vol.r(1); c1 = vol.c(1); +r2 = vol.r(2); c2 = vol.c(2); +r3 = vol.r(3); c3 = vol.c(3); +r4 = vol.r(4); c4 = vol.c(4); + +% check whether the electrode ly on the sphere, allowing 0.5% tolerance +dist = sqrt(sum(elc.^2,2)); +if any(abs(dist-r4)>r4*0.005) + warning('electrodes do not ly on sphere surface -> using projection') +end +elc = r4 * elc ./ [dist dist dist]; + +% check whether the dipole is inside the brain [disabled for EEGLAB] +% if sqrt(sum(R.^2))>=r1 +% error('dipole is outside the brain compartment'); +% end + +% rotate everything so that the dipole is along the pos. z-axis +% only if the dipole is not in the origin or along the positive z-axis +if R(1)~=0 | R(2)~=0 + % compute the rotation matrix + % the inverse rotation matrix is the transposed of this one + val1 = norm(R); + val2 = norm(R(1:2)); + rot(1,1) = R(1) * R(3) / (val1 * val2); + rot(1,2) = R(2) * R(3) / (val1 * val2); + rot(1,3) = -1.0 * val2 / val1; + rot(2,1) = -1.0 * R(2) / val2; + rot(2,2) = R(1) / val2; + rot(2,3) = 0; + rot(3,:) = R ./ val1; + % rotate the electrodes + elc = elc*rot'; +elseif R(1)==0 && R(2)==0 && R(3)<0 + % dipole on negative z-axis, rotation is very simple: around x-axis + elc(2,:) = -elc(2,:); + elc(3,:) = -elc(3,:); +else + % dipole is on positive z-axis, nothing has to be done +end + +% compute the constant factors for the sphere configuration if needed +if ~isfield(vol, 't') + vol.t = eeg_leadfield4_prepare(vol); +end + +Nchans = size(elc,1); +lf = zeros(Nchans,3); +Nmax = length(vol.t); +n = 1:Nmax; +f = norm(R)/r4; % following cuffin1979 +% c = r2/r4; % following cuffin1979 +% d = r3/r4; % following cuffin1979 + +% this code is to cross-validate the lutkenhoner and cuffin implementations +% [lut_t, cuf_t] = eeg_leadfield4_prepare(vol); +% lut_c = (2*n+1).^4.*f.^(n-1) ./ (lut_t.*4*pi*c4*r4^2); +% cuf_c = (2*n+1).^4.*f.^(n-1) .*(c*d).^(2.*n+1) ./ (cuf_t.*4*pi*c4*r4^2); + +% given a fixed volume conductor, these only need to be computed once for all electrodes +const = (2*n+1).^4.*f.^(n-1) ./ (vol.t.*4*pi*c4*r4^2); + +for i=1:Nchans + % convert the position of the electrodes to spherical coordinates + [phi, el] = cart2sph(elc(i,1), elc(i,2), elc(i,3)); + + % change from colatitude to latitude and compute the cosine + cos_theta = cos(pi/2-el); + + % the series summation starts at zero + s_x = 0; + s_z = 0; + + for n=1:Nmax + P0 = plgndr(n,0,cos_theta); % zero'th order Legendre + P1 = plgndr(n,1,cos_theta); % first order Legendre + s_x = s_x + const(n)*P1/n; % s_y is identical + s_z = s_z + const(n)*P0; + end + + lf(i,1) = -cos(phi) * s_x; + lf(i,2) = -sin(phi) * s_x; % s_y is identical to s_x + lf(i,3) = 1 * s_z; +end + +% apply the inverse rotation to the leadfield matrix +if R(1)~=0 || R(2)~=0 + lf = lf*rot; +elseif R(1)==0 && R(2)==0 && R(3)<0 + lf(2,:) = -lf(2,:); + lf(3,:) = -lf(3,:); +end + diff --git a/external/fieldtrip/forward/private/eeg_leadfield4_prepare.m b/external/fieldtrip/forward/private/eeg_leadfield4_prepare.m new file mode 100644 index 0000000..3101a18 --- /dev/null +++ b/external/fieldtrip/forward/private/eeg_leadfield4_prepare.m @@ -0,0 +1,90 @@ +function [lut_t, cuf_t] = eeg_leadfield4_prepare(vol, Nmax); + +% EEG_LEADFIELD4_PREPARE computes constant factors for series expansion +% for the 4 concentric sphere electric leadfield computation +% +% use this function prior to repeated calls of eeg_leadfield4 according to +% vol.t = eeg_leadfield4_prepare(vol, N); +% where +% vol.r radius of the 4 spheres +% vol.c conductivity of the 4 spheres +% and N is the number of terms for the series (default 60). The constant +% factors t then do not have to be computed each time in eeg_leadfield4. +% +% this implementation is adapted from +% Lutkenhoner, Habilschrift 1992. +% which again is taken from +% B. N. Cuffin and D. Cohen. Comparion of the Magnetoencephalogram and the Electroencephalogram. Electroencephalogr Clin Neurophysiol, 47:131-146, 1979. +% +% See also EEG_LEADFIELD4 + +% Copyright (C) 2002, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: eeg_leadfield4_prepare.m 946 2010-04-21 17:51:16Z roboos $ + +% sort the spheres from the smallest to the largest +[vol.r, indx] = sort(vol.r); +[vol.c] = vol.c(indx); + +r1 = vol.r(1); c1 = vol.c(1); +r2 = vol.r(2); c2 = vol.c(2); +r3 = vol.r(3); c3 = vol.c(3); +r4 = vol.r(4); c4 = vol.c(4); + +if nargin==1 + Nmax = 60; +end + +% these are the constants of cuffin1979 +k1 = c1/c2; +k2 = c2/c3; +k3 = c3/c4; + +for n=1:Nmax + % according to lutkenhoner1992 the constant C is + % lut_t(n) = ((n*c1/c2+n+1)*(n*c2/c3+n+1)+n*(n+1)*(c1/c2-1)*(c2/c3-1)*(r1/r2)^(2*n+1)) * ... + % ((n*c3/c4+n+1)+(n+1)*(c3/c4-1)*(r3/r4)^(2*n+1)) + ... + % ((c1/c2-1)*((n+1)*c2/c3+n)*(r1/r3)^(2*n+1)+(n*c1/c2+n+1)*(c2/c3-1)*(r2/r3)^(2*n+1)) * ... + % (n+1)*(n*(c3/c4-1)+((n+1)*c3/c4+n)*(r3/r4)^(2*n+1)); + % which can be rewritten as + lut_t(n) = ((n*k1+n+1)*(n*k2+n+1)+n*(n+1)*(k1-1)*(k2-1)*(r1/r2)^(2*n+1)) * ... + ((n*k3+n+1)+(n+1)*(k3-1)*(r3/r4)^(2*n+1)) + ... + ((k1-1)*((n+1)*k2+n)*(r1/r3)^(2*n+1)+(n*k1+n+1)*(k2-1)*(r2/r3)^(2*n+1)) * ... + (n+1)*(n*(k3-1)+((n+1)*k3+n)*(r3/r4)^(2*n+1)); + +end + +% for debugging purposes, it can also give the constants of cuffin19979 +if nargout>1 + % some extra constants of cuffin1979 + b = r1/r4; + c = r2/r4; + d = r3/r4; + + % according to cuffin1979 the constant Tau is (re-entered on 25 sept 2002) + % but this requires also slightly other constants in the eeg_leadfield4 function + for n=1:Nmax + cuf_t(n) = d^(2*n+1) * (b^(2*n+1)*n*(k1-1)*(k2-1)*(n+1)... + + c^(2*n+1)*(k1*n+n+1)*(k2*n+n+1))... + *((k3*n+n+1)+(n+1)*(k3-1)*d^(2*n+1))... + +(n+1)*c^(2*n+1)*(b^(2*n+1)*(k1-1)*(k2*n+k2+n)... + +c^(2*n+1)*(k1*n+n+1)*(k2-1))... + *(n*(k3-1)+(k3*n+k3+n)*d^(2*n+1)); + end +end diff --git a/external/fieldtrip/forward/private/eeg_leadfieldb.m b/external/fieldtrip/forward/private/eeg_leadfieldb.m new file mode 100644 index 0000000..46f7b5c --- /dev/null +++ b/external/fieldtrip/forward/private/eeg_leadfieldb.m @@ -0,0 +1,135 @@ +function [lf] = eeg_leadfieldb(pos, elc, vol) + +% EEG_LEADFIELDB computes the electric leadfield for a dipole in a volume +% using the boundary element method +% +% [lf] = eeg_leadfieldb(pos, elc, vol) +% +% with the input arguments +% pos position dipole (1x3 or Nx3) +% elc position electrodes (optional, can be empty) +% vol volume conductor model +% +% the volume conductor model is a structure and should have the fields +% vol.bnd structure array with vertices and triangles of each boundary +% vol.cond conductivity of all compartments +% vol.mat system matrix, which can include the electrode interpolation +% +% the compartment boundaries are described by a structure array with +% vol.bnd(i).pnt +% vol.bnd(i).pnt + +% Copyright (C) 2003, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: eeg_leadfieldb.m 946 2010-04-21 17:51:16Z roboos $ + + +% do some sanity checks +if ~isfield(vol, 'bnd') + error('there are no compartment boundaries present'); +end + +if length(vol.bnd)~=length(vol.cond) + error('the number of compartments in the volume in ambiguous'); +end + +if ~isfield(vol, 'mat') + error('there is no BEM system matrix present'); +end + +% determine the number of compartments +ncmp = length(vol.bnd); + +% the number of rows in the leadfield matrix should either correspond to +% the number of electrodes, to the number of vertices of the skin +% compartment or to the total number of vertices +nelc = size(elc, 1); +nskin = size(vol.bnd(vol.skin).pnt,1); +nall = 0; +for i=1:ncmp + nall = nall + size(vol.bnd(i).pnt,1); +end +if size(vol.mat,1)==nelc + % the output leadfield corresponds to the number of electrodes +elseif size(vol.mat,1)==nskin + % the output leadfield corresponds to the number skin vertices +elseif size(vol.mat,1)==nall + % the output leadfield corresponds to the total number of vertices +elseif strcmp(ft_voltype(vol),'openmeeg') + % this is handled differently, although at the moment I don't know why +else + error('unexpected size of vol.mat') +end + +% determine the conductivity of the source compartment +cond = vol.cond(vol.source); + +% compute the infinite medium potential on all vertices +switch ft_voltype(vol) + case 'avo' + % the system matrix was computed using code from Adriaan van Oosterom + % the code by Adriaan van Oosterom does not implement isolated source approach + lf = []; + for i=1:ncmp + lf = [lf; inf_medium_leadfield(pos, vol.bnd(i).pnt, mean(vol.sigmas(i,:)))]; + end + + case 'dipoli' + % the system matrix was computed using Thom Oostendorp's DIPOLI + % concatenate the vertices of all compartment boundaries in a single Nx3 matrix + pnt = []; + for i=1:ncmp + pnt = [pnt; vol.bnd(i).pnt]; + end + % dipoli incorporates the conductivity into the system matrix + lf = inf_medium_leadfield(pos, pnt, 1); + + case 'asa' + % the system matrix was computed using ASA from www.ant-neuro.com + % concatenate the vertices of all compartment boundaries in a single Nx3 matrix + pnt = []; + for i=1:ncmp + pnt = [pnt; vol.bnd(i).pnt]; + end + % assume that isolated potential approach was used + lf = inf_medium_leadfield(pos, pnt, cond); + + case 'bemcp' + % the system matrix was computed using code from Christopher Phillips + cond = [vol.cond 0]; % add the conductivity of air for simplicity + lf = cell(1,ncmp); + % loop over boundaries and compute the leadfield for each + for i=1:ncmp + co = (cond(i)+cond(i+1))/2 ; + lf{i} = inf_medium_leadfield(pos, vol.bnd(i).pnt, co); + end + % concatenate the leadfields + lf = cat(1, lf{:}); + + otherwise + error('unsupported type of volume conductor (%s)\n', ft_voltype(vol)); +end % switch ft_voltype + +if isfield(vol, 'mat') && ~ft_voltype(vol, 'openmeeg') + + % compute the bounded medium potential on all vertices + % this may include the bilinear interpolation from vertices towards electrodes + lf = vol.mat * lf; +end + diff --git a/external/forwinv/private/elproj.m b/external/fieldtrip/forward/private/elproj.m similarity index 75% rename from external/forwinv/private/elproj.m rename to external/fieldtrip/forward/private/elproj.m index e6b74cc..72dc9b5 100644 --- a/external/forwinv/private/elproj.m +++ b/external/fieldtrip/forward/private/elproj.m @@ -7,11 +7,11 @@ % [proj] = elproj([x, y, z], 'method'); % % Method should be one of these: -% 'gnomic' -% 'stereographic' -% 'ortographic' -% 'inverse' -% 'polar' +% 'gnomic' +% 'stereographic' +% 'orthographic' +% 'inverse' +% 'polar' % % Imagine a plane being placed against (tangent to) a globe. If % a light source inside the globe projects the graticule onto @@ -25,19 +25,23 @@ % Copyright (C) 2000-2008, Robert Oostenveld % -% $Log: elproj.m,v $ -% Revision 1.5 2009/10/14 15:27:40 roboos -% give error on method that is not recognized +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.4 2008/05/15 10:54:24 roboos -% updated documentation +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.3 2007/03/20 10:29:35 roboos -% renamed method 'default' into 'polar' +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.2 2003/03/17 10:37:28 roberto -% improved general help comments and added copyrights +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: elproj.m 946 2010-04-21 17:51:16Z roboos $ x = pos(:,1); y = pos(:,2); diff --git a/external/fieldtrip/forward/private/find_innermost_boundary.m b/external/fieldtrip/forward/private/find_innermost_boundary.m new file mode 100644 index 0000000..d7b37a1 --- /dev/null +++ b/external/fieldtrip/forward/private/find_innermost_boundary.m @@ -0,0 +1,57 @@ +function [innermost, inside] = find_innermost_boundary(bnd) + +% FIND_INNERMOST_BOUNDARY locates innermost compartment of a BEM model +% by looking at the containment of the triangular meshes describing +% the surface boundaries +% +% [innermost] = find_innermost_boundary(bnd) +% +% with the boundaries described by a struct array bnd with +% bnd(i).pnt vertices of boundary i (matrix of size Nx3) +% bnd(i).tri triangles of boundary i (matrix of size Mx3) + +% Copyright (C) 2003, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: find_innermost_boundary.m 946 2010-04-21 17:51:16Z roboos $ + +ncmp = length(bnd); + +if ncmp==1 + innermost = 1; + return +end + +% try to locate the innermost compartment +for i=1:ncmp +for j=1:ncmp + % determine for a single vertex on each surface if it is inside or outside the other surfaces + curpos = bnd(i).pnt(1,:); % any point on the boundary is ok + curpnt = bnd(j).pnt; + curtri = bnd(j).tri; + if i==j + inside(i,j) = 0; + else + inside(i,j) = bounding_mesh(curpos, curpnt, curtri); + end +end +end +% assume that the sources are in the innermost compartment +tmp = sum(inside, 2); +[i, innermost] = max(tmp); + diff --git a/external/fieldtrip/forward/private/find_inside_vol.m b/external/fieldtrip/forward/private/find_inside_vol.m new file mode 100644 index 0000000..6830ef6 --- /dev/null +++ b/external/fieldtrip/forward/private/find_inside_vol.m @@ -0,0 +1,35 @@ +function [inside, outside] = find_inside_vol(pos, vol); + +% FIND_INSIDE_VOL locates dipole locations inside/outside the source +% compartment of a volume conductor model. +% +% [inside, outside] = find_inside_vol(pos, vol) +% +% This function is obsolete and its use in other functions should be replaced +% by inside_vol + +% Copyright (C) 2003-2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: find_inside_vol.m 1074 2010-05-17 07:52:16Z roboos $ + + +inside = ft_inside_vol(pos, vol); +% replace boolean vector with indexing vectors +outside = find(~inside); +inside = find(inside); diff --git a/external/fieldtrip/forward/private/find_outermost_boundary.m b/external/fieldtrip/forward/private/find_outermost_boundary.m new file mode 100644 index 0000000..66b3a5f --- /dev/null +++ b/external/fieldtrip/forward/private/find_outermost_boundary.m @@ -0,0 +1,52 @@ +function [outermost, inside] = find_outermost_boundary(bnd) + +% FIND_OUTERMOST_BOUNDARY locates outermost compartment of a BEM model +% by looking at the containment of the triangular meshes describing +% the surface boundaries +% +% [outermost] = find_innermost_boundary(bnd) +% +% with the boundaries described by a struct array bnd with +% bnd(i).pnt vertices of boundary i (matrix of size Nx3) +% bnd(i).tri triangles of boundary i (matrix of size Mx3) + +% Copyright (C) 2003, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: find_outermost_boundary.m 946 2010-04-21 17:51:16Z roboos $ + +ncmp = length(bnd); + +% try to locate the outermost compartment +for i=1:ncmp +for j=1:ncmp + % determine for a single vertex on each surface if it is inside or outside the other surfaces + curpos = bnd(i).pnt(1,:); % any point on the boundary is ok + curpnt = bnd(j).pnt; + curtri = bnd(j).tri; + if i==j + inside(i,j) = 0; + else + inside(i,j) = bounding_mesh(curpos, curpnt, curtri); + end +end +end +% assume that the sources are in the innermost compartment +tmp = sum(inside, 2); +[i, outermost] = min(tmp); + diff --git a/external/fieldtrip/forward/private/fitsphere.m b/external/fieldtrip/forward/private/fitsphere.m new file mode 100644 index 0000000..dae0727 --- /dev/null +++ b/external/fieldtrip/forward/private/fitsphere.m @@ -0,0 +1,93 @@ +function [C,R] = fitsphere(pnt) + +% FITSPHERE fits the centre and radius of a sphere to a set of points +% using Taubin's method. +% +% Use as +% [center,radius] = fitsphere(pnt) +% where +% pnt = Nx3 matrix with the Carthesian coordinates of the surface points +% and +% center = the center of the fitted sphere +% radius = the radius of the fitted sphere + +% Copyright (C) 2009, Jean Daunizeau (for SPM) +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: fitsphere.m 946 2010-04-21 17:51:16Z roboos $ + +x = pnt(:,1); +y = pnt(:,2); +z = pnt(:,3); + +% Make sugary one and zero vectors +l = ones(length(x),1); +O = zeros(length(x),1); + +% Make design mx +D = [(x.*x + y.*y + z.*z) x y z l]; + +Dx = [2*x l O O O]; +Dy = [2*y O l O O]; +Dz = [2*z O O l O]; + +% Create scatter matrices +M = D'*D; +N = Dx'*Dx + Dy'*Dy + Dz'*Dz; + +% Extract eigensystem +[v, evalues] = eig(M); +evalues = diag(evalues); +Mrank = sum(evalues > eps*5*norm(M)); + +if (Mrank == 5) + % Full rank -- min ev corresponds to solution + % Minverse = v'*diag(1./evalues)*v; + [v,evalues] = eig(inv(M)*N); + [dmin,dminindex] = max(diag(evalues)); + pvec = v(:,dminindex(1))'; +else + % Rank deficient -- just extract nullspace of M + % pvec = null(M)'; % this does not work reliably because of inconsistent rank definition + pvec = v(:,evalues <= eps*5*norm(M))'; + [m,n] = size(pvec); + if m > 1 + pvec = pvec(1,:); + end +end + +if isempty(pvec) + warning('was not able to fit a sphere to the surface points'); + C = [NaN NaN NaN]; + R = Inf; +else + % Convert to (R,C) + C = -0.5*pvec(2:4) / pvec(1); + R = sqrt(sum(C*C') - pvec(5)/pvec(1)); +end + + +% if nargout == 1, +% if pvec(1) < 0 +% pvec = -pvec; +% end +% C = pvec; +% else +% C = -0.5*pvec(2:4) / pvec(1); +% R = sqrt(sum(C*C') - pvec(5)/pvec(1)); +% end diff --git a/external/fieldtrip/forward/private/fixdipole.m b/external/fieldtrip/forward/private/fixdipole.m new file mode 100644 index 0000000..363fd34 --- /dev/null +++ b/external/fieldtrip/forward/private/fixdipole.m @@ -0,0 +1,52 @@ +function dip = fixdipole(dip) + +% FIXDIPOLE ensures that the dipole position and moment are +% consistently represented throughout FieldTrip functions. + +% Copyright (C) 2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: fixdipole.m 946 2010-04-21 17:51:16Z roboos $ + +[m, n] = size(dip.pos); + +if n==3 + % the input representation is Nx3, which is what we want +elseif m==3 + % it is possible to translate it into a Nx3 unambiguously + warning('input dipole positions should be specified as Nx3 matrix'); + dip.pos = dip.pos'; +elseif m==1 + % it is possible to translate it into a Nx3 unambiguously + warning('input dipole positions should be specified as Nx3 matrix'); + dip.pos = reshape(dip.pos, 3, n/3)'; +else + % it is not clear how to convert to a Nx3 matrix + error('input dipole positions should be specified as Nx3 matrix'); +end + +if isfield(dip, 'mom') + ndip = size(dip.pos,1); + if numel(dip.mom)==ndip*3 + ntime = 1; + else + ntime = numel(dip.mom)/(ndip*3); + end + dip.mom = reshape(dip.mom, ndip*3, ntime); +end + diff --git a/external/forwinv/private/geometry.c b/external/fieldtrip/forward/private/geometry.c similarity index 100% rename from external/forwinv/private/geometry.c rename to external/fieldtrip/forward/private/geometry.c diff --git a/external/forwinv/private/geometry.h b/external/fieldtrip/forward/private/geometry.h old mode 100755 new mode 100644 similarity index 100% rename from external/forwinv/private/geometry.h rename to external/fieldtrip/forward/private/geometry.h diff --git a/external/fieldtrip/forward/private/getsubfield.m b/external/fieldtrip/forward/private/getsubfield.m new file mode 100644 index 0000000..690e299 --- /dev/null +++ b/external/fieldtrip/forward/private/getsubfield.m @@ -0,0 +1,45 @@ +function [s] = getsubfield(s, f); + +% GETSUBFIELD returns a field from a structure just like the standard +% Matlab GETFIELD function, except that you can also specify nested fields +% using a '.' in the fieldname. The nesting can be arbitrary deep. +% +% Use as +% f = getsubfield(s, 'fieldname') +% or as +% f = getsubfield(s, 'fieldname.subfieldname') +% +% See also GETFIELD, ISSUBFIELD, SETSUBFIELD + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: getsubfield.m 951 2010-04-21 18:24:01Z roboos $ + +if ~isstr(f) + error('incorrect input argument for fieldname'); +end + +t = {}; +while (1) + [t{end+1}, f] = strtok(f, '.'); + if isempty(f) + break + end +end +s = getfield(s, t{:}); diff --git a/external/fieldtrip/forward/private/hastoolbox.m b/external/fieldtrip/forward/private/hastoolbox.m new file mode 100644 index 0000000..311bb7e --- /dev/null +++ b/external/fieldtrip/forward/private/hastoolbox.m @@ -0,0 +1,321 @@ +function [status] = hastoolbox(toolbox, autoadd, silent) + +% HASTOOLBOX tests whether an external toolbox is installed. Optionally +% it will try to determine the path to the toolbox and install it +% automatically. +% +% Use as +% [status] = hastoolbox(toolbox, autoadd, silent) +% +% autoadd = 0 means that it will not be added +% autoadd = 1 means that give an error if it cannot be added +% autoadd = 2 means that give a warning if it cannot be added +% autoadd = 3 means that it try to add it silently + +% Copyright (C) 2005-2010, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: hastoolbox.m 1411 2010-07-14 11:00:12Z jansch $ + +% this function is called many times in FieldTrip and associated toolboxes +% use efficient handling if the same toolbox has been investigated before +persistent previous previouspath + +if ~isequal(previouspath, matlabpath) + previous = []; +end + +if isempty(previous) + previous = struct; +elseif isfield(previous, fixname(toolbox)) + status = previous.(fixname(toolbox)); + return +end + +% this points the user to the website where he/she can download the toolbox +url = { + 'AFNI' 'see http://afni.nimh.nih.gov' + 'DSS' 'see http://www.cis.hut.fi/projects/dss' + 'EEGLAB' 'see http://www.sccn.ucsd.edu/eeglab' + 'NWAY' 'see http://www.models.kvl.dk/source/nwaytoolbox' + 'SPM99' 'see http://www.fil.ion.ucl.ac.uk/spm' + 'SPM2' 'see http://www.fil.ion.ucl.ac.uk/spm' + 'SPM5' 'see http://www.fil.ion.ucl.ac.uk/spm' + 'SPM8' 'see http://www.fil.ion.ucl.ac.uk/spm' + 'MEG-PD' 'see http://www.kolumbus.fi/kuutela/programs/meg-pd' + 'MEG-CALC' 'this is a commercial toolbox from Neuromag, see http://www.neuromag.com' + 'BIOSIG' 'see http://biosig.sourceforge.net' + 'EEG' 'see http://eeg.sourceforge.net' + 'EEGSF' 'see http://eeg.sourceforge.net' % alternative name + 'MRI' 'see http://eeg.sourceforge.net' % alternative name + 'NEUROSHARE' 'see http://www.neuroshare.org' + 'BESA' 'see http://www.megis.de, or contact Karsten Hoechstetter' + 'EEPROBE' 'see http://www.ant-neuro.com, or contact Maarten van der Velde' + 'YOKOGAWA' 'see http://www.yokogawa.co.jp, or contact Nobuhiko Takahashi' + 'BEOWULF' 'see http://oostenveld.net, or contact Robert Oostenveld' + 'MENTAT' 'see http://oostenveld.net, or contact Robert Oostenveld' + 'SON2' 'see http://www.kcl.ac.uk/depsta/biomedical/cfnr/lidierth.html, or contact Malcolm Lidierth' + '4D-VERSION' 'contact Christian Wienbruch' + 'SIGNAL' 'see http://www.mathworks.com/products/signal' + 'OPTIM' 'see http://www.mathworks.com/products/optim' + 'IMAGE' 'see http://www.mathworks.com/products/image' + 'SPLINES' 'see http://www.mathworks.com/products/splines' + 'FASTICA' 'see http://www.cis.hut.fi/projects/ica/fastica' + 'BRAINSTORM' 'see http://neuroimage.ucs.edu/brainstorm' + 'FILEIO' 'see http://www.ru.nl/neuroimaging/fieldtrip' + 'FORWINV' 'see http://www.ru.nl/neuroimaging/fieldtrip' + 'PLOTTING' 'see http://www.ru.nl/neuroimaging/fieldtrip' + 'DENOISE' 'see http://lumiere.ens.fr/Audition/adc/meg, or contact Alain de Cheveigne' + 'BCI2000' 'see http://bci2000.org' + 'NLXNETCOM' 'see http://www.neuralynx.com' + 'DIPOLI' 'see ftp://ftp.fcdonders.nl/pub/fieldtrip/external' + 'MNE' 'see http://www.nmr.mgh.harvard.edu/martinos/userInfo/data/sofMNE.php' + 'TCP_UDP_IP' 'see http://www.mathworks.com/matlabcentral/fileexchange/345, or contact Peter Rydes?ter' + 'BEMCP' 'contact Christophe Phillips' + 'OPENMEEG' 'see http://gforge.inria.fr/projects/openmeeg' + 'PRTOOLS' 'see http://www.prtools.org' + 'ITAB' 'contact Stefania Della Penna' + 'BSMART' 'see http://www.brain-smart.org' + 'PEER' 'see http://fieldtrip.fcdonders.nl/development/peer' + }; + +if nargin<2 + % default is not to add the path automatically + autoadd = 0; +end + +if nargin<3 + % default is not to be silent + silent = 0; +end + +% determine whether the toolbox is installed +toolbox = upper(toolbox); +switch toolbox + case 'AFNI' + status = (exist('BrikLoad') && exist('BrikInfo')); + case 'DSS' + status = exist('dss', 'file') && exist('dss_create_state', 'file'); + case 'EEGLAB' + status = exist('runica', 'file'); + case 'NWAY' + status = exist('parafac', 'file'); + case 'SPM99' + status = exist('spm.m') && strcmp(spm('ver'),'SPM99'); + case 'SPM2' + status = exist('spm.m') && strcmp(spm('ver'),'SPM2'); + case 'SPM5' + status = exist('spm.m') && strcmp(spm('ver'),'SPM5'); + case 'SPM8' + status = exist('spm.m') && strncmp(spm('ver'),'SPM8', 4); + case 'MEG-PD' + status = (exist('rawdata') && exist('channames')); + case 'MEG-CALC' + status = (exist('megmodel') && exist('megfield') && exist('megtrans')); + case 'BIOSIG' + status = (exist('sopen') && exist('sread')); + case 'EEG' + status = (exist('ctf_read_res4') && exist('ctf_read_meg4')); + case 'EEGSF' % alternative name + status = (exist('ctf_read_res4') && exist('ctf_read_meg4')); + case 'MRI' % other functions in the mri section + status = (exist('avw_hdr_read') && exist('avw_img_read')); + case 'NEUROSHARE' + status = (exist('ns_OpenFile') && exist('ns_SetLibrary') && exist('ns_GetAnalogData')); + case 'BESA' + status = (exist('readBESAtfc') && exist('readBESAswf')); + case 'EEPROBE' + status = (exist('read_eep_avr') && exist('read_eep_cnt')); + case 'YOKOGAWA' + status = hasyokogawa('16bitBeta6'); + case 'BEOWULF' + status = (exist('evalwulf') && exist('evalwulf') && exist('evalwulf')); + case 'MENTAT' + status = (exist('pcompile') && exist('pfor') && exist('peval')); + case 'SON2' + status = (exist('SONFileHeader') && exist('SONChanList') && exist('SONGetChannel')); + case '4D-VERSION' + status = (exist('read4d') && exist('read4dhdr')); + case 'SIGNAL' + status = hasfunction('medfilt1', toolbox) && exist('butter', 'file'); % also check the availability of a toolbox license + case 'OPTIM' + status = hasfunction('fmincon', toolbox) && exist('fminunc', 'file'); % also check the availability of a toolbox license + case 'SPLINES' + status = hasfunction('bspline', toolbox) && exist('csape', 'file'); % also check the availability of a toolbox license + case 'IMAGE' + status = hasfunction('bwlabeln', toolbox); % also check the availability of a toolbox license + case 'FASTICA' + status = exist('fastica', 'file'); + case 'BRAINSTORM' + status = exist('bem_xfer'); + case 'FILEIO' + status = (exist('read_header') && exist('read_data') && exist('read_event') && exist('read_sens')); + case 'FORWINV' + status = (exist('compute_leadfield') && exist('prepare_vol_sens')); + case 'DENOISE' + status = (exist('tsr') && exist('sns')); + case 'CTF' + status = (exist('getCTFBalanceCoefs') && exist('getCTFdata')); + case 'BCI2000' + status = exist('load_bcidat'); + case 'NLXNETCOM' + status = (exist('MatlabNetComClient') && exist('NlxConnectToServer') && exist('NlxGetNewCSCData')); + case 'DIPOLI' + status = exist('dipoli.m', 'file'); + case 'MNE' + status = (exist('fiff_read_meas_info', 'file') && exist('fiff_setup_read_raw', 'file')); + case 'TCP_UDP_IP' + status = (exist('pnet', 'file') && exist('pnet_getvar', 'file') && exist('pnet_putvar', 'file')); + case 'BEMCP' + status = (exist('bem_Cij_cog', 'file') && exist('bem_Cij_lin', 'file') && exist('bem_Cij_cst', 'file')); + case 'OPENMEEG' + status = exist('openmeeg.m', 'file'); + case 'PLOTTING' + status = (exist('plot_topo', 'file') && exist('plot_mesh', 'file') && exist('plot_matrix', 'file')); + case 'PRTOOLS' + status = (exist('prversion', 'file') && exist('dataset', 'file') && exist('svc', 'file')); + case 'ITAB' + status = (exist('lcReadHeader', 'file') && exist('lcReadData', 'file')); + case 'BSMART' + status = exist('bsmart'); + case 'PEER' + status = exist('peerslave', 'file') && exist('peermaster', 'file'); + case 'CONNECTIVITY' + status = exist('ft_connectivity_corr', 'file') && exist('ft_connectivity_granger', 'file'); + otherwise + if ~silent, warning(sprintf('cannot determine whether the %s toolbox is present', toolbox)); end + status = 0; +end + +% it should be a boolean value +status = (status~=0); + +% try to determine the path of the requested toolbox +if autoadd>0 && ~status + + % for core fieldtrip modules + prefix = fileparts(which('fieldtripdefs')); + if ~status + status = myaddpath(fullfile(prefix, lower(toolbox)), silent); + end + + % for external fieldtrip modules + prefix = fullfile(fileparts(which('fieldtripdefs')), 'external'); + if ~status + status = myaddpath(fullfile(prefix, lower(toolbox)), silent); + end + + % for linux computers in the F.C. Donders Centre + prefix = '/home/common/matlab'; + if ~status && (strcmp(computer, 'GLNX86') || strcmp(computer, 'GLNXA64')) + status = myaddpath(fullfile(prefix, lower(toolbox)), silent); + end + + % for windows computers in the F.C. Donders Centre + prefix = 'h:\common\matlab'; + if ~status && (strcmp(computer, 'PCWIN') || strcmp(computer, 'PCWIN64')) + status = myaddpath(fullfile(prefix, lower(toolbox)), silent); + end + + % use the matlab subdirectory in your homedirectory, this works on unix and mac + prefix = [getenv('HOME') '/matlab']; + if ~status + status = myaddpath(fullfile(prefix, lower(toolbox)), silent); + end + + if ~status + % the toolbox is not on the path and cannot be added + sel = find(strcmp(url(:,1), toolbox)); + if ~isempty(sel) + msg = sprintf('the %s toolbox is not installed, %s', toolbox, url{sel, 2}); + else + msg = sprintf('the %s toolbox is not installed', toolbox); + end + if autoadd==1 + error(msg); + elseif autoadd==2 + warning(msg); + else + % fail silently + end + end +end + +% this function is called many times in FieldTrip and associated toolboxes +% use efficient handling if the same toolbox has been investigated before +if status + previous.(fixname(toolbox)) = status; +end + +% remember the previous path, allows us to determine on the next call +% whether the path has been modified outise of this function +previouspath = matlabpath; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% helper function +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function status = myaddpath(toolbox, silent) +if exist(toolbox, 'dir') + if ~silent, warning(sprintf('adding %s toolbox to your Matlab path', toolbox)); end + addpath(toolbox); + status = 1; +else + status = 0; +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% helper function +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function out = fixname(toolbox) +out = lower(toolbox); +out(out=='-') = '_'; % fix dashes +out(out==' ') = '_'; % fix spaces +out(out=='/') = '_'; % fix forward slashes +out(out=='\') = '_'; % fix backward slashes + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% helper function +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function status = hasfunction(funname, toolbox) +try + % call the function without any input arguments, which probably is inapropriate + feval(funname); + % it might be that the function without any input already works fine + status = true; +catch + % either the function returned an error, or the function is not available + % availability is influenced by the function being present and by having a + % license for the function, i.e. in a concurrent licensing setting it might + % be that all toolbox licenses are in use + m = lasterror; + if strcmp(m.identifier, 'MATLAB:license:checkouterror') + if nargin>1 + warning('the %s toolbox is available, but you don''t have a license for it', toolbox); + else + warning('the function ''%s'' is available, but you don''t have a license for it', funname); + end + status = false; + elseif strcmp(m.identifier, 'MATLAB:UndefinedFunction') + status = false; + else + % the function seems to be available and it gave an unknown error, + % which is to be expected with inappropriate input arguments + status = true; + end +end + diff --git a/external/fieldtrip/forward/private/inf_medium_leadfield.m b/external/fieldtrip/forward/private/inf_medium_leadfield.m new file mode 100644 index 0000000..034c02b --- /dev/null +++ b/external/fieldtrip/forward/private/inf_medium_leadfield.m @@ -0,0 +1,58 @@ +function [lf] = inf_medium_leadfield(rd, pnt, cond); + +% INF_MEDIUM_LEADFIELD calculate the infinite medium leadfield +% on positions pnt for dipole position R and conductivity cond +% +% [lf] = inf_medium_leadfield(R, pnt, cond) + +% Copyright (C) 1998, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: inf_medium_leadfield.m 946 2010-04-21 17:51:16Z roboos $ + +siz = size(rd); +if any(siz==1) + % positions are specified as a single vector + Ndipoles = prod(siz)/3; +elseif siz(2)==3 + % positions are specified as a Nx3 matrix -> reformat to a single vector + Ndipoles = siz(1); + rd = rd'; + rd = rd(:); +else + error('incorrect specification of dipole locations'); +end + +Npnt = size(pnt,1); +lf = zeros(Npnt,3*Ndipoles); +s1 = size(rd); + +if s1(1)>s1(2) + % make sure that the dipole position is a row-vector + rd = rd'; +end + +for i=1:Ndipoles + r = pnt - ones(Npnt,1) * rd((1:3) + 3*(i-1)); + R = (4*pi*cond) * (sum(r' .^2 ) .^ 1.5)'; + if any(R)==0 + warning('dipole lies on boundary of volume model'); + end + lf(:,(1:3) + 3*(i-1)) = r ./ [R R R]; +end + diff --git a/external/fieldtrip/forward/private/issubfield.m b/external/fieldtrip/forward/private/issubfield.m new file mode 100644 index 0000000..ff54060 --- /dev/null +++ b/external/fieldtrip/forward/private/issubfield.m @@ -0,0 +1,42 @@ +function [r] = issubfield(s, f) + +% ISSUBFIELD tests for the presence of a field in a structure just like the standard +% Matlab ISFIELD function, except that you can also specify nested fields +% using a '.' in the fieldname. The nesting can be arbitrary deep. +% +% Use as +% f = issubfield(s, 'fieldname') +% or as +% f = issubfield(s, 'fieldname.subfieldname') +% +% This function returns true if the field is present and false if the field +% is not present. +% +% See also ISFIELD, GETSUBFIELD, SETSUBFIELD + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: issubfield.m 951 2010-04-21 18:24:01Z roboos $ + +try + getsubfield(s, f); % if this works, then the subfield must be present + r = true; +catch + r = false; % apparently the subfield is not present +end diff --git a/external/fieldtrip/forward/private/keyval.m b/external/fieldtrip/forward/private/keyval.m new file mode 100644 index 0000000..36422c0 --- /dev/null +++ b/external/fieldtrip/forward/private/keyval.m @@ -0,0 +1,70 @@ +function [val, remaining] = keyval(key, varargin) + +% KEYVAL returns the value that corresponds to the requested key in a +% key-value pair list of variable input arguments +% +% Use as +% [val] = keyval(key, varargin) +% +% See also VARARGIN + +% Copyright (C) 2005-2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: keyval.m 1394 2010-07-10 21:02:48Z roboos $ + +if length(varargin)==1 && iscell(varargin{1}) + varargin = varargin{1}; +end + +if mod(length(varargin),2) + error('optional input arguments should come in key-value pairs, i.e. there should be an even number'); +end + +% the 1st, 3rd, etc. contain the keys, the 2nd, 4th, etc. contain the values +keys = varargin(1:2:end); +vals = varargin(2:2:end); + +% the following is faster than cellfun(@isstr, keys) +valid = false(size(keys)); +for i=1:numel(keys) + valid = ischar(keys{i}); +end + +if ~all(valid) + error('optional input arguments should come in key-value pairs, the optional input argument %d is invalid (should be a string)', i); +end + +hit = find(strcmpi(key, keys)); +if isempty(hit) + % the requested key was not found + val = []; +elseif length(hit)==1 + % the requested key was found + val = vals{hit}; +else + error('multiple input arguments with the same name'); +end + +if nargout>1 + % return the remaining input arguments with the key-value pair removed + keys(hit) = []; + vals(hit) = []; + remaining = cat(1, keys(:)', vals(:)'); + remaining = remaining(:)'; +end diff --git a/external/fieldtrip/forward/private/leadsphere_all.m b/external/fieldtrip/forward/private/leadsphere_all.m new file mode 100644 index 0000000..c3c71ef --- /dev/null +++ b/external/fieldtrip/forward/private/leadsphere_all.m @@ -0,0 +1,87 @@ +function out=leadsphere_chans(xloc,sensorloc,sensorori) +% usage: out=leadsphere_chans(xloc,sensorloc,sensorori) + +% Copyright (C) 2003, Guido Nolte +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: leadsphere_all.m 946 2010-04-21 17:51:16Z roboos $ + +[n,nsens]=size(sensorloc); %n=3 m=? +[n,ndip]=size(xloc); + + +xlocrep=reshape(repmat(xloc,1,nsens),3,ndip,nsens); +sensorlocrep=reshape(repmat(sensorloc,ndip,1),3,ndip,nsens); +sensororirep=reshape(repmat(sensorori,ndip,1),3,ndip,nsens); + +r2=norms(sensorlocrep); +veca=sensorlocrep-xlocrep; +a=norms(veca); +adotr2=dotproduct(veca,sensorlocrep); + +gradf1=scal2vec(1./r2.*(a.^2)+adotr2./a+2*a+2*r2); +gradf2=scal2vec(a+2*r2+adotr2./a); +gradf=gradf1.*sensorlocrep-gradf2.*xlocrep; + +F=a.*(r2.*a+adotr2); + +A1=scal2vec(1./F); +A2=A1.^2; + +A3=crossproduct(xlocrep,sensororirep); +A4=scal2vec(dotproduct(gradf,sensororirep)); +A5=crossproduct(xlocrep,sensorlocrep); + +out=1000*(A3.*A1-(A4.*A2).*A5); + +return; + + + +function out=crossproduct(x,y) +[n,m,k]=size(x); +out=zeros(3,m,k); +out(1,:,:)=x(2,:,:).*y(3,:,:)-x(3,:,:).*y(2,:,:); +out(2,:,:)=x(3,:,:).*y(1,:,:)-x(1,:,:).*y(3,:,:); +out(3,:,:)=x(1,:,:).*y(2,:,:)-x(2,:,:).*y(1,:,:); +return; + + +function out=dotproduct(x,y) +[n,m,k]=size(x); +outb=x(1,:,:).*y(1,:,:)+x(2,:,:).*y(2,:,:)+x(3,:,:).*y(3,:,:); +out=reshape(outb,m,k); +return; + + +function result=norms(x) +[n,m,k]=size(x); +resultb=sqrt(x(1,:,:).^2+x(2,:,:).^2+x(3,:,:).^2); +result=reshape(resultb,m,k); +return; + + +function result=scal2vec(x) +[m,k]=size(x); +% result=zeros(3,m,k); +% for i=1:3 +% result(i,:,:)=x; +% end +result=reshape(repmat(x(:)', [3 1]), [3 m k]); +return + diff --git a/external/forwinv/private/legs.m b/external/fieldtrip/forward/private/legs.m similarity index 82% rename from external/forwinv/private/legs.m rename to external/fieldtrip/forward/private/legs.m index 0fb2082..bf6e856 100644 --- a/external/forwinv/private/legs.m +++ b/external/fieldtrip/forward/private/legs.m @@ -27,9 +27,26 @@ % % gradbasis: Nx((n+1)^2-1) matrix containing in the j.th row the scalar % product of the gradient of the former with the j.th row of dir -% -% CC Guido Nolte + +% Copyright (C) 2003, Guido Nolte +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: legs.m 946 2010-04-21 17:51:16Z roboos $ [n1,n2]=size(x); diff --git a/external/forwinv/private/lmoutr.c b/external/fieldtrip/forward/private/lmoutr.c similarity index 100% rename from external/forwinv/private/lmoutr.c rename to external/fieldtrip/forward/private/lmoutr.c diff --git a/external/fieldtrip/forward/private/lmoutr.m b/external/fieldtrip/forward/private/lmoutr.m new file mode 100644 index 0000000..fc41ac5 --- /dev/null +++ b/external/fieldtrip/forward/private/lmoutr.m @@ -0,0 +1,90 @@ +function [varargout] = funname(varargin) + +% LMOUTR computes the la/mu parameters of a point projected to a triangle +% +% Use as +% [la, mu, dist] = lmoutr(v1, v2, v3, r) +% where v1, v2 and v3 are three vertices of the triangle, and r is +% the point that is projected onto the plane spanned by the vertices + +% Copyright (C) 2002-2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: lmoutr.m 946 2010-04-21 17:51:16Z roboos $ + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% This is the Matlab implementation. +% The mex file is many times faster and therefore preferred. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% function [la, mu, dist] = lmoutr(v1, v2, v3, r); +% +% % compute la/mu parameters +% vec0 = r - v1; +% vec1 = v2 - v1; +% vec2 = v3 - v2; +% vec3 = v3 - v1; +% +% tmp = [vec1' vec3'] \ (vec0'); +% la = tmp(1); +% mu = tmp(2); +% +% % determine the projection onto the plane of the triangle +% proj = v1 + la*vec1 + mu*vec3; +% +% % determine the distance from the original point to its projection +% dist = norm(r-proj); + +% compile the missing mex file on the fly +% remember the original working directory +pwdir = pwd; + +% determine the name and full path of this function +funname = mfilename('fullpath'); +mexsrc = [funname '.c']; +[mexdir, mexname] = fileparts(funname); + +try + % try to compile the mex file on the fly + warning('trying to compile MEX file from %s', mexsrc); + cd(mexdir); + + if ispc + mex -I. -c geometry.c + mex -I. -c lmoutr.c ; mex lmoutr.c lmoutr.obj geometry.obj + else + mex -I. -c geometry.c + mex -I. -c lmoutr.c ; mex -o lmoutr lmoutr.o geometry.o + end + + cd(pwdir); + success = true; + +catch + % compilation failed + disp(lasterr); + error('could not locate MEX file for %s', mexname); + cd(pwdir); + success = false; +end + +if success + % execute the mex file that was juist created + funname = mfilename; + funhandle = str2func(funname); + [varargout{1:nargout}] = funhandle(varargin{:}); +end diff --git a/external/forwinv/private/lmoutr.mexa64 b/external/fieldtrip/forward/private/lmoutr.mexa64 similarity index 100% rename from external/forwinv/private/lmoutr.mexa64 rename to external/fieldtrip/forward/private/lmoutr.mexa64 diff --git a/external/forwinv/private/lmoutr.mexglx b/external/fieldtrip/forward/private/lmoutr.mexglx similarity index 100% rename from external/forwinv/private/lmoutr.mexglx rename to external/fieldtrip/forward/private/lmoutr.mexglx diff --git a/external/forwinv/private/lmoutr.mexmaci b/external/fieldtrip/forward/private/lmoutr.mexmaci similarity index 99% rename from external/forwinv/private/lmoutr.mexmaci rename to external/fieldtrip/forward/private/lmoutr.mexmaci index 60a491a..dfa8f34 100755 Binary files a/external/forwinv/private/lmoutr.mexmaci and b/external/fieldtrip/forward/private/lmoutr.mexmaci differ diff --git a/external/forwinv/private/lmoutr.mexmaci64 b/external/fieldtrip/forward/private/lmoutr.mexmaci64 similarity index 100% rename from external/forwinv/private/lmoutr.mexmaci64 rename to external/fieldtrip/forward/private/lmoutr.mexmaci64 diff --git a/external/fieldtrip/forward/private/lmoutr.mexw32 b/external/fieldtrip/forward/private/lmoutr.mexw32 new file mode 100644 index 0000000..ea1de8b Binary files /dev/null and b/external/fieldtrip/forward/private/lmoutr.mexw32 differ diff --git a/external/forwinv/private/lmoutr.mexw64 b/external/fieldtrip/forward/private/lmoutr.mexw64 similarity index 95% rename from external/forwinv/private/lmoutr.mexw64 rename to external/fieldtrip/forward/private/lmoutr.mexw64 index 220cbb8..30fd746 100644 Binary files a/external/forwinv/private/lmoutr.mexw64 and b/external/fieldtrip/forward/private/lmoutr.mexw64 differ diff --git a/external/fieldtrip/forward/private/magnetic_dipole.m b/external/fieldtrip/forward/private/magnetic_dipole.m new file mode 100644 index 0000000..6d80827 --- /dev/null +++ b/external/fieldtrip/forward/private/magnetic_dipole.m @@ -0,0 +1,80 @@ +function [lf] = magnetic_dipole(R, pos, ori) + +% MAGNETIC_DIPOLE leadfield for a magnetic dipole in an infinite medium +% +% [lf] = magnetic_dipole(R, pos, ori) +% +% with input arguments +% R position dipole +% pos position magnetometers +% ori orientation magnetometers + +% Copyright (C) 2003, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: magnetic_dipole.m 946 2010-04-21 17:51:16Z roboos $ + +u0 = 1e-7; +nchan = size(pos,1); + +% ensure that the dipole position is a row vector +R = reshape(R, [1 3]); + +% shift the magnetometers so that the dipole is in the origin +pos = pos - repmat(R, [nchan 1]); + +% change the variable names for convenience +% R position of magnetometer, relative to dipole +% r distance of magnetometer, relative to dipole +R = pos; +r = sqrt(sum(R.^2,2)); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% this is the original code, which follows the physical formulation closely +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% magnetic field on all magnetometer positions for an x-oriented dipole +% Bmx = u0/(4*pi) * (3 * repmat(R(:,1), [1 3]) .* R - repmat([1 0 0], [nchan 1]) .* repmat(r.^2, [1 3])) ./ repmat(r.^5, [1 3]); +% magnetic field on all magnetometer positions for an y-oriented dipole +% Bmy = u0/(4*pi) * (3 * repmat(R(:,2), [1 3]) .* R - repmat([0 1 0], [nchan 1]) .* repmat(r.^2, [1 3])) ./ repmat(r.^5, [1 3]); +% magnetic field on all magnetometer positions for an z-oriented dipole +% Bmz = u0/(4*pi) * (3 * repmat(R(:,3), [1 3]) .* R - repmat([0 0 1], [nchan 1]) .* repmat(r.^2, [1 3])) ./ repmat(r.^5, [1 3]); +% compute the field along the orientation of each magnetometer for an x/y/z oriented dipole +% lf(:,1) = dot(Bmx, ori, 2); +% lf(:,2) = dot(Bmy, ori, 2); +% lf(:,3) = dot(Bmz, ori, 2); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% this is the optimized code, which make the previous computation approximately +% three times more efficent by introducing temporary variables +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +r2 = repmat(r.^2, [1 3]); +r5 = repmat(r.^5, [1 3]); +x = R(:,1); x = [x x x]; +y = R(:,2); y = [y y y]; +z = R(:,3); z = [z z z]; +mx = zeros(nchan,3); mx(:,1) = 1; +my = zeros(nchan,3); my(:,2) = 1; +mz = zeros(nchan,3); mz(:,3) = 1; +Tx = (3 * x .* R - mx .* r2); +Ty = (3 * y .* R - my .* r2); +Tz = (3 * z .* R - mz .* r2); +lf(:,1) = dot(Tx, ori, 2); +lf(:,2) = dot(Ty, ori, 2); +lf(:,3) = dot(Tz, ori, 2); +lf = u0/(4*pi) * lf ./ r5; + diff --git a/external/fieldtrip/forward/private/match_str.m b/external/fieldtrip/forward/private/match_str.m new file mode 100644 index 0000000..602b2f1 --- /dev/null +++ b/external/fieldtrip/forward/private/match_str.m @@ -0,0 +1,75 @@ +function [sel1, sel2] = match_str(a, b); + +% MATCH_STR looks for matching labels in two listst of strings +% and returns the indices into both the 1st and 2nd list of the matches. +% They will be ordered according to the first input argument. +% +% [sel1, sel2] = match_str(strlist1, strlist2) +% +% The strings can be stored as a char matrix or as an vertical array of +% cells, the matching is done for each row. + +% Copyright (C) 2000, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: match_str.m 951 2010-04-21 18:24:01Z roboos $ + +% ensure that both are cell-arrays +if isempty(a) + a = {}; +elseif ~iscell(a) + a = cellstr(a); +end +if isempty(b) + b = {}; +elseif ~iscell(b) + b = cellstr(b); +end + +% regardless of what optimizations are implemented, the code should remain +% functionally compatible to the original, which is +% for i=1:length(a) +% for j=1:length(b) +% if strcmp(a(i),b(j)) +% sel1 = [sel1; i]; +% sel2 = [sel2; j]; +% end +% end +% end + +% ensure that both are column vectors +a = a(:); +b = b(:); +Na = numel(a); +Nb = numel(b); + +% replace all unique strings by a unique number and use the fact that +% numeric comparisons are much faster than string comparisons +[dum1, dum2, c] = unique([a; b]); +a = c(1:Na); +b = c((Na+1):end); + +sel1 = []; +sel2 = []; +for i=1:length(a) + % s = find(strcmp(a(i), b)); % for string comparison + s = find(a(i)==b); % for numeric comparison + sel2 = [sel2; s]; + s(:) = i; + sel1 = [sel1; s]; +end diff --git a/external/forwinv/private/meg_forward.m b/external/fieldtrip/forward/private/meg_forward.m similarity index 78% rename from external/forwinv/private/meg_forward.m rename to external/fieldtrip/forward/private/meg_forward.m index 5f54bcb..4bbf9b2 100644 --- a/external/forwinv/private/meg_forward.m +++ b/external/fieldtrip/forward/private/meg_forward.m @@ -21,15 +21,29 @@ % % note: it is assumed that locations are in cm, and dipole moments in nAm. % Then the field is in fT. -% -% written by Guido Nolte - +% Copyright (C) 2003, Guido Nolte +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: meg_forward.m 946 2010-04-21 17:51:16Z roboos $ device_sens=forwpar.device_sens; - - field_sens_sphere=getfield_sphere(dip_par,forwpar.device_sens,forwpar.center); field=field_sens_sphere;clear field_sens_sphere; if isfield(forwpar,'device_ref') diff --git a/external/forwinv/private/meg_ini.m b/external/fieldtrip/forward/private/meg_ini.m similarity index 84% rename from external/forwinv/private/meg_ini.m rename to external/fieldtrip/forward/private/meg_ini.m index e127f95..e39335d 100644 --- a/external/forwinv/private/meg_ini.m +++ b/external/fieldtrip/forward/private/meg_ini.m @@ -27,9 +27,26 @@ % forpwar: structure containing all parameters needed for forward % calculation % note: it is assumed that locations are in cm. -% -% written by Guido Nolte +% Copyright (C) 2003, Guido Nolte +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: meg_ini.m 946 2010-04-21 17:51:16Z roboos $ if nargin==4 if order>0; diff --git a/external/fieldtrip/private/meg_leadfield1.c b/external/fieldtrip/forward/private/meg_leadfield1.c similarity index 100% rename from external/fieldtrip/private/meg_leadfield1.c rename to external/fieldtrip/forward/private/meg_leadfield1.c diff --git a/external/fieldtrip/forward/private/meg_leadfield1.m b/external/fieldtrip/forward/private/meg_leadfield1.m new file mode 100644 index 0000000..619918c --- /dev/null +++ b/external/fieldtrip/forward/private/meg_leadfield1.m @@ -0,0 +1,120 @@ +function [varargout] = funname(varargin) + +% MEG_LEADFIELD1 magnetic leadfield for a dipole in a homogenous sphere +% +% [lf] = meg_leadfield1(R, pos, ori) +% +% with input arguments +% R position dipole +% pos position magnetometers +% ori orientation magnetometers +% +% The center of the homogenous sphere is in the origin, the field +% of the dipole is not dependent on the sphere radius. +% +% This function is also implemented as MEX file. + +% adapted from Luetkenhoener, Habilschrift '92 +% optimized for speed using temporary variables +% the mex implementation is a literary copy of this + +% Copyright (C) 2002-2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: meg_leadfield1.m 946 2010-04-21 17:51:16Z roboos $ + +% compile the missing mex file on the fly +% remember the original working directory +pwdir = pwd; + +% determine the name and full path of this function +funname = mfilename('fullpath'); +mexsrc = [funname '.c']; +[mexdir, mexname] = fileparts(funname); + +try + % try to compile the mex file on the fly + warning('trying to compile MEX file from %s', mexsrc); + cd(mexdir); + mex(mexsrc); + cd(pwdir); + success = true; + +catch + % compilation failed + disp(lasterr); + error('could not locate MEX file for %s', mexname); + cd(pwdir); + success = false; +end + +if success + % execute the mex file that was juist created + funname = mfilename; + funhandle = str2func(funname); + [varargout{1:nargout}] = funhandle(varargin{:}); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% THE FOLLOWING CODE CORRESPONDS WITH THE ORIGINAL IMPLEMENTATION +% function [lf] = meg_leadfield1(R, Rm, Um); +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Nchans = size(Rm, 1); +% +% lf = zeros(Nchans,3); +% +% tmp2 = norm(R); +% +% for i=1:Nchans +% r = Rm(i,:); +% u = Um(i,:); +% +% tmp1 = norm(r); +% % tmp2 = norm(R); +% tmp3 = norm(r-R); +% tmp4 = dot(r,R); +% tmp5 = dot(r,r-R); +% tmp6 = dot(R,r-R); +% tmp7 = (tmp1*tmp2)^2 - tmp4^2; % cross(r,R)^2 +% +% alpha = 1 / (-tmp3 * (tmp1*tmp3+tmp5)); +% A = 1/tmp3 - 2*alpha*tmp2^2 - 1/tmp1; +% B = 2*alpha*tmp4; +% C = -tmp6/(tmp3^3); +% +% if tmp7. +% +% $Id: normals.m 946 2010-04-21 17:51:16Z roboos $ + +if nargin<3 + opt='vertex'; +elseif (opt(1)=='v' | opt(1)=='V') + opt='vertex'; +elseif (opt(1)=='t' | opt(1)=='T') + opt='triangle'; +else + error('invalid optional argument'); +end + +npnt = size(pnt,1); +ndhk = size(dhk,1); + +% shift to center +pnt(:,1) = pnt(:,1)-mean(pnt(:,1),1); +pnt(:,2) = pnt(:,2)-mean(pnt(:,2),1); +pnt(:,3) = pnt(:,3)-mean(pnt(:,3),1); + +% compute triangle normals +nrm_dhk = zeros(ndhk, 3); +for i=1:ndhk + v2 = pnt(dhk(i,2),:) - pnt(dhk(i,1),:); + v3 = pnt(dhk(i,3),:) - pnt(dhk(i,1),:); + nrm_dhk(i,:) = cross(v2, v3); +end + +if strcmp(opt, 'vertex') + % compute vertex normals + nrm_pnt = zeros(npnt, 3); + for i=1:ndhk + nrm_pnt(dhk(i,1),:) = nrm_pnt(dhk(i,1),:) + nrm_dhk(i,:); + nrm_pnt(dhk(i,2),:) = nrm_pnt(dhk(i,2),:) + nrm_dhk(i,:); + nrm_pnt(dhk(i,3),:) = nrm_pnt(dhk(i,3),:) + nrm_dhk(i,:); + end + % normalise the direction vectors to have length one + nrm = nrm_pnt ./ (sqrt(sum(nrm_pnt.^2, 2)) * ones(1,3)); +else + % normalise the direction vectors to have length one + nrm = nrm_dhk ./ (sqrt(sum(nrm_dhk.^2, 2)) * ones(1,3)); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% fast cross product to replace the Matlab standard version +function [c] = cross(a,b) +c = [a(2)*b(3)-a(3)*b(2) a(3)*b(1)-a(1)*b(3) a(1)*b(2)-a(2)*b(1)]; + diff --git a/external/forwinv/private/plgndr.c b/external/fieldtrip/forward/private/plgndr.c similarity index 100% rename from external/forwinv/private/plgndr.c rename to external/fieldtrip/forward/private/plgndr.c diff --git a/external/fieldtrip/forward/private/plgndr.m b/external/fieldtrip/forward/private/plgndr.m new file mode 100644 index 0000000..457767c --- /dev/null +++ b/external/fieldtrip/forward/private/plgndr.m @@ -0,0 +1,63 @@ +function [varargout] = funname(varargin) + +% PLGNDR associated Legendre function +% +% y = plgndr(n,k,x) computes the values of the associated Legendre functions +% of degree N and order K +% +% implemented as MEX file + +% the original implementation was based on "Numerical Recipes in C", version 2.0 +% but has been replaced with an equvalent function from GNU Scientific Library + +% Copyright (C) 2002, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: plgndr.m 946 2010-04-21 17:51:16Z roboos $ + +% compile the missing mex file on the fly +% remember the original working directory +pwdir = pwd; + +% determine the name and full path of this function +funname = mfilename('fullpath'); +mexsrc = [funname '.c']; +[mexdir, mexname] = fileparts(funname); + +try + % try to compile the mex file on the fly + warning('trying to compile MEX file from %s', mexsrc); + cd(mexdir); + mex(mexsrc); + cd(pwdir); + success = true; + +catch + % compilation failed + disp(lasterr); + error('could not locate MEX file for %s', mexname); + cd(pwdir); + success = false; +end + +if success + % execute the mex file that was juist created + funname = mfilename; + funhandle = str2func(funname); + [varargout{1:nargout}] = funhandle(varargin{:}); +end diff --git a/external/forwinv/private/plgndr.mexa64 b/external/fieldtrip/forward/private/plgndr.mexa64 similarity index 100% rename from external/forwinv/private/plgndr.mexa64 rename to external/fieldtrip/forward/private/plgndr.mexa64 diff --git a/external/forwinv/private/plgndr.mexglx b/external/fieldtrip/forward/private/plgndr.mexglx similarity index 100% rename from external/forwinv/private/plgndr.mexglx rename to external/fieldtrip/forward/private/plgndr.mexglx diff --git a/external/forwinv/private/plgndr.mexmaci b/external/fieldtrip/forward/private/plgndr.mexmaci similarity index 98% rename from external/forwinv/private/plgndr.mexmaci rename to external/fieldtrip/forward/private/plgndr.mexmaci index e359b3b..bef58fe 100755 Binary files a/external/forwinv/private/plgndr.mexmaci and b/external/fieldtrip/forward/private/plgndr.mexmaci differ diff --git a/external/forwinv/private/plgndr.mexmaci64 b/external/fieldtrip/forward/private/plgndr.mexmaci64 similarity index 100% rename from external/forwinv/private/plgndr.mexmaci64 rename to external/fieldtrip/forward/private/plgndr.mexmaci64 diff --git a/external/forwinv/private/plgndr.mexw32 b/external/fieldtrip/forward/private/plgndr.mexw32 similarity index 76% rename from external/forwinv/private/plgndr.mexw32 rename to external/fieldtrip/forward/private/plgndr.mexw32 index 9d44268..246c0f3 100644 Binary files a/external/forwinv/private/plgndr.mexw32 and b/external/fieldtrip/forward/private/plgndr.mexw32 differ diff --git a/external/forwinv/private/plgndr.mexw64 b/external/fieldtrip/forward/private/plgndr.mexw64 similarity index 96% rename from external/forwinv/private/plgndr.mexw64 rename to external/fieldtrip/forward/private/plgndr.mexw64 index 05ecf9e..921c30e 100644 Binary files a/external/forwinv/private/plgndr.mexw64 and b/external/fieldtrip/forward/private/plgndr.mexw64 differ diff --git a/external/fieldtrip/forward/private/progress.m b/external/fieldtrip/forward/private/progress.m new file mode 100644 index 0000000..b39afd9 --- /dev/null +++ b/external/fieldtrip/forward/private/progress.m @@ -0,0 +1,247 @@ +function progress(varargin) + +% PROGRESS shows a graphical or non-graphical progress indication similar +% to the standard Matlab WAITBAR function, but with the extra option of +% printing it in the command window as a plain text string or as a rotating +% dial. Alternatively, you can also specify it not to give feedback on the +% progress. +% +% Prior to the for-loop, you should call either +% progress('init', 'none', 'Please wait...') +% progress('init', 'gui', 'Please wait...') +% progress('init', 'etf', 'Please wait...') % estimated time to finish +% progress('init', 'dial', 'Please wait...') % rotating dial +% progress('init', 'textbar', 'Please wait...') % ascii progress bar +% progress('init', 'text', 'Please wait...') +% progress('init', 'textcr', 'Please wait...') % force cariage return +% progress('init', 'textnl', 'Please wait...') % force newline +% +% In each iteration of the for-loop, you should call either +% progress(x) % only show percentage +% progress(x, 'Processing event %d from %d', i, N) % show string, x=i/N +% +% After finishing the for-loop, you should call +% progress('close') +% +% Here is an example for the use of a progress indicator +% progress('init', 'etf', 'Please wait...'); +% for i=1:42 +% progress(i/42, 'Processing event %d from %d', i, 42); +% pause(0.1); +% end +% progress('close') + +% Copyright (C) 2004-2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: progress.m 951 2010-04-21 18:24:01Z roboos $ + +persistent p % the previous value of the progress +persistent c % counter for the number of updates that is done +persistent t0 % initial time, required for ETF +persistent p0 % initial percentage, required for ETF +persistent t % type of feedback, string with none, gui, text, textcr, textnl +persistent h % the handle of the dialog (in case of type=gui) +persistent a % the angle in degrees, for dial or textbar +persistent s % the string containing the title + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +if nargin>1 && ischar(varargin{1}) && strcmp(varargin{1}, 'init') + a = 0; + p = 0; + h = 0; + c = 0; + % determine the type of feedback + t = varargin{2}; + % determine the title of the dialog + if nargin>2 + s = varargin{3}; + else + s = ''; + end + switch t + case 'gui' + % initialise the waitbar dialog + if ~isempty(s) + h = waitbar(0, s); + else + h = waitbar(0, 'Please wait'); + end + case {'text', 'textnl', 'textcr'} + if ~isempty(s) + % print the title to the screen and go to the next line + fprintf('%s\n', s) + end + end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +elseif nargin==1 && ischar(varargin{1}) && strcmp(varargin{1}, 'close') + switch t + case 'gui' + % close the waitbar dialog + close(h); + case {'textcr', 'dial', 'textbar'} + % finish by going to the next line + fprintf('\n'); + end + % reset these to the defaults + a = 0; + h = 0; + p = 0; + t = 'none'; + s = ''; + t0 = []; + p0 = []; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +else + if strcmp(t, 'dial') + % display should always be updated for the dial + % continue; + elseif (varargin{1}-p)<0.01 && strcmp(t, 'gui') + % display should not be updated it the difference is less than one percent + return; + elseif (varargin{1}-p)<0.01 && strcmp(t, 'textbar') + % display should not be updated it the difference is less than one percent + return; + elseif (varargin{1}-p)<0.01 && strcmp(t, 'etf') + % display should not be updated it the difference is less than one percent + return; + end + + % count the number of updates, for debugging + c = c+1; + + % remember the current value for the next function call + p = varargin{1}; + + switch t + case 'gui' + % update the the length of the bar in the waitbar dialog + waitbar(varargin{1}, h); + + case 'etf' + % compute the estimated time that the computation still needs to finish + if isempty(t0) || isempty(p0) + t0 = clock; + p0 = p; + end + elapsed = etime(clock, t0); + if nargin>1 && ~isempty(varargin{2}) + % include the specified string + fprintf(varargin{2:end}); + fprintf(' - estimated time to finish is %d seconds\n', round(elapsed*(1-p)/(p-p0))); + else + % only print the estimated time to finish + fprintf(' - estimated time to finish is %d seconds\n', round(elapsed*(1-p)/(p-p0))); + end + + case 'dial' + dial = '|/-\|/-\'; + if ~isempty(s) + % print the title and draw a new hand of the rotating dial + fprintf('\r%s %s', s, dial(1+a/45)); + else + % draw a new hand of the rotating dial + fprintf('\r%s', dial(1+a/45)); + end + % increment the angle with 45 degrees + a = a + 45; + if a==360 + % reset the angle to 0 degrees + a = 0; + end + + case 'textbar' + dial = '|/-\|/-\'; + % construct the line looking like [------/ ] + len = 75 - length(s) - 3; + len1 = round(p*len); % number of '-' characters before the dial + len2 = len - len1; % number of ' ' characters after the dial + line = [s, ' [' repmat('-',1,len1), dial(1+a/45), repmat(' ',1,len2) ,']']; + fprintf('\r%s', line); + % increment the angle with 45 degrees + a = a + 45; + if a==360 + % reset the angle to 0 degrees + a = 0; + end + + case 'text' + if nargin>1 + % print the string as it is + fprintf(varargin{2:end}); + else + fprintf('%6.2f %%\n', 100*varargin{1}); + end + + case 'textnl' + if nargin>1 + % ensure that the string ends with a newline + if length(varargin{2})>1 && all(varargin{2}((end-1):end) == '\r') + varargin{2}((end-1):end) = '\n'; + elseif length(varargin{2})>1 && ~all(varargin{2}((end-1):end) == '\n') + varargin{2}((end+1):(end+2)) = '\n'; + elseif length(varargin{2})<2 + varargin{2}((end+1):(end+2)) = '\n'; + end + fprintf(varargin{2:end}); + else + fprintf('%6.2f %%\n', 100*varargin{1}); + end + + case 'textcr' + if nargin>1 + % ensure that the string ends with a cariage return + if length(varargin{2})>1 && all(varargin{2}((end-1):end) == '\n') + varargin{2}((end-1):end) = '\r'; + elseif length(varargin{2})>1 && ~all(varargin{2}((end-1):end) == '\r') + varargin{2}((end+1):(end+2)) = '\r'; + elseif length(varargin{2})<2 + varargin{2}((end+1):(end+2)) = '\r'; + end + fprintf(varargin{2:end}); + else + fprintf('%6.2f %%\r', 100*varargin{1}); + end + + end % case gui, dial, text, textnl, textcr +end % updating the displayed value + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% some test code follows +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% progress('init', 'gui'); for i=1:100, progress(i/100, '%d/%d\r', i, 100); end; progress('close') +% progress('init', 'dial'); for i=1:100, progress(i/100, '%d/%d\r', i, 100); end; progress('close') +% progress('init', 'none'); for i=1:100, progress(i/100, '%d/%d\r', i, 100); end; progress('close') + +% progress('init', 'text'); for i=1:100, progress(i/100, '%d/%d' , i, 100); end; progress('close') +% progress('init', 'text'); for i=1:100, progress(i/100, '%d/%d\n', i, 100); end; progress('close') +% progress('init', 'text'); for i=1:100, progress(i/100, '%d/%d\r', i, 100); end; progress('close') + +% progress('init', 'textnl'); for i=1:100, progress(i/100, '%d/%d' , i, 100); end; progress('close') +% progress('init', 'textnl'); for i=1:100, progress(i/100, '%d/%d\n', i, 100); end; progress('close') +% progress('init', 'textnl'); for i=1:100, progress(i/100, '%d/%d\r', i, 100); end; progress('close') + +% progress('init', 'textcr'); for i=1:100, progress(i/100, '%d/%d' , i, 100); end; progress('close') +% progress('init', 'textcr'); for i=1:100, progress(i/100, '%d/%d\n', i, 100); end; progress('close') +% progress('init', 'textcr'); for i=1:100, progress(i/100, '%d/%d\r', i, 100); end; progress('close') + + diff --git a/external/fieldtrip/forward/private/project_elec.m b/external/fieldtrip/forward/private/project_elec.m new file mode 100644 index 0000000..6ff36e0 --- /dev/null +++ b/external/fieldtrip/forward/private/project_elec.m @@ -0,0 +1,55 @@ +function [el] = project_elec(elc, pnt, tri) + +% PROJECT_ELEC projects electrodes on a triangulated surface +% and returns triangle index, la/mu parameters and distance +% +% [el] = project_elec(elc, pnt, tri) +% +% it returns a Nx4 matrix with [tri, la, mu, dist] for each electrode +% +% See also TRANSFER_ELEC + +% Copyright (C) 1999-2002, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: project_elec.m 946 2010-04-21 17:51:16Z roboos $ + +Nelc = size(elc,1); +Npnt = size(pnt,1); +Ntri = size(tri,1); +el = zeros(Nelc, 4); + +for i=1:Nelc + smallest_dist = Inf; + + for j=1:Ntri + [proj, dist] = ptriproj(pnt(tri(j,1),:), pnt(tri(j,2),:), pnt(tri(j,3),:), elc(i,:), 1); + if dist. +% +% $Id: ptriproj.m 946 2010-04-21 17:51:16Z roboos $ + +% compile the missing mex file on the fly +% remember the original working directory +pwdir = pwd; + +% determine the name and full path of this function +funname = mfilename('fullpath'); +mexsrc = [funname '.c']; +[mexdir, mexname] = fileparts(funname); + +try + % try to compile the mex file on the fly + warning('trying to compile MEX file from %s', mexsrc); + cd(mexdir); + + if ispc + mex -I. -c geometry.c + mex -I. -c ptriproj.c ; mex ptriproj.c ptriproj.obj geometry.obj + else + mex -I. -c geometry.c + mex -I. -c ptriproj.c ; mex -o ptriproj ptriproj.o geometry.o + end + + cd(pwdir); + success = true; + +catch + % compilation failed + disp(lasterr); + error('could not locate MEX file for %s', mexname); + cd(pwdir); + success = false; +end + +if success + % execute the mex file that was juist created + funname = mfilename; + funhandle = str2func(funname); + [varargout{1:nargout}] = funhandle(varargin{:}); +end diff --git a/external/forwinv/private/ptriproj.mexa64 b/external/fieldtrip/forward/private/ptriproj.mexa64 similarity index 100% rename from external/forwinv/private/ptriproj.mexa64 rename to external/fieldtrip/forward/private/ptriproj.mexa64 diff --git a/external/forwinv/private/ptriproj.mexglx b/external/fieldtrip/forward/private/ptriproj.mexglx similarity index 100% rename from external/forwinv/private/ptriproj.mexglx rename to external/fieldtrip/forward/private/ptriproj.mexglx diff --git a/external/forwinv/private/ptriproj.mexmaci b/external/fieldtrip/forward/private/ptriproj.mexmaci similarity index 99% rename from external/forwinv/private/ptriproj.mexmaci rename to external/fieldtrip/forward/private/ptriproj.mexmaci index 4a89244..7301ba5 100755 Binary files a/external/forwinv/private/ptriproj.mexmaci and b/external/fieldtrip/forward/private/ptriproj.mexmaci differ diff --git a/external/forwinv/private/ptriproj.mexmaci64 b/external/fieldtrip/forward/private/ptriproj.mexmaci64 similarity index 100% rename from external/forwinv/private/ptriproj.mexmaci64 rename to external/fieldtrip/forward/private/ptriproj.mexmaci64 diff --git a/external/forwinv/private/ptriproj.mexw32 b/external/fieldtrip/forward/private/ptriproj.mexw32 similarity index 79% rename from external/forwinv/private/ptriproj.mexw32 rename to external/fieldtrip/forward/private/ptriproj.mexw32 index 83e243c..663259f 100644 Binary files a/external/forwinv/private/ptriproj.mexw32 and b/external/fieldtrip/forward/private/ptriproj.mexw32 differ diff --git a/external/forwinv/private/ptriproj.mexw64 b/external/fieldtrip/forward/private/ptriproj.mexw64 similarity index 96% rename from external/forwinv/private/ptriproj.mexw64 rename to external/fieldtrip/forward/private/ptriproj.mexw64 index 8a2ce85..f31cd29 100644 Binary files a/external/forwinv/private/ptriproj.mexw64 and b/external/fieldtrip/forward/private/ptriproj.mexw64 differ diff --git a/external/fieldtrip/forward/private/rmsubfield.m b/external/fieldtrip/forward/private/rmsubfield.m new file mode 100644 index 0000000..4d8752f --- /dev/null +++ b/external/fieldtrip/forward/private/rmsubfield.m @@ -0,0 +1,46 @@ +function [s] = rmsubfield(s, f, v); + +% RMSUBFIELD removes the contents of the specified field from a structure +% just like the standard Matlab RMFIELD function, except that you can also +% specify nested fields using a '.' in the fieldname. The nesting can be +% arbitrary deep. +% +% Use as +% s = rmsubfield(s, 'fieldname') +% or as +% s = rmsubfield(s, 'fieldname.subfieldname') +% +% See also SETFIELD, GETSUBFIELD, ISSUBFIELD + +% Copyright (C) 2006, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: rmsubfield.m 951 2010-04-21 18:24:01Z roboos $ + +if ~isstr(f) + error('incorrect input argument for fieldname'); +end + +% remove the nested subfield using recursion +[t, f] = strtok(f, '.'); +if any(f=='.') + u = rmsubfield(getfield(s, t), f); + s = setfield(s, t, u); +else + s = rmfield(s, t); +end diff --git a/external/fieldtrip/forward/private/setsubfield.m b/external/fieldtrip/forward/private/setsubfield.m new file mode 100644 index 0000000..18f4793 --- /dev/null +++ b/external/fieldtrip/forward/private/setsubfield.m @@ -0,0 +1,46 @@ +function [s] = setsubfield(s, f, v); + +% SETSUBFIELD sets the contents of the specified field to a specified value +% just like the standard Matlab SETFIELD function, except that you can also +% specify nested fields using a '.' in the fieldname. The nesting can be +% arbitrary deep. +% +% Use as +% s = setsubfield(s, 'fieldname', value) +% or as +% s = setsubfield(s, 'fieldname.subfieldname', value) +% +% See also SETFIELD, GETSUBFIELD, ISSUBFIELD + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: setsubfield.m 951 2010-04-21 18:24:01Z roboos $ + +if ~isstr(f) + error('incorrect input argument for fieldname'); +end + +t = {}; +while (1) + [t{end+1}, f] = strtok(f, '.'); + if isempty(f) + break + end +end +s = setfield(s, t{:}, v); diff --git a/external/forwinv/private/solid_angle.c b/external/fieldtrip/forward/private/solid_angle.c similarity index 100% rename from external/forwinv/private/solid_angle.c rename to external/fieldtrip/forward/private/solid_angle.c diff --git a/external/fieldtrip/forward/private/solid_angle.m b/external/fieldtrip/forward/private/solid_angle.m new file mode 100644 index 0000000..93a3c77 --- /dev/null +++ b/external/fieldtrip/forward/private/solid_angle.m @@ -0,0 +1,124 @@ +function [varargout] = funname(varargin) + +% SOLID_ANGLE of a planar triangle as seen from the origin +% +% The solid angle W subtended by a surface S is defined as the surface +% area W of a unit sphere covered by the surface's projection onto the +% sphere. Solid angle is measured in steradians, and the solid angle +% corresponding to all of space being subtended is 4*pi sterradians. +% +% Use: +% [w] = solid_angle(v1, v2, v3) +% or +% [w] = solid_angle(pnt, tri) +% where v1, v2 and v3 are the vertices of a single triangle in 3D or +% pnt and tri contain a description of a triangular mesh (this will +% compute the solid angle for each triangle) + +% Copyright (C) 2003-2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: solid_angle.m 946 2010-04-21 17:51:16Z roboos $ + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% The first section contains the plain Matlab implementation. The mex file +% is many times faster and this function is called so frequently (for +% large meshes), that the mex file should be used in all practical cases. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% function [w] = solid_angle(r1, r2, r3); +% +% if nargin==2 +% % reassign the input arguments +% pnt = r1; +% tri = r2; +% npnt = size(pnt,1); +% ntri = size(tri,1); +% w = zeros(ntri,1); +% % compute solid angle for each triangle +% for i=1:ntri +% r1 = pnt(tri(i,1),:); +% r2 = pnt(tri(i,2),:); +% r3 = pnt(tri(i,3),:); +% w(i) = solid_angle(r1, r2, r3); +% end +% return +% elseif nargin==3 +% % compute the solid angle for this triangle +% cp23_x = r2(2) * r3(3) - r2(3) * r3(2); +% cp23_y = r2(3) * r3(1) - r2(1) * r3(3); +% cp23_z = r2(1) * r3(2) - r2(2) * r3(1); +% nom = cp23_x * r1(1) + cp23_y * r1(2) + cp23_z * r1(3); +% n1 = sqrt (r1(1) * r1(1) + r1(2) * r1(2) + r1(3) * r1(3)); +% n2 = sqrt (r2(1) * r2(1) + r2(2) * r2(2) + r2(3) * r2(3)); +% n3 = sqrt (r3(1) * r3(1) + r3(2) * r3(2) + r3(3) * r3(3)); +% ip12 = r1(1) * r2(1) + r1(2) * r2(2) + r1(3) * r2(3); +% ip23 = r2(1) * r3(1) + r2(2) * r3(2) + r2(3) * r3(3); +% ip13 = r1(1) * r3(1) + r1(2) * r3(2) + r1(3) * r3(3); +% den = n1 * n2 * n3 + ip12 * n3 + ip23 * n1 + ip13 * n2; +% if (nom == 0) +% if (den <= 0) +% w = nan; +% return +% end +% end +% w = 2 * atan2 (nom, den); +% return +% else +% error('invalid input'); +% end + +% compile the missing mex file on the fly +% remember the original working directory +pwdir = pwd; + +% determine the name and full path of this function +funname = mfilename('fullpath'); +mexsrc = [funname '.c']; +[mexdir, mexname] = fileparts(funname); + +try + % try to compile the mex file on the fly + warning('trying to compile MEX file from %s', mexsrc); + cd(mexdir); + + if ispc + mex -I. -c geometry.c + mex -I. -c solid_angle.c ; mex solid_angle.c solid_angle.obj geometry.obj + else + mex -I. -c geometry.c + mex -I. -c solid_angle.c ; mex -o solid_angle solid_angle.o geometry.o + end + + cd(pwdir); + success = true; + +catch + % compilation failed + disp(lasterr); + error('could not locate MEX file for %s', mexname); + cd(pwdir); + success = false; +end + +if success + % execute the mex file that was juist created + funname = mfilename; + funhandle = str2func(funname); + [varargout{1:nargout}] = funhandle(varargin{:}); +end + diff --git a/external/forwinv/private/solid_angle.mexa64 b/external/fieldtrip/forward/private/solid_angle.mexa64 similarity index 100% rename from external/forwinv/private/solid_angle.mexa64 rename to external/fieldtrip/forward/private/solid_angle.mexa64 diff --git a/external/forwinv/private/solid_angle.mexglx b/external/fieldtrip/forward/private/solid_angle.mexglx similarity index 100% rename from external/forwinv/private/solid_angle.mexglx rename to external/fieldtrip/forward/private/solid_angle.mexglx diff --git a/external/fieldtrip/forward/private/solid_angle.mexmaci b/external/fieldtrip/forward/private/solid_angle.mexmaci new file mode 100755 index 0000000..26b57e0 Binary files /dev/null and b/external/fieldtrip/forward/private/solid_angle.mexmaci differ diff --git a/external/forwinv/private/solid_angle.mexmaci64 b/external/fieldtrip/forward/private/solid_angle.mexmaci64 similarity index 100% rename from external/forwinv/private/solid_angle.mexmaci64 rename to external/fieldtrip/forward/private/solid_angle.mexmaci64 diff --git a/external/fieldtrip/forward/private/solid_angle.mexw32 b/external/fieldtrip/forward/private/solid_angle.mexw32 new file mode 100644 index 0000000..a72e810 Binary files /dev/null and b/external/fieldtrip/forward/private/solid_angle.mexw32 differ diff --git a/external/fieldtrip/forward/private/solid_angle.mexw64 b/external/fieldtrip/forward/private/solid_angle.mexw64 new file mode 100644 index 0000000..33f902e Binary files /dev/null and b/external/fieldtrip/forward/private/solid_angle.mexw64 differ diff --git a/external/fieldtrip/forward/private/sphfit.m b/external/fieldtrip/forward/private/sphfit.m new file mode 100644 index 0000000..5b4b61d --- /dev/null +++ b/external/fieldtrip/forward/private/sphfit.m @@ -0,0 +1,115 @@ +function [center,radius]=sphfit(vc,Ni,stopth) +% fits a sphere to a set of surface points +% usage: [center,radius]=sphfit(vc,Ni,stopth) +% +% input: +% vc nx3 matrix, where each row represents the location +% of one surface point. vc can have more than 3 columns +% (e.g. orientations) - then only the first 3 columns are used +% Ni number of iteration requested, 20 by default +% stopth stopping threshold used for the relative difference between 2 +% succeessive estimates of the radius. Fixed 10^-6 by default +% If stopth<0, then no stopping till the end of the Ni iterations +% +% center 1x3 vector denoting the center +% radius scalar denoting the radius +% +% written by Guido Nolte +% updated by Christophe Phillips, 2009/1/19 +% - add the number of iterations as input, use 5 as default +% - add a stopping criteria based on the relative difference between 2 +% successive estimates of the radius. +% If rel_diff<1e-6 (default of use fixed), then break out. + +% Copyright (C) 2003, Guido Nolte +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: sphfit.m 946 2010-04-21 17:51:16Z roboos $ + +if nargin<2 || isempty(Ni) + Ni = 20; +end + +if nargin<3 || isempty(stopth) + stopth = 1e-6; +end + +vc=vc(:,1:3); +[nvc,ndum]=size(vc); + +center_0=mean(vc); +vcx=vc-repmat(center_0,nvc,1); +radius_0=mean(sqrt(vcx(:,1).^2+vcx(:,2).^2+vcx(:,3).^2)); + +alpha=1; +rd = 1; +err_0=costfun(vc,center_0,radius_0); + +for k=1:Ni; + + [center_new,radius_new]=lm1step(vc,center_0,radius_0,alpha); + + err_new=costfun(vc,center_new,radius_new); + % disp([k,err_0,err_new,center_new,radius_new]); + + if err_new. +% +% $Id: transfer_elec.m 946 2010-04-21 17:51:16Z roboos $ + +Npnt = size(pnt,1); +Ntri = size(tri,1); +Nel = size(el,1); + +tra = zeros(Nel, Npnt); + +for i=1:Nel + tra(i, tri(el(i,1), 1)) = 1 - el(i,2) - el(i,3); + tra(i, tri(el(i,1), 2)) = el(i,2); + tra(i, tri(el(i,1), 3)) = el(i,3); +end + diff --git a/external/forwinv/private/triangle4pt.m b/external/fieldtrip/forward/private/triangle4pt.m old mode 100755 new mode 100644 similarity index 91% rename from external/forwinv/private/triangle4pt.m rename to external/fieldtrip/forward/private/triangle4pt.m index cbfa6c2..1b93570 --- a/external/forwinv/private/triangle4pt.m +++ b/external/fieldtrip/forward/private/triangle4pt.m @@ -33,14 +33,8 @@ % % written by Christophe Phillips, 2009/01/19 % Cyclotron Research Centre, University of li?ge, belgium - -% $Log: triangle4pt.m,v $ -% Revision 1.4 2009/04/30 16:59:49 vlalit -% Bug fix for the problem of too flat mesh surfaces as suggested by Christophe -% -% Revision 1.3 2009/04/01 13:26:05 roboos -% use Taubin's method of sphere fitting (fitsphere) instead of the iterative implementation by Guido Nolte % +% $Id: triangle4pt.m 946 2010-04-21 17:51:16Z roboos $ Ns = length(vol.bnd); for ii=1:Ns % treat each mesh one at a time diff --git a/external/fieldtrip/forward/private/warp_apply.m b/external/fieldtrip/forward/private/warp_apply.m new file mode 100644 index 0000000..290a991 --- /dev/null +++ b/external/fieldtrip/forward/private/warp_apply.m @@ -0,0 +1,166 @@ +function [warped] = warp_apply(M, input, method); + +% WARP_APPLY performs a 3D linear or nonlinear transformation on the input +% coordinates, similar to those in AIR 3.08. You can find technical +% documentation on warping in general at http://bishopw.loni.ucla.edu/AIR3 +% +% Use as +% [warped] = warp_apply(M, input, method) +% where +% M vector or matrix with warping parameters +% input Nx3 matrix with coordinates +% warped Nx3 matrix with coordinates +% method string describing the warping method +% +% The methods 'nonlin0', 'nonlin2' ... 'nonlin5' specify a +% polynomial transformation. The size of the transformation matrix +% depends on the order of the warp +% zeroth order : 1 parameter per coordinate (translation) +% first order : 4 parameters per coordinate (total 12, affine) +% second order : 10 parameters per coordinate +% third order : 20 parameters per coordinate +% fourth order : 35 parameters per coordinate +% fifth order : 56 parameters per coordinate (total 168) +% The size of M should be 3xP, where P is the number of parameters +% per coordinate. Alternatively, you can specify the method to be +% 'nonlinear', where the order will be determined from teh size of +% the matrix M. +% +% If the method 'homogeneous' is selected, the input matrix M should be +% a 4x4 homogenous transformation matrix. +% +% If any other method is selected, it is assumed that it specifies +% the name of an auxiliary function that will, when given the input +% parameter vector M, return an 4x4 homogenous transformation +% matrix. Supplied functions in teh warping toolbox are translate, +% rotate, scale, rigidbody, globalrescale, traditional, affine, +% perspective. + +% Copyright (C) 2000-2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: warp_apply.m 945 2010-04-21 17:41:20Z roboos $ + +if nargin<3 && all(size(M)==4) + % no specific transformation mode has been selected + % it looks like a homogenous transformation matrix + method = 'homogenous'; +elseif nargin<3 + % the default method is 'nonlinear' + method = 'nonlinear'; +end + +if size(input,2)==2 + % convert the input points from 2D to 3D representation + input(:,3) = 0; + input3d = false; +else + input3d = true; +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% nonlinear warping +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +if any(strcmp(method, {'nonlinear', 'nonlin0', 'nonlin1', 'nonlin2', 'nonlin3', 'nonlin4', 'nonlin5'})) + x = input(:,1); + y = input(:,2); + z = input(:,3); + s = size(M); + + if s(1)~=3 + error('invalid size of nonlinear transformation matrix'); + elseif strcmp(method, 'nonlin0') & s(2)~=1 + error('invalid size of nonlinear transformation matrix'); + elseif strcmp(method, 'nonlin1') & s(2)~=4 + error('invalid size of nonlinear transformation matrix'); + elseif strcmp(method, 'nonlin2') & s(2)~=10 + error('invalid size of nonlinear transformation matrix'); + elseif strcmp(method, 'nonlin3') & s(2)~=20 + error('invalid size of nonlinear transformation matrix'); + elseif strcmp(method, 'nonlin4') & s(2)~=35 + error('invalid size of nonlinear transformation matrix'); + elseif strcmp(method, 'nonlin5') & s(2)~=56 + error('invalid size of nonlinear transformation matrix'); + end + + if s(2)==1 + % this is a translation, which in a strict sense is not the 0th order nonlinear transformation + xx = M(1,1) + x; + yy = M(2,1) + y; + zz = M(3,1) + z; + elseif s(2)==4 + xx = M(1,1) + M(1,2)*x + M(1,3)*y + M(1,4)*z; + yy = M(2,1) + M(2,2)*x + M(2,3)*y + M(2,4)*z; + zz = M(3,1) + M(3,2)*x + M(3,3)*y + M(3,4)*z; + elseif s(2)==10 + xx = M(1,1) + M(1,2)*x + M(1,3)*y + M(1,4)*z + M(1,5)*x.*x + M(1,6)*x.*y + M(1,7)*x.*z + M(1,8)*y.*y + M(1,9)*y.*z + M(1,10)*z.*z; + yy = M(2,1) + M(2,2)*x + M(2,3)*y + M(2,4)*z + M(2,5)*x.*x + M(2,6)*x.*y + M(2,7)*x.*z + M(2,8)*y.*y + M(2,9)*y.*z + M(2,10)*z.*z; + zz = M(3,1) + M(3,2)*x + M(3,3)*y + M(3,4)*z + M(3,5)*x.*x + M(3,6)*x.*y + M(3,7)*x.*z + M(3,8)*y.*y + M(3,9)*y.*z + M(3,10)*z.*z; + elseif s(2)==20 + xx = M(1,1) + M(1,2)*x + M(1,3)*y + M(1,4)*z + M(1,5)*x.*x + M(1,6)*x.*y + M(1,7)*x.*z + M(1,8)*y.*y + M(1,9)*y.*z + M(1,10)*z.*z + M(1,11)*x.*x.*x + M(1,12)*x.*x.*y + M(1,13)*x.*x.*z + M(1,14)*x.*y.*y + M(1,15)*x.*y.*z + M(1,16)*x.*z.*z + M(1,17)*y.*y.*y + M(1,18)*y.*y.*z + M(1,19)*y.*z.*z + M(1,20)*z.*z.*z; + yy = M(2,1) + M(2,2)*x + M(2,3)*y + M(2,4)*z + M(2,5)*x.*x + M(2,6)*x.*y + M(2,7)*x.*z + M(2,8)*y.*y + M(2,9)*y.*z + M(2,10)*z.*z + M(2,11)*x.*x.*x + M(2,12)*x.*x.*y + M(2,13)*x.*x.*z + M(2,14)*x.*y.*y + M(2,15)*x.*y.*z + M(2,16)*x.*z.*z + M(2,17)*y.*y.*y + M(2,18)*y.*y.*z + M(2,19)*y.*z.*z + M(2,20)*z.*z.*z; + zz = M(3,1) + M(3,2)*x + M(3,3)*y + M(3,4)*z + M(3,5)*x.*x + M(3,6)*x.*y + M(3,7)*x.*z + M(3,8)*y.*y + M(3,9)*y.*z + M(3,10)*z.*z + M(3,11)*x.*x.*x + M(3,12)*x.*x.*y + M(3,13)*x.*x.*z + M(3,14)*x.*y.*y + M(3,15)*x.*y.*z + M(3,16)*x.*z.*z + M(3,17)*y.*y.*y + M(3,18)*y.*y.*z + M(3,19)*y.*z.*z + M(3,20)*z.*z.*z; + elseif s(2)==35 + xx = M(1,1) + M(1,2)*x + M(1,3)*y + M(1,4)*z + M(1,5)*x.*x + M(1,6)*x.*y + M(1,7)*x.*z + M(1,8)*y.*y + M(1,9)*y.*z + M(1,10)*z.*z + M(1,11)*x.*x.*x + M(1,12)*x.*x.*y + M(1,13)*x.*x.*z + M(1,14)*x.*y.*y + M(1,15)*x.*y.*z + M(1,16)*x.*z.*z + M(1,17)*y.*y.*y + M(1,18)*y.*y.*z + M(1,19)*y.*z.*z + M(1,20)*z.*z.*z + M(1,21)*x.*x.*x.*x + M(1,22)*x.*x.*x.*y + M(1,23)*x.*x.*x.*z + M(1,24)*x.*x.*y.*y + M(1,25)*x.*x.*y.*z + M(1,26)*x.*x.*z.*z + M(1,27)*x.*y.*y.*y + M(1,28)*x.*y.*y.*z + M(1,29)*x.*y.*z.*z + M(1,30)*x.*z.*z.*z + M(1,31)*y.*y.*y.*y + M(1,32)*y.*y.*y.*z + M(1,33)*y.*y.*z.*z + M(1,34)*y.*z.*z.*z + M(1,35)*z.*z.*z.*z; + yy = M(2,1) + M(2,2)*x + M(2,3)*y + M(2,4)*z + M(2,5)*x.*x + M(2,6)*x.*y + M(2,7)*x.*z + M(2,8)*y.*y + M(2,9)*y.*z + M(2,10)*z.*z + M(2,11)*x.*x.*x + M(2,12)*x.*x.*y + M(2,13)*x.*x.*z + M(2,14)*x.*y.*y + M(2,15)*x.*y.*z + M(2,16)*x.*z.*z + M(2,17)*y.*y.*y + M(2,18)*y.*y.*z + M(2,19)*y.*z.*z + M(2,20)*z.*z.*z + M(2,21)*x.*x.*x.*x + M(2,22)*x.*x.*x.*y + M(2,23)*x.*x.*x.*z + M(2,24)*x.*x.*y.*y + M(2,25)*x.*x.*y.*z + M(2,26)*x.*x.*z.*z + M(2,27)*x.*y.*y.*y + M(2,28)*x.*y.*y.*z + M(2,29)*x.*y.*z.*z + M(2,30)*x.*z.*z.*z + M(2,31)*y.*y.*y.*y + M(2,32)*y.*y.*y.*z + M(2,33)*y.*y.*z.*z + M(2,34)*y.*z.*z.*z + M(2,35)*z.*z.*z.*z; + zz = M(3,1) + M(3,2)*x + M(3,3)*y + M(3,4)*z + M(3,5)*x.*x + M(3,6)*x.*y + M(3,7)*x.*z + M(3,8)*y.*y + M(3,9)*y.*z + M(3,10)*z.*z + M(3,11)*x.*x.*x + M(3,12)*x.*x.*y + M(3,13)*x.*x.*z + M(3,14)*x.*y.*y + M(3,15)*x.*y.*z + M(3,16)*x.*z.*z + M(3,17)*y.*y.*y + M(3,18)*y.*y.*z + M(3,19)*y.*z.*z + M(3,20)*z.*z.*z + M(3,21)*x.*x.*x.*x + M(3,22)*x.*x.*x.*y + M(3,23)*x.*x.*x.*z + M(3,24)*x.*x.*y.*y + M(3,25)*x.*x.*y.*z + M(3,26)*x.*x.*z.*z + M(3,27)*x.*y.*y.*y + M(3,28)*x.*y.*y.*z + M(3,29)*x.*y.*z.*z + M(3,30)*x.*z.*z.*z + M(3,31)*y.*y.*y.*y + M(3,32)*y.*y.*y.*z + M(3,33)*y.*y.*z.*z + M(3,34)*y.*z.*z.*z + M(3,35)*z.*z.*z.*z; + elseif s(2)==56 + xx = M(1,1) + M(1,2)*x + M(1,3)*y + M(1,4)*z + M(1,5)*x.*x + M(1,6)*x.*y + M(1,7)*x.*z + M(1,8)*y.*y + M(1,9)*y.*z + M(1,10)*z.*z + M(1,11)*x.*x.*x + M(1,12)*x.*x.*y + M(1,13)*x.*x.*z + M(1,14)*x.*y.*y + M(1,15)*x.*y.*z + M(1,16)*x.*z.*z + M(1,17)*y.*y.*y + M(1,18)*y.*y.*z + M(1,19)*y.*z.*z + M(1,20)*z.*z.*z + M(1,21)*x.*x.*x.*x + M(1,22)*x.*x.*x.*y + M(1,23)*x.*x.*x.*z + M(1,24)*x.*x.*y.*y + M(1,25)*x.*x.*y.*z + M(1,26)*x.*x.*z.*z + M(1,27)*x.*y.*y.*y + M(1,28)*x.*y.*y.*z + M(1,29)*x.*y.*z.*z + M(1,30)*x.*z.*z.*z + M(1,31)*y.*y.*y.*y + M(1,32)*y.*y.*y.*z + M(1,33)*y.*y.*z.*z + M(1,34)*y.*z.*z.*z + M(1,35)*z.*z.*z.*z + M(1,36)*x.*x.*x.*x.*x + M(1,37)*x.*x.*x.*x.*y + M(1,38)*x.*x.*x.*x.*z + M(1,39)*x.*x.*x.*y.*y + M(1,40)*x.*x.*x.*y.*z + M(1,41)*x.*x.*x.*z.*z + M(1,42)*x.*x.*y.*y.*y + M(1,43)*x.*x.*y.*y.*z + M(1,44)*x.*x.*y.*z.*z + M(1,45)*x.*x.*z.*z.*z + M(1,46)*x.*y.*y.*y.*y + M(1,47)*x.*y.*y.*y.*z + M(1,48)*x.*y.*y.*z.*z + M(1,49)*x.*y.*z.*z.*z + M(1,50)*x.*z.*z.*z.*z + M(1,51)*y.*y.*y.*y.*y + M(1,52)*y.*y.*y.*y.*z + M(1,53)*y.*y.*y.*z.*z + M(1,54)*y.*y.*z.*z.*z + M(1,55)*y.*z.*z.*z.*z + M(1,56)*z.*z.*z.*z.*z; + yy = M(2,1) + M(2,2)*x + M(2,3)*y + M(2,4)*z + M(2,5)*x.*x + M(2,6)*x.*y + M(2,7)*x.*z + M(2,8)*y.*y + M(2,9)*y.*z + M(2,10)*z.*z + M(2,11)*x.*x.*x + M(2,12)*x.*x.*y + M(2,13)*x.*x.*z + M(2,14)*x.*y.*y + M(2,15)*x.*y.*z + M(2,16)*x.*z.*z + M(2,17)*y.*y.*y + M(2,18)*y.*y.*z + M(2,19)*y.*z.*z + M(2,20)*z.*z.*z + M(2,21)*x.*x.*x.*x + M(2,22)*x.*x.*x.*y + M(2,23)*x.*x.*x.*z + M(2,24)*x.*x.*y.*y + M(2,25)*x.*x.*y.*z + M(2,26)*x.*x.*z.*z + M(2,27)*x.*y.*y.*y + M(2,28)*x.*y.*y.*z + M(2,29)*x.*y.*z.*z + M(2,30)*x.*z.*z.*z + M(2,31)*y.*y.*y.*y + M(2,32)*y.*y.*y.*z + M(2,33)*y.*y.*z.*z + M(2,34)*y.*z.*z.*z + M(2,35)*z.*z.*z.*z + M(2,36)*x.*x.*x.*x.*x + M(2,37)*x.*x.*x.*x.*y + M(2,38)*x.*x.*x.*x.*z + M(2,39)*x.*x.*x.*y.*y + M(2,40)*x.*x.*x.*y.*z + M(2,41)*x.*x.*x.*z.*z + M(2,42)*x.*x.*y.*y.*y + M(2,43)*x.*x.*y.*y.*z + M(2,44)*x.*x.*y.*z.*z + M(2,45)*x.*x.*z.*z.*z + M(2,46)*x.*y.*y.*y.*y + M(2,47)*x.*y.*y.*y.*z + M(2,48)*x.*y.*y.*z.*z + M(2,49)*x.*y.*z.*z.*z + M(2,50)*x.*z.*z.*z.*z + M(2,51)*y.*y.*y.*y.*y + M(2,52)*y.*y.*y.*y.*z + M(2,53)*y.*y.*y.*z.*z + M(2,54)*y.*y.*z.*z.*z + M(2,55)*y.*z.*z.*z.*z + M(2,56)*z.*z.*z.*z.*z; + zz = M(3,1) + M(3,2)*x + M(3,3)*y + M(3,4)*z + M(3,5)*x.*x + M(3,6)*x.*y + M(3,7)*x.*z + M(3,8)*y.*y + M(3,9)*y.*z + M(3,10)*z.*z + M(3,11)*x.*x.*x + M(3,12)*x.*x.*y + M(3,13)*x.*x.*z + M(3,14)*x.*y.*y + M(3,15)*x.*y.*z + M(3,16)*x.*z.*z + M(3,17)*y.*y.*y + M(3,18)*y.*y.*z + M(3,19)*y.*z.*z + M(3,20)*z.*z.*z + M(3,21)*x.*x.*x.*x + M(3,22)*x.*x.*x.*y + M(3,23)*x.*x.*x.*z + M(3,24)*x.*x.*y.*y + M(3,25)*x.*x.*y.*z + M(3,26)*x.*x.*z.*z + M(3,27)*x.*y.*y.*y + M(3,28)*x.*y.*y.*z + M(3,29)*x.*y.*z.*z + M(3,30)*x.*z.*z.*z + M(3,31)*y.*y.*y.*y + M(3,32)*y.*y.*y.*z + M(3,33)*y.*y.*z.*z + M(3,34)*y.*z.*z.*z + M(3,35)*z.*z.*z.*z + M(3,36)*x.*x.*x.*x.*x + M(3,37)*x.*x.*x.*x.*y + M(3,38)*x.*x.*x.*x.*z + M(3,39)*x.*x.*x.*y.*y + M(3,40)*x.*x.*x.*y.*z + M(3,41)*x.*x.*x.*z.*z + M(3,42)*x.*x.*y.*y.*y + M(3,43)*x.*x.*y.*y.*z + M(3,44)*x.*x.*y.*z.*z + M(3,45)*x.*x.*z.*z.*z + M(3,46)*x.*y.*y.*y.*y + M(3,47)*x.*y.*y.*y.*z + M(3,48)*x.*y.*y.*z.*z + M(3,49)*x.*y.*z.*z.*z + M(3,50)*x.*z.*z.*z.*z + M(3,51)*y.*y.*y.*y.*y + M(3,52)*y.*y.*y.*y.*z + M(3,53)*y.*y.*y.*z.*z + M(3,54)*y.*y.*z.*z.*z + M(3,55)*y.*z.*z.*z.*z + M(3,56)*z.*z.*z.*z.*z; + else + error('invalid size of nonlinear transformation matrix'); + end + + warped = [xx yy zz]; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % linear warping using homogenous coordinate transformation matrix + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +elseif strcmp(method, 'homogenous') || strcmp(method, 'homogeneous') + if all(size(M)==3) + % convert the 3x3 homogenous transformation matrix (corresponding with 2D) + % into a 4x4 homogenous transformation matrix (corresponding with 3D) + M = [ + M(1,1) M(1,2) 0 M(1,3) + M(2,1) M(2,2) 0 M(2,3) + 0 0 0 0 + M(3,1) M(3,2) 0 M(3,3) + ]; + end + + warped = M * [input'; ones(1, size(input, 1))]; + warped = warped(1:3,:)'; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % using external function that returns a homogenous transformation matrix + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +elseif exist(method, 'file') + % get the homogenous transformation matrix + H = feval(method, M); + warped = warp_apply(H, input, 'homogenous'); + +else + error('unrecognized transformation method'); +end + +if ~input3d + % convert from 3D back to 2D representation + warped = warped(:,1:2); +end + diff --git a/external/fieldtrip/ft_analysisprotocol.m b/external/fieldtrip/ft_analysisprotocol.m new file mode 100644 index 0000000..23d54da --- /dev/null +++ b/external/fieldtrip/ft_analysisprotocol.m @@ -0,0 +1,355 @@ +function [script, details] = ft_analysisprotocol(cfg, datacfg) + +% FT_ANALYSISPROTOCOL tries to reconstruct the complete analysis protocol that +% was used to create an arbitrary FieldTrip data structure. It will create +% a Matlab script (as text file) and a flowchart with a graphical +% representation. +% +% Use as +% ft_analysisprotocol(cfg, data) +% +% where the first cfg input contains the settings that apply to the +% behaviour of this particular function and the second data input argument +% can be the output of any FieldTrip function, e.g. FT_PREPROCESSING, +% FT_TIMELOCKANALYSIS, FT_SOURCEANALYSIS, FT_FREQSTATISTICS or whatever you like. +% +% Alternatively, for the second input argument you can also only give the +% configuration of the processed data (i.e. "data.cfg") instead of the full +% data. +% +% The configuration options that apply to the behaviour of this function are +% cfg.feedback = 'no', 'text', 'gui' or 'yes', whether text and/or +% graphical feedback should be presented (default = 'yes') +% cfg.filename = string, filename of m-file to which the script will be +% written (default = []) +% cfg.remove = cell-array with strings, determines which objects will +% be removed from the configuration prior to writing it to +% file. For readibility of the script, you may want to +% remove the large objectssuch as event structure, trial +% definition, source positions +% cfg.keepremoved = 'yes' or 'no', determines whether removed fields are +% completely removed, or only replaced by a short textual +% description (default = 'no') +% +% This function uses the nested cfg and cfg.previous that are present in +% the data structure. It will use the configuration and the nested previous +% configurations to climb all the way back into the tree. This funtction +% will print a complete Matlab script to screen (and optionally to file). +% Furthermore, it will show an interactive graphical flowchart +% representation of the steps taken during the analysis. In the flowchart +% you can click on one of the steps to see the configuration details of +% that step. +% +% Note that the nested cfg and cfg.previous in your data might not contain +% all details that are required to reconstruct a complete and valid +% analysis script. + +% TODO the output of this function can perhaps be used as input for the wizard function + +% Copyright (C) 2006-2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_analysisprotocol.m 948 2010-04-21 18:02:21Z roboos $ + +persistent depth % this corresponds to the vertical direction in the figure +persistent branch % this corresponds to the horizontal direction in the figure +persistent parent +persistent info + +fieldtripdefs + +% set the defaults +if ~isfield(cfg, 'filename'), cfg.filename = []; end +if ~isfield(cfg, 'keepremoved'), cfg.keepremoved = 'no'; end +if ~isfield(cfg, 'feedback'), cfg.feedback = 'yes'; end + +if ~isfield(cfg, 'remove') + % this is the default list of configuration elements to be removed. These + % elements would be very large to print and make the script difficult to + % read. To get a correctly behaving script, you may have to change this. + cfg.remove = { + 'sgncmb' + 'channelcmb' + 'event' + 'trl' + 'trlold' + 'artfctdef.eog.trl' + 'artfctdef.jump.trl' + 'artfctdef.muscle.trl' + 'pos' + 'inside' + 'outside' + 'grid.pos' + 'grid.inside' + 'grid.outside' + 'version.name' + 'version.id' + 'vol.bnd.pnt' + 'vol.bnd.tri' + }; +end + +feedbackgui = strcmp(cfg.feedback, 'gui') || strcmp(cfg.feedback, 'yes'); +feedbacktext = strcmp(cfg.feedback, 'text') || strcmp(cfg.feedback, 'yes'); + +% we are only interested in the cfg-part of the data +if isfield(datacfg, 'cfg') + datacfg = datacfg.cfg; +end + +% set up the persistent variables +if isempty(depth), depth = 1; end +if isempty(branch), branch = 1; end + +% start with an empty script +script = ''; + +% get the function call details before they are removed +try + thisname = getsubfield(datacfg, 'version.name'); + if isstruct(thisname) + % I think that this was needed for Matlab 6.5 + thisname = thisname.name; + end + [p, f] = fileparts(thisname); + thisname = f; +catch + thisname = 'unknown'; +end + +try + thisid = getsubfield(datacfg, 'version.id'); +catch + thisid = 'unknown'; +end + +if feedbacktext + % give some feedback on screen + fprintf('\n'); + fprintf('recursion depth = %d, branch = %d\n', depth, branch); + disp(thisname) + disp(thisid) +end + +% remove the fields that are too large or not interesting +for i=1:length(cfg.remove) + if issubfield(datacfg, cfg.remove{i}) + if feedbacktext + fprintf('removing %s\n', cfg.remove{i}); + end + siz = size(getsubfield(datacfg, cfg.remove{i})); + if strcmp(cfg.keepremoved, 'yes') + % keep the field, but replace the value with a descriptive string + datacfg = setsubfield(datacfg, cfg.remove{i}, sprintf('empty - this was cleared by analysisprotocol, original size = [%s]', num2str(siz))); + else + datacfg = rmsubfield(datacfg, cfg.remove{i}); + end + end +end + +% convert this part of the configuration to a matlab script +if isfield(datacfg, 'previous') + thiscfg = rmfield(datacfg, 'previous'); +else + thiscfg = datacfg; +end + +code = printstruct('cfg', thiscfg); +nl = sprintf('\n'); +emptycfg = sprintf('cfg = [];\n'); +sep = sprintf('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n'); +head1 = sprintf('%% version name = %s\n', thisname); +head2 = sprintf('%% version id = %s\n', thisid); +thisscript = [nl sep head1 head2 sep emptycfg code nl]; + +% remember this part of the configuration info +info(branch,depth).name = thisname; +info(branch,depth).id = thisid; +info(branch,depth).cfg = thiscfg; +info(branch,depth).script = thisscript; +info(branch,depth).this = [branch depth]; +info(branch,depth).parent = parent; +info(branch,depth).children = {}; % this will be determined later + +if isfield(datacfg, 'previous') + prev = parent; + parent = [branch depth]; % this will be used in the recursive call + if isstruct(datacfg.previous) + % increment the depth counter + depth = depth + 1; + % use recursion to parse the previous section of the tree + ft_analysisprotocol(cfg, datacfg.previous); + elseif iscell(datacfg.previous) + for i=1:length(datacfg.previous(:)) + % increment the branch counter + branch = branch + (i>1); + % increment the depth counter + depth = depth + 1; + % use recursion to parse each previous section of the tree + ft_analysisprotocol(cfg, datacfg.previous{i}); + end + end + % revert to the orignal parent + parent = prev; +end + +if depth==1 + % the recursion has finished, we are again at the top level + + % the parents were determined while climbing up the tree + % now it is time to descend and determine the children + for branch=1:size(info,1) + for depth=1:size(info,2) + if ~isempty(info(branch, depth).parent) + parentbranch = info(branch, depth).parent(1); + parentdepth = info(branch, depth).parent(2); + info(parentbranch, parentdepth).children{end+1} = [branch depth]; + end + end + end + + % complement the individual scripts with the input and output variables + % and the actual function call + for branch=1:size(info,1) + for depth=1:size(info,2) + outputvar = sprintf('var_%d_%d', info(branch, depth).this); + inputvar = ''; + commandline = sprintf('%s = %s(cfg%s);', outputvar, info(branch, depth).name, inputvar); + disp(commandline); + + end + end + + if nargout>0 + % return the complete script as output argument + script = ''; + for branch=1:size(info,1) + for depth=1:size(info,2) + script = [info(branch,depth).script script]; + end + end + end + + if nargout>1 + % return the information details as output argument + details = info; + end + + if feedbackgui + fig = figure; + hold on + % the axis should not change during the contruction of the arrows, + % otherwise the arrowheads will be distorted + axis manual; + for branch=1:size(info,1) + for depth=1:size(info,2) + plotinfo(info(branch,depth)); + end + end + axis auto + axis off + guidata(fig,info); + set(fig, 'WindowButtonUpFcn', @button); + set(fig, 'KeyPressFcn', @key); + end % feedbackgui + + if ~isempty(cfg.filename) + % write the complete script to file + fprintf('writing result to file ''%s''\n', cfg.filename); + fid = fopen(cfg.filename, 'wb'); + fprintf(fid, '%s', script); + fclose(fid); + end + + % clear all persistent variables + depth = []; + branch = []; + info = []; + parent = []; + fig = []; +else + % this level of recursion has finished, decrease the depth + depth = depth - 1; +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function plotinfo(element) +if isempty(element.name) + return +end +w = 0.6; +h = 0.3; +% create the 4 courners that can be used as patch +x = [-w/2 w/2 w/2 -w/2]; +y = [-h/2 -h/2 h/2 h/2]; +% close the patch +x = [x x(end)]; +y = [y y(end)]; +% move the patch to the desired location +x = element.this(1) + x; +y = element.this(2) + y; + +p = patch(x', y', 0); +set(p, 'Facecolor', [1 1 0.6]) + +label{1} = element.name; +% label{2} = num2str(element.this); + +l = text(element.this(1), element.this(2), label); +set(l, 'HorizontalAlignment', 'center') +set(l, 'interpreter', 'none') +set(l, 'fontUnits', 'normalized') +set(l, 'fontSize', 0.03) +% set(l, 'fontName', 'courier') + +% draw an arrow to connect this box to its parent +if ~isempty(element.parent) + base = element.this - [0 h/2]; + tip = element.parent + [0 h/2]; + % ARROW(Start,Stop,Length,BaseAngle,TipAngle,Width,Page,CrossDir) + arrow(base, tip, [], [], [], [], [], []); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function varargout = key(h, eventdata, handles, varargin) +% this is just a placeholder for future functionality +% at the moment it does not do anything + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function varargout = button(h, eventdata, handles, varargin) +pos = get(get(gcbo, 'CurrentAxes'), 'CurrentPoint'); +x = pos(1,1); +y = pos(1,2); +info = guidata(h); +dist = zeros(size(info)) + inf; +for i=1:numel(info) + if ~isempty(info(i).this) + dist(i) = norm(info(i).this - [x y]); + end +end +% determine the box that is nearest by the mouse click +[m, indx] = min(dist(:)); +% show the information contained in that box +uidisplaytext(info(indx).script, info(indx).name); + diff --git a/external/fieldtrip/ft_appenddata.m b/external/fieldtrip/ft_appenddata.m index b84b9b2..f340fbb 100644 --- a/external/fieldtrip/ft_appenddata.m +++ b/external/fieldtrip/ft_appenddata.m @@ -1,11 +1,287 @@ -function varargout = funname(varargin); +function [data] = ft_appenddata(cfg, varargin); -% this is a SPM wrapper around a FieldTrip function +% FT_APPENDDATA combines multiple datasets that have been preprocessed separately +% into a single large dataset. +% +% Use as +% data = ft_appenddata(cfg, data1, data2, data3, ...) +% where the configuration can be empty. +% +% If the input datasets all have the same channels, the trials will be +% concatenated. This is useful for example if you have different +% experimental conditions, which, besides analyzing them separately, for +% some reason you also want to analyze together. The function will check +% for consistency in the order of the channels. If the order is inconsistent +% the channel order of the output will be according to the channel order of +% the first data structure in the input. +% +% If the input datasets have different channels, but the same number of +% trials, the channels will be concatenated within each trial. This is +% useful for example if the data that you want to analyze contains both +% MEG and EMG channels which require different preprocessing options. +% +% Occasionally, the data needs to be concatenated in the trial dimension while +% there's a slight discrepancy in the channels in the input data (e.g. missing +% channels in one of the data structures). The function will then return a data +% structure containing only the channels which are present in all inputs. +% See also FT_PREPROCESSING +% +% Undocumented local options: +% cfg.inputfile = one can specifiy preanalysed saved data as input +% The data should be provided in a cell array +% cfg.outputfile = one can specify output as file to save to disk -% this part is variable -prefix = 'ft_'; +% Copyright (C) 2005-2008, Robert Oostenveld +% Copyright (C) 2009, Jan-Mathijs Schoffelen +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_appenddata.m 1311 2010-06-30 12:17:57Z timeng $ -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +fieldtripdefs + +% set the defaults +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +hasdata = nargin>1; +if ~isempty(cfg.inputfile) % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + for i=1:numel(cfg.inputfile) + varargin{i} = loadvar(cfg.inputfile{i}, 'data'); % read datasets from array inputfile + Ndata = numel(cfg.inputfile); % use Ndata as if separate datafiles were specified + end + end +else Ndata = nargin-1; % use old implementation of Ndata if no inputfile is specified + if Ndata<2 + error('you must give at least two datasets to append'); + end +end + +% check if the input data is valid for this function +for i=1:length(varargin) + varargin{i} = checkdata(varargin{i}, 'datatype', 'raw', 'feedback', 'no', 'hastrialdef', 'yes'); +end + +% determine the dimensions of the data +Nchan = zeros(1,Ndata); +Ntrial = zeros(1,Ndata); +label = {}; +for i=1:Ndata + Nchan(i) = length(varargin{i}.label); + Ntrial(i) = length(varargin{i}.trial); + fprintf('input dataset %d, %d channels, %d trials\n', i, Nchan(i), Ntrial(i)); + label = cat(1, label(:), varargin{i}.label(:)); +end + +% try to locate the trial definition (trl) in the nested configuration and +% check whether the input data contains trialinfo +hastrialinfo = 0; +for i=1:Ndata + if isfield(varargin{i}, 'cfg') + trl{i} = findcfg(varargin{i}.cfg, 'trl'); + else + trl{i} = []; + end + if isempty(trl{i}) + % a trial definition is expected in each continuous data set + warning(sprintf('could not locate the trial definition ''trl'' in data structure %d', i)); + end + hastrialinfo = isfield(varargin{i}, 'trialinfo') + hastrialinfo; +end +hastrialinfo = hastrialinfo==Ndata; + +% check the consistency of the labels across the input-structures +[alllabel, indx1, indx2] = unique(label, 'first'); +order = zeros(length(alllabel),Ndata); +%for i=1:length(alllabel) +% for j=1:Ndata +% tmp = strmatch(alllabel{i}, varargin{j}.label, 'exact'); +% if ~isempty(tmp) +% order(i,j) = tmp; +% end +% end +%end + +% replace the nested for-loops with something faster +for j=1:Ndata + tmplabel = varargin{j}.label; + [ix,iy] = match_str(alllabel, tmplabel); + order(ix,j) = iy; +end + +% check consistency of sensor positions across inputs +haselec = isfield(varargin{1}, 'elec'); +hasgrad = isfield(varargin{1}, 'grad'); +removesens = 0; +if haselec || hasgrad, + for j=1:Ndata + if haselec, sens{j} = getfield(varargin{j}, 'elec'); end + if hasgrad, sens{j} = getfield(varargin{j}, 'grad'); end + if j>1, + if numel(sens{j}.pnt) ~= numel(sens{1}.pnt) || any(sens{j}.pnt(:) ~= sens{1}.pnt(:)), + removesens = 1; + warning('sensor information does not seem to be consistent across the input arguments'); + break; + end + end + end +end + +% check whether the data are obtained from the same datafile +origfile1 = findcfg(varargin{1}.cfg, 'datafile'); +removetrialdef = 0; +for j=2:Ndata + if ~strcmp(origfile1, findcfg(varargin{j}.cfg, 'datafile')), + removetrialdef = 1; + warning('input data comes from different datafiles'); + break; + end +end + +catlabel = all(sum(order~=0,2)==1); +cattrial = any(sum(order~=0,2)==Ndata); +shuflabel = cattrial && ~all(all(order-repmat(order(:,1),[1 Ndata])==0)); +prunelabel = cattrial && sum(sum(order~=0,2)==Ndata). +% +% $Id: ft_appendspike.m 948 2010-04-21 18:02:21Z roboos $ + +fieldtripdefs + +isspike = zeros(size(varargin)); +for i=1:length(varargin) + % this is a quick test, more rigourous checking is done later + isspike(i) = isfield(varargin{i}, 'timestamp') & isfield(varargin{i}, 'label'); +end + +if all(isspike) + spike = {}; + for i=1:length(varargin) + spike{i} = checkdata(varargin{i}, 'datatype', 'spike'); + end + + % check the validity of the channel labels + label = {}; + for i=1:length(spike) + label = cat(1, label, spike{i}.label(:)); + end + if length(unique(label))~=length(label) + error('not all channel labels are unique'); + end + + % concatenate the spikes + data = spike{1}; + for i=2:length(spike) + data.label = cat(2, data.label, spike{i}.label); + data.waveform = cat(2, data.waveform, spike{i}.waveform); + data.timestamp = cat(2, data.timestamp, spike{i}.timestamp); + data.unit = cat(2, data.unit, spike{i}.unit); + end + +else + % this checks the validity of the input data and simultaneously renames it for convenience + data = varargin{1}; % checkdata(varargin{1}, 'datatype', 'raw'); + spike = ft_appendspike([], varargin{2:end}); + + % check the validity of the channel labels + label = cat(1, data.label(:), spike.label(:)); + if length(unique(label))~=length(label) + error('not all channel labels are unique'); + end + + trl = findcfg(data.cfg, 'trl'); + if isempty(trl); + error('could not find the trial information in the continuous data'); + end + + try + FirstTimeStamp = data.hdr.FirstTimeStamp; + TimeStampPerSample = data.hdr.TimeStampPerSample; + catch + error('could not find the timestamp information in the continuous data'); + end + + for i=1:length(spike.label) + % append the data with an empty channel + data.label{end+1} = spike.label{i}; + for j=1:size(trl,1) + data.trial{j}(end+1,:) = 0; + end + + % determine the corresponding sample numbers for each timestamp + ts = spike.timestamp{i}; + % timestamps can be uint64, hence explicitely convert to double at the right moment + sample = round(double(ts-FirstTimeStamp)/TimeStampPerSample + 1); + + fprintf('adding spike channel %s\n', spike.label{i}); + for j=1:size(trl,1) + begsample = trl(j,1); + endsample = trl(j,2); + sel = find((sample>=begsample) & (sample<=endsample)); + fprintf('adding spike channel %s, trial %d contains %d spikes\n', spike.label{i}, j, length(sel)); + for k=1:length(sel) + indx = sample(sel(k))-begsample+1; + data.trial{j}(end,indx) = data.trial{j}(end,indx)+1; + end % for k + end % for j + end % for i + +end + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_appendspike.m 948 2010-04-21 18:02:21Z roboos $'; +% remember the configuration details of the input data +cfg.previous = []; +for i=1:length(varargin) + try, cfg.previous{i} = varargin{i}.cfg; end +end +% remember the exact configuration details in the output +data.cfg = cfg; -% this part is variable -prefix = 'ft_'; -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_artifact_clip.m b/external/fieldtrip/ft_artifact_clip.m new file mode 100644 index 0000000..bfd9b76 --- /dev/null +++ b/external/fieldtrip/ft_artifact_clip.m @@ -0,0 +1,180 @@ +function [cfg, artifact] = ft_artifact_clip(cfg,data) + +% FT_ARTIFACT_CLIP scans the data segments of interest for channels that +% clip. A clipping artifact is detected by the signal being completely +% flat for some time. +% +% Use as +% [cfg, artifact] = ft_artifact_clip(cfg) +% required configuration options: +% cfg.dataset or both cfg.headerfile and cfg.datafile +% or +% [cfg, artifact] = ft_artifact_clip(cfg, data) +% forbidden configuration options: +% cfg.dataset, cfg.headerfile and cfg.datafile +% +% In both cases the configuration should also contain: +% cfg.artfctdef.clip.channel = Nx1 cell-array with selection of channels, see FT_CHANNELSELECTION for details +% cfg.artfctdef.clip.pretim = 0.000; pre-artifact rejection-interval in seconds +% cfg.artfctdef.clip.psttim = 0.000; post-artifact rejection-interval in seconds +% cfg.artfctdef.clip.thresh = 0.010; minimum duration in seconds of a datasegment with consecutive identical samples to be considered as 'clipped' +% cfg.continuous = 'yes' or 'no' whether the file contains continuous data +% +% See also FT_REJECTARTIFACT + +% Undocumented local options: +% cfg.inputfile = one can specifiy preanalysed saved data as input + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_artifact_clip.m 1212 2010-06-09 10:29:43Z timeng $ + +fieldtripdefs + +% check if the input cfg is valid for this function +cfg = checkconfig(cfg, 'trackconfig', 'on'); +cfg = checkconfig(cfg, 'renamed', {'datatype', 'continuous'}); +cfg = checkconfig(cfg, 'renamedval', {'continuous', 'continuous', 'yes'}); + +% set default rejection parameters for clip artifacts if necessary. +if ~isfield(cfg,'artfctdef'), cfg.artfctdef = []; end; +if ~isfield(cfg.artfctdef,'clip'), cfg.artfctdef.clip = []; end; +if ~isfield(cfg.artfctdef.clip,'channel'), cfg.artfctdef.clip.channel = 'all'; end; +if ~isfield(cfg.artfctdef.clip,'thresh'), cfg.artfctdef.clip.thresh = 0.010; end; +if ~isfield(cfg.artfctdef.clip,'pretim'), cfg.artfctdef.clip.pretim = 0.000; end; +if ~isfield(cfg.artfctdef.clip,'psttim'), cfg.artfctdef.clip.psttim = 0.000; end; +if ~isfield(cfg, 'headerformat'), cfg.headerformat = []; end; +if ~isfield(cfg, 'dataformat'), cfg.dataformat = []; end; +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end; + +% for backward compatibility +if isfield(cfg.artfctdef.clip,'sgn') + cfg.artfctdef.clip.channel = cfg.artfctdef.clip.sgn; + cfg.artfctdef.clip = rmfield(cfg.artfctdef.clip, 'sgn'); +end + +% start with an empty artifact list +artifact = []; + +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + hasdata = true; + end +end + +if hasdata + % read the header + % isfetch = 1; + cfg = checkconfig(cfg, 'forbidden', {'dataset', 'headerfile', 'datafile'}); + hdr = fetch_header(data); +else + % isfetch = 0; + cfg = checkconfig(cfg, 'dataset2files', {'yes'}); + cfg = checkconfig(cfg, 'required', {'headerfile', 'datafile'}); + hdr = ft_read_header(cfg.headerfile, 'headerformat', cfg.headerformat); +end + +% set default cfg.continuous +if ~isfield(cfg, 'continuous') + if hdr.nTrials==1 + cfg.continuous = 'yes'; + else + cfg.continuous = 'no'; + end +end + +% find the channel labels present in the data and their indices +label = ft_channelselection(cfg.artfctdef.clip.channel, hdr.label); +sgnindx = match_str(hdr.label, label); + +% make a local copy for convenience +artfctdef = cfg.artfctdef.clip; + +ntrl = size(cfg.trl,1); +nsgn = length(sgnindx); +for trlop=1:ntrl + fprintf('searching for clipping artifacts in trial %d\n', trlop); + % read the data of this trial + if hasdata + dat = fetch_data(data, 'header', hdr, 'begsample', cfg.trl(trlop,1), 'endsample', cfg.trl(trlop,2), 'chanindx', sgnindx); + else + dat = ft_read_data(cfg.datafile, 'header', hdr, 'begsample', cfg.trl(trlop,1), 'endsample', cfg.trl(trlop,2), 'chanindx', sgnindx, 'checkboundary', strcmp(cfg.continuous, 'no'), 'dataformat', cfg.dataformat); + end + % apply filtering etc to the data + datflt = preproc(dat, label, hdr.Fs, artfctdef, cfg.trl(trlop,3)); + % detect all samples that have the same value as the previous sample + identical = (datflt(:,1:(end-1)) == datflt(:,2:end)); + % ensure that the number of samples does not change + identical = [identical zeros(nsgn,1)]; + + % determine the number of consecutively identical samples + clip = zeros(size(dat)); + for sgnlop=1:length(sgnindx) + up = find(diff([0 identical(sgnlop,:)], 1, 2)== 1); + dw = find(diff([identical(sgnlop,:) 0], 1, 2)==-1); + for k=1:length(up) + clip(sgnlop,up(k):dw(k)) = dw(k)-up(k); + end + end + % collapse over cannels + clip = max(clip,[],1); + + % detect whether there are intervals in which the number of consecutive + % identical samples is larger than the threshold + thresh = (clip>=artfctdef.thresh*hdr.Fs); + + % remember the thresholded parts as artifacts + artup = find(diff([0 thresh])== 1) + cfg.trl(trlop,1) - 1; + artdw = find(diff([thresh 0])==-1) + cfg.trl(trlop,1) - 1; + for k=1:length(artup) + artifact(end+1,:) = [artup(k) artdw(k)]; + end +end + +if ~isempty(artifact) + % add the pretim and psttim to the detected artifacts + artifact(:,1) = artifact(:,1) - artfctdef.pretim * hdr.Fs; + artifact(:,2) = artifact(:,2) + artfctdef.psttim * hdr.Fs; +end + +% remember the details that were used here +cfg.artfctdef.clip = artfctdef; +cfg.artfctdef.clip.label = label; +cfg.artfctdef.clip.trl = cfg.trl; +cfg.artfctdef.clip.artifact = artifact; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_artifact_clip.m 1212 2010-06-09 10:29:43Z timeng $'; + diff --git a/external/fieldtrip/ft_artifact_ecg.m b/external/fieldtrip/ft_artifact_ecg.m new file mode 100644 index 0000000..bd833d7 --- /dev/null +++ b/external/fieldtrip/ft_artifact_ecg.m @@ -0,0 +1,312 @@ +function [cfg, artifact] = ft_artifact_ecg(cfg, data) + +% FT_ARTIFACT_ECG performs a peak-detection on the ECG-channel. The +% heart activity can be seen in the MEG data as an MCG artifact and +% can be removed using independent component analysis. +% +% Use as +% [cfg, artifact] = ft_artifact_ecg(cfg) +% required configuration options: +% cfg.dataset or both cfg.headerfile and cfg.datafile +% +% In both cases the configuration should also contain: +% cfg.artfctdef.ecg.channel = Nx1 cell-array with selection of channels, see FT_CHANNELSELECTION for details +% cfg.artfctdef.ecg.pretim = 0.05; pre-artifact rejection-interval in seconds +% cfg.artfctdef.ecg.psttim = 0.3; post-artifact rejection-interval in seconds +% cfg.artfctdef.ecg.method = 'zvalue'; peak-detection method +% cfg.artfctdef.ecg.cutoff = 3; peak-threshold +% cfg.artfctdef.ecg.inspect = Nx1 list of channels which will be shown in a QRS-locked average +% cfg.continuous = 'yes' or 'no' whether the file contains continuous data +% +% The output artifact variable is an Nx2-matrix, containing the +% begin and end samples of the QRST-complexes in the ECG. +% +% See also FT_REJECTARTIFACT + +% Undocumented local options: +% cfg.datatype + +% Copyright (c) 2005, Jan-Mathijs Schoffelen +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_artifact_ecg.m 1202 2010-06-08 10:11:30Z timeng $ + +fieldtripdefs + +% check if the input cfg is valid for this function +cfg = checkconfig(cfg, 'trackconfig', 'on'); +cfg = checkconfig(cfg, 'renamed', {'datatype', 'continuous'}); +cfg = checkconfig(cfg, 'renamedval', {'continuous', 'continuous', 'yes'}); + +% set default rejection parameters for eog artifacts if necessary. +if ~isfield(cfg,'artfctdef'), cfg.artfctdef = []; end +if ~isfield(cfg.artfctdef,'ecg'), cfg.artfctdef.ecg = []; end +if ~isfield(cfg.artfctdef.ecg,'channel'),cfg.artfctdef.ecg.channel = {'ECG'}; end +if ~isfield(cfg.artfctdef.ecg,'method'), cfg.artfctdef.ecg.method = 'zvalue'; end +if ~isfield(cfg.artfctdef.ecg,'cutoff'), cfg.artfctdef.ecg.cutoff = 3; end +if ~isfield(cfg.artfctdef.ecg,'padding'),cfg.artfctdef.ecg.padding = 0.5; end +if ~isfield(cfg.artfctdef.ecg,'inspect'),cfg.artfctdef.ecg.inspect = {'MLT' 'MRT'}; end +if ~isfield(cfg.artfctdef.ecg,'pretim'), cfg.artfctdef.ecg.pretim = 0.05; end +if ~isfield(cfg.artfctdef.ecg,'psttim'), cfg.artfctdef.ecg.psttim = 0.3; end +if ~isfield(cfg.artfctdef.ecg,'mindist'), cfg.artfctdef.ecg.mindist = 0.5; end +if ~isfield(cfg, 'headerformat'), cfg.headerformat = []; end +if ~isfield(cfg, 'dataformat'), cfg.dataformat = []; end + +% for backward compatibility +if isfield(cfg.artfctdef.ecg,'sgn') + cfg.artfctdef.ecg.channel = cfg.artfctdef.ecg.sgn; + cfg.artfctdef.ecg = rmfield(cfg.artfctdef.ecg, 'sgn'); +end + +if ~strcmp(cfg.artfctdef.ecg.method, 'zvalue'), + error('this method is not applicable'); +end + +if nargin == 1, + cfg = checkconfig(cfg, 'dataset2files', {'yes'}); + cfg = checkconfig(cfg, 'required', {'headerfile', 'datafile'}); + hdr = ft_read_header(cfg.headerfile,'headerformat', cfg.headerformat); + trl = cfg.trl; +elseif nargin == 2, + cfg = checkconfig(cfg, 'forbidden', {'dataset', 'headerfile', 'datafile'}); + hdr = fetch_header(data); + trl = findcfg(data.cfg, 'trl'); +end +artfctdef = cfg.artfctdef.ecg; +padsmp = round(artfctdef.padding*hdr.Fs); +ntrl = size(trl,1); +artfctdef.trl = trl; +artfctdef.channel = ft_channelselection(artfctdef.channel, hdr.label); +artfctdef.blc = 'yes'; +sgnind = match_str(hdr.label, artfctdef.channel); +numecgsgn = length(sgnind); +fltpadding = 0; + +if numecgsgn<1 + error('no ECG channels selected'); +elseif numecgsgn>1 + error('only one ECG channel can be selected'); +end + +% set default cfg.continuous +if ~isfield(cfg, 'continuous') + if hdr.nTrials==1 + cfg.continuous = 'yes'; + else + cfg.continuous = 'no'; + end +end + +% read in the ecg-channel and do blc and squaring +if nargin==2, + tmpcfg = []; + tmpcfg.channel = artfctdef.channel; + ecgdata = ft_preprocessing(tmpcfg, data); + ecg = ecgdata.trial; +end + +for j = 1:ntrl + if nargin==1, + ecg{j} = ft_read_data(cfg.datafile, 'header', hdr, 'begsample', trl(j,1), 'endsample', trl(j,2), 'chanindx', sgnind, 'checkboundary', strcmp(cfg.continuous, 'no'), 'dataformat', cfg.dataformat); + end + ecg{j} = preproc(ecg{j}, artfctdef.channel, hdr.Fs, artfctdef, [], fltpadding, fltpadding); + ecg{j} = ecg{j}.^2; +end + +if nargin==2 && ~isempty(findcfg(data.cfg,'resamplefs')) && ~isempty(findcfg(data.cfg,'resampletrl')), + %the data have been resampled along the way, the trl is in the original sampling rate + %adjust this + warning('the data have been resampled along the way, the trl-definition is in the original sampling rate, attempt to adjust for this may introduce some timing inaccuracies'); + trlold = trl; + trl = findcfg(data.cfg,'resampletrl'); +% fsampleold = findcfg(data.cfg,'origfs'); +% fsamplenew = findcfg(data.cfg,'resamplefs'); +% dfs = fsamplenew./fsampleold; +% trl(:,1) = round((trlold(:,1)-1).*dfs)+1; +% trl(:,2) = round((trlold(:,2)-1).*dfs)+1; +% %I don't know how to deal with some rounding errors brought about by strange values of sampling rates etc +% %allow slips of 1 sample +% trllen = cellfun('size',data.trial,2)'; +% trllen2 = trl(:,2)-trl(:,1)+1; +% toolong = trllen2-trllen==1; +% tooshort = trllen2-trllen==-1; +% trl(toolong,2) = trl(toolong,2)-1; +% trl(tooshort,2) = trl(tooshort,2)+1; +% data.cfg.trl = trl; +end + +tmp = cell2mat(ecg); +stmp = std(tmp, 0, 2); +mtmp = mean(tmp, 2); +Nsmp = max(trl(:,2)); +trace = zeros(1,Nsmp); + +% standardise the ecg +for j = 1:ntrl + trace(trl(j,1):trl(j,2)) = (ecg{j}-mtmp)./stmp; +end + +accept = 0; +while accept == 0, + h = figure; + plot(trace);zoom; + hold on; + plot([1 Nsmp], [artfctdef.cutoff artfctdef.cutoff], 'r:'); + hold off; + xlabel('samples'); + ylabel('zscore'); + + fprintf(['\ncurrent ',artfctdef.method,' threshold = %1.3f'], artfctdef.cutoff); + response = input('\nkeep the current value (y/n) ?\n','s'); + switch response + case 'n' + oldcutoff = artfctdef.cutoff; + artfctdef.cutoff = input('\nenter new value \n'); + case 'y' + oldcutoff = artfctdef.cutoff; + accept = 1; + otherwise + warning('unrecognised response, assuming no'); + oldcutoff = artfctdef.cutoff; + artfctdef.cutoff = input('\nenter new value \n'); + end; + close +end + +% detect peaks which are at least half a second apart and store +% the indices of the qrs-complexes in the artifact-configuration +mindist = round(cfg.artfctdef.ecg.mindist.*hdr.Fs); +[pindx, pval] = peakdetect2(trace, artfctdef.cutoff, mindist); +%sel = find(standardise(pval,2)<2); +%pindx = pindx(sel); +%pval = pval(sel); +artfctdef.qrs = pindx; + +%--------------------------------------- +% create trials for qrs-triggered average +trl = []; +trl(:,1) = pindx(:) - round(artfctdef.padding*(hdr.Fs)) ; +trl(:,2) = pindx(:) + round(artfctdef.padding*(hdr.Fs))-1; +trl(:,3) = -round(artfctdef.padding*(hdr.Fs)); +trl(trl(:,1)<1,:) = []; +trl(trl(:,2)>hdr.nSamples.*hdr.nTrials,:) = []; +%------------ + +% --------------------- +% qrs-triggered average +% FIXME, at present this only works for continuous data: the assumption can +% be made that all trials are equally long. +sgn = ft_channelselection(artfctdef.inspect, hdr.label); +megind = match_str(hdr.label, sgn); +sgnind = [megind(:); sgnind]; +dat = zeros(length(sgnind), trl(1,2)-trl(1,1)+1); +ntrl = size(trl,1); + +if ~isempty(sgnind) + ntrlok = 0; + for j = 1:ntrl + fprintf('reading and preprocessing trial %d of %d\n', j, ntrl); + if nargin==1, + dum = ft_read_data(cfg.datafile, 'header', hdr, 'begsample', trl(j,1), 'endsample', trl(j,2), 'chanindx', sgnind, 'checkboundary', strcmp(cfg.continuous, 'no'), 'dataformat', cfg.dataformat); + dat = dat + ft_preproc_baselinecorrect(dum); + ntrlok = ntrlok + 1; + elseif nargin==2, + dum = fetch_data(data, 'header', hdr, 'begsample', trl(j,1), 'endsample', trl(j,2), 'chanindx', sgnind, 'checkboundary', strcmp(cfg.continuous, 'no'), 'docheck', 0); + if any(~isfinite(dum(:))), + else + ntrlok = ntrlok + 1; + dat = dat + ft_preproc_baselinecorrect(dum); + end + end + end +end + +dat = dat./ntrlok; +time = offset2time(trl(1,3), hdr.Fs, size(dat,2)); +tmp = dat(1:end-1,:); +mdat = max(abs(tmp(:))); + +acceptpre = 0; +acceptpst = 0; +while acceptpre == 0 || acceptpst == 0, + h = figure; + subplot(2,1,1); plot(time, dat(end, :)); + abc = axis; + axis([time(1) time(end) abc(3:4)]); + subplot(2,1,2); + axis([time(1) time(end) -1.1*mdat 1.1*mdat]); + xpos = -artfctdef.pretim; + ypos = -1.05*mdat; + width = artfctdef.pretim + artfctdef.psttim; + height = 2.1*mdat; + rectangle('Position', [xpos ypos width height], 'FaceColor', 'r'); + hold on; plot(time, dat(1:end-1, :), 'b'); + + if acceptpre == 0, + fprintf(['\ncurrent pre-peak interval = %1.3f'], artfctdef.pretim); + response = input('\nkeep the current value (y/n) ?\n','s'); + switch response + case 'n' + oldpretim = artfctdef.pretim; + artfctdef.pretim = input('\nenter new value \n'); + case 'y' + oldpretim = artfctdef.pretim; + acceptpre = 1; + otherwise + warning('unrecognised response, assuming no'); + oldpretim = artfctdef.pretim; + end + end + if acceptpst == 0 && acceptpre == 1, + fprintf(['\ncurrent post-peak interval = %1.3f'], artfctdef.psttim); + response = input('\nkeep the current value (y/n) ?\n','s'); + switch response + case 'n' + oldpsttim = artfctdef.psttim; + artfctdef.psttim = input('\nenter new value \n'); + case 'y' + oldpsttim = artfctdef.psttim; + acceptpst = 1; + otherwise + warning('unrecognised response, assuming no'); + oldpsttim = artfctdef.psttim; + end + end + close +end + +artifact(:,1) = trl(:,1) - trl(:,3) - round(artfctdef.pretim*hdr.Fs); +artifact(:,2) = trl(:,1) - trl(:,3) + round(artfctdef.psttim*hdr.Fs); + +% remember the details that were used here +cfg.artfctdef.ecg = artfctdef; +cfg.artfctdef.ecg.artifact = artifact; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_artifact_ecg.m 1202 2010-06-08 10:11:30Z timeng $'; diff --git a/external/fieldtrip/ft_artifact_eog.m b/external/fieldtrip/ft_artifact_eog.m new file mode 100644 index 0000000..d22075f --- /dev/null +++ b/external/fieldtrip/ft_artifact_eog.m @@ -0,0 +1,162 @@ +function [cfg, artifact] = ft_artifact_eog(cfg,data) + +% FT_ARTIFACT_EOG reads the data segments of interest from file and +% identifies EOG artifacts. +% +% Use as +% [cfg, artifact] = ft_artifact_eog(cfg) +% required configuration options: +% cfg.dataset or both cfg.headerfile and cfg.datafile +% or +% [cfg, artifact] = ft_artifact_eog(cfg, data) +% forbidden configuration options: +% cfg.dataset, cfg.headerfile and cfg.datafile +% +% In both cases the configuration should also contain: +% cfg.trl = structure that defines the data segments of interest. See FT_DEFINETRIAL +% cfg.continuous = 'yes' or 'no' whether the file contains continuous data +% +% The data is preprocessed (again) with the following configuration parameters, +% which are optimal for identifying EOG artifacts: +% cfg.artfctdef.eog.bpfilter = 'yes' +% cfg.artfctdef.eog.bpfilttype = 'but' +% cfg.artfctdef.eog.bpfreq = [1 15] +% cfg.artfctdef.eog.bpfiltord = 4 +% cfg.artfctdef.eog.hilbert = 'yes' +% +% Artifacts are identified by means of thresholding the z-transformed value +% of the preprocessed data. +% cfg.artfctdef.eog.channel = Nx1 cell-array with selection of channels, see FT_CHANNELSELECTION for details +% cfg.artfctdef.eog.cutoff = 4 z-value at which to threshold +% cfg.artfctdef.eog.trlpadding = 0.5 +% cfg.artfctdef.eog.fltpadding = 0.1 +% cfg.artfctdef.eog.artpadding = 0.1 +% +% The output argument "artifact" is a Nx2 matrix comparable to the +% "trl" matrix of FT_DEFINETRIAL. The first column of which specifying the +% beginsamples of an artifact period, the second column contains the +% endsamples of the artifactperiods. +% +% See also FT_ARTIFACT_ZVALUE, FT_REJECTARTIFACT + +% Undocumented local options +% cfg.method +% cfg.inputfile + +% Copyright (c) 2003-2006, Jan-Mathijs Schoffelen & Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_artifact_eog.m 1212 2010-06-09 10:29:43Z timeng $ + +fieldtripdefs + +% check if the input cfg is valid for this function +cfg = checkconfig(cfg, 'trackconfig', 'on'); +cfg = checkconfig(cfg, 'renamed', {'datatype', 'continuous'}); +cfg = checkconfig(cfg, 'renamedval', {'continuous', 'continuous', 'yes'}); + +% set default rejection parameters +if ~isfield(cfg,'artfctdef'), cfg.artfctdef = []; end +if ~isfield(cfg.artfctdef,'eog'), cfg.artfctdef.eog = []; end +if ~isfield(cfg.artfctdef.eog,'method'), cfg.artfctdef.eog.method = 'zvalue'; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end + +% for backward compatibility +if isfield(cfg.artfctdef.eog,'sgn') + cfg.artfctdef.eog.channel = cfg.artfctdef.eog.sgn; + cfg.artfctdef.eog = rmfield(cfg.artfctdef.eog, 'sgn'); +end + +if isfield(cfg.artfctdef.eog, 'artifact') + fprintf('eog artifact detection has already been done, retaining artifacts\n'); + artifact = cfg.artfctdef.eog.artifact; + return +end + +if strcmp(cfg.artfctdef.eog.method, 'zvalue') + % the following fields should be supported for backward compatibility + if isfield(cfg.artfctdef.eog,'pssbnd'), + cfg.artfctdef.eog.bpfreq = cfg.artfctdef.eog.pssbnd; + cfg.artfctdef.eog.bpfilter = 'yes'; + cfg.artfctdef.eog = rmfield(cfg.artfctdef.eog,'pssbnd'); + end; + dum = 0; + if isfield(cfg.artfctdef.eog,'pretim'), + dum = max(dum, cfg.artfctdef.eog.pretim); + cfg.artfctdef.eog = rmfield(cfg.artfctdef.eog,'pretim'); + end + if isfield(cfg.artfctdef.eog,'psttim'), + dum = max(dum, cfg.artfctdef.eog.psttim); + cfg.artfctdef.eog = rmfield(cfg.artfctdef.eog,'psttim'); + end + if dum + cfg.artfctdef.eog.artpadding = max(dum); + end + if isfield(cfg.artfctdef.eog,'padding'), + cfg.artfctdef.eog.trlpadding = cfg.artfctdef.eog.padding; + cfg.artfctdef.eog = rmfield(cfg.artfctdef.eog,'padding'); + end + % settings for preprocessing + if ~isfield(cfg.artfctdef.eog,'bpfilter'), cfg.artfctdef.eog.bpfilter = 'yes'; end + if ~isfield(cfg.artfctdef.eog,'bpfilttype'), cfg.artfctdef.eog.bpfilttype = 'but'; end + if ~isfield(cfg.artfctdef.eog,'bpfreq'), cfg.artfctdef.eog.bpfreq = [1 15]; end + if ~isfield(cfg.artfctdef.eog,'bpfiltord'), cfg.artfctdef.eog.bpfiltord = 4; end + if ~isfield(cfg.artfctdef.eog,'hilbert'), cfg.artfctdef.eog.hilbert = 'yes'; end + % settings for the zvalue subfunction + if ~isfield(cfg.artfctdef.eog,'channel'), cfg.artfctdef.eog.channel = 'EOG'; end + if ~isfield(cfg.artfctdef.eog,'trlpadding'), cfg.artfctdef.eog.trlpadding = 0.5; end + if ~isfield(cfg.artfctdef.eog,'artpadding'), cfg.artfctdef.eog.artpadding = 0.1; end + if ~isfield(cfg.artfctdef.eog,'fltpadding'), cfg.artfctdef.eog.fltpadding = 0.1; end + if ~isfield(cfg.artfctdef.eog,'cutoff'), cfg.artfctdef.eog.cutoff = 4; end + % construct a temporary configuration that can be passed onto artifact_zvalue + tmpcfg = []; + tmpcfg.trl = cfg.trl; + tmpcfg.artfctdef.zvalue = cfg.artfctdef.eog; + if isfield(cfg, 'continuous'), tmpcfg.continuous = cfg.continuous; end + if isfield(cfg, 'dataformat'), tmpcfg.dataformat = cfg.dataformat; end + if isfield(cfg, 'headerformat'), tmpcfg.headerformat = cfg.headerformat; end + % call the zvalue artifact detection function + + hasdata = (nargin>1); + if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + hasdata = true; + end + end + + if hasdata + cfg = checkconfig(cfg, 'forbidden', {'dataset', 'headerfile', 'datafile'}); + [tmpcfg, artifact] = ft_artifact_zvalue(tmpcfg, data); + else + cfg = checkconfig(cfg, 'dataset2files', {'yes'}); + cfg = checkconfig(cfg, 'required', {'headerfile', 'datafile'}); + tmpcfg.datafile = cfg.datafile; + tmpcfg.headerfile = cfg.headerfile; + [tmpcfg, artifact] = ft_artifact_zvalue(tmpcfg); + end + cfg.artfctdef.eog = tmpcfg.artfctdef.zvalue; +else + error(sprintf('EOG artifact detection only works with cfg.method=''zvalue''')); +end + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); diff --git a/external/fieldtrip/ft_artifact_jump.m b/external/fieldtrip/ft_artifact_jump.m new file mode 100644 index 0000000..aa9d860 --- /dev/null +++ b/external/fieldtrip/ft_artifact_jump.m @@ -0,0 +1,159 @@ +function [cfg, artifact] = ft_artifact_jump(cfg,data) + +% FT_ARTIFACT_JUMP reads the data segments of interest from file and identifies +% SQUID jump artifacts. +% +% Use as +% [cfg, artifact] = ft_artifact_jump(cfg) +% required configuration options: +% cfg.dataset or both cfg.headerfile and cfg.datafile +% or +% [cfg, artifact] = ft_artifact_jump(cfg, data) +% forbidden configuration options: +% cfg.dataset, cfg.headerfile and cfg.datafile +% +% In both cases the configuration should also contain: +% cfg.trl = structure that defines the data segments of interest. See FT_DEFINETRIAL +% cfg.continuous = 'yes' or 'no' whether the file contains continuous data +% +% The data is preprocessed (again) with the following configuration parameters, +% which are optimal for identifying jump artifacts: +% cfg.artfctdef.jump.medianfilter = 'yes' +% cfg.artfctdef.jump.medianfiltord = 9 +% cfg.artfctdef.jump.absdiff = 'yes' +% +% Artifacts are identified by means of thresholding the z-transformed value +% of the preprocessed data. +% cfg.artfctdef.jump.channel = Nx1 cell-array with selection of channels, see FT_CHANNELSELECTION for details +% cfg.artfctdef.jump.cutoff = 20 z-value at which to threshold +% cfg.artfctdef.jump.trlpadding = automatically determined based on the filter padding (cfg.padding) +% cfg.artfctdef.jump.artpadding = automatically determined based on the filter padding (cfg.padding) +% +% The output argument "artifact" is a Nx2 matrix comparable to the +% "trl" matrix of DEFINETRIAL. The first column of which specifying the +% beginsamples of an artifact period, the second column contains the +% endsamples of the artifactperiods. +% +% See also FT_ARTIFACT_ZVALUE, FT_REJECTARTIFACT + +% Undocumented local options: +% cfg.method +% cfg.inputfile = one can specifiy preanalysed saved data as input + +% Copyright (c) 2003-2006, Jan-Mathijs Schoffelen & Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_artifact_jump.m 1212 2010-06-09 10:29:43Z timeng $ + +fieldtripdefs + +% check if the input cfg is valid for this function +cfg = checkconfig(cfg, 'trackconfig', 'on'); +cfg = checkconfig(cfg, 'renamed', {'datatype', 'continuous'}); +cfg = checkconfig(cfg, 'renamedval', {'continuous', 'continuous', 'yes'}); + +% set default rejection parameters +if ~isfield(cfg,'artfctdef'), cfg.artfctdef = []; end +if ~isfield(cfg.artfctdef,'jump'), cfg.artfctdef.jump = []; end +if ~isfield(cfg.artfctdef.jump,'method'), cfg.artfctdef.jump.method = 'zvalue'; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end + +% for backward compatibility +if isfield(cfg.artfctdef.jump,'sgn') + cfg.artfctdef.jump.channel = cfg.artfctdef.jump.sgn; + cfg.artfctdef.jump = rmfield(cfg.artfctdef.jump, 'sgn'); +end + +if isfield(cfg.artfctdef.jump, 'artifact') + fprintf('jump artifact detection has already been done, retaining artifacts\n'); + artifact = cfg.artfctdef.jump.artifact; + return +end + +if strcmp(cfg.artfctdef.jump.method, 'zvalue') + % the following fields should be supported for backward compatibility + dum = 0; + if isfield(cfg.artfctdef.jump,'pretim'), + dum = max(dum, cfg.artfctdef.jump.pretim); + cfg.artfctdef.jump = rmfield(cfg.artfctdef.jump,'pretim'); + end + if isfield(cfg.artfctdef.jump,'psttim'), + dum = max(dum, cfg.artfctdef.jump.psttim); + cfg.artfctdef.jump = rmfield(cfg.artfctdef.jump,'psttim'); + end + if dum + cfg.artfctdef.jump.artpadding = max(dum); + end + if isfield(cfg.artfctdef.jump,'padding'), + cfg.artfctdef.jump.trlpadding = cfg.artfctdef.jump.padding; + cfg.artfctdef.jump = rmfield(cfg.artfctdef.jump,'padding'); + end + % settings for preprocessing + if ~isfield(cfg.artfctdef.jump,'medianfilter'), cfg.artfctdef.jump.medianfilter = 'yes'; end + if ~isfield(cfg.artfctdef.jump,'medianfiltord'), cfg.artfctdef.jump.medianfiltord = 9; end + if ~isfield(cfg.artfctdef.jump,'absdiff'), cfg.artfctdef.jump.absdiff = 'yes'; end % compute abs(diff(data)), whereas the order of rectify=yes in combination with derivative=yes would be diff(abs(data)) due to the ordering in preproc + % settings for the zvalue subfunction + if ~isfield(cfg.artfctdef.jump,'cutoff'), cfg.artfctdef.jump.cutoff = 20; end + if ~isfield(cfg.artfctdef.jump,'channel'), cfg.artfctdef.jump.channel = 'MEG'; end + if ~isfield(cfg.artfctdef.jump,'cumulative'), cfg.artfctdef.jump.cumulative = 'no'; end + if isfield(cfg, 'padding') && cfg.padding~=0 + if ~isfield(cfg.artfctdef.jump,'trlpadding'), cfg.artfctdef.jump.trlpadding = 0.5*cfg.padding; end + if ~isfield(cfg.artfctdef.jump,'artpadding'), cfg.artfctdef.jump.artpadding = 0.5*cfg.padding; end + if ~isfield(cfg.artfctdef.jump,'fltpadding'), cfg.artfctdef.jump.fltpadding = 0; end + else + if ~isfield(cfg.artfctdef.jump,'trlpadding'), cfg.artfctdef.jump.trlpadding = 0; end + if ~isfield(cfg.artfctdef.jump,'artpadding'), cfg.artfctdef.jump.artpadding = 0; end + if ~isfield(cfg.artfctdef.jump,'fltpadding'), cfg.artfctdef.jump.fltpadding = 0; end + end + % construct a temporary configuration that can be passed onto artifact_zvalue + tmpcfg = []; + tmpcfg.trl = cfg.trl; + tmpcfg.artfctdef.zvalue = cfg.artfctdef.jump; + if isfield(cfg, 'continuous'), tmpcfg.continuous = cfg.continuous; end + if isfield(cfg, 'dataformat'), tmpcfg.dataformat = cfg.dataformat; end + if isfield(cfg, 'headerformat'), tmpcfg.headerformat = cfg.headerformat; end + % call the zvalue artifact detection function + + hasdata = (nargin>1); + if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + hasdata = true; + end + end + + if hasdata + cfg = checkconfig(cfg, 'forbidden', {'dataset', 'headerfile', 'datafile'}); + [tmpcfg, artifact] = ft_artifact_zvalue(tmpcfg, data); + else + cfg = checkconfig(cfg, 'dataset2files', {'yes'}); + cfg = checkconfig(cfg, 'required', {'headerfile', 'datafile'}); + tmpcfg.datafile = cfg.datafile; + tmpcfg.headerfile = cfg.headerfile; + [tmpcfg, artifact] = ft_artifact_zvalue(tmpcfg); + end + cfg.artfctdef.jump = tmpcfg.artfctdef.zvalue; +else + error(sprintf('jump artifact detection only works with cfg.method=''zvalue''')); +end + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); diff --git a/external/fieldtrip/ft_artifact_manual.m b/external/fieldtrip/ft_artifact_manual.m new file mode 100644 index 0000000..d7ad1ff --- /dev/null +++ b/external/fieldtrip/ft_artifact_manual.m @@ -0,0 +1,498 @@ +function [cfg, artifact] = ft_artifact_manual(cfg); + +% THIS FUNCTION IS DEPRECIATED, USE FT_REJECTVISUAL INSTEAD +% +% FT_ARTIFACT_MANUAL allows the user to detect artifacts manually using visual +% inspection. +% +% Use as: +% [cfg, artifact] = ft_artifact_manual(cfg) +% required configuration options: +% cfg.dataset or both cfg.headerfile and cfg.datafile +% +% The configuration should also contain: +% cfg.artfctdef.manual.channel = cell-array with channels to be displayed. +% (Be careful not to specify to much channels because the function then will be very slow.) +% cfg.continuous = 'yes' or 'no' whether the file contains continuous data +% +% You can specify: +% cfg.artfctdef.manual.pretrialtime = time shown before trialstart (default 0) +% cfg.artfctdef.manual.posttrialtime = time shown after trialend (default 0) +% cfg.artfctdef.manual.fft = 'no' (default) or 'yes' turns on FFT window +% cfg.artfctdef.manual.padding = 'no' (default) or FFT-padding in seconds +% +% The FFT will be executed on the complete time interval including pre and post +% trial times. +% +% cfg.artfctdef.manual.timeaxrelative = 'yes' (default) or 'no'. +% +% Set to yes defines the time axes relative to trialstart. Set to no defines it +% relative to the beginning of the experiment. +% +% cfg.artfctdef.manual.blc = 'no' (default) or 'yes' apply baseline correction +% cfg.artfctdef.manual.bpfilter = 'no' (default) or 'yes' apply bandpass filter +% cfg.artfctdef.manual.bpfreq = [0.3 30] in Hz +% cfg.artfctdef.manual.bpfiltord = 2 +% +% See also FT_REJECTARTIFACT, FT_REJECTVISUAL + +% Undocumented local options: +% cfg.artfctdef.manual.maxnumberofchannels = 20 (default) + +% Copyright (C) 2004, Geerten Kramer, FCDC +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_artifact_manual.m 1038 2010-05-05 15:48:52Z timeng $ + +fieldtripdefs + +% check if the input cfg is valid for this function +cfg = checkconfig(cfg, 'trackconfig', 'on'); +cfg = checkconfig(cfg, 'renamed', {'datatype', 'continuous'}); +cfg = checkconfig(cfg, 'renamedval', {'continuous', 'continuous', 'yes'}); + +% set default rejection parameters if necessary. +if ~isfield(cfg, 'artfctdef'), cfg.artfctdef = []; end +if ~isfield(cfg.artfctdef,'manual'), cfg.artfctdef.manual = []; end +if ~isfield(cfg.artfctdef.manual,'zscale'), cfg.artfctdef.manual.zscale = 100; end +if ~isfield(cfg.artfctdef.manual,'fft'), cfg.artfctdef.manual.fft ='no'; end +if ~isfield(cfg.artfctdef.manual,'padding'), cfg.artfctdef.manual.padding ='no'; end +if ~isfield(cfg.artfctdef.manual,'pretrialtime'), cfg.artfctdef.manual.pretrialtime = 0; end +if ~isfield(cfg.artfctdef.manual,'posttrialtime'), cfg.artfctdef.manual.posttrialtime = 0; end +if ~isfield(cfg.artfctdef.manual,'timeaxrelative'), cfg.artfctdef.manual.timeaxrelative = 'yes'; end +if ~isfield(cfg.artfctdef.manual,'maxnumberofchannels'),cfg.artfctdef.manual.maxnumberofchannels = 20; end +if ~isfield(cfg, 'headerformat'), cfg.headerformat = []; end +if ~isfield(cfg, 'dataformat'), cfg.dataformat = []; end + +% for backward compatibility +if isfield(cfg.artfctdef.manual,'sgn') + cfg.artfctdef.manual.channel = cfg.artfctdef.manual.sgn; + cfg.artfctdef.manual = rmfield(cfg.artfctdef.manual, 'sgn'); +end + +if ~isfield(cfg.artfctdef.manual,'channel'), + % set an unusual default because all crashes the program. + cfg.artfctdef.manual.channel = []; +end + +% read the header and do some preprocessing on the configuration +fprintf('Reading raw data...'); +cfg = checkconfig(cfg, 'dataset2files', {'yes'}); +cfg = checkconfig(cfg, 'required', {'headerfile', 'datafile'}); +hdr = ft_read_header(cfg.headerfile, 'headerformat', cfg.headerformat); +cfg.artfctdef.manual.channel=ft_channelselection(cfg.artfctdef.manual.channel, hdr.label); +cfg.artfctdef.manual.trl=cfg.trl; +if(isempty(cfg.artfctdef.manual.channel)) + error(sprintf('\nNo channels selected for artifact_manual!\nSelect at least one channel in cfg.artfctdef.manual.channel')); +end; +channelindx=match_str(hdr.label, cfg.artfctdef.manual.channel); +ntrial=size(cfg.trl, 1); +nch=length(channelindx); +if(nch<1) + error(sprintf('\nNo channels selected for artifact_manual!\nSelect at least one channel in cfg.artfctdef.manual.channel')); +elseif(nch>cfg.artfctdef.manual.maxnumberofchannels) + error(sprintf('\nMore than %i channels selected in cfg.artfctdef.manual.channel',cfg.artfctdef.manual.maxnumberofchannels)); +end + +% set default cfg.continuous +if ~isfield(cfg, 'continuous') + if hdr.nTrials==1 + cfg.continuous = 'yes'; + else + cfg.continuous = 'no'; + end +end + +show=ft_read_data(cfg.datafile, 'header', hdr, 'begsample', 1, 'endsample', hdr.nTrials*hdr.nSamples, 'chanindx', channelindx, 'checkboundary', strcmp(cfg.continuous, 'no'), 'dataformat', cfg.dataformat); +show=show'; + +N=length(show); +S=floor(N./hdr.Fs); % In seconds +x=1:N; +x=x./hdr.Fs; % In seconds. + +fprintf(' done.\n'); +fprintf('Processing raw data for artifact_manual...'); + +% these elements are stored inside the figure so that the callback routines can modify them +dat.RejMarkList=zeros(length(cfg.trl),1); +dat.ResRejMarkList=zeros(length(cfg.trl),1); +dat.RejCount=0; +dat.ResRejCount=0; +dat.stop=0; +dat.trln=1; +dat.numtrl=length(cfg.trl); +dat.FFT=strcmp(cfg.artfctdef.manual.fft,'yes')|strcmp(cfg.artfctdef.manual.fft,'Yes')... + |strcmp(cfg.artfctdef.manual.fft,'on')|strcmp(cfg.artfctdef.manual.fft,'On'); +if(strcmp(cfg.artfctdef.manual.padding,'no')|strcmp(cfg.artfctdef.manual.padding,'No')... + |strcmp(cfg.artfctdef.manual.padding,'Off')|strcmp(cfg.artfctdef.manual.padding,'off')) + cfg.artfctdef.manual.padding=[]; +end; +dat.IfRelOn=strcmp(cfg.artfctdef.manual.timeaxrelative,'yes')|strcmp(cfg.artfctdef.manual.timeaxrelative,'Yes')... + |strcmp(cfg.artfctdef.manual.timeaxrelative,'on')|strcmp(cfg.artfctdef.manual.timeaxrelative,'On'); + +ival=cell(dat.numtrl,1); +dataX=cell(dat.numtrl,1); +dataY=cell(dat.numtrl,1); +dataFx=cell(dat.numtrl,1); +dataFy=cell(dat.numtrl,1); +dataXLim=cell(dat.numtrl,1); +dataYLim=cell(dat.numtrl,1); + +% first we calculate everything and put it into varables. +for(i=1:dat.numtrl) + begpadding = round(cfg.artfctdef.manual.pretrialtime.*hdr.Fs); + endpadding = round(cfg.artfctdef.manual.posttrialtime.*hdr.Fs); + ival{i}=(cfg.trl(i,1)-begpadding):(cfg.trl(i,2)+endpadding); + dataY{i}=show(ival{i},:); + + % don't remove the padding + [dataY{i}, dumlab, dumtime, dumcfg] = preproc(dataY{i}', cfg.artfctdef.manual.channel, hdr.Fs, cfg.artfctdef.manual, cfg.trl(i,3)-begpadding, 0, 0); + dataY{i} = dataY{i}'; + + try, if(~rem(i,fix(dat.numtrl/10)))fprintf('.');end; end +end; +clear show; % Now, we don't need the complete dataset anymore... +for(i=1:dat.numtrl) % we go on with the calculations .... + dataX{i}=x(ival{i})-dat.IfRelOn.*(x(ival{i}(1))+cfg.artfctdef.manual.pretrialtime); + + dataYLim{i}=[]; + for(j=1:nch) + mini=min(dataY{i}(:,j)); + maxi=max(dataY{i}(:,j)); + + dataYLim{i}=[dataYLim{i};[mini-.03.*(maxi-mini),maxi+.03.*(maxi-mini)]]; + dataXLim{i}=[min(dataX{i}),max(dataX{i})]; + end; + + if(dat.FFT) % if FFT is on, calculate the FFT of the trials too... + tmp=[]; + for(k=1:nch) tmp=[tmp,dataY{i}(:,k)-mean(dataY{i}(:,k),1)];end; + dataFy{i}=abs(fft(tmp,cfg.artfctdef.manual.padding,1)); + tmp=floor((max(ival{i})-min(ival{i}))/2); + dataFx{i}=(1:tmp)./tmp.*hdr.Fs./2; + dataFy{i}=dataFy{i}(1:length(dataFx{i}),:); + end; + if(~rem(i,fix(dat.numtrl/10)))fprintf('.');end; +end; + +fprintf(' done.\n'); + +thisfig('fig_trace');% See the help of thisfig +set(fig_trace,'name','Traces'); +if(dat.FFT); + thisfig('fig_spec'); + set(fig_spec,'name','Spectra of traces'); +end; +gt=[5 40 5 25 0 50 5 60 5 60 5 60 5 60 5 60 5 25 0 25]; +uicontrol(fig_trace,'units','pixels','position',[sum(gt(1:1)),5,gt(2),18],'String','Done','Callback',@stop); +uicontrol(fig_trace,'units','pixels','position',[sum(gt(1:3)),5,gt(4),18],'String','<','Callback',@prevtrial); +uicontrol(fig_trace,'units','pixels','position',[sum(gt(1:5)),5,gt(6),18],'String','>','Callback',@nexttrial); +uicontrol(fig_trace,'units','pixels','position',[sum(gt(1:7)),5,gt(8),18],'String','Reject >','Callback',@reject_next); +uicontrol(fig_trace,'units','pixels','position',[sum(gt(1:9)),5,gt(10),18],'String','Reject','Callback',@reject); +uicontrol(fig_trace,'units','pixels','position',[sum(gt(1:11)),5,gt(12),18],'String','Accept','Callback',@undo); +uicontrol(fig_trace,'units','pixels','position',[sum(gt(1:13)),5,gt(14),18],'String','Accept All','Callback',@undoAll); +uicontrol(fig_trace,'units','pixels','position',[sum(gt(1:15)),5,gt(16),18],'String','Redo All','Callback',@redoAll); +uicontrol(fig_trace,'units','pixels','position',[sum(gt(1:17)),5,gt(18),18],'String','<<','Callback',@pptrial); +uicontrol(fig_trace,'units','pixels','position',[sum(gt(1:19)),5,gt(20),18],'String','>>','Callback',@nntrial); +set(fig_trace, 'KeyPressFcn',@keypress); +% set(get(fig_trace, 'children'),'KeyPressFcn',@keypress); +show_help; + +thisfig('fig_trace'); % See the help of thisfig. + +while(ishandle(fig_trace)) + + if(dat.FFT) % Plots FFT when requested + if(exist('HF')) % this is for remembering the zoom of the FFT-window + if(ishandle(HF)) % while zapping trough the data. + saveXLim=get(HF,'XLim'); + saveYLim=get(HF,'YLim'); + end; + end; + thisfig('fig_spec'); + plot(dataFx{dat.trln},dataFy{dat.trln}); + HF=get(fig_spec,'CurrentAxes'); + if(exist('saveXLim'))set(HF,'XLim',saveXLim);end; + if(exist('saveYLim'))set(HF,'YLim',saveYLim);end; + xlabel('Frequency [Hz]'); + ylabel('Power [A.U.]'); + thisfig('fig_trace'); + end; + + for(j=1:nch) % This loop fils the traces figure with the traces. + H=subplot(nch,1,j); + plot(dataX{dat.trln},dataY{dat.trln}(:,j),'b-'); + line([dataXLim{1}(1)+cfg.artfctdef.manual.pretrialtime dataXLim{1}(1)+cfg.artfctdef.manual.pretrialtime], dataYLim{dat.trln}(j,:), 'color', 'g'); + line([dataXLim{1}(2)-cfg.artfctdef.manual.posttrialtime dataXLim{1}(2)-cfg.artfctdef.manual.posttrialtime], dataYLim{dat.trln}(j,:), 'color', 'r'); + set(H,'YLim',dataYLim{dat.trln}(j,:) + [-eps +eps]); + set(H,'XLim',dataXLim{dat.trln}); + xlabel('Time [s]','position',... + [dataXLim{dat.trln}(2),dataYLim{dat.trln}(j,1)-(dataYLim{dat.trln}(j,2)-dataYLim{dat.trln}(j,1)).*.05]... + ,'HorizontalAlignment','left'); + ylabel(sprintf('%s', cfg.artfctdef.manual.channel{j})); + end; + + if(dat.RejMarkList(dat.trln)==0) + tiet=sprintf('trial %i: ACCEPT',dat.trln); + else + tiet=sprintf('trial %i: REJECT',dat.trln); + end; + H=subplot(nch,1,1); + title(tiet); + + guidata(fig_trace,dat); + uiwait; + if(ishandle(fig_trace)) dat=guidata(fig_trace);end; + + if(dat.stop)break;end; +end + +if(~ishandle(fig_trace)) + error('Figure closed unexpectedly, no manual artifacts marked.'); +else + close(fig_trace) +end; + +if(dat.FFT) + if(ishandle(fig_spec))close(fig_spec);end; +end; + +fprintf('Rejected %i trials.\n',dat.RejCount); +fprintf('Exported %i trials.\n',length(cfg.trl)-dat.RejCount); + +artifact=cfg.trl(find((dat.RejMarkList)),[1,2]); + +% remember the details that were used here +cfg.artfctdef.manual.artifact = artifact; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_artifact_manual.m 1038 2010-05-05 15:48:52Z timeng $'; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% here the SUBFUNCTIONS start that implement the gui callbacks +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function varargout=nexttrial(h, eventdata, handles, varargin) +dat=guidata(h); +if(dat.trln 1), + dat.trln=dat.trln - 1; +else + dat.trln=dat.numtrl; +end; +guidata(h,dat); +uiresume; + +function varargout=stop(h, eventdata, handles, varargin) +dat=guidata(h); +dat.stop=1; +guidata(h,dat); +uiresume; + +function varargout=reject(h, eventdata, handles, varargin) +dat=guidata(h); +if(dat.RejMarkList(dat.trln)==0) + dat.RejCount=dat.RejCount+1; + dat.RejMarkList(dat.trln)=1; + if(~dat.ResRejMarkList(dat.trln)) + dat.ResRejCount=dat.ResRejCount+1; + dat.ResRejMarkList(dat.trln)=1; + fprintf('Rejected trial %i!\n',dat.trln); + else + fprintf('Rejected trial %i again!\n',dat.trln); + end; +else + fprintf('Trial %i is already marked for rejection.\n',dat.trln); +end; +guidata(h,dat); +uiresume; + + +function varargout=reject_next(h, eventdata, handles, varargin) +dat=guidata(h); +if(dat.RejMarkList(dat.trln)==0) + dat.RejCount=dat.RejCount+1; + dat.RejMarkList(dat.trln)=1; + if(~dat.ResRejMarkList(dat.trln)) + dat.ResRejCount=dat.ResRejCount+1; + dat.ResRejMarkList(dat.trln)=1; + fprintf('Rejected trial %i!\n',dat.trln); + else + fprintf('Rejected trial %i again!\n',dat.trln); + end; +else + fprintf('Trial %i is already marked for rejection.\n',dat.trln); +end; +if(dat.trln < dat.numtrl) + dat.trln=dat.trln + 1; +else + dat.trln=1; +end; +guidata(h,dat); +uiresume; + +function varargout=undo(h, eventdata, handles, varargin) +dat=guidata(h); +if(dat.RejMarkList(dat.trln)>0) + dat.RejCount=dat.RejCount-1; + dat.RejMarkList(dat.trln)=0; + fprintf('Rejected trial %i recovered.\n',dat.trln); +end; +guidata(h,dat); +uiresume; + +function varargout=undoAll(h, eventdata, handles, varargin) +dat=guidata(h); +dat.RejCount=0; +dat.RejMarkList=zeros(dat.numtrl,1); +fprintf('All rejected trials recovered.\n'); +guidata(h,dat); +uiresume; + +function varargout=redoAll(h, eventdata, handles, varargin) +dat=guidata(h); +dat.RejMarkList=dat.ResRejMarkList; +dat.RejCount=dat.ResRejCount; +fprintf('All recovered trials rejected again.\n'); +guidata(h,dat); +uiresume; + +function varargout=nntrial(h, eventdata, handles, varargin) +dat=guidata(h); +if(dat.trln<(dat.numtrl-10)) + dat.trln=dat.trln + 10; +else + dat.trln=1; +end; +guidata(h,dat); +uiresume; + + +function varargout=pptrial(h, eventdata, handles, varargin) +dat=guidata(h); +if(dat.trln > 10), + dat.trln=dat.trln - 10; +else + dat.trln=dat.numtrl; +end; +guidata(h,dat); +uiresume; + +function keypress(h, eventdata, handles, varargin) +dat=guidata(gcbf); +key=get(gcbf, 'CurrentCharacter'); +if key + switch key + case 28 % arrow left + if(dat.trln > 1), + dat.trln=dat.trln - 1; + else + dat.trln=dat.numtrl; + end; + case 29 % arrow right + if(dat.trln. +% +% $Id: ft_artifact_muscle.m 1212 2010-06-09 10:29:43Z timeng $ + +fieldtripdefs + +% check if the input cfg is valid for this function +cfg = checkconfig(cfg, 'trackconfig', 'on'); +cfg = checkconfig(cfg, 'renamed', {'datatype', 'continuous'}); +cfg = checkconfig(cfg, 'renamedval', {'continuous', 'continuous', 'yes'}); + +% set default rejection parameters +if ~isfield(cfg,'artfctdef'), cfg.artfctdef = []; end +if ~isfield(cfg.artfctdef,'muscle'), cfg.artfctdef.muscle = []; end +if ~isfield(cfg.artfctdef.muscle,'method'), cfg.artfctdef.muscle.method = 'zvalue'; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end + +% for backward compatibility +if isfield(cfg.artfctdef.muscle,'sgn') + cfg.artfctdef.muscle.channel = cfg.artfctdef.muscle.sgn; + cfg.artfctdef.muscle = rmfield(cfg.artfctdef.muscle, 'sgn'); +end + +if isfield(cfg.artfctdef.muscle, 'artifact') + fprintf('muscle artifact detection has already been done, retaining artifacts\n'); + artifact = cfg.artfctdef.muscle.artifact; + return +end + +if strcmp(cfg.artfctdef.muscle.method, 'zvalue') + % the following settings should be supported for backward compatibility + if isfield(cfg.artfctdef.muscle,'pssbnd'), + cfg.artfctdef.muscle.bpfreq = cfg.artfctdef.muscle.pssbnd; + cfg.artfctdef.muscle.bpfilter = 'yes'; + cfg.artfctdef.muscle = rmfield(cfg.artfctdef.muscle,'pssbnd'); + end; + dum = 0; + if isfield(cfg.artfctdef.muscle,'pretim'), + dum = max(dum, cfg.artfctdef.muscle.pretim); + cfg.artfctdef.muscle = rmfield(cfg.artfctdef.muscle,'pretim'); + end + if isfield(cfg.artfctdef.muscle,'psttim'), + dum = max(dum, cfg.artfctdef.muscle.psttim); + cfg.artfctdef.muscle = rmfield(cfg.artfctdef.muscle,'psttim'); + end + if dum + cfg.artfctdef.muscle.artpadding = max(dum); + end + if isfield(cfg.artfctdef.muscle,'padding'), + cfg.artfctdef.muscle.trlpadding = cfg.artfctdef.muscle.padding; + cfg.artfctdef.muscle = rmfield(cfg.artfctdef.muscle,'padding'); + end + + % settings for preprocessing + if ~isfield(cfg.artfctdef.muscle,'bpfilter'), cfg.artfctdef.muscle.bpfilter = 'yes'; end + if ~isfield(cfg.artfctdef.muscle,'bpfreq'), cfg.artfctdef.muscle.bpfreq = [110 140]; end + if ~isfield(cfg.artfctdef.muscle,'bpfiltord'), cfg.artfctdef.muscle.bpfiltord = 10; end + if ~isfield(cfg.artfctdef.muscle,'bpfilttype'), cfg.artfctdef.muscle.bpfilttype = 'but'; end + if ~isfield(cfg.artfctdef.muscle,'hilbert'), cfg.artfctdef.muscle.hilbert = 'yes'; end + if ~isfield(cfg.artfctdef.muscle,'boxcar'), cfg.artfctdef.muscle.boxcar = 0.2; end + % settings for the zvalue subfunction + if ~isfield(cfg.artfctdef.muscle,'channel'), cfg.artfctdef.muscle.channel = 'MEG'; end + if ~isfield(cfg.artfctdef.muscle,'trlpadding'), cfg.artfctdef.muscle.trlpadding = 0.1; end + if ~isfield(cfg.artfctdef.muscle,'fltpadding'), cfg.artfctdef.muscle.fltpadding = 0.1; end + if ~isfield(cfg.artfctdef.muscle,'artpadding'), cfg.artfctdef.muscle.artpadding = 0.1; end + if ~isfield(cfg.artfctdef.muscle,'cutoff'), cfg.artfctdef.muscle.cutoff = 4; end + % construct a temporary configuration that can be passed onto artifact_zvalue + tmpcfg = []; + tmpcfg.trl = cfg.trl; + tmpcfg.artfctdef.zvalue = cfg.artfctdef.muscle; + if isfield(cfg, 'continuous'), tmpcfg.continuous = cfg.continuous; end + if isfield(cfg, 'dataformat'), tmpcfg.dataformat = cfg.dataformat; end + if isfield(cfg, 'headerformat'), tmpcfg.headerformat = cfg.headerformat; end + % call the zvalue artifact detection function + + hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + hasdata = true; + end +end + +if hasdata +% read the header +cfg = checkconfig(cfg, 'forbidden', {'dataset', 'headerfile', 'datafile'}); + [tmpcfg, artifact] = ft_artifact_zvalue(tmpcfg, data); +else + cfg = checkconfig(cfg, 'dataset2files', {'yes'}); + cfg = checkconfig(cfg, 'required', {'headerfile', 'datafile'}); + tmpcfg.datafile = cfg.datafile; + tmpcfg.headerfile = cfg.headerfile; + [tmpcfg, artifact] = ft_artifact_zvalue(tmpcfg); +end + cfg.artfctdef.muscle = tmpcfg.artfctdef.zvalue; + +else + error(sprintf('muscle artifact detection only works with cfg.method=''zvalue''')); +end + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); diff --git a/external/fieldtrip/ft_artifact_threshold.m b/external/fieldtrip/ft_artifact_threshold.m new file mode 100644 index 0000000..c7a98ac --- /dev/null +++ b/external/fieldtrip/ft_artifact_threshold.m @@ -0,0 +1,201 @@ +function [cfg, artifact] = ft_artifact_threshold(cfg,data) + +% FT_ARTIFACT_THRESHOLD scans for trials in which the range, i.e. the minimum, +% the maximum or the range (min-max difference) of the signal in any +% channel exceeds a specified threshold. +% +% use as: +% [cfg, artifact] = ft_artifact_threshold(cfg) +% required configuration options: +% cfg.dataset or both cfg.headerfile and cfg.datafile +% or +% [cfg, artifact] = ft_artifact_threshold(cfg, data) +% forbidden configuration options: +% cfg.dataset, cfg.headerfile and cfg.datafile +% +% In both cases the configuration should also contain: +% cfg.continuous = 'yes' or 'no' whether the file contains continuous data +% +% The following configuration options can be specified +% cfg.artfctdef.threshold.channel = cell-array with channel labels +% cfg.artfctdef.threshold.bpfilter = 'no' or 'yes' +% cfg.artfctdef.threshold.bpfreq = [0.3 30] +% cfg.artfctdef.threshold.bpfiltord = 4 +% +% The detection of artifacts is done according to the following settings, +% you should specify at least one of these thresholds +% cfg.artfctdef.threshold.range = value in uV/T, default inf +% cfg.artfctdef.threshold.min = value in uV/T, default -inf +% cfg.artfctdef.threshold.max = value in uV/T, default inf +% +% This function does not support partial rejections, since the whole trial +% is used to rate the minimum and maximum values. Furthermore, this +% function does not support artifact- or filterpadding. +% +% See also FT_REJECTARTIFACT +% +% Undocumented local options: +% cfg.inputfile +% cfg.outputfile +% +% Copyright (c) 2003, Robert Oostenveld, SMI, FCDC +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_artifact_threshold.m 1197 2010-06-08 07:48:54Z timeng $ + +fieldtripdefs + +% check if the input cfg is valid for this function +cfg = checkconfig(cfg, 'trackconfig', 'on'); +cfg = checkconfig(cfg, 'renamed', {'datatype', 'continuous'}); +cfg = checkconfig(cfg, 'renamedval', {'continuous', 'continuous', 'yes'}); + +% set default rejection parameters for clip artifacts if necessary +if ~isfield(cfg, 'artfctdef'), cfg.artfctdef = []; end +if ~isfield(cfg.artfctdef,'threshold'), cfg.artfctdef.threshold = []; end +if ~isfield(cfg, 'headerformat'), cfg.headerformat = []; end +if ~isfield(cfg, 'dataformat'), cfg.dataformat = []; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +% copy the specific configuration for this function out of the master cfg +artfctdef = cfg.artfctdef.threshold; + +% rename some cfg fields for backward compatibility +if isfield(artfctdef, 'sgn') && ~isfield(artfctdef, 'channel') + artfctdef.channel = artfctdef.sgn; + artfctdef = rmfield(artfctdef, 'sgn'); +end +if isfield(artfctdef, 'cutoff') && ~isfield(artfctdef, 'range') + artfctdef.range = artfctdef.cutoff; + artfctdef = rmfield(artfctdef, 'cutoff'); +end + +% set default preprocessing parameters if necessary +if ~isfield(artfctdef, 'channel'), artfctdef.channel = 'all'; end +if ~isfield(artfctdef, 'bpfilter'), artfctdef.bpfilter = 'yes'; end +if ~isfield(artfctdef, 'bpfreq'), artfctdef.bpfreq = [0.3 30]; end +if ~isfield(artfctdef, 'bpfiltord'), artfctdef.bpfiltord = 4; end + +% set the default artifact detection parameters +if ~isfield(artfctdef, 'range'), artfctdef.range = inf; end +if ~isfield(artfctdef, 'min'), artfctdef.min = -inf; end +if ~isfield(artfctdef, 'max'), artfctdef.max = inf; end + +% read the header +% depending on whether the inputfile is provided or not + +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + hasdata = true; + end +end + +if hasdata + % isfetch = 1; + cfg = checkconfig(cfg, 'forbidden', {'dataset', 'headerfile', 'datafile'}); + hdr = fetch_header(data); +else + % isfetch = 0; + cfg = checkconfig(cfg, 'dataset2files', {'yes'}); + cfg = checkconfig(cfg, 'required', {'headerfile', 'datafile'}); + hdr = ft_read_header(cfg.headerfile, 'headerformat', cfg.headerformat); +end + +% set default cfg.continuous +if ~isfield(cfg, 'continuous') + if hdr.nTrials==1 + cfg.continuous = 'yes'; + else + cfg.continuous = 'no'; + end +end + +% get the remaining settings +numtrl = size(cfg.trl,1); +channel = ft_channelselection(artfctdef.channel, hdr.label); +channelindx = match_str(hdr.label,channel); +artifact = []; + +for trlop = 1:numtrl + if hasdata + dat = fetch_data(data, 'header', hdr, 'begsample', cfg.trl(trlop,1), 'endsample', cfg.trl(trlop,2), 'chanindx', channelindx, 'checkboundary', strcmp(cfg.continuous, 'no')); + else + dat = ft_read_data(cfg.datafile, 'header', hdr, 'begsample', cfg.trl(trlop,1), 'endsample', cfg.trl(trlop,2), 'chanindx', channelindx, 'checkboundary', strcmp(cfg.continuous, 'no'), 'dataformat', cfg.dataformat); + end + dat = preproc(dat, channel, hdr.Fs, artfctdef, cfg.trl(trlop,3)); + % compute the min, max and range over all channels and samples + minval = min(dat(:)); + maxval = max(dat(:)); + rangeval = maxval-minval; + % test the min, max and range against the specified thresholds + if ~isempty(artfctdef.min) && minvalartfctdef.max + fprintf('threshold artifact scanning: trial %d from %d exceeds max-threshold\n', trlop, numtrl); + artifact(end+1,1:2) = cfg.trl(trlop,1:2); + elseif ~isempty(artfctdef.range) && rangeval>artfctdef.range + fprintf('threshold artifact scanning: trial %d from %d exceeds range-threshold\n', trlop, numtrl); + artifact(end+1,1:2) = cfg.trl(trlop,1:2); + else + fprintf('threshold artifact scanning: trial %d from %d is ok\n', trlop, numtrl); + end +end + +% remember the details that were used here +cfg.artfctdef.threshold = artfctdef; +cfg.artfctdef.threshold.trl = cfg.trl; % trialdefinition prior to rejection +cfg.artfctdef.threshold.channel = channel; % exact channels used for detection +cfg.artfctdef.threshold.artifact = artifact; % detected artifacts + +% accessing this field here is needed for the configuration tracking +% by accessing it once, it will not be removed from the output cfg +cfg.outputfile; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_artifact_threshold.m 1197 2010-06-08 07:48:54Z timeng $'; + +if hasdata && isfield(data, 'cfg') + % remember the configuration details of the input data + cfg.previous = data.cfg; +end + +% remember the exact configuration details in the output +data.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', data); % use the variable name "data" in the output file +end \ No newline at end of file diff --git a/external/fieldtrip/ft_artifact_zvalue.m b/external/fieldtrip/ft_artifact_zvalue.m new file mode 100644 index 0000000..d68eb4b --- /dev/null +++ b/external/fieldtrip/ft_artifact_zvalue.m @@ -0,0 +1,361 @@ +function [cfg, artifact] = ft_artifact_zvalue(cfg,data) + +% FT_ARTIFACT_ZVALUE reads the interesting segments of data from file and +% identifies artifacts by means of thresholding the z-transformed value +% of the preprocessed raw data. Depending on the preprocessing options, +% this method will be sensitive to EOG, muscle or jump artifacts. +% This procedure only works on continuously recorded data. +% +% Use as +% [cfg, artifact] = ft_artifact_zvalue(cfg) +% or +% [cfg, artifact] = ft_artifact_zvalue(cfg, data) +% +% The output argument "artifact" is a Nx2 matrix comparable to the +% "trl" matrix of FT_DEFINETRIAL. The first column of which specifying the +% beginsamples of an artifact period, the second column contains the +% endsamples of the artifactperiods. +% +% If you are calling FT_ARTIFACT_ZVALUE with only the configuration as first +% input argument and the data still has to be read from file, you should +% specify: +% cfg.headerfile +% cfg.headerfile +% cfg.datafile +% cfg.datatype +% +% If you are calling FT_ARTIFACT_ZVALUE with also the second input argument +% "data", then that should contain data that was already read from file in +% a call to FT_PREPROCESSING. +% +% The required configuration settings are: +% cfg.trl +% cfg.artfctdef.zvalue.channel +% cfg.artfctdef.zvalue.cutoff +% cfg.artfctdef.zvalue.trlpadding +% cfg.artfctdef.zvalue.fltpadding +% cfg.artfctdef.zvalue.artpadding +% cfg.continuous +% +% Configuration settings related to the preprocessing of the data are +% cfg.artfctdef.zvalue.lpfilter = 'no' or 'yes' lowpass filter +% cfg.artfctdef.zvalue.hpfilter = 'no' or 'yes' highpass filter +% cfg.artfctdef.zvalue.bpfilter = 'no' or 'yes' bandpass filter +% cfg.artfctdef.zvalue.lnfilter = 'no' or 'yes' line noise removal using notch filter +% cfg.artfctdef.zvalue.dftfilter = 'no' or 'yes' line noise removal using discrete fourier transform +% cfg.artfctdef.zvalue.medianfilter = 'no' or 'yes' jump preserving median filter +% cfg.artfctdef.zvalue.lpfreq = lowpass frequency in Hz +% cfg.artfctdef.zvalue.hpfreq = highpass frequency in Hz +% cfg.artfctdef.zvalue.bpfreq = bandpass frequency range, specified as [low high] in Hz +% cfg.artfctdef.zvalue.lnfreq = line noise frequency in Hz, default 50Hz +% cfg.artfctdef.zvalue.lpfiltord = lowpass filter order +% cfg.artfctdef.zvalue.hpfiltord = highpass filter order +% cfg.artfctdef.zvalue.bpfiltord = bandpass filter order +% cfg.artfctdef.zvalue.lnfiltord = line noise notch filter order +% cfg.artfctdef.zvalue.medianfiltord = length of median filter +% cfg.artfctdef.zvalue.lpfilttype = digital filter type, 'but' (default) or 'fir' +% cfg.artfctdef.zvalue.hpfilttype = digital filter type, 'but' (default) or 'fir' +% cfg.artfctdef.zvalue.bpfilttype = digital filter type, 'but' (default) or 'fir' +% cfg.artfctdef.zvalue.detrend = 'no' or 'yes' +% cfg.artfctdef.zvalue.blc = 'no' or 'yes' +% cfg.artfctdef.zvalue.blcwindow = [begin end] in seconds, the default is the complete trial +% cfg.artfctdef.zvalue.hilbert = 'no' or 'yes' +% cfg.artfctdef.zvalue.rectify = 'no' or 'yes' +% +% See also FT_REJECTARTIFACT + +% Copyright (c) 2003-2005, Jan-Mathijs Schoffelen, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_artifact_zvalue.m 1038 2010-05-05 15:48:52Z timeng $ + +fieldtripdefs + +% set default rejection parameters +if ~isfield(cfg,'artfctdef'), cfg.artfctdef = []; end +if ~isfield(cfg.artfctdef,'zvalue'), cfg.artfctdef.zvalue = []; end +if ~isfield(cfg, 'headerformat'), cfg.headerformat = []; end +if ~isfield(cfg, 'dataformat'), cfg.dataformat = []; end + +% for backward compatibility +if isfield(cfg.artfctdef.zvalue,'sgn') + cfg.artfctdef.zvalue.channel = cfg.artfctdef.zvalue.sgn; + cfg.artfctdef.zvalue = rmfield(cfg.artfctdef.zvalue, 'sgn'); +end + +if isfield(cfg.artfctdef.zvalue, 'artifact') + fprintf('zvalue artifact detection has already been done, retaining artifacts\n'); + artifact = cfg.artfctdef.zvalue.artifact; + return +end + +if ~isfield(cfg.artfctdef.zvalue,'channel'), cfg.artfctdef.zvalue.channel = {}; end +if ~isfield(cfg.artfctdef.zvalue,'trlpadding'), cfg.artfctdef.zvalue.trlpadding = 0; end +if ~isfield(cfg.artfctdef.zvalue,'artpadding'), cfg.artfctdef.zvalue.artpadding = 0; end +if ~isfield(cfg.artfctdef.zvalue,'fltpadding'), cfg.artfctdef.zvalue.fltpadding = 0; end +if ~isfield(cfg.artfctdef.zvalue,'feedback'), cfg.artfctdef.zvalue.feedback = 'no'; end +if ~isfield(cfg.artfctdef.zvalue,'cumulative'), cfg.artfctdef.zvalue.cumulative = 'yes'; end + +thresholdsum = strcmp(cfg.artfctdef.zvalue.cumulative, 'yes'); + +if nargin > 1 + % data given as input + isfetch = 1; + hdr = fetch_header(data); +elseif nargin == 1 + % only cfg given + isfetch = 0; + hdr = ft_read_header(cfg.headerfile, 'headerformat', cfg.headerformat); +end + +% set default cfg.continuous +if ~isfield(cfg, 'continuous') + if hdr.nTrials==1 + cfg.continuous = 'yes'; + else + cfg.continuous = 'no'; + end +end + +trl = cfg.trl; +trlpadding = round(cfg.artfctdef.zvalue.trlpadding*hdr.Fs); +fltpadding = round(cfg.artfctdef.zvalue.fltpadding*hdr.Fs); +artpadding = round(cfg.artfctdef.zvalue.artpadding*hdr.Fs); +trl(:,1) = trl(:,1) - trlpadding; % pad the trial with some samples, in order to detect +trl(:,2) = trl(:,2) + trlpadding; % artifacts at the edges of the relevant trials. +trl(:,3) = nan; % the offset is not correct any more +trllength = trl(:,2) - trl(:,1) + 1; % length of each trial +numtrl = size(trl,1); +cfg.artfctdef.zvalue.trl = trl; % remember where we are going to look for artifacts +cfg.artfctdef.zvalue.channel = ft_channelselection(cfg.artfctdef.zvalue.channel, hdr.label); +sgnind = match_str(hdr.label, cfg.artfctdef.zvalue.channel); +numsgn = length(sgnind); + +if numsgn<1 + error('no channels selected'); +else + fprintf('searching for artifacts in %d channels\n', numsgn); +end + +% read the data and apply preprocessing options +sumval = zeros(numsgn, 1); +sumsqr = zeros(numsgn, 1); +numsmp = zeros(numsgn, 1); +fprintf('searching trials'); +for trlop = 1:numtrl + fprintf('.'); + if isfetch + dat{trlop} = fetch_data(data, 'header', hdr, 'begsample', trl(trlop,1)-fltpadding, 'endsample', trl(trlop,2)+fltpadding, 'chanindx', sgnind, 'checkboundary', strcmp(cfg.continuous,'no')); + else + dat{trlop} = ft_read_data(cfg.datafile, 'header', hdr, 'begsample', trl(trlop,1)-fltpadding, 'endsample', trl(trlop,2)+fltpadding, 'chanindx', sgnind, 'checkboundary', strcmp(cfg.continuous,'no'), 'dataformat', cfg.dataformat); + end + dat{trlop} = preproc(dat{trlop}, cfg.artfctdef.zvalue.channel, hdr.Fs, cfg.artfctdef.zvalue, [], fltpadding, fltpadding); + % accumulate the sum and the sum-of-squares + sumval = sumval + sum(dat{trlop},2); + sumsqr = sumsqr + sum(dat{trlop}.^2,2); + numsmp = numsmp + size(dat{trlop},2); +end % for trlop + +% compute the average and the standard deviation +datavg = sumval./numsmp; +datstd = sqrt(sumsqr./numsmp - (sumval./numsmp).^2); + +for trlop = 1:numtrl + % initialize some matrices + zmax{trlop} = -inf + zeros(1,size(dat{trlop},2)); + zsum{trlop} = zeros(1,size(dat{trlop},2)); + zindx{trlop} = zeros(1,size(dat{trlop},2)); + + nsmp = size(dat{trlop},2); + zdata = (dat{trlop} - datavg(:,ones(1,nsmp)))./datstd(:,ones(1,nsmp)); % convert the filtered data to z-values + zsum{trlop} = sum(zdata,1); % accumulate the z-values over channels + [zmax{trlop},ind] = max(zdata,[],1); % find the maximum z-value and remember it + zindx{trlop} = sgnind(ind); % also remember the channel number that has the largest z-value + + % This alternative code does the same, but it is much slower + % for i=1:size(zmax{trlop},2) + % if zdata{trlop}(i)>zmax{trlop}(i) + % % update the maximum value and channel index + % zmax{trlop}(i) = zdata{trlop}(i); + % zindx{trlop}(i) = sgnind(sgnlop); + % end + % end +end % for trlop + +%for sgnlop=1:numsgn +% % read the data and apply preprocessing options +% sumval = 0; +% sumsqr = 0; +% numsmp = 0; +% fprintf('searching channel %s ', cfg.artfctdef.zvalue.channel{sgnlop}); +% for trlop = 1:numtrl +% fprintf('.'); +% if isfetch +% dat{trlop} = fetch_data(data, 'header', hdr, 'begsample', trl(trlop,1)-fltpadding, 'endsample', trl(trlop,2)+fltpadding, 'chanindx', sgnind(sgnlop), 'checkboundary', strcmp(cfg.continuous,'no')); +% else +% dat{trlop} = read_data(cfg.datafile, 'header', hdr, 'begsample', trl(trlop,1)-fltpadding, 'endsample', trl(trlop,2)+fltpadding, 'chanindx', sgnind(sgnlop), 'checkboundary', strcmp(cfg.continuous,'no')); +% end +% dat{trlop} = preproc(dat{trlop}, cfg.artfctdef.zvalue.channel(sgnlop), hdr.Fs, cfg.artfctdef.zvalue, [], fltpadding, fltpadding); +% % accumulate the sum and the sum-of-squares +% sumval = sumval + sum(dat{trlop},2); +% sumsqr = sumsqr + sum(dat{trlop}.^2,2); +% numsmp = numsmp + size(dat{trlop},2); +% end % for trlop +% +% % compute the average and the standard deviation +% datavg = sumval./numsmp; +% datstd = sqrt(sumsqr./numsmp - (sumval./numsmp).^2); +% +% for trlop = 1:numtrl +% if sgnlop==1 +% % initialize some matrices +% zdata{trlop} = zeros(size(dat{trlop})); +% zmax{trlop} = -inf + zeros(size(dat{trlop})); +% zsum{trlop} = zeros(size(dat{trlop})); +% zindx{trlop} = zeros(size(dat{trlop})); +% end +% zdata{trlop} = (dat{trlop} - datavg)./datstd; % convert the filtered data to z-values +% zsum{trlop} = zsum{trlop} + zdata{trlop}; % accumulate the z-values over channels +% zmax{trlop} = max(zmax{trlop}, zdata{trlop}); % find the maximum z-value and remember it +% zindx{trlop}(zmax{trlop}==zdata{trlop}) = sgnind(sgnlop); % also remember the channel number that has the largest z-value +% +% % This alternative code does the same, but it is much slower +% % for i=1:size(zmax{trlop},2) +% % if zdata{trlop}(i)>zmax{trlop}(i) +% % % update the maximum value and channel index +% % zmax{trlop}(i) = zdata{trlop}(i); +% % zindx{trlop}(i) = sgnind(sgnlop); +% % end +% % end +% end +% fprintf('\n'); +%end % for sgnlop + +for trlop = 1:numtrl + zsum{trlop} = zsum{trlop} ./ sqrt(numsgn); +end + +if strcmp(cfg.artfctdef.zvalue.feedback, 'yes') + % give graphical feedback and allow the user to modify the threshold + interactiveloop = 1; + while interactiveloop + h = figure; + hold on + for trlop=1:numtrl + xval = trl(trlop,1):trl(trlop,2); + if thresholdsum, + yval = zsum{trlop}; + else + yval = zmax{trlop}; + end + plot(xval, yval, 'b-'); + dum = yval<=cfg.artfctdef.zvalue.cutoff; + yval(dum) = nan; + plot(xval, yval, 'r-'); + end + hline(cfg.artfctdef.zvalue.cutoff, 'color', 'r', 'linestyle', ':'); + xlabel('sample number'); + ylabel('cumulative z-value'); + [response, interactiveloop] = smartinput('\nwould you like to page through the data [y/N]? ', 'n'); + artval = {}; + for trlop=1:numtrl + if thresholdsum, + % threshold the accumulated z-values + artval{trlop} = zsum{trlop}>cfg.artfctdef.zvalue.cutoff; + else + % threshold the max z-values + artval{trlop} = zmax{trlop}>cfg.artfctdef.zvalue.cutoff; + end + % pad the artifacts + artbeg = find(diff([0 artval{trlop}])== 1); + artend = find(diff([artval{trlop} 0])==-1); + artbeg = artbeg - artpadding; + artend = artend + artpadding; + artbeg(artbeg<1) = 1; + artend(artend>length(artval{trlop})) = length(artval{trlop}); + for artlop=1:length(artbeg) + artval{trlop}(artbeg(artlop):artend(artlop)) = 1; + end + end + % show the z-values, the artifacts and a selection of the original data + if interactiveloop + if nargin==1, + if ~thresholdsum, zsum = zmax; end; + artifact_viewer(cfg, cfg.artfctdef.zvalue, zsum, artval, zindx); + cfg.artfctdef.zvalue.cutoff = smartinput(sprintf('\ngive new cutoff value, or press enter to accept current value [%g]: ', cfg.artfctdef.zvalue.cutoff), cfg.artfctdef.zvalue.cutoff); + else + if ~thresholdsum, zsum = zmax; end; + artifact_viewer(cfg, cfg.artfctdef.zvalue, zsum, artval, zindx, data); + cfg.artfctdef.zvalue.cutoff = smartinput(sprintf('\ngive new cutoff value, or press enter to accept current value [%g]: ', cfg.artfctdef.zvalue.cutoff), cfg.artfctdef.zvalue.cutoff); + end + end + if ishandle(h), close(h), end; + end % interactiveloop +else + % this code snippet is the same as above, but without the plotting + artval = {}; + for trlop=1:numtrl + if thresholdsum, + % threshold the accumulated z-values + artval{trlop} = zsum{trlop}>cfg.artfctdef.zvalue.cutoff; + else + % threshold the max z-values + artval{trlop} = zmax{trlop}>cfg.artfctdef.zvalue.cutoff; + end + % pad the artifacts + artbeg = find(diff([0 artval{trlop}])== 1); + artend = find(diff([artval{trlop} 0])==-1); + artbeg = artbeg - artpadding; + artend = artend + artpadding; + artbeg(artbeg<1) = 1; + artend(artend>length(artval{trlop})) = length(artval{trlop}); + for artlop=1:length(artbeg) + artval{trlop}(artbeg(artlop):artend(artlop)) = 1; + end + end +end % feedback + +% convert to one long vector +dum = zeros(1,max(trl(:,2))); +for trlop=1:numtrl + dum(trl(trlop,1):trl(trlop,2)) = artval{trlop}; +end +artval = dum; + +% find the padded artifacts and put them in a Nx2 trl-like matrix +artbeg = find(diff([0 artval])== 1); +artend = find(diff([artval 0])==-1); +artifact = [artbeg(:) artend(:)]; + +% remember the artifacts that were found +cfg.artfctdef.zvalue.artifact = artifact; + +fprintf('detected %d artifacts\n', size(artifact,1)); + +% add version information to the configuration +try + % get the full name of the function + cfg.artfctdef.zvalue.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.artfctdef.zvalue.version.name = st(i); +end +cfg.artfctdef.zvalue.version.id = '$Id: ft_artifact_zvalue.m 1038 2010-05-05 15:48:52Z timeng $'; + + diff --git a/external/fieldtrip/ft_channelcombination.m b/external/fieldtrip/ft_channelcombination.m index b84b9b2..7a427c4 100644 --- a/external/fieldtrip/ft_channelcombination.m +++ b/external/fieldtrip/ft_channelcombination.m @@ -1,11 +1,146 @@ -function varargout = funname(varargin); +function [collect] = ft_channelcombination(channelcmb, datachannel, includeauto) -% this is a SPM wrapper around a FieldTrip function +% FT_CHANNELCOMBINATION creates a cell-array with combinations of EEG/MEG +% channels for subsequent cross-spectral-density and coherence analysis +% +% You should specify channel combinations as a two-column cell array, +% cfg.channelcmb = { 'EMG' 'MLF31' +% 'EMG' 'MLF32' +% 'EMG' 'MLF33' }; +% to compare EMG with these three sensors, or +% cfg.channelcmb = { 'MEG' 'MEG' }; +% to make all MEG combinations, or +% cfg.channelcmb = { 'EMG' 'MEG' }; +% to make all combinations between the EMG and all MEG channels. +% +% For each column, you can specify a mixture of real channel labels +% and of special strings that will be replaced by the corresponding +% channel labels. Channels that are not present in the raw datafile +% are automatically removed from the channel list. +% +% See also FT_CHANNELSELECTION -% this part is variable -prefix = 'ft_'; +% Undocumented local options: +% optional third input argument includeauto, specifies to include the +% auto-combinations -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +% Copyright (C) 2003-2006, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_channelcombination.m 948 2010-04-21 18:02:21Z roboos $ + +fieldtripdefs + +if nargin==2, + includeauto = 0; +end + +if ischar(channelcmb) && strcmp(channelcmb, 'all') + % make all possible combinations of all channels + channelcmb = {'all' 'all'}; +end + +% it should have a selection of two channels or channelgroups in each row +if size(channelcmb,1)==2 && size(channelcmb,2)~=2 + warning('transposing channelcombination matrix'); +end + +% this will hold the output +collect = {}; + +if isempty(setdiff(channelcmb(:), datachannel)) + % there is nothing to do, since there are no channelgroups with special names + % each element of the input therefore already contains a proper channel name + collect = channelcmb; + + if includeauto + for ch=1:numel(datachannel) + collect{end+1,1} = datachannel{ch}; + collect{end, 2} = datachannel{ch}; + end + end +else + % a combination is made for each row of the input selection after + % translating the channel group (such as 'all') to the proper channel names + % and within each set, double occurences and autocombinations are removed + + for sel=1:size(channelcmb,1) + % translate both columns and subsequently make all combinations + channelcmb1 = ft_channelselection(channelcmb(sel,1), datachannel); + channelcmb2 = ft_channelselection(channelcmb(sel,2), datachannel); + + % compute indices of channelcmb1 and channelcmb2 relative to datachannel + [dum,indx,indx1]=intersect(channelcmb1,datachannel); + [dum,indx,indx2]=intersect(channelcmb2,datachannel); + + % remove double occurrences of channels in either set of signals + indx1 = unique(indx1); + indx2 = unique(indx2); + + % create a matrix in which all possible combinations are set to one + cmb = zeros(length(datachannel)); + for ch1=1:length(indx1) + for ch2=1:length(indx2) + cmb(indx1(ch1),indx2(ch2))=1; + end + end + + % remove auto-combinations + cmb = cmb & ~eye(size(cmb)); + + % remove double occurences + cmb = cmb & ~tril(cmb, -1)'; + + [indx1,indx2] = find(cmb); + + % extend the previously allocated cell-array to also hold the new + % channel combinations (this is done to prevent memory allocation and + % copying in each iteration in the for-loop below) + num = size(collect,1); % count the number of existing combinations + dum = cell(num + length(indx1), 2); % allocate space for the existing+new combinations + if num>0 + dum(1:num,:) = collect(:,:); % copy the exisisting combinations into the new array + end + collect = dum; + clear dum + + % convert to channel-names + for ch=1:length(indx1) + collect{num+ch,1}=datachannel{indx1(ch)}; + collect{num+ch,2}=datachannel{indx2(ch)}; + end + end + + if includeauto + cmb = eye(length(datachannel)); + [indx1,indx2] = find(cmb); + num = size(collect,1); + dum = cell(num + length(indx1), 2); + if num>0, + dum(1:num,:) = collect(:,:); + end + collect = dum; + clear dum + + % convert to channel-names for the auto-combinations + for ch=1:length(indx1) + collect{num+ch,1} = datachannel{indx1(ch)}; + collect{num+ch,2} = datachannel{indx2(ch)}; + end + end +end diff --git a/external/fieldtrip/ft_channelnormalise.m b/external/fieldtrip/ft_channelnormalise.m new file mode 100644 index 0000000..3936691 --- /dev/null +++ b/external/fieldtrip/ft_channelnormalise.m @@ -0,0 +1,122 @@ +function [dataout] = ft_channelnormalise(cfg, data); + +% FT_CHANNELNORMALISE normalises the input data to a mean of 0 and +% a standard deviation of 1. +% +% Use as +% [dataout] = ft_channelnormalise(cfg, data) +% +% The configuration can contain +% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') +% +% Undocumented local options: +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk +% Copyright (C) 2010, Jan-Mathijs Schoffelen + +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_channelnormalise.m $ + +fieldtripdefs + +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +% set the defaults +if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + end +end + +% check if the input data is valid for this function +data = checkdata(data, 'datatype', 'raw', 'feedback', 'yes'); + +% select trials of interest +if ~strcmp(cfg.trials, 'all') + fprintf('selecting %d trials\n', length(cfg.trials)); + data = selectdata(data, 'rpt', cfg.trials); +end + +% initialise some variables +nchan = numel(data.label); +ntrl = numel(data.trial); +datsum = zeros(nchan,1); +datssq = zeros(nchan,1); + +% create output data, omitting sensor information +% FIXME this can be kept, provided the scaling is built in appropriately +dataout = []; +dataout.label = data.label; +dataout.fsample = data.fsample; +dataout.trial = cell(1,ntrl); +dataout.time = data.time; +if isfield(data, 'trialdef'), dataout.trialdef = data.trialdef; end +if isfield(data, 'trialinfo'), dataout.trialinfo = data.trialinfo; end + +% compute the mean and std +for k = 1:ntrl + n(k,1) = size(data.trial{k},2); + datsum = datsum + sum(data.trial{k},2); + datssq = datssq + sum(data.trial{k}.^2,2); +end +datmean = datsum./sum(n); +datstd = sqrt( (datssq - (datsum.^2)./sum(n))./sum(n)); %quick way to compute std from sum and sum-of-squared values + +% demean and normalise +for k = 1:ntrl + dataout.trial{k} = (data.trial{k}-datmean(:,ones(1,n(k))))./datstd(:,ones(1,n(k))); +end + + +% accessing this field here is needed for the configuration tracking +% by accessing it once, it will not be removed from the output cfg +cfg.outputfile; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% store the configuration of this function call, including that of the previous function call +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_channelnormalise.m $'; +% remember the configuration details of the input data + +% remember the configuration details of the input data +try cfg.previous = data.cfg;end + +% remember the exact configuration details in the output +dataout.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', dataout); % use the variable name "data" in the output file +end diff --git a/external/fieldtrip/ft_channelrepair.m b/external/fieldtrip/ft_channelrepair.m new file mode 100644 index 0000000..c0afd9c --- /dev/null +++ b/external/fieldtrip/ft_channelrepair.m @@ -0,0 +1,169 @@ +function [interp] = ft_channelrepair(cfg, data); + +% FT_CHANNELREPAIR repairs bad channels in MEG or EEG data by replacing them +% with the average of its neighbours. It cannot be used reliably to +% repair multiple bad channels that lie next to each other. +% +% Use as +% [interp] = ft_channelrepair(cfg, data) +% +% The configuration can contain +% cfg.badchannel = cell-array, see FT_CHANNELSELECTION for details +% cfg.neighbourdist = default is 4 cm +% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') +% +% Since a nearest neighbour average is used, the input should contain +% a gradiometer or electrode definition, i.e. data.grad or data.elec. +% +% See also FT_MEGINTERPOLATE +% +% Undocumented local options: +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk +% Copyright (C) 2004-2009, Robert Oostenveld + +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_channelrepair.m 1437 2010-07-21 11:53:51Z jansch $ + +fieldtripdefs + +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +% set the default configuration +if ~isfield(cfg, 'neighbourdist'), cfg.neighbourdist = 4; end +if ~isfield(cfg, 'badchannel'), cfg.badchannel = {}; end +if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + end +end + +% check if the input data is valid for this function +data = checkdata(data, 'datatype', 'raw', 'feedback', 'yes'); + +% select trials of interest +if ~strcmp(cfg.trials, 'all') + fprintf('selecting %d trials\n', length(cfg.trials)); + data = selectdata(data, 'rpt', cfg.trials); +end + +% determine the type of data +iseeg = ft_senstype(data, 'eeg'); +ismeg = ft_senstype(data, 'meg'); + +if iseeg + sens = data.elec; +elseif ismeg + sens = data.grad; +else + error('the data should contain either an electrode or a gradiometer definition'); +end + +% get the selection of channels that are bad +cfg.badchannel = ft_channelselection(cfg.badchannel, data.label); +[goodchanlabels,goodchanindcs] = setdiff(data.label,cfg.badchannel); +[goodsenslabels,goodsensindcs] = intersect(sens.label,goodchanlabels); + +Ntrials = length(data.trial); +Nchans = length(data.label); +Nsens = length(sens.label); + +repair = eye(Nchans,Nchans); +[badindx] = match_str(data.label, cfg.badchannel); + +for k=badindx(:)' + fprintf('repairing channel %s\n', data.label{k}); + repair(k,k) = 0; + + sensindx = match_str(sens.label, data.label{k}); + for l=goodsensindcs(:)' + distance = norm(sens.pnt(l,:)-sens.pnt(sensindx,:)); + if distance. +% +% $Id: ft_channelselection.m 1315 2010-06-30 19:13:57Z roboos $ + +fieldtripdefs + +if length(datachannel)~=length(unique(datachannel)) + error('data with non-unique channel names is not supported'); +end + +if any(size(channel) == 0) + % there is nothing to do if it is empty + return +end + +if isnumeric(channel) + % change index into channelname + channel = datachannel(channel); + return +end + +if ~iscell(channel) + % ensure that a single input argument like 'all' also works + channel = {channel}; +end + +if ~iscell(datachannel) + % ensure that a single input argument like 'all' also works + datachannel = {datachannel}; +end + +% ensure that both inputs are column vectors +channel = channel(:); +datachannel = datachannel(:); + +% remove channels that occur more than once, this sorts the channels alphabetically +[channel, indx] = unique(channel); +% undo the sorting, make the order identical to that of the data channels +[dum, indx] = sort(indx); +channel = channel(indx); + +[dataindx, chanindx] = match_str(datachannel, channel); +if length(chanindx)==length(channel) + % there is a perfect match between the channels and the datachannels, only some reordering is needed + channel = channel(chanindx); + % no need to look at channel groups + return +end + +% define the known groups with channel labels +labelall = datachannel; +label1020 = ft_senslabel('eeg1020'); % use external helper function +label1010 = ft_senslabel('eeg1010'); % use external helper function +label1005 = ft_senslabel('eeg1005'); % use external helper function +labelchwilla = {'Fz', 'Cz', 'Pz', 'F7', 'F8', 'LAT', 'RAT', 'LT', 'RT', 'LTP', 'RTP', 'OL', 'OR', 'FzA', 'Oz', 'F7A', 'F8A', 'F3A', 'F4A', 'F3', 'F4', 'P3', 'P4', 'T5', 'T6', 'P3P', 'P4P'}'; +labelbham = {'P9', 'PPO9h', 'PO7', 'PPO5h', 'PPO3h', 'PO5h', 'POO9h', 'PO9', 'I1', 'OI1h', 'O1', 'POO1', 'PO3h', 'PPO1h', 'PPO2h', 'POz', 'Oz', 'Iz', 'I2', 'OI2h', 'O2', 'POO2', 'PO4h', 'PPO4h', 'PO6h', 'POO10h', 'PO10', 'PO8', 'PPO6h', 'PPO10h', 'P10', 'P8', 'TPP9h', 'TP7', 'TTP7h', 'CP5', 'TPP7h', 'P7', 'P5', 'CPP5h', 'CCP5h', 'CP3', 'P3', 'CPP3h', 'CCP3h', 'CP1', 'P1', 'Pz', 'CPP1h', 'CPz', 'CPP2h', 'P2', 'CPP4h', 'CP2', 'CCP4h', 'CP4', 'P4', 'P6', 'CPP6h', 'CCP6h', 'CP6', 'TPP8h', 'TP8', 'TPP10h', 'T7', 'FTT7h', 'FT7', 'FC5', 'FCC5h', 'C5', 'C3', 'FCC3h', 'FC3', 'FC1', 'C1', 'CCP1h', 'Cz', 'FCC1h', 'FCz', 'FFC1h', 'Fz', 'FFC2h', 'FC2', 'FCC2h', 'CCP2h', 'C2', 'C4', 'FCC4h', 'FC4', 'FC6', 'FCC6h', 'C6', 'TTP8h', 'T8', 'FTT8h', 'FT8', 'FT9', 'FFT9h', 'F7', 'FFT7h', 'FFC5h', 'F5', 'AFF7h', 'AF7', 'AF5h', 'AFF5h', 'F3', 'FFC3h', 'F1', 'AF3h', 'Fp1', 'Fpz', 'Fp2', 'AFz', 'AF4h', 'F2', 'FFC4h', 'F4', 'AFF6h', 'AF6h', 'AF8', 'AFF8h', 'F6', 'FFC6h', 'FFT8h', 'F8', 'FFT10h', 'FT10'}; +labelref = {'M1', 'M2', 'LM', 'RM', 'A1', 'A2'}'; +labeleog = datachannel(strncmp('EOG', datachannel, length('EOG'))); % anything that starts with EOG +labeleog = {labeleog{:} 'HEOG', 'VEOG', 'VEOG-L', 'VEOG-R', 'hEOG', 'vEOG', 'Eye_Ver', 'Eye_Hor'}'; % or any of these +labelemg = datachannel(strncmp('EMG', datachannel, length('EMG'))); +labellfp = datachannel(strncmp('lfp', datachannel, length('lfp'))); +labelmua = datachannel(strncmp('mua', datachannel, length('mua'))); +labelspike = datachannel(strncmp('spike', datachannel, length('spike'))); + +% use regular expressions to deal with the wildcards +labelreg = false(size(datachannel)); +findreg = []; +for i=1:length(channel) + if length(channel{i})>1 && channel{i}(1)=='*' + % the wildcard is at the start + labelreg = labelreg | ~cellfun(@isempty, regexp(datachannel, ['.*' channel{i}(2:end) '$'], 'once')); + findreg = [findreg i]; + elseif length(channel{i})>1 && channel{i}(end)=='*' + % the wildcard is at the end + labelreg = labelreg | ~cellfun(@isempty, regexp(datachannel, ['^' channel{i}(1:end-1) '.*'], 'once')); + findreg = [findreg i]; + elseif length(channel{i})>1 && any(channel{i}=='*') + % the wildcard is in the middle + sel = strfind(channel{i}, '*'); + str1 = channel{i}(1:(sel-1)); + str2 = channel{i}((sel+1):end); + labelreg = labelreg | ~cellfun(@isempty, regexp(datachannel, ['^' str1 '.*' str2 '$'], 'once')); + findreg = [findreg i]; + end +end +labelreg = datachannel(labelreg); + +% initialize all the system-specific variables to empty +labelmeg = []; +labelmref = []; +labeleeg = []; + +switch ft_senstype(datachannel) + + case {'yokogawa', 'yokogawa160', 'yokogawa160_planar'} + % Yokogawa axial gradiometers channels start with AG, hardware planar gradiometer + % channels start with PG, magnetometers start with M + megax =strncmp('AG', datachannel, length('AG')); + megpl =strncmp('PG', datachannel, length('PG')); + megmag =strncmp('M', datachannel, length('M')); + megind = logical( megax + megpl + megmag); + labelmeg = datachannel(megind); + + case {'ctf', 'ctf275', 'ctf151', 'ctf275_planar', 'ctf151_planar'} + % all CTF MEG channels start with "M" + % all CTF reference channels start with B, G, P, Q or R + % all CTF EEG channels start with "EEG" + labelmeg = datachannel(strncmp('M' , datachannel, length('M' ))); + labelmref = [datachannel(strncmp('B' , datachannel, 1)); + datachannel(strncmp('G' , datachannel, 1)); + datachannel(strncmp('P' , datachannel, 1)); + datachannel(strncmp('Q' , datachannel, 1)); + datachannel(strncmp('R' , datachannel, length('G' )))]; + labeleeg = datachannel(strncmp('EEG', datachannel, length('EEG'))); + + % Not sure whether this should be here or outside the switch or + % whether these specifications should be supported for systems + % other than CTF. + labelmz = datachannel(strncmp('MZ' , datachannel, length('MZ' ))); % central MEG channels + labelml = datachannel(strncmp('ML' , datachannel, length('ML' ))); % left MEG channels + labelmr = datachannel(strncmp('MR' , datachannel, length('MR' ))); % right MEG channels + labelmlc = datachannel(strncmp('MLC', datachannel, length('MLC'))); + labelmlf = datachannel(strncmp('MLF', datachannel, length('MLF'))); + labelmlo = datachannel(strncmp('MLO', datachannel, length('MLO'))); + labelmlp = datachannel(strncmp('MLP', datachannel, length('MLP'))); + labelmlt = datachannel(strncmp('MLT', datachannel, length('MLT'))); + labelmrc = datachannel(strncmp('MRC', datachannel, length('MRC'))); + labelmrf = datachannel(strncmp('MRF', datachannel, length('MRF'))); + labelmro = datachannel(strncmp('MRO', datachannel, length('MRO'))); + labelmrp = datachannel(strncmp('MRP', datachannel, length('MRP'))); + labelmrt = datachannel(strncmp('MRT', datachannel, length('MRT'))); + labelmzc = datachannel(strncmp('MZC', datachannel, length('MZC'))); + labelmzf = datachannel(strncmp('MZF', datachannel, length('MZF'))); + labelmzo = datachannel(strncmp('MZO', datachannel, length('MZO'))); + labelmzp = datachannel(strncmp('MZP', datachannel, length('MZP'))); + + case {'bti', 'bti248', 'bti148', 'bti248_planar', 'bti148_planar'} + % all 4D-BTi MEG channels start with "A" + % all 4D-BTi reference channels start with M or G + labelmeg = datachannel(strncmp('A' , datachannel, 1)); + labelmref = [datachannel(strncmp('M' , datachannel, 1)); + datachannel(strncmp('G' , datachannel, 1))]; + labelmrefa = datachannel(~cellfun(@isempty,strfind(datachannel, 'a'))); + labelmrefc = datachannel(strncmp('MC', datachannel, 2)); + labelmrefg = datachannel(strncmp('G', datachannel, 1)); + labelmrefl = datachannel(strncmp('ML', datachannel, 2)); + labelmrefr = datachannel(strncmp('MR', datachannel, 2)); + + case {'neuromag306', 'neuromag122'} + % all neuromag MEG channels start with MEG + % all neuromag EEG channels start with EEG + labelmeg = datachannel(strncmp('MEG', datachannel, length('MEG'))); + labeleeg = datachannel(strncmp('EEG', datachannel, length('EEG'))); + + case {'biosemi64', 'biosemi128', 'biosemi256', 'egi64', 'egi128', 'egi256', 'ext1020'} + % use an external helper function to define the list with EEG channel names + labeleeg = ft_senslabel(ft_senstype(datachannel)); + +end % switch ft_senstype + +% figure out if there are bad channels or channel groups that should be excluded +findbadchannel = strncmp('-', channel, length('-')); % bad channels start with '-' +badchannel = channel(findbadchannel); +if ~isempty(badchannel) + for i=1:length(badchannel) + badchannel{i} = badchannel{i}(2:end); % remove the '-' from the channel label + end + badchannel = ft_channelselection(badchannel, datachannel); % support exclusion of channel groups + channel(findbadchannel) = []; % remove them from the channels to be processed +end + +% determine if any of the known groups is mentioned in the channel list +findall = find(strcmp(channel, 'all')); +% findreg (for the wildcards) is dealt with in the channel group specification above +findmeg = find(strcmp(channel, 'MEG')); +findemg = find(strcmp(channel, 'EMG')); +findeeg = find(strcmp(channel, 'EEG')); +findeeg1020 = find(strcmp(channel, 'EEG1020')); +findeeg1010 = find(strcmp(channel, 'EEG1010')); +findeeg1005 = find(strcmp(channel, 'EEG1005')); +findeegchwilla = find(strcmp(channel, 'EEGCHWILLA')); +findeegbham = find(strcmp(channel, 'EEGBHAM')); +findeegref = find(strcmp(channel, 'EEGREF')); +findmegref = find(strcmp(channel, 'MEGREF')); +findmegrefa = find(strcmp(channel, 'MEGREFA')); +findmegrefc = find(strcmp(channel, 'MEGREFC')); +findmegrefg = find(strcmp(channel, 'MEGREFG')); +findmegrefl = find(strcmp(channel, 'MEGREFL')); +findmegrefr = find(strcmp(channel, 'MEGREFR')); +findeog = find(strcmp(channel, 'EOG')); +findmz = find(strcmp(channel, 'MZ' )); +findml = find(strcmp(channel, 'ML' )); +findmr = find(strcmp(channel, 'MR' )); +findmlc = find(strcmp(channel, 'MLC')); +findmlf = find(strcmp(channel, 'MLF')); +findmlo = find(strcmp(channel, 'MLO')); +findmlp = find(strcmp(channel, 'MLP')); +findmlt = find(strcmp(channel, 'MLT')); +findmrc = find(strcmp(channel, 'MRC')); +findmrf = find(strcmp(channel, 'MRF')); +findmro = find(strcmp(channel, 'MRO')); +findmrp = find(strcmp(channel, 'MRP')); +findmrt = find(strcmp(channel, 'MRT')); +findmzc = find(strcmp(channel, 'MZC')); +findmzf = find(strcmp(channel, 'MZF')); +findmzo = find(strcmp(channel, 'MZO')); +findmzp = find(strcmp(channel, 'MZP')); +findlfp = find(strcmp(channel, 'lfp')); +findmua = find(strcmp(channel, 'mua')); +findspike = find(strcmp(channel, 'spike')); +findgui = find(strcmp(channel, 'gui')); + +% remove any occurences of groups in the channel list +channel([ + findall + findreg + findmeg + findemg + findeeg + findeeg1020 + findeeg1010 + findeeg1005 + findeegchwilla + findeegbham + findeegref + findmegref + findeog + findmz + findml + findmr + findmlc + findmlf + findmlo + findmlp + findmlt + findmrc + findmrf + findmro + findmrp + findmrt + findmzc + findmzf + findmzo + findmzp + findlfp + findmua + findspike + findgui + ]) = []; + +% add the full channel labels to the channel list +if findall, channel = [channel; labelall]; end +if findreg, channel = [channel; labelreg]; end +if findmeg, channel = [channel; labelmeg]; end +if findemg, channel = [channel; labelemg]; end +if findeeg, channel = [channel; labeleeg]; end +if findeeg1020, channel = [channel; label1020]; end +if findeeg1010, channel = [channel; label1010]; end +if findeeg1005, channel = [channel; label1005]; end +if findeegchwilla, channel = [channel; labelchwilla]; end +if findeegbham, channel = [channel; labelbham]; end +if findeegref, channel = [channel; labelref]; end +if findmegref, channel = [channel; labelmref]; end +if findmegrefa, channel = [channel; labelmrefa]; end +if findmegrefc, channel = [channel; labelmrefc]; end +if findmegrefg, channel = [channel; labelmrefg]; end +if findmegrefl, channel = [channel; labelmrefl]; end +if findmegrefr, channel = [channel; labelmrefr]; end +if findeog, channel = [channel; labeleog]; end +if findmz , channel = [channel; labelmz ]; end +if findml , channel = [channel; labelml ]; end +if findmr , channel = [channel; labelmr ]; end +if findmlc, channel = [channel; labelmlc]; end +if findmlf, channel = [channel; labelmlf]; end +if findmlo, channel = [channel; labelmlo]; end +if findmlp, channel = [channel; labelmlp]; end +if findmlt, channel = [channel; labelmlt]; end +if findmrc, channel = [channel; labelmrc]; end +if findmrf, channel = [channel; labelmrf]; end +if findmro, channel = [channel; labelmro]; end +if findmrp, channel = [channel; labelmrp]; end +if findmrt, channel = [channel; labelmrt]; end +if findmzc, channel = [channel; labelmzc]; end +if findmzf, channel = [channel; labelmzf]; end +if findmzo, channel = [channel; labelmzo]; end +if findmzp, channel = [channel; labelmzp]; end +if findlfp, channel = [channel; labellfp]; end +if findmua, channel = [channel; labelmua]; end +if findspike, channel = [channel; labelspike]; end + +% remove channel labels that have been excluded by the user +badindx = match_str(channel, badchannel); +channel(badindx) = []; + +% remove channel labels that are not present in the data +chanindx = match_str(channel, datachannel); + +channel = channel(chanindx); + +if findgui + indx = select_channel_list(datachannel, match_str(datachannel, channel), 'Select channels'); + channel = datachannel(indx); +end + +% remove channels that occur more than once, this sorts the channels alphabetically +channel = unique(channel); + +% undo the sorting, make the order identical to that of the data channels +[dataindx, indx] = match_str(datachannel, channel); +channel = channel(indx); diff --git a/external/fieldtrip/ft_clusterplot.m b/external/fieldtrip/ft_clusterplot.m index b84b9b2..0de374e 100644 --- a/external/fieldtrip/ft_clusterplot.m +++ b/external/fieldtrip/ft_clusterplot.m @@ -1,11 +1,366 @@ -function varargout = funname(varargin); +function ft_clusterplot(cfg, stat) -% this is a SPM wrapper around a FieldTrip function +% FT_CLUSTERPLOT plots a series of topoplots with found clusters highlighted. +% stat is 2D or 1D data from FT_TIMELOCKSTATISTICS or FT_FREQSTATISTICS with 'cluster' +% as cfg.correctmc. 2D: stat from timelockstatistics not averaged over +% time, or stat from freqstatistics averaged over frequency not averaged over +% time. 1D: averaged over time as well. +% +% use as: ft_clusterplot(cfg,stat) +% +% configuration options +% cfg.alpha = number, highest cluster p-value to be plotted +% max 0.3 (default = 0.05) +% cfg.highlightseries = 1x5 cell-array, highlight option series ('on','labels','numbers') +% default {'on','on','on','on','on'} for p < [0.01 0.05 0.1 0.2 0.3] +% cfg.highlightsymbolseries = 1x5 vector, highlight marker symbol series +% default ['*','x','+','o','.'] for p < [0.01 0.05 0.1 0.2 0.3] +% cfg.highlightsizeseries = 1x5 vector, highlight marker size series +% default [6 6 6 6 6] for p < [0.01 0.05 0.1 0.2 0.3] +% cfg.highlightcolorpos = color of highlight marker for positive clusters +% default = [0 0 0] +% cfg.highlightcolorneg = color of highlight marker for negative clusters +% default = [0 0 0] +% cfg.saveaspng = string, path where figure has to be saved to (default = 'no') +% When multiple figures figure gets extension with fignum +% +% It is also possible to specify other cfg options that apply to FT_TOPOPLOTER. +% You CANNOT specify cfg.xlim, any of the FT_TOPOPLOTER highlight +% options, cfg.comment and cfg.commentpos. +% +% See also: +% ft_topoplotER, ft_singleplotER +% +% Undocumented local option: +% cfg.inputfile = one can specifiy preanalysed saved data as input -% this part is variable -prefix = 'ft_'; -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +% Copyright (C) 2007, Ingrid Nieuwenhuis, F.C. Donders Centre +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_clusterplot.m 1303 2010-06-29 15:42:37Z timeng $ + +fieldtripdefs + +% default for inputfile +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end + +% load optional given inputfile as data +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + stat = loadvar(cfg.inputfile, 'data'); + end +end + +% check if given data is appropriate +if isfield(stat,'freq') && length(stat.freq) > 1 + error('stat contains multiple frequencies which is not allowed because it should be averaged over frequencies') +end + +% old config options +cfg = checkconfig(cfg, 'renamed', {'hlmarkerseries', 'highlightsymbolseries'}); +cfg = checkconfig(cfg, 'renamed', {'hlmarkersizeseries', 'highlightsizeseries'}); +cfg = checkconfig(cfg, 'renamed', {'hlcolorpos', 'highlightcolorpos'}); +cfg = checkconfig(cfg, 'renamed', {'hlcolorneg', 'highlightcolorneg'}); +cfg = checkconfig(cfg, 'deprecated', {'hllinewidthseries'}); + +% added several forbidden options +cfg = checkconfig(cfg, 'forbidden', {'highlight'}); +cfg = checkconfig(cfg, 'forbidden', {'highlightchannel'}); +cfg = checkconfig(cfg, 'forbidden', {'highlightsymbol'}); +cfg = checkconfig(cfg, 'forbidden', {'highlightcolor'}); +cfg = checkconfig(cfg, 'forbidden', {'highlightsize'}); +cfg = checkconfig(cfg, 'forbidden', {'highlightfontsize'}); +cfg = checkconfig(cfg, 'forbidden', {'xlim'}); +cfg = checkconfig(cfg, 'forbidden', {'comment'}); +cfg = checkconfig(cfg, 'forbidden', {'commentpos'}); + + +% set the defaults +if ~isfield(cfg,'alpha'), cfg.alpha = 0.05; end; +if ~isfield(cfg,'highlightseries'), cfg.highlightseries = {'on','on','on','on','on'}; end; +if ~isfield(cfg,'highlightsymbolseries'), cfg.highlightsymbolseries = ['*','x','+','o','.']; end; +if ~isfield(cfg,'highlightsizeseries'), cfg.highlightsizeseries = [6 6 6 6 6]; end; +if ~isfield(cfg,'hllinewidthseries'), cfg.hllinewidthseries = [1 1 1 1 1]; end; +if ~isfield(cfg,'highlightcolorpos'), cfg.highlightcolorpos = [0 0 0]; end; +if ~isfield(cfg,'highlightcolorneg'), cfg.highlightcolorneg = [0 0 0]; end; +if ~isfield(cfg,'zparam'), cfg.zparam = 'stat'; end; +if ~isfield(cfg,'saveaspng'), cfg.saveaspng = 'no'; end; + +% error if cfg.highlightseries is not a cell, for possible confusion with cfg-options +if ~iscell(cfg.highlightseries) + error('cfg.highlightseries should be a cell-array of strings') +end + +% set additional options for topoplotting +if isfield(cfg, 'marker'), cfgtopo.marker = cfg.marker ; end +if ~isfield(cfg,'marker'), cfgtopo.marker = 'off'; end +if isfield(cfg, 'markersymbol'), cfgtopo.markersymbol = cfg.markersymbol; end +if isfield(cfg, 'markercolor'), cfgtopo.markercolor = cfg.markercolor; end +if isfield(cfg, 'markersize'), cfgtopo.markersize = cfg.markersize; end +if isfield(cfg, 'markerfontsize'), cfgtopo.markerfontsize = cfg.markerfontsize; end +if isfield(cfg, 'style'), cfgtopo.style = cfg.style ; end +if isfield(cfg, 'gridscale'), cfgtopo.gridscale = cfg.gridscale; end +if isfield(cfg, 'interplimits'), cfgtopo.interplimits = cfg.interplimits; end +if isfield(cfg, 'interpolation'), cfgtopo.interpolation = cfg.interpolation; end +if isfield(cfg, 'contournum'), cfgtopo.contournum = cfg.contournum; end +if isfield(cfg, 'colorbar'), cfgtopo.colorbar = cfg.colorbar; end +if isfield(cfg, 'shading'), cfgtopo.shading = cfg.shading'; end +cfgtopo.zparam = cfg.zparam; + +% prepare the layout, this only has to be done once +cfgtopo.layout = ft_prepare_layout(cfg, stat); + +% detect 2D or 1D +is2D = isfield(stat,'time'); + +% add .time field to 1D data, topoplotER wants it +if ~is2D + stat.time = 0; %doesn't matter what it is, so just choose 0 +end; + +% find significant clusters +sigpos = []; +signeg = []; +haspos = isfield(stat,'posclusters'); +hasneg = isfield(stat,'negclusters'); + +if haspos == 0 && hasneg == 0 + fprintf('%s\n','no significant clusters in data; nothing to plot') +else + if haspos + for iPos = 1:length(stat.posclusters) + sigpos(iPos) = stat.posclusters(iPos).prob < cfg.alpha; + end + end + if hasneg + for iNeg = 1:length(stat.negclusters) + signeg(iNeg) = stat.negclusters(iNeg).prob < cfg.alpha; + end + end + sigpos = find(sigpos == 1); + signeg = find(signeg == 1); + Nsigpos = length(sigpos); + Nsigneg = length(signeg); + Nsigall = Nsigpos + Nsigneg; + + if Nsigall == 0 + error('no clusters present with a p-value lower than the specified alpha, nothing to plot') + end + + % make clusterslabel matrix per significant cluster + posCLM = squeeze(stat.posclusterslabelmat); + sigposCLM = zeros(size(posCLM)); + probpos = []; + for iPos = 1:length(sigpos) + sigposCLM(:,:,iPos) = (posCLM == sigpos(iPos)); + probpos(iPos) = stat.posclusters(iPos).prob; + hlsignpos(iPos) = prob2hlsign(probpos(iPos), cfg.highlightsymbolseries); + end + + negCLM = squeeze(stat.negclusterslabelmat); + signegCLM = zeros(size(negCLM)); + probneg = []; + for iNeg = 1:length(signeg) + signegCLM(:,:,iNeg) = (negCLM == signeg(iNeg)); + probneg(iNeg) = stat.negclusters(iNeg).prob; + hlsignneg(iNeg) = prob2hlsign(probneg(iNeg), cfg.highlightsymbolseries); + end + + fprintf('%s%i%s%g%s\n','There are ',Nsigall,' clusters smaller than alpha (',cfg.alpha,')') + + if is2D + % define time window per cluster + for iPos = 1:length(sigpos) + possum_perclus = sum(sigposCLM(:,:,iPos),1); %sum over Chans for each timepoint + ind_min = min(find(possum_perclus~=0)); + ind_max = max(find(possum_perclus~=0)); + time_perclus = [stat.time(ind_min) stat.time(ind_max)]; + fprintf('%s%s%s%s%s%s%s%s%s%s%s\n','Positive cluster: ',num2str(sigpos(iPos)),', pvalue: ',num2str(probpos(iPos)),' (',hlsignpos(iPos),')',', t = ',num2str(time_perclus(1)),' to ',num2str(time_perclus(2))) + end + for iNeg = 1:length(signeg) + negsum_perclus = sum(signegCLM(:,:,iNeg),1); + ind_min = min(find(negsum_perclus~=0)); + ind_max = max(find(negsum_perclus~=0)); + time_perclus = [stat.time(ind_min) stat.time(ind_max)]; + fprintf('%s%s%s%s%s%s%s%s%s%s%s\n','Negative cluster: ',num2str(signeg(iNeg)),', pvalue: ',num2str(probneg(iNeg)),' (',hlsignneg(iNeg),')',', t = ',num2str(time_perclus(1)),' to ',num2str(time_perclus(2))) + end + + % define timewindow containing all significant clusters + possum = sum(sigposCLM,3); %sum over Chans for timevector + possum = sum(possum,1); + negsum = sum(signegCLM,3); + negsum = sum(negsum,1); + allsum = possum + negsum; + + ind_timewin_min = min(find(allsum~=0)); + ind_timewin_max = max(find(allsum~=0)); + timewin = stat.time(ind_timewin_min:ind_timewin_max); + + else + for iPos = 1:length(sigpos) + fprintf('%s%s%s%s%s%s%s\n','Positive cluster: ',num2str(sigpos(iPos)),', pvalue: ',num2str(probpos(iPos)),' (',hlsignpos(iPos),')') + end + for iNeg = 1:length(signeg) + fprintf('%s%s%s%s%s%s%s\n','Negative cluster: ',num2str(signeg(iNeg)),', pvalue: ',num2str(probneg(iNeg)),' (',hlsignneg(iNeg),')') + end + end + + % setup highlight options for all clusters and make comment for 1D data + compos = []; + comneg = []; + for iPos = 1:length(sigpos) + if stat.posclusters(sigpos(iPos)).prob < 0.01 + cfgtopo.highlight{iPos} = cfg.highlightseries{1}; + cfgtopo.highlightsymbol{iPos} = cfg.highlightsymbolseries(1); + cfgtopo.highlightsize{iPos} = cfg.highlightsizeseries(1); + elseif stat.posclusters(sigpos(iPos)).prob < 0.05 + cfgtopo.highlight{iPos} = cfg.highlightseries{2}; + cfgtopo.highlightsymbol{iPos} = cfg.highlightsymbolseries(2); + cfgtopo.highlightsize{iPos} = cfg.highlightsizeseries(2); + elseif stat.posclusters(sigpos(iPos)).prob < 0.1 + cfgtopo.highlight{iPos} = cfg.highlightseries{3}; + cfgtopo.highlightsymbol{iPos} = cfg.highlightsymbolseries(3); + cfgtopo.highlightsize{iPos} = cfg.highlightsizeseries(3); + elseif stat.posclusters(sigpos(iPos)).prob < 0.2 + cfgtopo.highlight{iPos} = cfg.highlightseries{4}; + cfgtopo.highlightsymbol{iPos} = cfg.highlightsymbolseries(4); + cfgtopo.highlightsize{iPos} = cfg.highlightsizeseries(4); + elseif stat.posclusters(sigpos(iPos)).prob < 0.3 + cfgtopo.highlight{iPos} = cfg.highlightseries{5}; + cfgtopo.highlightsymbol{iPos} = cfg.highlightsymbolseries(5); + cfgtopo.highlightsize{iPos} = cfg.highlightsizeseries(5); + end + cfgtopo.highlightcolor{iPos} = cfg.highlightcolorpos; + compos = strcat(compos,cfgtopo.highlightsymbol{iPos}, 'p=',num2str(probpos(iPos)),' '); % make comment, only used for 1D data + end + + for iNeg = 1:length(signeg) + if stat.negclusters(signeg(iNeg)).prob < 0.01 + cfgtopo.highlight{length(sigpos)+iNeg} = cfg.highlightseries{1}; + cfgtopo.highlightsymbol{length(sigpos)+iNeg} = cfg.highlightsymbolseries(1); + cfgtopo.highlightsize{length(sigpos)+iNeg} = cfg.highlightsizeseries(1); + elseif stat.negclusters(signeg(iNeg)).prob < 0.05 + cfgtopo.highlight{length(sigpos)+iNeg} = cfg.highlightseries{2}; + cfgtopo.highlightsymbol{length(sigpos)+iNeg} = cfg.highlightsymbolseries(2); + cfgtopo.highlightsize{length(sigpos)+iNeg} = cfg.highlightsizeseries(2); + elseif stat.negclusters(signeg(iNeg)).prob < 0.1 + cfgtopo.highlight{length(sigpos)+iNeg} = cfg.highlightseries{3}; + cfgtopo.highlightsymbol{length(sigpos)+iNeg} = cfg.highlightsymbolseries(3); + cfgtopo.highlightsize{length(sigpos)+iNeg} = cfg.highlightsizeseries(3); + elseif stat.negclusters(signeg(iNeg)).prob < 0.2 + cfgtopo.highlight{length(sigpos)+iNeg} = cfg.highlightseries{4}; + cfgtopo.highlightsymbol{length(sigpos)+iNeg} = cfg.highlightsymbolseries(4); + cfgtopo.highlightsize{length(sigpos)+iNeg} = cfg.highlightsizeseries(4); + elseif stat.negclusters(signeg(iNeg)).prob < 0.3 + cfgtopo.highlight{length(sigpos)+iNeg} = cfg.highlightseries{5}; + cfgtopo.highlightsymbol{length(sigpos)+iNeg} = cfg.highlightsymbolseries(5); + cfgtopo.highlightsize{length(sigpos)+iNeg} = cfg.highlightsizeseries(5); + end + cfgtopo.highlightcolor{length(sigpos)+iNeg} = cfg.highlightcolorneg; + comneg = strcat(comneg,cfgtopo.highlightsymbol{length(sigpos)+iNeg}, 'p=',num2str(probneg(iNeg)),' '); % make comment, only used for 1D data + end + + if is2D + Npl = length(timewin); + else + Npl = 1; + end + Nfig = ceil(Npl/15); + + % put channel indexes in list + if is2D + for iPl = 1:Npl + for iPos = 1:length(sigpos) + list{iPl}{iPos} = find(sigposCLM(:,ind_timewin_min+iPl-1,iPos) == 1); + end + for iNeg = 1:length(signeg) + list{iPl}{length(sigpos)+iNeg} = find(signegCLM(:,ind_timewin_min+iPl-1,iNeg) == 1); + end + end + else + for iPl = 1:Npl + for iPos = 1:length(sigpos) + list{iPl}{iPos} = find(sigposCLM(:,iPos) == 1); + end + for iNeg = 1:length(signeg) + list{iPl}{length(sigpos)+iNeg} = find(signegCLM(:,iNeg) == 1); + end + end + end + + + % make plots + for iPl = 1:Nfig + figure; + if is2D + if iPl < Nfig + for iT = 1:15 + PlN = (iPl-1)*15 + iT; %plotnumber + cfgtopo.xlim = [stat.time(ind_timewin_min+PlN-1) stat.time(ind_timewin_min+PlN-1)]; + cfgtopo.highlightchannel = list{PlN}; + cfgtopo.comment = strcat('time: ',num2str(stat.time(ind_timewin_min+PlN-1)), ' s'); + cfgtopo.commentpos = 'title'; + subplot(3,5,iT); + ft_topoplotER(cfgtopo, stat); + end + elseif iPl == Nfig + for iT = 1:Npl-(15*(Nfig-1)) + PlN = (iPl-1)*15 + iT; %plotnumber + cfgtopo.xlim = [stat.time(ind_timewin_min+PlN-1) stat.time(ind_timewin_min+PlN-1)]; + cfgtopo.highlightchannel = list{PlN}; + cfgtopo.comment = strcat('time: ',num2str(stat.time(ind_timewin_min+PlN-1)), ' s'); + cfgtopo.commentpos = 'title'; + subplot(3,5,iT); + ft_topoplotER(cfgtopo, stat); + end + end + else + cfgtopo.highlightchannel = list{1}; + cfgtopo.xparam = 'time'; + cfgtopo.yparam = ''; + cfgtopo.comment = strcat(compos,comneg); + cfgtopo.commentpos = 'title'; + ft_topoplotER(cfgtopo, stat); + end + % save figure + if isequal(cfg.saveaspng,'no'); + else + filename = strcat(cfg.saveaspng, '_fig', num2str(iPl)); + print(gcf,'-dpng',filename); + end + end +end + +%% subfunctions %% +function sign = prob2hlsign(prob, hlsign) +if prob < 0.01 + sign = hlsign(1); +elseif prob < 0.05 + sign = hlsign(2); +elseif prob < 0.1 + sign = hlsign(3); +elseif prob < 0.2 + sign = hlsign(4); +elseif prob < 0.3 + sign = hlsign(5); +end diff --git a/external/fieldtrip/ft_combineplanar.m b/external/fieldtrip/ft_combineplanar.m index b84b9b2..7560dd7 100644 --- a/external/fieldtrip/ft_combineplanar.m +++ b/external/fieldtrip/ft_combineplanar.m @@ -1,11 +1,278 @@ -function varargout = funname(varargin); +function [data] = ft_combineplanar(cfg, data) -% this is a SPM wrapper around a FieldTrip function +% FT_COMBINEPLANAR computes the planar gradient magnitude over both directions +% combining the two gradients at each sensor to a single positive-valued number. +% This can be done for averaged ERFs or TFRs (i.e. powerspectra). +% +% Use as +% [data] = ft_combineplanar(cfg, data) +% where data contains an averaged planar gradient (either ERF or TFR). +% +% In the case of ERFs, the configuration can contain +% cfg.blc = 'yes' or 'no' (default) +% cfg.blcwindow = [begin end] +% +% After combining the planar data, the planar gradiometer definition does not +% match the data any more and therefore it is removed from the data. With +% cfg.combinegrad = 'yes' +% the function will try to reconstruct the axial gradiometer definition. +% +% See also FT_MEGPLANAR -% this part is variable -prefix = 'ft_'; +% Undocumented local options: +% cfg.baseline +% cfg.combinemethod +% cfg.foilim +% cfg.trials +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +% Copyright (C) 2004, Ole Jensen, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_combineplanar.m 1261 2010-06-22 15:09:23Z roboos $ + +fieldtripdefs + +% set the defaults +if ~isfield(cfg, 'blc'), cfg.blc = 'no'; end +if ~isfield(cfg, 'foilim'), cfg.foilim = [-inf inf]; end +if ~isfield(cfg, 'blcwindow'), cfg.blcwindow = [-inf inf]; end +if ~isfield(cfg, 'combinemethod'), cfg.combinemethod = 'sum'; end +if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end +if ~isfield(cfg, 'feedback'), cfg.feedback = 'none'; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + end +end + +% check if the input data is valid for this function +data = checkdata(data, 'datatype', {'raw', 'freq', 'timelock'}, 'feedback', 'yes', 'senstype', {'ctf151_planar', 'ctf275_planar', 'neuromag122', 'neuromag306', 'bti248_planar', 'bti148_planar', 'itab153_planar'}); + +cfg = checkconfig(cfg, 'trackconfig', 'on'); +cfg = checkconfig(cfg, 'forbidden', {'combinegrad'}); +cfg = checkconfig(cfg, 'deprecated', {'baseline'}); + +if isfield(cfg, 'baseline') + warning('only supporting cfg.baseline for backwards compatibility, please update your cfg'); + cfg.blc = 'yes'; + cfg.blcwindow = cfg.baseline; +end + +israw = datatype(data, 'raw'); +isfreq = datatype(data, 'freq'); +istimelock = datatype(data, 'timelock'); +try, dimord = data.dimord; end + +% select trials of interest +if ~strcmp(cfg.trials, 'all') + error('trial selection has not been implemented yet') % first fix checkdata (see above) +end + +% find the combination of horizontal and vertical channels that should be combined +planar = planarchannelset(data); +sel_dH = match_str(data.label, planar(:,1)); % indices of the horizontal channels +sel_dV = match_str(data.label, planar(:,2)); % indices of the vertical channels +lab_dH = data.label(sel_dH); +lab_dV = data.label(sel_dV); + +if length(sel_dH)~=length(sel_dV) + error('not all planar channel combinations are complete') +end + +% find the other channels that are present in the data +sel_other = setdiff(1:length(data.label), [sel_dH(:)' sel_dV(:)']); +lab_other = data.label(sel_other); + +% define the channel names after combining the planar combinations +% they should be sorted according to the order of the planar channels in the data +[dum, sel_planar] = match_str(data.label, planar(:,1)); +lab_comb = planar(sel_planar,3); + +% perform baseline correction +if strcmp(cfg.blc, 'yes') + if ~(istimelock || israw) + error('baseline correction is only supported for timelocked or raw input data') + end + if ischar(cfg.blcwindow) && strcmp(cfg.blcwindow, 'all') + cfg.blcwindow = [-inf inf]; + end + % find the timebins corresponding to the baseline interval + tbeg = nearest(data.time, cfg.blcwindow(1)); + tend = nearest(data.time, cfg.blcwindow(2)); + cfg.blcwindow(1) = data.time(tbeg); + cfg.blcwindow(2) = data.time(tend); + data.avg = blc(data.avg, tbeg, tend); +end + +if isfreq + + switch cfg.combinemethod + case 'sum' + if isfield(data, 'powspctrm'), + % compute the power of each planar channel, by summing the horizontal and vertical gradients + dimtok = tokenize(dimord,'_'); + catdim = strmatch('chan',dimtok); + if catdim==1, + combined = data.powspctrm(sel_dH,:,:,:) + data.powspctrm(sel_dV,:,:,:); + other = data.powspctrm(sel_other,:,:,:); + elseif catdim==2, + combined = data.powspctrm(:,sel_dH,:,:,:) + data.powspctrm(:,sel_dV,:,:,:); + other = data.powspctrm(:,sel_other,:,:,:); + else + error('unsupported dimension order of frequency data'); + end + data.powspctrm = cat(catdim, combined, other); + data.label = cat(1, lab_comb(:), lab_other(:)); + else + error('cfg.combinemethod = ''%s'' only works for frequency data with powspctrm', cfg.combinemethod); + end + case 'svd' + if isfield(data, 'fourierspctrm'), + fbin = nearest(data.freq, cfg.foilim(1)):nearest(data.freq, cfg.foilim(2)); + Nrpt = size(data.fourierspctrm,1); + Nsgn = length(sel_dH); + Nfrq = length(fbin); + Ntim = size(data.fourierspctrm,4); + %fourier= complex(zeros(Nrpt,Nsgn,Nfrq,Ntim),zeros(Nrpt,Nsgn,Nfrq,Ntim)); + fourier= zeros(Nrpt,Nsgn,Nfrq,Ntim)+nan; + progress('init', cfg.feedback, 'computing the svd'); + for j = 1:Nsgn + progress(j/Nsgn, 'computing the svd of signal %d/%d\n', j, Nsgn); + for k = 1:Nfrq + dum = reshape(data.fourierspctrm(:,[sel_dH(j) sel_dV(j)],fbin(k),:), [Nrpt 2 Ntim]); + dum = permute(dum, [2 3 1]); + dum = reshape(dum, [2 Ntim*Nrpt]); + timbin = ~isnan(dum(1,:)); + dum2 = svdfft(dum(:,timbin),1,data.cumtapcnt); + dum(1,timbin) = dum2; + dum = reshape(dum(1,:),[Ntim Nrpt]); + fourier(:,j,k,:) = transpose(dum); + + %for m = 1:Ntim + % dum = data.fourierspctrm(:,[sel_dH(j) sel_dV(j)],fbin(k),m); + % timbin = find(~isnan(dum(:,1))); + % [fourier(timbin,j,k,m)] = svdfft(transpose(dum(timbin,:)),1); + %end + end + end + progress('close'); + other = data.fourierspctrm(:,sel_other,fbin,:); + data = rmfield(data,'fourierspctrm'); + data.fourierspctrm = cat(2, fourier, other); + data.label = cat(1, lab_comb(:), lab_other(:)); + data.freq = data.freq(fbin); + else + error('cfg.combinemethod = ''%s'' only works for frequency data with fourierspctrm', cfg.combinemethod); + end + otherwise + error('cfg.combinemethod = ''%s'' is not supported for frequency data', cfg.combinemethod); + end + +elseif (israw || istimelock) + if istimelock, + % convert timelock to raw + data = checkdata(data, 'datatype', 'raw', 'feedback', 'yes'); + end + + switch cfg.combinemethod + case 'sum' + Nrpt = length(data.trial); + for k = 1:Nrpt + combined = sqrt(data.trial{k}(sel_dH,:).^2 + data.trial{k}(sel_dV,:).^2); + other = data.trial{k}(sel_other,:); + data.trial{k} = [combined; other]; + end + data.label = cat(1, lab_comb(:), lab_other(:)); + case 'svd' + Nrpt = length(data.trial); + Nsgn = length(sel_dH); + Nsmp = cellfun('size', data.trial, 2); + Csmp = cumsum([0 Nsmp]); + % do a 'fixed orientation' across all trials approach here + % this is different from the frequency case FIXME + tmpdat = zeros(2, sum(Nsmp)); + for k = 1:Nsgn + for m = 1:Nrpt + tmpdat(:, (Csmp(m)+1):Csmp(m+1)) = data.trial{m}([sel_dH(k) sel_dV(k)],:); + end + tmpdat2 = abs(svdfft(tmpdat,1)); + tmpdat2 = mat2cell(tmpdat2, 1, Nsmp); + for m = 1:Nrpt + if k==1, trial{m} = zeros(Nsgn, Nsmp(m)); end + trial{m}(k,:) = tmpdat2{m}; + end + end + for m = 1:Nrpt + other = data.trial{m}(sel_other,:); + trial{m} = [trial{m}; other]; + end + data.trial = trial; + data.label = cat(1, lab_comb(:), lab_other(:)); + otherwise + error('cfg.combinemethod = ''%s'' is not supported for timelocked or raw data', cfg.combinemethod); + end + + if istimelock, + % convert raw to timelock + data = checkdata(data, 'datatype', 'timelock', 'feedback', 'yes'); + end + +else + error('unsupported input data'); +end % which datatype + +% remove the fields for which the planar gradient could not be combined +try, data = rmfield(data, 'crsspctrm'); end +try, data = rmfield(data, 'labelcmb'); end + +% accessing this field here is needed for the configuration tracking +% by accessing it once, it will not be removed from the output cfg +cfg.outputfile; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% store the configuration of this function call, including that of the previous function call +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_combineplanar.m 1261 2010-06-22 15:09:23Z roboos $'; +% remember the configuration details of the input data +try, cfg.previous = data.cfg; end + +% remember the exact configuration details in the output +data.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', data); % use the variable name "data" in the output file +end \ No newline at end of file diff --git a/external/fieldtrip/ft_componentanalysis.m b/external/fieldtrip/ft_componentanalysis.m index b84b9b2..0f805d3 100644 --- a/external/fieldtrip/ft_componentanalysis.m +++ b/external/fieldtrip/ft_componentanalysis.m @@ -1,11 +1,423 @@ -function varargout = funname(varargin); +function [comp] = ft_componentanalysis(cfg, data) -% this is a SPM wrapper around a FieldTrip function +% FT_COMPONENTANALYSIS principal or independent component analysis +% computes the topography and timecourses of the ICA/PCA components +% in the EEG/MEG data. +% +% Use as +% [comp] =ft_componentanalysis(cfg, data) +% +% where the data comes from FT_PREPROCESING or FT_TIMELOCKANALYSIS and the +% configuration structure can contain +% cfg.method = 'runica', 'fastica', 'binica', 'pca', 'jader', 'varimax', 'dss', 'cca' (default = 'runica') +% cfg.channel = cell-array with channel selection (default = 'all'), see FT_CHANNELSELECTION for details +% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') +% cfg.numcomponent = 'all' or number (default = 'all') +% cfg.blc = 'no' or 'yes' (default = 'yes') +% cfg.runica = substructure with additional low-level options for this method +% cfg.binica = substructure with additional low-level options for this method +% cfg.dss = substructure with additional low-level options for this method +% cfg.fastica = substructure with additional low-level options for this method +% +% forbidden configuration option: cfg.detrend +% +% Instead of specifying a component analysis method, you can also specify +% a previously computed mixing matrix, which will be used to estimate the +% component timecourses in this data. This requires +% cfg.topo = NxN matrix with a component topography in each column +% cfg.topolabel = Nx1 cell-array with the channel labels +% +% See also FASTICA, RUNICA, SVD, JADER, VARIMAX, DSS, CCA +% +% Undocumented local options: +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk +% +% NOTE parafac is also implemented, but that does not fit into the +% structure of 2D decompositions very well. Probably I should implement it +% in a separate function for N-D decompositions -% this part is variable -prefix = 'ft_'; +% Copyright (C) 2003-2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_componentanalysis.m 1260 2010-06-22 09:25:42Z timeng $ -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +fieldtripdefs + +% set a timer to determine how long this function takes +tic; + +% check if the input cfg is valid for this function +cfg = checkconfig(cfg, 'trackconfig', 'on'); +cfg = checkconfig(cfg, 'forbidden', {'detrend'}); + +% set the defaults +if ~isfield(cfg, 'method'), cfg.method = 'runica'; end +if ~isfield(cfg, 'blc'), cfg.blc = 'yes'; end +if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end +if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end +if ~isfield(cfg, 'numcomponent'), cfg.numcomponent = 'all'; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +% load optional given inputfile as data +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + end +end + +% check if the input data is valid for this function +data = checkdata(data, 'datatype', 'raw', 'feedback', 'yes'); + +% select channels, has to be done prior to handling of previous (un)mixing matrix +cfg.channel = ft_channelselection(cfg.channel, data.label); + +if isfield(cfg, 'topo') && isfield(cfg, 'topolabel') + % use the previously determined unmixing matrix on this dataset + + % test whether all required channels are present in the data + [datsel, toposel] = match_str(cfg.channel, cfg.topolabel); + if length(toposel)~=length(cfg.topolabel) + error('not all channels that are required for the unmixing are present in the data'); + end + + % ensure that all data channels not used in the unmixing should be removed from the channel selection + tmpchan = match_str(cfg.channel, cfg.topolabel); + cfg.channel = cfg.channel(tmpchan); + + % remove all cfg settings that do not apply + tmpcfg = []; + tmpcfg.blc = cfg.blc; + tmpcfg.trials = cfg.trials; + tmpcfg.topo = cfg.topo; % the MxN mixing matrix (M channels, N components) + tmpcfg.topolabel = cfg.topolabel; % the Mx1 labels of the data that was used in determining the mixing matrix + tmpcfg.channel = cfg.channel; % the Mx1 labels of the data that is presented now to this function + tmpcfg.numcomponent = 'all'; + tmpcfg.method = 'predetermined mixing matrix'; + tmpcfg.outputfile = cfg.outputfile + cfg = tmpcfg; +end + +% additional options, see FASTICA for details +if ~isfield(cfg, 'fastica'), cfg.fastica = []; end; + +% additional options, see RUNICA for details +if ~isfield(cfg, 'runica'), cfg.runica = []; end +if ~isfield(cfg.runica, 'lrate'), cfg.runica.lrate = 0.001; end + +% additional options, see BINICA for details +if ~isfield(cfg, 'binica'), cfg.binica = []; end +if ~isfield(cfg.binica, 'lrate'), cfg.binica.lrate = 0.001; end + +% additional options, see DSS for details +if ~isfield(cfg, 'dss'), cfg.dss = []; end +if ~isfield(cfg.dss, 'denf'), cfg.dss.denf = []; end +if ~isfield(cfg.dss.denf, 'function'), cfg.dss.denf.function = 'denoise_fica_tanh'; end +if ~isfield(cfg.dss.denf, 'params'), cfg.dss.denf.params = []; end + +% check whether the required low-level toolboxes are installed +switch cfg.method + case 'fastica' + hastoolbox('fastica', 1); % see http://www.cis.hut.fi/projects/ica/fastica + case {'runica', 'jader', 'varimax', 'binica'} + hastoolbox('eeglab', 1); % see http://www.sccn.ucsd.edu/eeglab + case 'parafac' + hastoolbox('nway', 1); % see http://www.models.kvl.dk/source/nwaytoolbox + case 'dss' + hastoolbox('dss', 1); % see http://www.cis.hut.fi/projects/dss +end % cfg.method + +% default is to compute just as many components as there are channels in the data +if strcmp(cfg.numcomponent, 'all') + cfg.numcomponent = length(data.label); +end + +% select trials of interest +if ~strcmp(cfg.trials, 'all') + fprintf('selecting %d trials\n', length(cfg.trials)); + data = selectdata(data, 'rpt', cfg.trials); +end +Ntrials = length(data.trial); + +% select channels of interest +chansel = match_str(data.label, cfg.channel); +fprintf('selecting %d channels\n', length(chansel)); +for trial=1:Ntrials + data.trial{trial} = data.trial{trial}(chansel,:); +end +data.label = data.label(chansel); +Nchans = length(chansel); + +% determine the size of each trial, they can be variable length +Nsamples = zeros(1,Ntrials); +for trial=1:Ntrials + Nsamples(trial) = size(data.trial{trial},2); +end + +if strcmp(cfg.blc, 'yes') + % optionally perform baseline correction on each trial + fprintf('baseline correcting data \n'); + for trial=1:Ntrials + data.trial{trial} = ft_preproc_baselinecorrect(data.trial{trial}); + end +end + +if strcmp(cfg.method, 'predetermined mixing matrix') + % the single trial data does not have to be concatenated +elseif strcmp(cfg.method, 'parafac') + % concatenate all the data into a 3D matrix + fprintf('concatenating data'); + Nsamples = Nsamples(1); + dat = zeros(Ntrials, Nchans, Nsamples); + % all trials should have an equal number of samples + % and it is assumed that the time axes of all trials are aligned + for trial=1:Ntrials + fprintf('.'); + dat(trial,:,:) = data.trial{trial}; + end + fprintf('\n'); + fprintf('concatenated data matrix size %dx%dx%d\n', size(dat,1), size(dat,2), size(dat,3)); +else + % concatenate all the data into a 2D matrix + fprintf('concatenating data'); + + dat = zeros(Nchans, sum(Nsamples)); + for trial=1:Ntrials + fprintf('.'); + begsample = sum(Nsamples(1:(trial-1))) + 1; + endsample = sum(Nsamples(1:trial)); + dat(:,begsample:endsample) = data.trial{trial}; + end + fprintf('\n'); + fprintf('concatenated data matrix size %dx%d\n', size(dat,1), size(dat,2)); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% perform the component analysis +fprintf('starting decomposition using %s\n', cfg.method); +switch cfg.method + + case 'fastica' + + try + % construct key-value pairs for the optional arguments + optarg = cfg2keyval(cfg.fastica); + [A, W] = fastica(dat, optarg{:}); + weights = W; + sphere = eye(size(W,2)); + catch ME + % give a hopefully instructive error message + fprintf(['If you get an out-of-memory in fastica here, and you use fastica 2.5, change fastica.m, line 482: \n' ... + 'from\n' ... + ' if ~isempty(W) %% ORIGINAL VERSION\n' ... + 'to\n' ... + ' if ~isempty(W) && nargout ~= 2 %% if nargout == 2, we return [A, W], and NOT ICASIG\n']); + % forward original error + rethrow(ME); + end + + case 'runica' + % construct key-value pairs for the optional arguments + optarg = cfg2keyval(cfg.runica); + [weights, sphere] = runica(dat, optarg{:}); + + case 'binica' + % construct key-value pairs for the optional arguments + optarg = cfg2keyval(cfg.binica); + [weights, sphere] = binica(dat, optarg{:}); + + case 'jader' + weights = jader(dat); + sphere = eye(size(weights, 2)); + + case 'varimax' + weights = varimax(dat); + sphere = eye(size(weights, 2)); + + case 'cca' + [y, w] = ccabss(dat); + weights = w'; + sphere = eye(size(weights, 2)); + + case 'pca' + % compute data cross-covariance matrix + C = (dat*dat')./(size(dat,2)-1); + % eigenvalue decomposition (EVD) + [E,D] = eig(C); + % sort eigenvectors in descending order of eigenvalues + d = cat(2,[1:1:Nchans]',diag(D)); + d = sortrows(d,[-2]); + % return the desired number of principal components + weights = E(:,d(1:cfg.numcomponent,1))'; + sphere = eye(size(weights,2)); + clear C D E d + + case 'svd' + if cfg.numcomponent. +% +% $Id: ft_componentbrowser.m 1430 2010-07-20 07:41:41Z roboos $ + +fieldtripdefs + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Prepare the data +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% check that the data comes from componentanalysis +comp = checkdata(comp, 'datatype', 'comp'); + +% set the defaults: +if ~isfield(cfg, 'comp'), cfg.comp = 1:10; end +if ~isfield(cfg, 'trial'), cfg.trial = 1; end + +if numel(cfg.trial) > 1, + warning('componentbrowser:cfg_onetrial', 'only one trial can be plotted at the time'); + cfg.trial = cfg.trial(1); +end + +% Read or create the layout that will be used for plotting: +[cfg.layout] = ft_prepare_layout(cfg, comp); + +% Identify the channels to plot +[labels, cfg.chanidx.lay, cfg.chanidx.comp] = intersect(cfg.layout.label, comp.topolabel); % in case channels are missing +if isempty(cfg.chanidx.lay) + error('componentbrowser:labelmismatch', 'The channel labels in the data do not match the labels of the layout'); +end + +% fixed variables +cfg.shift = 1.2; % distance between topoplots + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Create figure and assign userdata +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% create figure and axes +cfg.h = figure('uni','pix', 'name', 'componentbrowser', 'vis', 'off', 'numbertitle', 'off'); +cfg.axis = axes; +hold on + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Buttons and Callbacks +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% scroll components +uicontrol(cfg.h,'uni','pix','pos',[105 5 25 18],'str','-',... + 'call',{@plottopography, comp}); + +cfg.ncomp = uicontrol(cfg.h,'sty','text','uni','pix','pos',[130 5 150 18],... + 'str',['comp n.' num2str(cfg.comp(1)) '-' num2str(cfg.comp(end))]); + +uicontrol(cfg.h,'uni','pix','pos',[280 5 25 18],'str','+',... + 'call',{@plottopography, comp}); + +% scroll trials +uicontrol(cfg.h,'uni','pix','pos',[330 5 25 18],'str','<<',... + 'call',{@plotactivation, comp}); + +uicontrol(cfg.h,'uni','pix','pos',[355 5 25 18],'str', '<',... + 'call',{@plotactivation, comp}); + +cfg.ntrl = uicontrol(cfg.h,'sty','text','uni','pix','pos',[380 5 70 18],... + 'str',['trial n.' num2str(cfg.trial)]); + +uicontrol(cfg.h,'uni','pix','pos',[450 5 25 18],'str', '>',... + 'call',{@plotactivation, comp}); + +uicontrol(cfg.h,'uni','pix','pos',[475 5 25 18],'str','>>',... + 'call',{@plotactivation, comp}); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% First callback and final adjustments +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% first call of the two plotting functions +plottopography([], cfg, comp) +plotactivation([], cfg, comp) + +% final adjustments +set(cfg.h, 'vis', 'on') +axis equal +axis off +hold off + +% the (optional) output is the handle +if nargout == 1; + varargout{1} = cfg.h; +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% PLOTTOPOGRAPHY +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function plottopography(h, cfg, comp) +% now plottopography is not associated with a callback, but it might in +% the future + +if isempty(h) % when called in isolation + set(cfg.h, 'user', cfg) +else + cfg = get(get(h, 'par'), 'user'); + + % which button has been pressed + if intersect(h, findobj(cfg.h, 'str', '+')) + + cfg.comp = cfg.comp + numel(cfg.comp); + if cfg.comp(end) > size(comp.label,1) + cfg.comp = cfg.comp - (cfg.comp(end) - size(comp.label,1)); + end + + elseif intersect(h, findobj(cfg.h, 'str', '-')) + + cfg.comp = cfg.comp - numel(cfg.comp); + if cfg.comp(1) < 1 + cfg.comp = cfg.comp - cfg.comp(1) + 1; + end + + end +end + +set(cfg.ncomp, 'str', ['comp n.' num2str(cfg.comp(1)) '-' num2str(cfg.comp(end))]) +drawnow +delete(findobj(cfg.h, 'tag', 'comptopo')) + +cnt = 0; +for k = cfg.comp + cnt = cnt + 1; + + % write number of the component on the left + h_text(cnt) = ft_plot_text(-2.5, -cnt*cfg.shift, ['n. ' num2str(cfg.comp(cnt))]); + + % plot only topography (no layout) + ft_plot_topo(cfg.layout.pos(cfg.chanidx.lay,1), cfg.layout.pos(cfg.chanidx.lay,2), ... + comp.topo(cfg.chanidx.comp, k)./max(abs(comp.topo(cfg.chanidx.comp, k))), ... % for proper scaling + 'hpos', -1, 'vpos', -cnt*cfg.shift, 'mask', cfg.layout.mask); + % plot layout + ft_plot_lay(cfg.layout, 'hpos', -1, 'vpos', -cnt*cfg.shift, 'point', false, 'box', false, 'label', false, 'mask', true, 'verbose', false); +end + +h_topo = findobj(cfg.h, 'type', 'surface'); + +set(h_text, 'tag', 'comptopo') +set(h_topo, 'tag', 'comptopo') + +% in the colorbar, green should be zero +set(cfg.axis, 'clim', [-1 1]) + +plotactivation([], cfg, comp) + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% PLOTACTIVATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function plotactivation(h, cfg, comp) +% plotactivation can be called in isolation or by buttondownfcn +% cfg is stored in 'user' of the main figure + +if isempty(h) % when called in isolation + set(cfg.h, 'user', cfg) +else + cfg = get(get(h, 'par'), 'user'); + + % which button has been pressed + if intersect(h, findobj(cfg.h, 'str', '>>')) + + cfg.trial = cfg.trial + 10; + if cfg.trial > size(comp.trial,2) + cfg.trial = size(comp.trial,2); + end + + elseif intersect(h, findobj(cfg.h, 'str', '>')) + + cfg.trial = cfg.trial + 1; + if cfg.trial > size(comp.trial,2) + cfg.trial = size(comp.trial,2); + end + + elseif intersect(h, findobj(cfg.h, 'str', '<')) + + cfg.trial = cfg.trial - 1; + if cfg.trial < 1 + cfg.trial = 1; + end + + elseif intersect(h, findobj(cfg.h, 'str', '<<')) + + cfg.trial = cfg.trial - 10; + if cfg.trial < 1 + cfg.trial = 1; + end + + end +end + +set(cfg.ntrl,'str',['trial n. ' num2str(cfg.trial)]) +drawnow +delete(findobj(cfg.h,'tag', 'activations')); + +hold on +cnt = 0; +for k = cfg.comp + cnt = cnt + 1; + + % plot the activations + h_act(cnt) = ft_plot_vector(comp.trial{cfg.trial}(k,:), 'hpos', 6 , 'vpos', -cnt*cfg.shift, 'width', 12, 'height', 1, 'box', true); +end + +h_inv = plot(6+12+1, -cnt*cfg.shift, '.'); % +set(h_inv, 'vis', 'off') + +set(h_act, 'tag', 'activations') +set(cfg.h, 'user', cfg) +hold off diff --git a/external/fieldtrip/ft_connectivityanalysis.m b/external/fieldtrip/ft_connectivityanalysis.m new file mode 100644 index 0000000..2f47b19 --- /dev/null +++ b/external/fieldtrip/ft_connectivityanalysis.m @@ -0,0 +1,965 @@ +function [stat] = ft_connectivityanalysis(cfg, data) + +% FT_CONNECTIVITYANALYIS computes various measures of connectivity +% between MEG/EEG channels or between source-level signals. +% +% Use as +% stat = ft_connectivityanalysis(cfg, data) +% stat = ft_connectivityanalysis(cfg, timelock) +% stat = ft_connectivityanalysis(cfg, freq) +% stat = ft_connectivityanalysis(cfg, source) +% where the first input argument is a configuration structure (see +% below) and the second argument is the output of FT_PREPROCESSING, +% FT_TIMELOCKANLAYSIS or FT_FREQANALYSIS or FT_MVARANALYSIS or +% FT_SOURCEANALYSIS, depending on the connectivity metric that you +% want to compute. +% +% The configuration structure has to contain +% cfg.method = 'coh', coherence, support for freq, freqmvar and +% source data. For partial coherence also +% specify cfg.partchannel +% 'csd', cross-spectral density matrix, can also +% calculate partial csds - +% if cfg.partchannel is specified +% 'plv', phase-locking value, support for freq and freqmvar data +% 'corr', correlation coefficient (Pearson) +% 'xcorr', cross correlation function +% 'powcorr', power correlation, support for freq and source data +% 'amplcorr', amplitude correlation, support for freq and source data +% 'dtf', directed transfer function, support for freq and freqmvar data +% 'pdc', partial directed coherence, support for freq and freqmvar data +% 'granger', granger causality, support for freq and freqmvar data +% 'psi', phaseslope index, support for freq and freqmvar data +% 'pcd', pairwise circular difference +% 'di', directionality index + +% Copyright (C) 2009, Robert Oostenveld, Jan-Mathijs Schoffelen, Andre Bastos +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_connectivityanalysis.m 1398 2010-07-12 14:26:24Z jansch $ + +fieldtripdefs + +% check if the input cfg is valid for this function +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +% set the defaults + +%FIXME do method specific calls to checkconfig +if ~isfield(cfg, 'feedback'), cfg.feedback = 'none'; end +if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end +if ~isfield(cfg, 'channelcmb'), cfg.channelcmb = {'all' 'all'}; end +if ~isfield(cfg, 'refindx'), cfg.refindx = []; end +if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end +if ~isfield(cfg, 'complex'), cfg.complex = 'abs'; end +if ~isfield(cfg, 'jackknife'), cfg.jackknife = 'no'; end +if ~isfield(cfg, 'removemean'), cfg.removemean = 'yes'; end +if ~isfield(cfg, 'partchannel'), cfg.partchannel = ''; end +if ~isfield(cfg, 'conditional'), cfg.conditional = []; end +if ~isfield(cfg, 'blockindx'), cfg.blockindx = {}; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +% load optional given inputfile as data +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + end +end + +hasjack = (isfield(data, 'method') && strcmp(data.method, 'jackknife')) || (isfield(data, 'dimord') && strcmp(data.dimord(1:6), 'rptjck')); +hasrpt = (isfield(data, 'dimord') && ~isempty(strfind(data.dimord, 'rpt'))) || (isfield(data, 'avg') && isfield(data.avg, 'mom')); %FIXME old-fashioned pcc data +dojack = strcmp(cfg.jackknife, 'yes'); +normrpt = 0; % default, has to be overruled e.g. in plv, because of single replicate normalisation +normpow = 1; % default, has to be overruled e.g. in csd, + +% FIXME check which methods require hasrpt + +% ensure that the input data is appropriate for the method +switch cfg.method + case {'coh' 'csd'} + if ~isempty(cfg.partchannel) + if hasrpt && ~hasjack, + error('partialisation on single trial observations is not supported'); + end + try + data = checkdata(data, 'datatype', {'freqmvar' 'freq'}, 'cmbrepresentation', 'full'); + inparam = 'crsspctrm'; + catch + error('partial coherence/csd is only supported for input allowing for a all-to-all csd representation'); + end + else + data = checkdata(data, 'datatype', {'freqmvar' 'freq' 'source'}); + inparam = 'crsspctrm'; + end + + if strcmp(cfg.method, 'csd'), + normpow = 0; + warning('cfg.complex for requested csd is set to %s, do you really want this?', cfg.complex); + end + + dtype = datatype(data); + switch dtype + case 'source' + if isempty(cfg.refindx), error('indices of reference voxels need to be specified'); end + % if numel(cfg.refindx)>1, error('more than one reference voxel is not yet supported'); end + otherwise + end + % FIXME think of accommodating partial coherence for source data with only a few references + + case {'plv'} + data = checkdata(data, 'datatype', {'freqmvar' 'freq'}); + inparam = 'crsspctrm'; + normrpt = 1; + case {'corr' 'xcorr'} + data = checkdata(data, 'datatype', 'raw'); + case {'amplcorr' 'powcorr'} + data = checkdata(data, 'datatype', {'freqmvar' 'freq' 'source'}); + dtype = datatype(data); + switch dtype + case {'freq' 'freqmvar'} + inparam = 'powcovspctrm'; + case 'source' + inparam = 'powcov'; + if isempty(cfg.refindx), error('indices of reference voxels need to be specified'); end + % if numel(cfg.refindx)>1, error('more than one reference voxel is not yet supported'); end + otherwise + end + case {'granger'} + data = checkdata(data, 'datatype', {'mvar' 'freqmvar' 'freq'}); + inparam = 'transfer'; + % FIXME could also work with time domain data + case {'instantaneous_causality'} + data = checkdata(data, 'datatype', {'mvar' 'freqmvar' 'freq'}); + inparam = 'transfer'; + case {'total_interdependence'} + data = checkdata(data, 'datatype', {'freqmvar' 'freq'}); + inparam = 'crsspctrm'; + case {'dtf' 'pdc'} + data = checkdata(data, 'datatype', {'freqmvar' 'freq'}); + inparam = 'transfer'; + case {'psi'} + if ~isfield(cfg, 'normalize'), cfg.normalize = 'no'; end + data = checkdata(data, 'datatype', {'freqmvar' 'freq'}); + inparam = 'crsspctrm'; + case {'di'} + %wat eigenlijk? + otherwise + error('unknown method %s', cfg.method); +end +dtype = datatype(data); + +% ensure that source data ?is in 'new' representation +if strcmp(dtype, 'source'), + data = checkdata(data, 'sourcerepresentation', 'new'); +end + +% FIXME throw an error if cfg.complex~='abs', and dojack==1 +% FIXME throw an error if no replicates and cfg.method='plv' +% FIXME trial selection has to be implemented still + +if isfield(data, 'label'), + cfg.channel = ft_channelselection(cfg.channel, data.label); + if ~isempty(cfg.partchannel) + cfg.partchannel = ft_channelselection(cfg.partchannel, data.label); + end +end + +if isfield(data, 'label') && ~isempty(cfg.channelcmb), + cfg.channelcmb = ft_channelcombination(cfg.channelcmb, cfg.channel, 1); +end + +% check whether the required inparam is present in the data +if ~isfield(data, inparam) || (strcmp(inparam, 'crsspctrm') && isfield(data, 'crsspctrm')), + switch dtype + case 'freq' + if strcmp(inparam, 'crsspctrm') + if isfield(data, 'fourierspctrm') + [data, powindx, hasrpt] = univariate2bivariate(data, 'fourierspctrm', 'crsspctrm', dtype, 0, cfg.channelcmb); + elseif strcmp(inparam, 'crsspctrm') && isfield(data, 'powspctrm') + % if input data is old-fashioned, i.e. contains powandcsd + [data, powindx, hasrpt] = univariate2bivariate(data, 'powandcsd', 'crsspctrm', dtype, 0, cfg.channelcmb); + else + powindx = labelcmb2indx(data.labelcmb); + end + elseif strcmp(inparam, 'powcovspctrm') + if isfield(data, 'powspctrm'), + [data, powindx] = univariate2bivariate(data, 'powspctrm', 'powcovspctrm', dtype, strcmp(cfg.removemean,'yes'), cfg.channelcmb, strcmp(cfg.method,'amplcorr')); + elseif isfield(data, 'fourierspctrm'), + [data, powindx] = univariate2bivariate(data, 'fourierspctrm', 'powcovspctrm', dtype, strcmp(cfg.removemean,'yes'), cfg.channelcmb, strcmp(cfg.method,'amplcorr')); + end + end + case 'source' + if strcmp(inparam, 'crsspctrm') + [data, powindx, hasrpt] = univariate2bivariate(data, 'mom', 'crsspctrm', dtype, 0, cfg.refindx, [], 0); + %[data, powindx, hasrpt] = univariate2bivariate(data, 'fourierspctrm', 'crsspctrm', dtype, 0, cfg.refindx, [], 1); + elseif strcmp(inparam, 'powcov') + data = checkdata(data, 'haspow', 'yes'); + [data, powindx] = univariate2bivariate(data, 'pow', 'powcov', dtype, strcmp(cfg.removemean,'yes'), cfg.refindx, strcmp(cfg.method,'amplcorr'), 0); + end + otherwise + end + +else + powindx = []; +end + +% do some additional work if single trial normalisation is required +if normrpt && hasrpt, + if strcmp(inparam, 'crsspctrm'), + tmp = getfield(data, inparam); + nrpt = size(tmp,1); + progress('init', cfg.feedback, 'normalising...'); + for k = 1:nrpt + progress(k/nrpt, 'normalising amplitude of replicate %d from %d to 1\n', k, nrpt); + tmp(k,:,:,:,:) = tmp(k,:,:,:,:)./abs(tmp(k,:,:,:,:)); + end + progress('close'); + data = setfield(data, inparam, tmp); + end +end + +if ~isempty(cfg.partchannel) + allchannel = ft_channelselection(cfg.channel, data.label); + pchanindx = match_str(allchannel,cfg.partchannel); + kchanindx = setdiff(1:numel(allchannel), pchanindx); + keepchn = allchannel(kchanindx); + + cfg.pchanindx = pchanindx; + cfg.allchanindx = kchanindx; + partstr = ''; + for k = 1:numel(cfg.partchannel) + partstr = [partstr,'-',cfg.partchannel{k}]; + end + for k = 1:numel(keepchn) + keepchn{k} = [keepchn{k},'\',partstr(2:end)]; + end + data.label = keepchn; % update labels to remove the partialed channels + % FIXME consider keeping track of which channels have been partialised +else + cfg.pchanindx = []; + cfg.allchanindx = []; +end + +% check if jackknife is required +if hasrpt && dojack && hasjack, + % do nothing +elseif hasrpt && dojack, + % compute leave-one-outs + data = selectdata(data, 'jackknife', 'yes'); + hasjack = 1; +elseif hasrpt + data = selectdata(data, 'avgoverrpt', 'yes'); + hasrpt = 0; +else + % nothing required +end + +% compute the desired connectivity metric +switch cfg.method + case 'coh' + % coherence (unsquared), if cfg.complex = 'imag' imaginary part of + % coherency + + tmpcfg = []; + tmpcfg.cmplx = cfg.complex; + tmpcfg.feedback = cfg.feedback; + tmpcfg.dimord = data.dimord; + tmpcfg.pownorm = normpow; + tmpcfg.pchanindx = cfg.pchanindx; + tmpcfg.allchanindx = cfg.allchanindx; + tmpcfg.hasrpt = hasrpt; + tmpcfg.hasjack = hasjack; + if exist('powindx', 'var'), tmpcfg.powindx = powindx; end + optarg = cfg2keyval(tmpcfg); + + [datout, varout, nrpt] = ft_connectivity_corr(data.(inparam), optarg); + outparam = 'cohspctrm'; + + case 'csd' + % cross-spectral density (only useful if partialisation is required) + + tmpcfg = []; + tmpcfg.cmplx = cfg.complex; + tmpcfg.feedback = cfg.feedback; + tmpcfg.dimord = data.dimord; + tmpcfg.pownorm = normpow; + tmpcfg.pchanindx = cfg.pchanindx; + tmpcfg.allchanindx = cfg.allchanindx; + tmpcfg.hasrpt = hasrpt; + tmpcfg.hasjack = hasjack; + if exist('powindx', 'var'), tmpcfg.powindx = powindx; end + optarg = cfg2keyval(tmpcfg); + + [datout, varout, nrpt] = ft_connectivity_corr(data.(inparam), optarg); + outparam = 'crsspctrm'; + + case 'plv' + % phase locking value + + tmpcfg = []; + tmpcfg.cmplx = cfg.complex; + tmpcfg.feedback = cfg.feedback; + tmpcfg.dimord = data.dimord; + tmpcfg.pownorm = normpow; + tmpcfg.pchanindx = cfg.pchanindx; + tmpcfg.allchanindx = cfg.allchanindx; + tmpcfg.hasrpt = hasrpt; + tmpcfg.hasjack = hasjack; + if exist('powindx', 'var'), tmpcfg.powindx = powindx; end + optarg = cfg2keyval(tmpcfg); + + [datout, varout, nrpt] = ft_connectivity_corr(data.(inparam), optarg); + outparam = 'plvspctrm'; + + case 'corr' + % pearson's correlation coefficient + case 'xcorr' + % cross-correlation function + case 'spearman' + % spearman's rank correlation + case 'amplcorr' + % amplitude correlation + + tmpcfg = []; + tmpcfg.feedback = cfg.feedback; + tmpcfg.dimord = data.dimord; + tmpcfg.complex = 'real'; + tmpcfg.pownorm = 1; + tmpcfg.pchanindx = []; + tmpcfg.hasrpt = hasrpt; + tmpcfg.hasjack = hasjack; + if exist('powindx', 'var'), tmpcfg.powindx = powindx; end + optarg = cfg2keyval(tmpcfg); + + [datout, varout, nrpt] = ft_connectivity_corr(data.(inparam), optarg); + outparam = 'amplcorrspctrm'; + + case 'powcorr' + % power correlation + + tmpcfg = []; + tmpcfg.feedback = cfg.feedback; + tmpcfg.dimord = data.dimord; + tmpcfg.complex = 'real'; + tmpcfg.hasrpt = hasrpt; + tmpcfg.hasjack = hasjack; + if exist('powindx', 'var'), tmpcfg.powindx = powindx; end + optarg = cfg2keyval(tmpcfg); + + [datout, varout, nrpt] = ft_connectivity_corr(data.(inparam), optarg); + outparam = 'powcorrspctrm'; + + case 'granger' + % granger causality + + if sum(datatype(data, {'freq' 'freqmvar'})), + hasrpt = ~isempty(strfind(data.dimord, 'rpt')); + if hasrpt, + nrpt = size(data.transfer,1); + else + nrpt = 1; + siz = size(data.transfer); + data.transfer = reshape(data.transfer, [1 siz]); + siz = size(data.noisecov); + data.noisecov = reshape(data.noisecov, [1 siz]); + siz = size(data.crsspctrm); + data.crsspctrm = reshape(data.crsspctrm, [1 siz]); + end + + if isfield(data, 'labelcmb') && isempty(cfg.conditional), + % multiple pairwise non-parametric transfer functions + % linearly indexed + powindx = labelcmb2indx(data.labelcmb); + elseif isfield(data, 'labelcmb') + % conditional (blockwise) needs linearly represented cross-spectra + for k = 1:size(cfg.conditional,1) + tmp{k,1} = cfg.conditional(k,:); + tmp{k,2} = cfg.conditional(k,[1 3]); + end + [cmbindx, n] = blockindx2cmbindx(data.labelcmb, cfg.blockindx, tmp); + powindx.cmbindx = cmbindx; + powindx.n = n; + elseif isfield(cfg, 'block') && ~isempty(cfg.block) + % blockwise granger + powindx = cfg.block; + for k = 1:2 + newlabel{k,1} = cat(2,powindx{k}); + end + data.label = newlabel; + else + % do nothing + end + + %fs = cfg.fsample; %FIXME do we really need this, or is this related to how + %noisecov is defined and normalised? + fs = 1; + [datout, varout, n] = ft_connectivity_granger(data.transfer, data.noisecov, data.crsspctrm, fs, hasjack, powindx); + outparam = 'grangerspctrm'; + else + error('granger for time domain data is not yet implemented'); + end + + case 'instantaneous_causality' + % instantaneous ft_connectivity between the series, requires the same elements as granger + if sum(datatype(data, {'freq' 'freqmvar'})), + hasrpt = ~isempty(strfind(data.dimord, 'rpt')); + if hasrpt, + nrpt = size(data.transfer,1); + else + nrpt = 1; + siz = size(data.transfer); + data.transfer = reshape(data.transfer, [1 siz]); + siz = size(data.noisecov); + data.noisecov = reshape(data.noisecov, [1 siz]); + siz = size(data.crsspctrm); + data.crsspctrm = reshape(data.crsspctrm, [1 siz]); + end + + if isfield(data, 'labelcmb'), + % multiple pairwise non-parametric transfer functions + % linearly indexed + powindx = labelcmb2indx(data.labelcmb); + elseif isfield(cfg, 'block') && ~isempty(cfg.block) + % blockwise granger + powindx = cfg.block; + for k = 1:2 + newlabel{k,1} = cat(2,powindx{k}); + end + data.label = newlabel; + else + % do nothing + end + %fs = cfg.fsample; %FIXME do we really need this, or is this related to how + %noisecov is defined and normalised? + fs = 1; + [datout, varout, n] = ft_connectivity_instantaneous(data.transfer, data.noisecov, data.crsspctrm, fs, hasjack, powindx); + outparam = 'instantspctrm'; + else + error('instantaneous causality for time domain data is not yet implemented'); + end + + case 'total_interdependence' + %total interdependence + + tmpcfg = []; + tmpcfg.complex = cfg.complex; + tmpcfg.feedback = cfg.feedback; + tmpcfg.dimord = data.dimord; + tmpcfg.pownorm = normpow; + tmpcfg.pchanindx = cfg.pchanindx; + tmpcfg.allchanindx = cfg.allchanindx; + tmpcfg.hasrpt = hasrpt; + tmpcfg.hasjack = hasjack; + if exist('powindx', 'var'), tmpcfg.powindx = powindx; end + optarg = cfg2keyval(tmpcfg); + + [datout, varout, nrpt] = ft_connectivity_toti(tmpcfg, data.(inparam), hasrpt, hasjack); + outparam = 'totispctrm'; + + case 'dtf' + % directed transfer function + + if isfield(data, 'labelcmb'), + powindx = labelcmb2indx(data.labelcmb); + else + powindx = []; + end + + tmpcfg = []; + tmpcfg.feedback = cfg.feedback; + tmpcfg.powindx = powindx; + + hasrpt = ~isempty(strfind(data.dimord, 'rpt')); + if hasrpt, + nrpt = size(data.(inparam),1); + datin = data.(inparam); + else + nrpt = 1; + datin = reshape(data.(inparam), [1 size(data.(inparam))]); + end + [datout, varout, n] = ft_connectivity_dtf(tmpcfg, datin, hasjack); + outparam = 'dtfspctrm'; + + case 'pdc' + % partial directed coherence + + if isfield(data, 'labelcmb'), + powindx = labelcmb2indx(data.labelcmb); + else + powindx = []; + end + + tmpcfg = []; + tmpcfg.feedback = cfg.feedback; + tmpcfg.powindx = powindx; + + hasrpt = ~isempty(strfind(data.dimord, 'rpt')); + if hasrpt, + nrpt = size(data.(inparam),1); + datin = data.(inparam); + else + nrpt = 1; + datin = reshape(data.(inparam), [1 size(data.(inparam))]); + end + + [datout, varout, n] = ft_connectivity_pdc(tmpcfg, datin, hasjack); + outparam = 'pdcspctrm'; + + case 'pcd' + % pairwise circular distance + case 'psi' + % phase slope index + + tmpcfg = []; + tmpcfg.feedback = cfg.feedback; + tmpcfg.dimord = data.dimord; + tmpcfg.pownorm = normpow; + tmpcfg.pchanindx = cfg.pchanindx; + tmpcfg.allchanindx = cfg.allchanindx; + tmpcfg.nbin = nearest(data.freq, data.freq(1)+cfg.bandwidth)-1; + tmpcfg.normalize = cfg.normalize; + tmpcfg.hasrpt = hasrpt; + tmpcfg.hasjack = hasjack; + if exist('powindx', 'var'), tmpcfg.powindx = powindx; end + optarg = cfg2keyval(tmpcfg); + + [datout, varout, nrpt] = ft_connectivity_psi(tmpcfg, data.(inparam), hasrpt, hasjack); + outparam = 'psispctrm'; + + case 'di' + % directionality index + otherwise + error('unknown method %s', cfg.method); +end + +%remove the auto combinations if necessary +if exist('powindx', 'var') && ~isempty(powindx), + switch dtype + case {'freq' 'freqmvar'} + if isfield(data, 'labelcmb') && ~isstruct(powindx), + keepchn = powindx(:,1) ~= powindx(:,2); + datout = datout(keepchn,:,:,:,:); + if ~isempty(varout), + varout = varout(keepchn,:,:,:,:); + end + data.labelcmb = data.labelcmb(keepchn,:); + end + case 'source' + nvox = size(unique(data.pos(:,1:3),'rows'),1); + ncmb = size(data.pos,1)/nvox-1; + remove = (powindx(:,1) == powindx(:,2)) & ([1:size(powindx,1)]' > nvox*ncmb); + keepchn = ~remove; + + datout = datout(keepchn,:,:,:,:); + if ~isempty(varout), + varout = varout(keepchn,:,:,:,:); + end + inside = logical(zeros(1,size(data.pos,1))); + inside(data.inside) = true; + inside = inside(keepchn); + data.inside = find(inside)'; + data.outside = find(inside==0)'; + data.pos = data.pos(keepchn,:); + end +end + +%create output structure +switch dtype + case {'freq' 'freqmvar'}, + stat = []; + if isfield(data, 'label'), + stat.label = data.label; + end + if isfield(data, 'labelcmb'), + stat.labelcmb = data.labelcmb; + end + stat.dimord = data.dimord; %FIXME adjust dimord (remove rpt in dojack && hasrpt case) + stat = setfield(stat, outparam, datout); + if ~isempty(varout), + stat = setfield(stat, [outparam,'sem'], (varout/nrpt).^0.5); + end + case 'source' + stat = []; + stat.pos = data.pos; + stat.dim = data.dim; + stat.inside = data.inside; + stat.outside = data.outside; + stat = setfield(stat, outparam, datout); + if ~isempty(varout), + stat = setfield(stat, [outparam,'sem'], (varout/nrpt).^0.5); + end +end + +if isfield(data, 'freq'), stat.freq = data.freq; end +if isfield(data, 'frequency'), stat.frequency = data.frequency; end +if isfield(data, 'time'), stat.time = data.time; end +if isfield(data, 'grad'), stat.grad = data.grad; end +if isfield(data, 'elec'), stat.elec = data.elec; end +if exist('nrpt', 'var'), stat.dof = nrpt; end +%FIXME this is not correct for TF-representations when trials have +%different lengths + +% accessing this field here is needed for the configuration tracking +% by accessing it once, it will not be removed from the output cfg +cfg.outputfile; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add version information to the configuration +cfg.version.name = mfilename('fullpath'); +cfg.version.id = '$Id: ft_connectivityanalysis.m 1398 2010-07-12 14:26:24Z jansch $'; + +% remember the configuration details of the input data +try, cfg.previous = data.cfg; end +% remember the exact configuration details in the output +stat.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', stat); % use the variable name "data" in the output file +end + +%-------------------------------------------------------------- +%function [c, v, n] = ft_connectivity_corr(cfg, input, hasrpt, hasjack) + +%------------------------------------------------------------- +function [c, v, n] = ft_connectivity_toti(cfg, input, hasrpt, hasjack) + +% FIXME move functionality into ft_connectivity_granger + +cfg.hasrpt = hasrpt; +cfg.hasjack = hasjack; +optarg = cfg2keyval(cfg); + +[c, v, n] = ft_connectivity_corr(input, optarg); +c = -log(1-c.^2); +v = -log(1-v.^2); %FIXME this is probably not correct + +%------------------------------------------------------------- +%function [c, v, n] = ft_connectivity_psi(cfg, input, hasrpt, hasjack) + +%------------------------------------------------------------ +%function [pdc, pdcvar, n] = ft_connectivity_pdc(cfg, input, hasjack) + +%------------------------------------------------------------ +%function [dtf, dtfvar, n] = ft_connectivity_dtf(cfg, input, hasjack) + +%------------------------------------------------------------------------- +%function [granger, v, n] = ft_connectivity_granger(H, Z, S, fs, hasjack, powindx) + +%---------------------------------------------------------------- +function [instc, v, n] = ft_connectivity_instantaneous(H, Z, S, fs, hasjack,powindx) + +% FIXME move functionality into ft_connectivity_granger + +%Usage: causality = hz2causality(H,S,Z,fs); +%Inputs: transfer = transfer function, +% crsspctrm = 3-D spectral matrix; +% noisecov = noise covariance, +% fs = sampling rate +%Outputs: instantaneous causality spectrum between the channels. +%Total Interdependence = Granger (X->Y) + Granger (Y->X) + Instantaneous Causality +% : auto-causality spectra are set to zero +% Reference: Brovelli, et. al., PNAS 101, 9849-9854 (2004), Rajagovindan +% and Ding, PLoS One Vol. 3, 11, 1-8 (2008) +%M. Dhamala, UF, August 2006. + +%FIXME speed up code and check +siz = size(H); +if numel(siz)==4, + siz(5) = 1; +end +n = siz(1); +Nc = siz(2); + +outsum = zeros(siz(2:end)); +outssq = zeros(siz(2:end)); +if isempty(powindx) + + %clear S; for k = 1:size(H,3), h = squeeze(H(:,:,k)); S(:,:,k) = h*Z*h'/fs; end; + for kk = 1:n + for ii = 1:Nc + for jj = 1:Nc + if ii ~=jj, + zc1 = reshape(Z(kk,jj,jj,:) - Z(kk,ii,jj,:).^2./Z(kk,ii,ii,:),[1 1 1 1 siz(5)]); + zc1 = repmat(zc1,[1 1 1 siz(4) 1]); + zc2 = reshape(Z(kk,ii,ii,:) - Z(kk,jj,ii,:).^2./Z(kk,jj,jj,:),[1 1 1 1 siz(5)]); + zc2 = repmat(zc2,[1 1 1 siz(4) 1]); + CTH1 = reshape(ctranspose(squeeze(H(kk,ii,jj,:,:))),1,1,1,siz(4)); + CTH2 = reshape(ctranspose(squeeze(H(kk,jj,ii,:,:))),1,1,1,siz(4)); + term1 = (S(kk,ii,ii,:,:) - H(kk,ii,jj,:,:).*zc1.*CTH1); + term2 = (S(kk,jj,jj,:,:) - H(kk,jj,ii,:,:).*zc2.*CTH2); + Sdet = (S(kk,ii,ii,:,:).*S(kk,jj,jj,:,:)) - (S(kk,ii,jj,:,:).*S(kk,jj,ii,:,:)); + outsum(jj,ii,:) = outsum(jj,ii) + log((term1.*term2)./Sdet(kk,:,:,:)); + outssq(jj,ii,:) = outssq(jj,ii) + log((term1.*term2)./Sdet(kk,:,:,:)).^2; + end + end + outsum(ii,ii,:,:) = 0;%self-granger set to zero + end + end +elseif ~iscell(powindx) + % data are linearly indexed + for k = 1:Nc + for j = 1:n + iauto1 = find(sum(powindx==powindx(k,1),2)==2); + iauto2 = find(sum(powindx==powindx(k,2),2)==2); + icross1 = k; + icross2 = find(sum(powindx==powindx(ones(Nc,1)*k,[2 1]),2)==2); + if iauto1 ~= iauto2 + zc1 = Z(j,iauto1) - Z(j,icross2).^2./Z(j,iauto2); + zc1 = repmat(zc1,[1 1 siz(3)]); + zc2 = Z(j,iauto2) - Z(j,icross1).^2./Z(j,iauto1); + zc2 = repmat(zc2,[1 1 siz(3)]); + CTH1 = reshape(ctranspose(squeeze(H(j,icross2,:))),1,1,siz(3)); + CTH2 = reshape(ctranspose(squeeze(H(j,icross1,:))),1,1,siz(3)); + term1 = (S(j,iauto2,:) - H(j,icross2,:).*zc1.*CTH1); + term2 = (S(j,iauto1,:) - H(j,icross1,:).*zc2.*CTH2); + Sdet = (S(j,iauto2,:).*S(j,iauto1,:)) - (S(j,icross2,:).*S(j,icross1,:)); + outsum(k,:) = outsum(k) + log((term1.*term2)./Sdet(j,:,:)); + outssq(k,:) = outssq(k) + log((term1.*term2)./Sdet(j,:,:)).^2; + end + end + end + + +end +instc = outsum./n; + +if n>1, + if hasjack + bias = (n-1).^2; + else + bias = 1; + end + v = bias*(outssq - (outsum.^2)./n)./(n - 1); +else + v = []; +end + +%---------------------------------------- +function [indx] = labelcmb2indx(labelcmb) + +%identify the auto-combinations +ncmb = size(labelcmb,1); +indx = zeros(ncmb,2); + +label = unique(labelcmb(:)); +nchan = numel(label); +autoindx = zeros(nchan,1); +for k = 1:nchan + sel1 = strcmp(label{k}, labelcmb(:,1)); + sel2 = strcmp(label{k}, labelcmb(:,2)); + autoindx = find(sel1 & sel2); + + indx(sel1,1) = autoindx; + indx(sel2,2) = autoindx; +end + +%---------------------------------- +function [c] = complexeval(c, str) + +switch str + case 'complex' + %do nothing + case 'abs' + c = abs(c); + case 'angle' + c = angle(c); + case 'imag' + c = imag(c); + case 'real' + c = real(c); + otherwise + error('cfg.complex = ''%s'' not supported', cfg.complex); +end + +%------------------------------------------------------------------------------------------------------------------ +function [data, powindx, hasrpt] = univariate2bivariate(data, inparam, outparam, dtype, demeanflag, cmb, sqrtflag, keeprpt) + +if nargin<8, keeprpt = 1; end +if nargin<7, sqrtflag = 0; end +if nargin<6, cmb = []; end +if nargin<5, demeanflag = 0; end + +switch dtype + case 'freq' + ncmb = size(cmb,1); + nchan = numel(data.label); + getpowindx = 0; + if ncmb==0, + error('no channel combinations are specified'); + elseif ncmb==nchan.^2 || ncmb==(nchan+1)*nchan*0.5, + dofull = 1; + else + dofull = 0; + end + + if strcmp(inparam, 'fourierspctrm') && strcmp(outparam, 'crsspctrm'), + %fourier coefficients -> cross-spectral density + if dofull + data = checkdata(data, 'cmbrepresentation', 'full'); + else + data = checkdata(data, 'cmbrepresentation', 'sparse', 'channelcmb', cmb); + end + elseif strcmp(inparam, 'powandcsd') && strcmp(outparam, 'crsspctrm'), + if ~isempty(cmb), + data = checkdata(data, 'cmbrepresentation', 'sparse', 'channelcmb', cmb); + + %ensure getting powindx later on to prevent crash + getpowindx = 1; + else + %data = checkdata(data, 'cmbrepresentation', 'full'); + %this should not be possible + error('cannot convert to a full csd representation'); + + + end + elseif strcmp(inparam, 'fourierspctrm') && strcmp(outparam, 'powcovspctrm'), + %fourier coefficients -> power covariance + data = checkdata(data, 'cmbrepresentation', 'sparsewithpow', 'channelcmb', {}); + + if sqrtflag, data.powspctrm = sqrt(data.powspctrm); end + + %get covariance by using checkdata + if demeanflag, + nrpt = size(data.powspctrm,1); + mdat = nanmean(data.powspctrm,1); + data.powspctrm = data.powspctrm - mdat(ones(1,nrpt),:,:,:,:,:); + end + data.fourierspctrm = data.powspctrm; %this is necessary for checkdata to work + data.dimord = ['rpttap',data.dimord(4:end)]; + data = rmfield(data, 'powspctrm'); + data.cumtapcnt(:) = 1; + data.cumsumcnt(:) = 1; + if ncmb < (nchan-1)*nchan*0.5, + data = checkdata(data, 'cmbrepresentation', 'sparse', 'channelcmb', cmb); + else + data = checkdata(data, 'cmbrepresentation', 'full'); + end + data.powcovspctrm = data.crsspctrm; + data = rmfield(data, 'crsspctrm'); + elseif strcmp(inparam, 'powspctrm') && strcmp(outparam, 'powcovspctrm'), + %power-spectral density -> power covariance + + if sqrtflag, data.powspctrm = sqrt(data.powspctrm); end + + %get covariance by using checkdata + if demeanflag, + nrpt = size(data.powspctrm,1); + mdat = nanmean(data.powspctrm,1); + data.powspctrm = data.powspctrm - mdat(ones(1,nrpt),:,:,:,:,:); + end + data.fourierspctrm = data.powspctrm; %this is necessary for checkdata to work + data.dimord = ['rpttap',data.dimord(4:end)]; + data = rmfield(data, 'powspctrm'); + data.cumtapcnt(:) = 1; + data.cumsumcnt(:) = 1; + if ncmb < (nchan-1)*nchan*0.5, + data = checkdata(data, 'cmbrepresentation', 'sparse', 'channelcmb', cmb); + else + data = checkdata(data, 'cmbrepresentation', 'full'); + end + data.powcovspctrm = data.crsspctrm; + data = rmfield(data, 'crsspctrm'); + else + error('unknown conversion from univariate to bivariate representation'); + end + + if ~isempty(cmb) && (ncmb < (nchan-1)*nchan*0.5 || getpowindx==1), + powindx = labelcmb2indx(data.labelcmb); + else + powindx = []; + end + case 'source' + ncmb = numel(cmb); + + if strcmp(inparam, 'pow') && strcmp(outparam, 'powcov'), + [nrpt,nvox] = size(data.pow); + if sqrtflag, data.pow = sqrt(data.pow); end + if demeanflag, + mdat = nanmean(data.pow,1); + data.pow = data.pow - mdat(ones(1,nrpt),:); %FIXME only works for 1 frequency + end + + data.powcov = [data.pow .* data.pow(:,ones(1,nvox)*cmb) data.pow.*data.pow]; + data = rmfield(data, 'pow'); + powindx = [nvox+[1:nvox] nvox+[1:nvox]; cmb*ones(1,nvox) nvox+[1:nvox]]'; + + data.pos = [data.pos repmat(data.pos(cmb,:),[nvox 1]);data.pos data.pos]; + data.inside = [data.inside(:); data.inside(:)+nvox]; + data.outside = [data.outside(:); data.outside(:)+nvox]; + data.dim(2) = size(data.pos,1); + elseif strcmp(inparam, 'mom') && strcmp(outparam, 'crsspctrm'), + %get mom as rpttap_pos_freq matrix + %FIXME this assumes only 1 freq bin + mom = zeros(size(data.mom{data.inside(1)},1), size(data.pos,1)); + mom(:, data.inside) = cat(2, data.mom{data.inside}); + if keeprpt, + [nrpt,nvox] = size(mom); + data.crsspctrm = [mom.*conj(mom(:,ones(1,nvox)*cmb)) abs(mom).^2]; + data = rmfield(data, 'mom'); + data = rmfield(data, 'momdimord'); + powindx = [nvox+[1:nvox] nvox+[1:nvox]; cmb*ones(1,nvox) nvox+[1:nvox]]'; + + data.pos = [data.pos repmat(data.pos(cmb,:),[nvox 1]);data.pos data.pos]; + data.inside = [data.inside(:); data.inside(:)+nvox]; + data.outside = [data.outside(:); data.outside(:)+nvox]; + elseif ncmb. +% +% $Id: ft_connectivitysimulation.m 949 2010-04-21 18:09:23Z roboos $ + +% check input configuration for the generally applicable options +cfg = checkconfig(cfg, 'required', {'nsignal' 'ntrials' 'triallength' 'fsample' 'method'}); + +% method specific defaults +switch cfg.method +case {'linear_mix'} + %method specific defaults + if ~isfield(cfg, 'bpfilter'), cfg.bpfilter = 'yes'; end + if ~isfield(cfg, 'bpfreq'), cfg.bpfreq = [15 25]; end + if ~isfield(cfg, 'blc'), cfg.blc = 'yes'; end + if ~isfield(cfg, 'absnoise'), cfg.absnoise = 1; end + cfg = checkconfig(cfg, 'required', {'mix' 'delay'}); +case {'mvnrnd'} + if ~isfield(cfg, 'bpfilter'), cfg.bpfilter = 'yes'; end + if ~isfield(cfg, 'bpfreq'), cfg.bpfreq = [15 25]; end + if ~isfield(cfg, 'blc'), cfg.blc = 'yes'; end + if ~isfield(cfg, 'absnoise'), cfg.absnoise = 1; end + cfg = checkconfig(cfg, 'required', {'covmat' 'delay'}); +case {'ar'} + cfg = checkconfig(cfg, 'required', {'params' 'noisecov'}); +otherwise +end + +trial = cell(1, cfg.ntrials); +time = cell(1, cfg.ntrials); +nsmp = round(cfg.triallength*cfg.fsample); +tim = [0:nsmp-1]./cfg.fsample; + +% create the labels +for k = 1:cfg.nsignal + label{k,1} = ['signal',num2str(k,'%03d')]; +end + +switch cfg.method +case {'linear_mix'} + + fltpad = 50; %hard coded to avoid filtering artifacts + delay = cfg.delay; + delay = delay - min(delay(:)); %make explicitly >= 0 + maxdelay = max(delay(:)); + + if iscell(cfg.mix), + %each trial has different mix + mix = cfg.mix; + else + %make cell-array out of mix + tmpmix = cfg.mix; + mix = cell(1,cfg.ntrials); + for tr = 1:cfg.ntrials + mix{1,tr} = tmpmix; + end + end + + nmixsignal = size(mix{1}, 2); %number of "mixing signals" + nsignal = size(mix{1}, 1); + + if numel(size(mix{1}))==2, + %mix is static, no function of time + for tr = 1:cfg.ntrials + mix{tr} = mix{tr}(:,:,ones(1,nsmp+maxdelay)); + end + elseif numel(size(mix{1}))==3 && size(mix{1},3)==nsmp, + %mix changes with time + for tr = 1:cfg.ntrials + mix{tr} = cat(3,mix{tr},mix{tr}(:,:,nsmp*ones(1,maxdelay))); + end + %FIXME think about this + %due to the delay the mix cannot be defined instantaneously with respect to all signals + end + + for tr = 1:cfg.ntrials + mixsignal = randn(nmixsignal, nsmp + 2*fltpad + maxdelay); + mixsignal = preproc(mixsignal, label, cfg.fsample, cfg, -fltpad, fltpad, fltpad); + tmp = zeros(cfg.nsignal, nsmp); + for i=1:cfg.nsignal + for j=1:nmixsignal + begsmp = 1 + delay(i,j); + endsmp = nsmp + delay(i,j); + tmpmix = reshape(mix{tr}(i,j,:),[1 nsmp+maxdelay]) .* mixsignal(j,:); + tmp(i,:) = tmp(i,:) + tmpmix(begsmp:endsmp); + end + end + trial{tr} = tmp; + + % add some noise + trial{tr} = ft_preproc_baselinecorrect(trial{tr} + cfg.absnoise*randn(size(trial{tr}))); + + % define time axis for this trial + time{tr} = tim; + end + +case {'mvnrnd'} + fltpad = 100; %hard coded + + shift = max(cfg.delay(:,1)) - cfg.delay(:,1); + for k = 1:cfg.ntrials + % create the multivariate time series plus some padding + tmp = mvnrnd(zeros(1,cfg.nsignal), cfg.covmat, nsmp+2*fltpad+max(shift))'; + + % add the delays + newtmp = zeros(cfg.nsignal, nsmp+2*fltpad); + for kk = 1:cfg.nsignal + begsmp = + shift(kk) + 1; + endsmp = nsmp + 2*fltpad + shift(kk); + newtmp(kk,:) = ft_preproc_baselinecorrect(tmp(kk,begsmp:endsmp)); + end + + % apply preproc + newtmp = preproc(newtmp, label, cfg.fsample, cfg, -fltpad, fltpad, fltpad); + + trial{k} = newtmp; + + % add some noise + trial{k} = ft_preproc_baselinecorrect(trial{k} + cfg.absnoise*randn(size(trial{k}))); + + % define time axis for this trial + time{k} = tim; + end +case {'ar'} + nlag = size(cfg.params,3); + nsignal = cfg.nsignal; + params = zeros(nlag*nsignal, nsignal); + for k = 1:nlag + params(((k-1)*nsignal+1):k*nsignal,:) = cfg.params(:,:,k); + end + for k = 1:cfg.ntrials + tmp = zeros(nsignal, nsmp+nlag); + noise = mvnrnd(zeros(nsignal,1), cfg.noisecov, nsmp+nlag)'; + state0 = zeros(nsignal*nlag, 1); + for m = 1:nlag + indx = ((m-1)*nsignal+1):m*nsignal; + state0(indx) = params(indx,:)'*noise(:,m); + end + tmp(:,1:nlag) = fliplr(reshape(state0, [nsignal nlag])); + + for m = (nlag+1):(nsmp+nlag) + state0 = reshape(fliplr(tmp(:,(m-nlag):(m-1))), [nlag*nsignal 1]); + tmp(:, m) = params'*state0 + noise(:,m); + end + trial{k} = tmp(:,nlag+1:end); + time{k} = tim; + end + +otherwise + error('unknown method'); +end + +% create the output data +data = []; +data.trial = trial; +data.time = time; +data.fsample = cfg.fsample; +data.label = label; + +% add version details to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_connectivitysimulation.m 949 2010-04-21 18:09:23Z roboos $'; +% remember the configuration details of the input data +try, cfg.previous = data.cfg; end +% remember the exact configuration details in the output +data.cfg = cfg; diff --git a/external/fieldtrip/ft_databrowser.m b/external/fieldtrip/ft_databrowser.m new file mode 100644 index 0000000..07307a8 --- /dev/null +++ b/external/fieldtrip/ft_databrowser.m @@ -0,0 +1,1062 @@ +function [cfg] = ft_databrowser(cfg, data) + +% FT_DATABROWSER can be used for visual inspection of data. Artifacts that were detected +% by artifact functions (see FT_ARTIFACT_xxx functions where xxx is the type of artifact) +% are marked. Additionally data pieces can be marked and unmarked as artifact by +% manual selection. The output cfg contains the updated artifactdef field. +% +% Use as +% cfg = ft_databrowser(cfg) +% required configuration options: +% cfg.dataset or both cfg.headerfile and cfg.datafile +% or as +% cfg = ft_databrowser(cfg, data) +% with the data as obtained from FT_PREPROCESSING +% +% The following configuration options are supported: +% cfg.trl = structure that defines the data segments of interest. See FT_DEFINETRIAL +% cfg.continuous = 'yes' or 'no' whether the file contains continuous data +% cfg.channel = cell-array with channel labels, see FT_CHANNELSELECTION +% cfg.zscale = [zmin zmax] or 'auto' (default = 'auto') +% cfg.blocksize = number (in seconds), only aplicable if data contains only 1 (long) trial +% cfg.viewmode = string, 'butterfly', 'vertical', 'component' (default = 'butterfly') +% cfg.artfctdef.xxx.artifact = Nx2 matrix with artifact segments see FT_ARTIFACT_xxx functions +% cfg.selectfeature = string, name of feature to be selected/added (default = 'visual') +% cfg.selectmode = string, what to do with a selection, can be 'mark', or 'eval' (default = 'mark') +% 'mark': artfctdef field is updated, 'eval': the function defined in +% cfg.selfun is evaluated f.i. browse_movieplotER calls movieplotER which makes +% a movie of the selected data +% cfg.colorgroups = 'sequential' 'labelcharx' (x = xth character in label), 'chantype' or +% vector with length(data/hdr.label) defining groups (default = 'sequential') +% cfg.channelcolormap = COLORMAP (default = customized lines map with 15 colors) +% cfg.selfun = string, name of function which is evaluated if selectmode is set to 'eval'. +% The selected data and the selcfg are passed on to this function. +% cfg.selcfg = configuration options for selfun +% cfg.eegscale = number, scaling to apply to the EEG channels prior to display +% cfg.eogscale = number, scaling to apply to the EOG channels prior to display +% cfg.ecgscale = number, scaling to apply to the ECG channels prior to display +% cfg.megscale = number, scaling to apply to the MEG channels prior to display +% +% The "artifact" field in the output cfg is a Nx2 matrix comparable to the +% "trl" matrix of FT_DEFINETRIAL. The first column of which specifying the +% beginsamples of an artifact period, the second column contains the +% endsamples of the artifactperiods. +% +% NOTE for debugging: in case the databrowser crashes, use delete(gcf) to kill the figure. +% +% See also FT_PREPROCESSING, FT_REJECTARTIFACT, FT_ARTIFACT_EOG, FT_ARTIFACT_MUSCLE, +% FT_ARTIFACT_JUMP, FT_ARTIFACT_MANUAL, FT_ARTIFACT_THRESHOLD, FT_ARTIFACT_CLIP, FT_ARTIFACT_ECG +% +% Undocumented local options: +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk + +% Copyright (C) 2009, Robert Oostenveld, Ingrid Niewenhuis +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_databrowser.m 1430 2010-07-20 07:41:41Z roboos $ + +fieldtripdefs + +% set defaults for optional cfg.input and or cfg.outputfile +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +% load optional given inputfile as data +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + hasdata = true; + end +end + +if hasdata + data = checkdata(data, 'datatype', {'raw', 'comp'}, 'feedback', 'yes', 'hastrialdef', 'yes', 'hasoffset', 'yes'); + if ~isfield(cfg, 'continuous') && length(data.trial) == 1 + cfg.continuous = 'yes'; + end +else + % check if the input cfg is valid for this function + cfg = checkconfig(cfg, 'dataset2files', {'yes'}); + cfg = checkconfig(cfg, 'required', {'headerfile', 'datafile'}); + cfg = checkconfig(cfg, 'renamed', {'datatype', 'continuous'}); + cfg = checkconfig(cfg, 'renamedval', {'continuous', 'continuous', 'yes'}); +end + +% this is the default for cfg.channelcolormap +lines_color = [0.75 0 0;0 0 1;0 1 0;0.44 0.19 0.63;0 0.13 0.38;0.5 0.5 0.5;1 0.75 0;1 0 0;0.89 0.42 0.04;0.85 0.59 0.58;0.57 0.82 0.31;0 0.69 0.94;1 0 0.4;0 0.69 0.31;0 0.44 0.75]; + +% set the defaults +if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end +if ~isfield(cfg, 'zscale'), cfg.zscale = 'auto'; end +if ~isfield(cfg, 'artfctdef'), cfg.artfctdef = struct; end +if ~isfield(cfg, 'selectfeature'), cfg.selectfeature = 'visual'; end % string or cell-array +if ~isfield(cfg, 'selectmode'), cfg.selectmode = 'mark'; end +if ~isfield(cfg, 'viewmode'), cfg.viewmode = 'butterfly'; end % butterfly, vertical, component, settings +if ~isfield(cfg, 'blocksize'), cfg.blocksize = 1; end % only for segmenting continuous data, i.e. one long trial +if ~isfield(cfg, 'preproc'), cfg.preproc = []; end % see preproc for options +if ~isfield(cfg, 'event'), cfg.event = []; end +if ~isfield(cfg, 'selfun'), cfg.selfun = 'browse_multiplotER'; end +if ~isfield(cfg, 'selcfg'), cfg.selcfg = []; end +if ~isfield(cfg, 'colorgroups'), cfg.colorgroups = 'sequential'; end +if ~isfield(cfg, 'channelcolormap'), cfg.channelcolormap = lines_color; end +if ~isfield(cfg, 'eegscale'), cfg.eegscale = []; end +if ~isfield(cfg, 'eogscale'), cfg.eogscale = []; end +if ~isfield(cfg, 'ecgscale'), cfg.ecgscale = []; end +if ~isfield(cfg, 'megscale'), cfg.megscale = []; end + +if ischar(cfg.selectfeature) + % ensure that it is a cell array + cfg.selectfeature = {cfg.selectfeature}; +end + +% get some initial parameters from the data +if hasdata + % fetch the header + hdr = fetch_header(data); + + % fetch the events + event = fetch_event(data); + + cfg.channel = ft_channelselection(cfg.channel, data.label); + chansel = match_str(data.label, cfg.channel); + fsample = 1/(data.time{1}(2)-data.time{1}(1)); + Nchans = length(chansel); + + % this is how the input data is segmented + if isfield(data, 'trialdef'), + trlorg = [data.trialdef data.offset(:)]; + else + trlorg = []; + end + Ntrials = size(trlorg, 1); + + if strcmp(cfg.viewmode, 'component') + % read or create the layout that will be used for the topoplots + cfg.layout = ft_prepare_layout(cfg, data); + end + +else + % read the header + hdr = ft_read_header(cfg.headerfile, 'headerformat', cfg.headerformat); + +% FIXME how is this supposed to work? +% read the events + if ~isempty(cfg.event) + event = ft_read_event(cfg.dataset); + else + event = []; + end + + % this option relates to reading over trial boundaries in a pseudo-continuous dataset + if ~isfield(cfg, 'continuous') + if hdr.nTrials==1 + cfg.continuous = 'yes'; + else + cfg.continuous = 'no'; + end + end + + if ~isfield(cfg, 'trl') + % treat the data as continuous if possible, otherwise define all trials as indicated in the header + if strcmp(cfg.continuous, 'yes') + trl = zeros(1, 3); + trl(1,1) = 1; + trl(1,2) = hdr.nSamples*hdr.nTrials; + trl(1,3) = 0; + else + trl = zeros(hdr.nTrials, 3); + for i=1:hdr.nTrials + trl(i,1) = (i-1)*hdr.nSamples + 1; + trl(i,2) = (i )*hdr.nSamples ; + trl(i,3) = -hdr.nSamplesPre; + end + end + cfg.trl = trl; + end + + cfg.channel = ft_channelselection(cfg.channel, hdr.label); + chansel = match_str(hdr.label, cfg.channel); + fsample = hdr.Fs; + Nchans = length(chansel); + + % this is how the data from file should be segmented + trlorg = cfg.trl; + Ntrials = size(trlorg, 1); + + if strcmp(cfg.viewmode, 'component') + % read or create the layout that will be used for the topoplots + cfg.layout = ft_prepare_layout(cfg); + end +end + +if Nchans == 0 + error('no channels to display'); +end + +if Ntrials == 0 + error('no trials to display'); +end + +% determine coloring of channels +if hasdata + labels_all = data.label; +else + labels_all= hdr.label; +end +if size(cfg.channelcolormap,2) ~= 3 + error('cfg.channelcolormap is not valid, size should be Nx3') +end +if isnumeric(cfg.colorgroups) + % groups defined by user + if length(labels_all) ~= length(cfg.colorgroups) + error('length(cfg.colorgroups) should be length(data/hdr.label)') + end + R = cfg.channelcolormap(:,1); + G = cfg.channelcolormap(:,2); + B = cfg.channelcolormap(:,3); + chan_colors = [R(cfg.colorgroups(:)) G(cfg.colorgroups(:)) B(cfg.colorgroups(:))]; +elseif strcmp(cfg.colorgroups, 'chantype') + type = ft_chantype(labels_all); + [tmp1 tmp2 cfg.colorgroups] = unique(type); + fprintf('%3d colorgroups were identified\n',length(tmp1)) + R = cfg.channelcolormap(:,1); + G = cfg.channelcolormap(:,2); + B = cfg.channelcolormap(:,3); + chan_colors = [R(cfg.colorgroups(:)) G(cfg.colorgroups(:)) B(cfg.colorgroups(:))]; +elseif strcmp(cfg.colorgroups(1:9), 'labelchar') + % groups determined by xth letter of label + labelchar_num = str2double(cfg.colorgroups(10)); + vec_letters = num2str(zeros(length(labels_all),1)); + for iChan = 1:length(labels_all) + vec_letters(iChan) = labels_all{iChan}(labelchar_num); + end + [tmp1 tmp2 cfg.colorgroups] = unique(vec_letters); + fprintf('%3d colorgroups were identified\n',length(tmp1)) + R = cfg.channelcolormap(:,1); + G = cfg.channelcolormap(:,2); + B = cfg.channelcolormap(:,3); + chan_colors = [R(cfg.colorgroups(:)) G(cfg.colorgroups(:)) B(cfg.colorgroups(:))]; +elseif strcmp(cfg.colorgroups, 'sequential') + % no grouping + chan_colors = lines(length(labels_all)); +else + error('do not understand cfg.colorgroups') +end + +% collect the artifacts that have been detected from cfg.artfctdef.xxx.artifact +artlabel = fieldnames(cfg.artfctdef); +sel = zeros(size(artlabel)); +artifact = cell(size(artlabel)); +for i=1:length(artlabel) + sel(i) = issubfield(cfg.artfctdef, [artlabel{i} '.artifact']); + if sel(i) + artifact{i} = getsubfield(cfg.artfctdef, [artlabel{i} '.artifact']); + num = size(artifact{i}, 1); + if isempty(num) + num = 0; + end + fprintf('detected %3d %s artifacts\n', num, artlabel{i}); + end +end +artifact = artifact(sel==1); +artlabel = artlabel(sel==1); + +for i=1:length(cfg.selectfeature) + if ~any(strcmp(cfg.selectfeature{i}, artlabel)) + artifact = {[], artifact{:}}; + artlabel = {cfg.selectfeature{i}, artlabel{:}}; + end +end + +if length(artlabel) > 8 + error('only upto 8 artifacts groups supported') +end + +% make artdata representing all artifacts in a "raw data" format +datendsample = max(trlorg(:,2)); +artdat = convert_event(artifact, 'boolvec', 'endsample', datendsample); + +artdata = []; +artdata.trial{1} = artdat; % every artifact is a "channel" +artdata.time{1} = offset2time(0, fsample, datendsample); +artdata.label = artlabel; +artdata.fsample = fsample; +artdata.cfg.trl = [1 datendsample 0]; + +if ischar(cfg.zscale) && strcmp(cfg.zscale, 'auto') + if nargin>1 + dat = data.trial{1}(chansel,:); + minval = min(dat(:)); + maxval = max(dat(:)); + cfg.zscale = max(abs(minval), abs(maxval)); + else + cfg.zscale = 1; % FIXME + end +end + +h = figure; +set(h, 'KeyPressFcn', @keyboard_cb); +set(h, 'WindowButtonDownFcn', {@ft_select_range, 'multiple', false, 'xrange', true, 'yrange', false, 'clear', true, 'callback', {@select_range_cb, h}, 'event', 'WindowButtonDownFcn'}); +set(h, 'WindowButtonUpFcn', {@ft_select_range, 'multiple', false, 'xrange', true, 'yrange', false, 'clear', true, 'callback', {@select_range_cb, h}, 'event', 'WindowButtonUpFcn'}); +set(h, 'WindowButtonMotionFcn', {@ft_select_range, 'multiple', false, 'xrange', true, 'yrange', false, 'clear', true, 'callback', {@select_range_cb, h}, 'event', 'WindowButtonMotionFcn'}); + +% opt represents the global data/settings, it should contain +% - the original data, epoched or continuous +% - the artifacts represented as continuous data +% - the redraw_cb settings +% - the preproc settings +% - the select_range_cb settings (also used in keyboard_cb) + +% these elements are stored inside the figure so that the callback routines can modify them +opt = []; +if hasdata + opt.orgdata = data; +else + opt.orgdata = []; % this means that it will look in opt.cfg.dataset +end +opt.artdata = artdata; +opt.cfg = cfg; % the configuration of this function, not of the preprocessing +opt.hdr = hdr; +opt.event = event; +opt.trlop = 1; % active trial being displayed +opt.ftsel = find(strcmp(artlabel,cfg.selectfeature)); % current artifact/feature being selected +opt.trlorg = trlorg; +opt.fsample = fsample; +opt.artcol = [0.9686 0.7608 0.7686; 0.7529 0.7098 0.9647; 0.7373 0.9725 0.6824;0.8118 0.8118 0.8118; 0.9725 0.6745 0.4784; 0.9765 0.9176 0.5686; 0.6863 1 1; 1 0.6863 1]; +opt.chan_colors = chan_colors; +opt.cleanup = false; % this is needed for a corrent handling if the figure is closed (either in the corner or by "q") +if strcmp(cfg.continuous, 'yes') + opt.trialname = 'segment'; +else + opt.trialname = 'trial'; +end +guidata(h, opt); + +% make the user interface elements for the data view +uicontrol('tag', 'group1', 'parent', h, 'units', 'normalized', 'style', 'pushbutton', 'string', opt.trialname, 'userdata', 't') +uicontrol('tag', 'group2', 'parent', h, 'units', 'normalized', 'style', 'pushbutton', 'string', '<', 'userdata', 'leftarrow') +uicontrol('tag', 'group2', 'parent', h, 'units', 'normalized', 'style', 'pushbutton', 'string', '>', 'userdata', 'rightarrow') + +uicontrol('tag', 'group1', 'parent', h, 'units', 'normalized', 'style', 'pushbutton', 'string', 'channel','userdata', 'c') +uicontrol('tag', 'group2', 'parent', h, 'units', 'normalized', 'style', 'pushbutton', 'string', '<', 'userdata', 'uparrow') +uicontrol('tag', 'group2', 'parent', h, 'units', 'normalized', 'style', 'pushbutton', 'string', '>', 'userdata', 'downarrow') + +uicontrol('tag', 'group1a', 'parent', h, 'units', 'normalized', 'style', 'pushbutton', 'string', 'horizontal', 'userdata', 'h') +uicontrol('tag', 'group2a', 'parent', h, 'units', 'normalized', 'style', 'pushbutton', 'string', '-', 'userdata', 'shift+leftarrow') +uicontrol('tag', 'group2a', 'parent', h, 'units', 'normalized', 'style', 'pushbutton', 'string', '+', 'userdata', 'shift+rightarrow') +if strcmp(cfg.continuous, 'no') + uilayout(h, 'tag', 'group1a', 'visible', 'off', 'retag', 'group1'); + uilayout(h, 'tag', 'group2a', 'visible', 'off', 'retag', 'group2'); +else + uilayout(h, 'tag', 'group1a', 'visible', 'on', 'retag', 'group1'); + uilayout(h, 'tag', 'group2a', 'visible', 'on', 'retag', 'group2'); +end + +uicontrol('tag', 'group1', 'parent', h, 'units', 'normalized', 'style', 'pushbutton', 'string', 'vertical', 'userdata', 'v') +uicontrol('tag', 'group2', 'parent', h, 'units', 'normalized', 'style', 'pushbutton', 'string', '-', 'userdata', 'shift+downarrow') +uicontrol('tag', 'group2', 'parent', h, 'units', 'normalized', 'style', 'pushbutton', 'string', '+', 'userdata', 'shift+uparrow') + +% legend artifacts/features +for iArt = 1:length(artlabel) + uicontrol('tag', 'group3', 'parent', h, 'units', 'normalized', 'style', 'pushbutton', 'string', artlabel{iArt}, 'userdata', num2str(iArt), 'position', [0.91, 0.9 - ((iArt-1)*0.1), 0.08, 0.04], 'backgroundcolor', opt.artcol(iArt,:)) + uicontrol('tag', 'group3', 'parent', h, 'units', 'normalized', 'style', 'pushbutton', 'string', '<', 'userdata', ['shift+' num2str(iArt)], 'position', [0.91, 0.85 - ((iArt-1)*0.1), 0.03, 0.04], 'backgroundcolor', opt.artcol(iArt,:)) + uicontrol('tag', 'group3', 'parent', h, 'units', 'normalized', 'style', 'pushbutton', 'string', '>', 'userdata', ['control+' num2str(iArt)], 'position', [0.96, 0.85 - ((iArt-1)*0.1), 0.03, 0.04], 'backgroundcolor', opt.artcol(iArt,:)) +end + +if strcmp(cfg.viewmode, 'butterfly') + % button to find label of nearest channel to datapoint + uicontrol('tag', 'group3', 'parent', h, 'units', 'normalized', 'style', 'pushbutton', 'string', 'identify', 'userdata', 'i', 'position', [0.91, 0.1, 0.08, 0.05], 'backgroundcolor', [1 1 1]) +end + +uilayout(h, 'tag', 'group1', 'width', 0.10, 'height', 0.05); +uilayout(h, 'tag', 'group2', 'width', 0.05, 'height', 0.05); + +uilayout(h, 'tag', 'group1', 'style', 'pushbutton', 'callback', @keyboard_cb); +uilayout(h, 'tag', 'group2', 'style', 'pushbutton', 'callback', @keyboard_cb); +uilayout(h, 'tag', 'group3', 'style', 'pushbutton', 'callback', @keyboard_cb); + +uilayout(h, 'tag', 'group1', 'retag', 'viewui'); +uilayout(h, 'tag', 'group2', 'retag', 'viewui'); +uilayout(h, 'tag', 'viewui', 'BackgroundColor', [0.8 0.8 0.8], 'hpos', 'auto', 'vpos', 0.01); + +definetrial_cb(h); +redraw_cb(h); + +if nargout + % wait until the user interface is closed, get the user data with the updated artifact details + set(h, 'CloseRequestFcn', @cleanup_cb); + + while ishandle(h) + uiwait(h); + opt = guidata(h); + if opt.cleanup + delete(h); + end + end + + % add the updated artifact definitions to the output cfg + for i=1:length(opt.artdata.label) + cfg.artfctdef.(opt.artdata.label{i}).artifact = convert_event(opt.artdata.trial{1}(i,:), 'artifact'); + end +end % if nargout + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_databrowser.m 1430 2010-07-20 07:41:41Z roboos $'; + +% remember the configuration details of the input data +if hasdata && isfield(data, 'cfg') + cfg.previous = data.cfg; +end +% remember the exact configuration details in the output +dataout.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', dataout); % use the variable name "data" in the output file +end + +end % main function +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function cleanup_cb(h, eventdata) +opt = guidata(h); +opt.cleanup = true; +guidata(h, opt); +uiresume +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function definetrial_cb(h, eventdata) +opt = guidata(h); +if strcmp(opt.cfg.continuous, 'no') + % keep the original trial definition for visualisation + opt.trlvis = opt.trlorg; +else + % construct a trial definition for visualisation + if isfield(opt, 'trlvis') + thistrlbeg = opt.trlvis(opt.trlop,1); + thistrlend = opt.trlvis(opt.trlop,2); + % remember a representative sample of the current trial + % thissample = round((thistrlbeg+thistrlend)/2); + thissample = thistrlbeg; + end + % look at opt.cfg.blocksize and make opt.trl accordingly + % if original data contains more than one trial, it will fail in fetch_data + datbegsample = min(opt.trlorg(:,1)); + datendsample = max(opt.trlorg(:,2)); + smppertrl = round(opt.fsample * opt.cfg.blocksize); + begsamples = datbegsample:smppertrl:datendsample; + endsamples = datbegsample+smppertrl-1:smppertrl:datendsample; + if numel(endsamples) 1 || isempty(opt.orgdata) + % offset is now (re)defined that 1st sample is time 0 + trlvis(:,3) = begsamples-1; + else + % offset according to original time axis + trlvis(:,3) = opt.trlorg(3) + begsamples - opt.trlorg(1); + end + + if isfield(opt, 'trlvis') + % update the current trial counter and try to keep the current sample the same + % opt.trlop = nearest(round((begsamples+endsamples)/2), thissample); + opt.trlop = nearest(begsamples, thissample); + end + opt.trlvis = trlvis; +end % if continuous +guidata(h, opt); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function help_cb(h, eventdata) +fprintf('------------------------------------------------------------------------------------\n') +fprintf('You can use the following buttons in the data viewer\n') +fprintf('1-9 : select artifact number 1-9\n'); +fprintf('arrow-left : previous trial\n'); +fprintf('arrow-right : next trial\n'); +fprintf('shift arrow-up : increase vertical scaling\n'); +fprintf('shift arrow-down : decrease vertical scaling\n'); +fprintf('shift arrow-left : increase cfg.blocksize\n'); +fprintf('shift arrow-down : decrease cfg.blocksize\n'); +fprintf('q : quit\n'); +fprintf('------------------------------------------------------------------------------------\n') +fprintf('\n') +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function select_range_cb(range, h) %range 1X4 in sec relative to current trial +opt = guidata(h); + +switch opt.cfg.viewmode + case 'butterfly' + begsample = opt.trlvis(opt.trlop,1); + endsample = opt.trlvis(opt.trlop,2); + offset = opt.trlvis(opt.trlop,3); + % determine the selection + if strcmp(opt.trialname, 'trial') + % this is appropriate when the offset is defined according to a + % different trigger in each trial, which is usually the case in trial data + begsel = round(range(1)*opt.fsample+begsample-offset-1); + endsel = round(range(2)*opt.fsample+begsample-offset); + elseif strcmp(opt.trialname, 'segment') + % this is appropriate when the offset is defined according to a + % one trigger, which is always the case in segment data [I think ingnie] + begsel = round(range(1)*opt.fsample+1); + endsel = round(range(2)*opt.fsample+1); + end + % the selection should always be confined to the current trial + begsel = max(begsample, begsel); + endsel = min(endsample, endsel); + + case {'vertical', 'component'} + % the range should be in the displayed box + range(1) = max(opt.hpos(1), range(1)); + range(2) = max(opt.hpos(1), range(2)); + range(1) = min(opt.hpos(2), range(1)); + range(2) = min(opt.hpos(2), range(2)); + range = (range - opt.hpos(1)) / (opt.hpos(2) - opt.hpos(1)); % left side of the box becomes 0, right side becomes 1 + range = range * (opt.hlim(2) - opt.hlim(1)) + opt.hlim(1); % 0 becomes hlim(1), 1 becomes hlim(2) + + begsample = opt.trlvis(opt.trlop,1); + endsample = opt.trlvis(opt.trlop,2); + offset = opt.trlvis(opt.trlop,3); + % determine the selection + if strcmp(opt.trialname, 'trial') + % this is appropriate when the offset is defined according to a + % different trigger in each trial, which is usually the case in trial data + begsel = round(range(1)*opt.fsample+begsample-offset-1); + endsel = round(range(2)*opt.fsample+begsample-offset); + elseif strcmp(opt.trialname, 'segment') + % this is appropriate when the offset is defined according to + % one trigger, which is always the case in segment data [I think ingnie] + begsel = round(range(1)*opt.fsample+1); + endsel = round(range(2)*opt.fsample+1); + end + % the selection should always be confined to the current trial + begsel = max(begsample, begsel); + endsel = min(endsample, endsel); + + otherwise + error('unknown opt.cfg.viewmode "%s"', opt.cfg.viewmode); +end % switch + +if strcmp(opt.cfg.selectmode, 'disp') + % FIXME this is only for debugging + disp([begsel endsel]) + +elseif strcmp(opt.cfg.selectmode, 'mark') + % mark or unmark artifacts + artval = opt.artdata.trial{1}(opt.ftsel, begsel:endsel); + artval = any(artval,1); + if any(artval) + fprintf('there is overlap with the active artifact (%s), disable this artifact\n',opt.artdata.label{opt.ftsel}); + opt.artdata.trial{1}(opt.ftsel, begsel:endsel) = 0; + else + fprintf('there is no overlap with the active artifact (%s), mark this as a new artifact\n',opt.artdata.label{opt.ftsel}); + opt.artdata.trial{1}(opt.ftsel, begsel:endsel) = 1; + end + +elseif strcmp(opt.cfg.selectmode, 'eval') + % cut out the requested data segment + seldata.label = opt.curdat.label; + seldata.time{1} = offset2time(offset+begsel-begsample, opt.fsample, endsel-begsel+1); + seldata.trial{1} = fetch_data(opt.curdat, 'begsample', begsel, 'endsample', endsel); + seldata.fsample = opt.fsample; + seldata.cfg.trl = [begsel endsel offset]; + + feval(opt.cfg.selfun, opt.cfg.selcfg, seldata); + +else + error('unknown value for cfg.selectmode'); +end + +guidata(h, opt); +redraw_cb(h); +end % function + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function keyboard_cb(h, eventdata) +opt = guidata(h); + +if isempty(eventdata) + % determine the key that corresponds to the uicontrol element that was activated + key = get(h, 'userdata'); + h = getparent(h); +else + % determine the key that was pressed on the keyboard + key = eventdata.Key; + if ~isempty(eventdata.Modifier) + key = [eventdata.Modifier{1} '+' key]; + end +end + +switch key + case {'1' '2' '3' '4' '5' '6' '7' '8'} + % switch to another artifact type + opt.ftsel = str2double(key); + guidata(h, opt); + fprintf('switching to the "%s" artifact\n', opt.artdata.label{opt.ftsel}); + redraw_cb(h, eventdata); + case {'shift+1' 'shift+2' 'shift+3' 'shift+4' 'shift+5' 'shift+6' 'shift+7' 'shift+8'} + % go to previous artifact + opt.ftsel = str2double(key(end)); + cursam = opt.trlvis(opt.trlop,1); + artsam = find(opt.artdata.trial{1}(opt.ftsel,1:cursam-1), 1, 'last'); + if isempty(artsam) + fprintf('no earlier "%s" artifact found\n', opt.artdata.label{opt.ftsel}); + else + fprintf('going to previous "%s" artifact\n', opt.artdata.label{opt.ftsel}); + if opt.trlvis(nearest(opt.trlvis(:,1),artsam),1) < artsam + arttrl = nearest(opt.trlvis(:,1),artsam); + else + arttrl = nearest(opt.trlvis(:,1),artsam)-1; + end + opt.trlop = arttrl; + guidata(h, opt); + redraw_cb(h, eventdata); + end + case {'control+1' 'control+2' 'control+3' 'control+4' 'control+5' 'control+6' 'control+7' 'control+8'} + % go to next artifact + opt.ftsel = str2double(key(end)); + cursam = opt.trlvis(opt.trlop,2); + artsam = find(opt.artdata.trial{1}(opt.ftsel,cursam+1:end), 1, 'first') + cursam; + if isempty(artsam) + fprintf('no later "%s" artifact found\n', opt.artdata.label{opt.ftsel}); + else + fprintf('going to next "%s" artifact\n', opt.artdata.label{opt.ftsel}); + if opt.trlvis(nearest(opt.trlvis(:,1),artsam),1) < artsam + arttrl = nearest(opt.trlvis(:,1),artsam); + else + arttrl = nearest(opt.trlvis(:,1),artsam)-1; + end + opt.trlop = arttrl; + guidata(h, opt); + redraw_cb(h, eventdata); + end + case 'leftarrow' + opt.trlop = max(opt.trlop - 1, 1); % should not be smaller than 1 + guidata(h, opt); + redraw_cb(h, eventdata); + case 'rightarrow' + opt.trlop = min(opt.trlop + 1, size(opt.trlvis,1)); % should not be larger than the number of trials + guidata(h, opt); + redraw_cb(h, eventdata); + case 'uparrow' + chansel = match_str(opt.hdr.label, opt.cfg.channel); + minchan = min(chansel); + numchan = length(chansel); + chansel = minchan - numchan : minchan - 1; + if min(chansel)<1 + chansel = chansel - min(chansel) + 1; + end + % convert numeric array into cell-array with channel labels + opt.cfg.channel = opt.hdr.label(chansel); + disp(opt.cfg.channel); + guidata(h, opt); + redraw_cb(h, eventdata); + case 'downarrow' + chansel = match_str(opt.hdr.label, opt.cfg.channel); + maxchan = max(chansel); + numchan = length(chansel); + chansel = maxchan + 1 : maxchan + numchan; + if max(chansel)>length(opt.hdr.label) + chansel = chansel - (max(chansel) - length(opt.hdr.label)); + end + % convert numeric array into cell-array with channel labels + opt.cfg.channel = opt.hdr.label(chansel); + disp(opt.cfg.channel); + guidata(h, opt); + redraw_cb(h, eventdata); + case 'shift+leftarrow' + opt.cfg.blocksize = opt.cfg.blocksize*sqrt(2); + disp(opt.cfg.blocksize); + guidata(h, opt); + definetrial_cb(h, eventdata); + redraw_cb(h, eventdata); + case 'shift+rightarrow' + opt.cfg.blocksize = opt.cfg.blocksize/sqrt(2); + disp(opt.cfg.blocksize); + guidata(h, opt); + definetrial_cb(h, eventdata); + redraw_cb(h, eventdata); + case 'shift+uparrow' + opt.cfg.zscale = opt.cfg.zscale/sqrt(2); + guidata(h, opt); + redraw_cb(h, eventdata); + case 'shift+downarrow' + opt.cfg.zscale = opt.cfg.zscale*sqrt(2); + guidata(h, opt); + redraw_cb(h, eventdata); + case 'q' + guidata(h, opt); + cleanup_cb(h); + case 't' + % select the trial to display + response = inputdlg(sprintf('%s to display', opt.trialname), 'specify', 1, {num2str(opt.trlop)}); + if ~isempty(response) + opt.trlop = str2double(response); + opt.trlop = min(opt.trlop, size(opt.trlvis,1)); % should not be larger than the number of trials + opt.trlop = max(opt.trlop, 1); % should not be smaller than 1 + end + guidata(h, opt); + redraw_cb(h, eventdata); + case 'h' + % select the horizontal scaling + response = inputdlg('horizontal scale', 'specify', 1, {num2str(opt.cfg.blocksize)}); + if ~isempty(response) + opt.cfg.blocksize = str2double(response); + end + guidata(h, opt); + definetrial_cb(h, eventdata); + redraw_cb(h, eventdata); + case 'v' + % select the vertical scaling + response = inputdlg('vertical scale, number or ''maxabs'')', 'specify', 1, {num2str(opt.cfg.zscale)}); + if ~isempty(response) + if isnan(str2double(response)) && strcmp(response, 'maxabs') + minval = min(opt.curdat.trial{1}(:)); + maxval = max(opt.curdat.trial{1}(:)); + opt.cfg.zscale = max(abs([minval maxval])); + else + opt.cfg.zscale = str2double(response); + end + end + guidata(h, opt); + redraw_cb(h, eventdata); + case 'c' + % select channels + select = match_str(opt.hdr.label, opt.cfg.channel); + select = select_channel_list(opt.hdr.label, select); + opt.cfg.channel = opt.hdr.label(select); + guidata(h, opt); + redraw_cb(h, eventdata); + case 'i' + if strcmp(opt.cfg.viewmode, 'butterfly') + % click in data and get name of nearest channel + fprintf('click in the figure to identify the name of the closest channel\n'); + val = ginput(1); + channame = val2nearestchan(opt.curdat,val); + channb = match_str(opt.curdat.label,channame); + fprintf('channel name: %s\n',channame); + redraw_cb(h, eventdata); + hold on + xtext = opt.cfg.zscale - 0.1*opt.cfg.zscale; + ft_plot_text(val(1), xtext, channame, 'FontSize', 16); + plot(opt.curdat.time{1}, opt.curdat.trial{1}(channb,:),'k','LineWidth',2) + end + case 'control+control' + % do nothing + case 'shift+shift' + % do nothing + otherwise + guidata(h, opt); + help_cb(h); +end +uiresume(h); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function toggle_viewmode_cb(h, eventdata, varargin) +opt = guidata(getparent(h)); +if ~isempty(varargin) && ischar(varargin{1}) + opt.cfg.viewmode = varargin{1}; +end +guidata(getparent(h), opt); +redraw_cb(h); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function h = getparent(h) +p = h; +while p~=0 + h = p; + p = get(h, 'parent'); +end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function redraw_cb(h, eventdata) +h = getparent(h); +opt = guidata(h); +figure(h); % ensure that the calling figure is in the front +cla; % clear the content in the current axis + +fprintf('redrawing with viewmode %s\n', opt.cfg.viewmode); + +begsample = opt.trlvis(opt.trlop, 1); +endsample = opt.trlvis(opt.trlop, 2); +offset = opt.trlvis(opt.trlop, 3); +chanindx = match_str(opt.hdr.label, opt.cfg.channel); + +if ~isempty(opt.event) + % select only the events in the current time window + event = opt.event; + evtsample = [event(:).sample]; + event = event(evtsample>=begsample & evtsample<=endsample); +else + event = []; +end + +if isempty(opt.orgdata) + fprintf('reading data... '); + dat = ft_read_data(opt.cfg.datafile, 'header', opt.hdr, 'begsample', begsample, 'endsample', endsample, 'chanindx', chanindx, 'checkboundary', strcmp(opt.cfg.continuous, 'no'), 'dataformat', opt.cfg.dataformat, 'headerformat', opt.cfg.headerformat); +else + fprintf('fetching data... '); + dat = fetch_data(opt.orgdata, 'header', opt.hdr, 'begsample', begsample, 'endsample', endsample, 'chanindx', chanindx); +end +fprintf('done\n'); + +fprintf('fetching artifacts... '); +art = fetch_data(opt.artdata, 'begsample', begsample, 'endsample', endsample); +fprintf('done\n'); + +% apply preprocessing and determine the time axis +fprintf('preprocessing data... '); +[dat, lab, tim] = preproc(dat, opt.hdr.label(chanindx), opt.fsample, opt.cfg.preproc, offset); +fprintf('done\n'); + +opt.curdat.label = lab; +opt.curdat.time{1} = tim; +opt.curdat.trial{1} = dat; +opt.curdat.fsample = opt.fsample; +opt.curdat.cfg.trl = [begsample endsample offset]; + +% apply scaling to selected channels +if ~isempty(opt.cfg.megscale) + chansel = match_str(lab, ft_channelselection('MEG', lab)); + dat(chansel,:) = dat(chansel,:) .* opt.cfg.megscale; +end +if ~isempty(opt.cfg.eegscale) + chansel = match_str(lab, ft_channelselection('EEG', lab)); + dat(chansel,:) = dat(chansel,:) .* opt.cfg.eegscale; +end +if ~isempty(opt.cfg.eogscale) + chansel = match_str(lab, ft_channelselection('EOG', lab)); + dat(chansel,:) = dat(chansel,:) .* opt.cfg.eogscale; +end +if ~isempty(opt.cfg.ecgscale) + chansel = match_str(lab, ft_channelselection('ECG', lab)); + dat(chansel,:) = dat(chansel,:) .* opt.cfg.ecgscale; +end + +fprintf('plotting data... '); +switch opt.cfg.viewmode + case 'butterfly' + % to assure current feature is plotted on top + ordervec = 1:length(opt.artdata.label); + ordervec(opt.ftsel) = []; + ordervec(end+1) = opt.ftsel; + + for i = ordervec + tmp = diff([0 art(i,:) 0]); + artbeg = find(tmp==+1); + artend = find(tmp==-1) - 1; + for j=1:numel(artbeg) + ft_plot_box([tim(artbeg(j)) tim(artend(j)) -opt.cfg.zscale opt.cfg.zscale], 'facecolor', opt.artcol(i,:), 'edgecolor', 'none'); + end + end + + % plot a line with text for each event + for i=1:length(event) + try + eventstr = sprintf('%s=%d', event(i).type, event(i).value); + catch + eventstr = 'unknown'; + end + eventtim = (event(i).sample-begsample+offset)/opt.fsample; + ft_plot_line([eventtim eventtim], [-opt.cfg.zscale opt.cfg.zscale]); + ft_plot_text(eventtim, opt.cfg.zscale, eventstr); + end + set(gca,'ColorOrder',opt.chan_colors(chanindx,:)) % plot vector does not clear axis, therefore this is possible + % plot the data on top of the box + ft_plot_vector(tim, dat) + ax(1) = tim(1); + ax(2) = tim(end); + ax(3) = -opt.cfg.zscale; + ax(4) = opt.cfg.zscale; + axis(ax); + title(sprintf('%s %d, time from %g to %g s', opt.trialname, opt.trlop, tim(1), tim(end))); + xlabel('time'); + + case 'vertical' + tmpcfg = []; + tmpcfg.layout = 'vertical'; + tmpcfg.channel = opt.cfg.channel; + tmpcfg.skipcomnt = 'yes'; + tmpcfg.skipscale = 'yes'; + laytime = ft_prepare_layout(tmpcfg, opt.orgdata); + + hlim = [tim(1) tim(end)]; + vlim = [-opt.cfg.zscale +opt.cfg.zscale]; + + % determine the position of each of the labels + labelx = laytime.pos(:,1) - laytime.width/2 - 0.01; + labely = laytime.pos(:,2); + + ax(1) = min(laytime.pos(:,1) - laytime.width/2); + ax(2) = max(laytime.pos(:,1) + laytime.width/2); + ax(3) = min(laytime.pos(:,2) - laytime.height/2); + ax(4) = max(laytime.pos(:,2) + laytime.height/2); + axis(ax) + + % remember the scaling of the horizontal axis, this is needed for mouse input + hpos(1) = laytime.pos(1,1) - laytime.width(1)/2; % the position of the left side of the timecourse box + hpos(2) = laytime.pos(1,1) + laytime.width(1)/2; % the position of the right side of the timecourse box + opt.hlim = hlim; + opt.hpos = hpos; + + % to assure current feature is plotted on top + ordervec = 1:length(opt.artdata.label); + ordervec(opt.ftsel) = []; + ordervec(end+1) = opt.ftsel; + + for j = ordervec + tmp = diff([0 art(j,:) 0]); + artbeg = find(tmp==+1); + artend = find(tmp==-1) - 1; + arttim = [tim(artbeg)' tim(artend)']; % convert the artifact sample number to time + arttim = (arttim - opt.hlim(1)) / (opt.hlim(2) - opt.hlim(1)); % convert to value relative to box, i.e. from 0 to 1 + arttim = arttim * (opt.hpos(2) - opt.hpos(1)) + opt.hpos(1); % convert from relative to actual value along the horizontal figure axis + + for k=1:numel(artbeg) + ft_plot_box([arttim(k,1) arttim(k,2) ax(3) ax(4)], 'facecolor', opt.artcol(j,:), 'edgecolor', 'none'); + end + end % for each of the artifact channels + + for i = 1:length(chanindx) + datsel = i; + laysel = match_str(laytime.label, opt.hdr.label(chanindx(i))); + if ~isempty(datsel) + ft_plot_text(labelx(laysel), labely(laysel), opt.hdr.label(chanindx(i)), 'HorizontalAlignment', 'right'); + ft_plot_vector(tim, dat(datsel, :), 'hpos', laytime.pos(laysel,1), 'vpos', laytime.pos(laysel,2), 'width', laytime.width(laysel), 'height', laytime.height(laysel), 'hlim', hlim, 'vlim', vlim, 'box', false, 'color', opt.chan_colors(chanindx(i),:)); + end + end + + nticks = 11; + set(gca, 'xTick', linspace(ax(1), ax(2), nticks)) + xTickLabel = cellstr(num2str( linspace(tim(1), tim(end), nticks)' , '%1.2f'))'; + set(gca, 'xTickLabel', xTickLabel) + set(gca, 'yTick', []) + title(sprintf('%s %d, time from %g to %g s', opt.trialname, opt.trlop, tim(1), tim(end))); + + case 'component' + compindx = chanindx; + clear chanindx + + tmpcfg = []; + tmpcfg.layout = 'vertical'; + tmpcfg.channel = opt.cfg.channel; + tmpcfg.skipcomnt = 'yes'; + tmpcfg.skipscale = 'yes'; + laytime = ft_prepare_layout(tmpcfg, opt.orgdata); + + tmpcfg = []; + tmpcfg.layout = opt.cfg.layout; + laychan = ft_prepare_layout(tmpcfg, opt.orgdata); + + % determine the position of each of the topographies + laytopo.pos(:,1) = laytime.pos(:,1) - laytime.width/2 - laytime.height*2; + laytopo.pos(:,2) = laytime.pos(:,2); + laytopo.width = laytime.height; + laytopo.height = laytime.height; + laytopo.label = laytime.label; + + % determine the position of each of the labels + labelx = laytopo.pos(:,1) + laytopo.width; + labely = laytopo.pos(:,2); + + hlim = [tim(1) tim(end)]; + vlim = [-opt.cfg.zscale +opt.cfg.zscale]; + + [sel1, sel2] = match_str(opt.orgdata.topolabel, laychan.label); + chanx = laychan.pos(sel2,1); + chany = laychan.pos(sel2,2); + + for i=1:length(compindx) + datsel = i; + laysel = match_str(laytime.label,opt.hdr.label(compindx(i))); + if ~isempty(datsel) + ft_plot_text(labelx(laysel), labely(laysel), opt.hdr.label(compindx(i))); + % plot the timecourse of this component + ft_plot_vector(tim, dat(datsel, :), 'hpos', laytime.pos(laysel,1), 'vpos', laytime.pos(laysel,2), 'width', laytime.width(laysel), 'height', laytime.height(laysel), 'hlim', hlim, 'vlim', vlim); + % plot the topography of this component + chanz = opt.orgdata.topo(sel1,compindx(i)); + ft_plot_topo(chanx, chany, chanz, 'mask', laychan.mask, 'outline', laychan.outline, 'hpos', laytopo.pos(laysel,1), 'vpos', laytopo.pos(laysel,2), 'width', laytopo.width(laysel), 'height', laytopo.height(laysel)); + axis equal + drawnow + end + end + set(gca, 'xTick', []) + set(gca, 'yTick', []) + title(sprintf('%s %d, time from %g to %g s', opt.trialname, opt.trlop, tim(1), tim(end))); + + ax(1) = min(laytopo.pos(:,1) - laytopo.width/2); + ax(2) = max(laytime.pos(:,1) + laytime.width/2); + ax(3) = min(laytime.pos(:,2) - laytime.height/2); + ax(4) = max(laytime.pos(:,2) + laytime.height/2); + axis(ax) + + % remember the scaling of the horizontal axis, this is needed for mouse input + hpos(1) = laytime.pos(1,1) - laytime.width(1)/2; % the position of the left side of the timecourse box + hpos(2) = laytime.pos(1,1) + laytime.width(1)/2; % the position of the right side of the timecourse box + opt.hlim = hlim; + opt.hpos = hpos; + + case 'settings' + % FIXME implement further details + + otherwise + error('unknown viewmode "%s"', opt.cfg.viewmode); +end % switch viewmode +fprintf('done\n'); + +guidata(h, opt); +end diff --git a/external/fieldtrip/ft_definetrial.m b/external/fieldtrip/ft_definetrial.m index b84b9b2..e34bae0 100644 --- a/external/fieldtrip/ft_definetrial.m +++ b/external/fieldtrip/ft_definetrial.m @@ -1,11 +1,166 @@ -function varargout = funname(varargin); +function [cfg] = ft_definetrial(cfg); -% this is a SPM wrapper around a FieldTrip function +% FT_DEFINETRIAL defines the trials, i.e. the pieces of data that will be read +% in for preprocessing. Trials are defined by their begin and end sample +% in the data file and each trial has an offset that defines where the +% relative t=0 point (usually the point of the trigger) is for that trial. +% +% Use as +% [cfg] = ft_definetrial(cfg) +% where the configuration structure should contain either +% cfg.trialdef = structure with details of trial definition, see below +% cfg.trialfun = function name, see below +% +% A call to FT_DEFINETRIAL results in the trial definition "trl" being added +% to the output configuration structure. The trials are defined according +% to the triggers, trials or other events in the data, or from a +% user-specified Matlab function which returns "trl". +% +% The trial definition "trl" is an Nx3 matrix, N is the number of trials. +% The first column contains the sample-indices of the begin of each trial +% relative to the begin of the raw data, the second column contains the +% sample-indices of the end of each trial, and the third column contains +% the offset of the trigger with respect to the trial. An offset of 0 +% means that the first sample of the trial corresponds to the trigger. A +% positive offset indicates that the first sample is later than the trigger, +% a negative offset indicates that the trial begins before the trigger. +% +% Simple trial definitions (e.g. based on a trigger alone) are supported by +% FT_DEFINETRIAL itself. For this, the general and data format independent way +% of handling trials is by relying on the FT_READ_EVENT function to +% collect all event information (such as triggers) from your dataset and +% select trials based on those events. This is implemented in FT_DEFINETRIAL as +% cfg.trialdef.eventtype = 'string' +% cfg.trialdef.eventvalue = number, string or list with numbers or strings +% cfg.trialdef.prestim = number, latency in seconds (optional) +% cfg.trialdef.poststim = number, latency in seconds (optional) +% +% If you specify cfg.trialdef.eventtype = '?' a list with the events in your +% data file will be displayed on screen. +% +% However, there are also many other complex ways in which you can define +% data pieces of interest, for example based on a conditional sequence of +% events (e.g. stimulus trigger followed by a correct response). For those +% cases, a general mechanism has been implemented through which you can +% supply your own trial-defining function, the 'trialfun'. +% +% This 'trialfun' is a string containing the name of a function that you +% have to write yourself. The function should take the cfg-structure as +% input and should give a Nx3 matrix in the same format as "trl" as the +% output. You can add extra custom fields to the configuration structure to +% pass as arguments to your own trialfun. Furthermore, inside the trialfun +% you can use the FT_READ_EVENT function to get the event information +% from your data file. +% +% See also FT_PREPROCESSING, FT_READ_HEADER, FT_READ_DATA, FT_READ_EVENT -% this part is variable -prefix = 'ft_'; +% Undocumented local options: +% cfg.datafile +% cfg.dataset +% cfg.event +% cfg.trl +% cfg.version -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +% Copyright (c) 2003, Robert Oostenveld, F.C. Donders Centre +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_definetrial.m 948 2010-04-21 18:02:21Z roboos $ + +fieldtripdefs + +% check if the input cfg is valid for this function +cfg = checkconfig(cfg, 'trackconfig', 'on'); +cfg = checkconfig(cfg, 'dataset2files', {'yes'}); + +if ~isfield(cfg, 'trl') && (~isfield(cfg, 'trialfun') || isempty(cfg.trialfun)) + % there used to be other system specific trialfuns in previous versions + % of fieldtrip, but they are deprecated and not included in recent + % versions any more + cfg.trialfun = 'trialfun_general'; + warning('no trialfun was specified, using trialfun_general'); +end + +% create the trial definition for this dataset and condition +if isfield(cfg, 'trl') + % the trial definition is already part of the configuration + fprintf('retaining exist trial definition\n'); + trl = cfg.trl; + if isfield(cfg, 'event') + fprintf('retaining exist event information\n'); + event = cfg.event; + else + event = []; + end +elseif isfield(cfg, 'trialfun') + % evaluate the user-defined function that gives back the trial definition + fprintf('evaluating trialfunction ''%s''\n', cfg.trialfun); + % determine the number of outpout arguments of the user-supplied trial function + try + % the nargout function in Matlab 6.5 and older does not work on function handles + num = nargout(cfg.trialfun); + catch + num = 1; + end + if num==1 + % the user-defined function only gives back the trial definition + trl = feval(cfg.trialfun, cfg); + event = []; + else + % the user-defined function also gives back detailed information about + % conditions, reaction time or any other information + [trl, event] = feval(cfg.trialfun, cfg); + end +else + error('no trialfunction specified, see DEFINETRIAL for help'); +end + +if isfield(cfg, 'trialdef') && isfield(cfg.trialdef, 'eventtype') && strcmp(cfg.trialdef.eventtype, '?') + % give a gentle message instead of an error + fprintf('no trials have been defined yet, see DEFINETRIAL for further help\n'); +elseif size(trl,1)<1 + error('no trials were defined, see DEFINETRIAL for help'); +end + +% add the new trials and events to the output configuration +fprintf('found %d events\n', length(event)); +cfg.event = event; +fprintf('created %d trials\n', size(trl,1)); +cfg.trl = trl; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add information about the version of this function to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i1] = dbstack; + cfg.version.name = st(i1); +end +cfg.version.id = '$Id: ft_definetrial.m 948 2010-04-21 18:02:21Z roboos $'; + +% % remember the exact configuration details in the output +% cfgtmp = cfg; +% cfg = []; +% try cfg.trl = cfgtmp.trl; end +% try cfg.dataset = cfgtmp.dataset; end +% try cfg.datafile = cfgtmp.datafile; end +% try cfg.headerfile = cfgtmp.headerfile; end +% cfg.previous = cfgtmp; diff --git a/external/fieldtrip/ft_denoise_sns.m b/external/fieldtrip/ft_denoise_sns.m deleted file mode 100644 index b84b9b2..0000000 --- a/external/fieldtrip/ft_denoise_sns.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'ft_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_denoise_synthetic.m b/external/fieldtrip/ft_denoise_synthetic.m index b84b9b2..d65e42a 100644 --- a/external/fieldtrip/ft_denoise_synthetic.m +++ b/external/fieldtrip/ft_denoise_synthetic.m @@ -1,11 +1,134 @@ -function varargout = funname(varargin); +function [data] = ft_denoise_synthetic(cfg, data); -% this is a SPM wrapper around a FieldTrip function +% FT_DENOISE_SYNTHETIC computes CTF higher-order synthetic gradients for +% preprocessed data and for the corresponding gradiometer definition. +% +% Use as +% [data] = ft_denoise_synthetic(cfg, data); +% +% where data should come from FT_PREPROCESSING and the configuration should contain +% cfg.gradient = 'none', 'G1BR', 'G2BR' or 'G3BR' specifies the gradiometer +% type to which the data should be changed +% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') +% +% See also FT_PREPROCESSING, FT_DENOISE_SNS, FT_DENOISE_TSR, FT_DENOISE_PCA +% +% Undocumented local options: +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk -% this part is variable -prefix = 'ft_'; +% Copyright (C) 2004-2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_denoise_synthetic.m 1386 2010-07-09 11:29:38Z jansch $ -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +fieldtripdefs + +% set the defaults +if ~isfield(cfg, 'gradient'), error('cfg.gradient must be specified'); end +if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +% load optional given inputfile as data +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + end +end + +data = checkdata(data, 'datatype', 'raw', 'feedback', 'yes', 'hastrialdef', 'yes'); + +if ~ft_senstype(data, 'ctf') + error('synthetic gradients can only be computed for CTF data'); +end + +% select trials of interest +if ~strcmp(cfg.trials, 'all') + fprintf('selecting %d trials\n', length(cfg.trials)); + data = selectdata(data, 'rpt', cfg.trials); +end + +% remember the original channel ordering +labelorg = data.label; + +% apply the balancing to the MEG data and to the gradiometer definition +current = data.grad.balance.current; +desired = cfg.gradient; + +if ~strcmp(current, 'none') + % first undo/invert the previously applied balancing + try + current_montage = getfield(data.grad.balance, data.grad.balance.current); + catch + error('unknown balancing for input data'); + end + fprintf('converting from "%s" to "none"\n', current); + data.grad = ft_apply_montage(data.grad, current_montage, 'keepunused', 'yes', 'inverse', 'yes'); + data = ft_apply_montage(data , current_montage, 'keepunused', 'yes', 'inverse', 'yes'); + data.grad.balance.current = 'none'; +end % if + +if ~strcmp(desired, 'none') + % then apply the desired balancing + try + desired_montage = getfield(data.grad.balance, cfg.gradient); + catch + error('unknown balancing for input data'); + end + fprintf('converting from "none" to "%s"\n', desired); + data.grad = ft_apply_montage(data.grad, desired_montage, 'keepunused', 'yes'); + data = ft_apply_montage(data , desired_montage, 'keepunused', 'yes'); + data.grad.balance.current = desired; +end % if + +% reorder the channels to stay close to the original ordering +[selorg, selnew] = match_str(labelorg, data.label); +if numel(selnew)==numel(labelorg) + for i=1:numel(data.trial) + data.trial{i} = data.trial{i}(selnew,:); + end + data.label = data.label(selnew); +else + warning('channel ordering might have changed'); +end + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_denoise_synthetic.m 1386 2010-07-09 11:29:38Z jansch $'; + + % remember the configuration details of the input data +try, cfg.previous = data.cfg; end +% remember the exact configuration details in the output +data.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', data); % use the variable name "data" in the output file +end diff --git a/external/fieldtrip/ft_denoise_tsr.m b/external/fieldtrip/ft_denoise_tsr.m deleted file mode 100644 index b84b9b2..0000000 --- a/external/fieldtrip/ft_denoise_tsr.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'ft_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_dipolefitting.m b/external/fieldtrip/ft_dipolefitting.m index b84b9b2..f107f62 100644 --- a/external/fieldtrip/ft_dipolefitting.m +++ b/external/fieldtrip/ft_dipolefitting.m @@ -1,11 +1,586 @@ -function varargout = funname(varargin); +function [source] = ft_dipolefitting(cfg, data) -% this is a SPM wrapper around a FieldTrip function +% FT_DIPOLEFITTING perform grid search and non-linear fit with one or multiple +% dipoles and try to find the location where the dipole model is best able +% to explain the measured EEG or MEG topography. +% +% This function will initially scan the whole brain with a single dipole on +% a regular coarse grid, and subsequently start at the most optimal location +% with a non-linear search. Alternatively you can specify the initial +% location of the dipole(s) and the non-linear search will start from there. +% +% Use as +% [source] = ft_dipolefitting(cfg, data) +% +% The configuration has the following general fields +% cfg.numdipoles = number, default is 1 +% cfg.symmetry = 'x', 'y' or 'z' symmetry for two dipoles, can be empty (default = []) +% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), +% see FT_CHANNELSELECTION for details +% cfg.gridsearch = 'yes' or 'no', perform global search for initial +% guess for the dipole parameters (default = 'yes') +% cfg.nonlinear = 'yes' or 'no', perform nonlinear search for optimal +% dipole parameters (default = 'yes') +% +% You should specify the volume conductor model with +% cfg.hdmfile = string, file containing the volume conduction model +% or alternatively +% cfg.vol = structure with volume conduction model +% If the sensor information is not contained in the data itself you should +% also specify the sensor information using +% cfg.gradfile = string, file containing the gradiometer definition +% cfg.elecfile = string, file containing the electrode definition +% or alternatively +% cfg.grad = structure with gradiometer definition +% cfg.elec = structure with electrode definition +% +% If you start with a grid search, you should specify the grid locations at +% which a test dipole will be placed. The positions of the dipoles can be +% specified as a regular 3-D grid that is aligned with the axes of the head +% coordinate system +% cfg.grid.xgrid = vector (e.g. -20:1:20) or 'auto' (default = 'auto') +% cfg.grid.ygrid = vector (e.g. -20:1:20) or 'auto' (default = 'auto') +% cfg.grid.zgrid = vector (e.g. 0:1:20) or 'auto' (default = 'auto') +% cfg.grid.resolution = number (e.g. 1 cm) for automatic grid generation +% Alternatively a complete grid with dipole positions and precomputed +% leadfields can be specified +% cfg.grid = structure, see FT_PREPARE_LEADFIELD +% or the position of a few dipoles at locations of interest can be +% specified, for example obtained from an anatomical or functional MRI +% cfg.grid.pos = Nx3 matrix with position of each source +% cfg.grid.dim = [Nx Ny Nz] vector with dimensions in case of 3-D grid (optional) +% cfg.grid.inside = vector with indices of the sources inside the brain (optional) +% cfg.grid.outside = vector with indices of the sources outside the brain (optional) +% +% If you do not start with a grid search, you have to give a starting location +% for the nonlinear search +% cfg.dip.pos = initial dipole position, matrix of Ndipoles x 3 +% +% The conventional approach is to fit dipoles to event-related averages, which +% within fieldtrip can be obtained from the FT_TIMELOCKANALYSIS or from +% the FT_TIMELOCKGRANDAVERAGE function. This has the additional options +% cfg.latency = [begin end] in seconds or 'all' (default = 'all') +% cfg.model = 'moving' or 'regional' +% A moving dipole model has a different position (and orientation) for each +% timepoint, or for each component. A regional dipole model has the same +% position for each timepoint or component, and a different orientation. +% +% You can also fit dipoles to the spatial topographies of an independent +% component analysis, obtained from the FT_COMPONENTANALYSIS function. +% This has the additional options +% cfg.component = array with numbers (can be empty -> all) +% +% You can also fit dipoles to the spatial topographies that are present +% in the data in the frequency domain, which can be obtained using the +% FT_FREQANALYSIS function. This has the additional options +% cfg.frequency = single number (in Hz) +% +% Low level details of the fitting can be specified in the cfg.dipfit structure +% cfg.dipfit.display = level of display, can be 'off', 'iter', 'notify' or 'final' (default = 'iter') +% cfg.dipfit.optimfun = function to use, can be 'fminsearch' or 'fminunc' (default is determined automatic) +% cfg.dipfit.maxiter = maximum number of function evaluations allowed (default depends on the optimfun) +% +% See also FT_SOURCEANALYSIS, FT_PREPARE_LEADFIELD -% this part is variable -prefix = 'ft_'; +% TODO change the output format, more suitable would be something like: +% dip.label +% dip.time +% dip.avg (instead of Vdata) +% dip.dip.pos +% dip.dip.mom +% dip.dip.model, or dip.dip.avg +% dip.dimord + +% Undocumented local options: +% cfg.dipfit.constr = Source model constraints, depends on cfg.symmetry +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk +% +% This function depends on FT_PREPARE_DIPOLE_GRID which has the following options: +% cfg.grid.xgrid (default set in FT_PREPARE_DIPOLE_GRID: cfg.grid.xgrid = 'auto'), documented +% cfg.grid.ygrid (default set in FT_PREPARE_DIPOLE_GRID: cfg.grid.ygrid = 'auto'), documented +% cfg.grid.zgrid (default set in FT_PREPARE_DIPOLE_GRID: cfg.grid.zgrid = 'auto'), documented +% cfg.grid.resolution, documented +% cfg.grid.pos, documented +% cfg.grid.dim, documented +% cfg.grid.inside, documented +% cfg.grid.outside, documented +% cfg.symmetry, documented +% cfg.mri +% cfg.mriunits +% cfg.smooth +% cfg.sourceunits +% cfg.threshold +% +% This function depends on FT_PREPARE_VOL_SENS which has the following options: +% cfg.channel (default set in FT_DIPOLEFITTING: cfg.channel = 'all'), documented +% cfg.elec, documented +% cfg.elecfile, documented +% cfg.grad, documented +% cfg.gradfile, documented +% cfg.hdmfile, documented +% cfg.order +% cfg.vol, documented + +% Copyright (C) 2004-2006, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_dipolefitting.m 1258 2010-06-22 08:33:48Z timeng $ + +fieldtripdefs +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +% set the defaults +if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end +if ~isfield(cfg, 'component'), cfg.component = []; end % for comp input +if ~isfield(cfg, 'frequency'), cfg.frequency = []; end % for freq input +if ~isfield(cfg, 'latency'), cfg.latency = 'all'; end +if ~isfield(cfg, 'feedback'), cfg.feedback = 'text'; end +if ~isfield(cfg, 'gridsearch'), cfg.gridsearch = 'yes'; end +if ~isfield(cfg, 'nonlinear'), cfg.nonlinear = 'yes'; end +if ~isfield(cfg, 'symmetry'), cfg.symmetry = []; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +% load optional given inputfile as data +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + end +end + +% check if the input data is valid for this function +data = checkdata(data, 'datatype', {'timelock', 'freq', 'comp'}, 'feedback', 'yes'); + +% put the low-level options pertaining to the dipole grid (used for initial scanning) in their own field +cfg = checkconfig(cfg, 'createsubcfg', {'grid'}); + +% the default for this depends on the data type +if ~isfield(cfg, 'model'), + if ~isempty(cfg.component) + % each component is fitted independently + cfg.model = 'moving'; + elseif ~isempty(cfg.latency) + % fit the data with a dipole at one location + cfg.model = 'regional'; + elseif ~isempty(cfg.latency) + % fit the data with a dipole at one location + cfg.model = 'regional'; + end +end + +if ~isfield(cfg, 'numdipoles') + if isfield(cfg, 'dip') + cfg.numdipoles = size(cfg.dip(1).pos,1); + else + cfg.numdipoles = 1; + end +end + +% set up the symmetry constraints +if ~isempty(cfg.symmetry) + if cfg.numdipoles~=2 + error('symmetry constraints are only supported for two-dipole models'); + elseif strcmp(cfg.symmetry, 'x') + % this structure is passed onto the low-level ft_dipole_fit function + cfg.dipfit.constr.reduce = [1 2 3]; % select the parameters [x1 y1 z1] + cfg.dipfit.constr.expand = [1 2 3 1 2 3]; % repeat them as [x1 y1 z1 x1 y1 z1] + cfg.dipfit.constr.mirror = [1 1 1 -1 1 1]; % multiply each of them with 1 or -1, resulting in [x1 y1 z1 -x1 y1 z1] + elseif strcmp(cfg.symmetry, 'y') + % this structure is passed onto the low-level ft_dipole_fit function + cfg.dipfit.constr.reduce = [1 2 3]; % select the parameters [x1 y1 z1] + cfg.dipfit.constr.expand = [1 2 3 1 2 3]; % repeat them as [x1 y1 z1 x1 y1 z1] + cfg.dipfit.constr.mirror = [1 1 1 1 -1 1]; % multiply each of them with 1 or -1, resulting in [x1 y1 z1 x1 -y1 z1] + elseif strcmp(cfg.symmetry, 'z') + % this structure is passed onto the low-level ft_dipole_fit function + cfg.dipfit.constr.reduce = [1 2 3]; % select the parameters [x1 y1 z1] + cfg.dipfit.constr.expand = [1 2 3 1 2 3]; % repeat them as [x1 y1 z1 x1 y1 z1] + cfg.dipfit.constr.mirror = [1 1 1 1 1 -1]; % multiply each of them with 1 or -1, resulting in [x1 y1 z1 x1 y1 -z1] + else + error('unrecognized symmetry constraint'); + end +elseif ~isfield(cfg, 'dipfit') || ~isfield(cfg.dipfit, 'constr') + % no symmetry constraints have been specified + cfg.dipfit.constr = []; +end + +if isfield(data, 'topolabel') + % this looks like a component analysis + iscomp = 1; + % transform the data into a representation on which the timelocked dipole fit can perform its trick + data = comp2timelock(cfg, data); +else + iscomp = 0; +end + +if isfield(data, 'freq') + % this looks like a frequency analysis + isfreq = 1; + % transform the data into a representation on which the timelocked dipole fit can perform its trick + data = freq2timelock(cfg, data); +else + isfreq = 0; +end + +% prepare the volume conduction model and the sensor array +% this updates the configuration with the appropriate fields +[vol, sens, cfg] = prepare_headmodel(cfg, data); + +% select the desired channels, the order should be the same as in the sensor structure +[selsens, seldata] = match_str(sens.label, data.label); +Vdata = data.avg(seldata, :); + +if iscomp + % select the desired component topographies + Vdata = Vdata(:, cfg.component); +elseif isfreq + % the desired frequency topographies have already been selected + Vdata = Vdata(:, :); +else + % select the desired latencies + if ischar(cfg.latency) && strcmp(cfg.latency, 'all') + cfg.latency = data.time([1 end]); + end + tbeg = nearest(data.time, cfg.latency(1)); + tend = nearest(data.time, cfg.latency(end)); + cfg.latency = [data.time(tbeg) data.time(tend)]; + Vdata = Vdata(:, tbeg:tend); +end + +nchans = size(Vdata,1); +ntime = size(Vdata,2); +Vmodel = zeros(nchans, ntime); +fprintf('selected %d channels\n', nchans); +fprintf('selected %d topographies\n', ntime); + +if nchans0.001) + warning('the EEG data is not average referenced, correcting this'); + end + Vdata = avgref(Vdata); +end + +% set to zeros if no initial dipole was specified +if ~isfield(cfg, 'dip') + cfg.dip.pos = zeros(cfg.numdipoles, 3); + cfg.dip.mom = zeros(3*cfg.numdipoles, 1); +end + +% set to zeros if no initial dipole position was specified +if ~isfield(cfg.dip, 'pos') + cfg.dip.pos = zeros(cfg.numdipoles, 3); +end + +% set to zeros if no initial dipole moment was specified +if ~isfield(cfg.dip, 'mom') + cfg.dip.mom = zeros(3*cfg.numdipoles, 1); +end + +% check the specified dipole model +if numel(cfg.dip.pos)~=cfg.numdipoles*3 || numel(cfg.dip.mom)~=cfg.numdipoles*3 + error('inconsistent number of dipoles in configuration') +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% perform the dipole scan, this is usefull for generating an initial guess +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +if strcmp(cfg.gridsearch, 'yes') + % test whether we have a valid configuration for dipole scanning + if cfg.numdipoles==1 + % this is ok + elseif cfg.numdipoles==2 && ~isempty(cfg.dipfit.constr) + % this is also ok + else + error('dipole scanning is only possible for a single dipole or a symmetric dipole pair'); + end + + % construct the grid on which the scanning will be done + [grid, cfg] = prepare_dipole_grid(cfg, vol, sens); + progress('init', cfg.feedback, 'scanning grid'); + for i=1:length(grid.inside) + progress(i/length(grid.inside), 'scanning grid location %d/%d\n', i, length(grid.inside)); + indx = grid.inside(i); + if isfield(grid, 'leadfield') + % reuse the previously computed leadfield + lf = grid.leadfield{indx}; + else + lf = ft_compute_leadfield(grid.pos(indx,:), sens, vol); + end + % the model is V=lf*mom+noise, therefore mom=pinv(lf)*V estimates the + % dipole moment this makes the model potential U=lf*pinv(lf)*V and the + % model error is norm(V-U) = norm(V-lf*pinv(lf)*V) = norm((eye-lf*pinv(lf))*V) + switch cfg.model + case 'regional' + % sum the error over all latencies + grid.error(indx,1) = sum(sum(((eye(nchans)-lf*pinv(lf))*Vdata).^2)); + case 'moving' + % remember the error for each latency independently + grid.error(indx,:) = sum(((eye(nchans)-lf*pinv(lf))*Vdata).^2); + otherwise + error('unsupported cfg.model'); + end % switch model + end % looping over the grid + progress('close'); + + switch cfg.model + case 'regional' + % find the grid point(s) with the minimum error + [err, indx] = min(grid.error(grid.inside)); + dip.pos = grid.pos(grid.inside(indx),:); % note that for a symmetric dipole pair this results in a vector + dip.pos = reshape(dip.pos, cfg.numdipoles, 3); % convert to a Nx3 array + dip.mom = zeros(cfg.numdipoles*3,1); % set the dipole moment to zero + if cfg.numdipoles==1 + fprintf('found minimum after scanning on grid point [%g %g %g]\n', dip.pos(1), dip.pos(2), dip.pos(3)); + elseif cfg.numdipoles==2 + fprintf('found minimum after scanning on grid point [%g %g %g; %g %g %g]\n', dip.pos(1), dip.pos(2), dip.pos(3), dip.pos(4), dip.pos(5), dip.pos(6)); + end + case 'moving' + for t=1:ntime + % find the grid point(s) with the minimum error + [err, indx] = min(grid.error(grid.inside,t)); + dip(t).pos = grid.pos(grid.inside(indx),:); % note that for a symmetric dipole pair this results in a vector + dip(t).pos = reshape(dip(t).pos, cfg.numdipoles, 3); % convert to a Nx3 array + dip(t).mom = zeros(cfg.numdipoles*3,1); % set the dipole moment to zero + if cfg.numdipoles==1 + fprintf('found minimum after scanning for topography %d on grid point [%g %g %g]\n', t, dip(t).pos(1), dip(t).pos(2), dip(t).pos(3)); + elseif cfg.numdipoles==2 + fprintf('found minimum after scanning for topography %d on grid point [%g %g %g; %g %g %g]\n', t, dip(t).pos(1), dip(t).pos(2), dip(t).pos(3), dip(t).pos(4), dip(t).pos(5), dip(t).pos(6)); + end + end + otherwise + error('unsupported cfg.model'); + end % switch model +end % if gridsearch + +if strcmp(cfg.gridsearch, 'no') + % use the initial guess supplied in the configuration for the remainder + switch cfg.model + case 'regional' + dip = struct(cfg.dip); + case 'moving' + for t=1:ntime + dip(t) = struct(cfg.dip); + end + otherwise + error('unsupported cfg.model'); + end % switch model +end + +% multiple dipoles can be represented either as a 1x(N*3) vector or as a Nx3 matrix, +% i.e. [x1 y1 z1 x2 y2 z2] or [x1 y1 z1; x2 y2 z2] +switch cfg.model + case 'regional' + dip = fixdipole(dip); + case 'moving' + for t=1:ntime + dip(t) = fixdipole(dip(t)); + end + otherwise + error('unsupported cfg.model'); +end % switch model + +if isfield(cfg, 'dipfit') + % convert the structure with the additional low-level options into key-value pairs + optarg = cfg2keyval(getfield(cfg, 'dipfit')); +else + % no additional low-level options were specified + optarg = {}; +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% perform the non-linear fit +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +if strcmp(cfg.nonlinear, 'yes') + switch cfg.model + case 'regional' + % perform the non-linear dipole fit for all latencies together + % catch errors due to non-convergence + try + dip = dipole_fit(dip, sens, vol, Vdata, optarg{:}); + success = 1; + if cfg.numdipoles==1 + fprintf('found minimum after non-linear optimization on [%g %g %g]\n', dip.pos(1), dip.pos(2), dip.pos(3)); + elseif cfg.numdipoles==2 + fprintf('found minimum after non-linear optimization on [%g %g %g; %g %g %g]\n', dip.pos(1,1), dip.pos(1,2), dip.pos(1,3), dip.pos(2,1), dip.pos(2,2), dip.pos(2,3)); + end + catch + success = 0; + disp(lasterr); + end + case 'moving' + % perform the non-linear dipole fit for each latency independently + % instead of using dip(t) = ft_dipole_fit(dip(t),...), I am using temporary variables dipin and dipout + % this is to prevent errors of the type "Subscripted assignment between dissimilar structures" + dipin = dip; + for t=1:ntime + % catch errors due to non-convergence + try + dipout(t) = dipole_fit(dipin(t), sens, vol, Vdata(:,t), optarg{:}); + success(t) = 1; + if cfg.numdipoles==1 + fprintf('found minimum after non-linear optimization for topography %d on [%g %g %g]\n', t, dipout(t).pos(1), dipout(t).pos(2), dipout(t).pos(3)); + elseif cfg.numdipoles==2 + fprintf('found minimum after non-linear optimization for topography %d on [%g %g %g; %g %g %g]\n', t, dipout(t).pos(1,1), dipout(t).pos(1,2), dipout(t).pos(1,3), dipout(t).pos(2,1), dipout(t).pos(2,2), dipout(t).pos(2,3)); + end + catch + dipout(t).pos = dipin(t).pos; + dipout(t).mom = dipin(t).mom; + success(t) = 0; + disp(lasterr); + end + end + dip = dipout; + clear dipin dipout + otherwise + error('unsupported cfg.model'); + end % switch model +end % if nonlinear + +if strcmp(cfg.nonlinear, 'no') + % the optimal dipole positions are either obrained from scanning or from the initial configured seed + switch cfg.model + case 'regional' + success = 1; + case 'moving' + success = ones(1,ntime); + otherwise + error('unsupported cfg.model'); + + end % switch model +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% compute the model potential distribution and the residual variance +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +switch cfg.model + case 'regional' + if success + % re-compute the leadfield in order to compute the model potential and dipole moment + lf = ft_compute_leadfield(dip.pos, sens, vol); + % compute all details of the final dipole model + dip.mom = pinv(lf)*Vdata; + dip.pot = lf*dip.mom; + dip.rv = rv(Vdata, dip.pot); + Vmodel = dip.pot; + end + case 'moving' + for t=1:ntime + if success(t) + % re-compute the leadfield in order to compute the model potential and dipole moment + lf = ft_compute_leadfield(dip(t).pos, sens, vol); + % compute all details of the final dipole model + dip(t).mom = pinv(lf)*Vdata(:,t); + dip(t).pot = lf*dip(t).mom; + dip(t).rv = rv(Vdata(:,t), dip(t).pot); + Vmodel(:,t) = dip(t).pot; + end + end + otherwise + error('unsupported cfg.model'); +end % switch model + +switch cfg.model + case 'regional' + if isfreq + % the matrix with the dipole moment is encrypted and cannot be interpreted straight away + % reconstruct the frequency representation of the data at the source level + [dip.pow, dip.csd, dip.fourier] = timelock2freq(dip.mom); + end + case 'moving' + if isfreq + % although this is technically possible so far, it does not make any sense + warning('a moving dipole model in the frequency domain is not supported'); + end + otherwise + error('unsupported cfg.model'); +end % switch model + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% collect the results +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +source.label = cfg.channel; % these channels were used in fitting +source.dip = dip; +source.Vdata = Vdata; % FIXME this should be renamed (if possible w.r.t. EEGLAB) +source.Vmodel = Vmodel; % FIXME this should be renamed (if possible w.r.t. EEGLAB) + +% assign a latency, frequeny or component axis to the output +if iscomp + source.component = cfg.component; + % FIXME assign Vdata to an output variable, idem for the model potential +elseif isfreq + source.freq = cfg.frequency; + source.dimord = 'chan_freq'; + % FIXME assign Vdata to an output variable, idem for the model potential +else + tbeg = nearest(data.time, cfg.latency(1)); + tend = nearest(data.time, cfg.latency(end)); + source.time = data.time(tbeg:tend); + source.dimord = 'chan_time'; +end + +if isfield(data, 'grad') + % copy the gradiometer array along + source.grad = data.grad; +end +if isfield(data, 'elec') + % copy the electrode array along + source.elec = data.elec; +end + +% accessing this field here is needed for the configuration tracking +% by accessing it once, it will not be removed from the output cfg +cfg.outputfile; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add the version details of this function call to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_dipolefitting.m 1258 2010-06-22 08:33:48Z timeng $'; + +% remember the configuration details of the input data +try, cfg.previous = data.cfg; end + +% remember the exact configuration details in the output +source.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', source); % use the variable name "data" in the output file +end -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_dipolesimulation.m b/external/fieldtrip/ft_dipolesimulation.m index b84b9b2..306c7f7 100644 --- a/external/fieldtrip/ft_dipolesimulation.m +++ b/external/fieldtrip/ft_dipolesimulation.m @@ -1,11 +1,239 @@ -function varargout = funname(varargin); +function [simulated] = ft_dipolesimulation(cfg) -% this is a SPM wrapper around a FieldTrip function +% FT_DIPOLESIMULATION computes the field or potential of a simulated dipole +% and returns a datastructure identical to the FT_PREPROCESSING function. +% +% Use as +% data = ft_dipolesimulation(cfg) +% +% You should specify the volume conductor model with +% cfg.hdmfile = string, file containing the volume conduction model +% or alternatively +% cfg.vol = structure with volume conduction model +% If the sensor information is not contained in the data itself you should +% also specify the sensor information using +% cfg.gradfile = string, file containing the gradiometer definition +% cfg.elecfile = string, file containing the electrode definition +% or alternatively +% cfg.grad = structure with gradiometer definition +% cfg.elec = structure with electrode definition +% +% optionally +% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), +% see FT_CHANNELSELECTION for details +% +% The dipoles position and orientation have to be specified with +% cfg.dip.pos = [Rx Ry Rz] +% cfg.dip.mom = [Qx Qy Qz] +% +% The timecourse of the dipole activity is given as a single vector or as a +% cell-array with one vectors per trial +% cfg.dip.signal +% or by specifying a sine-wave signal +% cfg.dip.frequency in Hz +% cfg.dip.phase in radians +% cfg.ntrials number of trials +% cfg.triallength time in seconds +% cfg.fsample sampling frequency in Hz +% +% Random white noise can be added to the data in each trial, either by +% specifying an absolute or a relative noise level +% cfg.relnoise = add noise with level relative to simulated signal +% cfg.absnoise = add noise with absolute level -% this part is variable -prefix = 'ft_'; +% Undocumented local options +% cfg.feedback +% cfg.previous +% cfg.version +% +% This function depends on FT_PREPARE_VOL_SENS which has the following options: +% cfg.channel, documented +% cfg.elec, documented +% cfg.elecfile, documented +% cfg.grad, documented +% cfg.gradfile, documented +% cfg.hdmfile, documented +% cfg.order +% cfg.vol, documented + +% Copyright (C) 2004, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_dipolesimulation.m 1183 2010-06-01 14:35:47Z vlalit $ + +fieldtripdefs + +% set the defaults +if ~isfield(cfg, 'dip'), cfg.dip = []; end +if ~isfield(cfg.dip, 'pos'), cfg.dip.pos = [-5 0 15]; end +if ~isfield(cfg.dip, 'mom'), cfg.dip.mom = [1 0 0]'; end +if ~isfield(cfg, 'fsample'), cfg.fsample = 250; end +if ~isfield(cfg, 'relnoise'), cfg.relnoise = 0; end +if ~isfield(cfg, 'absnoise'), cfg.absnoise = 0; end +if ~isfield(cfg, 'feedback'), cfg.feedback = 'text'; end +if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end + +cfg.dip = fixdipole(cfg.dip); +Ndipoles = size(cfg.dip.pos,1); + +% prepare the volume conductor and the sensor array +[vol, sens, cfg] = prepare_headmodel(cfg, []); + +if ~isfield(cfg, 'ntrials') + if isfield(cfg.dip, 'signal') + cfg.ntrials = length(cfg.dip.signal); + else + cfg.ntrials = 20; + end +end +Ntrials = cfg.ntrials; + +if isfield(cfg.dip, 'frequency') + % this should be a column vector + cfg.dip.frequency = cfg.dip.frequency(:); +end + +if isfield(cfg.dip, 'phase') + % this should be a column vector + cfg.dip.phase = cfg.dip.phase(:); +end + +% no signal was given, compute a cosine-wave signal as timcourse for the dipole +if ~isfield(cfg.dip, 'signal') + % set some additional defaults if neccessary + if ~isfield(cfg.dip, 'frequency') + cfg.dip.frequency = ones(Ndipoles,1)*10; + end + if ~isfield(cfg.dip, 'phase') + cfg.dip.phase = zeros(Ndipoles,1); + end + if ~isfield(cfg.dip, 'amplitude') + cfg.dip.amplitude = ones(Ndipoles,1); + end + if ~isfield(cfg, 'triallength') + cfg.triallength = 1; + end + % compute a cosine-wave signal wit the desired frequency, phase and amplitude for each dipole + nsamples = round(cfg.triallength*cfg.fsample); + time = (0:(nsamples-1))/cfg.fsample; + for i=1:Ndipoles + cfg.dip.signal(i,:) = cos(cfg.dip.frequency(i)*time*2*pi + cfg.dip.phase(i)) * cfg.dip.amplitude(i); + end +end + +% construct the timecourse of the dipole activity for each individual trial +if ~iscell(cfg.dip.signal) + dipsignal = {}; + time = {}; + nsamples = length(cfg.dip.signal); + for trial=1:Ntrials + % each trial has the same dipole signal + dipsignal{trial} = cfg.dip.signal; + time{trial} = (0:(nsamples-1))/cfg.fsample; + end +else + dipsignal = {}; + time = {}; + for trial=1:Ntrials + % each trial has a different dipole signal + dipsignal{trial} = cfg.dip.signal{trial}; + time{trial} = (0:(length(dipsignal{trial})-1))/cfg.fsample; + end +end + +dippos = cfg.dip.pos; +dipmom = cfg.dip.mom; + +if ~iscell(dipmom) + dipmom = {dipmom}; +end + +if ~iscell(dippos) + dippos = {dippos}; +end + +if length(dippos)==1 + dippos = repmat(dippos, 1, Ntrials); +elseif length(dippos)~=Ntrials + error('incorrect number of trials specified in the dipole position'); +end + +if length(dipmom)==1 + dipmom = repmat(dipmom, 1, Ntrials); +elseif length(dipmom)~=Ntrials + error('incorrect number of trials specified in the dipole moment'); +end + +simulated.trial = {}; +simulated.time = {}; +progress('init', cfg.feedback, 'computing simulated data'); +for trial=1:Ntrials + progress(trial/Ntrials, 'computing simulated data for trial %d\n', trial); + lf = ft_compute_leadfield(dippos{trial}, sens, vol); + nsamples = size(dipsignal{trial},2); + nchannels = size(lf,1); + simulated.trial{trial} = zeros(nchannels,nsamples); + for i = 1:3, + simulated.trial{trial} = simulated.trial{trial} + lf(:,i:3:end) * ... + (repmat(dipmom{trial}(i:3:end),1,nsamples) .* dipsignal{trial}); + end + simulated.time{trial} = time{trial}; +end +progress('close'); + +if ft_senstype(sens, 'meg') + simulated.grad = sens; +elseif ft_senstype(sens, 'meg') + simulated.elec = sens; +end + +% determine RMS value of simulated data +ss = 0; +sc = 0; +for trial=1:Ntrials + ss = ss + sum(simulated.trial{trial}(:).^2); + sc = sc + length(simulated.trial{trial}(:)); +end +rms = sqrt(ss/sc); +fprintf('RMS value of simulated data is %g\n', rms); + +% add noise to the simulated data +for trial=1:Ntrials + relnoise = randn(size(simulated.trial{trial})) * cfg.relnoise * rms; + absnoise = randn(size(simulated.trial{trial})) * cfg.absnoise; + simulated.trial{trial} = simulated.trial{trial} + relnoise + absnoise; +end + +simulated.fsample = cfg.fsample; +simulated.label = sens.label; + +% add version details to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_dipolesimulation.m 1183 2010-06-01 14:35:47Z vlalit $'; +% remember the configuration details of the input data +try, cfg.previous = data.cfg; end +% remember the exact configuration details in the output +simulated.cfg = cfg; -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_documentationindex.m b/external/fieldtrip/ft_documentationindex.m new file mode 100644 index 0000000..b95e222 --- /dev/null +++ b/external/fieldtrip/ft_documentationindex.m @@ -0,0 +1,164 @@ +function index = ft_documentationindex(filename) + +% FT_DOCUMENTATIONINDEX is a helper function to maintain the online +% documentation + +% Copyright (C) 2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_preprocessing.m 948 2010-04-21 18:02:21Z roboos $ + +fieldtripdefs + +p = fileparts(which(mfilename)); + +f1 = dir(fullfile(p, 'ft_*.m')); +f1 = {f1.name}'; + +funname = f1; + +for i=1:length(funname) + [p, funname{i}, x] = fileparts(funname{i}); +end + +ncfg = 0; +index = {}; + +for j=1:length(funname) + str = help(funname{j}) + str = tokenize(str, 10); + + % compact the help description + for i=2:(length(str)-1) + prevline = str{i-1}; + thisline = str{i }; + nextline = str{i+1}; + if length(thisline)<5 || length(prevline)<5 + continue + end + try + if ~isempty(regexp(prevline, '^ *cfg')) && isempty(regexp(thisline, '^ *cfg')) && ~all(thisline(1:3)==' ') + % do not concatenate, this line starts a new paragraph + elseif ~isempty(regexp(prevline, '^ *cfg')) && all(thisline(1:5)==' ') + % concatenate a multiline cfg description + thisline = cat(2, prevline, thisline); + prevline = ''; + elseif ~all(prevline(1:5)==' ') && ~all(thisline(1:5)==' ') && isempty(regexp(thisline, '^ *cfg')) + % concatenate the lines of a paragraph + thisline = cat(2, prevline, thisline); + prevline = ''; + elseif isempty(regexp(prevline, '^ *cfg')) && ~isempty(regexp(thisline, '^ cfg')) + % previous line is a paragraph, this line starts with "cfg" but has no extra space in front of it + % so assume that the cfg is part of the running text in the paragraph and conactenate the lines + thisline = cat(2, prevline, thisline); + prevline = ''; + end + catch + disp(lasterr); + disp(thisline); + end + str{i-1} = prevline; + str{i } = thisline; + str{i+1} = nextline; + end + for i=1:length(str) + if length(str{i})>1 + % remove double spaces + dum = findstr(str{i}, ' '); + str{i}(dum) = []; + end + while ~isempty(str{i}) && str{i}(1)==' ' + % remove spaces at the begin of the line + str{i}(1) = []; + end + while ~isempty(str{i}) && str{i}(end)==' ' + % remove spaces at the end of the line + str{i}(1) = []; + end + end + for i=1:length(str) + if ~isempty(regexp(str{i}, '^ *cfg.[a-zA-Z0-9_\.]*')) + ncfg = ncfg+1; + index{ncfg,1} = funname{j}; + dum = regexp(str{i}, 'cfg.[a-zA-Z0-9_\.]*', 'match'); + index{ncfg,2} = dum{1}; + dum = str{i}; + while length(dum)>0 && dum(1)~=' ' + dum = dum(2:end); + end + while length(dum)>0 && (dum(1)=='=' || dum(1)==' ') + dum = dum(2:end); + end + index{ncfg,3} = dum; + dum1 = index{ncfg,1}; + dum1(end+1:30) = ' '; + dum2 = index{ncfg,2}; + dum2(end+1:30) = ' '; + end + end +end + +index = sortrows(index(:,[2 3 1])); +index = index(:, [3 1 2]); +count = 0; +for i=2:size(index,1) + prevfun = index{i-1,1}; + prevcfg = index{i-1,2}; + prevcmt = index{i-1,3}; + thisfun = index{i,1}; + thiscfg = index{i,2}; + thiscmt = index{i,3}; + + if strcmp(thiscfg,prevcfg) && strcmp(thiscmt,prevcmt) + count = count + 1; + thisfun = [prevfun ', ' thisfun]; + prevfun = ''; + prevcfg = ''; + prevcmt = ''; + index{i ,1} = thisfun; + index{i-1,1} = prevfun; + index{i-1,2} = prevcfg; + index{i-1,3} = prevcmt; + end +end +fprintf('merged %d cfg options\n', count); + +fid = fopen(filename, 'wb'); +currletter = char(96); +fprintf(fid, '====== Index of configuration options ======\n\n'); +fprintf(fid, 'A detailed description of each function is available in the [[:reference|reference documentation]].\n\n'); +fprintf(fid, 'This index to the reference documentation is automatically generated from the Matlab code every day. Therefore you should not edit this pages manually, since your changes would be overwritten automatically. If you want to suggest corrections to the documentation, please send them by email to the mailing list or to one of the main developers (see [[:contact]]).\n\n'); +for i=1:size(index,1) + fprintf('%s -- %s -- %s\n', index{i,2}, index{i,3}, index{i,1}); + if isempty(index{i,1}) + continue; + elseif length(index{i,2})<5 + continue; + end + thisletter = index{i,2}(5); + while currletter. +% +% $Id: ft_preprocessing.m 948 2010-04-21 18:02:21Z roboos $ + +fieldtripdefs + +p = fileparts(which(mfilename)); + +f1 = dir(fullfile(p, 'ft_*.m')); +f1 = {f1.name}'; + +f2 = dir(fullfile(p, 'public', '*.m')); +f2 = {f2.name}'; + +f3 = dir(fullfile(p, 'preproc', '*.m')); +f3 = {f3.name}'; + +f4 = dir(fullfile(p, 'fileio', '*.m')); +f4 = {f4.name}'; + +f5 = dir(fullfile(p, 'forward', '*.m')); +f5 = {f5.name}'; + +f6 = dir(fullfile(p, 'inverse', '*.m')); +f6 = {f6.name}'; + +f7 = dir(fullfile(p, 'realtime', '*.m')); +f7 = {f7.name}'; + +f8 = dir(fullfile(p, 'realtime', 'datasource', '*.m')); +f8 = {f8.name}'; + +funname = cat(1, f1, f2, f3, f4, f5, f6, f7, f8); + +for i=1:length(funname) + [p, funname{i}, x] = fileparts(funname{i}); +end + +% create the desired output directory +if ~isdir(outdir) +mkdir(outdir); +end + +for i=1:length(funname) + filename = fullfile(outdir, [funname{i} '.txt']); + str = help(funname{i}); + fid = fopen(filename, 'wt'); + fprintf(fid, '===== %s =====\n\n', upper(funname{i})); + fprintf(fid, 'Note that this reference documentation is identical to the help that is displayed in Matlab when you type "help %s".\n\n', funname{i}); + fprintf(fid, '\n'); % required for docuwiki + fprintf(fid, '%s', str); + fprintf(fid, '\n'); % required for docuwiki + fclose(fid); +end + + diff --git a/external/fieldtrip/ft_electroderealign.m b/external/fieldtrip/ft_electroderealign.m index b84b9b2..6d61958 100644 --- a/external/fieldtrip/ft_electroderealign.m +++ b/external/fieldtrip/ft_electroderealign.m @@ -1,11 +1,721 @@ -function varargout = funname(varargin); +function [norm] = ft_electroderealign(cfg) -% this is a SPM wrapper around a FieldTrip function +% FT_ELECTRODEREALIGN rotates and translates electrode positions to +% template electrode positions or towards the head surface. It can +% either perform a rigid body transformation, in which only the +% coordinate system is changed, or it can apply additional deformations +% to the input electrodes. +% +% Use as +% [elec] = ft_electroderealign(cfg) +% +% Three different methods for aligning the input electrodes are implemented: +% based on a warping method, based on the fiducials or interactive with a +% graphical user interface. Each of these approaches is described below. +% +% 1) You can apply a spatial transformation/deformation (i.e. 'warp') +% that automatically minimizes the distance between the electrodes +% and the template or standard electrode set. The warping methods use +% a non-linear search to optimize the error between input and template +% electrodes or the head surface. +% +% 2) You can apply a rigid body realignment based on three fiducial locations. +% Realigning using the fiducials only ensures that the fiducials (typically +% nose, left and right ear) are along the same axes in the input eectrode +% set as in the template electrode set. +% +% 3) You can display the electrode positions together with the skin surface, +% and manually (using the graphical user interface) adjust the rotation, +% translation and scaling parameters, so that the two match. +% +% 4) You can display the skin surface and manually position the electrodes by +% clicking. +% +% The configuration can contain the following options +% cfg.method = string representing the method for aligning or placing the electrodes +% 'template' realign the electrodes to a template electrode set +% 'fiducial' realign using the NAS, LPA and RPA fiducials +% 'interactive' realign manually using a graphical user interface +% 'manual' manual positioning of the electrodes by clicking in a graphical user interface +% cfg.warp = string describing the spatial transformation for the template method +% 'rigidbody' apply a rigid-body warp (default) +% 'globalrescale' apply a rigid-body warp with global rescaling +% 'traditional' apply a rigid-body warp with individual axes rescaling +% 'nonlin1' apply a 1st order non-linear warp +% 'nonlin2' apply a 2nd order non-linear warp +% 'nonlin3' apply a 3rd order non-linear warp +% 'nonlin4' apply a 4th order non-linear warp +% 'nonlin5' apply a 5th order non-linear warp +% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), +% see FT_CHANNELSELECTION for details +% cfg.fiducial = cell-array with the name of three fiducials used for +% realigning (default = {'nasion', 'lpa', 'rpa'}) +% cfg.casesensitive = 'yes' or 'no', determines whether string comparisons +% between electrode labels are case sensitive (default = 'yes') +% cfg.feedback = 'yes' or 'no' (default = 'no') +% +% The electrode set that will be realigned is specified as +% cfg.elecfile = string with filename, or alternatively +% cfg.elec = structure with electrode definition +% +% If you want to align the electrodes to a single template electrode set +% or to multiple electrode sets (which will be averaged), you should +% specify the template electrode sets as +% cfg.template = single electrode set that serves as standard +% or +% cfg.template{1..N} = list of electrode sets that are averaged into the standard +% The template electrode sets can be specified either as electrode +% structures (i.e. when they are already read in memory) or as electrode +% files. +% +% If you only want to realign using the fiducials, the template has to contain +% the three fiducials, e.g. +% cfg.template.pnt(1,:) = [110 0 0] % location of the nose +% cfg.template.pnt(2,:) = [0 90 0] % left ear +% cfg.template.pnt(3,:) = [0 -90 0] % right ear +% cfg.template.label = {''nasion', 'lpa', 'rpa'} +% +% If you want to align existing electrodes to the head surface or position +% new electrodes on the head surface, you should specify the head surface as +% cfg.headshape = a filename containing headshape, a structure containing a +% single triangulated boundary, or a Nx3 matrix with surface +% points +% +% See also FT_READ_SENS, FT_VOLUMEREALIGN -% this part is variable -prefix = 'ft_'; +% Copyright (C) 2005-2010, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_electroderealign.m 1431 2010-07-20 07:47:55Z roboos $ + +fieldtripdefs + +% this is used for feedback of the lower-level functions +global fb + +% set the defaults +if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end +if ~isfield(cfg, 'feedback'), cfg.feedback = 'no'; end +if ~isfield(cfg, 'casesensitive'), cfg.casesensitive = 'yes'; end +if ~isfield(cfg, 'headshape'), cfg.headshape = []; end % for triangulated head surface, without labels +if ~isfield(cfg, 'template'), cfg.template = []; end % for electrodes or fiducials, always with labels +if ~isfield(cfg, 'warp'), cfg.warp = 'rigidbody'; end + +cfg = checkconfig(cfg, 'renamed', {'realignfiducials', 'fiducial'}); +cfg = checkconfig(cfg, 'renamed', {'realignfiducial', 'fiducial'}); +cfg = checkconfig(cfg, 'forbidden', 'outline'); + +if isfield(cfg, 'headshape') && isa(cfg.headshape, 'config') + % convert the nested config-object back into a normal structure + cfg.headshape = struct(cfg.headshape); +end + +if strcmp(cfg.feedback, 'yes') + % use the global fb field to tell the warping toolbox to print feedback + fb = 1; +else + fb = 0; +end + +% get the electrode definition that should be warped +if isfield(cfg, 'elec') + elec = cfg.elec; +elseif isfield(cfg, 'elecfile') + elec = ft_read_sens(cfg.elecfile); +else + % start with an empty set of electrodes (usefull for manual positioning) + elec = []; + elec.pnt = zeros(0,3); + elec.label = cell(0,1); + elec.unit = 'mm'; +end +elec = ft_convert_units(elec); % ensure that the units are specified + +usetemplate = isfield(cfg, 'template') && ~isempty(cfg.template); +useheadshape = isfield(cfg, 'headshape') && ~isempty(cfg.headshape); + +if usetemplate + % get the template electrode definitions + if ~iscell(cfg.template) + cfg.template = {cfg.template}; + end + Ntemplate = length(cfg.template); + for i=1:Ntemplate + if isstruct(cfg.template{i}) + template(i) = cfg.template{i}; + else + template(i) = ft_read_sens(cfg.template{i}); + end + end + for i=1:Ntemplate + template(i) = ft_convert_units(template(i), elec.unit); % ensure that the units are consistent with the electrodes + end +elseif useheadshape + % get the surface describing the head shape + if isstruct(cfg.headshape) && isfield(cfg.headshape, 'pnt') + % use the headshape surface specified in the configuration + headshape = cfg.headshape; + elseif isnumeric(cfg.headshape) && size(cfg.headshape,2)==3 + % use the headshape points specified in the configuration + headshape.pnt = cfg.headshape; + elseif ischar(cfg.headshape) + % read the headshape from file + headshape = ft_read_headshape(cfg.headshape); + else + error('cfg.headshape is not specified correctly') + end + if ~isfield(headshape, 'tri') + % generate a closed triangulation from the surface points + headshape.pnt = unique(headshape.pnt, 'rows'); + headshape.tri = projecttri(headshape.pnt); + end + headshape = ft_convert_units(headshape, elec.unit); % ensure that the units are consistent with the electrodes +else + error('you should either specify template electrode positions, template fiducials or a head shape'); +end + +% remember the original electrode locations and labels +orig = elec; + +% convert all labels to lower case for string comparisons +% this has to be done AFTER keeping the original labels and positions +if strcmp(cfg.casesensitive, 'no') + for i=1:length(elec.label) + elec.label{i} = lower(elec.label{i}); + end + for j=1:length(template) + for i=1:length(template(j).label) + template(j).label{i} = lower(template(j).label{i}); + end + end +end + +if strcmp(cfg.feedback, 'yes') + % create an empty figure, continued below... + figure + axis equal + axis vis3d + hold on + xlabel('x') + ylabel('y') + zlabel('z') +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +if usetemplate && strcmp(cfg.method, 'template') + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + % determine electrode selection and overlapping subset for warping + cfg.channel = ft_channelselection(cfg.channel, elec.label); + for i=1:Ntemplate + cfg.channel = ft_channelselection(cfg.channel, template(i).label); + end + + % make subselection of electrodes + [cfgsel, datsel] = match_str(cfg.channel, elec.label); + elec.label = elec.label(datsel); + elec.pnt = elec.pnt(datsel,:); + for i=1:Ntemplate + [cfgsel, datsel] = match_str(cfg.channel, template(i).label); + template(i).label = template(i).label(datsel); + template(i).pnt = template(i).pnt(datsel,:); + end + + % compute the average of the template electrode positions + all = []; + for i=1:Ntemplate + all = cat(3, all, template(i).pnt); + end + avg = mean(all,3); + stderr = std(all, [], 3); + + fprintf('warping electrodes to template... '); % the newline comes later + [norm.pnt, norm.m] = warp_optim(elec.pnt, avg, cfg.warp); + norm.label = elec.label; + + dpre = mean(sqrt(sum((avg - elec.pnt).^2, 2))); + dpost = mean(sqrt(sum((avg - norm.pnt).^2, 2))); + fprintf('mean distance prior to warping %f, after warping %f\n', dpre, dpost); + + if strcmp(cfg.feedback, 'yes') + % plot all electrodes before warping + my_plot3(elec.pnt, 'r.'); + my_plot3(elec.pnt(1,:), 'r*'); + my_plot3(elec.pnt(2,:), 'r*'); + my_plot3(elec.pnt(3,:), 'r*'); + my_text3(elec.pnt(1,:), elec.label{1}, 'color', 'r'); + my_text3(elec.pnt(2,:), elec.label{2}, 'color', 'r'); + my_text3(elec.pnt(3,:), elec.label{3}, 'color', 'r'); + + % plot all electrodes after warping + my_plot3(norm.pnt, 'm.'); + my_plot3(norm.pnt(1,:), 'm*'); + my_plot3(norm.pnt(2,:), 'm*'); + my_plot3(norm.pnt(3,:), 'm*'); + my_text3(norm.pnt(1,:), norm.label{1}, 'color', 'm'); + my_text3(norm.pnt(2,:), norm.label{2}, 'color', 'm'); + my_text3(norm.pnt(3,:), norm.label{3}, 'color', 'm'); + + % plot the template electrode locations + my_plot3(avg, 'b.'); + my_plot3(avg(1,:), 'b*'); + my_plot3(avg(2,:), 'b*'); + my_plot3(avg(3,:), 'b*'); + my_text3(avg(1,:), norm.label{1}, 'color', 'b'); + my_text3(avg(2,:), norm.label{2}, 'color', 'b'); + my_text3(avg(3,:), norm.label{3}, 'color', 'b'); + + % plot lines connecting the input/warped electrode locations with the template locations + my_line3(elec.pnt, avg, 'color', 'r'); + my_line3(norm.pnt, avg, 'color', 'm'); + end + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +elseif useheadshape && strcmp(cfg.method, 'template') + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + % determine electrode selection and overlapping subset for warping + cfg.channel = ft_channelselection(cfg.channel, elec.label); + + % make subselection of electrodes + [cfgsel, datsel] = match_str(cfg.channel, elec.label); + elec.label = elec.label(datsel); + elec.pnt = elec.pnt(datsel,:); + + fprintf('warping electrodes to head shape... '); % the newline comes later + [norm.pnt, norm.m] = warp_optim(elec.pnt, headshape, cfg.warp); + norm.label = elec.label; + + dpre = warp_error([], elec.pnt, headshape, cfg.warp); + dpost = warp_error(norm.m, elec.pnt, headshape, cfg.warp); + fprintf('mean distance prior to warping %f, after warping %f\n', dpre, dpost); + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +elseif strcmp(cfg.method, 'fiducial') + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + % try to determine the fiducials automatically if not specified + if ~isfield(cfg, 'fiducial') + option1 = {'nasion' 'left' 'right'}; + option2 = {'nasion' 'lpa' 'rpa'}; + option3 = {'nz' 'lpa' 'rpa'}; + if length(match_str(elec.label, option1))==3 + cfg.fiducial = option1; + elseif length(match_str(elec.label, option2))==3 + cfg.fiducial = option2; + elseif length(match_str(elec.label, option3))==3 + cfg.fiducial = option3; + else + error('could not determine three fiducials, please specify cfg.fiducial') + end + end + fprintf('using fiducials {''%s'', ''%s'', ''%s''}\n', cfg.fiducial{1}, cfg.fiducial{2}, cfg.fiducial{3}); + + % determine electrode selection + cfg.channel = ft_channelselection(cfg.channel, elec.label); + [cfgsel, datsel] = match_str(cfg.channel, elec.label); + elec.label = elec.label(datsel); + elec.pnt = elec.pnt(datsel,:); + + if length(cfg.fiducial)~=3 + error('you must specify three fiducials'); + end + + % do case-insensitive search for fiducial locations + nas_indx = match_str(lower(elec.label), lower(cfg.fiducial{1})); + lpa_indx = match_str(lower(elec.label), lower(cfg.fiducial{2})); + rpa_indx = match_str(lower(elec.label), lower(cfg.fiducial{3})); + if length(nas_indx)~=1 || length(lpa_indx)~=1 || length(rpa_indx)~=1 + error('not all fiducials were found in the electrode set'); + end + elec_nas = elec.pnt(nas_indx,:); + elec_lpa = elec.pnt(lpa_indx,:); + elec_rpa = elec.pnt(rpa_indx,:); + + % FIXME change the flow in the remainder + % if one or more template electrode sets are specified, then align to the average of those + % if no template is specified, then align so that the fiducials are along the axis + + % find the matching fiducials in the template and average them + templ_nas = []; + templ_lpa = []; + templ_rpa = []; + for i=1:Ntemplate + nas_indx = match_str(lower(template(i).label), lower(cfg.fiducial{1})); + lpa_indx = match_str(lower(template(i).label), lower(cfg.fiducial{2})); + rpa_indx = match_str(lower(template(i).label), lower(cfg.fiducial{3})); + if length(nas_indx)~=1 || length(lpa_indx)~=1 || length(rpa_indx)~=1 + error(sprintf('not all fiducials were found in template %d', i)); + end + templ_nas(end+1,:) = template(i).pnt(nas_indx,:); + templ_lpa(end+1,:) = template(i).pnt(lpa_indx,:); + templ_rpa(end+1,:) = template(i).pnt(rpa_indx,:); + end + templ_nas = mean(templ_nas,1); + templ_lpa = mean(templ_lpa,1); + templ_rpa = mean(templ_rpa,1); + + % realign both to a common coordinate system + elec2common = headcoordinates(elec_nas, elec_lpa, elec_rpa); + templ2common = headcoordinates(templ_nas, templ_lpa, templ_rpa); + + % compute the combined transform and realign the electrodes to the template + norm = []; + norm.m = elec2common * inv(templ2common); + norm.pnt = warp_apply(norm.m, elec.pnt, 'homogeneous'); + norm.label = elec.label; + + nas_indx = match_str(lower(elec.label), lower(cfg.fiducial{1})); + lpa_indx = match_str(lower(elec.label), lower(cfg.fiducial{2})); + rpa_indx = match_str(lower(elec.label), lower(cfg.fiducial{3})); + dpre = mean(sqrt(sum((elec.pnt([nas_indx lpa_indx rpa_indx],:) - [templ_nas; templ_lpa; templ_rpa]).^2, 2))); + nas_indx = match_str(lower(norm.label), lower(cfg.fiducial{1})); + lpa_indx = match_str(lower(norm.label), lower(cfg.fiducial{2})); + rpa_indx = match_str(lower(norm.label), lower(cfg.fiducial{3})); + dpost = mean(sqrt(sum((norm.pnt([nas_indx lpa_indx rpa_indx],:) - [templ_nas; templ_lpa; templ_rpa]).^2, 2))); + fprintf('mean distance between fiducials prior to realignment %f, after realignment %f\n', dpre, dpost); + + if strcmp(cfg.feedback, 'yes') + % plot the first three electrodes before transformation + my_plot3(elec.pnt(1,:), 'r*'); + my_plot3(elec.pnt(2,:), 'r*'); + my_plot3(elec.pnt(3,:), 'r*'); + my_text3(elec.pnt(1,:), elec.label{1}, 'color', 'r'); + my_text3(elec.pnt(2,:), elec.label{2}, 'color', 'r'); + my_text3(elec.pnt(3,:), elec.label{3}, 'color', 'r'); + + % plot the template fiducials + my_plot3(templ_nas, 'b*'); + my_plot3(templ_lpa, 'b*'); + my_plot3(templ_rpa, 'b*'); + my_text3(templ_nas, ' nas', 'color', 'b'); + my_text3(templ_lpa, ' lpa', 'color', 'b'); + my_text3(templ_rpa, ' rpa', 'color', 'b'); + + % plot all electrodes after transformation + my_plot3(norm.pnt, 'm.'); + my_plot3(norm.pnt(1,:), 'm*'); + my_plot3(norm.pnt(2,:), 'm*'); + my_plot3(norm.pnt(3,:), 'm*'); + my_text3(norm.pnt(1,:), norm.label{1}, 'color', 'm'); + my_text3(norm.pnt(2,:), norm.label{2}, 'color', 'm'); + my_text3(norm.pnt(3,:), norm.label{3}, 'color', 'm'); + end + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +elseif strcmp(cfg.method, 'interactive') + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % open a figure + fig = figure; + % add the data to the figure + set(fig, 'CloseRequestFcn', @cb_close); + setappdata(fig, 'elec', elec); + setappdata(fig, 'transform', eye(4)); + if useheadshape + setappdata(fig, 'headshape', headshape); + end + if usetemplate + % FIXME interactive realigning to template electrodes is not yet supported + % this requires a consistent handling of channel selection etc. + setappdata(fig, 'template', template); + end + % add the GUI elements + cb_creategui(gca); + cb_redraw(gca); + rotate3d on + waitfor(fig); + % get the data from the figure that was left behind as global variable + global norm + tmp = norm; + clear global norm + norm = tmp; + clear tmp + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +elseif strcmp(cfg.method, 'manual') + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % open a figure + fig = figure; + rotate3d on + ft_plot_mesh(headshape, 'edgecolor', 'k') + xyz = ft_select_point3d(headshape, 'multiple', true); + orig.pnt = xyz; + for i=1:size(orig.pnt,1) + orig.label{i,1} = 'unknown'; + end + +else + error('unknown method'); +end + +% apply the spatial transformation to all electrodes, and replace the +% electrode labels by their case-sensitive original values +switch cfg.method + case {'template' 'fiducial', 'interactive'} + norm.pnt = warp_apply(norm.m, orig.pnt, cfg.warp); + case 'manual' + % the positions are already assigned in correspondence with the mesh + norm = orig; + otherwise + error('unknown method'); +end + +if isfield(orig, 'label') + norm.label = orig.label; +end + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_electroderealign.m 1431 2010-07-20 07:47:55Z roboos $'; + +% remember the configuration +norm.cfg = cfg; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% some simple SUBFUNCTIONs that facilitate 3D plotting +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function h = my_plot3(xyz, varargin) +h = plot3(xyz(:,1), xyz(:,2), xyz(:,3), varargin{:}); +function h = my_text3(xyz, varargin) +h = text(xyz(:,1), xyz(:,2), xyz(:,3), varargin{:}); +function my_line3(xyzB, xyzE, varargin) +for i=1:size(xyzB,1) + line([xyzB(i,1) xyzE(i,1)], [xyzB(i,2) xyzE(i,2)], [xyzB(i,3) xyzE(i,3)], varargin{:}) +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION to layout a moderately complex graphical user interface +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function h = layoutgui(fig, geometry, position, style, string, value, tag, callback); +horipos = geometry(1); % lower left corner of the GUI part in the figure +vertpos = geometry(2); % lower left corner of the GUI part in the figure +width = geometry(3); % width of the GUI part in the figure +height = geometry(4); % height of the GUI part in the figure +horidist = 0.05; +vertdist = 0.05; +options = {'units', 'normalized', 'HorizontalAlignment', 'center'}; % 'VerticalAlignment', 'middle' +Nrow = size(position,1); +h = cell(Nrow,1); +for i=1:Nrow + if isempty(position{i}) + continue; + end + position{i} = position{i} ./ sum(position{i}); + Ncol = size(position{i},2); + ybeg = (Nrow-i )/Nrow + vertdist/2; + yend = (Nrow-i+1)/Nrow - vertdist/2; + for j=1:Ncol + xbeg = sum(position{i}(1:(j-1))) + horidist/2; + xend = sum(position{i}(1:(j ))) - horidist/2; + pos(1) = xbeg*width + horipos; + pos(2) = ybeg*height + vertpos; + pos(3) = (xend-xbeg)*width; + pos(4) = (yend-ybeg)*height; + h{i}{j} = uicontrol(fig, ... + options{:}, ... + 'position', pos, ... + 'style', style{i}{j}, ... + 'string', string{i}{j}, ... + 'tag', tag{i}{j}, ... + 'value', value{i}{j}, ... + 'callback', callback{i}{j} ... + ); + end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function cb_creategui(hObject, eventdata, handles); +% define the position of each GUI element +position = { + [2 1 1 1] + [2 1 1 1] + [2 1 1 1] + [1] + [1] + [1] + [1] + [1 1] + }; + +% define the style of each GUI element +style = { + {'text' 'edit' 'edit' 'edit'} + {'text' 'edit' 'edit' 'edit'} + {'text' 'edit' 'edit' 'edit'} + {'pushbutton'} + {'pushbutton'} + {'toggle'} + {'toggle'} + {'text' 'edit'} + }; + +% define the descriptive string of each GUI element +string = { + {'rotate' 0 0 0} + {'translate' 0 0 0} + {'scale' 1 1 1} + {'redisplay'} + {'apply'} + {'toggle grid'} + {'toggle axes'} + {'alpha' 0.7} + }; + +% define the value of each GUI element +value = { + {[] [] [] []} + {[] [] [] []} + {[] [] [] []} + {[]} + {[]} + {0} + {0} + {[] []} + }; + +% define a tag for each GUI element +tag = { + {'' 'rx' 'ry' 'rz'} + {'' 'tx' 'ty' 'tz'} + {'' 'sx' 'sy' 'sz'} + {''} + {''} + {'toggle grid'} + {'toggle axes'} + {'' 'alpha'} + }; + +% define the callback function of each GUI element +callback = { + {[] @cb_redraw @cb_redraw @cb_redraw} + {[] @cb_redraw @cb_redraw @cb_redraw} + {[] @cb_redraw @cb_redraw @cb_redraw} + {@cb_redraw} + {@cb_apply} + {@cb_redraw} + {@cb_redraw} + {[] @cb_redraw} + }; + +fig = get(hObject, 'parent'); +layoutgui(fig, [0.7 0.05 0.25 0.50], position, style, string, value, tag, callback); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function cb_redraw(hObject, eventdata, handles); +fig = get(hObject, 'parent'); +headshape = getappdata(fig, 'headshape'); +elec = getappdata(fig, 'elec'); +template = getappdata(fig, 'template'); +% get the transformation details +rx = str2num(get(findobj(fig, 'tag', 'rx'), 'string')); +ry = str2num(get(findobj(fig, 'tag', 'ry'), 'string')); +rz = str2num(get(findobj(fig, 'tag', 'rz'), 'string')); +tx = str2num(get(findobj(fig, 'tag', 'tx'), 'string')); +ty = str2num(get(findobj(fig, 'tag', 'ty'), 'string')); +tz = str2num(get(findobj(fig, 'tag', 'tz'), 'string')); +sx = str2num(get(findobj(fig, 'tag', 'sx'), 'string')); +sy = str2num(get(findobj(fig, 'tag', 'sy'), 'string')); +sz = str2num(get(findobj(fig, 'tag', 'sz'), 'string')); +R = rotate ([rx ry rz]); +T = translate([tx ty tz]); +S = scale ([sx sy sz]); +H = S * T * R; +elec = ft_transform_sens(H, elec); +axis vis3d; cla +xlabel('x') +ylabel('y') +zlabel('z') +if ~isempty(headshape) + triplot(headshape.pnt, headshape.tri, [], 'faces_skin'); + alpha(str2num(get(findobj(fig, 'tag', 'alpha'), 'string'))); +end +if ~isempty(template) + triplot(template.pnt, [], [], 'nodes_blue') +end +triplot(elec.pnt, [], [], 'nodes'); +if isfield(elec, 'line') + triplot(elec.pnt, elec.line, [], 'edges'); +end +if isfield(elec, 'fid') && ~isempty(elec.fid.pnt) + triplot(elec.fid.pnt, [], [], 'nodes_red'); +end +if get(findobj(fig, 'tag', 'toggle axes'), 'value') + axis on +else + axis off +end +if get(findobj(fig, 'tag', 'toggle grid'), 'value') + grid on +else + grid off +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function cb_apply(hObject, eventdata, handles); +fig = get(hObject, 'parent'); +elec = getappdata(fig, 'elec'); +transform = getappdata(fig, 'transform'); +% get the transformation details +rx = str2num(get(findobj(fig, 'tag', 'rx'), 'string')); +ry = str2num(get(findobj(fig, 'tag', 'ry'), 'string')); +rz = str2num(get(findobj(fig, 'tag', 'rz'), 'string')); +tx = str2num(get(findobj(fig, 'tag', 'tx'), 'string')); +ty = str2num(get(findobj(fig, 'tag', 'ty'), 'string')); +tz = str2num(get(findobj(fig, 'tag', 'tz'), 'string')); +sx = str2num(get(findobj(fig, 'tag', 'sx'), 'string')); +sy = str2num(get(findobj(fig, 'tag', 'sy'), 'string')); +sz = str2num(get(findobj(fig, 'tag', 'sz'), 'string')); +R = rotate ([rx ry rz]); +T = translate([tx ty tz]); +S = scale ([sx sy sz]); +H = S * T * R; +elec = ft_transform_headshape(H, elec); +transform = H * transform; +set(findobj(fig, 'tag', 'rx'), 'string', 0); +set(findobj(fig, 'tag', 'ry'), 'string', 0); +set(findobj(fig, 'tag', 'rz'), 'string', 0); +set(findobj(fig, 'tag', 'tx'), 'string', 0); +set(findobj(fig, 'tag', 'ty'), 'string', 0); +set(findobj(fig, 'tag', 'tz'), 'string', 0); +set(findobj(fig, 'tag', 'sx'), 'string', 1); +set(findobj(fig, 'tag', 'sy'), 'string', 1); +set(findobj(fig, 'tag', 'sz'), 'string', 1); +setappdata(fig, 'elec', elec); +setappdata(fig, 'transform', transform); +cb_redraw(hObject); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function cb_close(hObject, eventdata, handles); +% make the current transformation permanent and subsequently allow deleting the figure +cb_apply(gca); +% get the updated electrode from the figure +fig = hObject; +% hmmm, this is ugly +global norm +norm = getappdata(fig, 'elec'); +norm.m = getappdata(fig, 'transform'); +set(fig, 'CloseRequestFcn', @delete); +delete(fig); -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_freqanalysis.m b/external/fieldtrip/ft_freqanalysis.m index b84b9b2..a848258 100644 --- a/external/fieldtrip/ft_freqanalysis.m +++ b/external/fieldtrip/ft_freqanalysis.m @@ -1,11 +1,250 @@ -function varargout = funname(varargin); +function [freq] =ft_freqanalysis(cfg, data, flag); + +% FT_FREQANALYSIS performs frequency and time-frequency analysis +% on time series data over multiple trials +% +% Use as +% [freq] = ft_freqanalysis(cfg, data) +% +% The input data should be organised in a structure as obtained from +% the FT_PREPROCESSING function. The configuration depends on the type +% of computation that you want to perform. +% +% The configuration should contain: +% cfg.method = different methods of calculating the spectra +% 'mtmfft', analyses an entire spectrum for the entire data +% length, implements multitaper frequency transformation +% 'mtmconvol', implements multitaper time-frequency transformation +% based on multiplication in the frequency domain +% 'mtmwelch', performs frequency analysis using Welch's averaged +% modified periodogram method of spectral estimation +% 'wltconvol', implements wavelet time frequency transformation +% (using Morlet wavelets) based on multiplication in the frequency domain +% 'tfr', implements wavelet time frequency transformation +% (using Morlet wavelets) based on convolution in the time domain +% +% +% The other cfg options depend on the method that you select. You should +% read the help of the respective subfunction FT_FREQANALYSIS_XXX for the +% corresponding parameter options and for a detailed explanation of each method. +% +% See also FT_FREQANALYSIS_MTMFFT, FT_FREQANALYSIS_MTMCONVOL, FT_FREQANALYSIS_MTMWELCH +% FT_FREQANALYSIS_WLTCONVOL, FT_FREQANALYSIS_TFR + +% Undocumented local options: +% cfg.label +% cfg.labelcmb +% cfg.sgn +% cfg.sgncmb +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk + +% Copyright (C) 2003-2006, F.C. Donders Centre, Pascal Fries +% Copyright (C) 2004-2006, F.C. Donders Centre, Markus Siegel +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_freqanalysis.m 1401 2010-07-12 18:52:40Z jansch $ + +fieldtripdefs + +%allow for both the new and old implementation to be changed with a flag +%input + +% defaults for optional input/ouputfile +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +% load optional given inputfile as data +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + end +end + +if nargin < 3 + flag = 0; +end + +% check if the input data is valid for this function +data = checkdata(data, 'datatype', {'raw', 'comp', 'mvar'}, 'feedback', 'yes', 'hasoffset', 'yes', 'hastrialdef', 'yes'); + +% check if the input cfg is valid for this function +cfg = checkconfig(cfg, 'trackconfig', 'on'); +cfg = checkconfig(cfg, 'renamed', {'label', 'channel'}); +cfg = checkconfig(cfg, 'renamed', {'sgn', 'channel'}); +cfg = checkconfig(cfg, 'renamed', {'labelcmb', 'channelcmb'}); +cfg = checkconfig(cfg, 'renamed', {'sgncmb', 'channelcmb'}); +cfg = checkconfig(cfg, 'required', {'method'}); +cfg = checkconfig(cfg, 'renamedval', {'method', 'fft', 'mtmfft'}); +cfg = checkconfig(cfg, 'renamedval', {'method', 'convol', 'mtmconvol'}); + +% select trials of interest +if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end % set the default +if ~strcmp(cfg.trials, 'all') + fprintf('selecting %d trials\n', length(cfg.trials)); + data = selectdata(data, 'rpt', cfg.trials); +end + +if ~flag + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % HERE THE OLD IMPLEMENTATION STARTS + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + [freq] = feval(sprintf('ft_freqanalysis_%s',lower(cfg.method)), cfg, data); + +else + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % HERE THE NEW IMPLEMENTATION STARTS + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + % do the bookkeeping that is required for the input data + % chansel = ...; + + % do the bookkeeping that is required for the computation + %offset = data.offset; + + if ~isfield(cfg, 'padding'), cfg.padding = []; end + if ~isfield(cfg, 'output'), cfg.output = 'pow'; end + if ~isfield(cfg, 'taper'), cfg.taper = 'dpss'; end + if ~isfield(cfg, 'method'), error('you must specify a method in cfg.method'); end + if ~isfield(cfg, 'foi'), cfg.foi = []; end + if isequal(cfg.taper, 'dpss') && not(isfield(cfg, 'tapsmofrq')) + error('you must specify a smoothing parameter with taper = dpss'); + end + + ntrials = size(data.trial,2); + trllength = zeros(1, ntrials); + + for trllop=1:ntrials + trllength(trllop) = size(data.trial{trllop}, 2); + end + + + if strcmp(cfg.padding, 'maxperlen') + padding = max(trllength); + cfg.padding = padding/data.fsample; + else + padding = cfg.padding*data.fsample; + cfg.padding = padding; + if padding. +% +% $Id: ft_freqanalysis_mtmconvol.m 1149 2010-05-27 15:23:29Z sashae $ + +fieldtripdefs + +% ensure that this function is started as a subfunction of the FT_FREQANALYSIS wrapper +if ~exist('OCTAVE_VERSION') + [s, i] = dbstack; + if length(s)>1 + [caller_path, caller_name, caller_ext] = fileparts(s(2).name); + else + caller_path = ''; + caller_name = ''; + caller_ext = ''; + end + % evalin('caller', 'mfilename') does not work for Matlab 6.1 and 6.5 + if ~strcmp(caller_name, 'ft_freqanalysis') + error(['you should call FREQANALYSIS, instead of the ' upper(mfilename) ' subfunction']); + end +end +% set all the defaults +if ~isfield(cfg, 'method'), cfg.method = 'mtmconvol'; end +if ~isfield(cfg, 'keeptapers'), cfg.keeptapers = 'no'; end +if ~isfield(cfg, 'keeptrials'), cfg.keeptrials = 'no'; end +if ~isfield(cfg, 'calcdof'), cfg.calcdof = 'no'; end +if ~isfield(cfg, 'output'), cfg.output = 'powandcsd'; end +if ~isfield(cfg, 'pad'), cfg.pad = 'maxperlen'; end +if ~isfield(cfg, 'taper'), cfg.taper = 'dpss'; end +if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end +if ~isfield(cfg, 'phaseshift'), cfg.phaseshift = 'no'; end +if ~isfield(cfg, 'precision'), cfg.precision = 'double'; end +if strcmp(cfg.output, 'fourier'), + cfg.keeptrials = 'yes'; + cfg.keeptapers = 'yes'; +end + +% setting a flag (csdflg) that determines whether this routine outputs +% only power-spectra or power-spectra and cross-spectra? +if strcmp(cfg.output,'pow') + powflg = 1; + csdflg = 0; + fftflg = 0; +elseif strcmp(cfg.output,'powandcsd') + powflg = 1; + csdflg = 1; + fftflg = 0; +elseif strcmp(cfg.output,'fourier') + powflg = 0; + csdflg = 0; + fftflg = 1; +else + error('Unrecognized output required'); +end + +if ~isfield(cfg, 'channelcmb') && csdflg + %set the default for the channelcombination + cfg.channelcmb = {'all' 'all'}; +elseif isfield(cfg, 'channelcmb') && ~csdflg + % no cross-spectrum needs to be computed, hence remove the combinations from cfg + cfg = rmfield(cfg, 'channelcmb'); +end + +% ensure that channelselection and selection of channelcombinations is +% perfomed consistently +cfg.channel = ft_channelselection(cfg.channel, data.label); +if isfield(cfg, 'channelcmb') + cfg.channelcmb = ft_channelcombination(cfg.channelcmb, data.label); +end + +% determine the corresponding indices of all channels +sgnindx = match_str(data.label, cfg.channel); +numsgn = size(sgnindx,1); +if csdflg + % determine the corresponding indices of all channel combinations + sgncmbindx = zeros(size(cfg.channelcmb)); + for k=1:size(cfg.channelcmb,1) + sgncmbindx(k,1) = strmatch(cfg.channelcmb(k,1), data.label, 'exact'); + sgncmbindx(k,2) = strmatch(cfg.channelcmb(k,2), data.label, 'exact'); + end + + numsgncmb = size(sgncmbindx,1); + sgnindx = unique([sgnindx(:); sgncmbindx(:)]); + numsgn = length(sgnindx); + + cutdatindcmb = zeros(size(sgncmbindx)); + for sgnlop = 1:numsgn + cutdatindcmb(find(sgncmbindx == sgnindx(sgnlop))) = sgnlop; + end +end + +% if rectan is 1 it means that trials are of equal lengths +numper = numel(data.trial); +numdatbnsarr = zeros(numper, 1); +for perlop = 1:numper + numdatbnsarr(perlop) = size(data.trial{perlop},2); +end +rectan = all(numdatbnsarr==numdatbnsarr(1)); + +% if cfg.pad is 'maxperlen', this is realized here: +% first establish where the first possible sample is +min_smp = min(data.offset); +% then establish where the last possible sample is +max_smp = max(numdatbnsarr(:)+data.offset(:)); +if isequal(cfg.pad, 'maxperlen') + % pad the data from the first possible to last possible sample + cfg.pad = (max_smp-min_smp) ./ data.fsample; +else + % check that the specified padding is not too short + if cfg.pad<((max_smp-min_smp)/data.fsample) + error('the padding that you specified is shorter than the longest trial in the data'); + end +end +clear min_smp max_smp +numsmp = round(cfg.pad .* data.fsample); + +% keeping trials and/or tapers? +if strcmp(cfg.keeptrials,'no') && strcmp(cfg.keeptapers,'no') + keeprpt = 1; +elseif strcmp(cfg.keeptrials,'yes') && strcmp(cfg.keeptapers,'no') + keeprpt = 2; +elseif strcmp(cfg.keeptrials,'no') && strcmp(cfg.keeptapers,'yes') + error('There is currently no support for keeping tapers WITHOUT KEEPING TRIALS.'); +elseif strcmp(cfg.keeptrials,'yes') && strcmp(cfg.keeptapers,'yes') + keeprpt = 4; +end + +if strcmp(cfg.keeptrials,'yes') && strcmp(cfg.keeptapers,'yes') + if ~strcmp(cfg.output, 'fourier'), + error('Keeping trials AND tapers is only possible with fourier as the output.'); + elseif strcmp(cfg.taper, 'dpss') && ~(all(cfg.tapsmofrq==cfg.tapsmofrq(1)) && all(cfg.t_ftimwin==cfg.t_ftimwin(1))), + error('Currently you can only keep trials AND tapers, when using the number of tapers per frequency is equal across frequency'); + end +end + +if strcmp(cfg.taper, 'alpha') && ~all(cfg.t_ftimwin==cfg.t_ftimwin(1)) + error('you can only use alpha tapers with an cfg.t_ftimwin that is equal for all frequencies'); +end + +minoffset = min(data.offset); +timboi = round(cfg.toi .* data.fsample - minoffset); +toi = round(cfg.toi .* data.fsample) ./ data.fsample; +numtoi = length(cfg.toi); +numfoi = length(cfg.foi); +numtap = zeros(numfoi,1); + +% calculating degrees of freedom +calcdof = strcmp(cfg.calcdof,'yes'); +if calcdof + dof = zeros(numper,numfoi,numtoi); +end; + +% compute the tapers and their fft +knlspctrmstr = cell(numfoi,1); +for foilop = 1:numfoi + acttapnumsmp = round(cfg.t_ftimwin(foilop) .* data.fsample); + if strcmp(cfg.taper, 'dpss') + % create a sequence of DPSS (Slepian) tapers, ensure that the input arguments are double + tap = double_dpss(acttapnumsmp, acttapnumsmp .* (cfg.tapsmofrq(foilop)./data.fsample)); + elseif strcmp(cfg.taper, 'sine') + tap = sine_taper(acttapnumsmp, acttapnumsmp .* (cfg.tapsmofrq(foilop)./data.fsample)); + elseif strcmp(cfg.taper, 'alpha') + tap = alpha_taper(acttapnumsmp, cfg.foi(foilop)./data.fsample); + tap = tap./norm(tap); + % freqanalysis_mtmconvol always throws away the last taper of the Slepian sequence, so add a dummy taper + tap(:,2) = nan; + else + % create a single taper according to the window specification as a replacement for the DPSS (Slepian) sequence + tap = window(cfg.taper, acttapnumsmp); + tap = tap./norm(tap); + % freqanalysis_mtmconvol always throws away the last taper of the Slepian sequence, so add a dummy taper + tap(:,2) = nan; + end + numtap(foilop) = size(tap,2)-1; + if (numtap(foilop) < 1) + error(sprintf('%.3f Hz : datalength to short for specified smoothing\ndatalength: %.3f s, smoothing: %.3f Hz, minimum smoothing: %.3f Hz', cfg.foi(foilop), acttapnumsmp/data.fsample, cfg.tapsmofrq(foilop), data.fsample/acttapnumsmp)); + elseif (numtap(foilop) < 2) && strcmp(cfg.taper, 'dpss') + fprintf('%.3f Hz : WARNING - using only one taper for specified smoothing\n',cfg.foi(foilop)); + end + ins = ceil(numsmp./2) - floor(acttapnumsmp./2); + prezer = zeros(ins,1); + pstzer = zeros(numsmp - ((ins-1) + acttapnumsmp)-1,1); + ind = (0:acttapnumsmp-1)' .* ((2.*pi./data.fsample) .* cfg.foi(foilop)); + knlspctrmstr{foilop} = complex(zeros(numtap(foilop),numsmp)); + for taplop = 1:numtap(foilop) + try + % construct the complex wavelet + if strcmp(cfg.phaseshift,'yes') % shift wavelets with pi (see undocumented options) + coswav = vertcat(prezer,tap(:,taplop).*-cos(ind),pstzer); + sinwav = vertcat(prezer,tap(:,taplop).*-sin(ind),pstzer); + else + coswav = vertcat(prezer,tap(:,taplop).*cos(ind),pstzer); + sinwav = vertcat(prezer,tap(:,taplop).*sin(ind),pstzer); + end + wavelet = complex(coswav, sinwav); + % store the fft of the complex wavelet + knlspctrmstr{foilop}(taplop,:) = fft(wavelet,[],1)'; + global fb + if ~isempty(fb) && fb + % plot the wavelet for debugging + figure + plot(tap(:,taplop).*cos(ind), 'r'); hold on + plot(tap(:,taplop).*sin(ind), 'g'); + plot(tap(:,taplop) , 'b'); + title(sprintf('taper %d @ %g Hz', taplop, cfg.foi(foilop))); + drawnow + end + end + end +end + +% added cfg.precision (undocumented) in below memory allocation +if keeprpt == 1 + if powflg, powspctrm = zeros(numsgn,numfoi,numtoi,cfg.precision); end + if csdflg, crsspctrm = complex(zeros(numsgncmb,numfoi,numtoi,cfg.precision)); end + if fftflg, fourierspctrm = complex(zeros(numsgn,numfoi,numtoi,cfg.precision)); end + cntpertoi = zeros(numfoi,numtoi); + dimord = 'chan_freq_time'; +elseif keeprpt == 2 + if powflg, powspctrm = zeros(numper,numsgn,numfoi,numtoi,cfg.precision); end + if csdflg, crsspctrm = complex(zeros(numper,numsgncmb,numfoi,numtoi,cfg.precision)); end + if fftflg, fourierspctrm = complex(zeros(numper,numsgn,numfoi,numtoi,cfg.precision)); end + dimord = 'rpt_chan_freq_time'; +elseif keeprpt == 4 + % FIXME this works only if all frequencies have the same number of tapers + if powflg, powspctrm = zeros(numper*numtap(1),numsgn,numfoi,numtoi,cfg.precision); end + if csdflg, crsspctrm = complex(zeros(numper*numtap(1),numsgncmb,numfoi,numtoi,cfg.precision)); end + if fftflg, fourierspctrm = complex(zeros(numper*numtap(1),numsgn,numfoi,numtoi,cfg.precision)); end + cnt = 0; + dimord = 'rpttap_chan_freq_time'; +end + +for perlop = 1:numper + fprintf('processing trial %d: %d samples\n', perlop, numdatbnsarr(perlop,1)); + if keeprpt == 2 + cnt = perlop; + end + numdatbns = numdatbnsarr(perlop,1); + % prepad = zeros(1,data.offset(perlop) - minoffset); + % pstpad = zeros(1,minoffset + numsmp - (data.offset(perlop) + numdatbns)); + % datspctra = complex(zeros(numsgn,numsmp)); + % for sgnlop = 1:numsgn + % datspctra(sgnlop,:) = fft([prepad, data.trial{perlop}(sgnindx(sgnlop),:), ... + % pstpad],[],2); + % end + prepad = zeros(numsgn,data.offset(perlop) - minoffset); + pstpad = zeros(numsgn,minoffset + numsmp - (data.offset(perlop) + numdatbns)); + tmp = data.trial{perlop}(sgnindx,:); + tmp = [prepad tmp pstpad]; + % avoid the use of a 3rd input argument to facilitate compatibility with star-P + % use explicit transpose, to avoid complex conjugate transpose + datspctra = transpose(fft(transpose(tmp))); + for foilop = 1:numfoi + fprintf('processing frequency %d (%.2f Hz), %d tapers\n', foilop,cfg.foi(foilop),numtap(foilop)); + actfoinumsmp = cfg.t_ftimwin(foilop) .* data.fsample; + acttimboiind = find(timboi >= (-minoffset + data.offset(perlop) + (actfoinumsmp ./ 2)) & timboi < (-minoffset + data.offset(perlop) + numdatbns - (actfoinumsmp ./2))); + nonacttimboiind = find(timboi < (-minoffset + data.offset(perlop) + (actfoinumsmp ./ 2)) | timboi >= (-minoffset + data.offset(perlop) + numdatbns - (actfoinumsmp ./2))); + acttimboi = timboi(acttimboiind); + numacttimboi = length(acttimboi); + if keeprpt ==1 + cntpertoi(foilop,acttimboiind) = cntpertoi(foilop,acttimboiind) + 1; + end + for taplop = 1:numtap(foilop) + if keeprpt == 3 + cnt = taplop; + elseif keeprpt == 4 + % this once again assumes a fixed number of tapers per frequency + cnt = (perlop-1)*numtap(1) + taplop; + end + autspctrmacttap = complex(zeros(numsgn,numacttimboi), zeros(numsgn,numacttimboi)); + if numacttimboi > 0 + for sgnlop = 1:numsgn + dum = fftshift(ifft(datspctra(sgnlop,:) .* knlspctrmstr{foilop}(taplop,:),[],2)); + autspctrmacttap(sgnlop,:) = dum(acttimboi); + end + end + if powflg + powdum = 2.* abs(autspctrmacttap) .^ 2 ./ actfoinumsmp; + if strcmp(cfg.taper, 'sine') + powdum = powdum .* (1 - (((taplop - 1) ./ numtap(foilop)) .^ 2)); + end + if keeprpt == 1 && numacttimboi > 0 + powspctrm(:,foilop,acttimboiind) = powspctrm(:,foilop,acttimboiind) + reshape(powdum ./ numtap(foilop),[numsgn,1,numacttimboi]); + elseif keeprpt == 2 && numacttimboi > 0 + powspctrm(cnt,:,foilop,acttimboiind) = powspctrm(cnt,:,foilop,acttimboiind) + reshape(powdum ./ numtap(foilop),[1,numsgn,1,numacttimboi]); + powspctrm(cnt,:,foilop,nonacttimboiind) = nan; + elseif keeprpt == 4 && numacttimboi > 0 + powspctrm(cnt,:,foilop,acttimboiind) = reshape(powdum,[1,numsgn,1,numacttimboi]); + powspctrm(cnt,:,foilop,nonacttimboiind) = nan; + elseif (keeprpt == 4 || keeprpt == 2) && numacttimboi == 0 + powspctrm(cnt,:,foilop,nonacttimboiind) = nan; + end + end + if fftflg + fourierdum = (autspctrmacttap) .* sqrt(2 ./ actfoinumsmp); %cf Numercial Receipes 13.4.9 + if keeprpt == 1 && numacttimboi > 0 + fourierspctrm(:,foilop,acttimboiind) = fourierspctrm(:,foilop,acttimboiind) + reshape((fourierdum ./ numtap(foilop)),[numsgn,1,numacttimboi]); + elseif keeprpt == 2 && numacttimboi > 0 + fourierspctrm(cnt,:,foilop,acttimboiind) = fourierspctrm(cnt,:,foilop,acttimboiind) + reshape(fourierdum ./ numtap(foilop),[1,numsgn,1,numacttimboi]); + fourierspctrm(cnt,:,foilop,nonacttimboiind) = nan; + elseif keeprpt == 4 && numacttimboi > 0 + fourierspctrm(cnt,:,foilop,acttimboiind) = reshape(fourierdum,[1,numsgn,1,numacttimboi]); + fourierspctrm(cnt,:,foilop,nonacttimboiind) = nan; + elseif (keeprpt == 4 || keeprpt == 2) && numacttimboi == 0 + fourierspctrm(cnt,:,foilop,nonacttimboiind) = nan; + end + end + if csdflg + csddum = 2.* (autspctrmacttap(cutdatindcmb(:,1),:) .* conj(autspctrmacttap(cutdatindcmb(:,2),:))) ./ actfoinumsmp; + if keeprpt == 1 && numacttimboi > 0 + crsspctrm(:,foilop,acttimboiind) = crsspctrm(:,foilop,acttimboiind) + reshape((csddum ./ numtap(foilop)),[numsgncmb,1,numacttimboi]); + elseif keeprpt == 2 && numacttimboi > 0 + crsspctrm(cnt,:,foilop,acttimboiind) = crsspctrm(cnt,:,foilop,acttimboiind) + reshape(csddum ./ numtap(foilop),[1,numsgncmb,1,numacttimboi]); + crsspctrm(cnt,:,foilop,nonacttimboiind) = nan; + elseif keeprpt == 4 && numacttimboi > 0 + crsspctrm(cnt,:,foilop,acttimboiind) = reshape(csddum,[1,numsgncmb,1,numacttimboi]); + crsspctrm(cnt,:,foilop,nonacttimboiind) = nan; + elseif (keeprpt == 4 || keeprpt == 2) && numacttimboi == 0 + crsspctrm(cnt,:,foilop,nonacttimboiind) = nan; + end + end + end % for taplop + if calcdof + dof(perlop,foilop,acttimboiind) = numtap(foilop); + end + end % for foilop +end % for perlop + +if keeprpt == 1 + ws = warning('off'); + if powflg + powspctrm(:,:,:) = powspctrm(:,:,:) ./ repmat(permute(cntpertoi,[3,1,2]),[numsgn,1,1]); + end + if fftflg + fourierspctrm(:,:,:) = fourierspctrm(:,:,:) ./ repmat(permute(cntpertoi,[3,1,2]),[numsgn,1,1]); + end + if csdflg + crsspctrm(:,:,:) = crsspctrm(:,:,:) ./ repmat(permute(cntpertoi,[3,1,2]),[numsgncmb,1,1]); + end + % return to previous warning state + warning(ws); +end + +% collect the results +freq.label = data.label(sgnindx); +freq.dimord = dimord; +freq.freq = cfg.foi; +freq.time = toi; + +if powflg + freq.powspctrm = powspctrm; +end + +if csdflg + freq.labelcmb = cfg.channelcmb; + freq.crsspctrm = crsspctrm; +end + +if fftflg + freq.fourierspctrm = fourierspctrm; +end + +if calcdof + freq.dof=2*dof; +end; + +if keeprpt == 2, + freq.cumtapcnt = repmat(numtap(:)', [size(powspctrm,1) 1]); +elseif keeprpt == 4, + %all(numtap(1)==numtap) + freq.cumtapcnt = repmat(numtap(1), [size(fourierspctrm,1)./numtap(1) 1]); +end + +try, freq.grad = data.grad; end % remember the gradiometer array +try, freq.elec = data.elec; end % remember the electrode array +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add information about the version of this function to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i1] = dbstack; + cfg.version.name = st(i1); +end +cfg.version.id = '$Id: ft_freqanalysis_mtmconvol.m 1149 2010-05-27 15:23:29Z sashae $'; +% remember the configuration details of the input data +try, cfg.previous = data.cfg; end +% remember the exact configuration details in the output +freq.cfg = cfg; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION ensure that the first two input arguments are of double +% precision this prevents an instability (bug) in the computation of the +% tapers for Matlab 6.5 and 7.0 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [tap] = double_dpss(a, b, varargin) +tap = dpss(double(a), double(b), varargin{:}); + diff --git a/external/fieldtrip/ft_freqanalysis_mtmfft.m b/external/fieldtrip/ft_freqanalysis_mtmfft.m new file mode 100644 index 0000000..162ef35 --- /dev/null +++ b/external/fieldtrip/ft_freqanalysis_mtmfft.m @@ -0,0 +1,441 @@ +function [freq] = ft_freqanalysis_mtmfft(cfg, data); + +% FT_FREQANALYSIS_MTMFFT performs frequency analysis on any time series +% trial data using the 'multitaper method' (MTM) based on discrete +% prolate spheroidal sequences (Slepian sequences) as tapers. Alternatively, +% you can use conventional tapers (e.g. Hanning). +% +% Use as +% [freq] = ft_freqanalysis(cfg, data) +% +% The data should be organised in a structure as obtained from +% the FT_PREPROCESSING function. The configuration should be according to +% cfg.method = method used for frequency or time-frequency decomposition +% see FT_FREQANALYSIS for details +% cfg.output = 'pow' return the power-spectra +% 'powandcsd' return the power and the cross-spectra +% 'fourier' return the complex Fourier-spectra +% cfg.taper = 'dpss', 'hanning' or many others, see WINDOW (default = 'dpss') +% +% For cfg.output='powandcsd', you should specify the channel combinations +% between which to compute the cross-spectra as cfg.channelcmb. Otherwise +% you should specify only the channels in cfg.channel. +% +% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), +% see FT_CHANNELSELECTION for details +% cfg.channelcmb = Mx2 cell-array with selection of channel pairs (default = {'all' 'all'}), +% see FT_CHANNELCOMBINATION for details +% cfg.foilim = [begin end], frequency band of interest +% cfg.tapsmofrq = number, the amount of spectral smoothing through +% multi-tapering. Note that 4 Hz smoothing means +% plus-minus 4 Hz, i.e. a 8 Hz smoothing box. +% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') +% cfg.keeptrials = 'yes' or 'no', return individual trials or average (default = 'no') +% cfg.keeptapers = 'yes' or 'no', return individual tapers or average (default = 'no') +% cfg.pad = number or 'maxperlen', length in seconds to which the data can be padded out (default = 'maxperlen') +% +% The padding will determine your spectral resolution. If you want to +% compare spectra from data pieces of different lengths, you should use +% the same cfg.pad for both, in order to spectrally interpolate them to +% the same spectral resolution. Note that this will run very slow if you +% specify cfg.pad as maxperlen AND the number of samples turns out to have +% a large prime factor sum. This is because the FFTs will then be computed +% very inefficiently. +% +% See also FT_FREQANALYSIS_MTMCONVOL, FT_REQANALYSIS_WLTCONVOL, FT_FREQANALYSIS_TFR + +% Undocumented local options +% cfg.calcdof = 'yes' calculate the degrees of freedom for every trial + +% Copyright (c) 2003-2006, Pascal Fries, F.C. Donders Centre +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_freqanalysis_mtmfft.m 1149 2010-05-27 15:23:29Z sashae $ + +fieldtripdefs + +% ensure that this function is started as a subfunction of the FT_FREQANALYSIS wrapper +if ~exist('OCTAVE_VERSION') + [s, i] = dbstack; + if length(s)>1 + [caller_path, caller_name, caller_ext] = fileparts(s(2).name); + else + caller_path = ''; + caller_name = ''; + caller_ext = ''; + end + % evalin('caller', 'mfilename') does not work for Matlab 6.1 and 6.5 + if ~strcmp(caller_name, 'ft_freqanalysis') + error(['you should call FREQANALYSIS, instead of the ' upper(mfilename) ' subfunction']); + end +end + +% set all the defaults +if ~isfield(cfg, 'method'), cfg.method = 'mtmfft'; end +if ~isfield(cfg, 'keeptapers'), cfg.keeptapers = 'no'; end +if ~isfield(cfg, 'keeptrials'), cfg.keeptrials = 'no'; end +if ~isfield(cfg, 'calcdof'), cfg.calcdof = 'no'; end +if ~isfield(cfg, 'pad'), cfg.pad = 'maxperlen'; end +if ~isfield(cfg, 'taper'), cfg.taper = 'dpss'; end +if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end +if ~isfield(cfg, 'foilim'), cfg.foilim = [0 data.fsample/2]; end +if ~isfield(cfg, 'output'), + if isfield(cfg, 'channelcmb') && ~isempty(cfg.channelcmb) + cfg.output = 'powandcsd'; + else + cfg.output = 'pow'; + end +end + +if strcmp(cfg.output, 'fourier'), + cfg.keeptrials = 'yes'; + cfg.keeptapers = 'yes'; +end + +if ~strcmp(cfg.method,'mtmfft') + error('unsupported method'); +end + +% setting a flag (csdflg) that determines whether this routine outputs +% only power-spectra or power-spectra and cross-spectra? +if strcmp(cfg.output,'pow') + powflg = 1; + csdflg = 0; + fftflg = 0; +elseif strcmp(cfg.output,'powandcsd') + powflg = 1; + csdflg = 1; + fftflg = 0; +elseif strcmp(cfg.output,'fourier') + powflg = 0; + csdflg = 0; + fftflg = 1; +else + error('unsupported value for cfg.method'); +end + +if ~isfield(cfg, 'channelcmb') && csdflg + %set the default for the channelcombination + cfg.channelcmb = {'all' 'all'}; +elseif isfield(cfg, 'channelcmb') && ~csdflg + % no cross-spectrum needs to be computed, hence remove the combinations from cfg + cfg = rmfield(cfg, 'channelcmb'); +end + +% ensure that channelselection and selection of channelcombinations is +% perfomed consistently +cfg.channel = ft_channelselection(cfg.channel, data.label); +if isfield(cfg, 'channelcmb') + cfg.channelcmb = ft_channelcombination(cfg.channelcmb, data.label); +end + +% determine the corresponding indices of all channels +sgnindx = match_str(data.label, cfg.channel); +numsgn = size(sgnindx,1); +if csdflg + % determine the corresponding indices of all channel combinations + sgncmbindx = zeros(size(cfg.channelcmb)); + for k=1:size(cfg.channelcmb,1) + sgncmbindx(k,1) = find(strcmp(cfg.channelcmb(k,1), data.label)); + sgncmbindx(k,2) = find(strcmp(cfg.channelcmb(k,2), data.label)); + % this works the same, but is much slower in Octave + % sgncmbindx(k,1) = strmatch(cfg.channelcmb(k,1), data.label, 'exact'); + % sgncmbindx(k,2) = strmatch(cfg.channelcmb(k,2), data.label, 'exact'); + end + + numsgncmb = size(sgncmbindx,1); + sgnindx = unique([sgnindx(:); sgncmbindx(:)]); + numsgn = length(sgnindx); + + cutdatindcmb = zeros(size(sgncmbindx)); + for sgnlop = 1:numsgn + cutdatindcmb(find(sgncmbindx == sgnindx(sgnlop))) = sgnlop; + end +end + +% if rectan is 1 it means that trials are of equal lengths +numper = numel(data.trial); +rectan = 1; +for perlop = 1:numper + numdatbnsarr(perlop,1) = size(data.trial{perlop},2); +end +rectan = all(numdatbnsarr==numdatbnsarr(1)); + +% if cfg.pad is 'maxperlen', this is realized here: +if isequal(cfg.pad, 'maxperlen') + cfg.pad = max(numdatbnsarr,[],1) ./ data.fsample; +else + % check that the specified padding is not too short + if cfg.pad<(max(numdatbnsarr,[],1)/data.fsample) + error('the padding that you specified is shorter than the longest trial in the data'); + end +end +numsmp = ceil(cfg.pad .* data.fsample); % this used to be "cfg.pad .* data.fsample" + +% keeping trials and/or tapers? +if strcmp(cfg.keeptrials,'no') && strcmp(cfg.keeptapers,'no') + keeprpt = 1; +elseif strcmp(cfg.keeptrials,'yes') && strcmp(cfg.keeptapers,'no') + keeprpt = 2; +elseif strcmp(cfg.keeptrials,'no') && strcmp(cfg.keeptapers,'yes') + error('There is no support for keeping tapers WITHOUT KEEPING TRIALS.'); +elseif strcmp(cfg.keeptrials,'yes') && strcmp(cfg.keeptapers,'yes') + keeprpt = 4; +end + +% calculating degrees of freedom +calcdof = strcmp(cfg.calcdof,'yes'); + +% doing the computation +boilim = round(cfg.foilim ./ (data.fsample ./ numsmp)) + 1; +boi = boilim(1):boilim(2); +numboi = size(boi,2); +foi = (boi-1) ./ cfg.pad; + +if keeprpt == 1 + if powflg, powspctrm = zeros(numsgn,numboi); end + if csdflg, crsspctrm = complex(zeros(numsgncmb,numboi)); end + if fftflg, fourierspctrm = complex(zeros(numsgn,numboi)); end + dimord = 'chan_freq'; +elseif keeprpt == 2 + if powflg, powspctrm = zeros(numper,numsgn,numboi); end + if csdflg, crsspctrm = complex(zeros(numper,numsgncmb,numboi)); end + if fftflg, fourierspctrm = complex(zeros(numper,numsgn,numboi)); end + dimord = 'rpt_chan_freq'; +elseif keeprpt == 4 + if rectan == 1, % compute the amount of memory needed to collect the results + numdatbns = numdatbnsarr(1,1); + if strcmp(cfg.taper, 'dpss'), + % ensure that the input arguments are double precision + tap = double_dpss(numdatbns, numdatbns*(cfg.tapsmofrq./data.fsample))'; + elseif strcmp(cfg.taper, 'sine') + tap = sine_taper(numdatbns, numdatbns*(cfg.tapsmofrq./data.fsample))'; + else + tap(2,:) = nan; + end + numtap = size(tap,1)-1; + numrpt = numtap.*numper; + elseif rectan == 0, + numrpt = 0; + for perlop = 1:numper + numdatbns = numdatbnsarr(perlop,1); + if strcmp(cfg.taper, 'dpss'), + % ensure that the input arguments are double precision + tap = double_dpss(numdatbns, numdatbns*(cfg.tapsmofrq./data.fsample))'; + elseif strcmp(cfg.taper, 'sine') + tap = sine_taper(numdatbns, numdatbns*(cfg.tapsmofrq./data.fsample))'; + else + tap(2,:) = nan; + end + numtap = size(tap,1)-1; + numrpt = numrpt + numtap; + end + end + if powflg, powspctrm = zeros(numrpt,numsgn,numboi); end + if csdflg, crsspctrm = complex(zeros(numrpt,numsgncmb,numboi)); end + if fftflg, fourierspctrm = complex(zeros(numrpt,numsgn,numboi)); end + cnt = 0; + dimord = 'rpttap_chan_freq'; +end + +% these count the number of tapers +cumsumcnt = zeros(numper,1); +cumtapcnt = zeros(numper,1); + +if rectan == 1 + % trials are of equal length, compute the set of tapers only once + numdatbns = numdatbnsarr(1,1); + if strcmp(cfg.taper, 'dpss') + % create a sequence of DPSS (Slepian) tapers + % ensure that the input arguments are double precision + tap = double_dpss(numdatbns,numdatbns*(cfg.tapsmofrq./data.fsample))'; + elseif strcmp(cfg.taper, 'sine') + tap = sine_taper(numdatbns, numdatbns*(cfg.tapsmofrq./data.fsample))'; + else + % create a single taper according to the window specification as a + % replacement for the DPSS (Slepian) sequence + tap = window(cfg.taper, numdatbns)'; + tap = tap./norm(tap); + % freqanalysis_mtmfft always throws away the last taper of the Slepian sequence, so add a dummy taper + tap(2,:) = nan; + end + numtap = size(tap,1) - 1; + if keeprpt == 2 || calcdof + cumtapcnt(:) = numtap; + end + if (numtap < 1) + error(sprintf(... + 'datalength to short for specified smoothing\ndatalength: %.3f s, smoothing: %.3f Hz, minimum smoothing: %.3f Hz',... + numdatbns/data.fsample, cfg.tapsmofrq, data.fsample/numdatbns)); + elseif (numtap < 2) && strcmp(cfg.taper, 'dpss') + fprintf('WARNING: using only one taper for specified smoothing\n'); + end + pad = zeros(1,numsmp - numdatbns); +end + +for perlop = 1:numper + fprintf('processing trial %d, ', perlop); + if keeprpt == 2 + cnt = perlop; + cumsumcnt(cnt,1) = numdatbnsarr(perlop,1); + end + if rectan == 0 + % trials are not of equal length, compute the set of tapers for this trial + numdatbns = numdatbnsarr(perlop,1); + if strcmp(cfg.taper, 'dpss') + % create a sequence of DPSS (Slepian) tapers + % ensure that the input arguments are double precision + tap = double_dpss(numdatbns,numdatbns*(cfg.tapsmofrq./data.fsample))'; + elseif strcmp(cfg.taper, 'sine') + tap = sine_taper(numdatbns, numdatbns*(cfg.tapsmofrq./data.fsample))'; + else + % create a single taper according to the window specification as a + % replacement for the DPSS (Slepian) sequence + tap = window(cfg.taper, numdatbns)'; + tap = tap./norm(tap); + % freqanalysis_mtmfft always throws away the last taper of the Slepian sequence, so add a dummy taper + tap(2,:) = nan; + end + numtap = size(tap,1) - 1; + if keeprpt == 2 || calcdof + cnt = perlop; + cumtapcnt(cnt,1) = numtap; + end + if (numtap < 1) + error(sprintf(... + 'datalength to short for specified smoothing\ndatalength: %.3f s, smoothing: %.3f Hz, minimum smoothing: %.3f Hz',... + numdatbns/data.fsample, cfg.tapsmofrq, data.fsample/numdatbns)); + elseif (numtap < 2) && strcmp(cfg.taper, 'dpss') + fprintf('WARNING: using only one taper for specified smoothing\n'); + end + pad = zeros(1,numsmp - numdatbns); + end + for taplop = 1:numtap + if keeprpt == 4 + cnt = cnt+1; + cumsumcnt(perlop,1) = numdatbnsarr(perlop,1); + cumtapcnt(perlop,1) = numtap; + end + if calcdof + cumtapcnt(perlop,1) = numtap; + end + + autspctrmacttap = complex(zeros(numsgn,numboi)); + for sgnlop = 1:numsgn + dum = fft([data.trial{perlop}(sgnindx(sgnlop),:) .* tap(taplop,:) , ... + pad],[],2); + autspctrmacttap(sgnlop,:) = dum(boi); + end + if taplop == 1 + fprintf('nfft: %d samples, taper length: %d samples, %d tapers\n',length(dum),size(tap,2),numtap); + end + if powflg + powdum = 2 .* (autspctrmacttap .* conj(autspctrmacttap)) ./ numsmp; %cf Numercial Receipes 13.4.9 + if keeprpt == 1 + powspctrm(:,:) = powspctrm(:,:) + (powdum ./ numtap); + elseif keeprpt == 2 + powspctrm(cnt,:,:) = powspctrm(cnt,:,:) + (permute(powdum,[3,1,2]) ./ numtap); + elseif keeprpt == 4 + powspctrm(cnt,:,:) = powdum; + end + end + if fftflg + fourierdum = (autspctrmacttap) .* sqrt(2 ./ numsmp); %cf Numercial Receipes 13.4.9 + if keeprpt == 1 + fourierspctrm(:,:) = fourierspctrm(:,:) + (fourierdum ./ numtap); + elseif keeprpt == 2 + fourierspctrm(cnt,:,:) = fourierspctrm(cnt,:,:) + (permute(fourierdum,[3,1,2]) ./ numtap); + elseif keeprpt == 4 + fourierspctrm(cnt,:,:) = fourierdum; + end + end + if csdflg + csddum = 2.* (autspctrmacttap(cutdatindcmb(:,1),:) .* ... + conj(autspctrmacttap(cutdatindcmb(:,2),:))) ./ numsmp; + if keeprpt == 1 + crsspctrm(:,:) = crsspctrm(:,:) + csddum ./ numtap; + elseif keeprpt == 2 + crsspctrm(cnt,:,:) = crsspctrm(cnt,:,:) + permute(csddum,[3,1,2]) ./ numtap; + elseif keeprpt == 4 + crsspctrm(cnt,:,:) = csddum; + end + end + end % taplop +end % perlop +if keeprpt ==1 + if powflg, powspctrm = powspctrm ./ numper; end + if csdflg, crsspctrm = crsspctrm ./ numper; end +end + +% collect the results +freq.label = data.label(sgnindx); +freq.dimord = dimord; +freq.freq = foi; +if powflg + freq.powspctrm = powspctrm; +end +if fftflg + freq.fourierspctrm = fourierspctrm; +end + +if csdflg + freq.labelcmb = cfg.channelcmb; + freq.crsspctrm = crsspctrm; +end + +if strcmp(cfg.method,'mtmfft') && (keeprpt == 2 || keeprpt == 4) + freq.cumsumcnt = cumsumcnt; +end + +if strcmp(cfg.method,'mtmfft') && (keeprpt == 2 || keeprpt == 4) + freq.cumtapcnt = cumtapcnt; +end + +if calcdof + freq.dof=2*repmat(cumtapcnt,[1,numboi]); +end; + +try, freq.grad = data.grad; end % remember the gradiometer array +try, freq.elec = data.elec; end % remember the electrode array + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add information about the version of this function to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i1] = dbstack; + cfg.version.name = st(i1); +end +cfg.version.id = '$Id: ft_freqanalysis_mtmfft.m 1149 2010-05-27 15:23:29Z sashae $'; +% remember the configuration details of the input data +try, cfg.previous = data.cfg; end +% remember the exact configuration details in the output +freq.cfg = cfg; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION ensure that the first two input arguments are of double +% precision this prevents an instability (bug) in the computation of the +% tapers for Matlab 6.5 and 7.0 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [tap] = double_dpss(a, b, varargin); +tap = dpss(double(a), double(b), varargin{:}); + diff --git a/external/fieldtrip/ft_freqanalysis_mtmwelch.m b/external/fieldtrip/ft_freqanalysis_mtmwelch.m new file mode 100644 index 0000000..7b5da35 --- /dev/null +++ b/external/fieldtrip/ft_freqanalysis_mtmwelch.m @@ -0,0 +1,139 @@ +function [freq] = ft_freqanalysis_mtmwelch(cfg, data); + +% FT_FREQANALYSIS_MTMWELCH performs frequency analysis on any time series +% trial data using the 'multitaper method' (MTM) based on discrete +% prolate spheroidal sequences (Slepian sequences) as tapers. Alternatively, +% you can use conventional tapers (e.g. Hanning). +% +% Besides multitapering, this function uses Welch's averaged, modified +% periodogram method. The data is divided into a number of sections with +% overlap, each section is windowed with the specified taper(s) and the +% powerspectra are computed and averaged over the sections in each trial. +% +% Use as +% [freq] = ft_freqanalysis(cfg, data) +% +% The data should be organised in a structure as obtained from +% the FT_PREPROCESSING function. The configuration should be according to +% cfg.method = method used for frequency or time-frequency decomposition +% see FT_FREQANALYSIS for details +% cfg.output = 'pow' return the power-spectra +% 'powandcsd' return the power and the cross-spectra +% cfg.taper = 'dpss', 'hanning' or many others, see WINDOW (default = 'dpss') +% +% For cfg.output='powandcsd', you should specify the channel combinations +% between which to compute the cross-spectra as cfg.channelcmb. Otherwise +% you should specify only the channels in cfg.channel. +% +% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), +% see FT_CHANNELSELECTION for details +% cfg.channelcmb = Mx2 cell-array with selection of channel pairs (default = {'all' 'all'}), +% see FT_CHANNELCOMBINATION for details +% +% This function uses FT_FREQANALYSIS_MTMCONVOL for the low-level +% computations, and you can use the options of that function to specify +% the length of the time windows, the amount of overlap, and the amount +% of spectral smoothing (in case of dpss tapers) per window. +% +% cfg.foi = vector 1 x numfoi, frequencies of interest +% cfg.t_ftimwin = vector 1 x numfoi, length of time window (in seconds) +% cfg.tapsmofrq = vector 1 x numfoi, the amount of spectral smoothing through +% multi-tapering. Note that 4 Hz smoothing means +% plus-minus 4 Hz, i.e. a 8 Hz smoothing box. +% cfg.toi = vector 1 x numtoi, the times on which the analysis windows +% should be centered (in seconds) +% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') +% cfg.keeptrials = 'yes' or 'no', return individual trials or average (default = 'no') +% cfg.keeptapers = 'yes' or 'no', return individual tapers or average (default = 'no') +% cfg.pad = number or 'maxperlen', length in seconds to which the data can be padded out (default = 'maxperlen') +% +% See also FT_FREQANALYSIS_MTMCONVOL, FT_FREQANALYSIS + +% This function depends on FT_FREQANALYSIS which uses cfg.method = 'mtmconvol' + +% Copyright (C) 2005-2006, F.C. Donders Centre +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_freqanalysis_mtmwelch.m 1085 2010-05-18 11:18:43Z sashae $ + +fieldtripdefs + +% ensure that this function is started as a subfunction of the FT_FREQANALYSIS wrapper +if ~exist('OCTAVE_VERSION') + [s, i] = dbstack; + if length(s)>1 + [caller_path, caller_name, caller_ext] = fileparts(s(2).name); + else + caller_path = ''; + caller_name = ''; + caller_ext = ''; + end + % evalin('caller', 'mfilename') does not work for Matlab 6.1 and 6.5 + if ~strcmp(caller_name, 'ft_freqanalysis') + error(['you should call FREQANALYSIS, instead of the ' upper(mfilename) ' subfunction']); + end +end + +tmin = inf; +tmax = -inf; +for i=1:length(data.time) + tmin = min(tmin, data.time{i}(1)); + tmax = max(tmax, data.time{i}(end)); +end + +fprintf('taking every sample as time of interest\n'); + +cfgconvol = cfg; +cfgconvol.method = 'mtmconvol'; +cfgconvol.toi = tmin:(1/data.fsample):tmax; +cfgconvol.trials = 'all'; % trial selection already applied during first call of freqanalysis + +% use mtmconvol to do the dirty work +freq = ft_freqanalysis(cfgconvol, data); + +% determine the time dimension +if strcmp(freq.dimord, 'chan_freq_time') + timedim = 3; +elseif strcmp(freq.dimord, 'rpt_chan_freq_time') + timedim = 4; +else + error('unexpected dimord'); +end + +% average over time +% NOTE: the degrees of freedom should be returned by freqanalysis_mtmconvol, +% and used here to weigh every trial and timepoint accordingly. But +% currently that is not yet possible. +freq.powspctrm = nan_mean(freq.powspctrm, timedim); +if isfield(freq, 'crsspctrm') + freq.crsspctrm = nan_mean(freq.crsspctrm, timedim); +end + +% remove the time axis +freq = rmfield(freq, 'time'); + +% update the dimord +if strcmp(freq.dimord, 'chan_freq_time') + freq.dimord = 'chan_freq'; +elseif strcmp(freq.dimord, 'rpt_chan_freq_time') + freq.dimord = 'rpt_chan_freq'; +end + +% only update the method and trials fields +freq.cfg.method = cfg.method; +freq.cfg.trials = cfg.trials; diff --git a/external/fieldtrip/ft_freqanalysis_mvar.m b/external/fieldtrip/ft_freqanalysis_mvar.m new file mode 100644 index 0000000..953f871 --- /dev/null +++ b/external/fieldtrip/ft_freqanalysis_mvar.m @@ -0,0 +1,126 @@ +function [freq] = ft_freqanalysis_mvar(cfg, data) + +% FT_FREQANALYSIS_MVAR performs frequency analysis on +% mvar data. +% +% Use as +% [freq] = ft_freqanalysis(cfg, data) + +% Copyright (C) 2009, Jan-Mathijs Schoffelen +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_freqanalysis_mvar.m 949 2010-04-21 18:09:23Z roboos $ + +if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end +if ~isfield(cfg, 'channelcmb'), cfg.channelcmb = {'all' 'all'}; end +if ~isfield(cfg, 'foi'), cfg.foi = 'all'; end +if ~isfield(cfg, 'keeptrials'), cfg.keeptrials = 'no'; end +if ~isfield(cfg, 'jackknife'), cfg.jackknife = 'no'; end +if ~isfield(cfg, 'keeptapers'), cfg.keeptapers = 'yes'; end +if ~isfield(cfg, 'feedback'), cfg.feedback = 'none'; end + +if strcmp(cfg.foi, 'all'), + cfg.foi = [0:1:data.fsampleorig./2]; +end + +cfg.channel = ft_channelselection(cfg.channel, data.label); +%cfg.channelcmb = channelcombination(cfg.channelcmb, data.label); + +%keeprpt = strcmp(cfg.keeptrials, 'yes'); +%keeptap = strcmp(cfg.keeptapers, 'yes'); +%dojack = strcmp(cfg.jackknife, 'yes'); +%dozscore = strcmp(cfg.zscore, 'yes'); + +%if ~keeptap, error('not keeping tapers is not possible yet'); end +%if dojack && keeprpt, error('you cannot simultaneously keep trials and do jackknifing'); end + +nfoi = length(cfg.foi); +ntoi = length(data.time); +nlag = size(data.coeffs,3); %change in due course +chanindx = match_str(data.label, cfg.channel); +nchan = length(chanindx); +label = data.label(chanindx); + +%---allocate memory +h = complex(zeros(nchan, nchan, nfoi, ntoi), zeros(nchan, nchan, nfoi, ntoi)); +a = complex(zeros(nchan, nchan, nfoi, ntoi), zeros(nchan, nchan, nfoi, ntoi)); +crsspctrm = complex(zeros(nchan, nchan, nfoi, ntoi), zeros(nchan, nchan, nfoi, ntoi)); + +%FIXME build in repetitions + +%---loop over the tois +progress('init', cfg.feedback, 'computing MAR-model based TFR'); +for j = 1:ntoi + progress(j/ntoi, 'processing timewindow %d from %d\n', j, ntoi); + + %---compute transfer function + ar = reshape(data.coeffs(:,:,:,j), [nchan nchan*nlag]); + [h(:,:,:,j), a(:,:,:,j)] = ar2h(ar, cfg.foi, data.fsampleorig); + + %---compute cross-spectra + nc = data.noisecov(:,:,j); + for k = 1:nfoi + tmph = h(:,:,k,j); + crsspctrm(:,:,k,j) = tmph*nc*tmph'; + end +end +progress('close'); + +%---create output-structure +freq = []; +freq.label = label; +freq.freq = cfg.foi; +freq.time = data.time; +%freq.cumtapcnt= ones(ntrl, 1)*ntap; +freq.dimord = 'chan_chan_freq_time'; +freq.transfer = h; +freq.itransfer = a; +freq.noisecov = data.noisecov; +freq.crsspctrm = crsspctrm; +freq.dof = data.dof; + +try, + cfg.previous = data.cfg; +end +freq.cfg = cfg; + +%---SUBFUNCTION to compute transfer-function from ar-parameters +function [h, zar] = ar2h(ar, foi, fsample) + +nchan = size(ar,1); +ncmb = nchan*nchan; +nfoi = length(foi); + +%---z-transform frequency axis +zfoi = exp(-2.*pi.*i.*(foi./fsample)); + +%---reorganize the ar-parameters +ar = reshape(ar, [ncmb size(ar,2)./nchan]); +ar = fliplr([reshape(eye(nchan), [ncmb 1]) -ar]); + +zar = complex(zeros(ncmb, nfoi), zeros(ncmb, nfoi)); +for k = 1:ncmb + zar(k,:) = polyval(ar(k,:),zfoi); +end +zar = reshape(zar, [nchan nchan nfoi]); +for k = 1:nfoi + h(:,:,k) = inv(zar(:,:,k)); +end +h = sqrt(2).*h; %account for the negative frequencies, normalization necessary for +%comparison with non-parametric (fft based) results in fieldtrip +zar = zar./sqrt(2); diff --git a/external/fieldtrip/ft_freqanalysis_tfr.m b/external/fieldtrip/ft_freqanalysis_tfr.m new file mode 100644 index 0000000..8f8be58 --- /dev/null +++ b/external/fieldtrip/ft_freqanalysis_tfr.m @@ -0,0 +1,246 @@ +function [freq] = ft_freqanalysis_tfr(cfg, data); + +% FT_FREQANALYSIS_TFR computes time-frequency representations of single-trial +% data using a convolution in the time-domain with Morlet's wavelets. +% +% Use as +% [freq] = ft_freqanalysis(cfg, data) +% +% The data should be organised in a structure as obtained from +% the FT_PREPROCESSING function. The configuration should be according to +% cfg.method = method used for frequency or time-frequency decomposition +% see FT_FREQANALYSIS for details +% cfg.foi = vector 1 x numfoi, frequencies of interest +% cfg.waveletwidth = 'width' of wavelets expressed in cycles (default = 7) +% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), +% see FT_CHANNELSELECTION for details +% cfg.downsample = ratio for downsampling, which occurs after convolution (default = 1) +% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') +% cfg.keeptrials = 'yes' or 'no', return individual trials or average (default = 'no') +% +% See also FT_FREQANALYSIS + +% Undocumented local options: +% cfg.latency +% cfg.output + +% Copyright (C) 2003, Ole Jensen, FCDC +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_freqanalysis_tfr.m 1085 2010-05-18 11:18:43Z sashae $ + +fieldtripdefs + +% ensure that this function is started as a subfunction of the FT_FREQANALYSIS wrapper +if ~exist('OCTAVE_VERSION') + [s, i] = dbstack; + if length(s)>1 + [caller_path, caller_name, caller_ext] = fileparts(s(2).name); + else + caller_path = ''; + caller_name = ''; + caller_ext = ''; + end + % evalin('caller', 'mfilename') does not work for Matlab 6.1 and 6.5 + if ~strcmp(caller_name, 'ft_freqanalysis') + error(['you should call FREQANALYSIS, instead of the ' upper(mfilename) ' subfunction']); + end +end + +% set the defaults +if ~isfield(cfg, 'method'), cfg.method = 'tfr'; end +if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end +if ~isfield(cfg, 'latency'), cfg.latency = 'minperlength'; end +if ~isfield(cfg, 'keeptrials'), cfg.keeptrials = 'no'; end +if ~isfield(cfg, 'waveletwidth'), cfg.waveletwidth = 7; end +if ~isfield(cfg, 'downsample'), cfg.downsample = 1; end +if ~isfield(cfg, 'feedback'), cfg.feedback = 'text'; end + +if isfield(cfg, 'output') && strcmp(cfg.output, 'powandcsd'), + error('This function does not compute cross-spectra\n'); +end + +% determine the channels of interest +cfg.channel = ft_channelselection(cfg.channel, data.label); +chansel = match_str(data.label, cfg.channel); + +% determine the duration of each trial +ntrial = length(data.trial); +nchan = size(data.trial{1}, 1); + +for i=1:ntrial + nsampl(i) = size(data.trial{i}, 2); + begsamplatency(i) = min(data.time{i}); + endsamplatency(i) = max(data.time{i}); +end; + +if cfg.downsample > 1 + % perform a decimation of the input data + warning('decimating the input data, better is to use RESAMPLEDATA'); + for k=1:ntrial + dTmp = data.trial{k}; + data.trial{k} = dTmp(:,1:cfg.downsample:end); + tTmp = data.time{k}; + data.time{k} = tTmp(1:cfg.downsample:end); + end + data.fsample = data.fsample / cfg.downsample; +end + +% automatically determine the latency window which is possible in all trials +minperlength = [max(begsamplatency) min(endsamplatency)]; + +% latency window for averaging and variance computation is given in seconds +if (strcmp(cfg.latency, 'minperlength')) + cfg.latency = []; + cfg.latency(1) = minperlength(1); + cfg.latency(2) = minperlength(2); +end +if (strcmp(cfg.latency, 'prestim')) + cfg.latency = []; + cfg.latency(1) = minperlength(1); + cfg.latency(2) = 0; +end +if (strcmp(cfg.latency, 'poststim')) + cfg.latency = []; + cfg.latency(1) = 0; + cfg.latency(2) = minperlength(2); +end + +M = waveletfam(cfg.foi,data.fsample,cfg.waveletwidth); + +progress('init', cfg.feedback, 'convolving wavelets'); + +for i=1:ntrial + indicvect = data.time{i}; + progress(i/ntrial, 'convolving wavelets, trial %d of %d\n', i, ntrial); + + %for average and variance + begsampl = nearest(indicvect,cfg.latency(1)); + endsampl = nearest(indicvect,cfg.latency(2)); + + numsamples(i) = endsampl-begsampl+1; + + if (i==1) + % allocate memory to hold the resulting powerspectra + if strcmp(cfg.keeptrials, 'yes') + freq.powspctrm = zeros(ntrial,nchan,length(cfg.foi),ceil((endsampl-begsampl+1)/cfg.downsample)); + else + freq.powspctrm = zeros(nchan,length(cfg.foi),ceil((endsampl-begsampl+1)/cfg.downsample)); + end + end; + + dat = data.trial{i}(chansel,begsampl:endsampl); + for k=1:size(dat,1) + for j=1:length(cfg.foi) + cTmp = conv(dat(k,:),M{j}); + cTmp = 2*(abs(cTmp).^2)/data.fsample; + cTmp = cTmp(ceil(length(M{j})/2):length(cTmp)-floor(length(M{j})/2)); + cTmp = cTmp(:,1:cfg.downsample:end); + if strcmp(cfg.keeptrials, 'yes') + freq.powspctrm(i,k,j,:) = cTmp'; + else + freq.powspctrm(k,j,:) = squeeze(freq.powspctrm(k,j,:)) + cTmp'; % compute the running sum + end + end + end + +end %for ntrial + +progress('close'); + +if strcmp(cfg.keeptrials, 'yes') + freq.dimord = 'rpt_chan_freq_time'; +else + freq.dimord = 'chan_freq_time'; + freq.powspctrm = freq.powspctrm / ntrial; % compute the average +end +freq.label = cfg.channel; +freq.freq = cfg.foi; +freq.time = indicvect(1:cfg.downsample:end); + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_freqanalysis_tfr.m 1085 2010-05-18 11:18:43Z sashae $'; +% remember the configuration details of the input data +try, cfg.previous = data.cfg; end +% remember the exact configuration details in the output +freq.cfg = cfg; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION for waveletanalysis +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function M = waveletfam(foi,Fs,width) +dt = 1/Fs; +for k=1:length(foi) + sf = foi(k)/width; + st = 1/(2*pi*sf); + toi=-3.5*st:dt:3.5*st; + A = 1/sqrt(st*sqrt(pi)); + M{k}= A*exp(-toi.^2/(2*st^2)).*exp(i*2*pi*foi(k).*toi); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION for waveletanalysis +% +% Return a vector containing the energy as a +% function of time for frequency f. The energy +% is calculated using Morlet's wavelets. +% s : signal +% Fs: sampling frequency +% width: width of Morlet wavelet (>= 5 suggested). +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function y = energyvec(f,s,Fs,width) +dt = 1/Fs; +sf = f/width; +st = 1/(2*pi*sf); +t=-3.5*st:dt:3.5*st; +m = morlet(f,t,width); +size(m) +y = conv(s,m); +y = (2*abs(y)/Fs).^2; +y = y(ceil(length(m)/2):length(y)-floor(length(m)/2)); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% subfunction for waveletanalysis +% +% Morlet's wavelet for frequency f and time t. +% The wavelet will be normalized so the total energy is 1. +% width defines the ``width'' of the wavelet. +% A value >= 5 is suggested. +% +% Ref: Tallon-Baudry et al., J. Neurosci. 15, 722-734 (1997) +% +% See also: PHASEGRAM, PHASEVEC, WAVEGRAM, ENERGY +% +% Ole Jensen, August 1998 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function y = morlet(f,t,width) +sf = f/width; +st = 1/(2*pi*sf); +A = 1/sqrt(st*sqrt(pi)); +y = A*exp(-t.^2/(2*st^2)).*exp(i*2*pi*f.*t); diff --git a/external/fieldtrip/ft_freqanalysis_wltconvol.m b/external/fieldtrip/ft_freqanalysis_wltconvol.m new file mode 100644 index 0000000..ad459b4 --- /dev/null +++ b/external/fieldtrip/ft_freqanalysis_wltconvol.m @@ -0,0 +1,311 @@ +function [freq] = ft_freqanalysis_wltconvol(cfg, data); + +% FT_FREQANALYSIS_WLTCONVOL performs time-frequency analysis on any time series trial data +% using the 'wavelet method' based on Morlet wavelets. +% +% Use as +% [freq] = ft_freqanalysis(cfg, data) +% +% The data should be organised in a structure as obtained from +% the FT_PREPROCESSING function. The configuration should be according to +% cfg.method = method used for frequency or time-frequency decomposition +% see FT_FREQANALYSIS for details +% cfg.output = 'pow' return the power-spectra +% 'powandcsd' return the power and the cross-spectra +% +% For cfg.output='powandcsd', you should specify the channel combinations +% between which to compute the cross-spectra as cfg.channelcmb. Otherwise +% you should specify only the channels in cfg.channel. +% +% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), +% see FT_CHANNELSELECTION for details +% cfg.channelcmb = Mx2 cell-array with selection of channel pairs (default = {'all' 'all'}), +% see FT_CHANNELCOMBINATION for details +% cfg.foi = vector 1 x numfoi, frequencies of interest +% cfg.toi = vector 1 x numtoi, the times on which the analysis windows +% should be centered (in seconds) +% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') +% cfg.keeptrials = 'yes' or 'no', return individual trials or average (default = 'no') +% cfg.width = 'width' of the wavelet, determines the temporal and spectral +% resolution of the analysis (default = 7) +% constant, for a 'classical constant-Q' wavelet analysis +% vector, defining a variable width for each frequency +% cfg.gwidth = determines the length of the used wavelets in standard deviations +% of the implicit Gaussian kernel and should be choosen +% >= 3; (default = 3) +% +% The standard deviation in the frequency domain (sf) at frequency f0 is +% defined as: sf = f0/width +% The standard deviation in the temporal domain (st) at frequency f0 is +% defined as: st = width/f0 = 1/sf +% +% See also FT_FREQANALYSIS + +% Copyright (C) 2003-2007, Markus Siegel, F.C. Donders Centre +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_freqanalysis_wltconvol.m 1149 2010-05-27 15:23:29Z sashae $ + +fieldtripdefs + +% ensure that this function is started as a subfunction of the FT_FREQANALYSIS wrapper +if ~exist('OCTAVE_VERSION') + [s, i] = dbstack; + if length(s)>1 + [caller_path, caller_name, caller_ext] = fileparts(s(2).name); + else + caller_path = ''; + caller_name = ''; + caller_ext = ''; + end + % evalin('caller', 'mfilename') does not work for Matlab 6.1 and 6.5 + if ~strcmp(caller_name, 'ft_freqanalysis') + error(['you should call FREQANALYSIS, instead of the ' upper(mfilename) ' subfunction']); + end +end + +% set all the defaults +if ~isfield(cfg, 'method'), cfg.method = 'wltconvol'; end +if ~isfield(cfg, 'keeptrials'), cfg.keeptrials = 'no'; end +if ~isfield(cfg, 'output'), cfg.output = 'powandcsd'; end +if ~isfield(cfg, 'pad'), cfg.pad = 'maxperlen'; end +if ~isfield(cfg, 'width'), cfg.width = 7; end +if ~isfield(cfg, 'gwidth'), cfg.gwidth = 3; end +if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end + +% expand cfg.width to array if constant width +if prod(size(cfg.width)) == 1 + cfg.width = ones(1,length(cfg.foi)) * cfg.width; +end + +% setting a flag (csdflg) that determines whether this routine outputs +% only power-spectra or power-spectra and cross-spectra? +if strcmp(cfg.output,'pow') + csdflg = 0; +elseif strcmp(cfg.output,'powandcsd') + csdflg = 1; +end + +if ~isfield(cfg, 'channelcmb') && csdflg + %set the default for the channelcombination + cfg.channelcmb = {'all' 'all'}; +elseif isfield(cfg, 'channelcmb') && ~csdflg + % no cross-spectrum needs to be computed, hence remove the combinations from cfg + cfg = rmfield(cfg, 'channelcmb'); +end + +% ensure that channelselection and selection of channelcombinations is +% perfomed consistently +cfg.channel = ft_channelselection(cfg.channel, data.label); +if isfield(cfg, 'channelcmb') + cfg.channelcmb = ft_channelcombination(cfg.channelcmb, data.label); +end + +% determine the corresponding indices of all channels +sgnindx = match_str(data.label, cfg.channel); +numsgn = size(sgnindx,1); +if csdflg + % determine the corresponding indices of all channel combinations + for k=1:size(cfg.channelcmb,1) + sgncmbindx(k,1) = strmatch(cfg.channelcmb(k,1), data.label, 'exact'); + sgncmbindx(k,2) = strmatch(cfg.channelcmb(k,2), data.label, 'exact'); + end + + numsgncmb = size(sgncmbindx,1); + sgnindx = unique([sgnindx(:); sgncmbindx(:)]); + numsgn = length(sgnindx); + + cutdatindcmb = zeros(size(sgncmbindx)); + for sgnlop = 1:numsgn + cutdatindcmb(find(sgncmbindx == sgnindx(sgnlop))) = sgnlop; + end +end + +% if rectan is 1 it means that trials are of equal lengths +numper = numel(data.trial); +rectan = 1; +for perlop = 1:numper + numdatbnsarr(perlop,1) = size(data.trial{perlop},2); + if numdatbnsarr(perlop,1) ~= numdatbnsarr(1,1) + rectan = 0; + end +end + +%if cfg.pad is 'maxperlen', this is realized here: +if ischar(cfg.pad) + if strcmp(cfg.pad,'maxperlen') + cfg.pad = max(numdatbnsarr,[],1) ./ data.fsample; + end +end +numsmp = cfg.pad .* data.fsample; + +% keeping trials and/or tapers? +if strcmp(cfg.keeptrials,'no') + keeprpt = 1; +elseif strcmp(cfg.keeptrials,'yes') + keeprpt = 2; +end + +% do the computation for WLTCONVOL +if strcmp(cfg.method,'wltconvol') + minoffset = min(data.offset); + timboi = round(cfg.toi .* data.fsample - minoffset); + toi = round(cfg.toi .* data.fsample) ./ data.fsample; + numtoi = length(toi); + numfoi = length(cfg.foi); + knlspctrmstr = cell(numfoi,1); + for foilop = 1:numfoi + dt = 1/data.fsample; + sf = cfg.foi(foilop)/cfg.width(foilop); + st = 1/(2*pi*sf); + toi2 = -cfg.gwidth*st:dt:cfg.gwidth*st; + A = 1/sqrt(st*sqrt(pi)); + tap = (A*exp(-toi2.^2/(2*st^2)))'; + acttapnumsmp = size(tap,1); + taplen(foilop) = acttapnumsmp; + ins = ceil(numsmp./2) - floor(acttapnumsmp./2); + prezer = zeros(ins,1); + pstzer = zeros(numsmp - ((ins-1) + acttapnumsmp)-1,1); + ind = (0:acttapnumsmp-1)' .* ... + ((2.*pi./data.fsample) .* cfg.foi(foilop)); + knlspctrmstr{foilop} = complex(zeros(1,numsmp)); + knlspctrmstr{foilop} = ... + fft(complex(vertcat(prezer,tap.*cos(ind),pstzer), ... + vertcat(prezer,tap.*sin(ind),pstzer)),[],1)'; + end + if keeprpt == 1 + powspctrm = zeros(numsgn,numfoi,numtoi); + if csdflg, crsspctrm = complex(zeros(numsgncmb,numfoi,numtoi)); end + cntpertoi = zeros(numfoi,numtoi); + dimord = 'chan_freq_time'; + elseif keeprpt == 2 + powspctrm = zeros(numper,numsgn,numfoi,numtoi); + if csdflg, crsspctrm = complex(zeros(numper,numsgncmb,numfoi,numtoi)); end + dimord = 'rpt_chan_freq_time'; + end + for perlop = 1:numper + fprintf('processing trial %d: %d samples\n', perlop, numdatbnsarr(perlop,1)); + if keeprpt == 2 + cnt = perlop; + end + numdatbns = numdatbnsarr(perlop,1); + prepad = zeros(1,data.offset(perlop) - minoffset); + pstpad = zeros(1,minoffset + numsmp - (data.offset(perlop) + numdatbns)); + datspctra = complex(zeros(numsgn,numsmp)); + for sgnlop = 1:numsgn + datspctra(sgnlop,:) = fft([prepad, data.trial{perlop}(sgnindx(sgnlop),:), ... + pstpad],[],2); + end + for foilop = 1:numfoi + fprintf('processing frequency %d (%.2f Hz)\n', foilop,cfg.foi(foilop)); + actfoinumsmp = taplen(foilop); + acttimboiind = ... + find(timboi >= (-minoffset + data.offset(perlop) + (actfoinumsmp ./ 2)) & ... + timboi < (-minoffset + data.offset(perlop) + numdatbns - (actfoinumsmp ./2))); + nonacttimboiind = ... + find(timboi < (-minoffset + data.offset(perlop) + (actfoinumsmp ./ 2)) | ... + timboi >= (-minoffset + data.offset(perlop) + numdatbns - (actfoinumsmp ./2))); + acttimboi = timboi(acttimboiind); + numacttimboi = length(acttimboi); + if keeprpt ==1 + cntpertoi(foilop,acttimboiind) = cntpertoi(foilop,acttimboiind) + 1; + end + if keeprpt == 3 + cnt = 1; + end + autspctrmacttap = complex(zeros(numsgn,numacttimboi)); + if numacttimboi > 0 + for sgnlop = 1:numsgn + dum = fftshift(ifft(datspctra(sgnlop,:) .* ... + [knlspctrmstr{foilop}],[],2)); + autspctrmacttap(sgnlop,:) = dum(acttimboi); + end + powdum = 2.* (abs(autspctrmacttap).^2) ./ data.fsample; + end + if keeprpt == 1 && numacttimboi > 0 + powspctrm(:,foilop,acttimboiind) = powspctrm(:,foilop,acttimboiind) + ... + reshape(powdum,[numsgn,1,numacttimboi]); + elseif keeprpt == 2 && numacttimboi > 0 + powspctrm(cnt,:,foilop,acttimboiind) = powspctrm(cnt,:,foilop,acttimboiind) + ... + reshape(powdum,[1,numsgn,1,numacttimboi]); + powspctrm(cnt,:,foilop,nonacttimboiind) = nan; + elseif keeprpt == 2 && numacttimboi == 0 + powspctrm(cnt,:,foilop,nonacttimboiind) = nan; + end + if csdflg + csddum = 2.* (autspctrmacttap(cutdatindcmb(:,1),:) .* ... + conj(autspctrmacttap(cutdatindcmb(:,2),:))) ./ data.fsample; %actfoinumsmp; + if keeprpt == 1 && numacttimboi > 0 + crsspctrm(:,foilop,acttimboiind) = ... + crsspctrm(:,foilop,acttimboiind) + ... + reshape(csddum,[numsgncmb,1,numacttimboi]); + elseif keeprpt == 2 && numacttimboi > 0 + crsspctrm(cnt,:,foilop,acttimboiind) = ... + crsspctrm(cnt,:,foilop,acttimboiind) + ... + reshape(csddum,[1,numsgncmb,1,numacttimboi]); + crsspctrm(cnt,:,foilop,nonacttimboiind) = nan; + elseif keeprpt == 2 && numacttimboi == 0 + crsspctrm(cnt,:,foilop,nonacttimboiind) = nan; + end + end + end% of foilop + end%of perlop + if keeprpt == 1 + ws = warning('off'); + powspctrm(:,:,:) = powspctrm(:,:,:) ./ repmat(permute(cntpertoi,[3,1,2]),[numsgn,1,1]); + if csdflg + crsspctrm(:,:,:) = crsspctrm(:,:,:) ./ repmat(permute(cntpertoi,[3,1,2]),[numsgncmb,1,1]); + end + % return to previous warning state + warning(ws); + end +end + +% collect the results +freq.label = data.label(sgnindx); +freq.dimord = dimord; +freq.powspctrm = powspctrm; +freq.freq = cfg.foi; +freq.time = cfg.toi; + +if csdflg + freq.labelcmb = cfg.channelcmb; + freq.crsspctrm = crsspctrm; +end + +try, freq.grad = data.grad; end % remember the gradiometer array +try, freq.elec = data.elec; end % remember the electrode array + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add information about the version of this function to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i1] = dbstack; + cfg.version.name = st(i1); +end +cfg.version.id = '$Id: ft_freqanalysis_wltconvol.m 1149 2010-05-27 15:23:29Z sashae $'; +% remember the configuration details of the input data +try, cfg.previous = data.cfg; end +% remember the exact configuration details in the output +freq.cfg = cfg; + diff --git a/external/fieldtrip/ft_freqbaseline.m b/external/fieldtrip/ft_freqbaseline.m index b84b9b2..4c4a2aa 100644 --- a/external/fieldtrip/ft_freqbaseline.m +++ b/external/fieldtrip/ft_freqbaseline.m @@ -1,11 +1,265 @@ -function varargout = funname(varargin); +function [freq] = ft_freqbaseline(cfg, freq) -% this is a SPM wrapper around a FieldTrip function +% FT_FREQBASELINE performs baseline normalization for time-frequency data +% +% Use as +% [freq] = ft_freqbaseline(cfg, freq) +% where the freq data comes from FT_FREQANALYSIS and the configuration +% should contain +% cfg.baseline = [begin end] (default = 'no') +% cfg.baselinetype = 'absolute' 'relchange' 'relative' (default = 'absolute') +% +% See also FT_FREQANALYSIS, FT_TIMELOCKBASELINE, FT_FREQCOMPARISON +% +% Undocumented local options: +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk -% this part is variable -prefix = 'ft_'; +% Copyright (C) 2004-2006, Marcel Bastiaansen +% Copyright (C) 2005-2006, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_freqbaseline.m 1258 2010-06-22 08:33:48Z timeng $ + +fieldtripdefs + +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +% set the defaults +if ~isfield(cfg, 'baseline'), cfg.baseline = 'no'; end +if ~isfield(cfg, 'baselinetype'), cfg.baselinetype = 'absolute'; end % default is to use an absolute baseline +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +% load optional given inputfile as data +hasdata = (nargin>1); + +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + freq = loadvar(cfg.inputfile, 'data'); + end +end + +% check if the input data is valid for this function +freq = checkdata(freq, 'datatype', 'freq', 'feedback', 'yes'); + +% give a warning if the input is inconsistent +if ischar(cfg.baseline) && strcmp(cfg.baseline, 'no') && ~isempty(cfg.baselinetype) + warning('no baseline correction done'); +end + +if ischar(cfg.baseline) && strcmp(cfg.baseline, 'yes') + % default is to take the prestimulus interval + cfg.baseline = [-inf 0]; +elseif ischar(cfg.baseline) && strcmp(cfg.baseline, 'no') + % nothing to do + return +end + +haspow = issubfield(freq, 'powspctrm'); +hascoh = issubfield(freq, 'cohspctrm'); + +% we have to ensure that we don't end up with an inconsistent dataset +% remove cross-spectral densities since coherence cannot be computed any more +if isfield(freq, 'crsspctrm') + freq = rmfield(freq, 'crsspctrm'); +end +if isfield(freq, 'cohspctrmsem') + freq = rmfield(freq, 'cohspctrmsem'); +end +if isfield(freq, 'powspctrmsem') + freq = rmfield(freq, 'powspctrmsem'); +end + +if strcmp(freq.dimord, 'chan_freq_time') + % apply the desired method for the average, see the subfunctions below + if strcmp(cfg.baselinetype, 'absolute') + if haspow, freq.powspctrm = TFabschange(freq.time, freq.freq, freq.powspctrm, cfg.baseline); end + if hascoh, freq.cohspctrm = TFabschange(freq.time, freq.freq, freq.cohspctrm, cfg.baseline); end + elseif strcmp(cfg.baselinetype, 'relchange') + if haspow, freq.powspctrm = TFrelchange(freq.time, freq.freq, freq.powspctrm, cfg.baseline); end + if hascoh, freq.cohspctrm = TFrelchange(freq.time, freq.freq, freq.cohspctrm, cfg.baseline); end + elseif strcmp(cfg.baselinetype, 'relative') + if haspow, freq.powspctrm = TFrelative(freq.time, freq.freq, freq.powspctrm, cfg.baseline); end + if hascoh, freq.cohspctrm = TFrelative(freq.time, freq.freq, freq.cohspctrm, cfg.baseline); end + % elseif strcmp(cfg.baselinetype, 'zscore') + % freq.powspctrm = TFzscore(freq.time, freq.freq, freq.powspctrm,cfg.baseline); + else + error('unsupported method for baseline normalization'); + end + +elseif strcmp(freq.dimord, 'rpt_chan_freq_time') + % apply the desired method for each trial, see the subfunctions below + if ~haspow || hascoh + error('this only works for power, not for coherence'); + end + + Ntrial = size(freq.powspctrm,1); + for i=1:Ntrial + % Reshape freq.powspctrm into 3D matrix + % This relies on dimord being 'rpt_chan_freq_time' + tfdata = reshape(freq.powspctrm(i,:,:,:), ... + size(freq.powspctrm,2), ... + size(freq.powspctrm,3), ... + size(freq.powspctrm,4)); + + if strcmp(cfg.baselinetype, 'absolute'), + freq.powspctrm(i,:,:,:) = TFabschange(freq.time, freq.freq, tfdata, cfg.baseline); + elseif strcmp(cfg.baselinetype, 'relchange') + freq.powspctrm(i,:,:,:) = TFrelchange(freq.time, freq.freq, tfdata, cfg.baseline); + elseif strcmp(cfg.baselinetype, 'relative') + freq.powspctrm(i,:,:,:) = TFrelative(freq.time, freq.freq, tfdata, cfg.baseline); + % elseif strcmp(cfg.baselinetype, 'zscore') + % freq.powspctrm = TFzscore(freq.time, freq.freq, freq.powspctrm,cfg.baseline); + else + error('unsupported method for baseline normalization'); + end + end + +else + error('unsupported data dimensions'); +end + +% accessing this field here is needed for the configuration tracking +% by accessing it once, it will not be removed from the output cfg +cfg.outputfile; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_freqbaseline.m 1258 2010-06-22 08:33:48Z timeng $'; + +% remember the configuration details of the input data +try, cfg.previous = freq.cfg; end + +% remember the exact configuration details in the output +freq.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', freq); % use the variable name "data" in the output file +end + +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% function [TFdata] = TFzscore(timeVec,freqVec,TFdata,TimeInt) +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % Compute relative change from baseline on a TFR representation as obtained from the framework software +% % NB fixed order of dimensions is assumed in the TFdata: channels, frequencies, timepoints +% tidx = find(timeVec >= TimeInt(1) & timeVec <= TimeInt(2)); +% TFtmp = TFdata(:,:,tidx); +% for k=1:size(TFdata,2) % loop frequencies +% for l=1:size(TFdata,1) % loop channels +% TFbl (l,k) = squeeze(mean(TFdata(l,k,tidx),3)); %compute average baseline power +% TFblstd(l,k) = squeeze(std (TFdata(l,k,tidx),[], 3)); %compute standard deviation +% end +% end +% for k=1:size(TFdata,2) % loop frequencies +% for l=1:size(TFdata,1) % loop channels +% TFdata(l,k,:) = ((TFdata(l,k,:) - TFbl(l,k)) / TFblstd(l,k)); % compute zscore +% end +% end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [TFdata] = TFrelative(timeVec,freqVec,TFdata,TimeInt) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Compute relative change from baseline on a TFR representation as obtained from the framework software +% NB fixed order of dimensions is assumed in the TFdata: channels, frequencies, timepoints +tidx = find(timeVec >= TimeInt(1) & timeVec <= TimeInt(2)); + +if length(size(TFdata))~=3, + error('Time-frequency matrix should have three dimensions (chan,freq,time)'); +end + +for k=1:size(TFdata,2) % loop frequencies + for l=1:size(TFdata,1) % loop channels + TFbl(l,k) = nan_mean(TFdata(l,k,tidx),3);%compute average baseline power + + if TFbl(l,k) == 0, + error('Average baseline power is zero'); + end + + end +end +for k=1:size(TFdata,2) % loop frequencies + for l=1:size(TFdata,1) % loop channels + TFdata(l,k,:) = TFdata(l,k,:) / TFbl(l,k); % compute relative change (i.e. ratio) + end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [TFdata] = TFrelchange(timeVec,freqVec,TFdata,TimeInt) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Compute relative change from baseline on a TFR representation as obtained from the framework software +% NB fixed order of dimensions is assumed in the TFdata: channels, frequencies, timepoints +tidx = find(timeVec >= TimeInt(1) & timeVec <= TimeInt(2)); + +if length(size(TFdata))~=3, + error('Time-frequency matrix should have three dimensions (chan,freq,time)'); +end + +for k=1:size(TFdata,2) % loop frequencies + for l=1:size(TFdata,1) % loop channels + TFbl(l,k) = nan_mean(TFdata(l,k,tidx),3); %compute average baseline power + + if TFbl(l,k) == 0, + error('Average baseline power is zero'); + end + + end +end + +for k=1:size(TFdata,2) % loop frequencies + for l=1:size(TFdata,1) % loop channels + TFdata(l,k,:) = ((TFdata(l,k,:) - TFbl(l,k)) / TFbl(l,k)); % compute relative change + end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [TFdata] = TFabschange(timeVec,freqVec,TFdata,TimeInt) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Subtract baseline from a TFR representation as obtained from the framework software +% NB fixed order of dimensions is assumed in the TFdata: channels, frequencies, timepoints +tidx = find(timeVec >= TimeInt(1) & timeVec <= TimeInt(2)); + +if length(size(TFdata))~=3, + error('Time-frequency matrix should have three dimensions (chan,freq,time)'); +end + +for k=1:size(TFdata,2) % loop frequencies + for l=1:size(TFdata,1) % loop channels + TFbl(l,k) = nan_mean(TFdata(l,k,tidx),3); %compute average baseline power + end +end +for k=1:size(TFdata,2) % loop frequencies + for l=1:size(TFdata,1) % loop channels + TFdata(l,k,:) = TFdata(l,k,:) - TFbl(l,k); % subtract baseline power + end +end -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_freqcomparison.m b/external/fieldtrip/ft_freqcomparison.m new file mode 100644 index 0000000..9beee97 --- /dev/null +++ b/external/fieldtrip/ft_freqcomparison.m @@ -0,0 +1,140 @@ +function [freq] = ft_freqcomparison(cfg, varargin) + +% FT_FREQCOMPARISON performs a baseline-like comparison for channel-frequency data +% +% Use as +% [freq] = ft_freqcomparison(cfg, dataset1, dataset2); +% +% where the freq data comes from FREQANALYSIS_MTMFFT and the configuration +% should contain +% cfg.baselinetype = 'absolute' 'relchange' 'relative' (default = +% 'absolute') +% +% where the first dataset is seen as baseline +% +% See also FT_FREQBASELINE, FT_FREQANALYSIS, FT_TIMELOCKBASELINE +% +% Copyright (C) 2010-2011, Arjen Stolk, DCCN, Donders Institute +% A.Stolk@donders.ru.nl +% +% not yet supported: cohspctrm + +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . + +fieldtripdefs + +% nargin check +if nargin ~= 3 + error('two conditions required for input'); +end + +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +% check if the input data is valid for this function +varargin{1} = checkdata(varargin{1}, 'datatype', 'freq', 'feedback', 'yes'); +varargin{2} = checkdata(varargin{2}, 'datatype', 'freq', 'feedback', 'yes'); + +% set the defaults +if ~isfield(cfg, 'baselinetype'), cfg.baselinetype = 'absolute'; end + +% we have to ensure that we don't end up with an inconsistent dataset +% remove cross-spectral densities since coherence cannot be computed any more +if isfield(varargin{1}, 'crsspctrm') + varargin{1} = rmfield(varargin{1}, 'crsspctrm'); +end +if isfield(varargin{1}, 'cohspctrmsem') + varargin{1} = rmfield(varargin{1}, 'cohspctrmsem'); +end +if isfield(varargin{1}, 'powspctrmsem') + varargin{1} = rmfield(varargin{1}, 'powspctrmsem'); +end +if isfield(varargin{2}, 'crsspctrm') + varargin{2} = rmfield(varargin{2}, 'crsspctrm'); +end +if isfield(varargin{2}, 'cohspctrmsem') + varargin{2} = rmfield(varargin{2}, 'cohspctrmsem'); +end +if isfield(varargin{2}, 'powspctrmsem') + varargin{2} = rmfield(varargin{2}, 'powspctrmsem'); +end + +% frequency comparison for multiple trials/subjects +if strcmp(varargin{1}.dimord, 'rpt_chan_freq') || strcmp(varargin{1}.dimord, 'subj_chan_freq') + + if size(varargin{1}.powspctrm,3) ~= size(varargin{2}.powspctrm,3) + error('input conditions have different sizes'); + end + + if strcmp(cfg.baselinetype, 'absolute') + for j = 1:size(varargin{2}.powspctrm,1) + freq.powspctrm(j,:,:) = varargin{2}.powspctrm(j,:,:) - mean(varargin{1}.powspctrm,1); + end + elseif strcmp(cfg.baselinetype, 'relchange') + for j = 1:size(varargin{2}.powspctrm,1) + freq.powspctrm(j,:,:) = (varargin{2}.powspctrm(j,:,:) - mean(varargin{1}.powspctrm,1)) ./ mean(varargin{1}.powspctrm,1); + end + elseif strcmp(cfg.baselinetype, 'relative') + for j = 1:size(varargin{2}.powspctrm,1) + freq.powspctrm(j,:,:) = varargin{2}.powspctrm(j,:,:) ./ mean(varargin{1}.powspctrm,1); + end + else + error('unsupported baselinetype'); + end + +% frequency comparison for averages +elseif strcmp(varargin{1}.dimord, 'chan_freq') + + if size(varargin{1}.powspctrm,2) ~= size(varargin{2}.powspctrm,2) + error('input conditions have different sizes'); + end + + if strcmp(cfg.baselinetype, 'absolute') + freq.powspctrm = varargin{2}.powspctrm - varargin{1}.powspctrm; + elseif strcmp(cfg.baselinetype, 'relchange') + freq.powspctrm = (varargin{2}.powspctrm - varargin{1}.powspctrm) ./ varargin{1}.powspctrm; + elseif strcmp(cfg.baselinetype, 'relative') + freq.powspctrm = varargin{2}.powspctrm ./ varargin{1}.powspctrm; + else + error('unsupported baselinetype'); + end +end + +% user update +fprintf('performing %s comparison \n', cfg.baselinetype); + +% add the remaining parameters +if isfield(varargin{1}, 'label') + freq.label = varargin{1}.label; +end +if isfield(varargin{1}, 'dimord') + freq.dimord = varargin{1}.dimord; +end +if isfield(varargin{1}, 'freq') + freq.freq = varargin{1}.freq; +end +if isfield(varargin{1}, 'cumsumcnt') + freq.cumsumcnt = varargin{1}.cumsumcnt; +end +if isfield(varargin{1}, 'cumtapcnt') + freq.cumtapcnt = varargin{1}.cumtapcnt; +end +if isfield(varargin{1}, 'grad') + freq.grad = varargin{1}.grad; +end +if isfield(varargin{1}, 'cfg') + freq.cfg = varargin{1}.cfg; +end \ No newline at end of file diff --git a/external/fieldtrip/ft_freqdescriptives.m b/external/fieldtrip/ft_freqdescriptives.m index b84b9b2..584f7a9 100644 --- a/external/fieldtrip/ft_freqdescriptives.m +++ b/external/fieldtrip/ft_freqdescriptives.m @@ -1,11 +1,222 @@ -function varargout = funname(varargin); -% this is a SPM wrapper around a FieldTrip function +function [output] = ft_freqdescriptives(cfg, freq) -% this part is variable -prefix = 'ft_'; +% FT_FREQDESCRIPTIVES computes descriptive univariate statistics of +% the frequency or time-frequency decomposition of the EEG/MEG signal, +% thus the powerspectrum and its standard error. +% +% Use as +% [freq] = ft_freqdescriptives(cfg, freq) +% [freq] = ft_freqdescriptives(cfg, freqmvar) +% +% The data in freq should be organised in a structure as obtained from +% from the FT_FREQANALYSIS or FT_MVARANALYSIS function. The output structure is comparable +% to the input structure and can be used in most functions that require +% a freq input. +% +% The configuration options are +% cfg.variance = 'yes' or 'no', estimate standard error in the standard way (default = 'no') +% cfg.jackknife = 'yes' or 'no', estimate standard error by means of the jack-knife (default = 'no') +% cfg.keeptrials = 'yes' or 'no', estimate single trial power (useful for fourier data) (default = 'no') +% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), +% see FT_CHANNELSELECTION for details +% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') +% cfg.foilim = [fmin fmax] or 'all', to specify a subset of frequencies (default = 'all') +% cfg.toilim = [tmin tmax] or 'all', to specify a subset of latencies (default = 'all') +% +% A variance estimate can only be computed if results from trials and/or +% tapers have been kept. +% +% Descriptive statistics of bivariate metrics is not computed by this function anymore. To this end you +% should use FT_CONNECTIVITYANALYSIS. +% +% See also FT_FREQANALYSIS, FT_FREQSTATISTICS, FT_FREQBASELINE, FT_CONNECTIVITYANALYSIS -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +% Undocumented local options: +% cfg.feedback +% cfg.latency +% cfg.previous +% cfg.version +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk + +% Copyright (C) 2004-2006, Pascal Fries & Jan-Mathijs Schoffelen, F.C. Donders Centre +% Copyright (C) 2010, Jan-Mathijs Schoffelen, F.C. Donders Centre +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_freqdescriptives.m 1311 2010-06-30 12:17:57Z timeng $ + +fieldtripdefs + +% check if the input cfg is valid for this function +cfg = checkconfig(cfg, 'trackconfig', 'on'); +cfg = checkconfig(cfg, 'renamed', {'jacknife', 'jackknife'}); + +% throw warnings for the deprecated options +cfg = checkconfig(cfg, 'deprecated', 'biascorrect'); +cfg = checkconfig(cfg, 'deprecated', 'channelcmb'); +cfg = checkconfig(cfg, 'deprecated', 'cohmethod'); +cfg = checkconfig(cfg, 'deprecated', 'combinemethod'); +cfg = checkconfig(cfg, 'deprecated', 'complex'); +cfg = checkconfig(cfg, 'deprecated', 'combinechan'); +cfg = checkconfig(cfg, 'deprecated', 'keepfourier'); +cfg = checkconfig(cfg, 'deprecated', 'partchan'); +cfg = checkconfig(cfg, 'deprecated', 'pseudovalue'); + +% set the defaults +if ~isfield(cfg, 'feedback'), cfg.feedback = 'textbar'; end +if ~isfield(cfg, 'jackknife'), cfg.jackknife = 'no'; end +if ~isfield(cfg, 'variance'), cfg.variance = 'no'; end +if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end +if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end +if ~isfield(cfg, 'foilim'), cfg.foilim = 'all'; end +if ~isfield(cfg, 'toilim'), cfg.toilim = 'all'; end +if ~isfield(cfg, 'keeptrials'), cfg.keeptrials = 'no'; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +% load optional given inputfile as data +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + freq = loadvar(cfg.inputfile, 'data'); + end +end + +% check if the input data is valid for this function +freq = checkdata(freq, 'datatype', {'freq', 'freqmvar'}, 'feedback', 'yes'); + +% determine some specific details of the input data +hasrpt = ~isempty(strfind(freq.dimord, 'rpt')) || ~isempty(strfind(freq.dimord, 'subj')); +hastim = ~isempty(strfind(freq.dimord, 'time')); + +varflg = strcmp(cfg.variance, 'yes'); +jckflg = strcmp(cfg.jackknife, 'yes'); +keepflg = strcmp(cfg.keeptrials, 'yes'); + +% check sensibility of configuration +if sum([varflg keepflg]>1), error('you should specify only one of cfg.keeptrials or cfg.variance'); end +if ~hasrpt && (varflg || keepflg), error('a variance-estimate or a single trial estimate without repeated observations in the input is not possible'); end +if ~hasrpt && ~strcmp(cfg.trials, 'all'), error('trial selection requires input data with repeated observations'); end +if ~varflg && jckflg, warning('you specified cfg.jackknife = ''yes'' and cfg.variance = ''no'': no variance will be computed'); end + +% select data of interest +if ~strcmp(cfg.foilim, 'all'), freq = selectdata(freq, 'foilim', cfg.foilim); end +if hastim, if ~strcmp(cfg.toilim, 'all'), freq = selectdata(freq, 'toilim', cfg.toilim); end; end +if hasrpt, if ~strcmp(cfg.trials, 'all'), freq = selectdata(freq, 'rpt', cfg.trials); end; end + +if ~strcmp(cfg.channel, 'all'), + channel = ft_channelselection(cfg.channel, freq.label); + freq = selectdata(freq, 'channel', channel); +end + +% get data in the correct representation +freq = checkdata(freq, 'cmbrepresentation', 'sparsewithpow', 'channelcmb', {}); + +if jckflg, + freq = selectdata(freq, 'jackknife', 1); +end + +if varflg, + siz = [size(freq.powspctrm) 1]; + outsum = zeros(siz(2:end)); + outssq = zeros(siz(2:end)); + n = zeros(siz(2:end)); + progress('init', cfg.feedback, 'computing power...'); + for j = 1:siz(1) + progress(j/siz(1), 'computing power for replicate %d from %d\n', j, siz(1)); + tmp = reshape(freq.powspctrm(j,:,:,:), siz(2:end)); + n = n + double(isfinite(tmp)); + tmp(~isfinite(tmp)) = 0; + outsum = outsum + tmp; + outssq = outssq + tmp.^2; + end + progress('close'); + + if jckflg, + bias = (n-1).^2; + else, + bias = 1; + end + + powspctrm = outsum./n; + powspctrmsem = sqrt(bias.*(outssq - (outsum.^2)./n)./(n - 1)./n); +elseif keepflg + %nothing to do + powspctrm = freq.powspctrm; +elseif hasrpt + %compute average only + siz = [size(freq.powspctrm) 1]; + powspctrm = reshape(nanmean(freq.powspctrm,1), [siz(2:end)]); +else + %nothing to do + powspctrm = freq.powspctrm; +end + +if hasrpt && ~keepflg, + dimtok = tokenize(freq.dimord, '_'); + newdimord = dimtok{2}; + for k = 3:numel(dimtok) + newdimord = [newdimord,'_',dimtok{k}]; + end +else + newdimord = freq.dimord; +end + +% create the output-structure +output = []; +output.dimord = newdimord; +output.freq = freq.freq; +output.label = freq.label; +try, output.time = freq.time; end; +try, output.grad = freq.grad; end; +try, output.cumtapcnt = freq.cumtapcnt; end; +try, output.cumsumcnt = freq.cumsumcnt; end; +output.powspctrm = powspctrm; +try, output.powspctrmsem = powspctrmsem; end; + +% accessing this field here is needed for the configuration tracking +% by accessing it once, it will not be removed from the output cfg +cfg.outputfile; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_freqdescriptives.m 1311 2010-06-30 12:17:57Z timeng $'; + +try, cfg.previous = freq.cfg; end + +% remember the configuration details +output.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', output); % use the variable name "data" in the output file +end diff --git a/external/fieldtrip/ft_freqgrandaverage.m b/external/fieldtrip/ft_freqgrandaverage.m index b84b9b2..a340c80 100644 --- a/external/fieldtrip/ft_freqgrandaverage.m +++ b/external/fieldtrip/ft_freqgrandaverage.m @@ -1,11 +1,278 @@ -function varargout = funname(varargin); +function [grandavg] = ft_freqgrandaverage(cfg, varargin); -% this is a SPM wrapper around a FieldTrip function +% FT_FREQGRANDAVERAGE computes the average powerspectrum or time-frequency spectrum +% over multiple subjects +% +% Use as +% [grandavg] = ft_freqgrandaverage(cfg, freq1, freq2, freq3...) +% +% The input data freq1..N are obtained from either FT_FREQANALYSIS with +% keeptrials=no or from FT_FREQDESCRIPTIVES. The configuration structure +% can contain +% cfg.keepindividual = 'yes' or 'no' (default = 'no') +% cfg.foilim = [fmin fmax] or 'all', to specify a subset of frequencies (default = 'all') +% cfg.toilim = [tmin tmax] or 'all', to specify a subset of latencies (default = 'all') +% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), +% see FT_CHANNELSELECTION for details +% +% See also FT_TIMELOCKGRANDAVERAGE, FT_FREQANALYSIS, FT_FREQDESCRIPTIVES +% +% Undocumented local options: +% cfg.inputfile = one can specifiy preanalysed saved data as input +% The data should be provided in a cell array +% cfg.outputfile = one can specify output as file to save to disk -% this part is variable -prefix = 'ft_'; +% FIXME averaging coherence is not possible if inputs contain different amounts of data (i.e. chan/freq/time) -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +% Copyright (C) 2005-2006, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_freqgrandaverage.m 1311 2010-06-30 12:17:57Z timeng $ + +fieldtripdefs + +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +% set the defaults +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +hasdata = nargin>1; +if ~isempty(cfg.inputfile) % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + for i=1:numel(cfg.inputfile) + varargin{i} = loadvar(cfg.inputfile{i}, 'data'); % read datasets from array inputfile + end + end +end + +% check if the input data is valid for this function +for i=1:length(varargin) + varargin{i} = checkdata(varargin{i}, 'datatype', 'freq', 'feedback', 'no'); +end + +% set the defaults +if ~isfield(cfg, 'keepindividual'), cfg.keepindividual = 'no'; end +if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end +if ~isfield(cfg, 'foilim'), cfg.foilim = 'all'; end +if ~isfield(cfg, 'toilim'), cfg.toilim = 'all'; end + +% for backward compatibility with old data structures +if isfield(varargin{1}, 'sgn') && ~isfield(varargin{1}, 'label') + warning('renaming "sng" field into label for backward compatibility'); + for s=1:Nsubj + varargin{s}.label = varargin{s}.sgn; + end +end + +% for backward compatibility with old data structures +if isfield(varargin{1}, 'sgncmb') && ~isfield(varargin{1}, 'labelcmb') + warning('renaming "sngcmb" field into labelcmb for backward compatibility'); + for s=1:Nsubj + varargin{s}.labelcmb = varargin{s}.sgncmb; + end +end + +Nsubj = length(varargin); +dimord = varargin{1}.dimord; +haspow = isfield(varargin{1}, 'powspctrm'); % this should always be true +hascoh = isfield(varargin{1}, 'cohspctrm'); +hasplv = isfield(varargin{1}, 'plvspctrm'); +hasfreq = ~isempty(strfind(varargin{i}.dimord, 'freq')); % this should always be true +hastime = ~isempty(strfind(varargin{i}.dimord, 'time')); +hasrpt = ~isempty(strfind(varargin{i}.dimord, 'rpt')); +hastap = ~isempty(strfind(varargin{i}.dimord, 'tap')); + +% check whether the input data is suitable +if hasrpt + error('the input data of each subject should be an average, use FREQDESCRIPTIVES first'); +end +if hastap + error('multiple tapers in the input are not supported'); +end + +if ischar(cfg.foilim) && strcmp(cfg.foilim, 'all') + fbeg = -inf; + fend = inf; +else + fbeg = cfg.foilim(1); + fend = cfg.foilim(2); +end + +if ischar(cfg.toilim) && strcmp(cfg.toilim, 'all') + tbeg = -inf; + tend = inf; +else + tbeg = cfg.toilim(1); + tend = cfg.toilim(2); +end + +% determine which channels, frequencies and latencies are available for all inputs +for i=1:Nsubj + cfg.channel = ft_channelselection(cfg.channel, varargin{i}.label); + if hasfreq + fbeg = max(fbeg, varargin{i}.freq(1 )); + fend = min(fend, varargin{i}.freq(end)); + end + if hastime + tbeg = max(tbeg, varargin{i}.time(1 )); + tend = min(tend, varargin{i}.time(end)); + end +end +cfg.foilim = [fbeg fend]; +cfg.toilim = [tbeg tend]; + +% select the data in all inputs +for i=1:Nsubj + chansel = match_str(varargin{i}.label, cfg.channel); + varargin{i}.label = varargin{i}.label(chansel); + if hasfreq + freqsel = nearest(varargin{i}.freq, fbeg):nearest(varargin{i}.freq, fend); + varargin{i}.freq = varargin{i}.freq(freqsel); + end + if hastime + timesel = nearest(varargin{i}.time, tbeg):nearest(varargin{i}.time, tend); + varargin{i}.time = varargin{i}.time(timesel); + end + % select the overlapping samples in the power spectrum + switch dimord + case 'chan_freq' + varargin{i}.powspctrm = varargin{i}.powspctrm(chansel,freqsel); + case 'chan_freq_time' + varargin{i}.powspctrm = varargin{i}.powspctrm(chansel,freqsel,timesel); + case {'rpt_chan_freq' 'rpttap_chan_freq' 'subj_chan_freq'} + varargin{i}.powspctrm = varargin{i}.powspctrm(:,chansel,freqsel); + case {'rpt_chan_freq_time' 'rpttap_chan_freq_time' 'subj_chan_freq_time'} + varargin{i}.powspctrm = varargin{i}.powspctrm(:,chansel,freqsel,timesel); + otherwise + error('unsupported dimord'); + end +end + +% determine the size of the data to be averaged +dim = size(varargin{1}.powspctrm); +if hascoh, + cohdim = size(varargin{1}.cohspctrm); +end +if hasplv, + plvdim = size(varargin{1}.plvspctrm); +end + +% give some feedback on the screen +if strcmp(cfg.keepindividual, 'no') + if haspow, fprintf('computing average power over %d subjects\n', Nsubj); end + if hascoh, fprintf('computing average coherence over %d subjects\n', Nsubj); end + if hasplv, fprintf('computing average phase-locking value over %d subjects\n', Nsubj); end +else + if haspow, fprintf('not computing grand average, but keeping individual power for %d subjects\n', Nsubj); end + if hascoh, fprintf('not computing grand average, but keeping individual coherence for %d subjects\n', Nsubj); end + if hasplv, fprintf('not computing grand average, but keeping individual phase-locking value for %d subjects\n', Nsubj); end +end + +% allocate memory to hold the data +if strcmp(cfg.keepindividual, 'no') + if haspow, s_pow = zeros( dim); end + if hascoh, s_coh = zeros(cohdim); end + if hasplv, s_plv = zeros(plvdim); end +else + if haspow, s_pow = zeros([Nsubj dim]); end + if hascoh, s_coh = zeros([Nsubj cohdim]); end + if hasplv, s_plv = zeros([Nsubj plvdim]); end +end + +for s=1:Nsubj + if strcmp(cfg.keepindividual, 'no') + % add this subject to the total sum + if haspow, s_pow = s_pow + varargin{s}.powspctrm; end + if hascoh, s_coh = s_coh + varargin{s}.cohspctrm; end + if hasplv, s_plv = s_plv + varargin{s}.plvspctrm; end + else + % concatenate this subject to the rest + if haspow, s_pow(s,:) = varargin{s}.powspctrm(:); end + if hascoh, s_coh(s,:) = varargin{s}.cohspctrm(:); end + if hasplv, s_plv(s,:) = varargin{s}.plvspctrm(:); end + end +end + +% collect the output data +grandavg.label = varargin{1}.label; +grandavg.freq = varargin{1}.freq; +if isfield(varargin{1}, 'time') + % remember the time axis + grandavg.time = varargin{1}.time; +end +if isfield(varargin{1}, 'grad') + warning('discarding gradiometer information because it cannot be averaged'); +end +if isfield(varargin{1}, 'elec') + warning('discarding electrode information because it cannot be averaged'); +end + +if strcmp(cfg.keepindividual, 'no') + grandavg.dimord = dimord; + grandavg.powspctrm = s_pow/Nsubj; + if hascoh, + grandavg.labelcmb = varargin{1}.labelcmb; + grandavg.cohspctrm = s_coh/Nsubj; + end + if hasplv, + grandavg.labelcmb = varargin{1}.labelcmb; + grandavg.plvspctrm = s_plv/Nsubj; + end +else + grandavg.dimord = ['subj_' dimord]; + grandavg.powspctrm = s_pow; + if hascoh, + grandavg.labelcmb = varargin{1}.labelcmb; + grandavg.cohspctrm = s_coh; + end + if hasplv, + grandavg.labelcmb = varargin{1}.labelcmb; + grandavg.plvspctrm = s_plv; + end +end + +cfg.outputfile; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_freqgrandaverage.m 1311 2010-06-30 12:17:57Z timeng $'; +% remember the configuration details of the input data +cfg.previous = []; +for i=1:length(varargin) + try, cfg.previous{i} = varargin{i}.cfg; end +end +% remember the exact configuration details in the output +grandavg.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', grandavg); % use the variable name "data" in the output file +end diff --git a/external/fieldtrip/ft_freqinterpolate.m b/external/fieldtrip/ft_freqinterpolate.m new file mode 100644 index 0000000..a5b8019 --- /dev/null +++ b/external/fieldtrip/ft_freqinterpolate.m @@ -0,0 +1,120 @@ + +function [freq] = ft_freqinterpolate(cfg, freq) + +% FT_FREQINTERPOLATE interpolates frequencies by looking at neighbouring +% values or simply replaces a piece in the spectrum by NaN. +% +% Use as +% freq = ft_freqinterpolate(cfg, freq) +% where freq is the output of FT_FREQANALYSIS or FT_FREQDESCRIPTIVES and the +% configuration may contain +% cfg.method = 'nan', 'linear' (default = 'nan') +% cfg.foilim = Nx2 matrix with begin and end of each interval to be +% interpolated (default = [49 51; 99 101; 149 151]) +% +% Undocumented local options: +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk + + +% Copyright (C) 2009, Aldemar Torres Valderama +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_freqinterpolate.m 1258 2010-06-22 08:33:48Z timeng $ + +fieldtripdefs + +% check if the input cfg is valid for this function +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +% set the default values +if ~isfield(cfg, 'method'), cfg.method = 'nan'; end +if ~isfield(cfg, 'foilim'), cfg.foilim = [49 51; 99 101; 149 151]; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +% load optional given inputfile as data +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + freq = loadvar(cfg.inputfile, 'data'); + end +end + +% check if the input data is valid for this function +freq = checkdata(freq, 'datatype', 'freq', 'feedback', 'yes'); + +for i = 1:size(cfg.foilim,1) + % determine the exact frequency bins to interpolate + peakbeg = nearest(freq.freq, cfg.foilim(i,1)); + peakend = nearest(freq.freq, cfg.foilim(i,2)); + % update the configuration + cfg.foilim(i,1) = freq.freq(peakbeg); + cfg.foilim(i,2) = freq.freq(peakend); + + if strcmp(cfg.method, 'nan') + switch freq.dimord + case 'chan_freq' + freq.powspctrm(:,peakbeg:peakend) = nan; + case 'chan_freq_time' + freq.powspctrm(:,peakbeg:peakend,:) = nan; + case 'rpt_chan_freq' + freq.powspctrm(:,:,peakbeg:peakend) = nan; + case 'rpt_chan_freq_time' + freq.powspctrm(:,:,peakbeg:peakend,:) = nan; + otherwise + error('unsupported dimord'); + end % switch + + elseif strcmp(cfg.method, 'linear') + error('not yet implemented'); + + else + error('unsupported method'); + end +end % for each frequency range + +% accessing this field here is needed for the configuration tracking +% by accessing it once, it will not be removed from the output cfg +cfg.outputfile; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add the version details of this function call to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_freqinterpolate.m 1258 2010-06-22 08:33:48Z timeng $'; +% remember the configuration details of the input data +try, cfg.previous = freq.cfg; end +% remember the exact configuration details in the output +freq.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', freq); % use the variable name "data" in the output file +end diff --git a/external/fieldtrip/ft_freqsimulation.m b/external/fieldtrip/ft_freqsimulation.m index b84b9b2..a53cb42 100644 --- a/external/fieldtrip/ft_freqsimulation.m +++ b/external/fieldtrip/ft_freqsimulation.m @@ -1,11 +1,521 @@ -function varargout = funname(varargin); +function [data] = ft_freqsimulation(cfg) -% this is a SPM wrapper around a FieldTrip function +% FT_FREQSIMULATION makes simulated data in FieldTrip format. The data is built +% up from fifferent frequencies and can contain a signal in which the +% different frequencies interact (i.e. cross-frequency coherent). Different +% methods are possible to make data with special properties. +% +% Use as +% [data] = ft_freqsimulation(cfg) +% +% The configuration options include +% cfg.method = The methods are explained in more detail below, but they can be +% 'superimposed' simply add the contribution of the different frequencies +% 'broadband' create a single broadband signal component +% 'phalow_amphigh' phase of low freq correlated with amplitude of high freq +% 'amplow_amphigh' amplitude of low freq correlated with amplithude of high freq +% 'phalow_freqhigh' phase of low freq correlated with frequency of high signal +% 'asymmetric' single signal component with asymmetric positive/negative deflections +% cfg.output = which channels should be in the output data, can be 'mixed' or 'all' (default = 'all') +% +% The number of trials and the time axes of the trials can be specified by +% cfg.fsample = simulated sample frequency +% cfg.trllen = length of simulated trials in seconds +% cfg.numtrl = number of simulated trials +% or by +% cfg.time = cell-array with one time axis per trial (i.e. from another dataset) +% +% For each of the methods default parameters are configured to generate +% example data, including noise. To get full control over the generated +% data you should explicitely set all parameters involved in the method +% of your choise. The interpretation of the following signal components +% depends on the specified method: +% +% cfg.s1.freq = frequency of signal 1 +% cfg.s1.phase = phase (in rad) relative to cosine of signal 1 (default depends on method) +% = number or 'random' +% cfg.s1.ampl = amplitude of signal 1 +% cfg.s2.freq = frequency of signal 2 +% cfg.s2.phase = phase (in rad) relative to cosine of signal 1 (default depends on method) +% = number or 'random' +% cfg.s2.ampl = amplitude of signal 2 +% cfg.s3.freq = frequency of signal 3 +% cfg.s3.phase = phase (in rad) relative to cosine of signal 1 (default depends on method) +% = number or 'random' +% cfg.s3.ampl = amplitude of signal 3 +% cfg.s4.freq = frequency of signal 4 +% cfg.s4.phase = phase (in rad) relative to cosine of signal 1 (default depends on method) +% = number or 'random' +% cfg.s4.ampl = amplitude of signal 4 +% +% cfg.n1.ampl = root-mean-square amplitude of wide-band signal prior to filtering +% cfg.n1.bpfreq = [Flow Fhigh] +% cfg.n2.ampl = root-mean-square amplitude of wide-band signal prior to filtering +% cfg.n2.bpfreq = [Flow Fhigh] +% +% cfg.asymmetry = amount of asymmetry (default = 0, which is none) +% cfg.noise.ampl = amplitude of noise +% +% +% In the method 'superimposed' the signal contains just the sum of the different frequency contributions: +% s1: first frequency +% s2: second frequency +% s3: third frequency +% and the output consists of the following channels: +% 1st channel: mixed signal = s1 + s2 + s3 + noise +% 2nd channel: s1 +% 3rd channel: s2 +% 4th channel: s3 +% 5th channel: noise +% +% In the method 'broadband' the signal contains a the superposition of two +% broadband signal components, which are created by bandpass filtering a +% Gaussian noise signal: +% n1: first broadband signal +% n2: second broadband signal +% and the output consists of the following channels: +% 1st channel: mixed signal = n1 + n2 + noise +% 2nd channel: n1 +% 3rd channel: n2 +% 4th channel: noise +% +% In the method 'phalow_amphigh' the signal is build up of 4 components; s1, s2, s3 and noise: +% s1: amplitude modulation (AM), frequency of this signal should be lower than s2 +% s2: second frequency, frequncy that becomes amplitude modulated +% s3: DC shift of s1, should have frequency of 0 +% and the output consists of the following channels: +% 1st channel: mixed signal = (s1 + s3)*s2 + noise, +% 2nd channel: s1 +% 3rd channel: s2 +% 4th channel: s3 +% 5th channel: noise +% +% In the method 'amplow_amphigh' the signal is build up of 5 components; s1, s2, s3, s4 and noise. +% s1: first frequency +% s2: second frequency +% s3: DC shift of s1 and s2, should have frequency of 0 +% s4: amplitude modulation (AM), frequency of this signal should be lower than s1 and s2 +% and the output consists of the following channels: +% 1st channel: mixed signal = (s4 + s3)*s1 + (s4 + s3)*s2 + noise, +% 2nd channel: s1 +% 3rd channel: s2 +% 4th channel: s3 +% 5th channel: noise +% 6th channel: s4 +% 7th channel: mixed part 1: (s4 + s3)*s1 +% 8th channel: mixed part 2: (s4 + s3)*s2 +% +% In the method 'phalow_freqhigh' a frequency modulated signal is created. +% signal is build up of 3 components; s1, s2 and noise. +% s1: represents the base signal that will be modulated +% s2: signal that will be used for the frequency modulation +% and the output consists of the following channels: +% 1st channel: mixed signal = s1.ampl * cos(ins_pha) + noise +% 2nd channel: s1 +% 3rd channel: s2 +% 4th channel: noise +% 5th channel: inst_pha_base instantaneous phase of the high (=base) frequency signal s1 +% 6th channel: inst_pha_mod low frequency phase modulation, this is equal to s2 +% 7th channel: inst_pha instantaneous phase, i.e. inst_pha_base + inst_pha_mod +% +% In the method 'asymmetric' there is only one periodic signal, but that +% signal is more peaked for the positive than for the negative deflections. +% The average of the signal over time is zero. +% s1: represents the frequency of the base signal +% and the output consists of the following channels: +% 1st channel: mixed signal = asymmetric signal + noise +% 2nd channel: sine wave with base frequency and phase, i.e. s1 +% 3rd channel: asymmetric signal +% 4th channel: noise -% this part is variable -prefix = 'ft_'; +% Copyright (C) 2007-2008, Ingrid Nieuwenhuis & Robert Oostenveld, F.C. Donders Centre +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_freqsimulation.m 948 2010-04-21 18:02:21Z roboos $ -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +fieldtripdefs + +% set defaults +if ~isfield(cfg, 'method'), cfg.method = 'phalow_amphigh'; end +if ~isfield(cfg, 'output'), cfg.output = 'all'; end +if ~isfield(cfg, 'time'), cfg.time = []; end + +if isempty(cfg.time) + if ~isfield(cfg, 'fsample'), cfg.fsample = 1200; end + if ~isfield(cfg, 'trllen'), cfg.trllen = 1; end + if ~isfield(cfg, 'numtrl'), cfg.numtrl = 1; end +else + cfg.trllen = []; % can be variable + cfg.fsample = 1/(cfg.time{1}(2) - cfg.time{1}(1)); % determine from time-axis + cfg.numtrl = length(cfg.time); +end + +if strcmp(cfg.method,'superimposed') + if ~isfield(cfg, 's1'), cfg.s1 = []; end + if ~isfield(cfg.s1, 'freq'), cfg.s1.freq = 10; end + if ~isfield(cfg.s1, 'phase'), cfg.s1.phase = 0; end + if ~isfield(cfg.s1, 'ampl'), cfg.s1.ampl = 1; end + if ~isfield(cfg, 's2'), cfg.s2 = []; end + if ~isfield(cfg.s2, 'freq'), cfg.s2.freq = 20; end + if ~isfield(cfg.s2, 'phase'), cfg.s2.phase = 0; end + if ~isfield(cfg.s2, 'ampl'), cfg.s2.ampl = 0; end + if ~isfield(cfg, 's3'), cfg.s3 = []; end + if ~isfield(cfg.s3, 'freq'), cfg.s3.freq = 30; end + if ~isfield(cfg.s3, 'phase'), cfg.s3.phase = 0; end + if ~isfield(cfg.s3, 'ampl'), cfg.s3.ampl = 0; end +end + +if strcmp(cfg.method,'broadband') + if ~isfield(cfg, 'n1'), cfg.n1 = []; end + if ~isfield(cfg.n1, 'ampl'), cfg.n1.ampl = 1; end + if ~isfield(cfg.n1, 'bpfreq'), cfg.n1.bpfreq = [30 50]; end + if ~isfield(cfg, 'n2'), cfg.n2 = []; end + if ~isfield(cfg.n2, 'ampl'), cfg.n2.ampl = 1; end + if ~isfield(cfg.n2, 'bpfreq'), cfg.n2.bpfreq = [80 120]; end +end + +if strcmp(cfg.method,'phalow_amphigh') + if ~isfield(cfg, 's1'), cfg.s1 = []; end + if ~isfield(cfg.s1, 'freq'), cfg.s1.freq = 3; end + if ~isfield(cfg.s1, 'phase'), cfg.s1.phase = -1*pi; end + if ~isfield(cfg.s1, 'ampl'), cfg.s1.ampl = 1; end + if ~isfield(cfg, 's2'), cfg.s2 = []; end + if ~isfield(cfg.s2, 'freq'), cfg.s2.freq = 20; end + if ~isfield(cfg.s2, 'phase'), cfg.s2.phase = 0; end + if ~isfield(cfg.s2, 'ampl'), cfg.s2.ampl = 1; end + if ~isfield(cfg, 's3'), cfg.s3 = []; end + if ~isfield(cfg.s3, 'freq'), cfg.s3.freq = 0; end + if ~isfield(cfg.s3, 'phase'), cfg.s3.phase = 0; end + if ~isfield(cfg.s3, 'ampl'), cfg.s3.ampl = cfg.s1.ampl; end +end + +if strcmp(cfg.method,'amplow_amphigh') + if ~isfield(cfg, 's1'), cfg.s1 = []; end + if ~isfield(cfg.s1, 'freq'), cfg.s1.freq = 6; end + if ~isfield(cfg.s1, 'phase'), cfg.s1.phase = 0; end + if ~isfield(cfg.s1, 'ampl'), cfg.s1.ampl = 1; end + if ~isfield(cfg, 's2'), cfg.s2 = []; end + if ~isfield(cfg.s2, 'freq'), cfg.s2.freq = 20; end + if ~isfield(cfg.s2, 'phase'), cfg.s2.phase = 0; end + if ~isfield(cfg.s2, 'ampl'), cfg.s2.ampl = 1; end + if ~isfield(cfg, 's4'), cfg.s4 = []; end + if ~isfield(cfg.s4, 'freq'), cfg.s4.freq = 1; end + if ~isfield(cfg.s4, 'phase'), cfg.s4.phase = -1*pi; end + if ~isfield(cfg.s4, 'ampl'), cfg.s4.ampl = 1; end + if ~isfield(cfg, 's3'), cfg.s3 = []; end + if ~isfield(cfg.s3, 'freq'), cfg.s3.freq = 0; end + if ~isfield(cfg.s3, 'phase'), cfg.s3.phase = 0; end + if ~isfield(cfg.s3, 'ampl'), cfg.s3.ampl = cfg.s4.ampl; end +end + +if strcmp(cfg.method,'phalow_freqhigh') + if ~isfield(cfg, 's1'), cfg.s1 = []; end + if ~isfield(cfg.s1, 'freq'), cfg.s1.freq = 20; end + if ~isfield(cfg.s1, 'phase'), cfg.s1.phase = 0; end + if ~isfield(cfg.s1, 'ampl'), cfg.s1.ampl = 1; end + if ~isfield(cfg, 's2'), cfg.s2 = []; end + if ~isfield(cfg.s2, 'freq'), cfg.s2.freq = 2; end + if ~isfield(cfg.s2, 'phase'), cfg.s2.phase = -0.5 * pi; end %then base freq at t=0 + if ~isfield(cfg.s2, 'ampl'), cfg.s2.ampl = pi; end +end + +if strcmp(cfg.method,'asymmetric') + if ~isfield(cfg, 's1'), cfg.s1 = []; end + if ~isfield(cfg.s1, 'freq'), cfg.s1.freq = 6; end + if ~isfield(cfg.s1, 'phase'), cfg.s1.phase = 0; end + if ~isfield(cfg.s1, 'ampl'), cfg.s1.ampl = 1; end + if ~isfield(cfg, 'noise'), cfg.noise = []; end + if ~isfield(cfg.noise, 'ampl'), cfg.noise.ampl = 0.1; end % default should not be too high +end + +if ~isfield(cfg, 'noise'), cfg.noise = []; end +if ~isfield(cfg.noise, 'ampl'), cfg.noise.ampl = 1; end + + +if ~isempty(cfg.time) + % use the user-supplied time vectors + timevec = cfg.time; +else + Nsamp_tr = cfg.fsample * cfg.trllen; + for iTr = 1 : cfg.numtrl + timevec{iTr} = (1:Nsamp_tr)/cfg.fsample; + end +end + + +%%%%%%% SUPERIMPOSED, SIMPLY ADD THE SIGNALS %%%%%%%%% +if strcmp(cfg.method,'superimposed') + + % make data + for iTr = 1 : length(timevec) + if isstr(cfg.s1.phase); phase_s1 = rand * 2 *pi; else phase_s1 = cfg.s1.phase; end + if isstr(cfg.s2.phase); phase_s2 = rand * 2 *pi; else phase_s2 = cfg.s2.phase; end + if isstr(cfg.s3.phase); phase_s3 = rand * 2 *pi; else phase_s3 = cfg.s3.phase; end + + s1 = cfg.s1.ampl*cos(2*pi*cfg.s1.freq*timevec{iTr} + phase_s1); + s2 = cfg.s2.ampl*cos(2*pi*cfg.s2.freq*timevec{iTr} + phase_s2); + s3 = cfg.s3.ampl*cos(2*pi*cfg.s3.freq*timevec{iTr} + phase_s3); + noise = cfg.noise.ampl*randn(size(timevec{iTr})); + mix = s1 + s2 + s3 + noise; + + data.trial{iTr}(1,:) = mix; + if strcmp(cfg.output,'all') + data.trial{iTr}(2,:) = s1; + data.trial{iTr}(3,:) = s2; + data.trial{iTr}(4,:) = s3; + data.trial{iTr}(5,:) = noise; + end + data.time{iTr} = timevec{iTr}; + end % for iTr + + data.label{1} = 'mix'; + if strcmp(cfg.output,'all') + data.label{2} = 's1'; + data.label{3} = 's2'; + data.label{4} = 's3'; + data.label{5} = 'noise'; + end + data.fsample = cfg.fsample; + + %%%%%%% SUPERIMPOSED BROADBAND SIGNAL %%%%%%%%% +elseif strcmp(cfg.method,'broadband') + + % make data + for iTr = 1 : length(timevec) + n1 = ft_preproc_bandpassfilter(cfg.n1.ampl*randn(size(timevec{iTr})), cfg.fsample, cfg.n1.bpfreq); + n2 = ft_preproc_bandpassfilter(cfg.n2.ampl*randn(size(timevec{iTr})), cfg.fsample, cfg.n2.bpfreq); + noise = cfg.noise.ampl*randn(size(timevec{iTr})); + mix = n1 + n2 + noise; + + data.trial{iTr}(1,:) = mix; + if strcmp(cfg.output,'all') + data.trial{iTr}(2,:) = n1; + data.trial{iTr}(3,:) = n2; + data.trial{iTr}(4,:) = noise; + end + data.time{iTr} = timevec{iTr}; + end % for iTr + + data.label{1} = 'mix'; + if strcmp(cfg.output,'all') + data.label{2} = 'n1'; + data.label{3} = 'n2'; + data.label{4} = 'noise'; + end + data.fsample = cfg.fsample; + + %%%%%%% PHASE TO AMPLITUDE CORRELATION %%%%%%%%% +elseif strcmp(cfg.method,'phalow_amphigh') + + % sanity checks + if cfg.s2.freq < cfg.s1.freq + error('with method is phalow_amphigh freq s2 should be higher than freq s1') + end + if cfg.s2.freq > cfg.fsample/2 + error('you cannot have a frequency higher than the sample frequency/2') + end + if cfg.s3.freq ~= 0 || cfg.s3.phase ~= 0 + warning('for method phalow_amphigh s3 is DC and therefore expect freq and phase to be zero but they are not') + end + if cfg.s3.ampl < cfg.s1.ampl + warning('expect amplitude s3 (=DC) not to be smaller than amplitude s1 (=low frequency)') + end + + % make data + for iTr = 1 : length(timevec) + + if isstr(cfg.s1.phase); phase_AM = rand * 2 *pi; else phase_AM = cfg.s1.phase; end + if isstr(cfg.s2.phase); phase_high = rand * 2 *pi; else phase_high = cfg.s2.phase; end + if isstr(cfg.s3.phase); phase_DC = rand * 2 *pi; else phase_DC = cfg.s3.phase; end + high = cfg.s2.ampl*cos(2*pi*cfg.s2.freq*timevec{iTr} + phase_high); + AM = cfg.s1.ampl*cos(2*pi*cfg.s1.freq*timevec{iTr} + phase_AM); + DC = cfg.s3.ampl*cos(2*pi*0*timevec{iTr} + phase_DC); + noise = cfg.noise.ampl*randn(size(timevec{iTr})); + mix = ((AM + DC) .* high) + noise; + + data.trial{iTr}(1,:) = mix; + if strcmp(cfg.output,'all') + data.trial{iTr}(2,:) = AM; + data.trial{iTr}(3,:) = high; + data.trial{iTr}(4,:) = DC; + data.trial{iTr}(5,:) = noise; + end + data.time{iTr} = timevec{iTr}; + end % for iTr + + data.label{1} = 'mix'; + if strcmp(cfg.output,'all') + data.label{2} = 's1 (AM)'; + data.label{3} = 's2 (high)'; + data.label{4} = 's3 (DC)'; + data.label{5} = 'noise'; + end + data.fsample = cfg.fsample; + + %%%%%%% POWER TO POWER CORRELATION %%%%%%%%% +elseif strcmp(cfg.method,'amplow_amphigh') + + % sanity checks + if cfg.s2.freq < cfg.s1.freq || cfg.s1.freq < cfg.s4.freq + error('with method is powlow_powhigh freq s4 < s1 < s2') + end + if cfg.s2.freq > cfg.fsample/2 + error('you cannot have a frequency higher than the sample frequency/2') + end + if cfg.s3.freq ~= 0 || cfg.s3.phase ~= 0 + warning('for method powlow_powhigh s3 is DC and therefore expect freq and phase to be zero but they are not') + end + if cfg.s3.ampl < cfg.s4.ampl + warning('expect amplitude s3 (=DC) not to be smaller than amplitude s4 (= AM frequency)') + end + + % make data + for iTr = 1 : length(timevec) + + if isstr(cfg.s1.phase); phase_low = rand * 2 *pi; else phase_low = cfg.s1.phase; end + if isstr(cfg.s2.phase); phase_high = rand * 2 *pi; else phase_high = cfg.s2.phase; end + if isstr(cfg.s3.phase); phase_DC = rand * 2 *pi; else phase_DC = cfg.s3.phase; end + if isstr(cfg.s4.phase); phase_AM = rand * 2 *pi; else phase_AM = cfg.s4.phase; end + high = cfg.s2.ampl*cos(2*pi*cfg.s2.freq*timevec{iTr} + phase_high); + low = cfg.s1.ampl*cos(2*pi*cfg.s1.freq*timevec{iTr} + phase_low); + AM = cfg.s4.ampl*cos(2*pi*cfg.s4.freq*timevec{iTr} + phase_AM); + DC = cfg.s3.ampl*cos(2*pi*0*timevec{iTr} + phase_DC); + noise = cfg.noise.ampl*randn(size(timevec{iTr})); + lowmix = ((AM + DC) .* low); + highmix = ((AM + DC) .* high); + mix = lowmix + highmix + noise; + + data.trial{iTr}(1,:) = mix; + if strcmp(cfg.output,'all') + data.trial{iTr}(2,:) = low; + data.trial{iTr}(3,:) = high; + data.trial{iTr}(4,:) = DC; + data.trial{iTr}(5,:) = noise; + data.trial{iTr}(6,:) = AM; + data.trial{iTr}(7,:) = lowmix; + data.trial{iTr}(8,:) = highmix; + end + data.time{iTr} = timevec{iTr}; + end % for iTr + + data.label{1} = 'mix'; + if strcmp(cfg.output,'all') + data.label{2} = 's1 (low)'; + data.label{3} = 's2 (high)'; + data.label{4} = 's3 (DC)'; + data.label{5} = 'noise'; + data.label{6} = 's4 (AM)'; + data.label{7} = 'mixlow'; + data.label{8} = 'mixhigh'; + end + data.fsample = cfg.fsample; + + %%%%%%% PHASE TO FREQUENCY CORRELATION %%%%%%%%% +elseif strcmp(cfg.method,'phalow_freqhigh') + + % sanity checks + if cfg.s1.freq > cfg.fsample/2 || cfg.s2.freq > cfg.fsample/2 + error('you cannot have a frequency higher than the sample frequency/2') + end + + % make data + for iTr = 1 : length(timevec) + + if isstr(cfg.s1.phase); phase_s1 = rand * 2 *pi; else phase_s1 = cfg.s1.phase; end + if isstr(cfg.s2.phase); phase_s2 = rand * 2 *pi; else phase_s2= cfg.s2.phase; end + s1 = cfg.s1.ampl .* cos(2*pi*cfg.s1.freq * timevec{iTr} + phase_s1); % to be modulated signal + s2 = cfg.s2.ampl .* cos(2*pi*cfg.s2.freq * timevec{iTr} + phase_s2); % modulation of instantaneous phase + inst_pha_base = 2*pi*cfg.s1.freq * timevec{iTr} + phase_s1; % unmodulated instantaneous phase s1 (linear) + inst_pha_mod = s2; % modulation of instantaneous phase + inst_pha = inst_pha_base + inst_pha_mod; + noise = cfg.noise.ampl*randn(size(timevec{iTr})); + mix = cfg.s1.ampl .* cos(inst_pha) + noise; + + data.trial{iTr}(1,:) = mix; + if strcmp(cfg.output,'all') + data.trial{iTr}(2,:) = s1; + data.trial{iTr}(3,:) = s2; + data.trial{iTr}(4,:) = noise; + data.trial{iTr}(5,:) = inst_pha_base; + data.trial{iTr}(6,:) = inst_pha_mod; + data.trial{iTr}(7,:) = inst_pha; + end + data.time{iTr} = timevec{iTr}; + end % for iTr + + data.label{1} = 'mix'; + if strcmp(cfg.output,'all') + data.label{2} = 's1'; + data.label{3} = 's2'; + data.label{4} = 'noise'; + data.label{5} = 'inst phase base'; + data.label{6} = 'inst phase modulation (=s2)'; + data.label{7} = 'inst phase'; + end + data.fsample = cfg.fsample; + + %%%%%%% ASYMETRIC POSITIVE AND NEGATIVE PEAKS %%%%%%%%% +elseif strcmp(cfg.method,'asymmetric') + + % make data + for iTr = 1 : length(timevec) + if isstr(cfg.s1.phase); phase_s1 = rand * 2 *pi; else phase_s1 = cfg.s1.phase; end + + s1 = cfg.s1.ampl*cos(2*pi*cfg.s1.freq*timevec{iTr} + phase_s1); + tmp = cos(2*pi*cfg.s1.freq*timevec{iTr} + phase_s1); % same signal but with unit amplitude + tmp = (tmp+1)/2; % scaled and shifted between 0 and 1 + tmp = tmp.^(cfg.asymmetry+1); % made asymmetric + tmp = (tmp - mean(tmp))*2*cfg.s1.ampl; % rescale + s2 = tmp; + noise = cfg.noise.ampl*randn(size(timevec{iTr})); + mix = s2 + noise; + + data.trial{iTr}(1,:) = mix; + if strcmp(cfg.output,'all') + data.trial{iTr}(2,:) = s1; + data.trial{iTr}(3,:) = s2; + data.trial{iTr}(4,:) = noise; + end + data.time{iTr} = timevec{iTr}; + end % for iTr + + data.label{1} = 'mix'; + if strcmp(cfg.output,'all') + data.label{2} = 's1'; + data.label{3} = 's2'; + data.label{4} = 'noise'; + end + data.fsample = cfg.fsample; + +else + error('unknown method specified') +end + +% add the version details of this function call to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_freqsimulation.m 948 2010-04-21 18:02:21Z roboos $'; + +% remember the exact configuration details in the output +data.cfg = cfg; diff --git a/external/fieldtrip/ft_freqstatistics.m b/external/fieldtrip/ft_freqstatistics.m index b84b9b2..8fcabe7 100644 --- a/external/fieldtrip/ft_freqstatistics.m +++ b/external/fieldtrip/ft_freqstatistics.m @@ -1,11 +1,160 @@ -function varargout = funname(varargin); +function [stat] = ft_freqstatistics(cfg, varargin) -% this is a SPM wrapper around a FieldTrip function +% FT_FREQSTATISTICS computes significance probabilities and/or critical values of a parametric statistical test +% or a non-parametric permutation test. +% +% Use as +% [stat] = ft_freqstatistics(cfg, freq1, freq2, ...) +% where the input data is the result from FT_FREQANALYSIS, FT_FREQDESCRIPTIVES +% or from FT_FREQGRANDAVERAGE. +% +% The configuration can contain the following options for data selection +% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), +% see FT_CHANNELSELECTION for details +% cfg.latency = [begin end] in seconds or 'all' (default = 'all') +% cfg.frequency = [begin end], can be 'all' (default = 'all') +% cfg.avgoverchan = 'yes' or 'no' (default = 'no') +% cfg.avgovertime = 'yes' or 'no' (default = 'no') +% cfg.avgoverfreq = 'yes' or 'no' (default = 'no') +% cfg.parameter = string (default = 'powspctrm') +% +% Furthermore, the configuration should contain +% cfg.method = different methods for calculating the significance probability and/or critical value +% 'montecarlo' get Monte-Carlo estimates of the significance probabilities and/or critical values from the permutation distribution, +% 'analytic' get significance probabilities and/or critical values from the analytic reference distribution (typically, the sampling distribution under the null hypothesis), +% 'stats' use a parametric test from the Matlab statistics toolbox, +% 'glm' use a general linear model approach. +% +% The other cfg options depend on the method that you select. You +% should read the help of the respective subfunction STATISTICS_XXX +% for the corresponding configuration options and for a detailed +% explanation of each method. +% +% See also FT_FREQANALYSIS, FT_FREQDESCRIPTIVES, FT_FREQGRANDAVERAGE +% +% Undocumented local options: +% cfg.inputfile = one can specifiy preanalysed saved data as input +% The data should be provided in a cell array +% cfg.outputfile = one can specify output as file to save to disk -% this part is variable -prefix = 'ft_'; -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +% This function depends on FT_STATISTICS_WRAPPER +% +% TODO change cfg.frequency in all functions to cfg.foi or cfg.foilim + +% Copyright (C) 2005-2006, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_freqstatistics.m 1273 2010-06-25 15:40:16Z timeng $ + +fieldtripdefs + +% set the defaults +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +hasdata = nargin>1; + +if ~isempty(cfg.inputfile) % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + for i=1:numel(cfg.inputfile) + varargin{i} = loadvar(cfg.inputfile{i}, 'data'); % read datasets from array inputfile + end + end +end + +% check if the input data is valid for this function +for i=1:length(varargin) + % FIXME at this moment (=2 April) this does not work, because the input might not always have a powspctrm o.i.d. + % See email from Juriaan + % varargin{i} = checkdata(varargin{i}, 'datatype', 'freq', 'feedback', 'no'); +end + +% the low-level data selection function does not know how to deal with other parameters, so work around it +if isfield(cfg, 'parameter') && strcmp(cfg.parameter, 'powspctrm') + % use the power spectrum, this is the default + for i=1:length(varargin) + if isfield(varargin{i}, 'crsspctrm'), varargin{i} = rmfield(varargin{i}, 'crsspctrm'); end % remove to avoid confusion + if isfield(varargin{i}, 'cohspctrm'), varargin{i} = rmfield(varargin{i}, 'cohspctrm'); end % remove to avoid confusion + if isfield(varargin{i}, 'labelcmb'), varargin{i} = rmfield(varargin{i}, 'labelcmb'); end % remove to avoid confusion + end +elseif isfield(cfg, 'parameter') && strcmp(cfg.parameter, 'crsspctrm') + % use the cross spectrum, this might work as well (but has not been tested) +elseif isfield(cfg, 'parameter') && strcmp(cfg.parameter, 'cohspctrm') + % for testing coherence on group level: + % rename cohspctrm->powspctrm and labelcmb->label + for i=1:length(varargin) + dat = varargin{i}.cohspctrm; + labcmb = varargin{i}.labelcmb; + for j=1:size(labcmb) + lab{j,1} = sprintf('%s - %s', labcmb{j,1}, labcmb{j,2}); + end + varargin{i} = rmsubfield(varargin{i}, 'cohspctrm'); + varargin{i} = rmsubfield(varargin{i}, 'labelcmb'); + varargin{i} = setsubfield(varargin{i}, 'powspctrm', dat); + varargin{i} = setsubfield(varargin{i}, 'label', lab); + end +elseif isfield(cfg, 'parameter') + % rename the desired parameter to powspctrm + fprintf('renaming parameter ''%s'' into ''powspctrm''\n', cfg.parameter); + for i=1:length(varargin) + dat = getsubfield(varargin{i}, cfg.parameter); + varargin{i} = rmsubfield (varargin{i}, cfg.parameter); + varargin{i} = setsubfield(varargin{i}, 'powspctrm', dat); + end +end + +[status,output] = system('whoami'); +if isempty(strfind(output,'jan')), + % call the general function + [stat, cfg] = statistics_wrapper(cfg, varargin{:}); +else + % call the general function + [stat, cfg] = statistics_wrapperJM(cfg, varargin{:}); +end + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_freqstatistics.m 1273 2010-06-25 15:40:16Z timeng $'; + +% remember the configuration of the input data +cfg.previous = []; +for i=1:length(varargin) + if isfield(varargin{i}, 'cfg') + cfg.previous{i} = varargin{i}.cfg; + else + cfg.previous{i} = []; + end +end + +% remember the exact configuration details +stat.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', stat); % use the variable name "data" in the output file +end diff --git a/external/fieldtrip/ft_headmodelplot.m b/external/fieldtrip/ft_headmodelplot.m index b84b9b2..32f9946 100644 --- a/external/fieldtrip/ft_headmodelplot.m +++ b/external/fieldtrip/ft_headmodelplot.m @@ -1,11 +1,456 @@ -function varargout = funname(varargin); +function [cfg] = ft_headmodelplot(cfg, data) -% this is a SPM wrapper around a FieldTrip function +% FT_HEADMODELPLOT makes a 3D visualisation of the volume conductor model +% and optionally of the gradiometer positions and headshape. It can +% be used for example to check CTF multiple-sphere head models. +% +% Use as +% ft_headmodelplot(cfg) +% ft_headmodelplot(cfg, data) +% +% You should specify the volume conductor model with +% cfg.hdmfile = string, file containing the volume conduction model +% or alternatively +% cfg.vol = structure with volume conduction model +% +% If the sensor information is not contained in the data itself you should +% also specify the sensor information using +% cfg.gradfile = string, file containing the gradiometer definition +% cfg.elecfile = string, file containing the electrode definition +% or alternatively +% cfg.grad = structure with gradiometer definition +% cfg.elec = structure with electrode definition +% +% The positions of the sources can be specified as a regular 3-D +% grid that is aligned with the axes of the head coordinate system +% cfg.grid.xgrid = vector (e.g. -20:1:20) or 'auto' (default = 'auto') +% cfg.grid.ygrid = vector (e.g. -20:1:20) or 'auto' (default = 'auto') +% cfg.grid.zgrid = vector (e.g. 0:1:20) or 'auto' (default = 'auto') +% cfg.grid.resolution = number (e.g. 1 cm) for automatic grid generation +% Alternatively the position of a few sources at locations of interest can +% be specified, for example obtained from an anatomical or functional MRI +% cfg.grid.pos = Nx3 matrix with position of each source +% cfg.grid.dim = [Nx Ny Nz] vector with dimensions in case of 3-D grid (optional) +% cfg.grid.inside = vector with indices of the sources inside the brain (optional) +% cfg.grid.outside = vector with indices of the sources outside the brain (optional) +% You can also use the FT_PREPARE_LEADFIELD or FT_SOURCEANALYSIS functions +% to create a grid with dipole positions. +% +% Other options are +% cfg.channel = cell-array, see FT_CHANNELSELECTION +% cfg.spheremesh = number of vertices for spheres, either 42, 162 or 642 +% cfg.plotheadsurface = 'yes' or 'no', is constructed from head model +% cfg.plotbnd = 'yes' or 'no' +% cfg.plotspheres = 'yes' or 'no' +% cfg.plotspherecenter = 'yes' or 'no' +% cfg.plotgrid = 'yes' or 'no' +% cfg.plotinside = 'yes' or 'no' +% cfg.plotoutside = 'yes' or 'no' +% cfg.plotsensors = 'yes' or 'no' plot electrodes or gradiometers +% cfg.plotcoil = 'yes' or 'no' plot all gradiometer coils +% cfg.plotlines = 'yes' or 'no' plot lines from sensor to head surface +% cfg.surftype = 'edges'or 'faces' +% cfg.headshape = a filename containing headshape, a structure containing a +% single triangulated boundary, or a Nx3 matrix with surface +% points -% this part is variable -prefix = 'ft_'; +% Undocumented local options: +% cfg.surface_facecolor +% cfg.surface_edgecolor +% cfg.surface_facealpha +% cfg.inputfile = one can specifiy preanalysed saved data as input -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +% +% This function depends on FT_PREPARE_VOL_SENS which has the following options: +% cfg.channel, documented +% cfg.elec, documented +% cfg.elecfile, documented +% cfg.grad, documented +% cfg.gradfile, documented +% cfg.hdmfile, documented +% cfg.order +% cfg.vol, (default set in FT_HEADMODELPLOT at cfg.vol =[]), documented + +% Copyright (C) 2004-2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_headmodelplot.m 1427 2010-07-19 11:44:01Z vlalit $ + +fieldtripdefs + +% these are suitable RGB colors +skin = [255 213 119]/255; +skull = [140 85 85]/255; +brain = [202 100 100]/255; +cortex = [255 213 119]/255; + +% set the defaults +if ~isfield(cfg, 'surface_facecolor'), cfg.surface_facecolor = skin; end +if ~isfield(cfg, 'surface_edgecolor'), cfg.surface_edgecolor = 'none'; end +if ~isfield(cfg, 'surface_facealpha'), cfg.surface_facealpha = 0.7; end +if ~isfield(cfg, 'surftype'), cfg.surftype = 'faces'; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end + +hasdata = (nargin>1); + +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + end +elseif nargin<2 + data = []; +end + +% put the low-level options pertaining to the dipole grid in their own field +cfg = checkconfig(cfg, 'createsubcfg', {'grid'}); + +if ~isfield(cfg, 'vol') && ~isfield(cfg, 'hdmfile') + cfg.vol = []; % FIXME why is this empty setting neccessary? +end + +% set the defaults that apply both to EEG and MEG +if ~isfield(cfg, 'spheremesh'), cfg.spheremesh = 642; end +if ~isfield(cfg, 'plotsensors'), cfg.plotsensors = 'yes'; end +if ~isfield(cfg, 'plotheadsurface'), cfg.plotheadsurface = 'yes'; end +if ~isfield(cfg, 'plotgrid'), cfg.plotgrid = 'yes'; end +if ~isfield(cfg, 'plotinside'), cfg.plotinside = 'yes'; end +if ~isfield(cfg, 'plotoutside'), cfg.plotoutside = 'no'; end +if ~isfield(cfg, 'plotbnd'), cfg.plotbnd = 'no'; end +if ~isfield(cfg, 'plotfiducial'), cfg.plotfiducial = 'no'; end + +% extract/read the gradiometer and volume conductor +[vol, sens, cfg] = prepare_headmodel(cfg, data); + +if strcmp(cfg.plotgrid, 'yes') + if isfield(cfg.grid, 'pos') + % use the specified grid + sourcegrid.pos = cfg.grid.pos; + sourcegrid.inside = cfg.grid.inside; + sourcegrid.outside = cfg.grid.outside; + else + % construct the grid according to the configuration + sourcegrid = prepare_dipole_grid(cfg, vol, sens); + end +else + % construct an empty dipole grid + sourcegrid = []; + sourcegrid.pos = zeros(0,3); + sourcegrid.inside = []; + sourcegrid.outside = []; +end + +% determine the type of input data +ismeg = ft_senstype(sens, 'meg'); +iseeg = ft_senstype(sens, 'eeg'); +isbem = isfield(vol, 'bnd'); +issphere = isfield(vol, 'r'); +ismultisphere = isfield(vol, 'r') && length(vol.r)>4; +issinglesphere = isfield(vol, 'r') && length(vol.r)==1; +isconcentric = isfield(vol, 'r') && length(vol.r)<=4 && ~issinglesphere; + +if ismeg + % sensors describe MEG data, set the corresponding defaults + if ~isfield(cfg, 'plotspheres'), cfg.plotspheres = 'no'; end + if ~isfield(cfg, 'plotspherecenter'), cfg.plotspherecenter = 'no'; end + if ~isfield(cfg, 'plotlines'), cfg.plotlines = 'yes'; end + if ~isfield(cfg, 'plotcoil'), cfg.plotcoil = 'no'; end + if ~isfield(cfg, 'headshape'), cfg.headshape = []; end +elseif iseeg + % sensors describe EEG data, set the corresponding defaults + if ~isfield(cfg, 'plotspheres'), cfg.plotspheres = 'no'; end + if ~isfield(cfg, 'plotspherecenter'), cfg.plotspherecenter = 'no'; end + if ~isfield(cfg, 'plotlines'), cfg.plotlines = 'yes'; end +end + +chan = []; +[chan.pnt, chan.label] = channelposition(sens); + +if issphere + % determine the number of spheres in the volume model + Nspheres = length(vol.r); + fprintf('spherical head model with %d spheres\n', Nspheres); +end + +clf +hold on +axis equal +axis vis3d +if ismeg + axis off +else + axis on + grid on + xlabel('x') + ylabel('y') + zlabel('z') +end + +if iseeg + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % plotting for EEG + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + if strcmp(cfg.plotgrid, 'yes') + if strcmp(cfg.plotinside, 'yes') + plot3(sourcegrid.pos(sourcegrid.inside,1), sourcegrid.pos(sourcegrid.inside,2), sourcegrid.pos(sourcegrid.inside,3), 'k.'); + end + if strcmp(cfg.plotoutside, 'yes') + plot3(sourcegrid.pos(sourcegrid.outside,1), sourcegrid.pos(sourcegrid.outside,2), sourcegrid.pos(sourcegrid.outside,3), 'k.'); + end + end % plotgrid + + if strcmp(cfg.plotsensors, 'yes') + ft_plot_sens(sens, 'style', 'g*'); + end % plotsensors + + if strcmp(cfg.plotheadsurface, 'yes') && ~isempty(vol) + [pnt, tri] = headsurface(vol, sens); + h = triplot(pnt, tri, [], cfg.surftype); + set(h, 'edgecolor', cfg.surface_edgecolor); + if strcmp(cfg.surftype, 'faces') + set(h, 'facecolor', cfg.surface_facecolor); + set(h, 'facealpha', cfg.surface_facealpha); + end + end % plotheadsurface + + if strcmp(cfg.plotspheres, 'yes') && ~isempty(vol) && issphere + % create a triangulated unit sphere + if cfg.spheremesh==42 + [pnt0, tri] = icosahedron42; + elseif cfg.spheremesh==162 + [pnt0, tri] = icosahedron162; + elseif cfg.spheremesh==642 + [pnt0, tri] = icosahedron642; + end + Nvertices = size(pnt0,1); + + colors = {cortex, brain, skull, skin}; + + for i=1:Nspheres + % scale and shift the unit sphere to the proper location + pnt = pnt0*vol.r(i) + repmat(vol.o, Nvertices,1); + + h = triplot(pnt, tri, [], cfg.surftype); + % set(h, 'FaceVertexCData', 0.5*ones(length(distance),30)); + % set(h, 'FaceVertexCData', [0 0 1]); + set(h, 'edgecolor', colors{i}) + % set(h, 'edgealpha', 1) + if strcmp(cfg.surftype, 'faces') + % set(h, 'AlphaDataMapping', 'direct'); + set(h, 'facealpha', 'interp') + % set(h, 'facealpha', 0) + set(h, 'facecolor', 'none'); + % set(h, 'linestyle', 'none'); + end + end + end % plotspheres + + if strcmp(cfg.plotbnd, 'yes') && ~isempty(vol) && isbem + + Nbnd = numel(vol.bnd); + + colors = {skin, skull, brain}; + + for i=1:Nbnd + h = triplot(vol.bnd(i).pnt, vol.bnd(i).tri, [], cfg.surftype); + % set(h, 'FaceVertexCData', 0.5*ones(length(distance),30)); + % set(h, 'FaceVertexCData', [0 0 1]); + set(h, 'edgecolor', colors{i}) + % set(h, 'edgealpha', 1) + if strcmp(cfg.surftype, 'faces') + % set(h, 'AlphaDataMapping', 'direct'); + set(h, 'facealpha', 'interp') + % set(h, 'facealpha', 0) + set(h, 'facecolor', 'none'); + % set(h, 'linestyle', 'none'); + end + end + end % plotbnd + + if strcmp(cfg.plotlines, 'yes') && ~isempty(vol) + if isbem + % project the electrodes on the skin surface, on the nearest triangle + [el] = project_elec(sens.pnt, vol.bnd(vol.skin).pnt, vol.bnd(vol.skin).tri); + % this returns [tri, la, mu] + tri = el(:,1); + la = el(:,2); + mu = el(:,3); + for i=1:Nsensors + v1 = vol.bnd(vol.skin).pnt(vol.bnd(vol.skin).tri(tri(i),1),:); + v2 = vol.bnd(vol.skin).pnt(vol.bnd(vol.skin).tri(tri(i),2),:); + v3 = vol.bnd(vol.skin).pnt(vol.bnd(vol.skin).tri(tri(i),3),:); + prj(i,:) = routlm(v1, v2, v3, la(i), mu(i)); + end + elseif issphere + % project the electrodes onto the sphere surface, towards the origin + nrm = sqrt(sum(sens.pnt.^2,2)); + prj = vol.r(vol.skin) * sens.pnt ./ [nrm nrm nrm]; + else + % in case that no known volume conductor is specified + prj = sens.pnt; + end + x = [sens.pnt(:,1) prj(:,1)]'; + y = [sens.pnt(:,2) prj(:,2)]'; + z = [sens.pnt(:,3) prj(:,3)]'; + line(x, y, z, 'color', 'm'); + end % plotlines + +elseif ismeg + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % plotting for MEG + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + if strcmp(cfg.plotgrid, 'yes') + if strcmp(cfg.plotinside, 'yes') + plot3(sourcegrid.pos(sourcegrid.inside,1), sourcegrid.pos(sourcegrid.inside,2), sourcegrid.pos(sourcegrid.inside,3), 'k.'); + end + if strcmp(cfg.plotoutside, 'yes') + plot3(sourcegrid.pos(sourcegrid.outside,1), sourcegrid.pos(sourcegrid.outside,2), sourcegrid.pos(sourcegrid.outside,3), 'k.'); + end + end % plotgrid + + if strcmp(cfg.plotsensors, 'yes') + ft_plot_sens(sens, 'style', 'g*'); + end % plotsensors + + if strcmp(cfg.plotcoil, 'yes') + pnt = sens.pnt; + ori = sens.ori; + x = [pnt(:,1) pnt(:,1)+ori(:,1)]'; + y = [pnt(:,2) pnt(:,2)+ori(:,2)]'; + z = [pnt(:,3) pnt(:,3)+ori(:,3)]'; + line(x, y, z, 'color', 'g'); + plot3(pnt(:,1), pnt(:,2), pnt(:,3), 'g.'); + end % plotsensors + + if ~isempty(cfg.headshape) + % get the surface describing the head shape + if isstruct(cfg.headshape) && isfield(cfg.headshape, 'pnt') + % use the headshape surface specified in the configuration + headshape.pnt = cfg.headshape.pnt; + elseif isnumeric(cfg.headshape) && size(cfg.headshape,2)==3 + % use the headshape points specified in the configuration + headshape.pnt = cfg.headshape; + elseif ischar(cfg.headshape) + % read the headshape from file + headshape = ft_read_headshape(cfg.headshape); + else + error('cfg.headshape is not specified correctly') + end + headshape.pnt = unique(headshape.pnt, 'rows'); + % the triangulation is not used inside this function + if isfield(headshape, 'tri') + headshape = rmfield(headshape, 'tri'); + end + plot3(headshape.pnt(:,1), headshape.pnt(:,2), headshape.pnt(:,3), 'r.'); + end % plotheadshape + + if strcmp(cfg.plotspheres, 'yes') && ~isempty(vol) && issphere + % create a triangulated unit sphere + if cfg.spheremesh==42 + [pnt0, tri] = icosahedron42; + elseif cfg.spheremesh==162 + [pnt0, tri] = icosahedron162; + elseif cfg.spheremesh==642 + [pnt0, tri] = icosahedron642; + end + Nvertices = size(pnt0,1); + for i=1:Nspheres + % scale and shift the unit sphere to the proper location + pnt = pnt0*vol.r(i) + repmat(vol.o(i,:),Nvertices,1); + if Nspheres>4 + distance = sqrt(sum((pnt - repmat(sens.pnt(i,:),Nvertices,1)).^2, 2)); + distance = (distance-min(distance))/range(distance); + else + distance = zeros(Nvertices, 1); + end + h = triplot(pnt, tri, [], cfg.surftype); + % set(h, 'FaceVertexCData', 0.5*ones(length(distance),30)); + % set(h, 'FaceVertexCData', [0 0 1]); + if strcmp(cfg.surftype, 'faces') + set(h, 'edgealpha', 'interp') + % set(h, 'edgealpha', 1) + set(h, 'FaceVertexAlphaData', (1-distance).*(distance<0.1)); + % set(h, 'AlphaDataMapping', 'direct'); + set(h, 'facealpha', 'interp') + % set(h, 'facealpha', 0) + set(h, 'facecolor', 'none'); + % set(h, 'linestyle', 'none'); + end + end + end % plotspheres + + if strcmp(cfg.plotbnd, 'yes') && ~isempty(vol) && isbem + + h = triplot(vol.bnd.pnt, vol.bnd.tri, [], cfg.surftype); + % set(h, 'FaceVertexCData', 0.5*ones(length(distance),30)); + % set(h, 'FaceVertexCData', [0 0 1]); + set(h, 'edgecolor', brain) + % set(h, 'edgealpha', 1) + if strcmp(cfg.surftype, 'faces') + % set(h, 'AlphaDataMapping', 'direct'); + set(h, 'facealpha', 'interp') + % set(h, 'facealpha', 0) + set(h, 'facecolor', 'none'); + % set(h, 'linestyle', 'none'); + end + + end % plotbnd + + if strcmp(cfg.plotspherecenter, 'yes') && ~isempty(vol) && issphere + plot3(vol.o(:,1), vol.o(:,2), vol.o(:,3), 'k.'); + end % plotspherecenter + + if strcmp(cfg.plotheadsurface, 'yes') && ~isempty(vol) + % estimate the head surface from the spheres and gradiometers + [pnt, tri] = headsurface(vol, sens); + h = triplot(pnt, tri, [], cfg.surftype); + set(h, 'edgecolor', cfg.surface_edgecolor); + if strcmp(cfg.surftype, 'faces') + set(h, 'facecolor', cfg.surface_facecolor); + set(h, 'facealpha', cfg.surface_facealpha); + end + end % plotheadsurface + + if strcmp(cfg.plotlines, 'yes') && ismultisphere + % first determine the indices of the relevant gradiometers. + [sel_g, sel_v] = match_str(chan.label, vol.label); + % create head-surface points from multisphere head-model. + dir = chan.pnt(sel_g,:) - vol.o(sel_v,:); + dist = sqrt(sum(dir.*dir,2)); + pnt0 = repmat((vol.r(sel_v)./dist),1,3).*dir + vol.o(sel_v,:); + pnt1 = chan.pnt(sel_g,:); + x = [pnt0(:,1) pnt1(:,1)]'; + y = [pnt0(:,2) pnt1(:,2)]'; + z = [pnt0(:,3) pnt1(:,3)]'; + line(x, y, z, 'color', 'm'); + end % plotlines + + if strcmp(cfg.plotfiducial, 'yes') && ~isempty(cfg.fiducial), + fiduc = cfg.fiducial; + plot3(fiduc(:,1), fiduc(:,2), fiduc(:,3), 'mo', 'lineWidth', 4); + end + +end % iseeg or ismeg + +lighting gouraud +camlight +hold off diff --git a/external/fieldtrip/ft_headmovement.m b/external/fieldtrip/ft_headmovement.m deleted file mode 100644 index b84b9b2..0000000 --- a/external/fieldtrip/ft_headmovement.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'ft_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_interactiverealign.m b/external/fieldtrip/ft_interactiverealign.m index b84b9b2..be826f8 100644 --- a/external/fieldtrip/ft_interactiverealign.m +++ b/external/fieldtrip/ft_interactiverealign.m @@ -1,11 +1,447 @@ -function varargout = funname(varargin); +function cfg = ft_interactiverealign(cfg) -% this is a SPM wrapper around a FieldTrip function +% FT_INTERACTIVEREALIGN interactively rotates, scales and translates +% electrode positions to template electrode positions or towards +% the head surface. +% +% Use as +% [cfg] = ft_interactiverealign(cfg) +% +% Required configuration options: +% cfg.individual.vol +% cfg.individual.elec +% cfg.individual.grad +% cfg.individual.headshape +% cfg.individual.headshapestyle = 'vertex' (default), 'surface' or 'both' +% cfg.individual.volstyle = 'edge' (default), 'surface' or 'both' +% +% cfg.template.vol +% cfg.template.elec +% cfg.template.grad +% cfg.template.headshape +% cfg.template.headshapestyle = 'surface' (default), 'vertex' or 'both' +% cfg.individual.volstyle = 'surface' (default), 'edge' or 'both' +% +% See also FT_VOLUMEREALIGN, FT_ELECTRODEREALIGN, FT_READ_SENS, FT_READ_VOL, FT_READ_HEADSHAPE -% this part is variable -prefix = 'ft_'; +% Copyright (C) 2008, Vladimir Litvak +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_interactiverealign.m 948 2010-04-21 18:02:21Z roboos $ + +fieldtripdefs + +% check if the input cfg is valid for this function +cfg = checkconfig(cfg, 'trackconfig', 'on'); +cfg = checkconfig(cfg, 'required', {'individual', 'template'}); + +if ~isfield(cfg.individual, 'vol'), cfg.individual.vol = []; end +if ~isfield(cfg.individual, 'elec'), cfg.individual.elec = []; end +if ~isfield(cfg.individual, 'grad'), cfg.individual.grad = []; end +if ~isfield(cfg.individual, 'headshape'), cfg.individual.headshape = []; end +if ~isfield(cfg.individual, 'headshapestyle'), cfg.individual.headshapestyle = 'vertex'; end +if ~isfield(cfg.individual, 'volstyle'), cfg.individual.volstyle = 'edge'; end + +if ~isfield(cfg.template, 'vol'), cfg.template.vol = []; end +if ~isfield(cfg.template, 'elec'), cfg.template.elec = []; end +if ~isfield(cfg.template, 'grad'), cfg.template.grad = []; end +if ~isfield(cfg.template, 'headshape'), cfg.template.headshape = []; end +if ~isfield(cfg.template, 'headshapestyle'), cfg.template.headshapestyle = 'surface'; end +if ~isfield(cfg.template, 'volstyle'), cfg.template.volstyle = 'surface'; end + +template = cfg.template; +individual = cfg.individual; + +if ~isempty(template.headshape) + if ~isfield(template.headshape, 'tri') || isempty(template.headshape.tri) + template.headshape.tri = projecttri(template.headshape.pnt); + end +end + +if ~isempty(individual.headshape) && isfield(individual.headshape, 'pnt') && ... + ~isempty(individual.headshape.pnt) + if ~isfield(individual.headshape, 'tri') || isempty(individual.headshape.tri) + individual.headshape.tri = projecttri(individual.headshape.pnt); + end +end + +% open a figure +fig = figure; +% add the data to the figure +set(fig, 'CloseRequestFcn', @cb_close); +setappdata(fig, 'individual', individual); +setappdata(fig, 'template', template); +setappdata(fig, 'transform', eye(4)); + +% add the GUI elements +cb_creategui(gca); +cb_redraw(gca); +rotate3d on +waitfor(fig); + +% get the data from the figure that was left behind as global variable +% FIXME pass this as appdata +global norm +tmp = norm; +clear global norm +norm = tmp; +clear tmp + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_interactiverealign.m 948 2010-04-21 18:02:21Z roboos $'; + +% remember the transform +cfg.m = norm.m; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% some simple SUBFUNCTIONs that facilitate 3D plotting +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function h = my_plot3(xyz, varargin) +h = plot3(xyz(:,1), xyz(:,2), xyz(:,3), varargin{:}); +function h = my_text3(xyz, varargin) +h = text(xyz(:,1), xyz(:,2), xyz(:,3), varargin{:}); +function my_line3(xyzB, xyzE, varargin) +for i=1:size(xyzB,1) + line([xyzB(i,1) xyzE(i,1)], [xyzB(i,2) xyzE(i,2)], [xyzB(i,3) xyzE(i,3)], varargin{:}) +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION to layout a moderately complex graphical user interface +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function h = layoutgui(fig, geometry, position, style, string, value, tag, callback); +horipos = geometry(1); % lower left corner of the GUI part in the figure +vertpos = geometry(2); % lower left corner of the GUI part in the figure +width = geometry(3); % width of the GUI part in the figure +height = geometry(4); % height of the GUI part in the figure +horidist = 0.05; +vertdist = 0.05; +options = {'units', 'normalized', 'HorizontalAlignment', 'center'}; % 'VerticalAlignment', 'middle' +Nrow = size(position,1); +h = cell(Nrow,1); +for i=1:Nrow + if isempty(position{i}) + continue; + end + position{i} = position{i} ./ sum(position{i}); + Ncol = size(position{i},2); + ybeg = (Nrow-i )/Nrow + vertdist/2; + yend = (Nrow-i+1)/Nrow - vertdist/2; + for j=1:Ncol + xbeg = sum(position{i}(1:(j-1))) + horidist/2; + xend = sum(position{i}(1:(j ))) - horidist/2; + pos(1) = xbeg*width + horipos; + pos(2) = ybeg*height + vertpos; + pos(3) = (xend-xbeg)*width; + pos(4) = (yend-ybeg)*height; + h{i}{j} = uicontrol(fig, ... + options{:}, ... + 'position', pos, ... + 'style', style{i}{j}, ... + 'string', string{i}{j}, ... + 'tag', tag{i}{j}, ... + 'value', value{i}{j}, ... + 'callback', callback{i}{j} ... + ); + end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function cb_creategui(hObject, eventdata, handles); +% define the position of each GUI element +position = { + [2 1 1 1] + [2 1 1 1] + [2 1 1 1] + [1] + [1] + [1] + [1] + [1 1] + }; + +% define the style of each GUI element +style = { + {'text' 'edit' 'edit' 'edit'} + {'text' 'edit' 'edit' 'edit'} + {'text' 'edit' 'edit' 'edit'} + {'pushbutton'} + {'pushbutton'} + {'toggle'} + {'toggle'} + {'text' 'edit'} + }; + +% define the descriptive string of each GUI element +string = { + {'rotate' 0 0 0} + {'translate' 0 0 0} + {'scale' 1 1 1} + {'redisplay'} + {'apply'} + {'toggle grid'} + {'toggle axes'} + {'alpha' 0.7} + }; + +% define the value of each GUI element +value = { + {[] [] [] []} + {[] [] [] []} + {[] [] [] []} + {[]} + {[]} + {0} + {0} + {[] []} + }; + +% define a tag for each GUI element +tag = { + {'' 'rx' 'ry' 'rz'} + {'' 'tx' 'ty' 'tz'} + {'' 'sx' 'sy' 'sz'} + {''} + {''} + {'toggle grid'} + {'toggle axes'} + {'' 'alpha'} + }; + +% define the callback function of each GUI element +callback = { + {[] @cb_redraw @cb_redraw @cb_redraw} + {[] @cb_redraw @cb_redraw @cb_redraw} + {[] @cb_redraw @cb_redraw @cb_redraw} + {@cb_redraw} + {@cb_apply} + {@cb_redraw} + {@cb_redraw} + {[] @cb_redraw} + }; + +fig = get(hObject, 'parent'); +layoutgui(fig, [0.7 0.05 0.25 0.50], position, style, string, value, tag, callback); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function cb_redraw(hObject, eventdata, handles) +fig = get(hObject, 'parent'); +individual = getappdata(fig, 'individual'); +template = getappdata(fig, 'template'); +% get the transformation details +rx = str2num(get(findobj(fig, 'tag', 'rx'), 'string')); +ry = str2num(get(findobj(fig, 'tag', 'ry'), 'string')); +rz = str2num(get(findobj(fig, 'tag', 'rz'), 'string')); +tx = str2num(get(findobj(fig, 'tag', 'tx'), 'string')); +ty = str2num(get(findobj(fig, 'tag', 'ty'), 'string')); +tz = str2num(get(findobj(fig, 'tag', 'tz'), 'string')); +sx = str2num(get(findobj(fig, 'tag', 'sx'), 'string')); +sy = str2num(get(findobj(fig, 'tag', 'sy'), 'string')); +sz = str2num(get(findobj(fig, 'tag', 'sz'), 'string')); +R = rotate ([rx ry rz]); +T = translate([tx ty tz]); +S = scale ([sx sy sz]); +H = S * T * R; +axis vis3d; cla +xlabel('x') +ylabel('y') +zlabel('z') + +hold on + +% the "individual" struct is a local copy, so it is safe to change it here +if ~isempty(individual.vol) + individual.vol = ft_transform_vol(H, individual.vol); +end +if ~isempty(individual.elec) + individual.elec = ft_transform_sens(H, individual.elec); +end +if ~isempty(individual.grad) + individual.grad = ft_transform_sens(H, individual.grad); +end +if ~isempty(individual.headshape) + individual.headshape = ft_transform_headshape(H, individual.headshape); +end + +if ~isempty(template.elec) + hs = triplot(template.elec.pnt, [], [], 'nodes'); + set(hs, 'MarkerSize', 10); + set(hs, 'Color', 'b'); + if isfield(template.elec, 'line') + hs = triplot(template.elec.pnt, template.elec.line, [], 'edges'); + try, set(hs, 'MarkerEdgeColor', 'b'); end + end +end + +if ~isempty(individual.elec) + hs = triplot(individual.elec.pnt, [], [], 'nodes'); + set(hs, 'MarkerSize', 10); + set(hs, 'Color', 'r'); + if isfield(individual.elec, 'line') + hs = triplot(individual.elec.pnt, elec.line, [], 'edges'); + try, set(hs, 'MarkerEdgeColor', 'r'); end + end +end + +if ~isempty(template.grad) + hs = triplot(template.grad.pnt, [], [], 'nodes'); + set(hs, 'MarkerSize', 10); + set(hs, 'Color', 'b'); + % FIXME also plot lines? +end + +if ~isempty(individual.grad) + hs = triplot(individual.grad.pnt, [], [], 'nodes'); + set(hs, 'MarkerSize', 10); + set(hs, 'Color', 'r'); + % FIXME also plot lines? +end + +if ~isempty(template.vol) + % FIXME this only works for boundary element models + for i = 1:numel(template.vol.bnd) + if strcmp(template.volstyle, 'edge') || ... + strcmp(template.volstyle, 'both') + hs = triplot(template.vol.bnd(i).pnt, template.vol.bnd(i).tri, [], 'edges'); + try, set(hs, 'EdgeColor', 'b'); end + end + if strcmp(template.volstyle, 'surface') || ... + strcmp(template.volstyle, 'both') + hs = triplot(template.vol.bnd(i).pnt, template.vol.bnd(i).tri, [], 'faces_blue'); + + end + end +end + +if ~isempty(individual.vol) + % FIXME this only works for boundary element models + for i = 1:numel(individual.vol.bnd) + if strcmp(individual.volstyle, 'edge') || ... + strcmp(individual.volstyle, 'both') + hs = triplot(individual.vol.bnd(i).pnt, individual.vol.bnd(i).tri, [], 'edges'); + try, set(hs, 'EdgeColor', 'r'); end + end + if strcmp(individual.volstyle, 'surface') || ... + strcmp(individual.volstyle, 'both') + hs = triplot(individual.vol.bnd(i).pnt, individual.vol.bnd(i).tri, [], 'faces_red'); + end + end +end + +if ~isempty(template.headshape) + if isfield(template.headshape, 'pnt') && ~isempty(template.headshape.pnt) + if strcmp(template.headshapestyle, 'surface') || ... + strcmp(template.headshapestyle, 'both') + triplot(template.headshape.pnt, template.headshape.tri, [], 'faces_blue'); + alpha(str2num(get(findobj(fig, 'tag', 'alpha'), 'string'))); + end + + if strcmp(template.headshapestyle, 'vertex') || ... + strcmp(template.headshapestyle, 'both') + hs = triplot(template.headshape.pnt, [], [], 'nodes'); + set(hs, 'Color', 'b'); + end + end + if isfield(template.headshape, 'fid') && ~isempty(template.headshape.fid.pnt) + triplot(template.headshape.fid.pnt, [], [], 'nodes_blue'); + end +end + +if ~isempty(individual.headshape) + if isfield(individual.headshape, 'pnt') && ~isempty(individual.headshape.pnt) + if strcmp(individual.headshapestyle, 'surface') || ... + strcmp(individual.headshapestyle, 'both') + triplot(individual.headshape.pnt, individual.headshape.tri, [], 'faces_red'); + alpha(str2num(get(findobj(fig, 'tag', 'alpha'), 'string'))); + end + + if strcmp(individual.headshapestyle, 'vertex') || ... + strcmp(individual.headshapestyle, 'both') + hs = triplot(individual.headshape.pnt, [], [], 'nodes'); + set(hs, 'Color', 'r'); + end + end + if isfield(individual.headshape, 'fid') && ~isempty(individual.headshape.fid.pnt) + triplot(individual.headshape.fid.pnt, [], [], 'nodes_red'); + end +end + +if get(findobj(fig, 'tag', 'toggle axes'), 'value') + axis on +else + axis off +end +if get(findobj(fig, 'tag', 'toggle grid'), 'value') + grid on +else + grid off +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function cb_apply(hObject, eventdata, handles); +fig = get(hObject, 'parent'); +transform = getappdata(fig, 'transform'); +% get the transformation details +rx = str2num(get(findobj(fig, 'tag', 'rx'), 'string')); +ry = str2num(get(findobj(fig, 'tag', 'ry'), 'string')); +rz = str2num(get(findobj(fig, 'tag', 'rz'), 'string')); +tx = str2num(get(findobj(fig, 'tag', 'tx'), 'string')); +ty = str2num(get(findobj(fig, 'tag', 'ty'), 'string')); +tz = str2num(get(findobj(fig, 'tag', 'tz'), 'string')); +sx = str2num(get(findobj(fig, 'tag', 'sx'), 'string')); +sy = str2num(get(findobj(fig, 'tag', 'sy'), 'string')); +sz = str2num(get(findobj(fig, 'tag', 'sz'), 'string')); +R = rotate ([rx ry rz]); +T = translate([tx ty tz]); +S = scale ([sx sy sz]); +H = S * T * R; +transform = H * transform; +set(findobj(fig, 'tag', 'rx'), 'string', 0); +set(findobj(fig, 'tag', 'ry'), 'string', 0); +set(findobj(fig, 'tag', 'rz'), 'string', 0); +set(findobj(fig, 'tag', 'tx'), 'string', 0); +set(findobj(fig, 'tag', 'ty'), 'string', 0); +set(findobj(fig, 'tag', 'tz'), 'string', 0); +set(findobj(fig, 'tag', 'sx'), 'string', 1); +set(findobj(fig, 'tag', 'sy'), 'string', 1); +set(findobj(fig, 'tag', 'sz'), 'string', 1); +setappdata(fig, 'transform', transform); +cb_redraw(hObject); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function cb_close(hObject, eventdata, handles); +% make the current transformation permanent and subsequently allow deleting the figure +cb_apply(gca); +% get the updated electrode from the figure +fig = hObject; +% hmmm, this is ugly +global norm +norm.m = getappdata(fig, 'transform'); +set(fig, 'CloseRequestFcn', @delete); +delete(fig); -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_lateralizedfield.m b/external/fieldtrip/ft_lateralizedfield.m deleted file mode 100644 index b84b9b2..0000000 --- a/external/fieldtrip/ft_lateralizedfield.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'ft_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_lateralizedpotential.m b/external/fieldtrip/ft_lateralizedpotential.m index b84b9b2..73beeb3 100644 --- a/external/fieldtrip/ft_lateralizedpotential.m +++ b/external/fieldtrip/ft_lateralizedpotential.m @@ -1,11 +1,139 @@ -function varargout = funname(varargin); +function lrp = ft_lateralizedpotential(cfg, avgL, avgR); -% this is a SPM wrapper around a FieldTrip function +% FT_LATERALIZEDPOTENTIAL computes lateralized potentials such as the LRP +% +% Use as +% [lrp] = ft_lateralizedpotential(cfg, avgL, avgR) +% +% where the input datasets should come from FT_TIMELOCKANALYSIS +% and the configuration should contain +% cfg.channelcmb = Nx2 cell array +% +% An example channelcombination containing the homologous channels +% in the 10-20 standard system is +% cfg.channelcmb = {'Fp1' 'Fp2' +% 'F7' 'F8' +% 'F3' 'F4' +% 'T7' 'T8' +% 'C3' 'C4' +% 'P7' 'P8' +% 'P3' 'P4' +% 'O1' 'O2'} +% +% The lateralized potential is computed on combinations of channels and +% not on indivudual channels. However, if you want to make a topographic +% plot with e.g. FT_MULTIPLOTER, you can replace the output lrp.label +% with lrp.plotlabel. +% +% The concept for the LRP was introduced approximately simultaneously in the +% following two papers +% - M. G. H. Coles. Modern mind-brain reading - psychophysiology, +% physiology, and cognition. Psychophysiology, 26(3):251-269, 1988. +% - R. de Jong, M. Wierda, G. Mulder, and L. J. Mulder. Use of +% partial stimulus information in response processing. J Exp Psychol +% Hum Percept Perform, 14:682-692, 1988. +% and it is discussed in detail on a technical level in +% - R. Oostenveld, D.F. Stegeman, P. Praamstra and A. van Oosterom. +% Brain symmetry and topographic analysis of lateralized event-related +% potentials. Clin Neurophysiol. 114(7):1194-202, 2003. +% +% See also FT_LATERALIZEDFIELD, FT_TIMELOCKANALYSIS, FT_MULTIPLOTER -% this part is variable -prefix = 'ft_'; +% Copyright (C) 2004, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_lateralizedpotential.m 1264 2010-06-24 11:40:55Z timeng $ -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +fieldtripdefs + +% set the defaults +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +hasdata = nargin>1; +if ~isempty(cfg.inputfile) % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + avgL=loadvar(cfg.inputfile{1}, 'data'); % read first element as avgL from array inputfile + avgR=loadvar(cfg.inputfile{2}, 'data'); % read second element as avgR from array inputfile + end +end + +if ~isfield(cfg, 'channelcmb'), + cfg.channelcmb = { + 'Fp1' 'Fp2' + 'F7' 'F8' + 'F3' 'F4' + 'T7' 'T8' + 'C3' 'C4' + 'P7' 'P8' + 'P3' 'P4' + 'O1' 'O2' + }; +end + +if ~all(avgL.time==avgR.time) + error('timeaxes are not the same'); +end + +% start with an empty output structure +lrp.label = {}; +lrp.plotlabel = {}; +lrp.avg = []; +lrp.time = avgL.time; + +% compute the lateralized potentials +Nchan = size(cfg.channelcmb); +for i=1:Nchan + C3R = strmatch(cfg.channelcmb{i,1}, avgR.label); + C4R = strmatch(cfg.channelcmb{i,2}, avgR.label); + C3L = strmatch(cfg.channelcmb{i,1}, avgL.label); + C4L = strmatch(cfg.channelcmb{i,2}, avgL.label); + if ~isempty(C3R) && ~isempty(C4R) && ~isempty(C3L) && ~isempty(C4L) + lrp.label{end+1} = sprintf('%s/%s', cfg.channelcmb{i,1}, cfg.channelcmb{i,2}); + lrp.plotlabel{end+1} = cfg.channelcmb{i,1}; + erpC3L = avgL.avg(C3L,:); + erpC4L = avgL.avg(C4L,:); + erpC3R = avgR.avg(C3R,:); + erpC4R = avgR.avg(C4R,:); + lrp.avg(end+1,:) = 1/2 * ((erpC3R - erpC4R) + (erpC4L - erpC3L)); + end +end + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_lateralizedpotential.m 1264 2010-06-24 11:40:55Z timeng $'; +% remember the configuration details of the input data +cfg.previous = []; +try, cfg.previous{1} = avgL.cfg; end +try, cfg.previous{2} = avgR.cfg; end +% remember the exact configuration details in the output +lrp.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', lrp); % use the variable name "data" in the output file +end diff --git a/external/fieldtrip/ft_layoutplot.m b/external/fieldtrip/ft_layoutplot.m index b84b9b2..31fc02d 100644 --- a/external/fieldtrip/ft_layoutplot.m +++ b/external/fieldtrip/ft_layoutplot.m @@ -1,11 +1,171 @@ -function varargout = funname(varargin); +function ft_layoutplot(cfg, data) -% this is a SPM wrapper around a FieldTrip function +% FT_LAYOUTPLOT makes a figure with the 2-D layout of the channel positions +% for topoplotting and the individual channel axes (i.e. width and height +% of the subfigures) for multiplotting. A correct 2-D layout is a +% prerequisite for plotting the topographical distribution of the +% potential or field distribution, or for plotting timecourses in a +% topographical arrangement. +% +% This function uses the same configuration options as prepare_layout and +% as the topoplotting and multiplotting functions. The difference is that +% this function plots the layout without any data, which facilitates +% the validation of your 2-D layout. +% +% Use as +% ft_layoutplot(cfg, data) +% +% There are several ways in which a 2-D layout can be made: it can be read +% directly from a *.lay file, it can be created based on 3-D electrode or +% gradiometer positions in the configuration or in the data, or it can be +% created based on the specification of an electrode of gradiometer file. +% +% You can specify either one of the following configuration options +% cfg.layout filename containg the layout +% cfg.rotate number, rotation around the z-axis in degrees (default = [], which means automatic) +% cfg.projection string, 2D projection method can be 'stereographic', 'ortographic', 'polar', 'gnomic' or 'inverse' (default = 'orthographic') +% cfg.elec structure with electrode positions, or +% cfg.elecfile filename containing electrode positions +% cfg.grad structure with gradiometer definition, or +% cfg.gradfile filename containing gradiometer definition +% cfg.output filename to which the layout will be written (default = []) +% cfg.montage 'no' or a montage structure (default = 'no') +% cfg.image filename, use an image to construct a layout (e.g. usefull for ECoG grids) +% +% Alternatively the layout can be constructed from either +% data.elec structure with electrode positions +% data.grad structure with gradiometer definition +% +% Alternatively, you can specify +% cfg.layout = 'ordered' +% which will give you a 2-D ordered layout. Note that this is only suited +% for multiplotting and not for topoplotting. +% +% See also ft_prepare_layout, ft_topoplotER, ft_topoplotTFR, ft_multiplotER, ft_multiplotTFR + +% Undocumented options +% cfg.montage + +% Copyright (C) 2006-2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_layoutplot.m 1430 2010-07-20 07:41:41Z roboos $ + +fieldtripdefs + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% basic check/initialization of input arguments +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +if (nargin<1) || (nargin>2), error('incorrect number of input arguments'); end; + +% defaults for input +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end + +% load optional given inputfile as data +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + end + elseif (nargin<2), + data = []; +end + +if ~isstruct(cfg) && ~isempty(cfg), error('argument cfg must be a structure'); end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% extract/generate layout information +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +lay = []; + +% try to use the layout structure from input if specified +if isfield(cfg, 'layout') + % brief check to determine if cfg.layout is a valid layout (lay) structre + if isstruct(cfg.layout) + if all(isfield(cfg.layout, {'pos';'width';'height';'label'})) + lay = cfg.layout; + end + end +end + +% otherwise create the layout structure +if isempty(lay), lay = ft_prepare_layout(cfg, data); end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% plot all details pertaining to the layout in one figure +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +figure + +if isfield(cfg, 'image') && ~isempty(cfg.image) + % start with the background image + fprintf('reading background image from %s\n', cfg.image); + img = imread(cfg.image); + img = flipdim(img, 1); % in combination with "axis xy" + + bw = 1; + + if bw + % convert to greyscale image + img = mean(img, 3); + imagesc(img); + colormap gray + else + % plot as RGB image + image(img); + end + axis equal + axis off + axis xy +end + +ft_plot_lay(lay, 'point', true, 'box', true, 'label', true, 'mask', true, 'outline', true); + +% the following code can be used to verify a bipolar montage, given the +% layout of the monopolar channels +if isfield(cfg, 'montage') && ~isempty(cfg.montage) + fprintf('plotting an arrow for each of the bipolar electrode pairs\n'); + % the arrow begins at the +1 electrode + % the arrow ends at the -1 electrode + for i=1:length(cfg.montage.labelnew) + begindx = find(cfg.montage.tra(i,:)==+1); + endindx = find(cfg.montage.tra(i,:)==-1); + if ~numel(begindx)==1 || ~numel(endindx)==1 + % the re-referenced channel does not seem to be a bipolar pair + continue + end + % find the position of the begin and end of the arrow + beglab = cfg.montage.labelorg{begindx}; + endlab = cfg.montage.labelorg{endindx}; + begindx = find(strcmp(lay.label, beglab)); % the index in the layout + endindx = find(strcmp(lay.label, endlab)); % the index in the layout + if ~numel(begindx)==1 || ~numel(endindx)==1 + % one of the channels in the bipolar pair does not seem to be in the layout + continue + end + + begpos = lay.pos(begindx,:); + endpos = lay.pos(endindx,:); + arrow(begpos, endpos, 'Length', 5) + + end % for all re-referenced channels +end % if montage -% this part is variable -prefix = 'ft_'; -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_megplanar.m b/external/fieldtrip/ft_megplanar.m index b84b9b2..c80f230 100644 --- a/external/fieldtrip/ft_megplanar.m +++ b/external/fieldtrip/ft_megplanar.m @@ -1,11 +1,323 @@ -function varargout = funname(varargin); +function [interp] = ft_megplanar(cfg, data) -% this is a SPM wrapper around a FieldTrip function +% FT_MEGPLANAR computes planar MEG gradients gradients for raw data +% obtained from FT_PREPROCESSING or an average ERF that was computed using +% FT_TIMELOCKANALYSIS. It can also work on data in the frequency domain, +% obtained with FREQANALYSIS. Prerequisite for this is that the data contain +% complex-valued fourierspectra. +% +% Use as +% [interp] = ft_megplanar(cfg, data) +% +% The configuration should contain +% cfg.planarmethod = 'orig' | 'sincos' | 'fitplane' | 'sourceproject' +% cfg.channel = Nx1 cell-array with selection of channels (default = 'MEG'), +% see FT_CHANNELSELECTION for details +% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') +% +% The methods orig, sincos and fitplane are all based on a neighbourhood +% interpolation. For these methods you can specify +% cfg.neighbourdist = default is 4 cm +% +% In the 'sourceproject' method a minumum current estimate is done using a +% large number of dipoles that are placed in the upper layer of the brain +% surface, followed by a forward computation towards a planar gradiometer +% array. This requires the specification of a volume conduction model of +% the head and of a source model. The 'sourceproject' method is not supported for +% frequency domain data. +% +% A head model must be specified with +% cfg.hdmfile = string, file containing the volume conduction model +% or alternatively manually using +% cfg.vol.r = radius of sphere +% cfg.vol.o = [x, y, z] position of origin +% +% A dipole layer representing the brain surface must be specified with +% cfg.inwardshift = depth of the source layer relative to the head model surface (default = 2.5, which is adequate for a skin-based head model) +% cfg.spheremesh = number of dipoles in the source layer (default = 642) +% cfg.pruneratio = for singular values, default is 1e-3 +% cfg.headshape = a filename containing headshape, a structure containing a +% single triangulated boundary, or a Nx3 matrix with surface +% points +% If no headshape is specified, the dipole layer will be based on the inner compartment +% of the volume conduction model. +% +% See also FT_COMBINEPLANAR +% +% Undocumented local options: +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk -% this part is variable -prefix = 'ft_'; +% This function depends on FT_PREPARE_BRAIN_SURFACE which has the following options: +% cfg.headshape (default set in FT_MEGPLANAR: cfg.headshape = 'headmodel'), documented +% cfg.inwardshift (default set in FT_MEGPLANAR: cfg.inwardshift = 2.5), documented +% cfg.spheremesh (default set in FT_MEGPLANAR: cfg.spheremesh = 642), documented +% +% This function depends on FT_PREPARE_VOL_SENS which has the following options: +% cfg.channel +% cfg.elec +% cfg.elecfile +% cfg.grad +% cfg.gradfile +% cfg.hdmfile, documented +% cfg.order +% cfg.vol, documented -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +% Copyright (C) 2004, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_megplanar.m 1401 2010-07-12 18:52:40Z jansch $ + +fieldtripdefs + +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +% set defaults +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +% load optional given inputfile as data +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + end +end + +isfreq = datatype(data, 'freq'); +israw = datatype(data, 'raw'); +istlck = datatype(data, 'timelock'); % this will be temporary converted into raw + +% check if the input data is valid for this function +data = checkdata(data, 'datatype', {'raw' 'freq'}, 'feedback', 'yes', 'hastrialdef', 'yes', 'ismeg', 'yes', 'senstype', {'ctf151', 'ctf275', 'bti148', 'bti248', 'itab153'}); + +if istlck + % the timelocked data has just been converted to a raw representation + % and will be converted back to timelocked at the end of this function + israw = true; +end + +if isfreq, + if ~isfield(data, 'fourierspctrm'), error('freq data should contain Fourier spectra'); end +end + +% set the default configuration +if ~isfield(cfg, 'channel'), cfg.channel = 'MEG'; end +if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end +% use a smart default for the distance +if ~isfield(cfg, 'neighbourdist'), + if isfield(data.grad, 'unit') && strcmp(data.grad.unit, 'cm') + cfg.neighbourdist = 4; + elseif isfield(data.grad, 'unit') && strcmp(data.grad.unit, 'mm') + cfg.neighbourdist = 40; + else + % don't provide a default in case the dimensions of the sensor array are unknown + end +end +if ~isfield(cfg, 'planarmethod'), cfg.planarmethod = 'sincos'; end +if strcmp(cfg.planarmethod, 'sourceproject') + if ~isfield(cfg, 'headshape'), cfg.headshape = []; end % empty will result in the vol being used + if ~isfield(cfg, 'inwardshift'), cfg.inwardshift = 2.5; end + if ~isfield(cfg, 'pruneratio'), cfg.pruneratio = 1e-3; end + if ~isfield(cfg, 'spheremesh'), cfg.spheremesh = 642; end +end + +if isfield(cfg, 'headshape') && isa(cfg.headshape, 'config') + % convert the nested config-object back into a normal structure + cfg.headshape = struct(cfg.headshape); +end + +% put the low-level options pertaining to the dipole grid in their own field +cfg = checkconfig(cfg, 'createsubcfg', {'grid'}); +cfg = checkconfig(cfg, 'renamedvalue', {'headshape', 'headmodel', []}); + +% select trials of interest +if ~strcmp(cfg.trials, 'all') + fprintf('selecting %d trials\n', length(cfg.trials)); + data = selectdata(data, 'rpt', cfg.trials); +end + +if strcmp(cfg.planarmethod, 'orig') + montage = megplanar_orig(cfg, data.grad); + +elseif strcmp(cfg.planarmethod, 'sincos') + montage = megplanar_sincos(cfg, data.grad); + +elseif strcmp(cfg.planarmethod, 'fitplane') + montage = megplanar_fitplane(cfg, data.grad); + +elseif strcmp(cfg.planarmethod, 'sourceproject') + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % Do an inverse computation with a simplified distributed source model + % and compute forward again with the axial gradiometer array replaced by + % a planar one. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + if isfreq + error('the method ''sourceproject'' is not supported for frequency data as input'); + end + + Nchan = length(data.label); + Ntrials = length(data.trial); + + % FT_PREPARE_VOL_SENS will match the data labels, the gradiometer labels and the + % volume model labels (in case of a multisphere model) and result in a gradiometer + % definition that only contains the gradiometers that are present in the data. + [vol, axial.grad, cfg] = prepare_headmodel(cfg, data); + + % determine the dipole layer that represents the surface of the brain + if isempty(cfg.headshape) + % construct from the inner layer of the volume conduction model + pos = headsurface(vol, axial.grad, 'surface', 'cortex', 'inwardshift', cfg.inwardshift, 'npnt', cfg.spheremesh); + else + % get the surface describing the head shape + if isstruct(cfg.headshape) && isfield(cfg.headshape, 'pnt') + % use the headshape surface specified in the configuration + headshape = cfg.headshape; + elseif isnumeric(cfg.headshape) && size(cfg.headshape,2)==3 + % use the headshape points specified in the configuration + headshape.pnt = cfg.headshape; + elseif ischar(cfg.headshape) + % read the headshape from file + headshape = ft_read_headshape(cfg.headshape); + else + error('cfg.headshape is not specified correctly') + end + if ~isfield(headshape, 'tri') + % generate a closed triangulation from the surface points + headshape.pnt = unique(headshape.pnt, 'rows'); + headshape.tri = projecttri(headshape.pnt); + end + % construct from the head surface + pos = headsurface([], [], 'headshape', headshape, 'inwardshift', cfg.inwardshift, 'npnt', cfg.spheremesh); + end + + % compute the forward model for the axial gradiometers + fprintf('computing forward model for %d dipoles\n', size(pos,1)); + lfold = ft_compute_leadfield(pos, axial.grad, vol); + + % construct the planar gradient definition and compute its forward model + % this will not work for a multisphere model, compute_leadfield will catch + % the error + planar.grad = constructplanargrad([], axial.grad); + lfnew = ft_compute_leadfield(pos, planar.grad, vol); + + % compute the interpolation matrix + transform = lfnew * prunedinv(lfold, cfg.pruneratio); + + % interpolate the data towards the planar gradiometers + for i=1:Ntrials + fprintf('interpolating trial %d to planar gradiometer\n', i); + interp.trial{i} = transform * data.trial{i}(dataindx,:); + end % for Ntrials + + % all planar gradiometer channels are included in the output + interp.grad = planar.grad; + interp.label = planar.grad.label; + + % copy the non-gradiometer channels back into the output data + other = setdiff(1:Nchan, dataindx); + for i=other + interp.label{end+1} = data.label{i}; + for j=1:Ntrials + interp.trial{j}(end+1,:) = data.trial{j}(i,:); + end + end + +else + error('unknown method for computation of planar gradient'); +end % cfg.planarmethod + +if any(strcmp(cfg.planarmethod, {'orig', 'sincos', 'fitplane'})) + % apply the linear transformation to the data + interp = ft_apply_montage(data, montage, 'keepunused', 'yes'); + % also apply the linear transformation to the gradiometer definition + interp.grad = ft_apply_montage(data.grad, montage); + interp.grad.balance.planar = montage; + % ensure that the old sensor type does not stick around, because it is now invalid + % the sensor type is added in FT_PREPARE_VOL_SENS but is not used in external fieldtrip code + if isfield(interp.grad, 'type') + interp.grad = rmfield(interp.grad, 'type'); + end + % keep track of the linear transformations that have been applied + if strcmp(interp.grad.balance.current, 'none') + interp.grad.balance.current = 'planar'; + else + interp.grad.balance.current = ['planar_' interp.grad.balance.current]; + end +end + +if istlck + % convert the raw structure back into a timelock structure + interp = checkdata(interp, 'datatype', 'timelock'); + israw = false; +end + +% accessing this field here is needed for the configuration tracking +% by accessing it once, it will not be removed from the output cfg +cfg.outputfile; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% store the configuration of this function call, including that of the previous function call +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_megplanar.m 1401 2010-07-12 18:52:40Z jansch $'; + +% remember the configuration details of the input data +try cfg.previous = data.cfg; end + +% remember the exact configuration details in the output +interp.cfg = cfg; + +% copy the trial specific information into the output +if isfield(data, 'trialinfo') + interp.trialinfo = data.trialinfo; +end + +% copy the trialdef field as well +if isfield(data, 'trialdef') + interp.trialdef = data.trialdef; +end + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', interp); % use the variable name "data" in the output file +end + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION that computes the inverse using a pruned SVD +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [lfi] = prunedinv(lf, r) +[u, s, v] = svd(lf); +p = find(s<(s(1,1)*r) & s~=0); +fprintf('pruning %d out of %d singular values\n', length(p), min(size(s))); +s(p) = 0; +s(find(s~=0)) = 1./s(find(s~=0)); +lfi = v * s' * u'; diff --git a/external/fieldtrip/ft_megrealign.m b/external/fieldtrip/ft_megrealign.m index b84b9b2..1bb8f92 100644 --- a/external/fieldtrip/ft_megrealign.m +++ b/external/fieldtrip/ft_megrealign.m @@ -1,11 +1,562 @@ -function varargout = funname(varargin); +function [interp] = ft_megrealign(cfg, data); -% this is a SPM wrapper around a FieldTrip function +% FT_MEGREALIGN interpolates MEG data towards standard gradiometer locations +% by projecting the individual timelocked data towards a coarse source +% reconstructed representation and computing the magnetic field on +% the standard gradiometer locations. +% +% Use as +% [interp] = ft_megrealign(cfg, data) +% +% Required configuration options: +% cfg.template +% cfg.inwardshift +% +% The new gradiometer definition is obtained from a template dataset, +% or can be constructed by averaging the gradiometer positions over +% multiple datasets. +% cfg.template = single dataset that serves as template +% cfg.template(1..N) = datasets that are averaged into the standard +% +% The realignment is done by computing a minumum current estimate using a +% large number of dipoles that are placed in the upper layer of the brain +% surface, followed by a forward computation towards the template +% gradiometer array. This requires the specification of a volume conduction +% model of the head and of a source model. +% +% A head model must be specified with +% cfg.hdmfile = string, file containing the volume conduction model +% or alternatively manually using +% cfg.vol.r = radius of sphere +% cfg.vol.o = [x, y, z] position of origin +% +% A source model (i.e. a superficial layer with distributed sources) can be +% constructed from a headshape file, or from the volume conduction model +% cfg.spheremesh = number of dipoles in the source layer (default = 642) +% cfg.inwardshift = depth of the source layer relative to the headshape +% surface or volume conduction model (no default +% supplied, see below) +% cfg.headshape = a filename containing headshape, a structure containing a +% single triangulated boundary, or a Nx3 matrix with surface +% points +% +% If you specify a headshape and it describes the skin surface, you should specify an +% inward shift of 2.5 cm. +% +% For a single-sphere or a local-spheres volume conduction model based on the skin +% surface, an inward shift of 2.5 cm is reasonable. +% +% For a single-sphere or a local-spheres volume conduction model based on the brain +% surface, you should probably use an inward shift of about 1 cm. +% +% For a realistic single-shell volume conduction model based on the brain surface, you +% should probably use an inward shift of about 1 cm. +% +% Other options are +% cfg.pruneratio = for singular values, default is 1e-3 +% cfg.verify = 'yes' or 'no', show the percentage difference (default = 'yes') +% cfg.feedback = 'yes' or 'no' (default = 'no') +% cfg.channel = Nx1 cell-array with selection of channels (default = 'MEG'), +% see FT_CHANNELSELECTION for details +% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') +% +% This implements the method described by T.R. Knosche, Transformation +% of whole-head MEG recordings between different sensor positions. +% Biomed Tech (Berl). 2002 Mar;47(3):59-62. +% +% See also FT_MEGINTERPOLATE, FT_PREPARE_LOCALSPHERES, FT_PREPARE_SINGLESHELL +% +% Undocumented local options: +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk -% this part is variable -prefix = 'ft_'; +% This function depends on FT_PREPARE_DIPOLE_GRID +% +% This function depends on FT_PREPARE_VOL_SENS which has the following options: +% cfg.channel +% cfg.elec +% cfg.elecfile +% cfg.grad +% cfg.gradfile +% cfg.hdmfile, documented +% cfg.order +% cfg.vol, documented -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +% Copyright (C) 2004-2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_megrealign.m 1401 2010-07-12 18:52:40Z jansch $ + +fieldtripdefs + +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +% set the default configuration +if ~isfield(cfg, 'headshape'), cfg.headshape = []; end +if ~isfield(cfg, 'pruneratio'), cfg.pruneratio = 1e-3; end +if ~isfield(cfg, 'spheremesh'), cfg.spheremesh = 642; end +if ~isfield(cfg, 'verify'), cfg.verify = 'yes'; end +if ~isfield(cfg, 'feedback'), cfg.feedback = 'yes'; end +if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end +if ~isfield(cfg, 'channel'), cfg.channel = 'MEG'; end +if ~isfield(cfg, 'topoparam'), cfg.topoparam = 'rms'; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +% load optional given inputfile as data +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + end +end + +% check if the input data is valid for this function +data = checkdata(data, 'datatype', 'raw', 'feedback', 'yes', 'hastrialdef', 'yes', 'ismeg', 'yes'); + +% check if the input cfg is valid for this function +cfg = checkconfig(cfg, 'renamed', {'plot3d', 'feedback'}); +cfg = checkconfig(cfg, 'renamedval', {'headshape', 'headmodel', []}); +cfg = checkconfig(cfg, 'required', {'inwardshift', 'template'}); + +%do realignment per trial +pertrial = all(ismember({'nasX';'nasY';'nasZ';'lpaX';'lpaY';'lpaZ';'rpaX';'rpaY';'rpaZ'}, data.label)); + +% put the low-level options pertaining to the dipole grid in their own field +cfg = checkconfig(cfg, 'createsubcfg', {'grid'}); + +% select trials of interest +if ~strcmp(cfg.trials, 'all') + fprintf('selecting %d trials\n', length(cfg.trials)); + data = selectdata(data, 'rpt', cfg.trials); +end + +Ntrials = length(data.trial); + +% retain only the MEG channels in the data and temporarily store +% the rest, these will be added back to the transformed data later. +cfg.channel = ft_channelselection(cfg.channel, data.label); +dataindx = match_str(data.label, cfg.channel); +restindx = setdiff(1:length(data.label),dataindx); +if ~isempty(restindx) + fprintf('removing %d non-MEG channels from the data\n', length(restindx)); + rest.label = data.label(restindx); % first remember the rest + data.label = data.label(dataindx); % then reduce the data + for i=1:Ntrials + rest.trial{i} = data.trial{i}(restindx,:); % first remember the rest + data.trial{i} = data.trial{i}(dataindx,:); % then reduce the data + end +else + rest.label = {}; + rest.trial = {}; +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% construct the average template gradiometer array +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +Ntemplate = length(cfg.template); +for i=1:Ntemplate + if isstr(cfg.template{i}), + fprintf('reading template sensor position from %s\n', cfg.template{i}); + template(i) = ft_read_sens(cfg.template{i}); + elseif isstruct(cfg.template{i}) && isfield(cfg.template{i}, 'pnt') && isfield(cfg.template{i}, 'ori') && isfield(cfg.template{i}, 'tra'), + template(i) = cfg.template{i}; + end +end + +% to construct the average location of the MEG sensors, 4 channels are needed that should be sufficiently far apart +switch ft_senstype(template(1)) + case {'ctf151' 'ctf275'} + labC = 'MZC01'; + labF = 'MZF03'; + labL = 'MLC21'; + labR = 'MRC21'; + case {'ctf151_planar' 'ctf275_planar'} + labC = 'MZC01_dH'; + labF = 'MZF03_dH'; + labL = 'MLC21_dH'; + labR = 'MRC21_dH'; + case {'bti148'} + labC = 'A14'; + labF = 'A2'; + labL = 'A15'; + labR = 'A29'; + case {'bti248'} + labC = 'A19'; + labF = 'A2'; + labL = 'A44'; + labR = 'A54'; + otherwise + % this could in principle be added to the cfg, but better is to have a more exhaustive list here + error('unsupported MEG system for realigning, please ask on the mailing list'); +end + +templ.meanC = [0 0 0]; +templ.meanF = [0 0 0]; +templ.meanL = [0 0 0]; +templ.meanR = [0 0 0]; +for i=1:Ntemplate + % determine the 4 ref sensors for this individual template helmet + % FIXME this assumes that coils and sensors coincide, this is generally not + % true, however there is not much of a problem, because the points are only + % used to get a transformation matrix + indxC = strmatch(labC, template(i).label, 'exact'); + indxF = strmatch(labF, template(i).label, 'exact'); + indxL = strmatch(labL, template(i).label, 'exact'); + indxR = strmatch(labR, template(i).label, 'exact'); + if isempty(indxC) || isempty(indxF) || isempty(indxL) || isempty(indxR) + error('not all 4 sensors were found that are needed to rotate/translate'); + end + % add them to the sum, to compute mean location of each ref sensor + templ.meanC = templ.meanC + template(i).pnt(indxC,:); + templ.meanF = templ.meanF + template(i).pnt(indxF,:); + templ.meanL = templ.meanL + template(i).pnt(indxL,:); + templ.meanR = templ.meanR + template(i).pnt(indxR,:); +end +templ.meanC = templ.meanC / Ntemplate; +templ.meanF = templ.meanF / Ntemplate; +templ.meanL = templ.meanL / Ntemplate; +templ.meanR = templ.meanR / Ntemplate; + +% construct two direction vectors that define the helmet orientation +templ.dirCF = (templ.meanF - templ.meanC); +templ.dirRL = (templ.meanL - templ.meanR); +% construct three orthonormal direction vectors +templ.dirX = normalize(templ.dirCF); +templ.dirY = normalize(templ.dirRL - dot(templ.dirRL, templ.dirX) * templ.dirX); +templ.dirZ = cross(templ.dirX, templ.dirY); +templ.tra = fixedbody(templ.meanC, templ.dirX, templ.dirY, templ.dirZ); + +% determine the 4 ref sensors for the helmet that belongs to this dataset +indxC = strmatch(labC, template(1).label, 'exact'); +indxF = strmatch(labF, template(1).label, 'exact'); +indxL = strmatch(labL, template(1).label, 'exact'); +indxR = strmatch(labR, template(1).label, 'exact'); +if isempty(indxC) || isempty(indxF) || isempty(indxL) || isempty(indxR) + error('not all 4 sensors were found that are needed to rotate/translate'); +end + +% construct two direction vectors that define the helmet orientation +orig.dirCF = template(1).pnt(indxF,:) - template(1).pnt(indxC,:); +orig.dirRL = template(1).pnt(indxL,:) - template(1).pnt(indxR,:); +% construct three orthonormal direction vectors +orig.dirX = normalize(orig.dirCF); +orig.dirY = normalize(orig.dirRL - dot(orig.dirRL, orig.dirX) * orig.dirX); +orig.dirZ = cross(orig.dirX, orig.dirY); +orig.tra = fixedbody(template(1).pnt(indxC,:), orig.dirX, orig.dirY, orig.dirZ); + +% compute the homogenous transformation matrix and transform the positions +tra = inv(templ.tra) * orig.tra; +pnt = template(1).pnt; +pnt(:,4) = 1; +pnt = (tra * pnt')'; +pnt = pnt(:,1:3); + +% remove the translation from the transformation matrix and rotate the orientations +tra(:,4) = [0 0 0 1]'; +ori = template(1).ori; +ori(:,4) = 1; +ori = (tra * ori')'; +ori = ori(:,1:3); + +tmp_label = template(1).label; +tmp_tra = template(1).tra; +tmp_unit = template(1).unit; + +% construct the final template gradiometer definition +template = []; +template.grad.pnt = pnt; +template.grad.ori = ori; +% keep the same labels and the linear weights of the coils +template.grad.label = tmp_label; +template.grad.tra = tmp_tra; +template.grad.unit = tmp_unit; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% FT_PREPARE_VOL_SENS will match the data labels, the gradiometer labels and the +% volume model labels (in case of a multisphere model) and result in a gradiometer +% definition that only contains the gradiometers that are present in the data. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +volcfg = []; +if isfield(cfg, 'hdmfile') + volcfg.hdmfile = cfg.hdmfile; +elseif isfield(cfg, 'vol') + volcfg.vol = cfg.vol; +end +volcfg.grad = data.grad; +volcfg.channel = data.label; % this might be a subset of the MEG channels +[volold, data.grad] = prepare_headmodel(volcfg); + +% note that it is neccessary to keep the two volume conduction models +% seperate, since the single-shell Nolte model contains gradiometer specific +% precomputed parameters. Note that this is not guaranteed to result in a +% good projection for local sphere models. +volcfg.grad = template.grad; +volcfg.channel = 'MEG'; % include all MEG channels +[volnew, template.grad] = prepare_headmodel(volcfg); + +if strcmp(ft_senstype(data.grad), ft_senstype(template.grad)) + [id, it] = match_str(data.grad.label, template.grad.label); + fprintf('mean distance towards template gradiometers is %.2f %s\n', mean(sum((data.grad.pnt(id,:)-template.grad.pnt(it,:)).^2, 2).^0.5), template.grad.unit); +else + % the projection is from one MEG system to another MEG system, which makes a comparison of the data difficult + cfg.feedback = 'no'; + cfg.verify = 'no'; +end + +% create the dipole grid on which the data will be projected +grid = prepare_dipole_grid(cfg, volold, data.grad); +pos = grid.pos; + +% sometimes some of the dipole positions are nan, due to problems with the headsurface triangulation +% remove them to prevent problems with the forward computation +sel = find(any(isnan(pos(:,1)),2)); +pos(sel,:) = []; + +% compute the forward model for the new gradiometer positions +fprintf('computing forward model for %d dipoles\n', size(pos,1)); +lfnew = ft_compute_leadfield(pos, template.grad, volnew); +if ~pertrial, + %this needs to be done only once + lfold = ft_compute_leadfield(pos, data.grad, volold); + [realign, noalign, bkalign] = computeprojection(lfold, lfnew, cfg.pruneratio, cfg.verify); +else + %the forward model and realignment matrices have to be computed for each trial + %this also goes for the singleshell volume conductor model + %x = which('rigidbodyJM'); %this function is needed + %if isempty(x), + % error('you are trying out experimental code for which you need some extra functionality which is currently not in the release version of fieldtrip. if you are interested in trying it out, contact jan-mathijs'); + %end +end + +% interpolate the data towards the template gradiometers +for i=1:Ntrials + fprintf('realigning trial %d\n', i); + if pertrial, + %warp the gradiometer array according to the motiontracking data + sel = match_str(rest.label, {'nasX';'nasY';'nasZ';'lpaX';'lpaY';'lpaZ';'rpaX';'rpaY';'rpaZ'}); + hmdat = rest.trial{i}(sel,:); + if ~all(hmdat==repmat(hmdat(:,1),[1 size(hmdat,2)])) + error('only one position per trial is at present allowed'); + else + %M = rigidbodyJM(hmdat(:,1)) + M = headcoordinates(hmdat(1:3,1),hmdat(4:6,1),hmdat(7:9,1)); + grad = ft_transform_sens(M, data.grad); + end + + volcfg.grad = grad; + %compute volume conductor + [volold, grad] = prepare_headmodel(volcfg); + %compute forward model + lfold = ft_compute_leadfield(pos, grad, volold); + %compute projection matrix + [realign, noalign, bkalign] = computeprojection(lfold, lfnew, cfg.pruneratio, cfg.verify); + end + data.realign{i} = realign * data.trial{i}; + if strcmp(cfg.verify, 'yes') + % also compute the residual variance when interpolating + [id,it] = match_str(data.grad.label, template.grad.label); + rvrealign = rv(data.trial{i}(id,:), data.realign{i}(it,:)); + fprintf('original -> template RV %.2f %%\n', 100 * mean(rvrealign)); + datnoalign = noalign * data.trial{i}; + datbkalign = bkalign * data.trial{i}; + rvnoalign = rv(data.trial{i}, datnoalign); + rvbkalign = rv(data.trial{i}, datbkalign); + fprintf('original -> original RV %.2f %%\n', 100 * mean(rvnoalign)); + fprintf('original -> template -> original RV %.2f %%\n', 100 * mean(rvbkalign)); + end +end + +% plot the topography before and after the realignment +if strcmp(cfg.feedback, 'yes') + + warning('showing MEG topography (RMS value over time) in the first trial only'); + Nchan = length(data.grad.label); + [id,it] = match_str(data.grad.label, template.grad.label); + pnt1 = data.grad.pnt(id,:); + pnt2 = template.grad.pnt(it,:); + prj1 = elproj(pnt1); tri1 = delaunay(prj1(:,1), prj1(:,2)); + prj2 = elproj(pnt2); tri2 = delaunay(prj2(:,1), prj2(:,2)); + + switch cfg.topoparam + case 'rms' + p1 = sqrt(mean(data.trial{1}(id,:).^2, 2)); + p2 = sqrt(mean(data.realign{1}(it,:).^2, 2)); + case 'svd' + [u, s, v] = svd(data.trial{1}(id,:)); p1 = u(:,1); + [u, s, v] = svd(data.realign{1}(it,:)); p2 = u(:,1); + otherwise + error('unsupported cfg.topoparam'); + end + + X = [pnt1(:,1) pnt2(:,1)]'; + Y = [pnt1(:,2) pnt2(:,2)]'; + Z = [pnt1(:,3) pnt2(:,3)]'; + + % show figure with old an new helmets, volume model and dipole grid + figure + tmpcfg = []; + tmpcfg.vol = volold; + tmpcfg.grad = data.grad; + tmpcfg.grid = grid; + tmpcfg.plotsensors = 'no'; % these are plotted seperately below + ft_headmodelplot(tmpcfg); + hold on + plot3(pnt1(:,1), pnt1(:,2), pnt1(:,3), 'r.') % original positions + plot3(pnt2(:,1), pnt2(:,2), pnt2(:,3), 'g.') % template positions + line(X,Y,Z, 'color', 'black'); + view(-90, 90); + + % show figure with data on old helmet location + figure + hold on + plot3(pnt1(:,1), pnt1(:,2), pnt1(:,3), 'r.') % original positions + plot3(pnt2(:,1), pnt2(:,2), pnt2(:,3), 'g.') % template positions + line(X,Y,Z, 'color', 'black'); + axis equal; axis vis3d + triplot(pnt1, tri1, p1); + title('RMS, before realignment') + view(-90, 90) + + % show figure with data on new helmet location + figure + hold on + plot3(pnt1(:,1), pnt1(:,2), pnt1(:,3), 'r.') % original positions + plot3(pnt2(:,1), pnt2(:,2), pnt2(:,3), 'g.') % template positions + line(X,Y,Z, 'color', 'black'); + axis equal; axis vis3d + triplot(pnt2, tri2, p2); + title('RMS, after realignment') + view(-90, 90) +end + +% store the realigned data in a new structure +interp.label = template.grad.label; +interp.grad = template.grad; % replace with the template gradiometer array +interp.trial = data.realign; % remember the processed data +interp.fsample = data.fsample; +interp.time = data.time; + +% add the rest channels back to the data, these were not interpolated +if ~isempty(rest.label) + fprintf('adding %d non-MEG channels back to the data (', length(rest.label)); + fprintf('%s, ', rest.label{1:end-1}); + fprintf('%s)\n', rest.label{end}); + for trial=1:length(rest.trial) + interp.trial{trial} = [interp.trial{trial}; rest.trial{trial}]; + end + interp.label = [interp.label; rest.label]; +end + +% accessing this field here is needed for the configuration tracking +% by accessing it once, it will not be removed from the output cfg +cfg.outputfile; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% store the configuration of this function call, including that of the previous function call +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_megrealign.m 1401 2010-07-12 18:52:40Z jansch $'; + +% remember the configuration details of the input data +try, cfg.previous = data.cfg; end + +% remember the exact configuration details in the output +interp.cfg = cfg; + +% copy the trial specific information into the output +if isfield(data, 'trialinfo') + interp.trialinfo = data.trialinfo; +end + +% copy the trialdef field as well +if isfield(data, 'trialdef') + interp.trialdef = data.trialdef; +end + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', interp); % use the variable name "data" in the output file +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% subfunction that computes the projection matrix(ces) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [realign, noalign, bkalign] = computeprojection(lfold, lfnew, pruneratio, verify) + +% compute this inverse only once, although it is used twice +tmp = prunedinv(lfold, pruneratio); +% compute the three interpolation matrices +fprintf('computing interpolation matrix #1\n'); +realign = lfnew * tmp; +if strcmp(verify, 'yes') + fprintf('computing interpolation matrix #2\n'); + noalign = lfold * tmp; + fprintf('computing interpolation matrix #3\n'); + bkalign = lfold * prunedinv(lfnew, pruneratio) * realign; +else + noalign = []; + bkalign = []; +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% subfunction that computes the inverse using a pruned SVD +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [lfi] = prunedinv(lf, r) +[u, s, v] = svd(lf); +if r<1, + % treat r as a ratio + p = find(s<(s(1,1)*r) & s~=0); +else + % treat r as the number of spatial components to keep + diagels = 1:(min(size(s))+1):(min(size(s)).^2); + p = diagels((r+1):end); +end +fprintf('pruning %d from %d, i.e. removing the %d smallest spatial components\n', length(p), min(size(s)), length(p)); +s(p) = 0; +s(find(s~=0)) = 1./s(find(s~=0)); +lfi = v * s' * u'; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% subfunction that computes the homogenous translation matrix +% corresponding to a fixed body rotation and translation +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [h] = fixedbody(center, dirx, diry, dirz); +rot = eye(4); +rot(1:3,1:3) = inv(eye(3) / [dirx; diry; dirz]); +tra = eye(4); +tra(1:4,4) = [-center 1]'; +h = rot * tra; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% subfunction that scales a vector to unit length +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [v] = normalize(v); +v = v / sqrt(v * v'); diff --git a/external/fieldtrip/ft_megrepair.m b/external/fieldtrip/ft_megrepair.m deleted file mode 100644 index b84b9b2..0000000 --- a/external/fieldtrip/ft_megrepair.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'ft_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_movieplotER.m b/external/fieldtrip/ft_movieplotER.m new file mode 100644 index 0000000..fa11a19 --- /dev/null +++ b/external/fieldtrip/ft_movieplotER.m @@ -0,0 +1,176 @@ +function ft_movieplotER(cfg, timelock) + +% FT_MOVIEPLOTER makes a movie of the topographic distribution of the +% time-locked average. +% +% Use as +% ft_movieplotER(cfg, timelock) +% where the input data is from FT_TIMELOCKANALYSIS and the configuration +% can contain +% cfg.samperframe = number, samples per fram (default = 1) +% cfg.framespersec = number, frames per second (default = 5) +% cfg.xlim = 'maxmin' or [xmin xmax] (default = 'maxmin') +% cfg.zlim = 'maxmin', 'maxabs' or [zmin zmax] (default = 'maxmin') +% cfg.framesfile = 'no', no file saved, or 'sting', filename of saved frames.mat (default = 'no'); +% cfg.layout = specification of the layout, see below +% +% The layout defines how the channels are arranged. You can specify the +% layout in a variety of ways: +% - you can provide a pre-computed layout structure (see prepare_layout) +% - you can give the name of an ascii layout file with extension *.lay +% - you can give the name of an electrode file +% - you can give an electrode definition, i.e. "elec" structure +% - you can give a gradiometer definition, i.e. "grad" structure +% If you do not specify any of these and the data structure contains an +% electrode or gradiometer structure, that will be used for creating a +% layout. If you want to have more fine-grained control over the layout +% of the subplots, you should create your own layout file. + +% Copyright (C) 2009, Ingrid Nieuwenhuis +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_movieplotER.m 1430 2010-07-20 07:41:41Z roboos $ + +% Defaults +if ~isfield(cfg, 'xlim'), cfg.xlim = 'maxmin'; end +if ~isfield(cfg, 'zlim'), cfg.zlim = 'maxmin'; end +if ~isfield(cfg, 'samperframe'), cfg.samperframe = 1; end +if ~isfield(cfg, 'framespersec'), cfg.framespersec = 5; end +if ~isfield(cfg, 'framesfile'), cfg.framesfile = 'no'; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end + +% load optional given inputfile as data +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + timelock = loadvar(cfg.inputfile, 'data'); + end +end + +% Checkdata +timelock = checkdata(timelock, 'datatype', 'timelock'); + +% check if the input cfg is valid for this function +cfg = checkconfig(cfg, 'renamedval', {'zlim', 'absmax', 'maxabs'}); + +% Read or create the layout that will be used for plotting: +lay = ft_prepare_layout(cfg, timelock); + +% Select the channels in the data that match with the layout: +[seldat, sellay] = match_str(timelock.label, lay.label); +if isempty(seldat) + error('labels in timelock and labels in layout do not match'); +end + +% Get physical min/max range of x: +if strcmp(cfg.xlim,'maxmin') + xmin = min(timelock.time); + xmax = max(timelock.time); +else + xmin = cfg.xlim(1); + xmax = cfg.xlim(2); +end + +% Replace value with the index of the nearest bin +xmin = nearest(timelock.time, xmin); +xmax = nearest(timelock.time, xmax); + +% Make datavector of whole time window +datavector = timelock.avg(seldat,xmin:xmax); + +% Select x and y coordinates and labels of the channels in the data +chanX = cfg.layout.pos(sellay,1); +chanY = cfg.layout.pos(sellay,2); +ind_COMNT = strmatch('COMNT', lay.label); +if length(ind_COMNT)==1 + % remember the position of the comment + X_COMNT = cfg.layout.pos(ind_COMNT, 1); + Y_COMNT = cfg.layout.pos(ind_COMNT, 1); +end + +% Same zlim for whole movie! Get physical min/max range of z: +if strcmp(cfg.zlim,'maxmin') + zmin = min(datavector(:)); + zmax = max(datavector(:)); +elseif strcmp(cfg.zlim,'maxabs') + zmin = -max(max(abs(datavector(:)))); + zmax = max(max(abs(datavector(:)))); +else + zmin = cfg.zlim(1); + zmax = cfg.zlim(2); +end +cfg.zlim = [zmin zmax]; + +figure; +% Collect frames +for iFrame = 1:floor(size(datavector,2)/cfg.samperframe) + data_frame = mean(datavector(:,((iFrame-1)*cfg.samperframe)+1:iFrame*cfg.samperframe),2); + % Draw topoplot: + ft_plot_topo(chanX, chanY, data_frame, 'mask', lay.mask, 'outline', lay.outline, 'interpmethod', 'cubic'); + %ft_plot_text(chanX, chanY, '.'); + axis off + % plot comment + if length(ind_COMNT)==1 + comment = sprintf('zlim=[%.3g %.3g]\ntime=[%.4g %.4g]', zmin, zmax, timelock.time(((iFrame-1)*cfg.samperframe)+1), timelock.time(iFrame*cfg.samperframe)); + ft_plot_text(X_COMNT,Y_COMNT, comment) + end + F(iFrame) = getframe; + cla +end +close + +% save frames file +if strcmp(cfg.framesfile, 'no'); +else + save(cfg.framesfile, 'F') +end +hmov = figure; +axis off +data_movie.F = F; +data_movie.cfg = cfg; + +uicontrol('parent', hmov, 'units', 'normalized', 'style', 'pushbutton', 'string', 'replay', 'userdata', 1, 'position', [0.86, 0.1, 0.12, 0.05], 'backgroundcolor', [1 1 1], 'callback', @replay_cb) +uicontrol('parent', hmov, 'units', 'normalized', 'style', 'pushbutton', 'string', 'frames/s', 'userdata', 1, 'position', [0.86, 0.18, 0.12, 0.05], 'backgroundcolor', [1 1 1], 'callback', @framespersec_cb) + +movie(F,1,cfg.framespersec) +guidata(hmov, data_movie); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function replay_cb(hmov, eventdata) +data_movie = guidata(hmov); +if get(hmov, 'userdata') + movie(data_movie.F,1,data_movie.cfg.framespersec) +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function framespersec_cb(hmov, eventdata) +data_movie = guidata(hmov); +if get(hmov, 'userdata') + response = inputdlg('frames per second', 'specify', 1, {num2str(data_movie.cfg.framespersec)}); + if ~isempty(response) + data_movie.cfg.framespersec = str2double(response{1}); + end + guidata(hmov, data_movie); +end diff --git a/external/fieldtrip/ft_multiplotCC.m b/external/fieldtrip/ft_multiplotCC.m new file mode 100644 index 0000000..3516a88 --- /dev/null +++ b/external/fieldtrip/ft_multiplotCC.m @@ -0,0 +1,118 @@ +function ft_multiplotCC(cfg, data) + +% FT_MULTIPLOTCC visualiuzes the coherence between channels by using multiple +% topoplots. The topoplot at a given channel location shows the coherence +% of that channel with all other channels. +% +% Use as +% ft_multiplotCC(cfg, data) +% +% See also topoplotCC + +% Undocumented local options: +% cfg.layout = layout filename or a structure produced by prepare_layout +% cfg.xlim +% cfg.xparam +% cfg.zparam +% This function requires input from FT_FREQSTATISTICS_SHIFTPREDICT +% This function should be rewritten, using the clean topoplot implementation + +% Copyright (C) 2005-2006, Jan-Mathijs Schoffelen, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_multiplotCC.m 948 2010-04-21 18:02:21Z roboos $ + +fieldtripdefs + +if ~isfield(cfg, 'layout'), cfg.layout = 'CTF151s.lay'; end; +if ~isfield(cfg, 'xparam'), cfg.xparam = 'foi'; end; +if ~isfield(cfg, 'xlim'), cfg.xlim = 'all'; end; +if ~isfield(cfg, 'zparam'), cfg.zparam = 'avg.icohspctrm'; end; + +% for backward compatibility with old data structures +data = checkdata(data); + +if strcmp(cfg.zparam, 'avg.icohspctrm') && ~issubfield(data, 'avg.icohspctrm'), + data.avg.icohspctrm = abs(imag(data.avg.cohspctrm)); +end + +if strcmp(data.dimord, 'refchan_chan_freq'), + %reshape input-data, such that ft_topoplotER will take it + cnt = 1; + siz = size(data.prob); + data.labelcmb = cell(siz(1)*siz(2),2); + data.prob = reshape(data.prob, [siz(1)*siz(2) siz(3)]); + data.stat = reshape(data.stat, [siz(1)*siz(2) siz(3)]); + for j = 1:length(data.label) + for k = 1:length(data.reflabel) + data.labelcmb(cnt,:) = [data.reflabel(k) data.label(j)]; + cnt = cnt + 1; + end + end + tmpdata = data; +else + dat = getsubfield(data, cfg.zparam); + scale = [0 max(dat(:))-0.2]; +end + +if isfield(cfg, 'xparam'), + xparam = getsubfield(data, cfg.xparam); + if ~strcmp(cfg.xlim, 'all'), + fbin = [nearest(xparam, cfg.xlim(1)) nearest(xparam, cfg.xlim(2))]; + else + fbin = [xparam(1) xparam(end)]; + end +end + +[chNum,X,Y,Width,Height,Lbl] = textread(cfg.layout,'%f %f %f %f %f %s'); + +xScaleFac = 1/(max(Width)+ max(X) - min(X)); +yScaleFac = 1/(max(Height)+ max(Y) - min(Y)); + + +Xpos = xScaleFac*(X-min(X)); +Ypos = 0.9*yScaleFac*(Y-min(Y)); + +for k=1:length(chNum) - 2 + subplotOL('position',[Xpos(k) Ypos(k)+(Height(k)*yScaleFac) Width(k)*xScaleFac*2 Height(k)*yScaleFac*2]) + config.layout = cfg.layout; + if exist('tmpdata'), + + config.style = 'straight'; + config.marker = 'off'; + try, config.refmarker = strmatch(Lbl(k), data.reflabel); + catch, config.refmarker = strmatch(Lbl(k), data.label); end + config.interplimits = 'electrodes'; + if isfield(cfg, 'xparam'), + config.xparam = cfg.xparam; + config.xlim = xparam; + else + config.xparam = 'time'; + config.xlim = [k-0.5 k+0.5]; + end + config.zparam = cfg.zparam; + config.cohrefchannel = Lbl(k); + config.colorbar = 'no'; + config.zlim = scale; + config.grid_scale = 30; + ft_topoplotER(config, data); + drawnow; + end +end + + diff --git a/external/fieldtrip/ft_multiplotER.m b/external/fieldtrip/ft_multiplotER.m index b84b9b2..b2ccf73 100644 --- a/external/fieldtrip/ft_multiplotER.m +++ b/external/fieldtrip/ft_multiplotER.m @@ -1,11 +1,575 @@ -function varargout = funname(varargin); +function [cfg] = ft_multiplotER(cfg, varargin) -% this is a SPM wrapper around a FieldTrip function +% ft_multiplotER plots the event-related fields or potentials versus time +% or of oscillatory activity (power or coherence) versus frequency. Multiple +% datasets can be overlayed. The plots are arranged according to their +% location specified in the layout. +% +% Use as: +% ft_multiplotER(cfg, data) +% ft_multiplotER(cfg, data, data2, ..., dataN) +% +% The data can be an ERP/ERF produced by FT_TIMELOCKANALYSIS, a powerspectrum +% produced by FT_FREQANALYSIS or a coherencespectrum produced by FT_FREQDESCRIPTIVES. +% If you specify multiple datasets they must contain the same channels, etc. +% +% The configuration can have the following parameters: +% cfg.xparam = field to be plotted on x-axis (default depends on data.dimord) +% 'time' or 'freq' +% cfg.zparam = field to be plotted on y-axis (default depends on data.dimord) +% 'avg', 'powspctrm' or 'cohspctrm' +% cfg.maskparameter = field in the first dataset to be used for marking significant data +% cfg.maskstyle = style used for masking of data, 'box', 'thickness' or 'saturation' (default = 'box') +% cfg.xlim = 'maxmin' or [xmin xmax] (default = 'maxmin') +% cfg.ylim = 'maxmin' or [ymin ymax] (default = 'maxmin') +% cfg.cohrefchannel = name of reference channel for visualising coherence, can be 'gui' +% cfg.baseline = 'yes','no' or [time1 time2] (default = 'no'), see FT_TIMELOCKBASELINE or FT_FREQBASELINE +% cfg.baselinetype = 'absolute' or 'relative' (default = 'absolute') +% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') +% cfg.axes = 'yes', 'no' (default = 'yes') +% Draw x- and y-axes for each graph +% cfg.box = 'yes', 'no' (default = 'no') +% Draw a box around each graph +% cfg.comment = string of text (default = date + colors) +% Add 'comment' to graph (according to COMNT in the layout) +% cfg.showlabels = 'yes', 'no' (default = 'no') +% cfg.showoutline = 'yes', 'no' (default = 'no') +% cfg.fontsize = font size of comment and labels (if present) (default = 8) +% cfg.interactive = Interactive plot 'yes' or 'no' (default = 'no') +% In a interactive plot you can select areas and produce a new +% interactive plot when a selected area is clicked. Multiple areas +% can be selected by holding down the SHIFT key. +% cfg.renderer = 'painters', 'zbuffer',' opengl' or 'none' (default = []) +% cfg.linestyle = linestyle/marker type, see options of the matlab PLOT function (default = '-') +% cfg.linewidth = linewidth in points (default = 0.5) +% cfg.graphcolor = color(s) used for plotting the dataset(s) (default = 'brgkywrgbkywrgbkywrgbkyw') +% alternatively, colors can be specified as Nx3 matrix of RGB values +% +% cfg.layout = specify the channel layout for plotting using one of +% the following ways: +% +% The layout defines how the channels are arranged and what the size of each +% subplot is. You can specify the layout in a variety of ways: +% - you can provide a pre-computed layout structure (see prepare_layout) +% - you can give the name of an ascii layout file with extension *.lay +% - you can give the name of an electrode file +% - you can give an electrode definition, i.e. "elec" structure +% - you can give a gradiometer definition, i.e. "grad" structure +% If you do not specify any of these and the data structure contains an +% electrode or gradiometer structure, that will be used for creating a +% layout. If you want to have more fine-grained control over the layout +% of the subplots, you should create your own layout file. +% +% See also: +% ft_multiplotTFR, ft_singleplotER, ft_singleplotTFR, ft_topoplotER, ft_topoplotTFR, +% ft_prepare_layout. -% this part is variable -prefix = 'ft_'; +% Undocumented local options: +% cfg.layoutname +% cfg.inputfile = one can specifiy preanalysed saved data as input +% The data should be provided in a cell array + +% +% This function depends on FT_TIMELOCKBASELINE which has the following options: +% cfg.baseline, documented +% cfg.channel +% cfg.blcwindow +% cfg.previous +% cfg.version +% +% This function depends on FT_FREQBASELINE which has the following options: +% cfg.baseline, documented +% cfg.baselinetype + +% Copyright (C) 2003-2006, Ole Jensen +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_multiplotER.m 1430 2010-07-20 07:41:41Z roboos $ + +fieldtripdefs + +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +clf + +% set default for inputfile +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end + +hasdata = nargin>1; +if ~isempty(cfg.inputfile) % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + for i=1:numel(cfg.inputfile) + varargin{i} = loadvar(cfg.inputfile{i}, 'data'); % read datasets from array inputfile + data = varargin{i}; + end + end +else + data = varargin{1}; +end + +% For backward compatibility with old data structures: +for i=1:length(varargin) + varargin{i} = checkdata(varargin{i}); +end + +% set the defaults: +if ~isfield(cfg,'baseline'), cfg.baseline = 'no'; end +if ~isfield(cfg,'trials'), cfg.trials = 'all'; end +if ~isfield(cfg,'xlim'), cfg.xlim = 'maxmin'; end +if ~isfield(cfg,'ylim'), cfg.ylim = 'maxmin'; end +if ~isfield(cfg,'comment'), cfg.comment = strcat([date '\n']); end +if ~isfield(cfg,'axes'), cfg.axes = 'yes'; end +if ~isfield(cfg,'showlabels'), cfg.showlabels = 'no'; end +if ~isfield(cfg,'showoutline'), cfg.showoutline = 'no'; end +if ~isfield(cfg,'box'), cfg.box = 'no'; end +if ~isfield(cfg,'fontsize'), cfg.fontsize = 8; end +if ~isfield(cfg,'graphcolor'), cfg.graphcolor = 'brgkywrgbkywrgbkywrgbkyw'; end +if ~isfield(cfg,'interactive'), cfg.interactive = 'no'; end +if ~isfield(cfg,'renderer'), cfg.renderer = []; end +if ~isfield(cfg,'maskparameter'), cfg.maskparameter = []; end +if ~isfield(cfg,'linestyle'), cfg.linestyle = '-'; end +if ~isfield(cfg,'linewidth'), cfg.linewidth = 0.5; end +if ~isfield(cfg,'maskstyle'), cfg.maskstyle = 'box'; end + +if ischar(cfg.graphcolor) + GRAPHCOLOR = ['k' cfg.graphcolor]; +elseif isnumeric(cfg.graphcolor) + GRAPHCOLOR = [0 0 0; cfg.graphcolor]; +end + +% Set x/y/zparam defaults according to varargin{1}.dimord value: +if strcmp(varargin{1}.dimord, 'chan_time') + if ~isfield(cfg, 'xparam'), cfg.xparam='time'; end + if ~isfield(cfg, 'zparam'), cfg.zparam='avg'; end +elseif strcmp(varargin{1}.dimord, 'chan_freq') + if ~isfield(cfg, 'xparam'), cfg.xparam='freq'; end + if ~isfield(cfg, 'zparam'), cfg.zparam='powspctrm'; end +elseif strcmp(varargin{1}.dimord, 'subj_chan_time') || strcmp(varargin{1}.dimord, 'rpt_chan_time') + tmpcfg = []; + tmpcfg.trials = cfg.trials; + for i=1:(nargin-1) + varargin{i} = ft_timelockanalysis(tmpcfg, varargin{i}); + end + if ~isfield(cfg, 'xparam'), cfg.xparam='time'; end + if ~isfield(cfg, 'zparam'), cfg.zparam='avg'; end +elseif strcmp(varargin{1}.dimord, 'subj_chan_freq') || strcmp(varargin{1}.dimord, 'rpt_chan_freq') + tmpcfg = []; + tmpcfg.trials = cfg.trials; + tmpcfg.jackknife = 'no'; + if isfield(cfg, 'zparam') && strcmp(cfg.zparam,'cohspctrm') + % on the fly computation of coherence spectrum is not supported + elseif isfield(cfg, 'zparam') && ~strcmp(cfg.zparam,'powspctrm') + % freqdesctiptives will only work on the powspctrm field, hence a temporary copy of the data is needed + for i=1:(nargin-1) + tempdata.dimord = varargin{i}.dimord; + tempdata.freq = varargin{i}.freq; + tempdata.label = varargin{i}.label; + tempdata.powspctrm = varargin{i}.(cfg.zparam); + tempdata.cfg = varargin{i}.cfg; + tempdata = ft_freqdescriptives(tmpcfg, tempdata); + varargin{i}.(cfg.zparam) = tempdata.powspctrm; + clear tempdata + end + else + for i=1:(nargin-1) + if isfield(varargin{i}, 'crsspctrm'), varargin{i} = rmfield(varargin{i}, 'crsspctrm'); end % on the fly computation of coherence spectrum is not supported + varargin{i} = ft_freqdescriptives(tmpcfg, varargin{i}); + end + end + if ~isfield(cfg, 'xparam'), cfg.xparam='freq'; end + if ~isfield(cfg, 'zparam'), cfg.zparam='powspctrm'; end +end + +% Make sure cfg.yparam and cfg.zparam become equivalent if only one is defined: +if (isfield(cfg, 'yparam')) && (~isfield(cfg, 'zparam')) + cfg.zparam = cfg.yparam; +elseif (~isfield(cfg, 'yparam')) && (isfield(cfg, 'zparam')) + cfg.yparam = cfg.zparam; +end + +% Old style coherence plotting with cohtargetchannel is no longer supported +cfg = checkconfig(cfg, 'unused', {'cohtargetchannel'}); + +% Read or create the layout that will be used for plotting +lay = ft_prepare_layout(cfg, varargin{1}); +cfg.layout = lay; + +for k=1:length(varargin) + % Check for unconverted coherence spectrum data + if (strcmp(cfg.zparam,'cohspctrm')) && (isfield(varargin{k}, 'labelcmb')) + % A reference channel is required: + if ~isfield(cfg,'cohrefchannel'), + error('no reference channel specified'); + end + + if strcmp(cfg.cohrefchannel, 'gui') + % Open a single figure with the channel layout, the user can click on a reference channel + h = clf; + ft_plot_lay(lay, 'box', false); + title('Select the reference channel by clicking on it...'); + % add the channel information to the figure + info = guidata(h); + info.x = lay.pos(:,1); + info.y = lay.pos(:,2); + info.label = lay.label; + guidata(h, info); + set(gcf, 'WindowButtonUpFcn', {@ft_select_channel, 'callback', {@select_multiplotER, cfg, varargin{:}}}); + return + end + + % Convert 2-dimensional channel matrix to a single dimension: + sel1 = strmatch(cfg.cohrefchannel, varargin{k}.labelcmb(:,2)); + sel2 = strmatch(cfg.cohrefchannel, varargin{k}.labelcmb(:,1)); + fprintf('selected %d channels for coherence\n', length(sel1)+length(sel2)); + varargin{k}.cohspctrm = varargin{k}.cohspctrm([sel1;sel2],:,:); + varargin{k}.label = [varargin{k}.labelcmb(sel1,1);varargin{k}.labelcmb(sel2,2)]; + varargin{k}.labelcmb = varargin{k}.labelcmb([sel1;sel2],:); + varargin{k} = rmfield(varargin{k}, 'labelcmb'); + end + + % Apply baseline correction: + if ~strcmp(cfg.baseline, 'no') + if strcmp(cfg.xparam, 'time') + varargin{k} = ft_timelockbaseline(cfg, varargin{k}); + elseif strcmp(cfg.xparam, 'freq') + varargin{k} = ft_freqbaseline(cfg, varargin{k}); + else + warning('Baseline not applied, please set cfg.xparam'); + end + end +end + +% Get physical x-axis range: +if strcmp(cfg.xlim,'maxmin') + % Find maxmin throughout all varargins: + xmin = []; + xmax = []; + for i=1:length(varargin) + xmin = min([xmin varargin{i}.(cfg.xparam)]); + xmax = max([xmax varargin{i}.(cfg.xparam)]); + end +else + xmin = cfg.xlim(1); + xmax = cfg.xlim(2); +end + +% Find corresponding x-axis bins: +xidc = find(varargin{1}.(cfg.xparam) >= xmin & varargin{1}.(cfg.xparam) <= xmax); + +% Align physical x-axis range to the array bins: +xmin = varargin{1}.(cfg.xparam)(xidc(1)); +xmax = varargin{1}.(cfg.xparam)(xidc(end)); + +% Get physical y-axis range (ylim / zparam): +if strcmp(cfg.ylim,'maxmin') + % Find maxmin throughout all varargins: + ymin = []; + ymax = []; + for i=1:length(varargin) + % Select the channels in the data that match with the layout: + dat = []; + dat = getsubfield(varargin{i}, cfg.zparam); + [seldat, sellay] = match_str(varargin{k}.label, lay.label); + if isempty(seldat) + error('labels in data and labels in layout do not match'); + end + data = dat(seldat,:); + ymin = min([ymin min(min(min(data)))]); + ymax = max([ymax max(max(max(data)))]); + end +else + ymin = cfg.ylim(1); + ymax = cfg.ylim(2); +end + +% convert the layout to Ole's style of variable names +X = lay.pos(:,1); +Y = lay.pos(:,2); +Width = lay.width; +Height = lay.height; +Lbl = lay.label; + +% Create empty channel coordinates and labels arrays: +chanX(1:length(Lbl)) = NaN; +chanY(1:length(Lbl)) = NaN; +chanLabels = cell(1,length(Lbl)); + +hold on; +colorLabels = []; + +if isfield(lay, 'outline') && strcmp(cfg.showoutline, 'yes') + for i=1:length(lay.outline) + if ~isempty(lay.outline{i}) + tmpX = lay.outline{i}(:,1); + tmpY = lay.outline{i}(:,2); + h = line(tmpX, tmpY); + set(h, 'color', 'k'); + set(h, 'linewidth', 2); + end + end +end + +% Plot each data set: +for k=1:length(varargin) + P = getsubfield(varargin{k}, cfg.zparam); + Labels = getfield(varargin{k}, 'label'); + + if length(varargin) > 1 + if ischar(GRAPHCOLOR); colorLabels = [colorLabels inputname(k+1) '=' GRAPHCOLOR(k+1) '\n']; + elseif isnumeric(GRAPHCOLOR); colorLabels = [colorLabels inputname(k+1) '=' num2str(GRAPHCOLOR(k+1,:)) '\n']; + end + end + + if ischar(GRAPHCOLOR); color = GRAPHCOLOR(k+1); + elseif isnumeric(GRAPHCOLOR); color = GRAPHCOLOR(k+1,:); + end + + for m=1:length(Lbl) + l = cellstrmatch(Lbl(m),Labels); + if ~isempty(l) + if ~isempty(cfg.maskparameter) + mask = varargin{1}.(cfg.maskparameter)(l,:); + else + mask = []; + end + % Plot ER: + plotWnd(varargin{k}.(cfg.xparam),P(l,:),xidc,[xmin xmax],[ymin ymax], ... + X(m), ... + Y(m), ... + Width(m), ... + Height(m), ... + Lbl(m), ... + cfg, color, mask) ... + ; + + % Keep ER plot coordinates (at centre of ER plot), and channel labels (will be stored in the figure's UserData struct): + chanX(m) = X(m) + 0.5 * Width(m); + chanY(m) = Y(m) + 0.5 * Height(m); + chanLabels{m} = Lbl{m}; + end + end +end + +% Add the colors of the different datasets to the comment: +cfg.comment = [cfg.comment colorLabels]; + +% Write comment text: +l = cellstrmatch('COMNT',Lbl); +if ~isempty(l) + ft_plot_text(X(l),Y(l),sprintf(cfg.comment),'Fontsize',cfg.fontsize); +end + +% Plot scales: +l = cellstrmatch('SCALE',Lbl); +if ~isempty(l) + plotScales([xmin xmax],[ymin ymax],X(l),Y(l),Width(1),Height(1),cfg) +end + +% Make the figure interactive: +if strcmp(cfg.interactive, 'yes') + + % add the channel information to the figure + info = guidata(gcf); + info.x = lay.pos(:,1); + info.y = lay.pos(:,2); + info.label = lay.label; + guidata(gcf, info); + + set(gcf, 'WindowButtonUpFcn', {@ft_select_channel, 'multiple', true, 'callback', {@select_singleplotER, cfg, varargin{:}}, 'event', 'WindowButtonUpFcn'}); + set(gcf, 'WindowButtonDownFcn', {@ft_select_channel, 'multiple', true, 'callback', {@select_singleplotER, cfg, varargin{:}}, 'event', 'WindowButtonDownFcn'}); + set(gcf, 'WindowButtonMotionFcn', {@ft_select_channel, 'multiple', true, 'callback', {@select_singleplotER, cfg, varargin{:}}, 'event', 'WindowButtonMotionFcn'}); +end + +axis tight +axis off +if strcmp(cfg.box, 'yes') + abc = axis; + axis(abc + [-1 +1 -1 +1]*mean(abs(abc))/10) +end +orient landscape +hold off + +% Set renderer if specified +if ~isempty(cfg.renderer) + set(gcf, 'renderer', cfg.renderer) +end + + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function plotScales(xlim,ylim,xpos,ypos,width,height,cfg) +x1 = xpos; +x2 = xpos+width; +y1 = ypos; +y2 = ypos+width; +ft_plot_box([xpos xpos+width ypos ypos+height],'edgecolor','b') + +if xlim(1) <= 0 && xlim(2) >= 0 + xs = xpos+width*([0 0]-xlim(1))/(xlim(2)-xlim(1)); + ys = ypos+height*(ylim-ylim(1))/(ylim(2)-ylim(1)); + ft_plot_vector(xs,ys,'color','b'); +end + +if ylim(1) <= 0 && ylim(2) >= 0 + xs = xpos+width*(xlim-xlim(1))/(xlim(2)-xlim(1)); + ys = ypos+height*([0 0]-ylim(1))/(ylim(2)-ylim(1)); + ft_plot_vector(xs,ys,'color','b'); +end + +ft_plot_text( x1,y1,num2str(xlim(1),3),'rotation',90,'HorizontalAlignment','Right','VerticalAlignment','middle','Fontsize',cfg.fontsize); +ft_plot_text( x2,y1,num2str(xlim(2),3),'rotation',90,'HorizontalAlignment','Right','VerticalAlignment','middle','Fontsize',cfg.fontsize); +ft_plot_text( x2,y1,num2str(ylim(1),3),'HorizontalAlignment','Left','VerticalAlignment','bottom','Fontsize',cfg.fontsize); +ft_plot_text( x2,y2,num2str(ylim(2),3),'HorizontalAlignment','Left','VerticalAlignment','bottom','Fontsize',cfg.fontsize); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function plotWnd(x,y,xidc,xlim,ylim,xpos,ypos,width,height,label,cfg,color,mask) +set(gca,'FontSize',cfg.fontsize); + +x = x(xidc); +y = y(xidc); + +% Clip out of bounds y values: +y(find(y > ylim(2))) = ylim(2); +y(find(y < ylim(1))) = ylim(1); + +xs = xpos+width*(x-xlim(1))/(xlim(2)-xlim(1)); +ys = ypos+height*(y-ylim(1))/(ylim(2)-ylim(1)); + +if isempty(mask) || (~isempty(mask) && strcmp(cfg.maskstyle,'box')) + ft_plot_vector(xs, ys, 'color', color, 'style', cfg.linestyle, 'linewidth', cfg.linewidth) +elseif ~isempty(mask) && ~strcmp(cfg.maskstyle,'box') % ft_plot_vector doesnt support boxes higher than ydata yet, so a separate option remains below + ft_plot_vector(xs, ys, 'color', color, 'style', cfg.linestyle, 'highlight', mask, 'highlightstyle', cfg.maskstyle, 'linewidth', cfg.linewidth) +end + +if strcmp(cfg.showlabels,'yes') + ft_plot_text(xpos,ypos+1.0*height,label,'Fontsize',cfg.fontsize) +end + +% Draw axes: +if strcmp(cfg.axes,'yes') || strcmp(cfg.axes, 'xy') + % Draw y axis + xs = xpos+width*([0 0]-xlim(1))/(xlim(2)-xlim(1)); + ys = ypos+height*(ylim-ylim(1))/(ylim(2)-ylim(1)); + ft_plot_vector(xs,ys,'color','k') + % Draw x axis + xs = xpos+width*(xlim-xlim(1))/(xlim(2)-xlim(1)); + ys = ypos+height*([0 0]-ylim(1))/(ylim(2)-ylim(1)); + ft_plot_vector(xs,ys,'color','k') + +elseif strcmp(cfg.axes,'x') + % Draw x axis + xs = xpos+width*(xlim-xlim(1))/(xlim(2)-xlim(1)); + ys = ypos+height*([0 0]-ylim(1))/(ylim(2)-ylim(1)); + ft_plot_vector(xs,ys,'color','k') + +elseif strcmp(cfg.axes,'y') + % Draw y axis + xs = xpos+width*([0 0]-xlim(1))/(xlim(2)-xlim(1)); + ys = ypos+height*(ylim-ylim(1))/(ylim(2)-ylim(1)); + ft_plot_vector(xs,ys,'color','k') +end + + +% Draw box around plot: +if strcmp(cfg.box,'yes') + ft_plot_box([xpos xpos+width ypos ypos+height],'edgecolor','k') +end + +% Add boxes when masktyle is box, ft_plot_vector doesnt support boxes higher than ydata yet, so this code is left here +if ~isempty(mask) && strcmp(cfg.maskstyle, 'box') + % determine how many boxes + foundbeg = 0; + foundend = 0; + beg = []; + eind = []; + for i = 1:length(mask) + if ~foundbeg && mask(i) == 1 + beg(length(beg)+1) = i; + foundbeg = 1; + foundend = 0; + elseif ~foundbeg && mask(i) == 0 + %next + elseif ~foundend && mask(i) == 1 + %next + elseif ~foundend && mask(i) == 0 + eind(length(eind)+1) = i-1; + foundend = 1; + foundbeg = 0; + end + end + if length(eind) == length(beg)-1 + eind(length(eind)+1) = length(mask); + end + numbox = length(beg); + for i = 1:numbox + xmaskmin = xpos+width*(x(beg(i))-xlim(1))/(xlim(2)-xlim(1)); + xmaskmax = xpos+width*(x(eind(i))-xlim(1))/(xlim(2)-xlim(1)); + %plot([xmaskmin xmaskmax xmaskmax xmaskmin xmaskmin],[ypos ypos ypos+height ypos+height ypos],'r'); + hs = patch([xmaskmin xmaskmax xmaskmax xmaskmin xmaskmin],[ypos ypos ypos+height ypos+height ypos], [.6 .6 .6]); + set(hs, 'EdgeColor', 'none'); + end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function l = cellstrmatch(str,strlist) +l = []; +for k=1:length(strlist) + if strcmp(char(str),char(strlist(k))) + l = [l k]; + end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION which is called after selecting channels in case of cfg.cohrefchannel='gui' +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function select_multiplotER(label, cfg, varargin) +cfg.cohrefchannel = label; +fprintf('selected cfg.cohrefchannel = ''%s''\n', cfg.cohrefchannel); +p = get(gcf, 'Position'); +f = figure; +set(f, 'Position', p); +ft_multiplotER(cfg, varargin{:}); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION which is called after selecting channels in case of cfg.interactive='yes' +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function select_singleplotER(label, cfg, varargin) +if ~isempty(label) + cfg.xlim = 'maxmin'; + cfg.channel = label; + fprintf('selected cfg.channel = {'); + for i=1:(length(cfg.channel)-1) + fprintf('''%s'', ', cfg.channel{i}); + end + fprintf('''%s''}\n', cfg.channel{end}); + p = get(gcf, 'Position'); + f = figure; + set(f, 'Position', p); + ft_singleplotER(cfg, varargin{:}); +end -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_multiplotTFR.m b/external/fieldtrip/ft_multiplotTFR.m index b84b9b2..382bd88 100644 --- a/external/fieldtrip/ft_multiplotTFR.m +++ b/external/fieldtrip/ft_multiplotTFR.m @@ -1,11 +1,482 @@ -function varargout = funname(varargin); +function [cfg] = ft_multiplotTFR(cfg, data) -% this is a SPM wrapper around a FieldTrip function +% ft_multiplotTFR plots time-frequency representations of power or coherence in a +% topographical layout. The plots of the indivual sensors are arranged according +% to their location specified in the layout. +% +% Use as: +% ft_multiplotTFR(cfg, data) +% +% The data can be a time-frequency representation of power or coherence that +% was computed using the FT_FREQANALYSIS or FT_FREQDESCRIPTIVES functions. +% +% The configuration can have the following parameters: +% cfg.xparam = field to be plotted on x-axis (default depends on data.dimord) +% 'time' +% cfg.yparam = field to be plotted on y-axis (default depends on data.dimord) +% 'freq' +% cfg.zparam = field to be represented as color (default depends on data.dimord) +% 'powspctrm' or 'cohspctrm' +% cfg.maskparameter = field in the data to be used for opacity masking of data +% cfg.maskstyle = style used to mask nans, 'opacity' or 'saturation' (default = 'opacity') +% use 'saturation' when saving to vector-format (like *.eps) to avoid all +% sorts of image-problems (currently only possible with a white backgroud) +% cfg.xlim = 'maxmin' or [xmin xmax] (default = 'maxmin') +% cfg.ylim = 'maxmin' or [ymin ymax] (default = 'maxmin') +% cfg.zlim = 'maxmin','maxabs' or [zmin zmax] (default = 'maxmin') +% cfg.cohrefchannel = name of reference channel for visualising coherence, can be 'gui' +% cfg.baseline = 'yes','no' or [time1 time2] (default = 'no'), see FT_FREQBASELINE +% cfg.baselinetype = 'absolute' or 'relative' (default = 'absolute') +% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') +% cfg.box = 'yes', 'no' (default = 'no' if maskparameter given default = 'yes') +% Draw a box around each graph +% cfg.colorbar = 'yes', 'no' (default = 'no') +% cfg.colormap = any sized colormap, see COLORMAP +% cfg.comment = string of text (default = date + zlimits) +% Add 'comment' to graph (according to COMNT in the layout) +% cfg.showlabels = 'yes', 'no' (default = 'no') +% cfg.showoutline = 'yes', 'no' (default = 'no') +% cfg.fontsize = font size of comment and labels (if present) (default = 8) +% cfg.interactive = Interactive plot 'yes' or 'no' (default = 'no') +% In a interactive plot you can select areas and produce a new +% interactive plot when a selected area is clicked. Multiple areas +% can be selected by holding down the SHIFT key. +% cfg.masknans = 'yes' or 'no' (default = 'yes') +% cfg.renderer = 'painters', 'zbuffer',' opengl' or 'none' (default = []) +% cfg.layout = specify the channel layout for plotting using one of +% the following ways: +% +% The layout defines how the channels are arranged and what the size of each +% subplot is. You can specify the layout in a variety of ways: +% - you can provide a pre-computed layout structure (see ft_prepare_layout) +% - you can give the name of an ascii layout file with extension *.lay +% - you can give the name of an electrode file +% - you can give an electrode definition, i.e. "elec" structure +% - you can give a gradiometer definition, i.e. "grad" structure +% If you do not specify any of these and the data structure contains an +% electrode or gradiometer structure (common for MEG data, since the header +% of the MEG datafile contains the gradiometer information), that will be +% used for creating a layout. If you want to have more fine-grained control +% over the layout of the subplots, you should create your own layout file. +% +% See also: +% ft_multiplotER, ft_singleplotER, ft_singleplotTFR, ft_topoplotER, ft_topoplotTFR, +% ft_prepare_layout -% this part is variable -prefix = 'ft_'; +% Undocumented local options: +% cfg.channel +% cfg.layoutname +% cfg.xparam +% cfg.zparam +% cfg.inputfile = one can specifiy preanalysed saved data as input +% The data should be provided in a cell array + +% +% This function depends on FT_FREQBASELINE which has the following options: +% cfg.baseline, documented +% cfg.baselinetype, documented + +% Copyright (C) 2003-2006, Ole Jensen +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_multiplotTFR.m 1431 2010-07-20 07:47:55Z roboos $ + +fieldtripdefs + +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +clf + +% set default for inputfile +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end + +% load optional given inputfile as data +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + end +end + +% for backward compatibility with old data structures +data = checkdata(data); + +% check if the input cfg is valid for this function +cfg = checkconfig(cfg, 'renamedval', {'zlim', 'absmax', 'maxabs'}); + +% Set the defaults: +if ~isfield(cfg,'baseline'), cfg.baseline = 'no'; end +if ~isfield(cfg,'baselinetype'), cfg.baselinetype = 'absolute'; end +if ~isfield(cfg,'trials'), cfg.trials = 'all'; end +if ~isfield(cfg,'xlim'), cfg.xlim = 'maxmin'; end +if ~isfield(cfg,'ylim'), cfg.ylim = 'maxmin'; end +if ~isfield(cfg,'zlim'), cfg.zlim = 'maxmin'; end +if ~isfield(cfg,'colorbar'), cfg.colorbar = 'no'; end +if ~isfield(cfg,'comment'), cfg.comment = date; end +if ~isfield(cfg,'showlabels'), cfg.showlabels = 'no'; end +if ~isfield(cfg,'showoutline'), cfg.showoutline = 'no'; end +if ~isfield(cfg,'channel'), cfg.channel = 'all'; end +if ~isfield(cfg,'fontsize'), cfg.fontsize = 8; end +if ~isfield(cfg,'interactive'), cfg.interactive = 'no'; end +if ~isfield(cfg,'renderer'), cfg.renderer = []; end % let matlab decide on default +if ~isfield(cfg,'masknans'), cfg.masknans = 'yes'; end +if ~isfield(cfg,'maskparameter'), cfg.maskparameter = []; end +if ~isfield(cfg,'maskstyle'), cfg.maskstyle = 'opacity'; end +if ~isfield(cfg,'box') + if ~isempty(cfg.maskparameter) + cfg.box = 'yes'; + else + cfg.box = 'no'; + end +end + +% Set x/y/zparam defaults according to data.dimord value: +if strcmp(data.dimord, 'chan_freq_time') + if ~isfield(cfg, 'xparam'), cfg.xparam='time'; end + if ~isfield(cfg, 'yparam'), cfg.yparam='freq'; end + if ~isfield(cfg, 'zparam'), cfg.zparam='powspctrm'; end +elseif strcmp(data.dimord, 'subj_chan_freq_time') || strcmp(data.dimord, 'rpt_chan_freq_time') + if isfield(data, 'crsspctrm'), data = rmfield(data, 'crsspctrm'); end % on the fly computation of coherence spectrum is not supported + tmpcfg = []; + tmpcfg.trials = cfg.trials; + tmpcfg.jackknife = 'no'; + if isfield(cfg, 'zparam') && strcmp(cfg.zparam,'cohspctrm') + % on the fly computation of coherence spectrum is not supported + elseif isfield(cfg, 'zparam') && ~strcmp(cfg.zparam,'powspctrm') + % freqdesctiptives will only work on the powspctrm field, hence a temporary copy of the data is needed + tempdata.dimord = data.dimord; + tempdata.freq = data.freq; + tempdata.time = data.time; + tempdata.label = data.label; + tempdata.powspctrm = data.(cfg.zparam); + tempdata.cfg = data.cfg; + tempdata = ft_freqdescriptives(tmpcfg, tempdata); + data.(cfg.zparam) = tempdata.powspctrm; + clear tempdata + else + data = ft_freqdescriptives(tmpcfg, data); + end + if ~isfield(cfg, 'xparam'), cfg.xparam='time'; end + if ~isfield(cfg, 'yparam'), cfg.yparam='freq'; end + if ~isfield(cfg, 'zparam'), cfg.zparam='powspctrm'; end +end + +% Old style coherence plotting with cohtargetchannel is no longer supported: +cfg = checkconfig(cfg, 'unused', {'cohtargetchannel'}); + +% Read or create the layout that will be used for plotting: +lay = ft_prepare_layout(cfg, data); +cfg.layout = lay; + +% Check for unconverted coherence spectrum data: +if (strcmp(cfg.zparam,'cohspctrm')), + % A reference channel is required: + if ~isfield(cfg,'cohrefchannel'), + error('no reference channel specified'); + end + + if strcmp(cfg.cohrefchannel, 'gui') + % Open a single figure with the channel layout, the user can click on a reference channel + h = clf; + ft_plot_lay(lay, 'box', false); + title('Select the reference channel by clicking on it...'); + info = []; + info.x = lay.pos(:,1); + info.y = lay.pos(:,2); + info.label = lay.label; + guidata(h, info); + set(gcf, 'WindowButtonUpFcn', {@ft_select_channel, 'callback', {@select_multiplotTFR, cfg, data}}); + return + end + + % Convert 2-dimensional channel matrix to a single dimension: + sel1 = strmatch(cfg.cohrefchannel, data.labelcmb(:,2)); + sel2 = strmatch(cfg.cohrefchannel, data.labelcmb(:,1)); + fprintf('selected %d channels for coherence\n', length(sel1)+length(sel2)); + data.cohspctrm = data.cohspctrm([sel1;sel2],:,:); + data.label = [data.labelcmb(sel1,1);data.labelcmb(sel2,2)]; + data.labelcmb = data.labelcmb([sel1;sel2],:); + data = rmfield(data, 'labelcmb'); +end + +% Apply baseline correction: +if ~strcmp(cfg.baseline, 'no') + data = ft_freqbaseline(cfg, data); +end + +% Get physical x-axis range: +if strcmp(cfg.xlim,'maxmin') + xmin = min(data.(cfg.xparam)); + xmax = max(data.(cfg.xparam)); +else + xmin = cfg.xlim(1); + xmax = cfg.xlim(2); +end + +% Find corresponding x-axis bins: +xidc = find(data.(cfg.xparam) >= xmin & data.(cfg.xparam) <= xmax); + +% Align physical x-axis range to the array bins: +xmin = data.(cfg.xparam)(xidc(1)); +xmax = data.(cfg.xparam)(xidc(end)); + +% Get physical y-axis range: +if strcmp(cfg.ylim,'maxmin') + ymin = min(data.(cfg.yparam)); + ymax = max(data.(cfg.yparam)); +else + ymin = cfg.ylim(1); + ymax = cfg.ylim(2); +end + +% Find corresponding y-axis bins: +yidc = find(data.(cfg.yparam) >= ymin & data.(cfg.yparam) <= ymax); + +% Align physical y-axis range to the array bins: +ymin = data.(cfg.yparam)(yidc(1)); +ymax = data.(cfg.yparam)(yidc(end)); + +% test if X and Y are linearly spaced (to within 10^-12): % FROM UIMAGE +x = data.(cfg.xparam)(xidc); +y = data.(cfg.yparam)(yidc); +dx = min(diff(x)); % smallest interval for X +dy = min(diff(y)); % smallest interval for Y +evenx = all(abs(diff(x)/dx-1)<1e-12); % true if X is linearly spaced +eveny = all(abs(diff(y)/dy-1)<1e-12); % true if Y is linearly spaced + +if ~evenx || ~eveny + warning('(one of the) axis is/are not evenly spaced, but plots are made as if axis are linear') +end + +% Select the channels in the data that match with the layout: +[seldat, sellay] = match_str(data.label, lay.label); +if isempty(seldat) + error('labels in data and labels in layout do not match'); +end + +datavector = data.(cfg.zparam)(seldat,yidc,xidc); +chanX = lay.pos(sellay, 1); +chanY = lay.pos(sellay, 2); +chanWidth = lay.width(sellay); +chanHeight = lay.height(sellay); +chanLabels = lay.label(sellay); +if ~isempty(cfg.maskparameter) + maskvector = data.(cfg.maskparameter)(seldat,yidc,xidc); +end + +% Get physical z-axis range (color axis): +if strcmp(cfg.zlim,'maxmin') + zmin = min(datavector(:)); + zmax = max(datavector(:)); +elseif strcmp(cfg.zlim,'maxabs') + zmin = -max(abs(datavector(:))); + zmax = max(abs(datavector(:))); +else + zmin = cfg.zlim(1); + zmax = cfg.zlim(2); +end + +hold on; + +if isfield(lay, 'outline') && strcmp(cfg.showoutline, 'yes') + for i=1:length(lay.outline) + if ~isempty(lay.outline{i}) + tmpX = lay.outline{i}(:,1); + tmpY = lay.outline{i}(:,2); + h = line(tmpX, tmpY); + set(h, 'color', 'k'); + set(h, 'linewidth', 2); + end + end +end + +% set colormap +if isfield(cfg,'colormap') + if size(cfg.colormap,2)~=3, error('singleplotTFR(): Colormap must be a n x 3 matrix'); end + set(gcf,'colormap',cfg.colormap); +end; + +% Plot channels: +for k=1:length(seldat) + % Get cdata: + cdata = squeeze(datavector(k,:,:)); + if ~isempty(cfg.maskparameter) + mdata = squeeze(maskvector(k,:,:)); + end + + % Get axes for this panel + xas = (chanX(k) + linspace(0,1,size(cdata,2))*chanWidth(k)) - chanWidth(k)/2; + yas = (chanY(k) + linspace(0,1,size(cdata,1))*chanHeight(k)) - chanHeight(k)/2; + + % Draw plot (and mask Nan's with maskfield if requested) + if isequal(cfg.masknans,'yes') && isempty(cfg.maskparameter) + mask = ~isnan(cdata); + mask = double(mask); + ft_plot_matrix(xas, yas, cdata,'clim',[zmin zmax],'tag','cip','highlightstyle',cfg.maskstyle,'highlight', mask) + elseif isequal(cfg.masknans,'yes') && ~isempty(cfg.maskparameter) + mask = ~isnan(cdata); + mask = mask .* mdata; + mask = double(mask); + ft_plot_matrix(xas, yas, cdata,'clim',[zmin zmax],'tag','cip','highlightstyle',cfg.maskstyle,'highlight', mask) + elseif isequal(cfg.masknans,'no') && ~isempty(cfg.maskparameter) + mask = mdata; + mask = double(mask); + ft_plot_matrix(xas, yas, cdata,'clim',[zmin zmax],'tag','cip','highlightstyle',cfg.maskstyle,'highlight', mask) + else + ft_plot_matrix(xas, yas, cdata,'clim',[zmin zmax],'tag','cip') + end + % Currently the handle isn't being used below, this is here for possible use in the future + h = findobj('tag','cip'); + + % Draw box around plot + if strcmp(cfg.box,'yes') + xstep = xas(2) - xas(1); ystep = yas(2) - yas(1); + xvalmin(1:length(yas)+2) = min(xas)-(0.5*xstep); xvalmax(1:length(yas)+2) = max(xas)+(0.5*xstep); yvalmin(1:length(xas)+2) = min(yas)-(0.5*ystep); yvalmax(1:length(xas)+2) = max(yas)+(0.5*ystep); + xas2 = [xvalmin(1) xas xvalmax(1)]; yas2 = [yvalmin(1) yas yvalmax(1)]; + ft_plot_box([min(xas2) max(xas2) min(yas2) max(yas2)]) + end + + % Draw channel labels: + if strcmp(cfg.showlabels,'yes') + ft_plot_text(chanX(k)-chanWidth(k)/2, chanY(k)+chanHeight(k)/2, sprintf(' %0s\n ', chanLabels{k}), 'Fontsize', cfg.fontsize); + end +end + +% write comment: +k = cellstrmatch('COMNT',lay.label); +if ~isempty(k) + comment = cfg.comment; + comment = sprintf('%0s\nxlim=[%.3g %.3g]', comment, xmin, xmax); + comment = sprintf('%0s\nylim=[%.3g %.3g]', comment, ymin, ymax); + comment = sprintf('%0s\nzlim=[%.3g %.3g]', comment, zmin, zmax); + ft_plot_text(lay.pos(k,1), lay.pos(k,2), sprintf(comment), 'Fontsize', cfg.fontsize); +end + +% plot scale: +k = cellstrmatch('SCALE',lay.label); +if ~isempty(k) + % Get average cdata across channels: + cdata = squeeze(mean(datavector, 1)); + + % Get axes for this panel: + xas = (lay.pos(k,1) + linspace(0,1,size(cdata,2))*lay.width(k)); + yas = (lay.pos(k,2) + linspace(0,1,size(cdata,1))*lay.height(k)); + + % Draw plot (and mask Nan's with maskfield if requested) + if isequal(cfg.masknans,'yes') && isempty(cfg.maskparameter) + mask = ~isnan(cdata); + mask = double(mask); + ft_plot_matrix(xas, yas, cdata,'clim',[zmin zmax],'tag','cip','highlightstyle',cfg.maskstyle,'highlight', mask) + elseif isequal(cfg.masknans,'yes') && ~isempty(cfg.maskparameter) + mask = ~isnan(cdata); + mask = mask .* mdata; + mask = double(mask); + ft_plot_matrix(xas, yas, cdata,'clim',[zmin zmax],'tag','cip','highlightstyle',cfg.maskstyle,'highlight', mask) + elseif isequal(cfg.masknans,'no') && ~isempty(cfg.maskparameter) + mask = mdata; + mask = double(mask); + ft_plot_matrix(xas, yas, cdata,'clim',[zmin zmax],'tag','cip','highlightstyle',cfg.maskstyle,'highlight', mask) + else + ft_plot_matrix(xas, yas, cdata,'clim',[zmin zmax],'tag','cip') + end + % Currently the handle isn't being used below, this is here for possible use in the future + h = findobj('tag','cip'); + +end + + +% plot colorbar: +if isfield(cfg, 'colorbar') && (strcmp(cfg.colorbar, 'yes')) + colorbar; +end + +% Make the figure interactive: +if strcmp(cfg.interactive, 'yes') + % add the channel information to the figure + info = guidata(gcf); + info.x = lay.pos(:,1); + info.y = lay.pos(:,2); + info.label = lay.label; + guidata(gcf, info); + + set(gcf, 'WindowButtonUpFcn', {@ft_select_channel, 'multiple', true, 'callback', {@select_singleplotTFR, cfg, data}, 'event', 'WindowButtonUpFcn'}); + set(gcf, 'WindowButtonDownFcn', {@ft_select_channel, 'multiple', true, 'callback', {@select_singleplotTFR, cfg, data}, 'event', 'WindowButtonDownFcn'}); + set(gcf, 'WindowButtonMotionFcn', {@ft_select_channel, 'multiple', true, 'callback', {@select_singleplotTFR, cfg, data}, 'event', 'WindowButtonMotionFcn'}); +end + +axis tight +axis off +if strcmp(cfg.box, 'yes') + abc = axis; + axis(abc + [-1 +1 -1 +1]*mean(abs(abc))/10) +end +orient landscape +hold off + +% Set renderer if specified +if ~isempty(cfg.renderer) + set(gcf, 'renderer', cfg.renderer) +end + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function l = cellstrmatch(str,strlist) +l = []; +for k=1:length(strlist) + if strcmp(char(str),char(strlist(k))) + l = [l k]; + end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION which is called by ft_select_channel in case cfg.cohrefchannel='gui' +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function select_multiplotTFR(label, cfg, varargin) +cfg.cohrefchannel = label; +fprintf('selected cfg.cohrefchannel = ''%s''\n', cfg.cohrefchannel); +p = get(gcf, 'Position'); +f = figure; +set(f, 'Position', p); +ft_multiplotTFR(cfg, varargin{:}); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION which is called after selecting channels in case of cfg.interactive='yes' +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function select_singleplotTFR(label, cfg, varargin) +if ~isempty(label) + cfg.xlim = 'maxmin'; + cfg.ylim = 'maxmin'; + cfg.channel = label; + fprintf('selected cfg.channel = {'); + for i=1:(length(cfg.channel)-1) + fprintf('''%s'', ', cfg.channel{i}); + end + fprintf('''%s''}\n', cfg.channel{end}); + p = get(gcf, 'Position'); + f = figure; + set(f, 'Position', p); + ft_singleplotTFR(cfg, varargin{:}); +end -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_mvaranalysis.m b/external/fieldtrip/ft_mvaranalysis.m new file mode 100644 index 0000000..0669bea --- /dev/null +++ b/external/fieldtrip/ft_mvaranalysis.m @@ -0,0 +1,375 @@ +function [mvardata] = ft_mvaranalysis(cfg, data) + +% FT_MVARANALYSIS performs multivariate autoregressive modeling on +% time series data over multiple trials. +% +% Use as +% [mvardata] = ft_mvaranalysis(cfg, data) +% +% The input data should be organised in a structure as obtained from +% the FT_PREPROCESSING function. The configuration depends on the type +% of computation that you want to perform. +% The output is a data structure of datatype 'mvar' which contains the +% multivariate autoregressive coefficients in the field coeffs, and the +% covariance of the residuals in the field noisecov. +% +% The configuration should contain: +% cfg.toolbox = the name of the toolbox containing the function for the +% actual computation of the ar-coefficients +% this can be 'biosig' (default) or 'bsmart' +% you should have a copy of the specified toolbox in order +% to use mvaranalysis (both can be downloaded directly). +% cfg.mvarmethod = scalar (only required when cfg.toolbox = 'biosig'). +% default is 2, relates to the algorithm used for the +% computation of the AR-coefficients by mvar.m +% cfg.order = scalar, order of the autoregressive model (default=10) +% cfg.channel = 'all' (default) or list of channels for which the model +% is fitted. +% cfg.keeptrials = 'no' (default) or 'yes' specifies whether the coefficients +% are estimated for each trial seperately, or on the +% concatenated data +% cfg.jackknife = 'no' (default) or 'yes' specifies whether the coefficients +% are estimated for all leave-one-out sets of trials +% cfg.zscore = 'no' (default) or 'yes' specifies whether the channel data +% are z-transformed prior to the model fit. This may be +% necessary if the magnitude of the signals is very different +% e.g. when fitting a model to combined MEG/EMG data +% cfg.blc = 'yes' (default) or 'no' explicit removal of DC-offset +% +% ft_mvaranalysis can be used to obtain one set of coefficients for +% the whole common time axis defined in the data. It will throw an error +% if the trials are of variable length, or if the time axes of the trials +% are not equal to one another. +% +% ft_mvaranalysis can be also used to obtain time-dependent sets of +% coefficients based on a sliding window. In this case the input cfg +% should contain: +% +% cfg.t_ftimwin = the width of the sliding window on which the coefficients +% are estimated +% cfg.toi = [t1 t2 ... tx] the time points at which the windows are +% centered + +% Undocumented local options: +% cfg.keeptapers +% cfg.taper +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk + +% Copyright (C) 2009, Jan-Mathijs Schoffelen +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_mvaranalysis.m 1247 2010-06-17 12:07:18Z timeng $ + +% set default configurations +if ~isfield(cfg, 'toolbox'), cfg.toolbox = 'biosig'; end +if ~isfield(cfg, 'mvarmethod'), cfg.mvarmethod = 2; end +if ~isfield(cfg, 'order'), cfg.order = 10; end +if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end +if ~isfield(cfg, 'keeptrials'), cfg.keeptrials = 'no'; end +if ~isfield(cfg, 'jackknife'), cfg.jackknife = 'no'; end +if ~isfield(cfg, 'zscore'), cfg.zscore = 'no'; end +if ~isfield(cfg, 'feedback'), cfg.feedback = 'textbar'; end +if ~isfield(cfg, 'blc'), cfg.blc = 'yes'; end +if ~isfield(cfg, 'toi'), cfg.toi = []; end +if ~isfield(cfg, 't_ftimwin'), cfg.t_ftimwin = []; end +if ~isfield(cfg, 'keeptapers'), cfg.keeptapers = 'yes'; end +if ~isfield(cfg, 'taper'), cfg.taper = 'rectwin'; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +%check whether the requested toolbox is present +switch cfg.toolbox + case 'biosig' + hastoolbox('biosig', 1); + nnans = cfg.order; + case 'bsmart' + hastoolbox('bsmart', 1); + nnans = 0; + otherwise + error('toolbox %s is not yet supported', cfg.toolbox); +end + +% load optional given inputfile as data +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + end +end + +%check the input-data +data = checkdata(data, 'datatype', 'raw', 'hastrialdef', 'yes'); + +%check configurations +switch cfg.toolbox + case 'biosig' + cfg = checkconfig(cfg, 'required', 'mvarmethod'); + case 'bsmart' + %nothing extra required +end + +if isempty(cfg.toi) && isempty(cfg.t_ftimwin) + %fit model to entire data segment + ok = 1; + for k = 1:numel(data.trial) + if any(data.time{k}~=data.time{1}), + ok = 0; + break + end + end + + if ~ok + error('time axes of all trials should be identical'); + else + cfg.toi = mean(data.time{1}([1 end])) + 0.5/data.fsample; + cfg.t_ftimwin = data.time{1}(end)-data.time{1}(1) + 1/data.fsample; + end + +elseif ~isempty(cfg.toi) && ~isempty(cfg.t_ftimwin) + %do sliding window approach +else + error('cfg should contain both cfg.toi and cfg.t_ftimwin'); +end + +cfg.channel = ft_channelselection(cfg.channel, data.label); + +keeprpt = strcmp(cfg.keeptrials, 'yes'); +keeptap = strcmp(cfg.keeptapers, 'yes'); +dojack = strcmp(cfg.jackknife, 'yes'); +dozscore = strcmp(cfg.zscore, 'yes'); + +if ~keeptap, error('not keeping tapers is not possible yet'); end +if dojack && keeprpt, error('you cannot simultaneously keep trials and do jackknifing'); end + +tfwin = round(data.fsample.*cfg.t_ftimwin); +ntrl = length(data.trial); +ntoi = length(cfg.toi); +chanindx = match_str(data.label, cfg.channel); +nchan = length(chanindx); +label = data.label(chanindx); + +ncmb = nchan*nchan; +cmbindx1 = repmat(chanindx(:), [1 nchan]); +cmbindx2 = repmat(chanindx(:)', [nchan 1]); +labelcmb = [data.label(cmbindx1(:)) data.label(cmbindx2(:))]; + +%---think whether this makes sense at all +if strcmp(cfg.taper, 'dpss') + % create a sequence of DPSS (Slepian) tapers + % ensure that the input arguments are double precision + tap = double_dpss(tfwin,tfwin*(cfg.tapsmofrq./data.fsample))'; + tap = tap(1,:); %only use first 'zero-order' taper +elseif strcmp(cfg.taper, 'sine') + tap = sine_taper(tfwin, tfwin*(cfg.tapsmofrq./data.fsample))'; + tap = tap(1,:); +else + tap = window(cfg.taper, tfwin)'; + tap = tap./norm(tap); +end +ntap = size(tap,1); + +%---preprocess data if necessary +%---blc +if strcmp(cfg.blc, 'yes'), + tmpcfg = []; + tmpcfg.blc = 'yes'; + tmpcfg.blcwindow = cfg.toi([1 end]) + cfg.t_ftimwin.*[-0.5 0.5]; + data = ft_preprocessing(tmpcfg, data); +else + %do nothing +end + +%---zscore +if dozscore, + zwindow = cfg.toi([1 end]) + cfg.t_ftimwin.*[-0.5 0.5]; + sumval = 0; + sumsqr = 0; + numsmp = 0; + trlindx = []; + for k = 1:ntrl + begsmp = nearest(data.time{k}, zwindow(1)); + endsmp = nearest(data.time{k}, zwindow(2)); + if endsmp>=begsmp, + sumval = sumval + sum(data.trial{k}(:, begsmp:endsmp), 2); + sumsqr = sumsqr + sum(data.trial{k}(:, begsmp:endsmp).^2, 2); + numsmp = numsmp + endsmp - begsmp + 1; + trlindx = [trlindx; k]; + end + end + datavg = sumval./numsmp; + datstd = sqrt(sumsqr./numsmp - (sumval./numsmp).^2); + + data.trial = data.trial(trlindx); + data.time = data.time(trlindx); + ntrl = length(trlindx); + for k = 1:ntrl + rvec = ones(1,size(data.trial{k},2)); + data.trial{k} = (data.trial{k} - datavg*rvec)./(datstd*rvec); + end +else + %do nothing +end + +%---generate time axis +maxtim = -inf; +mintim = inf; +for k = 1:ntrl + maxtim = max(maxtim, data.time{k}(end)); + mintim = min(mintim, data.time{k}(1)); +end +timeaxis = mintim:1./data.fsample:maxtim; + +%---allocate memory +if keeprpt || dojack + coeffs = zeros(length(data.trial), nchan, nchan, cfg.order, ntoi, ntap); + noisecov = zeros(length(data.trial), nchan, nchan, ntoi, ntap); +else + coeffs = zeros(1, nchan, nchan, cfg.order, ntoi, ntap); + noisecov = zeros(1, nchan, nchan, ntoi, ntap); +end + +%---loop over the tois +progress('init', cfg.feedback, 'computing MAR-model'); +for j = 1:ntoi + progress(j/ntoi, 'processing timewindow %d from %d\n', j, ntoi); + sample = nearest(timeaxis, cfg.toi(j)); + cfg.toi(j) = timeaxis(sample); + + tmpcfg = []; + tmpcfg.toilim = [timeaxis(sample-floor(tfwin/2)) timeaxis(sample+ceil(tfwin/2)-1)]; + tmpcfg.feedback = 'no'; + tmpcfg.minlength= 'maxperlen'; + tmpdata = ft_redefinetrial(tmpcfg, data); + + cfg.toi(j) = mean(tmpdata.time{1}([1 end]))+0.5./data.fsample; %FIXME think about this + + %---create cell-array indexing which original trials should go into each replicate + rpt = {}; + nrpt = numel(tmpdata.trial); + if dojack + for k = 1:nrpt + rpt{k,1} = setdiff(1:nrpt,k); + end + elseif keeprpt + for k = 1:nrpt + rpt{k,1} = k; + end + else + rpt{1} = 1:numel(tmpdata.trial); + nrpt = 1; + end + + for rlop = 1:nrpt + + for m = 1:ntap + %---construct data-matrix + dat = catnan(tmpdata.trial, chanindx, rpt{rlop}, tap(m,:), nnans); + + %---estimate autoregressive model + switch cfg.toolbox + case 'biosig' + [ar, rc, pe] = mvar(dat', cfg.order, cfg.mvarmethod); + + %---compute noise covariance + tmpnoisecov = pe(:,nchan*cfg.order+1:nchan*(cfg.order+1)); + case 'bsmart' + [ar, tmpnoisecov] = armorf(dat, numel(rpt{rlop}), size(tmpdata.trial{1},2), cfg.order); + ar = -ar; %convention is swapped sign with respect to biosig + %FIXME check which is which: X(t) = A1*X(t-1) + ... + An*X(t-n) + E + %the other is then X(t) + A1*X(t-1) + ... + An*X(t-n) = E + end + coeffs(rlop,:,:,:,j,m) = reshape(ar, [nchan nchan cfg.order]); + + %---rescale noisecov if necessary + if dozscore, + noisecov(rlop,:,:,j,m) = diag(datstd)*tmpnoisecov*diag(datstd); + else + noisecov(rlop,:,:,j,m) = tmpnoisecov; + end + dof(rlop,:,j) = numel(rpt{rlop}); + end %---tapers + + end %---replicates + +end %---tois +progress('close'); + +%---create output-structure +mvardata = []; +mvardata.label = label; +mvardata.time = cfg.toi; +mvardata.fsampleorig = data.fsample; + +if dojack, + mvardata.dimord = 'rptjck_chan_chan_lag_time'; +elseif keeprpt + mvardata.dimord = 'rpt_chan_chan_lag_time'; +else + mvardata.dimord = 'chan_chan_lag_time'; + siz = size(coeffs); + coeffs = reshape(coeffs, siz(2:end)); + siz = size(noisecov); + noisecov = reshape(noisecov, siz(2:end)); +end +mvardata.coeffs = coeffs; +mvardata.noisecov = noisecov; +mvardata.dof = dof; + +% remember the configuration details of the input data +try, cfg.previous = data.cfg; end + +mvardata.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', mvardata); % use the variable name "data" in the output file +end + +%---------------------------------------------------- +%subfunction to concatenate data with nans in between +function [datamatrix] = catnan(datacells, chanindx, trials, taper, nnans) + +nchan = numel(chanindx); +nsmp = size(datacells{1}, 2); +nrpt = numel(trials); + +%---initialize +datamatrix = zeros(nchan, nsmp*nrpt + nnans*(nrpt-1)) + nan; + +%---fill the matrix +for k = 1:nrpt + if k==1, + begsmp = (k-1)*nsmp + 1; + endsmp = k *nsmp ; + else + begsmp = (k-1)*(nsmp+nnans) + 1; + endsmp = k *(nsmp+nnans) - nnans; + end + datamatrix(:,begsmp:endsmp) = datacells{trials(k)}(chanindx,:).*taper(ones(nchan,1),:); +end + +%------------------------------------------------------ +%---subfunction to ensure that the first two input arguments are of double +% precision this prevents an instability (bug) in the computation of the +% tapers for Matlab 6.5 and 7.0 +function [tap] = double_dpss(a, b, varargin); +tap = dpss(double(a), double(b), varargin{:}); diff --git a/external/fieldtrip/ft_neighbourselection.m b/external/fieldtrip/ft_neighbourselection.m index b84b9b2..ea63e04 100644 --- a/external/fieldtrip/ft_neighbourselection.m +++ b/external/fieldtrip/ft_neighbourselection.m @@ -1,11 +1,178 @@ -function varargout = funname(varargin); +function neighbours = ft_neighbourselection(cfg,data) -% this is a SPM wrapper around a FieldTrip function +% FT_NEIGHBOURSELECTION finds the neighbours of the channels on the basis of a +% minimum neighbourhood distance (in cfg.neighbourdist). The positions of +% the channel are specified in a gradiometer or electrode configuration or +% from a layout. +% This configuration can be passed in three ways: +% (1) in a configuration field, +% (2) in a file whose name is passed in a configuration field, and that can be imported using READ_SENS, or +% (3) in a data field. +% +% Use as +% neighbours = ft_neighbourselection(cfg, data) +% +% The configuration can contain +% cfg.neighbourdist = number, maximum distance between neighbouring sensors +% cfg.elec = structure with EEG electrode positions +% cfg.grad = structure with MEG gradiometer positions +% cfg.elecfile = filename containing EEG electrode positions +% cfg.gradfile = filename containing MEG gradiometer positions +% cfg.layout = filename of the layout, see FT_PREPARE_LAYOUT +% cfg.feedback = 'yes' or 'no' (default = 'no') +% +% The following data fields may also be used by FT_NEIGHBOURSELECTION: +% data.elec = structure with EEG electrode positions +% data.grad = structure with MEG gradiometer positions +% +% The output: +% neighbours = definition of neighbours for each channel, +% which is structured like this: +% neighbours{1}.label = 'Fz'; +% neighbours{1}.neighblabel = {'Cz', 'F3', 'F3A', 'FzA', 'F4A', 'F4'}; +% neighbours{2}.label = 'Cz'; +% neighbours{2}.neighblabel = {'Fz', 'F4', 'RT', 'RTP', 'P4', 'Pz', 'P3', 'LTP', 'LT', 'F3'}; +% neighbours{3}.label = 'Pz'; +% neighbours{3}.neighblabel = {'Cz', 'P4', 'P4P', 'Oz', 'P3P', 'P3'}; +% etc. +% (Note that a channel is not considered to be a neighbour of itself.) -% this part is variable -prefix = 'ft_'; +% Copyright (C) 2006-2008, Eric Maris, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_neighbourselection.m 1262 2010-06-22 15:26:45Z roboos $ + +fieldtripdefs + +% set the defaults +if ~isfield(cfg, 'feedback'), cfg.feedback = 'no'; end + +% the default value for this is set later +% if ~isfield(cfg, 'neighbourdist'), cfg.neighbourdist = 4; end + +% get the the grad or elec if not present in the data +if isfield(cfg, 'grad') + fprintf('Obtaining the gradiometer configuration from the configuration.\n'); + sens = cfg.grad; +elseif isfield(cfg, 'elec') + fprintf('Obtaining the electrode configuration from the configuration.\n'); + sens = cfg.elec; +elseif isfield(cfg, 'gradfile') + fprintf('Obtaining the gradiometer configuration from a file.\n'); + sens = ft_read_sens(cfg.gradfile); +elseif isfield(cfg, 'elecfile') + fprintf('Obtaining the electrode configuration from a file.\n'); + sens = ft_read_sens(cfg.elecfile); +elseif isfield(cfg, 'layout') + fprintf('Using the 2-D layout to determine the neighbours\n'); + lay = ft_prepare_layout(cfg); + sens = []; + sens.label = lay.label; + sens.pnt = lay.pos; + sens.pnt(:,3) = 0; +elseif isfield(data, 'grad') + fprintf('Using the gradiometer configuration from the dataset.\n'); + sens = data.grad; +elseif isfield(data, 'elec') + fprintf('Using the electrode configuration from the dataset.\n'); + sens = data.elec; +end +if ~isstruct(sens) + error('Did not find gradiometer or electrode information.'); +end; + +% use a smart default for the distance +if ~isfield(cfg, 'neighbourdist'), + if isfield(sens, 'unit') && strcmp(sens.unit, 'cm') + cfg.neighbourdist = 4; + elseif isfield(sens, 'unit') && strcmp(sens.unit, 'mm') + cfg.neighbourdist = 40; + else + % don't provide a default in case the dimensions of the sensor array are unknown + end +end + +neighbours = compneighbstructfromgradelec(sens, cfg.neighbourdist); + +k = 0; +for i=1:length(neighbours) + k = k + length(neighbours{i}.neighblabel); +end +fprintf('there are on average %.1f neighbours per channel\n', k/length(neighbours)); + +if strcmp(cfg.feedback, 'yes') + % give some graphical feedback + if all(sens.pnt(:,3)==0) + % the sensor positions are already projected on a 2D plane + proj = sens.pnt(:,1:2); + else + % project the 3D positions onto a 2D plane + proj = elproj(sens.pnt); + end + figure + for i=1:length(neighbours) + cla + this = neighbours{i}; + sel1 = match_str(sens.label, this.label); + sel2 = match_str(sens.label, this.neighblabel); + plot(proj(:,1), proj(:,2), 'k.'); + axis equal + title(this.label); + axis off + for j=1:length(this.neighblabel) + x1 = proj(sel1,1); + y1 = proj(sel1,2); + x2 = proj(sel2(j),1); + y2 = proj(sel2(j),2); + X = [x1 x2]; + Y = [y1 y2]; + line(X, Y, 'color', 'r'); + end + drawnow + pause(0.1); + end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION that compute the neighbourhood geometry from the +% gradiometer/electrode positions +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [neighbours]=compneighbstructfromgradelec(sens,neighbourdist) + +nsensors = length(sens.label); + +% compute the distance between all sensors +dist = zeros(nsensors,nsensors); +for i=1:nsensors + dist(i,:) = sqrt(sum((sens.pnt(1:nsensors,:) - repmat(sens.pnt(i,:), nsensors, 1)).^2,2))'; +end; + +% find the neighbouring electrodes based on distance +% later we have to restrict the neighbouring electrodes to those actually selected in the dataset +channeighbstructmat = (dist. +% +% $Id: ft_prepare_atlas.m 948 2010-04-21 18:02:21Z roboos $ + +fieldtripdefs + +useafni = 0; +usewfu = 0; + +[p, f, x] = fileparts(filename); + +if strcmp(f, 'TTatlas+tlrc') + useafni = 1; +else + usewfu = 1; +end + +if useafni + % check whether the required AFNI toolbox is available + hastoolbox('afni', 1); + + atlas = ft_read_mri(filename); + + % the AFNI atlas contains two volumes at 1mm resolution + atlas.brick0 = atlas.anatomy(:,:,:,1); + atlas.brick1 = atlas.anatomy(:,:,:,2); + atlas = rmfield(atlas, 'anatomy'); + atlas.coord = 'tal'; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % the following information is from https://afni.nimh.nih.gov/afni/doc/misc/ttatlas_tlrc + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % column 1 contains sub-brick + % column 2 contains value + % column 3 contains stucture name + % 1 68 Hippocampus + % 1 71 Amygdala + % 0 20 Posterior Cingulate + % 0 21 Anterior Cingulate + % 0 22 Subcallosal Gyrus + % 0 24 Transverse Temporal Gyrus + % 0 25 Uncus + % 0 26 Rectal Gyrus + % 0 27 Fusiform Gyrus + % 0 28 Inferior Occipital Gyrus + % 0 29 Inferior Temporal Gyrus + % 0 30 Insula + % 0 31 Parahippocampal Gyrus + % 0 32 Lingual Gyrus + % 0 33 Middle Occipital Gyrus + % 0 34 Orbital Gyrus + % 0 35 Middle Temporal Gyrus + % 0 36 Superior Temporal Gyrus + % 0 37 Superior Occipital Gyrus + % 0 39 Inferior Frontal Gyrus + % 0 40 Cuneus + % 0 41 Angular Gyrus + % 0 42 Supramarginal Gyrus + % 0 43 Cingulate Gyrus + % 0 44 Inferior Parietal Lobule + % 0 45 Precuneus + % 0 46 Superior Parietal Lobule + % 0 47 Middle Frontal Gyrus + % 0 48 Paracentral Lobule + % 0 49 Postcentral Gyrus + % 0 50 Precentral Gyrus + % 0 51 Superior Frontal Gyrus + % 0 52 Medial Frontal Gyrus + % 0 70 Lentiform Nucleus + % 1 72 Hypothalamus + % 1 73 Red Nucleus + % 1 74 Substantia Nigra + % 0 75 Claustrum + % 0 76 Thalamus + % 0 77 Caudate + % 1 124 Caudate Tail + % 1 125 Caudate Body + % 1 126 Caudate Head + % 1 128 Ventral Anterior Nucleus + % 1 129 Ventral Posterior Medial Nucleus + % 1 130 Ventral Posterior Lateral Nucleus + % 1 131 Medial Dorsal Nucleus + % 1 132 Lateral Dorsal Nucleus + % 1 133 Pulvinar + % 1 134 Lateral Posterior Nucleus + % 1 135 Ventral Lateral Nucleus + % 1 136 Midline Nucleus + % 1 137 Anterior Nucleus + % 1 138 Mammillary Body + % 1 144 Medial Globus Pallidus + % 1 145 Lateral Globus Pallidus + % 1 151 Putamen + % 1 146 Nucleus Accumbens + % 1 147 Medial Geniculum Body + % 1 148 Lateral Geniculum Body + % 1 149 Subthalamic Nucleus + % 1 81 Brodmann area 1 + % 1 82 Brodmann area 2 + % 1 83 Brodmann area 3 + % 1 84 Brodmann area 4 + % 1 85 Brodmann area 5 + % 1 86 Brodmann area 6 + % 1 87 Brodmann area 7 + % 1 88 Brodmann area 8 + % 1 89 Brodmann area 9 + % 1 90 Brodmann area 10 + % 1 91 Brodmann area 11 + % 1 93 Brodmann area 13 + % 1 94 Brodmann area 17 + % 1 95 Brodmann area 18 + % 1 96 Brodmann area 19 + % 1 97 Brodmann area 20 + % 1 98 Brodmann area 21 + % 1 99 Brodmann area 22 + % 1 100 Brodmann area 23 + % 1 101 Brodmann area 24 + % 1 102 Brodmann area 25 + % 1 103 Brodmann area 27 + % 1 104 Brodmann area 28 + % 1 105 Brodmann area 29 + % 1 106 Brodmann area 30 + % 1 107 Brodmann area 31 + % 1 108 Brodmann area 32 + % 1 109 Brodmann area 33 + % 1 110 Brodmann area 34 + % 1 111 Brodmann area 35 + % 1 112 Brodmann area 36 + % 1 113 Brodmann area 37 + % 1 114 Brodmann area 38 + % 1 115 Brodmann area 39 + % 1 116 Brodmann area 40 + % 1 117 Brodmann area 41 + % 1 118 Brodmann area 42 + % 1 119 Brodmann area 43 + % 1 120 Brodmann area 44 + % 1 121 Brodmann area 45 + % 1 122 Brodmann area 46 + % 1 123 Brodmann area 47 + % 0 53 Uvula of Vermis + % 0 54 Pyramis of Vermis + % 0 55 Tuber of Vermis + % 0 56 Declive of Vermis + % 0 57 Culmen of Vermis + % 0 58 Cerebellar Tonsil + % 0 59 Inferior Semi-Lunar Lobule + % 0 60 Fastigium + % 0 61 Nodule + % 0 62 Uvula + % 0 63 Pyramis + % 0 66 Culmen + % 0 65 Declive + % 1 127 Dentate + % 0 64 Tuber + % 0 67 Cerebellar Lingual + + atlas.descr.brick = [ + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + ]; + + atlas.descr.value = [ + 68 + 71 + 20 + 21 + 22 + 24 + 25 + 26 + 27 + 28 + 29 + 30 + 31 + 32 + 33 + 34 + 35 + 36 + 37 + 39 + 40 + 41 + 42 + 43 + 44 + 45 + 46 + 47 + 48 + 49 + 50 + 51 + 52 + 70 + 72 + 73 + 74 + 75 + 76 + 77 + 124 + 125 + 126 + 128 + 129 + 130 + 131 + 132 + 133 + 134 + 135 + 136 + 137 + 138 + 144 + 145 + 151 + 146 + 147 + 148 + 149 + 81 + 82 + 83 + 84 + 85 + 86 + 87 + 88 + 89 + 90 + 91 + 93 + 94 + 95 + 96 + 97 + 98 + 99 + 100 + 101 + 102 + 103 + 104 + 105 + 106 + 107 + 108 + 109 + 110 + 111 + 112 + 113 + 114 + 115 + 116 + 117 + 118 + 119 + 120 + 121 + 122 + 123 + 53 + 54 + 55 + 56 + 57 + 58 + 59 + 60 + 61 + 62 + 63 + 66 + 65 + 127 + 64 + 67 + ]; + + atlas.descr.name = { + 'Hippocampus' + 'Amygdala' + 'Posterior Cingulate' + 'Anterior Cingulate' + 'Subcallosal Gyrus' + 'Transverse Temporal Gyrus' + 'Uncus' + 'Rectal Gyrus' + 'Fusiform Gyrus' + 'Inferior Occipital Gyrus' + 'Inferior Temporal Gyrus' + 'Insula' + 'Parahippocampal Gyrus' + 'Lingual Gyrus' + 'Middle Occipital Gyrus' + 'Orbital Gyrus' + 'Middle Temporal Gyrus' + 'Superior Temporal Gyrus' + 'Superior Occipital Gyrus' + 'Inferior Frontal Gyrus' + 'Cuneus' + 'Angular Gyrus' + 'Supramarginal Gyrus' + 'Cingulate Gyrus' + 'Inferior Parietal Lobule' + 'Precuneus' + 'Superior Parietal Lobule' + 'Middle Frontal Gyrus' + 'Paracentral Lobule' + 'Postcentral Gyrus' + 'Precentral Gyrus' + 'Superior Frontal Gyrus' + 'Medial Frontal Gyrus' + 'Lentiform Nucleus' + 'Hypothalamus' + 'Red Nucleus' + 'Substantia Nigra' + 'Claustrum' + 'Thalamus' + 'Caudate' + 'Caudate Tail' + 'Caudate Body' + 'Caudate Head' + 'Ventral Anterior Nucleus' + 'Ventral Posterior Medial Nucleus' + 'Ventral Posterior Lateral Nucleus' + 'Medial Dorsal Nucleus' + 'Lateral Dorsal Nucleus' + 'Pulvinar' + 'Lateral Posterior Nucleus' + 'Ventral Lateral Nucleus' + 'Midline Nucleus' + 'Anterior Nucleus' + 'Mammillary Body' + 'Medial Globus Pallidus' + 'Lateral Globus Pallidus' + 'Putamen' + 'Nucleus Accumbens' + 'Medial Geniculum Body' + 'Lateral Geniculum Body' + 'Subthalamic Nucleus' + 'Brodmann area 1' + 'Brodmann area 2' + 'Brodmann area 3' + 'Brodmann area 4' + 'Brodmann area 5' + 'Brodmann area 6' + 'Brodmann area 7' + 'Brodmann area 8' + 'Brodmann area 9' + 'Brodmann area 10' + 'Brodmann area 11' + 'Brodmann area 13' + 'Brodmann area 17' + 'Brodmann area 18' + 'Brodmann area 19' + 'Brodmann area 20' + 'Brodmann area 21' + 'Brodmann area 22' + 'Brodmann area 23' + 'Brodmann area 24' + 'Brodmann area 25' + 'Brodmann area 27' + 'Brodmann area 28' + 'Brodmann area 29' + 'Brodmann area 30' + 'Brodmann area 31' + 'Brodmann area 32' + 'Brodmann area 33' + 'Brodmann area 34' + 'Brodmann area 35' + 'Brodmann area 36' + 'Brodmann area 37' + 'Brodmann area 38' + 'Brodmann area 39' + 'Brodmann area 40' + 'Brodmann area 41' + 'Brodmann area 42' + 'Brodmann area 43' + 'Brodmann area 44' + 'Brodmann area 45' + 'Brodmann area 46' + 'Brodmann area 47' + 'Uvula of Vermis' + 'Pyramis of Vermis' + 'Tuber of Vermis' + 'Declive of Vermis' + 'Culmen of Vermis' + 'Cerebellar Tonsil' + 'Inferior Semi-Lunar Lobule' + 'Fastigium' + 'Nodule' + 'Uvula' + 'Pyramis' + 'Culmen' + 'Declive' + 'Dentate' + 'Tuber' + 'Cerebellar Lingual' + }; + +elseif usewfu + atlas = ft_read_mri(filename); % /home/... works, ~/.... does not work + atlas.brick0 = atlas.anatomy(:,:,:); + atlas = rmfield(atlas, 'anatomy'); + atlas.coord = 'mni'; + + % the WFU atlas contains a single atlas volume at 2mm resolution + % to keep it compatible with the existing code, add a dummy atlas volume + atlas.brick1 = zeros(size(atlas.brick0)); + + [p, f, x] = fileparts(filename); + f = [f '_List.mat']; + load(fullfile(p, f)); + + atlas.descr = []; + atlas.descr.brick = zeros(length(ROI),1); + atlas.descr.value = [ROI.ID]'; + atlas.descr.name = {ROI.Nom_C}'; % what is difference between Nom_C and Nom_L?? +end diff --git a/external/fieldtrip/ft_prepare_bemmodel.m b/external/fieldtrip/ft_prepare_bemmodel.m index b84b9b2..9e7e89c 100644 --- a/external/fieldtrip/ft_prepare_bemmodel.m +++ b/external/fieldtrip/ft_prepare_bemmodel.m @@ -1,11 +1,243 @@ -function varargout = funname(varargin); +function [vol, cfg] = ft_prepare_bemmodel(cfg, mri) -% this is a SPM wrapper around a FieldTrip function +% FT_PREPARE_BEMMODEL constructs triangulations of the boundaries between +% multiple segmented tissue types in an anatomical MRI and subsequently +% computes the BEM system matrix. +% +% Use as +% [vol, cfg] = ft_prepare_bemmodel(cfg, mri), or +% [vol, cfg] = ft_prepare_bemmodel(cfg, seg), or +% [vol, cfg] = ft_prepare_bemmodel(cfg, vol), or +% [vol, cfg] = ft_prepare_bemmodel(cfg) +% +% The configuration can contain +% cfg.tissue = [1 2 3], segmentation value of each tissue type +% cfg.numvertices = [Nskin Nskull Nbrain] +% cfg.conductivity = [Cskin Cskull Cbrain] +% cfg.hdmfile = string, file containing the volume conduction model (can be empty) +% cfg.isolatedsource = compartment number, or 0 +% cfg.method = 'dipoli', 'openmeeg', 'brainstorm' or 'bemcp' +% +% Although the example configuration uses 3 compartments, you can use +% an arbitrary number of compartments. +% +% This function implements +% Oostendorp TF, van Oosterom A. +% Source parameter estimation in inhomogeneous volume conductors of arbitrary shape +% IEEE Trans Biomed Eng. 1989 Mar;36(3):382-91. -% this part is variable -prefix = 'ft_'; +% Copyright (C) 2005-2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_prepare_bemmodel.m 948 2010-04-21 18:02:21Z roboos $ + +fieldtripdefs + +if ~isfield(cfg, 'tissue'), cfg.tissue = [8 12 14]; end +if ~isfield(cfg, 'numvertices'), cfg.numvertices = [1 2 3] * 500; end +if ~isfield(cfg, 'hdmfile'), cfg.hdmfile = []; end +if ~isfield(cfg, 'isolatedsource'), cfg.isolatedsource = []; end +if ~isfield(cfg, 'method'), cfg.method = 'dipoli'; end % dipoli, openmeeg, bemcp, brainstorm +if ~isfield(cfg, 'conductivity') + if isfield(mri, 'cond') + cfg.conductivity = mri.cond; + elseif isfield(mri, 'c') + cfg.conductivity = mri.c; + else + cfg.conductivity = [1 1/80 1] * 0.33; + end +end + +% start with an empty volume conductor +vol = []; + +if ~isfield(vol, 'cond') + % assign the conductivity of each compartment + vol.cond = cfg.conductivity; +end + +% determine the number of compartments +Ncompartment = length(vol.cond); + +% construct the geometry of the BEM boundaries +if nargin==1 + vol.bnd = ft_prepare_mesh(cfg); +else + vol.bnd = ft_prepare_mesh(cfg, mri); +end + +vol.source = find_innermost_boundary(vol.bnd); +vol.skin = find_outermost_boundary(vol.bnd); +fprintf('determining source compartment (%d)\n', vol.source); +fprintf('determining skin compartment (%d)\n', vol.skin); + +if isempty(cfg.isolatedsource) && Ncompartment>1 && strcmp(cfg.method, 'dipoli') + % the isolated source compartment is by default the most inner one + cfg.isolatedsource = true; +elseif isempty(cfg.isolatedsource) && Ncompartment==1 + % the isolated source interface should be contained within at least one other interface + cfg.isolatedsource = false; +elseif ~isempty(cfg.isolatedsource) && ~islogical(cfg.isolatedsource) + error('cfg.isolatedsource should be true or false'); +end + +if cfg.isolatedsource + fprintf('using compartment %d for the isolated source approach\n', vol.source); +else + fprintf('not using the isolated source approach\n'); +end + +if strcmp(cfg.method, 'dipoli') + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % this uses an implementation that was contributed by Thom Oostendorp + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + hastoolbox('dipoli', 1); + + % use the dipoli wrapper function + vol = dipoli(vol, cfg.isolatedsource); + vol.type = 'dipoli'; + +elseif strcmp(cfg.method, 'bemcp') + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % this uses an implementation that was contributed by Christophe Philips + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + hastoolbox('bemcp', 1); + + % do some sanity checks + if length(vol.bnd)~=3 + error('this only works for three surfaces'); + end + if vol.skin~=3 + error('the skin should be the third surface'); + end + if vol.source~=1 + error('the source compartment should correspond to the first surface'); + end + + % Build Triangle 4th point + vol = triangle4pt(vol); + + % 2. BEM model estimation, only for the scalp surface + + defl =[ 0 0 1/size(vol.bnd(vol.skin).pnt,1)]; + % ensure deflation for skin surface, i.e. average reference over skin + + % NOTE: + % Calculation proceeds by estimating each submatrix C_ij and combine them. + % There are 2 options: + % - calculating the matrices once, as it takes some time, keep them in + % memory and use them the 2-3 times they're needed. + % - calculating the matrices every time they're needed, i.e. 2-3 times + % The former option is faster but requires more memory space as up to *8* + % square matrices of size C_ij have to be kept in memory at once. + % The latter option requires less memory, but would take much more time to + % estimate. + % This faster but memory hungry solution is implemented here. + + % Deal first with surface 1 and 2 (inner and outer skull + %-------------------------------- + + % NOTE: + % C11st/C22st/C33st are simply the matrix C11/C22/C33 minus the identity + % matrix, i.e. C11st = C11-eye(N) + + weight = (vol.cond(1)-vol.cond(2))/((vol.cond(1)+vol.cond(2))*2*pi); + C11st = bem_Cii_lin(vol.bnd(1).tri,vol.bnd(1).pnt, weight,defl(1),vol.bnd(1).pnt4); + weight = (vol.cond(1)-vol.cond(2))/((vol.cond(2)+vol.cond(3))*2*pi); + C21 = bem_Cij_lin(vol.bnd(2).pnt,vol.bnd(1).pnt,vol.bnd(1).tri, weight,defl(1)); + tmp1 = C21/C11st; + + weight = (vol.cond(2)-vol.cond(3))/((vol.cond(1)+vol.cond(2))*2*pi); + C12 = bem_Cij_lin(vol.bnd(1).pnt,vol.bnd(2).pnt,vol.bnd(2).tri, weight,defl(2)); + weight = (vol.cond(2)-vol.cond(3))/((vol.cond(2)+vol.cond(3))*2*pi); + C22st = bem_Cii_lin(vol.bnd(2).tri,vol.bnd(2).pnt, weight,defl(2),vol.bnd(2).pnt4); + tmp2 = C12/C22st; + + % Try to spare some memory: + tmp10 = - tmp2 * C21 + C11st; + clear C21 C11st + tmp11 = - tmp1 * C12 + C22st; + clear C12 C22st + + % Combine with the effect of surface 3 (scalp) on the first 2 + %------------------------------------------------------------ + weight = (vol.cond(1)-vol.cond(2))/(vol.cond(3)*2*pi); + C31 = bem_Cij_lin(vol.bnd(3).pnt,vol.bnd(1).pnt,vol.bnd(1).tri, weight,defl(1)); + % tmp4 = C31/(- tmp2 * C21 + C11st ); + % clear C31 C21 C11st + tmp4 = C31/tmp10; + clear C31 tmp10 + + weight = (vol.cond(2)-vol.cond(3))/(vol.cond(3)*2*pi); + C32 = bem_Cij_lin(vol.bnd(3).pnt,vol.bnd(2).pnt,vol.bnd(2).tri, weight,defl(2)); + % tmp3 = C32/(- tmp1 * C12 + C22st ); + % clear C12 C22st C32 + tmp3 = C32/tmp11; + clear C32 tmp11 + + tmp5 = tmp3*tmp1-tmp4; + tmp6 = tmp4*tmp2-tmp3; + clear tmp1 tmp2 tmp3 tmp4 + + % Finally include effect of surface 3 on the others + %-------------------------------------------------- + % As the gama1 intermediate matrix is built as the sum of 3 matrices, I can + % spare some memory by building them one at a time, and summing directly + weight = vol.cond(3)/((vol.cond(1)+vol.cond(2))*2*pi); + Ci3 = bem_Cij_lin(vol.bnd(1).pnt,vol.bnd(3).pnt,vol.bnd(3).tri, weight,defl(3)); + gama1 = - tmp5*Ci3; % gama1 = - tmp5*C13; + + weight = vol.cond(3)/((vol.cond(2)+vol.cond(3))*2*pi); + Ci3 = bem_Cij_lin(vol.bnd(2).pnt,vol.bnd(3).pnt,vol.bnd(3).tri, weight,defl(3)); + gama1 = gama1 - tmp6*Ci3; % gama1 = - tmp5*C13 - tmp6*C23; + + weight = 1/(2*pi); + Ci3 = bem_Cii_lin(vol.bnd(3).tri,vol.bnd(3).pnt, weight,defl(3),vol.bnd(3).pnt4); + gama1 = gama1 - Ci3; % gama1 = - tmp5*C13 - tmp6*C23 - C33st; + clear Ci3 + + % Build system matrix + %-------------------- + i_gama1 = inv(gama1); + vol.mat = [i_gama1*tmp5 i_gama1*tmp6 i_gama1]; + vol.type = 'bemcp'; + +elseif strcmp(cfg.method, 'openmeeg') + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % this uses an implementation that was contributed by INRIA Odyssee Team + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + if ~hastoolbox('openmeeg'); + web('http://gforge.inria.fr/frs/?group_id=435') + error('OpenMEEG toolbox needs to be installed!') + else + % use the openmeeg wrapper function + vol = openmeeg(vol,cfg.isolatedsource); + vol.type = 'openmeeg'; + end + +elseif strcmp(cfg.method, 'brainstorm') + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % this uses an implementation from the BrainStorm toolbox + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + hastoolbox('brainstorm', 1); + error('not yet implemented'); + +else + error('unsupported method'); +end % which method -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_prepare_concentricspheres.m b/external/fieldtrip/ft_prepare_concentricspheres.m index b84b9b2..33d7d4d 100644 --- a/external/fieldtrip/ft_prepare_concentricspheres.m +++ b/external/fieldtrip/ft_prepare_concentricspheres.m @@ -1,11 +1,146 @@ -function varargout = funname(varargin); +function [vol, cfg] = ft_prepare_concentricspheres(cfg) -% this is a SPM wrapper around a FieldTrip function +% FT_PREPARE_CONCENTRICSPHERES creates a EEG volume conductor model with +% multiple concentric spheres. +% +% Use as +% [vol, cfg] = ft_prepare_concentricspheres(cfg) +% +% The input configuration should contain +% cfg.headshape = a filename containing headshape, a Nx3 matrix with surface +% points, or a structure with a single or multiple boundaries +% cfg.conductivity = conductivity values for the model (default = [0.3300 1 0.0042 0.3300]) +% cfg.fitind = indices of shapes to use for fitting the center (default = 'all') +% cfg.nonlinear = 'yes' or 'no' (default = 'yes') +% cfg.feedback = 'yes' or 'no' (default = 'yes') +% +% Example: +% +% % first create 4 surfaces that represent the brain, csf, skull and skin +% radius = [86 88 92 100]; +% headshape = []; +% for i=1:4 +% pnt = randn(100,3); +% for j=1:size(pnt,1) +% pnt(j,:) = pnt(j,:) ./ norm(pnt(j,:)); +% end +% headshape(i).pnt = radius(i) .* pnt + 0.1*randn(size(pnt)); +% end +% +% % then construct a volume conduction model of the head by fitting 4 concentric spheres +% cfg = []; +% cfg.headshape = headshape; +% cfg.conductivity = [0.3300 1 0.0042 0.3300] +% [vol, cfg] = prepare_concentricspheres(cfg) -% this part is variable -prefix = 'ft_'; +% Copyright (C) 2009, Vladimir Litvak & Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_prepare_concentricspheres.m 1428 2010-07-19 11:57:28Z vlalit $ + +fieldtripdefs + +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +% set the defaults +if ~isfield(cfg, 'fitind'), cfg.fitind = 'all'; end +if ~isfield(cfg, 'feedback'), cfg.feedback = 'yes'; end +if ~isfield(cfg, 'conductivity'), cfg.conductivity = [0.3300 1 0.0042 0.3300]; end +if ~isfield(cfg, 'numvertices'), cfg.numvertices = 'same'; end + +if isfield(cfg, 'headshape') && isa(cfg.headshape, 'config') + % convert the nested config-object back into a normal structure + cfg.headshape = struct(cfg.headshape); +end + +cfg = checkconfig(cfg, 'forbidden', 'nonlinear'); + +% get the surface describing the head shape +headshape = prepare_mesh_headshape(cfg); + +if strcmp(cfg.fitind, 'all') + fitind = 1:numel(headshape); +else + fitind = cfg.fitind; +end + +% concatenate the vertices of all surfaces +pnt = []; +for i = fitind + pnt = [pnt ; headshape(i).pnt]; +end +% remove double vertices +pnt = unique(pnt, 'rows'); + +Npnt = size(pnt, 1); + +% set up an empty figure +if strcmp(cfg.feedback, 'yes') + clf + hold on + axis equal + axis vis3d + axis off + drawnow + colors = {'b', 'y', 'm', 'r'}; + [sphere_pnt, sphere_tri] = icosahedron162; +end + +% fit a single sphere to all headshape points +[single_o, single_r] = fitsphere(pnt); +fprintf('initial sphere: number of surface points = %d\n', Npnt); +fprintf('initial sphere: center = [%.1f %.1f %.1f]\n', single_o(1), single_o(2), single_o(3)); +fprintf('initial sphere: radius = %.1f\n', single_r); + +% fit the radius of each concentric sphere to the corresponding surface points +vol = []; +vol.o = single_o; +for i = 1:numel(headshape) + dist = sqrt(sum(((headshape(end-i+1).pnt - repmat(single_o, size(headshape(end-i+1).pnt,1), 1)).^2), 2)); + vol.r(i) = mean(dist); + + if strcmp(cfg.feedback, 'yes') + if ~isfield(headshape(end-i+1), 'tri') + headshape(end-i+1).tri = []; + end + + % plot the original surface + bndtmp = []; + bndtmp.pnt = headshape(end-i+1).pnt; + bndtmp.tri = headshape(end-i+1).tri; + ft_plot_mesh(bndtmp,'facecolor','none') + + % plot the sphere surface + bndtmp = []; + bndtmp.pnt = sphere_pnt*vol.r(i) + repmat(single_o, size(sphere_pnt, 1), 1); + bndtmp.tri = sphere_tri; + ft_plot_mesh(bndtmp,'edgecolor',colors{mod(i, numel(colors)) + 1},'facecolor','none'); + end +end + +if numel(cfg.conductivity)==numel(headshape) + vol.c = cfg.conductivity; +else + error('incorrect specification of cfg.conductivity'); +end + +vol.type = 'concentric'; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_prepare_layout.m b/external/fieldtrip/ft_prepare_layout.m index b84b9b2..d2ae0a3 100644 --- a/external/fieldtrip/ft_prepare_layout.m +++ b/external/fieldtrip/ft_prepare_layout.m @@ -1,11 +1,732 @@ -function varargout = funname(varargin); +function [lay] = ft_prepare_layout(cfg, data); -% this is a SPM wrapper around a FieldTrip function +% FT_PREPARE_LAYOUT creates a 2-D layout of the channel locations. This layout +% is required for plotting the topographical distribution of the potential +% or field distribution, or for plotting timecourses in a topographical +% arrangement. +% +% Use as +% lay = ft_prepare_layout(cfg, data) +% +% There are several ways in which a 2-D layout can be made: it can be read +% directly from a *.lay file, it can be created based on 3-D electrode or +% gradiometer positions in the configuration or in the data, or it can be +% created based on the specification of an electrode of gradiometer file. +% +% You can specify either one of the following configuration options +% cfg.layout filename containg the layout +% cfg.rotate number, rotation around the z-axis in degrees (default = [], which means automatic) +% cfg.projection string, 2D projection method can be 'stereographic', 'orthographic', 'polar', 'gnomic' or 'inverse' (default = 'polar') +% cfg.elec structure with electrode positions, or +% cfg.elecfile filename containing electrode positions +% cfg.grad structure with gradiometer definition, or +% cfg.gradfile filename containing gradiometer definition +% cfg.output filename to which the layout will be written (default = []) +% cfg.montage 'no' or a montage structure (default = 'no') +% cfg.image filename, use an image to construct a layout (e.g. usefull for ECoG grids) +% cfg.bw if an image is used and bw = 1 transforms the image in black and white (default = 0, do not transform) +% +% Alternatively the layout can be constructed from either +% data.elec structure with electrode positions +% data.grad structure with gradiometer definition +% +% Alternatively you can specify the following layouts which will be +% generated for all channels present in the data. Note that these layouts +% are suitable for multiplotting, but not for topoplotting. +% cfg.layout = 'ordered' will give you a NxN ordered layout +% cfg.layout = 'vertical' will give you a Nx1 ordered layout +% cfg.layout = 'butterfly' will give you a layout with all channels on top of each other +% +% See also ft_layoutplot, ft_topoplotER, ft_topoplotTFR, ft_multiplotER, ft_multiplotTFR -% this part is variable -prefix = 'ft_'; +% TODO switch to using planarchannelset function -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +% undocumented and non-recommended option (for SPM only) +% cfg.style string, '2d' or '3d' (default = '2d') + +% Copyright (C) 2007-2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_prepare_layout.m 1118 2010-05-20 08:42:20Z tilsan $ + +% Undocumented option: +% cfg.layout can contain a lay structure which is simply returned as is + +fieldtripdefs + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% basic check/initialization of input arguments +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +if (nargin<1) || (nargin>2), error('incorrect number of input arguments'); end; +if (nargin<2), data = []; end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% set default configuration options +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +if ~isfield(cfg, 'rotate'), cfg.rotate = []; end % [] => rotation is determined based on the type of sensors +if ~isfield(cfg, 'style'), cfg.style = '2d'; end +if ~isfield(cfg, 'projection'), cfg.projection = 'polar'; end +if ~isfield(cfg, 'layout'), cfg.layout = []; end +if ~isfield(cfg, 'grad'), cfg.grad = []; end +if ~isfield(cfg, 'elec'), cfg.elec = []; end +if ~isfield(cfg, 'gradfile'), cfg.gradfile = []; end +if ~isfield(cfg, 'elecfile'), cfg.elecfile = []; end +if ~isfield(cfg, 'output'), cfg.output = []; end +if ~isfield(cfg, 'feedback'), cfg.feedback = 'no'; end +if ~isfield(cfg, 'montage'), cfg.montage = 'no'; end +if ~isfield(cfg, 'image'), cfg.image = []; end +if ~isfield(cfg, 'bw'), cfg.bw = 0; end +if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end +if ~isfield(cfg, 'skipscale'), cfg.skipscale = 'no'; end +if ~isfield(cfg, 'skipcomnt'), cfg.skipcomnt = 'no'; end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% try to generate the layout structure +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +skipscale = strcmp(cfg.skipscale, 'yes'); % in general a scale is desired +skipcomnt = strcmp(cfg.skipcomnt, 'yes'); % in general a comment desired + +if isa(cfg.layout, 'config') + % convert the nested config-object back into a normal structure + cfg.layout = struct(cfg.layout); +end + +% check whether cfg.layout already contains a valid layout structure (this can +% happen when higher level plotting functions are called with cfg.layout set to +% a lay structure) +if isstruct(cfg.layout) && isfield(cfg.layout, 'pos') && isfield(cfg.layout, 'label') && isfield(cfg.layout, 'width') && isfield(cfg.layout, 'height') + lay = cfg.layout; + +elseif isstruct(cfg.layout) && isfield(cfg.layout, 'pos') && isfield(cfg.layout, 'label') && (~isfield(cfg.layout, 'width') || ~isfield(cfg.layout, 'height')) + lay = cfg.layout; + % add width and height for multiplotting + d = dist(lay.pos'); + nchans = length(lay.label); + for i=1:nchans + d(i,i) = inf; % exclude the diagonal + end + mindist = min(d(:)); + lay.width = ones(nchans,1) * mindist * 0.8; + lay.height = ones(nchans,1) * mindist * 0.6; + +elseif isequal(cfg.layout, 'butterfly') + if nargin>1 && ~isempty(data) + % look at the data to determine the overlapping channels + cfg.channel = ft_channelselection(cfg.channel, data.label); + chanindx = match_str(data.label, cfg.channel); + nchan = length(data.label(chanindx)); + lay.label = data.label(chanindx); + else + nchan = length(cfg.channel); + lay.label = cfg.channel; + end + lay.pos = zeros(nchan,2); % centered at (0,0) + lay.width = ones(nchan,1) * 1.0; + lay.height = ones(nchan,1) * 1.0; + lay.mask = {}; + lay.outline = {}; + skipscale = true; % a scale is not desired + skipcomnt = true; % a comment is initially not desired, or at least requires more thought + +elseif isequal(cfg.layout, 'vertical') + if nargin>1 && ~isempty(data) + % look at the data to determine the overlapping channels + cfg.channel = ft_channelselection(data.label, cfg.channel); % with this order order of channels stays the same + [dum chanindx] = match_str(cfg.channel, data.label); % order of channels according to cfg specified by user + nchan = length(data.label(chanindx)); + lay.label = data.label(chanindx); + else + nchan = length(cfg.channel); + lay.label = cfg.channel; + end + for i=1:(nchan+2) + x = 0.5; + y = 1-i/(nchan+1+2); + lay.pos (i,:) = [x y]; + lay.width (i,1) = 0.9; + lay.height(i,1) = 0.9 * 1/(nchan+1+2); + if i==(nchan+1) + lay.label{i} = 'SCALE'; + elseif i==(nchan+2) + lay.label{i} = 'COMNT'; + end + end + lay.mask = {}; + lay.outline = {}; + +elseif isequal(cfg.layout, 'ordered') + if nargin>1 && ~isempty(data) + % look at the data to determine the overlapping channels + cfg.channel = ft_channelselection(cfg.channel, data.label); + chanindx = match_str(data.label, cfg.channel); + nchan = length(data.label(chanindx)); + lay.label = data.label(chanindx); + else + nchan = length(cfg.channel); + lay.label = cfg.channel; + end + ncol = ceil(sqrt(nchan))+1; + nrow = ceil(sqrt(nchan))+1; + k = 0; + for i=1:nrow + for j=1:ncol + k = k+1; + if k<=nchan + x = (j-1)/ncol; + y = (nrow-i-1)/nrow; + lay.pos(k,:) = [x y]; + lay.width(k,1) = 0.8 * 1/ncol; + lay.height(k,1) = 0.8 * 1/nrow; + end + end + end + + lay.label{end+1} = 'SCALE'; + lay.width(end+1) = 0.8 * 1/ncol; + lay.height(end+1) = 0.8 * 1/nrow; + x = (ncol-2)/ncol; + y = 0/nrow; + lay.pos(end+1,:) = [x y]; + + lay.label{end+1} = 'COMNT'; + lay.width(end+1) = 0.8 * 1/ncol; + lay.height(end+1) = 0.8 * 1/nrow; + x = (ncol-1)/ncol; + y = 0/nrow; + lay.pos(end+1,:) = [x y]; + + % try to generate layout from other configuration options +elseif ischar(cfg.layout) && ft_filetype(cfg.layout, 'matlab') + fprintf('reading layout from file %s\n', cfg.layout); + load(cfg.layout, 'lay'); + +elseif ischar(cfg.layout) && ft_filetype(cfg.layout, 'layout') + fprintf('reading layout from file %s\n', cfg.layout); + lay = readlay(cfg.layout); + +elseif ischar(cfg.layout) && ~ft_filetype(cfg.layout, 'layout') + % assume that cfg.layout is an electrode file + fprintf('creating layout from electrode file %s\n', cfg.layout); + lay = sens2lay(ft_read_sens(cfg.layout), cfg.rotate, cfg.projection, cfg.style); + +elseif ischar(cfg.elecfile) + fprintf('creating layout from electrode file %s\n', cfg.elecfile); + lay = sens2lay(ft_read_sens(cfg.elecfile), cfg.rotate, cfg.projection, cfg.style); + +elseif ~isempty(cfg.elec) && isstruct(cfg.elec) + fprintf('creating layout from cfg.elec\n'); + lay = sens2lay(cfg.elec, cfg.rotate, cfg.projection, cfg.style); + +elseif isfield(data, 'elec') && isstruct(data.elec) + fprintf('creating layout from data.elec\n'); + lay = sens2lay(data.elec, cfg.rotate, cfg.projection, cfg.style); + +elseif ischar(cfg.gradfile) + fprintf('creating layout from gradiometer file %s\n', cfg.gradfile); + lay = sens2lay(ft_read_sens(cfg.gradfile), cfg.rotate, cfg.projection, cfg.style); + +elseif ~isempty(cfg.grad) && isstruct(cfg.grad) + fprintf('creating layout from cfg.grad\n'); + lay = sens2lay(cfg.grad, cfg.rotate, cfg.projection, cfg.style); + +elseif isfield(data, 'grad') && isstruct(data.grad) + fprintf('creating layout from data.grad\n'); + lay = sens2lay(data.grad, cfg.rotate, cfg.projection, cfg.style); + +elseif ~isempty(cfg.image) && isempty(cfg.layout) + fprintf('reading background image from %s\n', cfg.image); + img = imread(cfg.image); + img = flipdim(img, 1); % in combination with "axis xy" + + figure + bw = cfg.bw; + + if bw + % convert to greyscale image + img = mean(img, 3); + imagesc(img); + colormap gray + else + % plot as RGB image + image(img); + end + + hold on + axis equal + axis off + axis xy + + % get the electrode positions + pos = zeros(0,2); + electrodehelp = [ ... + '-----------------------------------------------------\n' ... + 'specify electrode locations\n' ... + 'press the right mouse button to add another electrode\n' ... + 'press backspace on the keyboard to remove the last electrode\n' ... + 'press "q" on the keyboard to continue\n' ... + ]; + again = 1; + while again + fprintf(electrodehelp) + disp(round(pos)); % values are integers/pixels + try + [x, y, k] = ginput(1); + catch + % this happens if the figure is closed + return; + end + + switch k + case 1 + pos = cat(1, pos, [x y]); + % add it to the figure + plot(x, y, 'b.'); + plot(x, y, 'yo'); + + case 8 + if size(pos,1)>0 + % remove the last point + pos = pos(1:end-1,:); + % completely redraw the figure + cla + h = image(img); + hold on + axis equal + axis off + plot(pos(:,1), pos(:,2), 'b.'); + plot(pos(:,1), pos(:,2), 'yo'); + end + + case 'q' + again = 0; + + otherwise + warning('invalid button (%d)', k); + end + end + + % get the mask outline + polygon = {}; + thispolygon = 1; + polygon{thispolygon} = zeros(0,2); + maskhelp = [ ... + '------------------------------------------------------------------------\n' ... + 'specify polygons for masking the topgraphic interpolation\n' ... + 'press the right mouse button to add another point to the current polygon\n' ... + 'press backspace on the keyboard to remove the last point\n' ... + 'press "c" on the keyboard to close this polygon and start with another\n' ... + 'press "q" on the keyboard to continue\n' ... + ]; + again = 1; + while again + fprintf(maskhelp); + fprintf('\n'); + for i=1:length(polygon) + fprintf('polygon %d has %d points\n', i, size(polygon{i},1)); + end + + try + [x, y, k] = ginput(1); + catch + % this happens if the figure is closed + return; + end + + switch k + case 1 + polygon{thispolygon} = cat(1, polygon{thispolygon}, [x y]); + % add the last line segment to the figure + if size(polygon{thispolygon},1)>1 + x = polygon{i}([end-1 end],1); + y = polygon{i}([end-1 end],2); + end + plot(x, y, 'g.-'); + + case 8 % backspace + if size(polygon{thispolygon},1)>0 + % remove the last point + polygon{thispolygon} = polygon{thispolygon}(1:end-1,:); + % completely redraw the figure + cla + h = image(img); + hold on + axis equal + axis off + % plot the electrode positions + plot(pos(:,1), pos(:,2), 'b.'); + plot(pos(:,1), pos(:,2), 'yo'); + for i=1:length(polygon) + x = polygon{i}(:,1); + y = polygon{i}(:,2); + if i~=thispolygon + % close the polygon in the figure + x(end) = x(1); + y(end) = y(1); + end + plot(x, y, 'g.-'); + end + end + + case 'c' + if size(polygon{thispolygon},1)>0 + % close the polygon + polygon{thispolygon}(end+1,:) = polygon{thispolygon}(1,:); + % close the polygon in the figure + x = polygon{i}([end-1 end],1); + y = polygon{i}([end-1 end],2); + plot(x, y, 'g.-'); + % switch to the next polygon + thispolygon = thispolygon + 1; + polygon{thispolygon} = zeros(0,2); + end + + case 'q' + if size(polygon{thispolygon},1)>0 + % close the polygon + polygon{thispolygon}(end+1,:) = polygon{thispolygon}(1,:); + % close the polygon in the figure + x = polygon{i}([end-1 end],1); + y = polygon{i}([end-1 end],2); + plot(x, y, 'g.-'); + end + again = 0; + + otherwise + warning('invalid button (%d)', k); + end + end + % remember this set of polygons as the mask + mask = polygon; + + + % get the outline, e.g. head shape and sulci + polygon = {}; + thispolygon = 1; + polygon{thispolygon} = zeros(0,2); + maskhelp = [ ... + '-----------------------------------------------------------------------------------\n' ... + 'specify polygons for adding outlines (e.g. head shape and sulci) to the layout\n' ... + 'press the right mouse button to add another point to the current polygon\n' ... + 'press backspace on the keyboard to remove the last point\n' ... + 'press "c" on the keyboard to close this polygon and start with another\n' ... + 'press "n" on the keyboard to start with another without closing the current polygon\n' ... + 'press "q" on the keyboard to continue\n' ... + ]; + again = 1; + while again + fprintf(maskhelp); + fprintf('\n'); + for i=1:length(polygon) + fprintf('polygon %d has %d points\n', i, size(polygon{i},1)); + end + + try + [x, y, k] = ginput(1); + catch + % this happens if the figure is closed + return; + end + + switch k + case 1 + polygon{thispolygon} = cat(1, polygon{thispolygon}, [x y]); + % add the last line segment to the figure + if size(polygon{thispolygon},1)>1 + x = polygon{i}([end-1 end],1); + y = polygon{i}([end-1 end],2); + end + plot(x, y, 'm.-'); + + case 8 % backspace + if size(polygon{thispolygon},1)>0 + % remove the last point + polygon{thispolygon} = polygon{thispolygon}(1:end-1,:); + % completely redraw the figure + cla + h = image(img); + hold on + axis equal + axis off + % plot the electrode positions + plot(pos(:,1), pos(:,2), 'b.'); + plot(pos(:,1), pos(:,2), 'yo'); + for i=1:length(polygon) + x = polygon{i}(:,1); + y = polygon{i}(:,2); + if i~=thispolygon + % close the polygon in the figure + x(end) = x(1); + y(end) = y(1); + end + plot(x, y, 'm.-'); + end + end + + case 'c' + if size(polygon{thispolygon},1)>0 + x = polygon{thispolygon}(1,1); + y = polygon{thispolygon}(1,2); + polygon{thispolygon} = cat(1, polygon{thispolygon}, [x y]); + % add the last line segment to the figure + x = polygon{i}([end-1 end],1); + y = polygon{i}([end-1 end],2); + plot(x, y, 'm.-'); + % switch to the next polygon + thispolygon = thispolygon + 1; + polygon{thispolygon} = zeros(0,2); + end + + case 'n' + if size(polygon{thispolygon},1)>0 + % switch to the next polygon + thispolygon = thispolygon + 1; + polygon{thispolygon} = zeros(0,2); + end + + case 'q' + again = 0; + + otherwise + warning('invalid button (%d)', k); + end + end + % remember this set of polygons as the outline + outline = polygon; + + % convert electrode positions into a layout structure + lay.pos = pos; + nchans = size(pos,1); + for i=1:nchans + lay.label{i,1} = sprintf('chan%03d', i); + end + % add width and height for multiplotting + d = dist(pos'); + for i=1:nchans + d(i,i) = inf; % exclude the diagonal + end + mindist = min(d(:)); + lay.width = ones(nchans,1) * mindist * 0.8; + lay.height = ones(nchans,1) * mindist * 0.6; + % add mask and outline polygons + lay.mask = mask; + lay.outline = outline; + +else + error('no layout detected, please specify cfg.layout') +end + +% FIXME there is a conflict between the use of cfg.style here and in topoplot +if ~strcmp(cfg.style, '3d') + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % check whether outline and mask are available + % if not, add default "circle with triangle" to resemble the head + % in case of "circle with triangle", the electrode positions should also be + % scaled + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + if ~isfield(lay, 'outline') || ~isfield(lay, 'mask') + rmax = 0.5; + l = 0:2*pi/100:2*pi; + HeadX = cos(l).*rmax; + HeadY = sin(l).*rmax; + NoseX = [0.18*rmax 0 -0.18*rmax]; + NoseY = [rmax-.004 rmax*1.15 rmax-.004]; + EarX = [.497 .510 .518 .5299 .5419 .54 .547 .532 .510 .489]; + EarY = [.0555 .0775 .0783 .0746 .0555 -.0055 -.0932 -.1313 -.1384 -.1199]; + % Scale the electrode positions to fit within a unit circle, i.e. electrode radius = 0.45 + ind_scale = strmatch('SCALE', lay.label); + ind_comnt = strmatch('COMNT', lay.label); + sel = setdiff(1:length(lay.label), [ind_scale ind_comnt]); % these are excluded for scaling + x = lay.pos(sel,1); + y = lay.pos(sel,2); + xrange = range(x); + yrange = range(y); + % First scale the width and height of the box for multiplotting + lay.width = lay.width./xrange; + lay.height = lay.height./yrange; + % Then shift and scale the electrode positions + lay.pos(:,1) = 0.9*((lay.pos(:,1)-min(x))/xrange-0.5); + lay.pos(:,2) = 0.9*((lay.pos(:,2)-min(y))/yrange-0.5); + % Define the outline of the head, ears and nose + lay.outline{1} = [HeadX(:) HeadY(:)]; + lay.outline{2} = [NoseX(:) NoseY(:)]; + lay.outline{3} = [ EarX(:) EarY(:)]; + lay.outline{4} = [-EarX(:) EarY(:)]; + % Define the anatomical mask based on a circular head + lay.mask{1} = [HeadX(:) HeadY(:)]; + end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% apply the montage, i.e. combine bipolar channels into a new representation +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +if ~strcmp(cfg.montage, 'no') + Norg = length(cfg.montage.labelorg); + Nnew = length(cfg.montage.labelnew); + + for i=1:Nnew + cfg.montage.tra(i,:) = abs(cfg.montage.tra(i,:)); + cfg.montage.tra(i,:) = cfg.montage.tra(i,:) ./ sum(cfg.montage.tra(i,:)); + end + % pretend it is a sensor structure, this achieves averaging after channel matching + tmp.tra = lay.pos; + tmp.label = lay.label; + new = ft_apply_montage(tmp, cfg.montage); + lay.pos = new.tra; + lay.label = new.label; + % do the same for the width and height + tmp.tra = lay.width(:); + new = ft_apply_montage(tmp, cfg.montage); + lay.width = new.tra; + tmp.tra = lay.height(:); + new = ft_apply_montage(tmp, cfg.montage); + lay.height = new.tra; +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% add axes positions for comments and scale information if required +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +if ~any(strcmp('COMNT', lay.label)) && strcmpi(cfg.style, '2d') && ~skipcomnt + % add a placeholder for the comment in the upper left corner + lay.label{end+1} = 'COMNT'; + lay.width(end+1) = mean(lay.width); + lay.height(end+1) = mean(lay.height); + X = min(lay.pos(:,1)); + Y = max(lay.pos(:,2)); + Y = min(lay.pos(:,2)); + lay.pos(end+1,:) = [X Y]; +elseif any(strcmp('COMNT', lay.label)) && skipcomnt + % remove the scale entry + sel = find(strcmp('COMNT', lay.label)); + lay.label(sel) = []; + lay.pos(sel,:) = []; + lay.width(sel) = []; + lay.height(sel) = []; +end + +if ~any(strcmp('SCALE', lay.label)) && strcmpi(cfg.style, '2d') && ~skipscale + % add a placeholder for the scale in the upper right corner + lay.label{end+1} = 'SCALE'; + lay.width(end+1) = mean(lay.width); + lay.height(end+1) = mean(lay.height); + X = max(lay.pos(:,1)); + Y = max(lay.pos(:,2)); + Y = min(lay.pos(:,2)); + lay.pos(end+1,:) = [X Y]; +elseif any(strcmp('SCALE', lay.label)) && skipscale + % remove the scale entry + sel = find(strcmp('SCALE', lay.label)); + lay.label(sel) = []; + lay.pos(sel,:) = []; + lay.width(sel) = []; + lay.height(sel) = []; +end + +% to plot the layout for debugging, you can use this code snippet +if strcmp(cfg.feedback, 'yes') && strcmpi(cfg.style, '2d') + tmpcfg = []; + tmpcfg.layout = lay; + ft_layoutplot(tmpcfg); +end + +% to write the layout to a text file, you can use this code snippet +if ~isempty(cfg.output) && strcmpi(cfg.style, '2d') + fprintf('writing layout to ''%s''\n', cfg.output); + fid = fopen(cfg.output, 'wt'); + for i=1:numel(lay.label) + fprintf(fid, '%d %f %f %f %f %s\n', i, lay.pos(i,1), lay.pos(i,2), lay.width(i), lay.height(i), lay.label{i}); + end + fclose(fid); +elseif ~isempty(cfg.output) && strcmpi(cfg.style, '3d') + % the layout file format does not support 3D positions, furthermore for + % a 3D layout the width and height are currently set to NaN + error('writing a 3D layout to an output file is not supported'); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +% read the layout information from the ascii file +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function lay = readlay(filename) +if ~exist(filename, 'file') + error(sprintf('could not open layout file: %s', filename)); +end +[chNum,X,Y,Width,Height,Lbl,Rem] = textread(filename,'%f %f %f %f %f %q %q'); + +if length(Rem). +% +% $Id: ft_prepare_leadfield.m 1285 2010-06-29 11:34:13Z jansch $ + +fieldtripdefs +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% set the defaults +if ~isfield(cfg, 'normalize'), cfg.normalize = 'no'; end +if ~isfield(cfg, 'normalizeparam'), cfg.normalizeparam = 0.5; end +if ~isfield(cfg, 'lbex'), cfg.lbex = 'no'; end +if ~isfield(cfg, 'sel50p'), cfg.sel50p = 'no'; end +if ~isfield(cfg, 'feedback'), cfg.feedback = 'text'; end +if ~isfield(cfg, 'mollify'), cfg.mollify = 'no'; end +if ~isfield(cfg, 'patchsvd'), cfg.patchsvd = 'no'; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +% if ~isfield(cfg, 'reducerank'), cfg.reducerank = 'no'; end % the default for this depends on EEG/MEG and is set below + +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + end +else + data = []; +end + +% put the low-level options pertaining to the dipole grid in their own field +cfg = checkconfig(cfg, 'createsubcfg', {'grid'}); + +if strcmp(cfg.sel50p, 'yes') && strcmp(cfg.lbex, 'yes') + error('subspace projection with either lbex or sel50p is mutually exclusive'); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% collect and preprocess the electrodes/gradiometer and head model +[vol, sens, cfg] = prepare_headmodel(cfg, data); + +% set the default for reducing the rank of the leadfields +if ~isfield(cfg, 'reducerank') + if ft_senstype(sens, 'eeg') + cfg.reducerank = 3; + else + cfg.reducerank = 2; + end +end + +% construct the grid on which the scanning will be done +[grid, cfg] = prepare_dipole_grid(cfg, vol, sens); + +if ft_voltype(vol, 'openmeeg') + % the system call to the openmeeg executable makes it rather slow + % calling it once is much more efficient + fprintf('calculating leadfield for all positions at once, this may take a while...\n'); + lf = ft_compute_leadfield(grid.pos(grid.inside,:), sens, vol, 'reducerank', cfg.reducerank, 'normalize', cfg.normalize, 'normalizeparam', cfg.normalizeparam); + % reassign the large leadfield matrix over the single grid locations + for i=1:length(grid.inside) + sel = (3*i-2):(3*i); % 1:3, 4:6, ... + dipindx = grid.inside(i); + grid.leadfield{dipindx} = lf(:,sel); + end + clear lf + +else + progress('init', cfg.feedback, 'computing leadfield'); + for i=1:length(grid.inside) + % compute the leadfield on all grid positions inside the brain + progress(i/length(grid.inside), 'computing leadfield %d/%d\n', i, length(grid.inside)); + dipindx = grid.inside(i); + grid.leadfield{dipindx} = ft_compute_leadfield(grid.pos(dipindx,:), sens, vol, 'reducerank', cfg.reducerank, 'normalize', cfg.normalize, 'normalizeparam', cfg.normalizeparam); + + if isfield(cfg, 'grid') && isfield(cfg.grid, 'mom') + % multiply with the normalized dipole moment to get the leadfield in the desired orientation + grid.leadfield{dipindx} = grid.leadfield{dipindx} * grid.mom(:,dipindx); + end + end % for all grid locations inside the brain + progress('close'); +end + + +% fill the positions outside the brain with NaNs +grid.leadfield(grid.outside) = {nan}; + +% mollify the leadfields +if ~strcmp(cfg.mollify, 'no') + grid = mollify(cfg, grid); +end + +% combine leadfields in patches and do an SVD on them +if ~strcmp(cfg.patchsvd, 'no') + grid = patchsvd(cfg, grid); +end + +% compute the 50 percent channel selection subspace projection +if ~strcmp(cfg.sel50p, 'no') + grid = sel50p(cfg, grid, sens); +end + +% compute the local basis function expansion (LBEX) subspace projection +if ~strcmp(cfg.lbex, 'no') + grid = lbex(cfg, grid); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_prepare_leadfield.m 1285 2010-06-29 11:34:13Z jansch $'; + +% remember the configuration details of the input data +try, cfg.previous = data.cfg; end +% remember the exact configuration details in the output +grid.cfg = cfg; -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_prepare_localspheres.m b/external/fieldtrip/ft_prepare_localspheres.m index b84b9b2..e348b1c 100644 --- a/external/fieldtrip/ft_prepare_localspheres.m +++ b/external/fieldtrip/ft_prepare_localspheres.m @@ -1,11 +1,211 @@ -function varargout = funname(varargin); +function [vol, cfg] = ft_prepare_localspheres(cfg, mri) -% this is a SPM wrapper around a FieldTrip function +% FT_PREPARE_LOCALSPHERES creates a MEG volume conductor model with a sphere +% for every sensor. You can also use it to create a single sphere +% model that is fitted to the MRI or to the head shape points. +% +% Use as +% [vol, cfg] = ft_prepare_localspheres(cfg, seg), or +% [vol, cfg] = ft_prepare_localspheres(cfg, mri), or +% [vol, cfg] = ft_prepare_localspheres(cfg) +% +% The input configuration should contain +% cfg.grad = structure with gradiometer definition, or +% cfg.gradfile = filename containing gradiometer definition +% cfg.radius = number, which points to select for each channel (default = 7 cm) +% cfg.baseline = number, baseline of axial/planar gradiometer (default = 5 cm) +% cfg.feedback = 'yes' or 'no' (default = 'yes') +% cfg.singlesphere = 'yes' or 'no', fit only a single sphere (default = 'no') +% cfg.headshape = a filename containing headshape, a structure containing a +% single triangulated boundary, or a Nx3 matrix with surface +% points +% +% The following options are relevant if you use a segmented MRI +% cfg.smooth = 'no' or the FWHM of the gaussian kernel in voxels (default = 'no') +% cfg.mriunits = 'mm' or 'cm' (default = 'mm') +% cfg.sourceunits = 'mm' or 'cm' (default = 'cm') +% cfg.threshold = 0.5, relative to the maximum value in the segmentation +% +% This function implements +% Huang MX, Mosher JC, Leahy RM. +% A sensor-weighted overlapping-sphere head model and exhaustive head model comparison for MEG +% Phys Med Biol. 1999 Feb;44(2):423-40 -% this part is variable -prefix = 'ft_'; +% TODO cfg.spheremesh should be renamed consistently with other mesh generation cfgs +% TODO shape should contain pnt as subfield and not be equal to pnt (for consistency with other use of shape) +% +% Undocumented local options: +% cfg.spheremesh = number of points that is placed on the brain surface (default 4000) +% cfg.maxradius +% cfg.inputfile = one can specifiy preanalysed saved data as input -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +% Copyright (C) 2005-2006, Jan-Mathijs Schoffelen & Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_prepare_localspheres.m 1427 2010-07-19 11:44:01Z vlalit $ + +fieldtripdefs + +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +% set the defaults +if ~isfield(cfg, 'radius'), cfg.radius = 8.5; end +if ~isfield(cfg, 'maxradius'), cfg.maxradius = 20; end +if ~isfield(cfg, 'baseline'), cfg.baseline = 5; end +if ~isfield(cfg, 'feedback'), cfg.feedback = 'yes'; end +if ~isfield(cfg, 'smooth'); cfg.smooth = 5; end % in voxels +if ~isfield(cfg, 'mriunits'); cfg.mriunits = 'mm'; end +if ~isfield(cfg, 'sourceunits'), cfg.sourceunits = 'cm'; end +if ~isfield(cfg, 'threshold'), cfg.threshold = 0.5; end % relative +if ~isfield(cfg, 'spheremesh'), cfg.spheremesh = 4000; end +if ~isfield(cfg, 'singlesphere'), cfg.singlesphere = 'no'; end +if ~isfield(cfg, 'headshape'), cfg.headshape = []; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end + +% check for option of cfg.inputfile +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + mri = loadvar(cfg.inputfile, 'data'); + hasdata = true; + end +end + +if hasdata + headshape = ft_prepare_mesh(cfg, mri); +else + headshape = ft_prepare_mesh(cfg); +end + +% read the gradiometer definition from file or copy it from the configuration +if isfield(cfg, 'gradfile') + grad = ft_read_sens(cfg.gradfile); +else + grad = cfg.grad; +end + +Nshape = size(headshape.pnt,1); +Nchan = size(grad.tra, 1); + +% set up an empty figure +if strcmp(cfg.feedback, 'yes') + clf + hold on + axis equal + axis vis3d + axis off + drawnow +end + +% plot all channels and headshape points +if strcmp(cfg.feedback, 'yes') + cla + ft_plot_sens(grad); + ft_plot_mesh(headshape, 'vertexcolor', 'g', 'facecolor', 'none', 'edgecolor', 'none'); + drawnow +end + +% fit a single sphere to all headshape points +[single_o, single_r] = fitsphere(headshape.pnt); +fprintf('single sphere, %5d surface points, center = [%4.1f %4.1f %4.1f], radius = %4.1f\n', Nshape, single_o(1), single_o(2), single_o(3), single_r); + +vol = []; + +if strcmp(cfg.singlesphere, 'yes') + % only return a single sphere + vol.r = single_r; + vol.o = single_o; + return; +end + +% start with an empty structure that will hold the results +vol.r = zeros(Nchan,1); % radius of every sphere +vol.o = zeros(Nchan,3); % origin of every sphere +vol.label = cell(Nchan,1); % corresponding gradiometer channel label for every sphere + +for chan=1:Nchan + coilsel = find(grad.tra(chan,:)~=0); + allpnt = grad.pnt(coilsel, :); % position of all coils belonging to this channel + allori = grad.ori(coilsel, :); % orientation of all coils belonging to this channel + + if strcmp(cfg.feedback, 'yes') + cla + plot3(grad.pnt(:,1), grad.pnt(:,2), grad.pnt(:,3), 'b.'); % all coils + plot3(allpnt(:,1), allpnt(:,2), allpnt(:,3), 'r*'); % this channel in red + end + + % determine the average position and orientation of this channel + thispnt = mean(allpnt,1); + [u, s, v] = svd(allori); + thisori = v(:,1)'; + if dot(thispnt,thisori)<0 + % the orientation should be outwards pointing + thisori = -thisori; + end + + % compute the distance from every coil along this channels orientation + dist = zeros(size(coilsel)); + for i=1:length(coilsel) + dist(i) = dot((allpnt(i,:)-thispnt), thisori); + end + + [m, i] = min(dist); + % check whether the minimum difference is larger than a typical distance + if abs(m)>(cfg.baseline/4) + % replace the position of this channel by the coil that is the closest to the head (axial gradiometer) + % except when the center of the channel is approximately just as good (planar gradiometer) + thispnt = allpnt(i,:); + end + + % find the headshape points that are close to this channel + dist = sqrt(sum((headshape.pnt-repmat(thispnt,Nshape,1)).^2, 2)); + shapesel = find(dist10 + [o, r] = fitsphere(headshape.pnt(shapesel,:)); + fprintf('channel = %s, %5d surface points, center = [%4.1f %4.1f %4.1f], radius = %4.1f\n', grad.label{chan}, length(shapesel), o(1), o(2), o(3), r); + else + fprintf('channel = %s, not enough surface points, using all points\n', grad.label{chan}); + o = single_o; + r = single_r; + end + + if r > cfg.maxradius + fprintf('channel = %s, not enough surface points, using all points\n', grad.label{chan}); + o = single_o; + r = single_r; + end + + % add this sphere to the volume conductor + vol.o(chan,:) = o; + vol.r(chan) = r; + vol.label{chan} = grad.label{chan}; +end % for all channels + +vol.type = 'multisphere'; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); diff --git a/external/fieldtrip/ft_prepare_mesh.m b/external/fieldtrip/ft_prepare_mesh.m new file mode 100644 index 0000000..724525a --- /dev/null +++ b/external/fieldtrip/ft_prepare_mesh.m @@ -0,0 +1,165 @@ +function bnd = ft_prepare_mesh(cfg, mri) + +% FT_PREPARE_MESH creates a triangulated surface mesh for the volume +% conduction model. The mesh can either be selected manually from raw +% mri data or can be generated starting from a segmented volume +% information stored in the mri structure. The result is a bnd +% structure which contains the information about all segmented surfaces +% related to mri and are expressed in world coordinates. +% +% Use as +% bnd = ft_prepare_mesh(cfg, mri) +% +% Configuration options: +% cfg.method = 'segmentation' or 'manual' +% cfg.tissue = list with segmentation values corresponding with each compartment +% cfg.downsample = integer (1,2, ...) defines the level of refinement of the mri data +% cfg.headshape = a filename containing headshape, a Nx3 matrix with surface +% points, or a structure with a single or multiple boundaries +% +% Undocumented local options: +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk +% +% Example use: +% mri = ft_read_mri('Subject01.mri'); +% cfg = []; +% cfg.method = 'manual'; +% cfg.downsample = 2; +% bnd = prepare_mesh(cfg, mri); + +% Copyrights (C) 2009, Cristiano Micheli & Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_prepare_mesh.m 1432 2010-07-21 08:20:46Z jansch $ + +cfg = checkconfig(cfg, 'forbidden', 'numcompartments'); + +% set the defaults +if ~isfield(cfg, 'downsample'), cfg.downsample = 1; end +if ~isfield(cfg, 'tissue'), cfg.tissue = []; end +if ~isfield(cfg, 'numvertices'), cfg.numvertices = []; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +if isfield(cfg, 'headshape') && isa(cfg.headshape, 'config') + % convert the nested cmethodonfig-object back into a normal structure + cfg.headshape = struct(cfg.headshape); +end + +% load optional given inputfile like already segmented volume +hasdata = (nargin>1); +if hasdata && ~isempty(cfg.inputfile) + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); +elseif hasdata && isempty(cfg.inputfile) + % this is ok +elseif ~hasdata && ~isempty(cfg.inputfile) + % the input data should be read from file + mri = loadvar(cfg.inputfile, 'data'); +elseif ~hasdata && isempty(cfg.inputfile) + mri = []; +end + +if ~isfield(cfg,'headshape') || isempty(cfg.headshape) + basedonseg = isfield(mri, 'transform') && any(isfield(mri, {'seg', 'csf', 'white', 'gray'})); + basedonmri = isfield(mri, 'transform') && ~basedonseg; + basedonvol = isfield(mri, 'bnd'); + basedonsphere = isfield(mri,'r') && isfield(mri,'o'); + basedonheadshape = 0; +elseif isfield(cfg,'headshape') && ~isempty(cfg.headshape) + basedonseg = 0; + basedonmri = 0; + basedonvol = 0; + basedonsphere = 0; + basedonheadshape = 1; +else + error('inconsistent configuration, cfg.headshape should not be used in combination with an mri input') +end + +if basedonseg || basedonmri + % optionally downsample the anatomical MRI and/or the tissue segmentation + tmpcfg = []; + tmpcfg.outputfile = cfg.outputfile; + tmpcfg.downsample = cfg.downsample; + mri = ft_volumedownsample(tmpcfg, mri); +end + +if basedonseg + fprintf('using the segmentation approach\n'); + bnd = prepare_mesh_segmentation(cfg, mri); + +elseif basedonmri + fprintf('using the manual approach\n'); + bnd = prepare_mesh_manual(cfg, mri); + +elseif basedonheadshape + fprintf('using the head shape to construct a triangulated mesh\n'); + bnd = prepare_mesh_headshape(cfg); + +elseif basedonvol + fprintf('using the mesh specified in the input volume conductor\n'); + bnd = mri.bnd; + +elseif basedonsphere + vol = mri; + + if isempty(cfg.numvertices) + fprintf('using the mesh specified by icosaedron162\n'); + [pnt,tri] = icosahedron162; + elseif any(cfg.numvertices==[42 162 642 2562]) + sprintf('using the mesh specified by icosaedron%d\n',cfg.numvertices); + eval(['[pnt,tri] = icosahedron' num2str(cfg.numvertices) ';']); + else + [pnt, tri] = msphere(cfg.numvertices); + sprintf('using the mesh specified by msphere with %d vertices\n',size(pnt,1)); + end + + switch ft_voltype(vol) + case {'singlesphere' 'concentric'} + vol.r = sort(vol.r); + bnd = []; + for i=1:length(vol.r) + bnd(i).pnt(:,1) = pnt(:,1)*vol.r(i) + vol.o(1); + bnd(i).pnt(:,2) = pnt(:,2)*vol.r(i) + vol.o(2); + bnd(i).pnt(:,3) = pnt(:,3)*vol.r(i) + vol.o(3); + bnd(i).tri = tri; + end + case 'multisphere' + bnd = []; + for i=1:length(vol.label) + bnd(i).pnt(:,1) = pnt(:,1)*vol.r(i) + vol.o(i,1); + bnd(i).pnt(:,2) = pnt(:,2)*vol.r(i) + vol.o(i,2); + bnd(i).pnt(:,3) = pnt(:,3)*vol.r(i) + vol.o(i,3); + bnd(i).tri = tri; + end + end + +else + error('unsupported cfg.method and/or input') +end + +% ensure that the vertices and triangles are double precision, otherwise the bemcp mex files will crash +for i=1:length(bnd) + bnd(i).pnt = double(bnd(i).pnt); + bnd(i).tri = double(bnd(i).tri); +end + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', bnd); % use the variable name "data" in the output file +end diff --git a/external/fieldtrip/ft_prepare_singleshell.m b/external/fieldtrip/ft_prepare_singleshell.m index b84b9b2..9cbdc58 100644 --- a/external/fieldtrip/ft_prepare_singleshell.m +++ b/external/fieldtrip/ft_prepare_singleshell.m @@ -1,11 +1,93 @@ -function varargout = funname(varargin); +function [vol, cfg] = ft_prepare_singleshell(cfg, mri) -% this is a SPM wrapper around a FieldTrip function +% FT_PREPARE_SINGLESHELL creates a simple and fast method for the MEG forward +% calculation for one shell of arbitrary shape. This is based on a +% correction of the lead field for a spherical volume conductor by a +% superposition of basis functions, gradients of harmonic functions +% constructed from spherical harmonics. +% +% Use as +% [vol, cfg] = ft_prepare_singleshell(cfg, seg), or +% [vol, cfg] = ft_prepare_singleshell(cfg, mri), or +% [vol, cfg] = ft_prepare_singleshell(cfg) +% +% If you do not use a segmented MRI, the configuration should contain +% cfg.headshape = a filename containing headshape, a structure containing a +% single triangulated boundary, or a Nx3 matrix with surface +% points +% cfg.numvertices = number, to retriangulate the mesh with a sphere (default = 3000) +% instead of specifying a number, you can specify 'same' to keep the +% vertices of the mesh identical to the original headshape points +% +% The following options are relevant if you use a segmented MRI +% cfg.smooth = 'no' or the FWHM of the gaussian kernel in voxels (default = 5) +% cfg.mriunits = 'mm' or 'cm' (default is 'mm') +% cfg.sourceunits = 'mm' or 'cm' (default is 'cm') +% cfg.threshold = 0.5, relative to the maximum value in the segmentation +% +% This function implements +% G. Nolte, "The magnetic lead field theorem in the quasi-static +% approximation and its use for magnetoencephalography forward calculation +% in realistic volume conductors", Phys Med Biol. 2003 Nov 21;48(22):3637-52. +% +% Undocumented local options: +% cfg.inputfile = one can specifiy preanalysed saved data as input +% +% TODO the spheremesh option should be renamed consistently with other mesh generation cfgs +% TODO shape should contain pnt as subfield and not be equal to pnt (for consistency with other use of shape) -% this part is variable -prefix = 'ft_'; +% Copyright (C) 2006-2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_prepare_singleshell.m 1247 2010-06-17 12:07:18Z timeng $ -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +fieldtripdefs + +cfg = checkconfig(cfg, 'trackconfig', 'on'); +cfg = checkconfig(cfg, 'renamed', {'spheremesh', 'numvertices'}); + +% set the defaults +if ~isfield(cfg, 'smooth'); cfg.smooth = 5; end % in voxels +if ~isfield(cfg, 'mriunits'); cfg.mriunits = 'mm'; end +if ~isfield(cfg, 'sourceunits'), cfg.sourceunits = 'cm'; end +if ~isfield(cfg, 'threshold'), cfg.threshold = 0.5; end % relative +if ~isfield(cfg, 'numvertices'), cfg.numvertices = 4000; end % approximate number of vertices in sphere +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end + +% construct the geometry of the volume conductor model, containing a single boundary +% the initialization of the forward computation code is done later in prepare_headmodel +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + mri = loadvar(cfg.inputfile, 'data'); + hasdata = true; + end +end + +if hasdata + vol.bnd = ft_prepare_mesh(cfg, mri); +else + vol.bnd = ft_prepare_mesh(cfg); +end +vol.type = 'nolte'; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); diff --git a/external/fieldtrip/ft_preprocessing.m b/external/fieldtrip/ft_preprocessing.m index b84b9b2..c825b0e 100644 --- a/external/fieldtrip/ft_preprocessing.m +++ b/external/fieldtrip/ft_preprocessing.m @@ -1,11 +1,563 @@ -function varargout = funname(varargin); +function [dataout] = ft_preprocessing(cfg, data) -% this is a SPM wrapper around a FieldTrip function +% FT_PREPROCESSING reads MEG and/or EEG data according to user-specified trials +% and applies several user-specified preprocessing steps to the signals. +% +% Use as +% [data] = ft_preprocessing(cfg) +% or +% [data] = ft_preprocessing(cfg, data) +% +% The first input argument "cfg" is the configuration structure, which +% contains all details for the dataset filenames, trials and the +% preprocessing options. You can only do preprocessing after defining the +% segments of data to be read from the file (i.e. the trials), which is for +% example done based on the occurence of a trigger in the data. +% +% If you are calling FT_PREPROCESSING with only the configuration as first +% input argument and the data still has to be read from file, you should +% specify +% cfg.dataset = string with the filename +% cfg.trl = Nx3 matrix with the trial definition, see FT_DEFINETRIAL +% cfg.padding = length to which the trials are padded for filtering (default = 0) +% cfg.continuous = 'yes' or 'no' whether the file contains continuous data +% (default is determined automatic) +% +% Instead of specifying the dataset, you can also explicitely specify the +% name of the file containing the header information and the name of the +% file containing the data, using +% cfg.datafile = string with the filename +% cfg.headerfile = string with the filename +% +% If you are calling FT_PREPROCESSING with also the second input argument +% "data", then that should contain data that was already read from file in +% a previous call to FT_PREPROCESSING. In that case only the configuration +% options below apply. +% +% The channels that will be read and/or preprocessed are specified with +% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), +% see FT_CHANNELSELECTION for details +% +% The preprocessing options for the selected channels are specified with +% cfg.lpfilter = 'no' or 'yes' lowpass filter (default = 'no') +% cfg.hpfilter = 'no' or 'yes' highpass filter (default = 'no') +% cfg.bpfilter = 'no' or 'yes' bandpass filter (default = 'no') +% cfg.bsfilter = 'no' or 'yes' bandstop filter (default = 'no') +% cfg.dftfilter = 'no' or 'yes' line noise removal using discrete fourier transform (default = 'no') +% cfg.medianfilter = 'no' or 'yes' jump preserving median filter (default = 'no') +% cfg.lpfreq = lowpass frequency in Hz +% cfg.hpfreq = highpass frequency in Hz +% cfg.bpfreq = bandpass frequency range, specified as [low high] in Hz +% cfg.bsfreq = bandstop frequency range, specified as [low high] in Hz +% cfg.dftfreq = line noise frequencies in Hz for DFT filter (default = [50 100 150]) +% cfg.lpfiltord = lowpass filter order (default = 6) +% cfg.hpfiltord = highpass filter order (default = 6) +% cfg.bpfiltord = bandpass filter order (default = 4) +% cfg.bsfiltord = bandstop filter order (default = 4) +% cfg.lpfilttype = digital filter type, 'but' or 'fir' (default = 'but') +% cfg.hpfilttype = digital filter type, 'but' or 'fir' (default = 'but') +% cfg.bpfilttype = digital filter type, 'but' or 'fir' (default = 'but') +% cfg.bsfilttype = digital filter type, 'but' or 'fir' (default = 'but') +% cfg.lpfiltdir = filter direction, 'twopass', 'onepass' or 'onepass-reverse' (default = 'twopass') +% cfg.hpfiltdir = filter direction, 'twopass', 'onepass' or 'onepass-reverse' (default = 'twopass') +% cfg.bpfiltdir = filter direction, 'twopass', 'onepass' or 'onepass-reverse' (default = 'twopass') +% cfg.bsfiltdir = filter direction, 'twopass', 'onepass' or 'onepass-reverse' (default = 'twopass') +% cfg.medianfiltord = length of median filter (default = 9) +% cfg.blc = 'no' or 'yes', whether to apply baseline correction (default = 'no') +% cfg.blcwindow = [begin end] in seconds, the default is the complete trial (default = 'all') +% cfg.detrend = 'no' or 'yes', this is done on the complete trial (default = 'no') +% cfg.polyremoval = 'no' or 'yes', this is done on the complete trial (default = 'no') +% cfg.polyorder = polynome order (default = 2) +% cfg.derivative = 'no' or 'yes', computes the first order derivative of the data (default = 'no') +% cfg.hilbert = 'no', 'abs', 'complex', 'real', 'imag', 'absreal', 'absimag' or 'angle' (default = 'no') +% cfg.rectify = 'no' or 'yes' (default = 'no') +% cfg.precision = 'single' or 'double' (default = 'double') +% +% Preprocessing options that you should only use for EEG data are +% cfg.reref = 'no' or 'yes' (default = 'no') +% cfg.refchannel = cell-array with new EEG reference channel(s) +% cfg.implicitref = 'label' or empty, add the implicit EEG reference as zeros (default = []) +% cfg.montage = 'no' or a montage structure (default = 'no') +% +% Preprocessing options that you should only use when you are calling FT_PREPROCESSING with +% also the second input argument "data" are +% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') +% +% Preprocessing options that you should only use when you are calling +% FT_PREPROCESSING with a single cfg input argument are +% cfg.method = 'trial' or 'channel', read data per trial or per channel (default = 'trial') +% +% See also FT_DEFINETRIAL, FT_REDEFINETRIAL, FT_APPENDDATA, FT_APPENDSPIKE -% this part is variable -prefix = 'ft_'; +% Guidelines for use in an analysis pipeline: after FT_PREPROCESSING you +% will have raw data represented as a single continuous segment or as +% multiple data segments that often correspond to trials in an experiment. +% This usually serves as input for one of the following functions: +% FT_TIMELOCKANALYSIS to compute event-related fields or potentials +% FT_FREQANALYSIS to compute the frequency or time-frequency representation +% FT_PREPROCESSING if you want to apply additional temporal filters, baseline correct, rereference or apply an EEG montage +% FT_APPENDDATA if you have preprocessed seperate conditions or datasets and want to combine them +% FT_REDEFINETRIAL if you want to cut the data segments into smaller pieces or want to change the time axes +% FT_DATABROWSER to inspect the data and check for artefacts +% FT_REJECTVISUAL to inspect the data and remove trials that contain artefacts +% FT_COMPONENTANALYSIS if you want to use ICA to remove artifacts -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +% Undocumented local options: +% cfg.paddir = direction of padding, 'left'/'right'/'both' (default = 'both') +% cfg.artfctdef +% cfg.removemcg +% cfg.inputfile +% cfg.outputfile +% You can use this function to read data from one format, filter it, and +% write it to disk in another format. The reading is done either as one +% long continuous segment or in multiple trials. This is achieved by +% cfg.export.dataset = string with the output file name +% cfg.export.dataformat = string describing the output file format, see FT_WRITE_DATA + +% This function depends on PREPROC which has the following options: +% cfg.absdiff +% cfg.boxcar +% cfg.polyremoval, documented +% cfg.polyorder, documented +% cfg.blc, documented +% cfg.blcwindow, documented +% cfg.bpfilter, documented +% cfg.bpfiltord, documented +% cfg.bpfilttype, documented +% cfg.bpfreq, documented +% cfg.bsfilter, documented +% cfg.bsfiltord, documented +% cfg.bsfilttype, documented +% cfg.bsfreq, documented +% cfg.derivative, documented +% cfg.detrend, documented +% cfg.dftfilter, documented +% cfg.dftfreq, documented +% cfg.hilbert, documented +% cfg.hpfilter, documented +% cfg.hpfiltord, documented +% cfg.hpfilttype, documented +% cfg.hpfreq, documented +% cfg.implicitref, documented +% cfg.lpfilter, documented +% cfg.lpfiltord, documented +% cfg.lpfilttype, documented +% cfg.lpfreq, documented +% cfg.medianfilter, documented +% cfg.medianfiltord, documented +% cfg.rectify, documented +% cfg.refchannel, documented +% cfg.reref, documented + +% Copyright (C) 2003-2007, Robert Oostenveld, SMI, FCDC +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_preprocessing.m 1423 2010-07-18 12:34:47Z roboos $ + +fieldtripdefs + +if nargin==0 + help(mfilename); + return +elseif nargin==1 && isequal(cfg, 'help') + help(mfilename); + return +elseif nargin==1 && isequal(cfg, 'guidelines') + guidelines(mfilename); + return +end + +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +% set the defaults +if ~isfield(cfg, 'method'), cfg.method = 'trial'; end +if ~isfield(cfg, 'channel'), cfg.channel = {'all'}; end +if ~isfield(cfg, 'removemcg'), cfg.removemcg = 'no'; end +if ~isfield(cfg, 'removeeog'), cfg.removeeog = 'no'; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end % this is for exporting to another file format + +if ~isfield(cfg, 'feedback'), + if strcmp(cfg.method, 'channel') + cfg.feedback = 'none'; + else + cfg.feedback = 'text'; + end +end + +if ~isfield(cfg, 'precision'), cfg.precision = 'double'; end +if ~isfield(cfg, 'padding'), cfg.padding = 0; end % padding is only done when filtering +if ~isfield(cfg, 'paddir'), cfg.paddir = 'both'; end +if ~isfield(cfg, 'headerformat'), cfg.headerformat = []; end % is passed to low-level function, empty implies autodetection +if ~isfield(cfg, 'dataformat'), cfg.dataformat = []; end % is passed to low-level function, empty implies autodetection + +% these options relate to the actual preprocessing, it is neccessary to specify here because of padding +if ~isfield(cfg, 'dftfilter'), cfg.dftfilter = 'no'; end +if ~isfield(cfg, 'lpfilter'), cfg.lpfilter = 'no'; end +if ~isfield(cfg, 'hpfilter'), cfg.hpfilter = 'no'; end +if ~isfield(cfg, 'bpfilter'), cfg.bpfilter = 'no'; end +if ~isfield(cfg, 'bsfilter'), cfg.bsfilter = 'no'; end +if ~isfield(cfg, 'medianfilter'), cfg.medianfilter = 'no'; end +% these options relate to the actual preprocessing, it is neccessary to specify here because of channel selection +if ~isfield(cfg, 'reref'), cfg.reref = 'no'; end +if ~isfield(cfg, 'refchannel'), cfg.refchannel = {}; end +if ~isfield(cfg, 'implicitref'), cfg.implicitref = []; end + +% support for the following options was removed on 20 August 2004 in Revision 1.46 +if isfield(cfg, 'emgchannel'), error('EMG specific preprocessing is not supported any more'); end +if isfield(cfg, 'emghpfreq'), error('EMG specific preprocessing is not supported any more'); end +if isfield(cfg, 'emgrectify'), error('EMG specific preprocessing is not supported any more'); end +if isfield(cfg, 'emghilbert'), error('EMG specific preprocessing is not supported any more'); end +if isfield(cfg, 'eegchannel'), error('EEG specific preprocessing is not supported any more'); end +if isfield(cfg, 'resamplefs'), error('resampling is not supported any more, see RESAMPLEDATA'); end + +if isfield(cfg, 'lnfilter') && strcmp(cfg.lnfilter, 'yes') + error('line noise filtering using the option cfg.lnfilter is not supported any more, use cfg.bsfilter instead') +end + +% this option has been renamed? +cfg = checkconfig(cfg, 'renamed', {'output', 'export'}); + +%this relates to a previous fix to handle 32 bit neuroscan data +if isfield(cfg, 'nsdf'), + %FIXME this should be handled by checkconfig, but checkconfig does not allow yet for + %specific errors in the case of forbidden fields + error('the use of cfg.nsdf is deprecated. fieldtrip tries to determine the bit resolution automatically. you can overrule this by specifying cfg.dataformat and cfg.headerformat. see: http://fieldtrip.fcdonders.nl/faq/i_have_problems_reading_in_neuroscan_.cnt_files._how_can_i_fix_this'); +end + +if isfield(cfg, 'export') && ~isempty(cfg.export) + % export the data to an output file + if ~strcmp(cfg.method, 'trial') + error('exporting to an output file is only possible when processing all channels at once') + end +end + +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + hasdata = true; + end +end + +if hasdata + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % do preprocessing of data that has already been read into memory + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + % the input data must be raw + data = checkdata(data, 'datatype', 'raw', 'hasoffset', 'yes'); + + % check if the input cfg is valid for this function + cfg = checkconfig(cfg, 'forbidden', {'trl', 'dataset', 'datafile', 'headerfile'}); + + if cfg.padding>0 + error('cfg.padding should be zero, since filter padding is only possible while reading the data from file'); + end + + % set the defaults + if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end + + % select trials of interest + if ~strcmp(cfg.trials, 'all') + data = selectdata(data, 'rpt', cfg.trials); + if isfield(data, 'cfg'), + cfg.trl = findcfg(data.cfg, 'trl'); + cfg.trlold = findcfg(data.cfg, 'trlold'); + end + end + + % translate the channel groups (like 'all' and 'MEG') into real labels + cfg.channel = ft_channelselection(cfg.channel, data.label); + rawindx = match_str(data.label, cfg.channel); + + % this will contain the newly processed data + dataout = []; + % take along relevant fields of input data to output data + if isfield(data, 'hdr'), dataout.hdr = data.hdr; end + if isfield(data, 'fsample'), dataout.fsample = data.fsample; end + if isfield(data, 'grad'), dataout.grad = data.grad; end + if isfield(data, 'elec'), dataout.elec = data.elec; end + if isfield(data, 'trialdef'), dataout.trialdef = data.trialdef; end + if isfield(data, 'trialinfo'), dataout.trialinfo = data.trialinfo; end + + progress('init', cfg.feedback, 'preprocessing'); + ntrl = length(data.trial); + dataout.trial = cell(1, ntrl); + dataout.time = cell(1, ntrl); + for i=1:ntrl + progress(i/ntrl, 'preprocessing trial %d from %d\n', i, ntrl); + % do the preprocessing on the selected channels + [dataout.trial{i}, dataout.label, dataout.time{i}, cfg] = preproc(data.trial{i}(rawindx,:), data.label(rawindx), data.fsample, cfg, data.offset(i)); + end % for all trials + progress('close'); + +else + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % read the data from file and do the preprocessing + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + if isfield(cfg, 'trialdef') && ~isfield(cfg, 'trl') + error('you must call FT_DEFINETRIAL prior to FT_PREPROCESSING'); + end + + % check if the input cfg is valid for this function + cfg = checkconfig(cfg, 'dataset2files', {'yes'}); + cfg = checkconfig(cfg, 'required', {'headerfile', 'datafile'}); + cfg = checkconfig(cfg, 'renamed', {'datatype', 'continuous'}); + cfg = checkconfig(cfg, 'renamedval', {'continuous', 'continuous', 'yes'}); + + % read the header + hdr = ft_read_header(cfg.headerfile, 'headerformat', cfg.headerformat); + + % this option relates to reading over trial boundaries in a pseudo-continuous dataset + if ~isfield(cfg, 'continuous') + if hdr.nTrials==1 + cfg.continuous = 'yes'; + else + cfg.continuous = 'no'; + end + end + + % this should be a cell array + if ~iscell(cfg.channel) && ischar(cfg.channel) + cfg.channel = {cfg.channel}; + end + + % this should be a cell array + if ~iscell(cfg.refchannel) && ischar(cfg.refchannel) + cfg.refchannel = {cfg.refchannel}; + end + + % do a sanity check for the re-referencing + if strcmp(cfg.reref, 'no') && ~isempty(cfg.refchannel) + warning('no re-referencing is performed'); + cfg.refchannel = {}; + end + + % translate the channel groups (like 'all' and 'MEG') into real labels + cfg.channel = ft_channelselection(cfg.channel, hdr.label); + + if ~isempty(cfg.implicitref) + % add the label of the implicit reference channel to these cell-arrays + cfg.channel = cat(1, cfg.channel(:), cfg.implicitref); + end + cfg.refchannel = ft_channelselection(cfg.refchannel, cfg.channel); + + % determine the length in samples to which the data should be padded before filtering is applied + % the filter padding is done by reading a longer segment of data from the original data file + if cfg.padding>0 + if strcmp(cfg.dftfilter, 'yes') || ... + strcmp(cfg.lpfilter, 'yes') || ... + strcmp(cfg.hpfilter, 'yes') || ... + strcmp(cfg.bpfilter, 'yes') || ... + strcmp(cfg.bsfilter, 'yes') || ... + strcmp(cfg.medianfilter, 'yes') + padding = round(cfg.padding * hdr.Fs); + else + % no filtering will be done, hence no padding is neccessary + padding = 0; + end + % update the configuration (in seconds) for external reference + cfg.padding = padding / hdr.Fs; + else + % no padding was requested + padding = 0; + end + + if ~isfield(cfg, 'trl') + % treat the data as continuous if possible, otherwise define all trials as indicated in the header + if strcmp(cfg.continuous, 'yes') + trl = zeros(1, 3); + trl(1,1) = 1; + trl(1,2) = hdr.nSamples*hdr.nTrials; + trl(1,3) = -hdr.nSamplesPre; + else + trl = zeros(hdr.nTrials, 3); + for i=1:hdr.nTrials + trl(i,1) = (i-1)*hdr.nSamples + 1; + trl(i,2) = (i )*hdr.nSamples ; + trl(i,3) = -hdr.nSamplesPre; + end + end + cfg.trl = trl; + end + + if any(strmatch('reject', fieldnames(cfg))) || ... + any(strmatch('rejecteog', fieldnames(cfg))) || ... + any(strmatch('rejectmuscle', fieldnames(cfg))) || ... + any(strmatch('rejectjump', fieldnames(cfg))) + % this is only for backward compatibility + error('you should call FT_REJECTARTIFACT prior to FT_PREPROCESSING, please update your scripts'); + end + + ntrl = size(cfg.trl,1); + if ntrl<1 + error('no trials were selected for preprocessing, see FT_DEFINETRIAL for help'); + end + + % compute the template for MCG and the QRS latency indices, and add it to the configuration + if strcmp(cfg.removemcg, 'yes') + cfg = template_mcg(cfg); + mcgchannel = ft_channelselection(cfg.artfctdef.mcg.channel, hdr.label); + mcgindx = match_str(cfg.channel, mcgchannel); + for i=1:length(mcgchannel) + fprintf('removing mcg on channel %s\n', mcgchannel{i}); + end + end + + % determine the channel numbers of interest for preprocessing + [chnindx, rawindx] = match_str(cfg.channel, hdr.label); + + if strcmp(cfg.method, 'channel') + % read one channel at a time, loop over channels and over trials + chnloop = mat2cell(chnindx, ones(length(chnindx), 1), 1); + rawloop = mat2cell(rawindx, ones(length(chnindx), 1), 1); + + elseif strcmp(cfg.method, 'trial') + % read all channels simultaneously, only loop trials + chnloop = {chnindx}; + rawloop = {rawindx}; + + else + error('unsupported option for cfg.method'); + end + + for j=1:length(chnloop) + % read one channel group at a time, this speeds up combined datasets + % a multiplexed dataformat is faster if you read all channels, one trial at a time + chnindx = chnloop{j}; + rawindx = rawloop{j}; + + fprintf('processing channel { %s}\n', sprintf('''%s'' ', hdr.label{rawindx})); + + progress('init', cfg.feedback, 'reading and preprocessing'); + for i=1:ntrl + progress(i/ntrl, 'reading and preprocessing trial %d from %d\n', i, ntrl); + % non-zero padding is used for filtering and line noise removal + nsamples = cfg.trl(i,2)-cfg.trl(i,1)+1; + if nsamples>padding + % the trial is already longer than the total lenght requested + begsample = cfg.trl(i,1); + endsample = cfg.trl(i,2); + begpadding = 0; + endpadding = 0; + else + switch cfg.paddir + case 'both' + % begpadding+nsamples+endpadding = total length of raw data that will be read + begpadding = ceil((padding-nsamples)/2); + endpadding = floor((padding-nsamples)/2); + case 'left' + begpadding = padding-nsamples; + endpadding = 0; + case 'right' + begpadding = 0; + endpadding = padding-nsamples; + otherwise + error('unsupported requested direction of padding'); + end + + begsample = cfg.trl(i,1) - begpadding; + endsample = cfg.trl(i,2) + endpadding; + if begsample<1 + warning('cannot apply enough padding at begin of file'); + begpadding = begpadding - (1 - begsample); + begsample = 1; + end + if endsample>(hdr.nSamples*hdr.nTrials) + warning('cannot apply enough padding at end of file'); + endpadding = endpadding - (endsample - hdr.nSamples*hdr.nTrials); + endsample = hdr.nSamples*hdr.nTrials; + end + end + + % read the raw data with padding on both sides of the trial + dat = ft_read_data(cfg.datafile, 'header', hdr, 'begsample', begsample, 'endsample', endsample, 'chanindx', rawindx, 'checkboundary', strcmp(cfg.continuous, 'no'), 'dataformat', cfg.dataformat); + + % do the preprocessing on the padded trial data and remove the padding after filtering + [cutdat{i}, label, time{i}, cfg] = preproc(dat, hdr.label(rawindx), hdr.Fs, cfg, cfg.trl(i,3), begpadding, endpadding); + + if isfield(cfg, 'export') && ~isempty(cfg.export) + % write the processed data to an original manufacturer format file + newhdr = []; + newhdr.Fs = hdr.Fs; + newhdr.label = label; + newhdr.nChans = length(newhdr.label); + % only append for the second and consecutive trials + ft_write_data(cfg.export.dataset, cutdat{i}, 'dataformat', cfg.export.dataformat, 'header', newhdr, 'append', i~=1); + if nargout==0 + % don't keep th eprocessed data in memory + cutdat(i) = []; + end + end + + end % for all trials + progress('close'); + + dataout = []; + dataout.hdr = hdr; % header details of the datafile + dataout.label = label; % labels of channels that have been read, can be different from labels in file due to montage + dataout.time = time; % vector with the timeaxis for each individual trial + dataout.trial = cutdat; + dataout.fsample = hdr.Fs; + dataout.trialdef = cfg.trl(:,1:2); + if size(cfg.trl,2) > 3 + dataout.trialinfo = cfg.trl(:,4:end); + end + if isfield(hdr, 'grad') + dataout.grad = hdr.grad; % gradiometer system in head coordinates + end + + end % for all channel groups + +end % if hasdata + +% accessing this field here is needed for the configuration tracking +% by accessing it once, it will not be removed from the output cfg +cfg.outputfile; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add the version details of this function call to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_preprocessing.m 1423 2010-07-18 12:34:47Z roboos $'; + +if hasdata && isfield(data, 'cfg') + % remember the configuration details of the input data + cfg.previous = data.cfg; +end + +% remember the exact configuration details in the output +dataout.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', dataout); % use the variable name "data" in the output file +end diff --git a/external/fieldtrip/ft_read_fcdc_mri.m b/external/fieldtrip/ft_read_fcdc_mri.m deleted file mode 100644 index b84b9b2..0000000 --- a/external/fieldtrip/ft_read_fcdc_mri.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'ft_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_recodeevent.m b/external/fieldtrip/ft_recodeevent.m index b84b9b2..c894161 100644 --- a/external/fieldtrip/ft_recodeevent.m +++ b/external/fieldtrip/ft_recodeevent.m @@ -1,11 +1,236 @@ -function varargout = funname(varargin); +function [ev] = ft_recodeevent(cfg, event, trl) -% this is a SPM wrapper around a FieldTrip function +% FT_RECODEEVENT will recode the event structure, given the trial +% definition that was analyzed +% +% In FieldTrip, you always start with defining a "trl" field containing +% the samples in the raw datafile that you want to analyze. That "trl" +% is based on the events in the dataset. After artifact rejection, it may +% be the case that trials have been removed completely, or that trials +% have been cut into pieces. This complicates finding a match between the +% original events and the pieces of data that are analyzed. This functino +% restores that match. +% +% Use as +% [ev] = ft_recodeevent(cfg, data) +% where cfg is a structure with configuration settings and data contains the +% (nested) configuration that describes the original trial definition and +% event structure. +% +% Alternatively, you can also specify the event structure and trial definition +% yourself with +% [ev] = ft_recodeevent(cfg, event, trl) +% +% the configuration can contain +% cfg.eventtype = empty, 'string' or cell-array with multiple strings +% cfg.eventvalue = empty or a list of event values (can be numeric or string) +% +% cfg.searchrange = 'anywhere' search anywhere for the event, (default) +% 'insidetrial' only search inside +% 'outsidetrial' only search outside +% 'beforetrial' only search before the trial +% 'aftertrial' only search after the trial +% 'beforezero' only search before time t=0 of each trial +% 'afterzero' only search after time t=0 of each trial +% +% cfg.nearestto = 'trialzero' compare with time t=0 for each trial (default) +% 'trialbegin' compare with the begin of each trial +% 'trialend' compare with the end of each trial +% +% cfg.match = 'exact' or 'nearest' +% +% cfg.output = 'event' the event itself +% 'eventvalue' the value of the event +% 'eventnumber' the number of the event +% 'samplenumber' the sample at which the event is located +% 'samplefromoffset' number of samples from t=0 (c.f. response time) +% 'samplefrombegin' number of samples from the begin of the trial +% 'samplefromend' number of samples from the end of the trial -% this part is variable -prefix = 'ft_'; +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_recodeevent.m 948 2010-04-21 18:02:21Z roboos $ + +fieldtripdefs + +% set the defaults +if ~isfield(cfg, 'eventtype'), cfg.eventtype = []; end +if ~isfield(cfg, 'eventvalue'), cfg.eventvalue = []; end +if ~isfield(cfg, 'searchrange'),cfg.searchrange = 'anywhere'; end +if ~isfield(cfg, 'nearestto'), cfg.nearestto = 'trialzero'; end +if ~isfield(cfg, 'match'), cfg.match = 'nearest'; end +if ~isfield(cfg, 'output'), cfg.output = 'eventvalue'; end + +% these should be numeric lists or cell-arrays with strings +if ischar(cfg.eventtype) + cfg.eventtype = {cfg.eventtype}; +end +if ischar(cfg.eventvalue) + cfg.eventvalue = {cfg.eventvalue}; +end + +if nargin==2 + % event and trl are not specified in the function call, but the data is given -> + % try to locate event and trl in the configuration + data = event; % rename the input variable + event = findcfg(data.cfg, 'event'); % search for the event field + trl = findcfg(data.cfg, 'trl'); % search for the trl field + if isempty(event) + error('could not locate event structure in the data'); + elseif isempty(trl) + error('could not locate trial definition in the data'); + end +elseif nargin~=3 + error('incorrect number of input arguments'); +end + +Ntrl = size(trl,1); +Nevent = length(event); + +% select the events of interest +fprintf('trial definition describes %d trials\n', Ntrl); +fprintf('original event structure contains %d events\n', Nevent); +selecttype = zeros(Nevent,1); +selectvalue = zeros(Nevent,1); +for i=1:Nevent + % test whether this event should be selected + if ~isempty(cfg.eventtype) + selecttype(i) = ~isempty(intersect(cfg.eventtype, event(i).type)); + else + selecttype(i) = 1; + end + % test whether this event should be selected + if ~isempty(cfg.eventvalue) + selectvalue(i) = ~isempty(intersect(cfg.eventvalue, event(i).value)); + else + selectvalue(i) = 1; + end +end +fprintf('selected %d events based on event type\n', sum(selecttype)); +fprintf('selected %d events based on event value\n', sum(selectvalue)); +fprintf('selected %d events based on event type and value\n', sum(selecttype.*selectvalue)); +eventnum = find(selecttype.*selectvalue); +event = event(eventnum); +Nevent = length(event); + +if Nevent<1 + error('there are no events to analyze'); +end + +% make a list with the sample, offset and duration of each event +% and sort the events according to the sample at which they occurred +sample = zeros(Nevent,1); +offset = zeros(Nevent,1); +duration = zeros(Nevent,1); +for i=1:Nevent + sample(i) = event(i).sample; + if ~isempty(event(i).offset) + offset(i) = event(i).offset; + else + offset(i) = nan; + end + if ~isempty(event(i).duration) + duration(i) = event(i).duration; + else + duration(i) = nan; + end +end +[sample, indx] = sort(sample); % sort the samples +offset = offset(indx); % sort the offset accordingly +duration = duration(indx); % sort the duration accordingly +event = event(indx); % sort the events accordingly +eventnum = eventnum(indx); % sort the numbers of the original events + +for i=1:Ntrl + trlbeg = trl(i,1); + trlend = trl(i,2); + trloffset = trl(i,3); + trlzero = trlbeg - trloffset; % the sample that corresponds with t=0 + + if strcmp(cfg.nearestto, 'trialzero') + trlsample = trlzero; % the sample that corresponds with t=0 + elseif strcmp(cfg.nearestto, 'trialbegin') + trlsample = trlbeg; % the sample at which the trial begins + elseif strcmp(cfg.nearestto, 'trialend') + trlsample = trlend; % the sample at which the trial ends + else + error('incorrect specification of cfg.nearestto') + end + + % compute a "distance" measure for each event towards this trial + switch cfg.searchrange + case 'anywhere' + distance = abs(sample - trlsample); + case 'beforezero' + distance = abs(sample - trlsample); + distance(find(sample>=trlzero)) = inf; + case 'afterzero' + distance = abs(sample - trlsample); + distance(find(sample<=trlzero)) = inf; + case 'beforetrial' + distance = abs(sample - trlsample); + distance(find(sample>=trlbeg)) = inf; + case 'aftertrial' + distance = abs(sample - trlsample); + distance(find(sample<=trlend)) = inf; + case 'insidetrial' + distance = abs(sample - trlsample); + distance(find((sampletrlend))) = inf; + case 'outsidetrial' + distance = abs(sample - trlsample); + distance(find((sample>=trlbeg) & (sample<=trlend))) = inf; + otherwise + error('incorrect specification of cfg.searchrange'); + end + + % determine the event that has the shortest distance towards this trial + [mindist, minindx] = min(distance); + if length(find(distance==mindist))>1 + error('multiple events are at the same distance from the trial'); + end + + if isinf(mindist) + % no event was found + ev(i) = nan; + elseif mindist~=0 && strcmp(cfg.match, 'exact') + % the event is not an exact match + ev(i) = nan; + else + switch cfg.output + case 'event' + ev(i) = event(minindx); + case 'eventvalue' + ev(i) = event(minindx).value; + case 'eventnumber' + ev(i) = eventnum(minindx); + case 'samplenumber' + ev(i) = event(minindx).sample; + case 'samplefromoffset' + ev(i) = event(minindx).sample - trlzero; + case 'samplefrombegin' + ev(i) = event(minindx).sample - trlbeg; + case 'samplefromend' + ev(i) = event(minindx).sample - trlend; + otherwise + error('incorrect specification of cfg.output'); + end + end + +end % looping over all trials -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_redefinetrial.m b/external/fieldtrip/ft_redefinetrial.m index b84b9b2..dd90ccd 100644 --- a/external/fieldtrip/ft_redefinetrial.m +++ b/external/fieldtrip/ft_redefinetrial.m @@ -1,11 +1,332 @@ -function varargout = funname(varargin); +function [data] = ft_redefinetrial(cfg, data) -% this is a SPM wrapper around a FieldTrip function +% FT_REDEFINETRIAL allows you to adjust the time axis of your data, i.e. to +% change from stimulus-locked to response-locked. Furthermore, it allows +% you to select a time window of interest, or to resegment your long trials +% into shorter fragments. +% +% Use as +% data = ft_redefinetrial(cfg, data) +% where the input data should correspond to the output of FT_PREPROCESSING and +% the configuration should be specified as explained below. Note that some +% options are mutually exclusive, and require two calls to this function to +% avoid confucion about the order in which they are applied. +% +% For selecting a subset of trials you can specify +% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') +% +% For selecting trials with a minimum length you can specify +% cfg.minlength = length in seconds, can be 'maxperlen' (default = []) +% +% For realiging the time axes of all trials to a new reference time +% point (i.e. change the definition for t=0) you can use the following +% configuration option +% cfg.offset = single number or Nx1 vector, expressed in samples relative to current t=0 +% +% For selecting a specific subsection of (i.e. cut out a time window +% of interest) you can select a time window in seconds that is common +% in all trials +% cfg.toilim = [tmin tmax] to specify a latency window in seconds +% +% Alternatively you can specify the begin and end sample in each trial +% cfg.begsample = single number or Nx1 vector, expressed in samples relative to the start of the input trial +% cfg.endsample = single number or Nx1 vector, expressed in samples relative to the start of the input trial +% +% Alternatively you can specify a new trial definition, expressed in +% samples relative to the original recording +% cfg.trl = Nx3 matrix with the trial definition, see FT_DEFINETRIAL +% +% See also FT_DEFINETRIAL, FT_RECODEEVENT, FT_PREPROCESSING +% +% Undocumented local options: +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk -% this part is variable -prefix = 'ft_'; +% Copyright (C) 2006-2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_redefinetrial.m 1435 2010-07-21 11:45:18Z jansch $ -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +fieldtripdefs + +% set the defaults +if ~isfield(cfg, 'offset'), cfg.offset = []; end +if ~isfield(cfg, 'toilim'), cfg.toilim = []; end +if ~isfield(cfg, 'begsample'), cfg.begsample = []; end +if ~isfield(cfg, 'endsample'), cfg.endsample = []; end +if ~isfield(cfg, 'minlength'), cfg.minlength = []; end +if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end +if ~isfield(cfg, 'feedback'), cfg.feedback = 'yes'; end +if ~isfield(cfg, 'trl'), cfg.trl = []; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +% load optional given inputfile as data +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + end +end + +% check if the input data is valid for this function +data = checkdata(data, 'datatype', 'raw', 'feedback', cfg.feedback); +fb = strcmp(cfg.feedback, 'yes'); + +% trl is not specified in the function call, but the data is given -> +% recreate trl-matrix from trialdef and time axes, or +% try to locate the trial definition (trl) in the nested configuration +if isfield(data, 'trialdef') + trl = data.trialdef; + trl(:, 3) = 0; + for k = 1:numel(data.trial) + trl(k, 3) = time2offset(data.time{k}, data.fsample); + end +elseif isfield(data,'cfg') + trl = findcfg(data.cfg, 'trl'); + if length(data.trial)~=size(trl,1) || length(data.time)~=size(trl,1) + error('the trial definition in the configuration is inconsistent with the data'); + end +else + trl = []; +end +trlold = trl; + +% select trials of interest +if ~strcmp(cfg.trials, 'all') + if fb, fprintf('selecting %d trials\n', length(cfg.trials)); end + data = selectdata(data, 'rpt', cfg.trials); + if length(cfg.offset)>1 && length(cfg.offset)~=length(cfg.trials) + cfg.offset=cfg.offset(cfg.trials); + end + if length(cfg.begsample)>1 && length(cfg.begsample)~=length(cfg.trials) + cfg.begsample=cfg.begsample(cfg.trials); + end + if length(cfg.endsample)>1 && length(cfg.endsample)~=length(cfg.trials) + cfg.endsample=cfg.endsample(cfg.trials); + end + + % also update the trl-matrix + if ~isempty(trl) + trl = trl(cfg.trials, :); + end + +end +Ntrial = numel(data.trial); + +% check the input arguments, only one method for processing is allowed +numoptions = ~isempty(cfg.toilim) + ~isempty(cfg.offset) + (~isempty(cfg.begsample) || ~isempty(cfg.endsample)) + ~isempty(cfg.trl); +if numoptions>1 + error('you should specify only one of the options for redefining the data segments'); +end +if numoptions==0 && isempty(cfg.minlength) && strcmp(cfg.trials, 'all') + error('you should specify at least one configuration option'); +end + +% start processing +if ~isempty(cfg.toilim) + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % select a latency window from each trial + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + begsample = zeros(Ntrial,1); + endsample = zeros(Ntrial,1); + offset = zeros(Ntrial,1); + skiptrial = zeros(Ntrial,1); + for i=1:Ntrial + if cfg.toilim(1)>data.time{i}(end) || cfg.toilim(2)=begsample & dataold.trialdef(:,2)<=endsample); + if numel(iTrlorig)==1 && isfield(dataold, 'trialinfo'), + data.trialinfo(iTrl,:) = dataold.trialinfo(iTrlorig,:); + elseif isfield(dataold, 'trialinfo'), + remove = 1; + end + end + data.hdr = hdr; + data.label = dataold.label; + data.fsample = dataold.fsample; + if isfield(dataold, 'grad') + data.grad = dataold.grad; + end + if isfield(dataold, 'elec') + data.elec = dataold.elec; + end + if remove + data = rmfield(data, 'trialinfo'); + end + if isfield(dataold, 'trialdef') + % adjust the trial definition + data.trialdef = trl(:, 1:2); + end +end % processing the realignment or data selection + +if ~isempty(cfg.minlength) + Ntrial = length(data.trial); + trllength = zeros(Ntrial, 1); + % determine the length of each trial + for i=1:Ntrial + trllength(i) = data.time{i}(end) - data.time{i}(1); + end + if ischar(cfg.minlength) && strcmp(cfg.minlength, 'maxperlen') + minlength = max(trllength); + else + minlength = cfg.minlength; + end + % remove trials that are too short + skiptrial = (trllength. +% +% $Id: ft_rejectartifact.m 1436 2010-07-21 11:46:40Z jansch $ + +fieldtripdefs + +if 0 + % this code snippet ensures that these functions are included in the + % documentation as dependencies + try, dum = ft_artifact_ecg; end + try, dum = ft_artifact_eog; end + try, dum = ft_artifact_muscle; end + try, dum = ft_artifact_jump; end + try, dum = ft_artifact_clip; end + try, dum = ft_artifact_manual; end + try, dum = ft_artifact_threshold; end +end + +% check if the input cfg is valid for this function +cfg = checkconfig(cfg, 'trackconfig', 'on'); +cfg = checkconfig(cfg, 'dataset2files', {'yes'}); + +% set the defaults +if ~isfield(cfg, 'artfctdef'), cfg.artfctdef = []; end +if ~isfield(cfg.artfctdef,'type'), cfg.artfctdef.type = {}; end +if ~isfield(cfg.artfctdef,'reject'), cfg.artfctdef.reject = 'complete'; end +if ~isfield(cfg.artfctdef,'minaccepttim'), cfg.artfctdef.minaccepttim = 0.1; end +if ~isfield(cfg.artfctdef,'feedback'), cfg.artfctdef.feedback = 'no'; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end + +% convert from old-style to new-style configuration +if isfield(cfg,'reject') + warning('converting from old-style artifact configuration to new-style'); + cfg.artfctdef.reject = cfg.reject; + cfg = rmfield(cfg, 'reject'); +end + +% convert from old-style to new-style configuration +if isfield(cfg.artfctdef,'common') + warning('converting from old-style artifact configuration to new-style'); + if isfield(cfg.artfctdef.common,'minaccepttim') + cfg.artfctdef.minaccepttim = cfg.artfctdef.common.minaccepttim; + cfg.artfctdef = rmfield(cfg.artfctdef, 'common'); + end +end + +% ensure that it is a cell array +if ischar(cfg.artfctdef.type) + cfg.artfctdef.type = {cfg.artfctdef.type}; +end + +% support the rejectXXX cfg settings for backward compatibility +if isfield(cfg, 'rejectmuscle') + dum = strmatch('muscle', cfg.artfctdef.type, 'exact'); + if strcmp(cfg.rejectmuscle,'yes') && isempty(dum) + % this overrules the other setting, add it to the type-list + cfg.artfctdef.type = cat(1, {'muscle'}, cfg.artfctdef.type(:)); + elseif strcmp(cfg.rejectmuscle,'no') && ~isempty(dum) + % this overrules the other setting, remove it from the type-list + cfg.artfctdef.type(dum) = []; + end + cfg = rmfield(cfg, 'rejectmuscle'); +end + +% support the rejectXXX cfg settings for backward compatibility +if isfield(cfg, 'rejecteog') + dum = strmatch('eog', cfg.artfctdef.type, 'exact'); + if strcmp(cfg.rejecteog,'yes') && isempty(dum) + % this overrules the other setting, add it to the type-list + cfg.artfctdef.type = cat(1, {'eog'}, cfg.artfctdef.type(:)); + elseif strcmp(cfg.rejecteog,'no') && ~isempty(dum) + % this overrules the other setting, remove it from the type-list + cfg.artfctdef.type(dum) = []; + end + cfg = rmfield(cfg, 'rejecteog'); +end + +% support the rejectXXX cfg settings for backward compatibility +if isfield(cfg, 'rejectjump') + dum = strmatch('jump', cfg.artfctdef.type, 'exact'); + if strcmp(cfg.rejectjump,'yes') && isempty(dum) + % this overrules the other setting, add it to the type-list + cfg.artfctdef.type = cat(1, {'jump'}, cfg.artfctdef.type(:)); + elseif strcmp(cfg.rejectjump,'no') && ~isempty(dum) + % this overrules the other setting, remove it from the type-list + cfg.artfctdef.type(dum) = []; + end + cfg = rmfield(cfg, 'rejectjump'); +end + +% support the rejectXXX cfg settings for backward compatibility +if isfield(cfg, 'rejectfile') + % this is slightly different to the ones above, since rejectfile is either 'no' or contains the filename + dum = strmatch('file', cfg.artfctdef.type, 'exact'); + if ~strcmp(cfg.rejectfile,'no') && isempty(dum) + % this overrules the other setting, add it to the type-list + cfg.artfctdef.type = cat(1, {'file'}, cfg.artfctdef.type(:)); + elseif strcmp(cfg.rejectfile,'no') && ~isempty(dum) + % this overrules the other setting, remove it from the type-list + cfg.artfctdef.type(dum) = []; + end +end + +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + hasdata = true; + end +end + +if hasdata + data = checkdata(data, 'hastrialdef', 'yes', 'hasoffset', 'yes'); + if isfield(data, 'trialdef') + trl = [data.trialdef data.offset(:)]; + if isfield(data, 'trialinfo') + trl(:, 3+(1:size(data.trialinfo,2))) = data.trialinfo; + end + else + trl = []; + end +elseif isfield(cfg, 'trl') + trl = cfg.trl; +end + +% ensure that there are trials that can be scanned for artifacts and/or rejected +if isempty(trl) + error('no trials were selected, cannot perform artifact detection/rejection'); +end + +% prevent double occurences of artifact types, ensure that the order remains the same +[dum, i] = unique(cfg.artfctdef.type); +cfg.artfctdef.type = cfg.artfctdef.type(sort(i)); +% ensure that it is a row vector +cfg.artfctdef.type = cfg.artfctdef.type(:)'; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% call the appropriate function for each of the artifact types +% this will produce a Nx2 matrix with the begin and end sample of artifacts +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +for type=1:length(cfg.artfctdef.type) + fprintf('evaluating artifact_%s\n', cfg.artfctdef.type{type}); + % each call to artifact_xxx adds cfg.artfctdef.xxx.artifact + cfg = feval(sprintf('artifact_%s', cfg.artfctdef.type{type}), cfg); +end + +% collect the artifacts that have been detected from cfg.artfctdef.xxx.artifact +dum = fieldnames(cfg.artfctdef); +sel = []; +artifact = {}; +for i=1:length(dum) + sel(i) = issubfield(cfg.artfctdef, dum{i}) && issubfield(cfg.artfctdef, [dum{i} '.artifact']); + if sel(i) + artifact{end+1} = getsubfield(cfg.artfctdef, [dum{i} '.artifact']); + num = size(artifact{end}, 1); + if isempty(num) + num = 0; + end + fprintf('detected %3d %s artifacts\n', num, dum{i}); + end +end +% update the configuration to reflect the artifacts types that were scanned +cfg.artfctdef.type = dum(find(sel)); + +% combine all trials into a single boolean vector +trialall = convert_event(trl, 'boolvec'); + +% combine all artifacts into a single vector +rejectall = zeros(1,max(trl(:,2))); +for i=1:length(cfg.artfctdef.type) + dum = artifact{i}; + for j=1:size(dum,1) + rejectall(dum(j,1):dum(j,2)) = i; % the artifact type is coded here + end +end + +% ensure that both vectors are the same length +if length(trialall)>length(rejectall) + rejectall(length(trialall)) = 0; +elseif length(trialall)1 +% if isempty(cfg.trl) +% error('No trials left after artifact rejection.') +% else +% tmpcfg = []; +% tmpcfg.trl = cfg.trl; +% data = ft_redefinetrial(tmpcfg,data); +% % remember the configuration details, this overwrites the stored configuration of redefinetrial +% data.cfg = cfg; +% % return the data instead of the cfg +% cfg = data; +% end +% end + + diff --git a/external/fieldtrip/ft_rejectcomponent.m b/external/fieldtrip/ft_rejectcomponent.m index b84b9b2..f176d0b 100644 --- a/external/fieldtrip/ft_rejectcomponent.m +++ b/external/fieldtrip/ft_rejectcomponent.m @@ -1,11 +1,183 @@ -function varargout = funname(varargin); +function [data] = ft_rejectcomponent(cfg, comp, data) -% this is a SPM wrapper around a FieldTrip function +% FT_REJECTCOMPONENT backprojects an ICA (or similar) decomposition to the +% channel level after removing the independent components that contain +% the artifacts. This function does not automatically detect the artifact +% components, you will have to do that yourself. +% +% Use as +% [data] = ft_rejectcomponent(cfg, comp) +% or as +% [data] = ft_rejectcomponent(cfg, comp, data) +% +% where the input comp is the result of FT_COMPONENTANALYSIS. The output +% data will have the same format as the output of FT_PREFPROCESSING. +% An optional input argument data can be provided. In that case +% componentanalysis will do a subspace projection of the input data +% onto the space which is spanned by the topographies in the unmixing +% matrix in comp, after removal of the artifact components. +% +% The configuration should contain +% cfg.component = list of components to remove, e.g. [1 4 7] +% +% See also FT_COMPONENTANALYSIS, FT_PREFPROCESSING +% +% Undocumented local options: +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk -% this part is variable -prefix = 'ft_'; +% Copyright (C) 2005-2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_rejectcomponent.m 1258 2010-06-22 08:33:48Z timeng $ -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +fieldtripdefs + +% set defaults +if ~isfield(cfg, 'component'), cfg.component = []; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +if nargin==3 + ntrials = length(data.trial); + data = checkdata(data, 'datatype', 'raw'); + label = data.label; +elseif nargin==2 + ntrials = length(comp.trial); + label = comp.topolabel; +else nargin<2 % only cfg is given; inputfile is expected + comp = loadvar(cfg.inputfile, 'data'); + ntrials = length(comp.trial); + label = comp.topolabel; +end + +comp = checkdata(comp, 'datatype', 'comp'); +ncomps = length(comp.label); + +if min(cfg.component)<1 + error('you cannot remove components that are not present in the data'); +end + +if max(cfg.component)>ncomps + error('you cannot remove components that are not present in the data'); +end + +% set the rejected component amplitudes to zero +fprintf('removing %d components\n', length(cfg.component)); +fprintf('keeping %d components\n', ncomps-length(cfg.component)); + +%create a projection matrix by subtracting the subspace spanned by the +%topographies of the to-be-removed components from identity +[seldat, selcomp] = match_str(label, comp.topolabel); + +if length(seldat)~=length(label) && nargin==3, + warning('the subspace projection is not guaranteed to be correct for non-orthogonal components'); +end + +if nargin==3, + topo = comp.topo(selcomp,:); + invtopo = pinv(topo); + tra = eye(length(selcomp)) - topo(:, cfg.component)*invtopo(cfg.component, :); + %I am not sure about this, but it gives comparable results to the ~hasdata case + %when comp contains non-orthogonal (=ica) topographies, and contains a complete decomposition + + %the following is incorrect + %topo = comp.topo(selcomp, cfg.component); + %tra = eye(size(topo,1)) - topo*pinv(topo); + + %we are going from data to components, and back again + labelorg = comp.topolabel(selcomp); + labelnew = comp.topolabel(selcomp); + + keepunused = 'yes'; %keep the original data which are not present in the mixing provided +else + topo = comp.topo(selcomp, :); + topo(:, cfg.component) = 0; + tra = topo; + + %we are going from components to data + labelorg = comp.label; + labelnew = comp.topolabel(selcomp); + + %create data structure + data = []; + data.trial = comp.trial; + data.time = comp.time; + data.label = comp.label; + data.fsample = comp.fsample; + try, data.grad = comp.grad; end + + keepunused = 'no'; %don't need to keep the original rejected components +end + +%OLD CODE +% recontruct the trials +%for i=1:ntrials +% data.trial{i} = projector * data.trial{i}(seldat,:); +%end +%data.label = data.label(seldat); + +%create montage and apply this to data and grad +montage = []; +montage.tra = tra; +montage.labelorg = labelorg; +montage.labelnew = labelnew; +data = ft_apply_montage(data, montage, 'keepunused', keepunused); +if isfield(data, 'grad'), + data.grad.balance.component = montage; + data.grad.balance.current = 'component'; + data.grad = ft_apply_montage(data.grad, montage, 'keepunused', 'yes'); +else + warning('the gradiometer description does not match the data anymore'); +end + +% accessing this field here is needed for the configuration tracking +% by accessing it once, it will not be removed from the output cfg +cfg.outputfile; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add the version details of this function call to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_rejectcomponent.m 1258 2010-06-22 08:33:48Z timeng $'; +if nargin==2 || nargin < 2 + % remember the configuration details of the input data + try, cfg.previous = comp.cfg; end +elseif nargin==3, + try, cfg.previous{2} = comp.cfg; end + try, cfg.previous{1} = data.cfg; end + %the configuration of the data is relatively more important + %potential use of findcfg in subsequent analysis steps looks into + %the previous{1} first +end + +% keep the configuration in the output +data.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', data); % use the variable name "data" in the output file +end diff --git a/external/fieldtrip/ft_rejectvisual.m b/external/fieldtrip/ft_rejectvisual.m index b84b9b2..8d7f560 100644 --- a/external/fieldtrip/ft_rejectvisual.m +++ b/external/fieldtrip/ft_rejectvisual.m @@ -1,11 +1,375 @@ -function varargout = funname(varargin); +function [data] = ft_rejectvisual(cfg, data); -% this is a SPM wrapper around a FieldTrip function +% FT_REJECTVISUAL shows the preprocessed data in all channels and/or trials to +% allow the user to make a visual selection of the data that should be +% rejected. The data can be displayed in a "summary" mode, in which case +% the variance (or another metric) in each channel and each trial is +% computed. Alternatively, all channels can be shown at once allowing +% paging through the trials, or all trials can be shown, allowing paging +% through the channels. +% +% Use as +% [data] = ft_rejectvisual(cfg, data) +% +% The configuration can contain +% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), +% see FT_CHANNELSELECTION for details +% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') +% cfg.latency = [begin end] in seconds, or 'minperlength', 'maxperlength', +% 'prestim', 'poststim' (default = 'maxperlength') +% cfg.method = string, describes how the data should be shown, this can be +% 'summary' show a single number for each channel and trial (default) +% 'channel' show the data per channel, all trials at once +% 'trial' show the data per trial, all channels at once +% cfg.keepchannel = string, determines how to deal with channels that are +% not selected, can be +% 'no' completely remove unselected channels from the data (default) +% 'yes' keep unselected channels in the output data +% 'nan' fill the channels that are unselected with NaNs +% cfg.metric = string, describes the metric that should be computed in summary mode +% for each channel in each trial, can be +% 'var' variance within each channel (default) +% 'min' minimum value in each channel +% 'max' maximum value each channel +% 'maxabs' maximum absolute value in each channel +% 'range' range from min to max in each channel +% 'kurtosis' kurtosis, i.e. measure of peakedness of the amplitude distribution +% cfg.alim = value that determines the amplitude scaling for the +% channel and trial display, if empty then the amplitude +% scaling is automatic (default = []) +% cfg.eegscale = number, scaling to apply to the EEG channels prior to display +% cfg.eogscale = number, scaling to apply to the EOG channels prior to display +% cfg.ecgscale = number, scaling to apply to the ECG channels prior to display +% cfg.megscale = number, scaling to apply to the MEG channels prior to display +% +% The scaling to the EEG, EOG, ECG and MEG channels is optional and can +% be used to bring the absolute numbers of the different channel types in +% the same range (e.g. fT and uV). The channel types are determined from +% the input data using FT_CHANNELSELECTION. +% +% Optionally, the raw data is preprocessed (filtering etc.) prior to +% displaying it or prior to computing the summary metric. The +% preprocessing and the selection of the latency window is NOT applied +% to the output data. +% +% The following settings are usefull for identifying EOG artifacts: +% cfg.bpfilter = 'yes' +% cfg.bpfilttype = 'but' +% cfg.bpfreq = [1 15] +% cfg.bpfiltord = 4 +% cfg.rectify = 'yes' +% +% The following settings are usefull for identifying muscle artifacts: +% cfg.bpfilter = 'yes' +% cfg.bpfreq = [110 140] +% cfg.bpfiltord = 10 +% cfg.bpfilttype = 'but' +% cfg.rectify = 'yes' +% cfg.boxcar = 0.2 +% +% See also FT_REJECTARTIFACT, FT_REJECTCOMPONENT -% this part is variable -prefix = 'ft_'; +% Undocumented local options: +% cfg.feedback +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk +% +% This function depends on PREPROC which has the following options: +% cfg.absdiff +% cfg.blc +% cfg.blcwindow +% cfg.boxcar +% cfg.bpfilter +% cfg.bpfiltord +% cfg.bpfilttype +% cfg.bpfreq +% cfg.derivative +% cfg.detrend +% cfg.dftfilter +% cfg.dftfreq +% cfg.hilbert +% cfg.hpfilter +% cfg.hpfiltord +% cfg.hpfilttype +% cfg.hpfreq +% cfg.implicitref +% cfg.lnfilter +% cfg.lnfiltord +% cfg.lnfreq +% cfg.lpfilter +% cfg.lpfiltord +% cfg.lpfilttype +% cfg.lpfreq +% cfg.medianfilter +% cfg.medianfiltord +% cfg.rectify +% cfg.refchannel +% cfg.reref -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +% Copyright (C) 2005-2006, Markus Bauer, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_rejectvisual.m 1399 2010-07-12 16:11:43Z jansch $ + +fieldtripdefs + +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end +if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end +if ~isfield(cfg, 'latency'), cfg.latency = 'maxperlength'; end +if ~isfield(cfg, 'keepchannel'), cfg.keepchannel = 'no'; end +if ~isfield(cfg, 'feedback'), cfg.feedback = 'textbar'; end +if ~isfield(cfg, 'method'), cfg.method = 'summary'; end +if ~isfield(cfg, 'alim'), cfg.alim = []; end +if ~isfield(cfg, 'eegscale'), cfg.eegscale = []; end +if ~isfield(cfg, 'eogscale'), cfg.eogscale = []; end +if ~isfield(cfg, 'ecgscale'), cfg.ecgscale = []; end +if ~isfield(cfg, 'megscale'), cfg.megscale = []; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +% load optional given inputfile as data +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + end +end + +% check if the input data is valid for this function +data = checkdata(data, 'datatype', 'raw', 'feedback', 'yes', 'hastrialdef', 'yes', 'hasoffset', 'yes'); + +% for backward compatibility +cfg = checkconfig(cfg, 'renamedval', {'metric', 'absmax', 'maxabs'}); +cfg = checkconfig(cfg, 'renamedval', {'method', 'absmax', 'maxabs'}); +if ~isfield(cfg, 'metric') && any(strcmp(cfg.method, {'var', 'min', 'max', 'maxabs', 'range'})) + cfg.metric = cfg.method; + cfg.method = 'summary'; +end + +if ~isfield(cfg, 'metric') + cfg.metric = 'var'; +end + +% select trials of interest +if ~strcmp(cfg.trials, 'all') + fprintf('selecting %d trials\n', length(cfg.trials)); + data = selectdata(data, 'rpt', cfg.trials); +end + +% determine the duration of each trial +for i=1:length(data.time) + begsamplatency(i) = min(data.time{i}); + endsamplatency(i) = max(data.time{i}); +end + +% determine the latency window which is possible in all trials +minperlength = [max(begsamplatency) min(endsamplatency)]; +maxperlength = [min(begsamplatency) max(endsamplatency)]; + +% latency window for averaging and variance computation is given in seconds +if (strcmp(cfg.latency, 'minperlength')) + cfg.latency = []; + cfg.latency(1) = minperlength(1); + cfg.latency(2) = minperlength(2); +elseif (strcmp(cfg.latency, 'maxperlength')) + cfg.latency = []; + cfg.latency(1) = maxperlength(1); + cfg.latency(2) = maxperlength(2); +elseif (strcmp(cfg.latency, 'prestim')) + cfg.latency = []; + cfg.latency(1) = maxperlength(1); + cfg.latency(2) = 0; +elseif (strcmp(cfg.latency, 'poststim')) + cfg.latency = []; + cfg.latency(1) = 0; + cfg.latency(2) = maxperlength(2); +end + +% ensure that the preproc specific options are located in the cfg.preproc substructure +cfg = checkconfig(cfg, 'createsubcfg', {'preproc'}); + +% apply scaling to the selected channel types to equate the absolute numbers (i.e. fT and uV) +% make a seperate copy to prevent the original data from being scaled +tmpdata = data; +scaled = 0; +if ~isempty(cfg.eegscale) + scaled = 1; + chansel = match_str(tmpdata.label, ft_channelselection('EEG', tmpdata.label)); + for i=1:length(tmpdata.trial) + tmpdata.trial{i}(chansel,:) = tmpdata.trial{i}(chansel,:) .* cfg.eegscale; + end +end +if ~isempty(cfg.eogscale) + scaled = 1; + chansel = match_str(tmpdata.label, ft_channelselection('EOG', tmpdata.label)); + for i=1:length(tmpdata.trial) + tmpdata.trial{i}(chansel,:) = tmpdata.trial{i}(chansel,:) .* cfg.eogscale; + end +end +if ~isempty(cfg.ecgscale) + scaled = 1; + chansel = match_str(tmpdata.label, ft_channelselection('ECG', tmpdata.label)); + for i=1:length(tmpdata.trial) + tmpdata.trial{i}(chansel,:) = tmpdata.trial{i}(chansel,:) .* cfg.ecgscale; + end +end +if ~isempty(cfg.megscale) + scaled = 1; + chansel = match_str(tmpdata.label, ft_channelselection('MEG', tmpdata.label)); + for i=1:length(tmpdata.trial) + tmpdata.trial{i}(chansel,:) = tmpdata.trial{i}(chansel,:) .* cfg.megscale; + end +end + +if strcmp(cfg.method, 'channel') + if scaled + fprintf('showing the scaled data per channel, all trials at once\n'); + else + fprintf('showing the data per channel, all trials at once\n'); + end + [chansel, trlsel, cfg] = rejectvisual_channel(cfg, tmpdata); +elseif strcmp(cfg.method, 'trial') + if scaled + fprintf('showing the scaled per trial, all channels at once\n'); + else + fprintf('showing the data per trial, all channels at once\n'); + end + [chansel, trlsel, cfg] = rejectvisual_trial(cfg, tmpdata); +elseif strcmp(cfg.method, 'summary') + if scaled + fprintf('showing a summary of the scaled data for all channels and trials\n'); + else + fprintf('showing a summary of the data for all channels and trials\n'); + end + + [chansel, trlsel, cfg] = rejectvisual_summary(cfg, tmpdata); +end + +fprintf('%d trials marked as GOOD, %d trials marked as BAD\n', sum(trlsel), sum(~trlsel)); +fprintf('%d channels marked as GOOD, %d channels marked as BAD\n', sum(chansel), sum(~chansel)); + +% trl is not specified in the function call, but the data is given -> +% try to locate the trial definition (trl) in the nested configuration +if isfield(data, 'trialdef') + trl = [data.trialdef data.offset(:)]; +else + % a trial definition is expected in each continuous data set + trl = []; + warning('could not locate the trial definition ''trl'' in the data structure'); +end + +% construct an artifact matrix from the trl matrix +if ~isempty(trl) + % remember the sample numbers (begin and end) of each trial and each artifact + % updating the trl and creating a trlold makes it compatible with FT_REJECTARTIFACT + cfg.artifact = trl(~trlsel,1:2); + cfg.trl = trl( trlsel,:); +else + % since sample numbers are unknown, it is not possible to remember them here + cfg.artifact = []; + cfg.trl = []; +end + +% show the user which trials are removed +removed = find(~trlsel); +if ~isempty(removed) + fprintf('the following trials were removed: '); + for i=1:(length(removed)-1) + fprintf('%d, ', removed(i)); + end + fprintf('%d\n', removed(end)); +else + fprintf('no trials were removed\n'); +end + +% remove the selected trials from the data +data.time = data.time(trlsel); +data.trial = data.trial(trlsel); +if isfield(data, 'trialinfo'), data.trialinfo = data.trialinfo(trlsel,:); end; +if isfield(data, 'trialdef'), data.trialdef = data.trialdef(trlsel,:); end; + +% remove the offset vector if present (only applies to datasets that have been preprocessed a long time ago) +if isfield(data, 'offset') + data = rmfield(data, 'offset'); +end + +if ~all(chansel) + switch cfg.keepchannel + case 'no' + % show the user which channels are removed + removed = find(~chansel); + fprintf('the following channels were removed: '); + for i=1:(length(removed)-1) + fprintf('%s, ', data.label{removed(i)}); + end + fprintf('%s\n', data.label{removed(end)}); + + % remove channels that are not selected + for i=1:length(data.trial) + data.trial{i} = data.trial{i}(chansel,:); + end + data.label = data.label(chansel); + case 'nan' + % show the user which channels are removed + removed = find(~chansel); + fprintf('the following channels were filled with NANs: '); + for i=1:(length(removed)-1) + fprintf('%s, ', data.label{removed(i)}); + end + fprintf('%s\n', data.label{removed(end)}); + + % fill the data from the bad channels with nans + for i=1:length(data.trial) + data.trial{i}(~chansel,:) = nan; + end + case 'yes' + % keep all channels, also when they are not selected + end +end + +cfg.outputfile; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_rejectvisual.m 1399 2010-07-12 16:11:43Z jansch $'; + +% remember the configuration details of the input data +try, cfg.previous = data.cfg; end + +% remember the exact configuration details in the output +data.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', data); % use the variable name "data" in the output file +end diff --git a/external/fieldtrip/ft_resampledata.m b/external/fieldtrip/ft_resampledata.m index b84b9b2..7aca701 100644 --- a/external/fieldtrip/ft_resampledata.m +++ b/external/fieldtrip/ft_resampledata.m @@ -1,11 +1,266 @@ -function varargout = funname(varargin); +function [data] = ft_resampledata(cfg, data) -% this is a SPM wrapper around a FieldTrip function +% FT_RESAMPLEDATA performs a resampling or downsampling of the data +% +% Use as +% [data] = ft_resampledata(cfg, data) +% +% The data should be organised in a structure as obtained from +% the FT_PREPROCESSING function. The configuration should contain +% cfg.resamplefs = frequency at which the data will be resampled (default = 256 Hz) +% cfg.detrend = 'no' or 'yes', detrend the data prior to resampling (no default specified, see below) +% cfg.blc = 'no' or 'yes', baseline correct the data prior to resampling (default = 'no') +% cfg.feedback = 'no', 'text', 'textbar', 'gui' (default = 'text') +% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') +% +% Instead of specifying cfg.resamplefs, you can also specify a time axis on +% which you want the data to be resampled. This is usefull for merging data +% from two acquisition devides, after resampledata you can call FT_APPENDDATA +% to concatenate the channles from the different acquisition devices. +% cfg.time = cell-array with one time axis per trial (i.e. from another dataset) +% cfg.method = interpolation method, see INTERP1 (default = 'pchip') +% +% Previously this function used to detrend the data by default. The +% motivation for this is that the data is filtered prior to resampling +% to avoid aliassing and detrending prevents occasional edge artifacts +% of the filters. Detrending is fine for removing slow drifts in data +% priot to frequency analysis, but detrending is not good if you +% subsequenlty want to look at the evoked fields. Therefore the old +% default value 'yes' has been removed. You now explicitely have to +% specify whether you want to detrend (probably so if you want to +% keep your analysis compatible with previous analyses that you did), +% or if you do not want to detrent (recommended in most cases). +% If you observe edge artifacts after detrending, it is recommended +% to apply a baseline correction to the data. +% +% The following fields in the structure 'data' are modified by this function +% data.fsample +% data.trial +% data.time +% +% See also FT_PREPROCESSING +% +% Undocumented local options: +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk -% this part is variable -prefix = 'ft_'; +% Copyright (C) 2003-2006, FC Donders Centre, Markus Siegel +% Copyright (C) 2004-2009, FC Donders Centre, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_resampledata.m 1366 2010-07-06 13:58:13Z jansch $ + +fieldtripdefs + +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +% set the defaults +if ~isfield(cfg, 'resamplefs'), cfg.resamplefs = []; end +if ~isfield(cfg, 'time'), cfg.time = {}; end +if ~isfield(cfg, 'detrend'), cfg.detrend = []; end % no default to enforce people to consider backward compatibility problem, see below +if ~isfield(cfg, 'blc'), cfg.blc = 'no'; end +if ~isfield(cfg, 'feedback'), cfg.feedback = 'text'; end +if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end +if ~isfield(cfg, 'method'), cfg.method = 'pchip'; end % interpolation method +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +% load optional given inputfile as data +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + end +end + +% check if the input data is valid for this function +% ensure trialdef and trialinfo (if present) to be in the data +data = checkdata(data, 'datatype', 'raw', 'feedback', 'yes', 'hastrialdef', 'yes'); + +if isempty(cfg.detrend) + error('The previous default to apply detrending has been changed. Recommended is to apply a baseline correction instead of detrending. See the help of this function for more details.'); +end + +%set default resampling frequency +if isempty(cfg.resamplefs) && isempty(cfg.time), + cfg.resamplefs = 256; +end + +% select trials of interest +if ~strcmp(cfg.trials, 'all') + fprintf('selecting %d trials\n', length(cfg.trials)); + data = selectdata(data, 'rpt', cfg.trials); +end + +% trl is not specified in the function call, but the data is given -> +% recreate trl-matrix from trialdef and time axes, or +% try to locate the trial definition (trl) in the nested configuration +% if isfield(data, 'trialdef') +% trl = data.trialdef; +% trl(:, 3) = 0; +% for k = 1:numel(data.trial) +% trl(k, 3) = time2offset(data.time{k}, data.fsample); +% end +% else +% trl = []; +% end + +% this should be removed +if isfield(data, 'trialdef'), + data = rmfield(data, 'trialdef'); +end + +usefsample = ~isempty(cfg.resamplefs); +usetime = ~isempty(cfg.time); + +if usefsample && usetime + error('you should either specify cfg.resamplefs or cfg.time') +end + +% remember the original sampling frequency in the configuration +cfg.origfs = data.fsample; + +if usefsample + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % resample based on new sampling frequency + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + ntr = length(data.trial); + + progress('init', cfg.feedback, 'resampling data'); + [fsorig, fsres] = rat(cfg.origfs./cfg.resamplefs);%account for non-integer fs + cfg.resamplefs = cfg.origfs.*(fsres./fsorig);%get new fs exact + + % make sure that the resampled time axes are aligned (this is to avoid + % rounding errors in the time axes). this procedure relies on the + % fact that resample assumes all data outside the data window to be zero + % anyway. therefore, padding with zeros (to the left) before resampling + % does not hurt + firstsmp = zeros(ntr, 1); + for itr = 1:ntr + firstsmp(itr) = data.time{itr}(1); + end + minsmp = min(firstsmp); + padsmp = round((firstsmp-minsmp).*cfg.origfs); + + nchan = numel(data.label); + if any(padsmp~=0) + warning('not all of the trials have the same original time axis: to avoid rounding issues in the resampled time axes, data will be zero-padded to the left prior to resampling'); + end + + for itr = 1:ntr + progress(itr/ntr, 'resampling data in trial %d from %d\n', itr, ntr); + if strcmp(cfg.blc,'yes') + data.trial{itr} = ft_preproc_baselinecorrect(data.trial{itr}); + end + if strcmp(cfg.detrend,'yes') + data.trial{itr} = ft_preproc_detrend(data.trial{itr}); + end + + % pad the data with zeros to the left + data.trial{itr} = [zeros(nchan, padsmp(itr)) data.trial{itr}]; + data.time{itr} = [data.time{itr}(1)-(padsmp(itr):-1:1)./cfg.origfs data.time{itr}]; + + % perform the resampling + if isa(data.trial{itr}, 'single') + % temporary convert this trial to double precision + data.trial{itr} = transpose(single(resample(double(transpose(data.trial{itr})),fsres,fsorig))); + else + data.trial{itr} = transpose(resample(transpose(data.trial{itr}),fsres,fsorig)); + end + % update the time axis + nsmp = size(data.trial{itr},2); + data.time{itr} = data.time{itr}(1) + (0:(nsmp-1))/cfg.resamplefs; + + %un-pad the data + begindx = ceil(cfg.resamplefs.*padsmp(itr)./cfg.origfs) + 1; + data.time{itr} = data.time{itr}(begindx:end); + data.trial{itr} = data.trial{itr}(:, begindx:end); + + end % for itr + progress('close'); + + % specify the new sampling frequency in the output + data.fsample = cfg.resamplefs; + +elseif usetime + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % resample based on new time axes for each trial + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + ntr = length(data.trial); + + progress('init', cfg.feedback, 'resampling data'); + for itr = 1:ntr + progress(itr/ntr, 'resampling data in trial %d from %d\n', itr, ntr); + if strcmp(cfg.blc,'yes') + data.trial{itr} = ft_preproc_baselinecorrect(data.trial{itr}); + end + if strcmp(cfg.detrend,'yes') + data.trial{itr} = ft_preproc_detrend(data.trial{itr}); + end + % perform the resampling + if length(data.time{itr})>1, + data.trial{itr} = interp1(data.time{itr}', data.trial{itr}', cfg.time{itr}', cfg.method)'; + else + data.trial{itr} = repmat(data.trial{itr}, [1 length(cfg.time{itr}')]); + end + % update the time axis + data.time{itr} = cfg.time{itr}; + end % for itr + progress('close'); + + % specify the new sampling frequency in the output + t1 = cfg.time{1}(1); + t2 = cfg.time{1}(2); + data.fsample = 1/(t2-t1); + +end % if usefsample or usetime + +fprintf('original sampling rate = %d Hz\nnew sampling rate = %d Hz\n', cfg.origfs, data.fsample); + +% accessing this field here is needed for the configuration tracking +% by accessing it once, it will not be removed from the output cfg +cfg.outputfile; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_resampledata.m 1366 2010-07-06 13:58:13Z jansch $'; + +% remember the configuration details of the input data +try, cfg.previous = data.cfg; end + +% remember the exact configuration details in the output +data.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', data); % use the variable name "data" in the output file +end -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_scalpcurrentdensity.m b/external/fieldtrip/ft_scalpcurrentdensity.m index b84b9b2..c42bc6c 100644 --- a/external/fieldtrip/ft_scalpcurrentdensity.m +++ b/external/fieldtrip/ft_scalpcurrentdensity.m @@ -1,11 +1,250 @@ -function varargout = funname(varargin); +function [scd] = ft_scalpcurrentdensity(cfg, data); -% this is a SPM wrapper around a FieldTrip function +% FT_SCALPCURRENTDENSITY computes an estimate of the SCD using the +% second-order derivative (the surface Laplacian) of the EEG potential +% distribution +% +% Use as +% [data] = ft_scalpcurrentdensity(cfg, data) +% or +% [timelock] = ft_scalpcurrentdensity(cfg, timelock) +% where the input data is obtained from FT_PREPROCESSING or from +% FT_TIMELOCKANALYSIS. The output data has the same format as the input +% and can be used in combination with most other FieldTrip functions +% (e.g. FT_FREQNALYSIS or FT_TOPOPLOTER). +% +% The configuration can contain +% cfg.method = 'finite' for finite-difference method or +% 'spline' for spherical spline method +% 'hjorth' for Hjorth approximation method +% cfg.elecfile = string, file containing the electrode definition +% cfg.elec = structure with electrode definition +% cfg.conductivity = conductivity of the skin (default = 0.33 S/m) +% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') +% +% Note that the skin conductivity, electrode dimensions and the potential +% all have to be expressed in the same SI units, otherwise the units of +% the SCD values are not scaled correctly. The spatial distribution still +% will be correct. +% +% The 'finite' method implements +% TF Oostendorp, A van Oosterom; The surface Laplacian of the potential: +% theory and application. IEEE Trans Biomed Eng, 43(4): 394-405, 1996. +% G Huiskamp; Difference formulas for the surface Laplacian on a +% triangulated sphere. Journal of Computational Physics, 2(95): 477-496, +% 1991. +% +% The 'spline' method implements +% F. Perrin, J. Pernier, O. Bertrand, and J. F. Echallier. +% Spherical splines for scalp potential and curernt density mapping. +% Electroencephalogr Clin Neurophysiol, 72:184-187, 1989 +% including their corrections in +% F. Perrin, J. Pernier, O. Bertrand, and J. F. Echallier. +% Corrigenda: EEG 02274, Electroencephalography and Clinical +% Neurophysiology 76:565. +% +% The 'hjorth' method implements +% B. Hjort; An on-line transformation of EEG ccalp potentials into +% orthogonal source derivation. Electroencephalography and Clinical +% Neurophysiology 39:526-530, 1975. +% +% Undocumented local options: +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk -% this part is variable -prefix = 'ft_'; +% Copyright (C) 2004-2006, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_scalpcurrentdensity.m 1437 2010-07-21 11:53:51Z jansch $ + +fieldtripdefs + +% set the defaults +if ~isfield(cfg, 'method'), cfg.method = 'spline'; end +if ~isfield(cfg, 'conductivity'), cfg.conductivity = 0.33; end % in S/m +if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +% load optional given inputfile as data +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + end +end + +% check if the input data is valid for this function +data = checkdata(data, 'datatype', 'raw', 'feedback', 'yes', 'ismeg', 'no'); + +% select trials of interest +if ~strcmp(cfg.trials, 'all') + fprintf('selecting %d trials\n', length(cfg.trials)); + data = selectdata(data, 'rpt', cfg.trials); +end + +% get the electrode positions +if isfield(cfg, 'elecfile') + fprintf('reading electrodes from file %s\n', cfg.elecfile); + elec = ft_read_sens(cfg.elecfile); +elseif isfield(cfg, 'elec') + fprintf('using electrodes specified in the configuration\n'); + elec = cfg.elec; +elseif isfield(data, 'elec') + fprintf('using electrodes specified in the data\n'); + elec = data.elec; +elseif isfield(cfg, 'layout') + fprintf('using the 2-D layout to determine the neighbours\n'); + cfg.layout = ft_prepare_layout(cfg); + cfg.neighbours = ft_neighbourselection(cfg, data); + % create a dummy electrode structure, this is needed for channel selection + elec = []; + elec.label = cfg.layout.label; + elec.pnt = cfg.layout.pos; + elec.pnt(:,3) = 0; +else + error('electrode positions were not specified'); +end + +% remove all junk fields from the electrode array +tmp = elec; +elec = []; +elec.pnt = tmp.pnt; +elec.label = tmp.label; + +% find matching electrode positions and channels in the data +[dataindx, elecindx] = match_str(data.label, elec.label); +data.label = data.label(dataindx); +elec.label = elec.label(elecindx); +elec.pnt = elec.pnt(elecindx, :); +Ntrials = length(data.trial); +for trlop=1:Ntrials + data.trial{trlop} = data.trial{trlop}(dataindx,:); +end + +% compute SCD for each trial +if strcmp(cfg.method, 'spline') + for trlop=1:Ntrials + % do not compute intrepolation, but only one value at [0 0 1] + % this also gives L1, the laplacian of the original data in which we + % are interested here + fprintf('computing SCD for trial %d\n', trlop); + [V2, L2, L1] = splint(elec.pnt, data.trial{trlop}, [0 0 1]); + scd.trial{trlop} = L1; + end + +elseif strcmp(cfg.method, 'finite') + % the finite difference approach requires a triangulation + prj = elproj(elec.pnt); + tri = delaunay(prj(:,1), prj(:,2)); + % the new electrode montage only needs to be computed once for all trials + montage.tra = lapcal(elec.pnt, tri); + montage.labelorg = data.label; + montage.labelnew = data.label; + % apply the montage to the data, also update the electrode definition + scd = ft_apply_montage(data, montage); + elec = ft_apply_montage(elec, montage); + +elseif strcmp(cfg.method, 'hjorth') + % the Hjorth filter requires a specification of the neighbours + if ~isfield(cfg, 'neighbours') + tmpcfg = []; + tmpcfg.elec = elec; + cfg.neighbours = ft_neighbourselection(tmpcfg, data); + end + % convert the neighbourhood structure into a montage + labelnew = {}; + labelorg = {}; + for i=1:length(cfg.neighbours) + labelnew = cat(2, labelnew, cfg.neighbours{i}.label); + labelorg = cat(2, labelorg, cfg.neighbours{i}.neighblabel(:)'); + end + labelorg = cat(2, labelnew, labelorg); + labelorg = unique(labelorg); + tra = zeros(length(labelnew), length(labelorg)); + for i=1:length(cfg.neighbours) + thischan = match_str(labelorg, cfg.neighbours{i}.label); + thisneighb = match_str(labelorg, cfg.neighbours{i}.neighblabel); + tra(i, thischan) = 1; + tra(i, thisneighb) = -1/length(thisneighb); + end + % combine it in a montage + montage.tra = tra; + montage.labelorg = labelorg; + montage.labelnew = labelnew; + % apply the montage to the data, also update the electrode definition + scd = ft_apply_montage(data, montage); + elec = ft_apply_montage(elec, montage); + +else + error('unknown method for SCD computation'); +end + +if strcmp(cfg.method, 'spline') || strcmp(cfg.method, 'finite') + % correct the units + warning('trying to correct the units, assuming uV and mm'); + for trlop=1:Ntrials + % The surface laplacian is proportional to potential divided by squared distance which means that, if + % - input potential is in uV, which is 10^6 too large + % - units of electrode positions are in mm, which is 10^3 too large + % these two cancel out against each other. Hence the computed laplacian + % is in SI units (MKS). + scd.trial{trlop} = cfg.conductivity * -1 * scd.trial{trlop}; + end + fprintf('output surface laplacian is in V/m^2'); +else + fprintf('output Hjorth filtered potential is in uV'); +end + +% collect the results +scd.elec = elec; +scd.time = data.time; +scd.label = data.label; +scd.fsample = data.fsample; +if isfield(data, 'trialdef') + scd.trialdef = data.trialdef; +end +if isfield(data, 'trialinfo') + scd.trialinfo = data.trialinfo; +end + +% store the configuration of this function call, including that of the previous function call +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_scalpcurrentdensity.m 1437 2010-07-21 11:53:51Z jansch $'; + +% remember the configuration details of the input data +try, cfg.previous = data.cfg; end + +% remember the exact configuration details in the output +scd.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', scd); % use the variable name "data" in the output file +end -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_singleplotER.m b/external/fieldtrip/ft_singleplotER.m index b84b9b2..a907ec8 100644 --- a/external/fieldtrip/ft_singleplotER.m +++ b/external/fieldtrip/ft_singleplotER.m @@ -1,11 +1,358 @@ -function varargout = funname(varargin); +function [cfg] = ft_singleplotER(cfg, varargin) -% this is a SPM wrapper around a FieldTrip function +% ft_singleplotER plots the event-related fields or potentials of a single channel +% or the average over multiple channels. Multiple datasets can be overlayed. +% +% Use as: +% ft_sinlgeplotER(cfg, data) +% ft_singleplotER(cfg, data1, data2, ..., dataN) +% +% The data can be an ERP/ERF produced by FT_TIMELOCKANALYSIS, a powerspectrum +% produced by FT_FREQANALYSIS or a coherencespectrum produced by FT_FREQDESCRIPTIVES. +% If you specify multiple datasets they must contain the same channels, etc. +% +% The configuration can have the following parameters: +% cfg.xparam = field to be plotted on x-axis (default depends on data.dimord) +% 'time' or 'freq' +% cfg.zparam = field to be plotted on y-axis (default depends on data.dimord) +% 'avg', 'powspctrm' or 'cohspctrm' +% cfg.maskparameter = field in the first dataset to be used for masking of data +% (not possible for mean over multiple channels, or when input contains multiple subjects +% or trials) +% cfg.maskstyle = style used for masking of data, 'box', 'thickness' or 'saturation' (default = 'box') +% cfg.xlim = 'maxmin' or [xmin xmax] (default = 'maxmin') +% cfg.ylim = 'maxmin' or [ymin ymax] (default = 'maxmin') +% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), +% see FT_CHANNELSELECTION for details +% cfg.cohrefchannel = name of reference channel for visualising coherence, can be 'gui' +% cfg.baseline = 'yes','no' or [time1 time2] (default = 'no'), see FT_TIMELOCKBASELINE +% cfg.baselinetype = 'absolute' or 'relative' (default = 'absolute') +% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') +% cfg.fontsize = font size of title (default = 8) +% cfg.interactive = Interactive plot 'yes' or 'no' (default = 'no') +% In a interactive plot you can select areas and produce a new +% interactive plot when a selected area is clicked. Multiple areas +% can be selected by holding down the SHIFT key. +% cfg.renderer = 'painters', 'zbuffer',' opengl' or 'none' (default = []) +% cfg.linestyle = linestyle/marker type, see options of the matlab PLOT function (default = '-') +% cfg.linewidth = linewidth in points (default = 0.5) +% cfg.graphcolor = color(s) used for plotting the dataset(s) (default = 'brgkywrgbkywrgbkywrgbkyw') +% alternatively, colors can be specified as Nx3 matrix of RGB values +% +% See also: +% ft_singleplotTFR, ft_multiplotER, ft_multiplotTFR, ft_topoplotER, ft_topoplotTFR -% this part is variable -prefix = 'ft_'; +% This function depends on FT_TIMELOCKBASELINE which has the following options: +% cfg.baseline, documented +% cfg.channel +% cfg.blcwindow +% cfg.previous +% cfg.version -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +% Copyright (C) 2003-2006, Ole Jensen +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_singleplotER.m 1431 2010-07-20 07:47:55Z roboos $ + +fieldtripdefs + +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +cla + +% for backward compatibility with old data structures +for i=1:length(varargin) + varargin{i} = checkdata(varargin{i}); +end + +% set the defaults: +if ~isfield(cfg,'baseline'), cfg.baseline = 'no'; end +if ~isfield(cfg,'trials'), cfg.trials = 'all'; end +if ~isfield(cfg,'xlim'), cfg.xlim = 'maxmin'; end +if ~isfield(cfg,'ylim'), cfg.ylim = 'maxmin'; end +if ~isfield(cfg,'fontsize'), cfg.fontsize = 8; end +if ~isfield(cfg,'graphcolor'), cfg.graphcolor = 'brgkywrgbkywrgbkywrgbkyw'; end +if ~isfield(cfg,'interactive'), cfg.interactive = 'no'; end +if ~isfield(cfg,'renderer'), cfg.renderer = []; end +if ~isfield(cfg,'maskparameter'), cfg.maskparameter = []; end +if ~isfield(cfg,'linestyle'), cfg.linestyle = '-'; end +if ~isfield(cfg,'linewidth'), cfg.linewidth = 0.5; end +if ~isfield(cfg,'maskstyle'), cfg.maskstyle = 'box'; end + +if ischar(cfg.graphcolor) + GRAPHCOLOR = ['k' cfg.graphcolor]; +elseif isnumeric(cfg.graphcolor) + GRAPHCOLOR = [0 0 0; cfg.graphcolor]; +end + +% Set x/y/zparam defaults according to varargin{1}.dimord value: +if strcmp(varargin{1}.dimord, 'chan_time') + if ~isfield(cfg, 'xparam'), cfg.xparam='time'; end + if ~isfield(cfg, 'zparam'), cfg.zparam='avg'; end +elseif strcmp(varargin{1}.dimord, 'chan_freq') + if ~isfield(cfg, 'xparam'), cfg.xparam='freq'; end + if ~isfield(cfg, 'zparam'), cfg.zparam='powspctrm'; end +elseif strcmp(varargin{1}.dimord, 'subj_chan_time') || strcmp(varargin{1}.dimord, 'rpt_chan_time') + tmpcfg = []; + tmpcfg.trials = cfg.trials; + for i=1:(nargin-1) + varargin{i} = ft_timelockanalysis(tmpcfg, varargin{i}); + end + if ~isfield(cfg, 'xparam'), cfg.xparam='time'; end + if ~isfield(cfg, 'zparam'), cfg.zparam='avg'; end +elseif strcmp(varargin{1}.dimord, 'subj_chan_freq') || strcmp(varargin{1}.dimord, 'rpt_chan_freq') + tmpcfg = []; + tmpcfg.trials = cfg.trials; + tmpcfg.jackknife = 'no'; + if isfield(cfg, 'zparam') && strcmp(cfg.zparam,'cohspctrm') + % on the fly computation of coherence spectrum is not supported + elseif isfield(cfg, 'zparam') && ~strcmp(cfg.zparam,'powspctrm') + % freqdesctiptives will only work on the powspctrm field, hence a temporary copy of the data is needed + for i=1:(nargin-1) + tempdata.dimord = varargin{i}.dimord; + tempdata.freq = varargin{i}.freq; + tempdata.label = varargin{i}.label; + tempdata.powspctrm = varargin{i}.(cfg.zparam); + tempdata.cfg = varargin{i}.cfg; + tempdata = ft_freqdescriptives(tmpcfg, tempdata); + varargin{i}.(cfg.zparam) = tempdata.powspctrm; + clear tempdata + end + else + for i=1:(nargin-1) + if isfield(varargin{i}, 'crsspctrm'), varargin{i} = rmfield(varargin{i}, 'crsspctrm'); end % on the fly computation of coherence spectrum is not supported + varargin{i} = ft_freqdescriptives(tmpcfg, varargin{i}); + end + end + if ~isfield(cfg, 'xparam'), cfg.xparam='freq'; end + if ~isfield(cfg, 'zparam'), cfg.zparam='powspctrm'; end +end + +% Make sure cfg.yparam and cfg.zparam become equivalent if only one is defined: +if (isfield(cfg, 'yparam')) && (~isfield(cfg, 'zparam')) + cfg.zparam = cfg.yparam; +elseif (~isfield(cfg, 'yparam')) && (isfield(cfg, 'zparam')) + cfg.yparam = cfg.zparam; +end + +% Old style coherence plotting with cohtargetchannel is no longer supported: +cfg = checkconfig(cfg, 'unused', {'cohtargetchannel'}); + +for k=1:length(varargin) + % Check for unconverted coherence spectrum data: + if (strcmp(cfg.zparam,'cohspctrm')) && (isfield(varargin{k}, 'labelcmb')) + % A reference channel is required: + if ~isfield(cfg,'cohrefchannel'), + error('no reference channel specified'); + end + + if strcmp(cfg.cohrefchannel, 'gui') + % Open a single figure with the channel layout, the user can click on a reference channel + h = clf; + lay = ft_prepare_layout(cfg, varargin{1}); + cfg.layout = lay; + ft_plot_lay(cfg.layout, 'box', false); + title('Select the reference channel by clicking on it...'); + % add the channel information to the figure + info = guidata(h); + info.x = lay.pos(:,1); + info.y = lay.pos(:,2); + info.label = lay.label; + guidata(h, info); + set(gcf, 'WindowButtonUpFcn', {@ft_select_channel, 'callback', {@select_singleplotER, cfg, varargin{:}}}); + return + end + + % Convert 2-dimensional channel matrix to a single dimension: + sel1 = strmatch(cfg.cohrefchannel, varargin{k}.labelcmb(:,2)); + sel2 = strmatch(cfg.cohrefchannel, varargin{k}.labelcmb(:,1)); + fprintf('selected %d channels for coherence\n', length(sel1)+length(sel2)); + varargin{k}.cohspctrm = varargin{k}.cohspctrm([sel1;sel2],:,:); + varargin{k}.label = [varargin{k}.labelcmb(sel1,1);varargin{k}.labelcmb(sel2,2)]; + varargin{k}.labelcmb = varargin{k}.labelcmb([sel1;sel2],:); + varargin{k} = rmfield(varargin{k}, 'labelcmb'); + end + + % Apply baseline correction: + if ~strcmp(cfg.baseline, 'no') + if strcmp(cfg.xparam, 'time') + varargin{k} = ft_timelockbaseline(cfg, varargin{k}); + elseif strcmp(cfg.xparam, 'freq') + warning('Baseline correction not possible for powerspectra'); + else + warning('Baseline not applied, please set cfg.xparam'); + end + end +end + +% Determine x-axis range: +if strcmp(cfg.xlim,'maxmin') + % Find maxmin throughout all varargins: + xmin = []; + xmax = []; + for i=1:length(varargin) + xmin = min([xmin varargin{i}.(cfg.xparam)]); + xmax = max([xmax varargin{i}.(cfg.xparam)]); + end +else + xmin = cfg.xlim(1); + xmax = cfg.xlim(2); +end + +% Pick the channel(s) +if ~isfield(cfg,'channel') + % set the default + cfg.channel = 'all'; + % for backward compatibility + cfg = checkconfig(cfg, 'renamed', {'channelindex', 'channel'}); + cfg = checkconfig(cfg, 'renamed', {'channelname', 'channel'}); +end + +hold on; +colorLabels = []; +ymin = []; +ymax = []; + +% Plot one line for each data set: +for k=2:nargin + % Get data matrix: + P = varargin{k-1}.(cfg.zparam); + labels = getfield(varargin{k-1}, 'label'); + + % User colored labels if more than one data set is plotted: + if nargin > 2 %% FIXME: variable colorLabels is not used ??? sashae + if ischar(GRAPHCOLOR); colorLabels = [colorLabels inputname(k) '=' GRAPHCOLOR(k) ' ']; + elseif isnumeric(GRAPHCOLOR); colorLabels = [colorLabels inputname(k) '=' num2str(GRAPHCOLOR(k,:)) ' ']; + end + end + + % select channels + cfg.channel = ft_channelselection(cfg.channel, varargin{k-1}.label); + if isempty(cfg.channel) + error('no channels selected'); + else + chansel = match_str(varargin{k-1}.label, cfg.channel); + end + + % Average across selected channels: + if length(size(P)) > 2 %chan_chan_indexing + + refchan = match_str(varargin{k-1}.label,cfg.cohrefchannel); + + if strcmp(cfg.matrixside, 'feedback') + P = squeeze(mean(mean(P(chansel,refchan,:),2),1)); + elseif strcmp(cfg.matrixside, 'feedforward') + P = squeeze(mean(mean(P(refchan,chansel,:),2),1)); + elseif strcmp(cfg.matrixside, 'ff-fd') + P = squeeze(mean(mean(P(refchan,chansel,:),2),1)) - squeeze(mean(mean(P(chansel,refchan,:),2),1)); + elseif strcmp(cfg.matrixside, 'fd-ff') + P = squeeze(mean(mean(P(chansel,refchan,:),2),1)) - squeeze(mean(mean(P(refchan,chansel,:),2),1)); + end + else + P = squeeze(mean(P(chansel,:), 1)); + end + + % select mask + if ~isempty(cfg.maskparameter) %&& masking + M = varargin{1}.(cfg.maskparameter); % mask always from only first dataset + M = squeeze(mean(M(chansel,:), 1)); + else + M = []; + end + + % Update ymin and ymax for the current data set: + if strcmp(cfg.ylim, 'maxmin') + ind_xmin = nearest(varargin{k-1}.(cfg.xparam), xmin); + ind_xmax = nearest(varargin{k-1}.(cfg.xparam), xmax); + ymin = min([ymin min(P(ind_xmin:ind_xmax))]); + ymax = max([ymax max(P(ind_xmin:ind_xmax))]); + else + ymin = cfg.ylim(1); + ymax = cfg.ylim(2); + end + + if ischar(GRAPHCOLOR); color = GRAPHCOLOR(k); + elseif isnumeric(GRAPHCOLOR); color = GRAPHCOLOR(k,:); + end + ft_plot_vector(varargin{k-1}.(cfg.xparam), P, 'style', cfg.linestyle, 'color', color, 'highlight', M, 'highlightstyle', cfg.maskstyle, 'linewidth', cfg.linewidth); +end + +% Set xlim and ylim: +xlim([xmin xmax]); +ylim([ymin ymax]); + +% Make the figure interactive +if strcmp(cfg.interactive, 'yes') + set(gcf, 'WindowButtonUpFcn', {@ft_select_range, 'multiple', false, 'yrange', false, 'callback', {@select_topoplotER, cfg, varargin{:}}, 'event', 'WindowButtonUpFcn'}); + set(gcf, 'WindowButtonDownFcn', {@ft_select_range, 'multiple', false, 'yrange', false, 'callback', {@select_topoplotER, cfg, varargin{:}}, 'event', 'WindowButtonDownFcn'}); + set(gcf, 'WindowButtonMotionFcn', {@ft_select_range, 'multiple', false, 'yrange', false, 'callback', {@select_topoplotER, cfg, varargin{:}}, 'event', 'WindowButtonMotionFcn'}); +end + +% Create title text containing channel name(s) and channel number(s): +if length(chansel) == 1 + t = [char(cfg.channel) ' / ' num2str(chansel) ]; +else + t = sprintf('mean(%0s)', join(',', cfg.channel)); +end +h = title(t,'fontsize', cfg.fontsize); + +% Set renderer if specified +if ~isempty(cfg.renderer) + set(gcf, 'renderer', cfg.renderer) +end + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function t = join(separator,cells) +if isempty(cells) + t = ''; + return; +end +t = char(cells{1}); + +for i=2:length(cells) + t = [t separator char(cells{i})]; +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION which is called by ft_select_channel in case cfg.cohrefchannel='gui' +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function select_singleplotER(label, cfg, varargin) +cfg.cohrefchannel = label; +fprintf('selected cfg.cohrefchannel = ''%s''\n', cfg.cohrefchannel); +p = get(gcf, 'Position'); +f = figure; +set(f, 'Position', p); +ft_singleplotER(cfg, varargin{:}); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION which is called after selecting a time range +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function select_topoplotER(range, cfg, varargin) +cfg.comment = 'auto'; +cfg.yparam = []; +cfg.xlim = range(1:2); +fprintf('selected cfg.xlim = [%f %f]\n', cfg.xlim(1), cfg.xlim(2)); +p = get(gcf, 'Position'); +f = figure; +set(f, 'Position', p); +ft_topoplotER(cfg, varargin{:}); diff --git a/external/fieldtrip/ft_singleplotTFR.m b/external/fieldtrip/ft_singleplotTFR.m index b84b9b2..703b25b 100644 --- a/external/fieldtrip/ft_singleplotTFR.m +++ b/external/fieldtrip/ft_singleplotTFR.m @@ -1,11 +1,361 @@ -function varargout = funname(varargin); +function [cfg] = ft_singleplotTFR(cfg, data) -% this is a SPM wrapper around a FieldTrip function +% ft_singleplotTFR plots the time-frequency representations of power of a +% single channel or the average over multiple channels. +% +% Use as: +% ft_singleplotTFR(cfg,data) +% +% The data can be a time-frequency representation of power that was +% computed using the FT_FREQANALYSIS function. +% +% The configuration can have the following parameters: +% cfg.xparam = field to be plotted on x-axis, e.g. 'time' (default depends on data.dimord) +% cfg.yparam = field to be plotted on y-axis, e.g. 'freq' (default depends on data.dimord) +% cfg.zparam = field to be plotted on y-axis, e.g. 'powspcrtrm' (default depends on data.dimord) +% cfg.maskparameter = field in the data to be used for masking of data +% (not possible for mean over multiple channels, or when input contains multiple subjects +% or trials) +% cfg.maskstyle = style used to mask nans, 'opacity' or 'saturation' (default = 'opacity') +% use 'saturation' when saving to vector-format (like *.eps) to avoid all sorts of image-problems +% cfg.xlim = 'maxmin' or [xmin xmax] (default = 'maxmin') +% cfg.ylim = 'maxmin' or [ymin ymax] (default = 'maxmin') +% cfg.zlim = 'maxmin','maxabs' or [zmin zmax] (default = 'maxmin') +% cfg.baseline = 'yes','no' or [time1 time2] (default = 'no'), see FT_FREQBASELINE +% cfg.baselinetype = 'absolute' or 'relative' (default = 'absolute') +% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') +% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), +% see FT_CHANNELSELECTION for details +% cfg.cohrefchannel = name of reference channel for visualising coherence, can be 'gui' +% cfg.fontsize = font size of title (default = 8) +% cfg.colormap = any sized colormap, see COLORMAP +% cfg.colorbar = 'yes', 'no' (default = 'yes') +% cfg.interactive = Interactive plot 'yes' or 'no' (default = 'no') +% In a interactive plot you can select areas and produce a new +% interactive plot when a selected area is clicked. Multiple areas +% can be selected by holding down the SHIFT key. +% cfg.renderer = 'painters', 'zbuffer',' opengl' or 'none' (default = []) +% cfg.masknans = 'yes' or 'no' (default = 'yes') +% +% See also: +% ft_singleplotER, ft_multiplotER, ft_multiplotTFR, ft_topoplotER, ft_topoplotTFR -% this part is variable -prefix = 'ft_'; +% This function depends on FT_FREQBASELINE which has the following options: +% cfg.baseline, documented +% cfg.baselinetype, documented -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +% Copyright (C) 2005-2006, F.C. Donders Centre +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_singleplotTFR.m 1431 2010-07-20 07:47:55Z roboos $ + +fieldtripdefs + +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +cla + +% For backward compatibility with old data structures: +data = checkdata(data); + +% check if the input cfg is valid for this function +cfg = checkconfig(cfg, 'renamedval', {'zlim', 'absmax', 'maxabs'}); + +% Set the defaults: +if ~isfield(cfg,'baseline'), cfg.baseline = 'no'; end +if ~isfield(cfg,'baselinetype'), cfg.baselinetype = 'absolute'; end +if ~isfield(cfg,'trials'), cfg.trials = 'all'; end +if ~isfield(cfg,'xlim'), cfg.xlim = 'maxmin'; end +if ~isfield(cfg,'ylim'), cfg.ylim = 'maxmin'; end +if ~isfield(cfg,'zlim'), cfg.zlim = 'maxmin'; end +if ~isfield(cfg,'fontsize'), cfg.fontsize = 8; end +if ~isfield(cfg,'colorbar'), cfg.colorbar = 'yes'; end +if ~isfield(cfg,'interactive'), cfg.interactive = 'no'; end +if ~isfield(cfg,'renderer'), cfg.renderer = []; end +if ~isfield(cfg,'masknans'), cfg.masknans = 'yes'; end +if ~isfield(cfg,'maskparameter'), cfg.maskparameter = []; end +if ~isfield(cfg,'maskstyle'), cfg.maskstyle = 'opacity'; end + +% Set x/y/zparam defaults according to data.dimord value: +if strcmp(data.dimord, 'chan_freq_time') + if ~isfield(cfg, 'xparam'), cfg.xparam='time'; end + if ~isfield(cfg, 'yparam'), cfg.yparam='freq'; end + if ~isfield(cfg, 'zparam'), cfg.zparam='powspctrm'; end +elseif strcmp(data.dimord, 'subj_chan_freq_time') || strcmp(data.dimord, 'rpt_chan_freq_time') + if isfield(data, 'crsspctrm'), data = rmfield(data, 'crsspctrm'); end % on the fly computation of coherence spectrum is not supported + tmpcfg = []; + tmpcfg.trials = cfg.trials; + tmpcfg.jackknife = 'no'; + if isfield(cfg, 'zparam') && strcmp(cfg.zparam,'cohspctrm') + % on the fly computation of coherence spectrum is not supported + elseif isfield(cfg, 'zparam') && ~strcmp(cfg.zparam,'powspctrm') + % freqdesctiptives will only work on the powspctrm field, hence a temporary copy of the data is needed + tempdata.dimord = data.dimord; + tempdata.freq = data.freq; + tempdata.time = data.time; + tempdata.label = data.label; + tempdata.powspctrm = data.(cfg.zparam); + tempdata.cfg = data.cfg; + tempdata = ft_freqdescriptives(tmpcfg, tempdata); + data.(cfg.zparam) = tempdata.powspctrm; + clear tempdata + else + data = ft_freqdescriptives(tmpcfg, data); + end + if ~isfield(cfg, 'xparam'), cfg.xparam='time'; end + if ~isfield(cfg, 'yparam'), cfg.yparam='freq'; end + if ~isfield(cfg, 'zparam'), cfg.zparam='powspctrm'; end +end + +% Pick the channel(s) +if ~isfield(cfg,'channel') + % set the default + cfg.channel = 'all'; + % for backward compatibility + cfg = checkconfig(cfg, 'renamed', {'channelindex', 'channel'}); + cfg = checkconfig(cfg, 'renamed', {'channelname', 'channel'}); +end + +% Check for unconverted coherence spectrum data +if (strcmp(cfg.zparam,'cohspctrm')) && (isfield(data, 'labelcmb')) + % A reference channel is required: + if ~isfield(cfg,'cohrefchannel'), + error('no reference channel specified'); + end + + if strcmp(cfg.cohrefchannel, 'gui') + % Open a single figure with the channel layout, the user can click on a reference channel + h = clf; + lay = ft_prepare_layout(cfg, data); + cfg.layout = lay; + ft_plot_lay(lay, 'box', false); + title('Select the reference channel by clicking on it...'); + % add the channel information to the figure + info = guidata(h); + info.x = lay.pos(:,1); + info.y = lay.pos(:,2); + info.label = lay.label; + guidata(h, info); + set(gcf, 'WindowButtonUpFcn', {@ft_select_channel, 'callback', {@select_singleplotTFR, cfg, data}}); + return + end + + % Convert 2-dimensional channel matrix to a single dimension: + sel1 = strmatch(cfg.cohrefchannel, data.labelcmb(:,2)); + sel2 = strmatch(cfg.cohrefchannel, data.labelcmb(:,1)); + fprintf('selected %d channels for coherence\n', length(sel1)+length(sel2)); + data.cohspctrm = data.cohspctrm([sel1;sel2],:,:); + data.label = [data.labelcmb(sel1,1);data.labelcmb(sel2,2)]; + data.labelcmb = data.labelcmb([sel1;sel2],:); + data = rmfield(data, 'labelcmb'); +end + +cfg.channel = ft_channelselection(cfg.channel, data.label); +if isempty(cfg.channel) + error('no channels selected'); +else + chansel = match_str(data.label, cfg.channel); +end + +% cfg.maskparameter only possible for single channel +if length(chansel) > 1 && ~isempty(cfg.maskparameter) + warning('no masking possible for average over multiple channels -> cfg.maskparameter cleared') + cfg.maskparameter = []; +end + +% Apply baseline correction: +if ~strcmp(cfg.baseline, 'no') + data = ft_freqbaseline(cfg, data); +end + +% Get physical x-axis range: +if strcmp(cfg.xlim,'maxmin') + xmin = min(data.(cfg.xparam)); + xmax = max(data.(cfg.xparam)); +else + xmin = cfg.xlim(1); + xmax = cfg.xlim(2); +end + +% Find corresponding x-axis bins: +xidc = find(data.(cfg.xparam) >= xmin & data.(cfg.xparam) <= xmax); + +% Align physical x-axis range to the array bins: +xmin = data.(cfg.xparam)(xidc(1)); +xmax = data.(cfg.xparam)(xidc(end)); + +% Get physical y-axis range: +if strcmp(cfg.ylim,'maxmin') + ymin = min(data.(cfg.yparam)); + ymax = max(data.(cfg.yparam)); +else + ymin = cfg.ylim(1); + ymax = cfg.ylim(2); +end + +% Find corresponding y-axis bins: +yidc = find(data.(cfg.yparam) >= ymin & data.(cfg.yparam) <= ymax); + +% Align physical y-axis range to the array bins: +ymin = data.(cfg.yparam)(yidc(1)); +ymax = data.(cfg.yparam)(yidc(end)); + +% Get TFR data averaged across selected channels, within the selected x/y-range: +dat = getsubfield(data, cfg.zparam); +TFR = squeeze(mean(dat(chansel,yidc,xidc), 1)); +if ~isempty(cfg.maskparameter) + mas = getsubfield(data, cfg.maskparameter); + mdata = squeeze(mas(chansel,yidc,xidc)); +end + +% Get physical z-axis range (color axis): +if strcmp(cfg.zlim,'maxmin') + zmin = min(TFR(:)); + zmax = max(TFR(:)); +elseif strcmp(cfg.zlim,'maxabs') + zmin = -max(abs(TFR(:))); + zmax = max(abs(TFR(:))); +else + zmin = cfg.zlim(1); + zmax = cfg.zlim(2); +end + +% test if X and Y are linearly spaced (to within 10^-12): % FROM UIMAGE +x = data.(cfg.xparam)(xidc); +y = data.(cfg.yparam)(yidc); +dx = min(diff(x)); % smallest interval for X +dy = min(diff(y)); % smallest interval for Y +evenx = all(abs(diff(x)/dx-1)<1e-12); % true if X is linearly spaced +eveny = all(abs(diff(y)/dy-1)<1e-12); % true if Y is linearly spaced + +% masking only possible for evenly spaced axis +if strcmp(cfg.masknans, 'yes') && (~evenx || ~eveny) + warning('(one of the) axis are not evenly spaced -> nans cannot be masked out -> cfg.masknans is set to ''no'';') + cfg.masknans = 'no'; +end +if ~isempty(cfg.maskparameter) && (~evenx || ~eveny) + warning('(one of the) axis are not evenly spaced -> no masking possible -> cfg.maskparameter cleared') + cfg.maskparameter = []; +end + +% set colormap +if isfield(cfg,'colormap') + if size(cfg.colormap,2)~=3, error('singleplotTFR(): Colormap must be a n x 3 matrix'); end + set(gcf,'colormap',cfg.colormap); +end; + +% Draw plot (and mask NaN's if requested): +if isequal(cfg.masknans,'yes') && isempty(cfg.maskparameter) + mask = ~isnan(TFR); + mask = double(mask); + ft_plot_matrix(data.(cfg.xparam)(xidc),data.(cfg.yparam)(yidc), TFR, 'clim',[zmin,zmax],'tag','cip','highlightstyle',cfg.maskstyle,'highlight', mask) +elseif isequal(cfg.masknans,'yes') && ~isempty(cfg.maskparameter) + mask = ~isnan(TFR); + mask = mask .* mdata; + mask = double(mask); + ft_plot_matrix(data.(cfg.xparam)(xidc),data.(cfg.yparam)(yidc), TFR, 'clim',[zmin,zmax],'tag','cip','highlightstyle',cfg.maskstyle,'highlight', mask) +elseif isequal(cfg.masknans,'no') && ~isempty(cfg.maskparameter) + mask = mdata; + mask = double(mask); + ft_plot_matrix(data.(cfg.xparam)(xidc),data.(cfg.yparam)(yidc), TFR, 'clim',[zmin,zmax],'tag','cip','highlightstyle',cfg.maskstyle,'highlight', mask) +else + ft_plot_matrix(data.(cfg.xparam)(xidc),data.(cfg.yparam)(yidc), TFR, 'clim',[zmin,zmax],'tag','cip') +end +hold on +axis xy; + + + +if isequal(cfg.colorbar,'yes') + colorbar; +end + +% Make the figure interactive: +if strcmp(cfg.interactive, 'yes') + set(gcf, 'WindowButtonUpFcn', {@ft_select_range, 'multiple', false, 'callback', {@select_topoplotTFR, cfg, data}, 'event', 'WindowButtonUpFcn'}); + set(gcf, 'WindowButtonDownFcn', {@ft_select_range, 'multiple', false, 'callback', {@select_topoplotTFR, cfg, data}, 'event', 'WindowButtonDownFcn'}); + set(gcf, 'WindowButtonMotionFcn', {@ft_select_range, 'multiple', false, 'callback', {@select_topoplotTFR, cfg, data}, 'event', 'WindowButtonMotionFcn'}); +end + +% Create title text containing channel name(s) and channel number(s): +if length(chansel) == 1 + t = [char(cfg.channel) ' / ' num2str(chansel) ]; +else + t = sprintf('mean(%0s)', join(',', cfg.channel)); +end +h = title(t,'fontsize', cfg.fontsize); + +axis tight; +hold off; + +% Set renderer if specified +if ~isempty(cfg.renderer) + set(gcf, 'renderer', cfg.renderer) +end + + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function t = join(separator,cells) +if isempty(cells) + t = ''; + return; +end +t = char(cells{1}); + +for i=2:length(cells) + t = [t separator char(cells{i})]; +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION which is called by ft_select_channel in case cfg.cohrefchannel='gui' +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function select_singleplotTFR(label, cfg, varargin) +cfg.cohrefchannel = label; +fprintf('selected cfg.cohrefchannel = ''%s''\n', cfg.cohrefchannel); +p = get(gcf, 'Position'); +f = figure; +set(f, 'Position', p); +ft_singleplotTFR(cfg, varargin{:}); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION which is called after selecting a time range +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function select_topoplotTFR(range, cfg, varargin) +cfg.comment = 'auto'; +cfg.xlim = range(1:2); +cfg.ylim = range(3:4); +% compatibility fix for new ft_topoplotER/TFR cfg options +if isfield(cfg,'showlabels') && strcmp(cfg.showlabels,'yes') + cfg = rmfield(cfg,'showlabels'); + cfg.marker = 'labels'; +elseif isfield(cfg,'showlabels') && strcmp(cfg.showlabels,'no') + cfg = rmfield(cfg,'showlabels'); + cfg.marker = 'on'; +end +fprintf('selected cfg.xlim = [%f %f]\n', cfg.xlim(1), cfg.xlim(2)); +fprintf('selected cfg.ylim = [%f %f]\n', cfg.ylim(1), cfg.ylim(2)); +p = get(gcf, 'Position'); +f = figure; +set(f, 'Position', p); +ft_topoplotER(cfg, varargin{:}); diff --git a/external/fieldtrip/ft_sliceinterp.m b/external/fieldtrip/ft_sliceinterp.m new file mode 100644 index 0000000..526e603 --- /dev/null +++ b/external/fieldtrip/ft_sliceinterp.m @@ -0,0 +1,517 @@ +function [outim]=ft_sliceinterp(cfg, ininterp) + +% FT_SLICEINTERP plots a 2D-montage of source reconstruction and anatomical MRI +% after these have been interpolated onto the same grid. +% +% Use as +% ft_sliceinterp(cfg, interp) +% or +% [rgbimage] = ft_sliceinterp(cfg, interp), rgbimage is the monatage image +% +% where interp is the output of sourceinterpolate and cfg is a structure +% with any of the following fields: +% +% cfg.funparameter string with the functional parameter of interest (default = 'source') +% cfg.maskparameter parameter used as opacity mask (default = 'none') +% cfg.clipmin value or 'auto' (clipping of source data) +% cfg.clipmax value or 'auto' (clipping of source data) +% cfg.clipsym 'yes' or 'no' (default) symmetrical clipping +% cfg.colormap colormap for source overlay (default is jet(128)) +% cfg.colmin source value mapped to the lowest color (default = 'auto') +% cfg.colmax source value mapped to the highest color (default = 'auto') +% cfg.maskclipmin value or 'auto' (clipping of mask data) +% cfg.maskclipmax value or 'auto' (clipping of mask data) +% cfg.maskclipsym 'yes' or 'no' (default) symmetrical clipping +% cfg.maskmap opacitymap for source overlay +% (default is linspace(0,1,128)) +% cfg.maskcolmin mask value mapped to the lowest opacity, i.e. +% completely transparent (default ='auto') +% cfg.maskcolmin mask value mapped to the highest opacity, i.e. +% non-transparent (default = 'auto') +% cfg.alpha value between 0 and 1 or 'adaptive' (default) +% cfg.nslices integer value, default is 20 +% cfg.dim integer value, default is 3 (dimension to slice) +% cfg.spacemin 'auto' (default) or integer (first slice position) +% cfg.spacemax 'auto' (default) or integer (last slice position) +% cfg.resample integer value, default is 1 (for resolution reduction) +% cfg.rotate number of ccw 90 deg slice rotations (default = 0) +% cfg.title optional title (default is '') +% cfg.whitebg 'yes' or 'no' (default = 'yes') +% cfg.flipdim flip data along the sliced dimension, 'yes' or 'no' +% (default = 'no') +% cfg.marker [Nx3] array defining N marker positions to display +% cfg.markersize radius of markers (default = 5); +% cfg.markercolor [1x3] marker color in RGB (default = [1 1 1], i.e. white) +% cfg.interactive 'yes' or 'no' (default), interactive coordinates +% and source values +% +% if cfg.alpha is set to 'adaptive' the opacity of the source overlay +% linearly follows the source value: maxima are opaque and minima are +% transparent. +% +% if cfg.spacemin and/or cfg.spacemax are set to 'auto' the sliced +% space is automatically restricted to the evaluated source-space +% +% if cfg.colmin and/or cfg.colmax are set to 'auto' the colormap is mapped +% to source values the following way: if source values are either all +% positive or all negative the colormap is mapped to from +% min(source) to max(source). If source values are negative and positive +% the colormap is symmetrical mapped around 0 from -max(abs(source)) to +% +max(abs(source)). +% +% If cfg.maskparameter specifies a parameter to be used as an opacity mask +% cfg.alpha is not used. Instead the mask values are maped to an opacitymap +% that can be specified using cfg.maskmap. The mapping onto that +% opacitymap is controlled as for the functional data using the +% corresponding clipping and min/max options. +% +% if cfg.whitebg is set to 'yes' the function estimates the head volume and +% displays a white background outside the head, which can save a lot of black +% printer toner. +% +% if cfg.interactive is set to 'yes' a button will be displayed for +% interactive data evaluation and coordinate reading. After clicking the +% button named 'coords' you can click on any position in the slice montage. +% After clicking these coordinates and their source value are displayed in +% a text box below the button. The coordinates correspond to indeces in the +% input data array: +% +% f = interp.source(coord_1,coord_2,coord_3) +% +% The coordinates are not affected by any transformations used for displaying +% the data such as cfg.dim, cfg.rotate,cfg.flipdim or cfg.resample. + +% Copyright (C) 2004, Markus Siegel, markus.siegel@fcdonders.kun.nl +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_sliceinterp.m 948 2010-04-21 18:02:21Z roboos $ + +fieldtripdefs + +% check if the input data is valid for this function +ininterp = checkdata(ininterp, 'datatype', 'volume', 'feedback', 'yes'); + +if ~isfield(cfg, 'clipmin'); cfg.clipmin = 'auto'; end +if ~isfield(cfg, 'clipmax'); cfg.clipmax = 'auto'; end +if ~isfield(cfg, 'clipsym'); cfg.clipsym = 'no'; end +if ~isfield(cfg, 'alpha'); cfg.alpha = 'adaptive'; end +if ~isfield(cfg, 'nslices'); cfg.nslices = 20; end +if ~isfield(cfg, 'dim'); cfg.dim = 3; end +if ~isfield(cfg, 'colormap'); cfg.colormap = jet(128); end +if ~isfield(cfg, 'spacemin'); cfg.spacemin = 'auto'; end +if ~isfield(cfg, 'spacemax'); cfg.spacemax = 'auto'; end +if ~isfield(cfg, 'colmin'); cfg.colmin = 'auto'; end +if ~isfield(cfg, 'colmax'); cfg.colmax = 'auto'; end +if ~isfield(cfg, 'resample'); cfg.resample = 1; end +if ~isfield(cfg, 'rotate'); cfg.rotate = 0; end +if ~isfield(cfg, 'title'); cfg.title = ''; end +if ~isfield(cfg, 'whitebg'); cfg.whitebg = 'no'; end +if ~isfield(cfg, 'flipdim'); cfg.flipdim = 'no'; end +if ~isfield(cfg, 'marker'); cfg.marker = []; end +if ~isfield(cfg, 'markersize'); cfg.markersize = 5; end +if ~isfield(cfg, 'markercolor'); cfg.markercolor = [1,1,1]; end +if ~isfield(cfg, 'interactive'); cfg.interactive = 'no'; end +if ~isfield(cfg, 'maskclipmin'); cfg.maskclipmin = 'auto'; end +if ~isfield(cfg, 'maskclipmax'); cfg.maskclipmax = 'auto'; end +if ~isfield(cfg, 'maskclipsym'); cfg.maskclipsym = 'no'; end +if ~isfield(cfg, 'maskmap'); cfg.maskmap = linspace(0,1,128); end +if ~isfield(cfg, 'maskcolmin'); cfg.maskcolmin = 'auto'; end +if ~isfield(cfg, 'maskcolmax'); cfg.maskcolmax = 'auto'; end +if ~isfield(cfg, 'maskparameter');cfg.maskparameter = []; end + +% perform some checks on the configuration for backward compatibility +if ~isfield(cfg, 'funparameter') && isfield(ininterp, 'source') + % if present, the default behavior should be to use this field for plotting + cfg.funparameter = 'source'; +end + +% make the selection of functional and mask data consistent with the data +cfg.funparameter = parameterselection(cfg.funparameter, ininterp); +cfg.maskparameter = parameterselection(cfg.maskparameter, ininterp); +% only a single parameter should be selected +try, cfg.funparameter = cfg.funparameter{1}; end +try, cfg.maskparameter = cfg.maskparameter{1}; end + +% check anatomical data +if isfield(ininterp,'anatomy'); + interp.anatomy = reshape(ininterp.anatomy, ininterp.dim); +else + error('no anatomical data supplied'); +end + +% check functional data +if ~isempty(cfg.funparameter) + interp.source = double(reshape(getsubfield(ininterp, cfg.funparameter), ininterp.dim)); +else + error('no functional data supplied'); +end + +% check mask data +if ~isempty(cfg.maskparameter) + interp.mask = double(reshape(getsubfield(ininterp,cfg.maskparameter), ininterp.dim)); + maskdat = 1; +else + fprintf('no opacity mask data supplied\n'); + interp.mask = []; + maskdat = 0; +end + +% only work with the copy of the relevant parameters in "interp" +clear ininterp; + +% convert anatomy data type and optimize contrast +if isa(interp.anatomy, 'uint8') || isa(interp.anatomy, 'uint16') + fprintf('converting anatomy to floating point values...'); + interp.anatomy = double(interp.anatomy); + fprintf('done\n'); +end +fprintf('optimizing contrast of anatomical data ...'); +minana = min(interp.anatomy(:)); +maxana = max(interp.anatomy(:)); +interp.anatomy = (interp.anatomy-minana)./(maxana-minana); +fprintf('done\n'); + +% store original data if 'interactive' mode +if strcmp(cfg.interactive,'yes') + data.source = interp.source; +end + +% place markers +marker = zeros(size(interp.anatomy)); +if ~isempty(cfg.marker) + fprintf('placing markers ...'); + [x,y,z] = ndgrid([1:size(interp.anatomy,1)],[1:size(interp.anatomy,2)],[1:size(interp.anatomy,3)]); + for imarker = 1:size(cfg.marker,1) + marker(find(sqrt((x-cfg.marker(imarker,1)).^2 + (y-cfg.marker(imarker,2)).^2 + (z-cfg.marker(imarker,3)).^2)<=cfg.markersize)) = 1; + end + fprintf('done\n'); +end + +% shift dimensions +fprintf('sorting dimensions...'); +interp.anatomy = shiftdim(interp.anatomy,cfg.dim-1); +interp.source = shiftdim(interp.source,cfg.dim-1); +interp.mask = shiftdim(interp.mask,cfg.dim-1); +marker = shiftdim(marker,cfg.dim-1); +fprintf('done\n'); + +% flip dimensions +if strcmp(cfg.flipdim,'yes') + fprintf('flipping dimensions...'); + interp.anatomy = flipdim(interp.anatomy,1); + interp.source = flipdim(interp.source,1); + interp.mask = flipdim(interp.mask,1); + marker = flipdim(marker,1); + fprintf('done\n'); +end + +% set slice space +if ischar(cfg.spacemin) + fprintf('setting first slice position...'); + spacemin = min(find(~isnan(max(max(interp.source,[],3),[],2)))); + fprintf('%d...done\n',spacemin); +else + spacemin = cfg.spacemin; +end + +if ischar(cfg.spacemax) + fprintf('setting last slice position...'); + spacemax = max(find(~isnan(max(max(interp.source,[],3),[],2)))); + fprintf('%d...done\n',spacemax); +else + spacemax = cfg.spacemax; +end + +% clip funtional data +if ~ischar(cfg.clipmin) + fprintf('clipping functional minimum...'); + switch cfg.clipsym + case 'no' + interp.source(find(interp.sourcecfg.clipmax)) = nan; + case 'yes' + interp.source(find(abs(interp.source)>cfg.clipmax)) = nan; + end + fprintf('done\n'); +end + +% clip mask data +if maskdat + if ~ischar(cfg.maskclipmin) + fprintf('clipping mask minimum...'); + switch cfg.maskclipsym + case 'no' + interp.mask(find(interp.maskcfg.maskclipmax)) = nan; + case 'yes' + interp.mask(find(abs(interp.mask)>cfg.maskclipmax)) = nan; + end + fprintf('done\n'); + end +end + +% scale functional data +fprintf('scaling functional data...'); +fmin = min(interp.source(:)); +fmax = max(interp.source(:)); +if ~ischar(cfg.colmin) + fcolmin = cfg.colmin; +else + if sign(fmin)==sign(fmax) + fcolmin = fmin; + else + fcolmin = -max(abs([fmin,fmax])); + end +end +if ~ischar(cfg.colmax) + fcolmax = cfg.colmax; +else + if sign(fmin)==sign(fmax) + fcolmax = fmax; + else + fcolmax = max(abs([fmin,fmax])); + end +end +interp.source = (interp.source-fcolmin)./(fcolmax-fcolmin); +if ~ischar(cfg.colmax) + interp.source(find(interp.source>1)) = 1; +end +if ~ischar(cfg.colmin) + interp.source(find(interp.source<0)) = 0; +end +fprintf('done\n'); + +% scale mask data +if maskdat + fprintf('scaling mask data...'); + fmin = min(interp.mask(:)); + fmax = max(interp.mask(:)); + if ~ischar(cfg.maskcolmin) + mcolmin = cfg.maskcolmin; + else + if sign(fmin)==sign(fmax) + mcolmin = fmin; + else + mcolmin = -max(abs([fmin,fmax])); + end + end + if ~ischar(cfg.maskcolmax) + mcolmax = cfg.maskcolmax; + else + if sign(fmin)==sign(fmax) + mcolmax = fmax; + else + mcolmax = max(abs([fmin,fmax])); + end + end + interp.mask = (interp.mask-mcolmin)./(mcolmax-mcolmin); + if ~ischar(cfg.maskcolmax) + interp.mask(find(interp.mask>1)) = 1; + end + if ~ischar(cfg.maskcolmin) + interp.mask(find(interp.mask<0)) = 0; + end + fprintf('done\n'); +end + +% merge anatomy, functional data and mask +fprintf('constructing overlay...'); +if ischar(cfg.colormap) + % replace string by colormap using standard Matlab function + cfg.colormap = colormap(cfg.colormap); +end +cmap = cfg.colormap; +cmaplength = size(cmap,1); +maskmap = cfg.maskmap(:); +maskmaplength = size(maskmap,1); +indslice = round(linspace(spacemin,spacemax,cfg.nslices)); +nvox1 = length(1:cfg.resample:size(interp.anatomy,2)); +nvox2 = length(1:cfg.resample:size(interp.anatomy,3)); +if mod(cfg.rotate,2) + dummy = nvox1; + nvox1 = nvox2; + nvox2 = dummy; +end +out = zeros(nvox1,nvox2,3,cfg.nslices); +for islice = 1:cfg.nslices + dummy1 = squeeze(interp.anatomy(indslice(islice),1:cfg.resample:end,1:cfg.resample:end)); + dummy2 = squeeze(interp.source(indslice(islice),1:cfg.resample:end,1:cfg.resample:end)); + indmarker = find(squeeze(marker(indslice(islice),1:cfg.resample:end,1:cfg.resample:end))); + indsource = find(~isnan(dummy2)); + if maskdat + dummymask = squeeze(interp.mask(indslice(islice),1:cfg.resample:end,1:cfg.resample:end)); + indsource = find(~isnan(dummy2) & ~isnan(dummymask)); + end + for icol = 1:3 + dummy3 = dummy1; + if not(maskdat) + if ~ischar(cfg.alpha) + try + dummy3(indsource) = ... + (1-cfg.alpha) * dummy3(indsource) + ... + cfg.alpha * cmap(round(dummy2(indsource)*(cmaplength-1))+1,icol); + end + else + try + dummy3(indsource) = ... + (1-dummy2(indsource)) .* dummy3(indsource) + ... + dummy2(indsource) .* cmap(round(dummy2(indsource)*(cmaplength-1))+1,icol); + end + end + else + dummy3(indsource) = ... + (1-maskmap(round(dummymask(indsource)*(maskmaplength-1))+1)).* ... + dummy3(indsource) + ... + maskmap(round(dummymask(indsource)*(maskmaplength-1))+1) .* ... + cmap(round(dummy2(indsource)*(cmaplength-1))+1,icol); + end + dummy3(indmarker) = cfg.markercolor(icol); + out(:,:,icol,islice) = rot90(dummy3,cfg.rotate); + end + if strcmp(cfg.whitebg,'yes') + bgmask = zeros(nvox1,nvox2); + bgmask(find(conv2(mean(out(:,:,:,islice),3),ones(round((nvox1+nvox2)/8))/(round((nvox1+nvox2)/8).^2),'same')<0.1)) = 1; + for icol = 1:3 + out(:,:,icol,islice) = bgmask.*ones(nvox1,nvox2) + (1-bgmask).* out(:,:,icol,islice); + end + end +end +fprintf('done\n'); + +clf; +fprintf('plotting...'); +axes('position',[0.9 0.3 0.02 0.4]); +image(permute(cmap,[1 3 2])); +set(gca,'YAxisLocation','right'); +set(gca,'XTick',[]); +set(gca,'YDir','normal'); +set(gca,'YTick',linspace(1,cmaplength,5)); +set(gca,'YTickLabel',linspace(fcolmin,fcolmax,5)); +set(gca,'Box','on'); +axes('position',[0.01 0.01 0.88 0.90]); +[h,nrows,ncols]=slicemon(out); +xlim=get(gca,'XLim'); +ylim=get(gca,'YLim'); +text(diff(xlim)/2,-diff(ylim)/100,cfg.title,'HorizontalAlignment','center','Interpreter','none'); +drawnow; +fprintf('done\n'); +if nargout > 0 + outim=get(h,'CData'); +end + +if strcmp(cfg.interactive,'yes') + data.sin = size(interp.source); + data.nrows = nrows; + data.ncols = ncols; + data.out = out; + data.indslice = indslice; + data.cfg = cfg; + data.hfig = gcf; + uicontrol('Units','norm', 'Position', [0.9 0.2 0.08 0.05], 'Style','pushbutton', 'String','coords',... + 'Callback',@getcoords,'FontSize',7); + data.hcoords = uicontrol('Units','norm', 'Position', [0.9 0.05 0.08 0.13], 'Style','text', 'String','','HorizontalAlign','left','FontSize',7); + guidata(data.hfig,data); +end + +% ---------------- subfunctions ---------------- + +function getcoords(h,eventdata,handles,varargin) +data = guidata(gcf); +[xi,yi] = ginput(1); + +co(2,1) = round(mod(yi,size(data.out,1))); +co(3,1) = round(mod(xi,size(data.out,2))); +switch mod(data.cfg.rotate,4) +case 1, + t1 = co(2); + co(2) = co(3); + co(3) = data.sin(3)-t1; +case 2, + co(2) = data.sin(2)-co(2); + co(3) = data.sin(3)-co(3); +case 3, + t1 = co(3); + co(3) = co(2); + co(2) = data.sin(2)-t1; +end + +try + co(1) = data.indslice(fix(xi/size(data.out,2)) + fix(yi/size(data.out,1))*data.ncols + 1); +catch + co(1) = NaN; +end + +if strcmp(data.cfg.flipdim, 'yes') + co(1) = data.sin(1) - co(1) + 1; +end +co = co(:); + +co(2:3) = round(co(2:3)*data.cfg.resample); +for ishift = 1:data.cfg.dim-1 + co = [co(3);co(1);co(2)]; +end +set(data.hcoords,'String',sprintf('1: %d\n2: %d\n3: %d\nf: %0.4f',co(1),co(2),co(3),data.source(co(1),co(2),co(3)))); + +function [h,nrows,ncols] = slicemon(a) % display the montage w/o image_toolbox +siz = [size(a,1) size(a,2) size(a,4)]; +nn = sqrt(prod(siz))/siz(2); +mm = siz(3)/nn; +if (ceil(nn)-nn) < (ceil(mm)-mm), + nn = ceil(nn); mm = ceil(siz(3)/nn); +else + mm = ceil(mm); nn = ceil(siz(3)/mm); +end +b = a(1,1); +b(1,1) = 0; +b = repmat(b, [mm*siz(1), nn*siz(2), size(a,3), 1]); +rows = 1:siz(1); cols = 1:siz(2); +for i=0:mm-1, + for j=0:nn-1, + k = j+i*nn+1; + if k<=siz(3), + b(rows+i*siz(1),cols+j*siz(2),:) = a(:,:,:,k); + end + end +end +hh = image(b); +axis image; +box off; +set(gca,'XTick',[],'YTick',[],'Visible','off'); +if nargout > 0 + h = hh; + nrows = mm; + ncols = nn; +end diff --git a/external/fieldtrip/ft_source2grid.m b/external/fieldtrip/ft_source2grid.m deleted file mode 100644 index b84b9b2..0000000 --- a/external/fieldtrip/ft_source2grid.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'ft_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_sourceanalysis.m b/external/fieldtrip/ft_sourceanalysis.m index b84b9b2..905ed1b 100644 --- a/external/fieldtrip/ft_sourceanalysis.m +++ b/external/fieldtrip/ft_sourceanalysis.m @@ -1,11 +1,1036 @@ -function varargout = funname(varargin); +function [source] = ft_sourceanalysis(cfg, data, baseline); -% this is a SPM wrapper around a FieldTrip function +% FT_SOURCEANALYSIS performs beamformer dipole analysis on EEG or MEG data +% after preprocessing and a timelocked or frequency analysis +% +% Use as either +% [source] = ft_sourceanalysis(cfg, freq) +% [source] = ft_sourceanalysis(cfg, timelock) +% +% where the data in freq or timelock should be organised in a structure +% as obtained from the FT_FREQANALYSIS or FT_TIMELOCKANALYSIS function. The +% configuration "cfg" is a structure containing information about +% source positions and other options. +% +% The different source reconstruction algorithms that are implemented +% are +% cfg.method = 'lcmv' linear constrained minimum variance beamformer +% 'sam' synthetic aperture magnetometry +% 'dics' dynamic imaging of coherent sources +% 'pcc' partial cannonical correlation/coherence +% 'mne' minimum norm estimation +% 'loreta' minimum norm estimation with smoothness constraint +% 'rv' scan residual variance with single dipole +% 'music' multiple signal classification +% 'mvl' multivariate Laplace source localization +% The DICS and PCC methods are for frequency domain data, all other methods +% are for time domain data. +% +% The positions of the sources can be specified as a regular 3-D +% grid that is aligned with the axes of the head coordinate system +% cfg.grid.xgrid = vector (e.g. -20:1:20) or 'auto' (default = 'auto') +% cfg.grid.ygrid = vector (e.g. -20:1:20) or 'auto' (default = 'auto') +% cfg.grid.zgrid = vector (e.g. 0:1:20) or 'auto' (default = 'auto') +% cfg.grid.resolution = number (e.g. 1 cm) for automatic grid generation +% Alternatively the position of a few sources at locations of interest can +% be specified, for example obtained from an anatomical or functional MRI +% cfg.grid.pos = Nx3 matrix with position of each source +% cfg.grid.dim = [Nx Ny Nz] vector with dimensions in case of 3-D grid (optional) +% cfg.grid.inside = vector with indices of the sources inside the brain (optional) +% cfg.grid.outside = vector with indices of the sources outside the brain (optional) +% You can also use the FT_PREPARE_LEADFIELD function to create a grid with +% dipole positions and with precomputed leadfields. +% +% The following strategies are supported to obtain statistics for the source parameters using +% multiple trials in the data, either directly or through a resampling-based approach +% cfg.singletrial = 'no' or 'yes' construct filter from average, apply to single trials +% cfg.rawtrial = 'no' or 'yes' construct filter from single trials, apply to single trials +% cfg.jackknife = 'no' or 'yes' jackknife resampling of trials +% cfg.pseudovalue = 'no' or 'yes' pseudovalue resampling of trials +% cfg.bootstrap = 'no' or 'yes' bootstrap resampling of trials +% cfg.numbootstrap = number of bootstrap replications (e.g. number of original trials) +% If none of these options is specified, the average over the trials will +% be computed prior to computing the source reconstruction. +% +% To obtain statistics over the source parameters between two conditions, you +% can also use a resampling procedure that reshuffles the trials over both +% conditions. In that case, you should call the function with two datasets +% containing single trial data like +% [source] = ft_sourceanalysis(cfg, freqA, freqB) +% [source] = ft_sourceanalysis(cfg, timelockA, timelockB) +% and you should specify +% cfg.randomization = 'no' or 'yes' +% cfg.permutation = 'no' or 'yes' +% cfg.numrandomization = number, e.g. 500 +% cfg.numpermutation = number, e.g. 500 or 'all' +% +% You should specify the volume conductor model with +% cfg.hdmfile = string, file containing the volume conduction model +% or alternatively +% cfg.vol = structure with volume conduction model +% +% If the sensor information is not contained in the data itself you should +% also specify the sensor information using +% cfg.gradfile = string, file containing the gradiometer definition +% cfg.elecfile = string, file containing the electrode definition +% or alternatively +% cfg.grad = structure with gradiometer definition +% cfg.elec = structure with electrode definition +% +% If you have not specified a grid with pre-computed leadfields, +% the leadfield for each grid location will be computed on the fly. +% In that case you can modify the leadfields by reducing the rank +% (i.e. remove the weakest orientation), or by normalizing each +% column. +% cfg.reducerank = 'no', or number (default = 3 for EEG, 2 for MEG) +% cfg.normalize = 'no' or 'yes' (default = 'no') +% +% Other configuration options are +% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), +% see FT_CHANNELSELECTION for details +% cfg.frequency = single number (in Hz) +% cfg.latency = single number in seconds, for time-frequency analysis +% cfg.lambda = number or empty for automatic default +% cfg.refchan = reference channel label (for coherence) +% cfg.refdip = reference dipole location (for coherence) +% cfg.supchan = suppressed channel label(s) +% cfg.supdip = suppressed dipole location(s) +% cfg.keeptrials = 'no' or 'yes' +% cfg.keepleadfield = 'no' or 'yes' +% cfg.projectnoise = 'no' or 'yes' +% cfg.keepfilter = 'no' or 'yes' +% cfg.keepcsd = 'no' or 'yes' +% cfg.keepmom = 'no' or 'yes' +% cfg.feedback = 'no', 'text', 'textbar', 'gui' (default = 'text') +% +% See also FT_SOURCEDESCRIPTIVES, FT_SOURCESTATISTICS, FT_PREPARE_LEADFIELD -% this part is variable -prefix = 'ft_'; +% Undocumented local options: +% cfg.numcomponents +% cfg.refchannel +% cfg.trialweight = 'equal' or 'proportional' +% cfg.powmethod = 'lambda1' or 'trace' +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk +% +% This function depends on FT_PREPARE_DIPOLE_GRID which has the following options: +% cfg.grid.xgrid (default set in FT_PREPARE_DIPOLE_GRID: cfg.grid.xgrid = 'auto'), documented +% cfg.grid.ygrid (default set in FT_PREPARE_DIPOLE_GRID: cfg.grid.ygrid = 'auto'), documented +% cfg.grid.zgrid (default set in FT_PREPARE_DIPOLE_GRID: cfg.grid.zgrid = 'auto'), documented +% cfg.grid.resolution, documented +% cfg.grid.pos, documented +% cfg.grid.dim, documented +% cfg.grid.inside, documented +% cfg.grid.outside, documented +% cfg.mri +% cfg.mriunits +% cfg.smooth +% cfg.sourceunits +% cfg.threshold +% cfg.symmetry +% +% This function depends on FT_PREPARE_FREQ_MATRICES which has the following options: +% cfg.channel (default set in FT_SOURCEANALYSIS: cfg.channel = 'all'), documented +% cfg.dicsfix +% cfg.frequency, documented +% cfg.latency, documented +% cfg.refchan, documented +% +% This function depends on FT_PREPARE_RESAMPLED_DATA which has the following options: +% cfg.jackknife (default set in FT_SOURCEANALYSIS: cfg.jackknife = 'no'), documented +% cfg.numbootstrap, documented +% cfg.numcondition (set in FT_SOURCEANALYSIS: cfg.numcondition = 2) +% cfg.numpermutation (default set in FT_SOURCEANALYSIS: cfg.numpermutation = 100), documented +% cfg.numrandomization (default set in FT_SOURCEANALYSIS: cfg.numrandomization = 100), documented +% cfg.permutation (default set in FT_SOURCEANALYSIS: cfg.permutation = 'no'), documented +% cfg.pseudovalue (default set in FT_SOURCEANALYSIS: cfg.pseudovalue = 'no'), documented +% cfg.randomization (default set in FT_SOURCEANALYSIS: cfg.randomization = 'no'), documented +% +% This function depends on FT_PREPARE_VOL_SENS which has the following options: +% cfg.channel, (default set in FT_SOURCEANALYSIS: cfg.channel = 'all'), documented +% cfg.elec, documented +% cfg.elecfile, documented +% cfg.grad, documented +% cfg.gradfile, documented +% cfg.hdmfile, documented +% cfg.order +% cfg.vol, documented +% +% This function depends on FT_PREPARE_LEADFIELD which has the following options: +% cfg.feedback, (default set in FT_SOURCEANALYSIS: cfg.feedback = 'text'), documented +% cfg.grid, documented +% cfg.lbex +% cfg.normalize (default set in FT_SOURCEANALYSIS), documented +% cfg.previous +% cfg.reducerank (default set in FT_SOURCEANALYSIS), documented +% cfg.sel50p +% cfg.version + +% Copyright (c) 2003-2008, Robert Oostenveld, F.C. Donders Centre +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_sourceanalysis.m 1258 2010-06-22 08:33:48Z timeng $ + +fieldtripdefs + +% set a timer to determine how long the sourceanalysis takes in total +tic; + +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +% set defaults for optional cfg.inputfile, cfg.outputfile +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +% load optional given inputfile as data +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + end +end + +% check if the input data is valid for this function +data = checkdata(data, 'datatype', {'timelock', 'freq', 'comp'}, 'feedback', 'yes'); +if nargin>2 + baseline = checkdata(baseline, 'datatype', {'timelock', 'freq', 'comp'}, 'feedback', 'yes'); +end + +% check if the input cfg is valid for this function +cfg = checkconfig(cfg, 'renamed', {'jacknife', 'jackknife'}); +cfg = checkconfig(cfg, 'renamed', {'refchannel', 'refchan'}); +cfg = checkconfig(cfg, 'renamedval', {'method', 'power', 'dics'}); +cfg = checkconfig(cfg, 'renamedval', {'method', 'coh_refchan', 'dics'}); +cfg = checkconfig(cfg, 'renamedval', {'method', 'coh_refdip', 'dics'}); +cfg = checkconfig(cfg, 'renamedval', {'method', 'dics_cohrefchan', 'dics'}); +cfg = checkconfig(cfg, 'renamedval', {'method', 'dics_cohrefdip', 'dics'}); +cfg = checkconfig(cfg, 'forbidden', {'parallel'}); + +% determine the type of input data +if isfield(data, 'freq') + isfreq = 1; + iscomp = 0; + istimelock = 0; +elseif isfield(data, 'topo') + isfreq = 0; + iscomp = 1; + istimelock = 0; +elseif isfield(data, 'time') + iscomp = 0; + isfreq = 0; + istimelock = 1; +else + error('input data is not recognized'); +end + +% set the defaults +if ~isfield(cfg, 'method') && istimelock, cfg.method = 'lcmv'; end +if ~isfield(cfg, 'method') && isfreq, cfg.method = 'dics'; end +if ~isfield(cfg, 'keeptrials') cfg.keeptrials = 'no'; end +if ~isfield(cfg, 'keepfilter') cfg.keepfilter = 'no'; end +if ~isfield(cfg, 'keepleadfield') cfg.keepleadfield = 'no'; end +if ~isfield(cfg, 'keepcsd') cfg.keepcsd = 'no'; end +if ~isfield(cfg, 'keepmom') cfg.keepmom = 'yes'; end +if ~isfield(cfg, 'projectnoise') cfg.projectnoise = 'no'; end +if ~isfield(cfg, 'trialweight') cfg.trialweight = 'equal'; end +if ~isfield(cfg, 'jackknife'), cfg.jackknife = 'no'; end +if ~isfield(cfg, 'pseudovalue'), cfg.pseudovalue = 'no'; end +if ~isfield(cfg, 'bootstrap'), cfg.bootstrap = 'no'; end +if ~isfield(cfg, 'singletrial'), cfg.singletrial = 'no'; end +if ~isfield(cfg, 'rawtrial'), cfg.rawtrial = 'no'; end +if ~isfield(cfg, 'randomization'), cfg.randomization = 'no'; end +if ~isfield(cfg, 'numrandomization'), cfg.numrandomization = 100; end +if ~isfield(cfg, 'permutation'), cfg.permutation = 'no'; end +if ~isfield(cfg, 'numpermutation'), cfg.numpermutation = 100; end +if ~isfield(cfg, 'wakewulf'), cfg.wakewulf = 'yes'; end +if ~isfield(cfg, 'killwulf'), cfg.killwulf = 'yes'; end +if ~isfield(cfg, 'feedback'), cfg.feedback = 'text'; end +if ~isfield(cfg, 'supdip'), cfg.supdip = []; end +if ~isfield(cfg, 'lambda'), cfg.lambda = []; end +if ~isfield(cfg, 'powmethod'), cfg.powmethod = []; end +if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end +if ~isfield(cfg, 'normalize'), cfg.normalize = 'no'; end +if ~isfield(cfg, 'prewhiten'), cfg.prewhiten = 'no'; end +% if ~isfield(cfg, 'reducerank'), cfg.reducerank = 'no'; end % the default for this depends on EEG/MEG and is set below + +% put the low-level options pertaining to the source reconstruction method in their own field +% put the low-level options pertaining to the dipole grid in their own field +cfg = checkconfig(cfg, 'createsubcfg', {cfg.method, 'grid'}); + +convertfreq = 0; +convertcomp = 0; +if ~istimelock && (strcmp(cfg.method, 'mne') || strcmp(cfg.method, 'loreta') || strcmp(cfg.method, 'rv') || strcmp(cfg.method, 'music')) + % these timelock methods are also supported for frequency or component data + if isfreq + [data, cfg] = freq2timelock(cfg, data); + convertfreq = 1; % flag indicating that the data was converted + elseif iscomp + [data, cfg] = comp2timelock(cfg, data); + convertcomp = 1; % flag indicating that the data was converted + end + istimelock = 1; % from now on the data can be treated as timelocked + isfreq = 0; + iscomp = 0; +end + +% select only those channels that are present in the data +cfg.channel = ft_channelselection(cfg.channel, data.label); + +if nargin>2 && (strcmp(cfg.randomization, 'no') && strcmp(cfg.permutation, 'no') && strcmp(cfg.prewhiten, 'no')) + error('input of two conditions only makes sense if you want to randomize or permute, or if you want to prewhiten'); +elseif nargin<3 && (strcmp(cfg.randomization, 'yes') || strcmp(cfg.permutation, 'yes')) + error('randomization or permutation requires that you give two conditions as input'); +end + +if isfield(cfg, 'latency') && istimelock + error('specification of cfg.latency is only required for time-frequency data'); +end + +if sum([strcmp(cfg.jackknife, 'yes'), strcmp(cfg.bootstrap, 'yes'), strcmp(cfg.pseudovalue, 'yes'), strcmp(cfg.singletrial, 'yes'), strcmp(cfg.rawtrial, 'yes'), strcmp(cfg.randomization, 'yes'), strcmp(cfg.permutation, 'yes')])>1 + error('jackknife, bootstrap, pseudovalue, singletrial, rawtrial, randomization and permutation are mutually exclusive'); +end + +if isfreq + if ~strcmp(data.dimord, 'chan_freq') && ... + ~strcmp(data.dimord, 'chan_freq_time') && ... + ~strcmp(data.dimord, 'rpt_chan_freq') && ... + ~strcmp(data.dimord, 'rpt_chan_freq_time') && ... + ~strcmp(data.dimord, 'rpttap_chan_freq') && ... + ~strcmp(data.dimord, 'rpttap_chan_freq_time') + error('dimord of input frequency data is not recognized'); + end +end + +% collect and preprocess the electrodes/gradiometer and head model +[vol, sens, cfg] = prepare_headmodel(cfg, data); + +% It might be that the number of channels in the data, the number of +% channels in the electrode/gradiometer definition and the number of +% channels in the multisphere volume conduction model are different. +% Hence a subset of the data channels will be used. +Nchans = length(cfg.channel); + +% set the default for reducing the rank of the leadfields, this is an +% option to the specific method and will be passed on to the low-level +% function +if ~isfield(cfg.(cfg.method), 'reducerank') + if ft_senstype(sens, 'meg') + cfg.(cfg.method).reducerank = 2; + else + cfg.(cfg.method).reducerank = 3; + end +end + +if strcmp(cfg.keepleadfield, 'yes') && (~isfield(cfg, 'grid') || ~isfield(cfg.grid, 'leadfield')) + % precompute the leadfields upon the users request + fprintf('precomputing leadfields\n'); + [grid, cfg] = ft_prepare_leadfield(cfg, data); +elseif (strcmp(cfg.permutation, 'yes') || ... + strcmp(cfg.randomization, 'yes') || ... + strcmp(cfg.bootstrap, 'yes') || ... + strcmp(cfg.jackknife, 'yes') || ... + strcmp(cfg.pseudovalue, 'yes') || ... + strcmp(cfg.singletrial, 'yes') || ... + strcmp(cfg.rawtrial, 'yes')) && (~isfield(cfg, 'grid') || ~isfield(cfg.grid, 'leadfield')) + % also precompute the leadfields if multiple trials have to be processed + fprintf('precomputing leadfields for efficient handling of multiple trials\n'); + [grid, cfg] = ft_prepare_leadfield(cfg, data); +else + % only prepare the grid positions, the leadfield will be computed on the fly if not present + [grid, cfg] = prepare_dipole_grid(cfg, vol, sens); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% do frequency domain source reconstruction +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +if isfreq && any(strcmp(cfg.method, {'dics', 'pcc'})) + + if strcmp(cfg.method, 'pcc') + % HACK: requires some extra defaults + if ~isfield(cfg, 'refdip'), cfg.refdip = []; end + if ~isfield(cfg, 'supdip'), cfg.supdip = []; end + if ~isfield(cfg, 'refchan'), cfg.refchan = []; end + if ~isfield(cfg, 'supchan'), cfg.supchan = []; end + cfg.refchan = ft_channelselection(cfg.refchan, data.label); + cfg.supchan = ft_channelselection(cfg.supchan, data.label); + + % HACK: use some experimental code + if nargin>2 && strcmp(cfg.prewhiten, 'no'), + error('not supported') + end + tmpcfg = cfg; + tmpcfg.refchan = ''; % prepare_freq_matrices should not know explicitly about the refchan + tmpcfg.channel = cfg.channel(:)'; + if isfield(cfg, 'refchan') + % add the refchan implicitely + tmpcfg.channel = [tmpcfg.channel cfg.refchan(:)']; + end + if isfield(cfg, 'supchan') + % add the supchan implicitely + tmpcfg.channel = [tmpcfg.channel cfg.supchan(:)']; + end + + % select the data in the channels and the frequency of interest + [Cf, Cr, Pr, Ntrials, tmpcfg] = prepare_freq_matrices(tmpcfg, data); + if strcmp(cfg.prewhiten, 'yes'), + [Cfb, Crb, Prb, Ntrialsb, tmpcfgb] = prepare_freq_matrices(tmpcfg, baseline); + Cf = prewhitening_filter2(squeeze(mean(Cf,1)), squeeze(mean(Cfb,1))); + Ntrials = 1; + end + + if isfield(cfg, 'refchan') && ~isempty(cfg.refchan) + [dum, refchanindx] = match_str(cfg.refchan, tmpcfg.channel); + else + refchanindx = []; + end + if isfield(cfg, 'supchan') && ~isempty(cfg.supchan) + [dum, supchanindx] = match_str(cfg.supchan,tmpcfg.channel); + else + supchanindx = []; + end + Nchans = length(tmpcfg.channel); % update the number of channels + + % if the input data has a complete fourier spectrum, project it through the filters + % FIXME it was incorrect , since the + % ' leads to a conjugate transposition check this in beamformer_pcc + if isfield(data, 'fourierspctrm') + [dum, datchanindx] = match_str(tmpcfg.channel, data.label); + fbin = nearest(data.freq, cfg.frequency); + if strcmp(data.dimord, 'chan_freq') + avg = data.fourierspctrm(datchanindx, fbin); + elseif strcmp(data.dimord, 'rpt_chan_freq') || strcmp(data.dimord, 'rpttap_chan_freq'), + %avg = data.fourierspctrm(:, datchanindx, fbin)'; + avg = transpose(data.fourierspctrm(:, datchanindx, fbin)); + elseif strcmp(data.dimord, 'chan_freq_time') + tbin = nearest(data.time, cfg.latency); + avg = data.fourierspctrm(datchanindx, fbin, tbin); + elseif strcmp(data.dimord, 'rpt_chan_freq_time') || strcmp(data.dimord, 'rpttap_chan_freq_time'), + tbin = nearest(data.time, cfg.latency); + %avg = data.fourierspctrm(:, datchanindx, fbin, tbin)'; + avg = transpose(data.fourierspctrm(:, datchanindx, fbin, tbin)); + end + else + avg = []; + end + + else + % HACK: use the default code + % convert the input data, so that Cf, Cr and Pr contain either the average over all trials (if Ntrials==1) + % or the individual cross-spectral-densities/powers of each individual trial (if Ntrials>1) + [Cf, Cr, Pr, Ntrials, cfg] = prepare_freq_matrices(cfg, data); + end + + if strcmp(cfg.method, 'dics') + % assign a descriptive name to each of the dics sub-methods, the default is power only + if strcmp(cfg.method, 'dics') && isfield(cfg, 'refdip') && ~isempty(cfg.refdip); + submethod = 'dics_refdip'; + elseif strcmp(cfg.method, 'dics') && isfield(cfg, 'refchan') && ~isempty(cfg.refchan); + submethod = 'dics_refchan'; + else + submethod = 'dics_power'; + end + end + + % fill these with NaNs, so that I dont have to treat them separately + if isempty(Cr), Cr = nan*zeros(Ntrials, Nchans, 1); end + if isempty(Pr), Pr = nan*zeros(Ntrials, 1, 1); end + + if nargin>2 + % repeat the conversion for the baseline condition + [bCf, bCr, bPr, Nbaseline, cfg] = prepare_freq_matrices(cfg, baseline); + % fill these with NaNs, so that I dont have to treat them separately + if isempty(bCr), bCr = nan*zeros(Nbaseline, Nchans, 1); end + if isempty(bPr), bPr = nan*zeros(Nbaseline, 1, 1); end + % rename the active condition for convenience + aCf = Cf; + aCr = Cr; + aPr = Pr; + % this is required for averaging 2 conditions using prepare_resampled_data + cfg2 = []; + cfg2.numcondition = 2; + % this is required for randomizing/permuting 2 conditions using prepare_resampled_data + cfg.numcondition = 2; + end + + % prepare the resampling of the trials, or average the data if multiple trials are present and no resampling is neccessary + if (Ntrials<=1) && (strcmp(cfg.jackknife, 'yes') || strcmp(cfg.bootstrap, 'yes') || strcmp(cfg.pseudovalue, 'yes') || strcmp(cfg.singletrial, 'yes') || strcmp(cfg.rawtrial, 'yes') || strcmp(cfg.randomization, 'yes') || strcmp(cfg.permutation, 'yes')) + error('multiple trials required in the data\n'); + + elseif strcmp(cfg.permutation, 'yes') + % compute the cross-spectral density matrix without resampling + [dum, avg_aCf, avg_aCr, avg_aPr, avg_bCf, avg_bCr, avg_bPr] = prepare_resampled_data(cfg2 , aCf, aCr, aPr, bCf, bCr, bPr); + % compute the cross-spectral density matrix with random permutation + [dum, rnd_aCf, rnd_aCr, rnd_aPr, rnd_bCf, rnd_bCr, rnd_bPr] = prepare_resampled_data(cfg, aCf, aCr, aPr, bCf, bCr, bPr); + % concatenate the different resamplings + Cf = cat(1, reshape(avg_aCf, [1 Nchans Nchans]), reshape(avg_bCf, [1 Nchans Nchans]), rnd_aCf, rnd_bCf); + Cr = cat(1, reshape(avg_aCr, [1 Nchans 1 ]), reshape(avg_bCr, [1 Nchans 1 ]), rnd_aCr, rnd_bCr); + Pr = cat(1, reshape(avg_aPr, [1 1 1 ]), reshape(avg_bPr, [1 1 1 ]), rnd_aPr, rnd_bPr); + % clear temporary working copies + clear avg_aCf avg_aCr avg_aPr avg_bCf avg_bCr avg_bPr + clear rnd_aCf rnd_aCr rnd_aPr rnd_bCf rnd_bCr rnd_bPr + % the order of the resamplings should be [avgA avgB rndA rndB rndA rndB rndA rndB ....] + Nrepetitions = 2*cfg.numpermutation + 2; + order = [1 2 3:2:Nrepetitions 4:2:Nrepetitions]; + Cf = Cf(order,:,:); + Cr = Cr(order,:,:); + Pr = Pr(order,:,:); + + elseif strcmp(cfg.randomization, 'yes') + % compute the cross-spectral density matrix without resampling + [dum, avg_aCf, avg_aCr, avg_aPr, avg_bCf, avg_bCr, avg_bPr] = prepare_resampled_data(cfg2 , aCf, aCr, aPr, bCf, bCr, bPr); + % compute the cross-spectral density matrix with random resampling + [dum, rnd_aCf, rnd_aCr, rnd_aPr, rnd_bCf, rnd_bCr, rnd_bPr] = prepare_resampled_data(cfg, aCf, aCr, aPr, bCf, bCr, bPr); + % concatenate the different resamplings + Cf = cat(1, reshape(avg_aCf, [1 Nchans Nchans]), reshape(avg_bCf, [1 Nchans Nchans]), rnd_aCf, rnd_bCf); + Cr = cat(1, reshape(avg_aCr, [1 Nchans 1 ]), reshape(avg_bCr, [1 Nchans 1 ]), rnd_aCr, rnd_bCr); + Pr = cat(1, reshape(avg_aPr, [1 1 1 ]), reshape(avg_bPr, [1 1 1 ]), rnd_aPr, rnd_bPr); + % clear temporary working copies + clear avg_aCf avg_aCr avg_aPr avg_bCf avg_bCr avg_bPr + clear rnd_aCf rnd_aCr rnd_aPr rnd_bCf rnd_bCr rnd_bPr + % the order of the resamplings should be [avgA avgB rndA rndB rndA rndB rndA rndB ....] + Nrepetitions = 2*cfg.numrandomization + 2; + order = [1 2 3:2:Nrepetitions 4:2:Nrepetitions]; + Cf = Cf(order,:,:); + Cr = Cr(order,:,:); + Pr = Pr(order,:,:); + + elseif strcmp(cfg.jackknife, 'yes') + % compute the cross-spectral density matrix with jackknife resampling + [cfg, Cf, Cr, Pr] = prepare_resampled_data(cfg, Cf, Cr, Pr); + Nrepetitions = Ntrials; + + elseif strcmp(cfg.bootstrap, 'yes') + % compute the cross-spectral density matrix with bootstrap resampling + [cfg, Cf, Cr, Pr] = prepare_resampled_data(cfg, Cf, Cr, Pr); + Nrepetitions = cfg.numbootstrap; + + elseif strcmp(cfg.pseudovalue, 'yes') + % compute the cross-spectral density matrix with pseudovalue resampling + [cfg, Cf, Cr, Pr] = prepare_resampled_data(cfg, Cf, Cr, Pr); + Nrepetitions = Ntrials+1; + + elseif strcmp(cfg.singletrial, 'yes') + % The idea is that beamformer uses the average covariance to construct the + % filter and applies it to the single trial covariance/csd. The problem + % is that beamformer will use the averaged covariance/csd to estimate the + % power and not the single trial covariance/csd + error('this option contains a bug, and is therefore not supported at the moment'); + Cf = Cf; % FIXME, should be averaged and repeated for each trial + Cr = Cr; % FIXME, should be averaged and repeated for each trial + Pr = Pr; % FIXME, should be averaged and repeated for each trial + Nrepetitions = Ntrials; + + elseif strcmp(cfg.rawtrial, 'yes') + % keep all the individual trials, do not average them + Cf = Cf; + Cr = Cr; + Pr = Pr; + Nrepetitions = Ntrials; + + elseif Ntrials>1 + % compute the average from the individual trials + Cf = reshape(sum(Cf, 1) / Ntrials, [Nchans Nchans]); + Cr = reshape(sum(Cr, 1) / Ntrials, [Nchans 1]); + Pr = reshape(sum(Pr, 1) / Ntrials, [1 1]); + Nrepetitions = 1; + + elseif Ntrials==1 + % no rearrangement of trials is neccesary, the data already represents the average + Cf = Cf; + Cr = Cr; + Pr = Pr; + Nrepetitions = 1; + end + + % reshape so that it also looks like one trial (out of many) + if Nrepetitions==1 + Cf = reshape(Cf , [1 Nchans Nchans]); + Cr = reshape(Cr , [1 Nchans 1]); + Pr = reshape(Pr , [1 1 1]); + end + + % get the relevant low level options from the cfg and convert into key-value pairs + optarg = cfg2keyval(getfield(cfg, cfg.method)); + + for i=1:Nrepetitions + fprintf('scanning repetition %d\n', i); + if strcmp(cfg.method, 'dics') && strcmp(submethod, 'dics_power') + dip(i) = beamformer_dics(grid, sens, vol, [], squeeze(Cf(i,:,:)), optarg{:}); + elseif strcmp(cfg.method, 'dics') && strcmp(submethod, 'dics_refchan') + dip(i) = beamformer_dics(grid, sens, vol, [], squeeze(Cf(i,:,:)), optarg{:}, 'Cr', Cr(i,:), 'Pr', Pr(i)); + elseif strcmp(cfg.method, 'dics') && strcmp(submethod, 'dics_refdip') + dip(i) = beamformer_dics(grid, sens, vol, [], squeeze(Cf(i,:,:)), optarg{:}, 'refdip', cfg.refdip); + elseif strcmp(cfg.method, 'pcc') + dip(i) = beamformer_pcc(grid, sens, vol, avg, squeeze(Cf(i,:,:)), optarg{:}, 'refdip', cfg.refdip, 'refchan', refchanindx, 'supdip', cfg.supdip, 'supchan', supchanindx); + else + error(sprintf('method ''%s'' is unsupported for source reconstruction in the frequency domain', cfg.method)); + end + end + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % do time domain source reconstruction + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +elseif istimelock && any(strcmp(cfg.method, {'lcmv', 'sam', 'mne', 'loreta', 'rv', 'music', 'pcc', 'mvl'})) + + % determine the size of the data + Nsamples = size(data.avg,2); + Nchans = length(data.label); + if isfield(data, 'cov') && length(size(data.cov))==3 + Ntrials = size(data.cov,1); + elseif isfield(data, 'trial') && length(size(data.trial))==3 + Ntrials = size(data.trial,1); + else + Ntrials = 1; + end + + if isfield(data, 'cov') + % use the estimated data covariance matrix + hascovariance = 1; + else + % add a identity covariance matrix, this simplifies the handling of the different source reconstruction methods + % since the covariance is only used by some reconstruction methods and might not allways be present in the data + if Ntrials==1 + data.cov = eye(Nchans); + else + data.cov = zeros(Ntrials,Nchans,Nchans); + for i=1:Ntrials + data.cov(i,:,:) = eye(Nchans); + end + end + hascovariance = 0; + end + + if strcmp(cfg.method, 'pcc') + % HACK: requires some extra defaults + if ~isfield(cfg, 'refdip'), cfg.refdip = []; end + if ~isfield(cfg, 'supdip'), cfg.supdip = []; end + + % HACK: experimental code + if nargin>2 + error('not supported') + end + tmpcfg = []; + tmpcfg.channel = cfg.channel(:)'; + if isfield(cfg, 'refchan') + tmpcfg.channel = [tmpcfg.channel cfg.refchan(:)']; + end + if isfield(cfg, 'supchan') + tmpcfg.channel = [tmpcfg.channel cfg.supchan(:)']; + end + + % select the data in the channels of interest + [dum, datchanindx] = match_str(tmpcfg.channel, data.label); + if Ntrials==1 + data.avg = data.avg(datchanindx,:); + data.cov = data.cov(datchanindx,datchanindx); + else + data.avg = data.avg(datchanindx,:); + data.cov = data.cov(:,datchanindx,datchanindx); + data.trial = data.trial(:,datchanindx,:); + end + data.label = data.label(datchanindx); + + if isfield(cfg, 'refchan') && ~isempty(cfg.refchan) + [dum, refchanindx] = match_str(cfg.refchan, data.label); + else + refchanindx = []; + end + if isfield(cfg, 'supchan') && ~isempty(cfg.supchan) + [dum, supchanindx] = match_str(cfg.supchan, data.label); + else + supchanindx = []; + end + Nchans = length(tmpcfg.channel); % update the number of channels + + else + % HACK: use the default code + % select the channels of interest + [dum, datchanindx] = match_str(cfg.channel, data.label); + if strcmp(data.dimord, 'chan_time') + % It is in principle possible to have timelockanalysis with + % keeptrial=yes and only a single trial in the raw data. + % In that case the covariance should be represented as Nchan*Nchan + data.avg = data.avg(datchanindx,:); + data.cov = reshape(data.cov, length(datchanindx), length(datchanindx)); + data.cov = data.cov(datchanindx,datchanindx); + else + data.avg = data.avg(datchanindx,:); + data.cov = data.cov(:,datchanindx,datchanindx); + data.trial = data.trial(:,datchanindx,:); + end + data.label = data.label(datchanindx); + Nchans = length(data.label); + end + + if nargin>2 + % baseline and active are only available together for resampling purposes, + % hence I assume here that there are multiple trials in both + baseline.avg = baseline.avg(datchanindx,:); + baseline.cov = baseline.cov(:,datchanindx,datchanindx); + baseline.trial = baseline.trial(:,datchanindx,:); + % this is required for averaging 2 conditions using prepare_resampled_data + cfg2 = []; + cfg2.numcondition = 2; + end + + % prepare the resampling of the trials, or average the data if multiple trials are present and no resampling is neccessary + if (strcmp(cfg.jackknife, 'yes') || strcmp(cfg.bootstrap, 'yes') || strcmp(cfg.pseudovalue, 'yes') || strcmp(cfg.singletrial, 'yes') || strcmp(cfg.rawtrial, 'yes') || strcmp(cfg.randomization, 'yes')) && ~strcmp(data.dimord, 'rpt_chan_time') + error('multiple trials required in the data\n'); + + elseif strcmp(cfg.permutation, 'yes') + % compute the average and covariance without resampling + [dum, avgA, covA, avgB, covB] = prepare_resampled_data(cfg2 , data.trial, data.cov, baseline.trial, baseline.cov); + % compute the average and covariance with random permutation + [cfg, avRA, coRA, avRB, coRB] = prepare_resampled_data(cfg, data.trial, data.cov, baseline.trial, baseline.cov); + % concatenate the different resamplings + avg = cat(1, reshape(avgA, [1 Nchans Nsamples]), reshape(avgB, [1 Nchans Nsamples]), avRA, avRB); + Cy = cat(1, reshape(covA, [1 Nchans Nchans ]), reshape(covB, [1 Nchans Nchans ]), coRA, coRB); + % clear temporary working copies + clear avgA avgB covA covB + clear avRA avRB coRA coRB + % the order of the resamplings should be [avgA avgB randA randB randA randB randA randB ....] + Nrepetitions = 2*cfg.numpermutation + 2; + order = [1 2 3:2:Nrepetitions 4:2:Nrepetitions]; + avg = avg(order,:,:); + Cy = Cy (order,:,:); + + elseif strcmp(cfg.randomization, 'yes') + % compute the average and covariance without resampling + [dum, avgA, covA, avgB, covB] = prepare_resampled_data(cfg2 , data.trial, data.cov, baseline.trial, baseline.cov); + % compute the average and covariance with random resampling + [cfg, avRA, coRA, avRB, coRB] = prepare_resampled_data(cfg, data.trial, data.cov, baseline.trial, baseline.cov); + % concatenate the different resamplings + avg = cat(1, reshape(avgA, [1 Nchans Nsamples]), reshape(avgB, [1 Nchans Nsamples]), avRA, avRB); + Cy = cat(1, reshape(covA, [1 Nchans Nchans ]), reshape(covB, [1 Nchans Nchans ]), coRA, coRB); + % clear temporary working copies + clear avgA avgB covA covB + clear avRA avRB coRA coRB + % the order of the resamplings should be [avgA avgB randA randB randA randB randA randB ....] + Nrepetitions = 2*cfg.numrandomization + 2; + order = [1 2 3:2:Nrepetitions 4:2:Nrepetitions]; + avg = avg(order,:,:); + Cy = Cy (order,:,:); + + elseif strcmp(cfg.jackknife, 'yes') + % compute the jackknife repetitions for the average and covariance + [cfg, avg, Cy] = prepare_resampled_data(cfg, data.trial, data.cov); + Nrepetitions = Ntrials; + + elseif strcmp(cfg.bootstrap, 'yes') + % compute the bootstrap repetitions for the average and covariance + [cfg, avg, Cy] = prepare_resampled_data(cfg, data.trial, data.cov); + Nrepetitions = cfg.numbootstrap; + + elseif strcmp(cfg.pseudovalue, 'yes') + % compute the pseudovalue repetitions for the average and covariance + [cfg, avg, Cy] = prepare_resampled_data(cfg, data.trial, data.cov); + Nrepetitions = Ntrials+1; + + elseif strcmp(cfg.singletrial, 'yes') + % The idea is that beamformer uses the average covariance to construct the + % filter and applies it to the single trial covariance/csd. The problem + % is that beamformer will use the averaged covariance/csd to estimate the + % power and not the single trial covariance/csd + error('this option contains a bug, and is therefore not supported at the moment'); + % average the single-trial covariance matrices + Cy = mean(data.cov,1); + % copy the average covariance matrix for every individual trial + Cy = repmat(Cy, [Ntrials 1 1]); + % keep the single-trial ERFs, rename them to avg for convenience + avg = data.trial; + Nrepetitions = Ntrials; + + elseif strcmp(cfg.rawtrial, 'yes') + % do not do any resampling, keep the single-trial covariances + Cy = data.cov; + % do not do any resampling, keep the single-trial ERFs (rename them to avg for convenience) + avg = data.trial; + Nrepetitions = Ntrials; + + elseif Ntrials>1 + % average the single-trial covariance matrices + Cy = reshape(mean(data.cov,1), [Nchans Nchans]); + % select the average ERF + avg = data.avg; + Nrepetitions = 1; + + elseif Ntrials==1 + % select the average covariance matrix + Cy = data.cov; + % select the average ERF + avg = data.avg; + Nrepetitions = 1; + end + + % reshape so that it also looks like one trial (out of many) + if Nrepetitions==1 + Cy = reshape(Cy , [1 Nchans Nchans]); + avg = reshape(avg, [1 Nchans Nsamples]); + end + + % get the relevant low level options from the cfg and convert into key-value pairs + optarg = cfg2keyval(getfield(cfg, cfg.method)); + + if strcmp(cfg.method, 'lcmv') && ~isfield(grid, 'filter'), + for i=1:Nrepetitions + fprintf('scanning repetition %d\n', i); + dip(i) = beamformer_lcmv(grid, sens, vol, squeeze(avg(i,:,:)), squeeze(Cy(i,:,:)), optarg{:}); + end + elseif strcmp(cfg.method, 'lcmv') + %don't loop over repetitions (slow), but reshape the input data to obtain single trial timecourses efficiently + %in the presence of filters pre-computed on the average (or whatever) + siz = size(avg); + tmpdat = reshape(permute(avg,[2 3 1]),[siz(2) siz(3)*siz(1)]); + tmpdip = beamformer_lcmv(grid, sens, vol, tmpdat, squeeze(mean(Cy,1)), optarg{:}); + tmpmom = tmpdip.mom{tmpdip.inside(1)}; + sizmom = size(tmpmom); + for i=1:length(tmpdip.inside) + indx = tmpdip.inside(i); + tmpdip.mom{indx} = permute(reshape(tmpdip.mom{indx}, [sizmom(1) siz(3) siz(1)]), [3 1 2]); + end + try, tmpdip = rmfield(tmpdip, 'pow'); end + try, tmpdip = rmfield(tmpdip, 'cov'); end + try, tmpdip = rmfield(tmpdip, 'noise'); end + for i=1:Nrepetitions + dip(i).pos = tmpdip.pos; + dip(i).inside = tmpdip.inside; + dip(i).outside = tmpdip.outside; + dip(i).mom = cell(1,size(tmpdip.pos,1)); + for ii=1:length(tmpdip.inside) + indx = tmpdip.inside(ii); + dip(i).mom{indx} = reshape(tmpdip.mom{indx}(i,:,:),[sizmom(1) siz(3)]); + end + end + elseif strcmp(cfg.method, 'sam') + for i=1:Nrepetitions + fprintf('scanning repetition %d\n', i); + dip(i) = beamformer_sam(grid, sens, vol, squeeze(avg(i,:,:)), squeeze(Cy(i,:,:)), optarg{:}); + end + elseif strcmp(cfg.method, 'pcc') + for i=1:Nrepetitions + fprintf('scanning repetition %d\n', i); + dip(i) = beamformer_pcc(grid, sens, vol, squeeze(avg(i,:,:)), squeeze(Cy(i,:,:)), optarg{:}, 'refdip', cfg.refdip, 'refchan', refchanindx, 'supchan', supchanindx); + end + elseif strcmp(cfg.method, 'mne') + for i=1:Nrepetitions + fprintf('estimating current density distribution for repetition %d\n', i); + dip(i) = minimumnormestimate(grid, sens, vol, squeeze(avg(i,:,:)), optarg{:}); + end + elseif strcmp(cfg.method, 'loreta') + for i=1:Nrepetitions + fprintf('estimating LORETA current density distribution for repetition %d\n', i); + dip(i) = loreta( grid, sens, vol, squeeze(avg(i,:,:)), optarg{:}); + end + elseif strcmp(cfg.method, 'rv') + for i=1:Nrepetitions + fprintf('estimating residual variance at each grid point for repetition %d\n', i); + dip(i) = residualvariance( grid, sens, vol, squeeze(avg(i,:,:)), optarg{:}); + end + elseif strcmp(cfg.method, 'music') + for i=1:Nrepetitions + fprintf('computing multiple signal classification for repetition %d\n', i); + if hascovariance + dip(i) = music(grid, sens, vol, squeeze(avg(i,:,:)), 'cov', squeeze(Cy(i,:,:)), optarg{:}); + else + dip(i) = music(grid, sens, vol, squeeze(avg(i,:,:)), optarg{:}); + end + end + elseif strcmp(cfg.method, 'mvl') + for i=1:Nrepetitions + fprintf('estimating current density distribution for repetition %d\n', i); + fns = fieldnames(cfg); + optarg = cell(1,length(fns)); + n=1; + for c=1:length(fns) + optarg{n} = fns{c}; + optarg{n+1} = cfg.(fns{c}); + n=n+2; + end + dip(i) = mvlestimate(grid, sens, vol, squeeze(avg(i,:,:)), optarg{:}); + end + else + error(sprintf('method ''%s'' is unsupported for source reconstruction in the time domain', cfg.method)); + end + +end % if freq or timelock data + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% clean up and collect the results +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +if isfield(grid, 'xgrid') + % the dipoles are placed on a regular grid that is aligned with the carthesian axes + % copy the description of the grid axes + source.xgrid = grid.xgrid; + source.ygrid = grid.ygrid; + source.zgrid = grid.zgrid; + source.dim = [length(source.xgrid) length(source.ygrid) length(source.zgrid)]; +else + source.dim = [size(grid.pos,1) 1]; +end + +source.vol = vol; +if exist('grad', 'var') + source.grad = grad; +elseif exist('elec', 'var') + source.elec = elec; +end + +if istimelock + % add the time axis to the output + source.time = data.time; +elseif iscomp + % FIXME, add the component numbers to the output +elseif isfreq + % add the frequency axis to the output + cfg.frequency = data.freq(nearest(data.freq, cfg.frequency)); + source.frequency = cfg.frequency; + if isfield(data, 'time') && isfield(cfg, 'latency') + cfg.latency = data.time(nearest(data.time, cfg.latency)); + source.latency = cfg.latency; + end + if isfield(data, 'cumtapcnt'), + source.cumtapcnt = data.cumtapcnt; + end +end + +if exist('dip', 'var') + % do some cleaning up, keep the dipole positions etc. in the global structure and not in each trial + source.pos = dip(1).pos; + source.inside = dip(1).inside; + source.outside = dip(1).outside; + dip = rmfield(dip, 'pos'); + dip = rmfield(dip, 'inside'); + dip = rmfield(dip, 'outside'); + if isfield(dip(1), 'leadfield') + source.leadfield = dip(1).leadfield; + dip = rmfield(dip, 'leadfield'); + end +elseif exist('grid', 'var') + % no scanning has been done, probably only the leadfield has been computed + try, source.pos = grid.pos; end + try, source.inside = grid.inside; end + try, source.outside = grid.outside; end + try, source.leadfield = grid.leadfield; end +end + +if strcmp(cfg.keepleadfield, 'yes') && ~isfield(source, 'leadfield') + % add the precomputed leadfields to the output source + source.leadfield = grid.leadfield; +elseif strcmp(cfg.keepleadfield, 'no') && isfield(source, 'leadfield') + % remove the precomputed leadfields from the output source + source = rmfield(source, 'leadfield'); +end + + +% remove the precomputed leadfields from the cfg regardless of what keepleadfield is saying +% it should not be kept in cfg, since there it takes up too much space +if isfield(cfg, 'grid') && isfield(cfg.grid, 'leadfield') + cfg.grid = rmfield(cfg.grid, 'leadfield'); +end + +if convertfreq + % FIXME, convert the source reconstruction back to a frequency representation +elseif convertcomp + % FIXME, convert the source reconstruction back to a component representation +end + +if strcmp(cfg.jackknife, 'yes') + source.method = 'jackknife'; + source.trial = dip; + source.df = Ntrials; +elseif strcmp(cfg.bootstrap, 'yes') + source.method = 'bootstrap'; + source.trial = dip; + source.df = Ntrials; +elseif strcmp(cfg.pseudovalue, 'yes') + source.method = 'pseudovalue'; + source.trial = dip; +elseif strcmp(cfg.singletrial, 'yes') + source.method = 'singletrial'; + source.trial = dip; + source.df = Ntrials; % is this correct? +elseif strcmp(cfg.rawtrial, 'yes') + source.method = 'rawtrial'; + source.trial = dip; + source.df = Ntrials; % is this correct? +elseif strcmp(cfg.randomization, 'yes') + % assign the randomized resamplings to the output, keeping the special meaning of trial 1 and 2 in mind + source.method = 'randomization'; + source.avgA = dip(1); + source.avgB = dip(2); + source.trialA = dip(1+2*(1:cfg.numrandomization)); + source.trialB = dip(2+2*(1:cfg.numrandomization)); +elseif strcmp(cfg.permutation, 'yes') + % assign the randomized resamplings to the output, keeping the special meaning of trial 1 and 2 in mind + source.method = 'permutation'; + source.avgA = dip(1); + source.avgB = dip(2); + source.trialA = dip(1+2*(1:cfg.numpermutation)); + source.trialB = dip(2+2*(1:cfg.numpermutation)); +elseif exist('dip', 'var') + % it looks like beamformer analysis was done on an average input, keep the average source reconstruction + source.method = 'average'; + source.avg = dip; +else + % apparently no computations were performed +end + +if (strcmp(cfg.jackknife, 'yes') || strcmp(cfg.bootstrap, 'yes') || strcmp(cfg.pseudovalue, 'yes') || strcmp(cfg.singletrial, 'yes') || strcmp(cfg.rawtrial, 'yes')) && strcmp(cfg.keeptrials, 'yes') + % keep the source reconstruction for each repeated or resampled trial + source.trial = dip; +end + +% accessing this field here is needed for the configuration tracking +% by accessing it once, it will not be removed from the output cfg +cfg.outputfile; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_sourceanalysis.m 1258 2010-06-22 08:33:48Z timeng $'; +% remember the configuration details of the input data +if nargin==2 + try, cfg.previous = data.cfg; end +elseif nargin==3 + cfg.previous = []; + try, cfg.previous{1} = data.cfg; end + try, cfg.previous{2} = baseline.cfg; end +end +% remember the exact configuration details in the output +source.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', source); % use the variable name "data" in the output file +end + +fprintf('total time in sourceanalysis %.1f seconds\n', toc); -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_sourcedescriptives.m b/external/fieldtrip/ft_sourcedescriptives.m index b84b9b2..e5dc2da 100644 --- a/external/fieldtrip/ft_sourcedescriptives.m +++ b/external/fieldtrip/ft_sourcedescriptives.m @@ -1,11 +1,928 @@ -function varargout = funname(varargin); +function [source] = ft_sourcedescriptives(cfg, source) -% this is a SPM wrapper around a FieldTrip function +% FT_SOURCEDESCRIPTIVES computes descriptive parameters of the beamformer source +% analysis results. +% +% Use as: +% [source] = ft_sourcedescriptives(cfg, source) +% +% where cfg is a structure with the configuration details and source is the +% result from a beamformer source estimation. The configuration can contain +% cfg.cohmethod = 'regular', 'lambda1', 'canonical' +% cfg.powmethod = 'regular', 'lambda1', 'trace', 'none' +% cfg.supmethod = string +% cfg.projectmom = 'yes' or 'no' (default = 'no') +% cfg.eta = 'yes' or 'no' (default = 'no') +% cfg.kurtosis = 'yes' or 'no' (default = 'no') +% cfg.keeptrials = 'yes' or 'no' (default = 'no') +% cfg.resolutionmatrix = 'yes' or 'no' (default = 'no') +% cfg.feedback = 'no', 'text', 'textbar', 'gui' (default = 'text') +% +% The following option only applies to LCMV single-trial timecourses. +% cfg.fixedori = 'within_trials' or 'over_trials' (default = 'over_trials') +% +% You can apply a custom mathematical transformation such as a log-transform +% on the estimated power using +% cfg.transform = string describing the transformation (default is []) +% The nai, i.e. neural activity index (power divided by projected noise), +% is computed prior to applying the optional transformation. Subsequently, +% the transformation is applied on the power and on the projected noise +% using "feval". A usefull transformation is for example 'log' or 'log10'. +% +% If repeated trials are present that have undergone some sort of +% resampling (i.e. jackknife, bootstrap, singletrial or rawtrial), the mean, +% variance and standard error of mean will be computed for all source +% parameters. This is done after applying the optional transformation +% on the power and projected noise. +% +% See also FT_SOURCEANALYSIS, FT_SOURCESTATISTICS +% +% Undocumented local options: +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk +% +% Copyright (C) 2004-2007, Robert Oostenveld & Jan-Mathijs Schoffelen +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_sourcedescriptives.m 1247 2010-06-17 12:07:18Z timeng $ -% this part is variable -prefix = 'ft_'; +fieldtripdefs -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +% set the defaults +if ~isfield(cfg, 'transform'), cfg.transform = []; end +if ~isfield(cfg, 'projectmom'), cfg.projectmom = 'no'; end % if yes -> svdfft +if ~isfield(cfg, 'numcomp'), cfg.numcomp = 1; end +if ~isfield(cfg, 'powmethod'), cfg.powmethod = []; end % see below +if ~isfield(cfg, 'cohmethod'), cfg.cohmethod = []; end % see below +if ~isfield(cfg, 'feedback'), cfg.feedback = 'textbar'; end +if ~isfield(cfg, 'supmethod'), cfg.supmethod = 'none'; end +if ~isfield(cfg, 'resolutionmatrix'), cfg.resolutionmatrix = 'no'; end +if ~isfield(cfg, 'eta'), cfg.eta = 'no'; end +if ~isfield(cfg, 'fa'), cfg.fa = 'no'; end +if ~isfield(cfg, 'kurtosis'), cfg.kurtosis = 'no'; end +if ~isfield(cfg, 'keeptrials'), cfg.keeptrials = 'no'; end +if ~isfield(cfg, 'keepcsd'), cfg.keepcsd = 'no'; end +if ~isfield(cfg, 'fixedori'), cfg.fixedori = 'over_trials'; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + end +end + +% check if the input data is valid for this function +source = checkdata(source, 'datatype', 'source', 'feedback', 'yes'); + +% this is required for backward compatibility with the old sourceanalysis +if isfield(source, 'method') && strcmp(source.method, 'randomized') + source.method = 'randomization'; +elseif isfield(source, 'method') && strcmp(source.method, 'permuted') + source.method = 'permutation'; +elseif isfield(source, 'method') && strcmp(source.method, 'jacknife') + source.method = 'jackknife'; +end + +% determine the type of data, this is only relevant for a few specific types +ispccdata = isfield(source, 'avg') && isfield(source.avg, 'csdlabel'); +islcmvavg = isfield(source, 'avg') && isfield(source, 'time') && isfield(source.avg, 'mom'); +islcmvtrl = isfield(source, 'trial') && isfield(source, 'time') && isfield(source.trial, 'mom'); + +% check the consistency of the defaults +if strcmp(cfg.projectmom, 'yes') + if isempty(cfg.powmethod) + cfg.powmethod = 'regular'; % set the default + elseif ~strcmp(cfg.powmethod, 'regular') + error('unsupported powmethod in combination with projectmom'); + end + if isempty(cfg.cohmethod) + cfg.cohmethod = 'regular';% set the default + elseif ~strcmp(cfg.cohmethod, 'regular') + error('unsupported cohmethod in combination with projectmom'); + end +else + if isempty(cfg.powmethod) + cfg.powmethod = 'lambda1'; % set the default + end + if isempty(cfg.cohmethod) + cfg.cohmethod = 'lambda1'; % set the default + end +end + +% this is required for backward compatibility with an old version of sourcedescriptives +if isfield(cfg, 'singletrial'), cfg.keeptrials = cfg.singletrial; end + +% do a validity check on the input data and specified options +if strcmp(cfg.resolutionmatrix, 'yes') + if ~isfield(source.avg, 'filter') + error('The computation of the resolution matrix requires keepfilter=''yes'' in sourceanalysis.'); + elseif ~isfield(source, 'leadfield') + error('The computation of the resolution matrix requires keepleadfield=''yes'' in sourceanalysis.'); + end +end + +if strcmp(cfg.eta, 'yes') && strcmp(cfg.cohmethod, 'svdfft'), + error('eta cannot be computed in combination with the application of svdfft'); +end + +if strcmp(cfg.keeptrials, 'yes') && ~strcmp(cfg.supmethod, 'none'), + error('you cannot keep trials when you want to partialize something'); +end + +% set some flags for convenience +isnoise = isfield(source, 'avg') && isfield(source.avg, 'noisecsd'); +keeptrials = strcmp(cfg.keeptrials, 'yes'); +projectmom = strcmp(cfg.projectmom, 'yes'); + +% determine the subfunction used for computing power +switch cfg.powmethod + case 'regular' + powmethodfun = @powmethod_regular; + case 'lambda1' + powmethodfun = @powmethod_lambda1; + case 'trace' + powmethodfun = @powmethod_trace; + case 'none' + powmethodfun = []; + otherwise + error('unsupported powmethod'); +end + +if ispccdata + % the source reconstruction was computed using the pcc beamformer + Ndipole = length(source.inside) + length(source.outside); + dipsel = match_str(source.avg.csdlabel, 'scandip'); + refchansel = match_str(source.avg.csdlabel, 'refchan'); + refdipsel = match_str(source.avg.csdlabel, 'refdip'); + supchansel = match_str(source.avg.csdlabel, 'supchan'); + supdipsel = match_str(source.avg.csdlabel, 'supdip'); + + % cannot handle reference channels and reference dipoles simultaneously + if length(refchansel)>0 && length(refdipsel)>0 + error('cannot simultaneously handle reference channels and reference dipole'); + end + + % these are only used to count the number of reference/suppression dipoles and channels + refsel = [refdipsel refchansel]; + supsel = [supdipsel supchansel]; + + if projectmom + source.avg.ori = cell(1, Ndipole); + progress('init', cfg.feedback, 'projecting dipole moment'); + for diplop=1:length(source.inside) + progress(diplop/length(source.inside), 'projecting dipole moment %d/%d\n', diplop, length(source.inside)); + i = source.inside(diplop); + mom = source.avg.mom{i}(dipsel, :); + ref = source.avg.mom{i}(refdipsel, :); + sup = source.avg.mom{i}(supdipsel, :); + refchan = source.avg.mom{i}(refchansel, :); + supchan = source.avg.mom{i}(supchansel, :); + % compute the projection of the scanning dipole along the direction of the dominant amplitude + if length(dipsel)>1, [mom, rmom] = svdfft(mom, cfg.numcomp, source.cumtapcnt); else rmom = []; end + source.avg.ori{source.inside(diplop)} = rmom; + % compute the projection of the reference dipole along the direction of the dominant amplitude + if length(refdipsel)>1, [ref, rref] = svdfft(ref, 1, source.cumtapcnt); else rref = []; end + % compute the projection of the supression dipole along the direction of the dominant amplitude + if length(supdipsel)>1, [sup, rsup] = svdfft(sup, 1, source.cumtapcnt); else rsup = []; end + + % compute voxel-level fourier-matrix + source.avg.mom{i} = cat(1, mom, ref, sup, refchan, supchan); + + % create rotation-matrix + rotmat = zeros(0, length(source.avg.csdlabel)); + if ~isempty(rmom), + rotmat = [rotmat; rmom zeros(1,length([refsel(:);supsel(:)]))]; + end + if ~isempty(rref), + rotmat = [rotmat; zeros(1, length([dipsel])), rref, zeros(1,length([refchansel(:);supsel(:)]))]; + end + if ~isempty(rsup), + rotmat = [rotmat; zeros(1, length([dipsel(:);refdipsel(:)])), rsup, zeros(1,length([refchansel(:);supchansel(:)]))]; + end + for j=1:length(supchansel) + rotmat(end+1,:) = 0; + rotmat(end,length([dipsel(:);refdipsel(:);supdipsel(:)])+j) = 1; + end + for j=1:length(refchansel) + rotmat(end+1,:) = 0; + rotmat(end,length([dipsel(:);refdipsel(:);supdipsel(:);supchansel(:)])+j) = 1; + end + + % compute voxel-level csd-matrix + source.avg.csd{i} = rotmat * source.avg.csd{i} * rotmat'; + % compute voxel-level noisecsd-matrix + if isfield(source.avg, 'noisecsd'), source.avg.noisecsd{i} = rotmat * source.avg.noisecsd{i} * rotmat'; end + % compute rotated filter + if isfield(source.avg, 'filter'), source.avg.filter{i} = rotmat * source.avg.filter{i}; end + % compute rotated leadfield + % FIXME in the presence of a refdip and/or supdip, this does not work; leadfield is Nx3 + if isfield(source, 'leadfield'), + %FIXME this is a proposed dirty fix + n1 = size(source.leadfield{i},2); + %n2 = size(rotmat,2) - n1; + n2 = size(rotmat,2) - n1 +1; %added 1 JM + source.leadfield{i} = source.leadfield{i} * rotmat(1:n2, 1:n1)'; + end + end %for diplop + progress('close'); + + % remember what the interpretation is of all CSD output components + scandiplabel = repmat({'scandip'}, 1, cfg.numcomp); % only one dipole orientation remains + refdiplabel = repmat({'refdip'}, 1, length(refdipsel)>0); % for svdfft at max. only one dipole orientation remains + supdiplabel = repmat({'supdip'}, 1, length(supdipsel)>0); % for svdfft at max. only one dipole orientation remains + refchanlabel = repmat({'refchan'}, 1, length(refchansel)); + supchanlabel = repmat({'supchan'}, 1, length(supchansel)); + % concatenate all the labels + source.avg.csdlabel = cat(2, scandiplabel, refdiplabel, supdiplabel, refchanlabel, supchanlabel); + % update the indices + dipsel = match_str(source.avg.csdlabel, 'scandip'); + refchansel = match_str(source.avg.csdlabel, 'refchan'); + refdipsel = match_str(source.avg.csdlabel, 'refdip'); + supchansel = match_str(source.avg.csdlabel, 'supchan'); + supdipsel = match_str(source.avg.csdlabel, 'supdip'); + refsel = [refdipsel refchansel]; + supsel = [supdipsel supchansel]; + end % if projectmom + + if keeptrials + cumtapcnt = source.cumtapcnt(:); + sumtapcnt = cumsum([0;cumtapcnt]); + Ntrial = length(cumtapcnt); + + progress('init', cfg.feedback, 'computing singletrial voxel-level cross-spectral densities'); + for triallop = 1:Ntrial + source.trial(triallop).csd = cell(Ndipole, 1); % allocate memory for this trial + source.trial(triallop).mom = cell(Ndipole, 1); % allocate memory for this trial + + progress(triallop/Ntrial, 'computing singletrial voxel-level cross-spectral densities %d%d\n', triallop, Ntrial); + for diplop=1:length(source.inside) + i = source.inside(diplop); + dat = source.avg.mom{i}; + tmpmom = dat(:, sumtapcnt(triallop)+1:sumtapcnt(triallop+1)); + tmpcsd = [tmpmom * tmpmom'] ./cumtapcnt(triallop); + source.trial(triallop).mom{i} = tmpmom; + source.trial(triallop).csd{i} = tmpcsd; + end %for diplop + end % for triallop + progress('close'); + % remove the average, continue with separate trials + source = rmfield(source, 'avg'); + else + fprintf('using average voxel-level cross-spectral densities\n'); + end % if keeptrials + + hasrefdip = ~isempty(refdipsel); + hasrefchan = ~isempty(refchansel); + hassupdip = ~isempty(supdipsel); + hassupchan = ~isempty(supchansel); + + if keeptrials + % do the processing of the CSD matrices for each trial + if ~strcmp(cfg.supmethod, 'none') + error('suppression is only supported for average CSD'); + end + dipselcell = mat2cell(repmat(dipsel(:)', [Ndipole 1]), ones(Ndipole,1), length(dipsel)); + if hasrefdip, refdipselcell = mat2cell(repmat(refdipsel(:)', [Ndipole 1]), ones(Ndipole,1), length(refdipsel)); end + if hasrefchan, refchanselcell = mat2cell(repmat(refchansel(:)', [Ndipole 1]), ones(Ndipole,1), length(refchansel)); end + if hassupdip, supdipselcell = mat2cell(repmat(supdipsel(:)', [Ndipole 1]), ones(Ndipole,1), length(supdipsel)); end + if hassupchan, supchanselcell = mat2cell(repmat(supchansel(:)', [Ndipole 1]), ones(Ndipole,1), length(supchansel)); end + + progress('init', cfg.feedback, 'computing singletrial voxel-level power'); + for triallop = 1:Ntrial + %initialize the variables + source.trial(triallop).pow = zeros(Ndipole, 1); + if hasrefdip, source.trial(triallop).refdippow = zeros(Ndipole, 1); end + if hasrefchan, source.trial(triallop).refchanpow = zeros(Ndipole, 1); end + if hassupdip, source.trial(triallop).supdippow = zeros(Ndipole, 1); end + if hassupchan, source.trial(triallop).supchanpow = zeros(Ndipole, 1); end + + progress(triallop/Ntrial, 'computing singletrial voxel-level power %d%d\n', triallop, Ntrial); + source.trial(triallop).pow(source.inside) = cellfun(powmethodfun, source.trial(triallop).csd(source.inside), dipselcell(source.inside)); + if hasrefdip, source.trial(triallop).refdippow(source.inside) = cellfun(powmethodfun,source.trial(triallop).csd(source.inside), refdipselcell(source.inside)); end + if hassupdip, source.trial(triallop).supdippow(source.inside) = cellfun(powmethodfun,source.trial(triallop).csd(source.inside), supdipselcell(source.inside)); end + if hasrefchan, source.trial(triallop).refchanpow(source.inside) = cellfun(powmethodfun,source.trial(triallop).csd(source.inside), refchanselcell(source.inside)); end + if hassupchan, source.trial(triallop).supchanpow(source.inside) = cellfun(powmethodfun,source.trial(triallop).csd(source.inside), supchanselcell(source.inside)); end + %FIXME kan volgens mij niet + if isnoise && isfield(source.trial(triallop), 'noisecsd'), + % compute the power of the noise projected on each source component + source.trial(triallop).noise = cellfun(powmethodfun,source.trial(triallop).csd, dipselcell); + if hasrefdip, source.trial(triallop).refdipnoise = cellfun(powmethodfun,source.trial(triallop).noisecsd, refdipselcell); end + if hassupdip, source.trial(triallop).supdipnoise = cellfun(powmethodfun,source.trial(triallop).noisecsd, supdipselcell); end + if hasrefchan, source.trial(triallop).refchannoise = cellfun(powmethodfun,source.trial(triallop).noisecsd, refchanselcell); end + if hassupchan, source.trial(triallop).supchannoise = cellfun(powmethodfun,source.trial(triallop).noisecsd, supchanselcell); end + end % if isnoise + end % for triallop + progress('close'); + + if strcmp(cfg.keepcsd, 'no') + source.trial = rmfield(source.trial, 'csd'); + end + else + % do the processing of the average CSD matrix + for diplop = 1:length(source.inside) + i = source.inside(diplop); + switch cfg.supmethod + case 'chan_dip' + supindx = [supdipsel supchansel]; + if diplop==1, refsel = refsel - length(supdipsel); end%adjust index only once + case 'chan' + supindx = [supchansel]; + case 'dip' + supindx = [supdipsel]; + if diplop==1, refsel = refsel - length(supdipsel); end + case 'none' + % do nothing + supindx = []; + end + tmpcsd = source.avg.csd{i}; + scnindx = setdiff(1:size(tmpcsd,1), supindx); + tmpcsd = tmpcsd(scnindx, scnindx) - [tmpcsd(scnindx, supindx)*pinv(tmpcsd(supindx, supindx))*tmpcsd(supindx, scnindx)]; + source.avg.csd{i} = tmpcsd; + end % for diplop + source.avg.csdlabel = source.avg.csdlabel(scnindx); + + if isnoise && ~strcmp(cfg.supmethod, 'none') + source.avg = rmfield(source.avg, 'noisecsd'); + end + + % initialize the variables + source.avg.pow = nan*zeros(Ndipole, 1); + if ~isempty(refdipsel), source.avg.refdippow = nan*zeros(Ndipole, 1); end + if ~isempty(refchansel), source.avg.refchanpow = nan*zeros(Ndipole, 1); end + if ~isempty(supdipsel), source.avg.supdippow = nan*zeros(Ndipole, 1); end + if ~isempty(supchansel), source.avg.supchanpow = nan*zeros(Ndipole, 1); end + if isnoise + source.avg.noise = nan*zeros(Ndipole, 1); + if ~isempty(refdipsel), source.avg.refdipnoise = nan*zeros(Ndipole, 1); end + if ~isempty(refchansel), source.avg.refchannoise = nan*zeros(Ndipole, 1); end + if ~isempty(supdipsel), source.avg.supdipnoise = nan*zeros(Ndipole, 1); end + if ~isempty(supchansel), source.avg.supchannoise = nan*zeros(Ndipole, 1); end + end % if isnoise + if ~isempty(refsel), source.avg.coh = nan*zeros(Ndipole, 1); end + if strcmp(cfg.eta, 'yes'), + source.avg.eta = nan*zeros(Ndipole, 1); + source.avg.ori = cell(1, Ndipole); + end + if strcmp(cfg.eta, 'yes') && ~isempty(refsel), + source.avg.etacsd = nan*zeros(Ndipole, 1); + source.avg.ucsd = cell(1, Ndipole); + end + if strcmp(cfg.fa, 'yes'), + source.avg.fa = nan*zeros(Ndipole, 1); + end + + for diplop = 1:length(source.inside) + i = source.inside(diplop); + + % compute the power of each source component + if strcmp(cfg.projectmom, 'yes') && cfg.numcomp>1, + source.avg.pow(i) = powmethodfun(source.avg.csd{i}(dipsel,dipsel), 1); + else + source.avg.pow(i) = powmethodfun(source.avg.csd{i}(dipsel,dipsel)); + end + if ~isempty(refdipsel), source.avg.refdippow(i) = powmethodfun(source.avg.csd{i}(refdipsel,refdipsel)); end + if ~isempty(supdipsel), source.avg.supdippow(i) = powmethodfun(source.avg.csd{i}(supdipsel,supdipsel)); end + if ~isempty(refchansel), source.avg.refchanpow(i) = powmethodfun(source.avg.csd{i}(refchansel,refchansel)); end + if ~isempty(supchansel), source.avg.supchanpow(i) = powmethodfun(source.avg.csd{i}(supchansel,supchansel)); end + if isnoise + % compute the power of the noise projected on each source component + if strcmp(cfg.projectmom, 'yes') && cfg.numcomp>1, + source.avg.noise(i) = powmethodfun(source.avg.noisecsd{i}(dipsel,dipsel), 1); + else + source.avg.noise(i) = powmethodfun(source.avg.noisecsd{i}(dipsel,dipsel)); + end + if ~isempty(refdipsel), source.avg.refdipnoise(i) = powmethodfun(source.avg.noisecsd{i}(refdipsel,refdipsel)); end + if ~isempty(supdipsel), source.avg.supdipnoise(i) = powmethodfun(source.avg.noisecsd{i}(supdipsel,supdipsel)); end + if ~isempty(refchansel), source.avg.refchannoise(i) = powmethodfun(source.avg.noisecsd{i}(refchansel,refchansel)); end + if ~isempty(supchansel), source.avg.supchannoise(i) = powmethodfun(source.avg.noisecsd{i}(supchansel,supchansel)); end + end % if isnoise + + if ~isempty(refsel) + % compute coherence + csd = source.avg.csd{i}; + switch cfg.cohmethod + case 'regular' + % assume that all dipoles have been projected along the direction of maximum power + Pd = abs(csd(dipsel, dipsel)); + Pr = abs(csd(refsel, refsel)); + Cdr = csd(dipsel, refsel); + source.avg.coh(i) = (Cdr.^2) ./ (Pd*Pr); + case 'lambda1' + %compute coherence on Joachim Gross' way + Pd = lambda1(csd(dipsel, dipsel)); + Pr = lambda1(csd(refsel, refsel)); + Cdr = lambda1(csd(dipsel, refsel)); + source.avg.coh(i) = abs(Cdr).^2 ./ (Pd*Pr); + case 'canonical' + [ccoh, c2, v1, v2] = cancorr(csd, dipsel, refsel); + [cmax, indmax] = max(ccoh); + source.avg.coh(i) = ccoh(indmax); + otherwise + error('unsupported cohmethod'); + end % cohmethod + end + + % compute eta + if strcmp(cfg.eta, 'yes') + [source.avg.eta(i), source.avg.ori{i}] = csd2eta(source.avg.csd{i}(dipsel,dipsel)); + if ~isempty(refsel), + %FIXME this only makes sense when only a reference signal OR a dipole is selected + [source.avg.etacsd(i), source.avg.ucsd{i}] = csd2eta(source.avg.csd{i}(dipsel,refsel)); + end + end + + %compute fa + if strcmp(cfg.fa, 'yes') + source.avg.fa(i) = csd2fa(source.avg.csd{i}(dipsel,dipsel)); + end + end % for diplop + + if strcmp(cfg.keepcsd, 'no') + source.avg = rmfield(source.avg, 'csd'); + end + if strcmp(cfg.keepcsd, 'no') && isnoise + source.avg = rmfield(source.avg, 'noisecsd'); + end + end + +elseif islcmvavg + % the source reconstruction was computed using the lcmv beamformer and contains an average timecourse + + if projectmom + progress('init', cfg.feedback, 'projecting dipole moment'); + for diplop=1:length(source.inside) + progress(diplop/length(source.inside), 'projecting dipole moment %d/%d\n', diplop, length(source.inside)); + mom = source.avg.mom{source.inside(diplop)}; + [mom, rmom] = svdfft(mom, 1); + source.avg.mom{source.inside(diplop)} = mom; + source.avg.ori{source.inside(diplop)} = rmom; + end + progress('close'); + end + + if ~strcmp(cfg.powmethod, 'none') + fprintf('recomputing power based on dipole timecourse\n') + source.avg.pow = nan*zeros(size(source.pos,1),1); + for diplop=1:length(source.inside) + mom = source.avg.mom{source.inside(diplop)}; + cov = mom * mom'; + source.avg.pow(source.inside(diplop)) = powmethodfun(cov); + end + end + + if strcmp(cfg.kurtosis, 'yes') + fprintf('computing kurtosis based on dipole timecourse\n'); + source.avg.k2 = nan*zeros(size(source.pos,1),1); + for diplop=1:length(source.inside) + mom = source.avg.mom{source.inside(diplop)}; + if length(mom)~=prod(size(mom)) + error('kurtosis can only be computed for projected dipole moment'); + end + source.avg.k2(source.inside(diplop)) = kurtosis(mom); + end + end + +elseif islcmvtrl + % the source reconstruction was computed using the lcmv beamformer and contains a single-trial timecourse + ntrial = length(source.trial); + + if projectmom && strcmp(cfg.fixedori, 'within_trials') + % the dipole orientation is re-determined for each trial + progress('init', cfg.feedback, 'projecting dipole moment'); + for trllop=1:ntrial + progress(trllop/ntrial, 'projecting dipole moment %d/%d\n', trllop, ntrial); + for diplop=1:length(source.inside) + mom = source.trial(trllop).mom{source.inside(diplop)}; + [mom, rmom] = svdfft(mom, 1); + source.trial(trllop).mom{source.inside(diplop)} = mom; + source.trial(trllop).ori{source.inside(diplop)} = rmom; % remember the orientation + end + end + progress('close'); + elseif projectmom && strcmp(cfg.fixedori, 'over_trials') + progress('init', cfg.feedback, 'projecting dipole moment'); + % compute average covariance over all trials + for trllop=1:ntrial + for diplop=1:length(source.inside) + mom = source.trial(trllop).mom{source.inside(diplop)}; + if trllop==1 + cov{diplop} = mom*mom'./size(mom,2); + else + cov{diplop} = mom*mom'./size(mom,2) + cov{diplop}; + end + end + end + % compute source orientation over all trials + for diplop=1:length(source.inside) + [dum, ori{diplop}] = svdfft(cov{diplop}, 1); + end + % project the data in each trial + for trllop=1:ntrial + progress(trllop/ntrial, 'projecting dipole moment %d/%d\n', trllop, ntrial); + for diplop=1:length(source.inside) + mom = source.trial(trllop).mom{source.inside(diplop)}; + mom = ori{diplop}*mom; + source.trial(trllop).mom{source.inside(diplop)} = mom; + source.trial(trllop).ori{source.inside(diplop)} = ori{diplop}; + end + end + progress('close'); + end + + if ~strcmp(cfg.powmethod, 'none') + fprintf('recomputing power based on dipole timecourse\n') + for trllop=1:ntrial + for diplop=1:length(source.inside) + mom = source.trial(trllop).mom{source.inside(diplop)}; + cov = mom * mom'; + source.trial(trllop).pow(source.inside(diplop)) = powmethodfun(cov); + end + end + end + + if strcmp(cfg.kurtosis, 'yes') + fprintf('computing kurtosis based on dipole timecourse\n'); + for trllop=1:ntrial + source.trial(trllop).k2 = nan*zeros(size(source.pos,1),1); + for diplop=1:length(source.inside) + mom = source.trial(trllop).mom{source.inside(diplop)}; + if length(mom)~=prod(size(mom)) + error('kurtosis can only be computed for projected dipole moment'); + end + source.trial(trllop).k2(source.inside(diplop)) = kurtosis(mom); + end + end + end + +end % dealing with pcc or lcmv input + +if isfield(source, 'avg') && isfield(source.avg, 'pow') && isfield(source.avg, 'noise') + % compute the neural activity index for the average + source.avg.nai = source.avg.pow(:) ./ source.avg.noise(:); +end + +if isfield(source, 'trial') && isfield(source.trial, 'pow') && isfield(source.trial, 'noise') + % compute the neural activity index for the trials + ntrials = length(source.trial); + for trlop=1:ntrials + source.trial(trlop).nai = source.trial(trlop).pow ./ source.trial(trlop).noise; + end +end + +if strcmp(source.method, 'randomization') || strcmp(source.method, 'permutation') + % compute the neural activity index for the two randomized conditions + source.avgA.nai = source.avgA.pow ./ source.avgA.noise; + source.avgB.nai = source.avgB.pow ./ source.avgB.noise; + for trlop=1:length(source.trialA) + source.trialA(trlop).nai = source.trialA(trlop).pow ./ source.trialA(trlop).noise; + end + for trlop=1:length(source.trialB) + source.trialB(trlop).nai = source.trialB(trlop).pow ./ source.trialB(trlop).noise; + end +end + +if ~isempty(cfg.transform) + fprintf('applying %s transformation on the power and projected noise\n', cfg.transform); + % apply the specified transformation on the power + if isfield(source, 'avg' ) && isfield(source.avg , 'pow'), source.avg .pow = feval(cfg.transform, source.avg .pow); end + if isfield(source, 'avgA' ) && isfield(source.avgA , 'pow'), source.avgA.pow = feval(cfg.transform, source.avgA.pow); end + if isfield(source, 'avgB' ) && isfield(source.avgB , 'pow'), source.avgB.pow = feval(cfg.transform, source.avgB.pow); end + if isfield(source, 'trial' ) && isfield(source.trial , 'pow'), for i=1:length(source.trial ), source.trial (i).pow = feval(cfg.transform, source.trial (i).pow); end; end + if isfield(source, 'trialA') && isfield(source.trialA, 'pow'), for i=1:length(source.trialA), source.trialA(i).pow = feval(cfg.transform, source.trialA(i).pow); end; end + if isfield(source, 'trialB') && isfield(source.trialB, 'pow'), for i=1:length(source.trialB), source.trialB(i).pow = feval(cfg.transform, source.trialB(i).pow); end; end + % apply the specified transformation on the projected noise + if isfield(source, 'avg' ) && isfield(source.avg , 'noise'), source.avg .noise = feval(cfg.transform, source.avg .noise); end + if isfield(source, 'avgA' ) && isfield(source.avgA , 'noise'), source.avgA.noise = feval(cfg.transform, source.avgA.noise); end + if isfield(source, 'avgB' ) && isfield(source.avgB , 'noise'), source.avgB.noise = feval(cfg.transform, source.avgB.noise); end + if isfield(source, 'trial' ) && isfield(source.trial , 'noise'), for i=1:length(source.trial ), source.trial (i).noise = feval(cfg.transform, source.trial (i).noise); end; end + if isfield(source, 'trialA') && isfield(source.trialA, 'noise'), for i=1:length(source.trialA), source.trialA(i).noise = feval(cfg.transform, source.trialA(i).noise); end; end + if isfield(source, 'trialB') && isfield(source.trialB, 'noise'), for i=1:length(source.trialB), source.trialB(i).noise = feval(cfg.transform, source.trialB(i).noise); end; end +end + +if strcmp(source.method, 'pseudovalue') + % compute the pseudovalues for the beamformer output + avg = source.trial(1); % the first is the complete average + Ntrials = length(source.trial)-1; % the remaining are the leave-one-out averages + pseudoval = []; + if isfield(source.trial, 'pow') + allavg = getfield(avg, 'pow'); + for i=1:Ntrials + thisavg = getfield(source.trial(i+1), 'pow'); + thisval = Ntrials*allavg - (Ntrials-1)*thisavg; + pseudoval(i).pow = thisval; + end + end + if isfield(source.trial, 'coh') + allavg = getfield(avg, 'coh'); + for i=1:Ntrials + thisavg = getfield(source.trial(i+1), 'coh'); + thisval = Ntrials*allavg - (Ntrials-1)*thisavg; + pseudoval(i).coh = thisval; + end + end + if isfield(source.trial, 'nai') + allavg = getfield(avg, 'nai'); + for i=1:Ntrials + thisavg = getfield(source.trial(i+1), 'nai'); + thisval = Ntrials*allavg - (Ntrials-1)*thisavg; + pseudoval(i).nai = thisval; + end + end + if isfield(source.trial, 'noise') + allavg = getfield(avg, 'noise'); + for i=1:Ntrials + thisavg = getfield(source.trial(i+1), 'noise'); + thisval = Ntrials*allavg - (Ntrials-1)*thisavg; + pseudoval(i).noise = thisval; + end + end + % store the pseudovalues instead of the original values + source.trial = pseudoval; +end + +if strcmp(source.method, 'jackknife') || strcmp(source.method, 'bootstrap') || strcmp(source.method, 'pseudovalue') || strcmp(source.method, 'singletrial') || strcmp(source.method, 'rawtrial') + % compute descriptive statistics (mean, var, sem) for multiple trial data + % compute these for as many source parameters as possible + + % for convenience copy the trials out of the source structure + dip = source.trial; + + % determine the (original) number of trials in the data + if strcmp(source.method, 'bootstrap') %VERANDERD ER ZAT GEEN .RESAMPLE IN SOURCE + Ntrials = size(source.trial,2);% WAS size(source.resample, 2); + else + Ntrials = length(source.trial); + end + fprintf('original data contained %d trials\n', Ntrials); + + % allocate memory for all elements in the dipole structure + sumdip = []; + if isfield(dip(1), 'var'), sumdip.var = zeros(size(dip(1).var )); sumdip.var(source.outside)=nan; end + if isfield(dip(1), 'pow'), sumdip.pow = zeros(size(dip(1).pow )); sumdip.pow(source.outside)=nan; end + if isfield(dip(1), 'coh'), sumdip.coh = zeros(size(dip(1).coh )); sumdip.coh(source.outside)=nan; end + if isfield(dip(1), 'rv'), sumdip.rv = zeros(size(dip(1).rv )); sumdip.rv(source.outside)=nan; end + if isfield(dip(1), 'noise'), sumdip.noise = zeros(size(dip(1).noise)); sumdip.noise(source.outside)=nan; end + if isfield(dip(1), 'nai'), sumdip.nai = zeros(size(dip(1).nai )); sumdip.nai(source.outside)=nan; end + sqrdip = []; + if isfield(dip(1), 'var'), sqrdip.var = zeros(size(dip(1).var )); sqrdip.var(source.outside)=nan; end + if isfield(dip(1), 'pow'), sqrdip.pow = zeros(size(dip(1).pow )); sqrdip.pow(source.outside)=nan; end + if isfield(dip(1), 'coh'), sqrdip.coh = zeros(size(dip(1).coh )); sqrdip.coh(source.outside)=nan; end + if isfield(dip(1), 'rv'), sqrdip.rv = zeros(size(dip(1).rv )); sqrdip.rv(source.outside)=nan; end + if isfield(dip(1), 'noise'), sqrdip.noise = zeros(size(dip(1).noise)); sqrdip.noise(source.outside)=nan; end + if isfield(dip(1), 'nai'), sqrdip.nai = zeros(size(dip(1).nai )); sqrdip.nai(source.outside)=nan; end + if isfield(dip(1), 'mom') + sumdip.mom = cell(size(dip(1).mom)); + sqrdip.mom = cell(size(dip(1).mom)); + for i=1:length(dip(1).mom) + sumdip.mom{i} = nan*zeros(size(dip(1).mom{i})); + sqrdip.mom{i} = nan*zeros(size(dip(1).mom{i})); + end + end + if isfield(dip(1), 'csd') + sumdip.csd = cell(size(dip(1).csd)); + sqrdip.csd = cell(size(dip(1).csd)); + for i=1:length(dip(1).csd) + sumdip.csd{i} = nan*zeros(size(dip(1).csd{i})); + sqrdip.csd{i} = nan*zeros(size(dip(1).csd{i})); + end + end + + for trial=1:length(dip) + % compute the sum of all values + if isfield(dip(trial), 'var'), sumdip.var = sumdip.var + dip(trial).var; end + if isfield(dip(trial), 'pow'), sumdip.pow = sumdip.pow + dip(trial).pow; end + if isfield(dip(trial), 'coh'), sumdip.coh = sumdip.coh + dip(trial).coh; end + if isfield(dip(trial), 'rv'), sumdip.rv = sumdip.rv + dip(trial).rv; end + if isfield(dip(trial), 'noise'), sumdip.noise = sumdip.noise + dip(trial).noise; end + if isfield(dip(trial), 'nai'), sumdip.nai = sumdip.nai + dip(trial).nai; end + % compute the sum of squared values + if isfield(dip(trial), 'var'), sqrdip.var = sqrdip.var + (dip(trial).var ).^2; end + if isfield(dip(trial), 'pow'), sqrdip.pow = sqrdip.pow + (dip(trial).pow ).^2; end + if isfield(dip(trial), 'coh'), sqrdip.coh = sqrdip.coh + (dip(trial).coh ).^2; end + if isfield(dip(trial), 'rv'), sqrdip.rv = sqrdip.rv + (dip(trial).rv ).^2; end + if isfield(dip(trial), 'noise'), sqrdip.noise = sqrdip.noise + (dip(trial).noise).^2; end + if isfield(dip(trial), 'nai'), sqrdip.nai = sqrdip.nai + (dip(trial).nai ).^2; end + % do the same for the cell array with mom + if isfield(dip(trial), 'mom') + for i=1:length(dip(1).mom) + sumdip.mom{i} = sumdip.mom{i} + dip(trial).mom{i}; + sqrdip.mom{i} = sqrdip.mom{i} + (dip(trial).mom{i}).^2; + end + end + % do the same for the cell array with csd + if isfield(dip(trial), 'csd') + for i=1:length(dip(1).csd) + sumdip.csd{i} = sumdip.csd{i} + dip(trial).csd{i}; + sqrdip.csd{i} = sqrdip.csd{i} + (dip(trial).csd{i}).^2; + end + end + end + + % compute the mean over all repetitions + if isfield(sumdip, 'var'), dipmean.var = sumdip.var / length(dip); end + if isfield(sumdip, 'pow'), dipmean.pow = sumdip.pow / length(dip); end + if isfield(sumdip, 'coh'), dipmean.coh = sumdip.coh / length(dip); end + if isfield(sumdip, 'rv'), dipmean.rv = sumdip.rv / length(dip); end + if isfield(sumdip, 'noise'), dipmean.noise = sumdip.noise / length(dip); end + if isfield(sumdip, 'nai'), dipmean.nai = sumdip.nai / length(dip); end + % for the cell array with mom, this is done further below + % for the cell array with csd, this is done further below + + % the estimates for variance and SEM are biased if we are working with the jackknife/bootstrap + % determine the proper variance scaling that corrects for this bias + % note that Ntrials is not always the same as the length of dip, especially in case of the bootstrap + if strcmp(source.method, 'singletrial') + bias = 1; + elseif strcmp(source.method, 'rawtrial') + bias = 1; + elseif strcmp(source.method, 'jackknife') + % Effron gives SEM estimate for the jackknife method in equation 11.5 (paragraph 11.2) + % to get the variance instead of SEM, we also have to multiply with the number of trials + bias = (Ntrials - 1)^2; + elseif strcmp(source.method, 'bootstrap') + % Effron gives SEM estimate for the bootstrap method in algorithm 6.1 (equation 6.6) + % to get the variance instead of SEM, we also have to multiply with the number of trials + bias = Ntrials; + elseif strcmp(source.method, 'pseudovalue') + % note that I have not put any thought in this aspect yet + warning('don''t know how to compute bias for pseudovalue resampling'); + bias = 1; + end + + % compute the variance over all repetitions + if isfield(sumdip, 'var'), dipvar.var = bias*(sqrdip.var - (sumdip.var .^2)/length(dip))/(length(dip)-1); end + if isfield(sumdip, 'pow'), dipvar.pow = bias*(sqrdip.pow - (sumdip.pow .^2)/length(dip))/(length(dip)-1); end + if isfield(sumdip, 'coh'), dipvar.coh = bias*(sqrdip.coh - (sumdip.coh .^2)/length(dip))/(length(dip)-1); end + if isfield(sumdip, 'rv' ), dipvar.rv = bias*(sqrdip.rv - (sumdip.rv .^2)/length(dip))/(length(dip)-1); end + if isfield(sumdip, 'noise' ), dipvar.noise = bias*(sqrdip.noise - (sumdip.noise .^2)/length(dip))/(length(dip)-1); end + if isfield(sumdip, 'nai' ), dipvar.nai = bias*(sqrdip.nai - (sumdip.nai .^2)/length(dip))/(length(dip)-1); end + + % compute the SEM over all repetitions + if isfield(sumdip, 'var'), dipsem.var = (dipvar.var /Ntrials).^0.5; end + if isfield(sumdip, 'pow'), dipsem.pow = (dipvar.pow /Ntrials).^0.5; end + if isfield(sumdip, 'coh'), dipsem.coh = (dipvar.coh /Ntrials).^0.5; end + if isfield(sumdip, 'rv' ), dipsem.rv = (dipvar.rv /Ntrials).^0.5; end + if isfield(sumdip, 'noise' ), dipsem.noise = (dipvar.noise /Ntrials).^0.5; end + if isfield(sumdip, 'nai' ), dipsem.nai = (dipvar.nai /Ntrials).^0.5; end + + % compute the mean and SEM over all repetitions for the cell array with mom + if isfield(dip(trial), 'mom') + for i=1:length(dip(1).mom) + dipmean.mom{i} = sumdip.mom{i}/length(dip); + dipvar.mom{i} = bias*(sqrdip.mom{i} - (sumdip.mom{i}.^2)/length(dip))/(length(dip)-1); + dipsem.mom{i} = (dipvar.mom{i}/Ntrials).^0.5; + end + end + + % compute the mean and SEM over all repetitions for the cell array with csd + if isfield(dip(trial), 'csd') + for i=1:length(dip(1).csd) + dipmean.csd{i} = sumdip.csd{i}/length(dip); + dipvar.csd{i} = bias*(sqrdip.csd{i} - (sumdip.csd{i}.^2)/length(dip))/(length(dip)-1); + dipsem.csd{i} = (dipvar.csd{i}/Ntrials).^0.5; + end + end + + if strcmp(source.method, 'pseudovalue') + % keep the trials, since they have been converted to pseudovalues + % and hence the trials contain the interesting data + elseif keeptrials + % keep the trials upon request + else + % remove the original trials + source = rmfield(source, 'trial'); + % assign the descriptive statistics to the output source structure + source.avg = dipmean; + source.var = dipvar; + source.sem = dipsem; + end +end + +if strcmp(cfg.resolutionmatrix, 'yes') + % this is only implemented for pcc and no refdips/chans at the moment + Nchan = size(source.leadfield{source.inside(1)}, 1); + Ninside = length(source.inside); + allfilter = zeros(Ninside,Nchan); + allleadfield = zeros(Nchan,Ninside); + dipsel = match_str(source.avg.csdlabel, 'scandip'); + progress('init', cfg.feedback, 'computing resolution matrix'); + for diplop=1:length(source.inside) + progress(diplop/length(source.inside), 'computing resolution matrix %d/%d\n', diplop, length(source.inside)); + i = source.inside(diplop); + % concatenate all filters + allfilter(diplop,:) = source.avg.filter{i}(dipsel,:); + % concatenate all leadfields + allleadfield(:,diplop) = source.leadfield{i}; + end + progress('close'); + % multiply the filters and leadfields to obtain the resolution matrix + % see equation 1 and 2 in De Peralta-Menendez RG, Gonzalez-Andino SL: A critical analysis of linear inverse solutions to the neuroelectromagnetic inverse problem. IEEE Transactions on Biomedical Engineering 45: 440-448, 1998. + source.resolution = nan*zeros(Ndipole, Ndipole); + source.resolution(source.inside, source.inside) = allfilter*allleadfield; +end + +% accessing this field here is needed for the configuration tracking +% by accessing it once, it will not be removed from the output cfg +cfg.outputfile; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_sourcedescriptives.m 1247 2010-06-17 12:07:18Z timeng $'; +% remember the configuration details of the input data +try, cfg.previous = source.cfg; end +% remember the exact configuration details in the output +source.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', source); % use the variable name "data" in the output file +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% helper function to compute eta from a csd-matrix +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [eta, u] = csd2eta(csd) +[u,s,v] = svd(real(csd)); +eta = s(2,2)./s(1,1); +u = u'; %orientation is defined in the rows + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% helper function to compute fa from a csd-matrix +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [fa] = csd2fa(csd) +s = svd(real(csd)); +ns = rank(real(csd)); +s = s(1:ns); +ms = mean(s); +fa = sqrt( (ns./(ns-1)) .* (sum((s-ms).^2))./(sum(s.^2)) ); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% helper function to compute power +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function p = powmethod_lambda1(x, ind); + +if nargin==1, + ind = 1:size(x,1); +end +s = svd(x(ind,ind)); +p = s(1); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% helper function to compute power +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function p = powmethod_trace(x, ind); + +if nargin==1, + ind = 1:size(x,1); +end +p = trace(x(ind,ind)); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% helper function to compute power +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function p = powmethod_regular(x, ind); + +if nargin==1, + ind = 1:size(x,1); +end +p = abs(x(ind,ind)); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% helper function to obtain the largest singular value or trace of the +% source CSD matrices resulting from DICS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function s = lambda1(x); +s = svd(x); +s = s(1); diff --git a/external/fieldtrip/ft_sourcegrandaverage.m b/external/fieldtrip/ft_sourcegrandaverage.m index b84b9b2..0e0f891 100644 --- a/external/fieldtrip/ft_sourcegrandaverage.m +++ b/external/fieldtrip/ft_sourcegrandaverage.m @@ -1,11 +1,288 @@ -function varargout = funname(varargin); +function [grandavg] = ft_sourcegrandaverage(cfg, varargin); -% this is a SPM wrapper around a FieldTrip function +% FT_SOUREGRANDAVERAGE averages source reconstructions over either multiple +% subjects or conditions. It computes the average and variance for all +% known source parameters. The output can be used in FT_SOURCESTATISTICS +% with the method 'parametric'. +% +% Alternatively, it can construct an average for multiple input source +% reconstructions in two conditions after randomly reassigning the +% input data over the two conditions. The output then can be used in +% FT_SOURCESTATISTICS with the method 'randomization' or 'randcluster'. +% +% The input source structures should be spatially alligned to each other +% and should have the same positions for the source grid. +% +% Use as +% [grandavg] = ft_sourcegrandaverage(cfg, source1, source2, ...) +% +% where the source structures are obtained from FT_SOURCEANALYSIS or +% from FT_VOLUMENORMALISE, and the configuration can contain the +% following fields: +% cfg.parameter = string, describing the functional data to be processed, e.g. 'pow', 'nai' or 'coh' +% cfg.keepindividual = 'no' or 'yes' +% +% See also FT_SOURCEANALYSIS, FT_VOLUMENORMALISE, FT_SOURCESTATISTICS -% this part is variable -prefix = 'ft_'; +% Undocumented local options +% You can also use FT_SOURCEGRANDAVERAGE to compute averages after +% randomizing the assignment of the functional data over two conditions. +% The resulting output can then be used in a statistical test just like +% the randomized single-subject source reconstruction that results from +% randomization in FT_SOURCEANALYSIS. This involves the following options +% cfg.randomization = 'no' or 'yes' +% cfg.permutation = 'no' or 'yes' +% cfg.numrandomization = number, e.g. 500 +% cfg.numpermutation = number, e.g. 500 or 'all' +% cfg.c1 = list with subjects belonging to condition 1 (or A) +% cfg.c2 = list with subjects belonging to condition 2 (or B) +% cfg.inputfile = one can specifiy preanalysed saved data as input +% The data should be provided in a cell array +% cfg.outputfile = one can specify output as file to save to disk -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_sourcegrandaverage.m 1273 2010-06-25 15:40:16Z timeng $ + +fieldtripdefs + +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +% set the defaults +if ~isfield(cfg, 'parameter'), cfg.parameter = 'pow'; end +if ~isfield(cfg, 'keepindividual'), cfg.keepindividual = 'no'; end +if ~isfield(cfg, 'concatenate'), cfg.concatenate = 'no'; end +if ~isfield(cfg, 'randomization'), cfg.randomization = 'no'; end +if ~isfield(cfg, 'permutation'), cfg.permutation = 'no'; end +if ~isfield(cfg, 'c1'), cfg.c1 = []; end +if ~isfield(cfg, 'c2'), cfg.c2 = []; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +if strcmp(cfg.concatenate, 'yes') && strcmp(cfg.keepindividual, 'yes'), + error('you can either specify cfg.keepindividual or cfg.concatenate to be yes'); +end + +hasdata = nargin>2; +if ~isempty(cfg.inputfile) % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + for i=1:numel(cfg.inputfile) + varargin{i} = loadvar(cfg.inputfile{i}, 'data'); % read datasets from array inputfile + end + end +end + +% check if the input data is valid for this function +for i=1:length(varargin) + varargin{i} = checkdata(varargin{i}, 'datatype', {'source', 'volume'}, 'feedback', 'no'); +end + +Nsubject = length(varargin); +Nvoxel = prod(varargin{1}.dim); +dat = zeros(Nvoxel, Nsubject); +inside = zeros(Nvoxel, Nsubject); + +if isfield(varargin{1}, 'pos') + % check that the source locations of each input source reconstruction are the same + for i=2:Nsubject + if size(varargin{i}.pos,1)~=size(varargin{1}.pos,1) || any(varargin{i}.pos(:)~=varargin{1}.pos(:)) + error('different grid locations in source reconstructions'); + end + end + grandavg.pos = varargin{1}.pos; +end + +if isfield(varargin{1}, 'dim') + % check that the dimensions of each input volume is the same + for i=2:Nsubject + if any(varargin{i}.dim(:)~=varargin{1}.dim(:)) + error('different dimensions of the source reconstructions'); + end + end + grandavg.dim = varargin{1}.dim; +end + +if isfield(varargin{1}, 'xgrid') && isfield(varargin{1}, 'ygrid') && isfield(varargin{1}, 'zgrid') + % check that the grid locations of each input volume are the same + for i=2:Nsubject + if length(varargin{i}.xgrid)~=length(varargin{1}.xgrid) || any(varargin{i}.xgrid~=varargin{1}.xgrid) + error('different xgrid in source reconstructions'); + elseif length(varargin{i}.ygrid)~=length(varargin{1}.ygrid) || any(varargin{i}.ygrid~=varargin{1}.ygrid) + error('different ygrid in source reconstructions'); + elseif length(varargin{i}.zgrid)~=length(varargin{1}.zgrid) || any(varargin{i}.zgrid~=varargin{1}.zgrid) + error('different zgrid in source reconstructions'); + end + end + grandavg.xgrid = varargin{1}.xgrid; + grandavg.ygrid = varargin{1}.ygrid; + grandavg.zgrid = varargin{1}.zgrid; +end + +if isfield(varargin{1}, 'transform') + % check that the homogenous transformation matrix of each input volume is the same + for i=2:Nsubject + if any(varargin{i}.transform(:)~=varargin{1}.transform(:)) + error('different homogenous transformation matrices in source reconstructions'); + end + end + grandavg.transform = varargin{1}.transform; +end + +% get the source parameter from each input source reconstruction +% get the inside parameter from each input source reconstruction +for i=1:Nsubject + % TODO this function should use parameterselection + if issubfield(varargin{i}, ['avg.' cfg.parameter]) + tmp = getsubfield(varargin{i}, ['avg.' cfg.parameter]); + else + tmp = getsubfield(varargin{i}, cfg.parameter); + end + dat(:,i) = tmp(:); + tmp = getsubfield(varargin{i}, 'inside'); + inside(tmp,i) = 1; +end +% ensure that voxels that are not in the scanned brain region are excluded from the averaging +dat(~inside) = nan; + +if strcmp(cfg.randomization, 'yes') || strcmp(cfg.permutation, 'yes') + if strcmp(cfg.keepindividual, 'yes') + error('you cannot keep individual data in combination with randomization or permutation'); + end + + % construct a design vector that contains the condition number 1 or 2 + design = zeros(1,Nsubject); + design(cfg.c1) = 1; + design(cfg.c2) = 2; + if any(design==0) + error('not all input source structures have been assigned to a condition'); + elseif length(design)~=Nsubject + error('not enough input source structures given cfg.c1 and cfg.c2'); + end + + % create a matrix with all randomized assignments to the two conditions + if strcmp(cfg.randomization, 'yes') + res = zeros(cfg.numrandomization, Nsubject); + for i=1:cfg.numrandomization + res(i,:) = design(randperm(Nsubject)); + end + elseif strcmp(cfg.permutation, 'yes') + sel1 = find(design==1); + sel2 = find(design==2); + if length(sel1)~=length(sel2) + error('permutation requires that there is an equal number of replications in each conditions') + end + res = zeros(cfg.numpermutation, Nsubject); + for i=1:cfg.numpermutation + flip = randn(1,length(sel1))>0; + res(i,sel1) = 1; + res(i,sel2) = 2; + res(i,sel1(find(flip))) = 2; + res(i,sel2(find(flip))) = 1; + end + end % randomization or permutation + + % randomize the input source parameter between the two conditions + clear trialA + clear trialB + for i=1:size(res,1) + selA = find(res(i,:)==1); + selB = find(res(i,:)==2); + % create the randomized averaged data + trialA(i) = setsubfield([], cfg.parameter, nan_mean(dat(:,selA),2)); + trialB(i) = setsubfield([], cfg.parameter, nan_mean(dat(:,selB),2)); + end + % create the observed average data + selA = find(design==1); + selB = find(design==2); + avgA = setsubfield([], cfg.parameter, nan_mean(dat(:,selA),2)); + avgB = setsubfield([], cfg.parameter, nan_mean(dat(:,selB),2)); + + % construct a source structure that can be fed into SOURCESTATISTICS_RANDOMIZATION or SOURCESTATISTICS_RANDCLUSTER + grandavg.trialA = trialA; + grandavg.trialB = trialB; + grandavg.avgA = avgA; + grandavg.avgB = avgB; + +else + if strcmp(cfg.concatenate, 'no'), + % compute a plain average and variance over all input source structures + grandavg.avg = setsubfield([], cfg.parameter, nan_mean(dat,2)); + grandavg.var = setsubfield([], cfg.parameter, nan_std(dat')'.^2); % nan_std operates over the first dimension + grandavg.dimord = 'voxel'; + else + grandavg.avg = setsubfield([], cfg.parameter, dat); + grandavg.dimord = 'voxel_freq'; + grandavg.dim = [grandavg.dim size(dat,2)]; + end + + if strcmp(cfg.keepindividual, 'yes') + clear trial + for i=1:Nsubject + trial(i) = setsubfield([], cfg.parameter, dat(:,i)); + end + grandavg.trial = trial; + end +end + +% determine which sources were inside or outside the brain in all subjects +allinside = find(all( inside,2)); +alloutside = find(all(~inside,2)); +someinside = find(any( inside,2)); +fprintf('%d voxels are inside the brain of all subjects\n', length(allinside)); +fprintf('%d voxels are inside the brain of some, but not all subjects\n', length(someinside)); +fprintf('%d voxels are outside the brain of all subjects\n', length(alloutside)); +warning('marking only voxels inside the brain of all subjects as ''inside'''); +if strcmp(cfg.concatenate, 'no'), + grandavg.inside = find(all( inside,2)); + grandavg.outside = find(any(~inside,2)); + grandavg.df = sum(inside,2); +else + grandavg.inside = find(inside(:)); + grandavg.outside = setdiff([1:prod(size(dat))]', grandavg.inside); +end + +cfg.outputfile; +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_sourcegrandaverage.m 1273 2010-06-25 15:40:16Z timeng $'; +% remember the configuration details of the input data +cfg.previous = []; +for i=1:Nsubject + try, cfg.previous{i} = varargin{i}.cfg; end +end +% remember the exact configuration details in the output +grandavg.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', grandavg); % use the variable name "data" in the output file +end diff --git a/external/fieldtrip/ft_sourceinterpolate.m b/external/fieldtrip/ft_sourceinterpolate.m index b84b9b2..5831ed0 100644 --- a/external/fieldtrip/ft_sourceinterpolate.m +++ b/external/fieldtrip/ft_sourceinterpolate.m @@ -1,11 +1,321 @@ -function varargout = funname(varargin); +function [interp] = ft_sourceinterpolate(cfg, functional, anatomical); -% this is a SPM wrapper around a FieldTrip function +% FT_SOURCEINTERPOLATE reslices and interpolates a source reconstruction +% or a statistical distribution as an overlay onto an anatomical MRI. +% +% The source volume and the anatomical volume should be expressed in the +% same coordinate sytem, i.e. either both in CTF coordinates (NAS/LPA/RPA) +% or both in SPM coordinates (AC/PC). The output volume will contain a +% resliced source and anatomical volume that can be plotted together with +% FT_SOURCEPLOT or FT_SLICEINTERP, or that can be written to file using FT_SOURCEWRITE. +% +% Use as +% [interp] = ft_sourceinterpolate(cfg, source, mri) or +% [interp] = ft_sourceinterpolate(cfg, stat, mri) +% where +% source is the output of FT_SOURCEANALYSIS +% stat is the output of FT_SOURCESTATISTICS +% mri is the output of FT_READ_FCDC_MRI or the filename of a MRI +% and cfg is a structure with any of the following fields +% cfg.parameter = string, default is 'all' +% cfg.interpmethod = 'linear', 'cubic', 'nearest' or 'spline' +% cfg.downsample = integer number (default = 1, i.e. no downsampling) +% +% See also FT_SOURCEANALYSIS, FT_SOURCESTATISTICS, FT_READ_FCDC_MRI +% +% Undocumented options +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk +% cfg.voxelcoord = 'yes' (default) or 'no' determines whether the +% downsampled output anatomical MRI will have the x/y/zgrid converted or +% the homogenous transformation matrix -% this part is variable -prefix = 'ft_'; +% Copyright (C) 2003-2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_sourceinterpolate.m 1258 2010-06-22 08:33:48Z timeng $ + +fieldtripdefs + +%% checkdata see below!!! %% + +% check if the input cfg is valid for this function +cfg = checkconfig(cfg, 'trackconfig', 'on'); +cfg = checkconfig(cfg, 'unused', {'keepinside'}); + +% set the defaults +if ~isfield(cfg, 'parameter'), cfg.parameter = 'all'; end +if ~isfield(cfg, 'interpmethod'); cfg.interpmethod = 'linear'; end +if ~isfield(cfg, 'downsample'); cfg.downsample = 1; end +if ~isfield(cfg, 'voxelcoord'), cfg.voxelcoord = 'yes'; end +if ~isfield(cfg, 'feedback'), cfg.feedback = 'text'; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +% if ~isfield(cfg, 'sourceunits'); cfg.sourceunits = []; end % this is deprecated, since now autodetermined +% if ~isfield(cfg, 'mriunits'); cfg.mriunits = []; end % this is deprecated, since now autodetermined +cfg = checkconfig(cfg, 'deprecated', {'sourceunits', 'mriunits'}); + +hasdata = (nargin>2); + +% load optional given inputfile as data +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + anatomical = loadvar(cfg.inputfile, 'data'); + end +end + +if ischar(anatomical) + % read the anatomical MRI data from file + fprintf('reading MRI from file\n'); + anatomical = ft_read_mri(anatomical); +end + +% check if the input data is valid for this function and ensure that the structures correctly describes a volume +functional = checkdata(functional, 'datatype', 'volume', 'inside', 'logical', 'feedback', 'yes', 'hasunits', 'yes'); +anatomical = checkdata(anatomical, 'datatype', 'volume', 'inside', 'logical', 'feedback', 'yes', 'hasunits', 'yes'); + +if isfield(cfg, 'sourceunits') && ~isempty(cfg.sourceunits) + % this uses a deprecated option + if ~strcmp(functional.unit, cfg.sourceunits) + warning('the automatically determined sourceunits (%s) do not match your specification (%s)', functional.unit, cfg.sourceunits); + functional.unit = cfg.sourceunits; % override the automatically determined units + end +end + +if isfield(cfg, 'mriunits') && ~isempty(cfg.mriunits) + % this uses a deprecated option + if ~strcmp(anatomical.unit, cfg.mriunits) + warning('the automatically determined mriunits (%s) do not match your specification (%s)', anatomical.unit, cfg.sourceunits); + anatomical.unit = cfg.mriunits; % override the automatically determined units + end +end + +if ~strcmp(functional.unit, anatomical.unit) + fprintf('converting functional data from %s into %s\n', functional.unit, anatomical.unit); + functional = ft_convert_units(functional, anatomical.unit); +end + +% select the parameters that should be interpolated +cfg.parameter = parameterselection(cfg.parameter, functional); +cfg.parameter = setdiff(cfg.parameter, 'inside'); % inside is handled seperately + +if ~isequal(cfg.downsample, 1) + % downsample the anatomical volume + tmpcfg = []; + tmpcfg.downsample = cfg.downsample; + tmpcfg.parameter = 'anatomy'; + anatomical = ft_volumedownsample(tmpcfg, anatomical); +end + +% collect the functional volumes that should be converted +vol_name = {}; +vol_data = {}; +for i=1:length(cfg.parameter) + if ~iscell(getsubfield(functional, cfg.parameter{i})) + vol_name{end+1} = cfg.parameter{i}; + vol_data{end+1} = getsubfield(functional, cfg.parameter{i}); + else + fprintf('not interpolating %s, since it is not a scalar field\n', cfg.parameter{i}); + end +end + +% remember the coordinate trandsformation for both +transform_ana = anatomical.transform; +transform_fun = functional.transform; + +% convert the anatomical voxel positions into voxel indices into the functional volume +anatomical.transform = functional.transform \ anatomical.transform; +functional.transform = eye(4); + +[fx, fy, fz] = voxelcoords(functional); +[ax, ay, az] = voxelcoords(anatomical); + +% estimate the subvolume of the anatomy that is spanned by the functional volume +minfx = 1; +minfy = 1; +minfz = 1; +maxfx = functional.dim(1); +maxfy = functional.dim(2); +maxfz = functional.dim(3); +sel = ax(:)>=minfx & ... + ax(:)<=maxfx & ... + ay(:)>=minfy & ... + ay(:)<=maxfy & ... + az(:)>=minfz & ... + az(:)<=maxfz; +fprintf('selecting subvolume of %.1f%%\n', 100*sum(sel)./prod(anatomical.dim)); + +% start with an empty output structure +interp = []; + +dimf = [functional.dim 1 1]; +allav = zeros([anatomical.dim dimf(4:end)]); +functional.inside = functional.inside(:,:,:,1,1); + +if all(functional.inside(:)) + % keep all voxels marked as inside + interp.inside = true(anatomical.dim); +else + % reslice and interpolate inside + interp.inside = zeros(anatomical.dim); + % interpolate with method nearest + interp.inside( sel) = my_interpn(double(functional.inside), ax(sel), ay(sel), az(sel), 'nearest', cfg.feedback); + interp.inside(~sel) = 0; + interp.inside = logical(interp.inside); +end + +% prepare the grid that is used in the interpolation +fg = [fx(:) fy(:) fz(:)]; +clear fx fy fz + +% reslice and interpolate all functional volumes +for i=1:length(vol_name) + fprintf('reslicing and interpolating %s\n', vol_name{i}); + for k=1:dimf(4) + for m=1:dimf(5) + fv = vol_data{i}(:,:,:,k,m); + if ~isa(fv, 'double') + % only convert if needed, this saves memory + fv = double(fv); + end + av = zeros(anatomical.dim); + % av( sel) = my_interpn(fx, fy, fz, fv, ax(sel), ay(sel), az(sel), cfg.interpmethod, cfg.feedback); + if islogical(vol_data{i}) + % interpolate always with method nearest + av( sel) = my_interpn(fv, ax(sel), ay(sel), az(sel), 'nearest', cfg.feedback); + av = logical(av); + else + if ~all(functional.inside(:)) + % extrapolate the outside of the functional volumes for better interpolation at the edges + fv(~functional.inside) = griddatan(fg(functional.inside(:), :), fv(functional.inside(:)), fg(~functional.inside(:), :), 'nearest'); + end + % interpolate functional onto anatomical grid + av( sel) = my_interpn(fv, ax(sel), ay(sel), az(sel), cfg.interpmethod, cfg.feedback); + clear fv + av(~sel) = nan; + av(~interp.inside) = nan; + end + allav(:,:,:,k,m) = av; + clear av + end + end + interp = setsubfield(interp, vol_name{i}, allav); +end + +% add the other parameters to the output +interp.dim = anatomical.dim; +interp.transform = transform_ana; % the original coordinate system +if ~any(strcmp(cfg.parameter, 'anatomy')) + % copy the anatomy into the functional data + interp.anatomy = anatomical.anatomy; +end + +% accessing this field here is needed for the configuration tracking +% by accessing it once, it will not be removed from the output cfg +cfg.outputfile; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_sourceinterpolate.m 1258 2010-06-22 08:33:48Z timeng $'; +% remember the configuration details of the input data +cfg.previous = []; +try, cfg.previous{1} = functional.cfg; end +try, cfg.previous{2} = anatomical.cfg; end +% remember the exact configuration details in the output +interp.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', interp); % use the variable name "data" in the output file +end + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION this function computes the location of all voxels in head +% coordinates in a memory efficient manner +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [x, y, z] = voxelcoords(volume) +dim = volume.dim; +transform = volume.transform; +if isfield(volume, 'xgrid') + xgrid = volume.xgrid; + ygrid = volume.ygrid; + zgrid = volume.zgrid; +else + xgrid = 1:dim(1); + ygrid = 1:dim(2); + zgrid = 1:dim(3); +end +npix = prod(dim(1:2)); % number of voxels in a single slice +nvox = prod(dim); +x = zeros(dim); +y = zeros(dim); +z = zeros(dim); +X = zeros(1,npix); +Y = zeros(1,npix); +Z = zeros(1,npix); +E = ones(1,npix); +% determine the voxel locations per slice +for i=1:dim(3) + [X(:), Y(:), Z(:)] = ndgrid(xgrid, ygrid, zgrid(i)); + tmp = transform*[X; Y; Z; E]; + x((1:npix)+(i-1)*npix) = tmp(1,:); + y((1:npix)+(i-1)*npix) = tmp(2,:); + z((1:npix)+(i-1)*npix) = tmp(3,:); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION for memory efficient interpolation +% the only reason for this function is that it does the interpolation in smaller chuncks +% this prevents memory problems that I often encountered here +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% function [av] = my_interpn(fx, fy, fz, fv, ax, ay, az, interpmethod, feedback); +function [av] = my_interpn(fv, ax, ay, az, interpmethod, feedback); +num = numel(ax); % total number of voxels +blocksize = floor(num/20); % number of voxels to interpolate at once, split it into 20 chuncks +lastblock = 0; % boolean flag for while loop +sel = 1:blocksize; % selection of voxels that are interpolated, this is the first chunck +progress('init', feedback, 'interpolating'); +while (1) + progress(sel(1)/num, 'interpolating %.1f%%\n', 100*sel(1)/num); + if sel(end)>num + sel = sel(1):num; + lastblock = 1; + end + av(sel) = interpn(fv, ax(sel), ay(sel), az(sel), interpmethod); + if lastblock + break + end + sel = sel + blocksize; +end +progress('close'); -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_sourcenormalise.m b/external/fieldtrip/ft_sourcenormalise.m deleted file mode 100644 index b84b9b2..0000000 --- a/external/fieldtrip/ft_sourcenormalise.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'ft_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_sourceplot.m b/external/fieldtrip/ft_sourceplot.m index b84b9b2..417335b 100644 --- a/external/fieldtrip/ft_sourceplot.m +++ b/external/fieldtrip/ft_sourceplot.m @@ -1,11 +1,1134 @@ -function varargout = funname(varargin); +function [cfg] = ft_sourceplot(cfg, data) -% this is a SPM wrapper around a FieldTrip function +% FT_SOURCEPLOT plots functional source reconstruction data on slices or on a +% surface, optionally as an overlay on anatomical MRI data, where +% statistical data can be used to determine the opacity of the mask. +% Input data comes from FT_SOURCEANALYSIS, FT_SOURCEGRANDAVERAGE or +% statistical values from FT_SOURCESTATISTICS. +% +% Use as: +% ft_sourceplot(cfg, data) +% +% The data can contain functional data, anatomical MRI data and statistical data, +% interpolated onto the same grid. +% +% The configuration should contain: +% cfg.method = 'slice', plots the data on a number of slices in the same plane +% 'ortho', plots the data on three orthogonal slices +% 'surface', plots the data on a 3D brain surface +% +% cfg.anaparameter = string, field in data with the anatomical data (default = 'anatomy' if present in data) +% cfg.funparameter = string, field in data with the functional parameter of interest (default = []) +% cfg.maskparameter = string, field in the data to be used for opacity masking of fun data (default = []) +% If values are between 0 and 1, zero is fully transparant and one is fully opaque. +% If values in the field are not between 0 and 1 they will be scaled depending on the values +% of cfg.opacitymap and cfg.opacitylim (see below) +% You can use masking in several ways, f.i. +% - use outcome of statistics to show only the significant values and mask the insignificant +% NB see also cfg.opacitymap and cfg.opacitylim below +% - use the functional data itself as mask, the highest value (and/or lowest when negative) +% will be opaque and the value closest to zero transparent +% - Make your own field in the data with values between 0 and 1 to control opacity directly +% +% The following parameters can be used in all methods: +% cfg.downsample = downsampling for resolution reduction, integer value (default = 1) (orig: from surface) +% cfg.atlas = string, filename of atlas to use (default = []) SEE FT_PREPARE_ATLAS +% for ROI masking (see "masking" below) or in interactive mode (see "ortho-plotting" below) +% cfg.inputcoord = 'mni' or 'tal', coordinate system of data used to lookup the label from the atlas +% +% The following parameters can be used for the functional data: +% cfg.funcolormap = colormap for functional data, see COLORMAP (default = 'auto') +% 'auto', depends structure funparameter, or on funcolorlim +% - funparameter: only positive values, or funcolorlim:'zeromax' -> 'hot' +% - funparameter: only negative values, or funcolorlim:'minzero' -> 'cool' +% - funparameter: both pos and neg values, or funcolorlim:'maxabs' -> 'jet' +% - funcolorlim: [min max] if min & max pos-> 'hot', neg-> 'cool', both-> 'jet' +% cfg.funcolorlim = color range of the functional data (default = 'auto') +% [min max] +% 'maxabs', from -max(abs(funparameter)) to +max(abs(funparameter)) +% 'zeromax', from 0 to max(abs(funparameter)) +% 'minzero', from min(abs(funparameter)) to 0 +% 'auto', if funparameter values are all positive: 'zeromax', +% all negative: 'minzero', both possitive and negative: 'maxabs' +% cfg.colorbar = 'yes' or 'no' (default = 'yes') +% +% The following parameters can be used for the masking data: +% cfg.opacitymap = opacitymap for mask data, see ALPHAMAP (default = 'auto') +% 'auto', depends structure maskparameter, or on opacitylim +% - maskparameter: only positive values, or opacitylim:'zeromax' -> 'rampup' +% - maskparameter: only negative values, or opacitylim:'minzero' -> 'rampdown' +% - maskparameter: both pos and neg values, or opacitylim:'maxabs' -> 'vdown' +% - opacitylim: [min max] if min & max pos-> 'rampup', neg-> 'rampdown', both-> 'vdown' +% - NB. to use p-values use 'rampdown' to get lowest p-values opaque and highest transparent +% cfg.opacitylim = range of mask values to which opacitymap is scaled (default = 'auto') +% [min max] +% 'maxabs', from -max(abs(maskparameter)) to +max(abs(maskparameter)) +% 'zeromax', from 0 to max(abs(maskparameter)) +% 'minzero', from min(abs(maskparameter)) to 0 +% 'auto', if maskparameter values are all positive: 'zeromax', +% all negative: 'minzero', both possitive and negative: 'maxabs' +% cfg.roi = string or cell of strings, region(s) of interest from anatomical atlas (see cfg.atlas above) +% everything is masked except for ROI +% +% The folowing parameters apply for ortho-plotting +% cfg.location = location of cut, (default = 'auto') +% 'auto', 'center' if only anatomy, 'max' if functional data +% 'min' and 'max' position of min/max funparameter +% 'center' of the brain +% [x y z], coordinates in voxels or head, see cfg.locationcoordinates +% cfg.locationcoordinates = coordinate system used in cfg.location, 'head' or 'voxel' (default = 'head') +% 'head', headcoordinates from anatomical MRI +% 'voxel', voxelcoordinates +% cfg.crosshair = 'yes' or 'no' (default = 'yes') +% cfg.axis = 'on' or 'off' (default = 'on') +% cfg.interactive = 'yes' or 'no' (default = 'no') +% in interactive mode cursor click determines location of cut +% cfg.queryrange = number, in atlas voxels (default 3) +% +% +% The folowing parameters apply for slice-plotting +% cfg.nslices = number of slices, (default = 20) +% cfg.slicerange = range of slices in data, (default = 'auto') +% 'auto', full range of data +% [min max], coordinates of first and last slice in voxels +% cfg.slicedim = dimension to slice 1 (x-axis) 2(y-axis) 3(z-axis) (default = 3) +% cfg.title = string, title of the figure window +% +% The folowing parameters apply for surface-plotting +% cfg.surffile = string, file that contains the surface (default = 'single_subj_T1.mat') +% 'single_subj_T1.mat' contains a triangulation that corresponds with the +% SPM anatomical template in MNI coordinates +% cfg.surfinflated = string, file that contains the inflated surface (default = []) +% cfg.surfdownsample = number (default = 1, i.e. no downsampling) +% cfg.projmethod = projection method, how functional volume data is projected onto surface +% 'nearest', 'sphere_avg', 'sphere_weighteddistance' +% cfg.sphereradius = maximum distance from each voxel to the surface to be +% included in the sphere projection methods, expressed in mm +% cfg.distmat = precomputed distance matrix (default = []) +% cfg.camlight = 'yes' or 'no' (default = 'yes') +% cfg.renderer = 'painters', 'zbuffer',' opengl' or 'none' (default = 'opengl') +% When using opacity the OpenGL renderer is required. +% +% Undocumented local option: +% cfg.inputfile = one can specifiy preanalysed saved data as input -% this part is variable -prefix = 'ft_'; +% TODO have to be built in: +% cfg.marker = [Nx3] array defining N marker positions to display (orig: from sliceinterp) +% cfg.markersize = radius of markers (default = 5) +% cfg.markercolor = [1x3] marker color in RGB (default = [1 1 1], i.e. white) (orig: from sliceinterp) +% white background option + +% undocumented TODO +% slice in all directions +% surface also optimal when inside present +% come up with a good glass brain projection + +% Copyright (C) 2007-2008, Robert Oostenveld, Ingrid Nieuwenhuis +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_sourceplot.m 1303 2010-06-29 15:42:37Z timeng $ + +fieldtripdefs + +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +%%% checkdata see below!!! %%% + +% set default for inputfile +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end + +% load optional given inputfile as data +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + end +end + +% set the common defaults +if ~isfield(cfg, 'method'), cfg.method = 'ortho'; end +if ~isfield(cfg, 'anaparameter'), + if isfield(data, 'anatomy'), + cfg.anaparameter = 'anatomy'; + else + cfg.anaparameter = []; + end +end + +% all methods +if ~isfield(cfg, 'funparameter'), cfg.funparameter = []; end +if ~isfield(cfg, 'maskparameter'), cfg.maskparameter = []; end +if ~isfield(cfg, 'downsample'), cfg.downsample = 1; end +if ~isfield(cfg, 'title'), cfg.title = ''; end +if ~isfield(cfg, 'atlas'), cfg.atlas = []; end +if ~isfield(cfg, 'marker'), cfg.marker = []; end %TODO implement marker +if ~isfield(cfg, 'markersize'), cfg.markersize = 5; end +if ~isfield(cfg, 'markercolor'), cfg.markercolor = [1,1,1]; end + +% set the common defaults for the functional data +if ~isfield(cfg, 'funcolormap'), cfg.funcolormap = 'auto'; end +if ~isfield(cfg, 'funcolorlim'), cfg.funcolorlim = 'auto'; end; + +% set the common defaults for the statistical data +if ~isfield(cfg, 'opacitymap'), cfg.opacitymap = 'auto'; end; +if ~isfield(cfg, 'opacitylim'), cfg.opacitylim = 'auto'; end; +if ~isfield(cfg, 'roi'), cfg.roi = []; end; + +% set the defaults per method +% ortho +if ~isfield(cfg, 'location'), cfg.location = 'auto'; end +if ~isfield(cfg, 'locationcoordinates'), cfg.locationcoordinates = 'head'; end +if ~isfield(cfg, 'crosshair'), cfg.crosshair = 'yes'; end +if ~isfield(cfg, 'colorbar'), cfg.colorbar = 'yes'; end +if ~isfield(cfg, 'axis'), cfg.axis = 'on'; end +if ~isfield(cfg, 'interactive'), cfg.interactive = 'no'; end +if ~isfield(cfg, 'queryrange'); cfg.queryrange = 3; end +if ~isfield(cfg, 'inputcoord'); cfg.inputcoord = []; end +if isfield(cfg, 'TTlookup'), + error('TTlookup is old; now specify cfg.atlas, see help!'); +end +% slice +if ~isfield(cfg, 'nslices'); cfg.nslices = 20; end +if ~isfield(cfg, 'slicedim'); cfg.slicedim = 3; end +if ~isfield(cfg, 'slicerange'); cfg.slicerange = 'auto'; end +% surface +if ~isfield(cfg, 'downsample'), cfg.downsample = 1; end +if ~isfield(cfg, 'surfdownsample'), cfg.surfdownsample = 1; end +if ~isfield(cfg, 'surffile'), cfg.surffile = 'single_subj_T1.mat'; end % use a triangulation that corresponds with the collin27 anatomical template in MNI coordinates +if ~isfield(cfg, 'surfinflated'), cfg.surfinflated = []; end +if ~isfield(cfg, 'sphereradius'), cfg.sphereradius = []; end +if ~isfield(cfg, 'distmat'), cfg.distmat = []; end +if ~isfield(cfg, 'camlight'), cfg.camlight = 'yes'; end +if ~isfield(cfg, 'renderer'), cfg.renderer = 'opengl'; end +if isequal(cfg.method,'surface') + if ~isfield(cfg, 'projmethod'), error('specify cfg.projmethod'); end +end + +% for backward compatibility +if strcmp(cfg.location, 'interactive') + cfg.location = 'auto'; + cfg.interactive = 'yes'; +end + +%%%%%%% +if ischar(data) + % read the anatomical MRI data from file + filename = data; + fprintf('reading MRI from file\n'); + data = ft_read_mri(filename); +end + +% check if the input data is valid for this function +data = checkdata(data, 'datatype', 'volume', 'feedback', 'yes'); + +% select the functional and the mask parameter +cfg.funparameter = parameterselection(cfg.funparameter, data); +cfg.maskparameter = parameterselection(cfg.maskparameter, data); +% only a single parameter should be selected +try, cfg.funparameter = cfg.funparameter{1}; end +try, cfg.maskparameter = cfg.maskparameter{1}; end + +% downsample all volumes +tmpcfg = []; +tmpcfg.parameter = {cfg.funparameter, cfg.maskparameter, cfg.anaparameter}; +tmpcfg.downsample = cfg.downsample; +data = ft_volumedownsample(tmpcfg, data); + +%%% make the local variables: +dim = data.dim; + +hasatlas = 0; +if ~isempty(cfg.atlas) + % initialize the atlas + hasatlas = 1; + [p, f, x] = fileparts(cfg.atlas); + fprintf(['reading ', f,' atlas coordinates and labels\n']); + atlas = ft_prepare_atlas(cfg.atlas); +end + +hasroi = 0; +if ~isempty(cfg.roi) + if ~hasatlas + error('specify cfg.atlas which belongs to cfg.roi') + else + % get mask + hasroi = 1; + tmpcfg.roi = cfg.roi; + tmpcfg.atlas = cfg.atlas; + tmpcfg.inputcoord = cfg.inputcoord; + roi = ft_volumelookup(tmpcfg,data); + end +end + +%%% anaparameter +if isempty(cfg.anaparameter); + hasana = 0; + fprintf('not plotting anatomy\n'); +elseif isfield(data, cfg.anaparameter) + hasana = 1; + ana = getsubfield(data, cfg.anaparameter); + % convert integers to single precision float if neccessary + if isa(ana, 'uint8') || isa(ana, 'uint16') || isa(ana, 'int8') || isa(ana, 'int16') + fprintf('converting anatomy to double\n'); + ana = double(ana); + end +else + warning('do not understand cfg.anaparameter, not plotting anatomy\n') + hasana = 0; +end + +%%% funparameter +% has fun? +if ~isempty(cfg.funparameter) + if issubfield(data, cfg.funparameter) + hasfun = 1; + fun = getsubfield(data, cfg.funparameter); + else + error('cfg.funparameter not found in data'); + end +else + hasfun = 0; + fprintf('no functional parameter\n'); +end + +% handle fun +if hasfun && issubfield(data, 'dimord') && strcmp(data.dimord(end-2:end),'rgb') + % treat functional data as rgb values + if any(fun(:)>1 | fun(:)<0) + %scale + tmpdim = size(fun); + nvox = prod(tmpdim(1:end-1)); + tmpfun = reshape(fun,[nvox tmpdim(end)]); + m1 = max(tmpfun,[],1); + m2 = min(tmpfun,[],1); + tmpfun = (tmpfun-m2(ones(nvox,1),:))./(m1(ones(nvox,1),:)-m2(ones(nvox,1),:)); + fun = reshape(tmpfun, tmpdim); + end + qi = 1; + hasfreq = 0; + hastime = 0; + + doimage = 1; + fcolmin = 0; + fcolmax = 1; +elseif hasfun + % determine scaling min and max (fcolmin fcolmax) and funcolormap + funmin = min(fun(:)); + funmax = max(fun(:)); + % smart lims: make from auto other string + if isequal(cfg.funcolorlim,'auto') + if sign(funmin)>-1 && sign(funmax)>-1 + cfg.funcolorlim = 'zeromax'; + elseif sign(funmin)<1 && sign(funmax)<1 + cfg.funcolorlim = 'minzero'; + else + cfg.funcolorlim = 'maxabs'; + end + end + if ischar(cfg.funcolorlim) + % limits are given as string + if isequal(cfg.funcolorlim,'maxabs') + fcolmin = -max(abs([funmin,funmax])); + fcolmax = max(abs([funmin,funmax])); + if isequal(cfg.funcolormap,'auto'); cfg.funcolormap = 'jet'; end; + elseif isequal(cfg.funcolorlim,'zeromax') + fcolmin = 0; + fcolmax = funmax; + if isequal(cfg.funcolormap,'auto'); cfg.funcolormap = 'hot'; end; + elseif isequal(cfg.funcolorlim,'minzero') + fcolmin = funmin; + fcolmax = 0; + if isequal(cfg.funcolormap,'auto'); cfg.funcolormap = 'cool'; end; + else + error('do not understand cfg.funcolorlim'); + end + else + % limits are numeric + fcolmin = cfg.funcolorlim(1); + fcolmax = cfg.funcolorlim(2); + % smart colormap + if isequal(cfg.funcolormap,'auto') + if sign(fcolmin) == -1 && sign(fcolmax) == 1 + cfg.funcolormap = 'jet'; + else + if fcolmin < 0 + cfg.funcolormap = 'cool'; + else + cfg.funcolormap = 'hot'; + end + end + end + end %if ischar + clear funmin funmax; + % ensure that the functional data is real + if ~isreal(fun) + fprintf('taking absolute value of complex data\n'); + fun = abs(fun); + end + + %what if fun is 4D? + if ndims(fun)>3, + if isfield(data, 'time') && isfield(data, 'freq'), + %data contains timefrequency representation + qi = [1 1]; + hasfreq = 1; + hastime = 1; + elseif isfield(data, 'time') + %data contains evoked field + qi = 1; + hasfreq = 0; + hastime = 1; + elseif isfield(data, 'freq') + %data contains frequency spectra + qi = 1; + hasfreq = 1; + hastime = 0; + end + else + %do nothing + qi = 1; + hasfreq = 0; + hastime = 0; + end + + doimage = 0; +else + qi = 1; + hasfreq = 0; + hastime = 0; + + doimage = 0; +end % handle fun + +%%% maskparameter +% has mask? +if ~isempty(cfg.maskparameter) + if issubfield(data, cfg.maskparameter) + if ~hasfun + error('you can not have a mask without functional data') + else + hasmsk = 1; + msk = getsubfield(data, cfg.maskparameter); + if islogical(msk) %otherwise sign() not posible + msk = double(msk); + end + end + else + error('cfg.maskparameter not found in data'); + end +else + hasmsk = 0; + fprintf('no masking parameter\n'); +end +% handle mask +if hasmsk + % determine scaling and opacitymap + mskmin = min(msk(:)); + mskmax = max(msk(:)); + % determine the opacity limits and the opacity map + % smart lims: make from auto other string, or equal to funcolorlim if funparameter == maskparameter + if isequal(cfg.opacitylim,'auto') + if isequal(cfg.funparameter,cfg.maskparameter) + cfg.opacitylim = cfg.funcolorlim; + else + if sign(mskmin)>-1 && sign(mskmax)>-1 + cfg.opacitylim = 'zeromax'; + elseif sign(mskmin)<1 && sign(mskmax)<1 + cfg.opacitylim = 'minzero'; + else + cfg.opacitylim = 'maxabs'; + end + end + end + if ischar(cfg.opacitylim) + % limits are given as string + switch cfg.opacitylim + case 'zeromax' + opacmin = 0; + opacmax = mskmax; + if isequal(cfg.opacitymap,'auto'), cfg.opacitymap = 'rampup'; end; + case 'minzero' + opacmin = mskmin; + opacmax = 0; + if isequal(cfg.opacitymap,'auto'), cfg.opacitymap = 'rampdown'; end; + case 'maxabs' + opacmin = -max(abs([mskmin, mskmax])); + opacmax = max(abs([mskmin, mskmax])); + if isequal(cfg.opacitymap,'auto'), cfg.opacitymap = 'vdown'; end; + otherwise + error('incorrect specification of cfg.opacitylim'); + end % switch opacitylim + else + % limits are numeric + opacmin = cfg.opacitylim(1); + opacmax = cfg.opacitylim(2); + if isequal(cfg.opacitymap,'auto') + if sign(opacmin)>-1 && sign(opacmax)>-1 + cfg.opacitymap = 'rampup'; + elseif sign(opacmin)<1 && sign(opacmax)<1 + cfg.opacitymap = 'rampdown'; + else + cfg.opacitymap = 'vdown'; + end + end + end % handling opacitylim and opacitymap + clear mskmin mskmax; +end + +% prevent outside fun from being plotted +if hasfun && isfield(data,'inside') && ~hasmsk + hasmsk = 1; + msk = zeros(dim); + cfg.opacitymap = 'rampup'; + opacmin = 0; + opacmax = 1; + % make intelligent mask + if isequal(cfg.method,'surface') + msk(data.inside) = 1; + else + if hasana + msk(data.inside) = 0.5; %so anatomy is visible + else + msk(data.inside) = 1; + end + end +end + +% if region of interest is specified, mask everything besides roi +if hasfun && hasroi && ~hasmsk + hasmsk = 1; + msk = roi; + cfg.opacitymap = 'rampup'; + opacmin = 0; + opacmax = 1; +elseif hasfun && hasroi && hasmsk + msk = roi .* msk; +elseif hasroi + error('you can not have a roi without functional data') +end + +%%% set color and opacity mapping for this figure +if hasfun + cfg.funcolormap = colormap(cfg.funcolormap); + colormap(cfg.funcolormap); +end +if hasmsk + cfg.opacitymap = alphamap(cfg.opacitymap); + alphamap(cfg.opacitymap); +end + +%%% determine what has to be plotted, depends on method +if isequal(cfg.method,'ortho') + if ~ischar(cfg.location) + if strcmp(cfg.locationcoordinates, 'head') + % convert the headcoordinates location into voxel coordinates + loc = inv(data.transform) * [cfg.location(:); 1]; + loc = round(loc(1:3)); + elseif strcmp(cfg.locationcoordinates, 'voxel') + % the location is already in voxel coordinates + loc = round(cfg.location(1:3)); + else + error('you should specify cfg.locationcoordinates'); + end + else + if isequal(cfg.location,'auto') + if hasfun + if isequal(cfg.funcolorlim,'maxabs'); + loc = 'max'; + elseif isequal(cfg.funcolorlim, 'zeromax'); + loc = 'max'; + elseif isequal(cfg.funcolorlim, 'minzero'); + loc = 'min'; + else %if numerical + loc = 'max'; + end + else + loc = 'center'; + end; + else + loc = cfg.location; + end + end + + % determine the initial intersection of the cursor (xi yi zi) + if ischar(loc) && strcmp(loc, 'min') + if isempty(cfg.funparameter) + error('cfg.location is min, but no functional parameter specified'); + end + [minval, minindx] = min(fun(:)); + [xi, yi, zi] = ind2sub(dim, minindx); + elseif ischar(loc) && strcmp(loc, 'max') + if isempty(cfg.funparameter) + error('cfg.location is max, but no functional parameter specified'); + end + [maxval, maxindx] = max(fun(:)); + [xi, yi, zi] = ind2sub(dim, maxindx); + elseif ischar(loc) && strcmp(loc, 'center') + xi = round(dim(1)/2); + yi = round(dim(2)/2); + zi = round(dim(3)/2); + elseif ~ischar(loc) + % using nearest instead of round ensures that the position remains within the volume + xi = nearest(1:dim(1), loc(1)); + yi = nearest(1:dim(2), loc(2)); + zi = nearest(1:dim(3), loc(3)); + end + + %% do the actual plotting %% + nas = []; + lpa = []; + rpa = []; + interactive_flag = 1; % it happens at least once + while(interactive_flag) + interactive_flag = strcmp(cfg.interactive, 'yes'); + + xi = round(xi); xi = max(xi, 1); xi = min(xi, dim(1)); + yi = round(yi); yi = max(yi, 1); yi = min(yi, dim(2)); + zi = round(zi); zi = max(zi, 1); zi = min(zi, dim(3)); + + if interactive_flag + fprintf('\n'); + fprintf('click with mouse button to reposition the cursor\n'); + fprintf('press n/l/r on keyboard to record a fiducial position\n'); + fprintf('press q on keyboard to quit interactive mode\n'); + end + + ijk = [xi yi zi 1]'; + xyz = data.transform * ijk; + if hasfun && ~hasatlas + val = fun(xi, yi, zi, qi); + if ~hasfreq && ~hastime, + fprintf('voxel %d, indices [%d %d %d], location [%.1f %.1f %.1f], value %f\n', sub2ind(dim, xi, yi, zi), ijk(1:3), xyz(1:3), val); + elseif hastime && hasfreq, + val = fun(xi, yi, zi, qi(1), qi(2)); + fprintf('voxel %d, indices [%d %d %d %d %d], %s coordinates [%.1f %.1f %.1f %.1f %.1f], value %f\n', [sub2ind(dim(1:3), xi, yi, zi), ijk(1:3)', qi], cfg.inputcoord, [xyz(1:3)' data.freq(qi(1)) data.time(qi(2))], val); + elseif hastime, + fprintf('voxel %d, indices [%d %d %d %d], %s coordinates [%.1f %.1f %.1f %.1f], value %f\n', [sub2ind(dim(1:3), xi, yi, zi), ijk(1:3)', qi], cfg.inputcoord, [xyz(1:3)', data.time(qi(1))], val); + elseif hasfreq, + fprintf('voxel %d, indices [%d %d %d %d], %s coordinates [%.1f %.1f %.1f %.1f], value %f\n', [sub2ind(dim(1:3), xi, yi, zi), ijk(1:3)', qi], cfg.inputcoord, [xyz(1:3)', data.freq(qi)], val); + end + elseif hasfun && hasatlas + val = fun(xi, yi, zi, qi); + fprintf('voxel %d, indices [%d %d %d], %s coordinates [%.1f %.1f %.1f], value %f\n', sub2ind(dim, xi, yi, zi), ijk(1:3), cfg.inputcoord, xyz(1:3), val); + elseif ~hasfun && ~hasatlas + fprintf('voxel %d, indices [%d %d %d], location [%.1f %.1f %.1f]\n', sub2ind(dim, xi, yi, zi), ijk(1:3), xyz(1:3)); + elseif ~hasfun && hasatlas + fprintf('voxel %d, indices [%d %d %d], %s coordinates [%.1f %.1f %.1f]\n', sub2ind(dim, xi, yi, zi), ijk(1:3), cfg.inputcoord, xyz(1:3)); + end + + if hasatlas + % determine the anatomical label of the current position + lab = atlas_lookup(atlas, (xyz(1:3)), 'inputcoord', cfg.inputcoord, 'queryrange', cfg.queryrange); + if isempty(lab) + fprintf([f,' labels: not found\n']); + else + fprintf([f,' labels: ']) + fprintf('%s', lab{1}); + for i=2:length(lab) + fprintf(', %s', lab{i}); + end + fprintf('\n'); + end + end + + % make vols and scales, containes volumes to be plotted (fun, ana, msk) + vols = {}; + if hasana; vols{1} = ana; scales{1} = []; end; % needed when only plotting ana + if hasfun; vols{2} = fun; scales{2} = [fcolmin fcolmax]; end; + if hasmsk; vols{3} = msk; scales{3} = [opacmin opacmax]; end; + + if isempty(vols) + % this seems to be a problem that people often have + error('no anatomy is present and no functional data is selected, please check your cfg.funparameter'); + end + + h1 = subplot(2,2,1); + [vols2D] = handle_ortho(vols, [xi yi zi qi], 2, dim, doimage); + plot2D(vols2D, scales, doimage); + xlabel('i'); ylabel('k'); axis(cfg.axis); + if strcmp(cfg.crosshair, 'yes'), crosshair([xi zi]); end + + h2 = subplot(2,2,2); + [vols2D] = handle_ortho(vols, [xi yi zi qi], 1, dim, doimage); + plot2D(vols2D, scales, doimage); + xlabel('j'); ylabel('k'); axis(cfg.axis); + if strcmp(cfg.crosshair, 'yes'), crosshair([yi zi]); end + + h3 = subplot(2,2,3); + [vols2D] = handle_ortho(vols, [xi yi zi qi], 3, dim, doimage); + plot2D(vols2D, scales, doimage); + xlabel('i'); ylabel('j'); axis(cfg.axis); + if strcmp(cfg.crosshair, 'yes'), crosshair([xi yi]); end + + if hasfreq && hastime && hasfun, + h=subplot(2,2,4); + %uimagesc(data.time, data.freq, squeeze(vols{2}(xi,yi,zi,:,:))');axis xy; + tmpdat = double(squeeze(vols{2}(xi,yi,zi,:,:))); + pcolor(double(data.time), double(data.freq), double(squeeze(vols{2}(xi,yi,zi,:,:)))); + shading('interp'); + xlabel('time'); ylabel('freq'); + caxis([-1 1].*max(abs(caxis))); + colorbar; + %caxis([fcolmin fcolmax]); + %set(gca, 'Visible', 'off'); + elseif hasfreq && hasfun, + subplot(2,2,4); + plot(data.freq, squeeze(vols{2}(xi,yi,zi,:))); xlabel('freq'); + axis([data.freq(1) data.freq(end) scales{2}]); + elseif hastime && hasfun, + subplot(2,2,4); + plot(data.time, squeeze(vols{2}(xi,yi,zi,:))); xlabel('time'); + axis([data.time(1) data.time(end) scales{2}]); + elseif strcmp(cfg.colorbar, 'yes'), + if hasfun + % vectorcolorbar = linspace(fcolmin, fcolmax,length(cfg.funcolormap)); + % imagesc(vectorcolorbar,1,vectorcolorbar);colormap(cfg.funcolormap); + subplot(2,2,4); + % use a normal Matlab colorbar, attach it to the invisible 4th subplot + caxis([fcolmin fcolmax]); + hc = colorbar; + set(hc, 'YLim', [fcolmin fcolmax]); + set(gca, 'Visible', 'off'); + else + warning('no colorbar possible without functional data') + end + end + + set(gcf, 'renderer', cfg.renderer); % ensure that this is done in interactive mode + drawnow; + + if interactive_flag + try + [d1, d2, key] = ginput(1); + catch + % this happens if the figure is closed + key='q'; + end + + if isempty(key) + % this happens if you press the apple key + key = ''; + end + switch key + case '' + % do nothing + case 'q' + break; + case 'l' + lpa = [xi yi zi]; + case 'r' + rpa = [xi yi zi]; + case 'n' + nas = [xi yi zi]; + case {'i' 'j''k' 'm'} + % update the view to a new position + if l1=='i' && l2=='k' && key=='i', zi = zi+1; + elseif l1=='i' && l2=='k' && key=='j', xi = xi-1; + elseif l1=='i' && l2=='k' && key=='k', xi = xi+1; + elseif l1=='i' && l2=='k' && key=='m', zi = zi-1; + elseif l1=='i' && l2=='j' && key=='i', yi = yi+1; + elseif l1=='i' && l2=='j' && key=='j', xi = xi-1; + elseif l1=='i' && l2=='j' && key=='k', xi = xi+1; + elseif l1=='i' && l2=='j' && key=='m', yi = yi-1; + elseif l1=='j' && l2=='k' && key=='i', zi = zi+1; + elseif l1=='j' && l2=='k' && key=='j', yi = yi-1; + elseif l1=='j' && l2=='k' && key=='k', yi = yi+1; + elseif l1=='j' && l2=='k' && key=='m', zi = zi-1; + end; + otherwise + % update the view to a new position + l1 = get(get(gca, 'xlabel'), 'string'); + l2 = get(get(gca, 'ylabel'), 'string'); + switch l1, + case 'i' + xi = d1; + case 'j' + yi = d1; + case 'k' + zi = d1; + case 'freq' + qi = nearest(data.freq,d1); + case 'time' + qi = nearest(data.time,d1); + end + switch l2, + case 'i' + xi = d2; + case 'j' + yi = d2; + case 'k' + zi = d2; + case 'freq' + qi = [nearest(data.freq,d2) qi(1)]; + end + end % switch key + end % if interactive_flag + if ~isempty(nas), fprintf('nas = [%f %f %f]\n', nas); cfg.fiducial.nas = nas; else fprintf('nas = undefined\n'); end + if ~isempty(lpa), fprintf('lpa = [%f %f %f]\n', lpa); cfg.fiducial.lpa = lpa; else fprintf('lpa = undefined\n'); end + if ~isempty(rpa), fprintf('rpa = [%f %f %f]\n', rpa); cfg.fiducial.rpa = rpa; else fprintf('rpa = undefined\n'); end + end % while interactive_flag + +elseif isequal(cfg.method,'glassbrain') + tmpcfg = []; + tmpcfg.funparameter = cfg.funparameter; + tmpcfg.method = 'ortho'; + tmpcfg.location = [1 1 1]; + tmpcfg.funcolorlim = cfg.funcolorlim; + tmpcfg.funcolormap = cfg.funcolormap; + tmpcfg.opacitylim = cfg.opacitylim; + tmpcfg.locationcoordinates = 'voxel'; + tmpcfg.maskparameter = 'inside'; + tmpcfg.axis = cfg.axis; + tmpcfg.renderer = cfg.renderer; + if hasfun, + fun = getsubfield(data, cfg.funparameter); + fun(1,:,:) = max(fun, [], 1); + fun(:,1,:) = max(fun, [], 2); + fun(:,:,1) = max(fun, [], 3); + data = setsubfield(data, cfg.funparameter, fun); + end + + if hasana, + ana = getsubfield(data, cfg.anaparameter); + %ana(1,:,:) = max(ana, [], 1); + %ana(:,1,:) = max(ana, [], 2); + %ana(:,:,1) = max(ana, [], 3); + data = setsubfield(data, cfg.anaparameter, ana); + end + + if hasmsk, + msk = getsubfield(data, 'inside'); + msk(1,:,:) = squeeze(fun(1,:,:))>0 & imfill(abs(squeeze(ana(1,:,:))-1))>0; + msk(:,1,:) = squeeze(fun(:,1,:))>0 & imfill(abs(squeeze(ana(:,1,:))-1))>0; + msk(:,:,1) = squeeze(fun(:,:,1))>0 & imfill(abs(ana(:,:,1)-1))>0; + data = setsubfield(data, 'inside', msk); + end + + ft_sourceplot(tmpcfg, data); + +elseif isequal(cfg.method,'surface') + + % read the triangulated cortical surface from file + tmp = load(cfg.surffile, 'bnd'); + surf = tmp.bnd; + if isfield(surf, 'transform'), + % compute the surface vertices in head coordinates + surf.pnt = warp_apply(surf.transform, surf.pnt); + end + + % downsample the cortical surface + if cfg.surfdownsample > 1 + if ~isempty(cfg.surfinflated) + error('downsampling the surface is not possible in combination with an inflated surface'); + end + fprintf('downsampling surface from %d vertices\n', size(surf.pnt,1)); + [surf.tri, surf.pnt] = reducepatch(surf.tri, surf.pnt, 1/cfg.surfdownsample); + end + + % these are required + if ~isfield(data, 'inside') + data.inside = true(dim); + end + + fprintf('%d voxels in functional data\n', prod(dim)); + fprintf('%d vertices in cortical surface\n', size(surf.pnt,1)); + + if hasfun + [interpmat, cfg.distmat] = interp_gridded(data.transform, fun, surf.pnt, 'projmethod', cfg.projmethod, 'distmat', cfg.distmat, 'sphereradius', cfg.sphereradius, 'inside', data.inside); + % interpolate the functional data + val = interpmat * fun(data.inside(:)); + if hasmsk + % also interpolate the opacity mask + maskval = interpmat * msk(data.inside(:)); + end + end + + if ~isempty(cfg.surfinflated) + % read the inflated triangulated cortical surface from file + tmp = load(cfg.surfinflated, 'bnd'); + surf = tmp.bnd; + if isfield(surf, 'transform'), + % compute the surface vertices in head coordinates + surf.pnt = warp_apply(surf.transform, surf.pnt); + end + end + + %------do the plotting + cortex_light = [0.781 0.762 0.664]; + cortex_dark = [0.781 0.762 0.664]/2; + if isfield(surf, 'curv') + % the curvature determines the color of gyri and sulci + color = surf.curv(:) * cortex_light + (1-surf.curv(:)) * cortex_dark; + else + color = repmat(cortex_light, size(surf.pnt,1), 1); + end + + h1 = patch('Vertices', surf.pnt, 'Faces', surf.tri, 'FaceVertexCData', color , 'FaceColor', 'interp'); + set(h1, 'EdgeColor', 'none'); + axis off; + axis vis3d; + axis equal; + + h2 = patch('Vertices', surf.pnt, 'Faces', surf.tri, 'FaceVertexCData', val , 'FaceColor', 'interp'); + set(h2, 'EdgeColor', 'none'); + if hasmsk + set(h2, 'FaceVertexAlphaData', maskval); + set(h2, 'FaceAlpha', 'interp'); + set(h2, 'AlphaDataMapping', 'scaled'); + alim(gca, [opacmin opacmax]); + end + caxis(gca,[fcolmin fcolmax]); + + lighting gouraud + if hasfun + colormap(cfg.funcolormap); + end + if hasmsk + alphamap(cfg.opacitymap); + end + + if strcmp(cfg.camlight,'yes') + camlight + end + + if strcmp(cfg.colorbar, 'yes'), + if hasfun + % use a normal Matlab colorbar + hc = colorbar; + set(hc, 'YLim', [fcolmin fcolmax]); + else + warning('no colorbar possible without functional data') + end + end + +elseif isequal(cfg.method,'slice') + % white BG => mskana + + %% TODO: HERE THE FUNCTION THAT MAKES TO SLICE DIMENSION ALWAYS THE THIRD + %% DIMENSION, AND ALSO KEEP TRANSFORMATION MATRIX UP TO DATE + % zoiets + %if hasana; ana = shiftdim(ana,cfg.slicedim-1); end; + %if hasfun; fun = shiftdim(fun,cfg.slicedim-1); end; + %if hasmsk; msk = shiftdim(msk,cfg.slicedim-1); end; + %%%%% select slices + if ~ischar(cfg.slicerange) + ind_fslice = cfg.slicerange(1); + ind_lslice = cfg.slicerange(2); + elseif isequal(cfg.slicerange, 'auto') + if hasfun %default + if isfield(data,'inside') + ind_fslice = min(find(max(max(data.inside,[],1),[],2))); + ind_lslice = max(find(max(max(data.inside,[],1),[],2))); + else + ind_fslice = min(find(~isnan(max(max(fun,[],1),[],2)))); + ind_lslice = max(find(~isnan(max(max(fun,[],1),[],2)))); + end + elseif hasana %if only ana, no fun + ind_fslice = min(find(max(max(ana,[],1),[],2))); + ind_lslice = max(find(max(max(ana,[],1),[],2))); + else + error('no functional parameter and no anatomical parameter, can not plot'); + end + else + error('do not understand cfg.slicerange'); + end + ind_allslice = linspace(ind_fslice,ind_lslice,cfg.nslices); + ind_allslice = round(ind_allslice); + % make new ana, fun, msk, mskana with only the slices that will be plotted (slice dim is always third dimension) + if hasana; new_ana = ana(:,:,ind_allslice); clear ana; ana=new_ana; clear new_ana; end; + if hasfun; new_fun = fun(:,:,ind_allslice); clear fun; fun=new_fun; clear new_fun; end; + if hasmsk; new_msk = msk(:,:,ind_allslice); clear msk; msk=new_msk; clear new_msk; end; + %if hasmskana; new_mskana = mskana(:,:,ind_allslice); clear mskana; mskana=new_mskana; clear new_mskana; end; + + % update the dimensions of the volume + if hasana; dim=size(ana); else dim=size(fun); end; + + %%%%% make "quilts", that contain all slices on 2D patched sheet + % Number of patches along sides of Quilt (M and N) + % Size (in voxels) of side of patches of Quilt (m and n) + m = dim(1); + n = dim(2); + M = ceil(sqrt(dim(3))); + N = ceil(sqrt(dim(3))); + num_patch = N*M; + if cfg.slicedim~=3 + error('only supported for slicedim=3'); + end + num_slice = (dim(cfg.slicedim)); + num_empt = num_patch-num_slice; + % put empty slides on ana, fun, msk, mskana to fill Quilt up + if hasana; ana(:,:,end+1:num_patch)=0; end; + if hasfun; fun(:,:,end+1:num_patch)=0; end; + if hasmsk; msk(:,:,end+1:num_patch)=0; end; + %if hasmskana; mskana(:,:,end:num_patch)=0; end; + % put the slices in the quilt + for iSlice = 1:num_slice + xbeg = floor((iSlice-1)./M); + ybeg = mod(iSlice-1, M); + if hasana + quilt_ana(ybeg.*m+1:(ybeg+1).*m, xbeg.*n+1:(xbeg+1).*n)=squeeze(ana(:,:,iSlice)); + end + if hasfun + quilt_fun(ybeg.*m+1:(ybeg+1).*m, xbeg.*n+1:(xbeg+1).*n)=squeeze(fun(:,:,iSlice)); + end + if hasmsk + quilt_msk(ybeg.*m+1:(ybeg+1).*m, xbeg.*n+1:(xbeg+1).*n)=squeeze(msk(:,:,iSlice)); + end + % if hasmskana + % quilt_mskana(ybeg.*m+1:(ybeg+1).*m, xbeg.*n+1:(xbeg+1).*n)=squeeze(mskana(:,:,iSlice)); + % end + end + % make vols and scales, containes volumes to be plotted (fun, ana, msk) %added ingnie + if hasana; vols2D{1} = quilt_ana; scales{1} = []; end; % needed when only plotting ana + if hasfun; vols2D{2} = quilt_fun; scales{2} = [fcolmin fcolmax]; end; + if hasmsk; vols2D{3} = quilt_msk; scales{3} = [opacmin opacmax]; end; + plot2D(vols2D, scales, doimage); + axis off + if strcmp(cfg.colorbar, 'yes'), + if hasfun + % use a normal Matlab coorbar + hc = colorbar; + set(hc, 'YLim', [fcolmin fcolmax]); + else + warning('no colorbar possible without functional data') + end + end + +end + +title(cfg.title); +set(gcf, 'renderer', cfg.renderer); + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% handle_ortho makes an overlay of 3D anatomical, functional and probability +% volumes. The three volumes must be scaled between 0 and 1. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [vols2D] = handle_ortho(vols, indx, slicedir, dim, doimage) + +% put 2Dvolumes in fun, ana and msk +if length(vols)>=1 && isempty(vols{1}); hasana=0; else ana=vols{1}; hasana=1; end; +if length(vols)>=2 + if isempty(vols{2}); hasfun=0; else fun=vols{2}; hasfun=1; end; +else hasfun=0; end +if length(vols)>=3 + if isempty(vols{3}); hasmsk=0; else msk=vols{3}; hasmsk=1; end; +else hasmsk=0; end + +% select the indices of the intersection +xi = indx(1); +yi = indx(2); +zi = indx(3); +qi = indx(4); +if length(indx)>4, + qi(2) = indx(5); +else + qi(2) = 1; +end + +% select the slice to plot +if slicedir==1 + yi = 1:dim(2); + zi = 1:dim(3); +elseif slicedir==2 + xi = 1:dim(1); + zi = 1:dim(3); +elseif slicedir==3 + xi = 1:dim(1); + yi = 1:dim(2); +end + +% cut out the slice of interest +if hasana; ana = squeeze(ana(xi,yi,zi)); end; +if hasfun; + if doimage + fun = squeeze(fun(xi,yi,zi,:)); + else + fun = squeeze(fun(xi,yi,zi,qi(1),qi(2))); + end +end +if hasmsk && length(size(msk))>3 + msk = squeeze(msk(xi,yi,zi,qi(1),qi(2))); +elseif hasmsk + msk = squeeze(msk(xi,yi,zi)); +end; + +%put fun, ana and msk in vols2D +if hasana; vols2D{1} = ana; end; +if hasfun; vols2D{2} = fun; end; +if hasmsk; vols2D{3} = msk; end; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% plot2D plots a two dimensional plot, used in ortho and slice +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function plot2D(vols2D, scales, doimage); +cla; +% put 2D volumes in fun, ana and msk +hasana = length(vols2D)>0 && ~isempty(vols2D{1}); +hasfun = length(vols2D)>1 && ~isempty(vols2D{2}); +hasmsk = length(vols2D)>2 && ~isempty(vols2D{3}); + +% the transpose is needed for displaying the matrix using the Matlab image() function +if hasana; ana = vols2D{1}'; end; +if hasfun && ~doimage; fun = vols2D{2}'; end; +if hasfun && doimage; fun = permute(vols2D{2},[2 1 3]); end; +if hasmsk; msk = vols2D{3}'; end; + + +if hasana + % scale anatomy between 0 and 1 + fprintf('scaling anatomy\n'); + amin = min(ana(:)); + amax = max(ana(:)); + ana = (ana-amin)./(amax-amin); + clear amin amax; + % convert anatomy into RGB values + ana = cat(3, ana, ana, ana); + ha = imagesc(ana); +end +hold on + +if hasfun + + if doimage + hf = image(fun); + else + hf = imagesc(fun); + caxis(scales{2}); + % apply the opacity mask to the functional data + if hasmsk + % set the opacity + set(hf, 'AlphaData', msk) + set(hf, 'AlphaDataMapping', 'scaled') + alim(scales{3}); + elseif hasana + set(hf, 'AlphaData', 0.5) + end + + end +end + +axis equal +axis tight +axis xy -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_sourcestatistics.m b/external/fieldtrip/ft_sourcestatistics.m index b84b9b2..ae2107f 100644 --- a/external/fieldtrip/ft_sourcestatistics.m +++ b/external/fieldtrip/ft_sourcestatistics.m @@ -1,11 +1,586 @@ -function varargout = funname(varargin); +function [stat] = ft_sourcestatistics(cfg, varargin) -% this is a SPM wrapper around a FieldTrip function +% FT_SOURCESTATISTICS computes the probability for a given null-hypothesis using +% a parametric statistical test or using a non-parametric randomization test. +% +% Use as +% [stat] = ft_sourcestatistics(cfg, source1, source2, ...) +% where the input data is the result from FT_SOURCEANALYSIS, FT_SOURCEDESCRIPTIVES +% or FT_SOURCEGRANDAVERAGE. The source structures should be spatially alligned +% to each other and should have the same positions for the source grid. +% +% The configuration should contain the following option for data selection +% cfg.parameter = string, describing the functional data to be processed, e.g. 'pow', 'nai' or 'coh' +% +% Furthermore, the configuration should contain: +% cfg.method = different methods for calculating the probability of the null-hypothesis, +% 'montecarlo' uses a non-parametric randomization test to get a Monte-Carlo estimate of the probability, +% 'analytic' uses a parametric test that results in analytic probability, +% 'glm' uses a general linear model approach, +% 'stats' uses a parametric test from the Matlab statistics toolbox, +% 'parametric' uses the Matlab statistics toolbox (very similar to 'stats'), +% 'randomization' uses randomization of the data prior to source reconstruction, +% 'randcluster' uses randomization of the data prior to source reconstruction +% in combination with spatial clusters. +% +% You can restrict the statistical analysis to regions of interest (ROIs) +% or to the average value inside ROIs using the following options: +% cfg.atlas = filename of the atlas +% cfg.roi = string or cell of strings, region(s) of interest from anatomical atlas +% cfg.avgoverroi = 'yes' or 'no' (default = 'no') +% cfg.hemisphere = 'left', 'right', 'both', 'combined', specifying this is +% required when averaging over regions +% cfg.inputcoord = 'mni' or 'tal', the coordinate system in which your source +% reconstruction is expressed +% +% The other cfg options depend on the method that you select. You +% should read the help of the respective subfunction STATISTICS_XXX +% for the corresponding configuration options and for a detailed +% explanation of each method. +% +% +% See also FT_SOURCEANALYSIS, FT_SOURCEDESCRIPTIVES, FT_SOURCEGRANDAVERAGE -% this part is variable -prefix = 'ft_'; +% Undocumented local options: +% cfg.statistic -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +% Copyright (C) 2005-2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_sourcestatistics.m 1024 2010-05-04 08:21:07Z jansch $ + +fieldtripdefs + +% this wrapper should be compatible with the already existing statistical +% functions that only work for source input data + +if ~isfield(cfg, 'implementation'), cfg.implementation = 'old'; end + +if strcmp(cfg.implementation, 'old'), + + %-------------------------------- + % use the original implementation + + % check if the input data is valid for this function + for i=1:length(varargin) + if isfield(cfg, 'roi') && ~isempty(cfg.roi) + varargin{i} = checkdata(varargin{i}, 'datatype', 'source', 'feedback', 'no', 'inside', 'index'); + else + varargin{i} = checkdata(varargin{i}, 'datatype', {'source', 'volume'}, 'feedback', 'no', 'inside', 'index'); + end + end + + if isfield(cfg, 'method') + % call the appropriate subfunction + if (strcmp(cfg.method, 'zero-baseline') || ... + strcmp(cfg.method, 'nai') || ... + strcmp(cfg.method, 'pseudo-t') || ... + strcmp(cfg.method, 'difference') || ... + strcmp(cfg.method, 'anova1') || ... + strcmp(cfg.method, 'kruskalwallis')) + % these are all statistical methods that are implemented in the old SOURCESTATISTICS_PARAMETRIC subfunction + cfg.statistic = cfg.method; + cfg.method = 'parametric'; + elseif strcmp(cfg.method, 'randomization') + cfg.method = 'randomization'; + elseif strcmp(cfg.method, 'randcluster') + cfg.method = 'randcluster'; + end + end + + if strcmp(cfg.method, 'parametric') + % use the source-specific statistical subfunction + stat = sourcestatistics_parametric(cfg, varargin{:}); + elseif strcmp(cfg.method, 'randomization') + % use the source-specific statistical subfunction + stat = sourcestatistics_randomization(cfg, varargin{:}); + elseif strcmp(cfg.method, 'randcluster') + % use the source-specific statistical subfunction + stat = sourcestatistics_randcluster(cfg, varargin{:}); + else + [stat, cfg] = statistics_wrapper(cfg, varargin{:}); + end + + % add version information to the configuration + try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); + catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); + end + cfg.version.id = '$Id: ft_sourcestatistics.m 1024 2010-05-04 08:21:07Z jansch $'; + + % remember the configuration of the input data + cfg.previous = []; + for i=1:length(varargin) + if isfield(varargin{i}, 'cfg') + cfg.previous{i} = varargin{i}.cfg; + else + cfg.previous{i} = []; + end + end + + % remember the exact configuration details + stat.cfg = cfg; + +elseif strcmp(cfg.implementation, 'new') + + %--------------------------- + % use the new implementation + issource = datatype(varargin{1}, 'source'); + isvolume = datatype(varargin{1}, 'volume'); + + % check if the input data is valid for this function + for i=1:length(varargin) + if isfield(cfg, 'roi') && ~isempty(cfg.roi) + % FIXME implement roi-based statistics for the new implementation + % (code is copied over from the old implementation but not yet tested + error('roi based sourcestatistics is not yet implemented for the new implementation'); + varargin{i} = checkdata(varargin{i}, 'datatype', 'source', 'feedback', 'no', 'inside', 'index'); + else + varargin{i} = checkdata(varargin{i}, 'datatype', {'source', 'volume'}, 'feedback', 'no', 'inside', 'index', 'sourcerepresentation', 'new'); + if strcmp(cfg.parameter, 'pow') && ~isfield(varargin{i}, 'pow'), + varargin{i} = checkdata(varargin{i}, 'sourcerepresentation', 'new', 'haspow', 'yes'); + end + end + end + + if isfield(cfg, 'method') + % call the appropriate subfunction + if (strcmp(cfg.method, 'zero-baseline') || ... + strcmp(cfg.method, 'nai') || ... + strcmp(cfg.method, 'pseudo-t') || ... + strcmp(cfg.method, 'difference') || ... + strcmp(cfg.method, 'anova1') || ... + strcmp(cfg.method, 'kruskalwallis')) + % these are all statistical methods that are implemented in the old SOURCESTATISTICS_PARAMETRIC subfunction + cfg.statistic = cfg.method; + cfg.method = 'parametric'; + elseif strcmp(cfg.method, 'randomization') + cfg.method = 'randomization'; + elseif strcmp(cfg.method, 'randcluster') + cfg.method = 'randcluster'; + end + end + + if ismember('cfg.method', {'parametric' 'randomization' 'randcluster'}), + % FIXME only supported for old-style source representation + for i = 1:numel(varargin) + varargin{i} = checkdata(varargin{i}, 'sourcerepresentation', 'old'); + end + + if exist(['statistics_',cfg.method]), + statmethod = str2func(['statistics_' cfg.method]); + else + error(sprintf('could not find the corresponding function for cfg.method="%s"\n', cfg.method)); + end + stat = statmethod(cfg, varargin{:}); + + else + + % convert representation of input data to new style + for i = 1:numel(varargin) + varargin{i} = checkdata(varargin{i}, 'sourcerepresentation', 'new'); + end + + % check the input configuration + cfg = checkconfig(cfg, 'renamed', {'approach', 'method'}); + cfg = checkconfig(cfg, 'required', {'method', 'parameter'}); + cfg = checkconfig(cfg, 'forbidden', {'transform'}); + + % set the defaults + if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end + if ~isfield(cfg, 'latency'), cfg.latency = 'all'; end + if ~isfield(cfg, 'frequency'), cfg.frequency = 'all'; end + if ~isfield(cfg, 'roi'), cfg.roi = []; end + if ~isfield(cfg, 'avgoverchan'), cfg.avgoverchan = 'no'; end + if ~isfield(cfg, 'avgovertime'), cfg.avgovertime = 'no'; end + if ~isfield(cfg, 'avgoverfreq'), cfg.avgoverfreq = 'no'; end + if ~isfield(cfg, 'avgoverroi'), cfg.avgoverroi = 'no'; end + + % test that all source inputs have the same dimensions and are spatially aligned + for i=2:length(varargin) + if isfield(varargin{1}, 'dim') && (numel(varargin{i}.dim)~=length(varargin{1}.dim) || ~all(varargin{i}.dim==varargin{1}.dim)) + error('dimensions of the source reconstructions do not match, use VOLUMENORMALISE first'); + end + if isfield(varargin{1}, 'pos') && (numel(varargin{i}.pos(:))~=numel(varargin{1}.pos(:)) || ~all(varargin{i}.pos(:)==varargin{1}.pos(:))) + error('grid locations of the source reconstructions do not match, use VOLUMENORMALISE first'); + end + end + + Nsource = length(varargin); + Nvoxel = length(varargin{1}.inside) + length(varargin{1}.outside); + + %FIXME selectdata should be used for the subselection + %FIXME selectdata has to be adjusted to work with new style source data + %if isfield(varargin{1}, 'freq') && ~strcmp(cfg.frequency, 'all'), + % for i=1:length(varargin) + % varargin{i} = selectdata(varargin{i}, 'foilim', cfg.frequency, ... + % 'avgoverfreq', cfg.avgoverfreq); + % end + %end + + % this part contains the functionality of the old statistics_wrapper + % with source data in the input + if ~isempty(cfg.roi) + if ischar(cfg.roi) + cfg.roi = {cfg.roi}; + end + % the source representation should specify the position of each voxel in MNI coordinates + x = varargin{1}.pos(:,1); % this is from left (negative) to right (positive) + % determine the mask to restrict the subsequent analysis + % process each of the ROIs, and optionally also left and/or right seperately + roimask = {}; + roilabel = {}; + for i=1:length(cfg.roi) + tmpcfg.roi = cfg.roi{i}; + tmpcfg.inputcoord = cfg.inputcoord; + tmpcfg.atlas = cfg.atlas; + tmp = ft_volumelookup(tmpcfg, varargin{1}); + if strcmp(cfg.avgoverroi, 'no') && ~isfield(cfg, 'hemisphere') + % no reason to deal with seperated left/right hemispheres + cfg.hemisphere = 'combined'; + end + + if strcmp(cfg.hemisphere, 'left') + tmp(x>=0) = 0; % exclude the right hemisphere + roimask{end+1} = tmp; + roilabel{end+1} = ['Left ' cfg.roi{i}]; + + elseif strcmp(cfg.hemisphere, 'right') + tmp(x<=0) = 0; % exclude the right hemisphere + roimask{end+1} = tmp; + roilabel{end+1} = ['Right ' cfg.roi{i}]; + + elseif strcmp(cfg.hemisphere, 'both') + % deal seperately with the voxels on the left and right side of the brain + tmpL = tmp; tmpL(x>=0) = 0; % exclude the right hemisphere + tmpR = tmp; tmpR(x<=0) = 0; % exclude the left hemisphere + roimask{end+1} = tmpL; + roimask{end+1} = tmpR; + roilabel{end+1} = ['Left ' cfg.roi{i}]; + roilabel{end+1} = ['Right ' cfg.roi{i}]; + clear tmpL tmpR + + elseif strcmp(cfg.hemisphere, 'combined') + % all voxels of the ROI can be combined + roimask{end+1} = tmp; + roilabel{end+1} = cfg.roi{i}; + + else + error('incorrect specification of cfg.hemisphere'); + end + clear tmp + end % for each roi + + % note that avgoverroi=yes is implemented differently at a later stage + % avgoverroi=no is implemented using the inside/outside mask + if strcmp(cfg.avgoverroi, 'no') + for i=2:length(roimask) + % combine them all in the first mask + roimask{1} = roimask{1} | roimask{i}; + end + roimask = roimask{1}; % only keep the combined mask + % the source representation should have an inside and outside vector containing indices + sel = find(~roimask); + varargin{1}.inside = setdiff(varargin{1}.inside, sel); + varargin{1}.outside = union(varargin{1}.outside, sel); + clear roimask roilabel + end % if avgoverroi=no + end % if ~isempty cfg.roi + + % get the required source level data + [dat, cfg] = getfunctional(cfg, varargin{:}); + + % note that avgoverroi=no is implemented differently at an earlier stage + if strcmp(cfg.avgoverroi, 'yes') + tmp = zeros(length(roimask), size(dat,2)); + for i=1:length(roimask) + % the data only reflects those points that are inside the brain, + % the atlas-based mask reflects points inside and outside the brain + roi = roimask{i}(varargin{1}.inside); + tmp(i,:) = mean(dat(roi,:), 1); + end + % replace the original data with the average over each ROI + dat = tmp; + clear tmp roi roimask + % remember the ROIs + cfg.dimord = 'roi'; + end + end + + %get the design from the information in the cfg and data + if ~isfield(cfg, 'design'), + cfg.design = data.design; + cfg = prepare_design(cfg); + end + + if size(cfg.design, 2)~=size(dat, 2) + cfg.design = transpose(cfg.design); + end + + % determine the function handle to the intermediate-level statistics function + if exist(['statistics_' cfg.method]) + statmethod = str2func(['statistics_' cfg.method]); + else + error(sprintf('could not find the corresponding function for cfg.method="%s"\n', cfg.method)); + end + fprintf('using "%s" for the statistical testing\n', func2str(statmethod)); + + % check that the design completely describes the data + if size(dat,2) ~= size(cfg.design,2) + error('the size of the design matrix does not match the number of observations in the data'); + end + + % determine the number of output arguments + try + % the nargout function in Matlab 6.5 and older does not work on function handles + num = nargout(statmethod); + catch + num = 1; + end + + % perform the statistical test + if strcmp(func2str(statmethod),'statistics_montecarlo') + % because statistics_montecarlo (or to be precise, clusterstat) + % requires to know whether it is getting source data, + % the following (ugly) work around is necessary + if num>1 + [stat, cfg] = statmethod(cfg, dat, cfg.design, 'issource', 1); + else + [stat] = statmethod(cfg, dat, cfg.design, 'issource', 1); + end + else + if num>1 + [stat, cfg] = statmethod(cfg, dat, cfg.design); + else + [stat] = statmethod(cfg, dat, cfg.design); + end + end + + if isstruct(stat) + % the statistical output contains multiple elements, e.g. F-value, beta-weights and probability + statfield = fieldnames(stat); + else + % only the probability was returned as a single matrix, reformat into a structure + dum = stat; stat = []; % this prevents a Matlab warning that appears from release 7.0.4 onwards + stat.prob = dum; + statfield = fieldnames(stat); + end + + % add descriptive information to the output and rehape into the input format + if isempty(cfg.roi) || strcmp(cfg.avgoverroi, 'no') + % remember the definition of the volume, assume that they are identical for all input arguments + try, stat.dim = varargin{1}.dim; end + try, stat.xgrid = varargin{1}.xgrid; end + try, stat.ygrid = varargin{1}.ygrid; end + try, stat.zgrid = varargin{1}.zgrid; end + try, stat.inside = varargin{1}.inside; end + try, stat.outside = varargin{1}.outside; end + try, stat.pos = varargin{1}.pos; end + try, stat.transform = varargin{1}.transform; end + else + stat.inside = 1:length(roilabel); + stat.outside = []; + stat.label = roilabel(:); + end + + % additional descriptive fields + hasfreq = strcmp(cfg.avgoverfreq, 'no') && isfield(varargin{1},'freq'); + hastime = strcmp(cfg.avgovertime, 'no') && isfield(varargin{1},'time'); + stat.dimord = 'pos_'; + + if hasfreq, + stat.dimord = [stat.dimord, 'freq_']; + stat.freq = varargin{1}.freq; + nfreq = numel(varargin{1}.freq); + else + nfreq = 1; + end + if hastime, + stat.dimord = [stat.dimord, 'time_']; + stat.time = varargin{1}.time; + ntime = numel(varargin{1}.time); + else + ntime = 1; + end + stat.dimord = stat.dimord(1:end-1); + + if issource, + if hasfreq, + newdim = [size(stat.pos,1) nfreq ntime]; + else + newdim = [size(stat.pos,1) ntime]; + end + elseif isvolume, + if hasfreq, + newdim = [stat.dim nfreq ntime]; + else + newdim = [stat.dim ntime]; + end + end + + for i=1:length(statfield) + tmp = getsubfield(stat, statfield{i}); + tmp2 = []; + ntmp = numel(tmp); + if hasfreq, + tmpdim = [ntmp/(nfreq*ntime) nfreq ntime]; + else + tmpdim = [ntmp/ntime ntime]; + end + if isfield(varargin{1}, 'inside') && numel(tmp)==nfreq*ntime*length(varargin{1}.inside) + % the statistic was only computed on voxels that are inside the brain + % sort the inside and outside voxels back into their original place + if islogical(tmp) + if hasfreq, + tmp2 = logical(zeros(prod(varargin{1}.dim),nfreq,ntime)); + tmp2(varargin{1}.inside, 1:nfreq, 1:ntime) = reshape(tmp, [ntmp/(nfreq*ntime) nfreq ntime]); + else + tmp2 = logical(zeros(prod(varargin{1}.dim),nfreq,ntime)); + tmp2(varargin{1}.inside, 1:nfreq, 1:ntime) = reshape(tmp, [ntmp/ntime ntime]); + end + else + if hasfreq, + tmp2 = zeros(prod(varargin{1}.dim),nfreq,ntime)+nan; + tmp2(varargin{1}.inside, 1:nfreq, 1:ntime) = reshape(tmp, [ntmp/(nfreq*ntime) nfreq ntime]); + else + tmp2 = zeros(prod(varargin{1}.dim),nfreq,ntime)+nan; + tmp2(varargin{1}.inside, 1:nfreq, 1:ntime) = reshape(tmp, [ntmp/ntime ntime]); + end + end + end + if numel(tmp2)==prod(newdim) + % reshape the statistical volumes into the original format + stat = setsubfield(stat, statfield{i}, reshape(tmp2, newdim)); + end + end + + % add version information to the configuration + try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); + catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); + end + cfg.version.id = '$Id: ft_sourcestatistics.m 1024 2010-05-04 08:21:07Z jansch $'; + + % remember the configuration of the input data + cfg.previous = []; + for i=1:length(varargin) + if isfield(varargin{i}, 'cfg') + cfg.previous{i} = varargin{i}.cfg; + else + cfg.previous{i} = []; + end + end + + % remember the exact configuration details + stat.cfg = cfg; + +else + error('cfg.implementation can be only old or new'); +end + +%----------------------------------------------------- +%subfunction to extract functional data from the input +%and convert it into a 2D representation +function [dat, cfg] = getfunctional(cfg, varargin) + +%FIXME think of how this generalizes to volumetric data (boolean inside etc) +Nsource = numel(varargin); +Nvox = size(varargin{1}.pos, 1); +inside = varargin{1}.inside; +Ninside = numel(inside); + +dimord = varargin{1}.([cfg.parameter,'dimord']); +dimtok = tokenize(dimord, '_'); + +%check whether the requested parameter is represented as cell-array +x1 = strfind(dimord, '{'); +x2 = strfind(dimord, '}'); +if ~isempty(x1) && ~isempty(x2) + cellparam = 1; + cellsiz = size(varargin{1}.(cfg.parameter)); + %this only explicitly keeps the first singleton dimension + %the last to be removed + cellsiz(find(cellsiz(2:end)==1)+1) = []; + cellsiz(cellsiz==Nvox) = Ninside; +else + cellparam = 0; +end + +%check whether there are single observations/subjects in the data +rptdim = ~cellfun(@isempty, strfind(dimtok, 'rpt')) | ~cellfun(@isempty, strfind(dimtok, 'subj')); +hasrpt = sum(rptdim); + +if hasrpt && Nsource>1, + error('only a single input with multiple observations or multiple inputs with a single observation are supported'); +end + +if hasrpt, + if cellparam, + tmpsiz = [cellsiz size(varargin{1}.(cfg.parameter){inside(1)})]; + tmp = zeros(tmpsiz); + %FIXME what about volumetric data? + for k = 1:Ninside + tmp(k,:,:,:,:,:) = varargin{1}.(cfg.parameter){inside(k)}; + end + %tmp = cell2mat(varargin{1}.(cfg.parameter)(inside,:,:,:,:)); + else + tmp = varargin{1}.(cfg.parameter)(inside,:,:,:,:); + end + + if numel(rptdim)==1, + rptdim = [rptdim 0]; + end + %put the repetition dimension to the last dimension + tmp = permute(tmp, [find(rptdim==0) find(rptdim==1)]); + + %reshape the data to 2D + siz = size(tmp); + dat = reshape(tmp, [prod(siz(1:end-1)) siz(end)]); + +else + + for k = 1:Nsource + %check for cell-array representation in the input data + %FIXME this assumes positions to be in the first dimension always + %FIXME what about volumetric dadta + if cellparam + tmp = cell2mat(varargin{k}.(cfg.parameter)(inside,:,:,:,:)); + else + tmp = varargin{k}.(cfg.parameter)(inside,:,:,:,:); + end + + %allocate memory + if k==1, dat = zeros(numel(tmp), Nsource); end + + %reshape the data + siz = size(tmp); + dat(:,k) = tmp(:); + end +end +cfg.dim = varargin{1}.dim; +cfg.inside = varargin{1}.inside; %FIXME take the intersection between all inputs +cfg.dimord = 'voxel'; +cfg.origdim = [cfg.dim siz(2:end-1)]; diff --git a/external/fieldtrip/ft_sourcewrite.m b/external/fieldtrip/ft_sourcewrite.m index b84b9b2..3519a86 100644 --- a/external/fieldtrip/ft_sourcewrite.m +++ b/external/fieldtrip/ft_sourcewrite.m @@ -1,11 +1,32 @@ -function varargout = funname(varargin); +function ft_sourcewrite(cfg, volume) -% this is a SPM wrapper around a FieldTrip function +% FT_VOLUMEWRITE exports source analysis results to an Analyze MRI file +% that can subsequently be read into BrainVoyager or MRIcro +% +% Warning: FT_NORMALISEVOLUME has been renamed to FT_VOLUMENORMALISE +% Warning: backward compatibility will be removed in the future -% this part is variable -prefix = 'ft_'; +% Copyright (C) 2005-2006, F.C. Donders Centre +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_sourcewrite.m 948 2010-04-21 18:02:21Z roboos $ -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +warning('SOURCEWRITE has been renamed to VOLUMEWRITE'); +warning('backward compatibility will be removed in the future'); + +ft_volumewrite(cfg, volume); diff --git a/external/fieldtrip/ft_spikeanalysis.m b/external/fieldtrip/ft_spikeanalysis.m new file mode 100644 index 0000000..a364aeb --- /dev/null +++ b/external/fieldtrip/ft_spikeanalysis.m @@ -0,0 +1,220 @@ +function [spike] = ft_spikeanalysis(cfg, data); + +% FT_SPIKEANALYSIS performs analysis on spike data +% +% Use as +% [spike] = ft_spikeanalysis(cfg, data); +% +% The following configuration options are supported +% cfg.method = 'rate' (default), or 'spikephase' +% +% in combination with cfg.method = 'rate', +% cfg.toi = the spike-rate is computed in a window surrounding the time-points in cfg.toi +% cfg.timwin = window width +% +% if cfg.toi and cfg.timwin are not specified, the average rate across each trial is computed. +% +% in combination with cfg.method = 'spikephase' +% cfg.channelcmb = cell-array, see FT_CHANNELCOMBINATION +% cfg.bpfilter = 'no' or 'yes' bandpass filter +% cfg.bpfreq = bandpass frequency range, specified as [low high] in Hz +% cfg.bpfiltord = bandpass filter order + +% Undocumented local options: +% cfg.bpfilttype +% cfg.channel +% cfg.foi +% cfg.keeptrials +% cfg.output +% cfg.pad +% cfg.previous +% cfg.taper +% cfg.tapsmofrq +% cfg.version +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_spikeanalysis.m 1247 2010-06-17 12:07:18Z timeng $ + +fieldtripdefs + +% set the defaults +if ~isfield(cfg, 'method'), cfg.method = 'rate'; end +if ~isfield(cfg, 'channelcmb'), cfg.channelcmb = {'all', 'all'}; end +if ~isfield(cfg, 'bpfilter'), cfg.bpfilter = 'yes'; end +if ~isfield(cfg, 'bpfiltord'), cfg.bpfiltord = 4; end +if ~isfield(cfg, 'bpfilttype'), cfg.bpfilttype = 'but'; end +if ~isfield(cfg, 'bpfreq'), cfg.bpfreq = [30 90]; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +% load optional given inputfile as data +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + end +end + +if strcmp(cfg.method, 'rate'), + ntrials = length(data.trial); + nchans = length(data.label); + spikechan = zeros(nchans,1); + for i=1:ntrials + for j=1:nchans + spikechan(j) = spikechan(j) + all(data.trial{i}(j,:)==0 | data.trial{i}(j,:)==1); + end + end + chanindx = find(spikechan==ntrials); + nchans = length(chanindx); + label = data.label(chanindx); + + if ~isfield(cfg, 'toi'), + %compute the number of spikes within each trial and normalise for the triallength + rate = zeros(ntrials, nchans); + for i=1:ntrials + rate(i, :) = data.fsample*sum(data.trial{i}(chanindx, :), 2)/size(data.trial{i},2)'; + end + + spike = []; + spike.label = label(:); + spike.rate = rate; + elseif isfield(cfg, 'toi'), + if ~isfield(cfg, 'timwin'), error('no timewindow specified'); end; + %compute the spike-rate based on the DC-bin after fourier-transformation. CAVE: the + %data should NOT be baseline corrected. + tmpcfg = []; + tmpcfg.method = 'mtmconvol'; + tmpcfg.output = 'pow'; + tmpcfg.keeptrials= 'yes'; + tmpcfg.toi = cfg.toi; + tmpcfg.t_ftimwin = cfg.timwin; + tmpcfg.tapsmofrq = nan; + tmpcfg.taper = 'rectwin'; + tmpcfg.foi = 0; + tmpcfg.channel = label; + tmpcfg.pad = 'maxperlen'; + tmpfreq = ft_freqanalysis(tmpcfg, data); + rate = sqrt(squeeze(tmpfreq.powspctrm)/2)*data.fsample; + + spike = []; + spike.label = label(:); + spike.rate = rate; + end +elseif strcmp(cfg.method, 'spikephase'), + % select the combination of spike and lfp channels to be analyzed + if isfield(cfg, 'channelcmb') + cfg.channelcmb = ft_channelcombination(cfg.channelcmb, data.label); + end + + % check whether the selection of channels is valid + ntrials = length(data.trial); + nchans = length(data.label); + spikechan = zeros(nchans,1); + for i=1:ntrials + for j=1:nchans + spikechan(j) = spikechan(j) + all(data.trial{i}(j,:)==0 | data.trial{i}(j,:)==1); + end + end + spikechan = spikechan==ntrials; + cmbsel = ones(size(cfg.channelcmb,1), 1); + for i=1:size(cfg.channelcmb,1) + cmbsel(i) = spikechan(strmatch(cfg.channelcmb{i,1}, data.label))==1 & ... + spikechan(strmatch(cfg.channelcmb{i,2}, data.label))==0; + end + + % select only the valid combinations + cfg.channelcmb = cfg.channelcmb(find(cmbsel),:); + fprintf('selected %d channel combinations\n', size(cfg.channelcmb,1)); + + spksel = unique(match_str(data.label, cfg.channelcmb(:,1))); + lfpsel = unique(match_str(data.label, cfg.channelcmb(:,2))); + fprintf('selected %d spike channels\n', length(spksel)); + fprintf('selected %d lfp channels\n', length(lfpsel)); + + % allocate the output structure + for i=1:size(cfg.channelcmb,1) + spike.phase{i} = []; + spike.amplitude{i} = []; + spike.trlnum{i} = []; + end + + for lfplop=lfpsel(:)' + fprintf('processing lfp channel %s ', data.label{lfplop}); + for i=1:ntrials + % perform the bandpass filter and hilbert transform + lfp = bandpassfilter(data.trial{i}(lfplop,:), data.fsample, cfg.bpfreq, cfg.bpfiltord, cfg.bpfilttype); + lfp = hilbert(lfp); + for spklop=spksel(:)' + % find the output combination + outputcmb = find(strcmp(data.label{lfplop}, cfg.channelcmb(:,2)) & strcmp(data.label{spklop}, cfg.channelcmb(:,1))); + if isempty(outputcmb) + % this analog channel is not combined with this spike channel + continue + else + fprintf('.'); + % find all spikes in this channel and this trial + sel = find(data.trial{i}(spklop,:)); + % remember the instantaneous phase and amplitude of the lfp channel + spike.phase{outputcmb} = [spike.phase{outputcmb} phase(lfp(sel)) ]; + spike.amplitude{outputcmb} = [spike.amplitude{outputcmb} abs(lfp(sel)) ]; + % remember the trial number in which the spike occurred + spike.trlnum{outputcmb} = [spike.trlnum{outputcmb} i*ones(1,length(sel))]; + end + end + end + fprintf('\n'); + end + + % wrap the phase estimate between 0 and 2*pi + for i=1:size(cfg.channelcmb,1) + tmp = spike.phase{i}; + tmp = rem(tmp, 2*pi); + tmp(tmp<0) = tmp(tmp<0) + 2*pi; + spike.phase{i} = tmp; + end + + % append the other information to the output + spike.channelcmb = cfg.channelcmb; +end + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_spikeanalysis.m 1247 2010-06-17 12:07:18Z timeng $'; +% remember the configuration details of the input data +try, cfg.previous = data.cfg; end +% remember the exact configuration details in the output +spike.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', spike); % use the variable name "data" in the output file +end diff --git a/external/fieldtrip/ft_spikedetection.m b/external/fieldtrip/ft_spikedetection.m new file mode 100644 index 0000000..bb84a99 --- /dev/null +++ b/external/fieldtrip/ft_spikedetection.m @@ -0,0 +1,479 @@ +function [cfg, spike] = ft_spikedetection(cfg) + +% FT_SPIKEDETECTION +% +% Use as +% cfg = ft_spikedetection(cfg) +% +% The configuration options can contain +% cfg.dataset = string with the input dataset +% cfg.output = string with the output dataset (default is determined automatic) +% cfg.dataformat = string with the output dataset format, see FT_WRITE_FCDC_SPIKE +% cfg.method = string with the method to use, can be 'all', 'zthresh', 'ztrig', 'flank' +% cfg.interactive = 'yes' or 'no' +% cfg.timestampdefinition = 'orig' or 'sample' +% +% The default is to process the full dataset. You can select a latency range with +% cfg.latency = [begin end], default is [0 inf] +% or you can specify multiple latency segments with +% cfg.latency = [b1 e1; b2 e2; ...] +% +% Specific settings for the zthresh spike detection method are +% cfg.zthresh.neg = negative threshold, e.g. -3 +% cfg.zthresh.pos = positive threshold, e.g. 3 +% cfg.zthresh.offset = number of samples before peak (default = 16) +% cfg.zthresh.mindist = mininum distance in samples between detected peaks +% +% Specific settings for the flank spike detection method are +% cfg.flank.value = positive or negative threshold +% cfg.flank.offset = number of samples before peak +% cfg.flank.ztransform = 'yes' or 'no' +% cfg.flank.mindist = mininum distance in samples between detected peaks +% +% Furthermore, the configuration can contain options for preprocessing +% cfg.preproc.lpfilter = 'no' or 'yes' lowpass filter +% cfg.preproc.hpfilter = 'no' or 'yes' highpass filter +% cfg.preproc.bpfilter = 'no' or 'yes' bandpass filter +% cfg.preproc.lnfilter = 'no' or 'yes' line noise removal using notch filter +% cfg.preproc.dftfilter = 'no' or 'yes' line noise removal using discrete fourier transform +% cfg.preproc.medianfilter = 'no' or 'yes' jump preserving median filter +% cfg.preproc.lpfreq = lowpass frequency in Hz +% cfg.preproc.hpfreq = highpass frequency in Hz +% cfg.preproc.bpfreq = bandpass frequency range, specified as [low high] in Hz +% cfg.preproc.lnfreq = line noise frequency in Hz, default 50Hz +% cfg.preproc.lpfiltord = lowpass filter order +% cfg.preproc.hpfiltord = highpass filter order +% cfg.preproc.bpfiltord = bandpass filter order +% cfg.preproc.lnfiltord = line noise notch filter order +% cfg.preproc.medianfiltord = length of median filter +% cfg.preproc.lpfilttype = digital filter type, 'but' (default) or 'fir' +% cfg.preproc.hpfilttype = digital filter type, 'but' (default) or 'fir' +% cfg.preproc.bpfilttype = digital filter type, 'but' (default) or 'fir' +% cfg.preproc.lpfiltdir = filter direction, 'twopass' (default) or 'onepass' +% cfg.preproc.hpfiltdir = filter direction, 'twopass' (default) or 'onepass' +% cfg.preproc.bpfiltdir = filter direction, 'twopass' (default) or 'onepass' +% cfg.preproc.detrend = 'no' or 'yes' +% cfg.preproc.blc = 'no' or 'yes' +% cfg.preproc.blcwindow = [begin end] in seconds, the default is the complete trial +% cfg.preproc.hilbert = 'no' or 'yes' +% cfg.preproc.rectify = 'no' or 'yes' + +% Copyright (C) 2005-2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_spikedetection.m 1043 2010-05-06 10:27:19Z timeng $ + +fieldtripdefs +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +% set the general defaults +if ~isfield(cfg, 'dataset'), cfg.dataset = []; end +if ~isfield(cfg, 'output'), cfg.output = []; end +if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end +if ~isfield(cfg, 'channelprefix'), cfg.channelprefix = []; end +if ~isfield(cfg, 'latency'), cfg.latency = [0 inf]; end +if ~isfield(cfg, 'dataformat'), cfg.dataformat = []; end +if ~isfield(cfg, 'headerformat'), cfg.headerformat = []; end +% set the specific defaults +if ~isfield(cfg, 'method'), cfg.method = 'zthresh'; end +if ~isfield(cfg, 'adjustselection'), cfg.adjustselection = 'yes'; end +if ~isfield(cfg, 'interactive'), cfg.interactive = 'no'; end +if ~isfield(cfg, 'chanvals'), cfg.chanvals = []; end + +% set the defaults for the various spike detection methods +switch cfg.method + case 'all' + if ~isfield(cfg, 'all'), cfg.all = []; end + case 'zthresh' + if ~isfield(cfg, 'zthresh'), cfg.zthresh = []; end + if ~isfield(cfg.zthresh, 'neg'), cfg.zthresh.neg = -3; end + if ~isfield(cfg.zthresh, 'pos'), cfg.zthresh.pos = 3; end + if ~isfield(cfg.zthresh, 'offset'), cfg.zthresh.offset = -16; end % in samples + if ~isfield(cfg.zthresh, 'mindist'), cfg.zthresh.mindist = 0; end % in samples + case 'flank' + if ~isfield(cfg, 'flank'), cfg.flank = []; end + if ~isfield(cfg.flank, 'ztransform'), cfg.flank.ztransform = 'yes'; end + if ~isfield(cfg.flank, 'value'), cfg.flank.value = 1.5; end % trigger threshold value + if ~isfield(cfg.flank, 'offset'), cfg.flank.offset = 6; end % in samples + if ~isfield(cfg.flank, 'mindist'), cfg.flank.mindist = 0; end % in samples + otherwise + error('unsupported option for cfg.method'); +end + +% ensure that the preproc specific options are located in the preproc substructure +cfg = checkconfig(cfg, 'createsubcfg', {'preproc'}); + +status = mkdir(cfg.output); +if ~status + error(sprintf('error creating spike output dataset %s', cfg.output)); +end + +% read the header of the completete dataset +hdr = ft_read_header(cfg.dataset, 'headerformat', cfg.headerformat); +cfg.channel = ft_channelselection(cfg.channel, hdr.label); +chansel = match_str(hdr.label, cfg.channel); + +if strcmp(cfg.timestampdefinition, 'sample') + % the default would be to keep the original definition of timestamps as determined from looking at the file + % here the definition of timestamps is changed to correspond with samples at the original sampling rate + hdr.TimeStampPerSample = 1; + hdr.FirstTimeStamp = 1; + hdr.LastTimeStamp = hdr.nSamples*hdr.nTrials; +end + +if hdr.nSamples<1 + error('the input dataset contains no samples'); +elseif length(chansel)<1 + error('the input selection contains no channels'); +end + +% give some feedback, based on the complete data +fprintf('data contains %10d channels\n', hdr.nChans); +fprintf('selected %10d channels\n', length(chansel)); +numsample = []; +numsegment = size(cfg.latency,1); +for j=1:numsegment + begsample(j) = max(round(cfg.latency(j,1) * hdr.Fs + 1), 1); + endsample(j) = min(round(cfg.latency(j,2) * hdr.Fs ), hdr.nSamples); + numsample(j) = endsample(j) - begsample(j) + 1; + cfg.latency(j,1) = (begsample(j)-1)/hdr.Fs; + cfg.latency(j,2) = (endsample(j) )/hdr.Fs; +end +numsample = sum(numsample); +fprintf('data contains %10d samples\n', hdr.nSamples); +fprintf('selected %10d samples in %d segments\n', numsample, numsegment); + +s = floor(hdr.nSamples ./ hdr.Fs); +m = floor(s/60); +h = floor(m/60); +m = m - 60*h; +s = s - 60*m - 60*60*h; +fprintf('duration of data %02dh:%02dm:%02ds\n', h, m, s); + +s = floor(numsample ./ hdr.Fs); +m = floor(s/60); +h = floor(m/60); +m = m - 60*h; +s = s - 60*m - 60*60*h; +fprintf('duration of selection %02dh:%02dm:%02ds\n', h, m, s); + +fprintf('estimated memory usage %d MB\n', round((numsample*(8+8+2))/(1024^2))); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% process each channel separetely +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +for i=chansel(:)' + fprintf('processing channel %d, ''%s''\n', i, hdr.label{i}); + + % remain in the interactive phase as long as the user desires + % the interactive loop is also used once when imediately writing to file + runloop = true; + newdata = true; + + while runloop + % the loop is used once when writing to file, or multiple times for interactive use + runloop = false; + + % reading and filtering may be repeatedly done if the user interactively specified another latency selection + if newdata + fprintf('++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n'); + numsegment = size(cfg.latency,1); + clear begsample endsample numsample + for j=1:numsegment + begsample(j) = max(round(cfg.latency(j,1) * hdr.Fs + 1), 1); + endsample(j) = min(round(cfg.latency(j,2) * hdr.Fs ), hdr.nSamples); + numsample(j) = endsample(j) - begsample(j) + 1; + cfg.latency(j,1) = (begsample(j)-1)/hdr.Fs; + cfg.latency(j,2) = (endsample(j) )/hdr.Fs; + end + % read from a single channel and concatenate the segments into one vector + org = zeros(1,sum(numsample)); + for j=1:numsegment + fprintf('reading channel %s, latency from %f to %f\n', hdr.label{i}, cfg.latency(j,1), cfg.latency(j,2)); + buf = ft_read_data(cfg.dataset, 'header', hdr, 'begsample', begsample(j), 'endsample', endsample(j), 'chanindx', i, 'dataformat', cfg.dataformat); + if j==1 + begsegment = 1; + endsegment = numsample(j); + else + begsegment = sum(numsample(1:j-1)) + 1; + endsegment = sum(numsample(1:j )) ; + end + % concatenate the data into one large vector + org(begsegment:endsegment) = buf; + clear buf; + end + % apply preprocessing + fprintf('applying preprocessing options\n'); + dat = preproc(org, hdr.label(i), hdr.Fs, cfg.preproc); + end % if newdata + + peaks = []; + + % this while loop is used to automatically adjust the spike threshold + % if too few/ too many waveforms were selected + % it will break out of the while loop at the end + numadjustment = 1; + while (1) + + switch cfg.method + case 'all' + % place a spike marker at each 32 samples in the signal + % this makes a lot of waveforms that together reconstruct the complete continuous data + for j=1:32:(length(dat)-32) + peaks = [peaks j]; + end + + case 'zthresh' + % do peak detection on z-transformed signal + zdat = (dat-mean(dat))./std(dat); + if ~isinf(cfg.zthresh.neg) + % mindist is expressed in samples rather than sec + dum = peakdetect3(-zdat, -cfg.zthresh.neg, cfg.zthresh.mindist); + peaks = [peaks dum]; + end + if ~isinf(cfg.zthresh.pos) + % mindist is expressed in samples rather than sec + dum = peakdetect3( zdat, cfg.zthresh.pos, cfg.zthresh.mindist); + peaks = [peaks dum]; + end + % the mindist is not honored for spikes followed immediately by a spike of the other sign + peaks = sort(peaks); + % the begin of each waveform is shifted, to ensure that the spike is in the middle + peaks = peaks - cfg.zthresh.offset; + % ensure that no spikes are found within the first and last segment of the data + % since it is not possible to extract complete waveforms there + peaks(find(peaks<32)) = []; + peaks(find((length(dat)-peaks)<32)) = []; + + % --- store the thres val for current channnel + cfg.chanvals(find(chansel==i),1:3) = [cfg.zthresh.neg cfg.zthresh.pos cfg.zthresh.mindist]; + + case 'flank' + if strcmp(cfg.flank.ztransform, 'yes') + zdat = (dat-mean(dat))./std(dat); + else + zdat = dat; + end + if cfg.flank.value>0 + peaks = find(diff(zdat>cfg.flank.value)==1); + elseif cfg.flank.value<0 + peaks = find(diff(zdatcfg.flank.mindist); + end + + % the flanks are shifted by one sample due to the diff + peaks = peaks + 1; + % the begin of each waveform is shifted, to ensure that the spike is in the middle + peaks = peaks - cfg.flank.offset; + % ensure that no spikes are found within the first and last segment of the data + % since it is not possible to extract complete waveforms there + peaks(find(peaks<32)) = []; + peaks(find((length(dat)-peaks)<32)) = []; + + % --- store the thres val for current channnel + cfg.chanvals(find(chansel==i),1:3) = [cfg.flank.value NaN cfg.flank.mindist]; + + end % cfg.method + + fprintf('detected %d (avg. rate: %.2f)', length(peaks), (length(peaks) / (length(dat)/hdr.Fs) )); + + % check that n detected spikes is "reasonable" (more than 5 + % percent, less than 80%), otherwise changes the settings + % note: 32 samples per waveform, length(dat)/32 possible waveforms, hdr.Fs + if ~strcmp(cfg.adjustselection, 'yes') + % no automatic adjustment needs to be done + break; + elseif numadjustment>10 + % do not auto-adjust more than 10 times + break; + else + adjustValue = []; + if ( (length(peaks) / (length(dat)/hdr.Fs) ) < 4) + fprintf(', less than avg. rate of 4 spikes per sec. detected.\n'); + adjustValue = 1+(numadjustment*0.1); + elseif ~strcmp(cfg.method,'all') & ( (length(peaks) / (length(dat)/hdr.Fs) ) > 600) + fprintf(', more than avg. rate of 600 spikes per sec. detected.\n'); + adjustValue = 1-(numadjustment*0.1); + else + % the detected spike rate is "reasonable", no further adjustments neccessary + break; + end + + if ~isempty(adjustValue) + maxDat = max(abs(zdat))*0.95; % the minimum threshold value to ensure thres. is in correct range + if strcmp(cfg.method,'zthresh') + cfg.zthresh.neg = max([cfg.zthresh.neg*adjustValue -maxDat]); + cfg.zthresh.pos = min([cfg.zthresh.pos*adjustValue maxDat]); + fprintf('... adjusted thresh. to %.2f / %.2f\n',cfg.zthresh.neg, cfg.zthresh.pos); + elseif strcmp(cfg.method,'flank') + cfg.flank.value = min([cfg.flank.value*adjustValue maxDat]); + fprintf('... adjusted thresh. to %.2f\n',cfg.flank.value); + end + end + numadjustment = numadjustment + 1; + end + + end % while automatic threshold adjustment + + if strcmp(cfg.interactive, 'no') + % construct a structure like this + % spike.label = 1xNchans cell-array, with channel labels + % spike.waveform = 1xNchans cell-array, each element contains a matrix (Nsamples X Nspikes), can be empty + % spike.timestamp = 1xNchans cell-array, each element contains a vector (1 X Nspikes) + % spike.unit = 1xNchans cell-array, each element contains a vector (1 X Nspikes) + % note that it only contains a single channel + + spike = []; + if isempty(cfg.channelprefix) + % the label should be a cell-array of length one + spike.label = hdr.label(i); + else + % add a prefix to the channel name + spike.label = {[cfg.channelprefix '_' hdr.label{i}]}; + end + spike.waveform = {zeros(32,length(peaks))}; % FIXME implement variable length waveforms + spike.timestamp = {zeros(1,length(peaks), class(hdr.FirstTimeStamp))}; + spike.unit = {zeros(1,length(peaks))}; + + for j=1:length(peaks) + begsmp = peaks(j); + endsmp = peaks(j) + 32 - 1; % FIXME implement a peak shift + spike.waveform{1}(:,j) = dat(begsmp:endsmp); + spike.timestamp{1}(j) = hdr.FirstTimeStamp + typecast((peaks(j)-1)*hdr.TimeStampPerSample, class(hdr.FirstTimeStamp)); + end + + % write the spike data to a new file + datafile = fullfile(cfg.output, spike.label{1}); % this is without filename extension + fprintf(', writing to %s\n', datafile); + ft_write_fcdc_spike(datafile, spike, 'dataformat', cfg.dataformat, 'fsample', hdr.Fs, 'TimeStampPerSample', hdr.TimeStampPerSample*hdr.Fs); + + % jump out of the interactive loop + runloop = false; + newdata = false; + + elseif strcmp(cfg.interactive, 'yes') + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % show the spike data on screen + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + clf + fprintf('\n\n'); + fprintf('------------------------------------------------------------\n'); + fprintf('Channel %s, detected spike rate is %d per second, ', hdr.label{i}, round(length(peaks)./(cfg.latency(2)-cfg.latency(1)))); + fprintf('change settings or press return to accept\n'); + fprintf('------------------------------------------------------------\n'); + + % use the z-transformed data + dat = zdat; + + subplot('position', [0.1 0.3 0.1 0.6]); + [hdat, hval] = hist(double(dat), 256); + h = plot(hdat, hval); + x = [0 max(hdat)*2]; + if strcmp(cfg.method, 'zthresh') + y = [cfg.zthresh.neg cfg.zthresh.neg]; + line(x, y, 'color', 'g'); + y = [cfg.zthresh.pos cfg.zthresh.pos]; + line(x, y, 'color', 'g'); + elseif strcmp(cfg.method, 'flank') + y = [cfg.flank.value cfg.flank.value]; + line(x, y, 'color', 'g'); + end + abc = axis; abc(1) = 0; abc(2) = 1.2*max(hdat); axis(abc); + + subplot('position', [0.3 0.3 0.6 0.6]); + + if size(cfg.latency,1)==1 + % create a time axis that matches the data + time = linspace(cfg.latency(1,1), cfg.latency(1,2), length(dat)); + else + % the data consiss of multiple concatenated segments, create a dummy time axis + warning('the displayed time axis does not represent real time in the recording'); + time = (0:(length(dat)-1))/hdr.Fs; + end + h = plot(time, dat); + + if strcmp(cfg.method, 'zthresh') + x = [time(1) time(end)]; + y = [cfg.zthresh.neg cfg.zthresh.neg]; + line(x, y, 'color', 'g'); + x = [time(1) time(end)]; + y = [cfg.zthresh.pos cfg.zthresh.pos]; + line(x, y, 'color', 'g'); + elseif strcmp(cfg.method, 'flank') + x = [time(1) time(end)]; + y = [cfg.flank.value cfg.flank.value]; + line(x, y, 'color', 'g'); + end + + spiketime = (peaks-1)/hdr.Fs; + spiketime = spiketime + time(1); + hold on + plot(spiketime, zeros(size(peaks)), 'r.'); + hold off + abc = axis; abc(1) = time(1); abc(2) = time(end); axis(abc); + + subplot('position', [0.3 0.1 0.6 0.1]); + plot(spiketime, zeros(size(peaks)), '.'); + abc = axis; abc(1) = time(1); abc(2) = time(end); axis(abc); + + % start with a wider figure already, this prevents manual resizing + set(gcf,'Position',[42 302 879 372],'Color','w') + + % ask for a new latency selection + tmp=(cfg.latency'); oldval = sprintf('%.1f %.1f, ',tmp(:)); + [cfg.latency, newdata] = smartinput(['cfg.latency [' oldval '] = '], cfg.latency); + runloop = newdata; + + fn = fieldnames(getfield(cfg, cfg.method)); + for k=1:length(fn) + eval(['oldval = cfg.' cfg.method '.' fn{k} ';']); + if isnumeric(oldval), oldvalinf = sprintf('%.1f',oldval); else, oldvalinf = oldval; end + [newval, changed] = smartinput(sprintf('cfg.%s.%s [%s]= ', cfg.method, fn{k},oldvalinf), oldval); + eval(['cfg.' cfg.method '.' fn{k} ' = newval;']); + runloop = (runloop | changed); + end + + if ~runloop + warning('detected spikes are not written to disk in interactive mode'); + end + + end % elseif interactive + + end % while runloop + +end % for each file + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add the version details of this function call to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_spikedetection.m 1043 2010-05-06 10:27:19Z timeng $'; diff --git a/external/fieldtrip/ft_spikedownsample.m b/external/fieldtrip/ft_spikedownsample.m new file mode 100644 index 0000000..8b0c47d --- /dev/null +++ b/external/fieldtrip/ft_spikedownsample.m @@ -0,0 +1,289 @@ +function [cfg] = ft_spikedownsample(cfg) + +% FT_SPIKEDOWNSAMPLE takes electrophysiological data that was continuoudly +% sampled at 32KHz and preprocesses and downsamples it to obtain the LFP +% data, which can subsequently be processed in more detail. +% +% Use as +% [cfg] = ft_spikedownsample(cfg) +% +% The configuration should contain +% cfg.dataset = string with the input dataset +% cfg.output = string with the output dataset (default is determined automatic) +% cfg.dataformat = string with the output dataset format, see WRITE_DATA +% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), +% see FT_CHANNELSELECTION for details +% cfg.fsample = desired sampling frequency in Hz (default = 1000) +% cfg.method = resampling method, can be 'resample', 'decimate' or 'downsample' +% cfg.timestampdefinition = 'orig' or 'sample' +% cfg.channelprefix = string, will be added to channel name, e.g. 'lfp' -> 'lfp_ncs001' (default = []) +% cfg.calibration = optional scaling factor to apply to the data to convert it in uV, see below +% +% The Neuralynx acquisition system at the FCDC in Nijmegen makes use of +% Plexon headstages which have a amplification of 20x. The data that is +% written by the Neuralynx acquisition software therefore is 20x larger +% than the true microvolt values. When operating FT_SPIKEDOWNSAMPLE on the +% *.ncs files that are recorded with the Neuralynx Cheetah software, the +% calibration should be set to 1/20. The raw dma file (*.nrd) and the +% splitted DMA files contains AD values that are not scaled in uV and +% require an additional factor of 64x. If you operate FT_SPIKEDOWNSAMPLE on +% raw dma files or on splitted DMA files, the calibration should be set to +% 1/(64*20). +% +% The default is to process the full dataset. You can select a latency range with +% cfg.latency = [begin end], default is [0 inf] +% or you can specify multiple latency segments with +% cfg.latency = [b1 e1; b2 e2; ...] +% +% Furthermore, the configuration can contain the following preprocessing options +% cfg.preproc.lpfilter = 'no' or 'yes' lowpass filter +% cfg.preproc.hpfilter = 'no' or 'yes' highpass filter +% cfg.preproc.bpfilter = 'no' or 'yes' bandpass filter +% cfg.preproc.lnfilter = 'no' or 'yes' line noise removal using notch filter +% cfg.preproc.dftfilter = 'no' or 'yes' line noise removal using discrete fourier transform +% cfg.preproc.medianfilter = 'no' or 'yes' jump preserving median filter +% cfg.preproc.lpfreq = lowpass frequency in Hz +% cfg.preproc.hpfreq = highpass frequency in Hz +% cfg.preproc.bpfreq = bandpass frequency range, specified as [low high] in Hz +% cfg.preproc.lnfreq = line noise frequency in Hz, default 50Hz +% cfg.preproc.lpfiltord = lowpass filter order +% cfg.preproc.hpfiltord = highpass filter order +% cfg.preproc.bpfiltord = bandpass filter order +% cfg.preproc.lnfiltord = line noise notch filter order +% cfg.preproc.medianfiltord = length of median filter +% cfg.preproc.lpfilttype = digital filter type, 'but' (default) or 'fir' +% cfg.preproc.hpfilttype = digital filter type, 'but' (default) or 'fir' +% cfg.preproc.bpfilttype = digital filter type, 'but' (default) or 'fir' +% cfg.preproc.lpfiltdir = filter direction, 'twopass' (default) or 'onepass' +% cfg.preproc.hpfiltdir = filter direction, 'twopass' (default) or 'onepass' +% cfg.preproc.bpfiltdir = filter direction, 'twopass' (default) or 'onepass' +% cfg.preproc.detrend = 'no' or 'yes' +% cfg.preproc.blc = 'no' or 'yes' +% cfg.preproc.blcwindow = [begin end] in seconds, the default is the complete trial +% cfg.preproc.hilbert = 'no' or 'yes' +% cfg.preproc.rectify = 'no' or 'yes' + +% Copyright (C) 2005-2010, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_spikedownsample.m 1049 2010-05-07 09:47:57Z jansch $ + +fieldtripdefs +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +% set the general defaults +if ~isfield(cfg, 'dataset'), cfg.dataset = []; end +if ~isfield(cfg, 'output'), cfg.output = []; end +if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end +if ~isfield(cfg, 'channelprefix'), cfg.channelprefix = []; end +if ~isfield(cfg, 'latency'), cfg.latency = [0 inf]; end +if ~isfield(cfg, 'headerformat'), cfg.headerformat = []; end +if ~isfield(cfg, 'dataformat'), cfg.dataformat = []; end +% set the specific defaults +if ~isfield(cfg, 'fsample'), cfg.fsample = 1000; end +%if ~isfield(cfg, 'method'), cfg.method = []; end +if ~isfield(cfg, 'precision'), cfg.precision = 'double'; end + +if ~isfield(cfg, 'calibration') + if ft_filetype(cfg.dataset, 'neuralynx_dma') || ft_filetype(cfg.dataset, 'neuralynx_sdma') + error('You must specify cfg.calibration in case of neuralynx_dma or neuralynx_sdma'); + else + cfg.calibration = 1; + end +end + +% check that the input cfg is valid for this function +cfg = checkconfig(cfg, 'required', {'method', 'calibration', 'dataformat'}); +cfg = checkconfig(cfg, 'forbidden', {'ADtoUV'}); + +% ensure that the preproc specific options are located in the preproc substructure +cfg = checkconfig(cfg, 'createsubcfg', {'preproc'}); + +status = mkdir(cfg.output); +if ~status + error(sprintf('error creating LFP output dataset %s', cfg.output)); +end + +% read the header of the completete dataset +hdr = ft_read_header(cfg.dataset, 'headerformat', cfg.headerformat); +cfg.channel = ft_channelselection(cfg.channel, hdr.label); +chansel = match_str(hdr.label, cfg.channel); + +if strcmp(cfg.timestampdefinition, 'sample') + % the default would be to keep the original definition of timestamps as determined from looking at the file + % here the definition of timestamps is changed to correspond with samples at the original sampling rate + hdr.TimeStampPerSample = 1; + hdr.FirstTimeStamp = 1; + hdr.LastTimeStamp = hdr.nSamples*hdr.nTrials; +end + +if hdr.nSamples<1 + error('the input dataset contains no samples'); +elseif length(chansel)<1 + error('the input selection contains no channels'); +end + +% give some feedback, based on the complete data +fprintf('data contains %10d channels\n', hdr.nChans); +fprintf('selected %10d channels\n', length(chansel)); +numsample = []; +numsegment = size(cfg.latency,1); +for j=1:numsegment + begsample(j) = max(round(cfg.latency(j,1) * hdr.Fs + 1), 1); + endsample(j) = min(round(cfg.latency(j,2) * hdr.Fs ), hdr.nSamples); + numsample(j) = endsample(j) - begsample(j) + 1; + cfg.latency(j,1) = (begsample(j)-1)/hdr.Fs; + cfg.latency(j,2) = (endsample(j) )/hdr.Fs; +end +numsample = sum(numsample); +fprintf('data contains %10d samples\n', hdr.nSamples); +fprintf('selected %10d samples in %d segments\n', numsample, numsegment); + +s = floor(hdr.nSamples ./ hdr.Fs); +m = floor(s/60); +h = floor(m/60); +m = m - 60*h; +s = s - 60*m - 60*60*h; +fprintf('duration of data %02dh:%02dm:%02ds\n', h, m, s); + +s = floor(numsample ./ hdr.Fs); +m = floor(s/60); +h = floor(m/60); +m = m - 60*h; +s = s - 60*m - 60*60*h; +fprintf('duration of selection %02dh:%02dm:%02ds\n', h, m, s); + +fprintf('estimated memory usage %d MB\n', round((numsample*(8+8+2))/(1024^2))); + +% determine the exact sampling frequency for the LFP and MUA +fac = hdr.Fs/cfg.fsample; +if strcmp(cfg.method, 'resample'); + % this works with arbitrary changes in the frequency +else + % this requires an integer downsampling fraction + fac = round(fac); + cfg.fsample = hdr.Fs/fac; +end + +if numsegment==1 + % determine the timestamps of the first and last sample after downsampling + tsoff = cast(0, class(hdr.FirstTimeStamp)); + tsbeg = double(hdr.FirstTimeStamp - tsoff); + tsend = double(hdr.LastTimeStamp - tsoff); + tsdif = (tsend-tsbeg)/(hdr.nSamples-1); % should be the same as hdr.TimeStampPerSample + % this applies to all samples in the datafile, i.e. not on the selected latency window + resampled_tsbeg = tsbeg + ((fac-1)/2)*tsdif; + resampled_tsend = tsend - ((fac-1)/2)*tsdif; + resampled_tsdif = fac * tsdif; + % this applies to the selected latency window + selected_tsbeg = double(hdr.FirstTimeStamp - tsoff) + (begsample-1)*tsdif; + selected_tsend = double(hdr.FirstTimeStamp - tsoff) + (endsample-1)*tsdif; + resampled_selected_tsbeg = selected_tsbeg + ((fac-1)/2)*tsdif; + resampled_selected_tsend = selected_tsend - ((fac-1)/2)*tsdif; + % these should be integers, but will be casted to uint32 or uint64 later + resampled_selected_tsbeg = round(resampled_selected_tsbeg); + resampled_selected_tsend = round(resampled_selected_tsend); + resampled_tsdif ; % this remains a double +else + warning('multiple data segments were selected, timestamps are invalid'); +end + +% process each channel separetely +for i=chansel(:)' + fprintf('reading channel %d, ''%s''\n', i, hdr.label{i}); + + % read the data of a single channel and concatenate into one vector + org = zeros(1,sum(numsample)); + for j=1:numsegment + buf = ft_read_data(cfg.dataset, 'header', hdr, 'begsample', begsample(j), 'endsample', endsample(j), 'chanindx', i); + + % apply the optional calibration to the data to ensure that the numbers represent uV + if cfg.calibration~=1 + buf = cfg.calibration * buf; + end + + if j==1 + begsegment = 1; + endsegment = numsample(j); + else + begsegment = numsample(j-1) + 1; + endsegment = sum(numsample(1:j)); + end + % concatenate the data into one large vector + org(begsegment:endsegment) = buf; + clear buf; + end + label = hdr.label(i); % this should be cell-array for preproc + + % apply preprocessing and downsample + fprintf('preprocessing\n'); + dat = preproc(org, label, hdr.Fs, cfg.preproc); + dat = ft_preproc_resample(dat, hdr.Fs, cfg.fsample, cfg.method); + + chanhdr = []; + chanhdr.nChans = 1; + chanhdr.nTrials = 1; % since continuous + chanhdr.nSamplesPre = 1; % since continuous + chanhdr.Fs = cfg.fsample; + chanhdr.nSamples = length(dat); + if isempty(cfg.channelprefix) + % the label should be a cell-array of length one + chanhdr.label = hdr.label(i); + else + % add a prefix to the channel name + chanhdr.label = {[cfg.channelprefix '_' hdr.label{i}]}; + end + if numsegment==1 + chanhdr.FirstTimeStamp = resampled_selected_tsbeg; + chanhdr.LastTimeStamp = resampled_selected_tsend; + chanhdr.TimeStampPerSample = resampled_tsdif; + else + % these are not defined in case of multiple segments + warning('multiple data segments were selected, timestamps are invalid'); + chanhdr.FirstTimeStamp = nan; + chanhdr.LastTimeStamp = nan; + chanhdr.TimeStampPerSample = nan; + end + if strcmp(cfg.dataformat, 'fcdc_matbin') + chanhdr.precision = cfg.precision; + end + + % the output file contains the new channel name + datafile = fullfile(cfg.output, chanhdr.label{1}); % this is without filename extension + fprintf('writing to file ''%s''\n', datafile); + ft_write_data(datafile, dat, 'header', chanhdr, 'dataformat', cfg.dataformat); + + % keep memory tidy + clear dat + +end % for each file + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add the version details of this function call to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_spikedownsample.m 1049 2010-05-07 09:47:57Z jansch $'; + diff --git a/external/fieldtrip/ft_spikefixdmafile.m b/external/fieldtrip/ft_spikefixdmafile.m new file mode 100644 index 0000000..4f456fa --- /dev/null +++ b/external/fieldtrip/ft_spikefixdmafile.m @@ -0,0 +1,115 @@ +function ft_spikefixdmafile(cfg) + +% FT_SPIKEFIXDMAFILE fixes the problem in DMA files due to stopping +% and restarting the acquisition. It takes one Neuralynx DMA file and +% and creates seperate DMA files, each corresponding with one continuous +% section of the recording. +% +% Use as +% ft_spikefixdmafile(cfg); +% where the configuration should contain +% cfg.dataset = string with the name of the DMA log file +% cfg.output = string with the name of the DMA log file, (default is determined automatic) +% cfg.numchans = number of channels (default = 256) +% +% See also FT_SPIKESPLITTING + +% Copyright (C) 2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_spikefixdmafile.m 1102 2010-05-19 15:33:23Z roboos $ + +fieldtripdefs + +% set the general defaults +if ~isfield(cfg, 'dataset'), cfg.dataset = []; end +if ~isfield(cfg, 'output'), cfg.output = []; end +if ~isfield(cfg, 'numchans'), cfg.numchans = 256; end +if ~isfield(cfg, 'headerformat'), cfg.headerformat = []; end + +if isempty(cfg.output) + [p, f, x] = fileparts(cfg.dataset); + cfg.output = fullfile(p, f); % without the extension +end + +try + hdr = ft_read_header(cfg.dataset, 'headerformat', cfg.headerformat); +catch + disp(lasterr); +end + +nchan = cfg.numchans+18; +fsample = 32556; +hdroffset = 16384; +count = 0; + +fin = fopen(cfg.dataset, 'rb'); +header = fread(fin, hdroffset, 'uchar=>uchar'); + + +% skip the part that has been processed sofar +fseek(fin, hdroffset, 'bof'); + +ok = 1; +while (ok) + + % find the beginning of the next section in the file + buf = zeros(1, nchan); + while (buf(1)~=2048 && buf(2)~=1) + % read a single block + buf = fread(fin, nchan, 'uint32=>uint32'); + if feof(fin) || length(buf)~=nchan + ok = 0; + break; + end + if (buf(1)~=2048 && buf(2)~=1) + % jump back to the original location and slide one sample forward to try again + fseek(fin, -(nchan-1)*4, 'cof'); + else + % jump back to the original location and continue with the copying to the new file + fseek(fin, -nchan*4, 'cof'); + end + end + + % the first file gets an "a" appended, the second a "b", etc. + count = count + 1; + filename = sprintf('%s%s.nrd', cfg.output, char(96+count)); + fprintf('writing section %d to "%s"\n', count, filename); + + fout = fopen(filename, 'wb'); + fwrite(fout, header, 'uchar'); + + while (buf(1)==2048 && buf(2)==1) + % read a single blockr + buf = fread(fin, nchan, 'uint32=>uint32'); + if feof(fin) || length(buf)~=nchan + ok = 0; + break; + end + if (buf(1)==2048 && buf(2)==1) + % write the block to the other file + fwrite(fout, buf, 'uint32'); + end + end + + fclose(fout); + +end % while ok + +fclose(fin); + diff --git a/external/fieldtrip/ft_spikesimulation.m b/external/fieldtrip/ft_spikesimulation.m new file mode 100644 index 0000000..6c63b20 --- /dev/null +++ b/external/fieldtrip/ft_spikesimulation.m @@ -0,0 +1,134 @@ +function data = ft_spikesimulation(cfg) + +% FT_SPIKESIMULATION +% +% Use as +% data = ft_spikesimulation(cfg) +% and please look in the code for the cfg details. +% +% See also FT_DIPOLESIMULATION, FT_FREQSIMULATION + +% Copyright (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_spikesimulation.m 948 2010-04-21 18:02:21Z roboos $ + +fieldtripdefs + +% set the defaults +if ~isfield(cfg, 'trlduration'), cfg.trlduration = 1; end % in seconds +if ~isfield(cfg, 'nlfpchan'), cfg.nlfpchan = 10; end +if ~isfield(cfg, 'nspikechan'), cfg.nspikechan = 10; end +if ~isfield(cfg, 'spikerate'), cfg.spikerate = ones(cfg.nspikechan,1)*10; end +if ~isfield(cfg, 'ntrial'), cfg.ntrial = 10; end +if ~isfield(cfg, 'bpfreq'), cfg.bpfreq = [40 80]; end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% define the parameters +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% cfg.spikerate = [ 10 50 100 200]; +% cfg.nspikechan = 4; +% nlfpchan = 2; +% cfg.ntrial = 10; +% cfg.bpfreq = [40 80]; +% cfg.trlduration = 1; + +spikemix = eye(cfg.nspikechan, cfg.nlfpchan); +spikemix(5,1:2) = [0.5 0.5]; % mix with lfp chan 1 and 2 +spikemix(6,1:2) = [0.5 0.5]; % mix with lfp chan 1 and 2 + +% cfg.spikerate = 100*ones(1,cfg.nspikechan); % for each channel, per second +% cfg.spikerate = [100 100 300 300 100 300]; +fsample = 1000; +nsample = cfg.trlduration*fsample; +nchan = cfg.nlfpchan + cfg.nspikechan; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% create the data +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% start with empty data +data = []; +data.fsample = fsample; + +% create channel labels +k = 1; +for i=1:cfg.nlfpchan, data.label{k} = sprintf('lfp%02d', i); k=k+1; end +for i=1:cfg.nspikechan, data.label{k} = sprintf('spike%02d', i); k=k+1; end +data.label = data.label(:); + +for t=1:cfg.ntrial + fprintf('creating trial %d\n', t); + data.time{t} = (1:nsample)./fsample; + lfp = zeros(cfg.nlfpchan, nsample); + spike = zeros(cfg.nspikechan, nsample); + + for i=1:cfg.nlfpchan, + lfp(i,:) = ft_preproc_bandpassfilter(randn(1,nsample), fsample, cfg.bpfreq); + end + + for i=1:cfg.nspikechan + % the spikes are generated from a probabilistic mix of the LFP channels + x = spikemix(i,:) * lfp; + % apply a non-linear mapping to the spike probablility, output should be defined between 0 and 1 + x = mapping(x); + % normalize the total probability to one + x = x./sum(x); + % randomly assign the spikes over the time series + spike(i,:) = ((cfg.spikerate(i)*nsample/fsample)*x)>=rand(size(x)); + end + + data.time{t} = (1:nsample)./fsample; + data.trial{t} = [lfp; spike]; + clear lfp spike +end + +% add the version details of this function call to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_spikesimulation.m 948 2010-04-21 18:02:21Z roboos $'; +% remember the configuration details +data.cfg = cfg; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION to strengthen the temporal strucure in the spike train +% by a non-linear modulation of the spike probability +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function y = mapping(x) +x = 6*(x-mean(x))/std(x); +y = 1./(1+exp(-x)); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% IIRFILTER simple brick wall filter in the frequency domain +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function s = myiirfilter(s, fs, fb, a) +f = fft(s); +ax = linspace(0, fs, length(s)); +fl = nearest(ax, fb(1))-1; +fh = nearest(ax, fb(2))+1; +f(1:fl) = a.*f(1:fl); +f(fh:end) = a.*f(fh:end); +s = real(ifft(f)); + diff --git a/external/fieldtrip/ft_spikesorting.m b/external/fieldtrip/ft_spikesorting.m new file mode 100644 index 0000000..a245274 --- /dev/null +++ b/external/fieldtrip/ft_spikesorting.m @@ -0,0 +1,194 @@ +function [spike] = ft_spikesorting(cfg, spike); + +% FT_SPIKESORTING performs clustering of spike-waveforms and returns the unit number to which each spike belongs. +% +% Use as +% [spike] = ft_spikesorting(cfg, spike) +% +% The configuration can contain +% cfg.channel cell-array with channel selection (default = 'all'), see FT_CHANNELSELECTION for details +% cfg.method 'kmeans', 'ward' +% cfg.feedback 'no', 'text', 'textbar', 'gui' (default = 'textbar') +% cfg.kmeans substructure with additional low-level options for this method +% cfg.ward substructure with additional low-level options for this method +% cfg.ward.distance 'L1', 'L2', 'correlation', 'cosine' +% +% The input spike structure can be imported using READ_FCDC_SPIKE and should contain +% spike.label = 1 x Nchans cell-array, with channel labels +% spike.waveform = 1 x Nchans cell-array, each element contains a matrix (Nsamples x Nspikes), can be empty +% spike.timestamp = 1 x Nchans cell-array, each element contains a vector (1 x Nspikes) +% spike.unit = 1 x Nchans cell-array, each element contains a vector (1 x Nspikes) +% +% See also READ_FCDC_SPIKE, FT_SPIKEDOWNSAMPLE +% +% Undocumented local options: +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk + +% Copyright (C) 2006-2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_spikesorting.m 1247 2010-06-17 12:07:18Z timeng $ + +fieldtripdefs + +% set the defaults +if ~isfield(cfg, 'feedback'), cfg.feedback = 'textbar'; end +if ~isfield(cfg, 'method'), cfg.method = 'ward'; end +if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +if isequal(cfg.method, 'ward') + if ~isfield(cfg, 'ward'), cfg.ward = []; end + if ~isfield(cfg.ward, 'distance'), cfg.ward.distance = 'L2'; end + if ~isfield(cfg.ward, 'optie'), cfg.ward.optie = 'ward'; end + if ~isfield(cfg.ward, 'aantal'), cfg.ward.aantal = 10; end + if ~isfield(cfg.ward, 'absoluut'), cfg.ward.absoluut = 1; end +end + +if isequal(cfg.method, 'kmeans') + if ~isfield(cfg, 'kmeans'), cfg.kmeans = []; end + if ~isfield(cfg.kmeans, 'aantal'), cfg.kmeans.aantal = 10; end +end + +% load optional given inputfile as data +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + end +end + +% select the channels +cfg.channel = ft_channelselection(cfg.channel, spike.label); +sel = match_str(spike.label, cfg.channel); +spike.label = spike.label(sel); +spike.waveform = spike.waveform(sel); +spike.timestamp = spike.timestamp(sel); +spike.unit = {}; % this will be assigned by the clustering + +nchan = length(spike.label); +for chanlop=1:nchan + label = spike.label{chanlop}; + waveform = spike.waveform{chanlop}; + timestamp = spike.timestamp{chanlop}; + nspike = size(waveform,2); + unit = zeros(1,nspike); + fprintf('sorting %d spikes in channel %s\n', nspike, label); + + switch cfg.method + case 'ward' + dist = ward_distance(cfg, waveform); + [grootte,ordening] = cluster_ward(dist,cfg.ward.optie,cfg.ward.absoluut,cfg.ward.aantal); + for i=1:cfg.ward.aantal + begsel = sum([1 grootte(1:(i-1))]); + endsel = sum([0 grootte(1:(i ))]); + unit(ordening(begsel:endsel)) = i; + end + + case 'kmeans' + unit = kmeans(waveform', cfg.kmeans.aantal)'; + + % 'sqEuclidean' - Squared Euclidean distance + % 'cityblock' - Sum of absolute differences, a.k.a. L1 + % 'cosine' - One minus the cosine of the included angle + % between points (treated as vectors) + % 'correlation' - One minus the sample correlation between + % points (treated as sequences of values) + + otherwise + error('unsupported clustering method'); + end + + % remember the sorted units + spike.unit{chanlop} = unit; +end + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_spikesorting.m 1247 2010-06-17 12:07:18Z timeng $'; +% remember the configuration details of the input data +try, cfg.previous = spike.cfg; end +% remember the configuration +spike.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', spike); % use the variable name "data" in the output file +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION that computes the distance between all spike waveforms +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [dist] = ward_distance(cfg, waveform); +nspike = size(waveform,2); +dist = zeros(nspike, nspike); +progress('init', cfg.feedback, 'computing distance'); +switch lower(cfg.ward.distance) + case 'l1' + for i=1:nspike + progress((i-1)/nspike, 'computing distance for spike %d/%d', i, nspike); + for j=2:nspike + dist(i,j) = sum(abs(waveform(:,j)-waveform(:,i))); + dist(j,i) = dist(i,j); + end + end + case 'l2' + for i=1:nspike + progress((i-1)/nspike, 'computing distance for spike %d/%d', i, nspike); + for j=2:nspike + dist(i,j) = sqrt(sum((waveform(:,j)-waveform(:,i)).^2)); + dist(j,i) = dist(i,j); + end + end + case 'correlation' + for i=1:nspike + progress((i-1)/nspike, 'computing distance for spike %d/%d', i, nspike); + for j=2:nspike + dist(i,j) = corrcoef(waveform(:,j),waveform(:,i)); + dist(j,i) = dist(i,j); + end + end + case 'cosine' + for i=1:nspike + progress((i-1)/nspike, 'computing distance for spike %d/%d', i, nspike); + for j=2:nspike + x = waveform(:,j); + y = waveform(:,i); + x = x./norm(x); + y = y./norm(y); + dist(i,j) = dot(x, y); + dist(j,i) = dist(i,j); + end + end + + otherwise + error('unsupported distance metric'); +end +progress('close'); diff --git a/external/fieldtrip/ft_spikesplitting.m b/external/fieldtrip/ft_spikesplitting.m new file mode 100644 index 0000000..11900f6 --- /dev/null +++ b/external/fieldtrip/ft_spikesplitting.m @@ -0,0 +1,267 @@ +function [cfg] = ft_spikesplitting(cfg); + +% FT_SPIKESPLITTING reads a single Neuralynx DMA log file and writes each +% individual channel to a seperate file. +% +% Use as +% [cfg] = ft_spikesplitting(cfg) +% +% The configuration should contain +% cfg.dataset = string with the name of the DMA log file +% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), see FT_CHANNELSELECTION for details +% cfg.output = string with the name of the splitted DMA dataset directory, (default is determined automatic) +% cfg.latency = [begin end], (default = 'all') +% cfg.feedback = string, (default = 'textbar') +% cfg.format = 'int16' or 'int32' (default = 'int32') +% cfg.downscale = single number or vector (for each channel), corresponding to the number of bits removed from the LSB side (default = 0) +% +% This function expects the DMA file to be read as AD units (and not in uV) +% and will write the same AD values to the splitted DMA files. If you +% subsequently want to process the splitted DMA, you should look up the +% details of the headstage amplification and the Neuralynx amplifier and +% scale the values accordingly. +% +% See also FT_SPIKEDOWNSAMPLE, FT_SPIKEANALYSIS + +% Copyright (C) 2007-2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_spikesplitting.m 1043 2010-05-06 10:27:19Z timeng $ + +fieldtripdefs + +% set the general defaults +if ~isfield(cfg, 'dataset'), cfg.dataset = []; end +if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end +if ~isfield(cfg, 'latency'), cfg.latency = [0 inf]; end +if ~isfield(cfg, 'feedback'), cfg.feedback = 'textbar'; end +if ~isfield(cfg, 'output'), cfg.output = []; end % see below +if ~isfield(cfg, 'format'), cfg.format = 'int32'; end +if ~isfield(cfg, 'downscale'), cfg.downscale = 0; end +if ~isfield(cfg, 'headerformat'), cfg.headerformat = []; end + +if isempty(cfg.output) + % set smart defaults for the output + [p, f, x] = fileparts(cfg.dataset); + cfg.output = fullfile(p, [f '.sdma']); +end + +status = mkdir(cfg.output); +if ~status + error(sprintf('error creating splitted DMA output dataset %s', cfg.output)); +end +fprintf('writing to output directory ''%s''\n', cfg.output); + +% read the header of the completete dataset +hdr = ft_read_header(cfg.dataset, 'headerformat', cfg.headerformat); + +if isfield(hdr, 'orig') && isfield(hdr.orig, 'Header') + [p, f, x] = fileparts(cfg.output); + headerfile = fullfile(cfg.output, [f '.txt']); + fprintf('writing header information to %s\n', headerfile); + fid = fopen(headerfile, 'wb'); + fwrite(fid, hdr.orig.Header, 'char'); + fclose(fid); +end + +if hdr.nSamples<1 + error('the input dataset contains no samples'); +end + +if numel(cfg.downscale)==1 + % each channel should have its own downscale factor + cfg.downscale = repmat(cfg.downscale, 1, hdr.nChans); +end + +% determine the selected channels +cfg.channel = ft_channelselection(cfg.channel, hdr.label); +chansel = match_str(hdr.label, cfg.channel); % this is a list with the indices of the selected channels +writechan = zeros(1,hdr.nChans); +writechan(chansel) = 1; % this is a logical/boolean vector with a 0/1 for each channel + +if numel(cfg.downscale) ~= numel(writechan) + error('the downscale factor should be specified for all channels, not only for the selected ones'); +end + +if isequal(cfg.latency, 'all') + begsample = 1; + endsample = hdr.nSamples; +elseif numel(cfg.latency)==2 + begsample = max(round(cfg.latency(1) * hdr.Fs + 1), 1); + endsample = min(round(cfg.latency(2) * hdr.Fs ), hdr.nSamples); +else + errror('incorrect specification of cfg.latency'); +end + +numsample = endsample - begsample + 1; +cfg.latency(1) = (begsample-1)/hdr.Fs; +cfg.latency(2) = (endsample )/hdr.Fs; + +% give some feedback, based on the complete data +fprintf('data contains %10d samples\n', hdr.nSamples); +fprintf('data selected %10d samples\n', numsample); + +s = floor(hdr.nSamples ./ hdr.Fs); +m = floor(s/60); +h = floor(m/60); +m = m - 60*h; +s = s - 60*m - 60*60*h; +fprintf('duration of data %02dh:%02dm:%02ds\n', h, m, s); + +s = floor(numsample ./ hdr.Fs); +m = floor(s/60); +h = floor(m/60); +m = m - 60*h; +s = s - 60*m - 60*60*h; +fprintf('duration of selection %02dh:%02dm:%02ds\n', h, m, s); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% split the DMA file into seperate channels +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +if ~ft_filetype(cfg.dataset, 'neuralynx_dma') + error('unsupported data format for DMA splitting'); +end + +statuslabel = { + 'stx' + 'pid' + 'siz' + 'tsh' + 'tsl' + 'cpu' + 'ttl' + 'x01' + 'x02' + 'x03' + 'x04' + 'x05' + 'x06' + 'x07' + 'x08' + 'x09' + 'x10' + 'crc' + }; + +% the output files will have an extension that is based on the channel name like "dataset.channame.bin" +[p, f, x] = fileparts(cfg.output); +filename = cell(hdr.nChans,1); +format = cell(hdr.nChans,1); +for i=1:hdr.nChans + filename{i} = fullfile(cfg.output, [f '.' hdr.label{i} '.bin']); + if strmatch(hdr.label{i}, statuslabel) + format{i} = 'uint32'; + elseif strcmp(cfg.format, 'int16') + format{i} = 'int16'; + elseif strcmp(cfg.format, 'int32') + format{i} = 'int32'; + else + error('incorrect specification of cfg.format'); + end +end + +% the status channels are written in their original format +for i=1:hdr.nChans + if strcmp(format{i}, 'uint32') && cfg.downscale(i)~=0 + warning('not downscaling status channel (%s)', hdr.label{i}); + cfg.downscale(i) = 0; + end +end + +% read and write the data in one-second segments +begsample = max(cfg.latency(1) * hdr.Fs + 1, 1); +endsample = min(cfg.latency(2) * hdr.Fs + 1, hdr.nSamples); +segment = begsample:hdr.Fs:endsample; +if segment(end)~=endsample + segment(end+1) = endsample; % the last segment should end on the end sample +end + +% The first version of this file format contained in the first 8 bytes the +% channel label as string. Subsequently it contained 32 bit integer values. +% +% The second version of this file format starts with 8 bytes describing (as +% a space-padded string) the data type. The channel label is contained in +% the filename as dataset.chanlabel.bin. +% +% The third version of this file format starts with 7 bytes describing (as +% a zero-padded string) the data type, followed by the 8th byte which +% describes the downscaling for the 8 and 16 bit integer representations. +% The downscaling itself is represented as uint8 and should be interpreted as +% the number of bits to shift. The channel label is contained in the +% filename as dataset.chanlabel.bin. + +% open the output files, one for each selected channel +fid = zeros(hdr.nChans,1); +for j=1:hdr.nChans + if writechan(j) + fid(j) = fopen(filename{j}, 'wb', 'ieee-le'); % open the file + magic = format{j}; % this used to be the channel name + magic((end+1):8) = 0; % pad with zeros + magic(8) = cfg.downscale(j); % number of bits to shift + fwrite(fid(j), magic(1:8)); % write the 8-byte file header + end +end + +progress('init', cfg.feedback, 'splitting data'); +for i=1:(length(segment)-1) + % read one segment of data + begsample = segment(i); + endsample = segment(i+1)-1; % the begin of the next segment minus one + progress(i/(length(segment)-1), 'splitting data segment %d from %d\n', i, length(segment)-1); + buf = read_neuralynx_dma(cfg.dataset, begsample, endsample, 'all'); + if ~isa(buf, 'int32') + error('the buffer is expected to be int32'); + end + % apply the scaling, this corresponds to bit shifting + for j=1:hdr.nChans + buf(j,:) = buf(j,:) ./ (2^cfg.downscale(j)); + end + % write the segment of data to each of the 274 output files + % the data is casted into the desired output format + for j=1:hdr.nChans + if writechan(j) + if strcmp(format{j}, 'uint32') + % the individual file header specifies that it should be interpreted as uint32 + % write the int32 data from the buffer as it is, during reading the sign bit will again be correctly interpreted + fwrite(fid(j), buf(j,:), 'int32', 'ieee-le'); + else + fwrite(fid(j), buf(j,:), format{j}, 'ieee-le'); + end + end + end +end +progress('close'); + +% close all output files +for j=1:hdr.nChans + if writechan(j) + fclose(fid(j)); + end +end + +% add the version details of this function call to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_spikesplitting.m 1043 2010-05-06 10:27:19Z timeng $'; + diff --git a/external/fieldtrip/ft_spiketriggeredaverage.m b/external/fieldtrip/ft_spiketriggeredaverage.m index b84b9b2..28a4269 100644 --- a/external/fieldtrip/ft_spiketriggeredaverage.m +++ b/external/fieldtrip/ft_spiketriggeredaverage.m @@ -1,11 +1,222 @@ -function varargout = funname(varargin); +function [timelock] = ft_spiketriggeredaverage(cfg, data) -% this is a SPM wrapper around a FieldTrip function +% FT_SPIKETRIGGEREDAVERAGE computes the avererage of the LFP around the spikes. +% +% Use as +% [timelock] = ft_spiketriggeredaverage(cfg, data) +% +% The input data should be organised in a structure as obtained from +% the FT_PREPROCESSING function. The configuration should be according to +% +% cfg.timwin = [begin end], time around each spike (default = [-0.1 0.1]) +% cfg.spikechannel = string, name of single spike channel to trigger on +% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), +% see FT_CHANNELSELECTION for details +% cfg.keeptrials = 'yes' or 'no', return individual trials or average (default = 'no') +% cfg.feedback = 'no', 'text', 'textbar', 'gui' (default = 'no') +% +% Undocumented local options: +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk + +% Copyright (C) 2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_spiketriggeredaverage.m 1267 2010-06-25 09:08:42Z timeng $ + +fieldtripdefs + +% set the defaults +if ~isfield(cfg, 'timwin'), cfg.timwin = [-0.1 0.1]; end +if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end +if ~isfield(cfg, 'spikechannel'), cfg.spikechannel = []; end +if ~isfield(cfg, 'keeptrials'), cfg.keeptrials = 'no'; end +if ~isfield(cfg, 'feedback'), cfg.feedback = 'no'; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +% load optional given inputfile as data +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + end +end + +% autodetect the spike channels +ntrial = length(data.trial); +nchans = length(data.label); +spikechan = zeros(nchans,1); +for i=1:ntrial + for j=1:nchans + spikechan(j) = spikechan(j) + all(data.trial{i}(j,:)==0 | data.trial{i}(j,:)==1 | data.trial{i}(j,:)==2); + end +end +spikechan = (spikechan==ntrial); + +% determine the channels to be averaged +cfg.channel = ft_channelselection(cfg.channel, data.label); +chansel = match_str(data.label, cfg.channel); +nchansel = length(cfg.channel); % number of channels + +% determine the spike channel on which will be triggered +cfg.spikechannel = ft_channelselection(cfg.spikechannel, data.label); +spikesel = match_str(data.label, cfg.spikechannel); +nspikesel = length(cfg.spikechannel); % number of channels + +if nspikesel==0 + error('no spike channel selected'); +end + +if nspikesel>1 + error('only supported for a single spike channel'); +end + +if ~spikechan(spikesel) + error('the selected spike channel seems to contain continuous data'); +end + +begpad = round(cfg.timwin(1)*data.fsample); +endpad = round(cfg.timwin(2)*data.fsample); +numsmp = endpad - begpad + 1; + +singletrial = cell(1,ntrial); +spiketime = cell(1,ntrial); +spiketrial = cell(1,ntrial); +cumsum = zeros(nchansel, numsmp); +cumcnt = 0; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% compute the average +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +for i=1:ntrial + spikesmp = find(data.trial{i}(spikesel,:)); + spikecnt = data.trial{i}(spikesel,spikesmp); + + if any(spikecnt>5) || any(spikecnt<0) + error('the spike count lies out of the regular bounds'); + end + + % instead of doing the bookkeeping of double spikes below, replicate the double spikes by looking at spikecnt + sel = find(spikecnt>1); + tmp = zeros(1,sum(spikecnt(sel))); + n = 1; + for j=1:length(sel) + for k=1:spikecnt(sel(j)) + tmp(n) = spikesmp(sel(j)); + n = n + 1; + end + end + spikesmp(sel) = []; % remove the double spikes + spikecnt(sel) = []; % remove the double spikes + spikesmp = [spikesmp tmp]; % add the double spikes as replicated single spikes + spikecnt = [spikecnt ones(size(tmp))]; % add the double spikes as replicated single spikes + spikesmp = sort(spikesmp); % sort them to keep the original ordering (not needed on spikecnt, since that is all ones) + + spiketime{i} = data.time{i}(spikesmp); + spiketrial{i} = i*ones(size(spikesmp)); + fprintf('processing trial %d of %d (%d spikes)\n', i, ntrial, sum(spikecnt)); + + if strcmp(cfg.keeptrials, 'yes') + if any(spikecnt>1) + error('overlapping spikes not supported with cfg.keeptrials=yes'); + end + % initialize the memory for this trial + singletrial{i} = nan*zeros(length(spikesmp), nchansel, numsmp); + end + + progress('init', cfg.feedback, 'averaging spikes'); + for j=1:length(spikesmp) + progress(i/ntrial, 'averaging spike %d of %d\n', j, length(spikesmp)); + begsmp = spikesmp(j) + begpad; + endsmp = spikesmp(j) + endpad; + + if begsmp<1 + % a possible alternative would be to pad the begin with nan + % this excludes the complete segment + continue + elseif endsmp>size(data.trial{i},2) + % possible alternative would be to pad the end with nan + % this excludes the complete segment + continue + else + segment = data.trial{i}(chansel,begsmp:endsmp); + end + if strcmp(cfg.keeptrials, 'yes') + singletrial{i}(j,:,:) = segment; + end + + cumsum = cumsum + spikecnt(j)*segment; + cumcnt = cumcnt + spikecnt(j); + + end % for each spike in this trial + progress('close'); + +end % for each trial + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% collect the results +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +timelock.time = offset2time(begpad, data.fsample, numsmp); +timelock.avg = cumsum ./ cumcnt; +timelock.label = data.label(chansel); + +if (strcmp(cfg.keeptrials, 'yes')) + timelock.dimord = 'rpt_chan_time'; + % concatenate all the single spike snippets + timelock.trial = cat(1, singletrial{:}); + timelock.origtime = cat(2,spiketime{:})'; % this deviates from the standard output, but is included for reference + timelock.origtrial = cat(2,spiketrial{:})'; % this deviates from the standard output, but is included for reference + + % select all trials that do not contain data in the first sample + sel = isnan(timelock.trial(:,1,1)); + fprintf('removing %d trials from the output that do not contain data\n', sum(sel)); + % remove the selected trials from the output + timelock.trial = timelock.trial(~sel,:,:); + timelock.origtime = timelock.origtime(~sel); + timelock.origtrial = timelock.origtrial(~sel); +else + timelock.dimord = 'chan_time'; +end + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_spiketriggeredaverage.m 1267 2010-06-25 09:08:42Z timeng $'; +% remember the configuration details of the input data +try, cfg.previous = data.cfg; end +% remember the exact configuration details in the output +timelock.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', timelock); % use the variable name "data" in the output file +end -% this part is variable -prefix = 'ft_'; -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_spiketriggeredinterpolation.m b/external/fieldtrip/ft_spiketriggeredinterpolation.m new file mode 100644 index 0000000..c2df420 --- /dev/null +++ b/external/fieldtrip/ft_spiketriggeredinterpolation.m @@ -0,0 +1,202 @@ +function [data] = ft_spiketriggeredinterpolation(cfg, data) + +% FT_SPIKETRIGGEREDINTERPOLATION interpolates the data in the LFP channels +% around the spikes that are detected in the spike channels, or replaces +% the LFP around the spike with NaNs. +% +% Use as +% [data] = ft_spiketriggeredinterpolation(cfg, data) +% +% The input data should be organised in a structure as obtained from the +% FT_PREPROCESSING function. The configuration should be according to +% +% cfg.method = string, The interpolation method can be 'nan', +% 'cubic', 'linear', 'nearest', spline', 'pchip' +% (default = 'nan'). See INTERP1 for more details. +% cfg.timwin = [begin end], time around each spike (default = [-0.001 0.002]) +% cfg.interptoi = value, time in seconds used for interpolation, which +% must be larger than timwin (default = 0.01) +% cfg.spikechannel = string, name of single spike channel to trigger on +% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), +% see FT_CHANNELSELECTION for details +% cfg.feedback = 'no', 'text', 'textbar', 'gui' (default = 'no') +% +% The output will contain all channels of the input, only the data in the +% selected channels will be interpolated or replaced with NaNs. +% +% See also FT_SPIKETRIGGEREDSPECTRUM, FT_SPIKETRIGGEREDAVERAGE +% +% Undocumented local options: +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk + +% Copyright (C) 2008, Thilo Womelsdorf +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_spiketriggeredinterpolation.m 1267 2010-06-25 09:08:42Z timeng $ + +% set the defaults +if ~isfield(cfg, 'timwin'), cfg.timwin = [-0.001 0.002]; end +if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end +if ~isfield(cfg, 'method'), cfg.method = 'nan'; end +if ~isfield(cfg, 'spikechannel'), cfg.spikechannel = []; end +if ~isfield(cfg, 'outputexamples'), cfg.outputexamples = 'no'; end +if ~isfield(cfg, 'feedback'), cfg.feedback = 'no'; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end +if strcmp(cfg.method, 'nan') + cfg.interptoi = 0; +else + cfg.interptoi = 0.010; +end + +% load optional given inputfile as data +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + end +end + +% autodetect the spike channels +ntrial = length(data.trial); +nchans = length(data.label); +spikechan = zeros(nchans,1); +for i=1:ntrial + for j=1:nchans + spikechan(j) = spikechan(j) + all(data.trial{i}(j,:)==0 | data.trial{i}(j,:)==1 | data.trial{i}(j,:)==2); + end +end +spikechan = (spikechan==ntrial); + +% determine the channels for interpolation +cfg.channel = ft_channelselection(cfg.channel, data.label); +chansel = match_str(data.label, cfg.channel); + +% determine the spike channel on which will be triggered +cfg.spikechannel = ft_channelselection(cfg.spikechannel, data.label); +spikesel = match_str(data.label, cfg.spikechannel); +nspikesel = length(cfg.spikechannel); % number of spike channels + +if nspikesel==0 + error('no spike channel selected'); +end + +if nspikesel>1 + error('only supported for a single spike channel'); +end + +if ~spikechan(spikesel) + error('the selected spike channel seems to contain continuous data'); +end + +% this determines the segment that will be replaced around each spike +begpad = round(cfg.timwin(1)*data.fsample); +endpad = round(cfg.timwin(2)*data.fsample); + +% this determines the segment that is used for the inperpolation around each spike +interppad = round( cfg.interptoi*data.fsample); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% interpolate the LFP around the spikes +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% this is for storing the examples +cnte = 0; +spkexample = {}; + +for i=1:ntrial + spikesmp = find(data.trial{i}(spikesel,:)); + + fprintf('processing trial %d of %d (%d spikes)\n', i, ntrial, length(spikesmp)); + + progress('init', cfg.feedback, 'interpolating spikes'); + for j=1:length(spikesmp) + progress(i/ntrial, 'interpolating spike %d of %d\n', j, length(spikesmp)); + begsmp = spikesmp(j) + begpad; + endsmp = spikesmp(j) + endpad; + + begsmp_interp = begsmp - interppad; + endsmp_interp = endsmp + interppad; + + if begsmp_interp<1 + continue, + end + if endsmp_interp>size(data.trial{i},2) + continue, + end + + if strcmp(cfg.method,'nan') + % only replace with NaNs + data.trial{i}(chansel,begsmp:endsmp) = NaN; + + else + % interpolate the data around the spike + xall = [begsmp_interp : endsmp_interp]; + x = [begsmp_interp:begsmp-1 endsmp+1:endsmp_interp]; + y = data.trial{i}(chansel,x) ; + yi = interp1(x,y,xall,cfg.method); + + % store the interpolated segment back in the data + data.trial{i}(chansel,xall) = yi; + + if strcmp(cfg.outputexamples, 'yes') && (cnte<100) + yall = data.trial{i}(chansel,xall); + cnte = cnte+1; + spkexample{cnte} = [ xall; yall; yi]; + % plot(x,y,'r.',xall,yall,'bo',xall,yi,'g-d') + end + + end % if strcmp(cfg.method) + + end % for each spike in this trial + progress('close'); + +end % for each trial + +if strcmp(cfg.outputexamples, 'yes') + data.spkexample = spkexample; +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% the data has been modified on the fly, only update the configuration +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_spiketriggeredinterpolation.m 1267 2010-06-25 09:08:42Z timeng $'; +% remember the configuration details of the input data +try, cfg.previous = data.cfg; end +% remember the exact configuration details in the output +data.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', data); % use the variable name "data" in the output file +end + diff --git a/external/fieldtrip/ft_spiketriggeredspectrum.m b/external/fieldtrip/ft_spiketriggeredspectrum.m index b84b9b2..f068ac6 100644 --- a/external/fieldtrip/ft_spiketriggeredspectrum.m +++ b/external/fieldtrip/ft_spiketriggeredspectrum.m @@ -1,11 +1,230 @@ -function varargout = funname(varargin); +function [freq] = ft_spiketriggeredspectrum(cfg, data) -% this is a SPM wrapper around a FieldTrip function +% FT_SPIKETRIGGEREDSPECTRUM computes the Fourier spectrup of the LFP around the spikes. +% +% Use as +% [freq] = ft_spiketriggeredspectrum(cfg, data) +% +% The input data should be organised in a structure as obtained from +% the FT_APPENDSPIKE function. The configuration should be according to +% +% cfg.timwin = [begin end], time around each spike (default = [-0.1 0.1]) +% cfg.foilim = [begin end], frequency band of interest (default = [0 150]) +% cfg.taper = 'dpss', 'hanning' or many others, see WINDOW (default = 'hanning') +% cfg.spikechannel = string, name of single spike channel to trigger on +% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), +% see FT_CHANNELSELECTION for details +% cfg.feedback = 'no', 'text', 'textbar', 'gui' (default = 'no') +% +% If the triggered spike leads a spike in another channel, then the angle +% of the Fourier spectrum of that other channel will be negative. NOTE that +% this should be checked for consistency. -% this part is variable -prefix = 'ft_'; +% Copyright (C) 2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_spiketriggeredspectrum.m 948 2010-04-21 18:02:21Z roboos $ + +fieldtripdefs + +% set the defaults +if ~isfield(cfg, 'timwin'), cfg.timwin = [-0.1 0.1]; end +if ~isfield(cfg, 'foilim'), cfg.foilim = [0 150]; end +if ~isfield(cfg, 'taper'), cfg.taper = 'hanning'; end +if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end +if ~isfield(cfg, 'spikechannel'), cfg.spikechannel = []; end +% if ~isfield(cfg, 'keeptrials'), cfg.keeptrials = 'no'; end +if ~isfield(cfg, 'feedback'), cfg.feedback = 'no'; end + +if strcmp(cfg.taper, 'dpss') && strcmp(cfg.taper, 'sine') + error('sorry, multitapering is not yet implemented'); +end + +% see subfunction below, which demonstrates the expected function behaviour +% my_fft = @fft_along_rows; + +% use a NaN-aware spectral estimation technique, which will default to the +% standard Matlab FFT routine if no NaNs are present +my_fft = @specest_nanfft; + +% autodetect the spike channels +ntrial = length(data.trial); +nchans = length(data.label); +spikechan = zeros(nchans,1); +for i=1:ntrial + for j=1:nchans + spikechan(j) = spikechan(j) + all(data.trial{i}(j,:)==0 | data.trial{i}(j,:)==1 | data.trial{i}(j,:)==2); + end +end +spikechan = (spikechan==ntrial); + +% determine the channels to be averaged +cfg.channel = ft_channelselection(cfg.channel, data.label); +chansel = match_str(data.label, cfg.channel); +nchansel = length(cfg.channel); % number of channels + +% determine the spike channel on which will be triggered +cfg.spikechannel = ft_channelselection(cfg.spikechannel, data.label); +spikesel = match_str(data.label, cfg.spikechannel); +nspikesel = length(cfg.spikechannel); % number of channels + +if nspikesel==0 + error('no spike channel selected'); +end + +if nspikesel>1 + error('only supported for a single spike channel'); +end + +if ~spikechan(spikesel) + error('the selected spike channel seems to contain continuous data'); +end + +begpad = round(cfg.timwin(1)*data.fsample); +endpad = round(cfg.timwin(2)*data.fsample); +numsmp = endpad - begpad + 1; +taper = window(cfg.taper, numsmp); +taper = taper./norm(taper); +taper = sparse(diag(taper)); + +spectrum = cell(1,ntrial); +spiketime = cell(1,ntrial); +spiketrial = cell(1,ntrial); +cumsum = zeros(nchansel, numsmp); +cumcnt = 0; + +timeaxis = linspace(cfg.timwin(1),cfg.timwin(2), numsmp); +freqaxis = linspace(0, data.fsample, numsmp); +fbeg = nearest(freqaxis, cfg.foilim(1)); +fend = nearest(freqaxis, cfg.foilim(2)); +% update the configuration to acocunt for rounding off differences +cfg.foilim(1) = freqaxis(fbeg); +cfg.foilim(2) = freqaxis(fend); + +% make a representation of the spike, this is used for the phase rotation +spike = zeros(1,numsmp); +spike(1-begpad) = 1; +spike_fft = my_fft(spike); +spike_fft = spike_fft(fbeg:fend); +spike_fft = spike_fft./abs(spike_fft); +rephase = sparse(diag(conj(spike_fft))); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% compute the spectra +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +for i=1:ntrial + spikesmp = find(data.trial{i}(spikesel,:)); + spikecnt = data.trial{i}(spikesel,spikesmp); + + if any(spikecnt>5) || any(spikecnt<0) + error('the spike count lies out of the regular bounds'); + end + + % instead of doing the bookkeeping of double spikes below, replicate the double spikes by looking at spikecnt + sel = find(spikecnt>1); + tmp = zeros(1,sum(spikecnt(sel))); + n = 1; + for j=1:length(sel) + for k=1:spikecnt(sel(j)) + tmp(n) = spikesmp(sel(j)); + n = n + 1; + end + end + spikesmp(sel) = []; % remove the double spikes + spikecnt(sel) = []; % remove the double spikes + spikesmp = [spikesmp tmp]; % add the double spikes as replicated single spikes + spikecnt = [spikecnt ones(size(tmp))]; % add the double spikes as replicated single spikes + spikesmp = sort(spikesmp); % sort them to keep the original ordering (not needed on spikecnt, since that is all ones) + + spiketime{i} = data.time{i}(spikesmp); + spiketrial{i} = i*ones(size(spikesmp)); + fprintf('processing trial %d of %d (%d spikes)\n', i, ntrial, sum(spikecnt)); + + spectrum{i} = zeros(length(spikesmp), nchansel, fend-fbeg+1); + + progress('init', cfg.feedback, 'spectrally decomposing data around spikes'); + for j=1:length(spikesmp) + progress(i/ntrial, 'spectrally decomposing data around spike %d of %d\n', j, length(spikesmp)); + begsmp = spikesmp(j) + begpad; + endsmp = spikesmp(j) + endpad; + + if (begsmp<1) + segment = nan*zeros(nchansel, numsmp); + elseif endsmp>size(data.trial{i},2) + segment = nan*zeros(nchansel, numsmp); + else + segment = data.trial{i}(chansel,begsmp:endsmp); + end + + % taper the data segment around the spike and compute the fft + segment_fft = my_fft(segment * taper); + + % select the desired output frquencies and normalize + segment_fft = segment_fft(:,fbeg:fend) ./ sqrt(numsmp/2); + + % rotate the estimated phase at each frequency to correct for the segment t=0 not being at the first sample + segment_fft = segment_fft * rephase; + + % store the result for this spike in this trial + spectrum{i}(j,:,:) = segment_fft; + + end % for each spike in this trial + progress('close'); + +end % for each trial + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% collect the results +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +freq.label = data.label(chansel); +freq.freq = freqaxis(fbeg:fend); +freq.dimord = 'rpt_chan_freq'; + +freq.fourierspctrm = cat(1, spectrum{:}); +freq.origtime = cat(2,spiketime{:})'; % this deviates from the standard output, but is included for reference +freq.origtrial = cat(2,spiketrial{:})'; % this deviates from the standard output, but is included for reference + +% select all trials that do not contain data in the first sample +sel = isnan(freq.fourierspctrm(:,1,1)); +fprintf('removing %d trials from the output that do not contain data\n', sum(sel)); +% remove the selected trials from the output +freq.fourierspctrm = freq.fourierspctrm(~sel,:,:); +freq.origtime = freq.origtime(~sel); +freq.origtrial = freq.origtrial(~sel); + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_spiketriggeredspectrum.m 948 2010-04-21 18:02:21Z roboos $'; +% remember the configuration details of the input data +try, cfg.previous = data.cfg; end +% remember the exact configuration details in the output +freq.cfg = cfg; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function y = fft_along_rows(x) +y = fft(x, [], 2); % use normal Matlab function to compute the fft along 2nd dimension -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_statistics_analytic.m b/external/fieldtrip/ft_statistics_analytic.m deleted file mode 100644 index b84b9b2..0000000 --- a/external/fieldtrip/ft_statistics_analytic.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'ft_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_statistics_montecarlo.m b/external/fieldtrip/ft_statistics_montecarlo.m deleted file mode 100644 index b84b9b2..0000000 --- a/external/fieldtrip/ft_statistics_montecarlo.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'ft_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_timelockanalysis.m b/external/fieldtrip/ft_timelockanalysis.m index b84b9b2..d6b1f5a 100644 --- a/external/fieldtrip/ft_timelockanalysis.m +++ b/external/fieldtrip/ft_timelockanalysis.m @@ -1,11 +1,521 @@ -function varargout = funname(varargin); +function [timelock] = ft_timelockanalysis(cfg, data) -% this is a SPM wrapper around a FieldTrip function +% FT_TIMELOCKANALYSIS performs timelocked analysis such as averaging +% and covariance computation +% +% [timelock] = ft_timelockanalysis(cfg, data) +% +% The data should be organised in a structure as obtained from the +% FT_PREPROCESSING function. The configuration should be according to +% +% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), +% see FT_CHANNELSELECTION for details +% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') +% cfg.latency = [begin end] in seconds, or 'minperlength', 'maxperlength', +% 'prestim', 'poststim' (default = 'maxperlength') +% cfg.covariance = 'no' or 'yes' +% cfg.covariancewindow = [begin end] +% cfg.blcovariance = 'no' or 'yes' +% cfg.blcovariancewindow = [begin end] +% cfg.keeptrials = 'yes' or 'no', return individual trials or average (default = 'no') +% cfg.normalizevar = 'N' or 'N-1' (default = 'N-1') +% cfg.removemean = 'no' or 'yes' for covariance computation (default = 'yes') +% cfg.vartrllength = 0, 1 or 2 (see below) +% +% Depending on cfg.vartrllength, variable trials and missing values +% are treated differently: +% 0 - do not accept variable length trials [default] +% 1 - accept variable length trials, but only take those trials in which +% data is present in both the average and the covariance window +% 2 - accept variable length trials, use all available trials +% the available samples in every trial will be used for the +% average and covariance computation. Missing values are replaced +% by NaN and are not included in the computation. -% this part is variable -prefix = 'ft_'; +% FIXME if input is one raw trial, the covariance is not computed correctly +% +% Undocumented local options: +% cfg.feedback +% cfg.normalizecov +% cfg.preproc +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +% This function depends on PREPROC which has the following options: +% cfg.absdiff +% cfg.blc +% cfg.blcwindow +% cfg.boxcar +% cfg.bpfilter +% cfg.bpfiltord +% cfg.bpfilttype +% cfg.bpfreq +% cfg.derivative +% cfg.detrend +% cfg.dftfilter +% cfg.dftfreq +% cfg.hilbert +% cfg.hpfilter +% cfg.hpfiltord +% cfg.hpfilttype +% cfg.hpfreq +% cfg.implicitref +% cfg.lpfilter +% cfg.lpfiltord +% cfg.lpfilttype +% cfg.lpfreq +% cfg.medianfilter +% cfg.medianfiltord +% cfg.rectify +% cfg.refchannel +% cfg.reref + +% Copyright (C) 2003-2006, Markus Bauer +% Copyright (C) 2003-2006, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_timelockanalysis.m 1386 2010-07-09 11:29:38Z jansch $ + +fieldtripdefs + +% set the defaults +if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end +if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end +if ~isfield(cfg, 'keeptrials'), cfg.keeptrials = 'no'; end +if ~isfield(cfg, 'latency'), cfg.latency = 'maxperlength'; end +if ~isfield(cfg, 'covariance'), cfg.covariance = 'no'; end +if ~isfield(cfg, 'blcovariance'), cfg.blcovariance = 'no'; end +if ~isfield(cfg, 'removemean'), cfg.removemean = 'yes'; end +if ~isfield(cfg, 'vartrllength'), cfg.vartrllength = 0; end +if ~isfield(cfg, 'feedback'), cfg.feedback = 'text'; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + data = loadvar(cfg.inputfile, 'data'); + end +end + +% check if the input data is valid for this function +data = checkdata(data, 'datatype', {'raw', 'comp'}, 'feedback', 'yes', 'hastrialdef', 'yes', 'hasoffset', 'yes'); + +% check if the input cfg is valid for this function +cfg = checkconfig(cfg, 'trackconfig', 'on'); +cfg = checkconfig(cfg, 'deprecated', {'normalizecov', 'normalizevar'}); + +% convert average to raw data for convenience, the output will be an average again +% the purpose of this is to allow for repeated baseline correction, filtering and other preproc options that timelockanalysis supports +data = data2raw(data); + +% select trials of interest +if ~strcmp(cfg.trials, 'all') + fprintf('selecting %d trials\n', length(cfg.trials)); + data = selectdata(data, 'rpt', cfg.trials); +end + +ntrial = length(data.trial); + +% ensure that the preproc specific options are located in the cfg.preproc substructure +cfg = checkconfig(cfg, 'createsubcfg', {'preproc'}); + +% preprocess the data, i.e. apply filtering, baselinecorrection, etc. +fprintf('applying preprocessing options\n'); +for i=1:ntrial + [data.trial{i}, data.label, data.time{i}, cfg.preproc] = preproc(data.trial{i}, data.label, data.fsample, cfg.preproc, data.offset(i)); +end + +% determine the channels of interest +cfg.channel = ft_channelselection(cfg.channel, data.label); +chansel = match_str(data.label, cfg.channel); +nchan = length(cfg.channel); % number of channels +numsamples = zeros(ntrial,1); % number of selected samples in each trial, is determined later + +% determine the duration of each trial +for i=1:ntrial + begsamplatency(i) = min(data.time{i}); + endsamplatency(i) = max(data.time{i}); +end + +% automatically determine the latency window which is possible in all trials +minperlength = [max(begsamplatency) min(endsamplatency)]; +maxperlength = [min(begsamplatency) max(endsamplatency)]; +maxtrllength = round((max(endsamplatency)-min(begsamplatency))*data.fsample) + 1; % in samples +abstimvec = ([1:maxtrllength] + min(data.offset) -1)./data.fsample; % in seconds + +% latency window for averaging and variance computation is given in seconds +if (strcmp(cfg.latency, 'minperlength')) + cfg.latency = []; + cfg.latency(1) = minperlength(1); + cfg.latency(2) = minperlength(2); +end +if (strcmp(cfg.latency, 'maxperlength')) + cfg.latency = []; + cfg.latency(1) = maxperlength(1); + cfg.latency(2) = maxperlength(2); +end +if (strcmp(cfg.latency, 'prestim')) + cfg.latency = []; + cfg.latency(1) = maxperlength(1); + cfg.latency(2) = 0; +end +if (strcmp(cfg.latency, 'poststim')) + cfg.latency = []; + cfg.latency(1) = 0; + cfg.latency(2) = maxperlength(2); +end + +% check whether trial type (varlength) matches the user-specified type +switch cfg.vartrllength + case 0 + if ~all(minperlength==maxperlength) + error('data has variable trial lengths, you specified not to accept that !'); + end + case 1 + if all(minperlength==maxperlength) + disp('data is of type fixed length !'); + end + case 2 + if strcmp(cfg.keeptrials,'yes') + disp('processing and keeping variable length single trials'); + end + otherwise + error('unknown value for vartrllength'); +end + +% check whether the time window fits with the data +if (cfg.latency(1) < maxperlength(1)) cfg.latency(1) = maxperlength(1); + warning('Correcting begin latency of averaging window'); +end +if (cfg.latency(2) > maxperlength(2)) cfg.latency(2) = maxperlength(2); + warning('Correcting end latency of averaging window'); +end +if cfg.latency(1)>cfg.latency(2) + error('invalid latency window specified'); +end + +if strcmp(cfg.covariance, 'yes') + if ~isfield(cfg, 'covariancewindow') + % this used to be by default 'poststim', but that is not ideal as default + error('the option cfg.covariancewindow is required'); + end + % covariance window is given in seconds + if (strcmp(cfg.covariancewindow, 'minperlength')) + cfg.covariancewindow = []; + cfg.covariancewindow(1) = minperlength(1); + cfg.covariancewindow(2) = minperlength(2); + end + if (strcmp(cfg.covariancewindow, 'maxperlength')) + cfg.covariancewindow = []; + cfg.covariancewindow(1) = maxperlength(1); + cfg.covariancewindow(2) = maxperlength(2); + end + if (strcmp(cfg.covariancewindow, 'prestim')) + cfg.covariancewindow = []; + cfg.covariancewindow(1) = maxperlength(1); + cfg.covariancewindow(2) = 0; + end + if (strcmp(cfg.covariancewindow, 'poststim')) + cfg.covariancewindow = []; + cfg.covariancewindow(1) = 0; + cfg.covariancewindow(2) = maxperlength(2); + end + % check whether the time window fits with the data + if (cfg.covariancewindow(1) < maxperlength(1)) + cfg.covariancewindow(1) = maxperlength(1); + warning('Correcting begin latency of covariance window'); + end + if (cfg.covariancewindow(2) > maxperlength(2)) + cfg.covariancewindow(2) = maxperlength(2); + warning('Correcting end latency of covariance window'); + end + if cfg.covariancewindow(1)==cfg.covariancewindow(2) + error('Cannot compute covariance over a window of only one sample'); + end + if cfg.covariancewindow(1)>cfg.covariancewindow(2) + error('Cannot compute covariance over negative timewindow'); + end +end + +if strcmp(cfg.blcovariance, 'yes') + if ~isfield(cfg, 'blcovariancewindow') + % this used to be by default 'prestim', but that is not ideal as default + error('the option cfg.blcovariancewindow is required'); + end + % covariance window is given in seconds + if (strcmp(cfg.blcovariancewindow, 'minperlength')) + cfg.blcovariancewindow = []; + cfg.blcovariancewindow(1) = minperlength(1); + cfg.blcovariancewindow(2) = minperlength(2); + end + if (strcmp(cfg.blcovariancewindow, 'maxperlength')) + cfg.blcovariancewindow = []; + cfg.blcovariancewindow(1) = maxperlength(1); + cfg.blcovariancewindow(2) = maxperlength(2); + end + if (strcmp(cfg.blcovariancewindow, 'prestim')) + cfg.blcovariancewindow = []; + cfg.blcovariancewindow(1) = maxperlength(1); + cfg.blcovariancewindow(2) = 0; + end + if (strcmp(cfg.blcovariancewindow, 'poststim')) + cfg.blcovariancewindow = []; + cfg.blcovariancewindow(1) = 0; + cfg.blcovariancewindow(2) = maxperlength(2); + end + % check whether the time window fits with the data + if (cfg.blcovariancewindow(1) < maxperlength(1)) + cfg.blcovariancewindow(1) = maxperlength(1); + warning('Correcting begin latency of covariance window'); + end + if (cfg.blcovariancewindow(2) > maxperlength(2)) + cfg.blcovariancewindow(2) = maxperlength(2); + warning('Correcting end latency of covariance window'); + end + if cfg.blcovariancewindow(1)==cfg.blcovariancewindow(2) + error('Cannot compute covariance over a window of only one sample'); + end + if cfg.blcovariancewindow(1)>cfg.blcovariancewindow(2) + error('Cannot compute covariance over negative timewindow'); + end +end + +% pre-allocate some memory space for the covariance matrices +if strcmp(cfg.covariance, 'yes') + covsig = nan*zeros(ntrial, nchan, nchan); + numcovsigsamples = zeros(ntrial,1); +end +if strcmp(cfg.blcovariance, 'yes') + covbl = nan*zeros(ntrial, nchan, nchan); + numcovblsamples = zeros(ntrial,1); +end + +begsampl = nearest(abstimvec, cfg.latency(1)); +endsampl = nearest(abstimvec, cfg.latency(2)); +maxwin = endsampl-begsampl+1; +s = zeros(nchan, maxwin); % this will contain the sum +ss = zeros(nchan, maxwin); % this will contain the squared sum +dof = zeros(1, maxwin); +if (strcmp(cfg.keeptrials,'yes')) + singtrial = nan*zeros(ntrial, nchan, maxwin); +end + +progress('init', cfg.feedback, 'averaging trials'); +% do all the computations +for i=1:ntrial + % fprintf('averaging trial %d of %d\n', i, ntrial); + progress(i/ntrial, 'averaging trial %d of %d\n', i, ntrial); + + % determine whether the data in this trial can be used for all the requested computations + switch cfg.vartrllength + case 0 + % include this trial in any case since validation of data already done + usetrial = 1; + case 1 + % include this trial only if the data are complete in all specified windows + usetrial = 1; + if (begsamplatency(i)>cfg.latency(1) || endsamplatency(i)cfg.covariancewindow(1) || endsamplatency(i)cfg.blcovariancewindow(1) || endsamplatency(i)= cfg.latency(1)) + begsampl = nearest(data.time{i}, cfg.latency(1)); + endsampl = nearest(data.time{i}, cfg.latency(2)); + numsamples(i) = endsampl-begsampl+1; + if (cfg.latency(1). +% +% $Id: ft_timelockbaseline.m 1258 2010-06-22 08:33:48Z timeng $ -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +fieldtripdefs + +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +% set the defaults +if ~isfield(cfg, 'baseline'), cfg.baseline = 'no'; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +% load optional given inputfile as data +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + timelock = loadvar(cfg.inputfile, 'data'); + end +end + +% check if the input data is valid for this function +timelock = checkdata(timelock, 'datatype', 'timelock', 'feedback', 'yes'); + +% the cfg.blc/blcwindow options are used in preprocessing and in +% ft_timelockanalysis (i.e. in private/preproc), hence make sure that +% they can also be used here for consistency +if isfield(cfg, 'baseline') && (isfield(cfg, 'blc') || isfield(cfg, 'blcwindow')) + error('conflicting configuration options, you should use cfg.baseline'); +elseif isfield(cfg, 'blc') && strcmp(cfg.blc, 'no') + cfg.baseline = 'no'; + cfg = rmfield(cfg, 'blc'); + cfg = rmfield(cfg, 'blcwindow'); +elseif isfield(cfg, 'blc') && strcmp(cfg.blc, 'yes') + cfg.baseline = cfg.blcwindow; + cfg = rmfield(cfg, 'blc'); + cfg = rmfield(cfg, 'blcwindow'); +end + +if ischar(cfg.baseline) + if strcmp(cfg.baseline, 'yes') + % do correction on the whole time interval + cfg.baseline = [-inf inf]; + elseif strcmp(cfg.baseline, 'all') + % do correction on the whole time interval + cfg.baseline = [-inf inf]; + end +end + +if ~(ischar(cfg.baseline) && strcmp(cfg.baseline, 'no')) + % determine the time interval on which to apply baseline correction + tbeg = nearest(timelock.time, cfg.baseline(1)); + tend = nearest(timelock.time, cfg.baseline(2)); + % update the configuration + cfg.baseline(1) = timelock.time(tbeg); + cfg.baseline(2) = timelock.time(tend); + + if isfield(cfg, 'channel') + % only apply on selected channels + cfg.channel = ft_channelselection(cfg.channel, timelock.label); + chansel = match_str(timelock.label, cfg.channel); + timelock.avg(chansel,:) = ft_preproc_baselinecorrect(timelock.avg(chansel,:), tbeg, tend); + else + % apply on all channels + timelock.avg = ft_preproc_baselinecorrect(timelock.avg, tbeg, tend); + end + + if strcmp(timelock.dimord, 'rpt_chan_time') + fprintf('applying baseline correction on each individual trial\n'); + ntrial = size(timelock.trial,1); + if isfield(cfg, 'channel') + % only apply on selected channels + for i=1:ntrial + timelock.trial(i,chansel,:) = ft_preproc_baselinecorrect(shiftdim(timelock.trial(i,chansel,:),1), tbeg, tend); + end + else + % apply on all channels + for i=1:ntrial + timelock.trial(i,:,:) = ft_preproc_baselinecorrect(shiftdim(timelock.trial(i,:,:),1), tbeg, tend); + end + end + elseif strcmp(timelock.dimord, 'subj_chan_time') + fprintf('applying baseline correction on each individual subject\n'); + nsubj = size(timelock.individual,1); + if isfield(cfg, 'channel') + % only apply on selected channels + for i=1:nsubj + timelock.individual(i,chansel,:) = ft_preproc_baselinecorrect(shiftdim(timelock.individual(i,chansel,:),1), tbeg, tend); + end + else + % apply on all channels + for i=1:nsubj + timelock.individual(i,:,:) = ft_preproc_baselinecorrect(shiftdim(timelock.individual(i,:,:),1), tbeg, tend); + end + end + end + + if isfield(timelock, 'var') + fprintf('baseline correction invalidates previous variance estimate, removing var\n'); + timelock = rmfield(timelock, 'var'); + end + + if isfield(timelock, 'cov') + fprintf('baseline correction invalidates previous covariance estimate, removing cov\n'); + timelock = rmfield(timelock, 'cov'); + end + +end % ~strcmp(cfg.baseline, 'no') + +% accessing this field here is needed for the configuration tracking +% by accessing it once, it will not be removed from the output cfg +cfg.outputfile; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_timelockbaseline.m 1258 2010-06-22 08:33:48Z timeng $'; + +% remember the configuration details of the input data +try, cfg.previous = timelock.cfg; end + +% remember the exact configuration details in the output +timelock.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', timelock); % use the variable name "data" in the output file +end diff --git a/external/fieldtrip/ft_timelockdescriptives.m b/external/fieldtrip/ft_timelockdescriptives.m deleted file mode 100644 index b84b9b2..0000000 --- a/external/fieldtrip/ft_timelockdescriptives.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'ft_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_timelockgrandaverage.m b/external/fieldtrip/ft_timelockgrandaverage.m index b84b9b2..a335cd2 100644 --- a/external/fieldtrip/ft_timelockgrandaverage.m +++ b/external/fieldtrip/ft_timelockgrandaverage.m @@ -1,11 +1,199 @@ -function varargout = funname(varargin); +function [grandavg] = ft_timelockgrandaverage(cfg, varargin) -% this is a SPM wrapper around a FieldTrip function +% FT_TIMELOCKGRANDAVERAGE computes ERF/ERP average and variance +% over multiple subjects +% +% Use as +% [grandavg] = ft_timelockgrandaverage(cfg, avg1, avg2, avg3, ...) +% +% where +% avg1..N are the ERF/ERP averages as obtained from FT_TIMELOCKANALYSIS +% +% and cfg is a configuration structure with +% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), +% see FT_CHANNELSELECTION for details +% cfg.latency = [begin end] in seconds or 'all' (default = 'all') +% cfg.keepindividual = 'yes' or 'no' (default = 'no') +% cfg.normalizevar = 'N' or 'N-1' (default = 'N-1') +% +% See also FT_TIMELOCKANALYSIS, FT_TIMELOCKSTATISTICS +% +% Undocumented local options: +% cfg.inputfile = one can specifiy preanalysed saved data as input +% The data should be provided in a cell array +% cfg.outputfile = one can specify output as file to save to disk -% this part is variable -prefix = 'ft_'; +% Copyright (C) 2003-2006, Jens Schwarzbach +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_timelockgrandaverage.m 1273 2010-06-25 15:40:16Z timeng $ -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +fieldtripdefs + +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +% set the defaults +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +hasdata = nargin>2; +if ~isempty(cfg.inputfile) % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + for i=1:numel(cfg.inputfile) + varargin{i} = loadvar(cfg.inputfile{i}, 'data'); % read datasets from array inputfile + end + end +end + +% check if the input data is valid for this function +for i=1:length(varargin) + varargin{i} = checkdata(varargin{i}, 'datatype', 'timelock', 'feedback', 'no'); +end + +% set the defaults +if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end +if ~isfield(cfg, 'keepindividual'), cfg.keepindividual = 'no'; end +if ~isfield(cfg, 'latency'), cfg.latency = 'all'; end +if ~isfield(cfg, 'normalizevar'), cfg.normalizevar = 'N-1'; end + +% varargin{1} ... varargin{end} contain the individual ERFs +Nsubj = length(varargin); + +if isfield(varargin{1}, 'grad') + warning('discarding gradiometer information because it cannot be averaged'); +end +if isfield(varargin{1}, 'elec') + warning('discarding electrode information because it cannot be averaged'); +end + +% replace string latency selection by a timerange based on the range of all subjects +if ischar(cfg.latency) && strcmp(cfg.latency, 'all') + cfg.latency = []; + cfg.latency(1) = min(varargin{1}.time); + cfg.latency(2) = max(varargin{1}.time); + for s=2:Nsubj + % reset min/max latency (for variable trial length over subjects) + if min(varargin{s}.time) > cfg.latency(1) + cfg.latency(1) = min(varargin{s}.time); + end + if max(varargin{s}.time) < cfg.latency(2) + cfg.latency(2) = max(varargin{s}.time); + end + end +end + +%SELECT TIME WINDOW +idxs = nearest(varargin{1}.time, min(cfg.latency)); +idxe = nearest(varargin{1}.time, max(cfg.latency)); +% shift start and end index in case of flipped time axis (potentially introduced for response time locked data) +if idxe < idxs + ResultsTimeSelectCases = idxe:idxs; +else + ResultsTimeSelectCases = idxs:idxe; +end +ResultsNTimePoints = length(ResultsTimeSelectCases); +ResultsTime = varargin{1}.time(ResultsTimeSelectCases); + +%UPDATE CFG STRUCTURE WITH TIME THAT WAS FINALLY USED +cfg.latency = [ResultsTime(1), ResultsTime(end)]; + +%DETERMINE WHICH CHANNELS ARE AVAILABLE FOR ALL SUBJECTS +for i=1:Nsubj + cfg.channel = ft_channelselection(cfg.channel, varargin{i}.label); +end +ResultNChannels = size(cfg.channel, 1); + +%REDUCE DATASET TO INTERSECTION OF DESIRED AND AVAILABLE CHANNELS +for i=1:Nsubj + % select channel indices in this average, sorted according to configuration + [dum, chansel] = match_str(cfg.channel, varargin{i}.label); + varargin{i}.avg = varargin{i}.avg(chansel,:); + varargin{i}.label = varargin{i}.label(chansel); + try, varargin{i}.trial = varargin{i}.trial(chansel,:,:); end +end + +%PREALLOCATE +avgmat = zeros(Nsubj, ResultNChannels, ResultsNTimePoints); +%FILL MATRIX, MAY BE DONE MORE EFFECTIVELY WITH DEAL COMMAND +for s = 1:Nsubj + avgmat(s, :, :) = varargin{s}.avg(:, ResultsTimeSelectCases); +end + +%AVERAGE ACROSS SUBJECT DIMENSION +ResultGrandavg = mean(avgmat, 1); +ResultGrandavg = reshape(ResultGrandavg, [ResultNChannels, ResultsNTimePoints]); + +%COMPUTE VARIANCE ACROSS SUBJECT DIMENSION +%THIS LOOKS AWKWARD (std.^2) BUT IS FAST DUE TO BUILT IN FUNCTIONS +switch cfg.normalizevar + case 'N-1' + sdflag = 0; + case 'N' + sdflag = 1; +end +ResultVar = std(avgmat, sdflag, 1).^2; +ResultVar = reshape(ResultVar, [ResultNChannels, ResultsNTimePoints]); + +%-------------------------------------------- +% % collect the results +%-------------------------------------------- + +%SWITCH CHANNEL TO LABEL? +grandavg.label = cfg.channel; % cell-array +grandavg.fsample = varargin{1}.fsample; +grandavg.avg = ResultGrandavg; % Nchan x Nsamples +grandavg.var = ResultVar; % Nchan x Nsamples +grandavg.time = ResultsTime; % 1 x Nsamples + +%KEEP INDIVIDUAL MEANS? +if strcmp(cfg.keepindividual, 'yes') + grandavg.individual = avgmat; % Nsubj x Nchan x Nsamples + grandavg.dimord = 'subj_chan_time'; +else + grandavg.dimord = 'chan_time'; +end + +cfg.outputfile; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_timelockgrandaverage.m 1273 2010-06-25 15:40:16Z timeng $'; +% remember the configuration details of the input data +cfg.previous = []; +for i=1:length(varargin) + try, cfg.previous{i} = varargin{i}.cfg; end +end +% remember the exact configuration details in the output +grandavg.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', grandavg); % use the variable name "data" in the output file +end diff --git a/external/fieldtrip/ft_timelockstatistics.m b/external/fieldtrip/ft_timelockstatistics.m index b84b9b2..956201e 100644 --- a/external/fieldtrip/ft_timelockstatistics.m +++ b/external/fieldtrip/ft_timelockstatistics.m @@ -1,11 +1,147 @@ -function varargout = funname(varargin); +function [stat] = ft_timelockstatistics(cfg, varargin) -% this is a SPM wrapper around a FieldTrip function +% FT_TIMELOCKSTATISTICS computes significance probabilities and/or critical values of a parametric statistical test +% or a non-parametric permutation test. +% +% Use as +% [stat] = ft_timelockstatistics(cfg, timelock1, timelock2, ...) +% where the input data is the result from either FT_TIMELOCKANALYSIS or +% FT_TIMELOCKGRANDAVERAGE. +% +% The configuration can contain the following options for data selection +% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), +% see FT_CHANNELSELECTION for details +% cfg.latency = [begin end] in seconds or 'all' (default = 'all') +% cfg.avgoverchan = 'yes' or 'no' (default = 'no') +% cfg.avgovertime = 'yes' or 'no' (default = 'no') +% cfg.parameter = string (default = 'trial' or 'avg') +% +% Furthermore, the configuration should contain +% cfg.method = different methods for calculating the significance probability and/or critical value +% 'montecarlo' get Monte-Carlo estimates of the significance probabilities and/or critical values from the permutation distribution, +% 'analytic' get significance probabilities and/or critical values from the analytic reference distribution (typically, the sampling distribution under the null hypothesis), +% 'stats' use a parametric test from the Matlab statistics toolbox, +% 'glm' use a general linear model approach. +% +% The other cfg options depend on the method that you select. You +% should read the help of the respective subfunction STATISTICS_XXX +% for the corresponding configuration options and for a detailed +% explanation of each method. +% +% See also FT_TIMELOCKANALYSIS, FT_TIMELOCKGRANDAVERAGE +% +% Undocumented local options: +% cfg.inputfile = one can specifiy preanalysed saved data as input +% The data should be provided in a cell array +% cfg.outputfile = one can specify output as file to save to disk -% this part is variable -prefix = 'ft_'; -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +% This function depends on STATISTICS_WRAPPER + +% Copyright (C) 2005-2006, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_timelockstatistics.m 1273 2010-06-25 15:40:16Z timeng $ + +fieldtripdefs + +% set the defaults +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +hasdata = nargin>1; +if ~isempty(cfg.inputfile) % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + for i=1:numel(cfg.inputfile) + varargin{i} = loadvar(cfg.inputfile{i}, 'data'); % read datasets from array inputfile + end + end +end + +% % check if the input data is valid for this function +% for i=1:length(varargin) +% % FIXME at this moment (=10 May) this does not work, because the input might not always have an avg +% % See freqstatistics +% %varargin{i} = checkdata(varargin{i}, 'datatype', 'timelock', 'feedback', 'no'); +% end + +% the low-level data selection function does not know how to deal with other parameters, so work around it +if isfield(cfg, 'parameter') + if strcmp(cfg.parameter, 'trial') || strcmp(cfg.parameter, 'individual') + % this is dealt with correctly in the low-level code, even if an average is present + elseif strcmp(cfg.parameter, 'avg') + % this is only dealt with in the low-level code if no single-trial/individual data is present + for i=1:length(varargin) + if isfield(varargin{i}, 'trial') + varargin{i} = rmfield(varargin{i}, 'trial'); + end + if isfield(varargin{i}, 'individual') + varargin{i} = rmfield(varargin{i}, 'individual'); + end + end + else + % rename the parameter of interest into 'avg' + fprintf('renaming parameter ''%s'' into ''avg''\n', cfg.parameter); + for i=1:length(varargin) + dat = getsubfield(varargin{i}, cfg.parameter); + varargin{i} = rmsubfield (varargin{i}, cfg.parameter); + varargin{i} = setsubfield(varargin{i}, 'avg', dat); + if isfield(varargin{i}, 'trial') + varargin{i} = rmfield(varargin{i}, 'trial'); + end + if isfield(varargin{i}, 'individual') + varargin{i} = rmfield(varargin{i}, 'individual'); + end + end + end +end + +% call the general function +[stat, cfg] = statistics_wrapper(cfg, varargin{:}); + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_timelockstatistics.m 1273 2010-06-25 15:40:16Z timeng $'; + +% remember the configuration of the input data +cfg.previous = []; +for i=1:length(varargin) + if isfield(varargin{i}, 'cfg') + cfg.previous{i} = varargin{i}.cfg; + else + cfg.previous{i} = []; + end +end + +% remember the exact configuration details +stat.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', stat); % use the variable name "data" in the output file +end + diff --git a/external/fieldtrip/ft_topoplot.m b/external/fieldtrip/ft_topoplot.m deleted file mode 100644 index b84b9b2..0000000 --- a/external/fieldtrip/ft_topoplot.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'ft_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_topoplotCC.m b/external/fieldtrip/ft_topoplotCC.m new file mode 100644 index 0000000..6b7a90a --- /dev/null +++ b/external/fieldtrip/ft_topoplotCC.m @@ -0,0 +1,278 @@ +function cfg = ft_topoplotCC(cfg, freq) + +% FT_TOPOPLOTCC plots the connections between significantly coherent +% sensor pairs +% +% Use as +% ft_topoplotCC(cfg, freq) +% +% The configuration should contain: +% cfg.feedback = string (default = 'textbar') +% cfg.layout = specification of the layout, see FT_PREPARE_LAYOUT +% cfg.foi = the frequency of interest which is to be plotted (default is the first frequency bin) +% cfg.widthparam = string, parameter to be used to control the line width +% cfg.alphaparam = string, parameter to be used to control the opacity +% cfg.colorparam = string, parameter to be used to control the line color +% +% The widthparam should be indicated in pixels, e.g. usefull numbers are 1 +% and larger. +% +% The alphaparam should be indicated as opacity between 0 (fully transparent) +% and 1 (fully opaque). +% +% The default is to plot the connections as lines, but you can also use +% bidirectional arrows: +% cfg.arrowhead = none, stop, start, both (default = 'none') +% cfg.arrowsize = size of the arrow head (default = automatic) +% cfg.arrowoffset = amount that the arrow is shifted to the side (default = automatic) +% cfg.arrowlength = amount by which the length is reduced (default = 0.8) +% +% See also FT_PREPARE_LAYOUT, FT_MULTIPLOTCC +% +% Undocumented local options: +% cfg.inputfile = one can specifiy preanalysed saved data as input +% The data should be provided in a cell array + +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_topoplotCC.m 1430 2010-07-20 07:41:41Z roboos $ + +fieldtripdefs + + +% check if the input data is valid for this function +freq = checkdata(freq, 'cmbrepresentation', 'sparse'); + +% check if the input configuration is valid for this function +cfg = checkconfig(cfg, 'trackconfig', 'on'); +cfg = checkconfig(cfg, 'required', {'foi', 'layout'}); + +% set the defaults +if ~isfield(cfg, 'feedback'), cfg.feedback = 'text'; end +if ~isfield(cfg, 'alphaparam'), cfg.alphaparam = []; end +if ~isfield(cfg, 'widthparam'), cfg.widthparam = []; end +if ~isfield(cfg, 'colorparam'), cfg.colorparam = 'cohspctrm'; end +if ~isfield(cfg, 'newfigure'), cfg.newfigure = 'yes'; end + +if ~isfield(cfg, 'arrowhead'), cfg.arrowhead = 'none'; end % none, stop, start, both +if ~isfield(cfg, 'arrowsize'), cfg.arrowsize = nan; end % length of the arrow head, should be in in figure units, i.e. the same units as the layout +if ~isfield(cfg, 'arrowoffset'), cfg.arrowoffset = nan; end % absolute, should be in in figure units, i.e. the same units as the layout +if ~isfield(cfg, 'arrowlength'), cfg.arrowlength = 0.8; end % relative to the complete line + +lay = ft_prepare_layout(cfg, freq); + +beglabel = freq.labelcmb(:,1); +endlabel = freq.labelcmb(:,2); +ncmb = size(freq.labelcmb,1); + +% select the data to be used in the figure +fbin = nearest(freq.freq, cfg.foi); + +if isfield(freq, cfg.widthparam) + widthparam = freq.(cfg.widthparam)(:,fbin); +else + widthparam = ones(ncmb,1); +end + +if isfield(freq, cfg.alphaparam) + alphaparam = freq.(cfg.alphaparam)(:,fbin); +else + alphaparam = []; +end + +if isfield(freq, cfg.colorparam) + colorparam = freq.(cfg.colorparam)(:,:,fbin); +else + colorparam = []; +end + +if strcmp(cfg.newfigure, 'yes') + figure +end + +hold on +axis equal + +if isnan(cfg.arrowsize) + % use the size of the figure to estimate a decent number + siz = axis; + cfg.arrowsize = (siz(2) - siz(1))/50; + warning('using an arrowsize of %f', cfg.arrowsize); +end + +if isnan(cfg.arrowoffset) + % use the size of the figure to estimate a decent number + siz = axis; + cfg.arrowoffset = (siz(2) - siz(1))/100; + warning('using an arrowoffset of %f', cfg.arrowoffset); +end + +rgb = colormap; +if ~isempty(colorparam) + cmin = min(colorparam(:)); + cmax = max(colorparam(:)); + colorparam = (colorparam - cmin)./(cmax-cmin); + colorparam = round(colorparam * (size(rgb,1)-1) + 1); +end + +if strcmp(cfg.newfigure, 'yes') + % also plot the position of the electrodes + ft_plot_vector(lay.pos(:,1), lay.pos(:,2), 'style','k.'); + + % also plot the outline, i.e. head shape or sulci + if isfield(lay, 'outline') + fprintf('solid lines indicate the outline, e.g. head shape or sulci\n'); + for i=1:length(lay.outline) + if ~isempty(lay.outline{i}) + X = lay.outline{i}(:,1); + Y = lay.outline{i}(:,2); + ft_plot_line(X, Y, 'color', 'k', 'linewidth', 1.5, 'linestyle', '-'); + end + end + end + + % also plot the mask, i.e. global outline for masking the topoplot + if isfield(lay, 'mask') + fprintf('dashed lines indicate the mask for topograpic interpolation\n'); + for i=1:length(lay.mask) + if ~isempty(lay.mask{i}) + X = lay.mask{i}(:,1); + Y = lay.mask{i}(:,2); + % the polygon representing the mask should be closed + X(end+1) = X(1); + Y(end+1) = Y(1); + ft_plot_line(X, Y, 'color', 'k', 'linewidth', 1.5, 'linestyle', '-'); + end + end + end +end % if newfigure + +% fix the limits for the axis +axis(axis); + +progress('init', cfg.feedback, 'plotting connections...'); + +for i=1:ncmb + + if strcmp(beglabel{i}, endlabel{i}) + % skip autocombinations + continue + end + + progress(i/ncmb, 'plotting connection %d from %d (%s -> %s)\n', i, ncmb, beglabel{i}, endlabel{i}); + + if widthparam(i)>0 + begindx = strmatch(beglabel{i}, lay.label); + endindx = strmatch(endlabel{i}, lay.label); + xbeg = lay.pos(begindx,1); + ybeg = lay.pos(begindx,2); + xend = lay.pos(endindx,1); + yend = lay.pos(endindx,2); + + if strcmp(cfg.arrowhead, 'none') + x = [xbeg xend]'; + y = [ybeg yend]'; + % h = line(x, y); + h = patch(x, y, 1); + else + arrowbeg = [xbeg ybeg]; + arrowend = [xend yend]; + center = (arrowbeg+arrowend)/2; + direction = (arrowend - arrowbeg); + direction = direction/norm(direction); + offset = [direction(2) -direction(1)]; + arrowbeg = cfg.arrowlength * (arrowbeg-center) + center + cfg.arrowoffset * offset; + arrowend = cfg.arrowlength * (arrowend-center) + center + cfg.arrowoffset * offset; + + h = arrow(arrowbeg, arrowend, 'Ends', cfg.arrowhead, 'length', 0.05); + + end % if arrow + + if ~isempty(widthparam) + set(h, 'LineWidth', widthparam(i)); + end + + if ~isempty(alphaparam) + set(h, 'EdgeAlpha', alphaparam(i)); + set(h, 'FaceAlpha', alphaparam(i)); % for arrowheads + end + + if ~isempty(colorparam) + set(h, 'EdgeColor', rgb(colorparam(i),:)); + set(h, 'FaceColor', rgb(colorparam(i),:)); % for arrowheads + end + + end +end +progress('close'); + +% improve the fit in the axis +axis tight + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +if nargout<1 + clear cfg +end + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION for plotting arrows, see also fieldtrip/private/arrow +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function h = arrow(arrowbeg, arrowend, varargin) +ends = keyval('ends', varargin); +length = keyval('length', varargin); % the length of the arrow head, in figure units +color = [0 0 0]; % in RGB + +direction = (arrowend - arrowbeg); +direction = direction/norm(direction); +offset = [direction(2) -direction(1)]; + +pnt1 = arrowbeg; +pnt2 = arrowend; +h = patch([pnt1(1) pnt2(1)], [pnt1(2) pnt2(2)], color); + +switch ends + case 'stop' + pnt1 = arrowend - length*direction + 0.4*length*offset; + pnt2 = arrowend; + pnt3 = arrowend - length*direction - 0.4*length*offset; + h(end+1) = patch([pnt1(1) pnt2(1) pnt3(1)]', [pnt1(2) pnt2(2) pnt3(2)]', color); + + case 'start' + pnt1 = arrowbeg + length*direction + 0.4*length*offset; + pnt2 = arrowbeg; + pnt3 = arrowbeg + length*direction - 0.4*length*offset; + h(end+1) = patch([pnt1(1) pnt2(1) pnt3(1)]', [pnt1(2) pnt2(2) pnt3(2)]', color); + + case 'both' + pnt1 = arrowend - length*direction + 0.4*length*offset; + pnt2 = arrowend; + pnt3 = arrowend - length*direction - 0.4*length*offset; + h(end+1) = patch([pnt1(1) pnt2(1) pnt3(1)]', [pnt1(2) pnt2(2) pnt3(2)]', color); + + pnt1 = arrowbeg + length*direction + 0.4*length*offset; + pnt2 = arrowbeg; + pnt3 = arrowbeg + length*direction - 0.4*length*offset; + h(end+1) = patch([pnt1(1) pnt2(1) pnt3(1)]', [pnt1(2) pnt2(2) pnt3(2)]', color); + + case 'none' + % don't draw arrow heads +end + diff --git a/external/fieldtrip/ft_topoplotER.m b/external/fieldtrip/ft_topoplotER.m index b84b9b2..f0a6e69 100644 --- a/external/fieldtrip/ft_topoplotER.m +++ b/external/fieldtrip/ft_topoplotER.m @@ -1,11 +1,816 @@ -function varargout = funname(varargin); +function [cfg] = ft_topoplotER(cfg, varargin) -% this is a SPM wrapper around a FieldTrip function +% FT_TOPOPLOTER plots the topographic distribution of 2-Dimensional datatypes as +% event-related fields (ERF), potentials (ERP), the powerspectrum or coherence spectum +% that was computed using the FT_TIMELOCKALYSIS, FT_TIMELOCKGRANDAVERAGE, FT_FREQANALYSIS or +% FT_FREQDESCRIPTIVES functions, as a 2-D circular view (looking down at the top of the head). +% +% Use as: +% ft_topoplotER(cfg, data) +% +% cfg.xparam = first dimension in data in which a selection is made +% 'time' or 'freq' (default depends on data.dimord) +% cfg.zparam = field that contains the data to be plotted as color +% 'avg', 'powspctrm' or 'cohspctrm' (default depends on data.dimord) +% cfg.xlim = 'maxmin' or [xmin xmax] (default = 'maxmin') +% cfg.zlim = 'maxmin', 'maxabs' or [zmin zmax] (default = 'maxmin') +% cfg.cohrefchannel = name of reference channel for visualising coherence, can be 'gui' +% cfg.baseline = 'yes','no' or [time1 time2] (default = 'no'), see FT_TIMELOCKBASELINE or FT_FREQBASELINE +% cfg.baselinetype = 'absolute' or 'relative' (default = 'absolute') +% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') +% cfg.colormap = any sized colormap, see COLORMAP +% cfg.marker = 'on', 'labels', 'numbers', 'off' +% cfg.markersymbol = channel marker symbol (default = 'o') +% cfg.markercolor = channel marker color (default = [0 0 0] (black)) +% cfg.markersize = channel marker size (default = 2) +% cfg.markerfontsize = font size of channel labels (default = 8 pt) +% cfg.highlight = 'on', 'labels', 'numbers', 'off' +% cfg.highlightchannel = Nx1 cell-array with selection of channels, or vector containing channel indices see FT_CHANNELSELECTION +% cfg.highlightsymbol = highlight marker symbol (default = 'o') +% cfg.highlightcolor = highlight marker color (default = [0 0 0] (black)) +% cfg.highlightsize = highlight marker size (default = 6) +% cfg.highlightfontsize = highlight marker size (default = 8) +% cfg.colorbar = 'yes' +% 'no' (default) +% 'North' inside plot box near top +% 'South' inside bottom +% 'East' inside right +% 'West' inside left +% 'NorthOutside' outside plot box near top +% 'SouthOutside' outside bottom +% 'EastOutside' outside right +% 'WestOutside' outside left +% cfg.interplimits = limits for interpolation (default = 'head') +% 'electrodes' to furthest electrode +% 'head' to edge of head +% cfg.interpolation = 'linear','cubic','nearest','v4' (default = 'v4') see GRIDDATA +% cfg.style = plot style (default = 'both') +% 'straight' colormap only +% 'contour' contour lines only +% 'both' (default) both colormap and contour lines +% 'fill' constant color between lines +% 'blank' only the head shape +% cfg.gridscale = scaling grid size (default = 67) +% determines resolution of figure +% cfg.shading = 'flat' 'interp' (default = 'flat') +% cfg.comment = string 'no' 'auto' or 'xlim' (default = 'auto') +% 'auto': date, xparam and zparam limits are printed +% 'xlim': only xparam limits are printed +% cfg.commentpos = string or two numbers, position of comment (default 'leftbottom') +% 'lefttop' 'leftbottom' 'middletop' 'middlebottom' 'righttop' 'rightbottom' +% 'title' to place comment as title +% 'layout' to place comment as specified for COMNT in layout +% [x y] coordinates +% cfg.interactive = Interactive plot 'yes' or 'no' (default = 'no') +% In a interactive plot you can select areas and produce a new +% interactive plot when a selected area is clicked. Multiple areas +% can be selected by holding down the SHIFT key. +% cfg.layout = specification of the layout, see below +% +% The layout defines how the channels are arranged. You can specify the +% layout in a variety of ways: +% - you can provide a pre-computed layout structure (see prepare_layout) +% - you can give the name of an ascii layout file with extension *.lay +% - you can give the name of an electrode file +% - you can give an electrode definition, i.e. "elec" structure +% - you can give a gradiometer definition, i.e. "grad" structure +% If you do not specify any of these and the data structure contains an +% electrode or gradiometer structure, that will be used for creating a +% layout. If you want to have more fine-grained control over the layout +% of the subplots, you should create your own layout file. +% +% +% See also: +% ft_topoplotTFR, ft_topoplotIC, ft_singleplotER, ft_multiplotER, ft_prepare_layout -% this part is variable -prefix = 'ft_'; +% Undocumented local options: +% The following additional cfg parameters are used when plotting 3-dimensional +% data (i.e. when ft_topoplotTFR calls ft_topoplotER): +% cfg.yparam field to be plotted on y-axis +% cfg.ylim 'maxmin' or [ymin ymax] (default = 'maxmin') +% cfg.inputfile = one can specifiy preanalysed saved data as input +% The data should be provided in a cell array -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +% It is possible to use multiple highlight-selections (e.g.: multiple statistical clusters of channels) +% To do this, all the content of the highlight-options (including cfg.highlight) should be placed in a cell-array +% (even if the normal content was already in a cell-array). Specific marker settings (e.g. color, size) are defaulted when +% not present. +% Example (3 selections): +% cfg.highlight = {'labels', 'labels', 'numbers'} +% cfg.highlightchannel = {{'MZF03','MZC01','MRT54'}, [1:5], 'C*'} +% cfg.highlightsymbol = {'o',[],'+'} % the empty option will be defaulted +% cfg.highlightcolor = {'r',[0 0 1]}; % the missing option will be defaulted +% cfg.highlightsize = []; % will be set to default, as will the missing cfg.highlightfontsize +% +% Other options: +% cfg.labeloffset (offset of labels to their marker, default = 0.005) +% cfg.inputfile = one can specifiy preanalysed saved data as input +% The data should be provided in a cell array + +% This function depends on FT_TIMELOCKBASELINE which has the following options: +% cfg.baseline, documented +% cfg.channel +% cfg.blcwindow +% +% This function depends on FT_FREQBASELINE which has the following options: +% cfg.baseline, documented +% cfg.baselinetype + +% Copyright (C) 2005-2006, F.C. Donders Centre +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_topoplotER.m 1430 2010-07-20 07:41:41Z roboos $ + +fieldtripdefs + +cfg = checkconfig(cfg, 'trackconfig', 'on'); +cfg = checkconfig(cfg, 'unused', {'cohtargetchannel'}); + +cla + +% Multiple data sets are not supported for topoplot: +if length(varargin)>1 + error('Multiple data sets are not supported for topoplotER/topoplotTFR.'); +end + +% set default for inputfile +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end + +hasdata = nargin>1; +if ~isempty(cfg.inputfile) % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + for i=1:numel(cfg.inputfile) + varargin{i} = loadvar(cfg.inputfile{i}, 'data'); % read datasets from array inputfile + data = varargin{i}; + end + end +else + data = varargin{1}; +end + +% For backward compatibility with old data structures: +data = checkdata(data); + +% check for option-values to be renamed +cfg = checkconfig(cfg, 'renamedval', {'electrodes', 'dotnum', 'numbers'}); +cfg = checkconfig(cfg, 'renamedval', {'zlim', 'absmax', 'maxabs'}); +% check for renamed options +cfg = checkconfig(cfg, 'renamed', {'electrodes', 'marker'}); +cfg = checkconfig(cfg, 'renamed', {'emarker', 'markersymbol'}); +cfg = checkconfig(cfg, 'renamed', {'ecolor', 'markercolor'}); +cfg = checkconfig(cfg, 'renamed', {'emarkersize', 'markersize'}); +cfg = checkconfig(cfg, 'renamed', {'efontsize', 'markerfontsize'}); +cfg = checkconfig(cfg, 'renamed', {'hlmarker', 'highlightsymbol'}); +cfg = checkconfig(cfg, 'renamed', {'hlcolor', 'highlightcolor'}); +cfg = checkconfig(cfg, 'renamed', {'hlmarkersize', 'highlightsize'}); +cfg = checkconfig(cfg, 'renamed', {'maplimits', 'zlim'}); +% old checkconfig adapted partially from topoplot.m (backwards backwards compatability) +cfg = checkconfig(cfg, 'renamed', {'grid_scale', 'gridscale'}); +cfg = checkconfig(cfg, 'renamed', {'interpolate', 'interpolation'}); +cfg = checkconfig(cfg, 'renamed', {'numcontour', 'contournum'}); +cfg = checkconfig(cfg, 'renamed', {'electrod', 'marker'}); +cfg = checkconfig(cfg, 'renamed', {'electcolor', 'markercolor'}); +cfg = checkconfig(cfg, 'renamed', {'emsize', 'markersize'}); +cfg = checkconfig(cfg, 'renamed', {'efsize', 'markerfontsize'}); +cfg = checkconfig(cfg, 'renamed', {'headlimits', 'interplimits'}); + +% check for forbidden options +cfg = checkconfig(cfg, 'forbidden', {'hllinewidth'}); +cfg = checkconfig(cfg, 'forbidden', {'headcolor'}); +cfg = checkconfig(cfg, 'forbidden', {'hcolor'}); +cfg = checkconfig(cfg, 'forbidden', {'hlinewidth'}); +cfg = checkconfig(cfg, 'forbidden', {'contcolor'}); +cfg = checkconfig(cfg, 'forbidden', {'outline'}); +cfg = checkconfig(cfg, 'forbidden', {'highlightfacecolor'}); +cfg = checkconfig(cfg, 'forbidden', {'showlabels'}); +cfg = checkconfig(cfg, 'forbidden', {'hllinewidth'}); + +% Set other config defaults: +if ~isfield(cfg, 'xlim'), cfg.xlim = 'maxmin'; end +if ~isfield(cfg, 'ylim'), cfg.ylim = 'maxmin'; end +if ~isfield(cfg, 'zlim'), cfg.zlim = 'maxmin'; end +if ~isfield(cfg, 'style'), cfg.style = 'both'; end +if ~isfield(cfg, 'gridscale'), cfg.gridscale = 67; end +if ~isfield(cfg, 'interplimits'), cfg.interplimits = 'head'; end +if ~isfield(cfg, 'interpolation'), cfg.interpolation = 'v4'; end +if ~isfield(cfg, 'contournum'), cfg.contournum = 6; end +if ~isfield(cfg, 'colorbar'), cfg.colorbar = 'no'; end +if ~isfield(cfg, 'shading'), cfg.shading = 'flat'; end +if ~isfield(cfg, 'comment'), cfg.comment = 'auto'; end +if ~isfield(cfg, 'commentpos'), cfg.commentpos = 'leftbottom'; end +if ~isfield(cfg, 'fontsize'), cfg.fontsize = 8; end +if ~isfield(cfg, 'baseline'), cfg.baseline = 'no'; end %to avoid warning in timelock/freqbaseline +if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end +if ~isfield(cfg, 'interactive'), cfg.interactive = 'no'; end +if ~isfield(cfg, 'renderer'), cfg.renderer = []; end % matlab sets the default +if ~isfield(cfg, 'marker'), cfg.marker = 'on'; end +if ~isfield(cfg, 'markersymbol'), cfg.markersymbol = 'o'; end +if ~isfield(cfg, 'markercolor'), cfg.markercolor = [0 0 0]; end +if ~isfield(cfg, 'markersize'), cfg.markersize = 2; end +if ~isfield(cfg, 'markerfontsize'), cfg.markerfontsize = 8; end +if ~isfield(cfg, 'highlight'), cfg.highlight = 'off'; end +if ~isfield(cfg, 'highlightchannel'), cfg.highlightchannel = 'all'; end +if ~isfield(cfg, 'highlightsymbol'), cfg.highlightsymbol = '*'; end +if ~isfield(cfg, 'highlightcolor'), cfg.highlightcolor = [0 0 0]; end +if ~isfield(cfg, 'highlightsize'), cfg.highlightsize = 6; end +if ~isfield(cfg, 'highlightfontsize'), cfg.highlightfontsize = 8; end +if ~isfield(cfg, 'labeloffset'), cfg.labeloffset = 0.005; end +if ~isfield(cfg, 'maskparameter'), cfg.maskparameter = []; end +if ~isfield(cfg, 'component'), cfg.component = []; end +if ~isfield(cfg, 'matrixside'), cfg.matrixside = 'feedforward'; end + +% compatability for previous highlighting option +if isnumeric(cfg.highlight) + cfg.highlightchannel = cfg.highlight; + cfg.highlight = 'on'; + warning('cfg.highlight is now used for specifing highlighting-mode, use cfg.highlightchannel instead of cfg.highlight for specifiying channels') +elseif iscell(cfg.highlight) + if ~iscell(cfg.highlightchannel) + cfg.highlightchannel = cell(1,length(cfg.highlight)); + end + for icell = 1:length(cfg.highlight) + if isnumeric(cfg.highlight{icell}) + cfg.highlightchannel{icell} = cfg.highlight{icell}; + cfg.highlight{icell} = 'on'; + warning('cfg.highlight is now used for specifing highlighting-mode, use cfg.highlightchannel instead of cfg.highlight for specifiying channels') + end + end +end + +% Converting all higlight options to cell-arrays if they're not cell-arrays, to make defaulting and checking for backwards compatability and error +% checking much, much easier +if ~iscell(cfg.highlight), cfg.highlight = {cfg.highlight}; end +if ~iscell(cfg.highlightchannel), cfg.highlightchannel = {cfg.highlightchannel}; end +if ischar(cfg.highlightchannel{1}), cfg.highlightchannel = {cfg.highlightchannel}; end % {'all'} is valid input to channelselection, {1:5} isn't +if ~iscell(cfg.highlightsymbol), cfg.highlightsymbol = {cfg.highlightsymbol}; end +if ~iscell(cfg.highlightcolor), cfg.highlightcolor = {cfg.highlightcolor}; end +if ~iscell(cfg.highlightsize), cfg.highlightsize = {cfg.highlightsize}; end +if ~iscell(cfg.highlightfontsize), cfg.highlightfontsize = {cfg.highlightfontsize}; end +% then make sure all cell-arrays for options have length ncellhigh and default the last element if not present +ncellhigh = length(cfg.highlight); +if length(cfg.highlightsymbol) < ncellhigh, cfg.highlightsymbol{ncellhigh} = 'o'; end +if length(cfg.highlightcolor) < ncellhigh, cfg.highlightcolor{ncellhigh} = [0 0 0]; end +if length(cfg.highlightsize) < ncellhigh, cfg.highlightsize{ncellhigh} = 6; end +if length(cfg.highlightfontsize) < ncellhigh, cfg.highlightfontsize{ncellhigh} = 8; end +% then default all empty cells +for icell = 1:ncellhigh + if isempty(cfg.highlightsymbol{icell}), cfg.highlightsymbol{icell} = 'o'; end + if isempty(cfg.highlightcolor{icell}), cfg.highlightcolor{icell} = [0 0 0]; end + if isempty(cfg.highlightsize{icell}), cfg.highlightsize{icell} = 6; end + if isempty(cfg.highlightfontsize{icell}), cfg.highlightfontsize{icell} = 8; end +end + +% for backwards compatability +if strcmp(cfg.marker,'highlights') + warning('using cfg.marker option -highlights- is no longer used, please use cfg.highlight') + cfg.marker = 'off'; +end + +% check colormap is proper format and set it +if isfield(cfg,'colormap') + if size(cfg.colormap,2)~=3, error('topoplot(): Colormap must be a n x 3 matrix'); end + colormap(cfg.colormap); +end; + +% Set x/y/zparam defaults according to data.dimord value: +if strcmp(data.dimord, 'chan_time') + if ~isfield(cfg, 'xparam'), cfg.xparam='time'; end + if ~isfield(cfg, 'yparam'), cfg.yparam=''; end + if ~isfield(cfg, 'zparam'), cfg.zparam='avg'; end +elseif strcmp(data.dimord, 'chan_freq') + if ~isfield(cfg, 'xparam'), cfg.xparam='freq'; end + if ~isfield(cfg, 'yparam'), cfg.yparam=''; end + if ~isfield(cfg, 'zparam'), cfg.zparam='powspctrm'; end +elseif strcmp(data.dimord, 'subj_chan_time') || strcmp(data.dimord, 'rpt_chan_time') + tmpcfg = []; + tmpcfg.trials = cfg.trials; + data = ft_timelockanalysis(tmpcfg, data); + if ~isfield(cfg, 'xparam'), cfg.xparam='time'; end + if ~isfield(cfg, 'yparam'), cfg.yparam=''; end + if ~isfield(cfg, 'zparam'), cfg.zparam='avg'; end +elseif strcmp(data.dimord, 'subj_chan_freq') || strcmp(data.dimord, 'rpt_chan_freq') + if isfield(data, 'crsspctrm'), data = rmfield(data, 'crsspctrm'); end % on the fly computation of coherence spectrum is not supported + tmpcfg = []; + tmpcfg.trials = cfg.trials; + tmpcfg.jackknife = 'no'; + if isfield(cfg, 'zparam') && strcmp(cfg.zparam,'cohspctrm') + % on the fly computation of coherence spectrum is not supported + elseif isfield(cfg, 'zparam') && ~strcmp(cfg.zparam,'powspctrm') + % freqdesctiptives will only work on the powspctrm field, hence a temporary copy of the data is needed + tempdata.dimord = data.dimord; + tempdata.freq = data.freq; + tempdata.label = data.label; + tempdata.powspctrm = data.(cfg.zparam); + tempdata.cfg = data.cfg; + tempdata = ft_freqdescriptives(tmpcfg, tempdata); + data.(cfg.zparam) = tempdata.powspctrm; + clear tempdata + else + data = ft_freqdescriptives(tmpcfg, data); + end + if ~isfield(cfg, 'xparam'), cfg.xparam='freq'; end + if ~isfield(cfg, 'yparam'), cfg.yparam=''; end + if ~isfield(cfg, 'zparam'), cfg.zparam='powspctrm'; end +elseif strcmp(data.dimord, 'chan_freq_time') + if ~isfield(cfg, 'xparam'), cfg.xparam='time'; end + if ~isfield(cfg, 'yparam'), cfg.yparam='freq'; end + if ~isfield(cfg, 'zparam'), cfg.zparam='powspctrm'; end +elseif strcmp(data.dimord, 'subj_chan_freq_time') || strcmp(data.dimord, 'rpt_chan_freq_time') + if isfield(data, 'crsspctrm'), data = rmfield(data, 'crsspctrm'); end % on the fly computation of coherence spectrum is not supported + tmpcfg = []; + tmpcfg.trials = cfg.trials; + tmpcfg.jackknife = 'no'; + if isfield(cfg, 'zparam') && strcmp(cfg.zparam,'cohspctrm') + % on the fly computation of coherence spectrum is not supported + elseif isfield(cfg, 'zparam') && ~strcmp(cfg.zparam,'powspctrm') + % freqdesctiptives will only work on the powspctrm field, hence a temporary copy of the data is needed + tempdata.dimord = data.dimord; + tempdata.freq = data.freq; + tempdata.time = data.time; + tempdata.label = data.label; + tempdata.powspctrm = data.(cfg.zparam); + tempdata.cfg = data.cfg; + tempdata = ft_freqdescriptives(tmpcfg, tempdata); + data.(cfg.zparam) = tempdata.powspctrm; + clear tempdata + else + data = ft_freqdescriptives(tmpcfg, data); + end + if ~isfield(cfg, 'xparam'), cfg.xparam='time'; end + if ~isfield(cfg, 'yparam'), cfg.yparam='freq'; end + if ~isfield(cfg, 'zparam'), cfg.zparam='powspctrm'; end +elseif strcmp(data.dimord, 'chan_comp') + % Add a pseudo-axis with the component numbers: + data.comp = 1:size(data.topo,2); + % Specify the components + if ~isempty(cfg.component) + data.comp = cfg.component; + data.topo = data.topo(:,cfg.component); + end + % Rename the field with topographic label information: + data.label = data.topolabel; + if ~isfield(cfg, 'xparam'), cfg.xparam='comp'; end + if ~isfield(cfg, 'yparam'), cfg.yparam=''; end + if ~isfield(cfg, 'zparam'), cfg.zparam='topo'; end +else + if isfield(cfg, 'xparam') && isfield(cfg, 'zparam') && ~isfield(cfg, 'yparam') + % user specified own fields, but no yparam (which is not asked in help) + cfg.yparam = ''; + end +end + +% Read or create the layout that will be used for plotting: +lay = ft_prepare_layout(cfg, data); +cfg.layout = lay; + +% Create time-series of small topoplots: +if ~ischar(cfg.xlim) && length(cfg.xlim)>2 + % Switch off interactive mode: + cfg.interactive = 'no'; + xlims = cfg.xlim; + % Iteratively call topoplotER with different xlim values: + for i=1:length(xlims)-1 + subplot(ceil(sqrt(length(xlims)-1)), ceil(sqrt(length(xlims)-1)), i); + cfg.xlim = xlims(i:i+1); + ft_topoplotER(cfg, data); + end + return +end + +% Check for unconverted coherence spectrum data or any other bivariate metric: +dimtok = tokenize(data.dimord, '_'); +selchan = strmatch('chan', dimtok); +isfull = length(selchan)>1; +if (strcmp(cfg.zparam,'cohspctrm') && isfield(data, 'labelcmb')) || ... + (isfull && isfield(data, cfg.zparam)), + + % A reference channel is required: + if ~isfield(cfg,'cohrefchannel'), + error('no reference channel specified'); + end + + if strcmp(cfg.cohrefchannel, 'gui') + % Open a single figure with the channel layout, the user can click on a reference channel + h = clf; + ft_plot_lay(lay, 'box', false); + title('Select the reference channel by dragging a selection window, more than 1 channel can be selected...'); + % add the channel information to the figure + info = guidata(gcf); + info.x = lay.pos(:,1); + info.y = lay.pos(:,2); + info.label = lay.label; + guidata(h, info); + %set(gcf, 'WindowButtonUpFcn', {@ft_select_channel, 'callback', {@select_topoplotER, cfg, data}}); + set(gcf, 'WindowButtonUpFcn', {@ft_select_channel, 'multiple', true, 'callback', {@select_topoplotER, cfg, data}, 'event', 'WindowButtonUpFcn'}); + set(gcf, 'WindowButtonDownFcn', {@ft_select_channel, 'multiple', true, 'callback', {@select_topoplotER, cfg, data}, 'event', 'WindowButtonDownFcn'}); + set(gcf, 'WindowButtonMotionFcn', {@ft_select_channel, 'multiple', true, 'callback', {@select_topoplotER, cfg, data}, 'event', 'WindowButtonMotionFcn'}); + return + end + + if ~isfull, + % only works explicitly with coherence FIXME + % Convert 2-dimensional channel matrix to a single dimension: + sel1 = strmatch(cfg.cohrefchannel, data.labelcmb(:,2)); + sel2 = strmatch(cfg.cohrefchannel, data.labelcmb(:,1)); + fprintf('selected %d channels for coherence\n', length(sel1)+length(sel2)); + data.cohspctrm = data.cohspctrm([sel1;sel2],:,:); + data.label = [data.labelcmb(sel1,1);data.labelcmb(sel2,2)]; + data.labelcmb = data.labelcmb([sel1;sel2],:); + data = rmfield(data, 'labelcmb'); + else + % general solution + + sel = match_str(data.label, cfg.cohrefchannel); + siz = [size(data.(cfg.zparam)) 1]; + if strcmp(cfg.matrixside, 'feedback') + data.(cfg.zparam) = reshape(mean(data.(cfg.zparam)(:,sel,:),2),[siz(1) 1 siz(3:end)]); + elseif strcmp(cfg.matrixside, 'feedforward') + data.(cfg.zparam) = reshape(mean(data.(cfg.zparam)(sel,:,:),1),[siz(1) 1 siz(3:end)]); + elseif strcmp(cfg.matrixside, 'ff-fd') + data.(cfg.zparam) = reshape(mean(data.(cfg.zparam)(sel,:,:),1),[siz(1) 1 siz(3:end)]) - reshape(mean(data.(cfg.zparam)(:,sel,:),2),[siz(1) 1 siz(3:end)]); + elseif strcmp(cfg.matrixside, 'fd-ff') + data.(cfg.zparam) = reshape(mean(data.(cfg.zparam)(:,sel,:),2),[siz(1) 1 siz(3:end)]) - reshape(mean(data.(cfg.zparam)(sel,:,:),1),[siz(1) 1 siz(3:end)]); + end + end +end + +% Apply baseline correction: +if ~strcmp(cfg.baseline, 'no') + if strcmp(cfg.xparam, 'freq') || strcmp(cfg.yparam, 'freq') + data = ft_freqbaseline(cfg, data); + else + data = ft_timelockbaseline(cfg, data); + end +end + +% Get physical min/max range of x: +if strcmp(cfg.xlim,'maxmin') + xmin = min(getsubfield(data, cfg.xparam)); + xmax = max(getsubfield(data, cfg.xparam)); +else + xmin = cfg.xlim(1); + xmax = cfg.xlim(2); +end + +% Replace value with the index of the nearest bin +xmin = nearest(getsubfield(data, cfg.xparam), xmin); +xmax = nearest(getsubfield(data, cfg.xparam), xmax); + +% Get physical min/max range of y: +if ~isempty(cfg.yparam) + if strcmp(cfg.ylim,'maxmin') + ymin = min(getsubfield(data, cfg.yparam)); + ymax = max(getsubfield(data, cfg.yparam)); + else + ymin = cfg.ylim(1); + ymax = cfg.ylim(2); + end + + % Replace value with the index of the nearest bin: + ymin = nearest(getsubfield(data, cfg.yparam), ymin); + ymax = nearest(getsubfield(data, cfg.yparam), ymax); +end + +% make dat structure with one value for each channel +dat = getsubfield(data, cfg.zparam); +if ~isempty(cfg.yparam), + dat = dat(:, ymin:ymax, xmin:xmax); + dat = nanmean(nanmean(dat, 2), 3); + % if a component is specified, do nothing +elseif ~isempty(cfg.component), +else + dat = dat(:, xmin:xmax); + dat = nanmean(dat, 2); +end +dat = dat(:); + +% Select the channels in the data that match with the layout: +[seldat, sellay] = match_str(data.label, cfg.layout.label); +if isempty(seldat) + error('labels in data and labels in layout do not match'); +end + +datavector = dat(seldat); +% Select x and y coordinates and labels of the channels in the data +chanX = cfg.layout.pos(sellay,1); +chanY = cfg.layout.pos(sellay,2); +chanLabels = cfg.layout.label(sellay); + +% make datmask structure with one value for each channel +if ~isempty(cfg.maskparameter) + datmask = getsubfield(data, cfg.maskparameter); + if min(size(datmask)) ~= 1 || max(size(datmask)) ~= length(data.label) + error('data in cfg.maskparameter should be vector with one value per channel') + end + datmask = datmask(:); + % Select the channels in the maskdata that match with the layout: + maskdatavector = datmask(seldat); +else + maskdatavector = []; +end + +% Get physical min/max range of z: +if strcmp(cfg.zlim,'maxmin') + zmin = min(datavector); + zmax = max(datavector); +elseif strcmp(cfg.zlim,'maxabs') + zmin = -max(max(abs(datavector))); + zmax = max(max(abs(datavector))); +else + zmin = cfg.zlim(1); + zmax = cfg.zlim(2); +end + +% make comment +if strcmp(cfg.comment, 'auto') + comment = date; + if ~isempty(cfg.xparam) + if strcmp(cfg.xlim,'maxmin') + comment = sprintf('%0s\n%0s=[%.3g %.3g]', comment, cfg.xparam, data.(cfg.xparam)(xmin), data.(cfg.xparam)(xmax)); + else + comment = sprintf('%0s\n%0s=[%.3g %.3g]', comment, cfg.xparam, cfg.xlim(1), cfg.xlim(2)); + end + end + if ~isempty(cfg.yparam) + if strcmp(cfg.ylim,'maxmin') + comment = sprintf('%0s\n%0s=[%.3g %.3g]', comment, cfg.yparam, data.(cfg.yparam)(ymin), data.(cfg.yparam)(ymax)); + else + comment = sprintf('%0s\n%0s=[%.3g %.3g]', comment, cfg.yparam, cfg.ylim(1), cfg.ylim(2)); + end + end + if ~isempty(cfg.zparam) + comment = sprintf('%0s\n%0s=[%.3g %.3g]', comment, cfg.zparam, zmin, zmax); + end + cfg.comment = comment; +elseif strcmp(cfg.comment, 'xlim') + if strcmp(cfg.xlim,'maxmin') + comment = sprintf('%0s=[%.3g %.3g]', cfg.xparam, data.(cfg.xparam)(xmin), data.(cfg.xparam)(xmax)); + else + comment = sprintf('%0s=[%.3g %.3g]', cfg.xparam, cfg.xlim(1), cfg.xlim(2)); + end + cfg.comment = comment; +elseif ~ischar(cfg.comment) + error('cfg.comment must be string'); +end +if isfield(cfg,'cohrefchannel') + if iscell(cfg.cohrefchannel) + cfg.comment = sprintf('%s\nreference=%s %s', comment, cfg.cohrefchannel{:}); + else + cfg.comment = sprintf('%s\nreference=%s %s', comment, cfg.cohrefchannel); + end +end + +% Specify the x and y coordinates of the comment +if strcmp(cfg.commentpos,'layout') + ind_comment = strmatch('COMNT', cfg.layout.label); + x_comment = cfg.layout.pos(ind_comment,1); + y_comment = cfg.layout.pos(ind_comment,2); +elseif strcmp(cfg.commentpos,'lefttop') + x_comment = -0.7; + y_comment = 0.6; + HorAlign = 'left'; + VerAlign = 'top'; +elseif strcmp(cfg.commentpos,'leftbottom') + x_comment = -0.6; + y_comment = -0.6; + HorAlign = 'left'; + VerAlign = 'bottom'; +elseif strcmp(cfg.commentpos,'middletop') + x_comment = 0; + y_comment = 0.75; + HorAlign = 'center'; + VerAlign = 'top'; +elseif strcmp(cfg.commentpos,'middlebottom') + x_comment = 0; + y_comment = -0.7; + HorAlign = 'center'; + VerAlign = 'bottom'; +elseif strcmp(cfg.commentpos,'righttop') + x_comment = 0.65; + y_comment = 0.6; + HorAlign = 'right'; + VerAlign = 'top'; +elseif strcmp(cfg.commentpos,'rightbottom') + x_comment = 0.6; + y_comment = -0.6; + HorAlign = 'right'; + VerAlign = 'bottom'; +elseif isnumeric(cfg.commentpos) + x_comment = cfg.commentpos(1); + y_comment = cfg.commentpos(2); + HorAlign = 'left'; + VerAlign = 'middle'; + x_comment = 0.9*((x_comment-min(x))/(max(x)-min(x))-0.5); + y_comment = 0.9*((y_comment-min(y))/(max(y)-min(y))-0.5); +end + +% Draw topoplot +hold on +% Set ft_plot_topo specific options +if strcmp(cfg.interplimits,'head'), interplimits = 'mask'; +else interplimits = cfg.interplimits; end +if strcmp(cfg.style,'both'); style = 'surfiso'; end +if strcmp(cfg.style,'straight'); style = 'surf'; end +if strcmp(cfg.style,'contour'); style = 'iso'; end +if strcmp(cfg.style,'fill'); style = 'isofill'; end + +% Draw plot +if ~strcmp(cfg.style,'blank') + ft_plot_topo(chanX,chanY,datavector,'interpmethod',cfg.interpolation,... + 'interplim',interplimits,... + 'gridscale',cfg.gridscale,... + 'outline',lay.outline,... + 'shading',cfg.shading,... + 'isolines',cfg.contournum,... + 'mask',cfg.layout.mask,... + 'style',style,... + 'datmask', maskdatavector); +elseif ~strcmp(cfg.style,'blank') + ft_plot_lay(lay,'box','no','label','no','point','no') +end + +% Plotting markers for channels and/or highlighting a selection of channels +highlightchansel = []; % used for remembering selection of channels +templay.outline = lay.outline; +templay.mask = lay.mask; +% For Highlight (channel-selection) +for icell = 1:length(cfg.highlight) + if ~strcmp(cfg.highlight{icell},'off') + [dum labelindex] = match_str(ft_channelselection(cfg.highlightchannel{icell}, data.label), lay.label); + highlightchansel = [highlightchansel; match_str(data.label,ft_channelselection(cfg.highlightchannel{icell}, data.label))]; + templay.pos = lay.pos(labelindex,:); + templay.width = lay.width(labelindex); + templay.height = lay.height(labelindex); + templay.label = lay.label(labelindex); + if strcmp(cfg.highlight{icell}, 'labels') || strcmp(cfg.highlight{icell}, 'numbers') + labelflg = 1; + else + labelflg = 0; + end + if strcmp(cfg.highlight{icell}, 'numbers') + for ichan = 1:length(labelindex) + templay.label{ichan} = num2str(match_str(data.label,templay.label{ichan})); + end + end + ft_plot_lay(templay,'box','no','label',labelflg,'point','yes',... + 'pointsymbol',cfg.highlightsymbol{icell},... + 'pointcolor',cfg.highlightcolor{icell},... + 'pointsize',cfg.highlightsize{icell},... + 'labelsize',cfg.highlightfontsize{icell},... + 'labeloffset',cfg.labeloffset) + end +end % for icell +% For Markers (all channels) +if ~strcmp(cfg.marker,'off') + [dum labelindex] = match_str(ft_channelselection(setdiff(1:length(data.label),highlightchansel), data.label),lay.label); + templay.pos = lay.pos(labelindex,:); + templay.width = lay.width(labelindex); + templay.height = lay.height(labelindex); + templay.label = lay.label(labelindex); + if strcmp(cfg.marker, 'labels') || strcmp(cfg.marker, 'numbers') + labelflg = 1; + else + labelflg = 0; + end + if strcmp(cfg.marker, 'numbers') + for ichan = 1:length(labelindex) + templay.label{ichan} = num2str(match_str(data.label,templay.label{ichan})); + end + end + ft_plot_lay(templay,'box','no','label',labelflg,'point','yes',... + 'pointsymbol',cfg.markersymbol,... + 'pointcolor',cfg.markercolor,... + 'pointsize',cfg.markersize,... + 'labelsize',cfg.markerfontsize,... + 'labeloffset',cfg.labeloffset) +end + +% Set colour axis +caxis([zmin zmax]); + +% Write comment +if ~strcmp(cfg.comment,'no') + if strcmp(cfg.commentpos, 'title') + title(cfg.comment, 'Fontsize', cfg.fontsize); + else + ft_plot_text(x_comment,y_comment, cfg.comment, 'Fontsize', cfg.fontsize, 'HorizontalAlignment', 'left', 'VerticalAlignment', 'bottom'); + end +end + +% plot colorbar: +if isfield(cfg, 'colorbar') + if strcmp(cfg.colorbar, 'yes') + colorbar; + elseif ~strcmp(cfg.colorbar, 'no') + colorbar('location',cfg.colorbar); + end +end + +% Set renderer if specified +if ~isempty(cfg.renderer) + set(gcf, 'renderer', cfg.renderer) +end + +% The remainder of the code is meant to make the figure interactive +hold on; + +% Make the figure interactive +if strcmp(cfg.interactive, 'yes') + % add the channel information to the figure + info = guidata(gcf); + info.x = lay.pos(:,1); + info.y = lay.pos(:,2); + info.label = lay.label; + guidata(gcf, info); + + if any(strcmp(data.dimord, {'chan_time', 'chan_freq', 'subj_chan_time', 'rpt_chan_time', 'chan_chan_freq'})) + set(gcf, 'WindowButtonUpFcn', {@ft_select_channel, 'multiple', true, 'callback', {@select_singleplotER, cfg, varargin{:}}, 'event', 'WindowButtonUpFcn'}); + set(gcf, 'WindowButtonDownFcn', {@ft_select_channel, 'multiple', true, 'callback', {@select_singleplotER, cfg, varargin{:}}, 'event', 'WindowButtonDownFcn'}); + set(gcf, 'WindowButtonMotionFcn', {@ft_select_channel, 'multiple', true, 'callback', {@select_singleplotER, cfg, varargin{:}}, 'event', 'WindowButtonMotionFcn'}); + elseif any(strcmp(data.dimord, {'chan_freq_time', 'subj_chan_freq_time', 'rpt_chan_freq_time', 'rpttap_chan_freq_time'})) + set(gcf, 'WindowButtonUpFcn', {@ft_select_channel, 'multiple', true, 'callback', {@select_singleplotTFR, cfg, varargin{:}}, 'event', 'WindowButtonUpFcn'}); + set(gcf, 'WindowButtonDownFcn', {@ft_select_channel, 'multiple', true, 'callback', {@select_singleplotTFR, cfg, varargin{:}}, 'event', 'WindowButtonDownFcn'}); + set(gcf, 'WindowButtonMotionFcn', {@ft_select_channel, 'multiple', true, 'callback', {@select_singleplotTFR, cfg, varargin{:}}, 'event', 'WindowButtonMotionFcn'}); + else + error('unsupported dimord "%" for interactive plotting', data.dimord); + end +end + +axis off; +hold off; +axis equal; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION which is called after selecting channels in case of cfg.cohrefchannel='gui' +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function select_topoplotER(label, cfg, varargin) + +cfg.cohrefchannel = label; +fprintf('selected cfg.cohrefchannel = ''%s''\n', cfg.cohrefchannel{:}); +p = get(gcf, 'Position'); +f = figure; +set(f, 'Position', p); +cfg.highlight = 'on'; +cfg.highlightsymbol = '.'; +cfg.highlightcolor = 'r'; +cfg.highlightsize = 20; +cfg.highlightchannel = cfg.cohrefchannel; +ft_topoplotER(cfg, varargin{:}); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION which is called after selecting channels in case of cfg.interactive='yes' +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function select_singleplotER(label, cfg, varargin) +if ~isempty(label) + cfg.xlim = 'maxmin'; + cfg.channel = label; + fprintf('selected cfg.channel = {'); + for i=1:(length(cfg.channel)-1) + fprintf('''%s'', ', cfg.channel{i}); + end + fprintf('''%s''}\n', cfg.channel{end}); + p = get(gcf, 'Position'); + f = figure; + set(f, 'Position', p); + ft_singleplotER(cfg, varargin{:}); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION which is called after selecting channels in case of cfg.interactive='yes' +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function select_singleplotTFR(label, cfg, varargin) +if ~isempty(label) + cfg.xlim = 'maxmin'; + cfg.ylim = 'maxmin'; + cfg.channel = label; + fprintf('selected cfg.channel = {'); + for i=1:(length(cfg.channel)-1) + fprintf('''%s'', ', cfg.channel{i}); + end + fprintf('''%s''}\n', cfg.channel{end}); + p = get(gcf, 'Position'); + f = figure; + set(f, 'Position', p); + ft_singleplotTFR(cfg, varargin{:}); +end diff --git a/external/fieldtrip/ft_topoplotIC.m b/external/fieldtrip/ft_topoplotIC.m new file mode 100644 index 0000000..85323d0 --- /dev/null +++ b/external/fieldtrip/ft_topoplotIC.m @@ -0,0 +1,117 @@ +function [cfg] = ft_topoplotIC(cfg, varargin) + +% FT_TOPOPLOTIC plots the topographic distribution of an independent +% component that was computed using the FT_COMPONENTANALYSIS function, +% as a 2-D circular view (looking down at the top of the head). +% +% Use as +% ft_topoplotIC(cfg, data) +% +% The configuration should have the following parameters: +% cfg.component = field that contains the independent component(s) to be plotted as color +% cfg.layout = specification of the layout, see below +% +% The configuration can have the following parameters: +% cfg.colormap = any sized colormap, see COLORMAP +% cfg.marker = 'on', 'labels', 'numbers', 'off' +% cfg.markersymbol = channel marker symbol (default = 'o') +% cfg.markercolor = channel marker color (default = [0 0 0] (black)) +% cfg.markersize = channel marker size (default = 2) +% cfg.markerfontsize = font size of channel labels (default = 8 pt) +% cfg.highlight = 'on', 'labels', 'numbers', 'off' +% cfg.highlightchannel = Nx1 cell-array with selection of channels, or vector containing channel indices see FT_CHANNELSELECTION +% cfg.highlightsymbol = highlight marker symbol (default = 'o') +% cfg.highlightcolor = highlight marker color (default = [0 0 0] (black)) +% cfg.highlightsize = highlight marker size (default = 6) +% cfg.highlightfontsize = highlight marker size (default = 8) +% cfg.colorbar = 'yes' +% 'no' (default) +% 'North' inside plot box near top +% 'South' inside bottom +% 'East' inside right +% 'West' inside left +% 'NorthOutside' outside plot box near top +% 'SouthOutside' outside bottom +% 'EastOutside' outside right +% 'WestOutside' outside left +% cfg.interplimits = limits for interpolation (default = 'head') +% 'electrodes' to furthest electrode +% 'head' to edge of head +% cfg.interpolation = 'linear','cubic','nearest','v4' (default = 'v4') see GRIDDATA +% cfg.style = plot style (default = 'both') +% 'straight' colormap only +% 'contour' contour lines only +% 'both' (default) both colormap and contour lines +% 'fill' constant color between lines +% 'blank' only the head shape +% cfg.gridscale = scaling grid size (default = 67) +% determines resolution of figure +% cfg.shading = 'flat' 'interp' (default = 'flat') +% cfg.comment = string 'no' 'auto' or 'xlim' (default = 'auto') +% 'auto': date, xparam and zparam limits are printed +% 'xlim': only xparam limits are printed +% cfg.commentpos = string or two numbers, position of comment (default 'leftbottom') +% 'lefttop' 'leftbottom' 'middletop' 'middlebottom' 'righttop' 'rightbottom' +% 'title' to place comment as title +% 'layout' to place comment as specified for COMNT in layout +% [x y] coordinates +% +% The layout defines how the channels are arranged. You can specify the +% layout in a variety of ways: +% - you can provide a pre-computed layout structure (see prepare_layout) +% - you can give the name of an ascii layout file with extension *.lay +% - you can give the name of an electrode file +% - you can give an electrode definition, i.e. "elec" structure +% - you can give a gradiometer definition, i.e. "grad" structure +% If you do not specify any of these and the data structure contains an +% electrode or gradiometer structure, that will be used for creating a +% layout. If you want to have more fine-grained control over the layout +% of the subplots, you should create your own layout file. +% +% See also: +% ft_topoplotER, ft_singleplotTFR, ft_multiplotTFR, ft_prepare_layout + +% Undocumented local options: +% cfg.labeloffset (offset of labels to their marker, default = 0.005) + +% Copyright (C) 2010, Donders Centre for Cognitive Neuroimaging, Arjen Stolk +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id$ + +% config default +if ~isfield(cfg, 'component'), cfg.component = []; end + +% check whether cfg.component is speficied +if isempty(cfg.component) + error('this function requires the cfg.component parameter for input') +end + +% add a dimord +varargin{:}.dimord = 'chan_comp'; + +% create temporary variable +selcomp = cfg.component; + +% allow multiplotting +for i = 1:length(selcomp) + subplot(ceil(sqrt(length(selcomp))), ceil(sqrt(length(selcomp))), i); + cfg.component = selcomp(i); + ft_topoplotER(cfg, varargin{:}); + title(['component ' num2str(selcomp(i))]); +end diff --git a/external/fieldtrip/ft_topoplotTFR.m b/external/fieldtrip/ft_topoplotTFR.m index b84b9b2..2e15cef 100644 --- a/external/fieldtrip/ft_topoplotTFR.m +++ b/external/fieldtrip/ft_topoplotTFR.m @@ -1,11 +1,115 @@ -function varargout = funname(varargin); +function [cfg] = ft_topoplotTFR(cfg, varargin) -% this is a SPM wrapper around a FieldTrip function +% FT_TOPOPLOTTFR plots the topographic distribution of 3-Dimensional datatypes as +% the time-frequency representation of power or coherence that was computed +% using the FT_FREQANALYSIS or FT_FREQDESCRIPTIVES functions, as a 2-D circular +% view (looking down at the top of the head). +% +% Use as: +% ft_topoplotTFR(cfg, data) +% +% The configuration can have the following parameters: +% cfg.xparam = first dimension in data in which a selection is made +% 'time' or 'freq' (default depends on data.dimord) +% cfg.yparam = second dimension in data in which a selection is made +% 'freq' (default depends on data.dimord) +% cfg.zparam = field that contains the data to be plotted as color +% 'avg', 'powspctrm' or 'cohspctrm' (default depends on data.dimord) +% cfg.xlim = 'maxmin' or [xmin xmax] (default = 'maxmin') +% cfg.ylim = 'maxmin' or [ymin ymax] (default = 'maxmin') +% cfg.zlim = 'maxmin', 'maxabs' or [zmin zmax] (default = 'maxmin') +% cfg.cohrefchannel = name of reference channel for visualising coherence, can be 'gui' +% cfg.baseline = 'yes','no' or [time1 time2] (default = 'no'), see FT_TIMELOCKBASELINE or FT_FREQBASELINE +% cfg.baselinetype = 'absolute' or 'relative' (default = 'absolute') +% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') +% cfg.colormap = any sized colormap, see COLORMAP +% cfg.marker = 'on', 'labels', 'numbers', 'off' +% cfg.markersymbol = channel marker symbol (default = 'o') +% cfg.markercolor = channel marker color (default = [0 0 0] (black)) +% cfg.markersize = channel marker size (default = 2) +% cfg.markerfontsize = font size of channel labels (default = 8 pt) +% cfg.highlight = 'on', 'labels', 'numbers', 'off' +% cfg.highlightchannel = Nx1 cell-array with selection of channels, or vector containing channel indices see FT_CHANNELSELECTION +% cfg.highlightsymbol = highlight marker symbol (default = 'o') +% cfg.highlightcolor = highlight marker color (default = [0 0 0] (black)) +% cfg.highlightsize = highlight marker size (default = 6) +% cfg.highlightfontsize = highlight marker size (default = 8) +% cfg.colorbar = 'yes' +% 'no' (default) +% 'North' inside plot box near top +% 'South' inside bottom +% 'East' inside right +% 'West' inside left +% 'NorthOutside' outside plot box near top +% 'SouthOutside' outside bottom +% 'EastOutside' outside right +% 'WestOutside' outside left +% cfg.interplimits = limits for interpolation (default = 'head') +% 'electrodes' to furthest electrode +% 'head' to edge of head +% cfg.interpolation = 'linear','cubic','nearest','v4' (default = 'v4') see GRIDDATA +% cfg.style = plot style (default = 'both') +% 'straight' colormap only +% 'contour' contour lines only +% 'both' (default) both colormap and contour lines +% 'fill' constant color between lines +% 'blank' only the head shape +% cfg.gridscale = scaling grid size (default = 67) +% determines resolution of figure +% cfg.shading = 'flat' 'interp' (default = 'flat') +% cfg.comment = string 'no' 'auto' or 'xlim' (default = 'auto') +% 'auto': date, xparam and zparam limits are printed +% 'xlim': only xparam limits are printed +% cfg.commentpos = string or two numbers, position of comment (default 'leftbottom') +% 'lefttop' 'leftbottom' 'middletop' 'middlebottom' 'righttop' 'rightbottom' +% 'title' to place comment as title +% 'layout' to place comment as specified for COMNT in layout +% [x y] coordinates +% cfg.interactive = Interactive plot 'yes' or 'no' (default = 'no') +% In a interactive plot you can select areas and produce a new +% interactive plot when a selected area is clicked. Multiple areas +% can be selected by holding down the SHIFT key. +% cfg.layout = specification of the layout, see below +% +% The layout defines how the channels are arranged. You can specify the +% layout in a variety of ways: +% - you can provide a pre-computed layout structure (see prepare_layout) +% - you can give the name of an ascii layout file with extension *.lay +% - you can give the name of an electrode file +% - you can give an electrode definition, i.e. "elec" structure +% - you can give a gradiometer definition, i.e. "grad" structure +% If you do not specify any of these and the data structure contains an +% electrode or gradiometer structure, that will be used for creating a +% layout. If you want to have more fine-grained control over the layout +% of the subplots, you should create your own layout file. +% +% FT_TOPOPLOTTFR calls the function FT_TOPOPLOTER to do the plotting. +% +% See also: +% ft_topoplotER, ft_singleplotTFR, ft_multiplotTFR, ft_prepare_layout -% this part is variable -prefix = 'ft_'; +% Undocumented local options: +% cfg.labeloffset (offset of labels to their marker, default = 0.005) -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); + +% Copyright (C) 2005-2006, F.C. Donders Centre +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_topoplotTFR.m 948 2010-04-21 18:02:21Z roboos $ + +cfg=ft_topoplotER(cfg, varargin{:}); diff --git a/external/fieldtrip/ft_trialfun_general.m b/external/fieldtrip/ft_trialfun_general.m deleted file mode 100644 index b84b9b2..0000000 --- a/external/fieldtrip/ft_trialfun_general.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'ft_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_volumedownsample.m b/external/fieldtrip/ft_volumedownsample.m index b84b9b2..81dcfee 100644 --- a/external/fieldtrip/ft_volumedownsample.m +++ b/external/fieldtrip/ft_volumedownsample.m @@ -1,11 +1,168 @@ -function varargout = funname(varargin); +function [down] = ft_volumedownsample(cfg, source); -% this is a SPM wrapper around a FieldTrip function +% FT_VOLUMEDOWNSAMPLE downsamples an anatomical MRI or source reconstruction +% and optionally normalizes its coordinate axes, keeping the homogenous +% transformation matrix correct. +% +% Use as +% [volume] = ft_volumedownsample(cfg, volume) +% where the cconfiguration can contain +% cfg.downsample = integer number (default = 1, i.e. no downsampling) +% cfg.smooth = 'no' or the FWHM of the gaussian kernel in voxels (default = 'no') +% +% This function is used by FT_SOUREINTERPOLATE, FT_SOURCEREAD and FT_SOURCENORMALIZE. +% +% Undocumented local options: +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk -% this part is variable -prefix = 'ft_'; +% Copyright (C) 2004, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_volumedownsample.m 1259 2010-06-22 08:44:46Z jansch $ -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +fieldtripdefs + +%% checkdata see below!!! %% + +% check if the input cfg is valid for this function +cfg = checkconfig(cfg, 'trackconfig', 'on'); +cfg = checkconfig(cfg, 'unused', {'voxelcoord'}); + +if ~isfield(cfg, 'spmversion'), cfg.spmversion = 'spm8'; end +if ~isfield(cfg, 'downsample'), cfg.downsample = 1; end +if ~isfield(cfg, 'keepinside'), cfg.keepinside = 'yes'; end +if ~isfield(cfg, 'parameter'), cfg.parameter = 'all'; end +if ~isfield(cfg, 'smooth'), cfg.smooth = 'no'; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +% load optional given inputfile as data +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + source = loadvar(cfg.inputfile, 'data'); + end +end + +if strcmp(cfg.keepinside, 'yes') + % add inside to the list of parameters + if ~iscell(cfg.parameter), + cfg.parameter = {cfg.parameter 'inside'}; + else + cfg.parameter(end+1) = {'inside'}; + end +end + +% check if the input data is valid for this function +source = checkdata(source, 'datatype', 'volume', 'feedback', 'no'); + +%make local copy of source and remove all functional parameters +param = parameterselection('all', source); +down = source; +for k = 1:length(param) + down = rmsubfield(down, param{k}); +end + +% select the parameters that should be downsampled +cfg.parameter = parameterselection(cfg.parameter, source); + +% select the voxels that will be kept in the downsampled output volume +xsel = 1:cfg.downsample:source.dim(1); +ysel = 1:cfg.downsample:source.dim(2); +zsel = 1:cfg.downsample:source.dim(3); + +% store the coordinate transformation and downsampled axes definition +down.transform = source.transform; +down.xgrid = xsel; +down.ygrid = ysel; +down.zgrid = zsel; +down.dim = [length(xsel) length(ysel) length(zsel)]; +if length(source.dim)>3, + down.dim = [down.dim source.dim(4:end)]; +end + +% update the downsampled homogenous transformation matrix +down = grid2transform(down); + +% smooth functional parameters, excluding anatomy and inside +if ~strcmp(cfg.smooth, 'no'), + % check if the required spm is in your path: + if strcmpi(cfg.spmversion, 'spm2'), + hastoolbox('SPM2',1); + elseif strcmpi(cfg.spmversion, 'spm8'), + hastoolbox('SPM8',1); + end + + for j = 1:length(cfg.parameter) + if strcmp(cfg.parameter{j}, 'inside') + fprintf('not smoothing %s\n', cfg.parameter{j}); + elseif strcmp(cfg.parameter{j}, 'anatomy') + fprintf('not smoothing %s\n', cfg.parameter{j}); + else + fprintf('smoothing %s with a kernel of %d voxels\n', cfg.parameter{j}, cfg.smooth); + tmp = double(getsubfield(source, cfg.parameter{j})); + spm_smooth(tmp, tmp, cfg.smooth); + setsubfield(source, cfg.parameter{j}, tmp); + end + end +end + +% downsample each of the parameters +if cfg.downsample~=1 + for i=1:length(cfg.parameter) + fprintf('downsampling %s\n', cfg.parameter{i}); + tmp = getsubfield(source, cfg.parameter{i}); + down = setsubfield(down, cfg.parameter{i}, tmp(xsel, ysel, zsel)); % downsample the volume + end +else + for i=1:length(cfg.parameter) + fprintf('not downsampling %s\n', cfg.parameter{i}); + down = setsubfield(down, cfg.parameter{i}, reshape(getsubfield(source, cfg.parameter{i}), source.dim)); + end +end + +% accessing this field here is needed for the configuration tracking +% by accessing it once, it will not be removed from the output cfg +cfg.outputfile; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_volumedownsample.m 1259 2010-06-22 08:44:46Z jansch $'; +% remember the configuration details of the input data +try, cfg.previous = source.cfg; end +% remember the exact configuration details in the output +down.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', down); % use the variable name "data" in the output file +end diff --git a/external/fieldtrip/ft_volumelookup.m b/external/fieldtrip/ft_volumelookup.m new file mode 100644 index 0000000..34d94bd --- /dev/null +++ b/external/fieldtrip/ft_volumelookup.m @@ -0,0 +1,284 @@ +function [output] = ft_volumelookup(cfg, volume) + +% FT_VOLUMELOOKUP can be used in to combine an anatomical or functional +% atlas with source recunstruction. You can use it for forward and reverse +% lookup. +% +% Given the anatomical or functional label, it looks up the locations and +% creates a mask (as a binary volume) based on the label, or creates a +% sphere or box around a point of interest. In this case the function is to +% be used as: +% mask = ft_volumelookup(cfg, volume) +% +% Given a binary volume that indicates a region of interest, it looks up +% the corresponding anatomical or functional labels from a given atlas. In +% this case the function is to be used as follows: +% labels = ft_volumelookup(cfg, volume) +% +% In both cases the input volume can be: +% mri is the output of FT_READ_MRI +% source is the output of FT_SOURCEANALYSIS +% stat is the output of FT_SOURCESTATISTICS +% +% The configuration options for a mask according to an atlas: +% cfg.inputcoord = 'mni' or 'tal', coordinate system of the mri/source/stat +% cfg.atlas = string, filename of atlas to use, either the AFNI +% brik file that is available from http://afni.nimh.nih.gov/afni/doc/misc/ttatlas_tlrc, +% or the WFU atlasses available from http://fmri.wfubmc.edu. see FT_PREPARE_ATLAS +% cfg.roi = string or cell of strings, region(s) of interest from anatomical atlas +% +% The configuration options for a spherical/box mask around a point of interest: +% cfg.roi = Nx3 vector, coordinates of the points of interest +% cfg.sphere = radius of each sphere in cm/mm dep on unit of input +% cfg.box = Nx3 vector, size of each box in cm/mm dep on unit of input +% cfg.round2nearestvoxel = 'yes' or 'no' (default = 'no'), voxel closest to point of interest is calculated +% and box/sphere is centered around coordinates of that voxel +% +% The configuration options for labels from a mask: +% cfg.inputcoord = 'mni' or 'tal', coordinate system of the mri/source/stat +% cfg.atlas = string, filename of atlas to use, either the AFNI +% brik file that is available from http://afni.nimh.nih.gov/afni/doc/misc/ttatlas_tlrc, +% or the WFU atlasses available from http://fmri.wfubmc.edu. see FT_PREPARE_ATLAS +% cfg.maskparameter = string, field in volume to be lookedup, data in field should be logical +% cfg.maxqueryrange = number, should be 1, 3, 5 (default = 1) +% +% The label output has a field "names", a field "count" and a field "usedqueryrange" +% To get a list of areas of the given mask you can do for instance: +% [tmp ind] = sort(labels.count,1,'descend'); +% sel = find(tmp); +% for j = 1:length(sel) +% found_areas{j,1} = [num2str(labels.count(ind(j))) ': ' labels.name{ind(j)}]; +% end +% in found_areas you can then see how many times which labels are found +% NB in the AFNI brick one location can have 2 labels! +% +% Dependent on the input coordinates and the coordinates of the atlas, the +% input MRI is transformed betweem MNI and Talairach-Tournoux coordinates +% See http://www.mrc-cbu.cam.ac.uk/Imaging/Common/mnispace.shtml for more details. + +% Copyright (C) 2008, Robert Oostenveld, Ingrid Nieuwenhuis +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_volumelookup.m 962 2010-04-25 06:32:37Z roboos $ + +fieldtripdefs + +roi2mask = 0; +mask2label = 0; +if isfield(cfg, 'roi'); + roi2mask = 1; +elseif isfield(cfg, 'maskparameter') + mask2label = 1; +else + error('either specify cfg.roi, or cfg.maskparameter') +end + +if roi2mask + % only for volume data + volume = checkdata(volume, 'datatype', 'volume'); + + % set the defaults + if ~isfield(cfg, 'round2nearestvoxel'), cfg.round2nearestvoxel = 'no'; end + + if iscell(cfg.roi) || ischar(cfg.roi) + checkconfig(cfg, 'forbidden', {'sphere' 'box'}, 'required', {'atlas' 'inputcoord'}); + isatlas = 1; + ispoi = 0; + elseif isnumeric(cfg.roi) + checkconfig(cfg, 'forbidden', {'atlas' 'inputcoord'}); + isatlas = 0; + ispoi = 1; + else + error('do not understand cfg.roi') + end + + % determine location of each anatomical voxel in its own voxel coordinates + dim = volume.dim; + i = 1:dim(1); + j = 1:dim(2); + k = 1:dim(3); + [I, J, K] = ndgrid(i, j, k); + ijk = [I(:) J(:) K(:) ones(prod(dim),1)]'; + % determine location of each anatomical voxel in head coordinates + xyz = volume.transform * ijk; % note that this is 4xN + + if isatlas + atlas = ft_prepare_atlas(cfg.atlas); + + if ischar(cfg.roi) + cfg.roi = {cfg.roi}; + end + + sel = []; + for i = 1:length(cfg.roi) + sel = [sel; strmatch(cfg.roi{i}, atlas.descr.name, 'exact')]; + end + + fprintf('found %d matching anatomical labels\n', length(sel)); + + brick = atlas.descr.brick(sel); + value = atlas.descr.value(sel); + + % convert between MNI head coordinates and TAL head coordinates + % coordinates should be expressed compatible with the atlas + if strcmp(cfg.inputcoord, 'mni') && strcmp(atlas.coord, 'tal') + xyz(1:3,:) = mni2tal(xyz(1:3,:)); + elseif strcmp(cfg.inputcoord, 'mni') && strcmp(atlas.coord, 'mni') + % nothing to do + elseif strcmp(cfg.inputcoord, 'tal') && strcmp(atlas.coord, 'tal') + % nothing to do + elseif strcmp(cfg.inputcoord, 'tal') && strcmp(atlas.coord, 'mni') + xyz(1:3,:) = tal2mni(xyz(1:3,:)); + end + + % determine location of each anatomical voxel in atlas voxel coordinates + ijk = inv(atlas.transform) * xyz; + ijk = round(ijk(1:3,:))'; + + inside_vol = ijk(:,1)>=1 & ijk(:,1)<=atlas.dim(1) & ... + ijk(:,2)>=1 & ijk(:,2)<=atlas.dim(2) & ... + ijk(:,3)>=1 & ijk(:,3)<=atlas.dim(3); + inside_vol = find(inside_vol); + + % convert the selection inside the atlas volume into linear indices + ind = sub2ind(atlas.dim, ijk(inside_vol,1), ijk(inside_vol,2), ijk(inside_vol,3)); + + brick0_val = zeros(prod(dim),1); + brick1_val = zeros(prod(dim),1); + % search the two bricks for the value of each voxel + brick0_val(inside_vol) = atlas.brick0(ind); + brick1_val(inside_vol) = atlas.brick1(ind); + + mask = zeros(prod(dim),1); + for i=1:length(sel) + fprintf('constructing mask for %s\n', atlas.descr.name{sel(i)}); + if brick(i)==0 + mask = mask | (brick0_val==value(i)); + elseif brick(i)==1 + mask = mask | (brick1_val==value(i)); + end + end + + elseif ispoi + + if strcmp(cfg.round2nearestvoxel, 'yes') + for i=1:size(cfg.roi,1) + cfg.roi(i,:) = poi2voi(cfg.roi(i,:), xyz); + end + end + + % sphere(s) + if isfield(cfg, 'sphere') + mask = zeros(1,prod(dim)); + for i=1:size(cfg.roi,1) + dist = sqrt( (xyz(1,:) - cfg.roi(i,1)).^2 + (xyz(2,:) - cfg.roi(i,2)).^2 + (xyz(3,:) - cfg.roi(i,3)).^2 ); + mask = mask | (dist <= cfg.sphere(i)); + end + % box(es) + elseif isfield(cfg, 'box') + mask = zeros(1, prod(dim)); + for i=1:size(cfg.roi,1) + mask = mask | ... + (xyz(1,:) <= (cfg.roi(i,1) + cfg.box(i,1)./2) & xyz(1,:) >= (cfg.roi(i,1) - cfg.box(i,1)./2)) & ... + (xyz(2,:) <= (cfg.roi(i,2) + cfg.box(i,2)./2) & xyz(2,:) >= (cfg.roi(i,2) - cfg.box(i,2)./2)) & ... + (xyz(3,:) <= (cfg.roi(i,3) + cfg.box(i,3)./2) & xyz(3,:) >= (cfg.roi(i,3) - cfg.box(i,3)./2)); + end + else + error('either specify cfg.sphere or cfg.box') + end + end + + mask = reshape(mask, dim); + fprintf('%i voxels in mask, which is %.3f %% of total volume\n', sum(mask(:)), 100*mean(mask(:))); + output = mask; + +elseif mask2label + % convert to source representation (easier to work with) + volume = checkdata(volume, 'datatype', 'source'); + checkconfig(cfg, 'required', {'atlas' 'inputcoord'}); + + % set defaults + if ~isfield(cfg, 'maxqueryrange'), cfg.maxqueryrange = 1; end + + if isempty(intersect(cfg.maxqueryrange, [1 3 5])) + error('incorrect query range, should be one of [1 3 5]'); + end + + atlas = ft_prepare_atlas(cfg.atlas); + sel = find(volume.(cfg.maskparameter)(:)); + labels.name = atlas.descr.name; + labels.name{end+1} = 'no_label_found'; + labels.count = zeros(length(labels.name),1); + for iLab = 1:length(labels.name) + labels.usedqueryrange{iLab} = []; + end + + for iVox = 1:length(sel) + usedQR = 1; + label = atlas_lookup(atlas, [volume.pos(sel(iVox),1) volume.pos(sel(iVox),2) volume.pos(sel(iVox),3)], 'inputcoord', cfg.inputcoord, 'queryrange', 1); + if isempty(label) && cfg.maxqueryrange > 1 + label = atlas_lookup(atlas, [volume.pos(sel(iVox),1) volume.pos(sel(iVox),2) volume.pos(sel(iVox),3)], 'inputcoord', cfg.inputcoord, 'queryrange', 3); + usedQR = 3; + end + if isempty(label) && cfg.maxqueryrange > 3 + label = atlas_lookup(atlas, [volume.pos(sel(iVox),1) volume.pos(sel(iVox),2) volume.pos(sel(iVox),3)], 'inputcoord', cfg.inputcoord, 'queryrange', 5); + usedQR = 5; + end + if isempty(label) + label = {'no_label_found'}; + elseif length(label) == 1 + label = {label}; + end + + ind_lab = []; + for iLab = 1:length(label) + ind_lab = [ind_lab find(strcmp(label{iLab}, labels.name))]; + end + + labels.count(ind_lab) = labels.count(ind_lab) + (1/length(ind_lab)); + for iFoundLab = 1:length(ind_lab) + if isempty(labels.usedqueryrange{ind_lab(iFoundLab)}) + labels.usedqueryrange{ind_lab(iFoundLab)} = usedQR; + else + labels.usedqueryrange{ind_lab(iFoundLab)} = [labels.usedqueryrange{ind_lab(iFoundLab)} usedQR]; + end + end + end %iVox + + output = labels; + +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION point of interest to voxel of interest +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function voi = poi2voi(poi, xyz) +xmin = min(abs(xyz(1,:) - poi(1))); xcl = round(abs(xyz(1,:) - poi(1))) == round(xmin); +ymin = min(abs(xyz(2,:) - poi(2))); ycl = round(abs(xyz(2,:) - poi(2))) == round(ymin); +zmin = min(abs(xyz(3,:) - poi(3))); zcl = round(abs(xyz(3,:) - poi(3))) == round(zmin); +xyzcls = xcl + ycl + zcl; ind_voi = xyzcls == 3; +if sum(ind_voi) > 1; + fprintf('%i voxels at same distance of poi, taking first voxel\n', sum(ind_voi)) + ind_voi_temp = find(ind_voi); ind_voi_temp = ind_voi_temp(1); + ind_voi = zeros(size(ind_voi)); + ind_voi(ind_voi_temp) = 1; + ind_voi = logical(ind_voi); +end +voi = xyz(1:3,ind_voi); +fprintf('coordinates of voi: %.1f %.1f %.1f\n', voi(1), voi(2), voi(3)); + diff --git a/external/fieldtrip/ft_volumenormalise.m b/external/fieldtrip/ft_volumenormalise.m index b84b9b2..3471a0d 100644 --- a/external/fieldtrip/ft_volumenormalise.m +++ b/external/fieldtrip/ft_volumenormalise.m @@ -1,11 +1,370 @@ -function varargout = funname(varargin); +function [normalise] = ft_volumenormalise(cfg, interp) -% this is a SPM wrapper around a FieldTrip function +% FT_VOLUMENORMALISE normalises anatomical and functional volume data +% to a template anatomical MRI. +% +% Use as +% [volume] = ft_volumenormalise(cfg, volume) +% +% The input volume should be the result from FT_SOURCEINTERPOLATE. +% Alternatively, the input can contain a single anatomical MRI that +% was read with READ_FCDC_MRI, or you can specify a filename of an +% anatomical MRI. +% +% Configuration options are: +% cfg.spmversion = 'spm8' (default) or 'spm2' +% cfg.template = filename of the template anatomical MRI (default is the 'T1.mnc' (spm2) or 'T1.nii' (spm8) +% in the (spm-directory)/templates/) +% cfg.parameter = cell-array with the functional data which has to +% be normalised, can be 'all' +% cfg.downsample = integer number (default = 1, i.e. no downsampling) +% cfg.coordinates = 'spm, 'ctf' or empty for interactive (default = []) +% cfg.name = string for output filename +% cfg.write = 'no' (default) or 'yes', writes the segmented volumes to SPM2 +% compatible analyze-file, with the suffix +% _anatomy for the anatomical MRI volumeFT_ +% _param for each of the functional volumes +% cfg.nonlinear = 'yes' (default) or 'no', estimates a nonlinear transformation +% in addition to the linear affine registratFT_ion. If a reasonably +% accurate normalisation is sufficient, a purely linearly transformed +% image allows for 'reverse-normalisation', which might come in handy +% when for example a region of interest is dFT_efined on the normalised +% group-average. -% this part is variable -prefix = 'ft_'; +% Undocumented local options: +% cfg.keepintermediate = 'yes' or 'no' +% cfg.intermediatename = prefix of the the coregistered images and of the +% original images in the original headcFT_oordinate system +% cfg.spmparams = one can feed in parameters from a prior normalisation +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +% Copyright (C) 2004-2006, Jan-Mathijs Schoffelen +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_volumenormalise.m 1263 2010-06-23 15:40:37Z timeng $ + +fieldtripdefs + +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +%% checkdata see below!!! %% + +% set the defaults +if ~isfield(cfg,'spmversion'), cfg.spmversion = 'spm8'; end +if ~isfield(cfg,'parameter'), cfg.parameter = 'all'; end; +if ~isfield(cfg,'downsample'), cfg.downsample = 1; end; +if ~isfield(cfg,'write'), cfg.write = 'no'; end; +if ~isfield(cfg,'keepinside'), cfg.keepinside = 'yes'; end; +if ~isfield(cfg,'keepintermediate'), cfg.keepintermediate = 'no'; end; +if ~isfield(cfg,'coordinates'), cfg.coordinates = []; end; +if ~isfield(cfg,'initial'), cfg.initial = []; end; +if ~isfield(cfg,'nonlinear'), cfg.nonlinear = 'yes'; end; +if ~isfield(cfg,'smooth'), cfg.smooth = 'no'; end; +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end; +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end; + +% load optional given inputfile as data +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + interp = loadvar(cfg.inputfile, 'data'); + hasdata = true; + end +end + +% check if the required spm is in your path: +if strcmpi(cfg.spmversion, 'spm2'), + hastoolbox('SPM2',1); +elseif strcmpi(cfg.spmversion, 'spm8'), + hastoolbox('SPM8',1); +end + +if ~isfield(cfg, 'template'), + spmpath = spm('dir'); + if strcmpi(cfg.spmversion, 'spm8'), cfg.template = [spmpath,filesep,'templates',filesep,'T1.nii']; end + if strcmpi(cfg.spmversion, 'spm2'), cfg.template = [spmpath,filesep,'templates',filesep,'T1.mnc']; end +end + +if strcmp(cfg.keepinside, 'yes') + % add inside to the list of parameters + if ~iscell(cfg.parameter), + cfg.parameter = {cfg.parameter 'inside'}; + else + cfg.parameter(end+1) = {'inside'}; + end +end + +if ~isfield(cfg,'intermediatename') + cfg.intermediatename = tempname; +end + +if ~isfield(cfg,'name') && strcmp(cfg.write,'yes') + error('you must specify the output filename in cfg.name'); +end + +if isempty(cfg.template), + error('you must specify a template anatomical MRI'); +end + +if ~isfield(interp,'anatomy'), + error('no anatomical information available, this is required for normalisation'); +end + +if isfield(cfg, 'coordinates') + source_coordinates = cfg.coordinates; +end + +% the template anatomy should always be stored in a SPM-compatible file +template_ftype = ft_filetype(cfg.template); +if strcmp(template_ftype, 'analyze_hdr') || strcmp(template_ftype, 'analyze_img') || strcmp(template_ftype, 'minc') || strcmp(template_ftype, 'nifti') + % based on the filetype assume that the coordinates correspond with MNI/SPM convention + template_coordinates = 'spm'; +end + +% the source anatomy can be in a file that is not understood by SPM (e.g. in the +% native CTF *.mri format), therefore start by reading it into memory +if ischar(interp), + fprintf('reading source MRI from file\n'); + filename = interp; + interp = ft_read_mri(filename); + if ft_filetype(filename, 'ctf_mri') + % based on the filetype assume that the coordinates correspond with CTF convention + source_coordinates = 'ctf'; + end +end + +% check if the input data is valid for this function +interp = checkdata(interp, 'datatype', 'volume', 'feedback', 'yes'); + +% select the parameters that should be normalised +cfg.parameter = parameterselection(cfg.parameter, interp); + +% the anatomy should always be normalised as the first volume +sel = strcmp(cfg.parameter, 'anatomy'); +if ~any(sel) + cfg.parameter = {'anatomy' cfg.parameter{:}}; +else + [dum, indx] = sort(sel); + cfg.parameter = cfg.parameter(fliplr(indx)); +end + +% downsample the volume +tmpcfg = []; +tmpcfg.downsample = cfg.downsample; +tmpcfg.parameter = cfg.parameter; +tmpcfg.smooth = cfg.smooth; +tmpcfg.outputfile = cfg.outputfile; +interp = ft_volumedownsample(tmpcfg, interp); + +if isempty(source_coordinates) + source_coordinates = determine_coordinates('input'); % use interactive helper-function +end +if isempty(template_coordinates) + template_coordinates = determine_coordinates('template'); % use interactive helper-function +end + +% ensure that the source volume is approximately aligned with the template +if strcmp(source_coordinates, 'ctf') && strcmp(template_coordinates, 'spm') + fprintf('converting input coordinates from CTF into approximate SPM coordinates\n'); + initial = [ + 0.0000 -1.0000 0.0000 0.0000 + 0.9987 0.0000 -0.0517 -32.0000 + 0.0517 0.0000 0.9987 -54.0000 + 0.0000 0.0000 0.0000 1.0000 ]; +elseif strcmp(source_coordinates, template_coordinates) + fprintf('not converting input coordinates\n'); + initial = eye(4); +else + error('cannot determine the approximate alignmenmt of the source coordinates with the template'); +end + +% apply the approximate transformatino prior to passing it to SPM +interp.transform = initial * interp.transform; + +ws = warning('off'); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% here the normalisation starts +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% create an spm-compatible header for the anatomical volume data +VF = volumewrite_spm([cfg.intermediatename,'_anatomy.img'], interp.anatomy, interp.transform, cfg.spmversion); + +% create an spm-compatible file for each of the functional volumes +for parlop=2:length(cfg.parameter) % skip the anatomy + tmp = cfg.parameter{parlop}; + data = reshape(getsubfield(interp, tmp), interp.dim); + tmp(find(tmp=='.')) = '_'; + volumewrite_spm([cfg.intermediatename,'_' tmp '.img'], data, interp.transform, cfg.spmversion); +end + +% read the template anatomical volume +switch template_ftype + case 'minc' + VG = spm_vol_minc(cfg.template); + case {'analyze_img', 'analyze_hdr', 'nifti'}, + VG = spm_vol(cfg.template); + otherwise + error('Unknown template'); +end + +fprintf('performing the normalisation\n'); +% do spatial normalisation according to these steps +% step 1: read header information for template and source image +% step 2: compute transformation parameters +% step 3: write the results to a file with prefix 'w' + +if ~isfield(cfg, 'spmparams') && strcmp(cfg.nonlinear, 'yes'), + fprintf('warping the invdividual anatomy to the template anatomy\n'); + % compute the parameters by warping the individual anatomy + VF = spm_vol([cfg.intermediatename,'_anatomy.img']); + params = spm_normalise(VG,VF); +elseif ~isfield(cfg, 'spmparams') && strcmp(cfg.nonlinear, 'no'), + fprintf('warping the invdividual anatomy to the template anatomy, using only linear transformations\n'); + % compute the parameters by warping the individual anatomy + VF = spm_vol([cfg.intermediatename,'_anatomy.img']); + flags.nits = 0; %put number of non-linear iterations to zero + params = spm_normalise(VG,VF,[],[],[],flags); +else + fprintf('using the parameters specified in the configuration\n'); + % use the externally specified parameters + params = cfg.spmparams; +end +flags.vox = [cfg.downsample,cfg.downsample,cfg.downsample]; +files = {}; + +% determine the affine source->template coordinate transformation +final = VG.mat * inv(params.Affine) * inv(VF.mat) * initial; + +% apply the normalisation parameters to each of the volumes +for parlop=1:length(cfg.parameter) + fprintf('creating normalised analyze-file for %s\n', cfg.parameter{parlop}); + tmp = cfg.parameter{parlop}; + tmp(find(tmp=='.')) = '_'; + files{parlop} = sprintf('%s_%s.img', cfg.intermediatename, tmp); + [p, f, x] = fileparts(files{parlop}); + wfiles{parlop} = fullfile(p, ['w' f x]); +end +spm_write_sn(char(files),params,flags); % this creates the 'w' prefixed files + +normalise = []; + +% read the normalised results from the 'w' prefixed files +V = spm_vol(char(wfiles)); +for vlop=1:length(V) + normalise = setsubfield(normalise, cfg.parameter{vlop}, spm_read_vols(V(vlop))); +end + +normalise.transform = V(1).mat; +normalise.dim = size(normalise.anatomy); + +if isfield(normalise, 'inside') + % convert back to a logical volume + normalise.inside = abs(normalise.inside-1)<=10*eps; +end + +% flip and permute the dimensions to align the volume with the headcoordinate axes +normalise = align_ijk2xyz(normalise); + +if strcmp(cfg.write,'yes') + % create an spm-compatible file for each of the normalised volumes + for parlop=1:length(cfg.parameter) % include the anatomy + tmp = cfg.parameter{parlop}; + data = reshape(getsubfield(normalise, tmp), normalise.dim); + tmp(find(tmp=='.')) = '_'; + volumewrite_spm([cfg.name,'_' tmp '.img'], data, normalise.transform, cfg.spmversion); + end +end + +if strcmp(cfg.keepintermediate,'no') + % remove the intermediate files + for flop=1:length(files) + [p, f, x] = fileparts(files{flop}); + delete(fullfile(p, [f, '.*'])); + [p, f, x] = fileparts(wfiles{flop}); + delete(fullfile(p, [f, '.*'])); + end +end + +% accessing this field here is needed for the configuration tracking +% by accessing it once, it will not be removed from the output cfg +cfg.outputfile; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% remember the normalisation parameters in the configuration +cfg.spmparams = params; +cfg.initial = initial; +cfg.final = final; + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_volumenormalise.m 1263 2010-06-23 15:40:37Z timeng $'; +% remember the configuration details of the input data +try, cfg.previous = interp.cfg; end +% remember the exact configuration details in the output +normalise.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', normalise); % use the variable name "data" in the output file +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% HELPER FUNCTION that asks a few questions to determine the coordinate system +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [coordinates] = determine_coordinates(str); +fprintf('Please determine the coordinate system of the %s anatomical volume.\n', str); +% determine in which direction the nose is pointing +nosedir = []; +while isempty(nosedir) + response = input('Is the nose pointing in the positive X- or Y-direction? [x/y] ','s'); + if strcmp(response, 'x'), + nosedir = 'positivex'; + elseif strcmp(response, 'y'), + nosedir = 'positivey'; + end +end +% determine where the origin is +origin = []; +while isempty(origin) + response = input('Is the origin on the Anterior commissure or between the Ears? [a/e] ','s'); + if strcmp(response, 'e'), + origin = 'interauricular'; + elseif strcmp(response, 'a'), + origin = 'ant_comm'; + end +end +% determine the coordinate system of the MRI volume +if strcmp(origin, 'interauricular') && strcmp(nosedir, 'positivex') + coordinates = 'ctf'; +elseif strcmp(origin, 'ant_comm') && strcmp(nosedir, 'positivey') + coordinates = 'spm'; +end diff --git a/external/fieldtrip/ft_volumerealign.m b/external/fieldtrip/ft_volumerealign.m index b84b9b2..bd6f62f 100644 --- a/external/fieldtrip/ft_volumerealign.m +++ b/external/fieldtrip/ft_volumerealign.m @@ -1,11 +1,293 @@ -function varargout = funname(varargin); +function [mri] = ft_volumerealign(cfg, mri); -% this is a SPM wrapper around a FieldTrip function +% FT_VOLUMEREALIGN spatially aligns an anatomical MRI with head coordinates based on +% external fiducials. This function does not change the volume +% itself, but adjusts the homogenous transformation matrix that +% describes the coordinate system. +% +% This function only changes the coordinate system of an anatomical +% MRI, it does not change the MRI as such. For spatial normalisation +% (warping) of an MRI to a template brain you should use the +% FT_VOLUMENORMALISE function. +% +% Use as +% [mri] = ft_volumerealign(cfg, mri) +% where mri is an anatomical volume (i.e. MRI) or a functional +% volume (i.e. source recunstruction that has been interpolated on +% an MRI). +% +% The configuration can contain the following options +% cfg.clim = [min max], scaling of the anatomy color (default +% is to adjust to the minimum and maximum) +% cfg.method = different methods for aligning the electrodes +% 'fiducial' realign the volume to the fiducials +% 'interactive' manually using graphical user interface +% +% For realigning to the fiducials, you should specify the position of the +% fiducials in voxel indices. +% cfg.fiducial.nas = [i j k], position of nasion +% cfg.fiducial.lpa = [i j k], position of LPA +% cfg.fiducial.rpa = [i j k], position of RPA +% +% By specifying the fiducial coordinates either in the cfg or interactively, the +% anatomical MRI volume is realigned according to the folowing convention: +% - the origin is exactly between LPA and RPA +% - the X-axis goes towards NAS +% - the Y-axis goes approximately towards LPA, orthogonal to X and in the plane spanned by the fiducials +% - the Z-axis goes approximately towards the vertex, orthogonal to X and Y +% +% +% See also READ_MRI, FT_ELECTRODEREALIGN +% +% Undocumented local options: +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk -% this part is variable -prefix = 'ft_'; +% Copyright (C) 2006-2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_volumerealign.m 1258 2010-06-22 08:33:48Z timeng $ -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +fieldtripdefs + +cfg = checkconfig(cfg, 'renamedval', {'method', 'realignfiducial', 'fiducial'}); +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +% set the defaults +if ~isfield(cfg, 'fiducial'), cfg.fiducial = []; end +if ~isfield(cfg, 'parameter'), cfg.parameter = 'anatomy'; end +if ~isfield(cfg, 'clim'), cfg.clim = []; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'),cfg.outputfile = []; end + +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + mri = loadvar(cfg.inputfile, 'data'); + end +end + +% check if the input data is valid for this function +mri = checkdata(mri, 'datatype', 'volume', 'feedback', 'yes'); + +if ~isfield(cfg, 'method') + if ~isempty(cfg.fiducial) + cfg.method = 'fiducial'; + else + cfg.method = 'interactive'; + end +end + +% select the parameter that should be displayed +cfg.parameter = parameterselection(cfg.parameter, mri); +if iscell(cfg.parameter) + cfg.parameter = cfg.parameter{1}; +end + +switch cfg.method + case 'fiducial' + % do nothing + + case 'interactive' + showcrosshair = true; + dat = getsubfield(mri, cfg.parameter); + nas = []; + lpa = []; + rpa = []; + x = 1:mri.dim(1); + y = 1:mri.dim(2); + z = 1:mri.dim(3); + xc = round(mri.dim(1)/2); + yc = round(mri.dim(2)/2); + zc = round(mri.dim(3)/2); + + while true % break when 'q' is pressed + fprintf('============================================================\n'); + fprintf('click with mouse button to reslice the display to a new position\n'); + fprintf('press n/l/r on keyboard to record the current position as fiducial location\n'); + fprintf('press i,j,k or I,J,K on the keyboard to increment or decrement the slice number by one\n'); + fprintf('press c or C on the keyboard to show or hide the crosshair\n'); + fprintf('press q on keyboard to quit interactive mode\n'); + xc = round(xc); xc = max(1,xc); xc = min(mri.dim(1),xc); + yc = round(yc); yc = max(1,yc); yc = min(mri.dim(2),yc); + zc = round(zc); zc = max(1,zc); zc = min(mri.dim(3),zc); + volplot(x, y, z, dat, [xc yc zc], cfg.clim, showcrosshair); + drawnow; + try, [d1, d2, key] = ginput(1); catch, key='q'; end + if key=='q' + break; + elseif key=='l' + lpa = [xc yc zc]; + elseif key=='r' + rpa = [xc yc zc]; + elseif key=='n' + nas = [xc yc zc]; + elseif key=='c' + showcrosshair = true; + elseif key=='C' + showcrosshair = false; + elseif key=='i' + xc = xc+1; + elseif key=='I' + xc = xc-1; + elseif key=='j' + yc = yc+1; + elseif key=='J' + yc = yc-1; + elseif key=='k' + zc = zc+1; + elseif key=='K' + zc = zc-1; + else + % update the view to a new position + l1 = get(get(gca, 'xlabel'), 'string'); + l2 = get(get(gca, 'ylabel'), 'string'); + switch l1, + case 'i' + xc = d1; + case 'j' + yc = d1; + case 'k' + zc = d1; + end + switch l2, + case 'i' + xc = d2; + case 'j' + yc = d2; + case 'k' + zc = d2; + end + end + + fprintf('cur_voxel = [%f %f %f], cur_head = [%f %f %f]\n', [xc yc zc], warp_apply(mri.transform, [xc yc zc])); + if ~isempty(nas), + fprintf('nas_voxel = [%f %f %f], nas_head = [%f %f %f]\n', nas, warp_apply(mri.transform, nas)); + else + fprintf('nas = undefined\n'); + end + if ~isempty(lpa), + fprintf('lpa_voxel = [%f %f %f], lpa_head = [%f %f %f]\n', lpa, warp_apply(mri.transform, lpa)); + else + fprintf('lpa = undefined\n'); + end + if ~isempty(rpa), + fprintf('rpa_voxel = [%f %f %f], rpa_head = [%f %f %f]\n', rpa, warp_apply(mri.transform, rpa)); + else + fprintf('rpa = undefined\n'); + end + end % while true + + cfg.fiducial.nas = nas; + cfg.fiducial.lpa = lpa; + cfg.fiducial.rpa = rpa; + + otherwise + error('unsupported method'); +end + + +% the fiducial locations are now specified in voxels, convert them to head +% coordinates according to the existing transform matrix +nas_head = warp_apply(mri.transform, cfg.fiducial.nas); +lpa_head = warp_apply(mri.transform, cfg.fiducial.lpa); +rpa_head = warp_apply(mri.transform, cfg.fiducial.rpa); + +% compute the homogenous transformation matrix describing the new coordinate system +realign = headcoordinates(nas_head, lpa_head, rpa_head); +% combine the additional transformation with the original one +mri.transform = realign * mri.transform; + +% accessing this field here is needed for the configuration tracking +% by accessing it once, it will not be removed from the output cfg +cfg.outputfile; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_volumerealign.m 1258 2010-06-22 08:33:48Z timeng $'; + +% remember the configuration +mri.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', mri); % use the variable name "data" in the output file +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% helper function to show three orthogonal slices +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function volplot(x, y, z, dat, c, cscale, showcrosshair) +xi = c(1); +yi = c(2); +zi = c(3); + +% manual color scaling of anatomy data is usefull in case of some pixel noise +if nargin<6 || isempty(cscale) + cmin = min(dat(:)); + cmax = max(dat(:)); +else + cmin = cscale(1); + cmax = cscale(2); +end + +h1 = subplot(2,2,1); +h2 = subplot(2,2,2); +h3 = subplot(2,2,3); + +subplot(h1); +imagesc(x, z, squeeze(dat(:,yi,:))'); set(gca, 'ydir', 'normal') +axis equal; axis tight; +xlabel('i'); ylabel('k'); +caxis([cmin cmax]); +if showcrosshair + crosshair([x(xi) z(zi)], 'color', 'yellow'); +end + +subplot(h2); +imagesc(y, z, squeeze(dat(xi,:,:))'); set(gca, 'ydir', 'normal') +axis equal; axis tight; +xlabel('j'); ylabel('k'); +caxis([cmin cmax]); +if showcrosshair + crosshair([y(yi) z(zi)], 'color', 'yellow'); +end + +subplot(h3); +imagesc(x, y, squeeze(dat(:,:,zi))'); set(gca, 'ydir', 'normal') +axis equal; axis tight; +xlabel('i'); ylabel('j'); +caxis([cmin cmax]); +if showcrosshair + crosshair([x(xi) y(yi)], 'color', 'yellow'); +end + +colormap gray diff --git a/external/fieldtrip/ft_volumereslice.m b/external/fieldtrip/ft_volumereslice.m new file mode 100644 index 0000000..c759ed8 --- /dev/null +++ b/external/fieldtrip/ft_volumereslice.m @@ -0,0 +1,112 @@ +function mri = ft_volumereslice(cfg, mri) + +% FT_VOLUMERESLICE reslices a volume along the principal axes of the +% coordinate system according to a specified resolution. +% +% Use as +% mri = ft_volumereslice(cfg, mri) +% where the mri contains an anatomical or functional volume and cfg is a +% configuration structure containing +% cfg.xrange = [min max], in physical units +% cfg.yrange = [min max], in physical units +% cfg.zrange = [min max], in physical units +% cfg.resolution = number, in physical units +% +% See also FT_VOLUMEDOWNSAMPLE, FT_SOURCEINTREPOLATE +% +% Undocumented local options: +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk + +% Copyright (C) 2010, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id$ + +% check if the input cfg is valid for this function +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +% set the defaults +if ~isfield(cfg, 'resolution'); cfg.resolution = 1; end % in physical units +if ~isfield(cfg, 'downsample'); cfg.downsample = 1; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +% load optional given inputfile as data +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + mri = loadvar(cfg.inputfile, 'data'); + end +end + +% check if the input data is valid for this function and ensure that the structures correctly describes a volume +mri = checkdata(mri, 'datatype', 'volume', 'inside', 'logical', 'feedback', 'yes', 'hasunits', 'yes'); + +cfg = checkconfig(cfg, 'required', {'xrange', 'yrange', 'zrange'}); + +if ~isequal(cfg.downsample, 1) + % downsample the anatomical volume + tmpcfg = []; + tmpcfg.downsample = cfg.downsample; + mri = ft_volumedownsample(tmpcfg, mri); +end + +% compute the desired grid positions +xgrid = cfg.xrange(1):cfg.resolution:cfg.xrange(2); +ygrid = cfg.yrange(1):cfg.resolution:cfg.yrange(2); +zgrid = cfg.zrange(1):cfg.resolution:cfg.zrange(2); + +pseudomri = []; +pseudomri.dim = [length(xgrid) length(ygrid) length(zgrid)]; +pseudomri.transform = translate([cfg.xrange(1) cfg.yrange(1) cfg.zrange(1)]) * scale([cfg.resolution cfg.resolution cfg.resolution]); +pseudomri.anatomy = zeros(pseudomri.dim, 'int8'); + +clear xgrid ygrid zgrid + +fprintf('reslicing from [%d %d %d] to [%d %d %d]\n', mri.dim(1), mri.dim(2), mri.dim(3), pseudomri.dim(1), pseudomri.dim(2), pseudomri.dim(3)); + +tmpcfg = []; +mri = ft_sourceinterpolate(tmpcfg, mri, pseudomri); + +% accessing this field here is needed for the configuration tracking +% by accessing it once, it will not be removed from the output cfg +cfg.outputfile; + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: ft_sourceinterpolate.m 715 2010-03-09 10:57:27Z roboos $'; +% remember the configuration details of the input data +try cfg.previous = mri.cfg; end +% remember the exact configuration details in the output +mri.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', mri); % use the variable name "data" in the output file +end diff --git a/external/fieldtrip/ft_volumesegment.m b/external/fieldtrip/ft_volumesegment.m index b84b9b2..1a3446a 100644 --- a/external/fieldtrip/ft_volumesegment.m +++ b/external/fieldtrip/ft_volumesegment.m @@ -1,11 +1,368 @@ -function varargout = funname(varargin); +function [segment] = ft_volumesegment(cfg, mri) -% this is a SPM wrapper around a FieldTrip function +% FT_VOLUMESEGMENT segments an anatomical MRI into gray matter, white matter, +% and cerebro-spinal fluid compartments. +% +% This function uses the SPM2 toolbox, see http://www.fil.ion.ucl.ac.uk/spm/ +% +% Use as +% [segment] = ft_volumesegment(cfg, mri) +% +% The input arguments are a configuration structure (see below) and an +% anatomical MRI structure. Instead of an MRI structure, you can also +% specify a string with a filename of an MRI file. +% +% The configuration options are +% cfg.spmversion = 'spm8' (default) or 'spm2' +% cfg.template = filename of the template anatomical MRI (default is the 'T1.mnc' (spm2) or 'T1.nii' (spm8) +% in the (spm-directory)/templates/) +% cfg.name = string for output filename +% cfg.write = 'no' or 'yes' (default = 'no'), +% writes the segmented volumes to SPM compatible analyze-files, +% with the suffix (spm2) +% _seg1, for the gray matter segmentation +% _seg2, for the white matter segmentation +% _seg3, for the csf segmentation +% or with the prefix (spm8) +% c1, for the gray matter segmentation +% c2, for the white matter segmentation +% c3, for the csf segmentation +% +% cfg.smooth = 'no' or the FWHM of the gaussian kernel in voxels (default = 'no') +% cfg.coordinates = 'spm, 'ctf' or empty for interactive (default = []) +% +% As the first step the coordinate frame of the input MRI has to +% be approximately aligned to the template. For this, a homogeneous +% transformation matrix is used, which makes the assumption that the +% template mri is defined in SPM/MNI-coordinates: +% x-axis pointing to the right ear +% y-axis along the acpc-line +% z-axis pointing to the top of the head +% origin in the anterior commissure. +% Note that the segmentation only works if the template MRI is in SPM +% coordinates. +% +% If the input mri is a string pointing to a CTF *.mri file, the +% x-axis is assumed to point to the nose, and the origin is assumed +% to be on the interauricular line. +% +% If the input mri is a string pointing to another fileformat, or a +% structure containing an anatomical MRI in Matlab memory, the user will +% be asked about the axis-definition and the origin of the coordinate system. +% +% As a second step, the segmentation is performed, using the +% default parameters from SPM. The output volume is in the original +% coordinate-frame. +% +% As a third and optional step, you can perform a smoothing of the segmented +% volumes. + +% undocumented options +% cfg.keepintermediate = 'yes' or 'no' +% cfg.segment = 'yes' or 'no' +% cfg.inputfile = one can specifiy preanalysed saved data as input +% cfg.outputfile = one can specify output as file to save to disk + +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_volumesegment.m 1258 2010-06-22 08:33:48Z timeng $ + +fieldtripdefs + +cfg = checkconfig(cfg, 'trackconfig', 'on'); + +%% checkdata see below!!! %% + + +% set the defaults +if ~isfield(cfg,'segment'), cfg.segment = 'yes'; end; +if ~isfield(cfg,'smooth'), cfg.smooth = 'no'; end; +if ~isfield(cfg,'spmversion'), cfg.spmversion = 'spm8'; end; +if ~isfield(cfg,'write'), cfg.write = 'no'; end; +if ~isfield(cfg,'keepintermediate'),cfg.keepintermediate = 'no'; end; +if ~isfield(cfg,'coordinates'), cfg.coordinates = []; end; +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end +if ~isfield(cfg, 'outputfile'), cfg.outputfile = []; end + +if ~isfield(cfg,'name') + if ~strcmp(cfg.write,'yes') + tmp = tempname; + %[path,file] = fileparts(tmp); + %cfg.name = file; + cfg.name = tmp; + else + error('you must specify the output filename in cfg.name'); + end +end + +% check if the required spm is in your path: +if strcmpi(cfg.spmversion, 'spm2'), + hastoolbox('SPM2',1); +elseif strcmpi(cfg.spmversion, 'spm8'), + hastoolbox('SPM8',1); +end + +if ~isfield(cfg, 'template'), + spmpath = spm('dir'); + if strcmpi(cfg.spmversion, 'spm8'), cfg.template = [spmpath,filesep,'templates',filesep,'T1.nii']; end + if strcmpi(cfg.spmversion, 'spm2'), cfg.template = [spmpath,filesep,'templates',filesep,'T1.mnc']; end +end + +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + mri = loadvar(cfg.inputfile, 'data'); + end +end + +if hasdata + if ischar(mri), + % read the anatomical MRI data from file + filename = mri; + fprintf('reading MRI from file\n'); + mri = ft_read_mri(filename); + if ft_filetype(filename, 'ctf_mri') && isempty(cfg.coordinates) + % based on the filetype assume that the coordinates correspond with CTF convention + cfg.coordinates = 'ctf'; + end + end +end + +% check if the input data is valid for this function +mri = checkdata(mri, 'datatype', 'volume', 'feedback', 'yes'); + +% remember the original transformation matrix +original.transform = mri.transform; +original.nosedir = []; +original.origin = []; + +if isempty(cfg.coordinates) + % determine in which direction the nose is pointing + while isempty(original.nosedir) + response = input('Is the nose pointing in the positive X- or Y-direction? [x/y] ','s'); + if strcmp(response, 'x'), + original.nosedir = 'positivex'; + elseif strcmp(response, 'y'), + original.nosedir = 'positivey'; + end + end + + % determine where the origin is + while isempty(original.origin) + response = input('Is the origin on the Anterior commissure or between the Ears? [a/e] ','s'); + if strcmp(response, 'e'), + original.origin = 'interauricular'; + elseif strcmp(response, 'a'), + original.origin = 'ant_comm'; + end + end + + % determine the coordinatesystem of the input MRI volume + if strcmp(original.origin, 'interauricular') && strcmp(original.nosedir, 'positivex') + cfg.coordinates = 'ctf'; + elseif strcmp(original.origin, 'ant_comm') && strcmp(original.nosedir, 'positivey') + cfg.coordinates = 'spm'; + end +end + +% ensure that the input MRI volume is approximately aligned with the SPM template +if strcmp(cfg.coordinates, 'ctf') + fprintf('assuming CTF coordinates for input, i.e. positive X-axis towards nasion and Y-axis through ears\n'); + % flip, rotate and translate the CTF mri so that it approximately corresponds with SPM coordinates + % this only involves a manipulation of the coordinate tarnsformation matrix + mri = align_ctf2spm(mri); + % also flip and permute the 3D volume itself, so that the voxel and headcoordinates approximately correspond + % this seems to improve the convergence of the segmentation algorithm + mri = align_ijk2xyz(mri); +elseif strcmp(cfg.coordinates, 'spm') + fprintf('assuming that the input MRI is already approximately aligned with SPM coordinates\n'); + % nothing needs to be done +else + error('cannot determine the (approximate) alignmenmt of the input MRI with the SPM template'); +end + +if strcmp(cfg.segment, 'yes') + % convert and write the volume to an analyze format, so that it can be handled by spm + Va = volumewrite_spm([cfg.name,'.img'], mri.anatomy, mri.transform, cfg.spmversion); + + % spm is quite noisy, prevent the warnings from displaying on screen + % warning off; + + if strcmpi(cfg.spmversion, 'spm2'), + % set the spm segmentation defaults (from /opt/spm2/spm_defaults.m script) + defaults.segment.estimate.priors = str2mat(... + fullfile(spm('Dir'),'apriori','gray.mnc'),... + fullfile(spm('Dir'),'apriori','white.mnc'),... + fullfile(spm('Dir'),'apriori','csf.mnc')); + defaults.segment.estimate.reg = 0.01; + defaults.segment.estimate.cutoff = 30; + defaults.segment.estimate.samp = 3; + defaults.segment.estimate.bb = [[-88 88]' [-122 86]' [-60 95]']; + defaults.segment.estimate.affreg.smosrc = 8; + defaults.segment.estimate.affreg.regtype = 'mni'; + %defaults.segment.estimate.affreg.weight = fullfile(spm('Dir'),'apriori','brainmask.mnc'); + defaults.segment.estimate.affreg.weight = ''; + defaults.segment.write.cleanup = 1; + defaults.segment.write.wrt_cor = 1; + + flags = defaults.segment; + + % perform the segmentation + fprintf('performing the segmentation on the specified volume\n'); + spm_segment(Va,cfg.template,flags); + Vtmp = spm_vol({[cfg.name,'_seg1.img'];... + [cfg.name,'_seg2.img'];... + [cfg.name,'_seg3.img']}); + + % read the resulting volumes + for j = 1:3 + vol = spm_read_vols(Vtmp{j}); + Vtmp{j}.dat = vol; + V(j) = struct(Vtmp{j}); + end + + % keep or remove the files according to the configuration + if strcmp(cfg.keepintermediate,'no'), + delete([cfg.name,'.img']); + delete([cfg.name,'.hdr']); + delete([cfg.name,'.mat']); + end + if strcmp(cfg.write,'no'), + delete([cfg.name,'_seg1.hdr']); + delete([cfg.name,'_seg2.hdr']); + delete([cfg.name,'_seg3.hdr']); + delete([cfg.name,'_seg1.img']); + delete([cfg.name,'_seg2.img']); + delete([cfg.name,'_seg3.img']); + delete([cfg.name,'_seg1.mat']); + delete([cfg.name,'_seg2.mat']); + delete([cfg.name,'_seg3.mat']); + elseif strcmp(cfg.write,'yes'), + for j = 1:3 + % put the original transformation-matrix in the headers + V(j).mat = original.transform; + % write the updated header information back to file ??????? + V(j) = spm_create_vol(V(j)); + end + end + + elseif strcmpi(cfg.spmversion, 'spm8'), + + fprintf('performing the segmentation on the specified volume\n'); + p = spm_preproc(Va); + [po,pin] = spm_prep2sn(p); + + % I took these settings from a batch + opts = []; + opts.GM = [0 0 1]; + opts.WM = [0 0 1]; + opts.CSF = [0 0 1]; + opts.biascor = 1; + opts.cleanup = 0; + spm_preproc_write(po, opts); + + [pathstr,name,ext] = fileparts(cfg.name); + Vtmp = spm_vol({fullfile(pathstr,['c1',name,'.img']);... + fullfile(pathstr,['c2',name,'.img']);... + fullfile(pathstr,['c3',name,'.img'])}); + + % read the resulting volumes + for j = 1:3 + vol = spm_read_vols(Vtmp{j}); + Vtmp{j}.dat = vol; + V(j) = struct(Vtmp{j}); + end + + % keep or remove the files according to the configuration + if strcmp(cfg.keepintermediate,'no'), + delete([cfg.name,'.img']); + delete([cfg.name,'.hdr']); + delete([cfg.name,'.mat']); + end + if strcmp(cfg.write,'no'), + delete(fullfile(pathstr,['c1',name,'.hdr'])); + delete(fullfile(pathstr,['c1',name,'.img'])); + delete(fullfile(pathstr,['c2',name,'.hdr'])); + delete(fullfile(pathstr,['c2',name,'.img'])); + delete(fullfile(pathstr,['c3',name,'.hdr'])); + delete(fullfile(pathstr,['c3',name,'.img'])); + delete(fullfile(pathstr,['m',name,'.hdr'])); + delete(fullfile(pathstr,['m',name,'.img'])); + elseif strcmp(cfg.write,'yes'), + for j = 1:3 + % put the original transformation-matrix in the headers + V(j).mat = original.transform; + % write the updated header information back to file ??????? + V(j) = spm_create_vol(V(j)); + end + end + + end + +else + % the volume is already segmented, put it in an SPM structure + V = mri; + V.dat = V.anatomy; + V.mat = V.transform; + V = rmfield(V,'anatomy'); +end + +if ~strcmp(cfg.smooth, 'no'), + fprintf('smoothing with a %d-pixel FWHM kernel\n',cfg.smooth); + spm_smooth(V(1).dat, V(1).dat, cfg.smooth); % smooth the gray matter + if length(V)>1, spm_smooth(V(2).dat, V(2).dat, cfg.smooth); end % smooth the white matter + if length(V)>2, spm_smooth(V(3).dat, V(3).dat, cfg.smooth); end % smooth the csf +end + +% collect the results +segment.dim = size(V(1).dat); +segment.transform = original.transform; % use the original transformation-matrix +segment.gray = V(1).dat; +if length(V)>1, segment.white = V(2).dat; end +if length(V)>2, segment.csf = V(3).dat; end + +% accessing this field here is needed for the configuration tracking +% by accessing it once, it will not be removed from the output cfg +cfg.outputfile; + +% get the output cfg +cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); + +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i).name; +end +cfg.version.id = '$Id: ft_volumesegment.m 1258 2010-06-22 08:33:48Z timeng $'; +% remember the configuration details of the input data +try, cfg.previous = mri.cfg; end +% remember the exact configuration details in the output +segment.cfg = cfg; + +% the output data should be saved to a MATLAB file +if ~isempty(cfg.outputfile) + savevar(cfg.outputfile, 'data', segment); % use the variable name "data" in the output file +end -% this part is variable -prefix = 'ft_'; -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fieldtrip/ft_volumewrite.m b/external/fieldtrip/ft_volumewrite.m index b84b9b2..bf5c14f 100644 --- a/external/fieldtrip/ft_volumewrite.m +++ b/external/fieldtrip/ft_volumewrite.m @@ -1,11 +1,412 @@ -function varargout = funname(varargin); +function ft_volumewrite(cfg, volume) -% this is a SPM wrapper around a FieldTrip function +% FT_VOLUMEWRITE exports anatomical or functional volume data to a Analyze +% or BrainVoyager file. The data in the resulting file(s) can be +% further analyzed and/or visualized in MRIcro, SPM, BrainVoyager, +% AFNI or similar packages. +% +% Use as +% ft_volumewrite(cfg, volume) +% +% The volume structure should contain a source reconstruction that originates +% from SOURCANALYSIS, a statistical parameter from FT_SOURCESTATISTICS or an +% interpolated and re-aligned anatomical MRI source reconstruction +% from FT_SOURCEINTERPOLATE. +% +% The configuration structure should contain the following elements +% cfg.parameter = string, describing the functional data to be processed, e.g. 'pow', 'coh' or 'nai' +% cfg.filename = filename without the extension +% cfg.filetype = 'analyze', 'spm', 'vmp' or 'vmr' +% cfg.vmpversion = 1 or 2 (default) version of the vmp-format to use +% cfg.coordinates = 'spm, 'ctf' or empty for interactive (default = []) +% +% The default fileformat is 'spm', which means that a *.hdr and *.img file +% will be written using the SPM2 toolbox. The SPM format supports a +% homogenous transformation matrix, the other file formats do not support a +% homogenous coordinate transformation matrix and hence will be written in +% their native coordinate system. +% +% You can specify the datatype for the spm and analyze formats using +% cfg.datatype = 'bit1', 'uint8', 'int16', 'int32', 'float' or 'double' +% +% By default, integer datatypes will be scaled to the maximum value of the +% physical or statistical parameter, floating point datatypes will not be +% scaled. This can be modified with +% cfg.scaling = 'yes' or 'no' +% +% Optional configuration items are +% cfg.downsample = integer number (default = 1, i.e. no downsampling) +% cfg.fiducial.nas = [x y z] position of nasion +% cfg.fiducial.lpa = [x y z] position of LPA +% cfg.fiducial.rpa = [x y z] position of RPA +% cfg.markfiducial = 'yes' or 'no', mark the fiducials +% cfg.markorigin = 'yes' or 'no', mark the origin +% cfg.markcorner = 'yes' or 'no', mark the first corner of the volume +% +% See also FT_SOURCEANALYSIS, FT_SOURCESTATISTICS, FT_SOURCEINTERPOLATE -% this part is variable -prefix = 'ft_'; +% Undocumented local options: +% cfg.parameter +% cfg.inputfile = one can specifiy preanalysed saved data as input -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); +% Copyright (C) 2003-2006, Robert Oostenveld, Markus Siegel +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_volumewrite.m 1303 2010-06-29 15:42:37Z timeng $ + +fieldtripdefs + +%% checkdata see below!!! %% + +% check some of the cfg fields +if ~isfield(cfg, 'filename'), error('No output filename specified'); end +if ~isfield(cfg, 'parameter'), error('No parameter specified'); end +if isempty(cfg.filename), error('Empty output filename'); end + +% set the defaults +if ~isfield(cfg, 'filetype'), cfg.filetype = 'spm'; end +if ~isfield(cfg, 'datatype') cfg.datatype = 'int16'; end +if ~isfield(cfg, 'downsample'), cfg.downsample = 1; end +if ~isfield(cfg, 'markorigin') cfg.markorigin = 'no'; end +if ~isfield(cfg, 'markfiducial') cfg.markfiducial = 'no'; end +if ~isfield(cfg, 'markcorner') cfg.markcorner = 'no'; end +if ~isfield(cfg, 'inputfile'), cfg.inputfile = []; end + +if ~isfield(cfg, 'scaling'), + if any(strmatch(cfg.datatype, {'int8', 'int16', 'int32'})) + cfg.scaling = 'yes'; + else + cfg.scaling = 'no'; + end +end + +if ~isfield(cfg, 'coordinates') + fprintf('assuming CTF coordinates\n'); + cfg.coordinates = 'ctf'; +end + +if ~isfield(cfg, 'vmpversion') & strcmp(cfg.filetype, 'vmp'); + fprintf('using BrainVoyager version 2 VMP format\n'); + cfg.vmpversion = 2; +end + +% load optional given inputfile as data +hasdata = (nargin>1); +if ~isempty(cfg.inputfile) + % the input data should be read from file + if hasdata + error('cfg.inputfile should not be used in conjunction with giving input data to this function'); + else + volume = loadvar(cfg.inputfile, 'data'); + end +end + +% check if the input data is valid for this function +volume = checkdata(volume, 'datatype', 'volume', 'feedback', 'yes'); + +% select the parameter that should be written +cfg.parameter = parameterselection(cfg.parameter, volume); +% only a single parameter should be selected +try, cfg.parameter = cfg.parameter{1}; end + +% downsample the volume +tmpcfg = []; +tmpcfg.downsample = cfg.downsample; +tmpcfg.parameter = cfg.parameter; +volume = ft_volumedownsample(tmpcfg, volume); + +% copy the data and convert into double values so that it can be scaled later +transform = volume.transform; +data = double(getsubfield(volume, cfg.parameter)); +maxval = max(data(:)); +% ensure that the original volume is not used any more +clear volume + +if strcmp(cfg.markfiducial, 'yes') + % FIXME determine the voxel index of the fiducials + nas = cfg.fiducial.nas; + lpa = cfg.fiducial.lpa; + rpa = cfg.fiducial.rpa; + if any(nasmaxxyz) + warning('nasion does not ly within volume, using nearest voxel'); + end + if any(lpamaxxyz) + warning('LPA does not ly within volume, using nearest voxel'); + end + if any(rpamaxxyz) + warning('RPA does not ly within volume, using nearest voxel'); + end + idx_nas = [nearest(x, nas(1)) nearest(y, nas(2)) nearest(z, nas(3))]; + idx_lpa = [nearest(x, lpa(1)) nearest(y, lpa(2)) nearest(z, lpa(3))]; + idx_rpa = [nearest(x, rpa(1)) nearest(y, rpa(2)) nearest(z, rpa(3))]; + fprintf('NAS corresponds to voxel [%d, %d, %d]\n', idx_nas); + fprintf('LPA corresponds to voxel [%d, %d, %d]\n', idx_lpa); + fprintf('RPA corresponds to voxel [%d, %d, %d]\n', idx_rpa); + % set the voxel of the fiducials to the maximum value + data(idx_nas(1), idx_nas(2), idx_nas(3)) = maxval; + data(idx_lpa(1), idx_lpa(2), idx_lpa(3)) = maxval; + data(idx_rpa(1), idx_rpa(2), idx_rpa(3)) = maxval; +end + +if strcmp(cfg.markorigin, 'yes') + % FIXME determine the voxel index of the coordinate system origin + ori = [0 0 0]; + if any(orimaxxyz) + warning('origin does not ly within volume, using nearest voxel'); + end + idx_ori = [nearest(x, ori(1)) nearest(y, ori(2)) nearest(z, ori(3))]; + fprintf('origin corresponds to voxel [%d, %d, %d]\n', idx_ori); + % set the voxel of the origin to the maximum value + data(idx_ori(1), idx_ori(2), idx_ori(3)) = maxval; +end + +if strcmp(cfg.markcorner, 'yes') + % set the voxel of the first corner to the maximum value + data(1:2, 1:1, 1:1) = maxval; % length 2 along x-axis + data(1:1, 1:3, 1:1) = maxval; % length 3 along y-axis + data(1:1, 1:1, 1:4) = maxval; % length 4 along z-axis +end + +% set not-a-number voxels to zero +data(isnan(data)) = 0; + +if strcmp(cfg.scaling, 'yes') + % scale the data so that it fits in the desired numerical data format + switch lower(cfg.datatype) + case 'bit1' + data = (data~=0); + case 'uint8' + data = uint8((2^8-1) * data./maxval); + case 'int16' + data = int16((2^15-1) * data./maxval); + case 'int32' + data = int32((2^31-1) * data./maxval); + case 'float' + data = float(data ./ maxval); + case 'double' + data = double(data ./ maxval); + otherwise + error('unknown datatype'); + end +end + +% The coordinate system employed by the ANALYZE programs is left-handed, +% with the coordinate origin in the lower left corner. Thus, with the +% subject lying supine, the coordinate origin is on the right side of +% the body (x), at the back (y), and at the feet (z). + +% Analyze x = right-left +% Analyze y = post-ant +% Analyze z = inf-sup + +% SPM/MNI x = left-right +% SPM/MNI y = post-ant +% SPM/MNI z = inf-sup + +% CTF x = post-ant +% CTF y = right-left +% CTF z = inf-sup + +% The BrainVoyager and Analyze format do not support the specification of +% the coordinate system using a homogenous transformation axis, therefore +% the dimensions of the complete volume has to be reordered by flipping and +% permuting to correspond with their native coordinate system. +switch cfg.filetype + case {'vmp', 'vmr'} + % the reordering for BrainVoyager has been figured out by Markus Siegel + if strcmp(cfg.coordinates, 'ctf') + data = permute(data, [2 3 1]); + elseif strcmp(cfg.coordinates, 'spm') + data = permute(data, [2 3 1]); + data = flipdim(data, 1); + data = flipdim(data, 2); + end + siz = size(data); + case {'analyze'} + % the reordering of the Analyze format is according to documentation from Darren Webber + if strcmp(cfg.coordinates, 'ctf') + data = permute(data, [2 1 3]); + elseif strcmp(cfg.coordinates, 'spm') + data = flipdim(data, 1); + end + siz = size(data); + case 'spm' + % this format supports a homogenous transformation matrix + % nothing needs to be changed + otherwise + fprintf('unknown fileformat\n'); +end + +% write the volume data to file +switch cfg.filetype + case 'vmp' + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % write in BrainVoyager VMP format + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + fid = fopen(sprintf('%s.vmp', cfg.filename),'w'); + if fid < 0, + error('Cannot write to file %s.vmp\n',cfg.filename); + end + + switch cfg.vmpversion + case 1 + % write the header + fwrite(fid, 1, 'short'); % version + fwrite(fid, 1, 'short'); % number of maps + fwrite(fid, 1, 'short'); % map type + fwrite(fid, 0, 'short'); % lag + + fwrite(fid, 0, 'short'); % cluster size + fwrite(fid, 1, 'float'); % thresh min + fwrite(fid, maxval, 'float'); % thresh max + fwrite(fid, 0, 'short'); % df1 + fwrite(fid, 0, 'short'); % df2 + fwrite(fid, 0, 'char'); % name + + fwrite(fid, siz, 'short'); % size + fwrite(fid, 0, 'short'); + fwrite(fid, siz(1)-1, 'short'); + fwrite(fid, 0, 'short'); + fwrite(fid, siz(2)-1, 'short'); + fwrite(fid, 0, 'short'); + fwrite(fid, siz(3)-1, 'short'); + fwrite(fid, 1, 'short'); % resolution + + % write the data + fwrite(fid, data, 'float'); + case 2 + % determine relevant subvolume + % FIXME, this is not functional at the moment, since earlier in this function all nans have been replaced by zeros + minx = min(find(~isnan(max(max(data,[],3),[],2)))); + maxx = max(find(~isnan(max(max(data,[],3),[],2)))); + miny = min(find(~isnan(max(max(data,[],3),[],1)))); + maxy = max(find(~isnan(max(max(data,[],3),[],1)))); + minz = min(find(~isnan(max(max(data,[],1),[],2)))); + maxz = max(find(~isnan(max(max(data,[],1),[],2)))); + + % write the header + fwrite(fid, 2, 'short'); % version + fwrite(fid, 1, 'int'); % number of maps + fwrite(fid, 1, 'int'); % map type + fwrite(fid, 0, 'int'); % lag + + fwrite(fid, 0, 'int'); % cluster size + fwrite(fid, 0, 'char'); % cluster enable + fwrite(fid, 1, 'float'); % thresh + fwrite(fid, maxval, 'float'); % thresh + fwrite(fid, 0, 'int'); % df1 + fwrite(fid, 0, 'int'); % df2 + fwrite(fid, 0, 'int'); % bonf + fwrite(fid, [255,0,0], 'uchar'); % col1 + fwrite(fid, [255,255,0], 'uchar'); % col2 + fwrite(fid, 1, 'char'); % enable SMP + fwrite(fid, 1, 'float'); % transparency + fwrite(fid, 0, 'char'); % name + + fwrite(fid, siz, 'int'); % original size + fwrite(fid, minx-1, 'int'); + fwrite(fid, maxx-1, 'int'); + fwrite(fid, miny-1, 'int'); + fwrite(fid, maxy-1, 'int'); + fwrite(fid, minz-1, 'int'); + fwrite(fid, maxz-1, 'int'); + fwrite(fid, 1, 'int'); % resolution + + % write the data + fwrite(fid, data(minx:maxx,miny:maxy,minz:maxz), 'float'); + end + + case 'vmr' + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % write in BrainVoyager VMR format + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + fid = fopen(sprintf('%s.vmr',cfg.filename),'w'); + if fid < 0, + error('Cannot write to file %s.vmr\n',cfg.filename); + end + + % data should be scaled between 0 and 225 + data = data - min(data(:)); + data = round(225*data./max(data(:))); + + % write the header + fwrite(fid, siz, 'ushort'); + % write the data + fwrite(fid, data, 'uint8'); + fclose(fid); + case 'analyze' + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % write in Analyze format, using some functions from Darren Webbers toolbox + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + avw = avw_hdr_make; + + % specify the image data and dimensions + avw.hdr.dime.dim(2:4) = siz; + avw.img = data; + + % orientation 0 means transverse unflipped (axial, radiological) + % X direction first, progressing from patient right to left, + % Y direction second, progressing from patient posterior to anterior, + % Z direction third, progressing from patient inferior to superior. + avw.hdr.hist.orient = 0; + + % specify voxel size + avw.hdr.dime.pixdim(2:4) = [1 1 1]; + % FIXME, this currently does not work due to all flipping and permuting + % resx = x(2)-x(1); + % resy = y(2)-y(1); + % resz = z(2)-z(1); + % avw.hdr.dime.pixdim(2:4) = [resy resx resz]; + + % specify the data type + switch lower(cfg.datatype) + case 'bit1' + avw.hdr.dime.datatype = 1; + avw.hdr.dime.bitpix = 1; + case 'uint8' + avw.hdr.dime.datatype = 2; + avw.hdr.dime.bitpix = 8; + case 'int16' + avw.hdr.dime.datatype = 4; + avw.hdr.dime.bitpix = 16; + case 'int32' + avw.hdr.dime.datatype = 8; + avw.hdr.dime.bitpix = 32; + case 'float' + avw.hdr.dime.datatype = 16; + avw.hdr.dime.bitpix = 32; + case 'double' + avw.hdr.dime.datatype = 64; + avw.hdr.dime.bitpix = 64; + otherwise + error('unknown datatype'); + end + + % write the header and image data + avw_img_write(avw, cfg.filename, [], 'ieee-le'); + + case 'spm' + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % write in SPM format, using functions from the SPM2 toolbox + % this format supports a homogenous transformation matrix + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + volumewrite_spm(cfg.filename, data, transform); + + otherwise + fprintf('unknown fileformat\n'); +end diff --git a/external/fieldtrip/ft_wizard.m b/external/fieldtrip/ft_wizard.m new file mode 100644 index 0000000..239cb39 --- /dev/null +++ b/external/fieldtrip/ft_wizard.m @@ -0,0 +1,80 @@ +function varargout = ft_wizard(wizard_filename) + +% FT_WIZARD will evaluate a FieldTrip analysis script in steps, allowing you +% to go to the next step if you are content with the data so far, or to the +% previous step if you want to repeat it with different configuration +% settings. +% +% Use as +% ft_wizard scriptname +% or +% ft_wizard('scriptname') +% +% Use the functional form of FT_WIZARD, such as FT_WIZARD('scriptname'), when +% the name of the script is stored in a string, when an output argument is +% requested, or if the name of the script contains spaces. If you do not +% specify an output argument, the results will be stored as variables in +% the main Matlab workspace. +% +% Besides the buttons, you can use the following key combinations +% Ctrl-O load a new script from a file +% Ctrl-S save the script to a new file +% Ctrl-E open the current script in editor +% Ctrl-P go to previous step +% Ctrl-N go to next step +% Ctrl-Q quit, do not save the variables +% Ctrl-X exit, save the variables to the workspace +% +% See also FT_ANALYSISPROTOCOL + +% Copyright (C) 2007-2010, Robert Oostenveld +% +% $Log: wizard.m,v $ +% Revision 1.3 2008/09/22 20:17:44 roboos +% added call to fieldtripdefs to the begin of the function +% +% Revision 1.2 2007/05/14 08:30:56 roboos +% renamed wizard_gui to wizard_base, updated help +% +% Revision 1.1 2007/05/10 09:06:21 roboos +% initial version +% + +fieldtripdefs + +% this function is a wrapper around the actual GUI function +% the main purpose of this function is to provide a workspace where the +% intermediate results can be stored + +% the wizard_ok variable will be set to 0/1 by the wizard_base function +wizard_ok = 0; + +if nargin>0 + wizard_fig = wizard_base(wizard_filename); +else + wizard_fig = wizard_base; +end + +waitfor(wizard_fig); + +if wizard_ok + % get the intermediate variables, do not export the wizard bookkeeping + % variables (which all start with "wizard_") + wizard_var = whos; + wizard_var(strmatch('wizard_', {wizard_var.name})) = []; + + if nargout==0 + % store the results in the BASE workspace + for wizard_i=1:length(wizard_var) + assignin('base', wizard_var(wizard_i).name, eval(wizard_var(wizard_i).name)); + end + else + % store the results in an output structure + varargout{1} = []; + for wizard_i=1:length(wizard_var) + varargout{1}.(wizard_var(wizard_i).name) = eval(wizard_var(wizard_i).name); + end + end % if nargout +end % if ok + +return % main function diff --git a/external/fieldtrip/inverse/COPYING b/external/fieldtrip/inverse/COPYING new file mode 100644 index 0000000..1b28104 --- /dev/null +++ b/external/fieldtrip/inverse/COPYING @@ -0,0 +1,341 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + diff --git a/external/fieldtrip/inverse/README b/external/fieldtrip/inverse/README new file mode 100644 index 0000000..4faeafc --- /dev/null +++ b/external/fieldtrip/inverse/README @@ -0,0 +1,16 @@ +This is the FieldTrip INVERSE module. It contains functions for inverse +modeling and source estimation of EEG and MEG data, based on a choise +of volume conduction models, including spherical and realistic models. + +For more information please visit http://www.ru.nl/neuroimaging/fieldtrip + +The FieldTrip software is free but copyrighted software, distributed +under the terms of the GNU General Public Licence as published by +the Free Software Foundation (either version 2, or at your option +any later version). See the file COPYING for more details. + +Copyright (C) 2008-2009, Donders Institute for Brain, Cognition and Behaviour, The Netherlands (DCCN, DCC, DCN) +Copyright (C) 2003-2008, F.C. Donders Centre for Cognitive Neuroimaging, Nijmegen, The Netherlands (FCDC) +Copyright (C) 2003-2005, Center for Sensory-Motor Interaction, Aalborg University, Denmark (SMI) +Copyright (C) 1999-2003, Department of Medical Physics, Radboud University Nijmegen, The Netherlands (MBFYS) + diff --git a/external/fieldtrip/inverse/beamformer_dics.m b/external/fieldtrip/inverse/beamformer_dics.m new file mode 100644 index 0000000..eddd915 --- /dev/null +++ b/external/fieldtrip/inverse/beamformer_dics.m @@ -0,0 +1,485 @@ +function [dipout] = beamformer_dics(dip, grad, vol, dat, Cf, varargin) + +% BEAMFORMER_DICS scans on pre-defined dipole locations with a single dipole +% and returns the beamformer spatial filter output for a dipole on every +% location. Dipole locations that are outside the head will return a +% NaN value. +% +% Use as +% [dipout] = beamformer_dics(dipin, grad, vol, dat, cov, varargin) +% where +% dipin is the input dipole model +% grad is the gradiometer definition +% vol is the volume conductor definition +% dat is the data matrix with the ERP or ERF +% cov is the data covariance or cross-spectral density matrix +% and +% dipout is the resulting dipole model with all details +% +% The input dipole model consists of +% dipin.pos positions for dipole, e.g. regular grid +% dipin.mom dipole orientation (optional) +% +% Additional options should be specified in key-value pairs and can be +% 'Pr' = power of the external reference channel +% 'Cr' = cross spectral density between all data channels and the external reference channel +% 'refdip' = location of dipole with which coherence is computed +% 'lambda' = regularisation parameter +% 'powmethod' = can be 'trace' or 'lambda1' +% 'feedback' = give progress indication, can be 'text', 'gui' or 'none' +% 'fixedori' = use fixed or free orientation, can be 'yes' or 'no' +% 'projectnoise' = project noise estimate through filter, can be 'yes' or 'no' +% 'realfilter' = construct a real-valued filter, can be 'yes' or 'no' +% 'keepfilter' = remember the beamformer filter, can be 'yes' or 'no' +% 'keepleadfield' = remember the forward computation, can be 'yes' or 'no' +% 'keepcsd' = remember the estimated cross-spectral density, can be 'yes' or 'no' +% +% These options influence the forward computation of the leadfield +% 'reducerank' = reduce the leadfield rank, can be 'no' or a number (e.g. 2) +% 'normalize' = normalize the leadfield +% 'normalizeparam' = parameter for depth normalization (default = 0.5) +% +% If the dipole definition only specifies the dipole location, a rotating +% dipole (regional source) is assumed on each location. If a dipole moment +% is specified, its orientation will be used and only the strength will +% be fitted to the data. + +% Copyright (C) 2003-2008, Robert Oostenveld +% +% Subversion does not use the Log keyword, use 'svn log ' or 'svn -v log | less' to get detailled information + +if mod(nargin-5,2) + % the first 5 arguments are fixed, the other arguments should come in pairs + error('invalid number of optional arguments'); +end + +% these optional settings do not have defaults +Pr = keyval('Pr', varargin); +Cr = keyval('Cr', varargin); +refdip = keyval('refdip', varargin); +powmethod = keyval('powmethod', varargin); % the default for this is set below +realfilter = keyval('realfilter', varargin); % the default for this is set below +% these settings pertain to the forward model, the defaults are set in compute_leadfield +reducerank = keyval('reducerank', varargin); +normalize = keyval('normalize', varargin); +normalizeparam = keyval('normalizeparam', varargin); +% these optional settings have defaults +feedback = keyval('feedback', varargin); if isempty(feedback), feedback = 'text'; end +keepcsd = keyval('keepcsd', varargin); if isempty(keepcsd), keepcsd = 'no'; end +keepfilter = keyval('keepfilter', varargin); if isempty(keepfilter), keepfilter = 'no'; end +keepleadfield = keyval('keepleadfield', varargin); if isempty(keepleadfield), keepleadfield = 'no'; end +lambda = keyval('lambda', varargin); if isempty(lambda ), lambda = 0; end +projectnoise = keyval('projectnoise', varargin); if isempty(projectnoise), projectnoise = 'yes'; end +fixedori = keyval('fixedori', varargin); if isempty(fixedori), fixedori = 'no'; end + +% convert the yes/no arguments to the corresponding logical values +keepcsd = strcmp(keepcsd, 'yes'); +keepfilter = strcmp(keepfilter, 'yes'); +keepleadfield = strcmp(keepleadfield, 'yes'); +projectnoise = strcmp(projectnoise, 'yes'); +fixedori = strcmp(fixedori, 'yes'); +% FIXME besides regular/complex lambda1, also implement a real version + +% default is to use the largest singular value of the csd matrix, see Gross 2001 +if isempty(powmethod) + powmethod = 'lambda1'; +end + +% default is to be consistent with the original description of DICS in Gross 2001 +if isempty(realfilter) + realfilter = 'no'; +end + +% use these two logical flags instead of doing the string comparisons each time again +powtrace = strcmp(powmethod, 'trace'); +powlambda1 = strcmp(powmethod, 'lambda1'); + +if ~isempty(Cr) + % ensure that the cross-spectral density with the reference signal is a column matrix + Cr = Cr(:); +end + +if isfield(dip, 'mom') && fixedori + error('you cannot specify a dipole orientation and fixedmom simultaneously'); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% find the dipole positions that are inside/outside the brain +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +if ~isfield(dip, 'inside') && ~isfield(dip, 'outside'); + [dip.inside, dip.outside] = find_inside_vol(dip.pos, vol); +elseif isfield(dip, 'inside') && ~isfield(dip, 'outside'); + dip.outside = setdiff(1:size(dip.pos,1), dip.inside); +elseif ~isfield(dip, 'inside') && isfield(dip, 'outside'); + dip.inside = setdiff(1:size(dip.pos,1), dip.outside); +end + +% select only the dipole positions inside the brain for scanning +dip.origpos = dip.pos; +dip.originside = dip.inside; +dip.origoutside = dip.outside; +if isfield(dip, 'mom') + dip.mom = dip.mom(:,dip.inside); +end +if isfield(dip, 'leadfield') + fprintf('using precomputed leadfields\n'); + dip.leadfield = dip.leadfield(dip.inside); +end +if isfield(dip, 'filter') + fprintf('using precomputed filters\n'); + dip.filter = dip.filter(dip.inside); +end +if isfield(dip, 'subspace') + fprintf('using subspace projection\n'); + dip.subspace = dip.subspace(dip.inside); +end +dip.pos = dip.pos(dip.inside, :); +dip.inside = 1:size(dip.pos,1); +dip.outside = []; + +% dics has the following sub-methods, which depend on the function input arguments +% power only, cortico-muscular coherence and cortico-cortical coherence +if ~isempty(Cr) && ~isempty(Pr) && isempty(refdip) + % compute cortico-muscular coherence, using reference cross spectral density + submethod = 'dics_refchan'; +elseif isempty(Cr) && isempty(Pr) && ~isempty(refdip) + % compute cortico-cortical coherence with a dipole at the reference position + submethod = 'dics_refdip'; +elseif isempty(Cr) && isempty(Pr) && isempty(refdip) + % only compute power of a dipole at the grid positions + submethod = 'dics_power'; +else + error('invalid combination of input arguments for dics'); +end + +isrankdeficient = (rank(Cf) m + X = pinv(A',varargin{:})'; +else + [U,S,V] = svd(A,0); + if m > 1, s = diag(S); + elseif m == 1, s = S(1); + else s = 0; + end + if nargin == 2 + tol = varargin{1}; + else + tol = 10 * max(m,n) * max(s) * eps; + end + r = sum(s > tol); + if (r == 0) + X = zeros(size(A'),class(A)); + else + s = diag(ones(r,1)./s(1:r)); + X = V(:,1:r)*s*U(:,1:r)'; + end +end + diff --git a/external/fieldtrip/inverse/beamformer_lcmv.m b/external/fieldtrip/inverse/beamformer_lcmv.m new file mode 100644 index 0000000..379b599 --- /dev/null +++ b/external/fieldtrip/inverse/beamformer_lcmv.m @@ -0,0 +1,377 @@ +function [dipout] = beamformer_lcmv(dip, grad, vol, dat, Cy, varargin) + +% BEAMFORMER_LCMV scans on pre-defined dipole locations with a single dipole +% and returns the beamformer spatial filter output for a dipole on every +% location. Dipole locations that are outside the head will return a +% NaN value. +% +% Use as +% [dipout] = beamformer_lcmv(dipin, grad, vol, dat, cov, varargin) +% where +% dipin is the input dipole model +% grad is the gradiometer definition +% vol is the volume conductor definition +% dat is the data matrix with the ERP or ERF +% cov is the data covariance or cross-spectral density matrix +% and +% dipout is the resulting dipole model with all details +% +% The input dipole model consists of +% dipin.pos positions for dipole, e.g. regular grid +% dipin.mom dipole orientation (optional) +% +% Additional options should be specified in key-value pairs and can be +% 'lambda' = regularisation parameter +% 'powmethod' = can be 'trace' or 'lambda1' +% 'feedback' = give progress indication, can be 'text', 'gui' or 'none' (default) +% 'fixedori' = use fixed or free orientation, can be 'yes' or 'no' +% 'projectnoise' = project noise estimate through filter, can be 'yes' or 'no' +% 'projectmom' = project the dipole moment timecourse on the direction of maximal power, can be 'yes' or 'no' +% 'keepfilter' = remember the beamformer filter, can be 'yes' or 'no' +% 'keepleadfield' = remember the forward computation, can be 'yes' or 'no' +% 'keepmom' = remember the estimated dipole moment, can be 'yes' or 'no' +% 'keepcov' = remember the estimated dipole covariance, can be 'yes' or 'no' +% +% These options influence the forward computation of the leadfield +% 'reducerank' = reduce the leadfield rank, can be 'no' or a number (e.g. 2) +% 'normalize' = normalize the leadfield +% 'normalizeparam' = parameter for depth normalization (default = 0.5) +% +% If the dipole definition only specifies the dipole location, a rotating +% dipole (regional source) is assumed on each location. If a dipole moment +% is specified, its orientation will be used and only the strength will +% be fitted to the data. + +% Copyright (C) 2003-2008, Robert Oostenveld +% +% Subversion does not use the Log keyword, use 'svn log ' or 'svn -v log | less' to get detailled information + +if mod(nargin-5,2) + % the first 5 arguments are fixed, the other arguments should come in pairs + error('invalid number of optional arguments'); +end + +% these optional settings do not have defaults +powmethod = keyval('powmethod', varargin); % the default for this is set below +subspace = keyval('subspace', varargin); % used to implement an "eigenspace beamformer" as described in Sekihara et al. 2002 in HBM +% these settings pertain to the forward model, the defaults are set in compute_leadfield +reducerank = keyval('reducerank', varargin); +normalize = keyval('normalize', varargin); +normalizeparam = keyval('normalizeparam', varargin); +% these optional settings have defaults +feedback = keyval('feedback', varargin); if isempty(feedback), feedback = 'text'; end +keepfilter = keyval('keepfilter', varargin); if isempty(keepfilter), keepfilter = 'no'; end +keepleadfield = keyval('keepleadfield', varargin); if isempty(keepleadfield), keepleadfield = 'no'; end +keepcov = keyval('keepcov', varargin); if isempty(keepcov), keepcov = 'no'; end +keepmom = keyval('keepmom', varargin); if isempty(keepmom), keepmom = 'yes'; end +lambda = keyval('lambda', varargin); if isempty(lambda ), lambda = 0; end +projectnoise = keyval('projectnoise', varargin); if isempty(projectnoise), projectnoise = 'yes'; end +projectmom = keyval('projectmom', varargin); if isempty(projectmom), projectmom = 'no'; end +fixedori = keyval('fixedori', varargin); if isempty(fixedori), fixedori = 'no'; end + +% convert the yes/no arguments to the corresponding logical values +keepfilter = strcmp(keepfilter, 'yes'); +keepleadfield = strcmp(keepleadfield, 'yes'); +keepcov = strcmp(keepcov, 'yes'); +keepmom = strcmp(keepmom, 'yes'); +projectnoise = strcmp(projectnoise, 'yes'); +projectmom = strcmp(projectmom, 'yes'); +fixedori = strcmp(fixedori, 'yes'); + +% default is to use the trace of the covariance matrix, see Van Veen 1997 +if isempty(powmethod) + powmethod = 'trace'; +end + +% use these two logical flags instead of doing the string comparisons each time again +powtrace = strcmp(powmethod, 'trace'); +powlambda1 = strcmp(powmethod, 'lambda1'); + +if isfield(dip, 'mom') && fixedori + error('you cannot specify a dipole orientation and fixedmom simultaneously'); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% find the dipole positions that are inside/outside the brain +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +if ~isfield(dip, 'inside') && ~isfield(dip, 'outside'); + [dip.inside, dip.outside] = find_inside_vol(dip.pos, vol); +elseif isfield(dip, 'inside') && ~isfield(dip, 'outside'); + dip.outside = setdiff(1:size(dip.pos,1), dip.inside); +elseif ~isfield(dip, 'inside') && isfield(dip, 'outside'); + dip.inside = setdiff(1:size(dip.pos,1), dip.outside); +end + +% select only the dipole positions inside the brain for scanning +dip.origpos = dip.pos; +dip.originside = dip.inside; +dip.origoutside = dip.outside; +if isfield(dip, 'mom') + dip.mom = dip.mom(:, dip.inside); +end +if isfield(dip, 'leadfield') + fprintf('using precomputed leadfields\n'); + dip.leadfield = dip.leadfield(dip.inside); +end +if isfield(dip, 'filter') + fprintf('using precomputed filters\n'); + dip.filter = dip.filter(dip.inside); +end +if isfield(dip, 'subspace') + fprintf('using subspace projection\n'); + dip.subspace = dip.subspace(dip.inside); +end +dip.pos = dip.pos(dip.inside, :); +dip.inside = 1:size(dip.pos,1); +dip.outside = []; + +isrankdeficient = (rank(Cy)=1 it is the number of largest eigenvalues + dat_pre_subspace = dat; + Cy_pre_subspace = Cy; + [u, s, v] = svd(real(Cy)); + if subspace<1, + sel = find(diag(s)./s(1,1) > subspace); + subspace = max(sel); + else + Cy = s(1:subspace,1:subspace); + % this is equivalent to subspace*Cy*subspace' but behaves well numerically + % by construction. + invCy = diag(1./diag(Cy)); + subspace = u(:,1:subspace)'; + dat = subspace*dat; + end + else + dat_pre_subspace = dat; + Cy_pre_subspace = Cy; + Cy = subspace*Cy*subspace'; % here the subspace can be different from + % the singular vectors of Cy, so we have to do the sandwiching as opposed + % to line 216 + invCy = pinv(Cy); + dat = subspace*dat; + end +end + +% start the scanning with the proper metric +progress('init', feedback, 'scanning grid'); + +for i=1:size(dip.pos,1) + if isfield(dip, 'leadfield') + % reuse the leadfield that was previously computed + lf = dip.leadfield{i}; + elseif isfield(dip, 'mom') + % compute the leadfield for a fixed dipole orientation + lf = ft_compute_leadfield(dip.pos(i,:), grad, vol, 'reducerank', reducerank, 'normalize', normalize, 'normalizeparam', normalizeparam) * dip.mom(:,i); + else + % compute the leadfield + lf = ft_compute_leadfield(dip.pos(i,:), grad, vol, 'reducerank', reducerank, 'normalize', normalize, 'normalizeparam', normalizeparam); + end + + if isfield(dip, 'subspace') + % do subspace projection of the forward model + lf = dip.subspace{i} * lf; + % the data and the covariance become voxel dependent due to the projection + dat = dip.subspace{i} * dat_pre_subspace; + Cy = dip.subspace{i} * (Cy_pre_subspace + lambda * eye(size(Cy_pre_subspace))) * dip.subspace{i}'; + invCy = pinv(dip.subspace{i} * (Cy_pre_subspace + lambda * eye(size(Cy_pre_subspace))) * dip.subspace{i}'); + elseif ~isempty(subspace) + % do subspace projection of the forward model only + lforig = lf; + lf = subspace * lf; + + % according to Kensuke's paper, the eigenspace bf boils down to projecting + % the 'traditional' filter onto the subspace + % spanned by the first k eigenvectors [u,s,v] = svd(Cy); filt = ESES*filt; + % ESES = u(:,1:k)*u(:,1:k)'; + % however, even though it seems that the shape of the filter is identical to + % the shape it is obtained with the following code, the w*lf=I does not hold. + end + + if fixedori + % compute the leadfield for the optimal dipole orientation + % subsequently the leadfield for only that dipole orientation will be used for the final filter computation + % filt = pinv(lf' * invCy * lf) * lf' * invCy; + % [u, s, v] = svd(real(filt * Cy * ctranspose(filt))); + % in this step the filter computation is not necessary, use the quick way to compute the voxel level covariance (cf. van Veen 1997) + [u, s, v] = svd(real(pinv(lf' * invCy *lf))); + eta = u(:,1); + lf = lf * eta; + if ~isempty(subspace), lforig = lforig * eta; end + dipout.ori{i} = eta; + end + + if isfield(dip, 'filter') + % use the provided filter + filt = dip.filter{i}; + else + % construct the spatial filter + filt = pinv(lf' * invCy * lf) * lf' * invCy; % van Veen eqn. 23, use PINV/SVD to cover rank deficient leadfield + end + if projectmom + [u, s, v] = svd(filt * Cy * ctranspose(filt)); + mom = u(:,1); + filt = (mom') * filt; + end + if powlambda1 + % dipout.pow(i) = lambda1(pinv(lf' * invCy * lf)); % this is more efficient if the filters are not present + dipout.pow(i) = lambda1(filt * Cy * ctranspose(filt)); % this is more efficient if the filters are present + elseif powtrace + % dipout.pow(i) = trace(pinv(lf' * invCy * lf)); % this is more efficient if the filters are not present, van Veen eqn. 24 + dipout.pow(i) = trace(filt * Cy * ctranspose(filt)); % this is more efficient if the filters are present + end + if keepcov + % compute the source covariance matrix + dipout.cov{i} = filt * Cy * ctranspose(filt); + end + if keepmom && ~isempty(dat) + % estimate the instantaneous dipole moment at the current position + dipout.mom{i} = filt * dat; + end + if projectnoise + % estimate the power of the noise that is projected through the filter + if powlambda1 + dipout.noise(i) = noise * lambda1(filt * ctranspose(filt)); + elseif powtrace + dipout.noise(i) = noise * trace(filt * ctranspose(filt)); + end + if keepcov + dipout.noisecov{i} = noise * filt * ctranspose(filt); + end + end + if keepfilter + if ~isempty(subspace) + %dipout.filter{i} = filt*subspace; + dipout.filter{i} = filt*pinv(subspace); + else + dipout.filter{i} = filt; + end + end + if keepleadfield + if ~isempty(subspace) + dipout.leadfield{i} = lforig; + else + dipout.leadfield{i} = lf; + end + end + progress(i/size(dip.pos,1), 'scanning grid %d/%d\n', i, size(dip.pos,1)); +end + +progress('close'); + +dipout.inside = dip.originside; +dipout.outside = dip.origoutside; +dipout.pos = dip.origpos; + +% reassign the scan values over the inside and outside grid positions +if isfield(dipout, 'leadfield') + dipout.leadfield(dipout.inside) = dipout.leadfield; + dipout.leadfield(dipout.outside) = {[]}; +end +if isfield(dipout, 'filter') + dipout.filter(dipout.inside) = dipout.filter; + dipout.filter(dipout.outside) = {[]}; +end +if isfield(dipout, 'mom') + dipout.mom(dipout.inside) = dipout.mom; + dipout.mom(dipout.outside) = {[]}; +end +if isfield(dipout, 'ori') + dipout.ori(dipout.inside) = dipout.ori; + dipout.ori(dipout.outside) = {[]}; +end +if isfield(dipout, 'cov') + dipout.cov(dipout.inside) = dipout.cov; + dipout.cov(dipout.outside) = {[]}; +end +if isfield(dipout, 'noisecov') + dipout.noisecov(dipout.inside) = dipout.noisecov; + dipout.noisecov(dipout.outside) = {[]}; +end +if isfield(dipout, 'pow') + dipout.pow(dipout.inside) = dipout.pow; + dipout.pow(dipout.outside) = nan; +end +if isfield(dipout, 'noise') + dipout.noise(dipout.inside) = dipout.noise; + dipout.noise(dipout.outside) = nan; +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% helper function to obtain the largest singular value +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function s = lambda1(x) +% determine the largest singular value, which corresponds to the power along the dominant direction +s = svd(x); +s = s(1); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% helper function to compute the pseudo inverse. This is the same as the +% standard Matlab function, except that the default tolerance is twice as +% high. +% Copyright 1984-2004 The MathWorks, Inc. +% $Revision: 919 $ $Date: 2009/03/23 21:14:42 $ +% default tolerance increased by factor 2 (Robert Oostenveld, 7 Feb 2004) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function X = pinv(A,varargin) +[m,n] = size(A); +if n > m + X = pinv(A',varargin{:})'; +else + [U,S,V] = svd(A,0); + if m > 1, s = diag(S); + elseif m == 1, s = S(1); + else s = 0; + end + if nargin == 2 + tol = varargin{1}; + else + tol = 10 * max(m,n) * max(s) * eps; + end + r = sum(s > tol); + if (r == 0) + X = zeros(size(A'),class(A)); + else + s = diag(ones(r,1)./s(1:r)); + X = V(:,1:r)*s*U(:,1:r)'; + end +end + diff --git a/external/forwinv/private/beamformer_pcc.m b/external/fieldtrip/inverse/beamformer_pcc.m similarity index 78% rename from external/forwinv/private/beamformer_pcc.m rename to external/fieldtrip/inverse/beamformer_pcc.m index c5616b2..19d1a9a 100644 --- a/external/forwinv/private/beamformer_pcc.m +++ b/external/fieldtrip/inverse/beamformer_pcc.m @@ -8,63 +8,7 @@ % % Copyright (C) 2005-2008, Robert Oostenveld & Jan-Mathijs Schoffelen -% $Log: beamformer_pcc.m,v $ -% Revision 1.18 2009/01/07 13:12:03 jansch -% *** empty log message *** -% -% Revision 1.17 2009/01/06 10:25:50 roboos -% changed & into && -% -% Revision 1.16 2008/10/10 13:01:18 release -% fixed bug: switched order of lambda processing (i.e. as "10%") and filter computation (thanks to Joachim). -% removed double warning for rank deficient. -% -% Revision 1.15 2008/08/13 13:47:42 roboos -% updated documentation -% -% Revision 1.14 2008/07/02 16:03:05 roboos -% fixed bug in % lambda -% -% Revision 1.13 2008/07/02 07:57:33 roboos -% allow specification of percentage noise in lambda, relative to trace(cov)/nchans -% -% Revision 1.12 2008/03/18 13:01:17 roboos -% added optional argument normalizeparam, is passed onto compute_leadfield -% -% Revision 1.11 2007/12/11 11:17:49 roboos -% fixed bug in handling of prespecified dipole moment -% -% Revision 1.10 2006/10/12 10:15:36 roboos -% close the progress indicator -% -% Revision 1.9 2006/10/12 10:11:24 roboos -% fixed bug in selecting dipoles on the inside positions only -% output cell-arrays are [] for outside points -% removed catch for mom, fixed dipoles should also work -% -% Revision 1.8 2006/10/12 09:05:11 roboos -% restructured code to behave as a stand-alone function -% -% Revision 1.6 2006/05/04 08:03:37 roboos -% fixed a bug in the concatenation of the filters, which applied when the channel order was EMG-MEG instead of the more usual MEG-EMG -% -% Revision 1.5 2006/03/01 10:47:06 roboos -% test rank of meg part only instead of full CSD matrix -% -% Revision 1.4 2006/03/01 08:07:33 roboos -% added support for realfilter option -% -% Revision 1.3 2005/11/21 09:33:49 roboos -% added handling of optional reducerank/normalize/powmethod input arguments -% -% Revision 1.2 2005/11/08 11:04:36 roboos -% implemented support for normalize and reducerank using compute_leadfield -% changed from optarg structure to keyval function -% -% Revision 1.1 2005/06/08 16:36:27 roboos -% new implementation, still in experimental stage -% DO NOT DISTRIBUTE -% +% Subversion does not use the Log keyword, use 'svn log ' or 'svn -v log | less' to get detailled information if mod(nargin-5,2) % the first 5 arguments are fixed, the other arguments should come in pairs @@ -132,13 +76,13 @@ dip.outside = []; if ~isempty(refdip) - rf = compute_leadfield(refdip, grad, vol, 'reducerank', reducerank, 'normalize', normalize); + rf = ft_compute_leadfield(refdip, grad, vol, 'reducerank', reducerank, 'normalize', normalize); else rf = []; end if ~isempty(supdip) - sf = compute_leadfield(supdip, grad, vol, 'reducerank', reducerank, 'normalize', normalize); + sf = ft_compute_leadfield(supdip, grad, vol, 'reducerank', reducerank, 'normalize', normalize); else sf = []; end @@ -199,10 +143,10 @@ lf = dip.leadfield{i} * dip.mom(:,i); elseif ~isfield(dip, 'leadfield') && isfield(dip, 'mom') % compute the leadfield for a fixed dipole orientation - lf = compute_leadfield(dip.pos(i,:), grad, vol, 'reducerank', reducerank, 'normalize', normalize, 'normalizeparam', normalizeparam) * dip.mom(:,i); + lf = ft_compute_leadfield(dip.pos(i,:), grad, vol, 'reducerank', reducerank, 'normalize', normalize, 'normalizeparam', normalizeparam) * dip.mom(:,i); else % compute the leadfield - lf = compute_leadfield(dip.pos(i,:), grad, vol, 'reducerank', reducerank, 'normalize', normalize, 'normalizeparam', normalizeparam); + lf = ft_compute_leadfield(dip.pos(i,:), grad, vol, 'reducerank', reducerank, 'normalize', normalize, 'normalizeparam', normalizeparam); end % concatenate scandip, refdip and supdip @@ -287,7 +231,7 @@ % standard Matlab function, except that the default tolerance is twice as % high. % Copyright 1984-2004 The MathWorks, Inc. -% $Revision: 1.18 $ $Date: 2009/01/07 13:12:03 $ +% $Revision: 919 $ $Date: 2009/01/07 13:12:03 $ % default tolerance increased by factor 2 (Robert Oostenveld, 7 Feb 2004) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function X = pinv(A,varargin) diff --git a/external/fieldtrip/inverse/dipole_fit.m b/external/fieldtrip/inverse/dipole_fit.m new file mode 100644 index 0000000..6d72e14 --- /dev/null +++ b/external/fieldtrip/inverse/dipole_fit.m @@ -0,0 +1,268 @@ +function [dipout] = dipole_fit(dip, sens, vol, dat, varargin) + +% DIPOLE_FIT performs an equivalent current dipole fit with a single +% or a small number of dipoles to explain an EEG or MEG scalp topography. +% +% Use as +% [dipout] = dipole_fit(dip, sens, vol, dat, ...) +% +% Additional input arguments should be specified as key-value pairs and can include +% 'constr' = Structure with constraints +% 'display' = Level of display [ off | iter | notify | final ] +% 'optimfun' = Function to use [fminsearch | fminunc ] +% 'maxiter' = Maximum number of function evaluations allowed [ positive integer ] +% 'metric' = Error measure to be minimised [ rv | var | abs ] +% 'checkinside' = Boolean flag to check whether dipole is inside source compartment [ 0 | 1 ] +% 'weight' = weight matrix for maximum likelihood estimation, e.g. inverse noise covariance +% +% The following optional input arguments relate to the computation of the leadfields +% 'reducerank' = 'no' or number +% 'normalize' = 'no', 'yes' or 'column' +% 'normalizeparam' = parameter for depth normalization (default = 0.5) +% +% The maximum likelihood estimation implements +% Lutkenhoner B. "Dipole source localization by means of maximum +% likelihood estimation I. Theory and simulations" Electroencephalogr Clin +% Neurophysiol. 1998 Apr;106(4):314-21. + +% Copyright (C) 2003-2008, Robert Oostenveld +% +% Subversion does not use the Log keyword, use 'svn log ' or 'svn -v log | less' to get detailled information + +% It is neccessary to provide backward compatibility support for the old function call +% in case people want to use it in conjunction with EEGLAB and the dipfit1 plugin. +% old style: function [dipout] = dipole_fit(dip, dat, sens, vol, constr), where constr is optional +% new style: function [dipout] = dipole_fit(dip, sens, vol, dat, varargin), where varargin is in key-value pairs +if nargin==4 && ~isstruct(sens) && isstruct(dat) + % looks like old style, the order of the input arguments has to be changed + warning('converting from old style input\n'); + olddat = sens; + oldsens = vol; + oldvol = dat; + dat = olddat; + sens = oldsens; + vol = oldvol; +elseif nargin==5 && ~isstruct(sens) && isstruct(dat) + % looks like old style, the order of the input arguments has to be changed + % furthermore the additional constraint has to be fixed + warning('converting from old style input\n'); + olddat = sens; + oldsens = vol; + oldvol = dat; + dat = olddat; + sens = oldsens; + vol = oldvol; + varargin = {'constr', varargin{1}}; % convert into a key-value pair +else + % looks like new style, i.e. with optional key-value arguments + % this is dealt with below +end + +constr = keyval('constr', varargin); % default is not to have constraints +metric = keyval('metric', varargin); if isempty(metric), metric = 'rv'; end +checkinside = keyval('checkinside', varargin); if isempty(checkinside), checkinside = 0; end +display = keyval('display', varargin); if isempty(display), display = 'iter'; end +optimfun = keyval('optimfun', varargin); if isa(optimfun, 'char'), optimfun = str2fun(optimfun); end +maxiter = keyval('maxiter', varargin); +reducerank = keyval('reducerank', varargin); % for leadfield computation +normalize = keyval('normalize' , varargin); % for leadfield computation +normalizeparam = keyval('normalizeparam', varargin); % for leadfield computation +weight = keyval('weight', varargin); % for maximum likelihood estimation + +if isempty(optimfun) + % determine whether the Matlab Optimization toolbox is available and can be used + if hastoolbox('optim') + optimfun = @fminunc; + else + optimfun = @fminsearch; + end +end + +if isempty(maxiter) + % set a default for the maximum number of iterations, depends on the optimization function + if isequal(optimfun, @fminunc) + maxiter = 100; + else + maxiter = 500; + end +end + +% determine whether it is EEG or MEG +iseeg = ft_senstype(sens, 'eeg'); +ismeg = ft_senstype(sens, 'meg'); + +if ismeg && iseeg + % this is something that I might implement in the future + error('simultaneous EEG and MEG not supported'); +elseif iseeg + % ensure that the potential data is average referenced, just like the model potential + dat = avgref(dat); +end + +% ensure correct dipole position and moment specification +dip = fixdipole(dip); + +% reformat the position parameters in case of multiple dipoles, this +% should result in the matrix changing from [x1 y1 z1; x2 y2 z2] to +% [x1 y1 z1 x2 y2 z2] for the constraints to work +numdip = size(dip.pos, 1); +param = dip.pos'; +param = param(:)'; + +% add the orientation to the nonlinear parameters +if isfield(constr, 'fixedori') && constr.fixedori + for i=1:numdip + % add the orientation to the list of parameters + [th, phi, r] = cart2sph(dip.mom(1,i), dip.mom(2,i), dip.mom(3,i)); + param = [param th phi]; + end +end + +% reduce the number of parameters to be fitted according to the constraints +if isfield(constr, 'mirror') + param = param(constr.reduce); +end + +% set the parameters for the optimization function +if isequal(optimfun, @fminunc) + options = optimset(... + 'TolFun',1e-9,... + 'TypicalX',ones(size(param)),... + 'LargeScale','off',... + 'HessUpdate','bfgs',... + 'MaxIter',maxiter,... + 'MaxFunEvals',2*maxiter*length(param),... + 'Display',display); +elseif isequal(optimfun, @fminsearch) + options = optimset(... + 'MaxIter',maxiter,... + 'MaxFunEvals',2*maxiter*length(param),... + 'Display',display); +else + warning('unknown optimization function "%s", using default parameters', func2str(optimfun)); +end + +% perform the optimization with either the fminsearch or fminunc function +[param, fval, exitflag, output] = optimfun(@dipfit_error, param, options, dat, sens, vol, constr, metric, checkinside, reducerank, normalize, normalizeparam, weight); + +if exitflag==0 + error('Maximum number of iterations exceeded before reaching the minimum, please try with another initial guess.') +end + +% do linear optimization of dipole moment parameters +[err, mom] = dipfit_error(param, dat, sens, vol, constr, metric, checkinside, reducerank, normalize, normalizeparam, weight); + +% expand the number of parameters according to the constraints +if isfield(constr, 'mirror') + param = constr.mirror .* param(constr.expand); +end + +% get the dipole position and orientation +if isfield(constr, 'fixedori') && constr.fixedori + numdip = numel(param)/5; + ori = zeros(3,numdip); + for i=1:numdip + th = param(end-(2*i)+1); + phi = param(end-(2*i)+2); + [ori(1,i), ori(2,i), ori(3,i)] = sph2cart(th, phi, 1); + end + pos = reshape(param(1:(numdip*3)), 3, numdip)'; +else + numdip = numel(param)/3; + pos = reshape(param, 3, numdip)'; +end + +% return the optimal dipole parameters +dipout.pos = pos; +if isfield(constr, 'fixedori') && constr.fixedori + dipout.mom = ori; % dipole orientation as vector + dipout.ampl = mom; % dipole strength +else + dipout.mom = mom; % dipole moment as vector or matrix, which represents both the orientation and strength as vector +end + +% ensure correct dipole position and moment specification +dipout = fixdipole(dipout); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% DIPFIT_ERROR computes the error between measured and model data +% and can be used for non-linear fitting of dipole position +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [err, mom] = dipfit_error(param, dat, sens, vol, constr, metric, checkinside, reducerank, normalize, normalizeparam, weight) + +% flush pending graphics events, ensure that fitting is interruptible +drawnow; +if ~isempty(get(0, 'currentfigure')) && strcmp(get(gcf, 'tag'), 'stop') + % interrupt the fitting + close; + error('USER ABORT'); +end; + +% expand the number of parameters according to the constraints +if isfield(constr, 'mirror') + param = constr.mirror .* param(constr.expand); +end + +% get the dipole positions and optionally also the orientation +if isfield(constr, 'fixedori') && constr.fixedori + numdip = numel(param)/5; + ori = zeros(3,numdip); + for i=1:numdip + th = param(end-(2*i)+1); + phi = param(end-(2*i)+2); + [ori(1,i), ori(2,i), ori(3,i)] = sph2cart(th, phi, 1); + end + pos = reshape(param(1:(numdip*3)), 3, numdip)'; +else + numdip = numel(param)/3; + pos = reshape(param, 3, numdip)'; +end + +% check whether the dipole is inside the source compartment +if checkinside + [inside, outside] = find_inside_vol(pos, vol); + if ~isempty(outside) + error('Dipole is outside the source compartment'); + end +end + +% construct the leadfield matrix for all dipoles +lf = ft_compute_leadfield(pos, sens, vol, 'reducerank', reducerank, 'normalize', normalize, 'normalizeparam', normalizeparam); +if isfield(constr, 'fixedori') && constr.fixedori + lf = lf * ori; +end + +% compute the optimal dipole moment and the model error +if ~isempty(weight) + % maximum likelihood estimation using the weigth matrix + mom = pinv(lf'*weight*lf)*lf'*weight*dat; % Lutkenhoner equation 5 + dif = dat - lf*mom; + % compute the generalized goodness-of-fit measure + switch metric + case 'rv' % relative residual variance + num = dif' * weight * dif; + denom = dat' * weight * dat; + err = sum(num(:)) ./ sum(denom(:)); % Lutkenhonner equation 7, except for the gof=1-rv + case 'var' % residual variance + num = dif' * weight * dif'; + err = sum(num(:)); + otherwise + error('Unsupported error metric for maximum likelihood dipole fitting'); + end +else + % ordinary least squares, this is the same as MLE with weight=eye(nchans,nchans) + mom = pinv(lf)*dat; + dif = dat - lf*mom; + % compute the ordinary goodness-of-fit measures + switch metric + case 'rv' % relative residual variance + err = sum(dif(:).^2) / sum(dat(:).^2); + case 'var' % residual variance + err = sum(dif(:).^2); + case 'abs' % absolute difference + err = sum(abs(dif)); + otherwise + error('Unsupported error metric for dipole fitting'); + end +end + diff --git a/external/fieldtrip/inverse/minimumnormestimate.m b/external/fieldtrip/inverse/minimumnormestimate.m new file mode 100644 index 0000000..b0f514e --- /dev/null +++ b/external/fieldtrip/inverse/minimumnormestimate.m @@ -0,0 +1,142 @@ +function [dipout] = minimumnormestimate(dip, grad, vol, dat, varargin); + +% MINIMUMNORMESTIMATE computes a linear estimate of the current +% in a distributed source model +% +% Use as +% [dipout] = minimumnormestimate(dip, grad, vol, dat, ...) +% +% Optional input arguments should come in key-value pairs and can include +% 'noisecov' = Nchan x Nchan matrix with noise covariance +% 'sourcecov' = Nsource x Nsource matrix with source covariance (can be empty, the default will then be identity) +% 'lambda' = scalar, regularisation parameter (can be empty, it will then be estimated from snr) +% 'snr' = scalar, signal to noise ratio +% 'reducerank' = reduce the leadfield rank, can be 'no' or a number (e.g. 2) +% 'normalize' = normalize the leadfield +% 'normalizeparam' = parameter for depth normalization (default = 0.5) +% +% Note that leadfield normalization (depth regularisation) should be +% done by scaling the leadfields outside this function, e.g. in +% prepare_leadfield. +% +% This implements +% * Dale AM, Liu AK, Fischl B, Buckner RL, Belliveau JW, Lewine JD, +% Halgren E (2000): Dynamic statistical parametric mapping: combining +% fMRI and MEG to produce high-resolution spatiotemporal maps of +% cortical activity. Neuron 26:55-67. +% * Arthur K. Liu, Anders M. Dale, and John W. Belliveau (2002): Monte +% Carlo Simulation Studies of EEG and MEG Localization Accuracy. +% Human Brain Mapping 16:47-62. +% * Fa-Hsuan Lin, Thomas Witzel, Matti S. Hamalainen, Anders M. Dale, +% John W. Belliveau, and Steven M. Stufflebeam (2004): Spectral +% spatiotemporal imaging of cortical oscillations and interactions +% in the human brain. NeuroImage 23:582-595. + +% TODO implement the following options +% - keepleadfield +% - keepfilter +% - keepinverse (i.e. equivalent to keepfilter) + +% Copyright (C) 2004-2008, Robert Oostenveld +% +% Subversion does not use the Log keyword, use 'svn log ' or 'svn -v log | less' to get detailled information + +% ensure that these are row-vectors +dip.inside = dip.inside(:)'; +dip.outside = dip.outside(:)'; + +% get the optional inputs for the MNE method according to Dale et al 2000, and Liu et al. 2002 +noisecov = keyval('noisecov', varargin); +sourcecov = keyval('sourcecov', varargin); +lambda = keyval('lambda', varargin); % can be empty, it will then be estimated based on SNR +snr = keyval('snr', varargin); % is used to estimate lambda if lambda is not specified +% these settings pertain to the forward model, the defaults are set in compute_leadfield +reducerank = keyval('reducerank', varargin); +normalize = keyval('normalize', varargin); +normalizeparam = keyval('normalizeparam', varargin); + +if ~isfield(dip, 'leadfield') + fprintf('computing forward model\n'); + if isfield(dip, 'mom') + for i=dip.inside + % compute the leadfield for a fixed dipole orientation + dip.leadfield{i} = ft_compute_leadfield(dip.pos(i,:), grad, vol, 'reducerank', reducerank, 'normalize', normalize, 'normalizeparam', normalizeparam) * dip.mom(:,i); + end + else + for i=dip.inside + % compute the leadfield + dip.leadfield{i} = ft_compute_leadfield(dip.pos(i,:), grad, vol, 'reducerank', reducerank, 'normalize', normalize, 'normalizeparam', normalizeparam); + end + end + for i=dip.outside + dip.leadfield{i} = nan; + end +else + fprintf('using specified forward model\n'); +end + +Nchan = length(grad.label); + +% count the number of leadfield components for each source +Nsource = 0; +for i=dip.inside + Nsource = Nsource + size(dip.leadfield{i}, 2); +end + +% concatenate the leadfield components of all sources into one large matrix +lf = zeros(Nchan, Nsource); +n = 1; +for i=dip.inside + cbeg = n; + cend = n + size(dip.leadfield{i}, 2) - 1; + lf(:,cbeg:cend) = dip.leadfield{i}; + n = n + size(dip.leadfield{i}, 2); +end + +fprintf('computing MNE source reconstruction, this may take some time...\n'); +% compute the inverse o the forward model, this is where prior information +% on source and noise covariance would be usefull +if isempty(noisecov) + % use an unregularised minimum norm solution, i.e. using the Moore-Penrose pseudoinverse + w = pinv(lf); +else + % the noise covariance has been given and can be used to regularise the solution + if isempty(sourcecov) + sourcecov = eye(Nsource); + end + % rename some variables for consistency with the publications + A = lf; + R = sourcecov; + C = noisecov; + % the regularisation parameter can be estimated from the noise covariance, see equation 6 in Lin et al. 2004 + if isempty(lambda) + lambda = trace(A * R * A')/(trace(C)*snr^2); + end + % equation 5 from Lin et al 2004 (this implements Dale et al 2000, and Liu et al. 2002) + w = R * A' * inv( A * R * A' + (lambda^2) * C); +end + +% for each of the timebins, estimate the source strength +mom = w * dat; + +% re-assign the estimated source strength over the inside and outside dipoles +n = 1; +for i=dip.inside + cbeg = n; + cend = n + size(dip.leadfield{i}, 2) - 1; + dipout.mom{i} = mom(cbeg:cend,:); + n = n + size(dip.leadfield{i}, 2); +end +dipout.mom(dip.outside) = {nan}; + +% for convenience also compute power at each location +for i=dip.inside + dipout.pow(i,:) = sum(dipout.mom{i}.^2, 1); +end +dipout.pow(dip.outside,:) = nan; + +% add other descriptive information to the output source model +dipout.pos = dip.pos; +dipout.inside = dip.inside; +dipout.outside = dip.outside; + diff --git a/external/fieldtrip/inverse/music.m b/external/fieldtrip/inverse/music.m new file mode 100644 index 0000000..2b2ed5c --- /dev/null +++ b/external/fieldtrip/inverse/music.m @@ -0,0 +1,99 @@ +function [dipout] = music(dip, grad, vol, dat, varargin); + +% MUSIC source localization using MUltiple SIgnal Classification +% +% This is a signal subspace method, which covers the techniques for +% multiple source localization by using the eigen structure of the +% measured data matrix. +% +% Use as +% [dipout] = music(dip, grad, vol, dat, ...) +% +% Optional input arguments should be specified as key-value pairs and can be +% 'cov' = data covariance matrix +% 'numcomponent' = integer number +% 'feedback' = 'none', 'gui', 'dial', 'textbar', 'text', 'textcr', 'textnl' +% 'reducerank' = reduce the leadfield rank, can be 'no' or a number (e.g. 2) +% 'normalize' = normalize the leadfield +% 'normalizeparam' = parameter for depth normalization (default = 0.5) +% +% The original reference is +% J.C. Mosher, P.S. Lewis and R.M. Leahy, "Multiple dipole modeling and +% localization from spatiotemporal MEG data", IEEE Trans. Biomed. +% Eng., pp 541-557, June, 1992. + +% Copyright (C) 2004-2008, Robert Oostenveld +% +% Subversion does not use the Log keyword, use 'svn log ' or 'svn -v log | less' to get detailled information + +% get the optional settings, or use the default value +cov = keyval('cov', varargin); +numcomponent = keyval('numcomponent', varargin); % this is required, see below +feedback = keyval('feedback', varargin); if isempty(feedback), feedback = 'text'; end +% these settings pertain to the forward model, the defaults are set in compute_leadfield +reducerank = keyval('reducerank', varargin); +normalize = keyval('normalize', varargin); +normalizeparam = keyval('normalizeparam', varargin); + +if isempty(numcomponent) + error('you must specify the number of signal components'); +end + +% ensure that these are row-vectors +dip.inside = dip.inside(:)'; +dip.outside = dip.outside(:)'; + +Nchan = length(grad.label); +Ndip = length(dip.inside); + +if ~isempty(cov) + % compute signal and noise subspace from covariance matrix + [u, s, v] = svd(cov); +else + % compute signal and noise subspace from average data matrix + [u, s, v] = svd(dat); +end +% select the noise subspace, c.f. equation 25 +us = u(:,(numcomponent+1):end); +ps = us * us'; + +% allocate space to hold the result +jr = zeros(length(dip.inside)+length(dip.outside),1); + +progress('init', feedback, 'computing music metric'); +for i=1:length(dip.inside) + + progress(i/length(dip.inside), 'computing music metric %d/%d\n', i, length(dip.inside)); + i = dip.inside(i); + + if isfield(dip, 'leadfield') + % reuse the leadfield that was previously computed + lf = dip.leadfield{i}; + elseif isfield(dip, 'mom') + % compute the leadfield for a fixed dipole orientation + lf = ft_compute_leadfield(dip.pos(i,:), grad, vol, 'reducerank', reducerank, 'normalize', normalize, 'normalizeparam', normalizeparam) * dip.mom(:,i); + else + % compute the leadfield + lf = ft_compute_leadfield(dip.pos(i,:), grad, vol, 'reducerank', reducerank, 'normalize', normalize, 'normalizeparam', normalizeparam); + end + + % compute the MUSIC metric, c.f. equation 26 + jr(i) = (norm(ps * lf)./norm(lf)).^2; + % as described in the Mosher 1992 paper on page 550, "...the general approach is to + % evaluare Jr(i) over a fine three-dimensional grid, plot its inverse, + % and look for p sharp spikes..." + +end +progress('close'); + +% locations outside the head get assigned a nan +jr(dip.outside) = nan; + +% assign the output data +dipout.jr = jr(:); % ensure that it is a column vector + +% add other descriptive information to the output source model +dipout.pos = dip.pos; +dipout.inside = dip.inside; +dipout.outside = dip.outside; + diff --git a/external/fieldtrip/inverse/private/avgref.m b/external/fieldtrip/inverse/private/avgref.m new file mode 100644 index 0000000..eba47f2 --- /dev/null +++ b/external/fieldtrip/inverse/private/avgref.m @@ -0,0 +1,59 @@ +function [data] = avgref(data, sel); + +% AVGREF computes the average reference in each column +% [data] = avgref(data) +% +% or it computes the re-referenced data relative to the +% average over the selected channels +% [data] = avgref(data, sel) + +% Copyright (C) 1998-2002, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: avgref.m 946 2010-04-21 17:51:16Z roboos $ + +% determine the dimension of the data +if length(size(data))==3 + % multiple epochs + dim=3; +else + % single epoch with multiple channels + dim=2; +end + +if nargin==1 + % default is to use all channels for average referencing + if dim==3 + sel=1:size(data,2); + else + sel=1:size(data,1); + end +end + +if dim==3 + % the data contains multiple epochs + for epoch=1:size(data,1) + reference = mean(squeeze(data(epoch,sel,:)), 1); + data(epoch,:,:) = squeeze(data(epoch,:,:)) - repmat(reference, size(data,2), 1); + end +else + % the data contains a single epoch + reference = mean(data(sel,:), 1); + data = data - repmat(reference, size(data,1), 1); +end + diff --git a/external/fieldtrip/inverse/private/bounding_mesh.m b/external/fieldtrip/inverse/private/bounding_mesh.m new file mode 100644 index 0000000..c2fddd8 --- /dev/null +++ b/external/fieldtrip/inverse/private/bounding_mesh.m @@ -0,0 +1,84 @@ +function [inside] = bounding_mesh(pos, pnt, tri); + +% BOUNDING_MESH determines if a point is inside/outside a triangle mesh +% whereby the bounding triangle mesh should be closed. +% +% [inside] = bounding_mesh(pos, pnt, tri) +% +% where +% pos position of point of interest (can be 1x3 or Nx3) +% pnt bounding mesh vertices +% tri bounding mesh triangles +% +% See also SOLID_ANGLE + +% Copyright (C) 2003, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: bounding_mesh.m 946 2010-04-21 17:51:16Z roboos $ + +global fb; +if isempty(fb) + fb = 0; +end + +npos = size(pos, 1); +npnt = size(pnt, 1); +ntri = size(tri, 1); + +% determine a cube that encompases the boundary triangulation +bound_min = min(pnt); +bound_max = max(pnt); + +% determine a sphere that is completely inside the boundary triangulation +bound_org = mean(pnt); +bound_rad = sqrt(min(sum((pnt - repmat(bound_org, size(pnt,1), 1)).^2, 2))); + +inside = zeros(npos, 1); +for i=1:npos + if fb + fprintf('%6.2f%%', 100*i/npos); + end + if any(pos(i,:)bound_max) + % the point is outside the bounding cube + inside(i) = 0; + if fb, fprintf(' outside the bounding cube\n'); end + elseif sqrt(sum((pos(i,:)-bound_org).^2, 2))0 + % total solid angle is (approximately) plus or minus 4*pi + inside(i) = 1; + end + if fb, fprintf(' solid angle\n'); end + end +end + diff --git a/external/fieldtrip/inverse/private/find_innermost_boundary.m b/external/fieldtrip/inverse/private/find_innermost_boundary.m new file mode 100644 index 0000000..d7b37a1 --- /dev/null +++ b/external/fieldtrip/inverse/private/find_innermost_boundary.m @@ -0,0 +1,57 @@ +function [innermost, inside] = find_innermost_boundary(bnd) + +% FIND_INNERMOST_BOUNDARY locates innermost compartment of a BEM model +% by looking at the containment of the triangular meshes describing +% the surface boundaries +% +% [innermost] = find_innermost_boundary(bnd) +% +% with the boundaries described by a struct array bnd with +% bnd(i).pnt vertices of boundary i (matrix of size Nx3) +% bnd(i).tri triangles of boundary i (matrix of size Mx3) + +% Copyright (C) 2003, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: find_innermost_boundary.m 946 2010-04-21 17:51:16Z roboos $ + +ncmp = length(bnd); + +if ncmp==1 + innermost = 1; + return +end + +% try to locate the innermost compartment +for i=1:ncmp +for j=1:ncmp + % determine for a single vertex on each surface if it is inside or outside the other surfaces + curpos = bnd(i).pnt(1,:); % any point on the boundary is ok + curpnt = bnd(j).pnt; + curtri = bnd(j).tri; + if i==j + inside(i,j) = 0; + else + inside(i,j) = bounding_mesh(curpos, curpnt, curtri); + end +end +end +% assume that the sources are in the innermost compartment +tmp = sum(inside, 2); +[i, innermost] = max(tmp); + diff --git a/external/fieldtrip/inverse/private/find_inside_vol.m b/external/fieldtrip/inverse/private/find_inside_vol.m new file mode 100644 index 0000000..6830ef6 --- /dev/null +++ b/external/fieldtrip/inverse/private/find_inside_vol.m @@ -0,0 +1,35 @@ +function [inside, outside] = find_inside_vol(pos, vol); + +% FIND_INSIDE_VOL locates dipole locations inside/outside the source +% compartment of a volume conductor model. +% +% [inside, outside] = find_inside_vol(pos, vol) +% +% This function is obsolete and its use in other functions should be replaced +% by inside_vol + +% Copyright (C) 2003-2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: find_inside_vol.m 1074 2010-05-17 07:52:16Z roboos $ + + +inside = ft_inside_vol(pos, vol); +% replace boolean vector with indexing vectors +outside = find(~inside); +inside = find(inside); diff --git a/external/fieldtrip/inverse/private/fixdipole.m b/external/fieldtrip/inverse/private/fixdipole.m new file mode 100644 index 0000000..363fd34 --- /dev/null +++ b/external/fieldtrip/inverse/private/fixdipole.m @@ -0,0 +1,52 @@ +function dip = fixdipole(dip) + +% FIXDIPOLE ensures that the dipole position and moment are +% consistently represented throughout FieldTrip functions. + +% Copyright (C) 2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: fixdipole.m 946 2010-04-21 17:51:16Z roboos $ + +[m, n] = size(dip.pos); + +if n==3 + % the input representation is Nx3, which is what we want +elseif m==3 + % it is possible to translate it into a Nx3 unambiguously + warning('input dipole positions should be specified as Nx3 matrix'); + dip.pos = dip.pos'; +elseif m==1 + % it is possible to translate it into a Nx3 unambiguously + warning('input dipole positions should be specified as Nx3 matrix'); + dip.pos = reshape(dip.pos, 3, n/3)'; +else + % it is not clear how to convert to a Nx3 matrix + error('input dipole positions should be specified as Nx3 matrix'); +end + +if isfield(dip, 'mom') + ndip = size(dip.pos,1); + if numel(dip.mom)==ndip*3 + ntime = 1; + else + ntime = numel(dip.mom)/(ndip*3); + end + dip.mom = reshape(dip.mom, ndip*3, ntime); +end + diff --git a/external/fieldtrip/inverse/private/ft_inside_vol.m b/external/fieldtrip/inverse/private/ft_inside_vol.m new file mode 100644 index 0000000..deefaa5 --- /dev/null +++ b/external/fieldtrip/inverse/private/ft_inside_vol.m @@ -0,0 +1,110 @@ +function [inside] = ft_inside_vol(pos, vol) + +% FT_INSIDE_VOL locates dipole locations inside/outside the source +% compartment of a volume conductor model. +% +% [inside] = ft_inside_vol(pos, vol, ...) +% +% where the input should be +% pos Nx3 matrix with dipole positions +% vol structure with volume conductor model +% and the output is +% inside list of dipoles inside the brain compartment +% (1=inside, 0=outisde) +% +% Additional optional input arguments shoudl be given in key value pairs +% and can include +% + +% Copyright (C) 2003-2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_inside_vol.m 946 2010-04-21 17:51:16Z roboos $ + +% determine the type of volume conduction model +switch ft_voltype(vol) + + % single-sphere or multiple concentric spheres + case {'singlesphere' 'concentric'} + if ~isfield(vol, 'source') + % locate the innermost compartment and remember it + [dum, vol.source] = min(vol.r); + end + if isfield(vol, 'o') + % shift dipole positions toward origin of sphere + tmp = pos - repmat(vol.o, size(pos,1), 1); + else + tmp = pos; + end + distance = sqrt(sum(tmp.^2, 2))-vol.r(vol.source); + % positive if outside, negative if inside + inside = distance<0; + + % multi-sphere volume conductor model + case 'multisphere' + + % nspheres = size(vol.r,1); + % ndipoles = size(pos,1); + % inside = zeros(ndipoles,1); + % for sph=1:nspheres + % for dip=1:ndipoles + % if inside(dip) + % % the dipole has already been detected in one of the other spheres + % continue + % end + % inside(dip) = (norm(pos(dip,:) - vol.o(sph,:)) <= vol.r(sph)); + % end + % end + % outside = find(inside==0); + % inside = find(inside==1); + + % this is a much faster implementation + nspheres = size(vol.r,1); + ndipoles = size(pos,1); + inside = zeros(ndipoles,1); + for sph=1:nspheres + % temporary shift dipole positions toward origin + if isfield(vol, 'o') + tmp = pos - repmat(vol.o(sph,:), [ndipoles 1]); + else + tmp = pos; + end + flag = (sqrt(sum(tmp.^2,2)) <= vol.r(sph)); + inside = inside + flag; + end + inside = inside>0; + + % realistic BEM volume conductor model + case {'bem', 'dipoli', 'bemcp', 'asa', 'avo', 'nolte', 'neuromag'} + if ~isfield(vol, 'source') + % locate the innermost compartment and remember it + vol.source = find_innermost_boundary(vol.bnd); + end + % use the specified source compartment + pnt = vol.bnd(vol.source).pnt; + tri = vol.bnd(vol.source).tri; + % determine the dipole positions that are inside the brain compartment + inside = bounding_mesh(pos, pnt, tri); + + % unrecognized volume conductor model + otherwise + error('unrecognized volume conductor model'); +end + +% ensure that these are column vectors +inside = logical(inside(:)); diff --git a/external/fieldtrip/inverse/private/ft_senslabel.m b/external/fieldtrip/inverse/private/ft_senslabel.m new file mode 100644 index 0000000..4242fb1 --- /dev/null +++ b/external/fieldtrip/inverse/private/ft_senslabel.m @@ -0,0 +1,2808 @@ +function label = ft_senslabel(type) + +% FT_SENSLABEL returns a list of sensor labels given the MEEG system type +% +% Use as +% label = ft_senslabel(type) +% +% The input type can be any of the following +% 'biosemi64' +% 'biosemi128' +% 'biosemi256' +% 'bti148' +% 'bti148_planar' +% 'bti248' +% 'bti248_planar' +% 'btiref' +% 'ctf151' +% 'ctf151_planar' +% 'ctf275' +% 'ctf275_planar' +% 'ctfheadloc' +% 'ctfref' +% 'eeg1005' +% 'eeg1010' +% 'eeg1020' +% 'egi128' +% 'egi256' +% 'egi32' +% 'egi64' +% 'ext1020' +% 'neuromag122' +% 'neuromag122alt' +% 'neuromag306' +% 'neuromag306alt' +% 'itab153' +% 'itab153_planar' +% 'yokogawa160' +% 'yokogawa160_planar' +% 'electrode' +% +% See also FT_SENSTYPE, FT_CHANNELSELECTION + +% FIXME one channel is missing for ctf275 + +% Copyright (C) 2007-2008, Robert Oostenveld +% Copyright (C) 2008, Vladimir Litvak +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_senslabel.m 1006 2010-05-03 08:36:13Z roboos $ + +% these are for remembering the type on subsequent calls with the same input arguments +persistent previous_argin previous_argout + +if nargin<1 + % ensure that all input arguments are defined + type = []; +end + +current_argin = {type}; +if isequal(current_argin, previous_argin) + % don't do the type detection again, but return the previous values from cache + label = previous_argout{1}; + return +end + +switch type + + case 'btiref' + label = { + 'MRxA' + 'MRyA' + 'MRzA' + 'MLxA' + 'MLyA' + 'MLzA' + 'MCxA' + 'MCyA' + 'MCzA' + 'MRxaA' + 'MRyaA' + 'MRzaA' + 'MLxaA' + 'MLyaA' + 'MLzaA' + 'MCxaA' + 'MCyaA' + 'MCzaA' + 'GxxA' + 'GyxA' + 'GzxA' + 'GyyA' + 'GzyA' + }; + + case 'bti148' + label = cell(148,1); + for i=1:148 + label{i,1} = sprintf('A%d', i); + end + + case 'bti148_planar' + label = cell(148,2); + for i=1:148 + label{i,1} = sprintf('A%d_dH', i); + label{i,2} = sprintf('A%d_dV', i); + end + + case 'bti248' + label = cell(248,1); + for i=1:248 + label{i,1} = sprintf('A%d', i); + end + + case 'bti248_planar' + label = cell(248,2); + for i=1:248 + label{i,1} = sprintf('A%d_dH', i); + label{i,2} = sprintf('A%d_dV', i); + end + + case 'ctfref' + label = { + 'BG1' + 'BG2' + 'BG3' + 'BP1' + 'BP2' + 'BP3' + 'BR1' + 'BR2' + 'BR3' + 'G11' + 'G12' + 'G13' + 'G22' + 'G23' + 'P11' + 'P12' + 'P13' + 'P22' + 'P23' + 'Q11' + 'Q12' + 'Q13' + 'Q22' + 'Q23' + 'R11' + 'R12' + 'R13' + 'R22' + 'R23' + }; + + case 'ctfheadloc' + label = { + 'HLC0011' + 'HLC0012' + 'HLC0013' + 'HLC0021' + 'HLC0022' + 'HLC0023' + 'HLC0031' + 'HLC0032' + 'HLC0033' + 'HLC0018' + 'HLC0028' + 'HLC0038' + 'HLC0014' + 'HLC0015' + 'HLC0016' + 'HLC0017' + 'HLC0024' + 'HLC0025' + 'HLC0026' + 'HLC0027' + 'HLC0034' + 'HLC0035' + 'HLC0036' + 'HLC0037' + }; + + case 'ctf64' + label = { + 'SL11' + 'SL12' + 'SL13' + 'SL14' + 'SL15' + 'SL16' + 'SL17' + 'SL18' + 'SL19' + 'SL21' + 'SL22' + 'SL23' + 'SL24' + 'SL25' + 'SL26' + 'SL27' + 'SL28' + 'SL29' + 'SL31' + 'SL32' + 'SL33' + 'SL34' + 'SL35' + 'SL41' + 'SL42' + 'SL43' + 'SL44' + 'SL45' + 'SL46' + 'SL47' + 'SL51' + 'SL52' + 'SR11' + 'SR12' + 'SR13' + 'SR14' + 'SR15' + 'SR16' + 'SR17' + 'SR18' + 'SR19' + 'SR21' + 'SR22' + 'SR23' + 'SR24' + 'SR25' + 'SR26' + 'SR27' + 'SR28' + 'SR29' + 'SR31' + 'SR32' + 'SR33' + 'SR34' + 'SR35' + 'SR41' + 'SR42' + 'SR43' + 'SR44' + 'SR45' + 'SR46' + 'SR47' + 'SR51' + 'SR52' + }; + + case 'ctf151' + label = { + 'MLC11' + 'MLC12' + 'MLC13' + 'MLC14' + 'MLC15' + 'MLC21' + 'MLC22' + 'MLC23' + 'MLC24' + 'MLC31' + 'MLC32' + 'MLC33' + 'MLC41' + 'MLC42' + 'MLC43' + 'MLF11' + 'MLF12' + 'MLF21' + 'MLF22' + 'MLF23' + 'MLF31' + 'MLF32' + 'MLF33' + 'MLF34' + 'MLF41' + 'MLF42' + 'MLF43' + 'MLF44' + 'MLF45' + 'MLF51' + 'MLF52' + 'MLO11' + 'MLO12' + 'MLO21' + 'MLO22' + 'MLO31' + 'MLO32' + 'MLO33' + 'MLO41' + 'MLO42' + 'MLO43' + 'MLP11' + 'MLP12' + 'MLP13' + 'MLP21' + 'MLP22' + 'MLP31' + 'MLP32' + 'MLP33' + 'MLP34' + 'MLT11' + 'MLT12' + 'MLT13' + 'MLT14' + 'MLT15' + 'MLT16' + 'MLT21' + 'MLT22' + 'MLT23' + 'MLT24' + 'MLT25' + 'MLT26' + 'MLT31' + 'MLT32' + 'MLT33' + 'MLT34' + 'MLT35' + 'MLT41' + 'MLT42' + 'MLT43' + 'MLT44' + 'MRC11' + 'MRC12' + 'MRC13' + 'MRC14' + 'MRC15' + 'MRC21' + 'MRC22' + 'MRC23' + 'MRC24' + 'MRC31' + 'MRC32' + 'MRC33' + 'MRC41' + 'MRC42' + 'MRC43' + 'MRF11' + 'MRF12' + 'MRF21' + 'MRF22' + 'MRF23' + 'MRF31' + 'MRF32' + 'MRF33' + 'MRF34' + 'MRF41' + 'MRF42' + 'MRF43' + 'MRF44' + 'MRF45' + 'MRF51' + 'MRF52' + 'MRO11' + 'MRO12' + 'MRO21' + 'MRO22' + 'MRO31' + 'MRO32' + 'MRO33' + 'MRO41' + 'MRO42' + 'MRO43' + 'MRP11' + 'MRP12' + 'MRP13' + 'MRP21' + 'MRP22' + 'MRP31' + 'MRP32' + 'MRP33' + 'MRP34' + 'MRT11' + 'MRT12' + 'MRT13' + 'MRT14' + 'MRT15' + 'MRT16' + 'MRT21' + 'MRT22' + 'MRT23' + 'MRT24' + 'MRT25' + 'MRT26' + 'MRT31' + 'MRT32' + 'MRT33' + 'MRT34' + 'MRT35' + 'MRT41' + 'MRT42' + 'MRT43' + 'MRT44' + 'MZC01' + 'MZC02' + 'MZF01' + 'MZF02' + 'MZF03' + 'MZO01' + 'MZO02' + 'MZP01' + 'MZP02' + }; + + case 'ctf151_planar' + label = { + 'MLC11_dH' 'MLC11_dV' + 'MLC12_dH' 'MLC12_dV' + 'MLC13_dH' 'MLC13_dV' + 'MLC14_dH' 'MLC14_dV' + 'MLC15_dH' 'MLC15_dV' + 'MLC21_dH' 'MLC21_dV' + 'MLC22_dH' 'MLC22_dV' + 'MLC23_dH' 'MLC23_dV' + 'MLC24_dH' 'MLC24_dV' + 'MLC31_dH' 'MLC31_dV' + 'MLC32_dH' 'MLC32_dV' + 'MLC33_dH' 'MLC33_dV' + 'MLC41_dH' 'MLC41_dV' + 'MLC42_dH' 'MLC42_dV' + 'MLC43_dH' 'MLC43_dV' + 'MLF11_dH' 'MLF11_dV' + 'MLF12_dH' 'MLF12_dV' + 'MLF21_dH' 'MLF21_dV' + 'MLF22_dH' 'MLF22_dV' + 'MLF23_dH' 'MLF23_dV' + 'MLF31_dH' 'MLF31_dV' + 'MLF32_dH' 'MLF32_dV' + 'MLF33_dH' 'MLF33_dV' + 'MLF34_dH' 'MLF34_dV' + 'MLF41_dH' 'MLF41_dV' + 'MLF42_dH' 'MLF42_dV' + 'MLF43_dH' 'MLF43_dV' + 'MLF44_dH' 'MLF44_dV' + 'MLF45_dH' 'MLF45_dV' + 'MLF51_dH' 'MLF51_dV' + 'MLF52_dH' 'MLF52_dV' + 'MLO11_dH' 'MLO11_dV' + 'MLO12_dH' 'MLO12_dV' + 'MLO21_dH' 'MLO21_dV' + 'MLO22_dH' 'MLO22_dV' + 'MLO31_dH' 'MLO31_dV' + 'MLO32_dH' 'MLO32_dV' + 'MLO33_dH' 'MLO33_dV' + 'MLO41_dH' 'MLO41_dV' + 'MLO42_dH' 'MLO42_dV' + 'MLO43_dH' 'MLO43_dV' + 'MLP11_dH' 'MLP11_dV' + 'MLP12_dH' 'MLP12_dV' + 'MLP13_dH' 'MLP13_dV' + 'MLP21_dH' 'MLP21_dV' + 'MLP22_dH' 'MLP22_dV' + 'MLP31_dH' 'MLP31_dV' + 'MLP32_dH' 'MLP32_dV' + 'MLP33_dH' 'MLP33_dV' + 'MLP34_dH' 'MLP34_dV' + 'MLT11_dH' 'MLT11_dV' + 'MLT12_dH' 'MLT12_dV' + 'MLT13_dH' 'MLT13_dV' + 'MLT14_dH' 'MLT14_dV' + 'MLT15_dH' 'MLT15_dV' + 'MLT16_dH' 'MLT16_dV' + 'MLT21_dH' 'MLT21_dV' + 'MLT22_dH' 'MLT22_dV' + 'MLT23_dH' 'MLT23_dV' + 'MLT24_dH' 'MLT24_dV' + 'MLT25_dH' 'MLT25_dV' + 'MLT26_dH' 'MLT26_dV' + 'MLT31_dH' 'MLT31_dV' + 'MLT32_dH' 'MLT32_dV' + 'MLT33_dH' 'MLT33_dV' + 'MLT34_dH' 'MLT34_dV' + 'MLT35_dH' 'MLT35_dV' + 'MLT41_dH' 'MLT41_dV' + 'MLT42_dH' 'MLT42_dV' + 'MLT43_dH' 'MLT43_dV' + 'MLT44_dH' 'MLT44_dV' + 'MRC11_dH' 'MRC11_dV' + 'MRC12_dH' 'MRC12_dV' + 'MRC13_dH' 'MRC13_dV' + 'MRC14_dH' 'MRC14_dV' + 'MRC15_dH' 'MRC15_dV' + 'MRC21_dH' 'MRC21_dV' + 'MRC22_dH' 'MRC22_dV' + 'MRC23_dH' 'MRC23_dV' + 'MRC24_dH' 'MRC24_dV' + 'MRC31_dH' 'MRC31_dV' + 'MRC32_dH' 'MRC32_dV' + 'MRC33_dH' 'MRC33_dV' + 'MRC41_dH' 'MRC41_dV' + 'MRC42_dH' 'MRC42_dV' + 'MRC43_dH' 'MRC43_dV' + 'MRF11_dH' 'MRF11_dV' + 'MRF12_dH' 'MRF12_dV' + 'MRF21_dH' 'MRF21_dV' + 'MRF22_dH' 'MRF22_dV' + 'MRF23_dH' 'MRF23_dV' + 'MRF31_dH' 'MRF31_dV' + 'MRF32_dH' 'MRF32_dV' + 'MRF33_dH' 'MRF33_dV' + 'MRF34_dH' 'MRF34_dV' + 'MRF41_dH' 'MRF41_dV' + 'MRF42_dH' 'MRF42_dV' + 'MRF43_dH' 'MRF43_dV' + 'MRF44_dH' 'MRF44_dV' + 'MRF45_dH' 'MRF45_dV' + 'MRF51_dH' 'MRF51_dV' + 'MRF52_dH' 'MRF52_dV' + 'MRO11_dH' 'MRO11_dV' + 'MRO12_dH' 'MRO12_dV' + 'MRO21_dH' 'MRO21_dV' + 'MRO22_dH' 'MRO22_dV' + 'MRO31_dH' 'MRO31_dV' + 'MRO32_dH' 'MRO32_dV' + 'MRO33_dH' 'MRO33_dV' + 'MRO41_dH' 'MRO41_dV' + 'MRO42_dH' 'MRO42_dV' + 'MRO43_dH' 'MRO43_dV' + 'MRP11_dH' 'MRP11_dV' + 'MRP12_dH' 'MRP12_dV' + 'MRP13_dH' 'MRP13_dV' + 'MRP21_dH' 'MRP21_dV' + 'MRP22_dH' 'MRP22_dV' + 'MRP31_dH' 'MRP31_dV' + 'MRP32_dH' 'MRP32_dV' + 'MRP33_dH' 'MRP33_dV' + 'MRP34_dH' 'MRP34_dV' + 'MRT11_dH' 'MRT11_dV' + 'MRT12_dH' 'MRT12_dV' + 'MRT13_dH' 'MRT13_dV' + 'MRT14_dH' 'MRT14_dV' + 'MRT15_dH' 'MRT15_dV' + 'MRT16_dH' 'MRT16_dV' + 'MRT21_dH' 'MRT21_dV' + 'MRT22_dH' 'MRT22_dV' + 'MRT23_dH' 'MRT23_dV' + 'MRT24_dH' 'MRT24_dV' + 'MRT25_dH' 'MRT25_dV' + 'MRT26_dH' 'MRT26_dV' + 'MRT31_dH' 'MRT31_dV' + 'MRT32_dH' 'MRT32_dV' + 'MRT33_dH' 'MRT33_dV' + 'MRT34_dH' 'MRT34_dV' + 'MRT35_dH' 'MRT35_dV' + 'MRT41_dH' 'MRT41_dV' + 'MRT42_dH' 'MRT42_dV' + 'MRT43_dH' 'MRT43_dV' + 'MRT44_dH' 'MRT44_dV' + 'MZC01_dH' 'MZC01_dV' + 'MZC02_dH' 'MZC02_dV' + 'MZF01_dH' 'MZF01_dV' + 'MZF02_dH' 'MZF02_dV' + 'MZF03_dH' 'MZF03_dV' + 'MZO01_dH' 'MZO01_dV' + 'MZO02_dH' 'MZO02_dV' + 'MZP01_dH' 'MZP01_dV' + 'MZP02_dH' 'MZP02_dV' + }; + + case 'ctf275' + label = { + 'MLC11' + 'MLC12' + 'MLC13' + 'MLC14' + 'MLC15' + 'MLC16' + 'MLC17' + 'MLC21' + 'MLC22' + 'MLC23' + 'MLC24' + 'MLC25' + 'MLC31' + 'MLC32' + 'MLC41' + 'MLC42' + 'MLC51' + 'MLC52' + 'MLC53' + 'MLC54' + 'MLC55' + 'MLC61' + 'MLC62' + 'MLC63' + 'MLF11' + 'MLF12' + 'MLF13' + 'MLF14' + 'MLF21' + 'MLF22' + 'MLF23' + 'MLF24' + 'MLF25' + 'MLF31' + 'MLF32' + 'MLF33' + 'MLF34' + 'MLF35' + 'MLF41' + 'MLF42' + 'MLF43' + 'MLF44' + 'MLF45' + 'MLF46' + 'MLF51' + 'MLF52' + 'MLF53' + 'MLF54' + 'MLF55' + 'MLF56' + 'MLF61' + 'MLF62' + 'MLF63' + 'MLF64' + 'MLF65' + 'MLF66' + 'MLF67' + 'MLO11' + 'MLO12' + 'MLO13' + 'MLO14' + 'MLO21' + 'MLO22' + 'MLO23' + 'MLO24' + 'MLO31' + 'MLO32' + 'MLO33' + 'MLO34' + 'MLO41' + 'MLO42' + 'MLO43' + 'MLO44' + 'MLO51' + 'MLO52' + 'MLO53' + 'MLP11' + 'MLP12' + 'MLP21' + 'MLP22' + 'MLP23' + 'MLP31' + 'MLP32' + 'MLP33' + 'MLP34' + 'MLP35' + 'MLP41' + 'MLP42' + 'MLP43' + 'MLP44' + 'MLP45' + 'MLP51' + 'MLP52' + 'MLP53' + 'MLP54' + 'MLP55' + 'MLP56' + 'MLP57' + 'MLT11' + 'MLT12' + 'MLT13' + 'MLT14' + 'MLT15' + 'MLT16' + 'MLT21' + 'MLT22' + 'MLT23' + 'MLT24' + 'MLT25' + 'MLT26' + 'MLT27' + 'MLT31' + 'MLT32' + 'MLT33' + 'MLT34' + 'MLT35' + 'MLT36' + 'MLT37' + 'MLT41' + 'MLT42' + 'MLT43' + 'MLT44' + 'MLT45' + 'MLT46' + 'MLT47' + 'MLT51' + 'MLT52' + 'MLT53' + 'MLT54' + 'MLT55' + 'MLT56' + 'MLT57' + 'MRC11' + 'MRC12' + 'MRC13' + 'MRC14' + 'MRC15' + 'MRC16' + 'MRC17' + 'MRC21' + 'MRC22' + 'MRC23' + 'MRC24' + 'MRC25' + 'MRC31' + 'MRC32' + 'MRC41' + 'MRC42' + 'MRC51' + 'MRC52' + 'MRC53' + 'MRC54' + 'MRC55' + 'MRC61' + 'MRC62' + 'MRC63' + 'MRF11' + 'MRF12' + 'MRF13' + 'MRF14' + 'MRF21' + 'MRF22' + 'MRF23' + 'MRF24' + 'MRF25' + 'MRF31' + 'MRF32' + 'MRF33' + 'MRF34' + 'MRF35' + 'MRF41' + 'MRF42' + 'MRF43' + 'MRF44' + 'MRF45' + 'MRF46' + 'MRF51' + 'MRF52' + 'MRF53' + 'MRF54' + 'MRF55' + 'MRF56' + 'MRF61' + 'MRF62' + 'MRF63' + 'MRF64' + 'MRF65' + 'MRF66' + 'MRF67' + 'MRO11' + 'MRO12' + 'MRO13' + 'MRO14' + 'MRO21' + 'MRO22' + 'MRO23' + 'MRO24' + 'MRO31' + 'MRO32' + 'MRO33' + 'MRO34' + 'MRO41' + 'MRO42' + 'MRO43' + 'MRO44' + 'MRO51' + 'MRO52' + 'MRO53' + 'MRP11' + 'MRP12' + 'MRP21' + 'MRP22' + 'MRP23' + 'MRP32' + 'MRP33' + 'MRP34' + 'MRP35' + 'MRP41' + 'MRP42' + 'MRP43' + 'MRP44' + 'MRP45' + 'MRP51' + 'MRP52' + 'MRP53' + 'MRP54' + 'MRP55' + 'MRP56' + 'MRP57' + 'MRT11' + 'MRT12' + 'MRT13' + 'MRT14' + 'MRT15' + 'MRT16' + 'MRT21' + 'MRT22' + 'MRT23' + 'MRT24' + 'MRT25' + 'MRT26' + 'MRT27' + 'MRT31' + 'MRT32' + 'MRT33' + 'MRT34' + 'MRT35' + 'MRT36' + 'MRT37' + 'MRT41' + 'MRT42' + 'MRT43' + 'MRT44' + 'MRT45' + 'MRT46' + 'MRT47' + 'MRT51' + 'MRT52' + 'MRT53' + 'MRT54' + 'MRT55' + 'MRT56' + 'MRT57' + 'MZC01' + 'MZC02' + 'MZC03' + 'MZC04' + 'MZF01' + 'MZF02' + 'MZF03' + 'MZO01' + 'MZO02' + 'MZO03' + 'MZP01' + }; + + case 'ctf275_planar' + % FIXME one channel seems to be missing + label = { + 'MLC11_dH' 'MLC11_dV' + 'MLC12_dH' 'MLC12_dV' + 'MLC13_dH' 'MLC13_dV' + 'MLC14_dH' 'MLC14_dV' + 'MLC15_dH' 'MLC15_dV' + 'MLC16_dH' 'MLC16_dV' + 'MLC17_dH' 'MLC17_dV' + 'MLC21_dH' 'MLC21_dV' + 'MLC22_dH' 'MLC22_dV' + 'MLC23_dH' 'MLC23_dV' + 'MLC24_dH' 'MLC24_dV' + 'MLC25_dH' 'MLC25_dV' + 'MLC31_dH' 'MLC31_dV' + 'MLC32_dH' 'MLC32_dV' + 'MLC41_dH' 'MLC41_dV' + 'MLC42_dH' 'MLC42_dV' + 'MLC51_dH' 'MLC51_dV' + 'MLC52_dH' 'MLC52_dV' + 'MLC53_dH' 'MLC53_dV' + 'MLC54_dH' 'MLC54_dV' + 'MLC55_dH' 'MLC55_dV' + 'MLC61_dH' 'MLC61_dV' + 'MLC62_dH' 'MLC62_dV' + 'MLC63_dH' 'MLC63_dV' + 'MLF11_dH' 'MLF11_dV' + 'MLF12_dH' 'MLF12_dV' + 'MLF13_dH' 'MLF13_dV' + 'MLF14_dH' 'MLF14_dV' + 'MLF21_dH' 'MLF21_dV' + 'MLF22_dH' 'MLF22_dV' + 'MLF23_dH' 'MLF23_dV' + 'MLF24_dH' 'MLF24_dV' + 'MLF25_dH' 'MLF25_dV' + 'MLF31_dH' 'MLF31_dV' + 'MLF32_dH' 'MLF32_dV' + 'MLF33_dH' 'MLF33_dV' + 'MLF34_dH' 'MLF34_dV' + 'MLF35_dH' 'MLF35_dV' + 'MLF41_dH' 'MLF41_dV' + 'MLF42_dH' 'MLF42_dV' + 'MLF43_dH' 'MLF43_dV' + 'MLF44_dH' 'MLF44_dV' + 'MLF45_dH' 'MLF45_dV' + 'MLF46_dH' 'MLF46_dV' + 'MLF51_dH' 'MLF51_dV' + 'MLF52_dH' 'MLF52_dV' + 'MLF53_dH' 'MLF53_dV' + 'MLF54_dH' 'MLF54_dV' + 'MLF55_dH' 'MLF55_dV' + 'MLF56_dH' 'MLF56_dV' + 'MLF61_dH' 'MLF61_dV' + 'MLF62_dH' 'MLF62_dV' + 'MLF63_dH' 'MLF63_dV' + 'MLF64_dH' 'MLF64_dV' + 'MLF65_dH' 'MLF65_dV' + 'MLF66_dH' 'MLF66_dV' + 'MLF67_dH' 'MLF67_dV' + 'MLO11_dH' 'MLO11_dV' + 'MLO12_dH' 'MLO12_dV' + 'MLO13_dH' 'MLO13_dV' + 'MLO14_dH' 'MLO14_dV' + 'MLO21_dH' 'MLO21_dV' + 'MLO22_dH' 'MLO22_dV' + 'MLO23_dH' 'MLO23_dV' + 'MLO24_dH' 'MLO24_dV' + 'MLO31_dH' 'MLO31_dV' + 'MLO32_dH' 'MLO32_dV' + 'MLO33_dH' 'MLO33_dV' + 'MLO34_dH' 'MLO34_dV' + 'MLO41_dH' 'MLO41_dV' + 'MLO42_dH' 'MLO42_dV' + 'MLO43_dH' 'MLO43_dV' + 'MLO44_dH' 'MLO44_dV' + 'MLO51_dH' 'MLO51_dV' + 'MLO52_dH' 'MLO52_dV' + 'MLO53_dH' 'MLO53_dV' + 'MLP11_dH' 'MLP11_dV' + 'MLP12_dH' 'MLP12_dV' + 'MLP21_dH' 'MLP21_dV' + 'MLP22_dH' 'MLP22_dV' + 'MLP23_dH' 'MLP23_dV' + 'MLP31_dH' 'MLP31_dV' + 'MLP32_dH' 'MLP32_dV' + 'MLP33_dH' 'MLP33_dV' + 'MLP34_dH' 'MLP34_dV' + 'MLP35_dH' 'MLP35_dV' + 'MLP41_dH' 'MLP41_dV' + 'MLP42_dH' 'MLP42_dV' + 'MLP43_dH' 'MLP43_dV' + 'MLP44_dH' 'MLP44_dV' + 'MLP45_dH' 'MLP45_dV' + 'MLP51_dH' 'MLP51_dV' + 'MLP52_dH' 'MLP52_dV' + 'MLP53_dH' 'MLP53_dV' + 'MLP54_dH' 'MLP54_dV' + 'MLP55_dH' 'MLP55_dV' + 'MLP56_dH' 'MLP56_dV' + 'MLP57_dH' 'MLP57_dV' + 'MLT11_dH' 'MLT11_dV' + 'MLT12_dH' 'MLT12_dV' + 'MLT13_dH' 'MLT13_dV' + 'MLT14_dH' 'MLT14_dV' + 'MLT15_dH' 'MLT15_dV' + 'MLT16_dH' 'MLT16_dV' + 'MLT21_dH' 'MLT21_dV' + 'MLT22_dH' 'MLT22_dV' + 'MLT23_dH' 'MLT23_dV' + 'MLT24_dH' 'MLT24_dV' + 'MLT25_dH' 'MLT25_dV' + 'MLT26_dH' 'MLT26_dV' + 'MLT27_dH' 'MLT27_dV' + 'MLT31_dH' 'MLT31_dV' + 'MLT32_dH' 'MLT32_dV' + 'MLT33_dH' 'MLT33_dV' + 'MLT34_dH' 'MLT34_dV' + 'MLT35_dH' 'MLT35_dV' + 'MLT36_dH' 'MLT36_dV' + 'MLT37_dH' 'MLT37_dV' + 'MLT41_dH' 'MLT41_dV' + 'MLT42_dH' 'MLT42_dV' + 'MLT43_dH' 'MLT43_dV' + 'MLT44_dH' 'MLT44_dV' + 'MLT45_dH' 'MLT45_dV' + 'MLT46_dH' 'MLT46_dV' + 'MLT47_dH' 'MLT47_dV' + 'MLT51_dH' 'MLT51_dV' + 'MLT52_dH' 'MLT52_dV' + 'MLT53_dH' 'MLT53_dV' + 'MLT54_dH' 'MLT54_dV' + 'MLT55_dH' 'MLT55_dV' + 'MLT56_dH' 'MLT56_dV' + 'MLT57_dH' 'MLT57_dV' + 'MRC11_dH' 'MRC11_dV' + 'MRC12_dH' 'MRC12_dV' + 'MRC13_dH' 'MRC13_dV' + 'MRC14_dH' 'MRC14_dV' + 'MRC15_dH' 'MRC15_dV' + 'MRC16_dH' 'MRC16_dV' + 'MRC17_dH' 'MRC17_dV' + 'MRC21_dH' 'MRC21_dV' + 'MRC22_dH' 'MRC22_dV' + 'MRC23_dH' 'MRC23_dV' + 'MRC24_dH' 'MRC24_dV' + 'MRC25_dH' 'MRC25_dV' + 'MRC31_dH' 'MRC31_dV' + 'MRC32_dH' 'MRC32_dV' + 'MRC41_dH' 'MRC41_dV' + 'MRC42_dH' 'MRC42_dV' + 'MRC51_dH' 'MRC51_dV' + 'MRC52_dH' 'MRC52_dV' + 'MRC53_dH' 'MRC53_dV' + 'MRC54_dH' 'MRC54_dV' + 'MRC55_dH' 'MRC55_dV' + 'MRC61_dH' 'MRC61_dV' + 'MRC62_dH' 'MRC62_dV' + 'MRC63_dH' 'MRC63_dV' + 'MRF11_dH' 'MRF11_dV' + 'MRF12_dH' 'MRF12_dV' + 'MRF13_dH' 'MRF13_dV' + 'MRF14_dH' 'MRF14_dV' + 'MRF21_dH' 'MRF21_dV' + 'MRF22_dH' 'MRF22_dV' + 'MRF23_dH' 'MRF23_dV' + 'MRF24_dH' 'MRF24_dV' + 'MRF25_dH' 'MRF25_dV' + 'MRF31_dH' 'MRF31_dV' + 'MRF32_dH' 'MRF32_dV' + 'MRF33_dH' 'MRF33_dV' + 'MRF34_dH' 'MRF34_dV' + 'MRF35_dH' 'MRF35_dV' + 'MRF41_dH' 'MRF41_dV' + 'MRF42_dH' 'MRF42_dV' + 'MRF43_dH' 'MRF43_dV' + 'MRF44_dH' 'MRF44_dV' + 'MRF45_dH' 'MRF45_dV' + 'MRF46_dH' 'MRF46_dV' + 'MRF51_dH' 'MRF51_dV' + 'MRF52_dH' 'MRF52_dV' + 'MRF53_dH' 'MRF53_dV' + 'MRF54_dH' 'MRF54_dV' + 'MRF55_dH' 'MRF55_dV' + 'MRF56_dH' 'MRF56_dV' + 'MRF61_dH' 'MRF61_dV' + 'MRF62_dH' 'MRF62_dV' + 'MRF63_dH' 'MRF63_dV' + 'MRF64_dH' 'MRF64_dV' + 'MRF65_dH' 'MRF65_dV' + 'MRF66_dH' 'MRF66_dV' + 'MRF67_dH' 'MRF67_dV' + 'MRO11_dH' 'MRO11_dV' + 'MRO12_dH' 'MRO12_dV' + 'MRO13_dH' 'MRO13_dV' + 'MRO14_dH' 'MRO14_dV' + 'MRO21_dH' 'MRO21_dV' + 'MRO22_dH' 'MRO22_dV' + 'MRO23_dH' 'MRO23_dV' + 'MRO24_dH' 'MRO24_dV' + 'MRO31_dH' 'MRO31_dV' + 'MRO32_dH' 'MRO32_dV' + 'MRO33_dH' 'MRO33_dV' + 'MRO34_dH' 'MRO34_dV' + 'MRO41_dH' 'MRO41_dV' + 'MRO42_dH' 'MRO42_dV' + 'MRO43_dH' 'MRO43_dV' + 'MRO44_dH' 'MRO44_dV' + 'MRO51_dH' 'MRO51_dV' + 'MRO52_dH' 'MRO52_dV' + 'MRO53_dH' 'MRO53_dV' + 'MRP11_dH' 'MRP11_dV' + 'MRP12_dH' 'MRP12_dV' + 'MRP21_dH' 'MRP21_dV' + 'MRP22_dH' 'MRP22_dV' + 'MRP23_dH' 'MRP23_dV' + 'MRP32_dH' 'MRP32_dV' + 'MRP33_dH' 'MRP33_dV' + 'MRP34_dH' 'MRP34_dV' + 'MRP35_dH' 'MRP35_dV' + 'MRP41_dH' 'MRP41_dV' + 'MRP42_dH' 'MRP42_dV' + 'MRP43_dH' 'MRP43_dV' + 'MRP44_dH' 'MRP44_dV' + 'MRP45_dH' 'MRP45_dV' + 'MRP51_dH' 'MRP51_dV' + 'MRP52_dH' 'MRP52_dV' + 'MRP53_dH' 'MRP53_dV' + 'MRP54_dH' 'MRP54_dV' + 'MRP55_dH' 'MRP55_dV' + 'MRP56_dH' 'MRP56_dV' + 'MRP57_dH' 'MRP57_dV' + 'MRT11_dH' 'MRT11_dV' + 'MRT12_dH' 'MRT12_dV' + 'MRT13_dH' 'MRT13_dV' + 'MRT14_dH' 'MRT14_dV' + 'MRT15_dH' 'MRT15_dV' + 'MRT16_dH' 'MRT16_dV' + 'MRT21_dH' 'MRT21_dV' + 'MRT22_dH' 'MRT22_dV' + 'MRT23_dH' 'MRT23_dV' + 'MRT24_dH' 'MRT24_dV' + 'MRT25_dH' 'MRT25_dV' + 'MRT26_dH' 'MRT26_dV' + 'MRT27_dH' 'MRT27_dV' + 'MRT31_dH' 'MRT31_dV' + 'MRT32_dH' 'MRT32_dV' + 'MRT33_dH' 'MRT33_dV' + 'MRT34_dH' 'MRT34_dV' + 'MRT35_dH' 'MRT35_dV' + 'MRT36_dH' 'MRT36_dV' + 'MRT37_dH' 'MRT37_dV' + 'MRT41_dH' 'MRT41_dV' + 'MRT42_dH' 'MRT42_dV' + 'MRT43_dH' 'MRT43_dV' + 'MRT44_dH' 'MRT44_dV' + 'MRT45_dH' 'MRT45_dV' + 'MRT46_dH' 'MRT46_dV' + 'MRT47_dH' 'MRT47_dV' + 'MRT51_dH' 'MRT51_dV' + 'MRT52_dH' 'MRT52_dV' + 'MRT53_dH' 'MRT53_dV' + 'MRT54_dH' 'MRT54_dV' + 'MRT55_dH' 'MRT55_dV' + 'MRT56_dH' 'MRT56_dV' + 'MRT57_dH' 'MRT57_dV' + 'MZC01_dH' 'MZC01_dV' + 'MZC02_dH' 'MZC02_dV' + 'MZC03_dH' 'MZC03_dV' + 'MZC04_dH' 'MZC04_dV' + 'MZF01_dH' 'MZF01_dV' + 'MZF02_dH' 'MZF02_dV' + 'MZF03_dH' 'MZF03_dV' + 'MZO01_dH' 'MZO01_dV' + 'MZO02_dH' 'MZO02_dV' + 'MZO03_dH' 'MZO03_dV' + 'MZP01_dH' 'MZP01_dV' + }; + + + case 'neuromag122' + label = { + 'MEG 001' 'MEG 002' + 'MEG 003' 'MEG 004' + 'MEG 005' 'MEG 006' + 'MEG 007' 'MEG 008' + 'MEG 009' 'MEG 010' + 'MEG 011' 'MEG 012' + 'MEG 013' 'MEG 014' + 'MEG 015' 'MEG 016' + 'MEG 017' 'MEG 018' + 'MEG 019' 'MEG 020' + 'MEG 021' 'MEG 022' + 'MEG 023' 'MEG 024' + 'MEG 025' 'MEG 026' + 'MEG 027' 'MEG 028' + 'MEG 029' 'MEG 030' + 'MEG 031' 'MEG 032' + 'MEG 033' 'MEG 034' + 'MEG 035' 'MEG 036' + 'MEG 037' 'MEG 038' + 'MEG 039' 'MEG 040' + 'MEG 041' 'MEG 042' + 'MEG 043' 'MEG 044' + 'MEG 045' 'MEG 046' + 'MEG 047' 'MEG 048' + 'MEG 049' 'MEG 050' + 'MEG 051' 'MEG 052' + 'MEG 053' 'MEG 054' + 'MEG 055' 'MEG 056' + 'MEG 057' 'MEG 058' + 'MEG 059' 'MEG 060' + 'MEG 061' 'MEG 062' + 'MEG 063' 'MEG 064' + 'MEG 065' 'MEG 066' + 'MEG 067' 'MEG 068' + 'MEG 069' 'MEG 070' + 'MEG 071' 'MEG 072' + 'MEG 073' 'MEG 074' + 'MEG 075' 'MEG 076' + 'MEG 077' 'MEG 078' + 'MEG 079' 'MEG 080' + 'MEG 081' 'MEG 082' + 'MEG 083' 'MEG 084' + 'MEG 085' 'MEG 086' + 'MEG 087' 'MEG 088' + 'MEG 089' 'MEG 090' + 'MEG 091' 'MEG 092' + 'MEG 093' 'MEG 094' + 'MEG 095' 'MEG 096' + 'MEG 097' 'MEG 098' + 'MEG 099' 'MEG 100' + 'MEG 101' 'MEG 102' + 'MEG 103' 'MEG 104' + 'MEG 105' 'MEG 106' + 'MEG 107' 'MEG 108' + 'MEG 109' 'MEG 110' + 'MEG 111' 'MEG 112' + 'MEG 113' 'MEG 114' + 'MEG 115' 'MEG 116' + 'MEG 117' 'MEG 118' + 'MEG 119' 'MEG 120' + 'MEG 121' 'MEG 122' + }; + + case 'neuromag122alt' + % this is an alternative set of labels without a space in them + label = { + 'MEG001' 'MEG002' + 'MEG003' 'MEG004' + 'MEG005' 'MEG006' + 'MEG007' 'MEG008' + 'MEG009' 'MEG010' + 'MEG011' 'MEG012' + 'MEG013' 'MEG014' + 'MEG015' 'MEG016' + 'MEG017' 'MEG018' + 'MEG019' 'MEG020' + 'MEG021' 'MEG022' + 'MEG023' 'MEG024' + 'MEG025' 'MEG026' + 'MEG027' 'MEG028' + 'MEG029' 'MEG030' + 'MEG031' 'MEG032' + 'MEG033' 'MEG034' + 'MEG035' 'MEG036' + 'MEG037' 'MEG038' + 'MEG039' 'MEG040' + 'MEG041' 'MEG042' + 'MEG043' 'MEG044' + 'MEG045' 'MEG046' + 'MEG047' 'MEG048' + 'MEG049' 'MEG050' + 'MEG051' 'MEG052' + 'MEG053' 'MEG054' + 'MEG055' 'MEG056' + 'MEG057' 'MEG058' + 'MEG059' 'MEG060' + 'MEG061' 'MEG062' + 'MEG063' 'MEG064' + 'MEG065' 'MEG066' + 'MEG067' 'MEG068' + 'MEG069' 'MEG070' + 'MEG071' 'MEG072' + 'MEG073' 'MEG074' + 'MEG075' 'MEG076' + 'MEG077' 'MEG078' + 'MEG079' 'MEG080' + 'MEG081' 'MEG082' + 'MEG083' 'MEG084' + 'MEG085' 'MEG086' + 'MEG087' 'MEG088' + 'MEG089' 'MEG090' + 'MEG091' 'MEG092' + 'MEG093' 'MEG094' + 'MEG095' 'MEG096' + 'MEG097' 'MEG098' + 'MEG099' 'MEG100' + 'MEG101' 'MEG102' + 'MEG103' 'MEG104' + 'MEG105' 'MEG106' + 'MEG107' 'MEG108' + 'MEG109' 'MEG110' + 'MEG111' 'MEG112' + 'MEG113' 'MEG114' + 'MEG115' 'MEG116' + 'MEG117' 'MEG118' + 'MEG119' 'MEG120' + 'MEG121' 'MEG122' + }; + + case 'neuromag306' + label = { + 'MEG 0113' 'MEG 0112' 'MEG 0111' + 'MEG 0122' 'MEG 0123' 'MEG 0121' + 'MEG 0132' 'MEG 0133' 'MEG 0131' + 'MEG 0143' 'MEG 0142' 'MEG 0141' + 'MEG 0213' 'MEG 0212' 'MEG 0211' + 'MEG 0222' 'MEG 0223' 'MEG 0221' + 'MEG 0232' 'MEG 0233' 'MEG 0231' + 'MEG 0243' 'MEG 0242' 'MEG 0241' + 'MEG 0313' 'MEG 0312' 'MEG 0311' + 'MEG 0322' 'MEG 0323' 'MEG 0321' + 'MEG 0333' 'MEG 0332' 'MEG 0331' + 'MEG 0343' 'MEG 0342' 'MEG 0341' + 'MEG 0413' 'MEG 0412' 'MEG 0411' + 'MEG 0422' 'MEG 0423' 'MEG 0421' + 'MEG 0432' 'MEG 0433' 'MEG 0431' + 'MEG 0443' 'MEG 0442' 'MEG 0441' + 'MEG 0513' 'MEG 0512' 'MEG 0511' + 'MEG 0523' 'MEG 0522' 'MEG 0521' + 'MEG 0532' 'MEG 0533' 'MEG 0531' + 'MEG 0542' 'MEG 0543' 'MEG 0541' + 'MEG 0613' 'MEG 0612' 'MEG 0611' + 'MEG 0622' 'MEG 0623' 'MEG 0621' + 'MEG 0633' 'MEG 0632' 'MEG 0631' + 'MEG 0642' 'MEG 0643' 'MEG 0641' + 'MEG 0713' 'MEG 0712' 'MEG 0711' + 'MEG 0723' 'MEG 0722' 'MEG 0721' + 'MEG 0733' 'MEG 0732' 'MEG 0731' + 'MEG 0743' 'MEG 0742' 'MEG 0741' + 'MEG 0813' 'MEG 0812' 'MEG 0811' + 'MEG 0822' 'MEG 0823' 'MEG 0821' + 'MEG 0913' 'MEG 0912' 'MEG 0911' + 'MEG 0923' 'MEG 0922' 'MEG 0921' + 'MEG 0932' 'MEG 0933' 'MEG 0931' + 'MEG 0942' 'MEG 0943' 'MEG 0941' + 'MEG 1013' 'MEG 1012' 'MEG 1011' + 'MEG 1023' 'MEG 1022' 'MEG 1021' + 'MEG 1032' 'MEG 1033' 'MEG 1031' + 'MEG 1043' 'MEG 1042' 'MEG 1041' + 'MEG 1112' 'MEG 1113' 'MEG 1111' + 'MEG 1123' 'MEG 1122' 'MEG 1121' + 'MEG 1133' 'MEG 1132' 'MEG 1131' + 'MEG 1142' 'MEG 1143' 'MEG 1141' + 'MEG 1213' 'MEG 1212' 'MEG 1211' + 'MEG 1223' 'MEG 1222' 'MEG 1221' + 'MEG 1232' 'MEG 1233' 'MEG 1231' + 'MEG 1243' 'MEG 1242' 'MEG 1241' + 'MEG 1312' 'MEG 1313' 'MEG 1311' + 'MEG 1323' 'MEG 1322' 'MEG 1321' + 'MEG 1333' 'MEG 1332' 'MEG 1331' + 'MEG 1342' 'MEG 1343' 'MEG 1341' + 'MEG 1412' 'MEG 1413' 'MEG 1411' + 'MEG 1423' 'MEG 1422' 'MEG 1421' + 'MEG 1433' 'MEG 1432' 'MEG 1431' + 'MEG 1442' 'MEG 1443' 'MEG 1441' + 'MEG 1512' 'MEG 1513' 'MEG 1511' + 'MEG 1522' 'MEG 1523' 'MEG 1521' + 'MEG 1533' 'MEG 1532' 'MEG 1531' + 'MEG 1543' 'MEG 1542' 'MEG 1541' + 'MEG 1613' 'MEG 1612' 'MEG 1611' + 'MEG 1622' 'MEG 1623' 'MEG 1621' + 'MEG 1632' 'MEG 1633' 'MEG 1631' + 'MEG 1643' 'MEG 1642' 'MEG 1641' + 'MEG 1713' 'MEG 1712' 'MEG 1711' + 'MEG 1722' 'MEG 1723' 'MEG 1721' + 'MEG 1732' 'MEG 1733' 'MEG 1731' + 'MEG 1743' 'MEG 1742' 'MEG 1741' + 'MEG 1813' 'MEG 1812' 'MEG 1811' + 'MEG 1822' 'MEG 1823' 'MEG 1821' + 'MEG 1832' 'MEG 1833' 'MEG 1831' + 'MEG 1843' 'MEG 1842' 'MEG 1841' + 'MEG 1912' 'MEG 1913' 'MEG 1911' + 'MEG 1923' 'MEG 1922' 'MEG 1921' + 'MEG 1932' 'MEG 1933' 'MEG 1931' + 'MEG 1943' 'MEG 1942' 'MEG 1941' + 'MEG 2013' 'MEG 2012' 'MEG 2011' + 'MEG 2023' 'MEG 2022' 'MEG 2021' + 'MEG 2032' 'MEG 2033' 'MEG 2031' + 'MEG 2042' 'MEG 2043' 'MEG 2041' + 'MEG 2113' 'MEG 2112' 'MEG 2111' + 'MEG 2122' 'MEG 2123' 'MEG 2121' + 'MEG 2133' 'MEG 2132' 'MEG 2131' + 'MEG 2143' 'MEG 2142' 'MEG 2141' + 'MEG 2212' 'MEG 2213' 'MEG 2211' + 'MEG 2223' 'MEG 2222' 'MEG 2221' + 'MEG 2233' 'MEG 2232' 'MEG 2231' + 'MEG 2242' 'MEG 2243' 'MEG 2241' + 'MEG 2312' 'MEG 2313' 'MEG 2311' + 'MEG 2323' 'MEG 2322' 'MEG 2321' + 'MEG 2332' 'MEG 2333' 'MEG 2331' + 'MEG 2343' 'MEG 2342' 'MEG 2341' + 'MEG 2412' 'MEG 2413' 'MEG 2411' + 'MEG 2423' 'MEG 2422' 'MEG 2421' + 'MEG 2433' 'MEG 2432' 'MEG 2431' + 'MEG 2442' 'MEG 2443' 'MEG 2441' + 'MEG 2512' 'MEG 2513' 'MEG 2511' + 'MEG 2522' 'MEG 2523' 'MEG 2521' + 'MEG 2533' 'MEG 2532' 'MEG 2531' + 'MEG 2543' 'MEG 2542' 'MEG 2541' + 'MEG 2612' 'MEG 2613' 'MEG 2611' + 'MEG 2623' 'MEG 2622' 'MEG 2621' + 'MEG 2633' 'MEG 2632' 'MEG 2631' + 'MEG 2642' 'MEG 2643' 'MEG 2641' + }; + + case 'neuromag306alt' + % this is an alternative set of labels without a space in them + label = { + 'MEG0113' 'MEG0112' 'MEG0111' + 'MEG0122' 'MEG0123' 'MEG0121' + 'MEG0132' 'MEG0133' 'MEG0131' + 'MEG0143' 'MEG0142' 'MEG0141' + 'MEG0213' 'MEG0212' 'MEG0211' + 'MEG0222' 'MEG0223' 'MEG0221' + 'MEG0232' 'MEG0233' 'MEG0231' + 'MEG0243' 'MEG0242' 'MEG0241' + 'MEG0313' 'MEG0312' 'MEG0311' + 'MEG0322' 'MEG0323' 'MEG0321' + 'MEG0333' 'MEG0332' 'MEG0331' + 'MEG0343' 'MEG0342' 'MEG0341' + 'MEG0413' 'MEG0412' 'MEG0411' + 'MEG0422' 'MEG0423' 'MEG0421' + 'MEG0432' 'MEG0433' 'MEG0431' + 'MEG0443' 'MEG0442' 'MEG0441' + 'MEG0513' 'MEG0512' 'MEG0511' + 'MEG0523' 'MEG0522' 'MEG0521' + 'MEG0532' 'MEG0533' 'MEG0531' + 'MEG0542' 'MEG0543' 'MEG0541' + 'MEG0613' 'MEG0612' 'MEG0611' + 'MEG0622' 'MEG0623' 'MEG0621' + 'MEG0633' 'MEG0632' 'MEG0631' + 'MEG0642' 'MEG0643' 'MEG0641' + 'MEG0713' 'MEG0712' 'MEG0711' + 'MEG0723' 'MEG0722' 'MEG0721' + 'MEG0733' 'MEG0732' 'MEG0731' + 'MEG0743' 'MEG0742' 'MEG0741' + 'MEG0813' 'MEG0812' 'MEG0811' + 'MEG0822' 'MEG0823' 'MEG0821' + 'MEG0913' 'MEG0912' 'MEG0911' + 'MEG0923' 'MEG0922' 'MEG0921' + 'MEG0932' 'MEG0933' 'MEG0931' + 'MEG0942' 'MEG0943' 'MEG0941' + 'MEG1013' 'MEG1012' 'MEG1011' + 'MEG1023' 'MEG1022' 'MEG1021' + 'MEG1032' 'MEG1033' 'MEG1031' + 'MEG1043' 'MEG1042' 'MEG1041' + 'MEG1112' 'MEG1113' 'MEG1111' + 'MEG1123' 'MEG1122' 'MEG1121' + 'MEG1133' 'MEG1132' 'MEG1131' + 'MEG1142' 'MEG1143' 'MEG1141' + 'MEG1213' 'MEG1212' 'MEG1211' + 'MEG1223' 'MEG1222' 'MEG1221' + 'MEG1232' 'MEG1233' 'MEG1231' + 'MEG1243' 'MEG1242' 'MEG1241' + 'MEG1312' 'MEG1313' 'MEG1311' + 'MEG1323' 'MEG1322' 'MEG1321' + 'MEG1333' 'MEG1332' 'MEG1331' + 'MEG1342' 'MEG1343' 'MEG1341' + 'MEG1412' 'MEG1413' 'MEG1411' + 'MEG1423' 'MEG1422' 'MEG1421' + 'MEG1433' 'MEG1432' 'MEG1431' + 'MEG1442' 'MEG1443' 'MEG1441' + 'MEG1512' 'MEG1513' 'MEG1511' + 'MEG1522' 'MEG1523' 'MEG1521' + 'MEG1533' 'MEG1532' 'MEG1531' + 'MEG1543' 'MEG1542' 'MEG1541' + 'MEG1613' 'MEG1612' 'MEG1611' + 'MEG1622' 'MEG1623' 'MEG1621' + 'MEG1632' 'MEG1633' 'MEG1631' + 'MEG1643' 'MEG1642' 'MEG1641' + 'MEG1713' 'MEG1712' 'MEG1711' + 'MEG1722' 'MEG1723' 'MEG1721' + 'MEG1732' 'MEG1733' 'MEG1731' + 'MEG1743' 'MEG1742' 'MEG1741' + 'MEG1813' 'MEG1812' 'MEG1811' + 'MEG1822' 'MEG1823' 'MEG1821' + 'MEG1832' 'MEG1833' 'MEG1831' + 'MEG1843' 'MEG1842' 'MEG1841' + 'MEG1912' 'MEG1913' 'MEG1911' + 'MEG1923' 'MEG1922' 'MEG1921' + 'MEG1932' 'MEG1933' 'MEG1931' + 'MEG1943' 'MEG1942' 'MEG1941' + 'MEG2013' 'MEG2012' 'MEG2011' + 'MEG2023' 'MEG2022' 'MEG2021' + 'MEG2032' 'MEG2033' 'MEG2031' + 'MEG2042' 'MEG2043' 'MEG2041' + 'MEG2113' 'MEG2112' 'MEG2111' + 'MEG2122' 'MEG2123' 'MEG2121' + 'MEG2133' 'MEG2132' 'MEG2131' + 'MEG2143' 'MEG2142' 'MEG2141' + 'MEG2212' 'MEG2213' 'MEG2211' + 'MEG2223' 'MEG2222' 'MEG2221' + 'MEG2233' 'MEG2232' 'MEG2231' + 'MEG2242' 'MEG2243' 'MEG2241' + 'MEG2312' 'MEG2313' 'MEG2311' + 'MEG2323' 'MEG2322' 'MEG2321' + 'MEG2332' 'MEG2333' 'MEG2331' + 'MEG2343' 'MEG2342' 'MEG2341' + 'MEG2412' 'MEG2413' 'MEG2411' + 'MEG2423' 'MEG2422' 'MEG2421' + 'MEG2433' 'MEG2432' 'MEG2431' + 'MEG2442' 'MEG2443' 'MEG2441' + 'MEG2512' 'MEG2513' 'MEG2511' + 'MEG2522' 'MEG2523' 'MEG2521' + 'MEG2533' 'MEG2532' 'MEG2531' + 'MEG2543' 'MEG2542' 'MEG2541' + 'MEG2612' 'MEG2613' 'MEG2611' + 'MEG2623' 'MEG2622' 'MEG2621' + 'MEG2633' 'MEG2632' 'MEG2631' + 'MEG2642' 'MEG2643' 'MEG2641' + }; + + + case 'eeg1020' + label = { + 'Fp1' + 'Fpz' + 'Fp2' + 'F7' + 'F3' + 'Fz' + 'F4' + 'F8' + 'T7' + 'C3' + 'Cz' + 'C4' + 'T8' + 'P7' + 'P3' + 'Pz' + 'P4' + 'P8' + 'O1' + 'Oz' + 'O2'}; + + case 'eeg1010' + label = { + 'Fp1' + 'Fpz' + 'Fp2' + 'AF9' + 'AF7' + 'AF5' + 'AF3' + 'AF1' + 'AFz' + 'AF2' + 'AF4' + 'AF6' + 'AF8' + 'AF10' + 'F9' + 'F7' + 'F5' + 'F3' + 'F1' + 'Fz' + 'F2' + 'F4' + 'F6' + 'F8' + 'F10' + 'FT9' + 'FT7' + 'FC5' + 'FC3' + 'FC1' + 'FCz' + 'FC2' + 'FC4' + 'FC6' + 'FT8' + 'FT10' + 'T9' + 'T7' + 'C5' + 'C3' + 'C1' + 'Cz' + 'C2' + 'C4' + 'C6' + 'T8' + 'T10' + 'TP9' + 'TP7' + 'CP5' + 'CP3' + 'CP1' + 'CPz' + 'CP2' + 'CP4' + 'CP6' + 'TP8' + 'TP10' + 'P9' + 'P7' + 'P5' + 'P3' + 'P1' + 'Pz' + 'P2' + 'P4' + 'P6' + 'P8' + 'P10' + 'PO9' + 'PO7' + 'PO5' + 'PO3' + 'PO1' + 'POz' + 'PO2' + 'PO4' + 'PO6' + 'PO8' + 'PO10' + 'O1' + 'Oz' + 'O2' + 'I1' + 'Iz' + 'I2' + }; + + case 'eeg1005' + label = { + 'Fp1' + 'Fpz' + 'Fp2' + 'AF9' + 'AF7' + 'AF5' + 'AF3' + 'AF1' + 'AFz' + 'AF2' + 'AF4' + 'AF6' + 'AF8' + 'AF10' + 'F9' + 'F7' + 'F5' + 'F3' + 'F1' + 'Fz' + 'F2' + 'F4' + 'F6' + 'F8' + 'F10' + 'FT9' + 'FT7' + 'FC5' + 'FC3' + 'FC1' + 'FCz' + 'FC2' + 'FC4' + 'FC6' + 'FT8' + 'FT10' + 'T9' + 'T7' + 'C5' + 'C3' + 'C1' + 'Cz' + 'C2' + 'C4' + 'C6' + 'T8' + 'T10' + 'TP9' + 'TP7' + 'CP5' + 'CP3' + 'CP1' + 'CPz' + 'CP2' + 'CP4' + 'CP6' + 'TP8' + 'TP10' + 'P9' + 'P7' + 'P5' + 'P3' + 'P1' + 'Pz' + 'P2' + 'P4' + 'P6' + 'P8' + 'P10' + 'PO9' + 'PO7' + 'PO5' + 'PO3' + 'PO1' + 'POz' + 'PO2' + 'PO4' + 'PO6' + 'PO8' + 'PO10' + 'O1' + 'Oz' + 'O2' + 'I1' + 'Iz' + 'I2' + 'AFp9h' + 'AFp7h' + 'AFp5h' + 'AFp3h' + 'AFp1h' + 'AFp2h' + 'AFp4h' + 'AFp6h' + 'AFp8h' + 'AFp10h' + 'AFF9h' + 'AFF7h' + 'AFF5h' + 'AFF3h' + 'AFF1h' + 'AFF2h' + 'AFF4h' + 'AFF6h' + 'AFF8h' + 'AFF10h' + 'FFT9h' + 'FFT7h' + 'FFC5h' + 'FFC3h' + 'FFC1h' + 'FFC2h' + 'FFC4h' + 'FFC6h' + 'FFT8h' + 'FFT10h' + 'FTT9h' + 'FTT7h' + 'FCC5h' + 'FCC3h' + 'FCC1h' + 'FCC2h' + 'FCC4h' + 'FCC6h' + 'FTT8h' + 'FTT10h' + 'TTP9h' + 'TTP7h' + 'CCP5h' + 'CCP3h' + 'CCP1h' + 'CCP2h' + 'CCP4h' + 'CCP6h' + 'TTP8h' + 'TTP10h' + 'TPP9h' + 'TPP7h' + 'CPP5h' + 'CPP3h' + 'CPP1h' + 'CPP2h' + 'CPP4h' + 'CPP6h' + 'TPP8h' + 'TPP10h' + 'PPO9h' + 'PPO7h' + 'PPO5h' + 'PPO3h' + 'PPO1h' + 'PPO2h' + 'PPO4h' + 'PPO6h' + 'PPO8h' + 'PPO10h' + 'POO9h' + 'POO7h' + 'POO5h' + 'POO3h' + 'POO1h' + 'POO2h' + 'POO4h' + 'POO6h' + 'POO8h' + 'POO10h' + 'OI1h' + 'OI2h' + 'Fp1h' + 'Fp2h' + 'AF9h' + 'AF7h' + 'AF5h' + 'AF3h' + 'AF1h' + 'AF2h' + 'AF4h' + 'AF6h' + 'AF8h' + 'AF10h' + 'F9h' + 'F7h' + 'F5h' + 'F3h' + 'F1h' + 'F2h' + 'F4h' + 'F6h' + 'F8h' + 'F10h' + 'FT9h' + 'FT7h' + 'FC5h' + 'FC3h' + 'FC1h' + 'FC2h' + 'FC4h' + 'FC6h' + 'FT8h' + 'FT10h' + 'T9h' + 'T7h' + 'C5h' + 'C3h' + 'C1h' + 'C2h' + 'C4h' + 'C6h' + 'T8h' + 'T10h' + 'TP9h' + 'TP7h' + 'CP5h' + 'CP3h' + 'CP1h' + 'CP2h' + 'CP4h' + 'CP6h' + 'TP8h' + 'TP10h' + 'P9h' + 'P7h' + 'P5h' + 'P3h' + 'P1h' + 'P2h' + 'P4h' + 'P6h' + 'P8h' + 'P10h' + 'PO9h' + 'PO7h' + 'PO5h' + 'PO3h' + 'PO1h' + 'PO2h' + 'PO4h' + 'PO6h' + 'PO8h' + 'PO10h' + 'O1h' + 'O2h' + 'I1h' + 'I2h' + 'AFp9' + 'AFp7' + 'AFp5' + 'AFp3' + 'AFp1' + 'AFpz' + 'AFp2' + 'AFp4' + 'AFp6' + 'AFp8' + 'AFp10' + 'AFF9' + 'AFF7' + 'AFF5' + 'AFF3' + 'AFF1' + 'AFFz' + 'AFF2' + 'AFF4' + 'AFF6' + 'AFF8' + 'AFF10' + 'FFT9' + 'FFT7' + 'FFC5' + 'FFC3' + 'FFC1' + 'FFCz' + 'FFC2' + 'FFC4' + 'FFC6' + 'FFT8' + 'FFT10' + 'FTT9' + 'FTT7' + 'FCC5' + 'FCC3' + 'FCC1' + 'FCCz' + 'FCC2' + 'FCC4' + 'FCC6' + 'FTT8' + 'FTT10' + 'TTP9' + 'TTP7' + 'CCP5' + 'CCP3' + 'CCP1' + 'CCPz' + 'CCP2' + 'CCP4' + 'CCP6' + 'TTP8' + 'TTP10' + 'TPP9' + 'TPP7' + 'CPP5' + 'CPP3' + 'CPP1' + 'CPPz' + 'CPP2' + 'CPP4' + 'CPP6' + 'TPP8' + 'TPP10' + 'PPO9' + 'PPO7' + 'PPO5' + 'PPO3' + 'PPO1' + 'PPOz' + 'PPO2' + 'PPO4' + 'PPO6' + 'PPO8' + 'PPO10' + 'POO9' + 'POO7' + 'POO5' + 'POO3' + 'POO1' + 'POOz' + 'POO2' + 'POO4' + 'POO6' + 'POO8' + 'POO10' + 'OI1' + 'OIz' + 'OI2' + }; + + case 'ext1020' + % start with the eeg1005 list + label = { + 'Fp1' + 'Fpz' + 'Fp2' + 'AF9' + 'AF7' + 'AF5' + 'AF3' + 'AF1' + 'AFz' + 'AF2' + 'AF4' + 'AF6' + 'AF8' + 'AF10' + 'F9' + 'F7' + 'F5' + 'F3' + 'F1' + 'Fz' + 'F2' + 'F4' + 'F6' + 'F8' + 'F10' + 'FT9' + 'FT7' + 'FC5' + 'FC3' + 'FC1' + 'FCz' + 'FC2' + 'FC4' + 'FC6' + 'FT8' + 'FT10' + 'T9' + 'T7' + 'C5' + 'C3' + 'C1' + 'Cz' + 'C2' + 'C4' + 'C6' + 'T8' + 'T10' + 'TP9' + 'TP7' + 'CP5' + 'CP3' + 'CP1' + 'CPz' + 'CP2' + 'CP4' + 'CP6' + 'TP8' + 'TP10' + 'P9' + 'P7' + 'P5' + 'P3' + 'P1' + 'Pz' + 'P2' + 'P4' + 'P6' + 'P8' + 'P10' + 'PO9' + 'PO7' + 'PO5' + 'PO3' + 'PO1' + 'POz' + 'PO2' + 'PO4' + 'PO6' + 'PO8' + 'PO10' + 'O1' + 'Oz' + 'O2' + 'I1' + 'Iz' + 'I2' + 'AFp9h' + 'AFp7h' + 'AFp5h' + 'AFp3h' + 'AFp1h' + 'AFp2h' + 'AFp4h' + 'AFp6h' + 'AFp8h' + 'AFp10h' + 'AFF9h' + 'AFF7h' + 'AFF5h' + 'AFF3h' + 'AFF1h' + 'AFF2h' + 'AFF4h' + 'AFF6h' + 'AFF8h' + 'AFF10h' + 'FFT9h' + 'FFT7h' + 'FFC5h' + 'FFC3h' + 'FFC1h' + 'FFC2h' + 'FFC4h' + 'FFC6h' + 'FFT8h' + 'FFT10h' + 'FTT9h' + 'FTT7h' + 'FCC5h' + 'FCC3h' + 'FCC1h' + 'FCC2h' + 'FCC4h' + 'FCC6h' + 'FTT8h' + 'FTT10h' + 'TTP9h' + 'TTP7h' + 'CCP5h' + 'CCP3h' + 'CCP1h' + 'CCP2h' + 'CCP4h' + 'CCP6h' + 'TTP8h' + 'TTP10h' + 'TPP9h' + 'TPP7h' + 'CPP5h' + 'CPP3h' + 'CPP1h' + 'CPP2h' + 'CPP4h' + 'CPP6h' + 'TPP8h' + 'TPP10h' + 'PPO9h' + 'PPO7h' + 'PPO5h' + 'PPO3h' + 'PPO1h' + 'PPO2h' + 'PPO4h' + 'PPO6h' + 'PPO8h' + 'PPO10h' + 'POO9h' + 'POO7h' + 'POO5h' + 'POO3h' + 'POO1h' + 'POO2h' + 'POO4h' + 'POO6h' + 'POO8h' + 'POO10h' + 'OI1h' + 'OI2h' + 'Fp1h' + 'Fp2h' + 'AF9h' + 'AF7h' + 'AF5h' + 'AF3h' + 'AF1h' + 'AF2h' + 'AF4h' + 'AF6h' + 'AF8h' + 'AF10h' + 'F9h' + 'F7h' + 'F5h' + 'F3h' + 'F1h' + 'F2h' + 'F4h' + 'F6h' + 'F8h' + 'F10h' + 'FT9h' + 'FT7h' + 'FC5h' + 'FC3h' + 'FC1h' + 'FC2h' + 'FC4h' + 'FC6h' + 'FT8h' + 'FT10h' + 'T9h' + 'T7h' + 'C5h' + 'C3h' + 'C1h' + 'C2h' + 'C4h' + 'C6h' + 'T8h' + 'T10h' + 'TP9h' + 'TP7h' + 'CP5h' + 'CP3h' + 'CP1h' + 'CP2h' + 'CP4h' + 'CP6h' + 'TP8h' + 'TP10h' + 'P9h' + 'P7h' + 'P5h' + 'P3h' + 'P1h' + 'P2h' + 'P4h' + 'P6h' + 'P8h' + 'P10h' + 'PO9h' + 'PO7h' + 'PO5h' + 'PO3h' + 'PO1h' + 'PO2h' + 'PO4h' + 'PO6h' + 'PO8h' + 'PO10h' + 'O1h' + 'O2h' + 'I1h' + 'I2h' + 'AFp9' + 'AFp7' + 'AFp5' + 'AFp3' + 'AFp1' + 'AFpz' + 'AFp2' + 'AFp4' + 'AFp6' + 'AFp8' + 'AFp10' + 'AFF9' + 'AFF7' + 'AFF5' + 'AFF3' + 'AFF1' + 'AFFz' + 'AFF2' + 'AFF4' + 'AFF6' + 'AFF8' + 'AFF10' + 'FFT9' + 'FFT7' + 'FFC5' + 'FFC3' + 'FFC1' + 'FFCz' + 'FFC2' + 'FFC4' + 'FFC6' + 'FFT8' + 'FFT10' + 'FTT9' + 'FTT7' + 'FCC5' + 'FCC3' + 'FCC1' + 'FCCz' + 'FCC2' + 'FCC4' + 'FCC6' + 'FTT8' + 'FTT10' + 'TTP9' + 'TTP7' + 'CCP5' + 'CCP3' + 'CCP1' + 'CCPz' + 'CCP2' + 'CCP4' + 'CCP6' + 'TTP8' + 'TTP10' + 'TPP9' + 'TPP7' + 'CPP5' + 'CPP3' + 'CPP1' + 'CPPz' + 'CPP2' + 'CPP4' + 'CPP6' + 'TPP8' + 'TPP10' + 'PPO9' + 'PPO7' + 'PPO5' + 'PPO3' + 'PPO1' + 'PPOz' + 'PPO2' + 'PPO4' + 'PPO6' + 'PPO8' + 'PPO10' + 'POO9' + 'POO7' + 'POO5' + 'POO3' + 'POO1' + 'POOz' + 'POO2' + 'POO4' + 'POO6' + 'POO8' + 'POO10' + 'OI1' + 'OIz' + 'OI2' + }; + + % Add also alternative labels that are used in some systems + label = cat(1, label, {'A1' 'A2' 'M1' 'M2' 'T3' 'T4' 'T5' 'T6'}'); + + % This is to account for all variants of case in 1020 systems + label = unique(cat(1, label, upper(label), lower(label))); + + case 'biosemi64' + label = { + 'A1' + 'A2' + 'A3' + 'A4' + 'A5' + 'A6' + 'A7' + 'A8' + 'A9' + 'A10' + 'A11' + 'A12' + 'A13' + 'A14' + 'A15' + 'A16' + 'A17' + 'A18' + 'A19' + 'A20' + 'A21' + 'A22' + 'A23' + 'A24' + 'A25' + 'A26' + 'A27' + 'A28' + 'A29' + 'A30' + 'A31' + 'A32' + 'B1' + 'B2' + 'B3' + 'B4' + 'B5' + 'B6' + 'B7' + 'B8' + 'B9' + 'B10' + 'B11' + 'B12' + 'B13' + 'B14' + 'B15' + 'B16' + 'B17' + 'B18' + 'B19' + 'B20' + 'B21' + 'B22' + 'B23' + 'B24' + 'B25' + 'B26' + 'B27' + 'B28' + 'B29' + 'B30' + 'B31' + 'B32' + }; + + case 'biosemi128' + label = { + 'A1' + 'A2' + 'A3' + 'A4' + 'A5' + 'A6' + 'A7' + 'A8' + 'A9' + 'A10' + 'A11' + 'A12' + 'A13' + 'A14' + 'A15' + 'A16' + 'A17' + 'A18' + 'A19' + 'A20' + 'A21' + 'A22' + 'A23' + 'A24' + 'A25' + 'A26' + 'A27' + 'A28' + 'A29' + 'A30' + 'A31' + 'A32' + 'B1' + 'B2' + 'B3' + 'B4' + 'B5' + 'B6' + 'B7' + 'B8' + 'B9' + 'B10' + 'B11' + 'B12' + 'B13' + 'B14' + 'B15' + 'B16' + 'B17' + 'B18' + 'B19' + 'B20' + 'B21' + 'B22' + 'B23' + 'B24' + 'B25' + 'B26' + 'B27' + 'B28' + 'B29' + 'B30' + 'B31' + 'B32' + 'C1' + 'C2' + 'C3' + 'C4' + 'C5' + 'C6' + 'C7' + 'C8' + 'C9' + 'C10' + 'C11' + 'C12' + 'C13' + 'C14' + 'C15' + 'C16' + 'C17' + 'C18' + 'C19' + 'C20' + 'C21' + 'C22' + 'C23' + 'C24' + 'C25' + 'C26' + 'C27' + 'C28' + 'C29' + 'C30' + 'C31' + 'C32' + 'D1' + 'D2' + 'D3' + 'D4' + 'D5' + 'D6' + 'D7' + 'D8' + 'D9' + 'D10' + 'D11' + 'D12' + 'D13' + 'D14' + 'D15' + 'D16' + 'D17' + 'D18' + 'D19' + 'D20' + 'D21' + 'D22' + 'D23' + 'D24' + 'D25' + 'D26' + 'D27' + 'D28' + 'D29' + 'D30' + 'D31' + 'D32' + }; + + case 'biosemi256' + label = { + 'A1' + 'A2' + 'A3' + 'A4' + 'A5' + 'A6' + 'A7' + 'A8' + 'A9' + 'A10' + 'A11' + 'A12' + 'A13' + 'A14' + 'A15' + 'A16' + 'A17' + 'A18' + 'A19' + 'A20' + 'A21' + 'A22' + 'A23' + 'A24' + 'A25' + 'A26' + 'A27' + 'A28' + 'A29' + 'A30' + 'A31' + 'A32' + 'B1' + 'B2' + 'B3' + 'B4' + 'B5' + 'B6' + 'B7' + 'B8' + 'B9' + 'B10' + 'B11' + 'B12' + 'B13' + 'B14' + 'B15' + 'B16' + 'B17' + 'B18' + 'B19' + 'B20' + 'B21' + 'B22' + 'B23' + 'B24' + 'B25' + 'B26' + 'B27' + 'B28' + 'B29' + 'B30' + 'B31' + 'B32' + 'C1' + 'C2' + 'C3' + 'C4' + 'C5' + 'C6' + 'C7' + 'C8' + 'C9' + 'C10' + 'C11' + 'C12' + 'C13' + 'C14' + 'C15' + 'C16' + 'C17' + 'C18' + 'C19' + 'C20' + 'C21' + 'C22' + 'C23' + 'C24' + 'C25' + 'C26' + 'C27' + 'C28' + 'C29' + 'C30' + 'C31' + 'C32' + 'D1' + 'D2' + 'D3' + 'D4' + 'D5' + 'D6' + 'D7' + 'D8' + 'D9' + 'D10' + 'D11' + 'D12' + 'D13' + 'D14' + 'D15' + 'D16' + 'D17' + 'D18' + 'D19' + 'D20' + 'D21' + 'D22' + 'D23' + 'D24' + 'D25' + 'D26' + 'D27' + 'D28' + 'D29' + 'D30' + 'D31' + 'D32' + 'E1' + 'E2' + 'E3' + 'E4' + 'E5' + 'E6' + 'E7' + 'E8' + 'E9' + 'E10' + 'E11' + 'E12' + 'E13' + 'E14' + 'E15' + 'E16' + 'E17' + 'E18' + 'E19' + 'E20' + 'E21' + 'E22' + 'E23' + 'E24' + 'E25' + 'E26' + 'E27' + 'E28' + 'E29' + 'E30' + 'E31' + 'E32' + 'F1' + 'F2' + 'F3' + 'F4' + 'F5' + 'F6' + 'F7' + 'F8' + 'F9' + 'F10' + 'F11' + 'F12' + 'F13' + 'F14' + 'F15' + 'F16' + 'F17' + 'F18' + 'F19' + 'F20' + 'F21' + 'F22' + 'F23' + 'F24' + 'F25' + 'F26' + 'F27' + 'F28' + 'F29' + 'F30' + 'F31' + 'F32' + 'G1' + 'G2' + 'G3' + 'G4' + 'G5' + 'G6' + 'G7' + 'G8' + 'G9' + 'G10' + 'G11' + 'G12' + 'G13' + 'G14' + 'G15' + 'G16' + 'G17' + 'G18' + 'G19' + 'G20' + 'G21' + 'G22' + 'G23' + 'G24' + 'G25' + 'G26' + 'G27' + 'G28' + 'G29' + 'G30' + 'G31' + 'G32' + 'H1' + 'H2' + 'H3' + 'H4' + 'H5' + 'H6' + 'H7' + 'H8' + 'H9' + 'H10' + 'H11' + 'H12' + 'H13' + 'H14' + 'H15' + 'H16' + 'H17' + 'H18' + 'H19' + 'H20' + 'H21' + 'H22' + 'H23' + 'H24' + 'H25' + 'H26' + 'H27' + 'H28' + 'H29' + 'H30' + 'H31' + 'H32' + }; + + case 'egi32' + label = cell(32, 1); + for i = 1:32 + label{i} = sprintf('e%d', i); + end + + case 'egi64' + label = cell(64, 1); + for i = 1:64 + label{i} = sprintf('e%d', i); + end + + case 'egi128' + label = cell(128, 1); + for i = 1:128 + label{i} = sprintf('e%d', i); + end + + case 'egi256' + label = cell(256, 1); + for i = 1:256 + label{i} = sprintf('e%d', i); + end + + case 'itab153' + label = cell(153,1); + for i=1:153 + % channel names start counting at zero + label{i} = sprintf('MAG_%03d', i-1); + end + + case 'itab153_planar' + label = cell(153,2); + for i=1:153 + % channel names start counting at zero + label{i,1} = sprintf('MAG_%03d_dH', i-1); + label{i,2} = sprintf('MAG_%03d_dV', i-1); + end + + case 'yokogawa160' + % this should be consistent with read_yokogawa_header, with + % ft_channelselection and with yokogawa2grad + label = cell(160,1); + for i=1:160 + label{i} = sprintf('AG%03d', i); + end + + case 'yokogawa160_planar' + % this should be consistent with read_yokogawa_header, with + % ft_channelselection and with yokogawa2grad + label = cell(160,2); + for i=1:160 + label{i,1} = sprintf('AG%03d_dH', i); + label{i,2} = sprintf('AG%03d_dV', i); + end + + case 'electrode' + % there is no default set of electrode labels, by input type 'electrode' should not result in an error + label = {}; + + otherwise + error('the requested sensor type is not supported'); +end + +% remember the current input and output arguments, so that they can be +% reused on a subsequent call in case the same input argument is given +current_argout = {label}; +if isempty(previous_argin) + previous_argin = current_argin; + previous_argout = current_argout; +end + diff --git a/external/fieldtrip/inverse/private/ft_senstype.m b/external/fieldtrip/inverse/private/ft_senstype.m new file mode 100644 index 0000000..ade2190 --- /dev/null +++ b/external/fieldtrip/inverse/private/ft_senstype.m @@ -0,0 +1,362 @@ +function [type] = ft_senstype(input, desired) + +% FT_SENSTYPE determines the type of sensors by looking at the channel names +% and comparing them with predefined lists. +% +% Use as +% [type] = ft_senstype(sens) +% to get a string describing the type, or +% [flag] = ft_senstype(sens, desired) +% to get a boolean value. +% +% The output type can be any of the following +% 'electrode' +% 'magnetometer' +% 'biosemi64' +% 'biosemi128' +% 'biosemi256' +% 'bti148' +% 'bti148_planar' +% 'bti248' +% 'bti248_planar' +% 'ctf151' +% 'ctf151_planar' +% 'ctf275' +% 'ctf275_planar' +% 'egi128' +% 'egi256' +% 'egi32' +% 'egi64' +% 'ext1020' +% 'neuromag122' +% 'neuromag306' +% 'yokogawa160' +% 'yokogawa160_planar' +% 'plexon' +% 'itab153' +% 'itab153_planar' +% +% The optional input argument for the desired type can be any of the above, +% or any of the following +% 'eeg' +% 'meg' +% 'meg_planar' +% 'meg_axial' +% 'ctf' +% 'bti' +% 'neuromag' +% 'yokogawa' +% +% Besides specifiying a grad or elec structure as input, also allowed is +% giving a data structure containing a grad or elec field, or giving a list +% of channel names (as cell-arrray). I.e. assuming a FieldTrip data +% structure, all of the following calls would be correct. +% ft_senstype(data) +% ft_senstype(data.label) +% ft_senstype(data.grad) +% ft_senstype(data.grad.label) +% +% See also FT_SENSLABEL, FT_CHANTYPE, FT_READ_SENS, FT_COMPUTE_LEADFIELD + +% Copyright (C) 2007-2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_senstype.m 1290 2010-06-29 14:10:50Z roboos $ + +% these are for remembering the type on subsequent calls with the same input arguments +persistent previous_argin previous_argout + +if iscell(input) && numel(input)<4 && ~all(cellfun(@ischar, input)) + % this might represent combined EEG, ECoG and/or MEG + type = cell(size(input)); + if nargin<2 + desired = cell(size(input)); % empty elements + end + for i=1:numel(input) + type{i} = ft_senstype(input{i}, desired{i}); + end + return +end + +if nargin<2 + % ensure that all input arguments are defined + desired = []; +end + +current_argin = {input, desired}; +if isequal(current_argin, previous_argin) + % don't do the type detection again, but return the previous values from + % cache + type = previous_argout{1}; + return +end + +% FIXME the detection of the type of input structure should perhaps be done using the datatype function +isdata = isa(input, 'struct') && isfield(input, 'hdr'); +isheader = isa(input, 'struct') && isfield(input, 'label') && isfield(input, 'Fs'); +isgrad = isa(input, 'struct') && isfield(input, 'label') && isfield(input, 'pnt') && isfield(input, 'ori'); +iselec = isa(input, 'struct') && isfield(input, 'label') && isfield(input, 'pnt') && ~isfield(input, 'ori'); +islabel = isa(input, 'cell') && ~isempty(input) && isa(input{1}, 'char'); + +if ~isdata && ~isheader + % timelock or freq structures don't have the header structure + % the header is also removed from raw data after megrealign + % the gradiometer definition is lost after megplanar+combineplanar + isdata = isa(input, 'struct') && (isfield(input, 'grad') || isfield(input, 'elec') || isfield(input, 'label')); +end + +% the input may be a data structure which then contains a grad/elec structure, a header or only the labels +if isdata + % preferably look at the data and not the header for the grad, because it might be re-balanced and/or planar + if isfield(input, 'grad') + sens = input.grad; + isgrad = true; + elseif issubfield(input, 'hdr.grad') + sens = input.hdr.grad; + isgrad = true; + elseif issubfield(input, 'hdr.elec') + sens = input.hdr.elec; + iselec = true; + elseif isfield(input, 'elec') + sens = input.elec; + iselec = true; + elseif issubfield(input, 'hdr.label') + sens.label = input.hdr.label; + islabel = true; + elseif isfield(input, 'label') + sens.label = input.label; + islabel = true; + end +elseif isheader + if isfield(input, 'grad') + sens = input.grad; + isgrad = true; + elseif isfield(input, 'elec') + sens = input.elec; + iselec = true; + elseif isfield(input, 'label') + sens.label = input.label; + islabel = true; + end +elseif isgrad + sens = input; +elseif iselec + sens = input; +elseif islabel + sens.label = input; +else + sens = []; +end + +if isfield(input, 'type') + % preferably the structure specifies its own type + type = input.type; + +elseif issubfield(input, 'orig.FileHeader') && issubfield(input, 'orig.VarHeader') + % this is a complete header that was read from a Plexon *.nex file using read_plexon_nex + type = 'plexon'; + +elseif issubfield(input, 'orig.stname') + % this is a complete header that was read from an ITAB dataset + type = 'itab'; + +elseif issubfield(input, 'orig.sys_name') + % this is a complete header that was read from a Yokogawa dataset + type = 'yokogawa160'; + +else + % start with unknown, then try to determine the proper type by looking at the labels + type = 'unknown'; + + if isgrad + % probably this is MEG, determine the type of magnetometer/gradiometer system + % note that the order here is important: first check whether it matches a 275 channel system, then a 151 channel system, since the 151 channels are a subset of the 275 + if (mean(ismember(ft_senslabel('ctf275'), sens.label)) > 0.8) + type = 'ctf275'; + elseif (mean(ismember(ft_senslabel('ctfheadloc'), sens.label)) > 0.8) % look at the head localization channels + type = 'ctf275'; + elseif (mean(ismember(ft_senslabel('ctf151'), sens.label)) > 0.8) + type = 'ctf151'; + elseif (mean(ismember(ft_senslabel('ctf64'), sens.label)) > 0.8) + type = 'ctf64'; + elseif (mean(ismember(ft_senslabel('ctf275_planar'), sens.label)) > 0.8) + type = 'ctf275_planar'; + elseif (mean(ismember(ft_senslabel('ctf151_planar'), sens.label)) > 0.8) + type = 'ctf151_planar'; + elseif (mean(ismember(ft_senslabel('bti248'), sens.label)) > 0.8) + type = 'bti248'; + elseif (mean(ismember(ft_senslabel('bti148'), sens.label)) > 0.8) + type = 'bti148'; + elseif (mean(ismember(ft_senslabel('bti248_planar'), sens.label)) > 0.8) + type = 'bti248_planar'; + elseif (mean(ismember(ft_senslabel('bti148_planar'), sens.label)) > 0.8) + type = 'bti148_planar'; + elseif (mean(ismember(ft_senslabel('itab153'), sens.label)) > 0.8) + type = 'itab153'; + elseif (mean(ismember(ft_senslabel('itab153_planar'), sens.label)) > 0.8) + type = 'itab153_planar'; + elseif (mean(ismember(ft_senslabel('yokogawa160'), sens.label)) > 0.4) + type = 'yokogawa160'; + elseif (mean(ismember(ft_senslabel('yokogawa160_planar'), sens.label)) > 0.4) + type = 'yokogawa160_planar'; + elseif (mean(ismember(ft_senslabel('neuromag306'), sens.label)) > 0.8) + type = 'neuromag306'; + elseif (mean(ismember(ft_senslabel('neuromag306alt'),sens.label)) > 0.8) % an alternative set without spaces in the name + type = 'neuromag306'; + elseif (mean(ismember(ft_senslabel('neuromag122'), sens.label)) > 0.8) + type = 'neuromag122'; + elseif (mean(ismember(ft_senslabel('neuromag122alt'),sens.label)) > 0.8) % an alternative set without spaces in the name + type = 'neuromag122'; + elseif any(ismember(ft_senslabel('btiref'), sens.label)) + type = 'bti'; % it might be 148 or 248 channels + elseif any(ismember(ft_senslabel('ctfref'), sens.label)) + type = 'ctf'; % it might be 151 or 275 channels + elseif isfield(sens, 'pnt') && isfield(sens, 'ori') && numel(sens.label)==size(sens.pnt,1) + warning('could be Yokogawa system'); + type = 'magnetometer'; + else + warning('could be Yokogawa system'); + type = 'meg'; + end + + elseif iselec + % probably this is EEG + if (mean(ismember(ft_senslabel('biosemi256'), sens.label)) > 0.8) + type = 'biosemi256'; + elseif (mean(ismember(ft_senslabel('biosemi128'), sens.label)) > 0.8) + type = 'biosemi128'; + elseif (mean(ismember(ft_senslabel('biosemi64'), sens.label)) > 0.8) + type = 'biosemi64'; + elseif (mean(ismember(ft_senslabel('egi256'), sens.label)) > 0.8) + type = 'egi256'; + elseif (mean(ismember(ft_senslabel('egi128'), sens.label)) > 0.8) + type = 'egi128'; + elseif (mean(ismember(ft_senslabel('egi64'), sens.label)) > 0.8) + type = 'egi64'; + elseif (mean(ismember(ft_senslabel('egi32'), sens.label)) > 0.8) + type = 'egi32'; + elseif (sum(ismember(sens.label, ft_senslabel('eeg1005'))) > 10) % Otherwise it's not even worth recognizing + type = 'ext1020'; + else + type = 'electrode'; + end + + elseif islabel + % look only at the channel labels + if (mean(ismember(ft_senslabel('ctf275'), sens.label)) > 0.8) + type = 'ctf275'; + elseif (mean(ismember(ft_senslabel('ctfheadloc'), sens.label)) > 0.8) % look at the head localization channels + type = 'ctf275'; + elseif (mean(ismember(ft_senslabel('ctf151'), sens.label)) > 0.8) + type = 'ctf151'; + elseif (mean(ismember(ft_senslabel('ctf64'), sens.label)) > 0.8) + type = 'ctf64'; + elseif (mean(ismember(ft_senslabel('ctf275_planar'), sens.label)) > 0.8) + type = 'ctf275_planar'; + elseif (mean(ismember(ft_senslabel('ctf151_planar'), sens.label)) > 0.8) + type = 'ctf151_planar'; + elseif (mean(ismember(ft_senslabel('bti248'), sens.label)) > 0.8) + type = 'bti248'; + elseif (mean(ismember(ft_senslabel('bti148'), sens.label)) > 0.8) + type = 'bti148'; + elseif (mean(ismember(ft_senslabel('bti248_planar'), sens.label)) > 0.8) + type = 'bti248_planar'; + elseif (mean(ismember(ft_senslabel('bti148_planar'), sens.label)) > 0.8) + type = 'bti148_planar'; + elseif (mean(ismember(ft_senslabel('itab153'), sens.label)) > 0.8) + type = 'itab153'; + elseif (mean(ismember(ft_senslabel('itab153_planar'), sens.label)) > 0.8) + type = 'itab153_planar'; + elseif (mean(ismember(ft_senslabel('yokogawa160'), sens.label)) > 0.4) + type = 'yokogawa160'; + elseif (mean(ismember(ft_senslabel('yokogawa160_planar'), sens.label)) > 0.4) + type = 'yokogawa160_planar'; + elseif (mean(ismember(ft_senslabel('neuromag306'), sens.label)) > 0.8) + type = 'neuromag306'; + elseif (mean(ismember(ft_senslabel('neuromag306alt'),sens.label)) > 0.8) % an alternative set without spaces in the name + type = 'neuromag306'; + elseif (mean(ismember(ft_senslabel('neuromag122'), sens.label)) > 0.8) + type = 'neuromag122'; + elseif (mean(ismember(ft_senslabel('neuromag122alt'),sens.label)) > 0.8) % an alternative set without spaces in the name + type = 'neuromag122'; + elseif (mean(ismember(ft_senslabel('biosemi256'), sens.label)) > 0.8) + type = 'biosemi256'; + elseif (mean(ismember(ft_senslabel('biosemi128'), sens.label)) > 0.8) + type = 'biosemi128'; + elseif (mean(ismember(ft_senslabel('biosemi64'), sens.label)) > 0.8) + type = 'biosemi64'; + elseif (mean(ismember(ft_senslabel('egi256'), sens.label)) > 0.8) + type = 'egi256'; + elseif (mean(ismember(ft_senslabel('egi128'), sens.label)) > 0.8) + type = 'egi128'; + elseif (mean(ismember(ft_senslabel('egi64'), sens.label)) > 0.8) + type = 'egi64'; + elseif (mean(ismember(ft_senslabel('egi32'), sens.label)) > 0.8) + type = 'egi32'; + elseif (sum(ismember(sens.label, ft_senslabel('eeg1005'))) > 10) % Otherwise it's not even worth recognizing + type = 'ext1020'; + elseif any(ismember(ft_senslabel('btiref'), sens.label)) + type = 'bti'; % it might be 148 or 248 channels + elseif any(ismember(ft_senslabel('ctfref'), sens.label)) + type = 'ctf'; % it might be 151 or 275 channels + end + + end % look at label, ori and/or pnt +end % if isfield(sens, 'type') + +if ~isempty(desired) + % return a boolean flag + switch desired + case 'eeg' + type = any(strcmp(type, {'eeg' 'electrode' 'biosemi64' 'biosemi128' 'biosemi256' 'egi32' 'egi64' 'egi128' 'egi256' 'ext1020'})); + case 'biosemi' + type = any(strcmp(type, {'biosemi64' 'biosemi128' 'biosemi256'})); + case 'egi' + type = any(strcmp(type, {'egi64' 'egi128' 'egi256'})); + case 'meg' + type = any(strcmp(type, {'meg' 'magnetometer' 'ctf' 'bti' 'ctf151' 'ctf275' 'ctf151_planar' 'ctf275_planar' 'neuromag122' 'neuromag306' 'bti148' 'bti148_planar' 'bti248' 'bti248_planar' 'yokogawa160' 'yokogawa160_planar'})); + case 'ctf' + type = any(strcmp(type, {'ctf' 'ctf151' 'ctf275' 'ctf151_planar' 'ctf275_planar'})); + case 'bti' + type = any(strcmp(type, {'bti' 'bti148' 'bti148_planar' 'bti248' 'bti248_planar'})); + case 'neuromag' + type = any(strcmp(type, {'neuromag122' 'neuromag306'})); + case 'yokogawa' + type = any(strcmp(type, {'yokogawa160' 'yokogawa160_planar'})); + case 'itab' + type = any(strcmp(type, {'itab' 'itab153' 'itab153_planar'})); + case 'meg_axial' + % note that neuromag306 is mixed planar and axial + type = any(strcmp(type, {'magnetometer' 'neuromag306' 'ctf151' 'ctf275' 'bti148' 'bti248' 'yokogawa160'})); + case 'meg_planar' + % note that neuromag306 is mixed planar and axial + type = any(strcmp(type, {'neuromag122' 'neuromag306' 'ctf151_planar' 'ctf275_planar' 'bti148_planar' 'bti248_planar' 'yokogawa160_planar'})); + otherwise + type = any(strcmp(type, desired)); + end % switch desired +end % detemine the correspondence to the desired type + +% remember the current input and output arguments, so that they can be +% reused on a subsequent call in case the same input argument is given +current_argout = {type}; +if isempty(previous_argin) + previous_argin = current_argin; + previous_argout = current_argout; +end + +return % ft_senstype main() diff --git a/external/fieldtrip/inverse/private/ft_voltype.m b/external/fieldtrip/inverse/private/ft_voltype.m new file mode 100644 index 0000000..ede027d --- /dev/null +++ b/external/fieldtrip/inverse/private/ft_voltype.m @@ -0,0 +1,107 @@ +function [type] = ft_voltype(vol, desired) + +% FT_VOLTYPE determines the type of volume conduction model +% +% Use as +% [type] = ft_voltype(vol) +% to get a string describing the type, or +% [flag] = ft_voltype(vol, desired) +% to get a boolean value. +% +% See also FT_READ_VOL, FT_COMPUTE_LEADFIELD + +% Copyright (C) 2007-2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_voltype.m 946 2010-04-21 17:51:16Z roboos $ + +% these are for remembering the type on subsequent calls with the same input arguments +persistent previous_argin previous_argout + +if iscell(vol) && numel(vol)<4 + % this might represent combined EEG, ECoG and/or MEG + type = cell(size(vol)); + if nargin<2 + desired = cell(size(vol)); % empty elements + end + for i=1:numel(vol) + type{i} = ft_voltype(vol{i}, desired{i}); + end + return +end + +if nargin<2 + % ensure that all input arguments are defined + desired = []; +end + +current_argin = {vol, desired}; +if isequal(current_argin, previous_argin) + % don't do the type detection again, but return the previous values from cache + type = previous_argout{1}; + return +end + +if isfield(vol, 'type') + % preferably the structure specifies its own type + type = vol.type; + +elseif isfield(vol, 'r') && numel(vol.r)==1 && ~isfield(vol, 'label') + type = 'singlesphere'; + +elseif isfield(vol, 'r') && isfield(vol, 'o') && isfield(vol, 'label') + % this is before the spheres have been assigned to the coils + % and every sphere is still associated with a channel + type = 'multisphere'; + +elseif isfield(vol, 'r') && isfield(vol, 'o') && size(vol.r,1)==size(vol.o,1) && size(vol.r,1)>4 + % this is after the spheres have been assigned to the coils + % note that this one is easy to confuse with the concentric one + type = 'multisphere'; + +elseif isfield(vol, 'r') && numel(vol.r)>=2 && ~isfield(vol, 'label') + type = 'concentric'; + +elseif isfield(vol, 'bnd') + type = 'bem'; + +elseif isempty(vol) + type = 'infinite'; + +else + type = 'unknown'; + +end % if isfield(vol, 'type') + +if ~isempty(desired) + % return a boolean flag + switch desired + case 'bem' + type = any(strcmp(type, {'bem', 'dipoli', 'asa', 'avo', 'bemcp', 'openmeeg'})); + otherwise + type = any(strcmp(type, desired)); + end +end + +% remember the current input and output arguments, so that they can be +% reused on a subsequent call in case the same input argument is given +current_argout = {type}; +previous_argin = current_argin; +previous_argout = current_argout; + +return % voltype main() diff --git a/external/fieldtrip/inverse/private/getsubfield.m b/external/fieldtrip/inverse/private/getsubfield.m new file mode 100644 index 0000000..690e299 --- /dev/null +++ b/external/fieldtrip/inverse/private/getsubfield.m @@ -0,0 +1,45 @@ +function [s] = getsubfield(s, f); + +% GETSUBFIELD returns a field from a structure just like the standard +% Matlab GETFIELD function, except that you can also specify nested fields +% using a '.' in the fieldname. The nesting can be arbitrary deep. +% +% Use as +% f = getsubfield(s, 'fieldname') +% or as +% f = getsubfield(s, 'fieldname.subfieldname') +% +% See also GETFIELD, ISSUBFIELD, SETSUBFIELD + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: getsubfield.m 951 2010-04-21 18:24:01Z roboos $ + +if ~isstr(f) + error('incorrect input argument for fieldname'); +end + +t = {}; +while (1) + [t{end+1}, f] = strtok(f, '.'); + if isempty(f) + break + end +end +s = getfield(s, t{:}); diff --git a/external/fieldtrip/inverse/private/hastoolbox.m b/external/fieldtrip/inverse/private/hastoolbox.m new file mode 100644 index 0000000..311bb7e --- /dev/null +++ b/external/fieldtrip/inverse/private/hastoolbox.m @@ -0,0 +1,321 @@ +function [status] = hastoolbox(toolbox, autoadd, silent) + +% HASTOOLBOX tests whether an external toolbox is installed. Optionally +% it will try to determine the path to the toolbox and install it +% automatically. +% +% Use as +% [status] = hastoolbox(toolbox, autoadd, silent) +% +% autoadd = 0 means that it will not be added +% autoadd = 1 means that give an error if it cannot be added +% autoadd = 2 means that give a warning if it cannot be added +% autoadd = 3 means that it try to add it silently + +% Copyright (C) 2005-2010, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: hastoolbox.m 1411 2010-07-14 11:00:12Z jansch $ + +% this function is called many times in FieldTrip and associated toolboxes +% use efficient handling if the same toolbox has been investigated before +persistent previous previouspath + +if ~isequal(previouspath, matlabpath) + previous = []; +end + +if isempty(previous) + previous = struct; +elseif isfield(previous, fixname(toolbox)) + status = previous.(fixname(toolbox)); + return +end + +% this points the user to the website where he/she can download the toolbox +url = { + 'AFNI' 'see http://afni.nimh.nih.gov' + 'DSS' 'see http://www.cis.hut.fi/projects/dss' + 'EEGLAB' 'see http://www.sccn.ucsd.edu/eeglab' + 'NWAY' 'see http://www.models.kvl.dk/source/nwaytoolbox' + 'SPM99' 'see http://www.fil.ion.ucl.ac.uk/spm' + 'SPM2' 'see http://www.fil.ion.ucl.ac.uk/spm' + 'SPM5' 'see http://www.fil.ion.ucl.ac.uk/spm' + 'SPM8' 'see http://www.fil.ion.ucl.ac.uk/spm' + 'MEG-PD' 'see http://www.kolumbus.fi/kuutela/programs/meg-pd' + 'MEG-CALC' 'this is a commercial toolbox from Neuromag, see http://www.neuromag.com' + 'BIOSIG' 'see http://biosig.sourceforge.net' + 'EEG' 'see http://eeg.sourceforge.net' + 'EEGSF' 'see http://eeg.sourceforge.net' % alternative name + 'MRI' 'see http://eeg.sourceforge.net' % alternative name + 'NEUROSHARE' 'see http://www.neuroshare.org' + 'BESA' 'see http://www.megis.de, or contact Karsten Hoechstetter' + 'EEPROBE' 'see http://www.ant-neuro.com, or contact Maarten van der Velde' + 'YOKOGAWA' 'see http://www.yokogawa.co.jp, or contact Nobuhiko Takahashi' + 'BEOWULF' 'see http://oostenveld.net, or contact Robert Oostenveld' + 'MENTAT' 'see http://oostenveld.net, or contact Robert Oostenveld' + 'SON2' 'see http://www.kcl.ac.uk/depsta/biomedical/cfnr/lidierth.html, or contact Malcolm Lidierth' + '4D-VERSION' 'contact Christian Wienbruch' + 'SIGNAL' 'see http://www.mathworks.com/products/signal' + 'OPTIM' 'see http://www.mathworks.com/products/optim' + 'IMAGE' 'see http://www.mathworks.com/products/image' + 'SPLINES' 'see http://www.mathworks.com/products/splines' + 'FASTICA' 'see http://www.cis.hut.fi/projects/ica/fastica' + 'BRAINSTORM' 'see http://neuroimage.ucs.edu/brainstorm' + 'FILEIO' 'see http://www.ru.nl/neuroimaging/fieldtrip' + 'FORWINV' 'see http://www.ru.nl/neuroimaging/fieldtrip' + 'PLOTTING' 'see http://www.ru.nl/neuroimaging/fieldtrip' + 'DENOISE' 'see http://lumiere.ens.fr/Audition/adc/meg, or contact Alain de Cheveigne' + 'BCI2000' 'see http://bci2000.org' + 'NLXNETCOM' 'see http://www.neuralynx.com' + 'DIPOLI' 'see ftp://ftp.fcdonders.nl/pub/fieldtrip/external' + 'MNE' 'see http://www.nmr.mgh.harvard.edu/martinos/userInfo/data/sofMNE.php' + 'TCP_UDP_IP' 'see http://www.mathworks.com/matlabcentral/fileexchange/345, or contact Peter Rydes?ter' + 'BEMCP' 'contact Christophe Phillips' + 'OPENMEEG' 'see http://gforge.inria.fr/projects/openmeeg' + 'PRTOOLS' 'see http://www.prtools.org' + 'ITAB' 'contact Stefania Della Penna' + 'BSMART' 'see http://www.brain-smart.org' + 'PEER' 'see http://fieldtrip.fcdonders.nl/development/peer' + }; + +if nargin<2 + % default is not to add the path automatically + autoadd = 0; +end + +if nargin<3 + % default is not to be silent + silent = 0; +end + +% determine whether the toolbox is installed +toolbox = upper(toolbox); +switch toolbox + case 'AFNI' + status = (exist('BrikLoad') && exist('BrikInfo')); + case 'DSS' + status = exist('dss', 'file') && exist('dss_create_state', 'file'); + case 'EEGLAB' + status = exist('runica', 'file'); + case 'NWAY' + status = exist('parafac', 'file'); + case 'SPM99' + status = exist('spm.m') && strcmp(spm('ver'),'SPM99'); + case 'SPM2' + status = exist('spm.m') && strcmp(spm('ver'),'SPM2'); + case 'SPM5' + status = exist('spm.m') && strcmp(spm('ver'),'SPM5'); + case 'SPM8' + status = exist('spm.m') && strncmp(spm('ver'),'SPM8', 4); + case 'MEG-PD' + status = (exist('rawdata') && exist('channames')); + case 'MEG-CALC' + status = (exist('megmodel') && exist('megfield') && exist('megtrans')); + case 'BIOSIG' + status = (exist('sopen') && exist('sread')); + case 'EEG' + status = (exist('ctf_read_res4') && exist('ctf_read_meg4')); + case 'EEGSF' % alternative name + status = (exist('ctf_read_res4') && exist('ctf_read_meg4')); + case 'MRI' % other functions in the mri section + status = (exist('avw_hdr_read') && exist('avw_img_read')); + case 'NEUROSHARE' + status = (exist('ns_OpenFile') && exist('ns_SetLibrary') && exist('ns_GetAnalogData')); + case 'BESA' + status = (exist('readBESAtfc') && exist('readBESAswf')); + case 'EEPROBE' + status = (exist('read_eep_avr') && exist('read_eep_cnt')); + case 'YOKOGAWA' + status = hasyokogawa('16bitBeta6'); + case 'BEOWULF' + status = (exist('evalwulf') && exist('evalwulf') && exist('evalwulf')); + case 'MENTAT' + status = (exist('pcompile') && exist('pfor') && exist('peval')); + case 'SON2' + status = (exist('SONFileHeader') && exist('SONChanList') && exist('SONGetChannel')); + case '4D-VERSION' + status = (exist('read4d') && exist('read4dhdr')); + case 'SIGNAL' + status = hasfunction('medfilt1', toolbox) && exist('butter', 'file'); % also check the availability of a toolbox license + case 'OPTIM' + status = hasfunction('fmincon', toolbox) && exist('fminunc', 'file'); % also check the availability of a toolbox license + case 'SPLINES' + status = hasfunction('bspline', toolbox) && exist('csape', 'file'); % also check the availability of a toolbox license + case 'IMAGE' + status = hasfunction('bwlabeln', toolbox); % also check the availability of a toolbox license + case 'FASTICA' + status = exist('fastica', 'file'); + case 'BRAINSTORM' + status = exist('bem_xfer'); + case 'FILEIO' + status = (exist('read_header') && exist('read_data') && exist('read_event') && exist('read_sens')); + case 'FORWINV' + status = (exist('compute_leadfield') && exist('prepare_vol_sens')); + case 'DENOISE' + status = (exist('tsr') && exist('sns')); + case 'CTF' + status = (exist('getCTFBalanceCoefs') && exist('getCTFdata')); + case 'BCI2000' + status = exist('load_bcidat'); + case 'NLXNETCOM' + status = (exist('MatlabNetComClient') && exist('NlxConnectToServer') && exist('NlxGetNewCSCData')); + case 'DIPOLI' + status = exist('dipoli.m', 'file'); + case 'MNE' + status = (exist('fiff_read_meas_info', 'file') && exist('fiff_setup_read_raw', 'file')); + case 'TCP_UDP_IP' + status = (exist('pnet', 'file') && exist('pnet_getvar', 'file') && exist('pnet_putvar', 'file')); + case 'BEMCP' + status = (exist('bem_Cij_cog', 'file') && exist('bem_Cij_lin', 'file') && exist('bem_Cij_cst', 'file')); + case 'OPENMEEG' + status = exist('openmeeg.m', 'file'); + case 'PLOTTING' + status = (exist('plot_topo', 'file') && exist('plot_mesh', 'file') && exist('plot_matrix', 'file')); + case 'PRTOOLS' + status = (exist('prversion', 'file') && exist('dataset', 'file') && exist('svc', 'file')); + case 'ITAB' + status = (exist('lcReadHeader', 'file') && exist('lcReadData', 'file')); + case 'BSMART' + status = exist('bsmart'); + case 'PEER' + status = exist('peerslave', 'file') && exist('peermaster', 'file'); + case 'CONNECTIVITY' + status = exist('ft_connectivity_corr', 'file') && exist('ft_connectivity_granger', 'file'); + otherwise + if ~silent, warning(sprintf('cannot determine whether the %s toolbox is present', toolbox)); end + status = 0; +end + +% it should be a boolean value +status = (status~=0); + +% try to determine the path of the requested toolbox +if autoadd>0 && ~status + + % for core fieldtrip modules + prefix = fileparts(which('fieldtripdefs')); + if ~status + status = myaddpath(fullfile(prefix, lower(toolbox)), silent); + end + + % for external fieldtrip modules + prefix = fullfile(fileparts(which('fieldtripdefs')), 'external'); + if ~status + status = myaddpath(fullfile(prefix, lower(toolbox)), silent); + end + + % for linux computers in the F.C. Donders Centre + prefix = '/home/common/matlab'; + if ~status && (strcmp(computer, 'GLNX86') || strcmp(computer, 'GLNXA64')) + status = myaddpath(fullfile(prefix, lower(toolbox)), silent); + end + + % for windows computers in the F.C. Donders Centre + prefix = 'h:\common\matlab'; + if ~status && (strcmp(computer, 'PCWIN') || strcmp(computer, 'PCWIN64')) + status = myaddpath(fullfile(prefix, lower(toolbox)), silent); + end + + % use the matlab subdirectory in your homedirectory, this works on unix and mac + prefix = [getenv('HOME') '/matlab']; + if ~status + status = myaddpath(fullfile(prefix, lower(toolbox)), silent); + end + + if ~status + % the toolbox is not on the path and cannot be added + sel = find(strcmp(url(:,1), toolbox)); + if ~isempty(sel) + msg = sprintf('the %s toolbox is not installed, %s', toolbox, url{sel, 2}); + else + msg = sprintf('the %s toolbox is not installed', toolbox); + end + if autoadd==1 + error(msg); + elseif autoadd==2 + warning(msg); + else + % fail silently + end + end +end + +% this function is called many times in FieldTrip and associated toolboxes +% use efficient handling if the same toolbox has been investigated before +if status + previous.(fixname(toolbox)) = status; +end + +% remember the previous path, allows us to determine on the next call +% whether the path has been modified outise of this function +previouspath = matlabpath; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% helper function +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function status = myaddpath(toolbox, silent) +if exist(toolbox, 'dir') + if ~silent, warning(sprintf('adding %s toolbox to your Matlab path', toolbox)); end + addpath(toolbox); + status = 1; +else + status = 0; +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% helper function +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function out = fixname(toolbox) +out = lower(toolbox); +out(out=='-') = '_'; % fix dashes +out(out==' ') = '_'; % fix spaces +out(out=='/') = '_'; % fix forward slashes +out(out=='\') = '_'; % fix backward slashes + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% helper function +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function status = hasfunction(funname, toolbox) +try + % call the function without any input arguments, which probably is inapropriate + feval(funname); + % it might be that the function without any input already works fine + status = true; +catch + % either the function returned an error, or the function is not available + % availability is influenced by the function being present and by having a + % license for the function, i.e. in a concurrent licensing setting it might + % be that all toolbox licenses are in use + m = lasterror; + if strcmp(m.identifier, 'MATLAB:license:checkouterror') + if nargin>1 + warning('the %s toolbox is available, but you don''t have a license for it', toolbox); + else + warning('the function ''%s'' is available, but you don''t have a license for it', funname); + end + status = false; + elseif strcmp(m.identifier, 'MATLAB:UndefinedFunction') + status = false; + else + % the function seems to be available and it gave an unknown error, + % which is to be expected with inappropriate input arguments + status = true; + end +end + diff --git a/external/fieldtrip/inverse/private/issubfield.m b/external/fieldtrip/inverse/private/issubfield.m new file mode 100644 index 0000000..ff54060 --- /dev/null +++ b/external/fieldtrip/inverse/private/issubfield.m @@ -0,0 +1,42 @@ +function [r] = issubfield(s, f) + +% ISSUBFIELD tests for the presence of a field in a structure just like the standard +% Matlab ISFIELD function, except that you can also specify nested fields +% using a '.' in the fieldname. The nesting can be arbitrary deep. +% +% Use as +% f = issubfield(s, 'fieldname') +% or as +% f = issubfield(s, 'fieldname.subfieldname') +% +% This function returns true if the field is present and false if the field +% is not present. +% +% See also ISFIELD, GETSUBFIELD, SETSUBFIELD + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: issubfield.m 951 2010-04-21 18:24:01Z roboos $ + +try + getsubfield(s, f); % if this works, then the subfield must be present + r = true; +catch + r = false; % apparently the subfield is not present +end diff --git a/external/fieldtrip/inverse/private/keyval.m b/external/fieldtrip/inverse/private/keyval.m new file mode 100644 index 0000000..36422c0 --- /dev/null +++ b/external/fieldtrip/inverse/private/keyval.m @@ -0,0 +1,70 @@ +function [val, remaining] = keyval(key, varargin) + +% KEYVAL returns the value that corresponds to the requested key in a +% key-value pair list of variable input arguments +% +% Use as +% [val] = keyval(key, varargin) +% +% See also VARARGIN + +% Copyright (C) 2005-2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: keyval.m 1394 2010-07-10 21:02:48Z roboos $ + +if length(varargin)==1 && iscell(varargin{1}) + varargin = varargin{1}; +end + +if mod(length(varargin),2) + error('optional input arguments should come in key-value pairs, i.e. there should be an even number'); +end + +% the 1st, 3rd, etc. contain the keys, the 2nd, 4th, etc. contain the values +keys = varargin(1:2:end); +vals = varargin(2:2:end); + +% the following is faster than cellfun(@isstr, keys) +valid = false(size(keys)); +for i=1:numel(keys) + valid = ischar(keys{i}); +end + +if ~all(valid) + error('optional input arguments should come in key-value pairs, the optional input argument %d is invalid (should be a string)', i); +end + +hit = find(strcmpi(key, keys)); +if isempty(hit) + % the requested key was not found + val = []; +elseif length(hit)==1 + % the requested key was found + val = vals{hit}; +else + error('multiple input arguments with the same name'); +end + +if nargout>1 + % return the remaining input arguments with the key-value pair removed + keys(hit) = []; + vals(hit) = []; + remaining = cat(1, keys(:)', vals(:)'); + remaining = remaining(:)'; +end diff --git a/external/fieldtrip/inverse/private/progress.m b/external/fieldtrip/inverse/private/progress.m new file mode 100644 index 0000000..b39afd9 --- /dev/null +++ b/external/fieldtrip/inverse/private/progress.m @@ -0,0 +1,247 @@ +function progress(varargin) + +% PROGRESS shows a graphical or non-graphical progress indication similar +% to the standard Matlab WAITBAR function, but with the extra option of +% printing it in the command window as a plain text string or as a rotating +% dial. Alternatively, you can also specify it not to give feedback on the +% progress. +% +% Prior to the for-loop, you should call either +% progress('init', 'none', 'Please wait...') +% progress('init', 'gui', 'Please wait...') +% progress('init', 'etf', 'Please wait...') % estimated time to finish +% progress('init', 'dial', 'Please wait...') % rotating dial +% progress('init', 'textbar', 'Please wait...') % ascii progress bar +% progress('init', 'text', 'Please wait...') +% progress('init', 'textcr', 'Please wait...') % force cariage return +% progress('init', 'textnl', 'Please wait...') % force newline +% +% In each iteration of the for-loop, you should call either +% progress(x) % only show percentage +% progress(x, 'Processing event %d from %d', i, N) % show string, x=i/N +% +% After finishing the for-loop, you should call +% progress('close') +% +% Here is an example for the use of a progress indicator +% progress('init', 'etf', 'Please wait...'); +% for i=1:42 +% progress(i/42, 'Processing event %d from %d', i, 42); +% pause(0.1); +% end +% progress('close') + +% Copyright (C) 2004-2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: progress.m 951 2010-04-21 18:24:01Z roboos $ + +persistent p % the previous value of the progress +persistent c % counter for the number of updates that is done +persistent t0 % initial time, required for ETF +persistent p0 % initial percentage, required for ETF +persistent t % type of feedback, string with none, gui, text, textcr, textnl +persistent h % the handle of the dialog (in case of type=gui) +persistent a % the angle in degrees, for dial or textbar +persistent s % the string containing the title + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +if nargin>1 && ischar(varargin{1}) && strcmp(varargin{1}, 'init') + a = 0; + p = 0; + h = 0; + c = 0; + % determine the type of feedback + t = varargin{2}; + % determine the title of the dialog + if nargin>2 + s = varargin{3}; + else + s = ''; + end + switch t + case 'gui' + % initialise the waitbar dialog + if ~isempty(s) + h = waitbar(0, s); + else + h = waitbar(0, 'Please wait'); + end + case {'text', 'textnl', 'textcr'} + if ~isempty(s) + % print the title to the screen and go to the next line + fprintf('%s\n', s) + end + end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +elseif nargin==1 && ischar(varargin{1}) && strcmp(varargin{1}, 'close') + switch t + case 'gui' + % close the waitbar dialog + close(h); + case {'textcr', 'dial', 'textbar'} + % finish by going to the next line + fprintf('\n'); + end + % reset these to the defaults + a = 0; + h = 0; + p = 0; + t = 'none'; + s = ''; + t0 = []; + p0 = []; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +else + if strcmp(t, 'dial') + % display should always be updated for the dial + % continue; + elseif (varargin{1}-p)<0.01 && strcmp(t, 'gui') + % display should not be updated it the difference is less than one percent + return; + elseif (varargin{1}-p)<0.01 && strcmp(t, 'textbar') + % display should not be updated it the difference is less than one percent + return; + elseif (varargin{1}-p)<0.01 && strcmp(t, 'etf') + % display should not be updated it the difference is less than one percent + return; + end + + % count the number of updates, for debugging + c = c+1; + + % remember the current value for the next function call + p = varargin{1}; + + switch t + case 'gui' + % update the the length of the bar in the waitbar dialog + waitbar(varargin{1}, h); + + case 'etf' + % compute the estimated time that the computation still needs to finish + if isempty(t0) || isempty(p0) + t0 = clock; + p0 = p; + end + elapsed = etime(clock, t0); + if nargin>1 && ~isempty(varargin{2}) + % include the specified string + fprintf(varargin{2:end}); + fprintf(' - estimated time to finish is %d seconds\n', round(elapsed*(1-p)/(p-p0))); + else + % only print the estimated time to finish + fprintf(' - estimated time to finish is %d seconds\n', round(elapsed*(1-p)/(p-p0))); + end + + case 'dial' + dial = '|/-\|/-\'; + if ~isempty(s) + % print the title and draw a new hand of the rotating dial + fprintf('\r%s %s', s, dial(1+a/45)); + else + % draw a new hand of the rotating dial + fprintf('\r%s', dial(1+a/45)); + end + % increment the angle with 45 degrees + a = a + 45; + if a==360 + % reset the angle to 0 degrees + a = 0; + end + + case 'textbar' + dial = '|/-\|/-\'; + % construct the line looking like [------/ ] + len = 75 - length(s) - 3; + len1 = round(p*len); % number of '-' characters before the dial + len2 = len - len1; % number of ' ' characters after the dial + line = [s, ' [' repmat('-',1,len1), dial(1+a/45), repmat(' ',1,len2) ,']']; + fprintf('\r%s', line); + % increment the angle with 45 degrees + a = a + 45; + if a==360 + % reset the angle to 0 degrees + a = 0; + end + + case 'text' + if nargin>1 + % print the string as it is + fprintf(varargin{2:end}); + else + fprintf('%6.2f %%\n', 100*varargin{1}); + end + + case 'textnl' + if nargin>1 + % ensure that the string ends with a newline + if length(varargin{2})>1 && all(varargin{2}((end-1):end) == '\r') + varargin{2}((end-1):end) = '\n'; + elseif length(varargin{2})>1 && ~all(varargin{2}((end-1):end) == '\n') + varargin{2}((end+1):(end+2)) = '\n'; + elseif length(varargin{2})<2 + varargin{2}((end+1):(end+2)) = '\n'; + end + fprintf(varargin{2:end}); + else + fprintf('%6.2f %%\n', 100*varargin{1}); + end + + case 'textcr' + if nargin>1 + % ensure that the string ends with a cariage return + if length(varargin{2})>1 && all(varargin{2}((end-1):end) == '\n') + varargin{2}((end-1):end) = '\r'; + elseif length(varargin{2})>1 && ~all(varargin{2}((end-1):end) == '\r') + varargin{2}((end+1):(end+2)) = '\r'; + elseif length(varargin{2})<2 + varargin{2}((end+1):(end+2)) = '\r'; + end + fprintf(varargin{2:end}); + else + fprintf('%6.2f %%\r', 100*varargin{1}); + end + + end % case gui, dial, text, textnl, textcr +end % updating the displayed value + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% some test code follows +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% progress('init', 'gui'); for i=1:100, progress(i/100, '%d/%d\r', i, 100); end; progress('close') +% progress('init', 'dial'); for i=1:100, progress(i/100, '%d/%d\r', i, 100); end; progress('close') +% progress('init', 'none'); for i=1:100, progress(i/100, '%d/%d\r', i, 100); end; progress('close') + +% progress('init', 'text'); for i=1:100, progress(i/100, '%d/%d' , i, 100); end; progress('close') +% progress('init', 'text'); for i=1:100, progress(i/100, '%d/%d\n', i, 100); end; progress('close') +% progress('init', 'text'); for i=1:100, progress(i/100, '%d/%d\r', i, 100); end; progress('close') + +% progress('init', 'textnl'); for i=1:100, progress(i/100, '%d/%d' , i, 100); end; progress('close') +% progress('init', 'textnl'); for i=1:100, progress(i/100, '%d/%d\n', i, 100); end; progress('close') +% progress('init', 'textnl'); for i=1:100, progress(i/100, '%d/%d\r', i, 100); end; progress('close') + +% progress('init', 'textcr'); for i=1:100, progress(i/100, '%d/%d' , i, 100); end; progress('close') +% progress('init', 'textcr'); for i=1:100, progress(i/100, '%d/%d\n', i, 100); end; progress('close') +% progress('init', 'textcr'); for i=1:100, progress(i/100, '%d/%d\r', i, 100); end; progress('close') + + diff --git a/external/fieldtrip/inverse/private/rmsubfield.m b/external/fieldtrip/inverse/private/rmsubfield.m new file mode 100644 index 0000000..4d8752f --- /dev/null +++ b/external/fieldtrip/inverse/private/rmsubfield.m @@ -0,0 +1,46 @@ +function [s] = rmsubfield(s, f, v); + +% RMSUBFIELD removes the contents of the specified field from a structure +% just like the standard Matlab RMFIELD function, except that you can also +% specify nested fields using a '.' in the fieldname. The nesting can be +% arbitrary deep. +% +% Use as +% s = rmsubfield(s, 'fieldname') +% or as +% s = rmsubfield(s, 'fieldname.subfieldname') +% +% See also SETFIELD, GETSUBFIELD, ISSUBFIELD + +% Copyright (C) 2006, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: rmsubfield.m 951 2010-04-21 18:24:01Z roboos $ + +if ~isstr(f) + error('incorrect input argument for fieldname'); +end + +% remove the nested subfield using recursion +[t, f] = strtok(f, '.'); +if any(f=='.') + u = rmsubfield(getfield(s, t), f); + s = setfield(s, t, u); +else + s = rmfield(s, t); +end diff --git a/external/fieldtrip/inverse/private/setsubfield.m b/external/fieldtrip/inverse/private/setsubfield.m new file mode 100644 index 0000000..18f4793 --- /dev/null +++ b/external/fieldtrip/inverse/private/setsubfield.m @@ -0,0 +1,46 @@ +function [s] = setsubfield(s, f, v); + +% SETSUBFIELD sets the contents of the specified field to a specified value +% just like the standard Matlab SETFIELD function, except that you can also +% specify nested fields using a '.' in the fieldname. The nesting can be +% arbitrary deep. +% +% Use as +% s = setsubfield(s, 'fieldname', value) +% or as +% s = setsubfield(s, 'fieldname.subfieldname', value) +% +% See also SETFIELD, GETSUBFIELD, ISSUBFIELD + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: setsubfield.m 951 2010-04-21 18:24:01Z roboos $ + +if ~isstr(f) + error('incorrect input argument for fieldname'); +end + +t = {}; +while (1) + [t{end+1}, f] = strtok(f, '.'); + if isempty(f) + break + end +end +s = setfield(s, t{:}, v); diff --git a/external/fieldtrip/inverse/private/solid_angle.c b/external/fieldtrip/inverse/private/solid_angle.c new file mode 100644 index 0000000..cb379e0 --- /dev/null +++ b/external/fieldtrip/inverse/private/solid_angle.c @@ -0,0 +1,69 @@ +#include +#include "mex.h" +#include "matrix.h" +#include "geometry.h" + +void +mexFunction (int nlhs, mxArray * plhs[], int nrhs, const mxArray * prhs[]) +{ + char str[256]; + mxArray *sa; + double *v1, *v2, *v3, p1[3], p2[3], p3[3], *pnt, *tri, *sa_p; + int i1, i2, i3, npnt, ntri, i, on_triangle; + + if (nrhs==2) + { + /* the input consists of a vertex array and a triangle array */ + if (mxGetN(prhs[0])!=3) + mexErrMsgTxt ("Invalid dimension for input argument 1"); + if (mxGetN(prhs[1])!=3) + mexErrMsgTxt ("Invalid dimension for input argument 2"); + npnt = mxGetM(prhs[0]); + ntri = mxGetM(prhs[1]); + pnt = mxGetData (prhs[0]); + tri = mxGetData (prhs[1]); + sa = mxCreateDoubleMatrix (ntri, 1, mxREAL); + sa_p = mxGetData (sa); + /* compute the solid angle for all triangles */ + for (i=0; i. +% +% $Id: solid_angle.m 946 2010-04-21 17:51:16Z roboos $ + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% The first section contains the plain Matlab implementation. The mex file +% is many times faster and this function is called so frequently (for +% large meshes), that the mex file should be used in all practical cases. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% function [w] = solid_angle(r1, r2, r3); +% +% if nargin==2 +% % reassign the input arguments +% pnt = r1; +% tri = r2; +% npnt = size(pnt,1); +% ntri = size(tri,1); +% w = zeros(ntri,1); +% % compute solid angle for each triangle +% for i=1:ntri +% r1 = pnt(tri(i,1),:); +% r2 = pnt(tri(i,2),:); +% r3 = pnt(tri(i,3),:); +% w(i) = solid_angle(r1, r2, r3); +% end +% return +% elseif nargin==3 +% % compute the solid angle for this triangle +% cp23_x = r2(2) * r3(3) - r2(3) * r3(2); +% cp23_y = r2(3) * r3(1) - r2(1) * r3(3); +% cp23_z = r2(1) * r3(2) - r2(2) * r3(1); +% nom = cp23_x * r1(1) + cp23_y * r1(2) + cp23_z * r1(3); +% n1 = sqrt (r1(1) * r1(1) + r1(2) * r1(2) + r1(3) * r1(3)); +% n2 = sqrt (r2(1) * r2(1) + r2(2) * r2(2) + r2(3) * r2(3)); +% n3 = sqrt (r3(1) * r3(1) + r3(2) * r3(2) + r3(3) * r3(3)); +% ip12 = r1(1) * r2(1) + r1(2) * r2(2) + r1(3) * r2(3); +% ip23 = r2(1) * r3(1) + r2(2) * r3(2) + r2(3) * r3(3); +% ip13 = r1(1) * r3(1) + r1(2) * r3(2) + r1(3) * r3(3); +% den = n1 * n2 * n3 + ip12 * n3 + ip23 * n1 + ip13 * n2; +% if (nom == 0) +% if (den <= 0) +% w = nan; +% return +% end +% end +% w = 2 * atan2 (nom, den); +% return +% else +% error('invalid input'); +% end + +% compile the missing mex file on the fly +% remember the original working directory +pwdir = pwd; + +% determine the name and full path of this function +funname = mfilename('fullpath'); +mexsrc = [funname '.c']; +[mexdir, mexname] = fileparts(funname); + +try + % try to compile the mex file on the fly + warning('trying to compile MEX file from %s', mexsrc); + cd(mexdir); + + if ispc + mex -I. -c geometry.c + mex -I. -c solid_angle.c ; mex solid_angle.c solid_angle.obj geometry.obj + else + mex -I. -c geometry.c + mex -I. -c solid_angle.c ; mex -o solid_angle solid_angle.o geometry.o + end + + cd(pwdir); + success = true; + +catch + % compilation failed + disp(lasterr); + error('could not locate MEX file for %s', mexname); + cd(pwdir); + success = false; +end + +if success + % execute the mex file that was juist created + funname = mfilename; + funhandle = str2func(funname); + [varargout{1:nargout}] = funhandle(varargin{:}); +end + diff --git a/external/fieldtrip/inverse/private/solid_angle.mexa64 b/external/fieldtrip/inverse/private/solid_angle.mexa64 new file mode 100755 index 0000000..cbae8f6 Binary files /dev/null and b/external/fieldtrip/inverse/private/solid_angle.mexa64 differ diff --git a/external/fieldtrip/inverse/private/solid_angle.mexglx b/external/fieldtrip/inverse/private/solid_angle.mexglx new file mode 100755 index 0000000..611759d Binary files /dev/null and b/external/fieldtrip/inverse/private/solid_angle.mexglx differ diff --git a/external/fieldtrip/inverse/private/solid_angle.mexmaci b/external/fieldtrip/inverse/private/solid_angle.mexmaci new file mode 100755 index 0000000..26b57e0 Binary files /dev/null and b/external/fieldtrip/inverse/private/solid_angle.mexmaci differ diff --git a/external/fieldtrip/inverse/private/solid_angle.mexmaci64 b/external/fieldtrip/inverse/private/solid_angle.mexmaci64 new file mode 100755 index 0000000..d1c5d61 Binary files /dev/null and b/external/fieldtrip/inverse/private/solid_angle.mexmaci64 differ diff --git a/external/fieldtrip/inverse/private/solid_angle.mexw32 b/external/fieldtrip/inverse/private/solid_angle.mexw32 new file mode 100644 index 0000000..688b8a3 Binary files /dev/null and b/external/fieldtrip/inverse/private/solid_angle.mexw32 differ diff --git a/external/fieldtrip/inverse/private/solid_angle.mexw64 b/external/fieldtrip/inverse/private/solid_angle.mexw64 new file mode 100644 index 0000000..0a6a9a0 Binary files /dev/null and b/external/fieldtrip/inverse/private/solid_angle.mexw64 differ diff --git a/external/fieldtrip/inverse/residualvariance.m b/external/fieldtrip/inverse/residualvariance.m new file mode 100644 index 0000000..3152d6e --- /dev/null +++ b/external/fieldtrip/inverse/residualvariance.m @@ -0,0 +1,76 @@ +function [dipout] = residualvariance(dip, grad, vol, dat, varargin); + +% RESIDUALVARIANCE scan with a single dipole and computes the RV +% at each grid location +% +% Use as +% [dipout] = residualvariance(dip, grad, vol, dat, ...) + +% Copyright (C) 2004-2006, Robert Oostenveld +% +% Subversion does not use the Log keyword, use 'svn log ' or 'svn -v log | less' to get detailled information + +% get the optional settings, or use default value +feedback = keyval('feedback', varargin); if isempty(feedback), feedback = 'text'; end + +% ensure that these are row-vectors +dip.inside = dip.inside(:)'; +dip.outside = dip.outside(:)'; + +Nchan = length(grad.label); +Ndip = length(dip.inside); + +if isfield(dip, 'subspace') + % remember the original data prior to the voxel dependant subspace projection + dat_pre_subspace = dat; + fprintf('using subspace projection\n'); +end + +progress('init', feedback, 'computing inverse'); +for i=1:length(dip.inside) + + progress(i/length(dip.inside), 'computing inverse %d/%d\n', i, length(dip.inside)); + i = dip.inside(i); + + if isfield(dip, 'leadfield') + % reuse the leadfield that was previously computed + lf = dip.leadfield{i}; + else + % compute the leadfield + lf = ft_compute_leadfield(dip.pos(i,:), grad, vol); + end + + if isfield(dip, 'subspace') + % do subspace projection of the forward model + lf = dip.subspace{i} * lf; + % the data and the covariance become voxel dependent due to the projection + dat = dip.subspace{i} * dat_pre_subspace; + end + + % compute spatiotemporal inverse using regional source + lfi = pinv(lf); + mom{i} = lfi * dat; + rv(i) = sum(sum((dat - lf*mom{i}).^2, 1), 2)./sum(sum(dat.^2, 1), 2); + + % for plotting convenience also compute power at each location + % FIXME is this normalization correct? + pow(i) = mean(sum(mom{i}(:).^2, 1)); +end +progress('close'); + +% locations outside the head get assigned an +for i=dip.outside + mom{i} = []; + rv(i) = nan; + pow(i) = nan; +end + +% assign the output data +dipout.mom = mom(:); % ensure that it is a column vector +dipout.rv = rv(:); % ensure that it is a column vector +dipout.pow = pow(:); % ensure that it is a column vector + +% add other descriptive information to the output source model +dipout.pos = dip.pos; +dipout.inside = dip.inside; +dipout.outside = dip.outside; diff --git a/external/fieldtrip/private/loreta2fieldtrip.m b/external/fieldtrip/loreta2fieldtrip.m similarity index 79% rename from external/fieldtrip/private/loreta2fieldtrip.m rename to external/fieldtrip/loreta2fieldtrip.m index e58d868..772f66c 100644 --- a/external/fieldtrip/private/loreta2fieldtrip.m +++ b/external/fieldtrip/loreta2fieldtrip.m @@ -15,15 +15,23 @@ % Copyright (C) 2006, Vladimir Litvak % -% $Log: loreta2fieldtrip.m,v $ -% Revision 1.3 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.2 2006/08/29 20:50:21 roboos -% major cleanup, added optional key-value inputs, implemented timeframe selection, implemented support for storing multiple timeframes in the source.avg.mom field (i.e. timecourses) +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.1 2006/04/03 07:43:28 roboos -% first version under CVS control +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: loreta2fieldtrip.m 948 2010-04-21 18:02:21Z roboos $ fieldtripdefs @@ -110,7 +118,7 @@ [st, i] = dbstack; cfg.version.name = st(i); end -cfg.version.id = '$Id: loreta2fieldtrip.m,v 1.3 2008/09/22 20:17:43 roboos Exp $'; +cfg.version.id = '$Id: loreta2fieldtrip.m 948 2010-04-21 18:02:21Z roboos $'; % remember the full configuration details source.cfg = cfg; diff --git a/external/fieldtrip/plotSelection.m b/external/fieldtrip/plotSelection.m deleted file mode 100644 index 9393ebc..0000000 --- a/external/fieldtrip/plotSelection.m +++ /dev/null @@ -1,470 +0,0 @@ -function plotSelection(userData, buttonState) - -% PLOTSELECTION is the callback function for interactive ER or TFR plots. -% The function can be called by one of the following functions: -% multiplotER, multiplotTFR, singleplotER, singleplotTFR, and topoplot. -% -% This function is only to be used as a callback function, i.e. you should -% not call it directly. -% -% This function updates the selected areas in the plot, and produces a new -% interactive plot when a selected area is clicked. Multiple areas can be -% selected by holding down the SHIFT key. The newly produced plot is the -% outcome of a statistical function applied to the selected region(s), -% based on the calling plot type (multi, single, or topo). The statistical -% functions used by default are: -% for multiplots : mean of selected channels -% for singleplots : none -% for topoplots : none -% -% userData is a structure array linked to the 'UserData' property of the -% figure that contains the interactive ER/TFR plot. It contains the -% following fields: -% hFigure = figure handle -% hAxes = axes handle of the ER/TFR plot -% hSelection{:} = cell array of line handles of selection rectangles -% iSelection = cell array element index of current selection -% rectangle -% selecting = value specifying the current selecting status: -% 0: not selecting -% 1: starting a new selection (mouse button just -% pressed) -% 2: continuing current selection (dragging -% rectangle) -% selectionType = string specifying whether to extend current -% selection (when SHIFT key is held down), or to start -% a new selection (otherwise). -% selectAxes = string specifying which axes to select; any -% combination of x,y,z. For example, 'xy' means the -% user can select a range on the x- and y-axes. -% lastClick = mouse pointer coordinates at the latest button down -% event -% cfg = copy of configuration used for the plotting -% data = copy of data structure used for the plotting -% chanX,chanY = [only used by multiplot routines] x,y-coordinates of -% the plotted channels (centre coordinates) -% chanLabels = [only used by multiplot routines] label names of the -% plotted channels -% -% buttonState can be one of the following values: -% 0: button is not going up or down (it may be HELD down, though) -% 1: button is going down -% 2: button is going up -% - -% Undocumented local options: -% cfg.channelname -% cfg.interactive -% cfg.layout -% cfg.maplimits -% cfg.xlim -% cfg.xparam -% cfg.ylim -% cfg.yparam -% cfg.zlim - -% Copyright (C) 2006, Dennis Pasveer -% -% $Log: plotSelection.m,v $ -% Revision 1.18 2007/10/01 07:37:54 roboos -% copy cfg.rotate along in the new_cfg, for subsequent topoplots (thanks to Vladimir) -% -% Revision 1.17 2007/09/25 11:30:10 ingnie -% set cfg.baseline = 'no' to prevent multiple calls to baseline correction in interactive plotting -% -% Revision 1.16 2007/07/02 13:42:35 roboos -% only pass cfg.maskparameter on to next function if present -% -% Revision 1.15 2007/06/19 13:59:00 ingnie -% give cfg.maskparameter along in new_cfg -% -% Revision 1.14 2007/06/05 15:05:12 ingnie -% removed dimord repl_chan_time, added dimord rpt_chan_time -% -% Revision 1.13 2007/04/19 10:56:16 roboos -% pass the cfg.interpolation option along to subsequent interactive plots -% -% Revision 1.12 2007/03/14 11:21:29 chrhes -% fixed same bug as in previous revision but on line 252 -% -% Revision 1.11 2007/03/14 11:09:25 chrhes -% fixed a small bug to do with copying a possibly nonexistent field 'layout' -% from the userData.cfg structure to new_cfg (on line 222) -% -% Revision 1.10 2007/01/09 11:12:38 roboos -% pass cfg.renderer on to new_cfg for next plot function -% -% Revision 1.9 2007/01/09 10:41:43 roboos -% Added the option cfg.renderer, default is opengl. Interactive plotting -% on linux/VNC sometimes does not work, using cfg.renderer='painters' -% seems to fix it. -% -% Revision 1.8 2006/07/27 16:11:19 roboos -% also recognise timelocked data with keeptrials -% pass the xparam,zparam and layout along to the next plot in case of interactive -% -% Revision 1.7 2006/06/06 16:24:06 ingnie -% replaced cfg.channelindex and cfg.channelname with cfg.channel for consistency -% with other functions -% -% Revision 1.6 2006/05/30 20:57:15 roboos -% updated documentation -% -% Revision 1.5 2006/04/27 16:01:30 ingnie -% added dimord subj_chan_time -% -% Revision 1.4 2006/04/20 09:58:34 roboos -% updated documentation -% -% Revision 1.3 2006/03/22 16:22:34 jansch -% implemented the possibility to take cohspctrm from a multiplot to a singleplot -% -% Revision 1.2 2006/03/13 14:09:28 denpas -% Added semicolon to prevent display of new_cfg assignment. -% -% Revision 1.1 2006/03/03 10:03:43 roboos -% moved plotSelection from private into FT main, since a figure callback -% to a private does not work -% -% Revision 1.3 2006/03/02 12:39:55 jansch -% fixed typo -% -% Revision 1.2 2006/03/02 10:51:39 jansch -% corrected updating of xlim and ylim when creating topoplotTFR from singleplotTFR -% -% Revision 1.1 2006/02/27 15:03:47 denpas -% new function, is used as callback function for interactive plotting in multi-, single- and topoplot -% - -% Get cursor coordinates [x y]: -p = get(userData.hAxes, 'CurrentPoint'); -p = p(1,1:2); - -% Get physical axes limits: -xLim = get(userData.hAxes, 'XLim'); -yLim = get(userData.hAxes, 'YLim'); - -% Update pointer: -if ~userData.selecting - if buttonState==0 - % Mouse pointer becomes normal when outside plot boundaries, or when in selected area (=clickable): - if (p(1) < xLim(1)) | (p(1) > xLim(2)) | (p(2) < yLim(1)) | (p(2) > yLim(2)) | inSelection(p, userData.range) - set(userData.hFigure, 'Pointer', 'default'); - else - set(userData.hFigure, 'Pointer', 'crosshair'); - end - end -else - % While selecting, mouse pointer is always crosshair: - set(userData.hFigure, 'Pointer', 'crosshair'); -end - -% Button down starts a selection: -if buttonState==1 - % Check cursor coordinates: - if (p(1) < xLim(1)) | (p(1) > xLim(2)) | (p(2) < yLim(1)) | (p(2) > yLim(2)) - return; - end - - if strcmp(userData.selectAxes, 'x') - p(2) = yLim(1); - end - - % Starting new selection rectangle: - userData.selecting = 1; - - % Keep button down coordinates and selection type: - userData.lastClick = p; - userData.selectionType = get(userData.hFigure, 'SelectionType'); - - % Update figure's UserData: - set(userData.hFigure, 'UserData', userData); - -elseif userData.selecting - % Distinguish between clicking and dragging: - clicked = sum(p == userData.lastClick) == 2; - if strcmp(userData.selectAxes, 'x') - clicked = p(1) == userData.lastClick(1); - end - - % Limit cursor coordinates: - if p(1)xLim(2), p(1)=xLim(2); end; - if p(2)yLim(2), p(2)=yLim(2); end; - - if strcmp(userData.selectAxes, 'xy') - % Determine selected x,y-range: - if size(userData.range{1}, 2) == 4 - set(userData.hFigure, 'Name', sprintf('%0s=[%.3g %.3g]/%0s=[%.3g %.3g]', userData.cfg.xparam, min(userData.range{1}([1 3])), max(userData.range{1}([1 3])), userData.cfg.yparam, min(userData.range{1}([2 4])), max(userData.range{1}([2 4])))); - end - elseif strcmp(userData.selectAxes, 'z') - % Determine selected channels: - selChannels = []; - for k=1:length(userData.chanLabels) - if ~isempty(userData.chanLabels{k}) - if inSelection([userData.chanX(k) userData.chanY(k)], userData.range) - selChannels = [selChannels k]; - end - end - end - - % Update window caption: - set(userData.hFigure, 'Name', sprintf('%.0f channels selected', length(selChannels))); - elseif strcmp(userData.selectAxes, 'x') - % Determine selected x-range: - if size(userData.range{1}, 2) == 4 - set(userData.hFigure, 'Name', sprintf('%0s=[%.3g %.3g]', userData.cfg.xparam, min(userData.range{1}([1 3])), max(userData.range{1}([1 3])))); - end - - % Set y to the vertical limit: - p(2) = yLim(2); - end - - % Launch a new figure if a selected area has been clicked: - if (buttonState == 2) ... - & (userData.selecting == 1) ... - & (clicked) ... - & (inSelection(p, userData.range)) - - % Button has been released, so stop selecting: - userData.selecting = 0; - - % Update figure's UserData: - set(userData.hFigure, 'UserData', userData); - - % Check data dimord for ERP data: - dimord = getDimord(userData); - if strcmp(dimord, 'chan_time') || strcmp(dimord, 'chan_freq') || strcmp(dimord, 'subj_chan_time') || strcmp(dimord, 'rpt_chan_time') - if strcmp(userData.selectAxes, 'z') - if length(selChannels) > 0 - % Launch ER singleplot figure: - new_cfg = []; - if isfield(userData.cfg, 'layout') - new_cfg.layout = userData.cfg.layout; - end - if isfield(userData.cfg, 'rotate') - new_cfg.rotate = userData.cfg.rotate; - end - if isfield(userData.cfg, 'interpolation') - new_cfg.interpolation = userData.cfg.interpolation; - end - if isfield(userData.cfg, 'maskparameter') - new_cfg.maskparameter = userData.cfg.maskparameter; - end - new_cfg.xparam = userData.cfg.xparam; - new_cfg.zparam = userData.cfg.zparam; - new_cfg.interactive = 'yes'; - new_cfg.xlim = userData.cfg.xlim; - new_cfg.ylim = userData.cfg.ylim; - new_cfg.renderer = userData.cfg.renderer; - new_cfg.baseline = 'no'; %to prevent baseline correction to take place multiple times - - % Set xlim to 'maxmin' when going from topoplot to singleplot: - if strcmp(userData.plotType, 'topoplot') - new_cfg.xlim = 'maxmin'; - end - - new_cfg.channel = userData.chanLabels(selChannels); - - figure; - copyPosition(userData.hFigure); - - if iscell(userData.data) - singleplotER(new_cfg, userData.data{:}); - else - singleplotER(new_cfg, userData.data); - end - end - else - % Configure ER topoplot figure: - new_cfg = []; - if isfield(userData.cfg, 'layout') - new_cfg.layout = userData.cfg.layout; - end - if isfield(userData.cfg, 'rotate') - new_cfg.rotate = userData.cfg.rotate; - end - if isfield(userData.cfg, 'interpolation') - new_cfg.interpolation = userData.cfg.interpolation; - end - new_cfg.xparam = userData.cfg.xparam; - new_cfg.zparam = userData.cfg.zparam; - new_cfg.interactive = 'yes'; - new_cfg.maplimits = 'maxmin'; - new_cfg.ylim = userData.cfg.ylim; - new_cfg.renderer = userData.cfg.renderer; - new_cfg.baseline = 'no'; %to prevent baseline correction to take place multiple times - - % Calculate xlim: - new_cfg.xlim = sort(userData.range{1}([1 3])); - - % Produce topoplot: - figure; - copyPosition(userData.hFigure); - - if iscell(userData.data) - topoplotER(new_cfg, userData.data{:}); - else - topoplotER(new_cfg, userData.data); - end - end - - % Check data dimord for TFR data: - elseif strcmp(dimord, 'chan_freq_time') - if strcmp(userData.selectAxes, 'z') - if length(selChannels) > 0 - % Launch TFR singleplot figure: - new_cfg = userData.cfg; - new_cfg.xlim = userData.cfg.xlim; - new_cfg.ylim = userData.cfg.ylim; - new_cfg.zlim = userData.cfg.zlim; - new_cfg.baseline = 'no'; %to prevent baseline correction to take place multiple times - - % Set xlim and ylim to 'maxmin' when going from topoplot to singleplot: - if strcmp(userData.plotType, 'topoplot') - new_cfg.xlim = 'maxmin'; - new_cfg.ylim = 'maxmin'; - end - - % Get channel names of selected channels: - new_cfg.channel = userData.chanLabels(selChannels); - - figure; - copyPosition(userData.hFigure); - singleplotTFR(new_cfg, userData.data); - end - else - % Launch TFR topoplot figure: - new_cfg = userData.cfg; - new_cfg.maplimits = 'maxmin'; - new_cfg.xlim = userData.data.time([ ... - nearest(userData.data.time, min((userData.range{1}([1 3])))) ... - nearest(userData.data.time, max((userData.range{1}([1 3])))) ... - ]); - new_cfg.ylim = userData.data.freq([ ... - nearest(userData.data.freq, min((userData.range{1}([2 4])))) ... - nearest(userData.data.freq, max((userData.range{1}([2 4])))) ... - ]); - new_cfg.baseline = 'no'; %to prevent baseline correction to take place multiple times - - % Produce topoplot: - figure; - copyPosition(userData.hFigure); - topoplotTFR(new_cfg, userData.data); - end - - % Check data dimord for FREQ data: - elseif (isfield(userData.cfg, 'xparam') & strcmp(userData.cfg.yparam, 'freq')) - - - else - userData.cfg - error('Unable to produce figure: unidentified data.dimord value.'); - end - - return; - end - - % If starting new selection rectangle, determine rectangle index: - if userData.selecting ~= 2 - if strcmp(userData.selectionType, 'normal') - % If previous selection was finished, clear selection: - for i=1:length(userData.hSelection) - set(userData.hSelection{i}, 'Visible', 'off'); - userData.range{i} = []; - end - - % Update window caption for empty selection: - if strcmp(userData.selectAxes, 'xy') - set(userData.hFigure, 'Name', 'No selection'); - elseif strcmp(userData.selectAxes, 'z') - set(userData.hFigure, 'Name', '0 channels selected'); - elseif strcmp(userData.selectAxes, 'x') - set(userData.hFigure, 'Name', 'No selection'); - end - - userData.iSelection = 1; - else - % Proceed to next selection rectangle: - userData.iSelection = userData.iSelection + 1; - if userData.iSelection > length(userData.hSelection) - userData.iSelection = 1; - end - end - - % Set first corner coordinates: - userData.range{userData.iSelection} = userData.lastClick; - - % We're now selecting: - userData.selecting = 2; - end - - % Set rectangle range: - userData.range{userData.iSelection} = [userData.range{userData.iSelection}([1 2]) p]; - - % Keep rectangle coordinates: - xData = userData.range{userData.iSelection}([1 3 3 1 1]); - yData = userData.range{userData.iSelection}([2 2 4 4 2]); - - % Plot selection rectangle: - set(userData.hSelection{userData.iSelection}, 'XData', xData); - set(userData.hSelection{userData.iSelection}, 'YData', yData); - set(userData.hSelection{userData.iSelection}, 'Color', [0 0 0]); - set(userData.hSelection{userData.iSelection}, 'EraseMode', 'xor'); - set(userData.hSelection{userData.iSelection}, 'LineStyle', '--'); - set(userData.hSelection{userData.iSelection}, 'LineWidth', 1.5); - set(userData.hSelection{userData.iSelection}, 'Visible', 'on'); - - % On buttonUp, the selection rectangle is done: - if buttonState == 2 - userData.selecting = 0; - end - - % Update figure's UserData: - set(userData.hFigure, 'UserData', userData); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function a = inSelection(aPoint, selectionRanges) -% Function returns selection rectangle index number of the rectangle of a -% certain coordinate. - -a = 0; -for i=1:length(selectionRanges) - % Look only in complete selections (containing 4 elemens [left top right bottom]): - if (length(selectionRanges{i}) == 4) ... - & (aPoint(1) >= min(selectionRanges{i}([1 3]))) ... - & (aPoint(1) <= max(selectionRanges{i}([1 3]))) ... - & (aPoint(2) >= min(selectionRanges{i}([2 4]))) ... - & (aPoint(2) <= max(selectionRanges{i}([2 4]))) - - a = i; - return; - end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function copyPosition(hFigure) -% This function copies the window position from a given figure to the -% current figure. - -set(gcf, 'position', get(hFigure, 'position')); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function dimord = getDimord(userData) -% This function reads the dimord value from the userData.data structure. -% Since userData.data may be a cell array of multiple data sets, this -% function first detects the data type. - -if iscell(userData.data) - dimord = userData.data{1}.dimord; -else - dimord = userData.data.dimord; -end diff --git a/external/fieldtrip/plotting/COPYING b/external/fieldtrip/plotting/COPYING new file mode 100644 index 0000000..1b28104 --- /dev/null +++ b/external/fieldtrip/plotting/COPYING @@ -0,0 +1,341 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + diff --git a/external/fieldtrip/plotting/README b/external/fieldtrip/plotting/README new file mode 100644 index 0000000..8edb292 --- /dev/null +++ b/external/fieldtrip/plotting/README @@ -0,0 +1,15 @@ +This is the FieldTrip PLOTTING module. It contains functions for +visualising data and interacting with it. These functions form the +building blocks for the FieldTrip data plotting functions and graphical +user interfaces. + +For more information please visit http://www.ru.nl/neuroimaging/fieldtrip. + +The FieldTrip software is free but copyrighted software, distributed +under the terms of the GNU General Public Licence as published by +the Free Software Foundation (either version 2, or at your option +any later version). See the file COPYING for more details. + +Copyright (C) 2009, Donders Institute for Brain, Cognition and Behaviour, The Netherlands (DCCN) +Copyright (C) 2009, Netherlands Institute for Neuroscience (NIN) + diff --git a/external/fieldtrip/plotting/ft_plot_box.m b/external/fieldtrip/plotting/ft_plot_box.m new file mode 100644 index 0000000..001a7f0 --- /dev/null +++ b/external/fieldtrip/plotting/ft_plot_box.m @@ -0,0 +1,130 @@ +function [varargout] = plot_box(position, varargin); + +% PLOT_BOX plots the outline of a box that is specified by its lower +% left and upper right corner +% +% Use as +% plot_box(position, ...) +% where the position of the box is specified as is [x1, x2, y1, y2]. +% Optional arguments should come in key-value pairs and can include +% 'facealpha' = transparency value between 0 and 1 +% 'facecolor' = color specification as [r g b] values or a string, for example 'brain', 'cortex', 'skin', 'red', 'r' +% 'edgecolor' = color specification as [r g b] values or a string, for example 'brain', 'cortex', 'skin', 'red', 'r' +% 'hpos' = +% 'vpos' = +% 'width' = +% 'height' = +% 'hlim' = +% 'vlim' = +% +% Example +% plot_box([-1 1 2 3], 'facecolor', 'b') +% axis([-4 4 -4 4]) + +% Copyrights (C) 2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_plot_box.m 1413 2010-07-15 14:40:26Z crimic $ + +warning('on', 'MATLAB:divideByZero'); + +% get the optional input arguments +keyvalcheck(varargin, 'optional', {'hpos', 'vpos', 'width', 'height', 'hlim', 'vlim', 'facealpha', 'facecolor', 'edgecolor'}); +hpos = keyval('hpos', varargin); +vpos = keyval('vpos', varargin); +width = keyval('width', varargin); +height = keyval('height', varargin); +hlim = keyval('hlim', varargin); +vlim = keyval('vlim', varargin); +facealpha = keyval('facealpha', varargin); if isempty(facealpha), facealpha = 1; end +facecolor = keyval('facecolor', varargin); if isempty(facecolor), facecolor = 'none'; end +edgecolor = keyval('edgecolor', varargin); if isempty(edgecolor), edgecolor = 'k'; end + +% convert the two cornerpoints into something that the patch function understands +% the box position is represented just like the argument to the AXIS function +x1 = position(1); +x2 = position(2); +y1 = position(3); +y2 = position(4); +X = [x1 x2 x2 x1 x1]; +Y = [y1 y1 y2 y2 y1]; + +if isempty(hlim) && isempty(vlim) && isempty(hpos) && isempty(vpos) && isempty(height) && isempty(width) + % no scaling is needed, the input X and Y are already fine + % use a shortcut to speed up the plotting + +else + % use the full implementation + abc = axis; + + if isempty(hlim) + hlim = abc([1 2]); + end + + if isempty(vlim) + vlim = abc([3 4]); + end + + if isempty(hpos); + hpos = (hlim(1)+hlim(2))/2; + end + + if isempty(vpos); + vpos = (vlim(1)+vlim(2))/2; + end + + if isempty(width), + width = hlim(2)-hlim(1); + end + + if isempty(height), + height = vlim(2)-vlim(1); + end + + % first shift the horizontal axis to zero + X = X - (hlim(1)+hlim(2))/2; + % then scale to length 1 + X = X ./ (hlim(2)-hlim(1)); + % then scale to the new width + X = X .* width; + % then shift to the new horizontal position + X = X + hpos; + + % first shift the vertical axis to zero + Y = Y - (vlim(1)+vlim(2))/2; + % then scale to length 1 + Y = Y ./ (vlim(2)-vlim(1)); + % then scale to the new width + Y = Y .* height; + % then shift to the new vertical position + Y = Y + vpos; + +end % shortcut + +% use an arbitrary color, which will be replaced by the correct color a few lines down +C = 0; + +h = patch(X, Y, C); +set(h, 'FaceAlpha', facealpha) +set(h, 'FaceColor', facecolor) +set(h, 'EdgeColor', edgecolor) + +% the (optional) output is the handle +if nargout == 1 + varargout{1} = h; +end diff --git a/external/fieldtrip/plotting/ft_plot_dipole.m b/external/fieldtrip/plotting/ft_plot_dipole.m new file mode 100644 index 0000000..6dd7d6d --- /dev/null +++ b/external/fieldtrip/plotting/ft_plot_dipole.m @@ -0,0 +1,159 @@ +function plot_dipole(pos, ori, varargin) + +% PLOT_DIPOLE makes a 3-D representation of a dipole using a small sphere +% and a stick pointing along the dipole orientation +% +% Use as +% plot_dipole(pos, mom, ...) +% where pos and mom are the dipole mosition and moment. Optional +% input arguments should be specified in key-value pairs and can +% include +% 'diameter' number indicating sphere diameter (default = 'auto') +% 'length' number indicating length of the stick (default = 'auto') +% 'color' [r g b] values or string, for example 'brain', 'cortex', 'skin', 'black', 'red', 'r' +% 'units' 'm', 'cm' or 'mm', used for automatic scaling (default = 'cm') +% 'scale' scale the dipole with the amplitude, can be 'none', 'both', 'diameter', 'length' (default = 'none') +% +% Example +% plot_dipole([0 0 0], [1 2 3]) + +% Copyright (C) 2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_plot_dipole.m 1413 2010-07-15 14:40:26Z crimic $ + +warning('on', 'MATLAB:divideByZero'); + +% get the optional input arguments +units = keyval('units', varargin); if isempty(units), units = 'cm'; end +color = keyval('color', varargin); if isempty(color), color = [1 0 0]; end +diameter = keyval('diameter', varargin); if isempty(diameter), diameter = 'auto'; end +length = keyval('length', varargin); if isempty(length), length = 'auto'; end +amplitudescale = keyval('scale', varargin); if isempty(amplitudescale), amplitudescale = 'none'; end + +if isequal(diameter, 'auto') + % the default is a 5 mm sphere + switch units + case 'm' + diameter = 0.005; + case 'cm' + diameter = 0.5; + case 'mm' + diameter = 5; + otherwise + error('unsupported units'); + end +end + +if isequal(length, 'auto') + % the default is a 15 mm stick + switch units + case 'm' + length = 0.015; + case 'cm' + length = 1.5; + case 'mm' + length = 15; + otherwise + error('unsupported units'); + end +end + +% dipole position should be Nx3 +if all(size(pos) == [3 1]) + pos = pos'; +end + +% dipole moment and orientation should be 3xN +if all(size(ori) == [1 3]) + ori = ori'; +end + +% everything is added to the current figure +holdflag = ishold; +hold on + +for i=1:size(pos,1) + amplitude = norm(ori(:,i)); + ori(:,i) = ori(:,i) ./ amplitude; + + % scale the dipole diameter and length with its amplitude + if strcmp(amplitudescale, 'length') || strcmp(amplitudescale, 'both') + this_length = length*amplitude; + else + this_length = length; + end + if strcmp(amplitudescale, 'diameter') || strcmp(amplitudescale, 'both') + this_diameter = diameter*amplitude; + else + this_diameter = diameter; + end + + % create a unit sphere and cylinder + [sphere.pnt, sphere.tri] = icosahedron642; + sphere.pnt = warp_apply(scale([0.5 0.5 0.5]), sphere.pnt, 'homogeneous'); % the diameter should be 1 + [stick.pnt, stick.tri] = cylinder(36, 2); + stick.pnt = warp_apply(scale([0.5 0.5 0.5]), stick.pnt, 'homogeneous'); % the length should be 1 + stick.pnt = warp_apply(translate([0 0 0.5]), stick.pnt, 'homogeneous'); % it should start in the origin + + % scale the sphere + sx = this_diameter; + sy = this_diameter; + sz = this_diameter; + sphere.pnt = warp_apply(scale([sx sy sz]), sphere.pnt, 'homogeneous'); + + % translate the sphere + tx = pos(i,1); + ty = pos(i,2); + tz = pos(i,3); + sphere.pnt = warp_apply(translate([tx ty tz]), sphere.pnt, 'homogeneous'); + + % scale the stick + sx = this_diameter/3; + sy = this_diameter/3; + sz = this_length; + stick.pnt = warp_apply(scale([sx sy sz]), stick.pnt, 'homogeneous'); + + % first rotate the stick to point along the x-axis + stick.pnt = warp_apply(rotate([0 90 0]), stick.pnt, 'homogeneous'); + % then rotate the stick in the desired direction + [az, el] = cart2sph(ori(1,i), ori(2,i), ori(3,i)); + stick.pnt = warp_apply(rotate([0 -el*180/pi 0]), stick.pnt, 'homogeneous'); % rotate around y-axis + stick.pnt = warp_apply(rotate([0 0 az*180/pi]), stick.pnt, 'homogeneous'); % rotate around z-axis + + % translate the stick + tx = pos(i,1); + ty = pos(i,2); + tz = pos(i,3); + stick.pnt = warp_apply(translate([tx ty tz]), stick.pnt, 'homogeneous'); + + % plot the sphere and the stick + plot_mesh(sphere, 'vertexcolor', 'none', 'edgecolor', false, 'facecolor', color); + plot_mesh(stick, 'vertexcolor', 'none', 'edgecolor', false, 'facecolor', color); + +end % for each dipole + +axis off +axis vis3d +axis equal +camlight % fixme, this probably should be in the calling function + +if ~holdflag + hold off +end + diff --git a/external/fieldtrip/plotting/ft_plot_headshape.m b/external/fieldtrip/plotting/ft_plot_headshape.m new file mode 100644 index 0000000..e0208c1 --- /dev/null +++ b/external/fieldtrip/plotting/ft_plot_headshape.m @@ -0,0 +1,91 @@ +function hs = plot_headshape(headshape,varargin) + +% PLOT_HEADSHAPE visualizes the shape of a head generated from a variety of files +% (like CTF and Polhemus). The headshape and fiducials can for example be used for coregistration. +% +% Use as +% hs = plot_headshape(shape, varargin) +% +% Graphic facilities are available for vertices and fiducials (Nasion, Left, Right ...). A list of +% the arguments is given below with the correspondent admitted choices. +% +% 'vertexcolor' ['brain', 'cortex', 'skin', 'black', 'red', 'r', ..., [0.5 1 0], ...] +% 'fidcolor' ['brain', 'cortex', 'skin', 'black', 'red', 'r', ..., [0.5 1 0], ...] +% 'fidmarker' ['.', '*', '+', ...] +% 'fidlabel' ['yes', 'no', 1, 0, 'true', 'false'] +% 'transform' transformation matrix for the fiducials, converts MRI +% voxels into head shape coordinates +% +% Example +% [shape] = read_headshape(filename); +% plot_headshape(shape) + +% Copyright (C) 2009, Cristiano Micheli +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_plot_headshape.m 1413 2010-07-15 14:40:26Z crimic $ + +warning('on', 'MATLAB:divideByZero'); + +% get the optional input arguments +vertexcolor = keyval('vertexcolor', varargin); if isempty(vertexcolor), vertexcolor='r'; end +fidcolor = keyval('fidcolor', varargin); if isempty(fidcolor), fidcolor='g'; end +fidmarker = keyval('fidmarker', varargin); if isempty(fidmarker), fidmarker='.'; end +fidlabel = keyval('fidlabel', varargin); if isempty(fidlabel), fidlabel='no'; end +transform = keyval('transform', varargin); if isempty(transform), transform=[]; end + +% start with empty return values +hs = []; + +% everything is added to the current figure +holdflag = ishold; +hold on + +pnt = headshape.pnt; +bnd.pnt = pnt; +bnd.tri = []; + +hs = plot_mesh(bnd, 'vertices', 'yes', 'vertexcolor',vertexcolor,'vertexsize',10); + +if isfield(headshape, 'fid') + fid = headshape.fid; + if ~isempty(transform) + % plot the fiducials + fidc = fid.pnt; + try + fidc = warp_apply(transform, fidc); + end + hs = plot3(fidc(:,1), fidc(:,2), fidc(:,3), 'Marker',fidmarker,'MarkerEdgeColor',fidcolor); + % show the fiducial labels + if isfield(fid,'label') && istrue(fidlabel) + for node_indx=1:size(fidc,1) + str = sprintf('%s', fid.label{node_indx}); + h = text(fidc(node_indx, 1), fidc(node_indx, 2), fidc(node_indx, 3), str, ... + 'HorizontalAlignment', 'center', 'VerticalAlignment', 'middle','Interpreter','none'); + hs = [hs; h]; + end + end + end + +end +if nargout==0 + clear hs +end +if ~holdflag + hold off +end diff --git a/external/fieldtrip/plotting/ft_plot_lay.m b/external/fieldtrip/plotting/ft_plot_lay.m new file mode 100644 index 0000000..29d9403 --- /dev/null +++ b/external/fieldtrip/plotting/ft_plot_lay.m @@ -0,0 +1,136 @@ +function plot_lay(lay, varargin) + +% PLOT_LAY plots a two-dimensional layout +% +% Use as +% plot_lay(layout, ...) +% where the layout is a FieldTrip structure obtained from PREPARE_LAYOUT. +% +% Additional options should be specified in key-value pairs and can be +% 'point' = yes/no +% 'box' = yes/no +% 'label' = yes/no +% 'labelsize' = number indicating font size (e.g. 6) +% 'labeloffset' = offset of label from point (suggestion is 0.005) +% 'mask' = yes/no +% 'outline' = yes/no +% 'verbose' = yes/no +% 'pointsymbol' = string with symbol (e.g. 'o') - all three point options need to be used together +% 'pointcolor' = string with color (e.g. 'k') +% 'pointsize' = number indicating size (e.g. 8) + +% Copyright (C) 2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_plot_lay.m 1413 2010-07-15 14:40:26Z crimic $ + +warning('on', 'MATLAB:divideByZero'); + +% get the optional input arguments +keyvalcheck(varargin, 'optional', {'hpos', 'vpos', 'point', 'box', 'label','labelsize','labeloffset', 'mask', 'outline', 'verbose','pointsymbol','pointcolor','pointsize'}); +hpos = keyval('hpos', varargin{:}); if isempty(hpos), hpos = 0; end +vpos = keyval('vpos', varargin{:}); if isempty(vpos), vpos = 0; end +point = keyval('point', varargin{:}); if isempty(point), point = true; end +box = keyval('box', varargin{:}); if isempty(box), box = true; end +label = keyval('label', varargin{:}); if isempty(label), label = true; end +labelsize = keyval('labelsize', varargin{:}); if isempty(labelsize), labelsize = 10; end +labeloffset = keyval('labeloffset', varargin{:}); if isempty(labeloffset),labeloffset = 0; end +mask = keyval('mask', varargin{:}); if isempty(mask), mask = true; end +outline = keyval('outline', varargin{:}); if isempty(outline), outline = true; end +verbose = keyval('verbose', varargin{:}); if isempty(verbose), verbose = false; end +pointsymbol = keyval('pointsymbol', varargin{:}); +pointcolor = keyval('pointcolor', varargin{:}); +pointsize = keyval('pointsize', varargin{:}); + +% convert between true/false/yes/no etc. statements +point = istrue(point); +box = istrue(box); +label = istrue(label); +mask = istrue(mask); +outline = istrue(outline); +verbose = istrue(verbose); + + +% everything is added to the current figure +holdflag = ishold; +hold on + +X = lay.pos(:,1) + hpos; +Y = lay.pos(:,2) + vpos; +Width = lay.width; +Height = lay.height; +Lbl = lay.label; + +if point + if ~isempty(pointsymbol) && ~isempty(pointcolor) && ~isempty(pointsize) % if they're all non-empty, don't use the default + plot(X, Y, 'marker',pointsymbol,'color',pointcolor,'markersize',pointsize,'linestyle','none'); + else + plot(X, Y, 'marker','.','color','b','linestyle','none'); + plot(X, Y, 'marker','o','color','y','linestyle','none'); + end +end + +if label + text(X+labeloffset, Y+(labeloffset*1.5), Lbl,'fontsize',labelsize); +end + +if box + line([X-Width/2 X+Width/2 X+Width/2 X-Width/2 X-Width/2]',[Y-Height/2 Y-Height/2 Y+Height/2 Y+Height/2 Y-Height/2]'); +end + +if outline && isfield(lay, 'outline') + if verbose + fprintf('solid lines indicate the outline, e.g. head shape or sulci\n'); + end + for i=1:length(lay.outline) + if ~isempty(lay.outline{i}) + X = lay.outline{i}(:,1) + hpos; + Y = lay.outline{i}(:,2) + vpos; + h = line(X, Y); + set(h, 'color', 'k'); + set(h, 'linewidth', 2); + end + end +end + +if mask && isfield(lay, 'mask') + if verbose + fprintf('dashed lines indicate the mask for topograpic interpolation\n'); + end + for i=1:length(lay.mask) + if ~isempty(lay.mask{i}) + X = lay.mask{i}(:,1) + hpos; + Y = lay.mask{i}(:,2) + vpos; + % the polygon representing the mask should be closed + X(end+1) = X(1); + Y(end+1) = Y(1); + h = line(X, Y); + set(h, 'color', 'k'); + set(h, 'linewidth', 1.5); + set(h, 'linestyle', ':'); + end + end +end + +axis auto +axis equal +axis off + +if ~holdflag + hold off +end diff --git a/external/fieldtrip/plotting/ft_plot_line.m b/external/fieldtrip/plotting/ft_plot_line.m new file mode 100644 index 0000000..edf4211 --- /dev/null +++ b/external/fieldtrip/plotting/ft_plot_line.m @@ -0,0 +1,106 @@ +function plot_line(X, Y, varargin) + +% PLOT_LINE helper function for plotting a line, which can also be used in +% combination with the multiple channel layout display in FieldTrip. +% +% Use as +% plot_line(X, Y, ...) +% where optional input arguments should come in key-value pairs and may +% include +% hpos +% vpos +% width +% height +% hlim +% vlim +% color +% linestyle +% linewidth + +% Copyrights (C) 2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_plot_line.m 1413 2010-07-15 14:40:26Z crimic $ + +warning('on', 'MATLAB:divideByZero'); + +% get the optional input arguments +keyvalcheck(varargin, 'optional', {'hpos', 'vpos', 'width', 'height', 'hlim', 'vlim', 'color', 'linestyle', 'linewidth'}); +hpos = keyval('hpos', varargin); +vpos = keyval('vpos', varargin); +width = keyval('width', varargin); +height = keyval('height', varargin); +hlim = keyval('hlim', varargin); +vlim = keyval('vlim', varargin); +color = keyval('color', varargin); if isempty(color), color = 'k'; end +linestyle = keyval('linestyle', varargin); if isempty(linestyle), linestyle = '-'; end +linewidth = keyval('linewidth', varargin); if isempty(linewidth), linewidth = 0.5; end + +if isempty(hlim) && isempty(vlim) && isempty(hpos) && isempty(vpos) && isempty(height) && isempty(width) + % no scaling is needed, the input X and Y are already fine + % use a shortcut to speed up the plotting + +else + % use the full implementation + abc = axis; + + if isempty(hlim) + hlim = abc([1 2]); + end + + if isempty(vlim) + vlim = abc([3 4]); + end + + if isempty(hpos); + hpos = (hlim(1)+hlim(2))/2; + end + + if isempty(vpos); + vpos = (vlim(1)+vlim(2))/2; + end + + if isempty(width), + width = hlim(2)-hlim(1); + end + + if isempty(height), + height = vlim(2)-vlim(1); + end + + % first shift the horizontal axis to zero + X = X - (hlim(1)+hlim(2))/2; + % then scale to length 1 + X = X ./ (hlim(2)-hlim(1)); + % then scale to the new width + X = X .* width; + % then shift to the new horizontal position + X = X + hpos; + + % first shift the vertical axis to zero + Y = Y - (vlim(1)+vlim(2))/2; + % then scale to length 1 + Y = Y ./ (vlim(2)-vlim(1)); + % then scale to the new width + Y = Y .* height; + % then shift to the new vertical position + Y = Y + vpos; + +end % shortcut + +h = line(X, Y, 'Color', color, 'LineStyle', linestyle, 'LineWidth', linewidth); diff --git a/external/fieldtrip/plotting/ft_plot_matrix.m b/external/fieldtrip/plotting/ft_plot_matrix.m new file mode 100644 index 0000000..8c5455e --- /dev/null +++ b/external/fieldtrip/plotting/ft_plot_matrix.m @@ -0,0 +1,242 @@ +function plot_matrix(varargin) + +% PLOT_MATRIX +% +% Use as +% plot_matrix(C, ...) +% where C is a 2 dimensional MxN matrix, or +% plot_matrix(X, Y, C, ...) +% where X and Y describe the 1xN horizontal and 1xM vertical axes +% respectively. +% +% Additional options should be specified in key-value pairs and can be +% 'hpos' +% 'vpos' +% 'width' +% 'height' +% 'hlim' +% 'vlim' +% 'clim' +% 'box' can be 'yes' or 'no' +% 'highlight' +% 'highlightstlyle' can be 'saturation' or 'opacity' +% 'tag' +% +% Example use +% plot_matrix(randn(30,50), 'width', 1, 'height', 1, 'hpos', 0, 'vpos', 0) + +% Copyrights (C) 2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_plot_matrix.m 1413 2010-07-15 14:40:26Z crimic $ + +warning('on', 'MATLAB:divideByZero'); + +if nargin>2 && all(cellfun(@isnumeric, varargin(1:3))) + % the function was called like imagesc(x, y, c, ...) + hdat = varargin{1}; + vdat = varargin{2}; + cdat = varargin{3}; + varargin = varargin(4:end); +else + % the function was called like plot(c, ...) + cdat = varargin{1}; + vdat = 1:size(cdat,1); + hdat = 1:size(cdat,2); + varargin = varargin(2:end); +end + +% get the optional input arguments +keyvalcheck(varargin, 'optional', {'hpos', 'vpos', 'width', 'height', 'hlim', 'vlim', 'clim', 'box','highlight','highlightstyle','tag'}); +hpos = keyval('hpos', varargin); +vpos = keyval('vpos', varargin); +width = keyval('width', varargin); +height = keyval('height', varargin); +hlim = keyval('hlim', varargin); +vlim = keyval('vlim', varargin); +clim = keyval('clim', varargin); +box = keyval('box', varargin); if isempty(box), box = false; end +highlight = keyval('highlight', varargin); +highlightstyle = keyval('highlightstyle', varargin); if isempty(highlightstyle), highlightstyle = 'opacity'; end +tag = keyval('tag', varargin); if isempty(tag), tag=''; end + +% axis = keyval('axis', varargin); if isempty(axis), axis = false; end +% label = keyval('label', varargin); % FIXME +% style = keyval('style', varargin); % FIXME + +% convert the yes/no strings into boolean values +box = istrue(box); + +if isempty(hlim) + hlim = 'maxmin'; +end + +if isempty(vlim) + vlim = 'maxmin'; +end + +if isempty(clim) + clim = 'maxmin'; +end + +if ischar(hlim) + switch hlim + case 'maxmin' + hlim = [min(hdat) max(hdat)]; + case 'maxabs' + hlim = max(abs(hdat)); + hlim = [-hlim hlim]; + otherwise + error('unsupported option for hlim') + end % switch +end % if ischar + +if ischar(vlim) + switch vlim + case 'maxmin' + vlim = [min(vdat) max(vdat)]; + case 'maxabs' + vlim = max(abs(vdat)); + vlim = [-vlim vlim]; + otherwise + error('unsupported option for vlim') + end % switch +end % if ischar + +if ischar(clim) + switch clim + case 'maxmin' + clim = [min(cdat(:)) max(cdat(:))]; + case 'maxabs' + clim = max(abs(cdat(:))); + clim = [-clim clim]; + otherwise + error('unsupported option for clim') + end % switch +end % if ischar + +% these must be floating point values and not integers, otherwise the scaling fails +hdat = double(hdat); +vdat = double(vdat); +cdat = double(cdat); +hlim = double(hlim); +vlim = double(vlim); +clim = double(clim); + +if isempty(hpos); + hpos = (hlim(1)+hlim(2))/2; +end + +if isempty(vpos); + vpos = (vlim(1)+vlim(2))/2; +end + +if isempty(width), + width = hlim(2)-hlim(1); + width = width * length(hdat)/(length(hdat)-1); + autowidth = true; +else + autowidth = false; +end + +if isempty(height), + height = vlim(2)-vlim(1); + height = height * length(vdat)/(length(vdat)-1); + autoheight = true; +else + autoheight = false; +end + +% hlim +% vlim + +% first shift the horizontal axis to zero +hdat = hdat - (hlim(1)+hlim(2))/2; +% then scale to length 1 +hdat = hdat ./ (hlim(2)-hlim(1)); +% then scale to compensate for the patch size +hdat = hdat * (length(hdat)-1)/length(hdat); +% then scale to the new width +hdat = hdat .* width; +% then shift to the new horizontal position +hdat = hdat + hpos; + +% first shift the vertical axis to zero +vdat = vdat - (vlim(1)+vlim(2))/2; +% then scale to length 1 +vdat = vdat ./ (vlim(2)-vlim(1)); +% then scale to compensate for the patch size +vdat = vdat * (length(vdat)-1)/length(vdat); +% then scale to the new width +vdat = vdat .* height; +% then shift to the new vertical position +vdat = vdat + vpos; + +% the uimagesc-call needs to be here to avoid calling it several times in switch-highlight +if isempty(highlight) + h = uimagesc(hdat, vdat, cdat, clim); + set(h,'tag',tag); +end + +% the uimagesc-call needs to be inside switch-statement, otherwise 'saturation' will cause it to be called twice +if ~isempty(highlight) + switch highlightstyle + case 'opacity' + h = uimagesc(hdat, vdat, cdat, clim); + + set(h,'CData',cdat); % quick fix + + set(h,'tag',tag); + set(h,'AlphaData',highlight); + set(h, 'AlphaDataMapping', 'scaled'); + alim([0 1]); + case 'saturation' + satmask = highlight; + + % Transform cdat-values to have a 0-64 range, dependent on clim + % (think of it as the data having an exact range of min=clim(1) to max=(clim2), convert this range to 0-64) + cdat = (cdat + -clim(1)) * (64 / (-clim(1) + clim(2))); + + % Make sure NaNs are plotted as white pixels, even when using non-integer mask values + satmask(isnan(cdat)) = 0; + cdat(isnan(cdat)) = 32; + + % ind->rgb->hsv ||change saturation values|| hsv->rgb -> plot + rgbcdat = ind2rgb(uint8(floor(cdat)), colormap); + hsvcdat = rgb2hsv(rgbcdat); + hsvcdat(:,:,2) = hsvcdat(:,:,2) .* satmask; + rgbcdatsat = hsv2rgb(hsvcdat); + h = uimagesc(hdat, vdat, rgbcdatsat,clim); + set(h,'tag',tag); + case 'outline' + % the significant voxels could be outlined with a black contour + error('unsupported highlightstyle') + otherwise + error('unsupported highlightstyle') + end % switch highlightstyle +end + +if box + boxposition = zeros(1,4); + % this plots a box around the original hpos/vpos with appropriate width/height + boxposition(1) = hpos - width/2; + boxposition(2) = hpos + width/2; + boxposition(3) = vpos - height/2; + boxposition(4) = vpos + height/2; + plot_box(boxposition); +end diff --git a/external/fieldtrip/plotting/ft_plot_mesh.m b/external/fieldtrip/plotting/ft_plot_mesh.m new file mode 100644 index 0000000..5fd9ab4 --- /dev/null +++ b/external/fieldtrip/plotting/ft_plot_mesh.m @@ -0,0 +1,172 @@ +function plot_mesh(bnd, varargin) + +% PLOT_MESH visualizes the information of a mesh contained in the first +% argument bnd. The boundary argument (bnd) contains typically 2 fields +% called .pnt and .tri referring to vertices and triangulation of a mesh. +% +% Use as +% plot_mesh(bnd, ...) +% +% PLOT_MESH also allows to plot only vertices by +% plot_mesh(pnt) +% where pnt is a list of 3d points cartesian coordinates. +% +% Graphic facilities are available for vertices, edges and faces. A list of +% the arguments is given below with the correspondent admitted choices. +% +% 'facecolor' [r g b] values or string, for example 'brain', 'cortex', 'skin', 'black', 'red', 'r' +% 'vertexcolor' [r g b] values or string, for example 'brain', 'cortex', 'skin', 'black', 'red', 'r' +% 'edgecolor' [r g b] values or string, for example 'brain', 'cortex', 'skin', 'black', 'red', 'r' +% 'faceindex' true or false +% 'vertexindex' true or false +% 'facealpha' transparency, between 0 and 1 +% +% If you don't want the faces or vertices to be plotted, you should +% specify facecolor or respectively edgecolor as 'none'. +% +% Example +% [pnt, tri] = icosahedron162; +% bnd.pnt = pnt; +% bnd.tri = tri; +% plot_mesh(bnd, 'facecolor', 'skin', 'edgecolor', 'none') +% camlight +% +% See also TRIMESH + +% Copyright (C) 2009, Cristiano Micheli +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_plot_mesh.m 1413 2010-07-15 14:40:26Z crimic $ + +warning('on', 'MATLAB:divideByZero'); + +% FIXME: introduce option for color coding (see sourceplot) +keyvalcheck(varargin, 'forbidden', {'faces', 'edges', 'vertices'}); + +if ~isstruct(bnd) && isnumeric(bnd) && size(bnd,2)==3 + % the input seems like a list of points, convert into something that resembles a mesh + warning('off', 'MATLAB:warn_r14_stucture_assignment'); + bnd.pnt = bnd; +end + +% get the optional input arguments +facecolor = keyval('facecolor', varargin); if isempty(facecolor), facecolor='white';end +vertexcolor = keyval('vertexcolor', varargin); if isempty(vertexcolor), vertexcolor='none';end +edgecolor = keyval('edgecolor', varargin); if isempty(edgecolor), edgecolor='k';end +faceindex = keyval('faceindex', varargin); if isempty(faceindex), faceindex=false;end +vertexindex = keyval('vertexindex', varargin); if isempty(vertexindex), vertexindex=false;end +vertexsize = keyval('vertexsize', varargin); if isempty(vertexsize), vertexsize=10;end +facealpha = keyval('facealpha', varargin); if isempty(facealpha), facealpha=1;end +tag = keyval('tag', varargin); if isempty(tag), tag='';end + +% convert string into boolean values +faceindex = istrue(faceindex); +vertexindex = istrue(vertexindex); + +skin = [255 213 119]/255; +brain = [202 100 100]/255; +cortex = [255 213 119]/255; + +% there a various ways of disabling the plotting +if isequal(vertexcolor, 'false') || isequal(vertexcolor, 'no') || isequal(vertexcolor, 'off') || isequal(vertexcolor, false) + vertexcolor = 'none'; +end +if isequal(facecolor, 'false') || isequal(facecolor, 'no') || isequal(facecolor, 'off') || isequal(facecolor, false) + facecolor = 'none'; +end +if isequal(edgecolor, 'false') || isequal(edgecolor, 'no') || isequal(edgecolor, 'off') || isequal(edgecolor, false) + edgecolor = 'none'; +end + +% new colors management +if strcmpi(vertexcolor,'skin') || strcmpi(vertexcolor,'brain') || strcmpi(vertexcolor,'cortex') + vertexcolor = eval(vertexcolor); +end +if strcmpi(facecolor,'skin') || strcmpi(facecolor,'brain') || strcmpi(facecolor,'cortex') + facecolor = eval(facecolor); +end + +% everything is added to the current figure +holdflag = ishold; +hold on + +if ~isfield(bnd, 'tri') + bnd.tri = []; +end + +pnt = bnd.pnt; +tri = bnd.tri; + +if ~isempty(pnt) + hs = patch('Vertices', pnt, 'Faces', tri); + set(hs, 'FaceColor', facecolor); + set(hs, 'FaceAlpha', facealpha); + set(hs, 'EdgeColor', edgecolor); + set(hs, 'tag', tag); +end + +if faceindex + % plot the triangle indices (numbers) at each face + for face_indx=1:size(tri,1) + str = sprintf('%d', face_indx); + tri_x = (pnt(tri(face_indx,1), 1) + pnt(tri(face_indx,2), 1) + pnt(tri(face_indx,3), 1))/3; + tri_y = (pnt(tri(face_indx,1), 2) + pnt(tri(face_indx,2), 2) + pnt(tri(face_indx,3), 2))/3; + tri_z = (pnt(tri(face_indx,1), 3) + pnt(tri(face_indx,2), 3) + pnt(tri(face_indx,3), 3))/3; + h = text(tri_x, tri_y, tri_z, str, 'HorizontalAlignment', 'center', 'VerticalAlignment', 'middle'); + hs = [hs; h]; + end +end + +if ~isequal(vertexcolor, 'none') + if size(pnt, 2)==2 + hs = plot(pnt(:,1), pnt(:,2), 'k.'); + else + hs = plot3(pnt(:,1), pnt(:,2), pnt(:,3), 'k.'); + end + if ~isempty(vertexcolor) + try + set(hs, 'Marker','.','MarkerEdgeColor', vertexcolor,'MarkerSize', vertexsize); + catch + error('Unknown color') + end + end + if vertexindex + % plot the vertex indices (numbers) at each node + for node_indx=1:size(pnt,1) + str = sprintf('%d', node_indx); + if size(pnt, 2)==2 + h = text(pnt(node_indx, 1), pnt(node_indx, 2), str, 'HorizontalAlignment', 'center', 'VerticalAlignment', 'middle'); + else + h = text(pnt(node_indx, 1), pnt(node_indx, 2), pnt(node_indx, 3), str, 'HorizontalAlignment', 'center', 'VerticalAlignment', 'middle'); + end + hs = [hs; h]; + end + end +end + +axis off +axis vis3d +axis equal + +if ~nargout + clear hs +end +if ~holdflag + hold off +end + diff --git a/external/fieldtrip/plotting/ft_plot_ortho.m b/external/fieldtrip/plotting/ft_plot_ortho.m new file mode 100644 index 0000000..8379973 --- /dev/null +++ b/external/fieldtrip/plotting/ft_plot_ortho.m @@ -0,0 +1,362 @@ +function fiducial=plot_ortho(data) +% +% PLOT_ORTHO visualizes an MRI 3D volume in 3 orthogonal projections +% +% Use as +% hs = plot_ortho(data, varargin) +% +% Some defaults for the additional arguments: +% +% 'location' = location of cut, (default = 'auto') +% 'auto', 'center' if only anatomy, 'max' if functional data +% 'min' and 'max' position of min/max funparameter +% 'center' of the brain +% [x y z], coordinates in voxels or head, see locationcoordinates +% 'locationcoordinates' = coordinate system used in location, 'head' or 'voxel' (default = 'head') +% 'head', headcoordinates from anatomical MRI +% 'voxel', voxelcoordinates +% 'crosshair' = 'yes' or 'no' (default = 'yes') +% 'axis' = 'on' or 'off' (default = 'on') +% 'interactive' = 'yes' or 'no' (default = 'no') +% in interactive mode cursor click determines location of cut +% 'queryrange' = number, in atlas voxels (default 3) +% 'funcolorlim' = color range of the functional data (default = 'auto') +% [min max] +% 'maxabs', from -max(abs(funparameter)) to +max(abs(funparameter)) +% 'zeromax', from 0 to max(abs(funparameter)) +% 'minzero', from min(abs(funparameter)) to 0 +% 'auto', if funparameter values are all positive: 'zeromax', +% all negative: 'minzero', both possitive and negative: 'maxabs' +% 'funparameter' = string, field in data with the functional parameter of interest (default = []) +% 'inputcoord' = 'mni' or 'tal', coordinate system of data used to lookup the label from the atlas +% 'colorbar' = 'yes' or 'no' (default = 'yes') +% +% Example +% figure, plot_ortho(data,'colorbar','no','interactive','yes','axis','off') + +% Copyright (C) 2009, Cristiano Micheli +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_plot_ortho.m 1413 2010-07-15 14:40:26Z crimic $ + +warning('on', 'MATLAB:divideByZero'); + +% get the optional input arguments +location = keyval('location', varargin); if isempty(location),location='auto';end +locationcoordinates = keyval('locationcoordinates', varargin); if isempty(locationcoordinates),locationcoordinates='head';end +crosshair1 = keyval('crosshair', varargin); if isempty(crosshair1),crosshair1='yes';end +axis1 = keyval('axis', varargin); if isempty(axis1),axis1='yes';end +interactive = keyval('interactive', varargin); if isempty(interactive),interactive='no';end +queryrange = keyval('queryrange', varargin); if isempty(queryrange),queryrange=3;end +funcolorlim = keyval('funcolorlim', varargin); if isempty(funcolorlim),funcolorlim='auto';end +funparameter = keyval('funparameter', varargin); if isempty(funparameter),funparameter=[];end +colorbar1 = keyval('colorbar', varargin); if isempty(colorbar1),colorbar1='yes';end + +% initialize empty output structure +fiducial.nas = []; +fiducial.lpa = []; +fiducial.rpa = []; + +% check if it is a suitable volumetric dataset +if isfield(data,'transform') + if ~isstr(location) + if strcmp(locationcoordinates, 'head') + % convert the headcoordinates location into voxel coordinates + loc = inv(data.transform) * [location(:); 1]; + loc = round(loc(1:3)); + elseif strcmp(locationcoordinates, 'voxel') + % the location is already in voxel coordinates + loc = round(location(1:3)); + else + error('you should specify locationcoordinates'); + end + else + if isequal(location,'auto') + if hasfun + if isequal(funcolorlim,'maxabs'); + loc = 'max'; + elseif isequal(funcolorlim, 'zeromax'); + loc = 'max'; + elseif isequal(funcolorlim, 'minzero'); + loc = 'min'; + else %if numerical + loc = 'max'; + end + else + loc = 'center'; + end; + else + loc = location; + end + end + + % determine the initial intersection of the cursor (xi yi zi) + if isstr(loc) && strcmp(loc, 'min') + if isempty(funparameter) + error('location is min, but no functional parameter specified'); + end + [minval, minindx] = min(fun(:)); + [xi, yi, zi] = ind2sub(dim, minindx); + elseif isstr(loc) && strcmp(loc, 'max') + if isempty(funparameter) + error('location is max, but no functional parameter specified'); + end + [maxval, maxindx] = max(fun(:)); + [xi, yi, zi] = ind2sub(dim, maxindx); + elseif isstr(loc) && strcmp(loc, 'center') + xi = round(dim(1)/2); + yi = round(dim(2)/2); + zi = round(dim(3)/2); + elseif ~isstr(loc) + % using nearest instead of round ensures that the position remains within the volume + xi = nearest(1:dim(1), loc(1)); + yi = nearest(1:dim(2), loc(2)); + zi = nearest(1:dim(3), loc(3)); + end + + % % do the actual plotting %% + nas = []; + lpa = []; + rpa = []; + interactive_flag = 1; % it happens at least once + while(interactive_flag) + interactive_flag = strcmp(interactive, 'yes'); + + xi = round(xi); xi = max(xi, 1); xi = min(xi, dim(1)); + yi = round(yi); yi = max(yi, 1); yi = min(yi, dim(2)); + zi = round(zi); zi = max(zi, 1); zi = min(zi, dim(3)); + + if interactive_flag + fprintf('\n'); + fprintf('click with mouse button to reposition the cursor\n'); + fprintf('press n/l/r on keyboard to record a fiducial position\n'); + fprintf('press q on keyboard to quit interactive mode\n'); + end + + ijk = [xi yi zi 1]'; + xyz = data.transform * ijk; + if hasfun && ~hasatlas + val = fun(xi, yi, zi); + fprintf('voxel %d, indices [%d %d %d], location [%.1f %.1f %.1f], value %f\n', sub2ind(dim, xi, yi, zi), ijk(1:3), xyz(1:3), val); + elseif hasfun && hasatlas + val = fun(xi, yi, zi); + fprintf('voxel %d, indices [%d %d %d], %s coordinates [%.1f %.1f %.1f], value %f\n', sub2ind(dim, xi, yi, zi), ijk(1:3), inputcoord, xyz(1:3), val); + elseif ~hasfun && ~hasatlas + fprintf('voxel %d, indices [%d %d %d], location [%.1f %.1f %.1f]\n', sub2ind(dim, xi, yi, zi), ijk(1:3), xyz(1:3)); + elseif ~hasfun && hasatlas + fprintf('voxel %d, indices [%d %d %d], %s coordinates [%.1f %.1f %.1f]\n', sub2ind(dim, xi, yi, zi), ijk(1:3), inputcoord, xyz(1:3)); + end + + if hasatlas + % determine the anatomical label of the current position + lab = atlas_lookup(atlas, (xyz(1:3)), 'inputcoord', inputcoord, 'queryrange', queryrange); + if isempty(lab) + fprintf([f,' labels: not found\n']); + else + fprintf([f,' labels: ']) + fprintf('%s', lab{1}); + for i=2:length(lab) + fprintf(', %s', lab{i}); + end + fprintf('\n'); + end + end + + % make vols and scales, containes volumes to be plotted (fun, ana, msk) + vols = {}; + if hasana; vols{1} = ana; scales{1} = []; end; % needed when only plotting ana + if hasfun; vols{2} = fun; scales{2} = [fcolmin fcolmax]; end; + if hasmsk; vols{3} = msk; scales{3} = [opacmin opacmax]; end; + + if isempty(vols) + % this seems to be a problem that people often have + error('no anatomy is present and no functional data is selected, please check your funparameter'); + end + + h1 = subplot(2,2,1); + [vols2D] = handle_ortho(vols, [xi yi zi], 2, dim); + plot2D(vols2D, scales); + xlabel('i'); ylabel('k'); axis(axis1); + if strcmp(crosshair1, 'yes'), crosshair([xi zi]); end + + h2 = subplot(2,2,2); + [vols2D] = handle_ortho(vols, [xi yi zi], 1, dim); + plot2D(vols2D, scales); + xlabel('j'); ylabel('k'); axis(axis1); + if strcmp(crosshair1, 'yes'), crosshair([yi zi]); end + + h3 = subplot(2,2,3); + [vols2D] = handle_ortho(vols, [xi yi zi], 3, dim); + plot2D(vols2D, scales); + xlabel('i'); ylabel('j'); axis(axis1); + if strcmp(crosshair1, 'yes'), crosshair([xi yi]); end + + if strcmp(colorbar1, 'yes'), + if hasfun + % vectorcolorbar = linspace(fcolmin, fcolmax,length(funcolormap)); + % imagesc(vectorcolorbar,1,vectorcolorbar);colormap(funcolormap); + subplot(2,2,4); + % use a normal Matlab coorbar, attach it to the invisible 4th subplot + caxis([fcolmin fcolmax]); + hc = colorbar; + set(hc, 'YLim', [fcolmin fcolmax]); + set(gca, 'Visible', 'off'); + else + warning('no colorbar possible without functional data') + end + end + + drawnow; + + if interactive_flag + try, [d1, d2, key] = ginput(1); catch, key='q'; end + if isempty(key) + % this happens if you press the apple key + % do nothing + elseif key=='q' + break; + elseif key=='l' + lpa = [xi yi zi]; + elseif key=='r' + rpa = [xi yi zi]; + elseif key=='n' + nas = [xi yi zi]; + elseif key=='i' || key=='j' || key=='k' || key=='m' + % update the view to a new position + if l1=='i' && l2=='k' && key=='i', zi = zi+1; + elseif l1=='i' && l2=='k' && key=='j', xi = xi-1; + elseif l1=='i' && l2=='k' && key=='k', xi = xi+1; + elseif l1=='i' && l2=='k' && key=='m', zi = zi-1; + elseif l1=='i' && l2=='j' && key=='i', yi = yi+1; + elseif l1=='i' && l2=='j' && key=='j', xi = xi-1; + elseif l1=='i' && l2=='j' && key=='k', xi = xi+1; + elseif l1=='i' && l2=='j' && key=='m', yi = yi-1; + elseif l1=='j' && l2=='k' && key=='i', zi = zi+1; + elseif l1=='j' && l2=='k' && key=='j', yi = yi-1; + elseif l1=='j' && l2=='k' && key=='k', yi = yi+1; + elseif l1=='j' && l2=='k' && key=='m', zi = zi-1; + end; + else + % update the view to a new position + l1 = get(get(gca, 'xlabel'), 'string'); + l2 = get(get(gca, 'ylabel'), 'string'); + switch l1, + case 'i' + xi = d1; + case 'j' + yi = d1; + case 'k' + zi = d1; + end + switch l2, + case 'i' + xi = d2; + case 'j' + yi = d2; + case 'k' + zi = d2; + end + end + end % if interactive_flag + if ~isempty(nas), fprintf('nas = [%f %f %f]\n', nas); fiducial.nas = nas; else fprintf('nas = undefined\n'); end + if ~isempty(lpa), fprintf('lpa = [%f %f %f]\n', lpa); fiducial.lpa = lpa; else fprintf('lpa = undefined\n'); end + if ~isempty(rpa), fprintf('rpa = [%f %f %f]\n', rpa); fiducial.rpa = rpa; else fprintf('rpa = undefined\n'); end + end % while interactive_flag +end + +function plot2D(vols2D, scales); +cla; +% put 2D volumes in fun, ana and msk +hasana = length(vols2D)>0 && ~isempty(vols2D{1}); +hasfun = length(vols2D)>1 && ~isempty(vols2D{2}); +hasmsk = length(vols2D)>2 && ~isempty(vols2D{3}); + +% the transpose is needed for displaying the matrix using the Matlab image() function +if hasana; ana = vols2D{1}'; end; +if hasfun; fun = vols2D{2}'; end; +if hasmsk; msk = vols2D{3}'; end; + + +if hasana + % scale anatomy between 0 and 1 + fprintf('scaling anatomy\n'); + amin = min(ana(:)); + amax = max(ana(:)); + ana = (ana-amin)./(amax-amin); + clear amin amax; + % convert anatomy into RGB values + ana = cat(3, ana, ana, ana); + ha = imagesc(ana); +end +hold on + +if hasfun + hf = imagesc(fun); + caxis(scales{2}); + % apply the opacity mask to the functional data + if hasmsk + % set the opacity + set(hf, 'AlphaData', msk) + set(hf, 'AlphaDataMapping', 'scaled') + alim(scales{3}); + elseif hasana + set(hf, 'AlphaData', 0.5) + end +end + +axis equal +axis tight +axis xy + +function [vols2D] = handle_ortho(vols, indx, slicedir, dim); + +% put 2Dvolumes in fun, ana and msk +if length(vols)>=1 && isempty(vols{1}); hasana=0; else ana=vols{1}; hasana=1; end; +if length(vols)>=2 + if isempty(vols{2}); hasfun=0; else fun=vols{2}; hasfun=1; end; +else hasfun=0; end +if length(vols)>=3 + if isempty(vols{3}); hasmsk=0; else msk=vols{3}; hasmsk=1; end; +else hasmsk=0; end + +% select the indices of the intersection +xi = indx(1); +yi = indx(2); +zi = indx(3); + +% select the slice to plot +if slicedir==1 + yi = 1:dim(2); + zi = 1:dim(3); +elseif slicedir==2 + xi = 1:dim(1); + zi = 1:dim(3); +elseif slicedir==3 + xi = 1:dim(1); + yi = 1:dim(2); +end + +% cut out the slice of interest +if hasana; ana = squeeze(ana(xi,yi,zi)); end; +if hasfun; fun = squeeze(fun(xi,yi,zi)); end; +if hasmsk; msk = squeeze(msk(xi,yi,zi)); end; + +%put fun, ana and msk in vols2D +if hasana; vols2D{1} = ana; end; +if hasfun; vols2D{2} = fun; end; +if hasmsk; vols2D{3} = msk; end; diff --git a/external/fieldtrip/plotting/ft_plot_sens.m b/external/fieldtrip/plotting/ft_plot_sens.m new file mode 100644 index 0000000..cfd0117 --- /dev/null +++ b/external/fieldtrip/plotting/ft_plot_sens.m @@ -0,0 +1,92 @@ +function hs = plot_sens(sens, varargin) + +% PLOT_SENS plots the position of the channels in the EEG or MEG sensor array +% +% Use as +% plot_sens(sens, ...) +% where the first argument is the sensor array as returned by READ_SENS +% or PREPARE_VOL_SENS. +% +% Optional input arguments should come in key-value pairs and can include +% 'style' plotting style for the points representing the channels, see plot3 (default = 'k.') +% 'coil' true/false, plot each individual coil or the channelposition (default = false) +% +% Example +% sens = read_sens('Subject01.ds'); +% plot_sens(sens, 'style', 'r*') + +% Copyright (C) 2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_plot_sens.m 1413 2010-07-15 14:40:26Z crimic $ + +warning('on', 'MATLAB:divideByZero'); + +% get the optional input arguments +keyvalcheck(varargin, 'optional', {'style', 'coil', 'label'}); +style = keyval('style', varargin); if isempty(style), style = 'k.'; end +coil = keyval('coil', varargin); if isempty(coil), coil = false; end +label = keyval('label', varargin); if isempty(coil), coil = false; end + +% convert yes/no string into boolean value +coil = istrue(coil); + +% everything is added to the current figure +holdflag = ishold; +hold on + +if coil + % simply plot the position of all coils + hs = plot3(sens.pnt(:,1), sens.pnt(:,2), sens.pnt(:,3), style); +else + % determine the position of each channel, which is for example the mean of + % two bipolar electrodes, or the bottom coil of a axial gradiometer + [chan.pnt, chan.label] = channelposition(sens); + hs = plot3(chan.pnt(:,1), chan.pnt(:,2), chan.pnt(:,3), style); + + if ~isempty(label) + for i=1:length(chan.label) + switch label + case {'on', 'yes'} + str = chan.label{i}; + case {'off', 'no'} + str = ''; + case {'label' 'labels'} + str = chan.label{i}; + case {'number' 'numbers'} + str = num2str(i); + otherwise + error('unsupported value for option ''label'''); + end % switch + text(chan.pnt(i,1), chan.pnt(i,2), chan.pnt(i,3), str); + end % for + end % if + +end + +axis vis3d +axis equal + +if ~nargout + clear hs +end +if ~holdflag + hold off +end + + diff --git a/external/fieldtrip/plotting/ft_plot_slice.m b/external/fieldtrip/plotting/ft_plot_slice.m new file mode 100644 index 0000000..db57d30 --- /dev/null +++ b/external/fieldtrip/plotting/ft_plot_slice.m @@ -0,0 +1,528 @@ +function plot_slice(data,varargin) +% +% PLOT_SLICE visualizes the slices of a MRI 3D volume +% +% Use as +% plot_slice(data, varargin) +% +% Some defaults for the additional arguments: +% +% 'nslices' = number of slices, (default = 4) +% 'slicerange' = range of slices in data, (default = 'auto') +% 'auto', full range of data +% [min max], coordinates of first and last slice in voxels +% 'slicedim' = dimension to slice 1 (x-axis) 2(y-axis) 3(z-axis) (default = 3) +% 'sliceindex' = progressive integer index of the slice (1..N) in the selected dimension +% 'title' = string, title of the figure window +% 'colorbar' = 'yes' or 'no' (default = 'yes') +% 'map' = colormap assigned to the slices (default='gray') +% 'transform' = transformation matrix from voxels to mm (default = eye(4)) +% 'flat2D' = flat multi-slice representation (default=false) +% 'tag' +% 'funcolorlim' +% 'funcolormap' +% 'opacitylim' +% 'opacitymap' +% +% Example +% mri = read_mri('Subject01.mri'); +% figure, plot_slice(mri,'title','3D volume','colorbar','yes','map','jet') + +% Copyright (C) 2009, Cristiano Micheli +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_plot_slice.m 1413 2010-07-15 14:40:26Z crimic $ + +warning('on', 'MATLAB:divideByZero'); + +% get the optional input arguments +slicerange = keyval('slicerange', varargin); if isempty(slicerange),slicerange='auto'; end +nslices = keyval('nslices', varargin); if isempty(nslices),nslices=4; end +slicedim = keyval('slicedim', varargin); if isempty(slicedim),slicedim=3; end +sliceindex = keyval('sliceindex', varargin); if isempty(sliceindex),sliceindex=[]; end +title_ = keyval('title', varargin); if isempty(title_),title_=''; end +colorbar1 = keyval('colorbar', varargin); if isempty(colorbar1),colorbar1='no'; end +funparameter = keyval('funparameter', varargin); if isempty(funparameter),funparameter=[]; end +anaparameter = keyval('anaparameter', varargin); if isempty(anaparameter),anaparameter='anatomy'; end +maskparameter = keyval('maskparameter', varargin); if isempty(maskparameter),maskparameter=[]; end +flat2D = keyval('flat2D', varargin); if isempty(flat2D),flat2D=false; end +map = keyval('map', varargin); if isempty(map),map='gray'; end +transform = keyval('transform', varargin); if isempty(transform),transform=eye(4); end +tag = keyval('tag', varargin); if isempty(tag),tag=[]; end +funcolorlim = keyval('funcolorlim', varargin); if isempty(funcolorlim),funcolorlim=[]; end +funcolormap = keyval('funcolormap', varargin); if isempty(funcolormap),funcolormap=[]; end +opacitylim = keyval('opacitylim', varargin); if isempty(opacitylim),opacitylim=[]; end +opacitymap = keyval('opacitymap', varargin); if isempty(opacitymap),opacitymap=[]; end + +%%% funparameter +% has fun? +if ~isempty(funparameter) + if issubfield(data, funparameter) + hasfun = 1; + fun = getsubfield(data, funparameter); + else + error('funparameter not found in data'); + end +else + hasfun = 0; + fprintf('no functional parameter\n'); + fun = []; +end +if hasfun + handle_fun(fun,funcolorlim,funcolormap) +end +%%% anaparameter +if isequal(anaparameter,'anatomy') + if isfield(data, 'anatomy') + hasana = 1; + mri8 = isa(data.anatomy, 'uint8'); + mri16 = isa(data.anatomy, 'uint16'); + % convert integers to single precision float if neccessary + if mri8 || mri16 + fprintf('converting anatomy to double\n'); + ana = double(data.anatomy); + else + ana = data.anatomy; + end + else + warning('no anatomical volume present, not plotting anatomy\n') + hasana = 0; + end +elseif isempty(anaparameter); + hasana = 0; + fprintf('not plotting anatomy\n'); +else + warning('do not understand anaparameter, not plotting anatomy\n') + hasana = 0; +end +%%% maskparameter +% has mask? +if ~isempty(maskparameter) + if issubfield(data, maskparameter) + if ~hasfun + error('you can not have a mask without functional data') + else + hasmsk = 1; + msk = getsubfield(data, maskparameter); + if islogical(msk) %otherwise sign() not posible + msk = double(msk); + end + end + else + error('maskparameter not found in data'); + end +else + hasmsk = 0; + fprintf('no masking parameter\n'); + msk = []; +end +if hasmsk + handle_msk(msk,opacitylim,funparameter,maskparameter,funcolorlim,opacitymap) +end + + +%%%%% select slices +ss = setdiff([1 2 3], slicedim); + +if ~isstr(slicerange) + ind_fslice = slicerange(1); + ind_lslice = slicerange(2); +elseif isequal(slicerange, 'auto') + if hasfun %default + if isfield(data,'inside') + ind_fslice = min(find(max(max(data.inside,[],ss(1)),[],ss(2)))); + ind_lslice = max(find(max(max(data.inside,[],ss(1)),[],ss(2)))); + else + ind_fslice = min(find(~isnan(max(max(fun,[],ss(1)),[],ss(2))))); + ind_lslice = max(find(~isnan(max(max(fun,[],ss(1)),[],ss(2))))); + end + elseif hasana %if only ana, no fun + ind_fslice = min(find(max(max(ana,[],ss(1)),[],ss(2)))); + ind_lslice = max(find(max(max(ana,[],ss(1)),[],ss(2)))); + else + error('no functional parameter and no anatomical parameter, can not plot'); + end +else + error('do not understand slicerange'); +end + +if nslices==1 + ind_allslice = (ind_fslice+ind_lslice)/2; +elseif nslices==2 + ind_allslice = [ind_fslice+(ind_lslice-ind_fslice)/5 ind_fslice+4*(ind_lslice-ind_fslice)/5]; +else + ind_allslice = linspace(ind_fslice,ind_lslice,nslices); +end +ind_allslice = round(ind_allslice); + + +% if i want to plot a 2D representation of several slices +if flat2D + plot_flatslice(hasana,hasfun,hasmsk,ana,fun,msk,slicedim,ind_allslice,colorbar1) +else + if isempty(sliceindex) + plot_slice_sub(ana,fun,msk,slicedim,ind_allslice,map,transform); + else + plot_slice_sub(ana,fun,msk,slicedim,sliceindex,map,transform); + end +end +if ~isempty(title_), title(title_); end + + + +function plot_slice_sub(data,fun,msk,slicedim,ind_allslice,map,transform) +if ~ishold, hold on, end +ds = size(data); + +% determine location of each anatomical voxel in its own voxel coordinates +i = 1:ds(1); +j = 1:ds(2); +k = 1:ds(3); +[I, J, K] = ndgrid(i, j, k); +ijk = [I(:) J(:) K(:) ones(prod(ds),1)]'; + +% determine location of each anatomical voxel in head coordinates +xyz = transform * ijk; +% xyz = permute(xyz,[2 1 3]); +% xdata = reshape(xyz(:,1), [ds(2) ds(1) ds(3)]); +% ydata = reshape(xyz(:,2), [ds(2) ds(1) ds(3)]); +% zdata = reshape(xyz(:,3), [ds(2) ds(1) ds(3)]); +xdata = reshape(xyz(1,:), [ds(1) ds(2) ds(3)]); +ydata = reshape(xyz(2,:), [ds(1) ds(2) ds(3)]); +zdata = reshape(xyz(3,:), [ds(1) ds(2) ds(3)]); + + +if slicedim == 3 + for i=1:length(ind_allslice) + cdata = squeeze(data(:,:,ind_allslice(i))); + xdata_ = squeeze(xdata(:,:,ind_allslice(i))); + ydata_ = squeeze(ydata(:,:,ind_allslice(i))); + zdata_ = squeeze(zdata(:,:,ind_allslice(i))); + news = surface('cdata',cdata,'alphadata',cdata, 'xdata',xdata_, 'ydata',ydata_, 'zdata',zdata_); + set(news,'facec','interp','edgec','n','facea',0.5); + end +elseif slicedim == 2 + for i=1:length(ind_allslice) + cdata = squeeze(data(:,ind_allslice(i),:)); + xdata_ = squeeze(xdata(:,ind_allslice(i),:)); + ydata_ = squeeze(ydata(:,ind_allslice(i),:)); + zdata_ = squeeze(zdata(:,ind_allslice(i),:)); + news = surface('cdata',cdata,'alphadata',cdata, 'xdata',xdata_, 'ydata',ydata_, 'zdata',zdata_); + set(news,'facec','interp','edgec','n','facea',0.5); + end +elseif slicedim == 1 + for i=1:length(ind_allslice) + cdata = squeeze(data(ind_allslice(i),:,:)); + xdata_ = squeeze(xdata(ind_allslice(i),:,:)); + ydata_ = squeeze(ydata(ind_allslice(i),:,:)); + zdata_ = squeeze(zdata(ind_allslice(i),:,:)); + news = surface('cdata',cdata,'alphadata',cdata, 'xdata',xdata_, 'ydata',ydata_, 'zdata',zdata_); + set(news,'facec','interp','edgec','n','facea',0.5); + end +end +view(45,45) +colormap(map) +axis off +axis vis3d +axis equal + +function plot2D(vols2D, scales) +cla; +% put 2D volumes in fun, ana and msk +hasana = length(vols2D)>0 && ~isempty(vols2D{1}); +hasfun = length(vols2D)>1 && ~isempty(vols2D{2}); +hasmsk = length(vols2D)>2 && ~isempty(vols2D{3}); + +% the transpose is needed for displaying the matrix using the Matlab image() function +if hasana; ana = vols2D{1}'; end; +if hasfun; fun = vols2D{2}'; end; +if hasmsk; msk = vols2D{3}'; end; + + +if hasana + % scale anatomy between 0 and 1 + fprintf('scaling anatomy\n'); + amin = min(ana(:)); + amax = max(ana(:)); + ana = (ana-amin)./(amax-amin); + clear amin amax; + % convert anatomy into RGB values + ana = cat(3, ana, ana, ana); +% ha = imagesc(ana); + plot_matrix(ana) +end +hold on + +if hasfun +% hf = imagesc(fun); + plot_matrix(fun) + caxis(scales{2}); + % apply the opacity mask to the functional data + if hasmsk + % set the opacity + set(hf, 'AlphaData', msk) + set(hf, 'AlphaDataMapping', 'scaled') + alim(scales{3}); + elseif hasana + set(hf, 'AlphaData', 0.5) + end +end + +axis equal +axis tight +axis xy + +function handle_fun(fun,funcolorlim,funcolormap) + % determine scaling min and max (fcolmin fcolmax) and funcolormap + funmin = min(fun(:)); + funmax = max(fun(:)); + % smart lims: make from auto other string + if isequal(funcolorlim,'auto') + if sign(funmin)>-1 && sign(funmax)>-1 + funcolorlim = 'zeromax'; + elseif sign(funmin)<1 && sign(funmax)<1 + funcolorlim = 'minzero'; + else + funcolorlim = 'maxabs'; + end + end + if ischar(funcolorlim) + % limits are given as string + if isequal(funcolorlim,'maxabs') + fcolmin = -max(abs([funmin,funmax])); + fcolmax = max(abs([funmin,funmax])); + if isequal(funcolormap,'auto'); funcolormap = 'jet'; end; + elseif isequal(funcolorlim,'zeromax') + fcolmin = 0; + fcolmax = funmax; + if isequal(funcolormap,'auto'); funcolormap = 'hot'; end; + elseif isequal(funcolorlim,'minzero') + fcolmin = funmin; + fcolmax = 0; + if isequal(funcolormap,'auto'); funcolormap = 'cool'; end; + else + error('do not understand cfg.funcolorlim'); + end + else + if ~isempty(funcolorlim) + % limits are numeric + fcolmin = funcolorlim(1); + fcolmax = funcolorlim(2); + end + % smart colormap + if isequal(funcolormap,'auto') + if sign(fcolmin) == -1 && sign(fcolmax) == 1 + funcolormap = 'jet'; + else + if fcolmin < 0 + funcolormap = 'cool'; + else + funcolormap = 'hot'; + end + end + end + end %if ischar + clear funmin funmax; + % ensure that the functional data is real + if ~isreal(fun) + fprintf('taking absolute value of complex data\n'); + fun = abs(fun); + end + +function handle_msk(msk,opacitylim,funparameter,maskparameter,funcolorlim,opacitymap) + mskmin = min(msk(:)); + mskmax = max(msk(:)); + % determine the opacity limits and the opacity map + % smart lims: make from auto other string, or equal to funcolorlim if funparameter == maskparameter + if isequal(opacitylim,'auto') + if isequal(funparameter,maskparameter) + opacitylim = funcolorlim; + else + if sign(mskmin)>-1 && sign(mskmax)>-1 + opacitylim = 'zeromax'; + elseif sign(mskmin)<1 && sign(mskmax)<1 + opacitylim = 'minzero'; + else + opacitylim = 'maxabs'; + end + end + end + if ischar(opacitylim) + % limits are given as string + switch opacitylim + case 'zeromax' + opacmin = 0; + opacmax = mskmax; + if isequal(opacitymap,'auto'), opacitymap = 'rampup'; end; + case 'minzero' + opacmin = mskmin; + opacmax = 0; + if isequal(opacitymap,'auto'), opacitymap = 'rampdown'; end; + case 'maxabs' + opacmin = -max(abs([mskmin, mskmax])); + opacmax = max(abs([mskmin, mskmax])); + if isequal(opacitymap,'auto'), opacitymap = 'vdown'; end; + otherwise + error('incorrect specification of cfg.opacitylim'); + end + else + if ~isempty(opacitylim) + % limits are numeric + opacmin = opacitylim(1); + opacmax = opacitylim(2); + end + if isequal(opacitymap,'auto') + if sign(opacmin)>-1 && sign(opacmax)>-1 + opacitymap = 'rampup'; + elseif sign(opacmin)<1 && sign(opacmax)<1 + opacitymap = 'rampdown'; + else + opacitymap = 'vdown'; + end + end + end % handling opacitylim and opacitymap + clear mskmin mskmax; + +function plot_flatslice(hasana,hasfun,hasmsk,ana,fun,msk,slicedim,ind_allslice,colorbar1) + +% make new ana, fun, msk, mskana with only the slices that will be plotted (slice dim is always third dimension) +if slicedim == 3 + if hasana; new_ana = ana(:,:,ind_allslice); clear ana; ana=new_ana; clear new_ana; end; + if hasfun; new_fun = fun(:,:,ind_allslice); clear fun; fun=new_fun; clear new_fun; end; + if hasmsk; new_msk = msk(:,:,ind_allslice); clear msk; msk=new_msk; clear new_msk; end; +elseif slicedim == 2 + if hasana; new_ana = ana(:,ind_allslice,:); clear ana; ana=new_ana; clear new_ana; end; + if hasfun; new_fun = fun(:,ind_allslice,:); clear fun; fun=new_fun; clear new_fun; end; + if hasmsk; new_msk = msk(:,ind_allslice,:); clear msk; msk=new_msk; clear new_msk; end; +elseif slicedim == 1 + if hasana; new_ana = ana(ind_allslice,:,:); clear ana; ana=new_ana; clear new_ana; end; + if hasfun; new_fun = fun(ind_allslice,:,:); clear fun; fun=new_fun; clear new_fun; end; + if hasmsk; new_msk = msk(ind_allslice,:,:); clear msk; msk=new_msk; clear new_msk; end; +else + error('Error: incorrect slice dimension specification') +end +%if hasmskana; new_mskana = mskana(:,:,ind_allslice); clear mskana; mskana=new_mskana; clear new_mskana; end; + +% update the dimensions of the volume +if hasana; dim=size(ana); else dim=size(fun); end; + +%%%%% make "quilts", that contain all slices on 2D patched sheet +% Number of patches along sides of Quilt (M and N) +% Size (in voxels) of side of patches of Quilt (m and n) + +if slicedim == 3 + m = dim(1); + n = dim(2); + if length(dim)==2 + dim(3) = 1; + end + M = ceil(sqrt(dim(3))); + N = ceil(sqrt(dim(3))); +elseif slicedim == 2 + m = dim(1); + n = dim(3); + M = ceil(sqrt(dim(2))); + N = ceil(sqrt(dim(2))); +elseif slicedim == 1 + m = dim(2); + n = dim(3); + M = ceil(sqrt(dim(1))); + N = ceil(sqrt(dim(1))); +end + +num_patch = N*M; +% if slicedim~=3 +% error('only supported for slicedim=3'); +% end +num_slice = (dim(slicedim)); +num_empt = num_patch-num_slice; + +% put empty slides on ana, fun, msk, mskana to fill Quilt up +if slicedim == 3 + if hasana; ana(:,:,end+1:num_patch)=0; end; + if hasfun; fun(:,:,end+1:num_patch)=0; end; + if hasmsk; msk(:,:,end+1:num_patch)=0; end; +elseif slicedim == 2 + if hasana; ana(:,end+1:num_patch,:)=0; end; + if hasfun; fun(:,end+1:num_patch,:)=0; end; + if hasmsk; msk(:,end+1:num_patch,:)=0; end; +elseif slicedim == 1 + if hasana; ana(end+1:num_patch,:,:)=0; end; + if hasfun; fun(end+1:num_patch,:,:)=0; end; + if hasmsk; msk(end+1:num_patch,:,:)=0; end; +end + +%if hasmskana; mskana(:,:,end:num_patch)=0; end; +% put the slices in the quilt +for iSlice = 1:num_slice + xbeg = floor((iSlice-1)./M); + ybeg = mod(iSlice-1, M); + if slicedim == 3 + if hasana + quilt_ana(ybeg.*m+1:(ybeg+1).*m, xbeg.*n+1:(xbeg+1).*n)=squeeze(ana(:,:,iSlice)); + end + if hasfun + quilt_fun(ybeg.*m+1:(ybeg+1).*m, xbeg.*n+1:(xbeg+1).*n)=squeeze(fun(:,:,iSlice)); + end + if hasmsk + quilt_msk(ybeg.*m+1:(ybeg+1).*m, xbeg.*n+1:(xbeg+1).*n)=squeeze(msk(:,:,iSlice)); + end + elseif slicedim == 2 + if hasana + quilt_ana(ybeg.*m+1:(ybeg+1).*m, xbeg.*n+1:(xbeg+1).*n)=squeeze(ana(:,iSlice,:)); + end + if hasfun + quilt_fun(ybeg.*m+1:(ybeg+1).*m, xbeg.*n+1:(xbeg+1).*n)=squeeze(fun(:,iSlice,:)); + end + if hasmsk + quilt_msk(ybeg.*m+1:(ybeg+1).*m, xbeg.*n+1:(xbeg+1).*n)=squeeze(msk(:,iSlice,:)); + end + elseif slicedim == 1 + if hasana + quilt_ana(ybeg.*m+1:(ybeg+1).*m, xbeg.*n+1:(xbeg+1).*n)=squeeze(ana(iSlice,:,:)); + end + if hasfun + quilt_fun(ybeg.*m+1:(ybeg+1).*m, xbeg.*n+1:(xbeg+1).*n)=squeeze(fun(iSlice,:,:)); + end + if hasmsk + quilt_msk(ybeg.*m+1:(ybeg+1).*m, xbeg.*n+1:(xbeg+1).*n)=squeeze(msk(iSlice,:,:)); + end + end + + % if hasmskana + % quilt_mskana(ybeg.*m+1:(ybeg+1).*m, xbeg.*n+1:(xbeg+1).*n)=squeeze(mskana(:,:,iSlice)); + % end +end +% make vols and scales, containes volumes to be plotted (fun, ana, msk) %added ingnie +if hasana; vols2D{1} = quilt_ana; scales{1} = []; end; % needed when only plotting ana +if hasfun; vols2D{2} = quilt_fun; scales{2} = [fcolmin fcolmax]; end; +if hasmsk; vols2D{3} = quilt_msk; scales{3} = [opacmin opacmax]; end; + +plot2D(vols2D, scales); +axis off + +if strcmp(colorbar1, 'yes'), + if hasfun + % use a normal Matlab colorbar + hc = colorbar; + set(hc, 'YLim', [fcolmin fcolmax]); + else + warning('no colorbar possible without functional data') + end +end + diff --git a/external/fieldtrip/plotting/ft_plot_text.m b/external/fieldtrip/plotting/ft_plot_text.m new file mode 100644 index 0000000..11a0a3c --- /dev/null +++ b/external/fieldtrip/plotting/ft_plot_text.m @@ -0,0 +1,121 @@ +function [varargout] = plot_text(X, Y, str, varargin) + +% PLOT_TEXT helper function for plotting text, which can also be used in +% combination with the multiple channel layout display in FieldTrip. +% +% Use as +% plot_text(X, Y, ...) +% where optional input arguments should come in key-value pairs and may +% include +% hpos +% vpos +% width +% height +% hlim +% vlim +% Color +% FontSize +% FontName +% HorizontalAlignment + +% Copyrights (C) 2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_plot_text.m 1413 2010-07-15 14:40:26Z crimic $ + +warning('on', 'MATLAB:divideByZero'); + +% get the optional input arguments +keyvalcheck(varargin, 'optional', {'hpos', 'vpos', 'width', 'height', 'hlim', 'vlim', 'Color', .... + 'FontSize', 'FontName', 'HorizontalAlignment','rotation','VerticalAlignment'}); +hpos = keyval('hpos', varargin); +vpos = keyval('vpos', varargin); +width = keyval('width', varargin); +height = keyval('height', varargin); +hlim = keyval('hlim', varargin); +vlim = keyval('vlim', varargin); +Color = keyval('Color', varargin); if isempty(Color), Color = 'k'; end +FontSize = keyval('FontSize', varargin); +FontName = keyval('FontName', varargin); +HorizontalAlignment = keyval('HorizontalAlignment', varargin); if isempty(HorizontalAlignment), HorizontalAlignment = 'center'; end +rotation = keyval('rotation', varargin); if isempty(rotation), rotation = 0; end +VerticalAlignment = keyval('VerticalAlignment', varargin); if isempty(VerticalAlignment), VerticalAlignment = 'middle'; end + +if isempty(hlim) && isempty(vlim) && isempty(hpos) && isempty(vpos) && isempty(height) && isempty(width) + % no scaling is needed, the input X and Y are already fine + % use a shortcut to speed up the plotting + +else + % use the full implementation + abc = axis; + if isempty(hlim) + hlim = abc([1 2]); + end + + if isempty(vlim) + vlim = abc([3 4]); + end + + if isempty(hpos); + hpos = (hlim(1)+hlim(2))/2; + end + + if isempty(vpos); + vpos = (vlim(1)+vlim(2))/2; + end + + if isempty(width), + width = hlim(2)-hlim(1); + end + + if isempty(height), + height = vlim(2)-vlim(1); + end + + % first shift the horizontal axis to zero + X = X - (hlim(1)+hlim(2))/2; + % then scale to length 1 + X = X ./ (hlim(2)-hlim(1)); + % then scale to the new width + X = X .* width; + % then shift to the new horizontal position + X = X + hpos; + + % first shift the vertical axis to zero + Y = Y - (vlim(1)+vlim(2))/2; + % then scale to length 1 + Y = Y ./ (vlim(2)-vlim(1)); + % then scale to the new width + Y = Y .* height; + % then shift to the new vertical position + Y = Y + vpos; + +end % shortcut + +h = text(X, Y, str); +set(h, 'HorizontalAlignment', HorizontalAlignment); +set(h, 'Color', Color); +set(h, 'rotation', rotation); +set(h, 'VerticalAlignment',VerticalAlignment); +if ~isempty(FontSize), set(h, 'FontSize', FontSize); end +if ~isempty(FontName), set(h, 'FontName', FontName); end + +% the (optional) output is the handle +if nargout == 1; + varargout{1} = h; +end diff --git a/external/fieldtrip/plotting/ft_plot_topo.m b/external/fieldtrip/plotting/ft_plot_topo.m new file mode 100644 index 0000000..e3bc5ee --- /dev/null +++ b/external/fieldtrip/plotting/ft_plot_topo.m @@ -0,0 +1,188 @@ +function Zi = ft_plot_topo(chanX, chanY, dat, varargin) + +% PLOT_TOPO interpolates and plots the 2-D spatial topography of the +% potential or field distribution over the head +% +% Use as +% ft_plot_topo(x, y, val, ...) +% +% Additional options should be specified in key-value pairs and can be +% 'hpos' +% 'vpos' +% 'width' +% 'height' +% 'shading' +% 'gridscale' +% 'mask' +% 'outline' +% 'isolines' +% 'interplim' +% 'interpmethod' +% 'style' +% 'datmask' + +% Copyrights (C) 2009, Giovanni Piantoni +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_plot_topo.m 1427 2010-07-19 11:44:01Z vlalit $ + +% these are for speeding up the plotting on subsequent calls +persistent previous_argin previous_maskimage + +warning('on', 'MATLAB:divideByZero'); + +% get the optional input arguments +keyvalcheck(varargin, 'optional', {'hpos', 'vpos', 'width', 'height', 'gridscale', 'shading', 'mask', 'outline', 'interplim', 'interpmethod','isolines','style', 'datmask'}); +hpos = keyval('hpos', varargin); if isempty(hpos); hpos = 0; end +vpos = keyval('vpos', varargin); if isempty(vpos); vpos = 0; end +width = keyval('width', varargin); if isempty(width); width = 1; end +height = keyval('height', varargin); if isempty(height); height = 1; end +gridscale = keyval('gridscale', varargin); if isempty(gridscale); gridscale = 67; end; % 67 in original +shading = keyval('shading', varargin); if isempty(shading); shading = 'flat'; end; +mask = keyval('mask', varargin); +outline = keyval('outline', varargin); +interplim = keyval('interplim', varargin); if isempty(interplim); interplim = 'electrodes'; end +interpmethod = keyval('interpmethod', varargin); if isempty(interpmethod); interpmethod = 'v4'; end +isolines = keyval('isolines', varargin); +style = keyval('style', varargin); if isempty(style); style = 'surfiso'; end % can be 'surf', 'iso', 'isofill', 'surfiso' +datmask = keyval('datmask', varargin); + +% everything is added to the current figure +holdflag = ishold; +hold on + +chanX = chanX * width + hpos; +chanY = chanY * height + vpos; + +if strcmp(interplim, 'electrodes'), + hlim = [min(chanX) max(chanX)]; + vlim = [min(chanY) max(chanY)]; +elseif strcmp(interplim, 'mask') && ~isempty(mask), + hlim = [inf -inf]; + vlim = [inf -inf]; + for i=1:length(mask) + hlim = [min([hlim(1); mask{i}(:,1)+hpos]) max([hlim(2); mask{i}(:,1)+hpos])]; + vlim = [min([vlim(1); mask{i}(:,2)+vpos]) max([vlim(2); mask{i}(:,2)+vpos])]; + end +else + hlim = [min(chanX) max(chanX)]; + vlim = [min(chanY) max(chanY)]; +end + +% check if all mask point are inside the limits otherwise redefine mask +newpoints = []; +if length(mask)==1 + % which channels are outside + outside = false(length(chanX),1); + inside = inside_contour([chanX chanY], mask{1}); + outside = ~inside; + newpoints = [chanX(outside) chanY(outside)]; +end + + +% try to speed up the preparation of the mask on subsequent calls +current_argin = {chanX, chanY, gridscale, mask, datmask}; +if isequal(current_argin, previous_argin) + % don't construct the binary image, but reuse it from the previous call + maskimage = previous_maskimage; +elseif ~isempty(mask) + % convert the mask into a binary image + maskimage = false(gridscale); + %hlim = [min(chanX) max(chanX)]; + %vlim = [min(chanY) max(chanY)]; + xi = linspace(hlim(1), hlim(2), gridscale); % x-axis for interpolation (row vector) + yi = linspace(vlim(1), vlim(2), gridscale); % y-axis for interpolation (row vector) + [Xi,Yi] = meshgrid(xi', yi); + if ~isempty(newpoints) + tmp = [mask{1};newpoints]; + indx = convhull(tmp(:,1),tmp(:,2)); + mask{1} = tmp(indx,:); + end + for i=1:length(mask) + mask{i}(:,1) = mask{i}(:,1)+hpos; + mask{i}(:,2) = mask{i}(:,2)+vpos; + mask{i}(end+1,:) = mask{i}(1,:); % force them to be closed + maskimage(inside_contour([Xi(:) Yi(:)], mask{i})) = true; + end + +else + maskimage = []; +end + + +% adjust maskimage to also mask channels as specified in maskdat +if ~isempty(datmask) + xi = linspace(hlim(1), hlim(2), gridscale); % x-axis for interpolation (row vector) + yi = linspace(vlim(1), vlim(2), gridscale); % y-axis for interpolation (row vector) + maskimagetmp = griddata(chanX', chanY, datmask, xi', yi, 'nearest'); % interpolate the mask data + if isempty(maskimage) + maskimage = maskimagetmp; + else + maskimagetmp = maskimage + maskimagetmp; + maskimage = maskimagetmp > 1; + end +end + +xi = linspace(hlim(1), hlim(2), gridscale); % x-axis for interpolation (row vector) +yi = linspace(vlim(1), vlim(2), gridscale); % y-axis for interpolation (row vector) +[Xi,Yi,Zi] = griddata(chanX', chanY, dat, xi', yi, interpmethod); % interpolate the topographic data + +if ~isempty(maskimage) + % apply anatomical mask to the data, i.e. that determines that the interpolated data outside the circle is not displayed + Zi(~maskimage) = NaN; +end + + +% plot the outline of the head, ears and nose +for i=1:length(outline) + xval = outline{i}(:,1) * width + hpos; + yval = outline{i}(:,2) * height + vpos; + ft_plot_vector(xval, yval, 'Color','k', 'LineWidth',2) +end + + +% Create isolines +if strcmp(style,'iso') || strcmp(style,'surfiso') + if ~isempty(isolines) + contour(Xi,Yi,Zi,isolines,'k'); + end +end + +% Plot surface +if strcmp(style,'surf') || strcmp(style,'surfiso') + deltax = xi(2)-xi(1); % length of grid entry + deltay = yi(2)-yi(1); % length of grid entry + h = surface(Xi-deltax/2,Yi-deltay/2,zeros(size(Zi)), Zi, 'EdgeColor', 'none', 'FaceColor', shading); +end + +% Plot filled contours +if strcmp(style,'isofill') && ~isempty(isolines) + contourf(Xi,Yi,Zi,isolines,'k'); +end + + + +% remember the current input arguments, so that they can be +% reused on a subsequent call in case the same input argument is given +previous_argin = current_argin; +previous_maskimage = maskimage; + +if ~holdflag + hold off +end + diff --git a/external/fieldtrip/plotting/ft_plot_topo3d.m b/external/fieldtrip/plotting/ft_plot_topo3d.m new file mode 100644 index 0000000..894a19e --- /dev/null +++ b/external/fieldtrip/plotting/ft_plot_topo3d.m @@ -0,0 +1,180 @@ +function plot_topo3d(pnt, val, varargin) + +% PLOT_TOPO3D makes a 3-D topographic representation of the electric +% potential or field at the sensor locations +% +% Use as +% plot_topo3d(pos, val, ...); +% where the channel positions are given as a Nx3 matrix and the values are +% given as Nx1 vector. + +% Optional input arguments should be specified in key-value pairs and can include +% ... +% +% See also PLOT_TOPO2D, PLOTTING + +% Copyright (C) 2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_plot_topo3d.m 1413 2010-07-15 14:40:26Z crimic $ + +warning('on', 'MATLAB:divideByZero'); + +% get the optional input arguments +topostyle = keyval('topostyle', varargin); if isempty(topostyle), topostyle = 'color'; end +contourstyle = keyval('contourstyle', varargin); if isempty(contourstyle), contourstyle = false; end +isocontour = keyval('isocontour', varargin); if isempty(isocontour), isocontour = 'auto'; end + +% everything is added to the current figure +holdflag = ishold; +hold on + +% the interpolation requires a triangulation +tri = projecttri(pnt, 'delaunay'); + +if ~isequal(topostyle, false) + switch topostyle + case 'color' + % plot a 2D or 3D triangulated surface with linear interpolation + if length(val)==size(pnt,1) + hs = patch('Vertices', pnt, 'Faces', tri, 'FaceVertexCData', val, 'FaceColor', 'interp'); + else + hs = patch('Vertices', pnt, 'Faces', tri, 'CData', val, 'FaceColor', 'flat'); + end + set(hs, 'EdgeColor', 'none'); + set(hs, 'FaceLighting', 'none'); + otherwise + error('unsupported topostyle'); + end % switch contourstyle +end % plot the interpolated topography + + +if ~isequal(contourstyle, false) + + if isequal(isocontour, 'auto') + minval = min(val); + maxval = max(val); + scale = max(abs(minval), abs(maxval)); + scale = 10^(floor(log10(scale))-1); + minval = floor(minval/scale)*scale; + maxval = ceil(maxval/scale)*scale; + isocontour = minval:scale:maxval; + end + + triangle_val = val(tri); + triangle_min = min(triangle_val, [], 2); + triangle_max = max(triangle_val, [], 2); + + for cnt_indx=1:length(isocontour) + cnt = isocontour(cnt_indx); + use = cnt>=triangle_min & cnt<=triangle_max; + counter = 0; + intersect1 = []; + intersect2 = []; + + for tri_indx=find(use)' + pos = pnt(tri(tri_indx,:), :); + v(1) = triangle_val(tri_indx,1); + v(2) = triangle_val(tri_indx,2); + v(3) = triangle_val(tri_indx,3); + la(1) = (cnt-v(1)) / (v(2)-v(1)); % abcissa between vertex 1 and 2 + la(2) = (cnt-v(2)) / (v(3)-v(2)); % abcissa between vertex 2 and 3 + la(3) = (cnt-v(3)) / (v(1)-v(3)); % abcissa between vertex 1 and 2 + abc(1,:) = pos(1,:) + la(1) * (pos(2,:) - pos(1,:)); + abc(2,:) = pos(2,:) + la(2) * (pos(3,:) - pos(2,:)); + abc(3,:) = pos(3,:) + la(3) * (pos(1,:) - pos(3,:)); + counter = counter + 1; + sel = find(la>=0 & la<=1); + intersect1(counter, :) = abc(sel(1),:); + intersect2(counter, :) = abc(sel(2),:); + end + + % remember the details for external reference + contour(cnt_indx).level = cnt; + contour(cnt_indx).n = counter; + contour(cnt_indx).intersect1 = intersect1; + contour(cnt_indx).intersect2 = intersect2; + end + + % collect all different contour isocontour for plotting + intersect1 = []; + intersect2 = []; + cntlevel = []; + for cnt_indx=1:length(isocontour) + intersect1 = [intersect1; contour(cnt_indx).intersect1]; + intersect2 = [intersect2; contour(cnt_indx).intersect2]; + cntlevel = [cntlevel; ones(contour(cnt_indx).n,1) * isocontour(cnt_indx)]; + end + + X = [intersect1(:,1) intersect2(:,1)]'; + Y = [intersect1(:,2) intersect2(:,2)]'; + C = [cntlevel(:) cntlevel(:)]'; + + if size(pnt,2)>2 + Z = [intersect1(:,3) intersect2(:,3)]'; + else + Z = zeros(2, length(cntlevel)); + end + + switch contourstyle + case 'black' + % make black-white contours + hc = []; + for i=1:length(cntlevel) + if cntlevel(i)>0 + linestyle = '-'; + linewidth = 1; + elseif cntlevel(i)<0 + linestyle = '--'; + linewidth = 1; + else + linestyle = '-'; + linewidth = 2; + end + h1 = patch('XData', X(:,i), 'Ydata', Y(:,i), ... + 'ZData', Z(:,i), 'CData', C(:,i), ... + 'facecolor','none','edgecolor','black', ... + 'linestyle', linestyle, 'linewidth', linewidth, ... + 'userdata',cntlevel(i)); + hc = [hc; h1]; + end + + case 'color' + % make full-color contours + hc = []; + for i=1:length(cntlevel) + h1 = patch('XData', X(:,i), 'Ydata', Y(:,i), ... + 'ZData', Z(:,i), 'CData', C(:,i), ... + 'facecolor','none','edgecolor','flat',... + 'userdata',cntlevel(i)); + hc = [hc; h1]; + end + + otherwise + error('unsupported contourstyle'); + end % switch contourstyle + +end % plot the contours + +axis off +axis vis3d +axis equal + +if ~holdflag + hold off +end diff --git a/external/fieldtrip/plotting/ft_plot_vector.m b/external/fieldtrip/plotting/ft_plot_vector.m new file mode 100644 index 0000000..9eccb30 --- /dev/null +++ b/external/fieldtrip/plotting/ft_plot_vector.m @@ -0,0 +1,300 @@ +function [varargout] = plot_vector(varargin) + +% PLOT_VECTOR +% +% Use as +% plot_vector(Y, ...) +% plot_vector(X, Y, ...) +% where X and Y are similar as the input to the Matlab plot function. +% +% Additional options should be specified in key-value pairs and can be +% 'hpos' +% 'vpos' +% 'width' +% 'height' +% 'hlim' +% 'vlim' +% 'style' +% 'label' +% 'fontsize' +% 'axis' can be 'yes' or 'no' +% 'box' can be 'yes' or 'no' +% 'highlight' +% 'highlightstyle' +% 'color' +% 'linewidth' +% 'markersize' +% 'markerfacecolor' +% +% Example use +% plot_vector(randn(1,100), 'width', 1, 'height', 1, 'hpos', 0, 'vpos', 0) + +% Copyrights (C) 2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_plot_vector.m 1413 2010-07-15 14:40:26Z crimic $ + +warning('on', 'MATLAB:divideByZero'); + +if nargin>1 && all(cellfun(@isnumeric, varargin(1:2))) + % the function was called like plot(x, y, ...) + hdat = varargin{1}; + vdat = varargin{2}; + varargin = varargin(3:end); +else + % the function was called like plot(y, ...) + vdat = varargin{1}; + if any(size(vdat)==1) + % ensure that it is a column vector + vdat = vdat(:); + end + hdat = 1:size(vdat,1); + varargin = varargin(2:end); +end + +% get the optional input arguments +keyvalcheck(varargin, 'optional', {'hpos', 'vpos', 'width', 'height', 'hlim', 'vlim', 'style', 'label', ... + 'fontsize', 'axis', 'box','highlight','highlightstyle','color', 'linewidth','markersize','markerfacecolor'}); +hpos = keyval('hpos', varargin); +vpos = keyval('vpos', varargin); +width = keyval('width', varargin); +height = keyval('height', varargin); +hlim = keyval('hlim', varargin); if isempty(hlim), hlim = 'maxmin'; end +vlim = keyval('vlim', varargin); if isempty(vlim), vlim = 'maxmin'; end +style = keyval('style', varargin); if isempty(style), style = '-'; end +label = keyval('label', varargin); +fontsize = keyval('fontsize', varargin); +axis = keyval('axis', varargin); if isempty(axis), axis = false; end +box = keyval('box', varargin); if isempty(box), box = false; end +color = keyval('color', varargin); +linewidth = keyval('linewidth', varargin); if isempty(linewidth), linewidth = 0.5; end +highlight = keyval('highlight', varargin); +highlightstyle = keyval('highlightstyle', varargin); if isempty(highlightstyle), highlightstyle = 'box'; end +markersize = keyval('markersize', varargin); if isempty(markersize), markersize = 6; end +markerfacecolor = keyval('markerfacecolor', varargin); if isempty(markerfacecolor), markerfacecolor = 'none'; end +% convert the yes/no strings into boolean values +axis = istrue(axis); +box = istrue(box); + +% everything is added to the current figure +holdflag = ishold; +hold on + +if ischar(hlim) + switch hlim + case 'maxmin' + hlim = [min(hdat) max(hdat)]; + case 'maxabs' + hlim = max(abs(hdat)); + hlim = [-hlim hlim]; + otherwise + error('unsupported option for hlim') + end % switch +end % if ischar + +if ischar(vlim) + switch vlim + case 'maxmin' + vlim = [min(vdat(:)) max(vdat(:))]; + case 'maxabs' + vlim = max(abs(vdat(:))); + vlim = [-vlim vlim]; + otherwise + error('unsupported option for vlim') + end % switch +end % if ischar + +if vlim(1)==vlim(2) + % vertical scaling cannot be determined, behave consistent to the plot() function + vlim = [-1 1]; +end + +% these must be floating point values and not integers, otherwise the scaling fails +hdat = double(hdat); +vdat = double(vdat); +hlim = double(hlim); +vlim = double(vlim); + +if isempty(hpos) && ~isempty(hlim) + hpos = (hlim(1)+hlim(2))/2; +end +if isempty(vpos) && ~isempty(vlim) + vpos = (vlim(1)+vlim(2))/2; +end + +if isempty(width) && ~isempty(hlim) + width = hlim(2)-hlim(1); +end + +if isempty(height) && ~isempty(vlim) + height = vlim(2)-vlim(1); +end + +% first shift the horizontal axis to zero +hdat = hdat - (hlim(1)+hlim(2))/2; +% then scale to length 1 +if hlim(2)-hlim(1)~=0 + hdat = hdat ./ (hlim(2)-hlim(1)); +else + hdat = hdat /hlim(1); +end +% then scale to the new width +hdat = hdat .* width; +% then shift to the new horizontal position +hdat = hdat + hpos; +% first shift the vertical axis to zero +vdat = vdat - (vlim(1)+vlim(2))/2; +% then scale to length 1 +vdat = vdat / (vlim(2)-vlim(1)); +% then scale to the new width +vdat = vdat .* height; +% then shift to the new vertical position +vdat = vdat + vpos; + + +% plotting lines +if isempty(color) + h = plot(hdat, vdat, style, 'LineWidth', linewidth,'markersize',markersize,'markerfacecolor',markerfacecolor); +else + h = plot(hdat, vdat, style, 'LineWidth', linewidth, 'Color', color,'markersize',markersize,'markerfacecolor',markerfacecolor); +end + + +if ~isempty(highlight) + switch highlightstyle + case 'box' + % find the sample number where the highlight begins and ends + if ~islogical(highlight) + highlight=logical(highlight); + warning('converting mask to logical values') + end + begsample = find(diff([0 highlight 0])== 1); + endsample = find(diff([0 highlight 0])==-1)-1; + for i=1:length(begsample) + begx = hdat(begsample(i)); + endx = hdat(endsample(i)); + plot_box([begx endx vpos-height/2 vpos+height/2], 'facecolor', [.6 .6 .6], 'edgecolor', 'none'); + end + % plotting lines again, otherwise box will always be on top + if isempty(color) + h = plot(hdat, vdat, style, 'LineWidth', linewidth,'markersize',markersize,'markerfacecolor',markerfacecolor); + else + h = plot(hdat, vdat, style, 'LineWidth', linewidth, 'Color', color,'markersize',markersize,'markerfacecolor',markerfacecolor); + end + case 'thickness' + % find the sample number where the highligh begins and ends + if ~islogical(highlight) + highlight=logical(highlight); + warning('converting mask to logical values') + end + begsample = find(diff([0 highlight 0])== 1); + endsample = find(diff([0 highlight 0])==-1)-1; + linecolor = get(h,'Color'); % get current line color + for i=1:length(begsample) + hor = hdat(begsample(i):endsample(i)); + ver = vdat(begsample(i):endsample(i)); + plot(hor,ver,'linewidth',4*linewidth,'linestyle','-','Color', linecolor); % changed 3* to 4*, as 3* appeared to have no effect + end + case 'saturation' + % find the sample number where the highligh begins and ends + if ~islogical(highlight) + highlight=logical(highlight); + warning('converting mask to logical values') + end + highlight = ~highlight; % invert the mask + begsample = find(diff([0 highlight 0])== 1); + endsample = find(diff([0 highlight 0])==-1)-1; + linecolor = get(h,'Color'); % get current line color + linecolor = (linecolor * 0.2) + 0.8; % change saturation of color + for i=1:length(begsample) + hor = hdat(begsample(i):endsample(i)); + ver = vdat(begsample(i):endsample(i)); + plot(hor,ver,'color',linecolor); + end + case 'opacity' + error('unsupported highlightstyle') + otherwise + error('unsupported highlightstyle') + end % switch highlightstyle +end + + +if ~isempty(label) + boxposition(1) = hpos - width/2; + boxposition(2) = hpos + width/2; + boxposition(3) = vpos - height/2; + boxposition(4) = vpos + height/2; + h = text(boxposition(1), boxposition(4), label); + if ~isempty(fontsize) + set(h, 'Fontsize', fontsize); + end +end + +if box + boxposition = zeros(1,4); + % this plots a box around the original hpos/vpos with appropriate width/height + x1 = hpos - width/2; + x2 = hpos + width/2; + y1 = vpos - height/2; + y2 = vpos + height/2; + + X = [x1 x2 x2 x1 x1]; + Y = [y1 y1 y2 y2 y1]; + line(X, Y); + + % % this plots a box around the original hpos/vpos with appropriate width/height + % boxposition(1) = hpos - width/2; + % boxposition(2) = hpos + width/2; + % boxposition(3) = vpos - height/2; + % boxposition(4) = vpos + height/2; + % plot_box(boxposition, 'facecolor', 'none', 'edgecolor', 'k'); + + % this plots a box around the complete data + % boxposition(1) = hlim(1); + % boxposition(2) = hlim(2); + % boxposition(3) = vlim(1); + % boxposition(4) = vlim(2); + % plot_box(boxposition, 'hpos', hpos, 'vpos', vpos, 'width', width, 'height', height, 'hlim', hlim, 'vlim', vlim); +end + +if axis + % determine where the original [0, 0] in the data is located in the scaled and shifted axes + x0 = interp1(hlim, hpos + [-width/2 width/2 ], 0, 'linear', 'extrap'); + y0 = interp1(vlim, vpos + [-height/2 height/2], 0, 'linear', 'extrap'); + + X = [hpos-width/2 hpos+width/2]; + Y = [y0 y0]; + plot_line(X, Y); + % str = sprintf('%g', hlim(1)); plot_text(X(1), Y(1), str); + % str = sprintf('%g', hlim(2)); plot_text(X(2), Y(2), str); + + X = [x0 x0]; + Y = [vpos-height/2 vpos+height/2]; + plot_line(X, Y); + % str = sprintf('%g', vlim(1)); plot_text(X(1), Y(1), str); + % str = sprintf('%g', vlim(2)); plot_text(X(2), Y(2), str); +end + +% the (optional) output is the handle +if nargout == 1; + varargout{1} = h; +end + +if ~holdflag + hold off +end diff --git a/external/fieldtrip/plotting/ft_plot_vol.m b/external/fieldtrip/plotting/ft_plot_vol.m new file mode 100644 index 0000000..1fb5395 --- /dev/null +++ b/external/fieldtrip/plotting/ft_plot_vol.m @@ -0,0 +1,98 @@ +function plot_vol(vol, varargin) + +% PLOT_VOL visualizes the boundaries in the vol structure constituting the +% geometrical information of the forward model +% +% Use as +% hs = plot_vol(vol, varargin) +% +% Graphic facilities are available for vertices, edges and faces. A list of +% the arguments is given below with the correspondent admitted choices. +% +% 'facecolor' [r g b] values or string, for example 'brain', 'cortex', 'skin', 'black', 'red', 'r' +% 'vertexcolor' [r g b] values or string, for example 'brain', 'cortex', 'skin', 'black', 'red', 'r' +% 'edgecolor' [r g b] values or string, for example 'brain', 'cortex', 'skin', 'black', 'red', 'r' +% 'faceindex' true or false +% 'vertexindex' true or false +% +% Example +% vol.r = [86 88 92 100]; +% vol.o = [0 0 40]; +% figure, plot_vol(vol) + +% Copyright (C) 2009, Cristiano Micheli +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_plot_vol.m 1413 2010-07-15 14:40:26Z crimic $ + +warning('on', 'MATLAB:divideByZero'); + +% get the optional input arguments +keyvalcheck(varargin, 'forbidden', {'faces', 'edges', 'vertices'}); +faceindex = keyval('faceindex', varargin); if isempty(faceindex),faceindex = 'none';end +vertexindex = keyval('vertexindex', varargin); if isempty(vertexindex),vertexindex ='none';end +vertexsize = keyval('vertexsize', varargin); if isempty(vertexsize), vertexsize = 10; end +facecolor = keyval('facecolor', varargin); if isempty(facecolor),facecolor = 'white'; end +vertexcolor = keyval('vertexcolor', varargin); if isempty(vertexcolor),vertexcolor ='none';end +edgecolor = keyval('edgecolor', varargin); if isempty(edgecolor),edgecolor = 'k';end +facealpha = keyval('facealpha', varargin); if isempty(facealpha),facealpha = 1;end +map = keyval('colormap', varargin); + +faceindex = istrue(faceindex); +vertexindex = istrue(vertexindex); + +% we will probably need a sphere, so let's prepare one +[pnt, tri] = icosahedron162; + +% prepare a single or multiple triangulated boundaries +switch ft_voltype(vol) + case {'singlesphere' 'concentric'} + vol.r = sort(vol.r); + bnd = []; + for i=1:length(vol.r) + bnd(i).pnt(:,1) = pnt(:,1)*vol.r(i) + vol.o(1); + bnd(i).pnt(:,2) = pnt(:,2)*vol.r(i) + vol.o(2); + bnd(i).pnt(:,3) = pnt(:,3)*vol.r(i) + vol.o(3); + bnd(i).tri = tri; + end + + case 'multisphere' + bnd = []; + for i=1:length(vol.label) + bnd(i).pnt(:,1) = pnt(:,1)*vol.r(i) + vol.o(i,1); + bnd(i).pnt(:,2) = pnt(:,2)*vol.r(i) + vol.o(i,2); + bnd(i).pnt(:,3) = pnt(:,3)*vol.r(i) + vol.o(i,3); + bnd(i).tri = tri; + end + + case {'bem', 'dipoli', 'asa', 'avo', 'bemcp', 'nolte'} + % these already contain one or multiple triangulated surfaces for the boundaries + bnd = vol.bnd; + + otherwise + error('unsupported voltype') +end + + +% plot the triangulated surfaces of the volume conduction model +for i=1:length(bnd) + plot_mesh(bnd(i),'faceindex',faceindex,'vertexindex',vertexindex, ... + 'vertexsize',vertexsize,'facecolor',facecolor,'edgecolor',edgecolor, ... + 'vertexcolor',vertexcolor,'facealpha',facealpha); +end + diff --git a/external/fieldtrip/plotting/ft_select_box.m b/external/fieldtrip/plotting/ft_select_box.m new file mode 100644 index 0000000..b9fd45a --- /dev/null +++ b/external/fieldtrip/plotting/ft_select_box.m @@ -0,0 +1,52 @@ +function [x, y] = select_box(handle, eventdata, varargin) + +% SELECT_BOX helper function for selecting a rectangular region +% in the current figure using the mouse. +% +% Use as +% [x, y] = select_box(...) +% +% It returns a 2-element vector x and a 2-element vector y +% with the corners of the selected region. +% +% Optional input arguments should come in key-value pairs and can include +% 'multiple' true/false, make multiple selections by dragging, clicking +% in one will finalize the selection (default = false) + +% Copyright (C) 2006, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_select_box.m 1413 2010-07-15 14:40:26Z crimic $ + +% get the optional arguments +multiple = keyval('multiple', varargin); if isempty(multiple), multiple = false; end + +if multiple + error('not yet implemented'); +else + k = waitforbuttonpress; + point1 = get(gca,'CurrentPoint'); % button down detected + finalRect = rbbox; % return figure units + point2 = get(gca,'CurrentPoint'); % button up detected + point1 = point1(1,1:2); % extract x and y + point2 = point2(1,1:2); + x = sort([point1(1) point2(1)]); + y = sort([point1(2) point2(2)]); +end + + diff --git a/external/fieldtrip/plotting/ft_select_channel.m b/external/fieldtrip/plotting/ft_select_channel.m new file mode 100644 index 0000000..53c1680 --- /dev/null +++ b/external/fieldtrip/plotting/ft_select_channel.m @@ -0,0 +1,158 @@ +function ft_select_channel(handle, eventdata, varargin) + +% SELECT_CHANNEL is a helper function that can be used as callback function +% in a figure. It allows the user to select a channel. The channel labels +% are returned. +% +% Use as +% label = select_channel(h, eventdata, ...) +% The first two arguments are automatically passed by Matlab to any +% callback function. +% +% Additional options should be specified in key-value pairs and can be +% 'callback' = function handle to be executed after channels have been selected +% +% You can pass additional arguments to the callback function in a cell-array +% like {@function_handle,arg1,arg2} +% +% Example +% % create a figure +% lay = prepare_layout([]) +% plot_lay(lay) +% +% % add the required guidata +% info = guidata(gcf) +% info.x = lay.pos(:,1); +% info.y = lay.pos(:,2); +% info.label = lay.label +% guidata(gcf, info) +% +% % add this function as the callback to make a single selection +% set(gcf, 'WindowButtonDownFcn', {@select_channel, 'callback', @disp}) +% +% % or to make multiple selections +% set(gcf, 'WindowButtonDownFcn', {@select_channel, 'multiple', true, 'callback', @disp, 'event', 'WindowButtonDownFcn'}) +% set(gcf, 'WindowButtonUpFcn', {@select_channel, 'multiple', true, 'callback', @disp, 'event', 'WindowButtonDownFcn'}) +% set(gcf, 'WindowButtonMotionFcn', {@select_channel, 'multiple', true, 'callback', @disp, 'event', 'WindowButtonDownFcn'}) +% +% Subsequently you can click in the figure and you'll see that the disp +% function is executed as callback and that it displays the selected +% channels. + +% Copyright (C) 2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_select_channel.m 1427 2010-07-19 11:44:01Z vlalit $ + +% get optional input arguments +callback = keyval('callback', varargin); +multiple = keyval('multiple', varargin); if isempty(multiple), multiple = false; end + +% convert 'yes/no' string to boolean value +multiple = istrue(multiple); + +if multiple + % the selection is done using select_range, which will subsequently call select_channel_multiple + set(gcf, 'WindowButtonDownFcn', {@ft_select_range, 'multiple', true, 'callback', {@select_channel_multiple, callback}, 'event', 'WindowButtonDownFcn'}); + set(gcf, 'WindowButtonUpFcn', {@ft_select_range, 'multiple', true, 'callback', {@select_channel_multiple, callback}, 'event', 'WindowButtonUpFcn'}); + set(gcf, 'WindowButtonMotionFcn', {@ft_select_range, 'multiple', true, 'callback', {@select_channel_multiple, callback}, 'event', 'WindowButtonMotionFcn'}); +else + % the selection is done using select_channel_single + pos = get(gca, 'CurrentPoint'); + pos = pos(1,1:2); + select_channel_single(pos, callback) +end % if multiple + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION to assist in the selection of a single channel +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function select_channel_single(pos, callback) + +info = guidata(gcf); +x = info.x; +y = info.y; +label = info.label; + +% compute a tolerance measure +distance = dist([x y]'); +distance = triu(distance, 1); +distance = distance(:); +distance = distance(distance>0); +distance = median(distance); +tolerance = 0.3*distance; + +% compute the distance between the clicked point and all channels +dx = x - pos(1); +dy = y - pos(2); +dd = sqrt(dx.^2 + dy.^2); +[d, i] = min(dd); +if d=range(i, 1) & x<=range(i, 2) & y>=range(i, 3) & y<=range(i, 4)); +end +label = label(select); + +% execute the original callback with the selected channels as input argument +if any(select) + if ~isempty(callback) + if isa(callback, 'cell') + % the callback specifies a function and additional arguments + funhandle = callback{1}; + funargs = callback(2:end); + feval(funhandle, label, funargs{:}); + else + % the callback only specifies a function + funhandle = callback; + feval(funhandle, label); + end + end +end diff --git a/external/fieldtrip/plotting/ft_select_circle.m b/external/fieldtrip/plotting/ft_select_circle.m new file mode 100644 index 0000000..63fc294 --- /dev/null +++ b/external/fieldtrip/plotting/ft_select_circle.m @@ -0,0 +1,21 @@ +function select_circle + +% SELECT_CIRCLE + +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_select_circle.m 1417 2010-07-15 15:33:01Z crimic $ diff --git a/external/fieldtrip/plotting/ft_select_contour.m b/external/fieldtrip/plotting/ft_select_contour.m new file mode 100644 index 0000000..9fc0006 --- /dev/null +++ b/external/fieldtrip/plotting/ft_select_contour.m @@ -0,0 +1,21 @@ +function select_contour + +% SELECT_CONTOUR + +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_select_contour.m 1417 2010-07-15 15:33:01Z crimic $ diff --git a/external/fieldtrip/plotting/ft_select_point.m b/external/fieldtrip/plotting/ft_select_point.m new file mode 100644 index 0000000..730298f --- /dev/null +++ b/external/fieldtrip/plotting/ft_select_point.m @@ -0,0 +1,105 @@ +function [selected] = select_point(pos, varargin) + +% SELECT_POINT helper function for selecting a one or multiple points +% in the current figure using the mouse. +% +% Use as +% [selected] = select_point(pos, ...) +% +% It returns a list of the [x y] coordinates of the selected points. +% +% Optional input arguments should come in key-value pairs and can include +% 'multiple' true/false, make multiple selections, pressing "q" on the keyboard finalizes the selection (default = false) +% 'nearest' true/false (default = true) +% +% Example use +% pos = randn(10,2); +% figure +% plot(pos(:,1), pos(:,2), '.') +% select_point(pos) + +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_select_point.m 1413 2010-07-15 14:40:26Z crimic $ + + +% get optional input arguments +nearest = keyval('nearest', varargin); if isempty(nearest), nearest = true; end +multiple = keyval('multiple', varargin); if isempty(multiple), multiple = false; end + +% ensure that it is boolean +nearest = istrue(nearest); +multiple = istrue(multiple); + +if multiple + fprintf('select multiple points by clicking in the figure, press "q" if you are done\n'); +end + +x = []; +y = []; +done = false; + +selected = zeros(0,3); + +% ensure that "q" is not the current character, which happens if you reuse the same figure +set(gcf, 'CurrentCharacter', 'x') + +while ~done + k = waitforbuttonpress; + point = get(gca,'CurrentPoint'); % button down detected + key = get(gcf,'CurrentCharacter'); % which key was pressed (if any)? + if strcmp(key, 'q') + % we are done with the clicking + done = true; + else + % add the current point + x(end+1) = point(1,1); + y(end+1) = point(1,2); + end + + if ~multiple + done = true; + end +end + +if nearest && ~isempty(pos) + % determine the points that are the nearest to the displayed points + selected = []; + + % compute the distance between the points to get an estimate of the tolerance + dp = dist(pos'); + dp = triu(dp, 1); + dp = dp(:); + dp = dp(dp>0); + % allow for some tolerance in the clicking + dp = median(dp); + tolerance = 0.3*dp; + + for i=1:length(x) + % compute the distance between the clicked position and all points + dx = pos(:,1) - x(i); + dy = pos(:,2) - y(i); + dd = sqrt(dx.^2 + dy.^2); + [d, i] = min(dd); + if d. +% +% $Id: ft_select_point3d.m 1413 2010-07-15 14:40:26Z crimic $ + +% get optional input arguments +nearest = keyval('nearest', varargin); if isempty(nearest), nearest = true; end +multiple = keyval('multiple', varargin); if isempty(multiple), multiple = false; end + +% ensure that it is boolean +nearest = istrue(nearest); +multiple = istrue(multiple); + +% get the object handles +h = get(gca, 'children'); + +% select the correct objects +iscorrect = false(size(h)); +for i=1:length(h) + try + pnt = get(h(i),'vertices'); + tri = get(h(i),'faces'); + if ~isempty(bnd) && isequal(bnd.pnt, pnt) && isequal(bnd.tri, tri) + % it is the same object that the user has plotted before + iscorrect(i) = true; + elseif isempty(bnd) + % assume that it is the same object that the user has plotted before + iscorrect(i) = true; + end + end +end +h = h(iscorrect); + +if isempty(h) && ~isempty(bnd) + figure + plot_mesh(bnd); + camlight + selected = select_point3d(bnd, varargin{:}); + return +end + +if length(h)>1 + warning('using the first patch object in the figure'); + h = h(1); +end + +selected = zeros(0,3); + +done = false; +while ~done + k = waitforbuttonpress; + [p v vi facev facei] = select3d(h); + key = get(gcf,'CurrentCharacter'); % which key was pressed (if any)? + + if strcmp(key, 'q') + % finished selecting points + done = true; + else + % a new point was selected + if nearest + selected(end+1,:) = v; + else + selected(end+1,:) = p; + end % if nearest + fprintf('selected point at [%f %f %f]\n', selected(end,1), selected(end,2), selected(end,3)); + end + + if ~multiple + done = true; + end +end + diff --git a/external/fieldtrip/plotting/ft_select_range.m b/external/fieldtrip/plotting/ft_select_range.m new file mode 100644 index 0000000..a84ee47 --- /dev/null +++ b/external/fieldtrip/plotting/ft_select_range.m @@ -0,0 +1,242 @@ +function ft_select_range(handle, eventdata, varargin) + +% SELECT_RANGE is a helper function that can be used as callback function +% in a figure. It allows the user to select a horizontal or a vertical +% range, or one or multiple boxes. +% +% Example +% x = randn(10,1); +% y = randn(10,1); +% figure; plot(x, y, '.'); +% +% set(gcf, 'WindowButtonDownFcn', {@ft_select_range, 'multiple', true, 'callback', @disp, 'event', 'WindowButtonDownFcn'}); +% set(gcf, 'WindowButtonUpFcn', {@ft_select_range, 'multiple', true, 'callback', @disp, 'event', 'WindowButtonUpFcn'}); +% set(gcf, 'WindowButtonMotionFcn', {@ft_select_range, 'multiple', true, 'callback', @disp, 'event', 'WindowButtonMotionFcn'}); +% +% set(gcf, 'WindowButtonDownFcn', {@ft_select_range, 'multiple', false, 'xrange', false, 'yrange', false, 'callback', @disp, 'event', 'WindowButtonDownFcn'}); +% set(gcf, 'WindowButtonUpFcn', {@ft_select_range, 'multiple', false, 'xrange', false, 'yrange', false, 'callback', @disp, 'event', 'WindowButtonUpFcn'}); +% set(gcf, 'WindowButtonMotionFcn', {@ft_select_range, 'multiple', false, 'xrange', false, 'yrange', false, 'callback', @disp, 'event', 'WindowButtonMotionFcn'}); + +% Copyright (C) 2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_select_range.m 1427 2010-07-19 11:44:01Z vlalit $ + +% get the optional arguments +event = keyval('event', varargin); +callback = keyval('callback', varargin); +multiple = keyval('multiple', varargin); if isempty(multiple), multiple = false; end +xrange = keyval('xrange', varargin); if isempty(xrange), xrange = true; end +yrange = keyval('yrange', varargin); if isempty(yrange), yrange = true; end +clear = keyval('clear', varargin); if isempty(clear), clear = false; end + +% convert 'yes/no' string to boolean value +multiple = istrue(multiple); +xrange = istrue(xrange); +yrange = istrue(yrange); + +p = handle; +while ~isequal(p, 0) + handle = p; + p = get(handle, 'parent'); +end + +if ishandle(handle) + userData = getappdata(handle, 'select_range_m'); +else + userData = []; +end + +if isempty(userData) + userData.range = []; % this is a Nx4 matrix with the selection range + userData.box = []; % this is a Nx1 vector with the line handle +end + +p = get(gca, 'CurrentPoint'); +p = p(1,1:2); + +abc = axis; +xLim = abc(1:2); +yLim = abc(3:4); + +% limit cursor coordinates +if p(1)xLim(2), p(1)=xLim(2); end; +if p(2)yLim(2), p(2)=yLim(2); end; + +% determine whether the user is currently making a selection +selecting = numel(userData.range)>0 && any(isnan(userData.range(end,:))); +pointonly = ~xrange && ~yrange; + +if pointonly && multiple + warning('multiple selections are not possible for a point'); + multiple = false; +end + +switch event + case 'WindowButtonDownFcn' + if inSelection(p, userData.range) + % the user has clicked in one of the existing selections + evalCallback(callback, userData.range); + if clear + delete(userData.box(ishandle(userData.box))); + userData.range = []; + userData.box = []; + set(handle, 'Pointer', 'crosshair'); + end + + else + if ~multiple + % start with a new selection + delete(userData.box(ishandle(userData.box))); + userData.range = []; + userData.box = []; + end + + % add a new selection range + userData.range(end+1,1:4) = nan; + userData.range(end,1) = p(1); + userData.range(end,3) = p(2); + + % add a new selection box + xData = [nan nan nan nan nan]; + yData = [nan nan nan nan nan]; + userData.box(end+1) = line(xData, yData); + end + + case 'WindowButtonUpFcn' + if selecting + % select the other corner of the box + userData.range(end,2) = p(1); + userData.range(end,4) = p(2); + end + + if multiple && ~isempty(userData.range) && ~diff(userData.range(end,1:2)) && ~diff(userData.range(end,3:4)) + % start with a new selection + delete(userData.box(ishandle(userData.box))); + userData.range = []; + userData.box = []; + end + + if ~isempty(userData.range) + % ensure that the selection is sane + if diff(userData.range(end,1:2))<0 + userData.range(end,1:2) = userData.range(end,[2 1]); + end + if diff(userData.range(end,3:4))<0 + userData.range(end,3:4) = userData.range(end,[4 3]); + end + if pointonly + % only select a single point + userData.range(end,2) = userData.range(end,1); + userData.range(end,4) = userData.range(end,3); + elseif ~xrange + % only select along the y-axis + userData.range(end,1:2) = [-inf inf]; + elseif ~yrange + % only select along the x-axis + userData.range(end,3:4) = [-inf inf]; + end + end + + if pointonly && ~multiple + evalCallback(callback, userData.range); + if clear + delete(userData.box(ishandle(userData.box))); + userData.range = []; + userData.box = []; + set(handle, 'Pointer', 'crosshair'); + end + end + + case 'WindowButtonMotionFcn' + if selecting && ~pointonly + % update the selection box + if xrange + x1 = userData.range(end,1); + x2 = p(1); + else + x1 = xLim(1); + x2 = xLim(2); + end + if yrange + y1 = userData.range(end,3); + y2 = p(2); + else + y1 = yLim(1); + y2 = yLim(2); + end + + xData = [x1 x2 x2 x1 x1]; + yData = [y1 y1 y2 y2 y1]; + set(userData.box(end), 'xData', xData); + set(userData.box(end), 'yData', yData); + set(userData.box(end), 'Color', [0 0 0]); + set(userData.box(end), 'EraseMode', 'xor'); + set(userData.box(end), 'LineStyle', '--'); + set(userData.box(end), 'LineWidth', 1.5); + set(userData.box(end), 'Visible', 'on'); + + else + % update the cursor + if inSelection(p, userData.range) + set(handle, 'Pointer', 'hand'); + else + set(handle, 'Pointer', 'crosshair'); + end + end + + otherwise + error('unexpected event "%s"', event); + +end % switch event + +% put the modified selections back into the figure +if ishandle(handle) + setappdata(handle, 'select_range_m', userData); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function retval = inSelection(p, range) +if isempty(range) + retval = false; +else + retval = (p(1)>=range(:,1) & p(1)<=range(:,2) & p(2)>=range(:,3) & p(2)<=range(:,4)); + retval = any(retval); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function evalCallback(callback, val) +if ~isempty(callback) + if isa(callback, 'cell') + % the callback specifies a function and additional arguments + funhandle = callback{1}; + funargs = callback(2:end); + feval(funhandle, val, funargs{:}); + else + % the callback only specifies a function + funhandle = callback; + feval(funhandle, val); + end +end + diff --git a/external/fieldtrip/plotting/ft_uilayout.m b/external/fieldtrip/plotting/ft_uilayout.m new file mode 100644 index 0000000..0b1a736 --- /dev/null +++ b/external/fieldtrip/plotting/ft_uilayout.m @@ -0,0 +1,170 @@ +function uilayout(h, varargin) + +% UILAYOUT is a helper function to facilitate the layout of multiple +% usercontrol elements + +% Copyright (C) 2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_uilayout.m 1415 2010-07-15 15:26:27Z crimic $ + +% these are used to make a selection of uicontrol elements +tag = keyval('tag', varargin{:}); +style = keyval('style', varargin{:}); + +% determine all children +if ~isempty(tag) && ~isempty(style) + c = findall(h, 'tag', tag, 'style', style); +elseif ~isempty(tag) + c = findall(h, 'tag', tag); +elseif ~isempty(style) + c = findall(h, 'style', style); +else + c = findall(h); +end +c = flipud(c); +% fprintf('selected %d elements\n', numel(c)); + +% these are the normal features of an uicontrol +BackgroundColor = keyval('BackgroundColor', varargin{:}); +CallBack = keyval('CallBack', varargin{:}); +Clipping = keyval('Clipping', varargin{:}); +Enable = keyval('Enable', varargin{:}); +FontAngle = keyval('FontAngle', varargin{:}); +FontName = keyval('FontName', varargin{:}); +FontSize = keyval('FontSize', varargin{:}); +FontUnits = keyval('FontUnits', varargin{:}); +FontWeight = keyval('FontWeight', varargin{:}); +ForegroundColor = keyval('ForegroundColor', varargin{:}); +HorizontalAlignment = keyval('HorizontalAlignment', varargin{:}); +Max = keyval('Max', varargin{:}); +Min = keyval('Min', varargin{:}); +Position = keyval('Position', varargin{:}); +Selected = keyval('Selected', varargin{:}); +String = keyval('String', varargin{:}); +Units = keyval('Units', varargin{:}); +Value = keyval('Value', varargin{:}); +Visible = keyval('Visible', varargin{:}); +Tag = keyval('retag', varargin{:}); % this is to change the tag on the selected items +Style = keyval('restyle', varargin{:}); % this is to change the style on the selected items + +feature = { + 'BackgroundColor' + 'CallBack' + 'Clipping' + 'Enable' + 'FontAngle' + 'FontName' + 'FontSize' + 'FontUnits' + 'FontWeight' + 'ForegroundColor' + 'HorizontalAlignment' + 'Max' + 'Min' + 'Position' + 'Selected' + 'String' + 'Units' + 'Value' + 'Visible' + 'Tag' + 'Style' + }; + +for i=1:length(feature) + val = eval(feature{i}); + if ~isempty(val) + % fprintf('setting %s\n', feature{i}); + for j=1:length(c) + set(c(j), feature{i}, val) + end + end +end + +% these are special features to help with the positioning of the elements +hpos = keyval('hpos', varargin{:}); +vpos = keyval('vpos', varargin{:}); +width = keyval('width', varargin{:}); +height = keyval('height', varargin{:}); + +if isempty(hpos) && isempty(vpos) && isempty(width) && isempty(height) + % re-positioning of the elements is not needed + return +end + +pos = zeros(length(c), 4); +for i=1:length(c) + pos(i,:) = get(c(i), 'position'); +end + +if ~isempty(width) + pos(:,3) = width; +end +width = pos(:,3); + +if ~isempty(height) + pos(:,4) = height; +end +height = pos(:,4); + +if ~isempty(hpos) + if isequal(hpos, 'auto') + scale = (1 - 0.01 - 0.01*length(c)) / sum(width); + if scale>0 && scale<1 + % fprintf('adjusting width with %f\n', scale); + width = width*scale; + pos(:,3) = width; + end + hpos = cumsum([0.01; width+0.01]); + hpos = hpos(1:end-1); + elseif isequal(hpos, 'align') + hpos = pos(1,2); % the position of the first element + elseif isequal(hpos, 'distribute') + minpos = min(pos(:,1)); + maxpos = max(pos(:,1)); + hpos = linspace(minpos, maxpos, length(c)); + end + pos(:,1) = hpos; + pos(:,3) = width; +end % hpos + +if ~isempty(vpos) + if isequal(vpos, 'auto') + scale = (1 - 0.01 - 0.01*length(c)) / sum(height); + if scale>0 && scale<1 + % fprintf('adjusting height with %f\n', scale); + height = height*scale; + pos(:,4) = height; + end + vpos = cumsum([0.01; width]); + vpos = vpos(1:end-1); + elseif isequal(vpos, 'align') + vpos = pos(1,2); % the position of the first element + elseif isequal(vpos, 'distribute') + minpos = min(pos(:,2)); + maxpos = max(pos(:,2)); + vpos = linspace(minpos, maxpos, length(c)); + end + pos(:,2) = vpos; +end % vpos + +% assign the new/automatic position to each of the elements +for i=1:length(c) + set(c(i), 'position', pos(i,:)); +end diff --git a/external/fieldtrip/plotting/private/black.m b/external/fieldtrip/plotting/private/black.m new file mode 100644 index 0000000..2754548 --- /dev/null +++ b/external/fieldtrip/plotting/private/black.m @@ -0,0 +1,17 @@ +function rgb = rgbcolor + +% returns a predefined color as [red green blue] values +% +% skin = [255 213 119]/255; +% skull = [140 85 85]/255; +% brain = [202 100 100]/255; +% cortex = [255 213 119]/255; +% black = [0 0 0 ]/255; +% white = [255 255 255]/255; +% red = [255 0 0 ]/255; +% green = [0 192 0 ]/255; +% blue = [0 0 255]/255; +% yellow = [255 255 0 ]/255; + +rgb = [0 0 0 ]/255; + diff --git a/external/fieldtrip/plotting/private/blue.m b/external/fieldtrip/plotting/private/blue.m new file mode 100644 index 0000000..1695e12 --- /dev/null +++ b/external/fieldtrip/plotting/private/blue.m @@ -0,0 +1,17 @@ +function rgb = rgbcolor + +% returns a predefined color as [red green blue] values +% +% skin = [255 213 119]/255; +% skull = [140 85 85]/255; +% brain = [202 100 100]/255; +% cortex = [255 213 119]/255; +% black = [0 0 0 ]/255; +% white = [255 255 255]/255; +% red = [255 0 0 ]/255; +% green = [0 192 0 ]/255; +% blue = [0 0 255]/255; +% yellow = [255 255 0 ]/255; + +rgb = [0 0 255]/255; + diff --git a/external/fieldtrip/plotting/private/brain.m b/external/fieldtrip/plotting/private/brain.m new file mode 100644 index 0000000..de13986 --- /dev/null +++ b/external/fieldtrip/plotting/private/brain.m @@ -0,0 +1,17 @@ +function rgb = rgbcolor + +% returns a predefined color as [red green blue] values +% +% skin = [255 213 119]/255; +% skull = [140 85 85]/255; +% brain = [202 100 100]/255; +% cortex = [255 213 119]/255; +% black = [0 0 0 ]/255; +% white = [255 255 255]/255; +% red = [255 0 0 ]/255; +% green = [0 192 0 ]/255; +% blue = [0 0 255]/255; +% yellow = [255 255 0 ]/255; + +rgb = [202 100 100]/255; + diff --git a/external/fieldtrip/plotting/private/channelposition.m b/external/fieldtrip/plotting/private/channelposition.m new file mode 100644 index 0000000..5a950ea --- /dev/null +++ b/external/fieldtrip/plotting/private/channelposition.m @@ -0,0 +1,206 @@ +function [pnt, ori, lab] = channelposition(sens, varargin) + +% CHANNELPOSITION +% +% Use either as +% [pos] = channelposition(sens, ...) +% [pos, lab] = channelposition(sens, ...) +% [pos, ori, lab] = channelposition(sens, ...) + +% Copyright (C) 2009, Robert Oostenveld & Vladimir Litvak +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: channelposition.m 1261 2010-06-22 15:09:23Z roboos $ + +if isfield(sens, 'balance') && isfield(sens.balance, 'current') && ~strcmp(sens.balance.current, 'none') + fnames = setdiff(fieldnames(sens.balance), 'current'); + indx = find(ismember(fnames, sens.balance.current)); + + if length(indx)==1, + % undo the synthetic gradient balancing + fprintf('undoing the %s balancing\n', sens.balance.current); + sens = ft_apply_montage(sens, getfield(sens.balance, sens.balance.current), 'inverse', 'yes'); + sens.balance.current = 'none'; + else + warning('cannot undo %s balancing\n', sens.balance.current); + end +end + +switch ft_senstype(sens) + case {'ctf151', 'ctf275' 'bti148', 'bti248', 'itab153', 'yokogawa160'} + % remove the non-MEG channels altogether + sel = ft_chantype(sens, 'meg'); + sens.label = sens.label(sel); + sens.tra = sens.tra(sel,:); + + % subsequently remove the unused coils + used = any(abs(sens.tra)<0.5, 1); % allow a little bit of rounding-off error + sens.pnt = sens.pnt(used,:); + sens.ori = sens.ori(used,:); + sens.tra = sens.tra(:,used); + + % compute distances from the center + dist = sqrt(sum((sens.pnt - repmat(mean(sens.pnt), size(sens.pnt, 1), 1)).^2, 2)); + + % put the corresponding distances instead of non-zero tra entries + dist = (abs(sens.tra)>0.5).*repmat(dist', size(sens.tra, 1), 1); + + % put nans instead of the zero entries + dist(~dist) = inf; + + % use the matrix to find coils with minimal distance to the center, i.e. the bottom coil + [junk, ind] = min(dist, [], 2); + + lab = sens.label; + pnt = sens.pnt(ind, :); + ori = sens.ori(ind, :); + + case {'ctf151_planar', 'ctf275_planar', 'bti148_planar', 'bti248_planar', 'itab153_planar', 'yokogawa160_planar'} + % create a list with planar channel names + chan = {}; + for i=1:length(sens.label) + if ~isempty(findstr(sens.label{i}, '_dH')) || ~isempty(findstr(sens.label{i}, '_dV')) + chan{i} = sens.label{i}(1:(end-3)); + end + end + chan = unique(chan); + % find the matching channel-duplets + ind = []; + lab = {}; + for i=1:length(chan) + ch1 = [chan{i} '_dH']; + ch2 = [chan{i} '_dV']; + sel = match_str(sens.label, {ch1, ch2}); + if length(sel)==2 + ind = [ind; i]; + lab(i,:) = {ch1, ch2}; + meanpnt1 = mean(sens.pnt(abs(sens.tra(sel(1),:))>0.5, :), 1); + meanpnt2 = mean(sens.pnt(abs(sens.tra(sel(2),:))>0.5, :), 1); + pnt(i,:) = mean([meanpnt1; meanpnt2], 1); + end + end + lab = lab(ind,:); + pnt = pnt(ind,:); + + case 'neuromag122' + % find the matching channel-duplets + ind = []; + lab = {}; + for i=1:2:140 + % first try MEG channel labels with a space + ch1 = sprintf('MEG %03d', i); + ch2 = sprintf('MEG %03d', i+1); + sel = match_str(sens.label, {ch1, ch2}); + % then try MEG channel labels without a space + if (length(sel)~=2) + ch1 = sprintf('MEG%03d', i); + ch2 = sprintf('MEG%03d', i+1); + sel = match_str(sens.label, {ch1, ch2}); + end + % then try to determine the channel locations + if (length(sel)==2) + ind = [ind; i]; + lab(i,:) = {ch1, ch2}; + meanpnt1 = mean(sens.pnt(abs(sens.tra(sel(1),:))>0.5,:), 1); + meanpnt2 = mean(sens.pnt(abs(sens.tra(sel(2),:))>0.5,:), 1); + pnt(i,:) = mean([meanpnt1; meanpnt2], 1); + end + end + lab = lab(ind,:); + pnt = pnt(ind,:); + + case 'neuromag306' + % find the matching channel-triplets + ind = []; + lab = {}; + for i=1:300 + % first try MEG channel labels with a space + ch1 = sprintf('MEG %03d1', i); + ch2 = sprintf('MEG %03d2', i); + ch3 = sprintf('MEG %03d3', i); + sel = match_str(sens.label, {ch1, ch2, ch3}); + % the try MEG channels without a space + if (length(sel)~=3) + ch1 = sprintf('MEG%03d1', i); + ch2 = sprintf('MEG%03d2', i); + ch3 = sprintf('MEG%03d3', i); + sel = match_str(sens.label, {ch1, ch2, ch3}); + end + % then try to determine the channel locations + if (length(sel)==3) + ind = [ind; i]; + lab(i,:) = {ch1, ch2, ch3}; + meanpnt1 = mean(sens.pnt(abs(sens.tra(sel(1),:))>0.5,:), 1); + meanpnt2 = mean(sens.pnt(abs(sens.tra(sel(2),:))>0.5,:), 1); + meanpnt3 = mean(sens.pnt(abs(sens.tra(sel(3),:))>0.5,:), 1); + pnt(i,:) = mean([meanpnt1; meanpnt2; meanpnt3], 1); + end + end + lab = lab(ind,:); + pnt = pnt(ind,:); + + + otherwise + % compute the position for each electrode + + if isfield(sens, 'tra') + % each channel depends on multiple sensors (electrodes or coils) + % compute a weighted position for the channel + [nchan, ncoil] = size(sens.tra); + pnt = zeros(nchan,3); + ori = zeros(nchan,3); % FIXME not sure whether this will work + for i=1:nchan + weight = abs(sens.tra(i,:)); + weight = weight ./ norm(weight); + pnt(i,:) = weight * sens.pnt; + ori(i,:) = weight * sens.ori; + end + lab = sens.label; + + else + % there is one sensor per channel, which means that the channel position + % is identical to the sensor position + pnt = sens.pnt; + lab = sens.label; + end + +end % switch senstype + +n = size(lab,2); +% this is to fix the planar layouts, which cannot be plotted anyway +if n>1 && size(lab, 1)>1 %this is to prevent confusion when lab happens to be a row array + pnt = repmat(pnt, n, 1); +end + +% ensure that it is a row vector +lab = lab(:); + +% the function can be called with a different number of output arguments +if nargout==1 + pnt = pnt; + ori = []; + lab = []; +elseif nargout==2 + pnt = pnt; + ori = lab; % second output argument + lab = []; % third output argument +elseif nargout==3 + pnt = pnt; + ori = ori; % second output argument + lab = lab; % third output argument +end diff --git a/external/fieldtrip/plotting/private/cortex.m b/external/fieldtrip/plotting/private/cortex.m new file mode 100644 index 0000000..d0e56e6 --- /dev/null +++ b/external/fieldtrip/plotting/private/cortex.m @@ -0,0 +1,17 @@ +function rgb = rgbcolor + +% returns a predefined color as [red green blue] values +% +% skin = [255 213 119]/255; +% skull = [140 85 85]/255; +% brain = [202 100 100]/255; +% cortex = [255 213 119]/255; +% black = [0 0 0 ]/255; +% white = [255 255 255]/255; +% red = [255 0 0 ]/255; +% green = [0 192 0 ]/255; +% blue = [0 0 255]/255; +% yellow = [255 255 0 ]/255; + +rgb = [255 213 119]/255; + diff --git a/external/fieldtrip/plotting/private/cylinder.m b/external/fieldtrip/plotting/private/cylinder.m new file mode 100644 index 0000000..6f356d1 --- /dev/null +++ b/external/fieldtrip/plotting/private/cylinder.m @@ -0,0 +1,69 @@ +function [pnt, dhk] = cylinder(Naz, Nel) + +% CYLINDER creates a triangulated cylinder +% +% Use as +% [pnt, dhk] = cylinder(Naz, Nel) + +% Copyright (C) 2002, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: cylinder.m 950 2010-04-21 18:12:58Z roboos $ + +az = (2*pi*(0:(Naz-1))/Naz)'; +el = (linspace(-1,1,Nel))'; + +pnt = zeros(Naz*Nel+2, 3); +dhk = zeros(2*Naz*(Nel-1)+2*Naz,3); + +for i=1:Nel + pnt(((i-1)*Naz+1):(i*Naz), :) = [cos(az) sin(az) el(i)*ones(Naz,1)]; +end + +pnt(Naz*Nel+1,:) = [0 0 -1]; +pnt(Naz*Nel+2,:) = [0 0 1]; + +ndhk = 1; +for i=1:(Nel-1) + for j=1:(Naz-1) + dhk(ndhk, :) = [(i-1)*Naz+j (i-1)*Naz+j+1 i*Naz+j+1]; + ndhk = ndhk+1; + dhk(ndhk, :) = [(i-1)*Naz+j i*Naz+j+1 i*Naz+j]; + ndhk = ndhk+1; + end + dhk(ndhk, :) = [i*Naz (i-1)*Naz+1 i*Naz+1]; + ndhk = ndhk+1; + dhk(ndhk, :) = [i*Naz i*Naz+1 (i+1)*Naz]; + ndhk = ndhk+1; +end + +% connect the bottom point to the cylinder edge +for i=1:(Naz-1) + dhk(ndhk, :) = [Naz*Nel+1 i+1 i]; + ndhk = ndhk+1; +end +dhk(ndhk, :) = [Naz*Nel+1 1 Naz]; +ndhk = ndhk+1; + +% connect the top point to the cylinder edge +for i=1:(Naz-1) + dhk(ndhk, :) = [Naz*Nel+2 Naz*(Nel-1)+i Naz*(Nel-1)+i+1]; + ndhk = ndhk+1; +end +dhk(ndhk, :) = [Naz*Nel+2 Naz*Nel Naz*(Nel-1)+1]; + diff --git a/external/fieldtrip/plotting/private/green.m b/external/fieldtrip/plotting/private/green.m new file mode 100644 index 0000000..96c2154 --- /dev/null +++ b/external/fieldtrip/plotting/private/green.m @@ -0,0 +1,17 @@ +function rgb = rgbcolor + +% returns a predefined color as [red green blue] values +% +% skin = [255 213 119]/255; +% skull = [140 85 85]/255; +% brain = [202 100 100]/255; +% cortex = [255 213 119]/255; +% black = [0 0 0 ]/255; +% white = [255 255 255]/255; +% red = [255 0 0 ]/255; +% green = [0 192 0 ]/255; +% blue = [0 0 255]/255; +% yellow = [255 255 0 ]/255; + +rgb = [0 192 0 ]/255; + diff --git a/external/fieldtrip/plotting/private/icosahedron.m b/external/fieldtrip/plotting/private/icosahedron.m new file mode 100644 index 0000000..a01ccae --- /dev/null +++ b/external/fieldtrip/plotting/private/icosahedron.m @@ -0,0 +1,69 @@ +function [pnt, dhk] = icosahedron(); + +% ICOSAHEDRON creates an icosahedron +% +% [pnt, dhk] = icosahedron +% creates an icosahedron with 12 vertices and 20 triangles +% +% See also OCTAHEDRON, ICOSAHEDRON42, ICOSAHEDRON162, ICOSAHEDRON642, ICOSAHEDRON2562 + +% Copyright (C) 2002, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: icosahedron.m 952 2010-04-21 18:29:51Z roboos $ + +dhk = [ + 1 2 3 + 1 3 4 + 1 4 5 + 1 5 6 + 1 6 2 + 2 8 3 + 3 9 4 + 4 10 5 + 5 11 6 + 6 7 2 + 7 8 2 + 8 9 3 + 9 10 4 + 10 11 5 + 11 7 6 + 12 8 7 + 12 9 8 + 12 10 9 + 12 11 10 + 12 7 11 +]; + +pnt = zeros(12, 3); + +rho=0.4*sqrt(5); +phi=2*pi*(0:4)/5; + +pnt( 1, :) = [0 0 1]; % top point + +pnt(2:6, 1) = rho*cos(phi)'; +pnt(2:6, 2) = rho*sin(phi)'; +pnt(2:6, 3) = rho/2; + +pnt(7:11, 1) = rho*cos(phi - pi/5)'; +pnt(7:11, 2) = rho*sin(phi - pi/5)'; +pnt(7:11, 3) = -rho/2; + +pnt(12, :) = [0 0 -1]; % bottom point + diff --git a/external/fieldtrip/plotting/private/icosahedron162.m b/external/fieldtrip/plotting/private/icosahedron162.m new file mode 100644 index 0000000..f589e87 --- /dev/null +++ b/external/fieldtrip/plotting/private/icosahedron162.m @@ -0,0 +1,29 @@ +function [pnt, dhk] = icosahedron(); + +% ICOSAHEDRON162 creates a 2-fold refined icosahedron + +% Copyright (C) 2003, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: icosahedron162.m 952 2010-04-21 18:29:51Z roboos $ + +[pnt, dhk] = icosahedron; +[pnt, dhk] = refine(pnt, dhk); +[pnt, dhk] = refine(pnt, dhk); + +pnt = pnt ./ repmat(sqrt(sum(pnt.^2,2)), 1,3); diff --git a/external/fieldtrip/plotting/private/icosahedron42.m b/external/fieldtrip/plotting/private/icosahedron42.m new file mode 100644 index 0000000..abc6c51 --- /dev/null +++ b/external/fieldtrip/plotting/private/icosahedron42.m @@ -0,0 +1,28 @@ +function [pnt, dhk] = icosahedron(); + +% ICOSAHEDRON42 creates a 1-fold refined icosahedron + +% Copyright (C) 2003, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: icosahedron42.m 952 2010-04-21 18:29:51Z roboos $ + +[pnt, dhk] = icosahedron; +[pnt, dhk] = refine(pnt, dhk); + +pnt = pnt ./ repmat(sqrt(sum(pnt.^2,2)), 1,3); diff --git a/external/fieldtrip/plotting/private/icosahedron642.m b/external/fieldtrip/plotting/private/icosahedron642.m new file mode 100644 index 0000000..360de75 --- /dev/null +++ b/external/fieldtrip/plotting/private/icosahedron642.m @@ -0,0 +1,30 @@ +function [pnt, dhk] = icosahedron(); + +% ICOSAHEDRON642 creates a 3-fold refined icosahedron + +% Copyright (C) 2003, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: icosahedron642.m 952 2010-04-21 18:29:51Z roboos $ + +[pnt, dhk] = icosahedron; +[pnt, dhk] = refine(pnt, dhk); +[pnt, dhk] = refine(pnt, dhk); +[pnt, dhk] = refine(pnt, dhk); + +pnt = pnt ./ repmat(sqrt(sum(pnt.^2,2)), 1,3); diff --git a/external/fieldtrip/plotting/private/inside_contour.m b/external/fieldtrip/plotting/private/inside_contour.m new file mode 100644 index 0000000..5056d7a --- /dev/null +++ b/external/fieldtrip/plotting/private/inside_contour.m @@ -0,0 +1,48 @@ +function bool = inside_contour(pos, contour); + +npos = size(pos,1); +ncnt = size(contour,1); +x = pos(:,1); +y = pos(:,2); + +minx = min(x); +miny = min(y); +maxx = max(x); +maxy = max(y); + +bool = true(npos,1); +bool(xmaxx) = false; +bool(y>maxy) = false; + +% the summed angle over the contour is zero if the point is outside, and 2*pi if the point is inside the contour +% leave some room for inaccurate f +critval = 0.1; + +% the remaining points have to be investigated with more attention +sel = find(bool); +for i=1:length(sel) + contourx = contour(:,1) - pos(sel(i),1); + contoury = contour(:,2) - pos(sel(i),2); + angle = atan2(contoury, contourx); + % angle = unwrap(angle); + angle = my_unwrap(angle); + total = sum(diff(angle)); + bool(sel(i)) = (abs(total)>critval); +end + +function x = my_unwrap(x) +% this is a faster implementation of the MATLAB unwrap function +% with hopefully the same functionality +d = diff(x); +indx = find(abs(d)>pi); +for i=indx(:)' + if d(i)>0 + x((i+1):end) = x((i+1):end) - 2*pi; + else + x((i+1):end) = x((i+1):end) + 2*pi; + end +end + + diff --git a/external/fieldtrip/plotting/private/projecttri.m b/external/fieldtrip/plotting/private/projecttri.m new file mode 100644 index 0000000..4529776 --- /dev/null +++ b/external/fieldtrip/plotting/private/projecttri.m @@ -0,0 +1,55 @@ +function [tri] = projecttri(pnt, method) + +% PROJECTTRI makes a closed triangulation of a list of vertices by +% projecting them onto a unit sphere and subsequently by constructing +% a convex hull triangulation. +% +% Use as +% [tri] = projecttri(pnt, method) +% The optional method argument can be 'convhull' (default) or 'delaunay'. + +% Copyright (C) 2006, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: projecttri.m 952 2010-04-21 18:29:51Z roboos $ + +if nargin<2 + method = 'convhull'; +end + +switch method + case 'convhull' + ori = (min(pnt) + max(pnt))./2; + pnt(:,1) = pnt(:,1) - ori(1); + pnt(:,2) = pnt(:,2) - ori(2); + pnt(:,3) = pnt(:,3) - ori(3); + nrm = sqrt(sum(pnt.^2, 2)); + pnt(:,1) = pnt(:,1)./nrm; + pnt(:,2) = pnt(:,2)./nrm; + pnt(:,3) = pnt(:,3)./nrm; + tri = convhulln(pnt); + case 'delaunay' + % make a 2d triangulation of the projected points using delaunay + prj = elproj(pnt); + tri = delaunay(prj(:,1), prj(:,2)); + otherwise + error('unsupported method'); +end + + + diff --git a/external/fieldtrip/plotting/private/red.m b/external/fieldtrip/plotting/private/red.m new file mode 100644 index 0000000..4ce795f --- /dev/null +++ b/external/fieldtrip/plotting/private/red.m @@ -0,0 +1,17 @@ +function rgb = rgbcolor + +% returns a predefined color as [red green blue] values +% +% skin = [255 213 119]/255; +% skull = [140 85 85]/255; +% brain = [202 100 100]/255; +% cortex = [255 213 119]/255; +% black = [0 0 0 ]/255; +% white = [255 255 255]/255; +% red = [255 0 0 ]/255; +% green = [0 192 0 ]/255; +% blue = [0 0 255]/255; +% yellow = [255 255 0 ]/255; + +rgb = [255 0 0 ]/255; + diff --git a/external/fieldtrip/plotting/private/refine.m b/external/fieldtrip/plotting/private/refine.m new file mode 100644 index 0000000..e6e7967 --- /dev/null +++ b/external/fieldtrip/plotting/private/refine.m @@ -0,0 +1,111 @@ +function [pntr, dhkr] = refine(pnt, dhk, method, varargin); + +% REFINE a 3D surface that is described by a triangulation +% +% Use as +% [pnt, tri] = refine(pnt, tri) +% [pnt, tri] = refine(pnt, tri, 'updown', numtri) +% +% The default method is to refine the mesh globally by inserting a vertex at +% each edge according to the algorithm described in Banks, 1983. +% +% The alternative 'updown' method refines the mesh a couple of times +% using Banks' algorithm, followed by a downsampling using the REDUCEPATCH +% function. + +% The Banks method is a memory efficient implementation which remembers +% the previously inserted vertices. The refinement algorithm executes in +% linear time with the number of triangles. + +% Copyright (C) 2002-2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: refine.m 952 2010-04-21 18:29:51Z roboos $ + +if nargin<3 + method = 'banks'; +end + +switch lower(method) +case 'banks' + npnt = size(pnt,1); + ndhk = size(dhk,1); + insert = spalloc(3*npnt,3*npnt,3*ndhk); + + dhkr = zeros(4*ndhk,3); % allocate memory for the new triangles + pntr = zeros(npnt+3*ndhk,3); % allocate memory for the maximum number of new vertices + pntr(1:npnt,:) = pnt; % insert the original vertices + current = npnt; + + for i=1:ndhk + + if ~insert(dhk(i,1),dhk(i,2)) + current = current + 1; + pntr(current,:) = (pnt(dhk(i,1),:) + pnt(dhk(i,2),:))/2; + insert(dhk(i,1),dhk(i,2)) = current; + insert(dhk(i,2),dhk(i,1)) = current; + v12 = current; + else + v12 = insert(dhk(i,1),dhk(i,2)); + end + + if ~insert(dhk(i,2),dhk(i,3)) + current = current + 1; + pntr(current,:) = (pnt(dhk(i,2),:) + pnt(dhk(i,3),:))/2; + insert(dhk(i,2),dhk(i,3)) = current; + insert(dhk(i,3),dhk(i,2)) = current; + v23 = current; + else + v23 = insert(dhk(i,2),dhk(i,3)); + end + + if ~insert(dhk(i,3),dhk(i,1)) + current = current + 1; + pntr(current,:) = (pnt(dhk(i,3),:) + pnt(dhk(i,1),:))/2; + insert(dhk(i,3),dhk(i,1)) = current; + insert(dhk(i,1),dhk(i,3)) = current; + v31 = current; + else + v31 = insert(dhk(i,3),dhk(i,1)); + end + + % add the 4 new triangles with the correct indices + dhkr(4*(i-1)+1, :) = [dhk(i,1) v12 v31]; + dhkr(4*(i-1)+2, :) = [dhk(i,2) v23 v12]; + dhkr(4*(i-1)+3, :) = [dhk(i,3) v31 v23]; + dhkr(4*(i-1)+4, :) = [v12 v23 v31]; + + end + + % remove the space for the vertices that was not used + pntr = pntr(1:current, :); + +case 'updown' + ndhk = size(dhk,1); + while ndhk -y1.*(x2-x1); + +% Find all line segments that cross the positive x axis +crossing_test = (cross_product_test==vert_with_negative_y) & is_line_segment_spanning_x; + +% If the number of line segments is odd, then we intersected the polygon +s = sum(crossing_test,2); +s = mod(s,2); +ind_intersection_test = find(s~=0); + +% Bail out early if no faces were hit +if isempty(ind_intersection_test) + return; +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Plane/ray intersection test %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Perform plane/ray intersection with the faces that passed +% the polygon intersection tests. Grab the only the first +% three vertices since that is all we need to define a plane). +% assuming planar polygons. +candidate_faces = candidate_faces(ind_intersection_test,1:3); +candidate_faces = reshape(candidate_faces',1,prod(size(candidate_faces))); +vert = vert'; +candidate_facev = vert(:,candidate_faces); +candidate_facev = reshape(candidate_facev,3,3,length(ind_intersection_test)); + +% Get three contiguous vertices along polygon +v1 = squeeze(candidate_facev(:,1,:)); +v2 = squeeze(candidate_facev(:,2,:)); +v3 = squeeze(candidate_facev(:,3,:)); + +% Get normal to face plane +vec1 = [v2-v1]; +vec2 = [v3-v2]; +crs = cross(vec1,vec2); +mag = sqrt(sum(crs.*crs)); +nplane(1,:) = crs(1,:)./mag; +nplane(2,:) = crs(2,:)./mag; +nplane(3,:) = crs(3,:)./mag; + +% Compute intersection between plane and ray +cp1 = cp(:,1); +cp2 = cp(:,2); +d = cp2-cp1; +dp = dot(-nplane,v1); + +%A = dot(nplane,d); +A(1,:) = nplane(1,:).*d(1); +A(2,:) = nplane(2,:).*d(2); +A(3,:) = nplane(3,:).*d(3); +A = sum(A,1); + +%B = dot(nplane,pt1) +B(1,:) = nplane(1,:).*cp1(1); +B(2,:) = nplane(2,:).*cp1(2); +B(3,:) = nplane(3,:).*cp1(3); +B = sum(B,1); + +% Distance to intersection point +t = (-dp-B)./A; + +% Find "best" distance (smallest) +[tbest ind_best] = min(t); + +% Determine intersection point +pout = cp1 + tbest .* d; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Assign additional output variables %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +if nargout>1 + + % Get face index and vertices + faceiout = ind_is_face_spanning_x(ind_intersection_test(ind_best)); + facevout = vert(:,faces(faceiout,:)); + + % Determine index of closest face vertex intersected + facexv = xvert(:,faces(faceiout,:)); + dist = sqrt(facexv(1,:).*facexv(1,:) + facexv(2,:).*facexv(2,:)); + min_dist = min(dist); + min_index = find(dist==min_dist); + + % Get closest vertex index and vertex + viout = faces(faceiout,min_index); + vout = vert(:,viout); +end diff --git a/external/fieldtrip/plotting/private/select3dtool.m b/external/fieldtrip/plotting/private/select3dtool.m new file mode 100644 index 0000000..8b4ba34 --- /dev/null +++ b/external/fieldtrip/plotting/private/select3dtool.m @@ -0,0 +1,111 @@ +function select3dtool(arg) +%SELECT3DTOOL A simple tool for interactively obtaining 3-D coordinates +% +% SELECT3DTOOL(FIG) Specify figure handle +% +% Example: +% surf(peaks); +% select3dtool; +% % click on surface + +if nargin<1 + arg = gcf; +end + +if ~ishandle(arg) + feval(arg); + return; +end + +%% initialize gui %% +fig = arg; +figure(fig); + +uistate = uiclearmode(fig); +[tool, htext] = createUI; +hmarker1 = line('marker','o','markersize',10,'markerfacecolor','k','erasemode','xor','visible','off'); +hmarker2 = line('marker','o','markersize',10,'markerfacecolor','r','erasemode','xor','visible','off'); + +state.uistate = uistate; +state.text = htext; +state.tool = tool; +state.fig = fig; +state.marker1 = hmarker1; +state.marker2 = hmarker2; +setappdata(fig,'select3dtool',state); +setappdata(state.tool,'select3dhost',fig); + +set(fig,'windowbuttondownfcn','select3dtool(''click'')'); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function off + +state = getappdata(gcbf,'select3dtool'); + +if ~isempty(state) + delete(state.tool); +end + +fig = getappdata(gcbf,'select3dhost'); + +if ~isempty(fig) & ishandle(fig) + state = getappdata(fig,'select3dtool'); + uirestore(state.uistate); + delete(state.marker1); + delete(state.marker2); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function click + +[p v vi] = select3d; +state = getappdata(gcbf,'select3dtool'); + +if ~ishandle(state.text) + state.text = createUI; +end + +if ~ishandle(state.marker1) + state.marker1 = []; +end + +if ~ishandle(state.marker2) + state.marker2 = []; +end + +setappdata(state.fig,'select3dtool',state); + +if isempty(v) + v = [nan nan nan]; + vi = nan; + set(state.marker2,'visible','off'); +else + set(state.marker2,'visible','on','xdata',v(1),'ydata',v(2),'zdata',v(3)); +end + +if isempty(p) + p = [nan nan nan]; + set(state.marker1,'visible','off'); +else + set(state.marker1,'visible','on','xdata',p(1),'ydata',p(2),'zdata',p(3)); +end + +% Update tool and markers +set(state.text,'string',createString(p(1),p(2),p(3),v(1),v(2),v(3),vi)); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [fig, h] = createUI + +pos = [200 200 200 200]; + +% Create selection tool % +fig = figure('handlevisibility','off','menubar','none','resize','off',... + 'numbertitle','off','name','Select 3-D Tool','position',pos,'deletefcn','select3dtool(''off'')'); + +h = uicontrol('style','text','parent',fig,'string',createString(0,0,0,0,0,0,0),... + 'units','norm','position',[0 0 1 1],'horizontalalignment','left'); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [str] = createString(px,py,pz,vx,vy,vz,vi) + +str = sprintf(' Position:\n X %f\n Y: %f\n Z: %f \n\n Vertex:\n X: %f\n Y: %f\n Z: %f \n\n Vertex Index:\n %d',px,py,pz,vx,vy,vz,vi); diff --git a/external/fieldtrip/plotting/private/skin.m b/external/fieldtrip/plotting/private/skin.m new file mode 100644 index 0000000..d0e56e6 --- /dev/null +++ b/external/fieldtrip/plotting/private/skin.m @@ -0,0 +1,17 @@ +function rgb = rgbcolor + +% returns a predefined color as [red green blue] values +% +% skin = [255 213 119]/255; +% skull = [140 85 85]/255; +% brain = [202 100 100]/255; +% cortex = [255 213 119]/255; +% black = [0 0 0 ]/255; +% white = [255 255 255]/255; +% red = [255 0 0 ]/255; +% green = [0 192 0 ]/255; +% blue = [0 0 255]/255; +% yellow = [255 255 0 ]/255; + +rgb = [255 213 119]/255; + diff --git a/external/fieldtrip/plotting/private/skull.m b/external/fieldtrip/plotting/private/skull.m new file mode 100644 index 0000000..e02271a --- /dev/null +++ b/external/fieldtrip/plotting/private/skull.m @@ -0,0 +1,17 @@ +function rgb = rgbcolor + +% returns a predefined color as [red green blue] values +% +% skin = [255 213 119]/255; +% skull = [140 85 85]/255; +% brain = [202 100 100]/255; +% cortex = [255 213 119]/255; +% black = [0 0 0 ]/255; +% white = [255 255 255]/255; +% red = [255 0 0 ]/255; +% green = [0 192 0 ]/255; +% blue = [0 0 255]/255; +% yellow = [255 255 0 ]/255; + +rgb = [140 85 85]/255; + diff --git a/external/fieldtrip/plotting/private/white.m b/external/fieldtrip/plotting/private/white.m new file mode 100644 index 0000000..d7b157c --- /dev/null +++ b/external/fieldtrip/plotting/private/white.m @@ -0,0 +1,17 @@ +function rgb = rgbcolor + +% returns a predefined color as [red green blue] values +% +% skin = [255 213 119]/255; +% skull = [140 85 85]/255; +% brain = [202 100 100]/255; +% cortex = [255 213 119]/255; +% black = [0 0 0 ]/255; +% white = [255 255 255]/255; +% red = [255 0 0 ]/255; +% green = [0 192 0 ]/255; +% blue = [0 0 255]/255; +% yellow = [255 255 0 ]/255; + +rgb = [255 255 255]/255; + diff --git a/external/fieldtrip/plotting/private/yellow.m b/external/fieldtrip/plotting/private/yellow.m new file mode 100644 index 0000000..cc2d1df --- /dev/null +++ b/external/fieldtrip/plotting/private/yellow.m @@ -0,0 +1,17 @@ +function rgb = rgbcolor + +% returns a predefined color as [red green blue] values +% +% skin = [255 213 119]/255; +% skull = [140 85 85]/255; +% brain = [202 100 100]/255; +% cortex = [255 213 119]/255; +% black = [0 0 0 ]/255; +% white = [255 255 255]/255; +% red = [255 0 0 ]/255; +% green = [0 192 0 ]/255; +% blue = [0 0 255]/255; +% yellow = [255 255 0 ]/255; + +rgb = [255 255 0 ]/255; + diff --git a/external/fieldtrip/preproc/COPYING b/external/fieldtrip/preproc/COPYING new file mode 100644 index 0000000..1b28104 --- /dev/null +++ b/external/fieldtrip/preproc/COPYING @@ -0,0 +1,341 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + diff --git a/external/fieldtrip/preproc/README b/external/fieldtrip/preproc/README new file mode 100644 index 0000000..143b486 --- /dev/null +++ b/external/fieldtrip/preproc/README @@ -0,0 +1,16 @@ +This is the FieldTrip PREPROC module. It contains functions for the +preprocessing of EEG and MEG data, such as filtering, baseline +correction and re-referencing. + +For more information please visit http://www.ru.nl/fcdonders/fieldtrip. + +The FieldTrip software is free but copyrighted software, distributed +under the terms of the GNU General Public Licence as published by +the Free Software Foundation (either version 2, or at your option +any later version). See the file COPYING for more details. + +Copyright (C) 2008-2009, Donders Institute for Brain, Cognition and Behaviour, The Netherlands (DCCN) +Copyright (C) 2003-2008, F.C. Donders Centre for Cognitive Neuroimaging, Nijmegen, The Netherlands (FCDC) +Copyright (C) 2003-2005, Center for Sensory-Motor Interaction, Aalborg University, Denmark (SMI) +Copyright (C) 1999-2003, Department of Medical Physics, Radboud University Nijmegen, The Netherlands (MBFYS) + diff --git a/external/fieldtrip/preproc/ft_preproc_bandpassfilter.m b/external/fieldtrip/preproc/ft_preproc_bandpassfilter.m new file mode 100644 index 0000000..a5f9eb7 --- /dev/null +++ b/external/fieldtrip/preproc/ft_preproc_bandpassfilter.m @@ -0,0 +1,91 @@ +function [filt] = ft_preproc_bandpassfilter(dat, Fs, Fbp, N, type, dir) + +% FT_PREPROC_BANDPASSFILTER applies a band-pass filter to the data and thereby +% removes the spectral components in the data except for the ones in the +% specified frequency band +% +% Use as +% [filt] = ft_preproc_bandpassfilter(dat, Fsample, Fbp, N, type, dir) +% where +% dat data matrix (Nchans X Ntime) +% Fsample sampling frequency in Hz +% Fbp frequency band, specified as [Fhp Flp] +% N optional filter order, default is 4 (but) or 25 (fir) +% type optional filter type, can be +% 'but' Butterworth IIR filter (default) +% 'fir' FIR filter using Matlab fir1 function +% dir optional filter direction, can be +% 'onepass' forward filter only +% 'onepass-reverse' reverse filter only, i.e. backward in time +% 'twopass' zero-phase forward and reverse filter (default) +% +% Note that a one- or two-pass filter has consequences for the +% strength of the filter, i.e. a two-pass filter with the same filter +% order will attenuate the signal twice as strong. +% +% See also PREPROC + +% Copyright (c) 2003-2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_preproc_bandpassfilter.m 947 2010-04-21 17:56:46Z roboos $ + +% set the default filter order later +if nargin<4 || isempty(N) + N = []; +end + +% set the default filter type +if nargin<5 || isempty(type) + type = 'but'; +end + +% set the default filter direction +if nargin<6|| isempty(dir) + dir = 'twopass'; +end + +% Nyquist frequency +Fn = Fs/2; + +% compute filter coefficients +switch type + case 'but' + if isempty(N) + N = 4; + end + [B, A] = butter(N, [min(Fbp)/Fn max(Fbp)/Fn]); + case 'fir' + if isempty(N) + N = 25; + end + [B, A] = fir1(N, [min(Fbp)/Fn max(Fbp)/Fn]); +end + +% apply filter to the data +switch dir + case 'onepass' + filt = filter(B, A, dat')'; + case 'onepass-reverse' + dat = fliplr(dat); + filt = filter(B, A, dat')'; + filt = fliplr(filt); + case 'twopass' + filt = filtfilt(B, A, dat')'; +end + diff --git a/external/fieldtrip/preproc/ft_preproc_bandstopfilter.m b/external/fieldtrip/preproc/ft_preproc_bandstopfilter.m new file mode 100644 index 0000000..96c6029 --- /dev/null +++ b/external/fieldtrip/preproc/ft_preproc_bandstopfilter.m @@ -0,0 +1,90 @@ +function [filt] = ft_preproc_bandstopfilter(dat,Fs,Fbp,N,type,dir) + +% FT_PREPROC_BANDSTOPFILTER applies a band-stop filter to the data and thereby +% removes the spectral components in the specified frequency band +% +% Use as +% [filt] = ft_preproc_bandstopfilter(dat, Fsample, Fbp, N, type, dir) +% where +% dat data matrix (Nchans X Ntime) +% Fsample sampling frequency in Hz +% Fbp frequency band, specified as [Fhp Flp] +% N optional filter order, default is 4 (but) or 25 (fir) +% type optional filter type, can be +% 'but' Butterworth IIR filter (default) +% 'fir' FIR filter using Matlab fir1 function +% dir optional filter direction, can be +% 'onepass' forward filter only +% 'onepass-reverse' reverse filter only, i.e. backward in time +% 'twopass' zero-phase forward and reverse filter (default) +% +% Note that a one- or two-pass filter has consequences for the +% strength of the filter, i.e. a two-pass filter with the same filter +% order will attenuate the signal twice as strong. +% +% See also PREPROC + +% Copyright (c) 2007-2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_preproc_bandstopfilter.m 947 2010-04-21 17:56:46Z roboos $ + +% set the default filter order later +if nargin<4 || isempty(N) + N = []; +end + +% set the default filter type +if nargin<5 || isempty(type) + type = 'but'; +end + +% set the default filter direction +if nargin<6|| isempty(dir) + dir = 'twopass'; +end + +% Nyquist frequency +Fn = Fs/2; + +% compute filter coefficients +switch type + case 'but' + if isempty(N) + N = 4; + end + [B, A] = butter(N, [min(Fbp)/Fn max(Fbp)/Fn], 'stop'); + case 'fir' + if isempty(N) + N = 25; + end + [B, A] = fir1(N, [min(Fbp)/Fn max(Fbp)/Fn], 'stop'); +end + +% apply filter to the data +switch dir + case 'onepass' + filt = filter(B, A, dat')'; + case 'onepass-reverse' + dat = fliplr(dat); + filt = filter(B, A, dat')'; + filt = fliplr(filt); + case 'twopass' + filt = filtfilt(B, A, dat')'; +end + diff --git a/external/fieldtrip/preproc/ft_preproc_baselinecorrect.m b/external/fieldtrip/preproc/ft_preproc_baselinecorrect.m new file mode 100644 index 0000000..22a6751 --- /dev/null +++ b/external/fieldtrip/preproc/ft_preproc_baselinecorrect.m @@ -0,0 +1,62 @@ +function [dat, baseline] = ft_preproc_baselinecorrect(dat, begsample, endsample) + +% FT_PREPROC_BASELINECORRECT performs a baseline correction, e.g. using the +% prestimulus interval of the data or using the complete data +% +% Use as +% [dat] = ft_preproc_baselinecorrect(dat, begin, end) +% where +% dat data matrix (Nchans X Ntime) +% begsample index of the begin sample for the baseline estimate +% endsample index of the end sample for the baseline estimate +% +% If no begin and end sample are specified for the baseline estimate, it +% will be estimated on the complete data. +% +% See also PREPROC + +% Copyright (C) 1998-2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_preproc_baselinecorrect.m 1122 2010-05-20 12:12:32Z marvger $ + +% determine the size of the data +[Nchans, Nsamples] = size(dat); + +% determine the interval to use for baseline correction +if nargin<2 || isempty(begsample) + begsample = 1; +end +if nargin<3 || isempty(endsample) + endsample = Nsamples; +end + +% estimate the baseline and subtract it +baseline = mean(dat(:,begsample:endsample), 2); + +% it is faster to loop over samples than over channels due to the internal memory representation of Matlab +% for chan=1:Nchans +% dat(chan,:) = dat(chan,:) - baseline(chan); +% end + +% for sample=1:Nsamples +% dat(:,sample) = dat(:,sample) - baseline; +% end + +% it is even faster to do this +dat = bsxfun(@minus,dat,baseline); diff --git a/external/fieldtrip/preproc/ft_preproc_denoise.m b/external/fieldtrip/preproc/ft_preproc_denoise.m new file mode 100644 index 0000000..0274ce1 --- /dev/null +++ b/external/fieldtrip/preproc/ft_preproc_denoise.m @@ -0,0 +1,63 @@ +function [dat, w] = ft_preproc_denoise(dat, refdat, hilbertflag) + +% FT_PREPROC_DENOISE performs a regression of the matrix dat onto +% refdat, and subtracts the projected data. Tis is for the +% purpose of removing signals generated by coils during continuous +% head motion tracking, for exxample. +% +% Use as +% [dat] = ft_preproc_denoise(dat, refdat, hilbertflag) +% where +% dat data matrix (Nchan1 X Ntime) +% refdat data matrix (Nchan2 X Ntime) +% hilbertflag specifying to regress out the real and imaginary parts of +% the hilbert transformed signal. Only meaningful for narrow +% band reference data +% +% See also PREPROC + +% Copyright (C) 2009, Jan-Mathijs Schoffelen +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_preproc_denoise.m 947 2010-04-21 17:56:46Z roboos $ + +if nargin<3, + hilbertflag = 0; +end + +n1 = size(dat,2); +n2 = size(refdat,2); +m1 = mean(dat,2); +m2 = mean(refdat,2); + +%remove mean +refdat = refdat-m2(:,ones(n2,1)); +tmpdat = dat-m1(:,ones(n1,1)); + +%do hilbert transformation +if hilbertflag>0, + hrefdat = hilbert(refdat')'; + refdat = [real(hrefdat);imag(hrefdat)]; +end + +c12 = tmpdat*refdat'; %covariance between signals and references +c1 = refdat*refdat'; %covariance between references and references +w = (pinv(c1)*c12')'; %regression weights + +%subtract +dat = dat-w*refdat; diff --git a/external/fieldtrip/preproc/ft_preproc_derivative.m b/external/fieldtrip/preproc/ft_preproc_derivative.m new file mode 100644 index 0000000..5722e1a --- /dev/null +++ b/external/fieldtrip/preproc/ft_preproc_derivative.m @@ -0,0 +1,66 @@ +function [dat] = ft_preproc_derivative(dat, order, padding) + +% FT_PREPROC_DERIVATIVE computes the temporal Nth order derivative of the +% data +% +% Use as +% [dat] = ft_preproc_derivative(dat, order, padding) +% where +% dat data matrix (Nchans X Ntime) +% order number representing the Nth derivative (default = 1) +% padding string that determines whether and how the data will be +% padded to keep the number of samples the same, can be +% 'none' do not apply padding, the output will be N samples shorter +% 'both' apply padding to both sides +% 'beg' apply padding at the beginning of the data +% 'end' apply padding at the end of the data (default) +% +% See also PREPROC + +% Copyright (C) 2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_preproc_derivative.m 947 2010-04-21 17:56:46Z roboos $ + +% determine the size of the data +[Nchans, Nsamples] = size(dat); + +% set the defaults if options are not specified +if nargin<2 || isempty(order) + order = 1; +end +if nargin<3 || isempty(padding) + padding = 'end'; +end + +% compute the derivative +dat = diff(dat, order, 2); + +% pad the resulting data to keep the number of samples the same +switch padding + case 'beg' + dat = cat(2, zeros(Nchans, order), dat); + case 'end' + dat = cat(2, dat, zeros(Nchans, order)); + case 'both' + if rem(order,2) + error('padding can only be applied to both sides if the order is an even number'); + end + dat = cat(2, zeros(Nchans, order/2), dat, zeros(Nchans, order/2)); +end + diff --git a/external/fieldtrip/preproc/ft_preproc_detrend.m b/external/fieldtrip/preproc/ft_preproc_detrend.m new file mode 100644 index 0000000..9cffe4b --- /dev/null +++ b/external/fieldtrip/preproc/ft_preproc_detrend.m @@ -0,0 +1,64 @@ +function [dat, beta, x] = ft_preproc_detrend(dat, begsample, endsample, order) + +% FT_PREPROC_DETREND removes linear or higher order polynomial trends from the +% data using using General Linear Modeling +% +% Use as +% [dat] = ft_preproc_detrend(dat, begin, end, order) +% where +% dat data matrix (Nchans X Ntime) +% begsample index of the begin sample for the trend estimate +% endsample index of the end sample for the trend estimate +% order number representing the polynomial order (default = 1, i.e. linear) +% +% If no begin and end sample are specified for the trend estimate, it +% will be estimated on the complete data. +% +% See also PREPROC + +% Copyright (C) 2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_preproc_detrend.m 947 2010-04-21 17:56:46Z roboos $ + +% determine the size of the data +[Nchans, Nsamples] = size(dat); + +% determine the interval to use for baseline correction +if nargin<2 || isempty(begsample) + begsample = 1; +end +if nargin<3 || isempty(endsample) + endsample = Nsamples; +end + +% determine the order of the polynomial trend to be removed, default is linear +if nargin<4 || isempty(order) + order = 1; +end + +% create a matrix with regressor components +basis = 1:Nsamples; +x = zeros(order+1,Nsamples); +for i=0:order + x(i+1,:) = basis.^(i); +end +% estimate the polynomial trend using General Linear Modeling, where dat=beta*x+noise +beta = dat(:,begsample:endsample)/x(:,begsample:endsample); +% subtract the trend from the complete data +dat = dat - beta*x; diff --git a/external/fieldtrip/preproc/ft_preproc_dftfilter.m b/external/fieldtrip/preproc/ft_preproc_dftfilter.m new file mode 100644 index 0000000..cc3fe48 --- /dev/null +++ b/external/fieldtrip/preproc/ft_preproc_dftfilter.m @@ -0,0 +1,72 @@ +function [filt] = ft_preproc_dftfilter(dat, Fs, Fl) + +% PREPROC_DFTFILTER applies a notch filter to the data to remove the 50Hz +% or 60Hz line noise components. This is done by fitting a sine and cosine +% at the specified frequency to the data and subsequently subtracting the +% estimated components. The longer the data is, the sharper the spectral +% notch will be that is removed from the data. +% +% Use as +% [filt] = ft_preproc_dftfilter(dat, Fsample, Fline) +% where +% dat data matrix (Nchans X Ntime) +% Fsample sampling frequency in Hz +% Fline line noise frequency +% +% The line frequency should be specified as a single number. +% If omitted, a European default of 50Hz will be assumed. +% +% Preferaby the data should have a length that is a multiple of the +% oscillation period of the line noise (i.e. 20ms for 50Hz noise). If the +% data is of different lenght, then only the first N complete periods are +% used to estimate the line noise. The estimate is subtracted from the +% complete data. +% +% See also PREPROC + +% Copyright (C) 2003, Pascal Fries +% Copyright (C) 2003-2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_preproc_dftfilter.m 947 2010-04-21 17:56:46Z roboos $ + +% determine the size of the data +[Nchans, Nsamples] = size(dat); + +% set the default filter frequency +if nargin<3 || isempty(Fl) + Fl = 50; +end + +% determine the largest integer number of line-noise cycles that fits in the data +sel = 1:round(floor(Nsamples * Fl/Fs) * Fs/Fl); + +% temporarily remove mean to avoid leakage +mdat = mean(dat(:,sel),2); +dat = dat - mdat(:,ones(1,Nsamples)); + +% fit a sin and cos to the signal and subtract them +time = (0:Nsamples-1)/Fs; +tmp = exp(j*2*pi*Fl*time); % complex sin and cos +% ampl = 2*dat*tmp'/Nsamples; % estimated amplitude of complex sin and cos +ampl = 2*dat(:,sel)*tmp(sel)'/length(sel); % estimated amplitude of complex sin and cos on integer number of cycles +est = ampl*tmp; % estimated signal at this frequency +%filt = dat - est; % subtract estimated signal +filt = dat - est + mdat(:,ones(1,Nsamples)); +filt = real(filt); + diff --git a/external/fieldtrip/preproc/ft_preproc_highpassfilter.m b/external/fieldtrip/preproc/ft_preproc_highpassfilter.m new file mode 100644 index 0000000..482ab77 --- /dev/null +++ b/external/fieldtrip/preproc/ft_preproc_highpassfilter.m @@ -0,0 +1,90 @@ +function [filt] = ft_preproc_highpassfilter(dat,Fs,Fhp,N,type,dir) + +% FT_PREPROC_HIGHPASSFILTER applies a high-pass filter to the data and thereby +% removes the low frequency components in the data +% +% Use as +% [filt] = ft_preproc_highpassfilter(dat, Fsample, Fhp, N, type, dir) +% where +% dat data matrix (Nchans X Ntime) +% Fsample sampling frequency in Hz +% Fhp filter frequency +% N optional filter order, default is 6 (but) or 25 (fir) +% type optional filter type, can be +% 'but' Butterworth IIR filter (default) +% 'fir' FIR filter using Matlab fir1 function +% dir optional filter direction, can be +% 'onepass' forward filter only +% 'onepass-reverse' reverse filter only, i.e. backward in time +% 'twopass' zero-phase forward and reverse filter (default) +% +% Note that a one- or two-pass filter has consequences for the +% strength of the filter, i.e. a two-pass filter with the same filter +% order will attenuate the signal twice as strong. +% +% See also PREPROC + +% Copyright (c) 2003-2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_preproc_highpassfilter.m 947 2010-04-21 17:56:46Z roboos $ + +% set the default filter order later +if nargin<4 || isempty(N) + N = []; +end + +% set the default filter type +if nargin<5 || isempty(type) + type = 'but'; +end + +% set the default filter direction +if nargin<6|| isempty(dir) + dir = 'twopass'; +end + +% Nyquist frequency +Fn = Fs/2; + +% compute filter coefficients +switch type + case 'but' + if isempty(N) + N = 6; + end + [B, A] = butter(N, max(Fhp)/Fn, 'high'); + case 'fir' + if isempty(N) + N = 25; + end + [B, A] = fir1(N, max(Fhp)/Fn, 'high'); +end + +% apply filter to the data +switch dir + case 'onepass' + filt = filter(B, A, dat')'; + case 'onepass-reverse' + dat = fliplr(dat); + filt = filter(B, A, dat')'; + filt = fliplr(filt); + case 'twopass' + filt = filtfilt(B, A, dat')'; +end + diff --git a/external/fieldtrip/preproc/ft_preproc_hilbert.m b/external/fieldtrip/preproc/ft_preproc_hilbert.m new file mode 100644 index 0000000..80ab358 --- /dev/null +++ b/external/fieldtrip/preproc/ft_preproc_hilbert.m @@ -0,0 +1,74 @@ +function [dat] = ft_preproc_hilbert(dat, option) + +% FT_PREPROC_HILBERT computes the Hilbert transpose of the data and optionally +% performs post-processing on the complex representation, e.g. the absolute +% value of the Hilbert transform of a band-pass filtered signal corresponds +% with the amplitude envelope. +% +% Use as +% [dat] = ft_preproc_hilbert(dat, option) +% where +% dat data matrix (Nchans X Ntime) +% option string that determines whether and how the Hilbert transform +% should be post-processed, can be +% 'abs' +% 'complex' +% 'real' +% 'imag' +% 'absreal' +% 'absimag' +% 'angle' +% +% The default is to return the absolute value of the Hilbert transform. +% +% See also PREPROC + +% Copyright (C) 2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_preproc_hilbert.m 947 2010-04-21 17:56:46Z roboos $ + +% set the defaults if option is not specified +if nargin<2 || isempty(option) + option = 'abs'; +end + +% use the non-conjugate transpose to be sure +dat = transpose(hilbert(transpose(dat))); + +% do postprocessing of the complex representation +switch option + case {'yes' 'abs'} + dat = abs(dat); % this is the default if 'yes' is specified + case {'no' 'complex'} + dat = dat; % this is the default if 'no' is specified + case 'real' + dat = real(dat); + case 'imag' + dat = imag(dat); + case 'absreal' + dat = abs(real(dat)); + case 'absimag' + dat = abs(imag(dat)); + case 'angle' + dat = (angle(dat./abs(dat))); + case 'unwrap_angle' + dat = unwrap(angle(dat./abs(dat)),[],2); + otherwise + error('incorrect specification of the optional input argument'); +end diff --git a/external/fieldtrip/preproc/ft_preproc_lowpassfilter.m b/external/fieldtrip/preproc/ft_preproc_lowpassfilter.m new file mode 100644 index 0000000..fff988c --- /dev/null +++ b/external/fieldtrip/preproc/ft_preproc_lowpassfilter.m @@ -0,0 +1,90 @@ +function [filt] = ft_preproc_lowpassfilter(dat,Fs,Flp,N,type,dir) + +% FT_PREPROC_LOWPASSFILTER applies a low-pass filter to the data and thereby +% removes all high frequency components in the data +% +% Use as +% [filt] = ft_preproc_lowpassfilter(dat, Fsample, Flp, N, type, dir) +% where +% dat data matrix (Nchans X Ntime) +% Fsample sampling frequency in Hz +% Flp filter frequency +% N optional filter order, default is 6 (but) or 25 (fir) +% type optional filter type, can be +% 'but' Butterworth IIR filter (default) +% 'fir' FIR filter using Matlab fir1 function +% dir optional filter direction, can be +% 'onepass' forward filter only +% 'onepass-reverse' reverse filter only, i.e. backward in time +% 'twopass' zero-phase forward and reverse filter (default) +% +% Note that a one- or two-pass filter has consequences for the +% strength of the filter, i.e. a two-pass filter with the same filter +% order will attenuate the signal twice as strong. +% +% See also PREPROC + +% Copyright (c) 2003-2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_preproc_lowpassfilter.m 947 2010-04-21 17:56:46Z roboos $ + +% set the default filter order later +if nargin<4 || isempty(N) + N = []; +end + +% set the default filter type +if nargin<5 || isempty(type) + type = 'but'; +end + +% set the default filter direction +if nargin<6|| isempty(dir) + dir = 'twopass'; +end + +% Nyquist frequency +Fn = Fs/2; + +% compute filter coefficients +switch type + case 'but' + if isempty(N) + N = 6; + end + [B, A] = butter(N, max(Flp)/Fn); + case 'fir' + if isempty(N) + N = 25; + end + [B, A] = fir1(N, max(Flp)/Fn); +end + +% apply filter to the data +switch dir + case 'onepass' + filt = filter(B, A, dat')'; + case 'onepass-reverse' + dat = fliplr(dat); + filt = filter(B, A, dat')'; + filt = fliplr(filt); + case 'twopass' + filt = filtfilt(B, A, dat')'; +end + diff --git a/external/fieldtrip/preproc/ft_preproc_medianfilter.m b/external/fieldtrip/preproc/ft_preproc_medianfilter.m new file mode 100644 index 0000000..b6963c5 --- /dev/null +++ b/external/fieldtrip/preproc/ft_preproc_medianfilter.m @@ -0,0 +1,40 @@ +function dat = ft_preproc_medianfilter(dat, order); + +% FT_PREPROC_MEDIANFILTER applies a median filter, which smooths the data with +% a boxcar-like kernel except that it keeps steps in the data. This +% function requires the Matlab Signal Processing toolbox. +% +% Use as +% [dat] = ft_preproc_medianfilter(dat, order) +% where +% dat data matrix (Nchans X Ntime) +% order number, the length of the median filter kernel (default = 25) +% +% See also PREPROC + +% Copyright (C) 2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_preproc_medianfilter.m 947 2010-04-21 17:56:46Z roboos $ + +% set the default filter order +if nargin<2 || isempty(order) + order = 25; +end + +dat = medfilt1(dat, order, [], 2); diff --git a/external/fieldtrip/preproc/ft_preproc_rectify.m b/external/fieldtrip/preproc/ft_preproc_rectify.m new file mode 100644 index 0000000..cc32eb7 --- /dev/null +++ b/external/fieldtrip/preproc/ft_preproc_rectify.m @@ -0,0 +1,34 @@ +function [dat] = ft_preproc_rectify(dat) + +% FT_PREPROC_RECTIFY rectifies the data, i.e. converts all samples with a +% negative value into the similar magnitude positive value +% +% Use as +% [dat] = ft_preproc_rectify(dat) +% where +% dat data matrix (Nchans X Ntime) +% +% See also PREPROC + +% Copyright (C) 2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_preproc_rectify.m 947 2010-04-21 17:56:46Z roboos $ + +dat = abs(dat); + diff --git a/external/fieldtrip/preproc/ft_preproc_rereference.m b/external/fieldtrip/preproc/ft_preproc_rereference.m new file mode 100644 index 0000000..2aaad87 --- /dev/null +++ b/external/fieldtrip/preproc/ft_preproc_rereference.m @@ -0,0 +1,51 @@ +function [dat, ref] = ft_preproc_rereference(dat, refchan) + +% FT_PREPROC_REREFERENCE computes the average reference over all EEG channels +% or rereferences the data to the selected channeld +% +% Use as +% [dat] = ft_preproc_rereference(dat, refchan) +% where +% dat data matrix (Nchans X Ntime) +% refchan vector with indices of the new reference channels +% +% If the new reference channel is not specified, the data will be +% rereferenced to the average of all channels. +% +% See also PREPROC + +% Copyright (C) 1998-2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_preproc_rereference.m 947 2010-04-21 17:56:46Z roboos $ + +% determine the size of the data +[Nchans, Nsamples] = size(dat); + +% determine the new reference channels +if nargin<2 || isempty(refchan) || (ischar(refchan) && strcmp(refchan, 'all')) + refchan = 1:Nchans; +end + +% compute the average value over the reference channels +ref = mean(dat(refchan,:), 1); + +% apply the new reference to the data +for chan=1:Nchans + dat(chan,:) = dat(chan,:) - ref; +end diff --git a/external/fieldtrip/preproc/ft_preproc_resample.m b/external/fieldtrip/preproc/ft_preproc_resample.m new file mode 100644 index 0000000..5c52015 --- /dev/null +++ b/external/fieldtrip/preproc/ft_preproc_resample.m @@ -0,0 +1,75 @@ +function [dat, tim] = ft_preproc_resample(dat, Fold, Fnew, method) + +% FT_PREPROC_RESAMPLE resamples all channels in the data matrix +% +% Use as +% dat = ft_preproc_resample(dat, Fold, Fnew, method) +% where +% dat = matrix with the input data (Nchans X Nsamples) +% Fold = scalar, original sampling frequency in Hz +% Fnew = scalar, desired sampling frequency in Hz +% method = string, can be 'resample', 'decimate', 'downsample' +% +% The resample method applies an anti-aliasing (lowpass) FIR filter to +% the data during the resampling process, and compensates for the filter's +% delay. For the other two methods you should apply an anti-aliassing +% filter prior to calling this function. +% +% See also PREPROC, FT_PREPROC_LOWPASSFILTER + +% Copyright (C) 2006-2010, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id$ + +if nargout==2 + tim = 1:size(dat,2); + tim = ft_preproc_resample(tim, Fold, Fnew, method); +end + +if Fold==Fnew + return +end + +switch method + case 'resample' + if ~isa(dat, 'double') + typ = class(dat); + dat = typecast(dat, 'double'); + dat = resample(dat, Fnew, Fold); % this requires a double array + dat = typecast(dat, typ); + else + dat = resample(dat, Fnew, Fold); + end + case 'decimate' + fac = round(Fold/Fnew); + if ~isa(dat, 'double') + typ = class(dat); + dat = typecast(dat, 'double'); + dat = decimate(dat, fac); % this requires a double array + dat = typecast(dat, typ); + else + dat = decimate(dat, fac); % this requires a double array + end + case 'downsample' + fac = Fold/Fnew; + dat = downsample(dat, fac); + otherwise + error('unsupported resampling method'); +end + diff --git a/external/fieldtrip/preproc/ft_preproc_standardize.m b/external/fieldtrip/preproc/ft_preproc_standardize.m new file mode 100644 index 0000000..464c14b --- /dev/null +++ b/external/fieldtrip/preproc/ft_preproc_standardize.m @@ -0,0 +1,78 @@ +function [x, state] = ft_preproc_standardize(x, begsample, endsample, state) + +% FT_PREPROC_STANDARDIZE performs a z-transformation or standardization +% of the data. The standardized data will have a zero-mean and a unit +% standard deviation. +% +% Use as +% [dat] = ft_preproc_standardize(dat, begsample, endsample) +% where +% dat data matrix (Nchans X Ntime) +% begsample index of the begin sample for the mean and stdev estimate +% endsample index of the end sample for the mean and stdev estimate +% +% If no begin and end sample are specified, it will be estimated on the +% complete data. +% +% See also PREPROC + +% Copyright (C) 2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ft_preproc_standardize.m 947 2010-04-21 17:56:46Z roboos $ + +if nargin<2 || isempty(begsample) + begsample = 1; +end + +if nargin<3 || isempty(endsample) + endsample = size(x,2); +end + +if nargin<4 + state = []; +end + +% get the data selection +y = x(:,begsample:endsample); + +% determine the size of the selected data: nChans X nSamples +[m, n] = size(y); + +% compute the sum and sum of squares +s = sum(y,2); +ss = sum(y.^2,2); + +% include the state information from the previous calls +if ~isempty(state) + s = s + state.s; + ss = ss + state.ss; + n = n + state.n; +end + +% compute the mean and standard deviation +my = s ./ n; +sy = sqrt((ss - (s.^2)./n) ./ (n-1)); + +% standardize the complete input data +x = (x - repmat(my, 1, size(x, 2))) ./ repmat(sy, 1, size(x, 2)); + +% remember the state +state.s = s; % sum +state.ss = ss; % sum of sqares +state.n = n; % number of samples diff --git a/external/fieldtrip/preproc/private/bilinear.m b/external/fieldtrip/preproc/private/bilinear.m new file mode 100644 index 0000000..ca41b31 --- /dev/null +++ b/external/fieldtrip/preproc/private/bilinear.m @@ -0,0 +1,106 @@ +% Copyright (C) 1999 Paul Kienzle +% +% This program is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; If not, see . + +% usage: [Zz, Zp, Zg] = bilinear(Sz, Sp, Sg, T) +% [Zb, Za] = bilinear(Sb, Sa, T) +% +% Transform a s-plane filter specification into a z-plane +% specification. Filters can be specified in either zero-pole-gain or +% transfer function form. The input form does not have to match the +% output form. 1/T is the sampling frequency represented in the z plane. +% +% Note: this differs from the bilinear function in the signal processing +% toolbox, which uses 1/T rather than T. +% +% Theory: Given a piecewise flat filter design, you can transform it +% from the s-plane to the z-plane while maintaining the band edges by +% means of the bilinear transform. This maps the left hand side of the +% s-plane into the interior of the unit circle. The mapping is highly +% non-linear, so you must design your filter with band edges in the +% s-plane positioned at 2/T tan(w*T/2) so that they will be positioned +% at w after the bilinear transform is complete. +% +% The following table summarizes the transformation: +% +% +---------------+-----------------------+----------------------+ +% | Transform | Zero at x | Pole at x | +% | H(S) | H(S) = S-x | H(S)=1/(S-x) | +% +---------------+-----------------------+----------------------+ +% | 2 z-1 | zero: (2+xT)/(2-xT) | zero: -1 | +% | S -> - --- | pole: -1 | pole: (2+xT)/(2-xT) | +% | T z+1 | gain: (2-xT)/T | gain: (2-xT)/T | +% +---------------+-----------------------+----------------------+ +% +% With tedious algebra, you can derive the above formulae yourself by +% substituting the transform for S into H(S)=S-x for a zero at x or +% H(S)=1/(S-x) for a pole at x, and converting the result into the +% form: +% +% H(Z)=g prod(Z-Xi)/prod(Z-Xj) +% +% Please note that a pole and a zero at the same place exactly cancel. +% This is significant since the bilinear transform creates numerous +% extra poles and zeros, most of which cancel. Those which do not +% cancel have a 'fill-in' effect, extending the shorter of the sets to +% have the same number of as the longer of the sets of poles and zeros +% (or at least split the difference in the case of the band pass +% filter). There may be other opportunistic cancellations but I will +% not check for them. +% +% Also note that any pole on the unit circle or beyond will result in +% an unstable filter. Because of cancellation, this will only happen +% if the number of poles is smaller than the number of zeros. The +% analytic design methods all yield more poles than zeros, so this will +% not be a problem. +% +% References: +% +% Proakis & Manolakis (1992). Digital Signal Processing. New York: +% Macmillan Publishing Company. + +% Author: Paul Kienzle + +function [Zz, Zp, Zg] = bilinear(Sz, Sp, Sg, T) + +if nargin==3 + T = Sg; + [Sz, Sp, Sg] = tf2zp(Sz, Sp); +elseif nargin~=4 + usage('[Zz, Zp, Zg]=bilinear(Sz,Sp,Sg,T) or [Zb, Za]=blinear(Sb,Sa,T)'); +end; + +p = length(Sp); +z = length(Sz); +if z > p || p==0 + error('bilinear: must have at least as many poles as zeros in s-plane'); +end + +% ---------------- ------------------------- ------------------------ +% Bilinear zero: (2+xT)/(2-xT) pole: (2+xT)/(2-xT) +% 2 z-1 pole: -1 zero: -1 +% S -> - --- gain: (2-xT)/T gain: (2-xT)/T +% T z+1 +% ---------------- ------------------------- ------------------------ +Zg = real(Sg * prod((2-Sz*T)/T) / prod((2-Sp*T)/T)); +Zp = (2+Sp*T)./(2-Sp*T); +if isempty(Sz) + Zz = -ones(size(Zp)); +else + Zz = [(2+Sz*T)./(2-Sz*T)]; + Zz = postpad(Zz, p, -1); +end + +if nargout==2, [Zz, Zp] = zp2tf(Zz, Zp, Zg); end + diff --git a/external/fieldtrip/preproc/private/butter.m b/external/fieldtrip/preproc/private/butter.m new file mode 100644 index 0000000..b826550 --- /dev/null +++ b/external/fieldtrip/preproc/private/butter.m @@ -0,0 +1,122 @@ +% Copyright (C) 1999 Paul Kienzle +% +% This program is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; If not, see . + +% Generate a butterworth filter. +% Default is a discrete space (Z) filter. +% +% [b,a] = butter(n, Wc) +% low pass filter with cutoff pi*Wc radians +% +% [b,a] = butter(n, Wc, 'high') +% high pass filter with cutoff pi*Wc radians +% +% [b,a] = butter(n, [Wl, Wh]) +% band pass filter with edges pi*Wl and pi*Wh radians +% +% [b,a] = butter(n, [Wl, Wh], 'stop') +% band reject filter with edges pi*Wl and pi*Wh radians +% +% [z,p,g] = butter(...) +% return filter as zero-pole-gain rather than coefficients of the +% numerator and denominator polynomials. +% +% [...] = butter(...,'s') +% return a Laplace space filter, W can be larger than 1. +% +% [a,b,c,d] = butter(...) +% return state-space matrices +% +% References: +% +% Proakis & Manolakis (1992). Digital Signal Processing. New York: +% Macmillan Publishing Company. + +% Author: Paul Kienzle +% Modified by: Doug Stewart Feb, 2003 + +function [a, b, c, d] = butter (n, W, varargin) + +if (nargin>4 || nargin<2) || (nargout>4 || nargout<2) + usage ('[b, a] or [z, p, g] or [a,b,c,d] = butter (n, W [, "ftype"][,"s"])'); +end + +% interpret the input parameters +if (~(length(n)==1 && n == round(n) && n > 0)) + error ('butter: filter order n must be a positive integer'); +end + +stop = 0; +digital = 1; +for i=1:length(varargin) + switch varargin{i} + case 's', digital = 0; + case 'z', digital = 1; + case { 'high', 'stop' }, stop = 1; + case { 'low', 'pass' }, stop = 0; + otherwise, error ('butter: expected [high|stop] or [s|z]'); + end +end + + +[r, c]=size(W); +if (~(length(W)<=2 && (r==1 || c==1))) + error ('butter: frequency must be given as w0 or [w0, w1]'); +elseif (~(length(W)==1 || length(W) == 2)) + error ('butter: only one filter band allowed'); +elseif (length(W)==2 && ~(W(1) < W(2))) + error ('butter: first band edge must be smaller than second'); +end + +if ( digital && ~all(W >= 0 & W <= 1)) + error ('butter: critical frequencies must be in (0 1)'); +elseif ( ~digital && ~all(W >= 0 )) + error ('butter: critical frequencies must be in (0 inf)'); +end + +% Prewarp to the band edges to s plane +if digital + T = 2; % sampling frequency of 2 Hz + W = 2/T*tan(pi*W/T); +end + +% Generate splane poles for the prototype butterworth filter +% source: Kuc +C = 1; % default cutoff frequency +pole = C*exp(1i*pi*(2*[1:n] + n - 1)/(2*n)); +if mod(n,2) == 1, pole((n+1)/2) = -1; end % pure real value at exp(i*pi) +zero = []; +gain = C^n; + +% splane frequency transform +[zero, pole, gain] = sftrans(zero, pole, gain, W, stop); + +% Use bilinear transform to convert poles to the z plane +if digital + [zero, pole, gain] = bilinear(zero, pole, gain, T); +end + +% convert to the correct output form +if nargout==2, + a = real(gain*poly(zero)); + b = real(poly(pole)); +elseif nargout==3, + a = zero; + b = pole; + c = gain; +else + % output ss results + [a, b, c, d] = zp2ss (zero, pole, gain); +end + diff --git a/external/fieldtrip/preproc/private/filtfilt.m b/external/fieldtrip/preproc/private/filtfilt.m new file mode 100644 index 0000000..c282a05 --- /dev/null +++ b/external/fieldtrip/preproc/private/filtfilt.m @@ -0,0 +1,95 @@ +% Copyright (C) 1999 Paul Kienzle +% Copyright (C) 2007 Francesco Potortì +% Copyright (C) 2008 Luca Citi +% +% This program is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; If not, see . + +% usage: y = filtfilt(b, a, x) +% +% Forward and reverse filter the signal. This corrects for phase +% distortion introduced by a one-pass filter, though it does square the +% magnitude response in the process. That's the theory at least. In +% practice the phase correction is not perfect, and magnitude response +% is distorted, particularly in the stop band. +%% +% Example +% [b, a]=butter(3, 0.1); % 10 Hz low-pass filter +% t = 0:0.01:1.0; % 1 second sample +% x=sin(2*pi*t*2.3)+0.25*randn(size(t)); % 2.3 Hz sinusoid+noise +% y = filtfilt(b,a,x); z = filter(b,a,x); % apply filter +% plot(t,x,';data;',t,y,';filtfilt;',t,z,';filter;') + +% Changelog: +% 2000 02 pkienzle@kienzle.powernet.co.uk +% - pad with zeros to load up the state vector on filter reverse. +% - add example +% 2007 12 pot@gnu.org +% - use filtic to compute initial and final states +% - work for multiple columns as well +% 2008 12 lciti@essex.ac.uk +% - fixed instability issues with IIR filters and noisy inputs +% - initial states computed according to Likhterov & Kopeika, 2003 +% - use of a "reflection method" to reduce end effects +% - added some basic tests + +% TODO: (pkienzle) My version seems to have similar quality to matlab, +% but both are pretty bad. They do remove gross lag errors, though. + + +function y = filtfilt(b, a, x) +if (nargin ~= 3) + usage('y=filtfilt(b,a,x)'); +end + +rotate = (size(x, 1)==1); + +if rotate % a row vector + x = x(:); % make it a column vector +end + +lx = size(x,1); +a = a(:).'; +b = b(:).'; +lb = length(b); +la = length(a); +n = max(lb, la); +lrefl = 3 * (n - 1); +if la < n, a(n) = 0; end +if lb < n, b(n) = 0; end + +% Compute a the initial state taking inspiration from +% Likhterov & Kopeika, 2003. "Hardware-efficient technique for +% minimizing startup transients in Direct Form II digital filters" +kdc = sum(b) / sum(a); +if (abs(kdc) < inf) % neither NaN nor +/- Inf + si = fliplr(cumsum(fliplr(b - kdc * a))); +else + si = zeros(size(a)); % fall back to zero initialization +end +si(1) = []; + +for c = 1:size(x, 2) % filter all columns, one by one + v = [2*x(1,c)-x((lrefl+1):-1:2,c); x(:,c); + 2*x(end,c)-x((end-1):-1:end-lrefl,c)]; % a column vector + + % Do forward and reverse filtering + v = filter(b,a,v,si*v(1)); % forward filter + v = flipud(filter(b,a,flipud(v),si*v(end))); % reverse filter + y(:,c) = v((lrefl+1):(lx+lrefl)); +end + +if (rotate) % x was a row vector + y = rot90(y); % rotate it back +end + diff --git a/external/fieldtrip/preproc/private/postpad.m b/external/fieldtrip/preproc/private/postpad.m new file mode 100644 index 0000000..17909de --- /dev/null +++ b/external/fieldtrip/preproc/private/postpad.m @@ -0,0 +1,80 @@ +% Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2002, 2004, 2005, +% 2006, 2007, 2008, 2009 John W. Eaton +% +% This file is part of Octave. +% +% Octave is free software; you can redistribute it and/or modify it +% under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 3 of the License, or (at +% your option) any later version. +% +% Octave is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +% General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with Octave; see the file COPYING. If not, see +% . + +% -*- texinfo -*- +% @deftypefn {Function File} {} postpad (@var{x}, @var{l}, @var{c}) +% @deftypefnx {Function File} {} postpad (@var{x}, @var{l}, @var{c}, @var{dim}) +% @seealso{prepad, resize} +% @end deftypefn + +% Author: Tony Richardson +% Created: June 1994 + +function y = postpad (x, l, c, dim) + +if nargin < 2 || nargin > 4 + %print_usage (); + error('wrong number of input arguments, should be between 2 and 4'); +end + +if nargin < 3 || isempty(c) + c = 0; +else + if ~isscalar(c) + error ('postpad: third argument must be empty or a scalar'); + end +end + +nd = ndims(x); +sz = size(x); +if nargin < 4 + % Find the first non-singleton dimension + dim = 1; + while dim < nd+1 && sz(dim)==1 + dim = dim + 1; + end + if dim > nd + dim = 1; + elseif ~(isscalar(dim) && dim == round(dim)) && dim > 0 && dim< nd+1 + error('postpad: dim must be an integer and valid dimension'); + end +end + +if ~isscalar(l) || l<0 + error ('second argument must be a positive scalar'); +end + +if dim > nd + sz(nd+1:dim) = 1; +end + +d = sz(dim); + +if d >= l + idx = cell(1,nd); + for i = 1:nd + idx{i} = 1:sz(i); + end + idx{dim} = 1:l; + y = x(idx{:}); +else + sz(dim) = l-d; + y = cat(dim, x, c * ones(sz)); +end + diff --git a/external/fieldtrip/preproc/private/sftrans.m b/external/fieldtrip/preproc/private/sftrans.m new file mode 100644 index 0000000..428a7cc --- /dev/null +++ b/external/fieldtrip/preproc/private/sftrans.m @@ -0,0 +1,192 @@ +% Copyright (C) 1999 Paul Kienzle +% +% This program is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; If not, see . + +% usage: [Sz, Sp, Sg] = sftrans(Sz, Sp, Sg, W, stop) +% +% Transform band edges of a generic lowpass filter (cutoff at W=1) +% represented in splane zero-pole-gain form. W is the edge of the +% target filter (or edges if band pass or band stop). Stop is true for +% high pass and band stop filters or false for low pass and band pass +% filters. Filter edges are specified in radians, from 0 to pi (the +% nyquist frequency). +% +% Theory: Given a low pass filter represented by poles and zeros in the +% splane, you can convert it to a low pass, high pass, band pass or +% band stop by transforming each of the poles and zeros individually. +% The following table summarizes the transformation: +% +% Transform Zero at x Pole at x +% ---------------- ------------------------- ------------------------ +% Low Pass zero: Fc x/C pole: Fc x/C +% S -> C S/Fc gain: C/Fc gain: Fc/C +% ---------------- ------------------------- ------------------------ +% High Pass zero: Fc C/x pole: Fc C/x +% S -> C Fc/S pole: 0 zero: 0 +% gain: -x gain: -1/x +% ---------------- ------------------------- ------------------------ +% Band Pass zero: b ? sqrt(b^2-FhFl) pole: b ? sqrt(b^2-FhFl) +% S^2+FhFl pole: 0 zero: 0 +% S -> C -------- gain: C/(Fh-Fl) gain: (Fh-Fl)/C +% S(Fh-Fl) b=x/C (Fh-Fl)/2 b=x/C (Fh-Fl)/2 +% ---------------- ------------------------- ------------------------ +% Band Stop zero: b ? sqrt(b^2-FhFl) pole: b ? sqrt(b^2-FhFl) +% S(Fh-Fl) pole: ?sqrt(-FhFl) zero: ?sqrt(-FhFl) +% S -> C -------- gain: -x gain: -1/x +% S^2+FhFl b=C/x (Fh-Fl)/2 b=C/x (Fh-Fl)/2 +% ---------------- ------------------------- ------------------------ +% Bilinear zero: (2+xT)/(2-xT) pole: (2+xT)/(2-xT) +% 2 z-1 pole: -1 zero: -1 +% S -> - --- gain: (2-xT)/T gain: (2-xT)/T +% T z+1 +% ---------------- ------------------------- ------------------------ +% +% where C is the cutoff frequency of the initial lowpass filter, Fc is +% the edge of the target low/high pass filter and [Fl,Fh] are the edges +% of the target band pass/stop filter. With abundant tedious algebra, +% you can derive the above formulae yourself by substituting the +% transform for S into H(S)=S-x for a zero at x or H(S)=1/(S-x) for a +% pole at x, and converting the result into the form: +% +% H(S)=g prod(S-Xi)/prod(S-Xj) +% +% The transforms are from the references. The actual pole-zero-gain +% changes I derived myself. +% +% Please note that a pole and a zero at the same place exactly cancel. +% This is significant for High Pass, Band Pass and Band Stop filters +% which create numerous extra poles and zeros, most of which cancel. +% Those which do not cancel have a 'fill-in' effect, extending the +% shorter of the sets to have the same number of as the longer of the +% sets of poles and zeros (or at least split the difference in the case +% of the band pass filter). There may be other opportunistic +% cancellations but I will not check for them. +% +% Also note that any pole on the unit circle or beyond will result in +% an unstable filter. Because of cancellation, this will only happen +% if the number of poles is smaller than the number of zeros and the +% filter is high pass or band pass. The analytic design methods all +% yield more poles than zeros, so this will not be a problem. +% +% References: +% +% Proakis & Manolakis (1992). Digital Signal Processing. New York: +% Macmillan Publishing Company. + +% Author: Paul Kienzle + +% 2000-03-01 pkienzle@kienzle.powernet.co.uk +% leave transformed Sg as a complex value since cheby2 blows up +% otherwise (but only for odd-order low-pass filters). bilinear +% will return Zg as real, so there is no visible change to the +% user of the IIR filter design functions. +% 2001-03-09 pkienzle@kienzle.powernet.co.uk +% return real Sg; don't know what to do for imaginary filters +function [Sz, Sp, Sg] = sftrans(Sz, Sp, Sg, W, stop) + +if (nargin ~= 5) + usage('[Sz, Sp, Sg] = sftrans(Sz, Sp, Sg, W, stop)'); +end; + +C = 1; +p = length(Sp); +z = length(Sz); +if z > p || p == 0 + error('sftrans: must have at least as many poles as zeros in s-plane'); +end + +if length(W)==2 + Fl = W(1); + Fh = W(2); + if stop + % ---------------- ------------------------- ------------------------ + % Band Stop zero: b ? sqrt(b^2-FhFl) pole: b ? sqrt(b^2-FhFl) + % S(Fh-Fl) pole: ?sqrt(-FhFl) zero: ?sqrt(-FhFl) + % S -> C -------- gain: -x gain: -1/x + % S^2+FhFl b=C/x (Fh-Fl)/2 b=C/x (Fh-Fl)/2 + % ---------------- ------------------------- ------------------------ + if (isempty(Sz)) + Sg = Sg * real (1./ prod(-Sp)); + elseif (isempty(Sp)) + Sg = Sg * real(prod(-Sz)); + else + Sg = Sg * real(prod(-Sz)/prod(-Sp)); + end + b = (C*(Fh-Fl)/2)./Sp; + Sp = [b+sqrt(b.^2-Fh*Fl), b-sqrt(b.^2-Fh*Fl)]; + extend = [sqrt(-Fh*Fl), -sqrt(-Fh*Fl)]; + if isempty(Sz) + Sz = [extend(1+rem([1:2*p],2))]; + else + b = (C*(Fh-Fl)/2)./Sz; + Sz = [b+sqrt(b.^2-Fh*Fl), b-sqrt(b.^2-Fh*Fl)]; + if (p > z) + Sz = [Sz, extend(1+rem([1:2*(p-z)],2))]; + end + end + else + + % ---------------- ------------------------- ------------------------ + % Band Pass zero: b ? sqrt(b^2-FhFl) pole: b ? sqrt(b^2-FhFl) + % S^2+FhFl pole: 0 zero: 0 + % S -> C -------- gain: C/(Fh-Fl) gain: (Fh-Fl)/C + % S(Fh-Fl) b=x/C (Fh-Fl)/2 b=x/C (Fh-Fl)/2 + % ---------------- ------------------------- ------------------------ + Sg = Sg * (C/(Fh-Fl))^(z-p); + b = Sp*((Fh-Fl)/(2*C)); + Sp = [b+sqrt(b.^2-Fh*Fl), b-sqrt(b.^2-Fh*Fl)]; + if isempty(Sz) + Sz = zeros(1,p); + else + b = Sz*((Fh-Fl)/(2*C)); + Sz = [b+sqrt(b.^2-Fh*Fl), b-sqrt(b.^2-Fh*Fl)]; + if (p>z) + Sz = [Sz, zeros(1, (p-z))]; + end + end + end +else + Fc = W; + if stop + % ---------------- ------------------------- ------------------------ + % High Pass zero: Fc C/x pole: Fc C/x + % S -> C Fc/S pole: 0 zero: 0 + % gain: -x gain: -1/x + % ---------------- ------------------------- ------------------------ + if (isempty(Sz)) + Sg = Sg * real (1./ prod(-Sp)); + elseif (isempty(Sp)) + Sg = Sg * real(prod(-Sz)); + else + Sg = Sg * real(prod(-Sz)/prod(-Sp)); + end + Sp = C * Fc ./ Sp; + if isempty(Sz) + Sz = zeros(1,p); + else + Sz = [C * Fc ./ Sz]; + if (p > z) + Sz = [Sz, zeros(1,p-z)]; + end + end + else + % ---------------- ------------------------- ------------------------ + % Low Pass zero: Fc x/C pole: Fc x/C + % S -> C S/Fc gain: C/Fc gain: Fc/C + % ---------------- ------------------------- ------------------------ + Sg = Sg * (C/Fc)^(z-p); + Sp = Fc * Sp / C; + Sz = Fc * Sz / C; + end +end diff --git a/external/fieldtrip/private/4D248.lay b/external/fieldtrip/private/4D248.lay deleted file mode 100644 index d3171cf..0000000 --- a/external/fieldtrip/private/4D248.lay +++ /dev/null @@ -1,248 +0,0 @@ -1 0.23057 -0.26062 3 2.25 A1 -2 0.23057 3.8119 3 2.25 A2 -3 0.064345 8.2238 3 2.25 A3 -4 0.064345 11.957 3 2.25 A4 -5 -0.10188 16.0295 3 2.25 A5 -6 -3.7588 16.0295 3 2.25 A6 -7 -4.0913 11.957 3 2.25 A7 -8 -4.2575 8.2238 3 2.25 A8 -9 -4.0913 4.1513 3 2.25 A9 -10 -4.2575 -0.09093 3 2.25 A10 -11 -3.9251 -3.8241 3 2.25 A11 -12 0.064345 -4.1635 3 2.25 A12 -13 3.8875 -3.8241 3 2.25 A13 -14 4.0538 -0.09093 3 2.25 A14 -15 4.22 3.9816 3 2.25 A15 -16 4.0538 8.2238 3 2.25 A16 -17 4.0538 11.957 3 2.25 A17 -18 3.7213 16.0295 3 2.25 A18 -19 -0.10188 19.9323 3 2.25 A19 -20 -4.9224 19.7627 3 2.25 A20 -21 -7.7483 16.878 3 2.25 A21 -22 -8.0807 12.1267 3 2.25 A22 -23 -8.4132 8.3935 3 2.25 A23 -24 -8.5794 3.9816 3 2.25 A24 -25 -8.2469 0.078759 3 2.25 A25 -26 -7.9145 -4.5028 3 2.25 A26 -27 -4.59 -8.0663 3 2.25 A27 -28 0.064345 -8.4057 3 2.25 A28 -29 4.3862 -8.0663 3 2.25 A29 -30 7.7107 -4.6725 3 2.25 A30 -31 8.0432 -0.26062 3 2.25 A31 -32 8.5419 4.1513 3 2.25 A32 -33 8.2094 8.3935 3 2.25 A33 -34 8.3756 12.1267 3 2.25 A34 -35 7.877 16.7083 3 2.25 A35 -36 4.7187 19.7627 3 2.25 A36 -37 0.064345 24.1746 3 2.25 A37 -38 -4.4238 23.8352 3 2.25 A38 -39 -8.4132 20.9505 3 2.25 A39 -40 -11.7377 17.5567 3 2.25 A40 -41 -12.4026 13.1448 3 2.25 A41 -42 -12.735 9.0723 3 2.25 A42 -43 -12.9013 4.83 3 2.25 A43 -44 -12.4026 0.9272 3 2.25 A44 -45 -12.0701 -3.1453 3 2.25 A45 -46 -10.9066 -7.3878 3 2.25 A46 -47 -7.9145 -10.2723 3 2.25 A47 -48 -4.2575 -12.1388 3 2.25 A48 -49 -0.10188 -12.9873 3 2.25 A49 -50 3.8875 -11.9691 3 2.25 A50 -51 7.7107 -10.4419 3 2.25 A51 -52 10.7028 -7.3875 3 2.25 A52 -53 12.1988 -3.1453 3 2.25 A53 -54 12.5313 0.9272 3 2.25 A54 -55 12.5313 5.1694 3 2.25 A55 -56 12.5313 9.0723 3 2.25 A56 -57 12.1988 13.3145 3 2.25 A57 -58 11.3677 17.5567 3 2.25 A58 -59 8.3756 21.1202 3 2.25 A59 -60 4.5524 23.8352 3 2.25 A60 -61 -0.10188 27.9077 3 2.25 A61 -62 -4.59 27.5683 3 2.25 A62 -63 -9.0781 25.5321 3 2.25 A63 -64 -12.5688 22.4777 3 2.25 A64 -65 -15.2284 18.4051 3 2.25 A65 -66 -16.392 13.4842 3 2.25 A66 -67 -16.8907 9.0723 3 2.25 A67 -68 -17.0569 4.6604 3 2.25 A68 -69 -16.5582 -0.09093 3 2.25 A69 -70 -16.0596 -4.5028 3 2.25 A70 -71 -14.3973 -8.7451 3 2.25 A71 -72 -11.5715 -11.9691 3 2.25 A72 -73 -8.4132 -14.5145 3 2.25 A73 -74 -4.59 -16.3811 3 2.25 A74 -75 0.23057 -16.8901 3 2.25 A75 -76 4.3862 -16.2114 3 2.25 A76 -77 8.2094 -14.6842 3 2.25 A77 -78 11.7001 -12.1388 3 2.25 A78 -79 14.1935 -8.4057 3 2.25 A79 -80 15.6896 -4.6725 3 2.25 A80 -81 16.1882 -0.26062 3 2.25 A81 -82 16.6869 4.4907 3 2.25 A82 -83 16.5207 9.0723 3 2.25 A83 -84 16.022 13.1448 3 2.25 A84 -85 15.1909 18.557 3 2.25 A85 -86 12.6975 22.308 3 2.25 A86 -87 8.8743 25.5321 3 2.25 A87 -88 4.8849 28.0774 3 2.25 A88 -89 0.064345 32.1499 3 2.25 A89 -90 -4.7562 31.4712 3 2.25 A90 -91 -9.4105 29.944 3 2.25 A91 -92 -13.2337 27.0593 3 2.25 A92 -93 -16.392 23.8352 3 2.25 A93 -94 -18.8854 19.2536 3 2.25 A94 -95 -19.7165 14.1629 3 2.25 A95 -96 -20.049 10.0904 3 2.25 A96 -97 -20.5476 4.83 3 2.25 A97 -98 -20.2152 0.078759 3 2.25 A98 -99 -19.7165 -4.5028 3 2.25 A99 -100 -18.2205 -9.0844 3 2.25 A100 -101 -15.7271 -12.9873 3 2.25 A101 -102 -12.5688 -16.2114 3 2.25 A102 -103 -8.7456 -18.7567 3 2.25 A103 -104 -4.4238 -20.2839 3 2.25 A104 -105 0.23057 -20.793 3 2.25 A105 -106 4.7187 -20.2839 3 2.25 A106 -107 8.8743 -18.7567 3 2.25 A107 -108 12.8637 -16.3811 3 2.25 A108 -109 16.022 -12.8176 3 2.25 A109 -110 18.183 -9.0844 3 2.25 A110 -111 19.8452 -4.5028 3 2.25 A111 -112 20.5101 0.078759 3 2.25 A112 -113 20.5101 4.9997 3 2.25 A113 -114 20.0114 9.751 3 2.25 A114 -115 19.8452 14.3326 3 2.25 A115 -116 18.8479 19.4233 3 2.25 A116 -117 16.5207 23.4958 3 2.25 A117 -118 13.3624 27.0593 3 2.25 A118 -119 9.5392 29.7743 3 2.25 A119 -120 5.0511 31.6409 3 2.25 A120 -121 0.064345 35.7134 3 2.25 A121 -122 -5.0887 35.0347 3 2.25 A122 -123 -10.2417 32.9984 3 2.25 A123 -124 -14.896 30.1137 3 2.25 A124 -125 -18.5529 26.0411 3 2.25 A125 -126 -21.3788 21.2899 3 2.25 A126 -127 -22.8748 15.3508 3 2.25 A127 -128 -23.5397 10.9388 3 2.25 A128 -129 -24.0384 5.3391 3 2.25 A129 -130 -23.7059 -0.09093 3 2.25 A130 -131 -23.3735 -5.3513 3 2.25 A131 -132 -21.545 -10.7813 3 2.25 A132 -133 -18.3867 -15.3629 3 2.25 A133 -134 -14.5635 -19.0961 3 2.25 A134 -135 -10.5741 -21.8111 3 2.25 A135 -136 -5.2549 -23.6777 3 2.25 A136 -137 -0.10188 -24.3564 3 2.25 A137 -138 5.3836 -23.8474 3 2.25 A138 -139 10.5366 -22.1505 3 2.25 A139 -140 14.8584 -19.0961 3 2.25 A140 -141 18.6816 -15.1932 3 2.25 A141 -142 21.175 -10.6116 3 2.25 A142 -143 23.1697 -5.3513 3 2.25 A143 -144 24.0009 -0.09093 3 2.25 A144 -145 24.1671 5.5088 3 2.25 A145 -146 23.6684 10.9388 3 2.25 A146 -147 23.0035 15.5204 3 2.25 A147 -148 21.175 21.1202 3 2.25 A148 -149 18.6816 26.0411 3 2.25 A149 -150 15.0247 29.944 3 2.25 A150 -151 10.5366 32.9984 3 2.25 A151 -152 5.716 35.0347 3 2.25 A152 -153 -21.545 26.8896 3 2.25 A153 -154 -23.8722 22.1383 3 2.25 A154 -155 -25.3682 17.0476 3 2.25 A155 -156 -28.3603 10.4298 3 2.25 A156 -157 -29.1914 4.321 3 2.25 A157 -158 -29.5238 -1.4484 3 2.25 A158 -159 -24.8695 -8.7451 3 2.25 A159 -160 -22.5424 -14.0054 3 2.25 A160 -161 -18.8854 -18.9264 3 2.25 A161 -162 -14.2311 -22.6595 3 2.25 A162 -163 -8.4132 -25.5442 3 2.25 A163 -164 -3.0939 -26.7321 3 2.25 A164 -165 3.2226 -26.9018 3 2.25 A165 -166 8.7081 -25.5442 3 2.25 A166 -167 14.1935 -22.9989 3 2.25 A167 -168 18.6816 -18.9264 3 2.25 A168 -169 22.671 -14.1751 3 2.25 A169 -170 24.832 -8.7451 3 2.25 A170 -171 29.4863 -1.6181 3 2.25 A171 -172 28.8214 4.321 3 2.25 A172 -173 28.489 10.0904 3 2.25 A173 -174 25.6631 17.0476 3 2.25 A174 -175 24.0009 22.4777 3 2.25 A175 -176 21.6737 26.8896 3 2.25 A176 -177 -25.202 28.0774 3 2.25 A177 -178 -27.5291 22.8171 3 2.25 A178 -179 -28.5265 17.7264 3 2.25 A179 -180 -31.851 -6.3694 3 2.25 A180 -181 -25.8669 -12.6479 3 2.25 A181 -182 -22.7086 -18.2476 3 2.25 A182 -183 -18.0543 -22.6595 3 2.25 A183 -184 -12.735 -26.3927 3 2.25 A184 -185 -6.2522 -28.938 3 2.25 A185 -186 0.064345 -29.7865 3 2.25 A186 -187 6.7134 -28.7683 3 2.25 A187 -188 12.8637 -26.3927 3 2.25 A188 -189 18.183 -22.8292 3 2.25 A189 -190 22.671 -18.0779 3 2.25 A190 -191 25.9956 -12.4782 3 2.25 A191 -192 31.6472 -6.7088 3 2.25 A192 -193 28.489 18.9142 3 2.25 A193 -194 27.1591 23.6655 3 2.25 A194 -195 24.832 28.4168 3 2.25 A195 -196 -32.5159 11.6176 3 2.25 A196 -197 -33.5133 4.9997 3 2.25 A197 -198 -34.0119 -1.9575 3 2.25 A198 -199 -26.698 -16.7204 3 2.25 A199 -200 -22.7086 -22.4899 3 2.25 A200 -201 -17.3894 -27.4108 3 2.25 A201 -202 -10.4079 -30.6349 3 2.25 A202 -203 -3.7588 -31.653 3 2.25 A203 -204 3.3889 -32.3318 3 2.25 A204 -205 10.7028 -30.1258 3 2.25 A205 -206 17.0194 -27.0714 3 2.25 A206 -207 22.5048 -22.4899 3 2.25 A207 -208 26.8267 -16.8901 3 2.25 A208 -209 34.3069 -1.7878 3 2.25 A209 -210 33.642 5.3391 3 2.25 A210 -211 32.6446 11.957 3 2.25 A211 -212 -29.6901 27.738 3 2.25 A212 -213 -31.5185 20.7808 3 2.25 A213 -214 -36.3391 -7.2179 3 2.25 A214 -215 -31.3523 -14.8539 3 2.25 A215 -216 -27.1967 -21.8111 3 2.25 A216 -217 -22.2099 -27.7502 3 2.25 A217 -218 -15.7271 -31.653 3 2.25 A218 -219 -8.0807 -34.5378 3 2.25 A219 -220 -0.10188 -35.8953 3 2.25 A220 -221 7.7107 -35.0468 3 2.25 A221 -222 15.1909 -31.653 3 2.25 A222 -223 22.1724 -27.5805 3 2.25 A223 -224 27.4916 -21.6414 3 2.25 A224 -225 31.8135 -15.3629 3 2.25 A225 -226 36.9665 -7.7269 3 2.25 A226 -227 31.6472 20.9505 3 2.25 A227 -228 29.6525 27.229 3 2.25 A228 -229 -34.0119 26.8896 3 2.25 A229 -230 -35.8404 20.102 3 2.25 A230 -231 -38.3338 13.8236 3 2.25 A231 -232 -39.3312 5.8482 3 2.25 A232 -233 -39.8298 -2.1272 3 2.25 A233 -234 -33.0146 -20.6233 3 2.25 A234 -235 -27.6954 -27.2411 3 2.25 A235 -236 -21.2126 -33.3499 3 2.25 A236 -237 -13.3999 -36.4043 3 2.25 A237 -238 -4.2575 -40.1375 3 2.25 A238 -239 4.3862 -39.4587 3 2.25 A239 -240 13.03 -37.2528 3 2.25 A240 -241 20.8426 -33.5196 3 2.25 A241 -242 27.3254 -27.9199 3 2.25 A242 -243 33.3095 -20.6233 3 2.25 A243 -244 39.6261 -1.9575 3 2.25 A244 -245 39.2936 5.8482 3 2.25 A245 -246 38.13 14.1629 3 2.25 A246 -247 35.8029 20.6111 3 2.25 A247 -248 34.3069 26.8896 3 2.25 A248 diff --git a/external/fieldtrip/private/CTF151.lay b/external/fieldtrip/private/CTF151.lay deleted file mode 100644 index c9d68f3..0000000 --- a/external/fieldtrip/private/CTF151.lay +++ /dev/null @@ -1,153 +0,0 @@ -1 -0.440000 -4.000000 0.551100 0.351100 MLC11 -2 -1.200000 -4.130000 0.551100 0.351100 MLC12 -3 -2.220000 -4.270000 0.551100 0.351100 MLC13 -4 -2.820000 -4.710000 0.551100 0.351100 MLC14 -5 -3.340000 -5.230000 0.551100 0.351100 MLC15 -6 -0.820000 -4.550000 0.551100 0.351100 MLC21 -7 -1.620000 -4.570000 0.551100 0.351100 MLC22 -8 -2.160000 -4.970000 0.551100 0.351100 MLC23 -9 -2.640000 -5.370000 0.551100 0.351100 MLC24 -10 -1.270000 -5.050000 0.551100 0.351100 MLC31 -11 -1.780000 -5.450000 0.551100 0.351100 MLC32 -12 -1.300000 -5.930000 0.551100 0.351100 MLC33 -13 -0.440000 -5.050000 0.551100 0.351100 MLC41 -14 -0.820000 -5.530000 0.551100 0.351100 MLC42 -15 -0.400000 -6.010000 0.551100 0.351100 MLC43 -16 -1.170000 -2.010000 0.551100 0.351100 MLF11 -17 -2.260000 -2.230000 0.551100 0.351100 MLF12 -18 -0.490000 -2.300000 0.551100 0.351100 MLF21 -19 -1.540000 -2.470000 0.551100 0.351100 MLF22 -20 -2.540000 -2.750000 0.551100 0.351100 MLF23 -21 -1.000000 -2.750000 0.551100 0.351100 MLF31 -22 -1.950000 -2.980000 0.551100 0.351100 MLF32 -23 -2.780000 -3.300000 0.551100 0.351100 MLF33 -24 -3.440000 -3.770000 0.551100 0.351100 MLF34 -25 -0.450000 -3.100000 0.551100 0.351100 MLF41 -26 -1.380000 -3.260000 0.551100 0.351100 MLF42 -27 -2.280000 -3.570000 0.551100 0.351100 MLF43 -28 -2.870000 -4.060000 0.551100 0.351100 MLF44 -29 -3.500000 -4.510000 0.551100 0.351100 MLF45 -30 -0.850000 -3.580000 0.551100 0.351100 MLF51 -31 -1.700000 -3.790000 0.551100 0.351100 MLF52 -32 -0.470000 -7.690000 0.551100 0.351100 MLO11 -33 -1.650000 -7.420000 0.551100 0.351100 MLO12 -34 -1.210000 -7.930000 0.551100 0.351100 MLO21 -35 -2.350000 -7.580000 0.551100 0.351100 MLO22 -36 -0.600000 -8.400000 0.551100 0.351100 MLO31 -37 -1.920000 -8.120000 0.551100 0.351100 MLO32 -38 -3.110000 -7.670000 0.551100 0.351100 MLO33 -39 -1.400000 -8.560000 0.551100 0.351100 MLO41 -40 -2.750000 -8.210000 0.551100 0.351100 MLO42 -41 -3.910000 -7.620000 0.551100 0.351100 MLO43 -42 -0.840000 -6.390000 0.551100 0.351100 MLP11 -43 -1.710000 -6.320000 0.551100 0.351100 MLP12 -44 -2.240000 -5.870000 0.551100 0.351100 MLP13 -45 -0.440000 -6.900000 0.551100 0.351100 MLP21 -46 -1.220000 -6.760000 0.551100 0.351100 MLP22 -47 -0.970000 -7.220000 0.551100 0.351100 MLP31 -48 -1.900000 -6.880000 0.551100 0.351100 MLP32 -49 -2.470000 -6.390000 0.551100 0.351100 MLP33 -50 -2.990000 -5.850000 0.551100 0.351100 MLP34 -51 -3.420000 -3.120000 0.551100 0.351100 MLT11 -52 -4.100000 -4.200000 0.551100 0.351100 MLT12 -53 -4.040000 -5.030000 0.551100 0.351100 MLT13 -54 -3.780000 -5.770000 0.551100 0.351100 MLT14 -55 -3.210000 -6.440000 0.551100 0.351100 MLT15 -56 -2.570000 -7.010000 0.551100 0.351100 MLT16 -57 -3.320000 -2.550000 0.551100 0.351100 MLT21 -58 -4.260000 -3.520000 0.551100 0.351100 MLT22 -59 -4.720000 -4.710000 0.551100 0.351100 MLT23 -60 -4.520000 -5.590000 0.551100 0.351100 MLT24 -61 -4.040000 -6.350000 0.551100 0.351100 MLT25 -62 -3.280000 -7.060000 0.551100 0.351100 MLT26 -63 -4.340000 -2.900000 0.551100 0.351100 MLT31 -64 -5.040000 -4.050000 0.551100 0.351100 MLT32 -65 -5.200000 -5.210000 0.551100 0.351100 MLT33 -66 -4.820000 -6.140000 0.551100 0.351100 MLT34 -67 -4.090000 -7.000000 0.551100 0.351100 MLT35 -68 -5.210000 -3.450000 0.551100 0.351100 MLT41 -69 -5.640000 -4.620000 0.551100 0.351100 MLT42 -70 -5.500000 -5.730000 0.551100 0.351100 MLT43 -71 -4.910000 -6.720000 0.551100 0.351100 MLT44 -72 0.410000 -4.000000 0.551100 0.351100 MRC11 -73 1.170000 -4.130000 0.551100 0.351100 MRC12 -74 2.200000 -4.270000 0.551100 0.351100 MRC13 -75 2.800000 -4.710000 0.551100 0.351100 MRC14 -76 3.320000 -5.230000 0.551100 0.351100 MRC15 -77 0.800000 -4.560000 0.551100 0.351100 MRC21 -78 1.600000 -4.570000 0.551100 0.351100 MRC22 -79 2.140000 -4.970000 0.551100 0.351100 MRC23 -80 2.620000 -5.370000 0.551100 0.351100 MRC24 -81 1.260000 -5.050000 0.551100 0.351100 MRC31 -82 1.760000 -5.450000 0.551100 0.351100 MRC32 -83 1.280000 -5.930000 0.551100 0.351100 MRC33 -84 0.420000 -5.050000 0.551100 0.351100 MRC41 -85 0.810000 -5.540000 0.551100 0.351100 MRC42 -86 0.380000 -6.010000 0.551100 0.351100 MRC43 -87 1.130000 -2.010000 0.551100 0.351100 MRF11 -88 2.240000 -2.230000 0.551100 0.351100 MRF12 -89 0.460000 -2.290000 0.551100 0.351100 MRF21 -90 1.510000 -2.470000 0.551100 0.351100 MRF22 -91 2.520000 -2.740000 0.551100 0.351100 MRF23 -92 0.970000 -2.740000 0.551100 0.351100 MRF31 -93 1.920000 -2.980000 0.551100 0.351100 MRF32 -94 2.760000 -3.300000 0.551100 0.351100 MRF33 -95 3.420000 -3.770000 0.551100 0.351100 MRF34 -96 0.420000 -3.100000 0.551100 0.351100 MRF41 -97 1.360000 -3.260000 0.551100 0.351100 MRF42 -98 2.260000 -3.570000 0.551100 0.351100 MRF43 -99 2.840000 -4.050000 0.551100 0.351100 MRF44 -100 3.480000 -4.510000 0.551100 0.351100 MRF45 -101 0.820000 -3.580000 0.551100 0.351100 MRF51 -102 1.670000 -3.790000 0.551100 0.351100 MRF52 -103 0.470000 -7.690000 0.551100 0.351100 MRO11 -104 1.640000 -7.420000 0.551100 0.351100 MRO12 -105 1.200000 -7.930000 0.551100 0.351100 MRO21 -106 2.350000 -7.580000 0.551100 0.351100 MRO22 -107 0.580000 -8.390000 0.551100 0.351100 MRO31 -108 1.910000 -8.110000 0.551100 0.351100 MRO32 -109 3.110000 -7.670000 0.551100 0.351100 MRO33 -110 1.380000 -8.570000 0.551100 0.351100 MRO41 -111 2.750000 -8.220000 0.551100 0.351100 MRO42 -112 3.900000 -7.610000 0.551100 0.351100 MRO43 -113 0.820000 -6.380000 0.551100 0.351100 MRP11 -114 1.700000 -6.320000 0.551100 0.351100 MRP12 -115 2.220000 -5.870000 0.551100 0.351100 MRP13 -116 0.420000 -6.900000 0.551100 0.351100 MRP21 -117 1.200000 -6.750000 0.551100 0.351100 MRP22 -118 0.960000 -7.220000 0.551100 0.351100 MRP31 -119 1.880000 -6.870000 0.551100 0.351100 MRP32 -120 2.470000 -6.390000 0.551100 0.351100 MRP33 -121 2.990000 -5.850000 0.551100 0.351100 MRP34 -122 3.390000 -3.120000 0.551100 0.351100 MRT11 -123 4.070000 -4.190000 0.551100 0.351100 MRT12 -124 4.020000 -5.030000 0.551100 0.351100 MRT13 -125 3.760000 -5.770000 0.551100 0.351100 MRT14 -126 3.200000 -6.430000 0.551100 0.351100 MRT15 -127 2.570000 -7.010000 0.551100 0.351100 MRT16 -128 3.300000 -2.540000 0.551100 0.351100 MRT21 -129 4.230000 -3.510000 0.551100 0.351100 MRT22 -130 4.700000 -4.710000 0.551100 0.351100 MRT23 -131 4.500000 -5.590000 0.551100 0.351100 MRT24 -132 4.020000 -6.360000 0.551100 0.351100 MRT25 -133 3.260000 -7.060000 0.551100 0.351100 MRT26 -134 4.310000 -2.900000 0.551100 0.351100 MRT31 -135 5.020000 -4.050000 0.551100 0.351100 MRT32 -136 5.180000 -5.210000 0.551100 0.351100 MRT33 -137 4.800000 -6.140000 0.551100 0.351100 MRT34 -138 4.080000 -7.000000 0.551100 0.351100 MRT35 -139 5.200000 -3.450000 0.551100 0.351100 MRT41 -140 5.620000 -4.610000 0.551100 0.351100 MRT42 -141 5.480000 -5.730000 0.551100 0.351100 MRT43 -142 4.900000 -6.710000 0.551100 0.351100 MRT44 -143 0.000000 -4.510000 0.551100 0.351100 MZC01 -144 0.000000 -5.550000 0.551100 0.351100 MZC02 -145 0.000000 -1.930000 0.551100 0.351100 MZF01 -146 0.000000 -2.660000 0.551100 0.351100 MZF02 -147 0.000000 -3.510000 0.551100 0.351100 MZF03 -148 0.000000 -8.050000 0.551100 0.351100 MZO01 -149 0.000000 -8.660000 0.551100 0.351100 MZO02 -150 0.000000 -6.470000 0.551100 0.351100 MZP01 -151 0.000000 -7.290000 0.551100 0.351100 MZP02 -152 5.000000 -2.000000 0.551100 0.351100 SCALE -153 -5.50000 -1.500000 0.551100 0.351100 COMNT diff --git a/external/fieldtrip/private/CTF151s.lay b/external/fieldtrip/private/CTF151s.lay deleted file mode 100644 index c9d68f3..0000000 --- a/external/fieldtrip/private/CTF151s.lay +++ /dev/null @@ -1,153 +0,0 @@ -1 -0.440000 -4.000000 0.551100 0.351100 MLC11 -2 -1.200000 -4.130000 0.551100 0.351100 MLC12 -3 -2.220000 -4.270000 0.551100 0.351100 MLC13 -4 -2.820000 -4.710000 0.551100 0.351100 MLC14 -5 -3.340000 -5.230000 0.551100 0.351100 MLC15 -6 -0.820000 -4.550000 0.551100 0.351100 MLC21 -7 -1.620000 -4.570000 0.551100 0.351100 MLC22 -8 -2.160000 -4.970000 0.551100 0.351100 MLC23 -9 -2.640000 -5.370000 0.551100 0.351100 MLC24 -10 -1.270000 -5.050000 0.551100 0.351100 MLC31 -11 -1.780000 -5.450000 0.551100 0.351100 MLC32 -12 -1.300000 -5.930000 0.551100 0.351100 MLC33 -13 -0.440000 -5.050000 0.551100 0.351100 MLC41 -14 -0.820000 -5.530000 0.551100 0.351100 MLC42 -15 -0.400000 -6.010000 0.551100 0.351100 MLC43 -16 -1.170000 -2.010000 0.551100 0.351100 MLF11 -17 -2.260000 -2.230000 0.551100 0.351100 MLF12 -18 -0.490000 -2.300000 0.551100 0.351100 MLF21 -19 -1.540000 -2.470000 0.551100 0.351100 MLF22 -20 -2.540000 -2.750000 0.551100 0.351100 MLF23 -21 -1.000000 -2.750000 0.551100 0.351100 MLF31 -22 -1.950000 -2.980000 0.551100 0.351100 MLF32 -23 -2.780000 -3.300000 0.551100 0.351100 MLF33 -24 -3.440000 -3.770000 0.551100 0.351100 MLF34 -25 -0.450000 -3.100000 0.551100 0.351100 MLF41 -26 -1.380000 -3.260000 0.551100 0.351100 MLF42 -27 -2.280000 -3.570000 0.551100 0.351100 MLF43 -28 -2.870000 -4.060000 0.551100 0.351100 MLF44 -29 -3.500000 -4.510000 0.551100 0.351100 MLF45 -30 -0.850000 -3.580000 0.551100 0.351100 MLF51 -31 -1.700000 -3.790000 0.551100 0.351100 MLF52 -32 -0.470000 -7.690000 0.551100 0.351100 MLO11 -33 -1.650000 -7.420000 0.551100 0.351100 MLO12 -34 -1.210000 -7.930000 0.551100 0.351100 MLO21 -35 -2.350000 -7.580000 0.551100 0.351100 MLO22 -36 -0.600000 -8.400000 0.551100 0.351100 MLO31 -37 -1.920000 -8.120000 0.551100 0.351100 MLO32 -38 -3.110000 -7.670000 0.551100 0.351100 MLO33 -39 -1.400000 -8.560000 0.551100 0.351100 MLO41 -40 -2.750000 -8.210000 0.551100 0.351100 MLO42 -41 -3.910000 -7.620000 0.551100 0.351100 MLO43 -42 -0.840000 -6.390000 0.551100 0.351100 MLP11 -43 -1.710000 -6.320000 0.551100 0.351100 MLP12 -44 -2.240000 -5.870000 0.551100 0.351100 MLP13 -45 -0.440000 -6.900000 0.551100 0.351100 MLP21 -46 -1.220000 -6.760000 0.551100 0.351100 MLP22 -47 -0.970000 -7.220000 0.551100 0.351100 MLP31 -48 -1.900000 -6.880000 0.551100 0.351100 MLP32 -49 -2.470000 -6.390000 0.551100 0.351100 MLP33 -50 -2.990000 -5.850000 0.551100 0.351100 MLP34 -51 -3.420000 -3.120000 0.551100 0.351100 MLT11 -52 -4.100000 -4.200000 0.551100 0.351100 MLT12 -53 -4.040000 -5.030000 0.551100 0.351100 MLT13 -54 -3.780000 -5.770000 0.551100 0.351100 MLT14 -55 -3.210000 -6.440000 0.551100 0.351100 MLT15 -56 -2.570000 -7.010000 0.551100 0.351100 MLT16 -57 -3.320000 -2.550000 0.551100 0.351100 MLT21 -58 -4.260000 -3.520000 0.551100 0.351100 MLT22 -59 -4.720000 -4.710000 0.551100 0.351100 MLT23 -60 -4.520000 -5.590000 0.551100 0.351100 MLT24 -61 -4.040000 -6.350000 0.551100 0.351100 MLT25 -62 -3.280000 -7.060000 0.551100 0.351100 MLT26 -63 -4.340000 -2.900000 0.551100 0.351100 MLT31 -64 -5.040000 -4.050000 0.551100 0.351100 MLT32 -65 -5.200000 -5.210000 0.551100 0.351100 MLT33 -66 -4.820000 -6.140000 0.551100 0.351100 MLT34 -67 -4.090000 -7.000000 0.551100 0.351100 MLT35 -68 -5.210000 -3.450000 0.551100 0.351100 MLT41 -69 -5.640000 -4.620000 0.551100 0.351100 MLT42 -70 -5.500000 -5.730000 0.551100 0.351100 MLT43 -71 -4.910000 -6.720000 0.551100 0.351100 MLT44 -72 0.410000 -4.000000 0.551100 0.351100 MRC11 -73 1.170000 -4.130000 0.551100 0.351100 MRC12 -74 2.200000 -4.270000 0.551100 0.351100 MRC13 -75 2.800000 -4.710000 0.551100 0.351100 MRC14 -76 3.320000 -5.230000 0.551100 0.351100 MRC15 -77 0.800000 -4.560000 0.551100 0.351100 MRC21 -78 1.600000 -4.570000 0.551100 0.351100 MRC22 -79 2.140000 -4.970000 0.551100 0.351100 MRC23 -80 2.620000 -5.370000 0.551100 0.351100 MRC24 -81 1.260000 -5.050000 0.551100 0.351100 MRC31 -82 1.760000 -5.450000 0.551100 0.351100 MRC32 -83 1.280000 -5.930000 0.551100 0.351100 MRC33 -84 0.420000 -5.050000 0.551100 0.351100 MRC41 -85 0.810000 -5.540000 0.551100 0.351100 MRC42 -86 0.380000 -6.010000 0.551100 0.351100 MRC43 -87 1.130000 -2.010000 0.551100 0.351100 MRF11 -88 2.240000 -2.230000 0.551100 0.351100 MRF12 -89 0.460000 -2.290000 0.551100 0.351100 MRF21 -90 1.510000 -2.470000 0.551100 0.351100 MRF22 -91 2.520000 -2.740000 0.551100 0.351100 MRF23 -92 0.970000 -2.740000 0.551100 0.351100 MRF31 -93 1.920000 -2.980000 0.551100 0.351100 MRF32 -94 2.760000 -3.300000 0.551100 0.351100 MRF33 -95 3.420000 -3.770000 0.551100 0.351100 MRF34 -96 0.420000 -3.100000 0.551100 0.351100 MRF41 -97 1.360000 -3.260000 0.551100 0.351100 MRF42 -98 2.260000 -3.570000 0.551100 0.351100 MRF43 -99 2.840000 -4.050000 0.551100 0.351100 MRF44 -100 3.480000 -4.510000 0.551100 0.351100 MRF45 -101 0.820000 -3.580000 0.551100 0.351100 MRF51 -102 1.670000 -3.790000 0.551100 0.351100 MRF52 -103 0.470000 -7.690000 0.551100 0.351100 MRO11 -104 1.640000 -7.420000 0.551100 0.351100 MRO12 -105 1.200000 -7.930000 0.551100 0.351100 MRO21 -106 2.350000 -7.580000 0.551100 0.351100 MRO22 -107 0.580000 -8.390000 0.551100 0.351100 MRO31 -108 1.910000 -8.110000 0.551100 0.351100 MRO32 -109 3.110000 -7.670000 0.551100 0.351100 MRO33 -110 1.380000 -8.570000 0.551100 0.351100 MRO41 -111 2.750000 -8.220000 0.551100 0.351100 MRO42 -112 3.900000 -7.610000 0.551100 0.351100 MRO43 -113 0.820000 -6.380000 0.551100 0.351100 MRP11 -114 1.700000 -6.320000 0.551100 0.351100 MRP12 -115 2.220000 -5.870000 0.551100 0.351100 MRP13 -116 0.420000 -6.900000 0.551100 0.351100 MRP21 -117 1.200000 -6.750000 0.551100 0.351100 MRP22 -118 0.960000 -7.220000 0.551100 0.351100 MRP31 -119 1.880000 -6.870000 0.551100 0.351100 MRP32 -120 2.470000 -6.390000 0.551100 0.351100 MRP33 -121 2.990000 -5.850000 0.551100 0.351100 MRP34 -122 3.390000 -3.120000 0.551100 0.351100 MRT11 -123 4.070000 -4.190000 0.551100 0.351100 MRT12 -124 4.020000 -5.030000 0.551100 0.351100 MRT13 -125 3.760000 -5.770000 0.551100 0.351100 MRT14 -126 3.200000 -6.430000 0.551100 0.351100 MRT15 -127 2.570000 -7.010000 0.551100 0.351100 MRT16 -128 3.300000 -2.540000 0.551100 0.351100 MRT21 -129 4.230000 -3.510000 0.551100 0.351100 MRT22 -130 4.700000 -4.710000 0.551100 0.351100 MRT23 -131 4.500000 -5.590000 0.551100 0.351100 MRT24 -132 4.020000 -6.360000 0.551100 0.351100 MRT25 -133 3.260000 -7.060000 0.551100 0.351100 MRT26 -134 4.310000 -2.900000 0.551100 0.351100 MRT31 -135 5.020000 -4.050000 0.551100 0.351100 MRT32 -136 5.180000 -5.210000 0.551100 0.351100 MRT33 -137 4.800000 -6.140000 0.551100 0.351100 MRT34 -138 4.080000 -7.000000 0.551100 0.351100 MRT35 -139 5.200000 -3.450000 0.551100 0.351100 MRT41 -140 5.620000 -4.610000 0.551100 0.351100 MRT42 -141 5.480000 -5.730000 0.551100 0.351100 MRT43 -142 4.900000 -6.710000 0.551100 0.351100 MRT44 -143 0.000000 -4.510000 0.551100 0.351100 MZC01 -144 0.000000 -5.550000 0.551100 0.351100 MZC02 -145 0.000000 -1.930000 0.551100 0.351100 MZF01 -146 0.000000 -2.660000 0.551100 0.351100 MZF02 -147 0.000000 -3.510000 0.551100 0.351100 MZF03 -148 0.000000 -8.050000 0.551100 0.351100 MZO01 -149 0.000000 -8.660000 0.551100 0.351100 MZO02 -150 0.000000 -6.470000 0.551100 0.351100 MZP01 -151 0.000000 -7.290000 0.551100 0.351100 MZP02 -152 5.000000 -2.000000 0.551100 0.351100 SCALE -153 -5.50000 -1.500000 0.551100 0.351100 COMNT diff --git a/external/fieldtrip/private/CTF274.lay b/external/fieldtrip/private/CTF274.lay deleted file mode 100644 index d13bc38..0000000 --- a/external/fieldtrip/private/CTF274.lay +++ /dev/null @@ -1,274 +0,0 @@ -1 -0.029414 0.428191 0.100000 0.040000 MLC11 -2 -0.105398 0.378716 0.100000 0.040000 MLC12 -3 -0.187924 0.341472 0.100000 0.040000 MLC13 -4 -0.268071 0.285079 0.100000 0.040000 MLC14 -5 -0.330692 0.221374 0.100000 0.040000 MLC15 -6 -0.378697 0.144627 0.100000 0.040000 MLC16 -7 -0.411309 0.049716 0.100000 0.040000 MLC17 -8 -0.112105 0.295427 0.100000 0.040000 MLC21 -9 -0.189457 0.259287 0.100000 0.040000 MLC22 -10 -0.254180 0.203140 0.100000 0.040000 MLC23 -11 -0.298355 0.137997 0.100000 0.040000 MLC24 -12 -0.337649 0.050767 0.100000 0.040000 MLC25 -13 -0.213750 0.138862 0.100000 0.040000 MLC31 -14 -0.266243 0.056433 0.100000 0.040000 MLC32 -15 -0.150010 0.191395 0.100000 0.040000 MLC41 -16 -0.188739 0.067511 0.100000 0.040000 MLC42 -17 -0.027405 0.285532 0.100000 0.040000 MLC51 -18 -0.072194 0.217381 0.100000 0.040000 MLC52 -19 -0.130467 0.119358 0.100000 0.040000 MLC53 -20 -0.119656 0.041473 0.100000 0.040000 MLC54 -21 -0.083927 -0.021961 0.100000 0.040000 MLC55 -22 -0.027810 0.155198 0.100000 0.040000 MLC61 -23 -0.062042 0.088583 0.100000 0.040000 MLC62 -24 -0.025587 0.023975 0.100000 0.040000 MLC63 -25 -0.154623 0.879985 0.100000 0.040000 MLF11 -26 -0.322264 0.823233 0.100000 0.040000 MLF12 -27 -0.478342 0.740223 0.100000 0.040000 MLF13 -28 -0.622338 0.633371 0.100000 0.040000 MLF14 -29 -0.052995 0.810917 0.100000 0.040000 MLF21 -30 -0.193258 0.778479 0.100000 0.040000 MLF22 -31 -0.319702 0.726613 0.100000 0.040000 MLF23 -32 -0.447065 0.639878 0.100000 0.040000 MLF24 -33 -0.551024 0.545805 0.100000 0.040000 MLF25 -34 -0.106993 0.717661 0.100000 0.040000 MLF31 -35 -0.227303 0.683510 0.100000 0.040000 MLF32 -36 -0.344973 0.613898 0.100000 0.040000 MLF33 -37 -0.437794 0.535071 0.100000 0.040000 MLF34 -38 -0.516944 0.440135 0.100000 0.040000 MLF35 -39 -0.037498 0.646457 0.100000 0.040000 MLF41 -40 -0.145663 0.629747 0.100000 0.040000 MLF42 -41 -0.257022 0.575998 0.100000 0.040000 MLF43 -42 -0.344741 0.511350 0.100000 0.040000 MLF44 -43 -0.434608 0.430669 0.100000 0.040000 MLF45 -44 -0.512928 0.325699 0.100000 0.040000 MLF46 -45 -0.065241 0.564676 0.100000 0.040000 MLF51 -46 -0.176866 0.530203 0.100000 0.040000 MLF52 -47 -0.264799 0.476609 0.100000 0.040000 MLF53 -48 -0.344149 0.409817 0.100000 0.040000 MLF54 -49 -0.432009 0.328939 0.100000 0.040000 MLF55 -50 -0.502082 0.225317 0.100000 0.040000 MLF56 -51 -0.108196 0.473300 0.100000 0.040000 MLF61 -52 -0.191454 0.428184 0.100000 0.040000 MLF62 -53 -0.268505 0.371569 0.100000 0.040000 MLF63 -54 -0.343162 0.314227 0.100000 0.040000 MLF64 -55 -0.415355 0.241209 0.100000 0.040000 MLF65 -56 -0.459435 0.157639 0.100000 0.040000 MLF66 -57 -0.484998 0.050963 0.100000 0.040000 MLF67 -58 -0.086701 -0.382545 0.100000 0.040000 MLO11 -59 -0.173621 -0.361571 0.100000 0.040000 MLO12 -60 -0.257557 -0.329066 0.100000 0.040000 MLO13 -61 -0.337129 -0.278810 0.100000 0.040000 MLO14 -62 -0.050176 -0.456757 0.100000 0.040000 MLO21 -63 -0.138937 -0.440153 0.100000 0.040000 MLO22 -64 -0.234625 -0.414329 0.100000 0.040000 MLO23 -65 -0.323700 -0.370345 0.100000 0.040000 MLO24 -66 -0.099528 -0.519048 0.100000 0.040000 MLO31 -67 -0.201576 -0.499713 0.100000 0.040000 MLO32 -68 -0.300736 -0.464088 0.100000 0.040000 MLO33 -69 -0.395767 -0.412426 0.100000 0.040000 MLO34 -70 -0.054171 -0.598130 0.100000 0.040000 MLO41 -71 -0.162924 -0.587463 0.100000 0.040000 MLO42 -72 -0.270457 -0.559057 0.100000 0.040000 MLO43 -73 -0.375045 -0.514503 0.100000 0.040000 MLO44 -74 -0.114841 -0.674066 0.100000 0.040000 MLO51 -75 -0.232779 -0.654920 0.100000 0.040000 MLO52 -76 -0.347032 -0.617457 0.100000 0.040000 MLO53 -77 -0.050706 -0.086860 0.100000 0.040000 MLP11 -78 -0.157880 -0.022819 0.100000 0.040000 MLP12 -79 -0.027384 -0.156541 0.100000 0.040000 MLP21 -80 -0.125969 -0.090281 0.100000 0.040000 MLP22 -81 -0.229468 -0.007021 0.100000 0.040000 MLP23 -82 -0.063851 -0.221282 0.100000 0.040000 MLP31 -83 -0.117483 -0.164444 0.100000 0.040000 MLP32 -84 -0.191075 -0.130343 0.100000 0.040000 MLP33 -85 -0.256310 -0.076997 0.100000 0.040000 MLP34 -86 -0.301408 -0.017428 0.100000 0.040000 MLP35 -87 -0.145628 -0.236552 0.100000 0.040000 MLP41 -88 -0.211609 -0.201084 0.100000 0.040000 MLP42 -89 -0.277557 -0.161143 0.100000 0.040000 MLP43 -90 -0.330491 -0.093163 0.100000 0.040000 MLP44 -91 -0.372987 -0.024823 0.100000 0.040000 MLP45 -92 -0.032003 -0.311166 0.100000 0.040000 MLP51 -93 -0.120201 -0.309697 0.100000 0.040000 MLP52 -94 -0.197411 -0.282930 0.100000 0.040000 MLP53 -95 -0.273221 -0.242434 0.100000 0.040000 MLP54 -96 -0.341326 -0.192353 0.100000 0.040000 MLP55 -97 -0.397869 -0.117824 0.100000 0.040000 MLP56 -98 -0.439023 -0.040798 0.100000 0.040000 MLP57 -99 -0.600517 0.341742 0.100000 0.040000 MLT11 -100 -0.583854 0.221014 0.100000 0.040000 MLT12 -101 -0.546672 0.118228 0.100000 0.040000 MLT13 -102 -0.525679 -0.043954 0.100000 0.040000 MLT14 -103 -0.482366 -0.132402 0.100000 0.040000 MLT15 -104 -0.408785 -0.217740 0.100000 0.040000 MLT16 -105 -0.657080 0.441193 0.100000 0.040000 MLT21 -106 -0.681569 0.225254 0.100000 0.040000 MLT22 -107 -0.647357 0.101107 0.100000 0.040000 MLT23 -108 -0.618158 -0.017119 0.100000 0.040000 MLT24 -109 -0.570925 -0.147553 0.100000 0.040000 MLT25 -110 -0.505869 -0.237678 0.100000 0.040000 MLT26 -111 -0.406336 -0.310886 0.100000 0.040000 MLT27 -112 -0.758025 0.508412 0.100000 0.040000 MLT31 -113 -0.761740 0.316423 0.100000 0.040000 MLT32 -114 -0.751268 0.088675 0.100000 0.040000 MLT33 -115 -0.712573 -0.047448 0.100000 0.040000 MLT34 -116 -0.658112 -0.159355 0.100000 0.040000 MLT35 -117 -0.592395 -0.256839 0.100000 0.040000 MLT36 -118 -0.495312 -0.345113 0.100000 0.040000 MLT37 -119 -0.885393 0.353401 0.100000 0.040000 MLT41 -120 -0.847844 0.160648 0.100000 0.040000 MLT42 -121 -0.823787 -0.043736 0.100000 0.040000 MLT43 -122 -0.758805 -0.175411 0.100000 0.040000 MLT44 -123 -0.684634 -0.280647 0.100000 0.040000 MLT45 -124 -0.591783 -0.373867 0.100000 0.040000 MLT46 -125 -0.476572 -0.454666 0.100000 0.040000 MLT47 -126 -0.983285 0.161080 0.100000 0.040000 MLT51 -127 -0.944753 -0.028756 0.100000 0.040000 MLT52 -128 -0.872989 -0.188195 0.100000 0.040000 MLT53 -129 -0.785517 -0.310620 0.100000 0.040000 MLT54 -130 -0.688014 -0.407791 0.100000 0.040000 MLT55 -131 -0.571347 -0.497554 0.100000 0.040000 MLT56 -132 -0.457303 -0.565438 0.100000 0.040000 MLT57 -133 0.063389 0.426606 0.100000 0.040000 MRC11 -134 0.137902 0.375428 0.100000 0.040000 MRC12 -135 0.219516 0.336386 0.100000 0.040000 MRC13 -136 0.297688 0.277771 0.100000 0.040000 MRC14 -137 0.355955 0.213304 0.100000 0.040000 MRC15 -138 0.404150 0.135598 0.100000 0.040000 MRC16 -139 0.434870 0.040656 0.100000 0.040000 MRC17 -140 0.142678 0.292126 0.100000 0.040000 MRC21 -141 0.219470 0.254066 0.100000 0.040000 MRC22 -142 0.281922 0.196472 0.100000 0.040000 MRC23 -143 0.325059 0.128269 0.100000 0.040000 MRC24 -144 0.361805 0.044213 0.100000 0.040000 MRC25 -145 0.240157 0.132538 0.100000 0.040000 MRC31 -146 0.290750 0.048681 0.100000 0.040000 MRC32 -147 0.178346 0.187415 0.100000 0.040000 MRC41 -148 0.213493 0.062545 0.100000 0.040000 MRC42 -149 0.058440 0.284194 0.100000 0.040000 MRC51 -150 0.101359 0.215083 0.100000 0.040000 MRC52 -151 0.156968 0.115486 0.100000 0.040000 MRC53 -152 0.144211 0.038238 0.100000 0.040000 MRC54 -153 0.106635 -0.024115 0.100000 0.040000 MRC55 -154 0.055338 0.153928 0.100000 0.040000 MRC61 -155 0.088138 0.086634 0.100000 0.040000 MRC62 -156 0.049557 0.022680 0.100000 0.040000 MRC63 -157 0.197726 0.874477 0.100000 0.040000 MRF11 -158 0.364689 0.811426 0.100000 0.040000 MRF12 -159 0.518245 0.722181 0.100000 0.040000 MRF13 -160 0.658136 0.611411 0.100000 0.040000 MRF14 -161 0.095713 0.807816 0.100000 0.040000 MRF21 -162 0.233999 0.772267 0.100000 0.040000 MRF22 -163 0.358821 0.715911 0.100000 0.040000 MRF23 -164 0.484765 0.623142 0.100000 0.040000 MRF24 -165 0.585405 0.526324 0.100000 0.040000 MRF25 -166 0.147633 0.713396 0.100000 0.040000 MRF31 -167 0.265823 0.676341 0.100000 0.040000 MRF32 -168 0.382256 0.601823 0.100000 0.040000 MRF33 -169 0.473850 0.521768 0.100000 0.040000 MRF34 -170 0.548726 0.424836 0.100000 0.040000 MRF35 -171 0.075451 0.644959 0.100000 0.040000 MRF41 -172 0.182924 0.624842 0.100000 0.040000 MRF42 -173 0.379529 0.501620 0.100000 0.040000 MRF44 -174 0.465778 0.418231 0.100000 0.040000 MRF45 -175 0.541913 0.311405 0.100000 0.040000 MRF46 -176 0.102375 0.561860 0.100000 0.040000 MRF51 -177 0.212879 0.524802 0.100000 0.040000 MRF52 -178 0.299077 0.468924 0.100000 0.040000 MRF53 -179 0.376186 0.400507 0.100000 0.040000 MRF54 -180 0.461150 0.316311 0.100000 0.040000 MRF55 -181 0.527532 0.213125 0.100000 0.040000 MRF56 -182 0.143360 0.469857 0.100000 0.040000 MRF61 -183 0.224730 0.422291 0.100000 0.040000 MRF62 -184 0.301012 0.364856 0.100000 0.040000 MRF63 -185 0.373056 0.305526 0.100000 0.040000 MRF64 -186 0.443172 0.230008 0.100000 0.040000 MRF65 -187 0.482916 0.144546 0.100000 0.040000 MRF66 -188 0.509363 0.039864 0.100000 0.040000 MRF67 -189 0.101312 -0.384464 0.100000 0.040000 MRO11 -190 0.188777 -0.365285 0.100000 0.040000 MRO12 -191 0.274286 -0.333994 0.100000 0.040000 MRO13 -192 0.354824 -0.285987 0.100000 0.040000 MRO14 -193 0.062633 -0.457476 0.100000 0.040000 MRO21 -194 0.152570 -0.440791 0.100000 0.040000 MRO22 -195 0.248565 -0.418432 0.100000 0.040000 MRO23 -196 0.338845 -0.376241 0.100000 0.040000 MRO24 -197 0.111160 -0.521375 0.100000 0.040000 MRO31 -198 0.212466 -0.502957 0.100000 0.040000 MRO32 -199 0.313063 -0.468465 0.100000 0.040000 MRO33 -200 0.409385 -0.418933 0.100000 0.040000 MRO34 -201 0.063270 -0.599845 0.100000 0.040000 MRO41 -202 0.172480 -0.589865 0.100000 0.040000 MRO42 -203 0.279919 -0.563495 0.100000 0.040000 MRO43 -204 0.386742 -0.520993 0.100000 0.040000 MRO44 -205 0.121969 -0.676100 0.100000 0.040000 MRO51 -206 0.240331 -0.658743 0.100000 0.040000 MRO52 -207 0.356156 -0.623026 0.100000 0.040000 MRO53 -208 0.071855 -0.088269 0.100000 0.040000 MRP11 -209 0.180874 -0.026656 0.100000 0.040000 MRP12 -210 0.047839 -0.157479 0.100000 0.040000 MRP21 -211 0.147221 -0.093053 0.100000 0.040000 MRP22 -212 0.252807 -0.012686 0.100000 0.040000 MRP23 -213 0.082012 -0.222790 0.100000 0.040000 MRP31 -214 0.136825 -0.166819 0.100000 0.040000 MRP32 -215 0.210796 -0.134697 0.100000 0.040000 MRP33 -216 0.277587 -0.083946 0.100000 0.040000 MRP34 -217 0.322867 -0.024718 0.100000 0.040000 MRP35 -218 0.162954 -0.240118 0.100000 0.040000 MRP41 -219 0.230510 -0.205793 0.100000 0.040000 MRP42 -220 0.296283 -0.169213 0.100000 0.040000 MRP43 -221 0.351532 -0.101316 0.100000 0.040000 MRP44 -222 0.395383 -0.032706 0.100000 0.040000 MRP45 -223 0.048690 -0.312307 0.100000 0.040000 MRP51 -224 0.137008 -0.312230 0.100000 0.040000 MRP52 -225 0.214275 -0.287336 0.100000 0.040000 MRP53 -226 0.290637 -0.248388 0.100000 0.040000 MRP54 -227 0.360555 -0.199475 0.100000 0.040000 MRP55 -228 0.419086 -0.126737 0.100000 0.040000 MRP56 -229 0.463976 -0.050387 0.100000 0.040000 MRP57 -230 0.628409 0.323946 0.100000 0.040000 MRT11 -231 0.609835 0.205866 0.100000 0.040000 MRT12 -232 0.571838 0.105198 0.100000 0.040000 MRT13 -233 0.544252 -0.054539 0.100000 0.040000 MRT14 -234 0.500732 -0.143104 0.100000 0.040000 MRT15 -235 0.427582 -0.225716 0.100000 0.040000 MRT16 -236 0.685440 0.421411 0.100000 0.040000 MRT21 -237 0.705800 0.208084 0.100000 0.040000 MRT22 -238 0.667392 0.088109 0.100000 0.040000 MRT23 -239 0.637062 -0.030086 0.100000 0.040000 MRT24 -240 0.588417 -0.159092 0.100000 0.040000 MRT25 -241 0.522350 -0.247039 0.100000 0.040000 MRT26 -242 0.422093 -0.318167 0.100000 0.040000 MRT27 -243 0.789789 0.482334 0.100000 0.040000 MRT31 -244 0.786599 0.293212 0.100000 0.040000 MRT32 -245 0.770320 0.070984 0.100000 0.040000 MRT33 -246 0.731214 -0.061690 0.100000 0.040000 MRT34 -247 0.674802 -0.172109 0.100000 0.040000 MRT35 -248 0.607500 -0.268226 0.100000 0.040000 MRT36 -249 0.510484 -0.353209 0.100000 0.040000 MRT37 -250 0.910695 0.324672 0.100000 0.040000 MRT41 -251 0.867982 0.137317 0.100000 0.040000 MRT42 -252 0.839920 -0.060661 0.100000 0.040000 MRT43 -253 0.773256 -0.189639 0.100000 0.040000 MRT44 -254 0.698444 -0.293384 0.100000 0.040000 MRT45 -255 0.604482 -0.385347 0.100000 0.040000 MRT46 -256 0.489291 -0.462983 0.100000 0.040000 MRT47 -257 1.000000 0.135648 0.100000 0.040000 MRT51 -258 0.959092 -0.049055 0.100000 0.040000 MRT52 -259 0.886964 -0.204289 0.100000 0.040000 MRT53 -260 0.796842 -0.324881 0.100000 0.040000 MRT54 -261 0.698769 -0.420596 0.100000 0.040000 MRT55 -262 0.582500 -0.506810 0.100000 0.040000 MRT56 -263 0.467934 -0.572706 0.100000 0.040000 MRT57 -264 0.016063 0.355556 0.100000 0.040000 MZC01 -265 0.014747 0.217488 0.100000 0.040000 MZC02 -266 0.013199 0.087763 0.100000 0.040000 MZC03 -267 0.011197 -0.046263 0.100000 0.040000 MZC04 -268 0.022267 0.897778 0.100000 0.040000 MZF01 -269 0.019840 0.730557 0.100000 0.040000 MZF02 -270 0.017559 0.517279 0.100000 0.040000 MZF03 -271 0.007392 -0.378522 0.100000 0.040000 MZO01 -272 0.005634 -0.528155 0.100000 0.040000 MZO02 -273 0.003722 -0.675585 0.100000 0.040000 MZO03 -274 0.008864 -0.248776 0.100000 0.040000 MZP01 diff --git a/external/fieldtrip/private/CTF275.lay b/external/fieldtrip/private/CTF275.lay deleted file mode 100644 index 2af28d3..0000000 --- a/external/fieldtrip/private/CTF275.lay +++ /dev/null @@ -1,275 +0,0 @@ -1 -0.029414 0.428191 0.100000 0.040000 MLC11 -2 -0.105398 0.378716 0.100000 0.040000 MLC12 -3 -0.187924 0.341472 0.100000 0.040000 MLC13 -4 -0.268071 0.285079 0.100000 0.040000 MLC14 -5 -0.330692 0.221374 0.100000 0.040000 MLC15 -6 -0.378697 0.144627 0.100000 0.040000 MLC16 -7 -0.411309 0.049716 0.100000 0.040000 MLC17 -8 -0.112105 0.295427 0.100000 0.040000 MLC21 -9 -0.189457 0.259287 0.100000 0.040000 MLC22 -10 -0.254180 0.203140 0.100000 0.040000 MLC23 -11 -0.298355 0.137997 0.100000 0.040000 MLC24 -12 -0.337649 0.050767 0.100000 0.040000 MLC25 -13 -0.213750 0.138862 0.100000 0.040000 MLC31 -14 -0.266243 0.056433 0.100000 0.040000 MLC32 -15 -0.150010 0.191395 0.100000 0.040000 MLC41 -16 -0.188739 0.067511 0.100000 0.040000 MLC42 -17 -0.027405 0.285532 0.100000 0.040000 MLC51 -18 -0.072194 0.217381 0.100000 0.040000 MLC52 -19 -0.130467 0.119358 0.100000 0.040000 MLC53 -20 -0.119656 0.041473 0.100000 0.040000 MLC54 -21 -0.083927 -0.021961 0.100000 0.040000 MLC55 -22 -0.027810 0.155198 0.100000 0.040000 MLC61 -23 -0.062042 0.088583 0.100000 0.040000 MLC62 -24 -0.025587 0.023975 0.100000 0.040000 MLC63 -25 -0.154623 0.879985 0.100000 0.040000 MLF11 -26 -0.322264 0.823233 0.100000 0.040000 MLF12 -27 -0.478342 0.740223 0.100000 0.040000 MLF13 -28 -0.622338 0.633371 0.100000 0.040000 MLF14 -29 -0.052995 0.810917 0.100000 0.040000 MLF21 -30 -0.193258 0.778479 0.100000 0.040000 MLF22 -31 -0.319702 0.726613 0.100000 0.040000 MLF23 -32 -0.447065 0.639878 0.100000 0.040000 MLF24 -33 -0.551024 0.545805 0.100000 0.040000 MLF25 -34 -0.106993 0.717661 0.100000 0.040000 MLF31 -35 -0.227303 0.683510 0.100000 0.040000 MLF32 -36 -0.344973 0.613898 0.100000 0.040000 MLF33 -37 -0.437794 0.535071 0.100000 0.040000 MLF34 -38 -0.516944 0.440135 0.100000 0.040000 MLF35 -39 -0.037498 0.646457 0.100000 0.040000 MLF41 -40 -0.145663 0.629747 0.100000 0.040000 MLF42 -41 -0.257022 0.575998 0.100000 0.040000 MLF43 -42 -0.344741 0.511350 0.100000 0.040000 MLF44 -43 -0.434608 0.430669 0.100000 0.040000 MLF45 -44 -0.512928 0.325699 0.100000 0.040000 MLF46 -45 -0.065241 0.564676 0.100000 0.040000 MLF51 -46 -0.176866 0.530203 0.100000 0.040000 MLF52 -47 -0.264799 0.476609 0.100000 0.040000 MLF53 -48 -0.344149 0.409817 0.100000 0.040000 MLF54 -49 -0.432009 0.328939 0.100000 0.040000 MLF55 -50 -0.502082 0.225317 0.100000 0.040000 MLF56 -51 -0.108196 0.473300 0.100000 0.040000 MLF61 -52 -0.191454 0.428184 0.100000 0.040000 MLF62 -53 -0.268505 0.371569 0.100000 0.040000 MLF63 -54 -0.343162 0.314227 0.100000 0.040000 MLF64 -55 -0.415355 0.241209 0.100000 0.040000 MLF65 -56 -0.459435 0.157639 0.100000 0.040000 MLF66 -57 -0.484998 0.050963 0.100000 0.040000 MLF67 -58 -0.086701 -0.382545 0.100000 0.040000 MLO11 -59 -0.173621 -0.361571 0.100000 0.040000 MLO12 -60 -0.257557 -0.329066 0.100000 0.040000 MLO13 -61 -0.337129 -0.278810 0.100000 0.040000 MLO14 -62 -0.050176 -0.456757 0.100000 0.040000 MLO21 -63 -0.138937 -0.440153 0.100000 0.040000 MLO22 -64 -0.234625 -0.414329 0.100000 0.040000 MLO23 -65 -0.323700 -0.370345 0.100000 0.040000 MLO24 -66 -0.099528 -0.519048 0.100000 0.040000 MLO31 -67 -0.201576 -0.499713 0.100000 0.040000 MLO32 -68 -0.300736 -0.464088 0.100000 0.040000 MLO33 -69 -0.395767 -0.412426 0.100000 0.040000 MLO34 -70 -0.054171 -0.598130 0.100000 0.040000 MLO41 -71 -0.162924 -0.587463 0.100000 0.040000 MLO42 -72 -0.270457 -0.559057 0.100000 0.040000 MLO43 -73 -0.375045 -0.514503 0.100000 0.040000 MLO44 -74 -0.114841 -0.674066 0.100000 0.040000 MLO51 -75 -0.232779 -0.654920 0.100000 0.040000 MLO52 -76 -0.347032 -0.617457 0.100000 0.040000 MLO53 -77 -0.050706 -0.086860 0.100000 0.040000 MLP11 -78 -0.157880 -0.022819 0.100000 0.040000 MLP12 -79 -0.027384 -0.156541 0.100000 0.040000 MLP21 -80 -0.125969 -0.090281 0.100000 0.040000 MLP22 -81 -0.229468 -0.007021 0.100000 0.040000 MLP23 -82 -0.063851 -0.221282 0.100000 0.040000 MLP31 -83 -0.117483 -0.164444 0.100000 0.040000 MLP32 -84 -0.191075 -0.130343 0.100000 0.040000 MLP33 -85 -0.256310 -0.076997 0.100000 0.040000 MLP34 -86 -0.301408 -0.017428 0.100000 0.040000 MLP35 -87 -0.145628 -0.236552 0.100000 0.040000 MLP41 -88 -0.211609 -0.201084 0.100000 0.040000 MLP42 -89 -0.277557 -0.161143 0.100000 0.040000 MLP43 -90 -0.330491 -0.093163 0.100000 0.040000 MLP44 -91 -0.372987 -0.024823 0.100000 0.040000 MLP45 -92 -0.032003 -0.311166 0.100000 0.040000 MLP51 -93 -0.120201 -0.309697 0.100000 0.040000 MLP52 -94 -0.197411 -0.282930 0.100000 0.040000 MLP53 -95 -0.273221 -0.242434 0.100000 0.040000 MLP54 -96 -0.341326 -0.192353 0.100000 0.040000 MLP55 -97 -0.397869 -0.117824 0.100000 0.040000 MLP56 -98 -0.439023 -0.040798 0.100000 0.040000 MLP57 -99 -0.600517 0.341742 0.100000 0.040000 MLT11 -100 -0.583854 0.221014 0.100000 0.040000 MLT12 -101 -0.546672 0.118228 0.100000 0.040000 MLT13 -102 -0.525679 -0.043954 0.100000 0.040000 MLT14 -103 -0.482366 -0.132402 0.100000 0.040000 MLT15 -104 -0.408785 -0.217740 0.100000 0.040000 MLT16 -105 -0.657080 0.441193 0.100000 0.040000 MLT21 -106 -0.681569 0.225254 0.100000 0.040000 MLT22 -107 -0.647357 0.101107 0.100000 0.040000 MLT23 -108 -0.618158 -0.017119 0.100000 0.040000 MLT24 -109 -0.570925 -0.147553 0.100000 0.040000 MLT25 -110 -0.505869 -0.237678 0.100000 0.040000 MLT26 -111 -0.406336 -0.310886 0.100000 0.040000 MLT27 -112 -0.758025 0.508412 0.100000 0.040000 MLT31 -113 -0.761740 0.316423 0.100000 0.040000 MLT32 -114 -0.751268 0.088675 0.100000 0.040000 MLT33 -115 -0.712573 -0.047448 0.100000 0.040000 MLT34 -116 -0.658112 -0.159355 0.100000 0.040000 MLT35 -117 -0.592395 -0.256839 0.100000 0.040000 MLT36 -118 -0.495312 -0.345113 0.100000 0.040000 MLT37 -119 -0.885393 0.353401 0.100000 0.040000 MLT41 -120 -0.847844 0.160648 0.100000 0.040000 MLT42 -121 -0.823787 -0.043736 0.100000 0.040000 MLT43 -122 -0.758805 -0.175411 0.100000 0.040000 MLT44 -123 -0.684634 -0.280647 0.100000 0.040000 MLT45 -124 -0.591783 -0.373867 0.100000 0.040000 MLT46 -125 -0.476572 -0.454666 0.100000 0.040000 MLT47 -126 -0.983285 0.161080 0.100000 0.040000 MLT51 -127 -0.944753 -0.028756 0.100000 0.040000 MLT52 -128 -0.872989 -0.188195 0.100000 0.040000 MLT53 -129 -0.785517 -0.310620 0.100000 0.040000 MLT54 -130 -0.688014 -0.407791 0.100000 0.040000 MLT55 -131 -0.571347 -0.497554 0.100000 0.040000 MLT56 -132 -0.457303 -0.565438 0.100000 0.040000 MLT57 -133 0.063389 0.426606 0.100000 0.040000 MRC11 -134 0.137902 0.375428 0.100000 0.040000 MRC12 -135 0.219516 0.336386 0.100000 0.040000 MRC13 -136 0.297688 0.277771 0.100000 0.040000 MRC14 -137 0.355955 0.213304 0.100000 0.040000 MRC15 -138 0.404150 0.135598 0.100000 0.040000 MRC16 -139 0.434870 0.040656 0.100000 0.040000 MRC17 -140 0.142678 0.292126 0.100000 0.040000 MRC21 -141 0.219470 0.254066 0.100000 0.040000 MRC22 -142 0.281922 0.196472 0.100000 0.040000 MRC23 -143 0.325059 0.128269 0.100000 0.040000 MRC24 -144 0.361805 0.044213 0.100000 0.040000 MRC25 -145 0.240157 0.132538 0.100000 0.040000 MRC31 -146 0.290750 0.048681 0.100000 0.040000 MRC32 -147 0.178346 0.187415 0.100000 0.040000 MRC41 -148 0.213493 0.062545 0.100000 0.040000 MRC42 -149 0.058440 0.284194 0.100000 0.040000 MRC51 -150 0.101359 0.215083 0.100000 0.040000 MRC52 -151 0.156968 0.115486 0.100000 0.040000 MRC53 -152 0.144211 0.038238 0.100000 0.040000 MRC54 -153 0.106635 -0.024115 0.100000 0.040000 MRC55 -154 0.055338 0.153928 0.100000 0.040000 MRC61 -155 0.088138 0.086634 0.100000 0.040000 MRC62 -156 0.049557 0.022680 0.100000 0.040000 MRC63 -157 0.197726 0.874477 0.100000 0.040000 MRF11 -158 0.364689 0.811426 0.100000 0.040000 MRF12 -159 0.518245 0.722181 0.100000 0.040000 MRF13 -160 0.658136 0.611411 0.100000 0.040000 MRF14 -161 0.095713 0.807816 0.100000 0.040000 MRF21 -162 0.233999 0.772267 0.100000 0.040000 MRF22 -163 0.358821 0.715911 0.100000 0.040000 MRF23 -164 0.484765 0.623142 0.100000 0.040000 MRF24 -165 0.585405 0.526324 0.100000 0.040000 MRF25 -166 0.147633 0.713396 0.100000 0.040000 MRF31 -167 0.265823 0.676341 0.100000 0.040000 MRF32 -168 0.382256 0.601823 0.100000 0.040000 MRF33 -169 0.473850 0.521768 0.100000 0.040000 MRF34 -170 0.548726 0.424836 0.100000 0.040000 MRF35 -171 0.075451 0.644959 0.100000 0.040000 MRF41 -172 0.182924 0.624842 0.100000 0.040000 MRF42 -173 0.292900 0.568899 0.100000 0.040000 MRF43 -174 0.379529 0.501620 0.100000 0.040000 MRF44 -175 0.465778 0.418231 0.100000 0.040000 MRF45 -176 0.541913 0.311405 0.100000 0.040000 MRF46 -177 0.102375 0.561860 0.100000 0.040000 MRF51 -178 0.212879 0.524802 0.100000 0.040000 MRF52 -179 0.299077 0.468924 0.100000 0.040000 MRF53 -180 0.376186 0.400507 0.100000 0.040000 MRF54 -181 0.461150 0.316311 0.100000 0.040000 MRF55 -182 0.527532 0.213125 0.100000 0.040000 MRF56 -183 0.143360 0.469857 0.100000 0.040000 MRF61 -184 0.224730 0.422291 0.100000 0.040000 MRF62 -185 0.301012 0.364856 0.100000 0.040000 MRF63 -186 0.373056 0.305526 0.100000 0.040000 MRF64 -187 0.443172 0.230008 0.100000 0.040000 MRF65 -188 0.482916 0.144546 0.100000 0.040000 MRF66 -189 0.509363 0.039864 0.100000 0.040000 MRF67 -190 0.101312 -0.384464 0.100000 0.040000 MRO11 -191 0.188777 -0.365285 0.100000 0.040000 MRO12 -192 0.274286 -0.333994 0.100000 0.040000 MRO13 -193 0.354824 -0.285987 0.100000 0.040000 MRO14 -194 0.062633 -0.457476 0.100000 0.040000 MRO21 -195 0.152570 -0.440791 0.100000 0.040000 MRO22 -196 0.248565 -0.418432 0.100000 0.040000 MRO23 -197 0.338845 -0.376241 0.100000 0.040000 MRO24 -198 0.111160 -0.521375 0.100000 0.040000 MRO31 -199 0.212466 -0.502957 0.100000 0.040000 MRO32 -200 0.313063 -0.468465 0.100000 0.040000 MRO33 -201 0.409385 -0.418933 0.100000 0.040000 MRO34 -202 0.063270 -0.599845 0.100000 0.040000 MRO41 -203 0.172480 -0.589865 0.100000 0.040000 MRO42 -204 0.279919 -0.563495 0.100000 0.040000 MRO43 -205 0.386742 -0.520993 0.100000 0.040000 MRO44 -206 0.121969 -0.676100 0.100000 0.040000 MRO51 -207 0.240331 -0.658743 0.100000 0.040000 MRO52 -208 0.356156 -0.623026 0.100000 0.040000 MRO53 -209 0.071855 -0.088269 0.100000 0.040000 MRP11 -210 0.180874 -0.026656 0.100000 0.040000 MRP12 -211 0.047839 -0.157479 0.100000 0.040000 MRP21 -212 0.147221 -0.093053 0.100000 0.040000 MRP22 -213 0.252807 -0.012686 0.100000 0.040000 MRP23 -214 0.082012 -0.222790 0.100000 0.040000 MRP31 -215 0.136825 -0.166819 0.100000 0.040000 MRP32 -216 0.210796 -0.134697 0.100000 0.040000 MRP33 -217 0.277587 -0.083946 0.100000 0.040000 MRP34 -218 0.322867 -0.024718 0.100000 0.040000 MRP35 -219 0.162954 -0.240118 0.100000 0.040000 MRP41 -220 0.230510 -0.205793 0.100000 0.040000 MRP42 -221 0.296283 -0.169213 0.100000 0.040000 MRP43 -222 0.351532 -0.101316 0.100000 0.040000 MRP44 -223 0.395383 -0.032706 0.100000 0.040000 MRP45 -224 0.048690 -0.312307 0.100000 0.040000 MRP51 -225 0.137008 -0.312230 0.100000 0.040000 MRP52 -226 0.214275 -0.287336 0.100000 0.040000 MRP53 -227 0.290637 -0.248388 0.100000 0.040000 MRP54 -228 0.360555 -0.199475 0.100000 0.040000 MRP55 -229 0.419086 -0.126737 0.100000 0.040000 MRP56 -230 0.463976 -0.050387 0.100000 0.040000 MRP57 -231 0.628409 0.323946 0.100000 0.040000 MRT11 -232 0.609835 0.205866 0.100000 0.040000 MRT12 -233 0.571838 0.105198 0.100000 0.040000 MRT13 -234 0.544252 -0.054539 0.100000 0.040000 MRT14 -235 0.500732 -0.143104 0.100000 0.040000 MRT15 -236 0.427582 -0.225716 0.100000 0.040000 MRT16 -237 0.685440 0.421411 0.100000 0.040000 MRT21 -238 0.705800 0.208084 0.100000 0.040000 MRT22 -239 0.667392 0.088109 0.100000 0.040000 MRT23 -240 0.637062 -0.030086 0.100000 0.040000 MRT24 -241 0.588417 -0.159092 0.100000 0.040000 MRT25 -242 0.522350 -0.247039 0.100000 0.040000 MRT26 -243 0.422093 -0.318167 0.100000 0.040000 MRT27 -244 0.789789 0.482334 0.100000 0.040000 MRT31 -245 0.786599 0.293212 0.100000 0.040000 MRT32 -246 0.770320 0.070984 0.100000 0.040000 MRT33 -247 0.731214 -0.061690 0.100000 0.040000 MRT34 -248 0.674802 -0.172109 0.100000 0.040000 MRT35 -249 0.607500 -0.268226 0.100000 0.040000 MRT36 -250 0.510484 -0.353209 0.100000 0.040000 MRT37 -251 0.910695 0.324672 0.100000 0.040000 MRT41 -252 0.867982 0.137317 0.100000 0.040000 MRT42 -253 0.839920 -0.060661 0.100000 0.040000 MRT43 -254 0.773256 -0.189639 0.100000 0.040000 MRT44 -255 0.698444 -0.293384 0.100000 0.040000 MRT45 -256 0.604482 -0.385347 0.100000 0.040000 MRT46 -257 0.489291 -0.462983 0.100000 0.040000 MRT47 -258 1.000000 0.135648 0.100000 0.040000 MRT51 -259 0.959092 -0.049055 0.100000 0.040000 MRT52 -260 0.886964 -0.204289 0.100000 0.040000 MRT53 -261 0.796842 -0.324881 0.100000 0.040000 MRT54 -262 0.698769 -0.420596 0.100000 0.040000 MRT55 -263 0.582500 -0.506810 0.100000 0.040000 MRT56 -264 0.467934 -0.572706 0.100000 0.040000 MRT57 -265 0.016063 0.355556 0.100000 0.040000 MZC01 -266 0.014747 0.217488 0.100000 0.040000 MZC02 -267 0.013199 0.087763 0.100000 0.040000 MZC03 -268 0.011197 -0.046263 0.100000 0.040000 MZC04 -269 0.022267 0.897778 0.100000 0.040000 MZF01 -270 0.019840 0.730557 0.100000 0.040000 MZF02 -271 0.017559 0.517279 0.100000 0.040000 MZF03 -272 0.007392 -0.378522 0.100000 0.040000 MZO01 -273 0.005634 -0.528155 0.100000 0.040000 MZO02 -274 0.003722 -0.675585 0.100000 0.040000 MZO03 -275 0.008864 -0.248776 0.100000 0.040000 MZP01 diff --git a/external/fieldtrip/private/Contents.m b/external/fieldtrip/private/Contents.m deleted file mode 100644 index 889f274..0000000 --- a/external/fieldtrip/private/Contents.m +++ /dev/null @@ -1,162 +0,0 @@ -% FieldTrip is a Matlab toolbox for MEG and EEG analysis that is being -% developed at the Centre for Cognitive Neuroimaging of the Donders -% Institute for Brain, Cognition and Behaviour together with collaborating -% institutes. The development of FieldTrip is supported by funding from the -% BrainGain consortium. The FieldTrip software is released as open source -% under the GNU general public license. -% -% The toolbox includes algorithms for simple and advanced analysis of MEG -% and EEG data, such as time-frequency analysis, source reconstruction -% using dipoles, distributed sources and beamformers and non-parametric -% statistical testing. It supports the data formats of all major MEG -% systems (CTF, Neuromag, BTi) and of the most popular EEG systems, and new -% formats can be added easily. FieldTrip contains high-level functions that -% you can use to construct your own analysis protocol in Matlab. -% Furthermore, it easily allows developers to incorporate low-level -% algorithms for new EEG/MEG analysis methods. -% -% The FieldTrip software is free but copyrighted software, distributed -% under the terms of the GNU General Public Licence as published by -% the Free Software Foundation (either version 2, or at your option -% any later version). See the file COPYING for more details. -% -% The functions in this toolbox are copyrighted by their respective authors: -% Robert Oostenveld, DCCN, FCDC, SMI, MBFYS -% Jan-Matthijs Schoffelen, CCNi, FCDC -% Pascal Fries, FCDC -% Markus Bauer, FCDC -% Ole Jensen, FCDC -% Markus Siegel, FCDC, UKE -% Jens Schwarzbach, FCDC -% Eric Maris, DCC, FCDC -% Ingrid Nieuwenhuis, DCCN, FCDC -% Saskia Haegens, DCCN, FCDC -% -% Copyrights (C) 2008-2009, Donders Institute for Brain, Cognition and Behaviour, The Netherlands (DCCN, DCC, DCN) -% Copyrights (C) 2008-2009, Centre for Cognitive Neuroimaging in Glasgow, United Kingdom (CCNi) -% Copyrights (C) 2003-2008, F.C. Donders Centre, University Nijmegen, The Netherlands (FCDC) -% Copyrights (C) 2004-2007, Nijmegen Institute for Cognition and Information, The Netherlands (NICI) -% Copyrights (C) 2004-2005, Universitatsklinikum Hamburg-Eppendorf, Germany (UKE) -% Copyrights (C) 2003-2004, Center for Sensory Motor Interaction, University Aalborg, Denmark (SMI) -% Copyrights (C) 1999-2003, Department of Medical Physics, Radboud University Nijmegen, The Netherlands (MBFYS) -% -% The FieldTrip toolbox depend on functions from other toolboxes to do a -% large part of the actual work, such as reading data from binary files and -% forward and inverse modelling of the EEG/MEG. These low-level functions -% are contained in the private subdirectory. These other toolboxes on which -% the framework depends are copyrighted by their respective authors, see -% each individual matlab file for the details. -% -% Unauthorised copying and distribution of functions that are not -% explicitely covered by the GPL is not allowed! -% -% Below is an overview of the most important FieldTrip functions, sorted by -% category. You can get more details on a function by typing "help functionname" -% in Matlab. -% -% Preprocessing and reading data -% definetrial -% rejectartifact -% rejectvisual -% preprocessing -% appenddata -% resampledata -% channelrepair -% recodeevent -% redefinetrial -% read_fcdc_header -% read_fcdc_data -% read_fcdc_event -% read_fcdc_mri -% -% Event-Related Fields or Potentials -% timelockanalysis -% timelockgrandaverage -% timelockstatistics -% singleplotER -% topoplotER -% multiplotER -% -% Frequency and Time-Frequency analysis -% freqanalysis -% freqanalysis_mtmfft -% freqanalysis_mtmwelch -% freqanalysis_mtmconvol -% freqanalysis_wltconvol -% freqanalysis_tfr -% freqgrandaverage -% freqdescriptives -% freqstatistics -% singleplotTFR -% topoplotTFR -% multiplotTFR -% -% Source analysis -% dipolefitting -% dipolesimulation -% sourceanalysis -% sourcegrandaverage -% sourcedescriptives -% sourcestatistics -% sourceplot -% sourceinterpolate -% prepare_localspheres -% prepare_singleshell -% prepare_bemmodel -% prepare_leadfield -% prepare_atlas -% volumelookup -% -% Statistical analysis -% timelockstatistics -% freqstatistics -% sourcestatistics -% -% Plotting and display of data -% prepare_layout -% layoutplot -% topoplot -% topoplotER -% topoplotTFR -% multiplotER -% multiplotTFR -% singleplotER -% singleplotTFR -% sourceplot -% clusterplot - -% $Log: Contents.m,v $ -% Revision 1.11 2009/02/04 10:14:30 roboos -% updated -% -% Revision 1.10 2009/02/04 10:10:17 roboos -% updated copyrights, added list with main function names -% -% Revision 1.9 2007/05/30 06:53:29 roboos -% added Eric and Ingrid -% -% Revision 1.8 2006/07/04 16:14:24 roboos -% removed obsolete function list, clarified and cleaned up copyrights -% -% Revision 1.7 2005/06/02 12:23:20 roboos -% updated some of the descriptions, it is still not complete -% -% Revision 1.6 2004/02/04 14:00:13 roberto -% added Jens to authors and included his functions -% -% Revision 1.5 2004/01/27 10:20:08 roberto -% added combineplanar -% -% Revision 1.4 2004/01/21 16:09:03 roberto -% updated documentation -% -% Revision 1.3 2004/01/14 10:34:21 roberto -% added Markus Siegels functions and listed him as author -% -% Revision 1.2 2003/11/28 21:37:26 roberto -% updated help and function list -% -% Revision 1.1 2003/11/07 16:20:14 roberto -% updated contents with new functions -% - diff --git a/external/fieldtrip/private/EEG1005.lay b/external/fieldtrip/private/EEG1005.lay deleted file mode 100644 index a600468..0000000 --- a/external/fieldtrip/private/EEG1005.lay +++ /dev/null @@ -1,337 +0,0 @@ -1 -0.485328 1.493835 0.069221 0.051916 Fp1 -2 0.000000 1.570696 0.069221 0.051916 Fpz -3 0.485501 1.493884 0.069221 0.051916 Fp2 -4 -1.154207 1.588656 0.069221 0.051916 AF9 -5 -0.923319 1.270781 0.069221 0.051916 AF7 -6 -0.706117 1.226029 0.069221 0.051916 AF5 -7 -0.477022 1.197254 0.069221 0.051916 AF3 -8 -0.240008 1.182594 0.069221 0.051916 AF1 -9 0.000000 1.178022 0.069221 0.051916 AFz -10 0.240008 1.182594 0.069221 0.051916 AF2 -11 0.476904 1.197159 0.069221 0.051916 AF4 -12 0.706117 1.226029 0.069221 0.051916 AF6 -13 0.923319 1.270781 0.069221 0.051916 AF8 -14 1.154207 1.588656 0.069221 0.051916 AF10 -15 -1.588376 1.154294 0.069221 0.051916 F9 -16 -1.270781 0.923319 0.069221 0.051916 F7 -17 -0.968950 0.852434 0.069221 0.051916 F5 -18 -0.652084 0.812357 0.069221 0.051916 F3 -19 -0.327689 0.791876 0.069221 0.051916 F1 -20 0.000000 0.785398 0.069221 0.051916 Fz -21 0.327689 0.791876 0.069221 0.051916 F2 -22 0.652084 0.812357 0.069221 0.051916 F4 -23 0.968950 0.852434 0.069221 0.051916 F6 -24 1.270781 0.923319 0.069221 0.051916 F8 -25 1.588496 1.154168 0.069221 0.051916 F10 -26 -1.867677 0.606883 0.069221 0.051916 FT9 -27 -1.493930 0.485359 0.069221 0.051916 FT7 -28 -1.126134 0.436152 0.069221 0.051916 FC5 -29 -0.752811 0.409634 0.069221 0.051916 FC3 -30 -0.376942 0.396836 0.069221 0.051916 FC1 -31 0.000000 0.392844 0.069221 0.051916 FCz -32 0.376942 0.396836 0.069221 0.051916 FC2 -33 0.752811 0.409634 0.069221 0.051916 FC4 -34 1.126134 0.436152 0.069221 0.051916 FC6 -35 1.493930 0.485359 0.069221 0.051916 FT8 -36 1.867677 0.606883 0.069221 0.051916 FT10 -37 -1.963487 -0.000213 0.069221 0.051916 T9 -38 -1.570796 0.000000 0.069221 0.051916 T7 -39 -1.178106 0.000128 0.069221 0.051916 C5 -40 -0.785398 0.000111 0.069221 0.051916 C3 -41 -0.392736 0.000205 0.069221 0.051916 C1 -42 0.000000 0.000200 0.069221 0.051916 Cz -43 0.392736 0.000103 0.069221 0.051916 C2 -44 0.785398 0.000111 0.069221 0.051916 C4 -45 1.178106 0.000128 0.069221 0.051916 C6 -46 1.570796 -0.000000 0.069221 0.051916 T8 -47 1.963487 -0.000000 0.069221 0.051916 T10 -48 -1.867677 -0.606883 0.069221 0.051916 TP9 -49 -1.494026 -0.485389 0.069221 0.051916 TP7 -50 -1.126048 -0.435839 0.069221 0.051916 CP5 -51 -0.752775 -0.409460 0.069221 0.051916 CP3 -52 -0.376804 -0.396486 0.069221 0.051916 CP1 -53 -0.000000 -0.392551 0.069221 0.051916 CPz -54 0.376804 -0.396486 0.069221 0.051916 CP2 -55 0.752795 -0.409357 0.069221 0.051916 CP4 -56 1.126048 -0.435839 0.069221 0.051916 CP6 -57 1.494026 -0.485389 0.069221 0.051916 TP8 -58 1.867603 -0.607072 0.069221 0.051916 TP10 -59 -1.588496 -1.154168 0.069221 0.051916 P9 -60 -1.270862 -0.923378 0.069221 0.051916 P7 -61 -0.969077 -0.852293 0.069221 0.051916 P5 -62 -0.652231 -0.811998 0.069221 0.051916 P3 -63 -0.327776 -0.791360 0.069221 0.051916 P1 -64 -0.000000 -0.785257 0.069221 0.051916 Pz -65 0.327776 -0.791360 0.069221 0.051916 P2 -66 0.652231 -0.811998 0.069221 0.051916 P4 -67 0.969077 -0.852293 0.069221 0.051916 P6 -68 1.270862 -0.923378 0.069221 0.051916 P8 -69 1.588496 -1.154168 0.069221 0.051916 P10 -70 -1.154207 -1.588656 0.069221 0.051916 PO9 -71 -0.923319 -1.270781 0.069221 0.051916 PO7 -72 -0.706303 -1.225606 0.069221 0.051916 PO5 -73 -0.476710 -1.197888 0.069221 0.051916 PO3 -74 -0.240097 -1.182523 0.069221 0.051916 PO1 -75 -0.000000 -1.178022 0.069221 0.051916 POz -76 0.240223 -1.182505 0.069221 0.051916 PO2 -77 0.476710 -1.197888 0.069221 0.051916 PO4 -78 0.706303 -1.225606 0.069221 0.051916 PO6 -79 0.923319 -1.270781 0.069221 0.051916 PO8 -80 1.154207 -1.588656 0.069221 0.051916 PO10 -81 -0.485359 -1.493930 0.069221 0.051916 O1 -82 -0.000000 -1.570796 0.069221 0.051916 Oz -83 0.485359 -1.493930 0.069221 0.051916 O2 -84 -0.606613 -1.867239 0.069221 0.051916 I1 -85 -0.000000 -1.963478 0.069221 0.051916 Iz -86 0.606613 -1.867239 0.069221 0.051916 I2 -87 -0.802226 1.574520 0.069221 0.051916 AFp9h -88 -0.626475 1.393612 0.069221 0.051916 AFp7h -89 -0.451133 1.382849 0.069221 0.051916 AFp5h -90 -0.271959 1.376738 0.069221 0.051916 AFp3h -91 -0.090887 1.374548 0.069221 0.051916 AFp1h -92 0.090887 1.374548 0.069221 0.051916 AFp2h -93 0.271959 1.376738 0.069221 0.051916 AFp4h -94 0.451133 1.382849 0.069221 0.051916 AFp6h -95 0.626475 1.393612 0.069221 0.051916 AFp8h -96 0.802226 1.574520 0.069221 0.051916 AFp10h -97 -1.249550 1.249550 0.069221 0.051916 AFF9h -98 -0.982948 1.075122 0.069221 0.051916 AFF7h -99 -0.713694 1.024626 0.069221 0.051916 AFF5h -100 -0.432315 0.996167 0.069221 0.051916 AFF3h -101 -0.144727 0.983315 0.069221 0.051916 AFF1h -102 0.144727 0.983315 0.069221 0.051916 AFF2h -103 0.432315 0.996167 0.069221 0.051916 AFF4h -104 0.713694 1.024626 0.069221 0.051916 AFF6h -105 0.982881 1.075049 0.069221 0.051916 AFF8h -106 1.249550 1.249550 0.069221 0.051916 AFF10h -107 -1.574645 0.802293 0.069221 0.051916 FFT9h -108 -1.232019 0.675885 0.069221 0.051916 FFT7h -109 -0.886990 0.627578 0.069221 0.051916 FFC5h -110 -0.534535 0.601827 0.069221 0.051916 FFC3h -111 -0.178478 0.590622 0.069221 0.051916 FFC1h -112 0.178478 0.590622 0.069221 0.051916 FFC2h -113 0.534535 0.601827 0.069221 0.051916 FFC4h -114 0.886990 0.627578 0.069221 0.051916 FFC6h -115 1.232019 0.675885 0.069221 0.051916 FFT8h -116 1.574645 0.802293 0.069221 0.051916 FFT10h -117 -1.745475 0.276484 0.069221 0.051916 FTT9h -118 -1.358553 0.230430 0.069221 0.051916 FTT7h -119 -0.971386 0.211155 0.069221 0.051916 FCC5h -120 -0.583084 0.201295 0.069221 0.051916 FCC3h -121 -0.194460 0.196994 0.069221 0.051916 FCC1h -122 0.194460 0.196994 0.069221 0.051916 FCC2h -123 0.583084 0.201295 0.069221 0.051916 FCC4h -124 0.971386 0.211155 0.069221 0.051916 FCC6h -125 1.358553 0.230430 0.069221 0.051916 FTT8h -126 1.745475 0.276484 0.069221 0.051916 FTT10h -127 -1.745506 -0.276309 0.069221 0.051916 TTP9h -128 -1.358573 -0.230293 0.069221 0.051916 TTP7h -129 -0.971375 -0.211008 0.069221 0.051916 CCP5h -130 -0.583085 -0.200906 0.069221 0.051916 CCP3h -131 -0.194448 -0.196679 0.069221 0.051916 CCP1h -132 0.194448 -0.196679 0.069221 0.051916 CCP2h -133 0.583078 -0.201010 0.069221 0.051916 CCP4h -134 0.971375 -0.211008 0.069221 0.051916 CCP6h -135 1.358573 -0.230293 0.069221 0.051916 TTP8h -136 1.745475 -0.276484 0.069221 0.051916 TTP10h -137 -1.574667 -0.802213 0.069221 0.051916 TPP9h -138 -1.232021 -0.675979 0.069221 0.051916 TPP7h -139 -0.887025 -0.627306 0.069221 0.051916 CPP5h -140 -0.534524 -0.601312 0.069221 0.051916 CPP3h -141 -0.178473 -0.590144 0.069221 0.051916 CPP1h -142 0.178473 -0.590144 0.069221 0.051916 CPP2h -143 0.534524 -0.601312 0.069221 0.051916 CPP4h -144 0.887025 -0.627306 0.069221 0.051916 CPP6h -145 1.231976 -0.676032 0.069221 0.051916 TPP8h -146 1.574586 -0.802352 0.069221 0.051916 TPP10h -147 -1.249639 -1.249639 0.069221 0.051916 PPO9h -148 -0.983137 -1.074700 0.069221 0.051916 PPO7h -149 -0.713821 -1.024109 0.069221 0.051916 PPO5h -150 -0.432363 -0.995909 0.069221 0.051916 PPO3h -151 -0.144761 -0.982953 0.069221 0.051916 PPO1h -152 0.144761 -0.982953 0.069221 0.051916 PPO2h -153 0.432253 -0.995937 0.069221 0.051916 PPO4h -154 0.713967 -1.023998 0.069221 0.051916 PPO6h -155 0.983137 -1.074700 0.069221 0.051916 PPO8h -156 1.249639 -1.249639 0.069221 0.051916 PPO10h -157 -0.802293 -1.574645 0.069221 0.051916 POO9h -158 -0.626849 -1.393237 0.069221 0.051916 POO7h -159 -0.451236 -1.382715 0.069221 0.051916 POO5h -160 -0.271951 -1.377572 0.069221 0.051916 POO3h -161 -0.090910 -1.374606 0.069221 0.051916 POO1h -162 0.090910 -1.374606 0.069221 0.051916 POO2h -163 0.271951 -1.377572 0.069221 0.051916 POO4h -164 0.451236 -1.382715 0.069221 0.051916 POO6h -165 0.626849 -1.393237 0.069221 0.051916 POO8h -166 0.802293 -1.574645 0.069221 0.051916 POO10h -167 -0.276453 -1.745460 0.069221 0.051916 OI1h -168 0.276453 -1.745460 0.069221 0.051916 OI2h -169 -0.245655 1.551367 0.069221 0.051916 Fp1h -170 0.245655 1.551367 0.069221 0.051916 Fp2h -171 -1.038573 1.429729 0.069221 0.051916 AF9h -172 -0.816811 1.245775 0.069221 0.051916 AF7h -173 -0.592502 1.210176 0.069221 0.051916 AF5h -174 -0.359066 1.188527 0.069221 0.051916 AF3h -175 -0.120203 1.179114 0.069221 0.051916 AF1h -176 0.120212 1.179076 0.069221 0.051916 AF2h -177 0.359066 1.188527 0.069221 0.051916 AF4h -178 0.592545 1.210263 0.069221 0.051916 AF6h -179 0.816811 1.245775 0.069221 0.051916 AF8h -180 1.038668 1.429679 0.069221 0.051916 AF10h -181 -1.429588 1.038701 0.069221 0.051916 F9h -182 -1.122287 0.883303 0.069221 0.051916 F7h -183 -0.811863 0.829210 0.069221 0.051916 F5h -184 -0.490601 0.800049 0.069221 0.051916 F3h -185 -0.164017 0.787126 0.069221 0.051916 F1h -186 0.164017 0.787126 0.069221 0.051916 F2h -187 0.490601 0.800049 0.069221 0.051916 F4h -188 0.811863 0.829210 0.069221 0.051916 F6h -189 1.122287 0.883303 0.069221 0.051916 F8h -190 1.429588 1.038701 0.069221 0.051916 F10h -191 -1.680799 0.546075 0.069221 0.051916 FT9h -192 -1.310995 0.457012 0.069221 0.051916 FT7h -193 -0.939857 0.420814 0.069221 0.051916 FC5h -194 -0.565142 0.401905 0.069221 0.051916 FC3h -195 -0.188491 0.393826 0.069221 0.051916 FC1h -196 0.188491 0.393826 0.069221 0.051916 FC2h -197 0.565142 0.401905 0.069221 0.051916 FC4h -198 0.939857 0.420814 0.069221 0.051916 FC6h -199 1.310995 0.457012 0.069221 0.051916 FT8h -200 1.680740 0.546236 0.069221 0.051916 FT10h -201 -1.767191 0.000000 0.069221 0.051916 T9h -202 -1.374500 0.000000 0.069221 0.051916 T7h -203 -0.981850 0.000118 0.069221 0.051916 C5h -204 -0.589058 0.000212 0.069221 0.051916 C3h -205 -0.196395 0.000101 0.069221 0.051916 C1h -206 0.196395 0.000201 0.069221 0.051916 C2h -207 0.589058 0.000212 0.069221 0.051916 C4h -208 0.981850 0.000118 0.069221 0.051916 C6h -209 1.374500 -0.000000 0.069221 0.051916 T8h -210 1.767191 -0.000000 0.069221 0.051916 T10h -211 -1.680646 -0.546088 0.069221 0.051916 TP9h -212 -1.310970 -0.456960 0.069221 0.051916 TP7h -213 -0.939815 -0.420500 0.069221 0.051916 CP5h -214 -0.565062 -0.401491 0.069221 0.051916 CP3h -215 -0.188515 -0.393352 0.069221 0.051916 CP1h -216 0.188515 -0.393352 0.069221 0.051916 CP2h -217 0.565062 -0.401491 0.069221 0.051916 CP4h -218 0.939815 -0.420500 0.069221 0.051916 CP6h -219 1.310970 -0.456960 0.069221 0.051916 TP8h -220 1.680646 -0.546088 0.069221 0.051916 TP10h -221 -1.429668 -1.038758 0.069221 0.051916 P9h -222 -1.122286 -0.883271 0.069221 0.051916 P7h -223 -0.812037 -0.829137 0.069221 0.051916 P5h -224 -0.490726 -0.799336 0.069221 0.051916 P3h -225 -0.164146 -0.786762 0.069221 0.051916 P1h -226 0.164146 -0.786762 0.069221 0.051916 P2h -227 0.490600 -0.799436 0.069221 0.051916 P4h -228 0.812037 -0.829137 0.069221 0.051916 P6h -229 1.122286 -0.883271 0.069221 0.051916 P8h -230 1.429668 -1.038758 0.069221 0.051916 P10h -231 -1.038821 -1.429709 0.069221 0.051916 PO9h -232 -0.816502 -1.246067 0.069221 0.051916 PO7h -233 -0.593079 -1.209372 0.069221 0.051916 PO5h -234 -0.359230 -1.188332 0.069221 0.051916 PO3h -235 -0.120221 -1.179168 0.069221 0.051916 PO1h -236 0.120348 -1.179159 0.069221 0.051916 PO2h -237 0.359230 -1.188332 0.069221 0.051916 PO4h -238 0.593079 -1.209372 0.069221 0.051916 PO6h -239 0.816502 -1.246067 0.069221 0.051916 PO8h -240 1.038710 -1.429804 0.069221 0.051916 PO10h -241 -0.245671 -1.551466 0.069221 0.051916 O1h -242 0.245671 -1.551466 0.069221 0.051916 O2h -243 -0.307129 -1.939338 0.069221 0.051916 I1h -244 0.307129 -1.939338 0.069221 0.051916 I2h -245 -0.891328 1.749684 0.069221 0.051916 AFp9 -246 -0.713143 1.399582 0.069221 0.051916 AFp7 -247 -0.539182 1.387878 0.069221 0.051916 AFp5 -248 -0.361777 1.379743 0.069221 0.051916 AFp3 -249 -0.181624 1.374948 0.069221 0.051916 AFp1 -250 0.000000 1.374461 0.069221 0.051916 AFpz -251 0.181624 1.374948 0.069221 0.051916 AFp2 -252 0.361802 1.379839 0.069221 0.051916 AFp4 -253 0.539182 1.387878 0.069221 0.051916 AFp6 -254 0.713143 1.399582 0.069221 0.051916 AFp8 -255 0.891489 1.749582 0.069221 0.051916 AFp10 -256 -1.388504 1.388504 0.069221 0.051916 AFF9 -257 -1.110721 1.110721 0.069221 0.051916 AFF7 -258 -0.850463 1.046170 0.069221 0.051916 AFF5 -259 -0.574170 1.008058 0.069221 0.051916 AFF3 -260 -0.288981 0.988233 0.069221 0.051916 AFF1 -261 0.000000 0.981739 0.069221 0.051916 AFFz -262 0.288981 0.988233 0.069221 0.051916 AFF2 -263 0.574170 1.008058 0.069221 0.051916 AFF4 -264 0.850463 1.046170 0.069221 0.051916 AFF6 -265 1.110721 1.110721 0.069221 0.051916 AFF8 -266 1.388504 1.388504 0.069221 0.051916 AFF10 -267 -1.749576 0.891591 0.069221 0.051916 FFT9 -268 -1.399582 0.713143 0.069221 0.051916 FFT7 -269 -1.060830 0.648168 0.069221 0.051916 FFC5 -270 -0.711350 0.612390 0.069221 0.051916 FFC3 -271 -0.356750 0.594619 0.069221 0.051916 FFC1 -272 0.000000 0.589085 0.069221 0.051916 FFCz -273 0.356750 0.594619 0.069221 0.051916 FFC2 -274 0.711350 0.612390 0.069221 0.051916 FFC4 -275 1.060749 0.648119 0.069221 0.051916 FFC6 -276 1.399582 0.713143 0.069221 0.051916 FFT8 -277 1.749576 0.891591 0.069221 0.051916 FFT10 -278 -1.939489 0.307119 0.069221 0.051916 FTT9 -279 -1.551442 0.245824 0.069221 0.051916 FTT7 -280 -1.165132 0.219351 0.069221 0.051916 FCC5 -281 -0.777319 0.205363 0.069221 0.051916 FCC3 -282 -0.388766 0.198515 0.069221 0.051916 FCC1 -283 0.000000 0.196434 0.069221 0.051916 FCCz -284 0.388766 0.198515 0.069221 0.051916 FCC2 -285 0.777319 0.205363 0.069221 0.051916 FCC4 -286 1.165132 0.219351 0.069221 0.051916 FCC6 -287 1.551466 0.245671 0.069221 0.051916 FTT8 -288 1.939489 0.307119 0.069221 0.051916 FTT10 -289 -1.939553 -0.307197 0.069221 0.051916 TTP9 -290 -1.551565 -0.245687 0.069221 0.051916 TTP7 -291 -1.165206 -0.219084 0.069221 0.051916 CCP5 -292 -0.777275 -0.205069 0.069221 0.051916 CCP3 -293 -0.388806 -0.198175 0.069221 0.051916 CCP1 -294 -0.000000 -0.196218 0.069221 0.051916 CCPz -295 0.388801 -0.198275 0.069221 0.051916 CCP2 -296 0.777275 -0.205069 0.069221 0.051916 CCP4 -297 1.165206 -0.219084 0.069221 0.051916 CCP6 -298 1.551565 -0.245687 0.069221 0.051916 TTP8 -299 1.939553 -0.307197 0.069221 0.051916 TTP10 -300 -1.749664 -0.891531 0.069221 0.051916 TPP9 -301 -1.399671 -0.713188 0.069221 0.051916 TPP7 -302 -1.060852 -0.647970 0.069221 0.051916 CPP5 -303 -0.711356 -0.612379 0.069221 0.051916 CPP3 -304 -0.356663 -0.594548 0.069221 0.051916 CPP1 -305 -0.000000 -0.588863 0.069221 0.051916 CPPz -306 0.356778 -0.594448 0.069221 0.051916 CPP2 -307 0.711384 -0.612287 0.069221 0.051916 CPP4 -308 1.060852 -0.647970 0.069221 0.051916 CPP6 -309 1.399671 -0.713188 0.069221 0.051916 TPP8 -310 1.749664 -0.891531 0.069221 0.051916 TPP10 -311 -1.388427 -1.388427 0.069221 0.051916 PPO9 -312 -1.110721 -1.110721 0.069221 0.051916 PPO7 -313 -0.850511 -1.046155 0.069221 0.051916 PPO5 -314 -0.574228 -1.007462 0.069221 0.051916 PPO3 -315 -0.289055 -0.987715 0.069221 0.051916 PPO1 -316 -0.000000 -0.981655 0.069221 0.051916 PPOz -317 0.289055 -0.987715 0.069221 0.051916 PPO2 -318 0.574228 -1.007462 0.069221 0.051916 PPO4 -319 0.850454 -1.046223 0.069221 0.051916 PPO6 -320 1.110721 -1.110721 0.069221 0.051916 PPO8 -321 1.388427 -1.388427 0.069221 0.051916 PPO10 -322 -0.891143 -1.749540 0.069221 0.051916 POO9 -323 -0.713143 -1.399582 0.069221 0.051916 POO7 -324 -0.539360 -1.387717 0.069221 0.051916 POO5 -325 -0.362020 -1.379310 0.069221 0.051916 POO3 -326 -0.181486 -1.375484 0.069221 0.051916 POO1 -327 -0.000000 -1.374422 0.069221 0.051916 POOz -328 0.181626 -1.375468 0.069221 0.051916 POO2 -329 0.362020 -1.379310 0.069221 0.051916 POO4 -330 0.539360 -1.387717 0.069221 0.051916 POO6 -331 0.713143 -1.399582 0.069221 0.051916 POO8 -332 0.891143 -1.749540 0.069221 0.051916 POO10 -333 -0.546073 -1.680586 0.069221 0.051916 OI1 -334 -0.000000 -1.767132 0.069221 0.051916 OIz -335 0.546073 -1.680586 0.069221 0.051916 OI2 -336 -1.963487 1.749684 0.069221 0.051916 COMNT -337 1.963487 1.749684 0.069221 0.051916 SCALE diff --git a/external/fieldtrip/private/EEG1010.lay b/external/fieldtrip/private/EEG1010.lay deleted file mode 100644 index 4111a04..0000000 --- a/external/fieldtrip/private/EEG1010.lay +++ /dev/null @@ -1,88 +0,0 @@ -1 -0.485328 1.493835 0.177334 0.133001 Fp1 -2 0.000000 1.570696 0.177334 0.133001 Fpz -3 0.485501 1.493884 0.177334 0.133001 Fp2 -4 -1.154207 1.588656 0.177334 0.133001 AF9 -5 -0.923319 1.270781 0.177334 0.133001 AF7 -6 -0.706117 1.226029 0.177334 0.133001 AF5 -7 -0.477022 1.197254 0.177334 0.133001 AF3 -8 -0.240008 1.182594 0.177334 0.133001 AF1 -9 0.000000 1.178022 0.177334 0.133001 AFz -10 0.240008 1.182594 0.177334 0.133001 AF2 -11 0.476904 1.197159 0.177334 0.133001 AF4 -12 0.706117 1.226029 0.177334 0.133001 AF6 -13 0.923319 1.270781 0.177334 0.133001 AF8 -14 1.154207 1.588656 0.177334 0.133001 AF10 -15 -1.588376 1.154294 0.177334 0.133001 F9 -16 -1.270781 0.923319 0.177334 0.133001 F7 -17 -0.968950 0.852434 0.177334 0.133001 F5 -18 -0.652084 0.812357 0.177334 0.133001 F3 -19 -0.327689 0.791876 0.177334 0.133001 F1 -20 0.000000 0.785398 0.177334 0.133001 Fz -21 0.327689 0.791876 0.177334 0.133001 F2 -22 0.652084 0.812357 0.177334 0.133001 F4 -23 0.968950 0.852434 0.177334 0.133001 F6 -24 1.270781 0.923319 0.177334 0.133001 F8 -25 1.588496 1.154168 0.177334 0.133001 F10 -26 -1.867677 0.606883 0.177334 0.133001 FT9 -27 -1.493930 0.485359 0.177334 0.133001 FT7 -28 -1.126134 0.436152 0.177334 0.133001 FC5 -29 -0.752811 0.409634 0.177334 0.133001 FC3 -30 -0.376942 0.396836 0.177334 0.133001 FC1 -31 0.000000 0.392844 0.177334 0.133001 FCz -32 0.376942 0.396836 0.177334 0.133001 FC2 -33 0.752811 0.409634 0.177334 0.133001 FC4 -34 1.126134 0.436152 0.177334 0.133001 FC6 -35 1.493930 0.485359 0.177334 0.133001 FT8 -36 1.867677 0.606883 0.177334 0.133001 FT10 -37 -1.963487 -0.000213 0.177334 0.133001 T9 -38 -1.570796 0.000000 0.177334 0.133001 T7 -39 -1.178106 0.000128 0.177334 0.133001 C5 -40 -0.785398 0.000111 0.177334 0.133001 C3 -41 -0.392736 0.000205 0.177334 0.133001 C1 -42 0.000000 0.000200 0.177334 0.133001 Cz -43 0.392736 0.000103 0.177334 0.133001 C2 -44 0.785398 0.000111 0.177334 0.133001 C4 -45 1.178106 0.000128 0.177334 0.133001 C6 -46 1.570796 -0.000000 0.177334 0.133001 T8 -47 1.963487 -0.000000 0.177334 0.133001 T10 -48 -1.867677 -0.606883 0.177334 0.133001 TP9 -49 -1.494026 -0.485389 0.177334 0.133001 TP7 -50 -1.126048 -0.435839 0.177334 0.133001 CP5 -51 -0.752775 -0.409460 0.177334 0.133001 CP3 -52 -0.376804 -0.396486 0.177334 0.133001 CP1 -53 -0.000000 -0.392551 0.177334 0.133001 CPz -54 0.376804 -0.396486 0.177334 0.133001 CP2 -55 0.752795 -0.409357 0.177334 0.133001 CP4 -56 1.126048 -0.435839 0.177334 0.133001 CP6 -57 1.494026 -0.485389 0.177334 0.133001 TP8 -58 1.867603 -0.607072 0.177334 0.133001 TP10 -59 -1.588496 -1.154168 0.177334 0.133001 P9 -60 -1.270862 -0.923378 0.177334 0.133001 P7 -61 -0.969077 -0.852293 0.177334 0.133001 P5 -62 -0.652231 -0.811998 0.177334 0.133001 P3 -63 -0.327776 -0.791360 0.177334 0.133001 P1 -64 -0.000000 -0.785257 0.177334 0.133001 Pz -65 0.327776 -0.791360 0.177334 0.133001 P2 -66 0.652231 -0.811998 0.177334 0.133001 P4 -67 0.969077 -0.852293 0.177334 0.133001 P6 -68 1.270862 -0.923378 0.177334 0.133001 P8 -69 1.588496 -1.154168 0.177334 0.133001 P10 -70 -1.154207 -1.588656 0.177334 0.133001 PO9 -71 -0.923319 -1.270781 0.177334 0.133001 PO7 -72 -0.706303 -1.225606 0.177334 0.133001 PO5 -73 -0.476710 -1.197888 0.177334 0.133001 PO3 -74 -0.240097 -1.182523 0.177334 0.133001 PO1 -75 -0.000000 -1.178022 0.177334 0.133001 POz -76 0.240223 -1.182505 0.177334 0.133001 PO2 -77 0.476710 -1.197888 0.177334 0.133001 PO4 -78 0.706303 -1.225606 0.177334 0.133001 PO6 -79 0.923319 -1.270781 0.177334 0.133001 PO8 -80 1.154207 -1.588656 0.177334 0.133001 PO10 -81 -0.485359 -1.493930 0.177334 0.133001 O1 -82 -0.000000 -1.570796 0.177334 0.133001 Oz -83 0.485359 -1.493930 0.177334 0.133001 O2 -84 -0.606613 -1.867239 0.177334 0.133001 I1 -85 -0.000000 -1.963478 0.177334 0.133001 Iz -86 0.606613 -1.867239 0.177334 0.133001 I2 -87 -1.963487 1.588656 0.177334 0.133001 COMNT -88 1.963487 1.588656 0.177334 0.133001 SCALE diff --git a/external/fieldtrip/private/EEG1020.lay b/external/fieldtrip/private/EEG1020.lay deleted file mode 100644 index 9907888..0000000 --- a/external/fieldtrip/private/EEG1020.lay +++ /dev/null @@ -1,23 +0,0 @@ -1 -0.485328 1.493835 0.393101 0.294826 Fp1 -2 0.000000 1.570696 0.393101 0.294826 Fpz -3 0.485501 1.493884 0.393101 0.294826 Fp2 -4 -1.270781 0.923319 0.393101 0.294826 F7 -5 -0.652084 0.812357 0.393101 0.294826 F3 -6 0.000000 0.785398 0.393101 0.294826 Fz -7 0.652084 0.812357 0.393101 0.294826 F4 -8 1.270781 0.923319 0.393101 0.294826 F8 -9 -1.570796 0.000000 0.393101 0.294826 T7 -10 -0.785398 0.000111 0.393101 0.294826 C3 -11 0.000000 0.000200 0.393101 0.294826 Cz -12 0.785398 0.000111 0.393101 0.294826 C4 -13 1.570796 -0.000000 0.393101 0.294826 T8 -14 -1.270862 -0.923378 0.393101 0.294826 P7 -15 -0.652231 -0.811998 0.393101 0.294826 P3 -16 -0.000000 -0.785257 0.393101 0.294826 Pz -17 0.652231 -0.811998 0.393101 0.294826 P4 -18 1.270862 -0.923378 0.393101 0.294826 P8 -19 -0.485359 -1.493930 0.393101 0.294826 O1 -20 -0.000000 -1.570796 0.393101 0.294826 Oz -21 0.485359 -1.493930 0.393101 0.294826 O2 -22 -1.570796 1.570696 0.393101 0.294826 COMNT -23 1.570796 1.570696 0.393101 0.294826 SCALE diff --git a/external/fieldtrip/private/LoadSpikes.m b/external/fieldtrip/private/LoadSpikes.m new file mode 100644 index 0000000..71a83d3 --- /dev/null +++ b/external/fieldtrip/private/LoadSpikes.m @@ -0,0 +1,73 @@ +function S = LoadSpikes(tfilelist,varargin) +% +% S = LoadSpikes(tfilelist) +% +% inp: tfilelist is a cellarray of strings, each of which is a +% tfile to open. Note: this is incompatible with version unix3.1. +% out: Returns a cell array such that each cell contains a ts +% object (timestamps which correspond to times at which the cell fired) + +% ADR 1998 +% version L4.0 +% status: PROMOTED + +tsflag = 'sec'; +display = 1; + +try +extract_varargin; +end + +%------------------- +% Check input type +%------------------- +if ~isa(tfilelist, 'cell') + error('LoadSpikes: tfilelist should be a cell array.'); +end + +nFiles = length(tfilelist); + +%-------------------- +% Read files +%-------------------- + +%fprintf(2, 'Reading %d files.', nFiles); + +% for each tfile +% first read the header, the read a tfile +% note: uses the bigendian modifier to ensure correct read format. + +S = cell(nFiles, 1); +for iF = 1:nFiles +% if display +% DisplayProgress(iF, nFiles, 'Title', 'LoadSpikes'); +% end + tfn = tfilelist{iF}; + if ~isempty(tfn) + tfp = fopen(tfn, 'rb','ieee-be'); + if (tfp == -1) + warning([ 'Could not open tfile ' tfn]); + end + + ReadHeader(tfp); + S{iF} = fread(tfp,inf,'uint32'); %read as 32 bit ints + + % Set appropriate time units. + switch (tsflag) + case 'sec' + S{iF} = S{iF}/10000; + case 'ts' + S{iF} = S{iF}; + case 'ms' + S{iF} = S{iF}*10000*1000; + otherwise + error('LoadSpikes called with invalid tsflag.'); + end + +% S{iF} = ts(S{iF}); + + fclose(tfp); + + end % if tfn valid +end % for all files +fprintf(2,'\n'); diff --git a/external/fieldtrip/private/NM122.lay b/external/fieldtrip/private/NM122.lay deleted file mode 100644 index 34ac3dc..0000000 --- a/external/fieldtrip/private/NM122.lay +++ /dev/null @@ -1,122 +0,0 @@ -1 25.381295 -0.771781 2.000000 1.500000 MEG 001 -2 25.381295 0.727697 2.000000 1.500000 MEG 002 -3 22.715372 -0.733246 2.000000 1.500000 MEG 003 -4 22.715372 0.766753 2.000000 1.500000 MEG 004 -5 19.911143 -0.608748 2.000000 1.500000 MEG 005 -6 19.911143 0.891252 2.000000 1.500000 MEG 006 -7 24.481102 4.347077 2.000000 1.500000 MEG 007 -8 24.481102 5.847077 2.000000 1.500000 MEG 008 -9 21.967300 3.613717 2.000000 1.500000 MEG 009 -10 21.967300 5.113717 2.000000 1.500000 MEG 010 -11 19.345958 3.110359 2.000000 1.500000 MEG 011 -12 19.345958 4.610058 2.000000 1.500000 MEG 012 -13 16.706588 2.875744 2.000000 1.500000 MEG 013 -14 16.706588 4.375643 2.000000 1.500000 MEG 014 -15 14.090470 2.753697 2.000000 1.500000 MEG 015 -16 14.090470 4.253697 2.000000 1.500000 MEG 016 -17 19.559995 7.243332 2.000000 1.500000 MEG 017 -18 19.559995 8.743163 2.000000 1.500000 MEG 018 -19 16.942979 6.237191 2.000000 1.500000 MEG 019 -20 16.942979 7.737225 2.000000 1.500000 MEG 020 -21 14.204774 5.792745 2.000000 1.500000 MEG 021 -22 14.204774 7.292858 2.000000 1.500000 MEG 022 -23 11.500000 5.704290 2.000000 1.500000 MEG 023 -24 11.500000 7.204446 2.000000 1.500000 MEG 024 -25 16.662514 9.878430 2.000000 1.500000 MEG 025 -26 16.662514 11.378430 2.000000 1.500000 MEG 026 -27 13.466339 11.859999 2.000000 1.500000 MEG 027 -28 13.466339 13.359952 2.000000 1.500000 MEG 028 -29 13.450371 8.807222 2.000000 1.500000 MEG 029 -30 13.450371 10.307518 2.000000 1.500000 MEG 030 -31 9.533661 11.859999 2.000000 1.500000 MEG 031 -32 9.533661 13.359952 2.000000 1.500000 MEG 032 -33 9.549630 8.807222 2.000000 1.500000 MEG 033 -34 9.549630 10.307518 2.000000 1.500000 MEG 034 -35 6.337486 9.878430 2.000000 1.500000 MEG 035 -36 6.337486 11.378430 2.000000 1.500000 MEG 036 -37 3.440005 7.243332 2.000000 1.500000 MEG 037 -38 3.440005 8.743163 2.000000 1.500000 MEG 038 -39 6.057021 6.237192 2.000000 1.500000 MEG 039 -40 6.057021 7.737225 2.000000 1.500000 MEG 040 -41 8.795226 5.792745 2.000000 1.500000 MEG 041 -42 8.795226 7.292858 2.000000 1.500000 MEG 042 -43 -1.481102 4.347078 2.000000 1.500000 MEG 043 -44 -1.481102 5.847078 2.000000 1.500000 MEG 044 -45 1.032700 3.613581 2.000000 1.500000 MEG 045 -46 1.032700 5.113717 2.000000 1.500000 MEG 046 -47 3.654042 3.110360 2.000000 1.500000 MEG 047 -48 3.654042 4.610058 2.000000 1.500000 MEG 048 -49 6.293412 2.875744 2.000000 1.500000 MEG 049 -50 6.293412 4.375643 2.000000 1.500000 MEG 050 -51 8.909530 2.753697 2.000000 1.500000 MEG 051 -52 8.909530 4.253697 2.000000 1.500000 MEG 052 -53 11.500000 2.731327 2.000000 1.500000 MEG 053 -54 11.500000 4.231464 2.000000 1.500000 MEG 054 -55 -2.381295 -0.771781 2.000000 1.500000 MEG 055 -56 -2.381295 0.727697 2.000000 1.500000 MEG 056 -57 0.284628 -0.733246 2.000000 1.500000 MEG 057 -58 0.284628 0.766753 2.000000 1.500000 MEG 058 -59 3.088857 -0.608748 2.000000 1.500000 MEG 059 -60 3.088857 0.891252 2.000000 1.500000 MEG 060 -61 5.895393 -0.521429 2.000000 1.500000 MEG 061 -62 5.895393 0.978571 2.000000 1.500000 MEG 062 -63 8.696664 -0.481488 2.000000 1.500000 MEG 063 -64 8.696664 1.018793 2.000000 1.500000 MEG 064 -65 11.500000 -0.463140 2.000000 1.500000 MEG 065 -66 11.500000 1.036853 2.000000 1.500000 MEG 066 -67 -1.590015 -6.177621 2.000000 1.500000 MEG 067 -68 -1.590015 -4.677286 2.000000 1.500000 MEG 068 -69 0.893853 -5.313065 2.000000 1.500000 MEG 069 -70 0.893853 -3.813065 2.000000 1.500000 MEG 070 -71 3.788197 -4.494587 2.000000 1.500000 MEG 071 -72 3.788197 -2.994811 2.000000 1.500000 MEG 072 -73 6.749538 -3.954580 2.000000 1.500000 MEG 073 -74 6.749538 -2.454261 2.000000 1.500000 MEG 074 -75 1.096738 -10.894836 2.000000 1.500000 MEG 075 -76 1.096738 -9.394836 2.000000 1.500000 MEG 076 -77 3.402274 -9.346367 2.000000 1.500000 MEG 077 -78 3.402274 -7.846579 2.000000 1.500000 MEG 078 -79 6.182132 -8.131419 2.000000 1.500000 MEG 079 -80 6.182132 -6.631304 2.000000 1.500000 MEG 080 -81 6.102499 -15.409053 2.000000 1.500000 MEG 081 -82 6.102499 -13.908834 2.000000 1.500000 MEG 082 -83 6.914234 -12.406122 2.000000 1.500000 MEG 083 -84 6.914234 -10.906034 2.000000 1.500000 MEG 084 -85 9.307503 -10.644013 2.000000 1.500000 MEG 085 -86 9.307503 -9.143762 2.000000 1.500000 MEG 086 -87 9.660984 -7.199067 2.000000 1.500000 MEG 087 -88 9.660984 -5.699067 2.000000 1.500000 MEG 088 -89 9.807536 -3.822648 2.000000 1.500000 MEG 089 -90 9.807536 -2.322552 2.000000 1.500000 MEG 090 -91 11.500000 -16.259918 2.000000 1.500000 MEG 091 -92 11.500000 -14.759918 2.000000 1.500000 MEG 092 -93 11.500000 -13.097164 2.000000 1.500000 MEG 093 -94 11.500000 -11.597439 2.000000 1.500000 MEG 094 -95 13.692497 -10.644013 2.000000 1.500000 MEG 095 -96 13.692497 -9.143762 2.000000 1.500000 MEG 096 -97 13.339016 -7.199067 2.000000 1.500000 MEG 097 -98 13.339016 -5.699067 2.000000 1.500000 MEG 098 -99 13.192464 -3.822648 2.000000 1.500000 MEG 099 -100 13.192464 -2.322552 2.000000 1.500000 MEG 100 -101 16.897501 -15.409053 2.000000 1.500000 MEG 101 -102 16.897501 -13.908834 2.000000 1.500000 MEG 102 -103 16.085766 -12.406122 2.000000 1.500000 MEG 103 -104 16.085766 -10.906034 2.000000 1.500000 MEG 104 -105 21.903262 -10.894836 2.000000 1.500000 MEG 105 -106 21.903262 -9.394836 2.000000 1.500000 MEG 106 -107 19.597726 -9.346367 2.000000 1.500000 MEG 107 -108 19.597726 -7.846579 2.000000 1.500000 MEG 108 -109 16.817868 -8.131419 2.000000 1.500000 MEG 109 -110 16.817868 -6.631304 2.000000 1.500000 MEG 110 -111 24.590015 -6.177621 2.000000 1.500000 MEG 111 -112 24.590015 -4.677286 2.000000 1.500000 MEG 112 -113 22.106147 -5.313065 2.000000 1.500000 MEG 113 -114 22.106147 -3.813065 2.000000 1.500000 MEG 114 -115 19.211802 -4.494588 2.000000 1.500000 MEG 115 -116 19.211802 -2.994811 2.000000 1.500000 MEG 116 -117 16.250462 -3.954580 2.000000 1.500000 MEG 117 -118 16.250462 -2.454261 2.000000 1.500000 MEG 118 -119 17.104607 -0.521429 2.000000 1.500000 MEG 119 -120 17.104607 0.978571 2.000000 1.500000 MEG 120 -121 14.303336 -0.481488 2.000000 1.500000 MEG 121 -122 14.303336 1.018792 2.000000 1.500000 MEG 122 diff --git a/external/fieldtrip/private/NM122all.lay b/external/fieldtrip/private/NM122all.lay deleted file mode 100644 index 45437f2..0000000 --- a/external/fieldtrip/private/NM122all.lay +++ /dev/null @@ -1,122 +0,0 @@ -1 25.381295 -0.771781 2.000000 1.500000 001 -2 25.381295 0.727697 2.000000 1.500000 002 -3 22.715372 -0.733246 2.000000 1.500000 003 -4 22.715372 0.766753 2.000000 1.500000 004 -5 19.911143 -0.608748 2.000000 1.500000 005 -6 19.911143 0.891252 2.000000 1.500000 006 -7 24.481102 4.347077 2.000000 1.500000 007 -8 24.481102 5.847077 2.000000 1.500000 008 -9 21.967300 3.613717 2.000000 1.500000 009 -10 21.967300 5.113717 2.000000 1.500000 010 -11 19.345958 3.110359 2.000000 1.500000 011 -12 19.345958 4.610058 2.000000 1.500000 012 -13 16.706588 2.875744 2.000000 1.500000 013 -14 16.706588 4.375643 2.000000 1.500000 014 -15 14.090470 2.753697 2.000000 1.500000 015 -16 14.090470 4.253697 2.000000 1.500000 016 -17 19.559995 7.243332 2.000000 1.500000 017 -18 19.559995 8.743163 2.000000 1.500000 018 -19 16.942979 6.237191 2.000000 1.500000 019 -20 16.942979 7.737225 2.000000 1.500000 020 -21 14.204774 5.792745 2.000000 1.500000 021 -22 14.204774 7.292858 2.000000 1.500000 022 -23 11.500000 5.704290 2.000000 1.500000 023 -24 11.500000 7.204446 2.000000 1.500000 024 -25 16.662514 9.878430 2.000000 1.500000 025 -26 16.662514 11.378430 2.000000 1.500000 026 -27 13.466339 11.859999 2.000000 1.500000 027 -28 13.466339 13.359952 2.000000 1.500000 028 -29 13.450371 8.807222 2.000000 1.500000 029 -30 13.450371 10.307518 2.000000 1.500000 030 -31 9.533661 11.859999 2.000000 1.500000 031 -32 9.533661 13.359952 2.000000 1.500000 032 -33 9.549630 8.807222 2.000000 1.500000 033 -34 9.549630 10.307518 2.000000 1.500000 034 -35 6.337486 9.878430 2.000000 1.500000 035 -36 6.337486 11.378430 2.000000 1.500000 036 -37 3.440005 7.243332 2.000000 1.500000 037 -38 3.440005 8.743163 2.000000 1.500000 038 -39 6.057021 6.237192 2.000000 1.500000 039 -40 6.057021 7.737225 2.000000 1.500000 040 -41 8.795226 5.792745 2.000000 1.500000 041 -42 8.795226 7.292858 2.000000 1.500000 042 -43 -1.481102 4.347078 2.000000 1.500000 043 -44 -1.481102 5.847078 2.000000 1.500000 044 -45 1.032700 3.613581 2.000000 1.500000 045 -46 1.032700 5.113717 2.000000 1.500000 046 -47 3.654042 3.110360 2.000000 1.500000 047 -48 3.654042 4.610058 2.000000 1.500000 048 -49 6.293412 2.875744 2.000000 1.500000 049 -50 6.293412 4.375643 2.000000 1.500000 050 -51 8.909530 2.753697 2.000000 1.500000 051 -52 8.909530 4.253697 2.000000 1.500000 052 -53 11.500000 2.731327 2.000000 1.500000 053 -54 11.500000 4.231464 2.000000 1.500000 054 -55 -2.381295 -0.771781 2.000000 1.500000 055 -56 -2.381295 0.727697 2.000000 1.500000 056 -57 0.284628 -0.733246 2.000000 1.500000 057 -58 0.284628 0.766753 2.000000 1.500000 058 -59 3.088857 -0.608748 2.000000 1.500000 059 -60 3.088857 0.891252 2.000000 1.500000 060 -61 5.895393 -0.521429 2.000000 1.500000 061 -62 5.895393 0.978571 2.000000 1.500000 062 -63 8.696664 -0.481488 2.000000 1.500000 063 -64 8.696664 1.018793 2.000000 1.500000 064 -65 11.500000 -0.463140 2.000000 1.500000 065 -66 11.500000 1.036853 2.000000 1.500000 066 -67 -1.590015 -6.177621 2.000000 1.500000 067 -68 -1.590015 -4.677286 2.000000 1.500000 068 -69 0.893853 -5.313065 2.000000 1.500000 069 -70 0.893853 -3.813065 2.000000 1.500000 070 -71 3.788197 -4.494587 2.000000 1.500000 071 -72 3.788197 -2.994811 2.000000 1.500000 072 -73 6.749538 -3.954580 2.000000 1.500000 073 -74 6.749538 -2.454261 2.000000 1.500000 074 -75 1.096738 -10.894836 2.000000 1.500000 075 -76 1.096738 -9.394836 2.000000 1.500000 076 -77 3.402274 -9.346367 2.000000 1.500000 077 -78 3.402274 -7.846579 2.000000 1.500000 078 -79 6.182132 -8.131419 2.000000 1.500000 079 -80 6.182132 -6.631304 2.000000 1.500000 080 -81 6.102499 -15.409053 2.000000 1.500000 081 -82 6.102499 -13.908834 2.000000 1.500000 082 -83 6.914234 -12.406122 2.000000 1.500000 083 -84 6.914234 -10.906034 2.000000 1.500000 084 -85 9.307503 -10.644013 2.000000 1.500000 085 -86 9.307503 -9.143762 2.000000 1.500000 086 -87 9.660984 -7.199067 2.000000 1.500000 087 -88 9.660984 -5.699067 2.000000 1.500000 088 -89 9.807536 -3.822648 2.000000 1.500000 089 -90 9.807536 -2.322552 2.000000 1.500000 090 -91 11.500000 -16.259918 2.000000 1.500000 091 -92 11.500000 -14.759918 2.000000 1.500000 092 -93 11.500000 -13.097164 2.000000 1.500000 093 -94 11.500000 -11.597439 2.000000 1.500000 094 -95 13.692497 -10.644013 2.000000 1.500000 095 -96 13.692497 -9.143762 2.000000 1.500000 096 -97 13.339016 -7.199067 2.000000 1.500000 097 -98 13.339016 -5.699067 2.000000 1.500000 098 -99 13.192464 -3.822648 2.000000 1.500000 099 -100 13.192464 -2.322552 2.000000 1.500000 100 -101 16.897501 -15.409053 2.000000 1.500000 101 -102 16.897501 -13.908834 2.000000 1.500000 102 -103 16.085766 -12.406122 2.000000 1.500000 103 -104 16.085766 -10.906034 2.000000 1.500000 104 -105 21.903262 -10.894836 2.000000 1.500000 105 -106 21.903262 -9.394836 2.000000 1.500000 106 -107 19.597726 -9.346367 2.000000 1.500000 107 -108 19.597726 -7.846579 2.000000 1.500000 108 -109 16.817868 -8.131419 2.000000 1.500000 109 -110 16.817868 -6.631304 2.000000 1.500000 110 -111 24.590015 -6.177621 2.000000 1.500000 111 -112 24.590015 -4.677286 2.000000 1.500000 112 -113 22.106147 -5.313065 2.000000 1.500000 113 -114 22.106147 -3.813065 2.000000 1.500000 114 -115 19.211802 -4.494588 2.000000 1.500000 115 -116 19.211802 -2.994811 2.000000 1.500000 116 -117 16.250462 -3.954580 2.000000 1.500000 117 -118 16.250462 -2.454261 2.000000 1.500000 118 -119 17.104607 -0.521429 2.000000 1.500000 119 -120 17.104607 0.978571 2.000000 1.500000 120 -121 14.303336 -0.481488 2.000000 1.500000 121 -122 14.303336 1.018792 2.000000 1.500000 122 diff --git a/external/fieldtrip/private/NM122combined.lay b/external/fieldtrip/private/NM122combined.lay deleted file mode 100644 index 8ee54ad..0000000 --- a/external/fieldtrip/private/NM122combined.lay +++ /dev/null @@ -1,63 +0,0 @@ -1 25.3813 -0.022042 2.0000 1.5000 MEG 001+002 -2 22.7154 0.016754 2.0000 1.5000 MEG 003+004 -3 19.9111 0.14125 2.0000 1.5000 MEG 005+006 -4 24.4811 5.0971 2.0000 1.5000 MEG 007+008 -5 21.9673 4.3637 2.0000 1.5000 MEG 009+010 -6 19.346 3.8602 2.0000 1.5000 MEG 011+012 -7 16.7066 3.6257 2.0000 1.5000 MEG 013+014 -8 14.0905 3.5037 2.0000 1.5000 MEG 015+016 -9 19.56 7.9932 2.0000 1.5000 MEG 017+018 -10 16.943 6.9872 2.0000 1.5000 MEG 019+020 -11 14.2048 6.5428 2.0000 1.5000 MEG 021+022 -12 11.5 6.4544 2.0000 1.5000 MEG 023+024 -13 16.6625 10.6284 2.0000 1.5000 MEG 025+026 -14 13.4663 12.61 2.0000 1.5000 MEG 027+028 -15 13.4504 9.5574 2.0000 1.5000 MEG 029+030 -16 9.5337 12.61 2.0000 1.5000 MEG 031+032 -17 9.5496 9.5574 2.0000 1.5000 MEG 033+034 -18 6.3375 10.6284 2.0000 1.5000 MEG 035+036 -19 3.44 7.9932 2.0000 1.5000 MEG 037+038 -20 6.057 6.9872 2.0000 1.5000 MEG 039+040 -21 8.7952 6.5428 2.0000 1.5000 MEG 041+042 -22 -1.4811 5.0971 2.0000 1.5000 MEG 043+044 -23 1.0327 4.3636 2.0000 1.5000 MEG 045+046 -24 3.654 3.8602 2.0000 1.5000 MEG 047+048 -25 6.2934 3.6257 2.0000 1.5000 MEG 049+050 -26 8.9095 3.5037 2.0000 1.5000 MEG 051+052 -27 11.5 3.4814 2.0000 1.5000 MEG 053+054 -28 -2.3813 -0.022042 2.0000 1.5000 MEG 055+056 -29 0.28463 0.016754 2.0000 1.5000 MEG 057+058 -30 3.0889 0.14125 2.0000 1.5000 MEG 059+060 -31 5.8954 0.22857 2.0000 1.5000 MEG 061+062 -32 8.6967 0.26865 2.0000 1.5000 MEG 063+064 -33 11.5 0.28686 2.0000 1.5000 MEG 065+066 -34 -1.59 -5.4275 2.0000 1.5000 MEG 067+068 -35 0.89385 -4.5631 2.0000 1.5000 MEG 069+070 -36 3.7882 -3.7447 2.0000 1.5000 MEG 071+072 -37 6.7495 -3.2044 2.0000 1.5000 MEG 073+074 -38 1.0967 -10.1448 2.0000 1.5000 MEG 075+076 -39 3.4023 -8.5965 2.0000 1.5000 MEG 077+078 -40 6.1821 -7.3814 2.0000 1.5000 MEG 079+080 -41 6.1025 -14.6589 2.0000 1.5000 MEG 081+082 -42 6.9142 -11.6561 2.0000 1.5000 MEG 083+084 -43 9.3075 -9.8939 2.0000 1.5000 MEG 085+086 -44 9.661 -6.4491 2.0000 1.5000 MEG 087+088 -45 9.8075 -3.0726 2.0000 1.5000 MEG 089+090 -46 11.5 -15.5099 2.0000 1.5000 MEG 091+092 -47 11.5 -12.3473 2.0000 1.5000 MEG 093+094 -48 13.6925 -9.8939 2.0000 1.5000 MEG 095+096 -49 13.339 -6.4491 2.0000 1.5000 MEG 097+098 -50 13.1925 -3.0726 2.0000 1.5000 MEG 099+100 -51 16.8975 -14.6589 2.0000 1.5000 MEG 101+102 -52 16.0858 -11.6561 2.0000 1.5000 MEG 103+104 -53 21.9033 -10.1448 2.0000 1.5000 MEG 105+106 -54 19.5977 -8.5965 2.0000 1.5000 MEG 107+108 -55 16.8179 -7.3814 2.0000 1.5000 MEG 109+110 -56 24.59 -5.4275 2.0000 1.5000 MEG 111+112 -57 22.1061 -4.5631 2.0000 1.5000 MEG 113+114 -58 19.2118 -3.7447 2.0000 1.5000 MEG 115+116 -59 16.2505 -3.2044 2.0000 1.5000 MEG 117+118 -60 17.1046 0.22857 2.0000 1.5000 MEG 119+120 -61 14.3033 0.26865 2.0000 1.5000 MEG 121+122 -62 -2.3813 13.36 2.0000 1.5000 COMNT -63 25.3813 13.36 2.0000 1.5000 SCALE diff --git a/external/fieldtrip/private/NM306all.lay b/external/fieldtrip/private/NM306all.lay deleted file mode 100644 index 56aade4..0000000 --- a/external/fieldtrip/private/NM306all.lay +++ /dev/null @@ -1,306 +0,0 @@ -1 -73.416206 33.416687 5.000000 4.800000 0113 -2 -73.416206 38.416687 5.000000 4.800000 0112 -3 -67.416206 35.916687 5.000000 4.800000 0111 -4 -59.602242 38.489067 5.000000 4.800000 0122 -5 -59.602242 43.489067 5.000000 4.800000 0123 -6 -53.602242 40.989067 5.000000 4.800000 0121 -7 -68.018288 18.676970 5.000000 4.800000 0132 -8 -68.018288 23.676970 5.000000 4.800000 0133 -9 -62.018288 21.176970 5.000000 4.800000 0131 -10 -80.582848 8.095787 5.000000 4.800000 0143 -11 -80.582848 13.095787 5.000000 4.800000 0142 -12 -74.582848 10.595787 5.000000 4.800000 0141 -13 -56.595154 17.019251 5.000000 4.800000 0213 -14 -56.595154 22.019251 5.000000 4.800000 0212 -15 -50.595154 19.519251 5.000000 4.800000 0211 -16 -44.599728 17.543873 5.000000 4.800000 0222 -17 -44.599728 22.543873 5.000000 4.800000 0223 -18 -38.599728 20.043873 5.000000 4.800000 0221 -19 -47.416420 -0.216784 5.000000 4.800000 0232 -20 -47.416420 4.783216 5.000000 4.800000 0233 -21 -41.416420 2.283216 5.000000 4.800000 0231 -22 -59.280643 -2.761772 5.000000 4.800000 0243 -23 -59.280643 2.238228 5.000000 4.800000 0242 -24 -53.280643 -0.261772 5.000000 4.800000 0241 -25 -39.790501 47.430138 5.000000 4.800000 0313 -26 -39.790501 52.430138 5.000000 4.800000 0312 -27 -33.790501 49.930138 5.000000 4.800000 0311 -28 -38.014336 32.768585 5.000000 4.800000 0322 -29 -38.014336 37.768585 5.000000 4.800000 0323 -30 -32.014336 35.268585 5.000000 4.800000 0321 -31 -27.679966 28.868065 5.000000 4.800000 0333 -32 -27.679966 33.868065 5.000000 4.800000 0332 -33 -21.679966 31.368065 5.000000 4.800000 0331 -34 -49.684467 34.878434 5.000000 4.800000 0343 -35 -49.684467 39.078434 5.000000 4.800000 0342 -36 -43.684467 36.578434 5.000000 4.800000 0341 -37 -32.997990 15.607347 5.000000 4.800000 0413 -38 -32.997990 20.607347 5.000000 4.800000 0412 -39 -26.997990 18.107347 5.000000 4.800000 0411 -40 -21.084751 13.953575 5.000000 4.800000 0422 -41 -21.084751 18.953575 5.000000 4.800000 0423 -42 -15.084751 16.453575 5.000000 4.800000 0421 -43 -21.930935 -0.085500 5.000000 4.800000 0432 -44 -21.930935 4.914500 5.000000 4.800000 0433 -45 -15.930935 2.414500 5.000000 4.800000 0431 -46 -34.824663 0.362587 5.000000 4.800000 0443 -47 -34.824663 5.362587 5.000000 4.800000 0442 -48 -28.824663 2.862587 5.000000 4.800000 0441 -49 -27.861498 55.439636 5.000000 4.800000 0513 -50 -27.861498 60.439636 5.000000 4.800000 0512 -51 -21.861498 57.939636 5.000000 4.800000 0511 -52 -15.506709 59.619865 5.000000 4.800000 0523 -53 -15.506709 64.619865 5.000000 4.800000 0522 -54 -9.506709 62.119865 5.000000 4.800000 0521 -55 -14.616095 49.308380 5.000000 4.800000 0532 -56 -14.616095 54.308380 5.000000 4.800000 0533 -57 -8.616095 51.808380 5.000000 4.800000 0531 -58 -27.240477 43.863430 5.000000 4.800000 0542 -59 -27.240477 48.863430 5.000000 4.800000 0543 -60 -21.240477 46.363430 5.000000 4.800000 0541 -61 -14.782405 38.147827 5.000000 4.800000 0613 -62 -14.782405 43.147827 5.000000 4.800000 0612 -63 -8.782405 40.647827 5.000000 4.800000 0611 -64 -2.967276 27.260933 5.000000 4.800000 0622 -65 -2.967276 32.260933 5.000000 4.800000 0623 -66 3.032724 29.760933 5.000000 4.800000 0621 -67 -9.094766 14.700909 5.000000 4.800000 0633 -68 -9.094766 19.700909 5.000000 4.800000 0632 -69 -3.094766 17.200909 5.000000 4.800000 0631 -70 -15.199021 26.631405 5.000000 4.800000 0642 -71 -15.199021 31.631405 5.000000 4.800000 0643 -72 -9.199021 29.131405 5.000000 4.800000 0641 -73 -9.246834 1.693846 5.000000 4.800000 0713 -74 -9.246834 6.693846 5.000000 4.800000 0712 -75 -3.246834 4.193846 5.000000 4.800000 0711 -76 3.314525 1.573887 5.000000 4.800000 0723 -77 3.314525 6.573887 5.000000 4.800000 0722 -78 9.314525 4.873887 5.000000 4.800000 0721 -79 3.387173 -10.588106 5.000000 4.800000 0733 -80 3.387173 -5.588106 5.000000 4.800000 0732 -81 9.387173 -8.088106 5.000000 4.800000 0731 -82 -9.422897 -10.519942 5.000000 4.800000 0743 -83 -9.422897 -5.519942 5.000000 4.800000 0742 -84 -3.422897 -8.019942 5.000000 4.800000 0741 -85 -2.962408 61.007698 5.000000 4.800000 0813 -86 -2.962408 65.007698 5.000000 4.800000 0812 -87 3.037592 63.507698 5.000000 4.800000 0811 -88 -2.965545 50.641838 5.000000 4.800000 0822 -89 -2.965545 55.641838 5.000000 4.800000 0823 -90 3.034455 53.141838 5.000000 4.800000 0821 -91 9.504830 59.655254 5.000000 4.800000 0913 -92 9.504830 64.655254 5.000000 4.800000 0912 -93 15.504830 62.155254 5.000000 4.800000 0911 -94 21.967310 55.408710 5.000000 4.800000 0923 -95 21.967310 60.408710 5.000000 4.800000 0922 -96 27.967310 57.908710 5.000000 4.800000 0921 -97 21.254196 43.889683 5.000000 4.800000 0932 -98 21.254196 48.889683 5.000000 4.800000 0933 -99 27.254196 46.389683 5.000000 4.800000 0931 -100 8.661931 49.358044 5.000000 4.800000 0942 -101 8.661931 54.358044 5.000000 4.800000 0943 -102 14.661931 51.858044 5.000000 4.800000 0941 -103 -2.967087 39.669956 5.000000 4.800000 1013 -104 -2.967087 44.669956 5.000000 4.800000 1012 -105 3.032913 42.169956 5.000000 4.800000 1011 -106 8.751018 38.154079 5.000000 4.800000 1023 -107 8.751018 43.154079 5.000000 4.800000 1022 -108 14.751018 40.654079 5.000000 4.800000 1021 -109 9.123913 26.648697 5.000000 4.800000 1032 -110 9.123913 31.648697 5.000000 4.800000 1033 -111 15.123913 29.148697 5.000000 4.800000 1031 -112 3.200539 14.795620 5.000000 4.800000 1043 -113 3.200539 19.795620 5.000000 4.800000 1042 -114 9.200539 17.295620 5.000000 4.800000 1041 -115 15.014965 13.912239 5.000000 4.800000 1112 -116 15.014965 18.912239 5.000000 4.800000 1113 -117 21.014965 16.412239 5.000000 4.800000 1111 -118 26.958527 15.562130 5.000000 4.800000 1123 -119 26.958527 20.562130 5.000000 4.800000 1122 -120 32.958527 18.062130 5.000000 4.800000 1121 -121 28.757563 0.227141 5.000000 4.800000 1133 -122 28.757563 5.227141 5.000000 4.800000 1132 -123 34.757563 2.727141 5.000000 4.800000 1131 -124 15.882982 0.037700 5.000000 4.800000 1142 -125 15.882982 5.037700 5.000000 4.800000 1143 -126 21.882982 2.537700 5.000000 4.800000 1141 -127 33.958897 47.388790 5.000000 4.800000 1213 -128 33.958897 52.388790 5.000000 4.800000 1212 -129 39.958897 49.888790 5.000000 4.800000 1211 -130 43.923473 33.914738 5.000000 4.800000 1223 -131 43.923473 38.914738 5.000000 4.800000 1222 -132 49.923473 36.414738 5.000000 4.800000 1221 -133 32.014336 32.768585 5.000000 4.800000 1232 -134 32.014336 37.768585 5.000000 4.800000 1233 -135 38.014336 35.268585 5.000000 4.800000 1231 -136 21.600079 28.898149 5.000000 4.800000 1243 -137 21.600079 33.898149 5.000000 4.800000 1242 -138 27.600079 31.398149 5.000000 4.800000 1241 -139 38.599728 17.543867 5.000000 4.800000 1312 -140 38.599728 22.543867 5.000000 4.800000 1313 -141 44.599728 20.043867 5.000000 4.800000 1311 -142 50.558392 16.887651 5.000000 4.800000 1323 -143 50.558392 21.887651 5.000000 4.800000 1322 -144 56.558392 19.387651 5.000000 4.800000 1321 -145 53.420483 -2.919475 5.000000 4.800000 1333 -146 53.420483 2.080525 5.000000 4.800000 1332 -147 59.420483 -0.419475 5.000000 4.800000 1331 -148 41.371586 -0.216817 5.000000 4.800000 1342 -149 41.371586 4.783183 5.000000 4.800000 1343 -150 47.371586 2.283183 5.000000 4.800000 1341 -151 53.704369 38.563030 5.000000 4.800000 1412 -152 53.704369 43.563030 5.000000 4.800000 1413 -153 59.704369 41.063030 5.000000 4.800000 1411 -154 67.119286 33.843739 5.000000 4.800000 1423 -155 67.119286 38.843739 5.000000 4.800000 1422 -156 73.119286 36.343739 5.000000 4.800000 1421 -157 74.438919 8.335863 5.000000 4.800000 1433 -158 74.438919 13.335863 5.000000 4.800000 1432 -159 80.438919 10.835863 5.000000 4.800000 1431 -160 61.883209 18.562304 5.000000 4.800000 1442 -161 61.883209 23.562304 5.000000 4.800000 1443 -162 67.883209 21.062304 5.000000 4.800000 1441 -163 -71.298943 -4.707253 5.000000 4.800000 1512 -164 -71.298943 0.292747 5.000000 4.800000 1513 -165 -65.298943 -2.207253 5.000000 4.800000 1511 -166 -67.281609 -25.407852 5.000000 4.800000 1522 -167 -67.281609 -20.407852 5.000000 4.800000 1523 -168 -61.281609 -22.907852 5.000000 4.800000 1521 -169 -71.702820 -40.152336 5.000000 4.800000 1533 -170 -71.702820 -35.152336 5.000000 4.800000 1532 -171 -65.702820 -37.652336 5.000000 4.800000 1531 -172 -79.907913 -17.418098 5.000000 4.800000 1543 -173 -79.907913 -12.418098 5.000000 4.800000 1542 -174 -73.907913 -14.918098 5.000000 4.800000 1541 -175 -56.916454 -20.312164 5.000000 4.800000 1613 -176 -56.916454 -15.312164 5.000000 4.800000 1612 -177 -50.916454 -17.812164 5.000000 4.800000 1611 -178 -45.631779 -16.320436 5.000000 4.800000 1622 -179 -45.631779 -11.320436 5.000000 4.800000 1623 -180 -39.631779 -13.820436 5.000000 4.800000 1621 -181 -37.896103 -30.578358 5.000000 4.800000 1632 -182 -37.896103 -25.578358 5.000000 4.800000 1633 -183 -31.896103 -28.078358 5.000000 4.800000 1631 -184 -48.859089 -36.176094 5.000000 4.800000 1643 -185 -48.859089 -31.176094 5.000000 4.800000 1642 -186 -42.859089 -33.676094 5.000000 4.800000 1641 -187 -56.796040 -59.082275 5.000000 4.800000 1713 -188 -56.796040 -54.882275 5.000000 4.800000 1712 -189 -50.796040 -56.582275 5.000000 4.800000 1711 -190 -57.188797 -44.857373 5.000000 4.800000 1722 -191 -57.188797 -39.057373 5.000000 4.800000 1723 -192 -51.188797 -41.557373 5.000000 4.800000 1721 -193 -41.902962 -58.279526 5.000000 4.800000 1732 -194 -41.902962 -53.279526 5.000000 4.800000 1733 -195 -35.902962 -55.779526 5.000000 4.800000 1731 -196 -37.408134 -72.449036 5.000000 4.800000 1743 -197 -37.408134 -67.449036 5.000000 4.800000 1742 -198 -31.408134 -69.949036 5.000000 4.800000 1741 -199 -33.801163 -13.768716 5.000000 4.800000 1813 -200 -33.801163 -8.768716 5.000000 4.800000 1812 -201 -27.801163 -11.268716 5.000000 4.800000 1811 -202 -21.685101 -12.619589 5.000000 4.800000 1822 -203 -21.685101 -7.619589 5.000000 4.800000 1823 -204 -15.685101 -10.119589 5.000000 4.800000 1821 -205 -9.600111 -22.190945 5.000000 4.800000 1832 -206 -9.600111 -17.190945 5.000000 4.800000 1833 -207 -3.600111 -19.690945 5.000000 4.800000 1831 -208 -24.483526 -26.850609 5.000000 4.800000 1843 -209 -24.483526 -21.850609 5.000000 4.800000 1842 -210 -18.483526 -24.350609 5.000000 4.800000 1841 -211 -25.866816 -40.850040 5.000000 4.800000 1912 -212 -25.866816 -35.850040 5.000000 4.800000 1913 -213 -19.866816 -38.350040 5.000000 4.800000 1911 -214 -20.513481 -56.355225 5.000000 4.800000 1923 -215 -20.513481 -51.355225 5.000000 4.800000 1922 -216 -14.513481 -53.855225 5.000000 4.800000 1921 -217 -23.428471 -67.375893 5.000000 4.800000 1932 -218 -23.428471 -62.375893 5.000000 4.800000 1933 -219 -17.428471 -64.875893 5.000000 4.800000 1931 -220 -36.237587 -48.444530 5.000000 4.800000 1943 -221 -36.237587 -43.444530 5.000000 4.800000 1942 -222 -30.237587 -45.944530 5.000000 4.800000 1941 -223 -10.441930 -34.308243 5.000000 4.800000 2013 -224 -10.441930 -29.308243 5.000000 4.800000 2012 -225 -4.441930 -31.808243 5.000000 4.800000 2011 -226 4.357624 -34.289736 5.000000 4.800000 2023 -227 4.357624 -29.289736 5.000000 4.800000 2022 -228 10.357624 -31.789736 5.000000 4.800000 2021 -229 4.645295 -46.290749 5.000000 4.800000 2032 -230 4.645295 -41.290749 5.000000 4.800000 2033 -231 10.645295 -43.790749 5.000000 4.800000 2031 -232 -10.645079 -46.244335 5.000000 4.800000 2042 -233 -10.645079 -41.244335 5.000000 4.800000 2043 -234 -4.645079 -43.744335 5.000000 4.800000 2041 -235 -3.052351 -58.889515 5.000000 4.800000 2113 -236 -3.052351 -53.889515 5.000000 4.800000 2112 -237 2.947649 -56.389515 5.000000 4.800000 2111 -238 -2.999999 -70.362061 5.000000 4.800000 2122 -239 -2.999999 -65.362061 5.000000 4.800000 2123 -240 3.000001 -67.862061 5.000000 4.800000 2121 -241 8.918572 -79.441826 5.000000 4.800000 2133 -242 8.918572 -74.441826 5.000000 4.800000 2132 -243 14.918572 -76.941826 5.000000 4.800000 2131 -244 -14.987089 -79.428932 5.000000 4.800000 2143 -245 -14.987089 -74.428932 5.000000 4.800000 2142 -246 -8.987089 -76.928932 5.000000 4.800000 2141 -247 15.641460 -12.579389 5.000000 4.800000 2212 -248 15.641460 -7.579389 5.000000 4.800000 2213 -249 21.641460 -10.079389 5.000000 4.800000 2211 -250 27.786499 -13.669980 5.000000 4.800000 2223 -251 27.786499 -8.669980 5.000000 4.800000 2222 -252 33.786499 -11.169980 5.000000 4.800000 2221 -253 18.501518 -26.949615 5.000000 4.800000 2233 -254 18.501518 -21.949615 5.000000 4.800000 2232 -255 24.501518 -24.449615 5.000000 4.800000 2231 -256 3.641699 -22.206125 5.000000 4.800000 2242 -257 3.641699 -17.206125 5.000000 4.800000 2243 -258 9.641699 -19.706125 5.000000 4.800000 2241 -259 19.852789 -40.871220 5.000000 4.800000 2312 -260 19.852789 -35.871220 5.000000 4.800000 2313 -261 25.852789 -38.371220 5.000000 4.800000 2311 -262 30.078903 -48.474960 5.000000 4.800000 2323 -263 30.078903 -43.474960 5.000000 4.800000 2322 -264 35.078903 -45.974960 5.000000 4.800000 2321 -265 17.363274 -67.365387 5.000000 4.800000 2332 -266 17.363274 -62.365387 5.000000 4.800000 2333 -267 23.363274 -64.865387 5.000000 4.800000 2331 -268 14.329920 -56.380260 5.000000 4.800000 2343 -269 14.329920 -51.380260 5.000000 4.800000 2342 -270 20.329920 -53.880260 5.000000 4.800000 2341 -271 39.644810 -16.175139 5.000000 4.800000 2412 -272 39.644810 -11.175139 5.000000 4.800000 2413 -273 45.644810 -13.675139 5.000000 4.800000 2411 -274 50.812263 -20.401899 5.000000 4.800000 2423 -275 50.812263 -15.401899 5.000000 4.800000 2422 -276 56.812263 -17.901899 5.000000 4.800000 2421 -277 42.694180 -36.278580 5.000000 4.800000 2433 -278 42.694180 -31.278580 5.000000 4.800000 2432 -279 48.694180 -33.778580 5.000000 4.800000 2431 -280 31.896111 -30.578348 5.000000 4.800000 2442 -281 31.896111 -25.578348 5.000000 4.800000 2443 -282 37.896111 -28.078348 5.000000 4.800000 2441 -283 35.812634 -58.300888 5.000000 4.800000 2512 -284 35.812634 -53.300888 5.000000 4.800000 2513 -285 41.812634 -55.800888 5.000000 4.800000 2511 -286 51.171906 -43.981274 5.000000 4.800000 2522 -287 51.171906 -38.981274 5.000000 4.800000 2523 -288 57.171906 -41.481274 5.000000 4.800000 2521 -289 50.704624 -59.132656 5.000000 4.800000 2533 -290 50.704624 -54.132656 5.000000 4.800000 2532 -291 56.704624 -56.632656 5.000000 4.800000 2531 -292 31.320171 -72.484848 5.000000 4.800000 2543 -293 31.320171 -67.484848 5.000000 4.800000 2542 -294 37.320171 -69.984848 5.000000 4.800000 2541 -295 65.137360 -4.702045 5.000000 4.800000 2612 -296 65.137360 0.297955 5.000000 4.800000 2613 -297 71.137360 -2.202045 5.000000 4.800000 2611 -298 73.822243 -17.329140 5.000000 4.800000 2623 -299 73.822243 -12.329140 5.000000 4.800000 2622 -300 79.822243 -14.829140 5.000000 4.800000 2621 -301 65.490112 -40.332645 5.000000 4.800000 2633 -302 65.490112 -35.332645 5.000000 4.800000 2632 -303 71.490112 -37.832645 5.000000 4.800000 2631 -304 61.220192 -25.385981 5.000000 4.800000 2642 -305 61.220192 -20.385981 5.000000 4.800000 2643 -306 67.220192 -22.885981 5.000000 4.800000 2641 diff --git a/external/fieldtrip/private/NM306mag.lay b/external/fieldtrip/private/NM306mag.lay deleted file mode 100644 index b38ac2f..0000000 --- a/external/fieldtrip/private/NM306mag.lay +++ /dev/null @@ -1,102 +0,0 @@ -3 -67.416206 35.916687 10.000000 10.000000 0111 -6 -53.602242 40.989067 10.000000 10.000000 0121 -9 -62.018288 21.176970 10.000000 10.000000 0131 -12 -74.582848 10.595787 10.000000 10.000000 0141 -15 -50.595154 19.519251 10.000000 10.000000 0211 -18 -38.599728 20.043873 10.000000 10.000000 0221 -21 -41.416420 2.283216 10.000000 10.000000 0231 -24 -53.280643 -0.261772 10.000000 10.000000 0241 -27 -33.790501 49.930138 10.000000 10.000000 0311 -30 -32.014336 35.268585 10.000000 10.000000 0321 -33 -21.679966 31.368065 10.000000 10.000000 0331 -36 -43.684467 36.578434 10.000000 10.000000 0341 -39 -26.997990 18.107347 10.000000 10.000000 0411 -42 -15.084751 16.453575 10.000000 10.000000 0421 -45 -15.930935 2.414500 10.000000 10.000000 0431 -48 -28.824663 2.862587 10.000000 10.000000 0441 -51 -21.861498 57.939636 10.000000 10.000000 0511 -54 -9.506709 62.119865 10.000000 10.000000 0521 -57 -8.616095 51.808380 10.000000 10.000000 0531 -60 -21.240477 46.363430 10.000000 10.000000 0541 -63 -8.782405 40.647827 10.000000 10.000000 0611 -66 3.032724 29.760933 10.000000 10.000000 0621 -69 -3.094766 17.200909 10.000000 10.000000 0631 -72 -9.199021 29.131405 10.000000 10.000000 0641 -75 -3.246834 4.193846 10.000000 10.000000 0711 -78 9.314525 4.073887 10.000000 10.000000 0721 -81 9.387173 -8.088106 10.000000 10.000000 0731 -84 -3.422897 -8.019942 10.000000 10.000000 0741 -87 3.037592 63.507698 10.000000 10.000000 0811 -90 3.034455 53.141838 10.000000 10.000000 0821 -93 15.504830 62.155254 10.000000 10.000000 0911 -96 27.967310 57.908710 10.000000 10.000000 0921 -99 27.254196 46.389683 10.000000 10.000000 0931 -102 14.661931 51.858044 10.000000 10.000000 0941 -105 3.032913 42.169956 10.000000 10.000000 1011 -108 14.751018 40.654079 10.000000 10.000000 1021 -111 15.123913 29.148697 10.000000 10.000000 1031 -114 9.200539 17.295620 10.000000 10.000000 1041 -117 21.014965 16.412239 10.000000 10.000000 1111 -120 32.958527 18.062130 10.000000 10.000000 1121 -123 34.757563 2.727141 10.000000 10.000000 1131 -126 21.882982 2.537700 10.000000 10.000000 1141 -129 39.958897 49.888790 10.000000 10.000000 1211 -132 49.923473 36.414738 10.000000 10.000000 1221 -135 38.014336 35.268585 10.000000 10.000000 1231 -138 27.600079 31.398149 10.000000 10.000000 1241 -141 44.599728 20.043867 10.000000 10.000000 1311 -144 56.558392 19.387651 10.000000 10.000000 1321 -147 59.420483 -0.419475 10.000000 10.000000 1331 -150 47.371586 2.283183 10.000000 10.000000 1341 -153 59.704369 41.063030 10.000000 10.000000 1411 -156 73.119286 36.343739 10.000000 10.000000 1421 -159 80.438919 10.835863 10.000000 10.000000 1431 -162 67.883209 21.062304 10.000000 10.000000 1441 -165 -65.298943 -2.207253 10.000000 10.000000 1511 -168 -61.281609 -22.907852 10.000000 10.000000 1521 -171 -65.702820 -37.652336 10.000000 10.000000 1531 -174 -73.907913 -14.918098 10.000000 10.000000 1541 -177 -50.916454 -17.812164 10.000000 10.000000 1611 -180 -39.631779 -13.820436 10.000000 10.000000 1621 -183 -31.896103 -28.078358 10.000000 10.000000 1631 -186 -42.859089 -33.676094 10.000000 10.000000 1641 -189 -50.796040 -56.582275 10.000000 10.000000 1711 -192 -51.188797 -41.557373 10.000000 10.000000 1721 -195 -35.902962 -55.779526 10.000000 10.000000 1731 -198 -31.408134 -69.949036 10.000000 10.000000 1741 -201 -27.801163 -11.268716 10.000000 10.000000 1811 -204 -15.685101 -10.119589 10.000000 10.000000 1821 -207 -3.600111 -19.690945 10.000000 10.000000 1831 -210 -18.483526 -24.350609 10.000000 10.000000 1841 -213 -19.866816 -38.350040 10.000000 10.000000 1911 -216 -14.513481 -53.855225 10.000000 10.000000 1921 -219 -17.428471 -64.875893 10.000000 10.000000 1931 -222 -30.237587 -45.944530 10.000000 10.000000 1941 -225 -4.441930 -31.808243 10.000000 10.000000 2011 -228 10.357624 -31.789736 10.000000 10.000000 2021 -231 10.645295 -43.790749 10.000000 10.000000 2031 -234 -4.645079 -43.744335 10.000000 10.000000 2041 -237 2.947649 -56.389515 10.000000 10.000000 2111 -240 3.000001 -67.862061 10.000000 10.000000 2121 -243 14.918572 -76.941826 10.000000 10.000000 2131 -246 -8.987089 -76.928932 10.000000 10.000000 2141 -249 21.641460 -10.079389 10.000000 10.000000 2211 -252 33.786499 -11.169980 10.000000 10.000000 2221 -255 24.501518 -24.449615 10.000000 10.000000 2231 -258 9.641699 -19.706125 10.000000 10.000000 2241 -261 25.852789 -38.371220 10.000000 10.000000 2311 -264 36.078903 -45.974960 10.000000 10.000000 2321 -267 23.363274 -64.865387 10.000000 10.000000 2331 -270 20.329920 -53.880260 10.000000 10.000000 2341 -273 45.644810 -13.675139 10.000000 10.000000 2411 -276 56.812263 -17.901899 10.000000 10.000000 2421 -279 48.694180 -33.778580 10.000000 10.000000 2431 -282 37.896111 -28.078348 10.000000 10.000000 2441 -285 41.812634 -55.800888 10.000000 10.000000 2511 -288 57.171906 -41.481274 10.000000 10.000000 2521 -291 56.704624 -56.632656 10.000000 10.000000 2531 -294 37.320171 -69.984848 10.000000 10.000000 2541 -297 71.137360 -2.202045 10.000000 10.000000 2611 -300 79.822243 -14.829140 10.000000 10.000000 2621 -303 71.490112 -37.832645 10.000000 10.000000 2631 -306 67.220192 -22.885981 10.000000 10.000000 2641 diff --git a/external/fieldtrip/private/NM306planar.lay b/external/fieldtrip/private/NM306planar.lay deleted file mode 100644 index cb56732..0000000 --- a/external/fieldtrip/private/NM306planar.lay +++ /dev/null @@ -1,204 +0,0 @@ -1 -48.186871 26.886379 6.000000 3.500000 0113 -2 -48.186871 31.886379 6.000000 3.500000 0112 -4 -39.322296 31.036510 6.000000 3.500000 0122 -5 -39.322296 36.036510 6.000000 3.500000 0123 -7 -44.722965 14.826612 6.000000 3.500000 0132 -8 -44.722965 19.826612 6.000000 3.500000 0133 -10 -52.785782 6.169280 6.000000 3.500000 0143 -11 -52.785782 11.169280 6.000000 3.500000 0142 -13 -37.392612 13.470296 6.000000 3.500000 0213 -14 -37.392612 18.470296 6.000000 3.500000 0212 -16 -29.695013 13.899532 6.000000 3.500000 0222 -17 -29.695013 18.899532 6.000000 3.500000 0223 -19 -31.502516 -0.631914 6.000000 3.500000 0232 -20 -31.502516 4.368086 6.000000 3.500000 0233 -22 -39.115921 -2.709978 6.000000 3.500000 0243 -23 -39.115921 2.290022 6.000000 3.500000 0242 -25 -26.608879 38.351933 6.000000 3.500000 0313 -26 -26.608879 43.351933 6.000000 3.500000 0312 -28 -25.469093 26.356115 6.000000 3.500000 0322 -29 -25.469093 31.356115 6.000000 3.500000 0323 -31 -18.837411 23.164780 6.000000 3.500000 0333 -32 -18.837411 28.164780 6.000000 3.500000 0332 -34 -32.957949 27.427811 6.000000 3.500000 0343 -35 -32.957949 32.427811 6.000000 3.500000 0342 -37 -22.250046 12.315103 6.000000 3.500000 0413 -38 -22.250046 17.315103 6.000000 3.500000 0412 -40 -14.605187 10.962016 6.000000 3.500000 0422 -41 -14.605187 15.962016 6.000000 3.500000 0423 -43 -15.148193 -0.524500 6.000000 3.500000 0432 -44 -15.148193 4.475500 6.000000 3.500000 0433 -46 -23.422245 -0.157884 6.000000 3.500000 0443 -47 -23.422245 4.842116 6.000000 3.500000 0442 -49 -18.953902 44.905155 6.000000 3.500000 0513 -50 -18.953902 49.905155 6.000000 3.500000 0512 -52 -11.025696 48.325344 6.000000 3.500000 0523 -53 -11.025696 53.325344 6.000000 3.500000 0522 -55 -10.454178 39.888676 6.000000 3.500000 0532 -56 -10.454178 44.888676 6.000000 3.500000 0533 -58 -18.555386 35.433716 6.000000 3.500000 0542 -59 -18.555386 40.433716 6.000000 3.500000 0543 -61 -10.560901 30.757313 6.000000 3.500000 0613 -62 -10.560901 35.757313 6.000000 3.500000 0612 -64 -2.979000 21.849854 6.000000 3.500000 0622 -65 -2.979000 26.849854 6.000000 3.500000 0623 -67 -6.911079 11.573471 6.000000 3.500000 0633 -68 -6.911079 16.573471 6.000000 3.500000 0632 -70 -10.828249 21.334785 6.000000 3.500000 0642 -71 -10.828249 26.334785 6.000000 3.500000 0643 -73 -7.008664 0.931329 6.000000 3.500000 0713 -74 -7.008664 5.931329 6.000000 3.500000 0712 -76 1.052102 0.833180 6.000000 3.500000 0723 -77 1.052102 5.833180 6.000000 3.500000 0722 -79 1.098721 -8.987786 6.000000 3.500000 0733 -80 1.098721 -3.987786 6.000000 3.500000 0732 -82 -7.121645 -8.933109 6.000000 3.500000 0743 -83 -7.121645 -3.933109 6.000000 3.500000 0742 -85 -2.975877 49.460842 6.000000 3.500000 0813 -86 -2.975877 54.460842 6.000000 3.500000 0812 -88 -2.977890 40.979687 6.000000 3.500000 0822 -89 -2.977890 45.979687 6.000000 3.500000 0823 -91 5.024490 48.354298 6.000000 3.500000 0913 -92 5.024490 53.354298 6.000000 3.500000 0912 -94 13.021803 44.879852 6.000000 3.500000 0923 -95 13.021803 49.879852 6.000000 3.500000 0922 -97 12.564190 35.455193 6.000000 3.500000 0932 -98 12.564190 40.455193 6.000000 3.500000 0933 -100 4.483593 39.929310 6.000000 3.500000 0942 -101 4.483593 44.929310 6.000000 3.500000 0943 -103 -2.978879 32.002693 6.000000 3.500000 1013 -104 -2.978879 37.002693 6.000000 3.500000 1012 -106 4.540760 30.762428 6.000000 3.500000 1023 -107 4.540760 35.762428 6.000000 3.500000 1022 -109 4.780051 21.348934 6.000000 3.500000 1032 -110 4.780051 26.348934 6.000000 3.500000 1033 -112 0.978956 11.650963 6.000000 3.500000 1043 -113 0.978956 16.650963 6.000000 3.500000 1042 -115 8.560405 10.928195 6.000000 3.500000 1112 -116 8.560405 15.928195 6.000000 3.500000 1113 -118 16.224724 12.278107 6.000000 3.500000 1123 -119 16.224724 17.278107 6.000000 3.500000 1122 -121 17.379185 -0.268703 6.000000 3.500000 1133 -122 17.379185 4.731297 6.000000 3.500000 1132 -124 9.117422 -0.423700 6.000000 3.500000 1142 -125 9.117422 4.576300 6.000000 3.500000 1143 -127 20.716938 38.318100 6.000000 3.500000 1213 -128 20.716938 43.318100 6.000000 3.500000 1212 -130 27.111319 27.293877 6.000000 3.500000 1223 -131 27.111319 32.293877 6.000000 3.500000 1222 -133 19.469093 26.356115 6.000000 3.500000 1232 -134 19.469093 31.356115 6.000000 3.500000 1233 -136 12.786146 23.189396 6.000000 3.500000 1243 -137 12.786146 28.189396 6.000000 3.500000 1242 -139 23.695013 13.899529 6.000000 3.500000 1312 -140 23.695013 18.899529 6.000000 3.500000 1313 -142 31.369019 13.362624 6.000000 3.500000 1323 -143 31.369019 18.362624 6.000000 3.500000 1322 -145 33.205658 -2.836478 6.000000 3.500000 1333 -146 33.205658 2.163522 6.000000 3.500000 1332 -148 25.473745 -0.631941 6.000000 3.500000 1342 -149 25.473745 4.368059 6.000000 3.500000 1343 -151 33.387833 31.097027 6.000000 3.500000 1412 -152 33.387833 36.097027 6.000000 3.500000 1413 -154 41.996334 27.235786 6.000000 3.500000 1423 -155 41.996334 32.235786 6.000000 3.500000 1422 -157 46.693424 6.365705 6.000000 3.500000 1433 -158 46.693424 11.365705 6.000000 3.500000 1432 -160 38.636284 14.732794 6.000000 3.500000 1442 -161 38.636284 19.732794 6.000000 3.500000 1443 -163 -46.828197 -4.270524 6.000000 3.500000 1512 -164 -46.828197 0.729476 6.000000 3.500000 1513 -166 -44.250233 -20.875282 6.000000 3.500000 1522 -167 -44.250233 -15.875282 6.000000 3.500000 1523 -169 -47.087372 -32.702410 6.000000 3.500000 1533 -170 -47.087372 -27.702410 6.000000 3.500000 1532 -172 -52.352669 -14.466389 6.000000 3.500000 1543 -173 -52.352669 -9.466389 6.000000 3.500000 1542 -175 -37.598797 -16.787832 6.000000 3.500000 1613 -176 -37.598797 -11.787832 6.000000 3.500000 1612 -178 -30.357292 -13.585911 6.000000 3.500000 1622 -179 -30.357292 -8.585911 6.000000 3.500000 1623 -181 -25.393221 -25.022747 6.000000 3.500000 1632 -182 -25.393221 -20.022747 6.000000 3.500000 1633 -184 -32.428291 -29.512911 6.000000 3.500000 1643 -185 -32.428291 -24.512911 6.000000 3.500000 1642 -187 -37.521523 -47.886852 6.000000 3.500000 1713 -188 -37.521523 -42.886852 6.000000 3.500000 1712 -190 -37.773560 -35.834789 6.000000 3.500000 1722 -191 -37.773560 -30.834789 6.000000 3.500000 1723 -193 -27.964468 -47.242935 6.000000 3.500000 1732 -194 -27.964468 -42.242935 6.000000 3.500000 1733 -196 -25.080088 -58.608849 6.000000 3.500000 1743 -197 -25.080088 -53.608849 6.000000 3.500000 1742 -199 -22.765453 -11.539077 6.000000 3.500000 1813 -200 -22.765453 -6.539077 6.000000 3.500000 1812 -202 -14.990439 -10.617317 6.000000 3.500000 1822 -203 -14.990439 -5.617317 6.000000 3.500000 1823 -205 -7.235366 -18.294876 6.000000 3.500000 1832 -206 -7.235366 -13.294876 6.000000 3.500000 1833 -208 -16.786220 -22.032574 6.000000 3.500000 1843 -209 -16.786220 -17.032574 6.000000 3.500000 1842 -211 -17.673892 -33.262066 6.000000 3.500000 1912 -212 -17.673892 -28.262066 6.000000 3.500000 1913 -214 -14.238597 -45.699379 6.000000 3.500000 1923 -215 -14.238597 -40.699379 6.000000 3.500000 1922 -217 -16.109179 -54.539486 6.000000 3.500000 1932 -218 -16.109179 -49.539486 6.000000 3.500000 1933 -220 -24.328934 -39.353901 6.000000 3.500000 1943 -221 -24.328934 -34.353901 6.000000 3.500000 1942 -223 -7.775570 -28.014633 6.000000 3.500000 2013 -224 -7.775570 -23.014633 6.000000 3.500000 2012 -226 1.721470 -27.999788 6.000000 3.500000 2023 -227 1.721470 -22.999788 6.000000 3.500000 2022 -229 1.906072 -37.626270 6.000000 3.500000 2032 -230 1.906072 -32.626270 6.000000 3.500000 2033 -232 -7.905933 -37.589039 6.000000 3.500000 2042 -233 -7.905933 -32.589039 6.000000 3.500000 2043 -235 -3.033595 -47.732231 6.000000 3.500000 2113 -236 -3.033595 -42.732231 6.000000 3.500000 2112 -238 -2.999999 -56.934807 6.000000 3.500000 2122 -239 -2.999999 -51.934807 6.000000 3.500000 2123 -241 4.648282 -64.218044 6.000000 3.500000 2133 -242 4.648282 -59.218044 6.000000 3.500000 2132 -244 -10.692250 -64.207703 6.000000 3.500000 2143 -245 -10.692250 -59.207703 6.000000 3.500000 2142 -247 8.962435 -10.585071 6.000000 3.500000 2212 -248 8.962435 -5.585071 6.000000 3.500000 2213 -250 16.756042 -11.459877 6.000000 3.500000 2223 -251 16.756042 -6.459877 6.000000 3.500000 2222 -253 10.797766 -22.111992 6.000000 3.500000 2233 -254 10.797766 -17.111992 6.000000 3.500000 2232 -256 1.262053 -18.307052 6.000000 3.500000 2242 -257 1.262053 -13.307052 6.000000 3.500000 2243 -259 11.664891 -33.279053 6.000000 3.500000 2312 -260 11.664891 -28.279053 6.000000 3.500000 2313 -262 18.227104 -39.378311 6.000000 3.500000 2323 -263 18.227104 -34.378311 6.000000 3.500000 2322 -265 10.067341 -54.531059 6.000000 3.500000 2332 -266 10.067341 -49.531059 6.000000 3.500000 2333 -268 8.120804 -45.719460 6.000000 3.500000 2343 -269 8.120804 -40.719460 6.000000 3.500000 2342 -271 24.365654 -13.469363 6.000000 3.500000 2412 -272 24.365654 -8.469363 6.000000 3.500000 2413 -274 31.531933 -16.859812 6.000000 3.500000 2423 -275 31.531933 -11.859812 6.000000 3.500000 2422 -277 26.322470 -29.595119 6.000000 3.500000 2433 -278 26.322470 -24.595119 6.000000 3.500000 2432 -280 19.393225 -25.022739 6.000000 3.500000 2442 -281 19.393225 -20.022739 6.000000 3.500000 2443 -283 21.906504 -47.260071 6.000000 3.500000 2512 -284 21.906504 -42.260071 6.000000 3.500000 2513 -286 31.762718 -35.773750 6.000000 3.500000 2522 -287 31.762718 -30.773750 6.000000 3.500000 2523 -289 31.462860 -47.927265 6.000000 3.500000 2533 -290 31.462860 -42.927265 6.000000 3.500000 2532 -292 19.023640 -58.637577 6.000000 3.500000 2543 -293 19.023640 -53.637577 6.000000 3.500000 2542 -295 40.724506 -4.266347 6.000000 3.500000 2612 -296 40.724506 0.733653 6.000000 3.500000 2613 -298 46.297695 -14.395032 6.000000 3.500000 2623 -299 46.297695 -9.395032 6.000000 3.500000 2622 -301 40.950874 -32.847042 6.000000 3.500000 2633 -302 40.950874 -27.847042 6.000000 3.500000 2632 -304 38.210819 -20.857738 6.000000 3.500000 2642 -305 38.210819 -15.857738 6.000000 3.500000 2643 diff --git a/external/fieldtrip/private/ReadHeader.m b/external/fieldtrip/private/ReadHeader.m new file mode 100644 index 0000000..bd6fcfe --- /dev/null +++ b/external/fieldtrip/private/ReadHeader.m @@ -0,0 +1,68 @@ +function H = ReadHeader(fp) + + +% H = ReadHeader(fp) +% +% Reads NSMA header, leaves file-read-location at end of header +% +% INPUT: + +% fid -- file-pointer (i.e. not filename) +% OUTPUT: + +% H -- cell array. Each entry is one line from the NSMA header + +% + +% Now works for files with no header. + +% ADR 1997 + +% version L4.1 + +% status: PROMOTED + + + +% v4.1 17 nov 98 now works for files sans header + + + +%--------------- + +% Get keys + +beginheader = '%%BEGINHEADER'; +endheader = '%%ENDHEADER'; + +iH = 1; H = {}; + +curfpos = ftell(fp); + + +%-------------- + +% go + + + +% look for beginheader + +headerLine = fgetl(fp); + +if strcmp(headerLine, beginheader) + + H{1} = headerLine; + + while ~feof(fp) & ~strcmp(headerLine, endheader) + headerLine = fgetl(fp); + iH = iH+1; + + H{iH} = headerLine; + + end + +else % no header + + fseek(fp, curfpos, 'bof'); +end diff --git a/external/fieldtrip/private/alpha_taper.m b/external/fieldtrip/private/alpha_taper.m index 008d094..9c0bbae 100644 --- a/external/fieldtrip/private/alpha_taper.m +++ b/external/fieldtrip/private/alpha_taper.m @@ -33,13 +33,23 @@ % Copyright (C) 2007, Robert Oostenveld % -% $Log: alpha_taper.m,v $ -% Revision 1.2 2007/08/06 15:00:03 roboos -% transposed the output, updated documentation +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.1 2007/08/01 16:20:27 roboos -% first implementation +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: alpha_taper.m 952 2010-04-21 18:29:51Z roboos $ % time axis expressed in cycles of the desired wavelet frequency t = ((-n+1):0) * f; diff --git a/external/fieldtrip/private/ama2vol.m b/external/fieldtrip/private/ama2vol.m index c7e155d..248b014 100644 --- a/external/fieldtrip/private/ama2vol.m +++ b/external/fieldtrip/private/ama2vol.m @@ -7,19 +7,23 @@ % Copyright (C) 2008, Robert Oostenveld % -% $Log: ama2vol.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.1 2008/01/28 19:56:13 roboos -% moved code from subfunction in prepare_bemmodel and prepare_vol_sens into seperate function -% renamed from convert_ama2vol +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ama2vol.m 945 2010-04-21 17:41:20Z roboos $ vol = []; ngeo = length(ama.geo); diff --git a/external/fieldtrip/private/analysisprotocol.m b/external/fieldtrip/private/analysisprotocol.m deleted file mode 100644 index 086dce9..0000000 --- a/external/fieldtrip/private/analysisprotocol.m +++ /dev/null @@ -1,365 +0,0 @@ -function [script, details] = analysisprotocol(cfg, datacfg) - -% ANALYSISPROTOCOL tries to reconstruct the complete analysis protocol that -% was used to create an arbitrary FieldTrip data structure. It will create -% a Matlab script (as text file) and a flowchart with a graphical -% representation. -% -% Use as -% ANALYSISPROTOCOL(cfg, data) -% where the first cfg input contains the settings that apply to the -% behaviour of this particular function and the second data input argument -% can be the output of any FieldTrip function, e.g. PREPROCESSING, -% TIMELOCKANALYSIS, SOURCEANALYSIS, FREQSTATISTICS or whatever you like. -% -% Alternatively, for the second input argument you can also only give the -% configuration of the processed data (i.e. "data.cfg") instead of the full -% data. -% -% The configuration options that apply to the behaviour of this function are -% cfg.feedback = 'no', 'text', 'gui' or 'yes', whether text and/or -% graphical feedback should be presented (default = 'yes') -% cfg.filename = string, filename of m-file to which the script will be -% written (default = []) -% cfg.remove = cell-array with strings, determines which objects will -% be removed from the configuration prior to writing it to -% file. For readibility of the script, you may want to -% remove the large objectssuch as event structure, trial -% definition, source positions -% cfg.keepremoved = 'yes' or 'no', determines whether removed fields are -% completely removed, or only replaced by a short textual -% description (default = 'no') -% -% This function uses the nested cfg and cfg.previous that are present in -% the data structure. It will use the configuration and the nested previous -% configurations to climb all the way back into the tree. This funtction -% will print a complete Matlab script to screen (and optionally to file). -% Furthermore, it will show an interactive graphical flowchart -% representation of the steps taken during the analysis. In the flowchart -% you can click on one of the steps to see the configuration details of -% that step. -% -% Note that the nested cfg and cfg.previous in your data might not contain -% all details that are required to reconstruct a complete and valid -% analysis script. - -% TODO the output of this function can perhaps be used as input for the wizard function - -% Copyright (C) 2006-2009, Robert Oostenveld -% -% $Log: analysisprotocol.m,v $ -% Revision 1.4 2009/05/07 07:58:35 roboos -% some general cleanup, don't know the precise details -% -% Revision 1.3 2009/03/23 21:17:53 roboos -% made font slightly larger -% -% Revision 1.2 2009/03/05 09:40:32 roboos -% small change in text feedback -% -% Revision 1.1 2009/03/05 09:38:31 roboos -% renamed cfg2script into analysisprotocol -% created wrapper for deprecated function that gives a warning -% updated documentation -% -% Revision 1.4 2009/03/05 09:07:40 roboos -% added graphical display of the analysis protocol -% changed some details of the recursion, now works with a few persistent variables -% -% Revision 1.3 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.2 2007/05/15 07:02:16 roboos -% updated help -% -% Revision 1.1 2006/12/04 16:03:18 roboos -% new implementation -% - -persistent depth % this corresponds to the vertical direction in the figure -persistent branch % this corresponds to the horizontal direction in the figure -persistent parent -persistent info - -fieldtripdefs - -% set the defaults -if ~isfield(cfg, 'filename'), cfg.filename = []; end -if ~isfield(cfg, 'keepremoved'), cfg.keepremoved = 'no'; end -if ~isfield(cfg, 'feedback'), cfg.feedback = 'yes'; end - -if ~isfield(cfg, 'remove') - % this is the default list of configuration elements to be removed. These - % elements would be very large to print and make the script difficult to - % read. To get a correctly behaving script, you may have to change this. - cfg.remove = { - 'sgncmb' - 'channelcmb' - 'event' - 'trl' - 'trlold' - 'artfctdef.eog.trl' - 'artfctdef.jump.trl' - 'artfctdef.muscle.trl' - 'pos' - 'inside' - 'outside' - 'grid.pos' - 'grid.inside' - 'grid.outside' - 'version.name' - 'version.id' - 'vol.bnd.pnt' - 'vol.bnd.tri' - }; -end - -feedbackgui = strcmp(cfg.feedback, 'gui') || strcmp(cfg.feedback, 'yes'); -feedbacktext = strcmp(cfg.feedback, 'text') || strcmp(cfg.feedback, 'yes'); - -% we are only interested in the cfg-part of the data -if isfield(datacfg, 'cfg') - datacfg = datacfg.cfg; -end - -% set up the persistent variables -if isempty(depth), depth = 1; end -if isempty(branch), branch = 1; end - -% start with an empty script -script = ''; - -% get the function call details before they are removed -try - thisname = getsubfield(datacfg, 'version.name'); - if isstruct(thisname) - % I think that this was needed for Matlab 6.5 - thisname = thisname.name; - end - [p, f] = fileparts(thisname); - thisname = f; -catch - thisname = 'unknown'; -end - -try - thisid = getsubfield(datacfg, 'version.id'); -catch - thisid = 'unknown'; -end - -if feedbacktext - % give some feedback on screen - fprintf('\n'); - fprintf('recursion depth = %d, branch = %d\n', depth, branch); - disp(thisname) - disp(thisid) -end - -% remove the fields that are too large or not interesting -for i=1:length(cfg.remove) - if issubfield(datacfg, cfg.remove{i}) - if feedbacktext - fprintf('removing %s\n', cfg.remove{i}); - end - siz = size(getsubfield(datacfg, cfg.remove{i})); - if strcmp(cfg.keepremoved, 'yes') - % keep the field, but replace the value with a descriptive string - datacfg = setsubfield(datacfg, cfg.remove{i}, sprintf('empty - this was cleared by analysisprotocol, original size = [%s]', num2str(siz))); - else - datacfg = rmsubfield(datacfg, cfg.remove{i}); - end - end -end - -% convert this part of the configuration to a matlab script -if isfield(datacfg, 'previous') - thiscfg = rmfield(datacfg, 'previous'); -else - thiscfg = datacfg; -end - -code = printstruct('cfg', thiscfg); -nl = sprintf('\n'); -emptycfg = sprintf('cfg = [];\n'); -sep = sprintf('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n'); -head1 = sprintf('%% version name = %s\n', thisname); -head2 = sprintf('%% version id = %s\n', thisid); -thisscript = [nl sep head1 head2 sep emptycfg code nl]; - -% remember this part of the configuration info -info(branch,depth).name = thisname; -info(branch,depth).id = thisid; -info(branch,depth).cfg = thiscfg; -info(branch,depth).script = thisscript; -info(branch,depth).this = [branch depth]; -info(branch,depth).parent = parent; -info(branch,depth).children = {}; % this will be determined later - -if isfield(datacfg, 'previous') - prev = parent; - parent = [branch depth]; % this will be used in the recursive call - if isstruct(datacfg.previous) - % increment the depth counter - depth = depth + 1; - % use recursion to parse the previous section of the tree - analysisprotocol(cfg, datacfg.previous); - elseif iscell(datacfg.previous) - for i=1:length(datacfg.previous(:)) - % increment the branch counter - branch = branch + (i>1); - % increment the depth counter - depth = depth + 1; - % use recursion to parse each previous section of the tree - analysisprotocol(cfg, datacfg.previous{i}); - end - end - % revert to the orignal parent - parent = prev; -end - -if depth==1 - % the recursion has finished, we are again at the top level - - % the parents were determined while climbing up the tree - % now it is time to descend and determine the children - for branch=1:size(info,1) - for depth=1:size(info,2) - if ~isempty(info(branch, depth).parent) - parentbranch = info(branch, depth).parent(1); - parentdepth = info(branch, depth).parent(2); - info(parentbranch, parentdepth).children{end+1} = [branch depth]; - end - end - end - - % complement the individual scripts with the input and output variables - % and the actual function call - for branch=1:size(info,1) - for depth=1:size(info,2) - outputvar = sprintf('var_%d_%d', info(branch, depth).this); - inputvar = ''; - commandline = sprintf('%s = %s(cfg%s);', outputvar, info(branch, depth).name, inputvar); - disp(commandline); - - end - end - - if nargout>0 - % return the complete script as output argument - script = ''; - for branch=1:size(info,1) - for depth=1:size(info,2) - script = [info(branch,depth).script script]; - end - end - end - - if nargout>1 - % return the information details as output argument - details = info; - end - - if feedbackgui - fig = figure; - hold on - % the axis should not change during the contruction of the arrows, - % otherwise the arrowheads will be distorted - axis manual; - for branch=1:size(info,1) - for depth=1:size(info,2) - plotinfo(info(branch,depth)); - end - end - axis auto - axis off - guidata(fig,info); - set(fig, 'WindowButtonUpFcn', @button); - set(fig, 'KeyPressFcn', @key); - end % feedbackgui - - if ~isempty(cfg.filename) - % write the complete script to file - fprintf('writing result to file ''%s''\n', cfg.filename); - fid = fopen(cfg.filename, 'wb'); - fprintf(fid, '%s', script); - fclose(fid); - end - - % clear all persistent variables - depth = []; - branch = []; - info = []; - parent = []; - fig = []; -else - % this level of recursion has finished, decrease the depth - depth = depth - 1; -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function plotinfo(element) -if isempty(element.name) - return -end -w = 0.6; -h = 0.3; -% create the 4 courners that can be used as patch -x = [-w/2 w/2 w/2 -w/2]; -y = [-h/2 -h/2 h/2 h/2]; -% close the patch -x = [x x(end)]; -y = [y y(end)]; -% move the patch to the desired location -x = element.this(1) + x; -y = element.this(2) + y; - -p = patch(x', y', 0); -set(p, 'Facecolor', [1 1 0.6]) - -label{1} = element.name; -% label{2} = num2str(element.this); - -l = text(element.this(1), element.this(2), label); -set(l, 'HorizontalAlignment', 'center') -set(l, 'interpreter', 'none') -set(l, 'fontUnits', 'normalized') -set(l, 'fontSize', 0.03) -% set(l, 'fontName', 'courier') - -% draw an arrow to connect this box to its parent -if ~isempty(element.parent) - base = element.this - [0 h/2]; - tip = element.parent + [0 h/2]; - % ARROW(Start,Stop,Length,BaseAngle,TipAngle,Width,Page,CrossDir) - arrow(base, tip, [], [], [], [], [], []); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function varargout = key(h, eventdata, handles, varargin) -% this is just a placeholder for future functionality -% at the moment it does not do anything - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function varargout = button(h, eventdata, handles, varargin) -pos = get(get(gcbo, 'CurrentAxes'), 'CurrentPoint'); -x = pos(1,1); -y = pos(1,2); -info = guidata(h); -dist = zeros(size(info)) + inf; -for i=1:numel(info) - if ~isempty(info(i).this) - dist(i) = norm(info(i).this - [x y]); - end -end -% determine the box that is nearest by the mouse click -[m, indx] = min(dist(:)); -% show the information contained in that box -uidisplaytext(info(indx).script, info(indx).name); - diff --git a/external/fieldtrip/private/appenddata.m b/external/fieldtrip/private/appenddata.m deleted file mode 100644 index ef2fcc6..0000000 --- a/external/fieldtrip/private/appenddata.m +++ /dev/null @@ -1,238 +0,0 @@ -function [data] = appenddata(cfg, varargin); - -% APPENDDATA combines multiple datasets that have been preprocessed separately -% into a single large dataset. -% -% Use as -% data = appenddata(cfg, data1, data2, data3, ...) -% where the configuration can be empty. -% -% If the input datasets all have the same channels, the trials will be -% concatenated. This is useful for example if you have different -% experimental conditions, which, besides analyzing them separately, for -% some reason you also want to analyze together. The function will check -% for consistency in the order of the channels. If the order is inconsistent -% the channel order of the output will be according to the channel order of -% the first data structure in the input. -% -% If the input datasets have different channels, but the same number of -% trials, the channels will be concatenated within each trial. This is -% useful for example if the data that you want to analyze contains both -% MEG and EMG channels which require different preprocessing options. -% -% Occasionally, the data needs to be concatenated in the trial dimension while -% there's a slight discrepancy in the channels in the input data (e.g. missing -% channels in one of the data structures). The function will then return a data -% structure containing only the channels which are present in all inputs. -% See also PREPROCESSING - -% undocumented options: -% none - -% Copyright (C) 2005-2008, Robert Oostenveld -% Copyright (C) 2009, Jan-Mathijs Schoffelen -% -% $Log: appenddata.m,v $ -% Revision 1.17 2009/04/30 14:42:20 jansch -% included explicit check on the channel order in the inputs. if the order is -% not the same the channels will be reordered according to the first input. -% included possibility to concatenate in the trial dimension when the number of -% channels is not entirely consistent (missing channels). updated documentation -% -% Revision 1.16 2008/09/22 20:17:42 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.15 2007/11/13 15:25:07 roboos -% removed handling of spike data, since that can be done in appendspike -% -% Revision 1.14 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.13 2007/03/30 17:05:40 ingnie -% checkinput; only proceed when input data is allowed datatype -% -% Revision 1.12 2007/01/09 09:50:39 roboos -% some changes in whitespace -% -% Revision 1.11 2007/01/04 17:06:33 roboos -% implemented support for appending spike data (i.e. timestamps) to a continuously sampled data set (i.e. one obtained from PREPROCESSING) -% -% Revision 1.10 2006/07/24 11:29:29 roboos -% use private/findcfg function for locating the trl and event in the nested (previous) cfgs -% -% Revision 1.9 2006/05/02 19:17:04 roboos -% search for th trl in cfg and cfg.previous etc., and also append it -% -% Revision 1.8 2006/04/20 09:58:33 roboos -% updated documentation -% -% Revision 1.7 2006/01/30 12:15:01 roboos -% ensure consistent function declaration: "function [x] = funname()" -% -% Revision 1.6 2005/08/05 09:16:22 roboos -% removed the obsolete data.offset -% -% Revision 1.5 2005/06/29 12:46:29 roboos -% the following changes were done on a large number of files at the same time, not all of them may apply to this specific file -% - added try-catch around the inclusion of input data configuration -% - moved cfg.version, cfg.previous and the assignment of the output cfg to the end -% - changed help comments around the configuration handling -% - some changes in whitespace -% -% Revision 1.4 2005/03/14 11:17:29 jansch -% fixed small bug in handling of dimensions in the case of concatenating trials -% -% Revision 1.3 2005/02/16 17:07:13 roboos -% fixed error that occurred when input data label was not a column-cell-array -% -% Revision 1.2 2005/01/27 12:06:33 roboos -% fixed bug in checking of identical time axes -% -% Revision 1.1 2005/01/17 14:39:43 roboos -% new implementation -% - -fieldtripdefs - -% check if the input data is valid for this function -for i=1:length(varargin) - varargin{i} = checkdata(varargin{i}, 'datatype', 'raw', 'feedback', 'no'); -end - -% set the defaults -cfg = []; - -Ndata = nargin-1; -if Ndata<2 - error('you must give at least two datasets to append'); -end - -% determine the dimensions of the data -Nchan = zeros(1,Ndata); -Ntrial = zeros(1,Ndata); -label = {}; -for i=1:Ndata - Nchan(i) = length(varargin{i}.label); - Ntrial(i) = length(varargin{i}.trial); - fprintf('input dataset %d, %d channels, %d trials\n', i, Nchan(i), Ntrial(i)); - label = [label(:); varargin{i}.label(:)]; -end - -% try to locate the trial definition (trl) in the nested configuration -for i=1:Ndata - if isfield(varargin{i}, 'cfg') - trl{i} = findcfg(varargin{i}.cfg, 'trl'); - else - trl{i} = []; - end - if isempty(trl{i}) - % a trial definition is expected in each continuous data set - warning(sprintf('could not locate the trial definition ''trl'' in data structure %d', i)); - end -end - -% check the consistency of the labels across the input-structures -[alllabel, indx1, indx2] = unique(label, 'first'); -order = zeros(length(alllabel),Ndata); -for i=1:length(alllabel) - for j=1:Ndata - tmp = strmatch(alllabel{i}, varargin{j}.label, 'exact'); - if ~isempty(tmp) - order(i,j) = tmp; - end - end -end - -catlabel = all(sum(order~=0,2)==1); -cattrial = any(sum(order~=0,2)==Ndata); -shuflabel = cattrial && ~all(all(order-repmat(order(:,1),[1 Ndata])==0)); -prunelabel = cattrial && sum(sum(order~=0,2)==Ndata). +% +% $Id: appendevent.m 945 2010-04-21 17:41:20Z roboos $ if isempty(a) c = b(:); @@ -38,4 +42,4 @@ c(end ).duration = b(i).duration; % optional end end -end \ No newline at end of file +end diff --git a/external/fieldtrip/private/appendspike.m b/external/fieldtrip/private/appendspike.m deleted file mode 100644 index c963f40..0000000 --- a/external/fieldtrip/private/appendspike.m +++ /dev/null @@ -1,135 +0,0 @@ -function [data] = appendspike(cfg, varargin); - -% APPENDSPIKE combines continuous data (i.e. LFP) with point-process data -% (i.e. spikes) into a single large dataset. For each spike channel an -% additional continuuos channel is inserted in the data that contains -% zeros most of the time, and an occasional one at the samples at which a -% spike occurred. The continuous and spike data are linked together using -% the timestamps. -% -% Use as -% [spike] = appendspike(cfg, spike1, spike2, spike3, ...) -% where the input structures come from READ_FCDC_SPIKE, or as -% [data] = appendspike(cfg, data, spike1, spike2, ...) -% where the first data structure is the result of PREPROCESSING -% and the subsequent ones come from READ_FCDC_SPIKE. -% -% See also APPENDDATA, PREPROCESSING - -% Copyright (C) 2007, Robert Osotenveld -% -% $Log: appendspike.m,v $ -% Revision 1.4 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.3 2008/04/25 12:30:22 roboos -% enabled the checkdata call at the beginning -% -% Revision 1.2 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.1 2007/03/14 13:57:04 roboos -% initial implementation, tested on neuralynx data -% - -fieldtripdefs - -isspike = zeros(size(varargin)); -for i=1:length(varargin) - % this is a quick test, more rigourous checking is done later - isspike(i) = isfield(varargin{i}, 'timestamp') & isfield(varargin{i}, 'label'); -end - -if all(isspike) - spike = {}; - for i=1:length(varargin) - spike{i} = checkdata(varargin{i}, 'datatype', 'spike'); - end - - % check the validity of the channel labels - label = {}; - for i=1:length(spike) - label = cat(1, label, spike{i}.label(:)); - end - if length(unique(label))~=length(label) - error('not all channel labels are unique'); - end - - % concatenate the spikes - data = spike{1}; - for i=2:length(spike) - data.label = cat(2, data.label, spike{i}.label); - data.waveform = cat(2, data.waveform, spike{i}.waveform); - data.timestamp = cat(2, data.timestamp, spike{i}.timestamp); - data.unit = cat(2, data.unit, spike{i}.unit); - end - -else - % this checks the validity of the input data and simultaneously renames it for convenience - data = varargin{1}; % checkdata(varargin{1}, 'datatype', 'raw'); - spike = appendspike([], varargin{2:end}); - - % check the validity of the channel labels - label = cat(1, data.label(:), spike.label(:)); - if length(unique(label))~=length(label) - error('not all channel labels are unique'); - end - - trl = findcfg(data.cfg, 'trl'); - if isempty(trl); - error('could not find the trial information in the continuous data'); - end - - try - FirstTimeStamp = data.hdr.FirstTimeStamp; - TimeStampPerSample = data.hdr.TimeStampPerSample; - catch - error('could not find the timestamp information in the continuous data'); - end - - for i=1:length(spike.label) - % append the data with an empty channel - data.label{end+1} = spike.label{i}; - for j=1:size(trl,1) - data.trial{j}(end+1,:) = 0; - end - - % determine the corresponding sample numbers for each timestamp - ts = spike.timestamp{i}; - % timestamps can be uint64, hence explicitely convert to double at the right moment - sample = round(double(ts-FirstTimeStamp)/TimeStampPerSample + 1); - - fprintf('adding spike channel %s\n', spike.label{i}); - for j=1:size(trl,1) - begsample = trl(j,1); - endsample = trl(j,2); - sel = find((sample>=begsample) & (sample<=endsample)); - fprintf('adding spike channel %s, trial %d contains %d spikes\n', spike.label{i}, j, length(sel)); - for k=1:length(sel) - indx = sample(sel(k))-begsample+1; - data.trial{j}(end,indx) = data.trial{j}(end,indx)+1; - end % for k - end % for j - end % for i - -end - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: appendspike.m,v 1.4 2008/09/22 20:17:43 roboos Exp $'; -% remember the configuration details of the input data -cfg.previous = []; -for i=1:length(varargin) - try, cfg.previous{i} = varargin{i}.cfg; end -end -% remember the exact configuration details in the output -data.cfg = cfg; - - diff --git a/external/fieldtrip/private/apply_montage.m b/external/fieldtrip/private/apply_montage.m deleted file mode 100644 index ccf0716..0000000 --- a/external/fieldtrip/private/apply_montage.m +++ /dev/null @@ -1,226 +0,0 @@ -function [sens] = apply_montage(sens, montage, varargin) - -% APPLY_MONTAGE changes the montage of an electrode or gradiometer array. A -% montage can be used for EEG rereferencing, MEG synthetic gradients, MEG -% planar gradients or unmixing using ICA. This function applies the montage -% to the sensor array. The sensor array can subsequently be used for -% forward computation and source reconstruction of the data. -% -% Use as -% [sens] = apply_montage(sens, montage, ...) -% [data] = apply_montage(data, montage, ...) -% [montage] = apply_montage(montage1, montage2, ...) -% where the input is a FieldTrip sensor definition as obtained from READ_SENS -% or a FieldTrip raw data structure as obtained from PREPROCESSING. -% -% A montage is specified as a structure with the fields -% montage.tra = MxN matrix -% montage.labelnew = Mx1 cell-array -% montage.labelorg = Nx1 cell-array -% -% Additional options should be specified in key-value pairs and can be -% 'keepunused' string, 'yes' or 'no' (default = 'no') -% 'inverse' string, 'yes' or 'no' (default = 'no') -% -% If the first input is a montage, then the second input montage will be -% applied to the first. In effect the resulting montage will first do -% montage1, then montage2. -% -% See also READ_SENS, TRANSFORM_SENS - -% Copyright (C) 2008, Robert Oostenveld -% -% $Log: apply_montage.m,v $ -% Revision 1.19 2009/07/02 16:14:15 roboos -% allow to apply one montage on another one -% -% Revision 1.18 2009/07/02 09:18:41 vlalit -% Fixing a bug in building an inverse montage (confusion between 'montage' and 'tra') -% -% Revision 1.17 2009/07/01 09:21:37 roboos -% changed handling of rank-reduced montage for inversion, give warning -% removed the modification by vladimir for the sequential application of montages -% -% Revision 1.16 2009/06/27 13:24:54 vlalit -% Additional fixes to make custom balancing work. -% -% Revision 1.15 2009/06/26 17:39:17 vlalit -% Added the possiblity to handle custom montages applied to MEG sensors (for removing -% spatial confounds). Hopefully there won't be major side effects. -% -% Revision 1.14 2009/06/17 10:13:05 roboos -% improved documentation -% -% Revision 1.13 2009/03/26 11:07:40 roboos -% start with an explicit check on the channel number -% -% Revision 1.12 2009/03/26 11:02:01 jansch -% changed order of unused channels (was initially sorted alphabetically) into -% how the appear in the input data -% -% Revision 1.11 2008/12/15 12:58:56 roboos -% convert from sparse to full when data is single precision -% -% Revision 1.10 2008/09/10 08:42:23 roboos -% fixed small bug, thanks to Vladimir -% -% Revision 1.9 2008/08/21 12:03:37 roboos -% fixed small typo related to last commit -% -% Revision 1.8 2008/08/21 12:01:47 roboos -% selection of rows and columns to be removed had to be inverted, thanks to Thilo -% -% Revision 1.7 2008/08/13 16:14:46 roboos -% remove columns and rows for montage channels that are not present in the data -% -% Revision 1.6 2008/07/17 14:46:06 roboos -% check on presence of channels required for montage was incorrect -% -% Revision 1.5 2008/05/15 15:08:51 roboos -% added support for applying the inverse montage (i.e. undo a previous montage) -% added support for applying the montage to preprocessed/raw data -% -% Revision 1.4 2008/05/13 11:43:27 roboos -% fixed bug in selempty -% -% Revision 1.3 2008/05/13 09:08:19 roboos -% fixed bug in assignment -% added option keepunused=yes|no -% -% Revision 1.2 2008/04/28 14:14:29 roboos -% added closing bracket -% -% Revision 1.1 2008/04/14 20:16:37 roboos -% new implementation, required for spm integration -% - -% get optional input arguments -keepunused = keyval('keepunused', varargin{:}); if isempty(keepunused), keepunused = 'no'; end -inverse = keyval('inverse', varargin{:}); if isempty(inverse), inverse = 'no'; end - -% check the consistency of the input sensor array or data -if isfield(sens, 'labelorg') && isfield(sens, 'labelnew') - % the input data structure is also a montage, i.e. apply the montages sequentially - sens.label = sens.labelnew; -end - -% check the consistency of the montage -if size(montage.tra,1)~=length(montage.labelnew) - error('the number of channels in the montage is inconsistent'); -elseif size(montage.tra,2)~=length(montage.labelorg) - error('the number of channels in the montage is inconsistent'); -end - -if strcmp(inverse, 'yes') - % apply the inverse montage, i.e. undo a previously applied montage - tmp.labelnew = montage.labelorg; % swap around - tmp.labelorg = montage.labelnew; % swap around - tmp.tra = full(montage.tra); - if rank(tmp.tra) < length(tmp.tra) - warning('the linear projection for the montage is not full-rank, the resulting data will have reduced dimensionality'); - tmp.tra = pinv(tmp.tra); - else - tmp.tra = inv(tmp.tra); - end - montage = tmp; -end - -% use default transfer from sensors to channels if not specified -if ~isfield(sens, 'tra') && ~isfield(sens, 'trial') - nchan = size(sens.pnt,1); - sens.tra = sparse(eye(nchan)); -end - -% select and keep the columns that are non-empty, i.e. remove the empty columns -selcol = find(~all(montage.tra==0, 1)); -montage.tra = montage.tra(:,selcol); -montage.labelorg = montage.labelorg(selcol); -clear selcol - -% select and remove the columns corresponding to channels that are not present in the original data -remove = setdiff(montage.labelorg, intersect(montage.labelorg, sens.label)); -selcol = match_str(montage.labelorg, remove); -% we cannot just remove the colums, all rows that depend on it should also be removed -selrow = false(length(montage.labelnew),1); -for i=1:length(selcol) - selrow = selrow & (montage.tra(:,selcol(i))~=0); -end -% convert from indices to logical vector -selcol = indx2logical(selcol, length(montage.labelorg)); -% remove rows and columns -montage.labelorg = montage.labelorg(~selcol); -montage.labelnew = montage.labelnew(~selrow); -montage.tra = montage.tra(~selrow, ~selcol); -clear remove selcol selrow i -% add columns for the channels that are present in the data but not involved in the montage, and stick to the original order in the data -[add, ix] = setdiff(sens.label, montage.labelorg); -add = sens.label(sort(ix)); -m = size(montage.tra,1); -n = size(montage.tra,2); -k = length(add); -if strcmp(keepunused, 'yes') - % add the channels that are not rereferenced to the input and output - montage.tra((m+(1:k)),(n+(1:k))) = eye(k); - montage.labelorg = cat(1, montage.labelorg(:), add(:)); - montage.labelnew = cat(1, montage.labelnew(:), add(:)); -else - % add the channels that are not rereferenced to the input montage only - montage.tra(:,(n+(1:k))) = zeros(m,k); - montage.labelorg = cat(1, montage.labelorg(:), add(:)); -end -clear add m n k - -% determine whether all channels are unique -m = size(montage.tra,1); -n = size(montage.tra,2); -if length(unique(montage.labelnew))~=m - error('not all output channels of the montage are unique'); -end -if length(unique(montage.labelorg))~=n - error('not all input channels of the montage are unique'); -end - -% determine whether all channels that have to be rereferenced are available -if length(intersect(sens.label, montage.labelorg))~=length(montage.labelorg) - error('not all channels that are required in the montage are available in the data'); -end - -% reorder the columns of the montage matrix -[selsens, selmont] = match_str(sens.label, montage.labelorg); -montage.tra = sparse(montage.tra(:,selmont)); -montage.labelorg = montage.labelorg(selmont); - -if isfield(sens, 'labelorg') && isfield(sens, 'labelnew') - % apply the montage on top of the other montage - sens = rmfield(sens, 'label'); - sens.tra = montage.tra * sens.tra; - sens.labelnew = montage.labelnew; - -elseif isfield(sens, 'tra') - % apply the montage to the sensor array - sens.tra = montage.tra * sens.tra; - sens.label = montage.labelnew; - -elseif isfield(sens, 'trial') - % apply the montage to the data that was preprocessed using fieldtrip - Ntrials = numel(sens.trial); - for i=1:Ntrials - fprintf('processing trial %d from %d\n', i, Ntrials); - if isa(sens.trial{i}, 'single') - % sparse matrices and single precision do not match - sens.trial{i} = full(montage.tra) * sens.trial{i}; - else - sens.trial{i} = montage.tra * sens.trial{i}; - end - end - sens.label = montage.labelnew; -else - error('unrecognized input'); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% HELPER FUNCTION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function y = indx2logical(x, n) -y = false(1,n); -y(x) = true; diff --git a/external/fieldtrip/private/arrow.m b/external/fieldtrip/private/arrow.m index ac0f005..67b7824 100644 --- a/external/fieldtrip/private/arrow.m +++ b/external/fieldtrip/private/arrow.m @@ -1 +1,1358 @@ -function [h,yy,zz] = arrow(varargin) % ARROW Draw a line with an arrowhead. % % ARROW(Start,Stop) draws a line with an arrow from Start to Stop (points % should be vectors of length 2 or 3, or matrices with 2 or 3 % columns), and returns the graphics handle of the arrow(s). % % ARROW uses the mouse (click-drag) to create an arrow. % % ARROW DEMO & ARROW DEMO2 show 3-D & 2-D demos of the capabilities of ARROW. % % ARROW may be called with a normal argument list or a property-based list. % ARROW(Start,Stop,Length,BaseAngle,TipAngle,Width,Page,CrossDir) is % the full normal argument list, where all but the Start and Stop % points are optional. If you need to specify a later argument (e.g., % Page) but want default values of earlier ones (e.g., TipAngle), % pass an empty matrix for the earlier ones (e.g., TipAngle=[]). % % ARROW('Property1',PropVal1,'Property2',PropVal2,...) creates arrows with the % given properties, using default values for any unspecified or given as % 'default' or NaN. Some properties used for line and patch objects are % used in a modified fashion, others are passed directly to LINE, PATCH, % or SET. For a detailed properties explanation, call ARROW PROPERTIES. % % Start The starting points. B % Stop The end points. /|\ ^ % Length Length of the arrowhead in pixels. /|||\ | % BaseAngle Base angle in degrees (ADE). //|||\\ L| % TipAngle Tip angle in degrees (ABC). ///|||\\\ e| % Width Width of the base in pixels. ////|||\\\\ n| % Page Use hardcopy proportions. /////|D|\\\\\ g| % CrossDir Vector || to arrowhead plane. //// ||| \\\\ t| % NormalDir Vector out of arrowhead plane. /// ||| \\\ h| % Ends Which end has an arrowhead. //<----->|| \\ | % ObjectHandles Vector of handles to update. / base ||| \ V % E angle||<-------->C % ARROW(H,'Prop1',PropVal1,...), where H is a |||tipangle % vector of handles to previously-created arrows ||| % and/or line objects, will update the previously- ||| % created arrows according to the current view -->|A|<-- width % and any specified properties, and will convert % two-point line objects to corresponding arrows. ARROW(H) will update % the arrows if the current view has changed. Root, figure, or axes % handles included in H are replaced by all descendant Arrow objects. % % A property list can follow any specified normal argument list, e.g., % ARROW([1 2 3],[0 0 0],36,'BaseAngle',60) creates an arrow from (1,2,3) to % the origin, with an arrowhead of length 36 pixels and 60-degree base angle. % % The basic arguments or properties can generally be vectorized to create % multiple arrows with the same call. This is done by passing a property % with one row per arrow, or, if all arrows are to have the same property % value, just one row may be specified. % % You may want to execute AXIS(AXIS) before calling ARROW so it doesn't change % the axes on you; ARROW determines the sizes of arrow components BEFORE the % arrow is plotted, so if ARROW changes axis limits, arrows may be malformed. % % This version of ARROW uses features of MATLAB 5 and is incompatible with % earlier MATLAB versions (ARROW for MATLAB 4.2c is available separately); % some problems with perspective plots still exist. % Copyright (c)1995-2002, Dr. Erik A. Johnson , 11/15/02 % Revision history: % 11/15/02 EAJ Accomodate how MATLAB 6.5 handles NaN and logicals % 7/28/02 EAJ Tried (but failed) work-around for MATLAB 6.x / OpenGL bug % if zero 'Width' or not double-ended % 11/10/99 EAJ Add logical() to eliminate zero index problem in MATLAB 5.3. % 11/10/99 EAJ Corrected warning if axis limits changed on multiple axes. % 11/10/99 EAJ Update e-mail address. % 2/10/99 EAJ Some documentation updating. % 2/24/98 EAJ Fixed bug if Start~=Stop but both colinear with viewpoint. % 8/14/97 EAJ Added workaround for MATLAB 5.1 scalar logical transpose bug. % 7/21/97 EAJ Fixed a few misc bugs. % 7/14/97 EAJ Make arrow([],'Prop',...) do nothing (no old handles) % 6/23/97 EAJ MATLAB 5 compatible version, release. % 5/27/97 EAJ Added Line Arrows back in. Corrected a few bugs. % 5/26/97 EAJ Changed missing Start/Stop to mouse-selected arrows. % 5/19/97 EAJ MATLAB 5 compatible version, beta. % 4/13/97 EAJ MATLAB 5 compatible version, alpha. % 1/31/97 EAJ Fixed bug with multiple arrows and unspecified Z coords. % 12/05/96 EAJ Fixed one more bug with log plots and NormalDir specified % 10/24/96 EAJ Fixed bug with log plots and NormalDir specified % 11/13/95 EAJ Corrected handling for 'reverse' axis directions % 10/06/95 EAJ Corrected occasional conflict with SUBPLOT % 4/24/95 EAJ A major rewrite. % Fall 94 EAJ Original code. % Things to be done: % - segment parsing, computing, and plotting into separate subfunctions % - change computing from Xform to Camera paradigms % + this will help especially with 3-D perspective plots % + if the WarpToFill section works right, remove warning code % + when perpsective works properly, remove perspective warning code % - add cell property values and struct property name/values (like get/set) % - get rid of NaN as the "default" data label % + perhaps change userdata to a struct and don't include (or leave % empty) the values specified as default; or use a cell containing % an empty matrix for a default value % - add functionality of GET to retrieve current values of ARROW properties % Many thanks to Keith Rogers for his many excellent % suggestions and beta testing. Check out his shareware package MATDRAW % (at ftp://ftp.mathworks.com/pub/contrib/v5/graphics/matdraw/) -- he has % permission to distribute ARROW with MATDRAW. % Permission is granted to distribute ARROW with the toolboxes for the book % "Solving Solid Mechanics Problems with MATLAB 5", by F. Golnaraghi et al. % (Prentice Hall, 1999). % global variable initialization global ARROW_PERSP_WARN ARROW_STRETCH_WARN ARROW_AXLIMITS if isempty(ARROW_PERSP_WARN ), ARROW_PERSP_WARN =1; end; if isempty(ARROW_STRETCH_WARN), ARROW_STRETCH_WARN=1; end; % Handle callbacks if (nargin>0 & isstr(varargin{1}) & strcmp(lower(varargin{1}),'callback')), arrow_callback(varargin{2:end}); return; end; % Are we doing the demo? c = sprintf('\n'); if (nargin==1 & isstr(varargin{1})), arg1 = lower(varargin{1}); if strncmp(arg1,'prop',4), arrow_props; elseif strncmp(arg1,'demo',4) clf reset demo_info = arrow_demo; if ~strncmp(arg1,'demo2',5), hh=arrow_demo3(demo_info); else, hh=arrow_demo2(demo_info); end; if (nargout>=1), h=hh; end; elseif strncmp(arg1,'fixlimits',3), arrow_fixlimits(ARROW_AXLIMITS); ARROW_AXLIMITS=[]; elseif strncmp(arg1,'help',4), disp(help(mfilename)); else, error([upper(mfilename) ' got an unknown single-argument string ''' deblank(arg1) '''.']); end; return; end; % Check # of arguments if (nargout>3), error([upper(mfilename) ' produces at most 3 output arguments.']); end; % find first property number firstprop = nargin+1; for k=1:length(varargin), if ~isnumeric(varargin{k}), firstprop=k; break; end; end; lastnumeric = firstprop-1; % check property list if (firstprop<=nargin), for k=firstprop:2:nargin, curarg = varargin{k}; if ~isstr(curarg) | sum(size(curarg)>1)>1, error([upper(mfilename) ' requires that a property name be a single string.']); end; end; if (rem(nargin-firstprop,2)~=1), error([upper(mfilename) ' requires that the property ''' ... varargin{nargin} ''' be paired with a property value.']); end; end; % default output if (nargout>0), h=[]; end; if (nargout>1), yy=[]; end; if (nargout>2), zz=[]; end; % set values to empty matrices start = []; stop = []; len = []; baseangle = []; tipangle = []; wid = []; page = []; crossdir = []; ends = []; ax = []; oldh = []; ispatch = []; defstart = [NaN NaN NaN]; defstop = [NaN NaN NaN]; deflen = 16; defbaseangle = 90; deftipangle = 16; defwid = 0; defpage = 0; defcrossdir = [NaN NaN NaN]; defends = 1; defoldh = []; defispatch = 1; % The 'Tag' we'll put on our arrows ArrowTag = 'Arrow'; % check for oldstyle arguments if (firstprop==2), % assume arg1 is a set of handles oldh = varargin{1}(:); if isempty(oldh), return; end; elseif (firstprop>9), error([upper(mfilename) ' takes at most 8 non-property arguments.']); elseif (firstprop>2), s = str2mat('start','stop','len','baseangle','tipangle','wid','page','crossdir'); for k=1:firstprop-1, eval([deblank(s(k,:)) '=varargin{k};']); end; end; % parse property pairs extraprops={}; for k=firstprop:2:nargin, prop = varargin{k}; val = varargin{k+1}; prop = [lower(prop(:)') ' ']; if strncmp(prop,'start' ,5), start = val; elseif strncmp(prop,'stop' ,4), stop = val; elseif strncmp(prop,'len' ,3), len = val(:); elseif strncmp(prop,'base' ,4), baseangle = val(:); elseif strncmp(prop,'tip' ,3), tipangle = val(:); elseif strncmp(prop,'wid' ,3), wid = val(:); elseif strncmp(prop,'page' ,4), page = val; elseif strncmp(prop,'cross' ,5), crossdir = val; elseif strncmp(prop,'norm' ,4), if (isstr(val)), crossdir=val; else, crossdir=val*sqrt(-1); end; elseif strncmp(prop,'end' ,3), ends = val; elseif strncmp(prop,'object',6), oldh = val(:); elseif strncmp(prop,'handle',6), oldh = val(:); elseif strncmp(prop,'type' ,4), ispatch = val; elseif strncmp(prop,'userd' ,5), %ignore it else, % make sure it is a valid patch or line property eval('get(0,[''DefaultPatch'' varargin{k}]);err=0;','err=1;'); errstr=lasterr; if (err), eval('get(0,[''DefaultLine'' varargin{k}]);err=0;','err=1;'); end; if (err), errstr(1:max(find(errstr==setstr(13)|errstr==setstr(10)))) = ''; error([upper(mfilename) ' got ' errstr]); end; extraprops={extraprops{:},varargin{k},val}; end; end; % Check if we got 'default' values start = arrow_defcheck(start ,defstart ,'Start' ); stop = arrow_defcheck(stop ,defstop ,'Stop' ); len = arrow_defcheck(len ,deflen ,'Length' ); baseangle = arrow_defcheck(baseangle,defbaseangle,'BaseAngle' ); tipangle = arrow_defcheck(tipangle ,deftipangle ,'TipAngle' ); wid = arrow_defcheck(wid ,defwid ,'Width' ); crossdir = arrow_defcheck(crossdir ,defcrossdir ,'CrossDir' ); page = arrow_defcheck(page ,defpage ,'Page' ); ends = arrow_defcheck(ends ,defends ,'' ); oldh = arrow_defcheck(oldh ,[] ,'ObjectHandles'); ispatch = arrow_defcheck(ispatch ,defispatch ,'' ); % check transpose on arguments [m,n]=size(start ); if any(m==[2 3])&(n==1|n>3), start = start'; end; [m,n]=size(stop ); if any(m==[2 3])&(n==1|n>3), stop = stop'; end; [m,n]=size(crossdir); if any(m==[2 3])&(n==1|n>3), crossdir = crossdir'; end; % convert strings to numbers if ~isempty(ends) & isstr(ends), endsorig = ends; [m,n] = size(ends); col = lower([ends(:,1:min(3,n)) ones(m,max(0,3-n))*' ']); ends = NaN*ones(m,1); oo = ones(1,m); ii=find(all(col'==['non']'*oo)'); if ~isempty(ii), ends(ii)=ones(length(ii),1)*0; end; ii=find(all(col'==['sto']'*oo)'); if ~isempty(ii), ends(ii)=ones(length(ii),1)*1; end; ii=find(all(col'==['sta']'*oo)'); if ~isempty(ii), ends(ii)=ones(length(ii),1)*2; end; ii=find(all(col'==['bot']'*oo)'); if ~isempty(ii), ends(ii)=ones(length(ii),1)*3; end; if any(isnan(ends)), ii = min(find(isnan(ends))); error([upper(mfilename) ' does not recognize ''' deblank(endsorig(ii,:)) ''' as a valid ''Ends'' value.']); end; else, ends = ends(:); end; if ~isempty(ispatch) & isstr(ispatch), col = lower(ispatch(:,1)); patchchar='p'; linechar='l'; defchar=' '; mask = col~=patchchar & col~=linechar & col~=defchar; if any(mask), error([upper(mfilename) ' does not recognize ''' deblank(ispatch(min(find(mask)),:)) ''' as a valid ''Type'' value.']); end; ispatch = (col==patchchar)*1 + (col==linechar)*0 + (col==defchar)*defispatch; else, ispatch = ispatch(:); end; oldh = oldh(:); % check object handles if ~all(ishandle(oldh)), error([upper(mfilename) ' got invalid object handles.']); end; % expand root, figure, and axes handles if ~isempty(oldh), ohtype = get(oldh,'Type'); mask = strcmp(ohtype,'root') | strcmp(ohtype,'figure') | strcmp(ohtype,'axes'); if any(mask), oldh = num2cell(oldh); for ii=find(mask)', oldh(ii) = {findobj(oldh{ii},'Tag',ArrowTag)}; end; oldh = cat(1,oldh{:}); if isempty(oldh), return; end; % no arrows to modify, so just leave end; end; % largest argument length [mstart,junk]=size(start); [mstop,junk]=size(stop); [mcrossdir,junk]=size(crossdir); argsizes = [length(oldh) mstart mstop ... length(len) length(baseangle) length(tipangle) ... length(wid) length(page) mcrossdir length(ends) ]; args=['length(ObjectHandle) '; ... '#rows(Start) '; ... '#rows(Stop) '; ... 'length(Length) '; ... 'length(BaseAngle) '; ... 'length(TipAngle) '; ... 'length(Width) '; ... 'length(Page) '; ... '#rows(CrossDir) '; ... '#rows(Ends) ']; if (any(imag(crossdir(:))~=0)), args(9,:) = '#rows(NormalDir) '; end; if isempty(oldh), narrows = max(argsizes); else, narrows = length(oldh); end; if (narrows<=0), narrows=1; end; % Check size of arguments ii = find((argsizes~=0)&(argsizes~=1)&(argsizes~=narrows)); if ~isempty(ii), s = args(ii',:); while ((size(s,2)>1)&((abs(s(:,size(s,2)))==0)|(abs(s(:,size(s,2)))==abs(' ')))), s = s(:,1:size(s,2)-1); end; s = [ones(length(ii),1)*[upper(mfilename) ' requires that '] s ... ones(length(ii),1)*[' equal the # of arrows (' num2str(narrows) ').' c]]; s = s'; s = s(:)'; s = s(1:length(s)-1); error(setstr(s)); end; % check element length in Start, Stop, and CrossDir if ~isempty(start), [m,n] = size(start); if (n==2), start = [start NaN*ones(m,1)]; elseif (n~=3), error([upper(mfilename) ' requires 2- or 3-element Start points.']); end; end; if ~isempty(stop), [m,n] = size(stop); if (n==2), stop = [stop NaN*ones(m,1)]; elseif (n~=3), error([upper(mfilename) ' requires 2- or 3-element Stop points.']); end; end; if ~isempty(crossdir), [m,n] = size(crossdir); if (n<3), crossdir = [crossdir NaN*ones(m,3-n)]; elseif (n~=3), if (all(imag(crossdir(:))==0)), error([upper(mfilename) ' requires 2- or 3-element CrossDir vectors.']); else, error([upper(mfilename) ' requires 2- or 3-element NormalDir vectors.']); end; end; end; % fill empty arguments if isempty(start ), start = [Inf Inf Inf]; end; if isempty(stop ), stop = [Inf Inf Inf]; end; if isempty(len ), len = Inf; end; if isempty(baseangle ), baseangle = Inf; end; if isempty(tipangle ), tipangle = Inf; end; if isempty(wid ), wid = Inf; end; if isempty(page ), page = Inf; end; if isempty(crossdir ), crossdir = [Inf Inf Inf]; end; if isempty(ends ), ends = Inf; end; if isempty(ispatch ), ispatch = Inf; end; % expand single-column arguments o = ones(narrows,1); if (size(start ,1)==1), start = o * start ; end; if (size(stop ,1)==1), stop = o * stop ; end; if (length(len )==1), len = o * len ; end; if (length(baseangle )==1), baseangle = o * baseangle ; end; if (length(tipangle )==1), tipangle = o * tipangle ; end; if (length(wid )==1), wid = o * wid ; end; if (length(page )==1), page = o * page ; end; if (size(crossdir ,1)==1), crossdir = o * crossdir ; end; if (length(ends )==1), ends = o * ends ; end; if (length(ispatch )==1), ispatch = o * ispatch ; end; ax = o * gca; % if we've got handles, get the defaults from the handles if ~isempty(oldh), for k=1:narrows, oh = oldh(k); ud = get(oh,'UserData'); ax(k) = get(oh,'Parent'); ohtype = get(oh,'Type'); if strcmp(get(oh,'Tag'),ArrowTag), % if it's an arrow already if isinf(ispatch(k)), ispatch(k)=strcmp(ohtype,'patch'); end; % arrow UserData format: [start' stop' len base tip wid page crossdir' ends] start0 = ud(1:3); stop0 = ud(4:6); if (isinf(len(k))), len(k) = ud( 7); end; if (isinf(baseangle(k))), baseangle(k) = ud( 8); end; if (isinf(tipangle(k))), tipangle(k) = ud( 9); end; if (isinf(wid(k))), wid(k) = ud(10); end; if (isinf(page(k))), page(k) = ud(11); end; if (isinf(crossdir(k,1))), crossdir(k,1) = ud(12); end; if (isinf(crossdir(k,2))), crossdir(k,2) = ud(13); end; if (isinf(crossdir(k,3))), crossdir(k,3) = ud(14); end; if (isinf(ends(k))), ends(k) = ud(15); end; elseif strcmp(ohtype,'line')|strcmp(ohtype,'patch'), % it's a non-arrow line or patch convLineToPatch = 1; %set to make arrow patches when converting from lines. if isinf(ispatch(k)), ispatch(k)=convLineToPatch|strcmp(ohtype,'patch'); end; x=get(oh,'XData'); x=x(~isnan(x(:))); if isempty(x), x=NaN; end; y=get(oh,'YData'); y=y(~isnan(y(:))); if isempty(y), y=NaN; end; z=get(oh,'ZData'); z=z(~isnan(z(:))); if isempty(z), z=NaN; end; start0 = [x(1) y(1) z(1) ]; stop0 = [x(end) y(end) z(end)]; else, error([upper(mfilename) ' cannot convert ' ohtype ' objects.']); end; ii=find(isinf(start(k,:))); if ~isempty(ii), start(k,ii)=start0(ii); end; ii=find(isinf(stop( k,:))); if ~isempty(ii), stop( k,ii)=stop0( ii); end; end; end; % convert Inf's to NaN's start( isinf(start )) = NaN; stop( isinf(stop )) = NaN; len( isinf(len )) = NaN; baseangle( isinf(baseangle)) = NaN; tipangle( isinf(tipangle )) = NaN; wid( isinf(wid )) = NaN; page( isinf(page )) = NaN; crossdir( isinf(crossdir )) = NaN; ends( isinf(ends )) = NaN; ispatch( isinf(ispatch )) = NaN; % set up the UserData data (here so not corrupted by log10's and such) ud = [start stop len baseangle tipangle wid page crossdir ends]; % Set Page defaults page = ~isnan(page) & trueornan(page); % Get axes limits, range, min; correct for aspect ratio and log scale axm = zeros(3,narrows); axr = zeros(3,narrows); axrev = zeros(3,narrows); ap = zeros(2,narrows); xyzlog = zeros(3,narrows); limmin = zeros(2,narrows); limrange = zeros(2,narrows); oldaxlims = zeros(narrows,7); oneax = all(ax==ax(1)); if (oneax), T = zeros(4,4); invT = zeros(4,4); else, T = zeros(16,narrows); invT = zeros(16,narrows); end; axnotdone = logical(ones(size(ax))); while (any(axnotdone)), ii = min(find(axnotdone)); curax = ax(ii); curpage = page(ii); % get axes limits and aspect ratio axl = [get(curax,'XLim'); get(curax,'YLim'); get(curax,'ZLim')]; oldaxlims(min(find(oldaxlims(:,1)==0)),:) = [curax reshape(axl',1,6)]; % get axes size in pixels (points) u = get(curax,'Units'); axposoldunits = get(curax,'Position'); really_curpage = curpage & strcmp(u,'normalized'); if (really_curpage), curfig = get(curax,'Parent'); pu = get(curfig,'PaperUnits'); set(curfig,'PaperUnits','points'); pp = get(curfig,'PaperPosition'); set(curfig,'PaperUnits',pu); set(curax,'Units','pixels'); curapscreen = get(curax,'Position'); set(curax,'Units','normalized'); curap = pp.*get(curax,'Position'); else, set(curax,'Units','pixels'); curapscreen = get(curax,'Position'); curap = curapscreen; end; set(curax,'Units',u); set(curax,'Position',axposoldunits); % handle non-stretched axes position str_stretch = { 'DataAspectRatioMode' ; ... 'PlotBoxAspectRatioMode' ; ... 'CameraViewAngleMode' }; str_camera = { 'CameraPositionMode' ; ... 'CameraTargetMode' ; ... 'CameraViewAngleMode' ; ... 'CameraUpVectorMode' }; notstretched = strcmp(get(curax,str_stretch),'manual'); manualcamera = strcmp(get(curax,str_camera),'manual'); if ~arrow_WarpToFill(notstretched,manualcamera,curax), % give a warning that this has not been thoroughly tested if 0 & ARROW_STRETCH_WARN, ARROW_STRETCH_WARN = 0; strs = {str_stretch{1:2},str_camera{:}}; strs = [char(ones(length(strs),1)*sprintf('\n ')) char(strs)]'; warning([upper(mfilename) ' may not yet work quite right ' ... 'if any of the following are ''manual'':' strs(:).']); end; % find the true pixel size of the actual axes texttmp = text(axl(1,[1 2 2 1 1 2 2 1]), ... axl(2,[1 1 2 2 1 1 2 2]), ... axl(3,[1 1 1 1 2 2 2 2]),''); set(texttmp,'Units','points'); textpos = get(texttmp,'Position'); delete(texttmp); textpos = cat(1,textpos{:}); textpos = max(textpos(:,1:2)) - min(textpos(:,1:2)); % adjust the axes position if (really_curpage), % adjust to printed size textpos = textpos * min(curap(3:4)./textpos); curap = [curap(1:2)+(curap(3:4)-textpos)/2 textpos]; else, % adjust for pixel roundoff textpos = textpos * min(curapscreen(3:4)./textpos); curap = [curap(1:2)+(curap(3:4)-textpos)/2 textpos]; end; end; if ARROW_PERSP_WARN & ~strcmp(get(curax,'Projection'),'orthographic'), ARROW_PERSP_WARN = 0; warning([upper(mfilename) ' does not yet work right for 3-D perspective projection.']); end; % adjust limits for log scale on axes curxyzlog = [strcmp(get(curax,'XScale'),'log'); ... strcmp(get(curax,'YScale'),'log'); ... strcmp(get(curax,'ZScale'),'log')]; if (any(curxyzlog)), ii = find([curxyzlog;curxyzlog]); if (any(axl(ii)<=0)), error([upper(mfilename) ' does not support non-positive limits on log-scaled axes.']); else, axl(ii) = log10(axl(ii)); end; end; % correct for 'reverse' direction on axes; curreverse = [strcmp(get(curax,'XDir'),'reverse'); ... strcmp(get(curax,'YDir'),'reverse'); ... strcmp(get(curax,'ZDir'),'reverse')]; ii = find(curreverse); if ~isempty(ii), axl(ii,[1 2])=-axl(ii,[2 1]); end; % compute the range of 2-D values curT = get(curax,'Xform'); lim = curT*[0 1 0 1 0 1 0 1;0 0 1 1 0 0 1 1;0 0 0 0 1 1 1 1;1 1 1 1 1 1 1 1]; lim = lim(1:2,:)./([1;1]*lim(4,:)); curlimmin = min(lim')'; curlimrange = max(lim')' - curlimmin; curinvT = inv(curT); if (~oneax), curT = curT.'; curinvT = curinvT.'; curT = curT(:); curinvT = curinvT(:); end; % check which arrows to which cur corresponds ii = find((ax==curax)&(page==curpage)); oo = ones(1,length(ii)); axr(:,ii) = diff(axl')' * oo; axm(:,ii) = axl(:,1) * oo; axrev(:,ii) = curreverse * oo; ap(:,ii) = curap(3:4)' * oo; xyzlog(:,ii) = curxyzlog * oo; limmin(:,ii) = curlimmin * oo; limrange(:,ii) = curlimrange * oo; if (oneax), T = curT; invT = curinvT; else, T(:,ii) = curT * oo; invT(:,ii) = curinvT * oo; end; axnotdone(ii) = zeros(1,length(ii)); end; oldaxlims(oldaxlims(:,1)==0,:)=[]; % correct for log scales curxyzlog = xyzlog.'; ii = find(curxyzlog(:)); if ~isempty(ii), start( ii) = real(log10(start( ii))); stop( ii) = real(log10(stop( ii))); if (all(imag(crossdir)==0)), % pulled (ii) subscript on crossdir, 12/5/96 eaj crossdir(ii) = real(log10(crossdir(ii))); end; end; % correct for reverse directions ii = find(axrev.'); if ~isempty(ii), start( ii) = -start( ii); stop( ii) = -stop( ii); crossdir(ii) = -crossdir(ii); end; % transpose start/stop values start = start.'; stop = stop.'; % take care of defaults, page was done above ii=find(isnan(start(:) )); if ~isempty(ii), start(ii) = axm(ii)+axr(ii)/2; end; ii=find(isnan(stop(:) )); if ~isempty(ii), stop(ii) = axm(ii)+axr(ii)/2; end; ii=find(isnan(crossdir(:) )); if ~isempty(ii), crossdir(ii) = zeros(length(ii),1); end; ii=find(isnan(len )); if ~isempty(ii), len(ii) = ones(length(ii),1)*deflen; end; ii=find(isnan(baseangle )); if ~isempty(ii), baseangle(ii) = ones(length(ii),1)*defbaseangle; end; ii=find(isnan(tipangle )); if ~isempty(ii), tipangle(ii) = ones(length(ii),1)*deftipangle; end; ii=find(isnan(wid )); if ~isempty(ii), wid(ii) = ones(length(ii),1)*defwid; end; ii=find(isnan(ends )); if ~isempty(ii), ends(ii) = ones(length(ii),1)*defends; end; % transpose rest of values len = len.'; baseangle = baseangle.'; tipangle = tipangle.'; wid = wid.'; page = page.'; crossdir = crossdir.'; ends = ends.'; ax = ax.'; % given x, a 3xN matrix of points in 3-space; % want to convert to X, the corresponding 4xN 2-space matrix % % tmp1=[(x-axm)./axr; ones(1,size(x,1))]; % if (oneax), X=T*tmp1; % else, tmp1=[tmp1;tmp1;tmp1;tmp1]; tmp1=T.*tmp1; % tmp2=zeros(4,4*N); tmp2(:)=tmp1(:); % X=zeros(4,N); X(:)=sum(tmp2)'; end; % X = X ./ (ones(4,1)*X(4,:)); % for all points with start==stop, start=stop-(verysmallvalue)*(up-direction); ii = find(all(start==stop)); if ~isempty(ii), % find an arrowdir vertical on screen and perpendicular to viewer % transform to 2-D tmp1 = [(stop(:,ii)-axm(:,ii))./axr(:,ii);ones(1,length(ii))]; if (oneax), twoD=T*tmp1; else, tmp1=[tmp1;tmp1;tmp1;tmp1]; tmp1=T(:,ii).*tmp1; tmp2=zeros(4,4*length(ii)); tmp2(:)=tmp1(:); twoD=zeros(4,length(ii)); twoD(:)=sum(tmp2)'; end; twoD=twoD./(ones(4,1)*twoD(4,:)); % move the start point down just slightly tmp1 = twoD + [0;-1/1000;0;0]*(limrange(2,ii)./ap(2,ii)); % transform back to 3-D if (oneax), threeD=invT*tmp1; else, tmp1=[tmp1;tmp1;tmp1;tmp1]; tmp1=invT(:,ii).*tmp1; tmp2=zeros(4,4*length(ii)); tmp2(:)=tmp1(:); threeD=zeros(4,length(ii)); threeD(:)=sum(tmp2)'; end; start(:,ii) = (threeD(1:3,:)./(ones(3,1)*threeD(4,:))).*axr(:,ii)+axm(:,ii); end; % compute along-arrow points % transform Start points tmp1=[(start-axm)./axr;ones(1,narrows)]; if (oneax), X0=T*tmp1; else, tmp1=[tmp1;tmp1;tmp1;tmp1]; tmp1=T.*tmp1; tmp2=zeros(4,4*narrows); tmp2(:)=tmp1(:); X0=zeros(4,narrows); X0(:)=sum(tmp2)'; end; X0=X0./(ones(4,1)*X0(4,:)); % transform Stop points tmp1=[(stop-axm)./axr;ones(1,narrows)]; if (oneax), Xf=T*tmp1; else, tmp1=[tmp1;tmp1;tmp1;tmp1]; tmp1=T.*tmp1; tmp2=zeros(4,4*narrows); tmp2(:)=tmp1(:); Xf=zeros(4,narrows); Xf(:)=sum(tmp2)'; end; Xf=Xf./(ones(4,1)*Xf(4,:)); % compute pixel distance between points D = sqrt(sum(((Xf(1:2,:)-X0(1:2,:)).*(ap./limrange)).^2)); D = D + (D==0); %eaj new 2/24/98 % compute and modify along-arrow distances len1 = len; len2 = len - (len.*tan(tipangle/180*pi)-wid/2).*tan((90-baseangle)/180*pi); slen0 = zeros(1,narrows); slen1 = len1 .* ((ends==2)|(ends==3)); slen2 = len2 .* ((ends==2)|(ends==3)); len0 = zeros(1,narrows); len1 = len1 .* ((ends==1)|(ends==3)); len2 = len2 .* ((ends==1)|(ends==3)); % for no start arrowhead ii=find((ends==1)&(D0), set(H,extraprops{:}); end; % handle choosing arrow Start and/or Stop locations if unspecified [H,oldaxlims,errstr] = arrow_clicks(H,ud,x,y,z,ax,oldaxlims); if ~isempty(errstr), error([upper(mfilename) ' got ' errstr]); end; % set the output if (nargout>0), h=H; end; % make sure the axis limits did not change if isempty(oldaxlims), ARROW_AXLIMITS = []; else, lims = get(oldaxlims(:,1),{'XLim','YLim','ZLim'})'; lims = reshape(cat(2,lims{:}),6,size(lims,2)); mask = arrow_is2DXY(oldaxlims(:,1)); oldaxlims(mask,6:7) = lims(5:6,mask)'; ARROW_AXLIMITS = oldaxlims(find(any(oldaxlims(:,2:7)'~=lims)),:); if ~isempty(ARROW_AXLIMITS), warning(arrow_warnlimits(ARROW_AXLIMITS,narrows)); end; end; else, % don't create the patch, just return the data h=x; yy=y; zz=z; end; function out = arrow_defcheck(in,def,prop) % check if we got 'default' values out = in; if ~isstr(in), return; end; if size(in,1)==1 & strncmp(lower(in),'def',3), out = def; elseif ~isempty(prop), error([upper(mfilename) ' does not recognize ''' in(:)' ''' as a valid ''' prop ''' string.']); end; function [H,oldaxlims,errstr] = arrow_clicks(H,ud,x,y,z,ax,oldaxlims) % handle choosing arrow Start and/or Stop locations if necessary errstr = ''; if isempty(H)|isempty(ud)|isempty(x), return; end; % determine which (if any) need Start and/or Stop needStart = all(isnan(ud(:,1:3)'))'; needStop = all(isnan(ud(:,4:6)'))'; mask = any(needStart|needStop); if ~any(mask), return; end; ud(~mask,:)=[]; ax(:,~mask)=[]; x(:,~mask)=[]; y(:,~mask)=[]; z(:,~mask)=[]; % make them invisible for the time being set(H,'Visible','off'); % save the current axes and limits modes; set to manual for the time being oldAx = gca; limModes=get(ax(:),{'XLimMode','YLimMode','ZLimMode'}); set(ax(:),{'XLimMode','YLimMode','ZLimMode'},{'manual','manual','manual'}); % loop over each arrow that requires attention jj = find(mask); for ii=1:length(jj), h = H(jj(ii)); axes(ax(ii)); % figure out correct call if needStart(ii), prop='Start'; else, prop='Stop'; end; [wasInterrupted,errstr] = arrow_click(needStart(ii)&needStop(ii),h,prop,ax(ii)); % handle errors and control-C if wasInterrupted, delete(H(jj(ii:end))); H(jj(ii:end))=[]; oldaxlims(jj(ii:end),:)=[]; break; end; end; % restore the axes and limit modes axes(oldAx); set(ax(:),{'XLimMode','YLimMode','ZLimMode'},limModes); function [wasInterrupted,errstr] = arrow_click(lockStart,H,prop,ax) % handle the clicks for one arrow fig = get(ax,'Parent'); % save some things oldFigProps = {'Pointer','WindowButtonMotionFcn','WindowButtonUpFcn'}; oldFigValue = get(fig,oldFigProps); oldArrowProps = {'EraseMode'}; oldArrowValue = get(H,oldArrowProps); set(H,'EraseMode','background'); %because 'xor' makes shaft invisible unless Width>1 global ARROW_CLICK_H ARROW_CLICK_PROP ARROW_CLICK_AX ARROW_CLICK_USE_Z ARROW_CLICK_H=H; ARROW_CLICK_PROP=prop; ARROW_CLICK_AX=ax; ARROW_CLICK_USE_Z=~arrow_is2DXY(ax)|~arrow_planarkids(ax); set(fig,'Pointer','crosshair'); % set up the WindowButtonMotion so we can see the arrow while moving around set(fig,'WindowButtonUpFcn','set(gcf,''WindowButtonUpFcn'','''')', ... 'WindowButtonMotionFcn',''); if ~lockStart, set(H,'Visible','on'); set(fig,'WindowButtonMotionFcn',[mfilename '(''callback'',''motion'');']); end; % wait for the button to be pressed [wasKeyPress,wasInterrupted,errstr] = arrow_wfbdown(fig); % if we wanted to click-drag, set the Start point if lockStart & ~wasInterrupted, pt = arrow_point(ARROW_CLICK_AX,ARROW_CLICK_USE_Z); feval(mfilename,H,'Start',pt,'Stop',pt); set(H,'Visible','on'); ARROW_CLICK_PROP='Stop'; set(fig,'WindowButtonMotionFcn',[mfilename '(''callback'',''motion'');']); % wait for the mouse button to be released eval('waitfor(fig,''WindowButtonUpFcn'','''');','wasInterrupted=1;'); if wasInterrupted, errstr=lasterr; end; end; if ~wasInterrupted, feval(mfilename,'callback','motion'); end; % restore some things set(gcf,oldFigProps,oldFigValue); set(H,oldArrowProps,oldArrowValue); function arrow_callback(varargin) % handle redrawing callbacks if nargin==0, return; end; str = varargin{1}; if ~isstr(str), error([upper(mfilename) ' got an invalid Callback command.']); end; s = lower(str); if strcmp(s,'motion'), % motion callback global ARROW_CLICK_H ARROW_CLICK_PROP ARROW_CLICK_AX ARROW_CLICK_USE_Z feval(mfilename,ARROW_CLICK_H,ARROW_CLICK_PROP,arrow_point(ARROW_CLICK_AX,ARROW_CLICK_USE_Z)); drawnow; else, error([upper(mfilename) ' does not recognize ''' str(:).' ''' as a valid Callback option.']); end; function out = arrow_point(ax,use_z) % return the point on the given axes if nargin==0, ax=gca; end; if nargin<2, use_z=~arrow_is2DXY(ax)|~arrow_planarkids(ax); end; out = get(ax,'CurrentPoint'); out = out(1,:); if ~use_z, out=out(1:2); end; function [wasKeyPress,wasInterrupted,errstr] = arrow_wfbdown(fig) % wait for button down ignoring object ButtonDownFcn's if nargin==0, fig=gcf; end; errstr = ''; % save ButtonDownFcn values objs = findobj(fig); buttonDownFcns = get(objs,'ButtonDownFcn'); mask=~strcmp(buttonDownFcns,''); objs=objs(mask); buttonDownFcns=buttonDownFcns(mask); set(objs,'ButtonDownFcn',''); % save other figure values figProps = {'KeyPressFcn','WindowButtonDownFcn'}; figValue = get(fig,figProps); % do the real work set(fig,'KeyPressFcn','set(gcf,''KeyPressFcn'','''',''WindowButtonDownFcn'','''');', ... 'WindowButtonDownFcn','set(gcf,''WindowButtonDownFcn'','''')'); lasterr(''); wasInterrupted=0; eval('waitfor(fig,''WindowButtonDownFcn'','''');','wasInterrupted=1;'); wasKeyPress = ~wasInterrupted & strcmp(get(fig,'KeyPressFcn'),''); if wasInterrupted, errstr=lasterr; end; % restore ButtonDownFcn and other figure values set(objs,'ButtonDownFcn',buttonDownFcns); set(fig,figProps,figValue); function [out,is2D] = arrow_is2DXY(ax) % check if axes are 2-D X-Y plots % may not work for modified camera angles, etc. out = logical(zeros(size(ax))); % 2-D X-Y plots is2D = out; % any 2-D plots views = get(ax(:),{'View'}); views = cat(1,views{:}); out(:) = abs(views(:,2))==90; is2D(:) = out(:) | all(rem(views',90)==0)'; function out = arrow_planarkids(ax) % check if axes descendents all have empty ZData (lines,patches,surfaces) out = logical(ones(size(ax))); allkids = get(ax(:),{'Children'}); for k=1:length(allkids), kids = get([findobj(allkids{k},'flat','Type','line') findobj(allkids{k},'flat','Type','patch') findobj(allkids{k},'flat','Type','surface')],{'ZData'}); for j=1:length(kids), if ~isempty(kids{j}), out(k)=logical(0); break; end; end; end; function arrow_fixlimits(axlimits) % reset the axis limits as necessary if isempty(axlimits), disp([upper(mfilename) ' does not remember any axis limits to reset.']); end; for k=1:size(axlimits,1), if any(get(axlimits(k,1),'XLim')~=axlimits(k,2:3)), set(axlimits(k,1),'XLim',axlimits(k,2:3)); end; if any(get(axlimits(k,1),'YLim')~=axlimits(k,4:5)), set(axlimits(k,1),'YLim',axlimits(k,4:5)); end; if any(get(axlimits(k,1),'ZLim')~=axlimits(k,6:7)), set(axlimits(k,1),'ZLim',axlimits(k,6:7)); end; end; function out = arrow_WarpToFill(notstretched,manualcamera,curax) % check if we are in "WarpToFill" mode. out = strcmp(get(curax,'WarpToFill'),'on'); % 'WarpToFill' is undocumented, so may need to replace this by % out = ~( any(notstretched) & any(manualcamera) ); function out = arrow_warnlimits(axlimits,narrows) % create a warning message if we've changed the axis limits msg = ''; switch (size(axlimits,1)) case 1, msg=''; case 2, msg='on two axes '; otherwise, msg='on several axes '; end; msg = [upper(mfilename) ' changed the axis limits ' msg ... 'when adding the arrow']; if (narrows>1), msg=[msg 's']; end; out = [msg '.' sprintf('\n') ' Call ' upper(mfilename) ... ' FIXLIMITS to reset them now.']; function arrow_copyprops(fm,to) % copy line properties to patches props = {'EraseMode','LineStyle','LineWidth','Marker','MarkerSize',... 'MarkerEdgeColor','MarkerFaceColor','ButtonDownFcn', ... 'Clipping','DeleteFcn','BusyAction','HandleVisibility', ... 'Selected','SelectionHighlight','Visible'}; lineprops = {'Color', props{:}}; patchprops = {'EdgeColor',props{:}}; patch2props = {'FaceColor',patchprops{:}}; fmpatch = strcmp(get(fm,'Type'),'patch'); topatch = strcmp(get(to,'Type'),'patch'); set(to( fmpatch& topatch),patch2props,get(fm( fmpatch& topatch),patch2props)); %p->p set(to(~fmpatch&~topatch),lineprops, get(fm(~fmpatch&~topatch),lineprops )); %l->l set(to( fmpatch&~topatch),lineprops, get(fm( fmpatch&~topatch),patchprops )); %p->l set(to(~fmpatch& topatch),patchprops, get(fm(~fmpatch& topatch),lineprops) ,'FaceColor','none'); %l->p function arrow_props % display further help info about ARROW properties c = sprintf('\n'); disp([c ... 'ARROW Properties: Default values are given in [square brackets], and other' c ... ' acceptable equivalent property names are in (parenthesis).' c c ... ' Start The starting points. For N arrows, B' c ... ' this should be a Nx2 or Nx3 matrix. /|\ ^' c ... ' Stop The end points. For N arrows, this /|||\ |' c ... ' should be a Nx2 or Nx3 matrix. //|||\\ L|' c ... ' Length Length of the arrowhead (in pixels on ///|||\\\ e|' c ... ' screen, points on a page). [16] (Len) ////|||\\\\ n|' c ... ' BaseAngle Angle (degrees) of the base angle /////|D|\\\\\ g|' c ... ' ADE. For a simple stick arrow, use //// ||| \\\\ t|' c ... ' BaseAngle=TipAngle. [90] (Base) /// ||| \\\ h|' c ... ' TipAngle Angle (degrees) of tip angle ABC. //<----->|| \\ |' c ... ' [16] (Tip) / base ||| \ V' c ... ' Width Width of the base in pixels. Not E angle ||<-------->C' c ... ' the ''LineWidth'' prop. [0] (Wid) |||tipangle' c ... ' Page If provided, non-empty, and not NaN, |||' c ... ' this causes ARROW to use hardcopy |||' c ... ' rather than onscreen proportions. A' c ... ' This is important if screen aspect --> <-- width' c ... ' ratio and hardcopy aspect ratio are ----CrossDir---->' c ... ' vastly different. []' c... ' CrossDir A vector giving the direction towards which the fletches' c ... ' on the arrow should go. [computed such that it is perpen-' c ... ' dicular to both the arrow direction and the view direction' c ... ' (i.e., as if it was pasted on a normal 2-D graph)] (Note' c ... ' that CrossDir is a vector. Also note that if an axis is' c ... ' plotted on a log scale, then the corresponding component' c ... ' of CrossDir must also be set appropriately, i.e., to 1 for' c ... ' no change in that direction, >1 for a positive change, >0' c ... ' and <1 for negative change.)' c ... ' NormalDir A vector normal to the fletch direction (CrossDir is then' c ... ' computed by the vector cross product [Line]x[NormalDir]). []' c ... ' (Note that NormalDir is a vector. Unlike CrossDir,' c ... ' NormalDir is used as is regardless of log-scaled axes.)' c ... ' Ends Set which end has an arrowhead. Valid values are ''none'',' c ... ' ''stop'', ''start'', and ''both''. [''stop''] (End)' c... ' ObjectHandles Vector of handles to previously-created arrows to be' c ... ' updated or line objects to be converted to arrows.' c ... ' [] (Object,Handle)' c ]); function out = arrow_demo % demo % create the data [x,y,z] = peaks; [ddd,out.iii]=max(z(:)); out.axlim = [min(x(:)) max(x(:)) min(y(:)) max(y(:)) min(z(:)) max(z(:))]; % modify it by inserting some NaN's [m,n] = size(z); m = floor(m/2); n = floor(n/2); z(1:m,1:n) = NaN*ones(m,n); % graph it clf('reset'); out.hs=surf(x,y,z); out.x=x; out.y=y; out.z=z; xlabel('x'); ylabel('y'); function h = arrow_demo3(in) % set the view axlim = in.axlim; axis(axlim); zlabel('z'); %set(in.hs,'FaceColor','interp'); view(viewmtx(-37.5,30,20)); title(['Demo of the capabilities of the ARROW function in 3-D']); % Normal blue arrow h1 = feval(mfilename,[axlim(1) axlim(4) 4],[-.8 1.2 4], ... 'EdgeColor','b','FaceColor','b'); % Normal white arrow, clipped by the surface h2 = feval(mfilename,axlim([1 4 6]),[0 2 4]); t=text(-2.4,2.7,7.7,'arrow clipped by surf'); % Baseangle<90 h3 = feval(mfilename,[3 .125 3.5],[1.375 0.125 3.5],30,50); t2=text(3.1,.125,3.5,'local maximum'); % Baseangle<90, fill and edge colors different h4 = feval(mfilename,axlim(1:2:5)*.5,[0 0 0],36,60,25, ... 'EdgeColor','b','FaceColor','c'); t3=text(axlim(1)*.5,axlim(3)*.5,axlim(5)*.5-.75,'origin'); set(t3,'HorizontalAlignment','center'); % Baseangle>90, black fill h5 = feval(mfilename,[-2.9 2.9 3],[-1.3 .4 3.2],30,120,[],6, ... 'EdgeColor','r','FaceColor','k','LineWidth',2); % Baseangle>90, no fill h6 = feval(mfilename,[-2.9 2.9 1.3],[-1.3 .4 1.5],30,120,[],6, ... 'EdgeColor','r','FaceColor','none','LineWidth',2); % Stick arrow h7 = feval(mfilename,[-1.6 -1.65 -6.5],[0 -1.65 -6.5],[],16,16); t4=text(-1.5,-1.65,-7.25,'global mininum'); set(t4,'HorizontalAlignment','center'); % Normal, black fill h8 = feval(mfilename,[-1.4 0 -7.2],[-1.4 0 -3],'FaceColor','k'); t5=text(-1.5,0,-7.75,'local minimum'); set(t5,'HorizontalAlignment','center'); % Gray fill, crossdir specified, 'LineStyle' -- h9 = feval(mfilename,[-3 2.2 -6],[-3 2.2 -.05],36,[],27,6,[],[0 -1 0], ... 'EdgeColor','k','FaceColor',.75*[1 1 1],'LineStyle','--'); % a series of normal arrows, linearly spaced, crossdir specified h10y=(0:4)'/3; h10 = feval(mfilename,[-3*ones(size(h10y)) h10y -6.5*ones(size(h10y))], ... [-3*ones(size(h10y)) h10y -.05*ones(size(h10y))], ... 12,[],[],[],[],[0 -1 0]); % a series of normal arrows, linearly spaced h11x=(1:.33:2.8)'; h11 = feval(mfilename,[h11x -3*ones(size(h11x)) 6.5*ones(size(h11x))], ... [h11x -3*ones(size(h11x)) -.05*ones(size(h11x))]); % series of magenta arrows, radially oriented, crossdir specified h12x=2; h12y=-3; h12z=axlim(5)/2; h12xr=1; h12zr=h12z; ir=.15;or=.81; h12t=(0:11)'/6*pi; h12 = feval(mfilename, ... [h12x+h12xr*cos(h12t)*ir h12y*ones(size(h12t)) ... h12z+h12zr*sin(h12t)*ir],[h12x+h12xr*cos(h12t)*or ... h12y*ones(size(h12t)) h12z+h12zr*sin(h12t)*or], ... 10,[],[],[],[], ... [-h12xr*sin(h12t) zeros(size(h12t)) h12zr*cos(h12t)],... 'FaceColor','none','EdgeColor','m'); % series of normal arrows, tangentially oriented, crossdir specified or13=.91; h13t=(0:.5:12)'/6*pi; locs = [h12x+h12xr*cos(h13t)*or13 h12y*ones(size(h13t)) h12z+h12zr*sin(h13t)*or13]; h13 = feval(mfilename,locs(1:end-1,:),locs(2:end,:),6); % arrow with no line ==> oriented downwards h14 = feval(mfilename,[3 3 .100001],[3 3 .1],30); t6=text(3,3,3.6,'no line'); set(t6,'HorizontalAlignment','center'); % arrow with arrowheads at both ends h15 = feval(mfilename,[-.5 -3 -3],[1 -3 -3],'Ends','both','FaceColor','g', ... 'Length',20,'Width',3,'CrossDir',[0 0 1],'TipAngle',25); h=[h1;h2;h3;h4;h5;h6;h7;h8;h9;h10;h11;h12;h13;h14;h15]; function h = arrow_demo2(in) axlim = in.axlim; dolog = 1; if (dolog), set(in.hs,'YData',10.^get(in.hs,'YData')); end; shading('interp'); view(2); title(['Demo of the capabilities of the ARROW function in 2-D']); hold on; [C,H]=contour(in.x,in.y,in.z,20,'-'); hold off; for k=H', set(k,'ZData',(axlim(6)+1)*ones(size(get(k,'XData'))),'Color','k'); if (dolog), set(k,'YData',10.^get(k,'YData')); end; end; if (dolog), axis([axlim(1:2) 10.^axlim(3:4)]); set(gca,'YScale','log'); else, axis(axlim(1:4)); end; % Normal blue arrow start = [axlim(1) axlim(4) axlim(6)+2]; stop = [in.x(in.iii) in.y(in.iii) axlim(6)+2]; if (dolog), start(:,2)=10.^start(:,2); stop(:,2)=10.^stop(:,2); end; h1 = feval(mfilename,start,stop,'EdgeColor','b','FaceColor','b'); % three arrows with varying fill, width, and baseangle start = [-3 -3 10; -3 -1.5 10; -1.5 -3 10]; stop = [-.03 -.03 10; -.03 -1.5 10; -1.5 -.03 10]; if (dolog), start(:,2)=10.^start(:,2); stop(:,2)=10.^stop(:,2); end; h2 = feval(mfilename,start,stop,24,[90;60;120],[],[0;0;4],'Ends',str2mat('both','stop','stop')); set(h2(2),'EdgeColor',[0 .35 0],'FaceColor',[0 .85 .85]); set(h2(3),'EdgeColor','r','FaceColor',[1 .5 1]); h=[h1;h2]; function out = trueornan(x) if isempty(x), out=x; else, out = isnan(x); out(~out) = x(~out); end; \ No newline at end of file +function [h,yy,zz] = arrow(varargin) +% ARROW Draw a line with an arrowhead. +% +% ARROW(Start,Stop) draws a line with an arrow from Start to Stop (points +% should be vectors of length 2 or 3, or matrices with 2 or 3 +% columns), and returns the graphics handle of the arrow(s). +% +% ARROW uses the mouse (click-drag) to create an arrow. +% +% ARROW DEMO & ARROW DEMO2 show 3-D & 2-D demos of the capabilities of ARROW. +% +% ARROW may be called with a normal argument list or a property-based list. +% ARROW(Start,Stop,Length,BaseAngle,TipAngle,Width,Page,CrossDir) is +% the full normal argument list, where all but the Start and Stop +% points are optional. If you need to specify a later argument (e.g., +% Page) but want default values of earlier ones (e.g., TipAngle), +% pass an empty matrix for the earlier ones (e.g., TipAngle=[]). +% +% ARROW('Property1',PropVal1,'Property2',PropVal2,...) creates arrows with the +% given properties, using default values for any unspecified or given as +% 'default' or NaN. Some properties used for line and patch objects are +% used in a modified fashion, others are passed directly to LINE, PATCH, +% or SET. For a detailed properties explanation, call ARROW PROPERTIES. +% +% Start The starting points. B +% Stop The end points. /|\ ^ +% Length Length of the arrowhead in pixels. /|||\ | +% BaseAngle Base angle in degrees (ADE). //|||\\ L| +% TipAngle Tip angle in degrees (ABC). ///|||\\\ e| +% Width Width of the base in pixels. ////|||\\\\ n| +% Page Use hardcopy proportions. /////|D|\\\\\ g| +% CrossDir Vector || to arrowhead plane. //// ||| \\\\ t| +% NormalDir Vector out of arrowhead plane. /// ||| \\\ h| +% Ends Which end has an arrowhead. //<----->|| \\ | +% ObjectHandles Vector of handles to update. / base ||| \ V +% E angle||<-------->C +% ARROW(H,'Prop1',PropVal1,...), where H is a |||tipangle +% vector of handles to previously-created arrows ||| +% and/or line objects, will update the previously- ||| +% created arrows according to the current view -->|A|<-- width +% and any specified properties, and will convert +% two-point line objects to corresponding arrows. ARROW(H) will update +% the arrows if the current view has changed. Root, figure, or axes +% handles included in H are replaced by all descendant Arrow objects. +% +% A property list can follow any specified normal argument list, e.g., +% ARROW([1 2 3],[0 0 0],36,'BaseAngle',60) creates an arrow from (1,2,3) to +% the origin, with an arrowhead of length 36 pixels and 60-degree base angle. +% +% The basic arguments or properties can generally be vectorized to create +% multiple arrows with the same call. This is done by passing a property +% with one row per arrow, or, if all arrows are to have the same property +% value, just one row may be specified. +% +% You may want to execute AXIS(AXIS) before calling ARROW so it doesn't change +% the axes on you; ARROW determines the sizes of arrow components BEFORE the +% arrow is plotted, so if ARROW changes axis limits, arrows may be malformed. +% +% This version of ARROW uses features of MATLAB 5 and is incompatible with +% earlier MATLAB versions (ARROW for MATLAB 4.2c is available separately); +% some problems with perspective plots still exist. + +% Copyright (c)1995-2002, Dr. Erik A. Johnson , 11/15/02 + +% Revision history: +% 11/15/02 EAJ Accomodate how MATLAB 6.5 handles NaN and logicals +% 7/28/02 EAJ Tried (but failed) work-around for MATLAB 6.x / OpenGL bug +% if zero 'Width' or not double-ended +% 11/10/99 EAJ Add logical() to eliminate zero index problem in MATLAB 5.3. +% 11/10/99 EAJ Corrected warning if axis limits changed on multiple axes. +% 11/10/99 EAJ Update e-mail address. +% 2/10/99 EAJ Some documentation updating. +% 2/24/98 EAJ Fixed bug if Start~=Stop but both colinear with viewpoint. +% 8/14/97 EAJ Added workaround for MATLAB 5.1 scalar logical transpose bug. +% 7/21/97 EAJ Fixed a few misc bugs. +% 7/14/97 EAJ Make arrow([],'Prop',...) do nothing (no old handles) +% 6/23/97 EAJ MATLAB 5 compatible version, release. +% 5/27/97 EAJ Added Line Arrows back in. Corrected a few bugs. +% 5/26/97 EAJ Changed missing Start/Stop to mouse-selected arrows. +% 5/19/97 EAJ MATLAB 5 compatible version, beta. +% 4/13/97 EAJ MATLAB 5 compatible version, alpha. +% 1/31/97 EAJ Fixed bug with multiple arrows and unspecified Z coords. +% 12/05/96 EAJ Fixed one more bug with log plots and NormalDir specified +% 10/24/96 EAJ Fixed bug with log plots and NormalDir specified +% 11/13/95 EAJ Corrected handling for 'reverse' axis directions +% 10/06/95 EAJ Corrected occasional conflict with SUBPLOT +% 4/24/95 EAJ A major rewrite. +% Fall 94 EAJ Original code. + +% Things to be done: +% - segment parsing, computing, and plotting into separate subfunctions +% - change computing from Xform to Camera paradigms +% + this will help especially with 3-D perspective plots +% + if the WarpToFill section works right, remove warning code +% + when perpsective works properly, remove perspective warning code +% - add cell property values and struct property name/values (like get/set) +% - get rid of NaN as the "default" data label +% + perhaps change userdata to a struct and don't include (or leave +% empty) the values specified as default; or use a cell containing +% an empty matrix for a default value +% - add functionality of GET to retrieve current values of ARROW properties + +% Many thanks to Keith Rogers for his many excellent +% suggestions and beta testing. Check out his shareware package MATDRAW +% (at ftp://ftp.mathworks.com/pub/contrib/v5/graphics/matdraw/) -- he has +% permission to distribute ARROW with MATDRAW. + +% Permission is granted to distribute ARROW with the toolboxes for the book +% "Solving Solid Mechanics Problems with MATLAB 5", by F. Golnaraghi et al. +% (Prentice Hall, 1999). + +% global variable initialization +global ARROW_PERSP_WARN ARROW_STRETCH_WARN ARROW_AXLIMITS +if isempty(ARROW_PERSP_WARN ), ARROW_PERSP_WARN =1; end; +if isempty(ARROW_STRETCH_WARN), ARROW_STRETCH_WARN=1; end; + +% Handle callbacks +if (nargin>0 & isstr(varargin{1}) & strcmp(lower(varargin{1}),'callback')), + arrow_callback(varargin{2:end}); return; +end; + +% Are we doing the demo? +c = sprintf('\n'); +if (nargin==1 & isstr(varargin{1})), + arg1 = lower(varargin{1}); + if strncmp(arg1,'prop',4), arrow_props; + elseif strncmp(arg1,'demo',4) + clf reset + demo_info = arrow_demo; + if ~strncmp(arg1,'demo2',5), + hh=arrow_demo3(demo_info); + else, + hh=arrow_demo2(demo_info); + end; + if (nargout>=1), h=hh; end; + elseif strncmp(arg1,'fixlimits',3), + arrow_fixlimits(ARROW_AXLIMITS); + ARROW_AXLIMITS=[]; + elseif strncmp(arg1,'help',4), + disp(help(mfilename)); + else, + error([upper(mfilename) ' got an unknown single-argument string ''' deblank(arg1) '''.']); + end; + return; +end; + +% Check # of arguments +if (nargout>3), error([upper(mfilename) ' produces at most 3 output arguments.']); end; + +% find first property number +firstprop = nargin+1; +for k=1:length(varargin), if ~isnumeric(varargin{k}), firstprop=k; break; end; end; +lastnumeric = firstprop-1; + +% check property list +if (firstprop<=nargin), + for k=firstprop:2:nargin, + curarg = varargin{k}; + if ~isstr(curarg) | sum(size(curarg)>1)>1, + error([upper(mfilename) ' requires that a property name be a single string.']); + end; + end; + if (rem(nargin-firstprop,2)~=1), + error([upper(mfilename) ' requires that the property ''' ... + varargin{nargin} ''' be paired with a property value.']); + end; +end; + +% default output +if (nargout>0), h=[]; end; +if (nargout>1), yy=[]; end; +if (nargout>2), zz=[]; end; + +% set values to empty matrices +start = []; +stop = []; +len = []; +baseangle = []; +tipangle = []; +wid = []; +page = []; +crossdir = []; +ends = []; +ax = []; +oldh = []; +ispatch = []; +defstart = [NaN NaN NaN]; +defstop = [NaN NaN NaN]; +deflen = 16; +defbaseangle = 90; +deftipangle = 16; +defwid = 0; +defpage = 0; +defcrossdir = [NaN NaN NaN]; +defends = 1; +defoldh = []; +defispatch = 1; + +% The 'Tag' we'll put on our arrows +ArrowTag = 'Arrow'; + +% check for oldstyle arguments +if (firstprop==2), + % assume arg1 is a set of handles + oldh = varargin{1}(:); + if isempty(oldh), return; end; +elseif (firstprop>9), + error([upper(mfilename) ' takes at most 8 non-property arguments.']); +elseif (firstprop>2), + s = str2mat('start','stop','len','baseangle','tipangle','wid','page','crossdir'); + for k=1:firstprop-1, eval([deblank(s(k,:)) '=varargin{k};']); end; +end; + +% parse property pairs +extraprops={}; +for k=firstprop:2:nargin, + prop = varargin{k}; + val = varargin{k+1}; + prop = [lower(prop(:)') ' ']; + if strncmp(prop,'start' ,5), start = val; + elseif strncmp(prop,'stop' ,4), stop = val; + elseif strncmp(prop,'len' ,3), len = val(:); + elseif strncmp(prop,'base' ,4), baseangle = val(:); + elseif strncmp(prop,'tip' ,3), tipangle = val(:); + elseif strncmp(prop,'wid' ,3), wid = val(:); + elseif strncmp(prop,'page' ,4), page = val; + elseif strncmp(prop,'cross' ,5), crossdir = val; + elseif strncmp(prop,'norm' ,4), if (isstr(val)), crossdir=val; else, crossdir=val*sqrt(-1); end; + elseif strncmp(prop,'end' ,3), ends = val; + elseif strncmp(prop,'object',6), oldh = val(:); + elseif strncmp(prop,'handle',6), oldh = val(:); + elseif strncmp(prop,'type' ,4), ispatch = val; + elseif strncmp(prop,'userd' ,5), %ignore it + else, + % make sure it is a valid patch or line property + eval('get(0,[''DefaultPatch'' varargin{k}]);err=0;','err=1;'); errstr=lasterr; + if (err), eval('get(0,[''DefaultLine'' varargin{k}]);err=0;','err=1;'); end; + if (err), + errstr(1:max(find(errstr==setstr(13)|errstr==setstr(10)))) = ''; + error([upper(mfilename) ' got ' errstr]); + end; + extraprops={extraprops{:},varargin{k},val}; + end; +end; + +% Check if we got 'default' values +start = arrow_defcheck(start ,defstart ,'Start' ); +stop = arrow_defcheck(stop ,defstop ,'Stop' ); +len = arrow_defcheck(len ,deflen ,'Length' ); +baseangle = arrow_defcheck(baseangle,defbaseangle,'BaseAngle' ); +tipangle = arrow_defcheck(tipangle ,deftipangle ,'TipAngle' ); +wid = arrow_defcheck(wid ,defwid ,'Width' ); +crossdir = arrow_defcheck(crossdir ,defcrossdir ,'CrossDir' ); +page = arrow_defcheck(page ,defpage ,'Page' ); +ends = arrow_defcheck(ends ,defends ,'' ); +oldh = arrow_defcheck(oldh ,[] ,'ObjectHandles'); +ispatch = arrow_defcheck(ispatch ,defispatch ,'' ); + +% check transpose on arguments +[m,n]=size(start ); if any(m==[2 3])&(n==1|n>3), start = start'; end; +[m,n]=size(stop ); if any(m==[2 3])&(n==1|n>3), stop = stop'; end; +[m,n]=size(crossdir); if any(m==[2 3])&(n==1|n>3), crossdir = crossdir'; end; + +% convert strings to numbers +if ~isempty(ends) & isstr(ends), + endsorig = ends; + [m,n] = size(ends); + col = lower([ends(:,1:min(3,n)) ones(m,max(0,3-n))*' ']); + ends = NaN*ones(m,1); + oo = ones(1,m); + ii=find(all(col'==['non']'*oo)'); if ~isempty(ii), ends(ii)=ones(length(ii),1)*0; end; + ii=find(all(col'==['sto']'*oo)'); if ~isempty(ii), ends(ii)=ones(length(ii),1)*1; end; + ii=find(all(col'==['sta']'*oo)'); if ~isempty(ii), ends(ii)=ones(length(ii),1)*2; end; + ii=find(all(col'==['bot']'*oo)'); if ~isempty(ii), ends(ii)=ones(length(ii),1)*3; end; + if any(isnan(ends)), + ii = min(find(isnan(ends))); + error([upper(mfilename) ' does not recognize ''' deblank(endsorig(ii,:)) ''' as a valid ''Ends'' value.']); + end; +else, + ends = ends(:); +end; +if ~isempty(ispatch) & isstr(ispatch), + col = lower(ispatch(:,1)); + patchchar='p'; linechar='l'; defchar=' '; + mask = col~=patchchar & col~=linechar & col~=defchar; + if any(mask), + error([upper(mfilename) ' does not recognize ''' deblank(ispatch(min(find(mask)),:)) ''' as a valid ''Type'' value.']); + end; + ispatch = (col==patchchar)*1 + (col==linechar)*0 + (col==defchar)*defispatch; +else, + ispatch = ispatch(:); +end; +oldh = oldh(:); + +% check object handles +if ~all(ishandle(oldh)), error([upper(mfilename) ' got invalid object handles.']); end; + +% expand root, figure, and axes handles +if ~isempty(oldh), + ohtype = get(oldh,'Type'); + mask = strcmp(ohtype,'root') | strcmp(ohtype,'figure') | strcmp(ohtype,'axes'); + if any(mask), + oldh = num2cell(oldh); + for ii=find(mask)', + oldh(ii) = {findobj(oldh{ii},'Tag',ArrowTag)}; + end; + oldh = cat(1,oldh{:}); + if isempty(oldh), return; end; % no arrows to modify, so just leave + end; +end; + +% largest argument length +[mstart,junk]=size(start); [mstop,junk]=size(stop); [mcrossdir,junk]=size(crossdir); +argsizes = [length(oldh) mstart mstop ... + length(len) length(baseangle) length(tipangle) ... + length(wid) length(page) mcrossdir length(ends) ]; +args=['length(ObjectHandle) '; ... + '#rows(Start) '; ... + '#rows(Stop) '; ... + 'length(Length) '; ... + 'length(BaseAngle) '; ... + 'length(TipAngle) '; ... + 'length(Width) '; ... + 'length(Page) '; ... + '#rows(CrossDir) '; ... + '#rows(Ends) ']; +if (any(imag(crossdir(:))~=0)), + args(9,:) = '#rows(NormalDir) '; +end; +if isempty(oldh), + narrows = max(argsizes); +else, + narrows = length(oldh); +end; +if (narrows<=0), narrows=1; end; + +% Check size of arguments +ii = find((argsizes~=0)&(argsizes~=1)&(argsizes~=narrows)); +if ~isempty(ii), + s = args(ii',:); + while ((size(s,2)>1)&((abs(s(:,size(s,2)))==0)|(abs(s(:,size(s,2)))==abs(' ')))), + s = s(:,1:size(s,2)-1); + end; + s = [ones(length(ii),1)*[upper(mfilename) ' requires that '] s ... + ones(length(ii),1)*[' equal the # of arrows (' num2str(narrows) ').' c]]; + s = s'; + s = s(:)'; + s = s(1:length(s)-1); + error(setstr(s)); +end; + +% check element length in Start, Stop, and CrossDir +if ~isempty(start), + [m,n] = size(start); + if (n==2), + start = [start NaN*ones(m,1)]; + elseif (n~=3), + error([upper(mfilename) ' requires 2- or 3-element Start points.']); + end; +end; +if ~isempty(stop), + [m,n] = size(stop); + if (n==2), + stop = [stop NaN*ones(m,1)]; + elseif (n~=3), + error([upper(mfilename) ' requires 2- or 3-element Stop points.']); + end; +end; +if ~isempty(crossdir), + [m,n] = size(crossdir); + if (n<3), + crossdir = [crossdir NaN*ones(m,3-n)]; + elseif (n~=3), + if (all(imag(crossdir(:))==0)), + error([upper(mfilename) ' requires 2- or 3-element CrossDir vectors.']); + else, + error([upper(mfilename) ' requires 2- or 3-element NormalDir vectors.']); + end; + end; +end; + +% fill empty arguments +if isempty(start ), start = [Inf Inf Inf]; end; +if isempty(stop ), stop = [Inf Inf Inf]; end; +if isempty(len ), len = Inf; end; +if isempty(baseangle ), baseangle = Inf; end; +if isempty(tipangle ), tipangle = Inf; end; +if isempty(wid ), wid = Inf; end; +if isempty(page ), page = Inf; end; +if isempty(crossdir ), crossdir = [Inf Inf Inf]; end; +if isempty(ends ), ends = Inf; end; +if isempty(ispatch ), ispatch = Inf; end; + +% expand single-column arguments +o = ones(narrows,1); +if (size(start ,1)==1), start = o * start ; end; +if (size(stop ,1)==1), stop = o * stop ; end; +if (length(len )==1), len = o * len ; end; +if (length(baseangle )==1), baseangle = o * baseangle ; end; +if (length(tipangle )==1), tipangle = o * tipangle ; end; +if (length(wid )==1), wid = o * wid ; end; +if (length(page )==1), page = o * page ; end; +if (size(crossdir ,1)==1), crossdir = o * crossdir ; end; +if (length(ends )==1), ends = o * ends ; end; +if (length(ispatch )==1), ispatch = o * ispatch ; end; +ax = o * gca; + +% if we've got handles, get the defaults from the handles +if ~isempty(oldh), + for k=1:narrows, + oh = oldh(k); + ud = get(oh,'UserData'); + ax(k) = get(oh,'Parent'); + ohtype = get(oh,'Type'); + if strcmp(get(oh,'Tag'),ArrowTag), % if it's an arrow already + if isinf(ispatch(k)), ispatch(k)=strcmp(ohtype,'patch'); end; + % arrow UserData format: [start' stop' len base tip wid page crossdir' ends] + start0 = ud(1:3); + stop0 = ud(4:6); + if (isinf(len(k))), len(k) = ud( 7); end; + if (isinf(baseangle(k))), baseangle(k) = ud( 8); end; + if (isinf(tipangle(k))), tipangle(k) = ud( 9); end; + if (isinf(wid(k))), wid(k) = ud(10); end; + if (isinf(page(k))), page(k) = ud(11); end; + if (isinf(crossdir(k,1))), crossdir(k,1) = ud(12); end; + if (isinf(crossdir(k,2))), crossdir(k,2) = ud(13); end; + if (isinf(crossdir(k,3))), crossdir(k,3) = ud(14); end; + if (isinf(ends(k))), ends(k) = ud(15); end; + elseif strcmp(ohtype,'line')|strcmp(ohtype,'patch'), % it's a non-arrow line or patch + convLineToPatch = 1; %set to make arrow patches when converting from lines. + if isinf(ispatch(k)), ispatch(k)=convLineToPatch|strcmp(ohtype,'patch'); end; + x=get(oh,'XData'); x=x(~isnan(x(:))); if isempty(x), x=NaN; end; + y=get(oh,'YData'); y=y(~isnan(y(:))); if isempty(y), y=NaN; end; + z=get(oh,'ZData'); z=z(~isnan(z(:))); if isempty(z), z=NaN; end; + start0 = [x(1) y(1) z(1) ]; + stop0 = [x(end) y(end) z(end)]; + else, + error([upper(mfilename) ' cannot convert ' ohtype ' objects.']); + end; + ii=find(isinf(start(k,:))); if ~isempty(ii), start(k,ii)=start0(ii); end; + ii=find(isinf(stop( k,:))); if ~isempty(ii), stop( k,ii)=stop0( ii); end; + end; +end; + +% convert Inf's to NaN's +start( isinf(start )) = NaN; +stop( isinf(stop )) = NaN; +len( isinf(len )) = NaN; +baseangle( isinf(baseangle)) = NaN; +tipangle( isinf(tipangle )) = NaN; +wid( isinf(wid )) = NaN; +page( isinf(page )) = NaN; +crossdir( isinf(crossdir )) = NaN; +ends( isinf(ends )) = NaN; +ispatch( isinf(ispatch )) = NaN; + +% set up the UserData data (here so not corrupted by log10's and such) +ud = [start stop len baseangle tipangle wid page crossdir ends]; + +% Set Page defaults +page = ~isnan(page) & trueornan(page); + +% Get axes limits, range, min; correct for aspect ratio and log scale +axm = zeros(3,narrows); +axr = zeros(3,narrows); +axrev = zeros(3,narrows); +ap = zeros(2,narrows); +xyzlog = zeros(3,narrows); +limmin = zeros(2,narrows); +limrange = zeros(2,narrows); +oldaxlims = zeros(narrows,7); +oneax = all(ax==ax(1)); +if (oneax), + T = zeros(4,4); + invT = zeros(4,4); +else, + T = zeros(16,narrows); + invT = zeros(16,narrows); +end; +axnotdone = logical(ones(size(ax))); +while (any(axnotdone)), + ii = min(find(axnotdone)); + curax = ax(ii); + curpage = page(ii); + % get axes limits and aspect ratio + axl = [get(curax,'XLim'); get(curax,'YLim'); get(curax,'ZLim')]; + oldaxlims(min(find(oldaxlims(:,1)==0)),:) = [curax reshape(axl',1,6)]; + % get axes size in pixels (points) + u = get(curax,'Units'); + axposoldunits = get(curax,'Position'); + really_curpage = curpage & strcmp(u,'normalized'); + if (really_curpage), + curfig = get(curax,'Parent'); + pu = get(curfig,'PaperUnits'); + set(curfig,'PaperUnits','points'); + pp = get(curfig,'PaperPosition'); + set(curfig,'PaperUnits',pu); + set(curax,'Units','pixels'); + curapscreen = get(curax,'Position'); + set(curax,'Units','normalized'); + curap = pp.*get(curax,'Position'); + else, + set(curax,'Units','pixels'); + curapscreen = get(curax,'Position'); + curap = curapscreen; + end; + set(curax,'Units',u); + set(curax,'Position',axposoldunits); + % handle non-stretched axes position + str_stretch = { 'DataAspectRatioMode' ; ... + 'PlotBoxAspectRatioMode' ; ... + 'CameraViewAngleMode' }; + str_camera = { 'CameraPositionMode' ; ... + 'CameraTargetMode' ; ... + 'CameraViewAngleMode' ; ... + 'CameraUpVectorMode' }; + notstretched = strcmp(get(curax,str_stretch),'manual'); + manualcamera = strcmp(get(curax,str_camera),'manual'); + if ~arrow_WarpToFill(notstretched,manualcamera,curax), + % give a warning that this has not been thoroughly tested + if 0 & ARROW_STRETCH_WARN, + ARROW_STRETCH_WARN = 0; + strs = {str_stretch{1:2},str_camera{:}}; + strs = [char(ones(length(strs),1)*sprintf('\n ')) char(strs)]'; + warning([upper(mfilename) ' may not yet work quite right ' ... + 'if any of the following are ''manual'':' strs(:).']); + end; + % find the true pixel size of the actual axes + texttmp = text(axl(1,[1 2 2 1 1 2 2 1]), ... + axl(2,[1 1 2 2 1 1 2 2]), ... + axl(3,[1 1 1 1 2 2 2 2]),''); + set(texttmp,'Units','points'); + textpos = get(texttmp,'Position'); + delete(texttmp); + textpos = cat(1,textpos{:}); + textpos = max(textpos(:,1:2)) - min(textpos(:,1:2)); + % adjust the axes position + if (really_curpage), + % adjust to printed size + textpos = textpos * min(curap(3:4)./textpos); + curap = [curap(1:2)+(curap(3:4)-textpos)/2 textpos]; + else, + % adjust for pixel roundoff + textpos = textpos * min(curapscreen(3:4)./textpos); + curap = [curap(1:2)+(curap(3:4)-textpos)/2 textpos]; + end; + end; + if ARROW_PERSP_WARN & ~strcmp(get(curax,'Projection'),'orthographic'), + ARROW_PERSP_WARN = 0; + warning([upper(mfilename) ' does not yet work right for 3-D perspective projection.']); + end; + % adjust limits for log scale on axes + curxyzlog = [strcmp(get(curax,'XScale'),'log'); ... + strcmp(get(curax,'YScale'),'log'); ... + strcmp(get(curax,'ZScale'),'log')]; + if (any(curxyzlog)), + ii = find([curxyzlog;curxyzlog]); + if (any(axl(ii)<=0)), + error([upper(mfilename) ' does not support non-positive limits on log-scaled axes.']); + else, + axl(ii) = log10(axl(ii)); + end; + end; + % correct for 'reverse' direction on axes; + curreverse = [strcmp(get(curax,'XDir'),'reverse'); ... + strcmp(get(curax,'YDir'),'reverse'); ... + strcmp(get(curax,'ZDir'),'reverse')]; + ii = find(curreverse); + if ~isempty(ii), + axl(ii,[1 2])=-axl(ii,[2 1]); + end; + % compute the range of 2-D values + curT = get(curax,'Xform'); + lim = curT*[0 1 0 1 0 1 0 1;0 0 1 1 0 0 1 1;0 0 0 0 1 1 1 1;1 1 1 1 1 1 1 1]; + lim = lim(1:2,:)./([1;1]*lim(4,:)); + curlimmin = min(lim')'; + curlimrange = max(lim')' - curlimmin; + curinvT = inv(curT); + if (~oneax), + curT = curT.'; + curinvT = curinvT.'; + curT = curT(:); + curinvT = curinvT(:); + end; + % check which arrows to which cur corresponds + ii = find((ax==curax)&(page==curpage)); + oo = ones(1,length(ii)); + axr(:,ii) = diff(axl')' * oo; + axm(:,ii) = axl(:,1) * oo; + axrev(:,ii) = curreverse * oo; + ap(:,ii) = curap(3:4)' * oo; + xyzlog(:,ii) = curxyzlog * oo; + limmin(:,ii) = curlimmin * oo; + limrange(:,ii) = curlimrange * oo; + if (oneax), + T = curT; + invT = curinvT; + else, + T(:,ii) = curT * oo; + invT(:,ii) = curinvT * oo; + end; + axnotdone(ii) = zeros(1,length(ii)); +end; +oldaxlims(oldaxlims(:,1)==0,:)=[]; + +% correct for log scales +curxyzlog = xyzlog.'; +ii = find(curxyzlog(:)); +if ~isempty(ii), + start( ii) = real(log10(start( ii))); + stop( ii) = real(log10(stop( ii))); + if (all(imag(crossdir)==0)), % pulled (ii) subscript on crossdir, 12/5/96 eaj + crossdir(ii) = real(log10(crossdir(ii))); + end; +end; + +% correct for reverse directions +ii = find(axrev.'); +if ~isempty(ii), + start( ii) = -start( ii); + stop( ii) = -stop( ii); + crossdir(ii) = -crossdir(ii); +end; + +% transpose start/stop values +start = start.'; +stop = stop.'; + +% take care of defaults, page was done above +ii=find(isnan(start(:) )); if ~isempty(ii), start(ii) = axm(ii)+axr(ii)/2; end; +ii=find(isnan(stop(:) )); if ~isempty(ii), stop(ii) = axm(ii)+axr(ii)/2; end; +ii=find(isnan(crossdir(:) )); if ~isempty(ii), crossdir(ii) = zeros(length(ii),1); end; +ii=find(isnan(len )); if ~isempty(ii), len(ii) = ones(length(ii),1)*deflen; end; +ii=find(isnan(baseangle )); if ~isempty(ii), baseangle(ii) = ones(length(ii),1)*defbaseangle; end; +ii=find(isnan(tipangle )); if ~isempty(ii), tipangle(ii) = ones(length(ii),1)*deftipangle; end; +ii=find(isnan(wid )); if ~isempty(ii), wid(ii) = ones(length(ii),1)*defwid; end; +ii=find(isnan(ends )); if ~isempty(ii), ends(ii) = ones(length(ii),1)*defends; end; + +% transpose rest of values +len = len.'; +baseangle = baseangle.'; +tipangle = tipangle.'; +wid = wid.'; +page = page.'; +crossdir = crossdir.'; +ends = ends.'; +ax = ax.'; + +% given x, a 3xN matrix of points in 3-space; +% want to convert to X, the corresponding 4xN 2-space matrix +% +% tmp1=[(x-axm)./axr; ones(1,size(x,1))]; +% if (oneax), X=T*tmp1; +% else, tmp1=[tmp1;tmp1;tmp1;tmp1]; tmp1=T.*tmp1; +% tmp2=zeros(4,4*N); tmp2(:)=tmp1(:); +% X=zeros(4,N); X(:)=sum(tmp2)'; end; +% X = X ./ (ones(4,1)*X(4,:)); + +% for all points with start==stop, start=stop-(verysmallvalue)*(up-direction); +ii = find(all(start==stop)); +if ~isempty(ii), + % find an arrowdir vertical on screen and perpendicular to viewer + % transform to 2-D + tmp1 = [(stop(:,ii)-axm(:,ii))./axr(:,ii);ones(1,length(ii))]; + if (oneax), twoD=T*tmp1; + else, tmp1=[tmp1;tmp1;tmp1;tmp1]; tmp1=T(:,ii).*tmp1; + tmp2=zeros(4,4*length(ii)); tmp2(:)=tmp1(:); + twoD=zeros(4,length(ii)); twoD(:)=sum(tmp2)'; end; + twoD=twoD./(ones(4,1)*twoD(4,:)); + % move the start point down just slightly + tmp1 = twoD + [0;-1/1000;0;0]*(limrange(2,ii)./ap(2,ii)); + % transform back to 3-D + if (oneax), threeD=invT*tmp1; + else, tmp1=[tmp1;tmp1;tmp1;tmp1]; tmp1=invT(:,ii).*tmp1; + tmp2=zeros(4,4*length(ii)); tmp2(:)=tmp1(:); + threeD=zeros(4,length(ii)); threeD(:)=sum(tmp2)'; end; + start(:,ii) = (threeD(1:3,:)./(ones(3,1)*threeD(4,:))).*axr(:,ii)+axm(:,ii); +end; + +% compute along-arrow points +% transform Start points + tmp1=[(start-axm)./axr;ones(1,narrows)]; + if (oneax), X0=T*tmp1; + else, tmp1=[tmp1;tmp1;tmp1;tmp1]; tmp1=T.*tmp1; + tmp2=zeros(4,4*narrows); tmp2(:)=tmp1(:); + X0=zeros(4,narrows); X0(:)=sum(tmp2)'; end; + X0=X0./(ones(4,1)*X0(4,:)); +% transform Stop points + tmp1=[(stop-axm)./axr;ones(1,narrows)]; + if (oneax), Xf=T*tmp1; + else, tmp1=[tmp1;tmp1;tmp1;tmp1]; tmp1=T.*tmp1; + tmp2=zeros(4,4*narrows); tmp2(:)=tmp1(:); + Xf=zeros(4,narrows); Xf(:)=sum(tmp2)'; end; + Xf=Xf./(ones(4,1)*Xf(4,:)); +% compute pixel distance between points + D = sqrt(sum(((Xf(1:2,:)-X0(1:2,:)).*(ap./limrange)).^2)); + D = D + (D==0); %eaj new 2/24/98 +% compute and modify along-arrow distances + len1 = len; + len2 = len - (len.*tan(tipangle/180*pi)-wid/2).*tan((90-baseangle)/180*pi); + slen0 = zeros(1,narrows); + slen1 = len1 .* ((ends==2)|(ends==3)); + slen2 = len2 .* ((ends==2)|(ends==3)); + len0 = zeros(1,narrows); + len1 = len1 .* ((ends==1)|(ends==3)); + len2 = len2 .* ((ends==1)|(ends==3)); + % for no start arrowhead + ii=find((ends==1)&(D0), set(H,extraprops{:}); end; + % handle choosing arrow Start and/or Stop locations if unspecified + [H,oldaxlims,errstr] = arrow_clicks(H,ud,x,y,z,ax,oldaxlims); + if ~isempty(errstr), error([upper(mfilename) ' got ' errstr]); end; + % set the output + if (nargout>0), h=H; end; + % make sure the axis limits did not change + if isempty(oldaxlims), + ARROW_AXLIMITS = []; + else, + lims = get(oldaxlims(:,1),{'XLim','YLim','ZLim'})'; + lims = reshape(cat(2,lims{:}),6,size(lims,2)); + mask = arrow_is2DXY(oldaxlims(:,1)); + oldaxlims(mask,6:7) = lims(5:6,mask)'; + ARROW_AXLIMITS = oldaxlims(find(any(oldaxlims(:,2:7)'~=lims)),:); + if ~isempty(ARROW_AXLIMITS), + warning(arrow_warnlimits(ARROW_AXLIMITS,narrows)); + end; + end; +else, + % don't create the patch, just return the data + h=x; + yy=y; + zz=z; +end; + + + +function out = arrow_defcheck(in,def,prop) +% check if we got 'default' values + out = in; + if ~isstr(in), return; end; + if size(in,1)==1 & strncmp(lower(in),'def',3), + out = def; + elseif ~isempty(prop), + error([upper(mfilename) ' does not recognize ''' in(:)' ''' as a valid ''' prop ''' string.']); + end; + + + +function [H,oldaxlims,errstr] = arrow_clicks(H,ud,x,y,z,ax,oldaxlims) +% handle choosing arrow Start and/or Stop locations if necessary + errstr = ''; + if isempty(H)|isempty(ud)|isempty(x), return; end; + % determine which (if any) need Start and/or Stop + needStart = all(isnan(ud(:,1:3)'))'; + needStop = all(isnan(ud(:,4:6)'))'; + mask = any(needStart|needStop); + if ~any(mask), return; end; + ud(~mask,:)=[]; ax(:,~mask)=[]; + x(:,~mask)=[]; y(:,~mask)=[]; z(:,~mask)=[]; + % make them invisible for the time being + set(H,'Visible','off'); + % save the current axes and limits modes; set to manual for the time being + oldAx = gca; + limModes=get(ax(:),{'XLimMode','YLimMode','ZLimMode'}); + set(ax(:),{'XLimMode','YLimMode','ZLimMode'},{'manual','manual','manual'}); + % loop over each arrow that requires attention + jj = find(mask); + for ii=1:length(jj), + h = H(jj(ii)); + axes(ax(ii)); + % figure out correct call + if needStart(ii), prop='Start'; else, prop='Stop'; end; + [wasInterrupted,errstr] = arrow_click(needStart(ii)&needStop(ii),h,prop,ax(ii)); + % handle errors and control-C + if wasInterrupted, + delete(H(jj(ii:end))); + H(jj(ii:end))=[]; + oldaxlims(jj(ii:end),:)=[]; + break; + end; + end; + % restore the axes and limit modes + axes(oldAx); + set(ax(:),{'XLimMode','YLimMode','ZLimMode'},limModes); + +function [wasInterrupted,errstr] = arrow_click(lockStart,H,prop,ax) +% handle the clicks for one arrow + fig = get(ax,'Parent'); + % save some things + oldFigProps = {'Pointer','WindowButtonMotionFcn','WindowButtonUpFcn'}; + oldFigValue = get(fig,oldFigProps); + oldArrowProps = {'EraseMode'}; + oldArrowValue = get(H,oldArrowProps); + set(H,'EraseMode','background'); %because 'xor' makes shaft invisible unless Width>1 + global ARROW_CLICK_H ARROW_CLICK_PROP ARROW_CLICK_AX ARROW_CLICK_USE_Z + ARROW_CLICK_H=H; ARROW_CLICK_PROP=prop; ARROW_CLICK_AX=ax; + ARROW_CLICK_USE_Z=~arrow_is2DXY(ax)|~arrow_planarkids(ax); + set(fig,'Pointer','crosshair'); + % set up the WindowButtonMotion so we can see the arrow while moving around + set(fig,'WindowButtonUpFcn','set(gcf,''WindowButtonUpFcn'','''')', ... + 'WindowButtonMotionFcn',''); + if ~lockStart, + set(H,'Visible','on'); + set(fig,'WindowButtonMotionFcn',[mfilename '(''callback'',''motion'');']); + end; + % wait for the button to be pressed + [wasKeyPress,wasInterrupted,errstr] = arrow_wfbdown(fig); + % if we wanted to click-drag, set the Start point + if lockStart & ~wasInterrupted, + pt = arrow_point(ARROW_CLICK_AX,ARROW_CLICK_USE_Z); + feval(mfilename,H,'Start',pt,'Stop',pt); + set(H,'Visible','on'); + ARROW_CLICK_PROP='Stop'; + set(fig,'WindowButtonMotionFcn',[mfilename '(''callback'',''motion'');']); + % wait for the mouse button to be released + eval('waitfor(fig,''WindowButtonUpFcn'','''');','wasInterrupted=1;'); + if wasInterrupted, errstr=lasterr; end; + end; + if ~wasInterrupted, feval(mfilename,'callback','motion'); end; + % restore some things + set(gcf,oldFigProps,oldFigValue); + set(H,oldArrowProps,oldArrowValue); + +function arrow_callback(varargin) +% handle redrawing callbacks + if nargin==0, return; end; + str = varargin{1}; + if ~isstr(str), error([upper(mfilename) ' got an invalid Callback command.']); end; + s = lower(str); + if strcmp(s,'motion'), + % motion callback + global ARROW_CLICK_H ARROW_CLICK_PROP ARROW_CLICK_AX ARROW_CLICK_USE_Z + feval(mfilename,ARROW_CLICK_H,ARROW_CLICK_PROP,arrow_point(ARROW_CLICK_AX,ARROW_CLICK_USE_Z)); + drawnow; + else, + error([upper(mfilename) ' does not recognize ''' str(:).' ''' as a valid Callback option.']); + end; + +function out = arrow_point(ax,use_z) +% return the point on the given axes + if nargin==0, ax=gca; end; + if nargin<2, use_z=~arrow_is2DXY(ax)|~arrow_planarkids(ax); end; + out = get(ax,'CurrentPoint'); + out = out(1,:); + if ~use_z, out=out(1:2); end; + +function [wasKeyPress,wasInterrupted,errstr] = arrow_wfbdown(fig) +% wait for button down ignoring object ButtonDownFcn's + if nargin==0, fig=gcf; end; + errstr = ''; + % save ButtonDownFcn values + objs = findobj(fig); + buttonDownFcns = get(objs,'ButtonDownFcn'); + mask=~strcmp(buttonDownFcns,''); objs=objs(mask); buttonDownFcns=buttonDownFcns(mask); + set(objs,'ButtonDownFcn',''); + % save other figure values + figProps = {'KeyPressFcn','WindowButtonDownFcn'}; + figValue = get(fig,figProps); + % do the real work + set(fig,'KeyPressFcn','set(gcf,''KeyPressFcn'','''',''WindowButtonDownFcn'','''');', ... + 'WindowButtonDownFcn','set(gcf,''WindowButtonDownFcn'','''')'); + lasterr(''); + wasInterrupted=0; eval('waitfor(fig,''WindowButtonDownFcn'','''');','wasInterrupted=1;'); + wasKeyPress = ~wasInterrupted & strcmp(get(fig,'KeyPressFcn'),''); + if wasInterrupted, errstr=lasterr; end; + % restore ButtonDownFcn and other figure values + set(objs,'ButtonDownFcn',buttonDownFcns); + set(fig,figProps,figValue); + + + +function [out,is2D] = arrow_is2DXY(ax) +% check if axes are 2-D X-Y plots + % may not work for modified camera angles, etc. + out = logical(zeros(size(ax))); % 2-D X-Y plots + is2D = out; % any 2-D plots + views = get(ax(:),{'View'}); + views = cat(1,views{:}); + out(:) = abs(views(:,2))==90; + is2D(:) = out(:) | all(rem(views',90)==0)'; + +function out = arrow_planarkids(ax) +% check if axes descendents all have empty ZData (lines,patches,surfaces) + out = logical(ones(size(ax))); + allkids = get(ax(:),{'Children'}); + for k=1:length(allkids), + kids = get([findobj(allkids{k},'flat','Type','line') + findobj(allkids{k},'flat','Type','patch') + findobj(allkids{k},'flat','Type','surface')],{'ZData'}); + for j=1:length(kids), + if ~isempty(kids{j}), out(k)=logical(0); break; end; + end; + end; + + + +function arrow_fixlimits(axlimits) +% reset the axis limits as necessary + if isempty(axlimits), disp([upper(mfilename) ' does not remember any axis limits to reset.']); end; + for k=1:size(axlimits,1), + if any(get(axlimits(k,1),'XLim')~=axlimits(k,2:3)), set(axlimits(k,1),'XLim',axlimits(k,2:3)); end; + if any(get(axlimits(k,1),'YLim')~=axlimits(k,4:5)), set(axlimits(k,1),'YLim',axlimits(k,4:5)); end; + if any(get(axlimits(k,1),'ZLim')~=axlimits(k,6:7)), set(axlimits(k,1),'ZLim',axlimits(k,6:7)); end; + end; + + + +function out = arrow_WarpToFill(notstretched,manualcamera,curax) +% check if we are in "WarpToFill" mode. + out = strcmp(get(curax,'WarpToFill'),'on'); + % 'WarpToFill' is undocumented, so may need to replace this by + % out = ~( any(notstretched) & any(manualcamera) ); + + + +function out = arrow_warnlimits(axlimits,narrows) +% create a warning message if we've changed the axis limits + msg = ''; + switch (size(axlimits,1)) + case 1, msg=''; + case 2, msg='on two axes '; + otherwise, msg='on several axes '; + end; + msg = [upper(mfilename) ' changed the axis limits ' msg ... + 'when adding the arrow']; + if (narrows>1), msg=[msg 's']; end; + out = [msg '.' sprintf('\n') ' Call ' upper(mfilename) ... + ' FIXLIMITS to reset them now.']; + + + +function arrow_copyprops(fm,to) +% copy line properties to patches + props = {'EraseMode','LineStyle','LineWidth','Marker','MarkerSize',... + 'MarkerEdgeColor','MarkerFaceColor','ButtonDownFcn', ... + 'Clipping','DeleteFcn','BusyAction','HandleVisibility', ... + 'Selected','SelectionHighlight','Visible'}; + lineprops = {'Color', props{:}}; + patchprops = {'EdgeColor',props{:}}; + patch2props = {'FaceColor',patchprops{:}}; + fmpatch = strcmp(get(fm,'Type'),'patch'); + topatch = strcmp(get(to,'Type'),'patch'); + set(to( fmpatch& topatch),patch2props,get(fm( fmpatch& topatch),patch2props)); %p->p + set(to(~fmpatch&~topatch),lineprops, get(fm(~fmpatch&~topatch),lineprops )); %l->l + set(to( fmpatch&~topatch),lineprops, get(fm( fmpatch&~topatch),patchprops )); %p->l + set(to(~fmpatch& topatch),patchprops, get(fm(~fmpatch& topatch),lineprops) ,'FaceColor','none'); %l->p + + + +function arrow_props +% display further help info about ARROW properties + c = sprintf('\n'); + disp([c ... + 'ARROW Properties: Default values are given in [square brackets], and other' c ... + ' acceptable equivalent property names are in (parenthesis).' c c ... + ' Start The starting points. For N arrows, B' c ... + ' this should be a Nx2 or Nx3 matrix. /|\ ^' c ... + ' Stop The end points. For N arrows, this /|||\ |' c ... + ' should be a Nx2 or Nx3 matrix. //|||\\ L|' c ... + ' Length Length of the arrowhead (in pixels on ///|||\\\ e|' c ... + ' screen, points on a page). [16] (Len) ////|||\\\\ n|' c ... + ' BaseAngle Angle (degrees) of the base angle /////|D|\\\\\ g|' c ... + ' ADE. For a simple stick arrow, use //// ||| \\\\ t|' c ... + ' BaseAngle=TipAngle. [90] (Base) /// ||| \\\ h|' c ... + ' TipAngle Angle (degrees) of tip angle ABC. //<----->|| \\ |' c ... + ' [16] (Tip) / base ||| \ V' c ... + ' Width Width of the base in pixels. Not E angle ||<-------->C' c ... + ' the ''LineWidth'' prop. [0] (Wid) |||tipangle' c ... + ' Page If provided, non-empty, and not NaN, |||' c ... + ' this causes ARROW to use hardcopy |||' c ... + ' rather than onscreen proportions. A' c ... + ' This is important if screen aspect --> <-- width' c ... + ' ratio and hardcopy aspect ratio are ----CrossDir---->' c ... + ' vastly different. []' c... + ' CrossDir A vector giving the direction towards which the fletches' c ... + ' on the arrow should go. [computed such that it is perpen-' c ... + ' dicular to both the arrow direction and the view direction' c ... + ' (i.e., as if it was pasted on a normal 2-D graph)] (Note' c ... + ' that CrossDir is a vector. Also note that if an axis is' c ... + ' plotted on a log scale, then the corresponding component' c ... + ' of CrossDir must also be set appropriately, i.e., to 1 for' c ... + ' no change in that direction, >1 for a positive change, >0' c ... + ' and <1 for negative change.)' c ... + ' NormalDir A vector normal to the fletch direction (CrossDir is then' c ... + ' computed by the vector cross product [Line]x[NormalDir]). []' c ... + ' (Note that NormalDir is a vector. Unlike CrossDir,' c ... + ' NormalDir is used as is regardless of log-scaled axes.)' c ... + ' Ends Set which end has an arrowhead. Valid values are ''none'',' c ... + ' ''stop'', ''start'', and ''both''. [''stop''] (End)' c... + ' ObjectHandles Vector of handles to previously-created arrows to be' c ... + ' updated or line objects to be converted to arrows.' c ... + ' [] (Object,Handle)' c ]); + + + +function out = arrow_demo + % demo + % create the data + [x,y,z] = peaks; + [ddd,out.iii]=max(z(:)); + out.axlim = [min(x(:)) max(x(:)) min(y(:)) max(y(:)) min(z(:)) max(z(:))]; + + % modify it by inserting some NaN's + [m,n] = size(z); + m = floor(m/2); + n = floor(n/2); + z(1:m,1:n) = NaN*ones(m,n); + + % graph it + clf('reset'); + out.hs=surf(x,y,z); + out.x=x; out.y=y; out.z=z; + xlabel('x'); ylabel('y'); + +function h = arrow_demo3(in) + % set the view + axlim = in.axlim; + axis(axlim); + zlabel('z'); + %set(in.hs,'FaceColor','interp'); + view(viewmtx(-37.5,30,20)); + title(['Demo of the capabilities of the ARROW function in 3-D']); + + % Normal blue arrow + h1 = feval(mfilename,[axlim(1) axlim(4) 4],[-.8 1.2 4], ... + 'EdgeColor','b','FaceColor','b'); + + % Normal white arrow, clipped by the surface + h2 = feval(mfilename,axlim([1 4 6]),[0 2 4]); + t=text(-2.4,2.7,7.7,'arrow clipped by surf'); + + % Baseangle<90 + h3 = feval(mfilename,[3 .125 3.5],[1.375 0.125 3.5],30,50); + t2=text(3.1,.125,3.5,'local maximum'); + + % Baseangle<90, fill and edge colors different + h4 = feval(mfilename,axlim(1:2:5)*.5,[0 0 0],36,60,25, ... + 'EdgeColor','b','FaceColor','c'); + t3=text(axlim(1)*.5,axlim(3)*.5,axlim(5)*.5-.75,'origin'); + set(t3,'HorizontalAlignment','center'); + + % Baseangle>90, black fill + h5 = feval(mfilename,[-2.9 2.9 3],[-1.3 .4 3.2],30,120,[],6, ... + 'EdgeColor','r','FaceColor','k','LineWidth',2); + + % Baseangle>90, no fill + h6 = feval(mfilename,[-2.9 2.9 1.3],[-1.3 .4 1.5],30,120,[],6, ... + 'EdgeColor','r','FaceColor','none','LineWidth',2); + + % Stick arrow + h7 = feval(mfilename,[-1.6 -1.65 -6.5],[0 -1.65 -6.5],[],16,16); + t4=text(-1.5,-1.65,-7.25,'global mininum'); + set(t4,'HorizontalAlignment','center'); + + % Normal, black fill + h8 = feval(mfilename,[-1.4 0 -7.2],[-1.4 0 -3],'FaceColor','k'); + t5=text(-1.5,0,-7.75,'local minimum'); + set(t5,'HorizontalAlignment','center'); + + % Gray fill, crossdir specified, 'LineStyle' -- + h9 = feval(mfilename,[-3 2.2 -6],[-3 2.2 -.05],36,[],27,6,[],[0 -1 0], ... + 'EdgeColor','k','FaceColor',.75*[1 1 1],'LineStyle','--'); + + % a series of normal arrows, linearly spaced, crossdir specified + h10y=(0:4)'/3; + h10 = feval(mfilename,[-3*ones(size(h10y)) h10y -6.5*ones(size(h10y))], ... + [-3*ones(size(h10y)) h10y -.05*ones(size(h10y))], ... + 12,[],[],[],[],[0 -1 0]); + + % a series of normal arrows, linearly spaced + h11x=(1:.33:2.8)'; + h11 = feval(mfilename,[h11x -3*ones(size(h11x)) 6.5*ones(size(h11x))], ... + [h11x -3*ones(size(h11x)) -.05*ones(size(h11x))]); + + % series of magenta arrows, radially oriented, crossdir specified + h12x=2; h12y=-3; h12z=axlim(5)/2; h12xr=1; h12zr=h12z; ir=.15;or=.81; + h12t=(0:11)'/6*pi; + h12 = feval(mfilename, ... + [h12x+h12xr*cos(h12t)*ir h12y*ones(size(h12t)) ... + h12z+h12zr*sin(h12t)*ir],[h12x+h12xr*cos(h12t)*or ... + h12y*ones(size(h12t)) h12z+h12zr*sin(h12t)*or], ... + 10,[],[],[],[], ... + [-h12xr*sin(h12t) zeros(size(h12t)) h12zr*cos(h12t)],... + 'FaceColor','none','EdgeColor','m'); + + % series of normal arrows, tangentially oriented, crossdir specified + or13=.91; h13t=(0:.5:12)'/6*pi; + locs = [h12x+h12xr*cos(h13t)*or13 h12y*ones(size(h13t)) h12z+h12zr*sin(h13t)*or13]; + h13 = feval(mfilename,locs(1:end-1,:),locs(2:end,:),6); + + % arrow with no line ==> oriented downwards + h14 = feval(mfilename,[3 3 .100001],[3 3 .1],30); + t6=text(3,3,3.6,'no line'); set(t6,'HorizontalAlignment','center'); + + % arrow with arrowheads at both ends + h15 = feval(mfilename,[-.5 -3 -3],[1 -3 -3],'Ends','both','FaceColor','g', ... + 'Length',20,'Width',3,'CrossDir',[0 0 1],'TipAngle',25); + + h=[h1;h2;h3;h4;h5;h6;h7;h8;h9;h10;h11;h12;h13;h14;h15]; + +function h = arrow_demo2(in) + axlim = in.axlim; + dolog = 1; + if (dolog), set(in.hs,'YData',10.^get(in.hs,'YData')); end; + shading('interp'); + view(2); + title(['Demo of the capabilities of the ARROW function in 2-D']); + hold on; [C,H]=contour(in.x,in.y,in.z,20,'-'); hold off; + for k=H', + set(k,'ZData',(axlim(6)+1)*ones(size(get(k,'XData'))),'Color','k'); + if (dolog), set(k,'YData',10.^get(k,'YData')); end; + end; + if (dolog), axis([axlim(1:2) 10.^axlim(3:4)]); set(gca,'YScale','log'); + else, axis(axlim(1:4)); end; + + % Normal blue arrow + start = [axlim(1) axlim(4) axlim(6)+2]; + stop = [in.x(in.iii) in.y(in.iii) axlim(6)+2]; + if (dolog), start(:,2)=10.^start(:,2); stop(:,2)=10.^stop(:,2); end; + h1 = feval(mfilename,start,stop,'EdgeColor','b','FaceColor','b'); + + % three arrows with varying fill, width, and baseangle + start = [-3 -3 10; -3 -1.5 10; -1.5 -3 10]; + stop = [-.03 -.03 10; -.03 -1.5 10; -1.5 -.03 10]; + if (dolog), start(:,2)=10.^start(:,2); stop(:,2)=10.^stop(:,2); end; + h2 = feval(mfilename,start,stop,24,[90;60;120],[],[0;0;4],'Ends',str2mat('both','stop','stop')); + set(h2(2),'EdgeColor',[0 .35 0],'FaceColor',[0 .85 .85]); + set(h2(3),'EdgeColor','r','FaceColor',[1 .5 1]); + h=[h1;h2]; + +function out = trueornan(x) +if isempty(x), + out=x; +else, + out = isnan(x); + out(~out) = x(~out); +end; + diff --git a/external/fieldtrip/private/artifact_clip.m b/external/fieldtrip/private/artifact_clip.m deleted file mode 100644 index d523e84..0000000 --- a/external/fieldtrip/private/artifact_clip.m +++ /dev/null @@ -1,216 +0,0 @@ -function [cfg, artifact] = artifact_clip(cfg,data) - -% ARTIFACT_CLIP scans the data segments of interest for channels that -% clip. A clipping artifact is detected by the signal being completely -% flat for some time. -% -% Use as -% [cfg, artifact] = artifact_clip(cfg) -% required configuration options: -% cfg.dataset or both cfg.headerfile and cfg.datafile -% or -% [cfg, artifact] = artifact_clip(cfg, data) -% forbidden configuration options: -% cfg.dataset, cfg.headerfile and cfg.datafile -% -% In both cases the configuration should also contain: -% cfg.artfctdef.clip.channel = Nx1 cell-array with selection of channels, see CHANNELSELECTION for details -% cfg.artfctdef.clip.pretim = 0.000; pre-artifact rejection-interval in seconds -% cfg.artfctdef.clip.psttim = 0.000; post-artifact rejection-interval in seconds -% cfg.artfctdef.clip.thresh = 0.010; minimum duration in seconds of a datasegment with consecutive identical samples to be considered as 'clipped' -% cfg.continuous = 'yes' or 'no' whether the file contains continuous data -% -% See also REJECTARTIFACT - -% Copyright (C) 2005, Robert Oostenveld -% -% $Log: artifact_clip.m,v $ -% Revision 1.22 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.21 2009/01/16 18:19:41 sashae -% moved some lines of code, no functional change -% -% Revision 1.20 2009/01/14 11:47:07 sashae -% changed handling of cfg.datatype -% added call to checkconfig at start and end of function -% -% Revision 1.19 2008/12/02 16:29:42 estmee -% Set default cfg.continuous/ checkconfig cfg.datatype = forbidden -% -% Revision 1.18 2008/11/25 13:12:48 estmee -% Documentation update -% -% Revision 1.17 2008/11/18 16:11:42 estmee -% Added cfg.continuous option to documentation. -% -% Revision 1.16 2008/10/13 14:37:46 estmee -% Changed the checkboundary again when calling read_data. -% -% Revision 1.15 2008/10/13 13:57:23 estmee -% Added checkboundary as input argument read_data. -% -% Revision 1.14 2008/10/13 11:39:34 sashae -% added call to checkconfig (as discussed with estmee) -% -% Revision 1.13 2008/10/07 16:16:31 estmee -% Added data as second input argument to artifact_clip. -% -% Revision 1.12 2008/10/07 08:58:51 roboos -% committed the changes that Esther made recently, related to the support of data as input argument to the artifact detection functions. I hope that this does not break the functions too seriously. -% -% Revision 1.11 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.10 2008/05/13 15:37:24 roboos -% switched to using read_data/header instead of the read_fcdc_data/header wrapper functions -% -% Revision 1.9 2006/11/29 09:06:36 roboos -% renamed all cfg options with "sgn" into "channel", added backward compatibility when required -% updated documentation, mainly in the artifact detection routines -% -% Revision 1.8 2006/06/14 12:43:48 roboos -% removed the documentation for cfg.lnfilttype, since that option is not supported by preproc -% -% Revision 1.7 2006/04/20 09:58:33 roboos -% updated documentation -% -% Revision 1.6 2006/04/12 08:38:01 ingnie -% updated documentation -% -% Revision 1.5 2006/01/31 13:49:29 jansch -% included dataset2files to ensure the presence of cfg.headerfile or cfg.datafile -% whenever needed -% -% Revision 1.4 2005/12/20 08:36:47 roboos -% add the artifact Nx2 matrix to the output configuration -% changed some indentation and white space, renamed a few variables -% -% Revision 1.3 2005/10/06 14:28:20 roboos -% added check for case when no artifacts are found -% -% Revision 1.2 2005/09/05 10:37:03 roboos -% added pretim and psttim option for extending the detected artifacts -% added copyright and log -% - -fieldtripdefs - -% check if the input cfg is valid for this function -cfg = checkconfig(cfg, 'trackconfig', 'on'); -cfg = checkconfig(cfg, 'renamed', {'datatype', 'continuous'}); -cfg = checkconfig(cfg, 'renamedval', {'continuous', 'continuous', 'yes'}); - -% set default rejection parameters for clip artifacts if necessary. -if ~isfield(cfg,'artfctdef'), cfg.artfctdef = []; end; -if ~isfield(cfg.artfctdef,'clip'), cfg.artfctdef.clip = []; end; -if ~isfield(cfg.artfctdef.clip,'channel'), cfg.artfctdef.clip.channel = 'all'; end; -if ~isfield(cfg.artfctdef.clip,'thresh'), cfg.artfctdef.clip.thresh = 0.010; end; -if ~isfield(cfg.artfctdef.clip,'pretim'), cfg.artfctdef.clip.pretim = 0.000; end; -if ~isfield(cfg.artfctdef.clip,'psttim'), cfg.artfctdef.clip.psttim = 0.000; end; - -% for backward compatibility -if isfield(cfg.artfctdef.clip,'sgn') - cfg.artfctdef.clip.channel = cfg.artfctdef.clip.sgn; - cfg.artfctdef.clip = rmfield(cfg.artfctdef.clip, 'sgn'); -end - -% start with an empty artifact list -artifact = []; - -% read the header -if nargin == 1 - isfetch = 0; - cfg = checkconfig(cfg, 'dataset2files', {'yes'}); - cfg = checkconfig(cfg, 'required', {'headerfile', 'datafile'}); - hdr = read_header(cfg.headerfile); -elseif nargin == 2 - isfetch = 1; - cfg = checkconfig(cfg, 'forbidden', {'dataset', 'headerfile', 'datafile'}); - hdr = fetch_header(data); -end - -% set default cfg.continuous -if ~isfield(cfg, 'continuous') - if hdr.nTrials==1 - cfg.continuous = 'yes'; - else - cfg.continuous = 'no'; - end -end - -% find the channel labels present in the data and their indices -label = channelselection(cfg.artfctdef.clip.channel, hdr.label); -sgnindx = match_str(hdr.label, label); - -% make a local copy for convenience -artfctdef = cfg.artfctdef.clip; - -ntrl = size(cfg.trl,1); -nsgn = length(sgnindx); -for trlop=1:ntrl - fprintf('searching for clipping artifacts in trial %d\n', trlop); - % read the data of this trial - if isfetch - dat = fetch_data(data, 'header', hdr, 'begsample', cfg.trl(trlop,1), 'endsample', cfg.trl(trlop,2), 'chanindx', sgnindx); - else - dat = read_data(cfg.datafile, 'header', hdr, 'begsample', cfg.trl(trlop,1), 'endsample', cfg.trl(trlop,2), 'chanindx', sgnindx, 'checkboundary', strcmp(cfg.continuous, 'no')); - end - % apply filtering etc to the data - datflt = preproc(dat, label, hdr.Fs, artfctdef, cfg.trl(trlop,3)); - % detect all samples that have the same value as the previous sample - identical = (datflt(:,1:(end-1)) == datflt(:,2:end)); - % ensure that the number of samples does not change - identical = [identical zeros(nsgn,1)]; - - % determine the number of consecutively identical samples - clip = zeros(size(dat)); - for sgnlop=1:length(sgnindx) - up = find(diff([0 identical(sgnlop,:)], 1, 2)== 1); - dw = find(diff([identical(sgnlop,:) 0], 1, 2)==-1); - for k=1:length(up) - clip(sgnlop,up(k):dw(k)) = dw(k)-up(k); - end - end - % collapse over cannels - clip = max(clip,[],1); - - % detect whether there are intervals in which the number of consecutive - % identical samples is larger than the threshold - thresh = (clip>=artfctdef.thresh*hdr.Fs); - - % remember the thresholded parts as artifacts - artup = find(diff([0 thresh])== 1) + cfg.trl(trlop,1) - 1; - artdw = find(diff([thresh 0])==-1) + cfg.trl(trlop,1) - 1; - for k=1:length(artup) - artifact(end+1,:) = [artup(k) artdw(k)]; - end -end - -if ~isempty(artifact) - % add the pretim and psttim to the detected artifacts - artifact(:,1) = artifact(:,1) - artfctdef.pretim * hdr.Fs; - artifact(:,2) = artifact(:,2) + artfctdef.psttim * hdr.Fs; -end - -% remember the details that were used here -cfg.artfctdef.clip = artfctdef; -cfg.artfctdef.clip.label = label; -cfg.artfctdef.clip.trl = cfg.trl; -cfg.artfctdef.clip.artifact = artifact; - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: artifact_clip.m,v 1.22 2009/01/20 13:01:31 sashae Exp $'; diff --git a/external/fieldtrip/private/artifact_ecg.m b/external/fieldtrip/private/artifact_ecg.m deleted file mode 100644 index 0d03c80..0000000 --- a/external/fieldtrip/private/artifact_ecg.m +++ /dev/null @@ -1,367 +0,0 @@ -function [cfg, artifact] = artifact_ecg(cfg, data) - -% ARTIFACT_ECG performs a peak-detection on the ECG-channel. The -% heart activity can be seen in the MEG data as an MCG artifact and -% can be removed using independent component analysis. -% -% Use as -% [cfg, artifact] = artifact_ecg(cfg) -% required configuration options: -% cfg.dataset or both cfg.headerfile and cfg.datafile -% -% In both cases the configuration should also contain: -% cfg.artfctdef.ecg.channel = Nx1 cell-array with selection of channels, see CHANNELSELECTION for details -% cfg.artfctdef.ecg.pretim = 0.05; pre-artifact rejection-interval in seconds -% cfg.artfctdef.ecg.psttim = 0.3; post-artifact rejection-interval in seconds -% cfg.artfctdef.ecg.method = 'zvalue'; peak-detection method -% cfg.artfctdef.ecg.cutoff = 3; peak-threshold -% cfg.artfctdef.ecg.inspect = Nx1 list of channels which will be shown in a QRS-locked average -% cfg.continuous = 'yes' or 'no' whether the file contains continuous data -% -% The output artifact variable is an Nx2-matrix, containing the -% begin and end samples of the QRST-complexes in the ECG. -% -% See also REJECTARTIFACT - -% Undocumented local options: -% cfg.datatype - -% Copyright (c) 2005, Jan-Mathijs Schoffelen -% -% $Log: artifact_ecg.m,v $ -% Revision 1.25 2009/09/30 12:40:11 jansch -% allow to work on data which have been downsampled from the original sampling rate -% -% Revision 1.24 2009/02/19 10:09:47 jansch -% added possibility to take a data structure as second input -% -% Revision 1.23 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.22 2009/01/16 18:19:41 sashae -% moved some lines of code, no functional change -% -% Revision 1.21 2009/01/14 11:47:07 sashae -% changed handling of cfg.datatype -% added call to checkconfig at start and end of function -% -% Revision 1.20 2008/12/02 16:30:45 estmee -% Set default cfg.continuous/ checkconfig cfg.datatype = forbidden -% -% Revision 1.19 2008/11/25 13:13:47 estmee -% Documentation update -% -% Revision 1.18 2008/11/18 16:13:49 estmee -% Added cfg.continuous -% -% Revision 1.17 2008/10/13 10:40:47 sashae -% added call to checkconfig -% -% Revision 1.16 2008/10/07 08:58:51 roboos -% committed the changes that Esther made recently, related to the support of data as input argument to the artifact detection functions. I hope that this does not break the functions too seriously. -% -% Revision 1.15 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.14 2008/06/17 15:43:09 sashae -% now using preproc_modules -% -% Revision 1.13 2008/05/13 15:37:24 roboos -% switched to using read_data/header instead of the read_fcdc_data/header wrapper functions -% -% Revision 1.12 2007/07/31 08:40:59 jansch -% added option cfg.arfctdef.ecg.mindist to specify the minimal distance between -% the peaks -% -% Revision 1.11 2006/11/29 09:06:36 roboos -% renamed all cfg options with "sgn" into "channel", added backward compatibility when required -% updated documentation, mainly in the artifact detection routines -% -% Revision 1.10 2006/06/14 12:43:49 roboos -% removed the documentation for cfg.lnfilttype, since that option is not supported by preproc -% -% Revision 1.9 2006/04/20 09:58:33 roboos -% updated documentation -% -% Revision 1.8 2006/04/12 08:38:01 ingnie -% updated documentation -% -% Revision 1.7 2006/01/31 13:49:29 jansch -% included dataset2files to ensure the presence of cfg.headerfile or cfg.datafile -% whenever needed -% -% Revision 1.6 2006/01/30 14:07:01 jansch -% added new ntrl in line 135 since the number of trials could have changed -% -% Revision 1.5 2005/12/20 08:36:47 roboos -% add the artifact Nx2 matrix to the output configuration -% changed some indentation and white space, renamed a few variables -% -% Revision 1.4 2005/09/29 14:56:32 jansch -% first implementation -% - -fieldtripdefs - -% check if the input cfg is valid for this function -cfg = checkconfig(cfg, 'trackconfig', 'on'); -cfg = checkconfig(cfg, 'renamed', {'datatype', 'continuous'}); -cfg = checkconfig(cfg, 'renamedval', {'continuous', 'continuous', 'yes'}); - -% set default rejection parameters for eog artifacts if necessary. -if ~isfield(cfg,'artfctdef'), cfg.artfctdef = []; end -if ~isfield(cfg.artfctdef,'ecg'), cfg.artfctdef.ecg = []; end -if ~isfield(cfg.artfctdef.ecg,'channel'),cfg.artfctdef.ecg.channel = {'ECG'}; end -if ~isfield(cfg.artfctdef.ecg,'method'), cfg.artfctdef.ecg.method = 'zvalue'; end -if ~isfield(cfg.artfctdef.ecg,'cutoff'), cfg.artfctdef.ecg.cutoff = 3; end -if ~isfield(cfg.artfctdef.ecg,'padding'),cfg.artfctdef.ecg.padding = 0.5; end -if ~isfield(cfg.artfctdef.ecg,'inspect'),cfg.artfctdef.ecg.inspect = {'MLT' 'MRT'}; end -if ~isfield(cfg.artfctdef.ecg,'pretim'), cfg.artfctdef.ecg.pretim = 0.05; end -if ~isfield(cfg.artfctdef.ecg,'psttim'), cfg.artfctdef.ecg.psttim = 0.3; end -if ~isfield(cfg.artfctdef.ecg,'mindist'), cfg.artfctdef.ecg.mindist = 0.5; end - -% for backward compatibility -if isfield(cfg.artfctdef.ecg,'sgn') - cfg.artfctdef.ecg.channel = cfg.artfctdef.ecg.sgn; - cfg.artfctdef.ecg = rmfield(cfg.artfctdef.ecg, 'sgn'); -end - -if ~strcmp(cfg.artfctdef.ecg.method, 'zvalue'), - error('this method is not applicable'); -end - -if nargin == 1, - cfg = checkconfig(cfg, 'dataset2files', {'yes'}); - cfg = checkconfig(cfg, 'required', {'headerfile', 'datafile'}); - hdr = read_header(cfg.headerfile); - trl = cfg.trl; -elseif nargin == 2, - cfg = checkconfig(cfg, 'forbidden', {'dataset', 'headerfile', 'datafile'}); - hdr = fetch_header(data); - trl = findcfg(data.cfg, 'trl'); -end -artfctdef = cfg.artfctdef.ecg; -padsmp = round(artfctdef.padding*hdr.Fs); -ntrl = size(trl,1); -artfctdef.trl = trl; -artfctdef.channel = channelselection(artfctdef.channel, hdr.label); -artfctdef.blc = 'yes'; -sgnind = match_str(hdr.label, artfctdef.channel); -numecgsgn = length(sgnind); -fltpadding = 0; - -if numecgsgn<1 - error('no ECG channels selected'); -elseif numecgsgn>1 - error('only one ECG channel can be selected'); -end - -% set default cfg.continuous -if ~isfield(cfg, 'continuous') - if hdr.nTrials==1 - cfg.continuous = 'yes'; - else - cfg.continuous = 'no'; - end -end - -% read in the ecg-channel and do blc and squaring -if nargin==2, - tmpcfg = []; - tmpcfg.channel = artfctdef.channel; - ecgdata = preprocessing(tmpcfg, data); - ecg = ecgdata.trial; -end - -for j = 1:ntrl - if nargin==1, - ecg{j} = read_data(cfg.datafile, 'header', hdr, 'begsample', trl(j,1), 'endsample', trl(j,2), 'chanindx', sgnind, 'checkboundary', strcmp(cfg.continuous, 'no')); - end - ecg{j} = preproc(ecg{j}, artfctdef.channel, hdr.Fs, artfctdef, [], fltpadding, fltpadding); - ecg{j} = ecg{j}.^2; -end - -if nargin==2 && ~isempty(findcfg(data.cfg,'resamplefs')) && ~isempty(findcfg(data.cfg,'resampletrl')), - %the data have been resampled along the way, the trl is in the original sampling rate - %adjust this - warning('the data have been resampled along the way, the trl-definition is in the original sampling rate, attempt to adjust for this may introduce some timing inaccuracies'); - trlold = trl; - trl = findcfg(data.cfg,'resampletrl'); -% fsampleold = findcfg(data.cfg,'origfs'); -% fsamplenew = findcfg(data.cfg,'resamplefs'); -% dfs = fsamplenew./fsampleold; -% trl(:,1) = round((trlold(:,1)-1).*dfs)+1; -% trl(:,2) = round((trlold(:,2)-1).*dfs)+1; -% %I don't know how to deal with some rounding errors brought about by strange values of sampling rates etc -% %allow slips of 1 sample -% trllen = cellfun('size',data.trial,2)'; -% trllen2 = trl(:,2)-trl(:,1)+1; -% toolong = trllen2-trllen==1; -% tooshort = trllen2-trllen==-1; -% trl(toolong,2) = trl(toolong,2)-1; -% trl(tooshort,2) = trl(tooshort,2)+1; -% data.cfg.trl = trl; -end - -tmp = cell2mat(ecg); -stmp = std(tmp, 0, 2); -mtmp = mean(tmp, 2); -Nsmp = max(trl(:,2)); -trace = zeros(1,Nsmp); - -% standardise the ecg -for j = 1:ntrl - trace(trl(j,1):trl(j,2)) = (ecg{j}-mtmp)./stmp; -end - -accept = 0; -while accept == 0, - h = figure; - plot(trace);zoom; - hold on; - plot([1 Nsmp], [artfctdef.cutoff artfctdef.cutoff], 'r:'); - hold off; - xlabel('samples'); - ylabel('zscore'); - - fprintf(['\ncurrent ',artfctdef.method,' threshold = %1.3f'], artfctdef.cutoff); - response = input('\nkeep the current value (y/n) ?\n','s'); - switch response - case 'n' - oldcutoff = artfctdef.cutoff; - artfctdef.cutoff = input('\nenter new value \n'); - case 'y' - oldcutoff = artfctdef.cutoff; - accept = 1; - otherwise - warning('unrecognised response, assuming no'); - oldcutoff = artfctdef.cutoff; - artfctdef.cutoff = input('\nenter new value \n'); - end; - close -end - -% detect peaks which are at least half a second apart and store -% the indices of the qrs-complexes in the artifact-configuration -mindist = round(cfg.artfctdef.ecg.mindist.*hdr.Fs); -[pindx, pval] = peakdetect2(trace, artfctdef.cutoff, mindist); -%sel = find(standardise(pval,2)<2); -%pindx = pindx(sel); -%pval = pval(sel); -artfctdef.qrs = pindx; - -%--------------------------------------- -% create trials for qrs-triggered average -trl = []; -trl(:,1) = pindx(:) - round(artfctdef.padding*(hdr.Fs)) ; -trl(:,2) = pindx(:) + round(artfctdef.padding*(hdr.Fs))-1; -trl(:,3) = -round(artfctdef.padding*(hdr.Fs)); -trl(trl(:,1)<1,:) = []; -trl(trl(:,2)>hdr.nSamples.*hdr.nTrials,:) = []; -%------------ - -% --------------------- -% qrs-triggered average -% FIXME, at present this only works for continuous data: the assumption can -% be made that all trials are equally long. -sgn = channelselection(artfctdef.inspect, hdr.label); -megind = match_str(hdr.label, sgn); -sgnind = [megind(:); sgnind]; -dat = zeros(length(sgnind), trl(1,2)-trl(1,1)+1); -ntrl = size(trl,1); - -if ~isempty(sgnind) - ntrlok = 0; - for j = 1:ntrl - fprintf('reading and preprocessing trial %d of %d\n', j, ntrl); - if nargin==1, - dum = read_data(cfg.datafile, 'header', hdr, 'begsample', trl(j,1), 'endsample', trl(j,2), 'chanindx', sgnind, 'checkboundary', strcmp(cfg.continuous, 'no')); - dat = dat + preproc_baselinecorrect(dum); - ntrlok = ntrlok + 1; - elseif nargin==2, - dum = fetch_data(data, 'header', hdr, 'begsample', trl(j,1), 'endsample', trl(j,2), 'chanindx', sgnind, 'checkboundary', strcmp(cfg.continuous, 'no'), 'docheck', 0); - if any(~isfinite(dum(:))), - else - ntrlok = ntrlok + 1; - dat = dat + preproc_baselinecorrect(dum); - end - end - end -end - -dat = dat./ntrlok; -time = offset2time(trl(1,3), hdr.Fs, size(dat,2)); -tmp = dat(1:end-1,:); -mdat = max(abs(tmp(:))); - -acceptpre = 0; -acceptpst = 0; -while acceptpre == 0 || acceptpst == 0, - h = figure; - subplot(2,1,1); plot(time, dat(end, :)); - abc = axis; - axis([time(1) time(end) abc(3:4)]); - subplot(2,1,2); - axis([time(1) time(end) -1.1*mdat 1.1*mdat]); - xpos = -artfctdef.pretim; - ypos = -1.05*mdat; - width = artfctdef.pretim + artfctdef.psttim; - height = 2.1*mdat; - rectangle('Position', [xpos ypos width height], 'FaceColor', 'r'); - hold on; plot(time, dat(1:end-1, :), 'b'); - - if acceptpre == 0, - fprintf(['\ncurrent pre-peak interval = %1.3f'], artfctdef.pretim); - response = input('\nkeep the current value (y/n) ?\n','s'); - switch response - case 'n' - oldpretim = artfctdef.pretim; - artfctdef.pretim = input('\nenter new value \n'); - case 'y' - oldpretim = artfctdef.pretim; - acceptpre = 1; - otherwise - warning('unrecognised response, assuming no'); - oldpretim = artfctdef.pretim; - end - end - if acceptpst == 0 && acceptpre == 1, - fprintf(['\ncurrent post-peak interval = %1.3f'], artfctdef.psttim); - response = input('\nkeep the current value (y/n) ?\n','s'); - switch response - case 'n' - oldpsttim = artfctdef.psttim; - artfctdef.psttim = input('\nenter new value \n'); - case 'y' - oldpsttim = artfctdef.psttim; - acceptpst = 1; - otherwise - warning('unrecognised response, assuming no'); - oldpsttim = artfctdef.psttim; - end - end - close -end - -artifact(:,1) = trl(:,1) - trl(:,3) - round(artfctdef.pretim*hdr.Fs); -artifact(:,2) = trl(:,1) - trl(:,3) + round(artfctdef.psttim*hdr.Fs); - -% remember the details that were used here -cfg.artfctdef.ecg = artfctdef; -cfg.artfctdef.ecg.artifact = artifact; - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: artifact_ecg.m,v 1.25 2009/09/30 12:40:11 jansch Exp $'; diff --git a/external/fieldtrip/private/artifact_eog.m b/external/fieldtrip/private/artifact_eog.m deleted file mode 100644 index fdd0eb5..0000000 --- a/external/fieldtrip/private/artifact_eog.m +++ /dev/null @@ -1,187 +0,0 @@ -function [cfg, artifact] = artifact_eog(cfg,data) - -% ARTIFACT_EOG reads the data segments of interest from file and -% identifies EOG artifacts. -% -% Use as -% [cfg, artifact] = artifact_eog(cfg) -% required configuration options: -% cfg.dataset or both cfg.headerfile and cfg.datafile -% or -% [cfg, artifact] = artifact_eog(cfg, data) -% forbidden configuration options: -% cfg.dataset, cfg.headerfile and cfg.datafile -% -% In both cases the configuration should also contain: -% cfg.trl = structure that defines the data segments of interest. See DEFINETRIAL -% cfg.continuous = 'yes' or 'no' whether the file contains continuous data -% -% The data is preprocessed (again) with the following configuration parameters, -% which are optimal for identifying EOG artifacts: -% cfg.artfctdef.eog.bpfilter = 'yes' -% cfg.artfctdef.eog.bpfilttype = 'but' -% cfg.artfctdef.eog.bpfreq = [1 15] -% cfg.artfctdef.eog.bpfiltord = 4 -% cfg.artfctdef.eog.hilbert = 'yes' -% -% Artifacts are identified by means of thresholding the z-transformed value -% of the preprocessed data. -% cfg.artfctdef.eog.channel = Nx1 cell-array with selection of channels, see CHANNELSELECTION for details -% cfg.artfctdef.eog.cutoff = 4 z-value at which to threshold -% cfg.artfctdef.eog.trlpadding = 0.5 -% cfg.artfctdef.eog.fltpadding = 0.1 -% cfg.artfctdef.eog.artpadding = 0.1 -% -% The output argument "artifact" is a Nx2 matrix comparable to the -% "trl" matrix of DEFINETRIAL. The first column of which specifying the -% beginsamples of an artifact period, the second column contains the -% endsamples of the artifactperiods. -% -% See also ARTIFACT_ZVALUE, REJECTARTIFACT - -% Undocumented local options -% cfg.method - -% Copyright (c) 2003-2006, Jan-Mathijs Schoffelen & Robert Oostenveld -% -% $Log: artifact_eog.m,v $ -% Revision 1.36 2009/03/10 14:25:59 roboos -% fixed bug in copying of cfg.continuous to tmpcfg, also keek data and headerformat -% -% Revision 1.35 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.34 2009/01/14 11:47:07 sashae -% changed handling of cfg.datatype -% added call to checkconfig at start and end of function -% -% Revision 1.33 2008/12/02 16:35:01 estmee -% Checkconfig cfg.datatype = forbidden -% -% Revision 1.32 2008/11/25 13:14:28 estmee -% Documentation update -% -% Revision 1.31 2008/11/18 16:20:28 estmee -% Added cfg.continuous -% -% Revision 1.30 2008/10/13 13:03:11 sashae -% added call to checkconfig (as discussed with estmee) -% -% Revision 1.29 2008/10/10 15:00:10 estmee -% Repaired determining artifacts with cfg as only input argument. -% -% Revision 1.28 2008/10/07 16:11:08 estmee -% Added data as second input argument to artifact_eog itself and to the way it calls artifact_zvalue. -% -% Revision 1.27 2008/10/07 08:58:51 roboos -% committed the changes that Esther made recently, related to the support of data as input argument to the artifact detection functions. I hope that this does not break the functions too seriously. -% -% Revision 1.26 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.25 2006/11/29 09:06:36 roboos -% renamed all cfg options with "sgn" into "channel", added backward compatibility when required -% updated documentation, mainly in the artifact detection routines -% -% Revision 1.24 2006/04/25 17:06:28 ingnie -% updated documentation -% -% Revision 1.23 2006/04/20 09:58:33 roboos -% updated documentation -% -% Revision 1.22 2006/02/27 17:01:07 roboos -% added tmpcfg.dataset, added try-end around copying of headerfile, datafile and dataset -% -% Revision 1.21 2006/01/12 13:51:38 roboos -% completely new implementation, all based upon the same artifact_zvalue code -% all preprocessing is now done consistently and the various paddings have been better defined -% the functions do not have any explicit support any more for non-continuous data -% the old artifact_xxx functions from JM have been renamed to xxx_old -% - -fieldtripdefs - -% check if the input cfg is valid for this function -cfg = checkconfig(cfg, 'trackconfig', 'on'); -cfg = checkconfig(cfg, 'renamed', {'datatype', 'continuous'}); -cfg = checkconfig(cfg, 'renamedval', {'continuous', 'continuous', 'yes'}); - -% set default rejection parameters -if ~isfield(cfg,'artfctdef'), cfg.artfctdef = []; end -if ~isfield(cfg.artfctdef,'eog'), cfg.artfctdef.eog = []; end -if ~isfield(cfg.artfctdef.eog,'method'), cfg.artfctdef.eog.method = 'zvalue'; end - -% for backward compatibility -if isfield(cfg.artfctdef.eog,'sgn') - cfg.artfctdef.eog.channel = cfg.artfctdef.eog.sgn; - cfg.artfctdef.eog = rmfield(cfg.artfctdef.eog, 'sgn'); -end - -if isfield(cfg.artfctdef.eog, 'artifact') - fprintf('eog artifact detection has already been done, retaining artifacts\n'); - artifact = cfg.artfctdef.eog.artifact; - return -end - -if strcmp(cfg.artfctdef.eog.method, 'zvalue') - % the following fields should be supported for backward compatibility - if isfield(cfg.artfctdef.eog,'pssbnd'), - cfg.artfctdef.eog.bpfreq = cfg.artfctdef.eog.pssbnd; - cfg.artfctdef.eog.bpfilter = 'yes'; - cfg.artfctdef.eog = rmfield(cfg.artfctdef.eog,'pssbnd'); - end; - dum = 0; - if isfield(cfg.artfctdef.eog,'pretim'), - dum = max(dum, cfg.artfctdef.eog.pretim); - cfg.artfctdef.eog = rmfield(cfg.artfctdef.eog,'pretim'); - end - if isfield(cfg.artfctdef.eog,'psttim'), - dum = max(dum, cfg.artfctdef.eog.psttim); - cfg.artfctdef.eog = rmfield(cfg.artfctdef.eog,'psttim'); - end - if dum - cfg.artfctdef.eog.artpadding = max(dum); - end - if isfield(cfg.artfctdef.eog,'padding'), - cfg.artfctdef.eog.trlpadding = cfg.artfctdef.eog.padding; - cfg.artfctdef.eog = rmfield(cfg.artfctdef.eog,'padding'); - end - % settings for preprocessing - if ~isfield(cfg.artfctdef.eog,'bpfilter'), cfg.artfctdef.eog.bpfilter = 'yes'; end - if ~isfield(cfg.artfctdef.eog,'bpfilttype'), cfg.artfctdef.eog.bpfilttype = 'but'; end - if ~isfield(cfg.artfctdef.eog,'bpfreq'), cfg.artfctdef.eog.bpfreq = [1 15]; end - if ~isfield(cfg.artfctdef.eog,'bpfiltord'), cfg.artfctdef.eog.bpfiltord = 4; end - if ~isfield(cfg.artfctdef.eog,'hilbert'), cfg.artfctdef.eog.hilbert = 'yes'; end - % settings for the zvalue subfunction - if ~isfield(cfg.artfctdef.eog,'channel'), cfg.artfctdef.eog.channel = 'EOG'; end - if ~isfield(cfg.artfctdef.eog,'trlpadding'), cfg.artfctdef.eog.trlpadding = 0.5; end - if ~isfield(cfg.artfctdef.eog,'artpadding'), cfg.artfctdef.eog.artpadding = 0.1; end - if ~isfield(cfg.artfctdef.eog,'fltpadding'), cfg.artfctdef.eog.fltpadding = 0.1; end - if ~isfield(cfg.artfctdef.eog,'cutoff'), cfg.artfctdef.eog.cutoff = 4; end - % construct a temporary configuration that can be passed onto artifact_zvalue - tmpcfg = []; - tmpcfg.trl = cfg.trl; - tmpcfg.artfctdef.zvalue = cfg.artfctdef.eog; - if isfield(cfg, 'continuous'), tmpcfg.continuous = cfg.continuous; end - if isfield(cfg, 'dataformat'), tmpcfg.dataformat = cfg.dataformat; end - if isfield(cfg, 'headerformat'), tmpcfg.headerformat = cfg.headerformat; end - % call the zvalue artifact detection function - if nargin ==1 - cfg = checkconfig(cfg, 'dataset2files', {'yes'}); - cfg = checkconfig(cfg, 'required', {'headerfile', 'datafile'}); - tmpcfg.datafile = cfg.datafile; - tmpcfg.headerfile = cfg.headerfile; - [tmpcfg, artifact] = artifact_zvalue(tmpcfg); - elseif nargin ==2 - cfg = checkconfig(cfg, 'forbidden', {'dataset', 'headerfile', 'datafile'}); - [tmpcfg, artifact] = artifact_zvalue(tmpcfg, data); - end - cfg.artfctdef.eog = tmpcfg.artfctdef.zvalue; -else - error(sprintf('EOG artifact detection only works with cfg.method=''zvalue''')); -end - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); diff --git a/external/fieldtrip/private/artifact_eog_old.m b/external/fieldtrip/private/artifact_eog_old.m deleted file mode 100644 index d056192..0000000 --- a/external/fieldtrip/private/artifact_eog_old.m +++ /dev/null @@ -1,208 +0,0 @@ -function [cfg, artifact] = artifact_eog_old(cfg); - -% ARTIFACT_EOG_OLD is deprecated, please use ARTIFACT_EOG instead - -% Undocumented local options: -% cfg.artfctdef -% cfg.datafile -% cfg.datatype -% cfg.headerfile -% cfg.trl -% cfg.version - -% Copyright (C) 2004, F.C. Donders Centre -% -% $Log: artifact_eog_old.m,v $ -% Revision 1.5 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.4 2008/05/13 15:37:24 roboos -% switched to using read_data/header instead of the read_fcdc_data/header wrapper functions -% -% Revision 1.3 2006/04/20 09:56:07 roboos -% removed the (outdated and unclear) documentation, now it only -% contains a comment that the function is deprecated and has been -% replaced by a new one -% - -fieldtripdefs - -% set default rejection parameters for eog artifacts if necessary. -if ~isfield(cfg,'artfctdef'), cfg.artfctdef = [] ; end; -if ~isfield(cfg.artfctdef,'eog'), cfg.artfctdef.eog = []; end; -if ~isfield(cfg.artfctdef.eog,'sgn'), cfg.artfctdef.eog.sgn = {'EOG'}; end; -if ~isfield(cfg.artfctdef.eog,'method'), cfg.artfctdef.eog.method = 'zvalue'; end; - -% for backward-compatibility -if isfield(cfg.artfctdef.eog,'pssbnd'), - cfg.artfctdef.eog.bpfreq = cfg.artfctdef.eog.pssbnd; - cfg.artfctdef.eog = rmfield(cfg.artfctdef.eog,'pssbnd'); -end; - -% method independent settings -if ~isfield(cfg.artfctdef.eog,'pretim'), cfg.artfctdef.eog.pretim = 0.1; end; -if ~isfield(cfg.artfctdef.eog,'psttim'), cfg.artfctdef.eog.psttim = 0.1; end; -if ~isfield(cfg.artfctdef.eog,'padding'),cfg.artfctdef.eog.padding = 0.5; end; -if ~isfield(cfg.artfctdef.eog,'feedback'),cfg.artfctdef.eog.feedback = 'no'; end; - -% method dependent settings -if strcmp(cfg.artfctdef.eog.method,'zvalue'), - if ~isfield(cfg.artfctdef.eog,'cutoff'), cfg.artfctdef.eog.cutoff = 4; end; - if ~isfield(cfg.artfctdef.eog,'bpfilter'), cfg.artfctdef.eog.bpfilter = 'yes'; end; - if ~isfield(cfg.artfctdef.eog,'bpfreq'), cfg.artfctdef.eog.bpfreq = [1 15]; end; - if ~isfield(cfg.artfctdef.eog,'bpfiltord'),cfg.artfctdef.eog.bpfiltord= 4; end; - if ~isfield(cfg.artfctdef.eog,'bpfilttype'),cfg.artfctdef.eog.bpfilttype= 'but'; end; - if ~isfield(cfg.artfctdef.eog,'hilbert'), cfg.artfctdef.eog.hilbert = 'yes'; end; -elseif strcmp(cfg.artfctdef.eog.method,'percnt'), - if ~isfield(cfg.artfctdef.eog,'cutoff'), cfg.artfctdef.eog.cutoff = 0.995; end; - if ~isfield(cfg.artfctdef.eog,'bpfilter'), cfg.artfctdef.eog.bpfilter = 'yes'; end; - if ~isfield(cfg.artfctdef.eog,'bpfreq'), cfg.artfctdef.eog.bpfreq = [1 15]; end; - if ~isfield(cfg.artfctdef.eog,'bpfiltord'),cfg.artfctdef.eog.bpfiltord= 4; end; - if ~isfield(cfg.artfctdef.eog,'bpfilttype'),cfg.artfctdef.eog.bpfilttype= 'but'; end; - if ~isfield(cfg.artfctdef.eog,'hilbert'), cfg.artfctdef.eog.hilbert = 'yes'; end; -elseif strcmp(cfg.artfctdef.eog.method,'abs'), - if ~isfield(cfg.artfctdef.eog,'cutoff'), cfg.artfctdef.eog.cutoff = 50e-6; end; - if ~isfield(cfg.artfctdef.eog,'hpfilter'), cfg.artfctdef.eog.bpfilter = 'yes'; end; - if ~isfield(cfg.artfctdef.eog,'hpfreq'), cfg.artfctdef.eog.bpfreq = 1; end; - if ~isfield(cfg.artfctdef.eog,'bpfiltord'),cfg.artfctdef.eog.bpfiltord= 4; end; - if ~isfield(cfg.artfctdef.eog,'bpfilttype'),cfg.artfctdef.eog.bpfilttype= 'but'; end; - if ~isfield(cfg.artfctdef.eog,'hilbert'), cfg.artfctdef.eog.hilbert = 'yes'; end; -end - -if ~isfield(cfg, 'datatype') || ~strcmp(cfg.datatype, 'continuous') - % datatype is unknown or not continuous, perform epoch boundary check - iscontinuous = 0; -else - % do not perform epoch boundary check, usefull for pseudo-continuous data - iscontinuous = strcmp(cfg.datatype, 'continuous'); -end - -artfctdef = cfg.artfctdef.eog; -cfg = dataset2files(cfg); -hdr = read_header(cfg.headerfile); -padsmp = round(artfctdef.padding*hdr.Fs); -trl = cfg.trl; -trl(:,1) = trl(:,1) - padsmp; % pad the trial with padsmp-samples, in order to detect -trl(:,2) = trl(:,2) + padsmp; % artifacts at the edges of the relevant trials. -numtrl = size(trl,1); -trllength = trl(:,2) - trl(:,1) + 1; -artfctdef.trl= trl; -artfctdef.sgn= channelselection(artfctdef.sgn,hdr.label); -sgnind = match_str(hdr.label, artfctdef.sgn); -numeogsgn = length(sgnind); - -if numeogsgn<1 - error('no EOG channels selected'); -end - -if ~isfield(artfctdef, 'fltpadding') - if iscontinuous - if ~isfield(artfctdef, 'bpfilttype') || ~isfield(artfctdef, 'hpfilttype'), - fltpadding = 0; - elseif strcmp(artfctdef.bpfilttype, 'but') || strcmp(artfctdef.hpfilttype, 'but'), - fltpadding = 20*artfctdef.bpfiltord; - elseif strcmp(artfctdef.bpfilttype, 'fir') || strcmp(artfctdef.hpfilttype, 'fir'), - fltpadding = artfctdef.bpfiltord; - else - warning('unknown filter type, cannot determine filter padding'); - fltpadding = 0; - end - else - warning('default is not to apply filter padding on trial based data'); - fltpadding = 0; - end -else - fltpadding = round(artfctdef.fltpadding*hdr.Fs); -end - -% initialize some variables -fltdatavg = zeros(numeogsgn,1); -fltdatvar = zeros(numeogsgn,1); -fltdatstd = zeros(numeogsgn,1); -cumpernumsmp = 0; -cutfltdatstr = cell(numtrl,1); -artfctchn = zeros(numtrl,1); -rejectall = zeros(1,trl(end,2)); -z_tdata = zeros(1,trl(end,2)); - -for trllop = 1:numtrl - fprintf('scanning for eog artifacts in trial %d from %d\n', trllop, numtrl); - dat = read_data(cfg.datafile, hdr, trl(trllop,1)-fltpadding, ... - trl(trllop,2)+fltpadding, sgnind, iscontinuous);%read data - fltdat = preproc(dat, artfctdef.sgn, hdr.Fs, artfctdef, [], fltpadding, fltpadding); - cutfltdatstr{trllop} = fltdat; - fltdatavg = fltdatavg + mean(fltdat,2) .* trllength(trllop); - fltdatvar = fltdatvar + (std(fltdat,[],2)).^2 .* trllength(trllop); - cumpernumsmp = cumpernumsmp + trllength(trllop); -end - -fltdatavg = fltdatavg ./ cumpernumsmp; -fltdatstd = sqrt(fltdatvar ./ cumpernumsmp); - -for trllop = 1:numtrl - if strcmp(artfctdef.method,'zvalue'), - dummy = ((cutfltdatstr{trllop} - repmat(fltdatavg,1,trllength(trllop))) ./ ... - repmat(fltdatstd,1,trllength(trllop))); - [dummy, index] = sort(dummy,1); - [dum indx] = max(dummy(end,:)); - artfctchn(trllop)=index(end,indx); - z_tdata(1,trl(trllop,1):trl(trllop,2)) = sum(dummy,1)./sqrt(size(dummy,1)); - elseif strcmp(artfctdef.method,'abs'), - dummy = cutfltdatstr{trllop}; - [dummy,index] = sort(dummy); - [dum indx] = max(dummy(end,:)); - artfctchn(trllop)=index(end,indx); - z_tdata(1,trl(trllop,1):trl(trllop,2)) = sum(dummy,1)./sqrt(size(dummy,1)); - end; -end; - -if strcmp(artfctdef.method,'percnt'), - dummy = zeros(numeogsgn,trl(end,2)); - for trllop = 1:numtrl - dummy(:,trl(trllop,1):trl(trllop,2)) = cutfltdatstr{trllop}; - clear cutfltdatstr{trllop}; - end; - - for sgnlop = 1:numeogsgn - [sd,id] = sort(dummy(sgnlop,:),2); - sel = find(sd); - dummy(sgnlop,id(sel)) = [1:length(sel)]./length(sel); - end - [dummy, index] = sort(dummy,1); - - for trllop = 1:numtrl - dum = dummy(:,trl(trllop,1):trl(trllop,2)); - [dum,index] = sort(dum,1); - artfctchn(trllop)=index(end,find(dum(end,:)==max(dum(end,:)))); - z_tdata(1,trl(trllop,1):trl(trllop,2)) = dum(end,:); - end -end - -clear cutfltdatstr; - -% update the configuration prior to calling artifact_feedback -cfg.artfctdef.eog = artfctdef; - -if (strcmp(cfg.artfctdef.eog.feedback,'yes')) - [artfctdef,artifact] = artifact_feedback_old(cfg, z_tdata, artfctchn,'EOGraw'); -elseif (strcmp(cfg.artfctdef.eog.feedback,'flt')) - [artfctdef,artifact] = artifact_feedback_old(cfg, z_tdata, artfctchn,'EOGflt'); -else - [artfctdef,artifact] = artifact_feedback_old(cfg, z_tdata, artfctchn,'EOG'); -end; - -% remember the details that were used here -cfg.artfctdef.eog = artfctdef; -cfg.artfctdef.eog.artifact = artifact; - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: artifact_eog_old.m,v 1.5 2008/09/22 20:17:43 roboos Exp $'; - diff --git a/external/fieldtrip/private/artifact_feedback_old.m b/external/fieldtrip/private/artifact_feedback_old.m deleted file mode 100644 index e5eefe8..0000000 --- a/external/fieldtrip/private/artifact_feedback_old.m +++ /dev/null @@ -1,272 +0,0 @@ -function [artfctdef, artifact] = artifact_feedback(cfg,z_tdata,artfctchn,flag); - -% ARTIFACT_FEEDBACK provides feedback about the artifacts in the data. -% -% [artfctdef, artifact] = artifact_feedback(cfg,artfctdef,artifact,z_tdata,artfctchn); -% If cfg.artfctdef.xxx.feedback was set to 'yes', the function updates the artifact-definition -% parameters and outputs artifact. artifact is a binary vector as a function of time (in samples). -% Its value is 1 if in one of the channels to be analysed an xxx artifact -% is present. artifact is computed by thresholding the vector z_tdata, and -% convolving this result with an appropriate artifact-kernel. -% The rejection threshold can be set interactively, while given feedback about the to -% be rejected epochs. This can be done, until the threshold is set in a satisfactory way. - -% Copyright (c) 2003, F.C. Donders Centre -% -% $Log: artifact_feedback_old.m,v $ -% Revision 1.1 2006/01/12 14:21:26 roboos -% renamed JMs artifact_feedback and artifact_viewer into xxx_old -% they are only provided for people who insist on running the old code -% -% Revision 1.14 2005/08/01 12:40:22 roboos -% added units (samples/uV) to the axes in the feedback plots -% -% Revision 1.13 2005/05/17 17:50:49 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.12 2005/04/22 08:00:14 jansch -% fixed bug that caused routine to crash in the case of no artifacts -% -% Revision 1.11 2005/04/19 16:50:36 roboos -% do not try to prevent artifact leakage if there are no artifacts -% -% Revision 1.10 2005/04/19 12:33:51 jansch -% fixed minor bug -% -% Revision 1.9 2005/04/08 12:07:09 roboos -% added an empty line between the help and the log messages -% -% Revision 1.8 2005/04/08 11:54:30 jansch -% notwithstanding pieter's excellent feedback, Robert did not manage to fix -% the bug sufficiently. now it should work -% -% Revision 1.7 2005/04/08 11:47:23 jansch -% fixed small bug. -% -% Revision 1.6 2005/04/08 11:33:13 roboos -% prolonged the rejectall vector, so that it can hold all trials after artifact padding (thanks to Pieter Medendorp) -% -% Revision 1.5 2005/04/08 08:23:47 roboos -% replaced convolve_suprathreshold subfunction with two separate functions, one that does the padding (not using a convolution) and that merges the artifacts, the other one preventing the artifacts from leaking into other trials for non-continuous data -% -% Revision 1.4 2005/04/08 07:10:09 roboos -% added a check to prevent a crash due to a bug (negative artifact length), the bug is still present -% -% Revision 1.3 2005/04/06 13:08:00 roboos -% implemented check for non-continuous data to ensure that artifacts do not leak over trial boundaries -% -% Revision 1.2 2005/02/08 08:36:55 jansch -% fixed bug in handling of non-padded data -% -% Revision 1.1 2005/02/07 15:10:50 roboos -% moved two subfunctions for artifact detection from main to private directory -% -% Revision 1.4 2004/09/01 09:39:28 jansch -% *** empty log message *** -% -% Revision 1.3 2004/09/01 09:27:25 jansch -% fixed some small bugs, and inconsistencies. replaced convolution with fft-convolution in the merging of artifacts, closely related in time. added GUI in artifact_viewer -% - -if strcmp(flag,'muscle'), artfctdef = cfg.artfctdef.muscle; -elseif strcmp(flag,'jump'), artfctdef = cfg.artfctdef.jump; -elseif strcmp(flag,'EOGraw') || strcmp(flag,'EOGflt') || strcmp(flag,'EOG') ,artfctdef = cfg.artfctdef.eog; -end; - -hdr = read_fcdc_header(cfg.headerfile); -% artifact = convolve_suprathreshold(cfg,artfctdef,z_tdata,hdr.Fs); -artifact = artifact_padding(cfg,artfctdef,z_tdata,hdr.Fs); -artifact = prevent_trial_leakage(cfg,artfctdef,artifact,hdr.Fs); - - -%rejectall = zeros(1,max(numtrlsmp, numartsmp)); % make a vector with enough samples to hold the trials and artifacts -rejectall = zeros(1,length(z_tdata)); -if ~isempty(artifact), - % update the rejectall vector - numtrlsmp = max(cfg.trl(:,2)); % count the number of samples in the trial definition - numartsmp = max(artifact(:,2)); % count the number of samples in the trial definition, could be longer since the artifact can be padded - for i=1:size(artifact,1) - rejectall(artifact(i,1):artifact(i,2)) = 1; - end -end - -if strcmp(artfctdef.feedback,'yes') || strcmp(artfctdef.feedback,'flt') - - trl = cfg.trl; - numtrl = size(trl,1); - accept = 0; - - while accept == 0 , - h = figure; - plot(z_tdata); - hold on; - plot([1 length(z_tdata)],[artfctdef.cutoff artfctdef.cutoff],'r:'); - hold off; - xlabel('samples'); - ylabel('zscore'); - - response = input('\nwould you like to page through the data (y/n) ?\n','s'); - switch response - case 'y' - close(h); - artifact_viewer_old(cfg,artfctdef,rejectall,z_tdata,artfctchn,flag); - end; - - fprintf(strcat('\ncurrent ',artfctdef.method,' threshold = %1.3f'),artfctdef.cutoff); - response = input('\nkeep the current value (y/n) ?\n','s'); - switch response - case 'n' - oldcutoff = artfctdef.cutoff; - artfctdef.cutoff = input('\nenter new value \n'); - case 'y' - oldcutoff = artfctdef.cutoff; - accept = 1; - otherwise - warning('unrecognised response, assuming no'); - oldcutoff = artfctdef.cutoff; - artfctdef.cutoff = input('\nenter new value \n'); - end; - if oldcutoff ~= artfctdef.cutoff, - % artifact = convolve_suprathreshold(cfg,artfctdef,z_tdata,hdr.Fs); - artifact = artifact_padding(cfg,artfctdef,z_tdata,hdr.Fs); - artifact = prevent_trial_leakage(cfg,artfctdef,artifact,hdr.Fs); - % update the rejectall vector - rejectall(:) = 0; - for i=1:size(artifact,1) - rejectall(artifact(i,1):artifact(i,2)) = 1; - end - end - close; - end; -end; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [artifact] = artifact_padding(cfg,artfctdef,z_tdata,Fs); -fprintf('\nidentifying artifact-epochs\n'); -datind = z_tdata>artfctdef.cutoff; -begsmp = (find(diff([0 datind])==1))'; -endsmp = (find(diff([datind 0])==-1))'; -% add the padding to the begin and end of each artifact -begsmp = begsmp - round(artfctdef.pretim .* Fs); -endsmp = endsmp + round(artfctdef.psttim .* Fs); -begsmp(begsmp<1) = 1; % prevent artifacts to start before time zero -% merge the artifacts that are overlapping each other -remove = zeros(size(begsmp)); -for i=2:length(begsmp) - if begsmp(i)<=endsmp(i-1) - begsmp(i)= begsmp(i-1); % include the previous artifact into this one - remove(i-1) = 1; % mark the previous one so that it will be removed - end -end -begsmp = begsmp(~remove); % remove the artifacts that have been swallowed up -endsmp = endsmp(~remove); % remove the artifacts that have been swallowed up -% assign the output artifact structure -if ~isempty(begsmp) && ~isempty(endsmp), - artifact = [begsmp(:) endsmp(:)]; -else - artifact = []; -end; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [artifact] = prevent_trial_leakage(cfg,artfctdef,artifact,Fs); -if ~strcmp(cfg.datatype, 'continuous') - if isempty(artifact) - fprintf('no artifacts are found, therefore no leakage will occur\n'); - return - end - fprintf('preventing artifacts from leaking into other trials\n'); - trl = cfg.trl; - dum = artifact; - % remove the padding at the begin and end of each artifact - dum(:,1) = dum(:,1) + round(artfctdef.pretim*Fs); - dum(:,2) = dum(:,2) - round(artfctdef.psttim*Fs); - for i=1:size(dum,1); - containcomplete = trl(:,1)<=dum(i,1) & trl(:,2)>=dum(i,2); - % containpartial = trl(:,1)<=dum(i,2) & trl(:,2)>=dum(i,1); - % containpartial = containpartial & ~containcomplete; - sel = find(containcomplete); - if length(sel)==1 - artifact(i,1) = max(trl(sel,1), artifact(i,1)); - artifact(i,2) = min(trl(sel,2), artifact(i,2)); - elseif length(sel)>1 - error('artifact is completely contained within two trials, error in trial definition'); - end - end -end - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [artifact, datind] = convolve_suprathreshold(cfg,artfctdef,z_tdata,Fs); - -fprintf('\nidentifying artifact-epochs\n'); - -trl = cfg.trl; -presmp = max([round(artfctdef.pretim .* Fs) 1]); -pstsmp = round(artfctdef.psttim .* Fs); -maxsmp = max([presmp,pstsmp]); -kernel = [zeros(1,maxsmp - presmp) ones(1,presmp) ... - ones(1,pstsmp) zeros(1,maxsmp - pstsmp)]; -krnsmp = length(kernel); -datsmp = size(z_tdata,2); -datind = zeros(size(z_tdata)); -datind = sum(z_tdata>artfctdef.cutoff,1); -%datind = (conv(datind,kernel))>0; - -begsmp = (find(diff([0 datind])==1))'; -endsmp = (find(diff([datind 0])==-1))'; - -% add the padding to the begin and end of each artifact -begsmp = begsmp - presmp; -endsmp = endsmp - pstsmp; -begsmp(begsmp<1) = 1; % prevent artifacts before time zero - -% merge overlapping artifacts together -remove = zeros(size(begsmp)); -for i=2:length(begsmp) - if begsmp(i)<=endsmp(i-1) - begsmp(i)= begsmp(i-1); % merge with the previous one - remove(i-1) = 1; % mark the previous one so that it will be removed - end -end -begsmp = begsmp(~remove); % remove the artifacts that have been swallowed up -endsmp = endsmp(~remove); % remove the artifacts that have been swallowed up - -% assign the output artifact structure -if ~isempty(begsmp) && ~isempty(endsmp), - artifact(:,1) = begsmp; - artifact(:,2) = endsmp; -else - artifact = []; -end; - -if ~strcmp(cfg.datatype, 'continuous') - fprintf('preventing artifacts from leaking into other trials\n'); - dum = artifact; - dum(:,1) = dum(:,1) + round(artfctdef.pretim*Fs); - dum(:,2) = dum(:,2) - round(artfctdef.psttim*Fs); - % somehow the convolution does not do what I would expect - % the pretim and psttim are not added correctly around the artifact - sel = dum(:,1)>dum(:,2); % find artifacts with negative length - dum(sel,2) = dum(sel,1); % set the length to zero - for i=1:size(dum,1); - containcomplete = trl(:,1)<=dum(i,1) & trl(:,2)>=dum(i,2); - % containpartial = trl(:,1)<=dum(i,2) & trl(:,2)>=dum(i,1); - % containpartial = containpartial & ~containcomplete; - sel = find(containcomplete); - if length(sel)==1 - artifact(i,1) = max(trl(sel,1), artifact(i,1)); - artifact(i,2) = min(trl(sel,2), artifact(i,2)); - elseif length(sel)>1 - error('this is weird, contact Robert'); - end - end -end - diff --git a/external/fieldtrip/private/artifact_file.m b/external/fieldtrip/private/artifact_file.m deleted file mode 100644 index 8beecf2..0000000 --- a/external/fieldtrip/private/artifact_file.m +++ /dev/null @@ -1,114 +0,0 @@ -function [cfg, artifact] = artifact_file(cfg); - -% ARTIFACT_FILE reads rejection marks from a file -% -% Use as -% [cfg, artifact] = arifact_file(cfg) -% required configuration options: -% cfg.dataset or cfg.headerfile -% -% See also REJECTARTIFACT - -% Copyright (C) 2003-2006, Robert Oostenveld -% -% $Log: artifact_file.m,v $ -% Revision 1.17 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.16 2009/01/16 17:21:20 sashae -% added config tracking -% -% Revision 1.15 2008/11/25 13:15:42 estmee -% Documentation update -% -% Revision 1.14 2008/10/13 10:40:47 sashae -% added call to checkconfig -% -% Revision 1.13 2008/10/07 08:58:51 roboos -% committed the changes that Esther made recently, related to the support of data as input argument to the artifact detection functions. I hope that this does not break the functions too seriously. -% -% Revision 1.12 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.11 2008/05/13 15:37:24 roboos -% switched to using read_data/header instead of the read_fcdc_data/header wrapper functions -% -% Revision 1.10 2006/05/03 08:12:51 ingnie -% updated documentation -% -% Revision 1.9 2006/04/20 09:58:33 roboos -% updated documentation -% -% Revision 1.8 2006/01/31 13:49:29 jansch -% included dataset2files to ensure the presence of cfg.headerfile or cfg.datafile -% whenever needed -% -% Revision 1.7 2005/12/20 08:36:47 roboos -% add the artifact Nx2 matrix to the output configuration -% changed some indentation and white space, renamed a few variables -% -% Revision 1.6 2005/06/29 12:42:00 roboos -% added version to the output configuration -% -% Revision 1.5 2005/05/17 17:50:36 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.4 2004/09/01 17:59:28 roboos -% added copyright statements to all filed -% added cfg.version to all functions that give configuration in their output -% added cfg.previous to all functions with input data containing configuration details -% -% Revision 1.3 2004/08/26 16:01:34 roboos -% added support for brainvision_marker -% -% Revision 1.2 2003/12/11 09:35:27 roberto -% fixed bug in "if isfield()" -% -% Revision 1.1 2003/12/08 12:34:27 roberto -% initial version, according to pluggable artifact rejection -% - -fieldtripdefs -cfg = checkconfig(cfg, 'trackconfig', 'on'); - -if isfield(cfg, 'rejectfile') && ~strcmp(cfg.rejectfile, 'no') - cfg = checkconfig(cfg, 'dataset2files', {'yes'}); - cfg = checkconfig(cfg, 'required', {'headerfile'}); - hdr = read_header(cfg.headerfile); - if filetype(cfg.rejectfile, 'eep_rej') - artifact = read_eep_rej(cfg.rejectfile); - elseif filetype(cfg.rejectfile, 'brainvision_marker') - artifact = read_brainvision_marker(cfg.rejectfile); - else - error(sprintf('unrecognized filetype for rejection file ''%s''', cfg.rejectfile)); - end - % convert rejection marks from miliseconds into seconds - artifact = artifact/1000; - % convert rejection marks into samples - artifact = round(artifact * hdr.Fs); - fprintf('%d rejection marks read\n', size(artifact,1)); -else - artifact = []; - fprintf('no rejection marks read\n'); -end - -% remember the details that were used here -cfg.artfctdef.file.trl = cfg.trl; -cfg.artfctdef.file.artifact = artifact; - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: artifact_file.m,v 1.17 2009/01/20 13:01:31 sashae Exp $'; diff --git a/external/fieldtrip/private/artifact_jump.m b/external/fieldtrip/private/artifact_jump.m deleted file mode 100644 index 520df2d..0000000 --- a/external/fieldtrip/private/artifact_jump.m +++ /dev/null @@ -1,191 +0,0 @@ -function [cfg, artifact] = artifact_jump(cfg,data) - -% ARTIFACT_JUMP reads the data segments of interest from file and identifies -% SQUID jump artifacts. -% -% Use as -% [cfg, artifact] = artifact_jump(cfg) -% required configuration options: -% cfg.dataset or both cfg.headerfile and cfg.datafile -% or -% [cfg, artifact] = artifact_jump(cfg, data) -% forbidden configuration options: -% cfg.dataset, cfg.headerfile and cfg.datafile -% -% In both cases the configuration should also contain: -% cfg.trl = structure that defines the data segments of interest. See DEFINETRIAL -% cfg.continuous = 'yes' or 'no' whether the file contains continuous data -% -% The data is preprocessed (again) with the following configuration parameters, -% which are optimal for identifying jump artifacts: -% cfg.artfctdef.jump.medianfilter = 'yes' -% cfg.artfctdef.jump.medianfiltord = 9 -% cfg.artfctdef.jump.absdiff = 'yes' -% -% Artifacts are identified by means of thresholding the z-transformed value -% of the preprocessed data. -% cfg.artfctdef.jump.channel = Nx1 cell-array with selection of channels, see CHANNELSELECTION for details -% cfg.artfctdef.jump.cutoff = 20 z-value at which to threshold -% cfg.artfctdef.jump.trlpadding = automatically determined based on the filter padding (cfg.padding) -% cfg.artfctdef.jump.artpadding = automatically determined based on the filter padding (cfg.padding) -% -% The output argument "artifact" is a Nx2 matrix comparable to the -% "trl" matrix of DEFINETRIAL. The first column of which specifying the -% beginsamples of an artifact period, the second column contains the -% endsamples of the artifactperiods. -% -% See also ARTIFACT_ZVALUE, REJECTARTIFACT - -% Undocumented local options: -% cfg.method - -% Copyright (c) 2003-2006, Jan-Mathijs Schoffelen & Robert Oostenveld -% -% $Log: artifact_jump.m,v $ -% Revision 1.27 2009/10/12 14:26:47 jansch -% added default for not taking cumulated z-value across channels for artifact -% identification -% -% Revision 1.26 2009/03/10 14:25:59 roboos -% fixed bug in copying of cfg.continuous to tmpcfg, also keek data and headerformat -% -% Revision 1.25 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.24 2009/01/14 11:47:07 sashae -% changed handling of cfg.datatype -% added call to checkconfig at start and end of function -% -% Revision 1.23 2008/12/02 16:35:32 estmee -% Checkconfig cfg.datatype= forbidden -% -% Revision 1.22 2008/11/25 13:16:24 estmee -% Documentation update -% -% Revision 1.21 2008/11/18 16:20:58 estmee -% Added cfg.continuous -% -% Revision 1.20 2008/10/13 13:03:11 sashae -% added call to checkconfig (as discussed with estmee) -% -% Revision 1.19 2008/10/10 15:01:13 estmee -% Repaired determining artifacts with only cfg as input argument. -% -% Revision 1.18 2008/10/07 16:13:44 estmee -% Added data as second intput argument to artifact_jump itself and the way it calls artifact_zvalue. -% -% Revision 1.17 2008/10/07 08:58:51 roboos -% committed the changes that Esther made recently, related to the support of data as input argument to the artifact detection functions. I hope that this does not break the functions too seriously. -% -% Revision 1.16 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.15 2006/11/29 09:06:36 roboos -% renamed all cfg options with "sgn" into "channel", added backward compatibility when required -% updated documentation, mainly in the artifact detection routines -% -% Revision 1.14 2006/04/25 17:06:28 ingnie -% updated documentation -% -% Revision 1.13 2006/04/20 09:58:33 roboos -% updated documentation -% -% Revision 1.12 2006/02/27 17:01:07 roboos -% added tmpcfg.dataset, added try-end around copying of headerfile, datafile and dataset -% -% Revision 1.11 2006/01/17 14:05:27 roboos -% do preproc absdiff instead of rectify in combination with derivative, absdiff ensures the right order -% -% Revision 1.10 2006/01/12 13:51:38 roboos -% completely new implementation, all based upon the same artifact_zvalue code -% all preprocessing is now done consistently and the various paddings have been better defined -% the functions do not have any explicit support any more for non-continuous data -% the old artifact_xxx functions from JM have been renamed to xxx_old -% - -fieldtripdefs - -% check if the input cfg is valid for this function -cfg = checkconfig(cfg, 'trackconfig', 'on'); -cfg = checkconfig(cfg, 'renamed', {'datatype', 'continuous'}); -cfg = checkconfig(cfg, 'renamedval', {'continuous', 'continuous', 'yes'}); - -% set default rejection parameters -if ~isfield(cfg,'artfctdef'), cfg.artfctdef = []; end -if ~isfield(cfg.artfctdef,'jump'), cfg.artfctdef.jump = []; end -if ~isfield(cfg.artfctdef.jump,'method'), cfg.artfctdef.jump.method = 'zvalue'; end - -% for backward compatibility -if isfield(cfg.artfctdef.jump,'sgn') - cfg.artfctdef.jump.channel = cfg.artfctdef.jump.sgn; - cfg.artfctdef.jump = rmfield(cfg.artfctdef.jump, 'sgn'); -end - -if isfield(cfg.artfctdef.jump, 'artifact') - fprintf('jump artifact detection has already been done, retaining artifacts\n'); - artifact = cfg.artfctdef.jump.artifact; - return -end - -if strcmp(cfg.artfctdef.jump.method, 'zvalue') - % the following fields should be supported for backward compatibility - dum = 0; - if isfield(cfg.artfctdef.jump,'pretim'), - dum = max(dum, cfg.artfctdef.jump.pretim); - cfg.artfctdef.jump = rmfield(cfg.artfctdef.jump,'pretim'); - end - if isfield(cfg.artfctdef.jump,'psttim'), - dum = max(dum, cfg.artfctdef.jump.psttim); - cfg.artfctdef.jump = rmfield(cfg.artfctdef.jump,'psttim'); - end - if dum - cfg.artfctdef.jump.artpadding = max(dum); - end - if isfield(cfg.artfctdef.jump,'padding'), - cfg.artfctdef.jump.trlpadding = cfg.artfctdef.jump.padding; - cfg.artfctdef.jump = rmfield(cfg.artfctdef.jump,'padding'); - end - % settings for preprocessing - if ~isfield(cfg.artfctdef.jump,'medianfilter'), cfg.artfctdef.jump.medianfilter = 'yes'; end - if ~isfield(cfg.artfctdef.jump,'medianfiltord'), cfg.artfctdef.jump.medianfiltord = 9; end - if ~isfield(cfg.artfctdef.jump,'absdiff'), cfg.artfctdef.jump.absdiff = 'yes'; end % compute abs(diff(data)), whereas the order of rectify=yes in combination with derivative=yes would be diff(abs(data)) due to the ordering in preproc - % settings for the zvalue subfunction - if ~isfield(cfg.artfctdef.jump,'cutoff'), cfg.artfctdef.jump.cutoff = 20; end - if ~isfield(cfg.artfctdef.jump,'channel'), cfg.artfctdef.jump.channel = 'MEG'; end - if ~isfield(cfg.artfctdef.jump,'cumulative'), cfg.artfctdef.jump.cumulative = 'no'; end - if isfield(cfg, 'padding') && cfg.padding~=0 - if ~isfield(cfg.artfctdef.jump,'trlpadding'), cfg.artfctdef.jump.trlpadding = 0.5*cfg.padding; end - if ~isfield(cfg.artfctdef.jump,'artpadding'), cfg.artfctdef.jump.artpadding = 0.5*cfg.padding; end - if ~isfield(cfg.artfctdef.jump,'fltpadding'), cfg.artfctdef.jump.fltpadding = 0; end - else - if ~isfield(cfg.artfctdef.jump,'trlpadding'), cfg.artfctdef.jump.trlpadding = 0; end - if ~isfield(cfg.artfctdef.jump,'artpadding'), cfg.artfctdef.jump.artpadding = 0; end - if ~isfield(cfg.artfctdef.jump,'fltpadding'), cfg.artfctdef.jump.fltpadding = 0; end - end - % construct a temporary configuration that can be passed onto artifact_zvalue - tmpcfg = []; - tmpcfg.trl = cfg.trl; - tmpcfg.artfctdef.zvalue = cfg.artfctdef.jump; - if isfield(cfg, 'continuous'), tmpcfg.continuous = cfg.continuous; end - if isfield(cfg, 'dataformat'), tmpcfg.dataformat = cfg.dataformat; end - if isfield(cfg, 'headerformat'), tmpcfg.headerformat = cfg.headerformat; end - % call the zvalue artifact detection function - if nargin ==1 - cfg = checkconfig(cfg, 'dataset2files', {'yes'}); - cfg = checkconfig(cfg, 'required', {'headerfile', 'datafile'}); - tmpcfg.datafile = cfg.datafile; - tmpcfg.headerfile = cfg.headerfile; - [tmpcfg, artifact] = artifact_zvalue(tmpcfg); - elseif nargin ==2 - cfg = checkconfig(cfg, 'forbidden', {'dataset', 'headerfile', 'datafile'}); - [tmpcfg, artifact] = artifact_zvalue(tmpcfg, data); - end - cfg.artfctdef.jump = tmpcfg.artfctdef.zvalue; -else - error(sprintf('jump artifact detection only works with cfg.method=''zvalue''')); -end - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); diff --git a/external/fieldtrip/private/artifact_jump_old.m b/external/fieldtrip/private/artifact_jump_old.m deleted file mode 100644 index 5a1b3f6..0000000 --- a/external/fieldtrip/private/artifact_jump_old.m +++ /dev/null @@ -1,167 +0,0 @@ -function [cfg, artifact] = artifact_jump_old(cfg); - -% ARTIFACT_JUMP_OLD is deprecated, please use ARTIFACT_JUMP instead - -% Undocumented local options: -% cfg.artfctdef -% cfg.datafile -% cfg.datatype -% cfg.headerfile -% cfg.padding -% cfg.trl -% cfg.version - -% Copyright (C) 2004, F.C. Donders Centre -% -% $Log: artifact_jump_old.m,v $ -% Revision 1.5 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.4 2008/05/13 15:37:24 roboos -% switched to using read_data/header instead of the read_fcdc_data/header wrapper functions -% -% Revision 1.3 2006/04/20 09:56:07 roboos -% removed the (outdated and unclear) documentation, now it only -% contains a comment that the function is deprecated and has been -% replaced by a new one -% - -fieldtripdefs - -% set default rejection parameters for jump artifacts if necessary. -if ~isfield(cfg,'artfctdef'), cfg.artfctdef = []; end; -if ~isfield(cfg.artfctdef,'jump'), cfg.artfctdef.jump = []; end; -if ~isfield(cfg.artfctdef.jump,'sgn'), cfg.artfctdef.jump.sgn = 'MEG'; end; -if ~isfield(cfg.artfctdef.jump,'method'), cfg.artfctdef.jump.method = 'zvalue'; end; -if ~isfield(cfg.artfctdef.jump,'feedback'), cfg.artfctdef.jump.feedback = 'no'; end; -if ~isfield(cfg.artfctdef.jump,'medianfilter'), cfg.artfctdef.jump.medianfilter = 'yes'; end; -if ~isfield(cfg.artfctdef.jump,'medianfiltord'),cfg.artfctdef.jump.medianfiltord = 9; end; - -% padding dependent settings -if ~isfield(cfg,'padding'), cfg.padding = 0; end; -if cfg.padding~=0 - if ~isfield(cfg.artfctdef.jump,'pretim'), cfg.artfctdef.jump.pretim = cfg.padding; end; - if ~isfield(cfg.artfctdef.jump,'psttim'), cfg.artfctdef.jump.psttim = cfg.padding; end; - if ~isfield(cfg.artfctdef.jump,'padding'),cfg.artfctdef.jump.padding = 0.5*cfg.padding; end; -else - if ~isfield(cfg.artfctdef.jump,'pretim'), cfg.artfctdef.jump.pretim = 0; end; - if ~isfield(cfg.artfctdef.jump,'psttim'), cfg.artfctdef.jump.psttim = 0; end; - if ~isfield(cfg.artfctdef.jump,'padding'),cfg.artfctdef.jump.padding = 0; end; -end; - -% method dependent settings -artfctdef.fltord = 0; -if strcmp(cfg.artfctdef.jump.method,'zvalue'), - if ~isfield(cfg.artfctdef.jump,'cutoff'), cfg.artfctdef.jump.cutoff = 20; end; -elseif strcmp(cfg.artfctdef.jump.method,'abs'), - if ~isfield(cfg.artfctdef.jump,'cutoff'), cfg.artfctdef.jump.cutoff = 5e-11; end; - if ~isfield(cfg.artfctdef.jump,'blc'), cfg.artfctdef.jump.blc = 'yes'; end; -end - -if ~isfield(cfg, 'datatype') || ~strcmp(cfg.datatype, 'continuous') - % datatype is unknown or not continuous, perform epoch boundary check - iscontinuous = 0; -else - % do not perform epoch boundary check, usefull for pseudo-continuous data - iscontinuous = strcmp(cfg.datatype, 'continuous'); -end - -fprintf('\nscanning for jump artifacts'); - -artfctdef = cfg.artfctdef.jump; -cfg = dataset2files(cfg); -hdr = read_header(cfg.headerfile); -trl = cfg.trl; -numtrl = size(trl,1); -padding = round(artfctdef.padding*hdr.Fs); -trl(:,1) = trl(:,1)-padding; -trl(:,2) = trl(:,2)+padding; -if ~isempty(find(trl(:,1)<1)), - fprintf('\nWARNING: required padding goes beyond begin of dataset'); - trl(find(trl(:,1)<1),1) = 1; -end -nsmp = trl(:,2) - trl(:,1) + 1;%compute number of samples per trial -artfctdef.sgn = channelselection(artfctdef.sgn,hdr.label); -sgnind = match_str(hdr.label, artfctdef.sgn); -artfctdef.trl = trl; -cutfltdatstr = cell(numtrl,1); -artfctchn = zeros(numtrl,1); -z_tdata = zeros(1,trl(end,2)); - -if ~isfield(artfctdef, 'fltpadding') - fltpadding = 0; -else - fltpadding = round(artfctdef.fltpadding*hdr.Fs); -end - -% loop over all signals on which jump-artifact detection is required. -for sgnlop = 1:length(sgnind) - fprintf('\nreading in signal %d from %d', sgnlop, length(sgnind)); - fltdatavg = 0; - fltdatstd = 0; - fltdatvar = 0; - cumpernumsmp = 0; - % loop over the trials and calculate mean and std - for trllop = 1:numtrl - dat = read_data(cfg.datafile, hdr, trl(trllop,1)-fltpadding, ... - trl(trllop,2)+fltpadding, sgnind(sgnlop), iscontinuous);%read data - if strcmp(artfctdef.method,'zvalue'), - fltdat = preproc(dat, artfctdef.sgn, hdr.Fs, artfctdef, [], fltpadding, fltpadding); - fltdat = [abs(diff(fltdat,1,2)) 0]; - elseif strcmp(artfctdef.method,'abs'), - fltdat = preproc(dat, artfctdef.sgn, hdr.Fs, artfctdef, [], fltpadding, fltpadding); - fltdat = fltdat - (min(fltdat)); - fltdat = fltdat(1:end-1); - end; - cutfltdatstr{trllop} = fltdat; - fltdatavg = fltdatavg + mean(fltdat,2) .* nsmp(trllop); - fltdatvar = fltdatvar + (std(fltdat,[],2)).^2 .* nsmp(trllop); - cumpernumsmp = cumpernumsmp + nsmp(trllop); - end - - fltdatavg = fltdatavg ./ cumpernumsmp; - fltdatstd = sqrt(fltdatvar ./ cumpernumsmp); - - % select for each sample the highest z-value, and keep track of the highest z-value for the - % respective channel in each trial - for trllop = 1:numtrl - if strcmp(artfctdef.method,'zvalue'), - z_tdat = (cutfltdatstr{trllop} - repmat(fltdatavg,[1 nsmp(trllop)])) ./ ... - repmat(fltdatstd,[1 nsmp(trllop)]); - elseif strcmp(artfctdef.method,'abs'), - z_tdat = cutfltdatstr{trllop}; - end; - dummy = sort([z_tdat;z_tdata(1,trl(trllop,1):trl(trllop,2))]); - z_tdata(1,trl(trllop,1):trl(trllop,2)) = dummy(end,:); - maxval(trllop,sgnlop) = max(z_tdat); - end; -end; - -% compute for each trial the channel-index with the maximum z-value -for trllop=1:numtrl - sgnind = find(maxval(trllop,:) == max(maxval(trllop,:))); - artfctchn(trllop) = sgnind; -end; - -clear cutfltdatstr; - -% update the configuration prior to calling artifact_feedback -cfg.artfctdef.jump = artfctdef; - -[artfctdef, artifact] = artifact_feedback_old(cfg, z_tdata, artfctchn, 'jump'); - -% remember the details that were used here -cfg.artfctdef.jump = artfctdef; -cfg.artfctdef.jump.artifact = artifact; - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: artifact_jump_old.m,v 1.5 2008/09/22 20:17:43 roboos Exp $'; - diff --git a/external/fieldtrip/private/artifact_manual.m b/external/fieldtrip/private/artifact_manual.m deleted file mode 100644 index bfc9085..0000000 --- a/external/fieldtrip/private/artifact_manual.m +++ /dev/null @@ -1,568 +0,0 @@ -function [cfg, artifact] = artifact_manual(cfg); - -% THIS FUNCTION IS DEPRECIATED, USE REJECTVISUAL INSTEAD -% -% ARTIFACT_MANUAL allows the user to detect artifacts manually using visual -% inspection. -% -% Use as: -% [cfg, artifact] = artifact_manual(cfg) -% required configuration options: -% cfg.dataset or both cfg.headerfile and cfg.datafile -% -% The configuration should also contain: -% cfg.artfctdef.manual.channel = cell-array with channels to be displayed. -% (Be careful not to specify to much channels because the function then will be very slow.) -% cfg.continuous = 'yes' or 'no' whether the file contains continuous data -% -% You can specify: -% cfg.artfctdef.manual.pretrialtime = time shown before trialstart (default 0) -% cfg.artfctdef.manual.posttrialtime = time shown after trialend (default 0) -% cfg.artfctdef.manual.fft = 'no' (default) or 'yes' turns on FFT window -% cfg.artfctdef.manual.padding = 'no' (default) or FFT-padding in seconds -% -% The FFT will be executed on the complete time interval including pre and post -% trial times. -% -% cfg.artfctdef.manual.timeaxrelative = 'yes' (default) or 'no'. -% -% Set to yes defines the time axes relative to trialstart. Set to no defines it -% relative to the beginning of the experiment. -% -% cfg.artfctdef.manual.blc = 'no' (default) or 'yes' apply baseline correction -% cfg.artfctdef.manual.bpfilter = 'no' (default) or 'yes' apply bandpass filter -% cfg.artfctdef.manual.bpfreq = [0.3 30] in Hz -% cfg.artfctdef.manual.bpfiltord = 2 -% -% See also REJECTARTIFACT, REJECTVISUAL - -% Undocumented local options: -% cfg.artfctdef.manual.maxnumberofchannels = 20 (default) - -% Copyright (C) 2004, Geerten Kramer, FCDC -% -% $Log: artifact_manual.m,v $ -% Revision 1.25 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.24 2009/01/16 18:19:41 sashae -% moved some lines of code, no functional change -% -% Revision 1.23 2009/01/14 11:47:07 sashae -% changed handling of cfg.datatype -% added call to checkconfig at start and end of function -% -% Revision 1.22 2008/12/02 16:31:49 estmee -% Set default cfg.continuous/ checkconfig cfg.datatype = forbidden -% -% Revision 1.21 2008/11/25 13:17:16 estmee -% Documentation update -% -% Revision 1.20 2008/11/18 16:14:47 estmee -% Added cfg.continuous -% -% Revision 1.19 2008/10/13 10:40:47 sashae -% added call to checkconfig -% -% Revision 1.18 2008/10/07 08:58:51 roboos -% committed the changes that Esther made recently, related to the support of data as input argument to the artifact detection functions. I hope that this does not break the functions too seriously. -% -% Revision 1.17 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.16 2008/05/13 15:37:24 roboos -% switched to using read_data/header instead of the read_fcdc_data/header wrapper functions -% -% Revision 1.15 2008/04/09 14:12:18 roboos -% fixed potential bug in print(fix(..))), see mail from Marcel from a few weeks abo -% -% Revision 1.14 2006/11/29 09:06:36 roboos -% renamed all cfg options with "sgn" into "channel", added backward compatibility when required -% updated documentation, mainly in the artifact detection routines -% -% Revision 1.13 2006/06/14 12:43:51 roboos -% removed the documentation for cfg.lnfilttype, since that option is not supported by preproc -% -% Revision 1.12 2006/04/20 09:58:33 roboos -% updated documentation -% -% Revision 1.11 2006/04/19 09:41:07 ingnie -% updated documentation -% -% Revision 1.10 2006/02/07 08:20:24 roboos -% fixed silly bug that was introduced along with dataset2files -% -% Revision 1.9 2006/01/31 13:49:29 jansch -% included dataset2files to ensure the presence of cfg.headerfile or cfg.datafile -% whenever needed -% -% Revision 1.8 2005/12/20 08:36:47 roboos -% add the artifact Nx2 matrix to the output configuration -% changed some indentation and white space, renamed a few variables -% -% Revision 1.7 2005/10/31 13:02:36 geekra -% - Made the field cfg.artfctdef.manual.channel required and removed the default -% value 'all'. This is done because 'all' selects more channels than the -% function can handle. -% - Build in a check on the number of channels selected, resulting in an error -% if: 1. No channels are selected or 2. more then 20 channels are selected. -% - Added the non documented option cfg.artfctdef.manual.maxnumberofchannels -% - Changed some Dutch comment into English. -% -% Revision 1.6 2005/06/29 12:42:00 roboos -% added version to the output configuration -% -% Revision 1.5 2005/05/17 17:50:36 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.4 2005/03/02 14:28:44 roboos -% added backward compatibility support for xxx.sgn (copy into xxx.channel) -% -% Revision 1.3 2005/01/25 13:15:41 roboos -% added check for cfg.datatype=continuous and extended the call to read_fcdc_data with the boundary check for non-continuous data -% -% Revision 1.2 2004/12/20 12:22:56 roboos -% fixed multiple bugs, added general preproc function, cleaned up code -% -% Revision 1.1 2004/12/20 08:47:50 roboos -% initial implementation, based on Geertens version of 23 November 2004 -% - -fieldtripdefs - -% check if the input cfg is valid for this function -cfg = checkconfig(cfg, 'trackconfig', 'on'); -cfg = checkconfig(cfg, 'renamed', {'datatype', 'continuous'}); -cfg = checkconfig(cfg, 'renamedval', {'continuous', 'continuous', 'yes'}); - -% set default parameters if necessary. -if ~isfield(cfg, 'artfctdef'), cfg.artfctdef = []; end -if ~isfield(cfg.artfctdef,'manual'), cfg.artfctdef.manual = []; end -if ~isfield(cfg.artfctdef.manual,'zscale'), cfg.artfctdef.manual.zscale = 100; end -if ~isfield(cfg.artfctdef.manual,'fft'), cfg.artfctdef.manual.fft ='no'; end -if ~isfield(cfg.artfctdef.manual,'padding'), cfg.artfctdef.manual.padding ='no'; end -if ~isfield(cfg.artfctdef.manual,'pretrialtime'), cfg.artfctdef.manual.pretrialtime = 0; end -if ~isfield(cfg.artfctdef.manual,'posttrialtime'), cfg.artfctdef.manual.posttrialtime = 0; end -if ~isfield(cfg.artfctdef.manual,'timeaxrelative'), cfg.artfctdef.manual.timeaxrelative = 'yes'; end -if ~isfield(cfg.artfctdef.manual,'maxnumberofchannels'),cfg.artfctdef.manual.maxnumberofchannels = 20; end - -% for backward compatibility -if isfield(cfg.artfctdef.manual,'sgn') - cfg.artfctdef.manual.channel = cfg.artfctdef.manual.sgn; - cfg.artfctdef.manual = rmfield(cfg.artfctdef.manual, 'sgn'); -end - -if ~isfield(cfg.artfctdef.manual,'channel'), - % set an unusual default because all crashes the program. - cfg.artfctdef.manual.channel = []; -end - -% read the header and do some preprocessing on the configuration -fprintf('Reading raw data...'); -cfg = checkconfig(cfg, 'dataset2files', {'yes'}); -cfg = checkconfig(cfg, 'required', {'headerfile', 'datafile'}); -hdr = read_header(cfg.headerfile); -cfg.artfctdef.manual.channel=channelselection(cfg.artfctdef.manual.channel, hdr.label); -cfg.artfctdef.manual.trl=cfg.trl; -if(isempty(cfg.artfctdef.manual.channel)) - error(sprintf('\nNo channels selected for artifact_manual!\nSelect at least one channel in cfg.artfctdef.manual.channel')); -end; -channelindx=match_str(hdr.label, cfg.artfctdef.manual.channel); -ntrial=size(cfg.trl, 1); -nch=length(channelindx); -if(nch<1) - error(sprintf('\nNo channels selected for artifact_manual!\nSelect at least one channel in cfg.artfctdef.manual.channel')); -elseif(nch>cfg.artfctdef.manual.maxnumberofchannels) - error(sprintf('\nMore than %i channels selected in cfg.artfctdef.manual.channel',cfg.artfctdef.manual.maxnumberofchannels)); -end - -% set default cfg.continuous -if ~isfield(cfg, 'continuous') - if hdr.nTrials==1 - cfg.continuous = 'yes'; - else - cfg.continuous = 'no'; - end -end - -show=read_data(cfg.datafile, 'header', hdr, 'begsample', 1, 'endsample', hdr.nTrials*hdr.nSamples, 'chanindx', channelindx, 'checkboundary', strcmp(cfg.continuous, 'no')); -show=show'; - -N=length(show); -S=floor(N./hdr.Fs); % In seconds -x=1:N; -x=x./hdr.Fs; % In seconds. - -fprintf(' done.\n'); -fprintf('Processing raw data for artifact_manual...'); - -% these elements are stored inside the figure so that the callback routines can modify them -dat.RejMarkList=zeros(length(cfg.trl),1); -dat.ResRejMarkList=zeros(length(cfg.trl),1); -dat.RejCount=0; -dat.ResRejCount=0; -dat.stop=0; -dat.trln=1; -dat.numtrl=length(cfg.trl); -dat.FFT=strcmp(cfg.artfctdef.manual.fft,'yes')|strcmp(cfg.artfctdef.manual.fft,'Yes')... - |strcmp(cfg.artfctdef.manual.fft,'on')|strcmp(cfg.artfctdef.manual.fft,'On'); -if(strcmp(cfg.artfctdef.manual.padding,'no')|strcmp(cfg.artfctdef.manual.padding,'No')... - |strcmp(cfg.artfctdef.manual.padding,'Off')|strcmp(cfg.artfctdef.manual.padding,'off')) - cfg.artfctdef.manual.padding=[]; -end; -dat.IfRelOn=strcmp(cfg.artfctdef.manual.timeaxrelative,'yes')|strcmp(cfg.artfctdef.manual.timeaxrelative,'Yes')... - |strcmp(cfg.artfctdef.manual.timeaxrelative,'on')|strcmp(cfg.artfctdef.manual.timeaxrelative,'On'); - -ival=cell(dat.numtrl,1); -dataX=cell(dat.numtrl,1); -dataY=cell(dat.numtrl,1); -dataFx=cell(dat.numtrl,1); -dataFy=cell(dat.numtrl,1); -dataXLim=cell(dat.numtrl,1); -dataYLim=cell(dat.numtrl,1); - -% first we calculate everything and put it into varables. -for(i=1:dat.numtrl) - begpadding = round(cfg.artfctdef.manual.pretrialtime.*hdr.Fs); - endpadding = round(cfg.artfctdef.manual.posttrialtime.*hdr.Fs); - ival{i}=(cfg.trl(i,1)-begpadding):(cfg.trl(i,2)+endpadding); - dataY{i}=show(ival{i},:); - - % don't remove the padding - [dataY{i}, dumlab, dumtime, dumcfg] = preproc(dataY{i}', cfg.artfctdef.manual.channel, hdr.Fs, cfg.artfctdef.manual, cfg.trl(i,3)-begpadding, 0, 0); - dataY{i} = dataY{i}'; - - try, if(~rem(i,fix(dat.numtrl/10)))fprintf('.');end; end -end; -clear show; % Now, we don't need the complete dataset anymore... -for(i=1:dat.numtrl) % we go on with the calculations .... - dataX{i}=x(ival{i})-dat.IfRelOn.*(x(ival{i}(1))+cfg.artfctdef.manual.pretrialtime); - - dataYLim{i}=[]; - for(j=1:nch) - mini=min(dataY{i}(:,j)); - maxi=max(dataY{i}(:,j)); - - dataYLim{i}=[dataYLim{i};[mini-.03.*(maxi-mini),maxi+.03.*(maxi-mini)]]; - dataXLim{i}=[min(dataX{i}),max(dataX{i})]; - end; - - if(dat.FFT) % if FFT is on, calculate the FFT of the trials too... - tmp=[]; - for(k=1:nch) tmp=[tmp,dataY{i}(:,k)-mean(dataY{i}(:,k),1)];end; - dataFy{i}=abs(fft(tmp,cfg.artfctdef.manual.padding,1)); - tmp=floor((max(ival{i})-min(ival{i}))/2); - dataFx{i}=(1:tmp)./tmp.*hdr.Fs./2; - dataFy{i}=dataFy{i}(1:length(dataFx{i}),:); - end; - if(~rem(i,fix(dat.numtrl/10)))fprintf('.');end; -end; - -fprintf(' done.\n'); - -thisfig('fig_trace');% See the help of thisfig -set(fig_trace,'name','Traces'); -if(dat.FFT); - thisfig('fig_spec'); - set(fig_spec,'name','Spectra of traces'); -end; -gt=[5 40 5 25 0 50 5 60 5 60 5 60 5 60 5 60 5 25 0 25]; -uicontrol(fig_trace,'units','pixels','position',[sum(gt(1:1)),5,gt(2),18],'String','Done','Callback',@stop); -uicontrol(fig_trace,'units','pixels','position',[sum(gt(1:3)),5,gt(4),18],'String','<','Callback',@prevtrial); -uicontrol(fig_trace,'units','pixels','position',[sum(gt(1:5)),5,gt(6),18],'String','>','Callback',@nexttrial); -uicontrol(fig_trace,'units','pixels','position',[sum(gt(1:7)),5,gt(8),18],'String','Reject >','Callback',@reject_next); -uicontrol(fig_trace,'units','pixels','position',[sum(gt(1:9)),5,gt(10),18],'String','Reject','Callback',@reject); -uicontrol(fig_trace,'units','pixels','position',[sum(gt(1:11)),5,gt(12),18],'String','Accept','Callback',@undo); -uicontrol(fig_trace,'units','pixels','position',[sum(gt(1:13)),5,gt(14),18],'String','Accept All','Callback',@undoAll); -uicontrol(fig_trace,'units','pixels','position',[sum(gt(1:15)),5,gt(16),18],'String','Redo All','Callback',@redoAll); -uicontrol(fig_trace,'units','pixels','position',[sum(gt(1:17)),5,gt(18),18],'String','<<','Callback',@pptrial); -uicontrol(fig_trace,'units','pixels','position',[sum(gt(1:19)),5,gt(20),18],'String','>>','Callback',@nntrial); -set(fig_trace, 'KeyPressFcn',@keypress); -% set(get(fig_trace, 'children'),'KeyPressFcn',@keypress); -show_help; - -thisfig('fig_trace'); % See the help of thisfig. - -while(ishandle(fig_trace)) - - if(dat.FFT) % Plots FFT when requested - if(exist('HF')) % this is for remembering the zoom of the FFT-window - if(ishandle(HF)) % while zapping trough the data. - saveXLim=get(HF,'XLim'); - saveYLim=get(HF,'YLim'); - end; - end; - thisfig('fig_spec'); - plot(dataFx{dat.trln},dataFy{dat.trln}); - HF=get(fig_spec,'CurrentAxes'); - if(exist('saveXLim'))set(HF,'XLim',saveXLim);end; - if(exist('saveYLim'))set(HF,'YLim',saveYLim);end; - xlabel('Frequency [Hz]'); - ylabel('Power [A.U.]'); - thisfig('fig_trace'); - end; - - for(j=1:nch) % This loop fils the traces figure with the traces. - H=subplot(nch,1,j); - plot(dataX{dat.trln},dataY{dat.trln}(:,j),'b-'); - line([dataXLim{1}(1)+cfg.artfctdef.manual.pretrialtime dataXLim{1}(1)+cfg.artfctdef.manual.pretrialtime], dataYLim{dat.trln}(j,:), 'color', 'g'); - line([dataXLim{1}(2)-cfg.artfctdef.manual.posttrialtime dataXLim{1}(2)-cfg.artfctdef.manual.posttrialtime], dataYLim{dat.trln}(j,:), 'color', 'r'); - set(H,'YLim',dataYLim{dat.trln}(j,:) + [-eps +eps]); - set(H,'XLim',dataXLim{dat.trln}); - xlabel('Time [s]','position',... - [dataXLim{dat.trln}(2),dataYLim{dat.trln}(j,1)-(dataYLim{dat.trln}(j,2)-dataYLim{dat.trln}(j,1)).*.05]... - ,'HorizontalAlignment','left'); - ylabel(sprintf('%s', cfg.artfctdef.manual.channel{j})); - end; - - if(dat.RejMarkList(dat.trln)==0) - tiet=sprintf('trial %i: ACCEPT',dat.trln); - else - tiet=sprintf('trial %i: REJECT',dat.trln); - end; - H=subplot(nch,1,1); - title(tiet); - - guidata(fig_trace,dat); - uiwait; - if(ishandle(fig_trace)) dat=guidata(fig_trace);end; - - if(dat.stop)break;end; -end - -if(~ishandle(fig_trace)) - error('Figure closed unexpectedly, no manual artifacts marked.'); -else - close(fig_trace) -end; - -if(dat.FFT) - if(ishandle(fig_spec))close(fig_spec);end; -end; - -fprintf('Rejected %i trials.\n',dat.RejCount); -fprintf('Exported %i trials.\n',length(cfg.trl)-dat.RejCount); - -artifact=cfg.trl(find((dat.RejMarkList)),[1,2]); - -% remember the details that were used here -cfg.artfctdef.manual.artifact = artifact; - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: artifact_manual.m,v 1.25 2009/01/20 13:01:31 sashae Exp $'; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% here the SUBFUNCTIONS start that implement the gui callbacks -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -function varargout=nexttrial(h, eventdata, handles, varargin) -dat=guidata(h); -if(dat.trln 1), - dat.trln=dat.trln - 1; -else - dat.trln=dat.numtrl; -end; -guidata(h,dat); -uiresume; - -function varargout=stop(h, eventdata, handles, varargin) -dat=guidata(h); -dat.stop=1; -guidata(h,dat); -uiresume; - -function varargout=reject(h, eventdata, handles, varargin) -dat=guidata(h); -if(dat.RejMarkList(dat.trln)==0) - dat.RejCount=dat.RejCount+1; - dat.RejMarkList(dat.trln)=1; - if(~dat.ResRejMarkList(dat.trln)) - dat.ResRejCount=dat.ResRejCount+1; - dat.ResRejMarkList(dat.trln)=1; - fprintf('Rejected trial %i!\n',dat.trln); - else - fprintf('Rejected trial %i again!\n',dat.trln); - end; -else - fprintf('Trial %i is already marked for rejection.\n',dat.trln); -end; -guidata(h,dat); -uiresume; - - -function varargout=reject_next(h, eventdata, handles, varargin) -dat=guidata(h); -if(dat.RejMarkList(dat.trln)==0) - dat.RejCount=dat.RejCount+1; - dat.RejMarkList(dat.trln)=1; - if(~dat.ResRejMarkList(dat.trln)) - dat.ResRejCount=dat.ResRejCount+1; - dat.ResRejMarkList(dat.trln)=1; - fprintf('Rejected trial %i!\n',dat.trln); - else - fprintf('Rejected trial %i again!\n',dat.trln); - end; -else - fprintf('Trial %i is already marked for rejection.\n',dat.trln); -end; -if(dat.trln < dat.numtrl) - dat.trln=dat.trln + 1; -else - dat.trln=1; -end; -guidata(h,dat); -uiresume; - -function varargout=undo(h, eventdata, handles, varargin) -dat=guidata(h); -if(dat.RejMarkList(dat.trln)>0) - dat.RejCount=dat.RejCount-1; - dat.RejMarkList(dat.trln)=0; - fprintf('Rejected trial %i recovered.\n',dat.trln); -end; -guidata(h,dat); -uiresume; - -function varargout=undoAll(h, eventdata, handles, varargin) -dat=guidata(h); -dat.RejCount=0; -dat.RejMarkList=zeros(dat.numtrl,1); -fprintf('All rejected trials recovered.\n'); -guidata(h,dat); -uiresume; - -function varargout=redoAll(h, eventdata, handles, varargin) -dat=guidata(h); -dat.RejMarkList=dat.ResRejMarkList; -dat.RejCount=dat.ResRejCount; -fprintf('All recovered trials rejected again.\n'); -guidata(h,dat); -uiresume; - -function varargout=nntrial(h, eventdata, handles, varargin) -dat=guidata(h); -if(dat.trln<(dat.numtrl-10)) - dat.trln=dat.trln + 10; -else - dat.trln=1; -end; -guidata(h,dat); -uiresume; - - -function varargout=pptrial(h, eventdata, handles, varargin) -dat=guidata(h); -if(dat.trln > 10), - dat.trln=dat.trln - 10; -else - dat.trln=dat.numtrl; -end; -guidata(h,dat); -uiresume; - -function keypress(h, eventdata, handles, varargin) -dat=guidata(gcbf); -key=get(gcbf, 'CurrentCharacter'); -if key - switch key - case 28 % arrow left - if(dat.trln > 1), - dat.trln=dat.trln - 1; - else - dat.trln=dat.numtrl; - end; - case 29 % arrow right - if(dat.trlnartfctdef.max - fprintf('threshold artifact scanning: trial %d from %d exceeds max-threshold\n', trlop, numtrl); - artifact(end+1,1:2) = cfg.trl(trlop,1:2); - elseif ~isempty(artfctdef.range) && rangeval>artfctdef.range - fprintf('threshold artifact scanning: trial %d from %d exceeds range-threshold\n', trlop, numtrl); - artifact(end+1,1:2) = cfg.trl(trlop,1:2); - else - fprintf('threshold artifact scanning: trial %d from %d is ok\n', trlop, numtrl); - end -end - -% remember the details that were used here -cfg.artfctdef.threshold = artfctdef; -cfg.artfctdef.threshold.trl = cfg.trl; % trialdefinition prior to rejection -cfg.artfctdef.threshold.channel = channel; % exact channels used for detection -cfg.artfctdef.threshold.artifact = artifact; % detected artifacts - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: artifact_threshold.m,v 1.29 2009/01/20 13:01:31 sashae Exp $'; diff --git a/external/fieldtrip/private/artifact_viewer.m b/external/fieldtrip/private/artifact_viewer.m index eb6bfe7..e10b80c 100644 --- a/external/fieldtrip/private/artifact_viewer.m +++ b/external/fieldtrip/private/artifact_viewer.m @@ -6,28 +6,29 @@ % Copyright (C) 2004-2006, Jan-Mathijs Schoffelen & Robert Oostenveld % -% $Log: artifact_viewer.m,v $ -% Revision 1.12 2008/11/18 16:22:42 estmee -% Added cfg.continuous +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.11 2008/10/07 16:22:12 estmee -% Changed the output of fetch_data and read_data from dat to data. +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.10 2008/10/07 08:58:51 roboos -% committed the changes that Esther made recently, related to the support of data as input argument to the artifact detection functions. I hope that this does not break the functions too seriously. +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.9 2006/08/28 08:10:24 jansch -% fixed small bug in number of padding-samples when non-integer, thanks to Jasper -% -% Revision 1.8 2006/01/12 14:20:08 roboos -% new implementation that belongs to artifact_zvalue +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: artifact_viewer.m 1434 2010-07-21 11:44:43Z jansch $ dat.cfg = cfg; dat.artcfg = artcfg; if nargin == 5 % no data is given - dat.hdr = read_fcdc_header(cfg.headerfile); + dat.hdr = ft_read_header(cfg.headerfile); elseif nargin == 6 % data is given dat.hdr = fetch_header(inputdata); % used name inputdata iso data, because data is already used later in this function diff --git a/external/fieldtrip/private/artifact_viewer_old.m b/external/fieldtrip/private/artifact_viewer_old.m deleted file mode 100644 index 4a39b62..0000000 --- a/external/fieldtrip/private/artifact_viewer_old.m +++ /dev/null @@ -1,221 +0,0 @@ -function artifact_viewer(cfg,artfctdef,rejectall,z_tdata,artfctchn,flag) - -% artifact_viewer provides a GUI for browsing through the data while applying automatic artifact -% detection. it presents the data on trial by trial, and ad lib. one can jump through the data. -% the figure shows two subplot, the lower one containing the transformed data, on which the -% thresholding has been applied. the upper window contains the data of the channel (which is a -% member of the subset, defined in xxx.artfctdef.sgn), contributing most to the most deviant -% transformed data-point in the respective trial. -% -% Copyright (c) 2004, F.C. Donders Centre -% - -dat.trln= 1; -dat.cfg = cfg; -dat.rej = rejectall; -dat.zdat= z_tdata; -dat.art = artfctdef; -dat.chn = artfctchn; -dat.hdr = read_fcdc_header(cfg.headerfile); -dat.trl = artfctdef.trl; -dat.numtrl = size(dat.trl,1); -dat.nsmp = dat.trl(:,2) - dat.trl(:,1) + 1; -dat.stop = 0; -dat.afv = cell(1,size(dat.trl,1)); -for j = 1:size(dat.trl,1) - dat.afv{j} = rejectall(1,dat.trl(j,1):dat.trl(j,2)); - dat.afv{j} = diff([0 dat.afv{j} 0]); - if isempty(find(dat.afv{j})) - dat.trialok(j) = 1; - else - dat.trialok(j) = 0; - end -end - -h = figure; -guidata(h,dat); -uicontrol(gcf,'units','pixels','position',[5 5 40 18],'String','stop','Callback',@stop); -uicontrol(gcf,'units','pixels','position',[50 5 25 18],'String','<','Callback',@prevtrial); -uicontrol(gcf,'units','pixels','position',[75 5 25 18],'String','>','Callback',@nexttrial); -uicontrol(gcf,'units','pixels','position',[105 5 25 18],'String','<<','Callback',@prev10trial); -uicontrol(gcf,'units','pixels','position',[130 5 25 18],'String','>>','Callback',@next10trial); -uicontrol(gcf,'units','pixels','position',[160 5 50 18],'String','','Callback',@nextartfct); - -while ishandle(h), - dat = guidata(h); - if dat.stop == 0, - read_and_plot(h); - uiwait; - else - break - end -end -if ishandle(h) - close(h); -end - -%------------ -%subfunctions -%------------ - -function read_and_plot(h) - dat = guidata(h); - - rej = []; - trln = dat.trln; - cfg = dat.cfg; - rejectall = dat.rej; - z_tdata = dat.zdat; - artfctdef = dat.art; - hdr = dat.hdr; - trl = dat.trl; - nsmp = dat.nsmp; - chn = dat.chn(trln); - channel = dat.art.sgn(chn,:); - sgnind = match_str(dat.hdr.label,channel); - afv = dat.afv{trln}; - - if ~isfield(cfg, 'datatype') || ~strcmp(cfg.datatype, 'continuous') - % datatype is unknown or not continuous, perform epoch boundary check - iscontinuous = 0; - else - % do not perform epoch boundary check, usefull for pseudo-continuous data - iscontinuous = strcmp(cfg.datatype, 'continuous'); - end - - if ~isfield(artfctdef, 'fltpadding') - if iscontinuous - if ~isfield(artfctdef, 'bpfilttype') - fltpadding = 0; - elseif strcmp(artfctdef.bpfilttype, 'but') - fltpadding = 20*artfctdef.bpfiltord; - elseif strcmp(artfctdef.bpfilttype, 'fir') - fltpadding = artfctdef.bpfiltord; - else - warning('unknown filter type, cannot determine filter padding'); - fltpadding = 0; - end - else - warning('default is not to apply filter padding on trial based data'); - fltpadding = 0; - end - else - fltpadding = round(artfctdef.fltpadding*hdr.Fs); - end - - if (strcmp(flag,'EOGflt')|strcmp(flag,'jump')) - data = read_fcdc_data(cfg.datafile,hdr,trl(trln,1)-fltpadding, ... - trl(trln,2)+fltpadding,sgnind,iscontinuous); - data = preproc(data, channel, hdr.Fs, artfctdef, [], fltpadding, fltpadding); - data = blc(data); - else - data = read_fcdc_data(cfg.datafile,hdr,trl(trln,1),trl(trln,2),sgnind,iscontinuous); - data = blc(data); - end; - if ~isempty(find(afv==1)) - rej(:,1)= find(afv==1)'; - rej(:,2)= (find(afv==-1)-1)'; - end - s=sprintf('trial: %d',trln); - - %plot data of most aberrant channel in upper subplot - gcf;subplot(211);plot(0,0);hold on;title(s); - if ~isempty(rej) - for artfct=1:size(rej,1) - xpos = rej(artfct,1)-round(artfctdef.pretim*hdr.Fs); - ypos = min(min(data(:))); - width = round((artfctdef.psttim+artfctdef.pretim)*hdr.Fs) + ... - rej(artfct,2)-rej(artfct,1) + 1; - % height = diff(minmax(data(1,:))); - height = range(data(1,:)); - rectangle('Position',[xpos ypos width height],'FaceColor','r'); - hold on; - end; - end; - plot(1:nsmp(trln),data,'b'); - lowlim = min(data(1,:)) - 0.1*(abs(min(data(1,:)))); - uplim = max(data(1,:))+ 0.1*(abs(max(data(1,:)))); - axis([0 nsmp(trln) lowlim uplim]); - hold off; - xlabel('samples'); - ylabel('uV or Tesla'); - - %plot the transformed data, on which the thresholding is applied, in the lower subplot - gcf;subplot(212);plot(1:nsmp(trln),z_tdata(:,trl(trln,1):trl(trln,2)));hold on; - plot([1 nsmp(trln)],[artfctdef.cutoff artfctdef.cutoff],'r:'); - lowlim = min(z_tdata(1,trl(trln,1):trl(trln,2))) - ... - 0.1*(abs(min(z_tdata(1,trl(trln,1):trl(trln,2))))); - uplim = max([max(z_tdata(1,trl(trln,1):trl(trln,2)))+ ... - 0.1*(abs(max(z_tdata(1,trl(trln,1):trl(trln,2))))) artfctdef.cutoff*1.05]); - axis([0 nsmp(trln) lowlim uplim]); - hold off; - xlabel('samples'); - ylabel('zscore'); - guidata(h,dat); - -function varargout = nexttrial(h, eventdata, handles, varargin) - dat = guidata(h); - if dat.trln < dat.numtrl, - dat.trln = dat.trln + 1; - end; - guidata(h,dat); - uiresume; - -function varargout = next10trial(h, eventdata, handles, varargin) - dat = guidata(h); - if dat.trln < dat.numtrl - 10, - dat.trln = dat.trln + 10; - else dat.trln = dat.numtrl; - end; - guidata(h,dat); - uiresume; - -function varargout = prevtrial(h, eventdata, handles, varargin) - dat = guidata(h); - if dat.trln > 1, - dat.trln = dat.trln - 1; - else dat.trln = 1; - end; - guidata(h,dat); - uiresume; - -function varargout = prev10trial(h, eventdata, handles, varargin) - dat = guidata(h); - if dat.trln > 10, - dat.trln = dat.trln - 10; - else dat.trln = 1; - end; - guidata(h,dat); - uiresume; - -function varargout = nextartfct(h, eventdata, handles, varargin) - dat = guidata(h); - artfctindx = find(dat.trialok == 0); - sel = find(artfctindx > dat.trln); - if ~isempty(sel) - dat.trln = artfctindx(sel(1)); - else - dat.trln = dat.trln; - end - guidata(h,dat); - uiresume; - -function varargout = prevartfct(h, eventdata, handles, varargin) - dat = guidata(h); - artfctindx = find(dat.trialok == 0); - sel = find(artfctindx < dat.trln); - if ~isempty(sel) - dat.trln = artfctindx(sel(end)); - else - dat.trln = dat.trln; - end - guidata(h,dat); - uiresume; - -function varargout = stop(h, eventdata, handles, varargin) - dat = guidata(h); - dat.stop = 1; - guidata(h,dat); - uiresume; - diff --git a/external/fieldtrip/private/artifact_zvalue.m b/external/fieldtrip/private/artifact_zvalue.m deleted file mode 100644 index e8ff9c9..0000000 --- a/external/fieldtrip/private/artifact_zvalue.m +++ /dev/null @@ -1,413 +0,0 @@ -function [cfg, artifact] = artifact_zvalue(cfg,data) - -% ARTIFACT_ZVALUE reads the interesting segments of data from file and -% identifies artifacts by means of thresholding the z-transformed value -% of the preprocessed raw data. Depending on the preprocessing options, -% this method will be sensitive to EOG, muscle or jump artifacts. -% This procedure only works on continuously recorded data. -% -% Use as -% [cfg, artifact] = artifact_zvalue(cfg) -% or -% [cfg, artifact] = artifact_zvalue(cfg, data) -% -% The output argument "artifact" is a Nx2 matrix comparable to the -% "trl" matrix of DEFINETRIAL. The first column of which specifying the -% beginsamples of an artifact period, the second column contains the -% endsamples of the artifactperiods. -% -% If you are calling ARTIFACT_ZVALUE with only the configuration as first -% input argument and the data still has to be read from file, you should -% specify: -% cfg.headerfile -% cfg.headerfile -% cfg.datafile -% cfg.datatype -% -% If you are calling ARTIFACT_ZVALUE with also the second input argument -% "data", then that should contain data that was already read from file in -% a call to PREPROCESSING. -% -% The required configuration settings are: -% cfg.trl -% cfg.artfctdef.zvalue.channel -% cfg.artfctdef.zvalue.cutoff -% cfg.artfctdef.zvalue.trlpadding -% cfg.artfctdef.zvalue.fltpadding -% cfg.artfctdef.zvalue.artpadding -% cfg.continuous -% -% Configuration settings related to the preprocessing of the data are -% cfg.artfctdef.zvalue.lpfilter = 'no' or 'yes' lowpass filter -% cfg.artfctdef.zvalue.hpfilter = 'no' or 'yes' highpass filter -% cfg.artfctdef.zvalue.bpfilter = 'no' or 'yes' bandpass filter -% cfg.artfctdef.zvalue.lnfilter = 'no' or 'yes' line noise removal using notch filter -% cfg.artfctdef.zvalue.dftfilter = 'no' or 'yes' line noise removal using discrete fourier transform -% cfg.artfctdef.zvalue.medianfilter = 'no' or 'yes' jump preserving median filter -% cfg.artfctdef.zvalue.lpfreq = lowpass frequency in Hz -% cfg.artfctdef.zvalue.hpfreq = highpass frequency in Hz -% cfg.artfctdef.zvalue.bpfreq = bandpass frequency range, specified as [low high] in Hz -% cfg.artfctdef.zvalue.lnfreq = line noise frequency in Hz, default 50Hz -% cfg.artfctdef.zvalue.lpfiltord = lowpass filter order -% cfg.artfctdef.zvalue.hpfiltord = highpass filter order -% cfg.artfctdef.zvalue.bpfiltord = bandpass filter order -% cfg.artfctdef.zvalue.lnfiltord = line noise notch filter order -% cfg.artfctdef.zvalue.medianfiltord = length of median filter -% cfg.artfctdef.zvalue.lpfilttype = digital filter type, 'but' (default) or 'fir' -% cfg.artfctdef.zvalue.hpfilttype = digital filter type, 'but' (default) or 'fir' -% cfg.artfctdef.zvalue.bpfilttype = digital filter type, 'but' (default) or 'fir' -% cfg.artfctdef.zvalue.detrend = 'no' or 'yes' -% cfg.artfctdef.zvalue.blc = 'no' or 'yes' -% cfg.artfctdef.zvalue.blcwindow = [begin end] in seconds, the default is the complete trial -% cfg.artfctdef.zvalue.hilbert = 'no' or 'yes' -% cfg.artfctdef.zvalue.rectify = 'no' or 'yes' -% -% See also REJECTARTIFACT - -% Copyright (c) 2003-2005, Jan-Mathijs Schoffelen, Robert Oostenveld -% -% $Log: artifact_zvalue.m,v $ -% Revision 1.21 2009/09/30 12:46:11 jansch -% Took out the loop over signals generally leading to a decent speed-up -% -% Revision 1.20 2009/03/19 10:53:51 roboos -% some cocde cleanup and whitespace, no functional change -% -% Revision 1.19 2009/03/18 10:09:00 jansch -% built in possibility to do thresholding based on the max across channels, -% rather than on the accumulated value across channels. this is the default -% for jump artifact detection, and more sensitive -% -% Revision 1.18 2008/12/02 16:34:20 estmee -% Set default cfg.continuous (hdr needed) -% -% Revision 1.17 2008/11/18 16:16:49 estmee -% Added cfg.continuous -% -% Revision 1.16 2008/10/13 13:03:11 sashae -% added call to checkconfig (as discussed with estmee) -% -% Revision 1.15 2008/10/07 16:20:15 estmee -% Added data as second input argument to artifact_zvalue, changed the output of preproc from data in dat and changed data in dat in the rest of the function. -% -% Revision 1.14 2008/10/07 08:58:51 roboos -% committed the changes that Esther made recently, related to the support of data as input argument to the artifact detection functions. I hope that this does not break the functions too seriously. -% -% Revision 1.13 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.12 2008/05/13 15:37:24 roboos -% switched to using read_data/header instead of the read_fcdc_data/header wrapper functions -% -% Revision 1.11 2006/11/29 16:14:15 roboos -% fixed a bug introduced by the previous commit, hope that everything works now... -% -% Revision 1.10 2006/11/29 11:52:27 roboos -% also fixed two forgotten references to sgn -% -% Revision 1.9 2006/11/29 11:51:29 roboos -% fixed typo -% -% Revision 1.8 2006/11/29 09:06:36 roboos -% renamed all cfg options with "sgn" into "channel", added backward compatibility when required -% updated documentation, mainly in the artifact detection routines -% -% Revision 1.7 2006/06/14 12:43:53 roboos -% removed the documentation for cfg.lnfilttype, since that option is not supported by preproc -% -% Revision 1.6 2006/05/02 19:21:57 roboos -% removed smartinput subfunction, which is now a seperate function -% -% Revision 1.5 2006/04/25 17:06:28 ingnie -% updated documentation -% -% Revision 1.4 2006/02/28 08:16:30 roboos -% added fprintf statement with number of artifacts detected -% -% Revision 1.3 2006/01/30 14:08:08 jansch -% added -inf to initialization of zmax-vector, for some obscure situations, in -% which initialization with zeros would crash. -% -% Revision 1.2 2006/01/13 11:03:05 roboos -% do not take absolute value of z-values prior to accumulating -% -% Revision 1.1 2006/01/12 13:51:38 roboos -% completely new implementation, all based upon the same artifact_zvalue code -% all preprocessing is now done consistently and the various paddings have been better defined -% the functions do not have any explicit support any more for non-continuous data -% the old artifact_xxx functions from JM have been renamed to xxx_old -% - -fieldtripdefs - -% set default rejection parameters -if ~isfield(cfg,'artfctdef'), cfg.artfctdef = []; end -if ~isfield(cfg.artfctdef,'zvalue'), cfg.artfctdef.zvalue = []; end - -% for backward compatibility -if isfield(cfg.artfctdef.zvalue,'sgn') - cfg.artfctdef.zvalue.channel = cfg.artfctdef.zvalue.sgn; - cfg.artfctdef.zvalue = rmfield(cfg.artfctdef.zvalue, 'sgn'); -end - -if isfield(cfg.artfctdef.zvalue, 'artifact') - fprintf('zvalue artifact detection has already been done, retaining artifacts\n'); - artifact = cfg.artfctdef.zvalue.artifact; - return -end - -if ~isfield(cfg.artfctdef.zvalue,'channel'), cfg.artfctdef.zvalue.channel = {}; end -if ~isfield(cfg.artfctdef.zvalue,'trlpadding'), cfg.artfctdef.zvalue.trlpadding = 0; end -if ~isfield(cfg.artfctdef.zvalue,'artpadding'), cfg.artfctdef.zvalue.artpadding = 0; end -if ~isfield(cfg.artfctdef.zvalue,'fltpadding'), cfg.artfctdef.zvalue.fltpadding = 0; end -if ~isfield(cfg.artfctdef.zvalue,'feedback'), cfg.artfctdef.zvalue.feedback = 'no'; end -if ~isfield(cfg.artfctdef.zvalue,'cumulative'), cfg.artfctdef.zvalue.cumulative = 'yes'; end - -thresholdsum = strcmp(cfg.artfctdef.zvalue.cumulative, 'yes'); - -if nargin > 1 - % data given as input - isfetch = 1; - hdr = fetch_header(data); -elseif nargin == 1 - % only cfg given - isfetch = 0; - hdr = read_header(cfg.headerfile); -end - -% set default cfg.continuous -if ~isfield(cfg, 'continuous') - if hdr.nTrials==1 - cfg.continuous = 'yes'; - else - cfg.continuous = 'no'; - end -end - -trl = cfg.trl; -trlpadding = round(cfg.artfctdef.zvalue.trlpadding*hdr.Fs); -fltpadding = round(cfg.artfctdef.zvalue.fltpadding*hdr.Fs); -artpadding = round(cfg.artfctdef.zvalue.artpadding*hdr.Fs); -trl(:,1) = trl(:,1) - trlpadding; % pad the trial with some samples, in order to detect -trl(:,2) = trl(:,2) + trlpadding; % artifacts at the edges of the relevant trials. -trl(:,3) = nan; % the offset is not correct any more -trllength = trl(:,2) - trl(:,1) + 1; % length of each trial -numtrl = size(trl,1); -cfg.artfctdef.zvalue.trl = trl; % remember where we are going to look for artifacts -cfg.artfctdef.zvalue.channel = channelselection(cfg.artfctdef.zvalue.channel, hdr.label); -sgnind = match_str(hdr.label, cfg.artfctdef.zvalue.channel); -numsgn = length(sgnind); - -if numsgn<1 - error('no channels selected'); -else - fprintf('searching for artifacts in %d channels\n', numsgn); -end - -% read the data and apply preprocessing options -sumval = zeros(numsgn, 1); -sumsqr = zeros(numsgn, 1); -numsmp = zeros(numsgn, 1); -fprintf('searching trials'); -for trlop = 1:numtrl - fprintf('.'); - if isfetch - dat{trlop} = fetch_data(data, 'header', hdr, 'begsample', trl(trlop,1)-fltpadding, 'endsample', trl(trlop,2)+fltpadding, 'chanindx', sgnind, 'checkboundary', strcmp(cfg.continuous,'no')); - else - dat{trlop} = read_data(cfg.datafile, 'header', hdr, 'begsample', trl(trlop,1)-fltpadding, 'endsample', trl(trlop,2)+fltpadding, 'chanindx', sgnind, 'checkboundary', strcmp(cfg.continuous,'no')); - end - dat{trlop} = preproc(dat{trlop}, cfg.artfctdef.zvalue.channel, hdr.Fs, cfg.artfctdef.zvalue, [], fltpadding, fltpadding); - % accumulate the sum and the sum-of-squares - sumval = sumval + sum(dat{trlop},2); - sumsqr = sumsqr + sum(dat{trlop}.^2,2); - numsmp = numsmp + size(dat{trlop},2); -end % for trlop - -% compute the average and the standard deviation -datavg = sumval./numsmp; -datstd = sqrt(sumsqr./numsmp - (sumval./numsmp).^2); - -for trlop = 1:numtrl - % initialize some matrices - zmax{trlop} = -inf + zeros(1,size(dat{trlop},2)); - zsum{trlop} = zeros(1,size(dat{trlop},2)); - zindx{trlop} = zeros(1,size(dat{trlop},2)); - - nsmp = size(dat{trlop},2); - zdata = (dat{trlop} - datavg(:,ones(1,nsmp)))./datstd(:,ones(1,nsmp)); % convert the filtered data to z-values - zsum{trlop} = sum(zdata,1); % accumulate the z-values over channels - [zmax{trlop},ind] = max(zdata,[],1); % find the maximum z-value and remember it - zindx{trlop} = sgnind(ind); % also remember the channel number that has the largest z-value - - % This alternative code does the same, but it is much slower - % for i=1:size(zmax{trlop},2) - % if zdata{trlop}(i)>zmax{trlop}(i) - % % update the maximum value and channel index - % zmax{trlop}(i) = zdata{trlop}(i); - % zindx{trlop}(i) = sgnind(sgnlop); - % end - % end -end % for trlop - -%for sgnlop=1:numsgn -% % read the data and apply preprocessing options -% sumval = 0; -% sumsqr = 0; -% numsmp = 0; -% fprintf('searching channel %s ', cfg.artfctdef.zvalue.channel{sgnlop}); -% for trlop = 1:numtrl -% fprintf('.'); -% if isfetch -% dat{trlop} = fetch_data(data, 'header', hdr, 'begsample', trl(trlop,1)-fltpadding, 'endsample', trl(trlop,2)+fltpadding, 'chanindx', sgnind(sgnlop), 'checkboundary', strcmp(cfg.continuous,'no')); -% else -% dat{trlop} = read_data(cfg.datafile, 'header', hdr, 'begsample', trl(trlop,1)-fltpadding, 'endsample', trl(trlop,2)+fltpadding, 'chanindx', sgnind(sgnlop), 'checkboundary', strcmp(cfg.continuous,'no')); -% end -% dat{trlop} = preproc(dat{trlop}, cfg.artfctdef.zvalue.channel(sgnlop), hdr.Fs, cfg.artfctdef.zvalue, [], fltpadding, fltpadding); -% % accumulate the sum and the sum-of-squares -% sumval = sumval + sum(dat{trlop},2); -% sumsqr = sumsqr + sum(dat{trlop}.^2,2); -% numsmp = numsmp + size(dat{trlop},2); -% end % for trlop -% -% % compute the average and the standard deviation -% datavg = sumval./numsmp; -% datstd = sqrt(sumsqr./numsmp - (sumval./numsmp).^2); -% -% for trlop = 1:numtrl -% if sgnlop==1 -% % initialize some matrices -% zdata{trlop} = zeros(size(dat{trlop})); -% zmax{trlop} = -inf + zeros(size(dat{trlop})); -% zsum{trlop} = zeros(size(dat{trlop})); -% zindx{trlop} = zeros(size(dat{trlop})); -% end -% zdata{trlop} = (dat{trlop} - datavg)./datstd; % convert the filtered data to z-values -% zsum{trlop} = zsum{trlop} + zdata{trlop}; % accumulate the z-values over channels -% zmax{trlop} = max(zmax{trlop}, zdata{trlop}); % find the maximum z-value and remember it -% zindx{trlop}(zmax{trlop}==zdata{trlop}) = sgnind(sgnlop); % also remember the channel number that has the largest z-value -% -% % This alternative code does the same, but it is much slower -% % for i=1:size(zmax{trlop},2) -% % if zdata{trlop}(i)>zmax{trlop}(i) -% % % update the maximum value and channel index -% % zmax{trlop}(i) = zdata{trlop}(i); -% % zindx{trlop}(i) = sgnind(sgnlop); -% % end -% % end -% end -% fprintf('\n'); -%end % for sgnlop - -for trlop = 1:numtrl - zsum{trlop} = zsum{trlop} ./ sqrt(numsgn); -end - -if strcmp(cfg.artfctdef.zvalue.feedback, 'yes') - % give graphical feedback and allow the user to modify the threshold - interactiveloop = 1; - while interactiveloop - h = figure; - hold on - for trlop=1:numtrl - xval = trl(trlop,1):trl(trlop,2); - if thresholdsum, - yval = zsum{trlop}; - else - yval = zmax{trlop}; - end - plot(xval, yval, 'b-'); - dum = yval<=cfg.artfctdef.zvalue.cutoff; - yval(dum) = nan; - plot(xval, yval, 'r-'); - end - hline(cfg.artfctdef.zvalue.cutoff, 'color', 'r', 'linestyle', ':'); - xlabel('sample number'); - ylabel('cumulative z-value'); - [response, interactiveloop] = smartinput('\nwould you like to page through the data [y/N]? ', 'n'); - artval = {}; - for trlop=1:numtrl - if thresholdsum, - % threshold the accumulated z-values - artval{trlop} = zsum{trlop}>cfg.artfctdef.zvalue.cutoff; - else - % threshold the max z-values - artval{trlop} = zmax{trlop}>cfg.artfctdef.zvalue.cutoff; - end - % pad the artifacts - artbeg = find(diff([0 artval{trlop}])== 1); - artend = find(diff([artval{trlop} 0])==-1); - artbeg = artbeg - artpadding; - artend = artend + artpadding; - artbeg(artbeg<1) = 1; - artend(artend>length(artval{trlop})) = length(artval{trlop}); - for artlop=1:length(artbeg) - artval{trlop}(artbeg(artlop):artend(artlop)) = 1; - end - end - % show the z-values, the artifacts and a selection of the original data - if interactiveloop - if nargin==1, - if ~thresholdsum, zsum = zmax; end; - artifact_viewer(cfg, cfg.artfctdef.zvalue, zsum, artval, zindx); - cfg.artfctdef.zvalue.cutoff = smartinput(sprintf('\ngive new cutoff value, or press enter to accept current value [%g]: ', cfg.artfctdef.zvalue.cutoff), cfg.artfctdef.zvalue.cutoff); - else - if ~thresholdsum, zsum = zmax; end; - artifact_viewer(cfg, cfg.artfctdef.zvalue, zsum, artval, zindx, data); - cfg.artfctdef.zvalue.cutoff = smartinput(sprintf('\ngive new cutoff value, or press enter to accept current value [%g]: ', cfg.artfctdef.zvalue.cutoff), cfg.artfctdef.zvalue.cutoff); - end - end - if ishandle(h), close(h), end; - end % interactiveloop -else - % this code snippet is the same as above, but without the plotting - artval = {}; - for trlop=1:numtrl - if thresholdsum, - % threshold the accumulated z-values - artval{trlop} = zsum{trlop}>cfg.artfctdef.zvalue.cutoff; - else - % threshold the max z-values - artval{trlop} = zmax{trlop}>cfg.artfctdef.zvalue.cutoff; - end - % pad the artifacts - artbeg = find(diff([0 artval{trlop}])== 1); - artend = find(diff([artval{trlop} 0])==-1); - artbeg = artbeg - artpadding; - artend = artend + artpadding; - artbeg(artbeg<1) = 1; - artend(artend>length(artval{trlop})) = length(artval{trlop}); - for artlop=1:length(artbeg) - artval{trlop}(artbeg(artlop):artend(artlop)) = 1; - end - end -end % feedback - -% convert to one long vector -dum = zeros(1,max(trl(:,2))); -for trlop=1:numtrl - dum(trl(trlop,1):trl(trlop,2)) = artval{trlop}; -end -artval = dum; - -% find the padded artifacts and put them in a Nx2 trl-like matrix -artbeg = find(diff([0 artval])== 1); -artend = find(diff([artval 0])==-1); -artifact = [artbeg(:) artend(:)]; - -% remember the artifacts that were found -cfg.artfctdef.zvalue.artifact = artifact; - -fprintf('detected %d artifacts\n', size(artifact,1)); - -% add version information to the configuration -try - % get the full name of the function - cfg.artfctdef.zvalue.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.artfctdef.zvalue.version.name = st(i); -end -cfg.artfctdef.zvalue.version.id = '$Id: artifact_zvalue.m,v 1.21 2009/09/30 12:46:11 jansch Exp $'; - - diff --git a/external/fieldtrip/private/atlas_init.m b/external/fieldtrip/private/atlas_init.m new file mode 100644 index 0000000..fe7814b --- /dev/null +++ b/external/fieldtrip/private/atlas_init.m @@ -0,0 +1,566 @@ +function [atlas] = atlas_init(filename) + +% ATLAS_INIT reads in a specified atlas with coordinates and anatomical +% labels. It either uses the AFNI brik file that is available from +% http://afni.nimh.nih.gov/afni/doc/misc/ttatlas_tlrc, or it uses one of +% the the WFU atlasses available from http://fmri.wfubmc.edu. +% +% Use as: +% [atlas] = atlas_init(filename) +% +% See also ATLAS_LOOKUP, ATLAS_MASK + +% Copyright (C) 2005-2008, Robert Oostenveld, Ingrid Nieuwenhuis +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: atlas_init.m 952 2010-04-21 18:29:51Z roboos $ + +useafni = 0; +usewfu = 0; + +[p, f, x] = fileparts(filename); + +if strcmp(f, 'TTatlas+tlrc') + useafni = 1; +else + usewfu = 1; +end + +if useafni + % check whether the required AFNI toolbox is available + hastoolbox('afni', 1); + + atlas = read_fcdc_mri(filename); + + % the AFNI atlas contains two volumes at 1mm resolution + atlas.brick0 = atlas.anatomy(:,:,:,1); + atlas.brick1 = atlas.anatomy(:,:,:,2); + atlas = rmfield(atlas, 'anatomy'); + atlas.coord = 'tal'; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % the following information is from https://afni.nimh.nih.gov/afni/doc/misc/ttatlas_tlrc + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % column 1 contains sub-brick + % column 2 contains value + % column 3 contains stucture name + % 1 68 Hippocampus + % 1 71 Amygdala + % 0 20 Posterior Cingulate + % 0 21 Anterior Cingulate + % 0 22 Subcallosal Gyrus + % 0 24 Transverse Temporal Gyrus + % 0 25 Uncus + % 0 26 Rectal Gyrus + % 0 27 Fusiform Gyrus + % 0 28 Inferior Occipital Gyrus + % 0 29 Inferior Temporal Gyrus + % 0 30 Insula + % 0 31 Parahippocampal Gyrus + % 0 32 Lingual Gyrus + % 0 33 Middle Occipital Gyrus + % 0 34 Orbital Gyrus + % 0 35 Middle Temporal Gyrus + % 0 36 Superior Temporal Gyrus + % 0 37 Superior Occipital Gyrus + % 0 39 Inferior Frontal Gyrus + % 0 40 Cuneus + % 0 41 Angular Gyrus + % 0 42 Supramarginal Gyrus + % 0 43 Cingulate Gyrus + % 0 44 Inferior Parietal Lobule + % 0 45 Precuneus + % 0 46 Superior Parietal Lobule + % 0 47 Middle Frontal Gyrus + % 0 48 Paracentral Lobule + % 0 49 Postcentral Gyrus + % 0 50 Precentral Gyrus + % 0 51 Superior Frontal Gyrus + % 0 52 Medial Frontal Gyrus + % 0 70 Lentiform Nucleus + % 1 72 Hypothalamus + % 1 73 Red Nucleus + % 1 74 Substantia Nigra + % 0 75 Claustrum + % 0 76 Thalamus + % 0 77 Caudate + % 1 124 Caudate Tail + % 1 125 Caudate Body + % 1 126 Caudate Head + % 1 128 Ventral Anterior Nucleus + % 1 129 Ventral Posterior Medial Nucleus + % 1 130 Ventral Posterior Lateral Nucleus + % 1 131 Medial Dorsal Nucleus + % 1 132 Lateral Dorsal Nucleus + % 1 133 Pulvinar + % 1 134 Lateral Posterior Nucleus + % 1 135 Ventral Lateral Nucleus + % 1 136 Midline Nucleus + % 1 137 Anterior Nucleus + % 1 138 Mammillary Body + % 1 144 Medial Globus Pallidus + % 1 145 Lateral Globus Pallidus + % 1 151 Putamen + % 1 146 Nucleus Accumbens + % 1 147 Medial Geniculum Body + % 1 148 Lateral Geniculum Body + % 1 149 Subthalamic Nucleus + % 1 81 Brodmann area 1 + % 1 82 Brodmann area 2 + % 1 83 Brodmann area 3 + % 1 84 Brodmann area 4 + % 1 85 Brodmann area 5 + % 1 86 Brodmann area 6 + % 1 87 Brodmann area 7 + % 1 88 Brodmann area 8 + % 1 89 Brodmann area 9 + % 1 90 Brodmann area 10 + % 1 91 Brodmann area 11 + % 1 93 Brodmann area 13 + % 1 94 Brodmann area 17 + % 1 95 Brodmann area 18 + % 1 96 Brodmann area 19 + % 1 97 Brodmann area 20 + % 1 98 Brodmann area 21 + % 1 99 Brodmann area 22 + % 1 100 Brodmann area 23 + % 1 101 Brodmann area 24 + % 1 102 Brodmann area 25 + % 1 103 Brodmann area 27 + % 1 104 Brodmann area 28 + % 1 105 Brodmann area 29 + % 1 106 Brodmann area 30 + % 1 107 Brodmann area 31 + % 1 108 Brodmann area 32 + % 1 109 Brodmann area 33 + % 1 110 Brodmann area 34 + % 1 111 Brodmann area 35 + % 1 112 Brodmann area 36 + % 1 113 Brodmann area 37 + % 1 114 Brodmann area 38 + % 1 115 Brodmann area 39 + % 1 116 Brodmann area 40 + % 1 117 Brodmann area 41 + % 1 118 Brodmann area 42 + % 1 119 Brodmann area 43 + % 1 120 Brodmann area 44 + % 1 121 Brodmann area 45 + % 1 122 Brodmann area 46 + % 1 123 Brodmann area 47 + % 0 53 Uvula of Vermis + % 0 54 Pyramis of Vermis + % 0 55 Tuber of Vermis + % 0 56 Declive of Vermis + % 0 57 Culmen of Vermis + % 0 58 Cerebellar Tonsil + % 0 59 Inferior Semi-Lunar Lobule + % 0 60 Fastigium + % 0 61 Nodule + % 0 62 Uvula + % 0 63 Pyramis + % 0 66 Culmen + % 0 65 Declive + % 1 127 Dentate + % 0 64 Tuber + % 0 67 Cerebellar Lingual + + atlas.descr.brick = [ + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + ]; + + atlas.descr.value = [ + 68 + 71 + 20 + 21 + 22 + 24 + 25 + 26 + 27 + 28 + 29 + 30 + 31 + 32 + 33 + 34 + 35 + 36 + 37 + 39 + 40 + 41 + 42 + 43 + 44 + 45 + 46 + 47 + 48 + 49 + 50 + 51 + 52 + 70 + 72 + 73 + 74 + 75 + 76 + 77 + 124 + 125 + 126 + 128 + 129 + 130 + 131 + 132 + 133 + 134 + 135 + 136 + 137 + 138 + 144 + 145 + 151 + 146 + 147 + 148 + 149 + 81 + 82 + 83 + 84 + 85 + 86 + 87 + 88 + 89 + 90 + 91 + 93 + 94 + 95 + 96 + 97 + 98 + 99 + 100 + 101 + 102 + 103 + 104 + 105 + 106 + 107 + 108 + 109 + 110 + 111 + 112 + 113 + 114 + 115 + 116 + 117 + 118 + 119 + 120 + 121 + 122 + 123 + 53 + 54 + 55 + 56 + 57 + 58 + 59 + 60 + 61 + 62 + 63 + 66 + 65 + 127 + 64 + 67 + ]; + + atlas.descr.name = { + 'Hippocampus' + 'Amygdala' + 'Posterior Cingulate' + 'Anterior Cingulate' + 'Subcallosal Gyrus' + 'Transverse Temporal Gyrus' + 'Uncus' + 'Rectal Gyrus' + 'Fusiform Gyrus' + 'Inferior Occipital Gyrus' + 'Inferior Temporal Gyrus' + 'Insula' + 'Parahippocampal Gyrus' + 'Lingual Gyrus' + 'Middle Occipital Gyrus' + 'Orbital Gyrus' + 'Middle Temporal Gyrus' + 'Superior Temporal Gyrus' + 'Superior Occipital Gyrus' + 'Inferior Frontal Gyrus' + 'Cuneus' + 'Angular Gyrus' + 'Supramarginal Gyrus' + 'Cingulate Gyrus' + 'Inferior Parietal Lobule' + 'Precuneus' + 'Superior Parietal Lobule' + 'Middle Frontal Gyrus' + 'Paracentral Lobule' + 'Postcentral Gyrus' + 'Precentral Gyrus' + 'Superior Frontal Gyrus' + 'Medial Frontal Gyrus' + 'Lentiform Nucleus' + 'Hypothalamus' + 'Red Nucleus' + 'Substantia Nigra' + 'Claustrum' + 'Thalamus' + 'Caudate' + 'Caudate Tail' + 'Caudate Body' + 'Caudate Head' + 'Ventral Anterior Nucleus' + 'Ventral Posterior Medial Nucleus' + 'Ventral Posterior Lateral Nucleus' + 'Medial Dorsal Nucleus' + 'Lateral Dorsal Nucleus' + 'Pulvinar' + 'Lateral Posterior Nucleus' + 'Ventral Lateral Nucleus' + 'Midline Nucleus' + 'Anterior Nucleus' + 'Mammillary Body' + 'Medial Globus Pallidus' + 'Lateral Globus Pallidus' + 'Putamen' + 'Nucleus Accumbens' + 'Medial Geniculum Body' + 'Lateral Geniculum Body' + 'Subthalamic Nucleus' + 'Brodmann area 1' + 'Brodmann area 2' + 'Brodmann area 3' + 'Brodmann area 4' + 'Brodmann area 5' + 'Brodmann area 6' + 'Brodmann area 7' + 'Brodmann area 8' + 'Brodmann area 9' + 'Brodmann area 10' + 'Brodmann area 11' + 'Brodmann area 13' + 'Brodmann area 17' + 'Brodmann area 18' + 'Brodmann area 19' + 'Brodmann area 20' + 'Brodmann area 21' + 'Brodmann area 22' + 'Brodmann area 23' + 'Brodmann area 24' + 'Brodmann area 25' + 'Brodmann area 27' + 'Brodmann area 28' + 'Brodmann area 29' + 'Brodmann area 30' + 'Brodmann area 31' + 'Brodmann area 32' + 'Brodmann area 33' + 'Brodmann area 34' + 'Brodmann area 35' + 'Brodmann area 36' + 'Brodmann area 37' + 'Brodmann area 38' + 'Brodmann area 39' + 'Brodmann area 40' + 'Brodmann area 41' + 'Brodmann area 42' + 'Brodmann area 43' + 'Brodmann area 44' + 'Brodmann area 45' + 'Brodmann area 46' + 'Brodmann area 47' + 'Uvula of Vermis' + 'Pyramis of Vermis' + 'Tuber of Vermis' + 'Declive of Vermis' + 'Culmen of Vermis' + 'Cerebellar Tonsil' + 'Inferior Semi-Lunar Lobule' + 'Fastigium' + 'Nodule' + 'Uvula' + 'Pyramis' + 'Culmen' + 'Declive' + 'Dentate' + 'Tuber' + 'Cerebellar Lingual' + }; + +elseif usewfu + atlas = read_fcdc_mri(filename); % /home/... works, ~/.... does not work + atlas.brick0 = atlas.anatomy(:,:,:); + atlas = rmfield(atlas, 'anatomy'); + atlas.coord = 'mni'; + + % the WFU atlas contains a single atlas volume at 2mm resolution + % to keep it compatible with the existing code, add a dummy atlas volume + atlas.brick1 = zeros(size(atlas.brick0)); + + [p, f, x] = fileparts(filename); + f = [f '_List.mat']; + load(fullfile(p, f)); + + atlas.descr = []; + atlas.descr.brick = zeros(length(ROI),1); + atlas.descr.value = [ROI.ID]'; + atlas.descr.name = {ROI.Nom_C}'; % what is difference between Nom_C and Nom_L?? +end diff --git a/external/fieldtrip/private/atlas_lookup.m b/external/fieldtrip/private/atlas_lookup.m new file mode 100644 index 0000000..4143fe6 --- /dev/null +++ b/external/fieldtrip/private/atlas_lookup.m @@ -0,0 +1,101 @@ +function [label] = atlas_lookup(atlas, pos, varargin) + +% ATLAS_LOOKUP determines the anatomical label of a location in the given atlas. +% +% Use as +% atlas = atlas_init(filename); +% label = atlas_lookup(atlas, pos, ...); +% +% Optinal input arguments should come in key-value pairs and can include +% 'queryrange' = number, should be 1, 3, 5, 7, 9 or 11 (default = 3) +% 'inputcoord' = 'mni' or 'tal' (default = []) +% +% Dependent on the input coordinates and the coordinates of the atlas, the +% input positions are transformed betweem MNI and Talairach-Tournoux coordinates. +% See http://www.mrc-cbu.cam.ac.uk/Imaging/Common/mnispace.shtml for more details. +% +% See also ATLAS_INIT, ATLAS_MASK + +% Copyright (C) 2005-2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: atlas_lookup.m 952 2010-04-21 18:29:51Z roboos $ + +% get the optional input arguments +queryrange = keyval('queryrange', varargin); if isempty(queryrange), queryrange = 3; end +inputcoord = keyval('inputcoord', varargin); if isempty(inputcoord), error('specify inputcoord'); end + +if isempty(intersect(queryrange, [1 3 5 7 9 11])) + error('incorrect query range, should be one of [1 3 5 7 9 11]'); +end + +if size(pos,1)==3 && size(pos,2)~=3 + % transpose the input positions to get Nx3 + pos = pos'; +end + +% convert between MNI head coordinates and TAL head coordinates +% coordinates should be expressed compatible with the atlas +if strcmp(inputcoord, 'mni') && strcmp(atlas.coord, 'tal') + pos = mni2tal(pos')'; % this function likes 3xN +elseif strcmp(inputcoord, 'mni') && strcmp(atlas.coord, 'mni') + % nothing to do +elseif strcmp(inputcoord, 'tal') && strcmp(atlas.coord, 'tal') + % nothing to do +elseif strcmp(inputcoord, 'tal') && strcmp(atlas.coord, 'mni') + pos = tal2mni(pos')'; % this function likes 3xN +end + +num = size(pos,1); +sel = []; + +% convert the atlas head coordinates into voxel coordinates +vox = inv(atlas.transform) * [pos ones(num,1)]'; +vox = vox(1:3,:)'; + +for i=1:num + + % this is the center voxel + ijk_center = vox(i,:); + + for di=(-(queryrange-1)/2):1:((queryrange-1)/2) + for dj=(-(queryrange-1)/2):1:((queryrange-1)/2) + for dk=(-(queryrange-1)/2):1:((queryrange-1)/2) + + % search in a cube around the center voxel + ijk = round(ijk_center + [di dj dk]); + + if ijk(1)>=1 && ijk(1)<=atlas.dim(1) && ... + ijk(2)>=1 && ijk(2)<=atlas.dim(2) && ... + ijk(3)>=1 && ijk(3)<=atlas.dim(3) + brick0_val = atlas.brick0(ijk(1), ijk(2), ijk(3)); + brick1_val = atlas.brick1(ijk(1), ijk(2), ijk(3)); + sel = [sel; find(atlas.descr.brick==0 & atlas.descr.value==brick0_val)]; + sel = [sel; find(atlas.descr.brick==1 & atlas.descr.value==brick1_val)]; + else + warning('location is outside atlas volume'); + end + + end % dk + end % dj + end % di + +end + +label = unique(atlas.descr.name(sel)); + diff --git a/external/fieldtrip/private/atlas_mask.m b/external/fieldtrip/private/atlas_mask.m new file mode 100644 index 0000000..a6002c2 --- /dev/null +++ b/external/fieldtrip/private/atlas_mask.m @@ -0,0 +1,117 @@ +function [mask] = atlas_mask(atlas, mri, label, varargin) + +% ATLAS_MASK creates a mask that can be used in visualizing a functional +% and/or anatomical MRI volume. +% +% Use as +% atlas = atlas_init; +% mask = atlas_mask(atlas, mri, label, ...); +% +% Optinal input arguments should come in key-value pairs and can include +% 'inputcoord' = 'mni' or 'tal' (default = []); +% +% Dependent on the input coordinates and the coordinates of the atlas, the +% input MRI is transformed betweem MNI and Talairach-Tournoux coordinates +% See http://www.mrc-cbu.cam.ac.uk/Imaging/Common/mnispace.shtml for more details. +% +% See also ATLAS_INIT, ATLAS_LOOKUP + +% Copyright (C) 2005-2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: atlas_mask.m 952 2010-04-21 18:29:51Z roboos $ + +% get the optional input arguments +inputcoord = keyval('inputcoord', varargin); if isempty(inputcoord), error('specify inputcoord'); end + +if ischar(label) + label = {label}; +end + +sel = []; +for i=1:length(label) + sel = [sel; strmatch(label{i}, atlas.descr.name, 'exact')]; +end + +fprintf('found %d matching anatomical labels\n', length(sel)); + +brick = atlas.descr.brick(sel); +value = atlas.descr.value(sel); + +if isfield(mri, 'transform') && isfield(mri, 'dim') + dim = mri.dim; + % determine location of each anatomical voxel in its own voxel coordinates + i = 1:dim(1); + j = 1:dim(2); + k = 1:dim(3); + [I, J, K] = ndgrid(i, j, k); + ijk = [I(:) J(:) K(:) ones(prod(dim),1)]'; + % determine location of each anatomical voxel in head coordinates + xyz = mri.transform * ijk; % note that this is 4xN +elseif isfield(mri, 'pos') + % the individual positions of every grid point are specified + npos = size(mri.pos,1); + dim = [npos 1]; + xyz = [mri.pos ones(npos,1)]'; % note that this is 4xN +else + error('could not determine whether the input describes a volume or a source'); +end + +% convert between MNI head coordinates and TAL head coordinates +% coordinates should be expressed compatible with the atlas +if strcmp(inputcoord, 'mni') && strcmp(atlas.coord, 'tal') + xyz(1:3,:) = mni2tal(xyz(1:3,:)); +elseif strcmp(inputcoord, 'mni') && strcmp(atlas.coord, 'mni') + % nothing to do +elseif strcmp(inputcoord, 'tal') && strcmp(atlas.coord, 'tal') + % nothing to do +elseif strcmp(inputcoord, 'tal') && strcmp(atlas.coord, 'mni') + xyz(1:3,:) = tal2mni(xyz(1:3,:)); +end + +% determine location of each anatomical voxel in atlas voxel coordinates +ijk = inv(atlas.transform) * xyz; +ijk = round(ijk(1:3,:))'; + +inside_vol = ijk(:,1)>=1 & ijk(:,1)<=atlas.dim(1) & ... + ijk(:,2)>=1 & ijk(:,2)<=atlas.dim(2) & ... + ijk(:,3)>=1 & ijk(:,3)<=atlas.dim(3); +inside_vol = find(inside_vol); + +% convert the selection inside the atlas volume into linear indices +ind = sub2ind(atlas.dim, ijk(inside_vol,1), ijk(inside_vol,2), ijk(inside_vol,3)); + +brick0_val = zeros(prod(dim),1); +brick1_val = zeros(prod(dim),1); +% search the two bricks for the value of each voxel +brick0_val(inside_vol) = atlas.brick0(ind); +brick1_val(inside_vol) = atlas.brick1(ind); + +mask = zeros(prod(dim),1); +for i=1:length(sel) + fprintf('constructing mask for %s\n', atlas.descr.name{sel(i)}); + if brick(i)==0 + mask = mask | (brick0_val==value(i)); + elseif brick(i)==1 + mask = mask | (brick1_val==value(i)); + end +end +mask = reshape(mask, dim); + +fprintf('masked %.1f %% of total volume\n', 100*mean(mask(:))); + diff --git a/external/fieldtrip/private/avgref.m b/external/fieldtrip/private/avgref.m index 558db08..eba47f2 100644 --- a/external/fieldtrip/private/avgref.m +++ b/external/fieldtrip/private/avgref.m @@ -1,18 +1,31 @@ function [data] = avgref(data, sel); % AVGREF computes the average reference in each column -% [data] = avgref(data) +% [data] = avgref(data) % % or it computes the re-referenced data relative to the % average over the selected channels -% [data] = avgref(data, sel) +% [data] = avgref(data, sel) % Copyright (C) 1998-2002, Robert Oostenveld % -% $Log: avgref.m,v $ -% Revision 1.2 2003/03/17 10:37:28 roberto -% improved general help comments and added copyrights +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: avgref.m 946 2010-04-21 17:51:16Z roboos $ % determine the dimension of the data if length(size(data))==3 diff --git a/external/fieldtrip/private/avw_hdr_make.m b/external/fieldtrip/private/avw_hdr_make.m new file mode 100644 index 0000000..301c5f6 --- /dev/null +++ b/external/fieldtrip/private/avw_hdr_make.m @@ -0,0 +1,118 @@ +function [ avw ] = avw_hdr_make + +% AVW_HDR_MAKE - Create Analyze format data header (avw.hdr) +% +% [ avw ] = avw_hdr_make +% +% avw.hdr - a struct, all fields returned from the header. +% For details, find a good description on the web +% or see the Analyze File Format pdf in the +% mri_toolbox doc folder or see avw_hdr_read.m +% +% See also, AVW_HDR_READ AVW_HDR_WRITE +% AVW_IMG_READ AVW_IMG_WRITE +% + +% $Revision: 883 $ $Date: 2009/01/14 09:24:45 $ + +% Licence: GNU GPL, no express or implied warranties +% History: 06/2002, Darren.Weber@flinders.edu.au +% 02/2003, Darren.Weber@flinders.edu.au +% date/time bug at lines 97-98 +% identified by Bennett.Landman@ieee.org +% +% The Analyze format is copyright +% (c) Copyright, 1986-1995 +% Biomedical Imaging Resource, Mayo Foundation +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +version = '[$Revision: 883 $]'; +fprintf('\nAVW_HDR_MAKE [v%s]\n',version(12:16)); tic; + + +% Comments +% The header format is flexible and can be extended for new +% user-defined data types. The essential structures of the header +% are the header_key and the image_dimension. See avw_hdr_read +% for more detail of the header structure +avw.hdr = make_header; + +t=toc; fprintf('...done (%5.2f sec).\n',t); + +return + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [ hdr ] = make_header + + hdr.hk = header_key; + hdr.dime = image_dimension; + hdr.hist = data_history; + +return + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [hk] = header_key + + hk.sizeof_hdr = int32(348); % must be 348! + hk.data_type(1:10) = sprintf('%10s',''); + hk.db_name(1:18) = sprintf('%18s',''); + hk.extents = int32(16384); + hk.session_error = int16(0); + hk.regular = sprintf('%1s','r'); % might be uint8 + hk.hkey_un0 = uint8(0); + +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [ dime ] = image_dimension + + dime.dim(1:8) = int16([4 256 256 256 1 0 0 0]); + dime.vox_units(1:4) = sprintf('%4s','mm'); + dime.cal_units(1:8) = sprintf('%8s',''); + dime.unused1 = int16(0); + dime.datatype = int16(2); + dime.bitpix = int16(8); + dime.dim_un0 = int16(0); + dime.pixdim(1:8) = single([0 1 1 1 1000 0 0 0]); + dime.vox_offset = single(0); + dime.funused1 = single(0); + dime.funused2 = single(0); + % Set default 8bit intensity scale (from MRIcro), otherwise funused3 + dime.roi_scale = single(1); + dime.cal_max = single(0); + dime.cal_min = single(0); + dime.compressed = int32(0); + dime.verified = int32(0); + dime.glmax = int32(255); + dime.glmin = int32(0); + +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [ hist ] = data_history + + datime = clock; + + hist.descrip(1:80) = sprintf('%-80s','mri_toolbox @ http://eeg.sf.net/'); + hist.aux_file(1:24) = sprintf('%-24s',''); + hist.orient = uint8(0); % sprintf( '%1s',''); % see notes in avw_hdr_read + hist.originator(1:10) = sprintf('%-10s',''); + hist.generated(1:10) = sprintf('%-10s','mri_toolbx'); + hist.scannum(1:10) = sprintf('%-10s',''); + hist.patient_id(1:10) = sprintf('%-10s',''); + hist.exp_date(1:10) = sprintf('%02d-%02d-%04d',datime(3),datime(2),datime(1)); + hist.exp_time(1:10) = sprintf('%02d-%02d-%04.1f',datime(4),datime(5),datime(6)); + hist.hist_un0(1:3) = sprintf( '%-3s',''); + hist.views = int32(0); + hist.vols_added = int32(0); + hist.start_field = int32(0); + hist.field_skip = int32(0); + hist.omax = int32(0); + hist.omin = int32(0); + hist.smax = int32(0); + hist.smin = int32(0); + +return diff --git a/external/fieldtrip/private/avw_hdr_read.m b/external/fieldtrip/private/avw_hdr_read.m new file mode 100644 index 0000000..10e2a65 --- /dev/null +++ b/external/fieldtrip/private/avw_hdr_read.m @@ -0,0 +1,389 @@ +function [ avw, machine ] = avw_hdr_read(fileprefix, machine, verbose) + +% avw_hdr_read - read Analyze format data header (*.hdr) +% +% [ avw, machine ] = avw_hdr_read(fileprefix, [machine], [verbose]) +% +% fileprefix - string filename (without .hdr); the file name +% can be given as a full path or relative to the +% current directory. +% +% machine - a string, see machineformat in fread for details. +% The default here is 'ieee-le' but the routine +% will automatically switch between little and big +% endian to read any such Analyze header. It +% reports the appropriate machine format and can +% return the machine value. +% +% avw.hdr - a struct, all fields returned from the header. +% For details, find a good description on the web +% or see the Analyze File Format pdf in the +% mri_toolbox doc folder or read this .m file. +% +% verbose - the default is to output processing information to the command +% window. If verbose = 0, this will not happen. +% +% This function is called by avw_img_read +% +% See also avw_hdr_write, avw_hdr_make, avw_view_hdr, avw_view +% + +% $Revision: 883 $ $Date: 2009/01/14 09:24:45 $ + +% Licence: GNU GPL, no express or implied warranties +% History: 05/2002, Darren.Weber@flinders.edu.au +% The Analyze format and c code below is copyright +% (c) Copyright, 1986-1995 +% Biomedical Imaging Resource, Mayo Foundation +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +if ~exist('verbose','var'), verbose = 1; end + +if verbose, + version = '[$Revision: 883 $]'; + fprintf('\nAVW_HDR_READ [v%s]\n',version(12:16)); tic; +end + +if ~exist('fileprefix','var'), + msg = sprintf('...no input fileprefix - see help avw_hdr_read\n\n'); + error(msg); +end +if ~exist('machine','var'), machine = 'ieee-le'; end + + +if findstr('.hdr',fileprefix), + % fprintf('...removing .hdr extension from ''%s''\n',fileprefix); + fileprefix = strrep(fileprefix,'.hdr',''); +end +if findstr('.img',fileprefix), + % fprintf('...removing .img extension from ''%s''\n',fileprefix); + fileprefix = strrep(fileprefix,'.img',''); +end +file = sprintf('%s.hdr',fileprefix); + +if exist(file), + if verbose, + fprintf('...reading %s Analyze format',machine); + end + fid = fopen(file,'r',machine); + avw.hdr = read_header(fid,verbose); + avw.fileprefix = fileprefix; + fclose(fid); + + if ~isequal(avw.hdr.hk.sizeof_hdr,348), + if verbose, fprintf('...failed.\n'); end + % first try reading the opposite endian to 'machine' + switch machine, + case 'ieee-le', machine = 'ieee-be'; + case 'ieee-be', machine = 'ieee-le'; + end + if verbose, fprintf('...reading %s Analyze format',machine); end + fid = fopen(file,'r',machine); + avw.hdr = read_header(fid,verbose); + avw.fileprefix = fileprefix; + fclose(fid); + end + if ~isequal(avw.hdr.hk.sizeof_hdr,348), + % Now throw an error + if verbose, fprintf('...failed.\n'); end + msg = sprintf('...size of header not equal to 348 bytes!\n\n'); + error(msg); + end +else + msg = sprintf('...cannot find file %s.hdr\n\n',file); + error(msg); +end + +if verbose, + t=toc; fprintf('...done (%5.2f sec).\n',t); +end + +return + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [ dsr ] = read_header(fid,verbose) + + % Original header structures - ANALYZE 7.5 + %struct dsr + % { + % struct header_key hk; /* 0 + 40 */ + % struct image_dimension dime; /* 40 + 108 */ + % struct data_history hist; /* 148 + 200 */ + % }; /* total= 348 bytes*/ + dsr.hk = header_key(fid); + dsr.dime = image_dimension(fid,verbose); + dsr.hist = data_history(fid); + +return + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [hk] = header_key(fid) + + % The required elements in the header_key substructure are: + % + % int sizeof_header Must indicate the byte size of the header file. + % int extents Should be 16384, the image file is created as + % contiguous with a minimum extent size. + % char regular Must be 'r' to indicate that all images and + % volumes are the same size. + + % Original header structures - ANALYZE 7.5 + % struct header_key /* header key */ + % { /* off + size */ + % int sizeof_hdr /* 0 + 4 */ + % char data_type[10]; /* 4 + 10 */ + % char db_name[18]; /* 14 + 18 */ + % int extents; /* 32 + 4 */ + % short int session_error; /* 36 + 2 */ + % char regular; /* 38 + 1 */ + % char hkey_un0; /* 39 + 1 */ + % }; /* total=40 bytes */ + + fseek(fid,0,'bof'); + + hk.sizeof_hdr = fread(fid, 1,'*int32'); % should be 348! + hk.data_type = fread(fid,10,'*char')'; + hk.db_name = fread(fid,18,'*char')'; + hk.extents = fread(fid, 1,'*int32'); + hk.session_error = fread(fid, 1,'*int16'); + hk.regular = fread(fid, 1,'*char')'; % might be uint8 + hk.hkey_un0 = fread(fid, 1,'*uint8')'; + + % check if this value was a char zero + if hk.hkey_un0 == 48, + hk.hkey_un0 = 0; + end + +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [ dime ] = image_dimension(fid,verbose) + + %struct image_dimension + % { /* off + size */ + % short int dim[8]; /* 0 + 16 */ + % /* + % dim[0] Number of dimensions in database; usually 4. + % dim[1] Image X dimension; number of *pixels* in an image row. + % dim[2] Image Y dimension; number of *pixel rows* in slice. + % dim[3] Volume Z dimension; number of *slices* in a volume. + % dim[4] Time points; number of volumes in database + % */ + % char vox_units[4]; /* 16 + 4 */ + % char cal_units[8]; /* 20 + 8 */ + % short int unused1; /* 28 + 2 */ + % short int datatype; /* 30 + 2 */ + % short int bitpix; /* 32 + 2 */ + % short int dim_un0; /* 34 + 2 */ + % float pixdim[8]; /* 36 + 32 */ + % /* + % pixdim[] specifies the voxel dimensions: + % pixdim[1] - voxel width, mm + % pixdim[2] - voxel height, mm + % pixdim[3] - slice thickness, mm + % pixdim[4] - volume timing, in msec + % ..etc + % */ + % float vox_offset; /* 68 + 4 */ + % float roi_scale; /* 72 + 4 */ + % float funused1; /* 76 + 4 */ + % float funused2; /* 80 + 4 */ + % float cal_max; /* 84 + 4 */ + % float cal_min; /* 88 + 4 */ + % int compressed; /* 92 + 4 */ + % int verified; /* 96 + 4 */ + % int glmax; /* 100 + 4 */ + % int glmin; /* 104 + 4 */ + % }; /* total=108 bytes */ + + dime.dim = fread(fid,8,'*int16')'; + dime.vox_units = fread(fid,4,'*char')'; + dime.cal_units = fread(fid,8,'*char')'; + dime.unused1 = fread(fid,1,'*int16'); + dime.datatype = fread(fid,1,'*int16'); + dime.bitpix = fread(fid,1,'*int16'); + dime.dim_un0 = fread(fid,1,'*int16'); + dime.pixdim = fread(fid,8,'*float')'; + dime.vox_offset = fread(fid,1,'*float'); + dime.roi_scale = fread(fid,1,'*float'); + dime.funused1 = fread(fid,1,'*float'); + dime.funused2 = fread(fid,1,'*float'); + dime.cal_max = fread(fid,1,'*float'); + dime.cal_min = fread(fid,1,'*float'); + dime.compressed = fread(fid,1,'*int32'); + dime.verified = fread(fid,1,'*int32'); + dime.glmax = fread(fid,1,'*int32'); + dime.glmin = fread(fid,1,'*int32'); + + if dime.dim(1) < 4, % Number of dimensions in database; usually 4. + if verbose, + fprintf('...ensuring 4 dimensions in avw.hdr.dime.dim\n'); + end + dime.dim(1) = int16(4); + end + if dime.dim(5) < 1, % Time points; number of volumes in database + if verbose, + fprintf('...ensuring at least 1 volume in avw.hdr.dime.dim(5)\n'); + end + dime.dim(5) = int16(1); + end + +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [ hist ] = data_history(fid) + + % Original header structures - ANALYZE 7.5 + %struct data_history + % { /* off + size */ + % char descrip[80]; /* 0 + 80 */ + % char aux_file[24]; /* 80 + 24 */ + % char orient; /* 104 + 1 */ + % char originator[10]; /* 105 + 10 */ + % char generated[10]; /* 115 + 10 */ + % char scannum[10]; /* 125 + 10 */ + % char patient_id[10]; /* 135 + 10 */ + % char exp_date[10]; /* 145 + 10 */ + % char exp_time[10]; /* 155 + 10 */ + % char hist_un0[3]; /* 165 + 3 */ + % int views /* 168 + 4 */ + % int vols_added; /* 172 + 4 */ + % int start_field; /* 176 + 4 */ + % int field_skip; /* 180 + 4 */ + % int omax; /* 184 + 4 */ + % int omin; /* 188 + 4 */ + % int smax; /* 192 + 4 */ + % int smin; /* 196 + 4 */ + % }; /* total=200 bytes */ + + hist.descrip = fread(fid,80,'*char')'; + hist.aux_file = fread(fid,24,'*char')'; + hist.orient = fread(fid, 1,'*uint8'); % see note below on char + hist.originator = fread(fid,10,'*char')'; + hist.generated = fread(fid,10,'*char')'; + hist.scannum = fread(fid,10,'*char')'; + hist.patient_id = fread(fid,10,'*char')'; + hist.exp_date = fread(fid,10,'*char')'; + hist.exp_time = fread(fid,10,'*char')'; + hist.hist_un0 = fread(fid, 3,'*char')'; + hist.views = fread(fid, 1,'*int32'); + hist.vols_added = fread(fid, 1,'*int32'); + hist.start_field = fread(fid, 1,'*int32'); + hist.field_skip = fread(fid, 1,'*int32'); + hist.omax = fread(fid, 1,'*int32'); + hist.omin = fread(fid, 1,'*int32'); + hist.smax = fread(fid, 1,'*int32'); + hist.smin = fread(fid, 1,'*int32'); + + % check if hist.orient was saved as ascii char value + switch hist.orient, + case 48, hist.orient = uint8(0); + case 49, hist.orient = uint8(1); + case 50, hist.orient = uint8(2); + case 51, hist.orient = uint8(3); + case 52, hist.orient = uint8(4); + case 53, hist.orient = uint8(5); + end + +return + + +% Note on using char: +% The 'char orient' field in the header is intended to +% hold simply an 8-bit unsigned integer value, not the ASCII representation +% of the character for that value. A single 'char' byte is often used to +% represent an integer value in Analyze if the known value range doesn't +% go beyond 0-255 - saves a byte over a short int, which may not mean +% much in today's computing environments, but given that this format +% has been around since the early 1980's, saving bytes here and there on +% older systems was important! In this case, 'char' simply provides the +% byte of storage - not an indicator of the format for what is stored in +% this byte. Generally speaking, anytime a single 'char' is used, it is +% probably meant to hold an 8-bit integer value, whereas if this has +% been dimensioned as an array, then it is intended to hold an ASCII +% character string, even if that was only a single character. +% Denny + + +% Comments +% The header format is flexible and can be extended for new +% user-defined data types. The essential structures of the header +% are the header_key and the image_dimension. +% + +% The required elements in the header_key substructure are: +% +% int sizeof_header Must indicate the byte size of the header file. +% int extents Should be 16384, the image file is created as +% contiguous with a minimum extent size. +% char regular Must be 'r' to indicate that all images and +% volumes are the same size. +% + +% The image_dimension substructure describes the organization and +% size of the images. These elements enable the database to reference +% images by volume and slice number. Explanation of each element follows: +% +% short int dim[ ]; /* Array of the image dimensions */ +% +% dim[0] Number of dimensions in database; usually 4. +% dim[1] Image X dimension; number of pixels in an image row. +% dim[2] Image Y dimension; number of pixel rows in slice. +% dim[3] Volume Z dimension; number of slices in a volume. +% dim[4] Time points; number of volumes in database. +% dim[5] Undocumented. +% dim[6] Undocumented. +% dim[7] Undocumented. +% +% char vox_units[4] Specifies the spatial units of measure for a voxel. +% char cal_units[8] Specifies the name of the calibration unit. +% short int unused1 /* Unused */ +% short int datatype /* Datatype for this image set */ +% /*Acceptable values for datatype are*/ +% #define DT_NONE 0 +% #define DT_UNKNOWN 0 /*Unknown data type*/ +% #define DT_BINARY 1 /*Binary ( 1 bit per voxel)*/ +% #define DT_UNSIGNED_CHAR 2 /*Unsigned character ( 8 bits per voxel)*/ +% #define DT_SIGNED_SHORT 4 /*Signed short (16 bits per voxel)*/ +% #define DT_SIGNED_INT 8 /*Signed integer (32 bits per voxel)*/ +% #define DT_FLOAT 16 /*Floating point (32 bits per voxel)*/ +% #define DT_COMPLEX 32 /*Complex (64 bits per voxel; 2 floating point numbers)/* +% #define DT_DOUBLE 64 /*Double precision (64 bits per voxel)*/ +% #define DT_RGB 128 /*A Red-Green-Blue datatype*/ +% #define DT_ALL 255 /*Undocumented*/ +% +% short int bitpix; /* Number of bits per pixel; 1, 8, 16, 32, or 64. */ +% short int dim_un0; /* Unused */ +% +% float pixdim[]; Parallel array to dim[], giving real world measurements in mm and ms. +% pixdim[0]; Pixel dimensions? +% pixdim[1]; Voxel width in mm. +% pixdim[2]; Voxel height in mm. +% pixdim[3]; Slice thickness in mm. +% pixdim[4]; timeslice in ms (ie, TR in fMRI). +% pixdim[5]; Undocumented. +% pixdim[6]; Undocumented. +% pixdim[7]; Undocumented. +% +% float vox_offset; Byte offset in the .img file at which voxels start. This value can be +% negative to specify that the absolute value is applied for every image +% in the file. +% +% float roi_scale; Specifies the Region Of Interest scale? +% float funused1; Undocumented. +% float funused2; Undocumented. +% +% float cal_max; Specifies the upper bound of the range of calibration values. +% float cal_min; Specifies the lower bound of the range of calibration values. +% +% int compressed; Undocumented. +% int verified; Undocumented. +% +% int glmax; The maximum pixel value for the entire database. +% int glmin; The minimum pixel value for the entire database. +% +% diff --git a/external/fieldtrip/private/avw_hdr_write.m b/external/fieldtrip/private/avw_hdr_write.m new file mode 100644 index 0000000..92239ef --- /dev/null +++ b/external/fieldtrip/private/avw_hdr_write.m @@ -0,0 +1,427 @@ +function avw_hdr_write(avw, fileprefix, machine, verbose) + +% AVW_HDR_WRITE - Write Analyze header file (*.hdr) +% +% avw_hdr_write(avw,[fileprefix],[machine],[verbose]) +% +% eg, avw_hdr_write(avw,'test'); +% +% avw - a struct with .hdr field, which itself is a struct, +% containing all fields of an Analyze header. +% For details, see avw_hdr_read.m +% +% fileprefix - a string, the filename without the .hdr extension. +% If empty, may use avw.fileprefix +% +% machine - a string, see machineformat in fread for details. +% The default here is 'ieee-le'. +% +% verbose - the default is to output processing information to the command +% window. If verbose = 0, this will not happen. +% +% See also, AVW_HDR_READ AVW_HDR_MAKE +% AVW_IMG_READ AVW_IMG_WRITE +% + +% $Revision: 883 $ $Date: 2009/01/14 09:24:45 $ + +% Licence: GNU GPL, no express or implied warranties +% History: 05/2002, Darren.Weber@flinders.edu.au +% 02/2003, Bennett.Landman@ieee.org +% - more specific data history var sizes +% - 02/2003 confirmed, Darren +% +% The Analyze format and c code below is copyright +% (c) Copyright, 1986-1995 +% Biomedical Imaging Resource, Mayo Foundation +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +if ~exist('verbose','var'), verbose = 1; end +if ~exist('machine','var'), machine = 'ieee-le'; end + +if verbose, + version = '[$Revision: 883 $]'; + fprintf('AVW_HDR_WRITE [v%s]\n',version(12:16)); tic; +end + +%---------------------------------------------------------------------------- +% Check inputs + +if ~exist('avw','var'), + warning('...no input avw - calling avw_hdr_make\n'); + avw = avw_hdr_make; +elseif isempty(avw), + warning('...empty input avw - calling avw_hdr_make\n'); + avw = avw_hdr_make; +elseif ~isfield(avw,'hdr'), + warning('...empty input avw.hdr - calling avw_hdr_make\n'); + avw = avw_hdr_make; +end +if ~isequal(avw.hdr.hk.sizeof_hdr,348), + msg = sprintf('...avw.hdr.hk.sizeof_hdr must be 348!\n'); + error(msg); +end + +quit = 0; +if ~exist('fileprefix','var'), + if isfield(avw,'fileprefix'), + if ~isempty(avw.fileprefix), + fileprefix = avw.fileprefix; + else, + quit = 1; + end + else + quit = 1; + end + if quit, + helpwin avw_hdr_write; + error('...no input fileprefix - see help avw_hdr_write\n\n'); + return; + end +end + +if findstr('.hdr',fileprefix), +% fprintf('AVW_HDR_WRITE: Removing .hdr extension from ''%s''\n',fileprefix); + fileprefix = strrep(fileprefix,'.hdr',''); +end + + + +%---------------------------------------------------------------------------- +% MAIN + +if verbose, tic; end + + +% % force volume to 4D if necessary; conforms to AVW standard. i lifted this +% % code from mri_toolbox/avw_hdr_read.m and modified it just a little bit +% % (using minDim = 4; etc) +% minDim = 4; +% currDim = double(avw.hdr.dime.dim(1)); +% if ( currDim < minDim ) +% % fprintf( 'Warning %s: Forcing %d dimensions in avw.hdr.dime.dim\n', ... +% % mfilename, minDim ); +% avw.hdr.dime.dim(1) = int16(minDim); +% avw.hdr.dime.dim(currDim+2:minDim+1) = int16(1); +% avw.hdr.dime.pixdim(1) = int16(minDim); +% avw.hdr.dime.pixdim(currDim+2:minDim+1) = int16(1); +% end; + + +fid = fopen(sprintf('%s.hdr',fileprefix),'w',machine); +if fid < 0, + msg = sprintf('Cannot write to file %s.hdr\n',fileprefix); + error(msg); +else + if verbose, fprintf('...writing %s Analyze header.\n',machine); end + write_header(fid,avw,verbose); +end + +if verbose, t=toc; fprintf('...done (%5.2f sec).\n\n',t); end + +return + + + + + +%---------------------------------------------------------------------------- + +function write_header(fid,avw,verbose) + + header_key(fid,avw.hdr.hk); + image_dimension(fid,avw.hdr.dime); + data_history(fid,avw.hdr.hist); + + % check the file size is 348 bytes + fbytes = ftell(fid); + fclose(fid); + if ~isequal(fbytes,348), + msg = sprintf('...file size is not 348 bytes!\n'); + warning(msg); + end + +return + +%---------------------------------------------------------------------------- + +function header_key(fid,hk) + + % Original header structures - ANALYZE 7.5 + % struct header_key /* header key */ + % { /* off + size */ + % int sizeof_hdr /* 0 + 4 */ + % char data_type[10]; /* 4 + 10 */ + % char db_name[18]; /* 14 + 18 */ + % int extents; /* 32 + 4 */ + % short int session_error; /* 36 + 2 */ + % char regular; /* 38 + 1 */ + % char hkey_un0; /* 39 + 1 */ + % }; /* total=40 bytes */ + + fseek(fid,0,'bof'); + + fwrite(fid, hk.sizeof_hdr(1), 'int32'); % must be 348! + + data_type = sprintf('%-10s',hk.data_type); % ensure it is 10 chars + fwrite(fid, hk.data_type(1:10), 'uchar'); + + db_name = sprintf('%-18s',hk.db_name); % ensure it is 18 chars + fwrite(fid, db_name(1:18), 'uchar'); + + fwrite(fid, hk.extents(1), 'int32'); + fwrite(fid, hk.session_error(1),'int16'); + + regular = sprintf('%1s',hk.regular); % ensure it is 1 char + fwrite(fid, regular(1), 'uchar'); % might be uint8 + + %hkey_un0 = sprintf('%1s',hk.hkey_un0); % ensure it is 1 char + %fwrite(fid, hkey_un0(1), 'uchar'); + fwrite(fid, hk.hkey_un0(1), 'uint8'); + + % >Would you set hkey_un0 as char or uint8? + % Really doesn't make any difference. As far as anyone here can remember, + % this was just to pad to an even byte boundary for that structure. I guess + % I'd suggest setting it to a uint8 value of 0 (i.e, truly zero-valued) so + % that it doesn't look like anything important! + % Denny + +return + +%---------------------------------------------------------------------------- + +function image_dimension(fid,dime) + + %struct image_dimension + % { /* off + size */ + % short int dim[8]; /* 0 + 16 */ + % char vox_units[4]; /* 16 + 4 */ + % char cal_units[8]; /* 20 + 8 */ + % short int unused1; /* 28 + 2 */ + % short int datatype; /* 30 + 2 */ + % short int bitpix; /* 32 + 2 */ + % short int dim_un0; /* 34 + 2 */ + % float pixdim[8]; /* 36 + 32 */ + % /* + % pixdim[] specifies the voxel dimensions: + % pixdim[1] - voxel width + % pixdim[2] - voxel height + % pixdim[3] - interslice distance + % ..etc + % */ + % float vox_offset; /* 68 + 4 */ + % float roi_scale; /* 72 + 4 */ + % float funused1; /* 76 + 4 */ + % float funused2; /* 80 + 4 */ + % float cal_max; /* 84 + 4 */ + % float cal_min; /* 88 + 4 */ + % int compressed; /* 92 + 4 */ + % int verified; /* 96 + 4 */ + % int glmax; /* 100 + 4 */ + % int glmin; /* 104 + 4 */ + % }; /* total=108 bytes */ + + fwrite(fid, dime.dim(1:8), 'int16'); + fwrite(fid, dime.vox_units(1:4),'uchar'); + fwrite(fid, dime.cal_units(1:8),'uchar'); + fwrite(fid, dime.unused1(1), 'int16'); + fwrite(fid, dime.datatype(1), 'int16'); + fwrite(fid, dime.bitpix(1), 'int16'); + fwrite(fid, dime.dim_un0(1), 'int16'); + fwrite(fid, dime.pixdim(1:8), 'float32'); + fwrite(fid, dime.vox_offset(1), 'float32'); + + % Ensure compatibility with SPM (according to MRIcro) + if dime.roi_scale == 0, dime.roi_scale = 0.00392157; end + fwrite(fid, dime.roi_scale(1), 'float32'); + + fwrite(fid, dime.funused1(1), 'float32'); + fwrite(fid, dime.funused2(1), 'float32'); + fwrite(fid, dime.cal_max(1), 'float32'); + fwrite(fid, dime.cal_min(1), 'float32'); + fwrite(fid, dime.compressed(1), 'int32'); + fwrite(fid, dime.verified(1), 'int32'); + fwrite(fid, dime.glmax(1), 'int32'); + fwrite(fid, dime.glmin(1), 'int32'); + +return + +%---------------------------------------------------------------------------- + +function data_history(fid,hist) + + % Original header structures - ANALYZE 7.5 + %struct data_history + % { /* off + size */ + % char descrip[80]; /* 0 + 80 */ + % char aux_file[24]; /* 80 + 24 */ + % char orient; /* 104 + 1 */ + % char originator[10]; /* 105 + 10 */ + % char generated[10]; /* 115 + 10 */ + % char scannum[10]; /* 125 + 10 */ + % char patient_id[10]; /* 135 + 10 */ + % char exp_date[10]; /* 145 + 10 */ + % char exp_time[10]; /* 155 + 10 */ + % char hist_un0[3]; /* 165 + 3 */ + % int views /* 168 + 4 */ + % int vols_added; /* 172 + 4 */ + % int start_field; /* 176 + 4 */ + % int field_skip; /* 180 + 4 */ + % int omax; /* 184 + 4 */ + % int omin; /* 188 + 4 */ + % int smax; /* 192 + 4 */ + % int smin; /* 196 + 4 */ + % }; /* total=200 bytes */ + + descrip = sprintf('%-80s', hist.descrip); % 80 chars + aux_file = sprintf('%-24s', hist.aux_file); % 24 chars + originator = sprintf('%-10s', hist.originator); % 10 chars + generated = sprintf('%-10s', hist.generated); % 10 chars + scannum = sprintf('%-10s', hist.scannum); % 10 chars + patient_id = sprintf('%-10s', hist.patient_id); % 10 chars + exp_date = sprintf('%-10s', hist.exp_date); % 10 chars + exp_time = sprintf('%-10s', hist.exp_time); % 10 chars + hist_un0 = sprintf( '%-3s', hist.hist_un0); % 3 chars + + % --- + % The following should not be necessary, but I actually + % found one instance where it was, so this totally anal + % retentive approach became necessary, despite the + % apparently elegant solution above to ensuring that variables + % are the right length. + + if length(descrip) < 80, + paddingN = 80-length(descrip); + padding = char(repmat(double(' '),1,paddingN)); + descrip = [descrip,padding]; + end + if length(aux_file) < 24, + paddingN = 24-length(aux_file); + padding = char(repmat(double(' '),1,paddingN)); + aux_file = [aux_file,padding]; + end + if length(originator) < 10, + paddingN = 10-length(originator); + padding = char(repmat(double(' '),1,paddingN)); + originator = [originator, padding]; + end + if length(generated) < 10, + paddingN = 10-length(generated); + padding = char(repmat(double(' '),1,paddingN)); + generated = [generated, padding]; + end + if length(scannum) < 10, + paddingN = 10-length(scannum); + padding = char(repmat(double(' '),1,paddingN)); + scannum = [scannum, padding]; + end + if length(patient_id) < 10, + paddingN = 10-length(patient_id); + padding = char(repmat(double(' '),1,paddingN)); + patient_id = [patient_id, padding]; + end + if length(exp_date) < 10, + paddingN = 10-length(exp_date); + padding = char(repmat(double(' '),1,paddingN)); + exp_date = [exp_date, padding]; + end + if length(exp_time) < 10, + paddingN = 10-length(exp_time); + padding = char(repmat(double(' '),1,paddingN)); + exp_time = [exp_time, padding]; + end + if length(hist_un0) < 10, + paddingN = 10-length(hist_un0); + padding = char(repmat(double(' '),1,paddingN)); + hist_un0 = [hist_un0, padding]; + end + + % -- if you thought that was anal, try this; + % -- lets check for unusual ASCII char values! + + if find(double(descrip)>128), + indexStrangeChar = find(double(descrip)>128); + descrip(indexStrangeChar) = ' '; + end + if find(double(aux_file)>128), + indexStrangeChar = find(double(aux_file)>128); + aux_file(indexStrangeChar) = ' '; + end + if find(double(originator)>128), + indexStrangeChar = find(double(originator)>128); + originator(indexStrangeChar) = ' '; + end + if find(double(generated)>128), + indexStrangeChar = find(double(generated)>128); + generated(indexStrangeChar) = ' '; + end + if find(double(scannum)>128), + indexStrangeChar = find(double(scannum)>128); + scannum(indexStrangeChar) = ' '; + end + if find(double(patient_id)>128), + indexStrangeChar = find(double(patient_id)>128); + patient_id(indexStrangeChar) = ' '; + end + if find(double(exp_date)>128), + indexStrangeChar = find(double(exp_date)>128); + exp_date(indexStrangeChar) = ' '; + end + if find(double(exp_time)>128), + indexStrangeChar = find(double(exp_time)>128); + exp_time(indexStrangeChar) = ' '; + end + if find(double(hist_un0)>128), + indexStrangeChar = find(double(hist_un0)>128); + hist_un0(indexStrangeChar) = ' '; + end + + + % --- finally, we write the fields + + fwrite(fid, descrip(1:80), 'uchar'); + fwrite(fid, aux_file(1:24), 'uchar'); + + + %orient = sprintf( '%1s', hist.orient); % 1 char + %fwrite(fid, orient(1), 'uchar'); + fwrite(fid, hist.orient(1), 'uint8'); % see note below on char + + fwrite(fid, originator(1:10), 'uchar'); + fwrite(fid, generated(1:10), 'uchar'); + fwrite(fid, scannum(1:10), 'uchar'); + fwrite(fid, patient_id(1:10), 'uchar'); + fwrite(fid, exp_date(1:10), 'uchar'); + fwrite(fid, exp_time(1:10), 'uchar'); + fwrite(fid, hist_un0(1:3), 'uchar'); + + fwrite(fid, hist.views(1), 'int32'); + fwrite(fid, hist.vols_added(1), 'int32'); + fwrite(fid, hist.start_field(1),'int32'); + fwrite(fid, hist.field_skip(1), 'int32'); + fwrite(fid, hist.omax(1), 'int32'); + fwrite(fid, hist.omin(1), 'int32'); + fwrite(fid, hist.smax(1), 'int32'); + fwrite(fid, hist.smin(1), 'int32'); + +return + + + +% Note on using char: +% The 'char orient' field in the header is intended to +% hold simply an 8-bit unsigned integer value, not the ASCII representation +% of the character for that value. A single 'char' byte is often used to +% represent an integer value in Analyze if the known value range doesn't +% go beyond 0-255 - saves a byte over a short int, which may not mean +% much in today's computing environments, but given that this format +% has been around since the early 1980's, saving bytes here and there on +% older systems was important! In this case, 'char' simply provides the +% byte of storage - not an indicator of the format for what is stored in +% this byte. Generally speaking, anytime a single 'char' is used, it is +% probably meant to hold an 8-bit integer value, whereas if this has +% been dimensioned as an array, then it is intended to hold an ASCII +% character string, even if that was only a single character. +% Denny + +% See other notes in avw_hdr_read diff --git a/external/fieldtrip/private/avw_img_read.m b/external/fieldtrip/private/avw_img_read.m new file mode 100644 index 0000000..ba17683 --- /dev/null +++ b/external/fieldtrip/private/avw_img_read.m @@ -0,0 +1,697 @@ +function [ avw, machine ] = avw_img_read(fileprefix,IMGorient,machine,verbose) + +% avw_img_read - read Analyze format data image (*.img) +% +% [ avw, machine ] = avw_img_read(fileprefix,[orient],[machine],[verbose]) +% +% fileprefix - a string, the filename without the .img extension +% +% orient - read a specified orientation, integer values: +% +% '', use header history orient field +% 0, transverse unflipped (LAS*) +% 1, coronal unflipped (LA*S) +% 2, sagittal unflipped (L*AS) +% 3, transverse flipped (LPS*) +% 4, coronal flipped (LA*I) +% 5, sagittal flipped (L*AI) +% +% where * follows the slice dimension and letters indicate +XYZ +% orientations (L left, R right, A anterior, P posterior, +% I inferior, & S superior). +% +% Some files may contain data in the 3-5 orientations, but this +% is unlikely. For more information about orientation, see the +% documentation at the end of this .m file. See also the +% AVW_FLIP function for orthogonal reorientation. +% +% machine - a string, see machineformat in fread for details. +% The default here is 'ieee-le' but the routine +% will automatically switch between little and big +% endian to read any such Analyze header. It +% reports the appropriate machine format and can +% return the machine value. +% +% verbose - the default is to output processing information to the command +% window. If verbose = 0, this will not happen. +% +% Returned values: +% +% avw.hdr - a struct with image data parameters. +% avw.img - a 3D matrix of image data (double precision). +% +% A returned 3D matrix will correspond with the +% default ANALYZE coordinate system, which +% is Left-handed: +% +% X-Y plane is Transverse +% X-Z plane is Coronal +% Y-Z plane is Sagittal +% +% X axis runs from patient right (low X) to patient Left (high X) +% Y axis runs from posterior (low Y) to Anterior (high Y) +% Z axis runs from inferior (low Z) to Superior (high Z) +% +% The function can read a 4D Analyze volume, but only if it is in the +% axial unflipped orientation. +% +% See also: avw_hdr_read (called by this function), +% avw_view, avw_write, avw_img_write, avw_flip +% + + +% $Revision: 883 $ $Date: 2009/01/14 09:24:45 $ + +% Licence: GNU GPL, no express or implied warranties +% History: 05/2002, Darren.Weber@flinders.edu.au +% The Analyze format is copyright +% (c) Copyright, 1986-1995 +% Biomedical Imaging Resource, Mayo Foundation +% 01/2003, Darren.Weber@flinders.edu.au +% - adapted for matlab v5 +% - revised all orientation information and handling +% after seeking further advice from AnalyzeDirect.com +% 03/2003, Darren.Weber@flinders.edu.au +% - adapted for -ve pixdim values (non standard Analyze) +% 07/2004, chodkowski@kennedykrieger.org, added ability to +% read volumes with dimensionality greather than 3. +% a >3D volume cannot be flipped. and error is thrown if a volume of +% greater than 3D (ie, avw.hdr.dime.dim(1) > 3) requests a data flip +% (ie, avw.hdr.hist.orient ~= 0 ). i pulled the transfer of read-in +% data (tmp) to avw.img out of any looping mechanism. looping is not +% necessary as the data is already in its correct orientation. using +% 'reshape' rather than looping should be faster but, more importantly, +% it allows the reading in of N-D volumes. See lines 270-280. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +% check if SPM2 is in path and if not add +hastoolbox('SPM2',1); + +if ~exist('IMGorient','var'), IMGorient = ''; end +if ~exist('machine','var'), machine = 'ieee-le'; end +if ~exist('verbose','var'), verbose = 1; end + +if isempty(IMGorient), IMGorient = ''; end +if isempty(machine), machine = 'ieee-le'; end +if isempty(verbose), verbose = 1; end + +if ~exist('fileprefix','var'), + msg = sprintf('...no input fileprefix - see help avw_img_read\n\n'); + error(msg); +end +if findstr('.hdr',fileprefix), + fileprefix = strrep(fileprefix,'.hdr',''); +end +if findstr('.img',fileprefix), + fileprefix = strrep(fileprefix,'.img',''); +end + +% MAIN + +% Read the file header +[ avw, machine ] = avw_hdr_read(fileprefix,machine,verbose); + +avw = read_image(avw,IMGorient,machine,verbose); + +return + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [ avw ] = read_image(avw,IMGorient,machine,verbose) + +fid = fopen(sprintf('%s.img',avw.fileprefix),'r',machine); +if fid < 0, + msg = sprintf('...cannot open file %s.img\n\n',avw.fileprefix); + error(msg); +end + +if verbose, + ver = '[$Revision: 883 $]'; + fprintf('\nAVW_IMG_READ [v%s]\n',ver(12:16)); tic; +end + +% short int bitpix; /* Number of bits per pixel; 1, 8, 16, 32, or 64. */ +% short int datatype /* Datatype for this image set */ +% /*Acceptable values for datatype are*/ +% #define DT_NONE 0 +% #define DT_UNKNOWN 0 /*Unknown data type*/ +% #define DT_BINARY 1 /*Binary ( 1 bit per voxel)*/ +% #define DT_UNSIGNED_CHAR 2 /*Unsigned character ( 8 bits per voxel)*/ +% #define DT_SIGNED_SHORT 4 /*Signed short (16 bits per voxel)*/ +% #define DT_SIGNED_INT 8 /*Signed integer (32 bits per voxel)*/ +% #define DT_FLOAT 16 /*Floating point (32 bits per voxel)*/ +% #define DT_COMPLEX 32 /*Complex (64 bits per voxel; 2 floating point numbers)/* +% #define DT_DOUBLE 64 /*Double precision (64 bits per voxel)*/ +% #define DT_RGB 128 /*A Red-Green-Blue datatype*/ +% #define DT_ALL 255 /*Undocumented*/ + +switch double(avw.hdr.dime.bitpix), + case 1, precision = 'bit1'; + case 8, precision = 'uchar'; + case 16, precision = 'int16'; + case 32, + if isequal(avw.hdr.dime.datatype, 8), precision = 'int32'; + else precision = 'single'; + end + case 64, precision = 'double'; + otherwise, + precision = 'uchar'; + if verbose, fprintf('...precision undefined in header, using ''uchar''\n'); end +end + +% read the whole .img file into matlab (faster) +if verbose, + fprintf('...reading %s Analyze %s image format.\n',machine,precision); +end +fseek(fid,0,'bof'); +% adjust for matlab version +ver = version; +ver = str2num(ver(1)); +if ver < 6, + tmp = fread(fid,inf,sprintf('%s',precision)); +else, + tmp = fread(fid,inf,sprintf('%s=>double',precision)); +end +fclose(fid); + +% Update the global min and max values +avw.hdr.dime.glmax = max(double(tmp)); +avw.hdr.dime.glmin = min(double(tmp)); + + +%--------------------------------------------------------------- +% Now partition the img data into xyz + +% --- first figure out the size of the image + +% short int dim[ ]; /* Array of the image dimensions */ +% +% dim[0] Number of dimensions in database; usually 4. +% dim[1] Image X dimension; number of pixels in an image row. +% dim[2] Image Y dimension; number of pixel rows in slice. +% dim[3] Volume Z dimension; number of slices in a volume. +% dim[4] Time points; number of volumes in database. + +PixelDim = double(avw.hdr.dime.dim(2)); +RowDim = double(avw.hdr.dime.dim(3)); +SliceDim = double(avw.hdr.dime.dim(4)); +TimeDim = double(avw.hdr.dime.dim(5)); + +PixelSz = double(avw.hdr.dime.pixdim(2)); +RowSz = double(avw.hdr.dime.pixdim(3)); +SliceSz = double(avw.hdr.dime.pixdim(4)); +TimeSz = double(avw.hdr.dime.pixdim(5)); + + + + +% ---- NON STANDARD ANALYZE... + +% Some Analyze files have been found to set -ve pixdim values, eg +% the MNI template avg152T1_brain in the FSL etc/standard folder, +% perhaps to indicate flipped orientation? If so, this code below +% will NOT handle the flip correctly! +if PixelSz < 0, + warning('X pixdim < 0 !!! resetting to abs(avw.hdr.dime.pixdim(2))'); + PixelSz = abs(PixelSz); + avw.hdr.dime.pixdim(2) = single(PixelSz); +end +if RowSz < 0, + warning('Y pixdim < 0 !!! resetting to abs(avw.hdr.dime.pixdim(3))'); + RowSz = abs(RowSz); + avw.hdr.dime.pixdim(3) = single(RowSz); +end +if SliceSz < 0, + warning('Z pixdim < 0 !!! resetting to abs(avw.hdr.dime.pixdim(4))'); + SliceSz = abs(SliceSz); + avw.hdr.dime.pixdim(4) = single(SliceSz); +end + +% ---- END OF NON STANDARD ANALYZE + + + + + +% --- check the orientation specification and arrange img accordingly +if ~isempty(IMGorient), + if ischar(IMGorient), + avw.hdr.hist.orient = uint8(str2num(IMGorient)); + else + avw.hdr.hist.orient = uint8(IMGorient); + end +end, + +if isempty(avw.hdr.hist.orient), + msg = [ '...unspecified avw.hdr.hist.orient, using default 0\n',... + ' (check image and try explicit IMGorient option).\n']; + fprintf(msg); + avw.hdr.hist.orient = uint8(0); +end + +% --- check if the orientation is to be flipped for a volume with more +% --- than 3 dimensions. this logic is currently unsupported so throw +% --- an error. volumes of any dimensionality may be read in *only* as +% --- unflipped, ie, avw.hdr.hist.orient == 0 +if ( TimeDim > 1 ) && (avw.hdr.hist.orient ~= 0 ), + msg = [ 'ERROR: This volume has more than 3 dimensions *and* ', ... + 'requires flipping the data. Flipping is not supported ', ... + 'for volumes with dimensionality greater than 3. Set ', ... + 'avw.hdr.hist.orient = 0 and flip your volume after ', ... + 'calling this function' ]; + msg = sprintf( '%s (%s).', msg, mfilename ); + error( msg ); +end + +switch double(avw.hdr.hist.orient), + + case 0, % transverse unflipped + + % orient = 0: The primary orientation of the data on disk is in the + % transverse plane relative to the object scanned. Most commonly, the fastest + % moving index through the voxels that are part of this transverse image would + % span the right-left extent of the structure imaged, with the next fastest + % moving index spanning the posterior-anterior extent of the structure. This + % 'orient' flag would indicate to Analyze that this data should be placed in + % the X-Y plane of the 3D Analyze Coordinate System, with the Z dimension + % being the slice direction. + + % For the 'transverse unflipped' type, the voxels are stored with + % Pixels in 'x' axis (varies fastest) - from patient right to left + % Rows in 'y' axis - from patient posterior to anterior + % Slices in 'z' axis - from patient inferior to superior + + if verbose, fprintf('...reading axial unflipped orientation\n'); end + + % -- This code will handle nD files + dims = double( avw.hdr.dime.dim(2:end) ); + % replace dimensions of 0 with 1 to be used in reshape + idx = find( dims == 0 ); + dims( idx ) = 1; + avw.img = reshape( tmp, dims ); + + % -- The code above replaces this + % avw.img = zeros(PixelDim,RowDim,SliceDim); + % + % n = 1; + % x = 1:PixelDim; + % for z = 1:SliceDim, + % for y = 1:RowDim, + % % load Y row of X values into Z slice avw.img + % avw.img(x,y,z) = tmp(n:n+(PixelDim-1)); + % n = n + PixelDim; + % end + % end + + + % no need to rearrange avw.hdr.dime.dim or avw.hdr.dime.pixdim + + +case 1, % coronal unflipped + + % orient = 1: The primary orientation of the data on disk is in the coronal + % plane relative to the object scanned. Most commonly, the fastest moving + % index through the voxels that are part of this coronal image would span the + % right-left extent of the structure imaged, with the next fastest moving + % index spanning the inferior-superior extent of the structure. This 'orient' + % flag would indicate to Analyze that this data should be placed in the X-Z + % plane of the 3D Analyze Coordinate System, with the Y dimension being the + % slice direction. + + % For the 'coronal unflipped' type, the voxels are stored with + % Pixels in 'x' axis (varies fastest) - from patient right to left + % Rows in 'z' axis - from patient inferior to superior + % Slices in 'y' axis - from patient posterior to anterior + + if verbose, fprintf('...reading coronal unflipped orientation\n'); end + + avw.img = zeros(PixelDim,SliceDim,RowDim); + + n = 1; + x = 1:PixelDim; + for y = 1:SliceDim, + for z = 1:RowDim, + % load Z row of X values into Y slice avw.img + avw.img(x,y,z) = tmp(n:n+(PixelDim-1)); + n = n + PixelDim; + end + end + + % rearrange avw.hdr.dime.dim or avw.hdr.dime.pixdim + avw.hdr.dime.dim(2:4) = int16([PixelDim,SliceDim,RowDim]); + avw.hdr.dime.pixdim(2:4) = single([PixelSz,SliceSz,RowSz]); + + + case 2, % sagittal unflipped + + % orient = 2: The primary orientation of the data on disk is in the sagittal + % plane relative to the object scanned. Most commonly, the fastest moving + % index through the voxels that are part of this sagittal image would span the + % posterior-anterior extent of the structure imaged, with the next fastest + % moving index spanning the inferior-superior extent of the structure. This + % 'orient' flag would indicate to Analyze that this data should be placed in + % the Y-Z plane of the 3D Analyze Coordinate System, with the X dimension + % being the slice direction. + + % For the 'sagittal unflipped' type, the voxels are stored with + % Pixels in 'y' axis (varies fastest) - from patient posterior to anterior + % Rows in 'z' axis - from patient inferior to superior + % Slices in 'x' axis - from patient right to left + + if verbose, fprintf('...reading sagittal unflipped orientation\n'); end + + avw.img = zeros(SliceDim,PixelDim,RowDim); + + n = 1; + y = 1:PixelDim; % posterior to anterior (fastest) + + for x = 1:SliceDim, % right to left (slowest) + for z = 1:RowDim, % inferior to superior + + % load Z row of Y values into X slice avw.img + avw.img(x,y,z) = tmp(n:n+(PixelDim-1)); + n = n + PixelDim; + end + end + + % rearrange avw.hdr.dime.dim or avw.hdr.dime.pixdim + avw.hdr.dime.dim(2:4) = int16([SliceDim,PixelDim,RowDim]); + avw.hdr.dime.pixdim(2:4) = single([SliceSz,PixelSz,RowSz]); + + + %-------------------------------------------------------------------------------- + % Orient values 3-5 have the second index reversed in order, essentially + % 'flipping' the images relative to what would most likely become the vertical + % axis of the displayed image. + %-------------------------------------------------------------------------------- + + case 3, % transverse/axial flipped + + % orient = 3: The primary orientation of the data on disk is in the + % transverse plane relative to the object scanned. Most commonly, the fastest + % moving index through the voxels that are part of this transverse image would + % span the right-left extent of the structure imaged, with the next fastest + % moving index spanning the *anterior-posterior* extent of the structure. This + % 'orient' flag would indicate to Analyze that this data should be placed in + % the X-Y plane of the 3D Analyze Coordinate System, with the Z dimension + % being the slice direction. + + % For the 'transverse flipped' type, the voxels are stored with + % Pixels in 'x' axis (varies fastest) - from patient right to Left + % Rows in 'y' axis - from patient anterior to Posterior * + % Slices in 'z' axis - from patient inferior to Superior + + if verbose, fprintf('...reading axial flipped (+Y from Anterior to Posterior)\n'); end + + avw.img = zeros(PixelDim,RowDim,SliceDim); + + n = 1; + x = 1:PixelDim; + for z = 1:SliceDim, + for y = RowDim:-1:1, % flip in Y, read A2P file into P2A 3D matrix + + % load a flipped Y row of X values into Z slice avw.img + avw.img(x,y,z) = tmp(n:n+(PixelDim-1)); + n = n + PixelDim; + end + end + + % no need to rearrange avw.hdr.dime.dim or avw.hdr.dime.pixdim + + + case 4, % coronal flipped + + % orient = 4: The primary orientation of the data on disk is in the coronal + % plane relative to the object scanned. Most commonly, the fastest moving + % index through the voxels that are part of this coronal image would span the + % right-left extent of the structure imaged, with the next fastest moving + % index spanning the *superior-inferior* extent of the structure. This 'orient' + % flag would indicate to Analyze that this data should be placed in the X-Z + % plane of the 3D Analyze Coordinate System, with the Y dimension being the + % slice direction. + + % For the 'coronal flipped' type, the voxels are stored with + % Pixels in 'x' axis (varies fastest) - from patient right to Left + % Rows in 'z' axis - from patient superior to Inferior* + % Slices in 'y' axis - from patient posterior to Anterior + + if verbose, fprintf('...reading coronal flipped (+Z from Superior to Inferior)\n'); end + + avw.img = zeros(PixelDim,SliceDim,RowDim); + + n = 1; + x = 1:PixelDim; + for y = 1:SliceDim, + for z = RowDim:-1:1, % flip in Z, read S2I file into I2S 3D matrix + + % load a flipped Z row of X values into Y slice avw.img + avw.img(x,y,z) = tmp(n:n+(PixelDim-1)); + n = n + PixelDim; + end + end + + % rearrange avw.hdr.dime.dim or avw.hdr.dime.pixdim + avw.hdr.dime.dim(2:4) = int16([PixelDim,SliceDim,RowDim]); + avw.hdr.dime.pixdim(2:4) = single([PixelSz,SliceSz,RowSz]); + + + case 5, % sagittal flipped + + % orient = 5: The primary orientation of the data on disk is in the sagittal + % plane relative to the object scanned. Most commonly, the fastest moving + % index through the voxels that are part of this sagittal image would span the + % posterior-anterior extent of the structure imaged, with the next fastest + % moving index spanning the *superior-inferior* extent of the structure. This + % 'orient' flag would indicate to Analyze that this data should be placed in + % the Y-Z plane of the 3D Analyze Coordinate System, with the X dimension + % being the slice direction. + + % For the 'sagittal flipped' type, the voxels are stored with + % Pixels in 'y' axis (varies fastest) - from patient posterior to Anterior + % Rows in 'z' axis - from patient superior to Inferior* + % Slices in 'x' axis - from patient right to Left + + if verbose, fprintf('...reading sagittal flipped (+Z from Superior to Inferior)\n'); end + + avw.img = zeros(SliceDim,PixelDim,RowDim); + + n = 1; + y = 1:PixelDim; + + for x = 1:SliceDim, + for z = RowDim:-1:1, % flip in Z, read S2I file into I2S 3D matrix + + % load a flipped Z row of Y values into X slice avw.img + avw.img(x,y,z) = tmp(n:n+(PixelDim-1)); + n = n + PixelDim; + end + end + + % rearrange avw.hdr.dime.dim or avw.hdr.dime.pixdim + avw.hdr.dime.dim(2:4) = int16([SliceDim,PixelDim,RowDim]); + avw.hdr.dime.pixdim(2:4) = single([SliceSz,PixelSz,RowSz]); + + otherwise + + error('unknown value in avw.hdr.hist.orient, try explicit IMGorient option.'); + +end + +if verbose, t=toc; fprintf('...done (%5.2f sec).\n\n',t); end + +return + + + + +% This function attempts to read the orientation of the +% Analyze file according to the hdr.hist.orient field of the +% header. Unfortunately, this field is optional and not +% all programs will set it correctly, so there is no guarantee, +% that the data loaded will be correctly oriented. If necessary, +% experiment with the 'orient' option to read the .img +% data into the 3D matrix of avw.img as preferred. +% + +% (Conventions gathered from e-mail with support@AnalyzeDirect.com) +% +% 0 transverse unflipped +% X direction first, progressing from patient right to left, +% Y direction second, progressing from patient posterior to anterior, +% Z direction third, progressing from patient inferior to superior. +% 1 coronal unflipped +% X direction first, progressing from patient right to left, +% Z direction second, progressing from patient inferior to superior, +% Y direction third, progressing from patient posterior to anterior. +% 2 sagittal unflipped +% Y direction first, progressing from patient posterior to anterior, +% Z direction second, progressing from patient inferior to superior, +% X direction third, progressing from patient right to left. +% 3 transverse flipped +% X direction first, progressing from patient right to left, +% Y direction second, progressing from patient anterior to posterior, +% Z direction third, progressing from patient inferior to superior. +% 4 coronal flipped +% X direction first, progressing from patient right to left, +% Z direction second, progressing from patient superior to inferior, +% Y direction third, progressing from patient posterior to anterior. +% 5 sagittal flipped +% Y direction first, progressing from patient posterior to anterior, +% Z direction second, progressing from patient superior to inferior, +% X direction third, progressing from patient right to left. + + +%---------------------------------------------------------------------------- +% From ANALYZE documentation... +% +% The ANALYZE coordinate system has an origin in the lower left +% corner. That is, with the subject lying supine, the coordinate +% origin is on the right side of the body (x), at the back (y), +% and at the feet (z). This means that: +% +% +X increases from right (R) to left (L) +% +Y increases from the back (posterior,P) to the front (anterior, A) +% +Z increases from the feet (inferior,I) to the head (superior, S) +% +% The LAS orientation is the radiological convention, where patient +% left is on the image right. The alternative neurological +% convention is RAS (also Talairach convention). +% +% A major advantage of the Analzye origin convention is that the +% coordinate origin of each orthogonal orientation (transverse, +% coronal, and sagittal) lies in the lower left corner of the +% slice as it is displayed. +% +% Orthogonal slices are numbered from one to the number of slices +% in that orientation. For example, a volume (x, y, z) dimensioned +% 128, 256, 48 has: +% +% 128 sagittal slices numbered 1 through 128 (X) +% 256 coronal slices numbered 1 through 256 (Y) +% 48 transverse slices numbered 1 through 48 (Z) +% +% Pixel coordinates are made with reference to the slice numbers from +% which the pixels come. Thus, the first pixel in the volume is +% referenced p(1,1,1) and not at p(0,0,0). +% +% Transverse slices are in the XY plane (also known as axial slices). +% Sagittal slices are in the ZY plane. +% Coronal slices are in the ZX plane. +% +%---------------------------------------------------------------------------- + + +%---------------------------------------------------------------------------- +% E-mail from support@AnalyzeDirect.com +% +% The 'orient' field in the data_history structure specifies the primary +% orientation of the data as it is stored in the file on disk. This usually +% corresponds to the orientation in the plane of acquisition, given that this +% would correspond to the order in which the data is written to disk by the +% scanner or other software application. As you know, this field will contain +% the values: +% +% orient = 0 transverse unflipped +% 1 coronal unflipped +% 2 sagittal unflipped +% 3 transverse flipped +% 4 coronal flipped +% 5 sagittal flipped +% +% It would be vary rare that you would ever encounter any old Analyze 7.5 +% files that contain values of 'orient' which indicate that the data has been +% 'flipped'. The 'flipped flag' values were really only used internal to +% Analyze to precondition data for fast display in the Movie module, where the +% images were actually flipped vertically in order to accommodate the raster +% paint order on older graphics devices. The only cases you will encounter +% will have values of 0, 1, or 2. +% +% As mentioned, the 'orient' flag only specifies the primary orientation of +% data as stored in the disk file itself. It has nothing to do with the +% representation of the data in the 3D Analyze coordinate system, which always +% has a fixed representation to the data. The meaning of the 'orient' values +% should be interpreted as follows: +% +% orient = 0: The primary orientation of the data on disk is in the +% transverse plane relative to the object scanned. Most commonly, the fastest +% moving index through the voxels that are part of this transverse image would +% span the right-left extent of the structure imaged, with the next fastest +% moving index spanning the posterior-anterior extent of the structure. This +% 'orient' flag would indicate to Analyze that this data should be placed in +% the X-Y plane of the 3D Analyze Coordinate System, with the Z dimension +% being the slice direction. +% +% orient = 1: The primary orientation of the data on disk is in the coronal +% plane relative to the object scanned. Most commonly, the fastest moving +% index through the voxels that are part of this coronal image would span the +% right-left extent of the structure imaged, with the next fastest moving +% index spanning the inferior-superior extent of the structure. This 'orient' +% flag would indicate to Analyze that this data should be placed in the X-Z +% plane of the 3D Analyze Coordinate System, with the Y dimension being the +% slice direction. +% +% orient = 2: The primary orientation of the data on disk is in the sagittal +% plane relative to the object scanned. Most commonly, the fastest moving +% index through the voxels that are part of this sagittal image would span the +% posterior-anterior extent of the structure imaged, with the next fastest +% moving index spanning the inferior-superior extent of the structure. This +% 'orient' flag would indicate to Analyze that this data should be placed in +% the Y-Z plane of the 3D Analyze Coordinate System, with the X dimension +% being the slice direction. +% +% Orient values 3-5 have the second index reversed in order, essentially +% 'flipping' the images relative to what would most likely become the vertical +% axis of the displayed image. +% +% Hopefully you understand the difference between the indication this 'orient' +% flag has relative to data stored on disk and the full 3D Analyze Coordinate +% System for data that is managed as a volume image. As mentioned previously, +% the orientation of patient anatomy in the 3D Analyze Coordinate System has a +% fixed orientation relative to each of the orthogonal axes. This orientation +% is completely described in the information that is attached, but the basics +% are: +% +% Left-handed coordinate system +% +% X-Y plane is Transverse +% X-Z plane is Coronal +% Y-Z plane is Sagittal +% +% X axis runs from patient right (low X) to patient left (high X) +% Y axis runs from posterior (low Y) to anterior (high Y) +% Z axis runs from inferior (low Z) to superior (high Z) +% +%---------------------------------------------------------------------------- + + + +%---------------------------------------------------------------------------- +% SPM2 NOTES from spm2 webpage: One thing to watch out for is the image +% orientation. The proper Analyze format uses a left-handed co-ordinate +% system, whereas Talairach uses a right-handed one. In SPM99, images were +% flipped at the spatial normalisation stage (from one co-ordinate system +% to the other). In SPM2b, a different approach is used, so that either a +% left- or right-handed co-ordinate system is used throughout. The SPM2b +% program is told about the handedness that the images are stored with by +% the spm_flip_analyze_images.m function and the defaults.analyze.flip +% parameter that is specified in the spm_defaults.m file. These files are +% intended to be customised for each site. If you previously used SPM99 +% and your images were flipped during spatial normalisation, then set +% defaults.analyze.flip=1. If no flipping took place, then set +% defaults.analyze.flip=0. Check that when using the Display facility +% (possibly after specifying some rigid-body rotations) that: +% +% 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. +%---------------------------------------------------------------------------- diff --git a/external/fieldtrip/private/avw_img_write.m b/external/fieldtrip/private/avw_img_write.m new file mode 100644 index 0000000..4d8f274 --- /dev/null +++ b/external/fieldtrip/private/avw_img_write.m @@ -0,0 +1,412 @@ +function avw_img_write(avw, fileprefix, IMGorient, machine, verbose) + +% avw_img_write - write Analyze image files (*.img) +% +% avw_img_write(avw,fileprefix,[IMGorient],[machine],[verbose]) +% +% avw.img - a 3D matrix of image data (double precision). +% avw.hdr - a struct with image data parameters. If +% not empty, this function calls avw_hdr_write. +% +% fileprefix - a string, the filename without the .img +% extension. If empty, may use avw.fileprefix +% +% IMGorient - optional int, force writing of specified +% orientation, with values: +% +% [], if empty, will use avw.hdr.hist.orient field +% 0, transverse/axial unflipped (default, radiological) +% 1, coronal unflipped +% 2, sagittal unflipped +% 3, transverse/axial flipped, left to right +% 4, coronal flipped, anterior to posterior +% 5, sagittal flipped, superior to inferior +% +% This function will set avw.hdr.hist.orient and write the +% image data in a corresponding order. This function is +% in alpha development, so it has not been exhaustively +% tested (07/2003). See avw_img_read for more information +% and documentation on the orientation option. +% Orientations 3-5 are NOT recommended! They are part +% of the Analyze format, but only used in Analyze +% for faster raster graphics during movies. +% +% machine - a string, see machineformat in fread for details. +% The default here is 'ieee-le'. +% +% verbose - the default is to output processing information to the command +% window. If verbose = 0, this will not happen. +% +% Tip: to change the data type, set avw.hdr.dime.datatype to: +% +% 1 Binary ( 1 bit per voxel) +% 2 Unsigned character ( 8 bits per voxel) +% 4 Signed short ( 16 bits per voxel) +% 8 Signed integer ( 32 bits per voxel) +% 16 Floating point ( 32 bits per voxel) +% 32 Complex, 2 floats ( 64 bits per voxel), not supported +% 64 Double precision ( 64 bits per voxel) +% 128 Red-Green-Blue (128 bits per voxel), not supported +% +% See also: avw_write, avw_hdr_write, +% avw_read, avw_hdr_read, avw_img_read, avw_view +% + +% $Revision: 883 $ $Date: 2009/01/14 09:24:45 $ + +% Licence: GNU GPL, no express or implied warranties +% History: 05/2002, Darren.Weber@flinders.edu.au +% The Analyze format is copyright +% (c) Copyright, 1986-1995 +% Biomedical Imaging Resource, Mayo Foundation +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%------------------------------------------------------------------------ +% Check inputs + +if ~exist('avw','var'), + doc avw_img_write; + error('...no input avw.'); +elseif isempty(avw), + error('...empty input avw.'); +elseif ~isfield(avw,'img'), + error('...empty input avw.img'); +end + +if ~exist('fileprefix','var'), + if isfield(avw,'fileprefix'), + if ~isempty(avw.fileprefix), + fileprefix = avw.fileprefix; + else + fileprefix = []; + end + else + fileprefix = []; + end +end +if isempty(fileprefix), + [fileprefix, pathname, filterindex] = uiputfile('*.hdr','Specify an output Analyze .hdr file'); + if pathname, cd(pathname); end + if ~fileprefix, + doc avw_img_write; + error('no output .hdr file specified'); + end +end + +if findstr('.hdr',fileprefix), +% fprintf('AVW_IMG_WRITE: Removing .hdr extension from ''%s''\n',fileprefix); + fileprefix = strrep(fileprefix,'.hdr',''); +end +if findstr('.img',fileprefix), +% fprintf('AVW_IMG_WRITE: Removing .img extension from ''%s''\n',fileprefix); + fileprefix = strrep(fileprefix,'.img',''); +end + +if ~exist('IMGorient','var'), IMGorient = ''; end +if ~exist('machine','var'), machine = 'ieee-le'; end +if ~exist('verbose','var'), verbose = 1; end + +if isempty(IMGorient), IMGorient = ''; end +if isempty(machine), machine = 'ieee-le'; end +if isempty(verbose), verbose = 1; end + + + +%------------------------------------------------------------------------ +% MAIN +if verbose, + version = '[$Revision: 883 $]'; + fprintf('\nAVW_IMG_WRITE [v%s]\n',version(12:16)); tic; +end + +fid = fopen(sprintf('%s.img',fileprefix),'w',machine); +if fid < 0, + msg = sprintf('Cannot open file %s.img\n',fileprefix); + error(msg); +else + avw = write_image(fid,avw,fileprefix,IMGorient,machine,verbose); +end + +if verbose, + t=toc; fprintf('...done (%5.2f sec).\n\n',t); +end + +% MUST write header after the image, to ensure any +% orientation changes during image write are saved +% in the header +avw_hdr_write(avw,fileprefix,machine,verbose); + +return + + + + +%----------------------------------------------------------------------------------- + +function avw = write_image(fid,avw,fileprefix,IMGorient,machine,verbose) + +% short int bitpix; /* Number of bits per pixel; 1, 8, 16, 32, or 64. */ +% short int datatype /* Datatype for this image set */ +% /*Acceptable values for datatype are*/ +% #define DT_NONE 0 +% #define DT_UNKNOWN 0 /*Unknown data type*/ +% #define DT_BINARY 1 /*Binary ( 1 bit per voxel)*/ +% #define DT_UNSIGNED_CHAR 2 /*Unsigned character ( 8 bits per voxel)*/ +% #define DT_SIGNED_SHORT 4 /*Signed short (16 bits per voxel)*/ +% #define DT_SIGNED_INT 8 /*Signed integer (32 bits per voxel)*/ +% #define DT_FLOAT 16 /*Floating point (32 bits per voxel)*/ +% #define DT_COMPLEX 32 /*Complex,2 floats (64 bits per voxel)/* +% #define DT_DOUBLE 64 /*Double precision (64 bits per voxel)*/ +% #define DT_RGB 128 /*A Red-Green-Blue datatype*/ +% #define DT_ALL 255 /*Undocumented*/ + +switch double(avw.hdr.dime.datatype), +case 1, + avw.hdr.dime.bitpix = int16( 1); precision = 'bit1'; +case 2, + avw.hdr.dime.bitpix = int16( 8); precision = 'uchar'; +case 4, + avw.hdr.dime.bitpix = int16(16); precision = 'int16'; +case 8, + avw.hdr.dime.bitpix = int16(32); precision = 'int32'; +case 16, + avw.hdr.dime.bitpix = int16(32); precision = 'single'; +case 32, + error('...complex datatype not yet supported.\n'); +case 64, + avw.hdr.dime.bitpix = int16(64); precision = 'double'; +case 128, + error('...RGB datatype not yet supported.\n'); +otherwise + warning('...unknown datatype, using type 16 (32 bit floats).\n'); + avw.hdr.dime.datatype = int16(16); + avw.hdr.dime.bitpix = int16(32); precision = 'single'; +end + + +% write the .img file, depending on the .img orientation +if verbose, + fprintf('...writing %s precision Analyze image (%s).\n',precision,machine); +end + +fseek(fid,0,'bof'); + +% The standard image orientation is axial unflipped +if isempty(avw.hdr.hist.orient), + msg = [ '...avw.hdr.hist.orient ~= 0.\n',... + ' This function assumes the input avw.img is\n',... + ' in axial unflipped orientation in memory. This is\n',... + ' created by the avw_img_read function, which converts\n',... + ' any input file image to axial unflipped in memory.\n']; + warning(msg) +end + +if isempty(IMGorient), + if verbose, + fprintf('...no IMGorient specified, using avw.hdr.hist.orient value.\n'); + end + IMGorient = double(avw.hdr.hist.orient); +end + +if ~isfinite(IMGorient), + if verbose, + fprintf('...IMGorient is not finite!\n'); + end + IMGorient = 99; +end + +switch IMGorient, + +case 0, % transverse/axial unflipped + + % For the 'transverse unflipped' type, the voxels are stored with + % Pixels in 'x' axis (varies fastest) - from patient right to left + % Rows in 'y' axis - from patient posterior to anterior + % Slices in 'z' axis - from patient inferior to superior + + if verbose, fprintf('...writing axial unflipped\n'); end + + avw.hdr.hist.orient = uint8(0); + + SliceDim = double(avw.hdr.dime.dim(4)); % z + RowDim = double(avw.hdr.dime.dim(3)); % y + PixelDim = double(avw.hdr.dime.dim(2)); % x + SliceSz = double(avw.hdr.dime.pixdim(4)); + RowSz = double(avw.hdr.dime.pixdim(3)); + PixelSz = double(avw.hdr.dime.pixdim(2)); + + x = 1:PixelDim; + for z = 1:SliceDim, + for y = 1:RowDim, + fwrite(fid,avw.img(x,y,z),precision); + end + end + +case 1, % coronal unflipped + + % For the 'coronal unflipped' type, the voxels are stored with + % Pixels in 'x' axis (varies fastest) - from patient right to left + % Rows in 'z' axis - from patient inferior to superior + % Slices in 'y' axis - from patient posterior to anterior + + if verbose, fprintf('...writing coronal unflipped\n'); end + + avw.hdr.hist.orient = uint8(1); + + SliceDim = double(avw.hdr.dime.dim(3)); % y + RowDim = double(avw.hdr.dime.dim(4)); % z + PixelDim = double(avw.hdr.dime.dim(2)); % x + SliceSz = double(avw.hdr.dime.pixdim(3)); + RowSz = double(avw.hdr.dime.pixdim(4)); + PixelSz = double(avw.hdr.dime.pixdim(2)); + + x = 1:PixelDim; + for y = 1:SliceDim, + for z = 1:RowDim, + fwrite(fid,avw.img(x,y,z),precision); + end + end + +case 2, % sagittal unflipped + + % For the 'sagittal unflipped' type, the voxels are stored with + % Pixels in 'y' axis (varies fastest) - from patient posterior to anterior + % Rows in 'z' axis - from patient inferior to superior + % Slices in 'x' axis - from patient right to left + + if verbose, fprintf('...writing sagittal unflipped\n'); end + + avw.hdr.hist.orient = uint8(2); + + SliceDim = double(avw.hdr.dime.dim(2)); % x + RowDim = double(avw.hdr.dime.dim(4)); % z + PixelDim = double(avw.hdr.dime.dim(3)); % y + SliceSz = double(avw.hdr.dime.pixdim(2)); + RowSz = double(avw.hdr.dime.pixdim(4)); + PixelSz = double(avw.hdr.dime.pixdim(3)); + + y = 1:PixelDim; + for x = 1:SliceDim, + for z = 1:RowDim, + fwrite(fid,avw.img(x,y,z),precision); + end + end + +case 3, % transverse/axial flipped + + % For the 'transverse flipped' type, the voxels are stored with + % Pixels in 'x' axis (varies fastest) - from patient right to left + % Rows in 'y' axis - from patient anterior to posterior* + % Slices in 'z' axis - from patient inferior to superior + + if verbose, + fprintf('...writing axial flipped (+Y from Anterior to Posterior)\n'); + end + + avw.hdr.hist.orient = uint8(3); + + SliceDim = double(avw.hdr.dime.dim(4)); % z + RowDim = double(avw.hdr.dime.dim(3)); % y + PixelDim = double(avw.hdr.dime.dim(2)); % x + SliceSz = double(avw.hdr.dime.pixdim(4)); + RowSz = double(avw.hdr.dime.pixdim(3)); + PixelSz = double(avw.hdr.dime.pixdim(2)); + + x = 1:PixelDim; + for z = 1:SliceDim, + for y = RowDim:-1:1, % flipped in Y + fwrite(fid,avw.img(x,y,z),precision); + end + end + +case 4, % coronal flipped + + % For the 'coronal flipped' type, the voxels are stored with + % Pixels in 'x' axis (varies fastest) - from patient right to left + % Rows in 'z' axis - from patient inferior to superior + % Slices in 'y' axis - from patient anterior to posterior + + if verbose, + fprintf('...writing coronal flipped (+Z from Superior to Inferior)\n'); + end + + avw.hdr.hist.orient = uint8(4); + + SliceDim = double(avw.hdr.dime.dim(3)); % y + RowDim = double(avw.hdr.dime.dim(4)); % z + PixelDim = double(avw.hdr.dime.dim(2)); % x + SliceSz = double(avw.hdr.dime.pixdim(3)); + RowSz = double(avw.hdr.dime.pixdim(4)); + PixelSz = double(avw.hdr.dime.pixdim(2)); + + x = 1:PixelDim; + for y = 1:SliceDim, + for z = RowDim:-1:1, + fwrite(fid,avw.img(x,y,z),precision); + end + end + +case 5, % sagittal flipped + + % For the 'sagittal flipped' type, the voxels are stored with + % Pixels in 'y' axis (varies fastest) - from patient posterior to anterior + % Rows in 'z' axis - from patient superior to inferior + % Slices in 'x' axis - from patient right to left + + if verbose, + fprintf('...writing sagittal flipped (+Z from Superior to Inferior)\n'); + end + + avw.hdr.hist.orient = uint8(5); + + SliceDim = double(avw.hdr.dime.dim(2)); % x + RowDim = double(avw.hdr.dime.dim(4)); % z + PixelDim = double(avw.hdr.dime.dim(3)); % y + SliceSz = double(avw.hdr.dime.pixdim(2)); + RowSz = double(avw.hdr.dime.pixdim(4)); + PixelSz = double(avw.hdr.dime.pixdim(3)); + + y = 1:PixelDim; + for x = 1:SliceDim, + for z = RowDim:-1:1, % superior to inferior + fwrite(fid,avw.img(x,y,z),precision); + end + end + +otherwise, % transverse/axial unflipped + + % For the 'transverse unflipped' type, the voxels are stored with + % Pixels in 'x' axis (varies fastest) - from patient right to left + % Rows in 'y' axis - from patient posterior to anterior + % Slices in 'z' axis - from patient inferior to superior + + if verbose, + fprintf('...unknown orientation specified, assuming default axial unflipped\n'); + end + + avw.hdr.hist.orient = uint8(0); + + SliceDim = double(avw.hdr.dime.dim(4)); % z + RowDim = double(avw.hdr.dime.dim(3)); % y + PixelDim = double(avw.hdr.dime.dim(2)); % x + SliceSz = double(avw.hdr.dime.pixdim(4)); + RowSz = double(avw.hdr.dime.pixdim(3)); + PixelSz = double(avw.hdr.dime.pixdim(2)); + + x = 1:PixelDim; + for z = 1:SliceDim, + for y = 1:RowDim, + fwrite(fid,avw.img(x,y,z),precision); + end + end + +end + +fclose(fid); + +% Update the header +avw.hdr.dime.dim(2:4) = int16([PixelDim,RowDim,SliceDim]); +avw.hdr.dime.pixdim(2:4) = single([PixelSz,RowSz,SliceSz]); + +return diff --git a/external/fieldtrip/private/bandpassfilter.m b/external/fieldtrip/private/bandpassfilter.m index 4f25ed2..9626ddd 100644 --- a/external/fieldtrip/private/bandpassfilter.m +++ b/external/fieldtrip/private/bandpassfilter.m @@ -25,25 +25,23 @@ % Copyright (c) 2003, Robert Oostenveld % -% $Log: bandpassfilter.m,v $ -% Revision 1.5 2006/08/31 07:57:22 roboos -% implemented onepass-reverse filter: usefull for stimulus artifacts, e.g. TMS or electrical stimulation +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.4 2006/06/14 12:36:20 roboos -% added the filter direction as additional option, default is 'twopass', i.e. using filtfilt +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.3 2004/02/11 08:55:13 roberto -% added optional fir1 filter (default still is butterworth), changed -% layout of code for better support of multiple optional arguments, -% extended documentation +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.2 2003/06/12 08:40:44 roberto -% added variable option to determine filter order -% changed default order from 6 to 4 for notch and bandpass -% -% Revision 1.1 2003/04/04 09:53:36 roberto -% new implementation, using 6th order Butterworth FIR filter +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: bandpassfilter.m 952 2010-04-21 18:29:51Z roboos $ % set the default filter order later if nargin<4 diff --git a/external/fieldtrip/private/bandstopfilter.m b/external/fieldtrip/private/bandstopfilter.m index 7b635d5..b229e0a 100644 --- a/external/fieldtrip/private/bandstopfilter.m +++ b/external/fieldtrip/private/bandstopfilter.m @@ -25,10 +25,23 @@ % Copyright (c) 2007, Robert Oostenveld % -% $Log: bandstopfilter.m,v $ -% Revision 1.1 2007/09/11 15:30:59 roboos -% new implementation based on bandpassfilter +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: bandstopfilter.m 952 2010-04-21 18:29:51Z roboos $ % set the default filter order later if nargin<4 diff --git a/external/fieldtrip/private/beamformer_dics.m b/external/fieldtrip/private/beamformer_dics.m deleted file mode 100644 index 3cf9393..0000000 --- a/external/fieldtrip/private/beamformer_dics.m +++ /dev/null @@ -1,536 +0,0 @@ -function [dipout] = beamformer_dics(dip, grad, vol, dat, Cf, varargin) - -% BEAMFORMER_DICS scans on pre-defined dipole locations with a single dipole -% and returns the beamformer spatial filter output for a dipole on every -% location. Dipole locations that are outside the head will return a -% NaN value. -% -% Use as -% [dipout] = beamformer_dics(dipin, grad, vol, dat, cov, varargin) -% where -% dipin is the input dipole model -% grad is the gradiometer definition -% vol is the volume conductor definition -% dat is the data matrix with the ERP or ERF -% cov is the data covariance or cross-spectral density matrix -% and -% dipout is the resulting dipole model with all details -% -% The input dipole model consists of -% dipin.pos positions for dipole, e.g. regular grid -% dipin.mom dipole orientation (optional) -% -% Additional options should be specified in key-value pairs and can be -% 'Pr' = power of the external reference channel -% 'Cr' = cross spectral density between all data channels and the external reference channel -% 'refdip' = location of dipole with which coherence is computed -% 'lambda' = regularisation parameter -% 'powmethod' = can be 'trace' or 'lambda1' -% 'feedback' = give progress indication, can be 'text', 'gui' or 'none' -% 'fixedori' = use fixed or free orientation, can be 'yes' or 'no' -% 'projectnoise' = project noise estimate through filter, can be 'yes' or 'no' -% 'realfilter' = construct a real-valued filter, can be 'yes' or 'no' -% 'keepfilter' = remember the beamformer filter, can be 'yes' or 'no' -% 'keepleadfield' = remember the forward computation, can be 'yes' or 'no' -% 'keepcsd' = remember the estimated cross-spectral density, can be 'yes' or 'no' -% -% These options influence the forward computation of the leadfield -% 'reducerank' = reduce the leadfield rank, can be 'no' or a number (e.g. 2) -% 'normalize' = normalize the leadfield -% 'normalizeparam' = parameter for depth normalization (default = 0.5) -% -% If the dipole definition only specifies the dipole location, a rotating -% dipole (regional source) is assumed on each location. If a dipole moment -% is specified, its orientation will be used and only the strength will -% be fitted to the data. - -% Copyright (C) 2003-2008, Robert Oostenveld -% -% $Log: beamformer_dics.m,v $ -% Revision 1.15 2009/06/17 13:40:37 roboos -% small change in the order of the code for subspace projection -% -% Revision 1.14 2009/05/14 19:25:12 roboos -% added a FIXME comment -% -% Revision 1.13 2009/03/24 13:13:33 roboos -% fixed bug for coh_refchan in case trace was used for power estimate -% -% Revision 1.12 2009/01/06 10:25:32 roboos -% fixed a bug for leadfield computation in case a pre-specified dipole -% orientation is present. The bug would have caused a crash in case -% the particular combination of options would have been used. -% -% Revision 1.11 2008/12/04 16:44:29 jansch -% fixed typo in line 260 (thanks to Jurrian) -% -% Revision 1.10 2008/12/04 11:45:13 jansch -% fixed bug in fixedori -% -% Revision 1.9 2008/08/13 16:13:38 roboos -% added option fixedori, not yet fully tested -% -% Revision 1.8 2008/08/13 13:47:42 roboos -% updated documentation -% -% Revision 1.7 2008/07/02 07:57:33 roboos -% allow specification of percentage noise in lambda, relative to trace(cov)/nchans -% -% Revision 1.6 2008/03/18 13:01:17 roboos -% added optional argument normalizeparam, is passed onto compute_leadfield -% -% Revision 1.5 2007/12/11 11:17:49 roboos -% fixed bug in handling of prespecified dipole moment -% -% Revision 1.4 2006/10/16 15:18:35 roboos -% small change in comment -% -% Revision 1.3 2006/10/16 15:17:24 roboos -% fixed bug for powlambda/powtrace computation of noise (powlambda was hardcoded) -% also keep noise csd matrix if requested (projectnoise & keepcsd) -% fixed obvious bug in progress indicator -% -% Revision 1.2 2006/10/12 10:17:31 roboos -% fixed bug in selecting dipoles on the inside positions only -% output cell-arrays are [] for outside points -% removed catch for mom, fixed dipoles should also work -% -% Revision 1.1 2006/10/12 09:07:07 roboos -% moved code from beamformer into stand-alone functions, for easier use and maintenance -% - -if mod(nargin-5,2) - % the first 5 arguments are fixed, the other arguments should come in pairs - error('invalid number of optional arguments'); -end - -% these optional settings do not have defaults -Pr = keyval('Pr', varargin); -Cr = keyval('Cr', varargin); -refdip = keyval('refdip', varargin); -powmethod = keyval('powmethod', varargin); % the default for this is set below -realfilter = keyval('realfilter', varargin); % the default for this is set below -% these settings pertain to the forward model, the defaults are set in compute_leadfield -reducerank = keyval('reducerank', varargin); -normalize = keyval('normalize', varargin); -normalizeparam = keyval('normalizeparam', varargin); -% these optional settings have defaults -feedback = keyval('feedback', varargin); if isempty(feedback), feedback = 'text'; end -keepcsd = keyval('keepcsd', varargin); if isempty(keepcsd), keepcsd = 'no'; end -keepfilter = keyval('keepfilter', varargin); if isempty(keepfilter), keepfilter = 'no'; end -keepleadfield = keyval('keepleadfield', varargin); if isempty(keepleadfield), keepleadfield = 'no'; end -lambda = keyval('lambda', varargin); if isempty(lambda ), lambda = 0; end -projectnoise = keyval('projectnoise', varargin); if isempty(projectnoise), projectnoise = 'yes'; end -fixedori = keyval('fixedori', varargin); if isempty(fixedori), fixedori = 'no'; end - -% convert the yes/no arguments to the corresponding logical values -keepcsd = strcmp(keepcsd, 'yes'); -keepfilter = strcmp(keepfilter, 'yes'); -keepleadfield = strcmp(keepleadfield, 'yes'); -projectnoise = strcmp(projectnoise, 'yes'); -fixedori = strcmp(fixedori, 'yes'); -% FIXME besides regular/complex lambda1, also implement a real version - -% default is to use the largest singular value of the csd matrix, see Gross 2001 -if isempty(powmethod) - powmethod = 'lambda1'; -end - -% default is to be consistent with the original description of DICS in Gross 2001 -if isempty(realfilter) - realfilter = 'no'; -end - -% use these two logical flags instead of doing the string comparisons each time again -powtrace = strcmp(powmethod, 'trace'); -powlambda1 = strcmp(powmethod, 'lambda1'); - -if ~isempty(Cr) - % ensure that the cross-spectral density with the reference signal is a column matrix - Cr = Cr(:); -end - -if isfield(dip, 'mom') && fixedori - error('you cannot specify a dipole orientation and fixedmom simultaneously'); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% find the dipole positions that are inside/outside the brain -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if ~isfield(dip, 'inside') && ~isfield(dip, 'outside'); - [dip.inside, dip.outside] = find_inside_vol(dip.pos, vol); -elseif isfield(dip, 'inside') && ~isfield(dip, 'outside'); - dip.outside = setdiff(1:size(dip.pos,1), dip.inside); -elseif ~isfield(dip, 'inside') && isfield(dip, 'outside'); - dip.inside = setdiff(1:size(dip.pos,1), dip.outside); -end - -% select only the dipole positions inside the brain for scanning -dip.origpos = dip.pos; -dip.originside = dip.inside; -dip.origoutside = dip.outside; -if isfield(dip, 'mom') - dip.mom = dip.mom(:,dip.inside); -end -if isfield(dip, 'leadfield') - fprintf('using precomputed leadfields\n'); - dip.leadfield = dip.leadfield(dip.inside); -end -if isfield(dip, 'filter') - fprintf('using precomputed filters\n'); - dip.filter = dip.filter(dip.inside); -end -if isfield(dip, 'subspace') - fprintf('using subspace projection\n'); - dip.subspace = dip.subspace(dip.inside); -end -dip.pos = dip.pos(dip.inside, :); -dip.inside = 1:size(dip.pos,1); -dip.outside = []; - -% dics has the following sub-methods, which depend on the function input arguments -% power only, cortico-muscular coherence and cortico-cortical coherence -if ~isempty(Cr) && ~isempty(Pr) && isempty(refdip) - % compute cortico-muscular coherence, using reference cross spectral density - submethod = 'dics_refchan'; -elseif isempty(Cr) && isempty(Pr) && ~isempty(refdip) - % compute cortico-cortical coherence with a dipole at the reference position - submethod = 'dics_refdip'; -elseif isempty(Cr) && isempty(Pr) && isempty(refdip) - % only compute power of a dipole at the grid positions - submethod = 'dics_power'; -else - error('invalid combination of input arguments for dics'); -end - -isrankdeficient = (rank(Cf) m - X = pinv(A',varargin{:})'; -else - [U,S,V] = svd(A,0); - if m > 1, s = diag(S); - elseif m == 1, s = S(1); - else s = 0; - end - if nargin == 2 - tol = varargin{1}; - else - tol = 10 * max(m,n) * max(s) * eps; - end - r = sum(s > tol); - if (r == 0) - X = zeros(size(A'),class(A)); - else - s = diag(ones(r,1)./s(1:r)); - X = V(:,1:r)*s*U(:,1:r)'; - end -end - diff --git a/external/fieldtrip/private/beamformer_lcmv.m b/external/fieldtrip/private/beamformer_lcmv.m deleted file mode 100644 index 260846a..0000000 --- a/external/fieldtrip/private/beamformer_lcmv.m +++ /dev/null @@ -1,422 +0,0 @@ -function [dipout] = beamformer_lcmv(dip, grad, vol, dat, Cy, varargin) - -% BEAMFORMER_LCMV scans on pre-defined dipole locations with a single dipole -% and returns the beamformer spatial filter output for a dipole on every -% location. Dipole locations that are outside the head will return a -% NaN value. -% -% Use as -% [dipout] = beamformer_lcmv(dipin, grad, vol, dat, cov, varargin) -% where -% dipin is the input dipole model -% grad is the gradiometer definition -% vol is the volume conductor definition -% dat is the data matrix with the ERP or ERF -% cov is the data covariance or cross-spectral density matrix -% and -% dipout is the resulting dipole model with all details -% -% The input dipole model consists of -% dipin.pos positions for dipole, e.g. regular grid -% dipin.mom dipole orientation (optional) -% -% Additional options should be specified in key-value pairs and can be -% 'lambda' = regularisation parameter -% 'powmethod' = can be 'trace' or 'lambda1' -% 'feedback' = give progress indication, can be 'text', 'gui' or 'none' (default) -% 'fixedori' = use fixed or free orientation, can be 'yes' or 'no' -% 'projectnoise' = project noise estimate through filter, can be 'yes' or 'no' -% 'projectmom' = project the dipole moment timecourse on the direction of maximal power, can be 'yes' or 'no' -% 'keepfilter' = remember the beamformer filter, can be 'yes' or 'no' -% 'keepleadfield' = remember the forward computation, can be 'yes' or 'no' -% 'keepmom' = remember the estimated dipole moment, can be 'yes' or 'no' -% 'keepcov' = remember the estimated dipole covariance, can be 'yes' or 'no' -% -% These options influence the forward computation of the leadfield -% 'reducerank' = reduce the leadfield rank, can be 'no' or a number (e.g. 2) -% 'normalize' = normalize the leadfield -% 'normalizeparam' = parameter for depth normalization (default = 0.5) -% -% If the dipole definition only specifies the dipole location, a rotating -% dipole (regional source) is assumed on each location. If a dipole moment -% is specified, its orientation will be used and only the strength will -% be fitted to the data. - -% Copyright (C) 2003-2008, Robert Oostenveld -% -% $Log: beamformer_lcmv.m,v $ -% Revision 1.14 2009/03/23 21:14:42 roboos -% some whitespace changes, nothing functional -% -% Revision 1.13 2009/02/11 10:25:43 jansch -% added some comments -% -% Revision 1.12 2009/02/10 10:51:02 jansch -% implemented subspace projection (for eigenspace bf, sensor-array subsampling etc) -% -% Revision 1.11 2008/12/04 11:45:57 jansch -% made minor change in fixedori for consistency of code with respect to -% beamformer_dics (added real() and ctranspose) -% -% Revision 1.10 2008/08/13 16:13:38 roboos -% added option fixedori, not yet fully tested -% -% Revision 1.9 2008/08/13 13:47:42 roboos -% updated documentation -% -% Revision 1.8 2008/07/02 16:02:01 roboos -% fixed bug in % lambda -% -% Revision 1.7 2008/07/02 07:57:33 roboos -% allow specification of percentage noise in lambda, relative to trace(cov)/nchans -% -% Revision 1.6 2008/03/18 13:01:17 roboos -% added optional argument normalizeparam, is passed onto compute_leadfield -% -% Revision 1.5 2008/03/05 16:28:26 roboos -% added some dummy code for subspace projection, not yet finished -% -% Revision 1.4 2007/12/11 11:17:49 roboos -% fixed bug in handling of prespecified dipole moment -% -% Revision 1.3 2006/10/16 15:19:44 roboos -% added keepcov option, also in combination with projectnoise -% fixed obvious bug for progress indicator -% -% Revision 1.2 2006/10/12 10:17:31 roboos -% fixed bug in selecting dipoles on the inside positions only -% output cell-arrays are [] for outside points -% removed catch for mom, fixed dipoles should also work -% -% Revision 1.1 2006/10/12 09:07:07 roboos -% moved code from beamformer into stand-alone functions, for easier use and maintenance -% - -if mod(nargin-5,2) - % the first 5 arguments are fixed, the other arguments should come in pairs - error('invalid number of optional arguments'); -end - -% these optional settings do not have defaults -powmethod = keyval('powmethod', varargin); % the default for this is set below -subspace = keyval('subspace', varargin); % used to implement an "eigenspace beamformer" as described in Sekihara et al. 2002 in HBM -% these settings pertain to the forward model, the defaults are set in compute_leadfield -reducerank = keyval('reducerank', varargin); -normalize = keyval('normalize', varargin); -normalizeparam = keyval('normalizeparam', varargin); -% these optional settings have defaults -feedback = keyval('feedback', varargin); if isempty(feedback), feedback = 'text'; end -keepfilter = keyval('keepfilter', varargin); if isempty(keepfilter), keepfilter = 'no'; end -keepleadfield = keyval('keepleadfield', varargin); if isempty(keepleadfield), keepleadfield = 'no'; end -keepcov = keyval('keepcov', varargin); if isempty(keepcov), keepcov = 'no'; end -keepmom = keyval('keepmom', varargin); if isempty(keepmom), keepmom = 'yes'; end -lambda = keyval('lambda', varargin); if isempty(lambda ), lambda = 0; end -projectnoise = keyval('projectnoise', varargin); if isempty(projectnoise), projectnoise = 'yes'; end -projectmom = keyval('projectmom', varargin); if isempty(projectmom), projectmom = 'no'; end -fixedori = keyval('fixedori', varargin); if isempty(fixedori), fixedori = 'no'; end - -% convert the yes/no arguments to the corresponding logical values -keepfilter = strcmp(keepfilter, 'yes'); -keepleadfield = strcmp(keepleadfield, 'yes'); -keepcov = strcmp(keepcov, 'yes'); -keepmom = strcmp(keepmom, 'yes'); -projectnoise = strcmp(projectnoise, 'yes'); -projectmom = strcmp(projectmom, 'yes'); -fixedori = strcmp(fixedori, 'yes'); - -% default is to use the trace of the covariance matrix, see Van Veen 1997 -if isempty(powmethod) - powmethod = 'trace'; -end - -% use these two logical flags instead of doing the string comparisons each time again -powtrace = strcmp(powmethod, 'trace'); -powlambda1 = strcmp(powmethod, 'lambda1'); - -if isfield(dip, 'mom') && fixedori - error('you cannot specify a dipole orientation and fixedmom simultaneously'); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% find the dipole positions that are inside/outside the brain -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if ~isfield(dip, 'inside') && ~isfield(dip, 'outside'); - [dip.inside, dip.outside] = find_inside_vol(dip.pos, vol); -elseif isfield(dip, 'inside') && ~isfield(dip, 'outside'); - dip.outside = setdiff(1:size(dip.pos,1), dip.inside); -elseif ~isfield(dip, 'inside') && isfield(dip, 'outside'); - dip.inside = setdiff(1:size(dip.pos,1), dip.outside); -end - -% select only the dipole positions inside the brain for scanning -dip.origpos = dip.pos; -dip.originside = dip.inside; -dip.origoutside = dip.outside; -if isfield(dip, 'mom') - dip.mom = dip.mom(:, dip.inside); -end -if isfield(dip, 'leadfield') - fprintf('using precomputed leadfields\n'); - dip.leadfield = dip.leadfield(dip.inside); -end -if isfield(dip, 'filter') - fprintf('using precomputed filters\n'); - dip.filter = dip.filter(dip.inside); -end -if isfield(dip, 'subspace') - fprintf('using subspace projection\n'); - dip.subspace = dip.subspace(dip.inside); -end -dip.pos = dip.pos(dip.inside, :); -dip.inside = 1:size(dip.pos,1); -dip.outside = []; - -isrankdeficient = (rank(Cy)=1 it is the number of largest eigenvalues - dat_pre_subspace = dat; - Cy_pre_subspace = Cy; - [u, s, v] = svd(real(Cy)); - if subspace<1, - sel = find(diag(s)./s(1,1) > subspace); - subspace = max(sel); - else - Cy = s(1:subspace,1:subspace); - % this is equivalent to subspace*Cy*subspace' but behaves well numerically - % by construction. - invCy = diag(1./diag(Cy)); - subspace = u(:,1:subspace)'; - dat = subspace*dat; - end - else - dat_pre_subspace = dat; - Cy_pre_subspace = Cy; - Cy = subspace*Cy*subspace'; % here the subspace can be different from - % the singular vectors of Cy, so we have to do the sandwiching as opposed - % to line 216 - invCy = pinv(Cy); - dat = subspace*dat; - end -end - -% start the scanning with the proper metric -progress('init', feedback, 'scanning grid'); - -for i=1:size(dip.pos,1) - if isfield(dip, 'leadfield') - % reuse the leadfield that was previously computed - lf = dip.leadfield{i}; - elseif isfield(dip, 'mom') - % compute the leadfield for a fixed dipole orientation - lf = compute_leadfield(dip.pos(i,:), grad, vol, 'reducerank', reducerank, 'normalize', normalize, 'normalizeparam', normalizeparam) * dip.mom(:,i); - else - % compute the leadfield - lf = compute_leadfield(dip.pos(i,:), grad, vol, 'reducerank', reducerank, 'normalize', normalize, 'normalizeparam', normalizeparam); - end - - if isfield(dip, 'subspace') - % do subspace projection of the forward model - lf = dip.subspace{i} * lf; - % the data and the covariance become voxel dependent due to the projection - dat = dip.subspace{i} * dat_pre_subspace; - Cy = dip.subspace{i} * (Cy_pre_subspace + lambda * eye(size(Cy_pre_subspace))) * dip.subspace{i}'; - invCy = pinv(dip.subspace{i} * (Cy_pre_subspace + lambda * eye(size(Cy_pre_subspace))) * dip.subspace{i}'); - elseif ~isempty(subspace) - % do subspace projection of the forward model only - lforig = lf; - lf = subspace * lf; - - % according to Kensuke's paper, the eigenspace bf boils down to projecting - % the 'traditional' filter onto the subspace - % spanned by the first k eigenvectors [u,s,v] = svd(Cy); filt = ESES*filt; - % ESES = u(:,1:k)*u(:,1:k)'; - % however, even though it seems that the shape of the filter is identical to - % the shape it is obtained with the following code, the w*lf=I does not hold. - end - - if fixedori - % compute the leadfield for the optimal dipole orientation - % subsequently the leadfield for only that dipole orientation will be used for the final filter computation - % filt = pinv(lf' * invCy * lf) * lf' * invCy; - % [u, s, v] = svd(real(filt * Cy * ctranspose(filt))); - % in this step the filter computation is not necessary, use the quick way to compute the voxel level covariance (cf. van Veen 1997) - [u, s, v] = svd(real(pinv(lf' * invCy *lf))); - eta = u(:,1); - lf = lf * eta; - if ~isempty(subspace), lforig = lforig * eta; end - dipout.ori{i} = eta; - end - - if isfield(dip, 'filter') - % use the provided filter - filt = dip.filter{i}; - else - % construct the spatial filter - filt = pinv(lf' * invCy * lf) * lf' * invCy; % van Veen eqn. 23, use PINV/SVD to cover rank deficient leadfield - end - if projectmom - [u, s, v] = svd(filt * Cy * ctranspose(filt)); - mom = u(:,1); - filt = (mom') * filt; - end - if powlambda1 - % dipout.pow(i) = lambda1(pinv(lf' * invCy * lf)); % this is more efficient if the filters are not present - dipout.pow(i) = lambda1(filt * Cy * ctranspose(filt)); % this is more efficient if the filters are present - elseif powtrace - % dipout.pow(i) = trace(pinv(lf' * invCy * lf)); % this is more efficient if the filters are not present, van Veen eqn. 24 - dipout.pow(i) = trace(filt * Cy * ctranspose(filt)); % this is more efficient if the filters are present - end - if keepcov - % compute the source covariance matrix - dipout.cov{i} = filt * Cy * ctranspose(filt); - end - if keepmom && ~isempty(dat) - % estimate the instantaneous dipole moment at the current position - dipout.mom{i} = filt * dat; - end - if projectnoise - % estimate the power of the noise that is projected through the filter - if powlambda1 - dipout.noise(i) = noise * lambda1(filt * ctranspose(filt)); - elseif powtrace - dipout.noise(i) = noise * trace(filt * ctranspose(filt)); - end - if keepcov - dipout.noisecov{i} = noise * filt * ctranspose(filt); - end - end - if keepfilter - if ~isempty(subspace) - dipout.filter{i} = filt*subspace; - else - dipout.filter{i} = filt; - end - end - if keepleadfield - if ~isempty(subspace) - dipout.leadfield{i} = lforig; - else - dipout.leadfield{i} = lf; - end - end - progress(i/size(dip.pos,1), 'scanning grid %d/%d\n', i, size(dip.pos,1)); -end - -progress('close'); - -dipout.inside = dip.originside; -dipout.outside = dip.origoutside; -dipout.pos = dip.origpos; - -% reassign the scan values over the inside and outside grid positions -if isfield(dipout, 'leadfield') - dipout.leadfield(dipout.inside) = dipout.leadfield; - dipout.leadfield(dipout.outside) = {[]}; -end -if isfield(dipout, 'filter') - dipout.filter(dipout.inside) = dipout.filter; - dipout.filter(dipout.outside) = {[]}; -end -if isfield(dipout, 'mom') - dipout.mom(dipout.inside) = dipout.mom; - dipout.mom(dipout.outside) = {[]}; -end -if isfield(dipout, 'ori') - dipout.ori(dipout.inside) = dipout.ori; - dipout.ori(dipout.outside) = {[]}; -end -if isfield(dipout, 'cov') - dipout.cov(dipout.inside) = dipout.cov; - dipout.cov(dipout.outside) = {[]}; -end -if isfield(dipout, 'noisecov') - dipout.noisecov(dipout.inside) = dipout.noisecov; - dipout.noisecov(dipout.outside) = {[]}; -end -if isfield(dipout, 'pow') - dipout.pow(dipout.inside) = dipout.pow; - dipout.pow(dipout.outside) = nan; -end -if isfield(dipout, 'noise') - dipout.noise(dipout.inside) = dipout.noise; - dipout.noise(dipout.outside) = nan; -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% helper function to obtain the largest singular value -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function s = lambda1(x) -% determine the largest singular value, which corresponds to the power along the dominant direction -s = svd(x); -s = s(1); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% helper function to compute the pseudo inverse. This is the same as the -% standard Matlab function, except that the default tolerance is twice as -% high. -% Copyright 1984-2004 The MathWorks, Inc. -% $Revision: 1.14 $ $Date: 2009/03/23 21:14:42 $ -% default tolerance increased by factor 2 (Robert Oostenveld, 7 Feb 2004) -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function X = pinv(A,varargin) -[m,n] = size(A); -if n > m - X = pinv(A',varargin{:})'; -else - [U,S,V] = svd(A,0); - if m > 1, s = diag(S); - elseif m == 1, s = S(1); - else s = 0; - end - if nargin == 2 - tol = varargin{1}; - else - tol = 10 * max(m,n) * max(s) * eps; - end - r = sum(s > tol); - if (r == 0) - X = zeros(size(A'),class(A)); - else - s = diag(ones(r,1)./s(1:r)); - X = V(:,1:r)*s*U(:,1:r)'; - end -end - diff --git a/external/fieldtrip/private/benchmark.m b/external/fieldtrip/private/benchmark.m deleted file mode 100644 index f243aa1..0000000 --- a/external/fieldtrip/private/benchmark.m +++ /dev/null @@ -1,132 +0,0 @@ -function benchmark(funname, argname, argval, m_array, n_array, niter, varargin) - -% BENCHMARK a given function -% -% Use as -% benchmark(funname, argname, argval, m_array, n_array, niter, ...) -% -% Optional input arguments should come in key-value pairs and may include -% feedback = none, figure, text, table, all -% tableheader = true, false -% tabledata = true, false -% selection = 3x2 array with nchans and nsamples to be used for the table - -% Copyright (C) 2009, Robert Oostenveld -% -% $Log: benchmark.m,v $ -% Revision 1.1 2009/01/07 12:56:48 roboos -% first implementation of helper function for benchmarking the low-level functions that are relevant for real-time processing -% - -% get the optional input arguments -feedback = keyval('feedback', varargin); % none, figure, text, table, all -tableheader = keyval('tableheader', varargin); % true, false -tabledata = keyval('tabledata', varargin); % true, false -selection = keyval('selection', varargin); % 3x2 array with nchans and nsamples to be used for the table - -% set the defaults -if isempty(feedback) - feedback = 'all'; -end -if isempty(tableheader) - tableheader = true; -end -if isempty(tabledata) - tabledata = true; -end -if isempty(selection) - selection = [ - 8 100 - 8 500 - 64 500 - ]; -end - -% convert the function from a string to a handle -funhandle = str2func(funname); - -% this will hold the time that all computations took -t_array = nan(length(m_array), length(n_array)); - -% do the actual benchmarking -for m_indx=1:length(m_array) - for n_indx=1:length(n_array) - - m = m_array(m_indx); - n = n_array(n_indx); - - if strcmp(feedback, 'table') - if ~any(selection(:,1)==m & selection(:,2)==n) - continue - end - end - - % create some random data - dat = randn(m, n); - - elapsed = zeros(1,niter); - for iteration=1:niter - tic; - funhandle(dat, argval{:}); - elapsed(iteration) = toc*1000; % convert from s into ms - end - - % remember the amount of time spent on the computation for this M and N - t_array(m_indx, n_indx) = robustmean(elapsed); - - % give some feedback on screen - if strcmp(feedback, 'text') || strcmp(feedback, 'all') - fprintf('nchans = %d, nsamples = %d, time = %f ms\n', m, n, t_array(m_indx, n_indx)); - end - - end -end - -if strcmp(feedback, 'figure') || strcmp(feedback, 'all') - % give some output in a figure - figure - surf(n_array, m_array, t_array); -end - -if strcmp(feedback, 'table') || strcmp(feedback, 'all') - % give some output to screen that can be copied and pasted into the wiki - - m1 = find(m_array==selection(1,1)); % channels - n1 = find(n_array==selection(1,2)); % samples - m2 = find(m_array==selection(2,1)); % channels - n2 = find(n_array==selection(2,2)); % samples - m3 = find(m_array==selection(3,1)); % channels - n3 = find(n_array==selection(3,2)); % samples - - if tableheader - fprintf('^function name and algorithm details ^ %dch x %dsmp ^ %dch x %dsmp ^ %dch x %dsmp ^\n', ... - m_array(m1), n_array(n1), ... - m_array(m2), n_array(n2), ... - m_array(m3), n_array(n3)); - end - if tabledata - str = []; - dum = sprintf('%s;\n', funname); - str = cat(2, str, dum); - for i=1:length(argval) - dum = printstruct(argname{i}, argval{i}); - str = cat(2, str, dum); - end - str(str==10) = ' '; - fprintf('|%s | %.2f ms | %.2f ms | %.2f ms |\n', str, ... - t_array(m1, n1), ... - t_array(m2, n2), ... - t_array(m3, n3)); - end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION for robust estimation of mean, removing outliers on both sides -% select the central part of the sorted vector, a quarter of the values is removed from both sides -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function y = robustmean(x) -x = sort(x); -n = length(x); -trim = round(0.25*n); -sel = (trim+1):(n-trim); -y = mean(x(sel)); diff --git a/external/fieldtrip/private/besa2fieldtrip.m b/external/fieldtrip/private/besa2fieldtrip.m deleted file mode 100644 index 7465506..0000000 --- a/external/fieldtrip/private/besa2fieldtrip.m +++ /dev/null @@ -1,299 +0,0 @@ -function [data] = besa2fieldtrip(filename); - -% BESA2FIELDTRIP reads and converts various BESA datafiles into a FieldTrip -% data structure, which subsequently can be used for statistical analysis -% or other analysis methods implemented in Fieldtrip. -% -% Use as -% [data] = besa2fieldtrip(filename) -% where the filename should point to a BESA datafile (or data that -% is exported by BESA). The output is a Matlab structure that is -% compatible with FieldTrip. -% -% The format of the output structure depends on the type of datafile: -% *.avr is converted to a structure similar to the output of TIMELOCKANALYSIS -% *.mul is converted to a structure similar to the output of TIMELOCKANALYSIS -% *.swf is converted to a structure similar to the output of TIMELOCKANALYSIS (*) -% *.tfc is converted to a structure similar to the output of FREQANALYSIS (*) -% *.dat is converted to a structure similar to the output of SOURCANALYSIS -% *.dat combined with a *.gen or *.generic is converted to a structure similar to the output of PREPROCESSING -% -% Note (*): If the BESA toolbox by Karsten Hochstatter is found on your -% Matlab path, the readBESAxxx functions will be used (where xxx=tfc/swf), -% alternatively the private functions from FieldTrip will be used. -% -% See also EEGLAB2FIELDTRIP - -% Undocumented local options: -% cfg.filename -% cfg.version - -% Copyright (C) 2005-2007, Robert Oostenveld -% -% $Log: besa2fieldtrip.m,v $ -% Revision 1.16 2008/10/21 09:34:12 roboos -% fixed sampling frequency (factor 1000 wrgon), thanks to Stephan Moratti -% -% Revision 1.15 2008/09/22 21:23:11 roboos -% always add besa path (now as external/besa) -% -% Revision 1.14 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.13 2007/04/24 09:45:56 roboos -% added support for besa simple binary, requires besa toolbox -% -% Revision 1.12 2006/10/05 08:54:14 roboos -% convert time to seconds for TFR data -% -% Revision 1.11 2006/06/27 13:26:51 roboos -% use readBESAswf from besa toolbox if available, otherwise use fieldtrip/private function -% -% Revision 1.10 2006/06/07 09:34:19 roboos -% changed checktoolbox into hastoolbox -% -% Revision 1.9 2006/05/15 13:18:23 roboos -% implemented fixlabels subfunction, use it to convert between char and cell-array -% -% Revision 1.8 2006/04/26 11:36:52 roboos -% detect the presence of the BESA toolbox and added support for reading -% *.tfc using Karstens readBESAtfc function -% -% Revision 1.7 2006/04/20 09:58:33 roboos -% updated documentation -% -% Revision 1.6 2006/03/16 17:36:13 roboos -% added besa_swf -% -% Revision 1.5 2006/02/23 10:28:16 roboos -% changed dimord strings for consistency, changed toi and foi into time and freq, added fixdimord where neccessary -% -% Revision 1.4 2006/02/01 12:26:00 roboos -% made all uses of dimord consistent with the common definition of data dimensions, see the fixdimord() function -% -% Revision 1.3 2005/09/01 09:25:33 roboos -% added beamformer source reconstruction -% -% Revision 1.2 2005/07/29 13:23:58 roboos -% various improvements and fixes -% -% Revision 1.1 2005/07/28 15:08:58 roboos -% new implementation, see documentation on website -% - -fieldtripdefs - -% This function can either use the reading functions included in FieldTrip -% (with contributions from Karsten, Vladimir and Robert), or the official -% released functions by Karsten Hoechstetter from BESA. The functions in the -% official toolbox have precedence. -hasbesa = hastoolbox('besa',1, 1); - -type = filetype(filename); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if strcmp(type, 'besa_avr') - fprintf('reading ERP/ERF\n'); - % this should be similar to the output of TIMELOCKANALYSIS - tmp = read_besa_avr(filename); - % convert into a TIMELOCKANALYSIS compatible data structure - data = []; - data.label = fixlabels(tmp.label); - data.avg = tmp.data; - data.time = (0:(tmp.npnt-1)) * tmp.di + tmp.tsb; - data.time = data.time / 1000; % convert to seconds - data.fsample = 1000/tmp.di; - data.dimord = 'chan_time'; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif strcmp(type, 'besa_mul') - fprintf('reading ERP/ERF\n'); - % this should be similar to the output of TIMELOCKANALYSIS - tmp = read_besa_mul(filename); - % convert into a TIMELOCKANALYSIS compatible data structure - data = []; - data.label = tmp.label(:); - data.avg = tmp.data; - data.time = (0:(tmp.TimePoints-1)) * tmp.SamplingInterval_ms_ + tmp.BeginSweep_ms_; - data.time = data.time / 1000; % convert to seconds - data.fsample = 1000/tmp.SamplingInterval_ms_; - data.dimord = 'chan_time'; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif strcmp(type, 'besa_sb') - if hasbesa - fprintf('reading preprocessed channel data using BESA toolbox\n'); - else - error('this data format requires the BESA toolbox'); - end - [p, f, x] = fileparts(filename); - filename = fullfile(p, [f '.dat']); - [time,buf,ntrial] = readBESAsb(filename); - time = time/1000; % convert from ms to sec - nchan = size(buf,1); - ntime = size(buf,3); - - % convert into a PREPROCESSING compatible data structure - data = []; - data.trial = {}; - data.time = {}; - for i=1:ntrial - data.trial{i} = reshape(buf(:,i,:), [nchan, ntime]); - data.time{i} = time; - end - data.label = {}; - for i=1:size(buf,1) - data.label{i,1} = sprintf('chan%03d', i); - end - data.fsample = 1/(time(2)-time(1)); % time is already in seconds - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif strcmp(type, 'besa_tfc') && hasbesa - fprintf('reading time-frequency representation using BESA toolbox\n'); - % this should be similar to the output of FREQANALYSIS - tfc = readBESAtfc(filename); - Nchan = size(tfc.ChannelLabels,1); - % convert into a FREQANALYSIS compatible data structure - data = []; - data.time = tfc.Time(:)'; - data.freq = tfc.Frequency(:)'; - if isfield(tfc, 'DataType') && strcmp(tfc.DataType, 'COHERENCE_SQUARED') - % it contains coherence between channel pairs - fprintf('reading coherence between %d channel pairs\n', Nchan); - for i=1:Nchan - tmp = tokenize(deblank(tfc.ChannelLabels(i,:)), '-'); - data.labelcmb{i,1} = tmp{1}; - data.labelcmb{i,2} = tmp{2}; - end - data.cohspctrm = permute(tfc.Data, [1 3 2]); - else - % it contains power on channels - fprintf('reading power on %d channels\n', Nchan); - for i=1:Nchan - data.label{i,1} = deblank(tfc.ChannelLabels(i,:)); - end - data.powspctrm = permute(tfc.Data, [1 3 2]); - end - data.dimord = 'chan_freq_time'; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif strcmp(type, 'besa_tfc') && ~hasbesa - fprintf('reading time-frequency representation\n'); - % this should be similar to the output of FREQANALYSIS - [ChannelLabels, Time, Frequency, Data, Info] = read_besa_tfc(filename); - Nchan = size(ChannelLabels,1); - % convert into a FREQANALYSIS compatible data structure - data = []; - data.time = Time * 1e-3; % convert to seconds; - data.freq = Frequency; - if isfield(Info, 'DataType') && strcmp(Info.DataType, 'COHERENCE_SQUARED') - % it contains coherence between channel pairs - fprintf('reading coherence between %d channel pairs\n', Nchan); - for i=1:Nchan - tmp = tokenize(deblank(ChannelLabels(i,:)), '-'); - data.labelcmb{i,1} = tmp{1}; - data.labelcmb{i,2} = tmp{2}; - end - data.cohspctrm = permute(Data, [1 3 2]); - else - % it contains power on channels - fprintf('reading power on %d channels\n', Nchan); - for i=1:Nchan - data.label{i} = deblank(ChannelLabels(i,:)); - end - data.powspctrm = permute(Data, [1 3 2]); - end - data.dimord = 'chan_freq_time'; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif strcmp(type, 'besa_swf') && hasbesa - fprintf('reading source waveform using BESA toolbox\n'); - swf = readBESAswf(filename); - % convert into a TIMELOCKANALYSIS compatible data structure - data = []; - data.label = fixlabels(swf.waveName); - data.avg = swf.data; - data.time = swf.Time * 1e-3; % convert to seconds - data.fsample = 1/(data.time(2)-data.time(1)); - data.dimord = 'chan_time'; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif strcmp(type, 'besa_swf') && ~hasbesa - fprintf('reading source waveform\n'); - % hmm, I guess that this should be similar to the output of TIMELOCKANALYSIS - tmp = read_besa_swf(filename); - % convert into a TIMELOCKANALYSIS compatible data structure - data = []; - data.label = fixlabels(tmp.label); - data.avg = tmp.data; - data.time = (0:(tmp.npnt-1)) * tmp.di + tmp.tsb; - data.time = data.time / 1000; % convert to seconds - data.fsample = 1000/tmp.di; - data.dimord = 'chan_time'; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif strcmp(type, 'besa_src') - src = read_besa_src(filename); - data.xgrid = linspace(src.X(1), src.X(2), src.X(3)); - data.ygrid = linspace(src.Y(1), src.Y(2), src.Y(3)); - data.zgrid = linspace(src.Z(1), src.Z(2), src.Z(3)); - data.avg.pow = src.vol; - data.dim = size(src.vol); - [X, Y, Z] = ndgrid(data.xgrid, data.ygrid, data.zgrid); - data.pos = [X(:) Y(:) Z(:)]; - % cannot determine which voxels are inside the brain volume - data.inside = 1:prod(data.dim); - data.outside = []; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif strcmp(type, 'besa_pdg') - % hmmm, I have to think about this one... - error('sorry, pdg is not yet supported'); - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -else - error('unrecognized file format for importing BESA data'); -end - -% construct and add a configuration to the output -cfg = []; -cfg.filename = filename; -% add the version details of this function call to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: besa2fieldtrip.m,v 1.16 2008/10/21 09:34:12 roboos Exp $'; -data.cfg = cfg; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION that fixes the channel labels, should be a cell-array -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [newlabels] = fixlabels(labels); -if iscell(labels) && length(labels)>1 - % seems to be ok - newlabels = labels; -elseif iscell(labels) && length(labels)==1 - % could be a cell with a single long string in it - if length(tokenize(labels{1}, ' '))>1 - % seems like a long string that accidentaly ended up in a single - cell - newlabels = tokenize(labels{1}, ' '); - else - % seems to be ok - newlabels = labels; - end -elseif ischar(labels) && any(size(labels)==1) - newlabels = tokenize(labels(:)', ' '); % also ensure that it is a - row-string -elseif ischar(labels) && ~any(size(labels)==1) - for i=1:size(labels) - newlabels{i} = fliplr(deblank(fliplr(deblank(labels(i,:))))); - end -end -% convert to column -newlabels = newlabels(:); diff --git a/external/fieldtrip/private/bigendian.m b/external/fieldtrip/private/bigendian.m index f3e4c69..aff84b1 100644 --- a/external/fieldtrip/private/bigendian.m +++ b/external/fieldtrip/private/bigendian.m @@ -12,12 +12,22 @@ % Copyrigth (C) 2007, Robert Oostenveld % -% $Log: bigendian.m,v $ -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.1 2007/01/04 12:10:42 roboos -% new implementation +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: bigendian.m 945 2010-04-21 17:41:20Z roboos $ val = (typecast(uint8([0 1]), 'uint16')==1); diff --git a/external/fieldtrip/private/binocdf.m b/external/fieldtrip/private/binocdf.m new file mode 100644 index 0000000..18a029c --- /dev/null +++ b/external/fieldtrip/private/binocdf.m @@ -0,0 +1,17 @@ +function y=binocdf(x,n,p); + +% BINOCDF binomial cumulative distribution function +% +% Y=BINOCDF(X,N,P) returns the binomial cumulative distribution +% function with parameters N and P at the values in X. +% +% See also BINOPDF and STATS (Matlab statistics toolbox) + +% compute the cumulative probability for all values up to the maximum +c = cumsum(binopdf(0:max(x(:)),n,p)); +y = c(x+1); + +% fix rounding errors +y(y<0) = 0; +y(y>1) = 1; + diff --git a/external/fieldtrip/private/binomialprob.m b/external/fieldtrip/private/binomialprob.m new file mode 100644 index 0000000..d447134 --- /dev/null +++ b/external/fieldtrip/private/binomialprob.m @@ -0,0 +1,88 @@ +function [bp, x] = binomialprob(pobs, alpha, subjratio); + +% BINOMIALPROB computes the probability of observing a significant effect +% in multiple tests. It allows you to test questions like "How likely +% is it that there is a significant effect at this time-frequency point +% for 8 out of 10 subjects, given that the probability of observing a +% significant effect in a given subject is 5%" +% +% Use as +% [bprob] = binomialprob(prob, alpha) +% where +% prob is a Nvoxel X Nsubject matrix with the single-subject probability +% alpha is the probability of observing a significant voxel +% +% The function also has more advanced functionality, please read the code +% if you are interested. +% +% See also BINOPDF, BINOCDF + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: binomialprob.m 952 2010-04-21 18:29:51Z roboos $ + +% determine the number of subjects +[M, N] = size(pobs); + +if nargin<2 + alpha = []; +end + +if nargin<3 + subjratio = []; +end + +if ~isempty(subjratio) + % threshold the statistical maps per subject to obtain the desired ratio + for i=1:N + s = sort(pobs(:,i)); % sort the values over voxels + t = round((1-subjratio) * M); % determine the index of the threshold + a = (pobs(:,i)>=s(t)); % determine the voxels that exceed the threshold + pobs(:,i) = a; % assign the thresholded statistic + end +end + +% determine whether the single subject statistical maps have already been thresholded +isthresh = all(pobs(:)==0 | pobs(:)==1); + +% determine whether the probability for the binomial distribution is specified +isalpha = ~isempty(alpha); + +if isthresh && isalpha + % the probability of observing a significant voxel is specified + p = alpha; + % count the number of subjects in which each voxel is significant + x = sum(pobs, 2); +elseif isthresh && ~isalpha + % estimate the probability from the ratio of thresholded voxels + p = sum(pobs(:))/length(pobs(:)); + % count the number of subjects in which each voxel is significant + x = sum(pobs, 2); +elseif ~isthresh && isalpha + % the probability of observing a significant voxel is specified + p = alpha; + % threshold the single subject probability maps at the alpha level + x = sum(pobs<=alpha, 2); +elseif ~isthresh && ~isalpha + error('can only determine alpha automatically from thresholded statistical maps'); +end + +% this uses Matlab stats toolbox +bp = 1 - binocdf(x, N, p); + diff --git a/external/fieldtrip/private/binopdf.m b/external/fieldtrip/private/binopdf.m new file mode 100644 index 0000000..f18c328 --- /dev/null +++ b/external/fieldtrip/private/binopdf.m @@ -0,0 +1,27 @@ +function y = binopdf(x,n,p) + +% BINOPDF binomial probability density function +% +% Y = BINOPDF(X,N,P) returns the binomial probability density +% function with parameters N and P at the values in X. +% +% See also BINOCDF and STATS (Matlab statistics toolbox) + +if prod(size(p))>1 + error('probability should be a scalar'); +elseif p<0 || p>1 + error('probability should be between 0 and 1'); +end + +if min(x(:))<0 | max(x(:))>n + error('X should be in the range 0:N') +end + +nk = gammaln(n + 1) - gammaln(x + 1) - gammaln(n - x + 1); +lny = nk + x.*log( p) + (n - x).*log(1 - p); +y = exp(lny); + +% fix rounding errors +y(y<0) = 0; +y(y>1) = 1; + diff --git a/external/fieldtrip/private/biosemi128.lay b/external/fieldtrip/private/biosemi128.lay deleted file mode 100644 index 8c918ad..0000000 --- a/external/fieldtrip/private/biosemi128.lay +++ /dev/null @@ -1,150 +0,0 @@ -1 0.000000 0.000000 0.180000 0.140000 A1 -2 0.000000 -0.200713 0.180000 0.140000 A2 -3 0.000000 -0.401426 0.180000 0.140000 A3 -4 0.000000 -0.602139 0.180000 0.140000 A4 -5 -0.307238 -0.741738 0.180000 0.140000 A5 -6 -0.567702 -0.567702 0.180000 0.140000 A6 -7 -0.709627 -0.709627 0.180000 0.140000 A7 -8 -0.707856 -0.974281 0.180000 0.140000 A8 -9 -0.825832 -1.136661 0.180000 0.140000 A9 -10 -0.943808 -1.299041 0.180000 0.140000 A10 -11 -1.061785 -1.461421 0.180000 0.140000 A11 -12 -1.179761 -1.623801 0.180000 0.140000 A12 -13 -0.620237 -1.908893 0.180000 0.140000 A13 -14 -0.558213 -1.718003 0.180000 0.140000 A14 -15 -0.496189 -1.527114 0.180000 0.140000 A15 -16 -0.434166 -1.336225 0.180000 0.140000 A16 -17 -0.372142 -1.145336 0.180000 0.140000 A17 -18 -0.384047 -0.927173 0.180000 0.140000 A18 -19 0.000000 -0.802851 0.180000 0.140000 A19 -20 0.000000 -1.003564 0.180000 0.140000 A20 -21 0.000000 -1.204277 0.180000 0.140000 A21 -22 0.000000 -1.404990 0.180000 0.140000 A22 -23 0.000000 -1.605703 0.180000 0.140000 A23 -24 0.000000 -1.806416 0.180000 0.140000 A24 -25 0.000000 -2.007129 0.180000 0.140000 A25 -26 0.620237 -1.908893 0.180000 0.140000 A26 -27 0.558213 -1.718003 0.180000 0.140000 A27 -28 0.496189 -1.527114 0.180000 0.140000 A28 -29 0.434166 -1.336225 0.180000 0.140000 A29 -30 0.372142 -1.145336 0.180000 0.140000 A30 -31 0.384047 -0.927173 0.180000 0.140000 A31 -32 0.307238 -0.741738 0.180000 0.140000 A32 -33 0.190889 -0.062024 0.180000 0.140000 B1 -34 0.283851 -0.283851 0.180000 0.140000 B2 -35 0.567702 -0.567702 0.180000 0.140000 B3 -36 0.709627 -0.709627 0.180000 0.140000 B4 -37 0.707856 -0.974281 0.180000 0.140000 B5 -38 0.825832 -1.136661 0.180000 0.140000 B6 -39 0.943808 -1.299041 0.180000 0.140000 B7 -40 1.061785 -1.461421 0.180000 0.140000 B8 -41 1.179761 -1.623801 0.180000 0.140000 B9 -42 1.461421 -1.061785 0.180000 0.140000 B10 -43 1.299041 -0.943808 0.180000 0.140000 B11 -44 1.136661 -0.825832 0.180000 0.140000 B12 -45 0.974281 -0.707856 0.180000 0.140000 B13 -46 1.527114 -0.496189 0.180000 0.140000 B14 -47 1.336225 -0.434166 0.180000 0.140000 B15 -48 1.145336 -0.372142 0.180000 0.140000 B16 -49 0.927173 -0.384047 0.180000 0.140000 B17 -50 0.741738 -0.307238 0.180000 0.140000 B18 -51 0.521467 -0.301069 0.180000 0.140000 B19 -52 0.401426 0.000000 0.180000 0.140000 B20 -53 0.602139 0.000000 0.180000 0.140000 B21 -54 0.802851 0.000000 0.180000 0.140000 B22 -55 1.003564 0.000000 0.180000 0.140000 B23 -56 1.204277 0.000000 0.180000 0.140000 B24 -57 1.404990 0.000000 0.180000 0.140000 B25 -58 1.605703 0.000000 0.180000 0.140000 B26 -59 1.527114 0.496189 0.180000 0.140000 B27 -60 1.336225 0.434166 0.180000 0.140000 B28 -61 1.145336 0.372142 0.180000 0.140000 B29 -62 0.927173 0.384047 0.180000 0.140000 B30 -63 0.741738 0.307238 0.180000 0.140000 B31 -64 0.521467 0.301069 0.180000 0.140000 B32 -65 0.117976 0.162380 0.180000 0.140000 C1 -66 0.283851 0.283851 0.180000 0.140000 C2 -67 0.567702 0.567702 0.180000 0.140000 C3 -68 0.709627 0.709627 0.180000 0.140000 C4 -69 0.974281 0.707856 0.180000 0.140000 C5 -70 1.136661 0.825832 0.180000 0.140000 C6 -71 1.299041 0.943808 0.180000 0.140000 C7 -72 0.943808 1.299041 0.180000 0.140000 C8 -73 0.825832 1.136661 0.180000 0.140000 C9 -74 0.707856 0.974281 0.180000 0.140000 C10 -75 0.301069 0.521467 0.180000 0.140000 C11 -76 0.307238 0.741738 0.180000 0.140000 C12 -77 0.384047 0.927173 0.180000 0.140000 C13 -78 0.372142 1.145336 0.180000 0.140000 C14 -79 0.434166 1.336225 0.180000 0.140000 C15 -80 0.496189 1.527114 0.180000 0.140000 C16 -81 0.000000 1.605703 0.180000 0.140000 C17 -82 0.000000 1.404990 0.180000 0.140000 C18 -83 0.000000 1.204277 0.180000 0.140000 C19 -84 0.000000 1.003564 0.180000 0.140000 C20 -85 0.000000 0.802851 0.180000 0.140000 C21 -86 0.000000 0.602139 0.180000 0.140000 C22 -87 0.000000 0.401426 0.180000 0.140000 C23 -88 -0.301069 0.521467 0.180000 0.140000 C24 -89 -0.307238 0.741738 0.180000 0.140000 C25 -90 -0.384047 0.927173 0.180000 0.140000 C26 -91 -0.372142 1.145336 0.180000 0.140000 C27 -92 -0.434166 1.336225 0.180000 0.140000 C28 -93 -0.496189 1.527114 0.180000 0.140000 C29 -94 -0.943808 1.299041 0.180000 0.140000 C30 -95 -0.825832 1.136661 0.180000 0.140000 C31 -96 -0.707856 0.974281 0.180000 0.140000 C32 -97 -0.117976 0.162380 0.180000 0.140000 D1 -98 -0.283851 0.283851 0.180000 0.140000 D2 -99 -0.567702 0.567702 0.180000 0.140000 D3 -100 -0.709627 0.709627 0.180000 0.140000 D4 -101 -0.974281 0.707856 0.180000 0.140000 D5 -102 -1.136661 0.825832 0.180000 0.140000 D6 -103 -1.299041 0.943808 0.180000 0.140000 D7 -104 -1.527114 0.496189 0.180000 0.140000 D8 -105 -1.336225 0.434166 0.180000 0.140000 D9 -106 -1.145336 0.372142 0.180000 0.140000 D10 -107 -0.927173 0.384047 0.180000 0.140000 D11 -108 -0.741738 0.307238 0.180000 0.140000 D12 -109 -0.521467 0.301069 0.180000 0.140000 D13 -110 -0.401426 -0.000000 0.180000 0.140000 D14 -111 -0.190889 -0.062024 0.180000 0.140000 D15 -112 -0.283851 -0.283851 0.180000 0.140000 D16 -113 -0.521467 -0.301069 0.180000 0.140000 D17 -114 -0.602139 -0.000000 0.180000 0.140000 D18 -115 -0.802851 -0.000000 0.180000 0.140000 D19 -116 -1.003564 -0.000000 0.180000 0.140000 D20 -117 -1.204277 -0.000000 0.180000 0.140000 D21 -118 -1.404990 -0.000000 0.180000 0.140000 D22 -119 -1.605703 -0.000000 0.180000 0.140000 D23 -120 -1.527114 -0.496189 0.180000 0.140000 D24 -121 -1.336225 -0.434166 0.180000 0.140000 D25 -122 -1.145336 -0.372142 0.180000 0.140000 D26 -123 -0.927173 -0.384047 0.180000 0.140000 D27 -124 -0.741738 -0.307238 0.180000 0.140000 D28 -125 -0.974281 -0.707856 0.180000 0.140000 D29 -126 -1.136661 -0.825832 0.180000 0.140000 D30 -127 -1.299041 -0.943808 0.180000 0.140000 D31 -128 -1.461421 -1.061785 0.180000 0.140000 D32 -129 0.000000 0.000000 0.180000 0.140000 Cz -130 0.000000 -0.401426 0.180000 0.140000 CPz -131 0.000000 -0.802851 0.180000 0.140000 Pz -132 0.000000 -1.204277 0.180000 0.140000 Poz -133 0.000000 -1.605703 0.180000 0.140000 Oz -134 0.000000 -2.007129 0.180000 0.140000 Iz -135 1.299041 -0.943808 0.180000 0.140000 F8 -136 0.401426 0.000000 0.180000 0.140000 C2 -137 0.802851 0.000000 0.180000 0.140000 C4 -138 1.204277 0.000000 0.180000 0.140000 C6 -139 1.605703 0.000000 0.180000 0.140000 T8 -140 1.299041 0.943808 0.180000 0.140000 F8 -141 0.000000 1.605703 0.180000 0.140000 Fpz -142 0.000000 1.204277 0.180000 0.140000 Afz -143 0.000000 0.802851 0.180000 0.140000 Fz -144 0.000000 0.401426 0.180000 0.140000 FCz -145 -1.299041 0.943808 0.180000 0.140000 F7 -146 -0.401426 -0.000000 0.180000 0.140000 C1 -147 -0.802851 -0.000000 0.180000 0.140000 C3 -148 -1.204277 -0.000000 0.180000 0.140000 C5 -149 -1.605703 -0.000000 0.180000 0.140000 T7 -150 -1.299041 -0.943808 0.180000 0.140000 P7 diff --git a/external/fieldtrip/private/biosemi16.lay b/external/fieldtrip/private/biosemi16.lay deleted file mode 100644 index d1716bf..0000000 --- a/external/fieldtrip/private/biosemi16.lay +++ /dev/null @@ -1,16 +0,0 @@ -1 -0.496189 1.527114 0.450000 0.350000 Fp1 -2 0.496189 1.527114 0.450000 0.350000 Fp2 -3 0.659023 0.813825 0.450000 0.350000 F4 -4 0.000000 0.802851 0.450000 0.350000 Fz -5 -0.659023 0.813825 0.450000 0.350000 F3 -6 -1.605703 -0.000000 0.450000 0.350000 T7 -7 -0.802851 -0.000000 0.450000 0.350000 C3 -8 0.000000 0.000000 0.450000 0.350000 Cz -9 0.802851 0.000000 0.450000 0.350000 C4 -10 1.605703 0.000000 0.450000 0.350000 T8 -11 0.659023 -0.813825 0.450000 0.350000 P4 -12 0.000000 -0.802851 0.450000 0.350000 Pz -13 -0.659023 -0.813825 0.450000 0.350000 P3 -14 -0.496189 -1.527114 0.450000 0.350000 O1 -15 0.000000 -1.605703 0.450000 0.350000 Oz -16 0.496189 -1.527114 0.450000 0.350000 O2 diff --git a/external/fieldtrip/private/biosemi160.lay b/external/fieldtrip/private/biosemi160.lay deleted file mode 100644 index c07a265..0000000 --- a/external/fieldtrip/private/biosemi160.lay +++ /dev/null @@ -1,169 +0,0 @@ -1 0.000000 0.000000 0.180000 0.140000 A1 -2 0.000000 -0.200713 0.180000 0.140000 A2 -3 0.000000 -0.401426 0.180000 0.140000 A3 -4 0.000000 -0.602139 0.180000 0.140000 A4 -5 -0.248095 -0.763557 0.180000 0.140000 A5 -6 -0.471904 -0.649520 0.180000 0.140000 A6 -7 -0.589880 -0.811901 0.180000 0.140000 A7 -8 -0.602139 -1.042935 0.180000 0.140000 A8 -9 -0.702495 -1.216757 0.180000 0.140000 A9 -10 -0.802851 -1.390580 0.180000 0.140000 A10 -11 -0.903208 -1.564402 0.180000 0.140000 A11 -12 -1.003564 -1.738224 0.180000 0.140000 A12 -13 -0.519483 -1.938737 0.180000 0.140000 A13 -14 -0.467535 -1.744864 0.180000 0.140000 A14 -15 -0.415586 -1.550990 0.180000 0.140000 A15 -16 -0.363638 -1.357116 0.180000 0.140000 A16 -17 -0.311690 -1.163242 0.180000 0.140000 A17 -18 -0.310118 -0.954446 0.180000 0.140000 A18 -19 0.000000 -0.802851 0.180000 0.140000 A19 -20 0.000000 -1.003564 0.180000 0.140000 A20 -21 0.000000 -1.204277 0.180000 0.140000 A21 -22 0.000000 -1.404990 0.180000 0.140000 A22 -23 0.000000 -1.605703 0.180000 0.140000 A23 -24 0.000000 -1.806416 0.180000 0.140000 A24 -25 0.000000 -2.007129 0.180000 0.140000 A25 -26 0.519483 -1.938737 0.180000 0.140000 A26 -27 0.467535 -1.744864 0.180000 0.140000 A27 -28 0.415586 -1.550990 0.180000 0.140000 A28 -29 0.363638 -1.357116 0.180000 0.140000 A29 -30 0.311690 -1.163242 0.180000 0.140000 A30 -31 0.310118 -0.954446 0.180000 0.140000 A31 -32 0.248095 -0.763557 0.180000 0.140000 A32 -33 0.190889 -0.062024 0.180000 0.140000 B1 -34 0.200713 -0.347645 0.180000 0.140000 B2 -35 0.471904 -0.649520 0.180000 0.140000 B3 -36 0.589880 -0.811901 0.180000 0.140000 B4 -37 0.602139 -1.042935 0.180000 0.140000 B5 -38 0.702495 -1.216757 0.180000 0.140000 B6 -39 0.802851 -1.390580 0.180000 0.140000 B7 -40 0.903208 -1.564402 0.180000 0.140000 B8 -41 1.003564 -1.738224 0.180000 0.140000 B9 -42 1.419254 -1.419254 0.180000 0.140000 B10 -43 1.277329 -1.277329 0.180000 0.140000 B11 -44 1.135403 -1.135403 0.180000 0.140000 B12 -45 0.993478 -0.993478 0.180000 0.140000 B13 -46 0.851553 -0.851553 0.180000 0.140000 B14 -47 1.042935 -0.602139 0.180000 0.140000 B15 -48 1.216757 -0.702495 0.180000 0.140000 B16 -49 1.390580 -0.802851 0.180000 0.140000 B17 -50 1.564402 -0.903208 0.180000 0.140000 B18 -51 1.550990 -0.415586 0.180000 0.140000 B19 -52 1.357116 -0.363638 0.180000 0.140000 B20 -53 1.163242 -0.311690 0.180000 0.140000 B21 -54 0.811901 -0.589880 0.180000 0.140000 B22 -55 0.649520 -0.471904 0.180000 0.140000 B23 -56 0.425776 -0.425776 0.180000 0.140000 B24 -57 0.347645 -0.200713 0.180000 0.140000 B25 -58 0.556304 -0.230428 0.180000 0.140000 B26 -59 0.763557 -0.248095 0.180000 0.140000 B27 -60 0.954446 -0.310118 0.180000 0.140000 B28 -61 1.003564 0.000000 0.180000 0.140000 B29 -62 1.204277 0.000000 0.180000 0.140000 B30 -63 1.404990 0.000000 0.180000 0.140000 B31 -64 1.605703 0.000000 0.180000 0.140000 B32 -65 0.117976 0.162380 0.180000 0.140000 C1 -66 0.347645 0.200713 0.180000 0.140000 C2 -67 0.401426 0.000000 0.180000 0.140000 C3 -68 0.602139 0.000000 0.180000 0.140000 C4 -69 0.556304 0.230428 0.180000 0.140000 C5 -70 0.763557 0.248095 0.180000 0.140000 C6 -71 0.802851 0.000000 0.180000 0.140000 C7 -72 0.954446 0.310118 0.180000 0.140000 C8 -73 1.163242 0.311690 0.180000 0.140000 C9 -74 1.357116 0.363638 0.180000 0.140000 C10 -75 1.550990 0.415586 0.180000 0.140000 C11 -76 1.390580 0.802851 0.180000 0.140000 C12 -77 1.216757 0.702495 0.180000 0.140000 C13 -78 1.042935 0.602139 0.180000 0.140000 C14 -79 0.851553 0.851553 0.180000 0.140000 C15 -80 0.993478 0.993478 0.180000 0.140000 C16 -81 1.135403 1.135403 0.180000 0.140000 C17 -82 0.802851 1.390580 0.180000 0.140000 C18 -83 0.702495 1.216757 0.180000 0.140000 C19 -84 0.602139 1.042935 0.180000 0.140000 C20 -85 0.589880 0.811901 0.180000 0.140000 C21 -86 0.811901 0.589880 0.180000 0.140000 C22 -87 0.649520 0.471904 0.180000 0.140000 C23 -88 0.425776 0.425776 0.180000 0.140000 C24 -89 0.200713 0.347645 0.180000 0.140000 C25 -90 0.230428 0.556304 0.180000 0.140000 C26 -91 0.471904 0.649520 0.180000 0.140000 C27 -92 0.248095 0.763557 0.180000 0.140000 C28 -93 0.310118 0.954446 0.180000 0.140000 C29 -94 0.311690 1.163242 0.180000 0.140000 C30 -95 0.363638 1.357116 0.180000 0.140000 C31 -96 0.415586 1.550990 0.180000 0.140000 C32 -97 -0.117976 0.162380 0.180000 0.140000 D1 -98 0.000000 0.401426 0.180000 0.140000 D2 -99 0.000000 0.602139 0.180000 0.140000 D3 -100 0.000000 0.802851 0.180000 0.140000 D4 -101 0.000000 1.003564 0.180000 0.140000 D5 -102 0.000000 1.204277 0.180000 0.140000 D6 -103 0.000000 1.404990 0.180000 0.140000 D7 -104 0.000000 1.605703 0.180000 0.140000 D8 -105 -0.415586 1.550990 0.180000 0.140000 D9 -106 -0.363638 1.357116 0.180000 0.140000 D10 -107 -0.311690 1.163242 0.180000 0.140000 D11 -108 -0.310118 0.954446 0.180000 0.140000 D12 -109 -0.248095 0.763557 0.180000 0.140000 D13 -110 -0.230428 0.556304 0.180000 0.140000 D14 -111 -0.200713 0.347645 0.180000 0.140000 D15 -112 -0.347645 0.200713 0.180000 0.140000 D16 -113 -0.425776 0.425776 0.180000 0.140000 D17 -114 -0.471904 0.649520 0.180000 0.140000 D18 -115 -0.589880 0.811901 0.180000 0.140000 D19 -116 -0.602139 1.042935 0.180000 0.140000 D20 -117 -0.702495 1.216757 0.180000 0.140000 D21 -118 -0.802851 1.390580 0.180000 0.140000 D22 -119 -1.135403 1.135403 0.180000 0.140000 D23 -120 -0.993478 0.993478 0.180000 0.140000 D24 -121 -0.851553 0.851553 0.180000 0.140000 D25 -122 -0.811901 0.589880 0.180000 0.140000 D26 -123 -0.649520 0.471904 0.180000 0.140000 D27 -124 -0.556304 0.230428 0.180000 0.140000 D28 -125 -0.763557 0.248095 0.180000 0.140000 D29 -126 -1.042935 0.602139 0.180000 0.140000 D30 -127 -1.216757 0.702495 0.180000 0.140000 D31 -128 -1.390580 0.802851 0.180000 0.140000 D32 -129 -0.190889 -0.062024 0.180000 0.140000 E1 -130 -0.401426 -0.000000 0.180000 0.140000 E2 -131 -0.602139 -0.000000 0.180000 0.140000 E3 -132 -0.802851 -0.000000 0.180000 0.140000 E4 -133 -0.954446 0.310118 0.180000 0.140000 E5 -134 -1.163242 0.311690 0.180000 0.140000 E6 -135 -1.357116 0.363638 0.180000 0.140000 E7 -136 -1.550990 0.415586 0.180000 0.140000 E8 -137 -1.605703 -0.000000 0.180000 0.140000 E9 -138 -1.404990 -0.000000 0.180000 0.140000 E10 -139 -1.204277 -0.000000 0.180000 0.140000 E11 -140 -1.003564 -0.000000 0.180000 0.140000 E12 -141 -0.954446 -0.310118 0.180000 0.140000 E13 -142 -1.163242 -0.311690 0.180000 0.140000 E14 -143 -1.357116 -0.363638 0.180000 0.140000 E15 -144 -1.550990 -0.415586 0.180000 0.140000 E16 -145 -1.564402 -0.903208 0.180000 0.140000 E17 -146 -1.390580 -0.802851 0.180000 0.140000 E18 -147 -1.216757 -0.702495 0.180000 0.140000 E19 -148 -1.042935 -0.602139 0.180000 0.140000 E20 -149 -0.763557 -0.248095 0.180000 0.140000 E21 -150 -0.556304 -0.230428 0.180000 0.140000 E22 -151 -0.347645 -0.200713 0.180000 0.140000 E23 -152 -0.200713 -0.347645 0.180000 0.140000 E24 -153 -0.425776 -0.425776 0.180000 0.140000 E25 -154 -0.649520 -0.471904 0.180000 0.140000 E26 -155 -0.811901 -0.589880 0.180000 0.140000 E27 -156 -0.851553 -0.851553 0.180000 0.140000 E28 -157 -0.993478 -0.993478 0.180000 0.140000 E29 -158 -1.135403 -1.135403 0.180000 0.140000 E30 -159 -1.277329 -1.277329 0.180000 0.140000 E31 -160 -1.419254 -1.419254 0.180000 0.140000 E32 -161 0.000000 0.000000 0.180000 0.140000 Cz -162 0.000000 -0.802851 0.180000 0.140000 Pz -163 0.000000 -1.605703 0.180000 0.140000 Oz -164 1.605703 0.000000 0.180000 0.140000 T8 -165 0.802851 0.000000 0.180000 0.140000 C4 -166 0.000000 0.802851 0.180000 0.140000 Fz -167 0.000000 1.605703 0.180000 0.140000 Fpz -168 -0.802851 -0.000000 0.180000 0.140000 C3 -169 -1.605703 -0.000000 0.180000 0.140000 T7 diff --git a/external/fieldtrip/private/biosemi256.lay b/external/fieldtrip/private/biosemi256.lay deleted file mode 100644 index db032e2..0000000 --- a/external/fieldtrip/private/biosemi256.lay +++ /dev/null @@ -1,265 +0,0 @@ -1 0.000000 0.000000 0.140000 0.110000 A1 -2 0.000000 -0.160570 0.140000 0.110000 A2 -3 0.000000 -0.321141 0.140000 0.110000 A3 -4 0.000000 -0.481711 0.140000 0.110000 A4 -5 0.000000 -0.642281 0.140000 0.110000 A5 -6 0.000000 -0.802851 0.140000 0.110000 A6 -7 -0.207793 -0.775495 0.140000 0.110000 A7 -8 -0.249352 -0.930594 0.140000 0.110000 A8 -9 -0.233691 -1.099430 0.140000 0.110000 A9 -10 -0.267076 -1.256492 0.140000 0.110000 A10 -11 -0.281931 -1.417365 0.140000 0.110000 A11 -12 -0.313257 -1.574850 0.140000 0.110000 A12 -13 -0.344583 -1.732335 0.140000 0.110000 A13 -14 -0.400613 -1.884737 0.140000 0.110000 A14 -15 -0.433998 -2.041799 0.140000 0.110000 A15 -16 0.000000 -2.087414 0.140000 0.110000 A16 -17 0.000000 -1.926843 0.140000 0.110000 A17 -18 0.000000 -1.766273 0.140000 0.110000 A18 -19 0.000000 -1.605703 0.140000 0.110000 A19 -20 0.000000 -1.445133 0.140000 0.110000 A20 -21 0.000000 -1.284562 0.140000 0.110000 A21 -22 0.000000 -1.123992 0.140000 0.110000 A22 -23 0.000000 -0.963422 0.140000 0.110000 A23 -24 0.207793 -0.775495 0.140000 0.110000 A24 -25 0.249352 -0.930594 0.140000 0.110000 A25 -26 0.233691 -1.099430 0.140000 0.110000 A26 -27 0.267076 -1.256492 0.140000 0.110000 A27 -28 0.281931 -1.417365 0.140000 0.110000 A28 -29 0.313257 -1.574850 0.140000 0.110000 A29 -30 0.344583 -1.732335 0.140000 0.110000 A30 -31 0.400613 -1.884737 0.140000 0.110000 A31 -32 0.433998 -2.041799 0.140000 0.110000 A32 -33 0.188762 -0.259808 0.140000 0.110000 B1 -34 0.195929 -0.440065 0.140000 0.110000 B2 -35 0.377523 -0.519616 0.140000 0.110000 B3 -36 0.401426 -0.695290 0.140000 0.110000 B4 -37 0.481711 -0.834348 0.140000 0.110000 B5 -38 0.457169 -1.026818 0.140000 0.110000 B6 -39 0.522479 -1.173506 0.140000 0.110000 B7 -40 0.553028 -1.335128 0.140000 0.110000 B8 -41 0.614476 -1.483476 0.140000 0.110000 B9 -42 0.675923 -1.631824 0.140000 0.110000 B10 -43 0.783718 -1.760259 0.140000 0.110000 B11 -44 0.849028 -1.906947 0.140000 0.110000 B12 -45 1.132570 -1.558849 0.140000 0.110000 B13 -46 0.981289 -1.468602 0.140000 0.110000 B14 -47 0.892081 -1.335093 0.140000 0.110000 B15 -48 0.802873 -1.201584 0.140000 0.110000 B16 -49 0.755047 -1.039233 0.140000 0.110000 B17 -50 0.660666 -0.909329 0.140000 0.110000 B18 -51 0.681242 -0.681242 0.140000 0.110000 B19 -52 0.567702 -0.567702 0.140000 0.110000 B20 -53 0.357981 -0.322327 0.140000 0.110000 B21 -54 0.519616 -0.377523 0.140000 0.110000 B22 -55 0.695290 -0.401426 0.140000 0.110000 B23 -56 0.834348 -0.481711 0.140000 0.110000 B24 -57 0.835289 -0.752097 0.140000 0.110000 B25 -58 0.954616 -0.859540 0.140000 0.110000 B26 -59 1.021863 -1.021863 0.140000 0.110000 B27 -60 1.135403 -1.135403 0.140000 0.110000 B28 -61 1.248944 -1.248944 0.140000 0.110000 B29 -62 1.431924 -1.289310 0.140000 0.110000 B30 -63 1.668695 -0.963422 0.140000 0.110000 B31 -64 1.468602 -0.981289 0.140000 0.110000 B32 -65 0.152711 -0.049619 0.140000 0.110000 C1 -66 0.305423 -0.099238 0.140000 0.110000 C2 -67 0.458134 -0.148857 0.140000 0.110000 C3 -68 0.610846 -0.198476 0.140000 0.110000 C4 -69 0.775495 -0.207793 0.140000 0.110000 C5 -70 0.930594 -0.249352 0.140000 0.110000 C6 -71 1.068980 -0.347333 0.140000 0.110000 C7 -72 0.973406 -0.561996 0.140000 0.110000 C8 -73 1.112464 -0.642281 0.140000 0.110000 C9 -74 1.201584 -0.802873 0.140000 0.110000 C10 -75 1.335093 -0.892081 0.140000 0.110000 C11 -76 1.631824 -0.675923 0.140000 0.110000 C12 -77 1.483476 -0.614476 0.140000 0.110000 C13 -78 1.335128 -0.553028 0.140000 0.110000 C14 -79 1.221691 -0.396952 0.140000 0.110000 C15 -80 1.417365 -0.281931 0.140000 0.110000 C16 -81 1.574850 -0.313257 0.140000 0.110000 C17 -82 1.605703 0.000000 0.140000 0.110000 C18 -83 1.445133 0.000000 0.140000 0.110000 C19 -84 1.277525 -0.134273 0.140000 0.110000 C20 -85 1.117835 -0.117489 0.140000 0.110000 C21 -86 0.963422 0.000000 0.140000 0.110000 C22 -87 0.802851 0.000000 0.140000 0.110000 C23 -88 0.642281 0.000000 0.140000 0.110000 C24 -89 0.479072 0.050352 0.140000 0.110000 C25 -90 0.610846 0.198476 0.140000 0.110000 C26 -91 0.775495 0.207793 0.140000 0.110000 C27 -92 0.930594 0.249352 0.140000 0.110000 C28 -93 1.117835 0.117489 0.140000 0.110000 C29 -94 1.277525 0.134273 0.140000 0.110000 C30 -95 1.417365 0.281931 0.140000 0.110000 C31 -96 1.574850 0.313257 0.140000 0.110000 C32 -97 0.094381 0.129904 0.140000 0.110000 D1 -98 0.305423 0.099238 0.140000 0.110000 D2 -99 0.417174 0.240855 0.140000 0.110000 D3 -100 0.519616 0.377523 0.140000 0.110000 D4 -101 0.695290 0.401426 0.140000 0.110000 D5 -102 1.068980 0.347333 0.140000 0.110000 D6 -103 1.221691 0.396952 0.140000 0.110000 D7 -104 1.335128 0.553028 0.140000 0.110000 D8 -105 1.483476 0.614476 0.140000 0.110000 D9 -106 1.631824 0.675923 0.140000 0.110000 D10 -107 1.468602 0.981289 0.140000 0.110000 D11 -108 1.335093 0.892081 0.140000 0.110000 D12 -109 1.201584 0.802873 0.140000 0.110000 D13 -110 1.112464 0.642281 0.140000 0.110000 D14 -111 0.973406 0.561996 0.140000 0.110000 D15 -112 0.834348 0.481711 0.140000 0.110000 D16 -113 0.567702 0.567702 0.140000 0.110000 D17 -114 0.681242 0.681242 0.140000 0.110000 D18 -115 0.835289 0.752097 0.140000 0.110000 D19 -116 0.954616 0.859540 0.140000 0.110000 D20 -117 1.021863 1.021863 0.140000 0.110000 D21 -118 1.135403 1.135403 0.140000 0.110000 D22 -119 1.248944 1.248944 0.140000 0.110000 D23 -120 0.892081 1.335093 0.140000 0.110000 D24 -121 0.802873 1.201584 0.140000 0.110000 D25 -122 0.755047 1.039233 0.140000 0.110000 D26 -123 0.660666 0.909329 0.140000 0.110000 D27 -124 0.481711 0.834348 0.140000 0.110000 D28 -125 0.457169 1.026818 0.140000 0.110000 D29 -126 0.522479 1.173506 0.140000 0.110000 D30 -127 0.553028 1.335128 0.140000 0.110000 D31 -128 0.614476 1.483476 0.140000 0.110000 D32 -129 0.000000 0.321141 0.140000 0.110000 E1 -130 0.188762 0.259808 0.140000 0.110000 E2 -131 0.283143 0.389712 0.140000 0.110000 E3 -132 0.377523 0.519616 0.140000 0.110000 E4 -133 0.401426 0.695290 0.140000 0.110000 E5 -134 0.207793 0.775495 0.140000 0.110000 E6 -135 0.249352 0.930594 0.140000 0.110000 E7 -136 0.233691 1.099430 0.140000 0.110000 E8 -137 0.267076 1.256492 0.140000 0.110000 E9 -138 0.281931 1.417365 0.140000 0.110000 E10 -139 0.313257 1.574850 0.140000 0.110000 E11 -140 0.000000 1.605703 0.140000 0.110000 E12 -141 0.000000 1.445133 0.140000 0.110000 E13 -142 0.000000 1.284562 0.140000 0.110000 E14 -143 0.000000 1.123992 0.140000 0.110000 E15 -144 0.000000 0.963422 0.140000 0.110000 E16 -145 0.000000 0.802851 0.140000 0.110000 E17 -146 0.000000 0.642281 0.140000 0.110000 E18 -147 0.198476 0.610846 0.140000 0.110000 E19 -148 0.100153 0.471184 0.140000 0.110000 E20 -149 -0.100153 0.471184 0.140000 0.110000 E21 -150 -0.198476 0.610846 0.140000 0.110000 E22 -151 -0.207793 0.775495 0.140000 0.110000 E23 -152 -0.249352 0.930594 0.140000 0.110000 E24 -153 -0.233691 1.099430 0.140000 0.110000 E25 -154 -0.267076 1.256492 0.140000 0.110000 E26 -155 -0.281931 1.417365 0.140000 0.110000 E27 -156 -0.313257 1.574850 0.140000 0.110000 E28 -157 -0.614476 1.483476 0.140000 0.110000 E29 -158 -0.553028 1.335128 0.140000 0.110000 E30 -159 -0.522479 1.173506 0.140000 0.110000 E31 -160 -0.457169 1.026818 0.140000 0.110000 E32 -161 -0.094381 0.129904 0.140000 0.110000 F1 -162 -0.188762 0.259808 0.140000 0.110000 F2 -163 -0.283143 0.389712 0.140000 0.110000 F3 -164 -0.377523 0.519616 0.140000 0.110000 F4 -165 -0.401426 0.695290 0.140000 0.110000 F5 -166 -0.481711 0.834348 0.140000 0.110000 F6 -167 -0.660666 0.909329 0.140000 0.110000 F7 -168 -0.755047 1.039233 0.140000 0.110000 F8 -169 -0.802873 1.201584 0.140000 0.110000 F9 -170 -0.892081 1.335093 0.140000 0.110000 F10 -171 -1.248944 1.248944 0.140000 0.110000 F11 -172 -1.135403 1.135403 0.140000 0.110000 F12 -173 -1.021863 1.021863 0.140000 0.110000 F13 -174 -0.954616 0.859540 0.140000 0.110000 F14 -175 -0.835289 0.752097 0.140000 0.110000 F15 -176 -0.681242 0.681242 0.140000 0.110000 F16 -177 -0.567702 0.567702 0.140000 0.110000 F17 -178 -0.519616 0.377523 0.140000 0.110000 F18 -179 -0.417174 0.240855 0.140000 0.110000 F19 -180 -0.305423 0.099238 0.140000 0.110000 F20 -181 -0.479072 0.050352 0.140000 0.110000 F21 -182 -0.610846 0.198476 0.140000 0.110000 F22 -183 -0.695290 0.401426 0.140000 0.110000 F23 -184 -0.834348 0.481711 0.140000 0.110000 F24 -185 -0.973406 0.561996 0.140000 0.110000 F25 -186 -1.112464 0.642281 0.140000 0.110000 F26 -187 -1.201584 0.802873 0.140000 0.110000 F27 -188 -1.335093 0.892081 0.140000 0.110000 F28 -189 -1.468602 0.981289 0.140000 0.110000 F29 -190 -1.631824 0.675923 0.140000 0.110000 F30 -191 -1.483476 0.614476 0.140000 0.110000 F31 -192 -1.335128 0.553028 0.140000 0.110000 F32 -193 -0.152711 -0.049619 0.140000 0.110000 G1 -194 -0.305423 -0.099238 0.140000 0.110000 G2 -195 -0.458134 -0.148857 0.140000 0.110000 G3 -196 -0.642281 -0.000000 0.140000 0.110000 G4 -197 -0.775495 0.207793 0.140000 0.110000 G5 -198 -0.930594 0.249352 0.140000 0.110000 G6 -199 -1.068980 0.347333 0.140000 0.110000 G7 -200 -1.221691 0.396952 0.140000 0.110000 G8 -201 -1.417365 0.281931 0.140000 0.110000 G9 -202 -1.574850 0.313257 0.140000 0.110000 G10 -203 -1.605703 -0.000000 0.140000 0.110000 G11 -204 -1.445133 -0.000000 0.140000 0.110000 G12 -205 -1.277525 0.134273 0.140000 0.110000 G13 -206 -1.117835 0.117489 0.140000 0.110000 G14 -207 -0.963422 -0.000000 0.140000 0.110000 G15 -208 -0.802851 -0.000000 0.140000 0.110000 G16 -209 -0.930594 -0.249352 0.140000 0.110000 G17 -210 -1.117835 -0.117489 0.140000 0.110000 G18 -211 -1.277525 -0.134273 0.140000 0.110000 G19 -212 -1.417365 -0.281931 0.140000 0.110000 G20 -213 -1.574850 -0.313257 0.140000 0.110000 G21 -214 -1.631824 -0.675923 0.140000 0.110000 G22 -215 -1.483476 -0.614476 0.140000 0.110000 G23 -216 -1.335128 -0.553028 0.140000 0.110000 G24 -217 -1.221691 -0.396952 0.140000 0.110000 G25 -218 -1.068980 -0.347333 0.140000 0.110000 G26 -219 -0.973406 -0.561996 0.140000 0.110000 G27 -220 -1.112464 -0.642281 0.140000 0.110000 G28 -221 -1.201584 -0.802873 0.140000 0.110000 G29 -222 -1.335093 -0.892081 0.140000 0.110000 G30 -223 -1.468602 -0.981289 0.140000 0.110000 G31 -224 -1.668695 -0.963422 0.140000 0.110000 G32 -225 -0.188762 -0.259808 0.140000 0.110000 H1 -226 -0.357981 -0.322327 0.140000 0.110000 H2 -227 -0.519616 -0.377523 0.140000 0.110000 H3 -228 -0.610846 -0.198476 0.140000 0.110000 H4 -229 -0.775495 -0.207793 0.140000 0.110000 H5 -230 -0.695290 -0.401426 0.140000 0.110000 H6 -231 -0.834348 -0.481711 0.140000 0.110000 H7 -232 -0.835289 -0.752097 0.140000 0.110000 H8 -233 -0.954616 -0.859540 0.140000 0.110000 H9 -234 -1.021863 -1.021863 0.140000 0.110000 H10 -235 -1.135403 -1.135403 0.140000 0.110000 H11 -236 -1.248944 -1.248944 0.140000 0.110000 H12 -237 -1.431924 -1.289310 0.140000 0.110000 H13 -238 -1.132570 -1.558849 0.140000 0.110000 H14 -239 -0.981289 -1.468602 0.140000 0.110000 H15 -240 -0.892081 -1.335093 0.140000 0.110000 H16 -241 -0.802873 -1.201584 0.140000 0.110000 H17 -242 -0.755047 -1.039233 0.140000 0.110000 H18 -243 -0.660666 -0.909329 0.140000 0.110000 H19 -244 -0.681242 -0.681242 0.140000 0.110000 H20 -245 -0.567702 -0.567702 0.140000 0.110000 H21 -246 -0.377523 -0.519616 0.140000 0.110000 H22 -247 -0.195929 -0.440065 0.140000 0.110000 H23 -248 -0.401426 -0.695290 0.140000 0.110000 H24 -249 -0.481711 -0.834348 0.140000 0.110000 H25 -250 -0.457169 -1.026818 0.140000 0.110000 H26 -251 -0.522479 -1.173506 0.140000 0.110000 H27 -252 -0.553028 -1.335128 0.140000 0.110000 H28 -253 -0.614476 -1.483476 0.140000 0.110000 H29 -254 -0.675923 -1.631824 0.140000 0.110000 H30 -255 -0.783718 -1.760259 0.140000 0.110000 H31 -256 -0.849028 -1.906947 0.140000 0.110000 H32 -257 0.000000 0.000000 0.140000 0.110000 Cz -258 0.000000 -0.802851 0.140000 0.110000 Pz -259 0.000000 -1.605703 0.140000 0.110000 Oz -260 1.605703 0.000000 0.140000 0.110000 T8 -261 0.802851 0.000000 0.140000 0.110000 C4 -262 0.000000 1.605703 0.140000 0.110000 Fpz -263 0.000000 0.802851 0.140000 0.110000 Fz -264 -1.605703 -0.000000 0.140000 0.110000 T7 -265 -0.802851 -0.000000 0.140000 0.110000 C3 diff --git a/external/fieldtrip/private/biosemi32.lay b/external/fieldtrip/private/biosemi32.lay deleted file mode 100644 index aa2b74c..0000000 --- a/external/fieldtrip/private/biosemi32.lay +++ /dev/null @@ -1,32 +0,0 @@ -1 -0.496189 1.527114 0.320000 0.250000 Fp1 -2 -0.545830 1.170536 0.320000 0.250000 AF3 -3 -1.299041 0.943808 0.320000 0.250000 F7 -4 -0.659023 0.813825 0.320000 0.250000 F3 -5 -0.394923 0.394923 0.320000 0.250000 FC1 -6 -1.173172 0.450338 0.320000 0.250000 FC5 -7 -1.605703 -0.000000 0.320000 0.250000 T7 -8 -0.802851 -0.000000 0.320000 0.250000 C3 -9 -0.394923 -0.394923 0.320000 0.250000 CP1 -10 -1.173172 -0.450338 0.320000 0.250000 CP5 -11 -1.299041 -0.943808 0.320000 0.250000 P7 -12 -0.659023 -0.813825 0.320000 0.250000 P3 -13 0.000000 -0.802851 0.320000 0.250000 Pz -14 -0.545830 -1.170536 0.320000 0.250000 PO3 -15 -0.496189 -1.527114 0.320000 0.250000 O1 -16 0.000000 -1.605703 0.320000 0.250000 Oz -17 0.496189 -1.527114 0.320000 0.250000 O2 -18 0.545830 -1.170536 0.320000 0.250000 PO4 -19 0.659023 -0.813825 0.320000 0.250000 P4 -20 1.299041 -0.943808 0.320000 0.250000 P8 -21 1.173172 -0.450338 0.320000 0.250000 CP6 -22 0.394923 -0.394923 0.320000 0.250000 CP2 -23 0.802851 0.000000 0.320000 0.250000 C4 -24 1.605703 0.000000 0.320000 0.250000 T8 -25 1.173172 0.450338 0.320000 0.250000 FC6 -26 0.394923 0.394923 0.320000 0.250000 FC2 -27 0.659023 0.813825 0.320000 0.250000 F4 -28 1.299041 0.943808 0.320000 0.250000 F8 -29 0.545830 1.170536 0.320000 0.250000 AF4 -30 0.496189 1.527114 0.320000 0.250000 Fp2 -31 0.000000 0.802851 0.320000 0.250000 Fz -32 0.000000 0.000000 0.320000 0.250000 Cz diff --git a/external/fieldtrip/private/biosemi64.lay b/external/fieldtrip/private/biosemi64.lay deleted file mode 100644 index db5019b..0000000 --- a/external/fieldtrip/private/biosemi64.lay +++ /dev/null @@ -1,64 +0,0 @@ -1 -0.496189 1.527114 0.290000 0.230000 Fp1 -2 -0.943808 1.299041 0.290000 0.230000 AF7 -3 -0.545830 1.170536 0.290000 0.230000 AF3 -4 -0.326906 0.809121 0.290000 0.230000 F1 -5 -0.659023 0.813825 0.290000 0.230000 F3 -6 -0.987913 0.858779 0.290000 0.230000 F5 -7 -1.299041 0.943808 0.290000 0.230000 F7 -8 -1.527114 0.496189 0.290000 0.230000 FT7 -9 -1.173172 0.450338 0.290000 0.230000 FC5 -10 -0.770517 0.409691 0.290000 0.230000 FC3 -11 -0.394923 0.394923 0.290000 0.230000 FC1 -12 -0.401426 -0.000000 0.290000 0.230000 C1 -13 -0.802851 -0.000000 0.290000 0.230000 C3 -14 -1.204277 -0.000000 0.290000 0.230000 C5 -15 -1.605703 -0.000000 0.290000 0.230000 T7 -16 -1.527114 -0.496189 0.290000 0.230000 TP7 -17 -1.173172 -0.450338 0.290000 0.230000 CP5 -18 -0.770517 -0.409691 0.290000 0.230000 CP3 -19 -0.394923 -0.394923 0.290000 0.230000 CP1 -20 -0.326906 -0.809121 0.290000 0.230000 P1 -21 -0.659023 -0.813825 0.290000 0.230000 P3 -22 -0.987913 -0.858779 0.290000 0.230000 P5 -23 -1.299041 -0.943808 0.290000 0.230000 P7 -24 -1.537550 -1.290157 0.290000 0.230000 P9 -25 -0.943808 -1.299041 0.290000 0.230000 PO7 -26 -0.545830 -1.170536 0.290000 0.230000 PO3 -27 -0.496189 -1.527114 0.290000 0.230000 O1 -28 0.000000 -2.007129 0.290000 0.230000 Iz -29 0.000000 -1.605703 0.290000 0.230000 Oz -30 0.000000 -1.204277 0.290000 0.230000 POz -31 0.000000 -0.802851 0.290000 0.230000 Pz -32 0.000000 -0.401426 0.290000 0.230000 CPz -33 0.000000 1.605703 0.290000 0.230000 Fpz -34 0.496189 1.527114 0.290000 0.230000 Fp2 -35 0.943808 1.299041 0.290000 0.230000 AF8 -36 0.545830 1.170536 0.290000 0.230000 AF4 -37 0.000000 1.204277 0.290000 0.230000 Afz -38 0.000000 0.802851 0.290000 0.230000 Fz -39 0.326906 0.809121 0.290000 0.230000 F2 -40 0.659023 0.813825 0.290000 0.230000 F4 -41 0.987913 0.858779 0.290000 0.230000 F6 -42 1.299041 0.943808 0.290000 0.230000 F8 -43 1.527114 0.496189 0.290000 0.230000 FT8 -44 1.173172 0.450338 0.290000 0.230000 FC6 -45 0.770517 0.409691 0.290000 0.230000 FC4 -46 0.394923 0.394923 0.290000 0.230000 FC2 -47 0.000000 0.401426 0.290000 0.230000 FCz -48 0.000000 0.000000 0.290000 0.230000 Cz -49 0.401426 0.000000 0.290000 0.230000 C2 -50 0.802851 0.000000 0.290000 0.230000 C4 -51 1.204277 0.000000 0.290000 0.230000 C6 -52 1.605703 0.000000 0.290000 0.230000 T8 -53 1.527114 -0.496189 0.290000 0.230000 TP8 -54 1.173172 -0.450338 0.290000 0.230000 CP6 -55 0.770517 -0.409691 0.290000 0.230000 CP4 -56 0.394923 -0.394923 0.290000 0.230000 CP2 -57 0.326906 -0.809121 0.290000 0.230000 P2 -58 0.659023 -0.813825 0.290000 0.230000 P4 -59 0.987913 -0.858779 0.290000 0.230000 P6 -60 1.299041 -0.943808 0.290000 0.230000 P8 -61 1.537550 -1.290157 0.290000 0.230000 P10 -62 0.943808 -1.299041 0.290000 0.230000 PO8 -63 0.545830 -1.170536 0.290000 0.230000 PO4 -64 0.496189 -1.527114 0.290000 0.230000 O2 diff --git a/external/fieldtrip/private/blc.m b/external/fieldtrip/private/blc.m index 9ecc12b..387573f 100644 --- a/external/fieldtrip/private/blc.m +++ b/external/fieldtrip/private/blc.m @@ -10,13 +10,23 @@ % Copyright (C) 1998-2002, Robert Oostenveld % -% $Log: blc.m,v $ -% Revision 1.3 2003/03/14 10:17:28 roberto -% fixed bug that was introduced by last change, changend from repmat to for-loop +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.2 2003/03/13 16:44:45 roberto -% fixed bug with multiple epochs and single channel data +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: blc.m 952 2010-04-21 18:29:51Z roboos $ % determine the dimension of the data if length(size(data))==3 diff --git a/external/fieldtrip/private/bounding_mesh.m b/external/fieldtrip/private/bounding_mesh.m index 781b29c..c2fddd8 100644 --- a/external/fieldtrip/private/bounding_mesh.m +++ b/external/fieldtrip/private/bounding_mesh.m @@ -6,46 +6,31 @@ % [inside] = bounding_mesh(pos, pnt, tri) % % where -% pos position of point of interest (can be 1x3 or Nx3) -% pnt bounding mesh vertices -% tri bounding mesh triangles +% pos position of point of interest (can be 1x3 or Nx3) +% pnt bounding mesh vertices +% tri bounding mesh triangles % % See also SOLID_ANGLE % Copyright (C) 2003, Robert Oostenveld % -% $Log: bounding_mesh.m,v $ -% Revision 1.11 2006/03/06 09:44:34 roboos -% changed a | into a || +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.10 2003/07/24 09:18:17 roberto -% added abs to solid angle to make it invariant for triange orientation +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.9 2003/03/21 13:40:29 roberto -% fixed small bug (unmatched end) +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.8 2003/03/21 13:38:46 roberto -% solid angle computation is now available in very fast mex file -% removed projection along x/y/z axes -% -% Revision 1.7 2003/03/21 12:32:35 roberto -% added projection along y and x, similar to z -% -% Revision 1.6 2003/03/21 12:15:23 roberto -% added new approach to determine inside/outside (proj along z) -% -% Revision 1.5 2003/03/21 08:26:46 roberto -% changed to percent (100x) -% -% Revision 1.4 2003/03/21 08:26:08 roberto -% fixed typo -% -% Revision 1.3 2003/03/21 08:25:34 roberto -% small modification to feedback/debugging info -% -% Revision 1.2 2003/03/04 21:35:26 roberto -% added CVS Log keyword +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: bounding_mesh.m 946 2010-04-21 17:51:16Z roboos $ global fb; if isempty(fb) diff --git a/external/fieldtrip/private/browse_movieplotER.m b/external/fieldtrip/private/browse_movieplotER.m new file mode 100644 index 0000000..7f314fc --- /dev/null +++ b/external/fieldtrip/private/browse_movieplotER.m @@ -0,0 +1,17 @@ +function browse_movieplotER(cfg, data) + +% this is a helper function for DATABROWSER which makes a movie of the data +% that was selected. See MOVIEPLOTER +% + +% Copyright (C) 2009, Ingrid Nieuwenhuis + +% Convert to an ERP +timelock = timelockanalysis([], data); + +if isfield(cfg, 'framesfile') + cfg.framesfile = [cfg.framesfile, '_S', num2str(data.cfg.trl(1)), 'toS', num2str(data.cfg.trl(2))]; +end + +figure; +movieplotER(cfg, timelock); \ No newline at end of file diff --git a/external/fieldtrip/private/browse_multiplotER.m b/external/fieldtrip/private/browse_multiplotER.m new file mode 100644 index 0000000..3af61d9 --- /dev/null +++ b/external/fieldtrip/private/browse_multiplotER.m @@ -0,0 +1,20 @@ +function browse_multiplotER(cfg, data) + +% this is a simple helper function for DATABROWSER + +% Copyright (C) 2009, Robert Oostenveld +% +% $Log: browse_multiplotER.m,v $ +% Revision 1.1 2009/10/19 14:19:21 roboos +% first version, to work with databrowser +% + +% convert to an ERP +timelock = timelockanalysis([], data); + +default = []; +default.interactive = 'yes'; +cfg = mergeconfig(cfg, default); + +figure; +multiplotER(cfg, timelock); diff --git a/external/fieldtrip/private/browse_topoplotER.m b/external/fieldtrip/private/browse_topoplotER.m new file mode 100644 index 0000000..367ce54 --- /dev/null +++ b/external/fieldtrip/private/browse_topoplotER.m @@ -0,0 +1,22 @@ +function browse_topoplotER(cfg, data) + +% this is a simple helper function for DATABROWSER + +% Copyright (C) 2009, Robert Oostenveld +% +% $Log: browse_topoplotER.m,v $ +% Revision 1.1 2009/10/19 14:19:21 roboos +% first version, to work with databrowser +% + +% convert to an ERP +timelock = timelockanalysis([], data); + +default = []; +default.xlim = [min(timelock.time) max(timelock.time)]; +default.marker = 'on'; +default.interactive = 'no'; +cfg = mergeconfig(cfg, default); + +figure; +topoplotER(cfg, timelock); diff --git a/external/fieldtrip/private/browse_topoplotVAR.m b/external/fieldtrip/private/browse_topoplotVAR.m new file mode 100644 index 0000000..2de10e6 --- /dev/null +++ b/external/fieldtrip/private/browse_topoplotVAR.m @@ -0,0 +1,25 @@ +function browse_topoplotVAR(cfg, data) + +% this is a simple helper function for DATABROWSER + +% Copyright (C) 2009, Robert Oostenveld +% +% $Log: browse_topoplotVAR.m,v $ +% Revision 1.1 2009/10/19 14:19:21 roboos +% first version, to work with databrowser +% + +% compute the variance, i.e. the broad-band power +timelock = []; +timelock.label = data.label; +timelock.time = mean(data.time{1}); +timelock.avg = sum(preproc_baselinecorrect(data.trial{1}).^2, 2); +timelock.dimord = 'chan_time'; + +default = []; +default.markers = 'labels'; +default.interactive = 'no'; +cfg = mergeconfig(cfg, default); + +figure; +topoplotER(cfg, timelock); diff --git a/external/fieldtrip/private/bti2grad.m b/external/fieldtrip/private/bti2grad.m index 3569a4a..e856bc8 100644 --- a/external/fieldtrip/private/bti2grad.m +++ b/external/fieldtrip/private/bti2grad.m @@ -17,51 +17,23 @@ % Copyright (C) 2008, Jan-Mathijs Schoffelen % -% $Log: bti2grad.m,v $ -% Revision 1.5 2009/10/07 09:45:50 jansch -% restructured the handling of balancing; balancing for data in which the -% weight table is of type 1 is still disabled, and balancing is applied for -% data with weight tables of type ~= 1 +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.4 2009/04/02 10:13:15 jansch -% disabled balancing for 148-sensor system (weight table version 1) since -% channel order is not known +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.3 2009/03/26 10:20:33 jansch -% added balancing based on the weight table used during acquisition. note that -% post acquisition computed weights using 4d software are not incorporated in -% the balancing of the gradiometers +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.2 2009/01/23 16:15:31 roboos -% removed ; after function declaration -% -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.8 2008/10/20 15:16:16 jansch -% removed the explicit sorting of the channels, this could cause problems -% later on. however, the sensors and references are block-wise sorted still -% -% Revision 1.7 2008/05/15 13:20:36 roboos -% updated documentation -% -% Revision 1.6 2008/05/14 10:20:37 jansch -% included tra-computation when inputting 'm4d' and 'xyz' headers -% -% Revision 1.5 2008/05/14 09:17:04 jansch -% included check for orientation in the case of gradiometers -% -% Revision 1.4 2008/05/14 08:02:40 jansch -% transposed grad.tra (was initially incorrect) -% -% Revision 1.3 2008/05/08 11:10:20 jansch -% implementation in analogy with ctf2grad +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: bti2grad.m 1058 2010-05-09 11:21:10Z roboos $ % for backward compatibility issues FIXME check whether anyone actually uses this code if isfield(hdr, 'Meg_pos'), @@ -226,9 +198,9 @@ if balanceflag, fprintf('applying digital weights in the gradiometer balancing matrix\n'); - grad.balance = balance; + grad.balance = balance; grad.balance.current = weights.position; - grad = apply_montage(grad, getfield(grad.balance, grad.balance.current)); + grad = ft_apply_montage(grad, getfield(grad.balance, grad.balance.current)); else fprintf('not applying digital weights in the gradiometer balancing matrix\n'); end diff --git a/external/fieldtrip/private/cancorr.m b/external/fieldtrip/private/cancorr.m new file mode 100644 index 0000000..870f3b7 --- /dev/null +++ b/external/fieldtrip/private/cancorr.m @@ -0,0 +1,126 @@ +function [px, py, wx, wy, powx, powy] = cancorr(C,x,y,powflag,realflag,trunc) + +% CANCORR computes the canonical correlation between multiple variables +% +% Canonical correlation analysis (CCA) is a way of measuring the linear +% relationship between two multidimensional variables. It finds two bases, +% one for each variable, that are optimal with respect to correlations and, +% at the same time, it finds the corresponding correlations. +% +% Use as +% [px, py, wx, wy] = cancorr(C,x,y) + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: cancorr.m 952 2010-04-21 18:29:51Z roboos $ + +if nargin<3, + error('to compute canonical coherence, you need to specify the indices to the cross-spectral density making up the dependent and independent variable'); +elseif nargin==3, + powflag = 0; + realflag = 0; + trunc = 0; +elseif nargin==4, + realflag = 0; + trunc = 0; +elseif nargin==5, + trunc = 0; +end + +siz = size(C,1); +ind = find(sum(isfinite(C))>0); + +xorig = x; +yorig = y; +x = intersect(ind, x); +y = intersect(ind, y); + +%use the approach as specified by Borga et al 1992: a unified approach to PCA, PLS, MLR and CCA +%that is: solve the generalized eigenvalue problem eig(inv(B)*A) with +%A = [O Cxy; Cyx O], and B = [Cxx O; O Cyy]; +indx = zeros(length(ind), 1); +indy = zeros(length(ind), 1); +indx(1:length(x)) = 1; +indy(length(x)+1:end) = 1; + +Aorig = [indx*indy' + indy*indx'].*C([x y],[x y]); +Borig = [indx*indx' + indy*indy'].*C([x y],[x y]); + +if realflag, + A = real(Aorig); + B = real(Borig); +else + A = Aorig; + B = Borig; +end +%if A and B are rank deficient this could lead to non-finite eigenvalues +%[w, p] = eig(A,B); +[ua,sa,va] = svds(C(x,x), rank(C(x,x))); +[ub,sb,vb] = svds(C(y,y), rank(C(y,y))); +U = [ua' zeros(size(ua,2),size(ub,1)); zeros(size(ub,2),size(ua,1)) ub']; +[w, p] = eig(U*A*U', U*B*U'); + +[srt, ind] = sort(diag(abs(p)), 'descend'); +w = w(:, ind); +p = p(ind, ind); + +%eigenvalues come in pairs, with 180-degree ambiguity +nump = ceil(size(p,1)/2); +%wx = zeros(length(xorig)); wx(find(ismember(xorig,x)), 1:nump) = w(1:length(x), 1:2:end); +%wy = zeros(length(yorig)); wy(find(ismember(yorig,y)), 1:nump) = w(length(x)+1:end, 1:2:end); +wx = zeros(length(xorig)); +wy = zeros(length(yorig)); +px = abs(p(1:2:end, 1:2:end)); +py = abs(p(1:2:end, 1:2:end)); + +if powflag, + powx = wx'*B(x,x)*wx; + powy = wy'*B(y,y)*wy; +end + +if 0, +Cxx = C(x,x); +Cyy = C(y,y); +Cxy = C(x,y); +Cyx = C(y,x); + +[wx, px] = eig(inv(Cxx)*Cxy*inv(Cyy)*Cyx); +[wy, py] = eig(inv(Cyy)*Cyx*inv(Cxx)*Cxy); + +[srtx,indx] = sort(diag(px), 'descend'); +[srty,indy] = sort(diag(py), 'descend'); + +px = px(indx,indx); +wx = wx(:, indx); +py = py(indy,indy); +wy = wy(:, indy); + +if powflag, + powx = wx'*Cxx*wx; + powy = wy'*Cyy*wy; +end +end + +if trunc>0 && trunc<1, + px = px.*double(px>trunc); + py = py.*double(py>trunc); +elseif trunc>=1, + px(trunc+1:end,trunc+1:end) = 0; + py(trunc+1:end,trunc+1:end) = 0; +end diff --git a/external/fieldtrip/private/ccabss.m b/external/fieldtrip/private/ccabss.m new file mode 100644 index 0000000..37ce1c8 --- /dev/null +++ b/external/fieldtrip/private/ccabss.m @@ -0,0 +1,82 @@ +function [y,w] = ccabss(x) +% CCABSS - Blind Source Separation by Canonical Correlation Analysis +% +% Y = CCABSS(X) is the BSS of X=A*S where S is a set of unknown source signals +% and A is an unknown mixing matrix. The components in S are supposed to +% be independent. Y is an estimate of S appart from permutation and scaling. +% For mixed 1-D signals, X is 2-D. The first index refer to the different +% components and the second index refers to the signal parameter (e.g. time) +% For mixed images, X is 3-D where the first index refers to the different +% mixed images and the second and third indeces are the spatial coordinates. +% +% [Y W] = CCABSS(X) also gives the 'de-mixing' matrix W, such that Y = W'*X. +% +% © 2000 Magnus Borga + + +switch ndims(x) + case 2 % 1D signals + spatial_mode = 0; + A = x(:,2:end-1); + B = conv2(x,[1 0 1],'valid'); % Temporal correlation + [wa wb r] = cc(A,B); % CCA + y = wa'*x; + case 3 % 2D signals + spatial_mode = 1; + x_size = size(x); + im_size = x_size(2)*x_size(3); + ab_size = (x_size(2)-2)*(x_size(3)-2); + for k = 1:x_size(1) % Flatten 2D-signals after convolution + X(k,:) = reshape(x(k,:,:),1,im_size); + A(k,:) = reshape(x(k,2:end-1,2:end-1),1,ab_size); + B(k,:) = reshape(conv2(squeeze(x(k,:,:)),[0 1 0;1 0 1;0 1 0],'valid'),1,ab_size); + end + [wa wb r] = cc(A,B); % CCA + for k = 1:x_size(1) % Flatten 2D-signals after convolution + y(k,:,:) = reshape(wa(:,k)'*X,x_size(2),x_size(3)); + end + otherwise, error('x must be 2- or 3-dimensional.') +end + +if nargout > 1 + w = wa; +end + +% ------------ +% --- CCA ---- +% ------------ + +function [Wx, Wy, r] = cc(X,Y) + +% --- Calculate covariance matrices --- + +z = [X;Y]; +C = cov(z.'); +sx = size(X,1); +sy = size(Y,1); +Cxx = C(1:sx, 1:sx) + 10^(-8)*eye(sx); +Cxy = C(1:sx, sx+1:sx+sy); +Cyx = Cxy'; +Cyy = C(sx+1:sx+sy, sx+1:sx+sy) + 10^(-8)*eye(sy); +invCyy = inv(Cyy); + +% --- Calcualte Wx and r --- + +[Wx,r] = eig(inv(Cxx)*Cxy*invCyy*Cyx); % Basis in X +r = sqrt(real(r)); % Canonical correlations + +% --- Sort correlations --- + +V = fliplr(Wx); % reverse order of eigenvectors +r = flipud(diag(r)); % extract eigenvalues anr reverse their orrer +[r,I]= sort((real(r))); % sort reversed eigenvalues in ascending order +r = flipud(r); % restore sorted eigenvalues into descending order +for j = 1:length(I) + Wx(:,j) = V(:,I(j)); % sort reversed eigenvectors in ascending order +end +Wx = fliplr(Wx); % restore sorted eigenvectors into descending order + +% --- Calcualte Wy --- + +Wy = invCyy*Cyx*Wx; % Basis in Y +Wy = Wy./repmat(sqrt(sum(abs(Wy).^2)),sy,1); % Normalize Wy diff --git a/external/fieldtrip/private/cfg2keyval.m b/external/fieldtrip/private/cfg2keyval.m deleted file mode 100644 index b10b118..0000000 --- a/external/fieldtrip/private/cfg2keyval.m +++ /dev/null @@ -1,14 +0,0 @@ -function [optarg] = cfg2keyval(cfg); - -% CFG2KEYVAL converts between a structure and a cell-array with key-value -% pairs which can be used for optional input arguments. -% -% Use as -% [optarg] = cfg2keyval(cfg) - -if ~isempty(cfg) - optarg = [fieldnames(cfg) struct2cell(cfg)]'; - optarg = optarg(:)'; -else - optarg = {}; -end \ No newline at end of file diff --git a/external/fieldtrip/private/channelcombination.m b/external/fieldtrip/private/channelcombination.m deleted file mode 100644 index 56fe6f6..0000000 --- a/external/fieldtrip/private/channelcombination.m +++ /dev/null @@ -1,146 +0,0 @@ -function [collect] = channelcombination(channelcmb, datachannel) - -% CHANNELCOMBINATION creates a cell-array with combinations of EEG/MEG -% channels for subsequent cross-spectral-density and coherence analysis -% -% You should specify channel combinations as a two-column cell array, -% cfg.channelcmb = { 'EMG' 'MLF31' -% 'EMG' 'MLF32' -% 'EMG' 'MLF33' }; -% to compare EMG with these three sensors, or -% cfg.channelcmb = { 'MEG' 'MEG' }; -% to make all MEG combinations, or -% cfg.channelcmb = { 'EMG' 'MEG' }; -% to make all combinations between the EMG and all MEG channels. -% -% For each column, you can specify a mixture of real channel labels -% and of special strings that will be replaced by the corresponding -% channel labels. Channels that are not present in the raw datafile -% are automatically removed from the channel list. -% -% See also CHANNELSELECTION - -% Undocumented local options: -% none - -% Copyright (C) 2003-2006, Robert Oostenveld -% -% $Log: channelcombination.m,v $ -% Revision 1.15 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.14 2006/06/06 16:57:51 ingnie -% updated documentation -% -% Revision 1.13 2006/04/20 09:58:33 roboos -% updated documentation -% -% Revision 1.12 2006/03/06 11:52:52 roboos -% prevent memory allocation and copying in a for loop, this was the -% reason for it being tremendously slow for a large number of channel -% combinations -% -% Revision 1.11 2005/09/29 00:46:11 roboos -% renamed the variable sgncmb into channelcmb, both in the help and code -% -% Revision 1.10 2005/05/17 17:50:36 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.9 2005/03/18 09:25:50 roboos -% changed handling of multiple rows of the input selection, each row is now processed separately -% removed (defunct) planar channel detection -% -% Revision 1.8 2004/10/19 10:44:43 roboos -% fixed bug in planar-gradient channel detection if labels are shorter than 3 chars -% -% Revision 1.7 2004/08/26 07:16:11 jansch -% re-added to CVS-repository. -% -% Revision 1.5 2004/01/16 08:28:50 roberto -% fixed small bug for 'all' -% -% Revision 1.4 2004/01/06 12:43:47 roberto -% redesign by JM -% -% Revision 1.3 2003/10/29 09:02:31 roberto -% fixed bug in varible names, sgncmb vs channel -% -% Revision 1.2 2003/10/27 16:24:06 roberto -% added check for double channel combinations -% -% Revision 1.1 2003/10/27 16:02:13 roberto -% new implementation after an idea by JM -% - -fieldtripdefs - -if ischar(channelcmb) && strcmp(channelcmb, 'all') - % make all possible combinations of all channels - channelcmb = {'all' 'all'}; -end - -% it should have a selection of two channels or channelgroups in each row -if size(channelcmb,1)==2 && size(channelcmb,2)~=2 - warning('transposing channelcombination matrix'); -end - -% this will hold the output -collect = {}; - -if isempty(setdiff(channelcmb(:), datachannel)) - % there is nothing to do, since there are no channelgroups with special names - % each element of the input therefore already contains a proper channel name - collect = channelcmb; - -else - % a combination is made for each row of the input selection after - % translating the channel group (such as 'all') to the proper channel names - % and within each set, double occurences and autocombinations are removed - - for sel=1:size(channelcmb,1) - % translate both columns and subsequently make all combinations - channelcmb1 = channelselection(channelcmb(sel,1), datachannel); - channelcmb2 = channelselection(channelcmb(sel,2), datachannel); - - % compute indices of channelcmb1 and channelcmb2 relative to datachannel - [dum,indx,indx1]=intersect(channelcmb1,datachannel); - [dum,indx,indx2]=intersect(channelcmb2,datachannel); - - % remove double occurrences of channels in either set of signals - indx1 = unique(indx1); - indx2 = unique(indx2); - - % create a matrix in which all possible combinations are set to one - cmb = zeros(length(datachannel)); - for ch1=1:length(indx1) - for ch2=1:length(indx2) - cmb(indx1(ch1),indx2(ch2))=1; - end - end - - % remove auto-combinations - cmb = cmb & ~eye(size(cmb)); - % remove double occurences - cmb = cmb & ~tril(cmb)'; - - [indx1,indx2] = find(cmb); - - % extend the previously allocated cell-array to also hold the new - % channel combinations (this is done to prevent memory allocation and - % copying in each iteration in the for-loop below) - num = size(collect,1); % count the number of existing combinations - dum = cell(num + length(indx1), 2); % allocate space for the existing+new combinations - if num>0 - dum(1:num,:) = collect(:,:); % copy the exisisting combinations into the new array - end - collect = dum; - clear dum - - % convert to channel-names - for ch=1:length(indx1) - collect{num+ch,1}=datachannel{indx1(ch)}; - collect{num+ch,2}=datachannel{indx2(ch)}; - end - end -end diff --git a/external/fieldtrip/private/channelposition.m b/external/fieldtrip/private/channelposition.m index b7742af..5a950ea 100644 --- a/external/fieldtrip/private/channelposition.m +++ b/external/fieldtrip/private/channelposition.m @@ -1,67 +1,50 @@ -function [pnt, lab] = channelposition(sens, varargin) +function [pnt, ori, lab] = channelposition(sens, varargin) % CHANNELPOSITION % -% Use as -% [pos, label] = channelposition(sens, ...) +% Use either as +% [pos] = channelposition(sens, ...) +% [pos, lab] = channelposition(sens, ...) +% [pos, ori, lab] = channelposition(sens, ...) % Copyright (C) 2009, Robert Oostenveld & Vladimir Litvak % -% $Log: channelposition.m,v $ -% Revision 1.9 2009/08/10 12:33:57 vlalit -% Adding thresholds to ignore small values in the tra also for Neuromag and planar +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.8 2009/07/08 07:42:50 jansch -% undone previous adjustment. convention now is that sequential balancing steps -% should be recorded in the grad-structure itself; rather than having -% balance.XXX and balance.YYY, it should be balance.XXX_YYY and -% balance.current = 'XXX_YYY' +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.7 2009/07/07 08:03:29 jansch -% allowing for sequential unbalancing, convention being that the individual -% balancing steps in balance.current are separated by '_', and the chronological -% ordering of the balancing steps are from right to left +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.6 2009/06/26 17:39:04 vlalit -% Added the possiblity to handle custom montages applied to MEG sensors (for removing -% spatial confounds). Hopefully there won't be major side effects. -% -% Revision 1.5 2009/06/03 09:49:03 roboos -% change in whitespace -% -% Revision 1.4 2009/04/03 08:14:27 vlalit -% getting rid of the dependence on statistics toolbox I accidentally introduced by using -% nanmin. -% -% Revision 1.3 2009/03/30 17:55:17 vlalit -% Changed prepare_layout and headmodelplot to use channelposition. Changed the color -% of sensor markers in headmodelplot to green for consistency with SPM plots. -% -% Revision 1.2 2009/03/26 16:27:17 roboos -% incorporated the sugegstions by Vladimir -% -% Revision 1.1 2009/03/25 09:04:36 roboos -% new function, will be used as helper function in prepare_layout +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: channelposition.m 1261 2010-06-22 15:09:23Z roboos $ -if isfield(sens, 'balance') && ~strcmp(sens.balance.current, 'none') +if isfield(sens, 'balance') && isfield(sens.balance, 'current') && ~strcmp(sens.balance.current, 'none') fnames = setdiff(fieldnames(sens.balance), 'current'); indx = find(ismember(fnames, sens.balance.current)); - + if length(indx)==1, % undo the synthetic gradient balancing fprintf('undoing the %s balancing\n', sens.balance.current); - sens = apply_montage(sens, getfield(sens.balance, sens.balance.current), 'inverse', 'yes'); + sens = ft_apply_montage(sens, getfield(sens.balance, sens.balance.current), 'inverse', 'yes'); sens.balance.current = 'none'; else warning('cannot undo %s balancing\n', sens.balance.current); end end -switch senstype(sens) - case {'ctf151', 'ctf275' 'bti148', 'bti248'} +switch ft_senstype(sens) + case {'ctf151', 'ctf275' 'bti148', 'bti248', 'itab153', 'yokogawa160'} % remove the non-MEG channels altogether - sel = chantype(sens, 'meg'); + sel = ft_chantype(sens, 'meg'); sens.label = sens.label(sel); sens.tra = sens.tra(sel,:); @@ -80,13 +63,14 @@ % put nans instead of the zero entries dist(~dist) = inf; - % use the matrix to find coils with minimal distance + % use the matrix to find coils with minimal distance to the center, i.e. the bottom coil [junk, ind] = min(dist, [], 2); lab = sens.label; pnt = sens.pnt(ind, :); + ori = sens.ori(ind, :); - case {'ctf151_planar', 'ctf275_planar', 'bti148_planar', 'bti248_planar'} + case {'ctf151_planar', 'ctf275_planar', 'bti148_planar', 'bti248_planar', 'itab153_planar', 'yokogawa160_planar'} % create a list with planar channel names chan = {}; for i=1:length(sens.label) @@ -179,10 +163,12 @@ % compute a weighted position for the channel [nchan, ncoil] = size(sens.tra); pnt = zeros(nchan,3); + ori = zeros(nchan,3); % FIXME not sure whether this will work for i=1:nchan weight = abs(sens.tra(i,:)); weight = weight ./ norm(weight); pnt(i,:) = weight * sens.pnt; + ori(i,:) = weight * sens.ori; end lab = sens.label; @@ -201,4 +187,20 @@ pnt = repmat(pnt, n, 1); end +% ensure that it is a row vector lab = lab(:); + +% the function can be called with a different number of output arguments +if nargout==1 + pnt = pnt; + ori = []; + lab = []; +elseif nargout==2 + pnt = pnt; + ori = lab; % second output argument + lab = []; % third output argument +elseif nargout==3 + pnt = pnt; + ori = ori; % second output argument + lab = lab; % third output argument +end diff --git a/external/fieldtrip/private/channelrepair.m b/external/fieldtrip/private/channelrepair.m deleted file mode 100644 index 8f42520..0000000 --- a/external/fieldtrip/private/channelrepair.m +++ /dev/null @@ -1,209 +0,0 @@ -function [interp] = channelrepair(cfg, data); - -% CHANNELREPAIR repairs bad channels in MEG or EEG data by replacing them -% with the average of its neighbours. It cannot be used reliably to -% repair multiple bad channels that ly next to each other. -% -% Use as -% [interp] = channelrepair(cfg, data) -% -% The configuration can contain -% cfg.badchannel = cell-array, see CHANNELSELECTION for details -% cfg.neighbourdist = default is 4 cm -% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') -% -% Since a nearest neighbour average is used, the input should contain -% a gradiometer or electrode definition, i.e. data.grad or data.elec. -% -% See also MEGINTERPOLATE - -% Copyright (C) 2004-2009, Robert Oostenveld -% -% $Log: channelrepair.m,v $ -% Revision 1.1 2009/02/04 09:33:48 roboos -% renamed megrepair to channelrepair, to make clear that it is not a MEG specific function -% -% Revision 1.20 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.19 2008/11/21 12:48:17 sashae -% added call to checkconfig at start and end of function -% -% Revision 1.18 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.17 2008/05/06 16:30:26 sashae -% change in trial selection, cfg.trials can be logical -% -% Revision 1.16 2008/04/22 13:28:01 roboos -% ensure that for loop over goodsensindcs is correct (fixes bug reported by Jurrian) -% -% Revision 1.15 2008/04/08 12:00:51 roboos -% also work on eeg data (using data.elec) -% only use the channels in the interpolation that are "good" (thanks to Markus Bauer) -% -% Revision 1.13 2007/05/02 15:59:13 roboos -% be more strict on the input and output data: It is now the task of -% the private/checkdata function to convert the input data to raw -% data (i.e. as if it were coming straight from preprocessing). -% Furthermore, the output data is NOT converted back any more to the -% input data, i.e. the output data is the same as what it would be -% on raw data as input, regardless of the actual input. -% -% Revision 1.12 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.11 2007/03/30 17:05:40 ingnie -% checkinput; only proceed when input data is allowed datatype -% -% Revision 1.10 2007/03/27 11:05:19 ingnie -% changed call to fixdimord in call to checkinput -% -% Revision 1.9 2006/02/23 10:28:16 roboos -% changed dimord strings for consistency, changed toi and foi into time and freq, added fixdimord where neccessary -% -% Revision 1.8 2005/06/29 12:46:29 roboos -% the following changes were done on a large number of files at the same time, not all of them may apply to this specific file -% - added try-catch around the inclusion of input data configuration -% - moved cfg.version, cfg.previous and the assignment of the output cfg to the end -% - changed help comments around the configuration handling -% - some changes in whitespace -% -% Revision 1.7 2005/06/02 12:18:41 roboos -% changed handling of input data: All input data that contains averages is converted to raw trials (like the output from preprocessing) prior to further processing. The output data is converted back into a format similar to the original input data using RAW2MEG. -% -% Revision 1.6 2004/08/23 06:34:58 roboos -% fixed bug in output labels -% -% Revision 1.5 2004/05/05 13:55:20 roberto -% fixed bug that occured when average data was made with keeptrials=yes -% -% Revision 1.4 2004/04/13 16:31:09 roberto -% fixed bug in dbstack selection of function filename for Matlab 6.1 -% -% Revision 1.3 2004/04/13 14:25:24 roberto -% wrapped code-snippet around mfilename to make it compatible with Matlab 6.1 -% -% Revision 1.2 2004/04/06 20:12:07 roberto -% Note: The previous revision was not just copy-and-paste from meginterpolate, -% but was actually a complete rewrite of the function. This current revision -% has only changes in help and comments. -% -% Revision 1.1 2004/04/06 20:01:49 roberto -% created new implementation by moving all functionality from meginterpolate to this function -% - -fieldtripdefs - -cfg = checkconfig(cfg, 'trackconfig', 'on'); - -% check if the input data is valid for this function -data = checkdata(data, 'datatype', 'raw', 'feedback', 'yes'); - -% set the default configuration -if ~isfield(cfg, 'neighbourdist'), cfg.neighbourdist = 4; end -if ~isfield(cfg, 'badchannel'), cfg.badchannel = {}; end -if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end - -% select trials of interest -if ~strcmp(cfg.trials, 'all') - if islogical(cfg.trials), cfg.trials=find(cfg.trials); end - fprintf('selecting %d trials\n', length(cfg.trials)); - data.trial = data.trial(cfg.trials); - data.time = data.time(cfg.trials); - % update the trial definition (trl) - if isfield(data, 'cfg') % try to locate the trl in the nested configuration - trl = findcfg(data.cfg, 'trl'); - else - trl = []; - end - if isempty(trl) - % a trial definition is expected in each continuous data set - warning('could not locate the trial definition ''trl'' in the data structure'); - else - cfg.trlold=trl; - cfg.trl=trl(cfg.trials,:); - end -end - -% determine the type of data -iseeg = senstype(data, 'eeg'); -ismeg = senstype(data, 'meg'); - -if iseeg - sens = data.elec; -elseif ismeg - sens = data.grad; -else - error('the data should contain either an electrode or a gradiometer definition'); -end - -% get the selection of channels that are bad -cfg.badchannel = channelselection(cfg.badchannel, data.label); -[goodchanlabels,goodchanindcs] = setdiff(data.label,cfg.badchannel); -[goodsenslabels,goodsensindcs] = intersect(sens.label,goodchanlabels); - -Ntrials = length(data.trial); -Nchans = length(data.label); -Nsens = length(sens.label); - -repair = eye(Nchans,Nchans); -[badindx] = match_str(data.label, cfg.badchannel); - -for k=badindx(:)' - fprintf('repairing channel %s\n', data.label{k}); - repair(k,k) = 0; - - sensindx = match_str(sens.label, data.label{k}); - for l=goodsensindcs(:)' - distance = norm(sens.pnt(l,:)-sens.pnt(sensindx,:)); - if distance1 && channel{i}(1)=='*' - % the wildcard is at the start - labelreg = labelreg | ~cellfun(@isempty, regexp(datachannel, ['.*' channel{i}(2:end) '$'], 'once')); - findreg = [findreg i]; - elseif length(channel{i})>1 && channel{i}(end)=='*' - % the wildcard is at the end - labelreg = labelreg | ~cellfun(@isempty, regexp(datachannel, ['^' channel{i}(1:end-1) '.*'], 'once')); - findreg = [findreg i]; - elseif length(channel{i})>1 && any(channel{i}=='*') - % the wildcard is in the middle - sel = strfind(channel{i}, '*'); - str1 = channel{i}(1:(sel-1)); - str2 = channel{i}((sel+1):end); - labelreg = labelreg | ~cellfun(@isempty, regexp(datachannel, ['^' str1 '.*' str2 '$'], 'once')); - findreg = [findreg i]; - end -end -labelreg = datachannel(labelreg); - -% initialize all the system-specific variables to empty -labelmeg = []; -labelmref = []; -labeleeg = []; - -switch senstype(datachannel) - - case {'ctf', 'ctf275', 'ctf151', 'ctf275_planar', 'ctf151_planar'} - % all CTF MEG channels start with "M" - % all CTF reference channels start with B, G, P, Q or R - % all CTF EEG channels start with "EEG" - labelmeg = datachannel(strncmp('M' , datachannel, length('M' ))); - labelmref = [datachannel(strncmp('B' , datachannel, 1)); - datachannel(strncmp('G' , datachannel, 1)); - datachannel(strncmp('P' , datachannel, 1)); - datachannel(strncmp('Q' , datachannel, 1)); - datachannel(strncmp('R' , datachannel, length('G' )))]; - labeleeg = datachannel(strncmp('EEG', datachannel, length('EEG'))); - - % Not sure whether this should be here or outside the switch or - % whether these specifications should be supported for systems - % other than CTF. - labelmz = datachannel(strncmp('MZ' , datachannel, length('MZ' ))); % central MEG channels - labelml = datachannel(strncmp('ML' , datachannel, length('ML' ))); % left MEG channels - labelmr = datachannel(strncmp('MR' , datachannel, length('MR' ))); % right MEG channels - labelmlc = datachannel(strncmp('MLC', datachannel, length('MLC'))); - labelmlf = datachannel(strncmp('MLF', datachannel, length('MLF'))); - labelmlo = datachannel(strncmp('MLO', datachannel, length('MLO'))); - labelmlp = datachannel(strncmp('MLP', datachannel, length('MLP'))); - labelmlt = datachannel(strncmp('MLT', datachannel, length('MLT'))); - labelmrc = datachannel(strncmp('MRC', datachannel, length('MRC'))); - labelmrf = datachannel(strncmp('MRF', datachannel, length('MRF'))); - labelmro = datachannel(strncmp('MRO', datachannel, length('MRO'))); - labelmrp = datachannel(strncmp('MRP', datachannel, length('MRP'))); - labelmrt = datachannel(strncmp('MRT', datachannel, length('MRT'))); - labelmzc = datachannel(strncmp('MZC', datachannel, length('MZC'))); - labelmzf = datachannel(strncmp('MZF', datachannel, length('MZF'))); - labelmzo = datachannel(strncmp('MZO', datachannel, length('MZO'))); - labelmzp = datachannel(strncmp('MZP', datachannel, length('MZP'))); - - case {'bti', 'bti248', 'bti148', 'bti248_planar', 'bti148_planar'} - % all 4D-BTi MEG channels start with "A" - % all 4D-BTi reference channels start with M or G - labelmeg = datachannel(strncmp('A' , datachannel, 1)); - labelmref = [datachannel(strncmp('M' , datachannel, 1)); - datachannel(strncmp('G' , datachannel, 1))]; - labelmrefa = datachannel(~cellfun(@isempty,strfind(datachannel, 'a'))); - labelmrefc = datachannel(strncmp('MC', datachannel, 2)); - labelmrefg = datachannel(strncmp('G', datachannel, 1)); - labelmrefl = datachannel(strncmp('ML', datachannel, 2)); - labelmrefr = datachannel(strncmp('MR', datachannel, 2)); - - case {'neuromag306', 'neuromag122'} - % all neuromag MEG channels start with MEG - % all neuromag EEG channels start with EEG - labelmeg = datachannel(strncmp('MEG', datachannel, length('MEG'))); - labeleeg = datachannel(strncmp('EEG', datachannel, length('EEG'))); - - case {'biosemi64', 'biosemi128', 'biosemi256', 'egi64', 'egi128', 'egi256', 'ext1020'} - % use an external helper function to define the list with EEG channel names - labeleeg = senslabel(senstype(datachannel)); - -end % switch senstype - -% figure out if there are bad channels or channel groups that should be excluded -findbadchannel = strncmp('-', channel, length('-')); % bad channels start with '-' -badchannel = channel(findbadchannel); -if ~isempty(badchannel) - for i=1:length(badchannel) - badchannel{i} = badchannel{i}(2:end); % remove the '-' from the channel label - end - badchannel = channelselection(badchannel, datachannel); % support exclusion of channel groups - channel(findbadchannel) = []; % remove them from the channels to be processed -end - -% determine if any of the known groups is mentioned in the channel list -findall = find(strcmp(channel, 'all')); -% findreg (for the wildcards) is dealt with in the channel group specification above -findmeg = find(strcmp(channel, 'MEG')); -findemg = find(strcmp(channel, 'EMG')); -findeeg = find(strcmp(channel, 'EEG')); -findeeg1020 = find(strcmp(channel, 'EEG1020')); -findeeg1010 = find(strcmp(channel, 'EEG1010')); -findeeg1005 = find(strcmp(channel, 'EEG1005')); -findeegchwilla = find(strcmp(channel, 'EEGCHWILLA')); -findeegbham = find(strcmp(channel, 'EEGBHAM')); -findeegref = find(strcmp(channel, 'EEGREF')); -findmegref = find(strcmp(channel, 'MEGREF')); -findmegrefa = find(strcmp(channel, 'MEGREFA')); -findmegrefc = find(strcmp(channel, 'MEGREFC')); -findmegrefg = find(strcmp(channel, 'MEGREFG')); -findmegrefl = find(strcmp(channel, 'MEGREFL')); -findmegrefr = find(strcmp(channel, 'MEGREFR')); -findeog = find(strcmp(channel, 'EOG')); -findmz = find(strcmp(channel, 'MZ' )); -findml = find(strcmp(channel, 'ML' )); -findmr = find(strcmp(channel, 'MR' )); -findmlc = find(strcmp(channel, 'MLC')); -findmlf = find(strcmp(channel, 'MLF')); -findmlo = find(strcmp(channel, 'MLO')); -findmlp = find(strcmp(channel, 'MLP')); -findmlt = find(strcmp(channel, 'MLT')); -findmrc = find(strcmp(channel, 'MRC')); -findmrf = find(strcmp(channel, 'MRF')); -findmro = find(strcmp(channel, 'MRO')); -findmrp = find(strcmp(channel, 'MRP')); -findmrt = find(strcmp(channel, 'MRT')); -findmzc = find(strcmp(channel, 'MZC')); -findmzf = find(strcmp(channel, 'MZF')); -findmzo = find(strcmp(channel, 'MZO')); -findmzp = find(strcmp(channel, 'MZP')); -findlfp = find(strcmp(channel, 'lfp')); -findmua = find(strcmp(channel, 'mua')); -findspike = find(strcmp(channel, 'spike')); -findgui = find(strcmp(channel, 'gui')); - -% remove any occurences of groups in the channel list -channel([ - findall - findreg - findmeg - findemg - findeeg - findeeg1020 - findeeg1010 - findeeg1005 - findeegchwilla - findeegbham - findeegref - findmegref - findeog - findmz - findml - findmr - findmlc - findmlf - findmlo - findmlp - findmlt - findmrc - findmrf - findmro - findmrp - findmrt - findmzc - findmzf - findmzo - findmzp - findlfp - findmua - findspike - findgui - ]) = []; - -% add the full channel labels to the channel list -if findall, channel = [channel; labelall]; end -if findreg, channel = [channel; labelreg]; end -if findmeg, channel = [channel; labelmeg]; end -if findemg, channel = [channel; labelemg]; end -if findeeg, channel = [channel; labeleeg]; end -if findeeg1020, channel = [channel; label1020]; end -if findeeg1010, channel = [channel; label1010]; end -if findeeg1005, channel = [channel; label1005]; end -if findeegchwilla, channel = [channel; labelchwilla]; end -if findeegbham, channel = [channel; labelbham]; end -if findeegref, channel = [channel; labelref]; end -if findmegref, channel = [channel; labelmref]; end -if findmegrefa, channel = [channel; labelmrefa]; end -if findmegrefc, channel = [channel; labelmrefc]; end -if findmegrefg, channel = [channel; labelmrefg]; end -if findmegrefl, channel = [channel; labelmrefl]; end -if findmegrefr, channel = [channel; labelmrefr]; end -if findeog, channel = [channel; labeleog]; end -if findmz , channel = [channel; labelmz ]; end -if findml , channel = [channel; labelml ]; end -if findmr , channel = [channel; labelmr ]; end -if findmlc, channel = [channel; labelmlc]; end -if findmlf, channel = [channel; labelmlf]; end -if findmlo, channel = [channel; labelmlo]; end -if findmlp, channel = [channel; labelmlp]; end -if findmlt, channel = [channel; labelmlt]; end -if findmrc, channel = [channel; labelmrc]; end -if findmrf, channel = [channel; labelmrf]; end -if findmro, channel = [channel; labelmro]; end -if findmrp, channel = [channel; labelmrp]; end -if findmrt, channel = [channel; labelmrt]; end -if findmzc, channel = [channel; labelmzc]; end -if findmzf, channel = [channel; labelmzf]; end -if findmzo, channel = [channel; labelmzo]; end -if findmzp, channel = [channel; labelmzp]; end -if findlfp, channel = [channel; labellfp]; end -if findmua, channel = [channel; labelmua]; end -if findspike, channel = [channel; labelspike]; end - -% remove channel labels that have been excluded by the user -badindx = match_str(channel, badchannel); -channel(badindx) = []; - -% remove channel labels that are not present in the data -chanindx = match_str(channel, datachannel); - -channel = channel(chanindx); - -if findgui - indx = select_channel_list(datachannel, match_str(datachannel, channel), 'Select channels'); - channel = datachannel(indx); -end - -% remove channels that occur more than once, this sorts the channels alphabetically -channel = unique(channel); - -% undo the sorting, make the order identical to that of the data channels -[dataindx, indx] = match_str(datachannel, channel); -channel = channel(indx); diff --git a/external/fieldtrip/private/chantype.m b/external/fieldtrip/private/chantype.m deleted file mode 100644 index 0b641f7..0000000 --- a/external/fieldtrip/private/chantype.m +++ /dev/null @@ -1,407 +0,0 @@ -function type = chantype(input, desired) - -% CHANTYPE determines for each channel what type it is, e.g. planar/axial gradiometer or magnetometer -% -% Use as -% type = chantype(hdr) -% type = chantype(sens) -% type = chantype(label) -% or as -% type = chantype(hdr, desired) -% type = chantype(sens, desired) -% type = chantype(label, desired) - -% Copyright (C) 2008, Robert Oostenveld -% -% $Log: chantype.m,v $ -% Revision 1.15 2009/10/16 12:27:53 roboos -% some small changes pertaining to the itab/chieti format -% -% Revision 1.14 2009/10/13 10:39:03 roboos -% added support for 153 channel itab system -% -% Revision 1.13 2009/09/22 11:15:47 vlalit -% Changes by Laurence Hunt for distinguishing between analog and digital event channels for Neuromag. -% -% Revision 1.12 2009/03/30 17:53:38 vlalit -% Fixed a bug in BTi handling code from the last update -% -% Revision 1.11 2009/03/26 19:17:21 vlalit -% Some improvements for non-MEG channels in BTi -% -% Revision 1.10 2009/03/06 08:49:54 roboos -% added handling of plexon header -% -% Revision 1.9 2009/02/05 18:30:44 vlalit -% Updates by Laurence to recognize additional Neuromag sensor types -% -% Revision 1.8 2009/02/02 12:09:28 vlalit -% Added back support of generic desired types 'meg' and 'ref'. -% -% Revision 1.7 2009/01/29 18:51:53 vlalit -% Some cosmetic changes + detection of additional channel types based on label -% -% Revision 1.6 2009/01/29 16:42:31 vlalit -% Standardized all the names of MEG-related types accross different MEG system. -% -% Revision 1.5 2009/01/29 16:09:06 jansch -% added check for gradiometers in meg-sensors for bti -% -% Revision 1.4 2009/01/29 11:45:12 vlalit -% Basic support for BTi based on code from channelselection -% -% Revision 1.3 2009/01/23 10:32:55 vlalit -% New reader for Neuromag fif format using the MNE toolbox -% (http://www.nmr.mgh.harvard.edu/martinos/userInfo/data/sofMNE.php) -% implemented by Laurence Hunt. -% -% Revision 1.2 2009/01/21 16:42:41 vlalit -% Added support for EEG systems. -% -% Revision 1.7 2008/11/12 20:32:31 roboos -% refined ctf headloc channels -% -% Revision 1.6 2008/11/03 11:36:09 roboos -% added work-around for unusual/spm5 ctf headers -> give warning and keep all at unknown -% give error for weird input -% -% Revision 1.5 2008/10/22 07:22:46 roboos -% also detect refmag and refgrad from ctf labels, use regexp and local subfunction -% -% Revision 1.4 2008/10/21 20:32:47 roboos -% added second input argument (desired type) -% besides hdr, also allow grad and label input (ctf only sofar) -% -% Revision 1.3 2008/10/20 15:14:06 roboos -% added missing semicolon -% -% Revision 1.2 2008/09/10 10:06:07 roboos -% added ctf headloc -% -% Revision 1.1 2008/09/10 10:04:22 roboos -% new function -% - -% determine the type of input - -isheader = isa(input, 'struct') && isfield(input, 'label') && isfield(input, 'Fs'); -isgrad = isa(input, 'struct') && isfield(input, 'pnt') && isfield(input, 'ori'); -islabel = isa(input, 'cell') && isa(input{1}, 'char'); - -hdr = input; -grad = input; -label = input; - -if isheader - numchan = length(hdr.label); - if isfield(hdr, 'grad') - grad = hdr.grad; - end - label = hdr.label; -elseif isgrad - label = grad.label; - numchan = length(label); -elseif islabel - numchan = length(label); -else - error('the input that was provided to this function cannot be deciphered'); -end - -% start with unknown type -type = cell(numchan,1); -for i=1:length(type) - type{i} = 'unknown'; -end - -if senstype(input, 'neuromag') - % channames-KI is the channel kind, 1=meg, 202=eog, 2=eeg, 3=trigger (I am nut sure, but have inferred this from a single test file) - % chaninfo-TY is the Coil type (0=magnetometer, 1=planar gradiometer) - if isfield(hdr, 'orig') && isfield(hdr.orig, 'channames') - for sel=find(hdr.orig.channames.KI(:)==202)' - type{sel} = 'eog'; - end - for sel=find(hdr.orig.channames.KI(:)==2)' - type{sel} = 'eeg'; - end - for sel=find(hdr.orig.channames.KI(:)==3)' - type{sel} = 'digital trigger'; - end - % determinge the MEG channel subtype - selmeg=find(hdr.orig.channames.KI(:)==1)'; - for i=1:length(selmeg) - if hdr.orig.chaninfo.TY(i)==0 - type{selmeg(i)} = 'megmag'; - elseif hdr.orig.chaninfo.TY(i)==1 - type{selmeg(i)} = 'megplanar'; - end - end - - elseif isfield(hdr, 'orig') && isfield(hdr.orig, 'chs') && isfield(hdr.orig.chs, 'coil_type') - %all the chs.kinds and chs.coil_types are obtained from the MNE - %manual, p.210-211 - for sel=find([hdr.orig.chs.kind]==1 & [hdr.orig.chs.coil_type]==2)' %planar gradiometers - type(sel) = {'megplanar'}; %Neuromag-122 planar gradiometer - end - for sel=find([hdr.orig.chs.kind]==1 & [hdr.orig.chs.coil_type]==3012)' %planar gradiometers - type(sel) = {'megplanar'}; %Type T1 planar grad - end - for sel=find([hdr.orig.chs.kind]==1 & [hdr.orig.chs.coil_type]==3013)' %planar gradiometers - type(sel) = {'megplanar'}; %Type T2 planar grad - end - for sel=find([hdr.orig.chs.kind]==1 & [hdr.orig.chs.coil_type]==3014)' %planar gradiometers - type(sel) = {'megplanar'}; %Type T3 planar grad - end - for sel=find([hdr.orig.chs.kind]==1 & [hdr.orig.chs.coil_type]==3022)' %magnetometers - type(sel) = {'megmag'}; %Type T1 magenetometer - end - for sel=find([hdr.orig.chs.kind]==1 & [hdr.orig.chs.coil_type]==3023)' %magnetometers - type(sel) = {'megmag'}; %Type T2 magenetometer - end - for sel=find([hdr.orig.chs.kind]==1 & [hdr.orig.chs.coil_type]==3024)' %magnetometers - type(sel) = {'megmag'}; %Type T3 magenetometer - end - for sel=find([hdr.orig.chs.kind]==301)' %MEG reference channel, located far from head - type(sel) = {'ref'}; - end - for sel=find([hdr.orig.chs.kind]==2)' %EEG channels - type(sel) = {'eeg'}; - end - for sel=find([hdr.orig.chs.kind]==201)' %MCG channels - type(sel) = {'mcg'}; - end - for sel=find([hdr.orig.chs.kind]==3)' %Stim channels - if any([hdr.orig.chs(sel).logno] == 101) %new systems: 101 (and 102, if enabled) are digital; - %low numbers are 'pseudo-analog' (if enabled) - type(sel([hdr.orig.chs(sel).logno] == 101)) = {'digital trigger'}; - type(sel([hdr.orig.chs(sel).logno] == 102)) = {'digital trigger'}; - type(sel([hdr.orig.chs(sel).logno] <= 32)) = {'analog trigger'}; - others = [hdr.orig.chs(sel).logno] > 32 & [hdr.orig.chs(sel).logno] ~= 101 & ... - [hdr.orig.chs(sel).logno] ~= 102; - type(sel(others)) = {'other trigger'}; - elseif any([hdr.orig.chs(sel).logno] == 14) %older systems: STI 014/015/016 are digital; - %lower numbers 'pseudo-analog'(if enabled) - type(sel([hdr.orig.chs(sel).logno] == 14)) = {'digital trigger'}; - type(sel([hdr.orig.chs(sel).logno] == 15)) = {'digital trigger'}; - type(sel([hdr.orig.chs(sel).logno] == 16)) = {'digital trigger'}; - type(sel([hdr.orig.chs(sel).logno] <= 13)) = {'analog trigger'}; - others = [hdr.orig.chs(sel).logno] > 16; - type(sel(others)) = {'other trigger'}; - else - warning('There does not seem to be a suitable trigger channel.'); - type(sel) = {'other trigger'}; - end - end - for sel=find([hdr.orig.chs.kind]==202)' %EOG - type(sel) = {'eog'}; - end - for sel=find([hdr.orig.chs.kind]==302)' %EMG - type(sel) = {'emg'}; - end - for sel=find([hdr.orig.chs.kind]==402)' %ECG - type(sel) = {'ecg'}; - end - for sel=find([hdr.orig.chs.kind]==502)' %MISC - type(sel) = {'misc'}; - end - for sel=find([hdr.orig.chs.kind]==602)' %Resp - type(sel) = {'respiration'}; - end - end - -elseif senstype(input, 'ctf') && isheader - % meg channels are 5, refmag 0, refgrad 1, adcs 18, trigger 11, eeg 9 - if isfield(hdr, 'orig') && isfield(hdr.orig, 'sensType') - origSensType = hdr.orig.sensType; - elseif isfield(hdr, 'orig') && isfield(hdr.orig, 'res4') - origSensType = [hdr.orig.res4.senres.sensorTypeIndex]; - else - warning('could not determine channel type from the CTF header'); - origSensType = []; - end - - for sel=find(origSensType(:)==5)' - type{sel} = 'meggrad'; - end - for sel=find(origSensType(:)==0)' - type{sel} = 'refmag'; - end - for sel=find(origSensType(:)==1)' - type{sel} = 'refgrad'; - end - for sel=find(origSensType(:)==18)' - type{sel} = 'adc'; - end - for sel=find(origSensType(:)==11)' - type{sel} = 'trigger'; - end - for sel=find(origSensType(:)==9)' - type{sel} = 'eeg'; - end - for sel=find(origSensType(:)==29)' - type{sel} = 'reserved'; % these are "reserved for future use", but relate to head localization - end - for sel=find(origSensType(:)==13)' - type{sel} = 'headloc'; % these represent the x, y, z position of the head coils - end - for sel=find(origSensType(:)==28)' - type{sel} = 'headloc_gof'; % these represent the goodness of fit for the head coils - end - % for sel=find(origSensType(:)==23)' - % type{sel} = 'SPLxxxx'; % I have no idea what these are - % end - -elseif senstype(input, 'ctf') && isgrad - % in principle it is possible to look at the number of coils, but here the channels are identified based on their name - sel = myregexp('^M[ZLR][A-Z][0-9][0-9]$', grad.label); - type(sel) = {'meggrad'}; % normal gradiometer channels - sel = myregexp('^B[GPR][0-9]$', grad.label); - type(sel) = {'refmag'}; % reference magnetometers - sel = myregexp('^[GPQR][0-9][0-9]$', grad.label); - type(sel) = {'refgrad'}; % reference gradiometers - -elseif senstype(input, 'ctf') && islabel - % the channels have to be identified based on their name alone - sel = myregexp('^M[ZLR][A-Z][0-9][0-9]$', label); - type(sel) = {'meggrad'}; % normal gradiometer channels - sel = myregexp('^B[GPR][0-9]$', label); - type(sel) = {'refmag'}; % reference magnetometers - sel = myregexp('^[GPQR][0-9][0-9]$', label); - type(sel) = {'refgrad'}; % reference gradiometers - -elseif senstype(input, 'bti') - % all 4D-BTi MEG channels start with "A" - % all 4D-BTi reference channels start with M or G - % all 4D-BTi EEG channels start with E - type(strncmp('A', label, 1)) = {'meg'}; - type(strncmp('M', label, 1)) = {'refmag'}; - type(strncmp('G', label, 1)) = {'refgrad'}; - - - if isfield(grad, 'tra') - selchan = find(strcmp('mag', type)); - for k = 1:length(selchan) - ncoils = length(find(grad.tra(selchan(k),:)==1)); - if ncoils==1, - type{selchan(k)} = 'megmag'; - elseif ncoils==2, - type{selchan(k)} = 'meggrad'; - end - end - end - - % This is to allow setting additional channel types based on the names - if isheader && issubfield(hdr, 'orig.channel_data.chan_label') - tmplabel = {hdr.orig.channel_data.chan_label}; - tmplabel = tmplabel(:); - else - tmplabel = label; % might work - end - sel = strmatch('unknown', type, 'exact'); - if ~isempty(sel) - type(sel)= chantype(tmplabel(sel)); - sel = strmatch('unknown', type, 'exact'); - if ~isempty(sel) - type(sel(strncmp('E', label(sel), 1))) = {'eeg'}; - end - end - -elseif senstype(input, 'itab') && isheader - sel = ([hdr.orig.ch.type]==0); - type(sel) = {'unknown'}; - sel = ([hdr.orig.ch.type]==1); - type(sel) = {'unknown'}; - sel = ([hdr.orig.ch.type]==2); - type(sel) = {'megmag'}; - sel = ([hdr.orig.ch.type]==8); - type(sel) = {'megref'}; - sel = ([hdr.orig.ch.type]==16); - type(sel) = {'aux'}; - sel = ([hdr.orig.ch.type]==64); - type(sel) = {'digital'}; - % not all channels are actually processed by fieldtrip, so only return - % the types fopr the ones that read_header and read_data return - type = type(hdr.orig.chansel); - -elseif senstype(input, 'itab') && isgrad - % the channels have to be identified based on their name alone - sel = myregexp('^MAG_[0-9][0-9][0-9]$', label); - type(sel) = {'megmag'}; - sel = myregexp('^REF_[0-9][0-9][0-9]$', label); - type(sel) = {'megref'}; - sel = myregexp('^AUX.*$', label); - type(sel) = {'aux'}; - -elseif senstype(input, 'itab') && islabel - % the channels have to be identified based on their name alone - sel = myregexp('^MAG_[0-9][0-9][0-9]$', label); - type(sel) = {'megmag'}; - sel = myregexp('^REF_[0-9][0-9][0-9]$', label); - type(sel) = {'megref'}; - sel = myregexp('^AUX.*$', label); - type(sel) = {'aux'}; - -elseif senstype(input, 'eeg') && islabel - % use an external helper function to define the list with EEG channel names - type(match_str(label, senslabel(senstype(label)))) = {'eeg'}; - -elseif senstype(input, 'eeg') && isheader - % use an external helper function to define the list with EEG channel names - type(match_str(hdr.label, senslabel(senstype(hdr)))) = {'eeg'}; - -elseif senstype(input, 'plexon') && isheader - % this is a complete header that was read from a Plexon *.nex file using read_plexon_nex - for i=1:numchan - switch hdr.orig.VarHeader(i).Type - case 0 - type{i} = 'spike'; - case 1 - type{i} = 'event'; - case 2 - type{i} = 'interval'; % Interval variables? - case 3 - type{i} = 'waveform'; - case 4 - type{i} = 'population'; % Population variables ? - case 5 - type{i} = 'analog'; - otherwise - % keep the default 'unknown' type - end - end - -end % senstype - -% if possible, set additional types based on channel labels -label2type = { - {'ecg', 'ekg'}; - {'emg'}; - {'eog', 'heog', 'veog'}; - {'lfp'}; - {'eeg'}; - }; -for i = 1:numel(label2type) - for j = 1:numel(label2type{i}) - type(intersect(strmatch(label2type{i}{j}, lower(label)),... - strmatch('unknown', type, 'exact'))) = label2type{i}(1); - end -end - -if nargin>1 - % return a boolean vector - if isequal(desired, 'meg') || isequal(desired, 'ref') - type = strncmp(desired, type, 3); - else - type = strcmp(desired, type); - end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% helper function -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function match = myregexp(pat, list) -match = false(size(list)); -for i=1:numel(list) - match(i) = ~isempty(regexp(list{i}, pat, 'once')); -end - - diff --git a/external/fieldtrip/private/check_cfg_required.m b/external/fieldtrip/private/check_cfg_required.m deleted file mode 100644 index 4a13306..0000000 --- a/external/fieldtrip/private/check_cfg_required.m +++ /dev/null @@ -1,40 +0,0 @@ -function check_cfg_required(cfg, a) - -% CHECK_CFG_REQUIRED will show an error if any of the fieldnames is not -% present in the configuration structure -% -% Use as -% check_cfg_required(cfg, fieldnames) -% where fieldnames should be a cell-array containing the fields that -% are required. - -% Copyright (C) 2004, Robert Oostenveld -% -% $Log: check_cfg_required.m,v $ -% Revision 1.1 2004/11/19 12:14:34 roboos -% new implementation -% - -msgid = 'FIELDTRIP:configurationRequired'; - -if ~iscell(a) - a = {a}; -end - -b = fieldnames(cfg); -[c, ia, ib] = setxor(a, b); - -% ensure that they are row vectors -ia = ia(:)'; -ib = ib(:)'; - -if length(ia)>0 - if str2num(version('-release'))>12.1 - % for Matlab versions 6.5 and later - error(msgid, 'The field cfg.%s is required\n', a{1}); - else - % backward compatible for Matlab 6.1 - error(sprintf('The field cfg.%s is required\n', a{1})); - end -end - diff --git a/external/fieldtrip/private/check_cfg_unused.m b/external/fieldtrip/private/check_cfg_unused.m deleted file mode 100644 index 510e272..0000000 --- a/external/fieldtrip/private/check_cfg_unused.m +++ /dev/null @@ -1,52 +0,0 @@ -function check_cfg_unused(cfg, a) - - -% CHECK_CFG_UNUSED will show a warning if the configuration structure -% contains fields that are not used -% -% Use as -% check_cfg_unused(cfg, fieldnames) -% where fieldnames should be a cell-array with the fields that are -% used. - -% Copyright (C) 2004, Robert Oostenveld -% -% $Log: check_cfg_unused.m,v $ -% Revision 1.1 2004/11/19 12:14:34 roboos -% new implementation -% - -% Check the configuration structure for unused fields - -msgid = 'FIELDTRIP:configurationUnused'; - -if ~iscell(a) - a = {a}; -end - -b = fieldnames(cfg); -[c, ia, ib] = setxor(a, b); - -% ensure that they are row vectors -ia = ia(:)'; -ib = ib(:)'; - -if str2num(version('-release'))>12.1 - % for Matlab versions 6.5 and later - if length(ib)>0 - warning off backtrace - warning off verbose - for i=ib(1:(end-1)) - warning(msgid, 'The field cfg.%s is unused\n', b{i}); - end - warning on backtrace - warning on verbose - warning(msgid, 'The field cfg.%s is unused\n', b{end}); - end -else - % backward compatible for Matlab 6.1 - for i=ib(1:end) - warning(sprintf('The field cfg.%s is unused\n', b{i})); - end -end - diff --git a/external/fieldtrip/private/checkdata.m b/external/fieldtrip/private/checkdata.m deleted file mode 100644 index 37c6748..0000000 --- a/external/fieldtrip/private/checkdata.m +++ /dev/null @@ -1,1312 +0,0 @@ -function [data] = checkdata(data, varargin) - -% CHECKDATA checks the input data of the main FieldTrip functions, e.g. whether -% the type of data strucure corresponds with the required data. If neccessary -% and possible, this function will adjust the data structure to the input -% requirements (e.g. change dimord, average over trials, convert inside from -% index into logical). -% -% If the input data does NOT correspond to the requirements, this function -% is supposed to give a elaborate warning message and if applicable point -% the user to external documentation (link to website). -% -% Use as -% [data] = checkdata(data, ...) -% -% Optional input arguments should be specified as key-value pairs and can include -% feedback = yes, no -% datatype = raw, freq, timelock, comp, spike, source, volume, dip -% dimord = any combination of time, freq, chan, refchan, rpt, subj, chancmb, rpttap, pos -% senstype = ctf151, ctf275, ctf151_planar, ctf275_planar, neuromag122, neuromag306, bti148, bti248, bti248_planar, magnetometer, electrode -% inside = logical, index -% ismeg = yes, no -% hastrials = yes, no -% hasoffset = yes, no (only applies to raw data) -% hascumtapcnt = yes, no (only applies to freq data) -% hasdof = yes, no -% cmbrepresentation = sparse, full (applies to covariance and cross-spectral density) -% -% For some options you can specify multiple values, e.g. -% [data] = checkdata(data, 'senstype', {'ctf151', 'ctf275'}), e.g. in megrealign -% [data] = checkdata(data, 'datatype', {'timelock', 'freq'}), e.g. in sourceanalysis - -% Copyright (C) 2007-2009, Robert Oostenveld -% -% $Log: checkdata.m,v $ -% Revision 1.20 2009/10/12 14:52:29 jansch -% fix to handle missing offset field in mvar data -% -% Revision 1.19 2009/10/01 12:41:11 jansch -% added some restructuring possibilities for sourcedimords -% -% Revision 1.18 2009/08/24 08:57:01 jansch -% some changes regarding dealing with dim in source data. made a temporary -% bypass for jan excluding sourcedata from fixdimord. this is done to be able -% to further develop this part of the code without creating an entirely parallel -% version of it. eventually the bypass will be removed -% -% Revision 1.17 2009/08/03 15:08:24 ingnie -% also send source and volume data to fixdimord -% -% Revision 1.16 2009/08/03 11:55:11 roboos -% added comp2raw conversion -% -% Revision 1.15 2009/07/15 12:11:19 jansch -% experimental bypass of sourcedescriptives to create source with single trial -% power per voxel: dimord = 'rpt_pos', undocumented -% -% Revision 1.14 2009/07/06 09:38:24 jansch -% added fixinside to source2volume -% -% Revision 1.13 2009/06/15 12:56:23 roboos -% added a fixcoh function (for sparse->full) -% added some explicit error handling to fixcsd function -% -% Revision 1.12 2009/04/17 09:12:12 jansch -% fixed bug in freq2raw and another typo in source2volume -% -% Revision 1.11 2009/04/07 13:45:01 tinsni -% Fixed typo in help (megtype should be senstype). -% -% Revision 1.10 2009/03/23 21:07:20 jansch -% fixed bug in source2volume in the case of higher dimensional source data -% -% Revision 1.9 2009/02/19 09:19:43 jansch -% built-in pos2dim3d in source2volume, which tries to create a 1x3 dim vector -% from a list of positions (only if the positions describe a full volume in -% an ordered (slice by slice) way. -% -% Revision 1.8 2009/02/13 17:35:22 roboos -% implemented dimord/dim handling for volume and source data, only in case of hasdimord=yes -% convert source.trial(1:N).pow into source.pow with appropriate reshaping -% -% Revision 1.7 2009/02/04 16:42:41 roboos -% use the datatype helper function -% -% Revision 1.6 2009/01/28 12:14:53 roboos -% fixed handling of variable trial length for raw2timelock, esp. in case the trials are of equal length but shifted -% update the trial definition after raw2timelock -% -% Revision 1.5 2009/01/28 10:24:22 jansch -% updated raw2timelock -% -% Revision 1.4 2009/01/28 09:09:40 jansch -% added handling of source data with time and frequency dimensions. -% -% Revision 1.3 2008/12/04 08:23:34 jansch -% added the option to toggle between fourier and sparsewithpow in fixcsd -% -% Revision 1.2 2008/11/14 10:45:47 jansch -% extended the fixcsd subfunction -% -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.28 2008/09/15 13:24:17 roboos -% add dimord to source data, remove x/y/zgrid for volume and/or source, also if no conversion between the two is done -% -% Revision 1.27 2008/08/20 19:00:23 jansch -% also enable correct trial-handling in case of isvolume. before this fix, -% sourcestatistics crashed (reproduced with a grandaverage as input). more -% specifically, it crashed in setsubfield, because the trials were not handled -% correctly. -% -% Revision 1.26 2008/07/30 07:41:10 roboos -% when reshaping source parameters, also loop over source.trial(...) structure array and not only source.avg -% -% Revision 1.25 2008/07/25 12:52:44 roboos -% fixed bug, hasdof would remove cumtapcnt (thanks to Jurrian) -% -% Revision 1.24 2008/07/25 07:15:49 roboos -% cleaned up documentation and some minor aspects of the code (sprintf/error) -% added hasdof, with default value of 'no' -% -% Revision 1.23 2008/07/22 11:39:55 ingnie -% moved the "inside" representation code to prior to reshaping, otherwise the logical volume inside would not be reshaped properly -% -% Revision 1.22 2008/07/22 11:11:01 roboos -% changed the source2volume function so that it works with any type of source positions, as long as they span a 3D volume -% -% Revision 1.21 2008/07/21 11:01:47 roboos -% added source2volume conversion -% update isXXXdatatype after all possible conversions -% ensure that the input is either source or volume, not both -% ensure consistent data dimensions in case of volume data (reshape into 3D representation) -% ensure consistent data dimensions in case of source data (reshape into linear vector representation) -% -% Revision 1.20 2008/05/08 10:45:34 jansch -% changed function-call to sensortype into senstype. changed variable-name -% senstype into stype -% -% Revision 1.19 2008/04/01 10:47:05 jansch -% remove nans in reconstructed timecourses in freq2raw -% -% Revision 1.18 2008/01/29 16:05:18 sashae -% added default setting hasoffset='no' -% -% Revision 1.17 2008/01/18 15:41:11 sashae -% implemented hascumtapcnt, adjusted hasoffset -% -% Revision 1.16 2008/01/10 21:30:30 roboos -% changed some formatting, no functional change -% -% Revision 1.15 2007/12/12 10:33:59 roboos -% switched to local subfunction for the conversion from timelock to raw (instead of seperate data2raw function) -% added support for converting from raw to timelocked, with some constraints -% -% Revision 1.14 2007/11/23 14:40:16 ingnie -% Fixed bug in converting data that occured when datatype had multiple options. -% Added loop over all cells of datatype. -% -% Revision 1.13 2007/11/05 16:01:51 roboos -% fixed bug in error message for sensortype -% -% Revision 1.12 2007/07/25 07:30:06 ingnie -% added freq2raw functionality -% -% Revision 1.11 2007/07/03 16:11:35 roboos -% add fample if required for offset -% -% Revision 1.10 2007/05/30 13:27:00 roboos -% fixed bug for senstype, which did not support multiple options -% -% Revision 1.9 2007/05/30 12:00:24 ingnie -% fixed bug in senstype -% -% Revision 1.8 2007/05/29 16:55:56 ingnie -% added options 'senstype', 'ismeg', 'inside', 'hastrials' and 'hasoffset' -% -% Revision 1.7 2007/05/29 12:54:40 roboos -% updated documentation -% -% Revision 1.6 2007/05/16 11:30:06 roboos -% added check for dimord -% -% Revision 1.5 2007/05/03 07:15:05 roboos -% fixed bug: missing end in loop (thanks to Ali) -% -% Revision 1.4 2007/05/02 16:02:28 roboos -% added dim as a requirement to volume data -% changed the program flow (i.e. the locig) for converting data between different types -% implemented conversion between timelock and raw data -% implemented conversion between source and raw data (will only work for projected lcmv virtual-channel time courses) -% -% Revision 1.3 2007/04/18 10:21:16 roboos -% convert volume to source data if possible -% -% Revision 1.2 2007/04/05 15:35:08 roboos -% less strict on volume data -% -% Revision 1.1 2007/04/03 15:30:05 roboos -% renamed latest copy of checkinput to checkdata, to accomodate the upcoming checkcfg function -% -% Revision 1.7 2007/04/03 06:55:48 jansch -% fixed typo fourier -> fourierspctrm -% -% Revision 1.6 2007/04/02 12:05:02 jansch -% fixed typo -% -% Revision 1.5 2007/03/30 16:50:02 ingnie -% fixed bug; hasfreq also when data does not have time field -% -% Revision 1.4 2007/03/28 16:00:35 roboos -% rewrote most of the function together with Ingrid, implemented feedback and datatype checkdata -% -% Revision 1.3 2007/03/27 09:39:56 ingnie -% only fixdimord implemented -% -% Revision 1.2 2007/02/27 13:35:01 roboos -% added some comments for ingnie to work on -% -% Revision 1.1 2007/02/27 09:24:11 roboos -% initial version that only serves as placeholder for the documentation and some example code -% - -% in case of an error this function could use dbstack for more detailled -% user feedback -% -% this function should replace/encapsulate -% fixdimord -% fixinside -% fixprecision -% fixvolume -% data2raw -% raw2data -% grid2transform -% transform2grid -% fourier2crsspctrm -% freq2cumtapcnt -% sensortype -% time2offset -% offset2time -% -% other potential uses for this function: -% time -> offset in freqanalysis -% average over trials -% csd as matrix - -% get the optional input arguments -feedback = keyval('feedback', varargin); if isempty(feedback), feedback = 'no'; end -dtype = keyval('datatype', varargin); % should not conflict with the datatype function -dimord = keyval('dimord', varargin); -stype = keyval('senstype', varargin); % senstype is a function name which should not be masked -ismeg = keyval('ismeg', varargin); -inside = keyval('inside', varargin); % can be logical or index -hastrials = keyval('hastrials', varargin); -hasoffset = keyval('hasoffset', varargin); if isempty(hasoffset), hasoffset = 'no'; end -hasdimord = keyval('hasdimord', varargin); if isempty(hasdimord), hasdimord = 'no'; end -hascumtapcnt = keyval('hascumtapcnt', varargin); -hasdof = keyval('hasdof', varargin); if isempty(hasdof), hasdof = 'no'; end -cmbrepresentation = keyval('cmbrepresentation', varargin); -channelcmb = keyval('channelcmb', varargin); -sourcedimord = keyval('sourcedimord', varargin); -keepoutside = keyval('keepoutside', varargin); - -% determine the type of input data -% this can be raw, freq, timelock, comp, spike, source, volume, dip -israw = datatype(data, 'raw'); -isfreq = datatype(data, 'freq'); -istimelock = datatype(data, 'timelock'); -iscomp = datatype(data, 'comp'); -isspike = datatype(data, 'spike'); -isvolume = datatype(data, 'volume'); -issource = datatype(data, 'source'); -isdip = datatype(data, 'dip'); -ismvar = datatype(data, 'mvar'); -isfreqmvar = datatype(data, 'freqmvar'); - -% FIXME use the istrue function on ismeg and hasxxx options - -if ~isequal(feedback, 'no') - if israw - nchan = length(data.label); - ntrial = length(data.trial); - fprintf('the input is raw data with %d channels and %d trials\n', nchan, ntrial); - elseif isfreq - nchan = length(data.label); - nfreq = length(data.freq); - if isfield(data, 'time'), ntime = num2str(length(data.time));, else ntime = 'no'; end - fprintf('the input is freq data with %d channels, %d frequencybins and %s timebins\n', nchan, nfreq, ntime); - elseif istimelock - nchan = length(data.label); - ntime = length(data.time); - fprintf('the input is timelock data with %d channels and %d timebins\n', nchan, ntime); - elseif iscomp - ncomp = length(data.label); - nchan = length(data.topolabel); - fprintf('the input is component data with %d components and %d original channels\n', ncomp, nchan); - elseif isspike - nchan = length(data.label); - fprintf('the input is spike data\n'); - elseif isvolume - fprintf('the input is volume data with dimensions [%d %d %d]\n', data.dim(1), data.dim(2), data.dim(3)); - elseif issource - nsource = size(data.pos, 1); - fprintf('the input is source data with %d positions\n', nsource); - elseif isdip - fprintf('the input is dipole data\n'); - elseif ismvar - fprintf('the input is mvar data\n'); - elseif isfreqmvar - fprintf('the input is freqmvar data\n'); - end -end % give feedback - -%HACK for jan to bypass source and volume data to enter fixdimord -[st,result] = system('whoami'); -if isempty(strfind(result,'jan')) - if isfreq || istimelock || iscomp || issource || isvolume - % ensure consistency between the dimord string and the axes that describe the data dimensions - data = fixdimord(data); - end -else - if isfreq || istimelock || iscomp - data = fixdimord(data); - end -end - -if istimelock - % remove the unwanted fields - if isfield(data, 'numsamples'), data = rmfield(data, 'numsamples'); end - if isfield(data, 'numcovsamples'), data = rmfield(data, 'numcovsamples'); end - if isfield(data, 'numblcovsamples'), data = rmfield(data, 'numblcovsamples'); end -end - -if issource && isvolume - % it should be either one or the other - % the choice here is to represent it as volume description since that is simpler to handle - % remove the unwanted fields - if isfield(data, 'pos'), data = rmfield(data, 'pos'); end - if isfield(data, 'xgrid'), data = rmfield(data, 'xgrid'); end - if isfield(data, 'ygrid'), data = rmfield(data, 'ygrid'); end - if isfield(data, 'zgrid'), data = rmfield(data, 'zgrid'); end - issource = false; -end - -if ~isempty(dtype) - if ~isa(dtype, 'cell') - dtype = {dtype}; - end - - okflag = 0; - for i=1:length(dtype) - % check that the data matches with one or more of the required datatypes - switch dtype{i} - case 'raw' - okflag = okflag + israw; - case 'freq' - okflag = okflag + isfreq; - case 'timelock' - okflag = okflag + istimelock; - case 'comp' - okflag = okflag + iscomp; - case 'spike' - okflag = okflag + isspike; - case 'volume' - okflag = okflag + isvolume; - case 'source' - okflag = okflag + issource; - case 'dip' - okflag = okflag + isdip; - case 'mvar' - okflag = okflag + ismvar; - case 'freqmvar' - okflag = okflag + isfreqmvar; - end % switch dtype - end % for dtype - - if ~okflag - % try to convert the data - for iCell = 1:length(dtype) - if isequal(dtype(iCell), {'source'}) && isvolume - data = volume2source(data); - isvolume = 0; - issource = 1; - okflag = 1; - elseif isequal(dtype(iCell), {'volume'}) && issource - data = source2volume(data); - isvolume = 1; - issource = 0; - okflag = 1; - elseif isequal(dtype(iCell), {'raw'}) && issource - data = data2raw(data); - issource = 0; - israw = 1; - okflag = 1; - elseif isequal(dtype(iCell), {'raw'}) && istimelock - data = timelock2raw(data); - istimelock = 0; - israw = 1; - okflag = 1; - elseif isequal(dtype(iCell), {'timelock'}) && israw - data = raw2timelock(data); - israw = 0; - istimelock = 1; - okflag = 1; - elseif isequal(dtype(iCell), {'raw'}) && isfreq - data = freq2raw(data); - isfreq = 0; - israw = 1; - okflag = 1; - elseif isequal(dtype(iCell), {'raw'}) && iscomp - data = comp2raw(data); - iscomp = 0; - israw = 1; - okflag = 1; - end - end % for iCell - end % if okflag - - if ~okflag - % construct an error message - if length(dtype)>1 - str = sprintf('%s, ', dtype{1:(end-2)}); - str = sprintf('%s%s or %s', str, dtype{end-1}, dtype{end}); - else - str = dtype{1}; - end - str = sprintf('This function requires %s data as input.', str); - error(str); - end % if okflag -end - -if ~isempty(dimord) - if ~isa(dimord, 'cell') - dimord = {dimord}; - end - - if isfield(data, 'dimord') - okflag = any(strcmp(data.dimord, dimord)); - else - okflag = 0; - end - - if ~okflag - % construct an error message - if length(dimord)>1 - str = sprintf('%s, ', dimord{1:(end-2)}); - str = sprintf('%s%s or %s', str, dimord{end-1}, dimord{end}); - else - str = dimord{1}; - end - str = sprintf('This function requires data with a dimord of %s.', str); - error(str); - end % if okflag -end - -if ~isempty(stype) - if ~isa(stype, 'cell') - stype = {stype}; - end - - if isfield(data, 'grad') || isfield(data, 'elec') - if any(strcmp(senstype(data), stype)); - okflag = 1; - else - okflag = 0; - end - else - okflag = 0; - end - - if ~okflag - % construct an error message - if length(stype)>1 - str = sprintf('%s, ', stype{1:(end-2)}); - str = sprintf('%s%s or %s', str, stype{end-1}, stype{end}); - else - str = stype{1}; - end - str = sprintf('This function requires %s data as input, but you are giving %s data.', str, senstype(data)); - error(str); - end % if okflag -end - -if ~isempty(ismeg) - if isequal(ismeg,'yes') - okflag = isfield(data, 'grad'); - elseif isequal(ismeg,'no') - okflag = ~isfield(data, 'grad'); - end - - if ~okflag && isequal(ismeg,'yes') - error('This function requires MEG data with a ''grad'' field'); - elseif ~okflag && isequal(ismeg,'no') - error('This function should not be given MEG data with a ''grad'' field'); - end % if okflag -end - -if ~isempty(inside) - % TODO absorb the fixinside function into this code - data = fixinside(data, inside); - okflag = isfield(data, 'inside'); - - if ~okflag - % construct an error message - error('This function requires data with an ''inside'' field.'); - end % if okflag -end - -%if isvolume -% % ensure consistent dimensions of the volumetric data -% % reshape each of the volumes that is found into a 3D array -% param = parameterselection('all', data); -% dim = data.dim; -% for i=1:length(param) -% tmp = getsubfield(data, param{i}); -% tmp = reshape(tmp, dim); -% data = setsubfield(data, param{i}, tmp); -% end -%end - -if issource || isvolume, - % these are not used any more - if isfield(data, 'xgrid'), data = rmfield(data, 'xgrid'); end - if isfield(data, 'ygrid'), data = rmfield(data, 'ygrid'); end - if isfield(data, 'zgrid'), data = rmfield(data, 'zgrid'); end - - % the following section is to make a dimord-consistent representation of - % volume and source data, taking trials, time and frequency into account - if isequal(hasdimord, 'yes') && (~isfield(data, 'dimord') || ~strcmp(data.dimord,sourcedimord)) - - % determine the size of the data - if isfield(data, 'dimord'), - dimtok = tokenize(data.dimord, '_'); - if ~isempty(strmatch('time', dimtok)), Ntime = length(data.time); else Ntime = 1; end - if ~isempty(strmatch('freq', dimtok)), Nfreq = length(data.freq); else Nfreq = 1; end - else - Nfreq = 1; - Ntime = 1; - end - if isfield(data, 'avg') && isfield(data.avg, 'mom') && (isfield(data, 'freq') || isfield(data, 'frequency')) && strcmp(sourcedimord, 'rpt_pos'), - Npos = size(data.pos,1); - Nrpt = length(data.cumtapcnt); - tmpmom = zeros(Npos, size(data.avg.mom{data.inside(1)},2)); - tmpmom(data.inside,:) = cat(1,data.avg.mom{data.inside}); - tmppow = zeros(Npos, Nrpt); - tapcnt = [0;cumsum(data.cumtapcnt)]; - for k = 1:Nrpt - Ntap = tapcnt(k+1)-tapcnt(k); - tmppow(data.inside,k) = sum(abs(tmpmom(data.inside,(tapcnt(k)+1):tapcnt(k+1))).^2,2)./Ntap; - end - data.pow = tmppow'; - data = rmfield(data, 'avg'); - elseif isfield(data, 'avg') && isfield(data.avg, 'mom') && isfield(data, 'time') && strcmp(sourcedimord, 'pos_time'), - Npos = size(data.pos,1); - Nrpt = 1; - tmpmom = zeros(Npos, size(data.avg.mom{data.inside(1)},2)); - tmpmom(data.inside,:) = cat(1,data.avg.mom{data.inside}); - data.mom = tmpmom; - if isfield(data.avg, 'noise'), - tmpnoise = data.avg.noise(:); - data.noise = tmpnoise(:,ones(1,size(tmpmom,2))); - end - data = rmfield(data, 'avg'); - Ntime = length(data.time); - elseif isfield(data, 'trial') && isfield(data.trial(1), 'mom') && isfield(data, 'time') && strcmp(sourcedimord, 'rpt_pos_time'), - Npos = size(data.pos,1); - Nrpt = length(data.trial); - Ntime = length(data.time); - tmpmom = zeros(Nrpt, Npos, Ntime); - for k = 1:Nrpt - tmpmom(k,data.inside,:) = cat(1,data.trial(k).mom{data.inside}); - end - data = rmfield(data, 'trial'); - data.mom = tmpmom; - elseif isfield(data, 'trial') && isstruct(data.trial) - Nrpt = length(data.trial); - else - Nrpt = 1; - end - - % start with an initial specification of the dimord and dim - if (~isfield(data, 'dim') || ~isfield(data, 'dimord')) - if issource - % at least it should have a Nx3 pos - data.dim = size(data.pos, 1); - data.dimord = 'pos'; - elseif isvolume - % at least it should have a 1x3 dim - data.dim = data.dim; - data.dimord = 'dim1_dim2_dim3'; - end - end - - % add the additional dimensions - if Nfreq>1 - data.dimord = [data.dimord '_freq']; - data.dim = [data.dim Nfreq]; - end - if Ntime>1 - data.dimord = [data.dimord '_time']; - data.dim = [data.dim Ntime]; - end - if Nrpt>1 - data.dimord = ['rpt_' data.dimord]; - data.dim = [Nrpt data.dim ]; - end - - % the nested trial structure is not compatible with dimord - if isfield(data, 'trial') && isstruct(data.trial) - param = fieldnames(data.trial); - for i=1:length(param) - if isa(data.trial(1).(param{i}), 'cell') - concat = cell(data.dim(1), prod(data.dim(2:end))); - else - concat = zeros(data.dim(1), prod(data.dim(2:end))); - end - for j=1:length(data.trial) - tmp = data.trial(j).(param{i}); - concat(j,:) = tmp(:); - end % for each trial - data.trial = rmfield(data.trial, param{i}); - data.(param{i}) = reshape(concat, data.dim); - end % for each param - data = rmfield(data, 'trial'); - end - end - - % ensure consistent dimensions of the source reconstructed data - % reshape each of the source reconstructed parameters - if isfield(data, 'dim'), - dim = [data.dim 1]; - else - %HACK - dimtok = tokenize(data.dimord, '_'); - for i=1:length(dimtok) - if strcmp(dimtok(i),'pos') - dim(1,i) = size(getsubfield(data,dimtok{i}),1); - elseif strcmp(dimtok(i),'rpt') - dim(1,i) = nan; - else - dim(1,i) = length(getsubfield(data,dimtok{i})); - end - end - i = find(isnan(dim)); - if ~isempty(i) - n = fieldnames(data); - for ii=1:length(n) - numels(1,ii) = numel(getfield(data,n{ii})); - end - nrpt = numels./prod(dim(setdiff(1:length(dim),i))); - nrpt = nrpt(nrpt==round(nrpt)); - dim(i) = max(nrpt); - end - if numel(dim)==1, dim(1,2) = 1; end; - end - - if issource, exclude = {'inside' 'fwhm' 'leadfield' 'q' 'rough'}; end - if isvolume, exclude = { 'fwhm' 'leadfield' 'q' 'rough'}; end - - param = setdiff(parameterselection('all', data), exclude); - for i=1:length(param) - if any(param{i}=='.') - % the parameter is nested in a substructure, which can have multiple elements (e.g. source.trial(1).pow, source.trial(2).pow, ...) - % loop over the substructure array and reshape for every element - tok = tokenize(param{i}, '.'); - sub1 = tok{1}; % i.e. this would be 'trial' - sub2 = tok{2}; % i.e. this would be 'pow' - tmp1 = getfield(data, sub1); - for j=1:numel(tmp1) - tmp2 = getfield(tmp1(j), sub2); - tmp2 = reshape(tmp2, dim); - tmp1(j) = setfield(tmp1(j), sub2, tmp2); - end - data = setfield(data, sub1, tmp1); - else - tmp = getfield(data, param{i}); - tmp = reshape(tmp, dim); - data = setfield(data, param{i}, tmp); - end - end - -end - -if isequal(hastrials,'yes') - okflag = isfield(data, 'trial'); - - if ~okflag - error('This function requires data with a ''trial'' field'); - end % if okflag -end - -if isequal(hasoffset,'yes') - okflag = isfield(data, 'offset'); - - if ~okflag && isfield(data, 'time') && isa(data.time, 'cell') - if ~isfield(data, 'fsample') - data.fsample = 1/(data.time{1}(2)-data.time{1}(1)); - end - for i=1:length(data.time); - data.offset(i) = time2offset(data.time{i}, data.fsample); - end - okflag = 1; - elseif ~okflag && datatype(data, 'mvar') - data.offset = 0; - okflag = 1; - end - - if ~okflag - error('This function requires data with an ''offset'' field'); - end % if okflag - -elseif isequal(hasoffset,'no') && isfield(data, 'offset') - data = rmfield(data, 'offset'); -end % if hasoffset - -if isequal(hascumtapcnt,'yes') && ~isfield(data, 'cumtapcnt') - error('This function requires data with a ''cumtapcnt'' field'); -elseif isequal(hascumtapcnt,'no') && isfield(data, 'cumtapcnt') - data = rmfield(data, 'cumtapcnt'); -end % if hascumtapcnt - -if isequal(hasdof,'yes') && ~isfield(data, 'hasdof') - error('This function requires data with a ''dof'' field'); -elseif isequal(hasdof,'no') && isfield(data, 'hasdof') - data = rmfield(data, 'cumtapcnt'); -end % if hasdof - -if ~isempty(cmbrepresentation) - if istimelock - data = fixcov(data, cmbrepresentation); - elseif isfreq && isfield(data, 'cohspctrm') - data = fixcoh(data, cmbrepresentation, channelcmb); - elseif isfreq && ~isfield(data, 'cohspctrm') - data = fixcsd(data, cmbrepresentation, channelcmb); - elseif isfreqmvar - data = fixcsd(data, cmbrepresentation, channelcmb); - else - error('This function requires data with a covariance, coherence or cross-spectrum'); - end -end % cmbrepresentation - -if issource && strcmp(keepoutside, 'no'), - data = source2sparse(data); % FIXME does this still exist? -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% represent the covariance matrix in a particular manner -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function data = fixcov(data, desired) -if isfield(data, 'cov') && ~isfield(data, 'labelcmb') - current = 'full'; -elseif isfield(data, 'cov') && isfield(data, 'labelcmb') - current = 'sparse'; -else - error('Could not determine the current representation of the covariance matrix'); -end -if isequal(current, desired) - % nothing to do -elseif strcmp(current, 'full') && strcmp(desired, 'sparse') - % FIXME should be implemented - error('not yet implemented'); -elseif strcmp(current, 'sparse') && strcmp(desired, 'full') - % FIXME should be implemented - error('not yet implemented'); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% represent the covariance matrix in a particular manner -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function data = fixcoh(data, desired, channelcmb) -if isfield(data, 'cohspctrm') && ~isfield(data, 'labelcmb') - current = 'full'; -elseif isfield(data, 'cohspctrm') && isfield(data, 'labelcmb') - current = 'sparse'; -else - error('Could not determine the current representation of the coherence'); -end -if isequal(current, desired) - % nothing to do -elseif strcmp(current, 'full') && strcmp(desired, 'sparse') - % FIXME should be implemented - error('not yet implemented'); - -elseif strcmp(current, 'sparse') && strcmp(desired, 'full') - dimtok = tokenize(data.dimord, '_'); - if ~isempty(strmatch('freq', dimtok)), nfrq=length(data.freq); else nfrq = 1; end - if ~isempty(strmatch('time', dimtok)), ntim=length(data.time); else ntim = 1; end - nchan = length(data.label); - cmbindx = zeros(nchan); - for k = 1:size(data.labelcmb,1) - ch1 = find(strcmp(data.label, data.labelcmb(k,1))); - ch2 = find(strcmp(data.label, data.labelcmb(k,2))); - if ~isempty(ch1) && ~isempty(ch2), cmbindx(ch1,ch2) = k; end - end - cohspctrm = nan(nchan,nchan,nfrq,ntim); - for k = 1:ntim - for m = 1:nfrq - tmpdat = nan+zeros(nchan); - tmpdat(find(cmbindx)) = data.cohspctrm(cmbindx(find(cmbindx)),m,k); - tmpdat = ctranspose(tmpdat); - tmpdat(find(cmbindx)) = data.cohspctrm(cmbindx(find(cmbindx)),m,k); - cohspctrm(:,:,m,k) = tmpdat; - end - end - % remove obsolete fields - data = rmfield(data, 'powspctrm'); - data = rmfield(data, 'labelcmb'); - % replace updated fields - data.cohspctrm = cohspctrm; - try, data = rmfield(data, 'dof'); end - if ntim>1, - data.dimord = 'chan_chan_freq_time'; - else - data.dimord = 'chan_chan_freq'; - end - -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% represent the cross-spectral-density matrix in a particular manner -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function data = fixcsd(data, desired, channelcmb) -if isfield(data, 'crsspctrm') && isfield(data, 'powspctrm') - current = 'sparsewithpow'; -elseif isfield(data, 'crsspctrm') && ~isfield(data, 'labelcmb') - current = 'full'; -elseif isfield(data, 'crsspctrm') && isfield(data, 'labelcmb') - current = 'sparse'; -elseif isfield(data, 'fourierspctrm') && ~isfield(data, 'labelcmb') - current = 'fourier'; -else - error('Could not determine the current representation of the cross-spectrum matrix'); -end - -if isequal(current, desired) - % nothing to do - -elseif (strcmp(current, 'full') && strcmp(desired, 'sparsewithpow')) - error('not yet implemented'); - -elseif (strcmp(current, 'fourier') && strcmp(desired, 'sparsewithpow')) - % this is what freqdescriptives currently does as an intermediate step - dimtok = tokenize(data.dimord, '_'); - if ~isempty(strmatch('rpttap', dimtok)), - nrpt = length(data.cumtapcnt); - flag = 0; - else - nrpt = 1; - flag = 1; - end - if ~isempty(strmatch('freq', dimtok)), nfrq=length(data.freq); else nfrq = 1; end - if ~isempty(strmatch('time', dimtok)), ntim=length(data.time); else ntim = 1; end - - %create auto-spectra - nchan = length(data.label); - powspctrm = zeros(nrpt,nchan,nfrq,ntim)+i.*zeros(nrpt,nchan,nfrq,ntim); - sumtapcnt = [0;cumsum(data.cumtapcnt(:))]; - for p = 1:nrpt - indx = (sumtapcnt(p)+1):sumtapcnt(p+1); - tmpdat = data.fourierspctrm(indx,:,:,:); - powspctrm(p,:,:,:) = (sum(tmpdat.*conj(tmpdat),1))./data.cumtapcnt(p); - end - - %create cross-spectra - if ~isempty(channelcmb), - ncmb = size(channelcmb,1); - cmbindx = zeros(ncmb,2); - labelcmb = cell(ncmb,2); - for k = 1:ncmb - ch1 = find(strcmp(data.label, channelcmb(k,1))); - ch2 = find(strcmp(data.label, channelcmb(k,2))); - if ~isempty(ch1) && ~isempty(ch2), - cmbindx(k,:) = [ch1 ch2]; - labelcmb(k,:) = data.label([ch1 ch2])'; - end - end - - crsspctrm = zeros(nrpt,ncmb,nfrq,ntim)+i.*zeros(nrpt,ncmb,nfrq,ntim); - for p = 1:nrpt - indx = (sumtapcnt(p)+1):sumtapcnt(p+1); - tmpdat1 = data.fourierspctrm(indx,cmbindx(:,1),:,:); - tmpdat2 = data.fourierspctrm(indx,cmbindx(:,2),:,:); - crsspctrm(p,:,:,:) = (sum(tmpdat1.*conj(tmpdat2),1))./data.cumtapcnt(p); - end - % for k = 1:ntim - % for m = 1:nfrq - % for p = 1:nrpt - % indx = (sumtapcnt(p)+1):sumtapcnt(p+1); - % tmpdat1 = data.fourierspctrm(indx,cmbindx(:,1),m,k); - % tmpdat2 = data.fourierspctrm(indx,cmbindx(:,2),m,k); - % crsspctrm(p,:,m,k) = (sum(tmpdat1.*conj(tmpdat2),1))./data.cumtapcnt(p); - % end - % end - % end - data.crsspctrm = crsspctrm; - data.labelcmb = labelcmb; - end - data.powspctrm = powspctrm; - data = rmfield(data, 'fourierspctrm'); - if nrpt>1, - if ntim>1, - data.dimord = 'rpt_chan_freq_time'; - else - data.dimord = 'rpt_chan_freq'; - end - else - if ntim>1, - data.dimord = 'chan_freq_time'; - else - data.dimord = 'chan_freq'; - end - end - if flag, siz = size(data.crsspctrm); data.crsspctrm = reshape(data.crsspctrm, siz(2:end)); end - -elseif (strcmp(current, 'sparse') && strcmp(desired, 'sparsewithpow')) - % convert back to crsspctrm/powspctrm representation: useful for plotting functions etc - error('not yet implemented'); - -elseif (strcmp(current, 'full') && strcmp(desired, 'fourier')) || ... - (strcmp(current, 'sparse') && strcmp(desired, 'fourier')) || ... - (strcmp(current, 'sparsewithpow') && strcmp(desired, 'fourier')) - % this is not possible - error('converting the cross-spectrum into a Fourier representation is not possible'); - -elseif strcmp(current, 'full') && strcmp(desired, 'sparse') - % why would you want this? FIXME give explicit error - error('not yet implemented'); - -elseif strcmp(current, 'fourier') && strcmp(desired, 'sparse') - - if isempty(channelcmb), error('no channel combinations are specified'); end - % this is what freqdescriptives currently does as an intermediate step - dimtok = tokenize(data.dimord, '_'); - if ~isempty(strmatch('rpttap', dimtok)), - nrpt = length(data.cumtapcnt); - flag = 0; - else - nrpt = 1; - flag = 1; - end - if ~isempty(strmatch('freq', dimtok)), nfrq=length(data.freq); else nfrq = 1; end - if ~isempty(strmatch('time', dimtok)), ntim=length(data.time); else ntim = 1; end - ncmb = size(channelcmb,1); - cmbindx = zeros(ncmb,2); - labelcmb = cell(ncmb,2); - for k = 1:ncmb - ch1 = find(strcmp(data.label, channelcmb(k,1))); - ch2 = find(strcmp(data.label, channelcmb(k,2))); - if ~isempty(ch1) && ~isempty(ch2), - cmbindx(k,:) = [ch1 ch2]; - labelcmb(k,:) = data.label([ch1 ch2])'; - end - end - - crsspctrm = zeros(nrpt,ncmb,nfrq,ntim)+i.*zeros(nrpt,ncmb,nfrq,ntim); - sumtapcnt = [0;cumsum(data.cumtapcnt(:))]; - %for k = 1:ntim - %for m = 1:nfrq - %for p = 1:nrpt - % indx = (sumtapcnt(p)+1):sumtapcnt(p+1); - % tmpdat1 = data.fourierspctrm(indx,cmbindx(:,1),m,k); - % tmpdat2 = data.fourierspctrm(indx,cmbindx(:,2),m,k); - % crsspctrm(p,:,m,k) = (sum(tmpdat1.*conj(tmpdat2),1))./data.cumtapcnt(p); - %end - for p = 1:nrpt - indx = (sumtapcnt(p)+1):sumtapcnt(p+1); - tmpdat1 = data.fourierspctrm(indx,cmbindx(:,1),:,:); - tmpdat2 = data.fourierspctrm(indx,cmbindx(:,2),:,:); - crsspctrm(p,:,:,:) = (sum(tmpdat1.*conj(tmpdat2),1))./data.cumtapcnt(p); - end - %end - %end - data.crsspctrm = crsspctrm; - data.labelcmb = labelcmb; - data = rmfield(data, 'fourierspctrm'); - if nrpt>1, - if ntim>1, - data.dimord = 'rpt_chan_freq_time'; - else - data.dimord = 'rpt_chan_freq'; - end - else - if ntim>1, - data.dimord = 'chan_freq_time'; - else - data.dimord = 'chan_freq'; - end - end - if flag, siz = size(data.crsspctrm); data.crsspctrm = reshape(data.crsspctrm, siz(2:end)); end - - -elseif strcmp(current, 'sparsewithpow') && strcmp(desired, 'sparse') - - % this is what freqdescriptives currently does as an intermediate step, - % and will be the new default representation for sparse data i.e. autospectra - % as {'A' 'A'} in labelcmb - if isfield(data, 'crsspctrm'), - dimtok = tokenize(data.dimord, '_'); - catdim = match_str(dimtok, {'chan' 'chancmb'}); - data.crsspctrm = cat(catdim, data.powspctrm, data.crsspctrm); - data.labelcmb = [data.label(:) data.label(:); data.labelcmb]; - data = rmfield(data, 'powspctrm'); - else - data.crsspctrm = data.powspctrm; - data.labelcmb = [data.label(:) data.label(:)]; - data = rmfield(data, 'powspctrm'); - end - -elseif strcmp(current, 'fourier') && strcmp(desired, 'full') - - % this is how it is currently and the desired functionality of prepare_freq_matrices - dimtok = tokenize(data.dimord, '_'); - if ~isempty(strmatch('rpttap', dimtok)), - nrpt = length(data.cumtapcnt); - flag = 0; - else - nrpt = 1; - flag = 1; - end - if ~isempty(strmatch('rpttap',dimtok)), nrpt=length(data.cumtapcnt); else nrpt = 1; end - if ~isempty(strmatch('freq', dimtok)), nfrq=length(data.freq); else nfrq = 1; end - if ~isempty(strmatch('time', dimtok)), ntim=length(data.time); else ntim = 1; end - nchan = length(data.label); - crsspctrm = zeros(nrpt,nchan,nchan,nfrq,ntim)+i.*zeros(nrpt,nchan,nchan,nfrq,ntim); - sumtapcnt = [0;cumsum(data.cumtapcnt(:))]; - for k = 1:ntim - for m = 1:nfrq - for p = 1:nrpt - indx = (sumtapcnt(p)+1):sumtapcnt(p+1); - tmpdat = transpose(data.fourierspctrm(indx,:,m,k)); - crsspctrm(p,:,:,m,k) = (tmpdat*tmpdat')./data.cumtapcnt(p); - end - end - end - data.crsspctrm = crsspctrm; - data = rmfield(data, 'fourierspctrm'); - if nrpt>1, - if ntim>1, - data.dimord = 'rpt_chan_chan_freq_time'; - else - data.dimord = 'rpt_chan_chan_freq'; - end - else - if ntim>1, - data.dimord = 'chan_chan_freq_time'; - else - data.dimord = 'chan_chan_freq'; - end - end - if flag, siz = size(data.crsspctrm); data.crsspctrm = reshape(data.crsspctrm, siz(2:end)); end - -elseif strcmp(current, 'sparse') && strcmp(desired, 'full') - - dimtok = tokenize(data.dimord, '_'); - if ~isempty(strmatch('rpt', dimtok)), - nrpt = size(data.crsspctrm,1); - flag = 0; - else - nrpt = 1; - data.crsspctrm = reshape(data.crsspctrm, [1 size(data.crsspctrm)]); - flag = 1; - end - if ~isempty(strmatch('freq', dimtok)), nfrq=length(data.freq); else nfrq = 1; end - if ~isempty(strmatch('time', dimtok)), ntim=length(data.time); else ntim = 1; end - nchan = length(data.label); - cmbindx = zeros(nchan); - for k = 1:size(data.labelcmb,1) - ch1 = find(strcmp(data.label, data.labelcmb(k,1))); - ch2 = find(strcmp(data.label, data.labelcmb(k,2))); - if ~isempty(ch1) && ~isempty(ch2), cmbindx(ch1,ch2) = k; end - end - crsspctrm = zeros(nrpt,nchan,nchan,nfrq,ntim)+i.*zeros(nrpt,nchan,nchan,nfrq,ntim); - for k = 1:ntim - for m = 1:nfrq - for p = 1:nrpt - tmpdat = nan+zeros(nchan); - tmpdat(find(cmbindx)) = data.crsspctrm(p,cmbindx(find(cmbindx)),m,k); - tmpdat = ctranspose(tmpdat); - tmpdat(find(cmbindx)) = data.crsspctrm(p,cmbindx(find(cmbindx)),m,k); - crsspctrm(p,:,:,m,k) = tmpdat; - end - end - end - data.crsspctrm = crsspctrm; - data = rmfield(data, 'labelcmb'); - if nrpt>1, - if ntim>1, - data.dimord = 'rpt_chan_chan_freq_time'; - else - data.dimord = 'rpt_chan_chan_freq'; - end - else - if ntim>1, - data.dimord = 'chan_chan_freq_time'; - else - data.dimord = 'chan_chan_freq'; - end - end - if flag, siz = size(data.crsspctrm); data.crsspctrm = reshape(data.crsspctrm, siz(2:end)); end - -elseif strcmp(current, 'sparsewithpow') && strcmp(desired, 'full') - - % this is how is currently done in prepare_freq_matrices - data = checkdata(data, 'cmbrepresentation', 'sparse'); - data = checkdata(data, 'cmbrepresentation', 'full'); - -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% convert between datatypes -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function data = comp2raw(data) -% just remove the component topographies -data = rmfield(data, 'topo'); -data = rmfield(data, 'topolabel'); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% convert between datatypes -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function data = volume2source(data) -if isfield(data, 'dimord') - % it is a modern source description -else - % it is an old-fashioned source description - xgrid = 1:data.dim(1); - ygrid = 1:data.dim(2); - zgrid = 1:data.dim(3); - [x y z] = ndgrid(xgrid, ygrid, zgrid); - data.pos = warp_apply(data.transform, [x(:) y(:) z(:)]); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% convert between datatypes -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function data = source2volume(data) - -if isfield(data, 'dimord') - % it is a modern source description - - %this part depends on the assumption that the list of positions is describing a full 3D volume in - %an ordered way which allows for the extraction of a transformation matrix - %i.e. slice by slice - try, - if isfield(data, 'dim'), - data.dim = pos2dim3d(data.pos, data.dim); - else - data.dim = pos2dim3d(data); - end - catch - end -end - -if isfield(data, 'dim') && length(data.dim)>=3, - % it is an old-fashioned source description, or the source describes a regular 3D volume in pos - xgrid = 1:data.dim(1); - ygrid = 1:data.dim(2); - zgrid = 1:data.dim(3); - [x y z] = ndgrid(xgrid, ygrid, zgrid); - ind = [x(:) y(:) z(:)]; % these are the positions expressed in voxel indices along each of the three axes - pos = data.pos; % these are the positions expressed in head coordinates - % represent the positions in a manner that is compatible with the homogeneous matrix multiplication, - % i.e. pos = H * ind - ind = ind'; ind(4,:) = 1; - pos = pos'; pos(4,:) = 1; - % recompute the homogeneous transformation matrix - data.transform = pos / ind; -end - -% remove the unwanted fields -if isfield(data, 'pos'), data = rmfield(data, 'pos'); end -if isfield(data, 'xgrid'), data = rmfield(data, 'xgrid'); end -if isfield(data, 'ygrid'), data = rmfield(data, 'ygrid'); end -if isfield(data, 'zgrid'), data = rmfield(data, 'zgrid'); end - -% make inside a volume -data = fixinside(data, 'logical'); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% convert between datatypes -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function data = freq2raw(freq) - -if strcmp(freq.dimord, 'rpt_chan_freq_time') - dat = freq.powspctrm; -elseif strcmp(freq.dimord, 'rpttap_chan_freq_time') - warning('converting fourier representation into raw data format. this is experimental code'); - dat = freq.fourierspctrm; -else - error('this only works for dimord=''rpt_chan_freq_time'''); -end - -nrpt = size(dat,1); -nchan = size(dat,2); -nfreq = size(dat,3); -ntime = size(dat,4); -data = []; -% create the channel labels like "MLP11@12Hz"" -k = 0; -for i=1:nfreq - for j=1:nchan - k = k+1; - data.label{k} = sprintf('%s@%dHz', freq.label{j}, freq.freq(i)); - end -end -% reshape and copy the data as if it were timecourses only -for i=1:nrpt - data.time{i} = freq.time; - data.trial{i} = reshape(dat(i,:,:,:), nchan*nfreq, ntime); - if any(isnan(data.trial{i}(1,:))), - tmp = data.trial{i}(1,:); - begsmp = find(isfinite(tmp),1,'first'); - endsmp = find(isfinite(tmp),1,'last' ); - data.trial{i} = data.trial{i}(:, begsmp:endsmp); - data.time{i} = data.time{i}(begsmp:endsmp); - end -end -nsmp = cellfun('size',data.time,2); -seln = find(nsmp>1,1,'first'); -data.fsample = 1/(data.time{seln}(2)-data.time{seln}(1)); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% convert between datatypes -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [data] = raw2timelock(data) -ntrial = numel(data.trial); -nchan = numel(data.label); -if ntrial==1 - data.time = data.time{1}; - data.avg = data.trial{1}; - data = rmfield(data, 'trial'); - data.dimord = 'chan_time'; -else - % determine the location of the trials relative to the resulting combined time axis - begtime = cellfun(@min, data.time); - endtime = cellfun(@max, data.time); - begsmp = round((begtime - min(begtime)) * data.fsample) + 1; - endsmp = round((endtime - min(begtime)) * data.fsample) + 1; - - % create a combined time axis and concatenate all trials - tmptime = min(begtime):(1/data.fsample):max(endtime); - tmptrial = zeros(ntrial, nchan, length(tmptime)) + nan; - for i=1:ntrial - tmptrial(i,:,begsmp(i):endsmp(i)) = data.trial{i}; - end - - % update the trial definition - trl = findcfg(data.cfg, 'trl'); - if ~isempty(trl) - begpad = begsmp - min(begsmp); % number of nan-samples added to the begin - endpad = max(endsmp) - endsmp; % number of nan-samples added to the end - data.cfg.trlold = trl; - trl(:,1) = trl(:,1) - begpad(:); - trl(:,2) = trl(:,2) + endpad(:); - trl(:,3) = trl(:,3) - begpad(:); - data.cfg.trl = trl; - end - - % construct the output timelocked data - % data.avg = reshape(nanmean(tmptrial, 1), nchan, length(tmptime)); - % data.var = reshape(nanvar (tmptrial, [], 1), nchan, length(tmptime)) - % data.dof = reshape(sum(~isnan(tmptrial), 1), nchan, length(tmptime)); - data.trial = tmptrial; - data.time = tmptime; - data.dimord = 'rpt_chan_time'; -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% convert between datatypes -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [data] = timelock2raw(data) -switch data.dimord - case 'chan_time' - data.trial{1} = data.avg; - data.time = {data.time}; - data = rmfield(data, 'avg'); - case 'rpt_chan_time' - tmptrial = {}; - tmptime = {}; - ntrial = size(data.trial,1); - nchan = size(data.trial,2); - ntime = size(data.trial,3); - for i=1:ntrial - tmptrial{i} = reshape(data.trial(i,:,:), [nchan, ntime]); - tmptime{i} = data.time; - end - data = rmfield(data, 'trial'); - data.trial = tmptrial; - data.time = tmptime; - case 'subj_chan_time' - tmptrial = {}; - tmptime = {}; - ntrial = size(data.individual,1); - nchan = size(data.individual,2); - ntime = size(data.individual,3); - for i=1:ntrial - tmptrial{i} = reshape(data.individual(i,:,:), [nchan, ntime]); - tmptime{i} = data.time; - end - data = rmfield(data, 'individual'); - data.trial = tmptrial; - data.time = tmptime; - otherwise - error('unsupported dimord'); -end -% remove the unwanted fields -if isfield(data, 'avg'), data = rmfield(data, 'avg'); end -if isfield(data, 'var'), data = rmfield(data, 'var'); end -if isfield(data, 'cov'), data = rmfield(data, 'cov'); end -if isfield(data, 'dimord'), data = rmfield(data, 'dimord'); end -if isfield(data, 'numsamples'), data = rmfield(data, 'numsamples'); end -if isfield(data, 'dof'), data = rmfield(data, 'dof'); end diff --git a/external/fieldtrip/private/closedf.m b/external/fieldtrip/private/closedf.m new file mode 100644 index 0000000..c7a8d53 --- /dev/null +++ b/external/fieldtrip/private/closedf.m @@ -0,0 +1,31 @@ +function [EDF]=closedf(EDF) + +% EDF=closedf(EDF) +% Opens an EDF File (European Data Format for Biosignals) into MATLAB +% About EDF +% +% EDF struct of EDF-Header of a EDF-File + +% Version 2.0 +% 15.12.1997 +% Copyright (c) 1997 by Alois Schloegl +% a.schloegl@ieee.org +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +% + +EDF.FILE.OPEN=0; +fclose(EDF.FILE.FID); +return; diff --git a/external/fieldtrip/private/clusterplot.m b/external/fieldtrip/private/clusterplot.m deleted file mode 100644 index 6d3034f..0000000 --- a/external/fieldtrip/private/clusterplot.m +++ /dev/null @@ -1,301 +0,0 @@ -function clusterplot(cfg, stat) - -% CLUSTERPLOT plots a series of topoplots with found clusters highlighted. -% stat is 2D or 1D data from TIMELOCKSTATISTICS or FREQSTATISTICS with 'cluster' -% as cfg.correctmc. 2D: stat from timelockstatistics not averaged over -% time, or stat from freqstatistics averaged over frequency not averaged over -% time. 1D: averaged over time as well. -% -% use as: clusterplot(cfg,stat) -% -% configuration options -% cfg.alpha = number, highest cluster p-value to be plotted -% max 0.3 (default = 0.05) -% cfg.hlmarkerseries = 1x5 vector, highlight marker symbol series -% default ['*','x','+','o','.'] for p < [0.01 0.05 0.1 0.2 0.3] -% cfg.hlmarkersizeseries = 1x5 vector, highlight marker size series -% default [6 6 6 6 6] for p < [0.01 0.05 0.1 0.2 0.3] -% cfg.hllinewidthseries = 1x5 vector, highlight marker linewidth series -% default [1 1 1 1 1] for p < [0.01 0.05 0.1 0.2 0.3] -% cfg.hlcolorpos = color of highlight marker for positive clusters -% default = [0 0 0] -% cfg.hlcolorneg = color of highlight marker for negative clusters -% default = [0 0 0] -% cfg.saveaspng = string, path where figure has to be saved to (default = 'no') -% When multiple figures figure gets extension with fignum -% -% It is also possible to specify other cfg options that apply to TOPOPLOTER -% or TOPOPLOT. You CANNOT specify cfg.xlim, any of the TOPOPLOT highlight -% options, cfg.comment and cfg.commentpos. -% -% See also: -% topoplot, singleplotER - -% Copyright (C) 2007, Ingrid Nieuwenhuis, F.C. Donders Centre -% -% $Log: clusterplot.m,v $ -% Revision 1.8 2009/05/22 14:54:58 ingnie -% added check of data, should be averged over frequencies -% -% Revision 1.7 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.6 2008/09/22 15:18:53 roboos -% only prepare the layout once -% -% Revision 1.5 2008/06/12 12:22:36 ingnie -% Now also works for 1D data (= avaraged over time), added some comma's in default setting for readability -% -% Revision 1.4 2007/11/07 16:28:08 ingnie -% added option saveaspng -% -% Revision 1.3 2007/11/07 12:52:46 ingnie -% add cvs log -% - -fieldtripdefs - -% check if given data is appropriate -if isfield(stat,'freq') && length(stat.freq) > 1 - error('stat contains multiple frequencies which is not allowed because it should be averaged over frequencies') -end - -% set the defaults -if ~isfield(cfg,'alpha'), cfg.alpha = 0.05; end; -if ~isfield(cfg,'hlmarkerseries'), cfg.hlmarkerseries = ['*','x','+','o','.']; end; -if ~isfield(cfg,'hlmarkersizeseries'), cfg.hlmarkersizeseries = [6 6 6 6 6]; end; -if ~isfield(cfg,'hllinewidthseries'), cfg.hllinewidthseries = [1 1 1 1 1]; end; -if ~isfield(cfg,'hlcolorpos'), cfg.hlcolorpos = [0 0 0]; end; -if ~isfield(cfg,'hlcolorneg'), cfg.hlcolorneg = [0 0 0]; end; -if ~isfield(cfg,'zparam'), cfg.zparam = 'stat'; end; -if ~isfield(cfg,'saveaspng'), cfg.saveaspng = 'no'; end; - -% prepare the layout, this only has to be done once -cfg.layout = prepare_layout(cfg, stat); - -% detect 2D or 1D -is2D = isfield(stat,'time'); - -% add .time field to 1D data, topoplotER wants it -if ~is2D - stat.time = 0; %doesn't matter what it is, so just choose 0 -end; - -% find significant clusters -sigpos = []; -signeg = []; -haspos = isfield(stat,'posclusters'); -hasneg = isfield(stat,'negclusters'); - -if haspos == 0 && hasneg == 0 - fprintf('%s\n','no significant clusters in data; nothing to plot') -else - for iPos = 1:length(stat.posclusters) - sigpos(iPos) = stat.posclusters(iPos).prob < cfg.alpha; - end - for iNeg = 1:length(stat.negclusters) - signeg(iNeg) = stat.negclusters(iNeg).prob < cfg.alpha; - end - sigpos = find(sigpos == 1); - signeg = find(signeg == 1); - Nsigpos = length(sigpos); - Nsigneg = length(signeg); - Nsigall = Nsigpos + Nsigneg; - - % make clusterslabel matrix per significant cluster - posCLM = squeeze(stat.posclusterslabelmat); - sigposCLM = zeros(size(posCLM)); - probpos = []; - for iPos = 1:length(sigpos) - sigposCLM(:,:,iPos) = (posCLM == sigpos(iPos)); - probpos(iPos) = stat.posclusters(iPos).prob; - hlsignpos(iPos) = prob2hlsign(probpos(iPos), cfg.hlmarkerseries); - end - - negCLM = squeeze(stat.negclusterslabelmat); - signegCLM = zeros(size(negCLM)); - probneg = []; - for iNeg = 1:length(signeg) - signegCLM(:,:,iNeg) = (negCLM == signeg(iNeg)); - probneg(iNeg) = stat.negclusters(iNeg).prob; - hlsignneg(iNeg) = prob2hlsign(probneg(iNeg), cfg.hlmarkerseries); - end - - fprintf('%s%i%s%g%s\n','There are ',Nsigall,' clusters smaller than alpha (',cfg.alpha,')') - - if is2D - % define time window per cluster - for iPos = 1:length(sigpos) - possum_perclus = sum(sigposCLM(:,:,iPos),1); %sum over Chans for each timepoint - ind_min = min(find(possum_perclus~=0)); - ind_max = max(find(possum_perclus~=0)); - time_perclus = [stat.time(ind_min) stat.time(ind_max)]; - fprintf('%s%s%s%s%s%s%s%s%s%s%s\n','Positive cluster: ',num2str(sigpos(iPos)),', pvalue: ',num2str(probpos(iPos)),' (',hlsignpos(iPos),')',', t = ',num2str(time_perclus(1)),' to ',num2str(time_perclus(2))) - end - for iNeg = 1:length(signeg) - negsum_perclus = sum(signegCLM(:,:,iNeg),1); - ind_min = min(find(negsum_perclus~=0)); - ind_max = max(find(negsum_perclus~=0)); - time_perclus = [stat.time(ind_min) stat.time(ind_max)]; - fprintf('%s%s%s%s%s%s%s%s%s%s%s\n','Negative cluster: ',num2str(signeg(iNeg)),', pvalue: ',num2str(probneg(iNeg)),' (',hlsignneg(iNeg),')',', t = ',num2str(time_perclus(1)),' to ',num2str(time_perclus(2))) - end - - % define timewindow containing all significant clusters - possum = sum(sigposCLM,3); %sum over Chans for timevector - possum = sum(possum,1); - negsum = sum(signegCLM,3); - negsum = sum(negsum,1); - allsum = possum + negsum; - - ind_timewin_min = min(find(allsum~=0)); - ind_timewin_max = max(find(allsum~=0)); - - timestep = stat.time(2) - stat.time(1); - timewin = [stat.time(ind_timewin_min): timestep :stat.time(ind_timewin_max)]; - else - for iPos = 1:length(sigpos) - fprintf('%s%s%s%s%s%s%s\n','Positive cluster: ',num2str(sigpos(iPos)),', pvalue: ',num2str(probpos(iPos)),' (',hlsignpos(iPos),')') - end - for iNeg = 1:length(signeg) - fprintf('%s%s%s%s%s%s%s\n','Negative cluster: ',num2str(signeg(iNeg)),', pvalue: ',num2str(probneg(iNeg)),' (',hlsignneg(iNeg),')') - end - end - - % setup highlight options for all clusters and make comment for 1D data - compos = []; - comneg = []; - for iPos = 1:length(sigpos) - if stat.posclusters(sigpos(iPos)).prob < 0.01 - cfg.hlmarker{iPos} = cfg.hlmarkerseries(1); - cfg.hlmarkersize{iPos} = cfg.hlmarkersizeseries(1); - cfg.hllinewidth{iPos} = cfg.hllinewidthseries(1); - elseif stat.posclusters(sigpos(iPos)).prob < 0.05 - cfg.hlmarker{iPos} = cfg.hlmarkerseries(2); - cfg.hlmarkersize{iPos} = cfg.hlmarkersizeseries(2); - cfg.hllinewidth{iPos} = cfg.hllinewidthseries(2); - elseif stat.posclusters(sigpos(iPos)).prob < 0.1 - cfg.hlmarker{iPos} = cfg.hlmarkerseries(3); - cfg.hlmarkersize{iPos} = cfg.hlmarkersizeseries(3); - cfg.hllinewidth{iPos} = cfg.hllinewidthseries(3); - elseif stat.posclusters(sigpos(iPos)).prob < 0.2 - cfg.hlmarker{iPos} = cfg.hlmarkerseries(4); - cfg.hlmarkersize{iPos} = cfg.hlmarkersizeseries(4); - cfg.hllinewidth{iPos} = cfg.hllinewidthseries(4); - elseif stat.posclusters(sigpos(iPos)).prob < 0.3 - cfg.hlmarker{iPos} = cfg.hlmarkerseries(5); - cfg.hlmarkersize{iPos} = cfg.hlmarkersizeseries(5); - cfg.hllinewidth{iPos} = cfg.hllinewidthseries(5); - end - cfg.hlcolor{iPos} = cfg.hlcolorpos; - compos = strcat(compos,cfg.hlmarker{iPos}, 'p=',num2str(probpos(iPos)),' '); % make comment, only used for 1D data - end - - for iNeg = 1:length(signeg) - if stat.negclusters(signeg(iNeg)).prob < 0.01 - cfg.hlmarker{length(sigpos)+iNeg} = cfg.hlmarkerseries(1); - cfg.hlmarkersize{length(sigpos)+iNeg} = cfg.hlmarkersizeseries(1); - cfg.hllinewidth{length(sigpos)+iNeg} = cfg.hllinewidthseries(1); - elseif stat.negclusters(signeg(iNeg)).prob < 0.05 - cfg.hlmarker{length(sigpos)+iNeg} = cfg.hlmarkerseries(2); - cfg.hlmarkersize{length(sigpos)+iNeg} = cfg.hlmarkersizeseries(2); - cfg.hllinewidth{length(sigpos)+iNeg} = cfg.hllinewidthseries(2); - elseif stat.negclusters(signeg(iNeg)).prob < 0.1 - cfg.hlmarker{length(sigpos)+iNeg} = cfg.hlmarkerseries(3); - cfg.hlmarkersize{length(sigpos)+iNeg} = cfg.hlmarkersizeseries(3); - cfg.hllinewidth{length(sigpos)+iNeg} = cfg.hllinewidthseries(3); - elseif stat.negclusters(signeg(iNeg)).prob < 0.2 - cfg.hlmarker{length(sigpos)+iNeg} = cfg.hlmarkerseries(4); - cfg.hlmarkersize{length(sigpos)+iNeg} = cfg.hlmarkersizeseries(4); - cfg.hllinewidth{length(sigpos)+iNeg} = cfg.hllinewidthseries(4); - elseif stat.negclusters(signeg(iNeg)).prob < 0.3 - cfg.hlmarker{length(sigpos)+iNeg} = cfg.hlmarkerseries(5); - cfg.hlmarkersize{length(sigpos)+iNeg} = cfg.hlmarkersizeseries(5); - cfg.hllinewidth{length(sigpos)+iNeg} = cfg.hllinewidthseries(5); - end - cfg.hlcolor{length(sigpos)+iNeg} = cfg.hlcolorneg; - comneg = strcat(comneg,cfg.hlmarker{length(sigpos)+iNeg}, 'p=',num2str(probneg(iNeg)),' '); % make comment, only used for 1D data - end - - if is2D - Npl = length(timewin); - else - Npl = 1; - end - Nfig = ceil(Npl/15); - - % put channel indexes in list - if is2D - for iPl = 1:Npl - for iPos = 1:length(sigpos) - list{iPl}{iPos} = find(sigposCLM(:,ind_timewin_min+iPl-1,iPos) == 1); - end - for iNeg = 1:length(signeg) - list{iPl}{length(sigpos)+iNeg} = find(signegCLM(:,ind_timewin_min+iPl-1,iNeg) == 1); - end - end - else - for iPl = 1:Npl - for iPos = 1:length(sigpos) - list{iPl}{iPos} = find(sigposCLM(:,iPos) == 1); - end - for iNeg = 1:length(signeg) - list{iPl}{length(sigpos)+iNeg} = find(signegCLM(:,iNeg) == 1); - end - end - end - - % make plots - for iPl = 1:Nfig - figure; - if is2D - if iPl < Nfig - for iT = 1:15 - PlN = (iPl-1)*15 + iT; %plotnumber - cfg.xlim = [stat.time(ind_timewin_min+PlN-1) stat.time(ind_timewin_min+PlN-1)]; - cfg.highlight = list{PlN}; - cfg.comment = strcat('time: ',num2str(stat.time(ind_timewin_min+PlN-1)), ' s'); - cfg.commentpos = 'title'; - subplot(3,5,iT); - topoplotER(cfg, stat); - end - elseif iPl == Nfig - for iT = 1:Npl-(15*(Nfig-1)) - PlN = (iPl-1)*15 + iT; %plotnumber - cfg.xlim = [stat.time(ind_timewin_min+PlN-1) stat.time(ind_timewin_min+PlN-1)]; - cfg.highlight = list{PlN}; - cfg.comment = strcat('time: ',num2str(stat.time(ind_timewin_min+PlN-1)), ' s'); - cfg.commentpos = 'title'; - subplot(3,5,iT); - topoplotER(cfg, stat); - end - end - else - cfg.highlight = list{1}; - cfg.xparam = 'time'; - cfg.yparam = ''; - cfg.comment = strcat(compos,comneg); - cfg.commentpos = 'title'; - topoplotER(cfg, stat); - end - % save figure - if isequal(cfg.saveaspng,'no'); - else - filename = strcat(cfg.saveaspng, '_fig', num2str(iPl)); - print(gcf,'-dpng',filename); - end - end -end - -%% subfunctions %% -function sign = prob2hlsign(prob, hlsign) -if prob < 0.01 - sign = hlsign(1); -elseif prob < 0.05 - sign = hlsign(2); -elseif prob < 0.1 - sign = hlsign(3); -elseif prob < 0.2 - sign = hlsign(4); -elseif prob < 0.3 - sign = hlsign(5); -end diff --git a/external/fieldtrip/private/clusterrandanalysis.m b/external/fieldtrip/private/clusterrandanalysis.m deleted file mode 100644 index c496189..0000000 --- a/external/fieldtrip/private/clusterrandanalysis.m +++ /dev/null @@ -1,908 +0,0 @@ -function [clusrand] = clusterrandanalysis(cfg,varargin); - -% CLUSTERRANDANALYSIS -% -% Use as -% [clusrand] = clusterrandanalysis(cfg, data) -% where the configuration can contain -% -% 1. Options for data selection and averaging over selected dimensions -% -------------------------------------------------------------------- -% -% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), -% see CHANNELSELECTION for details -% or, -% cfg.channelcmb = Mx2 cell-array with selection of channel pairs (default = {'all' 'all'}), -% see CHANNELCOMBINATION for details -% cfg.latency = [begin end] in seconds or 'all' (default = 'all') -% cfg.frequency = [begin end], can be 'all' (default = 'all') -% cfg.avgoverchan = 'yes' or 'no' (default = 'no') -% cfg.avgovertime = 'yes' or 'no' (default = 'no') -% cfg.avgoverfreq = 'yes' or 'no' (default = 'no') -% -% 2. Statistics options -% --------------------- -% -% cfg.statistic = 'indepsamplesT' (independent samples T-statistic) -% | 'indepsamplesregrT' (independent samples regression coefficient T-statistic) -% | 'indepsamplesZcoh' (independent samples Z-statistic for coherence) -% | 'indepsamplesTsqcrs' (independent samples T-square-statistic for the cross-spectrum) -% | 'depsamplesT' (dependent samples T-statistic) -% | 'actvsblT' (activation versus baseline T-statistic) -% | 'depsamplesregrT' (dependent samples regression coefficient T-statistic) -% | 'indepsamplesF' (independent samples F-statistic) -% | 'depsamplesF' (dependent samples F-statistic) -% -% cfg.alpha = alpha level of the randomization test -% cfg.clusterteststat = 'maxsum' (default) or 'orderedsums' -% cfg.smallestcluster = smallest cluster size that is large enough to be considered (only -% relevant when clusterteststat='orderedsums') -% -% For every statistic, we now list (a) the constraints with respect to the -% data that should be passed as an argument to this function (in varargin) and -% (b) a number of fields that are relevant for a particular choice of statistic. -% -% For the independent samples T-statistic: -% Two data sets must be passed. The first data set belongs to condition 1 -% and the second one belongs to condition 2. -% cfg.onetwo = 'onesided_1<2' (H_0:condition_10' (H_0: regr. coefficient B>0), or -% 'twosided' (H_0:regr. coefficient B=0, the default). -% -% For the independent samples Z-statistic for coherence: -% When this statistic is chosen, the spatial dimension of the data matrix must -% contain (a) the cross-spectrum for a number of channel combinations, and -% (b) the auto-spectrum (power) for the channels that are involved in the -% channel combinations. With this test statistic, one examines whether the -% two conditions differ with respect to coherence. -% cfg.onetwo = 'onesided_1<2' (H_0:condition_10' (H_0: regr. coefficient B>0), or -% 'twosided' (H_0:regr. coefficient B=0, the default). -% -% For the independent samples F-statistic: -% Two or more data sets must be passed. -% -% For the dependent samples F-statistic: -% Two or more data sets must be passed. The order of the conditions -% corresponds to the order of the data sets. The data sets must have -% the same number of replications (subjects or trials) and the order of -% these replications must be the same in both. -% cfg.contrastcoefs = matrix of contrast coefficients determining the -% effect being tested. The number of columns of this -% matrix must be equal to the number of conditions (ncond). -% The default is a matrix that specifies the -% main effect of the independent variable. This matrix -% has size [(ncond-1),ncond]. -% cfg.allowedperms = matrix of permutations of conditions that all have the -% same probability (given the data) under the null -% hypothesis. The default is all ncond! possible permutations. -% -% 3. Clustering options -% --------------------- -% -% cfg.makeclusters = 'yes' (default) | 'no' -% cfg.alphathresh = alpha level of the (channel,timepoint,frequency)-specific -% test statistic that will be used for thresholding -% cfg.minnbchan = minimum number of neighbouring channels in which a -% particular time-frequency-specific t-test has to be significant in order -% for it to be included in the clustering algorithm (default=0). -% cfg.chancmbgeom = 'refchan' (one reference channel; the neighborhood geometry of the channel -% combinations is determined by the non-reference channels) or 'free' -% (the neighborhood geometry of the channel combinations is determined by the -% channel combinations) -% -% 4. Neighborhood geometry -% ------------------------ -% -% You can specify the neighbours of each channel (1) by providing them as a structured -% cell array, (2) by looking at the sensor positions that are present in -% the data, or (3) by loading the neighborhood geometry from a file -% (cfg.geomfile). The latter option can also be used to load the geometry -% of the channel combinations. -% This is done either with -% cfg.neighbourdist = distance, default is 4 cm -% or with the field -% cfg.neighbours = definition of neighbours for each channel, see NEIGHBCHANSELECTION -% which should be structured like this: -% cfg.neighbours{1}.label = 'Fz'; -% cfg.neighbours{1}.neighblabel = {'Cz', 'F3', 'F3A', 'FzA', 'F4A', 'F4'}; -% cfg.neighbours{2}.label = 'Cz'; -% cfg.neighbours{2}.neighblabel = {'Fz', 'F4', 'RT', 'RTP', 'P4', 'Pz', 'P3', 'LTP', 'LT', 'F3'}; -% cfg.neighbours{3}.label = 'Pz'; -% cfg.neighbours{3}.neighblabel = {'Cz', 'P4', 'P4P', 'Oz', 'P3P', 'P3'}; -% etc. -% (Note that a channel is not considered to be a neighbour of itself.) -% or which can be the name of a file that contains the logical matrix in which the -% channel (combination) geometry is specified, together with the -% channel (combination) labels. -% or with the field -% cfg.geomfile = 'filename'; -% -% Electrode or gradiometer positions are obtained from the first dataset, or can be specified -% using either one of -% cfg.gradfile = string, file containing the gradiometer definition -% cfg.elecfile = string, file containing the electrode definition -% or alternatively -% cfg.grad = structure with gradiometer definition -% cfg.elec = structure with electrode definition -% -% 5. Miscellaneous options -% ------------------------ -% -% cfg.nranddraws = number of draws from the randomization distribution -% cfg.randomseed = 'yes' (default), 'no' or seed-number -% cfg.savegeom = 'yes', 'no' (default), save the neighborhood -% geometry (of channels or channel combinations) in the file cfg.geomfile. -% cfg.mirrordata = 'yes', 'no' (default), to be used when the data are -% elements of the cross-spectrum. If the results of -% the statistical test depends on the order of the -% channel pairs (e.g., if data contain the imaginary -% part of the cross-spectrum and the the test statistic is -% one-dimensional) then cfg.mirrordata should be -% 'yes'. Note that only the lower or upper diagonal of the -% cross-spectral matrix must be passed as an argument (in data). - -% This function depends on PREPARE_TIMEFREQ_DATA which has the following options: -% cfg.avgoverchan, documented -% cfg.avgoverfreq, documented -% cfg.avgovertime, documented -% cfg.channel, documented -% cfg.channelcmb, documented -% cfg.datarepresentation (set in CLUSTERRANDANALYSIS; if between = 'concatenated' if within = 'cell-array') -% cfg.frequency, documented -% cfg.latency, documented -% cfg.precision -% cfg.previous -% cfg.version - -% Copyright (C) 2005-2006, Eric Maris, NICI, University Nijmegen -% -% $Log: clusterrandanalysis.m,v $ -% Revision 1.26 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.25 2008/03/05 10:46:35 roboos -% moved electrode reading functionality from read_fcdc_elec to read_sens, switched to the use of the new function -% -% Revision 1.24 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.23 2007/03/27 11:05:18 ingnie -% changed call to fixdimord in call to checkinput -% -% Revision 1.22 2006/10/19 15:32:55 roboos -% updated documentation -% -% Revision 1.21 2006/10/04 07:10:07 roboos -% updated documentation -% -% Revision 1.20 2006/06/20 16:29:11 ingnie -% updated documentation added default cfg.channelcmb -% -% Revision 1.19 2006/06/13 14:51:03 ingnie -% updated documentation to increase consistency in help of cfg options, added -% defaults cfg.channel ='all', cfg.latency = 'all' -% -% Revision 1.18 2006/04/10 16:33:46 ingnie -% updated documentation -% -% Revision 1.17 2006/04/06 13:05:00 erimar -% Added help wrt channel combinations. -% -% Revision 1.16 2006/02/28 11:56:23 erimar -% Added functionality for channel combination data: test statistics indepsamplesZcoh (for coherence differences) and -% indepsamplesTsqcrs (for cross-spectrum differences), routines for calculating the neighborhood geometry for channel -% combinations, and the option to save the neighborhood geometry on file (cfg.geomfile, cfg.savegeom). -% - -% Revision 1.15 2006/02/23 10:28:16 roboos -% changed dimord strings for consistency, changed toi and foi into time and freq, added fixdimord where neccessary -% -% Revision 1.14 2006/02/01 12:26:00 roboos -% made all uses of dimord consistent with the common definition of data dimensions, see the fixdimord() function -% -% Revision 1.13 2005/12/06 13:18:08 erimar -% (1) Removed all functionality with respect to channel combinations -% (because it was not sufficiently tested for data sets of realistic -% sizes). (2) Improved and extended the handling of external predictor -% variables (for the independent and the dependent samples regression -% coefficient T-statistics). -% -% Revision 1.12 2005/11/28 11:15:09 erimar -% Improved help -% -% Revision 1.11 2005/08/10 15:35:41 roboos -% fixed cfg.elecfile (accidentally called gradfile), thanks to chrfor -% -% Revision 1.10 2005/08/05 12:19:03 erimar -% Correct an error in the handling of the .ext-field for -% cfg.indepsamplesregrT detected by Vladimir Litvak. -% -% Revision 1.9 2005/08/05 07:48:37 roboos -% added support for cfg.elec/grad/elecfile/gradfile -% cleaned up the help -% removed the "defaults set in xxx" help comments, since those subfunctions are not accessible for the end-user -% -% Revision 1.8 2005/04/22 07:44:41 roboos -% added/corrected copyrights, added a Log tag for CVS, converted to unix ascii -% - -fieldtripdefs - -warning off; -pack; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% set the defaults -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -if ~isfield(cfg, 'neighbours'), cfg.neighbours = []; end; -if ~isfield(cfg, 'neighbourdist'), cfg.neighbourdist = 4; end; -if ~isfield(cfg, 'geomfile'), cfg.geomfile = ''; end; -if ~isfield(cfg, 'chancmbgeom'), cfg.chancmbgeom = 'refchan'; end; -if ~isfield(cfg, 'savegeom'), cfg.savegeom = 'no'; end; -if ~isfield(cfg, 'randomseed'), cfg.randomseed = 'yes'; end; -if ~isfield(cfg, 'mirrordata'), cfg.mirrordata = 'no'; end; -if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end; -if ~isfield(cfg, 'channelcmb'), cfg.channelcmb = {'all' 'all'}; end; -if ~isfield(cfg, 'latency'), cfg.latency = 'all'; end; - -% for backward compatibility with old data structures -for i=1:length(varargin) - varargin{i} = checkdata(varargin{i}); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Perform some checks. -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% determine whether a beween or a within-replications design is requested. -if any(strcmp(cfg.statistic,{'indepsamplesT','indepsamplesregrT','indepsamplesZcoh','indepsamplesTsqcrs','indepsamplesF'})) - between = 1; -end; -if any(strcmp(cfg.statistic,{'depsamplesregrT','depsamplesT','actvsblT','depsamplesF'})) - between = 0; -end; -if ~(exist('between')==1) - error('Unknown test statistic.'); -end; - -onedimtest = any(strcmp(cfg.statistic,{'indepsamplesT','indepsamplesregrT','indepsamplesZcoh','depsamplesregrT','depsamplesT','actvsblT'})); - -Nvarargin = length(varargin); - -if any(strcmp(cfg.statistic,{'indepsamplesT','indepsamplesZcoh','indepsamplesTsqcrs','depsamplesT','actvsblT'})) && (Nvarargin~=2) - error('Number of data sets is not equal to 2, as is required by the test statistic.'); -end; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% If required by cfg, add the cross- and the autospectrum to cfg.channelcmb. -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -if any(strcmp(cfg.statistic,{'indepsamplesZcoh'})) - if ~isfield(cfg,'channelcmb') - if isfield(varargin{1},'labelcmb') - cfg.channelcmb=varargin{1}.labelcmb; - else - error('The first dataset does not contain cross-spectra, as is required with this test statistic.'); - end; - else - if isfield(varargin{1},'labelcmb') - cfg.channelcmb=channelcombination(cfg.channelcmb,varargin{1}.label); - else - error('The first dataset does not contain cross-spectra, as is required with this test statistic.'); - end; - end; - if strcmp(cfg.statistic,'indepsamplesZcoh') - uniqchanlabels = unique(cfg.channelcmb(:)); - nuniqchanlabels=length(uniqchanlabels); - autospctrselvec=strcmp(cfg.channelcmb(:,1),cfg.channelcmb(:,2)); - crsspctrselvec=~autospctrselvec; - autospctrchannelcmb=cat(2,uniqchanlabels,uniqchanlabels); - cfg.channelcmb=cat(1,autospctrchannelcmb, cfg.channelcmb(crsspctrselvec,:)); - end; -end; - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Preprocessing, specific for the activation-versus-baseline statistic. -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -if strcmp(cfg.statistic,'actvsblT') - poststim=find(varargin{1}.time>=0); - if length(poststim)~=length(varargin{1}.time) - error('Not all time points in the first data set are in the activation (post-stimulus) period.'); - end; - prestim=find(varargin{2}.time<=0); - if length(prestim)~=length(varargin{2}.time) - error('Not all time points in the second data set are in the baseline (pre-stimulus) period.'); - end; - if length(prestim)~=length(poststim) - error('The time axes of the first (activation) and the second (baseline) data set are of different length.'); - end; - varargin{2}.time=varargin{2}.time + min(varargin{1}.time) - min(varargin{2}.time); -end; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Data selection and averaging over selected dimensions -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -if between - cfg.datarepresentation = 'concatenated'; -else % a within-replication design - cfg.datarepresentation = 'cell-array'; -end; - -fprintf('Selecting and formatting the data.\n'); -[cfg,data]=prepare_timefreq_data(cfg, varargin{1:Nvarargin}); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Reshape the data in a format suitable for clusterrandstatistics. -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -if between - [nrepl,lengthspatialdim,nfreq,ntime]=size(data.biol); - data.biol=reshape(data.biol,[nrepl,1,lengthspatialdim,nfreq,ntime]); -else % within-replication conditions - data.biolcell=data.biol; - nwcond=length(data.biolcell); - [firstnrepl,lengthspatialdim,nfreq,ntime]=size(data.biolcell{1}); - data.biol=reshape(data.biolcell{1},[firstnrepl,1,lengthspatialdim,nfreq,ntime]); - data.biolcell{1}=[]; - for condindx=2:nwcond - nrepl=size(data.biolcell{condindx},1); - if nrepl~=firstnrepl - error('The number of replications in the different conditions are unequal. This is not allowed with a test statistic for a within-replications design.'); - end; - data.biol=cat(2,data.biol,reshape(data.biolcell{condindx},[nrepl,1,lengthspatialdim,nfreq,ntime])); - data.biolcell{condindx}=[]; - end; -end; -% add the dimension wcond to the dimord -s = strfind(data.dimord, 'chan'); -data.dimord = [data.dimord(1:(s-1)) 'wcond_chan' data.dimord((s+4):end)]; - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Adding the external variable data.ext -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -if between || strcmp(cfg.statistic,'depsamplesregrT') - if Nvarargin>1 - data.ext=zeros(Nvarargin,1); - else % Nvarargin=1 - if strcmp(cfg.statistic,'indepsamplesregrT') - data.ext=zeros(nrepl,1); - elseif strcmp(cfg.statistic,'depsamplesregrT') - data.ext=zeros(nwcond,1); - end; - end; - if strcmp(cfg.statistic,'indepsamplesregrT') | strcmp(cfg.statistic,'depsamplesregrT') - % constructing the predictor variable for the dependent and the - % independent samples regression T-statistic - if isfield(cfg,'ext') - if size(cfg.ext,1)==1 - data.ext=cfg.ext'; % take the transpose of the row vector - else - data.ext=cfg.ext; - end; - else - if Nvarargin>1 - for argindx=1:Nvarargin - if isfield(varargin{argindx},'ext') - data.ext(argindx)=varargin{argindx}.ext; - else - error('Neither the configuration nor the data contain the field "ext", as is required by the test statistic.'); - end; - end; - else - if isfield(varargin{1},'ext') - if size(varargin{1}.ext,1)==1 - data.ext=varargin{1}.ext'; - else - data.ext=varargin{1}.ext; - end; - else - error('Neither the configuration nor the data contain the field "ext", as is required by the test statistic.'); - end; - end; - end; - else % if the statistic is not the independent nor the dependent samples regression T-statistic - data.ext=data.design(:,3); - end; - if strcmp(cfg.statistic,'indepsamplesregrT') && (length(data.ext)~=size(data.biol,1)) - error('The number of entries in the predictor variable is not equal to the number of replications in the data.'); - end; - if strcmp(cfg.statistic,'depsamplesregrT') && (length(data.ext)~=size(data.biol,2)) - error('The number of entries in the predictor variable is not equal to the number of replications in the data.'); - end; -end; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Preprocessing, specific for channel combination data. -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -if isfield(data,'labelcmb') - data.label=unique(data.labelcmb(:)); - if isfield(cfg,'mirrordata') && strcmp(cfg.mirrordata,'yes') - reverseddatalabelcmb=cell(size(data.labelcmb,1),2); - reverseddatalabelcmb=data.labelcmb(:,[2 1]); - data.labelcmb=[data.labelcmb;reverseddatalabelcmb]; - end; -end; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Get the neighbourhood geometry. -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -fprintf('Calculating the neighbourhood structure of the channels.\n'); -[cfg,data] = getneighbgeometry(cfg,data,varargin{1}); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Run clusterrandstatistics. -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -[clusrand] = clusterrandstatistics(cfg, data); - -warning on; - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% BEGIN SUBFUNCTION GETNEIGHBGEOMETRY -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [cfg,data] = getneighbgeometry(cfg,data,firstdataset); -% get the neighbourhood geometry - -singlechans = ~isfield(data,'labelcmb'); - -if ~strcmp(cfg.savegeom,'yes') && ~isempty(cfg.geomfile) && exist(cfg.geomfile,'file') - load(cfg.geomfile); % load the structure geom into memory -end; - -if ~exist('geom') && isempty(cfg.neighbours) - % Add the grad and elec fields. - swapmemfile; % initialization - firstdataset = swapmemfile(firstdataset); - if isfield(cfg, 'grad') - fprintf('Obtaining the gradiometer configuration from the configuration.\n'); - data.grad = cfg.grad; - elseif isfield(cfg, 'elec') - fprintf('Obtaining the electrode configuration from the configuration.\n'); - data.elec = cfg.elec; - elseif isfield(cfg, 'gradfile') - fprintf('Obtaining the gradiometer configuration from a file.\n'); - data.grad = read_sens(cfg.gradfile); - elseif isfield(cfg, 'elecfile') - fprintf('Obtaining the electrode configuration from a file.\n'); - data.elec = read_sens(cfg.elecfile); - elseif isfield(firstdataset, 'grad') - fprintf('Obtaining the gradiometer configuration from the first dataset.\n'); - data.grad = firstdataset.grad; - elseif isfield(firstdataset, 'elec') - fprintf('Obtaining the electrode configuration from the first dataset.\n'); - data.elec = firstdataset.elec; - end - firstdataset = swapmemfile(firstdataset); - if ~(isfield(data,'grad') | isfield(data,'elec')) - error('Did not find gradiometer or electrode information.'); - end; - cfg.neighbours=compneighbstructfromgradelec(data,cfg.neighbourdist); -end; - -% At this point, either (1) cfg.neighbours contains the neighborhood -% structure, (2) cfg.neighbours does NOT contain the neighborhood -% structure, but geom exist, or (3) cfg.neighbours does NOT contain the neighborhood -% structure and geom does not exist. - -% Find the non-reference channels if cfg.chancmbgeom='refchan' -if ~singlechans && (strcmp(cfg.chancmbgeom,'refchan') | strcmp(cfg.chancmbgeom,'free')) - crsspctrselvec = find(~strcmp(data.labelcmb(:,1),data.labelcmb(:,2))); - crsspctrlabelcmb = data.labelcmb(crsspctrselvec,:); - if strcmp(cfg.chancmbgeom,'refchan') - uniquelabels=unique(crsspctrlabelcmb(:)); - nuniqlabels=length(uniquelabels); - npairsperchan=zeros(nuniqlabels,1); - for indx=1:nuniqlabels - npairsperchan(indx)=length(strmatch(uniquelabels{indx},crsspctrlabelcmb(:),'exact')); - end; - [sortednpairs,sorti]=sort(npairsperchan,'descend'); - % perform a check on the channel combinations to see if they conform to cfg.chancmbgeom='refchan' - if sortednpairs(1)~=(nuniqlabels-1) && sortednpairs(2)~=1 - error('The channel combinations in the data do not conform to the constraints imposed by cfg.chancmbgeom=''refchan''.'); - end; - refchanlabel=uniquelabels(sorti(1)); - nonrefchanlabels=cell(nuniqlabels-1,1); - nonrefchanlabels(~strcmp(refchanlabel,crsspctrlabelcmb(:,1)))=crsspctrlabelcmb(~strcmp(refchanlabel,crsspctrlabelcmb(:,1)),1); - nonrefchanlabels(~strcmp(refchanlabel,crsspctrlabelcmb(:,2)))=crsspctrlabelcmb(~strcmp(refchanlabel,crsspctrlabelcmb(:,2)),2); - end; -end; - -if exist('geom') - if singlechans - [checkvec,selvec]=match_str(data.label,geom.label); - if length(checkvec)~=length(data.label) - error('For some channels in the data, the neighbourhood geometry file does not contain information.'); - end; - data.channeighbstructmat=geom.channeighbstructmat(selvec,selvec); - else % channel combination data - if strcmp(cfg.chancmbgeom,'refchan') - [checkvec,selvec]=match_str(nonrefchanlabels,geom.label); - if length(checkvec)~=length(nonrefchanlabels) - error('For some non-reference channels in the data, the neighbourhood geometry file does not contain information.'); - end; - data.chancmbneighbstructmat=geom.channeighbstructmat(selvec,selvec); - elseif strcmp(cfg.chancmbgeom,'free') - datalabelcmb=cmb2label(data.labelcmb); - geomlabelcmb=cmb2label(geom.labelcmb); - [checkvec,selvec]=match_str(datalabelcmb,geomlabelcmb); - if length(checkvec)~=length(datalabelcmb) - error('For some channel combinations in the data, the neighbourhood geometry file does not contain information.'); - end; - data.chancmbneighbstructmat=geom.chancmbneighbstructmat(selvec,selvec); - if isfield(geom,'chancmbneighbselmat'); - data.chancmbneighbselmat=geom.chancmbneighbselmat(selvec,selvec); - end; - end; - end; - clear geom; -else % the neighbourhood geometry structure geom does not exist - % compute CHANNEIGHBSTRUCTMAT, which will be used in the clustering algorithm - if singlechans - data.channeighbstructmat = makechanneighbstructmat(cfg.neighbours,data.label); - if strcmp(cfg.savegeom,'yes') - geom.label = data.label; - geom.channeighbstructmat = data.channeighbstructmat; - end; - else % channel combination data - if strcmp(cfg.chancmbgeom,'refchan') - data.chancmbneighbstructmat = makechanneighbstructmat(cfg.neighbours,nonrefchanlabels); - if strcmp(cfg.savegeom,'yes') - geom.label = nonrefchanlabels; - geom.channeighbstructmat = data.chancmbneighbstructmat; - end; - elseif strcmp(cfg.chancmbgeom,'free') - % compute CHANNEIGHBSTRUCTMAT, which will be used in the clustering algorithm - singlechanlabels = unique(data.labelcmb(:)); - data.channeighbstructmat = makechanneighbstructmat(cfg.neighbours,singlechanlabels); - % compute CHANCMBNEIGHBSTRUCTMAT and CHANCMBNEIGHBSELMAT, which will be - % used for clustering channel combinations. - orderedchancmbs=strcmp(cfg.mirrordata,'yes'); - % orderedchancmbs is true if the result of the statistical test depends - % on the order of the elements of the cross-spectrum (as, for - % example, when these are coherencies or the imaginary - % parts of the coherencies). - original = true; - % with original=false, we use a calculation that consumes less memory. - [data.chancmbneighbstructmat data.chancmbneighbselmat] = makechancmbneighbmats(data.channeighbstructmat, ... - crsspctrlabelcmb,singlechanlabels,orderedchancmbs,original); - if strcmp(cfg.savegeom,'yes') - geom.labelcmb = crsspctrlabelcmb; - geom.chancmbneighbstructmat = data.chancmbneighbstructmat; - geom.chancmbneighbselmat = data.chancmbneighbselmat; - end; - else - error('Unsupported value for cfg.chancmbgeom.'); - end; - end; - if strcmp(cfg.savegeom,'yes') && ~isempty(cfg.geomfile) - save(cfg.geomfile,'geom'); - end; -end; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% BEGIN SUBFUNCTION COMPNEIGHBSTRUCTFROMGRADELEC -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [neighbours]=compneighbstructfromgradelec(data,neighbourdist); - -% compute the neighbourhood geometry from the gradiometer/electrode positions provided in the data - -if isfield(data, 'grad') - sens = data.grad; -elseif isfield(data, 'elec') - sens = data.elec; -else - error('No gradiometer or electrode configuration present in the data'); -end -nsensors = length(sens.label); - -% compute the distance between all sensors -dist = zeros(nsensors,nsensors); -for i=1:nsensors - dist(i,:) = sqrt(sum((sens.pnt(1:nsensors,:) - repmat(sens.pnt(i,:), nsensors, 1)).^2,2))'; -end; - -% find the neighbouring electrodes based on distance, later we have to restrict the neighbouring -% electrodes to those actually selected in the dataset -channeighbstructmat = (dist. % +% $Id: clusterrandstatistics.m 1362 2010-07-06 09:04:24Z roboos $ % Turn divideByZero warnings off. -warning off; +ws = warning('off', 'MATLAB:divideByZero'); fprintf('Running the statistics engine.\n'); @@ -1258,9 +1230,8 @@ if isfield(data,'time') clusrand.time=data.time; end; -clusrand.cfg = cfg; % remember the configuration details +clusrand.cfg = cfg; % remember the configuration details % Turn warnings on. -warning on; - +warning(ws); diff --git a/external/fieldtrip/private/clusterstat.m b/external/fieldtrip/private/clusterstat.m index bca6f4c..1c58716 100644 --- a/external/fieldtrip/private/clusterstat.m +++ b/external/fieldtrip/private/clusterstat.m @@ -1,4 +1,4 @@ -function [stat, cfg] = clusterstat(cfg, statrnd, statobs); +function [stat, cfg] = clusterstat(cfg, statrnd, statobs, varargin) % SUBFUNCTION for computing cluster statistic for N-D volumetric source data % or for channel-freq-time data @@ -18,31 +18,23 @@ % Copyright (C) 2005-2007, Robert Oostenveld % -% $Log: clusterstat.m,v $ -% Revision 1.23 2008/09/17 14:03:51 roboos -% fixed bug for negative critval (thanks to Vladimir) -% added error message if tail~=clustertail +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.22 2008/05/26 09:23:56 roboos -% fixed bug in neg and postailcritval concatenation when one was inf and the other a vector +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.21 2008/01/15 09:48:04 roboos -% added comment, no functional change +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.20 2008/01/15 08:29:59 roboos -% ensure that the critical values are column vectors -% -% Revision 1.19 2007/07/17 10:35:36 roboos -% treat critical values the same for parametric, nonparametric_common and nonparametric_individual and always return them in the cfg -% -% Revision 1.18 2007/06/19 12:52:37 roboos -% implemented seperate common and individual nonparametric thresholds -% renamed the option cfg.clusterthreshold=nonparametric into nonparametric_individual, the new option is nonparametric_common -% updated documentation -% -% Revision 1.17 2007/05/30 13:25:46 roboos -% added log, changed some help +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: clusterstat.m 1014 2010-05-03 13:30:24Z roevdmei $ % set the defaults if ~isfield(cfg,'orderedstats'), cfg.orderedstats = 'no'; end @@ -52,22 +44,29 @@ % if ~isfield(cfg,'chancmbneighbstructmat'), cfg.chancmbneighbstructmat=[]; end % if ~isfield(cfg,'chancmbneighbselmat'), cfg.chancmbneighbselmat=[]; end +% get issource from varargin, to determine source-data-specific options and allow the proper usage of cfg.neighbours +% (cfg.neighbours was previously used in determining wheter source-data was source data or not) set to zero by default +% note, this may cause problems when functions call clusterstat without giving issource, as issource was previously +% set in clusterstat.m but has now been transfered to the function that calls clusterstat.m (but only implemented in statistics_montecarlo) +issource = keyval('issource', varargin); if isempty(issource), issource = 0; end + if cfg.tail~=cfg.clustertail error('cfg.tail and cfg.clustertail should be identical') end -% determine whether the input represents N-D volumetric data or channel-freq-time data -% and provide the appropriate details -% TODO this detection should be more robust -if isfield(cfg, 'neighbours') && ~isempty(cfg.neighbours) + +% create neighbour structure (but only when not using source data) +if isfield(cfg, 'neighbours') && ~issource channeighbstructmat = makechanneighbstructmat(cfg); - issource = 0; -else - issource = 1; - % cfg contains dim and inside that are needed for reshaping the data to a volume, and inside should behave as a index vector +end + +% perform fixinside fix if input data is source data +if issource + % cfg contains dim and inside that are needed for reshaping the data to a volume, and inside should behave as a index vector cfg = fixinside(cfg, 'index'); end + needpos = cfg.tail==0 || cfg.tail== 1; needneg = cfg.tail==0 || cfg.tail==-1; Nsample = size(statrnd,1); @@ -491,7 +490,14 @@ % MAKECHANNEIGHBSTRUCTMAT makes the makes the matrix containing the channel % neighbourhood structure. -nchan=length(cfg.channel); +% because clusterstat has no access to the actual data (containing data.label), this workaround is required +% cfg.neighbours is cleared here because it is not done where avgoverchan is effectuated (it should actually be changed there) +if strcmp(cfg.avgoverchan, 'no') + nchan=length(cfg.channel); +elseif strcmp(cfg.avgoverchan, 'yes') + nchan = 1; + cfg.neighbours = []; +end channeighbstructmat = false(nchan,nchan); for chan=1:length(cfg.neighbours) [seld] = match_str(cfg.channel, cfg.neighbours{chan}.label); diff --git a/external/fieldtrip/private/combineplanar.m b/external/fieldtrip/private/combineplanar.m deleted file mode 100644 index 35a053b..0000000 --- a/external/fieldtrip/private/combineplanar.m +++ /dev/null @@ -1,425 +0,0 @@ -function [data] = combineplanar(cfg, data) - -% COMBINEPLANAR computes the planar gradient magnitude over both directions -% combining the two gradients at each sensor to a single positive-valued number. -% This can be done for averaged ERFs or TFRs (i.e. powerspectra). -% -% Use as -% [data] = combineplanar(cfg, data) -% where data contains an averaged planar gradient (either ERF or TFR). -% -% In the case of ERFs, the configuration can contain -% cfg.blc = 'yes' or 'no' (default) -% cfg.blcwindow = [begin end] -% -% After combining the planar data, the planar gradiometer definition does not -% match the data any more and therefore it is removed from the data. With -% cfg.combinegrad = 'yes' -% the function will try to reconstruct the axial gradiometer definition. -% -% See also MEGPLANAR - -% Undocumented local options: -% cfg.baseline -% cfg.combinemethod -% cfg.foilim -% cfg.trials - -% Copyright (C) 2004, Ole Jensen, Robert Oostenveld -% -% $Log: combineplanar.m,v $ -% Revision 1.44 2009/09/30 12:48:14 jansch -% added cumtapcnt as input to svdfft -% -% Revision 1.43 2009/07/23 08:11:29 crimic -% fixed tiny bug -% -% Revision 1.42 2009/07/17 08:17:24 jansch -% rewriting of big parts of the code; incorporating checkdata etc. implementation -% of 'svd' combinemethod also for time domain data -% -% Revision 1.41 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.40 2008/11/21 12:48:17 sashae -% added call to checkconfig at start and end of function -% -% Revision 1.39 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.38 2008/07/16 10:20:42 jansch -% added support for bti248_planar data -% -% Revision 1.37 2008/01/31 17:20:17 sashae -% added option for trial selection -% -% Revision 1.36 2007/05/29 14:26:44 ingnie -% changed sensortype to senstype (in calling checkdata) to avoid overlap with function name sensortype -% -% Revision 1.35 2007/05/29 12:51:31 roboos -% added new options for checkdata -% -% Revision 1.34 2007/05/07 09:38:09 chrhes -% added support for single trial time-domain data -% -% Revision 1.33 2007/05/02 15:56:41 roboos -% added some comments to the code -% -% Revision 1.32 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.31 2007/03/30 17:05:40 ingnie -% checkinput; only proceed when input data is allowed datatype -% -% Revision 1.30 2007/03/27 11:05:19 ingnie -% changed call to fixdimord in call to checkinput -% -% Revision 1.29 2006/04/20 09:58:33 roboos -% updated documentation -% -% Revision 1.28 2006/02/23 10:28:16 roboos -% changed dimord strings for consistency, changed toi and foi into time and freq, added fixdimord where neccessary -% -% Revision 1.27 2006/02/07 22:18:31 roboos -% changed the dimord chancmb (used to be sgncmb) into chan -% -% Revision 1.26 2006/02/01 12:26:00 roboos -% made all uses of dimord consistent with the common definition of data dimensions, see the fixdimord() function -% -% Revision 1.25 2006/01/30 14:12:13 jansch -% included svdfft instead of svd, for the combination of planar fourier-components -% -% Revision 1.24 2005/08/16 09:05:38 jansch -% implemented svd for fourier-input -% -% Revision 1.23 2005/06/29 12:46:29 roboos -% the following changes were done on a large number of files at the same time, not all of them may apply to this specific file -% - added try-catch around the inclusion of input data configuration -% - moved cfg.version, cfg.previous and the assignment of the output cfg to the end -% - changed help comments around the configuration handling -% - some changes in whitespace -% -% Revision 1.22 2005/06/28 15:56:34 roboos -% removed subfunction planarchannelset from the code, it is now a separate file in private/planarchannelset.m -% -% Revision 1.21 2005/06/02 16:00:20 roboos -% fixed bug: instead of combining the average many times, it should combine each trial -% -% Revision 1.20 2005/06/02 12:27:07 roboos -% changed from processing only the average ERF to processing only raw trials -% added call to data2raw and raw2data, which converts various types of averages to raw trials -% for keeptrial and keepsubject, the average and variance are recomputed after the combination of planar data for each trial/subject -% -% Revision 1.19 2005/05/17 17:50:36 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.18 2005/05/02 10:15:39 roboos -% corrected output labels for planar combinations -% fixed bug in removal of fields that are not combined (such as var and crsspctrm) -% -% Revision 1.17 2005/04/29 10:28:56 roboos -% changed selection of planar combinations into a lookup table -% added support for Neuromag 306 -% -% Revision 1.16 2005/02/18 12:57:50 roboos -% added support for singletrial power spectra -% -% Revision 1.15 2004/11/12 09:21:01 roboos -% added detection for 306 channel Neuromag data, no actual implementation yet -% -% Revision 1.14 2004/06/23 20:28:54 roberto -% added support for 122 channels, indicating Neuromag data -% -% Revision 1.13 2004/06/03 15:46:27 roberto -% added warning message for planar gradiometers -% -% Revision 1.12 2004/04/28 09:33:44 roberto -% added check for missing gradiometer definition -% -% Revision 1.11 2004/04/22 08:48:17 roberto -% added cfg.combinegrad, wrapped around planar to axial conversion -% -% Revision 1.10 2004/04/20 20:09:29 roberto -% convert input (planar) gradiometer definition into axial gradiometer definition, -% some changes in splaces and tabs -% -% Revision 1.9 2004/04/13 16:31:09 roberto -% fixed bug in dbstack selection of function filename for Matlab 6.1 -% -% Revision 1.8 2004/04/13 14:25:24 roberto -% wrapped code-snippet around mfilename to make it compatible with Matlab 6.1 -% -% Revision 1.7 2004/04/06 20:00:40 roberto -% minor changes in documentation -% -% Revision 1.6 2004/03/29 15:13:29 roberto -% added version and history to output configuration -% -% Revision 1.5 2004/03/23 11:01:09 roberto -% implemented support to keep non-MEG channels in the data after combining the planar gradients -% -% Revision 1.4 2004/02/10 15:45:04 roberto -% fixed bug in cfg.blcwindow and changed its default into 'all' -% -% Revision 1.3 2004/01/27 17:02:49 roberto -% added support for frequency and time-frequency data (only singletrial) -% removed custom baselinecorrection and replaced with blc function -% -% Revision 1.2 2004/01/27 09:49:26 roberto -% fixed small bug in length(data.label)~=302 -% -% Revision 1.1 2004/01/27 09:42:06 roberto -% took over this function from Ole, improved compatibility with framework, -% added help and built in some checks for invalid input data -% - -fieldtripdefs - -cfg = checkconfig(cfg, 'trackconfig', 'on'); - -% check if the input data is valid for this function -data = checkdata(data, 'datatype', {'raw', 'freq', 'timelock'}, 'feedback', 'yes', 'senstype', {'ctf151_planar', 'ctf275_planar', 'neuromag122', 'neuromag306', 'bti248_planar', 'bti148_planar'}); - -israw = datatype(data, 'raw'); -isfreq = datatype(data, 'freq'); -istimelock = datatype(data, 'timelock'); -try, dimord = data.dimord; end - -% set the defaults -if ~isfield(cfg, 'blc'), cfg.blc = 'no'; end -if ~isfield(cfg, 'blcwindow'), cfg.blcwindow = 'all'; end -if ~isfield(cfg, 'combinegrad'), cfg.combinegrad = 'no'; end -if ~isfield(cfg, 'combinemethod'), cfg.combinemethod = 'sum'; end -if ~isfield(cfg, 'foilim'), cfg.foilim = []; end -if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end -if ~isfield(cfg, 'feedback'), cfg.feedback = 'none'; end -if isfield(cfg, 'baseline') - warning('only supporting cfg.baseline for backwards compatibility, please update your cfg'); - cfg.blc = 'yes'; - cfg.blcwindow = cfg.baseline; -end -if strcmp(cfg.blc, 'yes') && isempty(cfg.blcwindow) - cfg.blcwindow = [min(data.time) max(data.time)]; -end - -% select trials of interest -if ~strcmp(cfg.trials, 'all') - error('trial selection has not been implemented yet') % first fix checkdata (see above) -end - -% find the combination of horizontal and vertical channels that should be combined -planar = planarchannelset(data); -sel_dH = match_str(data.label, planar(:,1)); % indices of the horizontal channels -sel_dV = match_str(data.label, planar(:,2)); % indices of the vertical channels -lab_dH = data.label(sel_dH); -lab_dV = data.label(sel_dV); - -if length(sel_dH)~=length(sel_dV) - error('not all planar channel combinations are complete') -end - -% find the other channels that are present in the data -sel_other = setdiff(1:length(data.label), [sel_dH(:)' sel_dV(:)']); -lab_other = data.label(sel_other); - -% define the channel names after combining the planar combinations -% they should be sorted according to the order of the planar channels in the data -[dum, sel_planar] = match_str(data.label, planar(:,1)); -lab_comb = planar(sel_planar,3); - -% perform baseline correction -if strcmp(cfg.blc, 'yes') - if ~istimelock, - error('baseline correction is only supported for ERFs') - else - if ischar(cfg.blcwindow) && strcmp(cfg.blcwindow, 'all') - cfg.blcwindow = [min(data.time) max(data.time)]; - end - % find the timebins corresponding to the baseline interval - tbeg = nearest(data.time, cfg.blcwindow(1)); - tend = nearest(data.time, cfg.blcwindow(2)); - cfg.blcwindow(1) = data.time(tbeg); - cfg.blcwindow(2) = data.time(tend); - data.avg = blc(data.avg, tbeg, tend); - end -end - -if isfreq - switch cfg.combinemethod - case 'sum' - if isfield(data, 'powspctrm'), - % compute the power of each planar channel, by summing the horizontal and vertical gradients - dimtok = tokenize(dimord,'_'); - catdim = strmatch('chan',dimtok); - if catdim==1, - tmp1 = data.powspctrm(sel_dH,:,:,:) + data.powspctrm(sel_dV,:,:,:); - tmp2 = data.powspctrm(sel_other,:,:,:); - elseif catdim==2, - tmp1 = data.powspctrm(:,sel_dH,:,:,:) + data.powspctrm(:,sel_dV,:,:,:); - tmp2 = data.powspctrm(:,sel_other,:,:,:); - else - error('unsupported dimension order of frequency data'); - end - data.powspctrm = cat(catdim, tmp1, tmp2); - else - error('cfg.combinemethod = ''sum'' only works for frequency data with powspctrm'); - end - case 'svd' - if isfield(data, 'fourierspctrm'), - if isempty(cfg.foilim), cfg.foilim = [data.freq(1) data.freq(end)]; end; - fbin = nearest(data.freq, cfg.foilim(1)):nearest(data.freq, cfg.foilim(2)); - - Nrpt = size(data.fourierspctrm,1); - Nsgn = length(sel_dH); - Nfrq = length(fbin); - Ntim = size(data.fourierspctrm,4); - %fourier= complex(zeros(Nrpt,Nsgn,Nfrq,Ntim),zeros(Nrpt,Nsgn,Nfrq,Ntim)); - fourier= zeros(Nrpt,Nsgn,Nfrq,Ntim)+nan; - progress('init', cfg.feedback, 'computing the svd'); - for j = 1:Nsgn - progress(j/Nsgn, 'computing the svd of signal %d/%d\n', j, Nsgn); - for k = 1:Nfrq - dum = reshape(data.fourierspctrm(:,[sel_dH(j) sel_dV(j)],fbin(k),:), [Nrpt 2 Ntim]); - dum = permute(dum, [2 3 1]); - dum = reshape(dum, [2 Ntim*Nrpt]); - timbin = ~isnan(dum(1,:)); - dum2 = svdfft(dum(:,timbin),1,data.cumtapcnt); - dum(1,timbin) = dum2; - dum = reshape(dum(1,:),[Ntim Nrpt]); - fourier(:,j,k,:) = transpose(dum); - - %for m = 1:Ntim - % dum = data.fourierspctrm(:,[sel_dH(j) sel_dV(j)],fbin(k),m); - % timbin = find(~isnan(dum(:,1))); - % [fourier(timbin,j,k,m)] = svdfft(transpose(dum(timbin,:)),1); - %end - end - end - progress('close'); - other = data.fourierspctrm(:,sel_other,fbin,:); - data = rmfield(data,'fourierspctrm'); - data.fourierspctrm = cat(2, fourier, other); - data.freq = data.freq(fbin); - else - error('cfg.combinemethod = ''svd'' only works for frequency data with fourierspctrm'); - end - otherwise - end -else - if istimelock, - data = checkdata(data, 'datatype', 'raw', 'feedback', 'yes'); - end - - switch cfg.combinemethod - case 'sum' - Nrpt = length(data.trial); - for k = 1:Nrpt - tmp1 = sqrt(data.trial{k}(sel_dH,:).^2 + data.trial{k}(sel_dV,:).^2); - tmp2 = data.trial{k}(sel_other,:); - data.trial{k} = [tmp1;tmp2]; - end - case 'svd' - Nrpt = length(data.trial); - Nsgn = length(sel_dH); - Nsmp = cellfun('size', data.trial, 2); - Csmp = cumsum([0 Nsmp]); - %do a 'fixed orientation' across all trials approach here - %this is different from the frequency case FIXME - tmpdat = zeros(2, sum(Nsmp)); - for k = 1:Nsgn - for m = 1:Nrpt - tmpdat(:, (Csmp(m)+1):Csmp(m+1)) = data.trial{m}([sel_dH(k) sel_dV(k)],:); - end - tmpdat2 = abs(svdfft(tmpdat,1)); - tmpdat2 = mat2cell(tmpdat2, 1, Nsmp); - for m = 1:Nrpt - if k==1, trial{m} = zeros(Nsgn, Nsmp(m)); end - trial{m}(k,:) = tmpdat2{m}; - end - end - - for m = 1:Nrpt - other = data.trial{m}(sel_other,:); - trial{m} = [trial{m}; other]; - end - data.trial = trial; - - otherwise - end - - if istimelock, - data = checkdata(data, 'datatype', 'timelock', 'feedback', 'yes'); - end -end - -if strcmp(cfg.combinegrad, 'no') && ~isfield(data, 'grad') - % the planar gradiometer definition was already removed - % nothing needs to be done here -elseif strcmp(cfg.combinegrad, 'no') && isfield(data, 'grad') - % remove the planar gradiometer definition since it does not match the data any more - data = rmfield(data, 'grad'); -elseif strcmp(cfg.combinegrad, 'yes') && ~isfield(data, 'grad') - % there is no gradiometer definition, impossible to reconstruct it - error('the planar gradiometer definition is missing, cannot convert it back to axial'); -elseif strcmp(cfg.combinegrad, 'yes') && isfield(data, 'grad') - warning('trying to convert planar to axial gradiometers, this is experimental'); - % try to reconstruct the original axial gradiometer array from the planar gradiometer definition - orig = data.grad; - if all(size(orig.pnt)==[302 3]) && ... - all(size(orig.pnt)==[302 3]) && ... - all(size(orig.tra)==[302 302]) && ... - length(orig.label)==302 && ... - all(sum(orig.tra~=0,1)>2) - % This looks as if it was made using the MEGPLANAR nearest neighbour approach - % which means that the coil position and orientation still correspond - % with those of the original axial gradiometer. Only the label and tra - % have been modified and have to be restored to their original values. - axial.pnt = orig.pnt; - axial.ori = orig.ori; - for i=1:151 - axial.label{i} = orig.label{i}(1:(end-3)); - end - if all(orig.ori(1,:)==orig.ori(152,:)) - % orientation is the same, the subtraction should be in "tra" - axial.tra = [eye(151) -eye(151)]; - else - % orientation is opposite, the subtraction should not be in "tra" - axial.tra = [eye(151) eye(151)]; - end - try - axial.unit = orig.unit; - end - else - error('cannot convert gradiometer definition back to axial, please contact Robert'); - end - data.grad = axial; -end - -% reconstruct the original channel labels -data.label = [lab_comb(:); lab_other(:)]; - -% remove the fields for which the planar gradient could not be combined -try, data = rmfield(data, 'crsspctrm'); end -try, data = rmfield(data, 'labelcmb'); end - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% store the configuration of this function call, including that of the previous function call -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: combineplanar.m,v 1.44 2009/09/30 12:48:14 jansch Exp $'; -% remember the configuration details of the input data -try, cfg.previous = data.cfg; end -% remember the exact configuration details in the output -data.cfg = cfg; - diff --git a/external/fieldtrip/private/comp2timelock.m b/external/fieldtrip/private/comp2timelock.m index 64a0b1d..18a00e1 100644 --- a/external/fieldtrip/private/comp2timelock.m +++ b/external/fieldtrip/private/comp2timelock.m @@ -6,13 +6,23 @@ % Copyright (C) 2005, Robert Oostenveld % -% $Log: comp2timelock.m,v $ -% Revision 1.2 2006/05/10 08:19:45 roboos -% added dimord to the output +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.1 2005/10/14 15:50:08 roboos -% new implementation, used by dipolefitting in case of frequency or ICA data +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: comp2timelock.m 952 2010-04-21 18:29:51Z roboos $ % only convert, do not perform channel or component selection timelock = []; diff --git a/external/fieldtrip/private/componentanalysis.m b/external/fieldtrip/private/componentanalysis.m deleted file mode 100644 index 76d6bc0..0000000 --- a/external/fieldtrip/private/componentanalysis.m +++ /dev/null @@ -1,550 +0,0 @@ -function [comp] = componentanalysis(cfg, data) - -% COMPONENTANALYSIS principal or independent component analysis -% computes the topography and timecourses of the ICA/PCA components -% in the EEG/MEG data. -% -% Use as -% [comp] = componentanalysis(cfg, data) -% -% where the data comes from PREPROCESING or TIMELOCKANALYSIS and the -% configuration structure can contain -% cfg.method = 'runica', 'fastica', 'binica', 'pca', 'jader', 'varimax', 'dss', 'cca' (default = 'runica') -% cfg.channel = cell-array with channel selection (default = 'all'), see CHANNELSELECTION for details -% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') -% cfg.numcomponent = 'all' or number (default = 'all') -% cfg.blc = 'no' or 'yes' (default = 'yes') -% cfg.runica = substructure with additional low-level options for this method -% cfg.binica = substructure with additional low-level options for this method -% cfg.dss = substructure with additional low-level options for this method -% cfg.fastica = substructure with additional low-level options for this method -% -% forbidden configuration option: cfg.detrend -% -% Instead of specifying a component analysis method, you can also specify -% a previously computed mixing matrix, which will be used to estimate the -% component timecourses in this data. This requires -% cfg.topo = NxN matrix with a component topography in each column -% cfg.topolabel = Nx1 cell-array with the channel labels -% -% See also FASTICA, RUNICA, SVD, JADER, VARIMAX, DSS, CCA - -% NOTE parafac is also implemented, but that does not fit into the -% structure of 2D decompositions very well. Probably I should implement it -% in a separate function for N-D decompositions - -% Copyright (C) 2003-2007, Robert Oostenveld -% -% $Log: componentanalysis.m,v $ -% Revision 1.46 2009/03/26 16:29:47 jansch -% cleaned up the code generating the output, no functional changes -% -% Revision 1.45 2009/03/26 12:48:40 jansch -% ensure correct number of labels if number of components < number of sensors -% -% Revision 1.44 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.43 2009/01/16 17:21:20 sashae -% added config tracking -% -% Revision 1.42 2009/01/14 21:16:51 marvger -% changes related to realtime processing -% -% Revision 1.41 2008/11/25 15:03:05 estmee -% Documentation update -% -% Revision 1.40 2008/11/10 12:55:01 roboos -% improved channel selection for re-applying an unmixing matrix -% -% Revision 1.39 2008/11/04 16:51:59 roboos -% ensure that all channels that are required for unmixing using previous matrix are present in the data -% -% Revision 1.38 2008/10/30 09:57:38 roboos -% fixed some small bugs that were introduced with the last change, thanks to Kai -% -% Revision 1.37 2008/10/29 15:54:50 roboos -% give hopefylly meaningfull error message if fastica fails due to memory error (thanks to Kai) -% -% Revision 1.36 2008/10/29 15:24:58 roboos -% unmixing based on previous weights now also works with non-square matrices, thanks to kaigoe -% -% Revision 1.35 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.34 2008/06/17 15:21:42 sashae -% now using preproc_modules -% -% Revision 1.33 2008/05/06 14:23:32 sashae -% change in trial selection, cfg.trials can be a logical -% -% Revision 1.32 2007/12/18 17:06:05 sashae -% updated documentation -% -% Revision 1.31 2007/05/02 15:59:13 roboos -% be more strict on the input and output data: It is now the task of -% the private/checkdata function to convert the input data to raw -% data (i.e. as if it were coming straight from preprocessing). -% Furthermore, the output data is NOT converted back any more to the -% input data, i.e. the output data is the same as what it would be -% on raw data as input, regardless of the actual input. -% -% Revision 1.30 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.29 2007/03/30 17:05:40 ingnie -% checkinput; only proceed when input data is allowed datatype -% -% Revision 1.28 2007/03/04 14:22:14 chrhes -% changes to pca option: this is now calculated using eigenvalue decomposition -% (EVD) of the data cross-covariance matrix (the traditional approach to PCA) -% rather than by means of singular value decomposition (SVD) of the data matrix -% (which has been added as a separate option: svd). For large data matrices -% EVD of the cross-covariancre matrix is computationally much faster than SVD, -% and avoids the risk of memory related errors in matlab. -% -% Revision 1.27 2007/03/04 13:45:12 chrhes -% changes to how the code calls fastica: the responsibility for providing the -% correct optional arguments through cfg.fastica lies entriely with the user -% (as for the runica option) -% -% Revision 1.26 2007/02/27 09:54:22 roboos -% added required defaults for binica, check for EEGLAB in case of binica -% -% Revision 1.25 2007/02/12 19:57:28 roboos -% implemented binica -% -% Revision 1.24 2007/02/12 19:44:31 roboos -% check fastica toolbox, try to add automatically -% -% Revision 1.23 2006/12/15 14:44:40 chrhes -% implemented (undocumented, preliminary) support for the FastICA algorithm -% -% Revision 1.22 2006/10/04 07:10:07 roboos -% updated documentation -% -% Revision 1.21 2006/08/16 10:49:53 roboos -% updated documentation -% -% Revision 1.20 2006/08/16 10:46:53 roboos -% added support for unmixing data using a previously determined (un)mixing -% matrix (options cfg.topo and cfg.topolabel) channels such as ECG can be -% excluded from teh unmixing, but will remain in the output data -% -% Revision 1.19 2006/06/07 09:34:19 roboos -% changed checktoolbox into hastoolbox -% -% Revision 1.18 2006/04/20 09:58:33 roboos -% updated documentation -% -% Revision 1.17 2006/01/11 12:58:16 roboos -% minor change to documentation -% -% Revision 1.16 2006/01/06 11:37:13 roboos -% switched to the checktoolbox() subfunction for toolbox dependency checking -% implemented canonical correlation analysis (CCA) using a function from Magnus -% Borga changed the DSS implementation from version 0.6 beta to version 1.0 -% fixed some small bugs related to the number of components -% -% Revision 1.15 2005/11/08 11:36:35 roboos -% updated the documentation to include dss -% -% Revision 1.14 2005/11/04 17:14:41 roboos -% implemented support for denoising source separation (dss), requires external -% toolbox -% -% Revision 1.13 2005/11/04 10:26:03 roboos -% changed the handling of optional arguments for runica to use cfg2keyval() -% -% Revision 1.12 2005/10/18 12:23:46 roboos -% added tic/toc timer around complete function -% changed handing of averages to using data2raw and raw2data -% added support for more options of runica, using cfg.runica substructure -% -% Revision 1.11 2005/08/05 09:16:22 roboos -% removed the obsolete data.offset -% -% Revision 1.10 2005/06/29 12:46:29 roboos -% the following changes were done on a large number of files at the same time, -% not all of them may apply to this specific file -% - added try-catch around the inclusion of input data configuration -% - moved cfg.version, cfg.previous and the assignment of the output cfg to the end -% - changed help comments around the configuration handling -% - some changes in whitespace -% -% Revision 1.9 2005/06/28 16:08:00 roboos -% cleaned up the detectin and error handling for eeglab and nway toolbox dependencies -% -% Revision 1.8 2004/09/16 15:36:08 roboos -% added preliminary support for parafac -% -% Revision 1.7 2004/09/01 17:59:28 roboos -% added copyright statements to all filed -% added cfg.version to all functions that give configuration in their output -% added cfg.previous to all functions with input data containing configuration details -% -% Revision 1.6 2004/05/19 14:47:20 roberto -% added version details to output configuration -% -% Revision 1.5 2004/03/06 13:06:49 roberto -% cleaded up transposing of weights matrix, no functional change -% -% Revision 1.4 2004/02/05 10:31:28 roberto -% implemented support for erf/erp input (from timelockanalysis) -% added option for svds with reduced number of components -% some layout changes to the code and updated documentation -% -% Revision 1.3 2004/02/04 14:01:44 roberto -% only change in help -% -% Revision 1.2 2003/12/16 21:03:19 roberto -% renamed my_xxx to their original function names (my_runica->runica etc.) -% -% Revision 1.1 2003/11/12 07:57:23 roberto -% new implementation, works with two functions from eeglab -% - -fieldtripdefs - -% set a timer to determine how long this function takes -tic; - -% check if the input data is valid for this function -data = checkdata(data, 'datatype', 'raw', 'feedback', 'yes'); - -% check if the input cfg is valid for this function -cfg = checkconfig(cfg, 'trackconfig', 'on'); -cfg = checkconfig(cfg, 'forbidden', {'detrend'}); - -% set the defaults -if ~isfield(cfg, 'method'), cfg.method = 'runica'; end -if ~isfield(cfg, 'blc'), cfg.blc = 'yes'; end -if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end -if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end -if ~isfield(cfg, 'numcomponent'), cfg.numcomponent = 'all'; end - -% select channels, has to be done prior to handling of previous (un)mixing matrix -cfg.channel = channelselection(cfg.channel, data.label); - -if isfield(cfg, 'topo') && isfield(cfg, 'topolabel') - % use the previously determined unmixing matrix on this dataset - - % test whether all required channels are present in the data - [datsel, toposel] = match_str(cfg.channel, cfg.topolabel); - if length(toposel)~=length(cfg.topolabel) - error('not all channels that are required for the unmixing are present in the data'); - end - - % ensure that all data channels not used in the unmixing should be removed from the channel selection - cfg.channel = intersect(cfg.channel, cfg.topolabel); - - % remove all cfg settings that do not apply - tmpcfg = []; - tmpcfg.blc = cfg.blc; - tmpcfg.trials = cfg.trials; - tmpcfg.topo = cfg.topo; % the MxN mixing matrix (M channels, N components) - tmpcfg.topolabel = cfg.topolabel; % the Mx1 labels of the data that was used in determining the mixing matrix - tmpcfg.channel = cfg.channel; % the Mx1 labels of the data that is presented now to this function - tmpcfg.numcomponent = 'all'; - tmpcfg.method = 'predetermined mixing matrix'; - cfg = tmpcfg; -end - -% additional options, see FASTICA for details -if ~isfield(cfg, 'fastica'), cfg.fastica = []; end; - -% additional options, see RUNICA for details -if ~isfield(cfg, 'runica'), cfg.runica = []; end -if ~isfield(cfg.runica, 'lrate'), cfg.runica.lrate = 0.001; end - -% additional options, see BINICA for details -if ~isfield(cfg, 'binica'), cfg.binica = []; end -if ~isfield(cfg.binica, 'lrate'), cfg.binica.lrate = 0.001; end - -% additional options, see DSS for details -if ~isfield(cfg, 'dss'), cfg.dss = []; end -if ~isfield(cfg.dss, 'denf'), cfg.dss.denf = []; end -if ~isfield(cfg.dss.denf, 'function'), cfg.dss.denf.function = 'denoise_fica_tanh'; end -if ~isfield(cfg.dss.denf, 'params'), cfg.dss.denf.params = []; end - -% check whether the required low-level toolboxes are installed -switch cfg.method - case 'fastica' - hastoolbox('fastica', 1); % see http://www.cis.hut.fi/projects/ica/fastica - case {'runica', 'jader', 'varimax', 'binica'} - hastoolbox('eeglab', 1); % see http://www.sccn.ucsd.edu/eeglab - case 'parafac' - hastoolbox('nway', 1); % see http://www.models.kvl.dk/source/nwaytoolbox - case 'dss' - hastoolbox('dss', 1); % see http://www.cis.hut.fi/projects/dss -end % cfg.method - -% default is to compute just as many components as there are channels in the data -if strcmp(cfg.numcomponent, 'all') - cfg.numcomponent = length(data.label); -end - -% select trials of interest -if ~strcmp(cfg.trials, 'all') - if islogical(cfg.trials), cfg.trials=find(cfg.trials); end - fprintf('selecting %d trials\n', length(cfg.trials)); - data.trial = data.trial(cfg.trials); - data.time = data.time(cfg.trials); -end -Ntrials = length(data.trial); - -% select channels of interest -chansel = match_str(data.label, cfg.channel); -fprintf('selecting %d channels\n', length(chansel)); -for trial=1:Ntrials - data.trial{trial} = data.trial{trial}(chansel,:); -end -data.label = data.label(chansel); -Nchans = length(chansel); - -% determine the size of each trial, they can be variable length -Nsamples = zeros(1,Ntrials); -for trial=1:Ntrials - Nsamples(trial) = size(data.trial{trial},2); -end - -if strcmp(cfg.blc, 'yes') - % optionally perform baseline correction on each trial - fprintf('baseline correcting data \n'); - for trial=1:Ntrials - data.trial{trial} = preproc_baselinecorrect(data.trial{trial}); - end -end - -if strcmp(cfg.method, 'predetermined mixing matrix') - % the single trial data does not have to be concatenated -elseif strcmp(cfg.method, 'parafac') - % concatenate all the data into a 3D matrix - fprintf('concatenating data'); - Nsamples = Nsamples(1); - dat = zeros(Ntrials, Nchans, Nsamples); - % all trials should have an equal number of samples - % and it is assumed that the time axes of all trials are aligned - for trial=1:Ntrials - fprintf('.'); - dat(trial,:,:) = data.trial{trial}; - end - fprintf('\n'); - fprintf('concatenated data matrix size %dx%dx%d\n', size(dat,1), size(dat,2), size(dat,3)); -else - % concatenate all the data into a 2D matrix - fprintf('concatenating data'); - - dat = zeros(Nchans, sum(Nsamples)); - for trial=1:Ntrials - fprintf('.'); - begsample = sum(Nsamples(1:(trial-1))) + 1; - endsample = sum(Nsamples(1:trial)); - dat(:,begsample:endsample) = data.trial{trial}; - end - fprintf('\n'); - fprintf('concatenated data matrix size %dx%d\n', size(dat,1), size(dat,2)); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% perform the component analysis -fprintf('starting decomposition using %s\n', cfg.method); -switch cfg.method - - case 'fastica' - - try - % construct key-value pairs for the optional arguments - optarg = cfg2keyval(cfg.fastica); - [A, W] = fastica(dat, optarg{:}); - weights = W; - sphere = eye(size(W,2)); - catch ME - % give a hopefully instructive error message - fprintf(['If you get an out-of-memory in fastica here, and you use fastica 2.5, change fastica.m, line 482: \n' ... - 'from\n' ... - ' if ~isempty(W) %% ORIGINAL VERSION\n' ... - 'to\n' ... - ' if ~isempty(W) && nargout ~= 2 %% if nargout == 2, we return [A, W], and NOT ICASIG\n']); - % forward original error - rethrow(ME); - end - - case 'runica' - % construct key-value pairs for the optional arguments - optarg = cfg2keyval(cfg.runica); - [weights, sphere] = runica(dat, optarg{:}); - - case 'binica' - % construct key-value pairs for the optional arguments - optarg = cfg2keyval(cfg.binica); - [weights, sphere] = binica(dat, optarg{:}); - - case 'jader' - weights = jader(dat); - sphere = eye(size(weights, 2)); - - case 'varimax' - weights = varimax(dat); - sphere = eye(size(weights, 2)); - - case 'cca' - [y, w] = ccabss(dat); - weights = w'; - sphere = eye(size(weights, 2)); - - case 'pca' - % compute data cross-covariance matrix - C = (dat*dat')./(size(dat,2)-1); - % eigenvalue decomposition (EVD) - [E,D] = eig(C); - % sort eigenvectors in descending order of eigenvalues - d = cat(2,[1:1:Nchans]',diag(D)); - d = sortrows(d,[-2]); - % return the desired number of principal components - weights = E(:,d(1:cfg.numcomponent,1))'; - sphere = eye(size(weights,2)); - clear C D E d - - case 'svd' - if cfg.numcomponent> buttons, updated help -% -% Revision 1.1 2009/07/17 14:25:39 giopia -% moved to main directory -% -% Revision 1.4 2009/07/15 08:38:28 giopia -% general cleanup, prepare_mask now standalone function -% -% Revision 1.3 2009/06/19 15:11:00 giopia -% allows scroll through components -% -% Revision 1.2 2009/06/03 14:00:26 roboos -% fixed cfg.lay, should be cfg.layout -% -% Revision 1.1 2009/06/02 15:48:58 giopia -% first implementation, plot topoplot, activations and simple interactive -% - -fieldtripdefs - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Prepare the data -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% check that the data comes from componentanalysis -comp = checkdata(comp, 'datatype', 'comp'); - -% set the defaults: -if ~isfield(cfg, 'comp'), cfg.comp = 1:10; end -if ~isfield(cfg, 'trial'), cfg.trial = 1; end - -if numel(cfg.trial) > 1, - warning('componentbrowser:cfg_onetrial', 'only one trial can be plotted at the time'); - cfg.trial = cfg.trial(1); -end - -% Read or create the layout that will be used for plotting: -[cfg.layout] = prepare_layout(cfg, comp); - -% Identify the channels to plot -[labels, cfg.chanidx.lay, cfg.chanidx.comp] = intersect(cfg.layout.label, comp.topolabel); % in case channels are missing -if isempty(cfg.chanidx.lay) - error('componentbrowser:labelmismatch', 'The channel labels in the data do not match the labels of the layout'); -end - -% fixed variables -cfg.shift = 1.2; % distance between topoplots - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Create figure and assign userdata -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% create figure and axes -cfg.h = figure('uni','pix', 'name', 'componentbrowser', 'vis', 'off', 'numbertitle', 'off'); -cfg.axis = axes; -hold on - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Buttons and Callbacks -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% scroll components -uicontrol(cfg.h,'uni','pix','pos',[105 5 25 18],'str','-',... - 'call',{@plottopography, comp}); - -cfg.ncomp = uicontrol(cfg.h,'sty','text','uni','pix','pos',[130 5 150 18],... - 'str',['comp n.' num2str(cfg.comp(1)) '-' num2str(cfg.comp(end))]); - -uicontrol(cfg.h,'uni','pix','pos',[280 5 25 18],'str','+',... - 'call',{@plottopography, comp}); - -% scroll trials -uicontrol(cfg.h,'uni','pix','pos',[330 5 25 18],'str','<<',... - 'call',{@plotactivation, comp}); - -uicontrol(cfg.h,'uni','pix','pos',[355 5 25 18],'str', '<',... - 'call',{@plotactivation, comp}); - -cfg.ntrl = uicontrol(cfg.h,'sty','text','uni','pix','pos',[380 5 70 18],... - 'str',['trial n.' num2str(cfg.trial)]); - -uicontrol(cfg.h,'uni','pix','pos',[450 5 25 18],'str', '>',... - 'call',{@plotactivation, comp}); - -uicontrol(cfg.h,'uni','pix','pos',[475 5 25 18],'str','>>',... - 'call',{@plotactivation, comp}); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% First callback and final adjustments -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% first call of the two plotting functions -plottopography([], cfg, comp) -plotactivation([], cfg, comp) - -% final adjustments -set(cfg.h, 'vis', 'on') -axis equal -axis off -hold off - -% the (optional) output is the handle -if nargout == 1; - varargout{1} = cfg.h; -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% PLOTTOPOGRAPHY -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function plottopography(h, cfg, comp) -% now plottopography is not associated with a callback, but it might in -% the future - -if isempty(h) % when called in isolation - set(cfg.h, 'user', cfg) -else - cfg = get(get(h, 'par'), 'user'); - - % which button has been pressed - if intersect(h, findobj(cfg.h, 'str', '+')) - - cfg.comp = cfg.comp + numel(cfg.comp); - if cfg.comp(end) > size(comp.label,1) - cfg.comp = cfg.comp - (cfg.comp(end) - size(comp.label,1)); - end - - elseif intersect(h, findobj(cfg.h, 'str', '-')) - - cfg.comp = cfg.comp - numel(cfg.comp); - if cfg.comp(1) < 1 - cfg.comp = cfg.comp - cfg.comp(1) + 1; - end - - end -end - -set(cfg.ncomp, 'str', ['comp n.' num2str(cfg.comp(1)) '-' num2str(cfg.comp(end))]) -drawnow -delete(findobj(cfg.h, 'tag', 'comptopo')) - -cnt = 0; -for k = cfg.comp - cnt = cnt + 1; - - % write number of the component on the left - h_text(cnt) = plot_text(-2.5, -cnt*cfg.shift, ['n. ' num2str(cfg.comp(cnt))]); - - % plot only topography (no layout) - h_topo(cnt) = plot_topo(cfg.layout.pos(cfg.chanidx.lay,1), cfg.layout.pos(cfg.chanidx.lay,2), comp.topo(cfg.chanidx.comp, k), ... - 'hpos', -1, 'vpos', -cnt*cfg.shift, 'mask', cfg.layout.mask); - % plot layout - plot_lay(cfg.layout, 'hpos', -1, 'vpos', -cnt*cfg.shift, 'point', false, 'box', false, 'label', false, 'mask', true, 'verbose', false); -end - -set(h_text, 'tag', 'comptopo') -set(h_topo, 'tag', 'comptopo') - -% in the colorbar, green should be zero -colorlimits = get(cfg.axis, 'clim'); -set(cfg.axis, 'clim', [-1 1] * max(abs(colorlimits))) - -plotactivation([], cfg, comp) - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% PLOTACTIVATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function plotactivation(h, cfg, comp) -% plotactivation can be called in isolation or by buttondownfcn -% cfg is stored in 'user' of the main figure - -if isempty(h) % when called in isolation - set(cfg.h, 'user', cfg) -else - cfg = get(get(h, 'par'), 'user'); - - % which button has been pressed - if intersect(h, findobj(cfg.h, 'str', '>>')) - - cfg.trial = cfg.trial + 10; - if cfg.trial > size(comp.trial,2) - cfg.trial = size(comp.trial,2); - end - - elseif intersect(h, findobj(cfg.h, 'str', '>')) - - cfg.trial = cfg.trial + 1; - if cfg.trial > size(comp.trial,2) - cfg.trial = size(comp.trial,2); - end - - elseif intersect(h, findobj(cfg.h, 'str', '<')) - - cfg.trial = cfg.trial - 1; - if cfg.trial < 1 - cfg.trial = 1; - end - - elseif intersect(h, findobj(cfg.h, 'str', '<<')) - - cfg.trial = cfg.trial - 10; - if cfg.trial < 1 - cfg.trial = 1; - end - - end -end - -set(cfg.ntrl,'str',['trial n. ' num2str(cfg.trial)]) -drawnow -delete(findobj(cfg.h,'tag', 'activations')); - -hold on -cnt = 0; -for k = cfg.comp - cnt = cnt + 1; - - % plot the activations - h_act(cnt) = plot_vector(comp.trial{cfg.trial}(k,:), 'hpos', 6 , 'vpos', -cnt*cfg.shift, 'width', 12, 'height', 1, 'box', true); -end - -h_inv = plot(6+12+1, -cnt*cfg.shift, '.'); % -set(h_inv, 'vis', 'off') - -set(h_act, 'tag', 'activations') -set(cfg.h, 'user', cfg) -hold off diff --git a/external/fieldtrip/private/compute_leadfield.m b/external/fieldtrip/private/compute_leadfield.m deleted file mode 100644 index 6684da2..0000000 --- a/external/fieldtrip/private/compute_leadfield.m +++ /dev/null @@ -1,534 +0,0 @@ -function [lf] = compute_leadfield(pos, sens, vol, varargin) - -% COMPUTE_LEADFIELD computes a forward solution for a dipole in a a volume -% conductor model. The forward solution is expressed as the leadfield -% matrix (Nchan*3), where each column corresponds with the potential or field -% distributions on all sensors for one of the x,y,z-orientations of the -% dipole. -% -% Use as -% [lf] = compute_leadfield(pos, sens, vol, ...) -% with input arguments -% pos position dipole (1x3 or Nx3) -% sens structure with gradiometer or electrode definition -% vol structure with volume conductor definition -% -% The vol structure represents a volume conductor model, its contents -% depend on the type of model. The sens structure represents a sensor -% arary, i.e. EEG electrodes or MEG gradiometers. -% -% It is possible to compute a simultaneous forward solution for EEG and MEG -% by specifying sens and grad as two cell-arrays, e.g. -% sens = {senseeg, sensmeg} -% vol = {voleeg, volmeg } -% This results in the computation of the leadfield of the first element of -% sens and vol, followed by the second, etc. The leadfields of the -% different imaging modalities are concatenated. -% -% Additional input arguments can be specified as key-value pairs, supported -% optional arguments are -% 'reducerank' = 'no' or number -% 'normalize' = 'no', 'yes' or 'column' -% 'normalizeparam' = parameter for depth normalization (default = 0.5) -% -% Depending on the specific input arguments for the sensor and volume, this -% function will select the appropriate low-level EEG or MEG forward model. -% The leadfield matrix for EEG will have an average reference over all the -% electrodes. -% -% The supported forward solutions for MEG are -% single sphere (Cuffin and Cohen, 1977) -% multiple spheres with one sphere per channel (Huang et al, 1999) -% realistic single shell using superposition of basis functions (Nolte, 2003) -% using leadfield interpolation on precomputed grid -% Boundary Element Method (BEM) using Neuromag meg_calc toolbox -% -% The supported forward solutions for EEG are -% single sphere -% multiple concentric spheres (max. 4) -% using leadfield interpolation on precomputed grid -% Boundary Element Method (BEM) using ASA to precompute the sytem matrix -% Boundary Element Method (BEM) using Neuromag meg_calc toolbox -% -% References to implemented methods: -% Cuffin BN, Cohen D. -% Magnetic fields of a dipole in special volume conductor shapes -% IEEE Trans Biomed Eng. 1977 Jul;24(4):372-81. -% -% Nolte G. -% The magnetic lead field theorem in the quasi-static approximation and its use for magnetoencephalography forward calculation in realistic volume conductors -% Phys Med Biol. 2003 Nov 21;48(22):3637-52 -% -% Huang MX, Mosher JC, Leahy RM. -% A sensor-weighted overlapping-sphere head model and exhaustive head model comparison for MEG -% Phys Med Biol. 1999 Feb;44(2):423-40 - -% Copyright (C) 2004-2008, Robert Oostenveld -% -% $Log: compute_leadfield.m,v $ -% Revision 1.30 2009/05/25 08:17:15 roboos -% small change in consistency test for multisphere MEG volume conductor -% -% Revision 1.29 2009/03/30 15:06:14 roboos -% added the patch from Alexandre to support openmeeg -% -% Revision 1.28 2009/02/02 13:05:44 roboos -% addec bemcp -% give warning once in case of eeg infinite medium -% -% Revision 1.27 2008/07/22 10:17:15 roboos -% replaced identical with strcmp -% -% Revision 1.26 2008/07/21 20:28:44 roboos -% added check on units (mm/cm/m) of the sensor array and volume conductor, give error if inconsistent -% -% Revision 1.25 2008/05/13 19:24:11 roboos -% consistently removed support for pnt1/pnt2 gradiometer description -% -% Revision 1.24 2008/04/30 13:47:20 roboos -% removed support for pnt1+pnt2 -% -% Revision 1.23 2008/04/15 20:36:21 roboos -% added explicit handling of various BEM implementations, i.e. for all voltype variants -% -% Revision 1.22 2008/04/11 13:16:16 roboos -% added support for simultaneous EEG and MEG -% -% Revision 1.21 2008/03/18 13:20:42 roboos -% updated documentation and some error messages -% -% Revision 1.20 2008/03/05 16:24:30 roboos -% use the voltype helper function -% added option for 'normalizeparam' -% -% Revision 1.19 2007/07/25 08:32:25 roboos -% switched to using senstype helper function -% -% Revision 1.18 2006/10/16 15:21:04 roboos -% small change in a comment -% -% Revision 1.17 2006/10/12 08:57:34 roboos -% added support for multiple dipoles for which the positions are in one long 1x(3*N) vector -% changed the functino call to neuromag megfield (not verified) -% renamed some internal variables -% only determine the number of dipoles (Ndipoles) once, and not in every section again -% -% Revision 1.16 2006/10/04 08:12:40 roboos -% changed some '&' into '&&', only apply reducerank when smaller than number of leadfield components (for efficiency) -% -% Revision 1.15 2006/09/07 12:43:22 roboos -% added code for multisphere, contributed by Punita Christopher (based on BrainStorm) -% -% Revision 1.14 2006/03/21 11:24:16 roboos -% multiply the nolte leadfield with sens.tra to transform from coils to gradiometers -% -% Revision 1.13 2006/03/21 09:40:08 roboos -% implemented support for Guido Nolte's method directly using his code -% improved documentation, added literature references -% -% Revision 1.12 2006/02/28 13:35:14 roboos -% added column-wise normalization for leadfield -% -% Revision 1.11 2006/02/14 09:42:31 roboos -% added a snippet of code to support forward computations using the Neuromag meg-calc toolbox -% -% Revision 1.10 2006/01/20 09:41:49 roboos -% changed assignment of sens.pnt (add structure field to existing double) according to matlab 7.1. recommendation (prevents warning) -% -% Revision 1.9 2005/11/16 09:56:17 roboos -% added a semicolon to prevent output on screen -% -% Revision 1.8 2005/11/08 11:05:14 roboos -% added support for normalize and reducerank as additional options (using key-value varargin) -% -% Revision 1.7 2005/07/29 07:19:47 roboos -% improved detection of meg data (ismeg if has ori and pos) -% -% Revision 1.6 2005/06/08 16:35:15 roboos -% corrected the check for the number of spheres in the grad and volume -% -% Revision 1.5 2005/02/21 08:01:19 roboos -% removed spaces at the end of line, no code changes -% -% Revision 1.4 2005/02/08 11:59:14 roboos -% added an extra check on the input -% -% Revision 1.3 2004/10/25 16:20:13 roboos -% fixed bug in selection of electrode positions from sens structure -% -% Revision 1.2 2004/09/21 15:31:51 roboos -% renamed grad into sens -% -% Revision 1.1 2004/08/19 08:18:20 roboos -% new implementations, generalized for EEG and MEG -% - -persistent warning_issued; - -if iscell(sens) && iscell(vol) && numel(sens)==numel(vol) - % this represents combined EEG and MEG sensors, where each modality has its own volume conduction model - lf = cell(1,numel(sens)); - for i=1:length(sens) - lf{i} = compute_leadfield(pos, sens{i}, vol{i}, varargin{:}); - end - lf = cat(1, lf{:}); - return; -end - -if ~isstruct(sens) && size(sens,2)==3 - % definition of electrode positions only, restructure it - sens = struct('pnt', sens); -end - -% determine whether it is EEG or MEG -iseeg = senstype(sens, 'eeg'); -ismeg = senstype(sens, 'meg'); - -% get the optional input arguments -reducerank = keyval('reducerank', varargin); if isempty(reducerank), reducerank = 'no'; end -normalize = keyval('normalize' , varargin); if isempty(normalize ), normalize = 'no'; end -normalizeparam = keyval('normalizeparam', varargin); if isempty(normalizeparam ), normalizeparam = 0.5; end - -% multiple dipoles can be represented either as a 1x(N*3) vector or as a -% as a Nx3 matrix, i.e. [x1 y1 z1 x2 y2 z2] or [x1 y1 z1; x2 y2 z2] -Ndipoles = numel(pos)/3; -if all(size(pos)==[1 3*Ndipoles]) - pos = reshape(pos, 3, Ndipoles)'; -end - -if isfield(vol, 'unit') && isfield(sens, 'unit') && ~strcmp(vol.unit, sens.unit) - error('inconsistency in the units of the volume conductor and the sensor array'); -end - -if ismeg && iseeg - % this is something that could be implemented relatively easily - error('simultaneous EEG and MEG not supported'); - -elseif ~ismeg && ~iseeg - error('the input does not look like EEG, nor like MEG'); - -elseif ismeg - switch voltype(vol) - - case 'singlesphere' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % MEG single-sphere volume conductor model - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - pnt = sens.pnt; % position of each coil - ori = sens.ori; % orientation of each coil - - if isfield(vol, 'o') - % shift dipole and magnetometers to origin of sphere - pos = pos - repmat(vol.o, Ndipoles, 1); - pnt = pnt - repmat(vol.o, size(pnt,1), 1); - end - - if Ndipoles>1 - % loop over multiple dipoles - lf = zeros(size(pnt,1),3*Ndipoles); - for i=1:Ndipoles - lf(:,(3*i-2):(3*i)) = meg_leadfield1(pos(i,:), pnt, ori); - end - else - % only single dipole - lf = meg_leadfield1(pos, pnt, ori); - end - - if isfield(sens, 'tra') - % this appears to be the modern complex gradiometer definition - % construct the channels from a linear combination of all magnetometers - lf = sens.tra * lf; - end - - case 'multisphere' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % MEG multi-sphere volume conductor model - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - ncoils = length(sens.pnt); - - if size(vol.r, 1)~=ncoils - error('number of spheres is not equal to the number of coils') - end - - if size(vol.o, 1)~=ncoils - error('number of spheres is not equal to the number of coils'); - end - - lf = zeros(ncoils, 3*Ndipoles); - for chan=1:ncoils - for dip=1:Ndipoles - % shift dipole and magnetometer coil to origin of sphere - dippos = pos(dip,:) - vol.o(chan,:); - chnpos = sens.pnt(chan,:) - vol.o(chan,:); - tmp = meg_leadfield1(dippos, chnpos, sens.ori(chan,:)); - lf(chan,(3*dip-2):(3*dip)) = tmp; - end - end - - if isfield(sens, 'tra') - % this appears to be the modern complex gradiometer definition - % construct the channels from a linear combination of all magnetometers - lf = sens.tra * lf; - end - - case 'neuromag' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % use external Neuromag toolbox for forward computation - % this requires that "megmodel" is initialized, which is done in PREPARE_VOL_SENS - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % compute the forward model for all channels - % tmp1 = ones(1, Ndipoles); - % tmp2 = 0.01*pos'; %convert to cm - % lf = megfield([tmp2 tmp2 tmp2],[[1 0 0]'*tmp1 [0 1 0]'*tmp1 [0 0 1]'*tmp1]); - for dip=1:Ndipoles - R = 0.01*pos(i,:)'; % convert from cm to m - Qx = [1 0 0]; - Qy = [0 1 0]; - Qz = [0 0 1]; - lf(:,(3*(dip-1)+1)) = megfield(R, Qx); - lf(:,(3*(dip-1)+2)) = megfield(R, Qy); - lf(:,(3*(dip-1)+3)) = megfield(R, Qz); - end - % select only those channels from the forward model that are part of the gradiometer definition - lf = lf(vol.chansel,:); - - case 'nolte' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % use code from Guido Nolte for the forward computation - % this requires that "meg_ini" is initialized, which is done in PREPARE_VOL_SENS - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % the dipole position and orientation should be combined in a single matrix - % furthermore, here I want to compute the leadfield for each of the - % orthogonzl x/y/z directions - dippar = zeros(Ndipoles*3, 6); - for i=1:Ndipoles - dippar((i-1)*3+1,:) = [pos(i,:) 1 0 0]; % single dipole, x-orientation - dippar((i-1)*3+2,:) = [pos(i,:) 0 1 0]; % single dipole, y-orientation - dippar((i-1)*3+3,:) = [pos(i,:) 0 0 1]; % single dipole, z-orientation - end - % compute the leadfield for each individual coil - lf = meg_forward(dippar,vol.forwpar); - if isfield(sens, 'tra') - % compute the leadfield for each gradiometer (linear combination of coils) - lf = sens.tra * lf; - end - - case 'infinite' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % magnetic dipole instead of electric (current) dipole in an infinite vacuum - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - if isempty(warning_issued) - % give the warning only once - warning('assuming magnetic dipole in an infinite vacuum'); - warning_issued = 1; - end - - pnt = sens.pnt; % position of each coil - ori = sens.ori; % orientation of each coil - - if Ndipoles>1 - % loop over multiple dipoles - lf = zeros(size(pnt,1),3*Ndipoles); - for i=1:Ndipoles - lf(:,(3*i-2):(3*i)) = magnetic_dipole(pos(i,:), pnt, ori); - end - else - % only single dipole - lf = magnetic_dipole(pos, pnt, ori); - end - - if isfield(sens, 'tra') - % construct the channels from a linear combination of all magnetometer coils - lf = sens.tra * lf; - end - - otherwise - error('unsupported volume conductor model for MEG'); - end % switch voltype for MEG - -elseif iseeg - switch voltype(vol) - - case 'multisphere' - % Based on the approximation of the potential due to a single dipole in - % a multishell sphere by three dipoles in a homogeneous sphere, code - % contributed by Punita Christopher - - Nelec = size(sens.pnt,1); - Nspheres = length(vol.r); - - % the center of the spherical volume conduction model does not have - % to be in the origin, therefore shift the spheres, the electrodes - % and the dipole - if isfield(vol, 'o') - center = vol.o; - else - center = [0 0 0]; - end - - % sort the spheres from the smallest to the largest - % furthermore, the radius should be one (?) - [radii, indx] = sort(vol.r/max(vol.r)); - sigma = vol.c(indx); - r = (sens.pnt-repmat(center, Nelec, 1))./max(vol.r); - pos = pos./max(vol.r); - - if Ndipoles>1 - % loop over multiple dipoles - lf = zeros(Nelec,3*Ndipoles); - for i=1:Ndipoles - rq = pos(i,:) - center; - % compute the potential for each dipole ortientation - % it would be much more efficient to change the punita function - q1 = [1 0 0]; lf(:,(3*i-2)) = multisphere(Nspheres, radii, sigma, r, rq, q1); - q1 = [0 1 0]; lf(:,(3*i-1)) = multisphere(Nspheres, radii, sigma, r, rq, q1); - q1 = [0 0 1]; lf(:,(3*i )) = multisphere(Nspheres, radii, sigma, r, rq, q1); - end - else - % only single dipole - lf = zeros(Nelec,3); - rq = pos - center; - % compute the potential for each dipole ortientation - % it would be much more efficient to change the punita function - q1 = [1 0 0] ; lf(:,1) = multisphere(Nspheres, radii, sigma, r, rq, q1); - q1 = [0 1 0] ; lf(:,2) = multisphere(Nspheres, radii, sigma, r, rq, q1); - q1 = [0 0 1] ; lf(:,3) = multisphere(Nspheres, radii, sigma, r, rq, q1); - end - - case {'singlesphere', 'concentric'} - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % EEG spherical volume conductor model - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - % FIXME, this is not consistent between spherical and BEM - % sort the spheres from the smallest to the largest - [vol.r, indx] = sort(vol.r); - vol.c = vol.c(indx); - - Nspheres = length(vol.c); - if length(vol.r)~=Nspheres - error('the number of spheres in the volume conductor model is ambiguous'); - end - - if isfield(vol, 'o') - % shift the origin of the spheres, electrodes and dipole - sens.pnt = sens.pnt - repmat(vol.o, size(sens.pnt,1), 1); - pos = pos - repmat(vol.o, Ndipoles, 1); - end - - if Nspheres==1 - if Ndipoles>1 - % loop over multiple dipoles - lf = zeros(size(sens.pnt,1),3*Ndipoles); - for i=1:Ndipoles - lf(:,(3*i-2):(3*i)) = eeg_leadfield1(pos(i,:), sens.pnt, vol); - end - else - % only single dipole - lf = eeg_leadfield1(pos, sens.pnt, vol); - end - - elseif Nspheres==2 - vol.r = [vol.r(1) vol.r(2) vol.r(2) vol.r(2)]; - vol.c = [vol.c(1) vol.c(2) vol.c(2) vol.c(2)]; - if Ndipoles>1 - % loop over multiple dipoles - lf = zeros(size(sens.pnt,1),3*Ndipoles); - for i=1:Ndipoles - lf(:,(3*i-2):(3*i)) = eeg_leadfield4(pos(i,:), sens.pnt, vol); - end - else - % only single dipole - lf = eeg_leadfield4(pos, sens.pnt, vol); - end - - elseif Nspheres==3 - vol.r = [vol.r(1) vol.r(2) vol.r(3) vol.r(3)]; - vol.c = [vol.c(1) vol.c(2) vol.c(3) vol.c(3)]; - if Ndipoles>1 - % loop over multiple dipoles - lf = zeros(size(sens.pnt,1),3*Ndipoles); - for i=1:Ndipoles - lf(:,(3*i-2):(3*i)) = eeg_leadfield4(pos(i,:), sens.pnt, vol); - end - else - % only single dipole - lf = eeg_leadfield4(pos, sens.pnt, vol); - end - - elseif Nspheres==4 - if Ndipoles>1 - % loop over multiple dipoles - lf = zeros(size(sens.pnt,1),3*Ndipoles); - for i=1:Ndipoles - lf(:,(3*i-2):(3*i)) = eeg_leadfield4(pos(i,:), sens.pnt, vol); - end - else - % only single dipole - lf = eeg_leadfield4(pos, sens.pnt, vol); - end - - else - error('more than 4 concentric spheres are not supported'); - end - - case {'bem', 'dipoli', 'asa', 'avo', 'bemcp', 'openmeeg'} - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % EEG boundary element method volume conductor model - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - lf = eeg_leadfieldb(pos, sens.pnt, vol); - - case 'infinite' - % the conductivity of the medium is not known - if isempty(warning_issued) - % give the warning only once - warning('assuming electric dipole in an infinite medium with unit conductivity'); - warning_issued = 1; - end - lf = inf_medium_leadfield(pos, sens.pnt, 1); - - otherwise - error('unsupported volume conductor model for EEG'); - end % switch voltype for EEG - - % compute average reference for EEG leadfield - avg = mean(lf, 1); - lf = lf - repmat(avg, size(lf,1), 1); - -end % iseeg or ismeg - -% optionally apply leadfield rank reduction -if ~strcmp(reducerank, 'no') && reducerank0 - lf = lf ./ nrm; - end -elseif strcmp(normalize, 'column') - % normalize each column of the leadfield by its norm - for j=1:size(lf,2) - nrm = sum(lf(:,j).^2)^normalizeparam; - lf(:,j) = lf(:,j)./nrm; - end -end diff --git a/external/fieldtrip/private/constructplanargrad.m b/external/fieldtrip/private/constructplanargrad.m index 1fd88b7..37137b9 100644 --- a/external/fieldtrip/private/constructplanargrad.m +++ b/external/fieldtrip/private/constructplanargrad.m @@ -30,26 +30,23 @@ % Copyright (C) 2004, Robert Oostenveld % -% $Log: constructplanargrad.m,v $ -% Revision 1.1 2006/01/30 14:22:00 roboos -% renamed axial2planar into constructplanargrad, updated help +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.1 2004/06/28 08:59:38 roboos -% moved files from fieldtrip to fieldtrip/private +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.3 2004/04/13 16:31:08 roberto -% fixed bug in dbstack selection of function filename for Matlab 6.1 +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.2 2004/04/13 14:25:24 roberto -% wrapped code-snippet around mfilename to make it compatible with Matlab 6.1 -% -% Revision 1.1 2004/04/06 20:25:04 roberto -% new implementation, initially used only for testing of planar -% gradient computation in MEGPLANAR and MEGINTERPOLATE with forward -% simulated data, but now also in use as one of the methods in -% MEGPLANAR to compute the planar gradient in real data using a -% distributed source inward-outward projection. +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: constructplanargrad.m 952 2010-04-21 18:29:51Z roboos $ if ~isfield(cfg, 'planaraxial'), cfg.planaraxial = 'yes'; end if ~isfield(cfg, 'baseline_axial'), cfg.baseline_axial = 5; end @@ -178,6 +175,6 @@ [st, i] = dbstack; cfg.version.name = st(i); end -cfg.version.id = '$Id: constructplanargrad.m,v 1.1 2006/01/30 14:22:00 roboos Exp $'; +cfg.version.id = '$Id: constructplanargrad.m 952 2010-04-21 18:29:51Z roboos $'; planar.cfg = cfg; diff --git a/external/fieldtrip/private/continuous_ns.m b/external/fieldtrip/private/continuous_ns.m new file mode 100644 index 0000000..7b3214d --- /dev/null +++ b/external/fieldtrip/private/continuous_ns.m @@ -0,0 +1,27 @@ +function [trl] = continuous_ns(cfg) + +% CONTINUOUS_NS created a trial definition from a Neuroscan *.cnt file +% which subsequently can be used in the EEG/MEG framework +% +% Use as +% [trl] = continuous_ns(cfg) +% +% where the configuration should contain +% cfg.trialdef.trigger = number or list with triggers +% cfg.trialdef.prestim = pre-stimulus in seconds +% cfg.trialdef.poststim = post-stimulus in seconds +% +% See also SINGLETRIAL_NS + +% Copyright (C) 2003, Robert Oostenveld + +% read the header and the event table from the continuous file +tmp = read_ns_cnt(cfg.datafile, 'ldheaderonly', 1); +fprintf('found %d events in continuous neuroscan file\n', length(tmp.event.frame)); +eventindx = find(ismember(tmp.event.stimtype, cfg.trialdef.trigger)); +trl(:,1) = tmp.event.frame(eventindx) - round(cfg.trialdef.prestim*tmp.rate) + 1; % begin sample +trl(:,2) = tmp.event.frame(eventindx) + round(cfg.trialdef.poststim*tmp.rate) + 1; % end sample +trl(:,3) = -round(cfg.trialdef.prestim*tmp.rate); % offset +fprintf('selected %d events based on triggercode\n', size(trl,1)); + +return diff --git a/external/fieldtrip/private/convert_event.m b/external/fieldtrip/private/convert_event.m new file mode 100644 index 0000000..c598cb6 --- /dev/null +++ b/external/fieldtrip/private/convert_event.m @@ -0,0 +1,249 @@ +function [obj] = convert_event(obj, target, varargin) + +% CONVERT_EVENT converts between the different representations of events. +% The representations are: +% event structure (see READ_EVENT) +% matrix representation as in trl (Nx3) or artifact (Nx2), with +% [begsample endsample] (see DEFINETRIAL, ARTIFACT_xxx functions) +% boolean vector representation with 1 for samples containing trial/artifact +% +% Use as +% [object] = convert_event(object, target, ....) +% +% The following input objects are supported: +% event structure +% trl (or cell array of multiple trl definitions) +% artifact (or cell array of multiple artifact definitions) +% boolean vector (or matrix of multiple vectors) +% +% Possible targets are 'event', 'trl', 'artifact', 'boolvec' +% +% Additional options should be specified in key-value pairs and can be +% 'endsample' +% 'typenames' +% +% See READ_EVENT, DEFINETRIAL, REJECTARTIFACT, ARTIFACT_xxx + +% Copyright (C) 2009, Ingrid Nieuwenhuis +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id$ + +% Check if target is specified correctly +if sum(strcmp(target, {'event', 'trl', 'artifact', 'boolvec'})) < 1 + error('target has to be ''event'', ''trl'', ''artifact'', or ''boolvec''.') +end + +% Get the options +endsample = keyval('endsample', varargin); +typenames = keyval('typenames', varargin); + +% Determine what the input object is +if isempty(obj) + input_obj = 'empty'; +elseif isstruct(obj) + input_obj = 'event'; +elseif iscell(obj) + if isempty(obj{1}) + input_obj = 'empty'; + elseif size(obj{1},2) == 3 + input_obj = 'trl'; + elseif size(obj{1},2) == 2 + input_obj = 'artifact'; + elseif size(obj{1},2) > 3 + % could be a strange trl-matrix with multiple columns + input_obj = 'trl'; + for i = 1:length(obj) + obj{i} = obj{i}(:,1:3); + end + else + error('incorrect input object, see help for what is allowed.') + end +elseif islogical(obj) + input_obj = 'boolvec'; +elseif size(obj,2) == 3 + input_obj = 'trl'; +elseif size(obj,2) == 2 + input_obj = 'artifact'; +elseif size(obj,2) > 3 + tmp = unique(obj); + if isempty(find(tmp>2, 1)) + input_obj = 'boolvec'; + obj = logical(obj); + else + %it is at least not boolean but could be a strange + %trl-matrix with multiple columns + input_obj = 'trl'; + obj = obj(:,1:3); + end +else + error('incorrect input object, see help for what is allowed.') +end + +% do conversion +if (strcmp(input_obj, 'trl') || strcmp(input_obj, 'artifact') || strcmp(input_obj, 'empty')) && strcmp(target, 'boolvec') + if ~isempty(endsample) + obj = artifact2artvec(obj,endsample); + else + obj = artifact2artvec(obj); + end +elseif strcmp(input_obj, 'boolvec') && strcmp(target,'artifact' ) + obj = artvec2artifact(obj); +elseif strcmp(input_obj, 'boolvec') && strcmp(target,'trl' ) + obj = artvec2artifact(obj); + if iscell(obj) + for i=1:length(obj) + obj{i}(:,3) = 0; + end + else + obj(:,3) = 0; + end +elseif (strcmp(input_obj, 'trl') || strcmp(input_obj, 'artifact')) && strcmp(target, 'event') + obj = artifact2event(obj, typenames); +elseif strcmp(input_obj, 'artifact') && strcmp(target,'trl') + if iscell(obj) + for i=1:length(obj) + obj{i}(:,3) = 0; + end + else + obj(:,3) = 0; + end +elseif strcmp(input_obj, 'trl') && strcmp(target,'artifact') + if iscell(obj) + for i=1:length(obj) + obj{i}(:,3:end) = []; + end + else + obj(:,3:end) = []; + end +elseif strcmp(input_obj, 'empty') + obj = []; +else + warning('conversion not supported yet') %FIXME +end + + +%%%%%%%%%%%%%%% SUBFUNCTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function artvec = artifact2artvec(varargin) +% ARTIFACT2ARTVEC makes boolian vector (or matrix when artifact is +% cell array of multiple artifact definitions) with 0 for artifact free +% sample and 1 for sample containing an artifact according to artifact +% specification. Length of vector is (from sample 1) last sample as +% defined in the artifact definition, or when datendsample is speciefied +% vector is length datendsample. + +artifact = varargin{1}; +if length(varargin) == 1 + if ~iscell(artifact) % assume only one artifact is given + if isempty(artifact) + error('When input object is empty ''endsample'' must be specified to convert into boolvec') + else + endsample = max(artifact(:,2)); + end + elseif length(artifact) == 1 + if isempty(artifact{1}) + error('When input object is empty ''endsample'' must be specified to convert into boolvec') + else + endsample = max(artifact{1}(:,2)); + end + else + error('when giving multiple artifact definitions, endsample should be specified to assure all output vectors are of the same length') + end +elseif length(varargin) == 2 + endsample = varargin{2}; +elseif length(varargin) > 2 + error('too many input arguments') +end +if ~iscell(artifact) + artifact = {artifact}; +end + +% make artvec +artvec = zeros(length(artifact), endsample); +breakflag = 0; +for i=1:length(artifact) + for j=1:size(artifact{i},1) + artbegsample = artifact{i}(j,1); + artendsample = artifact{i}(j,2); + if artbegsample > endsample + warning('artifact definition contains later samples than endsample, these samples are ignored') + break + elseif artendsample > endsample + warning('artifact definition contains later samples than endsample, these samples are ignored') + artendsample = endsample; + breakflag = 1; + end + artvec(i, artbegsample:artendsample) = 1; + if breakflag + break + end + end +end + +%%%%%%%%%%%%%%% SUBFUNCTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function artifact = artvec2artifact(artvec) +% ARTVEC2ARTIFACT makes artifact definition (or cell array of artifact +% definitions) from boolian vector (or matrix) with [artbegsample +% artendsample]. Assumed is that the artvec starts with sample 1. + +for i=1:size(artvec,1) + tmp = diff([0 artvec(i,:) 0]); + artbeg = find(tmp==+1); + artend = find(tmp==-1) - 1; + artifact{i} = [artbeg' artend']; +end + +if length(artifact) == 1 + artifact = artifact{1}; +end + +%%%%%%%%%%%%%%% SUBFUNCTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function event = artifact2event(artifact, typenames) +% ARTIFACT2EVENT makes event structure from artifact definition (or cell +% array of artifact definitions). event.type is always 'artifact', but +% incase of cellarays of artifacts is is also possible to hand 'typenames' +% with length(artifact) + +if ~iscell(artifact) + artifact = {artifact}; +end + +if ~isempty(typenames) + if length(artifact) ~= length(typenames) + error('length typenames should be the same as length artifact') + end +end + +event = []; +for i=1:length(artifact) + for j=1:size(artifact{i},1) + event(end+1).sample = artifact{i}(j,1); + event(end ).duration = artifact{i}(j,2)-artifact{i}(j,1)+1; + if ~isempty(typenames) + event(end).type = typenames{i}; + elseif size(artifact{i},2) == 2 + event(end).type = 'artifact'; + elseif size(artifact{i},2) == 3 + event(end).type = 'trial'; + end + event(end ).value = []; + event(end ).offset = []; + end +end + + diff --git a/external/fieldtrip/private/convert_units.m b/external/fieldtrip/private/convert_units.m deleted file mode 100644 index eb1366b..0000000 --- a/external/fieldtrip/private/convert_units.m +++ /dev/null @@ -1,217 +0,0 @@ -function [obj] = convert_units(obj, target); - -% CONVERT_UNITS changes the geometrical dimension to the specified SI unit. -% The units of the input object is determined from the structure field -% object.unit, or is estimated based on the spatial extend of the structure, -% e.g. a volume conduction model of the head should be approximately 20 cm large. -% -% Use as -% [object] = convert_units(object, target) -% -% The following input objects are supported -% simple dipole position -% electrode definition -% gradiometer array definition -% volume conductor definition -% dipole grid definition -% anatomical mri -% -% Possible target units are 'm', 'dm', 'cm ' or 'mm'. -% -% See READ_VOL, READ_SENS - -% Copyright (C) 2005-2008, Robert Oostenveld -% -% $Log: convert_units.m,v $ -% Revision 1.8 2009/03/26 14:57:04 roboos -% moved the unit estimation to a seperate function -% -% Revision 1.7 2009/03/11 11:28:24 roboos -% detect as mm for very wide anatomical MRIs (happens at the fcdc with the ctf MRIs) -% -% Revision 1.6 2009/02/05 10:20:35 roboos -% added bemcp as volume type -% -% Revision 1.5 2009/01/08 17:18:45 roboos -% fixed bug mom->pos for source structures -% added unit detection for volumes with a transform and a dim -% -% Revision 1.4 2008/07/21 20:29:22 roboos -% small change in output on screen -% -% Revision 1.3 2008/04/14 20:53:58 roboos -% added detection for headshape and/or fiducials -% fixed bug in scaling of fiducials -% -% Revision 1.2 2008/04/14 19:29:58 roboos -% cleanded up code and added autodetection based on geometrical size of object -% changed interface, no forced input type is possible -% changed from dos to unix -% -% Revision 1.1 2005/03/03 11:01:39 roboos -% already old (and unused) implementation, but sofar this function was not included in CVS -% - -% This function consists of three parts: -% 1) determine the input units -% 2) determine the requested scaling factor to obtain the output units -% 3) try to apply the scaling to the known geometrical elements in the input object - -% determine the unit-of-dimension of the input object -if isfield(obj, 'unit') - % use the units specified in the object - unit = obj.unit; -else - % try to estimate the units from the object - type = voltype(obj); - if ~strcmp(type, 'unknown') - switch type - case 'infinite' - % there is nothing to do to convert the units - unit = target; - - case 'singlesphere' - size = obj.r; - - case 'multisphere' - size = median(obj.r); - - case 'concentric' - size = max(obj.r); - - case 'nolte' - size = norm(range(obj.bnd.pnt)); - - case {'bem' 'dipoli' 'bemcp' 'asa' 'avo'} - size = norm(range(obj.bnd(1).pnt)); - - otherwise - error('cannot determine geometrical units of volume conduction model'); - end % switch - - % determine the units by looking at the size - unit = estimate_units(size); - - elseif senstype(obj, 'meg') - size = norm(range(obj.pnt)); - unit = estimate_units(size); - - elseif senstype(obj, 'eeg') - size = norm(range(obj.pnt)); - unit = estimate_units(size); - - elseif isfield(obj, 'pnt') && ~isempty(obj.pnt) - size = norm(range(obj.pnt)); - unit = estimate_units(size); - - elseif isfield(obj, 'pos') && ~isempty(obj.pos) - size = norm(range(obj.pos)); - unit = estimate_units(size); - - elseif isfield(obj, 'transform') && ~isempty(obj.transform) - % construct the corner points of the voxel grid in head coordinates - xi = 1:obj.dim(1); - yi = 1:obj.dim(2); - zi = 1:obj.dim(3); - pos = [ - xi( 1) yi( 1) zi( 1) - xi( 1) yi( 1) zi(end) - xi( 1) yi(end) zi( 1) - xi( 1) yi(end) zi(end) - xi(end) yi( 1) zi( 1) - xi(end) yi( 1) zi(end) - xi(end) yi(end) zi( 1) - xi(end) yi(end) zi(end) - ]; - pos = warp_apply(obj.transform, pos); - size = norm(range(pos)); - unit = estimate_units(size); - - elseif isfield(obj, 'fid') && isfield(obj.fid, 'pnt') && ~isempty(obj.fid.pnt) - size = norm(range(obj.fid.pnt)); - unit = estimate_units(size); - - else - error('cannot determine geometrical units'); - - end % recognized type of volume conduction model or sensor array -end % determine input units - -if nargin<2 - % just remember the units in the output and return - obj.unit = unit; - return -elseif strcmp(unit, target) - % no conversion is needed - obj.unit = unit; - return -end - -% give some information about the conversion -fprintf('converting units from ''%s'' to ''%s''\n', unit, target) - -if strcmp(unit, 'm') - unit2meter = 1; -elseif strcmp(unit, 'dm') - unit2meter = 0.1; -elseif strcmp(unit, 'cm') - unit2meter = 0.01; -elseif strcmp(unit, 'mm') - unit2meter = 0.001; -end - -% determine the unit-of-dimension of the output object -if strcmp(target, 'm') - meter2target = 1; -elseif strcmp(target, 'dm') - meter2target = 10; -elseif strcmp(target, 'cm') - meter2target = 100; -elseif strcmp(target, 'mm') - meter2target = 1000; -end - -% combine the units into one scaling factor -scale = unit2meter * meter2target; - -% volume conductor model -if isfield(obj, 'r'), obj.r = scale * obj.r; end -if isfield(obj, 'o'), obj.o = scale * obj.o; end -if isfield(obj, 'bnd'), for i=1:length(obj.bnd), obj.bnd(i).pnt = scale * obj.bnd(i).pnt; end, end - -% gradiometer array -if isfield(obj, 'pnt1'), obj.pnt1 = scale * obj.pnt1; end -if isfield(obj, 'pnt2'), obj.pnt2 = scale * obj.pnt2; end -if isfield(obj, 'prj'), obj.prj = scale * obj.prj; end - -% gradiometer array, electrode array, head shape or dipole grid -if isfield(obj, 'pnt'), obj.pnt = scale * obj.pnt; end - -% fiducials -if isfield(obj, 'fid') && isfield(obj.fid, 'pnt'), obj.fid.pnt = scale * obj.fid.pnt; end - -% dipole grid -if isfield(obj, 'pos'), obj.pos = scale * obj.pos; end - -% anatomical MRI or functional volume -if isfield(obj, 'transform'), - H = diag([scale scale scale 1]); - obj.transform = H * obj.transform; -end - -% remember the unit -obj.unit = target; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION -% Use as -% r = range(x) -% or you can also specify the dimension along which to look by -% r = range(x, dim) -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function r = range(x, dim) -if nargin==1 - r = max(x) - min(x); -else - r = max(x, [], dim) - min(x, [], dim); -end diff --git a/external/fieldtrip/private/createsubcfg.m b/external/fieldtrip/private/createsubcfg.m deleted file mode 100644 index c6f0abf..0000000 --- a/external/fieldtrip/private/createsubcfg.m +++ /dev/null @@ -1,177 +0,0 @@ -function [topcfg] = createsubcfg(topcfg, subname); - -% CREATESUBCFG collects the optional arguments for some of the low-level -% functions and puts them in a seperate substructure This function is to -% ensure backward compatibility of end-user scripts, fieldtrip functions -% and documentation that do not use the nested detailled configuration -% but that use a flat configuration. -% -% Use as -% cfg = createsubcfg(cfg, 'something') -% which will put all fields related to 'something' into cfg.something -% -% See also KEYVAL2CFG, CFG2KEYVAL - -% Copyright (C) 2006, Robert Oostenveld -% -% $Log: createsubcfg.m,v $ -% Revision 1.9 2008/07/15 19:34:13 roboos -% removed inwardshift from cfg.grid, will have to be reconsidered later -% -% Revision 1.8 2008/07/15 18:18:45 roboos -% added subfield grid -% -% Revision 1.7 2008/07/11 13:18:40 roboos -% removed all lnfilter references, added error to preprocessing and preproc -% -% Revision 1.6 2006/10/12 09:11:43 roboos -% split lcmv and dics, changed keepcsd into keepcov for lcmv -% -% Revision 1.5 2006/10/05 09:58:11 roboos -% removed powmethod for pcc -% -% Revision 1.4 2006/10/02 07:07:04 jansch -% added realfilter-option in beamformer-cfg -% -% Revision 1.3 2006/08/31 08:47:18 roboos -% added filter direction for preproc -% -% Revision 1.2 2006/06/22 12:29:42 roboos -% changed numcomponents into numcomponent for music -% -% Revision 1.1 2006/06/14 11:49:08 roboos -% new implementation, replaces construct_optarg in sourceanalysis and is now also used for cfg.preproc -% - -if isfield(topcfg, subname) - % get the options that are already specified in the substructure - subcfg = getfield(topcfg, subname); -else - % start with an empty substructure - subcfg = []; -end - -% add all other relevant options to the substructure -switch subname - case 'preproc' - fieldname = { - 'reref' - 'refchannel' - 'implicitref' - 'detrend' - 'blc' - 'blcwindow' - 'bpfiltdir' - 'bpfilter' - 'bpfiltord' - 'bpfilttype' - 'bpfreq' - 'bsfiltdir' - 'bsfilter' - 'bsfiltord' - 'bsfilttype' - 'bsfreq' - 'dftfilter' - 'dftfreq' - 'hpfiltdir' - 'hpfilter' - 'hpfiltord' - 'hpfilttype' - 'hpfreq' - 'lpfiltdir' - 'lpfilter' - 'lpfiltord' - 'lpfilttype' - 'lpfreq' - 'medianfilter' - 'medianfiltord' - 'hilbert' - 'derivative' - 'rectify' - 'boxcar' - 'absdiff' - }; - - case 'grid' - fieldname = { - 'xgrid' - 'ygrid' - 'zgrid' - 'resolution' - 'filter' - 'leadfield' - 'inside' - 'outside' - 'pos' - 'dim' - 'tight' - }; - - case 'dics' - fieldname = { - 'feedback' - 'keepfilter' - 'keepmom' - 'lambda' - 'normalize' - 'powmethod' - 'projectnoise' - 'reducerank' - 'keepcsd' - 'realfilter' - }; - - case 'lcmv' - fieldname = { - 'feedback' - 'keepfilter' - 'keepmom' - 'lambda' - 'normalize' - 'powmethod' - 'projectnoise' - 'reducerank' - 'keepcov' - }; - - case 'pcc' - fieldname = { - 'feedback' - 'keepfilter' - 'keepmom' - 'lambda' - 'normalize' -% 'powmethod' - 'projectnoise' - 'reducerank' - 'keepcsd' - 'realfilter' - }; - - case {'mne', 'loreta', 'rv'} - fieldname = { - 'feedback' - }; - - case 'music' - fieldname = { - 'feedback' - 'numcomponent' - }; - - otherwise - error('unexpected name of the subfunction'); - fieldname = {}; - -end % switch subname - -for i=1:length(fieldname) - if ~isfield(subcfg, fieldname{i}) && isfield(topcfg, fieldname{i}) - subcfg = setfield(subcfg, fieldname{i}, getfield(topcfg, fieldname{i})); % set it in the subconfiguration - topcfg = rmfield(topcfg, fieldname{i}); % remove it in the main configuration - end -end - -% copy the substructure back into the main configuration structure -topcfg = setfield(topcfg, subname, subcfg); - diff --git a/external/fieldtrip/private/crosshair.m b/external/fieldtrip/private/crosshair.m index fae633b..476d4b7 100644 --- a/external/fieldtrip/private/crosshair.m +++ b/external/fieldtrip/private/crosshair.m @@ -10,18 +10,31 @@ % Copyright (C) 2003, Robert Oostenveld % -% $Log: crosshair.m,v $ -% Revision 1.2 2003/03/17 10:37:28 roberto -% improved general help comments and added copyrights +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: crosshair.m 952 2010-04-21 18:29:51Z roboos $ border = axis; -x = [ border(1) pos(1) - border(2) pos(1) ]; +x = [ border(1) pos(1) + border(2) pos(1) ]; -y = [ pos(2) border(3) - pos(2) border(4) ]; +y = [ pos(2) border(3) + pos(2) border(4) ]; if (~ishold) hold on diff --git a/external/fieldtrip/private/cstructdecode.m b/external/fieldtrip/private/cstructdecode.m index ff8e289..efe6388 100644 --- a/external/fieldtrip/private/cstructdecode.m +++ b/external/fieldtrip/private/cstructdecode.m @@ -6,21 +6,23 @@ % Copyright (C) 2007, Robert Oostenveld % -% $Log: cstructdecode.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.2 2008/02/18 13:36:40 roboos -% added single and double +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.1 2007/12/18 16:14:38 roboos -% new implementation +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: cstructdecode.m 945 2010-04-21 17:41:20Z roboos $ if ~isa(buf, 'uint8') error('incorrect type of input data, should be uint8'); diff --git a/external/fieldtrip/private/ctf2grad.m b/external/fieldtrip/private/ctf2grad.m index 7a8138d..384e77a 100644 --- a/external/fieldtrip/private/ctf2grad.m +++ b/external/fieldtrip/private/ctf2grad.m @@ -13,52 +13,23 @@ % Copyright (C) 2004, Robert Oostenveld % -% $Log: ctf2grad.m,v $ -% Revision 1.4 2009/08/05 08:36:57 roboos -% preallocate the memory that will hold the coil positions, orientations and weights -> significant speedup +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.3 2009/03/23 21:16:03 roboos -% don't give error if balancing fails, but only warning and remove the balancing information +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.2 2009/02/04 13:29:03 roboos -% deal with missing BalanceCoefs in the file using try-catch and isfield (e.g. ArtifactMEG.ds) +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.6 2008/06/26 15:32:19 roboos -% balancing shoudl be subtracted from orig channel, hence added minus sign -% -% Revision 1.5 2008/05/20 12:24:14 roboos -% apply optional balancing to grad.tra -% -% Revision 1.4 2008/05/15 15:11:40 roboos -% add balancing coefficients to the gradiometer definition -% -% Revision 1.3 2008/05/15 13:21:13 roboos -% merged nihm impleemntation into this function -% added new implementation based on CTF p-files -% -% Revision 1.2 2007/03/07 08:57:32 roboos -% use the numeric sensor type for MEG and REF instead of hdr.rowMEG and hdr.rowREF -% -% Revision 1.1 2006/08/31 13:32:11 roboos -% moved from fieldtrip to fileio module -% -% Revision 1.2 2005/06/01 07:59:37 roboos -% added second argument which optionally causes the gradient information to be returend in dewar coordinates -% -% Revision 1.1 2005/05/26 09:55:17 roboos -% renamed the fileio/ctf_grad function to ctf2grad and moved it into fieldtrip/private for consistency with other gradiometer construction functions (nimh2grad and fif2grad) -% -% Revision 1.1 2004/07/02 11:33:47 roboos -% new function that creates a more complete gradiometer definition from the res4 header (compared to read_ctf_res4) +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: ctf2grad.m 1058 2010-05-09 11:21:10Z roboos $ % My preferred ordering in the grad structure is: % 1st 151 coils are bottom coils of MEG channels @@ -173,7 +144,7 @@ grad.label = label([selMEG selREF]); grad.unit = 'cm'; - % convert the balancing coefficients into a montage that can be used with the apply_montage function + % convert the balancing coefficients into a montage that can be used with the ft_apply_montage function if isfield(hdr.BalanceCoefs, 'G1BR') meglabel = label(hdr.BalanceCoefs.G1BR.MEGlist); reflabel = label(hdr.BalanceCoefs.G1BR.Refindex); @@ -207,6 +178,17 @@ grad.balance.G3BR = montage; end + if isfield(hdr.BalanceCoefs, 'G3AR') + meglabel = label(hdr.BalanceCoefs.G3AR.MEGlist); + reflabel = label(hdr.BalanceCoefs.G3AR.Refindex); + nmeg = length(meglabel); + nref = length(reflabel); + montage.labelorg = cat(1, meglabel, reflabel); + montage.labelnew = cat(1, meglabel, reflabel); + montage.tra = [eye(nmeg, nmeg), -hdr.BalanceCoefs.G3AR.alphaMEG'; zeros(nref, nmeg), eye(nref, nref)]; + grad.balance.G3AR = montage; + end + if all([hdr.res4.senres(selMEG).grad_order_no]==0) grad.balance.current = 'none'; elseif all([hdr.res4.senres(selMEG).grad_order_no]==1) @@ -215,6 +197,8 @@ grad.balance.current = 'G2BR'; elseif all([hdr.res4.senres(selMEG).grad_order_no]==3) grad.balance.current = 'G3BR'; + elseif all([hdr.res4.senres(selMEG).grad_order_no]==13) + grad.balance.current = 'G3AR'; else warning('cannot determine balancing of CTF gradiometers'); grad = rmfield(grad, 'balance'); @@ -223,7 +207,7 @@ % sofar the gradiometer definition was the ideal, non-balenced one if isfield(grad, 'balance') && ~strcmp(grad.balance.current, 'none') % apply the current balancing parameters to the gradiometer definition - grad = apply_montage(grad, getfield(grad.balance, grad.balance.current)); + grad = ft_apply_montage(grad, getfield(grad.balance, grad.balance.current)); end diff --git a/external/fieldtrip/private/data2raw.m b/external/fieldtrip/private/data2raw.m index be9b643..f54b427 100644 --- a/external/fieldtrip/private/data2raw.m +++ b/external/fieldtrip/private/data2raw.m @@ -8,26 +8,23 @@ % Copyright (C) 2005, Robert Oostenveld % -% $Log: data2raw.m,v $ -% Revision 1.6 2007/05/16 12:43:31 roboos -% changed a print statement +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.5 2007/01/17 17:04:17 roboos -% added support for lcmv beamed timecourses, only inside voxels after projectmom +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.4 2006/02/01 12:26:04 roboos -% made all uses of dimord consistent with the common definition of data dimensions, see the fixdimord() function +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.3 2005/06/03 07:02:48 roboos -% fixed error for empty dimord in case of raw input data (it should return immediately) -% -% Revision 1.2 2005/06/02 16:00:33 roboos -% removed average from the output structure -% -% Revision 1.1 2005/06/02 12:14:10 roboos -% new implementation for consistent conversion of averaged data (with either keepsubject or keepindividual) to raw trials as they come out of preprocessing -% these two helper functions are from now on used in freqanalysis, megplanar, megrealign, megrepair and in combineplanar +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: data2raw.m 952 2010-04-21 18:29:51Z roboos $ % determine the type of input data if isfield(data, 'label') && ~isfield(data, 'avg') && isfield(data, 'trial') && iscell(data.trial) diff --git a/external/fieldtrip/private/databrowser.m b/external/fieldtrip/private/databrowser.m deleted file mode 100644 index 33cb107..0000000 --- a/external/fieldtrip/private/databrowser.m +++ /dev/null @@ -1,1061 +0,0 @@ -function [cfg] = databrowser(cfg, data) - -% DATABROWSER can be used for visual inspection of data. Artifacts detected -% by FieldTrip artifact functions are marked. Data pieces can be marked as -% artifact by manual selection as well. -% -% Use as -% cfg = databrowser(cfg) -% with the cfg as obtained from DEFINETRIAL, or as -% cfg = databrowser(cfg, data) -% with the data as obtained from PREPROCESSING -% -% The following configuration options are supported: -% cfg.dataset = -% cfg.trl = -% cfg.continuous = 'yes' or 'no' -% cfg.channel = cell-array with channel labels, see CHANNELSELECTION -% cfg.zscale = [zmin zmax] or 'auto' (default = 'auto') -% cfg.blocksize = number (in seconds), only aplicable if data contains only 1 (long) trial -% cfg.artfctdef.xxx.artifact = Nx2 matrix with artifact segments -% cfg.viewmode = string, 'butterfly', 'vertical', 'component' (default = 'butterfly') -% cfg.selectfeature = string, name of feature to be selected/added (default = 'visual') -% cfg.selectmode = string, what to do with a selection, can be 'joint', 'individual', 'multiplot', 'topoplot-avg', 'topoplot-pow' (default = 'joint') -% cfg.colorgroups = 'sequential' 'labelcharx' (x = xth character in label), 'chantype' or -% vector with lenght(data/hdr.label) defining groups (default = 'sequential') -% cfg.channelcolormap = COLORMAP (default = customized lines map with 15 colors) -% -% See also PREPROCESSING - -% Copyright (C) 2009, Robert Oostenveld, Ingrid Niewenhuis -% -% $Log: databrowser.m,v $ -% Revision 1.24 2009/10/18 19:46:39 ingnie -% fixed bug -% -% Revision 1.23 2009/10/18 12:41:37 ingnie -% Added options colorgroups and linescolormap (does not work yer in butterfly mode, probably due to closerequestFcn). -% Changed name of channame button into identify. -% Minor changes in comments and white space. -% -% Revision 1.22 2009/10/09 15:27:12 ingnie -% added button to identify channel in butterfly viewmode -% -% Revision 1.21 2009/10/08 10:02:06 ingnie -% fixed bug when no cfg.eventfile, thanks to Steven for reporting -% -% Revision 1.20 2009/10/07 13:51:38 roboos -% allow for maxmin as vertical scale -% implemented drawing of events (sofar only in butterfly view mode) -% -% Revision 1.19 2009/10/01 07:59:52 ingnie -% 11 iso 10 xticks (devides time into 10 steps). redraw after feature selection -% -% Revision 1.18 2009/09/30 15:27:59 ingnie -% added button(=also legend) for artifacts/features. Make sure current feature is always plotted on top -% -% Revision 1.17 2009/09/30 09:48:00 ingnie -% opt.ftsel look at cfg.selectfeature, not just 1. fixed behavior scrolling through channels -> always keep same number of channels displayed. same spaces in code and fixed some typos in comment -% -% Revision 1.16 2009/09/28 11:17:11 giopia -% informative xtick in viewmode vertical. Check nticks and sprintf precision -% -% Revision 1.15 2009/09/24 12:11:55 ingnie -% return opt to guidata after selecting other artifact type (by typing number on keyboard) -% -% Revision 1.14 2009/09/24 11:45:28 ingnie -% added some comment, deleted set xtick in viewmode vertical to make x-axis appear -% -% Revision 1.13 2009/09/24 08:43:08 giopia -% fixed bug in selectmode: begsample -> begsel, endsample -> endsel -% -% Revision 1.12 2009/08/05 14:16:53 roboos -% added various options for selectmode -% -% Revision 1.11 2009/08/05 09:14:58 roboos -% fixed problem with zscale=auto when all data was negative -% -% Revision 1.10 2009/08/05 08:58:54 roboos -% changed the order of the input arguments to plot_topo from (val, x, y) into (x, y, val) -% -% Revision 1.9 2009/08/05 08:26:41 roboos -% if not continuous, keep the original data segments and don't display the horizontal zoom -% if continuous, use the label 'segment', other 'trial' -% give more information in figure title -% implemented preprocessing of data, use cfg.preproc -% added cfg.viewmode for external specification of visualisation method -% various bug fixes ans speed improvements -% -% Revision 1.8 2009/08/04 16:15:35 roboos -% removed settings uicontrol elements and button -% converted trial/channel/horizontal/vertical from text label into pushbutton with input dialog -% -% Revision 1.7 2009/08/04 13:37:00 ingnie -% renamed cfg.selectbehaviour into selectmode (consistent with viewmode) -% fixed bug in displaying of multiple artifacts in a single trial for viewmode=vertical -% -% Revision 1.6 2009/08/04 11:59:06 roboos -% first attempt to add some buttons to the figure and to toggle between the setting and the normal display -% -% Revision 1.5 2009/08/03 20:49:28 roboos -% some improvements for channelselection when reading data fromk disk -% -% Revision 1.4 2009/08/03 18:28:44 roboos -% started with implementation viewmode=component/layout/vertical/butterfly -% many small changes -% -% Revision 1.3 2009/08/03 10:55:43 roboos -% restructured the main function (order in which figure and opt are constructed), added multiplotER feature -% -% Revision 1.2 2009/08/03 08:30:17 ingnie -% replaced the initial version of Giovanni with another databrowser that Ingrid and Robert implemented. The newer one already has more functionality, like adding/removing artifacts and horizontal and vertical zooming -% - -fieldtripdefs - -if nargin>1 - data = checkdata(data, 'datatype', {'raw', 'comp'}, 'feedback', 'yes'); -else - % check if the input cfg is valid for this function - cfg = checkconfig(cfg, 'dataset2files', {'yes'}); - cfg = checkconfig(cfg, 'required', {'headerfile', 'datafile'}); - cfg = checkconfig(cfg, 'renamed', {'datatype', 'continuous'}); - cfg = checkconfig(cfg, 'renamedval', {'continuous', 'continuous', 'yes'}); -end - -% set the defaults -if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end -if ~isfield(cfg, 'continuous'), cfg.continuous = 'no'; end % only for reading from file -if ~isfield(cfg, 'zscale'), cfg.zscale = 'auto'; end -if ~isfield(cfg, 'artfctdef'), cfg.artfctdef = struct; end -if ~isfield(cfg, 'selectfeature'), cfg.selectfeature = 'visual'; end % string or cell-array -if ~isfield(cfg, 'selectmode'), cfg.selectmode = 'joint'; end % joint or individual -if ~isfield(cfg, 'viewmode'), cfg.viewmode = 'butterfly'; end % butterfly, vertical, component, settings -if ~isfield(cfg, 'blocksize'), cfg.blocksize = 1; end % only for segmenting continuous data, i.e. one long trial -if ~isfield(cfg, 'preproc'), cfg.preproc = []; end % see preproc for options -if ~isfield(cfg, 'eventfile'), cfg.eventfile = []; end -if ~isfield(cfg, 'colorgroups'), cfg.colorgroups = 'sequential'; end -lines_color = [0.75 0 0;0 0 1;0 1 0;0.44 0.19 0.63;0 0.13 0.38;0.5 0.5 0.5;1 0.75 0;1 0 0;0.89 0.42 0.04;0.85 0.59 0.58;0.57 0.82 0.31;0 0.69 0.94;1 0 0.4;0 0.69 0.31;0 0.44 0.75]; -if ~isfield(cfg, 'channelcolormap'), cfg.channelcolormap = lines_color; end - - -if ischar(cfg.selectfeature) - % ensure that it is a cell array - cfg.selectfeature = {cfg.selectfeature}; -end - -if nargin>1 - % read or create the layout that will be used for plotting - cfg.layout = prepare_layout(cfg, data); -else - % read or create the layout that will be used for plotting - cfg.layout = prepare_layout(cfg); -end - -% get some initial parameters from the data -if nargin>1 - % fetch the header - hdr = fetch_header(data); - - % fetch the events - event = fetch_event(data); - - cfg.channel = channelselection(cfg.channel, data.label); - chansel = match_str(data.label, cfg.channel); - fsample = 1/(data.time{1}(2)-data.time{1}(1)); - Nchans = length(chansel); - - % this is how the input data is segmented - trlorg = findcfg(data.cfg, 'trl'); - Ntrials = size(trlorg, 1); - -else - % read the header - hdr = read_header(cfg.headerfile, 'headerformat', cfg.headerformat); - - % read the events - if ~isempty(cfg.eventfile) - event = read_event(cfg.eventfile); - else - event = []; - end - - % this option relates to reading over trial boundaries in a pseudo-continuous dataset - if ~isfield(cfg, 'continuous') - if hdr.nTrials==1 - cfg.continuous = 'yes'; - else - cfg.continuous = 'no'; - end - end - - if ~isfield(cfg, 'trl') - % treat the data as continuous if possible, otherwise define all trials as indicated in the header - if strcmp(cfg.continuous, 'yes') - trl = zeros(1, 3); - trl(1,1) = 1; - trl(1,2) = hdr.nSamples*hdr.nTrials; - trl(1,3) = 0; - else - trl = zeros(hdr.nTrials, 3); - for i=1:hdr.nTrials - trl(i,1) = (i-1)*hdr.nSamples + 1; - trl(i,2) = (i )*hdr.nSamples ; - trl(i,3) = -hdr.nSamplesPre; - end - end - cfg.trl = trl; - end - - cfg.channel = channelselection(cfg.channel, hdr.label); - chansel = match_str(hdr.label, cfg.channel); - fsample = hdr.Fs; - Nchans = length(chansel); - - % this is how the data from file should be segmented - trlorg = cfg.trl; - Ntrials = size(trlorg, 1); -end - -if Nchans == 0 - error('no channels to display'); -end - -if Ntrials == 0 - error('no trials to display'); -end - -% determine coloring of channels -if nargin>1 - labels_all = data.label; -else - labels_all= hdr.label; -end -if size(cfg.channelcolormap,2) ~= 3 - error('cfg.channelcolormap is not valid, size should be Nx3') -end -if isstruct(cfg.colorgroups) - % groups defined by user - if length(labels_all) ~= length(cfg.colorgroups) - error('length(cfg.colorgroups) should be length(data/hdr.label)') - end - R = cfg.channelcolormap(:,1); - G = cfg.channelcolormap(:,2); - B = cfg.channelcolormap(:,3); - chan_colors = [R(cfg.colorgroups(:)) G(cfg.colorgroups(:)) B(cfg.colorgroups(:))]; -elseif strcmp(cfg.colorgroups, 'chantype') - type = chantype(labels_all); - [tmp1 tmp2 cfg.colorgroups] = unique(type); - fprintf('%3d colorgroups were identified\n',length(tmp1)) - R = cfg.channelcolormap(:,1); - G = cfg.channelcolormap(:,2); - B = cfg.channelcolormap(:,3); - chan_colors = [R(cfg.colorgroups(:)) G(cfg.colorgroups(:)) B(cfg.colorgroups(:))]; -elseif strcmp(cfg.colorgroups(1:9), 'labelchar') - % groups determined by xth letter of label - labelchar_num = str2double(cfg.colorgroups(10)); - vec_letters = num2str(zeros(length(labels_all),1)); - for iChan = 1:length(labels_all) - vec_letters(iChan) = labels_all{iChan}(labelchar_num); - end - [tmp1 tmp2 cfg.colorgroups] = unique(vec_letters); - fprintf('%3d colorgroups were identified\n',length(tmp1)) - R = cfg.channelcolormap(:,1); - G = cfg.channelcolormap(:,2); - B = cfg.channelcolormap(:,3); - chan_colors = [R(cfg.colorgroups(:)) G(cfg.colorgroups(:)) B(cfg.colorgroups(:))]; -elseif strcmp(cfg.colorgroups, 'sequential') - % no grouping - chan_colors = lines(length(labels_all)); -else - error('do not understand cfg.colorgroups') -end - -% collect the artifacts that have been detected from cfg.artfctdef.xxx.artifact -artlabel = fieldnames(cfg.artfctdef); -sel = zeros(size(artlabel)); -artifact = cell(size(artlabel)); -for i=1:length(artlabel) - sel(i) = issubfield(cfg.artfctdef, [artlabel{i} '.artifact']); - if sel(i) - artifact{i} = getsubfield(cfg.artfctdef, [artlabel{i} '.artifact']); - num = size(artifact{i}, 1); - if isempty(num) - num = 0; - end - fprintf('detected %3d %s artifacts\n', num, artlabel{i}); - end -end -artifact = artifact(sel==1); -artlabel = artlabel(sel==1); - -for i=1:length(cfg.selectfeature) - if ~any(strcmp(cfg.selectfeature{i}, artlabel)) - artifact = {[], artifact{:}}; - artlabel = {cfg.selectfeature{i}, artlabel{:}}; - end -end - -% make a artdata representing all artifacts in a "raw data" format -datbegsample = min(trlorg(:,1)); -datendsample = max(trlorg(:,2)); -artdat = zeros(length(artifact), datendsample); -for i=1:length(artifact) - for j=1:size(artifact{i},1) - artbegsample = artifact{i}(j,1); - artendsample = artifact{i}(j,2); - artendsample = min(artendsample, datendsample); - artdat(i, artbegsample:artendsample) = 1; - end -end - -artdata = []; -artdata.trial{1} = artdat; % every artifact is a "channel" -artdata.time{1} = offset2time(0, fsample, datendsample); -artdata.label = artlabel; -artdata.fsample = fsample; -artdata.cfg.trl = [1 datendsample 0]; - -if ischar(cfg.zscale) && strcmp(cfg.zscale, 'auto') - if nargin>1 - dat = data.trial{1}(chansel,:); - minval = min(dat(:)); - maxval = max(dat(:)); - cfg.zscale = max(abs(minval), abs(maxval)); - else - cfg.zscale = 1; % FIXME - end -end - -h = figure; -set(h, 'KeyPressFcn', @keyboard_cb); -set(h, 'WindowButtonDownFcn', {@select_range, 'multiple', false, 'xrange', true, 'yrange', false, 'clear', true, 'callback', {@select_range_cb, h}, 'event', 'WindowButtonDownFcn'}); -set(h, 'WindowButtonUpFcn', {@select_range, 'multiple', false, 'xrange', true, 'yrange', false, 'clear', true, 'callback', {@select_range_cb, h}, 'event', 'WindowButtonUpFcn'}); -set(h, 'WindowButtonMotionFcn', {@select_range, 'multiple', false, 'xrange', true, 'yrange', false, 'clear', true, 'callback', {@select_range_cb, h}, 'event', 'WindowButtonMotionFcn'}); - -% opt represents the global data/settings, it should contain -% - the original data, epoched or continuous -% - the artifacts represented as continuous data -% - the redraw_cb settings -% - the preproc settings -% - the select_range_cb settings (also used in keyboard_cb) - -% these elements are stored inside the figure so that the callback routines can modify them -opt = []; -if nargin<2 - opt.orgdata = []; % this means that it will look in opt.cfg.dataset -else - opt.orgdata = data; -end -opt.artdata = artdata; -opt.cfg = cfg; % the configuration of this function, not of the preprocessing -opt.hdr = hdr; -opt.event = event; -opt.trlop = 1; % active trial being displayed -opt.ftsel = find(strcmp(artlabel,cfg.selectfeature)); % current artifact/feature being selected -opt.trlorg = trlorg; -opt.fsample = fsample; -opt.artcol = [0.9686 0.7608 0.7686; 0.7529 0.7098 0.9647; 0.7373 0.9725 0.6824;0.8118 0.8118 0.8118; 0.9725 0.6745 0.4784; 0.9765 0.9176 0.5686]; -opt.chan_colors = chan_colors; -opt.cleanup = false; % this is needed for a corrent handling if the figure is closed (either in the corner or by "q") -if strcmp(cfg.continuous, 'yes') - opt.trialname = 'segment'; -else - opt.trialname = 'trial'; -end -guidata(h, opt); - -% make the user interface elements for the data view -uicontrol('tag', 'group1', 'parent', h, 'units', 'normalized', 'style', 'pushbutton', 'string', opt.trialname, 'userdata', 't') -uicontrol('tag', 'group2', 'parent', h, 'units', 'normalized', 'style', 'pushbutton', 'string', '<', 'userdata', 'leftarrow') -uicontrol('tag', 'group2', 'parent', h, 'units', 'normalized', 'style', 'pushbutton', 'string', '>', 'userdata', 'rightarrow') - -uicontrol('tag', 'group1', 'parent', h, 'units', 'normalized', 'style', 'pushbutton', 'string', 'channel','userdata', 'c') -uicontrol('tag', 'group2', 'parent', h, 'units', 'normalized', 'style', 'pushbutton', 'string', '<', 'userdata', 'uparrow') -uicontrol('tag', 'group2', 'parent', h, 'units', 'normalized', 'style', 'pushbutton', 'string', '>', 'userdata', 'downarrow') - -uicontrol('tag', 'group1a', 'parent', h, 'units', 'normalized', 'style', 'pushbutton', 'string', 'horizontal', 'userdata', 'h') -uicontrol('tag', 'group2a', 'parent', h, 'units', 'normalized', 'style', 'pushbutton', 'string', '-', 'userdata', 'shift+leftarrow') -uicontrol('tag', 'group2a', 'parent', h, 'units', 'normalized', 'style', 'pushbutton', 'string', '+', 'userdata', 'shift+rightarrow') -if strcmp(cfg.continuous, 'no') - uilayout(h, 'tag', 'group1a', 'visible', 'off', 'retag', 'group1'); - uilayout(h, 'tag', 'group2a', 'visible', 'off', 'retag', 'group2'); -else - uilayout(h, 'tag', 'group1a', 'visible', 'on', 'retag', 'group1'); - uilayout(h, 'tag', 'group2a', 'visible', 'on', 'retag', 'group2'); -end - -uicontrol('tag', 'group1', 'parent', h, 'units', 'normalized', 'style', 'pushbutton', 'string', 'vertical', 'userdata', 'v') -uicontrol('tag', 'group2', 'parent', h, 'units', 'normalized', 'style', 'pushbutton', 'string', '-', 'userdata', 'shift+downarrow') -uicontrol('tag', 'group2', 'parent', h, 'units', 'normalized', 'style', 'pushbutton', 'string', '+', 'userdata', 'shift+uparrow') - -% legend artifacts/features -for iArt = 1:length(artlabel) - uicontrol('tag', 'group3', 'parent', h, 'units', 'normalized', 'style', 'pushbutton', 'string', artlabel{iArt}, 'userdata', num2str(iArt), 'position', [0.91, 0.9 - ((iArt-1)*0.1), 0.08, 0.05], 'backgroundcolor', opt.artcol(iArt,:)) -end - -if strcmp(cfg.viewmode, 'butterfly') - % button to find label of nearest channel to datapoint - uicontrol('tag', 'group3', 'parent', h, 'units', 'normalized', 'style', 'pushbutton', 'string', 'identify', 'userdata', 'n', 'position', [0.91, 0.1, 0.08, 0.05], 'backgroundcolor', [1 1 1]) -end - -uilayout(h, 'tag', 'group1', 'width', 0.10, 'height', 0.05); -uilayout(h, 'tag', 'group2', 'width', 0.05, 'height', 0.05); - -uilayout(h, 'tag', 'group1', 'style', 'pushbutton', 'callback', @keyboard_cb); -uilayout(h, 'tag', 'group2', 'style', 'pushbutton', 'callback', @keyboard_cb); -uilayout(h, 'tag', 'group3', 'style', 'pushbutton', 'callback', @keyboard_cb); - -uilayout(h, 'tag', 'group1', 'retag', 'viewui'); -uilayout(h, 'tag', 'group2', 'retag', 'viewui'); -uilayout(h, 'tag', 'viewui', 'BackgroundColor', [0.8 0.8 0.8], 'hpos', 'auto', 'vpos', 0.01); - -definetrial_cb(h); -redraw_cb(h); - -if nargout - % wait until the user interface is closed, get the user data with the updated artifact details - set(h, 'CloseRequestFcn', @cleanup_cb); - - while ishandle(h) - uiwait(h); - opt = guidata(h); - if opt.cleanup - delete(h); - end - end - - % add the updated artifact definitions to the output cfg - for i=1:length(opt.artdata.label) - tmp = diff([0 opt.artdata.trial{1}(i,:) 0]); - artbeg = find(tmp==+1); - artend = find(tmp==-1) - 1; - cfg.artfctdef.(opt.artdata.label{i}).artifact = [artbeg' artend']; - end -end % if nargout - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: databrowser.m,v 1.24 2009/10/18 19:46:39 ingnie Exp $'; -% remember the configuration details of the input data -try cfg.previous = data.cfg; end - -end % main function - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function cleanup_cb(h, eventdata) -opt = guidata(h); -opt.cleanup = true; -guidata(h, opt); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function definetrial_cb(h, eventdata) -opt = guidata(h); -if strcmp(opt.cfg.continuous, 'no') - % keep the original trial definition for visualisation - opt.trlvis = opt.trlorg; -else - % construct a trial definition for visualisation - if isfield(opt, 'trlvis') - thistrlbeg = opt.trlvis(opt.trlop,1); - thistrlend = opt.trlvis(opt.trlop,2); - % remember a representative sample of the current trial - % thissample = round((thistrlbeg+thistrlend)/2); - thissample = thistrlbeg; - end - % look at opt.cfg.blocksize and make opt.trl accordingly - % if original data contains more than one trial, it will fail in fetch_data - datbegsample = min(opt.trlorg(:,1)); - datendsample = max(opt.trlorg(:,2)); - smppertrl = round(opt.fsample * opt.cfg.blocksize); - begsamples = datbegsample:smppertrl:datendsample; - endsamples = datbegsample+smppertrl-1:smppertrl:datendsample; - if numel(endsamples)length(opt.hdr.label) - chansel = chansel - (max(chansel) - length(opt.hdr.label)); - end - % convert numeric array into cell-array with channel labels - opt.cfg.channel = opt.hdr.label(chansel); - disp(opt.cfg.channel); - guidata(h, opt); - redraw_cb(h, eventdata); - case 'shift+leftarrow' - opt.cfg.blocksize = opt.cfg.blocksize*sqrt(2); - disp(opt.cfg.blocksize); - guidata(h, opt); - definetrial_cb(h, eventdata); - redraw_cb(h, eventdata); - case 'shift+rightarrow' - opt.cfg.blocksize = opt.cfg.blocksize/sqrt(2); - disp(opt.cfg.blocksize); - guidata(h, opt); - definetrial_cb(h, eventdata); - redraw_cb(h, eventdata); - case 'shift+uparrow' - opt.cfg.zscale = opt.cfg.zscale/sqrt(2); - guidata(h, opt); - redraw_cb(h, eventdata); - case 'shift+downarrow' - opt.cfg.zscale = opt.cfg.zscale*sqrt(2); - guidata(h, opt); - redraw_cb(h, eventdata); - case 'q' - guidata(h, opt); - cleanup_cb(h); - case 't' - % select the trial to display - response = inputdlg(sprintf('%s to display', opt.trialname), 'specify', 1, {num2str(opt.trlop)}); - if ~isempty(response) - opt.trlop = str2double(response); - opt.trlop = min(opt.trlop, size(opt.trlvis,1)); % should not be larger than the number of trials - opt.trlop = max(opt.trlop, 1); % should not be smaller than 1 - end - guidata(h, opt); - redraw_cb(h, eventdata); - case 'h' - % select the horizontal scaling - response = inputdlg('horizontal scale', 'specify', 1, {num2str(opt.cfg.blocksize)}); - if ~isempty(response) - opt.cfg.blocksize = str2double(response); - end - guidata(h, opt); - definetrial_cb(h, eventdata); - redraw_cb(h, eventdata); - case 'v' - % select the vertical scaling - response = inputdlg('vertical scale, number or ''maxmin'')', 'specify', 1, {num2str(opt.cfg.zscale)}); - if ~isempty(response) - if isnan(str2double(response)) && strcmp(response, 'maxmin') - minval = min(opt.curdat.trial{1}(:)); - maxval = max(opt.curdat.trial{1}(:)); - opt.cfg.zscale = max(abs([minval maxval])); - else - opt.cfg.zscale = str2double(response); - end - end - guidata(h, opt); - redraw_cb(h, eventdata); - case 'c' - % select channels - select = match_str(opt.hdr.label, opt.cfg.channel); - select = select_channel_list(opt.hdr.label, select); - opt.cfg.channel = opt.hdr.label(select); - guidata(h, opt); - redraw_cb(h, eventdata); - case 'n' - if strcmp(opt.cfg.viewmode, 'butterfly') - % click in data and get name of nearest channel - fprintf('click in the figure to receive the name of the closest channel\n'); - val = ginput(1); - channame = val2nearestchan(opt.curdat,val); - channb = match_str(opt.curdat.label,channame); - fprintf('channel name: %s\n',channame); - redraw_cb(h, eventdata); - hold on - xtext = opt.cfg.zscale - 0.1*opt.cfg.zscale; - plot_text(val(1), xtext, channame, 'FontSize', 16); - plot(opt.curdat.time{1}, opt.curdat.trial{1}(channb,:),'k','LineWidth',2) - end - case 'control+control' - % do nothing - case 'shift+shift' - % do nothing - otherwise - guidata(h, opt); - help_cb(h); -end -uiresume(h); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function toggle_viewmode_cb(h, eventdata, varargin) -opt = guidata(getparent(h)); -if ~isempty(varargin) && ischar(varargin{1}) - opt.cfg.viewmode = varargin{1}; -end -guidata(getparent(h), opt); -redraw_cb(h); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function h = getparent(h) -p = h; -while p~=0 - h = p; - p = get(h, 'parent'); -end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function redraw_cb(h, eventdata) -h = getparent(h); -opt = guidata(h); -figure(h); % ensure that the calling figure is in the front -cla; % clear the content in the current axis - -fprintf('redrawing with viewmode %s\n', opt.cfg.viewmode); - -begsample = opt.trlvis(opt.trlop, 1); -endsample = opt.trlvis(opt.trlop, 2); -offset = opt.trlvis(opt.trlop, 3); -chanindx = match_str(opt.hdr.label, opt.cfg.channel); - -if ~isempty(opt.event) - % select only the events in the current time window - event = opt.event; - evtsample = [event(:).sample]; - event = event(evtsample>=begsample & evtsample<=endsample); -else - event = []; -end - -if isempty(opt.orgdata) - fprintf('reading data... '); - dat = read_data(opt.cfg.datafile, 'header', opt.hdr, 'begsample', begsample, 'endsample', endsample, 'chanindx', chanindx, 'checkboundary', strcmp(opt.cfg.continuous, 'no'), 'dataformat', opt.cfg.dataformat, 'headerformat', opt.cfg.headerformat); -else - fprintf('fetching data... '); - dat = fetch_data(opt.orgdata, 'header', opt.hdr, 'begsample', begsample, 'endsample', endsample, 'chanindx', chanindx); -end -fprintf('done\n'); - -fprintf('fetching artifacts... '); -art = fetch_data(opt.artdata, 'begsample', begsample, 'endsample', endsample); -fprintf('done\n'); - -% apply preprocessing and determine the time axis -fprintf('preprocessing data... '); -[dat, lab, tim] = preproc(dat, opt.hdr.label(chanindx), opt.fsample, opt.cfg.preproc, offset); -fprintf('done\n'); - -opt.curdat.label = lab; -opt.curdat.time{1} = tim; -opt.curdat.trial{1} = dat; - -fprintf('plotting data... '); -switch opt.cfg.viewmode - case 'butterfly' - % to assure current feature is plotted on top - ordervec = 1:length(opt.artdata.label); - ordervec(opt.ftsel) = []; - ordervec(end+1) = opt.ftsel; - - for i = ordervec - tmp = diff([0 art(i,:) 0]); - artbeg = find(tmp==+1); - artend = find(tmp==-1) - 1; - for j=1:numel(artbeg) - plot_box([tim(artbeg(j)) tim(artend(j)) -opt.cfg.zscale opt.cfg.zscale], 'facecolor', opt.artcol(i,:), 'edgecolor', 'none'); - end - end - - % plot a line with text for each event - for i=1:length(event) - try - eventstr = sprintf('%s=%d', event(i).type, event(i).value); - catch - eventstr = 'unknown'; - end - eventtim = (event(i).sample-begsample+offset)/opt.fsample; - plot_line([eventtim eventtim], [-opt.cfg.zscale opt.cfg.zscale]); - plot_text(eventtim, opt.cfg.zscale, eventstr); - end - set(0,'DefaultAxesColorOrder',opt.chan_colors(chanindx,:)) %FIXME does not work?? - % plot the data on top of the box - plot_vector(tim, dat) - ax(1) = tim(1); - ax(2) = tim(end); - ax(3) = -opt.cfg.zscale; - ax(4) = opt.cfg.zscale; - axis(ax); - title(sprintf('%s %d, time from %g to %g s', opt.trialname, opt.trlop, tim(1), tim(end))); - xlabel('time'); - - case 'vertical' - tmpcfg = []; - tmpcfg.layout = 'vertical'; - tmpcfg.channel = opt.cfg.channel; - tmpcfg.skipcomnt = 'yes'; - tmpcfg.skipscale = 'yes'; - laytime = prepare_layout(tmpcfg, opt.orgdata); - - hlim = [tim(1) tim(end)]; - vlim = [-opt.cfg.zscale +opt.cfg.zscale]; - - % determine the position of each of the labels - labelx = laytime.pos(:,1) - laytime.width/2 - 0.01; - labely = laytime.pos(:,2); - - ax(1) = min(laytime.pos(:,1) - laytime.width/2); - ax(2) = max(laytime.pos(:,1) + laytime.width/2); - ax(3) = min(laytime.pos(:,2) - laytime.height/2); - ax(4) = max(laytime.pos(:,2) + laytime.height/2); - axis(ax) - - % remember the scaling of the horizontal axis, this is needed for mouse input - hpos(1) = laytime.pos(1,1) - laytime.width(1)/2; % the position of the left side of the timecourse box - hpos(2) = laytime.pos(1,1) + laytime.width(1)/2; % the position of the right side of the timecourse box - opt.hlim = hlim; - opt.hpos = hpos; - - % to assure current feature is plotted on top - ordervec = 1:length(opt.artdata.label); - ordervec(opt.ftsel) = []; - ordervec(end+1) = opt.ftsel; - - for j = ordervec - tmp = diff([0 art(j,:) 0]); - artbeg = find(tmp==+1); - artend = find(tmp==-1) - 1; - arttim = [tim(artbeg)' tim(artend)']; % convert the artifact sample number to time - arttim = (arttim - opt.hlim(1)) / (opt.hlim(2) - opt.hlim(1)); % convert to value relative to box, i.e. from 0 to 1 - arttim = arttim * (opt.hpos(2) - opt.hpos(1)) + opt.hpos(1); % convert from relative to actual value along the horizontal figure axis - - for k=1:numel(artbeg) - plot_box([arttim(k,1) arttim(k,2) ax(3) ax(4)], 'facecolor', opt.artcol(j,:), 'edgecolor', 'none'); - end - end % for each of the artifact channels - - for i = 1:length(chanindx) - datsel = i; - laysel = match_str(laytime.label, opt.hdr.label(chanindx(i))); - if ~isempty(datsel) - plot_text(labelx(laysel), labely(laysel), opt.hdr.label(chanindx(i)), 'HorizontalAlignment', 'right'); - plot_vector(tim, dat(datsel, :), 'hpos', laytime.pos(laysel,1), 'vpos', laytime.pos(laysel,2), 'width', laytime.width(laysel), 'height', laytime.height(laysel), 'hlim', hlim, 'vlim', vlim, 'box', false, 'color', opt.chan_colors(chanindx(i),:)); - end - end - - nticks = 11; - set(gca, 'xTick', linspace(ax(1), ax(2), nticks)) - xTickLabel = cellstr(num2str( linspace(tim(1), tim(end), nticks)' , '%1.2f'))'; - set(gca, 'xTickLabel', xTickLabel) - set(gca, 'yTick', []) - title(sprintf('%s %d, time from %g to %g s', opt.trialname, opt.trlop, tim(1), tim(end))); - - case 'component' - compindx = chanindx; - clear chanindx - - tmpcfg = []; - tmpcfg.layout = 'vertical'; - tmpcfg.channel = opt.cfg.channel; - tmpcfg.skipcomnt = 'yes'; - tmpcfg.skipscale = 'yes'; - laytime = prepare_layout(tmpcfg, opt.orgdata); - - tmpcfg = []; - tmpcfg.layout = opt.cfg.layout; - laychan = prepare_layout(tmpcfg, opt.orgdata); - - % determine the position of each of the topographies - laytopo.pos(:,1) = laytime.pos(:,1) - laytime.width/2 - laytime.height*2; - laytopo.pos(:,2) = laytime.pos(:,2); - laytopo.width = laytime.height; - laytopo.height = laytime.height; - laytopo.label = laytime.label; - - % determine the position of each of the labels - labelx = laytopo.pos(:,1) + laytopo.width; - labely = laytopo.pos(:,2); - - hlim = [tim(1) tim(end)]; - vlim = [-opt.cfg.zscale +opt.cfg.zscale]; - - [sel1, sel2] = match_str(opt.orgdata.topolabel, laychan.label); - chanx = laychan.pos(sel2,1); - chany = laychan.pos(sel2,2); - - for i=1:length(compindx) - datsel = i; - laysel = match_str(laytime.label,opt.hdr.label(compindx(i))); - if ~isempty(datsel) - plot_text(labelx(laysel), labely(laysel), opt.hdr.label(compindx(i))); - % plot the timecourse of this component - plot_vector(tim, dat(datsel, :), 'hpos', laytime.pos(laysel,1), 'vpos', laytime.pos(laysel,2), 'width', laytime.width(laysel), 'height', laytime.height(laysel), 'hlim', hlim, 'vlim', vlim); - % plot the topography of this component - chanz = opt.orgdata.topo(sel1,compindx(i)); - plot_topo(chanx, chany, chanz, 'mask', laychan.mask, 'outline', laychan.outline, 'hpos', laytopo.pos(laysel,1), 'vpos', laytopo.pos(laysel,2), 'width', laytopo.width(laysel), 'height', laytopo.height(laysel)) - axis equal - drawnow - end - end - set(gca, 'xTick', []) - set(gca, 'yTick', []) - title(sprintf('%s %d, time from %g to %g s', opt.trialname, opt.trlop, tim(1), tim(end))); - - ax(1) = min(laytopo.pos(:,1) - laytopo.width/2); - ax(2) = max(laytime.pos(:,1) + laytime.width/2); - ax(3) = min(laytime.pos(:,2) - laytime.height/2); - ax(4) = max(laytime.pos(:,2) + laytime.height/2); - axis(ax) - - % remember the scaling of the horizontal axis, this is needed for mouse input - hpos(1) = laytime.pos(1,1) - laytime.width(1)/2; % the position of the left side of the timecourse box - hpos(2) = laytime.pos(1,1) + laytime.width(1)/2; % the position of the right side of the timecourse box - opt.hlim = hlim; - opt.hpos = hpos; - - case 'settings' - % FIXME implement further details - - otherwise - error('unknown viewmode "%s"', opt.cfg.viewmode); -end % switch viewmode -fprintf('done\n'); - -guidata(h, opt); -end diff --git a/external/fieldtrip/private/dataset2files.m b/external/fieldtrip/private/dataset2files.m index 49cd071..6c5f36c 100644 --- a/external/fieldtrip/private/dataset2files.m +++ b/external/fieldtrip/private/dataset2files.m @@ -11,30 +11,23 @@ % Copyright (C) 2004, Robert Oostenveld % -% $Log: dataset2files.m,v $ -% Revision 1.7 2008/01/10 21:00:51 roboos -% added dataset=gui, pop up graphical interface (first asking for directory, then for file) +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.6 2005/09/07 10:00:46 roboos -% fixed bug in path/file for brainvision -% added check for presence of *.eeg/seg file in case dataset=brainvision_vhdr +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.5 2005/05/17 17:50:49 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.4 2005/02/16 08:05:16 roboos -% changed default behaviour so that dataset is copied into headerfile/datafile, except for ctf of brainvision -% -% Revision 1.3 2005/02/02 14:32:23 roboos -% added eep_cnt to the list of files for which dataset=headerfile+datafile -% -% Revision 1.2 2004/12/20 15:03:58 roboos -% added support for translating dataset to data+headerfile for neuroscan cnt and eeg -% -% Revision 1.1 2004/11/15 09:21:27 roboos -% simple helper function to avoid repliaction of code preprocessing and definetrial +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: dataset2files.m 952 2010-04-21 18:29:51Z roboos $ % start with empty fields if thery are not present if ~isfield(cfg, 'dataset') diff --git a/external/fieldtrip/private/datatype.m b/external/fieldtrip/private/datatype.m deleted file mode 100644 index 59e737a..0000000 --- a/external/fieldtrip/private/datatype.m +++ /dev/null @@ -1,96 +0,0 @@ -function [type, dimord] = datatype(data, desired) - -% DATATYPE determines the type of data represented in a FieldTrip data -% structure and returns a string with raw, freq, timelock source, comp, -% spike, source, volume, dip. -% -% Use as -% [type, dimord] = datatype(data) -% [type, dimord] = datatype(data, desired) -% -% See also CHANTYPE, FILETYPE, SENSTYPE, VOLTYPE - -% Copyright (C) 2008, Robert Oostenveld -% -% $Log: datatype.m,v $ -% Revision 1.8 2009/08/17 08:41:00 jansch -% added undocumented and experimental datatypes mvar and freqmvar -% -% Revision 1.7 2009/06/15 12:55:18 roboos -% also recognize cohspctrm as type=freq -% -% Revision 1.6 2009/03/25 20:52:07 jansch -% changed the conditional order to ensure correct behaviour for a comp-struct -% -% Revision 1.5 2009/01/28 15:00:45 roboos -% fixed detection of timelock for covariance -% -% Revision 1.4 2009/01/28 14:08:30 roboos -% added ) -% -% Revision 1.3 2009/01/28 14:08:08 roboos -% return 'unknown' -% detect timelock in case of only data.trial or data.cov -% -% Revision 1.2 2008/12/19 09:12:54 roboos -% added support for desired type, returning boolean -% -% Revision 1.1 2008/12/18 15:49:55 roboos -% new implementation -% - -% determine the type of input data, this can be raw, freq, timelock, comp, spike, source, volume, dip -israw = isfield(data, 'label') && isfield(data, 'time') && isa(data.time, 'cell') && isfield(data, 'trial') && isa(data.trial, 'cell'); -isfreq = isfield(data, 'label') && isfield(data, 'freq') && (isfield(data, 'powspctrm') || isfield(data, 'crsspctrm') || isfield(data, 'cohspctrm') || isfield(data, 'fourierspctrm')); -istimelock = isfield(data, 'label') && isfield(data, 'time') && ~isfield(data, 'freq') && ((isfield(data, 'avg') && isnumeric(data.avg)) || (isfield(data, 'trial') && isnumeric(data.trial) || (isfield(data, 'cov') && isnumeric(data.cov)))); -iscomp = isfield(data, 'topo') || isfield(data, 'topolabel'); -isspike = isfield(data, 'label') && isfield(data, 'waveform') && isa(data.waveform, 'cell') && isfield(data, 'timestamp') && isa(data.timestamp, 'cell'); -isvolume = isfield(data, 'transform') && isfield(data, 'dim'); -issource = isfield(data, 'pos'); -isdip = isfield(data, 'dip'); -ismvar = isfield(data, 'dimord') && ~isempty(strfind(data.dimord, 'lag')); -isfreqmvar = isfield(data, 'freq') && isfield(data, 'transfer'); - -if iscomp - type = 'comp'; - %comp should conditionally go before raw, otherwise the returned datatype - %will be raw -elseif isfreqmvar - type = 'freqmvar'; - %freqmvar should conditionally go before freq, otherwise the returned datatype - %will be freq in the case of frequency mvar data -elseif ismvar - type = 'mvar'; -elseif israw - type = 'raw'; -elseif isfreq - type = 'freq'; -elseif istimelock - type = 'timelock'; -elseif isspike - type = 'spike'; -elseif isvolume - type = 'volume'; -elseif issource - type = 'source'; -elseif isdip - type = 'dip'; -else - type = 'unknown'; -end - -if nargin>1 - % return a boolean value - type = strcmp(type, desired); - return; -end - -if nargout>1 - % also return the dimord of the input data - if isfield(data, 'dimord') - dimord = data.dimord; - else - dimord = 'unknown'; - end -end - diff --git a/external/fieldtrip/private/deblank2.m b/external/fieldtrip/private/deblank2.m deleted file mode 100644 index dfda927..0000000 --- a/external/fieldtrip/private/deblank2.m +++ /dev/null @@ -1,18 +0,0 @@ -function [out] = deblank2(in) - -% DEBLANK2 removes all blanks from the beginning and end of a char array -% -% out = deblank2(in) - -% Copyright (C) 2002-2007, Robert Oostenveld -% -% $Log: deblank2.m,v $ -% Revision 1.3 2007/12/20 19:08:06 roboos -% changed some whitespace -% -% Revision 1.2 2003/03/17 10:37:28 roberto -% improved general help comments and added copyrights -% - -out = fliplr(deblank(fliplr(deblank(in)))); - diff --git a/external/fieldtrip/private/define_biff.m b/external/fieldtrip/private/define_biff.m new file mode 100644 index 0000000..b84cf98 --- /dev/null +++ b/external/fieldtrip/private/define_biff.m @@ -0,0 +1,81 @@ +% DEFINE_BIFF matlab script to define the known BIFF chunk types +% +% This function should not be called seperately, it is intended to +% be used from withing read_biff and write_biff. +% +% See also READ_BIFF, WRITE_BIFF + +% Copyright (C) 2000, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: define_biff.m 952 2010-04-21 18:29:51Z roboos $ + +CAT_.desc = {'CAT ', 'cat', 'unknown'}; +LIST.desc = {'LIST', 'list', 'unknown'}; +BIFF.desc = {'BIFF', 'biff', 'group'}; + +BIFF.SEMG.desc = {'SEMG', 'semg', 'group'}; + +BIFF.SEMG.VERS.desc = {'VERS', 'version', 'group'}; +BIFF.SEMG.DINF.desc = {'DINF', 'data_info', 'group'}; +BIFF.SEMG.EXPI.desc = {'EXPI', 'experiment', 'group'}; +BIFF.SEMG.MEAS.desc = {'MEAS', 'measurement', 'group'}; +BIFF.SEMG.SGRD.desc = {'SGRD', 'semggrid', 'group'}; +BIFF.SEMG.PATI.desc = {'PATI', 'patient', 'group'}; + +BIFF.SEMG.VERS.ID__.desc = {'ID ', 'id', 'string'}; +BIFF.SEMG.VERS.LIC_.desc = {'LIC ', 'license', 'string'}; + +BIFF.SEMG.DATI.CHAN.desc = {'CHAN', 'unknown' 'unknown'}; +BIFF.SEMG.DATI.MODE.desc = {'MODE', 'unknown' 'unknown'}; +BIFF.SEMG.DATI.TYPE.desc = {'TYPE', 'unknown' 'unknown'}; +BIFF.SEMG.DATI.FS__.desc = {'FS ', 'unknown' 'unknown'}; +BIFF.SEMG.DATI.LABL.desc = {'LABL', 'unknown' 'unknown'}; +BIFF.SEMG.DATI.UNIT.desc = {'UNIT', 'unknown' 'unknown'}; +BIFF.SEMG.DATI.FILT.desc = {'FILT', 'unknown' 'unknown'}; + +BIFF.SEMG.EXPI.NAME.desc = {'NAME', 'name', 'string'}; +BIFF.SEMG.EXPI.EXAM.desc = {'EXAM', 'examination', 'string'}; +BIFF.SEMG.EXPI.EXRC.desc = {'EXRC', 'exercise', 'string'}; +BIFF.SEMG.EXPI.RPHS.desc = {'RPHS', 'ref_physician', 'string'}; +BIFF.SEMG.EXPI.DATE.desc = {'DATE', 'date', 'unknown'}; +BIFF.SEMG.EXPI.TIME.desc = {'TIME', 'time', 'unknown'}; + +BIFF.SEMG.MEAS.TIME.desc = {'TIME', 'time', 'string'}; +BIFF.SEMG.MEAS.ORFN.desc = {'ORFN', 'filename', 'string'}; +BIFF.SEMG.MEAS.MUSC.desc = {'MUSC', 'muscle', 'string'}; +BIFF.SEMG.MEAS.SIDE.desc = {'SIDE', 'side', 'unknown'}; +BIFF.SEMG.MEAS.FNUM.desc = {'FNUM', 'filenumber', 'unknown'}; +BIFF.SEMG.MEAS.TEMP.desc = {'TEMP', 'temperature', 'unknown'}; +BIFF.SEMG.MEAS.ANOT.desc = {'ANOT', 'annotation', 'string'}; +BIFF.SEMG.MEAS.FORC.desc = {'FORC', 'force', 'string'}; + +BIFF.SEMG.SGRD.NPD_.desc = {'NPD ', 'npd', 'unknown'}; +BIFF.SEMG.SGRD.NML_.desc = {'NML ', 'nml', 'unknown'}; +BIFF.SEMG.SGRD.IED_.desc = {'IED ', 'ied', 'unknown'}; +BIFF.SEMG.SGRD.FIBD.desc = {'FIBD', 'fibre_dir', 'unknown'}; +BIFF.SEMG.SGRD.POS_.desc = {'POS ', 'tle_pos', 'unknown'}; +BIFF.SEMG.SGRD.CABL.desc = {'CABL', 'cable_pos', 'unknown'}; +BIFF.SEMG.SGRD.GRID.desc = {'GRID', 'grid', 'int16vec'}; + +BIFF.SEMG.PATI.UPID.desc = {'UPID', 'unique_id', 'unknown'}; +BIFF.SEMG.PATI.GEND.desc = {'GEND', 'gendre', 'unknown'}; +BIFF.SEMG.PATI.BDAT.desc = {'BDAT', 'birthdate', 'unknown'}; +BIFF.SEMG.PATI.HPID.desc = {'HPID', 'hospital_id', 'unknown'}; +BIFF.SEMG.PATI.ANAM.desc = {'ANAM', 'anamnesis', 'unknown'}; + diff --git a/external/fieldtrip/private/definetrial.m b/external/fieldtrip/private/definetrial.m deleted file mode 100644 index bc8b847..0000000 --- a/external/fieldtrip/private/definetrial.m +++ /dev/null @@ -1,248 +0,0 @@ -function [cfg] = definetrial(cfg); - -% DEFINETRIAL defines the trials, i.e. the pieces of data that will be read -% in for preprocessing. Trials are defined by their begin and end sample -% in the data file and each trial has an offset that defines where the -% relative t=0 point (usually the point of the trigger) is for that trial. -% -% Use as -% [cfg] = definetrial(cfg) -% where the configuration structure should contain either -% cfg.trialdef = structure with details of trial definition, see below -% cfg.trialfun = function name, see below -% -% A call to DEFINETRIAL results in the trial definition "trl" being added -% to the output configuration structure. The trials are defined according -% to the triggers, trials or other events in the data, or from a -% user-specified Matlab function which returns "trl". -% -% The trial definition "trl" is an Nx3 matrix, N is the number of trials. -% The first column contains the sample-indices of the begin of each trial -% relative to the begin of the raw data, the second column contains the -% sample-indices of the end of each trial, and the third column contains -% the offset of the trigger with respect to the trial. An offset of 0 -% means that the first sample of the trial corresponds to the trigger. A -% positive offset indicates that the first sample is later than the trigger, -% a negative offset indicates that the trial begins before the trigger. -% -% Simple trial definitions (e.g. based on a trigger alone) are supported by -% DEFINETRIAL itself. For this, the general and data format independent way -% of handling trials is by relying on the READ_FCDC_EVENT function to -% collect all event information (such as triggers) from your dataset and -% select trials based on those events. This is implemented in DEFINETRIAL as -% cfg.trialdef.eventtype = 'string' -% cfg.trialdef.eventvalue = number, string or list with numbers or strings -% cfg.trialdef.prestim = number, latency in seconds (optional) -% cfg.trialdef.poststim = number, latency in seconds (optional) -% -% If you specify cfg.trialdef.eventtype = '?' a list with the events in your -% data file will be displayed on screen. -% -% However, there are also many other complex ways in which you can define -% data pieces of interest, for example based on a conditional sequence of -% events (e.g. stimulus trigger followed by a correct response). For those -% cases, a general mechanism has been implemented through which you can -% supply your own trial-defining function, the 'trialfun'. -% -% This 'trialfun' is a string containing the name of a function that you -% have to write yourself. The function should take the cfg-structure as -% input and should give a Nx3 matrix in the same format as "trl" as the -% output. You can add extra custom fields to the configuration structure to -% pass as arguments to your own trialfun. Furthermore, inside the trialfun -% you can use the READ_EVENT function to get the event information -% from your data file. -% -% See also PREPROCESSING, READ_HEADER, READ_DATA, READ_EVENT - -% Undocumented local options: -% cfg.datafile -% cfg.dataset -% cfg.event -% cfg.trl -% cfg.version - -% Copyright (c) 2003, Robert Oostenveld, F.C. Donders Centre -% -% $Log: definetrial.m,v $ -% Revision 1.57 2009/10/07 12:42:16 roevdmei -% changed reference to older FCDC read functions -% -% Revision 1.56 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.55 2009/01/14 11:29:55 sashae -% temporarily disabled previous revision -% -% Revision 1.54 2009/01/13 10:14:58 sashae -% changed handling of the output cfg: now the cfg also has cfg.previous fields, -% similar to data.cfg.previous. this way the output of definetrial and the -% artifact functions is kept separately from subsequent preprocessing steps -% -% Revision 1.53 2008/10/10 14:41:22 sashae -% replaced call to dataset2files with checkconfig -% -% Revision 1.52 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.51 2007/07/27 12:36:24 roboos -% updated a comment in the code -% -% Revision 1.50 2007/05/06 08:54:11 roboos -% do not add version info to cfg, will be done by preprocessing -% -% Revision 1.49 2006/09/18 07:41:50 roboos -% in case of eventtype=? give a gentle information message (instead of error) -% -% Revision 1.48 2006/06/20 16:25:58 ingnie -% updated documentation -% -% Revision 1.47 2006/05/30 20:57:15 roboos -% updated documentation -% -% Revision 1.46 2006/04/20 09:58:33 roboos -% updated documentation -% -% Revision 1.45 2006/03/29 10:34:02 ingnie -% updated documentation -% -% Revision 1.44 2005/11/04 16:06:15 ingnie -% fixed some typos in help -% -% Revision 1.43 2005/10/04 16:12:25 roboos -% changed exception handling of nargout for matlab65 into try-catch -% -% Revision 1.42 2005/09/07 10:18:31 roboos -% in matlab65 (R13) it does not find the functions in the private directory, whereas in matlab70 it does -% hence, made the specific evaluation of the nargout function dependent on the matlab version using "which" -% -% Revision 1.41 2005/09/02 14:24:14 roboos -% rigorously cleaned up the code -% moved all dataformat specific code into separate subfunctions -% added defaults for cfg.trialfun if not specified, depending on datatype and settings -% removed old CVS log history -% -% Revision 1.40 2005/05/17 17:50:37 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.39 2005/02/16 15:18:25 roboos -% cleaned up the documentation, removed cfg.trialfile as option (was not supported) -% cleaned up the handling of events, retain event if already present in cfg (just like trl) -% removed unclear warning about old v.s. new style of configuration -% improved fprintf feedback on number of events and trials -% - -fieldtripdefs - -% check if the input cfg is valid for this function -cfg = checkconfig(cfg, 'trackconfig', 'on'); -cfg = checkconfig(cfg, 'dataset2files', {'yes'}); - -if ~isfield(cfg, 'trl') && (~isfield(cfg, 'trialfun') || isempty(cfg.trialfun)) - % try to determine a standard trial function for the various data formats - % most of these trial functions are old-fashioned and do not use the - % event information that is returned by READ_FCDC_EVENT - - % determine the trials from the general events structure - if isfield(cfg, 'trialdef') && isfield(cfg.trialdef, 'eventtype') - cfg.trialfun = 'trialfun_general'; - % determine the trials from the events in the EEProbe file - elseif isfield(cfg, 'trialdef') && isfield(cfg.trialdef, 'trgfile') && filetype(cfg.trialdef.trgfile, 'eep_trg') - cfg.trialfun = 'trialfun_eeprobe_cnt'; - % determine the trials from the average EEProbe file - elseif filetype(cfg.datafile, 'eep_avr') - cfg.trialfun = 'trialfun_eeprobe_avr'; - % determine the trials from the events in the BrainVision file - elseif isfield(cfg, 'trialdef') && isfield(cfg.trialdef, 'trgfile') && filetype(cfg.trialdef.trgfile, 'brainvision_vmrk') - cfg.trialfun = 'trialfun_brainvision'; - % determine the trials from the Neuromag file - elseif filetype(cfg.datafile, 'neuromag_fif') - cfg.trialfun = 'trialfun_neuromag'; - % determine the trials from the triggers or class-definitions in the epoched CTF file - elseif filetype(cfg.dataset, 'ctf_ds') && isfield(cfg, 'trialdef') && (isfield(cfg.trialdef, 'includeTrigger') || isfield(cfg.trialdef, 'excludeTrigger') || isfield(cfg.trialdef, 'includeConditions') || isfield(cfg.trialdef, 'excludeConditions')) - cfg.trialfun = 'trialfun_ctf_epoched'; - % determine the trials from the triggers in the continuous CTF file - elseif filetype(cfg.dataset, 'ctf_ds') && isfield(cfg, 'trialdef') && ~(isfield(cfg.trialdef, 'includeTrigger') || isfield(cfg.trialdef, 'excludeTrigger') || isfield(cfg.trialdef, 'includeConditions') || isfield(cfg.trialdef, 'excludeConditions') || isfield(cfg.trialdef, 'eventtype')) - cfg.trialfun = 'trialfun_ctf_continuous'; - % determine the trials from the epoched NeuroScan file - elseif filetype(cfg.datafile, 'ns_eeg') - cfg.trialfun = 'trialfun_neuroscan_eeg'; - % determine the trials from the events in the continuous NeuroScan file - elseif isfield(cfg, 'trialdef') && filetype(cfg.datafile, 'ns_cnt') - cfg.trialfun = 'trialfun_neuroscan_cnt'; - else - error('no trialfunction specified, see DEFINETRIAL for help'); - end -end - -% create the trial definition for this dataset and condition -if isfield(cfg, 'trl') - % the trial definition is already part of the configuration - fprintf('retaining exist trial definition\n'); - trl = cfg.trl; - if isfield(cfg, 'event') - fprintf('retaining exist event information\n'); - event = cfg.event; - else - event = []; - end -elseif isfield(cfg, 'trialfun') - % evaluate the user-defined function that gives back the trial definition - fprintf('evaluating trialfunction ''%s''\n', cfg.trialfun); - % determine the number of outpout arguments of the user-supplied trial function - try - % the nargout function in Matlab 6.5 and older does not work on function handles - num = nargout(cfg.trialfun); - catch - num = 1; - end - if num==1 - % the user-defined function only gives back the trial definition - trl = feval(cfg.trialfun, cfg); - event = []; - else - % the user-defined function also gives back detailed information about - % conditions, reaction time or any other information - [trl, event] = feval(cfg.trialfun, cfg); - end -else - error('no trialfunction specified, see DEFINETRIAL for help'); -end - -if isfield(cfg, 'trialdef') && isfield(cfg.trialdef, 'eventtype') && strcmp(cfg.trialdef.eventtype, '?') - % give a gentle message instead of an error - fprintf('no trials have been defined yet, see DEFINETRIAL for further help\n'); -elseif size(trl,1)<1 - error('no trials were defined, see DEFINETRIAL for help'); -end - -% add the new trials and events to the output configuration -fprintf('found %d events\n', length(event)); -cfg.event = event; -fprintf('created %d trials\n', size(trl,1)); -cfg.trl = trl; - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% add information about the version of this function to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i1] = dbstack; - cfg.version.name = st(i1); -end -cfg.version.id = '$Id: definetrial.m,v 1.57 2009/10/07 12:42:16 roevdmei Exp $'; - -% % remember the exact configuration details in the output -% cfgtmp = cfg; -% cfg = []; -% try cfg.trl = cfgtmp.trl; end -% try cfg.dataset = cfgtmp.dataset; end -% try cfg.datafile = cfgtmp.datafile; end -% try cfg.headerfile = cfgtmp.headerfile; end -% cfg.previous = cfgtmp; diff --git a/external/fieldtrip/private/denoise_artifact.m b/external/fieldtrip/private/denoise_artifact.m new file mode 100644 index 0000000..20b2cff --- /dev/null +++ b/external/fieldtrip/private/denoise_artifact.m @@ -0,0 +1,91 @@ +function [params, s_new] = denoise_artifact(params, s, state) + +% DENOISE_ARTIFACT can be used for denoising source separation (DSS) +% during component analysis +% +% See also COMPONENTANALYSIS + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: denoise_artifact.m 952 2010-04-21 18:29:51Z roboos $ + +if nargin<3 || ~isstruct(state) + params.name = 'denoise_artifact'; + return; +end + +if ~isfield(params, 'concat') + % the artifact matrix should be relative to the concatenated data + % and not to the samples in the data file + trl = params.trl; + artifact = params.artifact; + concat = []; + trlnumsmp = trl(:,2) - trl(:,1) + 1; % count the number of samples in each trial + trlnumsmp = [0; cumsum(trlnumsmp)]; % compute the cumulative number of samples + for i=1:size(artifact,1) + % find the trial in which this artifact lies + trlnum = find(artifact(i,1)>=trl(:,1) & artifact(i,2)<=trl(:,2)); + if length(trlnum)==0 + fprintf('artifact %d is not completely in one trial\n', i); + elseif length(trlnum)==1 + fprintf('artifact %d is completely in trial %d\n', i, trlnum); + artbeg = artifact(i,1); + artend = artifact(i,2); + trlbeg = trl(trlnum,1); + trlend = trl(trlnum,2); + dum1 = artbeg - trlbeg + trlnumsmp(trlnum) + 1; + dum2 = artend - trlbeg + trlnumsmp(trlnum) + 1; + concat(end+1,:) = [dum1 dum2]; + else + fprintf('artifact %d seems to overlap with multiple trials\n', i); + end + end + fprintf('%d trial segments\n', size(trl,1)); + fprintf('%d artifact segments in input\n', size(artifact,1)); + fprintf('%d artifact segments in output\n', size(concat,1)); + % remember the artifact sample numbers in the concatinated data + params.concat = concat; +end + +% the artifacts are expressed in samples w.r.t. the concatenated data +artifact = params.concat; + +begsmp = artifact(:,1); +endsmp = artifact(:,2); + +% FIXME, this assumes that all artifacts are equally long +numsmp = endsmp(1) - begsmp(1) + 1; +numsrc = size(s,1); +numart = size(artifact,1); +sum = zeros(numsrc,numsmp); + +for i=1:numart + % cut data segments around the ECG trigger + sum = sum + s(:,begsmp(i):endsmp(i)); +end + +% averaging is not strictly neccessary, but conceptually nicer +sum = sum ./ numart; + +s_new = zeros(size(s)); +for i=1:numart + % put the average data segments back around the ECG trigger + s_new(:,begsmp(i):endsmp(i)) = sum; +end + diff --git a/external/fieldtrip/private/denoise_synthetic.m b/external/fieldtrip/private/denoise_synthetic.m deleted file mode 100644 index 8b0d975..0000000 --- a/external/fieldtrip/private/denoise_synthetic.m +++ /dev/null @@ -1,137 +0,0 @@ -function [data] = denoise_synthetic(cfg, data); - -% DENOISE_SYNTHETIC computes CTF higher-order synthetic gradients for -% preprocessed data and for the corresponding gradiometer definition. -% -% Use as -% [data] = denoise_synthetic(cfg, data); -% where data should come from PREPROCESSING and the configuration should contain -% cfg.gradient = 'none', 'G1BR', 'G2BR' or 'G3BR' specifies the gradiometer -% type to which the data should be changed -% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') -% -% See also PREPROCESSING, DENOISE_SNS, DENOISE_TSR, DENOISE_PCA - -% Copyright (C) 2004-2008, Robert Oostenveld -% -% $Log: denoise_synthetic.m,v $ -% Revision 1.8 2009/07/08 07:20:48 roboos -% allow for arbitrary balancing and not only a small hardcoded list -% -% Revision 1.7 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.6 2008/06/26 16:09:15 roboos -% added trial selection -% added check on ctf input -% try to keep channel ordering identical -% -% Revision 1.5 2008/05/21 19:39:56 roboos -% small fix in documentation -% -% Revision 1.4 2008/05/21 10:24:41 roboos -% fixed input error for checkdata -% -% Revision 1.3 2008/05/20 11:54:07 roboos -% fixed typo, new should be data -% -% Revision 1.2 2008/05/15 15:07:46 roboos -% complete rewrite, initial implementation using apply_montage helper function -% -% Revision 1.1 2008/05/15 09:52:05 roboos -% renamed function syntheticgradient to denoise_synthetic -% - -fieldtripdefs - -data = checkdata(data, 'datatype', 'raw', 'feedback', 'yes'); - -if ~senstype(data, 'ctf') - error('synthetic gradients can only be computed for CTF data'); -end - -% set the defaults -if ~isfield(cfg, 'gradient'), error('cfg.gradient must be specified'); end -if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end - -% select trials of interest -if ~strcmp(cfg.trials, 'all') - if islogical(cfg.trials), cfg.trials=find(cfg.trials); end - fprintf('selecting %d trials\n', length(cfg.trials)); - data.trial = data.trial(cfg.trials); - data.time = data.time(cfg.trials); - data.offset = data.offset(cfg.trials); - % update the trial definition (trl) - if isfield(data, 'cfg') % try to locate the trl in the nested configuration - trl = findcfg(data.cfg, 'trl'); - else - trl = []; - end - if isempty(trl) - % a trial definition is expected in each continuous data set - warning('could not locate the trial definition ''trl'' in the data structure'); - else - cfg.trlold=trl; - cfg.trl=trl(cfg.trials,:); - end -end - -% remember the original channel ordering -labelorg = data.label; - -% apply the balancing to the MEG data and to the gradiometer definition -current = data.grad.balance.current; -desired = cfg.gradient; - -if ~strcmp(current, 'none') - % first undo/invert the previously applied balancing - try - current_montage = getfield(data.grad.balance, data.grad.balance.current); - catch - error('unknown balancing for input data'); - end - fprintf('converting from "%s" to "none"\n', current); - data.grad = apply_montage(data.grad, current_montage, 'keepunused', 'yes', 'inverse', 'yes'); - data = apply_montage(data , current_montage, 'keepunused', 'yes', 'inverse', 'yes'); - data.grad.balance.current = 'none'; -end % if - -if ~strcmp(desired, 'none') - % then apply the desired balancing - try - desired_montage = getfield(data.grad.balance, cfg.gradient); - catch - error('unknown balancing for input data'); - end - fprintf('converting from "none" to "%s"\n', desired); - data.grad = apply_montage(data.grad, desired_montage, 'keepunused', 'yes', 'inverse', 'yes'); - data = apply_montage(data , desired_montage, 'keepunused', 'yes', 'inverse', 'yes'); - data.grad.balance.current = desired; -end % if - -% reorder the channels to stay close to the original ordering -[selorg, selnew] = match_str(labelorg, data.label); -if numel(selnew)==numel(labelorg) - for i=1:numel(data.trial) - data.trial{i} = data.trial{i}(selnew,:); - end - data.label = data.label(selnew); -else - warning('channel ordering might have changed'); -end - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: denoise_synthetic.m,v 1.8 2009/07/08 07:20:48 roboos Exp $'; -% remember the configuration details of the input data -try, cfg.previous = data.cfg; end -% remember the exact configuration details in the output -data.cfg = cfg; - diff --git a/external/fieldtrip/private/dftfilter.m b/external/fieldtrip/private/dftfilter.m index b446098..06c39c1 100644 --- a/external/fieldtrip/private/dftfilter.m +++ b/external/fieldtrip/private/dftfilter.m @@ -21,26 +21,23 @@ % original Copyright (C) 2003, Pascal Fries % modifications Copyright (C) 2003, Robert Oostenveld % -% $Log: dftfilter.m,v $ -% Revision 1.6 2005/01/27 17:06:22 roboos -% fixed bug in normalization of sine and cosine amplitude estimate in case number of samples in the data does not match with an integer number of cycles +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.5 2004/11/17 09:00:01 roboos -% added selection of data to ensure that the sine wave is estimated on an integer number of line-noise cycles -% all data is filtered, only amplitude estimation is done on this selection +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.4 2003/12/01 08:47:59 roberto -% updated copyright statement +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.3 2003/10/01 08:46:25 roberto -% updated help -% -% Revision 1.2 2003/10/01 08:45:23 roberto -% updated help -% -% Revision 1.1 2003/10/01 08:45:03 roberto -% first implementation as separate function, used to be notchfilter +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: dftfilter.m 952 2010-04-21 18:29:51Z roboos $ if nargin<3 | isempty(Fl) Fl = 50; diff --git a/external/fieldtrip/private/dimassign.m b/external/fieldtrip/private/dimassign.m new file mode 100644 index 0000000..b22b0aa --- /dev/null +++ b/external/fieldtrip/private/dimassign.m @@ -0,0 +1,72 @@ +function M=dimassign(A,dim,idx,B); +% function M=dimassign(A,dim,idx,B); +% +% The purpose of the function is shown by the following example: +% If A and B are multidimensional matrixes, +% A=dimassign(A,4,23,B); is the same as A(:,:,:,23,:,:,...)=B; +% The difference is that the dimention is selected by a scalar, not by +% the place between the brackets. +% A(2,4,3)=B; will then be written as: A=dimassign(A,[1,2,3],[2,4,3],B); +% In this last case B, of cource, must be a scalar. +% A([1,2],:,3)=B; can be written as: A=dimassign(A,[1,3],{[1,2],3},B); +% Of cource, again, the dimensions of B must fit! +% (size(B)==size(A([1,2],:,3) in this particular case) +% +% See also the function DIMINDEX + +% Copyright (C) 2005, Geerten Kramer +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: dimassign.m 952 2010-04-21 18:29:51Z roboos $ + +if(~iscell(idx)) + if(~any(size(dim)==1)||~any(size(idx)==1)||ndims(dim)>2||ndims(idx)>2||... + length(dim)~=length(idx)) + error('dim and idx must be both scalars oor both must have the same length'); + end; + dummi=[]; + for(i=1:length(idx)) + dummi{i}=idx(i); + end; + idx=dummi; + clear dummi; +end; +if(~any(size(dim)==1)||~any(size(idx)==1)||ndims(dim)>2||ndims(idx)>2||... + length(dim)~=length(idx)) + error('dim and idx must be both scalars or both must have the same length'); +end; + +if(~isequal(unique(dim),sort(dim))) + error('dim must be unique, every dimention can be addressed only once'); +end; + +Na=ndims(A); +for(i=1:max([max(dim),Na])) + ref=find(dim==i); + if(isempty(ref)) + C{i}=':'; + else + C{i}=idx{ref}; + end; +end; +M=A; +try + M(C{:})=B; +catch + error('Subscripted assignment dimension mismatch.'); +end; diff --git a/external/fieldtrip/private/dimindex.m b/external/fieldtrip/private/dimindex.m new file mode 100644 index 0000000..93f6ca6 --- /dev/null +++ b/external/fieldtrip/private/dimindex.m @@ -0,0 +1,69 @@ +function M=dimindex(A,dim,idx); +% function M=dimindex(A,dim,idx); +% +% The purpose of the function is shown by the following example: +% If A is a multidimensional matrix, +% dimindex(A,4,23); is the same as A(:,:,:,23,:,:,...); +% The advantage is that the dimention is selected by a scalar, not by +% the place between the brackets. +% A(2,4,3); will then be written as: dimindex(A,[1,2,3],[2,4,3]); +% A(4,:,[5:10]); will then be written as: dimindex(A,[1,3],{4,[5:10]}); +% +% See also the function DIMASSIGN + +% Copyright (C) 2005, Geerten Kramer +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: dimindex.m 952 2010-04-21 18:29:51Z roboos $ + +if(~iscell(idx)) + if(~any(size(dim)==1)||~any(size(idx)==1)||ndims(dim)>2||ndims(idx)>2||... + length(dim)~=length(idx)) + error('dim and idx must be both scalars or both vectors of the same size'); + end; + dummi=[]; + for(i=1:length(idx)) + dummi{i}=idx(i); + end; + idx=dummi; + clear dummi; +end; +if(~any(size(dim)==1)||~any(size(idx)==1)||ndims(dim)>2||ndims(idx)>2||... + length(dim)~=length(idx)) + error('dim and idx must be both scalars or both must have the same length'); +end; + + +if(length(dim)>ndims(A)||any(dim>ndims(A))) + error('dim, or one of its contents are larger than the number of dimentions in A'); +end; +if(~isequal(unique(dim),sort(dim))) + error('dim must be unique, every dimention can be addressed only once'); +end; + +N=ndims(A); +for(i=1:N) + ref=find(dim==i); + if(isempty(ref)) + C{i}=':'; + else + C{i}=idx{ref}; + end; +end; +M=A(C{:}); + diff --git a/external/fieldtrip/private/dimnum.m b/external/fieldtrip/private/dimnum.m new file mode 100644 index 0000000..7d69e27 --- /dev/null +++ b/external/fieldtrip/private/dimnum.m @@ -0,0 +1,61 @@ +function [num,dims]=dimnum(dimord, dim) +% This function returns the number of the given dimention 'dim' in the dimord string. +% +% Syntax: [num,dims]=dimnum(dimord, dim) +% +% e.g. when dimord='rpt_chancmb_freq_time' and dim='time', dimnum returns num=4 +% and dims contains {'rpt','chancmb','freq','tim'}. +% e.g. when dimord='rpt_chancmb_freq_time' and dim='chancmb', dimnum returns num=2 +% and dims again contains {'rpt','chancmb','freq','tim'}. +% +% For the known dimentiontypes dim can also be 'time' or 'frequency'. +% The known types are: +% tim: 'time' +% freq: 'frq', 'frequency' +% chancmb: 'sgncmb', 'channel', 'signal combination', 'channels' +% rpt: 'trial','trials' +% +% When dim is not found in dimord, an empty matrix is returned, but +% dims then still contains all dims in dimord. + +% Copyright (C) 2005, Geerten Kramer +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: dimnum.m 952 2010-04-21 18:29:51Z roboos $ + +if(~isstr(dimord)||~isstr(dim))error('Both dimord and dim must be strings');end; + +dims=tokenize(dimord,'_'); % splits the dimord string in parts using '_' as a delimiter +dim=lower(dim); % makes the function case unsensitive. + +switch dim %convert some dimension names. +case 'tim' + dim='time'; +case {'frq','frequency'} + dim='freq'; +case {'channel','signal combination','channels','sgncmb','chan'} + %dim='chancmb'; + dim='chan'; +case {'trial','trials'} + dim='rpt'; +end; + +num=find(strcmp(dims,dim)); % find the number of the specified dimension. + + + diff --git a/external/fieldtrip/private/dipole_fit.m b/external/fieldtrip/private/dipole_fit.m deleted file mode 100644 index 04137f1..0000000 --- a/external/fieldtrip/private/dipole_fit.m +++ /dev/null @@ -1,341 +0,0 @@ -function [dipout] = dipole_fit(dip, sens, vol, dat, varargin) - -% DIPOLE_FIT performs an equivalent current dipole fit with a single -% or a small number of dipoles to explain an EEG or MEG scalp topography. -% -% Use as -% [dipout] = dipole_fit(dip, sens, vol, dat, ...) -% -% Additional input arguments should be specified as key-value pairs and can include -% 'constr' = Structure with constraints -% 'display' = Level of display [ off | iter | notify | final ] -% 'optimfun' = Function to use [fminsearch | fminunc ] -% 'maxiter' = Maximum number of function evaluations allowed [ positive integer ] -% 'metric' = Error measure to be minimised [ rv | var | abs ] -% 'checkinside' = Boolean flag to check whether dipole is inside source compartment [ 0 | 1 ] -% 'weight' = weight matrix for maximum likelihood estimation, e.g. inverse noise covariance -% -% The following optional input arguments relate to the computation of the leadfields -% 'reducerank' = 'no' or number -% 'normalize' = 'no', 'yes' or 'column' -% 'normalizeparam' = parameter for depth normalization (default = 0.5) -% -% The maximum likelihood estimation implements -% Lutkenhoner B. "Dipole source localization by means of maximum -% likelihood estimation I. Theory and simulations" Electroencephalogr Clin -% Neurophysiol. 1998 Apr;106(4):314-21. - -% Copyright (C) 2003-2008, Robert Oostenveld -% -% $Log: dipole_fit.m,v $ -% Revision 1.15 2009/07/02 15:38:06 roboos -% use fixdipole for consistent dipole structure representation -% -% Revision 1.14 2009/03/13 07:24:52 roboos -% changed handling of optimization function (fminunc/fminsearch), now uses hastoolbox which is also able to check the availablity of a license for the optimimization toolbox -% -% Revision 1.13 2009/02/17 10:57:57 roboos -% use senstype to determine eeg/meg -% fixed bug in input pos/mom checking (thanks to Vladimir) -% -% Revision 1.12 2009/01/19 12:07:42 roboos -% fixed bug for symmetry constrained dipole fitting in case of multiple dipoles (thanks to John Iversen) -% added some checks on the input dipole position and moment -% -% Revision 1.11 2008/04/30 13:48:57 roboos -% finished implementation of MLE fitting, renamed cov into weight (inverse should be done outside this function) -% -% Revision 1.10 2008/04/29 15:41:53 roboos -% added skelleton for MAP estimation, but the covariance is not passed yet to lower level function -% -% Revision 1.9 2008/01/09 12:43:25 roboos -% added optional input arguments for reducerank, normalize and normalizeparam, these are directly passed on to compute_leadfield -% -% Revision 1.8 2007/12/18 13:01:55 roboos -% added support for fitting fixed orientation dipoles (constr.fixedori=1) -% -% Revision 1.7 2007/07/23 10:16:00 roboos -% implemented options for changing the error metric and for checking taht the dipole is inside the brain -% -% Revision 1.6 2007/03/21 11:13:29 roboos -% added MaxFunEvals to the optimization options -% -% Revision 1.5 2007/01/02 10:51:23 roboos -% renamed the output argument to dipout, no functional changes -% -% Revision 1.4 2006/09/07 12:39:51 roboos -% included optional input arguments to documentation -% -% Revision 1.3 2006/05/11 07:16:44 roboos -% Added additional input argument 'optimfun', can be fminunc or -% fminsearch. Changed the default maxiter to 500 for fminsearch. -% Changed the assignment of sens.pnt as structure (prevents warning -% in matlab7). -% -% Revision 1.2 2006/05/10 10:48:21 roboos -% Changed the order of the input arguments for consistency with -% other inverse functions, and switched to specifying optional inputs -% using key-value pairs. The old-style input is supported for backward -% compatibility with EEGLAB and dipfit1. Added optional input arguments -% for maxiter (default=100, just as before) and display (default='iter', -% just as before). -% -% Revision 1.1 2005/11/01 09:34:27 roboos -% replaced EEG/MEG specific dipole fit routines with a single general function -% -% Revision 1.7 2004/02/05 11:55:30 roberto -% fixed clearly apparent bug in error function (would not run) -% -% Revision 1.6 2003/09/12 08:45:41 roberto -% added error if maximum number of iterations is exceeded -% -% Revision 1.5 2003/09/02 13:01:18 roberto -% implemented constrained dipole fitting -% -% Revision 1.4 2003/06/16 10:03:31 roberto -% added check in error function for gui interrupt request (for eeglab) -% -% Revision 1.3 2003/03/13 13:41:00 roberto -% fixed bug in e/meg_error_func in assignment of Nchan -% -% Revision 1.2 2003/03/11 14:45:36 roberto -% updated help and copyrights -% - -% It is neccessary to provide backward compatibility support for the old function call -% in case people want to use it in conjunction with EEGLAB and the dipfit1 plugin. -% old style: function [dipout] = dipole_fit(dip, dat, sens, vol, constr), where constr is optional -% new style: function [dipout] = dipole_fit(dip, sens, vol, dat, varargin), where varargin is in key-value pairs -if nargin==4 && ~isstruct(sens) && isstruct(dat) - % looks like old style, the order of the input arguments has to be changed - warning('converting from old style input\n'); - olddat = sens; - oldsens = vol; - oldvol = dat; - dat = olddat; - sens = oldsens; - vol = oldvol; -elseif nargin==5 && ~isstruct(sens) && isstruct(dat) - % looks like old style, the order of the input arguments has to be changed - % furthermore the additional constraint has to be fixed - warning('converting from old style input\n'); - olddat = sens; - oldsens = vol; - oldvol = dat; - dat = olddat; - sens = oldsens; - vol = oldvol; - varargin = {'constr', varargin{1}}; % convert into a key-value pair -else - % looks like new style, i.e. with optional key-value arguments - % this is dealt with below -end - -constr = keyval('constr', varargin); % default is not to have constraints -metric = keyval('metric', varargin); if isempty(metric), metric = 'rv'; end -checkinside = keyval('checkinside', varargin); if isempty(checkinside), checkinside = 0; end -display = keyval('display', varargin); if isempty(display), display = 'iter'; end -optimfun = keyval('optimfun', varargin); if isa(optimfun, 'char'), optimfun = str2fun(optimfun); end -maxiter = keyval('maxiter', varargin); -reducerank = keyval('reducerank', varargin); % for leadfield computation -normalize = keyval('normalize' , varargin); % for leadfield computation -normalizeparam = keyval('normalizeparam', varargin); % for leadfield computation -weight = keyval('weight', varargin); % for maximum likelihood estimation - -if isempty(optimfun) - % determine whether the Matlab Optimization toolbox is available and can be used - if hastoolbox('optim') - optimfun = @fminunc; - else - optimfun = @fminsearch; - end -end - -if isempty(maxiter) - % set a default for the maximum number of iterations, depends on the optimization function - if isequal(optimfun, @fminunc) - maxiter = 100; - else - maxiter = 500; - end -end - -% determine whether it is EEG or MEG -iseeg = senstype(sens, 'eeg'); -ismeg = senstype(sens, 'meg'); - -if ismeg && iseeg - % this is something that I might implement in the future - error('simultaneous EEG and MEG not supported'); -elseif iseeg - % ensure that the potential data is average referenced, just like the model potential - dat = avgref(dat); -end - -% ensure correct dipole position and moment specification -dip = fixdipole(dip); - -% reformat the position parameters in case of multiple dipoles, this -% should result in the matrix changing from [x1 y1 z1; x2 y2 z2] to -% [x1 y1 z1 x2 y2 z2] for the constraints to work -numdip = size(dip.pos, 1); -param = dip.pos'; -param = param(:)'; - -% add the orientation to the nonlinear parameters -if isfield(constr, 'fixedori') && constr.fixedori - for i=1:numdip - % add the orientation to the list of parameters - [th, phi, r] = cart2sph(dip.mom(1,i), dip.mom(2,i), dip.mom(3,i)); - param = [param th phi]; - end -end - -% reduce the number of parameters to be fitted according to the constraints -if isfield(constr, 'mirror') - param = param(constr.reduce); -end - -% set the parameters for the optimization function -if isequal(optimfun, @fminunc) - options = optimset(... - 'TolFun',1e-9,... - 'TypicalX',ones(size(param)),... - 'LargeScale','off',... - 'HessUpdate','bfgs',... - 'MaxIter',maxiter,... - 'MaxFunEvals',2*maxiter*length(param),... - 'Display',display); -elseif isequal(optimfun, @fminsearch) - options = optimset(... - 'MaxIter',maxiter,... - 'MaxFunEvals',2*maxiter*length(param),... - 'Display',display); -else - warning('unknown optimization function "%s", using default parameters', func2str(optimfun)); -end - -% perform the optimization with either the fminsearch or fminunc function -[param, fval, exitflag, output] = optimfun(@dipfit_error, param, options, dat, sens, vol, constr, metric, checkinside, reducerank, normalize, normalizeparam, weight); - -if exitflag==0 - error('Maximum number of iterations exceeded before reaching the minimum, please try with another initial guess.') -end - -% do linear optimization of dipole moment parameters -[err, mom] = dipfit_error(param, dat, sens, vol, constr, metric, checkinside, reducerank, normalize, normalizeparam, weight); - -% expand the number of parameters according to the constraints -if isfield(constr, 'mirror') - param = constr.mirror .* param(constr.expand); -end - -% get the dipole position and orientation -if isfield(constr, 'fixedori') && constr.fixedori - numdip = numel(param)/5; - ori = zeros(3,numdip); - for i=1:numdip - th = param(end-(2*i)+1); - phi = param(end-(2*i)+2); - [ori(1,i), ori(2,i), ori(3,i)] = sph2cart(th, phi, 1); - end - pos = reshape(param(1:(numdip*3)), 3, numdip)'; -else - numdip = numel(param)/3; - pos = reshape(param, 3, numdip)'; -end - -% return the optimal dipole parameters -dipout.pos = pos; -if isfield(constr, 'fixedori') && constr.fixedori - dipout.mom = ori; % dipole orientation as vector - dipout.ampl = mom; % dipole strength -else - dipout.mom = mom; % dipole moment as vector or matrix, which represents both the orientation and strength as vector -end - -% ensure correct dipole position and moment specification -dipout = fixdipole(dipout); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% DIPFIT_ERROR computes the error between measured and model data -% and can be used for non-linear fitting of dipole position -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [err, mom] = dipfit_error(param, dat, sens, vol, constr, metric, checkinside, reducerank, normalize, normalizeparam, weight) - -% flush pending graphics events, ensure that fitting is interruptible -drawnow; -if ~isempty(get(0, 'currentfigure')) && strcmp(get(gcf, 'tag'), 'stop') - % interrupt the fitting - close; - error('USER ABORT'); -end; - -% expand the number of parameters according to the constraints -if isfield(constr, 'mirror') - param = constr.mirror .* param(constr.expand); -end - -% get the dipole positions and optionally also the orientation -if isfield(constr, 'fixedori') && constr.fixedori - numdip = numel(param)/5; - ori = zeros(3,numdip); - for i=1:numdip - th = param(end-(2*i)+1); - phi = param(end-(2*i)+2); - [ori(1,i), ori(2,i), ori(3,i)] = sph2cart(th, phi, 1); - end - pos = reshape(param(1:(numdip*3)), 3, numdip)'; -else - numdip = numel(param)/3; - pos = reshape(param, 3, numdip)'; -end - -% check whether the dipole is inside the source compartment -if checkinside - [inside, outside] = find_inside_vol(pos, vol); - if ~isempty(outside) - error('Dipole is outside the source compartment'); - end -end - -% construct the leadfield matrix for all dipoles -lf = compute_leadfield(pos, sens, vol, 'reducerank', reducerank, 'normalize', normalize, 'normalizeparam', normalizeparam); -if isfield(constr, 'fixedori') && constr.fixedori - lf = lf * ori; -end - -% compute the optimal dipole moment and the model error -if ~isempty(weight) - % maximum likelihood estimation using the weigth matrix - mom = pinv(lf'*weight*lf)*lf'*weight*dat; % Lutkenhoner equation 5 - dif = dat - lf*mom; - % compute the generalized goodness-of-fit measure - switch metric - case 'rv' % relative residual variance - num = dif' * weight * dif; - denom = dat' * weight * dat; - err = sum(num(:)) ./ sum(denom(:)); % Lutkenhonner equation 7, except for the gof=1-rv - case 'var' % residual variance - num = dif' * weight * dif'; - err = sum(num(:)); - otherwise - error('Unsupported error metric for maximum likelihood dipole fitting'); - end -else - % ordinary least squares, this is the same as MLE with weight=eye(nchans,nchans) - mom = pinv(lf)*dat; - dif = dat - lf*mom; - % compute the ordinary goodness-of-fit measures - switch metric - case 'rv' % relative residual variance - err = sum(dif(:).^2) / sum(dat(:).^2); - case 'var' % residual variance - err = sum(dif(:).^2); - case 'abs' % absolute difference - err = sum(abs(dif)); - otherwise - error('Unsupported error metric for dipole fitting'); - end -end - diff --git a/external/fieldtrip/private/dipolefitting.m b/external/fieldtrip/private/dipolefitting.m deleted file mode 100644 index 88df1ae..0000000 --- a/external/fieldtrip/private/dipolefitting.m +++ /dev/null @@ -1,751 +0,0 @@ -function [source] = dipolefitting(cfg, data) - -% DIPOLEFITTING perform grid search and non-linear fit with one or multiple -% dipoles and try to find the location where the dipole model is best able -% to explain the measured EEG or MEG topography. -% -% This function will initially scan the whole brain with a single dipole on -% a regular coarse grid, and subsequently start at the most optimal location -% with a non-linear search. Alternatively you can specify the initial -% location of the dipole(s) and the non-linear search will start from there. -% -% Use as -% [source] = dipolefitting(cfg, data) -% -% The configuration has the following general fields -% cfg.numdipoles = number, default is 1 -% cfg.symmetry = 'x', 'y' or 'z' symmetry for two dipoles, can be empty (default = []) -% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), -% see CHANNELSELECTION for details -% cfg.gridsearch = 'yes' or 'no', perform global search for initial -% guess for the dipole parameters (default = 'yes') -% cfg.nonlinear = 'yes' or 'no', perform nonlinear search for optimal -% dipole parameters (default = 'yes') -% -% You should specify the volume conductor model with -% cfg.hdmfile = string, file containing the volume conduction model -% or alternatively -% cfg.vol = structure with volume conduction model -% If the sensor information is not contained in the data itself you should -% also specify the sensor information using -% cfg.gradfile = string, file containing the gradiometer definition -% cfg.elecfile = string, file containing the electrode definition -% or alternatively -% cfg.grad = structure with gradiometer definition -% cfg.elec = structure with electrode definition -% -% If you start with a grid search, you should specify the grid locations at -% which a test dipole will be placed. The positions of the dipoles can be -% specified as a regular 3-D grid that is aligned with the axes of the head -% coordinate system -% cfg.grid.xgrid = vector (e.g. -20:1:20) or 'auto' (default = 'auto') -% cfg.grid.ygrid = vector (e.g. -20:1:20) or 'auto' (default = 'auto') -% cfg.grid.zgrid = vector (e.g. 0:1:20) or 'auto' (default = 'auto') -% cfg.grid.resolution = number (e.g. 1 cm) for automatic grid generation -% Alternatively a complete grid with dipole positions and precomputed -% leadfields can be specified -% cfg.grid = structure, see PREPARE_LEADFIELD -% or the position of a few dipoles at locations of interest can be -% specified, for example obtained from an anatomical or functional MRI -% cfg.grid.pos = Nx3 matrix with position of each source -% cfg.grid.dim = [Nx Ny Nz] vector with dimensions in case of 3-D grid (optional) -% cfg.grid.inside = vector with indices of the sources inside the brain (optional) -% cfg.grid.outside = vector with indices of the sources outside the brain (optional) -% -% If you do not start with a grid search, you have to give a starting location -% for the nonlinear search -% cfg.dip.pos = initial dipole position, matrix of Ndipoles x 3 -% -% The conventional approach is to fit dipoles to event-related averages, which -% within fieldtrip can be obtained from the TIMELOCKANALYSIS or from -% the TIMELOCKGRANDAVERAGE function. This has the additional options -% cfg.latency = [begin end] in seconds or 'all' (default = 'all') -% cfg.model = 'moving' or 'regional' -% A moving dipole model has a different position (and orientation) for each -% timepoint, or for each component. A regional dipole model has the same -% position for each timepoint or component, and a different orientation. -% -% You can also fit dipoles to the spatial topographies of an independent -% component analysis, obtained from the COMPONENTANALYSIS function. -% This has the additional options -% cfg.component = array with numbers (can be empty -> all) -% -% You can also fit dipoles to the spatial topographies that are present -% in the data in the frequency domain, which can be obtained using the -% FREQANALYSIS function. This has the additional options -% cfg.frequency = single number (in Hz) -% -% Low level details of the fitting can be specified in the cfg.dipfit structure -% cfg.dipfit.display = level of display, can be 'off', 'iter', 'notify' or 'final' (default = 'iter') -% cfg.dipfit.optimfun = function to use, can be 'fminsearch' or 'fminunc' (default is determined automatic) -% cfg.dipfit.maxiter = maximum number of function evaluations allowed (default depends on the optimfun) -% -% See also SOURCEANALYSIS, PREPARE_LEADFIELD - -% TODO change the output format, more suitable would be something like: -% dip.label -% dip.time -% dip.avg (instead of Vdata) -% dip.dip.pos -% dip.dip.mom -% dip.dip.model, or dip.dip.avg -% dip.dimord - -% Undocumented local options: -% cfg.dipfit.constr = Source model constraints, depends on cfg.symmetry -% -% This function depends on PREPARE_DIPOLE_GRID which has the following options: -% cfg.grid.xgrid (default set in PREPARE_DIPOLE_GRID: cfg.grid.xgrid = 'auto'), documented -% cfg.grid.ygrid (default set in PREPARE_DIPOLE_GRID: cfg.grid.ygrid = 'auto'), documented -% cfg.grid.zgrid (default set in PREPARE_DIPOLE_GRID: cfg.grid.zgrid = 'auto'), documented -% cfg.grid.resolution, documented -% cfg.grid.pos, documented -% cfg.grid.dim, documented -% cfg.grid.inside, documented -% cfg.grid.outside, documented -% cfg.symmetry, documented -% cfg.mri -% cfg.mriunits -% cfg.smooth -% cfg.sourceunits -% cfg.threshold -% -% This function depends on PREPARE_VOL_SENS which has the following options: -% cfg.channel (default set in DIPOLEFITTING: cfg.channel = 'all'), documented -% cfg.elec, documented -% cfg.elecfile, documented -% cfg.grad, documented -% cfg.gradfile, documented -% cfg.hdmfile, documented -% cfg.order -% cfg.vol, documented - -% Copyright (C) 2004-2006, Robert Oostenveld -% -% $Log: dipolefitting.m,v $ -% Revision 1.57 2009/07/02 15:55:15 roboos -% fixed typo -% -% Revision 1.56 2009/07/02 15:54:15 roboos -% convert 1x6 dipole position (after scanning with symmetric pair) into 2x3 to prevent warning later -% -% Revision 1.55 2009/07/02 15:37:04 roboos -% use senstype instead of strcmp -% use fixdipole helper function for consistent dipole structure representation -% -% Revision 1.54 2009/06/03 09:51:16 roboos -% changed input specification of dip.mom into 3xNdipoles -% give explicit error if unsupported dipole model -% -% Revision 1.53 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.52 2009/01/16 17:21:20 sashae -% added config tracking -% -% Revision 1.51 2008/10/02 15:32:20 sashae -% replaced call to createsubcfg with checkconfig -% -% Revision 1.50 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.49 2008/07/15 19:56:44 roboos -% moved cfg details for dipole grid to subcfg (cfg.grid)subcfg (cfg.grid.xxx) -% -% Revision 1.48 2008/04/10 08:03:11 roboos -% renamed the fieldtrip/private/prepare_vol_sens function into prepare_headmodel -% -% Revision 1.47 2008/03/18 12:38:40 roboos -% be more explicit about absense of symmetry constraint (since other options can also be passed in cfg.dipfit) -% -% Revision 1.46 2007/12/04 17:33:50 roboos -% added a space -% -% Revision 1.45 2007/12/04 17:33:02 roboos -% changed some print commands -% -% Revision 1.44 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.43 2007/03/30 17:05:40 ingnie -% checkinput; only proceed when input data is allowed datatype -% -% Revision 1.42 2007/03/27 11:05:19 ingnie -% changed call to fixdimord in call to checkinput -% -% Revision 1.41 2007/03/21 11:25:45 roboos -% removed model=fixed, since it was largely unsupported anyway -% more consistent handling of rotating/moving dipole model ("case model" everywhere) -% more consistent handling of input dipole model specification -% improved handling of dip(t) for moving dipole model when t>1 -% fixed bug as reported by Arno in the structure assignment for moving dipoles ("Subscripted assignment between dissimilar structures") -% added cfg.dipfit options to the documentation -% -% Revision 1.40 2007/01/09 09:51:17 roboos -% display the error message that was caught in try statement -% -% Revision 1.39 2006/11/23 10:52:46 roboos -% updated documentation -% -% Revision 1.38 2006/10/12 11:35:13 roboos -% replaced some ifs with switches -% reshape dipole position from 1x6 to 2x3 etc. -% -% Revision 1.37 2006/10/12 08:45:26 roboos -% added symmetry in z-direction, moved symmetric grid creation to prepare_dipole_grid -% -% Revision 1.36 2006/10/04 07:10:07 roboos -% updated documentation -% -% Revision 1.35 2006/07/05 10:34:52 roboos -% minor change in documentation -% -% Revision 1.34 2006/07/05 10:32:14 roboos -% minor change in documentation -% -% Revision 1.33 2006/07/05 10:23:57 roboos -% updated documentation -% removed default value for cfg.resolution (now determined in prepare_dipole_grid) -% removed default 'auto' values for xgrid/ygrid/zgrid (were similar to the default values in prepare_dipole_grid) -% -% Revision 1.32 2006/07/04 17:06:23 ingnie -% updated documentation -% -% Revision 1.31 2006/06/20 16:25:58 ingnie -% updated documentation -% -% Revision 1.30 2006/06/13 14:48:08 ingnie -% updated documentation -% -% Revision 1.29 2006/05/11 07:13:51 roboos -% removed the message about which optimization function is being used -% -% Revision 1.28 2006/05/10 16:01:55 roboos -% Fixed bug that occurred when the channel ordering in the elec was -% different than the data. Added measured and model data to the output -% structure, added elec or grad to the output structure (usefull for -% topoplotting). -% -% Revision 1.27 2006/05/10 15:41:14 roboos -% Changed the order of the input arguments for the dipole_fit() function -% to be consistent with the function itself. Changed the handling of a -% failed dipole fit. Added a transparent way for handing over optional -% key-value parameters to the low-level dipole_fit() function, currently -% supported are constr, maxiter, display. -% -% Revision 1.26 2006/04/20 09:58:34 roboos -% updated documentation -% -% Revision 1.25 2006/04/10 16:33:46 ingnie -% updated documentation -% -% Revision 1.24 2006/04/06 16:17:09 ingnie -% updated documentation -% -% Revision 1.23 2006/02/23 10:28:16 roboos -% changed dimord strings for consistency, changed toi and foi into time and freq, added fixdimord where neccessary -% -% Revision 1.22 2005/12/21 09:26:29 roboos -% implemented support for a fixed dipole model, only dipole moment is computed (i.e. no gridsearch or nonlinear fit is done) -% some changes in whitespace by auto indentation -% -% Revision 1.21 2005/11/01 09:37:46 roboos -% removed local subfunction compute_dipole_fit() and replaced by a -% call to the new and general dipole_fit() function which supports -% both EEG and MEG -% -% Revision 1.20 2005/10/14 16:23:11 roboos -% added support for dipole fitting in the frequency domain (based on fourier or csd input) -% restructured the handling of comp and freq input, now both consistent with timelock input -% changed the channel and latency selection of the topographies -% -% Revision 1.19 2005/06/29 12:46:29 roboos -% the following changes were done on a large number of files at the same time, not all of them may apply to this specific file -% - added try-catch around the inclusion of input data configuration -% - moved cfg.version, cfg.previous and the assignment of the output cfg to the end -% - changed help comments around the configuration handling -% - some changes in whitespace -% -% Revision 1.18 2005/06/01 09:15:36 roboos -% replaced fprintf for each grid point with more controlled progress indicator, using cfg.feedback -% -% Revision 1.17 2005/06/01 08:00:59 roboos -% some small changes to the help documentation -% -% Revision 1.16 2005/05/17 17:50:37 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.15 2005/03/14 10:44:54 roboos -% added informative fprintf about optimization toolbox (no functional change) -% -% Revision 1.14 2005/02/21 07:56:54 roboos -% deleted the subfunction compute_leadfield, it is now a separate function -% -% Revision 1.13 2004/12/08 18:00:14 roboos -% implemented consistent method of selecting a subset of channels for -% forward and inverse computations using cfg.channel and updated the -% ducumentation -% -% Revision 1.12 2004/09/06 07:47:03 roboos -% fixed bug for finding optimium after grid scanning fixed dipole model -% -% Revision 1.11 2004/09/01 17:59:28 roboos -% added copyright statements to all filed -% added cfg.version to all functions that give configuration in their output -% added cfg.previous to all functions with input data containing configuration details -% -% Revision 1.10 2004/08/30 13:18:06 roboos -% fixed 2 bogs for moving dipole model -% -% Revision 1.9 2004/06/21 20:13:25 roberto -% fixed two bugs: one with sens.pnt and the other with inside/outside dipole positions after scanning -% -% Revision 1.8 2004/06/03 15:47:21 roberto -% improved detecton of correct configuration (numdipoles) -% -% Revision 1.7 2004/05/19 15:39:35 roberto -% fixed bug in time, which can be cell-array in case of ICA on raw data -% added complete version details to output configuration -% -% Revision 1.6 2004/05/13 23:35:47 roberto -% fixed multiple bugs related to new implementation moving/regional -% -% Revision 1.5 2004/05/13 22:36:30 roberto -% implemented cfg.method = 'regional' (old behaviour) and 'moving' (additional) -% -% Revision 1.4 2004/03/06 13:04:03 roberto -% fixed some small bugs and added time/component number to the output -% -% Revision 1.3 2004/02/05 12:20:06 roberto -% moved the code that was common with dipolefitting into separate prepare_grid and prepare_sens_vol functions -% fixed multiple small bugs -% -% Revision 1.2 2004/01/27 14:39:05 roberto -% multiple small bug fixes -% -% Revision 1.1 2004/01/22 21:42:52 roberto -% initial version, not tested -% support for single dipole scanning, fitting and symmetric dipole pair -% - -fieldtripdefs -cfg = checkconfig(cfg, 'trackconfig', 'on'); - -% check if the input data is valid for this function -data = checkdata(data, 'datatype', {'timelock', 'freq', 'comp'}, 'feedback', 'yes'); - -% set the defaults -if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end -if ~isfield(cfg, 'component'), cfg.component = []; end % for comp input -if ~isfield(cfg, 'frequency'), cfg.frequency = []; end % for freq input -if ~isfield(cfg, 'latency'), cfg.latency = 'all'; end -if ~isfield(cfg, 'feedback'), cfg.feedback = 'text'; end -if ~isfield(cfg, 'gridsearch'), cfg.gridsearch = 'yes'; end -if ~isfield(cfg, 'nonlinear'), cfg.nonlinear = 'yes'; end -if ~isfield(cfg, 'symmetry'), cfg.symmetry = []; end - -% put the low-level options pertaining to the dipole grid (used for initial scanning) in their own field -cfg = checkconfig(cfg, 'createsubcfg', {'grid'}); - -% the default for this depends on the data type -if ~isfield(cfg, 'model'), - if ~isempty(cfg.component) - % each component is fitted independently - cfg.model = 'moving'; - elseif ~isempty(cfg.latency) - % fit the data with a dipole at one location - cfg.model = 'regional'; - elseif ~isempty(cfg.latency) - % fit the data with a dipole at one location - cfg.model = 'regional'; - end -end - -if ~isfield(cfg, 'numdipoles') - if isfield(cfg, 'dip') - cfg.numdipoles = size(cfg.dip(1).pos,1); - else - cfg.numdipoles = 1; - end -end - -% set up the symmetry constraints -if ~isempty(cfg.symmetry) - if cfg.numdipoles~=2 - error('symmetry constraints are only supported for two-dipole models'); - elseif strcmp(cfg.symmetry, 'x') - % this structure is passed onto the low-level dipole_fit function - cfg.dipfit.constr.reduce = [1 2 3]; % select the parameters [x1 y1 z1] - cfg.dipfit.constr.expand = [1 2 3 1 2 3]; % repeat them as [x1 y1 z1 x1 y1 z1] - cfg.dipfit.constr.mirror = [1 1 1 -1 1 1]; % multiply each of them with 1 or -1, resulting in [x1 y1 z1 -x1 y1 z1] - elseif strcmp(cfg.symmetry, 'y') - % this structure is passed onto the low-level dipole_fit function - cfg.dipfit.constr.reduce = [1 2 3]; % select the parameters [x1 y1 z1] - cfg.dipfit.constr.expand = [1 2 3 1 2 3]; % repeat them as [x1 y1 z1 x1 y1 z1] - cfg.dipfit.constr.mirror = [1 1 1 1 -1 1]; % multiply each of them with 1 or -1, resulting in [x1 y1 z1 x1 -y1 z1] - elseif strcmp(cfg.symmetry, 'z') - % this structure is passed onto the low-level dipole_fit function - cfg.dipfit.constr.reduce = [1 2 3]; % select the parameters [x1 y1 z1] - cfg.dipfit.constr.expand = [1 2 3 1 2 3]; % repeat them as [x1 y1 z1 x1 y1 z1] - cfg.dipfit.constr.mirror = [1 1 1 1 1 -1]; % multiply each of them with 1 or -1, resulting in [x1 y1 z1 x1 y1 -z1] - else - error('unrecognized symmetry constraint'); - end -elseif ~isfield(cfg, 'dipfit') || ~isfield(cfg.dipfit, 'constr') - % no symmetry constraints have been specified - cfg.dipfit.constr = []; -end - -if isfield(data, 'topolabel') - % this looks like a component analysis - iscomp = 1; - % transform the data into a representation on which the timelocked dipole fit can perform its trick - data = comp2timelock(cfg, data); -else - iscomp = 0; -end - -if isfield(data, 'freq') - % this looks like a frequency analysis - isfreq = 1; - % transform the data into a representation on which the timelocked dipole fit can perform its trick - data = freq2timelock(cfg, data); -else - isfreq = 0; -end - -% prepare the volume conduction model and the sensor array -% this updates the configuration with the appropriate fields -[vol, sens, cfg] = prepare_headmodel(cfg, data); - -% select the desired channels, the order should be the same as in the sensor structure -[selsens, seldata] = match_str(sens.label, data.label); -Vdata = data.avg(seldata, :); - -if iscomp - % select the desired component topographies - Vdata = Vdata(:, cfg.component); -elseif isfreq - % the desired frequency topographies have already been selected - Vdata = Vdata(:, :); -else - % select the desired latencies - if ischar(cfg.latency) && strcmp(cfg.latency, 'all') - cfg.latency = data.time([1 end]); - end - tbeg = nearest(data.time, cfg.latency(1)); - tend = nearest(data.time, cfg.latency(end)); - cfg.latency = [data.time(tbeg) data.time(tend)]; - Vdata = Vdata(:, tbeg:tend); -end - -nchans = size(Vdata,1); -ntime = size(Vdata,2); -Vmodel = zeros(nchans, ntime); -fprintf('selected %d channels\n', nchans); -fprintf('selected %d topographies\n', ntime); - -if nchans0.001) - warning('the EEG data is not average referenced, correcting this'); - end - Vdata = avgref(Vdata); -end - -% set to zeros if no initial dipole was specified -if ~isfield(cfg, 'dip') - cfg.dip.pos = zeros(cfg.numdipoles, 3); - cfg.dip.mom = zeros(3*cfg.numdipoles, 1); -end - -% set to zeros if no initial dipole position was specified -if ~isfield(cfg.dip, 'pos') - cfg.dip.pos = zeros(cfg.numdipoles, 3); -end - -% set to zeros if no initial dipole moment was specified -if ~isfield(cfg.dip, 'mom') - cfg.dip.mom = zeros(3*cfg.numdipoles, 1); -end - -% check the specified dipole model -if numel(cfg.dip.pos)~=cfg.numdipoles*3 || numel(cfg.dip.mom)~=cfg.numdipoles*3 - error('inconsistent number of dipoles in configuration') -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% perform the dipole scan, this is usefull for generating an initial guess -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if strcmp(cfg.gridsearch, 'yes') - % test whether we have a valid configuration for dipole scanning - if cfg.numdipoles==1 - % this is ok - elseif cfg.numdipoles==2 && ~isempty(cfg.dipfit.constr) - % this is also ok - else - error('dipole scanning is only possible for a single dipole or a symmetric dipole pair'); - end - - % construct the grid on which the scanning will be done - [grid, cfg] = prepare_dipole_grid(cfg, vol, sens); - progress('init', cfg.feedback, 'scanning grid'); - for i=1:length(grid.inside) - progress(i/length(grid.inside), 'scanning grid location %d/%d\n', i, length(grid.inside)); - indx = grid.inside(i); - if isfield(grid, 'leadfield') - % reuse the previously computed leadfield - lf = grid.leadfield{indx}; - else - lf = compute_leadfield(grid.pos(indx,:), sens, vol); - end - % the model is V=lf*mom+noise, therefore mom=pinv(lf)*V estimates the - % dipole moment this makes the model potential U=lf*pinv(lf)*V and the - % model error is norm(V-U) = norm(V-lf*pinv(lf)*V) = norm((eye-lf*pinv(lf))*V) - switch cfg.model - case 'regional' - % sum the error over all latencies - grid.error(indx,1) = sum(sum(((eye(nchans)-lf*pinv(lf))*Vdata).^2)); - case 'moving' - % remember the error for each latency independently - grid.error(indx,:) = sum(((eye(nchans)-lf*pinv(lf))*Vdata).^2); - otherwise - error('unsupported cfg.model'); - end % switch model - end % looping over the grid - progress('close'); - - switch cfg.model - case 'regional' - % find the grid point(s) with the minimum error - [err, indx] = min(grid.error(grid.inside)); - dip.pos = grid.pos(grid.inside(indx),:); % note that for a symmetric dipole pair this results in a vector - dip.pos = reshape(dip.pos, cfg.numdipoles, 3); % convert to a Nx3 array - dip.mom = zeros(cfg.numdipoles*3,1); % set the dipole moment to zero - if cfg.numdipoles==1 - fprintf('found minimum after scanning on grid point [%g %g %g]\n', dip.pos(1), dip.pos(2), dip.pos(3)); - elseif cfg.numdipoles==2 - fprintf('found minimum after scanning on grid point [%g %g %g; %g %g %g]\n', dip.pos(1), dip.pos(2), dip.pos(3), dip.pos(4), dip.pos(5), dip.pos(6)); - end - case 'moving' - for t=1:ntime - % find the grid point(s) with the minimum error - [err, indx] = min(grid.error(grid.inside,t)); - dip(t).pos = grid.pos(grid.inside(indx),:); % note that for a symmetric dipole pair this results in a vector - dip(t).pos = reshape(dip(t).pos, cfg.numdipoles, 3); % convert to a Nx3 array - dip(t).mom = zeros(cfg.numdipoles*3,1); % set the dipole moment to zero - if cfg.numdipoles==1 - fprintf('found minimum after scanning for topography %d on grid point [%g %g %g]\n', t, dip(t).pos(1), dip(t).pos(2), dip(t).pos(3)); - elseif cfg.numdipoles==2 - fprintf('found minimum after scanning for topography %d on grid point [%g %g %g; %g %g %g]\n', t, dip(t).pos(1), dip(t).pos(2), dip(t).pos(3), dip(t).pos(4), dip(t).pos(5), dip(t).pos(6)); - end - end - otherwise - error('unsupported cfg.model'); - end % switch model -end % if gridsearch - -if strcmp(cfg.gridsearch, 'no') - % use the initial guess supplied in the configuration for the remainder - switch cfg.model - case 'regional' - dip = struct(cfg.dip); - case 'moving' - for t=1:ntime - dip(t) = struct(cfg.dip); - end - otherwise - error('unsupported cfg.model'); - end % switch model -end - -% multiple dipoles can be represented either as a 1x(N*3) vector or as a Nx3 matrix, -% i.e. [x1 y1 z1 x2 y2 z2] or [x1 y1 z1; x2 y2 z2] -switch cfg.model - case 'regional' - dip = fixdipole(dip); - case 'moving' - for t=1:ntime - dip(t) = fixdipole(dip(t)); - end - otherwise - error('unsupported cfg.model'); -end % switch model - -if isfield(cfg, 'dipfit') - % convert the structure with the additional low-level options into key-value pairs - optarg = cfg2keyval(getfield(cfg, 'dipfit')); -else - % no additional low-level options were specified - optarg = {}; -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% perform the non-linear fit -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if strcmp(cfg.nonlinear, 'yes') - switch cfg.model - case 'regional' - % perform the non-linear dipole fit for all latencies together - % catch errors due to non-convergence - try - dip = dipole_fit(dip, sens, vol, Vdata, optarg{:}); - success = 1; - if cfg.numdipoles==1 - fprintf('found minimum after non-linear optimization on [%g %g %g]\n', dip.pos(1), dip.pos(2), dip.pos(3)); - elseif cfg.numdipoles==2 - fprintf('found minimum after non-linear optimization on [%g %g %g; %g %g %g]\n', dip.pos(1,1), dip.pos(1,2), dip.pos(1,3), dip.pos(2,1), dip.pos(2,2), dip.pos(2,3)); - end - catch - success = 0; - disp(lasterr); - end - case 'moving' - % perform the non-linear dipole fit for each latency independently - % instead of using dip(t) = dipole_fit(dip(t),...), I am using temporary variables dipin and dipout - % this is to prevent errors of the type "Subscripted assignment between dissimilar structures" - dipin = dip; - for t=1:ntime - % catch errors due to non-convergence - try - dipout(t) = dipole_fit(dipin(t), sens, vol, Vdata(:,t), optarg{:}); - success(t) = 1; - if cfg.numdipoles==1 - fprintf('found minimum after non-linear optimization for topography %d on [%g %g %g]\n', t, dipout(t).pos(1), dipout(t).pos(2), dipout(t).pos(3)); - elseif cfg.numdipoles==2 - fprintf('found minimum after non-linear optimization for topography %d on [%g %g %g; %g %g %g]\n', t, dipout(t).pos(1,1), dipout(t).pos(1,2), dipout(t).pos(1,3), dipout(t).pos(2,1), dipout(t).pos(2,2), dipout(t).pos(2,3)); - end - catch - dipout(t).pos = dipin(t).pos; - dipout(t).mom = dipin(t).mom; - success(t) = 0; - disp(lasterr); - end - end - dip = dipout; - clear dipin dipout - otherwise - error('unsupported cfg.model'); - end % switch model -end % if nonlinear - -if strcmp(cfg.nonlinear, 'no') - % the optimal dipole positions are either obrained from scanning or from the initial configured seed - switch cfg.model - case 'regional' - success = 1; - case 'moving' - success = ones(1,ntime); - otherwise - error('unsupported cfg.model'); - - end % switch model -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% compute the model potential distribution and the residual variance -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -switch cfg.model - case 'regional' - if success - % re-compute the leadfield in order to compute the model potential and dipole moment - lf = compute_leadfield(dip.pos, sens, vol); - % compute all details of the final dipole model - dip.mom = pinv(lf)*Vdata; - dip.pot = lf*dip.mom; - dip.rv = rv(Vdata, dip.pot); - Vmodel = dip.pot; - end - case 'moving' - for t=1:ntime - if success(t) - % re-compute the leadfield in order to compute the model potential and dipole moment - lf = compute_leadfield(dip(t).pos, sens, vol); - % compute all details of the final dipole model - dip(t).mom = pinv(lf)*Vdata(:,t); - dip(t).pot = lf*dip(t).mom; - dip(t).rv = rv(Vdata(:,t), dip(t).pot); - Vmodel(:,t) = dip(t).pot; - end - end - otherwise - error('unsupported cfg.model'); -end % switch model - -switch cfg.model - case 'regional' - if isfreq - % the matrix with the dipole moment is encrypted and cannot be interpreted straight away - % reconstruct the frequency representation of the data at the source level - [dip.pow, dip.csd, dip.fourier] = timelock2freq(dip.mom); - end - case 'moving' - if isfreq - % although this is technically possible sofar, it does not make any sense - warning('a moving dipole model in the frequency domain is not supported'); - end - otherwise - error('unsupported cfg.model'); -end % switch model - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% collect the results -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -source.label = cfg.channel; % these channels were used in fitting -source.dip = dip; -source.Vdata = Vdata; % FIXME this should be renamed (if possible w.r.t. EEGLAB) -source.Vmodel = Vmodel; % FIXME this should be renamed (if possible w.r.t. EEGLAB) - -% assign a latency, frequeny or component axis to the output -if iscomp - source.component = cfg.component; - % FIXME assign Vdata to an output variable, idem for the model potential -elseif isfreq - source.freq = cfg.frequency; - source.dimord = 'chan_freq'; - % FIXME assign Vdata to an output variable, idem for the model potential -else - tbeg = nearest(data.time, cfg.latency(1)); - tend = nearest(data.time, cfg.latency(end)); - source.time = data.time(tbeg:tend); - source.dimord = 'chan_time'; -end - -if isfield(data, 'grad') - % copy the gradiometer array along - source.grad = data.grad; -end -if isfield(data, 'elec') - % copy the electrode array along - source.elec = data.elec; -end - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% add the version details of this function call to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: dipolefitting.m,v 1.57 2009/07/02 15:55:15 roboos Exp $'; -% remember the configuration details of the input data -try, cfg.previous = data.cfg; end -% remember the exact configuration details in the output -source.cfg = cfg; - diff --git a/external/fieldtrip/private/dipolesimulation.m b/external/fieldtrip/private/dipolesimulation.m deleted file mode 100644 index 40a34fc..0000000 --- a/external/fieldtrip/private/dipolesimulation.m +++ /dev/null @@ -1,257 +0,0 @@ -function [simulated] = dipolesimulation(cfg) - -% DIPOLESIMULATION computes the field or potential of a simulated dipole -% and returns a datastructure identical to the PREPROCESSING function. -% -% Use as -% data = dipolesimulation(cfg) -% -% You should specify the volume conductor model with -% cfg.hdmfile = string, file containing the volume conduction model -% or alternatively -% cfg.vol = structure with volume conduction model -% If the sensor information is not contained in the data itself you should -% also specify the sensor information using -% cfg.gradfile = string, file containing the gradiometer definition -% cfg.elecfile = string, file containing the electrode definition -% or alternatively -% cfg.grad = structure with gradiometer definition -% cfg.elec = structure with electrode definition -% -% optionally -% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), -% see CHANNELSELECTION for details -% -% The dipoles position and orientation have to be specified with -% cfg.dip.pos = [Rx Ry Rz] -% cfg.dip.mom = [Qx Qy Qz] -% -% The timecourse of the dipole activity is given as a single vector or as a -% cell-array with one vectors per trial -% cfg.dip.signal -% or by specifying a sine-wave signal -% cfg.dip.frequency in Hz -% cfg.dip.phase in radians -% cfg.ntrials number of trials -% cfg.triallength time in seconds -% cfg.fsample sampling frequency in Hz -% -% Random white noise can be added to the data in each trial, either by -% specifying an absolute or a relative noise level -% cfg.relnoise = add noise with level relative to simulated signal -% cfg.absnoise = add noise with absolute level - -% Undocumented local options -% cfg.feedback -% cfg.previous -% cfg.version -% -% This function depends on PREPARE_VOL_SENS which has the following options: -% cfg.channel, documented -% cfg.elec, documented -% cfg.elecfile, documented -% cfg.grad, documented -% cfg.gradfile, documented -% cfg.hdmfile, documented -% cfg.order -% cfg.vol, documented - -% Copyright (C) 2004, Robert Oostenveld -% -% $Log: dipolesimulation.m,v $ -% Revision 1.24 2009/07/02 15:37:32 roboos -% use fixdipole for consistent dipole structure representation -% -% Revision 1.23 2009/03/23 21:19:51 roboos -% allow different amplitudes for different dipoles -% -% Revision 1.22 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.21 2008/04/10 08:03:11 roboos -% renamed the fieldtrip/private/prepare_vol_sens function into prepare_headmodel -% -% Revision 1.20 2008/03/18 12:27:22 roboos -% use senstype helper function to determine whether output should contain grad or elec -% -% Revision 1.19 2007/03/21 12:43:41 roboos -% replaced two "try" statements with if(isfield(..)) -% -% Revision 1.18 2006/10/04 07:10:07 roboos -% updated documentation -% -% Revision 1.17 2006/07/04 16:05:33 roboos -% removed offset from output data -% -% Revision 1.16 2006/06/20 16:25:58 ingnie -% updated documentation -% -% Revision 1.15 2006/06/13 14:51:38 ingnie -% updated documentation to increase consistency in help of cfg options, added -% default cfg.channel = 'all' -% -% Revision 1.14 2006/04/20 09:58:34 roboos -% updated documentation -% -% Revision 1.13 2006/04/10 16:33:46 ingnie -% updated documentation -% -% Revision 1.12 2005/11/10 10:02:14 roboos -% minor change in whitespace and help -% - -fieldtripdefs - -% set the defaults -if ~isfield(cfg, 'dip'), cfg.dip = []; end -if ~isfield(cfg.dip, 'pos'), cfg.dip.pos = [-5 0 15]; end -if ~isfield(cfg.dip, 'mom'), cfg.dip.mom = [1 0 0]'; end -if ~isfield(cfg, 'fsample'), cfg.fsample = 250; end -if ~isfield(cfg, 'relnoise'), cfg.relnoise = 0; end -if ~isfield(cfg, 'absnoise'), cfg.absnoise = 0; end -if ~isfield(cfg, 'feedback'), cfg.feedback = 'text'; end -if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end - -cfg.dip = fixdipole(cfg.dip); -Ndipoles = size(cfg.dip.pos,1); - -% prepare the volume conductor and the sensor array -[vol, sens, cfg] = prepare_headmodel(cfg, []); - -if ~isfield(cfg, 'ntrials') - if isfield(cfg.dip, 'signal') - cfg.ntrials = length(cfg.dip.signal); - else - cfg.ntrials = 20; - end -end -Ntrials = cfg.ntrials; - -if isfield(cfg.dip, 'frequency') - % this should be a column vector - cfg.dip.frequency = cfg.dip.frequency(:); -end - -if isfield(cfg.dip, 'phase') - % this should be a column vector - cfg.dip.phase = cfg.dip.phase(:); -end - -% no signal was given, compute a cosine-wave signal as timcourse for the dipole -if ~isfield(cfg.dip, 'signal') - % set some additional defaults if neccessary - if ~isfield(cfg.dip, 'frequency') - cfg.dip.frequency = ones(Ndipoles,1)*10; - end - if ~isfield(cfg.dip, 'phase') - cfg.dip.phase = zeros(Ndipoles,1); - end - if ~isfield(cfg.dip, 'amplitude') - cfg.dip.amplitude = ones(Ndipoles,1); - end - if ~isfield(cfg, 'triallength') - cfg.triallength = 1; - end - % compute a cosine-wave signal wit the desired frequency, phase and amplitude for each dipole - nsamples = round(cfg.triallength*cfg.fsample); - time = (0:(nsamples-1))/cfg.fsample; - for i=1:Ndipoles - cfg.dip.signal(i,:) = cos(cfg.dip.frequency(i)*time*2*pi + cfg.dip.phase(i)) * cfg.dip.amplitude(i); - end -end - -% construct the timecourse of the dipole activity for each individual trial -if ~iscell(cfg.dip.signal) - dipsignal = {}; - time = {}; - nsamples = length(cfg.dip.signal); - for trial=1:Ntrials - % each trial has the same dipole signal - dipsignal{trial} = cfg.dip.signal; - time{trial} = (0:(nsamples-1))/cfg.fsample; - end -else - dipsignal = {}; - time = {}; - for trial=1:Ntrials - % each trial has a different dipole signal - dipsignal{trial} = cfg.dip.signal{trial}; - time{trial} = (0:(length(dipsignal{trial})-1))/cfg.fsample; - end -end - -dippos = cfg.dip.pos; -dipmom = cfg.dip.mom; - -if ~iscell(dipmom) - dipmom = {dipmom}; -end - -if ~iscell(dippos) - dippos = {dippos}; -end - -if length(dippos)==1 - dippos = repmat(dippos, 1, Ntrials); -elseif length(dippos)~=Ntrials - error('incorrect number of trials specified in the dipole position'); -end - -if length(dipmom)==1 - dipmom = repmat(dipmom, 1, Ntrials); -elseif length(dipmom)~=Ntrials - error('incorrect number of trials specified in the dipole moment'); -end - -simulated.trial = {}; -simulated.time = {}; -progress('init', cfg.feedback, 'computing simulated data'); -for trial=1:Ntrials - progress(trial/Ntrials, 'computing simulated data for trial %d\n', trial); - lf = compute_leadfield(dippos{trial}, sens, vol); - simulated.trial{trial} = lf * dipmom{trial} * dipsignal{trial}; - simulated.time{trial} = time{trial}; -end -progress('close'); - -if senstype(sens, 'meg') - simulated.grad = sens; -elseif senstype(sens, 'meg') - simulated.elec = sens; -end - -% determine RMS value of simulated data -ss = 0; -sc = 0; -for trial=1:Ntrials - ss = ss + sum(simulated.trial{trial}(:).^2); - sc = sc + length(simulated.trial{trial}(:)); -end -rms = sqrt(ss/sc); -fprintf('RMS value of simulated data is %g\n', rms); - -% add noise to the simulated data -for trial=1:Ntrials - relnoise = randn(size(simulated.trial{trial})) * cfg.relnoise * rms; - absnoise = randn(size(simulated.trial{trial})) * cfg.absnoise; - simulated.trial{trial} = simulated.trial{trial} + relnoise + absnoise; -end - -simulated.fsample = cfg.fsample; -simulated.label = sens.label; - -% add version details to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: dipolesimulation.m,v 1.24 2009/07/02 15:37:32 roboos Exp $'; -% remember the configuration details of the input data -try, cfg.previous = data.cfg; end -% remember the exact configuration details in the output -simulated.cfg = cfg; - diff --git a/external/fieldtrip/private/dist.m b/external/fieldtrip/private/dist.m index aa1e9bb..e1ea313 100644 --- a/external/fieldtrip/private/dist.m +++ b/external/fieldtrip/private/dist.m @@ -11,10 +11,23 @@ % Copyright (C) 2005, Robert Oostenveld % -% $Log: dist.m,v $ -% Revision 1.1 2005/05/26 07:31:54 roboos -% new implementation to replace Neural Networks version (required by createlayout) +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: dist.m 952 2010-04-21 18:29:51Z roboos $ n = size(x,2); d = zeros(n,n); diff --git a/external/fieldtrip/private/downsamplevolume.m b/external/fieldtrip/private/downsamplevolume.m deleted file mode 100644 index ca6dcb0..0000000 --- a/external/fieldtrip/private/downsamplevolume.m +++ /dev/null @@ -1,23 +0,0 @@ -function [volume] = downsamplevolume(cfg, volume); - -% VOLUMEDOWNSAMPLE downsamples an anatomical MRI or source reconstruction -% and optionally normalizes its coordinate axes, keeping the homogenous -% transformation matrix correct. -% -% Warning: This function is deprecated, it has been renamed to VOLUMEDOWNSAMPLE -% Warning: backward compatibility will be removed in the future - -% Copyright (C) 2005-2006, F.C. Donders Centre -% -% $Log: downsamplevolume.m,v $ -% Revision 1.12 2007/01/09 09:52:07 roboos -% changed the warning a bit -% -% Revision 1.11 2006/03/14 08:09:22 roboos -% added copyrigth and cvs log statement -% - -warning('This function is deprecated, it has been renamed to VOLUMEDOWNSAMPLE'); -warning('backward compatibility will be removed in the future'); - -[volume] = volumedownsample(cfg, volume); diff --git a/external/fieldtrip/private/easycap128ch-avg.lay b/external/fieldtrip/private/easycap128ch-avg.lay deleted file mode 100644 index 478a78d..0000000 --- a/external/fieldtrip/private/easycap128ch-avg.lay +++ /dev/null @@ -1,127 +0,0 @@ -1 -0.152424 16.023216 1.033097 0.774822 1 -2 -0.092697 11.438642 1.033097 0.774822 2 -3 -0.122791 8.838130 1.033097 0.774822 3 -4 -0.086579 6.483106 1.033097 0.774822 4 -5 -0.038908 3.909524 1.033097 0.774822 5 -6 -0.060770 1.684619 1.033097 0.774822 6 -7 -0.111176 -2.289965 1.033097 0.774822 7 -8 -0.107057 -6.334760 1.033097 0.774822 8 -9 -0.210169 -10.736417 1.033097 0.774822 9 -10 -0.205235 -13.479102 1.033097 0.774822 10 -11 -4.230155 -12.856482 1.033097 0.774822 11 -12 -7.576336 -10.833138 1.033097 0.774822 12 -13 -10.507746 -8.575278 1.033097 0.774822 13 -14 -12.505464 -4.655812 1.033097 0.774822 14 -15 -13.381783 3.975466 1.033097 0.774822 15 -16 -12.564771 8.523160 1.033097 0.774822 16 -17 -11.133469 12.372501 1.033097 0.774822 17 -18 -8.814041 13.088932 1.033097 0.774822 18 -19 -5.092164 16.040882 1.033097 0.774822 19 -20 -3.567896 14.962887 1.033097 0.774822 20 -21 -1.722765 13.317761 1.033097 0.774822 21 -22 -2.490235 10.018020 1.033097 0.774822 22 -23 -2.256353 7.480056 1.033097 0.774822 23 -24 -2.447084 4.656264 1.033097 0.774822 24 -25 -2.083052 2.299778 1.033097 0.774822 25 -26 -1.386842 -0.080753 1.033097 0.774822 26 -27 -1.362641 -4.100783 1.033097 0.774822 27 -28 -1.736260 -8.264115 1.033097 0.774822 28 -29 -2.027074 -11.928669 1.033097 0.774822 29 -30 -5.599798 -10.468008 1.033097 0.774822 30 -31 -8.329617 -8.291974 1.033097 0.774822 31 -32 -10.289363 -4.882283 1.033097 0.774822 32 -33 -11.722990 -1.273594 1.033097 0.774822 33 -34 -11.145266 4.972978 1.033097 0.774822 34 -35 -10.459154 8.708478 1.033097 0.774822 35 -36 -8.958964 9.392224 1.033097 0.774822 36 -37 -6.921306 12.752688 1.033097 0.774822 37 -38 -4.766703 11.511399 1.033097 0.774822 38 -39 -4.539641 8.325329 1.033097 0.774822 39 -40 -4.285770 5.720232 1.033097 0.774822 40 -41 -4.119369 2.920261 1.033097 0.774822 41 -42 -3.019158 0.533630 1.033097 0.774822 42 -43 -2.549256 -1.970309 1.033097 0.774822 43 -44 -2.744921 -6.098953 1.033097 0.774822 44 -45 -4.201891 -7.704211 1.033097 0.774822 45 -46 -3.293380 -9.901516 1.033097 0.774822 46 -47 -6.386778 -8.163701 1.033097 0.774822 47 -48 -8.506449 -5.482694 1.033097 0.774822 48 -49 -9.964591 -2.427798 1.033097 0.774822 49 -50 -10.581743 1.193944 1.033097 0.774822 50 -51 -9.914762 5.364764 1.033097 0.774822 51 -52 -8.397710 6.800701 1.033097 0.774822 52 -53 -6.785899 9.296686 1.033097 0.774822 53 -54 -6.148296 6.608615 1.033097 0.774822 54 -55 -5.905275 3.685145 1.033097 0.774822 55 -56 -5.627240 1.021473 1.033097 0.774822 56 -57 -4.765313 -1.475758 1.033097 0.774822 57 -58 -3.180922 -3.745666 1.033097 0.774822 58 -59 -4.846406 -5.056842 1.033097 0.774822 59 -60 -6.447776 -5.540555 1.033097 0.774822 60 -61 -8.181945 -3.001512 1.033097 0.774822 61 -62 -9.025779 -0.173928 1.033097 0.774822 62 -63 -9.206570 3.249563 1.033097 0.774822 63 -64 -7.607924 4.457174 1.033097 0.774822 64 -65 -7.758289 1.781994 1.033097 0.774822 65 -66 -7.216684 -0.597527 1.033097 0.774822 66 -67 -6.274244 -2.697668 1.033097 0.774822 67 -68 3.740960 -12.377100 1.033097 0.774822 68 -69 7.233356 -10.259647 1.033097 0.774822 69 -70 10.156545 -7.751123 1.033097 0.774822 70 -71 11.916374 -4.132653 1.033097 0.774822 71 -72 12.709150 3.878648 1.033097 0.774822 72 -73 12.187837 7.800468 1.033097 0.774822 73 -74 11.647529 11.590926 1.033097 0.774822 74 -75 8.830574 12.873875 1.033097 0.774822 75 -76 5.223080 15.995239 1.033097 0.774822 76 -77 3.741005 15.017076 1.033097 0.774822 77 -78 1.858988 13.406917 1.033097 0.774822 78 -79 2.257934 10.115201 1.033097 0.774822 79 -80 2.029207 7.557748 1.033097 0.774822 80 -81 2.030731 4.877962 1.033097 0.774822 81 -82 1.969551 2.278909 1.033097 0.774822 82 -83 1.325827 0.022228 1.033097 0.774822 83 -84 1.059077 -3.897829 1.033097 0.774822 84 -85 1.193214 -8.135174 1.033097 0.774822 85 -86 1.678796 -11.494763 1.033097 0.774822 86 -87 5.245900 -9.963848 1.033097 0.774822 87 -88 8.075897 -7.796324 1.033097 0.774822 88 -89 10.262923 -4.726628 1.033097 0.774822 89 -90 11.412376 -1.121192 1.033097 0.774822 90 -91 11.089073 4.339439 1.033097 0.774822 91 -92 10.194870 8.310675 1.033097 0.774822 92 -93 8.937397 9.447145 1.033097 0.774822 93 -94 6.835845 13.050318 1.033097 0.774822 94 -95 4.829020 11.937097 1.033097 0.774822 95 -96 4.542505 8.343096 1.033097 0.774822 96 -97 4.253282 5.751575 1.033097 0.774822 97 -98 4.156059 3.021318 1.033097 0.774822 98 -99 2.915765 0.648812 1.033097 0.774822 99 -100 2.438351 -1.745275 1.033097 0.774822 100 -101 2.313872 -5.784331 1.033097 0.774822 101 -102 3.748400 -7.588636 1.033097 0.774822 102 -103 2.961003 -9.514305 1.033097 0.774822 103 -104 5.757636 -8.120945 1.033097 0.774822 104 -105 8.068864 -5.463119 1.033097 0.774822 105 -106 9.520996 -2.496665 1.033097 0.774822 106 -107 10.563670 1.234955 1.033097 0.774822 107 -108 10.001878 5.211759 1.033097 0.774822 108 -109 8.368086 6.698311 1.033097 0.774822 109 -110 6.817441 9.465605 1.033097 0.774822 110 -111 6.079439 6.521362 1.033097 0.774822 111 -112 5.741585 3.548555 1.033097 0.774822 112 -113 5.543709 0.948134 1.033097 0.774822 113 -114 4.762975 -1.497854 1.033097 0.774822 114 -115 2.950614 -3.754586 1.033097 0.774822 115 -116 4.348413 -5.182889 1.033097 0.774822 116 -117 6.232668 -5.474207 1.033097 0.774822 117 -118 7.918584 -2.964145 1.033097 0.774822 118 -119 8.870377 -0.237932 1.033097 0.774822 119 -120 9.174824 2.956286 1.033097 0.774822 120 -121 7.724656 4.382056 1.033097 0.774822 121 -122 7.682218 1.438245 1.033097 0.774822 122 -123 7.093112 -0.932228 1.033097 0.774822 123 -124 6.114839 -3.349139 1.033097 0.774822 124 -125 0.045614 21.533291 1.033097 0.774822 nasion -126 -13.638264 -0.454375 1.033097 0.774822 left -127 13.645793 0.565450 1.033097 0.774822 right diff --git a/external/fieldtrip/private/easycap32ch-avg.lay b/external/fieldtrip/private/easycap32ch-avg.lay deleted file mode 100644 index 09a61b4..0000000 --- a/external/fieldtrip/private/easycap32ch-avg.lay +++ /dev/null @@ -1,34 +0,0 @@ -1 -3.837749 13.308285 2.147611 1.610709 Fp1 -2 5.700807 12.863892 2.147611 1.610709 Fp2 -3 -8.801090 7.310438 2.147611 1.610709 F7 -4 -4.822684 7.719534 2.147611 1.610709 F3 -5 0.699290 8.307790 2.147611 1.610709 Fz -6 6.080786 7.069006 2.147611 1.610709 F4 -7 10.060247 5.766232 2.147611 1.610709 F8 -8 -7.882893 4.001457 2.147611 1.610709 FC5 -9 -2.466939 4.845382 2.147611 1.610709 FC1 -10 0.362983 4.978020 2.147611 1.610709 FCz -11 3.435992 4.437486 2.147611 1.610709 FC2 -12 8.619883 2.689526 2.147611 1.610709 FC6 -13 -10.136683 0.237999 2.147611 1.610709 T7 -14 -5.609665 1.813302 2.147611 1.610709 C3 -15 0.111080 1.786211 2.147611 1.610709 Cz -16 6.041378 0.727669 2.147611 1.610709 C4 -17 10.376825 -1.491501 2.147611 1.610709 T8 -18 -7.919199 -1.689539 2.147611 1.610709 CP5 -19 -2.521862 -0.762026 2.147611 1.610709 CP1 -20 2.599157 -1.117983 2.147611 1.610709 CP2 -21 7.667841 -2.926962 2.147611 1.610709 CP6 -22 -8.457450 -6.042018 2.147611 1.610709 P7 -23 -4.915900 -3.954582 2.147611 1.610709 P3 -24 -0.410531 -4.136967 2.147611 1.610709 Pz -25 4.220910 -4.845122 2.147611 1.610709 P4 -26 7.310020 -7.366834 2.147611 1.610709 P8 -27 -4.026078 -9.745686 2.147611 1.610709 O1 -28 2.247546 -10.201173 2.147611 1.610709 O2 -29 -11.131085 -5.800571 2.147611 1.610709 TP9 -30 10.207232 -7.633787 2.147611 1.610709 TP10 -31 0.868663 11.480392 2.147611 1.610709 Gnd -32 0.533857 16.315436 2.147611 1.610709 Nasion -33 -13.665185 -0.125838 2.147611 1.610709 LPA -34 13.553182 -1.407640 2.147611 1.610709 RPA diff --git a/external/fieldtrip/private/easycap64ch-avg.lay b/external/fieldtrip/private/easycap64ch-avg.lay deleted file mode 100644 index 940d5d7..0000000 --- a/external/fieldtrip/private/easycap64ch-avg.lay +++ /dev/null @@ -1,69 +0,0 @@ -1 0.031911 0.105920 1.127141 0.845356 1 -2 -0.005719 3.202174 1.127141 0.845356 2 -3 2.629770 1.671681 1.127141 0.845356 3 -4 2.683392 -1.647989 1.127141 0.845356 4 -5 0.061570 -2.937902 1.127141 0.845356 5 -6 -2.249698 -1.451915 1.127141 0.845356 6 -7 -2.677841 1.403720 1.127141 0.845356 7 -8 -0.104141 6.215314 1.127141 0.845356 8 -9 2.941391 5.135962 1.127141 0.845356 9 -10 5.157814 2.573004 1.127141 0.845356 10 -11 5.994049 -0.546028 1.127141 0.845356 11 -12 4.893547 -3.503478 1.127141 0.845356 12 -13 2.924405 -5.541258 1.127141 0.845356 13 -14 -0.148029 -6.017785 1.127141 0.845356 14 -15 -2.627141 -5.074193 1.127141 0.845356 15 -16 -4.875151 -2.875089 1.127141 0.845356 16 -17 -5.870839 -0.017073 1.127141 0.845356 17 -18 -5.323196 3.008731 1.127141 0.845356 18 -19 -3.206530 5.388295 1.127141 0.845356 19 -20 -0.066692 9.781624 1.127141 0.845356 20 -21 3.472878 8.709434 1.127141 0.845356 21 -22 6.507728 5.767038 1.127141 0.845356 22 -23 7.785165 2.214476 1.127141 0.845356 23 -24 8.399328 -1.574421 1.127141 0.845356 24 -25 6.800275 -4.859852 1.127141 0.845356 25 -26 4.815018 -7.704207 1.127141 0.845356 26 -27 1.467225 -9.172821 1.127141 0.845356 27 -28 -2.087141 -8.750139 1.127141 0.845356 28 -29 -4.889190 -7.058266 1.127141 0.845356 29 -30 -7.229418 -4.226884 1.127141 0.845356 30 -31 -8.383705 -0.766104 1.127141 0.845356 31 -32 -8.046397 3.324808 1.127141 0.845356 32 -33 -6.244512 6.992716 1.127141 0.845356 33 -34 -3.640878 9.240634 1.127141 0.845356 34 -35 -0.193321 12.980386 1.127141 0.845356 35 -36 4.419616 11.889246 1.127141 0.845356 36 -37 7.422593 8.800112 1.127141 0.845356 37 -38 8.980288 4.575882 1.127141 0.845356 38 -39 9.754268 -0.148249 1.127141 0.845356 39 -40 9.183665 -4.975333 1.127141 0.845356 40 -41 7.299718 -9.071946 1.127141 0.845356 41 -42 3.741737 -11.887629 1.127141 0.845356 42 -43 -0.078879 -12.696208 1.127141 0.845356 43 -44 -4.224549 -11.564661 1.127141 0.845356 44 -45 -7.214589 -8.471355 1.127141 0.845356 45 -46 -9.299065 -4.796734 1.127141 0.845356 46 -47 -10.605943 0.502429 1.127141 0.845356 47 -48 -9.908959 5.171527 1.127141 0.845356 48 -49 -7.997551 9.549091 1.127141 0.845356 49 -50 -5.451836 12.027468 1.127141 0.845356 50 -51 11.386764 7.104494 1.127141 0.845356 51 -52 11.511201 1.852825 1.127141 0.845356 52 -53 10.981077 -5.553505 1.127141 0.845356 53 -54 8.896037 -10.180950 1.127141 0.845356 54 -55 4.913386 -13.920422 1.127141 0.845356 55 -56 -0.149537 -15.308473 1.127141 0.845356 56 -57 -4.851433 -14.402173 1.127141 0.845356 57 -58 -8.279141 -10.367520 1.127141 0.845356 58 -59 -10.713190 -6.101504 1.127141 0.845356 59 -60 -11.889255 1.083967 1.127141 0.845356 60 -61 -11.495269 6.789712 1.127141 0.845356 61 -62 -15.019888 2.098340 1.127141 0.845356 63 -63 15.106367 1.521777 1.127141 0.845356 64 -64 -0.634262 17.758193 1.127141 0.845356 nasion -65 -13.176293 0.092571 1.127141 0.845356 left -66 12.269015 -0.119171 1.127141 0.845356 right -67 -13.5179 17.7582 1.127141 0.845356 COMNT -68 13.5958 17.7582 1.127141 0.845356 SCALE - diff --git a/external/fieldtrip/private/eeg_leadfield.m b/external/fieldtrip/private/eeg_leadfield.m deleted file mode 100644 index 99b0ecf..0000000 --- a/external/fieldtrip/private/eeg_leadfield.m +++ /dev/null @@ -1,146 +0,0 @@ -function [lf] = eeg_leadfield(pos, elc, vol) - -% EEG_LEADFIELD electric leadfield for a dipole in spherical or realistic -% volume conductor. This provides a wrapper around the functions EEG_LEADFIELD1 -% and EEG_LEADFIELD4 for spherical models and EEG_LEADFIELDB for models based on -% the boundary element method. -% -% [lf] = eeg_leadfield(pos, elc, vol) -% -% with the input arguments -% pos position dipole (1x3 or Nx3) -% elc position electrodes -% vol structure defining the volume conductor model -% -% a spherical volume conductor model should have the fields -% vol.r radius of spheres -% vol.c conductivity of spheres -% vol.o origin of sphere (can be omitted) -% vol.t constant factors for 4-sphere series expansion (can be omitted) -% -% a realistical volume conductor model should have the fields -% vol.bnd structure array with vertices and triangles of each boundary -% vol.cond conductivity of all compartments -% vol.mat system matrix, which can include the electrode interpolation -% vol.tra transfer matrix for interpolation from vertices to electrodes -% the BEM compartment boundaries are described by a structure array with -% vol.bnd(i).pnt -% vol.bnd(i).pnt -% -% See also MEG_LEADFIELD, READ_ASA_VOL - -% Copyright (C) 2002, Robert Oostenveld -% -% $Log: eeg_leadfield.m,v $ -% Revision 1.5 2003/10/07 08:40:43 roberto -% moved BEM specific code into a separate function -% -% Revision 1.4 2003/07/29 11:54:02 roberto -% removed ellipsiod support (untested/unused sofar) -% renamed volume into vol -% updated help and comments -% -% Revision 1.3 2003/06/03 08:29:39 roberto -% *** empty log message *** -% -% Revision 1.2 2003/03/11 14:45:36 roberto -% updated help and copyrights -% - -% approximate timing per EEG channel on a PIII/800Hz -% m-code p-code mex-file -% 1 sphere 0.30 0.30 0.15 -% 4 sphere 0.56 0.56 1.84 (!!) with Nmax=10 -% 4 sphere 1.46 1.46 5.36 (!!) with Nmax=30 - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% spherical volume conductor model -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if isfield(vol, 'r') - - % FIXME, this is not consistent between spherical and BEM - % sort the spheres from the smallest to the largest - [vol.r, indx] = sort(vol.r); - vol.c = vol.c(indx); - - Nspheres = length(vol.c); - if length(vol.r)~=Nspheres - error('the number of spheres in the volume conductor model is ambiguous'); - end - - if isfield(vol, 'o') - % shift the origin of the spheres, electrodes and dipole - elc = elc - repmat(vol.o, size(elc,1), 1); - pos = pos - repmat(vol.o, size(pos,1), 1); - end - - if Nspheres==1 - if size(pos,1)>1 - % loop over multiple dipoles - lf = zeros(size(elc,1),3*size(pos,1)); - for i=1:size(pos,1) - lf(:,(3*i-2):(3*i)) = eeg_leadfield1(pos(i,:), elc, vol); - end - else - % only single dipole - lf = eeg_leadfield1(pos, elc, vol); - end - - elseif Nspheres==2 - vol.r = [vol.r(1) vol.r(2) vol.r(2) vol.r(2)]; - vol.c = [vol.c(1) vol.c(2) vol.c(2) vol.c(2)]; - if size(pos,1)>1 - % loop over multiple dipoles - lf = zeros(size(elc,1),3*size(pos,1)); - for i=1:size(pos,1) - lf(:,(3*i-2):(3*i)) = eeg_leadfield4(pos(i,:), elc, vol); - end - else - % only single dipole - lf = eeg_leadfield4(pos, elc, vol); - end - - elseif Nspheres==3 - vol.r = [vol.r(1) vol.r(2) vol.r(3) vol.r(3)]; - vol.c = [vol.c(1) vol.c(2) vol.c(3) vol.c(3)]; - if size(pos,1)>1 - % loop over multiple dipoles - lf = zeros(size(elc,1),3*size(pos,1)); - for i=1:size(pos,1) - lf(:,(3*i-2):(3*i)) = eeg_leadfield4(pos(i,:), elc, vol); - end - else - % only single dipole - lf = eeg_leadfield4(pos, elc, vol); - end - - elseif Nspheres==4 - if size(pos,1)>1 - % loop over multiple dipoles - lf = zeros(size(elc,1),3*size(pos,1)); - for i=1:size(pos,1) - lf(:,(3*i-2):(3*i)) = eeg_leadfield4(pos(i,:), elc, vol); - end - else - % only single dipole - lf = eeg_leadfield4(pos, elc, vol); - end - - else - error('more than 4 concentric spheres are not supported'); - end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% realistic BEM volume conductor model -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif isfield(vol, 'bnd') - - lf = eeg_leadfieldb(pos, elc, vol); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% unrecognized volume conductor model -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -else - error('unrecognized volume conductor model'); -end - diff --git a/external/fieldtrip/private/eeg_leadfield1.m b/external/fieldtrip/private/eeg_leadfield1.m deleted file mode 100644 index b0628db..0000000 --- a/external/fieldtrip/private/eeg_leadfield1.m +++ /dev/null @@ -1,124 +0,0 @@ -function [lf, lforig] = eeg_leadfield1(R, elc, vol); - -% EEG_LEADFIELD1 electric leadfield for a dipole in a single sphere -% -% [lf] = eeg_leadfield1(R, elc, vol) -% -% with input arguments -% R position dipole (vector of length 3) -% elc position electrodes -% and vol being a structure with the elements -% vol.r radius of sphere -% vol.c conductivity of sphere - -% Copyright (C) 2002, Robert Oostenveld -% -% this implementation is adapted from -% Luetkenhoener, Habilschrift '92 -% the original reference is -% R. Kavanagh, T. M. Darccey, D. Lehmann, and D. H. Fender. Evaluation of methods for three-dimensional localization of electric sources in the human brain. IEEE Trans Biomed Eng, 25:421-429, 1978. -% -% $Log: eeg_leadfield1.m,v $ -% Revision 1.1 2009/01/21 10:32:38 roboos -% moved from forwinv/* and forwinv/mex/* directory to forwinv/private/* to make the CVS layout consistent with the release version -% -% Revision 1.11 2008/12/24 13:33:45 roboos -% fixed typo in documentation -% -% Revision 1.10 2006/02/09 08:30:28 roboos -% scale with conductivity in case of dipole in the origin (thanks to Denise van Barneveld) -% -% Revision 1.9 2006/01/20 09:40:09 roboos -% disabled the dipole-inside-brain check (for EEGLAB) -% use precomputed c5 to capture divide by zero situation -% -% Revision 1.8 2004/10/25 16:25:25 roboos -% re-enabled check for dipole outside head -% -% Revision 1.7 2003/12/05 09:48:45 roberto -% disabled error check for dipole outside brain [for EEGLAB] -% -% Revision 1.6 2003/12/04 10:43:51 roberto -% added error when dipole is outside brain compartment -% -% Revision 1.5 2003/07/29 16:04:55 roberto -% fixed bug in determining whether electrodes are lying on sphere surface -% -% Revision 1.4 2003/07/29 15:53:09 roberto -% minor change to the projection of the electrodes to the sphere (now default) -% -% Revision 1.3 2003/07/29 15:42:03 roberto -% found and fixed a bug in the handling of electrodes and dipoles on one line -% changed the name of the constants and added a constant -% -% Revision 1.2 2003/03/11 14:45:36 roberto -% updated help and copyrights -% - -Nchans = size(elc, 1); -lf = zeros(Nchans,3); - -% always take the outermost sphere, this makes comparison with the 4-sphere computation easier -[vol.r, indx] = max(vol.r); -vol.c = vol.c(indx); - -% check whether the electrode ly on the sphere, allowing 0.5% tolerance -dist = sqrt(sum(elc.^2,2)); -if any(abs(dist-vol.r)>vol.r*0.005) - warning('electrodes do not ly on sphere surface -> using projection') -end -elc = vol.r * elc ./ [dist dist dist]; - -% check whether the dipole is inside the brain [disabled for EEGLAB] -% if sqrt(sum(R.^2))>=vol.r -% error('dipole is outside the brain compartment'); -% end - -c0 = norm(R); -c1 = vol.r; -c2 = 4*pi*c0^2*vol.c; - -if c0==0 - % the dipole is in the origin, this can and should be handeled as an exception - [phi, el] = cart2sph(elc(:,1), elc(:,2), elc(:,3)); - theta = pi/2 - el; - lf(:,1) = sin(theta).*cos(phi); - lf(:,2) = sin(theta).*sin(phi); - lf(:,3) = cos(theta); - % the potential in a homogenous sphere is three times the infinite medium potential - lf = 3/(c1^2*4*pi*vol.c)*lf; - -else - for i=1:Nchans - % use another name for the electrode, in accordance with lutkenhoner1992 - r = elc(i,:); - - c3 = r-R; - c4 = norm(c3); - c5 = c1^2 * c0^2 - dot(r,R)^2; % lutkenhoner A.11 - c6 = c0^2*r - dot(r,R)*R; % lutkenhoner, just after A.17 - - % the original code reads (cf. lutkenhoner1992 equation A.17) - % lf(i,:) = ((dot(R, r/norm(r) - (r-R)/norm(r-R))/(norm(cross(r,R))^2) + 2/(norm(r-R)^3)) * cross(R, cross(r, R)) + ((norm(r)^2-norm(R)^2)/(norm(r-R)^3) - 1/norm(r)) * R) / (4*pi*vol.c(1)*norm(R)^2); - - % but more efficient execution of the code is achieved by some precomputations - if c5<1000*eps - % the dipole lies on a single line with the electrode - lf(i,:) = (2/c4^3 * c6 + ((c1^2-c0^2)/c4^3 - 1/c1) * R) / c2; - else - % nothing wrong, do the complete computation - lf(i,:) = ((dot(R, r/c1 - c3/c4)/c5 + 2/c4^3) * c6 + ((c1^2-c0^2)/c4^3 - 1/c1) * R) / c2; - end - end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% fast cross product -function [c] = cross(a,b) -c = [a(2)*b(3)-a(3)*b(2) a(3)*b(1)-a(1)*b(3) a(1)*b(2)-a(2)*b(1)]; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% fast dot product -function [c] = dot(a,b) -c = sum(a.*b); - diff --git a/external/fieldtrip/private/eeg_leadfield4.m b/external/fieldtrip/private/eeg_leadfield4.m deleted file mode 100644 index 754fc09..0000000 --- a/external/fieldtrip/private/eeg_leadfield4.m +++ /dev/null @@ -1,150 +0,0 @@ -function [lf, vol] = eeg_leadfield4(R, elc, vol) - -% EEG_LEADFIELD4 electric leadfield for a dipole in 4 concentric spheres -% -% [lf] = eeg_leadfield4(R, elc, vol) -% -% with input arguments -% R position of the dipole -% elc position of the electrodes -% and vol being a structure with the elements -% vol.r radius of the 4 spheres -% vol.c conductivity of the 4 spheres -% vol.t constant factors for series expansion (optional) -% -% See also EEG_LEADFIELD4_PREPARE for precomputing the constant factors, -% which can save time when multiple leadfield computations are done. - -% Copyright (C) 2002, Robert Oostenveld -% -% this implementation is adapted from -% Lutkenhoner, Habilschrift 1992. -% the original reference is -% Cuffin BN, Cohen D. Comparison of the magnetoencephalogram and electroencephalogram. Electroencephalogr Clin Neurophysiol. 1979 Aug;47(2):132-46. -% -% $Log: eeg_leadfield4.m,v $ -% Revision 1.1 2009/01/21 10:32:38 roboos -% moved from forwinv/* and forwinv/mex/* directory to forwinv/private/* to make the CVS layout consistent with the release version -% -% Revision 1.8 2008/12/24 13:33:27 roboos -% changed some & and | into && and || -% -% Revision 1.7 2006/05/01 08:13:51 roboos -% fixed literature reference -% -% Revision 1.6 2003/12/05 09:48:45 roberto -% disabled error check for dipole outside brain [for EEGLAB] -% -% Revision 1.5 2003/12/04 10:43:51 roberto -% added error when dipole is outside brain compartment -% -% Revision 1.4 2003/07/29 16:04:55 roberto -% fixed bug in determining whether electrodes are lying on sphere surface -% -% Revision 1.3 2003/07/29 15:52:44 roberto -% fixed a bug in the implementation of eeg_leadfield4, caused by mixing the constants of -% lutkenhoner and cuffin -% furthermore multiple cosmetic changes and default projection of electrodes to sphere -% -% Revision 1.2 2003/03/11 14:45:36 roberto -% updated help and copyrights -% - -% sort the spheres from the smallest to the largest -[vol.r, indx] = sort(vol.r); -[vol.c] = vol.c(indx); - -% use more convenient names for the radii and conductivity -r1 = vol.r(1); c1 = vol.c(1); -r2 = vol.r(2); c2 = vol.c(2); -r3 = vol.r(3); c3 = vol.c(3); -r4 = vol.r(4); c4 = vol.c(4); - -% check whether the electrode ly on the sphere, allowing 0.5% tolerance -dist = sqrt(sum(elc.^2,2)); -if any(abs(dist-r4)>r4*0.005) - warning('electrodes do not ly on sphere surface -> using projection') -end -elc = r4 * elc ./ [dist dist dist]; - -% check whether the dipole is inside the brain [disabled for EEGLAB] -% if sqrt(sum(R.^2))>=r1 -% error('dipole is outside the brain compartment'); -% end - -% rotate everything so that the dipole is along the pos. z-axis -% only if the dipole is not in the origin or along the positive z-axis -if R(1)~=0 | R(2)~=0 - % compute the rotation matrix - % the inverse rotation matrix is the transposed of this one - val1 = norm(R); - val2 = norm(R(1:2)); - rot(1,1) = R(1) * R(3) / (val1 * val2); - rot(1,2) = R(2) * R(3) / (val1 * val2); - rot(1,3) = -1.0 * val2 / val1; - rot(2,1) = -1.0 * R(2) / val2; - rot(2,2) = R(1) / val2; - rot(2,3) = 0; - rot(3,:) = R ./ val1; - % rotate the electrodes - elc = elc*rot'; -elseif R(1)==0 && R(2)==0 && R(3)<0 - % dipole on negative z-axis, rotation is very simple: around x-axis - elc(2,:) = -elc(2,:); - elc(3,:) = -elc(3,:); -else - % dipole is on positive z-axis, nothing has to be done -end - -% compute the constant factors for the sphere configuration if needed -if ~isfield(vol, 't') - vol.t = eeg_leadfield4_prepare(vol); -end - -Nchans = size(elc,1); -lf = zeros(Nchans,3); -Nmax = length(vol.t); -n = 1:Nmax; -f = norm(R)/r4; % following cuffin1979 -% c = r2/r4; % following cuffin1979 -% d = r3/r4; % following cuffin1979 - -% this code is to cross-validate the lutkenhoner and cuffin implementations -% [lut_t, cuf_t] = eeg_leadfield4_prepare(vol); -% lut_c = (2*n+1).^4.*f.^(n-1) ./ (lut_t.*4*pi*c4*r4^2); -% cuf_c = (2*n+1).^4.*f.^(n-1) .*(c*d).^(2.*n+1) ./ (cuf_t.*4*pi*c4*r4^2); - -% given a fixed volume conductor, these only need to be computed once for all electrodes -const = (2*n+1).^4.*f.^(n-1) ./ (vol.t.*4*pi*c4*r4^2); - -for i=1:Nchans - % convert the position of the electrodes to spherical coordinates - [phi, el] = cart2sph(elc(i,1), elc(i,2), elc(i,3)); - - % change from colatitude to latitude and compute the cosine - cos_theta = cos(pi/2-el); - - % the series summation starts at zero - s_x = 0; - s_z = 0; - - for n=1:Nmax - P0 = plgndr(n,0,cos_theta); % zero'th order Legendre - P1 = plgndr(n,1,cos_theta); % first order Legendre - s_x = s_x + const(n)*P1/n; % s_y is identical - s_z = s_z + const(n)*P0; - end - - lf(i,1) = -cos(phi) * s_x; - lf(i,2) = -sin(phi) * s_x; % s_y is identical to s_x - lf(i,3) = 1 * s_z; -end - -% apply the inverse rotation to the leadfield matrix -if R(1)~=0 || R(2)~=0 - lf = lf*rot; -elseif R(1)==0 && R(2)==0 && R(3)<0 - lf(2,:) = -lf(2,:); - lf(3,:) = -lf(3,:); -end - diff --git a/external/fieldtrip/private/eeg_leadfield4_prepare.m b/external/fieldtrip/private/eeg_leadfield4_prepare.m deleted file mode 100644 index c0ad935..0000000 --- a/external/fieldtrip/private/eeg_leadfield4_prepare.m +++ /dev/null @@ -1,88 +0,0 @@ -function [lut_t, cuf_t] = eeg_leadfield4_prepare(vol, Nmax); - -% EEG_LEADFIELD4_PREPARE computes constant factors for series expansion -% for the 4 concentric sphere electric leadfield computation -% -% use this function prior to repeated calls of eeg_leadfield4 according to -% vol.t = eeg_leadfield4_prepare(vol, N); -% where -% vol.r radius of the 4 spheres -% vol.c conductivity of the 4 spheres -% and N is the number of terms for the series (default 60). The constant -% factors t then do not have to be computed each time in eeg_leadfield4. -% -% See also EEG_LEADFIELD4 - -% Copyright (C) 2002, Robert Oostenveld -% -% this implementation is adapted from -% Lutkenhoner, Habilschrift 1992. -% which again is taken from -% B. N. Cuffin and D. Cohen. Comparion of the Magnetoencephalogram and the Electroencephalogram. Electroencephalogr Clin Neurophysiol, 47:131-146, 1979. -% -% $Log: eeg_leadfield4_prepare.m,v $ -% Revision 1.1 2009/01/21 10:46:10 roboos -% moved from forwinv/* and forwinv/mex/* directory to forwinv/private/* to make the CVS layout consistent with the release version -% -% Revision 1.4 2003/07/29 16:02:07 roberto -% minor cosmetic change in the constants -% -% Revision 1.3 2003/07/29 15:52:44 roberto -% fixed a bug in the implementation of eeg_leadfield4, caused by mixing the constants of -% lutkenhoner and cuffin -% furthermore multiple cosmetic changes and default projection of electrodes to sphere -% -% Revision 1.2 2003/03/11 14:45:36 roberto -% updated help and copyrights -% - -% sort the spheres from the smallest to the largest -[vol.r, indx] = sort(vol.r); -[vol.c] = vol.c(indx); - -r1 = vol.r(1); c1 = vol.c(1); -r2 = vol.r(2); c2 = vol.c(2); -r3 = vol.r(3); c3 = vol.c(3); -r4 = vol.r(4); c4 = vol.c(4); - -if nargin==1 - Nmax = 60; -end - -% these are the constants of cuffin1979 -k1 = c1/c2; -k2 = c2/c3; -k3 = c3/c4; - -for n=1:Nmax - % according to lutkenhoner1992 the constant C is - % lut_t(n) = ((n*c1/c2+n+1)*(n*c2/c3+n+1)+n*(n+1)*(c1/c2-1)*(c2/c3-1)*(r1/r2)^(2*n+1)) * ... - % ((n*c3/c4+n+1)+(n+1)*(c3/c4-1)*(r3/r4)^(2*n+1)) + ... - % ((c1/c2-1)*((n+1)*c2/c3+n)*(r1/r3)^(2*n+1)+(n*c1/c2+n+1)*(c2/c3-1)*(r2/r3)^(2*n+1)) * ... - % (n+1)*(n*(c3/c4-1)+((n+1)*c3/c4+n)*(r3/r4)^(2*n+1)); - % which can be rewritten as - lut_t(n) = ((n*k1+n+1)*(n*k2+n+1)+n*(n+1)*(k1-1)*(k2-1)*(r1/r2)^(2*n+1)) * ... - ((n*k3+n+1)+(n+1)*(k3-1)*(r3/r4)^(2*n+1)) + ... - ((k1-1)*((n+1)*k2+n)*(r1/r3)^(2*n+1)+(n*k1+n+1)*(k2-1)*(r2/r3)^(2*n+1)) * ... - (n+1)*(n*(k3-1)+((n+1)*k3+n)*(r3/r4)^(2*n+1)); - -end - -% for debugging purposes, it can also give the constants of cuffin19979 -if nargout>1 - % some extra constants of cuffin1979 - b = r1/r4; - c = r2/r4; - d = r3/r4; - - % according to cuffin1979 the constant Tau is (re-entered on 25 sept 2002) - % but this requires also slightly other constants in the eeg_leadfield4 function - for n=1:Nmax - cuf_t(n) = d^(2*n+1) * (b^(2*n+1)*n*(k1-1)*(k2-1)*(n+1)... - + c^(2*n+1)*(k1*n+n+1)*(k2*n+n+1))... - *((k3*n+n+1)+(n+1)*(k3-1)*d^(2*n+1))... - +(n+1)*c^(2*n+1)*(b^(2*n+1)*(k1-1)*(k2*n+k2+n)... - +c^(2*n+1)*(k1*n+n+1)*(k2-1))... - *(n*(k3-1)+(k3*n+k3+n)*d^(2*n+1)); - end -end diff --git a/external/fieldtrip/private/eeg_leadfieldb.m b/external/fieldtrip/private/eeg_leadfieldb.m deleted file mode 100644 index 3d62a54..0000000 --- a/external/fieldtrip/private/eeg_leadfieldb.m +++ /dev/null @@ -1,148 +0,0 @@ -function [lf] = eeg_leadfieldb(pos, elc, vol) - -% EEG_LEADFIELDB computes the electric leadfield for a dipole in a volume -% using the boundary element method -% -% [lf] = eeg_leadfieldb(pos, elc, vol) -% -% with the input arguments -% pos position dipole (1x3 or Nx3) -% elc position electrodes (optional, can be empty) -% vol volume conductor model -% -% the volume conductor model is a structure and should have the fields -% vol.bnd structure array with vertices and triangles of each boundary -% vol.cond conductivity of all compartments -% vol.mat system matrix, which can include the electrode interpolation -% -% the compartment boundaries are described by a structure array with -% vol.bnd(i).pnt -% vol.bnd(i).pnt - -% Copyright (C) 2003, Robert Oostenveld -% -% $Log: eeg_leadfieldb.m,v $ -% Revision 1.5 2009/04/23 15:06:14 roboos -% added patch from Cristiano -% -% Revision 1.4 2009/03/30 15:06:14 roboos -% added the patch from Alexandre to support openmeeg -% -% Revision 1.3 2009/02/02 13:12:53 roboos -% small fix, cpbem->bemcp -% -% Revision 1.2 2009/02/02 12:59:26 roboos -% added bemcp implementation, do not use vol.tra any more, made some changes to the checks on the input structures, use voltype in switch ladder -% -% Revision 1.1 2009/01/21 10:32:38 roboos -% moved from forwinv/* and forwinv/mex/* directory to forwinv/private/* to make the CVS layout consistent with the release version -% -% Revision 1.3 2008/04/14 20:54:35 roboos -% be more explicit about BEM type -% -% Revision 1.2 2005/12/06 11:41:07 roboos -% added support for dipoli models -% restructured the whole code -% combine electrode transfer and system matrix in a single matrix to speed forward computations up -% -% Revision 1.1 2003/10/07 08:40:22 roberto -% made separate function for BEM, based on part of eeg_leadfield.m -% - - -% do some sanity checks -if ~isfield(vol, 'bnd') - error('there are no compartment boundaries present'); -end - -if length(vol.bnd)~=length(vol.cond) - error('the number of compartments in the volume in ambiguous'); -end - -if ~isfield(vol, 'mat') - error('there is no BEM system matrix present'); -end - -% determine the number of compartments -ncmp = length(vol.bnd); - -% the number of rows in the leadfield matrix should either correspond to -% the number of electrodes, to the number of vertices of the skin -% compartment or to the total number of vertices -nelc = size(elc, 1); -nskin = size(vol.bnd(vol.skin).pnt,1); -nall = 0; -for i=1:ncmp - nall = nall + size(vol.bnd(i).pnt,1); -end -if size(vol.mat,1)==nelc - % the output leadfield corresponds to the number of electrodes -elseif size(vol.mat,1)==nskin - % the output leadfield corresponds to the number skin vertices -elseif size(vol.mat,1)==nall - % the output leadfield corresponds to the total number of vertices -elseif strcmp(voltype(vol),'openmeeg') - % this is handled differently, although at the moment I don't know why -else - error('unexpected size of vol.mat') -end - -% determine the conductivity of the source compartment -cond = vol.cond(vol.source); - -% compute the infinite medium potential on all vertices -switch voltype(vol) - case 'avo' - % the system matrix was computed using code from Adriaan van Oosterom - % the code by Adriaan van Oosterom does not implement isolated source approach - lf = []; - for i=1:ncmp - lf = [lf; inf_medium_leadfield(pos, vol.bnd(i).pnt, mean(vol.sigmas(i,:)))]; - end - - case 'dipoli' - % the system matrix was computed using Thom Oostendorp's DIPOLI - % concatenate the vertices of all compartment boundaries in a single Nx3 matrix - pnt = []; - for i=1:ncmp - pnt = [pnt; vol.bnd(i).pnt]; - end - % dipoli incorporates the conductivity into the system matrix - lf = inf_medium_leadfield(pos, pnt, 1); - - case 'asa' - % the system matrix was computed using ASA from www.ant-neuro.com - % concatenate the vertices of all compartment boundaries in a single Nx3 matrix - pnt = []; - for i=1:ncmp - pnt = [pnt; vol.bnd(i).pnt]; - end - % assume that isolated potential approach was used - lf = inf_medium_leadfield(pos, pnt, cond); - - case 'bemcp' - % the system matrix was computed using code from Christopher Phillips - cond = [vol.cond 0]; % add the conductivity of air for simplicity - lf = cell(1,ncmp); - % loop over boundaries and compute the leadfield for each - for i=1:ncmp - co = (cond(i)+cond(i+1))/2 ; - lf{i} = inf_medium_leadfield(pos, vol.bnd(i).pnt, co); - end - % concatenate the leadfields - lf = cat(1, lf{:}); - - case 'openmeeg' - % the system matrix is computed using OpenMEEG (Symmetric BEM) - lf = openmeeg_lf_eeg(pos, elc, vol); - - otherwise - error('unsupported type of volume conductor (%s)\n', voltype(vol)); -end % switch voltype - -if isfield(vol, 'mat') && ~voltype(vol, 'openmeeg') - % compute the bounded medium potential on all vertices - % this may include the bilinear interpolation from vertices towards electrodes - lf = vol.mat * lf; -end - diff --git a/external/fieldtrip/private/electrodenormalize.m b/external/fieldtrip/private/electrodenormalize.m deleted file mode 100644 index 1cb7020..0000000 --- a/external/fieldtrip/private/electrodenormalize.m +++ /dev/null @@ -1,20 +0,0 @@ -function [norm] = electrodenormalize(cfg); - -% ELECTRODENORMALIZE is deprecated, please use ELECTRODEREALIGN - -% Copyright (C) 2005-2006, Robert Oostenveld -% -% $Log: electrodenormalize.m,v $ -% Revision 1.11 2006/09/13 07:20:06 roboos -% renamed electrodenormalize to electroderealign, added "deprecated"-warning to the old function -% -% Revision 1.10 2006/09/13 07:09:24 roboos -% Implemented support for cfg.method=interactive, using GUI for specifying and showing transformations. Sofar only for electrodes+headsurface. -% -% Revision 1.9 2006/09/12 15:26:06 roboos -% implemented support for aligning electrodes to the skin surface, extended and improved documentation - -warning('ELECTRODENORMALIZE is deprecated, please use ELECTRODEREALIGN'); - -[norm] = rejectvisual(cfg); - diff --git a/external/fieldtrip/private/electroderealign.m b/external/fieldtrip/private/electroderealign.m deleted file mode 100644 index 0c39dfd..0000000 --- a/external/fieldtrip/private/electroderealign.m +++ /dev/null @@ -1,790 +0,0 @@ -function [norm] = electroderealign(cfg) - -% ELECTRODEREALIGN rotates and translates electrode positions to -% template electrode positions or towards the head surface. It can -% either perform a rigid body transformation, in which only the -% coordinate system is changed, or it can apply additional deformations -% to the input electrodes. -% -% Use as -% [elec] = electroderealign(cfg) -% -% Three different methods for aligning the input electrodes are implemented: -% based on a warping method, based on the fiducials or interactive with a -% graphical user interface. Each of these approaches is described below. -% -% 1) You can apply a spatial deformation method (i.e. 'warp') that -% automatically minimizes the distance between the electrodes and the -% averaged standard. The warping methods use a non-linear search to -% optimize the error between input and template electrodes or the -% head surface. -% -% 2) You can apply a rigid body realignment based on three fiducial locations. -% Realigning using the fiducials only ensures that the fiducials (typically -% nose, left and right ear) are along the same axes in the input electrode -% set as in the template electrode set. -% -% 3) You can display the electrode positions together with the skin surface, -% and manually (using the graphical user interface) adjust the rotation, -% translation and scaling parameters, so that the two match. -% -% The configuration can contain the following options -% cfg.method = string representing the method for aligning or placing the electrodes -% 'rigidbody' apply a rigid-body warp -% 'globalrescale' apply a rigid-body warp with global rescaling -% 'traditional' apply a rigid-body warp with individual axes rescaling -% 'nonlin1' apply a 1st order non-linear warp -% 'nonlin2' apply a 2nd order non-linear warp -% 'nonlin3' apply a 3rd order non-linear warp -% 'nonlin4' apply a 4th order non-linear warp -% 'nonlin5' apply a 5th order non-linear warp -% 'realignfiducial' realign the fiducials -% 'interactive' realign manually using graphical user interface -% 'position' position electrodes manually using graphical user interface -% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), -% see CHANNELSELECTION for details -% cfg.fiducial = cell-array with the name of three fiducials used for -% realigning (default = {'nasion', 'lpa', 'rpa'}) -% cfg.casesensitive = 'yes' or 'no', determines whether string comparisons -% between electrode labels are case sensitive (default = 'yes') -% cfg.feedback = 'yes' or 'no' (default = 'no') -% cfg.outline = 'yes' or 'no' to add the outline characteristic landmarks such as sulci (default = 'no') -% -% The electrode set that will be realigned is specified as -% cfg.elecfile = string with filename, or alternatively -% cfg.elec = structure with electrode definition -% -% If you want to align the electrodes to a single template electrode set -% or to multiple electrode sets (which will be averaged), you should -% specify the template electrode sets as -% cfg.template = single electrode set that serves as standard -% or -% cfg.template{1..N} = list of electrode sets that are averaged into the standard -% The template electrode sets can be specified either as electrode -% structures (i.e. when they are already read in memory) or as electrode -% files. -% -% If you only want to realign using the fiducials, the template electrode -% set only has to contain the three fiducials, e.g. -% cfg.template.pnt(1,:) = [110 0 0] % location of the nose -% cfg.template.pnt(2,:) = [0 90 0] % left ear -% cfg.template.pnt(3,:) = [0 -90 0] % right ear -% cfg.template.label = {''nasion', 'lpa', 'rpa'} -% -% If you want to align existing electrodes to the head surface or position -% new electrodes on the head surface, you should specify the head surface as -% cfg.headshape = a filename containing headshape, a structure containing a -% single triangulated boundary, or a Nx3 matrix with surface -% points -% -% See also READ_ELEC, VOLUMEREALIGN - -% Copyright (C) 2005-2009, Robert Oostenveld -% -% $Log: electroderealign.m,v $ -% Revision 1.13 2009/06/30 07:10:11 roboos -% first proper implementation of manual clicking of electrode locations (using scalp mesh) -% -% Revision 1.12 2009/06/04 10:03:46 roboos -% fixed problem in the input og cfg.headshape when it was not required -% -% Revision 1.11 2009/05/25 08:05:18 roboos -% ensure that cfg.headshape is a sturct and not a config object (in case tracking is on) -% -% Revision 1.10 2009/05/14 19:19:30 roboos -% only include unique headshape points -% -% Revision 1.9 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.8 2008/06/23 08:17:23 roboos -% allow method=interactive with both template and headshape (for Vladimir) -% repositioned global variable fb -% reordered help -% changed transform_headshape into transform_sens -% renamed internal variable surf into headshape (used in interactive plotting) -% -% Revision 1.7 2008/03/05 10:46:35 roboos -% moved electrode reading functionality from read_fcdc_elec to read_sens, switched to the use of the new function -% -% Revision 1.6 2007/08/06 09:20:14 roboos -% added support for bti_hs -% -% Revision 1.5 2007/07/26 08:00:09 roboos -% also deal with cfg.headshape if specified as surface, set of points or ctf_hs file. -% the construction of the tri is now done consistently for all headshapes if tri is missing -% -% Revision 1.4 2007/02/13 15:12:51 roboos -% removed cfg.plot3d option -% -% Revision 1.3 2006/12/12 11:28:33 roboos -% moved projecttri subfunction into seperate function -% -% Revision 1.2 2006/10/04 07:10:07 roboos -% updated documentation -% -% Revision 1.1 2006/09/13 07:20:06 roboos -% renamed electrodenormalize to electroderealign, added "deprecated"-warning to the old function -% -% Revision 1.10 2006/09/13 07:09:24 roboos -% Implemented support for cfg.method=interactive, using GUI for specifying and showing transformations. Sofar only for electrodes+headsurface. -% -% Revision 1.9 2006/09/12 15:26:06 roboos -% implemented support for aligning electrodes to the skin surface, extended and improved documentation -% -% Revision 1.8 2006/04/20 09:58:34 roboos -% updated documentation -% -% Revision 1.7 2006/04/19 15:42:53 roboos -% replaced call to warp_pnt with new function name warp_optim -% -% Revision 1.6 2006/03/14 08:16:00 roboos -% changed function call to warp3d into warp_apply (thanks to Arno) -% -% Revision 1.5 2005/05/17 17:50:37 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.4 2005/03/21 15:49:43 roboos -% added cfg.casesensitive for string comparison of electrode labels -% added cfg.feedback and cfg.plot3d option for debugging -% changed output: now ALL electrodes of the input are rerurned, after applying the specified transformation -% fixed small bug in feedback regarding distarnce prior/after realignfiducials) -% added support for various warping strategies, a.o. traditional, rigidbody, nonlin1-5, etc. -% -% Revision 1.3 2005/03/16 09:18:56 roboos -% fixed bug in fprintf feedback, instead of giving mean squared distance it should give mean distance before and after normalization -% -% Revision 1.2 2005/01/18 12:04:39 roboos -% improved error handling of missing fiducials -% added other default fiducials -% changed debugging output -% -% Revision 1.1 2005/01/17 14:56:06 roboos -% new implementation -% - -fieldtripdefs - -% this is used for feedback of the lower-level functions -global fb - -% set the defaults -if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end -if ~isfield(cfg, 'feedback'), cfg.feedback = 'no'; end -if ~isfield(cfg, 'outline'), cfg.outline = 'no'; end -if ~isfield(cfg, 'casesensitive'), cfg.casesensitive = 'yes'; end -if ~isfield(cfg, 'headshape'), cfg.headshape = []; end % for triangulated head surface, without labels -if ~isfield(cfg, 'template'), cfg.template = []; end % for electrodes or fiducials, always with labels - -if isfield(cfg, 'headshape') && isa(cfg.headshape, 'config') - % convert the nested config-object back into a normal structure - cfg.headshape = struct(cfg.headshape); -end - -% this is a common mistake which can be accepted -cfg = checkconfig(cfg, 'renamed', {'realignfiducials', 'realignfiducial'}); -% rename the default warp to one of the method recognized by the warping toolbox -cfg = checkconfig(cfg, 'renamed', {'warp', 'traditional'}); - -if strcmp(cfg.feedback, 'yes') - % use the global fb field to tell the warping toolbox to print feedback - fb = 1; -else - fb = 0; -end - -usetemplate = isfield(cfg, 'template') && ~isempty(cfg.template); -useheadshape = isfield(cfg, 'headshape') && ~isempty(cfg.headshape); - -if ~usetemplate && ~useheadshape - error('you should either specify template electrode positions, template fiducials or a head shape'); -end - -if usetemplate - % get the template electrode definitions - if ~iscell(cfg.template) - cfg.template = {cfg.template}; - end - Ntemplate = length(cfg.template); - for i=1:Ntemplate - if isstruct(cfg.template{i}) - template(i) = cfg.template{i}; - else - template(i) = read_sens(cfg.template{i}); - end - end -end - -if useheadshape - % get the surface describing the head shape - if isstruct(cfg.headshape) && isfield(cfg.headshape, 'pnt') - % use the headshape surface specified in the configuration - headshape = cfg.headshape; - elseif isnumeric(cfg.headshape) && size(cfg.headshape,2)==3 - % use the headshape points specified in the configuration - headshape.pnt = cfg.headshape; - elseif ischar(cfg.headshape) - % read the headshape from file - headshape = read_headshape(cfg.headshape); - else - error('cfg.headshape is not specified correctly') - end - if ~isfield(headshape, 'tri') - % generate a closed triangulation from the surface points - headshape.pnt = unique(headshape.pnt, 'rows'); - headshape.tri = projecttri(headshape.pnt); - end -end - -% get the electrode definition that should be warped -if isfield(cfg, 'elec') - elec = cfg.elec; -elseif isfield(cfg, 'elecfile') - elec = read_sens(cfg.elecfile); -else - % start with an empty set of electrodes (usefull for manual positioning) - elec = []; - elec.pnt = zeros(0,3); - elec.label = cell(0,1); -end - -% remember the original electrode locations and labels -orig = elec; - -% convert all labels to lower case for string comparisons -% this has to be done AFTER keeping the original labels and positions -if strcmp(cfg.casesensitive, 'no') - for i=1:length(elec.label) - elec.label{i} = lower(elec.label{i}); - end - for j=1:length(template) - for i=1:length(template(j).label) - template(j).label{i} = lower(template(j).label{i}); - end - end -end - -if strcmp(cfg.feedback, 'yes') - % create an empty figure, continued below... - figure - axis equal - axis vis3d - hold on - xlabel('x') - ylabel('y') - zlabel('z') -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if usetemplate && any(strcmp(cfg.method, {'rigidbody', 'globalrescale', 'traditional', 'nonlin1', 'nonlin2', 'nonlin3', 'nonlin4', 'nonlin5'})) - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - % determine electrode selection and overlapping subset for warping - cfg.channel = channelselection(cfg.channel, elec.label); - for i=1:Ntemplate - cfg.channel = channelselection(cfg.channel, template(i).label); - end - - % make subselection of electrodes - [cfgsel, datsel] = match_str(cfg.channel, elec.label); - elec.label = elec.label(datsel); - elec.pnt = elec.pnt(datsel,:); - for i=1:Ntemplate - [cfgsel, datsel] = match_str(cfg.channel, template(i).label); - template(i).label = template(i).label(datsel); - template(i).pnt = template(i).pnt(datsel,:); - end - - % compute the average of the template electrode positions - all = []; - for i=1:Ntemplate - all = cat(3, all, template(i).pnt); - end - avg = mean(all,3); - stderr = std(all, [], 3); - - fprintf('warping electrodes to template... '); % the newline comes later - [norm.pnt, norm.m] = warp_optim(elec.pnt, avg, cfg.method); - norm.label = elec.label; - - dpre = mean(sqrt(sum((avg - elec.pnt).^2, 2))); - dpost = mean(sqrt(sum((avg - norm.pnt).^2, 2))); - fprintf('mean distance prior to warping %f, after warping %f\n', dpre, dpost); - - if strcmp(cfg.feedback, 'yes') - % plot all electrodes before warping - my_plot3(elec.pnt, 'r.'); - my_plot3(elec.pnt(1,:), 'r*'); - my_plot3(elec.pnt(2,:), 'r*'); - my_plot3(elec.pnt(3,:), 'r*'); - my_text3(elec.pnt(1,:), elec.label{1}, 'color', 'r'); - my_text3(elec.pnt(2,:), elec.label{2}, 'color', 'r'); - my_text3(elec.pnt(3,:), elec.label{3}, 'color', 'r'); - - % plot all electrodes after warping - my_plot3(norm.pnt, 'm.'); - my_plot3(norm.pnt(1,:), 'm*'); - my_plot3(norm.pnt(2,:), 'm*'); - my_plot3(norm.pnt(3,:), 'm*'); - my_text3(norm.pnt(1,:), norm.label{1}, 'color', 'm'); - my_text3(norm.pnt(2,:), norm.label{2}, 'color', 'm'); - my_text3(norm.pnt(3,:), norm.label{3}, 'color', 'm'); - - % plot the template electrode locations - my_plot3(avg, 'b.'); - my_plot3(avg(1,:), 'b*'); - my_plot3(avg(2,:), 'b*'); - my_plot3(avg(3,:), 'b*'); - my_text3(avg(1,:), norm.label{1}, 'color', 'b'); - my_text3(avg(2,:), norm.label{2}, 'color', 'b'); - my_text3(avg(3,:), norm.label{3}, 'color', 'b'); - - % plot lines connecting the input/warped electrode locations with the template locations - my_line3(elec.pnt, avg, 'color', 'r'); - my_line3(norm.pnt, avg, 'color', 'm'); - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif useheadshape && any(strcmp(cfg.method, {'rigidbody', 'globalrescale', 'traditional', 'nonlin1', 'nonlin2', 'nonlin3', 'nonlin4', 'nonlin5'})) - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - % determine electrode selection and overlapping subset for warping - cfg.channel = channelselection(cfg.channel, elec.label); - - % make subselection of electrodes - [cfgsel, datsel] = match_str(cfg.channel, elec.label); - elec.label = elec.label(datsel); - elec.pnt = elec.pnt(datsel,:); - - fprintf('warping electrodes to head shape... '); % the newline comes later - [norm.pnt, norm.m] = warp_optim(elec.pnt, headshape, cfg.method); - norm.label = elec.label; - - dpre = warp_error([], elec.pnt, headshape, cfg.method); - dpost = warp_error(norm.m, elec.pnt, headshape, cfg.method); - fprintf('mean distance prior to warping %f, after warping %f\n', dpre, dpost); - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif strcmp(cfg.method, 'realignfiducial') - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - % try to determine the fiducials automatically if not specified - option1 = {'nasion' 'left' 'right'}; - option2 = {'nasion' 'lpa' 'rpa'}; - option3 = {'nz' 'lpa' 'rpa'}; - if ~isfield(cfg, 'fiducial') - if length(match_str(elec.label, option1))==3 - cfg.fiducial = option1; - elseif length(match_str(elec.label, option2))==3 - cfg.fiducial = option2; - elseif length(match_str(elec.label, option3))==3 - cfg.fiducial = option3; - else - error('could not determine three fiducials, please specify cfg.fiducial') - end - end - fprintf('using fiducials {''%s'', ''%s'', ''%s''}\n', cfg.fiducial{1}, cfg.fiducial{2}, cfg.fiducial{3}); - - % determine electrode selection - cfg.channel = channelselection(cfg.channel, elec.label); - [cfgsel, datsel] = match_str(cfg.channel, elec.label); - elec.label = elec.label(datsel); - elec.pnt = elec.pnt(datsel,:); - - if length(cfg.fiducial)~=3 - error('you must specify three fiducials'); - end - - % do case-insensitive search for fiducial locations - nas_indx = match_str(lower(elec.label), lower(cfg.fiducial{1})); - lpa_indx = match_str(lower(elec.label), lower(cfg.fiducial{2})); - rpa_indx = match_str(lower(elec.label), lower(cfg.fiducial{3})); - if length(nas_indx)~=1 || length(lpa_indx)~=1 || length(rpa_indx)~=1 - error('not all fiducials were found in the electrode set'); - end - elec_nas = elec.pnt(nas_indx,:); - elec_lpa = elec.pnt(lpa_indx,:); - elec_rpa = elec.pnt(rpa_indx,:); - - % find the matching fiducials in the template and average them - templ_nas = []; - templ_lpa = []; - templ_rpa = []; - for i=1:Ntemplate - nas_indx = match_str(lower(template(i).label), lower(cfg.fiducial{1})); - lpa_indx = match_str(lower(template(i).label), lower(cfg.fiducial{2})); - rpa_indx = match_str(lower(template(i).label), lower(cfg.fiducial{3})); - if length(nas_indx)~=1 || length(lpa_indx)~=1 || length(rpa_indx)~=1 - error(sprintf('not all fiducials were found in template %d', i)); - end - templ_nas(end+1,:) = template(i).pnt(nas_indx,:); - templ_lpa(end+1,:) = template(i).pnt(lpa_indx,:); - templ_rpa(end+1,:) = template(i).pnt(rpa_indx,:); - end - templ_nas = mean(templ_nas,1); - templ_lpa = mean(templ_lpa,1); - templ_rpa = mean(templ_rpa,1); - - % realign both to a common coordinate system - elec2common = headcoordinates(elec_nas, elec_lpa, elec_rpa); - templ2common = headcoordinates(templ_nas, templ_lpa, templ_rpa); - - % compute the combined transform and realign the electrodes to the template - norm = []; - norm.m = elec2common * inv(templ2common); - norm.pnt = warp_apply(norm.m, elec.pnt, 'homogeneous'); - norm.label = elec.label; - - nas_indx = match_str(lower(elec.label), lower(cfg.fiducial{1})); - lpa_indx = match_str(lower(elec.label), lower(cfg.fiducial{2})); - rpa_indx = match_str(lower(elec.label), lower(cfg.fiducial{3})); - dpre = mean(sqrt(sum((elec.pnt([nas_indx lpa_indx rpa_indx],:) - [templ_nas; templ_lpa; templ_rpa]).^2, 2))); - nas_indx = match_str(lower(norm.label), lower(cfg.fiducial{1})); - lpa_indx = match_str(lower(norm.label), lower(cfg.fiducial{2})); - rpa_indx = match_str(lower(norm.label), lower(cfg.fiducial{3})); - dpost = mean(sqrt(sum((norm.pnt([nas_indx lpa_indx rpa_indx],:) - [templ_nas; templ_lpa; templ_rpa]).^2, 2))); - fprintf('mean distance between fiducials prior to realignment %f, after realignment %f\n', dpre, dpost); - - if strcmp(cfg.feedback, 'yes') - % plot the first three electrodes before transformation - my_plot3(elec.pnt(1,:), 'r*'); - my_plot3(elec.pnt(2,:), 'r*'); - my_plot3(elec.pnt(3,:), 'r*'); - my_text3(elec.pnt(1,:), elec.label{1}, 'color', 'r'); - my_text3(elec.pnt(2,:), elec.label{2}, 'color', 'r'); - my_text3(elec.pnt(3,:), elec.label{3}, 'color', 'r'); - - % plot the template fiducials - my_plot3(templ_nas, 'b*'); - my_plot3(templ_lpa, 'b*'); - my_plot3(templ_rpa, 'b*'); - my_text3(templ_nas, ' nas', 'color', 'b'); - my_text3(templ_lpa, ' lpa', 'color', 'b'); - my_text3(templ_rpa, ' rpa', 'color', 'b'); - - % plot all electrodes after transformation - my_plot3(norm.pnt, 'm.'); - my_plot3(norm.pnt(1,:), 'm*'); - my_plot3(norm.pnt(2,:), 'm*'); - my_plot3(norm.pnt(3,:), 'm*'); - my_text3(norm.pnt(1,:), norm.label{1}, 'color', 'm'); - my_text3(norm.pnt(2,:), norm.label{2}, 'color', 'm'); - my_text3(norm.pnt(3,:), norm.label{3}, 'color', 'm'); - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif strcmp(cfg.method, 'interactive') - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % open a figure - fig = figure; - % add the data to the figure - set(fig, 'CloseRequestFcn', @cb_close); - setappdata(fig, 'elec', elec); - setappdata(fig, 'transform', eye(4)); - if useheadshape - setappdata(fig, 'headshape', headshape); - end - if usetemplate - % FIXME interactive realigning to template electrodes is not yet supported - % this requires a consistent handling of channel selection etc. - setappdata(fig, 'template', template); - end - % add the GUI elements - cb_creategui(gca); - cb_redraw(gca); - rotate3d on - waitfor(fig); - % get the data from the figure that was left behind as global variable - global norm - tmp = norm; - clear global norm - norm = tmp; - clear tmp - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif strcmp(cfg.method, 'position') - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % open a figure - fig = figure; - rotate3d on - plot_mesh(headshape, 'edgecolor', 'k') - xyz = select_point3d(headshape, 'multiple', true); - orig.pnt = xyz; - for i=1:size(orig.pnt,1) - orig.label{i,1} = 'unknown'; - end - - if strcmp(cfg.outline, 'yes') - % FIXME also go over the outlines with manual clicking - keyboard - end - -else - error('unknown method'); -end - -% apply the spatial transformation to all electrodes, and replace the -% electrode labels by their case-sensitive original values -switch cfg.method - case {'rigidbody', 'globalrescale', 'traditional', 'nonlin1', 'nonlin2', 'nonlin3', 'nonlin4', 'nonlin5'} - norm.pnt = warp_apply(norm.m, orig.pnt, cfg.method); - if isfield(orig, 'outline') - % FIXME also apply the warp to the outlines - end - case {'interactive'} - norm.pnt = warp_apply(norm.m, orig.pnt, 'homogenous'); - if isfield(orig, 'outline') - % FIXME also apply the warp to the outlines - end - case {'position'} - % the positions are already assigned in correspondence with the mesh - norm = orig; - otherwise - error('unknown method'); -end - -if isfield(orig, 'label') - norm.label = orig.label; -end - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: electroderealign.m,v 1.13 2009/06/30 07:10:11 roboos Exp $'; - -% remember the configuration -norm.cfg = cfg; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% some simple SUBFUNCTIONs that facilitate 3D plotting -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function h = my_plot3(xyz, varargin) -h = plot3(xyz(:,1), xyz(:,2), xyz(:,3), varargin{:}); -function h = my_text3(xyz, varargin) -h = text(xyz(:,1), xyz(:,2), xyz(:,3), varargin{:}); -function my_line3(xyzB, xyzE, varargin) -for i=1:size(xyzB,1) - line([xyzB(i,1) xyzE(i,1)], [xyzB(i,2) xyzE(i,2)], [xyzB(i,3) xyzE(i,3)], varargin{:}) -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION to layout a moderately complex graphical user interface -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function h = layoutgui(fig, geometry, position, style, string, value, tag, callback); -horipos = geometry(1); % lower left corner of the GUI part in the figure -vertpos = geometry(2); % lower left corner of the GUI part in the figure -width = geometry(3); % width of the GUI part in the figure -height = geometry(4); % height of the GUI part in the figure -horidist = 0.05; -vertdist = 0.05; -options = {'units', 'normalized', 'HorizontalAlignment', 'center'}; % 'VerticalAlignment', 'middle' -Nrow = size(position,1); -h = cell(Nrow,1); -for i=1:Nrow - if isempty(position{i}) - continue; - end - position{i} = position{i} ./ sum(position{i}); - Ncol = size(position{i},2); - ybeg = (Nrow-i )/Nrow + vertdist/2; - yend = (Nrow-i+1)/Nrow - vertdist/2; - for j=1:Ncol - xbeg = sum(position{i}(1:(j-1))) + horidist/2; - xend = sum(position{i}(1:(j ))) - horidist/2; - pos(1) = xbeg*width + horipos; - pos(2) = ybeg*height + vertpos; - pos(3) = (xend-xbeg)*width; - pos(4) = (yend-ybeg)*height; - h{i}{j} = uicontrol(fig, ... - options{:}, ... - 'position', pos, ... - 'style', style{i}{j}, ... - 'string', string{i}{j}, ... - 'tag', tag{i}{j}, ... - 'value', value{i}{j}, ... - 'callback', callback{i}{j} ... - ); - end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function cb_creategui(hObject, eventdata, handles); -% define the position of each GUI element -position = { - [2 1 1 1] - [2 1 1 1] - [2 1 1 1] - [1] - [1] - [1] - [1] - [1 1] - }; - -% define the style of each GUI element -style = { - {'text' 'edit' 'edit' 'edit'} - {'text' 'edit' 'edit' 'edit'} - {'text' 'edit' 'edit' 'edit'} - {'pushbutton'} - {'pushbutton'} - {'toggle'} - {'toggle'} - {'text' 'edit'} - }; - -% define the descriptive string of each GUI element -string = { - {'rotate' 0 0 0} - {'translate' 0 0 0} - {'scale' 1 1 1} - {'redisplay'} - {'apply'} - {'toggle grid'} - {'toggle axes'} - {'alpha' 0.7} - }; - -% define the value of each GUI element -value = { - {[] [] [] []} - {[] [] [] []} - {[] [] [] []} - {[]} - {[]} - {0} - {0} - {[] []} - }; - -% define a tag for each GUI element -tag = { - {'' 'rx' 'ry' 'rz'} - {'' 'tx' 'ty' 'tz'} - {'' 'sx' 'sy' 'sz'} - {''} - {''} - {'toggle grid'} - {'toggle axes'} - {'' 'alpha'} - }; - -% define the callback function of each GUI element -callback = { - {[] @cb_redraw @cb_redraw @cb_redraw} - {[] @cb_redraw @cb_redraw @cb_redraw} - {[] @cb_redraw @cb_redraw @cb_redraw} - {@cb_redraw} - {@cb_apply} - {@cb_redraw} - {@cb_redraw} - {[] @cb_redraw} - }; - -fig = get(hObject, 'parent'); -layoutgui(fig, [0.7 0.05 0.25 0.50], position, style, string, value, tag, callback); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function cb_redraw(hObject, eventdata, handles); -fig = get(hObject, 'parent'); -headshape = getappdata(fig, 'headshape'); -elec = getappdata(fig, 'elec'); -template = getappdata(fig, 'template'); -% get the transformation details -rx = str2num(get(findobj(fig, 'tag', 'rx'), 'string')); -ry = str2num(get(findobj(fig, 'tag', 'ry'), 'string')); -rz = str2num(get(findobj(fig, 'tag', 'rz'), 'string')); -tx = str2num(get(findobj(fig, 'tag', 'tx'), 'string')); -ty = str2num(get(findobj(fig, 'tag', 'ty'), 'string')); -tz = str2num(get(findobj(fig, 'tag', 'tz'), 'string')); -sx = str2num(get(findobj(fig, 'tag', 'sx'), 'string')); -sy = str2num(get(findobj(fig, 'tag', 'sy'), 'string')); -sz = str2num(get(findobj(fig, 'tag', 'sz'), 'string')); -R = rotate ([rx ry rz]); -T = translate([tx ty tz]); -S = scale ([sx sy sz]); -H = S * T * R; -elec = transform_sens(H, elec); -axis vis3d; cla -xlabel('x') -ylabel('y') -zlabel('z') -if ~isempty(headshape) - triplot(headshape.pnt, headshape.tri, [], 'faces_skin'); - alpha(str2num(get(findobj(fig, 'tag', 'alpha'), 'string'))); -end -if ~isempty(template) - triplot(template.pnt, [], [], 'nodes_blue') -end -triplot(elec.pnt, [], [], 'nodes'); -if isfield(elec, 'line') - triplot(elec.pnt, elec.line, [], 'edges'); -end -if isfield(elec, 'fid') && ~isempty(elec.fid.pnt) - triplot(elec.fid.pnt, [], [], 'nodes_red'); -end -if get(findobj(fig, 'tag', 'toggle axes'), 'value') - axis on -else - axis off -end -if get(findobj(fig, 'tag', 'toggle grid'), 'value') - grid on -else - grid off -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function cb_apply(hObject, eventdata, handles); -fig = get(hObject, 'parent'); -elec = getappdata(fig, 'elec'); -transform = getappdata(fig, 'transform'); -% get the transformation details -rx = str2num(get(findobj(fig, 'tag', 'rx'), 'string')); -ry = str2num(get(findobj(fig, 'tag', 'ry'), 'string')); -rz = str2num(get(findobj(fig, 'tag', 'rz'), 'string')); -tx = str2num(get(findobj(fig, 'tag', 'tx'), 'string')); -ty = str2num(get(findobj(fig, 'tag', 'ty'), 'string')); -tz = str2num(get(findobj(fig, 'tag', 'tz'), 'string')); -sx = str2num(get(findobj(fig, 'tag', 'sx'), 'string')); -sy = str2num(get(findobj(fig, 'tag', 'sy'), 'string')); -sz = str2num(get(findobj(fig, 'tag', 'sz'), 'string')); -R = rotate ([rx ry rz]); -T = translate([tx ty tz]); -S = scale ([sx sy sz]); -H = S * T * R; -elec = transform_headshape(H, elec); -transform = H * transform; -set(findobj(fig, 'tag', 'rx'), 'string', 0); -set(findobj(fig, 'tag', 'ry'), 'string', 0); -set(findobj(fig, 'tag', 'rz'), 'string', 0); -set(findobj(fig, 'tag', 'tx'), 'string', 0); -set(findobj(fig, 'tag', 'ty'), 'string', 0); -set(findobj(fig, 'tag', 'tz'), 'string', 0); -set(findobj(fig, 'tag', 'sx'), 'string', 1); -set(findobj(fig, 'tag', 'sy'), 'string', 1); -set(findobj(fig, 'tag', 'sz'), 'string', 1); -setappdata(fig, 'elec', elec); -setappdata(fig, 'transform', transform); -cb_redraw(hObject); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function cb_close(hObject, eventdata, handles); -% make the current transformation permanent and subsequently allow deleting the figure -cb_apply(gca); -% get the updated electrode from the figure -fig = hObject; -% hmmm, this is ugly -global norm -norm = getappdata(fig, 'elec'); -norm.m = getappdata(fig, 'transform'); -set(fig, 'CloseRequestFcn', @delete); -delete(fig); - diff --git a/external/fieldtrip/private/elproj.m b/external/fieldtrip/private/elproj.m index e6b74cc..72dc9b5 100644 --- a/external/fieldtrip/private/elproj.m +++ b/external/fieldtrip/private/elproj.m @@ -7,11 +7,11 @@ % [proj] = elproj([x, y, z], 'method'); % % Method should be one of these: -% 'gnomic' -% 'stereographic' -% 'ortographic' -% 'inverse' -% 'polar' +% 'gnomic' +% 'stereographic' +% 'orthographic' +% 'inverse' +% 'polar' % % Imagine a plane being placed against (tangent to) a globe. If % a light source inside the globe projects the graticule onto @@ -25,19 +25,23 @@ % Copyright (C) 2000-2008, Robert Oostenveld % -% $Log: elproj.m,v $ -% Revision 1.5 2009/10/14 15:27:40 roboos -% give error on method that is not recognized +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.4 2008/05/15 10:54:24 roboos -% updated documentation +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.3 2007/03/20 10:29:35 roboos -% renamed method 'default' into 'polar' +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.2 2003/03/17 10:37:28 roberto -% improved general help comments and added copyrights +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: elproj.m 946 2010-04-21 17:51:16Z roboos $ x = pos(:,1); y = pos(:,2); diff --git a/external/fieldtrip/private/estimate_units.m b/external/fieldtrip/private/estimate_units.m deleted file mode 100644 index 2749632..0000000 --- a/external/fieldtrip/private/estimate_units.m +++ /dev/null @@ -1,37 +0,0 @@ -function unit = estimate_units(size) - -% ESTIMATE_UNITS tries to determine the units of a geometrical object by -% looking at its size and by relating this to the size of the human -% brain. -% -% Use as -% unit = estimate_units(size) -% -% This function will return one of the following strings -% 'm' -% 'dm' -% 'cm' -% 'mm' - -% Copyright (C) 2009, Robert Oostenveld -% -% $Log: estimate_units.m,v $ -% Revision 1.1 2009/03/26 14:57:04 roboos -% moved the unit estimation to a seperate function -% - -% do some magic based on the size -unit = {'m', 'dm', 'cm', 'mm'}; -indx = round(log10(size)+2-0.2); - -if indx>length(unit) - indx = length(unit); - warning('assuming that the units are "%s"', unit{indx}); -end - -if indx<1 - indx = 1; - warning('assuming that the units are "%s"', unit{indx}); -end - -unit = unit{indx}; diff --git a/external/fieldtrip/private/expand_orthogonal.m b/external/fieldtrip/private/expand_orthogonal.m index 066ec7f..8d788d3 100644 --- a/external/fieldtrip/private/expand_orthogonal.m +++ b/external/fieldtrip/private/expand_orthogonal.m @@ -33,15 +33,23 @@ % Copyright (C) 2007, Christian Hesse % F.C. Donders Centre for Cognitive Neuroimaging, Nijmegen, NL % -% $Log: expand_orthogonal.m,v $ -% Revision 1.2 2007/03/05 15:29:10 chrhes -% added new (default) option to compute the orthogonal basis expansion using -% singular value decomposition instead of the Gram-Schmidt method (which can -% still be specified); updated the function declaration and documentation. +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.1 2007/03/05 14:08:02 chrhes -% initial version of this code added to FieldTrip +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: expand_orthogonal.m 952 2010-04-21 18:29:51Z roboos $ % References: @@ -147,4 +155,4 @@ if (flg==0), B(:,1:ncols) = A; end; -% end of function \ No newline at end of file +% end of function diff --git a/external/fieldtrip/private/fdr.m b/external/fieldtrip/private/fdr.m index 41db478..a3313ee 100644 --- a/external/fieldtrip/private/fdr.m +++ b/external/fieldtrip/private/fdr.m @@ -12,13 +12,23 @@ % Copyright (C) 2005, Robert Oostenveld % -% $Log: fdr.m,v $ -% Revision 1.2 2006/06/07 12:57:09 roboos -% also support n-D input arrays +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.1 2005/11/08 16:02:58 roboos -% initial implementation +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: fdr.m 952 2010-04-21 18:29:51Z roboos $ % convert the input into a row vector dim = size(p); diff --git a/external/fieldtrip/private/fetch_data.m b/external/fieldtrip/private/fetch_data.m deleted file mode 100644 index 1c31527..0000000 --- a/external/fieldtrip/private/fetch_data.m +++ /dev/null @@ -1,125 +0,0 @@ -function [dat] = fetch_data(data, varargin) - -% FETCH_DATA mimics the behaviour of READ_DATA, but for a FieldTrip -% raw data structure instead of a file on disk. -% -% Use as -% [event] = fetch_data(data, ...) -% -% See also READ_DATA, FETCH_HEADER, FETCH_EVENT - -% Copyright (C) 2008, Esther Meeuwissen -% -% $Log: fetch_data.m,v $ -% Revision 1.4 2009/08/05 08:23:25 roboos -% use preallocated integet vectors for all indexing -% skip the indexing of trials that are of no interest -> huge speedup -% -% Revision 1.3 2009/08/04 16:14:05 roboos -% give error for multiple occurence -% return nan for missing samples -% -% Revision 1.2 2009/07/06 09:41:18 jansch -% multiple changes. allowing for selection of rpt in frequency data when input -% data has rpttap. allowing for grandaveraging functionality in the case of -% multiple inputs with the same dimensionalities. this is equivalent to the -% XXXgrandaverage functions with keepindividual = 'yes'. -% -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.2 2008/09/29 21:12:39 roboos -% cleaned up the code from Esther, added copyrights, updated documentation -% - -% check whether input is data -data = checkdata(data, 'datatype', 'raw'); - -% get the options -hdr = keyval('header', varargin); -begsample = keyval('begsample', varargin); -endsample = keyval('endsample', varargin); -chanindx = keyval('chanindx', varargin); - -if isempty(hdr) - hdr = fetch_header(data); -end - -if isempty(begsample) || isempty(endsample) - error('begsample and endsample must be specified'); -end - -if isempty(chanindx) - chanindx = 1:hdr.nChans; -end - -% get trial definition according to original data file -trl = findcfg(data.cfg, 'trl'); -trlnum = length(data.trial); -trllen = zeros(trlnum,1); -for trllop=1:trlnum - trllen(trllop) = size(data.trial{trllop},2); -end - -% check whether data.trial is consistent with trl -if size(trl,1)~=length(data.trial) - error('trial definition is not internally consistent') -elseif any(trllen~=(trl(:,2)-trl(:,1)+1)) - error('trial definition is not internally consistent') -end - -minchan = min(chanindx); -maxchan = max(chanindx); -if minchan<1 || maxchan>hdr.nChans - error('selected channels are not present in the data') -end - -% these are for bookkeeping -maxsample = max(trl(:,2)); -count = zeros(1, maxsample, 'int32'); -trialnum = zeros(1, maxsample, 'int32'); -samplenum = zeros(1, maxsample, 'int32'); - -% determine for each sample in the data where it originates from -for trllop=1:trlnum - trlbeg = trl(trllop,1); - trlend = trl(trllop,2); - if trlbeg>endsample || trlend Nan - trialnum(trlbeg:trlend) = trllop; - % make samplenum vector with samplenrs for each sample in the old trials - samplenum(trlbeg:trlend) = 1:trllen(trllop); -end - -% overlap --> NaN -%trialnum(count>1) = NaN; -%samplenum(count>1) = NaN; - -% make a subselection for the desired samples -count = count(begsample:endsample); -trialnum = trialnum(begsample:endsample); -samplenum = samplenum(begsample:endsample); - -% check if all samples are present and are not present twice or more -if any(count==0) - warning('not all requested samples are present in the data, filling with NaNs'); -elseif any(count>1) - error('some of the requested samples occur twice in the data'); -end - -% construct the output data array -dat = nan(length(chanindx), length(samplenum)); -for smplop=1:length(samplenum) - if samplenum(smplop)==0 - dat(:, smplop) = nan; - else - dat(:, smplop) = data.trial{trialnum(smplop)}(chanindx,samplenum(smplop)); - end -end - diff --git a/external/fieldtrip/private/fetch_event.m b/external/fieldtrip/private/fetch_event.m deleted file mode 100644 index 12d1c22..0000000 --- a/external/fieldtrip/private/fetch_event.m +++ /dev/null @@ -1,26 +0,0 @@ -function [event]=fetch_event(data) - -% FETCH_EVENT mimics the behaviour of READ_EVENT, but for a FieldTrip -% raw data structure instead of a file on disk. -% -% Use as -% [event] = fetch_event(data) -% -% See also READ_EVENT, FETCH_HEADER, FETCH_DATA - -% Copyright (C) 2008, Esther Meeuwissen -% -% $Log: fetch_event.m,v $ -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.2 2008/09/29 21:12:39 roboos -% cleaned up the code from Esther, added copyrights, updated documentation -% - -% check whether input is data -data = checkdata(data, 'datatype', 'raw'); - -% locate the event structure -event = findcfg(data.cfg, 'event'); - diff --git a/external/fieldtrip/private/fetch_header.m b/external/fieldtrip/private/fetch_header.m deleted file mode 100644 index 41f1720..0000000 --- a/external/fieldtrip/private/fetch_header.m +++ /dev/null @@ -1,71 +0,0 @@ -function [hdr] = fetch_header(data) - -% FETCH_HEADER mimics the behaviour of READ_HEADER, but for a FieldTrip -% raw data structure instead of a file on disk. -% -% Use as -% [event] = fetch_header(data) -% -% See also READ_HEADER, FETCH_DATA, FETCH_EVENT - -% Copyright (C) 2008, Esther Meeuwissen -% -% $Log: fetch_header.m,v $ -% Revision 1.2 2009/10/01 12:36:01 jansch -% workaround if input data has been resampled, so that the comparison with -% trl matrix does not lead to a crash -% -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.2 2008/09/29 21:12:39 roboos -% cleaned up the code from Esther, added copyrights, updated documentation -% - -% check whether input is data -data = checkdata(data, 'datatype', 'raw'); - -% get trial definition according to original data file -trl = findcfg(data.cfg, 'trl'); -trlnum = length(data.trial); -trllen = zeros(trlnum,1); -for trllop=1:trlnum - trllen(trllop) = size(data.trial{trllop},2); -end - -% check whether data.trial is consistent with trl -if size(trl,1)~=length(data.trial) - error('trial definition is not internally consistent') -elseif any(trllen~=(trl(:,2)-trl(:,1)+1)) && ~isempty(findcfg(data.cfg, 'resamplefs')) && ~isempty(findcfg(data.cfg,'resampletrl')), - warning('the data have been resampled along the way, the trl-definition is in the original sampling rate, attempt to adjust for this may introduce some timing inaccuracies'); - trlold = trl; - trl = findcfg(data.cfg, 'resampletrl'); -end - -%this has to be done again -if any(trllen~=(trl(:,2)-trl(:,1)+1)) - error('trial definition is not internally consistent') -end - -% fill in hdr.nChans -hdr.nChans = length(data.label); - -% fill in hdr.label -hdr.label = data.label; - -% fill in hdr.Fs (sample frequency) -hdr.Fs = data.fsample; - -% determine hdr.nSamples, hdr.nSamplesPre, hdr.nTrials -% always pretend that it is continuous data -hdr.nSamples = max(trl(:,2)); -hdr.nSamplesPre = 0; -hdr.nTrials = 1; - -% fill in hdr.grad or hdr.elec -if isfield(data, 'grad') - hdr.grad=data.grad; -elseif isfield(data, 'elec') - hdr.elec=data.elec; -end - diff --git a/external/fieldtrip/private/fieldtripdefs.m b/external/fieldtrip/private/fieldtripdefs.m deleted file mode 100644 index 0a95060..0000000 --- a/external/fieldtrip/private/fieldtripdefs.m +++ /dev/null @@ -1,110 +0,0 @@ -function fieldtripdefs - -% FIELDTRIPDEFS is called at the begin of all FieldTrip functions and -% contains some defaults and path settings -% -% Note that this should be a function and not a script, otherwise the -% hastoolbox function appears not be found in fieldtrip/private. - -% $Log: fieldtripdefs.m,v $ -% Revision 1.14 2009/04/02 19:46:24 roboos -% added plotting module -% -% Revision 1.13 2009/03/26 09:28:17 roboos -% removed fixpath from the matlab path -% -% Revision 1.12 2008/11/12 11:41:54 sashae -% changed trackconfig options -% -% Revision 1.11 2008/11/11 13:13:44 roboos -% added/improved size checking -% -% Revision 1.10 2008/11/10 21:17:28 roboos -% added public subdirectory -% -% Revision 1.9 2008/10/08 10:21:57 roboos -% added realtime module for addpath -% -% Revision 1.8 2008/10/02 14:04:17 roboos -% added global ft_default, see also checkconfig -% -% Revision 1.7 2008/10/01 10:18:30 roboos -% changed from script into function to fix private path -% -% Revision 1.6 2008/10/01 08:22:40 roboos -% added specest module -% -% Revision 1.5 2008/09/23 07:54:09 roboos -% added template directory, moved all layouts and cortical meshes there -% -% Revision 1.4 2008/09/23 07:40:10 roboos -% changed order of the path additioons, fixpath should be the first (i.e. lowest on the path) -% -% Revision 1.3 2008/09/23 07:31:13 roboos -% Moved all statfuns and trialfuns to their own directories, where they will be easier to find for the end-user. Also updated fieldtripdefs accordingly. -% -% Revision 1.2 2008/09/22 20:58:57 roboos -% added modules: fileio, forwinv, preproc -% -% Revision 1.1 2008/09/22 20:02:50 roboos -% initial version, contains fixpath -% - - -% set the global defaults, the checkconfig function will copy these into the local configurations -global ft_default -if ~isfield(ft_default, 'trackconfig'), ft_default.trackconfig = 'off'; end % cleanup, report, off -if ~isfield(ft_default, 'checkconfig'), ft_default.checkconfig = 'loose'; end % pedantic, loose, silent -if ~isfield(ft_default, 'checksize'), ft_default.checksize = 1e5; end % number in bytes, can be inf - -try - % this contains general usefull functions, that do not have to be private - hastoolbox('public', 1, 1); -end - -try - % this contains layouts and cortical meshes - hastoolbox('template', 1, 1); -end - -try - % this is used in statistics - hastoolbox('statfun', 1, 1); -end - -try - % this is used in definetrial - hastoolbox('trialfun', 1, 1); -end - -try - % numerous functions depend on this module - hastoolbox('fileio', 1, 1); -end - -try - % numerous functions depend on this module - hastoolbox('forwinv', 1, 1); -end - -try - % numerous functions depend on this module - hastoolbox('preproc', 1, 1); -end - -try - % numerous functions depend on this module - hastoolbox('plotting', 1, 1); -end - -try - % only very few functions depent on this module - % it is not yet included in the FTP release version - hastoolbox('specest', 1, 1); -end - -try - % this contains some examples for realtime processing - hastoolbox('realtime', 1, 1); -end - diff --git a/external/fieldtrip/private/fif2grad.m b/external/fieldtrip/private/fif2grad.m index 51a6b39..fd81d47 100644 --- a/external/fieldtrip/private/fif2grad.m +++ b/external/fieldtrip/private/fif2grad.m @@ -11,27 +11,23 @@ % Copyright (C) 2004, Joachim Gross % -% $Log: fif2grad.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.3 2008/05/15 13:20:35 roboos -% updated documentation +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.2 2007/03/15 12:44:42 roboos -% added try-catch to deal with fif files that do not contain coil information (code by chrhes) +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.1 2006/08/31 13:32:11 roboos -% moved from fieldtrip to fileio module -% -% Revision 1.1 2004/09/20 13:53:04 roboos -% moved gradiometer definition for Neuromag fif files into separate function +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: fif2grad.m 1412 2010-07-15 10:46:19Z vlalit $ % this try-catch construct ensures that missing gradiometer information is % handeled in a "graceful" way @@ -58,11 +54,11 @@ elseif (TY(k) == 1), %planar gradiometer grad.pnt(kCoil,:)=100*(t{k}(1:3,4)-0.008*t{k}(1:3,1)); % multiply with 100 to get cm grad.ori(kCoil,:)=t{k}(1:3,3); - grad.tra(k,kCoil)=1; + grad.tra(k,kCoil)= -1; kCoil=kCoil+1; grad.pnt(kCoil,:)=100*(t{k}(1:3,4)+0.008*t{k}(1:3,1)); grad.ori(kCoil,:)=t{k}(1:3,3); - grad.tra(k,kCoil)=-1; + grad.tra(k,kCoil)= 1; kCoil=kCoil+1; grad.label{k}=deblank(s(k,:)); else diff --git a/external/fieldtrip/private/filetype.m b/external/fieldtrip/private/filetype.m deleted file mode 100644 index 56f22ef..0000000 --- a/external/fieldtrip/private/filetype.m +++ /dev/null @@ -1,1056 +0,0 @@ -function [type] = filetype(filename, desired, varargin) - -% FILETYPE determines the filetype of many EEG/MEG/MRI data files by -% looking at the name, extension and optionally (part of) its contents. -% It tries to determine the global type of file (which usually -% corresponds to the manufacturer, the recording system or to the -% software used to create the file) and the particular subtype (e.g. -% continuous, average). -% -% Use as -% type = filetype(filename) -% type = filetype(dirname) -% -% This gives you a descriptive string with the data type, and can be -% used in a switch-statement. The descriptive string that is returned -% usually is something like 'XXX_YYY'/ where XXX refers to the -% manufacturer and YYY to the type of the data. -% -% Alternatively, use as -% flag = filetype(filename, type) -% flag = filetype(dirname, type) -% This gives you a boolean flag (0 or 1) indicating whether the file -% is of the desired type, and can be used to check whether the -% user-supplied file is what your subsequent code expects. -% -% Alternatively, use as -% flag = filetype(dirlist, type) -% where the dirlist contains a list of files contained within one -% directory. This gives you a boolean vector indicating for each file -% whether it is of the desired type. -% -% Most filetypes of the following manufacturers and/or software programs are recognized -% - VSMMedtech/CTF -% - Elektra/Neuromag -% - Yokogawa -% - 4D/BTi -% - EDF -% - Neuroscan -% - Analyse -% - EEProbe -% - BrainVision -% - BESA -% - Curry -% - ASA -% - LORETA -% - Analyze/SPM -% - MINC -% - AFNI -% - Neuralynx -% - Plexon -% -% See also READ_XXX_YYY where XXX=manufacturer and YYY=subtype - -% Copyright (C) 2003-2007 Robert Oostenveld -% -% $Log: filetype.m,v $ -% Revision 1.101 2009/10/16 07:31:18 roboos -% renamed chieti into itab for consistency with other formats -% -% Revision 1.100 2009/10/13 10:12:51 roboos -% added support for chieti_raw -% -% Revision 1.99 2009/10/07 09:48:00 jansch -% added some lines to be able to deal with memory mapped files -% -% Revision 1.98 2009/07/07 10:38:38 roboos -% added header check for dicom -% -% Revision 1.97 2009/05/06 15:42:06 roboos -% also remember/check previous directory and don't do filetype caching in case type=unknown -% -% Revision 1.96 2009/04/01 06:53:23 roboos -% implemented caching for the type detection in case the same input is given multiple times -% this uses a persistent variable -% renamed the internal variable "ftype" into "type" -% removed the second output argument with the details, because sofar they have never been used in fieldtrip and therefore don't seem needed -% -% Revision 1.95 2009/02/12 11:47:23 vlalit -% Added support for neuro prax (eldith) EEG format based on functions from the manufacturer -% used with permission from the company's representative Mr. Klaus Schellhorn. -% -% Revision 1.94 2009/02/09 14:21:00 roboos -% added inport of micromed_trc data -% -% Revision 1.93 2009/01/07 10:37:55 roboos -% changed description for neuralynx_sdma, should not have any functional consequences -% -% Revision 1.92 2008/12/24 10:33:48 roboos -% fixed header for mbfys_ama -% -% Revision 1.91 2008/12/19 14:39:25 marvger -% added support for udp, tcp and fifo -% -% Revision 1.90 2008/12/18 11:24:30 vlalit -% Fixed detection of spike6 matlab file -% -% Revision 1.89 2008/12/09 16:50:41 roboos -% disabled detection of ced_spike6mat, because it contains an error. The error should be fixed by Vladimir. -% -% Revision 1.88 2008/11/28 10:24:24 roboos -% added ctf mri version 4, thanks to Ivar -% -% Revision 1.87 2008/11/12 16:50:26 roboos -% improved detection for BCI2000 -% -% Revision 1.86 2008/11/02 10:38:44 roboos -% added another check for ctf_ds (to deal with '.') -% -% Revision 1.85 2008/10/28 16:08:14 roboos -% additional check on yokogawa raw (first 4 bytes should be zero) -% -% Revision 1.84 2008/07/24 08:43:40 roboos -% added nimh_cortex -% -% Revision 1.83 2008/07/09 12:16:38 roboos -% added mclust_t -% -% Revision 1.82 2008/07/01 13:35:25 roboos -% moved long sequence for mat files onto single line (2x) -% -% Revision 1.81 2008/06/18 08:24:33 roboos -% added support for BCI2000 -% -% Revision 1.80 2008/05/27 16:12:26 vlalit -% Changed type name to ced_spike6mat -% -% Revision 1.79 2008/05/27 11:58:20 vlalit -% Added support of Matlab files exported from Spike 6 -% -% Revision 1.78 2008/05/21 13:31:34 vlalit -% Added check for existence of the file before the other spmeeg checks. -% -% Revision 1.77 2008/05/09 17:04:41 vlalit -% Added even more stringent criteria for recognition of SPM EEG mat files -% -% Revision 1.76 2008/05/06 14:36:23 roboos -% Added readers for SPM5 and SPM8 EEG formats (fix cvs conflict between jansch and vlalit) -% -% Revision 1.75 2008/05/06 12:00:38 jansch -% changed strcmp into strfind for 4d-data -% -% Revision 1.74 2008/05/06 09:24:36 jansch -% removed check for . in filename of 4D-files. necessary to read in data that -% are not DC-recorded. -% -% Revision 1.72 2008/04/21 11:50:51 roboos -% added support for egi_sbin, thanks to Joseph Dien -% -% Revision 1.71 2008/04/18 14:08:03 roboos -% added eeglab_set -% -% Revision 1.70 2008/04/11 12:09:18 roboos -% added polhemus_fil -% -% Revision 1.69 2008/03/04 11:14:26 roboos -% added neuralynx_nst -% -% Revision 1.68 2008/02/19 10:07:34 roboos -% replaced tcpsocket with buffer -% -% Revision 1.67 2008/01/31 20:10:22 roboos -% It is necessary to identify when it is necessary to execute the new -% read_4d_hdr.m function. To achieve this an extra IF statement was -% added from line 312. This statement checks for a passed filename -% which has no extension (not the case for .xyz or .m4d) and that the -% second to fourth characters in the filename are ,rf. If both of -% these conditions are met then the filetype and manufacturer are set -% to 4d. [thanks to Gavin] -% -% Revision 1.66 2008/01/25 07:41:57 roboos -% moved some code, no functional change -% -% Revision 1.65 2008/01/15 08:12:30 roboos -% more strict test for ctf_ds -% -% Revision 1.64 2007/12/19 07:17:26 roboos -% removed ftc, added txt -% -% Revision 1.63 2007/12/17 16:14:44 roboos -% added neuralynx_bin -% -% Revision 1.62 2007/12/17 08:25:04 roboos -% added nexstim_nxe -% -% Revision 1.61 2007/12/12 16:48:20 roboos -% deal with case of extension for nev/Nev -% fixed bug: correctly locate the events.nev file in the dataset directory -% -% Revision 1.60 2007/12/12 14:39:26 roboos -% added riff_wave -% -% Revision 1.59 2007/12/06 17:05:54 roboos -% added fcdc_ftc, only on file extension -% -% Revision 1.58 2007/10/25 12:47:31 roboos -% added *.nrd as neuralynx_dma, not sure yet whether this is correct -% -% Revision 1.57 2007/10/16 12:35:08 roboos -% implemented fcdc_global -% -% Revision 1.56 2007/10/15 16:02:46 roboos -% added rfb://@: -% -% Revision 1.55 2007/10/04 11:55:40 roboos -% added the various spass file formats -% -% Revision 1.54 2007/09/13 09:46:51 roboos -% adedd ctf_wts and svl -% -% Revision 1.53 2007/08/06 09:07:33 roboos -% added 4d_hs -% -% Revision 1.52 2007/07/27 12:17:47 roboos -% added ctf_shm -% -% Revision 1.51 2007/07/04 13:20:51 roboos -% added support for egi_egis/egia, thanks to Joseph Dien -% -% Revision 1.50 2007/06/06 07:10:16 roboos -% changed detection of BCI streams into using URI scheme -% changed deterction of BESA source waveform files -% -% Revision 1.49 2007/06/04 18:24:49 roboos -% added nifti -% -% Revision 1.48 2007/05/31 09:13:28 roboos -% added tcpsocket ans serial port -% -% Revision 1.47 2007/05/15 14:59:54 roboos -% try to separate besa *.dat from brainvision *.dat -% -% Revision 1.46 2007/04/25 15:27:28 roboos -% rmoved besa_gen, instead added besa_sb (simple binary), which comes with the *.gen or *.generic ascii header file -% -% Revision 1.45 2007/03/21 17:21:30 roboos -% remove . and .. from the file listing in case of a directory as input -% removed neuralynx_nte, the correct extension is *.nts -% added header check to neuralynx_nts -% implemented subfunction most, c.f. any -% swiched from using any(...) to most(...) for determining content of dataset directory -% implemented plexon_ds for directory with nex files in it -% made some additional small changes -% -% Revision 1.44 2007/03/19 16:52:37 roboos -% added neuralynx_nte -% -% Revision 1.43 2007/01/09 09:29:25 roboos -% small change -% -% Revision 1.42 2007/01/04 08:12:00 roboos -% fixed bug for besa_avr, renamed an incorrect tag into plexon_plx -% - -% these are for remembering the type on subsequent calls with the same input arguments -persistent previous_argin previous_argout previous_pwd - -if nargin<2 - % ensure that all input arguments are defined - desired = []; -end - -current_argin = {filename, desired, varargin{:}}; -current_pwd = pwd; -if isequal(current_argin, previous_argin) && isequal(current_pwd, previous_pwd) - % don't do the detection again, but return the previous value from cache - type = previous_argout{1}; - return -end - -if strcmp(class(filename), 'memmapfile'), - filename = filename.Filename; -end - -% % get the optional arguments -% checkheader = keyval('checkheader', varargin); if isempty(checkheader), checkheader=1; end -% -% if ~checkheader -% % assume that the header is always ok, e.g when the file does not yet exist -% % this replaces the normal function with a function that always returns true -% filetype_check_header = @filetype_true; -% end - -if iscell(filename) - % perform the test for each filename, return a boolean vector - type = false(size(filename)); - for i=1:length(filename) - if strcmp(filename{i}(end), '.') - % do not recurse into this directory or the parent directory - continue - else - type(i) = filetype(filename{i}, desired); - end - end - return -end - -% start with unknown values -type = 'unknown'; -manufacturer = 'unknown'; -content = 'unknown'; - -[p, f, x] = fileparts(filename); - -if isdir(filename) - % the directory listing is needed below - ls = dir(filename); - % remove the parent directory and the directory itself from the list - ls = ls(~strcmp({ls.name}, '.')); - ls = ls(~strcmp({ls.name}, '..')); - for i=1:length(ls) - % make sure that the directory listing includes the complete path - ls(i).name = fullfile(filename, ls(i).name); - end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% start determining the filetype -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% these are some streams for asynchronous BCI -if filetype_check_uri(filename, 'fifo') - type = 'fcdc_fifo'; - manufacturer = 'F.C. Donders Centre'; - content = 'stream'; -elseif filetype_check_uri(filename, 'buffer') - type = 'fcdc_buffer'; - manufacturer = 'F.C. Donders Centre'; - content = 'stream'; -elseif filetype_check_uri(filename, 'mysql') - type = 'fcdc_mysql'; - manufacturer = 'F.C. Donders Centre'; - content = 'stream'; -elseif filetype_check_uri(filename, 'tcp') - type = 'fcdc_tcp'; - manufacturer = 'F.C. Donders Centre'; - content = 'stream'; -elseif filetype_check_uri(filename, 'udp') - type = 'fcdc_udp'; - manufacturer = 'F.C. Donders Centre'; - content = 'stream'; -elseif filetype_check_uri(filename, 'rfb') - type = 'fcdc_rfb'; - manufacturer = 'F.C. Donders Centre'; - content = 'stream'; -elseif filetype_check_uri(filename, 'serial') - type = 'fcdc_serial'; - manufacturer = 'F.C. Donders Centre'; - content = 'stream'; -elseif filetype_check_uri(filename, 'global') - type = 'fcdc_global'; - manufacturer = 'F.C. Donders Centre'; - content = 'global variable'; -elseif filetype_check_uri(filename, 'shm') - type = 'ctf_shm'; - manufacturer = 'CTF'; - content = 'real-time shared memory buffer'; - - % known CTF file types -elseif isdir(filename) && filetype_check_extension(filename, '.ds') && exist(fullfile(filename, [f '.res4'])) - type = 'ctf_ds'; - manufacturer = 'CTF'; - content = 'MEG dataset'; -elseif isdir(filename) && ~isempty(dir(fullfile(filename, '*.res4'))) && ~isempty(dir(fullfile(filename, '*.meg4'))) - type = 'ctf_ds'; - manufacturer = 'CTF'; - content = 'MEG dataset'; -elseif filetype_check_extension(filename, '.res4') && (filetype_check_header(filename, 'MEG41RS') || filetype_check_header(filename, 'MEG42RS') || filetype_check_header(filename, 'MEG4RES')) - type = 'ctf_res4'; - manufacturer = 'CTF'; - content = 'MEG/EEG header information'; -elseif filetype_check_extension(filename, '.meg4') && filetype_check_header(filename, 'MEG41CP') - type = 'ctf_meg4'; - manufacturer = 'CTF'; - content = 'MEG/EEG'; -elseif filetype_check_extension(filename, '.mrk') && filetype_check_header(filename, 'PATH OF DATASET:') - type = 'ctf_mrk'; - manufacturer = 'CTF'; - content = 'marker file'; -elseif filetype_check_extension(filename, '.mri') && filetype_check_header(filename, 'CTF_MRI_FORMAT VER 2.2') - type = 'ctf_mri'; - manufacturer = 'CTF'; - content = 'MRI'; -elseif filetype_check_extension(filename, '.mri') && filetype_check_header(filename, 'CTF_MRI_FORMAT VER 4', 31) - type = 'ctf_mri4'; - manufacturer = 'CTF'; - content = 'MRI'; -elseif filetype_check_extension(filename, '.hdm') - type = 'ctf_hdm'; - manufacturer = 'CTF'; - content = 'volume conduction model'; -elseif filetype_check_extension(filename, '.hc') - type = 'ctf_hc'; - manufacturer = 'CTF'; - content = 'headcoil locations'; -elseif filetype_check_extension(filename, '.shape') - type = 'ctf_shape'; - manufacturer = 'CTF'; - content = 'headshape points'; -elseif filetype_check_extension(filename, '.shape_info') - type = 'ctf_shapeinfo'; - manufacturer = 'CTF'; - content = 'headshape information'; -elseif filetype_check_extension(filename, '.wts') - type = 'ctf_wts'; - manufacturer = 'CTF'; - content = 'SAM coefficients, i.e. spatial filter weights'; -elseif filetype_check_extension(filename, '.svl') - type = 'ctf_svl'; - manufacturer = 'CTF'; - content = 'SAM (pseudo-)statistic volumes'; - - % known Micromed file types -elseif filetype_check_extension(filename, '.trc') && filetype_check_header(filename, '* MICROMED') - type = 'micromed_trc'; - manufacturer = 'Micromed'; - content = 'Electrophysiological data'; - - % known Neuromag file types -elseif filetype_check_extension(filename, '.fif') - type = 'neuromag_fif'; - manufacturer = 'Neuromag'; - content = 'MEG header and data'; -elseif filetype_check_extension(filename, '.bdip') - type = 'neuromag_bdip'; - manufacturer = 'Neuromag'; - content = 'dipole model'; - - % known Yokogawa file types -elseif filetype_check_extension(filename, '.ave') || filetype_check_extension(filename, '.sqd') - type = 'yokogawa_ave'; - manufacturer = 'Yokogawa'; - content = 'averaged MEG data'; -elseif filetype_check_extension(filename, '.con') - type = 'yokogawa_con'; - manufacturer = 'Yokogawa'; - content = 'continuous MEG data'; -elseif filetype_check_extension(filename, '.raw') && filetype_check_header(filename, [char(0) char(0) char(0) char(0)]) - type = 'yokogawa_raw'; - manufacturer = 'Yokogawa'; - content = 'evoked/trialbased MEG data'; -elseif filetype_check_extension(filename, '.mri') && filetype_check_header(filename, '####') % FIXME, not correct - type = 'yokogawa_mri'; - manufacturer = 'Yokogawa'; - content = 'anatomical MRI'; - -elseif filetype_check_extension(filename, '.pdf') && filetype_check_header(filename, 'E|lk') % I am not sure whether this header always applies - type = '4d_pdf'; - manufacturer = '4D/BTI'; - content = 'raw MEG data (processed data file)'; -elseif exist([filename '.m4d'], 'file') && exist([filename '.xyz'], 'file') % these two ascii header files accompany the raw data - type = '4d_pdf'; - manufacturer = '4D/BTI'; - content = 'raw MEG data (processed data file)'; -elseif filetype_check_extension(filename, '.m4d') && exist([filename(1:(end-3)) 'xyz'], 'file') % these come in pairs - type = '4d_m4d'; - manufacturer = '4D/BTI'; - content = 'MEG header information'; -elseif filetype_check_extension(filename, '.xyz') && exist([filename(1:(end-3)) 'm4d'], 'file') % these come in pairs - type = '4d_xyz'; - manufacturer = '4D/BTI'; - content = 'MEG sensor positions'; -elseif isequal(f, 'hs_file') % the filename is "hs_file" - type = '4d_hs'; - manufacturer = '4D/BTI'; - content = 'head shape'; -elseif length(filename)>=4 && ~isempty(strfind(filename,',rf')) - type = '4d'; - manufacturer = '4D/BTi'; - content = ''; - - % known EEProbe file types -elseif filetype_check_extension(filename, '.cnt') && filetype_check_header(filename, 'RIFF') - type = 'eep_cnt'; - manufacturer = 'EEProbe'; - content = 'EEG'; -elseif filetype_check_extension(filename, '.avr') && filetype_check_header(filename, char([38 0 16 0])) - type = 'eep_avr'; - manufacturer = 'EEProbe'; - content = 'ERP'; -elseif filetype_check_extension(filename, '.trg') - type = 'eep_trg'; - manufacturer = 'EEProbe'; - content = 'trigger information'; -elseif filetype_check_extension(filename, '.rej') - type = 'eep_rej'; - manufacturer = 'EEProbe'; - content = 'rejection marks'; - - % known ASA file types -elseif filetype_check_extension(filename, '.elc') - type = 'asa_elc'; - manufacturer = 'ASA'; - content = 'electrode positions'; -elseif filetype_check_extension(filename, '.vol') - type = 'asa_vol'; - manufacturer = 'ASA'; - content = 'volume conduction model'; -elseif filetype_check_extension(filename, '.bnd') - type = 'asa_bnd'; - manufacturer = 'ASA'; - content = 'boundary element model details'; -elseif filetype_check_extension(filename, '.msm') - type = 'asa_msm'; - manufacturer = 'ASA'; - content = 'ERP'; -elseif filetype_check_extension(filename, '.msr') - type = 'asa_msr'; - manufacturer = 'ASA'; - content = 'ERP'; -elseif filetype_check_extension(filename, '.dip') - % FIXME, can also be CTF dipole file - type = 'asa_dip'; - manufacturer = 'ASA'; -elseif filetype_check_extension(filename, '.mri') - % FIXME, can also be CTF mri file - type = 'asa_mri'; - manufacturer = 'ASA'; - content = 'MRI image header'; -elseif filetype_check_extension(filename, '.iso') - type = 'asa_iso'; - manufacturer = 'ASA'; - content = 'MRI image data'; - - % known BCI2000 file types -elseif filetype_check_extension(filename, '.dat') && (filetype_check_header(filename, 'BCI2000') || filetype_check_header(filename, 'HeaderLen=')) - type = 'bci2000_dat'; - manufacturer = 'BCI2000'; - content = 'continuous EEG'; - - % known Neuroscan file types -elseif filetype_check_extension(filename, '.avg') && filetype_check_header(filename, 'Version 3.0') - type = 'ns_avg'; - manufacturer = 'Neuroscan'; - content = 'averaged EEG'; -elseif filetype_check_extension(filename, '.cnt') && filetype_check_header(filename, 'Version 3.0') - type = 'ns_cnt'; - manufacturer = 'Neuroscan'; - content = 'continuous EEG'; -elseif filetype_check_extension(filename, '.eeg') && filetype_check_header(filename, 'Version 3.0') - type = 'ns_eeg'; - manufacturer = 'Neuroscan'; - content = 'epoched EEG'; - -elseif filetype_check_extension(filename, '.eeg') && filetype_check_header(filename, 'V3.0') - type = 'neuroprax_eeg'; - manufacturer = 'eldith GmbH'; - content = 'continuous EEG'; -elseif filetype_check_extension(filename, '.ee_') - type = 'neuroprax_mrk'; - manufacturer = 'eldith GmbH'; - content = 'EEG markers'; - - % known Analyze & SPM file types -elseif filetype_check_extension(filename, '.hdr') - type = 'analyze_hdr'; - manufacturer = 'Mayo Analyze'; - content = 'PET/MRI image header'; -elseif filetype_check_extension(filename, '.img') - type = 'analyze_img'; - manufacturer = 'Mayo Analyze'; - content = 'PET/MRI image data'; -elseif filetype_check_extension(filename, '.mnc') - type = 'minc'; - content = 'MRI image data'; -elseif filetype_check_extension(filename, '.nii') - type = 'nifti'; - content = 'MRI image data'; - - % known LORETA file types -elseif filetype_check_extension(filename, '.lorb') - type = 'loreta_lorb'; - manufacturer = 'old LORETA'; - content = 'source reconstruction'; -elseif filetype_check_extension(filename, '.slor') - type = 'loreta_slor'; - manufacturer = 'sLORETA'; - content = 'source reconstruction'; - - % known AFNI file types -elseif filetype_check_extension(filename, '.brik') || filetype_check_extension(filename, '.BRIK') - type = 'afni_brik'; - content = 'MRI image data'; -elseif filetype_check_extension(filename, '.head') || filetype_check_extension(filename, '.HEAD') - type = 'afni_head'; - content = 'MRI header data'; - - % known BrainVison file types -elseif filetype_check_extension(filename, '.vhdr') - type = 'brainvision_vhdr'; - manufacturer = 'BrainProducts'; - content = 'EEG header'; -elseif filetype_check_extension(filename, '.vmrk') - type = 'brainvision_vmrk'; - manufacturer = 'BrainProducts'; - content = 'EEG markers'; -elseif filetype_check_extension(filename, '.vabs') - type = 'brainvision_vabs'; - manufacturer = 'BrainProducts'; - content = 'Brain Vison Analyzer macro'; -elseif filetype_check_extension(filename, '.eeg') - % FIXME, can also be Neuroscan epoched EEG data - type = 'brainvision_eeg'; - manufacturer = 'BrainProducts'; - content = 'continuous EEG data'; -elseif filetype_check_extension(filename, '.seg') - type = 'brainvision_seg'; - manufacturer = 'BrainProducts'; - content = 'segmented EEG data'; -elseif filetype_check_extension(filename, '.dat') && ~filetype_check_header(filename, 'HeaderLen=') && ~filetype_check_header(filename, 'BESA_SA_IMAGE') && ~(exist(fullfile(p, [f '.gen']), 'file') || exist(fullfile(p, [f '.generic']), 'file')) - % WARNING this is a very general name, it could be exported BrainVision - % data but also a BESA beamformer source reconstruction or BCI2000 - type = 'brainvision_dat'; - manufacturer = 'BrainProducts'; - content = 'exported EEG data'; -elseif filetype_check_extension(filename, '.marker') - type = 'brainvision_marker'; - manufacturer = 'BrainProducts'; - content = 'rejection markers'; - - % known Polhemus file types -elseif filetype_check_extension(filename, '.pos') - type = 'polhemus_pos'; - manufacturer = 'BrainProducts/CTF/Polhemus?'; % actually I don't know whose software it is - content = 'electrode positions'; - - % known Neuralynx file types -elseif filetype_check_extension(filename, '.nev') || filetype_check_extension(filename, '.Nev') - type = 'neuralynx_nev'; - manufacturer = 'Neuralynx'; - content = 'event information'; -elseif filetype_check_extension(filename, '.ncs') && filetype_check_header(filename, '####') - type = 'neuralynx_ncs'; - manufacturer = 'Neuralynx'; - content = 'continuous single channel recordings'; -elseif filetype_check_extension(filename, '.nse') && filetype_check_header(filename, '####') - type = 'neuralynx_nse'; - manufacturer = 'Neuralynx'; - content = 'spike waveforms'; -elseif filetype_check_extension(filename, '.nts') && filetype_check_header(filename, '####') - type = 'neuralynx_nts'; - manufacturer = 'Neuralynx'; - content = 'timestamps only'; -elseif filetype_check_extension(filename, '.nvt') - type = 'neuralynx_nvt'; - manufacturer = 'Neuralynx'; - content = 'video tracker'; -elseif filetype_check_extension(filename, '.nst') - type = 'neuralynx_nst'; - manufacturer = 'Neuralynx'; - content = 'continuous stereotrode recordings'; -elseif filetype_check_extension(filename, '.ntt') - type = 'neuralynx_ntt'; - manufacturer = 'Neuralynx'; - content = 'continuous tetrode recordings'; -elseif strcmpi(f, 'logfile') && strcmpi(x, '.txt') % case insensitive - type = 'neuralynx_log'; - manufacturer = 'Neuralynx'; - content = 'log information in ASCII format'; -elseif ~isempty(strfind(lower(f), 'dma')) && strcmpi(x, '.log') % this is not a very strong detection - type = 'neuralynx_dma'; - manufacturer = 'Neuralynx'; - content = 'raw aplifier data directly from DMA'; -elseif filetype_check_extension(filename, '.nrd') % see also above, since Cheetah 5.x the file extension has changed - type = 'neuralynx_dma'; - manufacturer = 'Neuralynx'; - content = 'raw aplifier data directly from DMA'; -elseif isdir(filename) && (any(filetype_check_extension({ls.name}, '.nev')) || any(filetype_check_extension({ls.name}, '.Nev'))) - % a regular Neuralynx dataset directory that contains an event file - type = 'neuralynx_ds'; - manufacturer = 'Neuralynx'; - content = 'dataset'; -elseif isdir(filename) && most(filetype_check_extension({ls.name}, '.ncs')) - % a directory containing continuously sampled channels in Neuralynx format - type = 'neuralynx_ds'; - manufacturer = 'Neuralynx'; - content = 'continuously sampled channels'; -elseif isdir(filename) && most(filetype_check_extension({ls.name}, '.nse')) - % a directory containing spike waveforms in Neuralynx format - type = 'neuralynx_ds'; - manufacturer = 'Neuralynx'; - content = 'spike waveforms'; -elseif isdir(filename) && most(filetype_check_extension({ls.name}, '.nte')) - % a directory containing spike timestamps in Neuralynx format - type = 'neuralynx_ds'; - manufacturer = 'Neuralynx'; - content = 'spike timestamps'; - - % these are formally not Neuralynx file formats, but at the FCDC we use them together with Neuralynx -elseif isdir(filename) && any(filetype({ls.name}, 'neuralynx_ds')) - % a downsampled Neuralynx DMA file can be split into three seperate lfp/mua/spike directories - % treat them as one combined dataset - type = 'neuralynx_cds'; - manufacturer = 'F.C. Donders Centre'; - content = 'dataset containing seperate lfp/mua/spike directories'; -elseif filetype_check_extension(filename, '.tsl') && filetype_check_header(filename, 'tsl') - type = 'neuralynx_tsl'; - manufacturer = 'F.C. Donders Centre'; - content = 'timestamps from DMA log file'; -elseif filetype_check_extension(filename, '.tsh') && filetype_check_header(filename, 'tsh') - type = 'neuralynx_tsh'; - manufacturer = 'F.C. Donders Centre'; - content = 'timestamps from DMA log file'; -elseif filetype_check_extension(filename, '.ttl') && filetype_check_header(filename, 'ttl') - type = 'neuralynx_ttl'; - manufacturer = 'F.C. Donders Centre'; - content = 'Parallel_in from DMA log file'; -elseif filetype_check_extension(filename, '.bin') && filetype_check_header(filename, {'uint8', 'uint16', 'uint32', 'int8', 'int16', 'int32', 'int64', 'float32', 'float64'}) - type = 'neuralynx_bin'; - manufacturer = 'F.C. Donders Centre'; - content = 'single channel continuous data'; -elseif isdir(filename) && any(filetype_check_extension({ls.name}, '.ttl')) && any(filetype_check_extension({ls.name}, '.tsl')) && any(filetype_check_extension({ls.name}, '.tsh')) - % a directory containing the split channels from a DMA logfile - type = 'neuralynx_sdma'; - manufacturer = 'F.C. Donders Centre'; - content = 'split DMA log file'; -elseif isdir(filename) && filetype_check_extension(filename, '.sdma') - % a directory containing the split channels from a DMA logfile - type = 'neuralynx_sdma'; - manufacturer = 'F.C. Donders Centre'; - content = 'split DMA log file'; - - % known Plexon file types -elseif filetype_check_extension(filename, '.nex') && filetype_check_header(filename, 'NEX1') - type = 'plexon_nex'; - manufacturer = 'Plexon'; - content = 'electrophysiological data'; -elseif filetype_check_extension(filename, '.plx') && filetype_check_header(filename, 'PLEX') - type = 'plexon_plx'; - manufacturer = 'Plexon'; - content = 'electrophysiological data'; -elseif filetype_check_extension(filename, '.ddt') - type = 'plexon_ddt'; - manufacturer = 'Plexon'; -elseif isdir(filename) && most(filetype_check_extension({ls.name}, '.nex')) && most(filetype_check_header({ls.name}, 'NEX1')) - % a directory containing multiple plexon NEX files - type = 'plexon_ds'; - manufacturer = 'Plexon'; - content = 'electrophysiological data'; - - % known Cambridge Electronic Design file types -elseif filetype_check_extension(filename, '.smr') - type = 'ced_son'; - manufacturer = 'Cambridge Electronic Design'; - content = 'Spike2 SON filing system'; - - % known BESA file types -elseif filetype_check_extension(filename, '.avr') && strcmp(type, 'unknown') - type = 'besa_avr'; % FIXME, can also be EEProbe average EEG - manufacturer = 'BESA'; - content = 'average EEG'; -elseif filetype_check_extension(filename, '.elp') - type = 'besa_elp'; - manufacturer = 'BESA'; - content = 'electrode positions'; -elseif filetype_check_extension(filename, '.eps') - type = 'besa_eps'; - manufacturer = 'BESA'; - content = 'digitizer information'; -elseif filetype_check_extension(filename, '.sfp') - type = 'besa_sfp'; - manufacturer = 'BESA'; - content = 'sensor positions'; -elseif filetype_check_extension(filename, '.ela') - type = 'besa_ela'; - manufacturer = 'BESA'; - content = 'sensor information'; -elseif filetype_check_extension(filename, '.pdg') - type = 'besa_pdg'; - manufacturer = 'BESA'; - content = 'paradigm file'; -elseif filetype_check_extension(filename, '.tfc') - type = 'besa_tfc'; - manufacturer = 'BESA'; - content = 'time frequency coherence'; -elseif filetype_check_extension(filename, '.mul') - type = 'besa_mul'; - manufacturer = 'BESA'; - content = 'multiplexed ascii format'; -elseif filetype_check_extension(filename, '.dat') && filetype_check_header(filename, 'BESA_SA') % header can start with BESA_SA_IMAGE or BESA_SA_MN_IMAGE - type = 'besa_src'; - manufacturer = 'BESA'; - content = 'beamformer source reconstruction'; -elseif filetype_check_extension(filename, '.swf') && filetype_check_header(filename, 'Npts=') - type = 'besa_swf'; - manufacturer = 'BESA'; - content = 'beamformer source waveform'; -elseif filetype_check_extension(filename, '.bsa') - type = 'besa_bsa'; - manufacturer = 'BESA'; - content = 'beamformer source locations and orientations'; -elseif exist(fullfile(p, [f '.dat']), 'file') && (exist(fullfile(p, [f '.gen']), 'file') || exist(fullfile(p, [f '.generic']), 'file')) - type = 'besa_sb'; - manufacturer = 'BESA'; - content = 'simple binary channel data with a seperate generic ascii header'; - - % old files from Pascal Fries' PhD research at the MPI -elseif filetype_check_extension(filename, '.dap') && filetype_check_header(filename, char(1)) - type = 'mpi_dap'; - manufacturer = 'MPI Frankfurt'; - content = 'electrophysiological data'; -elseif isdir(filename) && ~isempty(cell2mat(regexp({ls.name}, '.dap$'))) - type = 'mpi_ds'; - manufacturer = 'MPI Frankfurt'; - content = 'electrophysiological data'; - - % Frankfurt SPASS format, which uses the Labview Datalog (DTLG) format -elseif filetype_check_header(filename, 'DTLG') && filetype_check_extension(filename, '.ana') - type = 'spass_ana'; - manufacturer = 'MPI Frankfurt'; - content = 'electrophysiological data'; -elseif filetype_check_header(filename, 'DTLG') && filetype_check_extension(filename, '.swa') - type = 'spass_swa'; - manufacturer = 'MPI Frankfurt'; - content = 'electrophysiological data'; -elseif filetype_check_header(filename, 'DTLG') && filetype_check_extension(filename, '.spi') - type = 'spass_spi'; - manufacturer = 'MPI Frankfurt'; - content = 'electrophysiological data'; -elseif filetype_check_header(filename, 'DTLG') && filetype_check_extension(filename, '.stm') - type = 'spass_stm'; - manufacturer = 'MPI Frankfurt'; - content = 'electrophysiological data'; -elseif filetype_check_header(filename, 'DTLG') && filetype_check_extension(filename, '.bhv') - type = 'spass_bhv'; - manufacturer = 'MPI Frankfurt'; - content = 'electrophysiological data'; - - % known Chieti ITAB file types -elseif filetype_check_extension(filename, '.raw') && filetype_check_header(filename, 'FORMAT: ATB-BIOMAGDATA') - type = 'itab_raw'; - manufacturer = 'Chieti ITAB'; - content = 'MEG data, including sensor positions'; - - % known Nexstim file types -elseif filetype_check_extension(filename, '.nxe') - type = 'nexstim_nxe'; - manufacturer = 'Nexstim'; - content = 'electrophysiological data'; - - % known Curry V4 file types -elseif filetype_check_extension(filename, '.dap') - type = 'curry_dap'; % FIXME, can also be MPI Frankfurt electrophysiological data - manufacturer = 'Curry'; - content = 'data parameter file'; -elseif filetype_check_extension(filename, '.dat') - type = 'curry_dat'; - manufacturer = 'Curry'; - content = 'raw data file'; -elseif filetype_check_extension(filename, '.rs4') - type = 'curry_rs4'; - manufacturer = 'Curry'; - content = 'sensor geometry file'; -elseif filetype_check_extension(filename, '.par') - type = 'curry_par'; - manufacturer = 'Curry'; - content = 'data or image parameter file'; -elseif filetype_check_extension(filename, '.bd0') || filetype_check_extension(filename, '.bd1') || filetype_check_extension(filename, '.bd2') || filetype_check_extension(filename, '.bd3') || filetype_check_extension(filename, '.bd4') || filetype_check_extension(filename, '.bd5') || filetype_check_extension(filename, '.bd6') || filetype_check_extension(filename, '.bd7') || filetype_check_extension(filename, '.bd8') || filetype_check_extension(filename, '.bd9') - type = 'curry_bd'; - manufacturer = 'Curry'; - content = 'BEM description file'; -elseif filetype_check_extension(filename, '.bt0') || filetype_check_extension(filename, '.bt1') || filetype_check_extension(filename, '.bt2') || filetype_check_extension(filename, '.bt3') || filetype_check_extension(filename, '.bt4') || filetype_check_extension(filename, '.bt5') || filetype_check_extension(filename, '.bt6') || filetype_check_extension(filename, '.bt7') || filetype_check_extension(filename, '.bt8') || filetype_check_extension(filename, '.bt9') - type = 'curry_bt'; - manufacturer = 'Curry'; - content = 'BEM transfer matrix file'; -elseif filetype_check_extension(filename, '.bm0') || filetype_check_extension(filename, '.bm1') || filetype_check_extension(filename, '.bm2') || filetype_check_extension(filename, '.bm3') || filetype_check_extension(filename, '.bm4') || filetype_check_extension(filename, '.bm5') || filetype_check_extension(filename, '.bm6') || filetype_check_extension(filename, '.bm7') || filetype_check_extension(filename, '.bm8') || filetype_check_extension(filename, '.bm9') - type = 'curry_bm'; - manufacturer = 'Curry'; - content = 'BEM full matrix file'; -elseif filetype_check_extension(filename, '.dig') - type = 'curry_dig'; - manufacturer = 'Curry'; - content = 'digitizer file'; - - % known Curry V2 file types -elseif filetype_check_extension(filename, '.sp0') || filetype_check_extension(filename, '.sp1') || filetype_check_extension(filename, '.sp2') || filetype_check_extension(filename, '.sp3') || filetype_check_extension(filename, '.sp4') || filetype_check_extension(filename, '.sp5') || filetype_check_extension(filename, '.sp6') || filetype_check_extension(filename, '.sp7') || filetype_check_extension(filename, '.sp8') || filetype_check_extension(filename, '.sp9') - type = 'curry_sp'; - manufacturer = 'Curry'; - content = 'point list'; -elseif filetype_check_extension(filename, '.s10') || filetype_check_extension(filename, '.s11') || filetype_check_extension(filename, '.s12') || filetype_check_extension(filename, '.s13') || filetype_check_extension(filename, '.s14') || filetype_check_extension(filename, '.s15') || filetype_check_extension(filename, '.s16') || filetype_check_extension(filename, '.s17') || filetype_check_extension(filename, '.s18') || filetype_check_extension(filename, '.s19') || filetype_check_extension(filename, '.s20') || filetype_check_extension(filename, '.s21') || filetype_check_extension(filename, '.s22') || filetype_check_extension(filename, '.s23') || filetype_check_extension(filename, '.s24') || filetype_check_extension(filename, '.s25') || filetype_check_extension(filename, '.s26') || filetype_check_extension(filename, '.s27') || filetype_check_extension(filename, '.s28') || filetype_check_extension(filename, '.s29') || filetype_check_extension(filename, '.s30') || filetype_check_extension(filename, '.s31') || filetype_check_extension(filename, '.s32') || filetype_check_extension(filename, '.s33') || filetype_check_extension(filename, '.s34') || filetype_check_extension(filename, '.s35') || filetype_check_extension(filename, '.s36') || filetype_check_extension(filename, '.s37') || filetype_check_extension(filename, '.s38') || filetype_check_extension(filename, '.s39') - type = 'curry_s'; - manufacturer = 'Curry'; - content = 'triangle or tetraedra list'; -elseif filetype_check_extension(filename, '.pom') - type = 'curry_pom'; - manufacturer = 'Curry'; - content = 'anatomical localization file'; -elseif filetype_check_extension(filename, '.res') - type = 'curry_res'; - manufacturer = 'Curry'; - content = 'functional localization file'; - - % known MBFYS file types -elseif filetype_check_extension(filename, '.tri') - type = 'mbfys_tri'; - manufacturer = 'MBFYS'; - content = 'triangulated surface'; -elseif filetype_check_extension(filename, '.ama') && filetype_check_header(filename, [10 0 0 0]) - type = 'mbfys_ama'; - manufacturer = 'MBFYS'; - content = 'BEM volume conduction model'; - - % Electrical Geodesics Incorporated format -elseif (filetype_check_extension(filename, '.egis') || filetype_check_extension(filename, '.ave') || filetype_check_extension(filename, '.gave') || filetype_check_extension(filename, '.raw')) && (filetype_check_header(filename, [char(1) char(2) char(3) char(4) char(255) char(255)]) || filetype_check_header(filename, [char(3) char(4) char(1) char(2) char(255) char(255)])) - type = 'egi_egia'; - manufacturer = 'Electrical Geodesics Incorporated'; - content = 'averaged EEG data'; -elseif (filetype_check_extension(filename, '.egis') || filetype_check_extension(filename, '.ses') || filetype_check_extension(filename, '.raw')) && (filetype_check_header(filename, [char(1) char(2) char(3) char(4) char(0) char(3)]) || filetype_check_header(filename, [char(3) char(4) char(1) char(2) char(0) char(3)])) - type = 'egi_egis'; - manufacturer = 'Electrical Geodesics Incorporated'; - content = 'raw EEG data'; -elseif (filetype_check_extension(filename, '.sbin') || filetype_check_extension(filename, '.raw')) - % note that the Chieti MEG data format also has the extension *.raw - % but that can be detected by looking at the file header - type = 'egi_sbin'; - manufacturer = 'Electrical Geodesics Incorporated'; - content = 'averaged EEG data'; - - - % some other known file types -elseif length(filename)>4 && exist([filename(1:(end-4)) '.mat'], 'file') && exist([filename(1:(end-4)) '.bin'], 'file') - % this is a self-defined FCDC data format, consisting of two files - % there is a matlab V6 file with the header and a binary file with the data (multiplexed, ieee-le, double) - type = 'fcdc_matbin'; - manufacturer = 'F.C. Donders Centre'; - content = 'multiplexed electrophysiology data'; -elseif filetype_check_extension(filename, '.lay') - type = 'layout'; - manufacturer = 'Ole Jensen'; - content = 'layout of channels for plotting'; -elseif filetype_check_extension(filename, '.dcm') || filetype_check_extension(filename, '.ima') || filetype_check_header(filename, 'DICM', 128) - type = 'dicom'; - manufacturer = 'Dicom'; - content = 'image data'; -elseif filetype_check_extension(filename, '.trl') - type = 'fcdc_trl'; - manufacturer = 'F.C.Donders'; - content = 'trial definitions'; -elseif filetype_check_header(filename, [255 'BIOSEMI']) % filetype_check_extension(filename, '.bdf') - type = 'biosemi_bdf'; - % type = 'bham_bdf'; - manufacturer = 'Biosemi Data Format'; - content = 'electrophysiological data'; -elseif filetype_check_extension(filename, '.edf') - type = 'edf'; - manufacturer = 'European Data Format'; - content = 'electrophysiological data'; -elseif filetype_check_extension(filename, '.mat') && exist(filename, 'file') && exist([filename(1:(end-4)) '.dat'], 'file') && numel(whos('-file', filename))==1 && strcmp('D', getfield(whos('-file', filename), {1}, 'name')) && strcmp('struct', getfield(whos('-file', filename), {1}, 'class')) - type = 'spmeeg_mat'; - manufacturer = 'Wellcome Trust Centre for Neuroimaging, UCL, UK'; - content = 'electrophysiological data'; -elseif filetype_check_extension(filename, '.mat') && exist(filename, 'file') && filetype_check_ced_spike6mat(filename) - type = 'ced_spike6mat'; - manufacturer = 'Cambridge Electronic Design Limited'; - content = 'electrophysiological data'; -elseif filetype_check_extension(filename, '.mat') && filetype_check_header(filename, 'MATLAB') - type = 'matlab'; - manufacturer = 'Matlab'; - content = 'Matlab binary data'; -elseif filetype_check_header(filename, 'RIFF', 0) && filetype_check_header(filename, 'WAVE', 8) - type = 'riff_wave'; - manufacturer = 'Microsoft'; - content = 'audio'; -elseif filetype_check_extension(filename, '.txt') - type = 'ascii_txt'; - manufacturer = ''; - content = ''; -elseif filetype_check_extension(filename, '.pol') - type = 'polhemus_fil'; - manufacturer = 'Functional Imaging Lab, London, UK'; - content = 'headshape points'; -elseif filetype_check_extension(filename, '.set') - type = 'eeglab_set'; - manufacturer = 'Swartz Center for Computational Neuroscience, San Diego, USA'; - content = 'electrophysiological data'; -elseif filetype_check_extension(filename, '.t') && filetype_check_header(filename, '%%BEGINHEADER') - type = 'mclust_t'; - manufacturer = 'MClust'; - content = 'sorted spikes'; -elseif filetype_check_header(filename, 26) - type = 'nimh_cortex'; - manufacturer = 'NIMH Laboratory of Neuropsychology, http://www.cortex.salk.edu'; - content = 'events and eye channels'; -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% finished determining the filetype -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -if strcmp(type, 'unknown') - warning('could not determine filetype of %s', filename); -end - -if ~isempty(desired) - % return a boolean value instead of a descriptive string - type = strcmp(type, desired); -end - -% remember the current input and output arguments, so that they can be -% reused on a subsequent call in case the same input argument is given -current_argout = {type}; -if isempty(previous_argin) && ~strcmp(type, 'unknown') - previous_argin = current_argin; - previous_argout = current_argout; - previous_pwd = current_pwd; -else - % don't remember in case unknown - previous_argin = []; - previous_argout = []; - previous_pwd = []; -end - -return % filetype main() - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION that helps in deciding whether a directory with files should -% be treated as a "dataset". This function returns a logical 1 (TRUE) if more -% than half of the element of a vector are nonzero number or are logical 1 -% (TRUE). -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function y = most(x) -x = x(find(~isnan(x(:)))); -y = sum(x==0). % +% $Id: filetype_check_extension.m 1238 2010-06-16 16:03:32Z roboos $ + +% these are for remembering the type on subsequent calls with the same input arguments +persistent previous_argin previous_argout + +current_argin = {filename, ext}; +if isequal(current_argin, previous_argin) + % don't do the detection again, but return the previous value from cache + val = previous_argout; + return +end if iscell(filename) % compare the extension of multiple files @@ -33,10 +42,16 @@ else % compare the extension of a single file if numel(filename). % +% $Id: filetype_check_header.m 1238 2010-06-16 16:03:32Z roboos $ + +% these are for remembering the type on subsequent calls with the same input arguments +persistent previous_argin previous_argout if nargin<3 offset = 0; end +current_argin = {filename, head, offset}; +if isequal(current_argin, previous_argin) + % don't do the detection again, but return the previous value from cache + val = previous_argout; + return +end + if iscell(filename) % compare the header of multiple files val = zeros(size(filename)); @@ -55,13 +46,13 @@ end elseif isdir(filename) % a directory cannot have a header - val = 0; + val = false; else % read the first few bytes from the file and compare them to the desired header fid = fopen(filename, 'rb'); if fid<0 warning(sprintf('could not open %s', filename)); - val = 0; + val = false; else fseek(fid, offset, 'cof'); if iscell(head) @@ -81,12 +72,18 @@ fclose(fid); if siz~=length(head) warning(sprintf('could not read the header from %s', filename)); - val = 0; + val = false; else val = all(str(:)==head(:)); end end end end -return +% remember the current input and output arguments, so that they can be +% reused on a subsequent call in case the same input argument is given +current_argout = val; +previous_argin = current_argin; +previous_argout = current_argout; + +return % main() diff --git a/external/fieldtrip/private/filetype_check_uri.m b/external/fieldtrip/private/filetype_check_uri.m index c6cec94..b48fbc6 100644 --- a/external/fieldtrip/private/filetype_check_uri.m +++ b/external/fieldtrip/private/filetype_check_uri.m @@ -3,14 +3,15 @@ % FILETYPE_CHECK_URI % % Supported URIs are -% shm:// -% fifo:// % buffer://: -% tcp://: -% udp://: +% fifo:// +% global:// % mysql://:@: % rfb://@: % serial:?key1=value1&key2=value2&... +% shm:// +% tcp://: +% udp://: % % The URI schemes supproted by these function are not the official schemes. % See the documentation included inside this function for more details. @@ -20,37 +21,38 @@ % Copyright (C) 2007, Robert Oostenveld % -% $Log: filetype_check_uri.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.7 2008/12/19 14:40:23 marvger -% added support for udp, tcp and fifo -% -% Revision 1.6 2008/02/19 10:07:34 roboos -% replaced tcpsocket with buffer -% -% Revision 1.5 2007/11/07 10:45:56 roboos -% made port optional for mysql +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.4 2007/10/15 16:02:46 roboos -% added rfb://@: +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.3 2007/07/27 12:18:50 roboos -% added ctf_shm +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.2 2007/06/19 11:13:59 chrhes -% small change in how the serial port case is processed to allow for the -% possibility of no options being passed -% -% Revision 1.1 2007/06/06 07:10:36 roboos -% initial implementation +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: filetype_check_uri.m 1238 2010-06-16 16:03:32Z roboos $ + +% these are for remembering the type on subsequent calls with the same input arguments +persistent previous_argin previous_argout + +if nargin<2 + % ensure that all input arguments are defined + ftyp = []; +end + +current_argin = {filename, ftyp}; +if isequal(current_argin, previous_argin) + % don't do the detection again, but return the previous value from cache + varargout = previous_argout; + return +end sep = find(filename==':'); if ~isempty(sep) @@ -67,7 +69,7 @@ switch scheme case 'shm' % shm:// - % the filename is optional, usually it can and will be read from shared memory + % the filename is optional, usually it can and will be read from shared memory if length(filename)>6 varargout{1} = filename(7:end); else @@ -78,6 +80,10 @@ % fifo:// varargout{1} = filename(8:end); + case 'global' + % global:// + varargout{1} = filename(10:end); + case 'buffer' % buffer://: tok = tokenize(filename(10:end), ':'); @@ -119,7 +125,7 @@ end case 'serial' - % serial:?key1=value1&key2=value2&... + % serial:?key1=value1&key2=value2&... % the supported optional arguments are % BaudRate % DataBits @@ -143,80 +149,88 @@ end varargout{2} = opt; end - + otherwise error('unsupported scheme in URI') end end +% remember the current input and output arguments, so that they can be +% reused on a subsequent call in case the same input argument is given +current_argout = varargout; +previous_argin = current_argin; +previous_argout = current_argout; + +return % main() + % RFC4395 defines an IANA-maintained registry of URI Schemes. % see also http://www.iana.org/assignments/uri-schemes.html % and http://en.wikipedia.org/wiki/URI_scheme#Generic_syntax % % Scheme Description Reference % ------------------------------------------------------------- -% aaa Diameter Protocol [RFC3588] -% aaas Diameter Protocol with Secure Transport [RFC3588] -% acap application configuration access protocol [RFC2244] -% cap Calendar Access Protocol [RFC4324] -% cid content identifier [RFC2392] -% crid TV-Anytime Content Reference Identifier [RFC4078] -% data data [RFC2397] -% dav dav [RFC-ietf-webdav-rfc2518bis-18.txt] -% dict dictionary service protocol [RFC2229] -% dns Domain Name System [RFC4501] -% fax fax [RFC3966] -% file Host-specific file names [RFC1738] -% ftp File Transfer Protocol [RFC1738] -% go go [RFC3368] -% gopher The Gopher Protocol [RFC4266] -% h323 H.323 [RFC3508] -% http Hypertext Transfer Protocol [RFC2616] -% https Hypertext Transfer Protocol Secure [RFC2818] -% icap Internet Content Adaptation Protocol [RFC3507] -% im Instant Messaging [RFC3860] -% imap internet message access protocol [RFC2192] -% info Information Assets with Identifiers in Public Namespaces [RFC4452] -% ipp Internet Printing Protocol [RFC3510] -% iris Internet Registry Information Service [RFC3981] -% iris.beep iris.beep [RFC3983] -% iris.xpc iris.xpc [RFC-ietf-crisp-iris-xpc-06.txt] -% iris.xpcs iris.xpcs [RFC-ietf-crisp-iris-xpc-06.txt] -% iris.lwz iris.lwz [RFC-ietf-crisp-iris-lwz-08.txt] -% ldap Lightweight Directory Access Protocol [RFC4516] -% mailto Electronic mail address [RFC2368] -% mid message identifier [RFC2392] -% modem modem [RFC3966] -% msrp Message Session Relay Protocol [RFC-ietf-simple-message-sessions-19.txt] -% msrps Message Session Relay Protocol Secure [RFC-ietf-simple-message-sessions-19.txt] -% mtqp Message Tracking Query Protocol [RFC3887] -% mupdate Mailbox Update (MUPDATE) Protocol [RFC3656] -% news USENET news [RFC1738] -% nfs network file system protocol [RFC2224] -% nntp USENET news using NNTP access [RFC1738] -% opaquelocktoken opaquelocktokent [RFC-ietf-webdav-rfc2518bis-18.txt] -% pop Post Office Protocol v3 [RFC2384] -% pres Presence [RFC3859] -% rtsp real time streaming protocol [RFC2326] -% service service location [RFC2609] -% shttp Secure Hypertext Transfer Protocol [RFC2660] -% sip session initiation protocol [RFC3261] -% sips secure session initiation protocol [RFC3261] -% snmp Simple Network Management Protocol [RFC4088] -% soap.beep soap.beep [RFC3288] -% soap.beeps soap.beeps [RFC3288] -% tag tag [RFC4151] -% tel telephone [RFC3966] -% telnet Reference to interactive sessions [RFC4248] -% tftp Trivial File Transfer Protocol [RFC3617] -% thismessage multipart/related relative reference resolution [RFC2557] -% tip Transaction Internet Protocol [RFC2371] -% tv TV Broadcasts [RFC2838] -% urn Uniform Resource Names (click for registry) [RFC2141] -% vemmi versatile multimedia interface [RFC2122] -% xmlrpc.beep xmlrpc.beep [RFC3529] -% xmlrpc.beeps xmlrpc.beeps [RFC3529] -% xmpp Extensible Messaging and Presence Protocol [RFC4622] -% z39.50r Z39.50 Retrieval [RFC2056] -% z39.50s Z39.50 Session [RFC2056] +% aaa Diameter Protocol [RFC3588] +% aaas Diameter Protocol with Secure Transport [RFC3588] +% acap application configuration access protocol [RFC2244] +% cap Calendar Access Protocol [RFC4324] +% cid content identifier [RFC2392] +% crid TV-Anytime Content Reference Identifier [RFC4078] +% data data [RFC2397] +% dav dav [RFC-ietf-webdav-rfc2518bis-18.txt] +% dict dictionary service protocol [RFC2229] +% dns Domain Name System [RFC4501] +% fax fax [RFC3966] +% file Host-specific file names [RFC1738] +% ftp File Transfer Protocol [RFC1738] +% go go [RFC3368] +% gopher The Gopher Protocol [RFC4266] +% h323 H.323 [RFC3508] +% http Hypertext Transfer Protocol [RFC2616] +% https Hypertext Transfer Protocol Secure [RFC2818] +% icap Internet Content Adaptation Protocol [RFC3507] +% im Instant Messaging [RFC3860] +% imap internet message access protocol [RFC2192] +% info Information Assets with Identifiers in Public Namespaces [RFC4452] +% ipp Internet Printing Protocol [RFC3510] +% iris Internet Registry Information Service [RFC3981] +% iris.beep iris.beep [RFC3983] +% iris.xpc iris.xpc [RFC-ietf-crisp-iris-xpc-06.txt] +% iris.xpcs iris.xpcs [RFC-ietf-crisp-iris-xpc-06.txt] +% iris.lwz iris.lwz [RFC-ietf-crisp-iris-lwz-08.txt] +% ldap Lightweight Directory Access Protocol [RFC4516] +% mailto Electronic mail address [RFC2368] +% mid message identifier [RFC2392] +% modem modem [RFC3966] +% msrp Message Session Relay Protocol [RFC-ietf-simple-message-sessions-19.txt] +% msrps Message Session Relay Protocol Secure [RFC-ietf-simple-message-sessions-19.txt] +% mtqp Message Tracking Query Protocol [RFC3887] +% mupdate Mailbox Update (MUPDATE) Protocol [RFC3656] +% news USENET news [RFC1738] +% nfs network file system protocol [RFC2224] +% nntp USENET news using NNTP access [RFC1738] +% opaquelocktoken opaquelocktokent [RFC-ietf-webdav-rfc2518bis-18.txt] +% pop Post Office Protocol v3 [RFC2384] +% pres Presence [RFC3859] +% rtsp real time streaming protocol [RFC2326] +% service service location [RFC2609] +% shttp Secure Hypertext Transfer Protocol [RFC2660] +% sip session initiation protocol [RFC3261] +% sips secure session initiation protocol [RFC3261] +% snmp Simple Network Management Protocol [RFC4088] +% soap.beep soap.beep [RFC3288] +% soap.beeps soap.beeps [RFC3288] +% tag tag [RFC4151] +% tel telephone [RFC3966] +% telnet Reference to interactive sessions [RFC4248] +% tftp Trivial File Transfer Protocol [RFC3617] +% thismessage multipart/related relative reference resolution [RFC2557] +% tip Transaction Internet Protocol [RFC2371] +% tv TV Broadcasts [RFC2838] +% urn Uniform Resource Names (click for registry) [RFC2141] +% vemmi versatile multimedia interface [RFC2122] +% xmlrpc.beep xmlrpc.beep [RFC3529] +% xmlrpc.beeps xmlrpc.beeps [RFC3529] +% xmpp Extensible Messaging and Presence Protocol [RFC4622] +% z39.50r Z39.50 Retrieval [RFC2056] +% z39.50s Z39.50 Session [RFC2056] diff --git a/external/fieldtrip/private/filter_event.m b/external/fieldtrip/private/filter_event.m deleted file mode 100644 index 5cdba5f..0000000 --- a/external/fieldtrip/private/filter_event.m +++ /dev/null @@ -1,120 +0,0 @@ -function event = filter_event(event, varargin) - -% FILTER_EVENT does what its name implies -% -% Use as -% event = filter_event(event, ...) -% -% The optional arguments should come in key-value pairs and determine the -% filter characteristics: -% type = cell-array with strings -% value = numeric array -% sample = numeric array -% timestamp = numeric array -% offset = numeric array -% duration = numeric array -% minsample = value -% maxsample = value -% minduration = value -% maxduration = value -% mintimestamp = value -% maxtimestamp = value -% minnumber = value, applies only if event.number is present -% maxnmumber = value, applies only if event.number is present -% -% See also READ_EVEN, WRITE_EVENT - -% Copyright (C) 2007, Robert Oostenveld -% -% $Log: filter_event.m,v $ -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.6 2007/12/20 19:04:12 roboos -% added filtering for minnumber and maxnumber (in line with read_neuralyns_nev) -% -% Revision 1.5 2007/12/19 08:28:50 roboos -% fixed bug for those filters which accept a numeric array (inserted any(..) around teh comparison) -% added teh missing code for filtering on timestamp value -% -% Revision 1.4 2007/08/21 16:56:03 chrhes -% fixed some logic (typo) bugs in relation to setting the testing flags -% -% Revision 1.3 2007/08/16 13:33:20 chrhes -% fixed some typos in the if statements implementing the event selection -% -% Revision 1.2 2007/07/30 12:16:17 roboos -% updated documentation -% implemented min and max timestamp -% -% Revision 1.1 2007/06/13 14:47:35 roboos -% moved filter_event from fieldtrip to fileio module -% -% Revision 1.1 2007/06/06 12:41:22 roboos -% new implementation -% - -% get the optional input arguments -type = keyval('type', varargin); -value = keyval('value', varargin); -sample = keyval('sample', varargin); -timestamp = keyval('timestamp', varargin); -offset = keyval('offset', varargin); -duration = keyval('duration', varargin); - -% the numeric fields can also be filtered on a range -minsample = keyval('minsample', varargin); -maxsample = keyval('maxsample', varargin); -minduration = keyval('minduration', varargin); -maxduration = keyval('maxduration', varargin); -mintimestamp = keyval('mintimestamp', varargin); -maxtimestamp = keyval('maxtimestamp', varargin); -minnumber = keyval('minnumber', varargin); -maxnumber = keyval('maxnumber', varargin); - -if ~isempty(type) - % this can be specified as string or as cell-array, convert to cell-array - if ~iscell(type) - type = {type}; - end -end - -% determine which filters to apply -testtype = ~isempty(type) && isfield(event, 'type'); -testvalue = ~isempty(value) && isfield(event, 'value'); -testsample = ~isempty(sample) && isfield(event, 'sample'); -testtimestamp = ~isempty(timestamp) && isfield(event, 'timestamp'); -testoffset = ~isempty(offset) && isfield(event, 'offset'); -testduration = ~isempty(duration) && isfield(event, 'duration'); -testminsample = ~isempty(minsample) && isfield(event, 'sample'); -testmaxsample = ~isempty(maxsample) && isfield(event, 'sample'); -testminduration = ~isempty(minduration) && isfield(event, 'duration'); -testmaxduration = ~isempty(maxduration) && isfield(event, 'duration'); -testmintimestamp = ~isempty(mintimestamp) && isfield(event, 'timestamp'); -testmaxtimestamp = ~isempty(maxtimestamp) && isfield(event, 'timestamp'); -testminnumber = ~isempty(minnumber) && isfield(event, 'number'); -testmaxnumber = ~isempty(maxnumber) && isfield(event, 'number'); - -% apply the filters -sel = true(length(event),1); -for i=1:length(event) - % test whether they match with the selected arrays - if testvalue, sel(i) = sel(i) && any(event(i).value == value); end - if testsample, sel(i) = sel(i) && any(event(i).sample == sample); end - if testtimestamp,sel(i) = sel(i) && any(event(i).timestamp == timestamp); end - if testoffset, sel(i) = sel(i) && any(event(i).offset == offset); end - if testduration, sel(i) = sel(i) && any(event(i).duration == duration); end - % test whether they lie within the specified range - if testminsample, sel(i) = sel(i) && (event(i).sample >= minsample); end - if testmaxsample, sel(i) = sel(i) && (event(i).sample <= maxsample); end - if testminduration, sel(i) = sel(i) && (event(i).duration >= minduration); end - if testmaxduration, sel(i) = sel(i) && (event(i).duration <= maxduration); end - if testmintimestamp, sel(i) = sel(i) && (event(i).timestamp >= mintimestamp); end - if testmaxtimestamp, sel(i) = sel(i) && (event(i).timestamp <= maxtimestamp); end - if testminnumber, sel(i) = sel(i) && (event(i).number >= minnumber); end - if testmaxnumber, sel(i) = sel(i) && (event(i).number <= maxnumber); end - % this is potentially the slowest test, hence do it the last - if testtype, sel(i) = sel(i) && any(strcmp(event(i).type, type)); end -end - -event = event(sel); \ No newline at end of file diff --git a/external/fieldtrip/private/find_innermost_boundary.m b/external/fieldtrip/private/find_innermost_boundary.m index 9ab5a96..d7b37a1 100644 --- a/external/fieldtrip/private/find_innermost_boundary.m +++ b/external/fieldtrip/private/find_innermost_boundary.m @@ -7,18 +7,28 @@ % [innermost] = find_innermost_boundary(bnd) % % with the boundaries described by a struct array bnd with -% bnd(i).pnt vertices of boundary i (matrix of size Nx3) -% bnd(i).tri triangles of boundary i (matrix of size Mx3) +% bnd(i).pnt vertices of boundary i (matrix of size Nx3) +% bnd(i).tri triangles of boundary i (matrix of size Mx3) % Copyright (C) 2003, Robert Oostenveld % -% $Log: find_innermost_boundary.m,v $ -% Revision 1.3 2009/09/23 13:16:27 roboos -% also support single boundary +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.2 2003/03/04 21:46:18 roberto -% added CVS log entry and synchronized all copyright labels +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: find_innermost_boundary.m 946 2010-04-21 17:51:16Z roboos $ ncmp = length(bnd); @@ -31,7 +41,7 @@ for i=1:ncmp for j=1:ncmp % determine for a single vertex on each surface if it is inside or outside the other surfaces - curpos = bnd(i).pnt(1,:); % any point on the boundary is ok + curpos = bnd(i).pnt(1,:); % any point on the boundary is ok curpnt = bnd(j).pnt; curtri = bnd(j).tri; if i==j diff --git a/external/fieldtrip/private/find_inside_vol.m b/external/fieldtrip/private/find_inside_vol.m index b79600f..6830ef6 100644 --- a/external/fieldtrip/private/find_inside_vol.m +++ b/external/fieldtrip/private/find_inside_vol.m @@ -10,17 +10,26 @@ % Copyright (C) 2003-2007, Robert Oostenveld % -% $Log: find_inside_vol.m,v $ -% Revision 1.1 2009/01/21 10:32:38 roboos -% moved from forwinv/* and forwinv/mex/* directory to forwinv/private/* to make the CVS layout consistent with the release version +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.8 2008/09/20 13:41:35 roboos -% moved content of find_inside_vol to new inside_vol function with slightly different interface -% added wrapper for spm +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: find_inside_vol.m 1074 2010-05-17 07:52:16Z roboos $ -inside = inside_vol(pos, vol); +inside = ft_inside_vol(pos, vol); % replace boolean vector with indexing vectors outside = find(~inside); inside = find(inside); diff --git a/external/fieldtrip/private/find_mesh_edge.m b/external/fieldtrip/private/find_mesh_edge.m index d92c1a6..f93f115 100644 --- a/external/fieldtrip/private/find_mesh_edge.m +++ b/external/fieldtrip/private/find_mesh_edge.m @@ -4,15 +4,28 @@ % % [pnt, line] = find_mesh_edge(pnt, dhk), where % -% pnt contains the vertex locations and -% line contains the indices of the linepieces connecting the vertices +% pnt contains the vertex locations and +% line contains the indices of the linepieces connecting the vertices % Copyright (C) 2003, Robert Oostenveld % -% $Log: find_mesh_edge.m,v $ -% Revision 1.2 2003/03/04 21:46:18 roberto -% added CVS log entry and synchronized all copyright labels +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: find_mesh_edge.m 952 2010-04-21 18:29:51Z roboos $ npnt = size(pnt,1); ndhk = size(dhk,1); diff --git a/external/fieldtrip/private/find_nearest.m b/external/fieldtrip/private/find_nearest.m index 23cf3e7..8285f72 100644 --- a/external/fieldtrip/private/find_nearest.m +++ b/external/fieldtrip/private/find_nearest.m @@ -9,13 +9,23 @@ % Copyright (C) 2007, Robert Oostenveld % -% $Log: find_nearest.m,v $ -% Revision 1.2 2007/02/08 14:43:14 roboos -% handle case when points ly in an empty target partition (required for cortex in 3d volume) +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.1 2007/02/07 07:38:34 roboos -% new implementation, based on an idea of Theo +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: find_nearest.m 952 2010-04-21 18:29:51Z roboos $ global fb; if isempty(fb) diff --git a/external/fieldtrip/private/find_outermost_boundary.m b/external/fieldtrip/private/find_outermost_boundary.m index 28f9f85..66b3a5f 100644 --- a/external/fieldtrip/private/find_outermost_boundary.m +++ b/external/fieldtrip/private/find_outermost_boundary.m @@ -7,15 +7,28 @@ % [outermost] = find_innermost_boundary(bnd) % % with the boundaries described by a struct array bnd with -% bnd(i).pnt vertices of boundary i (matrix of size Nx3) -% bnd(i).tri triangles of boundary i (matrix of size Mx3) +% bnd(i).pnt vertices of boundary i (matrix of size Nx3) +% bnd(i).tri triangles of boundary i (matrix of size Mx3) % Copyright (C) 2003, Robert Oostenveld % -% $Log: find_outermost_boundary.m,v $ -% Revision 1.2 2003/03/04 21:46:18 roberto -% added CVS log entry and synchronized all copyright labels +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: find_outermost_boundary.m 946 2010-04-21 17:51:16Z roboos $ ncmp = length(bnd); @@ -23,7 +36,7 @@ for i=1:ncmp for j=1:ncmp % determine for a single vertex on each surface if it is inside or outside the other surfaces - curpos = bnd(i).pnt(1,:); % any point on the boundary is ok + curpos = bnd(i).pnt(1,:); % any point on the boundary is ok curpnt = bnd(j).pnt; curtri = bnd(j).tri; if i==j diff --git a/external/fieldtrip/private/find_triangle_neighbours.m b/external/fieldtrip/private/find_triangle_neighbours.m index 494b35d..5055732 100644 --- a/external/fieldtrip/private/find_triangle_neighbours.m +++ b/external/fieldtrip/private/find_triangle_neighbours.m @@ -8,10 +8,23 @@ % Copyright (C) 2003, Robert Oostenveld % -% $Log: find_triangle_neighbours.m,v $ -% Revision 1.2 2003/03/04 21:46:18 roberto -% added CVS log entry and synchronized all copyright labels +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: find_triangle_neighbours.m 952 2010-04-21 18:29:51Z roboos $ npnt = size(pnt,1); ndhk = size(dhk,1); diff --git a/external/fieldtrip/private/findcfg.m b/external/fieldtrip/private/findcfg.m deleted file mode 100644 index e2f2400..0000000 --- a/external/fieldtrip/private/findcfg.m +++ /dev/null @@ -1,46 +0,0 @@ -function [val, status] = findcfg(cfg, var); - -% FINDCFG searches for an element in the cfg structure -% or in the nested previous cfgs -% -% Use as -% [val] = findcfg(cfg, var) -% where the name of the variable should be specified as string. -% -% e.g. -% trl = findcfg(cfg, 'trl') -% event = findcfg(cfg, 'event') - -% Copyright (C) 2006, Robert Oostenveld -% -% $Log: findcfg.m,v $ -% Revision 1.1 2006/07/24 11:24:39 roboos -% new implementation -% - -if var(1)~='.' - var = ['.' var]; -end -val = []; -depth = 0; -status = 0; - -while ~status - depth = depth + 1; - if issubfield(cfg, var) - val = getsubfield(cfg, var); - status = 1; - elseif issubfield(cfg, '.previous'); - [val, status] = findcfg(cfg.previous, var); - if status, break; end; - elseif iscell(cfg) - for i=1:length(cfg) - [val, status] = findcfg(cfg{i}, var); - if status, break; end; - end - else - status = -1; - break - end -end - diff --git a/external/fieldtrip/private/findcluster.m b/external/fieldtrip/private/findcluster.m index e294744..a15a110 100644 --- a/external/fieldtrip/private/findcluster.m +++ b/external/fieldtrip/private/findcluster.m @@ -27,41 +27,23 @@ % Copyright (C) 2004, Robert Oostenveld % -% $Log: findcluster.m,v $ -% Revision 1.4 2006/06/12 08:22:03 erimar -% Added changes to allow processing with cfg.minnbchan~=0. +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.3 2006/03/21 15:02:42 roboos -% restructured the help, no functional change +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.2 2005/05/17 17:50:49 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.1 2004/11/04 15:30:26 erimar -% Erimar's version of findcluster. Previously, findcluster was part of Roboos' misc. -% -% Revision 1.7 10/27/04 1:13 PM erimar -% allow for the minnbchan option, allow for different matrices for -% selecting and clustering, some variable name changes -% -% Revision 1.6 2004/03/15 17:02:34 roberto -% fixed stupid bug at end of code due to renaming of variable -% -% Revision 1.5 2004/03/10 16:50:15 roberto -% added speed improvements of Eric (which accidentally were NOT in the previous revision) -% updated help, some cosmetical changes -% -% Revision 1.3 2004/02/25 10:34:10 roberto -% implemented smarter handling of real 3d data, improved help -% -% Revision 1.2 2004/02/23 15:41:03 roberto -% added global fb flag to determine amount of online feedback -% fixed bug in checking size of input matrices -% -% Revision 1.1 2004/02/17 14:30:37 roberto -% new efficient implementation to find clusters according to Eric Maris +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: findcluster.m 952 2010-04-21 18:29:51Z roboos $ spatdimlength = size(onoff, 1); nfreq = size(onoff, 2); @@ -81,9 +63,9 @@ end; if minnbchan>0 - % For every (time,frequency)-element, it is calculated how many significant - % neighbours this channel has. If a significant channel has less than minnbchan - % significant neighbours, then this channel is removed from onoff. + % For every (time,frequency)-element, it is calculated how many significant + % neighbours this channel has. If a significant channel has less than minnbchan + % significant neighbours, then this channel is removed from onoff. if length(varargin)==1 selectmat = single(spatdimneighbstructmat | spatdimneighbstructmat'); @@ -92,12 +74,12 @@ selectmat = single(spatdimneighbselmat | spatdimneighbselmat'); end; nremoved=1; - while nremoved>0 - nsigneighb=reshape(selectmat*reshape(single(onoff),[spatdimlength (nfreq*ntime)]),[spatdimlength nfreq ntime]); - remove=(onoff.*nsigneighb)0 + nsigneighb=reshape(selectmat*reshape(single(onoff),[spatdimlength (nfreq*ntime)]),[spatdimlength nfreq ntime]); + remove=(onoff.*nsigneighb). % +% $Id: fitsphere.m 946 2010-04-21 17:51:16Z roboos $ x = pnt(:,1); y = pnt(:,2); diff --git a/external/fieldtrip/private/fixdimord.m b/external/fieldtrip/private/fixdimord.m index 3291893..36c3dba 100644 --- a/external/fieldtrip/private/fixdimord.m +++ b/external/fieldtrip/private/fixdimord.m @@ -1,4 +1,4 @@ -function [data] = fixdimord(data); +function [data] = fixdimord(data, keepsourcedimord); % FIXDIMORD ensures consistency between the dimord string and the axes % that describe the data dimensions. The main purpose of this function @@ -23,46 +23,28 @@ % Copyright (C) 2009, Robert Oostenveld, Jan-Mathijs Schoffelen % -% $Log: fixdimord.m,v $ -% Revision 1.4 2009/10/01 12:23:10 jansch -% added {'pos'} as placeholder +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.3 2009/08/03 15:53:32 ingnie -% fixed bug introduced in last revision, thanks to Esther +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.2 2009/08/03 15:07:51 ingnie -% cut off dimord from source and volume data, dimord is not implemented in source and volume data yet, but some functions do add it which causes unexpected behavior +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.1 2009/07/02 08:04:36 roboos -% moved fixdimord and fixinside from private to public -% -% Revision 1.8 2006/04/12 09:11:23 roboos -% added ; to the end of a line -% -% Revision 1.7 2006/04/10 12:13:52 roboos -% improved documentation, added refchan as dimension -% -% Revision 1.6 2006/03/10 12:34:38 roboos -% ensure that label cell-array is a column -% -% Revision 1.5 2006/02/28 11:22:11 roboos -% changed chancmb into chan -% -% Revision 1.4 2006/02/23 10:28:17 roboos -% changed dimord strings for consistency, changed toi and foi into time and freq, added fixdimord where neccessary -% -% Revision 1.3 2006/02/09 10:06:01 roboos -% do not automatically add all unknown axes, that is too messy and currently not yet desired -% -% Revision 1.2 2006/02/01 12:26:04 roboos -% made all uses of dimord consistent with the common definition of data dimensions, see the fixdimord() function -% -% Revision 1.1 2006/02/01 11:34:32 roboos -% new implementation +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: fixdimord.m 1018 2010-05-03 15:07:06Z jansch $ + +if nargin<2, keepsourcedimord = 0; end if strcmp('volume', datatype(data)) || strcmp('source', datatype(data)); - if isfield(data, 'dimord') + if isfield(data, 'dimord') && ~keepsourcedimord % data should not have a dimord (is not implemented yet, but some % functions add a dimord to these data which leads to unexpected behavior) warning(sprintf('unexpected dimord "%s", dimord is removed from data', data.dimord)); @@ -76,8 +58,8 @@ if ~isfield(data, 'dimord') if ~isfield(data, 'trial') || ~iscell(data.trial) || ... - ~isfield(data, 'time') || ~iscell(data.time) || ... - ~isfield(data, 'label') || ~iscell(data.label) + ~isfield(data, 'time') || ~iscell(data.time) || ... + ~isfield(data, 'label') || ~iscell(data.label) error('The data does not contain a dimord, but it also does not resemble raw data'); elseif isfield(data, 'topo') % the data resembles a component decomposition diff --git a/external/fieldtrip/private/fixdipole.m b/external/fieldtrip/private/fixdipole.m index 8a9de8c..363fd34 100644 --- a/external/fieldtrip/private/fixdipole.m +++ b/external/fieldtrip/private/fixdipole.m @@ -5,10 +5,23 @@ % Copyright (C) 2009, Robert Oostenveld % -% $Log: fixdipole.m,v $ -% Revision 1.1 2009/07/02 15:35:55 roboos -% helper function for consistent dipole representation +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: fixdipole.m 946 2010-04-21 17:51:16Z roboos $ [m, n] = size(dip.pos); diff --git a/external/fieldtrip/private/fixinside.m b/external/fieldtrip/private/fixinside.m index 458cd7b..c7b91d8 100644 --- a/external/fieldtrip/private/fixinside.m +++ b/external/fieldtrip/private/fixinside.m @@ -11,24 +11,23 @@ % Copyright (C) 2006, Robert Oostenveld % -% $Log: fixinside.m,v $ -% Revision 1.2 2009/10/01 12:31:52 jansch -% enforce inside vector to be column +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.1 2009/07/02 08:04:36 roboos -% moved fixdimord and fixinside from private to public +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.3 2007/07/17 10:34:34 roboos -% prevent display of source structure on screen by adding ; +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.2 2007/05/29 16:08:13 ingnie -% also automatic construction of inside from source.dim (with roboos) -% -% Revision 1.1 2006/03/30 12:24:34 roboos -% Implemented private/fixinside, which facilitates consistent -% handling of source/volume data. Improved documentation. Fixed some -% bugs related to inconsistent handling of ROIs (i.e. inside/outside) +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: fixinside.m 952 2010-04-21 18:29:51Z roboos $ if nargin<2 diff --git a/external/fieldtrip/private/fixvolume.m b/external/fieldtrip/private/fixvolume.m deleted file mode 100644 index 8ec093a..0000000 --- a/external/fieldtrip/private/fixvolume.m +++ /dev/null @@ -1,33 +0,0 @@ -function [volume] = fixvolume(volume); - -% FIXVOLUME ensures that a source reconstruction, MRI or statistical -% volume is described using a homogenous transformation matrix and that -% the volumes are reshaped to the right dimension. -% -% Furthermore, if the volume contains a seperate inside and outside -% vector with voxel indices, these are transformed into a single boolean -% inside volume. - -% Copyright (C) 2006, Robert Oostenveld -% -% $Log: fixvolume.m,v $ -% Revision 1.2 2006/04/10 12:14:39 roboos -% use the new function private/fixinside instead of having a local snippet of code -% -% Revision 1.1 2006/02/27 16:55:55 roboos -% new function -% - -% the volume should have a homogenous transformation matrix instead of xgrid/ygrid/zgrid -volume = grid2transform(volume); - -% it should contain a logical ROI with the same dimensions as the volume itself -volume = fixinside(volume, 'logical'); - -% reshape each of the volumes that is found into a 3D array -param = parameterselection('all', volume); -for i=1:length(param) - tmp = getsubfield(volume, param{i}); - tmp = reshape(tmp, volume.dim); - volume = setsubfield(volume, param{i}, tmp); -end diff --git a/external/fieldtrip/private/fourier2crsspctrm.m b/external/fieldtrip/private/fourier2crsspctrm.m index fca44ed..994a5d4 100644 --- a/external/fieldtrip/private/fourier2crsspctrm.m +++ b/external/fieldtrip/private/fourier2crsspctrm.m @@ -19,51 +19,23 @@ % input is taken. % -%$Log: fourier2crsspctrm.m,v $ -%Revision 1.14 2008/11/27 09:04:48 kaigoe -%added default cfg.feedback=text +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -%Revision 1.13 2007/08/31 07:12:57 jansch -%added feedback to be specified by cfg.feedback instead of hardcoded textbar +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -%Revision 1.12 2007/07/31 08:28:36 jansch -%some cosmetic changes +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -%Revision 1.11 2006/06/23 10:49:33 jansch -%added cfg.keepfourier as an option -% -%Revision 1.10 2006/03/22 13:59:18 jansch -%implemented support for tfr-structures containing fourierspectra -% -%Revision 1.9 2006/03/20 11:25:12 jansch -%made changes, to be called from the newly implemented freqdescriptives -% -%Revision 1.8 2006/02/28 12:43:55 roboos -%changed a foi into freq -% -%Revision 1.7 2006/02/23 10:28:17 roboos -%changed dimord strings for consistency, changed toi and foi into time and freq, added fixdimord where neccessary -% -%Revision 1.6 2006/02/01 12:26:04 roboos -%made all uses of dimord consistent with the common definition of data dimensions, see the fixdimord() function -% -%Revision 1.5 2005/08/18 12:17:47 jansch -%added a try-catch in the assignment of the gradiometer-description to the -%output. -% -%Revision 1.4 2005/08/16 07:49:55 jansch -%included the powerspectra in the crsspctrm, removed powspctrm from output -% -%Revision 1.3 2005/08/15 14:46:57 jansch -%fixed small bug in creation of output-structure -% -%Revision 1.2 2005/08/15 10:36:08 jansch -%added version information to the configuration -% -%Revision 1.1 2005/08/15 10:33:19 jansch -%new implementation, to be used as a subfunction for freqdescriptives and -%other stuff +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: fourier2crsspctrm.m 952 2010-04-21 18:29:51Z roboos $ if ~isfield(cfg, 'channel'), cfg.channel = {'all'}; end if ~isfield(cfg, 'channelcmb'), cfg.channelcmb = {}; end @@ -153,7 +125,7 @@ [st, i1] = dbstack; cfg.version.name = st(i1); end -cfg.version.id = '$Id: fourier2crsspctrm.m,v 1.14 2008/11/27 09:04:48 kaigoe Exp $'; +cfg.version.id = '$Id: fourier2crsspctrm.m 952 2010-04-21 18:29:51Z roboos $'; % remember the configuration details of the input data try, cfg.previous = freq.cfg; end % remember the exact configuration details in the output diff --git a/external/fieldtrip/private/freq2cumtapcnt.m b/external/fieldtrip/private/freq2cumtapcnt.m new file mode 100644 index 0000000..2de74a4 --- /dev/null +++ b/external/fieldtrip/private/freq2cumtapcnt.m @@ -0,0 +1,48 @@ +function freq = freq2cumtapcnt(freq,fsample) + +hasrpt = ~isempty(strfind(freq.dimord, 'rpt')); +hastim = ~isempty(strfind(freq.dimord, 'time')); + +if ~hasrpt, + error('computation of number of tapers is not possible, there is not enough information'); +end + +if hastim, + tapsmo = freq.cfg.tapsmofrq; + Nfrq = length(freq.freq); + Nsmp = round(freq.cfg.t_ftimwin.*fsample); + Ntim = length(freq.time); + for j = 1:Nfrq + %number of tapers per frequency + dum = dpss(Nsmp(j),Nsmp(j).*(tapsmo(j)/fsample)); + numtap(j) = size(dum,2) - 1 ; + end + if isfield(freq, 'fourierspctrm') && all(numtap==numtap(1)), + Ntrl = size(freq.fourierspctrm,1)./numtap(1); + else + Ntrl = size(freq.powspctrm,1); + end + cumtapcnt = nan + zeros(Ntrl, Nfrq, Ntim); + for j = 1:Nfrq + for k = 1:Ntim + if isfield(freq, 'fourierspctrm'), + sel = find(~isnan(freq.fourierspctrm(1:numtap(1):end, 1, j, k))); + elseif isfield(freq, 'powspctrm'), + sel = find(~isnan(freq.powspctrm(:, 1, j ,k))); + end + cumtapcnt(sel, j, k) = numtap(j); + end + end + freq.cumtapcnt = cumtapcnt; +else + Nrpt = size(freq.powspctrm,1); + tapsmo = freq.cfg.tapsmofrq; + for j = 1:Nrpt + dum = dpss(freq.cumsumcnt(j),freq.cumsumcnt(j)*(tapsmo/fsample)); + freq.cumtapcnt(j) = size(dum,2) - 1; + end + freq.cumtapcnt = freq.cumtapcnt(:); +end + + + diff --git a/external/fieldtrip/private/freq2timelock.m b/external/fieldtrip/private/freq2timelock.m index 57f377a..877ac37 100644 --- a/external/fieldtrip/private/freq2timelock.m +++ b/external/fieldtrip/private/freq2timelock.m @@ -12,22 +12,23 @@ % Copyright (C) 2005, Robert Oostenveld % -% $Log: freq2timelock.m,v $ -% Revision 1.5 2009/02/02 13:22:27 jansch -% changed 'chancmb' into 'chan' (line 32) +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.4 2006/05/10 08:19:45 roboos -% added dimord to the output +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.3 2006/02/23 10:28:17 roboos -% changed dimord strings for consistency, changed toi and foi into time and freq, added fixdimord where neccessary +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.2 2006/02/01 12:26:04 roboos -% made all uses of dimord consistent with the common definition of data dimensions, see the fixdimord() function -% -% Revision 1.1 2005/10/14 15:50:08 roboos -% new implementation, used by dipolefitting in case of frequency or ICA data +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: freq2timelock.m 952 2010-04-21 18:29:51Z roboos $ if isfield(freq, 'fourierspctrm') fprintf('constructing real/imag data representation from single trial fourier representation\n'); diff --git a/external/fieldtrip/private/freqanalysis.m b/external/fieldtrip/private/freqanalysis.m deleted file mode 100644 index 4280345..0000000 --- a/external/fieldtrip/private/freqanalysis.m +++ /dev/null @@ -1,207 +0,0 @@ -function [freq] = freqanalysis(cfg, data); - -% FREQANALYSIS performs frequency and time-frequency analysis -% on time series data over multiple trials -% -% Use as -% [freq] = freqanalysis(cfg, data) -% -% The input data should be organised in a structure as obtained from -% the PREPROCESSING function. The configuration depends on the type -% of computation that you want to perform. -% -% The configuration should contain: -% cfg.method = different methods of calculating the spectra -% 'mtmfft', analyses an entire spectrum for the entire data -% length, implements multitaper frequency transformation -% 'mtmconvol', implements multitaper time-frequency transformation -% based on multiplication in the frequency domain -% 'mtmwelch', performs frequency analysis using Welch's averaged -% modified periodogram method of spectral estimation -% 'wltconvol', implements wavelet time frequency transformation -% (using Morlet wavelets) based on multiplication in the frequency domain -% 'tfr', implements wavelet time frequency transformation -% (using Morlet wavelets) based on convolution in the time domain -% -% The other cfg options depend on the method that you select. You should -% read the help of the respective subfunction FREQANALYSIS_XXX for the -% corresponding parameter options and for a detailed explanation of each method. -% -% See also FREQANALYSIS_MTMFFT, FREQANALYSIS_MTMCONVOL, FREQANALYSIS_MTMWELCH -% FREQANALYSIS_WLTCONVOL, FREQANALYSIS_TFR - -% Undocumented local options: -% cfg.label -% cfg.labelcmb -% cfg.sgn -% cfg.sgncmb - -% Copyright (C) 2003-2006, F.C. Donders Centre, Pascal Fries -% Copyright (C) 2004-2006, F.C. Donders Centre, Markus Siegel -% -% $Log: freqanalysis.m,v $ -% Revision 1.46 2009/09/30 12:50:16 jansch -% added mvar as a supported datatype -% -% Revision 1.45 2009/07/30 19:44:43 ingnie -% also allow datatype comp (by chekdata) -% -% Revision 1.44 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.43 2009/01/12 13:05:20 sashae -% small change in call to checkconfig -% -% Revision 1.42 2008/09/23 12:30:33 sashae -% checkconfig: checks if the input cfg is valid for this function -% -% Revision 1.41 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.40 2008/05/06 15:43:46 sashae -% change in trial selection, cfg.trials can be logical -% -% Revision 1.39 2008/01/18 13:14:50 sashae -% added option for trial selection, updated documentation -% -% Revision 1.38 2007/11/05 09:48:56 roboos -% removed comments that pertain to the matlab compiler -% -% Revision 1.37 2007/05/29 16:58:06 ingnie -% moved making of offset field to checkdata by adding 'hasoffset' is 'yes' -% -% Revision 1.36 2007/05/02 15:59:13 roboos -% be more strict on the input and output data: It is now the task of -% the private/checkdata function to convert the input data to raw -% data (i.e. as if it were coming straight from preprocessing). -% Furthermore, the output data is NOT converted back any more to the -% input data, i.e. the output data is the same as what it would be -% on raw data as input, regardless of the actual input. -% -% Revision 1.35 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.34 2007/03/30 17:05:40 ingnie -% checkinput; only proceed when input data is allowed datatype -% -% Revision 1.33 2007/03/27 11:05:19 ingnie -% changed call to fixdimord in call to checkinput -% -% Revision 1.32 2006/06/20 16:22:22 ingnie -% removed handling cfg.channel and cfg.channelcmb to freqanalysis_xxx functions -% -% Revision 1.31 2006/06/06 16:57:51 ingnie -% updated documentation -% -% Revision 1.30 2006/05/23 16:05:20 ingnie -% updated documentation -% -% Revision 1.29 2006/05/03 08:12:51 ingnie -% updated documentation -% -% Revision 1.28 2006/04/20 09:58:34 roboos -% updated documentation -% -% Revision 1.27 2006/02/23 10:28:16 roboos -% changed dimord strings for consistency, changed toi and foi into time and freq, added fixdimord where neccessary -% -% Revision 1.26 2005/08/01 12:41:22 roboos -% added some pragma-like comments that help the matlab compiler with the dependencies -% -% Revision 1.25 2005/07/03 20:15:30 roboos -% replaced eval() by feval() for better support by Matlab compiler -% -% Revision 1.24 2005/06/02 12:24:47 roboos -% replaced the local conversion of average into raw trials by a call to the new helper function DATA2RAW -% -% Revision 1.23 2005/05/17 17:50:37 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.22 2005/05/04 07:31:55 roboos -% remove avg after converting to single trial -% -% Revision 1.21 2005/03/08 10:39:50 roboos -% changed ordering: first check for backward compatibility, then set the (new) default -% -% Revision 1.20 2005/01/19 08:39:51 jansch -% added defaults for cfg.channel and cfg.channelcmb, delete cfg.channelcmb if output is not powandcsd -% -% Revision 1.19 2005/01/19 08:05:27 jansch -% fixed small bug in channelcombinations -% -% Revision 1.18 2005/01/18 15:20:38 roboos -% this function now already takes care of channelselection and, if needed, of selection of channelcombinations -% -% Revision 1.17 2005/01/18 15:05:15 roboos -% cleaned up configuration for sgn/label, now consistently using cfg.channel and cfg.channelcmb -% -% Revision 1.16 2004/11/01 11:34:53 roboos -% added support for timelocked trials, i.e. the result of timelockanalysis with keeptrials=yes -% tthese are now converted to raw trials prior to calling the freqanalysis_xxx subfunction -% -% Revision 1.15 2004/10/01 10:23:44 roboos -% fixed error in help for mtmconvol: f_timwin should be t_ftimwin -% -% Revision 1.14 2004/09/28 14:26:43 roboos -% fixed a typo in the help, added a line of comments -% -% Revision 1.13 2004/09/22 10:20:27 roboos -% converted to use external subfunctions time2offset and offset2time -% and add offset field to data structure if it is missing -% -% Revision 1.12 2004/09/21 12:07:28 marsie -% this version of the wrapper implements the new "freqanalysis_METHOD" convention -% for subfunction naming. -% -% Revision 1.11 2004/09/02 11:59:06 roboos -% restructured the help, fixed the copyrights -% -% Revision 1.10 2004/09/01 13:33:03 marsie -% switch to a wrapper function that calls the functions -% multitaperanalysis.m, wltanalysis.m and waveletanalysis.m for the corresponding -% methods -% - -fieldtripdefs - -% check if the input data is valid for this function -data = checkdata(data, 'datatype', {'raw', 'comp', 'mvar'}, 'feedback', 'yes', 'hasoffset', 'yes'); - -% check if the input cfg is valid for this function -cfg = checkconfig(cfg, 'trackconfig', 'on'); -cfg = checkconfig(cfg, 'renamed', {'label', 'channel'}); -cfg = checkconfig(cfg, 'renamed', {'sgn', 'channel'}); -cfg = checkconfig(cfg, 'renamed', {'labelcmb', 'channelcmb'}); -cfg = checkconfig(cfg, 'renamed', {'sgncmb', 'channelcmb'}); -cfg = checkconfig(cfg, 'required', {'method'}); -cfg = checkconfig(cfg, 'renamedval', {'method', 'fft', 'mtmfft'}); -cfg = checkconfig(cfg, 'renamedval', {'method', 'convol', 'mtmconvol'}); - -% select trials of interest -if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end % set the default -if ~strcmp(cfg.trials, 'all') - if islogical(cfg.trials), cfg.trials=find(cfg.trials); end - fprintf('selecting %d trials\n', length(cfg.trials)); - data.trial = data.trial(cfg.trials); - data.time = data.time(cfg.trials); - data.offset = data.offset(cfg.trials); - % update the trial definition (trl) - if isfield(data, 'cfg') - trl = findcfg(data.cfg, 'trl'); - else - trl = []; - end - if isempty(trl) - % a trial definition is expected in each continuous data set - warning('could not locate the trial definition ''trl'' in the data structure'); - else - cfg.trlold=trl; - cfg.trl=trl(cfg.trials,:); - end -end - -% call the corresponding function -[freq] = feval(sprintf('freqanalysis_%s',lower(cfg.method)), cfg, data); diff --git a/external/fieldtrip/private/freqanalysis_mtmconvol.m b/external/fieldtrip/private/freqanalysis_mtmconvol.m deleted file mode 100644 index e4b91c2..0000000 --- a/external/fieldtrip/private/freqanalysis_mtmconvol.m +++ /dev/null @@ -1,617 +0,0 @@ -function [freq] = freqanalysis_mtmconvol(cfg, data); - -% FREQANALYSIS_MTMCONVOL performs time-frequency analysis on any time series trial data -% using the 'multitaper method' (MTM) based on Slepian sequences as tapers. Alternatively, -% you can use conventional tapers (e.g. Hanning). -% -% Use as -% [freq] = freqanalysis(cfg, data) -% -% The data should be organised in a structure as obtained from -% the PREPROCESSING function. The configuration should be according to -% cfg.method = method used for frequency or time-frequency decomposition -% see FREQANALYSIS for details -% cfg.output = 'pow' return the power-spectra -% 'powandcsd' return the power and the cross-spectra -% 'fourier' return the complex Fourier-spectra -% cfg.taper = 'dpss', 'hanning' or many others, see WINDOW (default = 'dpss') -% -% For cfg.output='powandcsd', you should specify the channel combinations -% between which to compute the cross-spectra as cfg.channelcmb. Otherwise -% you should specify only the channels in cfg.channel. -% -% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), -% see CHANNELSELECTION for details -% cfg.channelcmb = Mx2 cell-array with selection of channel pairs (default = {'all' 'all'}), -% see CHANNELCOMBINATION for details -% cfg.foi = vector 1 x numfoi, frequencies of interest -% cfg.t_ftimwin = vector 1 x numfoi, length of time window (in seconds) -% cfg.tapsmofrq = vector 1 x numfoi, the amount of spectral smoothing through -% multi-tapering. Note that 4 Hz smoothing means -% plus-minus 4 Hz, i.e. a 8 Hz smoothing box. -% cfg.toi = vector 1 x numtoi, the times on which the analysis windows -% should be centered (in seconds) -% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') -% cfg.keeptrials = 'yes' or 'no', return individual trials or average (default = 'no') -% cfg.keeptapers = 'yes' or 'no', return individual tapers or average (default = 'no') -% cfg.pad = number or 'maxperlen', length in seconds to which the data can be padded out (default = 'maxperlen') -% -% The padding will determine your spectral resolution. If you want to -% compare spectra from data pieces of different lengths, you should use -% the same cfg.pad for both, in order to spectrally interpolate them to -% the same spectral resolution. Note that this will run very slow if you -% specify cfg.pad as maxperlen AND the number of samples turns out to have -% a large prime factor sum. This is because the FFTs will then be computed -% very inefficiently. -% -% An asymmetric taper usefull for TMS is used when cfg.taper='alpha' and corresponds to -% W. Kyle Mitchell, Mark R. Baker & Stuart N. Baker. Muscle Responses to -% Transcranial Stimulation Depend on Background Oscillatory Activity. -% published online Jul 12, 2007 J. Physiol. -% -% See also FREQANALYSIS - -% undocumented experimental options -% cfg.calcdof = 'yes' calculate the degrees of freedom for every trial - -% Copyright (c) 2003,2004-2006 F.C. Donders Centre -% -% $Log: freqanalysis_mtmconvol.m,v $ -% Revision 1.44 2009/03/11 10:39:37 roboos -% more strict checking of cfg.pad -% -% Revision 1.43 2008/11/11 18:59:26 sashae -% added call to checkconfig at end of function (trackconfig and checksize) -% -% Revision 1.42 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.41 2008/05/13 13:53:22 roboos -% added some documentation on alpha taper, fixed potential bug in assessing number of trials -% -% Revision 1.40 2008/02/28 09:44:30 roboos -% round the number of padded samples to an integer -% -% Revision 1.39 2008/01/18 13:14:50 sashae -% added option for trial selection, updated documentation -% -% Revision 1.38 2007/08/06 15:06:00 roboos -% implemented support for asymmetric alpha tapers -% changed the pre-allocation of some small arrays -% some changes in whitespace and removed some "..." to break up lines -% -% Revision 1.37 2007/03/27 11:00:28 ingnie -% deleted call to fixdimord because this is low level function -% -% Revision 1.36 2007/02/19 09:33:29 jansch -% fixed inappropriate behavour of freq.cumtapcnt in the case of fourierspectra as output -% -% Revision 1.35 2007/02/13 14:17:51 roboos -% made zero padding more memory efficient -% -% Revision 1.34 2006/11/30 07:51:12 jansch -% changed cumtapcnt into dof throughout the code. added cumtapcnt to output -% -% Revision 1.33 2006/10/19 15:32:55 roboos -% updated documentation -% -% Revision 1.32 2006/10/04 07:10:07 roboos -% updated documentation -% -% Revision 1.31 2006/06/20 16:27:52 ingnie -% updated documentation, added consistent handling of cfg.channel and cfg.channelcmb -% -% Revision 1.30 2006/06/13 14:53:21 ingnie -% some change in white space defaults, added default cfg.channel = 'all' -% -% Revision 1.29 2006/06/06 16:57:51 ingnie -% updated documentation -% -% Revision 1.28 2006/05/22 14:47:04 jansch -% fixed a bug in check for different amount of tapers for different frequencies -% -% Revision 1.27 2006/05/03 09:52:22 jansch -% updated error-message when checking for keeptrials and keeptapers in combination -% with fourier as an output -% -% Revision 1.26 2006/03/06 13:53:06 roboos -% pre-allocate sgncmbindx to save many memory allocation and copy operations -% -% Revision 1.25 2006/03/06 09:45:36 roboos -% fixed the callback detection for octave, added sine tapet (thanks to Tom) -% changed some | into || -% -% Revision 1.24 2006/02/28 12:25:09 erimar -% Added the configuration option cfg.calcdof to request for the calculation of the degrees of freedom. -% -% Revision 1.23 2006/02/23 10:28:16 roboos -% changed dimord strings for consistency, changed toi and foi into time and freq, added fixdimord where neccessary -% -% Revision 1.22 2006/02/07 20:08:22 roboos -% changed all occurences of a dimord with chancmb (was previous sgncmb) into chan -% -% Revision 1.21 2006/02/01 12:26:00 roboos -% made all uses of dimord consistent with the common definition of data dimensions, see the fixdimord() function -% -% Revision 1.20 2006/01/30 14:04:21 jansch -% included the option to keep fourier-data. it only works when the number of -% tapers per frequency are equal across frequencies -% -% Revision 1.19 2005/10/13 11:33:36 roboos -% fixed bug in computation of cfg.pad in case of 'maxperlength' (thanks to Floris) -% -% Revision 1.18 2005/09/22 14:29:20 jansch -% correct normalisation for tapers, different than dpss -% -% Revision 1.17 2005/08/23 12:28:36 jansch -% be sure that keeptapers and keeptrials = 'yes' for fourier-output -% -% Revision 1.16 2005/08/19 08:11:45 roboos -% implemented local subfunction that ensures that the input arguments for dpss are double precision -% -% Revision 1.15 2005/08/15 13:30:11 jansch -% changed the normalisation of the single-trial fourierspectra so that it is -% consistent with how it is done for the powerspectra and the cross-spectra. -% -% Revision 1.14 2005/06/29 12:46:29 roboos -% the following changes were done on a large number of files at the same time, not all of them may apply to this specific file -% - added try-catch around the inclusion of input data configuration -% - moved cfg.version, cfg.previous and the assignment of the output cfg to the end -% - changed help comments around the configuration handling -% - some changes in whitespace -% -% Revision 1.13 2005/05/17 17:50:37 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.12 2005/05/04 07:31:36 roboos -% fixed bug in non-dpss taper, had to be transposed -% -% Revision 1.11 2005/02/16 09:21:24 jansch -% inserted the cfg.output-option 'powandfourier'. in addition to outputting -% the powerspectrum, the complex discrete fourier spectrum is returned, -% allowing for computation of phases. -% -% Revision 1.10 2005/01/19 08:42:42 jansch -% removed obsolete code for generating and checking channelcombinations -% cleaned up handling of sgnindx/sgncmbindx -% ensured that power is computed for all channels that are in channelcmb -% -% Revision 1.9 2005/01/18 15:11:38 roboos -% Cleaned up configuration for sgn/sgncmb, now exclusively using channel/channelcmb which is consistent with rest of fieldtrip and freqanalysis documentation. Also the output now only contains freq.label/labelcmb and not any more the old sgn/sgncmb. -% -% Revision 1.8 2005/01/17 14:51:16 roboos -% implemented tapering with single window according to user specification -% (cfg.taper) to allow hanning and other windows to be used easily. -% The default is to multitaper with a dpss sequence. -% -% Revision 1.7 2004/12/20 14:52:56 roboos -% changed rounding off of timboi -% -% Revision 1.6 2004/12/20 14:47:03 roboos -% fixed rounding off error in sample number timboi -% -% Revision 1.5 2004/12/20 13:03:14 jansch -% fixed bug that incorrectly handled missing data as zeros -% -% Revision 1.4 2004/11/18 16:51:58 roboos -% updated the help: pointed to CHANNELCOMBINATION for cfg.channelcmb -% -% Revision 1.3 2004/10/28 09:00:33 roboos -% fixed bug in caller function detection (for matlab 6.1 and 6.5) -% -% Revision 1.2 2004/10/28 07:21:46 roboos -% added check to ensure that the FREQANALYSIS wrapper is started instead of the -% FERQANALYSIS_xxx subfunctions -% -% Revision 1.1 2004/09/21 12:04:02 marsie -% the mtmconvol method of multitaperanalysis.m has been moved to this seperate function -% -% Revision 1.3 2004/09/16 11:40:34 marsie -% fixed bug in 'mtmfft' that slowed computation down w/o causing bad results -% -% Revision 1.2 2004/08/31 14:36:30 marsie -% added support for data segments, which are to short to place a taper -% -% Revision 1.1 2004/08/25 17:38:28 marsie -% initial CVS commit -% this version is based on the original freqanalysis including the following changes -% and improvements: -% - the DFT method is no longer supported -% - methods are renamed with the prefix 'mtm': 'mtmfft' and 'mtmconvol' -% - the last taper returned by 'dpss' is not used -% - the function checks for the consistency of data length and spectral smoothing -% - improved performance by vectorization of loops -% - output of 'mtmfft' is correctly dimensioned for single frequency output -% - -fieldtripdefs - -% ensure that this function is started as a subfunction of the FREQANALYSIS wrapper -if ~exist('OCTAVE_VERSION') - [s, i] = dbstack; - if length(s)>1 - [caller_path, caller_name, caller_ext] = fileparts(s(2).name); - else - caller_path = ''; - caller_name = ''; - caller_ext = ''; - end - % evalin('caller', 'mfilename') does not work for Matlab 6.1 and 6.5 - if ~strcmp(caller_name, 'freqanalysis') - error(['you should call FREQANALYSIS, instead of the ' upper(mfilename) ' subfunction']); - end -end - -% set all the defaults -if ~isfield(cfg, 'method'), cfg.method = 'mtmconvol'; end -if ~isfield(cfg, 'keeptapers'), cfg.keeptapers = 'no'; end -if ~isfield(cfg, 'keeptrials'), cfg.keeptrials = 'no'; end -if ~isfield(cfg, 'calcdof'), cfg.calcdof = 'no'; end -if ~isfield(cfg, 'output'), cfg.output = 'powandcsd'; end -if ~isfield(cfg, 'pad'), cfg.pad = 'maxperlen'; end -if ~isfield(cfg, 'taper'), cfg.taper = 'dpss'; end -if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end -if strcmp(cfg.output, 'fourier'), - cfg.keeptrials = 'yes'; - cfg.keeptapers = 'yes'; -end - -% setting a flag (csdflg) that determines whether this routine outputs -% only power-spectra or power-spectra and cross-spectra? -if strcmp(cfg.output,'pow') - powflg = 1; - csdflg = 0; - fftflg = 0; -elseif strcmp(cfg.output,'powandcsd') - powflg = 1; - csdflg = 1; - fftflg = 0; -elseif strcmp(cfg.output,'fourier') - powflg = 0; - csdflg = 0; - fftflg = 1; -else - error('Unrecognized output required'); -end - -if ~isfield(cfg, 'channelcmb') && csdflg - %set the default for the channelcombination - cfg.channelcmb = {'all' 'all'}; -elseif isfield(cfg, 'channelcmb') && ~csdflg - % no cross-spectrum needs to be computed, hence remove the combinations from cfg - cfg = rmfield(cfg, 'channelcmb'); -end - -% ensure that channelselection and selection of channelcombinations is -% perfomed consistently -cfg.channel = channelselection(cfg.channel, data.label); -if isfield(cfg, 'channelcmb') - cfg.channelcmb = channelcombination(cfg.channelcmb, data.label); -end - -% determine the corresponding indices of all channels -sgnindx = match_str(data.label, cfg.channel); -numsgn = size(sgnindx,1); -if csdflg - % determine the corresponding indices of all channel combinations - sgncmbindx = zeros(size(cfg.channelcmb)); - for k=1:size(cfg.channelcmb,1) - sgncmbindx(k,1) = strmatch(cfg.channelcmb(k,1), data.label, 'exact'); - sgncmbindx(k,2) = strmatch(cfg.channelcmb(k,2), data.label, 'exact'); - end - - numsgncmb = size(sgncmbindx,1); - sgnindx = unique([sgnindx(:); sgncmbindx(:)]); - numsgn = length(sgnindx); - - cutdatindcmb = zeros(size(sgncmbindx)); - for sgnlop = 1:numsgn - cutdatindcmb(find(sgncmbindx == sgnindx(sgnlop))) = sgnlop; - end -end - -% if rectan is 1 it means that trials are of equal lengths -numper = numel(data.trial); -numdatbnsarr = zeros(numper, 1); -for perlop = 1:numper - numdatbnsarr(perlop) = size(data.trial{perlop},2); -end -rectan = all(numdatbnsarr==numdatbnsarr(1)); - -% if cfg.pad is 'maxperlen', this is realized here: -% first establish where the first possible sample is -min_smp = min(data.offset); -% then establish where the last possible sample is -max_smp = max(numdatbnsarr(:)+data.offset(:)); -if isequal(cfg.pad, 'maxperlen') - % pad the data from the first possible to last possible sample - cfg.pad = (max_smp-min_smp) ./ data.fsample; -else - % check that the specified padding is not too short - if cfg.pad<((max_smp-min_smp)/data.fsample) - error('the padding that you specified is shorter than the longest trial in the data'); - end -end - clear min_smp max_smp -numsmp = round(cfg.pad .* data.fsample); - -% keeping trials and/or tapers? -if strcmp(cfg.keeptrials,'no') && strcmp(cfg.keeptapers,'no') - keep = 1; -elseif strcmp(cfg.keeptrials,'yes') && strcmp(cfg.keeptapers,'no') - keep = 2; -elseif strcmp(cfg.keeptrials,'no') && strcmp(cfg.keeptapers,'yes') - error('There is currently no support for keeping tapers WITHOUT KEEPING TRIALS.'); -elseif strcmp(cfg.keeptrials,'yes') && strcmp(cfg.keeptapers,'yes') - keep = 4; -end - -if strcmp(cfg.keeptrials,'yes') && strcmp(cfg.keeptapers,'yes') - if ~strcmp(cfg.output, 'fourier'), - error('Keeping trials AND tapers is only possible with fourier as the output.'); - elseif strcmp(cfg.taper, 'dpss') && ~(all(cfg.tapsmofrq==cfg.tapsmofrq(1)) && all(cfg.t_ftimwin==cfg.t_ftimwin(1))), - error('Currently you can only keep trials AND tapers, when using the number of tapers per frequency is equal across frequency'); - end -end - -if strcmp(cfg.taper, 'alpha') && ~all(cfg.t_ftimwin==cfg.t_ftimwin(1)) - error('you can only use alpha tapers with an cfg.t_ftimwin that is equal for all frequencies'); -end - -minoffset = min(data.offset); -timboi = round(cfg.toi .* data.fsample - minoffset); -toi = round(cfg.toi .* data.fsample) ./ data.fsample; -numtoi = length(cfg.toi); -numfoi = length(cfg.foi); -numtap = zeros(numfoi,1); - -% calculating degrees of freedom -calcdof = strcmp(cfg.calcdof,'yes'); -if calcdof - dof = zeros(numper,numfoi,numtoi); -end; - -% compute the tapers and their fft -knlspctrmstr = cell(numfoi,1); -for foilop = 1:numfoi - acttapnumsmp = round(cfg.t_ftimwin(foilop) .* data.fsample); - if strcmp(cfg.taper, 'dpss') - % create a sequence of DPSS (Slepian) tapers, ensure that the input arguments are double - tap = double_dpss(acttapnumsmp, acttapnumsmp .* (cfg.tapsmofrq(foilop)./data.fsample)); - elseif strcmp(cfg.taper, 'sine') - tap = sine_taper(acttapnumsmp, acttapnumsmp .* (cfg.tapsmofrq(foilop)./data.fsample)); - elseif strcmp(cfg.taper, 'alpha') - tap = alpha_taper(acttapnumsmp, cfg.foi(foilop)./data.fsample); - tap = tap./norm(tap); - % freqanalysis_mtmconvol always throws away the last taper of the Slepian sequence, so add a dummy taper - tap(:,2) = nan; - else - % create a single taper according to the window specification as a replacement for the DPSS (Slepian) sequence - tap = window(cfg.taper, acttapnumsmp); - tap = tap./norm(tap); - % freqanalysis_mtmconvol always throws away the last taper of the Slepian sequence, so add a dummy taper - tap(:,2) = nan; - end - numtap(foilop) = size(tap,2)-1; - if (numtap(foilop) < 1) - error(sprintf('%.3f Hz : datalength to short for specified smoothing\ndatalength: %.3f s, smoothing: %.3f Hz, minimum smoothing: %.3f Hz', cfg.foi(foilop), acttapnumsmp/data.fsample, cfg.tapsmofrq(foilop), data.fsample/acttapnumsmp)); - elseif (numtap(foilop) < 2) && strcmp(cfg.taper, 'dpss') - fprintf('%.3f Hz : WARNING - using only one taper for specified smoothing\n',cfg.foi(foilop)); - end - ins = ceil(numsmp./2) - floor(acttapnumsmp./2); - prezer = zeros(ins,1); - pstzer = zeros(numsmp - ((ins-1) + acttapnumsmp)-1,1); - ind = (0:acttapnumsmp-1)' .* ((2.*pi./data.fsample) .* cfg.foi(foilop)); - knlspctrmstr{foilop} = complex(zeros(numtap(foilop),numsmp)); - for taplop = 1:numtap(foilop) - try - % construct the complex wavelet - coswav = vertcat(prezer,tap(:,taplop).*cos(ind),pstzer); - sinwav = vertcat(prezer,tap(:,taplop).*sin(ind),pstzer); - wavelet = complex(coswav, sinwav); - % store the fft of the complex wavelet - knlspctrmstr{foilop}(taplop,:) = fft(wavelet,[],1)'; - global fb - if ~isempty(fb) && fb - % plot the wavelet for debugging - figure - plot(tap(:,taplop).*cos(ind), 'r'); hold on - plot(tap(:,taplop).*sin(ind), 'g'); - plot(tap(:,taplop) , 'b'); - title(sprintf('taper %d @ %g Hz', taplop, cfg.foi(foilop))); - drawnow - end - end - end -end - -if keep == 1 - if powflg, powspctrm = zeros(numsgn,numfoi,numtoi); end - if csdflg, crsspctrm = complex(zeros(numsgncmb,numfoi,numtoi)); end - if fftflg, fourierspctrm = complex(zeros(numsgn,numfoi,numtoi)); end - cntpertoi = zeros(numfoi,numtoi); - dimord = 'chan_freq_time'; -elseif keep == 2 - if powflg, powspctrm = zeros(numper,numsgn,numfoi,numtoi); end - if csdflg, crsspctrm = complex(zeros(numper,numsgncmb,numfoi,numtoi)); end - if fftflg, fourierspctrm = complex(zeros(numper,numsgn,numfoi,numtoi)); end - dimord = 'rpt_chan_freq_time'; -elseif keep == 4 - % FIXME this works only if all frequencies have the same number of tapers - if powflg, powspctrm = zeros(numper*numtap(1),numsgn,numfoi,numtoi); end - if csdflg, crsspctrm = complex(zeros(numper*numtap(1),numsgncmb,numfoi,numtoi)); end - if fftflg, fourierspctrm = complex(zeros(numper*numtap(1),numsgn,numfoi,numtoi)); end - cnt = 0; - dimord = 'rpttap_chan_freq_time'; -end - -for perlop = 1:numper - fprintf('processing trial %d: %d samples\n', perlop, numdatbnsarr(perlop,1)); - if keep == 2 - cnt = perlop; - end - numdatbns = numdatbnsarr(perlop,1); - % prepad = zeros(1,data.offset(perlop) - minoffset); - % pstpad = zeros(1,minoffset + numsmp - (data.offset(perlop) + numdatbns)); - % datspctra = complex(zeros(numsgn,numsmp)); - % for sgnlop = 1:numsgn - % datspctra(sgnlop,:) = fft([prepad, data.trial{perlop}(sgnindx(sgnlop),:), ... - % pstpad],[],2); - % end - prepad = zeros(numsgn,data.offset(perlop) - minoffset); - pstpad = zeros(numsgn,minoffset + numsmp - (data.offset(perlop) + numdatbns)); - tmp = data.trial{perlop}(sgnindx,:); - tmp = [prepad tmp pstpad]; - % avoid the use of a 3rd input argument to facilitate compatibility with star-P - % use explicit transpose, to avoid complex conjugate transpose - datspctra = transpose(fft(transpose(tmp))); - for foilop = 1:numfoi - fprintf('processing frequency %d (%.2f Hz), %d tapers\n', foilop,cfg.foi(foilop),numtap(foilop)); - actfoinumsmp = cfg.t_ftimwin(foilop) .* data.fsample; - acttimboiind = find(timboi >= (-minoffset + data.offset(perlop) + (actfoinumsmp ./ 2)) & timboi < (-minoffset + data.offset(perlop) + numdatbns - (actfoinumsmp ./2))); - nonacttimboiind = find(timboi < (-minoffset + data.offset(perlop) + (actfoinumsmp ./ 2)) | timboi >= (-minoffset + data.offset(perlop) + numdatbns - (actfoinumsmp ./2))); - acttimboi = timboi(acttimboiind); - numacttimboi = length(acttimboi); - if keep ==1 - cntpertoi(foilop,acttimboiind) = cntpertoi(foilop,acttimboiind) + 1; - end - for taplop = 1:numtap(foilop) - if keep == 3 - cnt = taplop; - elseif keep == 4 - % this once again assumes a fixed number of tapers per frequency - cnt = (perlop-1)*numtap(1) + taplop; - end - autspctrmacttap = complex(zeros(numsgn,numacttimboi), zeros(numsgn,numacttimboi)); - if numacttimboi > 0 - for sgnlop = 1:numsgn - dum = fftshift(ifft(datspctra(sgnlop,:) .* knlspctrmstr{foilop}(taplop,:),[],2)); - autspctrmacttap(sgnlop,:) = dum(acttimboi); - end - end - if powflg - powdum = 2.* abs(autspctrmacttap) .^ 2 ./ actfoinumsmp; - if strcmp(cfg.taper, 'sine') - powdum = powdum .* (1 - (((taplop - 1) ./ numtap(foilop)) .^ 2)); - end - if keep == 1 && numacttimboi > 0 - powspctrm(:,foilop,acttimboiind) = powspctrm(:,foilop,acttimboiind) + reshape(powdum ./ numtap(foilop),[numsgn,1,numacttimboi]); - elseif keep == 2 && numacttimboi > 0 - powspctrm(cnt,:,foilop,acttimboiind) = powspctrm(cnt,:,foilop,acttimboiind) + reshape(powdum ./ numtap(foilop),[1,numsgn,1,numacttimboi]); - powspctrm(cnt,:,foilop,nonacttimboiind) = nan; - elseif keep == 4 && numacttimboi > 0 - powspctrm(cnt,:,foilop,acttimboiind) = reshape(powdum,[1,numsgn,1,numacttimboi]); - powspctrm(cnt,:,foilop,nonacttimboiind) = nan; - elseif (keep == 4 || keep == 2) && numacttimboi == 0 - powspctrm(cnt,:,foilop,nonacttimboiind) = nan; - end - end - if fftflg - fourierdum = (autspctrmacttap) .* sqrt(2 ./ actfoinumsmp); %cf Numercial Receipes 13.4.9 - if keep == 1 && numacttimboi > 0 - fourierspctrm(:,foilop,acttimboiind) = fourierspctrm(:,foilop,acttimboiind) + reshape((fourierdum ./ numtap(foilop)),[numsgn,1,numacttimboi]); - elseif keep == 2 && numacttimboi > 0 - fourierspctrm(cnt,:,foilop,acttimboiind) = fourierspctrm(cnt,:,foilop,acttimboiind) + reshape(fourierdum ./ numtap(foilop),[1,numsgn,1,numacttimboi]); - fourierspctrm(cnt,:,foilop,nonacttimboiind) = nan; - elseif keep == 4 && numacttimboi > 0 - fourierspctrm(cnt,:,foilop,acttimboiind) = reshape(fourierdum,[1,numsgn,1,numacttimboi]); - fourierspctrm(cnt,:,foilop,nonacttimboiind) = nan; - elseif (keep == 4 || keep == 2) && numacttimboi == 0 - fourierspctrm(cnt,:,foilop,nonacttimboiind) = nan; - end - end - if csdflg - csddum = 2.* (autspctrmacttap(cutdatindcmb(:,1),:) .* conj(autspctrmacttap(cutdatindcmb(:,2),:))) ./ actfoinumsmp; - if keep == 1 && numacttimboi > 0 - crsspctrm(:,foilop,acttimboiind) = crsspctrm(:,foilop,acttimboiind) + reshape((csddum ./ numtap(foilop)),[numsgncmb,1,numacttimboi]); - elseif keep == 2 && numacttimboi > 0 - crsspctrm(cnt,:,foilop,acttimboiind) = crsspctrm(cnt,:,foilop,acttimboiind) + reshape(csddum ./ numtap(foilop),[1,numsgncmb,1,numacttimboi]); - crsspctrm(cnt,:,foilop,nonacttimboiind) = nan; - elseif keep == 4 && numacttimboi > 0 - crsspctrm(cnt,:,foilop,acttimboiind) = reshape(csddum,[1,numsgncmb,1,numacttimboi]); - crsspctrm(cnt,:,foilop,nonacttimboiind) = nan; - elseif (keep == 4 || keep == 2) && numacttimboi == 0 - crsspctrm(cnt,:,foilop,nonacttimboiind) = nan; - end - end - end % for taplop - if calcdof - dof(perlop,foilop,acttimboiind) = numtap(foilop); - end - end % for foilop -end % for perlop - -if keep == 1 - warning off - if powflg - powspctrm(:,:,:) = powspctrm(:,:,:) ./ repmat(permute(cntpertoi,[3,1,2]),[numsgn,1,1]); - end - if fftflg - fourierspctrm(:,:,:) = fourierspctrm(:,:,:) ./ repmat(permute(cntpertoi,[3,1,2]),[numsgn,1,1]); - end - if csdflg - crsspctrm(:,:,:) = crsspctrm(:,:,:) ./ repmat(permute(cntpertoi,[3,1,2]),[numsgncmb,1,1]); - end - warning on -end - -% collect the results -freq.label = data.label(sgnindx); -freq.dimord = dimord; -freq.freq = cfg.foi; -freq.time = toi; - -if powflg - freq.powspctrm = powspctrm; -end - -if csdflg - freq.labelcmb = cfg.channelcmb; - freq.crsspctrm = crsspctrm; -end - -if fftflg - freq.fourierspctrm = fourierspctrm; -end - -if calcdof - freq.dof=2*dof; -end; - -if keep == 2, - freq.cumtapcnt = repmat(numtap(:)', [size(powspctrm,1) 1]); -elseif keep == 4, - %all(numtap(1)==numtap) - freq.cumtapcnt = repmat(numtap(1), [size(fourierspctrm,1)./numtap(1) 1]); -end - -try, freq.grad = data.grad; end % remember the gradiometer array -try, freq.elec = data.elec; end % remember the electrode array - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% add information about the version of this function to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i1] = dbstack; - cfg.version.name = st(i1); -end -cfg.version.id = '$Id: freqanalysis_mtmconvol.m,v 1.44 2009/03/11 10:39:37 roboos Exp $'; -% remember the configuration details of the input data -try, cfg.previous = data.cfg; end -% remember the exact configuration details in the output -freq.cfg = cfg; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION ensure that the first two input arguments are of double -% precision this prevents an instability (bug) in the computation of the -% tapers for Matlab 6.5 and 7.0 -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [tap] = double_dpss(a, b, varargin); -tap = dpss(double(a), double(b), varargin{:}); - diff --git a/external/fieldtrip/private/freqanalysis_mtmfft.m b/external/fieldtrip/private/freqanalysis_mtmfft.m deleted file mode 100644 index d073b6a..0000000 --- a/external/fieldtrip/private/freqanalysis_mtmfft.m +++ /dev/null @@ -1,599 +0,0 @@ -function [freq] = freqanalysis_mtmfft(cfg, data); - -% FREQANALYSIS_MTMFFT performs frequency analysis on any time series -% trial data using the 'multitaper method' (MTM) based on discrete -% prolate spheroidal sequences (Slepian sequences) as tapers. Alternatively, -% you can use conventional tapers (e.g. Hanning). -% -% Use as -% [freq] = freqanalysis(cfg, data) -% -% The data should be organised in a structure as obtained from -% the PREPROCESSING function. The configuration should be according to -% cfg.method = method used for frequency or time-frequency decomposition -% see FREQANALYSIS for details -% cfg.output = 'pow' return the power-spectra -% 'powandcsd' return the power and the cross-spectra -% 'fourier' return the complex Fourier-spectra -% cfg.taper = 'dpss', 'hanning' or many others, see WINDOW (default = 'dpss') -% -% For cfg.output='powandcsd', you should specify the channel combinations -% between which to compute the cross-spectra as cfg.channelcmb. Otherwise -% you should specify only the channels in cfg.channel. -% -% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), -% see CHANNELSELECTION for details -% cfg.channelcmb = Mx2 cell-array with selection of channel pairs (default = {'all' 'all'}), -% see CHANNELCOMBINATION for details -% cfg.foilim = [begin end], frequency band of interest -% cfg.tapsmofrq = number, the amount of spectral smoothing through -% multi-tapering. Note that 4 Hz smoothing means -% plus-minus 4 Hz, i.e. a 8 Hz smoothing box. -% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') -% cfg.keeptrials = 'yes' or 'no', return individual trials or average (default = 'no') -% cfg.keeptapers = 'yes' or 'no', return individual tapers or average (default = 'no') -% cfg.pad = number or 'maxperlen', length in seconds to which the data can be padded out (default = 'maxperlen') -% -% The padding will determine your spectral resolution. If you want to -% compare spectra from data pieces of different lengths, you should use -% the same cfg.pad for both, in order to spectrally interpolate them to -% the same spectral resolution. Note that this will run very slow if you -% specify cfg.pad as maxperlen AND the number of samples turns out to have -% a large prime factor sum. This is because the FFTs will then be computed -% very inefficiently. -% -% See also FREQANALYSIS_MTMCONVOL, FREQANALYSIS_WLTCONVOL, FREQANALYSIS_TFR - -% Undocumented local options -% cfg.calcdof = 'yes' calculate the degrees of freedom for every trial - -% Copyright (c) 2003-2006, Pascal Fries, F.C. Donders Centre -% -% $Log: freqanalysis_mtmfft.m,v $ -% Revision 1.45 2009/03/11 10:39:37 roboos -% more strict checking of cfg.pad -% -% Revision 1.44 2008/12/11 15:52:45 roboos -% fixed bug in normalisation of non-dpss tapers in case of non-rectangular data (i.e. data in which the length of the data is different over trials) -% -% Revision 1.43 2008/12/03 14:04:31 roboos -% only give warning about 1 taper for dpss -% -% Revision 1.42 2008/11/11 18:59:26 sashae -% added call to checkconfig at end of function (trackconfig and checksize) -% -% Revision 1.41 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.40 2008/05/13 15:36:09 roboos -% fixed potential bug in assessing the number of trials (when data.trial was column instead of row vector)a, now use numel instead of size -% -% Revision 1.39 2008/01/18 13:14:50 sashae -% added option for trial selection, updated documentation -% -% Revision 1.38 2007/09/23 14:10:09 erimar -% Replaced variable identifier as an argument to "exist" by its -% corresponding string. -% -% Revision 1.37 2007/08/06 15:02:03 roboos -% only changes in whitespace, no functional changes -% -% Revision 1.36 2007/03/27 11:00:28 ingnie -% deleted call to fixdimord because this is low level function -% -% Revision 1.35 2006/10/04 07:10:07 roboos -% updated documentation -% -% Revision 1.34 2006/06/20 16:28:29 ingnie -% added consistent handling of cfg.channel and cfg.channelcmb -% -% Revision 1.33 2006/06/13 14:53:22 ingnie -% some change in white space defaults, added default cfg.channel = 'all' -% -% Revision 1.32 2006/06/06 16:57:51 ingnie -% updated documentation -% -% Revision 1.31 2006/05/04 14:27:00 roboos -% fixed a detail in the documentation -% -% Revision 1.30 2006/05/04 12:56:02 roboos -% updated documentation, removed powandfourier output -% -% Revision 1.29 2006/03/06 13:53:06 roboos -% pre-allocate sgncmbindx to save many memory allocation and copy operations -% -% Revision 1.28 2006/03/06 09:45:36 roboos -% fixed the callback detection for octave, added sine tapet (thanks to Tom) -% changed some | into || -% -% Revision 1.27 2006/02/28 12:23:10 erimar -% Added configuratio option cfg.calcdof to request for the calculation of the degrees of freedom. -% -% Revision 1.26 2006/02/23 10:28:16 roboos -% changed dimord strings for consistency, changed toi and foi into time and freq, added fixdimord where neccessary -% -% Revision 1.25 2006/02/14 08:41:41 roboos -% replaced strmatch with find(strcmp) to speed up the handling of channelcombinations in Octave -% -% Revision 1.24 2006/02/07 20:08:22 roboos -% changed all occurences of a dimord with chancmb (was previous sgncmb) into chan -% -% Revision 1.23 2006/02/01 12:26:00 roboos -% made all uses of dimord consistent with the common definition of data dimensions, see the fixdimord() function -% -% Revision 1.22 2005/09/22 14:29:20 jansch -% correct normalisation for tapers, different than dpss -% -% Revision 1.21 2005/08/23 12:28:36 jansch -% be sure that keeptapers and keeptrials = 'yes' for fourier-output -% -% Revision 1.20 2005/08/20 08:13:47 roboos -% do not try to normalise powspctrm if output=foerier -% -% Revision 1.19 2005/08/19 08:11:45 roboos -% implemented local subfunction that ensures that the input arguments for dpss are double precision -% -% Revision 1.18 2005/08/19 08:10:08 roboos -% changed default output: powandcsd if channelcmb specified, pow otherwise -% -% Revision 1.17 2005/08/16 07:17:11 jansch -% Implemented the undocumented option of outputting the fourierspectrum only. -% Eventually this is intended to replace the 'powandfourier'-option altogether. -% -% Revision 1.16 2005/08/15 13:30:11 jansch -% changed the normalisation of the single-trial fourierspectra so that it is -% consistent with how it is done for the powerspectra and the cross-spectra. -% -% Revision 1.15 2005/08/09 10:15:15 jansch -% implemented pre-allocation of memory in the case of keeptapers. changed the -% cumsumcnt and cumtapcnt in the case of keeptapers. TAKE CARE, this is not -% necessarily backwardcompatible. cumsumcnt and cumtapcnt are now expressed -% in terms of the original number of trials, and not anymore on the total -% number of tapers. -% -% Revision 1.14 2005/06/29 12:46:29 roboos -% the following changes were done on a large number of files at the same time, not all of them may apply to this specific file -% - added try-catch around the inclusion of input data configuration -% - moved cfg.version, cfg.previous and the assignment of the output cfg to the end -% - changed help comments around the configuration handling -% - some changes in whitespace -% -% Revision 1.13 2005/06/09 07:12:14 jansch -% fixed bug in assigning cumtapcnt to output in the case of keeptaper -% -% Revision 1.12 2005/06/08 09:48:28 jansch -% added the tapercounter for the keeptapers-option -% -% Revision 1.11 2005/05/17 17:50:37 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.10 2005/05/10 07:39:33 jansch -% fixed small bug of assignment of number of tapers per trial in the case of -% equal-length trials -% -% Revision 1.9 2005/02/16 08:43:02 jansch -% changed f_t into fourier -% -% Revision 1.8 2005/02/15 11:02:25 jansch -% added the (hidden) option to keep the complex fourier-transform in the output. -% therefore, cfg.output has to be set to 'powandfourier'. this yields, in addition to -% the well-known powspctrm, an fourierspctrm, which can be used to extract the -% phase from the individual trials by using the angle command. -% -% Revision 1.7 2005/01/19 08:42:42 jansch -% removed obsolete code for generating and checking channelcombinations -% cleaned up handling of sgnindx/sgncmbindx -% ensured that power is computed for all channels that are in channelcmb -% -% Revision 1.6 2005/01/18 15:11:39 roboos -% Cleaned up configuration for sgn/sgncmb, now exclusively using channel/channelcmb which is consistent with rest of fieldtrip and freqanalysis documentation. Also the output now only contains freq.label/labelcmb and not any more the old sgn/sgncmb. -% -% Revision 1.5 2005/01/17 14:51:16 roboos -% implemented tapering with single window according to user specification -% (cfg.taper) to allow hanning and other windows to be used easily. -% The default is to multitaper with a dpss sequence. -% -% Revision 1.4 2004/11/18 16:51:58 roboos -% updated the help: pointed to CHANNELCOMBINATION for cfg.channelcmb -% -% Revision 1.3 2004/10/28 09:00:33 roboos -% fixed bug in caller function detection (for matlab 6.1 and 6.5) -% -% Revision 1.2 2004/10/28 07:21:46 roboos -% added check to ensure that the FREQANALYSIS wrapper is started instead of the -% FERQANALYSIS_xxx subfunctions -% -% Revision 1.1 2004/09/21 12:02:04 marsie -% the mtmfft method of multitaperanalysis.m has been moved to this seperate function -% -% Revision 1.3 2004/09/16 11:40:34 marsie -% fixed bug in 'mtmfft' that slowed computation down w/o causing bad results -% -% Revision 1.2 2004/08/31 14:36:30 marsie -% added support for data segments, which are to short to place a taper -% -% Revision 1.1 2004/08/25 17:38:28 marsie -% initial CVS commit -% this version is based on the original freqanalysis including the following changes -% and improvements: -% - the DFT method is no longer supported -% - methods are renamed with the prefix 'mtm': 'mtmfft' and 'mtmconvol' -% - the last taper returned by 'dpss' is not used -% - the function checks for the consistency of data length and spectral smoothing -% - improved performance by vectorization of loops -% - output of 'mtmfft' is correctly dimensioned for single frequency output -% - -fieldtripdefs - -% ensure that this function is started as a subfunction of the FREQANALYSIS wrapper -if ~exist('OCTAVE_VERSION') - [s, i] = dbstack; - if length(s)>1 - [caller_path, caller_name, caller_ext] = fileparts(s(2).name); - else - caller_path = ''; - caller_name = ''; - caller_ext = ''; - end - % evalin('caller', 'mfilename') does not work for Matlab 6.1 and 6.5 - if ~strcmp(caller_name, 'freqanalysis') - error(['you should call FREQANALYSIS, instead of the ' upper(mfilename) ' subfunction']); - end -end - -% set all the defaults -if ~isfield(cfg, 'method'), cfg.method = 'mtmfft'; end -if ~isfield(cfg, 'keeptapers'), cfg.keeptapers = 'no'; end -if ~isfield(cfg, 'keeptrials'), cfg.keeptrials = 'no'; end -if ~isfield(cfg, 'calcdof'), cfg.calcdof = 'no'; end -if ~isfield(cfg, 'pad'), cfg.pad = 'maxperlen'; end -if ~isfield(cfg, 'taper'), cfg.taper = 'dpss'; end -if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end -if ~isfield(cfg, 'foilim'), cfg.foilim = [0 data.fsample/2]; end -if ~isfield(cfg, 'output'), - if isfield(cfg, 'channelcmb') && ~isempty(cfg.channelcmb) - cfg.output = 'powandcsd'; - else - cfg.output = 'pow'; - end -end - -if strcmp(cfg.output, 'fourier'), - cfg.keeptrials = 'yes'; - cfg.keeptapers = 'yes'; -end - -if ~strcmp(cfg.method,'mtmfft') - error('unsupported method'); -end - -% setting a flag (csdflg) that determines whether this routine outputs -% only power-spectra or power-spectra and cross-spectra? -if strcmp(cfg.output,'pow') - powflg = 1; - csdflg = 0; - fftflg = 0; -elseif strcmp(cfg.output,'powandcsd') - powflg = 1; - csdflg = 1; - fftflg = 0; -elseif strcmp(cfg.output,'fourier') - powflg = 0; - csdflg = 0; - fftflg = 1; -else - error('unsupported value for cfg.method'); -end - -if ~isfield(cfg, 'channelcmb') && csdflg - %set the default for the channelcombination - cfg.channelcmb = {'all' 'all'}; -elseif isfield(cfg, 'channelcmb') && ~csdflg - % no cross-spectrum needs to be computed, hence remove the combinations from cfg - cfg = rmfield(cfg, 'channelcmb'); -end - -% ensure that channelselection and selection of channelcombinations is -% perfomed consistently -cfg.channel = channelselection(cfg.channel, data.label); -if isfield(cfg, 'channelcmb') - cfg.channelcmb = channelcombination(cfg.channelcmb, data.label); -end - -% determine the corresponding indices of all channels -sgnindx = match_str(data.label, cfg.channel); -numsgn = size(sgnindx,1); -if csdflg - % determine the corresponding indices of all channel combinations - sgncmbindx = zeros(size(cfg.channelcmb)); - for k=1:size(cfg.channelcmb,1) - sgncmbindx(k,1) = find(strcmp(cfg.channelcmb(k,1), data.label)); - sgncmbindx(k,2) = find(strcmp(cfg.channelcmb(k,2), data.label)); - % this works the same, but is much slower in Octave - % sgncmbindx(k,1) = strmatch(cfg.channelcmb(k,1), data.label, 'exact'); - % sgncmbindx(k,2) = strmatch(cfg.channelcmb(k,2), data.label, 'exact'); - end - - numsgncmb = size(sgncmbindx,1); - sgnindx = unique([sgnindx(:); sgncmbindx(:)]); - numsgn = length(sgnindx); - - cutdatindcmb = zeros(size(sgncmbindx)); - for sgnlop = 1:numsgn - cutdatindcmb(find(sgncmbindx == sgnindx(sgnlop))) = sgnlop; - end -end - -% if rectan is 1 it means that trials are of equal lengths -numper = numel(data.trial); -rectan = 1; -for perlop = 1:numper - numdatbnsarr(perlop,1) = size(data.trial{perlop},2); -end -rectan = all(numdatbnsarr==numdatbnsarr(1)); - -% if cfg.pad is 'maxperlen', this is realized here: -if isequal(cfg.pad, 'maxperlen') - cfg.pad = max(numdatbnsarr,[],1) ./ data.fsample; -else - % check that the specified padding is not too short - if cfg.pad<(max(numdatbnsarr,[],1)/data.fsample) - error('the padding that you specified is shorter than the longest trial in the data'); - end -end -numsmp = ceil(cfg.pad .* data.fsample); % this used to be "cfg.pad .* data.fsample" - -% keeping trials and/or tapers? -if strcmp(cfg.keeptrials,'no') && strcmp(cfg.keeptapers,'no') - keep = 1; -elseif strcmp(cfg.keeptrials,'yes') && strcmp(cfg.keeptapers,'no') - keep = 2; -elseif strcmp(cfg.keeptrials,'no') && strcmp(cfg.keeptapers,'yes') - error('There is no support for keeping tapers WITHOUT KEEPING TRIALS.'); -elseif strcmp(cfg.keeptrials,'yes') && strcmp(cfg.keeptapers,'yes') - keep = 4; -end - -% calculating degrees of freedom -calcdof = strcmp(cfg.calcdof,'yes'); - -% doing the computation -boilim = round(cfg.foilim ./ (data.fsample ./ numsmp)) + 1; -boi = boilim(1):boilim(2); -numboi = size(boi,2); -foi = (boi-1) ./ cfg.pad; - -if keep == 1 - if powflg, powspctrm = zeros(numsgn,numboi); end - if csdflg, crsspctrm = complex(zeros(numsgncmb,numboi)); end - if fftflg, fourierspctrm = complex(zeros(numsgn,numboi)); end - dimord = 'chan_freq'; -elseif keep == 2 - if powflg, powspctrm = zeros(numper,numsgn,numboi); end - if csdflg, crsspctrm = complex(zeros(numper,numsgncmb,numboi)); end - if fftflg, fourierspctrm = complex(zeros(numper,numsgn,numboi)); end - dimord = 'rpt_chan_freq'; -elseif keep == 4 - if rectan == 1, % compute the amount of memory needed to collect the results - numdatbns = numdatbnsarr(1,1); - if strcmp(cfg.taper, 'dpss'), - % ensure that the input arguments are double precision - tap = double_dpss(numdatbns, numdatbns*(cfg.tapsmofrq./data.fsample))'; - elseif strcmp(cfg.taper, 'sine') - tap = sine_taper(numdatbns, numdatbns*(cfg.tapsmofrq./data.fsample))'; - else - tap(2,:) = nan; - end - numtap = size(tap,1)-1; - numrpt = numtap.*numper; - elseif rectan == 0, - numrpt = 0; - for perlop = 1:numper - numdatbns = numdatbnsarr(perlop,1); - if strcmp(cfg.taper, 'dpss'), - % ensure that the input arguments are double precision - tap = double_dpss(numdatbns, numdatbns*(cfg.tapsmofrq./data.fsample))'; - elseif strcmp(cfg.taper, 'sine') - tap = sine_taper(numdatbns, numdatbns*(cfg.tapsmofrq./data.fsample))'; - else - tap(2,:) = nan; - end - numtap = size(tap,1)-1; - numrpt = numrpt + numtap; - end - end - if powflg, powspctrm = zeros(numrpt,numsgn,numboi); end - if csdflg, crsspctrm = complex(zeros(numrpt,numsgncmb,numboi)); end - if fftflg, fourierspctrm = complex(zeros(numrpt,numsgn,numboi)); end - cnt = 0; - dimord = 'rpttap_chan_freq'; -end - -% these count the number of tapers -cumsumcnt = zeros(numper,1); -cumtapcnt = zeros(numper,1); - -if rectan == 1 - % trials are of equal length, compute the set of tapers only once - numdatbns = numdatbnsarr(1,1); - if strcmp(cfg.taper, 'dpss') - % create a sequence of DPSS (Slepian) tapers - % ensure that the input arguments are double precision - tap = double_dpss(numdatbns,numdatbns*(cfg.tapsmofrq./data.fsample))'; - elseif strcmp(cfg.taper, 'sine') - tap = sine_taper(numdatbns, numdatbns*(cfg.tapsmofrq./data.fsample))'; - else - % create a single taper according to the window specification as a - % replacement for the DPSS (Slepian) sequence - tap = window(cfg.taper, numdatbns)'; - tap = tap./norm(tap); - % freqanalysis_mtmfft always throws away the last taper of the Slepian sequence, so add a dummy taper - tap(2,:) = nan; - end - numtap = size(tap,1) - 1; - if keep == 2 || calcdof - cumtapcnt(:) = numtap; - end - if (numtap < 1) - error(sprintf(... - 'datalength to short for specified smoothing\ndatalength: %.3f s, smoothing: %.3f Hz, minimum smoothing: %.3f Hz',... - numdatbns/data.fsample, cfg.tapsmofrq, data.fsample/numdatbns)); - elseif (numtap < 2) && strcmp(cfg.taper, 'dpss') - fprintf('WARNING: using only one taper for specified smoothing\n'); - end - pad = zeros(1,numsmp - numdatbns); -end - -for perlop = 1:numper - fprintf('processing trial %d, ', perlop); - if keep == 2 - cnt = perlop; - cumsumcnt(cnt,1) = numdatbnsarr(perlop,1); - end - if rectan == 0 - % trials are not of equal length, compute the set of tapers for this trial - numdatbns = numdatbnsarr(perlop,1); - if strcmp(cfg.taper, 'dpss') - % create a sequence of DPSS (Slepian) tapers - % ensure that the input arguments are double precision - tap = double_dpss(numdatbns,numdatbns*(cfg.tapsmofrq./data.fsample))'; - elseif strcmp(cfg.taper, 'sine') - tap = sine_taper(numdatbns, numdatbns*(cfg.tapsmofrq./data.fsample))'; - else - % create a single taper according to the window specification as a - % replacement for the DPSS (Slepian) sequence - tap = window(cfg.taper, numdatbns)'; - tap = tap./norm(tap); - % freqanalysis_mtmfft always throws away the last taper of the Slepian sequence, so add a dummy taper - tap(2,:) = nan; - end - numtap = size(tap,1) - 1; - if keep == 2 || calcdof - cnt = perlop; - cumtapcnt(cnt,1) = numtap; - end - if (numtap < 1) - error(sprintf(... - 'datalength to short for specified smoothing\ndatalength: %.3f s, smoothing: %.3f Hz, minimum smoothing: %.3f Hz',... - numdatbns/data.fsample, cfg.tapsmofrq, data.fsample/numdatbns)); - elseif (numtap < 2) && strcmp(cfg.taper, 'dpss') - fprintf('WARNING: using only one taper for specified smoothing\n'); - end - pad = zeros(1,numsmp - numdatbns); - end - for taplop = 1:numtap - if keep == 4 - cnt = cnt+1; - cumsumcnt(perlop,1) = numdatbnsarr(perlop,1); - cumtapcnt(perlop,1) = numtap; - end - if calcdof - cumtapcnt(perlop,1) = numtap; - end - - autspctrmacttap = complex(zeros(numsgn,numboi)); - for sgnlop = 1:numsgn - dum = fft([data.trial{perlop}(sgnindx(sgnlop),:) .* tap(taplop,:) , ... - pad],[],2); - autspctrmacttap(sgnlop,:) = dum(boi); - end - if taplop == 1 - fprintf('nfft: %d samples, taper length: %d samples, %d tapers\n',length(dum),size(tap,2),numtap); - end - if powflg - powdum = 2 .* (autspctrmacttap .* conj(autspctrmacttap)) ./ numsmp; %cf Numercial Receipes 13.4.9 - if keep == 1 - powspctrm(:,:) = powspctrm(:,:) + (powdum ./ numtap); - elseif keep == 2 - powspctrm(cnt,:,:) = powspctrm(cnt,:,:) + (permute(powdum,[3,1,2]) ./ numtap); - elseif keep == 4 - powspctrm(cnt,:,:) = powdum; - end - end - if fftflg - fourierdum = (autspctrmacttap) .* sqrt(2 ./ numsmp); %cf Numercial Receipes 13.4.9 - if keep == 1 - fourierspctrm(:,:) = fourierspctrm(:,:) + (fourierdum ./ numtap); - elseif keep == 2 - fourierspctrm(cnt,:,:) = fourierspctrm(cnt,:,:) + (permute(fourierdum,[3,1,2]) ./ numtap); - elseif keep == 4 - fourierspctrm(cnt,:,:) = fourierdum; - end - end - if csdflg - csddum = 2.* (autspctrmacttap(cutdatindcmb(:,1),:) .* ... - conj(autspctrmacttap(cutdatindcmb(:,2),:))) ./ numsmp; - if keep == 1 - crsspctrm(:,:) = crsspctrm(:,:) + csddum ./ numtap; - elseif keep == 2 - crsspctrm(cnt,:,:) = crsspctrm(cnt,:,:) + permute(csddum,[3,1,2]) ./ numtap; - elseif keep == 4 - crsspctrm(cnt,:,:) = csddum; - end - end - end % taplop -end % perlop -if keep ==1 - if powflg, powspctrm = powspctrm ./ numper; end - if csdflg, crsspctrm = crsspctrm ./ numper; end -end - -% collect the results -freq.label = data.label(sgnindx); -freq.dimord = dimord; -freq.freq = foi; -if powflg - freq.powspctrm = powspctrm; -end -if fftflg - freq.fourierspctrm = fourierspctrm; -end - -if csdflg - freq.labelcmb = cfg.channelcmb; - freq.crsspctrm = crsspctrm; -end - -if strcmp(cfg.method,'mtmfft') && (keep == 2 || keep == 4) - freq.cumsumcnt = cumsumcnt; -end - -if strcmp(cfg.method,'mtmfft') && (keep == 2 || keep == 4) - freq.cumtapcnt = cumtapcnt; -end - -if calcdof - freq.dof=2*repmat(cumtapcnt,[1,numboi]); -end; - -try, freq.grad = data.grad; end % remember the gradiometer array -try, freq.elec = data.elec; end % remember the electrode array - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% add information about the version of this function to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i1] = dbstack; - cfg.version.name = st(i1); -end -cfg.version.id = '$Id: freqanalysis_mtmfft.m,v 1.45 2009/03/11 10:39:37 roboos Exp $'; -% remember the configuration details of the input data -try, cfg.previous = data.cfg; end -% remember the exact configuration details in the output -freq.cfg = cfg; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION ensure that the first two input arguments are of double -% precision this prevents an instability (bug) in the computation of the -% tapers for Matlab 6.5 and 7.0 -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [tap] = double_dpss(a, b, varargin); -tap = dpss(double(a), double(b), varargin{:}); - diff --git a/external/fieldtrip/private/freqanalysis_mtmwelch.m b/external/fieldtrip/private/freqanalysis_mtmwelch.m deleted file mode 100644 index e4460b8..0000000 --- a/external/fieldtrip/private/freqanalysis_mtmwelch.m +++ /dev/null @@ -1,147 +0,0 @@ -function [freq] = freqanalysis_mtmwelch(cfg, data); - -% FREQANALYSIS_MTMWELCH performs frequency analysis on any time series -% trial data using the 'multitaper method' (MTM) based on discrete -% prolate spheroidal sequences (Slepian sequences) as tapers. Alternatively, -% you can use conventional tapers (e.g. Hanning). -% -% Besides multitapering, this function uses Welch's averaged, modified -% periodogram method. The data is divided into a number of sections with -% overlap, each section is windowed with the specified taper(s) and the -% powerspectra are computed and averaged over the sections in each trial. -% -% Use as -% [freq] = freqanalysis(cfg, data) -% -% The data should be organised in a structure as obtained from -% the PREPROCESSING function. The configuration should be according to -% cfg.method = method used for frequency or time-frequency decomposition -% see FREQANALYSIS for details -% cfg.output = 'pow' return the power-spectra -% 'powandcsd' return the power and the cross-spectra -% cfg.taper = 'dpss', 'hanning' or many others, see WINDOW (default = 'dpss') -% -% For cfg.output='powandcsd', you should specify the channel combinations -% between which to compute the cross-spectra as cfg.channelcmb. Otherwise -% you should specify only the channels in cfg.channel. -% -% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), -% see CHANNELSELECTION for details -% cfg.channelcmb = Mx2 cell-array with selection of channel pairs (default = {'all' 'all'}), -% see CHANNELCOMBINATION for details -% -% This function uses FREQANALYSIS_MTMCONVOL for the low-level -% computations, and you can use the options of that function to specify -% the length of the time windows, the amount of overlap, and the amount -% of spectral smoothing (in case of dpss tapers) per window. -% -% cfg.foi = vector 1 x numfoi, frequencies of interest -% cfg.t_ftimwin = vector 1 x numfoi, length of time window (in seconds) -% cfg.tapsmofrq = vector 1 x numfoi, the amount of spectral smoothing through -% multi-tapering. Note that 4 Hz smoothing means -% plus-minus 4 Hz, i.e. a 8 Hz smoothing box. -% cfg.toi = vector 1 x numtoi, the times on which the analysis windows -% should be centered (in seconds) -% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') -% cfg.keeptrials = 'yes' or 'no', return individual trials or average (default = 'no') -% cfg.keeptapers = 'yes' or 'no', return individual tapers or average (default = 'no') -% cfg.pad = number or 'maxperlen', length in seconds to which the data can be padded out (default = 'maxperlen') -% -% See also FREQANALYSIS_MTMCONVOL, FREQANALYSIS - -% This function depends on FREQANALYSIS which uses cfg.method = 'mtmconvol' - -% Copyright (C) 2005-2006, F.C. Donders Centre -% -% $Log: freqanalysis_mtmwelch.m,v $ -% Revision 1.12 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.11 2008/01/18 13:14:50 sashae -% added option for trial selection, updated documentation -% -% Revision 1.10 2006/10/04 07:10:07 roboos -% updated documentation -% -% Revision 1.9 2006/06/20 16:25:58 ingnie -% updated documentation -% -% Revision 1.8 2006/06/06 16:57:51 ingnie -% updated documentation -% -% Revision 1.7 2006/05/23 16:05:20 ingnie -% updated documentation -% -% Revision 1.6 2006/05/04 14:26:35 roboos -% added some real documentation -% -% Revision 1.5 2006/03/14 08:09:22 roboos -% added copyrigth and cvs log statement -% - -fieldtripdefs - -% ensure that this function is started as a subfunction of the FREQANALYSIS wrapper -if ~exist('OCTAVE_VERSION') - [s, i] = dbstack; - if length(s)>1 - [caller_path, caller_name, caller_ext] = fileparts(s(2).name); - else - caller_path = ''; - caller_name = ''; - caller_ext = ''; - end - % evalin('caller', 'mfilename') does not work for Matlab 6.1 and 6.5 - if ~strcmp(caller_name, 'freqanalysis') - error(['you should call FREQANALYSIS, instead of the ' upper(mfilename) ' subfunction']); - end -end - -tmin = inf; -tmax = -inf; -for i=1:length(data.time) - tmin = min(tmin, data.time{i}(1)); - tmax = max(tmax, data.time{i}(end)); -end - -fprintf('taking every sample as time of interest\n'); - -cfgconvol = cfg; -cfgconvol.method = 'mtmconvol'; -cfgconvol.toi = tmin:(1/data.fsample):tmax; -cfgconvol.trials = 'all'; % trial selection already applied during first call of freqanalysis - -% use mtmconvol to do the dirty work -freq = freqanalysis(cfgconvol, data); - -% determine the time dimension -if strcmp(freq.dimord, 'chan_freq_time') - timedim = 3; -elseif strcmp(freq.dimord, 'rpt_chan_freq_time') - timedim = 4; -else - error('unexpected dimord'); -end - -% average over time -% NOTE: the degrees of freedom should be returned by freqanalysis_mtmconvol, -% and used here to weigh every trial and timepoint accordingly. But -% currently that is not yet possible. -freq.powspctrm = nan_mean(freq.powspctrm, timedim); -if isfield(freq, 'crsspctrm') - freq.crsspctrm = nan_mean(freq.crsspctrm, timedim); -end - -% remove the time axis -freq = rmfield(freq, 'time'); - -% update the dimord -if strcmp(freq.dimord, 'chan_freq_time') - freq.dimord = 'chan_freq'; -elseif strcmp(freq.dimord, 'rpt_chan_freq_time') - freq.dimord = 'rpt_chan_freq'; -end - -% only update the method and trials fields -freq.cfg.method = cfg.method; -freq.cfg.trials = cfg.trials; diff --git a/external/fieldtrip/private/freqanalysis_tfr.m b/external/fieldtrip/private/freqanalysis_tfr.m deleted file mode 100644 index 0fbbe89..0000000 --- a/external/fieldtrip/private/freqanalysis_tfr.m +++ /dev/null @@ -1,321 +0,0 @@ -function [freq] = freqanalysis_tfr(cfg, data); - -% FREQANALYSIS_TFR computes time-frequency representations of single-trial -% data using a convolution in the time-domain with Morlet's wavelets. -% -% Use as -% [freq] = freqanalysis(cfg, data) -% -% The data should be organised in a structure as obtained from -% the PREPROCESSING function. The configuration should be according to -% cfg.method = method used for frequency or time-frequency decomposition -% see FREQANALYSIS for details -% cfg.foi = vector 1 x numfoi, frequencies of interest -% cfg.waveletwidth = 'width' of wavelets expressed in cycles (default = 7) -% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), -% see CHANNELSELECTION for details -% cfg.downsample = ratio for downsampling, which occurs after convolution (default = 1) -% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') -% cfg.keeptrials = 'yes' or 'no', return individual trials or average (default = 'no') -% -% See also FREQANALYSIS - -% Undocumented local options: -% cfg.latency -% cfg.output - -% Copyright (C) 2003, Ole Jensen, FCDC -% -% $Log: freqanalysis_tfr.m,v $ -% Revision 1.23 2009/02/16 20:30:44 jansch -% changed inconsistent normalization of power. initially, normalization was -% (2./data.fsample).^2. in other freqanalysis_xxx functions, this normalization -% is (2./data.fsample) -% -% Revision 1.22 2008/11/11 18:59:26 sashae -% added call to checkconfig at end of function (trackconfig and checksize) -% -% Revision 1.21 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.20 2008/01/18 13:14:50 sashae -% added option for trial selection, updated documentation -% -% Revision 1.19 2007/03/27 11:00:28 ingnie -% deleted call to fixdimord because this is low level function -% -% Revision 1.18 2006/10/04 07:10:07 roboos -% updated documentation -% -% Revision 1.17 2006/06/06 16:55:45 ingnie -% updated documentation, deleted default cfg.foi -% -% Revision 1.16 2006/05/03 08:12:51 ingnie -% updated documentation -% -% Revision 1.15 2006/04/20 09:58:34 roboos -% updated documentation -% -% Revision 1.14 2006/03/29 08:44:28 roboos -% added support for keeptrials, added check for call from -% freqanalysis-wrapper, changed default feedback, cleaned up help, -% autoindented code (spaces/tabs). -% -% Revision 1.13 2006/02/23 10:28:16 roboos -% changed dimord strings for consistency, changed toi and foi into time and freq, added fixdimord where neccessary -% -% Revision 1.12 2006/02/07 20:08:22 roboos -% changed all occurences of a dimord with chancmb (was previous sgncmb) into chan -% -% Revision 1.11 2006/02/07 08:12:19 roboos -% changed fprintf into progress indicator, added cfg.feedback -% -% Revision 1.10 2006/02/01 12:26:00 roboos -% made all uses of dimord consistent with the common definition of data dimensions, see the fixdimord() function -% -% Revision 1.9 2005/08/05 09:14:03 roboos -% replaced computation of trialtime by the time axis that is present in the data -% added warning to use RESAMPLEDATA is cfg.downsample is used -% -% Revision 1.8 2005/06/29 12:46:29 roboos -% the following changes were done on a large number of files at the same time, not all of them may apply to this specific file -% - added try-catch around the inclusion of input data configuration -% - moved cfg.version, cfg.previous and the assignment of the output cfg to the end -% - changed help comments around the configuration handling -% - some changes in whitespace -% -% Revision 1.7 2005/05/17 17:50:37 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.6 2005/01/19 08:40:40 jansch -% added check and error message if output=powandcsd -% -% Revision 1.5 2005/01/18 15:11:39 roboos -% Cleaned up configuration for sgn/sgncmb, now exclusively using channel/channelcmb which is consistent with rest of fieldtrip and freqanalysis documentation. Also the output now only contains freq.label/labelcmb and not any more the old sgn/sgncmb. -% -% Revision 1.4 2004/11/01 11:33:37 roboos -% replaced obbsolete translate_channel_list by channelselection -% -% Revision 1.3 2004/10/28 09:00:33 roboos -% fixed bug in caller function detection (for matlab 6.1 and 6.5) -% -% Revision 1.2 2004/10/28 07:21:46 roboos -% added check to ensure that the FREQANALYSIS wrapper is started instead of the -% FERQANALYSIS_xxx subfunctions -% -% Revision 1.1 2004/09/21 12:05:26 marsie -% the tfr method of waveletanalysis.m has been moved to this seperate function -% -% Revision 1.5 2004/08/16 13:31:58 roboos -% added a ";" at the end of the line -% -% Revision 1.4 2004/07/01 11:57:44 olejen -% Error in dimord corrected -% -% Revision 1.3 2004/06/30 11:44:48 roboos -% added CVS Log feature and copyright statement, no code changes -% (note: the previous change from revision 1.1 to 1.2 only affected -% documentation and comments, and also did not include any change to -% the functionality of the code) - -fieldtripdefs - -% ensure that this function is started as a subfunction of the FREQANALYSIS wrapper -if ~exist('OCTAVE_VERSION') - [s, i] = dbstack; - if length(s)>1 - [caller_path, caller_name, caller_ext] = fileparts(s(2).name); - else - caller_path = ''; - caller_name = ''; - caller_ext = ''; - end - % evalin('caller', 'mfilename') does not work for Matlab 6.1 and 6.5 - if ~strcmp(caller_name, 'freqanalysis') - error(['you should call FREQANALYSIS, instead of the ' upper(mfilename) ' subfunction']); - end -end - -% set the defaults -if ~isfield(cfg, 'method'), cfg.method = 'tfr'; end -if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end -if ~isfield(cfg, 'latency'), cfg.latency = 'minperlength'; end -if ~isfield(cfg, 'keeptrials'), cfg.keeptrials = 'no'; end -if ~isfield(cfg, 'waveletwidth'), cfg.waveletwidth = 7; end -if ~isfield(cfg, 'downsample'), cfg.downsample = 1; end -if ~isfield(cfg, 'feedback'), cfg.feedback = 'text'; end - -if isfield(cfg, 'output') && strcmp(cfg.output, 'powandcsd'), - error('This function does not compute cross-spectra\n'); -end - -% determine the channels of interest -cfg.channel = channelselection(cfg.channel, data.label); -chansel = match_str(data.label, cfg.channel); - -% determine the duration of each trial -ntrial = length(data.trial); -nchan = size(data.trial{1}, 1); - -for i=1:ntrial - nsampl(i) = size(data.trial{i}, 2); - begsamplatency(i) = min(data.time{i}); - endsamplatency(i) = max(data.time{i}); -end; - -if cfg.downsample > 1 - % perform a decimation of the input data - warning('decimating the input data, better is to use RESAMPLEDATA'); - for k=1:ntrial - dTmp = data.trial{k}; - data.trial{k} = dTmp(:,1:cfg.downsample:end); - tTmp = data.time{k}; - data.time{k} = tTmp(1:cfg.downsample:end); - end - data.fsample = data.fsample / cfg.downsample; -end - -% automatically determine the latency window which is possible in all trials -minperlength = [max(begsamplatency) min(endsamplatency)]; - -% latency window for averaging and variance computation is given in seconds -if (strcmp(cfg.latency, 'minperlength')) - cfg.latency = []; - cfg.latency(1) = minperlength(1); - cfg.latency(2) = minperlength(2); -end -if (strcmp(cfg.latency, 'prestim')) - cfg.latency = []; - cfg.latency(1) = minperlength(1); - cfg.latency(2) = 0; -end -if (strcmp(cfg.latency, 'poststim')) - cfg.latency = []; - cfg.latency(1) = 0; - cfg.latency(2) = minperlength(2); -end - -M = waveletfam(cfg.foi,data.fsample,cfg.waveletwidth); - -progress('init', cfg.feedback, 'convolving wavelets'); - -for i=1:ntrial - indicvect = data.time{i}; - progress(i/ntrial, 'convolving wavelets, trial %d of %d\n', i, ntrial); - - %for average and variance - begsampl = nearest(indicvect,cfg.latency(1)); - endsampl = nearest(indicvect,cfg.latency(2)); - - numsamples(i) = endsampl-begsampl+1; - - if (i==1) - % allocate memory to hold the resulting powerspectra - if strcmp(cfg.keeptrials, 'yes') - freq.powspctrm = zeros(ntrial,nchan,length(cfg.foi),ceil((endsampl-begsampl+1)/cfg.downsample)); - else - freq.powspctrm = zeros(nchan,length(cfg.foi),ceil((endsampl-begsampl+1)/cfg.downsample)); - end - end; - - dat = data.trial{i}(chansel,begsampl:endsampl); - for k=1:size(dat,1) - for j=1:length(cfg.foi) - cTmp = conv(dat(k,:),M{j}); - cTmp = 2*(abs(cTmp).^2)/data.fsample; - cTmp = cTmp(ceil(length(M{j})/2):length(cTmp)-floor(length(M{j})/2)); - cTmp = cTmp(:,1:cfg.downsample:end); - if strcmp(cfg.keeptrials, 'yes') - freq.powspctrm(i,k,j,:) = cTmp'; - else - freq.powspctrm(k,j,:) = squeeze(freq.powspctrm(k,j,:)) + cTmp'; % compute the running sum - end - end - end - -end %for ntrial - -progress('close'); - -if strcmp(cfg.keeptrials, 'yes') - freq.dimord = 'rpt_chan_freq_time'; -else - freq.dimord = 'chan_freq_time'; - freq.powspctrm = freq.powspctrm / ntrial; % compute the average -end -freq.label = cfg.channel; -freq.freq = cfg.foi; -freq.time = indicvect(1:cfg.downsample:end); - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: freqanalysis_tfr.m,v 1.23 2009/02/16 20:30:44 jansch Exp $'; -% remember the configuration details of the input data -try, cfg.previous = data.cfg; end -% remember the exact configuration details in the output -freq.cfg = cfg; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION for waveletanalysis -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function M = waveletfam(foi,Fs,width) -dt = 1/Fs; -for k=1:length(foi) - sf = foi(k)/width; - st = 1/(2*pi*sf); - toi=-3.5*st:dt:3.5*st; - A = 1/sqrt(st*sqrt(pi)); - M{k}= A*exp(-toi.^2/(2*st^2)).*exp(i*2*pi*foi(k).*toi); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION for waveletanalysis -% -% Return a vector containing the energy as a -% function of time for frequency f. The energy -% is calculated using Morlet's wavelets. -% s : signal -% Fs: sampling frequency -% width: width of Morlet wavelet (>= 5 suggested). -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function y = energyvec(f,s,Fs,width) -dt = 1/Fs; -sf = f/width; -st = 1/(2*pi*sf); -t=-3.5*st:dt:3.5*st; -m = morlet(f,t,width); -size(m) -y = conv(s,m); -y = (2*abs(y)/Fs).^2; -y = y(ceil(length(m)/2):length(y)-floor(length(m)/2)); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% subfunction for waveletanalysis -% -% Morlet's wavelet for frequency f and time t. -% The wavelet will be normalized so the total energy is 1. -% width defines the ``width'' of the wavelet. -% A value >= 5 is suggested. -% -% Ref: Tallon-Baudry et al., J. Neurosci. 15, 722-734 (1997) -% -% See also: PHASEGRAM, PHASEVEC, WAVEGRAM, ENERGY -% -% Ole Jensen, August 1998 -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function y = morlet(f,t,width) -sf = f/width; -st = 1/(2*pi*sf); -A = 1/sqrt(st*sqrt(pi)); -y = A*exp(-t.^2/(2*st^2)).*exp(i*2*pi*f.*t); diff --git a/external/fieldtrip/private/freqanalysis_wltconvol.m b/external/fieldtrip/private/freqanalysis_wltconvol.m deleted file mode 100644 index 5b63d98..0000000 --- a/external/fieldtrip/private/freqanalysis_wltconvol.m +++ /dev/null @@ -1,374 +0,0 @@ -function [freq] = freqanalysis_wltconvol(cfg, data); - -% FREQANALYSIS_WLTCONVOL performs time-frequency analysis on any time series trial data -% using the 'wavelet method' based on Morlet wavelets. -% -% Use as -% [freq] = freqanalysis(cfg, data) -% -% The data should be organised in a structure as obtained from -% the PREPROCESSING function. The configuration should be according to -% cfg.method = method used for frequency or time-frequency decomposition -% see FREQANALYSIS for details -% cfg.output = 'pow' return the power-spectra -% 'powandcsd' return the power and the cross-spectra -% -% For cfg.output='powandcsd', you should specify the channel combinations -% between which to compute the cross-spectra as cfg.channelcmb. Otherwise -% you should specify only the channels in cfg.channel. -% -% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), -% see CHANNELSELECTION for details -% cfg.channelcmb = Mx2 cell-array with selection of channel pairs (default = {'all' 'all'}), -% see CHANNELCOMBINATION for details -% cfg.foi = vector 1 x numfoi, frequencies of interest -% cfg.toi = vector 1 x numtoi, the times on which the analysis windows -% should be centered (in seconds) -% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') -% cfg.keeptrials = 'yes' or 'no', return individual trials or average (default = 'no') -% cfg.width = 'width' of the wavelet, determines the temporal and spectral -% resolution of the analysis (default = 7) -% constant, for a 'classical constant-Q' wavelet analysis -% vector, defining a variable width for each frequency -% cfg.gwidth = determines the length of the used wavelets in standard deviations -% of the implicit Gaussian kernel and should be choosen -% >= 3; (default = 3) -% -% The standard deviation in the frequency domain (sf) at frequency f0 is -% defined as: sf = f0/width -% The standard deviation in the temporal domain (st) at frequency f0 is -% defined as: st = width/f0 = 1/sf -% -% See also FREQANALYSIS - -% Copyright (C) 2003-2007, Markus Siegel, F.C. Donders Centre -% -% $Log: freqanalysis_wltconvol.m,v $ -% Revision 1.22 2008/11/11 18:59:26 sashae -% added call to checkconfig at end of function (trackconfig and checksize) -% -% Revision 1.21 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.20 2008/05/13 15:36:09 roboos -% fixed potential bug in assessing the number of trials (when data.trial was column instead of row vector)a, now use numel instead of size -% -% Revision 1.19 2008/01/18 13:14:50 sashae -% added option for trial selection, updated documentation -% -% Revision 1.18 2007/08/06 15:00:52 roboos -% updated documentaton and copyright -% -% Revision 1.17 2007/06/14 12:43:12 jansch -% fixed improper normalisation of powdum -% -% Revision 1.16 2006/10/04 07:10:07 roboos -% updated documentation -% -% Revision 1.15 2006/06/20 16:28:29 ingnie -% added consistent handling of cfg.channel and cfg.channelcmb -% -% Revision 1.14 2006/06/13 14:53:22 ingnie -% some change in white space defaults, added default cfg.channel = 'all' -% -% Revision 1.13 2006/06/06 16:57:51 ingnie -% updated documentation -% -% Revision 1.12 2006/02/23 10:28:16 roboos -% changed dimord strings for consistency, changed toi and foi into time and freq, added fixdimord where neccessary -% -% Revision 1.11 2006/02/07 20:08:22 roboos -% changed all occurences of a dimord with chancmb (was previous sgncmb) into chan -% -% Revision 1.10 2006/02/01 12:26:00 roboos -% made all uses of dimord consistent with the common definition of data dimensions, see the fixdimord() function -% -% Revision 1.9 2005/06/29 12:46:29 roboos -% the following changes were done on a large number of files at the same time, not all of them may apply to this specific file -% - added try-catch around the inclusion of input data configuration -% - moved cfg.version, cfg.previous and the assignment of the output cfg to the end -% - changed help comments around the configuration handling -% - some changes in whitespace -% -% Revision 1.8 2005/05/17 17:50:37 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.7 2005/01/19 08:42:42 jansch -% removed obsolete code for generating and checking channelcombinations -% cleaned up handling of sgnindx/sgncmbindx -% ensured that power is computed for all channels that are in channelcmb -% -% Revision 1.6 2005/01/18 15:11:39 roboos -% Cleaned up configuration for sgn/sgncmb, now exclusively using channel/channelcmb which is consistent with rest of fieldtrip and freqanalysis documentation. Also the output now only contains freq.label/labelcmb and not any more the old sgn/sgncmb. -% -% Revision 1.5 2004/12/20 14:52:56 roboos -% changed rounding off of timboi -% -% Revision 1.4 2004/11/18 16:51:58 roboos -% updated the help: pointed to CHANNELCOMBINATION for cfg.channelcmb -% -% Revision 1.3 2004/10/28 09:00:33 roboos -% fixed bug in caller function detection (for matlab 6.1 and 6.5) -% -% Revision 1.2 2004/10/28 07:21:46 roboos -% added check to ensure that the FREQANALYSIS wrapper is started instead of the -% FERQANALYSIS_xxx subfunctions -% -% Revision 1.1 2004/09/21 12:04:53 marsie -% the wltconvol method of wltanalysis.m has been moved to this seperate function -% -% Revision 1.2 2004/08/25 20:47:18 marsie -% fixed scaling problems -% -% Revision 1.1 2004/08/25 19:18:43 marsie -% initial release -% - -fieldtripdefs - -% ensure that this function is started as a subfunction of the FREQANALYSIS wrapper -if ~exist('OCTAVE_VERSION') - [s, i] = dbstack; - if length(s)>1 - [caller_path, caller_name, caller_ext] = fileparts(s(2).name); - else - caller_path = ''; - caller_name = ''; - caller_ext = ''; - end - % evalin('caller', 'mfilename') does not work for Matlab 6.1 and 6.5 - if ~strcmp(caller_name, 'freqanalysis') - error(['you should call FREQANALYSIS, instead of the ' upper(mfilename) ' subfunction']); - end -end - -% set all the defaults -if ~isfield(cfg, 'method'), cfg.method = 'wltconvol'; end -if ~isfield(cfg, 'keeptrials'), cfg.keeptrials = 'no'; end -if ~isfield(cfg, 'output'), cfg.output = 'powandcsd'; end -if ~isfield(cfg, 'pad'), cfg.pad = 'maxperlen'; end -if ~isfield(cfg, 'width'), cfg.width = 7; end -if ~isfield(cfg, 'gwidth'), cfg.gwidth = 3; end -if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end - -% expand cfg.width to array if constant width -if prod(size(cfg.width)) == 1 - cfg.width = ones(1,length(cfg.foi)) * cfg.width; -end - -% setting a flag (csdflg) that determines whether this routine outputs -% only power-spectra or power-spectra and cross-spectra? -if strcmp(cfg.output,'pow') - csdflg = 0; -elseif strcmp(cfg.output,'powandcsd') - csdflg = 1; -end - -if ~isfield(cfg, 'channelcmb') && csdflg - %set the default for the channelcombination - cfg.channelcmb = {'all' 'all'}; -elseif isfield(cfg, 'channelcmb') && ~csdflg - % no cross-spectrum needs to be computed, hence remove the combinations from cfg - cfg = rmfield(cfg, 'channelcmb'); -end - -% ensure that channelselection and selection of channelcombinations is -% perfomed consistently -cfg.channel = channelselection(cfg.channel, data.label); -if isfield(cfg, 'channelcmb') - cfg.channelcmb = channelcombination(cfg.channelcmb, data.label); -end - -% determine the corresponding indices of all channels -sgnindx = match_str(data.label, cfg.channel); -numsgn = size(sgnindx,1); -if csdflg - % determine the corresponding indices of all channel combinations - for k=1:size(cfg.channelcmb,1) - sgncmbindx(k,1) = strmatch(cfg.channelcmb(k,1), data.label, 'exact'); - sgncmbindx(k,2) = strmatch(cfg.channelcmb(k,2), data.label, 'exact'); - end - - numsgncmb = size(sgncmbindx,1); - sgnindx = unique([sgnindx(:); sgncmbindx(:)]); - numsgn = length(sgnindx); - - cutdatindcmb = zeros(size(sgncmbindx)); - for sgnlop = 1:numsgn - cutdatindcmb(find(sgncmbindx == sgnindx(sgnlop))) = sgnlop; - end -end - -% if rectan is 1 it means that trials are of equal lengths -numper = numel(data.trial); -rectan = 1; -for perlop = 1:numper - numdatbnsarr(perlop,1) = size(data.trial{perlop},2); - if numdatbnsarr(perlop,1) ~= numdatbnsarr(1,1) - rectan = 0; - end -end - -%if cfg.pad is 'maxperlen', this is realized here: -if ischar(cfg.pad) - if strcmp(cfg.pad,'maxperlen') - cfg.pad = max(numdatbnsarr,[],1) ./ data.fsample; - end -end -numsmp = cfg.pad .* data.fsample; - -% keeping trials and/or tapers? -if strcmp(cfg.keeptrials,'no') - keep = 1; -elseif strcmp(cfg.keeptrials,'yes') - keep = 2; -end - -% do the computation for WLTCONVOL -if strcmp(cfg.method,'wltconvol') - minoffset = min(data.offset); - timboi = round(cfg.toi .* data.fsample - minoffset); - toi = round(cfg.toi .* data.fsample) ./ data.fsample; - numtoi = length(toi); - numfoi = length(cfg.foi); - knlspctrmstr = cell(numfoi,1); - for foilop = 1:numfoi - dt = 1/data.fsample; - sf = cfg.foi(foilop)/cfg.width(foilop); - st = 1/(2*pi*sf); - toi2 = -cfg.gwidth*st:dt:cfg.gwidth*st; - A = 1/sqrt(st*sqrt(pi)); - tap = (A*exp(-toi2.^2/(2*st^2)))'; - acttapnumsmp = size(tap,1); - taplen(foilop) = acttapnumsmp; - ins = ceil(numsmp./2) - floor(acttapnumsmp./2); - prezer = zeros(ins,1); - pstzer = zeros(numsmp - ((ins-1) + acttapnumsmp)-1,1); - ind = (0:acttapnumsmp-1)' .* ... - ((2.*pi./data.fsample) .* cfg.foi(foilop)); - knlspctrmstr{foilop} = complex(zeros(1,numsmp)); - knlspctrmstr{foilop} = ... - fft(complex(vertcat(prezer,tap.*cos(ind),pstzer), ... - vertcat(prezer,tap.*sin(ind),pstzer)),[],1)'; - end - if keep == 1 - powspctrm = zeros(numsgn,numfoi,numtoi); - if csdflg, crsspctrm = complex(zeros(numsgncmb,numfoi,numtoi)); end - cntpertoi = zeros(numfoi,numtoi); - dimord = 'chan_freq_time'; - elseif keep == 2 - powspctrm = zeros(numper,numsgn,numfoi,numtoi); - if csdflg, crsspctrm = complex(zeros(numper,numsgncmb,numfoi,numtoi)); end - dimord = 'rpt_chan_freq_time'; - end - for perlop = 1:numper - fprintf('processing trial %d: %d samples\n', perlop, numdatbnsarr(perlop,1)); - if keep == 2 - cnt = perlop; - end - numdatbns = numdatbnsarr(perlop,1); - prepad = zeros(1,data.offset(perlop) - minoffset); - pstpad = zeros(1,minoffset + numsmp - (data.offset(perlop) + numdatbns)); - datspctra = complex(zeros(numsgn,numsmp)); - for sgnlop = 1:numsgn - datspctra(sgnlop,:) = fft([prepad, data.trial{perlop}(sgnindx(sgnlop),:), ... - pstpad],[],2); - end - for foilop = 1:numfoi - fprintf('processing frequency %d (%.2f Hz)\n', foilop,cfg.foi(foilop)); - actfoinumsmp = taplen(foilop); - acttimboiind = ... - find(timboi >= (-minoffset + data.offset(perlop) + (actfoinumsmp ./ 2)) & ... - timboi < (-minoffset + data.offset(perlop) + numdatbns - (actfoinumsmp ./2))); - nonacttimboiind = ... - find(timboi < (-minoffset + data.offset(perlop) + (actfoinumsmp ./ 2)) | ... - timboi >= (-minoffset + data.offset(perlop) + numdatbns - (actfoinumsmp ./2))); - acttimboi = timboi(acttimboiind); - numacttimboi = length(acttimboi); - if keep ==1 - cntpertoi(foilop,acttimboiind) = cntpertoi(foilop,acttimboiind) + 1; - end - if keep == 3 - cnt = 1; - end - autspctrmacttap = complex(zeros(numsgn,numacttimboi)); - if numacttimboi > 0 - for sgnlop = 1:numsgn - dum = fftshift(ifft(datspctra(sgnlop,:) .* ... - [knlspctrmstr{foilop}],[],2)); - autspctrmacttap(sgnlop,:) = dum(acttimboi); - end - powdum = 2.* (abs(autspctrmacttap).^2) ./ data.fsample; - end - if keep == 1 && numacttimboi > 0 - powspctrm(:,foilop,acttimboiind) = powspctrm(:,foilop,acttimboiind) + ... - reshape(powdum,[numsgn,1,numacttimboi]); - elseif keep == 2 && numacttimboi > 0 - powspctrm(cnt,:,foilop,acttimboiind) = powspctrm(cnt,:,foilop,acttimboiind) + ... - reshape(powdum,[1,numsgn,1,numacttimboi]); - powspctrm(cnt,:,foilop,nonacttimboiind) = nan; - elseif keep == 2 && numacttimboi == 0 - powspctrm(cnt,:,foilop,nonacttimboiind) = nan; - end - if csdflg - csddum = 2.* (autspctrmacttap(cutdatindcmb(:,1),:) .* ... - conj(autspctrmacttap(cutdatindcmb(:,2),:))) ./ data.fsample; %actfoinumsmp; - if keep == 1 && numacttimboi > 0 - crsspctrm(:,foilop,acttimboiind) = ... - crsspctrm(:,foilop,acttimboiind) + ... - reshape(csddum,[numsgncmb,1,numacttimboi]); - elseif keep == 2 && numacttimboi > 0 - crsspctrm(cnt,:,foilop,acttimboiind) = ... - crsspctrm(cnt,:,foilop,acttimboiind) + ... - reshape(csddum,[1,numsgncmb,1,numacttimboi]); - crsspctrm(cnt,:,foilop,nonacttimboiind) = nan; - elseif keep == 2 && numacttimboi == 0 - crsspctrm(cnt,:,foilop,nonacttimboiind) = nan; - end - end - end% of foilop - end%of perlop - if keep == 1 - warning off - powspctrm(:,:,:) = powspctrm(:,:,:) ./ repmat(permute(cntpertoi,[3,1,2]),[numsgn,1,1]); - if csdflg - crsspctrm(:,:,:) = crsspctrm(:,:,:) ./ repmat(permute(cntpertoi,[3,1,2]),[numsgncmb,1,1]); - end - warning on - end -end - -% collect the results -freq.label = data.label(sgnindx); -freq.dimord = dimord; -freq.powspctrm = powspctrm; -freq.freq = cfg.foi; -freq.time = cfg.toi; - -if csdflg - freq.labelcmb = cfg.channelcmb; - freq.crsspctrm = crsspctrm; -end - -try, freq.grad = data.grad; end % remember the gradiometer array -try, freq.elec = data.elec; end % remember the electrode array - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% add information about the version of this function to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i1] = dbstack; - cfg.version.name = st(i1); -end -cfg.version.id = '$Id: freqanalysis_wltconvol.m,v 1.22 2008/11/11 18:59:26 sashae Exp $'; -% remember the configuration details of the input data -try, cfg.previous = data.cfg; end -% remember the exact configuration details in the output -freq.cfg = cfg; - diff --git a/external/fieldtrip/private/freqbaseline.m b/external/fieldtrip/private/freqbaseline.m deleted file mode 100644 index 1778ed1..0000000 --- a/external/fieldtrip/private/freqbaseline.m +++ /dev/null @@ -1,296 +0,0 @@ -function [freq] = freqbaseline(cfg, freq); - -% FREQBASELINE performs baseline normalization for time-frequency data -% -% Use as -% [freq] = freqbaseline(cfg, freq) -% where the freq data comes from FREQANALYSIS and the configuration -% should contain -% cfg.baseline = [begin end] (default = 'no') -% cfg.baselinetype = 'absolute' 'relchange' 'relative' (default = 'absolute') -% -% See also FREQANALYSIS, TIMELOCKBASELINE - -% Copyright (C) 2004-2006, Marcel Bastiaansen -% Copyright (C) 2005-2006, Robert Oostenveld -% -% $Log: freqbaseline.m,v $ -% Revision 1.23 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.22 2008/11/21 10:39:09 sashae -% added call to checkconfig -% -% Revision 1.21 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.20 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.19 2007/03/30 17:05:40 ingnie -% checkinput; only proceed when input data is allowed datatype -% -% Revision 1.18 2007/03/27 11:05:19 ingnie -% changed call to fixdimord in call to checkinput -% -% Revision 1.17 2007/01/25 13:58:29 roboos -% fixed bug for single trial data due to incorrect handling of dimensions in 4D data in the nan_mean function (thanks to Doug) -% -% Revision 1.16 2006/10/04 07:08:39 roboos -% added support for baseline correcting single trial TFR data -% -% Revision 1.15 2006/05/03 08:12:51 ingnie -% updated documentation -% -% Revision 1.14 2006/03/09 17:48:36 roboos -% small change in documentation -% -% Revision 1.13 2006/02/23 10:28:16 roboos -% changed dimord strings for consistency, changed toi and foi into time and freq, added fixdimord where neccessary -% -% Revision 1.12 2006/02/07 20:08:22 roboos -% changed all occurences of a dimord with chancmb (was previous sgncmb) into chan -% -% Revision 1.11 2006/02/01 12:26:00 roboos -% made all uses of dimord consistent with the common definition of data dimensions, see the fixdimord() function -% -% Revision 1.10 2006/01/30 12:15:01 roboos -% ensure consistent function declaration: "function [x] = funname()" -% -% Revision 1.9 2006/01/18 10:59:01 jansch -% included the baseline-correction for coherence-spectra, if present in the data -% -% Revision 1.8 2005/08/23 08:44:40 roboos -% removed cfg.absolute and abschange, since they do not appear to be in use any more -% added a warning if baselinetype is specified but baseline=no (for Nelly) -% -% Revision 1.7 2005/06/29 12:46:29 roboos -% the following changes were done on a large number of files at the same time, not all of them may apply to this specific file -% - added try-catch around the inclusion of input data configuration -% - moved cfg.version, cfg.previous and the assignment of the output cfg to the end -% - changed help comments around the configuration handling -% - some changes in whitespace -% -% Revision 1.6 2005/06/01 08:01:39 roboos -% only changes in whitespace -% -% Revision 1.5 2005/05/18 11:53:55 jansch -% changed mean into nan_mean -% -% Revision 1.4 2005/04/08 17:25:23 olejen -% TFRtmp defined several time but never used - now erased -% -% Revision 1.3 2005/04/06 07:41:22 olejen -% *** empty log message *** -% -% Revision 1.2 2005/04/05 17:16:11 olejen -% abschange changed to absolute -% -% Revision 1.1 2005/04/04 16:13:39 olejen -% old implementation by Marcel and Ole put into fieldtrip like function -% - -fieldtripdefs - -cfg = checkconfig(cfg, 'trackconfig', 'on'); - -% check if the input data is valid for this function -freq = checkdata(freq, 'datatype', 'freq', 'feedback', 'yes'); - -% set the defaults -if ~isfield(cfg, 'baseline'), cfg.baseline = 'no'; end -if ~isfield(cfg, 'baselinetype'), cfg.baselinetype = 'absolute'; end % default is to use an absolute baseline - -% give a warning if the input is inconsistent -if ischar(cfg.baseline) && strcmp(cfg.baseline, 'no') && ~isempty(cfg.baselinetype) - warning('no baseline correction done'); -end - -if ischar(cfg.baseline) && strcmp(cfg.baseline, 'yes') - % default is to take the prestimulus interval - cfg.baseline = [-inf 0]; -elseif ischar(cfg.baseline) && strcmp(cfg.baseline, 'no') - % nothing to do - return -end - -haspow = issubfield(freq, 'powspctrm'); -hascoh = issubfield(freq, 'cohspctrm'); - -% we have to ensure that we don't end up with an inconsistent dataset -% remove cross-spectral densities since coherence cannot be computed any more -if isfield(freq, 'crsspctrm') - freq = rmfield(freq, 'crsspctrm'); -end -if isfield(freq, 'cohspctrmsem') - freq = rmfield(freq, 'cohspctrmsem'); -end -if isfield(freq, 'powspctrmsem') - freq = rmfield(freq, 'powspctrmsem'); -end - -if strcmp(freq.dimord, 'chan_freq_time') - % apply the desired method for the average, see the subfunctions below - if strcmp(cfg.baselinetype, 'absolute') - if haspow, freq.powspctrm = TFabschange(freq.time, freq.freq, freq.powspctrm, cfg.baseline); end - if hascoh, freq.cohspctrm = TFabschange(freq.time, freq.freq, freq.cohspctrm, cfg.baseline); end - elseif strcmp(cfg.baselinetype, 'relchange') - if haspow, freq.powspctrm = TFrelchange(freq.time, freq.freq, freq.powspctrm, cfg.baseline); end - if hascoh, freq.cohspctrm = TFrelchange(freq.time, freq.freq, freq.cohspctrm, cfg.baseline); end - elseif strcmp(cfg.baselinetype, 'relative') - if haspow, freq.powspctrm = TFrelative(freq.time, freq.freq, freq.powspctrm, cfg.baseline); end - if hascoh, freq.cohspctrm = TFrelative(freq.time, freq.freq, freq.cohspctrm, cfg.baseline); end - % elseif strcmp(cfg.baselinetype, 'zscore') - % freq.powspctrm = TFzscore(freq.time, freq.freq, freq.powspctrm,cfg.baseline); - else - error('unsupported method for baseline normalization'); - end - -elseif strcmp(freq.dimord, 'rpt_chan_freq_time') - % apply the desired method for each trial, see the subfunctions below - if ~haspow || hascoh - error('this only works for power, not for coherence'); - end - - Ntrial = size(freq.powspctrm,1); - for i=1:Ntrial - % Reshape freq.powspctrm into 3D matrix - % This relies on dimord being 'rpt_chan_freq_time' - tfdata = reshape(freq.powspctrm(i,:,:,:), ... - size(freq.powspctrm,2), ... - size(freq.powspctrm,3), ... - size(freq.powspctrm,4)); - - if strcmp(cfg.baselinetype, 'absolute'), - freq.powspctrm(i,:,:,:) = TFabschange(freq.time, freq.freq, tfdata, cfg.baseline); - elseif strcmp(cfg.baselinetype, 'relchange') - freq.powspctrm(i,:,:,:) = TFrelchange(freq.time, freq.freq, tfdata, cfg.baseline); - elseif strcmp(cfg.baselinetype, 'relative') - freq.powspctrm(i,:,:,:) = TFrelative(freq.time, freq.freq, tfdata, cfg.baseline); - % elseif strcmp(cfg.baselinetype, 'zscore') - % freq.powspctrm = TFzscore(freq.time, freq.freq, freq.powspctrm,cfg.baseline); - else - error('unsupported method for baseline normalization'); - end - end - -else - error('unsupported data dimensions'); -end - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: freqbaseline.m,v 1.23 2009/01/20 13:01:31 sashae Exp $'; -% remember the configuration details of the input data -try, cfg.previous = freq.cfg; end -% remember the exact configuration details in the output -freq.cfg = cfg; - -% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% function [TFdata] = TFzscore(timeVec,freqVec,TFdata,TimeInt) -% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % Compute relative change from baseline on a TFR representation as obtained from the framework software -% % NB fixed order of dimensions is assumed in the TFdata: channels, frequencies, timepoints -% tidx = find(timeVec >= TimeInt(1) & timeVec <= TimeInt(2)); -% TFtmp = TFdata(:,:,tidx); -% for k=1:size(TFdata,2) % loop frequencies -% for l=1:size(TFdata,1) % loop channels -% TFbl (l,k) = squeeze(mean(TFdata(l,k,tidx),3)); %compute average baseline power -% TFblstd(l,k) = squeeze(std (TFdata(l,k,tidx),[], 3)); %compute standard deviation -% end -% end -% for k=1:size(TFdata,2) % loop frequencies -% for l=1:size(TFdata,1) % loop channels -% TFdata(l,k,:) = ((TFdata(l,k,:) - TFbl(l,k)) / TFblstd(l,k)); % compute zscore -% end -% end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [TFdata] = TFrelative(timeVec,freqVec,TFdata,TimeInt) -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Compute relative change from baseline on a TFR representation as obtained from the framework software -% NB fixed order of dimensions is assumed in the TFdata: channels, frequencies, timepoints -tidx = find(timeVec >= TimeInt(1) & timeVec <= TimeInt(2)); - -if length(size(TFdata))~=3, - error('Time-frequency matrix should have three dimensions (chan,freq,time)'); -end - -for k=1:size(TFdata,2) % loop frequencies - for l=1:size(TFdata,1) % loop channels - TFbl(l,k) = nan_mean(TFdata(l,k,tidx),3);%compute average baseline power - - if TFbl(l,k) == 0, - error('Average baseline power is zero'); - end - - end -end -for k=1:size(TFdata,2) % loop frequencies - for l=1:size(TFdata,1) % loop channels - TFdata(l,k,:) = TFdata(l,k,:) / TFbl(l,k); % compute relative change (i.e. ratio) - end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [TFdata] = TFrelchange(timeVec,freqVec,TFdata,TimeInt) -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Compute relative change from baseline on a TFR representation as obtained from the framework software -% NB fixed order of dimensions is assumed in the TFdata: channels, frequencies, timepoints -tidx = find(timeVec >= TimeInt(1) & timeVec <= TimeInt(2)); - -if length(size(TFdata))~=3, - error('Time-frequency matrix should have three dimensions (chan,freq,time)'); -end - -for k=1:size(TFdata,2) % loop frequencies - for l=1:size(TFdata,1) % loop channels - TFbl(l,k) = nan_mean(TFdata(l,k,tidx),3); %compute average baseline power - - if TFbl(l,k) == 0, - error('Average baseline power is zero'); - end - - end -end - -for k=1:size(TFdata,2) % loop frequencies - for l=1:size(TFdata,1) % loop channels - TFdata(l,k,:) = ((TFdata(l,k,:) - TFbl(l,k)) / TFbl(l,k)); % compute relative change - end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [TFdata] = TFabschange(timeVec,freqVec,TFdata,TimeInt) -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Subtract baseline from a TFR representation as obtained from the framework software -% NB fixed order of dimensions is assumed in the TFdata: channels, frequencies, timepoints -tidx = find(timeVec >= TimeInt(1) & timeVec <= TimeInt(2)); - -if length(size(TFdata))~=3, - error('Time-frequency matrix should have three dimensions (chan,freq,time)'); -end - -for k=1:size(TFdata,2) % loop frequencies - for l=1:size(TFdata,1) % loop channels - TFbl(l,k) = nan_mean(TFdata(l,k,tidx),3); %compute average baseline power - end -end -for k=1:size(TFdata,2) % loop frequencies - for l=1:size(TFdata,1) % loop channels - TFdata(l,k,:) = TFdata(l,k,:) - TFbl(l,k); % subtract baseline power - end -end - diff --git a/external/fieldtrip/private/freqdescriptives.m b/external/fieldtrip/private/freqdescriptives.m deleted file mode 100644 index 78fda98..0000000 --- a/external/fieldtrip/private/freqdescriptives.m +++ /dev/null @@ -1,810 +0,0 @@ -function [output] = freqdescriptives(cfg, freq) - -% FREQDESCRIPTIVES computes descriptive statistics of the frequency -% or time-frequency decomposition of the EEG/MEG signal, such as -% the average power and the coherence. -% -% Use as -% [freq] = freqdescriptives(cfg, freq) -% -% The data in freq should be organised in a structure as obtained from -% from the FREQANALYSIS function. The output structure is comparable -% to the input structure and can be used in most functions that require -% a freq input. -% -% The configuration options are -% cfg.cohmethod = 'coh' or 'plv' computes coherence or phase-locking-value (default = 'coh') -% cfg.complex = 'abs', 'complex', 'real', 'imag', 'absreal', 'absimag' or 'angle' (default = 'abs') -% cfg.combinechan = 'no' or 'planar' (default = 'no'), see below -% cfg.combinemethod = 'svdfft', algorithm that is used to combine planar channels: the gradients -% are projected on the direction in which the average power over trials is maximal -% cfg.variance = 'yes' or 'no', estimate standard error in the standard way (default = 'no) -% works only for power -% cfg.jackknife = 'yes' or 'no', estimate standard error by means of the jack-knife (default = 'yes') -% for power and coherence -% cfg.biascorrect = 'yes' or 'no', calculate jackknife bias-corrected power and coherence (default = 'no') -% this option can only chosen if cfg.jackknife = 'yes' -% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), -% see CHANNELSELECTION for details -% cfg.channelcmb = Mx2 cell-array with selection of channel pairs (default = {'all' 'all'}), -% see CHANNELCOMBINATION for details -% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') -% cfg.foilim = [fmin fmax] or 'all', to specify a subset of frequencies (default = 'all') -% cfg.toilim = [tmin tmax] or 'all', to specify a subset of latencies (default = 'all') -% -% Coherence can only be computed if the input data contains either power- -% and cross-spectral densities, or the single-trial Fourier spectra. The -% option cfg.channelcmb only applies to Fourier data. -% -% A variance estimate can only be computed if results from trials and/or -% tapers have been kept. -% -% If the data consists of planar gradient data, you can specify -% cfg.combinechan = 'no'. In that case the power-spectra can be computed -% afterwards by using COMBINEPLANAR. However, if you want to compute -% coherence between two pairs of planar gradiometers, you should specify -% cfg.combinechan = 'planar'. This method only works if your input data -% contains Fourier spectra, i.e. you should specify cfg.output = 'fourier' -% in FREQANALYSIS. -% -% See also FREQANALYSIS, FREQSTATISTICS, FREQBASELINE - -% FIXME: include pseudovalue-stuff -% FIXME: optional z-transformation of coherence: for this, mtmconvol has to output a cumtapcnt -% FIXME: foilim and toilim moeten op alle input data werken -% -% Undocumented local options: -% cfg.feedback -% cfg.keeptrials -% cfg.latency -% cfg.partchan = cell-array (default is empty) -% cfg.previous -% cfg.pseudovalue -% cfg.version - -% Copyright (C) 2004-2006, Pascal Fries & Jan-Mathijs Schoffelen, F.C. Donders Centre -% -% $Log: freqdescriptives.m,v $ -% Revision 1.59 2009/06/12 11:48:22 jansch -% added default for cfg.keepfourier -% -% Revision 1.58 2009/04/08 06:05:23 roboos -% give warning in case plv and input only one trial (solves the problem of Wendy) -% -% Revision 1.57 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.56 2009/01/12 13:05:20 sashae -% small change in call to checkconfig -% -% Revision 1.55 2008/11/28 17:33:19 sashae -% fixed bug in calculating sumcrsspctrm when input data has no time dim -% -% Revision 1.54 2008/11/27 08:48:39 kaigoe -% Speedup by removing for-loops. Added some comments regarding coherence. -% Further speedup possible, if SEM Jackknife estimation should not be -% computed (3x). -% -% Revision 1.52 2008/09/30 16:45:55 sashae -% checkconfig: checks if the input cfg is valid for this function -% -% Revision 1.51 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.50 2008/09/22 11:30:42 roboos -% added default keeptrials=no, which appears to have gone missing in the previous commit -% -% Revision 1.49 2008/09/10 14:11:56 jansch -% fixed an issue with keeptrials -% -% Revision 1.48 2008/05/15 08:18:55 roboos -% replaced strmatch with strcmp where applicable to fix bug in toilim='all' (thanks to Doug) -% -% Revision 1.47 2008/05/06 16:30:26 sashae -% change in trial selection, cfg.trials can be logical -% -% Revision 1.46 2008/01/31 09:42:37 roboos -% keep cumtapcnt if available -% -% Revision 1.45 2008/01/29 18:17:40 sashae -% added option for trial selection -% input data with dimord 'subj_' now also possible, treated similarly as 'rpt_' -% -% Revision 1.44 2007/09/05 09:46:47 jansch -% fixed bug in passing of feedback to fourier2crsspctrm -% -% Revision 1.43 2007/05/30 11:38:43 roboos -% implemented real and absreal for cfg.complex, can be used for instantaneous correlation -% -% Revision 1.42 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.41 2007/03/30 17:05:40 ingnie -% checkinput; only proceed when input data is allowed datatype -% -% Revision 1.40 2007/03/27 11:05:19 ingnie -% changed call to fixdimord in call to checkinput -% -% Revision 1.39 2007/02/27 13:34:55 roboos -% added some comments for ingnie to work on -% -% Revision 1.38 2006/11/29 10:07:56 erimar -% Removed crash-producing code that was a leftover of a copy-paste. -% -% Revision 1.37 2006/10/04 07:10:07 roboos -% updated documentation -% -% Revision 1.36 2006/07/04 17:06:23 ingnie -% updated documentation -% -% Revision 1.35 2006/07/04 16:04:50 roboos -% renamed option 'jacknife' into 'jackknife' for consistency, maintain backward compatibility with cfgs and old data -% -% Revision 1.34 2006/06/22 07:09:00 erimar -% Corrected a bug involving missing brackets. -% -% Revision 1.33 2006/06/20 13:20:13 erimar -% Added the config-option 'biascorrect', which allows to calculate the -% jackknife bias-corrected power and coherence. -% -% Revision 1.32 2006/06/19 14:43:13 erimar -% Corrected some reshape-operations (by adding 1 as the last argument). -% -% Revision 1.31 2006/06/06 16:57:51 ingnie -% updated documentation -% -% Revision 1.30 2006/04/20 09:58:34 roboos -% updated documentation -% -% Revision 1.29 2006/03/22 13:59:59 jansch -% implemented support to do svdfft on input-data containing fourier-spectra -% -% Revision 1.28 2006/03/20 11:23:10 jansch -% new implementation, merging PF's functionality with RO's functionality -% -% Revision 1.26 2006/02/27 11:22:45 roboos -% fixed incorrect variable name, data should be freq -% -% Revision 1.25 2006/02/23 10:28:16 roboos -% changed dimord strings for consistency, changed toi and foi into time and freq, added fixdimord where neccessary -% -% Revision 1.24 2006/02/09 10:06:27 roboos -% changed a help comment -% -% Revision 1.23 2006/02/01 12:26:00 roboos -% made all uses of dimord consistent with the common definition of data dimensions, see the fixdimord() function -% -% Revision 1.22 2005/09/05 06:37:51 jansch -% small change in feedback -% -% Revision 1.21 2005/08/16 11:19:04 jansch -% moved some stuff in 'ro's implementation to a separate function -% fourier2crsspctrm to facilitate re-use - -fieldtripdefs - -% check if the input data is valid for this function -% freq = checkdata(freq, 'datatype', 'freq', 'feedback', 'yes', 'hascumtapcnt', 'no'); -freq = checkdata(freq, 'datatype', 'freq', 'feedback', 'yes'); - -% check if the input cfg is valid for this function -cfg = checkconfig(cfg, 'trackconfig', 'on'); -cfg = checkconfig(cfg, 'renamed', {'jacknife', 'jackknife'}); - -% determine some specific details of the input data -hascsd = isfield(freq, 'crsspctrm'); -hasdft = isfield(freq, 'fourierspctrm'); -haspow = isfield(freq, 'powspctrm'); -hasrpt = ~isempty(strfind(freq.dimord, 'rpt')) || ~isempty(strfind(freq.dimord, 'subj')); -hastap = ~isempty(strfind(freq.dimord, 'tap')); -hastim = ~isempty(strfind(freq.dimord, 'time')); - -% set the defaults -if ~isfield(cfg, 'feedback'), cfg.feedback = 'textbar'; end -if ~isfield(cfg, 'cohmethod'), cfg.cohmethod = 'coh'; end -if ~isfield(cfg, 'complex'), cfg.complex = 'abs'; end -if ~isfield(cfg, 'combinechan'), cfg.combinechan = 'no'; end -if ~isfield(cfg, 'combinemethod'), cfg.combinemethod = 'svdfft'; end -if ~isfield(cfg, 'pseudovalue'), cfg.pseudovalue = 'no'; end -if ~isfield(cfg, 'variance'), cfg.variance = 'no'; end -if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end -if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end -if ~isfield(cfg, 'partchan'), cfg.partchan = {}; end -if ~isfield(cfg, 'foilim'), cfg.foilim = 'all'; end -if ~isfield(cfg, 'toilim'), cfg.toilim = 'all'; end -if ~isfield(cfg, 'keeptrials'), cfg.keeptrials = 'no'; end -if ~isfield(cfg, 'keepfourier'), cfg.keepfourier = 'no'; end - -if ~isfield(cfg, 'channelcmb'), - if hascsd - cfg.channelcmb = freq.labelcmb; - elseif hasdft - cfg.channelcmb = {'all', 'all'}; - else - cfg.channelcmb = {}; - end -end -if ~isfield(cfg, 'jackknife') - if hasrpt - cfg.jackknife = 'yes'; - else - cfg.jackknife = 'no'; - end -end -if ~isfield(cfg, 'biascorrect') - cfg.biascorrect = 'no'; -end - -jckflg = strcmp(cfg.jackknife, 'yes'); -psdflg = strcmp(cfg.pseudovalue, 'yes'); -varflg = strcmp(cfg.variance, 'yes'); -plvflg = strcmp(cfg.cohmethod, 'plv'); -bcrflg = strcmp(cfg.biascorrect, 'yes'); - -if sum([jckflg psdflg varflg]>1) - error('you should specify only one of cfg.jackknife, cfg.pseudovalue or cfg.variance'); -end - -if ~hasrpt && (jckflg || psdflg || varflg), - error('a variance-estimate or pseudovalue-estimate without repeated observations in the input is not possible'); -end - -if ~(hascsd || hasdft) && ~isempty(cfg.partchan), - error('cannot do partialisation without cross-spectra or fourier-spectra in the input data'); -end - -if strcmp(cfg.combinechan, 'planar') && ~hasdft, - error('cfg.combinechan=''planar'' requires Fourier spectra in the input data'); -end - -if ~jckflg && bcrflg - error('You can only calculate jackknife bias-corrected power and coherence estimates if cfg.jackknife=''yes''.'); -end - -% select trials of interest -if ~strcmp(cfg.trials, 'all') - if hastap - error('trial selection is not possible for input data with a ''tap'' dimension'); - elseif ~hasrpt - error('trial selection requires input data with repeated observations'); - end - if hascsd - if islogical(cfg.trials), cfg.trials=find(cfg.trials); end - fprintf('selecting %d trials\n', length(cfg.trials)); - freq.crsspctrm=freq.crsspctrm(cfg.trials,:,:,:); - end - if haspow - if islogical(cfg.trials), cfg.trials=find(cfg.trials); end - fprintf('selecting %d trials\n', length(cfg.trials)); - freq.powspctrm=freq.powspctrm(cfg.trials,:,:,:); - end - % update the trial definition (trl) - if isfield(freq, 'cfg') % try to locate the trl in the nested configuration - trl = findcfg(freq.cfg, 'trl'); - else - trl = []; - end - if isempty(trl) - % a trial definition is expected in each continuous data set - warning('could not locate the trial definition ''trl'' in the data structure'); - else - cfg.trlold=trl; - cfg.trl=trl(cfg.trials,:); - end -end - -%FIXME: use tokenize -if hasrpt, - if strfind(freq.dimord, 'rpttap'), - newdimord = freq.dimord(8:end); - elseif strfind(freq.dimord, 'rpt'), - newdimord = freq.dimord(5:end); - elseif strfind(freq.dimord, 'subj'), - newdimord = freq.dimord(6:end); - end -else - if hascsd - freq.crsspctrm = reshape(freq.crsspctrm, [1 size(freq.crsspctrm)]); - end - if haspow - freq.powspctrm = reshape(freq.powspctrm, [1 size(freq.powspctrm)]); - end - newdimord = freq.dimord; % without the rpt -end - -%check which frequency bins are requested -if strcmp(cfg.foilim, 'all'), - fbin = [1:length(freq.freq)]; -else - fbin = [nearest(freq.freq, cfg.foilim(1)):nearest(freq.freq, cfg.foilim(2))]; -end - -%check which time bins are requested -if ~hastim, - tbin = 1; -elseif hastim && strcmp(cfg.toilim, 'all'), - tbin = [1:length(freq.time)]; -else - tbin = [nearest(freq.time, cfg.latency(1)):nearest(freq.time, cfg.latency(2))]; -end -hastim = length(tbin)>1; -Nfrq = length(fbin); -Ntim = length(tbin); - -% preprocessing of Fourier spectra -if hasdft, - Nrpttap = size(freq.fourierspctrm,1); - if ~strcmp(cfg.combinechan, 'no') - if ~strcmp(cfg.combinemethod, 'svdfft'), - error(sprintf('cfg.combinemethod=''%s'' is not yet implemented', cfg.combinemethod)); - end - % inputlabel2outputlabel will check whether combinechan = 'planar' and act accordingly - tmpcfg = []; - tmpcfg.combinechan = cfg.combinechan; - [outputlabel, outputindex] = inputlabel2outputlabel(tmpcfg, freq); - fourier = zeros(Nrpttap, length(outputindex), Nfrq, Ntim); - progress('init', cfg.feedback, 'computing svdfft for combined channels'); - for j = 1:length(outputindex) - progress(j/length(outputindex)); - if length(outputindex{j}) > 1, - for k = 1:Nfrq - for m = 1:Ntim - tmpsel = find(~isnan(freq.fourierspctrm(:, outputindex{j}(1), fbin(k), tbin(m)))); - fourier(tmpsel, j, k, m) = svdfft(transpose(freq.fourierspctrm(tmpsel, outputindex{j}, fbin(k), tbin(m))), 1); - fourier(setdiff(1:size(freq.fourierspctrm,1),tmpsel), j, k, m) = nan; - end - end - else - fourier(:, j, :, :) = freq.fourierspctrm(:, outputindex{j}, fbin, tbin); - end - end - progress('close'); - freq.fourierspctrm = fourier; - freq.label = outputlabel; - try, freq.time = freq.time(tbin); end - freq.freq = freq.freq(fbin); - clear fourier; - else - % FIXME do tbin and fbin selection, also when combinechan=no - end -end - -if haspow, - % FIXME, do fbin and tbin selection -end - -if hascsd, - % FIXME, do fbin and tbin selection -end - -%channels should be specified as channels in the desired output -cfg.channel = channelselection(cfg.channel, freq.label); -cfg.partchan = channelselection(cfg.partchan, freq.label); - -cfg.channelcmb = channelcombination(cfg.channelcmb, freq.label); -%further preprocessing of fourierspectra, not needed to consider planar combinations anymore -if hasdft, - %convert to cross-spectra - partindx = match_str(freq.label, cfg.partchan); - chnindx = match_str(freq.label, cfg.channel); - %check which channels are needed - chancmb = cfg.channelcmb; - for j = 1:length(cfg.partchan), - chancmb = [cfg.channel repmat(cfg.partchan(j), [length(cfg.channel) 1]); chancmb]; - end - chnindx = unique([chnindx; partindx]); - tmpcfg = []; - tmpcfg.channel = freq.label(chnindx); - tmpcfg.channelcmb = chancmb; - tmpcfg.keeptrials = 'yes'; - tmpcfg.feedback = cfg.feedback; - freq = fourier2crsspctrm(tmpcfg, freq); - hascsd = isfield(freq, 'crsspctrm'); - haspow = isfield(freq, 'powspctrm'); -end - -%concatenate cross-spectra and power-spectra -if hascsd && haspow, - freq.crsspctrm = cat(2,freq.powspctrm,freq.crsspctrm); - freq.labelcmb = [freq.label(:) freq.label(:); freq.labelcmb]; - freq = rmfield(freq,'powspctrm'); -elseif haspow, - freq.crsspctrm = freq.powspctrm; - freq.labelcmb = [freq.label(:) freq.label(:)]; - freq = rmfield(freq,'powspctrm'); -end - -%normalise cross-spectra -if plvflg, - if size(freq.crsspctrm,1)==1 - warning('It seems that the data only contains a single trial or an average, which makes it impossible to compute the phase-locking value. Use cfg.keeptrials=''yes'' in freqanalysis.') - end - freq.crsspctrm = freq.crsspctrm./abs(freq.crsspctrm); -end - -%prepare some stuff for jack-knifing -Nrpt = size(freq.crsspctrm,1); -Ncmb = size(freq.crsspctrm,2); -ind = isfinite(freq.crsspctrm); -dof = sum(ind,1); -if jckflg || psdflg || varflg - % these can only be computed if there are enough trials - dof(find(dof<3)) = nan; -end - -% new efficient version -sumcrsspctrm(1,1:Ncmb,1:Nfrq,1:Ntim) = nansum(freq.crsspctrm,1); -%% does the same as the old inefficient version -% sumcrsspctrm = complex(zeros(1,Ncmb,Nfrq,Ntim), ... -% zeros(1,Ncmb,Nfrq,Ntim)); -% for j = 1:Ncmb -% sumcrsspctrm(1,j,:,:) = nansum(freq.crsspctrm(:,j,:,:),1); -% end -avgcrsspctrm = sumcrsspctrm./dof; - -%compute leave-one-out averages -if jckflg || psdflg, - progress('init', cfg.feedback, 'computing the leave-one-out averages'); - for j = 1:Nrpt - progress(j/Nrpt); - freq.crsspctrm(j,:,:,:) = (sumcrsspctrm - freq.crsspctrm(j,:,:,:))./(dof-double(ind(j,:,:,:))); - end - progress('close'); -elseif varflg, - %do nothing - warning('variance computation only interpretable for power estimate'); -end - -%data-dimensionality -Nrpt = size(freq.crsspctrm,1); -Nsgn = length(freq.label); -Nfrq = size(freq.crsspctrm,3); -Ntim = size(freq.crsspctrm,4); - -%partialise the cross-spectra for the leave-one out averages -if ~isempty(cfg.partchan) && (jckflg || psdflg), - [freq] = partialisation(cfg, freq, 'crsspctrm'); -elseif ~isempty(cfg.partchan) && (varflg) - error('you cannot partialise out channels without leave-one-out averaging'); -end - -%partialise the cross-spectra for the average -if ~isempty(cfg.partchan), - tmpfreq = freq; - tmpfreq.crsspctrm = avgcrsspctrm; - [tmpfreq] = partialisation(cfg, tmpfreq, 'crsspctrm'); - avgcrsspctrm = tmpfreq.crsspctrm; - clear tmpfreq; -end - -%split cross-spectra into true cross-spectra and autospectra - -% determine the corresponding indices of all channel combinations -cmbindx = zeros(size(freq.labelcmb)); -for k=1:size(freq.labelcmb,1) - cmbindx(k,1) = find(strcmp(freq.labelcmb(k,1), freq.label)); - cmbindx(k,2) = find(strcmp(freq.labelcmb(k,2), freq.label)); - % this works the same, but is much slower in Octave - % sgncmbindx(k,1) = strmatch(freq.labelcmb(k,1), freq.label, 'exact'); - % sgncmbindx(k,2) = strmatch(freq.labelcmb(k,2), freq.label, 'exact'); -end -autocmb = cmbindx(:,1) == cmbindx(:,2); -autocmb = find(autocmb); - -avgpowspctrm = avgcrsspctrm(:, autocmb, :, :); -avgcrsspctrm = avgcrsspctrm(:, setdiff(1:size(cmbindx,1), autocmb), :, :); -freq.powspctrm = freq.crsspctrm(:, autocmb, :, :); -freq.crsspctrm = freq.crsspctrm(:, setdiff(1:size(cmbindx,1), autocmb), :, :); -freq.label = freq.label(cmbindx(autocmb,1)); -freq.labelcmb = freq.labelcmb(setdiff(1:size(cmbindx,1), autocmb), :); -dofcsd = dof(:, setdiff(1:size(cmbindx,1), autocmb), :, :); -dofpow = dof(:, autocmb, :, :); -haspow = 1; % from now on it again contains a seperate power spectrum - -%compute the coherence -if hascsd, - % determine the corresponding indices of all channel combinations - cmbindx = zeros(size(cfg.channelcmb)); - for k=1:size(cfg.channelcmb,1) - cmbindx(k,1) = find(strcmp(cfg.channelcmb(k,1), freq.label)); - cmbindx(k,2) = find(strcmp(cfg.channelcmb(k,2), freq.label)); - % this works the same, but is much slower in Octave - % sgncmbindx(k,1) = strmatch(cfg.channelcmb(k,1), data.label, 'exact'); - % sgncmbindx(k,2) = strmatch(cfg.channelcmb(k,2), data.label, 'exact'); - end - - % TODO: THIS is the COHERENCE - % AT LEAST THIS IS WHAT LINE - % 621: output.cohspctrm = reshape(avgcrsspctrm, [sizcrs(2:end), 1]); - % says - - fprintf('computing the coherence\n'); - % new efficient version - avgcrsspctrm = avgcrsspctrm./sqrt( avgpowspctrm(:, cmbindx(:,1), :, :) .* avgpowspctrm(:, cmbindx(:,2), :, :) ); - % does the same as the old, unefficient version: - % for j = 1 %average consists of 1 repetition - % for k = 1:Nfrq - % for m = 1:Ntim - % avgcrsspctrm(j, :, k, m) = avgcrsspctrm(j, :, k, m)./sqrt( avgpowspctrm(j, cmbindx(:,1), k, m) .* avgpowspctrm(j, cmbindx(:,2), k, m) ); - % end - % end - % end - - % TODO: If I see this correctly, thats not the coherence. Instead, the - % avgcrsspctrm computed above seems to be the coherence... - % TODO: It this is true, than avoid computing it, if we do not need it - % (takes quite long) - - fprintf('computing the coherence for SEM\n'); - % new efficient version - freq.crsspctrm = freq.crsspctrm ./sqrt( freq.powspctrm(:, cmbindx(:,1), :, :) .* freq.powspctrm(:, cmbindx(:,2), :, :) ); - % performs the same operation as the old but inefficient version - % (for larger datassets, >50x faster - Order: O(>n)) - % for j = 1:Nrpt - % progress(j/Nrpt); - % for k = 1:Nfrq - % for m = 1:Ntim - % freq.crsspctrm(j, :, k, m) = freq.crsspctrm(j, :, k, m)./sqrt( freq.powspctrm(j, cmbindx(:,1), k, m) .* freq.powspctrm(j, cmbindx(:,2), k, m) ); - % end - % end - % end - - - %put output coherence in correct format - switch cfg.complex - case 'complex' - % leave all values complex - case 'abs' - % convert to absolute values - freq.crsspctrm = abs(freq.crsspctrm); - avgcrsspctrm = abs(avgcrsspctrm); - case 'real' - freq.crsspctrm = real(freq.crsspctrm); - avgcrsspctrm = real(avgcrsspctrm); - case 'imag' - freq.crsspctrm = imag(freq.crsspctrm); - avgcrsspctrm = imag(avgcrsspctrm); - case 'absreal' - freq.crsspctrm = abs(real(freq.crsspctrm)); - avgcrsspctrm = abs(real(avgcrsspctrm)); - case 'absimag' - freq.crsspctrm = abs(imag(freq.crsspctrm)); - avgcrsspctrm = abs(imag(avgcrsspctrm)); - case 'angle' - freq.crsspctrm = angle(freq.crsspctrm); - avgcrsspctrm = angle(avgcrsspctrm); - otherwise - error(sprintf('method ''%s'' is not implemented for cfg.complex', cfg.complex)); - end -end - -%compute sem -if haspow, - powspctrmsem = zeros(size(freq.powspctrm,2),Nfrq,Ntim); - if bcrflg - powspctrmbcr = zeros(1,size(freq.powspctrm,2),Nfrq,Ntim); - end - if jckflg, - for j = 1:Ntim - powspctrmsem(:,:,j) = squeeze(nanstd(freq.powspctrm(:, :, :, j), 1, 1).*sqrt(dofpow(:,:,:,j)-1)); %cf Efron p.141 - if bcrflg - % temporarily store the average over the jackknife samples in powspctrmbcr - powspctrmbcr(:,:,:,j) = nanmean(freq.powspctrm(:, :, :, j), 1); - end; - end - elseif varflg, - for j = 1:Ntim - powspctrmsem(:,:,j) = squeeze(nanstd(freq.powspctrm(:, :, :, j), 0, 1)./sqrt(dofpow(:,:,:,j))); - end - end -end - -if hascsd, - if jckflg - cohspctrmsem = zeros(size(freq.crsspctrm,2),Nfrq,Ntim); - if bcrflg - cohspctrmbcr = zeros(1,size(freq.crsspctrm,2),Nfrq,Ntim); - end - for j = 1:Ntim - cohspctrmsem(:,:,j) = squeeze(nanstd(freq.crsspctrm(:, :, :, j), 1, 1).*sqrt(dofcsd(:,:,:,j)-1)); - if bcrflg - % temporarily store the average over the jackknife samples in cohspctrmbcr - cohspctrmbcr(:,:,:,j) = nanmean(freq.crsspctrm(:, :, :, j), 1); - end; - end - elseif varflg, - fprintf('cannot compute the variance of the coherence without leave-one-out resampling\n'); - end -end - -%create the output-structure -output = []; -output.dimord = newdimord; -output.freq = freq.freq; -if hastim, - output.time = freq.time; -end -output.label = freq.label; - -if strcmp(cfg.keeptrials, 'no'), - sizpow = size(avgpowspctrm); - output.powspctrm = reshape(avgpowspctrm, [sizpow(2:end), 1]); - if jckflg || varflg, - output.powspctrmsem = powspctrmsem; - end - if hascsd, - output.labelcmb = freq.labelcmb; - sizcrs = size(avgcrsspctrm); - if plvflg, - % rename to plv - output.plvspctrm = reshape(avgcrsspctrm, [sizcrs(2:end), 1]); - else - output.cohspctrm = reshape(avgcrsspctrm, [sizcrs(2:end), 1]); - end - if jckflg && plvflg, - % rename to plv - output.plvspctrmsem = cohspctrmsem; - elseif jckflg - output.cohspctrmsem = cohspctrmsem; - end - end - if hascsd, - output.dof = reshape(dofcsd, [sizcrs(2:end), 1]); - else - output.dof = reshape(dofpow, [sizpow(2:end), 1]); - end -else - output.powspctrm = freq.powspctrm; - output.dimord = ['rpt_',output.dimord]; - if hascsd, - output.crsspctrm = freq.crsspctrm; - output.labelcmb = freq.labelcmb; - output.cumtapcnt = freq.cumtapcnt; - end - if strcmp(cfg.keepfourier, 'yes'), - output.fourierspctrm = freq.fourierspctrm; - output.dimord = ['rpttap_',output.dimord(5:end)]; - output.cumtapcnt = freq.cumtapcnt; - output = rmfield(output, 'powspctrm'); - end -end -try, output.grad = freq.grad; end - -%FIXME: pseudovalue -%if psdflg, -% Nrpt = size(pow,1) - 1; -% output.pseudo.powspctrm = repmat(Nrpt.*pow(end,:,:,:), [Nrpt 1 1 1]) - (Nrpt-1).*pow(:,:,:,:); -%end -% -% -% if psdflg, -% output.pseudo.cohspctrm = repmat(Nrpt.*coh, [Nrpt 1 1 1]) - (Nrpt-1).*jckcoh; -% end - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: freqdescriptives.m,v 1.59 2009/06/12 11:48:22 jansch Exp $'; -try, cfg.previous = freq.cfg; end - -% remember the configuration details -output.cfg = cfg; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION that partialises cross-spectra -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [freq] = partialisation(cfg, freq, field) - -crsspctrm = getfield(freq, field); -Nrpt = size(crsspctrm,1); -Nsgn = size(crsspctrm,2); -Nfrq = size(crsspctrm,3); -Ntim = size(crsspctrm,4); -%create signalcombination-matrix, each non-nan entry corresponding -%with the index of the signalcombination in the cross-spectrum -%negative entries should be conjugated before further processing. -%the underlying idea is to temporarily convert the cross-spectra into -%a matrix-shape, so that the partialisation can take place efficiently -%this mainly involves a lot of careful book-keeping -fprintf('indexing the channels and channel combinations\n'); -sgnindx = [1:length(freq.label)]'; -cmbindx = zeros(size(freq.labelcmb)); -for i=1:size(freq.labelcmb,1) - cmbindx(i,1) = find(strcmp(freq.labelcmb(i,1), freq.label)); - cmbindx(i,2) = find(strcmp(freq.labelcmb(i,2), freq.label)); - % this works the same, but is much slower in Octave - % cmbindx(i,1) = strmatch(freq.labelcmb{i,1}, freq.label, 'exact'); - % cmbindx(i,2) = strmatch(freq.labelcmb{i,2}, freq.label, 'exact'); -end -sgncmbmat = nan*zeros(length(sgnindx),length(sgnindx)); -for i=1:size(cmbindx,1) - sgncmbmat(cmbindx(i,2),cmbindx(i,1)) = -i; - sgncmbmat(cmbindx(i,1),cmbindx(i,2)) = i; -end - -fprintf('checking whether partialisation of the requested channel(s) is possible\n'); -prtindx = []; -for j = 1:length(cfg.partchan) - prtindx = [prtindx; strmatch(cfg.partchan{j}, freq.label, 'exact')]; -end -if isempty(prtindx), warning('no partialisation will be performed, requested channel(s) not present in data'); end; - -prtindx = sort(prtindx); -sgnindx = setdiff(sgnindx, prtindx); -prtsgnmat = sgncmbmat(prtindx,prtindx); -rstsgnmat = sgncmbmat(sgnindx,sgnindx); -Nprtsgn = length(prtindx); -Nrstsgn = length(sgnindx); -prtsgnlabel = freq.label(prtindx); -label = freq.label(sgnindx); - -%the reformatting of the cross-spectral densities leads to a re-ordering of the signal-combinations -[ind1, ind2] = find(~isnan(rstsgnmat)); -labelcmb = [label(ind1) label(ind2)]; -cmbindx = [ind1 ind2]; -for j = 1:size(cmbindx,1) - duplicate(j,1) = find([cmbindx(:,1)==cmbindx(j,2)] .* [cmbindx(:,2)==cmbindx(j,1)]); -end %but we end up with a redundant amount of cross-spectra -powindx = find(duplicate==duplicate(duplicate)); %indices of auto-spectra -sel = setdiff(1:size(cmbindx,1),powindx); -duplicate(powindx) = nan; -for j = 1:length(duplicate) - if ~isnan(duplicate(j)), duplicate(find(duplicate==j)) = nan; end -end - -%these cross-spectral density matrices should be complete -if any(isnan(prtsgnmat)), error('partialisation of the requested channel(s) is not possible'); end; -prtrstsgnmat = sgncmbmat(prtindx,sgnindx); -if any(isnan(prtrstsgnmat)), error('partialisation of the requested channel(s) is not possible'); end; -rstprtsgnmat = sgncmbmat(sgnindx,prtindx); -if any(isnan(rstprtsgnmat)), error('partialisation of the requested channel(s) is not possible'); end; - -%allocate memory -csdrr = nan+complex(zeros(Nrstsgn.^2,Nfrq,Ntim) , zeros(Nrstsgn.^2,Nfrq,Ntim)); -csdpp = nan+complex(zeros(Nprtsgn.^2,Nfrq,Ntim) , zeros(Nprtsgn.^2,Nfrq,Ntim)); -csdrp = nan+complex(zeros(Nrstsgn.*Nprtsgn,Nfrq,Ntim), zeros(Nrstsgn.*Nprtsgn,Nfrq,Ntim)); -csdpr = nan+complex(zeros(Nprtsgn.*Nrstsgn,Nfrq,Ntim), zeros(Nprtsgn.*Nrstsgn,Nfrq,Ntim)); - -progress('init', cfg.feedback, 'partialising out the requested channel(s)') -for m = 1:size(crsspctrm,1) - progress(m/size(crsspctrm,1)); - %a bit of hocus-pocus with the cross-spectral densities - csdrr(find(~isnan(rstsgnmat)),:,:) = squeeze(crsspctrm(m,abs(rstsgnmat(find(~isnan(rstsgnmat)))),:,:)); - csdpp(:) = squeeze(crsspctrm(m,abs(prtsgnmat),:,:)); - csdrp(:) = squeeze(crsspctrm(m,abs(rstprtsgnmat),:,:)); - csdpr(:) = squeeze(crsspctrm(m,abs(prtrstsgnmat),:,:)); - - %take care of the conjugates - csdrr(find(rstsgnmat<0),:,:) = conj(csdrr(find(rstsgnmat<0),:,:)); - csdpp(find(prtsgnmat<0),:,:) = conj(csdpp(find(prtsgnmat<0),:,:)); - csdrp(find(rstprtsgnmat<0),:,:) = conj(csdrp(find(rstprtsgnmat<0),:,:)); - csdpr(find(prtrstsgnmat<0),:,:) = conj(csdpr(find(prtrstsgnmat<0),:,:)); - - %perform the partialisation - for j = 1:Nfrq - for k = 1:Ntim - rr = reshape(squeeze(csdrr(:,j,k)),[Nrstsgn Nrstsgn]); - rp = reshape(squeeze(csdrp(:,j,k)),[Nrstsgn Nprtsgn]); - pp = reshape(squeeze(csdpp(:,j,k)),[Nprtsgn Nprtsgn]); - pr = reshape(squeeze(csdpr(:,j,k)),[Nprtsgn Nrstsgn]); - rrp = rr - rp*pinv(pp)*pr; - csdp(m,:,j,k) = rrp(find(~isnan(rrp))); - end - end -end -progress('close'); - -freq.label = label; -freq.labelcmb = labelcmb([powindx; find(~isnan(duplicate))], :); -freq = setfield(freq, field, csdp(:, [powindx; find(~isnan(duplicate))], :, :)); diff --git a/external/fieldtrip/private/freqgrandaverage.m b/external/fieldtrip/private/freqgrandaverage.m deleted file mode 100644 index 3d6350a..0000000 --- a/external/fieldtrip/private/freqgrandaverage.m +++ /dev/null @@ -1,288 +0,0 @@ -function [grandavg] = freqgrandaverage(cfg, varargin); - -% FREQGRANDAVERAGE computes the average powerspectrum or time-frequency spectrum -% over multiple subjects -% -% Use as -% [grandavg] = freqgrandaverage(cfg, freq1, freq2, freq3...) -% -% The input data freq1..N are obtained from either FREQANALYSIS with -% keeptrials=no or from FREQDESCRIPTIVES. The configuration structure -% can contain -% cfg.keepindividual = 'yes' or 'no' (default = 'no') -% cfg.foilim = [fmin fmax] or 'all', to specify a subset of frequencies (default = 'all') -% cfg.toilim = [tmin tmax] or 'all', to specify a subset of latencies (default = 'all') -% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), -% see CHANNELSELECTION for details -% -% See also TIMELOCKGRANDAVERAGE, FREQANALYSIS, FREQDESCRIPTIVES - -% FIXME averaging coherence is not possible if inputs contain different amounts of data (i.e. chan/freq/time) - -% Copyright (C) 2005-2006, Robert Oostenveld -% -% $Log: freqgrandaverage.m,v $ -% Revision 1.15 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.14 2008/11/21 12:48:17 sashae -% added call to checkconfig at start and end of function -% -% Revision 1.13 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.12 2007/09/24 10:26:48 roboos -% implemented averaging of PLV, thanks to Joachim Gross -% -% Revision 1.11 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.10 2007/03/30 17:05:40 ingnie -% checkinput; only proceed when input data is allowed datatype -% -% Revision 1.9 2007/03/27 11:05:19 ingnie -% changed call to fixdimord in call to checkinput -% -% Revision 1.8 2006/10/04 07:10:07 roboos -% updated documentation -% -% Revision 1.7 2006/10/02 15:57:24 roboos -% updated documentation -% -% Revision 1.6 2006/08/29 14:59:03 roboos -% implemented channel/frequency/timeselection, selected data will be consistent over inputs -% -% Revision 1.5 2006/06/13 14:48:09 ingnie -% updated documentation -% -% Revision 1.4 2006/02/23 10:28:16 roboos -% changed dimord strings for consistency, changed toi and foi into time and freq, added fixdimord where neccessary -% -% Revision 1.3 2005/06/29 12:46:29 roboos -% the following changes were done on a large number of files at the same time, not all of them may apply to this specific file -% - added try-catch around the inclusion of input data configuration -% - moved cfg.version, cfg.previous and the assignment of the output cfg to the end -% - changed help comments around the configuration handling -% - some changes in whitespace -% -% Revision 1.2 2005/05/17 17:50:37 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.1 2005/01/03 12:23:17 roboos -% initial implementation -% - -fieldtripdefs - -cfg = checkconfig(cfg, 'trackconfig', 'on'); - -% check if the input data is valid for this function -for i=1:length(varargin) - varargin{i} = checkdata(varargin{i}, 'datatype', 'freq', 'feedback', 'no'); -end - -% set the defaults -if ~isfield(cfg, 'keepindividual'), cfg.keepindividual = 'no'; end -if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end -if ~isfield(cfg, 'foilim'), cfg.foilim = 'all'; end -if ~isfield(cfg, 'toilim'), cfg.toilim = 'all'; end - -% for backward compatibility with old data structures -if isfield(varargin{1}, 'sgn') && ~isfield(varargin{1}, 'label') - warning('renaming "sng" field into label for backward compatibility'); - for s=1:Nsubj - varargin{s}.label = varargin{s}.sgn; - end -end - -% for backward compatibility with old data structures -if isfield(varargin{1}, 'sgncmb') && ~isfield(varargin{1}, 'labelcmb') - warning('renaming "sngcmb" field into labelcmb for backward compatibility'); - for s=1:Nsubj - varargin{s}.labelcmb = varargin{s}.sgncmb; - end -end - -Nsubj = length(varargin); -dimord = varargin{1}.dimord; -haspow = isfield(varargin{1}, 'powspctrm'); % this should always be true -hascoh = isfield(varargin{1}, 'cohspctrm'); -hasplv = isfield(varargin{1}, 'plvspctrm'); -hasfreq = ~isempty(strfind(varargin{i}.dimord, 'freq')); % this should always be true -hastime = ~isempty(strfind(varargin{i}.dimord, 'time')); -hasrpt = ~isempty(strfind(varargin{i}.dimord, 'rpt')); -hastap = ~isempty(strfind(varargin{i}.dimord, 'tap')); - -% check whether the input data is suitable -if hasrpt - error('the input data of each subject should be an average, use FREQDESCRIPTIVES first'); -end -if hastap - error('multiple tapers in the input are not supported'); -end - -if ischar(cfg.foilim) && strcmp(cfg.foilim, 'all') - fbeg = -inf; - fend = inf; -else - fbeg = cfg.foilim(1); - fend = cfg.foilim(2); -end - -if ischar(cfg.toilim) && strcmp(cfg.toilim, 'all') - tbeg = -inf; - tend = inf; -else - tbeg = cfg.toilim(1); - tend = cfg.toilim(2); -end - -% determine which channels, frequencies and latencies are available for all inputs -for i=1:Nsubj - cfg.channel = channelselection(cfg.channel, varargin{i}.label); - if hasfreq - fbeg = max(fbeg, varargin{i}.freq(1 )); - fend = min(fend, varargin{i}.freq(end)); - end - if hastime - tbeg = max(tbeg, varargin{i}.time(1 )); - tend = min(tend, varargin{i}.time(end)); - end -end -cfg.foilim = [fbeg fend]; -cfg.toilim = [tbeg tend]; - -% select the data in all inputs -for i=1:Nsubj - chansel = match_str(varargin{i}.label, cfg.channel); - varargin{i}.label = varargin{i}.label(chansel); - if hasfreq - freqsel = nearest(varargin{i}.freq, fbeg):nearest(varargin{i}.freq, fend); - varargin{i}.freq = varargin{i}.freq(freqsel); - end - if hastime - timesel = nearest(varargin{i}.time, tbeg):nearest(varargin{i}.time, tend); - varargin{i}.time = varargin{i}.time(timesel); - end - % select the overlapping samples in the power spectrum - switch dimord - case 'chan_freq' - varargin{i}.powspctrm = varargin{i}.powspctrm(chansel,freqsel); - case 'chan_freq_time' - varargin{i}.powspctrm = varargin{i}.powspctrm(chansel,freqsel,timesel); - case {'rpt_chan_freq' 'rpttap_chan_freq' 'subj_chan_freq'} - varargin{i}.powspctrm = varargin{i}.powspctrm(:,chansel,freqsel); - case {'rpt_chan_freq_time' 'rpttap_chan_freq_time' 'subj_chan_freq_time'} - varargin{i}.powspctrm = varargin{i}.powspctrm(:,chansel,freqsel,timesel); - otherwise - error('unsupported dimord'); - end -end - -% determine the size of the data to be averaged -dim = size(varargin{1}.powspctrm); -if hascoh, - cohdim = size(varargin{1}.cohspctrm); -end -if hasplv, - plvdim = size(varargin{1}.plvspctrm); -end - -% give some feedback on the screen -if strcmp(cfg.keepindividual, 'no') - if haspow, fprintf('computing average power over %d subjects\n', Nsubj); end - if hascoh, fprintf('computing average coherence over %d subjects\n', Nsubj); end - if hasplv, fprintf('computing average phase-locking value over %d subjects\n', Nsubj); end -else - if haspow, fprintf('not computing grand average, but keeping individual power for %d subjects\n', Nsubj); end - if hascoh, fprintf('not computing grand average, but keeping individual coherence for %d subjects\n', Nsubj); end - if hasplv, fprintf('not computing grand average, but keeping individual phase-locking value for %d subjects\n', Nsubj); end -end - -% allocate memory to hold the data -if strcmp(cfg.keepindividual, 'no') - if haspow, s_pow = zeros( dim); end - if hascoh, s_coh = zeros(cohdim); end - if hasplv, s_plv = zeros(plvdim); end -else - if haspow, s_pow = zeros([Nsubj dim]); end - if hascoh, s_coh = zeros([Nsubj cohdim]); end - if hasplv, s_plv = zeros([Nsubj plvdim]); end -end - -for s=1:Nsubj - if strcmp(cfg.keepindividual, 'no') - % add this subject to the total sum - if haspow, s_pow = s_pow + varargin{s}.powspctrm; end - if hascoh, s_coh = s_coh + varargin{s}.cohspctrm; end - if hasplv, s_plv = s_plv + varargin{s}.plvspctrm; end - else - % concatenate this subject to the rest - if haspow, s_pow(s,:) = varargin{s}.powspctrm(:); end - if hascoh, s_coh(s,:) = varargin{s}.cohspctrm(:); end - if hasplv, s_plv(s,:) = varargin{s}.plvspctrm(:); end - end -end - -% collect the output data -grandavg.label = varargin{1}.label; -grandavg.freq = varargin{1}.freq; -if isfield(varargin{1}, 'time') - % remember the time axis - grandavg.time = varargin{1}.time; -end -if isfield(varargin{1}, 'grad') - warning('discarding gradiometer information because it cannot be averaged'); -end -if isfield(varargin{1}, 'elec') - warning('discarding electrode information because it cannot be averaged'); -end - -if strcmp(cfg.keepindividual, 'no') - grandavg.dimord = dimord; - grandavg.powspctrm = s_pow/Nsubj; - if hascoh, - grandavg.labelcmb = varargin{1}.labelcmb; - grandavg.cohspctrm = s_coh/Nsubj; - end - if hasplv, - grandavg.labelcmb = varargin{1}.labelcmb; - grandavg.plvspctrm = s_plv/Nsubj; - end -else - grandavg.dimord = ['subj_' dimord]; - grandavg.powspctrm = s_pow; - if hascoh, - grandavg.labelcmb = varargin{1}.labelcmb; - grandavg.cohspctrm = s_coh; - end - if hasplv, - grandavg.labelcmb = varargin{1}.labelcmb; - grandavg.plvspctrm = s_plv; - end -end - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: freqgrandaverage.m,v 1.15 2009/01/20 13:01:31 sashae Exp $'; -% remember the configuration details of the input data -cfg.previous = []; -for i=1:length(varargin) - try, cfg.previous{i} = varargin{i}.cfg; end -end -% remember the exact configuration details in the output -grandavg.cfg = cfg; - diff --git a/external/fieldtrip/private/freqinterpolate.m b/external/fieldtrip/private/freqinterpolate.m deleted file mode 100644 index 43b1a6e..0000000 --- a/external/fieldtrip/private/freqinterpolate.m +++ /dev/null @@ -1,79 +0,0 @@ -function [freq] = freqinterpolate(cfg, freq) - -% FREQINTERPOLATE interpolates frequencies by looking at neighbouring -% values or simply replaces a piece in the spectrum by NaN. -% -% Use as -% freq = freqinterpolate(cfg, freq) -% where freq is the output of FREQANALYSIS or FREQDESCRIPTIVES and the -% configuration may contain -% cfg.method = 'nan', 'linear' (default = 'nan') -% cfg.foilim = Nx2 matrix with begin and end of each interval to be -% interpolated (default = [49 51; 99 101; 149 151]) - -% Copyright (C) 2009, Aldemar Torres Valderama -% -% $Log: freqinterpolate.m,v $ -% Revision 1.1 2009/02/24 09:24:32 roboos -% first implementation of new functino, can be used for plotting of powerspectra that contain line-noise and harmonic peaks -% - -fieldtripdefs - -% check if the input data is valid for this function -freq = checkdata(freq, 'datatype', 'freq', 'feedback', 'yes'); - -% check if the input cfg is valid for this function -cfg = checkconfig(cfg, 'trackconfig', 'on'); - -% set the default values -if ~isfield(cfg, 'method'), cfg.method = 'nan'; end -if ~isfield(cfg, 'foilim'), cfg.foilim = [49 51; 99 101; 149 151]; end - -for i = 1:size(cfg.foilim,1) - % determine the exact frequency bins to interpolate - peakbeg = nearest(freq.freq, cfg.foilim(i,1)); - peakend = nearest(freq.freq, cfg.foilim(i,2)); - % update the configuration - cfg.foilim(i,1) = freq.freq(peakbeg); - cfg.foilim(i,2) = freq.freq(peakend); - - if strcmp(cfg.method, 'nan') - switch freq.dimord - case 'chan_freq' - freq.powspctrm(:,peakbeg:peakend) = nan; - case 'chan_freq_time' - freq.powspctrm(:,peakbeg:peakend,:) = nan; - case 'rpt_chan_freq' - freq.powspctrm(:,:,peakbeg:peakend) = nan; - case 'rpt_chan_freq_time' - freq.powspctrm(:,:,peakbeg:peakend,:) = nan; - otherwise - error('unsupported dimord'); - end % switch - - elseif strcmp(cfg.method, 'linear') - error('not yet implemented'); - - else - error('unsupported method'); - end -end % for each frequency range - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% add the version details of this function call to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: freqinterpolate.m,v 1.1 2009/02/24 09:24:32 roboos Exp $'; -% remember the configuration details of the input data -try, cfg.previous = freq.cfg; end -% remember the exact configuration details in the output -freq.cfg = cfg; diff --git a/external/fieldtrip/private/freqsimulation.m b/external/fieldtrip/private/freqsimulation.m deleted file mode 100644 index d6e3683..0000000 --- a/external/fieldtrip/private/freqsimulation.m +++ /dev/null @@ -1,554 +0,0 @@ -function [data] = freqsimulation(cfg) - -% FREQSIMULATION makes simulated data in FieldTrip format. The data is built -% up from fifferent frequencies and can contain a signal in which the -% different frequencies interact (i.e. cross-frequency coherent). Different -% methods are possible to make data with special properties. -% -% Use as -% [data] = freqsimulation(cfg) -% -% The configuration options include -% cfg.method = The methods are explained in more detail below, but they can be -% 'superimposed' simply add the contribution of the different frequencies -% 'broadband' create a single broadband signal component -% 'phalow_amphigh' phase of low freq correlated with amplitude of high freq -% 'amplow_amphigh' amplitude of low freq correlated with amplithude of high freq -% 'phalow_freqhigh' phase of low freq correlated with frequency of high signal -% 'asymmetric' single signal component with asymmetric positive/negative deflections -% cfg.output = which channels should be in the output data, can be 'mixed' or 'all' (default = 'all') -% -% The number of trials and the time axes of the trials can be specified by -% cfg.fsample = simulated sample frequency -% cfg.trllen = length of simulated trials in seconds -% cfg.numtrl = number of simulated trials -% or by -% cfg.time = cell-array with one time axis per trial (i.e. from another dataset) -% -% For each of the methods default parameters are configured to generate -% example data, including noise. To get full control over the generated -% data you should explicitely set all parameters involved in the method -% of your choise. The interpretation of the following signal components -% depends on the specified method: -% -% cfg.s1.freq = frequency of signal 1 -% cfg.s1.phase = phase (in rad) relative to cosine of signal 1 (default depends on method) -% = number or 'random' -% cfg.s1.ampl = amplitude of signal 1 -% cfg.s2.freq = frequency of signal 2 -% cfg.s2.phase = phase (in rad) relative to cosine of signal 1 (default depends on method) -% = number or 'random' -% cfg.s2.ampl = amplitude of signal 2 -% cfg.s3.freq = frequency of signal 3 -% cfg.s3.phase = phase (in rad) relative to cosine of signal 1 (default depends on method) -% = number or 'random' -% cfg.s3.ampl = amplitude of signal 3 -% cfg.s4.freq = frequency of signal 4 -% cfg.s4.phase = phase (in rad) relative to cosine of signal 1 (default depends on method) -% = number or 'random' -% cfg.s4.ampl = amplitude of signal 4 -% -% cfg.n1.ampl = root-mean-square amplitude of wide-band signal prior to filtering -% cfg.n1.bpfreq = [Flow Fhigh] -% cfg.n2.ampl = root-mean-square amplitude of wide-band signal prior to filtering -% cfg.n2.bpfreq = [Flow Fhigh] -% -% cfg.asymmetry = amount of asymmetry (default = 0, which is none) -% cfg.noise.ampl = amplitude of noise -% -% -% In the method 'superimposed' the signal contains just the sum of the different frequency contributions: -% s1: first frequency -% s2: second frequency -% s3: third frequency -% and the output consists of the following channels: -% 1st channel: mixed signal = s1 + s2 + s3 + noise -% 2nd channel: s1 -% 3rd channel: s2 -% 4th channel: s3 -% 5th channel: noise -% -% In the method 'broadband' the signal contains a the superposition of two -% broadband signal components, which are created by bandpass filtering a -% Gaussian noise signal: -% n1: first broadband signal -% n2: second broadband signal -% and the output consists of the following channels: -% 1st channel: mixed signal = n1 + n2 + noise -% 2nd channel: n1 -% 3rd channel: n2 -% 4th channel: noise -% -% In the method 'phalow_amphigh' the signal is build up of 4 components; s1, s2, s3 and noise: -% s1: amplitude modulation (AM), frequency of this signal should be lower than s2 -% s2: second frequency, frequncy that becomes amplitude modulated -% s3: DC shift of s1, should have frequency of 0 -% and the output consists of the following channels: -% 1st channel: mixed signal = (s1 + s3)*s2 + noise, -% 2nd channel: s1 -% 3rd channel: s2 -% 4th channel: s3 -% 5th channel: noise -% -% In the method 'amplow_amphigh' the signal is build up of 5 components; s1, s2, s3, s4 and noise. -% s1: first frequency -% s2: second frequency -% s3: DC shift of s1 and s2, should have frequency of 0 -% s4: amplitude modulation (AM), frequency of this signal should be lower than s1 and s2 -% and the output consists of the following channels: -% 1st channel: mixed signal = (s4 + s3)*s1 + (s4 + s3)*s2 + noise, -% 2nd channel: s1 -% 3rd channel: s2 -% 4th channel: s3 -% 5th channel: noise -% 6th channel: s4 -% 7th channel: mixed part 1: (s4 + s3)*s1 -% 8th channel: mixed part 2: (s4 + s3)*s2 -% -% In the method 'phalow_freqhigh' a frequency modulated signal is created. -% signal is build up of 3 components; s1, s2 and noise. -% s1: represents the base signal that will be modulated -% s2: signal that will be used for the frequency modulation -% and the output consists of the following channels: -% 1st channel: mixed signal = s1.ampl * cos(ins_pha) + noise -% 2nd channel: s1 -% 3rd channel: s2 -% 4th channel: noise -% 5th channel: inst_pha_base instantaneous phase of the high (=base) frequency signal s1 -% 6th channel: inst_pha_mod low frequency phase modulation, this is equal to s2 -% 7th channel: inst_pha instantaneous phase, i.e. inst_pha_base + inst_pha_mod -% -% In the method 'asymmetric' there is only one periodic signal, but that -% signal is more peaked for the positive than for the negative deflections. -% The average of the signal over time is zero. -% s1: represents the frequency of the base signal -% and the output consists of the following channels: -% 1st channel: mixed signal = asymmetric signal + noise -% 2nd channel: sine wave with base frequency and phase, i.e. s1 -% 3rd channel: asymmetric signal -% 4th channel: noise - -% Copyright (C) 2007-2008, Ingrid Nieuwenhuis & Robert Oostenveld, F.C. Donders Centre -% -% $Log: freqsimulation.m,v $ -% Revision 1.15 2009/10/12 14:15:06 jansch -% some typo fixes in comments -% -% Revision 1.14 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.13 2008/07/10 08:39:36 roboos -% updated documentation -% -% Revision 1.12 2008/06/17 16:13:18 sashae -% now using preproc_modules -% -% Revision 1.11 2008/02/26 14:39:25 roboos -% fixed bug in cfg.time -% -% Revision 1.10 2008/01/31 09:21:54 roboos -% look at length of timevec instead of cfg.numtrl -% -% Revision 1.9 2008/01/24 12:18:56 roboos -% allow user to specify his own time axes -% -% Revision 1.8 2008/01/24 11:55:45 roboos -% added method 'asymmetric' -% -% Revision 1.7 2007/11/08 12:57:26 roboos -% renamed method amplow_amphigh_1chan into amplow_amphigh -% -% Revision 1.6 2007/11/07 09:14:28 ingnie -% added method 'phalow_freqhigh' -% -% Revision 1.5 2007/11/06 14:47:53 ingnie -% changed naming from power to amplitude, changed documentation methods phalow_amphigh and amplow_amphigh, changed some variable names to match documentation -% -% Revision 1.4 2007/11/05 11:29:54 roboos -% added cfg.method=broadband -% add version details to output cfg -% -% Revision 1.3 2007/11/05 10:36:32 roboos -% added method superimposed, changed whitespace, moved some code out of for-loops -% -% Revision 1.2 2007/10/23 15:34:42 ingnie -% added option powlow_powhigh_1chan -% -% Revision 1.1 2007/08/08 06:33:10 roboos -% renamed simluatedata to freqsimuation -% -% Revision 1.1 2007/08/07 10:45:33 ingnie -% first implementation -% - -fieldtripdefs - -% set defaults -if ~isfield(cfg, 'method'), cfg.method = 'phalow_amphigh'; end -if ~isfield(cfg, 'output'), cfg.output = 'all'; end -if ~isfield(cfg, 'time'), cfg.time = []; end - -if isempty(cfg.time) - if ~isfield(cfg, 'fsample'), cfg.fsample = 1200; end - if ~isfield(cfg, 'trllen'), cfg.trllen = 1; end - if ~isfield(cfg, 'numtrl'), cfg.numtrl = 1; end -else - cfg.trllen = []; % can be variable - cfg.fsample = 1/(cfg.time{1}(2) - cfg.time{1}(1)); % determine from time-axis - cfg.numtrl = length(cfg.time); -end - -if strcmp(cfg.method,'superimposed') - if ~isfield(cfg, 's1'), cfg.s1 = []; end - if ~isfield(cfg.s1, 'freq'), cfg.s1.freq = 10; end - if ~isfield(cfg.s1, 'phase'), cfg.s1.phase = 0; end - if ~isfield(cfg.s1, 'ampl'), cfg.s1.ampl = 1; end - if ~isfield(cfg, 's2'), cfg.s2 = []; end - if ~isfield(cfg.s2, 'freq'), cfg.s2.freq = 20; end - if ~isfield(cfg.s2, 'phase'), cfg.s2.phase = 0; end - if ~isfield(cfg.s2, 'ampl'), cfg.s2.ampl = 0; end - if ~isfield(cfg, 's3'), cfg.s3 = []; end - if ~isfield(cfg.s3, 'freq'), cfg.s3.freq = 30; end - if ~isfield(cfg.s3, 'phase'), cfg.s3.phase = 0; end - if ~isfield(cfg.s3, 'ampl'), cfg.s3.ampl = 0; end -end - -if strcmp(cfg.method,'broadband') - if ~isfield(cfg, 'n1'), cfg.n1 = []; end - if ~isfield(cfg.n1, 'ampl'), cfg.n1.ampl = 1; end - if ~isfield(cfg.n1, 'bpfreq'), cfg.n1.bpfreq = [30 50]; end - if ~isfield(cfg, 'n2'), cfg.n2 = []; end - if ~isfield(cfg.n2, 'ampl'), cfg.n2.ampl = 1; end - if ~isfield(cfg.n2, 'bpfreq'), cfg.n2.bpfreq = [80 120]; end -end - -if strcmp(cfg.method,'phalow_amphigh') - if ~isfield(cfg, 's1'), cfg.s1 = []; end - if ~isfield(cfg.s1, 'freq'), cfg.s1.freq = 3; end - if ~isfield(cfg.s1, 'phase'), cfg.s1.phase = -1*pi; end - if ~isfield(cfg.s1, 'ampl'), cfg.s1.ampl = 1; end - if ~isfield(cfg, 's2'), cfg.s2 = []; end - if ~isfield(cfg.s2, 'freq'), cfg.s2.freq = 20; end - if ~isfield(cfg.s2, 'phase'), cfg.s2.phase = 0; end - if ~isfield(cfg.s2, 'ampl'), cfg.s2.ampl = 1; end - if ~isfield(cfg, 's3'), cfg.s3 = []; end - if ~isfield(cfg.s3, 'freq'), cfg.s3.freq = 0; end - if ~isfield(cfg.s3, 'phase'), cfg.s3.phase = 0; end - if ~isfield(cfg.s3, 'ampl'), cfg.s3.ampl = cfg.s1.ampl; end -end - -if strcmp(cfg.method,'amplow_amphigh') - if ~isfield(cfg, 's1'), cfg.s1 = []; end - if ~isfield(cfg.s1, 'freq'), cfg.s1.freq = 6; end - if ~isfield(cfg.s1, 'phase'), cfg.s1.phase = 0; end - if ~isfield(cfg.s1, 'ampl'), cfg.s1.ampl = 1; end - if ~isfield(cfg, 's2'), cfg.s2 = []; end - if ~isfield(cfg.s2, 'freq'), cfg.s2.freq = 20; end - if ~isfield(cfg.s2, 'phase'), cfg.s2.phase = 0; end - if ~isfield(cfg.s2, 'ampl'), cfg.s2.ampl = 1; end - if ~isfield(cfg, 's4'), cfg.s4 = []; end - if ~isfield(cfg.s4, 'freq'), cfg.s4.freq = 1; end - if ~isfield(cfg.s4, 'phase'), cfg.s4.phase = -1*pi; end - if ~isfield(cfg.s4, 'ampl'), cfg.s4.ampl = 1; end - if ~isfield(cfg, 's3'), cfg.s3 = []; end - if ~isfield(cfg.s3, 'freq'), cfg.s3.freq = 0; end - if ~isfield(cfg.s3, 'phase'), cfg.s3.phase = 0; end - if ~isfield(cfg.s3, 'ampl'), cfg.s3.ampl = cfg.s4.ampl; end -end - -if strcmp(cfg.method,'phalow_freqhigh') - if ~isfield(cfg, 's1'), cfg.s1 = []; end - if ~isfield(cfg.s1, 'freq'), cfg.s1.freq = 20; end - if ~isfield(cfg.s1, 'phase'), cfg.s1.phase = 0; end - if ~isfield(cfg.s1, 'ampl'), cfg.s1.ampl = 1; end - if ~isfield(cfg, 's2'), cfg.s2 = []; end - if ~isfield(cfg.s2, 'freq'), cfg.s2.freq = 2; end - if ~isfield(cfg.s2, 'phase'), cfg.s2.phase = -0.5 * pi; end %then base freq at t=0 - if ~isfield(cfg.s2, 'ampl'), cfg.s2.ampl = pi; end -end - -if strcmp(cfg.method,'asymmetric') - if ~isfield(cfg, 's1'), cfg.s1 = []; end - if ~isfield(cfg.s1, 'freq'), cfg.s1.freq = 6; end - if ~isfield(cfg.s1, 'phase'), cfg.s1.phase = 0; end - if ~isfield(cfg.s1, 'ampl'), cfg.s1.ampl = 1; end - if ~isfield(cfg, 'noise'), cfg.noise = []; end - if ~isfield(cfg.noise, 'ampl'), cfg.noise.ampl = 0.1; end % default should not be too high -end - -if ~isfield(cfg, 'noise'), cfg.noise = []; end -if ~isfield(cfg.noise, 'ampl'), cfg.noise.ampl = 1; end - - -if ~isempty(cfg.time) - % use the user-supplied time vectors - timevec = cfg.time; -else - Nsamp_tr = cfg.fsample * cfg.trllen; - for iTr = 1 : cfg.numtrl - timevec{iTr} = (1:Nsamp_tr)/cfg.fsample; - end -end - - -%%%%%%% SUPERIMPOSED, SIMPLY ADD THE SIGNALS %%%%%%%%% -if strcmp(cfg.method,'superimposed') - - % make data - for iTr = 1 : length(timevec) - if isstr(cfg.s1.phase); phase_s1 = rand * 2 *pi; else phase_s1 = cfg.s1.phase; end - if isstr(cfg.s2.phase); phase_s2 = rand * 2 *pi; else phase_s2 = cfg.s2.phase; end - if isstr(cfg.s3.phase); phase_s3 = rand * 2 *pi; else phase_s3 = cfg.s3.phase; end - - s1 = cfg.s1.ampl*cos(2*pi*cfg.s1.freq*timevec{iTr} + phase_s1); - s2 = cfg.s2.ampl*cos(2*pi*cfg.s2.freq*timevec{iTr} + phase_s2); - s3 = cfg.s3.ampl*cos(2*pi*cfg.s3.freq*timevec{iTr} + phase_s3); - noise = cfg.noise.ampl*randn(size(timevec{iTr})); - mix = s1 + s2 + s3 + noise; - - data.trial{iTr}(1,:) = mix; - if strcmp(cfg.output,'all') - data.trial{iTr}(2,:) = s1; - data.trial{iTr}(3,:) = s2; - data.trial{iTr}(4,:) = s3; - data.trial{iTr}(5,:) = noise; - end - data.time{iTr} = timevec{iTr}; - end % for iTr - - data.label{1} = 'mix'; - if strcmp(cfg.output,'all') - data.label{2} = 's1'; - data.label{3} = 's2'; - data.label{4} = 's3'; - data.label{5} = 'noise'; - end - data.fsample = cfg.fsample; - - %%%%%%% SUPERIMPOSED BROADBAND SIGNAL %%%%%%%%% -elseif strcmp(cfg.method,'broadband') - - % make data - for iTr = 1 : length(timevec) - n1 = preproc_bandpassfilter(cfg.n1.ampl*randn(size(timevec{iTr})), cfg.fsample, cfg.n1.bpfreq); - n2 = preproc_bandpassfilter(cfg.n2.ampl*randn(size(timevec{iTr})), cfg.fsample, cfg.n2.bpfreq); - noise = cfg.noise.ampl*randn(size(timevec{iTr})); - mix = n1 + n2 + noise; - - data.trial{iTr}(1,:) = mix; - if strcmp(cfg.output,'all') - data.trial{iTr}(2,:) = n1; - data.trial{iTr}(3,:) = n2; - data.trial{iTr}(4,:) = noise; - end - data.time{iTr} = timevec{iTr}; - end % for iTr - - data.label{1} = 'mix'; - if strcmp(cfg.output,'all') - data.label{2} = 'n1'; - data.label{3} = 'n2'; - data.label{4} = 'noise'; - end - data.fsample = cfg.fsample; - - %%%%%%% PHASE TO AMPLITUDE CORRELATION %%%%%%%%% -elseif strcmp(cfg.method,'phalow_amphigh') - - % sanity checks - if cfg.s2.freq < cfg.s1.freq - error('with method is phalow_amphigh freq s2 should be higher than freq s1') - end - if cfg.s2.freq > cfg.fsample/2 - error('you cannot have a frequency higher than the sample frequency/2') - end - if cfg.s3.freq ~= 0 || cfg.s3.phase ~= 0 - warning('for method phalow_amphigh s3 is DC and therefore expect freq and phase to be zero but they are not') - end - if cfg.s3.ampl < cfg.s1.ampl - warning('expect amplitude s3 (=DC) not to be smaller than amplitude s1 (=low frequency)') - end - - % make data - for iTr = 1 : length(timevec) - - if isstr(cfg.s1.phase); phase_AM = rand * 2 *pi; else phase_AM = cfg.s1.phase; end - if isstr(cfg.s2.phase); phase_high = rand * 2 *pi; else phase_high = cfg.s2.phase; end - if isstr(cfg.s3.phase); phase_DC = rand * 2 *pi; else phase_DC = cfg.s3.phase; end - high = cfg.s2.ampl*cos(2*pi*cfg.s2.freq*timevec{iTr} + phase_high); - AM = cfg.s1.ampl*cos(2*pi*cfg.s1.freq*timevec{iTr} + phase_AM); - DC = cfg.s3.ampl*cos(2*pi*0*timevec{iTr} + phase_DC); - noise = cfg.noise.ampl*randn(size(timevec{iTr})); - mix = ((AM + DC) .* high) + noise; - - data.trial{iTr}(1,:) = mix; - if strcmp(cfg.output,'all') - data.trial{iTr}(2,:) = AM; - data.trial{iTr}(3,:) = high; - data.trial{iTr}(4,:) = DC; - data.trial{iTr}(5,:) = noise; - end - data.time{iTr} = timevec{iTr}; - end % for iTr - - data.label{1} = 'mix'; - if strcmp(cfg.output,'all') - data.label{2} = 's1 (AM)'; - data.label{3} = 's2 (high)'; - data.label{4} = 's3 (DC)'; - data.label{5} = 'noise'; - end - data.fsample = cfg.fsample; - - %%%%%%% POWER TO POWER CORRELATION %%%%%%%%% -elseif strcmp(cfg.method,'amplow_amphigh') - - % sanity checks - if cfg.s2.freq < cfg.s1.freq || cfg.s1.freq < cfg.s4.freq - error('with method is powlow_powhigh freq s4 < s1 < s2') - end - if cfg.s2.freq > cfg.fsample/2 - error('you cannot have a frequency higher than the sample frequency/2') - end - if cfg.s3.freq ~= 0 || cfg.s3.phase ~= 0 - warning('for method powlow_powhigh s3 is DC and therefore expect freq and phase to be zero but they are not') - end - if cfg.s3.ampl < cfg.s4.ampl - warning('expect amplitude s3 (=DC) not to be smaller than amplitude s4 (= AM frequency)') - end - - % make data - for iTr = 1 : length(timevec) - - if isstr(cfg.s1.phase); phase_low = rand * 2 *pi; else phase_low = cfg.s1.phase; end - if isstr(cfg.s2.phase); phase_high = rand * 2 *pi; else phase_high = cfg.s2.phase; end - if isstr(cfg.s3.phase); phase_DC = rand * 2 *pi; else phase_DC = cfg.s3.phase; end - if isstr(cfg.s4.phase); phase_AM = rand * 2 *pi; else phase_AM = cfg.s4.phase; end - high = cfg.s2.ampl*cos(2*pi*cfg.s2.freq*timevec{iTr} + phase_high); - low = cfg.s1.ampl*cos(2*pi*cfg.s1.freq*timevec{iTr} + phase_low); - AM = cfg.s4.ampl*cos(2*pi*cfg.s4.freq*timevec{iTr} + phase_AM); - DC = cfg.s3.ampl*cos(2*pi*0*timevec{iTr} + phase_DC); - noise = cfg.noise.ampl*randn(size(timevec{iTr})); - lowmix = ((AM + DC) .* low); - highmix = ((AM + DC) .* high); - mix = lowmix + highmix + noise; - - data.trial{iTr}(1,:) = mix; - if strcmp(cfg.output,'all') - data.trial{iTr}(2,:) = low; - data.trial{iTr}(3,:) = high; - data.trial{iTr}(4,:) = DC; - data.trial{iTr}(5,:) = noise; - data.trial{iTr}(6,:) = AM; - data.trial{iTr}(7,:) = lowmix; - data.trial{iTr}(8,:) = highmix; - end - data.time{iTr} = timevec{iTr}; - end % for iTr - - data.label{1} = 'mix'; - if strcmp(cfg.output,'all') - data.label{2} = 's1 (low)'; - data.label{3} = 's2 (high)'; - data.label{4} = 's3 (DC)'; - data.label{5} = 'noise'; - data.label{6} = 's4 (AM)'; - data.label{7} = 'mixlow'; - data.label{8} = 'mixhigh'; - end - data.fsample = cfg.fsample; - - %%%%%%% PHASE TO FREQUENCY CORRELATION %%%%%%%%% -elseif strcmp(cfg.method,'phalow_freqhigh') - - % sanity checks - if cfg.s1.freq > cfg.fsample/2 || cfg.s2.freq > cfg.fsample/2 - error('you cannot have a frequency higher than the sample frequency/2') - end - - % make data - for iTr = 1 : length(timevec) - - if isstr(cfg.s1.phase); phase_s1 = rand * 2 *pi; else phase_s1 = cfg.s1.phase; end - if isstr(cfg.s2.phase); phase_s2 = rand * 2 *pi; else phase_s2= cfg.s2.phase; end - s1 = cfg.s1.ampl .* cos(2*pi*cfg.s1.freq * timevec{iTr} + phase_s1); % to be modulated signal - s2 = cfg.s2.ampl .* cos(2*pi*cfg.s2.freq * timevec{iTr} + phase_s2); % modulation of instantaneous phase - inst_pha_base = 2*pi*cfg.s1.freq * timevec{iTr} + phase_s1; % unmodulated instantaneous phase s1 (linear) - inst_pha_mod = s2; % modulation of instantaneous phase - inst_pha = inst_pha_base + inst_pha_mod; - noise = cfg.noise.ampl*randn(size(timevec{iTr})); - mix = cfg.s1.ampl .* cos(inst_pha) + noise; - - data.trial{iTr}(1,:) = mix; - if strcmp(cfg.output,'all') - data.trial{iTr}(2,:) = s1; - data.trial{iTr}(3,:) = s2; - data.trial{iTr}(4,:) = noise; - data.trial{iTr}(5,:) = inst_pha_base; - data.trial{iTr}(6,:) = inst_pha_mod; - data.trial{iTr}(7,:) = inst_pha; - end - data.time{iTr} = timevec{iTr}; - end % for iTr - - data.label{1} = 'mix'; - if strcmp(cfg.output,'all') - data.label{2} = 's1'; - data.label{3} = 's2'; - data.label{4} = 'noise'; - data.label{5} = 'inst phase base'; - data.label{6} = 'inst phase modulation (=s2)'; - data.label{7} = 'inst phase'; - end - data.fsample = cfg.fsample; - - %%%%%%% ASYMETRIC POSITIVE AND NEGATIVE PEAKS %%%%%%%%% -elseif strcmp(cfg.method,'asymmetric') - - % make data - for iTr = 1 : length(timevec) - if isstr(cfg.s1.phase); phase_s1 = rand * 2 *pi; else phase_s1 = cfg.s1.phase; end - - s1 = cfg.s1.ampl*cos(2*pi*cfg.s1.freq*timevec{iTr} + phase_s1); - tmp = cos(2*pi*cfg.s1.freq*timevec{iTr} + phase_s1); % same signal but with unit amplitude - tmp = (tmp+1)/2; % scaled and shifted between 0 and 1 - tmp = tmp.^(cfg.asymmetry+1); % made asymmetric - tmp = (tmp - mean(tmp))*2*cfg.s1.ampl; % rescale - s2 = tmp; - noise = cfg.noise.ampl*randn(size(timevec{iTr})); - mix = s2 + noise; - - data.trial{iTr}(1,:) = mix; - if strcmp(cfg.output,'all') - data.trial{iTr}(2,:) = s1; - data.trial{iTr}(3,:) = s2; - data.trial{iTr}(4,:) = noise; - end - data.time{iTr} = timevec{iTr}; - end % for iTr - - data.label{1} = 'mix'; - if strcmp(cfg.output,'all') - data.label{2} = 's1'; - data.label{3} = 's2'; - data.label{4} = 'noise'; - end - data.fsample = cfg.fsample; - -else - error('unknown method specified') -end - -% add the version details of this function call to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: freqsimulation.m,v 1.15 2009/10/12 14:15:06 jansch Exp $'; - -% remember the exact configuration details in the output -data.cfg = cfg; diff --git a/external/fieldtrip/private/freqstatistics.m b/external/fieldtrip/private/freqstatistics.m deleted file mode 100644 index 950b1ac..0000000 --- a/external/fieldtrip/private/freqstatistics.m +++ /dev/null @@ -1,175 +0,0 @@ -function [stat] = freqstatistics(cfg, varargin) - -% FREQSTATISTICS computes significance probabilities and/or critical values of a parametric statistical test -% or a non-parametric permutation test. -% -% Use as -% [stat] = freqstatistics(cfg, freq1, freq2, ...) -% where the input data is the result from FREQANALYSIS, FREQDESCRIPTIVES -% or from FREQGRANDAVERAGE. -% -% The configuration can contain the following options for data selection -% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), -% see CHANNELSELECTION for details -% cfg.latency = [begin end] in seconds or 'all' (default = 'all') -% cfg.frequency = [begin end], can be 'all' (default = 'all') -% cfg.avgoverchan = 'yes' or 'no' (default = 'no') -% cfg.avgovertime = 'yes' or 'no' (default = 'no') -% cfg.avgoverfreq = 'yes' or 'no' (default = 'no') -% cfg.parameter = string (default = 'powspctrm') -% -% Furthermore, the configuration should contain -% cfg.method = different methods for calculating the significance probability and/or critical value -% 'montecarlo' get Monte-Carlo estimates of the significance probabilities and/or critical values from the permutation distribution, -% 'analytic' get significance probabilities and/or critical values from the analytic reference distribution (typically, the sampling distribution under the null hypothesis), -% 'stats' use a parametric test from the Matlab statistics toolbox, -% 'glm' use a general linear model approach. -% -% The other cfg options depend on the method that you select. You -% should read the help of the respective subfunction STATISTICS_XXX -% for the corresponding configuration options and for a detailed -% explanation of each method. -% -% See also FREQANALYSIS, FREQDESCRIPTIVES, FREQGRANDAVERAGE - -% This function depends on STATISTICS_WRAPPER -% -% TODO change cfg.frequency in all functions to cfg.foi or cfg.foilim - -% Copyright (C) 2005-2006, Robert Oostenveld -% -% $Log: freqstatistics.m,v $ -% Revision 1.23 2009/10/07 10:03:30 jansch -% temporary workaround to work with private copy statistics_wrapperJM, in order -% to develop some code. users whose (part of their) username contains 'jan' -% will run into problems, and have to uncomment lines 140, 143-145 -% -% Revision 1.22 2009/04/08 15:57:08 roboos -% moved the handling of the output cfg (with all history details) from wrapper to main function -% -% Revision 1.21 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.20 2007/07/16 16:02:13 roboos -% fixed small bug for cfg.parameter -% -% Revision 1.19 2007/07/04 08:21:02 roboos -% remove cross/coherence spectrum in case cfg.parameter=powspctrm -% -% Revision 1.18 2007/06/13 06:19:40 roboos -% fixed bug in strcmp(cfg.parameter, ...), thanks to Vladimir -% -% Revision 1.17 2007/05/14 08:28:05 roboos -% changed handling of non-powspctrm input, also support cohspctrm -% -% Revision 1.16 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.15 2007/04/02 14:33:44 roboos -% disabled checkinput for the time being, since freq data can contain stat/zvalue/tvalue instead of powsptrm -% -% Revision 1.14 2007/03/30 17:05:40 ingnie -% checkinput; only proceed when input data is allowed datatype -% -% Revision 1.13 2007/03/27 15:20:50 erimar -% Updated help (replaced "p-value" by "significance probability"). -% -% Revision 1.12 2007/01/17 13:23:35 roboos -% added bug report, no functional change -% -% Revision 1.11 2006/11/27 15:38:20 roboos -% implemented support for cfg.parameter, by locally renaming the field in the data structure -% -% Revision 1.10 2006/10/19 15:05:51 roboos -% updated documentation -% -% Revision 1.9 2006/10/04 07:10:07 roboos -% updated documentation -% -% Revision 1.8 2006/07/12 09:18:17 roboos -% improved documentation -% -% Revision 1.7 2006/06/20 16:25:58 ingnie -% updated documentation -% -% Revision 1.6 2006/06/20 12:57:26 roboos -% updated documentation -% -% Revision 1.5 2006/06/13 14:48:09 ingnie -% updated documentation - -fieldtripdefs - -% check if the input data is valid for this function -for i=1:length(varargin) - % FIXME at this moment (=2 April) this does not work, because the input might not always have a powspctrm o.i.d. - % See email from Juriaan - % varargin{i} = checkdata(varargin{i}, 'datatype', 'freq', 'feedback', 'no'); -end - -% the low-level data selection function does not know how to deal with other parameters, so work around it -if isfield(cfg, 'parameter') && strcmp(cfg.parameter, 'powspctrm') - % use the power spectrum, this is the default - for i=1:length(varargin) - if isfield(varargin{i}, 'crsspctrm'), varargin{i} = rmfield(varargin{i}, 'crsspctrm'); end % remove to avoid confusion - if isfield(varargin{i}, 'cohspctrm'), varargin{i} = rmfield(varargin{i}, 'cohspctrm'); end % remove to avoid confusion - if isfield(varargin{i}, 'labelcmb'), varargin{i} = rmfield(varargin{i}, 'labelcmb'); end % remove to avoid confusion - end -elseif isfield(cfg, 'parameter') && strcmp(cfg.parameter, 'crsspctrm') - % use the cross spectrum, this might work as well (but has not been tested) -elseif isfield(cfg, 'parameter') && strcmp(cfg.parameter, 'cohspctrm') - % for testing coherence on group level: - % rename cohspctrm->powspctrm and labelcmb->label - for i=1:length(varargin) - dat = varargin{i}.cohspctrm; - labcmb = varargin{i}.labelcmb; - for j=1:size(labcmb) - lab{j,1} = sprintf('%s - %s', labcmb{j,1}, labcmb{j,2}); - end - varargin{i} = rmsubfield(varargin{i}, 'cohspctrm'); - varargin{i} = rmsubfield(varargin{i}, 'labelcmb'); - varargin{i} = setsubfield(varargin{i}, 'powspctrm', dat); - varargin{i} = setsubfield(varargin{i}, 'label', lab); - end -elseif isfield(cfg, 'parameter') - % rename the desired parameter to powspctrm - fprintf('renaming parameter ''%s'' into ''powspctrm''\n', cfg.parameter); - for i=1:length(varargin) - dat = getsubfield(varargin{i}, cfg.parameter); - varargin{i} = rmsubfield (varargin{i}, cfg.parameter); - varargin{i} = setsubfield(varargin{i}, 'powspctrm', dat); - end -end - -[status,output] = system('whoami'); -if isempty(strfind(output,'jan')), - % call the general function - [stat, cfg] = statistics_wrapper(cfg, varargin{:}); -else - % call the general function - [stat, cfg] = statistics_wrapperJM(cfg, varargin{:}); -end - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: freqstatistics.m,v 1.23 2009/10/07 10:03:30 jansch Exp $'; - -% remember the configuration of the input data -cfg.previous = []; -for i=1:length(varargin) - if isfield(varargin{i}, 'cfg') - cfg.previous{i} = varargin{i}.cfg; - else - cfg.previous{i} = []; - end -end - -% remember the exact configuration details -stat.cfg = cfg; diff --git a/external/fieldtrip/private/fwer.m b/external/fieldtrip/private/fwer.m new file mode 100644 index 0000000..1f446e7 --- /dev/null +++ b/external/fieldtrip/private/fwer.m @@ -0,0 +1,32 @@ +function [h] = fwer(p, q); + +% FWER family-wise error rate control using Bonferoni method +% +% Use as +% h = fwer(p, q) + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: fwer.m 952 2010-04-21 18:29:51Z roboos $ + +% count the number of voxels +V = length(p); + +% threshold the probability of all voxels +h = (p<=(q/V)); diff --git a/external/fieldtrip/private/geometry.h b/external/fieldtrip/private/geometry.h old mode 100755 new mode 100644 diff --git a/external/fieldtrip/private/getsubfield.m b/external/fieldtrip/private/getsubfield.m deleted file mode 100644 index b376a50..0000000 --- a/external/fieldtrip/private/getsubfield.m +++ /dev/null @@ -1,35 +0,0 @@ -function [s] = getsubfield(s, f); - -% GETSUBFIELD returns a field from a structure just like the standard -% Matlab GETFIELD function, except that you can also specify nested fields -% using a '.' in the fieldname. The nesting can be arbitrary deep. -% -% Use as -% f = getsubfield(s, 'fieldname') -% or as -% f = getsubfield(s, 'fieldname.subfieldname') -% -% See also GETFIELD, ISSUBFIELD, SETSUBFIELD - -% Copyright (C) 2005, Robert Oostenveld -% -% $Log: getsubfield.m,v $ -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.1 2005/02/08 09:30:18 roboos -% new implementations to make it easier to work with nested structures -% - -if ~isstr(f) - error('incorrect input argument for fieldname'); -end - -t = {}; -while (1) - [t{end+1}, f] = strtok(f, '.'); - if isempty(f) - break - end -end -s = getfield(s, t{:}); diff --git a/external/fieldtrip/private/globalrescale.m b/external/fieldtrip/private/globalrescale.m index 4f0c639..6511901 100644 --- a/external/fieldtrip/private/globalrescale.m +++ b/external/fieldtrip/private/globalrescale.m @@ -33,15 +33,23 @@ % along with this program; if not, write to the Free Software % Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -% $Log: globalrescale.m,v $ -% Revision 1.3 2005/08/15 08:15:32 roboos -% reimplemented the rotate function, which contained an error (the error is in the AIR technical reference) -% changed all functions to be dependent on the rotate, translate and scale function -% all functions now behave consistenly, which also means that they are not compleetly backward compatible w.r.t. the order of the rotations +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.2 2004/05/19 09:57:07 roberto -% added GPL copyright statement, added CVS log item +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: globalrescale.m 952 2010-04-21 18:29:51Z roboos $ % compute the homogenous transformation matrix for the translation T = translate(f([1 2 3])); diff --git a/external/fieldtrip/private/guidelines.m b/external/fieldtrip/private/guidelines.m new file mode 100644 index 0000000..8562818 --- /dev/null +++ b/external/fieldtrip/private/guidelines.m @@ -0,0 +1,52 @@ +function str = guidelines(funname, pat) + +% GUIDELINES searches for a contiguous block of commented text and shows +% its contents. It is used to display additional help sections. + +if nargin<2 + pat = '[Gg]uidelines'; +end + +if ispc + linesep = [13 10]; +else + linesep = 10; +end + +if nargout>0 + str = ''; +end + +funfile = which(funname); +fid = fopen(funfile, 'rt'); + +blockbeg = false; +blockend = false; + +while ~feof(fid) + line = fgetl(fid); + + if ~blockbeg + % test whether the block begins + blockbeg = ~isempty(regexp(line, pat, 'once')); + else + % test whether the block ends + blockend = isempty(line) || ~isequal(line(1), '%'); + end + + if blockbeg && blockend + break + end + + if blockbeg && ~blockend + if nargout>0 + str = cat(2, str, line(2:end), linesep); + else + disp(line(2:end)); + end + end + +end + +fclose(fid); + diff --git a/external/fieldtrip/private/hastoolbox.m b/external/fieldtrip/private/hastoolbox.m deleted file mode 100644 index a4ca969..0000000 --- a/external/fieldtrip/private/hastoolbox.m +++ /dev/null @@ -1,408 +0,0 @@ -function [status] = hastoolbox(toolbox, autoadd, silent) - -% HASTOOLBOX tests whether an external toolbox is installed. Optionally -% it will try to determine the path to the toolbox and install it -% automatically. -% -% Use as -% [status] = hastoolbox(toolbox, autoadd, silent) - -% Copyright (C) 2005-2008, Robert Oostenveld -% -% $Log: hastoolbox.m,v $ -% Revision 1.37 2009/10/13 10:11:06 roboos -% added lc-libs -% -% Revision 1.36 2009/09/08 14:34:01 roboos -% also detect 64 bit windows version (thanks to arno) -% -% Revision 1.35 2009/04/21 09:54:15 roboos -% added prtools -% -% Revision 1.34 2009/04/02 19:47:33 roboos -% added plotting module -% -% Revision 1.33 2009/03/30 15:06:14 roboos -% added the patch from Alexandre to support openmeeg -% -% Revision 1.32 2009/03/12 10:40:21 roboos -% added the splines toolbox (mainly for testing) and changed the warning message related to the license -% -% Revision 1.31 2009/03/12 10:33:35 roboos -% not only check that a function is available, also check whether a license for that function is available -% -% Revision 1.30 2009/03/11 21:26:27 roboos -% detect spm8b just as spm8 -% -% Revision 1.29 2009/03/11 10:35:19 roboos -% spm detection was confused with function and directory, explicitely check for "spm.m" which is the function -% -% Revision 1.28 2009/03/11 08:49:04 roboos -% improved the detection of the various spm versions -% -% Revision 1.27 2009/02/11 11:03:08 roboos -% changed naming of the functions of Chris in accordance with SPM8 -% -% Revision 1.26 2009/02/02 12:57:21 roboos -% added bemcp, image, tcp_udp_ip -% -% Revision 1.25 2009/01/19 15:02:21 roboos -% added mne for fiff access -% -% Revision 1.24 2009/01/08 17:00:02 roboos -% improved caching in case the toolbox is not present -% -% Revision 1.23 2008/12/24 09:10:46 roboos -% added dipoli -% -% Revision 1.22 2008/10/29 15:45:12 roboos -% fix dashes and spaces in directory names for caching -% -% Revision 1.21 2008/10/20 21:50:56 roboos -% added NlxNetCom -% -% Revision 1.20 2008/10/20 16:31:15 roboos -% fixed problem in case with dash "-" in the directory -% -% Revision 1.19 2008/09/29 09:00:19 roboos -% implemented smart handling of previously seen toolboxes using a persistent variable -% this should speed up fieldtrip and fileio (e.g. read_data checks the presence of ctf for every trial) -% -% Revision 1.18 2008/09/24 15:43:00 roboos -% added read_data and read_sens for fileio, should solve problem for MEEGfileio in spm5 -% -% Revision 1.17 2008/09/22 19:42:09 roboos -% added option for silent processing -% -% Revision 1.16 2008/08/11 16:11:19 roboos -% also automatically add to path for fieldtrip code and external modules -% -% Revision 1.15 2008/06/20 07:25:56 roboos -% added check for presence of BCI2000 load_bcidat mex file -% -% Revision 1.14 2008/05/15 10:52:29 roboos -% added ctf -% -% Revision 1.13 2008/03/17 08:29:40 roboos -% changed some contact addresses -% -% Revision 1.12 2008/03/14 10:20:29 roboos -% added denoise -% -% Revision 1.11 2008/03/05 10:59:14 roboos -% added fileio and forwinv -% -% Revision 1.10 2007/05/06 09:10:07 roboos -% added spm5 -% -% Revision 1.9 2007/02/26 13:41:07 roboos -% made small change to fastica detection (suggested by Sameer) -% -% Revision 1.8 2007/02/13 17:22:27 roboos -% added MRI from eeg.sf.net -% -% Revision 1.7 2007/02/13 14:01:26 roboos -% added brainstorm -% -% Revision 1.6 2007/02/12 19:43:23 roboos -% added fastica, optim -% -% Revision 1.5 2007/01/17 17:05:34 roboos -% added matlab signal processing toolbox -% -% Revision 1.4 2007/01/04 12:25:19 roboos -% added SON2 -% -% Revision 1.3 2007/01/03 17:01:15 roboos -% added 4d-version toolbox -% -% Revision 1.2 2006/06/07 10:48:02 roboos -% changed the "see xxx" string -% -% Revision 1.1 2006/06/07 09:28:41 roboos -% renamed fieldtrip/private/checktoolbox into misc/hastoolbox -% -% Revision 1.8 2006/06/06 14:18:22 roboos -% added neuroshare, eeprobe, yokogawa -% -% Revision 1.7 2006/05/31 08:56:24 roboos -% implemented detection of toolbox in users ~/matlab/toolboxname -% -% Revision 1.6 2006/05/23 10:20:46 roboos -% added beowulf and mentat toolboxes -% -% Revision 1.5 2006/04/26 11:37:22 roboos -% added besa toolbox -% -% Revision 1.4 2006/02/07 20:01:39 roboos -% aded biosig and meg-pd (neuromag) -% -% Revision 1.3 2006/01/17 14:05:54 roboos -% added GLNA64 for mentat000 -% -% Revision 1.2 2006/01/06 11:39:23 roboos -% added copyrigth and cvs logging, changed some comments -% - -% this function is called many times in FieldTrip and associated toolboxes -% use efficient handling if the same toolbox has been investigated before -persistent previous -if isempty(previous) - previous = struct; -elseif isfield(previous, fixname(toolbox)) - status = previous.(fixname(toolbox)); - return -end - -% this points the user to the website where he/she can download the toolbox -url = { - 'AFNI' 'see http://afni.nimh.nih.gov' - 'DSS' 'see http://www.cis.hut.fi/projects/dss' - 'EEGLAB' 'see http://www.sccn.ucsd.edu/eeglab' - 'NWAY' 'see http://www.models.kvl.dk/source/nwaytoolbox' - 'SPM99' 'see http://www.fil.ion.ucl.ac.uk/spm' - 'SPM2' 'see http://www.fil.ion.ucl.ac.uk/spm' - 'SPM5' 'see http://www.fil.ion.ucl.ac.uk/spm' - 'SPM8' 'see http://www.fil.ion.ucl.ac.uk/spm' - 'MEG-PD' 'see http://www.kolumbus.fi/kuutela/programs/meg-pd' - 'MEG-CALC' 'this is a commercial toolbox from Neuromag, see http://www.neuromag.com' - 'BIOSIG' 'see http://biosig.sourceforge.net' - 'EEG' 'see http://eeg.sourceforge.net' - 'EEGSF' 'see http://eeg.sourceforge.net' % alternative name - 'MRI' 'see http://eeg.sourceforge.net' % alternative name - 'NEUROSHARE' 'see http://www.neuroshare.org' - 'BESA' 'see http://www.megis.de, or contact Karsten Hoechstetter' - 'EEPROBE' 'see http://www.ant-neuro.com, or contact Maarten van der Velde' - 'YOKOGAWA' 'see http://www.yokogawa.co.jp, or contact Nobuhiko Takahashi' - 'BEOWULF' 'see http://oostenveld.net, or contact Robert Oostenveld' - 'MENTAT' 'see http://oostenveld.net, or contact Robert Oostenveld' - 'SON2' 'see http://www.kcl.ac.uk/depsta/biomedical/cfnr/lidierth.html, or contact Malcolm Lidierth' - '4D-VERSION' 'contact Christian Wienbruch' - 'SIGNAL' 'see http://www.mathworks.com/products/signal' - 'OPTIM' 'see http://www.mathworks.com/products/optim' - 'IMAGE' 'see http://www.mathworks.com/products/image' - 'SPLINES' 'see http://www.mathworks.com/products/splines' - 'FASTICA' 'see http://www.cis.hut.fi/projects/ica/fastica' - 'BRAINSTORM' 'see http://neuroimage.ucs.edu/brainstorm' - 'FILEIO' 'see http://www.ru.nl/neuroimaging/fieldtrip' - 'FORWINV' 'see http://www.ru.nl/neuroimaging/fieldtrip' - 'PLOTTING' 'see http://www.ru.nl/neuroimaging/fieldtrip' - 'DENOISE' 'see http://lumiere.ens.fr/Audition/adc/meg, or contact Alain de Cheveigne' - 'BCI2000' 'see http://bci2000.org' - 'NLXNETCOM' 'see http://www.neuralynx.com' - 'DIPOLI' 'see ftp://ftp.fcdonders.nl/pub/fieldtrip/external' - 'MNE' 'see http://www.nmr.mgh.harvard.edu/martinos/userInfo/data/sofMNE.php' - 'TCP_UDP_IP' 'see http://www.mathworks.com/matlabcentral/fileexchange/345, or contact Peter Rydes?ter' - 'BEMCP' 'contact Christophe Phillips' - 'OPENMEEG' 'see http://gforge.inria.fr/projects/openmeeg' - 'PRTOOLS' 'see http://www.prtools.org' - 'LC-LIBS' 'contact Stefania Della Penna' - }; - -if nargin<2 - % default is not to add the path automatically - autoadd = 0; -end - -if nargin<3 - % default is not to be silent - silent = 0; -end - -% determine whether the toolbox is installed -toolbox = upper(toolbox); -switch toolbox - case 'AFNI' - status = (exist('BrikLoad') && exist('BrikInfo')); - case 'DSS' - status = exist('dss', 'file') && exist('dss_create_state', 'file'); - case 'EEGLAB' - status = exist('runica', 'file'); - case 'NWAY' - status = exist('parafac', 'file'); - case 'SPM99' - status = exist('spm.m') && strcmp(spm('ver'),'SPM99'); - case 'SPM2' - status = exist('spm.m') && strcmp(spm('ver'),'SPM2'); - case 'SPM5' - status = exist('spm.m') && strcmp(spm('ver'),'SPM5'); - case 'SPM8' - status = exist('spm.m') && strncmp(spm('ver'),'SPM8', 3); - case 'MEG-PD' - status = (exist('rawdata') && exist('channames')); - case 'MEG-CALC' - status = (exist('megmodel') && exist('megfield') && exist('megtrans')); - case 'BIOSIG' - status = (exist('sopen') && exist('sread')); - case 'EEG' - status = (exist('ctf_read_res4') && exist('ctf_read_meg4')); - case 'EEGSF' % alternative name - status = (exist('ctf_read_res4') && exist('ctf_read_meg4')); - case 'MRI' % other functions in the mri section - status = (exist('avw_hdr_read') && exist('avw_img_read')); - case 'NEUROSHARE' - status = (exist('ns_OpenFile') && exist('ns_SetLibrary') && exist('ns_GetAnalogData')); - case 'BESA' - status = (exist('readBESAtfc') && exist('readBESAswf')); - case 'EEPROBE' - status = (exist('read_eep_avr') && exist('read_eep_cnt')); - case 'YOKOGAWA' - status = (exist('GetMeg160ChannelInfoM') && exist('GetMeg160ContinuousRawDataM')); - case 'BEOWULF' - status = (exist('evalwulf') && exist('evalwulf') && exist('evalwulf')); - case 'MENTAT' - status = (exist('pcompile') && exist('pfor') && exist('peval')); - case 'SON2' - status = (exist('SONFileHeader') && exist('SONChanList') && exist('SONGetChannel')); - case '4D-VERSION' - status = (exist('read4d') && exist('read4dhdr')); - case 'SIGNAL' - status = hasfunction('medfilt1', toolbox); % also check the availability of a toolbox license - case 'OPTIM' - status = hasfunction('fmincon', toolbox) && hasfunction('fminunc', toolbox); % also check the availability of a toolbox license - case 'SPLINES' - status = hasfunction('bspline', toolbox) && hasfunction('csape', toolbox); % also check the availability of a toolbox license - case 'IMAGE' - status = hasfunction('bwlabeln', toolbox); % also check the availability of a toolbox license - case 'FASTICA' - status = exist('fastica', 'file'); - case 'BRAINSTORM' - status = exist('bem_xfer'); - case 'FILEIO' - status = (exist('read_header') && exist('read_data') && exist('read_event') && exist('read_sens')); - case 'FORWINV' - status = (exist('compute_leadfield') && exist('prepare_vol_sens')); - case 'DENOISE' - status = (exist('tsr') && exist('sns')); - case 'CTF' - status = (exist('getCTFBalanceCoefs') && exist('getCTFdata')); - case 'BCI2000' - status = exist('load_bcidat'); - case 'NLXNETCOM' - status = (exist('MatlabNetComClient') && exist('NlxConnectToServer') && exist('NlxGetNewCSCData')); - case 'DIPOLI' - status = exist('dipoli.m', 'file'); - case 'MNE' - status = (exist('fiff_read_meas_info', 'file') && exist('fiff_setup_read_raw', 'file')); - case 'TCP_UDP_IP' - status = (exist('pnet', 'file') && exist('pnet_getvar', 'file') && exist('pnet_putvar', 'file')); - case 'BEMCP' - status = (exist('bem_Cij_cog', 'file') && exist('bem_Cij_lin', 'file') && exist('bem_Cij_cst', 'file')); - case 'OPENMEEG' - status = exist('openmeeg.m', 'file'); - case 'PLOTTING' - status = (exist('plot_topo', 'file') && exist('plot_mesh', 'file') && exist('plot_matrix', 'file')); - case 'PRTOOLS' - status = (exist('prversion', 'file') && exist('dataset', 'file') && exist('svc', 'file')); - case 'LC-LIBS' - status = (exist('lcReadHeader', 'file') && exist('lcReadData', 'file')); - otherwise - if ~silent, warning(sprintf('cannot determine whether the %s toolbox is present', toolbox)); end - status = 0; -end - -% it should be a boolean value -status = (status~=0); - -% try to determine the path of the requested toolbox -if autoadd && ~status - - % for core fieldtrip modules - prefix = fileparts(which('preprocessing')); - if ~status - status = myaddpath(fullfile(prefix, lower(toolbox)), silent); - end - - % for external fieldtrip modules - prefix = fullfile(fileparts(which('preprocessing')), 'external'); - if ~status - status = myaddpath(fullfile(prefix, lower(toolbox)), silent); - end - - % for linux computers in the F.C. Donders Centre - prefix = '/home/common/matlab'; - if ~status && (strcmp(computer, 'GLNX86') || strcmp(computer, 'GLNXA64')) - status = myaddpath(fullfile(prefix, lower(toolbox)), silent); - end - - % for windows computers in the F.C. Donders Centre - prefix = 'h:\common\matlab'; - if ~status && (strcmp(computer, 'PCWIN') || strcmp(computer, 'PCWIN64')) - status = myaddpath(fullfile(prefix, lower(toolbox)), silent); - end - - % use the matlab subdirectory in your homedirectory, this works on unix and mac - prefix = [getenv('HOME') '/matlab']; - if ~status - status = myaddpath(fullfile(prefix, lower(toolbox)), silent); - end - - if ~status - % the toolbox is not on the path and cannot be added - sel = find(strcmp(url(:,1), toolbox)); - if ~isempty(sel) - msg = sprintf('the %s toolbox is not installed, %s', toolbox, url{sel, 2}); - else - msg = sprintf('the %s toolbox is not installed', toolbox); - end - error(msg); - end -end - -% this function is called many times in FieldTrip and associated toolboxes -% use efficient handling if the same toolbox has been investigated before -if status - previous.(fixname(toolbox)) = status; -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% helper function -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function status = myaddpath(toolbox, silent) -if exist(toolbox, 'dir') - if ~silent, warning(sprintf('adding %s toolbox to your Matlab path', toolbox)); end - addpath(toolbox); - status = 1; -else - status = 0; -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% helper function -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function out = fixname(toolbox) -out = lower(toolbox); -out(out=='-') = '_'; % fix dashes -out(out==' ') = '_'; % fix spaces - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% helper function -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function status = hasfunction(funname, toolbox) -try - % call the function without any input arguments, which probably is inapropriate - feval(funname); - % it might be that the function without any input already works fine - status = true; -catch - % either the function returned an error, or the function is not available - % availability is influenced by the function being present and by having a - % license for the function, i.e. in a concurrent licensing setting it might - % be that all toolbox licenses are in use - m = lasterror; - if strcmp(m.identifier, 'MATLAB:license:checkouterror') - if nargin>1 - warning('the %s toolbox is available, but you don''t have a license for it', toolbox); - else - warning('the function ''%s'' is available, but you don''t have a license for it', funname); - end - status = false; - elseif strcmp(m.identifier, 'MATLAB:UndefinedFunction') - status = false; - else - % the function seems to be available and it gave an unknown error, - % which is to be expected with inappropriate input arguments - status = true; - end -end - diff --git a/external/fieldtrip/private/head_surf.m b/external/fieldtrip/private/head_surf.m index b276dce..87640aa 100644 --- a/external/fieldtrip/private/head_surf.m +++ b/external/fieldtrip/private/head_surf.m @@ -7,8 +7,8 @@ % Use as % [pnt, tri] = head_surf(vol, grad, flag) % where -% grad gradiometer definition -% vol multisphere volume conductor definition +% grad gradiometer definition +% vol multisphere volume conductor definition % % If flag=1 the lower rim of the helmet-shaped head surface will % be shifted downward, if flag=0 it will not be shifted downward. @@ -20,31 +20,23 @@ % Copyright (C) Jan-Matthijs Schoffelen % -% $Log: head_surf.m,v $ -% Revision 1.7 2005/11/01 09:53:17 roboos -% added optional input argument 'flag', which determines whether the lower rim -% will be shifted downward +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.6 2005/09/29 00:37:33 roboos -% made the code independent of the gradiometer and volume label -% changed the shift of the lower rim, now with distance that is 1/4 of the radius -% updated the help +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.5 2004/01/26 09:03:12 roberto -% replaced complex 2x2D delaunay with single 3D convex hull triangulation -% better coverage of inferio-frontal region +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.4 2003/11/03 14:43:25 roberto -% included search for matching labels in volume and gradiometer -% -% Revision 1.3 2003/10/07 10:43:02 roberto -% head surface is now only computed from M channels and not reference channels -% -% Revision 1.2 2003/06/03 08:30:32 roberto -% *** empty log message *** -% -% Revision 1.1 2003/04/17 14:57:32 roberto +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: head_surf.m 952 2010-04-21 18:29:51Z roboos $ if nargin<3 flag = 1; diff --git a/external/fieldtrip/private/headcoordinates.m b/external/fieldtrip/private/headcoordinates.m index 6acea46..2269b01 100644 --- a/external/fieldtrip/private/headcoordinates.m +++ b/external/fieldtrip/private/headcoordinates.m @@ -33,10 +33,23 @@ % Copyright (C) 2003 Robert Oostenveld % -% $Log: headcoordinates.m,v $ -% Revision 1.1 2004/09/27 16:00:04 roboos -% initial submission +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: headcoordinates.m 952 2010-04-21 18:29:51Z roboos $ if nargin<4 flag=0; diff --git a/external/fieldtrip/private/headmodelplot.m b/external/fieldtrip/private/headmodelplot.m deleted file mode 100644 index 2218b7f..0000000 --- a/external/fieldtrip/private/headmodelplot.m +++ /dev/null @@ -1,525 +0,0 @@ -function [cfg] = headmodelplot(cfg, data) - -% HEADMODELPLOT makes a 3D visualisation of the volume conductor model -% and optionally of the gradiometer positions and headshape. It can -% be used for example to check CTF multiple-sphere head models. -% -% Use as -% headmodelplot(cfg) -% headmodelplot(cfg, data) -% -% You should specify the volume conductor model with -% cfg.hdmfile = string, file containing the volume conduction model -% or alternatively -% cfg.vol = structure with volume conduction model -% -% If the sensor information is not contained in the data itself you should -% also specify the sensor information using -% cfg.gradfile = string, file containing the gradiometer definition -% cfg.elecfile = string, file containing the electrode definition -% or alternatively -% cfg.grad = structure with gradiometer definition -% cfg.elec = structure with electrode definition -% -% The positions of the sources can be specified as a regular 3-D -% grid that is aligned with the axes of the head coordinate system -% cfg.grid.xgrid = vector (e.g. -20:1:20) or 'auto' (default = 'auto') -% cfg.grid.ygrid = vector (e.g. -20:1:20) or 'auto' (default = 'auto') -% cfg.grid.zgrid = vector (e.g. 0:1:20) or 'auto' (default = 'auto') -% cfg.grid.resolution = number (e.g. 1 cm) for automatic grid generation -% Alternatively the position of a few sources at locations of interest can -% be specified, for example obtained from an anatomical or functional MRI -% cfg.grid.pos = Nx3 matrix with position of each source -% cfg.grid.dim = [Nx Ny Nz] vector with dimensions in case of 3-D grid (optional) -% cfg.grid.inside = vector with indices of the sources inside the brain (optional) -% cfg.grid.outside = vector with indices of the sources outside the brain (optional) -% You can also use the PREPARE_LEADFIELD or SOURCEANALYSIS functions -% to create a grid with dipole positions. -% -% Other options are -% cfg.channel = cell-array, see CHANNELSELECTION -% cfg.spheremesh = number of vertices for spheres, either 42, 162 or 642 -% cfg.plotheadsurface = 'yes' or 'no', is constructed from head model -% cfg.plotbnd = 'yes' or 'no' -% cfg.plotspheres = 'yes' or 'no' -% cfg.plotspherecenter = 'yes' or 'no' -% cfg.plotgrid = 'yes' or 'no' -% cfg.plotinside = 'yes' or 'no' -% cfg.plotoutside = 'yes' or 'no' -% cfg.plotsensors = 'yes' or 'no' plot electrodes or gradiometers -% cfg.plotcoil = 'yes' or 'no' plot all gradiometer coils -% cfg.plotlines = 'yes' or 'no' plot lines from sensor to head surface -% cfg.surftype = 'edges'or 'faces' -% cfg.headshape = a filename containing headshape, a structure containing a -% single triangulated boundary, or a Nx3 matrix with surface -% points - -% Undocumented local options: -% cfg.surface_facecolor -% cfg.surface_edgecolor -% cfg.surface_facealpha -% -% This function depends on PREPARE_VOL_SENS which has the following options: -% cfg.channel, documented -% cfg.elec, documented -% cfg.elecfile, documented -% cfg.grad, documented -% cfg.gradfile, documented -% cfg.hdmfile, documented -% cfg.order -% cfg.vol, (default set in HEADMODELPLOT at cfg.vol =[]), documented - -% Copyright (C) 2004-2007, Robert Oostenveld -% -% $Log: headmodelplot.m,v $ -% Revision 1.30 2009/09/30 12:51:17 jansch -% included option to plot fiducials (as specified in cfg.fiducial) -% -% Revision 1.29 2009/05/18 16:00:33 roboos -% fixed problem with plotlines, changed output to cfg instead of vol+sens -% -% Revision 1.28 2009/05/14 19:20:39 roboos -% consistent handling of cfg.headshape in code and documentation -% -% Revision 1.27 2009/04/08 06:34:44 roboos -% use the new plot_sens function -% -% Revision 1.26 2009/03/30 17:55:17 vlalit -% Changed prepare_layout and headmodelplot to use channelposition. Changed the color -% of sensor markers in headmodelplot to green for consistency with SPM plots. -% -% Revision 1.25 2009/03/23 13:40:53 roboos -% some small changes suggested by Vladimir, use senstype instead of sensortype -% -% Revision 1.24 2009/01/07 14:19:26 roboos -% incorporated some suggestions from vladimir -% -% Revision 1.23 2008/10/02 15:32:20 sashae -% replaced call to createsubcfg with checkconfig -% -% Revision 1.22 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.21 2008/08/13 21:02:20 roboos -% use general read_headshape instead of specific subfunctions -% -% Revision 1.20 2008/07/15 19:53:23 roboos -% use grid subcfg, prevent recreation of grid if already fully specified -% -% Revision 1.19 2008/04/10 08:03:11 roboos -% renamed the fieldtrip/private/prepare_vol_sens function into prepare_headmodel -% -% Revision 1.18 2007/10/25 12:13:45 roboos -% make better determination of channel number for CTF gradiometer systems with broken channels -% -% Revision 1.17 2007/08/06 09:20:14 roboos -% added support for bti_hs -% -% Revision 1.16 2007/07/26 07:58:24 roboos -% also deal with cfg.headshape specified as surface, set of points or ctf_hs file (todo: add bti_hs) -% -% Revision 1.15 2007/07/26 07:07:08 roboos -% add empty inside and outside to empty sourcegrid -% -% Revision 1.14 2007/05/16 11:47:39 roboos -% added plotting of dipole grid, default for inside=yes and outside=no -% updated documentation -% -% Revision 1.13 2007/05/01 08:25:36 roboos -% fixed bug that was due to search-and-replace -% -% Revision 1.12 2006/10/04 08:19:42 roboos -% renamed megsystem into sensortype -% -% Revision 1.11 2006/07/24 07:59:16 roboos -% updated documentation -% -% Revision 1.10 2006/04/25 12:52:41 roboos -% added the facecolor and edgecolor options to the cfg as default -% -% Revision 1.9 2006/04/20 09:15:09 roboos -% updated documentation -% made color and opacity for the head surface externally available through cfg -% -% Revision 1.8 2006/04/10 16:33:46 ingnie -% updated documentation -% -% Revision 1.7 2005/12/14 10:44:23 roboos -% implemented support for EEG, spherical and BEM -% implemented support for single sphere in case of MEG -% fixed some incompatibilities in grad and vol structure for MEG -% removed cfg.plotheadshape, just look whether isempty(cfg.headshape) -% -% Revision 1.6 2005/11/24 16:26:07 roboos -% updated multisphere selection to reflect the current change in multisphere vol structure (no labels any more) -% -% Revision 1.5 2005/05/17 17:50:37 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.4 2004/08/19 07:22:49 roboos -% added cfg.plotspherecenter option -% -% Revision 1.3 2004/08/19 07:19:55 roboos -% added cfg.plotcoil option -% -% Revision 1.2 2004/08/06 12:37:25 roboos -% fixed minor bugs -% -% Revision 1.1 2004/08/06 08:55:23 roboos -% new implementation -% - -fieldtripdefs - -% these are suitable RGB colors -skin = [255 213 119]/255; -skull = [140 85 85]/255; -brain = [202 100 100]/255; -cortex = [255 213 119]/255; - -% set the defaults -if ~isfield(cfg, 'surface_facecolor'), cfg.surface_facecolor = skin; end -if ~isfield(cfg, 'surface_edgecolor'), cfg.surface_edgecolor = 'none'; end -if ~isfield(cfg, 'surface_facealpha'), cfg.surface_facealpha = 0.7; end -if ~isfield(cfg, 'surftype'), cfg.surftype = 'faces'; end - -% put the low-level options pertaining to the dipole grid in their own field -cfg = checkconfig(cfg, 'createsubcfg', {'grid'}); - -if ~isfield(cfg, 'vol') && ~isfield(cfg, 'hdmfile') - cfg.vol = []; % FIXME why is this empty setting neccessary? -end - -if nargin<2 - data = []; -end - -% set the defaults that apply both to EEG and MEG -if ~isfield(cfg, 'spheremesh'), cfg.spheremesh = 642; end -if ~isfield(cfg, 'plotsensors'), cfg.plotsensors = 'yes'; end -if ~isfield(cfg, 'plotheadsurface'), cfg.plotheadsurface = 'yes'; end -if ~isfield(cfg, 'plotgrid'), cfg.plotgrid = 'yes'; end -if ~isfield(cfg, 'plotinside'), cfg.plotinside = 'yes'; end -if ~isfield(cfg, 'plotoutside'), cfg.plotoutside = 'no'; end -if ~isfield(cfg, 'plotbnd'), cfg.plotbnd = 'no'; end -if ~isfield(cfg, 'plotfiducial'), cfg.plotfiducial = 'no'; end - -% extract/read the gradiometer and volume conductor -[vol, sens, cfg] = prepare_headmodel(cfg, data); - -if strcmp(cfg.plotgrid, 'yes') - if isfield(cfg.grid, 'pos') - % use the specified grid - sourcegrid.pos = cfg.grid.pos; - sourcegrid.inside = cfg.grid.inside; - sourcegrid.outside = cfg.grid.outside; - else - % construct the grid according to the configuration - sourcegrid = prepare_dipole_grid(cfg, vol, sens); - end -else - % construct an empty dipole grid - sourcegrid = []; - sourcegrid.pos = zeros(0,3); - sourcegrid.inside = []; - sourcegrid.outside = []; -end - -% determine the type of input data -ismeg = senstype(sens, 'meg'); -iseeg = senstype(sens, 'eeg'); -isbem = isfield(vol, 'bnd'); -issphere = isfield(vol, 'r'); -ismultisphere = isfield(vol, 'r') && length(vol.r)>4; -issinglesphere = isfield(vol, 'r') && length(vol.r)==1; -isconcentric = isfield(vol, 'r') && length(vol.r)<=4 && ~issinglesphere; - -if ismeg - % sensors describe MEG data, set the corresponding defaults - if ~isfield(cfg, 'plotspheres'), cfg.plotspheres = 'no'; end - if ~isfield(cfg, 'plotspherecenter'), cfg.plotspherecenter = 'no'; end - if ~isfield(cfg, 'plotlines'), cfg.plotlines = 'yes'; end - if ~isfield(cfg, 'plotcoil'), cfg.plotcoil = 'no'; end - if ~isfield(cfg, 'headshape'), cfg.headshape = []; end -elseif iseeg - % sensors describe EEG data, set the corresponding defaults - if ~isfield(cfg, 'plotspheres'), cfg.plotspheres = 'no'; end - if ~isfield(cfg, 'plotspherecenter'), cfg.plotspherecenter = 'no'; end - if ~isfield(cfg, 'plotlines'), cfg.plotlines = 'yes'; end -end - -chan = []; -[chan.pnt, chan.label] = channelposition(sens); - -if issphere - % determine the number of spheres in the volume model - Nspheres = length(vol.r); - fprintf('spherical head model with %d spheres\n', Nspheres); -end - -clf -hold on -axis equal -axis vis3d -if ismeg - axis off -else - axis on - grid on - xlabel('x') - ylabel('y') - zlabel('z') -end - -if iseeg - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % plotting for EEG - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - if strcmp(cfg.plotgrid, 'yes') - if strcmp(cfg.plotinside, 'yes') - plot3(sourcegrid.pos(sourcegrid.inside,1), sourcegrid.pos(sourcegrid.inside,2), sourcegrid.pos(sourcegrid.inside,3), 'k.'); - end - if strcmp(cfg.plotoutside, 'yes') - plot3(sourcegrid.pos(sourcegrid.outside,1), sourcegrid.pos(sourcegrid.outside,2), sourcegrid.pos(sourcegrid.outside,3), 'k.'); - end - end % plotgrid - - if strcmp(cfg.plotsensors, 'yes') - plot_sens(sens, 'style', 'g*'); - end % plotsensors - - if strcmp(cfg.plotheadsurface, 'yes') && ~isempty(vol) - [pnt, tri] = headsurface(vol, sens); - h = triplot(pnt, tri, [], cfg.surftype); - set(h, 'edgecolor', cfg.surface_edgecolor); - if strcmp(cfg.surftype, 'faces') - set(h, 'facecolor', cfg.surface_facecolor); - set(h, 'facealpha', cfg.surface_facealpha); - end - end % plotheadsurface - - if strcmp(cfg.plotspheres, 'yes') && ~isempty(vol) && issphere - % create a triangulated unit sphere - if cfg.spheremesh==42 - [pnt0, tri] = icosahedron42; - elseif cfg.spheremesh==162 - [pnt0, tri] = icosahedron162; - elseif cfg.spheremesh==642 - [pnt0, tri] = icosahedron642; - end - Nvertices = size(pnt0,1); - - colors = {cortex, brain, skull, skin}; - - for i=1:Nspheres - % scale and shift the unit sphere to the proper location - pnt = pnt0*vol.r(i) + repmat(vol.o, Nvertices,1); - - h = triplot(pnt, tri, [], cfg.surftype); - % set(h, 'FaceVertexCData', 0.5*ones(length(distance),30)); - % set(h, 'FaceVertexCData', [0 0 1]); - set(h, 'edgecolor', colors{i}) - % set(h, 'edgealpha', 1) - if strcmp(cfg.surftype, 'faces') - % set(h, 'AlphaDataMapping', 'direct'); - set(h, 'facealpha', 'interp') - % set(h, 'facealpha', 0) - set(h, 'facecolor', 'none'); - % set(h, 'linestyle', 'none'); - end - end - end % plotspheres - - if strcmp(cfg.plotbnd, 'yes') && ~isempty(vol) && isbem - - Nbnd = numel(vol.bnd); - - colors = {skin, skull, brain}; - - for i=1:Nbnd - h = triplot(vol.bnd(i).pnt, vol.bnd(i).tri, [], cfg.surftype); - % set(h, 'FaceVertexCData', 0.5*ones(length(distance),30)); - % set(h, 'FaceVertexCData', [0 0 1]); - set(h, 'edgecolor', colors{i}) - % set(h, 'edgealpha', 1) - if strcmp(cfg.surftype, 'faces') - % set(h, 'AlphaDataMapping', 'direct'); - set(h, 'facealpha', 'interp') - % set(h, 'facealpha', 0) - set(h, 'facecolor', 'none'); - % set(h, 'linestyle', 'none'); - end - end - end % plotbnd - - if strcmp(cfg.plotlines, 'yes') && ~isempty(vol) - if isbem - % project the electrodes on the skin surface, on the nearest triangle - [el] = project_elec(sens.pnt, vol.bnd(vol.skin).pnt, vol.bnd(vol.skin).tri); - % this returns [tri, la, mu] - tri = el(:,1); - la = el(:,2); - mu = el(:,3); - for i=1:Nsensors - v1 = vol.bnd(vol.skin).pnt(vol.bnd(vol.skin).tri(tri(i),1),:); - v2 = vol.bnd(vol.skin).pnt(vol.bnd(vol.skin).tri(tri(i),2),:); - v3 = vol.bnd(vol.skin).pnt(vol.bnd(vol.skin).tri(tri(i),3),:); - prj(i,:) = routlm(v1, v2, v3, la(i), mu(i)); - end - elseif issphere - % project the electrodes onto the sphere surface, towards the origin - nrm = sqrt(sum(sens.pnt.^2,2)); - prj = vol.r(vol.skin) * sens.pnt ./ [nrm nrm nrm]; - else - % in case that no known volume conductor is specified - prj = sens.pnt; - end - x = [sens.pnt(:,1) prj(:,1)]'; - y = [sens.pnt(:,2) prj(:,2)]'; - z = [sens.pnt(:,3) prj(:,3)]'; - line(x, y, z, 'color', 'm'); - end % plotlines - -elseif ismeg - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % plotting for MEG - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - if strcmp(cfg.plotgrid, 'yes') - if strcmp(cfg.plotinside, 'yes') - plot3(sourcegrid.pos(sourcegrid.inside,1), sourcegrid.pos(sourcegrid.inside,2), sourcegrid.pos(sourcegrid.inside,3), 'k.'); - end - if strcmp(cfg.plotoutside, 'yes') - plot3(sourcegrid.pos(sourcegrid.outside,1), sourcegrid.pos(sourcegrid.outside,2), sourcegrid.pos(sourcegrid.outside,3), 'k.'); - end - end % plotgrid - - if strcmp(cfg.plotsensors, 'yes') - plot_sens(sens, 'style', 'g*'); - end % plotsensors - - if strcmp(cfg.plotcoil, 'yes') - pnt = sens.pnt; - ori = sens.ori; - x = [pnt(:,1) pnt(:,1)+ori(:,1)]'; - y = [pnt(:,2) pnt(:,2)+ori(:,2)]'; - z = [pnt(:,3) pnt(:,3)+ori(:,3)]'; - line(x, y, z, 'color', 'g'); - plot3(pnt(:,1), pnt(:,2), pnt(:,3), 'g.'); - end % plotsensors - - if ~isempty(cfg.headshape) - % get the surface describing the head shape - if isstruct(cfg.headshape) && isfield(cfg.headshape, 'pnt') - % use the headshape surface specified in the configuration - headshape.pnt = cfg.headshape.pnt; - elseif isnumeric(cfg.headshape) && size(cfg.headshape,2)==3 - % use the headshape points specified in the configuration - headshape.pnt = cfg.headshape; - elseif ischar(cfg.headshape) - % read the headshape from file - headshape = read_headshape(cfg.headshape); - else - error('cfg.headshape is not specified correctly') - end - headshape.pnt = unique(headshape.pnt, 'rows'); - % the triangulation is not used inside this function - if isfield(headshape, 'tri') - headshape = rmfield(headshape, 'tri'); - end - plot3(headshape.pnt(:,1), headshape.pnt(:,2), headshape.pnt(:,3), 'r.'); - end % plotheadshape - - if strcmp(cfg.plotspheres, 'yes') && ~isempty(vol) && issphere - % create a triangulated unit sphere - if cfg.spheremesh==42 - [pnt0, tri] = icosahedron42; - elseif cfg.spheremesh==162 - [pnt0, tri] = icosahedron162; - elseif cfg.spheremesh==642 - [pnt0, tri] = icosahedron642; - end - Nvertices = size(pnt0,1); - for i=1:Nspheres - % scale and shift the unit sphere to the proper location - pnt = pnt0*vol.r(i) + repmat(vol.o(i,:),Nvertices,1); - if Nspheres>4 - distance = sqrt(sum((pnt - repmat(sens.pnt(i,:),Nvertices,1)).^2, 2)); - distance = (distance-min(distance))/range(distance); - else - distance = zeros(Nvertices, 1); - end - h = triplot(pnt, tri, [], cfg.surftype); - % set(h, 'FaceVertexCData', 0.5*ones(length(distance),30)); - % set(h, 'FaceVertexCData', [0 0 1]); - if strcmp(cfg.surftype, 'faces') - set(h, 'edgealpha', 'interp') - % set(h, 'edgealpha', 1) - set(h, 'FaceVertexAlphaData', (1-distance).*(distance<0.1)); - % set(h, 'AlphaDataMapping', 'direct'); - set(h, 'facealpha', 'interp') - % set(h, 'facealpha', 0) - set(h, 'facecolor', 'none'); - % set(h, 'linestyle', 'none'); - end - end - end % plotspheres - - if strcmp(cfg.plotbnd, 'yes') && ~isempty(vol) && isbem - - h = triplot(vol.bnd.pnt, vol.bnd.tri, [], cfg.surftype); - % set(h, 'FaceVertexCData', 0.5*ones(length(distance),30)); - % set(h, 'FaceVertexCData', [0 0 1]); - set(h, 'edgecolor', brain) - % set(h, 'edgealpha', 1) - if strcmp(cfg.surftype, 'faces') - % set(h, 'AlphaDataMapping', 'direct'); - set(h, 'facealpha', 'interp') - % set(h, 'facealpha', 0) - set(h, 'facecolor', 'none'); - % set(h, 'linestyle', 'none'); - end - - end % plotbnd - - if strcmp(cfg.plotspherecenter, 'yes') && ~isempty(vol) && issphere - plot3(vol.o(:,1), vol.o(:,2), vol.o(:,3), 'k.'); - end % plotspherecenter - - if strcmp(cfg.plotheadsurface, 'yes') && ~isempty(vol) - % estimate the head surface from the spheres and gradiometers - [pnt, tri] = headsurface(vol, sens); - h = triplot(pnt, tri, [], cfg.surftype); - set(h, 'edgecolor', cfg.surface_edgecolor); - if strcmp(cfg.surftype, 'faces') - set(h, 'facecolor', cfg.surface_facecolor); - set(h, 'facealpha', cfg.surface_facealpha); - end - end % plotheadsurface - - if strcmp(cfg.plotlines, 'yes') && ismultisphere - % first determine the indices of the relevant gradiometers. - [sel_g, sel_v] = match_str(chan.label, vol.label); - % create head-surface points from multisphere head-model. - dir = chan.pnt(sel_g,:) - vol.o(sel_v,:); - dist = sqrt(sum(dir.*dir,2)); - pnt0 = repmat((vol.r(sel_v)./dist),1,3).*dir + vol.o(sel_v,:); - pnt1 = chan.pnt(sel_g,:); - x = [pnt0(:,1) pnt1(:,1)]'; - y = [pnt0(:,2) pnt1(:,2)]'; - z = [pnt0(:,3) pnt1(:,3)]'; - line(x, y, z, 'color', 'm'); - end % plotlines - - if strcmp(cfg.plotfiducial, 'yes') && ~isempty(cfg.fiducial), - fiduc = cfg.fiducial; - plot3(fiduc(:,1), fiduc(:,2), fiduc(:,3), 'mo', 'lineWidth', 4); - end - -end % iseeg or ismeg - -lighting gouraud -camlight -hold off diff --git a/external/fieldtrip/private/headsurface.m b/external/fieldtrip/private/headsurface.m index 7a1811b..5aa50b2 100644 --- a/external/fieldtrip/private/headsurface.m +++ b/external/fieldtrip/private/headsurface.m @@ -20,37 +20,23 @@ % Copyright (C) 2005-2006, Robert Oostenveld % -% $Log: headsurface.m,v $ -% Revision 1.9 2009/05/14 19:24:51 roboos -% don't read the headshape from file, it should be externally read and passed as pnt/tri +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.8 2009/03/10 14:25:03 roboos -% use voltype function -% fixed bug for multisphere model when shifting lower rim down +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.7 2009/02/11 13:48:07 roboos -% prevent double vertices in the triangulations -% added a fixme comment for a particilar configuration that has problems +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.6 2007/05/16 12:02:57 roboos -% use a new subfunction for determining the surface orientation -% -% Revision 1.5 2007/05/08 07:35:24 roboos -% try to automatically correct the surface orientation -% -% Revision 1.4 2007/02/13 15:39:02 roboos -% fixed bug in inwardshift, it should be subtracted instead of added (the bug was causing an outwardshift for megrealign) -% -% Revision 1.3 2006/12/12 11:29:29 roboos -% moved projecttri subfunction into seperate function -% be flexible with headsurfaces specified as structure or filename/string -% -% Revision 1.2 2006/07/24 08:23:49 roboos -% removed default for inwardshift, apply inwardshift irrespective of surface type, improved documentation, some other small changes -% -% Revision 1.1 2005/12/13 16:28:34 roboos -% new implementation, should replace the head_surf function +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: headsurface.m 952 2010-04-21 18:29:51Z roboos $ if nargin<1 vol = []; @@ -135,7 +121,7 @@ pnt(:,3) = pnt(:,3) + origin(3); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif voltype(vol, 'multisphere') +elseif ft_voltype(vol, 'multisphere') % local spheres MEG model, this also requires a gradiometer structure grad = sens; if ~isfield(grad, 'tra') || ~isfield(grad, 'pnt') @@ -170,7 +156,7 @@ tri = projecttri(pnt); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif voltype(vol, 'bem') || voltype(vol, 'nolte') +elseif ft_voltype(vol, 'bem') || ft_voltype(vol, 'nolte') % volume conduction model with triangulated boundaries switch surface case 'skin' diff --git a/external/fieldtrip/private/highpassfilter.m b/external/fieldtrip/private/highpassfilter.m index b9e6513..1149381 100644 --- a/external/fieldtrip/private/highpassfilter.m +++ b/external/fieldtrip/private/highpassfilter.m @@ -25,28 +25,23 @@ % Copyright (c) 2003, Robert Oostenveld % -% $Log: highpassfilter.m,v $ -% Revision 1.6 2006/08/31 07:57:22 roboos -% implemented onepass-reverse filter: usefull for stimulus artifacts, e.g. TMS or electrical stimulation +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.5 2006/06/15 08:46:34 roboos -% fixed bug: added dir to input argument list +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.4 2006/06/14 12:36:20 roboos -% added the filter direction as additional option, default is 'twopass', i.e. using filtfilt +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.3 2004/02/11 08:55:13 roberto -% added optional fir1 filter (default still is butterworth), changed -% layout of code for better support of multiple optional arguments, -% extended documentation -% -% Revision 1.2 2003/06/12 08:40:44 roberto -% added variable option to determine filter order -% changed default order from 6 to 4 for notch and bandpass -% -% Revision 1.1 2003/04/04 09:53:37 roberto -% new implementation, using 6th order Butterworth FIR filter +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: highpassfilter.m 952 2010-04-21 18:29:51Z roboos $ % set the default filter order later if nargin<4 diff --git a/external/fieldtrip/private/icosahedron.m b/external/fieldtrip/private/icosahedron.m index 659d82a..a01ccae 100644 --- a/external/fieldtrip/private/icosahedron.m +++ b/external/fieldtrip/private/icosahedron.m @@ -9,16 +9,23 @@ % Copyright (C) 2002, Robert Oostenveld % -% $Log: icosahedron.m,v $ -% Revision 1.4 2006/07/26 11:03:38 roboos -% added "see also octahedron" +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.3 2003/03/11 15:35:20 roberto -% converted all files from DOS to UNIX +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.2 2003/03/04 21:46:18 roberto -% added CVS log entry and synchronized all copyright labels +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: icosahedron.m 952 2010-04-21 18:29:51Z roboos $ dhk = [ 1 2 3 @@ -48,7 +55,7 @@ rho=0.4*sqrt(5); phi=2*pi*(0:4)/5; -pnt( 1, :) = [0 0 1]; % top point +pnt( 1, :) = [0 0 1]; % top point pnt(2:6, 1) = rho*cos(phi)'; pnt(2:6, 2) = rho*sin(phi)'; @@ -58,5 +65,5 @@ pnt(7:11, 2) = rho*sin(phi - pi/5)'; pnt(7:11, 3) = -rho/2; -pnt(12, :) = [0 0 -1]; % bottom point +pnt(12, :) = [0 0 -1]; % bottom point diff --git a/external/fieldtrip/private/icosahedron162.m b/external/fieldtrip/private/icosahedron162.m index 45131cc..f589e87 100644 --- a/external/fieldtrip/private/icosahedron162.m +++ b/external/fieldtrip/private/icosahedron162.m @@ -4,13 +4,23 @@ % Copyright (C) 2003, Robert Oostenveld % -% $Log: icosahedron162.m,v $ -% Revision 1.3 2003/11/28 09:40:12 roberto -% added a single help line +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.2 2003/03/04 21:46:18 roberto -% added CVS log entry and synchronized all copyright labels +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: icosahedron162.m 952 2010-04-21 18:29:51Z roboos $ [pnt, dhk] = icosahedron; [pnt, dhk] = refine(pnt, dhk); diff --git a/external/fieldtrip/private/icosahedron2562.m b/external/fieldtrip/private/icosahedron2562.m index d9d2a1a..8bbee86 100644 --- a/external/fieldtrip/private/icosahedron2562.m +++ b/external/fieldtrip/private/icosahedron2562.m @@ -4,13 +4,23 @@ % Copyright (C) 2003, Robert Oostenveld % -% $Log: icosahedron2562.m,v $ -% Revision 1.3 2003/11/28 09:40:12 roberto -% added a single help line +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.2 2003/03/04 21:46:18 roberto -% added CVS log entry and synchronized all copyright labels +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: icosahedron2562.m 952 2010-04-21 18:29:51Z roboos $ [pnt, dhk] = icosahedron; [pnt, dhk] = refine(pnt, dhk); diff --git a/external/fieldtrip/private/icosahedron42.m b/external/fieldtrip/private/icosahedron42.m index 5af6f07..abc6c51 100644 --- a/external/fieldtrip/private/icosahedron42.m +++ b/external/fieldtrip/private/icosahedron42.m @@ -4,13 +4,23 @@ % Copyright (C) 2003, Robert Oostenveld % -% $Log: icosahedron42.m,v $ -% Revision 1.3 2003/11/28 09:40:12 roberto -% added a single help line +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.2 2003/03/04 21:46:18 roberto -% added CVS log entry and synchronized all copyright labels +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: icosahedron42.m 952 2010-04-21 18:29:51Z roboos $ [pnt, dhk] = icosahedron; [pnt, dhk] = refine(pnt, dhk); diff --git a/external/fieldtrip/private/icosahedron642.m b/external/fieldtrip/private/icosahedron642.m index 2a053fa..360de75 100644 --- a/external/fieldtrip/private/icosahedron642.m +++ b/external/fieldtrip/private/icosahedron642.m @@ -4,13 +4,23 @@ % Copyright (C) 2003, Robert Oostenveld % -% $Log: icosahedron642.m,v $ -% Revision 1.3 2003/11/28 09:40:12 roberto -% added a single help line +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.2 2003/03/04 21:46:19 roberto -% added CVS log entry and synchronized all copyright labels +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: icosahedron642.m 952 2010-04-21 18:29:51Z roboos $ [pnt, dhk] = icosahedron; [pnt, dhk] = refine(pnt, dhk); diff --git a/external/fieldtrip/private/inf_medium_leadfield.m b/external/fieldtrip/private/inf_medium_leadfield.m index 385276d..034c02b 100644 --- a/external/fieldtrip/private/inf_medium_leadfield.m +++ b/external/fieldtrip/private/inf_medium_leadfield.m @@ -7,22 +7,23 @@ % Copyright (C) 1998, Robert Oostenveld % -% $Log: inf_medium_leadfield.m,v $ -% Revision 1.1 2009/01/21 10:32:38 roboos -% moved from forwinv/* and forwinv/mex/* directory to forwinv/private/* to make the CVS layout consistent with the release version +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.5 2005/02/23 14:31:19 roboos -% changed the detection of Ndipoles, added reshaping of Nx3 input +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.4 2003/08/04 09:12:32 roberto -% added check for dipole on BEM model boundary, gives warning message +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.3 2003/06/03 08:29:26 roberto -% fixed error affecting multiple dipole computations -% -% Revision 1.2 2003/03/11 14:45:36 roberto -% updated help and copyrights +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: inf_medium_leadfield.m 946 2010-04-21 17:51:16Z roboos $ siz = size(rd); if any(siz==1) diff --git a/external/fieldtrip/private/inifile.m b/external/fieldtrip/private/inifile.m new file mode 100644 index 0000000..25c1fe5 --- /dev/null +++ b/external/fieldtrip/private/inifile.m @@ -0,0 +1,675 @@ +function readsett = inifile(fileName,operation,keys,style) +%readsett = INIFILE(fileName,operation,keys,style) +% Creates, reads, or writes data from/to ini (ascii) file. +% +% - fileName: ini file name +% - operation: can be one of the following: +% 'new' (rewrites an existing or creates a new, empty file), +% 'deletekeys'(deletes keys and their values - if they exist), +% 'read' (reads values as strings), +% 'write' (writes values given as strings), +% - keys: cell array of STRINGS; max 5 columns, min +% 3 columns. Each row has the same number of columns. The columns are: +% 'section': section name string (the root is considered if empty or not given) +% 'subsection': subsection name string (the root is considered if empty or not given) +% 'key': name of the field to write/read from (given as a string). +% 'value': (optional) string-value to write to the ini file in case of 'write' operation +% 'defaultValue': (optional) value that is returned when the key is not found when reading ('read' operation) +% - style: 'tabbed' writes sections, subsections and keys in a tabbed style +% to get a more readable file. The 'plain' style is the +% default style. This only affects the keys that will be written/rewritten. +% +% - readsett: read setting in the case of the 'read' operation. If +% the keys are not found, the default values are returned +% as strings (if given in the 5-th column). +% +% EXAMPLE: +% Suppose we want a new ini file, test1.ini with 3 fields. +% We can write them into the file using: +% +% inifile('test1.ini','new'); +% writeKeys = {'measurement','person','name','Primoz Cermelj';... +% 'measurement','protocol','id','1';... +% 'application','','description','some...'}; +% inifile('test1.ini','write',writeKeys,'plain'); +% +% Later, you can read them out. Additionally, if any of them won't +% exist, a default value will be returned (if the 5-th column is given as below). +% +% readKeys = {'measurement','person','name','','John Doe';... +% 'measurement','protocol','id','','0';... +% 'application','','description','','none'}; +% readSett = inifile('test1.ini','read',readKeys); +% +% +% NOTES: When the operation is 'new', only the first 2 parameters are +% required. If the operation is 'write' and the file is empty or does not exist, +% a new file is created. When writing and if any of the section or subsection or key does not exist, +% it creates (adds) a new one. +% Everything but value is NOT case sensitive. Given keys and values +% will be trimmed (leading and trailing spaces will be removed). +% Any duplicates (section, subsection, and keys) are ignored. Empty section and/or +% subsection can be given as an empty string, '', but NOT as an empty matrix, []. +% +% This function was tested on the win32 platform only but it should +% also work on Unix/Linux platforms. Since some short-circuit operators +% are used, at least Matlab 6.5 should be used. + +% +% FREE SOFTWARE - please refer the source +% Copyright (c) 2003 by Primoz Cermelj +% First release on 29.01.2003 +% Primoz Cermelj, Slovenia +% Contact: primoz.cermelj@email.si +% Download location: http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=2976&objectType=file +% +% Version: 1.1.0 +% Last revision: 04.02.2004 +% +% Bug reports, questions, etc. can be sent to the e-mail given above. +% +% This programme is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or any later version. +% +% This programme is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +%-------------------------------------------------------------------------- + +%---------------- +% INIFILE history +%---------------- +% +% [v.1.1.0] 04.02.2004 +% - FIX: 'writetext' option removed (there was a bug previously) +% +% [v.1.01b] 19.12.2003 +% - NEW: A new concept - multiple keys can now be read, written, or deleted +% ALL AT ONCE which makes this function much faster. For example, to +% write 1000 keys, using previous versions it took 157 seconds on a +% 1.5 GHz machine, with this new version it took only 1.83 seconds. +% In general, the speed improvement is greater when larger number of +% read/written keys are considered. +% - NEW: The format of the input parameters has changed. See above. +% +% [v.0.97] 19.11.2003 +% - NEW: Additional m-function, strtrim, is no longer needed +% +% [v.0.96] 16.10.2003 +% - FIX: Detects empty keys +% +% [v.0.95] 04.07.2003 +% - NEW: 'deletekey' option/operation added +% - FIX: A major file refinement to obtain a more compact utility -> additional operations can "easily" be implemented +% +% [v.0.91-0.94] +% - FIX: Some minor refinements +% +% [v.0.90] 29.01.2003 +% - NEW: First release of this tool +% +%---------------- + +global NL_CHAR; + +% Checks the input arguments +if nargin < 2 + error('Not enough input arguments'); +end +if (strcmpi(operation,'read')) | (strcmpi(operation,'deletekeys')) + if nargin < 3 + error('Not enough input arguments.'); + end + if ~exist(fileName) + error(['File ' fileName ' does not exist.']); + end + [m,n] = size(keys); + if n > 5 + error('Keys argument has too many columns'); + end + for ii=1:m + if isempty(keys(ii,3)) | ~ischar(keys{ii,3}) + error('Empty or non-char keys are not allowed.'); + end + end +elseif (strcmpi(operation,'write')) | (strcmpi(operation,'writetext')) + if nargin < 3 + error('Not enough input arguments'); + end + [m,n] = size(keys); + for ii=1:m + if isempty(keys(ii,3)) | ~ischar(keys{ii,3}) + error('Empty or non-char keys are not allowed.'); + end + end +elseif (~strcmpi(operation,'new')) + error(['Unknown inifile operation: ''' operation '''']); +end +if nargin >= 3 + for ii=1:m + for jj=1:n + if ~ischar(keys{ii,jj}) + error('All cells from keys must be given as strings, even the empty ones.'); + end + end + end +end +if nargin < 4 || isempty(style) + style = 'plain'; +else + if ~(strcmpi(style,'plain') | strcmpi(style,'tabbed')) | ~ischar(style) + error('Unsupported style given or style not given as a string'); + end +end + +% Sets new-line character (string) +if ispc + NL_CHAR = '\r\n'; +else + NL_CHAR = '\n'; +end + + +%---------------------------- +% CREATES a new, empty file (rewrites an existing one) +%---------------------------- +if strcmpi(operation,'new') + fh = fopen(fileName,'w'); + if fh == -1 + error(['File: ''' fileName ''' can not be (re)created']); + end + fclose(fh); + return + +%---------------------------- +% READS key-value pairs out +%---------------------------- +elseif (strcmpi(operation,'read')) + if n < 5 + defaultValues = cellstrings(m,1); + else + defaultValues = keys(:,5); + end + readsett = defaultValues; + keysIn = keys(:,1:3); + [secsExist,subsecsExist,keysExist,readValues,so,eo] = findkeys(fileName,keysIn); + ind = find(keysExist); + if ~isempty(ind) + readsett(ind) = readValues(ind); + end + return + +%---------------------------- +% WRITES key-value pairs to an existing or non-existing +% file (file can even be empty) +%---------------------------- +elseif (strcmpi(operation,'write')) + if m < 1 + error('At least one key is needed when writing keys'); + end + if ~exist(fileName) + inifile(fileName,'new'); + end + writekeys(fileName,keys,style); + return + +%---------------------------- +% DELETES key-value pairs out +%---------------------------- +elseif (strcmpi(operation,'deletekeys')) + deletekeys(fileName,keys); + + + +else + error('Unknown operation for INIFILE.'); +end + + + + +%-------------------------------------------------- +%%%%%%%%%%%%% SUBFUNCTIONS SECTION %%%%%%%%%%%%%%%% +%-------------------------------------------------- + + +%------------------------------------ +function [secsExist,subSecsExist,keysExist,values,startOffsets,endOffsets] = findkeys(fileName,keysIn) +% This function parses ini file for keys as given by keysIn. keysIn is a cell +% array of strings having 3 columns; section, subsection and key in each row. +% section and/or subsection can be empty (root section or root subsection) +% but the key can not be empty. The startOffsets and endOffsets are start and +% end bytes that each key occuppies, respectively. If any of the keys doesn't exist, +% startOffset and endOffset for this key are the same. A special case is +% when the key that doesn't exist also corresponds to a non-existing +% section and non-existing subsection. In such a case, the startOffset and +% endOffset have values of -1. + +nKeys = size(keysIn,1); % number of keys +nKeysLocated = 0; % number of keys located +secsExist = zeros(nKeys,1); % if section exists (and is non-empty) +subSecsExist = zeros(nKeys,1); % if subsection... +keysExist = zeros(nKeys,1); % if key that we are looking for exists +keysLocated = keysExist; % if the key's position (existing or non-existing) is LOCATED +values = cellstrings(nKeys,1); % read values of keys (strings) +startOffsets = -ones(nKeys,1); % start byte-position of the keys +endOffsets = -ones(nKeys,1); % end byte-position of the keys + +keyInd = find(strcmpi(keysIn(:,1),'')); % key indices having [] section (root section) + +line = []; +currSection = ''; +currSubSection = ''; + +fh = fopen(fileName,'r'); +if fh == -1 + error(['File: ''' fileName ''' does not exist or can not be opened.']); +end + +try + %--- Searching for the keys - their values and start and end locations in bytes + while 1 + + pos1 = ftell(fh); + line = fgetl(fh); + if line == -1 % end of file, exit + line = []; + break + end + [status,readValue,readKey] = processiniline(line); + if (status == 1) % (new) section found + % Keys that were found as belonging to any previous section + % are now assumed as located (because another + % section is found here which could even be a repeated one) + keyInd = find( ~keysLocated & strcmpi(keysIn(:,1),currSection) ); + if length(keyInd) + keysLocated(keyInd) = 1; + nKeysLocated = nKeysLocated + length(keyInd); + end + currSection = readValue; + currSubSection = ''; + % Indices to non-located keys belonging to current section + keyInd = find( ~keysLocated & strcmpi(keysIn(:,1),currSection) ); + if ~isempty(keyInd) + secsExist(keyInd) = 1; + end + pos2 = ftell(fh); + startOffsets(keyInd) = pos2+1; + endOffsets(keyInd) = pos2+1; + elseif (status == 2) % (new) subsection found + % Keys that were found as belonging to any PREVIOUS section + % and/or subsection are now assumed as located (because another + % subsection is found here which could even be a repeated one) + keyInd = find( ~keysLocated & strcmpi(keysIn(:,1),currSection) & ~keysLocated & strcmpi(keysIn(:,2),currSubSection)); + if length(keyInd) + keysLocated(keyInd) = 1; + nKeysLocated = nKeysLocated + length(keyInd); + end + currSubSection = readValue; + % Indices to non-located keys belonging to current section and subsection at the same time + keyInd = find( ~keysLocated & strcmpi(keysIn(:,1),currSection) & ~keysLocated & strcmpi(keysIn(:,2),currSubSection)); + if ~isempty(keyInd) + subSecsExist(keyInd) = 1; + end + pos2 = ftell(fh); + startOffsets(keyInd) = pos2+1; + endOffsets(keyInd) = pos2+1; + elseif (status == 3) % key found + if isempty(keyInd) + continue % no keys from 'keys' - from section-subsection par currently in + end + currKey = readValue; + pos2 = ftell(fh); % the last-byte position of the read key - the total sum of chars read so far + for ii=1:length(keyInd) + if strcmpi( keysIn(keyInd(ii),3),readKey ) & ~keysLocated(keyInd(ii)) + keysExist(keyInd(ii)) = 1; + startOffsets(keyInd(ii)) = pos1+1; + endOffsets(keyInd(ii)) = pos2; + values{keyInd(ii)} = currKey; + keysLocated(keyInd(ii)) = 1; + nKeysLocated = nKeysLocated + 1; + else + if ~keysLocated(keyInd(ii)) + startOffsets(keyInd(ii)) = pos2+1; + endOffsets(keyInd(ii)) = pos2+1; + end + end + end + if nKeysLocated >= nKeys % if all the keys are located + break + end + else + % general text found (even empty line(s)) + end + %--- End searching + end + fclose(fh); +catch + fclose(fh); + error(['Error parsing the file for keys: ' fileName ': ' lasterr]); +end +%------------------------------------ + + + + +%------------------------------------ +function writekeys(fileName,keys,style) +% Writes keys to the section and subsection pair +% If any of the keys doesn't exist, a new key is added to +% the end of the section-subsection pair otherwise the key is updated (changed). +% Keys is a 4-column cell array of strings. + +global NL_CHAR; + +RETURN = sprintf('\r'); +NEWLINE = sprintf('\n'); + +[m,n] = size(keys); +if n < 4 + error('Keys to be written are given in an invalid format.'); +end + +% Get keys position first using findkeys +keysIn = keys; +[secsExist,subSecsExist,keysExist,readValues,so,eo] = findkeys(fileName,keys(:,1:3)); + +% Read the whole file's contents out +fh = fopen(fileName,'r'); +if fh == -1 + error(['File: ''' fileName ''' does not exist or can not be opened.']); +end +try + dataout = fscanf(fh,'%c'); +catch + fclose(fh); + error(lasterr); +end +fclose(fh); + +%--- Rewriting the file -> writing the refined contents +fh = fopen(fileName,'w'); +if fh == -1 + error(['File: ''' fileName ''' does not exist or can not be opened.']); +end +try + tab1 = []; + if strcmpi(style,'tabbed') + tab1 = sprintf('\t'); + end + % Proper sorting of keys is cruical at this point in order to avoid + % inproper key-writing. + + % Find keys with -1 offsets - keys with non-existing section AND + % subsection - keys that will be added to the end of the file + fs = length(dataout); % file size in bytes + nAddedKeys = 0; + ind = find(so==-1); + if ~isempty(ind) + so(ind) = (fs+10); % make sure these keys will come to the end when sorting + eo(ind) = (fs+10); + nAddedKeys = length(ind); + end + + % Sort keys according to start- and end-offsets + [dummy,ind] = sort(so,1); + so = so(ind); + eo = eo(ind); + keysIn = keysIn(ind,:); + keysExist = keysExist(ind); + secsExist = secsExist(ind); + subSecsExist = subSecsExist(ind); + readValues = readValues(ind); + values = keysIn(:,4); + + % Find keys with equal start offset (so) and additionally sort them + % (locally). These are non-existing keys, including the ones whose + % section and subsection will also be added. + nKeys = size(so,1); + fullInd = 1:nKeys; + ii = 1; + while ii < nKeys + ind = find(so==so(ii)); + if ~isempty(ind) && length(ind) > 1 + n = length(ind); + from = ind(1); + to = ind(end); + tmpKeys = keysIn( ind,: ); + [tmpKeys,ind2] = sortrows( lower(tmpKeys) ); + fullInd(from:to) = ind(ind2); + ii = ii + n; + else + ii = ii + 1; + end + end + + % Final (re)sorting + so = so(fullInd); + eo = eo(fullInd); + keysIn = keysIn(fullInd,:); + keysExist = keysExist(fullInd); + secsExist = secsExist(fullInd); + subSecsExist = subSecsExist(fullInd); + readValues = readValues(fullInd); + values = keysIn(:,4); + + % Refined data - datain + datain = []; + + for ii=1:nKeys % go through all the keys, existing and non-existing ones + if ii==1 + from = 1; % from byte-offset of original data (dataout) + else + from = eo(ii-1); + if keysExist(ii-1) + from = from + 1; + end + end + to = min(so(ii)-1,fs); % to byte-offset of original data (dataout) + + if ~isempty(dataout) + datain = [datain dataout(from:to)]; % the lines before the key + end + + if length(datain) & (~(datain(end)==RETURN | datain(end)==NEWLINE)) + datain = [datain, sprintf(NL_CHAR)]; + end + + tab = []; + if ~keysExist(ii) + if ~secsExist(ii) && ~isempty(keysIn(ii,1)) + if ~isempty(keysIn{ii,1}) + datain = [datain sprintf(['%s' NL_CHAR],['[' keysIn{ii,1} ']'])]; + end + % Key-indices with the same section as this, ii-th key (even empty sections are considered) + ind = find( strcmpi( keysIn(:,1), keysIn(ii,1)) ); + % This section exists at all keys corresponding to the same section from know on (even the empty ones) + secsExist(ind) = 1; + end + if ~subSecsExist(ii) && ~isempty(keysIn(ii,2)) + if ~isempty( keysIn{ii,2}) + if secsExist(ii); tab = tab1; end; + datain = [datain sprintf(['%s' NL_CHAR],[tab '{' keysIn{ii,2} '}'])]; + end + % Key-indices with the same section AND subsection as this, ii-th key (even empty sections and subsections are considered) + ind = find( strcmpi( keysIn(:,1), keysIn(ii,1)) & strcmpi( keysIn(:,2), keysIn(ii,2)) ); + % This subsection exists at all keys corresponding to the same section and subsection from know on (even the empty ones) + subSecsExist(ind) = 1; + end + end + if secsExist(ii) & (~isempty(keysIn{ii,1})); tab = tab1; end; + if subSecsExist(ii) & (~isempty(keysIn{ii,2})); tab = [tab tab1]; end; + datain = [datain sprintf(['%s' NL_CHAR],[tab keysIn{ii,3} ' = ' values{ii}])]; + end + from = eo(ii); + if keysExist(ii) + from = from + 1; + end + to = length(dataout); + if from < to + datain = [datain dataout(from:to)]; + end + fprintf(fh,'%c',datain); +catch + fclose(fh); + error(['Error writing keys to file: ''' fileName ''' : ' lasterr]); +end +fclose(fh); +%------------------------------------ + + + +%------------------------------------ +function deletekeys(fileName,keys) +% Deletes keys and their values out; keys must have at least 3 columns: +% section, subsection, and key + +[m,n] = size(keys); +if n < 3 + error('Keys to be deleted are given in an invalid format.'); +end + +% Get keys position first +keysIn = keys; +[secsExist,subSecsExist,keysExist,readValues,so,eo] = findkeys(fileName,keys(:,1:3)); + +% Read the whole file's contents out +fh = fopen(fileName,'r'); +if fh == -1 + error(['File: ''' fileName ''' does not exist or can not be opened.']); +end +try + dataout = fscanf(fh,'%c'); +catch + fclose(fh); + error(lasterr); +end +fclose(fh); + +%--- Rewriting the file -> writing the refined contents +fh = fopen(fileName,'w'); +if fh == -1 + error(['File: ''' fileName ''' does not exist or can not be opened.']); +end +try + ind = find(keysExist); + nExistingKeys = length(ind); + datain = dataout; + + if nExistingKeys + % Filtering - retain only the existing keys... + fs = length(dataout); % file size in bytes + so = so(ind); + eo = eo(ind); + keysIn = keysIn(ind,:); + % ...and sorting + [so,ind] = sort(so); + eo = eo(ind); + keysIn = keysIn(ind,:); + + % Refined data - datain + datain = []; + + for ii=1:nExistingKeys % go through all the existing keys + if ii==1 + from = 1; % from byte-offset of original data (dataout) + else + from = eo(ii-1)+1; + end + to = so(ii)-1; % to byte-offset of original data (dataout) + + if ~isempty(dataout) + datain = [datain dataout(from:to)]; % the lines before the key + end + end + from = eo(ii)+1; + to = length(dataout); + if from < to + datain = [datain dataout(from:to)]; + end + end + + fprintf(fh,'%c',datain); +catch + fclose(fh); + error(['Error deleting keys from file: ''' fileName ''' : ' lasterr]); +end +fclose(fh); +%------------------------------------ + + + + +%------------------------------------ +function [status,value,key] = processiniline(line) +% Processes a line read from the ini file and +% returns the following values: +% - status: 0 => empty line or unknown string +% 1 => section found +% 2 => subsection found +% 3 => key-value pair found +% - value: value-string of a key, section, or subsection +% - key: key-string + +status = 0; +value = []; +key = []; +line = strim(line); % removes any leading and trailing spaces +if isempty(line) % empty line + return +end +if (line(1) == '[') & (line(end) == ']')... % section found + & (length(line) >= 3) + value = lower(line(2:end-1)); + status = 1; +elseif (line(1) == '{') &... % subsection found + (line(end) == '}') & (length(line) >= 3) + value = lower(line(2:end-1)); + status = 2; +else + pos = findstr(line,'='); + if ~isempty(pos) % key-value pair found + status = 3; + key = lower(line(1:pos-1)); + value = line(pos+1:end); + key = strim(key); % removes any leading and trailing spaces + value = strim(value); % removes any leading and trailing spaces + if isempty(key) % empty keys are not allowed + status = 0; + key = []; + value = []; + end + end +end +%------------------------------------ + + +%------------------------------------ +function outstr = strim(str) +% Removes leading and trailing spaces (spaces, tabs, endlines,...) +% from the str string. +if isnumeric(str); + outstr = str; + return +end +ind = find( ~isspace(str) ); % indices of the non-space characters in the str +if isempty(ind) + outstr = []; +else + outstr = str( ind(1):ind(end) ); +end + + + +%------------------------------------ +function cs = cellstrings(m,n) +% Creates a m x n cell array of empty strings - '' +cs = cell(m,n); +for ii=1:m + for jj=1:n + cs{ii,jj} = ''; + end +end diff --git a/external/fieldtrip/private/inputlabel2outputlabel.m b/external/fieldtrip/private/inputlabel2outputlabel.m index 8ac1802..e4cdc69 100644 --- a/external/fieldtrip/private/inputlabel2outputlabel.m +++ b/external/fieldtrip/private/inputlabel2outputlabel.m @@ -10,16 +10,23 @@ % 'pseudomeg' one gradiometer versus the rest % TODO: more flexible way of combining, e.g. by providing a cell-array -% $Log: inputlabel2outputlabel.m,v $ -% Revision 1.3 2009/10/01 12:43:36 jansch -% allowing for single missing dV or dH channels +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.2 2006/06/23 10:51:02 jansch -% changed format of outputlabel +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.1 2005/08/15 15:16:19 jansch -% First implementation. Moved out of freqdescriptives.m +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: inputlabel2outputlabel.m 952 2010-04-21 18:29:51Z roboos $ if ~isfield(cfg, 'combinechan'), cfg.combinechan = 'no'; end; diff --git a/external/fieldtrip/private/inside_vol.m b/external/fieldtrip/private/inside_vol.m deleted file mode 100644 index 99007d8..0000000 --- a/external/fieldtrip/private/inside_vol.m +++ /dev/null @@ -1,138 +0,0 @@ -function [inside] = inside_vol(pos, vol) - -% INSIDE_VOL locates dipole locations inside/outside the source -% compartment of a volume conductor model. -% -% [inside] = inside_vol(pos, vol, ...) -% -% where the input should be -% pos Nx3 matrix with dipole positions -% vol structure with volume conductor model -% and the output is -% inside list of dipoles inside the brain compartment -% (1=inside, 0=outisde) -% -% Additional optional input arguments shoudl be given in key value pairs -% and can include -% - -% Copyright (C) 2003-2007, Robert Oostenveld -% -% $Log: inside_vol.m,v $ -% Revision 1.5 2009/02/05 10:20:35 roboos -% added bemcp as volume type -% -% Revision 1.4 2009/01/21 11:15:57 roboos -% moved function back from forwinv/private into public section, because it is part of the public API -% -% Revision 1.1 2009/01/21 10:46:10 roboos -% moved from forwinv/* and forwinv/mex/* directory to forwinv/private/* to make the CVS layout consistent with the release version -% -% Revision 1.2 2008/09/29 12:04:41 roboos -% use logical (built-in) instead of boolean (simulink) -% -% Revision 1.1 2008/09/20 13:41:35 roboos -% moved content of find_inside_vol to new inside_vol function with slightly different interface -% added wrapper for spm -% -% -% %%% -% Switch from find_inside_vol.m to inside_vol.m -% 2008/09/09 chrisp -% %%% -% -% Revision 1.7 2008/04/15 20:36:21 roboos -% added explicit handling of various BEM implementations, i.e. for all -% voltype variants -% -% Revision 1.6 2007/07/25 08:34:05 roboos -% switched to using voltype helper function -% also support N-shell concentric sphere model -% changed detection for single and concentric sphere model, now explicitely -% using distance and source compartment -% -% Revision 1.5 2004/09/06 08:46:27 roboos -% moved reading of neuromag BEM boundary into fieldtrip's prepare_vol_sens -% -% Revision 1.4 2004/09/03 09:07:17 roboos -% added support for finding dipoles in neuromag BEM model -% -% Revision 1.3 2003/08/04 09:19:30 roberto -% fixed bug for dipole on BEM volume boundary -% -% Revision 1.2 2003/03/24 12:30:06 roberto -% added support for multi-sphere volume conductor model -% - -% determine the type of volume conduction model -switch voltype(vol) - - % single-sphere or multiple concentric spheres - case {'singlesphere' 'concentric'} - if ~isfield(vol, 'source') - % locate the innermost compartment and remember it - [dum, vol.source] = min(vol.r); - end - if isfield(vol, 'o') - % shift dipole positions toward origin of sphere - tmp = pos - repmat(vol.o, size(pos,1), 1); - else - tmp = pos; - end - distance = sqrt(sum(tmp.^2, 2))-vol.r(vol.source); - % positive if outside, negative if inside - inside = distance<0; - - % multi-sphere volume conductor model - case 'multisphere' - - % nspheres = size(vol.r,1); - % ndipoles = size(pos,1); - % inside = zeros(ndipoles,1); - % for sph=1:nspheres - % for dip=1:ndipoles - % if inside(dip) - % % the dipole has already been detected in one of the other spheres - % continue - % end - % inside(dip) = (norm(pos(dip,:) - vol.o(sph,:)) <= vol.r(sph)); - % end - % end - % outside = find(inside==0); - % inside = find(inside==1); - - % this is a much faster implementation - nspheres = size(vol.r,1); - ndipoles = size(pos,1); - inside = zeros(ndipoles,1); - for sph=1:nspheres - % temporary shift dipole positions toward origin - if isfield(vol, 'o') - tmp = pos - repmat(vol.o(sph,:), [ndipoles 1]); - else - tmp = pos; - end - flag = (sqrt(sum(tmp.^2,2)) <= vol.r(sph)); - inside = inside + flag; - end - inside = inside>0; - - % realistic BEM volume conductor model - case {'bem', 'dipoli', 'bemcp', 'asa', 'avo', 'nolte', 'neuromag'} - if ~isfield(vol, 'source') - % locate the innermost compartment and remember it - vol.source = find_innermost_boundary(vol.bnd); - end - % use the specified source compartment - pnt = vol.bnd(vol.source).pnt; - tri = vol.bnd(vol.source).tri; - % determine the dipole positions that are inside the brain compartment - inside = bounding_mesh(pos, pnt, tri); - - % unrecognized volume conductor model - otherwise - error('unrecognized volume conductor model'); -end - -% ensure that these are column vectors -inside = logical(inside(:)); diff --git a/external/fieldtrip/private/interactiverealign.m b/external/fieldtrip/private/interactiverealign.m deleted file mode 100644 index b508fa1..0000000 --- a/external/fieldtrip/private/interactiverealign.m +++ /dev/null @@ -1,457 +0,0 @@ -function cfg = interactiverealign(cfg) - -% INTERACTIVEREALIGN interactively rotates, scales and translates -% electrode positions to template electrode positions or towards -% the head surface. -% -% Use as -% [cfg] = interactiverealign(cfg) -% -% Required configuration options: -% cfg.individual.vol -% cfg.individual.elec -% cfg.individual.grad -% cfg.individual.headshape -% cfg.individual.headshapestyle = 'vertex' (default), 'surface' or 'both' -% cfg.individual.volstyle = 'edge' (default), 'surface' or 'both' -% -% cfg.template.vol -% cfg.template.elec -% cfg.template.grad -% cfg.template.headshape -% cfg.template.headshapestyle = 'surface' (default), 'vertex' or 'both' -% cfg.individual.volstyle = 'surface' (default), 'edge' or 'both' -% -% See also VOLUMEREALIGN, ELECTRODEREALIGN, READ_SENS, READ_VOL, READ_HEADSHAPE - -% Copyright (C) 2008, Vladimir Litvak -% -% $Log: interactiverealign.m,v $ -% Revision 1.8 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.7 2009/01/16 17:21:20 sashae -% added config tracking -% -% Revision 1.6 2008/11/25 14:35:04 estmee -% Documentation update -% -% Revision 1.5 2008/10/10 14:43:58 sashae -% added call to checkconfig -% -% Revision 1.4 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.3 2008/07/01 19:05:23 roboos -% Vladimir fixed some bugs -% -% Revision 1.2 2008/06/25 09:21:38 roboos -% various changes -% -% Revision 1.1 2008/06/24 13:51:15 roboos -% initial version from Vladimir with some minor changes -% - -fieldtripdefs - -% check if the input cfg is valid for this function -cfg = checkconfig(cfg, 'trackconfig', 'on'); -cfg = checkconfig(cfg, 'required', {'individual', 'template'}); - -if ~isfield(cfg.individual, 'vol'), cfg.individual.vol = []; end -if ~isfield(cfg.individual, 'elec'), cfg.individual.elec = []; end -if ~isfield(cfg.individual, 'grad'), cfg.individual.grad = []; end -if ~isfield(cfg.individual, 'headshape'), cfg.individual.headshape = []; end -if ~isfield(cfg.individual, 'headshapestyle'), cfg.individual.headshapestyle = 'vertex'; end -if ~isfield(cfg.individual, 'volstyle'), cfg.individual.volstyle = 'edge'; end - -if ~isfield(cfg.template, 'vol'), cfg.template.vol = []; end -if ~isfield(cfg.template, 'elec'), cfg.template.elec = []; end -if ~isfield(cfg.template, 'grad'), cfg.template.grad = []; end -if ~isfield(cfg.template, 'headshape'), cfg.template.headshape = []; end -if ~isfield(cfg.template, 'headshapestyle'), cfg.template.headshapestyle = 'surface'; end -if ~isfield(cfg.template, 'volstyle'), cfg.template.volstyle = 'surface'; end - -template = cfg.template; -individual = cfg.individual; - -if ~isempty(template.headshape) - if ~isfield(template.headshape, 'tri') || isempty(template.headshape.tri) - template.headshape.tri = projecttri(template.headshape.pnt); - end -end - -if ~isempty(individual.headshape) && isfield(individual.headshape, 'pnt') && ... - ~isempty(individual.headshape.pnt) - if ~isfield(individual.headshape, 'tri') || isempty(individual.headshape.tri) - individual.headshape.tri = projecttri(individual.headshape.pnt); - end -end - -% open a figure -fig = figure; -% add the data to the figure -set(fig, 'CloseRequestFcn', @cb_close); -setappdata(fig, 'individual', individual); -setappdata(fig, 'template', template); -setappdata(fig, 'transform', eye(4)); - -% add the GUI elements -cb_creategui(gca); -cb_redraw(gca); -rotate3d on -waitfor(fig); - -% get the data from the figure that was left behind as global variable -% FIXME pass this as appdata -global norm -tmp = norm; -clear global norm -norm = tmp; -clear tmp - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: interactiverealign.m,v 1.8 2009/01/20 13:01:31 sashae Exp $'; - -% remember the transform -cfg.m = norm.m; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% some simple SUBFUNCTIONs that facilitate 3D plotting -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function h = my_plot3(xyz, varargin) -h = plot3(xyz(:,1), xyz(:,2), xyz(:,3), varargin{:}); -function h = my_text3(xyz, varargin) -h = text(xyz(:,1), xyz(:,2), xyz(:,3), varargin{:}); -function my_line3(xyzB, xyzE, varargin) -for i=1:size(xyzB,1) - line([xyzB(i,1) xyzE(i,1)], [xyzB(i,2) xyzE(i,2)], [xyzB(i,3) xyzE(i,3)], varargin{:}) -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION to layout a moderately complex graphical user interface -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function h = layoutgui(fig, geometry, position, style, string, value, tag, callback); -horipos = geometry(1); % lower left corner of the GUI part in the figure -vertpos = geometry(2); % lower left corner of the GUI part in the figure -width = geometry(3); % width of the GUI part in the figure -height = geometry(4); % height of the GUI part in the figure -horidist = 0.05; -vertdist = 0.05; -options = {'units', 'normalized', 'HorizontalAlignment', 'center'}; % 'VerticalAlignment', 'middle' -Nrow = size(position,1); -h = cell(Nrow,1); -for i=1:Nrow - if isempty(position{i}) - continue; - end - position{i} = position{i} ./ sum(position{i}); - Ncol = size(position{i},2); - ybeg = (Nrow-i )/Nrow + vertdist/2; - yend = (Nrow-i+1)/Nrow - vertdist/2; - for j=1:Ncol - xbeg = sum(position{i}(1:(j-1))) + horidist/2; - xend = sum(position{i}(1:(j ))) - horidist/2; - pos(1) = xbeg*width + horipos; - pos(2) = ybeg*height + vertpos; - pos(3) = (xend-xbeg)*width; - pos(4) = (yend-ybeg)*height; - h{i}{j} = uicontrol(fig, ... - options{:}, ... - 'position', pos, ... - 'style', style{i}{j}, ... - 'string', string{i}{j}, ... - 'tag', tag{i}{j}, ... - 'value', value{i}{j}, ... - 'callback', callback{i}{j} ... - ); - end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function cb_creategui(hObject, eventdata, handles); -% define the position of each GUI element -position = { - [2 1 1 1] - [2 1 1 1] - [2 1 1 1] - [1] - [1] - [1] - [1] - [1 1] - }; - -% define the style of each GUI element -style = { - {'text' 'edit' 'edit' 'edit'} - {'text' 'edit' 'edit' 'edit'} - {'text' 'edit' 'edit' 'edit'} - {'pushbutton'} - {'pushbutton'} - {'toggle'} - {'toggle'} - {'text' 'edit'} - }; - -% define the descriptive string of each GUI element -string = { - {'rotate' 0 0 0} - {'translate' 0 0 0} - {'scale' 1 1 1} - {'redisplay'} - {'apply'} - {'toggle grid'} - {'toggle axes'} - {'alpha' 0.7} - }; - -% define the value of each GUI element -value = { - {[] [] [] []} - {[] [] [] []} - {[] [] [] []} - {[]} - {[]} - {0} - {0} - {[] []} - }; - -% define a tag for each GUI element -tag = { - {'' 'rx' 'ry' 'rz'} - {'' 'tx' 'ty' 'tz'} - {'' 'sx' 'sy' 'sz'} - {''} - {''} - {'toggle grid'} - {'toggle axes'} - {'' 'alpha'} - }; - -% define the callback function of each GUI element -callback = { - {[] @cb_redraw @cb_redraw @cb_redraw} - {[] @cb_redraw @cb_redraw @cb_redraw} - {[] @cb_redraw @cb_redraw @cb_redraw} - {@cb_redraw} - {@cb_apply} - {@cb_redraw} - {@cb_redraw} - {[] @cb_redraw} - }; - -fig = get(hObject, 'parent'); -layoutgui(fig, [0.7 0.05 0.25 0.50], position, style, string, value, tag, callback); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function cb_redraw(hObject, eventdata, handles) -fig = get(hObject, 'parent'); -individual = getappdata(fig, 'individual'); -template = getappdata(fig, 'template'); -% get the transformation details -rx = str2num(get(findobj(fig, 'tag', 'rx'), 'string')); -ry = str2num(get(findobj(fig, 'tag', 'ry'), 'string')); -rz = str2num(get(findobj(fig, 'tag', 'rz'), 'string')); -tx = str2num(get(findobj(fig, 'tag', 'tx'), 'string')); -ty = str2num(get(findobj(fig, 'tag', 'ty'), 'string')); -tz = str2num(get(findobj(fig, 'tag', 'tz'), 'string')); -sx = str2num(get(findobj(fig, 'tag', 'sx'), 'string')); -sy = str2num(get(findobj(fig, 'tag', 'sy'), 'string')); -sz = str2num(get(findobj(fig, 'tag', 'sz'), 'string')); -R = rotate ([rx ry rz]); -T = translate([tx ty tz]); -S = scale ([sx sy sz]); -H = S * T * R; -axis vis3d; cla -xlabel('x') -ylabel('y') -zlabel('z') - -hold on - -% the "individual" struct is a local copy, so it is safe to change it here -if ~isempty(individual.vol) - individual.vol = transform_vol(H, individual.vol); -end -if ~isempty(individual.elec) - individual.elec = transform_sens(H, individual.elec); -end -if ~isempty(individual.grad) - individual.grad = transform_sens(H, individual.grad); -end -if ~isempty(individual.headshape) - individual.headshape = transform_headshape(H, individual.headshape); -end - -if ~isempty(template.elec) - hs = triplot(template.elec.pnt, [], [], 'nodes'); - set(hs, 'MarkerSize', 10); - set(hs, 'Color', 'b'); - if isfield(template.elec, 'line') - hs = triplot(template.elec.pnt, template.elec.line, [], 'edges'); - try, set(hs, 'MarkerEdgeColor', 'b'); end - end -end - -if ~isempty(individual.elec) - hs = triplot(individual.elec.pnt, [], [], 'nodes'); - set(hs, 'MarkerSize', 10); - set(hs, 'Color', 'r'); - if isfield(individual.elec, 'line') - hs = triplot(individual.elec.pnt, elec.line, [], 'edges'); - try, set(hs, 'MarkerEdgeColor', 'r'); end - end -end - -if ~isempty(template.grad) - hs = triplot(template.grad.pnt, [], [], 'nodes'); - set(hs, 'MarkerSize', 10); - set(hs, 'Color', 'b'); - % FIXME also plot lines? -end - -if ~isempty(individual.grad) - hs = triplot(individual.grad.pnt, [], [], 'nodes'); - set(hs, 'MarkerSize', 10); - set(hs, 'Color', 'r'); - % FIXME also plot lines? -end - -if ~isempty(template.vol) - % FIXME this only works for boundary element models - for i = 1:numel(template.vol.bnd) - if strcmp(template.volstyle, 'edge') || ... - strcmp(template.volstyle, 'both') - hs = triplot(template.vol.bnd(i).pnt, template.vol.bnd(i).tri, [], 'edges'); - try, set(hs, 'EdgeColor', 'b'); end - end - if strcmp(template.volstyle, 'surface') || ... - strcmp(template.volstyle, 'both') - hs = triplot(template.vol.bnd(i).pnt, template.vol.bnd(i).tri, [], 'faces_blue'); - - end - end -end - -if ~isempty(individual.vol) - % FIXME this only works for boundary element models - for i = 1:numel(individual.vol.bnd) - if strcmp(individual.volstyle, 'edge') || ... - strcmp(individual.volstyle, 'both') - hs = triplot(individual.vol.bnd(i).pnt, individual.vol.bnd(i).tri, [], 'edges'); - try, set(hs, 'EdgeColor', 'r'); end - end - if strcmp(individual.volstyle, 'surface') || ... - strcmp(individual.volstyle, 'both') - hs = triplot(individual.vol.bnd(i).pnt, individual.vol.bnd(i).tri, [], 'faces_red'); - end - end -end - -if ~isempty(template.headshape) - if isfield(template.headshape, 'pnt') && ~isempty(template.headshape.pnt) - if strcmp(template.headshapestyle, 'surface') || ... - strcmp(template.headshapestyle, 'both') - triplot(template.headshape.pnt, template.headshape.tri, [], 'faces_blue'); - alpha(str2num(get(findobj(fig, 'tag', 'alpha'), 'string'))); - end - - if strcmp(template.headshapestyle, 'vertex') || ... - strcmp(template.headshapestyle, 'both') - hs = triplot(template.headshape.pnt, [], [], 'nodes'); - set(hs, 'Color', 'b'); - end - end - if isfield(template.headshape, 'fid') && ~isempty(template.headshape.fid.pnt) - triplot(template.headshape.fid.pnt, [], [], 'nodes_blue'); - end -end - -if ~isempty(individual.headshape) - if isfield(individual.headshape, 'pnt') && ~isempty(individual.headshape.pnt) - if strcmp(individual.headshapestyle, 'surface') || ... - strcmp(individual.headshapestyle, 'both') - triplot(individual.headshape.pnt, individual.headshape.tri, [], 'faces_red'); - alpha(str2num(get(findobj(fig, 'tag', 'alpha'), 'string'))); - end - - if strcmp(individual.headshapestyle, 'vertex') || ... - strcmp(individual.headshapestyle, 'both') - hs = triplot(individual.headshape.pnt, [], [], 'nodes'); - set(hs, 'Color', 'r'); - end - end - if isfield(individual.headshape, 'fid') && ~isempty(individual.headshape.fid.pnt) - triplot(individual.headshape.fid.pnt, [], [], 'nodes_red'); - end -end - -if get(findobj(fig, 'tag', 'toggle axes'), 'value') - axis on -else - axis off -end -if get(findobj(fig, 'tag', 'toggle grid'), 'value') - grid on -else - grid off -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function cb_apply(hObject, eventdata, handles); -fig = get(hObject, 'parent'); -transform = getappdata(fig, 'transform'); -% get the transformation details -rx = str2num(get(findobj(fig, 'tag', 'rx'), 'string')); -ry = str2num(get(findobj(fig, 'tag', 'ry'), 'string')); -rz = str2num(get(findobj(fig, 'tag', 'rz'), 'string')); -tx = str2num(get(findobj(fig, 'tag', 'tx'), 'string')); -ty = str2num(get(findobj(fig, 'tag', 'ty'), 'string')); -tz = str2num(get(findobj(fig, 'tag', 'tz'), 'string')); -sx = str2num(get(findobj(fig, 'tag', 'sx'), 'string')); -sy = str2num(get(findobj(fig, 'tag', 'sy'), 'string')); -sz = str2num(get(findobj(fig, 'tag', 'sz'), 'string')); -R = rotate ([rx ry rz]); -T = translate([tx ty tz]); -S = scale ([sx sy sz]); -H = S * T * R; -transform = H * transform; -set(findobj(fig, 'tag', 'rx'), 'string', 0); -set(findobj(fig, 'tag', 'ry'), 'string', 0); -set(findobj(fig, 'tag', 'rz'), 'string', 0); -set(findobj(fig, 'tag', 'tx'), 'string', 0); -set(findobj(fig, 'tag', 'ty'), 'string', 0); -set(findobj(fig, 'tag', 'tz'), 'string', 0); -set(findobj(fig, 'tag', 'sx'), 'string', 1); -set(findobj(fig, 'tag', 'sy'), 'string', 1); -set(findobj(fig, 'tag', 'sz'), 'string', 1); -setappdata(fig, 'transform', transform); -cb_redraw(hObject); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function cb_close(hObject, eventdata, handles); -% make the current transformation permanent and subsequently allow deleting the figure -cb_apply(gca); -% get the updated electrode from the figure -fig = hObject; -% hmmm, this is ugly -global norm -norm.m = getappdata(fig, 'transform'); -set(fig, 'CloseRequestFcn', @delete); -delete(fig); - diff --git a/external/fieldtrip/private/interp_gridded.m b/external/fieldtrip/private/interp_gridded.m index 59c1a34..8c392c5 100644 --- a/external/fieldtrip/private/interp_gridded.m +++ b/external/fieldtrip/private/interp_gridded.m @@ -20,14 +20,23 @@ % Copyright (C) 2007, Jan-Mathijs Schoffelen & Robert Oostenveld % -% $Log: interp_gridded.m,v $ -% Revision 1.1 2007/05/06 12:07:26 roboos -% new function, based on old surfaceplot and interp_ungridded -% this implementation is much faster for sourceplot with method=surface +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.1 2007/02/07 07:42:06 roboos -% new implementation to be used in teh new sourceplot, mainly based on code from the old surfaceplot +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: interp_gridded.m 952 2010-04-21 18:29:51Z roboos $ if nargin<3 error('Not enough input arguments.'); diff --git a/external/fieldtrip/private/interp_ungridded.m b/external/fieldtrip/private/interp_ungridded.m index 336ef6b..894ec07 100644 --- a/external/fieldtrip/private/interp_ungridded.m +++ b/external/fieldtrip/private/interp_ungridded.m @@ -23,10 +23,23 @@ % Copyright (C) 2007, Jan-Mathijs Schoffelen & Robert Oostenveld % -% $Log: interp_ungridded.m,v $ -% Revision 1.1 2007/02/07 07:42:06 roboos -% new implementation to be used in teh new sourceplot, mainly based on code from the old surfaceplot +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: interp_ungridded.m 952 2010-04-21 18:29:51Z roboos $ if nargin<3 error('Not enough input arguments.'); diff --git a/external/fieldtrip/private/issubfield.m b/external/fieldtrip/private/issubfield.m deleted file mode 100644 index 60d94f4..0000000 --- a/external/fieldtrip/private/issubfield.m +++ /dev/null @@ -1,35 +0,0 @@ -function [r] = issubfield(s, f) - -% ISSUBFIELD tests for the presence of a field in a structure just like the standard -% Matlab ISFIELD function, except that you can also specify nested fields -% using a '.' in the fieldname. The nesting can be arbitrary deep. -% -% Use as -% f = issubfield(s, 'fieldname') -% or as -% f = issubfield(s, 'fieldname.subfieldname') -% -% This function returns true if the field is present and false if the field -% is not present. -% -% See also ISFIELD, GETSUBFIELD, SETSUBFIELD - -% Copyright (C) 2005, Robert Oostenveld -% -% $Log: issubfield.m,v $ -% Revision 1.2 2009/07/30 20:11:44 ingnie -% made output boolian -% -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.1 2005/02/08 09:30:18 roboos -% new implementations to make it easier to work with nested structures -% - -try - getsubfield(s, f); % if this works, then the subfield must be present - r = true; -catch - r = false; % apparently the subfield is not present -end \ No newline at end of file diff --git a/external/fieldtrip/private/istrue.m b/external/fieldtrip/private/istrue.m deleted file mode 100644 index 2cfd5a9..0000000 --- a/external/fieldtrip/private/istrue.m +++ /dev/null @@ -1,38 +0,0 @@ -function y = istrue(x) - -% ISTRUE ensures that a true/false input argument like "yes", "true" -% or "on" is converted into a boolean - -% Copyright (C) 2009, Robert Oostenveld -% -% $Log: istrue.m,v $ -% Revision 1.4 2009/06/05 14:26:23 crimic -% added 'none' option -% -% Revision 1.3 2009/05/14 11:57:37 crimic -% introduced check for 'y' and 'n' -% -% Revision 1.2 2009/04/14 18:30:35 roboos -% small fix -% -% Revision 1.1 2009/04/14 18:28:45 roboos -% extended and moved from plotting to public -% - -true_list = {'yes' 'true' 'on' 'y' }; -false_list = {'no' 'false' 'off' 'n' 'none'}; - -if ischar(x) - % convert string to boolean value - if any(strcmpi(x, true_list)) - y = true; - elseif any(strcmpi(x, false_list)) - y = false; - else - error('cannot determine whether "%s" should be interpreted as true or false', x); - end -else - % convert numerical value to boolean - y = logical(x); -end - diff --git a/external/fieldtrip/private/keyval.m b/external/fieldtrip/private/keyval.m deleted file mode 100644 index 106cf02..0000000 --- a/external/fieldtrip/private/keyval.m +++ /dev/null @@ -1,62 +0,0 @@ -function [val] = keyval(key, varargin) - -% KEYVAL returns the value that corresponds to the requested key in a -% key-value pair list of variable input arguments -% -% Use as -% [val] = keyval(key, varargin) -% -% See also VARARGIN - -% Copyright (C) 2005-2007, Robert Oostenveld -% -% $Log: keyval.m,v $ -% Revision 1.5 2009/08/04 11:58:28 roboos -% perform a case-insensitive string comparison for keys -% -% Revision 1.4 2009/07/14 16:11:02 roboos -% speed up the input checks -% -% Revision 1.3 2009/05/14 19:24:02 roboos -% removed ; at end of function declaration -% -% Revision 1.2 2009/01/06 09:05:26 roboos -% added additional check on optional input arguments: the 1st, 3rd, etc. should be strings (keys) -% -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.2 2007/07/18 12:43:53 roboos -% test for an even number of optional input arguments -% -% Revision 1.1 2005/11/04 10:24:46 roboos -% new implementation -% - -if length(varargin)==1 && iscell(varargin{1}) - varargin = varargin{1}; -end - -if mod(length(varargin),2) - error('optional input arguments should come in key-value pairs, i.e. there should be an even number'); -end - -% the 1st, 3rd, etc. contain the keys, the 2nd, 4th, etc. contain the values -keys = varargin(1:2:end); -vals = varargin(2:2:end); - -if ~all(cellfun(@ischar, keys)) - error('optional input arguments should come in key-value pairs, the optional input argument %d is invalid (should be a string)', i); -end - -hit = find(strcmpi(key, keys)); -if isempty(hit) - % the requested key was not found - val = []; -elseif length(hit)==1 - % the requested key was found - val = vals{hit}; -else - error('multiple input arguments with the same name'); -end - diff --git a/external/fieldtrip/private/keyval2cfg.m b/external/fieldtrip/private/keyval2cfg.m deleted file mode 100644 index b7fdabe..0000000 --- a/external/fieldtrip/private/keyval2cfg.m +++ /dev/null @@ -1,16 +0,0 @@ -function [cfg] = keyval2cfg(varargin); - -% KEYVAL2CFG converts between a structure and a cell-array with key-value -% pairs which can be used for optional input arguments. -% -% Use as -% [cfg] = keyval2cfg(varargin) - -if iscell(varargin) && length(varargin)==1 - varargin = varargin{1}; -end - -% assign the optional key-value arguments to a configuration structure -var = varargin(1:2:length(varargin)); % get the odd arguments -val = varargin(2:2:length(varargin)); % get the even arguments -cfg = cell2struct(val(:), var(:), 1); diff --git a/external/fieldtrip/private/keyvalcheck.m b/external/fieldtrip/private/keyvalcheck.m deleted file mode 100644 index b928f19..0000000 --- a/external/fieldtrip/private/keyvalcheck.m +++ /dev/null @@ -1,78 +0,0 @@ -function keyvalcheck(arglist, varargin) - -% KEYVALCHECK is a helper function for parsing optional key-value input pairs. -% -% Use as -% keyvalcheck(argin, 'required', {'key1', 'key2', ...}) -% keyvalcheck(argin, 'forbidden', {'key1', 'key2', ...}) -% keyvalcheck(argin, 'optional', {'key1', 'key2', ...}) -% -% See also KEYVAL - -% Copyright (C) 2009, Robert Oostenveld -% -% $Log: keyvalcheck.m,v $ -% Revision 1.4 2009/08/05 08:50:50 roboos -% allow different case in the option names, i.e. use case-insensitive comparisons -% -% Revision 1.3 2009/07/14 16:10:34 roboos -% added caching for previous input -% -% Revision 1.2 2009/06/15 14:23:26 roboos -% only check an option if specified (i.e. non-empty) -% -% Revision 1.1 2009/04/14 19:37:44 roboos -% new helper function, used in plot_xxx functions -% - -% this is to speed up subsequent calls with the same input arguments -persistent previous_argin - -current_argin = {arglist, varargin{:}}; -if ~isempty(previous_argin) && isequal(previous_argin, current_argin) - % the input is the same to the previous input, and that was OK - return -end - -required = keyval('required', varargin); -forbidden = keyval('forbidden', varargin); -optional = keyval('optional', varargin); - -keys = arglist(1:2:end); -vals = arglist(2:2:end); - -if numel(keys)~=numel(vals) - error('optional input arguments should come in key-value pairs, i.e. there should be an even number'); -end - -keys = cellfun(@lower, keys, 'UniformOutput', false); - -if ~isempty(required) - % only check if specified - required = cellfun(@lower, required, 'UniformOutput', false); - set = intersect(keys, required); - if numel(set)~=numel(required) - error('the required input argument ''%s'' was not specified', set{:}); - end -end - -if ~isempty(forbidden) - % only check if specified - forbidden = cellfun(@lower, forbidden, 'UniformOutput', false); - set = intersect(keys, forbidden); - if numel(set)~=0 - error('the input argument ''%s'' is forbidden', set{:}); - end -end - -if ~isempty(optional) - % only check if specified - optional = cellfun(@lower, optional, 'UniformOutput', false); - set = setdiff(keys, optional); - if numel(set)>0 - error('the input argument ''%s'' is forbidden', set{:}); - end -end - -% remember the current input arguments, which appear to be OK -previous_argin = current_argin; diff --git a/external/fieldtrip/private/ksphere.m b/external/fieldtrip/private/ksphere.m index 5177037..c15b954 100644 --- a/external/fieldtrip/private/ksphere.m +++ b/external/fieldtrip/private/ksphere.m @@ -15,10 +15,23 @@ % Copyright (C) 2005, Robert Oostenveld % -% $Log: ksphere.m,v $ -% Revision 1.1 2005/11/01 09:56:00 roboos -% new implementation +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ksphere.m 952 2010-04-21 18:29:51Z roboos $ for k=1:N h = -1 + 2*(k-1)/(N-1); diff --git a/external/fieldtrip/private/language29ch-avg.lay b/external/fieldtrip/private/language29ch-avg.lay deleted file mode 100644 index 80cba57..0000000 --- a/external/fieldtrip/private/language29ch-avg.lay +++ /dev/null @@ -1,35 +0,0 @@ -1 -0.297748 9.710306 1.958587 1.468940 Fz -2 -0.440232 6.412069 1.958587 1.468940 FCz -3 -0.893818 2.505291 1.958587 1.468940 Cz -4 -1.329903 -4.341909 1.958587 1.468940 Pz -5 -1.518064 -11.520090 1.958587 1.468940 Oz -6 4.264220 12.213813 1.958587 1.468940 AF4 -7 -4.309059 12.959407 1.958587 1.468940 AF3 -8 5.067300 8.325666 1.958587 1.468940 F4 -9 -6.319716 9.033403 1.958587 1.468940 F3 -10 9.101720 7.147147 1.958587 1.468940 F8 -11 -10.608780 8.838123 1.958587 1.468940 F7 -12 4.787408 4.667875 1.958587 1.468940 FC4 -13 -6.651218 5.836743 1.958587 1.468940 FC3 -14 9.648098 3.250883 1.958587 1.468940 FT8 -15 -10.998214 4.029187 1.958587 1.468940 FT7 -16 5.175426 1.621019 1.958587 1.468940 C4 -17 -7.127019 2.331433 1.958587 1.468940 C3 -18 8.216692 0.236613 1.958587 1.468940 RT -19 -10.246361 1.130718 1.958587 1.468940 LT -20 4.594511 -1.598973 1.958587 1.468940 CP4 -21 -6.797265 -0.775081 1.958587 1.468940 CP3 -22 6.331378 -3.324414 1.958587 1.468940 RTP -23 -8.680347 -2.360832 1.958587 1.468940 LTP -24 3.535765 -5.232313 1.958587 1.468940 P4 -25 -6.199775 -4.001943 1.958587 1.468940 P3 -26 5.775461 -6.578155 1.958587 1.468940 RP -27 -8.309895 -5.906355 1.958587 1.468940 LP -28 4.430050 -9.757231 1.958587 1.468940 PO8 -29 -6.937175 -9.268404 1.958587 1.468940 PO7 -30 11.130008 -7.546117 1.958587 1.468940 M2 -31 -14.581878 -8.098725 1.958587 1.468940 M1 -32 -0.201026 16.414412 1.958587 1.468940 Gnd -33 0.168505 19.917224 1.958587 1.468940 Nasion -34 -15.448850 2.054051 1.958587 1.468940 LPA -35 15.253888 4.514997 1.958587 1.468940 RPA diff --git a/external/fieldtrip/private/lapcal.m b/external/fieldtrip/private/lapcal.m index f60920d..430cee1 100644 --- a/external/fieldtrip/private/lapcal.m +++ b/external/fieldtrip/private/lapcal.m @@ -6,9 +6,9 @@ % lap = lapcal(pnt, tri) % % where -% pnt contains the positions of the vertices -% tri contains the triangle definition -% lap is the surface laplacian matrix +% pnt contains the positions of the vertices +% tri contains the triangle definition +% lap is the surface laplacian matrix % % See also LAPINT, LAPINTMAT, READ_TRI, SAVE_TRI @@ -19,13 +19,23 @@ % Copyright (C) 2001, Robert Oostenveld % -% $Log: lapcal.m,v $ -% Revision 1.1 2009/01/21 10:46:10 roboos -% moved from forwinv/* and forwinv/mex/* directory to forwinv/private/* to make the CVS layout consistent with the release version +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.2 2003/03/11 14:45:36 roberto -% updated help and copyrights +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: lapcal.m 952 2010-04-21 18:29:51Z roboos $ npnt = size(pnt,1); ntri = size(tri,1); @@ -45,10 +55,10 @@ lap = zeros(npnt); for i=1:npnt - k = find(edge(i,:)); % the indices of the neighbours - n = length(k); % the number of neighbours - h = mean(edge(i,k)); % the average distance to the neighbours - hi = mean(1./edge(i,k)); % the average inverse distance to the neighbours + k = find(edge(i,:)); % the indices of the neighbours + n = length(k); % the number of neighbours + h = mean(edge(i,k)); % the average distance to the neighbours + hi = mean(1./edge(i,k)); % the average inverse distance to the neighbours lap(i,i) = -(4/h) * hi; lap(i,k) = (4/(h*n)) * 1./edge(i,k); diff --git a/external/fieldtrip/private/lateralizedpotential.m b/external/fieldtrip/private/lateralizedpotential.m deleted file mode 100644 index 71bd5d8..0000000 --- a/external/fieldtrip/private/lateralizedpotential.m +++ /dev/null @@ -1,128 +0,0 @@ -function lrp = lateralizedpotential(cfg, avgL, avgR); - -% LATERALIZEDPOTENTIAL computes lateralized potentials such as the LRP -% -% Use as -% [lrp] = lateralizedpotential(cfg, avgL, avgR) -% -% where the input datasets should come from TIMELOCKANALYSIS -% and the configuration should contain -% cfg.channelcmb = Nx2 cell array -% -% An example channelcombination containing the homologous channels -% in the 10-20 standard system is -% cfg.channelcmb = {'Fp1' 'Fp2' -% 'F7' 'F8' -% 'F3' 'F4' -% 'T7' 'T8' -% 'C3' 'C4' -% 'P7' 'P8' -% 'P3' 'P4' -% 'O1' 'O2'} -% -% The lateralized potential is computed on combinations of channels and -% not on indivudual channels. However, if you want to make a topographic -% plot with e.g. MULTIPLOTER, you can replace the output lrp.label -% with lrp.plotlabel. -% -% The concept for the LRP was introduced approximately simultaneously in the -% following two papers -% - M. G. H. Coles. Modern mind-brain reading - psychophysiology, -% physiology, and cognition. Psychophysiology, 26(3):251-269, 1988. -% - R. de Jong, M. Wierda, G. Mulder, and L. J. Mulder. Use of -% partial stimulus information in response processing. J Exp Psychol -% Hum Percept Perform, 14:682-692, 1988. -% and it is discussed in detail on a technical level in -% - R. Oostenveld, D.F. Stegeman, P. Praamstra and A. van Oosterom. -% Brain symmetry and topographic analysis of lateralized event-related -% potentials. Clin Neurophysiol. 114(7):1194-202, 2003. -% -% See also LATERALIZEDFIELD, TIMELOCKANALYSIS, MULTIPLOTER - -% Copyright (C) 2004, Robert Oostenveld -% -% $Log: lateralizedpotential.m,v $ -% Revision 1.6 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.5 2005/06/29 12:46:29 roboos -% the following changes were done on a large number of files at the same time, not all of them may apply to this specific file -% - added try-catch around the inclusion of input data configuration -% - moved cfg.version, cfg.previous and the assignment of the output cfg to the end -% - changed help comments around the configuration handling -% - some changes in whitespace -% -% Revision 1.4 2005/06/24 08:26:43 roboos -% restructured the help, changed some whitespace -% -% Revision 1.3 2005/05/17 17:50:37 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.2 2005/01/25 08:13:40 roboos -% fixed small error with brackets -% -% Revision 1.1 2004/12/16 11:19:05 roboos -% new implementation -% - -fieldtripdefs - -if ~isfield(cfg, 'channelcmb'), - cfg.channelcmb = { - 'Fp1' 'Fp2' - 'F7' 'F8' - 'F3' 'F4' - 'T7' 'T8' - 'C3' 'C4' - 'P7' 'P8' - 'P3' 'P4' - 'O1' 'O2' - }; -end - -if ~all(avgL.time==avgR.time) - error('timeaxes are not the same'); -end - -% start with an empty output structure -lrp.label = {}; -lrp.plotlabel = {}; -lrp.avg = []; -lrp.time = avgL.time; - -% compute the lateralized potentials -Nchan = size(cfg.channelcmb); -for i=1:Nchan - C3R = strmatch(cfg.channelcmb{i,1}, avgR.label); - C4R = strmatch(cfg.channelcmb{i,2}, avgR.label); - C3L = strmatch(cfg.channelcmb{i,1}, avgL.label); - C4L = strmatch(cfg.channelcmb{i,2}, avgL.label); - if ~isempty(C3R) && ~isempty(C4R) && ~isempty(C3L) && ~isempty(C4L) - lrp.label{end+1} = sprintf('%s/%s', cfg.channelcmb{i,1}, cfg.channelcmb{i,2}); - lrp.plotlabel{end+1} = cfg.channelcmb{i,1}; - erpC3L = avgL.avg(C3L,:); - erpC4L = avgL.avg(C4L,:); - erpC3R = avgR.avg(C3R,:); - erpC4R = avgR.avg(C4R,:); - lrp.avg(end+1,:) = 1/2 * ((erpC3R - erpC4R) + (erpC4L - erpC3L)); - end -end - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: lateralizedpotential.m,v 1.6 2008/09/22 20:17:43 roboos Exp $'; -% remember the configuration details of the input data -cfg.previous = []; -try, cfg.previous{1} = avgL.cfg; end -try, cfg.previous{2} = avgR.cfg; end -% remember the exact configuration details in the output -lrp.cfg = cfg; - diff --git a/external/fieldtrip/private/layoutplot.m b/external/fieldtrip/private/layoutplot.m deleted file mode 100644 index 4937eee..0000000 --- a/external/fieldtrip/private/layoutplot.m +++ /dev/null @@ -1,176 +0,0 @@ -function layoutplot(cfg, data) - -% LAYOUTPLOT makes a figure with the 2-D layout of the channel positions -% for topoplotting and the individual channel axes (i.e. width and height -% of the subfigures) for multiplotting. A correct 2-D layout is a -% prerequisite for plotting the topographical distribution of the -% potential or field distribution, or for plotting timecourses in a -% topographical arrangement. -% -% This function uses the same configuration options as prepare_layout and -% as the topoplotting and multiplotting functions. The difference is that -% this function plots the layout without any data, which facilitates -% the validation of your 2-D layout. -% -% Use as -% layoutplot(cfg, data) -% -% There are several ways in which a 2-D layout can be made: it can be read -% directly from a *.lay file, it can be created based on 3-D electrode or -% gradiometer positions in the configuration or in the data, or it can be -% created based on the specification of an electrode of gradiometer file. -% -% You can specify either one of the following configuration options -% cfg.layout filename containg the layout -% cfg.rotate number, rotation around the z-axis in degrees (default = [], which means automatic) -% cfg.projection string, 2D projection method can be 'stereographic', 'ortographic', 'polar', 'gnomic' or 'inverse' (default = 'orthographic') -% cfg.elec structure with electrode positions, or -% cfg.elecfile filename containing electrode positions -% cfg.grad structure with gradiometer definition, or -% cfg.gradfile filename containing gradiometer definition -% cfg.output filename to which the layout will be written (default = []) -% cfg.montage 'no' or a montage structure (default = 'no') -% cfg.image filename, use an image to construct a layout (e.g. usefull for ECoG grids) -% -% Alternatively the layout can be constructed from either -% data.elec structure with electrode positions -% data.grad structure with gradiometer definition -% -% Alternatively, you can specify -% cfg.layout = 'ordered' -% which will give you a 2-D ordered layout. Note that this is only suited -% for multiplotting and not for topoplotting. -% -% See also prepare_layout, topoplotER, topoplotTFR, multiplotER, multiplotTFR - -% Undocumented options -% cfg.montage - -% Copyright (C) 2006-2008, Robert Oostenveld -% -% $Log: layoutplot.m,v $ -% Revision 1.11 2009/09/10 12:30:00 roboos -% added option for plotting an arrow for each of the bipolar electrode pairs, requires a montage and a layout -% -% Revision 1.10 2009/05/12 12:35:15 roboos -% moved plotting to seperate function (plot_lay) where it can be reused -% -% Revision 1.9 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.8 2008/09/22 12:44:46 roboos -% added support for cfg.image, some small changes to documentation and to plotting style -% -% Revision 1.7 2008/07/16 09:27:36 roboos -% added support for creating a layout based on a figure, including mask and outline for topoplot -% -% Revision 1.6 2007/03/21 14:47:06 chrhes -% updated some comments -% -% Revision 1.5 2007/03/20 10:44:37 roboos -% updated documentation, change figure axis, changed whitespaces -% -% Revision 1.4 2007/03/20 09:46:31 chrhes -% added some checks to determine whether the field cfg.layout already contains a -% valid layout structure that can be used, thereby avoiding a redundant call to -% the function PREPARE_LAYOUT -% -% Revision 1.3 2007/03/14 08:56:00 roboos -% changed some documentation -% -% Revision 1.2 2007/03/14 08:53:29 roboos -% changed from using private/createlayout to prepare_layout, changed the lay -% structure, added some help to clarify the usefullness of this function -% -% Revision 1.1 2006/06/01 11:51:45 roboos -% new implementation -% - -fieldtripdefs - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% basic check/initialization of input arguments -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if (nargin<1) || (nargin>2), error('incorrect number of input arguments'); end; -if (nargin<2), data = []; end; - -if ~isstruct(cfg) && ~isempty(cfg), error('argument cfg must be a structure'); end; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% extract/generate layout information -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -lay = []; - -% try to use the layout structure from input if specified -if isfield(cfg, 'layout') - % brief check to determine if cfg.layout is a valid layout (lay) structre - if isstruct(cfg.layout) - if all(isfield(cfg.layout, {'pos';'width';'height';'label'})) - lay = cfg.layout; - end - end -end - -% otherwise create the layout structure -if isempty(lay), lay = prepare_layout(cfg, data); end; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% plot all details pertaining to the layout in one figure -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -figure - -if isfield(cfg, 'image') && ~isempty(cfg.image) - % start with the background image - fprintf('reading background image from %s\n', cfg.image); - img = imread(cfg.image); - img = flipdim(img, 1); % in combination with "axis xy" - - bw = 1; - - if bw - % convert to greyscale image - img = mean(img, 3); - imagesc(img); - colormap gray - else - % plot as RGB image - image(img); - end - axis equal - axis off - axis xy -end - -plot_lay(lay, 'point', true, 'box', true, 'label', true, 'mask', true, 'outline', true); - -% the following code can be used to verify a bipolar montage, given the -% layout of the monopolar channels -if isfield(cfg, 'montage') && ~isempty(cfg.montage) - fprintf('plotting an arrow for each of the bipolar electrode pairs\n'); - % the arrow begins at the +1 electrode - % the arrow ends at the -1 electrode - for i=1:length(cfg.montage.labelnew) - begindx = find(cfg.montage.tra(i,:)==+1); - endindx = find(cfg.montage.tra(i,:)==-1); - if ~numel(begindx)==1 || ~numel(endindx)==1 - % the re-referenced channel does not seem to be a bipolar pair - continue - end - % find the position of the begin and end of the arrow - beglab = cfg.montage.labelorg{begindx}; - endlab = cfg.montage.labelorg{endindx}; - begindx = find(strcmp(lay.label, beglab)); % the index in the layout - endindx = find(strcmp(lay.label, endlab)); % the index in the layout - if ~numel(begindx)==1 || ~numel(endindx)==1 - % one of the channels in the bipolar pair does not seem to be in the layout - continue - end - - begpos = lay.pos(begindx,:); - endpos = lay.pos(endindx,:); - arrow(begpos, endpos, 'Length', 5) - - end % for all re-referenced channels -end % if montage - - diff --git a/external/fieldtrip/private/lbex.m b/external/fieldtrip/private/lbex.m new file mode 100644 index 0000000..805bdfb --- /dev/null +++ b/external/fieldtrip/private/lbex.m @@ -0,0 +1,69 @@ +function [grid] = lbex(cfg, grid) + +% This function will add the field "subspace" to the grid definition. +% +% The subspace projection is based on the LBEX (local basis expansion) +% method. + +% set the defaults +if ~isfield(cfg, 'lbex'), cfg.lbex = 3; end +if ~isfield(cfg, 'lbexeigtol'), cfg.lbexeigtol = 1000*eps; end +if ~isfield(cfg, 'feedback'), cfg.feedback = 'text'; end + +Ndipoles = size(grid.pos,1); +Ninside = length(grid.inside); + +% concatenate the leadfield of all dipoles that are inside the brain into one large matrix +sel = grid.inside; +lfa = cell2mat(grid.leadfield(sel(:)')); +% covariance of all leadfields +Ca = lfa * lfa'; + +progress('init', cfg.feedback, 'computing lbex'); +for dipindx=1:Ninside + % renumber the loop-index variable to make it easier to print the progress bar + i = grid.inside(dipindx); + + % compute the distance from this dipole to each other dipole + dist = sqrt(sum((grid.pos-repmat(grid.pos(i,:), [Ndipoles 1])).^2, 2)); + + % define the region of interest around this dipole + sel = find(dist<=cfg.lbex); + sel = intersect(sel, grid.inside); + Nsel = length(sel); + + progress(dipindx/Ninside, 'computing lbex %d/%d, Nsel=%d\n', dipindx, Ninside, Nsel); + + % concatenate the leadfield of all dipoles that are inside the ROI into one matrix + lfr = cell2mat(grid.leadfield(sel(:)')); + % covariance of leadfields of dipoles inside the ROI + Cr = lfr * lfr'; + + % The eigenvalue problem is to determine the nontrivial solutions of the equation + % A*x = l*x + % The generalized eigenvalue decomposition solves + % A*x = l*B*x + % If B is non-singular, the problem could be solved by reducing it into a standard eigenvalue problem + % inv(B)*A*x = l*x + % See http://www.mathworks.com/access/helpdesk/help/techdoc/ref/eig.html + + % compute eigenspace decomposition, THIS IS NUMERICALLY UNSTABLE + [v, d] = eig(Cr, Ca); + % compute eigenspace decomposition, THIS ALSO DOES NOT SOLVE THE PROBLEM + % [v, d] = eig(pinv(Ca, cfg.lbexeigtol)*Cr); + + % select the eigenvectors with a non-zero eigenvalue + dd = diag(d); + dd = dd./max(dd); + sel = dd>cfg.lbexeigtol; + + % remember the subspace projection matrix + grid.subspace{grid.inside(dipindx)} = v(:, sel)'; +end +progress('close'); + +% fill the positions outside the brain with NaNs +for dipindx=grid.outside(:)' + grid.subspace{dipindx} = nan; +end + diff --git a/external/fieldtrip/private/leadsphere_all.m b/external/fieldtrip/private/leadsphere_all.m index 96b8c42..c3c71ef 100644 --- a/external/fieldtrip/private/leadsphere_all.m +++ b/external/fieldtrip/private/leadsphere_all.m @@ -1,6 +1,25 @@ function out=leadsphere_chans(xloc,sensorloc,sensorori) % usage: out=leadsphere_chans(xloc,sensorloc,sensorori) +% Copyright (C) 2003, Guido Nolte +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: leadsphere_all.m 946 2010-04-21 17:51:16Z roboos $ [n,nsens]=size(sensorloc); %n=3 m=? [n,ndip]=size(xloc); diff --git a/external/fieldtrip/private/legs.m b/external/fieldtrip/private/legs.m index 0fb2082..bf6e856 100644 --- a/external/fieldtrip/private/legs.m +++ b/external/fieldtrip/private/legs.m @@ -27,9 +27,26 @@ % % gradbasis: Nx((n+1)^2-1) matrix containing in the j.th row the scalar % product of the gradient of the former with the j.th row of dir -% -% CC Guido Nolte + +% Copyright (C) 2003, Guido Nolte +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: legs.m 946 2010-04-21 17:51:16Z roboos $ [n1,n2]=size(x); diff --git a/external/fieldtrip/private/littleendian.m b/external/fieldtrip/private/littleendian.m index e8766ce..ad83dc5 100644 --- a/external/fieldtrip/private/littleendian.m +++ b/external/fieldtrip/private/littleendian.m @@ -12,12 +12,22 @@ % Copyrigth (C) 2007, Robert Oostenveld % -% $Log: littleendian.m,v $ -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.1 2007/01/04 12:10:42 roboos -% new implementation +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: littleendian.m 945 2010-04-21 17:41:20Z roboos $ val = (typecast(uint8([0 1]), 'uint16')==256); diff --git a/external/fieldtrip/private/lmoutr.m b/external/fieldtrip/private/lmoutr.m index 63af461..fc41ac5 100644 --- a/external/fieldtrip/private/lmoutr.m +++ b/external/fieldtrip/private/lmoutr.m @@ -1,40 +1,90 @@ -function [la, mu, dist] = lmoutr(v1, v2, v3, r); +function [varargout] = funname(varargin) % LMOUTR computes the la/mu parameters of a point projected to a triangle % -% [la, mu, dist] = lmoutr(v1, v2, v3, r) -% +% Use as +% [la, mu, dist] = lmoutr(v1, v2, v3, r) % where v1, v2 and v3 are three vertices of the triangle, and r is % the point that is projected onto the plane spanned by the vertices -% -% also implemented as MEX file -% Copyright (C) 2002, Robert Oostenveld +% Copyright (C) 2002-2009, Robert Oostenveld % -% $Log: lmoutr.m,v $ -% Revision 1.4 2007/01/03 17:02:26 roboos -% removed an incorrect statement from the help +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.3 2003/03/11 15:35:20 roberto -% converted all files from DOS to UNIX +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.2 2003/03/04 21:46:19 roberto -% added CVS log entry and synchronized all copyright labels +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: lmoutr.m 946 2010-04-21 17:51:16Z roboos $ + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% This is the Matlab implementation. +% The mex file is many times faster and therefore preferred. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% function [la, mu, dist] = lmoutr(v1, v2, v3, r); +% +% % compute la/mu parameters +% vec0 = r - v1; +% vec1 = v2 - v1; +% vec2 = v3 - v2; +% vec3 = v3 - v1; +% +% tmp = [vec1' vec3'] \ (vec0'); +% la = tmp(1); +% mu = tmp(2); +% +% % determine the projection onto the plane of the triangle +% proj = v1 + la*vec1 + mu*vec3; +% +% % determine the distance from the original point to its projection +% dist = norm(r-proj); -% compute la/mu parameters -vec0 = r - v1; -vec1 = v2 - v1; -vec2 = v3 - v2; -vec3 = v3 - v1; +% compile the missing mex file on the fly +% remember the original working directory +pwdir = pwd; -tmp = [vec1' vec3'] \ (vec0'); -la = tmp(1); -mu = tmp(2); +% determine the name and full path of this function +funname = mfilename('fullpath'); +mexsrc = [funname '.c']; +[mexdir, mexname] = fileparts(funname); -% determine the projection onto the plane of the triangle -proj = v1 + la*vec1 + mu*vec3; +try + % try to compile the mex file on the fly + warning('trying to compile MEX file from %s', mexsrc); + cd(mexdir); + + if ispc + mex -I. -c geometry.c + mex -I. -c lmoutr.c ; mex lmoutr.c lmoutr.obj geometry.obj + else + mex -I. -c geometry.c + mex -I. -c lmoutr.c ; mex -o lmoutr lmoutr.o geometry.o + end + + cd(pwdir); + success = true; -% determine the distance from the original point to its projection -dist = norm(r-proj); +catch + % compilation failed + disp(lasterr); + error('could not locate MEX file for %s', mexname); + cd(pwdir); + success = false; +end +if success + % execute the mex file that was juist created + funname = mfilename; + funhandle = str2func(funname); + [varargout{1:nargout}] = funhandle(varargin{:}); +end diff --git a/external/fieldtrip/private/lmoutr.mexmaci b/external/fieldtrip/private/lmoutr.mexmaci index 60a491a..dfa8f34 100755 Binary files a/external/fieldtrip/private/lmoutr.mexmaci and b/external/fieldtrip/private/lmoutr.mexmaci differ diff --git a/external/fieldtrip/private/lmoutr.mexw32 b/external/fieldtrip/private/lmoutr.mexw32 index 14105eb..e22e241 100644 Binary files a/external/fieldtrip/private/lmoutr.mexw32 and b/external/fieldtrip/private/lmoutr.mexw32 differ diff --git a/external/fieldtrip/private/lmoutr.mexw64 b/external/fieldtrip/private/lmoutr.mexw64 index 49573ff..bfc5056 100644 Binary files a/external/fieldtrip/private/lmoutr.mexw64 and b/external/fieldtrip/private/lmoutr.mexw64 differ diff --git a/external/fieldtrip/private/loadama.m b/external/fieldtrip/private/loadama.m new file mode 100644 index 0000000..06d144d --- /dev/null +++ b/external/fieldtrip/private/loadama.m @@ -0,0 +1,111 @@ +function [ama] = loadama(filename); + +% LOADAMA read an inverted A-matrix and associated geometry information +% from an ama file that was written by Tom Oostendorp's DIPOLI +% +% Use as +% [ama] = loadama(filename) +% +% See also LOADTRI, LOADMAT + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: loadama.m 945 2010-04-21 17:41:20Z roboos $ + +fid = fopen(filename, 'rb', 'ieee-le'); + +version = fread(fid, 1, 'int'); +if version~=10 + error(sprintf('%s is either not an inverted A matrix, or one of an old version', filename)); +end + +mode = fread(fid, 1, 'int'); +ngeo = fread(fid, 1, 'int'); + +totpnt = 0; +totdhk = 0; +nrow = 0; + +% read the boundaries +geo = []; +for i=1:ngeo + geo(i).name = char(fread(fid, [1 80], 'uchar')); + geo(i).npnt = fread(fid, 1, 'int'); + geo(i).pnt = fread(fid, [3 geo(i).npnt], 'float')'; + geo(i).ndhk = fread(fid, 1, 'int'); + geo(i).dhk = fread(fid, [3 geo(i).ndhk], 'int')' + 1; % Matlab indexing starts at 1 + geo(i).sigmam = fread(fid, 1, 'float'); + geo(i).sigmap = fread(fid, 1, 'float'); + geo(i).geocon = fread(fid, ngeo, 'int'); + geo(i).deflat = fread(fid, ngeo, 'float'); + totpnt = totpnt + geo(i).npnt; + totdhk = totdhk + geo(i).ndhk; +end + +% read the electrodes +if mode~=1 + elec.name = char(fread(fid, [1 80], 'uchar')); + elec.npnt = fread(fid, 1, 'int'); + for i=1:(elec.npnt+1) + elec.el(i).dhk = fread(fid, 1, 'int') + 1; % Matlab indexing starts at 1 + elec.el(i).la = fread(fid, 1, 'float'); + elec.el(i).mu = fread(fid, 1, 'float'); + elec.el(i).name = char(fread(fid, [1 10], 'char')); + % the ELECTRODE c-structure is padded to word boundaries, i.e. to 4 bytes + dum = fread(fid, 2, 'char'); + end + elec.vertex = fread(fid, 1, 'int'); + elec.surface = fread(fid, 1, 'int'); + nrow = nrow + elec.npnt; +else + elec = []; +end + +% read the gradiometers +if mode~=0 + error('gradiometers not yet implemented'); +else + grad = []; +end + +% read the inverted A-matrix +bi = fread(fid, [totpnt nrow], 'float')'; + +% read the isolated source compartment information, if present +iso_sur = fread(fid, 1, 'int') + 1; % Matlab indexing starts at 1 +inner_only = fread(fid, 1, 'int'); +if iso_sur~=0 + iso_totpnt = geo(iso_sur).npnt; + iso_b = fread(fid, [iso_totpnt iso_totpnt], 'float')'; +else + iso_b = []; +end + +fclose(fid); + +% put all local variables into a structure, this is a bit unusual programming style +% the output structure is messy, but contains all relevant information +tmp = whos; +ama = []; +for i=1:length(tmp) + if isempty(strmatch(tmp(i).name, {'tmp', 'fid', 'ans', 'handles'})) + ama = setfield(ama, tmp(i).name, eval(tmp(i).name)); + end +end + diff --git a/external/fieldtrip/private/loadvar.m b/external/fieldtrip/private/loadvar.m new file mode 100644 index 0000000..cf22d47 --- /dev/null +++ b/external/fieldtrip/private/loadvar.m @@ -0,0 +1,26 @@ +function value = loadvar(filename, varname) + +% LOADVAR is a helper function for cfg.inputfile + +% Copyright (C) 2010, Robert Oostenveld +% +% $Id: loadvar.m 1358 2010-07-06 08:34:26Z roboos $ + +if nargin<2 + fprintf('reading variable from file ''%s''\n', filename); +else + fprintf('reading ''%s'' from file ''%s''\n', varname, filename); +end + +var = whos('-file', filename); + +if length(var)==1 + filecontent = load(filename); % read the one variable in the file, regardless of how it is called + value = filecontent.(var.name); + clear filecontent +else + filecontent = load(filename, varname); + value = filecontent.(varname); % read the variable named according to the input specification + clear filecontent +end + diff --git a/external/fieldtrip/private/loreta_ind.mat b/external/fieldtrip/private/loreta_ind.mat new file mode 100644 index 0000000..015ecc2 Binary files /dev/null and b/external/fieldtrip/private/loreta_ind.mat differ diff --git a/external/fieldtrip/private/lowpassfilter.m b/external/fieldtrip/private/lowpassfilter.m index 502b7cb..d1f9a79 100644 --- a/external/fieldtrip/private/lowpassfilter.m +++ b/external/fieldtrip/private/lowpassfilter.m @@ -25,25 +25,23 @@ % Copyright (c) 2003, Robert Oostenveld % -% $Log: lowpassfilter.m,v $ -% Revision 1.5 2006/08/31 07:57:22 roboos -% implemented onepass-reverse filter: usefull for stimulus artifacts, e.g. TMS or electrical stimulation +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.4 2006/06/14 12:36:21 roboos -% added the filter direction as additional option, default is 'twopass', i.e. using filtfilt +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.3 2004/02/11 08:55:13 roberto -% added optional fir1 filter (default still is butterworth), changed -% layout of code for better support of multiple optional arguments, -% extended documentation +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.2 2003/06/12 08:40:44 roberto -% added variable option to determine filter order -% changed default order from 6 to 4 for notch and bandpass -% -% Revision 1.1 2003/04/04 09:53:37 roberto -% new implementation, using 6th order Butterworth FIR filter +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: lowpassfilter.m 952 2010-04-21 18:29:51Z roboos $ % set the default filter order later if nargin<4 diff --git a/external/fieldtrip/private/ltrisect.m b/external/fieldtrip/private/ltrisect.m new file mode 100644 index 0000000..3baa50f --- /dev/null +++ b/external/fieldtrip/private/ltrisect.m @@ -0,0 +1,68 @@ +function [varargout] = funname(varargin) + +% LTRISECT intersects a line with a plane spanned by three vertices +% +% Use as +% [sect] = ltrisect(v1, v2, v3, l1, l2) +% where v1, v2 and v3 are three vertices spanning the plane, and l1 and l2 +% are two points on the line + +% Copyright (C) 2002-2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: ltrisect.m 952 2010-04-21 18:29:51Z roboos $ + +% compile the missing mex file on the fly +% remember the original working directory +pwdir = pwd; + +% determine the name and full path of this function +funname = mfilename('fullpath'); +mexsrc = [funname '.c']; +[mexdir, mexname] = fileparts(funname); + +try + % try to compile the mex file on the fly + warning('trying to compile MEX file from %s', mexsrc); + cd(mexdir); + + if ispc + mex -I. -c geometry.c + mex -I. -c ltrisect.c ; mex ltrisect.c ltrisect.obj geometry.obj + else + mex -I. -c geometry.c + mex -I. -c ltrisect.c ; mex -o ltrisect ltrisect.o geometry.o + end + + cd(pwdir); + success = true; + +catch + % compilation failed + disp(lasterr); + error('could not locate MEX file for %s', mexname); + cd(pwdir); + success = false; +end + +if success + % execute the mex file that was juist created + funname = mfilename; + funhandle = str2func(funname); + [varargout{1:nargout}] = funhandle(varargin{:}); +end diff --git a/external/fieldtrip/private/ltrisect.mexmaci b/external/fieldtrip/private/ltrisect.mexmaci index 78b83fb..116a2dd 100755 Binary files a/external/fieldtrip/private/ltrisect.mexmaci and b/external/fieldtrip/private/ltrisect.mexmaci differ diff --git a/external/fieldtrip/private/ltrisect.mexw32 b/external/fieldtrip/private/ltrisect.mexw32 index c523602..a3381a5 100644 Binary files a/external/fieldtrip/private/ltrisect.mexw32 and b/external/fieldtrip/private/ltrisect.mexw32 differ diff --git a/external/fieldtrip/private/ltrisect.mexw64 b/external/fieldtrip/private/ltrisect.mexw64 index f2a81e0..b482b80 100644 Binary files a/external/fieldtrip/private/ltrisect.mexw64 and b/external/fieldtrip/private/ltrisect.mexw64 differ diff --git a/external/fieldtrip/private/magnetic_dipole.m b/external/fieldtrip/private/magnetic_dipole.m index e73f02c..6d80827 100644 --- a/external/fieldtrip/private/magnetic_dipole.m +++ b/external/fieldtrip/private/magnetic_dipole.m @@ -11,14 +11,23 @@ % Copyright (C) 2003, Robert Oostenveld % -% $Log: magnetic_dipole.m,v $ -% Revision 1.1 2009/01/21 10:32:38 roboos -% moved from forwinv/* and forwinv/mex/* directory to forwinv/private/* to make the CVS layout consistent with the release version +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.1 2003/03/12 09:22:18 roberto -% new implementation, optimized for speed -% based on http://scienceworld.wolfram.com/physics/MagneticDipole.html +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: magnetic_dipole.m 946 2010-04-21 17:51:16Z roboos $ u0 = 1e-7; nchan = size(pos,1); diff --git a/external/fieldtrip/private/match_str.m b/external/fieldtrip/private/match_str.m deleted file mode 100644 index 9903621..0000000 --- a/external/fieldtrip/private/match_str.m +++ /dev/null @@ -1,85 +0,0 @@ -function [sel1, sel2] = match_str(a, b); - -% MATCH_STR looks for matching labels in two listst of strings -% and returns the indices into both the 1st and 2nd list of the matches. -% They will be ordered according to the first input argument. -% -% [sel1, sel2] = match_str(strlist1, strlist2) -% -% The strings can be stored as a char matrix or as an vertical array of -% cells, the matching is done for each row. - -% Copyright (C) 2000, Robert Oostenveld -% -% $Log: match_str.m,v $ -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.7 2008/07/17 10:26:11 roboos -% cleaned up the code a little bit, no functional change -% -% Revision 1.6 2006/11/06 21:11:45 roboos -% also deal with empty [] input -% -% Revision 1.5 2004/11/10 17:11:40 roboos -% reverted to original implementation and reimplemented the speed up -% from scratch. The previous two revisions both were incompatible -% with the original implementation. -% -% Revision 1.4 2004/11/09 15:28:57 roboos -% fixed incompatibility that was introduced by previous speed increase: -% the original version gave back double occurences, and other fieldtrip -% functions (sourceanalysis) rely on this. The previously commited -% version only gave back one occurence of each hit, this is fixed by jansch -% in this version -% -% Revision 1.3 2004/10/22 15:59:41 roboos -% large speed increase by replacing 2 nested for loops by a standard matlab function (intersect) -% -% Revision 1.2 2003/03/17 10:37:28 roberto -% improved general help comments and added copyrights - -% ensure that both are cell-arrays -if isempty(a) - a = {}; -elseif ~iscell(a) - a = cellstr(a); -end -if isempty(b) - b = {}; -elseif ~iscell(b) - b = cellstr(b); -end - -% regardless of what optimizations are implemented, the code should remain -% functionally compatible to the original, which is -% for i=1:length(a) -% for j=1:length(b) -% if strcmp(a(i),b(j)) -% sel1 = [sel1; i]; -% sel2 = [sel2; j]; -% end -% end -% end - -% ensure that both are column vectors -a = a(:); -b = b(:); -Na = numel(a); -Nb = numel(b); - -% replace all unique strings by a unique number and use the fact that -% numeric comparisons are much faster than string comparisons -[dum1, dum2, c] = unique([a; b]); -a = c(1:Na); -b = c((Na+1):end); - -sel1 = []; -sel2 = []; -for i=1:length(a) - % s = find(strcmp(a(i), b)); % for string comparison - s = find(a(i)==b); % for numeric comparison - sel2 = [sel2; s]; - s(:) = i; - sel1 = [sel1; s]; -end diff --git a/external/fieldtrip/private/matlabversion.m b/external/fieldtrip/private/matlabversion.m index 9081071..1e64ed2 100644 --- a/external/fieldtrip/private/matlabversion.m +++ b/external/fieldtrip/private/matlabversion.m @@ -17,16 +17,23 @@ % Copyright (C) 2006, Robert Oostenveld % -% $Log: matlabversion.m,v $ -% Revision 1.3 2007/07/07 12:10:02 roboos -% detect matlab version 7.0.1 and 7.0.4 and treat as 7.0 +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.2 2006/06/08 07:08:38 roboos -% convert string into number +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.1 2006/05/29 07:58:25 roboos -% new helper function +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: matlabversion.m 952 2010-04-21 18:29:51Z roboos $ s = ver('matlab'); v = s.Version; diff --git a/external/fieldtrip/private/mbmatrix.m b/external/fieldtrip/private/mbmatrix.m deleted file mode 100644 index 52735be..0000000 --- a/external/fieldtrip/private/mbmatrix.m +++ /dev/null @@ -1,3 +0,0 @@ -function bool = mbmatrix(x) - -bool = (ndims(x) == 2) & (prod(size(x)) > 1); diff --git a/external/fieldtrip/private/mbreal.m b/external/fieldtrip/private/mbreal.m deleted file mode 100644 index acaede7..0000000 --- a/external/fieldtrip/private/mbreal.m +++ /dev/null @@ -1,5 +0,0 @@ -function mbreal(a); - -if ~isreal(a) - error('Argument to mbreal must be real'); -end diff --git a/external/fieldtrip/private/mbrealscalar.m b/external/fieldtrip/private/mbrealscalar.m deleted file mode 100644 index 50b33e5..0000000 --- a/external/fieldtrip/private/mbrealscalar.m +++ /dev/null @@ -1,4 +0,0 @@ -function mbrealscalar(a) - -mbreal(a); -mbscalar(a); diff --git a/external/fieldtrip/private/mbrealvector.m b/external/fieldtrip/private/mbrealvector.m deleted file mode 100644 index 9937964..0000000 --- a/external/fieldtrip/private/mbrealvector.m +++ /dev/null @@ -1,4 +0,0 @@ -function mbrealvector(a); - -mbvector(a); -mbreal(a); diff --git a/external/fieldtrip/private/mbscalar.m b/external/fieldtrip/private/mbscalar.m deleted file mode 100644 index 0db105b..0000000 --- a/external/fieldtrip/private/mbscalar.m +++ /dev/null @@ -1,5 +0,0 @@ -function mbscalar(a); - -if ~all(size(a)==1) - error('Argument to mbscalar must be scalar'); -end diff --git a/external/fieldtrip/private/mbvector.m b/external/fieldtrip/private/mbvector.m deleted file mode 100644 index 2dfb120..0000000 --- a/external/fieldtrip/private/mbvector.m +++ /dev/null @@ -1,5 +0,0 @@ -function mbvector(a) - -if ndims(a) > 2 | (size(a, 1) > 1 & size(a, 2) > 1) - error('Argument to mbvector must be a vector'); -end diff --git a/external/fieldtrip/private/meg_forward.m b/external/fieldtrip/private/meg_forward.m index 5f54bcb..4bbf9b2 100644 --- a/external/fieldtrip/private/meg_forward.m +++ b/external/fieldtrip/private/meg_forward.m @@ -21,15 +21,29 @@ % % note: it is assumed that locations are in cm, and dipole moments in nAm. % Then the field is in fT. -% -% written by Guido Nolte - +% Copyright (C) 2003, Guido Nolte +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: meg_forward.m 946 2010-04-21 17:51:16Z roboos $ device_sens=forwpar.device_sens; - - field_sens_sphere=getfield_sphere(dip_par,forwpar.device_sens,forwpar.center); field=field_sens_sphere;clear field_sens_sphere; if isfield(forwpar,'device_ref') diff --git a/external/fieldtrip/private/meg_ini.m b/external/fieldtrip/private/meg_ini.m index e127f95..e39335d 100644 --- a/external/fieldtrip/private/meg_ini.m +++ b/external/fieldtrip/private/meg_ini.m @@ -27,9 +27,26 @@ % forpwar: structure containing all parameters needed for forward % calculation % note: it is assumed that locations are in cm. -% -% written by Guido Nolte +% Copyright (C) 2003, Guido Nolte +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: meg_ini.m 946 2010-04-21 17:51:16Z roboos $ if nargin==4 if order>0; diff --git a/external/fieldtrip/private/meg_leadfield1.m b/external/fieldtrip/private/meg_leadfield1.m deleted file mode 100644 index c3ef0af..0000000 --- a/external/fieldtrip/private/meg_leadfield1.m +++ /dev/null @@ -1,131 +0,0 @@ -function [varargout] = funname(varargin) - -% MEG_LEADFIELD1 magnetic leadfield for a dipole in a homogenous sphere -% -% [lf] = meg_leadfield1(R, pos, ori) -% -% with input arguments -% R position dipole -% pos position magnetometers -% ori orientation magnetometers -% -% The center of the homogenous sphere is in the origin, the field -% of the dipole is not dependent on the sphere radius. -% -% This function is also implemented as MEX file. - -% adapted from Luetkenhoener, Habilschrift '92 -% optimized for speed using temporary variables -% the mex implementation is a literary copy of this - -% Copyright (C) 2002-2008, Robert Oostenveld -% -% $Log: meg_leadfield1.m,v $ -% Revision 1.3 2009/06/17 13:38:06 roboos -% cleaned up documentation -% -% Revision 1.2 2009/03/12 11:05:04 roboos -% implemented auto-compilation of the mex file in case it is missing -% -% Revision 1.1 2009/01/21 10:32:38 roboos -% moved from forwinv/* and forwinv/mex/* directory to forwinv/private/* to make the CVS layout consistent with the release version -% -% Revision 1.8 2008/07/21 20:32:27 roboos -% updated documentation -% -% Revision 1.7 2008/03/05 16:27:33 roboos -% updated documentation -% -% Revision 1.5 2003/03/28 10:01:15 roberto -% created mex implementation, updated help and comments -% -% Revision 1.4 2003/03/28 09:01:55 roberto -% fixed important bug (incorrect use of a temporary variable) -% -% Revision 1.3 2003/03/12 08:19:45 roberto -% improved help -% -% Revision 1.2 2003/03/11 14:45:37 roberto -% updated help and copyrights -% - -% compile the missing mex file on the fly -% remember the original working directory -pwdir = pwd; - -% determine the name and full path of this function -funname = mfilename('fullpath'); -mexsrc = [funname '.c']; -[mexdir, mexname] = fileparts(funname); - -try - % try to compile the mex file on the fly - warning('trying to compile MEX file from %s', mexsrc); - cd(mexdir); - mex(mexsrc); - cd(pwdir); - success = true; - -catch - % compilation failed - disp(lasterr); - error('could not locate MEX file for %s', mexname); - cd(pwdir); - success = false; -end - -if success - % execute the mex file that was juist created - funname = mfilename; - funhandle = str2func(funname); - [varargout{1:nargout}] = funhandle(varargin{:}); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% THE FOLLOWING CODE CORRESPONDS WITH THE ORIGINAL IMPLEMENTATION -% function [lf] = meg_leadfield1(R, Rm, Um); -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% Nchans = size(Rm, 1); -% -% lf = zeros(Nchans,3); -% -% tmp2 = norm(R); -% -% for i=1:Nchans -% r = Rm(i,:); -% u = Um(i,:); -% -% tmp1 = norm(r); -% % tmp2 = norm(R); -% tmp3 = norm(r-R); -% tmp4 = dot(r,R); -% tmp5 = dot(r,r-R); -% tmp6 = dot(R,r-R); -% tmp7 = (tmp1*tmp2)^2 - tmp4^2; % cross(r,R)^2 -% -% alpha = 1 / (-tmp3 * (tmp1*tmp3+tmp5)); -% A = 1/tmp3 - 2*alpha*tmp2^2 - 1/tmp1; -% B = 2*alpha*tmp4; -% C = -tmp6/(tmp3^3); -% -% if tmp7. +% +% $Id: megplanar_fitplane.m 952 2010-04-21 18:29:51Z roboos $ + +[pnt, ori, lab] = channelposition(grad); +Ngrad = length(lab); +distance = zeros(Ngrad,Ngrad); + +for i=1:Ngrad + for j=(i+1):Ngrad + distance(i,j) = norm(pnt(i,:)-pnt(j,:)); + distance(j,i) = distance(i,j); + end +end + +fprintf('minimum distance between gradiometers is %6.2f %s\n', min(distance(find(distance~=0))), grad.unit); +fprintf('maximum distance between gradiometers is %6.2f %s\n', max(distance(find(distance~=0))), grad.unit); + +% select the channels that are neighbours, channel is not a neighbour of itself +neighbsel = distance. +% +% $Id: megplanar_orig.m 952 2010-04-21 18:29:51Z roboos $ + +[pnt, ori, lab] = channelposition(grad); +Ngrad = length(lab); +distance = zeros(Ngrad,Ngrad); + +for i=1:Ngrad + for j=(i+1):Ngrad + distance(i,j) = norm(pnt(i,:)-pnt(j,:)); + distance(j,i) = distance(i,j); + end +end + +fprintf('minimum distance between gradiometers is %6.2f %s\n', min(distance(find(distance~=0))), grad.unit); +fprintf('maximum distance between gradiometers is %6.2f %s\n', max(distance(find(distance~=0))), grad.unit); + +% select the channels that are neighbours, channel is not a neighbour of itself +neighbsel = distance. +% +% $Id: megplanar_sincos.m 952 2010-04-21 18:29:51Z roboos $ + +[pnt, ori, lab] = channelposition(grad); +Ngrad = length(lab); +distance = zeros(Ngrad,Ngrad); + +for i=1:Ngrad + for j=(i+1):Ngrad + distance(i,j) = norm(pnt(i,:)-pnt(j,:)); + distance(j,i) = distance(i,j); + end +end + +fprintf('minimum distance between gradiometers is %6.2f %s\n', min(distance(find(distance~=0))), grad.unit); +fprintf('maximum distance between gradiometers is %6.2f %s\n', max(distance(find(distance~=0))), grad.unit); + +% select the channels that are neighbours, channel is not a neighbour of itself +neighbsel = distancectf151) -% -% Revision 1.58 2009/02/11 21:17:22 jansch -% changed key-sensors from which to compute the transformation matrix between -% template gradiometer array and original for 4d-248 system. fixed some minor -% bugs when target and original grad do not contain the same sensors. built -% in the possibility to prune the leadfield-matrix according to a number of -% spatial components (i.e. if cfg.pruneratio>1 and integer). -% -% Revision 1.57 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.56 2008/12/02 12:22:00 roboos -% allow data to be realigned AND simultaneously interpolated to another MEG sensor type, e.g. from ctf151 to ctf275 -% -% Revision 1.55 2008/11/25 14:56:52 estmee -% Documentation update -% -% Revision 1.54 2008/11/21 12:48:17 sashae -% added call to checkconfig at start and end of function -% -% Revision 1.53 2008/10/02 15:32:21 sashae -% replaced call to createsubcfg with checkconfig -% -% Revision 1.52 2008/09/30 16:45:55 sashae -% checkconfig: checks if the input cfg is valid for this function -% -% Revision 1.51 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.50 2008/07/15 19:56:44 roboos -% moved cfg details for dipole grid to subcfg (cfg.grid)subcfg (cfg.grid.xxx) - -fieldtripdefs - -cfg = checkconfig(cfg, 'trackconfig', 'on'); - -% check if the input data is valid for this function -data = checkdata(data, 'datatype', 'raw', 'feedback', 'yes', 'ismeg', 'yes'); - -% check if the input cfg is valid for this function -cfg = checkconfig(cfg, 'renamed', {'plot3d', 'feedback'}); -cfg = checkconfig(cfg, 'renamedval', {'headshape', 'headmodel', []}); -cfg = checkconfig(cfg, 'required', {'inwardshift', 'template'}); - -% set the default configuration -if ~isfield(cfg, 'headshape'), cfg.headshape = []; end -if ~isfield(cfg, 'pruneratio'), cfg.pruneratio = 1e-3; end -if ~isfield(cfg, 'spheremesh'), cfg.spheremesh = 642; end -if ~isfield(cfg, 'verify'), cfg.verify = 'yes'; end -if ~isfield(cfg, 'feedback'), cfg.feedback = 'yes'; end -if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end -if ~isfield(cfg, 'channel'), cfg.channel = 'MEG'; end -if ~isfield(cfg, 'topoparam'), cfg.topoparam = 'rms'; end - -%do realignment per trial -pertrial = all(ismember({'nasX';'nasY';'nasZ';'lpaX';'lpaY';'lpaZ';'rpaX';'rpaY';'rpaZ'}, data.label)); - -% put the low-level options pertaining to the dipole grid in their own field -cfg = checkconfig(cfg, 'createsubcfg', {'grid'}); - -% select trials of interest -if ~strcmp(cfg.trials, 'all') - if islogical(cfg.trials), cfg.trials=find(cfg.trials); end - fprintf('selecting %d trials\n', length(cfg.trials)); - data.trial = data.trial(cfg.trials); - data.time = data.time(cfg.trials); - % update the trial definition (trl) - if isfield(data, 'cfg') % try to locate the trl in the nested configuration - trl = findcfg(data.cfg, 'trl'); - else - trl = []; - end - if isempty(trl) - % a trial definition is expected in each continuous data set - warning('could not locate the trial definition ''trl'' in the data structure'); - else - cfg.trlold=trl; - cfg.trl=trl(cfg.trials,:); - end -end - -Ntrials = length(data.trial); - -% retain only the MEG channels in the data and temporarily store -% the rest, these will be added back to the transformed data later. -cfg.channel = channelselection(cfg.channel, data.label); -dataindx = match_str(data.label, cfg.channel); -restindx = setdiff(1:length(data.label),dataindx); -if ~isempty(restindx) - fprintf('removing %d non-MEG channels from the data\n', length(restindx)); - rest.label = data.label(restindx); % first remember the rest - data.label = data.label(dataindx); % then reduce the data - for i=1:Ntrials - rest.trial{i} = data.trial{i}(restindx,:); % first remember the rest - data.trial{i} = data.trial{i}(dataindx,:); % then reduce the data - end -else - rest.label = {}; - rest.trial = {}; -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% construct the average template gradiometer array -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -Ntemplate = length(cfg.template); -for i=1:Ntemplate - if isstr(cfg.template{i}), - fprintf('reading template sensor position from %s\n', cfg.template{i}); - template(i) = read_sens(cfg.template{i}); - elseif isstruct(cfg.template{i}) && isfield(cfg.template{i}, 'pnt') && isfield(cfg.template{i}, 'ori') && isfield(cfg.template{i}, 'tra'), - template(i) = cfg.template{i}; - end -end - -% to construct the average location of the MEG sensors, 4 channels are needed that should be sufficiently far apart -switch senstype(template(1)) -case {'ctf151' 'ctf275'} - labC = 'MZC01'; - labF = 'MZF03'; - labL = 'MLC21'; - labR = 'MRC21'; -case {'ctf151_planar' 'ctf275_planar'} - labC = 'MZC01_dH'; - labF = 'MZF03_dH'; - labL = 'MLC21_dH'; - labR = 'MRC21_dH'; -case {'bti148'} - labC = 'A14'; - labF = 'A2'; - labL = 'A15'; - labR = 'A29'; -case {'bti248'} - labC = 'A19'; - labF = 'A2'; - labL = 'A44'; - labR = 'A54'; -otherwise - % this could in principle be added to the cfg, but better is to have a more exhaustive list here - error('unsupported MEG system for realigning, please ask on the mailing list'); -end - -templ.meanC = [0 0 0]; -templ.meanF = [0 0 0]; -templ.meanL = [0 0 0]; -templ.meanR = [0 0 0]; -for i=1:Ntemplate - % determine the 4 ref sensors for this individual template helmet - % FIXME this assumes that coils and sensors coincide, this is generally not - % true, however there is not much of a problem, because the points are only - % used to get a transformation matrix - indxC = strmatch(labC, template(i).label, 'exact'); - indxF = strmatch(labF, template(i).label, 'exact'); - indxL = strmatch(labL, template(i).label, 'exact'); - indxR = strmatch(labR, template(i).label, 'exact'); - if isempty(indxC) || isempty(indxF) || isempty(indxL) || isempty(indxR) - error('not all 4 sensors were found that are needed to rotate/translate'); - end - % add them to the sum, to compute mean location of each ref sensor - templ.meanC = templ.meanC + template(i).pnt(indxC,:); - templ.meanF = templ.meanF + template(i).pnt(indxF,:); - templ.meanL = templ.meanL + template(i).pnt(indxL,:); - templ.meanR = templ.meanR + template(i).pnt(indxR,:); -end -templ.meanC = templ.meanC / Ntemplate; -templ.meanF = templ.meanF / Ntemplate; -templ.meanL = templ.meanL / Ntemplate; -templ.meanR = templ.meanR / Ntemplate; - -% construct two direction vectors that define the helmet orientation -templ.dirCF = (templ.meanF - templ.meanC); -templ.dirRL = (templ.meanL - templ.meanR); -% construct three orthonormal direction vectors -templ.dirX = normalize(templ.dirCF); -templ.dirY = normalize(templ.dirRL - dot(templ.dirRL, templ.dirX) * templ.dirX); -templ.dirZ = cross(templ.dirX, templ.dirY); -templ.tra = fixedbody(templ.meanC, templ.dirX, templ.dirY, templ.dirZ); - -% determine the 4 ref sensors for the helmet that belongs to this dataset -indxC = strmatch(labC, template(1).label, 'exact'); -indxF = strmatch(labF, template(1).label, 'exact'); -indxL = strmatch(labL, template(1).label, 'exact'); -indxR = strmatch(labR, template(1).label, 'exact'); -if isempty(indxC) || isempty(indxF) || isempty(indxL) || isempty(indxR) - error('not all 4 sensors were found that are needed to rotate/translate'); -end - -% construct two direction vectors that define the helmet orientation -orig.dirCF = template(1).pnt(indxF,:) - template(1).pnt(indxC,:); -orig.dirRL = template(1).pnt(indxL,:) - template(1).pnt(indxR,:); -% construct three orthonormal direction vectors -orig.dirX = normalize(orig.dirCF); -orig.dirY = normalize(orig.dirRL - dot(orig.dirRL, orig.dirX) * orig.dirX); -orig.dirZ = cross(orig.dirX, orig.dirY); -orig.tra = fixedbody(template(1).pnt(indxC,:), orig.dirX, orig.dirY, orig.dirZ); - -% compute the homogenous transformation matrix and transform the positions -tra = inv(templ.tra) * orig.tra; -pnt = template(1).pnt; -pnt(:,4) = 1; -pnt = (tra * pnt')'; -pnt = pnt(:,1:3); - -% remove the translation from the transformation matrix and rotate the orientations -tra(:,4) = [0 0 0 1]'; -ori = template(1).ori; -ori(:,4) = 1; -ori = (tra * ori')'; -ori = ori(:,1:3); - -tmp_label = template(1).label; -tmp_tra = template(1).tra; -tmp_unit = template(1).unit; - -% construct the final template gradiometer definition -template = []; -template.grad.pnt = pnt; -template.grad.ori = ori; -% keep the same labels and the linear weights of the coils -template.grad.label = tmp_label; -template.grad.tra = tmp_tra; -template.grad.unit = tmp_unit; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% PREPARE_VOL_SENS will match the data labels, the gradiometer labels and the -% volume model labels (in case of a multisphere model) and result in a gradiometer -% definition that only contains the gradiometers that are present in the data. -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -volcfg = []; -if isfield(cfg, 'hdmfile') - volcfg.hdmfile = cfg.hdmfile; -elseif isfield(cfg, 'vol') - volcfg.vol = cfg.vol; -end -volcfg.grad = data.grad; -volcfg.channel = data.label; % this might be a subset of the MEG channels -[volold, data.grad] = prepare_headmodel(volcfg); - -% note that it is neccessary to keep the two volume conduction models -% seperate, since the single-shell Nolte model contains gradiometer specific -% precomputed parameters. Note that this is not guaranteed to result in a -% good projection for local sphere models. -volcfg.grad = template.grad; -volcfg.channel = 'MEG'; % include all MEG channels -[volnew, template.grad] = prepare_headmodel(volcfg); - -if strcmp(senstype(data.grad), senstype(template.grad)) - [id, it] = match_str(data.grad.label, template.grad.label); - fprintf('mean distance towards template gradiometers is %.2f %s\n', mean(sum((data.grad.pnt(id,:)-template.grad.pnt(it,:)).^2, 2).^0.5), template.grad.unit); -else - % the projection is from one MEG system to another MEG system, which makes a comparison of the data difficult - cfg.feedback = 'no'; - cfg.verify = 'no'; -end - -% create the dipole grid on which the data will be projected -grid = prepare_dipole_grid(cfg, volold, data.grad); -pos = grid.pos; - -% sometimes some of the dipole positions are nan, due to problems with the headsurface triangulation -% remove them to prevent problems with the forward computation -sel = find(any(isnan(pos(:,1)),2)); -pos(sel,:) = []; - -% compute the forward model for the new gradiometer positions -fprintf('computing forward model for %d dipoles\n', size(pos,1)); -lfnew = compute_leadfield(pos, template.grad, volnew); -if ~pertrial, - %this needs to be done only once - lfold = compute_leadfield(pos, data.grad, volold); - [realign, noalign, bkalign] = computeprojection(lfold, lfnew, cfg.pruneratio, cfg.verify); -else - %the forward model and realignment matrices have to be computed for each trial - %this also goes for the singleshell volume conductor model - %x = which('rigidbodyJM'); %this function is needed - %if isempty(x), - % error('you are trying out experimental code for which you need some extra functionality which is currently not in the release version of fieldtrip. if you are interested in trying it out, contact jan-mathijs'); - %end -end - -% interpolate the data towards the template gradiometers -for i=1:Ntrials - fprintf('realigning trial %d\n', i); - if pertrial, - %warp the gradiometer array according to the motiontracking data - sel = match_str(rest.label, {'nasX';'nasY';'nasZ';'lpaX';'lpaY';'lpaZ';'rpaX';'rpaY';'rpaZ'}); - hmdat = rest.trial{i}(sel,:); - if ~all(hmdat==repmat(hmdat(:,1),[1 size(hmdat,2)])) - error('only one position per trial is at present allowed'); - else - %M = rigidbodyJM(hmdat(:,1)) - M = headcoordinates(hmdat(1:3,1),hmdat(4:6,1),hmdat(7:9,1)); - grad = transform_sens(M, data.grad); - end - - volcfg.grad = grad; - %compute volume conductor - [volold, grad] = prepare_headmodel(volcfg); - %compute forward model - lfold = compute_leadfield(pos, grad, volold); - %compute projection matrix - [realign, noalign, bkalign] = computeprojection(lfold, lfnew, cfg.pruneratio, cfg.verify); - end - data.realign{i} = realign * data.trial{i}; - if strcmp(cfg.verify, 'yes') - % also compute the residual variance when interpolating - [id,it] = match_str(data.grad.label, template.grad.label); - rvrealign = rv(data.trial{i}(id,:), data.realign{i}(it,:)); - fprintf('original -> template RV %.2f %%\n', 100 * mean(rvrealign)); - datnoalign = noalign * data.trial{i}; - datbkalign = bkalign * data.trial{i}; - rvnoalign = rv(data.trial{i}, datnoalign); - rvbkalign = rv(data.trial{i}, datbkalign); - fprintf('original -> original RV %.2f %%\n', 100 * mean(rvnoalign)); - fprintf('original -> template -> original RV %.2f %%\n', 100 * mean(rvbkalign)); - end -end - -% plot the topography before and after the realignment -if strcmp(cfg.feedback, 'yes') - - warning('showing MEG topography (RMS value over time) in the first trial only'); - Nchan = length(data.grad.label); - [id,it] = match_str(data.grad.label, template.grad.label); - pnt1 = data.grad.pnt(id,:); - pnt2 = template.grad.pnt(it,:); - prj1 = elproj(pnt1); tri1 = delaunay(prj1(:,1), prj1(:,2)); - prj2 = elproj(pnt2); tri2 = delaunay(prj2(:,1), prj2(:,2)); - - switch cfg.topoparam - case 'rms' - p1 = sqrt(mean(data.trial{1}(id,:).^2, 2)); - p2 = sqrt(mean(data.realign{1}(it,:).^2, 2)); - case 'svd' - [u, s, v] = svd(data.trial{1}(id,:)); p1 = u(:,1); - [u, s, v] = svd(data.realign{1}(it,:)); p2 = u(:,1); - otherwise - error('unsupported cfg.topoparam'); - end - - X = [pnt1(:,1) pnt2(:,1)]'; - Y = [pnt1(:,2) pnt2(:,2)]'; - Z = [pnt1(:,3) pnt2(:,3)]'; - - % show figure with old an new helmets, volume model and dipole grid - figure - tmpcfg = []; - tmpcfg.vol = volold; - tmpcfg.grad = data.grad; - tmpcfg.grid = grid; - tmpcfg.plotsensors = 'no'; % these are plotted seperately below - headmodelplot(tmpcfg); - hold on - plot3(pnt1(:,1), pnt1(:,2), pnt1(:,3), 'r.') % original positions - plot3(pnt2(:,1), pnt2(:,2), pnt2(:,3), 'g.') % template positions - line(X,Y,Z, 'color', 'black'); - view(-90, 90); - - % show figure with data on old helmet location - figure - hold on - plot3(pnt1(:,1), pnt1(:,2), pnt1(:,3), 'r.') % original positions - plot3(pnt2(:,1), pnt2(:,2), pnt2(:,3), 'g.') % template positions - line(X,Y,Z, 'color', 'black'); - axis equal; axis vis3d - triplot(pnt1, tri1, p1); - title('RMS, before realignment') - view(-90, 90) - - % show figure with data on new helmet location - figure - hold on - plot3(pnt1(:,1), pnt1(:,2), pnt1(:,3), 'r.') % original positions - plot3(pnt2(:,1), pnt2(:,2), pnt2(:,3), 'g.') % template positions - line(X,Y,Z, 'color', 'black'); - axis equal; axis vis3d - triplot(pnt2, tri2, p2); - title('RMS, after realignment') - view(-90, 90) -end - -% store the realigned data in a new structure -interp.label = template.grad.label; -interp.grad = template.grad; % replace with the template gradiometer array -interp.trial = data.realign; % remember the processed data -interp.fsample = data.fsample; -interp.time = data.time; - -% add the rest channels back to the data, these were not interpolated -if ~isempty(rest.label) - fprintf('adding %d non-MEG channels back to the data (', length(rest.label)); - fprintf('%s, ', rest.label{1:end-1}); - fprintf('%s)\n', rest.label{end}); - for trial=1:length(rest.trial) - interp.trial{trial} = [interp.trial{trial}; rest.trial{trial}]; - end - interp.label = [interp.label; rest.label]; -end - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% store the configuration of this function call, including that of the previous function call -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: megrealign.m,v 1.62 2009/10/12 14:12:03 jansch Exp $'; -% remember the configuration details of the input data -try, cfg.previous = data.cfg; end -% remember the exact configuration details in the output -interp.cfg = cfg; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% subfunction that computes the projection matrix(ces) -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [realign, noalign, bkalign] = computeprojection(lfold, lfnew, pruneratio, verify) - -% compute this inverse only once, although it is used twice -tmp = prunedinv(lfold, pruneratio); -% compute the three interpolation matrices -fprintf('computing interpolation matrix #1\n'); -realign = lfnew * tmp; -if strcmp(verify, 'yes') - fprintf('computing interpolation matrix #2\n'); - noalign = lfold * tmp; - fprintf('computing interpolation matrix #3\n'); - bkalign = lfold * prunedinv(lfnew, pruneratio) * realign; -else - noalign = []; - bkalign = []; -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% subfunction that computes the inverse using a pruned SVD -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [lfi] = prunedinv(lf, r) -[u, s, v] = svd(lf); -if r<1, - % treat r as a ratio - p = find(s<(s(1,1)*r) & s~=0); -else - % treat r as the number of spatial components to keep - diagels = 1:(min(size(s))+1):(min(size(s)).^2); - p = diagels((r+1):end); -end -fprintf('pruning %d from %d, i.e. removing the %d smallest spatial components\n', length(p), min(size(s)), length(p)); -s(p) = 0; -s(find(s~=0)) = 1./s(find(s~=0)); -lfi = v * s' * u'; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% subfunction that computes the homogenous translation matrix -% corresponding to a fixed body rotation and translation -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [h] = fixedbody(center, dirx, diry, dirz); -rot = eye(4); -rot(1:3,1:3) = inv(eye(3) / [dirx; diry; dirz]); -tra = eye(4); -tra(1:4,4) = [-center 1]'; -h = rot * tra; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% subfunction that scales a vector to unit length -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [v] = normalize(v); -v = v / sqrt(v * v'); diff --git a/external/fieldtrip/private/megrepair.m b/external/fieldtrip/private/megrepair.m deleted file mode 100644 index a8dc806..0000000 --- a/external/fieldtrip/private/megrepair.m +++ /dev/null @@ -1,14 +0,0 @@ -function [data] = megrepair(cfg, data) - -% MEGREPAIR is deprecated, please use CHANNELREPAIR - -% Copyright (C) 2003-2009, Robert Oostenveld, F.C. Donders Centre -% -% $Log: megrepair.m,v $ -% Revision 1.21 2009/02/04 09:33:49 roboos -% renamed megrepair to channelrepair, to make clear that it is not a MEG specific function -% - -warning('MEGREPAIR is deprecated, please use CHANNELREPAIR'); -data = channelrepair(cfg, data); - diff --git a/external/fieldtrip/private/mergeconfig.m b/external/fieldtrip/private/mergeconfig.m new file mode 100644 index 0000000..31b8533 --- /dev/null +++ b/external/fieldtrip/private/mergeconfig.m @@ -0,0 +1,34 @@ +function output = mergeconfig(input, default) + +% MERGECONFIG + +% Copyright (C) 2009, Robert Oostenveld +% +% $Log: mergeconfig.m,v $ +% Revision 1.1 2009/10/19 14:19:21 roboos +% first version, to work with databrowser +% + +% FIXME also deal with configuration objects +if ~isstruct(input) + input = struct([]); +end + +% FIXME also deal with configuration objects +if ~isstruct(default) + default = struct([]); +end + +fni = fieldnames(input); +fnd = fieldnames(default); +fnd = setdiff(fnd, fni); + +for i=1:length(fnd) + output.(fnd{i}) = default.(fnd{i}); +end + +for i=1:length(fni) + output.(fni{i}) = input.(fni{i}); +end + + diff --git a/external/fieldtrip/private/minimumnormestimate.m b/external/fieldtrip/private/minimumnormestimate.m deleted file mode 100644 index 94c32f9..0000000 --- a/external/fieldtrip/private/minimumnormestimate.m +++ /dev/null @@ -1,165 +0,0 @@ -function [dipout] = minimumnormestimate(dip, grad, vol, dat, varargin); - -% MINIMUMNORMESTIMATE computes a linear estimate of the current -% in a distributed source model -% -% Use as -% [dipout] = minimumnormestimate(dip, grad, vol, dat, ...) -% -% Optional input arguments should come in key-value pairs and can include -% 'noisecov' = Nchan x Nchan matrix with noise covariance -% 'sourcecov' = Nsource x Nsource matrix with source covariance (can be empty, the default will then be identity) -% 'lambda' = scalar, regularisation parameter (can be empty, it will then be estimated from snr) -% 'snr' = scalar, signal to noise ratio -% 'reducerank' = reduce the leadfield rank, can be 'no' or a number (e.g. 2) -% 'normalize' = normalize the leadfield -% 'normalizeparam' = parameter for depth normalization (default = 0.5) -% -% Note that leadfield normalization (depth regularisation) should be -% done by scaling the leadfields outside this function, e.g. in -% prepare_leadfield. -% -% This implements -% * Dale AM, Liu AK, Fischl B, Buckner RL, Belliveau JW, Lewine JD, -% Halgren E (2000): Dynamic statistical parametric mapping: combining -% fMRI and MEG to produce high-resolution spatiotemporal maps of -% cortical activity. Neuron 26:55-67. -% * Arthur K. Liu, Anders M. Dale, and John W. Belliveau (2002): Monte -% Carlo Simulation Studies of EEG and MEG Localization Accuracy. -% Human Brain Mapping 16:47-62. -% * Fa-Hsuan Lin, Thomas Witzel, Matti S. Hamalainen, Anders M. Dale, -% John W. Belliveau, and Steven M. Stufflebeam (2004): Spectral -% spatiotemporal imaging of cortical oscillations and interactions -% in the human brain. NeuroImage 23:582-595. - -% TODO implement the following options -% - keepleadfield -% - keepfilter -% - keepinverse (i.e. equivalent to keepfilter) - -% Copyright (C) 2004-2008, Robert Oostenveld -% -% $Log: minimumnormestimate.m,v $ -% Revision 1.7 2008/04/21 14:50:10 roboos -% added full literature references to documentation -% -% Revision 1.6 2008/03/18 13:18:06 roboos -% added optional settings for compute_leadfield -% fixed typo in equation (would have cased Matlab error) -% updated documentation -% -% Revision 1.5 2007/08/07 08:48:21 roboos -% implemented regularized MNE according to the method described by Dale and Liu -% -% Revision 1.4 2006/06/22 12:05:54 roboos -% changed a comment and a whitespace -% -% Revision 1.3 2006/05/10 08:17:30 roboos -% some changes in comments and documentation -% -% Revision 1.2 2005/10/05 06:32:39 roboos -% minor change in user feedback -% -% Revision 1.1 2004/09/21 13:26:49 roboos -% initial implementation -% - -% ensure that these are row-vectors -dip.inside = dip.inside(:)'; -dip.outside = dip.outside(:)'; - -% get the optional inputs for the MNE method according to Dale et al 2000, and Liu et al. 2002 -noisecov = keyval('noisecov', varargin); -sourcecov = keyval('sourcecov', varargin); -lambda = keyval('lambda', varargin); % can be empty, it will then be estimated based on SNR -snr = keyval('snr', varargin); % is used to estimate lambda if lambda is not specified -% these settings pertain to the forward model, the defaults are set in compute_leadfield -reducerank = keyval('reducerank', varargin); -normalize = keyval('normalize', varargin); -normalizeparam = keyval('normalizeparam', varargin); - -if ~isfield(dip, 'leadfield') - fprintf('computing forward model\n'); - if isfield(dip, 'mom') - for i=dip.inside - % compute the leadfield for a fixed dipole orientation - dip.leadfield{i} = compute_leadfield(dip.pos(i,:), grad, vol, 'reducerank', reducerank, 'normalize', normalize, 'normalizeparam', normalizeparam) * dip.mom(:,i); - end - else - for i=dip.inside - % compute the leadfield - dip.leadfield{i} = compute_leadfield(dip.pos(i,:), grad, vol, 'reducerank', reducerank, 'normalize', normalize, 'normalizeparam', normalizeparam); - end - end - for i=dip.outside - dip.leadfield{i} = nan; - end -else - fprintf('using specified forward model\n'); -end - -Nchan = length(grad.label); - -% count the number of leadfield components for each source -Nsource = 0; -for i=dip.inside - Nsource = Nsource + size(dip.leadfield{i}, 2); -end - -% concatenate the leadfield components of all sources into one large matrix -lf = zeros(Nchan, Nsource); -n = 1; -for i=dip.inside - cbeg = n; - cend = n + size(dip.leadfield{i}, 2) - 1; - lf(:,cbeg:cend) = dip.leadfield{i}; - n = n + size(dip.leadfield{i}, 2); -end - -fprintf('computing MNE source reconstruction, this may take some time...\n'); -% compute the inverse o the forward model, this is where prior information -% on source and noise covariance would be usefull -if isempty(noisecov) - % use an unregularised minimum norm solution, i.e. using the Moore-Penrose pseudoinverse - w = pinv(lf); -else - % the noise covariance has been given and can be used to regularise the solution - if isempty(sourcecov) - sourcecov = eye(Nsource); - end - % rename some variables for consistency with the publications - A = lf; - R = sourcecov; - C = noisecov; - % the regularisation parameter can be estimated from the noise covariance, see equation 6 in Lin et al. 2004 - if isempty(lambda) - lambda = trace(A * R * A')/(trace(C)*snr^2); - end - % equation 5 from Lin et al 2004 (this implements Dale et al 2000, and Liu et al. 2002) - w = R * A' * inv( A * R * A' + (lambda^2) * C); -end - -% for each of the timebins, estimate the source strength -mom = w * dat; - -% re-assign the estimated source strength over the inside and outside dipoles -n = 1; -for i=dip.inside - cbeg = n; - cend = n + size(dip.leadfield{i}, 2) - 1; - dipout.mom{i} = mom(cbeg:cend,:); - n = n + size(dip.leadfield{i}, 2); -end -dipout.mom(dip.outside) = {nan}; - -% for convenience also compute power at each location -for i=dip.inside - dipout.pow(i,:) = sum(dipout.mom{i}.^2, 1); -end -dipout.pow(dip.outside,:) = nan; - -% add other descriptive information to the output source model -dipout.pos = dip.pos; -dipout.inside = dip.inside; -dipout.outside = dip.outside; - diff --git a/external/fieldtrip/private/mni2tal.m b/external/fieldtrip/private/mni2tal.m new file mode 100644 index 0000000..a101124 --- /dev/null +++ b/external/fieldtrip/private/mni2tal.m @@ -0,0 +1,46 @@ +function outpoints = mni2tal(inpoints) +% Converts coordinates from MNI brain to best guess +% for equivalent Talairach coordinates +% FORMAT outpoints = mni2tal(inpoints) +% Where inpoints is N by 3 or 3 by N matrix of coordinates +% (N being the number of points) +% outpoints is the coordinate matrix with Talairach points +% Matthew Brett 10/8/99 + + +% check if SPM is in path and if not add +hasspm2 = hastoolbox('SPM2'); +hasspm8 = hastoolbox('SPM8'); + +if ~hasspm2 && ~hasspm8 + try, hasspm8 = hastoolbox('SPM8', 1); end +end + +if ~hasspm8 + try, hastoolbox('SPM2', 1); end +end + +dimdim = find(size(inpoints) == 3); +if isempty(dimdim) + error('input must be a N by 3 or 3 by N matrix') +end +if dimdim == 2 + inpoints = inpoints'; +end + +% Transformation matrices, different zooms above/below AC +upT = spm_matrix([0 0 0 0.05 0 0 0.99 0.97 0.92]); +downT = spm_matrix([0 0 0 0.05 0 0 0.99 0.97 0.84]); + +tmp = inpoints(3,:)<0; % 1 if below AC +inpoints = [inpoints; ones(1, size(inpoints, 2))]; +inpoints(:, tmp) = downT * inpoints(:, tmp); +inpoints(:, ~tmp) = upT * inpoints(:, ~tmp); +outpoints = inpoints(1:3, :); +if dimdim == 2 + outpoints = outpoints'; +end + + + + diff --git a/external/fieldtrip/private/mollify.m b/external/fieldtrip/private/mollify.m new file mode 100644 index 0000000..4520140 --- /dev/null +++ b/external/fieldtrip/private/mollify.m @@ -0,0 +1,94 @@ +function [grid] = mollify(cfg, grid); + +% This function does something +% + +% Copyright (c) 2006, Jan-Mathijs Schoffelen & Robert Oostenveld, F.C. Donders Centre +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: mollify.m 952 2010-04-21 18:29:51Z roboos $ + + +% set the defaults +if ~isfield(cfg, 'mollify'), cfg.mollify = 1; end % fwhm in pos-units +if ~isfield(cfg, 'sphereradius'),cfg.sphereradius = 2.*cfg.mollify; end % truncate gaussian +if ~isfield(cfg, 'feedback'), cfg.feedback = 'textbar'; end + +hasnrm = isfield(grid, 'normals'); + +Ndipoles = size(grid.pos,1); +Ninside = length(grid.inside); +Nchans = size(grid.leadfield{grid.inside(1)}, 1); +Ncomp = size(grid.leadfield{grid.inside(1)}, 2); + +if isempty(cfg.sphereradius) + error('cfg.sphereradius should be specified'); +end +% the distance only has to be computed to voxels inside the brain +pos = grid.pos(grid.inside,:); +npos = size(pos,1); +% compute the distance between voxels and each surface point in a reasonable amount of time, so don't compute everything with everything, but only take those point-pairs into account at a distance of < sphereradius, because the gaussian will be truncated anyhow +distmat = pntdist(pos, cfg.sphereradius); +[indx, indy] = find(distmat > 0 & distmat <= cfg.sphereradius); +val = distmat(find(distmat > 0 & distmat <= cfg.sphereradius)); +distmat = sparse(indx, indy, val, Ninside, Ninside); + +ldfall = zeros(Nchans*Ncomp,Ninside); +%put leadfields in one matrix and concatenate the columns +for k=1:Ninside + ldfall(:,k) = grid.leadfield{grid.inside(k)}(:); +end + +if hasnrm, + nrmall = grid.normals(grid.inside,:)'; + nrmnew = zeros(size(nrmall)); +end + +ldfnew = cell(1,Ndipoles); +sigma = cfg.mollify./(2*sqrt(2*log(2))); %Weisstein, Eric W. "Gaussian Function." From MathWorld--A Wolfram Web Resource. http://mathworld.wolfram.com/GaussianFunction.html + +progress('init', cfg.feedback, 'computing mollification'); +for k=1:Ninside + progress(k/Ninside, 'computing mollification %d/%d\n', k, Ninside); + % compute the squared distance from this dipole to each other dipole + distsq = full(distmat(:,k).^2); + % gaussianize the kernel + kernel = exp(-distsq./(2.*(sigma^2)));%CHECK THIS + % put everything outside the sphereradius to zero, except the point itself + kernel(find(distsq==0)) = 0; + kernel(k) = 1; + % normalize kernel + kernel = kernel./sum(kernel); + % compute mollified leadfield + dum = reshape(ldfall*kernel, [Nchans Ncomp]); + if ~strcmp(cfg.reducerank, 'no'), + [u,s,v] = svd(dum); + r = diag(s); + s(:) = 0; + s(1,1) = r(1); + s(2,2) = r(2); + dum = u*s*v'; + end + ldfnew{grid.inside(k)} = dum; + if hasnrm, nrmnew(:, grid.inside(k)) = nrmall * kernel; end +end +progress('close'); + +% update the leadfields and the normals +grid.leadfield = ldfnew; +if hasnrm, grid.normals = nrmnew; end diff --git a/external/fieldtrip/private/msphere.m b/external/fieldtrip/private/msphere.m index 2f198d2..b795615 100644 --- a/external/fieldtrip/private/msphere.m +++ b/external/fieldtrip/private/msphere.m @@ -16,10 +16,23 @@ % from the sci.math newsgroup. The full news message can be found % below. This Matlab implementation was made by Robert Oostenveld. % -% $Log: msphere.m,v $ -% Revision 1.1 2004/06/04 08:08:24 roberto -% *** empty log message *** +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: msphere.m 952 2010-04-21 18:29:51Z roboos $ % From: rusin@washington.math.niu.edu (Dave Rusin) % Newsgroups: sci.math diff --git a/external/fieldtrip/private/multiplotCC.m b/external/fieldtrip/private/multiplotCC.m deleted file mode 100644 index 08299c0..0000000 --- a/external/fieldtrip/private/multiplotCC.m +++ /dev/null @@ -1,133 +0,0 @@ -function multiplotCC(cfg, data) - -% MULTIPLOTCC visualiuzes the coherence between channels by using multiple -% topoplots. The topoplot at a given channel location shows the coherence -% of that channel with all other channels. -% -% Use as -% multiplotCC(cfg, data) - -% Undocumented local options: -% cfg.layout = layout filename or a structure produced by prepare_layout -% cfg.xlim -% cfg.xparam -% cfg.zparam -% This function requires input from FREQSTATISTICS_SHIFTPREDICT -% This function should be rewritten, using the clean topoplot implementation - -% Copyright (C) 2005-2006, Jan-Mathijs Schoffelen, Robert Oostenveld -% -% $Log: multiplotCC.m,v $ -% Revision 1.12 2009/06/17 13:44:52 roboos -% cleaned up help -% -% Revision 1.11 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.10 2008/09/22 12:53:27 roboos -% ensure equal and tight axes -% -% Revision 1.9 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.8 2007/03/27 11:05:19 ingnie -% changed call to fixdimord in call to checkinput -% -% Revision 1.7 2007/03/21 16:24:13 chrhes -% updated documentation regarding the fact that cfg.layout can also contain a -% layout structure obtained using the function prepare_layout.m -% -% Revision 1.6 2006/04/20 09:58:34 roboos -% updated documentation -% -% Revision 1.5 2006/04/10 12:21:14 roboos -% improved documentation -% -% Revision 1.4 2006/03/14 08:09:22 roboos -% added copyrigth and cvs log statement -% - -fieldtripdefs - -if ~isfield(cfg, 'layout'), cfg.layout = 'CTF151s.lay'; end; -if ~isfield(cfg, 'xparam'), cfg.xparam = 'foi'; end; -if ~isfield(cfg, 'xlim'), cfg.xlim = 'all'; end; -if ~isfield(cfg, 'zparam'), cfg.zparam = 'avg.icohspctrm'; end; - -% for backward compatibility with old data structures -data = checkdata(data); - -if strcmp(cfg.zparam, 'avg.icohspctrm') && ~issubfield(data, 'avg.icohspctrm'), - data.avg.icohspctrm = abs(imag(data.avg.cohspctrm)); -end - -if strcmp(data.dimord, 'refchan_chan_freq'), - %reshape input-data, such that topoplotER will take it - cnt = 1; - siz = size(data.prob); - data.labelcmb = cell(siz(1)*siz(2),2); - data.prob = reshape(data.prob, [siz(1)*siz(2) siz(3)]); - data.stat = reshape(data.stat, [siz(1)*siz(2) siz(3)]); - for j = 1:length(data.label) - for k = 1:length(data.reflabel) - data.labelcmb(cnt,:) = [data.reflabel(k) data.label(j)]; - cnt = cnt + 1; - end - end - tmpdata = data; -else - dat = getsubfield(data, cfg.zparam); - scale = [0 max(dat(:))-0.2]; -end - -if isfield(cfg, 'xparam'), - xparam = getsubfield(data, cfg.xparam); - if ~strcmp(cfg.xlim, 'all'), - fbin = [nearest(xparam, cfg.xlim(1)) nearest(xparam, cfg.xlim(2))]; - else - fbin = [xparam(1) xparam(end)]; - end -end - -[chNum,X,Y,Width,Height,Lbl] = textread(cfg.layout,'%f %f %f %f %f %s'); - -xScaleFac = 1/(max(Width)+ max(X) - min(X)); -yScaleFac = 1/(max(Height)+ max(Y) - min(Y)); - - -Xpos = xScaleFac*(X-min(X)); -Ypos = 0.9*yScaleFac*(Y-min(Y)); - -for k=1:length(chNum) - 2 - subplotOL('position',[Xpos(k) Ypos(k)+(Height(k)*yScaleFac) Width(k)*xScaleFac*2 Height(k)*yScaleFac*2]) - config.layout = cfg.layout; - if exist('tmpdata'), - - config.style = 'straight'; - config.electrodes = 'off'; - config.hlinewidth = 0.5; - try, config.refmarker = strmatch(Lbl(k), data.reflabel); - catch, config.refmarker = strmatch(Lbl(k), data.label); end - config.maplimits = [0 0.5]; - config.ecolor = [1 1 1]; - config.interplimits = 'electrodes'; - if isfield(cfg, 'xparam'), - config.xparam = cfg.xparam; - config.xlim = xparam; - else - config.xparam = 'time'; - config.xlim = [k-0.5 k+0.5]; - end - config.zparam = cfg.zparam; - config.cohrefchannel = Lbl(k); - config.showxlim = 'no'; - config.showzlim = 'no'; - config.colorbar = 'no'; - config.zlim = scale; - config.grid_scale = 30; - topoplotER(config, data); - drawnow; - end -end - - diff --git a/external/fieldtrip/private/multiplotER.m b/external/fieldtrip/private/multiplotER.m deleted file mode 100644 index 8e56e67..0000000 --- a/external/fieldtrip/private/multiplotER.m +++ /dev/null @@ -1,688 +0,0 @@ -function [cfg] = multiplotER(cfg, varargin) - -% multiplotER plots the event-related fields or potentials versus time -% or of oscillatory activity (power or coherence) versus frequency. Multiple -% datasets can be overlayed. The plots are arranged according to their -% location specified in the layout. -% -% Use as: -% multiplotER(cfg, data) -% multiplotER(cfg, data, data2, ..., dataN) -% -% The data can be an ERP/ERF produced by TIMELOCKANALYSIS, a powerspectrum -% produced by FREQANALYSIS or a coherencespectrum produced by FREQDESCRIPTIVES. -% If you specify multiple datasets they must contain the same channels, etc. -% -% The configuration can have the following parameters: -% cfg.xparam = field to be plotted on x-axis (default depends on data.dimord) -% 'time' or 'freq' -% cfg.zparam = field to be plotted on y-axis (default depends on data.dimord) -% 'avg', 'powspctrm' or 'cohspctrm' -% cfg.maskparameter = field in the first dataset to be used for marking significant data -% cfg.xlim = 'maxmin' or [xmin xmax] (default = 'maxmin') -% cfg.ylim = 'maxmin' or [ymin ymax] (default = 'maxmin') -% cfg.cohrefchannel = name of reference channel for visualising coherence, can be 'gui' -% cfg.baseline = 'yes','no' or [time1 time2] (default = 'no'), see TIMELOCKBASELINE or FREQBASELINE -% cfg.baselinetype = 'absolute' or 'relative' (default = 'absolute') -% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') -% cfg.axes = 'yes', 'no' (default = 'yes') -% Draw x- and y-axes for each graph -% cfg.box = 'yes', 'no' (default = 'no') -% Draw a box around each graph -% cfg.comment = string of text (default = date + colors) -% Add 'comment' to graph (according to COMNT in the layout) -% cfg.showlabels = 'yes', 'no' (default = 'no') -% cfg.showoutline = 'yes', 'no' (default = 'no') -% cfg.fontsize = font size of comment and labels (if present) (default = 8) -% cfg.interactive = Interactive plot 'yes' or 'no' (default = 'no') -% In a interactive plot you can select areas and produce a new -% interactive plot when a selected area is clicked. Multiple areas -% can be selected by holding down the SHIFT key. -% cfg.renderer = 'painters', 'zbuffer',' opengl' or 'none' (default = 'opengl') -% -% cfg.layout = specify the channel layout for plotting using one of -% the following ways: -% -% The layout defines how the channels are arranged and what the size of each -% subplot is. You can specify the layout in a variety of ways: -% - you can provide a pre-computed layout structure (see prepare_layout) -% - you can give the name of an ascii layout file with extension *.lay -% - you can give the name of an electrode file -% - you can give an electrode definition, i.e. "elec" structure -% - you can give a gradiometer definition, i.e. "grad" structure -% If you do not specify any of these and the data structure contains an -% electrode or gradiometer structure, that will be used for creating a -% layout. If you want to have more fine-grained control over the layout -% of the subplots, you should create your own layout file. -% -% See also: -% multiplotTFR, singleplotER, singleplotTFR, topoplotER, topoplotTFR, -% prepare_layout. - -% Undocumented local options: -% cfg.graphcolor -% cfg.layoutname -% -% This function depends on TIMELOCKBASELINE which has the following options: -% cfg.baseline, documented -% cfg.channel -% cfg.blcwindow -% cfg.previous -% cfg.version -% -% This function depends on FREQBASELINE which has the following options: -% cfg.baseline, documented -% cfg.baselinetype - -% Copyright (C) 2003-2006, Ole Jensen -% -% $Log: multiplotER.m,v $ -% Revision 1.52 2009/10/12 14:25:02 jansch -% allow for plotting only x or y axis in cfg.axes -% -% Revision 1.51 2009/07/14 13:21:09 roboos -% changed the interactive plotting: instead of using plotSelection it now uses the selection function from the new plotting module (select_range and select_channel) and uses a local subfunction to update the cfg and call the next figure -% -% Revision 1.50 2009/06/17 13:44:52 roboos -% cleaned up help -% -% Revision 1.49 2009/06/17 13:35:53 roboos -% some minor changes to comments -% -% Revision 1.48 2009/05/12 18:13:12 roboos -% added handling of cfg.cohrefchannel='gui' for manual/interactive selection -% -% Revision 1.47 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.46 2008/12/16 14:59:13 sashae -% plot functions can now give cfg as output -% added checkconfig to start and end of function, configtracking possible -% -% Revision 1.45 2008/12/16 13:17:06 sashae -% replaced backward compatibility code by call to checkconfig -% removed obsolete subfunction pwrspctm2cohspctrm -% -% Revision 1.44 2008/11/28 22:14:58 sashae -% added call to checkconfig -% -% Revision 1.43 2008/11/28 22:08:19 sashae -% allow averaging over rpt/subj also for other fields than zparam=powspctrm (thanks to Jurrian) -% -% Revision 1.42 2008/10/29 12:40:58 roboos -% removed "axis equal" -% -% Revision 1.41 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.40 2008/09/22 12:53:27 roboos -% ensure equal and tight axes -% -% Revision 1.39 2008/09/22 12:44:08 roboos -% added option cfg.showoutline, default is no -% -% Revision 1.38 2008/01/29 19:43:33 sashae -% added option for trial selection; plot functions now also accept data with -% repetitions (either trials or subjects), the avg is computed and plotted -% removed some old code -% -% Revision 1.37 2007/07/05 08:36:19 roboos -% fixed bug related to layout and varargin -% -% Revision 1.36 2007/06/19 13:57:07 ingnie -% axis wider if cfg.box = 'yes', changed color box and mask-patch -% -% Revision 1.35 2007/06/07 14:32:09 ingnie -% fixed error: baselining should depend on xparam not yparam -% -% Revision 1.34 2007/06/05 16:14:23 ingnie -% added cfg.maskparameter -% -% Revision 1.33 2007/04/25 17:23:46 ingnie -% *** empty log message *** -% -% Revision 1.32 2007/04/19 10:26:11 roboos -% Added a warning to the "Apply baseline correction" sections. If a user doesn't set yparam, baselining is not applied. (thanks to Doug) -% -% Revision 1.31 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.30 2007/03/27 11:05:19 ingnie -% changed call to fixdimord in call to checkinput -% -% Revision 1.29 2007/03/21 15:56:18 chrhes -% updated documentation regarding the fact that cfg.layout can also contain a -% layout structure obtained using the function prepare_layout.m -% -% Revision 1.28 2007/03/14 08:43:12 roboos -% replaced call to createlayout to prepare_layout, made some small changes to -% the lay structure -% -% Revision 1.27 2007/01/09 10:46:31 roboos -% fixed accidental typo in function definition -% -% Revision 1.26 2007/01/09 10:41:43 roboos -% Added the option cfg.renderer, default is opengl. Interactive plotting -% on linux/VNC sometimes does not work, using cfg.renderer='painters' -% seems to fix it. -% -% Revision 1.25 2006/07/27 15:33:29 roboos -% autodetect params for timelocked data with keeptrials -% -% Revision 1.24 2006/06/19 11:11:37 roboos -% fixed small bug in the conversion of coherence data: first select labels for -% the channels, then for the channelcombinations -% -% Revision 1.23 2006/05/30 14:19:18 ingnie -% if axis is 'yes' axis are always drawn and not only when data crosses zero, -% updated documentation -% -% Revision 1.22 2006/05/26 12:47:28 ingnie -% added error when labels in layout and labels in data do not match and therefore -% no data is selected to be plotted -% -% Revision 1.21 2006/05/11 14:53:52 ingnie -% when cfg.ylim is 'maxmin', the scaling (ymin ymax) only determined by channels -% that are present in the layout. -% -% Revision 1.20 2006/05/03 08:12:51 ingnie -% updated documentation -% -% Revision 1.19 2006/04/20 09:58:34 roboos -% updated documentation -% -% Revision 1.18 2006/03/17 14:47:27 denpas -% Updated documentation. -% -% Revision 1.17 2006/03/17 14:43:59 denpas -% Fixed cfg.yparam / cfg.zparam bug. Either param may now be used to specify -% the y-axis in case of 2D data. -% -% Revision 1.16 2006/03/13 14:08:47 denpas -% Fixed a bug concerning dynamic fieldnames in combination with (:), which doesn't work. -% Removed the (:) and added min(min(...)) and max(max(...)). -% -% Revision 1.15 2006/03/02 13:54:47 jansch -% fixed multiple small bugs -% -% Revision 1.14 2006/02/28 12:43:15 roboos -% made plotting of coherence consistent between all xxxplotER functions -% made baselining consistent, use cfg.xparam to decide between freqbaseline -% and timelockbaseline -% -% Revision 1.13 2006/02/27 15:03:03 denpas -% many changes, most important is added interactive functionality -% made data selection consistent between different plot functions -% changed dimord for consistency -% -% Revision 1.11 2005/08/18 12:15:41 jansch -% added support to plot subfields -% -% Revision 1.10 2005/05/17 17:50:37 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer -% correspondence with Matlab documentation on shortcircuited evaluation of -% sequential boolean constructs -% -% Revision 1.9 2005/04/29 12:46:44 roboos -% small change in help -% -% Revision 1.8 2005/04/29 12:40:43 roboos -% cleaned up and updated the help -% -% Revision 1.7 2005/04/12 10:06:57 olejen -% clf added -% -% Revision 1.6 2005/04/06 07:40:56 jansch -% included option cfg.cohrefchannel. updated help. -% -% Revision 1.5 2005/02/07 17:12:00 roboos -% changed handling of layout files (using new function createlayout), now also -% supports automatic layout creation based on gradiometer/electrode definition -% in data, updated help, cleaned up indentation -% -% Revision 1.4 2005/01/27 09:31:49 roboos -% applied autoindentation on code, removed many empty lines and spaces, -% replaced layoutfile reading with read_lay, applied doudavs code to all input arguments -% implemented automatic detection of arguments to plot, -% updated help, changed input from p1, p2, p3... to varargin -% -% Revision 1.3 2004/09/24 15:54:54 roboos -% included the suggested improvements by Doug Davidson: added option cfg.cohtargetchannel -% and updated the help -% -% Revision 1.2 2004/09/01 17:59:28 roboos -% added copyright statements to all filed -% added cfg.version to all functions that give configuration in their output -% added cfg.previous to all functions with input data containing configuration details - -fieldtripdefs - -cfg = checkconfig(cfg, 'trackconfig', 'on'); - -clf - -% For backward compatibility with old data structures: -for i=1:length(varargin) - varargin{i} = checkdata(varargin{i}); -end - -% set the defaults: -if ~isfield(cfg,'baseline'), cfg.baseline = 'no'; end -if ~isfield(cfg,'trials'), cfg.trials = 'all'; end -if ~isfield(cfg,'xlim'), cfg.xlim = 'maxmin'; end -if ~isfield(cfg,'ylim'), cfg.ylim = 'maxmin'; end -if ~isfield(cfg,'comment'), cfg.comment = strcat([date '\n']); end -if ~isfield(cfg,'axes'), cfg.axes = 'yes'; end -if ~isfield(cfg,'showlabels'), cfg.showlabels = 'no'; end -if ~isfield(cfg,'showoutline'), cfg.showoutline = 'no'; end -if ~isfield(cfg,'box'), cfg.box = 'no'; end -if ~isfield(cfg,'fontsize'), cfg.fontsize = 8; end -if ~isfield(cfg,'graphcolor') cfg.graphcolor = ['brgkywrgbkywrgbkywrgbkyw'];end -if ~isfield(cfg,'interactive'), cfg.interactive = 'no'; end -if ~isfield(cfg,'renderer'), cfg.renderer = 'opengl'; end -if ~isfield(cfg,'maskparameter'),cfg.maskparameter = []; end - -GRAPHCOLOR = ['k' cfg.graphcolor ]; - -% Set x/y/zparam defaults according to varargin{1}.dimord value: -if strcmp(varargin{1}.dimord, 'chan_time') - if ~isfield(cfg, 'xparam'), cfg.xparam='time'; end - if ~isfield(cfg, 'zparam'), cfg.zparam='avg'; end -elseif strcmp(varargin{1}.dimord, 'chan_freq') - if ~isfield(cfg, 'xparam'), cfg.xparam='freq'; end - if ~isfield(cfg, 'zparam'), cfg.zparam='powspctrm'; end -elseif strcmp(varargin{1}.dimord, 'subj_chan_time') || strcmp(varargin{1}.dimord, 'rpt_chan_time') - tmpcfg = []; - tmpcfg.trials = cfg.trials; - for i=1:(nargin-1) - varargin{i} = timelockanalysis(tmpcfg, varargin{i}); - end - if ~isfield(cfg, 'xparam'), cfg.xparam='time'; end - if ~isfield(cfg, 'zparam'), cfg.zparam='avg'; end -elseif strcmp(varargin{1}.dimord, 'subj_chan_freq') || strcmp(varargin{1}.dimord, 'rpt_chan_freq') - tmpcfg = []; - tmpcfg.trials = cfg.trials; - tmpcfg.jackknife = 'no'; - if isfield(cfg, 'zparam') && strcmp(cfg.zparam,'cohspctrm') - % on the fly computation of coherence spectrum is not supported - elseif isfield(cfg, 'zparam') && ~strcmp(cfg.zparam,'powspctrm') - % freqdesctiptives will only work on the powspctrm field, hence a temporary copy of the data is needed - for i=1:(nargin-1) - tempdata.dimord = varargin{i}.dimord; - tempdata.freq = varargin{i}.freq; - tempdata.label = varargin{i}.label; - tempdata.powspctrm = varargin{i}.(cfg.zparam); - tempdata.cfg = varargin{i}.cfg; - tempdata = freqdescriptives(tmpcfg, tempdata); - varargin{i}.(cfg.zparam) = tempdata.powspctrm; - clear tempdata - end - else - for i=1:(nargin-1) - if isfield(varargin{i}, 'crsspctrm'), varargin{i} = rmfield(varargin{i}, 'crsspctrm'); end % on the fly computation of coherence spectrum is not supported - varargin{i} = freqdescriptives(tmpcfg, varargin{i}); - end - end - if ~isfield(cfg, 'xparam'), cfg.xparam='freq'; end - if ~isfield(cfg, 'zparam'), cfg.zparam='powspctrm'; end -end - -% Make sure cfg.yparam and cfg.zparam become equivalent if only one is defined: -if (isfield(cfg, 'yparam')) && (~isfield(cfg, 'zparam')) - cfg.zparam = cfg.yparam; -elseif (~isfield(cfg, 'yparam')) && (isfield(cfg, 'zparam')) - cfg.yparam = cfg.zparam; -end - -% Old style coherence plotting with cohtargetchannel is no longer supported -cfg = checkconfig(cfg, 'unused', {'cohtargetchannel'}); - -% Read or create the layout that will be used for plotting -lay = prepare_layout(cfg, varargin{1}); -cfg.layout = lay; - -for k=1:length(varargin) - % Check for unconverted coherence spectrum data - if (strcmp(cfg.zparam,'cohspctrm')) && (isfield(varargin{k}, 'labelcmb')) - % A reference channel is required: - if ~isfield(cfg,'cohrefchannel'), - error('no reference channel specified'); - end - - if strcmp(cfg.cohrefchannel, 'gui') - % Open a single figure with the channel layout, the user can click on a reference channel - h = clf; - plot_lay(lay, 'box', false); - title('Select the reference channel by clicking on it...'); - % add the channel information to the figure - info = guidata(h); - info.x = lay.pos(:,1); - info.y = lay.pos(:,2); - info.label = lay.label; - guidata(h, info); - set(gcf, 'WindowButtonUpFcn', {@select_channel, 'callback', {@select_multiplotER, cfg, varargin{:}}}); - return - end - - % Convert 2-dimensional channel matrix to a single dimension: - sel1 = strmatch(cfg.cohrefchannel, varargin{k}.labelcmb(:,2)); - sel2 = strmatch(cfg.cohrefchannel, varargin{k}.labelcmb(:,1)); - fprintf('selected %d channels for coherence\n', length(sel1)+length(sel2)); - varargin{k}.cohspctrm = varargin{k}.cohspctrm([sel1;sel2],:,:); - varargin{k}.label = [varargin{k}.labelcmb(sel1,1);varargin{k}.labelcmb(sel2,2)]; - varargin{k}.labelcmb = varargin{k}.labelcmb([sel1;sel2],:); - varargin{k} = rmfield(varargin{k}, 'labelcmb'); - end - - % Apply baseline correction: - if ~strcmp(cfg.baseline, 'no') - if strcmp(cfg.xparam, 'time') - varargin{k} = timelockbaseline(cfg, varargin{k}); - elseif strcmp(cfg.xparam, 'freq') - varargin{k} = freqbaseline(cfg, varargin{k}); - else - warning('Baseline not applied, please set cfg.xparam'); - end - end -end - -% Get physical x-axis range: -if strcmp(cfg.xlim,'maxmin') - % Find maxmin throughout all varargins: - xmin = []; - xmax = []; - for i=1:length(varargin) - xmin = min([xmin varargin{i}.(cfg.xparam)]); - xmax = max([xmax varargin{i}.(cfg.xparam)]); - end -else - xmin = cfg.xlim(1); - xmax = cfg.xlim(2); -end - -% Find corresponding x-axis bins: -xidc = find(varargin{1}.(cfg.xparam) >= xmin & varargin{1}.(cfg.xparam) <= xmax); - -% Align physical x-axis range to the array bins: -xmin = varargin{1}.(cfg.xparam)(xidc(1)); -xmax = varargin{1}.(cfg.xparam)(xidc(end)); - -% Get physical y-axis range (ylim / zparam): -if strcmp(cfg.ylim,'maxmin') - % Find maxmin throughout all varargins: - ymin = []; - ymax = []; - for i=1:length(varargin) - % Select the channels in the data that match with the layout: - dat = []; - dat = getsubfield(varargin{i}, cfg.zparam); - [seldat, sellay] = match_str(varargin{k}.label, lay.label); - if isempty(seldat) - error('labels in data and labels in layout do not match'); - end - data = dat(seldat,:); - ymin = min([ymin min(min(min(data)))]); - ymax = max([ymax max(max(max(data)))]); - end -else - ymin = cfg.ylim(1); - ymax = cfg.ylim(2); -end - -% convert the layout to Ole's style of variable names -X = lay.pos(:,1); -Y = lay.pos(:,2); -Width = lay.width; -Height = lay.height; -Lbl = lay.label; - -% Create empty channel coordinates and labels arrays: -chanX(1:length(Lbl)) = NaN; -chanY(1:length(Lbl)) = NaN; -chanLabels = cell(1,length(Lbl)); - -hold on; -colorLabels = []; - -if isfield(lay, 'outline') && strcmp(cfg.showoutline, 'yes') - for i=1:length(lay.outline) - if ~isempty(lay.outline{i}) - tmpX = lay.outline{i}(:,1); - tmpY = lay.outline{i}(:,2); - h = line(tmpX, tmpY); - set(h, 'color', 'k'); - set(h, 'linewidth', 2); - end - end -end - -% Plot each data set: -for k=1:length(varargin) - P = getsubfield(varargin{k}, cfg.zparam); - Labels = getfield(varargin{k}, 'label'); - - if length(varargin) > 1 - colorLabels = [colorLabels inputname(k+1) '=' GRAPHCOLOR(k+1) '\n']; - end - - style = GRAPHCOLOR(k+1); - - for m=1:length(Lbl) - l = cellstrmatch(Lbl(m),Labels); - if ~isempty(l) - if ~isempty(cfg.maskparameter) - mask = varargin{1}.(cfg.maskparameter)(l,:); - else - mask = []; - end - % Plot ER: - plotWnd(varargin{k}.(cfg.xparam),P(l,:),xidc,[xmin xmax],[ymin ymax], ... - X(m), ... - Y(m), ... - Width(m), ... - Height(m), ... - Lbl(m), ... - cfg,style, mask); - - % Keep ER plot coordinates (at centre of ER plot), and channel labels (will be stored in the figure's UserData struct): - chanX(m) = X(m) + 0.5 * Width(m); - chanY(m) = Y(m) + 0.5 * Height(m); - chanLabels{m} = Lbl{m}; - end - end -end - -% Add the colors of the different datasets to the comment: -cfg.comment = [cfg.comment colorLabels]; - -% Write comment text: -l = cellstrmatch('COMNT',Lbl); -if ~isempty(l) - text(X(l),Y(l),sprintf(cfg.comment),'Fontsize',cfg.fontsize); -end - -% Plot scales: -l = cellstrmatch('SCALE',Lbl); -if ~isempty(l) - plotScales([xmin xmax],[ymin ymax],X(l),Y(l),Width(1),Height(1),cfg) -end - -% Make the figure interactive: -if strcmp(cfg.interactive, 'yes') - - % add the channel information to the figure - info = guidata(gcf); - info.x = lay.pos(:,1); - info.y = lay.pos(:,2); - info.label = lay.label; - guidata(gcf, info); - - set(gcf, 'WindowButtonUpFcn', {@select_channel, 'multiple', true, 'callback', {@select_singleplotER, cfg, varargin{:}}, 'event', 'WindowButtonUpFcn'}); - set(gcf, 'WindowButtonDownFcn', {@select_channel, 'multiple', true, 'callback', {@select_singleplotER, cfg, varargin{:}}, 'event', 'WindowButtonDownFcn'}); - set(gcf, 'WindowButtonMotionFcn', {@select_channel, 'multiple', true, 'callback', {@select_singleplotER, cfg, varargin{:}}, 'event', 'WindowButtonMotionFcn'}); -end - -axis tight -axis off -if strcmp(cfg.box, 'yes') - abc = axis; - axis(abc + [-1 +1 -1 +1]*mean(abs(abc))/10) -end -orient landscape -hold off - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function plotScales(xlim,ylim,xpos,ypos,width,height,cfg) -x1 = xpos; -x2 = xpos+width; -y1 = ypos; -y2 = ypos+width; -plot([xpos xpos+width xpos+width xpos xpos],[ypos ypos ypos+height ypos+height ypos],'b'); -if xlim(1) <= 0 && xlim(2) >= 0 - xs = xpos+width*([0 0]-xlim(1))/(xlim(2)-xlim(1)); - ys = ypos+height*(ylim-ylim(1))/(ylim(2)-ylim(1)); - plot(xs,ys,'b'); -end - -if ylim(1) <= 0 && ylim(2) >= 0 - xs = xpos+width*(xlim-xlim(1))/(xlim(2)-xlim(1)); - ys = ypos+height*([0 0]-ylim(1))/(ylim(2)-ylim(1)); - plot(xs,ys,'b'); -end - -text( x1,y1,num2str(xlim(1),3),'rotation',90,'HorizontalAlignment','Right','VerticalAlignment','middle','Fontsize',cfg.fontsize); -text( x2,y1,num2str(xlim(2),3),'rotation',90,'HorizontalAlignment','Right','VerticalAlignment','middle','Fontsize',cfg.fontsize); -text( x2,y1,num2str(ylim(1),3),'HorizontalAlignment','Left','VerticalAlignment','bottom','Fontsize',cfg.fontsize); -text( x2,y2,num2str(ylim(2),3),'HorizontalAlignment','Left','VerticalAlignment','bottom','Fontsize',cfg.fontsize); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function plotWnd(x,y,xidc,xlim,ylim,xpos,ypos,width,height,label,cfg,style,mask) -set(gca,'FontSize',cfg.fontsize); - -x = x(xidc); -y = y(xidc); - -% Clip out of bounds y values: -y(find(y > ylim(2))) = ylim(2); -y(find(y < ylim(1))) = ylim(1); - -xs = xpos+width*(x-xlim(1))/(xlim(2)-xlim(1)); -ys = ypos+height*(y-ylim(1))/(ylim(2)-ylim(1)); -plot(xs,ys,style) - -if strcmp(cfg.showlabels,'yes') - text(xpos,ypos+1.0*height,label,'Fontsize',cfg.fontsize) -end - -% Draw axes: -if strcmp(cfg.axes,'yes') || strcmp(cfg.axes, 'xy') - % Draw y axis - xs = xpos+width*([0 0]-xlim(1))/(xlim(2)-xlim(1)); - ys = ypos+height*(ylim-ylim(1))/(ylim(2)-ylim(1)); - plot(xs,ys,'k'); - % Draw x axis - xs = xpos+width*(xlim-xlim(1))/(xlim(2)-xlim(1)); - ys = ypos+height*([0 0]-ylim(1))/(ylim(2)-ylim(1)); - plot(xs,ys,'k'); -elseif strcmp(cfg.axes,'x') - % Draw x axis - xs = xpos+width*(xlim-xlim(1))/(xlim(2)-xlim(1)); - ys = ypos+height*([0 0]-ylim(1))/(ylim(2)-ylim(1)); - plot(xs,ys,'k'); -elseif strcmp(cfg.axes,'y') - % Draw y axis - xs = xpos+width*([0 0]-xlim(1))/(xlim(2)-xlim(1)); - ys = ypos+height*(ylim-ylim(1))/(ylim(2)-ylim(1)); - plot(xs,ys,'k'); -end - -% Draw box around plot: -if strcmp(cfg.box,'yes') - plot([xpos xpos+width xpos+width xpos xpos],[ypos ypos ypos+height ypos+height ypos],'k'); -end - -% Add mask patch -if ~isempty(mask) - % determine how many boxes - foundbeg = 0; - foundend = 0; - beg = []; - eind = []; - for i = 1:length(mask) - if ~foundbeg && mask(i) == 1 - beg(length(beg)+1) = i; - foundbeg = 1; - foundend = 0; - elseif ~foundbeg && mask(i) == 0 - %next - elseif ~foundend && mask(i) == 1 - %next - elseif ~foundend && mask(i) == 0 - eind(length(eind)+1) = i-1; - foundend = 1; - foundbeg = 0; - end - end - if length(eind) == length(beg)-1 - eind(length(eind)+1) = length(mask); - end - numbox = length(beg); - for i = 1:numbox - xmaskmin = xpos+width*(x(beg(i))-xlim(1))/(xlim(2)-xlim(1)); - xmaskmax = xpos+width*(x(eind(i))-xlim(1))/(xlim(2)-xlim(1)); - %plot([xmaskmin xmaskmax xmaskmax xmaskmin xmaskmin],[ypos ypos ypos+height ypos+height ypos],'r'); - hs = patch([xmaskmin xmaskmax xmaskmax xmaskmin xmaskmin],[ypos ypos ypos+height ypos+height ypos], [.6 .6 .6]); - set(hs, 'EdgeColor', 'none'); - end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function l = cellstrmatch(str,strlist) -l = []; -for k=1:length(strlist) - if strcmp(char(str),char(strlist(k))) - l = [l k]; - end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION which is called after selecting channels in case of cfg.cohrefchannel='gui' -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function select_multiplotER(label, cfg, varargin) -cfg.cohrefchannel = label; -fprintf('selected cfg.cohrefchannel = ''%s''\n', cfg.cohrefchannel); -p = get(gcf, 'Position'); -f = figure; -set(f, 'Position', p); -multiplotER(cfg, varargin{:}); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION which is called after selecting channels in case of cfg.interactive='yes' -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function select_singleplotER(label, cfg, varargin) -if ~isempty(label) - cfg.xlim = 'maxmin'; - cfg.channel = label; - fprintf('selected cfg.channel = {'); - for i=1:(length(cfg.channel)-1) - fprintf('''%s'', ', cfg.channel{i}); - end - fprintf('''%s''}\n', cfg.channel{end}); - p = get(gcf, 'Position'); - f = figure; - set(f, 'Position', p); - singleplotER(cfg, varargin{:}); -end - diff --git a/external/fieldtrip/private/multiplotTFR.m b/external/fieldtrip/private/multiplotTFR.m deleted file mode 100644 index 431f2a2..0000000 --- a/external/fieldtrip/private/multiplotTFR.m +++ /dev/null @@ -1,576 +0,0 @@ -function [cfg] = multiplotTFR(cfg, data) - -% multiplotTFR plots time-frequency representations of power or coherence in a -% topographical layout. The plots of the indivual sensors are arranged according -% to their location specified in the layout. -% -% Use as: -% multiplotTFR(cfg, data) -% -% The data can be a time-frequency representation of power or coherence that -% was computed using the FREQANALYSIS or FREQDESCRIPTIVES functions. -% -% The configuration can have the following parameters: -% cfg.xparam = field to be plotted on x-axis (default depends on data.dimord) -% 'time' -% cfg.yparam = field to be plotted on y-axis (default depends on data.dimord) -% 'freq' -% cfg.zparam = field to be represented as color (default depends on data.dimord) -% 'powspctrm' or 'cohspctrm' -% cfg.maskparameter = field in the data to be used for opacity masking of data -% cfg.xlim = 'maxmin' or [xmin xmax] (default = 'maxmin') -% cfg.ylim = 'maxmin' or [ymin ymax] (default = 'maxmin') -% cfg.zlim = 'maxmin','absmax' or [zmin zmax] (default = 'maxmin') -% cfg.cohrefchannel = name of reference channel for visualising coherence, can be 'gui' -% cfg.baseline = 'yes','no' or [time1 time2] (default = 'no'), see FREQBASELINE -% cfg.baselinetype = 'absolute' or 'relative' (default = 'absolute') -% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') -% cfg.box = 'yes', 'no' (default = 'no' if maskparameter given default = 'yes') -% Draw a box around each graph -% cfg.colorbar = 'yes', 'no' (default = 'no') -% cfg.colormap = any sized colormap, see COLORMAP -% cfg.comment = string of text (default = date + zlimits) -% Add 'comment' to graph (according to COMNT in the layout) -% cfg.showlabels = 'yes', 'no' (default = 'no') -% cfg.showoutline = 'yes', 'no' (default = 'no') -% cfg.fontsize = font size of comment and labels (if present) (default = 8) -% cfg.interactive = Interactive plot 'yes' or 'no' (default = 'no') -% In a interactive plot you can select areas and produce a new -% interactive plot when a selected area is clicked. Multiple areas -% can be selected by holding down the SHIFT key. -% cfg.masknans = 'yes' or 'no' (default = 'yes') -% cfg.renderer = 'painters', 'zbuffer',' opengl' or 'none' (default = []) -% cfg.layout = specify the channel layout for plotting using one of -% the following ways: -% -% The layout defines how the channels are arranged and what the size of each -% subplot is. You can specify the layout in a variety of ways: -% - you can provide a pre-computed layout structure (see prepare_layout) -% - you can give the name of an ascii layout file with extension *.lay -% - you can give the name of an electrode file -% - you can give an electrode definition, i.e. "elec" structure -% - you can give a gradiometer definition, i.e. "grad" structure -% If you do not specify any of these and the data structure contains an -% electrode or gradiometer structure (common for MEG data, since the header -% of the MEG datafile contains the gradiometer information), that will be -% used for creating a layout. If you want to have more fine-grained control -% over the layout of the subplots, you should create your own layout file. -% -% See also: -% multiplotER, singleplotER, singleplotTFR, topoplotER, topoplotTFR, -% prepare_layout - -% Undocumented local options: -% cfg.channel -% cfg.layoutname -% cfg.xparam -% cfg.zparam -% -% This function depends on FREQBASELINE which has the following options: -% cfg.baseline, documented -% cfg.baselinetype, documented - -% Copyright (C) 2003-2006, Ole Jensen -% -% $Log: multiplotTFR.m,v $ -% Revision 1.51 2009/07/14 13:52:16 roboos -% changed the interactive plotting: instead of using plotSelection it now uses the selection function from the new plotting module (select_range and select_channel) and uses a local subfunction to update the cfg and call the next figure -% -% Revision 1.50 2009/07/14 13:27:25 roboos -% consistent handling of cfg.renderer, default is to let matlab decide -% -% Revision 1.49 2009/06/17 13:44:52 roboos -% cleaned up help -% -% Revision 1.48 2009/05/12 18:48:15 roboos -% added handling of cfg.cohrefchannel='gui' for manual/interactive selection -% changed default for cfg.renderer -> let matlab decide -% -% Revision 1.47 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.46 2008/12/16 14:59:13 sashae -% plot functions can now give cfg as output -% added checkconfig to start and end of function, configtracking possible -% -% Revision 1.45 2008/12/16 13:17:06 sashae -% replaced backward compatibility code by call to checkconfig -% removed obsolete subfunction pwrspctm2cohspctrm -% -% Revision 1.44 2008/11/28 14:30:30 sashae -% averaging over rpt/subj skipped if zparam='cohspctrm' -% -% Revision 1.43 2008/11/27 14:48:27 roboos -% allow averaging over rpt or subj also for other fieldz than zparam=powspctrm (thanks to Jurrian) -% -% Revision 1.42 2008/10/29 12:40:58 roboos -% removed "axis equal" -% -% Revision 1.41 2008/10/28 14:30:51 ingnie -% linearity of axis is tested, warning given in case of nonlinear axis -% -% Revision 1.40 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.39 2008/09/22 12:53:27 roboos -% ensure equal and tight axes -% -% Revision 1.38 2008/09/22 12:44:08 roboos -% added option cfg.showoutline, default is no -% -% Revision 1.37 2008/09/22 12:30:59 roboos -% position the subplots with the box centered on the electrode position -% -% Revision 1.36 2008/01/29 19:43:33 sashae -% added option for trial selection; plot functions now also accept data with -% repetitions (either trials or subjects), the avg is computed and plotted -% removed some old code -% -% Revision 1.35 2007/10/12 12:58:59 marvger -% oops; removed accidental keyboard command -% -% Revision 1.34 2007/10/10 10:22:07 marvger -% *** empty log message *** -% -% Revision 1.33 2007/06/19 13:57:46 ingnie -% axis wider if cfg.box = 'yes' -% -% Revision 1.32 2007/06/14 12:23:48 ingnie -% added cfg.colormap option -% -% Revision 1.31 2007/06/13 12:09:59 ingnie -% made alphadata scaled between 0 and 1, partly transparent possible now -% -% Revision 1.30 2007/06/13 09:32:01 ingnie -% fixed maskparameter (all chans got mask of last chan, is fixed now) -% -% Revision 1.29 2007/06/06 10:04:29 jansch -% fixed typo on line 173 ~empty into ~isempty -% -% Revision 1.28 2007/06/05 16:14:58 ingnie -% added cfg.maskparameter and cfg.box -% -% Revision 1.27 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.26 2007/03/27 11:05:19 ingnie -% changed call to fixdimord in call to checkinput -% -% Revision 1.25 2007/03/21 15:49:41 chrhes -% updated documentation regarding the fact that cfg.layout can also contain a -% layout structure obtained using the function prepare_layout.m -% -% Revision 1.24 2007/03/14 08:43:12 roboos -% replaced call to createlayout to prepare_layout, made some small changes to the lay structure -% -% Revision 1.23 2007/01/09 10:41:43 roboos -% Added the option cfg.renderer, default is opengl. Interactive plotting -% on linux/VNC sometimes does not work, using cfg.renderer='painters' -% seems to fix it. -% -% Revision 1.22 2006/06/20 16:25:59 ingnie -% updated documentation -% -% Revision 1.21 2006/06/19 11:11:37 roboos -% fixed small bug in the conversion of coherence data: first select labels for the channels, then for the channelcombinations -% -% Revision 1.20 2006/06/06 16:57:51 ingnie -% updated documentation -% -% Revision 1.19 2006/05/30 14:16:42 ingnie -% updated documentation -% -% Revision 1.18 2006/05/26 12:42:00 ingnie -% added error when labels in layout and labels in data do not match and therefore -% no data is selected to be plotted -% -% Revision 1.17 2006/05/03 08:12:51 ingnie -% updated documentation -% -% Revision 1.16 2006/04/20 09:58:34 roboos -% updated documentation -% -% Revision 1.15 2006/03/23 09:48:35 jansch -% fixed bug in plotting of coherence-spectrum -% -% Revision 1.14 2006/03/06 11:47:55 denpas -% Fixed zmin/zmax bug. -% -% Revision 1.13 2006/02/27 15:03:03 denpas -% many changes, most important is added interactive functionality -% made data selection consistent between different plot functions -% changed dimord for consistency -% -% Revision 1.9 2005/05/17 17:50:37 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.8 2005/04/08 17:26:54 olejen -% TFR was wrongly assigned before calling freqbaseline.m - this is now reversed -% -% Revision 1.7 2005/04/06 14:26:55 olejen -% clf before plotting -% now make use of freqbaseline.m -% -% Revision 1.6 2005/04/06 07:40:56 jansch -% included option cfg.cohrefchannel. updated help. -% -% Revision 1.5 2005/02/07 17:12:00 roboos -% changed handling of layout files (using new function createlayout), now also supports automatic layout creation based on gradiometer/electrode definition in data, updated help, cleaned up indentation -% -% Revision 1.4 2004/09/24 15:54:54 roboos -% included the suggested improvements by Doug Davidson: added option cfg.cohtargetchannel -% and updated the help -% -% Revision 1.3 2004/09/01 18:02:23 roboos -% added copyright statements, removed cfg as output argument -% - -fieldtripdefs - -cfg = checkconfig(cfg, 'trackconfig', 'on'); - -clf - -% for backward compatibility with old data structures -data = checkdata(data); - -% Set the defaults: -if ~isfield(cfg,'baseline'), cfg.baseline = 'no'; end -if ~isfield(cfg,'baselinetype'), cfg.baselinetype = 'absolute'; end -if ~isfield(cfg,'trials'), cfg.trials = 'all'; end -if ~isfield(cfg,'xlim'), cfg.xlim = 'maxmin'; end -if ~isfield(cfg,'ylim'), cfg.ylim = 'maxmin'; end -if ~isfield(cfg,'zlim'), cfg.zlim = 'maxmin'; end -if ~isfield(cfg,'colorbar'), cfg.colorbar = 'no'; end -if ~isfield(cfg,'comment'), cfg.comment = date; end -if ~isfield(cfg,'showlabels'), cfg.showlabels = 'no'; end -if ~isfield(cfg,'showoutline'), cfg.showoutline = 'no'; end -if ~isfield(cfg,'channel'), cfg.channel = 'all'; end -if ~isfield(cfg,'fontsize'), cfg.fontsize = 8; end -if ~isfield(cfg,'interactive'), cfg.interactive = 'no'; end -if ~isfield(cfg,'renderer'), cfg.renderer = []; end % let matlab decide on default -if ~isfield(cfg,'masknans'), cfg.masknans = 'yes'; end -if ~isfield(cfg,'maskparameter'), cfg.maskparameter = []; end -if ~isfield(cfg,'box') - if ~isempty(cfg.maskparameter) - cfg.box = 'yes'; - else - cfg.box = 'no'; - end -end - -% Set x/y/zparam defaults according to data.dimord value: -if strcmp(data.dimord, 'chan_freq_time') - if ~isfield(cfg, 'xparam'), cfg.xparam='time'; end - if ~isfield(cfg, 'yparam'), cfg.yparam='freq'; end - if ~isfield(cfg, 'zparam'), cfg.zparam='powspctrm'; end -elseif strcmp(data.dimord, 'subj_chan_freq_time') || strcmp(data.dimord, 'rpt_chan_freq_time') - if isfield(data, 'crsspctrm'), data = rmfield(data, 'crsspctrm'); end % on the fly computation of coherence spectrum is not supported - tmpcfg = []; - tmpcfg.trials = cfg.trials; - tmpcfg.jackknife = 'no'; - if isfield(cfg, 'zparam') && strcmp(cfg.zparam,'cohspctrm') - % on the fly computation of coherence spectrum is not supported - elseif isfield(cfg, 'zparam') && ~strcmp(cfg.zparam,'powspctrm') - % freqdesctiptives will only work on the powspctrm field, hence a temporary copy of the data is needed - tempdata.dimord = data.dimord; - tempdata.freq = data.freq; - tempdata.time = data.time; - tempdata.label = data.label; - tempdata.powspctrm = data.(cfg.zparam); - tempdata.cfg = data.cfg; - tempdata = freqdescriptives(tmpcfg, tempdata); - data.(cfg.zparam) = tempdata.powspctrm; - clear tempdata - else - data = freqdescriptives(tmpcfg, data); - end - if ~isfield(cfg, 'xparam'), cfg.xparam='time'; end - if ~isfield(cfg, 'yparam'), cfg.yparam='freq'; end - if ~isfield(cfg, 'zparam'), cfg.zparam='powspctrm'; end -end - -% Old style coherence plotting with cohtargetchannel is no longer supported: -cfg = checkconfig(cfg, 'unused', {'cohtargetchannel'}); - -% Read or create the layout that will be used for plotting: -lay = prepare_layout(cfg, data); -cfg.layout = lay; - -% Check for unconverted coherence spectrum data: -if (strcmp(cfg.zparam,'cohspctrm')), - % A reference channel is required: - if ~isfield(cfg,'cohrefchannel'), - error('no reference channel specified'); - end - - if strcmp(cfg.cohrefchannel, 'gui') - % Open a single figure with the channel layout, the user can click on a reference channel - h = clf; - plot_lay(lay, 'box', false); - title('Select the reference channel by clicking on it...'); - info = []; - info.x = lay.pos(:,1); - info.y = lay.pos(:,2); - info.label = lay.label; - guidata(h, info); - set(gcf, 'WindowButtonUpFcn', {@select_channel, 'callback', {@select_multiplotTFR, cfg, data}}); - return - end - - % Convert 2-dimensional channel matrix to a single dimension: - sel1 = strmatch(cfg.cohrefchannel, data.labelcmb(:,2)); - sel2 = strmatch(cfg.cohrefchannel, data.labelcmb(:,1)); - fprintf('selected %d channels for coherence\n', length(sel1)+length(sel2)); - data.cohspctrm = data.cohspctrm([sel1;sel2],:,:); - data.label = [data.labelcmb(sel1,1);data.labelcmb(sel2,2)]; - data.labelcmb = data.labelcmb([sel1;sel2],:); - data = rmfield(data, 'labelcmb'); -end - -% Apply baseline correction: -if ~strcmp(cfg.baseline, 'no') - data = freqbaseline(cfg, data); -end - -% Get physical x-axis range: -if strcmp(cfg.xlim,'maxmin') - xmin = min(data.(cfg.xparam)); - xmax = max(data.(cfg.xparam)); -else - xmin = cfg.xlim(1); - xmax = cfg.xlim(2); -end - -% Find corresponding x-axis bins: -xidc = find(data.(cfg.xparam) >= xmin & data.(cfg.xparam) <= xmax); - -% Align physical x-axis range to the array bins: -xmin = data.(cfg.xparam)(xidc(1)); -xmax = data.(cfg.xparam)(xidc(end)); - -% Get physical y-axis range: -if strcmp(cfg.ylim,'maxmin') - ymin = min(data.(cfg.yparam)); - ymax = max(data.(cfg.yparam)); -else - ymin = cfg.ylim(1); - ymax = cfg.ylim(2); -end - -% Find corresponding y-axis bins: -yidc = find(data.(cfg.yparam) >= ymin & data.(cfg.yparam) <= ymax); - -% Align physical y-axis range to the array bins: -ymin = data.(cfg.yparam)(yidc(1)); -ymax = data.(cfg.yparam)(yidc(end)); - -% test if X and Y are linearly spaced (to within 10^-12): % FROM UIMAGE -x = data.(cfg.xparam)(xidc); -y = data.(cfg.yparam)(yidc); -dx = min(diff(x)); % smallest interval for X -dy = min(diff(y)); % smallest interval for Y -evenx = all(abs(diff(x)/dx-1)<1e-12); % true if X is linearly spaced -eveny = all(abs(diff(y)/dy-1)<1e-12); % true if Y is linearly spaced - -if ~evenx || ~eveny - warning('(one of the) axis is/are not evenly spaced, but plots are made as if axis are linear') -end - -% Select the channels in the data that match with the layout: -[seldat, sellay] = match_str(data.label, lay.label); -if isempty(seldat) - error('labels in data and labels in layout do not match'); -end - -datavector = data.(cfg.zparam)(seldat,yidc,xidc); -chanX = lay.pos(sellay, 1); -chanY = lay.pos(sellay, 2); -chanWidth = lay.width(sellay); -chanHeight = lay.height(sellay); -chanLabels = lay.label(sellay); -if ~isempty(cfg.maskparameter) - maskvector = data.(cfg.maskparameter)(seldat,yidc,xidc); -end - -% Get physical z-axis range (color axis): -if strcmp(cfg.zlim,'maxmin') - zmin = min(datavector(:)); - zmax = max(datavector(:)); -elseif strcmp(cfg.zlim,'absmax') - zmin = -max(abs(datavector(:))); - zmax = max(abs(datavector(:))); -else - zmin = cfg.zlim(1); - zmax = cfg.zlim(2); -end - -hold on; - -if isfield(lay, 'outline') && strcmp(cfg.showoutline, 'yes') - for i=1:length(lay.outline) - if ~isempty(lay.outline{i}) - tmpX = lay.outline{i}(:,1); - tmpY = lay.outline{i}(:,2); - h = line(tmpX, tmpY); - set(h, 'color', 'k'); - set(h, 'linewidth', 2); - end - end -end - -% Plot channels: -for k=1:length(seldat) - % Get cdata: - cdata = squeeze(datavector(k,:,:)); - if ~isempty(cfg.maskparameter) - mdata = squeeze(maskvector(k,:,:)); - end - - % Get axes for this panel - xas = (chanX(k) + linspace(0,1,size(cdata,2))*chanWidth(k)) - chanWidth(k)/2; - yas = (chanY(k) + linspace(0,1,size(cdata,1))*chanHeight(k)) - chanHeight(k)/2; - - % Draw plot: - h = imagesc(xas, yas, cdata, [zmin zmax]); - - % Mask Nan's and maskfield - if isequal(cfg.masknans,'yes') && isempty(cfg.maskparameter) - mask = ~isnan(cdata); - mask = double(mask); - set(h,'AlphaData',mask, 'AlphaDataMapping', 'scaled'); - alim([0 1]); - elseif isequal(cfg.masknans,'yes') && ~isempty(cfg.maskparameter) - mask = ~isnan(cdata); - mask = mask .* mdata; - mask = double(mask); - set(h,'AlphaData',mask, 'AlphaDataMapping', 'scaled'); - alim([0 1]); - elseif isequal(cfg.masknans,'no') && ~isempty(cfg.maskparameter) - mask = mdata; - mask = double(mask); - set(h,'AlphaData',mask, 'AlphaDataMapping', 'scaled'); - alim([0 1]); - end - -% Draw box around plot - if strcmp(cfg.box,'yes') - xstep = xas(2) - xas(1); ystep = yas(2) - yas(1); - xvalmin(1:length(yas)+2) = min(xas)-(0.5*xstep); xvalmax(1:length(yas)+2) = max(xas)+(0.5*xstep); yvalmin(1:length(xas)+2) = min(yas)-(0.5*ystep); yvalmax(1:length(xas)+2) = max(yas)+(0.5*ystep); - xas2 = [xvalmin(1) xas xvalmax(1)]; yas2 = [yvalmin(1) yas yvalmax(1)]; - hold on - plot([xas2 xvalmax xas2],[yvalmin yas2 yvalmax],'k'); - plot(xvalmin, yas2,'k'); - end - - % Draw channel labels: - if strcmp(cfg.showlabels,'yes') - text(chanX(k)-chanWidth(k)/2, chanY(k)+chanHeight(k)/2, sprintf(' %0s\n ', chanLabels{k}), 'Fontsize', cfg.fontsize); - end -end - -% write comment: -k = cellstrmatch('COMNT',lay.label); -if ~isempty(k) - comment = cfg.comment; - comment = sprintf('%0s\nxlim=[%.3g %.3g]', comment, xmin, xmax); - comment = sprintf('%0s\nylim=[%.3g %.3g]', comment, ymin, ymax); - comment = sprintf('%0s\nzlim=[%.3g %.3g]', comment, zmin, zmax); - text(lay.pos(k,1), lay.pos(k,2), sprintf(comment), 'Fontsize', cfg.fontsize); -end - -% plot scale: -k = cellstrmatch('SCALE',lay.label); -if ~isempty(k) - % Get average cdata across channels: - cdata = squeeze(mean(datavector, 1)); - - % Get axes for this panel: - xas = (lay.pos(k,1) + linspace(0,1,size(cdata,2))*lay.width(k)); - yas = (lay.pos(k,2) + linspace(0,1,size(cdata,1))*lay.height(k)); - - % Draw plot: - imagesc(xas, yas, cdata, [zmin zmax]); -end - -% set colormap -if isfield(cfg,'colormap') - if size(cfg.colormap,2)~=3, error('singleplotTFR(): Colormap must be a n x 3 matrix'); end - colormap(cfg.colormap); -end; - -% plot colorbar: -if isfield(cfg, 'colorbar') && (strcmp(cfg.colorbar, 'yes')) - colorbar; -end - -% Make the figure interactive: -if strcmp(cfg.interactive, 'yes') - % add the channel information to the figure - info = guidata(gcf); - info.x = lay.pos(:,1); - info.y = lay.pos(:,2); - info.label = lay.label; - guidata(gcf, info); - - set(gcf, 'WindowButtonUpFcn', {@select_channel, 'multiple', true, 'callback', {@select_singleplotTFR, cfg, data}, 'event', 'WindowButtonUpFcn'}); - set(gcf, 'WindowButtonDownFcn', {@select_channel, 'multiple', true, 'callback', {@select_singleplotTFR, cfg, data}, 'event', 'WindowButtonDownFcn'}); - set(gcf, 'WindowButtonMotionFcn', {@select_channel, 'multiple', true, 'callback', {@select_singleplotTFR, cfg, data}, 'event', 'WindowButtonMotionFcn'}); -end - -axis tight -axis off -if strcmp(cfg.box, 'yes') - abc = axis; - axis(abc + [-1 +1 -1 +1]*mean(abs(abc))/10) -end -orient landscape -hold off - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function l = cellstrmatch(str,strlist) -l = []; -for k=1:length(strlist) - if strcmp(char(str),char(strlist(k))) - l = [l k]; - end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION which is called by select_channel in case cfg.cohrefchannel='gui' -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function select_multiplotTFR(label, cfg, varargin) -cfg.cohrefchannel = label; -fprintf('selected cfg.cohrefchannel = ''%s''\n', cfg.cohrefchannel); -p = get(gcf, 'Position'); -f = figure; -set(f, 'Position', p); -multiplotTFR(cfg, varargin{:}); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION which is called after selecting channels in case of cfg.interactive='yes' -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function select_singleplotTFR(label, cfg, varargin) -if ~isempty(label) - cfg.xlim = 'maxmin'; - cfg.ylim = 'maxmin'; - cfg.channel = label; - fprintf('selected cfg.channel = {'); - for i=1:(length(cfg.channel)-1) - fprintf('''%s'', ', cfg.channel{i}); - end - fprintf('''%s''}\n', cfg.channel{end}); - p = get(gcf, 'Position'); - f = figure; - set(f, 'Position', p); - singleplotTFR(cfg, varargin{:}); -end - diff --git a/external/fieldtrip/private/music.m b/external/fieldtrip/private/music.m deleted file mode 100644 index 1e996c1..0000000 --- a/external/fieldtrip/private/music.m +++ /dev/null @@ -1,121 +0,0 @@ -function [dipout] = music(dip, grad, vol, dat, varargin); - -% MUSIC source localization using MUltiple SIgnal Classification -% -% This is a signal subspace method, which covers the techniques for -% multiple source localization by using the eigen structure of the -% measured data matrix. -% -% Use as -% [dipout] = music(dip, grad, vol, dat, ...) -% -% Optional input arguments should be specified as key-value pairs and can be -% 'cov' = data covariance matrix -% 'numcomponent' = integer number -% 'feedback' = 'none', 'gui', 'dial', 'textbar', 'text', 'textcr', 'textnl' -% 'reducerank' = reduce the leadfield rank, can be 'no' or a number (e.g. 2) -% 'normalize' = normalize the leadfield -% 'normalizeparam' = parameter for depth normalization (default = 0.5) -% -% The original reference is -% J.C. Mosher, P.S. Lewis and R.M. Leahy, "Multiple dipole modeling and -% localization from spatiotemporal MEG data", IEEE Trans. Biomed. -% Eng., pp 541-557, June, 1992. - -% Copyright (C) 2004-2008, Robert Oostenveld -% -% $Log: music.m,v $ -% Revision 1.6 2008/03/18 13:17:04 roboos -% updated documentation -% -% Revision 1.5 2008/03/18 13:02:11 roboos -% added all options for leadfield computation -% use dip.mom as dipole orientation if present -% -% Revision 1.4 2008/03/18 12:30:46 roboos -% renamed output metric to dipout.jr -% fixed typo in literature reference -% add explicit references to the equations and pages -% some other changes that should not affect the functionality but that improve the readability of the code -% -% Revision 1.3 2006/06/22 12:17:57 roboos -% function was broken, renamed some variables, added optinal inputs for numcomponents and covariance -% -% Revision 1.2 2006/05/10 08:18:21 roboos -% swiched to using keyval() function for getting optional arguments instead of using eval() -% -% Revision 1.1 2005/09/29 00:56:19 roboos -% new implementation, has not yet been tested -% - -% get the optional settings, or use the default value -cov = keyval('cov', varargin); -numcomponent = keyval('numcomponent', varargin); % this is required, see below -feedback = keyval('feedback', varargin); if isempty(feedback), feedback = 'text'; end -% these settings pertain to the forward model, the defaults are set in compute_leadfield -reducerank = keyval('reducerank', varargin); -normalize = keyval('normalize', varargin); -normalizeparam = keyval('normalizeparam', varargin); - -if isempty(numcomponent) - error('you must specify the number of signal components'); -end - -% ensure that these are row-vectors -dip.inside = dip.inside(:)'; -dip.outside = dip.outside(:)'; - -Nchan = length(grad.label); -Ndip = length(dip.inside); - -if ~isempty(cov) - % compute signal and noise subspace from covariance matrix - [u, s, v] = svd(cov); -else - % compute signal and noise subspace from average data matrix - [u, s, v] = svd(dat); -end -% select the noise subspace, c.f. equation 25 -us = u(:,(numcomponent+1):end); -ps = us * us'; - -% allocate space to hold the result -jr = zeros(length(dip.inside)+length(dip.outside),1); - -progress('init', feedback, 'computing music metric'); -for i=1:length(dip.inside) - - progress(i/length(dip.inside), 'computing music metric %d/%d\n', i, length(dip.inside)); - i = dip.inside(i); - - if isfield(dip, 'leadfield') - % reuse the leadfield that was previously computed - lf = dip.leadfield{i}; - elseif isfield(dip, 'mom') - % compute the leadfield for a fixed dipole orientation - lf = compute_leadfield(dip.pos(i,:), grad, vol, 'reducerank', reducerank, 'normalize', normalize, 'normalizeparam', normalizeparam) * dip.mom(:,i); - else - % compute the leadfield - lf = compute_leadfield(dip.pos(i,:), grad, vol, 'reducerank', reducerank, 'normalize', normalize, 'normalizeparam', normalizeparam); - end - - % compute the MUSIC metric, c.f. equation 26 - jr(i) = (norm(ps * lf)./norm(lf)).^2; - % as described in the Mosher 1992 paper on page 550, "...the general approach is to - % evaluare Jr(i) over a fine three-dimensional grid, plot its inverse, - % and look for p sharp spikes..." - -end -progress('close'); - -% locations outside the head get assigned a nan -jr(dip.outside) = nan; - -% assign the output data -dipout.jr = jr(:); % ensure that it is a column vector - -% add other descriptive information to the output source model -dipout.pos = dip.pos; -dipout.inside = dip.inside; -dipout.outside = dip.outside; - diff --git a/external/fieldtrip/private/nan_mean.m b/external/fieldtrip/private/nan_mean.m index 759832a..27ec3e9 100644 --- a/external/fieldtrip/private/nan_mean.m +++ b/external/fieldtrip/private/nan_mean.m @@ -22,23 +22,23 @@ % along with this program; if not, write to the Free Software % Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -% $Log: nan_mean.m,v $ -% Revision 1.3 2006/03/14 15:01:58 roboos -% turn divideByZero warning temporary off +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.2 2005/05/17 17:50:49 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.1 2004/09/27 15:20:08 roboos -% subfunction required by multiplotTFR, singleplotTFR and topoplotTFR +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.2 2002/10/17 18:43:16 arno -% debugging dim -% -% Revision 1.1 2002/10/17 02:34:52 arno -% Initial revision +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: nan_mean.m 952 2010-04-21 18:29:51Z roboos $ function out = nan_mean(in, dim) diff --git a/external/fieldtrip/private/nan_std.m b/external/fieldtrip/private/nan_std.m index 7c03ba4..261e969 100644 --- a/external/fieldtrip/private/nan_std.m +++ b/external/fieldtrip/private/nan_std.m @@ -22,13 +22,23 @@ % along with this program; if not, write to the Free Software % Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -% $Log: nan_std.m,v $ -% Revision 1.1 2005/04/08 06:53:00 roboos -% originates from EEGLAB, goes together with nan_mean +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.1 2003/09/04 00:57:11 arno -% Initial revision +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: nan_std.m 952 2010-04-21 18:29:51Z roboos $ function out = nan_std(in) diff --git a/external/fieldtrip/private/nanmean.m b/external/fieldtrip/private/nanmean.m index bd03901..04a6912 100644 --- a/external/fieldtrip/private/nanmean.m +++ b/external/fieldtrip/private/nanmean.m @@ -22,26 +22,23 @@ % along with this program; if not, write to the Free Software % Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -% $Log: nanmean.m,v $ -% Revision 1.1 2006/03/20 14:36:46 jansch -% adjusted the nan_XXX functions in fieldtrip's private directory such that the -% corresponding functions behave consistently with the identical matlab-functions, -% not using the stats toolbox. original private functions are renamed from nan_XXX -% into nanXXX (also consistent with matlab terminology) +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.2 2005/05/17 17:50:49 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.1 2004/09/27 15:20:08 roboos -% subfunction required by multiplotTFR, singleplotTFR and topoplotTFR +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.2 2002/10/17 18:43:16 arno -% debugging dim -% -% Revision 1.1 2002/10/17 02:34:52 arno -% Initial revision +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: nanmean.m 952 2010-04-21 18:29:51Z roboos $ function out = nanmean(in, dim) diff --git a/external/fieldtrip/private/nanstandardise.m b/external/fieldtrip/private/nanstandardise.m new file mode 100644 index 0000000..eab06ea --- /dev/null +++ b/external/fieldtrip/private/nanstandardise.m @@ -0,0 +1,45 @@ +function [x,mx,sx] = standardise(x,dim) + +% X = NANSTANDARDISE(X, DIM) computes the zscore of a matrix along dimension +% dim, taking nans into account +% has similar functionality as the stats-toolbox's zscore function + +% Copyright (C) 2010, Jan-Mathijs Schoffelen +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id$ + +if nargin == 1, dim = find(size(x)>1,1,'first'); end + +siz = size(x); +n = sum(~isnan(x),dim); +x(isnan(x)) = 0; +repsiz = siz; +repsiz(setdiff(1:numel(siz), dim)) = 1; +ressiz = [siz 1]; +if dim>1, + ressiz(dim) = []; +else + ressiz(dim) = 1; +end +mx = sum(x,dim)./n; +x = x - repmat(mx, repsiz); +%mx = reshape(mx, ressiz); +sx = sqrt(sum(x.^2,dim)./n); +x = x ./repmat(sx, repsiz); +%sx = reshape(sx, ressiz); diff --git a/external/fieldtrip/private/nanstd.m b/external/fieldtrip/private/nanstd.m index 897f200..bae32cf 100644 --- a/external/fieldtrip/private/nanstd.m +++ b/external/fieldtrip/private/nanstd.m @@ -22,22 +22,23 @@ % along with this program; if not, write to the Free Software % Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -% $Log: nanstd.m,v $ -% Revision 1.2 2006/08/19 12:27:02 marsie -% fixed bug: crashed with empty flag +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.1 2006/03/20 14:36:46 jansch -% adjusted the nan_XXX functions in fieldtrip's private directory such that the -% corresponding functions behave consistently with the identical matlab-functions, -% not using the stats toolbox. original private functions are renamed from nan_XXX -% into nanXXX (also consistent with matlab terminology) +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.1 2005/04/08 06:53:00 roboos -% originates from EEGLAB, goes together with nan_mean +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.1 2003/09/04 00:57:11 arno -% Initial revision +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: nanstd.m 952 2010-04-21 18:29:51Z roboos $ function out = nanstd(in, varargin) diff --git a/external/fieldtrip/private/nansum.m b/external/fieldtrip/private/nansum.m index 592133b..93f3479 100644 --- a/external/fieldtrip/private/nansum.m +++ b/external/fieldtrip/private/nansum.m @@ -22,13 +22,23 @@ % along with this program; if not, write to the Free Software % Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -%$Log: nansum.m,v $ -%Revision 1.1 2006/03/20 14:36:45 jansch -%adjusted the nan_XXX functions in fieldtrip's private directory such that the -%corresponding functions behave consistently with the identical matlab-functions, -%not using the stats toolbox. original private functions are renamed from nan_XXX -%into nanXXX (also consistent with matlab terminology) +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: nansum.m 952 2010-04-21 18:29:51Z roboos $ function out = nansum(in, dim) diff --git a/external/fieldtrip/private/nanvar.m b/external/fieldtrip/private/nanvar.m index 22348ad..e1474df 100644 --- a/external/fieldtrip/private/nanvar.m +++ b/external/fieldtrip/private/nanvar.m @@ -22,10 +22,23 @@ % along with this program; if not, write to the Free Software % Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -% $Log: nanvar.m,v $ -% Revision 1.1 2009/01/28 12:12:40 roboos -% initial implementation, based on nanstd +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: nanvar.m 952 2010-04-21 18:29:51Z roboos $ function out = nanvar(in, varargin) diff --git a/external/fieldtrip/private/nearest.m b/external/fieldtrip/private/nearest.m deleted file mode 100644 index 653bccb..0000000 --- a/external/fieldtrip/private/nearest.m +++ /dev/null @@ -1,38 +0,0 @@ -function [i] = nearest(array, val) - -% NEAREST return the index of an array nearest to a scalar -% -% [indx] = nearest(array, val) - -% Copyright (C) 2002, Robert Oostenveld -% -% $Log: nearest.m,v $ -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.3 2004/12/06 12:55:57 roboos -% added support for -inf and inf, respectively returning the first and last occurence of the nearest element -% -% Revision 1.2 2003/03/17 10:37:28 roberto -% improved general help comments and added copyrights -% - -mbrealvector(array) -mbrealscalar(val) - -% ensure that it is a column vector -array = array(:); - -if isnan(val) - error('incorrect value') -end - -if val>max(array) - % return the last occurence of the nearest number - [dum, i] = max(flipud(array)); - i = length(array) + 1 - i; -else - % return the first occurence of the nearest number - [mindist, i] = min(abs(array(:) - val)); -end - diff --git a/external/fieldtrip/private/neighbourselection.m b/external/fieldtrip/private/neighbourselection.m deleted file mode 100644 index 390af41..0000000 --- a/external/fieldtrip/private/neighbourselection.m +++ /dev/null @@ -1,190 +0,0 @@ -function neighbours = neighbourselection(cfg,data) - -% NEIGHBOURSELECTION finds the neighbours of the channels on the basis of a -% minimum neighbourhood distance (in cfg.neighbourdist). The positions of -% the channel are specified in a gradiometer or electrode configuration or -% from a layout. -% This configuration can be passed in three ways: -% (1) in a configuration field, -% (2) in a file whose name is passed in a configuration field, and that can be imported using READ_SENS, or -% (3) in a data field. -% -% Use as -% neighbours = neighbourselection(cfg, data) -% -% The configuration can contain -% cfg.neighbourdist = number, maximum distance between neighbouring sensors -% cfg.elec = structure with EEG electrode positions -% cfg.grad = structure with MEG gradiometer positions -% cfg.elecfile = filename containing EEG electrode positions -% cfg.gradfile = filename containing MEG gradiometer positions -% cfg.layout = filename of the layout, see PREPARE_LAYOUT -% cfg.feedback = 'yes' or 'no' (default = 'no') -% -% The following data fields may also be used by NEIGHBOURSELECTION: -% data.elec = structure with EEG electrode positions -% data.grad = structure with MEG gradiometer positions -% -% The output: -% neighbours = definition of neighbours for each channel, -% which is structured like this: -% neighbours{1}.label = 'Fz'; -% neighbours{1}.neighblabel = {'Cz', 'F3', 'F3A', 'FzA', 'F4A', 'F4'}; -% neighbours{2}.label = 'Cz'; -% neighbours{2}.neighblabel = {'Fz', 'F4', 'RT', 'RTP', 'P4', 'Pz', 'P3', 'LTP', 'LT', 'F3'}; -% neighbours{3}.label = 'Pz'; -% neighbours{3}.neighblabel = {'Cz', 'P4', 'P4P', 'Oz', 'P3P', 'P3'}; -% etc. -% (Note that a channel is not considered to be a neighbour of itself.) - -% Copyright (C) 2006-2008, Eric Maris, Robert Oostenveld -% -% $Log: neighbourselection.m,v $ -% Revision 1.13 2009/04/07 15:49:40 ingnie -% Only changed help -> fixed typo and mentioned layout possibility in description. -% -% Revision 1.12 2008/11/12 19:22:38 roboos -% documented cfg.layout, added cfg.feedback -% -% Revision 1.11 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.10 2008/03/05 10:46:36 roboos -% moved electrode reading functionality from read_fcdc_elec to read_sens, switched to the use of the new function -% -% Revision 1.9 2008/01/24 17:05:04 roboos -% mention layout in the "undocumented options" section -% -% Revision 1.8 2007/05/14 08:26:31 roboos -% added option to construct neighbours from 2-D layout -% -% Revision 1.7 2006/10/11 09:44:54 roboos -% updated documentation -% -% Revision 1.6 2006/07/12 14:14:59 roboos -% get sens from data.grad/elec -% -% Revision 1.5 2006/07/03 12:57:07 erimar -% Improved help. -% -% Revision 1.4 2006/06/12 08:25:25 erimar -% Added help concerning the structure of cfg.neighbour. Removed -% subfunction involving the calculation of the channel (combination) -% neighourhood geometry. -% -% Revision 1.3 2006/04/20 09:58:34 roboos -% updated documentation -% -% Revision 1.2 2006/04/12 09:10:53 roboos -% added a fprintf statement about the number of neighbours that was found -% -% Revision 1.1 2006/04/11 16:15:24 roboos -% created seperate implementation for the construction of the neighbourhood structure, slightly comparable to channelselection -% - -fieldtripdefs - -% set the defaults -if ~isfield(cfg, 'neighbourdist'), cfg.neighbourdist = 4; end -if ~isfield(cfg, 'feedback'), cfg.feedback = 'no'; end - -% get the the grad or elec if not present in the data -if isfield(cfg, 'grad') - fprintf('Obtaining the gradiometer configuration from the configuration.\n'); - sens = cfg.grad; -elseif isfield(cfg, 'elec') - fprintf('Obtaining the electrode configuration from the configuration.\n'); - sens = cfg.elec; -elseif isfield(cfg, 'gradfile') - fprintf('Obtaining the gradiometer configuration from a file.\n'); - sens = read_sens(cfg.gradfile); -elseif isfield(cfg, 'elecfile') - fprintf('Obtaining the electrode configuration from a file.\n'); - sens = read_sens(cfg.elecfile); -elseif isfield(cfg, 'layout') - fprintf('Using the 2-D layout to determine the neighbours\n'); - lay = prepare_layout(cfg); - sens = []; - sens.label = lay.label; - sens.pnt = lay.pos; - sens.pnt(:,3) = 0; -elseif isfield(data, 'grad') - fprintf('Using the gradiometer configuration from the dataset.\n'); - sens = data.grad; -elseif isfield(data, 'elec') - fprintf('Using the electrode configuration from the dataset.\n'); - sens = data.elec; -end -if ~isstruct(sens) - error('Did not find gradiometer or electrode information.'); -end; - -neighbours = compneighbstructfromgradelec(sens, cfg.neighbourdist); - -k = 0; -for i=1:length(neighbours) - k = k + length(neighbours{i}.neighblabel); -end -fprintf('there are on average %.1f neighbours per channel\n', k/length(neighbours)); - -if strcmp(cfg.feedback, 'yes') - % give some graphical feedback - if all(sens.pnt(:,3)==0) - % the sensor positions are already projected on a 2D plane - proj = sens.pnt(:,1:2); - else - % project the 3D positions onto a 2D plane - proj = elproj(sens.pnt); - end - figure - for i=1:length(neighbours) - cla - this = neighbours{i}; - sel1 = match_str(sens.label, this.label); - sel2 = match_str(sens.label, this.neighblabel); - plot(proj(:,1), proj(:,2), 'k.'); - axis equal - title(this.label); - axis off - for j=1:length(this.neighblabel) - x1 = proj(sel1,1); - y1 = proj(sel1,2); - x2 = proj(sel2(j),1); - y2 = proj(sel2(j),2); - X = [x1 x2]; - Y = [y1 y2]; - line(X, Y, 'color', 'r'); - end - drawnow - pause(0.1); - end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION that compute the neighbourhood geometry from the -% gradiometer/electrode positions -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [neighbours]=compneighbstructfromgradelec(sens,neighbourdist) - -nsensors = length(sens.label); - -% compute the distance between all sensors -dist = zeros(nsensors,nsensors); -for i=1:nsensors - dist(i,:) = sqrt(sum((sens.pnt(1:nsensors,:) - repmat(sens.pnt(i,:), nsensors, 1)).^2,2))'; -end; - -% find the neighbouring electrodes based on distance -% later we have to restrict the neighbouring electrodes to those actually selected in the dataset -channeighbstructmat = (dist. +% +% $Id: neuralynx_crc.m 945 2010-04-21 17:41:20Z roboos $ nchans = size(dat,1); diff --git a/external/fieldtrip/private/neuralynx_getheader.m b/external/fieldtrip/private/neuralynx_getheader.m index dfc85be..0f2eaf0 100644 --- a/external/fieldtrip/private/neuralynx_getheader.m +++ b/external/fieldtrip/private/neuralynx_getheader.m @@ -4,6 +4,26 @@ % SUBFUNCTION for reading the 16384 byte header from any Neuralynx file %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Copyright (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: neuralynx_getheader.m 945 2010-04-21 17:41:20Z roboos $ + fid = fopen(filename, 'rb', 'ieee-le'); buf = fread(fid, 16*1024, 'uint8=>char'); fclose(fid); diff --git a/external/fieldtrip/private/neuralynx_numrecords.m b/external/fieldtrip/private/neuralynx_numrecords.m index 7755516..0f1e346 100644 --- a/external/fieldtrip/private/neuralynx_numrecords.m +++ b/external/fieldtrip/private/neuralynx_numrecords.m @@ -1,9 +1,29 @@ -function [t] = neuralynx_numrecords(filename); +function [t] = neuralynx_numrecords(filename) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % SUBFUNCTION for determining the number of records in a single channel Neualynx file %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Copyright (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: neuralynx_numrecords.m 945 2010-04-21 17:41:20Z roboos $ + headersize = 16384; switch filetype(filename) case 'neuralynx_ncs' diff --git a/external/fieldtrip/private/neuralynx_timestamp.m b/external/fieldtrip/private/neuralynx_timestamp.m index 94e6b91..5d7d657 100644 --- a/external/fieldtrip/private/neuralynx_timestamp.m +++ b/external/fieldtrip/private/neuralynx_timestamp.m @@ -4,6 +4,26 @@ % SUBFUNCTION for reading a single timestamp of a single channel Neuralynx file %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Copyright (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: neuralynx_timestamp.m 945 2010-04-21 17:41:20Z roboos $ + headersize = 16384; switch filetype(filename) case 'neuralynx_ncs' diff --git a/external/fieldtrip/private/nex_cont.m b/external/fieldtrip/private/nex_cont.m index 0835ea4..b90eee3 100644 --- a/external/fieldtrip/private/nex_cont.m +++ b/external/fieldtrip/private/nex_cont.m @@ -20,19 +20,23 @@ % original from Plexon, download from http://www.plexoninc.com (8/4/02) % modifications by Robert Oostenveld % -% $Log: nex_cont.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.3 2008/09/30 07:47:04 roboos -% replaced all occurences of setstr() with char(), because setstr is deprecated by Matlab +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.2 2008/07/24 12:03:23 roboos -% changed end of line to unix style +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.1 2005/02/11 07:46:34 roboos -% downloaded from Plexon website, added support for reading nex files on Solaris and Mac OS X (fopen ieee-le), added log-section to the comments after the help +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: nex_cont.m 952 2010-04-21 18:29:51Z roboos $ n = 0; adfreq = 0; @@ -57,7 +61,7 @@ if(length(filename) == 0) [fname, pathname] = uigetfile('*.nex', 'Select a Nex file'); - filename = strcat(pathname, fname); + filename = strcat(pathname, fname); end fid = fopen(filename, 'r', 'ieee-le'); @@ -77,41 +81,41 @@ name = zeros(1, 64); found = 0; for i=1:nvar - type = fread(fid, 1, 'int32'); - var_version = fread(fid, 1, 'int32'); - name = fread(fid, [1 64], 'char'); - offset = fread(fid, 1, 'int32'); - nf = fread(fid, 1, 'int32'); - dummy = fread(fid, 32, 'char'); - adfreq = fread(fid, 1, 'double'); - adtomv = fread(fid, 1, 'double'); - n = fread(fid, 1, 'int32'); - name = char(name); - name = deblank(name); - k = strcmp(name, deblank(varname)); - if(k == 1) - if type ~= 5 - disp(sprintf('%s is not a continuous variable', deblank(varname))); - return; - end - found = 1; - fseek(fid, offset, 'bof'); - ts = fread(fid, [1 nf], 'int32'); - fn = fread(fid, [1 nf], 'int32'); - d = fread(fid, [1 n], 'int16'); - break - end - dummy = fread(fid, 76, 'char'); + type = fread(fid, 1, 'int32'); + var_version = fread(fid, 1, 'int32'); + name = fread(fid, [1 64], 'char'); + offset = fread(fid, 1, 'int32'); + nf = fread(fid, 1, 'int32'); + dummy = fread(fid, 32, 'char'); + adfreq = fread(fid, 1, 'double'); + adtomv = fread(fid, 1, 'double'); + n = fread(fid, 1, 'int32'); + name = char(name); + name = deblank(name); + k = strcmp(name, deblank(varname)); + if(k == 1) + if type ~= 5 + disp(sprintf('%s is not a continuous variable', deblank(varname))); + return; + end + found = 1; + fseek(fid, offset, 'bof'); + ts = fread(fid, [1 nf], 'int32'); + fn = fread(fid, [1 nf], 'int32'); + d = fread(fid, [1 n], 'int16'); + break + end + dummy = fread(fid, 76, 'char'); end fclose(fid); if found == 0 - disp('did not find variable in the file'); + disp('did not find variable in the file'); else - ts = ts/freq; - d = d*adtomv; - fn(nf+1) = n; - fn = diff(fn); - disp(strcat('number of data points = ', num2str(n))); + ts = ts/freq; + d = d*adtomv; + fn(nf+1) = n; + fn = diff(fn); + disp(strcat('number of data points = ', num2str(n))); end diff --git a/external/fieldtrip/private/nex_info.m b/external/fieldtrip/private/nex_info.m index fdb4613..f2c0c31 100644 --- a/external/fieldtrip/private/nex_info.m +++ b/external/fieldtrip/private/nex_info.m @@ -15,19 +15,23 @@ % original from Plexon, download from http://www.plexoninc.com (8/4/02) % modifications by Robert Oostenveld % -% $Log: nex_info.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.3 2008/09/30 07:47:04 roboos -% replaced all occurences of setstr() with char(), because setstr is deprecated by Matlab +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.2 2008/07/24 12:03:23 roboos -% changed end of line to unix style +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.1 2005/02/11 07:46:34 roboos -% downloaded from Plexon website, added support for reading nex files on Solaris and Mac OS X (fopen ieee-le), added log-section to the comments after the help +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: nex_info.m 952 2010-04-21 18:29:51Z roboos $ if(nargin ~= 1) disp('1 input arguments are required') @@ -36,12 +40,12 @@ if(length(filename) == 0) [fname, pathname] = uigetfile('*.nex', 'Select a Nex file'); - filename = strcat(pathname, fname); + filename = strcat(pathname, fname); end fid = fopen(filename, 'r', 'ieee-le'); if(fid == -1) - disp('cannot open file'); + disp('cannot open file'); return end @@ -60,10 +64,10 @@ disp(strcat('number of variables = ', num2str(nvar))); names = zeros(1, 64); for i=1:nvar - types(i) = fread(fid, 1, 'int32'); - var_version = fread(fid, 1, 'int32'); - names(i, :) = fread(fid, [1 64], 'char'); - dummy = fread(fid, 128+8, 'char'); + types(i) = fread(fid, 1, 'int32'); + var_version = fread(fid, 1, 'int32'); + names(i, :) = fread(fid, [1 64], 'char'); + dummy = fread(fid, 128+8, 'char'); end names = char(names); fclose(fid); diff --git a/external/fieldtrip/private/nex_int.m b/external/fieldtrip/private/nex_int.m index 95eac43..2b8c17e 100644 --- a/external/fieldtrip/private/nex_int.m +++ b/external/fieldtrip/private/nex_int.m @@ -14,19 +14,23 @@ % original from Plexon, download from http://www.plexoninc.com (8/4/02) % modifications by Robert Oostenveld % -% $Log: nex_int.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.3 2008/09/30 07:47:04 roboos -% replaced all occurences of setstr() with char(), because setstr is deprecated by Matlab +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.2 2008/07/24 12:03:23 roboos -% changed end of line to unix style +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.1 2005/02/11 07:46:34 roboos -% downloaded from Plexon website, added support for reading nex files on Solaris and Mac OS X (fopen ieee-le), added log-section to the comments after the help +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: nex_int.m 952 2010-04-21 18:29:51Z roboos $ n = 0; ts_left = 0; @@ -49,12 +53,12 @@ if(length(filename) == 0) [fname, pathname] = uigetfile('*.nex', 'Select a Nex file'); - filename = strcat(pathname, fname); + filename = strcat(pathname, fname); end fid = fopen(filename, 'r', 'ieee-le'); if(fid == -1) - disp('cannot open file'); + disp('cannot open file'); return end @@ -70,34 +74,34 @@ name = zeros(1, 64); found = 0; for i=1:nvar - type = fread(fid, 1, 'int32'); - var_version = fread(fid, 1, 'int32'); - name = fread(fid, [1 64], 'char'); - offset = fread(fid, 1, 'int32'); - n = fread(fid, 1, 'int32'); - name = char(name); - name = deblank(name); - k = strcmp(name, deblank(varname)); - if(k == 1) - if type ~= 2 - disp(sprintf('%s is not an interval variable', deblank(varname))); - return; - end - found = 1; - fseek(fid, offset, 'bof'); - ts_left = fread(fid, [1 n], 'int32'); - ts_right = fread(fid, [1 n], 'int32'); - break - end - dummy = fread(fid, 128, 'char'); + type = fread(fid, 1, 'int32'); + var_version = fread(fid, 1, 'int32'); + name = fread(fid, [1 64], 'char'); + offset = fread(fid, 1, 'int32'); + n = fread(fid, 1, 'int32'); + name = char(name); + name = deblank(name); + k = strcmp(name, deblank(varname)); + if(k == 1) + if type ~= 2 + disp(sprintf('%s is not an interval variable', deblank(varname))); + return; + end + found = 1; + fseek(fid, offset, 'bof'); + ts_left = fread(fid, [1 n], 'int32'); + ts_right = fread(fid, [1 n], 'int32'); + break + end + dummy = fread(fid, 128, 'char'); end fclose(fid); if found == 0 - disp('did not find variable in the file'); + disp('did not find variable in the file'); else - ts_left = ts_left/freq; - ts_right = ts_right/freq; - disp(strcat('number of intervals = ', num2str(n))); + ts_left = ts_left/freq; + ts_right = ts_right/freq; + disp(strcat('number of intervals = ', num2str(n))); end diff --git a/external/fieldtrip/private/nex_marker.m b/external/fieldtrip/private/nex_marker.m index 3ffa287..b48dee9 100644 --- a/external/fieldtrip/private/nex_marker.m +++ b/external/fieldtrip/private/nex_marker.m @@ -22,19 +22,23 @@ % original from Plexon, download from http://www.plexoninc.com (8/4/02) % modifications by Robert Oostenveld % -% $Log: nex_marker.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.3 2008/09/30 07:47:04 roboos -% replaced all occurences of setstr() with char(), because setstr is deprecated by Matlab +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.2 2008/07/24 11:57:57 roboos -% converted end of line into unix style +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.1 2005/02/11 07:46:34 roboos -% downloaded from Plexon website, added support for reading nex files on Solaris and Mac OS X (fopen ieee-le), added log-section to the comments after the help +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: nex_marker.m 952 2010-04-21 18:29:51Z roboos $ n = 0; nm = 0; @@ -60,12 +64,12 @@ if(length(filename) == 0) [fname, pathname] = uigetfile('*.nex', 'Select a Nex file'); - filename = strcat(pathname, fname); + filename = strcat(pathname, fname); end fid = fopen(filename, 'r', 'ieee-le'); if(fid == -1) - disp('cannot open file'); + disp('cannot open file'); return end @@ -81,48 +85,48 @@ name = zeros(1, 64); found = 0; for i=1:nvar - type = fread(fid, 1, 'int32'); - var_version = fread(fid, 1, 'int32'); - name = fread(fid, [1 64], 'char'); - offset = fread(fid, 1, 'int32'); - n = fread(fid, 1, 'int32'); - dummy = fread(fid, 32, 'char'); - adfreq = fread(fid, 1, 'double'); - adtomv = fread(fid, 1, 'double'); - npw = fread(fid, 1, 'int32'); - nm = fread(fid, 1, 'int32'); - nl = fread(fid, 1, 'int32'); - dummy = fread(fid, 68, 'char'); - name = char(name); - name = deblank(name); - k = strcmp(name, deblank(varname)); - if(k == 1) - if type ~= 6 - disp(sprintf('%s is not a marker variable', deblank(varname))); - return; - end - found = 1; - fseek(fid, offset, 'bof'); - ts = fread(fid, [1 n], 'int32'); - names = zeros(1,64); - m = zeros(n, nl, nm); - for j=1:nm - names(j, :) = fread(fid, [1 64], 'char'); - for p = 1:n - m(p, :, j) = fread(fid, [1 nl], 'char'); - end - end - break - end + type = fread(fid, 1, 'int32'); + var_version = fread(fid, 1, 'int32'); + name = fread(fid, [1 64], 'char'); + offset = fread(fid, 1, 'int32'); + n = fread(fid, 1, 'int32'); + dummy = fread(fid, 32, 'char'); + adfreq = fread(fid, 1, 'double'); + adtomv = fread(fid, 1, 'double'); + npw = fread(fid, 1, 'int32'); + nm = fread(fid, 1, 'int32'); + nl = fread(fid, 1, 'int32'); + dummy = fread(fid, 68, 'char'); + name = char(name); + name = deblank(name); + k = strcmp(name, deblank(varname)); + if(k == 1) + if type ~= 6 + disp(sprintf('%s is not a marker variable', deblank(varname))); + return; + end + found = 1; + fseek(fid, offset, 'bof'); + ts = fread(fid, [1 n], 'int32'); + names = zeros(1,64); + m = zeros(n, nl, nm); + for j=1:nm + names(j, :) = fread(fid, [1 64], 'char'); + for p = 1:n + m(p, :, j) = fread(fid, [1 nl], 'char'); + end + end + break + end end fclose(fid); if found == 0 - disp('did not find variable in the file'); + disp('did not find variable in the file'); else - names = char(names); - m = char(m); - ts = ts/freq; - disp(strcat('number of markers = ', num2str(n))); + names = char(names); + m = char(m); + ts = ts/freq; + disp(strcat('number of markers = ', num2str(n))); end diff --git a/external/fieldtrip/private/nex_ts.m b/external/fieldtrip/private/nex_ts.m index b90115a..3e6d765 100644 --- a/external/fieldtrip/private/nex_ts.m +++ b/external/fieldtrip/private/nex_ts.m @@ -13,19 +13,23 @@ % original from Plexon, download from http://www.plexoninc.com (8/4/02) % modifications by Robert Oostenveld % -% $Log: nex_ts.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.3 2008/09/30 07:47:04 roboos -% replaced all occurences of setstr() with char(), because setstr is deprecated by Matlab +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.2 2008/07/24 12:03:23 roboos -% changed end of line to unix style +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.1 2005/02/11 07:46:34 roboos -% downloaded from Plexon website, added support for reading nex files on Solaris and Mac OS X (fopen ieee-le), added log-section to the comments after the help +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: nex_ts.m 952 2010-04-21 18:29:51Z roboos $ n = 0; ts = 0; @@ -47,12 +51,12 @@ if(length(filename) == 0) [fname, pathname] = uigetfile('*.nex', 'Select a Nex file'); - filename = strcat(pathname, fname); + filename = strcat(pathname, fname); end fid = fopen(filename, 'r', 'ieee-le'); if(fid == -1) - disp('cannot open file'); + disp('cannot open file'); return end @@ -68,28 +72,28 @@ name = zeros(1, 64); found = 0; for i=1:nvar - type = fread(fid, 1, 'int32'); - var_version = fread(fid, 1, 'int32'); - name = fread(fid, [1 64], 'char'); - offset = fread(fid, 1, 'int32'); - n = fread(fid, 1, 'int32'); - name = char(name); - name = deblank(name); - k = strcmp(name, deblank(varname)); - if(k == 1) - found = 1; - fseek(fid, offset, 'bof'); - ts = fread(fid, [1 n], 'int32'); - break - end - dummy = fread(fid, 128, 'char'); + type = fread(fid, 1, 'int32'); + var_version = fread(fid, 1, 'int32'); + name = fread(fid, [1 64], 'char'); + offset = fread(fid, 1, 'int32'); + n = fread(fid, 1, 'int32'); + name = char(name); + name = deblank(name); + k = strcmp(name, deblank(varname)); + if(k == 1) + found = 1; + fseek(fid, offset, 'bof'); + ts = fread(fid, [1 n], 'int32'); + break + end + dummy = fread(fid, 128, 'char'); end fclose(fid); if found == 0 - disp('did not find variable in the file'); + disp('did not find variable in the file'); else - ts = ts/freq; - disp(strcat('number of timestamps = ', num2str(n))); + ts = ts/freq; + disp(strcat('number of timestamps = ', num2str(n))); end diff --git a/external/fieldtrip/private/nex_wf.m b/external/fieldtrip/private/nex_wf.m index ec0939e..0fa47f3 100644 --- a/external/fieldtrip/private/nex_wf.m +++ b/external/fieldtrip/private/nex_wf.m @@ -17,19 +17,23 @@ % original from Plexon, download from http://www.plexoninc.com (8/4/02) % modifications by Robert Oostenveld % -% $Log: nex_wf.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.3 2008/09/30 07:47:04 roboos -% replaced all occurences of setstr() with char(), because setstr is deprecated by Matlab +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.2 2008/07/24 12:02:01 roboos -% changed end of line to unix style +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.1 2005/02/11 07:46:34 roboos -% downloaded from Plexon website, added support for reading nex files on Solaris and Mac OS X (fopen ieee-le), added log-section to the comments after the help +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: nex_wf.m 952 2010-04-21 18:29:51Z roboos $ n = 0; adfreq = 0; @@ -54,7 +58,7 @@ if(length(filename) == 0) [fname, pathname] = uigetfile('*.nex', 'Select a Nex file'); - filename = strcat(pathname, fname); + filename = strcat(pathname, fname); end fid = fopen(filename, 'r', 'ieee-le'); @@ -74,38 +78,38 @@ name = zeros(1, 64); found = 0; for i=1:nvar - type = fread(fid, 1, 'int32'); - var_version = fread(fid, 1, 'int32'); - name = fread(fid, [1 64], 'char'); - offset = fread(fid, 1, 'int32'); - nf = fread(fid, 1, 'int32'); - dummy = fread(fid, 32, 'char'); - adfreq = fread(fid, 1, 'double'); - adtomv = fread(fid, 1, 'double'); - n = fread(fid, 1, 'int32'); - name = char(name); - name = deblank(name); - k = strcmp(name, deblank(varname)); - if(k == 1) - if type ~= 3 - disp(sprintf('%s is not a waveform variable', deblank(varname))); - return; - end - found = 1; - fseek(fid, offset, 'bof'); - ts = fread(fid, [1 nf], 'int32'); - w = fread(fid, [n nf], 'int16'); - break - end - dummy = fread(fid, 76, 'char'); + type = fread(fid, 1, 'int32'); + var_version = fread(fid, 1, 'int32'); + name = fread(fid, [1 64], 'char'); + offset = fread(fid, 1, 'int32'); + nf = fread(fid, 1, 'int32'); + dummy = fread(fid, 32, 'char'); + adfreq = fread(fid, 1, 'double'); + adtomv = fread(fid, 1, 'double'); + n = fread(fid, 1, 'int32'); + name = char(name); + name = deblank(name); + k = strcmp(name, deblank(varname)); + if(k == 1) + if type ~= 3 + disp(sprintf('%s is not a waveform variable', deblank(varname))); + return; + end + found = 1; + fseek(fid, offset, 'bof'); + ts = fread(fid, [1 nf], 'int32'); + w = fread(fid, [n nf], 'int16'); + break + end + dummy = fread(fid, 76, 'char'); end fclose(fid); if found == 0 - disp('did not find variable in the file'); + disp('did not find variable in the file'); else - ts = ts/freq; - w = w*adtomv; - disp(strcat('number of waveforms = ', num2str(nf))); + ts = ts/freq; + w = w*adtomv; + disp(strcat('number of waveforms = ', num2str(nf))); end diff --git a/external/fieldtrip/private/nimh2grad.m b/external/fieldtrip/private/nimh2grad.m index a97c396..11417d2 100644 --- a/external/fieldtrip/private/nimh2grad.m +++ b/external/fieldtrip/private/nimh2grad.m @@ -13,22 +13,23 @@ % Copyright (C) 2005, Robert Oostenveld % -% $Log: nimh2grad.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.3 2007/03/07 08:37:55 roboos -% fixed typo +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.2 2007/03/06 09:37:35 roboos -% small change in determining the MEG channels, thanks to Nicolas Robitaille +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.1 2006/08/31 13:32:11 roboos -% moved from fieldtrip to fileio module -% -% Revision 1.1 2005/05/26 09:55:55 roboos -% new implementation to complement the NIMH ctf reading routines +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: nimh2grad.m 952 2010-04-21 18:29:51Z roboos $ % only work on the MEG channels if isfield(hdr.sensor.index, 'meg') diff --git a/external/fieldtrip/private/nonlinearassociation.m b/external/fieldtrip/private/nonlinearassociation.m deleted file mode 100644 index 49eea40..0000000 --- a/external/fieldtrip/private/nonlinearassociation.m +++ /dev/null @@ -1,403 +0,0 @@ -function [association] = nonlinearassociation(cfg, data) - -% NONLINEARASSOCIATION calculate the association coefficient as a -% function of delay. -% -% In order to estimate the amount of association between all possible -% pairs of MEG sensors the nonlinear association analysis is used. -% It was first developed for EEG data analysis by Pijn and co-workers -% (Lopes da Silva, et al. 1989; Pijn, et al. 1990). The basic principle -% is similar to that of coherence and (cross) correlation, with the -% exception that this nonlinear association method can be applied -% independent of the type of relationship (linear or nonlinear) in -% the data. -% -% The method is based on the idea that if two signals x and y are -% correlated, a nonlinear regression curve can be calculated that -% represents their relationship. In practice, that regression curve -% is estimated by creating a scatterplot of y versus x, dividing the -% data in segments and describing each segment with a linear regression -% curve. The estimated correlation ratio h2, which gives the reduction -% in variance of y as a result of predicting its values according to -% the regression curve, can be calculated as follows: -% -% h^2 = (sum(Yi - mean(Y))^2 - sum(Yi - f(Xi))^2) / sum(Yi - mean(Y))^2 -% -% With the sum going over N samples and f(Xi) the estimated value of -% Yi according to the regression line. The h2 coefficient has values -% between 0 (y is completely independent of x) and 1 (y is completely -% determined by x). In the case of a linear relationship between x -% and y, h2 is equal to the well known Pearson correlation coefficient -% (r2). As is the case with cross-correlation, it is possible to -% estimate h2 as a function of time shift () between the signals. The -% h2 is then iteratively calculated for different values of , by -% shifting the signals in comparison to each other, and the value for -% which the maximal h2 is reached can be used as an estimate of the -% time lag between both signals. In deciding what epoch length to use -% in the association analysis, a trade-off has to be made between -% successfully determining the correct delay and h2-value (for which -% large epoch lengths are necessary) and a small enough time-resolution -% (for which small epoch lengths are necessary). -% -% Use as -% [association] = nonlinearassociation(cfg, data) -% -% The input data should be organised in a structure as obtained from -% the PREPROCESSING function. -% -% The configuration should contain -% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), see CHANNELSELECTION for details -% cfg.keeptrials = 'yes' or 'no', process the individual trials or the concatenated data (default = 'no') -% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') -% cfg.fsample = 1200 -% cfg.maxdelay = 32/cfg.fsample -% cfg.delaystep = 2/cfg.fsample -% cfg.nr_bins = 7 -% cfg.offset = 0 -% cfg.order = 'Hxy' -% cfg.timwin = 0.2 -% cfg.toi = [] -% -% References -% - Lopes da Silva F, Pijn JP, Boeijinga P. (1989): Interdependence of -% EEG signals: linear vs. nonlinear associations and the significance -% of time delays and phase shifts. Brain Topogr 2(1-2):9-18. -% - Pijn JP, Vijn PC, Lopes da Silva FH, Van Ende Boas W, Blanes W. -% (1990): Localization of epileptogenic foci using a new signal -% analytical approach. Neurophysiol Clin 20(1):1-11. - -% Copyright (C) 2007, Inge Westmijse -% -% $Log: nonlinearassociation.m,v $ -% Revision 1.11 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.10 2008/05/13 15:36:09 roboos -% fixed potential bug in assessing the number of trials (when data.trial was column instead of row vector)a, now use numel instead of size -% -% Revision 1.9 2008/05/06 14:23:32 sashae -% change in trial selection, cfg.trials can be a logical -% -% Revision 1.8 2008/02/20 16:07:48 roboos -% added the documentation according to Pauly -% -% Revision 1.7 2008/02/20 15:38:39 roboos -% removed saving to file, instead return to the command line -% some other small changes to make it run through -% -% Revision 1.6 2008/02/20 14:57:45 roboos -% this is the version that I received from Inge on cdrom -% it was labeled nonlinearassociation_v170108.m -% -% Revision 1.3 2007/11/13 09:16:49 roboos -% fixed bug due to debugging (fixed for-loop) -% -% Revision 1.2 2007/11/13 09:14:57 roboos -% merged Inges contribution, included faster subfunctions for mean and hist -% -% Revision 1.1 2007/10/29 11:18:41 roboos -% renamed function and moved to fieldtrip main, added normal data handling -% and selection - -fieldtripdefs - -% set the defaults -if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end -if ~isfield(cfg, 'keeptrials'), cfg.keeptrials = 'no'; end -if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end -if ~isfield(cfg, 'toi'), cfg.toi = []; end -if ~isfield(cfg, 'timwin'), cfg.timwin = 0.2; end -if ~isfield(cfg, 'fsample'), cfg.fsample = 1200; end -if ~isfield(cfg, 'delaystep'), cfg.delaystep = 2/cfg.fsample; end -if ~isfield(cfg, 'maxdelay'), cfg.maxdelay = 32/cfg.fsample; end -if ~isfield(cfg, 'offset'), cfg.offset = 0; end -if ~isfield(cfg, 'nr_bins'), cfg.nr_bins = 7; end -if ~isfield(cfg, 'order'), cfg.order = 'Hxy'; end -if ~isfield(cfg, 'feedback'), cfg.feedback = 'textbar'; end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% do some bookkeeping on the data -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% select trials of interest -if ~strcmp(cfg.trials, 'all') - if islogical(cfg.trials), cfg.trials=find(cfg.trials); end - fprintf('selecting %d trials\n', length(cfg.trials)); - data.trial = data.trial(cfg.trials); - data.time = data.time(cfg.trials); -end -Ntrials = numel(data.trial); - -% select channels of interest -cfg.channel = channelselection(cfg.channel, data.label); -chansel = match_str(data.label, cfg.channel); -fprintf('selecting %d channels\n', length(chansel)); -for trial=1:Ntrials - data.trial{trial} = data.trial{trial}(chansel,:); -end -data.label = data.label(chansel); -Nchans = length(chansel); - -% determine the size of each trial, they can be variable length -Nsamples = zeros(1,Ntrials); -for trial=1:Ntrials - Nsamples(trial) = size(data.trial{trial},2); -end - -if strcmp(cfg.keeptrials, 'no') - % concatenate all the data into a 2D matrix - fprintf('concatenating data'); - dat = zeros(Nchans, sum(Nsamples)); - for trial=1:Ntrials - fprintf('.'); - begsample = sum(Nsamples(1:(trial-1))) + 1; - endsample = sum(Nsamples(1:trial)); - dat(:,begsample:endsample) = data.trial{trial}; - end - fprintf('\n'); - fprintf('concatenated data matrix size %dx%d\n', size(dat,1), size(dat,2)); - time = [1/cfg.fsample : size(dat,1)/cfg.fsample : size(dat,1)]; - data.trial = {dat}; - data.time = {time}; - Ntrials = 1; -else - % replace the time axis, since shifted time-axes over trials are not supported - for i = 1:Ntrials - data.time{i} = [1/cfg.fsample : 1/cfg.fsample : size(data.trial{i},2) / cfg.fsample]; - end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% prepare all data selection -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% item 1: channel combinations -numchannelcmb = Nchans*(Nchans-1)/2; -channelcmb = zeros(numchannelcmb, 2); -k = 1; - -if (strcmp(cfg.order, 'Hxy')) - for i=1:Nchans - for j=(i+1):Nchans - channelcmb(k, :) = [i j]; - k = k+1; - end - end -elseif (strcmp(cfg.order, 'Hyx')) - for i = Nchans:-1:1 - for j = Nchans : -1:(i+1) - channelcmb(k,:) = [i j]; - k = k+1; - end - end -end -numchannelcmb = size(channelcmb,1); - -% item 2: time windows -% this requires -% cfg.toi = [t1 t2 t3 t4] center time of each window -% cfg.timwin = 0.2 in seconds -% TODO implement "time, offset, fsample" - -for j = 1:Ntrials - time = data.time{j}; - numtimwin = size(cfg.toi,2); % initial guess, not all might fit in this trial - timwin = zeros(numtimwin,2); - sel = zeros(numtimwin,1); - for i=1:numtimwin - timwin(i,1) = cfg.toi(i) - cfg.timwin/2; % begin of time window - timwin(i,2) = cfg.toi(i) + cfg.timwin/2; % end of time window - sel(i) = timwin(i,1)>=time(1) && timwin(i,2)<=time(end); % does it fit in? - end - timwin = timwin(find(sel==1),:); - toi_mat{j} = cfg.toi(find(sel == 1)); % update the configuration - timwin_mat{j} = round((timwin - cfg.offset) * cfg.fsample); % convert to samples -end - -timwin = timwin_mat; -cfg.toi = toi_mat; - -% item 3: delays within each timewindow -% this requires -% cfg.delaystep -% cfg.maxdelay -delay = -cfg.maxdelay:cfg.delaystep:cfg.maxdelay; -numdelay = length(delay); -% convert to samples -delay = round(delay * cfg.fsample); - -if strcmp(cfg.keeptrials, 'yes') - for trllop=1:Ntrials - association.trial(trllop) = Do_Association_Calculation( trllop , Ntrials , cfg , timwin , numchannelcmb , numdelay , data , channelcmb , delay ); - end % for each trial -else - trllop = 1; - association = Do_Association_Calculation( trllop , Ntrials , cfg , timwin , numchannelcmb , numdelay , data , channelcmb , delay ); -end - -% add the version details of this function call to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: nonlinearassociation.m,v 1.11 2008/09/22 20:17:43 roboos Exp $'; -% remember the configuration details of the input data -try, cfg.previous = data.cfg; end -% remember the exact configuration details in the output -association.cfg = cfg; - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION that does the computation for each trial -function [association] = Do_Association_Calculation( trllop , Ntrials , cfg , timwin , numchannelcmb , numdelay , data , channelcmb , delay ) - -fprintf('\nprocessing trial %d from %d\n', trllop, Ntrials); - -association = []; -numtimwin = size(timwin{trllop},1); -h2 = zeros(numchannelcmb, numtimwin, numdelay); - -l = 0; -maxl = numchannelcmb*numtimwin*numdelay; -progress('init', cfg.feedback, 'Computing nonlinear association for each delay'); - -for i=1:numchannelcmb - dat1_chan = data.trial{trllop}(channelcmb(i,1),:); - dat2_chan = data.trial{trllop}(channelcmb(i,2),:); - progress(l/maxl,'Computing nonlinear association %d from %d', l, maxl); - - for j=1:numtimwin - dat1_timwin = dat1_chan(timwin{trllop}(j,1):timwin{trllop}(j,2)); - dat2_timwin = dat2_chan(timwin{trllop}(j,1):timwin{trllop}(j,2)); - - for k=1:numdelay - if delay(k)==0 - % select the complete (unshifted) window - dat1_delay = dat1_timwin; - dat2_delay = dat2_timwin; - elseif delay(k)<0 - % channel 1 is shifted w.r.t. channel 2 - dat1_delay = dat1_timwin((abs(delay(k))+1):end); - dat2_delay = dat2_timwin(1:(end-abs(delay(k)))); - elseif delay(k)>0 - % channel 2 is shifted w.r.t. channel 1 - dat1_delay = dat1_timwin(1:(end-delay(k))); - dat2_delay = dat2_timwin((delay(k)+1):end); - end - - % remove the mean of each snippet of data - dat1_delay = dat1_delay - mean(dat1_delay); - dat2_delay = dat2_delay - mean(dat2_delay); - - % do the computation - - [sorted_data1,id] = sort(dat1_delay); - sorted_data2 = dat2_delay(id); - - data_is = sorted_data1; - data_js = sorted_data2; - - % divided data_i in bins - [H,mp_i] = hist(data_is,cfg.nr_bins); - - % Divide data_i and data_j in bins - bp = 1; - gem_j = zeros (cfg.nr_bins,1); - for s = 1:cfg.nr_bins - gem_j(s) = mean(data_js(bp:bp+H(s)-1)); - bp = bp + H(s); - end - - % Calculation of line segment and variance per bin - p=1; - sp = 1; - - clear unex_var tot_var; - - for u = 1:cfg.nr_bins - data_is_bin = data_is(sp:sp+H(u)-1)'; - data_js_bin = data_js(sp:sp+H(u)-1)'; - - if u == 1 - fx1 = gem_j(u) + (gem_j(u+1) - gem_j(u))/(mp_i(u+1) - mp_i(u))*(data_is_bin(1:round(length(data_is_bin)/2)) - mp_i(u)); - else - fx1 = gem_j(u-1) + (gem_j(u) - gem_j(u-1))/(mp_i(u) - mp_i(u-1))*(data_is_bin(1:round(length(data_is_bin)/2)) - mp_i(u-1)); - end - if u == cfg.nr_bins - fx2 = gem_j(u-1) + (gem_j(u) - gem_j(u-1))/(mp_i(u) - mp_i(u-1))*(data_is_bin(round(length(data_is_bin)/2)+1:end) - mp_i(u-1)); - else - fx2 = gem_j(u) + (gem_j(u+1) - gem_j(u))/(mp_i(u+1) - mp_i(u))*(data_is_bin(round(length(data_is_bin)/2)+1:end) - mp_i(u)); - end - - % calculation unexplained variance - ftot = [fx1; fx2]; - unex_var(p:p+length(data_js_bin)-1,:) = (data_js_bin - ftot).^2; - - % calculation total variance - tot_var(p:p+length(data_js_bin)-1,:) = (data_js_bin - mean(data_js)).^2; - - p = p+length(data_is_bin); - sp = sp + H(u); - end - - % Calculation of association coefficient h2 - h2(i,j,k) = ((sum(tot_var) - sum(unex_var)) / sum(tot_var))*100; - l=l+1; - end - end -end - -progress('close'); - -% collect the results -if (size(h2, 1) ~= numchannelcmb) - error('number of channel combinations is not right'); -end -if (size(h2, 2) ~= numtimwin) - error('number of timewindows does not match input'); -end -if (size(h2, 3) ~= numdelay) - error('number of delays does not match input'); -end -h2 = reshape(h2, numchannelcmb*numtimwin, numdelay); -[m, indx] = max(h2, [], 2); -h2 = reshape(m, numchannelcmb, numtimwin); -d = (delay(indx)./cfg.fsample)*1000; % convert to miliseconds (to compare with original method) -d = reshape(d, numchannelcmb, numtimwin); - -% FIXME this does not work: one is not supposed to rely on data.cfg.trl, use data.time please! -% association.time = cfg.toi{trllop} + data.cfg.trl(trllop,1); - -association.h2 = h2; -association.delay = d; - -return % from Do_Association_Calculation - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION that computes the mean over all values without checking the dimensions -% this function is approximately 2x faster on 1 dimensional data than the matlab version -function y = mean(x) -y = sum(x(:))./numel(x); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION that bins the elements of Y into equally spaced containers -% this function is approximately 2x faster on 1 dimensional data than the matlab version -function [nn, x] = hist(y, x) -miny = min(y); -maxy = max(y); -binwidth = (maxy - miny) ./ x; -xx = miny:binwidth:maxy; -x = xx(1:(end-1)) + binwidth/2; -% Shift bins so the interval is ( ] instead of [ ). -xx = full(real(xx)); y = full(real(y)); % For compatibility -bins = xx + eps(xx); -nn = histc(y',[-inf bins],1); -% Combine first bin with 2nd bin and last bin with next to last bin -nn(2,:) = nn(2,:)+nn(1,:); -nn(end-1,:) = nn(end-1,:)+nn(end,:); -nn = nn(2:end-1,:); - diff --git a/external/fieldtrip/private/normalisevolume.m b/external/fieldtrip/private/normalisevolume.m deleted file mode 100644 index 42dcd9d..0000000 --- a/external/fieldtrip/private/normalisevolume.m +++ /dev/null @@ -1,22 +0,0 @@ -function [volume] = normalisevolume(cfg, volume) - -% VOLUMENORMALISE normalizes anatomical and functional data -% to a template anatomical MRI -% -% Warning: This function is deprecated, it has been renamed to VOLUMENORMALISE -% Warning: backward compatibility will be removed in the future - -% Copyright (C) 2005-2006, F.C. Donders Centre -% -% $Log: normalisevolume.m,v $ -% Revision 1.15 2007/01/09 09:52:07 roboos -% changed the warning a bit -% -% Revision 1.14 2006/03/14 08:09:22 roboos -% added copyrigth and cvs log statement -% - -warning('This function is deprecated, it has been renamed to VOLUMENORMALISE'); -warning('backward compatibility will be removed in the future'); - -[volume] = volumenormalise(cfg, volume); diff --git a/external/fieldtrip/private/normals.m b/external/fieldtrip/private/normals.m index e8959df..05a0378 100644 --- a/external/fieldtrip/private/normals.m +++ b/external/fieldtrip/private/normals.m @@ -8,19 +8,23 @@ % Copyright (C) 2002-2007, Robert Oostenveld % -% $Log: normals.m,v $ -% Revision 1.5 2008/10/21 09:00:34 roboos -% use local version of "cross" function to speed it up +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.4 2007/07/26 07:13:08 roboos -% shift center of vertices to origin +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.3 2003/03/11 15:35:20 roberto -% converted all files from DOS to UNIX +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.2 2003/03/04 21:46:19 roberto -% added CVS log entry and synchronized all copyright labels +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: normals.m 946 2010-04-21 17:51:16Z roboos $ if nargin<3 opt='vertex'; diff --git a/external/fieldtrip/private/notchfilter.m b/external/fieldtrip/private/notchfilter.m index 75b32eb..3b361e1 100644 --- a/external/fieldtrip/private/notchfilter.m +++ b/external/fieldtrip/private/notchfilter.m @@ -16,28 +16,23 @@ % original (c) 2003, Pascal Fries % modifications (c) 2003, Robert Oostenveld % -% $Log: notchfilter.m,v $ -% Revision 1.6 2007/04/16 16:08:52 roboos -% removed the old code that was commented out already +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.5 2004/01/21 13:04:21 roberto -% changed help and comments +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.4 2003/06/12 08:40:44 roberto -% added variable option to determine filter order -% changed default order from 6 to 4 for notch and bandpass +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.3 2003/04/04 09:53:06 roberto -% played around and tested 3 options, finally implemented 6th -% order Butterworth FIR filter -% -% Revision 1.2 2003/03/28 15:07:57 roberto -% added default for Fl (50 Hz) -% fixed bug with channel iterator in for-loop (i, was also used for complex number) -% -% Revision 1.1 2003/03/27 09:03:40 roberto -% new implementation based on input from pascal and Ole +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: notchfilter.m 952 2010-04-21 18:29:51Z roboos $ if nargin<4 % set the default filter order diff --git a/external/fieldtrip/private/offset2time.m b/external/fieldtrip/private/offset2time.m index e69c968..df5c5d5 100644 --- a/external/fieldtrip/private/offset2time.m +++ b/external/fieldtrip/private/offset2time.m @@ -17,16 +17,23 @@ % Copyright (C) 2005, Robert Oostenveld % -% $Log: offset2time.m,v $ -% Revision 1.2 2009/02/06 10:10:47 roboos -% convert nsamples and offset to double precision +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.1 2008/11/20 13:48:47 roboos -% moved from private to public +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.2 2005/08/05 09:19:00 roboos -% added copyright and cvs log +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: offset2time.m 952 2010-04-21 18:29:51Z roboos $ % ensure that these are not integers offset = double(offset); diff --git a/external/fieldtrip/private/openbdf.m b/external/fieldtrip/private/openbdf.m index ed418d5..97c2dbd 100644 --- a/external/fieldtrip/private/openbdf.m +++ b/external/fieldtrip/private/openbdf.m @@ -9,13 +9,13 @@ % % See also: readedf() -% Copyright (C) 1997-1998 by Alois Schloegl -% a.schloegl@ieee.org -% Ver 2.20 18.Aug.1998 -% Ver 2.21 10.Oct.1998 -% Ver 2.30 5.Nov.1998 +% Copyright (C) 1997-1998 by Alois Schloegl +% a.schloegl@ieee.org +% Ver 2.20 18.Aug.1998 +% Ver 2.21 10.Oct.1998 +% Ver 2.30 5.Nov.1998 % -% For use under Octave define the following function +% For use under Octave define the following function % function s=upper(s); s=toupper(s); end; % V2.12 Warning for missing Header information @@ -41,7 +41,7 @@ function [DAT,H1]=openbdf(FILENAME) -SLASH='/'; % defines Seperator for Subdirectories +SLASH='/'; % defines Seperator for Subdirectories BSLASH=char(92); cname=computer; @@ -49,8 +49,8 @@ fid=fopen(FILENAME,'r','ieee-le'); if fid<0 - fprintf(2,['Error LOADEDF: File ' FILENAME ' not found\n']); - return; + fprintf(2,['Error LOADEDF: File ' FILENAME ' not found\n']); + return; end; EDF.FILE.FID=fid; @@ -62,9 +62,9 @@ EDF.FILE.Ext = FILENAME(PPos+1:length(FILENAME)); EDF.FILE.Name = FILENAME(SPos+1:PPos-1); if SPos==0 - EDF.FILE.Path = pwd; + EDF.FILE.Path = pwd; else - EDF.FILE.Path = FILENAME(1:SPos-1); + EDF.FILE.Path = FILENAME(1:SPos-1); end; EDF.FileName = [EDF.FILE.Path SLASH EDF.FILE.Name '.' EDF.FILE.Ext]; @@ -73,8 +73,8 @@ %if 0 fprintf(2,'LOADEDF: WARNING Version EDF Format %i',ver); end; EDF.PID = deblank(H1(9:88)); % 80 Byte local patient identification EDF.RID = deblank(H1(89:168)); % 80 Byte local recording identification -%EDF.H.StartDate = H1(169:176); % 8 Byte -%EDF.H.StartTime = H1(177:184); % 8 Byte +%EDF.H.StartDate = H1(169:176); % 8 Byte +%EDF.H.StartTime = H1(177:184); % 8 Byte EDF.T0=[str2num(H1(168+[7 8])) str2num(H1(168+[4 5])) str2num(H1(168+[1 2])) str2num(H1(168+[9 10])) str2num(H1(168+[12 13])) str2num(H1(168+[15 16])) ]; % Y2K compatibility until year 2090 @@ -89,19 +89,19 @@ end; EDF.HeadLen = str2num(H1(185:192)); % 8 Byte Length of Header -% reserved = H1(193:236); % 44 Byte +% reserved = H1(193:236); % 44 Byte EDF.NRec = str2num(H1(237:244)); % 8 Byte # of data records EDF.Dur = str2num(H1(245:252)); % 8 Byte # duration of data record in sec EDF.NS = str2num(H1(253:256)); % 8 Byte # of signals -EDF.Label = char(fread(EDF.FILE.FID,[16,EDF.NS],'char')'); -EDF.Transducer = char(fread(EDF.FILE.FID,[80,EDF.NS],'char')'); -EDF.PhysDim = char(fread(EDF.FILE.FID,[8,EDF.NS],'char')'); +EDF.Label = char(fread(EDF.FILE.FID,[16,EDF.NS],'char')'); +EDF.Transducer = char(fread(EDF.FILE.FID,[80,EDF.NS],'char')'); +EDF.PhysDim = char(fread(EDF.FILE.FID,[8,EDF.NS],'char')'); -EDF.PhysMin= str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); -EDF.PhysMax= str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); -EDF.DigMin = str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); % -EDF.DigMax = str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); % +EDF.PhysMin= str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); +EDF.PhysMax= str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); +EDF.DigMin = str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); % +EDF.DigMax = str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); % % check validity of DigMin and DigMax if (length(EDF.DigMin) ~= EDF.NS) @@ -129,9 +129,9 @@ EDF.PhysMin = EDF.DigMin; EDF.PhysMax = EDF.DigMax; end -EDF.PreFilt= char(fread(EDF.FILE.FID,[80,EDF.NS],'char')'); % -tmp = fread(EDF.FILE.FID,[8,EDF.NS],'char')'; % samples per data record -EDF.SPR = str2num(char(tmp)); % samples per data record +EDF.PreFilt= char(fread(EDF.FILE.FID,[80,EDF.NS],'char')'); % +tmp = fread(EDF.FILE.FID,[8,EDF.NS],'char')'; % samples per data record +EDF.SPR = str2num(char(tmp)); % samples per data record fseek(EDF.FILE.FID,32*EDF.NS,0); @@ -159,30 +159,30 @@ EDF.Chan_Select=(EDF.SPR==max(EDF.SPR)); for k=1:EDF.NS - if EDF.Chan_Select(k) - EDF.ChanTyp(k)='N'; - else - EDF.ChanTyp(k)=' '; - end; - if findstr(upper(EDF.Label(k,:)),'ECG') - EDF.ChanTyp(k)='C'; - elseif findstr(upper(EDF.Label(k,:)),'EKG') - EDF.ChanTyp(k)='C'; - elseif findstr(upper(EDF.Label(k,:)),'EEG') - EDF.ChanTyp(k)='E'; - elseif findstr(upper(EDF.Label(k,:)),'EOG') - EDF.ChanTyp(k)='O'; - elseif findstr(upper(EDF.Label(k,:)),'EMG') - EDF.ChanTyp(k)='M'; - end; + if EDF.Chan_Select(k) + EDF.ChanTyp(k)='N'; + else + EDF.ChanTyp(k)=' '; + end; + if findstr(upper(EDF.Label(k,:)),'ECG') + EDF.ChanTyp(k)='C'; + elseif findstr(upper(EDF.Label(k,:)),'EKG') + EDF.ChanTyp(k)='C'; + elseif findstr(upper(EDF.Label(k,:)),'EEG') + EDF.ChanTyp(k)='E'; + elseif findstr(upper(EDF.Label(k,:)),'EOG') + EDF.ChanTyp(k)='O'; + elseif findstr(upper(EDF.Label(k,:)),'EMG') + EDF.ChanTyp(k)='M'; + end; end; -EDF.AS.spb = sum(EDF.SPR); % Samples per Block +EDF.AS.spb = sum(EDF.SPR); % Samples per Block bi=[0;cumsum(EDF.SPR)]; idx=[];idx2=[]; for k=1:EDF.NS, - idx2=[idx2, (k-1)*max(EDF.SPR)+(1:EDF.SPR(k))]; + idx2=[idx2, (k-1)*max(EDF.SPR)+(1:EDF.SPR(k))]; end; maxspr=max(EDF.SPR); idx3=zeros(EDF.NS*maxspr,1); diff --git a/external/fieldtrip/private/openedf.m b/external/fieldtrip/private/openedf.m new file mode 100644 index 0000000..a508639 --- /dev/null +++ b/external/fieldtrip/private/openedf.m @@ -0,0 +1,192 @@ +function [DAT,H1]=openedf(FILENAME) + +% EDF=openedf(FILENAME) +% Opens an EDF File (European Data Format for Biosignals) in MATLAB (R) +% About EDF + +% Copyright (C) 1997-1998 by Alois Schloegl +% a.schloegl@ieee.org +% Ver 2.20 18.Aug.1998 +% Ver 2.21 10.Oct.1998 +% Ver 2.30 5.Nov.1998 +% +% For use under Octave define the following function +% function s=upper(s); s=toupper(s); end; + +% V2.12 Warning for missing Header information +% V2.20 EDF.AS.* changed +% V2.30 EDF.T0 made Y2K compatible until Year 2090 + +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +SLASH='/'; % defines Seperator for Subdirectories +BSLASH=char(92); + +cname=computer; +if cname(1:2)=='PC' SLASH=BSLASH; end; + +fid=fopen(FILENAME,'r','ieee-le'); +if fid<0 + fprintf(2,['Error LOADEDF: File ' FILENAME ' not found\n']); + return; +end; + +EDF.FILE.FID=fid; +EDF.FILE.OPEN = 1; +EDF.FileName = FILENAME; + +PPos=min([max(find(FILENAME=='.')) length(FILENAME)+1]); +SPos=max([0 find((FILENAME=='/') | (FILENAME==BSLASH))]); +EDF.FILE.Ext = FILENAME(PPos+1:length(FILENAME)); +EDF.FILE.Name = FILENAME(SPos+1:PPos-1); +if SPos==0 + EDF.FILE.Path = pwd; +else + EDF.FILE.Path = FILENAME(1:SPos-1); +end; +EDF.FileName = [EDF.FILE.Path SLASH EDF.FILE.Name '.' EDF.FILE.Ext]; + +H1=char(fread(EDF.FILE.FID,256,'char')'); % +EDF.VERSION=H1(1:8); % 8 Byte Versionsnummer +%if 0 fprintf(2,'LOADEDF: WARNING Version EDF Format %i',ver); end; +EDF.PID = deblank(H1(9:88)); % 80 Byte local patient identification +EDF.RID = deblank(H1(89:168)); % 80 Byte local recording identification +%EDF.H.StartDate = H1(169:176); % 8 Byte +%EDF.H.StartTime = H1(177:184); % 8 Byte +EDF.T0=[str2num(H1(168+[7 8])) str2num(H1(168+[4 5])) str2num(H1(168+[1 2])) str2num(H1(168+[9 10])) str2num(H1(168+[12 13])) str2num(H1(168+[15 16])) ]; + +% Y2K compatibility until year 2090 +if EDF.VERSION(1)=='0' + if EDF.T0(1) < 91 + EDF.T0(1)=2000+EDF.T0(1); + else + EDF.T0(1)=1900+EDF.T0(1); + end; +else ; + % in a future version, this is hopefully not needed +end; + +EDF.HeadLen = str2num(H1(185:192)); % 8 Byte Length of Header +% reserved = H1(193:236); % 44 Byte +EDF.NRec = str2num(H1(237:244)); % 8 Byte # of data records +EDF.Dur = str2num(H1(245:252)); % 8 Byte # duration of data record in sec +EDF.NS = str2num(H1(253:256)); % 8 Byte # of signals + +EDF.Label = char(fread(EDF.FILE.FID,[16,EDF.NS],'char')'); +EDF.Transducer = char(fread(EDF.FILE.FID,[80,EDF.NS],'char')'); +EDF.PhysDim = char(fread(EDF.FILE.FID,[8,EDF.NS],'char')'); + +EDF.PhysMin= str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); +EDF.PhysMax= str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); +EDF.DigMin = str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); % +EDF.DigMax = str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); % + +% check validity of DigMin and DigMax +if (length(EDF.DigMin) ~= EDF.NS) + fprintf(2,'Warning OPENEDF: Failing Digital Minimum\n'); + EDF.DigMin = -(2^15)*ones(EDF.NS,1); +end +if (length(EDF.DigMax) ~= EDF.NS) + fprintf(2,'Warning OPENEDF: Failing Digital Maximum\n'); + EDF.DigMax = (2^15-1)*ones(EDF.NS,1); +end +if (any(EDF.DigMin >= EDF.DigMax)) + fprintf(2,'Warning OPENEDF: Digital Minimum larger than Maximum\n'); +end +% check validity of PhysMin and PhysMax +if (length(EDF.PhysMin) ~= EDF.NS) + fprintf(2,'Warning OPENEDF: Failing Physical Minimum\n'); + EDF.PhysMin = EDF.DigMin; +end +if (length(EDF.PhysMax) ~= EDF.NS) + fprintf(2,'Warning OPENEDF: Failing Physical Maximum\n'); + EDF.PhysMax = EDF.DigMax; +end +if (any(EDF.PhysMin >= EDF.PhysMax)) + fprintf(2,'Warning OPENEDF: Physical Minimum larger than Maximum\n'); + EDF.PhysMin = EDF.DigMin; + EDF.PhysMax = EDF.DigMax; +end +EDF.PreFilt= char(fread(EDF.FILE.FID,[80,EDF.NS],'char')'); % +tmp = fread(EDF.FILE.FID,[8,EDF.NS],'char')'; % samples per data record +EDF.SPR = str2num(char(tmp)); % samples per data record + +fseek(EDF.FILE.FID,32*EDF.NS,0); + +EDF.Cal = (EDF.PhysMax-EDF.PhysMin)./ ... + (EDF.DigMax-EDF.DigMin); +EDF.Off = EDF.PhysMin - EDF.Cal .* EDF.DigMin; +tmp = find(EDF.Cal < 0); +EDF.Cal(tmp) = ones(size(tmp)); +EDF.Off(tmp) = zeros(size(tmp)); + +EDF.Calib=[EDF.Off';(diag(EDF.Cal))]; +%EDF.Calib=sparse(diag([1; EDF.Cal])); +%EDF.Calib(1,2:EDF.NS+1)=EDF.Off'; + +EDF.SampleRate = EDF.SPR / EDF.Dur; + +EDF.FILE.POS = ftell(EDF.FILE.FID); +if EDF.NRec == -1 % unknown record size, determine correct NRec + fseek(EDF.FILE.FID, 0, 'eof'); + endpos = ftell(EDF.FILE.FID); + EDF.NRec = floor((endpos - EDF.FILE.POS) / (sum(EDF.SPR) * 2)); + fseek(EDF.FILE.FID, EDF.FILE.POS, 'bof'); + H1(237:244)=sprintf('%-8i',EDF.NRec); % write number of records +end; + +EDF.Chan_Select=(EDF.SPR==max(EDF.SPR)); +for k=1:EDF.NS + if EDF.Chan_Select(k) + EDF.ChanTyp(k)='N'; + else + EDF.ChanTyp(k)=' '; + end; + if findstr(upper(EDF.Label(k,:)),'ECG') + EDF.ChanTyp(k)='C'; + elseif findstr(upper(EDF.Label(k,:)),'EKG') + EDF.ChanTyp(k)='C'; + elseif findstr(upper(EDF.Label(k,:)),'EEG') + EDF.ChanTyp(k)='E'; + elseif findstr(upper(EDF.Label(k,:)),'EOG') + EDF.ChanTyp(k)='O'; + elseif findstr(upper(EDF.Label(k,:)),'EMG') + EDF.ChanTyp(k)='M'; + end; +end; + +EDF.AS.spb = sum(EDF.SPR); % Samples per Block +bi=[0;cumsum(EDF.SPR)]; + +idx=[];idx2=[]; +for k=1:EDF.NS, + idx2=[idx2, (k-1)*max(EDF.SPR)+(1:EDF.SPR(k))]; +end; +maxspr=max(EDF.SPR); +idx3=zeros(EDF.NS*maxspr,1); +for k=1:EDF.NS, idx3(maxspr*(k-1)+(1:maxspr))=bi(k)+ceil((1:maxspr)'/maxspr*EDF.SPR(k));end; + +%EDF.AS.bi=bi; +EDF.AS.IDX2=idx2; +%EDF.AS.IDX3=idx3; + + +DAT.Head=EDF; +DAT.MX.ReRef=1; + +%DAT.MX=feval('loadxcm',EDF); + +return; diff --git a/external/fieldtrip/private/parameterselection.m b/external/fieldtrip/private/parameterselection.m index 1f6c0a5..71a47ce 100644 --- a/external/fieldtrip/private/parameterselection.m +++ b/external/fieldtrip/private/parameterselection.m @@ -13,50 +13,23 @@ % Copyright (C) 2005-2008, Robert oostenveld % -% $Log: parameterselection.m,v $ -% Revision 1.14 2008/07/30 07:41:39 roboos -% also detect parameters in source.trial +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.13 2008/07/25 09:05:02 roboos -% not only check the parameter dimensions against source.dim, but optionally also against source.pos (required if it is an irregular grid) +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.12 2007/07/31 08:36:27 jansch -% added support for volume data with dimensionality > 3 +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.11 2006/10/02 13:54:14 roboos -% replaced predefined list for 'all' by automatic generated list -% -% Revision 1.10 2006/05/16 10:41:13 roboos -% removed trialA/trialB elements, since typically they cannot be dealt with automatically -% -% Revision 1.9 2006/03/30 07:41:15 roboos -% added fields df and dof in case of selecting 'all' -% -% Revision 1.8 2006/03/29 08:25:57 roboos -% Ensure that it is a cell array, also when empty. Remove empty fields (thanks to Vladimir). -% -% Revision 1.7 2006/02/13 07:45:16 jansch -% added paramters such as lbex, leadfield, trialX.xxx so that this function -% can also be used within source2sparse, and source2full -% -% Revision 1.6 2006/02/09 09:43:20 roboos -% added 'leadfield' as a known volume -% -% Revision 1.5 2006/01/05 13:29:36 roboos -% always return a cell-array (this function used to return a string if only -% one parameter was selected and a cell-array if there were multiple) -% -% Revision 1.4 2005/09/29 00:37:57 roboos -% if 'all' is specified, do not replace complete list, but only the 'all' element -% prevent double occurences in parameter list -% -% Revision 1.3 2005/09/12 09:50:46 jansch -% added ref as a parameter -% -% Revision 1.2 2005/08/19 17:26:27 roboos -% added support for 'pow' -> will be replaced by 'avg.pow' (similar for other volumes) -% added help documentation +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: parameterselection.m 952 2010-04-21 18:29:51Z roboos $ if ischar(param) param = {param}; % it should be a cell-array @@ -115,6 +88,25 @@ select{end+1} = param{i}; elseif isfield(data, 'pos') && prod(dim)==size(data.pos, 1) select{end+1} = param{i}; + elseif isfield(data, 'dimord') && (isfield(data, 'pos') || isfield(data, 'transform')), + dimtok = tokenize(data.dimord, '_'); + nels = 1; + for k=1:numel(dimtok) + if strcmp(dimtok{k}, 'rpt') || strcmp(dimtok{k}, 'rpttap') + nels = nels*dim(k); + elseif strcmp(dimtok{k}, 'pos') && isfield(data, 'pos') + %for source structure + nels = nels*size(data.pos,1); + elseif strcmp(dimtok{k}, 'pos') + %for volume structure FIXME 'pos' in dimord is not OK + nels = nels*prod(data.dim(1:3)); + else + nels = nels*numel(getfield(data, dimtok{k})); + end + end + if nels==prod(dim), + select{end+1} = param{i}; + end end end end diff --git a/external/fieldtrip/private/patchsvd.m b/external/fieldtrip/private/patchsvd.m new file mode 100644 index 0000000..b535b30 --- /dev/null +++ b/external/fieldtrip/private/patchsvd.m @@ -0,0 +1,148 @@ +function [grid] = patchsvd(cfg, grid); + +% This function does something +% cf. Limpiti et al IEEE trans biomed eng 2006;53(9);1740-54 + +% Copyright (c) 2006, Jan-Mathijs Schoffelen & Robert Oostenveld, F.C. Donders Centre +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: patchsvd.m 952 2010-04-21 18:29:51Z roboos $ + +% set the defaults +if ~isfield(cfg, 'patchsvd'), cfg.patchsvd = 3; end +if ~isfield(cfg, 'patchsvdnum'), cfg.patchsvdnum = 5; end +if ~isfield(cfg, 'feedback'), cfg.feedback = 'textbar'; end + +if isnumeric(cfg.patchsvd), + Ndipoles = size(grid.pos,1); +else + Ndipoles = 1; +end +Ninside = length(grid.inside); +Nchans = size(grid.leadfield{grid.inside(1)}, 1); +lfall = cell(1,Ndipoles); +coeff = cell(1,Ndipoles); +nghbr = cell(1,Ndipoles); + +if isnumeric(cfg.patchsvd) && ~isfield(grid, 'patchindx'), + fprintf('computing patches in 3D, not taking topology into account\n'); + progress('init', cfg.feedback, 'computing patchsvd'); + for dipindx=1:Ninside + % renumber the loop-index variable to make it easier to print the progress bar + i = grid.inside(dipindx); + + % compute the distance from this dipole to each other dipole + dist = sqrt(sum((grid.pos-repmat(grid.pos(i,:), [Ndipoles 1])).^2, 2)); + + % define the region of interest around this dipole + sel = find(dist<=cfg.patchsvd); + sel = intersect(sel, grid.inside); + Nsel = length(sel); + + progress(dipindx/Ninside, 'computing patchsvd %d/%d, Nsel=%d\n', dipindx, Ninside, Nsel); + % concatenate the leadfield of all dipoles that are inside the ROI into one matrix + lfr = cell2mat(grid.leadfield(sel(:)')); + % svd of leadfields of dipoles inside the ROI + [U,S,V] = svd(lfr); + + if cfg.patchsvdnum < 1, + % Limpiti et al 2006 formula 12 + s = diag(S).^2; + s = cumsum(s)./sum(s); + n(dipindx) = find(s - cfg.patchsvdnum > 0, 1); + else + n(dipindx) = cfg.patchsvdnum; + end + lfall{i} = U(:,1:n(dipindx));%*S(1:n(dipindx),1:n(dipindx)); %klopt dit? + nghbr{i} = sel; + coeff{i} = V(1:n(dipindx), :); + end + progress('close'); +elseif isnumeric(cfg.patchsvd) && isfield(grid, 'patchindx'), + fprintf('computing patches in 2D, taking surface topology into account\n'); + progress('init', cfg.feedback, 'computing patchsvd'); + for dipindx=1:Ninside + % renumber the loop-index variable to make it easier to print the progress bar + i = grid.inside(dipindx); + + % define the region of interest around this dipole + sel = nearest(grid.patchsize(i,:), cfg.patchsvd); + sel = grid.patchindx(i,1:sel); + Nsel = length(sel); + + progress(dipindx/Ninside, 'computing patchsvd %d/%d, Nsel=%d\n', dipindx, Ninside, Nsel); + % concatenate the leadfield of all dipoles that are inside the ROI into one matrix + lfr = cell2mat(grid.leadfield(sel(:)')); + % svd of leadfields of dipoles inside the ROI + [U,S,V] = svd(lfr); + + if cfg.patchsvdnum < 1, + % Limpiti et al 2006 formula 12 + s = diag(S).^2; + s = cumsum(s)./sum(s); + n(dipindx) = find(s - cfg.patchsvdnum > 0, 1); + else + n(dipindx) = min(cfg.patchsvdnum, size(lfr,2)); + end + lfall{i} = U(:,1:n(dipindx));%*S(1:n(dipindx),1:n(dipindx)); %klopt dit? + nghbr{i} = sel; + coeff{i} = V(1:n(dipindx), :); + sv{i} = s; + end + progress('close'); +elseif strcmp(cfg.patchsvd, 'all'), + lfr = cell2mat(grid.leadfield(grid.inside(:)')); + [U,S,V] = svd(lfr); + + if cfg.patchsvdnum < 1, + % Limpiti et al 2006 formula 12 + s = diag(S).^2; + s = cumsum(s)./sum(s); + n = find(s - cfg.patchsvdnum > 0, 1); + else + n = cfg.patchsvdnum; + end + lfall{1} = U(:,1:n);%*S(1:n(dipindx),1:n(dipindx)); %klopt dit? + nghbr{1} = grid.inside; + coeff{1} = V(1:n, :); + + %---change output + grid.pos = mean(grid.pos(grid.inside,:),1); + grid.inside = 1; + grid.dim = [1 1 1]; + grid.xgrid = grid.pos(1); + grid.ygrid = grid.pos(2); + grid.zgrid = grid.pos(3); +else + %do nothing +end + +if ~all(n==n(1)), + nmax = max(n); + for dipindx = 1:Ninside + i = grid.inside(dipindx); + if n(dipindx). +% +% $Id: peakdetect2.m 952 2010-04-21 18:29:51Z roboos $ if nargin<3 mindist=1; diff --git a/external/fieldtrip/private/peakdetect3.m b/external/fieldtrip/private/peakdetect3.m new file mode 100644 index 0000000..519fa5b --- /dev/null +++ b/external/fieldtrip/private/peakdetect3.m @@ -0,0 +1,49 @@ +function [pindx, pval] = peakdetect3(dat, threshold, mindist) + +% PEAKDETECT3 detects peaks above a certain threshold in single-channel data +% +% Use as +% [pindx, pval] = peakdetect3(dat, threshold, mindist) +% +% See also PEAKDETECT, PEAKDETECT2 + +% Copyright (C) 2000-2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: peakdetect3.m 952 2010-04-21 18:29:51Z roboos $ + +% threshold the data +tr = dat>threshold; + +% the derivative of the data changes its sign at the peak +td = diff(dat); +td = td(1:(end-1))>0 & td(2:end)<0; +td = [0 td 0]; + +pindx = find(td & tr); + +if nargin>2 && length(pindx)>0 + % find the peaks that are too close to each other + pd = [inf diff(pindx)]; + pindx = pindx(pd>mindist); +end + +if nargout>1 + pval = dat(pindx); +end + diff --git a/external/fieldtrip/private/planarchannelset.m b/external/fieldtrip/private/planarchannelset.m index 0131f0a..3af8bd6 100644 --- a/external/fieldtrip/private/planarchannelset.m +++ b/external/fieldtrip/private/planarchannelset.m @@ -11,28 +11,23 @@ % Copyright (C) 2005-2008, Robert Oostenveld % -% $Log: planarchannelset.m,v $ -% Revision 1.10 2009/07/29 06:47:55 roboos -% resolved conflict related to simultaneous changes to the neuromag306alt handling +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.9 2009/07/21 11:55:56 roboos -% added support for the alternative neuromag306 channel names, changed channel order for neuromag306 +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.8 2009/03/23 21:12:20 jansch -% added support for bti148_planar +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.7 2008/07/16 10:20:14 jansch -% added support for bti248 system. -% -% Revision 1.6 2008/04/09 14:13:07 roboos -% updated docu -% -% Revision 1.5 2006/10/04 15:42:14 roboos -% renamed megsystem into sensortype, thanks to Juan -% -% Revision 1.4 2006/01/30 14:28:47 roboos -% updated help and copyright +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: planarchannelset.m 1261 2010-06-22 15:09:23Z roboos $ switch lower(senstype(data)) case 'ctf151_planar' @@ -769,8 +764,44 @@ planar{k,2} = ['A',num2str(k),'_dV']; planar{k,3} = ['A',num2str(k)]; end + + case 'itab153_planar' + planar = cell(153,3); + for k = 1:153 + planar{k,1} = sprintf('MAG_%03d_dH', k-1); + planar{k,2} = sprintf('MAG_%03d_dV', k-1); + planar{k,3} = sprintf('MAG_%03d', k-1); + end otherwise - error('unrecognized MEG system'); + + % try to define the horizontal, vertical and combined channel based on the input data + islabel = isa(data, 'cell') && ~isempty(data) && isa(data{1}, 'char'); + if islabel + if any(cellfun(@isempty, regexp(data, '_dV$'))) + % assume that it is a nicely behaving set of planar channel pairs + selH = find(~cellfun(@isempty, regexp(data, '_dH$'))); + selV = find(~cellfun(@isempty, regexp(data, '_dV$'))); + if length(selH) ~= length(selV) + error('inconsistent number of horizontal and vertical planar channels'); + end + for i=1:length(selH) + basename = data{selH(i)}(1:(end-3)); + planar{i,1} = sprintf('%s_dH', basename); + planar{i,2} = sprintf('%s_dV', basename); + planar{i,3} = sprintf('%s', basename); + end + else + % assume that it is a nicely behaving set of non-planar channels + for i=1:length(data) + planar{i,1} = sprintf('%s_dH', data{i}); + planar{i,2} = sprintf('%s_dV', data{i}); + planar{i,3} = sprintf('%s', data{i}); + end + end % if contains _dV + + else % ~islabel + error('unrecognized MEG system'); + end end diff --git a/external/fieldtrip/private/plgndr.m b/external/fieldtrip/private/plgndr.m index 9dde62c..457767c 100644 --- a/external/fieldtrip/private/plgndr.m +++ b/external/fieldtrip/private/plgndr.m @@ -12,19 +12,23 @@ % Copyright (C) 2002, Robert Oostenveld % -% $Log: plgndr.m,v $ -% Revision 1.2 2009/03/12 11:05:03 roboos -% implemented auto-compilation of the mex file in case it is missing +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.1 2009/01/21 10:32:38 roboos -% moved from forwinv/* and forwinv/mex/* directory to forwinv/private/* to make the CVS layout consistent with the release version +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.3 2008/03/05 16:26:18 roboos -% updated documentation +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.2 2003/03/11 14:45:37 roberto -% updated help and copyrights +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: plgndr.m 946 2010-04-21 17:51:16Z roboos $ % compile the missing mex file on the fly % remember the original working directory diff --git a/external/fieldtrip/private/plgndr.mexmaci b/external/fieldtrip/private/plgndr.mexmaci index e359b3b..bef58fe 100755 Binary files a/external/fieldtrip/private/plgndr.mexmaci and b/external/fieldtrip/private/plgndr.mexmaci differ diff --git a/external/fieldtrip/private/plgndr.mexw32 b/external/fieldtrip/private/plgndr.mexw32 index bc57777..f98eae5 100644 Binary files a/external/fieldtrip/private/plgndr.mexw32 and b/external/fieldtrip/private/plgndr.mexw32 differ diff --git a/external/fieldtrip/private/plgndr.mexw64 b/external/fieldtrip/private/plgndr.mexw64 index bdee932..346d9d4 100644 Binary files a/external/fieldtrip/private/plgndr.mexw64 and b/external/fieldtrip/private/plgndr.mexw64 differ diff --git a/external/fieldtrip/private/plinproj.m b/external/fieldtrip/private/plinproj.m new file mode 100644 index 0000000..1a6a153 --- /dev/null +++ b/external/fieldtrip/private/plinproj.m @@ -0,0 +1,72 @@ +function [varargout] = funname(varargin) + +% PLINPROJ projects a point onto a line or linepiece +% +% Use as +% [proj, dist] = plinproj(l1, l2, r, flag) +% where l1 and l2 are the begin and endpoint of the linepiece, and r is +% the point that is projected onto the line +% +% the optional flag can be: +% 0 (default) project the point anywhere on the complete line +% 1 project the point within or on the edge of the linepiece + +% Copyright (C) 2002-2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: plinproj.m 952 2010-04-21 18:29:51Z roboos $ + +% compile the missing mex file on the fly +% remember the original working directory +pwdir = pwd; + +% determine the name and full path of this function +funname = mfilename('fullpath'); +mexsrc = [funname '.c']; +[mexdir, mexname] = fileparts(funname); + +try + % try to compile the mex file on the fly + warning('trying to compile MEX file from %s', mexsrc); + cd(mexdir); + + if ispc + mex -I. -c geometry.c + mex -I. -c plinproj.c ; mex plinproj.c plinproj.obj geometry.obj + else + mex -I. -c geometry.c + mex -I. -c plinproj.c ; mex -o plinproj plinproj.o geometry.o + end + + cd(pwdir); + success = true; + +catch + % compilation failed + disp(lasterr); + error('could not locate MEX file for %s', mexname); + cd(pwdir); + success = false; +end + +if success + % execute the mex file that was juist created + funname = mfilename; + funhandle = str2func(funname); + [varargout{1:nargout}] = funhandle(varargin{:}); +end diff --git a/external/fieldtrip/private/plinproj.mexmaci b/external/fieldtrip/private/plinproj.mexmaci index cfd2f64..308458a 100755 Binary files a/external/fieldtrip/private/plinproj.mexmaci and b/external/fieldtrip/private/plinproj.mexmaci differ diff --git a/external/fieldtrip/private/plinproj.mexw32 b/external/fieldtrip/private/plinproj.mexw32 index e46b389..fc08976 100644 Binary files a/external/fieldtrip/private/plinproj.mexw32 and b/external/fieldtrip/private/plinproj.mexw32 differ diff --git a/external/fieldtrip/private/plinproj.mexw64 b/external/fieldtrip/private/plinproj.mexw64 index 9810956..06e1eeb 100644 Binary files a/external/fieldtrip/private/plinproj.mexw64 and b/external/fieldtrip/private/plinproj.mexw64 differ diff --git a/external/fieldtrip/private/plotSelection.m b/external/fieldtrip/private/plotSelection.m deleted file mode 100644 index 8f19fe8..0000000 --- a/external/fieldtrip/private/plotSelection.m +++ /dev/null @@ -1,477 +0,0 @@ -function plotSelection(userData, buttonState) - -% PLOTSELECTION is the callback function for interactive ER or TFR plots. -% The function can be called by one of the following functions: -% multiplotER, multiplotTFR, singleplotER, singleplotTFR, and topoplot. -% -% This function is only to be used as a callback function, i.e. you should -% not call it directly. -% -% This function updates the selected areas in the plot, and produces a new -% interactive plot when a selected area is clicked. Multiple areas can be -% selected by holding down the SHIFT key. The newly produced plot is the -% outcome of a statistical function applied to the selected region(s), -% based on the calling plot type (multi, single, or topo). The statistical -% functions used by default are: -% for multiplots : mean of selected channels -% for singleplots : none -% for topoplots : none -% -% userData is a structure array linked to the 'UserData' property of the -% figure that contains the interactive ER/TFR plot. It contains the -% following fields: -% hFigure = figure handle -% hAxes = axes handle of the ER/TFR plot -% hSelection{:} = cell array of line handles of selection rectangles -% iSelection = cell array element index of current selection -% rectangle -% selecting = value specifying the current selecting status: -% 0: not selecting -% 1: starting a new selection (mouse button just -% pressed) -% 2: continuing current selection (dragging -% rectangle) -% selectionType = string specifying whether to extend current -% selection (when SHIFT key is held down), or to start -% a new selection (otherwise). -% selectAxes = string specifying which axes to select; any -% combination of x,y,z. For example, 'xy' means the -% user can select a range on the x- and y-axes. -% lastClick = mouse pointer coordinates at the latest button down -% event -% cfg = copy of configuration used for the plotting -% data = copy of data structure used for the plotting -% chanX,chanY = [only used by multiplot routines] x,y-coordinates of -% the plotted channels (centre coordinates) -% chanLabels = [only used by multiplot routines] label names of the -% plotted channels -% -% buttonState can be one of the following values: -% 0: button is not going up or down (it may be HELD down, though) -% 1: button is going down -% 2: button is going up -% - -% Undocumented local options: -% cfg.channelname -% cfg.interactive -% cfg.layout -% cfg.maplimits -% cfg.xlim -% cfg.xparam -% cfg.ylim -% cfg.yparam -% cfg.zlim - -% Copyright (C) 2006, Dennis Pasveer -% -% $Log: plotSelection.m,v $ -% Revision 1.20 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.19 2008/09/22 14:23:25 roboos -% fixed some lint warnings, i.e. no functional change, only efficiency -% -% Revision 1.18 2007/10/01 07:37:54 roboos -% copy cfg.rotate along in the new_cfg, for subsequent topoplots (thanks to Vladimir) -% -% Revision 1.17 2007/09/25 11:30:10 ingnie -% set cfg.baseline = 'no' to prevent multiple calls to baseline correction in interactive plotting -% -% Revision 1.16 2007/07/02 13:42:35 roboos -% only pass cfg.maskparameter on to next function if present -% -% Revision 1.15 2007/06/19 13:59:00 ingnie -% give cfg.maskparameter along in new_cfg -% -% Revision 1.14 2007/06/05 15:05:12 ingnie -% removed dimord repl_chan_time, added dimord rpt_chan_time -% -% Revision 1.13 2007/04/19 10:56:16 roboos -% pass the cfg.interpolation option along to subsequent interactive plots -% -% Revision 1.12 2007/03/14 11:21:29 chrhes -% fixed same bug as in previous revision but on line 252 -% -% Revision 1.11 2007/03/14 11:09:25 chrhes -% fixed a small bug to do with copying a possibly nonexistent field 'layout' -% from the userData.cfg structure to new_cfg (on line 222) -% -% Revision 1.10 2007/01/09 11:12:38 roboos -% pass cfg.renderer on to new_cfg for next plot function -% -% Revision 1.9 2007/01/09 10:41:43 roboos -% Added the option cfg.renderer, default is opengl. Interactive plotting -% on linux/VNC sometimes does not work, using cfg.renderer='painters' -% seems to fix it. -% -% Revision 1.8 2006/07/27 16:11:19 roboos -% also recognise timelocked data with keeptrials -% pass the xparam,zparam and layout along to the next plot in case of interactive -% -% Revision 1.7 2006/06/06 16:24:06 ingnie -% replaced cfg.channelindex and cfg.channelname with cfg.channel for consistency -% with other functions -% -% Revision 1.6 2006/05/30 20:57:15 roboos -% updated documentation -% -% Revision 1.5 2006/04/27 16:01:30 ingnie -% added dimord subj_chan_time -% -% Revision 1.4 2006/04/20 09:58:34 roboos -% updated documentation -% -% Revision 1.3 2006/03/22 16:22:34 jansch -% implemented the possibility to take cohspctrm from a multiplot to a singleplot -% -% Revision 1.2 2006/03/13 14:09:28 denpas -% Added semicolon to prevent display of new_cfg assignment. -% -% Revision 1.1 2006/03/03 10:03:43 roboos -% moved plotSelection from private into FT main, since a figure callback -% to a private does not work -% -% Revision 1.3 2006/03/02 12:39:55 jansch -% fixed typo -% -% Revision 1.2 2006/03/02 10:51:39 jansch -% corrected updating of xlim and ylim when creating topoplotTFR from singleplotTFR -% -% Revision 1.1 2006/02/27 15:03:47 denpas -% new function, is used as callback function for interactive plotting in multi-, single- and topoplot -% - -fieldtripdefs - -% Get cursor coordinates [x y]: -p = get(userData.hAxes, 'CurrentPoint'); -p = p(1,1:2); - -% Get physical axes limits: -xLim = get(userData.hAxes, 'XLim'); -yLim = get(userData.hAxes, 'YLim'); - -% Update pointer: -if ~userData.selecting - if buttonState==0 - % Mouse pointer becomes normal when outside plot boundaries, or when in selected area (=clickable): - if (p(1) < xLim(1)) || (p(1) > xLim(2)) || (p(2) < yLim(1)) || (p(2) > yLim(2)) || inSelection(p, userData.range) - set(userData.hFigure, 'Pointer', 'default'); - else - set(userData.hFigure, 'Pointer', 'crosshair'); - end - end -else - % While selecting, mouse pointer is always crosshair: - set(userData.hFigure, 'Pointer', 'crosshair'); -end - -% Button down starts a selection: -if buttonState==1 - % Check cursor coordinates: - if (p(1) < xLim(1)) || (p(1) > xLim(2)) || (p(2) < yLim(1)) || (p(2) > yLim(2)) - return; - end - - if strcmp(userData.selectAxes, 'x') - p(2) = yLim(1); - end - - % Starting new selection rectangle: - userData.selecting = 1; - - % Keep button down coordinates and selection type: - userData.lastClick = p; - userData.selectionType = get(userData.hFigure, 'SelectionType'); - - % Update figure's UserData: - set(userData.hFigure, 'UserData', userData); - -elseif userData.selecting - % Distinguish between clicking and dragging: - clicked = sum(p == userData.lastClick) == 2; - if strcmp(userData.selectAxes, 'x') - clicked = p(1) == userData.lastClick(1); - end - - % Limit cursor coordinates: - if p(1)xLim(2), p(1)=xLim(2); end; - if p(2)yLim(2), p(2)=yLim(2); end; - - if strcmp(userData.selectAxes, 'xy') - % Determine selected x,y-range: - if size(userData.range{1}, 2) == 4 - set(userData.hFigure, 'Name', sprintf('%0s=[%.3g %.3g]/%0s=[%.3g %.3g]', userData.cfg.xparam, min(userData.range{1}([1 3])), max(userData.range{1}([1 3])), userData.cfg.yparam, min(userData.range{1}([2 4])), max(userData.range{1}([2 4])))); - end - elseif strcmp(userData.selectAxes, 'z') - % Determine selected channels: - selChannels = []; - for k=1:length(userData.chanLabels) - if ~isempty(userData.chanLabels{k}) - if inSelection([userData.chanX(k) userData.chanY(k)], userData.range) - selChannels = [selChannels k]; - end - end - end - - % Update window caption: - set(userData.hFigure, 'Name', sprintf('%.0f channels selected', length(selChannels))); - elseif strcmp(userData.selectAxes, 'x') - % Determine selected x-range: - if size(userData.range{1}, 2) == 4 - set(userData.hFigure, 'Name', sprintf('%0s=[%.3g %.3g]', userData.cfg.xparam, min(userData.range{1}([1 3])), max(userData.range{1}([1 3])))); - end - - % Set y to the vertical limit: - p(2) = yLim(2); - end - - % Launch a new figure if a selected area has been clicked: - if (buttonState == 2) ... - && (userData.selecting == 1) ... - && (clicked) ... - && (inSelection(p, userData.range)) - - % Button has been released, so stop selecting: - userData.selecting = 0; - - % Update figure's UserData: - set(userData.hFigure, 'UserData', userData); - - % Check data dimord for ERP data: - dimord = getDimord(userData); - if strcmp(dimord, 'chan_time') || strcmp(dimord, 'chan_freq') || strcmp(dimord, 'subj_chan_time') || strcmp(dimord, 'rpt_chan_time') - if strcmp(userData.selectAxes, 'z') - if ~isempty(selChannels) - % Launch ER singleplot figure: - new_cfg = []; - if isfield(userData.cfg, 'layout') - new_cfg.layout = userData.cfg.layout; - end - if isfield(userData.cfg, 'rotate') - new_cfg.rotate = userData.cfg.rotate; - end - if isfield(userData.cfg, 'interpolation') - new_cfg.interpolation = userData.cfg.interpolation; - end - if isfield(userData.cfg, 'maskparameter') - new_cfg.maskparameter = userData.cfg.maskparameter; - end - new_cfg.xparam = userData.cfg.xparam; - new_cfg.zparam = userData.cfg.zparam; - new_cfg.interactive = 'yes'; - new_cfg.xlim = userData.cfg.xlim; - new_cfg.ylim = userData.cfg.ylim; - new_cfg.renderer = userData.cfg.renderer; - new_cfg.baseline = 'no'; %to prevent baseline correction to take place multiple times - - % Set xlim to 'maxmin' when going from topoplot to singleplot: - if strcmp(userData.plotType, 'topoplot') - new_cfg.xlim = 'maxmin'; - end - - new_cfg.channel = userData.chanLabels(selChannels); - - figure; - copyPosition(userData.hFigure); - - if iscell(userData.data) - singleplotER(new_cfg, userData.data{:}); - else - singleplotER(new_cfg, userData.data); - end - end - else - % Configure ER topoplot figure: - new_cfg = []; - if isfield(userData.cfg, 'layout') - new_cfg.layout = userData.cfg.layout; - end - if isfield(userData.cfg, 'rotate') - new_cfg.rotate = userData.cfg.rotate; - end - if isfield(userData.cfg, 'interpolation') - new_cfg.interpolation = userData.cfg.interpolation; - end - new_cfg.xparam = userData.cfg.xparam; - new_cfg.zparam = userData.cfg.zparam; - new_cfg.interactive = 'yes'; - new_cfg.maplimits = 'maxmin'; - new_cfg.ylim = userData.cfg.ylim; - new_cfg.renderer = userData.cfg.renderer; - new_cfg.baseline = 'no'; %to prevent baseline correction to take place multiple times - - % Calculate xlim: - new_cfg.xlim = sort(userData.range{1}([1 3])); - - % Produce topoplot: - figure; - copyPosition(userData.hFigure); - - if iscell(userData.data) - topoplotER(new_cfg, userData.data{:}); - else - topoplotER(new_cfg, userData.data); - end - end - - % Check data dimord for TFR data: - elseif strcmp(dimord, 'chan_freq_time') - if strcmp(userData.selectAxes, 'z') - if ~isempty(selChannels) - % Launch TFR singleplot figure: - new_cfg = userData.cfg; - new_cfg.xlim = userData.cfg.xlim; - new_cfg.ylim = userData.cfg.ylim; - new_cfg.zlim = userData.cfg.zlim; - new_cfg.baseline = 'no'; %to prevent baseline correction to take place multiple times - - % Set xlim and ylim to 'maxmin' when going from topoplot to singleplot: - if strcmp(userData.plotType, 'topoplot') - new_cfg.xlim = 'maxmin'; - new_cfg.ylim = 'maxmin'; - end - - % Get channel names of selected channels: - new_cfg.channel = userData.chanLabels(selChannels); - - figure; - copyPosition(userData.hFigure); - singleplotTFR(new_cfg, userData.data); - end - else - % Launch TFR topoplot figure: - new_cfg = userData.cfg; - new_cfg.maplimits = 'maxmin'; - new_cfg.xlim = userData.data.time([ ... - nearest(userData.data.time, min((userData.range{1}([1 3])))) ... - nearest(userData.data.time, max((userData.range{1}([1 3])))) ... - ]); - new_cfg.ylim = userData.data.freq([ ... - nearest(userData.data.freq, min((userData.range{1}([2 4])))) ... - nearest(userData.data.freq, max((userData.range{1}([2 4])))) ... - ]); - new_cfg.baseline = 'no'; %to prevent baseline correction to take place multiple times - - % Produce topoplot: - figure; - copyPosition(userData.hFigure); - topoplotTFR(new_cfg, userData.data); - end - - % Check data dimord for FREQ data: - elseif (isfield(userData.cfg, 'xparam') && strcmp(userData.cfg.yparam, 'freq')) - - - else - userData.cfg - error('Unable to produce figure: unidentified data.dimord value.'); - end - - return; - end - - % If starting new selection rectangle, determine rectangle index: - if userData.selecting ~= 2 - if strcmp(userData.selectionType, 'normal') - % If previous selection was finished, clear selection: - for i=1:length(userData.hSelection) - set(userData.hSelection{i}, 'Visible', 'off'); - userData.range{i} = []; - end - - % Update window caption for empty selection: - if strcmp(userData.selectAxes, 'xy') - set(userData.hFigure, 'Name', 'No selection'); - elseif strcmp(userData.selectAxes, 'z') - set(userData.hFigure, 'Name', '0 channels selected'); - elseif strcmp(userData.selectAxes, 'x') - set(userData.hFigure, 'Name', 'No selection'); - end - - userData.iSelection = 1; - else - % Proceed to next selection rectangle: - userData.iSelection = userData.iSelection + 1; - if userData.iSelection > length(userData.hSelection) - userData.iSelection = 1; - end - end - - % Set first corner coordinates: - userData.range{userData.iSelection} = userData.lastClick; - - % We're now selecting: - userData.selecting = 2; - end - - % Set rectangle range: - userData.range{userData.iSelection} = [userData.range{userData.iSelection}([1 2]) p]; - - % Keep rectangle coordinates: - xData = userData.range{userData.iSelection}([1 3 3 1 1]); - yData = userData.range{userData.iSelection}([2 2 4 4 2]); - - % Plot selection rectangle: - set(userData.hSelection{userData.iSelection}, 'XData', xData); - set(userData.hSelection{userData.iSelection}, 'YData', yData); - set(userData.hSelection{userData.iSelection}, 'Color', [0 0 0]); - set(userData.hSelection{userData.iSelection}, 'EraseMode', 'xor'); - set(userData.hSelection{userData.iSelection}, 'LineStyle', '--'); - set(userData.hSelection{userData.iSelection}, 'LineWidth', 1.5); - set(userData.hSelection{userData.iSelection}, 'Visible', 'on'); - - % On buttonUp, the selection rectangle is done: - if buttonState == 2 - userData.selecting = 0; - end - - % Update figure's UserData: - set(userData.hFigure, 'UserData', userData); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function a = inSelection(aPoint, selectionRanges) -% Function returns selection rectangle index number of the rectangle of a -% certain coordinate. - -a = 0; -for i=1:length(selectionRanges) - % Look only in complete selections (containing 4 elemens [left top right bottom]): - if (length(selectionRanges{i}) == 4) ... - && (aPoint(:,1) >= min(selectionRanges{i}([1 3]))) ... - && (aPoint(:,1) <= max(selectionRanges{i}([1 3]))) ... - && (aPoint(:,2) >= min(selectionRanges{i}([2 4]))) ... - && (aPoint(:,2) <= max(selectionRanges{i}([2 4]))) - a = i; - return; - end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function copyPosition(hFigure) -% This function copies the window position from a given figure to the -% current figure. - -set(gcf, 'position', get(hFigure, 'position')); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function dimord = getDimord(userData) -% This function reads the dimord value from the userData.data structure. -% Since userData.data may be a cell array of multiple data sets, this -% function first detects the data type. - -if iscell(userData.data) - dimord = userData.data{1}.dimord; -else - dimord = userData.data.dimord; -end diff --git a/external/fieldtrip/private/plot_box.m b/external/fieldtrip/private/plot_box.m deleted file mode 100644 index bedb1af..0000000 --- a/external/fieldtrip/private/plot_box.m +++ /dev/null @@ -1,127 +0,0 @@ -function [varargout] = plot_box(position, varargin); - -% PLOT_BOX plots the outline of a box that is specified by its lower -% left and upper right corner -% -% Use as -% plot_box(position, ...) -% where the position of the box is specified as is [x1, x2, y1, y2]. -% Optional arguments should come in key-value pairs and can include -% 'facealpha' = transparency value between 0 and 1 -% 'facecolor' = color specification as [r g b] values or a string, for example 'brain', 'cortex', 'skin', 'red', 'r' -% 'edgecolor' = color specification as [r g b] values or a string, for example 'brain', 'cortex', 'skin', 'red', 'r' -% 'hpos' = -% 'vpos' = -% 'width' = -% 'height' = -% 'hlim' = -% 'vlim' = -% -% Example -% plot_box([-1 1 2 3], 'facecolor', 'b') -% axis([-4 4 -4 4]) - -% Copyrights (C) 2009, Robert Oostenveld -% -% $Log: plot_box.m,v $ -% Revision 1.6 2009/07/14 16:13:14 roboos -% speed up the plotting if no rescaling needs to be done -% -% Revision 1.5 2009/06/04 08:48:23 roboos -% updated documentation -% -% Revision 1.4 2009/06/02 15:38:50 giopia -% added varargout to pass the handle -% -% Revision 1.3 2009/04/14 19:48:28 roboos -% added keyvalcheck -% -% Revision 1.2 2009/04/14 14:31:08 roboos -% many small changes to make it fully functional -% - -% get the optional input arguments -keyvalcheck(varargin, 'optional', {'hpos', 'vpos', 'width', 'height', 'hlim', 'vlim', 'facealpha', 'facecolor', 'edgecolor'}); -hpos = keyval('hpos', varargin); -vpos = keyval('vpos', varargin); -width = keyval('width', varargin); -height = keyval('height', varargin); -hlim = keyval('hlim', varargin); -vlim = keyval('vlim', varargin); -facealpha = keyval('facealpha', varargin); if isempty(facealpha), facealpha = 1; end -facecolor = keyval('facecolor', varargin); if isempty(facecolor), facecolor = 'none'; end -edgecolor = keyval('edgecolor', varargin); if isempty(edgecolor), edgecolor = 'k'; end - -% convert the two cornerpoints into something that the patch function understands -% the box position is represented just like the argument to the AXIS function -x1 = position(1); -x2 = position(2); -y1 = position(3); -y2 = position(4); -X = [x1 x2 x2 x1 x1]; -Y = [y1 y1 y2 y2 y1]; - -if isempty(hlim) && isempty(vlim) && isempty(hpos) && isempty(vpos) && isempty(height) && isempty(width) - % no scaling is needed, the input X and Y are already fine - % use a shortcut to speed up the plotting - -else - % use the full implementation - abc = axis; - - if isempty(hlim) - hlim = abc([1 2]); - end - - if isempty(vlim) - vlim = abc([3 4]); - end - - if isempty(hpos); - hpos = (hlim(1)+hlim(2))/2; - end - - if isempty(vpos); - vpos = (vlim(1)+vlim(2))/2; - end - - if isempty(width), - width = hlim(2)-hlim(1); - end - - if isempty(height), - height = vlim(2)-vlim(1); - end - - % first shift the horizontal axis to zero - X = X - (hlim(1)+hlim(2))/2; - % then scale to length 1 - X = X ./ (hlim(2)-hlim(1)); - % then scale to the new width - X = X .* width; - % then shift to the new horizontal position - X = X + hpos; - - % first shift the vertical axis to zero - Y = Y - (vlim(1)+vlim(2))/2; - % then scale to length 1 - Y = Y ./ (vlim(2)-vlim(1)); - % then scale to the new width - Y = Y .* height; - % then shift to the new vertical position - Y = Y + vpos; - -end % shortcut - -% use an arbitrary color, which will be replaced by the correct color a few lines down -C = 0; - -h = patch(X, Y, C); -set(h, 'FaceAlpha', facealpha) -set(h, 'FaceColor', facecolor) -set(h, 'EdgeColor', edgecolor) - -% the (optional) output is the handle -if nargout == 1 - varargout{1} = h; -end diff --git a/external/fieldtrip/private/plot_dipole.m b/external/fieldtrip/private/plot_dipole.m deleted file mode 100644 index 06f5fa3..0000000 --- a/external/fieldtrip/private/plot_dipole.m +++ /dev/null @@ -1,156 +0,0 @@ -function plot_dipole(pos, ori, varargin) - -% PLOT_DIPOLE makes a 3-D representation of a dipole using a small sphere -% and a stick pointing along the dipole orientation -% -% Use as -% plot_dipole(pos, mom, ...) -% where pos and mom are the dipole mosition and moment. Optional -% input arguments should be specified in key-value pairs and can -% include -% 'diameter' number indicating sphere diameter (default = 'auto') -% 'length' number indicating length of the stick (default = 'auto') -% 'color' [r g b] values or string, for example 'brain', 'cortex', 'skin', 'black', 'red', 'r' -% 'units' 'm', 'cm' or 'mm', used for automatic scaling (default = 'cm') -% 'scale' scale the dipole with the amplitude, can be 'none', 'both', 'diameter', 'length' (default = 'none') -% -% Example -% plot_dipole([0 0 0], [1 2 3]) - -% Copyright (C) 2009, Robert Oostenveld -% -% $Log: plot_dipole.m,v $ -% Revision 1.5 2009/10/07 12:51:22 roboos -% fixed typo in help -% -% Revision 1.4 2009/09/23 14:55:36 crimic -% small fix -% -% Revision 1.3 2009/06/03 16:13:19 roboos -% updated documentation -% -% Revision 1.2 2009/06/03 09:53:18 roboos -% number of small changes, still work in progress -% -% Revision 1.1 2009/06/03 07:53:27 roboos -% first version -% - -% get the optional input arguments -units = keyval('units', varargin); if isempty(units), units = 'cm'; end -color = keyval('color', varargin); if isempty(color), color = [1 0 0]; end -diameter = keyval('diameter', varargin); if isempty(diameter), diameter = 'auto'; end -length = keyval('length', varargin); if isempty(length), length = 'auto'; end -amplitudescale = keyval('scale', varargin); if isempty(amplitudescale), amplitudescale = 'none'; end - -if isequal(diameter, 'auto') - % the default is a 5 mm sphere - switch units - case 'm' - diameter = 0.005; - case 'cm' - diameter = 0.5; - case 'mm' - diameter = 5; - otherwise - error('unsupported units'); - end -end - -if isequal(length, 'auto') - % the default is a 15 mm stick - switch units - case 'm' - length = 0.015; - case 'cm' - length = 1.5; - case 'mm' - length = 15; - otherwise - error('unsupported units'); - end -end - -% dipole position should be Nx3 -if all(size(pos) == [3 1]) - pos = pos'; -end - -% dipole moment and orientation should be 3xN -if all(size(ori) == [1 3]) - ori = ori'; -end - -% everything is added to the current figure -holdflag = ishold; -hold on - -for i=1:size(pos,1) - amplitude = norm(ori(:,i)); - ori(:,i) = ori(:,i) ./ amplitude; - - % scale the dipole diameter and length with its amplitude - if strcmp(amplitudescale, 'length') || strcmp(amplitudescale, 'both') - this_length = length*amplitude; - else - this_length = length; - end - if strcmp(amplitudescale, 'diameter') || strcmp(amplitudescale, 'both') - this_diameter = diameter*amplitude; - else - this_diameter = diameter; - end - - % create a unit sphere and cylinder - [sphere.pnt, sphere.tri] = icosahedron642; - sphere.pnt = warp_apply(scale([0.5 0.5 0.5]), sphere.pnt, 'homogeneous'); % the diameter should be 1 - [stick.pnt, stick.tri] = cylinder(36, 2); - stick.pnt = warp_apply(scale([0.5 0.5 0.5]), stick.pnt, 'homogeneous'); % the length should be 1 - stick.pnt = warp_apply(translate([0 0 0.5]), stick.pnt, 'homogeneous'); % it should start in the origin - - % scale the sphere - sx = this_diameter; - sy = this_diameter; - sz = this_diameter; - sphere.pnt = warp_apply(scale([sx sy sz]), sphere.pnt, 'homogeneous'); - - % translate the sphere - tx = pos(i,1); - ty = pos(i,2); - tz = pos(i,3); - sphere.pnt = warp_apply(translate([tx ty tz]), sphere.pnt, 'homogeneous'); - - % scale the stick - sx = this_diameter/3; - sy = this_diameter/3; - sz = this_length; - stick.pnt = warp_apply(scale([sx sy sz]), stick.pnt, 'homogeneous'); - - % first rotate the stick to point along the x-axis - stick.pnt = warp_apply(rotate([0 90 0]), stick.pnt, 'homogeneous'); - % then rotate the stick in the desired direction - [az, el] = cart2sph(ori(1,i), ori(2,i), ori(3,i)); - stick.pnt = warp_apply(rotate([0 -el*180/pi 0]), stick.pnt, 'homogeneous'); % rotate around y-axis - stick.pnt = warp_apply(rotate([0 0 az*180/pi]), stick.pnt, 'homogeneous'); % rotate around z-axis - - % translate the stick - tx = pos(i,1); - ty = pos(i,2); - tz = pos(i,3); - stick.pnt = warp_apply(translate([tx ty tz]), stick.pnt, 'homogeneous'); - - % plot the sphere and the stick - plot_mesh(sphere, 'vertexcolor', 'none', 'edgecolor', false, 'facecolor', color); - plot_mesh(stick, 'vertexcolor', 'none', 'edgecolor', false, 'facecolor', color); - -end % for each dipole - -axis off -axis vis3d -axis equal -camlight % fixme, this probably should be in the calling function - -if ~holdflag - hold off -end - diff --git a/external/fieldtrip/private/plot_headshape.m b/external/fieldtrip/private/plot_headshape.m deleted file mode 100644 index 3a910f9..0000000 --- a/external/fieldtrip/private/plot_headshape.m +++ /dev/null @@ -1,91 +0,0 @@ -function hs = plot_headshape(headshape,varargin) - -% PLOT_HEADSHAPE visualizes the shape of a head generated from a variety of files -% (like CTF and Polhemus). The headshape and fiducials can for example be used for coregistration. -% -% Use as -% hs = plot_headshape(shape, varargin) -% -% Graphic facilities are available for vertices and fiducials (Nasion, Left, Right ...). A list of -% the arguments is given below with the correspondent admitted choices. -% -% 'vertexcolor' ['brain', 'cortex', 'skin', 'black', 'red', 'r', ..., [0.5 1 0], ...] -% 'fidcolor' ['brain', 'cortex', 'skin', 'black', 'red', 'r', ..., [0.5 1 0], ...] -% 'fidmarker' ['.', '*', '+', ...] -% 'fidlabel' ['yes', 'no', 1, 0, 'true', 'false'] -% 'transform' transformation matrix for the fiducials, converts MRI -% voxels into head shape coordinates -% -% Example -% [shape] = read_headshape(filename); -% plot_headshape(shape) - -% Copyright (C) 2009, Cristiano Micheli -% -% $Log: plot_headshape.m,v $ -% Revision 1.7 2009/04/21 14:14:22 crimic -% fixed label plotting -% -% Revision 1.6 2009/04/21 14:09:16 crimic -% fixed fiducials plotting, added check on voxel to head coordinates -% -% Revision 1.5 2009/04/14 19:49:18 roboos -% fixed the input argument parsing (incorrect keys were used) -% -% Revision 1.4 2009/04/14 10:19:16 crimic -% updated help -% -% Revision 1.3 2009/04/14 10:16:09 crimic -% updated help -% -% Revision 1.2 2009/04/14 08:57:57 crimic -% added labeling of fiducials, integrated help -% - -% get the optional input arguments -vertexcolor = keyval('vertexcolor', varargin); if isempty(vertexcolor), vertexcolor='r'; end -fidcolor = keyval('fidcolor', varargin); if isempty(fidcolor), fidcolor='g'; end -fidmarker = keyval('fidmarker', varargin); if isempty(fidmarker), fidmarker='.'; end -fidlabel = keyval('fidlabel', varargin); if isempty(fidlabel), fidlabel='no'; end -transform = keyval('transform', varargin); if isempty(transform), transform=[]; end - -% start with empty return values -hs = []; - -% everything is added to the current figure -holdflag = ishold; -hold on - -pnt = headshape.pnt; -bnd.pnt = pnt; -bnd.tri = []; - -hs = plot_mesh(bnd, 'vertices', 'yes', 'vertexcolor',vertexcolor,'vertexsize',10); - -if isfield(headshape, 'fid') - fid = headshape.fid; - if ~isempty(transform) - % plot the fiducials - fidc = fid.pnt; - try - fidc = warp_apply(transform, fidc); - end - hs = plot3(fidc(:,1), fidc(:,2), fidc(:,3), 'Marker',fidmarker,'MarkerEdgeColor',fidcolor); - % show the fiducial labels - if isfield(fid,'label') && istrue(fidlabel) - for node_indx=1:size(fidc,1) - str = sprintf('%s', fid.label{node_indx}); - h = text(fidc(node_indx, 1), fidc(node_indx, 2), fidc(node_indx, 3), str, ... - 'HorizontalAlignment', 'center', 'VerticalAlignment', 'middle','Interpreter','none'); - hs = [hs; h]; - end - end - end - -end -if nargout==0 - clear hs -end -if ~holdflag - hold off -end diff --git a/external/fieldtrip/private/plot_lay.m b/external/fieldtrip/private/plot_lay.m deleted file mode 100644 index 5e058fb..0000000 --- a/external/fieldtrip/private/plot_lay.m +++ /dev/null @@ -1,101 +0,0 @@ -function plot_lay(lay, varargin) - -% PLOT_LAY plots a two-dimensional layout -% -% Use as -% plot_lay(layout, ...) -% where the layout is a FieldTrip structure obtained from PREPARE_LAYOUT. -% -% Additional options should be specified in key-value pairs and can be -% 'point' = yes/no -% 'box' = yes/no -% 'label' = yes/no -% 'mask' = yes/no -% 'outline' = yes/no - -% Copyright (C) 2009, Robert Oostenveld -% -% $Log: plot_lay.m,v $ -% Revision 1.3 2009/06/02 15:46:37 giopia -% added vpos and hpos for position and verbose to control fprintf -% -% Revision 1.2 2009/05/12 12:34:27 roboos -% updated docuemntation -% -% Revision 1.1 2009/05/12 12:30:19 roboos -% first version, used by Chris for interactive cohrefchan picking -% - -point = keyval('point', varargin{:}); if isempty(point), point = true; end -box = keyval('box', varargin{:}); if isempty(box), box = true; end -label = keyval('label', varargin{:}); if isempty(label), label = true; end -mask = keyval('mask', varargin{:}); if isempty(mask), mask = true; end -outline = keyval('outline', varargin{:}); if isempty(outline), outline = true; end -hpos = keyval('hpos', varargin{:}); if isempty(hpos), hpos = 0; end -vpos = keyval('vpos', varargin{:}); if isempty(vpos), vpos = 0; end -verbose = keyval('verbose', varargin{:}); if isempty(verbose), verbose = true; end - -% everything is added to the current figure -holdflag = ishold; -hold on - -X = lay.pos(:,1) + hpos; -Y = lay.pos(:,2) + vpos; -Width = lay.width; -Height = lay.height; -Lbl = lay.label; - -if point - plot(X, Y, 'b.'); - plot(X, Y, 'yo'); -end - -if label - text(X, Y, Lbl); -end - -if box - line([X-Width/2 X+Width/2 X+Width/2 X-Width/2 X-Width/2]',[Y-Height/2 Y-Height/2 Y+Height/2 Y+Height/2 Y-Height/2]'); -end - -if outline && isfield(lay, 'outline') - if verbose - fprintf('solid lines indicate the outline, e.g. head shape or sulci\n'); - end - for i=1:length(lay.outline) - if ~isempty(lay.outline{i}) - X = lay.outline{i}(:,1) + hpos; - Y = lay.outline{i}(:,2) + vpos; - h = line(X, Y); - set(h, 'color', 'k'); - set(h, 'linewidth', 2); - end - end -end - -if mask && isfield(lay, 'mask') - if verbose - fprintf('dashed lines indicate the mask for topograpic interpolation\n'); - end - for i=1:length(lay.mask) - if ~isempty(lay.mask{i}) - X = lay.mask{i}(:,1) + hpos; - Y = lay.mask{i}(:,2) + vpos; - % the polygon representing the mask should be closed - X(end+1) = X(1); - Y(end+1) = Y(1); - h = line(X, Y); - set(h, 'color', 'k'); - set(h, 'linewidth', 1.5); - set(h, 'linestyle', ':'); - end - end -end - -axis auto -axis equal -axis off - -if ~holdflag - hold off -end diff --git a/external/fieldtrip/private/plot_line.m b/external/fieldtrip/private/plot_line.m deleted file mode 100644 index 4b29eb3..0000000 --- a/external/fieldtrip/private/plot_line.m +++ /dev/null @@ -1,102 +0,0 @@ -function plot_line(X, Y, varargin) - -% PLOT_LINE helper function for plotting a line, which can also be used in -% combination with the multiple channel layout display in FieldTrip. -% -% Use as -% plot_line(X, Y, ...) -% where optional input arguments should come in key-value pairs and may -% include -% hpos -% vpos -% width -% height -% hlim -% vlim -% color -% linestyle - -% Copyrights (C) 2009, Robert Oostenveld -% -% $Log: plot_line.m,v $ -% Revision 1.6 2009/10/07 13:52:03 roboos -% updated documentation -% -% Revision 1.5 2009/07/14 16:13:14 roboos -% speed up the plotting if no rescaling needs to be done -% -% Revision 1.4 2009/04/14 19:48:28 roboos -% added keyvalcheck -% -% Revision 1.3 2009/04/14 14:31:08 roboos -% many small changes to make it fully functional -% - -% get the optional input arguments -keyvalcheck(varargin, 'optional', {'hpos', 'vpos', 'width', 'height', 'hlim', 'vlim', 'color', 'linestyle'}); -hpos = keyval('hpos', varargin); -vpos = keyval('vpos', varargin); -width = keyval('width', varargin); -height = keyval('height', varargin); -hlim = keyval('hlim', varargin); -vlim = keyval('vlim', varargin); -color = keyval('color', varargin); if isempty(color), color = 'k'; end -linestyle = keyval('linestyle', varargin); if isempty(linestyle), linestyle = '-'; end - -if isempty(hlim) && isempty(vlim) && isempty(hpos) && isempty(vpos) && isempty(height) && isempty(width) - % no scaling is needed, the input X and Y are already fine - % use a shortcut to speed up the plotting - -else - % use the full implementation - abc = axis; - - if isempty(hlim) - hlim = abc([1 2]); - end - - if isempty(vlim) - vlim = abc([3 4]); - end - - if isempty(hpos); - hpos = (hlim(1)+hlim(2))/2; - end - - if isempty(vpos); - vpos = (vlim(1)+vlim(2))/2; - end - - if isempty(width), - width = hlim(2)-hlim(1); - end - - if isempty(height), - height = vlim(2)-vlim(1); - end - - % first shift the horizontal axis to zero - X = X - (hlim(1)+hlim(2))/2; - % then scale to length 1 - X = X ./ (hlim(2)-hlim(1)); - % then scale to the new width - X = X .* width; - % then shift to the new horizontal position - X = X + hpos; - - % first shift the vertical axis to zero - Y = Y - (vlim(1)+vlim(2))/2; - % then scale to length 1 - Y = Y ./ (vlim(2)-vlim(1)); - % then scale to the new width - Y = Y .* height; - % then shift to the new vertical position - Y = Y + vpos; - -end % shortcut - -h = line(X, Y); -set(h, 'Color', color); -set(h, 'LineStyle', linestyle); - - diff --git a/external/fieldtrip/private/plot_matrix.m b/external/fieldtrip/private/plot_matrix.m deleted file mode 100644 index 0550df4..0000000 --- a/external/fieldtrip/private/plot_matrix.m +++ /dev/null @@ -1,195 +0,0 @@ -function plot_matrix(varargin) - -% PLOT_MATRIX -% -% Use as -% plot_matrix(C, ...) -% where C is a 2 dimensional MxN matrix, or -% plot_matrix(X, Y, C, ...) -% where X and Y describe the 1xN horizontal and 1xM vertical axes -% respectively. -% -% Additional options should be specified in key-value pairs and can be -% 'hpos' -% 'vpos' -% 'width' -% 'height' -% 'hlim' -% 'vlim' -% 'clim' -% 'box' can be 'yes' or 'no' -% -% Example use -% plot_matrix(randn(30,50), 'width', 1, 'height', 1, 'hpos', 0, 'vpos', 0) - -% Copyrights (C) 2009, Robert Oostenveld -% -% $Log: plot_matrix.m,v $ -% Revision 1.6 2009/07/14 16:13:53 roboos -% added implementation for clim and highlight -% -% Revision 1.5 2009/06/16 07:51:51 crimic -% small change -% -% Revision 1.4 2009/04/15 20:02:17 roboos -% changed input parsing, fixed 1-pixel offset, added box option -% -% Revision 1.3 2009/04/14 14:31:08 roboos -% many small changes to make it fully functional -% - -if nargin>2 && all(cellfun(@isnumeric, varargin(1:3))) - % the function was called like imagesc(x, y, c, ...) - hdat = varargin{1}; - vdat = varargin{2}; - cdat = varargin{3}; - varargin = varargin(4:end); -else - % the function was called like plot(c, ...) - cdat = varargin{1}; - vdat = 1:size(cdat,1); - hdat = 1:size(cdat,2); - varargin = varargin(2:end); -end - -% get the optional input arguments -keyvalcheck(varargin, 'optional', {'hpos', 'vpos', 'width', 'height', 'hlim', 'vlim', 'clim', 'box','highlight','highlightstyle'}); -hpos = keyval('hpos', varargin); -vpos = keyval('vpos', varargin); -width = keyval('width', varargin); -height = keyval('height', varargin); -hlim = keyval('hlim', varargin); -vlim = keyval('vlim', varargin); -clim = keyval('clim', varargin); -box = keyval('box', varargin); if isempty(box), box = false; end -highlight = keyval('highlight', varargin); -highlightstyle = keyval('highlightstyle', varargin); if isempty(highlightstyle), highlightstyle = 'opacity'; end -% axis = keyval('axis', varargin); if isempty(axis), axis = false; end -% label = keyval('label', varargin); % FIXME -% style = keyval('style', varargin); % FIXME - -% convert the yes/no strings into boolean values -box = istrue(box); - -if isempty(hlim) - hlim = 'maxmin'; -end - -if isempty(vlim) - vlim = 'maxmin'; -end - -if isempty(clim) - clim = 'maxmin'; -end - -if ischar(hlim) - switch hlim - case 'maxmin' - hlim = [min(hdat) max(hdat)]; - case 'absmax' - hlim = max(abs(hdat)); - hlim = [-hlim hlim]; - otherwise - error('unsupported option for hlim') - end % switch -end % if ischar - -if ischar(vlim) - switch vlim - case 'maxmin' - vlim = [min(vdat) max(vdat)]; - case 'absmax' - vlim = max(abs(vdat)); - vlim = [-vlim vlim]; - otherwise - error('unsupported option for vlim') - end % switch -end % if ischar - -if ischar(clim) - switch clim - case 'maxmin' - clim = [min(cdat(:)) max(cdat(:))]; - case 'absmax' - clim = max(abs(cdat(:))); - clim = [-clim clim]; - otherwise - error('unsupported option for clim') - end % switch -end % if ischar - -if isempty(hpos); - hpos = (hlim(1)+hlim(2))/2; -end - -if isempty(vpos); - vpos = (vlim(1)+vlim(2))/2; -end - -if isempty(width), - width = hlim(2)-hlim(1); - width = width * length(hdat)/(length(hdat)-1); - autowidth = true; -else - autowidth = false; -end - -if isempty(height), - height = vlim(2)-vlim(1); - height = height * length(vdat)/(length(vdat)-1); - autoheight = true; -else - autoheight = false; -end - -% hlim -% vlim - -% first shift the horizontal axis to zero -hdat = hdat - (hlim(1)+hlim(2))/2; -% then scale to length 1 -hdat = hdat ./ (hlim(2)-hlim(1)); -% then scale to compensate for the patch size -hdat = hdat * (length(hdat)-1)/length(hdat); -% then scale to the new width -hdat = hdat .* width; -% then shift to the new horizontal position -hdat = hdat + hpos; - -% first shift the vertical axis to zero -vdat = vdat - (vlim(1)+vlim(2))/2; -% then scale to length 1 -vdat = vdat ./ (vlim(2)-vlim(1)); -% then scale to compensate for the patch size -vdat = vdat * (length(vdat)-1)/length(vdat); -% then scale to the new width -vdat = vdat .* height; -% then shift to the new vertical position -vdat = vdat + vpos; - -h = uimagesc(hdat, vdat, cdat, clim); - -if ~isempty(highlight) - switch highlightstyle - case 'opacity' - set(h,'AlphaData',highlight); - set(h, 'AlphaDataMapping', 'scaled'); - alim([0 1]); - case 'outline' - % the significant voxels could be outlined with a black contour - error('unsupported highlightstyle') - otherwise - error('unsupported highlightstyle') - end % switch highlightstyle -end - -if box - boxposition = zeros(1,4); - % this plots a box around the original hpos/vpos with appropriate width/height - boxposition(1) = hpos - width/2; - boxposition(2) = hpos + width/2; - boxposition(3) = vpos - height/2; - boxposition(4) = vpos + height/2; - plot_box(boxposition); -end diff --git a/external/fieldtrip/private/plot_mesh.m b/external/fieldtrip/private/plot_mesh.m deleted file mode 100644 index 9d547a7..0000000 --- a/external/fieldtrip/private/plot_mesh.m +++ /dev/null @@ -1,233 +0,0 @@ -function plot_mesh(bnd, varargin) - -% PLOT_MESH visualizes the information of a mesh contained in the first -% argument bnd. The boundary argument (bnd) contains typically 2 fields -% called .pnt and .tri referring to vertices and triangulation of a mesh. -% -% Use as -% plot_mesh(bnd, ...) -% -% PLOT_MESH also allows to plot only vertices by -% plot_mesh(pnt) -% where pnt is a list of 3d points cartesian coordinates. -% -% Graphic facilities are available for vertices, edges and faces. A list of -% the arguments is given below with the correspondent admitted choices. -% -% 'facecolor' [r g b] values or string, for example 'brain', 'cortex', 'skin', 'black', 'red', 'r' -% 'vertexcolor' [r g b] values or string, for example 'brain', 'cortex', 'skin', 'black', 'red', 'r' -% 'edgecolor' [r g b] values or string, for example 'brain', 'cortex', 'skin', 'black', 'red', 'r' -% 'faceindex' true or false -% 'vertexindex' true or false -% 'facealpha' transparency, between 0 and 1 -% -% If you don't want the faces or vertices to be plotted, you should -% specify facecolor or respectively edgecolor as 'none'. -% -% Example -% [pnt, tri] = icosahedron162; -% bnd.pnt = pnt; -% bnd.tri = tri; -% plot_mesh(bnd, 'facecolor', 'skin', 'edgecolor', 'none') -% camlight -% -% See also TRIMESH - -% Copyright (C) 2009, Cristiano Micheli -% -% $Log: plot_mesh.m,v $ -% Revision 1.29 2009/09/24 07:46:50 crimic -% added realistic colors -% -% Revision 1.28 2009/09/23 09:27:35 roboos -% removed accidental keyboard statement -% -% Revision 1.27 2009/09/23 09:26:55 roboos -% empty is not an appropriate facecolor -% -% Revision 1.26 2009/09/23 09:18:17 roboos -% made handling of facecolor=none more robust, idem for vertex and edgecolor -% -% Revision 1.25 2009/09/23 06:53:20 roboos -% updated documentation, some cleanup of the code and defaults (no functional changes) -% -% Revision 1.24 2009/09/23 06:41:34 roboos -% added "see also" -% -% Revision 1.23 2009/07/29 06:40:16 roboos -% allow empty pnt -% -% Revision 1.22 2009/06/29 16:03:16 roboos -% allow input Nx3 as set of points -% -% Revision 1.21 2009/06/25 16:02:03 crimic -% fixed little error -% -% Revision 1.20 2009/06/21 19:45:52 crimic -% minor changes -% -% Revision 1.19 2009/06/21 19:25:01 crimic -% added tag argument and set edge default color to black -% -% Revision 1.18 2009/06/16 12:19:04 crimic -% erased output graphic handles -% -% Revision 1.17 2009/06/15 15:48:21 roboos -% fixed handling in case input does not have a triangulation -% -% Revision 1.16 2009/06/08 11:52:55 crimic -% updates single points' vertexcolor property -% -% Revision 1.15 2009/06/04 12:55:34 crimic -% changes input parameters check -% -% Revision 1.14 2009/06/03 09:53:50 roboos -% added option for facealpha (transparency) -% updated help for consistency -% -% Revision 1.13 2009/05/13 07:54:36 crimic -% updated help -% -% Revision 1.12 2009/05/13 07:49:55 crimic -% inserted option to manage plot of points in 3d -% -% Revision 1.11 2009/05/12 18:11:21 roboos -% cleaned up whitespace and indentation -% -% Revision 1.10 2009/04/17 13:43:33 crimic -% updated help -% -% Revision 1.9 2009/04/17 13:38:23 crimic -% added default options for varargin, added edgecolor argument -% -% Revision 1.8 2009/04/09 09:36:50 crimic -% *** empty log message *** -% -% Revision 1.7 2009/04/09 09:35:53 crimic -% integrated help -% -% Revision 1.6 2009/04/09 09:20:33 crimic -% clean-up of non used options (val, contour and surface), inserted istrue check -% -% Revision 1.5 2009/04/08 17:09:40 crimic -% added help and modified input argument structure -% -% Revision 1.4 2009/04/08 16:08:50 crimic -% indented with 2 spaces tab, added log signature and copyright -% - -% FIXME: introduce option for color coding (see sourceplot) -keyvalcheck(varargin, 'forbidden', {'faces', 'edges', 'vertices'}); - -if ~isstruct(bnd) && isnumeric(bnd) && size(bnd,2)==3 - % the input seems like a list of points, convert into something that resembles a mesh - warning('off', 'MATLAB:warn_r14_stucture_assignment'); - bnd.pnt = bnd; -end - -% get the optional input arguments -facecolor = keyval('facecolor', varargin); if isempty(facecolor), facecolor='white';end -vertexcolor = keyval('vertexcolor', varargin); if isempty(vertexcolor), vertexcolor='none';end -edgecolor = keyval('edgecolor', varargin); if isempty(edgecolor), edgecolor='k';end -faceindex = keyval('faceindex', varargin); if isempty(faceindex), faceindex=false;end -vertexindex = keyval('vertexindex', varargin); if isempty(vertexindex), vertexindex=false;end -vertexsize = keyval('vertexsize', varargin); if isempty(vertexsize), vertexsize=10;end -facealpha = keyval('facealpha', varargin); if isempty(facealpha), facealpha=1;end -tag = keyval('tag', varargin); if isempty(tag), tag='';end - -% convert string into boolean values -faceindex = istrue(faceindex); -vertexindex = istrue(vertexindex); - -skin = [255 213 119]/255; -brain = [202 100 100]/255; -cortex = [255 213 119]/255; - -% there a various ways of disabling the plotting -if isequal(vertexcolor, 'false') || isequal(vertexcolor, 'no') || isequal(vertexcolor, 'off') || isequal(vertexcolor, false) - vertexcolor = 'none'; -end -if isequal(facecolor, 'false') || isequal(facecolor, 'no') || isequal(facecolor, 'off') || isequal(facecolor, false) - facecolor = 'none'; -end -if isequal(edgecolor, 'false') || isequal(edgecolor, 'no') || isequal(edgecolor, 'off') || isequal(edgecolor, false) - edgecolor = 'none'; -end - -% new colors management -if strcmpi(vertexcolor,'skin') || strcmpi(vertexcolor,'brain') || strcmpi(vertexcolor,'cortex') - vertexcolor = eval(vertexcolor); -end -if strcmpi(facecolor,'skin') || strcmpi(facecolor,'brain') || strcmpi(facecolor,'cortex') - facecolor = eval(facecolor); -end - -% everything is added to the current figure -holdflag = ishold; -hold on - -if ~isfield(bnd, 'tri') - bnd.tri = []; -end - -pnt = bnd.pnt; -tri = bnd.tri; - -if ~isempty(pnt) - hs = patch('Vertices', pnt, 'Faces', tri); - set(hs, 'FaceColor', facecolor); - set(hs, 'FaceAlpha', facealpha); - set(hs, 'EdgeColor', edgecolor); - set(hs, 'tag', tag); -end - -if faceindex - % plot the triangle indices (numbers) at each face - for face_indx=1:size(tri,1) - str = sprintf('%d', face_indx); - tri_x = (pnt(tri(face_indx,1), 1) + pnt(tri(face_indx,2), 1) + pnt(tri(face_indx,3), 1))/3; - tri_y = (pnt(tri(face_indx,1), 2) + pnt(tri(face_indx,2), 2) + pnt(tri(face_indx,3), 2))/3; - tri_z = (pnt(tri(face_indx,1), 3) + pnt(tri(face_indx,2), 3) + pnt(tri(face_indx,3), 3))/3; - h = text(tri_x, tri_y, tri_z, str, 'HorizontalAlignment', 'center', 'VerticalAlignment', 'middle'); - hs = [hs; h]; - end -end - -if ~isequal(vertexcolor, 'none') - if size(pnt, 2)==2 - hs = plot(pnt(:,1), pnt(:,2), 'k.'); - else - hs = plot3(pnt(:,1), pnt(:,2), pnt(:,3), 'k.'); - end - if ~isempty(vertexcolor) - try - set(hs, 'Marker','.','MarkerEdgeColor', vertexcolor,'MarkerSize', vertexsize); - catch - error('Unknown color') - end - end - if vertexindex - % plot the vertex indices (numbers) at each node - for node_indx=1:size(pnt,1) - str = sprintf('%d', node_indx); - if size(pnt, 2)==2 - h = text(pnt(node_indx, 1), pnt(node_indx, 2), str, 'HorizontalAlignment', 'center', 'VerticalAlignment', 'middle'); - else - h = text(pnt(node_indx, 1), pnt(node_indx, 2), pnt(node_indx, 3), str, 'HorizontalAlignment', 'center', 'VerticalAlignment', 'middle'); - end - hs = [hs; h]; - end - end -end - -axis off -axis vis3d -axis equal - -if ~nargout - clear hs -end -if ~holdflag - hold off -end - diff --git a/external/fieldtrip/private/plot_ortho.m b/external/fieldtrip/private/plot_ortho.m deleted file mode 100644 index a739e1f..0000000 --- a/external/fieldtrip/private/plot_ortho.m +++ /dev/null @@ -1,350 +0,0 @@ -function fiducial=plot_ortho(data) -% -% PLOT_ORTHO visualizes an MRI 3D volume in 3 orthogonal projections -% -% Use as -% hs = plot_ortho(data, varargin) -% -% Some defaults for the additional arguments: -% -% 'location' = location of cut, (default = 'auto') -% 'auto', 'center' if only anatomy, 'max' if functional data -% 'min' and 'max' position of min/max funparameter -% 'center' of the brain -% [x y z], coordinates in voxels or head, see locationcoordinates -% 'locationcoordinates' = coordinate system used in location, 'head' or 'voxel' (default = 'head') -% 'head', headcoordinates from anatomical MRI -% 'voxel', voxelcoordinates -% 'crosshair' = 'yes' or 'no' (default = 'yes') -% 'axis' = 'on' or 'off' (default = 'on') -% 'interactive' = 'yes' or 'no' (default = 'no') -% in interactive mode cursor click determines location of cut -% 'queryrange' = number, in atlas voxels (default 3) -% 'funcolorlim' = color range of the functional data (default = 'auto') -% [min max] -% 'maxabs', from -max(abs(funparameter)) to +max(abs(funparameter)) -% 'zeromax', from 0 to max(abs(funparameter)) -% 'minzero', from min(abs(funparameter)) to 0 -% 'auto', if funparameter values are all positive: 'zeromax', -% all negative: 'minzero', both possitive and negative: 'maxabs' -% 'funparameter' = string, field in data with the functional parameter of interest (default = []) -% 'inputcoord' = 'mni' or 'tal', coordinate system of data used to lookup the label from the atlas -% 'colorbar' = 'yes' or 'no' (default = 'yes') -% -% Example -% figure, plot_ortho(data,'colorbar','no','interactive','yes','axis','off') -% -% Copyright (C) 2009, Cristiano Micheli -% -% $Log: plot_ortho.m,v $ -% Revision 1.3 2009/04/21 13:24:13 crimic -% modified help -% -% Revision 1.2 2009/04/20 11:22:51 crimic -% first implementation -% - -% get the optional input arguments -location = keyval('location', varargin); if isempty(location),location='auto';end -locationcoordinates = keyval('locationcoordinates', varargin); if isempty(locationcoordinates),locationcoordinates='head';end -crosshair1 = keyval('crosshair', varargin); if isempty(crosshair1),crosshair1='yes';end -axis1 = keyval('axis', varargin); if isempty(axis1),axis1='yes';end -interactive = keyval('interactive', varargin); if isempty(interactive),interactive='no';end -queryrange = keyval('queryrange', varargin); if isempty(queryrange),queryrange=3;end -funcolorlim = keyval('funcolorlim', varargin); if isempty(funcolorlim),funcolorlim='auto';end -funparameter = keyval('funparameter', varargin); if isempty(funparameter),funparameter=[];end -colorbar1 = keyval('colorbar', varargin); if isempty(colorbar1),colorbar1='yes';end - -% initialize empty output structure -fiducial.nas = []; -fiducial.lpa = []; -fiducial.rpa = []; - -% check if it is a suitable volumetric dataset -if isfield(data,'transform') - if ~isstr(location) - if strcmp(locationcoordinates, 'head') - % convert the headcoordinates location into voxel coordinates - loc = inv(data.transform) * [location(:); 1]; - loc = round(loc(1:3)); - elseif strcmp(locationcoordinates, 'voxel') - % the location is already in voxel coordinates - loc = round(location(1:3)); - else - error('you should specify locationcoordinates'); - end - else - if isequal(location,'auto') - if hasfun - if isequal(funcolorlim,'maxabs'); - loc = 'max'; - elseif isequal(funcolorlim, 'zeromax'); - loc = 'max'; - elseif isequal(funcolorlim, 'minzero'); - loc = 'min'; - else %if numerical - loc = 'max'; - end - else - loc = 'center'; - end; - else - loc = location; - end - end - - % determine the initial intersection of the cursor (xi yi zi) - if isstr(loc) && strcmp(loc, 'min') - if isempty(funparameter) - error('location is min, but no functional parameter specified'); - end - [minval, minindx] = min(fun(:)); - [xi, yi, zi] = ind2sub(dim, minindx); - elseif isstr(loc) && strcmp(loc, 'max') - if isempty(funparameter) - error('location is max, but no functional parameter specified'); - end - [maxval, maxindx] = max(fun(:)); - [xi, yi, zi] = ind2sub(dim, maxindx); - elseif isstr(loc) && strcmp(loc, 'center') - xi = round(dim(1)/2); - yi = round(dim(2)/2); - zi = round(dim(3)/2); - elseif ~isstr(loc) - % using nearest instead of round ensures that the position remains within the volume - xi = nearest(1:dim(1), loc(1)); - yi = nearest(1:dim(2), loc(2)); - zi = nearest(1:dim(3), loc(3)); - end - - % % do the actual plotting %% - nas = []; - lpa = []; - rpa = []; - interactive_flag = 1; % it happens at least once - while(interactive_flag) - interactive_flag = strcmp(interactive, 'yes'); - - xi = round(xi); xi = max(xi, 1); xi = min(xi, dim(1)); - yi = round(yi); yi = max(yi, 1); yi = min(yi, dim(2)); - zi = round(zi); zi = max(zi, 1); zi = min(zi, dim(3)); - - if interactive_flag - fprintf('\n'); - fprintf('click with mouse button to reposition the cursor\n'); - fprintf('press n/l/r on keyboard to record a fiducial position\n'); - fprintf('press q on keyboard to quit interactive mode\n'); - end - - ijk = [xi yi zi 1]'; - xyz = data.transform * ijk; - if hasfun && ~hasatlas - val = fun(xi, yi, zi); - fprintf('voxel %d, indices [%d %d %d], location [%.1f %.1f %.1f], value %f\n', sub2ind(dim, xi, yi, zi), ijk(1:3), xyz(1:3), val); - elseif hasfun && hasatlas - val = fun(xi, yi, zi); - fprintf('voxel %d, indices [%d %d %d], %s coordinates [%.1f %.1f %.1f], value %f\n', sub2ind(dim, xi, yi, zi), ijk(1:3), inputcoord, xyz(1:3), val); - elseif ~hasfun && ~hasatlas - fprintf('voxel %d, indices [%d %d %d], location [%.1f %.1f %.1f]\n', sub2ind(dim, xi, yi, zi), ijk(1:3), xyz(1:3)); - elseif ~hasfun && hasatlas - fprintf('voxel %d, indices [%d %d %d], %s coordinates [%.1f %.1f %.1f]\n', sub2ind(dim, xi, yi, zi), ijk(1:3), inputcoord, xyz(1:3)); - end - - if hasatlas - % determine the anatomical label of the current position - lab = atlas_lookup(atlas, (xyz(1:3)), 'inputcoord', inputcoord, 'queryrange', queryrange); - if isempty(lab) - fprintf([f,' labels: not found\n']); - else - fprintf([f,' labels: ']) - fprintf('%s', lab{1}); - for i=2:length(lab) - fprintf(', %s', lab{i}); - end - fprintf('\n'); - end - end - - % make vols and scales, containes volumes to be plotted (fun, ana, msk) - vols = {}; - if hasana; vols{1} = ana; scales{1} = []; end; % needed when only plotting ana - if hasfun; vols{2} = fun; scales{2} = [fcolmin fcolmax]; end; - if hasmsk; vols{3} = msk; scales{3} = [opacmin opacmax]; end; - - if isempty(vols) - % this seems to be a problem that people often have - error('no anatomy is present and no functional data is selected, please check your funparameter'); - end - - h1 = subplot(2,2,1); - [vols2D] = handle_ortho(vols, [xi yi zi], 2, dim); - plot2D(vols2D, scales); - xlabel('i'); ylabel('k'); axis(axis1); - if strcmp(crosshair1, 'yes'), crosshair([xi zi]); end - - h2 = subplot(2,2,2); - [vols2D] = handle_ortho(vols, [xi yi zi], 1, dim); - plot2D(vols2D, scales); - xlabel('j'); ylabel('k'); axis(axis1); - if strcmp(crosshair1, 'yes'), crosshair([yi zi]); end - - h3 = subplot(2,2,3); - [vols2D] = handle_ortho(vols, [xi yi zi], 3, dim); - plot2D(vols2D, scales); - xlabel('i'); ylabel('j'); axis(axis1); - if strcmp(crosshair1, 'yes'), crosshair([xi yi]); end - - if strcmp(colorbar1, 'yes'), - if hasfun - % vectorcolorbar = linspace(fcolmin, fcolmax,length(funcolormap)); - % imagesc(vectorcolorbar,1,vectorcolorbar);colormap(funcolormap); - subplot(2,2,4); - % use a normal Matlab coorbar, attach it to the invisible 4th subplot - caxis([fcolmin fcolmax]); - hc = colorbar; - set(hc, 'YLim', [fcolmin fcolmax]); - set(gca, 'Visible', 'off'); - else - warning('no colorbar possible without functional data') - end - end - - drawnow; - - if interactive_flag - try, [d1, d2, key] = ginput(1); catch, key='q'; end - if isempty(key) - % this happens if you press the apple key - % do nothing - elseif key=='q' - break; - elseif key=='l' - lpa = [xi yi zi]; - elseif key=='r' - rpa = [xi yi zi]; - elseif key=='n' - nas = [xi yi zi]; - elseif key=='i' || key=='j' || key=='k' || key=='m' - % update the view to a new position - if l1=='i' && l2=='k' && key=='i', zi = zi+1; - elseif l1=='i' && l2=='k' && key=='j', xi = xi-1; - elseif l1=='i' && l2=='k' && key=='k', xi = xi+1; - elseif l1=='i' && l2=='k' && key=='m', zi = zi-1; - elseif l1=='i' && l2=='j' && key=='i', yi = yi+1; - elseif l1=='i' && l2=='j' && key=='j', xi = xi-1; - elseif l1=='i' && l2=='j' && key=='k', xi = xi+1; - elseif l1=='i' && l2=='j' && key=='m', yi = yi-1; - elseif l1=='j' && l2=='k' && key=='i', zi = zi+1; - elseif l1=='j' && l2=='k' && key=='j', yi = yi-1; - elseif l1=='j' && l2=='k' && key=='k', yi = yi+1; - elseif l1=='j' && l2=='k' && key=='m', zi = zi-1; - end; - else - % update the view to a new position - l1 = get(get(gca, 'xlabel'), 'string'); - l2 = get(get(gca, 'ylabel'), 'string'); - switch l1, - case 'i' - xi = d1; - case 'j' - yi = d1; - case 'k' - zi = d1; - end - switch l2, - case 'i' - xi = d2; - case 'j' - yi = d2; - case 'k' - zi = d2; - end - end - end % if interactive_flag - if ~isempty(nas), fprintf('nas = [%f %f %f]\n', nas); fiducial.nas = nas; else fprintf('nas = undefined\n'); end - if ~isempty(lpa), fprintf('lpa = [%f %f %f]\n', lpa); fiducial.lpa = lpa; else fprintf('lpa = undefined\n'); end - if ~isempty(rpa), fprintf('rpa = [%f %f %f]\n', rpa); fiducial.rpa = rpa; else fprintf('rpa = undefined\n'); end - end % while interactive_flag -end - -function plot2D(vols2D, scales); -cla; -% put 2D volumes in fun, ana and msk -hasana = length(vols2D)>0 && ~isempty(vols2D{1}); -hasfun = length(vols2D)>1 && ~isempty(vols2D{2}); -hasmsk = length(vols2D)>2 && ~isempty(vols2D{3}); - -% the transpose is needed for displaying the matrix using the Matlab image() function -if hasana; ana = vols2D{1}'; end; -if hasfun; fun = vols2D{2}'; end; -if hasmsk; msk = vols2D{3}'; end; - - -if hasana - % scale anatomy between 0 and 1 - fprintf('scaling anatomy\n'); - amin = min(ana(:)); - amax = max(ana(:)); - ana = (ana-amin)./(amax-amin); - clear amin amax; - % convert anatomy into RGB values - ana = cat(3, ana, ana, ana); - ha = imagesc(ana); -end -hold on - -if hasfun - hf = imagesc(fun); - caxis(scales{2}); - % apply the opacity mask to the functional data - if hasmsk - % set the opacity - set(hf, 'AlphaData', msk) - set(hf, 'AlphaDataMapping', 'scaled') - alim(scales{3}); - elseif hasana - set(hf, 'AlphaData', 0.5) - end -end - -axis equal -axis tight -axis xy - -function [vols2D] = handle_ortho(vols, indx, slicedir, dim); - -% put 2Dvolumes in fun, ana and msk -if length(vols)>=1 && isempty(vols{1}); hasana=0; else ana=vols{1}; hasana=1; end; -if length(vols)>=2 - if isempty(vols{2}); hasfun=0; else fun=vols{2}; hasfun=1; end; -else hasfun=0; end -if length(vols)>=3 - if isempty(vols{3}); hasmsk=0; else msk=vols{3}; hasmsk=1; end; -else hasmsk=0; end - -% select the indices of the intersection -xi = indx(1); -yi = indx(2); -zi = indx(3); - -% select the slice to plot -if slicedir==1 - yi = 1:dim(2); - zi = 1:dim(3); -elseif slicedir==2 - xi = 1:dim(1); - zi = 1:dim(3); -elseif slicedir==3 - xi = 1:dim(1); - yi = 1:dim(2); -end - -% cut out the slice of interest -if hasana; ana = squeeze(ana(xi,yi,zi)); end; -if hasfun; fun = squeeze(fun(xi,yi,zi)); end; -if hasmsk; msk = squeeze(msk(xi,yi,zi)); end; - -%put fun, ana and msk in vols2D -if hasana; vols2D{1} = ana; end; -if hasfun; vols2D{2} = fun; end; -if hasmsk; vols2D{3} = msk; end; diff --git a/external/fieldtrip/private/plot_sens.m b/external/fieldtrip/private/plot_sens.m deleted file mode 100644 index 748f784..0000000 --- a/external/fieldtrip/private/plot_sens.m +++ /dev/null @@ -1,69 +0,0 @@ -function hs = plot_sens(sens, varargin) - -% PLOT_SENS plots the position of the channels in the EEG or MEG sensor array -% -% Use as -% plot_sens(sens, ...) -% where the first argument is the sensor array as returned by READ_SENS -% or PREPARE_VOL_SENS. -% -% Optional input arguments should come in key-value pairs and can include -% 'style' plotting style for the points representing the channels, see plot3 (default = 'k.') -% 'coil' true/false, plot each individual coil or the channelposition (default = false) -% -% Example -% sens = read_sens('Subject01.ds'); -% plot_sens(sens, 'style', 'r*') - -% Copyright (C) 2009, Robert Oostenveld -% -% $Log: plot_sens.m,v $ -% Revision 1.6 2009/07/29 07:07:02 roboos -% added option for plotting all coils -% -% Revision 1.5 2009/06/04 07:30:07 roboos -% added example -% -% Revision 1.4 2009/05/12 18:12:26 roboos -% added handling of hold on/off -% -% Revision 1.3 2009/04/14 19:48:28 roboos -% added keyvalcheck -% -% Revision 1.2 2009/04/08 06:35:05 roboos -% first implementation, covers the use in headmodelplot -% - -% get the optional input arguments -keyvalcheck(varargin, 'optional', {'style', 'coil'}); -style = keyval('style', varargin); if isempty(style), style = 'k.'; end -coil = keyval('coil', varargin); if isempty(coil), coil = false; end - -% convert yes/no string into boolean value -coil = istrue(coil); - -% everything is added to the current figure -holdflag = ishold; -hold on - -if coil - % simply plot the position of all coils - hs = plot3(sens.pnt(:,1), sens.pnt(:,2), sens.pnt(:,3), style); -else - % determine the position of each channel, which is for example the mean of - % two bipolar electrodes, or the bottom coil of a axial gradiometer - [chan.pnt, chan.label] = channelposition(sens); - hs = plot3(chan.pnt(:,1), chan.pnt(:,2), chan.pnt(:,3), style); -end - -axis vis3d -axis equal - -if ~nargout - clear hs -end -if ~holdflag - hold off -end - - diff --git a/external/fieldtrip/private/plot_slice.m b/external/fieldtrip/private/plot_slice.m deleted file mode 100644 index 1284c9f..0000000 --- a/external/fieldtrip/private/plot_slice.m +++ /dev/null @@ -1,510 +0,0 @@ -function plot_slice(data,varargin) -% -% PLOT_SLICE visualizes the slices of a MRI 3D volume -% -% Use as -% plot_slice(data, varargin) -% -% Some defaults for the additional arguments: -% -% 'nslices' = number of slices, (default = 4) -% 'slicerange' = range of slices in data, (default = 'auto') -% 'auto', full range of data -% [min max], coordinates of first and last slice in voxels -% 'slicedim' = dimension to slice 1 (x-axis) 2(y-axis) 3(z-axis) (default = 3) -% 'title' = string, title of the figure window -% 'colorbar' = 'yes' or 'no' (default = 'yes') -% 'map' = colormap assigned to the slices (default='gray') -% 'transform' = transformation matrix from voxels to mm (default = eye(4)) -% 'flat2D' = flat multi-slice representation (default=false) -% 'tag' -% -% Example -% mri = read_mri('Subject01.mri'); -% figure, plot_slice(mri,'title','3D volume','colorbar','yes','map','jet') -% -% Copyright (C) 2009, Cristiano Micheli -% -% $Log: plot_slice.m,v $ -% Revision 1.11 2009/06/21 19:47:09 crimic -% added tag argument -% -% Revision 1.10 2009/06/21 19:01:31 crimic -% minor changes -% -% Revision 1.9 2009/06/21 19:01:02 crimic -% update help -% -% Revision 1.8 2009/06/21 12:22:58 crimic -% introduced head coordinate transform slice dependency -% -% Revision 1.6 2009/06/16 12:17:55 crimic -% inserted subfunction to plot slices in 3D -% -% Revision 1.5 2009/04/21 13:29:26 crimic -% modified help -% -% Revision 1.4 2009/04/20 11:22:07 crimic -% integrated help -% -% Revision 1.3 2009/04/20 11:16:49 crimic -% minor changes and corrrections -% -% Revision 1.2 2009/04/20 09:51:50 crimic -% implemented first version -% - -% get the optional input arguments -slicerange = keyval('slicerange', varargin); if isempty(slicerange),slicerange='auto'; end -nslices = keyval('nslices', varargin); if isempty(nslices),nslices=4; end -slicedim = keyval('slicedim', varargin); if isempty(slicedim),slicedim=3; end -title_ = keyval('title', varargin); if isempty(title_),title_=''; end -colorbar1 = keyval('colorbar', varargin); if isempty(colorbar1),colorbar1='yes'; end -funparameter = keyval('funparameter', varargin); if isempty(funparameter),funparameter=[]; end -anaparameter = keyval('anaparameter', varargin); if isempty(anaparameter),anaparameter='anatomy'; end -maskparameter = keyval('maskparameter', varargin); if isempty(maskparameter),maskparameter=[]; end -flat2D = keyval('flat2D', varargin); if isempty(flat2D),flat2D=false; end -map = keyval('map', varargin); if isempty(map),map='gray'; end -transform = keyval('transform', varargin); if isempty(transform),transform=eye(4); end -tag = keyval('tag', varargin); if isempty(tag),tag=[]; end - -%%% funparameter -% has fun? -if ~isempty(funparameter) - if issubfield(data, funparameter) - hasfun = 1; - fun = getsubfield(data, funparameter); - else - error('funparameter not found in data'); - end -else - hasfun = 0; - fprintf('no functional parameter\n'); -end -if hasfun - handle_fun(fun) -end -%%% anaparameter -if isequal(anaparameter,'anatomy') - if isfield(data, 'anatomy') - hasana = 1; - mri8 = isa(data.anatomy, 'uint8'); - mri16 = isa(data.anatomy, 'uint16'); - % convert integers to single precision float if neccessary - if mri8 || mri16 - fprintf('converting anatomy to double\n'); - ana = double(data.anatomy); - else - ana = data.anatomy; - end - else - warning('no anatomical volume present, not plotting anatomy\n') - hasana = 0; - end -elseif isempty(anaparameter); - hasana = 0; - fprintf('not plotting anatomy\n'); -else - warning('do not understand anaparameter, not plotting anatomy\n') - hasana = 0; -end -%%% maskparameter -% has mask? -if ~isempty(maskparameter) - if issubfield(data, maskparameter) - if ~hasfun - error('you can not have a mask without functional data') - else - hasmsk = 1; - msk = getsubfield(data, maskparameter); - if islogical(msk) %otherwise sign() not posible - msk = double(msk); - end - end - else - error('maskparameter not found in data'); - end -else - hasmsk = 0; - fprintf('no masking parameter\n'); -end -if hasmsk - handle_msk(msk); -end - - - %%%%% select slices - ss = setdiff([1 2 3], slicedim); - - if ~isstr(slicerange) - ind_fslice = slicerange(1); - ind_lslice = slicerange(2); - elseif isequal(slicerange, 'auto') - if hasfun %default - if isfield(data,'inside') - ind_fslice = min(find(max(max(data.inside,[],ss(1)),[],ss(2)))); - ind_lslice = max(find(max(max(data.inside,[],ss(1)),[],ss(2)))); - else - ind_fslice = min(find(~isnan(max(max(fun,[],ss(1)),[],ss(2))))); - ind_lslice = max(find(~isnan(max(max(fun,[],ss(1)),[],ss(2))))); - end - elseif hasana %if only ana, no fun - ind_fslice = min(find(max(max(ana,[],ss(1)),[],ss(2)))); - ind_lslice = max(find(max(max(ana,[],ss(1)),[],ss(2)))); - else - error('no functional parameter and no anatomical parameter, can not plot'); - end - else - error('do not understand slicerange'); - end - - if nslices==1 - ind_allslice = (ind_fslice+ind_lslice)/2; - elseif nslices==2 - ind_allslice = [ind_fslice+(ind_lslice-ind_fslice)/5 ind_fslice+4*(ind_lslice-ind_fslice)/5]; - else - ind_allslice = linspace(ind_fslice,ind_lslice,nslices); - end - ind_allslice = round(ind_allslice); - - - % if i want to plot a 2D representation of several slices - if flat2D - - % make new ana, fun, msk, mskana with only the slices that will be plotted (slice dim is always third dimension) - if slicedim == 3 - if hasana; new_ana = ana(:,:,ind_allslice); clear ana; ana=new_ana; clear new_ana; end; - if hasfun; new_fun = fun(:,:,ind_allslice); clear fun; fun=new_fun; clear new_fun; end; - if hasmsk; new_msk = msk(:,:,ind_allslice); clear msk; msk=new_msk; clear new_msk; end; - elseif slicedim == 2 - if hasana; new_ana = ana(:,ind_allslice,:); clear ana; ana=new_ana; clear new_ana; end; - if hasfun; new_fun = fun(:,ind_allslice,:); clear fun; fun=new_fun; clear new_fun; end; - if hasmsk; new_msk = msk(:,ind_allslice,:); clear msk; msk=new_msk; clear new_msk; end; - elseif slicedim == 1 - if hasana; new_ana = ana(ind_allslice,:,:); clear ana; ana=new_ana; clear new_ana; end; - if hasfun; new_fun = fun(ind_allslice,:,:); clear fun; fun=new_fun; clear new_fun; end; - if hasmsk; new_msk = msk(ind_allslice,:,:); clear msk; msk=new_msk; clear new_msk; end; - else - error('Error: incorrect slice dimension specification') - end - %if hasmskana; new_mskana = mskana(:,:,ind_allslice); clear mskana; mskana=new_mskana; clear new_mskana; end; - - % update the dimensions of the volume - if hasana; dim=size(ana); else dim=size(fun); end; - - %%%%% make "quilts", that contain all slices on 2D patched sheet - % Number of patches along sides of Quilt (M and N) - % Size (in voxels) of side of patches of Quilt (m and n) - - if slicedim == 3 - m = dim(1); - n = dim(2); - if length(dim)==2 - dim(3) = 1; - end - M = ceil(sqrt(dim(3))); - N = ceil(sqrt(dim(3))); - elseif slicedim == 2 - m = dim(1); - n = dim(3); - M = ceil(sqrt(dim(2))); - N = ceil(sqrt(dim(2))); - elseif slicedim == 1 - m = dim(2); - n = dim(3); - M = ceil(sqrt(dim(1))); - N = ceil(sqrt(dim(1))); - end - - num_patch = N*M; - % if slicedim~=3 - % error('only supported for slicedim=3'); - % end - num_slice = (dim(slicedim)); - num_empt = num_patch-num_slice; - - % put empty slides on ana, fun, msk, mskana to fill Quilt up - if slicedim == 3 - if hasana; ana(:,:,end+1:num_patch)=0; end; - if hasfun; fun(:,:,end+1:num_patch)=0; end; - if hasmsk; msk(:,:,end+1:num_patch)=0; end; - elseif slicedim == 2 - if hasana; ana(:,end+1:num_patch,:)=0; end; - if hasfun; fun(:,end+1:num_patch,:)=0; end; - if hasmsk; msk(:,end+1:num_patch,:)=0; end; - elseif slicedim == 1 - if hasana; ana(end+1:num_patch,:,:)=0; end; - if hasfun; fun(end+1:num_patch,:,:)=0; end; - if hasmsk; msk(end+1:num_patch,:,:)=0; end; - end - - %if hasmskana; mskana(:,:,end:num_patch)=0; end; - % put the slices in the quilt - for iSlice = 1:num_slice - xbeg = floor((iSlice-1)./M); - ybeg = mod(iSlice-1, M); - if slicedim == 3 - if hasana - quilt_ana(ybeg.*m+1:(ybeg+1).*m, xbeg.*n+1:(xbeg+1).*n)=squeeze(ana(:,:,iSlice)); - end - if hasfun - quilt_fun(ybeg.*m+1:(ybeg+1).*m, xbeg.*n+1:(xbeg+1).*n)=squeeze(fun(:,:,iSlice)); - end - if hasmsk - quilt_msk(ybeg.*m+1:(ybeg+1).*m, xbeg.*n+1:(xbeg+1).*n)=squeeze(msk(:,:,iSlice)); - end - elseif slicedim == 2 - if hasana - quilt_ana(ybeg.*m+1:(ybeg+1).*m, xbeg.*n+1:(xbeg+1).*n)=squeeze(ana(:,iSlice,:)); - end - if hasfun - quilt_fun(ybeg.*m+1:(ybeg+1).*m, xbeg.*n+1:(xbeg+1).*n)=squeeze(fun(:,iSlice,:)); - end - if hasmsk - quilt_msk(ybeg.*m+1:(ybeg+1).*m, xbeg.*n+1:(xbeg+1).*n)=squeeze(msk(:,iSlice,:)); - end - elseif slicedim == 1 - if hasana - quilt_ana(ybeg.*m+1:(ybeg+1).*m, xbeg.*n+1:(xbeg+1).*n)=squeeze(ana(iSlice,:,:)); - end - if hasfun - quilt_fun(ybeg.*m+1:(ybeg+1).*m, xbeg.*n+1:(xbeg+1).*n)=squeeze(fun(iSlice,:,:)); - end - if hasmsk - quilt_msk(ybeg.*m+1:(ybeg+1).*m, xbeg.*n+1:(xbeg+1).*n)=squeeze(msk(iSlice,:,:)); - end - end - - % if hasmskana - % quilt_mskana(ybeg.*m+1:(ybeg+1).*m, xbeg.*n+1:(xbeg+1).*n)=squeeze(mskana(:,:,iSlice)); - % end - end - % make vols and scales, containes volumes to be plotted (fun, ana, msk) %added ingnie - if hasana; vols2D{1} = quilt_ana; scales{1} = []; end; % needed when only plotting ana - if hasfun; vols2D{2} = quilt_fun; scales{2} = [fcolmin fcolmax]; end; - if hasmsk; vols2D{3} = quilt_msk; scales{3} = [opacmin opacmax]; end; - - plot2D(vols2D, scales); - axis off - - if strcmp(colorbar1, 'yes'), - if hasfun - % use a normal Matlab colorbar - hc = colorbar; - set(hc, 'YLim', [fcolmin fcolmax]); - else - warning('no colorbar possible without functional data') - end - end - - else - plot_slice_sub(ana,slicedim,ind_allslice,map,transform); - end - - if ~isempty(title_), title(title_); end - -function plot_slice_sub(data,slicedim,ind_allslice,map,transform) -if ~ishold, hold on, end -ds = size(data); - -% determine location of each anatomical voxel in its own voxel coordinates -i = 1:ds(1); -j = 1:ds(2); -k = 1:ds(3); -[I, J, K] = ndgrid(i, j, k); -ijk = [I(:) J(:) K(:) ones(prod(ds),1)]'; - -% determine location of each anatomical voxel in head coordinates -xyz = transform * ijk; -xyz = permute(xyz,[2 1 3]); -xdata = reshape(xyz(:,1), [ds(2) ds(1) ds(3)]); -ydata = reshape(xyz(:,2), [ds(2) ds(1) ds(3)]); -zdata = reshape(xyz(:,3), [ds(2) ds(1) ds(3)]); - -if slicedim == 3 - for i=1:length(ind_allslice) - cdata = squeeze(data(:,:,ind_allslice(i))); - xdata_ = squeeze(xdata(:,:,ind_allslice(i))); - ydata_ = squeeze(ydata(:,:,ind_allslice(i))); - zdata_ = squeeze(zdata(:,:,ind_allslice(i))); - news = surface('cdata',cdata,'alphadata',cdata, 'xdata',xdata_, 'ydata',ydata_, 'zdata',zdata_); - set(news,'facec','interp','edgec','n','facea',0.5); - end -elseif slicedim == 2 - for i=1:length(ind_allslice) - cdata = squeeze(data(:,ind_allslice(i),:)); - xdata_ = squeeze(xdata(:,ind_allslice(i),:)); - ydata_ = squeeze(ydata(:,ind_allslice(i),:)); - zdata_ = squeeze(zdata(:,ind_allslice(i),:)); - news = surface('cdata',cdata,'alphadata',cdata, 'xdata',xdata_, 'ydata',ydata_, 'zdata',zdata_); - set(news,'facec','interp','edgec','n','facea',0.5); - end -elseif slicedim == 1 - for i=1:length(ind_allslice) - cdata = squeeze(data(ind_allslice(i),:,:)); - xdata_ = squeeze(xdata(ind_allslice(i),:,:)); - ydata_ = squeeze(ydata(ind_allslice(i),:,:)); - zdata_ = squeeze(zdata(ind_allslice(i),:,:)); - news = surface('cdata',cdata,'alphadata',cdata, 'xdata',xdata_, 'ydata',ydata_, 'zdata',zdata_); - set(news,'facec','interp','edgec','n','facea',0.5); - end -end -view(45,45) -colormap(map) -axis off -axis vis3d -axis equal - -function plot2D(vols2D, scales) -cla; -% put 2D volumes in fun, ana and msk -hasana = length(vols2D)>0 && ~isempty(vols2D{1}); -hasfun = length(vols2D)>1 && ~isempty(vols2D{2}); -hasmsk = length(vols2D)>2 && ~isempty(vols2D{3}); - -% the transpose is needed for displaying the matrix using the Matlab image() function -if hasana; ana = vols2D{1}'; end; -if hasfun; fun = vols2D{2}'; end; -if hasmsk; msk = vols2D{3}'; end; - - -if hasana - % scale anatomy between 0 and 1 - fprintf('scaling anatomy\n'); - amin = min(ana(:)); - amax = max(ana(:)); - ana = (ana-amin)./(amax-amin); - clear amin amax; - % convert anatomy into RGB values - ana = cat(3, ana, ana, ana); -% ha = imagesc(ana); - plot_matrix(ana) -end -hold on - -if hasfun -% hf = imagesc(fun); - plot_matrix(fun) - caxis(scales{2}); - % apply the opacity mask to the functional data - if hasmsk - % set the opacity - set(hf, 'AlphaData', msk) - set(hf, 'AlphaDataMapping', 'scaled') - alim(scales{3}); - elseif hasana - set(hf, 'AlphaData', 0.5) - end -end - -axis equal -axis tight -axis xy - -function handle_fun(fun) - % determine scaling min and max (fcolmin fcolmax) and funcolormap - funmin = min(fun(:)); - funmax = max(fun(:)); - % smart lims: make from auto other string - if isequal(cfg.funcolorlim,'auto') - if sign(funmin)>-1 && sign(funmax)>-1 - cfg.funcolorlim = 'zeromax'; - elseif sign(funmin)<1 && sign(funmax)<1 - cfg.funcolorlim = 'minzero'; - else - cfg.funcolorlim = 'maxabs'; - end - end - if ischar(cfg.funcolorlim) - % limits are given as string - if isequal(cfg.funcolorlim,'maxabs') - fcolmin = -max(abs([funmin,funmax])); - fcolmax = max(abs([funmin,funmax])); - if isequal(cfg.funcolormap,'auto'); cfg.funcolormap = 'jet'; end; - elseif isequal(cfg.funcolorlim,'zeromax') - fcolmin = 0; - fcolmax = funmax; - if isequal(cfg.funcolormap,'auto'); cfg.funcolormap = 'hot'; end; - elseif isequal(cfg.funcolorlim,'minzero') - fcolmin = funmin; - fcolmax = 0; - if isequal(cfg.funcolormap,'auto'); cfg.funcolormap = 'cool'; end; - else - error('do not understand cfg.funcolorlim'); - end - else - % limits are numeric - fcolmin = cfg.funcolorlim(1); - fcolmax = cfg.funcolorlim(2); - % smart colormap - if isequal(cfg.funcolormap,'auto') - if sign(fcolmin) == -1 && sign(fcolmax) == 1 - cfg.funcolormap = 'jet'; - else - if fcolmin < 0 - cfg.funcolormap = 'cool'; - else - cfg.funcolormap = 'hot'; - end - end - end - end %if ischar - clear funmin funmax; - % ensure that the functional data is real - if ~isreal(fun) - fprintf('taking absolute value of complex data\n'); - fun = abs(fun); - end - -function handle_msk(msk) - mskmin = min(msk(:)); - mskmax = max(msk(:)); - % determine the opacity limits and the opacity map - % smart lims: make from auto other string, or equal to funcolorlim if funparameter == maskparameter - if isequal(cfg.opacitylim,'auto') - if isequal(cfg.funparameter,cfg.maskparameter) - cfg.opacitylim = cfg.funcolorlim; - else - if sign(mskmin)>-1 && sign(mskmax)>-1 - cfg.opacitylim = 'zeromax'; - elseif sign(mskmin)<1 && sign(mskmax)<1 - cfg.opacitylim = 'minzero'; - else - cfg.opacitylim = 'maxabs'; - end - end - end - if ischar(cfg.opacitylim) - % limits are given as string - switch cfg.opacitylim - case 'zeromax' - opacmin = 0; - opacmax = mskmax; - if isequal(cfg.opacitymap,'auto'), cfg.opacitymap = 'rampup'; end; - case 'minzero' - opacmin = mskmin; - opacmax = 0; - if isequal(cfg.opacitymap,'auto'), cfg.opacitymap = 'rampdown'; end; - case 'maxabs' - opacmin = -max(abs([mskmin, mskmax])); - opacmax = max(abs([mskmin, mskmax])); - if isequal(cfg.opacitymap,'auto'), cfg.opacitymap = 'vdown'; end; - otherwise - error('incorrect specification of cfg.opacitylim'); - end - else - % limits are numeric - opacmin = cfg.opacitylim(1); - opacmax = cfg.opacitylim(2); - if isequal(cfg.opacitymap,'auto') - if sign(opacmin)>-1 && sign(opacmax)>-1 - cfg.opacitymap = 'rampup'; - elseif sign(opacmin)<1 && sign(opacmax)<1 - cfg.opacitymap = 'rampdown'; - else - cfg.opacitymap = 'vdown'; - end - end - end % handling opacitylim and opacitymap - clear mskmin mskmax; - \ No newline at end of file diff --git a/external/fieldtrip/private/plot_text.m b/external/fieldtrip/private/plot_text.m deleted file mode 100644 index 4c354c2..0000000 --- a/external/fieldtrip/private/plot_text.m +++ /dev/null @@ -1,114 +0,0 @@ -function [varargout] = plot_text(X, Y, str, varargin) - -% PLOT_TEXT helper function for plotting text, which can also be used in -% combination with the multiple channel layout display in FieldTrip. -% -% Use as -% plot_text(X, Y, ...) -% where optional input arguments should come in key-value pairs and may -% include -% hpos -% vpos -% width -% height -% hlim -% vlim -% Color -% FontSize -% FontName -% HorizontalAlignment - -% Copyrights (C) 2009, Robert Oostenveld -% -% $Log: plot_text.m,v $ -% Revision 1.6 2009/10/07 13:52:03 roboos -% updated documentation -% -% Revision 1.5 2009/08/05 08:52:09 roboos -% added HorizontalAlignment option -% use CamelCase for options that are passed on to the default set() function -% -% Revision 1.4 2009/06/02 15:40:36 giopia -% added varargout to pass handle -% -% Revision 1.3 2009/04/14 19:48:28 roboos -% added keyvalcheck -% -% Revision 1.2 2009/04/14 14:31:08 roboos -% many small changes to make it fully functional -% - -% get the optional input arguments -keyvalcheck(varargin, 'optional', {'hpos', 'vpos', 'width', 'height', 'hlim', 'vlim', 'Color', 'FontSize', 'FontName', 'HorizontalAlignment'}); -hpos = keyval('hpos', varargin); -vpos = keyval('vpos', varargin); -width = keyval('width', varargin); -height = keyval('height', varargin); -hlim = keyval('hlim', varargin); -vlim = keyval('vlim', varargin); -Color = keyval('Color', varargin); if isempty(Color), Color = 'k'; end -FontSize = keyval('FontSize', varargin); -FontName = keyval('FontName', varargin); -HorizontalAlignment = keyval('HorizontalAlignment', varargin); if isempty(HorizontalAlignment), HorizontalAlignment = 'center'; end - -if isempty(hlim) && isempty(vlim) && isempty(hpos) && isempty(vpos) && isempty(height) && isempty(width) - % no scaling is needed, the input X and Y are already fine - % use a shortcut to speed up the plotting - -else - % use the full implementation - abc = axis; - if isempty(hlim) - hlim = abc([1 2]); - end - - if isempty(vlim) - vlim = abc([3 4]); - end - - if isempty(hpos); - hpos = (hlim(1)+hlim(2))/2; - end - - if isempty(vpos); - vpos = (vlim(1)+vlim(2))/2; - end - - if isempty(width), - width = hlim(2)-hlim(1); - end - - if isempty(height), - height = vlim(2)-vlim(1); - end - - % first shift the horizontal axis to zero - X = X - (hlim(1)+hlim(2))/2; - % then scale to length 1 - X = X ./ (hlim(2)-hlim(1)); - % then scale to the new width - X = X .* width; - % then shift to the new horizontal position - X = X + hpos; - - % first shift the vertical axis to zero - Y = Y - (vlim(1)+vlim(2))/2; - % then scale to length 1 - Y = Y ./ (vlim(2)-vlim(1)); - % then scale to the new width - Y = Y .* height; - % then shift to the new vertical position - Y = Y + vpos; - -end % shortcut - -h = text(X, Y, str); -set(h, 'HorizontalAlignment', HorizontalAlignment); -set(h, 'Color', Color); -if ~isempty(FontSize), set(h, 'FontSize', FontSize); end -if ~isempty(FontName), set(h, 'FontName', FontName); end - -% the (optional) output is the handle -if nargout == 1; - varargout{1} = h; -end diff --git a/external/fieldtrip/private/plot_topo.m b/external/fieldtrip/private/plot_topo.m deleted file mode 100644 index 4cb9772..0000000 --- a/external/fieldtrip/private/plot_topo.m +++ /dev/null @@ -1,143 +0,0 @@ -function [varargout] = plot_topo(chanX, chanY, dat, varargin) - -% PLOT_TOPO interpolates and plots the 2-D spatial topography of the -% potential or field distribution over the head -% -% Use as -% plot_topo(x, y, val, ...) -% -% Additional options should be specified in key-value pairs and can be -% 'hpos' -% 'vpos' -% 'width' -% 'height' -% 'shading' -% 'gridscale' -% 'mask' -% 'outline' - -% Copyrights (C) 2009, Giovanni Piantoni -% -% $Log: plot_topo.m,v $ -% Revision 1.9 2009/10/09 11:18:23 jansch -% fixed some inappropriate behaviour -% -% Revision 1.8 2009/10/09 10:23:34 jansch -% added interplim as option, according to topoplot (default = electrodes) -% -% Revision 1.7 2009/08/12 15:15:18 jansch -% also changed the order of inputs on the first line of the function -% -% Revision 1.6 2009/08/05 08:58:54 roboos -% changed the order of the input arguments to plot_topo from (val, x, y) into (x, y, val) -% -% Revision 1.5 2009/08/05 08:53:20 roboos -% plot the outline of the head if specified -% keep hold on/off the same -% -% Revision 1.4 2009/07/29 15:04:16 giopia -% resolved ambiguity of var mask -% -% Revision 1.3 2009/07/29 10:24:24 roboos -% construct the binary image for masking inside this function and reuse it as long as the relevant input does not change -% this is achieved with a persistent variable and by checking the input arguments -% -% Revision 1.2 2009/06/02 15:36:25 giopia -% first implementation based on topoplot.m -% - -% these are for speeding up the plotting on subsequent calls -persistent previous_argin previous_maskimage - -holdflag = ishold; -hold on - -% get the optional input arguments -keyvalcheck(varargin, 'optional', {'hpos', 'vpos', 'width', 'height', 'gridscale', 'shading', 'mask', 'outline', 'interplim'}); -hpos = keyval('hpos', varargin); if isempty(hpos); hpos = 0; end -vpos = keyval('vpos', varargin); if isempty(vpos); vpos = 0; end -width = keyval('width', varargin); if isempty(width); width = 1; end -height = keyval('height', varargin); if isempty(height); height = 1; end -gridscale = keyval('gridscale', varargin); if isempty(gridscale); gridscale = 67; end; % 67 in original -shading = keyval('shading', varargin); if isempty(shading); shading = 'flat'; end; -mask = keyval('mask', varargin); -outline = keyval('outline', varargin); -interplim = keyval('interplim', varargin); if isempty(interplim); interplim = 'electrodes'; end - -chanX = chanX * width + hpos; -chanY = chanY * height + vpos; - -if strcmp(interplim, 'electrodes'), - hlim = [min(chanX) max(chanX)]; - vlim = [min(chanY) max(chanY)]; -elseif strcmp(interplim, 'mask') && ~isempty(mask), - hlim = [inf -inf]; - vlim = [inf -inf]; - for i=1:length(mask) - hlim = [min([hlim(1); mask{i}(:,1)+hpos]) max([hlim(2); mask{i}(:,1)+hpos])]; - vlim = [min([vlim(1); mask{i}(:,2)+vpos]) max([vlim(2); mask{i}(:,2)+vpos])]; - end -else - hlim = [min(chanX) max(chanX)]; - vlim = [min(chanY) max(chanY)]; -end - -% try to speed up the preparation of the mask on subsequent calls -current_argin = {chanX, chanY, gridscale, mask}; -if isequal(current_argin, previous_argin) - % don't construct the binary image, but reuse it from the previous call - maskimage = previous_maskimage; -elseif ~isempty(mask) - % convert the mask into a binary image - maskimage = false(gridscale); - %hlim = [min(chanX) max(chanX)]; - %vlim = [min(chanY) max(chanY)]; - xi = linspace(hlim(1), hlim(2), gridscale); % x-axis for interpolation (row vector) - yi = linspace(vlim(1), vlim(2), gridscale); % y-axis for interpolation (row vector) - [Xi,Yi] = meshgrid(xi', yi); - for i=1:length(mask) - mask{i}(:,1) = mask{i}(:,1)+hpos; - mask{i}(:,2) = mask{i}(:,2)+vpos; - mask{i}(end+1,:) = mask{i}(1,:); % force them to be closed - maskimage(inside_contour([Xi(:) Yi(:)], mask{i})) = true; - end -else - maskimage = []; -end - -xi = linspace(hlim(1), hlim(2), gridscale); % x-axis for interpolation (row vector) -yi = linspace(vlim(1), vlim(2), gridscale); % y-axis for interpolation (row vector) -[Xi,Yi,Zi] = griddata(chanX', chanY, dat, xi', yi, 'v4'); % interpolate the topographic data - -if ~isempty(maskimage) - % apply anatomical mask to the data, i.e. that determines that the interpolated data outside the circle is not displayed - Zi(~maskimage) = NaN; -end - -deltax = xi(2)-xi(1); % length of grid entry -deltay = yi(2)-yi(1); % length of grid entry -h = surface(Xi-deltax/2,Yi-deltay/2,zeros(size(Zi)), Zi, 'EdgeColor', 'none', 'FaceColor', shading); - -% plot the outline of the head, ears and nose -for i=1:length(outline) - xval = outline{i}(:,1) * width + hpos; - yval = outline{i}(:,2) * height + vpos; - plot(xval, yval, 'Color', 'k', 'LineWidth', 1) -end - -% the (optional) output is the handle -if nargout == 1 - varargout{1} = h; -end - -% remember the current input and output arguments, so that they can be -% reused on a subsequent call in case the same input argument is given -if isempty(previous_argin) - previous_argin = current_argin; - previous_maskimage = maskimage; -end - -if ~holdflag - hold off -end - diff --git a/external/fieldtrip/private/plot_topo2d.m b/external/fieldtrip/private/plot_topo2d.m deleted file mode 100644 index e69de29..0000000 diff --git a/external/fieldtrip/private/plot_topo3d.m b/external/fieldtrip/private/plot_topo3d.m deleted file mode 100644 index 3a7b5d1..0000000 --- a/external/fieldtrip/private/plot_topo3d.m +++ /dev/null @@ -1,168 +0,0 @@ -function plot_topo3d(pnt, val, varargin) - -% PLOT_TOPO3D makes a 3-D topographic representation of the electric -% potential or field at the sensor locations -% -% Use as -% plot_topo3d(pos, val, ...); -% where the channel positions are given as a Nx3 matrix and the values are -% given as Nx1 vector. - -% Optional input arguments should be specified in key-value pairs and can include -% ... -% -% See also PLOT_TOPO2D, PLOTTING - -% Copyright (C) 2009, Robert Oostenveld -% -% $Log: plot_topo3d.m,v $ -% Revision 1.3 2009/06/03 09:55:10 roboos -% prevent camera lighting of the interpolated helmet/scalp surface -% -% Revision 1.2 2009/06/03 08:55:55 roboos -% first functional version -% - -% get the optional input arguments -topostyle = keyval('topostyle', varargin); if isempty(topostyle), topostyle = 'color'; end -contourstyle = keyval('contourstyle', varargin); if isempty(contourstyle), contourstyle = false; end -isocontour = keyval('isocontour', varargin); if isempty(isocontour), isocontour = 'auto'; end - -% the interpolation requires a triangulation -tri = projecttri(pnt, 'delaunay'); - -% everything is added to the current figure -holdflag = ishold; -hold on - -if ~isequal(topostyle, false) - switch topostyle - case 'color' - % plot a 2D or 3D triangulated surface with linear interpolation - if length(val)==size(pnt,1) - hs = patch('Vertices', pnt, 'Faces', tri, 'FaceVertexCData', val, 'FaceColor', 'interp'); - else - hs = patch('Vertices', pnt, 'Faces', tri, 'CData', val, 'FaceColor', 'flat'); - end - set(hs, 'EdgeColor', 'none'); - set(hs, 'FaceLighting', 'none'); - otherwise - error('unsupported topostyle'); - end % switch contourstyle -end % plot the interpolated topography - - -if ~isequal(contourstyle, false) - - if isequal(isocontour, 'auto') - minval = min(val); - maxval = max(val); - scale = max(abs(minval), abs(maxval)); - scale = 10^(floor(log10(scale))-1); - minval = floor(minval/scale)*scale; - maxval = ceil(maxval/scale)*scale; - isocontour = minval:scale:maxval; - end - - triangle_val = val(tri); - triangle_min = min(triangle_val, [], 2); - triangle_max = max(triangle_val, [], 2); - - for cnt_indx=1:length(isocontour) - cnt = isocontour(cnt_indx); - use = cnt>=triangle_min & cnt<=triangle_max; - counter = 0; - intersect1 = []; - intersect2 = []; - - for tri_indx=find(use)' - pos = pnt(tri(tri_indx,:), :); - v(1) = triangle_val(tri_indx,1); - v(2) = triangle_val(tri_indx,2); - v(3) = triangle_val(tri_indx,3); - la(1) = (cnt-v(1)) / (v(2)-v(1)); % abcissa between vertex 1 and 2 - la(2) = (cnt-v(2)) / (v(3)-v(2)); % abcissa between vertex 2 and 3 - la(3) = (cnt-v(3)) / (v(1)-v(3)); % abcissa between vertex 1 and 2 - abc(1,:) = pos(1,:) + la(1) * (pos(2,:) - pos(1,:)); - abc(2,:) = pos(2,:) + la(2) * (pos(3,:) - pos(2,:)); - abc(3,:) = pos(3,:) + la(3) * (pos(1,:) - pos(3,:)); - counter = counter + 1; - sel = find(la>=0 & la<=1); - intersect1(counter, :) = abc(sel(1),:); - intersect2(counter, :) = abc(sel(2),:); - end - - % remember the details for external reference - contour(cnt_indx).level = cnt; - contour(cnt_indx).n = counter; - contour(cnt_indx).intersect1 = intersect1; - contour(cnt_indx).intersect2 = intersect2; - end - - % collect all different contour isocontour for plotting - intersect1 = []; - intersect2 = []; - cntlevel = []; - for cnt_indx=1:length(isocontour) - intersect1 = [intersect1; contour(cnt_indx).intersect1]; - intersect2 = [intersect2; contour(cnt_indx).intersect2]; - cntlevel = [cntlevel; ones(contour(cnt_indx).n,1) * isocontour(cnt_indx)]; - end - - X = [intersect1(:,1) intersect2(:,1)]'; - Y = [intersect1(:,2) intersect2(:,2)]'; - C = [cntlevel(:) cntlevel(:)]'; - - if size(pnt,2)>2 - Z = [intersect1(:,3) intersect2(:,3)]'; - else - Z = zeros(2, length(cntlevel)); - end - - switch contourstyle - case 'black' - % make black-white contours - hc = []; - for i=1:length(cntlevel) - if cntlevel(i)>0 - linestyle = '-'; - linewidth = 1; - elseif cntlevel(i)<0 - linestyle = '--'; - linewidth = 1; - else - linestyle = '-'; - linewidth = 2; - end - h1 = patch('XData', X(:,i), 'Ydata', Y(:,i), ... - 'ZData', Z(:,i), 'CData', C(:,i), ... - 'facecolor','none','edgecolor','black', ... - 'linestyle', linestyle, 'linewidth', linewidth, ... - 'userdata',cntlevel(i)); - hc = [hc; h1]; - end - - case 'color' - % make full-color contours - hc = []; - for i=1:length(cntlevel) - h1 = patch('XData', X(:,i), 'Ydata', Y(:,i), ... - 'ZData', Z(:,i), 'CData', C(:,i), ... - 'facecolor','none','edgecolor','flat',... - 'userdata',cntlevel(i)); - hc = [hc; h1]; - end - - otherwise - error('unsupported contourstyle'); - end % switch contourstyle - -end % plot the contours - -axis off -axis vis3d -axis equal - -if ~holdflag - hold off -end diff --git a/external/fieldtrip/private/plot_vector.m b/external/fieldtrip/private/plot_vector.m deleted file mode 100644 index 28d5794..0000000 --- a/external/fieldtrip/private/plot_vector.m +++ /dev/null @@ -1,250 +0,0 @@ -function [varargout] = plot_vector(varargin) - -% PLOT_VECTOR -% -% Use as -% plot_vector(Y, ...) -% plot_vector(X, Y, ...) -% where X and Y are similar as the input to the Matlab plot function. -% -% Additional options should be specified in key-value pairs and can be -% 'hpos' -% 'vpos' -% 'width' -% 'height' -% 'hlim' -% 'vlim' -% 'style' -% 'axis' can be 'yes' or 'no' -% 'box' can be 'yes' or 'no' -% 'highlight' -% 'highlightstyle' -% -% Example use -% plot_vector(randn(1,100), 'width', 1, 'height', 1, 'hpos', 0, 'vpos', 0) - -% Copyrights (C) 2009, Robert Oostenveld -% -% $Log: plot_vector.m,v $ -% Revision 1.11 2009/10/18 11:43:27 ingnie -% added option Color -% -% Revision 1.10 2009/07/30 09:13:58 ingnie -% fixed bug in determining if function was called as plot(x,y,...) or plot(y,...) -% -% Revision 1.9 2009/07/14 16:14:45 roboos -% fixed the plotting of the axes, which were not at [0, 0] -% some general cleanup -% -% Revision 1.8 2009/06/04 13:11:54 crimic -% added highlight option -% -% Revision 1.7 2009/06/02 15:42:52 giopia -% correct error in first if-statement and added varargout for handle -% -% Revision 1.6 2009/04/15 20:00:45 roboos -% small change in input parsing -% -% Revision 1.5 2009/04/14 19:48:28 roboos -% added keyvalcheck -% -% Revision 1.4 2009/04/14 18:55:51 roboos -% changed the handling of the input arguments for a closer resemblance to plot() -% -% Revision 1.3 2009/04/14 14:31:08 roboos -% many small changes to make it fully functional -% - -holdflag = ishold; -hold on - -if nargin>1 && all(cellfun(@isnumeric, varargin(1:2))) - % the function was called like plot(x, y, ...) - hdat = varargin{1}; - vdat = varargin{2}; - varargin = varargin(3:end); -else - % the function was called like plot(y, ...) - vdat = varargin{1}; - if any(size(vdat)==1) - % ensure that it is a column vector - vdat = vdat(:); - end - hdat = 1:size(vdat,1); - varargin = varargin(2:end); -end - -% get the optional input arguments -keyvalcheck(varargin, 'optional', {'hpos', 'vpos', 'width', 'height', 'hlim', 'vlim', 'style', 'label', 'fontsize', 'axis', 'box','highlight','highlightstyle','color'}); -hpos = keyval('hpos', varargin); -vpos = keyval('vpos', varargin); -width = keyval('width', varargin); -height = keyval('height', varargin); -hlim = keyval('hlim', varargin); if isempty(hlim), hlim = 'maxmin'; end -vlim = keyval('vlim', varargin); if isempty(vlim), vlim = 'maxmin'; end -style = keyval('style', varargin); if isempty(style), style = '-'; end -label = keyval('label', varargin); -fontsize = keyval('fontsize', varargin); -axis = keyval('axis', varargin); if isempty(axis), axis = false; end -box = keyval('box', varargin); if isempty(box), box = false; end -color = keyval('color', varargin); -highlight = keyval('highlight', varargin); -highlightstyle = keyval('highlightstyle', varargin); if isempty(highlightstyle), highlightstyle = 'box'; end - -% convert the yes/no strings into boolean values -axis = istrue(axis); -box = istrue(box); - -% label = keyval('label', varargin); % FIXME - -if ischar(hlim) - switch hlim - case 'maxmin' - hlim = [min(hdat) max(hdat)]; - case 'absmax' - hlim = max(abs(hdat)); - hlim = [-hlim hlim]; - otherwise - error('unsupported option for hlim') - end % switch -end % if ischar - -if ischar(vlim) - switch vlim - case 'maxmin' - vlim = [min(vdat(:)) max(vdat(:))]; - case 'absmax' - vlim = max(abs(vdat(:))); - vlim = [-vlim vlim]; - otherwise - error('unsupported option for vlim') - end % switch -end % if ischar - - -if isempty(hpos) && ~isempty(hlim) - hpos = (hlim(1)+hlim(2))/2; -end -if isempty(vpos) && ~isempty(vlim) - vpos = (vlim(1)+vlim(2))/2; -end - -if isempty(width) && ~isempty(hlim) - width = hlim(2)-hlim(1); -end - -if isempty(height) && ~isempty(vlim) - height = vlim(2)-vlim(1); -end - -% first shift the horizontal axis to zero -hdat = hdat - (hlim(1)+hlim(2))/2; -% then scale to length 1 -hdat = hdat ./ (hlim(2)-hlim(1)); -% then scale to the new width -hdat = hdat .* width; -% then shift to the new horizontal position -hdat = hdat + hpos; -% first shift the vertical axis to zero -vdat = vdat - (vlim(1)+vlim(2))/2; -% then scale to length 1 -vdat = vdat ./ (vlim(2)-vlim(1)); -% then scale to the new width -vdat = vdat .* height; -% then shift to the new vertical position -vdat = vdat + vpos; - -if ~isempty(highlight) - switch highlightstyle - case 'box' - % find the sample number where the highligh begins and ends - if ~islogical(highlight) - highlight=logical(highlight); - warning('converting mask to logical values') - end - begsample = find(diff([0 highlight 0])== 1); - endsample = find(diff([0 highlight 0])==-1)-1; - for i=1:length(begsample) - begx = hdat(begsample(i)); - endx = hdat(endsample(i)); - plot_box([begx endx vpos-height/2 vpos+height/2], 'facecolor', [.6 .6 .6], 'edgecolor', 'none'); - end - case 'thickness' - error('unsupported highlightstyle') - case 'opacity' - error('unsupported highlightstyle') - otherwise - error('unsupported highlightstyle') - end % switch highlightstyle -end - -if isempty(color) - h = plot(hdat, vdat, style); -else - h = plot(hdat, vdat, style, 'Color', color); -end - -if ~isempty(label) - boxposition(1) = hpos - width/2; - boxposition(2) = hpos + width/2; - boxposition(3) = vpos - height/2; - boxposition(4) = vpos + height/2; - h = text(boxposition(1), boxposition(4), label); - if ~isempty(fontsize) - set(h, 'Fontsize', fontsize); - end -end - -if box - boxposition = zeros(1,4); - % this plots a box around the original hpos/vpos with appropriate width/height - x1 = hpos - width/2; - x2 = hpos + width/2; - y1 = vpos - height/2; - y2 = vpos + height/2; - - X = [x1 x2 x2 x1 x1]; - Y = [y1 y1 y2 y2 y1]; - line(X, Y); - -% % this plots a box around the original hpos/vpos with appropriate width/height -% boxposition(1) = hpos - width/2; -% boxposition(2) = hpos + width/2; -% boxposition(3) = vpos - height/2; -% boxposition(4) = vpos + height/2; -% plot_box(boxposition, 'facecolor', 'none', 'edgecolor', 'k'); - - % this plots a box around the complete data - % boxposition(1) = hlim(1); - % boxposition(2) = hlim(2); - % boxposition(3) = vlim(1); - % boxposition(4) = vlim(2); - % plot_box(boxposition, 'hpos', hpos, 'vpos', vpos, 'width', width, 'height', height, 'hlim', hlim, 'vlim', vlim); -end - -if axis - % determine where the original [0, 0] in the data is located in the scaled and shifted axes - x0 = interp1(hlim, hpos + [-width/2 width/2 ], 0, 'linear', 'extrap'); - y0 = interp1(vlim, vpos + [-height/2 height/2], 0, 'linear', 'extrap'); - - X = [hpos-width/2 hpos+width/2]; - Y = [y0 y0]; - plot_line(X, Y); - % str = sprintf('%g', hlim(1)); plot_text(X(1), Y(1), str); - % str = sprintf('%g', hlim(2)); plot_text(X(2), Y(2), str); - - X = [x0 x0]; - Y = [vpos-height/2 vpos+height/2]; - plot_line(X, Y); - % str = sprintf('%g', vlim(1)); plot_text(X(1), Y(1), str); - % str = sprintf('%g', vlim(2)); plot_text(X(2), Y(2), str); -end - -% the (optional) output is the handle -if nargout == 1; - varargout{1} = h; -end - -if ~holdflag - hold off -end diff --git a/external/fieldtrip/private/plot_vol.m b/external/fieldtrip/private/plot_vol.m deleted file mode 100644 index adf337b..0000000 --- a/external/fieldtrip/private/plot_vol.m +++ /dev/null @@ -1,109 +0,0 @@ -function plot_vol(vol, varargin) - -% PLOT_VOL visualizes the boundaries in the vol structure constituting the -% geometrical information of the forward model -% -% Use as -% hs = plot_vol(vol, varargin) -% -% Graphic facilities are available for vertices, edges and faces. A list of -% the arguments is given below with the correspondent admitted choices. -% -% 'facecolor' [r g b] values or string, for example 'brain', 'cortex', 'skin', 'black', 'red', 'r' -% 'vertexcolor' [r g b] values or string, for example 'brain', 'cortex', 'skin', 'black', 'red', 'r' -% 'edgecolor' [r g b] values or string, for example 'brain', 'cortex', 'skin', 'black', 'red', 'r' -% 'faceindex' true or false -% 'vertexindex' true or false -% -% Example -% vol.r = [86 88 92 100]; -% vol.o = [0 0 40]; -% figure, plot_vol(vol) - -% Copyright (C) 2009, Cristiano Micheli -% -% $Log: plot_vol.m,v $ -% Revision 1.10 2009/09/04 09:26:28 crimic -% made sphere mesh lighter, added plot_mesh options -% -% Revision 1.9 2009/06/25 16:03:06 crimic -% function now compatible with toolbox guidelines -% -% Revision 1.8 2009/06/03 10:05:40 roboos -% changed handling of mesh generation and teh actual plotting -% -% Revision 1.7 2009/04/22 11:45:02 crimic -% updated help -% -% Revision 1.6 2009/04/22 11:43:57 crimic -% fixed colormap feature -% -% Revision 1.5 2009/04/19 11:35:16 crimic -% added colormap for all vol options -% -% Revision 1.4 2009/04/17 17:00:59 crimic -% updated help -% -% Revision 1.3 2009/04/17 16:48:34 crimic -% updated help -% -% Revision 1.2 2009/04/17 16:45:40 crimic -% created function to plot forward model geometry -% - -keyvalcheck(varargin, 'forbidden', {'faces', 'edges', 'vertices'}); -% get the optional input arguments - -faceindex = keyval('faceindex', varargin); if isempty(faceindex),faceindex = 'none';end -vertexindex = keyval('vertexindex', varargin); if isempty(faceindex),vertexindex ='none';end -vertexsize = keyval('vertexsize', varargin); if isempty(vertexsize), vertexsize = 10; end -facecolor = keyval('facecolor', varargin); if isempty(facecolor),facecolor = 'white'; end -vertexcolor = keyval('vertexcolor', varargin); if isempty(vertexcolor),vertexcolor ='none';end -edgecolor = keyval('edgecolor', varargin); if isempty(edgecolor),edgecolor = 'k';end -facealpha = keyval('facealpha', varargin); if isempty(facealpha),facealpha = 1;end -map = keyval('colormap', varargin); - -faceindex = istrue(faceindex); -vertexindex = istrue(vertexindex); - - -% we will probably need a sphere, so let's prepare one -[pnt, tri] = icosahedron162; - -% prepare a single or multiple triangulated boundaries -switch voltype(vol) - case {'singlesphere' 'concentric'} - vol.r = sort(vol.r); - bnd = []; - for i=1:length(vol.r) - bnd(i).pnt(:,1) = pnt(:,1)*vol.r(i) + vol.o(1); - bnd(i).pnt(:,2) = pnt(:,2)*vol.r(i) + vol.o(2); - bnd(i).pnt(:,3) = pnt(:,3)*vol.r(i) + vol.o(3); - bnd(i).tri = tri; - end - - case 'multisphere' - bnd = []; - for i=1:length(vol.label) - bnd(i).pnt(:,1) = pnt(:,1)*vol.r(i) + vol.o(i,1); - bnd(i).pnt(:,2) = pnt(:,2)*vol.r(i) + vol.o(i,2); - bnd(i).pnt(:,3) = pnt(:,3)*vol.r(i) + vol.o(i,3); - bnd(i).tri = tri; - end - - case {'bem', 'dipoli', 'asa', 'avo', 'bemcp', 'nolte'} - % these already contain one or multiple triangulated surfaces for the boundaries - bnd = vol.bnd; - - otherwise - error('unsupported voltype') -end - - -% plot the triangulated surfaces of the volume conduction model -for i=1:length(bnd) - plot_mesh(bnd(i),'faceindex',faceindex,'vertexindex',vertexindex, ... - 'vertexsize',vertexsize,'facecolor',facecolor,'edgecolor',edgecolor, ... - 'vertexcolor',vertexcolor,'facealpha',facealpha); -end - diff --git a/external/fieldtrip/private/precompute_leadfield.m b/external/fieldtrip/private/precompute_leadfield.m deleted file mode 100644 index 9d11327..0000000 --- a/external/fieldtrip/private/precompute_leadfield.m +++ /dev/null @@ -1,18 +0,0 @@ -function [grid] = precompute_leadfield(cfg, data) - -% PRECOMPUTE_LEADFIELD is deprecated, please use PREPARE_LEADFIELD - -% Copyright (C) 2005-2006, F.C. Donders Centre -% -% $Log: precompute_leadfield.m,v $ -% Revision 1.9 2006/03/14 08:09:22 roboos -% added copyrigth and cvs log statement -% - -warning('PRECOMPUTE_LEADFIELD is deprecated, please use PREPARE_LEADFIELD'); - -if nargin==1 - [grid] = prepare_leadfield(cfg); -else - [grid] = prepare_leadfield(cfg, data); -end diff --git a/external/fieldtrip/private/prepare_atlas.m b/external/fieldtrip/private/prepare_atlas.m deleted file mode 100644 index 819d6d5..0000000 --- a/external/fieldtrip/private/prepare_atlas.m +++ /dev/null @@ -1,559 +0,0 @@ -function [atlas] = prepare_atlas(filename) - -% PREPARE_ATLAS reads in a specified atlas with coordinates and anatomical -% labels. It either uses the AFNI brik file that is available from -% http://afni.nimh.nih.gov/afni/doc/misc/ttatlas_tlrc, or it uses one of -% the WFU atlasses available from http://fmri.wfubmc.edu. This function is -% called by functions that make use of an atlas. -% -% Use as: -% [atlas] = prepare_atlas(filename) -% -% See also VOLUMELOOKUP SOURCEPLOT - -% Copyright (C) 2005-2008, Robert Oostenveld, Ingrid Nieuwenhuis -% -% $Log: prepare_atlas.m,v $ -% Revision 1.2 2009/07/14 07:27:30 roboos -% replaced read_fcdc_mri with read_mri to avoid warning -% -% Revision 1.1 2008/12/05 13:46:24 ingnie -% this function replaces atlas_init -% - -fieldtripdefs - -useafni = 0; -usewfu = 0; - -[p, f, x] = fileparts(filename); - -if strcmp(f, 'TTatlas+tlrc') - useafni = 1; -else - usewfu = 1; -end - -if useafni - % check whether the required AFNI toolbox is available - hastoolbox('afni', 1); - - atlas = read_mri(filename); - - % the AFNI atlas contains two volumes at 1mm resolution - atlas.brick0 = atlas.anatomy(:,:,:,1); - atlas.brick1 = atlas.anatomy(:,:,:,2); - atlas = rmfield(atlas, 'anatomy'); - atlas.coord = 'tal'; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % the following information is from https://afni.nimh.nih.gov/afni/doc/misc/ttatlas_tlrc - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % column 1 contains sub-brick - % column 2 contains value - % column 3 contains stucture name - % 1 68 Hippocampus - % 1 71 Amygdala - % 0 20 Posterior Cingulate - % 0 21 Anterior Cingulate - % 0 22 Subcallosal Gyrus - % 0 24 Transverse Temporal Gyrus - % 0 25 Uncus - % 0 26 Rectal Gyrus - % 0 27 Fusiform Gyrus - % 0 28 Inferior Occipital Gyrus - % 0 29 Inferior Temporal Gyrus - % 0 30 Insula - % 0 31 Parahippocampal Gyrus - % 0 32 Lingual Gyrus - % 0 33 Middle Occipital Gyrus - % 0 34 Orbital Gyrus - % 0 35 Middle Temporal Gyrus - % 0 36 Superior Temporal Gyrus - % 0 37 Superior Occipital Gyrus - % 0 39 Inferior Frontal Gyrus - % 0 40 Cuneus - % 0 41 Angular Gyrus - % 0 42 Supramarginal Gyrus - % 0 43 Cingulate Gyrus - % 0 44 Inferior Parietal Lobule - % 0 45 Precuneus - % 0 46 Superior Parietal Lobule - % 0 47 Middle Frontal Gyrus - % 0 48 Paracentral Lobule - % 0 49 Postcentral Gyrus - % 0 50 Precentral Gyrus - % 0 51 Superior Frontal Gyrus - % 0 52 Medial Frontal Gyrus - % 0 70 Lentiform Nucleus - % 1 72 Hypothalamus - % 1 73 Red Nucleus - % 1 74 Substantia Nigra - % 0 75 Claustrum - % 0 76 Thalamus - % 0 77 Caudate - % 1 124 Caudate Tail - % 1 125 Caudate Body - % 1 126 Caudate Head - % 1 128 Ventral Anterior Nucleus - % 1 129 Ventral Posterior Medial Nucleus - % 1 130 Ventral Posterior Lateral Nucleus - % 1 131 Medial Dorsal Nucleus - % 1 132 Lateral Dorsal Nucleus - % 1 133 Pulvinar - % 1 134 Lateral Posterior Nucleus - % 1 135 Ventral Lateral Nucleus - % 1 136 Midline Nucleus - % 1 137 Anterior Nucleus - % 1 138 Mammillary Body - % 1 144 Medial Globus Pallidus - % 1 145 Lateral Globus Pallidus - % 1 151 Putamen - % 1 146 Nucleus Accumbens - % 1 147 Medial Geniculum Body - % 1 148 Lateral Geniculum Body - % 1 149 Subthalamic Nucleus - % 1 81 Brodmann area 1 - % 1 82 Brodmann area 2 - % 1 83 Brodmann area 3 - % 1 84 Brodmann area 4 - % 1 85 Brodmann area 5 - % 1 86 Brodmann area 6 - % 1 87 Brodmann area 7 - % 1 88 Brodmann area 8 - % 1 89 Brodmann area 9 - % 1 90 Brodmann area 10 - % 1 91 Brodmann area 11 - % 1 93 Brodmann area 13 - % 1 94 Brodmann area 17 - % 1 95 Brodmann area 18 - % 1 96 Brodmann area 19 - % 1 97 Brodmann area 20 - % 1 98 Brodmann area 21 - % 1 99 Brodmann area 22 - % 1 100 Brodmann area 23 - % 1 101 Brodmann area 24 - % 1 102 Brodmann area 25 - % 1 103 Brodmann area 27 - % 1 104 Brodmann area 28 - % 1 105 Brodmann area 29 - % 1 106 Brodmann area 30 - % 1 107 Brodmann area 31 - % 1 108 Brodmann area 32 - % 1 109 Brodmann area 33 - % 1 110 Brodmann area 34 - % 1 111 Brodmann area 35 - % 1 112 Brodmann area 36 - % 1 113 Brodmann area 37 - % 1 114 Brodmann area 38 - % 1 115 Brodmann area 39 - % 1 116 Brodmann area 40 - % 1 117 Brodmann area 41 - % 1 118 Brodmann area 42 - % 1 119 Brodmann area 43 - % 1 120 Brodmann area 44 - % 1 121 Brodmann area 45 - % 1 122 Brodmann area 46 - % 1 123 Brodmann area 47 - % 0 53 Uvula of Vermis - % 0 54 Pyramis of Vermis - % 0 55 Tuber of Vermis - % 0 56 Declive of Vermis - % 0 57 Culmen of Vermis - % 0 58 Cerebellar Tonsil - % 0 59 Inferior Semi-Lunar Lobule - % 0 60 Fastigium - % 0 61 Nodule - % 0 62 Uvula - % 0 63 Pyramis - % 0 66 Culmen - % 0 65 Declive - % 1 127 Dentate - % 0 64 Tuber - % 0 67 Cerebellar Lingual - - atlas.descr.brick = [ - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 1 - 1 - 0 - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - ]; - - atlas.descr.value = [ - 68 - 71 - 20 - 21 - 22 - 24 - 25 - 26 - 27 - 28 - 29 - 30 - 31 - 32 - 33 - 34 - 35 - 36 - 37 - 39 - 40 - 41 - 42 - 43 - 44 - 45 - 46 - 47 - 48 - 49 - 50 - 51 - 52 - 70 - 72 - 73 - 74 - 75 - 76 - 77 - 124 - 125 - 126 - 128 - 129 - 130 - 131 - 132 - 133 - 134 - 135 - 136 - 137 - 138 - 144 - 145 - 151 - 146 - 147 - 148 - 149 - 81 - 82 - 83 - 84 - 85 - 86 - 87 - 88 - 89 - 90 - 91 - 93 - 94 - 95 - 96 - 97 - 98 - 99 - 100 - 101 - 102 - 103 - 104 - 105 - 106 - 107 - 108 - 109 - 110 - 111 - 112 - 113 - 114 - 115 - 116 - 117 - 118 - 119 - 120 - 121 - 122 - 123 - 53 - 54 - 55 - 56 - 57 - 58 - 59 - 60 - 61 - 62 - 63 - 66 - 65 - 127 - 64 - 67 - ]; - - atlas.descr.name = { - 'Hippocampus' - 'Amygdala' - 'Posterior Cingulate' - 'Anterior Cingulate' - 'Subcallosal Gyrus' - 'Transverse Temporal Gyrus' - 'Uncus' - 'Rectal Gyrus' - 'Fusiform Gyrus' - 'Inferior Occipital Gyrus' - 'Inferior Temporal Gyrus' - 'Insula' - 'Parahippocampal Gyrus' - 'Lingual Gyrus' - 'Middle Occipital Gyrus' - 'Orbital Gyrus' - 'Middle Temporal Gyrus' - 'Superior Temporal Gyrus' - 'Superior Occipital Gyrus' - 'Inferior Frontal Gyrus' - 'Cuneus' - 'Angular Gyrus' - 'Supramarginal Gyrus' - 'Cingulate Gyrus' - 'Inferior Parietal Lobule' - 'Precuneus' - 'Superior Parietal Lobule' - 'Middle Frontal Gyrus' - 'Paracentral Lobule' - 'Postcentral Gyrus' - 'Precentral Gyrus' - 'Superior Frontal Gyrus' - 'Medial Frontal Gyrus' - 'Lentiform Nucleus' - 'Hypothalamus' - 'Red Nucleus' - 'Substantia Nigra' - 'Claustrum' - 'Thalamus' - 'Caudate' - 'Caudate Tail' - 'Caudate Body' - 'Caudate Head' - 'Ventral Anterior Nucleus' - 'Ventral Posterior Medial Nucleus' - 'Ventral Posterior Lateral Nucleus' - 'Medial Dorsal Nucleus' - 'Lateral Dorsal Nucleus' - 'Pulvinar' - 'Lateral Posterior Nucleus' - 'Ventral Lateral Nucleus' - 'Midline Nucleus' - 'Anterior Nucleus' - 'Mammillary Body' - 'Medial Globus Pallidus' - 'Lateral Globus Pallidus' - 'Putamen' - 'Nucleus Accumbens' - 'Medial Geniculum Body' - 'Lateral Geniculum Body' - 'Subthalamic Nucleus' - 'Brodmann area 1' - 'Brodmann area 2' - 'Brodmann area 3' - 'Brodmann area 4' - 'Brodmann area 5' - 'Brodmann area 6' - 'Brodmann area 7' - 'Brodmann area 8' - 'Brodmann area 9' - 'Brodmann area 10' - 'Brodmann area 11' - 'Brodmann area 13' - 'Brodmann area 17' - 'Brodmann area 18' - 'Brodmann area 19' - 'Brodmann area 20' - 'Brodmann area 21' - 'Brodmann area 22' - 'Brodmann area 23' - 'Brodmann area 24' - 'Brodmann area 25' - 'Brodmann area 27' - 'Brodmann area 28' - 'Brodmann area 29' - 'Brodmann area 30' - 'Brodmann area 31' - 'Brodmann area 32' - 'Brodmann area 33' - 'Brodmann area 34' - 'Brodmann area 35' - 'Brodmann area 36' - 'Brodmann area 37' - 'Brodmann area 38' - 'Brodmann area 39' - 'Brodmann area 40' - 'Brodmann area 41' - 'Brodmann area 42' - 'Brodmann area 43' - 'Brodmann area 44' - 'Brodmann area 45' - 'Brodmann area 46' - 'Brodmann area 47' - 'Uvula of Vermis' - 'Pyramis of Vermis' - 'Tuber of Vermis' - 'Declive of Vermis' - 'Culmen of Vermis' - 'Cerebellar Tonsil' - 'Inferior Semi-Lunar Lobule' - 'Fastigium' - 'Nodule' - 'Uvula' - 'Pyramis' - 'Culmen' - 'Declive' - 'Dentate' - 'Tuber' - 'Cerebellar Lingual' - }; - -elseif usewfu - atlas = read_fcdc_mri(filename); % /home/... works, ~/.... does not work - atlas.brick0 = atlas.anatomy(:,:,:); - atlas = rmfield(atlas, 'anatomy'); - atlas.coord = 'mni'; - - % the WFU atlas contains a single atlas volume at 2mm resolution - % to keep it compatible with the existing code, add a dummy atlas volume - atlas.brick1 = zeros(size(atlas.brick0)); - - [p, f, x] = fileparts(filename); - f = [f '_List.mat']; - load(fullfile(p, f)); - - atlas.descr = []; - atlas.descr.brick = zeros(length(ROI),1); - atlas.descr.value = [ROI.ID]'; - atlas.descr.name = {ROI.Nom_C}'; % what is difference between Nom_C and Nom_L?? -end diff --git a/external/fieldtrip/private/prepare_bemmodel.m b/external/fieldtrip/private/prepare_bemmodel.m deleted file mode 100644 index 4153e04..0000000 --- a/external/fieldtrip/private/prepare_bemmodel.m +++ /dev/null @@ -1,240 +0,0 @@ -function [vol, cfg] = prepare_bemmodel(cfg, mri) - -% PREPARE_BEMMODEL constructs triangulations of the boundaries between -% multiple segmented tissue types in an anatomical MRI and subsequently -% computes the BEM system matrix. -% -% Use as -% [vol, cfg] = prepare_bemmodel(cfg, mri), or -% [vol, cfg] = prepare_bemmodel(cfg, seg), or -% [vol, cfg] = prepare_bemmodel(cfg, vol), or -% [vol, cfg] = prepare_bemmodel(cfg) -% -% The configuration can contain -% cfg.tissue = [1 2 3], segmentation value of each tissue type -% cfg.numvertices = [Nskin Nskull Nbrain] -% cfg.conductivity = [Cskin Cskull Cbrain] -% cfg.hdmfile = string, file containing the volume conduction model (can be empty) -% cfg.isolatedsource = compartment number, or 0 -% cfg.method = 'dipoli', 'brainstorm' or 'bemcp' -% -% Although the example configuration uses 3 compartments, you can use -% an arbitrary number of compartments. -% -% This function implements -% Oostendorp TF, van Oosterom A. -% Source parameter estimation in inhomogeneous volume conductors of arbitrary shape -% IEEE Trans Biomed Eng. 1989 Mar;36(3):382-91. - -% Copyright (C) 2005-2009, Robert Oostenveld -% -% $Log: prepare_bemmodel.m,v $ -% Revision 1.17 2009/07/16 09:11:19 crimic -% added link to prepare_mesh.m and modified help -% -% Revision 1.16 2009/03/30 15:06:14 roboos -% added the patch from Alexandre to support openmeeg -% -% Revision 1.15 2009/03/24 12:47:11 roboos -% Christophe-> try to spare some memory -% -% Revision 1.14 2009/02/25 09:27:08 roboos -% ensure that the vertices and triangles are double precision, otherwise the bemcp mex files will crash (thanks to Alexandre Gramfort) -% -% Revision 1.13 2009/02/11 11:03:42 roboos -% changed naming of the functions of Chris in accordance with SPM8 -% -% Revision 1.12 2009/02/02 13:15:04 roboos -% added bemcp method, removed the incomplete implementation of brainstorm -% -% Revision 1.11 2008/12/24 10:47:13 roboos -% moved the dipoli code to seperate helper function - -fieldtripdefs - -if ~isfield(cfg, 'tissue'), cfg.tissue = [8 12 14]; end -if ~isfield(cfg, 'numvertices'), cfg.numvertices = [1 2 3] * 500; end -if ~isfield(cfg, 'hdmfile'), cfg.hdmfile = []; end -if ~isfield(cfg, 'isolatedsource'), cfg.isolatedsource = []; end -if ~isfield(cfg, 'method'), cfg.method = 'dipoli'; end % dipoli, openmeeg, bemcp, brainstorm -if ~isfield(cfg, 'conductivity') && isfield(mri, 'cond') - cfg.conductivity = mri.cond; -else - cfg.conductivity = [1 1/80 1] * 0.33; -end - -% start with an empty volume conductor -vol = []; - -if ~isfield(vol, 'cond') - % assign the conductivity of each compartment - vol.cond = cfg.conductivity; -end - -% determine the number of compartments -Ncompartment = length(vol.cond); - -% construct the geometry of the BEM boundaries -if nargin==1 - vol.bnd = prepare_mesh(cfg); -else - vol.bnd = prepare_mesh(cfg, mri); -end - -vol.source = find_innermost_boundary(vol.bnd); -vol.skin = find_outermost_boundary(vol.bnd); -fprintf('determining source compartment (%d)\n', vol.source); -fprintf('determining skin compartment (%d)\n', vol.skin); - -if isempty(cfg.isolatedsource) && Ncompartment>1 && strcmp(cfg.method, 'dipoli') - % the isolated source compartment is by default the most inner one - cfg.isolatedsource = true; -elseif isempty(cfg.isolatedsource) && Ncompartment==1 - % the isolated source interface should be contained within at least one other interface - cfg.isolatedsource = false; -elseif ~isempty(cfg.isolatedsource) && ~islogical(cfg.isolatedsource) - error('cfg.isolatedsource should be true or false'); -end - -if cfg.isolatedsource - fprintf('using compartment %d for the isolated source approach\n', vol.source); -else - fprintf('not using the isolated source approach\n'); -end - -if strcmp(cfg.method, 'dipoli') - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % this uses an implementation that was contributed by Thom Oostendorp - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - hastoolbox('dipoli', 1); - - % use the dipoli wrapper function - vol = dipoli(vol, cfg.isolatedsource); - vol.type = 'dipoli'; - -elseif strcmp(cfg.method, 'bemcp') - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % this uses an implementation that was contributed by Christophe Philips - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - hastoolbox('bemcp', 1); - - % do some sanity checks - if length(vol.bnd)~=3 - error('this only works for three surfaces'); - end - if vol.skin~=3 - error('the skin should be the third surface'); - end - if vol.source~=1 - error('the source compartment should correspond to the first surface'); - end - - % Build Triangle 4th point - vol = triangle4pt(vol); - - % 2. BEM model estimation, only for the scalp surface - - defl =[ 0 0 1/size(vol.bnd(vol.skin).pnt,1)]; - % ensure deflation for skin surface, i.e. average reference over skin - - % NOTE: - % Calculation proceeds by estimating each submatrix C_ij and combine them. - % There are 2 options: - % - calculating the matrices once, as it takes some time, keep them in - % memory and use them the 2-3 times they're needed. - % - calculating the matrices every time they're needed, i.e. 2-3 times - % The former option is faster but requires more memory space as up to *8* - % square matrices of size C_ij have to be kept in memory at once. - % The latter option requires less memory, but would take much more time to - % estimate. - % This faster but memory hungry solution is implemented here. - - % Deal first with surface 1 and 2 (inner and outer skull - %-------------------------------- - - % NOTE: - % C11st/C22st/C33st are simply the matrix C11/C22/C33 minus the identity - % matrix, i.e. C11st = C11-eye(N) - - weight = (vol.cond(1)-vol.cond(2))/((vol.cond(1)+vol.cond(2))*2*pi); - C11st = bem_Cii_lin(vol.bnd(1).tri,vol.bnd(1).pnt, weight,defl(1),vol.bnd(1).pnt4); - weight = (vol.cond(1)-vol.cond(2))/((vol.cond(2)+vol.cond(3))*2*pi); - C21 = bem_Cij_lin(vol.bnd(2).pnt,vol.bnd(1).pnt,vol.bnd(1).tri, weight,defl(1)); - tmp1 = C21/C11st; - - weight = (vol.cond(2)-vol.cond(3))/((vol.cond(1)+vol.cond(2))*2*pi); - C12 = bem_Cij_lin(vol.bnd(1).pnt,vol.bnd(2).pnt,vol.bnd(2).tri, weight,defl(2)); - weight = (vol.cond(2)-vol.cond(3))/((vol.cond(2)+vol.cond(3))*2*pi); - C22st = bem_Cii_lin(vol.bnd(2).tri,vol.bnd(2).pnt, weight,defl(2),vol.bnd(2).pnt4); - tmp2 = C12/C22st; - - % Try to spare some memory: - tmp10 = - tmp2 * C21 + C11st; - clear C21 C11st - tmp11 = - tmp1 * C12 + C22st; - clear C12 C22st - - % Combine with the effect of surface 3 (scalp) on the first 2 - %------------------------------------------------------------ - weight = (vol.cond(1)-vol.cond(2))/(vol.cond(3)*2*pi); - C31 = bem_Cij_lin(vol.bnd(3).pnt,vol.bnd(1).pnt,vol.bnd(1).tri, weight,defl(1)); - % tmp4 = C31/(- tmp2 * C21 + C11st ); - % clear C31 C21 C11st - tmp4 = C31/tmp10; - clear C31 tmp10 - - weight = (vol.cond(2)-vol.cond(3))/(vol.cond(3)*2*pi); - C32 = bem_Cij_lin(vol.bnd(3).pnt,vol.bnd(2).pnt,vol.bnd(2).tri, weight,defl(2)); - % tmp3 = C32/(- tmp1 * C12 + C22st ); - % clear C12 C22st C32 - tmp3 = C32/tmp11; - clear C32 tmp11 - - tmp5 = tmp3*tmp1-tmp4; - tmp6 = tmp4*tmp2-tmp3; - clear tmp1 tmp2 tmp3 tmp4 - - % Finally include effect of surface 3 on the others - %-------------------------------------------------- - % As the gama1 intermediate matrix is built as the sum of 3 matrices, I can - % spare some memory by building them one at a time, and summing directly - weight = vol.cond(3)/((vol.cond(1)+vol.cond(2))*2*pi); - Ci3 = bem_Cij_lin(vol.bnd(1).pnt,vol.bnd(3).pnt,vol.bnd(3).tri, weight,defl(3)); - gama1 = - tmp5*Ci3; % gama1 = - tmp5*C13; - - weight = vol.cond(3)/((vol.cond(2)+vol.cond(3))*2*pi); - Ci3 = bem_Cij_lin(vol.bnd(2).pnt,vol.bnd(3).pnt,vol.bnd(3).tri, weight,defl(3)); - gama1 = gama1 - tmp6*Ci3; % gama1 = - tmp5*C13 - tmp6*C23; - - weight = 1/(2*pi); - Ci3 = bem_Cii_lin(vol.bnd(3).tri,vol.bnd(3).pnt, weight,defl(3),vol.bnd(3).pnt4); - gama1 = gama1 - Ci3; % gama1 = - tmp5*C13 - tmp6*C23 - C33st; - clear Ci3 - - % Build system matrix - %-------------------- - i_gama1 = inv(gama1); - vol.mat = [i_gama1*tmp5 i_gama1*tmp6 i_gama1]; - vol.type = 'bemcp'; - -elseif strcmp(cfg.method, 'openmeeg') - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % this uses an implementation that was contributed by INRIA Odyssee Team - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - hastoolbox('openmeeg', 1); - - % use the openmeeg wrapper function - vol = openmeeg(vol); - vol.type = 'openmeeg'; - -elseif strcmp(cfg.method, 'brainstorm') - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % this uses an implementation from the BrainStorm toolbox - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - hastoolbox('brainstorm', 1); - error('not yet implemented'); - -else - error('unsupported method'); -end % which method - diff --git a/external/fieldtrip/private/prepare_brain_surface.m b/external/fieldtrip/private/prepare_brain_surface.m index 6aa7146..103ace3 100644 --- a/external/fieldtrip/private/prepare_brain_surface.m +++ b/external/fieldtrip/private/prepare_brain_surface.m @@ -13,41 +13,23 @@ % Copyright (C) 2004, Robet Oostenveld % -% $Log: prepare_brain_surface.m,v $ -% Revision 1.6 2007/08/06 09:20:14 roboos -% added support for bti_hs +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.5 2005/11/16 09:10:47 roboos -% only change in some whitespace +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.4 2005/11/04 22:16:59 geekra -% Changed triangulation method when constructing surface from multiple sphere -% model. Now all points are used to create the surface, preventing problems -% with the function normals. +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.3 2005/11/02 10:09:21 geekra -% Removed extra bracket in line 73 that resulted in a syntax error. -% -% Revision 1.2 2005/11/01 09:52:00 roboos -% Changed the construction of the dipole mesh for a localspheres -% headmodel, which was hardcoded for the 151 channel CTF system. Now -% it uses an updated version of the head_surf function. Furthermore, -% implemented support for cfg.spheremesh values other than the number -% of vertices of the refined icosahedrons, and made the reducepatch -% of the headshape dependent on the cfg.spheremesh. -% -% Revision 1.1 2004/06/28 08:59:38 roboos -% moved files from fieldtrip to fieldtrip/private -% -% Revision 1.3 2004/05/17 07:22:16 roberto -% fixed bug in triangle orientation for multi-sphere -% -% Revision 1.2 2004/04/26 12:36:49 roberto -% fixed bug in case of multisphere head surface -% -% Revision 1.1 2004/04/08 15:51:20 roberto -% initial submissiion into cvs +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: prepare_brain_surface.m 952 2010-04-21 18:29:51Z roboos $ % create a head surface, which by default is assumed to correspond to the skin if strcmp(cfg.headshape, 'headmodel') @@ -82,12 +64,8 @@ else fprintf('constructing brain surface from headshape file\n'); % read the headshape from file - if filetype(cfg.headshape, 'ctf_shape') - shape = read_ctf_shape(cfg.headshape); - pnt = shape.pnt; - elseif filetype(cfg.headshape, '4d_hs') - pnt = read_bti_hs(cfg.headshape); - end + shape = read_headshape(cfg.headshape); + pnt = shape.pnt; prj = elproj(pnt); tri = delaunay(prj(:,1), prj(:,2)); % the number of triangles is approximately twice the number of vertices diff --git a/external/fieldtrip/private/prepare_concentricspheres.m b/external/fieldtrip/private/prepare_concentricspheres.m deleted file mode 100644 index b6d4ded..0000000 --- a/external/fieldtrip/private/prepare_concentricspheres.m +++ /dev/null @@ -1,154 +0,0 @@ -function [vol, cfg] = prepare_concentricspheres(cfg) - -% PREPARE_CONCENTRICSPHERES creates a EEG volume conductor model with -% multiple concentric spheres. -% -% Use as -% [vol, cfg] = prepare_concentricspheres(cfg) -% -% The input configuration should contain -% cfg.headshape = a filename containing headshape, a Nx3 matrix with surface -% points, or a structure with a single or multiple boundaries -% cfg.conductivity = conductivity values for the model (default = [0.3300 1 0.0042 0.3300]) -% cfg.fitind = indices of shapes to use for fitting the center (default = 'all') -% cfg.nonlinear = 'yes' or 'no' (default = 'yes') -% cfg.feedback = 'yes' or 'no' (default = 'yes') -% -% Example: -% -% % first create 4 surfaces that represent the brain, csf, skull and skin -% radius = [86 88 92 100]; -% headshape = []; -% for i=1:4 -% pnt = randn(100,3); -% for j=1:size(pnt,1) -% pnt(j,:) = pnt(j,:) ./ norm(pnt(j,:)); -% end -% headshape(i).pnt = radius(i) .* pnt + 0.1*randn(size(pnt)); -% end -% -% % then construct a volume conduction model of the head by fitting 4 concentric spheres -% cfg = []; -% cfg.headshape = headshape; -% cfg.conductivity = [0.3300 1 0.0042 0.3300] -% [vol, cfg] = prepare_concentricspheres(cfg) - -% Copyright (C) 2009, Vladimir Litvak & Robert Oostenveld -% -% $Log: prepare_concentricspheres.m,v $ -% Revision 1.8 2009/07/16 09:14:52 crimic -% part of code reimplemented in function prepare_mesh_headshape.m -% -% Revision 1.7 2009/06/23 14:59:28 crimic -% use of plotting toolbox funtion: plot_mesh -% -% Revision 1.6 2009/05/29 11:40:07 roboos -% only convert cfg.headshape from config to struct in case it is present -% -% Revision 1.5 2009/05/25 08:05:18 roboos -% ensure that cfg.headshape is a sturct and not a config object (in case tracking is on) -% -% Revision 1.4 2009/05/14 19:21:36 roboos -% consistent handling of cfg.headshape in code and documentation -% -% Revision 1.3 2009/04/01 12:28:58 roboos -% use Taubin's method instead of nonlinear search (thanks to Jean and Guillaume) -% -% Revision 1.2 2009/02/05 10:22:55 roboos -% don't open new figure, clear the existing one -% -% Revision 1.1 2009/01/05 13:06:39 roboos -% initial version of Vladimir with some extensions/improvements -% - -fieldtripdefs - -cfg = checkconfig(cfg, 'trackconfig', 'on'); - -% set the defaults -if ~isfield(cfg, 'fitind'), cfg.fitind = 'all'; end -if ~isfield(cfg, 'feedback'), cfg.feedback = 'yes'; end -if ~isfield(cfg, 'conductivity'), cfg.conductivity = [0.3300 1 0.0042 0.3300]; end -if ~isfield(cfg, 'numvertices'), cfg.numvertices = 'same'; end - -if isfield(cfg, 'headshape') && isa(cfg.headshape, 'config') - % convert the nested config-object back into a normal structure - cfg.headshape = struct(cfg.headshape); -end - -cfg = checkconfig(cfg, 'forbidden', 'nonlinear'); - -% get the surface describing the head shape -headshape = prepare_mesh_headshape(cfg); - -if strcmp(cfg.fitind, 'all') - fitind = 1:numel(headshape); -else - fitind = cfg.fitind; -end - -% concatenate the vertices of all surfaces -pnt = []; -for i = fitind - pnt = [pnt ; headshape(i).pnt]; -end -% remove double vertices -pnt = unique(pnt, 'rows'); - -Npnt = size(pnt, 1); - -% set up an empty figure -if strcmp(cfg.feedback, 'yes') - clf - hold on - axis equal - axis vis3d - axis off - drawnow - colors = {'b', 'y', 'm', 'r'}; - [sphere_pnt, sphere_tri] = icosahedron162; -end - -% fit a single sphere to all headshape points -[single_o, single_r] = fitsphere(pnt); -fprintf('initial sphere: number of surface points = %d\n', Npnt); -fprintf('initial sphere: center = [%.1f %.1f %.1f]\n', single_o(1), single_o(2), single_o(3)); -fprintf('initial sphere: radius = %.1f\n', single_r); - -% fit the radius of each concentric sphere to the corresponding surface points -vol = []; -vol.o = single_o; -for i = 1:numel(headshape) - dist = sqrt(sum(((headshape(end-i+1).pnt - repmat(single_o, size(headshape(end-i+1).pnt,1), 1)).^2), 2)); - vol.r(i) = mean(dist); - - if strcmp(cfg.feedback, 'yes') - if ~isfield(headshape(end-i+1), 'tri') - headshape(end-i+1).tri = []; - end - - % plot the original surface - bndtmp = []; - bndtmp.pnt = headshape(end-i+1).pnt; - bndtmp.tri = headshape(end-i+1).tri; - plot_mesh(bndtmp,'facecolor','none') - - % plot the sphere surface - bndtmp = []; - bndtmp.pnt = sphere_pnt*vol.r(i) + repmat(single_o, size(sphere_pnt, 1), 1); - bndtmp.tri = sphere_tri; - plot_mesh(bndtmp,'edgecolor',colors{mod(i, numel(colors)) + 1},'facecolor','none'); - end -end - -if numel(cfg.conductivity)==numel(headshape) - vol.c = cfg.conductivity; -else - error('incorrect specification of cfg.conductivity'); -end - -vol.type = 'concentric'; - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - diff --git a/external/fieldtrip/private/prepare_design.m b/external/fieldtrip/private/prepare_design.m index 3216b2c..99b0ca6 100644 --- a/external/fieldtrip/private/prepare_design.m +++ b/external/fieldtrip/private/prepare_design.m @@ -45,14 +45,23 @@ % Copyright (C) 2006, Eric Maris % -% $Log: prepare_design.m,v $ -% Revision 1.2 2006/06/07 12:56:18 roboos -% give a warning instead of an error if the statistic is unknown +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.1 2006/06/06 20:32:04 erimar -% First commit of prepare_design. +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: prepare_design.m 952 2010-04-21 18:29:51Z roboos $ % determine whether a beween or a within-units design is requested. if any(strcmp(cfg.statistic,{'indepsamplesT','indepsamplesregrT','indepsamplesZcoh','indepsamplesF'})) @@ -141,6 +150,6 @@ [st, i] = dbstack; cfg.version.name = st(i); end -cfg.version.id = '$Id: prepare_design.m,v 1.2 2006/06/07 12:56:18 roboos Exp $'; +cfg.version.id = '$Id: prepare_design.m 952 2010-04-21 18:29:51Z roboos $'; diff --git a/external/fieldtrip/private/prepare_dipole_grid.m b/external/fieldtrip/private/prepare_dipole_grid.m index ebc7a1a..366e2f5 100644 --- a/external/fieldtrip/private/prepare_dipole_grid.m +++ b/external/fieldtrip/private/prepare_dipole_grid.m @@ -48,54 +48,7 @@ % Copyright (C) 2004-2009, Robert Oostenveld % -% $Log: prepare_dipole_grid.m,v $ -% Revision 1.49 2009/05/14 19:22:31 roboos -% consistent handling of cfg.headshape in code and documentation -% -% Revision 1.48 2009/04/16 07:54:52 roboos -% in case of basedonpos keep the dim if present -% -% Revision 1.47 2009/03/18 20:55:28 roboos -% updated detection of infinite medium volume (for magnetic dipole) -% -% Revision 1.46 2008/09/17 14:57:24 roboos -% removed call to fixvolume, it does not seem necessary any more -% -% Revision 1.45 2008/08/13 12:58:45 roboos -% iadded backward compatibility support for tightgrid -% -% Revision 1.44 2008/08/04 09:40:18 jansch -% added field tight to cfg.grid to prevent crash -% -% Revision 1.43 2008/07/31 15:57:16 roboos -% prevent basedongrid if xgrid=auto -% -% Revision 1.42 2008/07/21 09:22:06 roboos -% do not copy grid back into cfg.grid -% -% Revision 1.41 2008/07/17 14:56:38 roboos -% fixed bug in basedonauto causing xgrid to be overwritten with 'auto' (thanks to Vladimir) -% -% Revision 1.40 2008/07/16 10:51:46 roboos -% fixed bug: inwardshift is in cfg, not yet in cfg.grid -% -% Revision 1.39 2008/07/16 10:47:33 roboos -% basedonpos overrides basedongrid -% -% Revision 1.38 2008/07/16 10:15:15 roboos -% added two missing defaults for basedonpos, thanks to Jan-Mathijs -% -% Revision 1.37 2008/07/16 08:53:55 roboos -% only fall back to default "basedonvol" in case none of the other methods was selected -% -% Revision 1.36 2008/07/15 19:52:21 roboos -% cleaned up the handling of the different grid-generating methods -% more output on screen, more rigid checking of conflicting cfgs -% renamed cfg.tightgrid into cfg.grid.tight -% -% Revision 1.35 2007/12/11 11:12:44 roboos -% remember dipole moment if specified -% +% Subversion does not use the Log keyword, use 'svn log ' or 'svn -v log | less' to get detailled information % set the defaults if ~isfield(cfg, 'symmetry'), cfg.symmetry = []; end @@ -185,6 +138,21 @@ error('incorrect cfg specification for constructing a dipole grid'); end +needspm = isfield(cfg, 'smooth') && ~strcmp(cfg.smooth, 'no'); +if needspm + % check if SPM is in path and if not add + hasspm2 = hastoolbox('SPM2'); + hasspm8 = hastoolbox('SPM8'); + + if ~hasspm2 && ~hasspm8 + try, hasspm8 = hastoolbox('SPM8', 1); end + end + + if ~hasspm8 + try, hastoolbox('SPM2', 1); end + end +end + % start with an empty grid grid = []; @@ -341,9 +309,9 @@ end % apply a smoothing of a certain amount of voxels - if ~isstr(cfg.smooth) && cfg.smooth>1 + if ~strcmp(cfg.smooth, 'no'); fprintf('smoothing gray matter segmentation with %d voxels\n', cfg.smooth); - mri.gray = spm_conv(mri.gray, cfg.smooth); + spm_smooth(mri.gray, mri.gray, cfg.smooth); end % determine for each voxel whether it belongs to the cortex @@ -441,7 +409,7 @@ % FIXME use inside_vol instead of this replication of code % determine the dipole locations inside the brain volume if ~isfield(grid, 'inside') && ~isfield(grid, 'outside') - if voltype(vol, 'infinite') + if ft_voltype(vol, 'infinite') % an empty vol in combination with gradiometers indicates a magnetic dipole % in an infinite vacuum, i.e. all dipoles can be considered to be inside grid.inside = 1:size(grid.pos,1); diff --git a/external/fieldtrip/private/prepare_freq_matrices.m b/external/fieldtrip/private/prepare_freq_matrices.m index fde81e9..2367b41 100644 --- a/external/fieldtrip/private/prepare_freq_matrices.m +++ b/external/fieldtrip/private/prepare_freq_matrices.m @@ -10,93 +10,23 @@ % Copyright (C) 2004-2006, Robert Oostenveld % -% $Log: prepare_freq_matrices.m,v $ -% Revision 1.25 2009/08/16 12:43:22 jansch -% added default empty cfg.refchan +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.24 2009/02/05 10:22:07 roboos -% better support for single-trial data, thanks to Vladimir +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.23 2008/07/11 14:06:43 jansch -% fixed the cfg.channel freq.label issue for fourierspctrm as well +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.22 2008/07/10 15:50:27 roboos -% keep channel order consistent with the input cfg -% -% Revision 1.21 2008/07/08 15:39:22 roboos -% initial version for Saskia to work on -% -% Revision 1.20 2006/10/30 16:37:29 roboos -% fixed bug in reshaping of fourier data (was ctranspose, whereas it should be normal transpose), all phase differences in the CSD matix were therefore defined the other way around -% added support for Cr and Pr (needed for dics) in case fourier input data -% -% Revision 1.19 2006/10/02 13:02:27 roboos -% fixed bug for rpttap_chan_freq_time, where the 'tap' part was dropped from the dimord -% -% Revision 1.18 2006/03/08 15:31:14 roboos -% removed default cfg.channel=all, since no channelselection is done inside this function -% -% Revision 1.17 2006/02/23 10:28:17 roboos -% changed dimord strings for consistency, changed toi and foi into time and freq, added fixdimord where neccessary -% -% Revision 1.16 2006/02/10 09:15:30 jansch -% changed some chancmb which were missed during last fix -% -% Revision 1.15 2006/02/10 09:12:15 jansch -% changed _chancmb in the dimord into _chan -% -% Revision 1.14 2006/02/01 12:26:04 roboos -% made all uses of dimord consistent with the common definition of data dimensions, see the fixdimord() function -% -% Revision 1.13 2005/08/26 14:56:27 roboos -% selection of tbin in freq.toi was done twice, resulting in error -% -% Revision 1.12 2005/08/26 13:39:02 roboos -% changed the indentation throughout the code, no functional changes -% -% Revision 1.11 2005/08/25 08:05:42 jansch -% removed support for fourier in case of average, since that does not make sense -% added support for multiple tapers in computation of CSD from fourier input -% -% Revision 1.10 2005/08/16 13:16:24 jansch -% *** empty log message *** -% -% Revision 1.9 2005/08/16 12:47:57 jansch -% made change to also support input dimord of 'rpttap_sgncmb_frq' -% -% Revision 1.8 2005/08/15 13:30:50 jansch -% removed the normalisation for the number of samples, when computing the cross- -% spectra from the fourierspctrum: TAKE CARE! this is not backward-compatible -% -% Revision 1.7 2005/05/20 16:50:26 roboos -% added normalisation of the CSD matrix computed from the fourier spectra -% -% Revision 1.6 2005/05/17 18:01:21 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% added cfg.dicsfix for taking conjugate of csd from MEG to reference channel (default) -% implemented computation of csd from single trial fourier spectrum (if freqanalysis with output=fourier) -% -% Revision 1.5 2005/03/03 10:59:29 roboos -% Added cfg as output argument and added selected chanels to the output -% cfg, so that the calling function knows which were selected. Renamed -% tbin into timebin. -% -% Revision 1.4 2005/02/16 15:13:50 roboos -% renamed cfg.refchannel into cfg.refchan, replaced detection of coh_refchan submethod for dics (now looking for presence of cfg.refchan instead of explicitely testing the submethod) -% -% Revision 1.3 2004/08/26 12:43:22 roboos -% fixed bug in backward-compatibility code for sgn/sgncmb -% -% Revision 1.2 2004/08/25 17:00:08 roboos -% changed from sgn/sgncmb to label/labelcmb, backward compatible -% -% Revision 1.1 2004/06/28 08:59:38 roboos -% moved files from fieldtrip to fieldtrip/private -% -% Revision 1.1 2004/04/08 15:51:20 roberto -% initial submissiion into cvs +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: prepare_freq_matrices.m 952 2010-04-21 18:29:51Z roboos $ % set the defaults if ~isfield(cfg, 'dicsfix'), cfg.dicsfix = 'yes'; end @@ -247,7 +177,7 @@ for trial=1:Ntrials Pr(trial) = freq.powspctrm(trial, refindx, fbin); end - Pr = Pr(:); % ensure that the first dimension contains the trials + Pr = Pr(:); % ensure that the first dimension contains the trials end end @@ -281,8 +211,8 @@ Cf(1,:,:) = (dat * ctranspose(dat)) ./ ntap; if ~isempty(refindx) ref = transpose(freq.fourierspctrm(:, refindx, fbin)); - Cr(1,:,1) = dat * ctranspose(ref) ./ ntap; - Pr(1,1,1) = ref * ctranspose(ref) ./ ntap; + Cr(1,:,1) = dat * ctranspose(ref) ./ ntap; + Pr(1,1,1) = ref * ctranspose(ref) ./ ntap; end else freq.cumtapcnt = freq.cumtapcnt(:)'; diff --git a/external/fieldtrip/private/prepare_headmodel.m b/external/fieldtrip/private/prepare_headmodel.m index 6de51ef..ddd6d81 100644 --- a/external/fieldtrip/private/prepare_headmodel.m +++ b/external/fieldtrip/private/prepare_headmodel.m @@ -29,132 +29,23 @@ % Copyright (C) 2004-2009, Robert Oostenveld % -% $Log: prepare_headmodel.m,v $ -% Revision 1.6 2009/03/11 11:26:21 roboos -% switched to using forwinv/prepare_vol_sens +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.5 2009/01/21 12:47:46 sashae -% ensure vol is always a struct +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.4 2009/01/19 12:09:00 roboos -% fixed typo in 4-sphere eeg code (thanks to John Iversen) +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.3 2008/07/07 12:36:09 roboos -% fixed bug in skin-compartment determination for 4-sphere -% -% Revision 1.2 2008/04/10 08:03:11 roboos -% renamed the fieldtrip/private/prepare_vol_sens function into prepare_headmodel -% -% Revision 1.1 2008/04/10 07:57:37 roboos -% renamed from prepare_vol_sens into prepare_headmodel, based on rev -% 1.28. This is to avild a name clash with the lower level function -% that is part of the forwinv module (i.e. this is part of the -% rearrangement of high-level and low-level functionality between -% fieldtrip and teh seperate modules) -% -% Revision 1.28 2008/03/18 12:26:47 roboos -% use senstype function to add descriptive string to the output (sens.type=...) -% -% Revision 1.27 2008/03/05 10:50:06 roboos -% switched to read_sens for reading elec or grad structures from file -% moved convert_ama2vol to standalone function -% -% Revision 1.26 2007/04/19 17:15:56 roboos -% only initialize the nolte method when the gradiometer array is not empty (usefull for plotting) -% -% Revision 1.25 2006/07/20 15:04:23 roboos -% added instructive fprintf message -% -% Revision 1.24 2006/05/23 10:17:32 roboos -% changed some comments, no code changes -% -% Revision 1.23 2006/04/12 08:38:15 ingnie -% updated documentation -% -% Revision 1.22 2006/04/10 16:35:20 ingnie -% updated documentation -% -% Revision 1.21 2006/03/21 09:44:03 roboos -% implemented support for Guido Nolte's method using vol.type='nolte' -% for neuromag: store the surface normals in the vol.bnd.nrm (consistent with nolte) -% -% Revision 1.20 2005/12/14 10:42:26 roboos -% removed warning for synthetic gradiometers -% if topolabel is present in data, look at that instead of label (for ICA) -% always try to add vol.skin and vol.brain -% -% Revision 1.19 2005/11/16 09:14:06 roboos -% moved the conversion from dipoli/ama format to fieldtrip/vol format to subfunction -% changed the post-processing of the EEG BEM model: incorporate the tra and mat matrices into one matrix (for computational efficiency) -% -% Revision 1.18 2005/09/29 01:15:32 roboos -% changed construction of the localsphere per coil for CTF hdm file -% -% Revision 1.17 2005/09/29 00:47:05 roboos -% added support for mbfys_ama BEM volume conductor file -% -% Revision 1.16 2005/08/05 07:26:22 roboos -% switched to teh use of read_fcdc_elec for cfg.gradfile -% -% Revision 1.15 2005/07/18 10:13:23 roboos -% fixed reading gradiometer from cfg.gradfile for CTF using ctf2grad -% added reading gradiometer from fif file -% -% Revision 1.14 2005/06/28 19:50:42 roboos -% minor change to solve problem when compiling to c-code, functionality is the same -% load(cfg.filename) gives compilation error, so first copy the string with the filename from the structure in a plain variable and then load(...) -% -% Revision 1.13 2005/06/08 16:33:54 roboos -% changed reading of gradiometers from matlab file -% prune the coils for a higher-order gradiometer system (i.e. remove non-contributing coils) -> this temporary solves a problem with multisphere headmodels -% -% Revision 1.12 2005/05/17 17:50:49 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.11 2005/03/03 10:52:37 roboos -% changed the handling of the channel selection. The input cfg now specifies -% the channels that should be kept in the sensor array. If no selection is -% specified in the input cfg (e.g. for dipolesimulation), the default is 'all'. -% -% Revision 1.10 2005/01/26 08:05:23 roboos -% added empty data if second input argument not given -% -% Revision 1.9 2005/01/17 14:52:50 roboos -% changed to use read_fcdc_elec -% -% Revision 1.8 2004/12/08 18:00:13 roboos -% implemented consistent method of selecting a subset of channels for -% forward and inverse computations using cfg.channel and updated the -% ducumentation -% -% Revision 1.7 2004/09/06 08:45:38 roboos -% moved reading of neuromag BEM bondary from find_inside_vol into prepare_vol_sens -% -% Revision 1.6 2004/09/03 09:15:28 roboos -% added channelselection to the volume for neuromag -% -% Revision 1.5 2004/09/03 06:39:09 roboos -% fixed bug in non-functional neuromag section, cfg->vol -% -% Revision 1.4 2004/09/01 17:30:09 roboos -% added some explanation to the chansel for neuromag -% -% Revision 1.3 2004/08/31 13:55:22 roboos -% added initialization of neuromag megmodel -% -% Revision 1.2 2004/08/06 08:54:53 roboos -% fixed bug for gradiometer info coming from matlab file -% -% Revision 1.1 2004/06/28 08:59:38 roboos -% moved files from fieldtrip to fieldtrip/private -% -% Revision 1.2 2004/05/08 21:06:25 roberto -% added support for reading gradiometer from matlab file -% -% Revision 1.1 2004/04/08 15:51:20 roberto -% initial submissiion into cvs +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: prepare_headmodel.m 952 2010-04-21 18:29:51Z roboos $ % set the defaults if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end @@ -204,15 +95,15 @@ if isfield(data, 'topolabel') % the data reflects a componentanalysis, where the topographic and the % timecourse labels are different - cfg.channel = channelselection(cfg.channel, data.topolabel); + cfg.channel = ft_channelselection(cfg.channel, data.topolabel); elseif isfield(data, 'label') % In the subsequent code, the matching channels in the sensor array and % in the configuration will be selected. To ensure that these channels % are also present in the data, update the configuration to match the data. - cfg.channel = channelselection(cfg.channel, data.label); + cfg.channel = ft_channelselection(cfg.channel, data.label); else % update the selected channels based on the electrode/gradiometer definition - cfg.channel = channelselection(cfg.channel, sens.label); + cfg.channel = ft_channelselection(cfg.channel, sens.label); end % ensure that these are a struct, which may be required in case configuration tracking is used @@ -220,7 +111,7 @@ sens = struct(sens); % the prepare_vol_sens function from the forwinv module does most of the actual work -[vol, sens] = prepare_vol_sens(vol, sens, 'channel', cfg.channel, 'order', cfg.order); +[vol, sens] = ft_prepare_vol_sens(vol, sens, 'channel', cfg.channel, 'order', cfg.order); % update the selected channels in the configuration cfg.channel = sens.label; diff --git a/external/fieldtrip/private/prepare_layout.m b/external/fieldtrip/private/prepare_layout.m deleted file mode 100644 index 7d9e845..0000000 --- a/external/fieldtrip/private/prepare_layout.m +++ /dev/null @@ -1,860 +0,0 @@ -function [lay] = prepare_layout(cfg, data); - -% PREPARE_LAYOUT creates a 2-D layout of the channel locations. This layout -% is required for plotting the topographical distribution of the potential -% or field distribution, or for plotting timecourses in a topographical -% arrangement. -% -% Use as -% lay = prepare_layout(cfg, data) -% -% There are several ways in which a 2-D layout can be made: it can be read -% directly from a *.lay file, it can be created based on 3-D electrode or -% gradiometer positions in the configuration or in the data, or it can be -% created based on the specification of an electrode of gradiometer file. -% -% You can specify either one of the following configuration options -% cfg.layout filename containg the layout -% cfg.rotate number, rotation around the z-axis in degrees (default = [], which means automatic) -% cfg.projection string, 2D projection method can be 'stereographic', 'orthographic', 'polar', 'gnomic' or 'inverse' (default = 'polar') -% cfg.elec structure with electrode positions, or -% cfg.elecfile filename containing electrode positions -% cfg.grad structure with gradiometer definition, or -% cfg.gradfile filename containing gradiometer definition -% cfg.output filename to which the layout will be written (default = []) -% cfg.montage 'no' or a montage structure (default = 'no') -% cfg.image filename, use an image to construct a layout (e.g. usefull for ECoG grids) -% cfg.bw if an image is used and bw = 1 transforms the image in black and white (default = 0, do not transform) -% -% Alternatively the layout can be constructed from either -% data.elec structure with electrode positions -% data.grad structure with gradiometer definition -% -% Alternatively you can specify the following layouts which will be -% generated for all channels present in the data. Note that these layouts -% are suitable for multiplotting, but not for topoplotting. -% cfg.layout = 'ordered' will give you a NxN ordered layout -% cfg.layout = 'vertical' will give you a Nx1 ordered layout -% cfg.layout = 'butterfly' will give you a layout with all channels on top of each other -% -% See also layoutplot, topoplotER, topoplotTFR, multiplotER, multiplotTFR - -% TODO switch to using planarchannelset function - -% undocumented and non-recommended option (for SPM only) -% cfg.style string, '2d' or '3d' (default = '2d') - -% Copyright (C) 2007-2009, Robert Oostenveld -% -% $Log: prepare_layout.m,v $ -% Revision 1.41 2009/10/14 15:26:36 roboos -% There was a typo in the cfg.projection default, which was ortographic -% (without "h"). The consequence was that the actual default being -% used is polar (because the underlying function would not recognise -% the typo and switch to its own polar default). I have changed the -% default to polar, consistent with its actual behaviour sofar. Polar -% is also the most robust for electrodes along the edge. -% -% Revision 1.40 2009/08/05 08:22:09 roboos -% better detection of empty/absent input data -% -% Revision 1.39 2009/08/05 06:32:41 roboos -% fixed layout generation for ordered and vertical when no data was given as input, labels fully depend on cfg.channel, not on data.label -% -% Revision 1.38 2009/08/04 13:57:00 roboos -% make tight vertical and orderer layout in case cfg.channel is specified -% allow skipping the COMNT and SCALE positions through the cfg -% -% Revision 1.37 2009/06/30 07:08:55 roboos -% removed debug keyboard statement -% -% Revision 1.36 2009/06/17 14:03:41 roboos -% consistent handling of ginput in case figure is closed -% -% Revision 1.35 2009/06/05 15:30:05 crimic -% updated help -% -% Revision 1.34 2009/06/05 15:28:03 crimic -% updated cfg -% -% Revision 1.33 2009/06/05 15:26:32 crimic -% minor change -% -% Revision 1.32 2009/05/18 15:59:44 roboos -% optinal plotting of RGB as greyscale image -% -% Revision 1.31 2009/03/30 17:55:17 vlalit -% Changed prepare_layout and headmodelplot to use channelposition. Changed the color -% of sensor markers in headmodelplot to green for consistency with SPM plots. -% -% Revision 1.30 2009/02/26 10:37:10 roboos -% fixed bug, thanks to Yoni -% -% Revision 1.29 2009/02/25 17:44:27 roboos -% added vertical and butterfly layouts -% -% Revision 1.28 2009/02/04 16:58:31 roboos -% fixed backward compatibility bug in related to isfield, thanks to Irina -% -% Revision 1.27 2009/01/21 10:02:58 roboos -% explicit handling of config->struct in case configuration tracking is used -% changed default handling, don't use try-catch any more (thanks to Ivar) -% -% Revision 1.26 2009/01/20 14:27:24 jansch -% fixed bug in the case that the cfg.layout is a config-object leading to the -% generation of a 'default' CTF151 layout. this was problematic in the -% interactive mode of the plotting routines, toggling back and forth -% -% Revision 1.25 2008/12/24 13:34:19 roboos -% fixed bug in hte closing of masking polygons -% -% Revision 1.24 2008/12/05 10:58:17 roboos -% fixed bug due to non-aligned vectors Rem and Lbl in subfunction readlay (thanks to pawel) -% -% Revision 1.23 2008/10/22 07:25:01 roboos -% undo the balancing of ctf meg channels prior to removing the unused coils -% -% Revision 1.22 2008/10/21 20:36:21 roboos -% (in grad2lay for ctf) prune the gradiometers to only contain meg -% channels and corresponding meg coils: this will not work for balanced -% gradiometers. -% -% Revision 1.21 2008/09/25 15:22:46 roboos -% fixed bug due to overlapping use of cfg.style, thanks to Tineke -% -% Revision 1.20 2008/09/25 12:55:52 roboos -% prevent x and y from being scaled in case of 3d layout, also don't add width, height, mask and outline for 3d -% -% Revision 1.19 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.18 2008/09/22 12:54:22 roboos -% added default handling for construction of outline and mask and for scaling the electrode positions to fith within unit circle -% -% Revision 1.17 2008/07/16 09:27:36 roboos -% added support for creating a layout based on a figure, including mask and outline for topoplot -% -% Revision 1.16 2008/06/25 06:36:06 roboos -% added option cfg.montage, computes average location for bipolar channels -% -% Revision 1.15 2008/05/14 19:17:24 roboos -% fixed bug for vladimirs neuromag306 example, removed spm specific documentation -% -% Revision 1.14 2008/05/14 13:53:30 roboos -% rotate only if needed -% -% Revision 1.13 2008/05/13 20:19:39 roboos -% changed senstype eeg into electrode -% -% Revision 1.12 2008/05/13 09:54:07 roboos -% added option cfg.style=2d|3d, used by SPM8 -% -% Revision 1.11 2008/05/06 13:16:56 roboos -% added option for writing *.lay files -% merged bti and ctf code -% -% Revision 1.10 2008/04/25 12:29:52 roboos -% slight improvement for ordered layout -% -% Revision 1.9 2008/03/05 10:46:36 roboos -% moved electrode reading functionality from read_fcdc_elec to read_sens, switched to the use of the new function -% -% Revision 1.8 2007/12/12 09:59:10 roboos -% use cfg.feedback instead of global fb variable -% -% Revision 1.7 2007/11/05 09:43:31 roboos -% only whitespace -% -% Revision 1.6 2007/05/06 09:06:37 roboos -% implemented layout=ordered, for multiplotting only -% -% Revision 1.5 2007/03/21 15:52:30 roboos -% included the cfg.layout=lay case in the if-ladder -% -% Revision 1.4 2007/03/21 14:17:28 chrhes -% added a check to detect the (unlikely) case where cfg.layout already contains -% a valid layout (lay) structure, which is then returned as is; added a few -% comments to code; updated documentation. -% -% Revision 1.3 2007/03/20 10:41:30 roboos -% added options cfg.rotate and cfg.projection -% changed the default projection method from stereographic into orthographic -% by default rotate MEG electrode positions 90 degrees around the z-axis -% changed the default rotation for some MEG systems (now it is more explicit in -% the code) -% -% Revision 1.2 2007/03/20 09:23:23 chrhes -% small change to subfunction grad2lay which allows for MEG channel labels that -% do not have a space after the "MEG" token in the cases of neuromag122 and -% neuromag306 data -% -% Revision 1.1 2007/03/14 08:44:29 roboos -% new function that replaces private/createlayout, this new function can be used -% by end-users added support for mat files containing a lay variable, made some -% changes to the lay structure -% - -% Undocumented option: -% cfg.layout can contain a lay structure which is simply returned as is - -fieldtripdefs - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% basic check/initialization of input arguments -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if (nargin<1) || (nargin>2), error('incorrect number of input arguments'); end; -if (nargin<2), data = []; end; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% set default configuration options -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if ~isfield(cfg, 'rotate'), cfg.rotate = []; end % [] => rotation is determined based on the type of sensors -if ~isfield(cfg, 'style'), cfg.style = '2d'; end -if ~isfield(cfg, 'projection'), cfg.projection = 'polar'; end -if ~isfield(cfg, 'layout'), cfg.layout = []; end -if ~isfield(cfg, 'grad'), cfg.grad = []; end -if ~isfield(cfg, 'elec'), cfg.elec = []; end -if ~isfield(cfg, 'gradfile'), cfg.gradfile = []; end -if ~isfield(cfg, 'elecfile'), cfg.elecfile = []; end -if ~isfield(cfg, 'output'), cfg.output = []; end -if ~isfield(cfg, 'feedback'), cfg.feedback = 'no'; end -if ~isfield(cfg, 'montage'), cfg.montage = 'no'; end -if ~isfield(cfg, 'image'), cfg.image = []; end -if ~isfield(cfg, 'bw'), cfg.bw = 0; end -if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end -if ~isfield(cfg, 'skipscale'), cfg.skipscale = 'no'; end -if ~isfield(cfg, 'skipcomnt'), cfg.skipcomnt = 'no'; end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% try to generate the layout structure -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - -skipscale = strcmp(cfg.skipscale, 'yes'); % in general a scale is desired -skipcomnt = strcmp(cfg.skipcomnt, 'yes'); % in general a comment desired - -if isa(cfg.layout, 'config') - % convert the nested config-object back into a normal structure - cfg.layout = struct(cfg.layout); -end - -% check whether cfg.layout already contains a valid layout structure (this can -% happen when higher level plotting functions are called with cfg.layout set to -% a lay structure) -if isstruct(cfg.layout) && isfield(cfg.layout, 'pos') && isfield(cfg.layout, 'label') && isfield(cfg.layout, 'width') && isfield(cfg.layout, 'height') - lay = cfg.layout; - -elseif isstruct(cfg.layout) && isfield(cfg.layout, 'pos') && isfield(cfg.layout, 'label') && (~isfield(cfg.layout, 'width') || ~isfield(cfg.layout, 'height')) - lay = cfg.layout; - % add width and height for multiplotting - d = dist(lay.pos'); - nchans = length(lay.label); - for i=1:nchans - d(i,i) = inf; % exclude the diagonal - end - mindist = min(d(:)); - lay.width = ones(nchans,1) * mindist * 0.8; - lay.height = ones(nchans,1) * mindist * 0.6; - -elseif isequal(cfg.layout, 'butterfly') - if nargin>1 && ~isempty(data) - % look at the data to determine the overlapping channels - cfg.channel = channelselection(cfg.channel, data.label); - chanindx = match_str(data.label, cfg.channel); - nchan = length(data.label(chanindx)); - lay.label = data.label(chanindx); - else - nchan = length(cfg.channel); - lay.label = cfg.channel; - end - lay.pos = zeros(nchan,2); % centered at (0,0) - lay.width = ones(nchan,1) * 1.0; - lay.height = ones(nchan,1) * 1.0; - lay.mask = {}; - lay.outline = {}; - skipscale = true; % a scale is not desired - skipcomnt = true; % a comment is initially not desired, or at least requires more thought - -elseif isequal(cfg.layout, 'vertical') - if nargin>1 && ~isempty(data) - % look at the data to determine the overlapping channels - cfg.channel = channelselection(cfg.channel, data.label); - chanindx = match_str(data.label, cfg.channel); - nchan = length(data.label(chanindx)); - lay.label = data.label(chanindx); - else - nchan = length(cfg.channel); - lay.label = cfg.channel; - end - for i=1:(nchan+2) - x = 0.5; - y = 1-i/(nchan+1+2); - lay.pos (i,:) = [x y]; - lay.width (i,1) = 0.9; - lay.height(i,1) = 0.9 * 1/(nchan+1+2); - if i==(nchan+1) - lay.label{i} = 'SCALE'; - elseif i==(nchan+2) - lay.label{i} = 'COMNT'; - end - end - lay.mask = {}; - lay.outline = {}; - -elseif isequal(cfg.layout, 'ordered') - if nargin>1 && ~isempty(data) - % look at the data to determine the overlapping channels - cfg.channel = channelselection(cfg.channel, data.label); - chanindx = match_str(data.label, cfg.channel); - nchan = length(data.label(chanindx)); - lay.label = data.label(chanindx); - else - nchan = length(cfg.channel); - lay.label = cfg.channel; - end - ncol = ceil(sqrt(nchan))+1; - nrow = ceil(sqrt(nchan))+1; - k = 0; - for i=1:nrow - for j=1:ncol - k = k+1; - if k<=nchan - x = (j-1)/ncol; - y = (nrow-i-1)/nrow; - lay.pos(k,:) = [x y]; - lay.width(k,1) = 0.8 * 1/ncol; - lay.height(k,1) = 0.8 * 1/nrow; - end - end - end - - lay.label{end+1} = 'SCALE'; - lay.width(end+1) = 0.8 * 1/ncol; - lay.height(end+1) = 0.8 * 1/nrow; - x = (ncol-2)/ncol; - y = 0/nrow; - lay.pos(end+1,:) = [x y]; - - lay.label{end+1} = 'COMNT'; - lay.width(end+1) = 0.8 * 1/ncol; - lay.height(end+1) = 0.8 * 1/nrow; - x = (ncol-1)/ncol; - y = 0/nrow; - lay.pos(end+1,:) = [x y]; - - % try to generate layout from other configuration options -elseif ischar(cfg.layout) && filetype(cfg.layout, 'matlab') - fprintf('reading layout from file %s\n', cfg.layout); - load(cfg.layout, 'lay'); - -elseif ischar(cfg.layout) && filetype(cfg.layout, 'layout') - fprintf('reading layout from file %s\n', cfg.layout); - lay = readlay(cfg.layout); - -elseif ischar(cfg.layout) && ~filetype(cfg.layout, 'layout') - % assume that cfg.layout is an electrode file - fprintf('creating layout from electrode file %s\n', cfg.layout); - lay = sens2lay(read_sens(cfg.layout), cfg.rotate, cfg.projection, cfg.style); - -elseif ischar(cfg.elecfile) - fprintf('creating layout from electrode file %s\n', cfg.elecfile); - lay = sens2lay(read_sens(cfg.elecfile), cfg.rotate, cfg.projection, cfg.style); - -elseif ~isempty(cfg.elec) && isstruct(cfg.elec) - fprintf('creating layout from cfg.elec\n'); - lay = sens2lay(cfg.elec, cfg.rotate, cfg.projection, cfg.style); - -elseif isfield(data, 'elec') && isstruct(data.elec) - fprintf('creating layout from data.elec\n'); - lay = sens2lay(data.elec, cfg.rotate, cfg.projection, cfg.style); - -elseif ischar(cfg.gradfile) - fprintf('creating layout from gradiometer file %s\n', cfg.gradfile); - lay = sens2lay(read_sens(cfg.gradfile), cfg.rotate, cfg.projection, cfg.style); - -elseif ~isempty(cfg.grad) && isstruct(cfg.grad) - fprintf('creating layout from cfg.grad\n'); - lay = sens2lay(cfg.grad, cfg.rotate, cfg.projection, cfg.style); - -elseif isfield(data, 'grad') && isstruct(data.grad) - fprintf('creating layout from data.grad\n'); - lay = sens2lay(data.grad, cfg.rotate, cfg.projection, cfg.style); - -elseif ~isempty(cfg.image) && isempty(cfg.layout) - fprintf('reading background image from %s\n', cfg.image); - img = imread(cfg.image); - img = flipdim(img, 1); % in combination with "axis xy" - - figure - bw = cfg.bw; - - if bw - % convert to greyscale image - img = mean(img, 3); - imagesc(img); - colormap gray - else - % plot as RGB image - image(img); - end - - hold on - axis equal - axis off - axis xy - - % get the electrode positions - pos = zeros(0,2); - electrodehelp = [ ... - '-----------------------------------------------------\n' ... - 'specify electrode locations\n' ... - 'press the right mouse button to add another electrode\n' ... - 'press backspace on the keyboard to remove the last electrode\n' ... - 'press "q" on the keyboard to continue\n' ... - ]; - again = 1; - while again - fprintf(electrodehelp) - disp(round(pos)); % values are integers/pixels - try - [x, y, k] = ginput(1); - catch - % this happens if the figure is closed - return; - end - - switch k - case 1 - pos = cat(1, pos, [x y]); - % add it to the figure - plot(x, y, 'b.'); - plot(x, y, 'yo'); - - case 8 - if size(pos,1)>0 - % remove the last point - pos = pos(1:end-1,:); - % completely redraw the figure - cla - h = image(img); - hold on - axis equal - axis off - plot(pos(:,1), pos(:,2), 'b.'); - plot(pos(:,1), pos(:,2), 'yo'); - end - - case 'q' - again = 0; - - otherwise - warning('invalid button (%d)', k); - end - end - - % get the mask outline - polygon = {}; - thispolygon = 1; - polygon{thispolygon} = zeros(0,2); - maskhelp = [ ... - '------------------------------------------------------------------------\n' ... - 'specify polygons for masking the topgraphic interpolation\n' ... - 'press the right mouse button to add another point to the current polygon\n' ... - 'press backspace on the keyboard to remove the last point\n' ... - 'press "c" on the keyboard to close this polygon and start with another\n' ... - 'press "q" on the keyboard to continue\n' ... - ]; - again = 1; - while again - fprintf(maskhelp); - fprintf('\n'); - for i=1:length(polygon) - fprintf('polygon %d has %d points\n', i, size(polygon{i},1)); - end - - try - [x, y, k] = ginput(1); - catch - % this happens if the figure is closed - return; - end - - switch k - case 1 - polygon{thispolygon} = cat(1, polygon{thispolygon}, [x y]); - % add the last line segment to the figure - if size(polygon{thispolygon},1)>1 - x = polygon{i}([end-1 end],1); - y = polygon{i}([end-1 end],2); - end - plot(x, y, 'g.-'); - - case 8 % backspace - if size(polygon{thispolygon},1)>0 - % remove the last point - polygon{thispolygon} = polygon{thispolygon}(1:end-1,:); - % completely redraw the figure - cla - h = image(img); - hold on - axis equal - axis off - % plot the electrode positions - plot(pos(:,1), pos(:,2), 'b.'); - plot(pos(:,1), pos(:,2), 'yo'); - for i=1:length(polygon) - x = polygon{i}(:,1); - y = polygon{i}(:,2); - if i~=thispolygon - % close the polygon in the figure - x(end) = x(1); - y(end) = y(1); - end - plot(x, y, 'g.-'); - end - end - - case 'c' - if size(polygon{thispolygon},1)>0 - % close the polygon - polygon{thispolygon}(end+1,:) = polygon{thispolygon}(1,:); - % close the polygon in the figure - x = polygon{i}([end-1 end],1); - y = polygon{i}([end-1 end],2); - plot(x, y, 'g.-'); - % switch to the next polygon - thispolygon = thispolygon + 1; - polygon{thispolygon} = zeros(0,2); - end - - case 'q' - if size(polygon{thispolygon},1)>0 - % close the polygon - polygon{thispolygon}(end+1,:) = polygon{thispolygon}(1,:); - % close the polygon in the figure - x = polygon{i}([end-1 end],1); - y = polygon{i}([end-1 end],2); - plot(x, y, 'g.-'); - end - again = 0; - - otherwise - warning('invalid button (%d)', k); - end - end - % remember this set of polygons as the mask - mask = polygon; - - - % get the outline, e.g. head shape and sulci - polygon = {}; - thispolygon = 1; - polygon{thispolygon} = zeros(0,2); - maskhelp = [ ... - '-----------------------------------------------------------------------------------\n' ... - 'specify polygons for adding outlines (e.g. head shape and sulci) to the layout\n' ... - 'press the right mouse button to add another point to the current polygon\n' ... - 'press backspace on the keyboard to remove the last point\n' ... - 'press "c" on the keyboard to close this polygon and start with another\n' ... - 'press "n" on the keyboard to start with another without closing the current polygon\n' ... - 'press "q" on the keyboard to continue\n' ... - ]; - again = 1; - while again - fprintf(maskhelp); - fprintf('\n'); - for i=1:length(polygon) - fprintf('polygon %d has %d points\n', i, size(polygon{i},1)); - end - - try - [x, y, k] = ginput(1); - catch - % this happens if the figure is closed - return; - end - - switch k - case 1 - polygon{thispolygon} = cat(1, polygon{thispolygon}, [x y]); - % add the last line segment to the figure - if size(polygon{thispolygon},1)>1 - x = polygon{i}([end-1 end],1); - y = polygon{i}([end-1 end],2); - end - plot(x, y, 'm.-'); - - case 8 % backspace - if size(polygon{thispolygon},1)>0 - % remove the last point - polygon{thispolygon} = polygon{thispolygon}(1:end-1,:); - % completely redraw the figure - cla - h = image(img); - hold on - axis equal - axis off - % plot the electrode positions - plot(pos(:,1), pos(:,2), 'b.'); - plot(pos(:,1), pos(:,2), 'yo'); - for i=1:length(polygon) - x = polygon{i}(:,1); - y = polygon{i}(:,2); - if i~=thispolygon - % close the polygon in the figure - x(end) = x(1); - y(end) = y(1); - end - plot(x, y, 'm.-'); - end - end - - case 'c' - if size(polygon{thispolygon},1)>0 - x = polygon{thispolygon}(1,1); - y = polygon{thispolygon}(1,2); - polygon{thispolygon} = cat(1, polygon{thispolygon}, [x y]); - % add the last line segment to the figure - x = polygon{i}([end-1 end],1); - y = polygon{i}([end-1 end],2); - plot(x, y, 'm.-'); - % switch to the next polygon - thispolygon = thispolygon + 1; - polygon{thispolygon} = zeros(0,2); - end - - case 'n' - if size(polygon{thispolygon},1)>0 - % switch to the next polygon - thispolygon = thispolygon + 1; - polygon{thispolygon} = zeros(0,2); - end - - case 'q' - again = 0; - - otherwise - warning('invalid button (%d)', k); - end - end - % remember this set of polygons as the outline - outline = polygon; - - % convert electrode positions into a layout structure - lay.pos = pos; - nchans = size(pos,1); - for i=1:nchans - lay.label{i,1} = sprintf('chan%03d', i); - end - % add width and height for multiplotting - d = dist(pos'); - for i=1:nchans - d(i,i) = inf; % exclude the diagonal - end - mindist = min(d(:)); - lay.width = ones(nchans,1) * mindist * 0.8; - lay.height = ones(nchans,1) * mindist * 0.6; - % add mask and outline polygons - lay.mask = mask; - lay.outline = outline; - -else - fprintf('reverting to 151 channel CTF default\n'); - lay = readlay('CTF151.lay'); -end - -% FIXME there is a conflict between the use of cfg.style here and in topoplot -if ~strcmp(cfg.style, '3d') - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % check whether outline and mask are available - % if not, add default "circle with triangle" to resemble the head - % in case of "circle with triangle", the electrode positions should also be - % scaled - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - if ~isfield(lay, 'outline') || ~isfield(lay, 'mask') - rmax = 0.5; - l = 0:2*pi/100:2*pi; - HeadX = cos(l).*rmax; - HeadY = sin(l).*rmax; - NoseX = [0.18*rmax 0 -0.18*rmax]; - NoseY = [rmax-.004 rmax*1.15 rmax-.004]; - EarX = [.497 .510 .518 .5299 .5419 .54 .547 .532 .510 .489]; - EarY = [.0555 .0775 .0783 .0746 .0555 -.0055 -.0932 -.1313 -.1384 -.1199]; - % Scale the electrode positions to fit within a unit circle, i.e. electrode radius = 0.45 - ind_scale = strmatch('SCALE', lay.label); - ind_comnt = strmatch('COMNT', lay.label); - sel = setdiff(1:length(lay.label), [ind_scale ind_comnt]); % these are excluded for scaling - x = lay.pos(sel,1); - y = lay.pos(sel,2); - xrange = range(x); - yrange = range(y); - % First scale the width and height of the box for multiplotting - lay.width = lay.width./xrange; - lay.height = lay.height./yrange; - % Then shift and scale the electrode positions - lay.pos(:,1) = 0.9*((lay.pos(:,1)-min(x))/xrange-0.5); - lay.pos(:,2) = 0.9*((lay.pos(:,2)-min(y))/yrange-0.5); - % Define the outline of the head, ears and nose - lay.outline{1} = [HeadX(:) HeadY(:)]; - lay.outline{2} = [NoseX(:) NoseY(:)]; - lay.outline{3} = [ EarX(:) EarY(:)]; - lay.outline{4} = [-EarX(:) EarY(:)]; - % Define the anatomical mask based on a circular head - lay.mask{1} = [HeadX(:) HeadY(:)]; - end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% apply the montage, i.e. combine bipolar channels into a new representation -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if ~strcmp(cfg.montage, 'no') - Norg = length(cfg.montage.labelorg); - Nnew = length(cfg.montage.labelnew); - - for i=1:Nnew - cfg.montage.tra(i,:) = abs(cfg.montage.tra(i,:)); - cfg.montage.tra(i,:) = cfg.montage.tra(i,:) ./ sum(cfg.montage.tra(i,:)); - end - % pretend it is a sensor structure, this achieves averaging after channel matching - tmp.tra = lay.pos; - tmp.label = lay.label; - new = apply_montage(tmp, cfg.montage); - lay.pos = new.tra; - lay.label = new.label; - % do the same for the width and height - tmp.tra = lay.width(:); - new = apply_montage(tmp, cfg.montage); - lay.width = new.tra; - tmp.tra = lay.height(:); - new = apply_montage(tmp, cfg.montage); - lay.height = new.tra; -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% add axes positions for comments and scale information if required -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if ~any(strcmp('COMNT', lay.label)) && strcmpi(cfg.style, '2d') && ~skipcomnt - % add a placeholder for the comment in the upper left corner - lay.label{end+1} = 'COMNT'; - lay.width(end+1) = mean(lay.width); - lay.height(end+1) = mean(lay.height); - X = min(lay.pos(:,1)); - Y = max(lay.pos(:,2)); - Y = min(lay.pos(:,2)); - lay.pos(end+1,:) = [X Y]; -elseif any(strcmp('COMNT', lay.label)) && skipcomnt - % remove the scale entry - sel = find(strcmp('COMNT', lay.label)); - lay.label(sel) = []; - lay.pos(sel,:) = []; - lay.width(sel) = []; - lay.height(sel) = []; -end - -if ~any(strcmp('SCALE', lay.label)) && strcmpi(cfg.style, '2d') && ~skipscale - % add a placeholder for the scale in the upper right corner - lay.label{end+1} = 'SCALE'; - lay.width(end+1) = mean(lay.width); - lay.height(end+1) = mean(lay.height); - X = max(lay.pos(:,1)); - Y = max(lay.pos(:,2)); - Y = min(lay.pos(:,2)); - lay.pos(end+1,:) = [X Y]; -elseif any(strcmp('SCALE', lay.label)) && skipscale - % remove the scale entry - sel = find(strcmp('SCALE', lay.label)); - lay.label(sel) = []; - lay.pos(sel,:) = []; - lay.width(sel) = []; - lay.height(sel) = []; -end - -% to plot the layout for debugging, you can use this code snippet -if strcmp(cfg.feedback, 'yes') && strcmpi(cfg.style, '2d') - tmpcfg = []; - tmpcfg.layout = lay; - layoutplot(tmpcfg); -end - -% to write the layout to a text file, you can use this code snippet -if ~isempty(cfg.output) && strcmpi(cfg.style, '2d') - fprintf('writing layout to ''%s''\n', cfg.output); - fid = fopen(cfg.output, 'wt'); - for i=1:numel(lay.label) - fprintf(fid, '%d %f %f %f %f %s\n', i, lay.pos(i,1), lay.pos(i,2), lay.width(i), lay.height(i), lay.label{i}); - end - fclose(fid); -elseif ~isempty(cfg.output) && strcmpi(cfg.style, '3d') - % the layout file format does not support 3D positions, furthermore for - % a 3D layout the width and height are currently set to NaN - error('writing a 3D layout to an output file is not supported'); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION -% read the layout information from the ascii file -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function lay = readlay(filename) -if ~exist(filename, 'file') - error(sprintf('could not open layout file: %s', filename)); -end -[chNum,X,Y,Width,Height,Lbl,Rem] = textread(filename,'%f %f %f %f %f %q %q'); - -if length(Rem)leadfield) -% -% Revision 1.8 2005/09/29 12:52:25 jansch -% changed column-wise normalisation into matrix-wise normalisation -% -% Revision 1.7 2005/09/29 10:37:08 jansch -% fixed bug in improper normalisation -% -% Revision 1.6 2005/06/29 12:46:29 roboos -% the following changes were done on a large number of files at the same time, not all of them may apply to this specific file -% - added try-catch around the inclusion of input data configuration -% - moved cfg.version, cfg.previous and the assignment of the output cfg to the end -% - changed help comments around the configuration handling -% - some changes in whitespace -% -% Revision 1.5 2005/06/08 13:40:33 roboos -% replaced the specific call to either meg_leadfield or eeg_leadfield to the generic compute_leadfield -% -% Revision 1.4 2005/05/17 17:50:37 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.3 2005/04/25 16:05:11 roboos -% includedupdated options for cortex segmentation based grid in the documentation (not in main documentation) -% -% Revision 1.2 2005/01/10 16:28:10 roboos -% some changes in order of code, no functional change -% -% Revision 1.1 2004/12/24 14:31:09 roboos -% Renamed precompute_leadfield into prepare_leadfield. For backward -% compatibility in peoples scripts, precompute_leadfield still will remain -% available for some time (it prints a warning and calls prepare_leadfield). -% The newly committed prepare_leadfield is a copy of precompute_leadfield -% revision 1.6. -% -% Revision 1.6 2004/12/08 18:00:13 roboos -% implemented consistent method of selecting a subset of channels for -% forward and inverse computations using cfg.channel and updated the -% ducumentation -% -% Revision 1.5 2004/10/27 16:13:53 roboos -% changed progress indication into private progress function -% added sel50p subspace projection -% -% Revision 1.4 2004/09/22 08:49:12 roboos -% added computation of LBEX -% -% Revision 1.3 2004/08/19 06:31:31 roboos -% removed consistency check for cfg.xgrid etc., this is now done in prepare_dipole_grid -% -% Revision 1.2 2004/08/17 08:53:55 roboos -% added cfg to the output, updated help -% -% Revision 1.1 2004/08/16 09:10:47 roboos -% initial version, this replaces the leadfield precomputation in sourceanalysis with some extra options -% - -fieldtripdefs -cfg = checkconfig(cfg, 'trackconfig', 'on'); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -if nargin<2 - data = []; -end - -% set the defaults -if ~isfield(cfg, 'normalize'), cfg.normalize = 'no'; end -if ~isfield(cfg, 'normalizeparam'), cfg.normalizeparam = 0.5; end -if ~isfield(cfg, 'lbex'), cfg.lbex = 'no'; end -if ~isfield(cfg, 'sel50p'), cfg.sel50p = 'no'; end -if ~isfield(cfg, 'feedback'), cfg.feedback = 'text'; end -if ~isfield(cfg, 'mollify'), cfg.mollify = 'no'; end -if ~isfield(cfg, 'patchsvd'), cfg.patchsvd = 'no'; end -% if ~isfield(cfg, 'reducerank'), cfg.reducerank = 'no'; end % the default for this depends on EEG/MEG and is set below - -% put the low-level options pertaining to the dipole grid in their own field -cfg = checkconfig(cfg, 'createsubcfg', {'grid'}); - -if strcmp(cfg.sel50p, 'yes') && strcmp(cfg.lbex, 'yes') - error('subspace projection with either lbex or sel50p is mutually exclusive'); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% collect and preprocess the electrodes/gradiometer and head model -[vol, sens, cfg] = prepare_headmodel(cfg, data); - -% set the default for reducing the rank of the leadfields -if ~isfield(cfg, 'reducerank') - if senstype(sens, 'eeg') - cfg.reducerank = 3; - else - cfg.reducerank = 2; - end -end - -% construct the grid on which the scanning will be done -[grid, cfg] = prepare_dipole_grid(cfg, vol, sens); - -progress('init', cfg.feedback, 'computing leadfield'); -for i=1:length(grid.inside) - % compute the leadfield on all grid positions inside the brain - progress(i/length(grid.inside), 'computing leadfield %d/%d\n', i, length(grid.inside)); - dipindx = grid.inside(i); - grid.leadfield{dipindx} = compute_leadfield(grid.pos(dipindx,:), sens, vol, 'reducerank', cfg.reducerank, 'normalize', cfg.normalize, 'normalizeparam', cfg.normalizeparam); - - if isfield(cfg, 'grid') && isfield(cfg.grid, 'mom') - % multiply with the normalized dipole moment to get the leadfield in the desired orientation - grid.leadfield{dipindx} = grid.leadfield{dipindx} * grid.mom(:,dipindx); - end - -end % for all grid locations inside the brain -progress('close'); - -% fill the positions outside the brain with NaNs -grid.leadfield(grid.outside) = {nan}; - -% mollify the leadfields -if ~strcmp(cfg.mollify, 'no') - grid = mollify(cfg, grid); -end - -% combine leadfields in patches and do an SVD on them -if ~strcmp(cfg.patchsvd, 'no') - grid = patchsvd(cfg, grid); -end - -% compute the 50 percent channel selection subspace projection -if ~strcmp(cfg.sel50p, 'no') - grid = sel50p(cfg, grid, sens); -end - -% compute the local basis function expansion (LBEX) subspace projection -if ~strcmp(cfg.lbex, 'no') - grid = lbex(cfg, grid); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: prepare_leadfield.m,v 1.30 2009/04/09 16:28:40 crimic Exp $'; -% remember the configuration details of the input data -try, cfg.previous = data.cfg; end -% remember the exact configuration details in the output -grid.cfg = cfg; - diff --git a/external/fieldtrip/private/prepare_localspheres.m b/external/fieldtrip/private/prepare_localspheres.m deleted file mode 100644 index c64c9f9..0000000 --- a/external/fieldtrip/private/prepare_localspheres.m +++ /dev/null @@ -1,276 +0,0 @@ -function [vol, cfg] = prepare_localspheres(cfg, mri) - -% PREPARE_LOCALSPHERES creates a MEG volume conductor model with a sphere -% for every sensor. You can also use it to create a single sphere -% model that is fitted to the MRI or to the head shape points. -% -% Use as -% [vol, cfg] = prepare_localspheres(cfg, seg), or -% [vol, cfg] = prepare_localspheres(cfg, mri), or -% [vol, cfg] = prepare_localspheres(cfg) -% -% The input configuration should contain -% cfg.grad = structure with gradiometer definition, or -% cfg.gradfile = filename containing gradiometer definition -% cfg.radius = number, which points to select for each channel (default = 7 cm) -% cfg.baseline = number, baseline of axial/planar gradiometer (default = 5 cm) -% cfg.feedback = 'yes' or 'no' (default = 'yes') -% cfg.singlesphere = 'yes' or 'no', fit only a single sphere (default = 'no') -% cfg.headshape = a filename containing headshape, a structure containing a -% single triangulated boundary, or a Nx3 matrix with surface -% points -% -% The following options are relevant if you use a segmented MRI -% cfg.smooth = 'no' or the FWHM of the gaussian kernel in voxels (default = 'no') -% cfg.mriunits = 'mm' or 'cm' (default = 'mm') -% cfg.sourceunits = 'mm' or 'cm' (default = 'cm') -% cfg.threshold = 0.5, relative to the maximum value in the segmentation -% -% This function implements -% Huang MX, Mosher JC, Leahy RM. -% A sensor-weighted overlapping-sphere head model and exhaustive head model comparison for MEG -% Phys Med Biol. 1999 Feb;44(2):423-40 - -% TODO cfg.spheremesh should be renamed consistently with other mesh generation cfgs -% TODO shape should contain pnt as subfield and not be equal to pnt (for consistency with other use of shape) -% -% Undocumented local options: -% cfg.spheremesh, number of points that is placed on the brain surface (default 4000) -% cfg.maxradius - -% Copyright (C) 2005-2006, Jan-Mathijs Schoffelen & Robert Oostenveld -% -% $Log: prepare_localspheres.m,v $ -% Revision 1.29 2009/07/29 06:40:41 roboos -% updated plotting functions -% -% Revision 1.28 2009/07/16 09:17:17 crimic -% link to prepare_mesh.m function -% -% Revision 1.27 2009/05/29 10:47:19 roboos -% only convert to struct in case headshape is specified -% -% Revision 1.26 2009/05/25 08:04:40 roboos -% fixed the name of the "headshape" variable -% ensure that cfg.headshape is a structure and not a config object -% -% Revision 1.25 2009/05/18 13:59:14 vlalit -% typo fix -% -% Revision 1.24 2009/05/14 19:21:36 roboos -% consistent handling of cfg.headshape in code and documentation -% -% Revision 1.23 2009/04/01 12:29:26 roboos -% added checkconfig -% -% Revision 1.22 2009/04/01 12:17:24 roboos -% use Taubin's method instead of optimization toolbox for fitting the sphere (thanks to Jean and Guillaume) -% -% Revision 1.21 2009/01/07 14:28:51 roboos -% do not open new figure but start with "clf" -% removed typicalx from optimization -% -% Revision 1.20 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.19 2008/08/13 21:02:20 roboos -% use general read_headshape instead of specific subfunctions -% -% Revision 1.18 2008/05/13 15:37:24 roboos -% switched to using read_data/header instead of the read_fcdc_data/header wrapper functions -% -% Revision 1.17 2007/08/06 09:20:14 roboos -% added support for bti_hs -% -% Revision 1.16 2007/07/26 08:02:10 roboos -% remove double vertices in headshape -% changed some indentation -% -% Revision 1.15 2006/10/09 15:25:00 roboos -% added option to fit only a single sphere to the MRI or headshape points -% -% Revision 1.14 2006/08/16 10:52:12 marsie -% fixed use of spm_smooth() -% -% Revision 1.13 2006/08/01 10:32:01 marsie -% fixed bug in using spm_smooth -% -% Revision 1.12 2006/07/27 08:29:38 roboos -% use spm_smooth instead of spm_conv, updated documentation -% -% Revision 1.11 2006/06/08 07:50:52 roboos -% updated the conversion between the source and MRI units (support mm,cm,dm,m for both) -% -% Revision 1.10 2006/06/07 09:34:19 roboos -% changed checktoolbox into hastoolbox -% -% Revision 1.9 2006/04/20 09:58:34 roboos -% updated documentation -% -% Revision 1.8 2006/04/18 19:04:35 roboos -% changed hard-coded 10000 vertex points for brain surface into cfg.spheremesh with default value of 4000 -% -% Revision 1.7 2006/04/05 15:07:37 roboos -% return the configuration as second argument, store the headshape points in the cfg -% -% Revision 1.6 2006/04/03 10:47:13 roboos -% pre-allocate memory to hold the result, ensure that the dimensions are correct (thanks to Hanneke) -% -% Revision 1.5 2006/03/21 09:45:07 roboos -% some irrelevant changes in the code flow to deal with presence/absence of segmented MRI input -% -% Revision 1.4 2006/03/09 08:18:34 roboos -% added code to use a segmented anatomical MRI, i.e. smooth and do edge detection -% with options similar to prepare_dipole_grid in gray matter -% updated help -% -% Revision 1.3 2006/02/06 21:22:28 roboos -% removed obvious dependency on CTF for reading hdr.grad -% -% Revision 1.2 2006/01/25 10:08:27 roboos -% added the complete implementation of this function, sofar it had been empty -% the implementation is based on code from jansch, which again was partially based on roboos' code -% -% Revision 1.1 2005/11/03 11:15:45 roboos -% new implementation -% - -fieldtripdefs - -cfg = checkconfig(cfg, 'trackconfig', 'on'); - -% set the defaults -if ~isfield(cfg, 'radius'), cfg.radius = 8.5; end -if ~isfield(cfg, 'maxradius'), cfg.maxradius = 20; end -if ~isfield(cfg, 'baseline'), cfg.baseline = 5; end -if ~isfield(cfg, 'feedback'), cfg.feedback = 'yes'; end -if ~isfield(cfg, 'smooth'); cfg.smooth = 5; end % in voxels -if ~isfield(cfg, 'mriunits'); cfg.mriunits = 'mm'; end -if ~isfield(cfg, 'sourceunits'), cfg.sourceunits = 'cm'; end -if ~isfield(cfg, 'threshold'), cfg.threshold = 0.5; end % relative -if ~isfield(cfg, 'spheremesh'), cfg.spheremesh = 4000; end -if ~isfield(cfg, 'singlesphere'), cfg.singlesphere = 'no'; end -if ~isfield(cfg, 'headshape'), cfg.headshape = []; end - -% construct the geometry of the headshape using a single boundary -if nargin==1 - headshape = prepare_mesh(cfg); -else - headshape = prepare_mesh(cfg, mri); -end - -% read the gradiometer definition from file or copy it from the configuration -if isfield(cfg, 'gradfile') - grad = read_sens(cfg.gradfile); -else - grad = cfg.grad; -end - -Nshape = size(headshape.pnt,1); -Nchan = size(grad.tra, 1); - -% set up an empty figure -if strcmp(cfg.feedback, 'yes') - clf - hold on - axis equal - axis vis3d - axis off - drawnow -end - -% plot all channels and headshape points -if strcmp(cfg.feedback, 'yes') - cla - plot_sens(grad); - plot_mesh(headshape, 'vertexcolor', 'g', 'facecolor', 'none', 'edgecolor', 'none'); - drawnow -end - -% fit a single sphere to all headshape points -[single_o, single_r] = fitsphere(headshape.pnt); -fprintf('single sphere, %5d surface points, center = [%4.1f %4.1f %4.1f], radius = %4.1f\n', Nshape, single_o(1), single_o(2), single_o(3), single_r); - -vol = []; - -if strcmp(cfg.singlesphere, 'yes') - % only return a single sphere - vol.r = single_r; - vol.o = single_o; - return; -end - -% start with an empty structure that will hold the results -vol.r = zeros(Nchan,1); % radius of every sphere -vol.o = zeros(Nchan,3); % origin of every sphere -vol.label = cell(Nchan,1); % corresponding gradiometer channel label for every sphere - -for chan=1:Nchan - coilsel = find(grad.tra(chan,:)~=0); - allpnt = grad.pnt(coilsel, :); % position of all coils belonging to this channel - allori = grad.ori(coilsel, :); % orientation of all coils belonging to this channel - - if strcmp(cfg.feedback, 'yes') - cla - plot3(grad.pnt(:,1), grad.pnt(:,2), grad.pnt(:,3), 'b.'); % all coils - plot3(allpnt(:,1), allpnt(:,2), allpnt(:,3), 'r*'); % this channel in red - end - - % determine the average position and orientation of this channel - thispnt = mean(allpnt,1); - [u, s, v] = svd(allori); - thisori = v(:,1)'; - if dot(thispnt,thisori)<0 - % the orientation should be outwards pointing - thisori = -thisori; - end - - % compute the distance from every coil along this channels orientation - dist = zeros(size(coilsel)); - for i=1:length(coilsel) - dist(i) = dot((allpnt(i,:)-thispnt), thisori); - end - - [m, i] = min(dist); - % check whether the minimum difference is larger than a typical distance - if abs(m)>(cfg.baseline/4) - % replace the position of this channel by the coil that is the closest to the head (axial gradiometer) - % except when the center of the channel is approximately just as good (planar gradiometer) - thispnt = allpnt(i,:); - end - - % find the headshape points that are close to this channel - dist = sqrt(sum((headshape.pnt-repmat(thispnt,Nshape,1)).^2, 2)); - shapesel = find(dist10 - [o, r] = fitsphere(headshape.pnt(shapesel,:)); - fprintf('channel = %s, %5d surface points, center = [%4.1f %4.1f %4.1f], radius = %4.1f\n', grad.label{chan}, length(shapesel), o(1), o(2), o(3), r); - else - fprintf('channel = %s, not enough surface points, using all points\n', grad.label{chan}); - o = single_o; - r = single_r; - end - - if r > cfg.maxradius - fprintf('channel = %s, not enough surface points, using all points\n', grad.label{chan}); - o = single_o; - r = single_r; - end - - % add this sphere to the volume conductor - vol.o(chan,:) = o; - vol.r(chan) = r; - vol.label{chan} = grad.label{chan}; -end % for all channels - -vol.type = 'multisphere'; - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - diff --git a/external/fieldtrip/private/prepare_mask.m b/external/fieldtrip/private/prepare_mask.m deleted file mode 100755 index b414cb9..0000000 --- a/external/fieldtrip/private/prepare_mask.m +++ /dev/null @@ -1,50 +0,0 @@ -function [mask] = prepare_mask(layout, varargin) -% PREPARE_MASK calculate anatomical mask only once, based only on layout -% Use as: -% [mask] = prepare_mask(layout, 'key', 'val'); -% with optional parameter: -% 'gridscale' scale of the interpolated grid (default: 67) -% -% See also COMPONENTBROWSER, DATABROWSER - -% Copyright (C) 2009 -% -% $Log: prepare_mask.m,v $ -% Revision 1.1 2009/07/15 08:40:54 giopia -% from topoplot, it relies on inside_contour -% - -% check the input -if ~isfield(layout, 'mask') - warning('prepare_mask:nomask', 'Mask is not present in layout. Mask not created'); - mask = []; - return -end - -[gridscale] = keyval('gridscale', varargin); -if isempty(gridscale); gridscale = 67; end - -% find limits for interpolation: -xmin = +inf; -xmax = -inf; -ymin = +inf; -ymax = -inf; - -for i=1:length(layout.mask) - xmin = min([xmin; layout.mask{i}(:,1)]); - xmax = max([xmax; layout.mask{i}(:,1)]); - ymin = min([ymin; layout.mask{i}(:,2)]); - ymax = max([ymax; layout.mask{i}(:,2)]); -end - -xi = linspace(xmin, xmax, gridscale); % x-axis for interpolation (row vector) -yi = linspace(ymin, ymax, gridscale); % y-axis for interpolation (row vector) -Xi = ones(gridscale,1)*xi; -Yi = (ones(gridscale,1)*yi)'; - -% apply anatomical mask to the data, i.e. that determines that the interpolated data outside the circle is not displayed -mask = false(gridscale); -for i=1:length(layout.mask) - layout.mask{i}(end+1,:) = layout.mask{i}(1,:); % force them to be closed - mask(inside_contour([Xi(:) Yi(:)], layout.mask{i})) = true; -end diff --git a/external/fieldtrip/private/prepare_mesh.m b/external/fieldtrip/private/prepare_mesh.m deleted file mode 100644 index 02c96cb..0000000 --- a/external/fieldtrip/private/prepare_mesh.m +++ /dev/null @@ -1,121 +0,0 @@ -function bnd = prepare_mesh(cfg, mri) - -% PREPARE_MESH creates a triangulated surface mesh for the volume -% conduction model. The mesh can either be selected manually from raw -% mri data or can be generated starting from a segmented volume -% information stored in the mri structure. The result is a bnd -% structure which contains the information about all segmented surfaces -% related to mri and are expressed in world coordinates. -% -% Use as -% bnd = prepare_mesh(cfg, mri) -% -% Configuration options: -% cfg.method = 'segmentation' or 'manual' -% cfg.tissue = list with segmentation values corresponding with each compartment -% cfg.downsample = integer (1,2, ...) defines the level of refinement of the mri data -% cfg.headshape = a filename containing headshape, a Nx3 matrix with surface -% points, or a structure with a single or multiple boundaries -% -% Example use: -% mri = read_mri('Subject01.mri'); -% cfg = []; -% cfg.method = 'manual'; -% cfg.downsample = 2; -% bnd = prepare_mesh(cfg, mri); - -% Copyrights (C) 2009, Cristiano Micheli & Robert Oostenveld -% -% $Log: prepare_mesh.m,v $ -% Revision 1.11 2009/07/29 06:43:16 roboos -% fixed basedonseg for headshape input (thanks to Vladimir) -% -% Revision 1.10 2009/07/16 09:00:51 crimic -% added choice of multiple mesh methods and fixed a small typo -% -% Revision 1.9 2009/06/17 13:38:41 roboos -% cleaned up handling of method=manual -% -% Revision 1.8 2009/06/15 14:01:08 roboos -% minor updates in documentation and default cfg -% -% Revision 1.7 2009/06/03 12:07:11 crimic -% changed help -% -% Revision 1.6 2009/06/03 12:05:06 crimic -% added cfg.numcompartments option as input for automatic segmentation -% -% Revision 1.5 2009/06/02 10:18:39 crimic -% minor changes -% -% Revision 1.4 2009/05/14 19:23:33 roboos -% small cleanup, nothing functionally changed -% -% Revision 1.3 2009/05/06 16:09:17 roboos -% renamed gui_mesh into prepare_mesh_manual and moved to private -% some cleanup of the code -% -% Revision 1.2 2009/05/06 08:46:29 crimic -% First implementation -% - -cfg = checkconfig(cfg, 'forbidden', 'numcompartments'); - -% set the defaults -if ~isfield(cfg, 'downsample'), cfg.downsample = 1; end -if ~isfield(cfg, 'tissue'), cfg.tissue = []; end -if ~isfield(cfg, 'numvertices'), cfg.numvertices = []; end - -if isfield(cfg, 'headshape') && isa(cfg.headshape, 'config') - % convert the nested cmethodonfig-object back into a normal structure - cfg.headshape = struct(cfg.headshape); -end - -% there are three types of input possible -if nargin>1 && (~isfield(cfg,'headshape') || isempty(cfg.headshape)) - basedonseg = isfield(mri, 'transform') && any(isfield(mri, {'seg', 'csf', 'white', 'gray'})); - basedonmri = isfield(mri, 'transform') && ~basedonseg; - basedonvol = isfield(mri, 'bnd'); - basedonheadshape = 0; -elseif nargin==1 && isfield(cfg,'headshape') && ~isempty(cfg.headshape) - basedonseg = 0; - basedonmri = 0; - basedonvol = 0; - basedonheadshape = 1; -else - error('inconsistent configuration, cfg.headshape should not be used in combination with an mri input') -end - -if basedonseg || basedonmri - % optionally downsample the anatomical MRI and/or the tissue segmentation - tmpcfg = []; - tmpcfg.downsample = cfg.downsample; - mri = volumedownsample(tmpcfg, mri); -end - -if basedonseg - fprintf('using the segmentation approach\n'); - bnd = prepare_mesh_segmentation(cfg, mri); - -elseif basedonmri - fprintf('using the manual approach\n'); - bnd = prepare_mesh_manual(cfg, mri); - -elseif basedonheadshape - fprintf('using the head shape to construct a triangulated mesh\n'); - bnd = prepare_mesh_headshape(cfg); - -elseif basedonvol - fprintf('using the mesh specified in the input volume conductor\n'); - bnd = mri.bnd; - -else - error('unsupported cfg.method and/or input') -end - -% ensure that the vertices and triangles are double precision, otherwise the bemcp mex files will crash -for i=1:length(bnd) - bnd(i).pnt = double(bnd(i).pnt); - bnd(i).tri = double(bnd(i).tri); -end - diff --git a/external/fieldtrip/private/prepare_mesh_headshape.m b/external/fieldtrip/private/prepare_mesh_headshape.m index 157f361..691ba89 100644 --- a/external/fieldtrip/private/prepare_mesh_headshape.m +++ b/external/fieldtrip/private/prepare_mesh_headshape.m @@ -6,13 +6,23 @@ % Copyrights (C) 2009, Robert Oostenveld % -% $Log: prepare_mesh_headshape.m,v $ -% Revision 1.2 2009/09/09 14:34:55 roboos -% fixed bug in case the input consisted of multiple boundaries +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.1 2009/07/13 14:45:06 crimic -% copy code of existin funtions into stand-alone functions for inclusion in the prepare_mesh helper function +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: prepare_mesh_headshape.m 952 2010-04-21 18:29:51Z roboos $ % get the surface describing the head shape if isstruct(cfg.headshape) && isfield(cfg.headshape, 'pnt') diff --git a/external/fieldtrip/private/prepare_mesh_manual.m b/external/fieldtrip/private/prepare_mesh_manual.m index 8a0544d..035efe2 100644 --- a/external/fieldtrip/private/prepare_mesh_manual.m +++ b/external/fieldtrip/private/prepare_mesh_manual.m @@ -15,41 +15,23 @@ % Copyrights (C) 2009, Cristiano Micheli & Robert Oostenveld % -% $Log: prepare_mesh_manual.m,v $ -% Revision 1.10 2009/08/31 11:13:45 crimic -% minibug fix +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.9 2009/08/27 16:12:13 crimic -% minibug fix +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.8 2009/07/13 14:43:05 crimic -% inserted spherical harmonics sub-functions +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.7 2009/06/30 11:45:38 roboos -% renamed select_point2d function call -% -% Revision 1.6 2009/06/26 14:33:28 crimic -% added mesh smoothing option and subfunctions -% -% Revision 1.5 2009/06/26 13:06:21 crimic -% point delete function implemented -% -% Revision 1.4 2009/06/17 13:37:11 roboos -% used autoindentation to clean up whitespace -% -% Revision 1.3 2009/06/03 11:29:59 crimic -% small fixes -% -% Revision 1.2 2009/06/03 10:36:29 crimic -% changes of layout and small fixes -% -% Revision 1.1 2009/05/06 16:09:17 roboos -% renamed gui_mesh into prepare_mesh_manual and moved to private -% some cleanup of the code -% -% Revision 1.1 2009/05/06 13:55:37 crimic -% First implementation +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: prepare_mesh_manual.m 1431 2010-07-20 07:47:55Z roboos $ % FIXME: control slice's cmap referred to abs values % FIXME: clean structure slicedata @@ -625,7 +607,7 @@ function erase_points2d (obj) % 2d slice selected box boundaries if strcmp(get(obj,'string'),'box') - [x, y] = select_box; + [x, y] = ft_select_box; rowmin = min(y); rowmax = max(y); colmin = min(x); colmax = max(x); box = getappdata(fig,'box'); @@ -634,7 +616,7 @@ function erase_points2d (obj) else % converts lines to points pos = slicedata2pnts(prop{1},prop{2}); - tmp = select_point(pos); + tmp = ft_select_point(pos); point2mark.x = tmp(1); point2mark.y = tmp(2); setappdata(fig,'point2mark',point2mark); end @@ -790,7 +772,8 @@ function view_mesh(hObject, eventdata, handles) bnd.pnt = pnt_; bnd.tri = tri; slicedata = getappdata(fig,'slicedata'); - figure,plot_mesh(bnd,'vertexcolor','k') + figure + ft_plot_mesh(bnd,'vertexcolor','k'); end function cancel_mesh(hObject, eventdata, handles) diff --git a/external/fieldtrip/private/prepare_mesh_segmentation.m b/external/fieldtrip/private/prepare_mesh_segmentation.m index 349d54a..7aaf21c 100644 --- a/external/fieldtrip/private/prepare_mesh_segmentation.m +++ b/external/fieldtrip/private/prepare_mesh_segmentation.m @@ -6,19 +6,22 @@ % Copyrights (C) 2009, Robert Oostenveld % -% $Log: prepare_mesh_segmentation.m,v $ -% Revision 1.4 2009/08/11 12:47:20 jansch -% fixed bug in assignment of default cfg.threshold -% -% Revision 1.3 2009/07/17 10:10:56 crimic -% added initial checks and variables consinstency -% -% Revision 1.2 2009/07/16 15:30:55 crimic -% fixed tiny error -% -% Revision 1.1 2009/07/13 14:45:06 crimic -% copy code of existing functions into stand-alone functions for inclusion in the prepare_mesh helper function -% +% Subversion does not use the Log keyword, use 'svn log ' or 'svn -v log | less' to get detailled information + +needspm = isfield(cfg, 'smooth') && ~strcmp(cfg.smooth, 'no'); +if needspm + % check if SPM is in path and if not add + hasspm2 = hastoolbox('SPM2'); + hasspm8 = hastoolbox('SPM8'); + + if ~hasspm2 && ~hasspm8 + try, hasspm8 = hastoolbox('SPM8', 1); end + end + + if ~hasspm8 + try, hastoolbox('SPM2', 1); end + end +end % some initial checks cfg = checkconfig(cfg, 'forbidden', 'numcompartments'); @@ -44,8 +47,6 @@ mri.seg = mri.seg | (mri.csf>(cfg.threshold*max(mri.csf(:)))); end if ~strcmp(cfg.smooth, 'no'), - % check whether the required SPM2 toolbox is available - hastoolbox('spm2', 1); fprintf('smoothing the segmentation with a %d-pixel FWHM kernel\n',cfg.smooth); mri.seg = double(mri.seg); spm_smooth(mri.seg, mri.seg, cfg.smooth); diff --git a/external/fieldtrip/private/prepare_resampled_data.m b/external/fieldtrip/private/prepare_resampled_data.m index b54b046..3ba573c 100644 --- a/external/fieldtrip/private/prepare_resampled_data.m +++ b/external/fieldtrip/private/prepare_resampled_data.m @@ -46,43 +46,23 @@ % Copyright (C) 2004, Robert Oostenveld % -% $Log: prepare_resampled_data.m,v $ -% Revision 1.11 2006/07/04 16:04:50 roboos -% renamed option 'jacknife' into 'jackknife' for consistency, maintain backward compatibility with cfgs and old data +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.10 2005/05/17 17:50:49 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.9 2005/03/03 13:57:35 roboos -% implemented pseudovalue resampling, i.e. a combination of jackknife and the complete average +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.8 2004/10/13 11:23:12 roboos -% changed indentation, I am not sure whether code was changed -% -% Revision 1.7 2004/09/22 13:38:21 roboos -% replaced personal fac function by prod(1:x) to compute x! -% -% Revision 1.6 2004/09/21 14:39:03 roboos -% fixed bug related to previous fix -% -% Revision 1.5 2004/09/21 14:36:05 roboos -% fixed bug in averaging when different conditions have different number of replications -% -% Revision 1.4 2004/09/21 12:26:23 roboos -% added FIXME comment -% -% Revision 1.3 2004/09/20 09:18:56 roboos -% fixed bug in permutation, the number of permutations was hardcoded to 10 -% -% Revision 1.2 2004/09/13 08:27:08 roboos -% implemented permutation for multiple conditions -% -% Revision 1.1 2004/09/08 16:37:48 roboos -% new implementation based on the functionality that was already present in sourceanalysis -% it facilitates updating the different resampling strategies for the different beamformers -% and this separate subfunction can now also be used by other algorithms +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: prepare_resampled_data.m 952 2010-04-21 18:29:51Z roboos $ % for backward compatibility with misspelled configuration option if isfield(cfg, 'jacknife'), cfg.jackknife = cfg.jacknife; cfg = rmfield(cfg, 'jacknife'); end @@ -363,8 +343,8 @@ % into a selection array that can be used as indices into the concatenated data tmp = []; for r=1:cfg.numpermutation - sel1 = (1:Nreplication) + (permute(r,:)==0)*Nreplication; % select the trials assigned to condition 1 - sel2 = (1:Nreplication) + (permute(r,:)==1)*Nreplication; % select the trials assigned to condition 2 + sel1 = (1:Nreplication) + (permute(r,:)==0)*Nreplication; % select the trials assigned to condition 1 + sel2 = (1:Nreplication) + (permute(r,:)==1)*Nreplication; % select the trials assigned to condition 2 tmp(r,:) = [sel1 sel2]; end permute = tmp; @@ -381,11 +361,11 @@ error('it is not possible to generate all possible permutations for more than two conditions'); end allperms = sortrows(perms(1:Ncondition)); - numperms = prod(1:Ncondition); % equal to size(allperms,1) + numperms = prod(1:Ncondition); % equal to size(allperms,1) permute = zeros(cfg.numpermutation, Ncondition*Nreplication); for r=1:cfg.numpermutation % select one of the possible permutations for every trial - sel = floor(rand(1,Nreplication)*numperms) + 1; + sel = floor(rand(1,Nreplication)*numperms) + 1; tmp = allperms(sel,:); % convert to a list that can be used as indices into the concatenated data tmp = (tmp-1)*Nreplication + repmat((1:Nreplication)', [1 Ncondition]); diff --git a/external/fieldtrip/private/prepare_singleshell.m b/external/fieldtrip/private/prepare_singleshell.m deleted file mode 100644 index 914d7f8..0000000 --- a/external/fieldtrip/private/prepare_singleshell.m +++ /dev/null @@ -1,132 +0,0 @@ -function [vol, cfg] = prepare_singleshell(cfg, mri) - -% PREPARE_SINGLESHELL creates a simple and fast method for the MEG forward -% calculation for one shell of arbitrary shape. This is based on a -% correction of the lead field for a spherical volume conductor by a -% superposition of basis functions, gradients of harmonic functions -% constructed from spherical harmonics. -% -% Use as -% [vol, cfg] = prepare_singleshell(cfg, seg), or -% [vol, cfg] = prepare_singleshell(cfg, mri), or -% [vol, cfg] = prepare_singleshell(cfg) -% -% If you do not use a segmented MRI, the configuration should contain -% cfg.headshape = a filename containing headshape, a structure containing a -% single triangulated boundary, or a Nx3 matrix with surface -% points -% cfg.numvertices = number, to retriangulate the mesh with a sphere (default = 3000) -% instead of specifying a number, you can specify 'same' to keep the -% vertices of the mesh identical to the original headshape points -% -% The following options are relevant if you use a segmented MRI -% cfg.smooth = 'no' or the FWHM of the gaussian kernel in voxels (default = 5) -% cfg.mriunits = 'mm' or 'cm' (default is 'mm') -% cfg.sourceunits = 'mm' or 'cm' (default is 'cm') -% cfg.threshold = 0.5, relative to the maximum value in the segmentation -% -% This function implements -% G. Nolte, "The magnetic lead field theorem in the quasi-static -% approximation and its use for magnetoencephalography forward calculation -% in realistic volume conductors", Phys Med Biol. 2003 Nov 21;48(22):3637-52. - -% TODO the spheremesh option should be renamed consistently with other mesh generation cfgs -% TODO shape should contain pnt as subfield and not be equal to pnt (for consistency with other use of shape) - -% Copyright (C) 2006-2007, Robert Oostenveld -% -% $Log: prepare_singleshell.m,v $ -% Revision 1.22 2009/07/16 09:08:32 crimic -% added link with prepare_mesh function -% -% Revision 1.21 2009/05/29 12:31:04 roboos -% only convert cfg.headshape from config to struct in case it is present -% -% Revision 1.20 2009/05/25 08:05:18 roboos -% ensure that cfg.headshape is a sturct and not a config object (in case tracking is on) -% -% Revision 1.19 2009/05/18 07:34:04 marvger -% fixed bugs introduced by the previous update -% -% Revision 1.18 2009/05/14 19:22:13 roboos -% consistent handling of cfg.headshape in code and documentation -% -% Revision 1.17 2009/04/01 12:29:26 roboos -% added checkconfig -% -% Revision 1.16 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.15 2008/08/13 21:02:20 roboos -% use general read_headshape instead of specific subfunctions -% -% Revision 1.14 2008/07/31 16:10:33 roboos -% corrected documentation for default smooth=5 -% -% Revision 1.13 2008/04/10 08:03:11 roboos -% renamed the fieldtrip/private/prepare_vol_sens function into prepare_headmodel -% -% Revision 1.12 2007/08/06 09:20:14 roboos -% added support for bti_hs -% -% Revision 1.11 2007/07/26 07:11:47 roboos -% remove double vertices when possible (twice) -% implemented cfg.sphremesh=same -% updated documentation -% -% Revision 1.10 2007/04/19 17:15:15 roboos -% retriangulate headshape to the desired number of vertices -% -% Revision 1.9 2006/08/16 10:52:30 marsie -% fixed use of spm_smooth() -% -% Revision 1.8 2006/08/01 10:31:03 marsie -% fixed bug in using spm_smooth -% -% Revision 1.7 2006/07/27 08:29:38 roboos -% use spm_smooth instead of spm_conv, updated documentation -% -% Revision 1.6 2006/06/08 07:50:53 roboos -% updated the conversion between the source and MRI units (support mm,cm,dm,m for both) -% -% Revision 1.5 2006/06/07 15:50:36 roboos -% changed checktoolbox into hastoolbox -% -% Revision 1.4 2006/04/18 19:04:35 roboos -% changed hard-coded 10000 vertex points for brain surface into cfg.spheremesh with default value of 4000 -% -% Revision 1.3 2006/04/05 16:09:48 roboos -% forgot to add cfg to output in previous commit -% -% Revision 1.2 2006/04/05 15:07:37 roboos -% return the configuration as second argument, store the headshape points in the cfg -% -% Revision 1.1 2006/03/21 09:41:46 roboos -% new implementation, mainly copy and paste from prepare_localspheres -% - -fieldtripdefs - -cfg = checkconfig(cfg, 'trackconfig', 'on'); -cfg = checkconfig(cfg, 'renamed', {'spheremesh', 'numvertices'}); - -% set the defaults -if ~isfield(cfg, 'smooth'); cfg.smooth = 5; end % in voxels -if ~isfield(cfg, 'mriunits'); cfg.mriunits = 'mm'; end -if ~isfield(cfg, 'sourceunits'), cfg.sourceunits = 'cm'; end -if ~isfield(cfg, 'threshold'), cfg.threshold = 0.5; end % relative -if ~isfield(cfg, 'spheremesh'), cfg.numvertices = 4000; end % approximate number of vertices in sphere - -% construct the geometry of the volume conductor model, containing a single boundary -% the initialization of the forward computation code is done later in prepare_headmodel -vol = []; -if nargin==1 - vol.bnd = prepare_mesh(cfg); -else - vol.bnd = prepare_mesh(cfg, mri); -end -vol.type = 'nolte'; - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - diff --git a/external/fieldtrip/private/prepare_timefreq_data.m b/external/fieldtrip/private/prepare_timefreq_data.m index a944d88..133ec99 100644 --- a/external/fieldtrip/private/prepare_timefreq_data.m +++ b/external/fieldtrip/private/prepare_timefreq_data.m @@ -34,112 +34,23 @@ % Copyright (C) 2004, Robert Oostenveld % -% $Log: prepare_timefreq_data.m,v $ -% Revision 1.28 2009/01/26 12:44:38 marvger -% added control condition when computing output.dof; computed -% incorrectly for single trial data. probably needs a more elegant solution. +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.27 2006/09/05 10:42:25 roboos -% added fixdimord for backward compatibility with old data (toi->time etc) +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.26 2006/05/08 09:02:02 roboos -% fixed bug in assesment of the dimensionality and size of the data, relevant vor averaging over time or frequencies +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.25 2006/03/21 15:03:43 roboos -% added support for fourier data, not yet keeping track of tapers and trials -% -% Revision 1.24 2006/02/28 12:18:16 erimar -% Added handling of degrees of freedom, which may be passed by freqanalysis. -% -% Revision 1.23 2006/02/23 10:28:17 roboos -% changed dimord strings for consistency, changed toi and foi into time and freq, added fixdimord where neccessary -% -% Revision 1.22 2005/05/17 17:50:49 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.21 2005/04/05 06:54:08 roboos -% fixed bug in data selectino which occurred when the order of the channels was different in the different input datasets -% -% Revision 1.20 2005/03/23 08:01:27 roboos -% fixed typing mistake, causing invalid assignment of variable size -% -% Revision 1.19 2005/03/23 07:25:18 roboos -% extended support for single precision to ERPs and power -% fixed bug with singleton dimensions for frequency and time-selection -% -% Revision 1.18 2005/01/19 12:39:56 erimar -% Added pack for efficient memory use. -% -% Revision 1.17 2004/11/22 08:45:25 roboos -% fixed bug in data.label for avgoverchan (was string instead of cell-array) -% -% Revision 1.16 2004/11/19 09:12:40 roboos -% fixed bug in sprintf with cell-array -% -% Revision 1.15 2004/11/10 12:57:54 erimar -% correct wrong Nfreq and Ntime values (made them dataset-dependent) -% -% Revision 1.14 2004/11/09 15:53:17 roboos -% fixed bug in the separate handling of chansel for cross- and auto-spectra -% -% Revision 1.13 2004/11/09 13:59:17 roboos -% fixed bug in checking whether all chan/freq/time bins were selected -% -% Revision 1.12 2004/11/08 13:06:53 roboos -% made changes to improve memory efficiency, mainly for concatenated output and cross-spectra -% implemented single-precision output datatype (cfg.precision) -% split handling of auto- and cross-spectra in forcedimord -% made avgoverdim optional, do not call if avgdim is empty -% made dataselection optional, do not explicitely select if the selection contains everything -% -% Revision 1.11 2004/11/02 11:33:19 roboos -% fixed double concatenation of power and cross-spectra -% improved output of time/freq axis if time/freq is not present in data -% -% Revision 1.10 2004/11/01 15:55:43 roboos -% fixed hascrsspctrm in forcedimord for ERP input data -% -% Revision 1.9 2004/11/01 13:51:03 roboos -% fixed bug in labelcmb v.s. channelcmb -% fixed bug in default channelcmb -% print either the string "channels" or "channelcombinations" in fprintf feedback -% cleaned up internal handling of label and labelcombinatinos using two subfunctions that convert between the two representations -% -% Revision 1.8 2004/10/29 11:34:16 roboos -% cleaned up the code on many places -% renamed subfunction in forcedimord -% made permute and reshape in forcedimord conditional -% -% Revision 1.7 2004/10/29 09:45:54 roboos -% complete redesign with numerous changes, with the most important ones being: -% added support for data in matlab files -% attempt to make memory efficient -% output dimord is fixed repl_chan_freq_time -% added output design matrix (in case of concatenated) -% -% Revision 1.6 2004/10/22 16:26:04 roboos -% added default for cfg.channelcmb -% added backward compatibility support for ERPs without dimord -% fixed some small bugs -% -% Revision 1.5 2004/10/22 10:48:28 roboos -% implemented support for cross-spectra and selec tion of channel combinations -% -% Revision 1.4 2004/10/13 14:11:30 roboos -% changed cfg.previous, now consistent over functions with try-statement -% and will also work if the input already had a cfg.previous -% -% Revision 1.3 2004/10/13 11:24:03 roboos -% added support for cfg.datarepresentation = 'cell-array' or 'concatenated' -% -% Revision 1.2 2004/10/12 13:51:19 roboos -% implemented avgoverchan/freq/time -% many general improvements -% -% Revision 1.1 2004/10/06 15:12:13 roboos -% initial implementation to serve as subfunction for main statistical functions +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: prepare_timefreq_data.m 1189 2010-06-02 15:34:31Z vlalit $ % set the defaults if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end @@ -209,7 +120,7 @@ for c=1:Nvarargin % match the channel selection with this dataset - cfg.channel = channelselection(cfg.channel, remember{c}.label); + cfg.channel = ft_channelselection(cfg.channel, remember{c}.label); % match the selected latency with this dataset if isempty(findstr(remember{c}.dimord, 'time')) || all(isnan(remember{c}.time)) @@ -311,7 +222,6 @@ avgdim = [avgdim freqdim]; end -pack; % this will hold the output data if strcmp(cfg.datarepresentation, 'cell-array') dat = {}; @@ -535,7 +445,7 @@ [st, i] = dbstack; cfg.version.name = st(i).name; end -cfg.version.id = '$Id: prepare_timefreq_data.m,v 1.28 2009/01/26 12:44:38 marvger Exp $'; +cfg.version.id = '$Id: prepare_timefreq_data.m 1189 2010-06-02 15:34:31Z vlalit $'; cfg.previous = []; % remember the configuration details from the input data diff --git a/external/fieldtrip/private/prepare_vol_sens.m b/external/fieldtrip/private/prepare_vol_sens.m deleted file mode 100644 index f658297..0000000 --- a/external/fieldtrip/private/prepare_vol_sens.m +++ /dev/null @@ -1,419 +0,0 @@ -function [vol, sens] = prepare_vol_sens(vol, sens, varargin) - -% PREPARE_VOL_SENS does some bookkeeping to ensure that the volume -% conductor model and the sensor array are ready for subsequent forward -% leadfield computations. It takes care of some pre-computations that can -% be done efficiently prior to the leadfield calculations. -% -% Use as -% [vol, sens] = prepare_vol_sens(vol, sens, ...) -% with input arguments -% sens structure with gradiometer or electrode definition -% vol structure with volume conductor definition -% -% The vol structure represents a volume conductor model, its contents -% depend on the type of model. The sens structure represents a sensor -% array, i.e. EEG electrodes or MEG gradiometers. -% -% Additional options should be specified in key-value pairs and can be -% 'channel' cell-array with strings (default = 'all') -% 'order' number, for single shell "Nolte" model (default = 10) -% -% The detailled behaviour of this function depends on whether the input -% consists of EEG or MEG and furthermoree depends on the type of volume -% conductor model: -% - in case of EEG single and concentric sphere models, the electrodes are -% projected onto the skin surface. -% - in case of EEG boundary element models, the electrodes are projected on -% the surface and a blilinear interpoaltion matrix from vertices to -% electrodes is computed. -% - in case of MEG and a multispheres model, a local sphere is determined -% for each coil in the gradiometer definition. -% - in case of MEG with a singleshell Nolte model, the volume conduction -% model is initialized -% In any case channel selection and reordering will be done. The channel -% order returned by this function corresponds to the order in the 'channel' -% option, or if not specified, to the order in the input sensor array. -% -% See also READ_VOL, READ_SENS, TRANSFORM_VOL, TRANSFORM_SENS, COMPUTE_LEADFIELD - -% Copyright (C) 2004-2009, Robert Oostenveld -% -% $Log: prepare_vol_sens.m,v $ -% Revision 1.21 2009/09/27 19:12:38 crimic -% wrapper adapted for openmeeg forward solution -% -% Revision 1.20 2009/09/21 11:12:51 roboos -% added openmeeg as supported voltype, thanks to Cristiano -% -% Revision 1.19 2009/05/29 11:50:34 vlalit -% Fixed a bug with wrong kind of brackets -% -% Revision 1.18 2009/05/25 11:50:40 roboos -% consistent handling of multiple spheres in case of ctf localspheres.hdm and fieldtrip prepare_localspheres, also in case of synthetic gradients. -% -% Revision 1.17 2009/05/25 08:06:37 roboos -% don't assign the channel labels to each coil for multisphere -% handle the input situation of an already prepared vol and sens (for multisphere) -% -% Revision 1.16 2009/05/18 15:57:23 roboos -% added the label of each coil to the multisphere model output -% -% Revision 1.15 2009/04/01 12:36:52 roboos -% use Taubin's method for fitting the sphere instead of Guido's iterative sphfit function -% -% Revision 1.14 2009/03/26 16:44:03 roboos -% allow 3rd order gradients iduring the construction of the localspheres model, requires that the hdm file contains a global sphere -% -% Revision 1.13 2009/03/23 21:15:18 roboos -% fixed bug for empty vol (inf medium magnetic dipole) -% -% Revision 1.12 2009/03/11 11:29:26 roboos -% ensure that the channel order in the sens and in the vol is consistent with the user-specified channel-keyval argument -% -% Revision 1.11 2009/02/02 13:06:40 roboos -% added bemcp -% changed handling of vertex->electrode interpolation, now also possible if bem system matrix only describes the skin surface -% -% Revision 1.10 2009/01/19 12:13:49 roboos -% added code at the end to determine the brain and the skin compartment -% -% Revision 1.9 2008/12/24 10:34:15 roboos -% added two fprintf statements -% -% Revision 1.8 2008/09/29 09:56:04 release -% some spelling fixes, thanks to Karl -% -% Revision 1.7 2008/07/22 10:17:15 roboos -% replaced identical with strcmp -% -% Revision 1.6 2008/07/21 20:28:44 roboos -% added check on units (mm/cm/m) of the sensor array and volume conductor, give error if inconsistent -% -% Revision 1.5 2008/04/30 13:47:59 roboos -% project electrodes on scalp surface if sphere -% always ensure that grad.tra exists (not yet for elec) -% -% Revision 1.4 2008/04/15 20:36:21 roboos -% added explicit handling of various BEM implementations, i.e. for all voltype variants -% -% Revision 1.3 2008/04/10 11:00:29 roboos -% fixed some small but obvious bugs -% -% Revision 1.2 2008/04/09 20:37:32 roboos -% copied code over from ft version, not yet tested -% -% Revision 1.1 2008/03/06 09:30:36 roboos -% Created skeleton implementation according to how it should be for the forwinv toolbox, i.e. fieldtrip independent, so that it can be included in spm8. -% The functionality should be moved from the existing fieldtrip/private/prepare_vol_sens.m function into this new function. -% - -% get the options -% fileformat = keyval('fileformat', varargin); -channel = keyval('channel', varargin); % cell-array with channel labels -order = keyval('order', varargin); % order of expansion for Nolte method; 10 should be enough for real applications; in simulations it makes sense to go higher - -% set the defaults -if isempty(channel), channel = sens.label; end -if isempty(order), order = 10; end - -% determine whether the input contains EEG or MEG sensors -iseeg = senstype(sens, 'eeg'); -ismeg = senstype(sens, 'meg'); - -if isfield(vol, 'unit') && isfield(sens, 'unit') && ~strcmp(vol.unit, sens.unit) - error('inconsistency in the units of the volume conductor and the sensor array'); -end - -if ismeg && iseeg - % this is something that could be implemented relatively easily - error('simultaneous EEG and MEG not yet supported'); - -elseif ~ismeg && ~iseeg - error('the input does not look like EEG, nor like MEG'); - -elseif ismeg - % always ensure that there is a linear transfer matrix for combining the coils into gradiometers - if ~isfield(sens, 'tra'); - sens.tra = sparse(eye(length(sens.label))); - end - - % select the desired channels from the gradiometer array - % order them according to the users specification - [selchan, selsens] = match_str(channel, sens.label); - - % first only modify the linear combination of coils into channels - sens.label = sens.label(selsens); - sens.tra = sens.tra(selsens,:); - % subsequently remove the coils that do not contribute to any sensor output - selcoil = find(sum(sens.tra,1)~=0); - sens.pnt = sens.pnt(selcoil,:); - sens.ori = sens.ori(selcoil,:); - sens.tra = sens.tra(:,selcoil); - - switch voltype(vol) - case 'infinite' - % nothing to do - - case 'singlesphere' - % nothing to do - - case 'concentric' - % nothing to do - - case 'neuromag' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % if the forward model is computed using the external Neuromag toolbox, - % we have to add a selection of the channels so that the channels - % in the forward model correspond with those in the data. - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - [selchan, selsens] = match_str(channel, sens.label); - vol.chansel = selsens; - - case 'multisphere' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % If the volume conduction model consists of multiple spheres then we - % have to match the channels in the gradiometer array and the volume - % conduction model. - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - % the initial multisphere volume conductor has a single sphere per - % channel, whereas it should have a sphere for each coil - if size(vol.r,1)==size(sens.pnt,1) - % it appears that each coil already has a sphere, which suggests - % that the volume conductor already has been prepared to match the - % sensor array - if ~isfield(vol, 'label') - % this is ok, since coils should not have labels - else - % hmm, this only works if there is a one-to-one match between - % coils in the sensor array and coils in the volme conductor - if ~isequal(vol.label(:), sens.label(:)) - % the problem here is that each channel can have multiple coils - % in case of a gradiometer arrangement. The consequence is that - % the coil label is not unique, because the bottom and top - % coil will have the same label. That causes problems with the - % channel selection. - error('the coils in the volume conduction model do not correspond to the sensor array'); - else - % the coil-specific spheres in the volume conductor should not have a label - % because the label is already specified for the coils in the - % sensor array - vol = rmfield(vol, 'label'); - end - end - end - - % select the desired channels from the multisphere volume conductor - % order them according to the users specification - [selchan, selvol] = match_str(channel, vol.label); - vol.label = vol.label(selvol); - vol.r = vol.r(selvol); - vol.o = vol.o(selvol,:); - - % the CTF way of representing the headmodel is one-sphere-per-channel - % whereas the FieldTrip way of doing the forward computation is one-sphere-per-coil - Nchans = size(sens.tra,1); - Ncoils = size(sens.tra,2); - Nspheres = size(vol.label); - - if isfield(vol, 'orig') - % these are present in a CTF *.hdm file - singlesphere.o(1,1) = vol.orig.MEG_Sphere.ORIGIN_X; - singlesphere.o(1,2) = vol.orig.MEG_Sphere.ORIGIN_Y; - singlesphere.o(1,3) = vol.orig.MEG_Sphere.ORIGIN_Z; - singlesphere.r = vol.orig.MEG_Sphere.RADIUS; - % ensure consistent units - singlesphere = convert_units(singlesphere, vol.unit); - else - singlesphere = []; - end - - if ~isempty(singlesphere) - % determine the channels that do not have a corresponding sphere - % and use the globally fitted single sphere for those - missing = setdiff(sens.label, vol.label); - if ~isempty(missing) - warning('using the global fitted single sphere for %d channels that do not have a local sphere', length(missing)); - end - for i=1:length(missing) - vol.label(end+1) = missing(i); - vol.r(end+1,:) = singlesphere.r; - vol.o(end+1,:) = singlesphere.o; - end - end - - multisphere = []; - % for each coil in the MEG helmet, determine the corresponding local sphere - for i=1:Ncoils - coilindex = find(sens.tra(:,i)~=0); % to which channel does the coil belong - if length(coilindex)>1 - % this indicates that there are multiple channels to which this coil contributes, - % which happens if the sensor array represents a synthetic higher-order gradient. - [dum, coilindex] = max(abs(sens.tra(:,i))); - end - - coillabel = sens.label{coilindex}; % what is the label of the channel - chanindex = strmatch(coillabel, vol.label, 'exact'); - multisphere.r(i,:) = vol.r(chanindex); - multisphere.o(i,:) = vol.o(chanindex,:); - end - vol = multisphere; - - case 'nolte' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % if the forward model is computed using the code from Guido Nolte, we - % have to initialize the volume model using the gradiometer coil - % locations - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - % compute the surface normals for each vertex point - if ~isfield(vol.bnd, 'nrm') - fprintf('computing surface normals\n'); - vol.bnd.nrm = normals(vol.bnd.pnt, vol.bnd.tri); - end - % estimate center and radius - [center,radius] = fitsphere(vol.bnd.pnt); - % initialize the forward calculation (only if gradiometer coils are available) - if size(sens.pnt,1)>0 - vol.forwpar = meg_ini([vol.bnd.pnt vol.bnd.nrm], center', order, [sens.pnt sens.ori]); - end - - otherwise - error('unsupported volume conductor model for MEG'); - end - -elseif iseeg - % select the desired channels from the electrode array - % order them according to the users specification - [selchan, selsens] = match_str(channel, sens.label); - sens.label = sens.label(selsens); - sens.pnt = sens.pnt(selsens,:); - - % create a 2D projection and triangulation - sens.prj = elproj(sens.pnt); - sens.tri = delaunay(sens.prj(:,1), sens.prj(:,2)); - - switch voltype(vol) - case 'infinite' - % nothing to do - - case {'singlesphere', 'concentric'} - % ensure that the electrodes ly on the skin surface - radius = max(vol.r); - pnt = sens.pnt; - if isfield(vol, 'o') - % shift the the centre of the sphere to the origin - pnt(:,1) = pnt(:,1) - vol.o(1); - pnt(:,2) = pnt(:,2) - vol.o(2); - pnt(:,3) = pnt(:,3) - vol.o(3); - end - distance = sqrt(sum(pnt.^2,2)); % to the center of the sphere - if any((abs(distance-radius)/radius)>0.005) - warning('electrodes do not lie on skin surface -> using radial projection') - end - pnt = pnt * radius ./ [distance distance distance]; - if isfield(vol, 'o') - % shift the center back to the original location - pnt(:,1) = pnt(:,1) + vol.o(1); - pnt(:,2) = pnt(:,2) + vol.o(2); - pnt(:,3) = pnt(:,3) + vol.o(3); - end - sens.pnt = pnt; - - case {'bem', 'dipoli', 'asa', 'avo', 'bemcp'} - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % do postprocessing of volume and electrodes in case of BEM model - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - % project the electrodes on the skin and determine the bilinear interpolation matrix - if ~isfield(vol, 'tra') - % determine boundary corresponding with skin and brain - if ~isfield(vol, 'skin') - vol.skin = find_outermost_boundary(vol.bnd); - fprintf('determining skin compartment (%d)\n', vol.skin); - end - if ~isfield(vol, 'source') - vol.source = find_innermost_boundary(vol.bnd); - fprintf('determining source compartment (%d)\n', vol.source); - end - if size(vol.mat,1)~=size(vol.mat,2) && size(vol.mat,1)==length(sens.pnt) - fprintf('electrode transfer and system matrix were already combined\n'); - else - fprintf('projecting electrodes on skin surface\n'); - % compute linear interpolation from triangle vertices towards electrodes - el = project_elec(sens.pnt, vol.bnd(vol.skin).pnt, vol.bnd(vol.skin).tri); - tra = transfer_elec(vol.bnd(vol.skin).pnt, vol.bnd(vol.skin).tri, el); - if size(vol.mat,1)==size(vol.bnd(vol.skin).pnt,1) - % construct the transfer from only the skin vertices towards electrodes - interp = tra; - else - % construct the transfer from all vertices (also brain/skull) towards electrodes - interp = []; - for i=1:length(vol.bnd) - if i==vol.skin - interp = [interp, tra]; - else - interp = [interp, zeros(size(el,1), size(vol.bnd(i).pnt,1))]; - end - end - end - % convert to sparse matrix to speed up the subsequent multiplication - interp = sparse(interp); - % incorporate the linear interpolation matrix and the system matrix into one matrix - % this speeds up the subsequent repeated leadfield computations - fprintf('combining electrode transfer and system matrix\n'); - vol.mat = interp * vol.mat; - % FIXME should I also add the electrode labels to the volume definition? - end - % ensure that the model potential will be average referenced - avg = mean(vol.mat, 1); - vol.mat = vol.mat - repmat(avg, size(vol.mat,1), 1); - end - - case {'openmeeg'} - % do nothing - % in case of openmeeg do nothing because electrodes projection is - % already performed in command line INRIA routines - % FIXME: to be checked the average referencing of the openmeeg tool - % vol.mat = vol.mat; - - otherwise - error('unsupported volume conductor model for EEG'); - end - - % FIXME this needs carefull thought to ensure that the average referencing which is now done here and there, and that the linear interpolation in case of BEM are all dealt with consistently - % % always ensure that there is a linear transfer matrix for - % % rereferencing the EEG potential - % if ~isfield(sens, 'tra'); - % sens.tra = sparse(eye(length(sens.label))); - % end - -end % if iseeg or ismeg - -% determine the skin compartment -if ~isfield(vol, 'skin') - if isfield(vol, 'bnd') - vol.skin = find_outermost_boundary(vol.bnd); - elseif isfield(vol, 'r') && length(vol.r)<=4 - [dum, vol.skin] = max(vol.r); - end -end - -% determine the brain compartment -if ~isfield(vol, 'brain') - if isfield(vol, 'bnd') - vol.brain = find_innermost_boundary(vol.bnd); - elseif isfield(vol, 'r') && length(vol.r)<=4 - [dum, vol.brain] = min(vol.r); - end -end - -% otherwise the voltype assignment to an empty struct below won't work -if isempty(vol) - vol = []; -end - -% this makes them easier to recognise -sens.type = senstype(sens); -vol.type = voltype(vol); diff --git a/external/fieldtrip/private/preproc.m b/external/fieldtrip/private/preproc.m index 739981b..e9603f1 100644 --- a/external/fieldtrip/private/preproc.m +++ b/external/fieldtrip/private/preproc.m @@ -95,138 +95,23 @@ % Copyright (C) 2004-2009, Robert Oostenveld % -% $Log: preproc.m,v $ -% Revision 1.38 2009/09/30 12:58:53 jansch -% added optional call to preproc_denoise and preproc_subspace +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.37 2009/08/05 08:36:09 roboos -% don't fill up the complete data with nans if a nan is detected -% the behaviour of not filtering and giving a warning remains the same +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.36 2009/06/17 10:12:26 roboos -% cfg.montage=[] should also work (just like 'no') +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.35 2009/03/13 13:24:00 jansch -% added support for preproc_denoise -% -% Revision 1.34 2009/03/11 11:26:43 roboos -% updated documentation and copyrights -% -% Revision 1.33 2008/10/10 09:54:53 jansch -% added (undocumented) option dftinvert which results in the dftfilter being -% a very sharp bandpass instead of a notch filter. added (undocumented) option -% conv. fixed small bug in derivative -% -% Revision 1.32 2008/07/08 08:05:44 sashae -% fixed small bug in derivative -% -% Revision 1.31 2008/07/07 14:59:14 sashae -% now using preproc_modules for low-level preprocessing functions -% lnfilter is no longer supported -% updated documentation -% -% Revision 1.30 2008/06/26 07:55:38 roboos -% apply_montage needs cell+label structure and not matrix (thanks to Conrado) -% -% Revision 1.29 2008/06/25 06:37:17 roboos -% change in whitespace -% -% Revision 1.28 2008/06/24 12:47:12 roboos -% added cfg.montage as alternative for rereferencing -% -% Revision 1.27 2008/04/09 14:12:41 roboos -% test isnan over both dimensions of data -% -% Revision 1.26 2007/11/27 16:42:17 roboos -% unwrap angle for hilbert, fixed typo for absimag -% -% Revision 1.25 2007/11/14 13:16:14 roboos -% loop over multiple frequency bands for bandstopfilter, thanks to Saskia -% -% Revision 1.24 2007/11/08 10:09:50 roboos -% allow other versions of the hilbert transformed signal to be computed (e.g. complex, real, imag) -% -% Revision 1.23 2007/10/16 12:38:10 roboos -% do not process the data if there are NaNs, give warning and replace the data with all NaNs -% -% Revision 1.22 2007/09/20 12:59:40 roboos -% updated documentation, added cfg.precision for typecasting data to double or single -% -% Revision 1.21 2007/08/01 15:10:47 ingnie -% added option polyremoval, renamed internal variable blcbeg/endsample into -% beg/endsample -% -% Revision 1.20 2007/04/16 19:04:11 roboos -% removed an excess "end", thanks to Jo -% -% Revision 1.19 2007/04/16 16:10:36 roboos -% loop over all frequencies specified in the cfg.lnfreq (for notch filtering, 2Hz wide) -% added support bandstop filtering (cfg.bsfilter) for when the user wants to specify a wider stop-band -% -% Revision 1.18 2007/01/17 17:05:10 roboos -% use hastoolbox('signal') -% -% Revision 1.17 2006/08/31 07:56:05 roboos -% added onepass-reverse filter to documentation -% -% Revision 1.16 2006/06/14 12:45:58 roboos -% removed documentation of non-functional option cfg.lnfilttype -% added support for onepass and twopass filtering using cfg.lpfiltdir etc. -% -% Revision 1.15 2006/06/14 11:56:30 roboos -% added support for multiple preprocessing stages, achieved by using a cell-array as input (each cell containing a seperate cfg) -% -% Revision 1.14 2006/04/25 20:20:50 roboos -% moved some of the sanity checks from preprocessing to private/preproc -% reinserted the default of some of the cfg settings, since that was broken -% -% Revision 1.13 2006/02/06 20:41:35 roboos -% fixed bug: padding should be removed from time axis -% fixed bug: blc window selection should be done on time axis keeping padding in mind -% -% Revision 1.12 2006/01/18 15:00:00 jansch -% moved the removal of the filter-padding to the end. replaced conv and for-loop -% by convn. implemented mydetrend as a subfunction, which behaves similar to blc. -% -% Revision 1.11 2006/01/17 14:07:43 roboos -% moved rereferencing for EEG all the way to the top, prior to filtering -% implemented cfg.absdiff=yes|no, which does abs(diff(data)) to ensure the order of these two operations (important for jump detection) -% -% Revision 1.10 2006/01/12 16:02:27 roboos -% fixed bug in boxcar, loop over conv() for multiple channels -% -% Revision 1.9 2005/12/20 13:21:46 roboos -% added boxcar convolution as proccessing method -% added temporal derivative as processing method -% -% Revision 1.8 2005/12/02 08:58:29 roboos -% made construction of the time axis optional (can take large amount of memory) -% -% Revision 1.7 2005/11/23 10:44:14 roboos -% added bp/lp/hp/lnfilttype to the documentation -% -% Revision 1.6 2005/09/08 16:56:00 roboos -% only remove padding if unequal to zero -% changed location in file where the time axis is computed -% -% Revision 1.5 2005/09/02 13:17:50 roboos -% Changed dftfilter, loop over all specified frequencies instead of explicitely taking the 2x and 3x harmonics -% Changed default for dftfilter, it now used cfg.dftfreq instead of cfg.lnfreq -% The default is cfg.dftfreq=[50 100 150] -% -% Revision 1.4 2005/05/17 17:50:49 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.3 2005/05/02 08:17:46 roboos -% implemented suggestion of Christian Forkstam: only add implicit reference channel if it is not yet present in the data -% -% Revision 1.2 2005/01/21 09:53:11 roboos -% implemented median filter in preproc, updated help -% -% Revision 1.1 2004/12/09 17:22:28 roboos -% initial version, replicates all preprocessing steps from the large preprocessing function such as filtering, detrending and re-referencing. +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: preproc.m 1177 2010-06-01 11:22:26Z vlalit $ if nargin<5 || isempty(offset) offset = 0; @@ -348,14 +233,14 @@ if isempty(refindx) error('reference channel was not found') end - dat = preproc_rereference(dat, refindx); + dat = ft_preproc_rereference(dat, refindx); end if ~strcmp(cfg.montage, 'no') && ~isempty(cfg.montage) % this is an alternative approach for rereferencing, with arbitrary complex linear combinations of channels tmp.trial = {dat}; tmp.label = label; - tmp = apply_montage(tmp, cfg.montage); + tmp = ft_apply_montage(tmp, cfg.montage); dat = tmp.trial{1}; label = tmp.label; clear tmp @@ -378,24 +263,24 @@ hflag = isfield(cfg.denoise, 'hilbert') && strcmp(cfg.denoise.hilbert, 'yes'); datlabel = match_str(label, cfg.denoise.channel); reflabel = match_str(label, cfg.denoise.refchannel); - tmpdat = preproc_denoise(dat(datlabel,:), dat(reflabel,:), hflag); + tmpdat = ft_preproc_denoise(dat(datlabel,:), dat(reflabel,:), hflag); dat(datlabel,:) = tmpdat; end -if strcmp(cfg.medianfilter, 'yes'), dat = preproc_medianfilter(dat, cfg.medianfiltord); end -if strcmp(cfg.lpfilter, 'yes'), dat = preproc_lowpassfilter(dat, fsample, cfg.lpfreq, cfg.lpfiltord, cfg.lpfilttype, cfg.lpfiltdir); end -if strcmp(cfg.hpfilter, 'yes'), dat = preproc_highpassfilter(dat, fsample, cfg.hpfreq, cfg.hpfiltord, cfg.hpfilttype, cfg.hpfiltdir); end -if strcmp(cfg.bpfilter, 'yes'), dat = preproc_bandpassfilter(dat, fsample, cfg.bpfreq, cfg.bpfiltord, cfg.bpfilttype, cfg.bpfiltdir); end +if strcmp(cfg.medianfilter, 'yes'), dat = ft_preproc_medianfilter(dat, cfg.medianfiltord); end +if strcmp(cfg.lpfilter, 'yes'), dat = ft_preproc_lowpassfilter(dat, fsample, cfg.lpfreq, cfg.lpfiltord, cfg.lpfilttype, cfg.lpfiltdir); end +if strcmp(cfg.hpfilter, 'yes'), dat = ft_preproc_highpassfilter(dat, fsample, cfg.hpfreq, cfg.hpfiltord, cfg.hpfilttype, cfg.hpfiltdir); end +if strcmp(cfg.bpfilter, 'yes'), dat = ft_preproc_bandpassfilter(dat, fsample, cfg.bpfreq, cfg.bpfiltord, cfg.bpfilttype, cfg.bpfiltdir); end if strcmp(cfg.bsfilter, 'yes') for i=1:size(cfg.bsfreq,1) % apply a bandstop filter for each of the specified bands, i.e. cfg.bsfreq should be Nx2 - dat = preproc_bandstopfilter(dat, fsample, cfg.bsfreq(i,:), cfg.bsfiltord, cfg.bsfilttype, cfg.bsfiltdir); + dat = ft_preproc_bandstopfilter(dat, fsample, cfg.bsfreq(i,:), cfg.bsfiltord, cfg.bsfilttype, cfg.bsfiltdir); end end if strcmp(cfg.dftfilter, 'yes') datorig = dat; for i=1:length(cfg.dftfreq) % filter out the 50Hz noise, optionally also the 100 and 150 Hz harmonics - dat = preproc_dftfilter(dat, fsample, cfg.dftfreq(i)); + dat = ft_preproc_dftfilter(dat, fsample, cfg.dftfreq(i)); end if strcmp(cfg.dftinvert, 'yes'), dat = datorig - dat; @@ -413,7 +298,7 @@ % the begin and endsample of the detrend period correspond to the complete data minus padding begsample = 1 + begpadding; endsample = nsamples - endpadding; - dat = preproc_detrend(dat, begsample, endsample); + dat = ft_preproc_detrend(dat, begsample, endsample); end if strcmp(cfg.blc, 'yes') || nargout>2 % determine the complete time axis for the baseline correction @@ -427,19 +312,19 @@ % the begin and endsample of the baseline period correspond to the complete data minus padding begsample = 1 + begpadding; endsample = nsamples - endpadding; - dat = preproc_baselinecorrect(dat, begsample, endsample); + dat = ft_preproc_baselinecorrect(dat, begsample, endsample); else % determine the begin and endsample of the baseline period and baseline correct for it begsample = nearest(time, cfg.blcwindow(1)); endsample = nearest(time, cfg.blcwindow(2)); - dat = preproc_baselinecorrect(dat, begsample, endsample); + dat = ft_preproc_baselinecorrect(dat, begsample, endsample); end end if ~strcmp(cfg.hilbert, 'no') - dat = preproc_hilbert(dat, cfg.hilbert); + dat = ft_preproc_hilbert(dat, cfg.hilbert); end if strcmp(cfg.rectify, 'yes'), - dat = preproc_rectify(dat); + dat = ft_preproc_rectify(dat); end if isnumeric(cfg.boxcar) numsmp = round(cfg.boxcar*fsample); @@ -465,17 +350,17 @@ dat = convn(dat, kernel, 'same'); end if strcmp(cfg.derivative, 'yes'), - dat = preproc_derivative(dat, 1, 'end'); + dat = ft_preproc_derivative(dat, 1, 'end'); end if strcmp(cfg.absdiff, 'yes'), % this implements abs(diff(data), which is required for jump detection dat = abs([diff(dat, 1, 2) zeros(size(dat,1),1)]); end if strcmp(cfg.standardize, 'yes'), - dat = preproc_standardize(dat, 1, size(dat,2)); + dat = ft_preproc_standardize(dat, 1, size(dat,2)); end if ~isempty(cfg.subspace), - dat = preproc_subspace(dat, cfg.subspace); + dat = ft_preproc_subspace(dat, cfg.subspace); end if ~isempty(cfg.precision) % convert the data to another numeric precision, i.e. double, single or int32 diff --git a/external/fieldtrip/private/preproc_bandpassfilter.m b/external/fieldtrip/private/preproc_bandpassfilter.m deleted file mode 100644 index 528ad0e..0000000 --- a/external/fieldtrip/private/preproc_bandpassfilter.m +++ /dev/null @@ -1,100 +0,0 @@ -function [filt] = preproc_bandpassfilter(dat, Fs, Fbp, N, type, dir) - -% PREPROC_BANDPASSFILTER applies a band-pass filter to the data and thereby -% removes the spectral components in the data except for the ones in the -% specified frequency band -% -% Use as -% [filt] = preproc_bandpassfilter(dat, Fsample, Fbp, N, type, dir) -% where -% dat data matrix (Nchans X Ntime) -% Fsample sampling frequency in Hz -% Fbp frequency band, specified as [Fhp Flp] -% N optional filter order, default is 4 (but) or 25 (fir) -% type optional filter type, can be -% 'but' Butterworth IIR filter (default) -% 'fir' FIR filter using Matlab fir1 function -% dir optional filter direction, can be -% 'onepass' forward filter only -% 'onepass-reverse' reverse filter only, i.e. backward in time -% 'twopass' zero-phase forward and reverse filter (default) -% -% Note that a one- or two-pass filter has consequences for the -% strength of the filter, i.e. a two-pass filter with the same filter -% order will attenuate the signal twice as strong. -% -% See also PREPROC - -% Copyright (c) 2003-2008, Robert Oostenveld -% -% $Log: preproc_bandpassfilter.m,v $ -% Revision 1.2 2008/05/23 09:13:58 roboos -% cleaned up code and documentation, ensure that all functions are consistent, added proper implementation to the scratch functions -% -% Revision 1.1 2008/05/23 06:54:21 roboos -% created initial scratch version of preprocessing module, to be used in fieldtrip or as stand-alone toolbox (e.g. in spm8 or braingain) -% some functions are copies of existing roboos/misc versions, some just contain some example code for the implementation -% -% Revision 1.5 2006/08/31 07:57:22 roboos -% implemented onepass-reverse filter: usefull for stimulus artifacts, e.g. TMS or electrical stimulation -% -% Revision 1.4 2006/06/14 12:36:20 roboos -% added the filter direction as additional option, default is 'twopass', i.e. using filtfilt -% -% Revision 1.3 2004/02/11 08:55:13 roberto -% added optional fir1 filter (default still is butterworth), changed -% layout of code for better support of multiple optional arguments, -% extended documentation -% -% Revision 1.2 2003/06/12 08:40:44 roberto -% added variable option to determine filter order -% changed default order from 6 to 4 for notch and bandpass -% -% Revision 1.1 2003/04/04 09:53:36 roberto -% new implementation, using 6th order Butterworth FIR filter -% - -% set the default filter order later -if nargin<4 || isempty(N) - N = []; -end - -% set the default filter type -if nargin<5 || isempty(type) - type = 'but'; -end - -% set the default filter direction -if nargin<6|| isempty(dir) - dir = 'twopass'; -end - -% Nyquist frequency -Fn = Fs/2; - -% compute filter coefficients -switch type - case 'but' - if isempty(N) - N = 4; - end - [B, A] = butter(N, [min(Fbp)/Fn max(Fbp)/Fn]); - case 'fir' - if isempty(N) - N = 25; - end - [B, A] = fir1(N, [min(Fbp)/Fn max(Fbp)/Fn]); -end - -% apply filter to the data -switch dir - case 'onepass' - filt = filter(B, A, dat')'; - case 'onepass-reverse' - dat = fliplr(dat); - filt = filter(B, A, dat')'; - filt = fliplr(filt); - case 'twopass' - filt = filtfilt(B, A, dat')'; -end - diff --git a/external/fieldtrip/private/preproc_bandstopfilter.m b/external/fieldtrip/private/preproc_bandstopfilter.m deleted file mode 100644 index c8ca4e6..0000000 --- a/external/fieldtrip/private/preproc_bandstopfilter.m +++ /dev/null @@ -1,85 +0,0 @@ -function [filt] = preproc_bandstopfilter(dat,Fs,Fbp,N,type,dir) - -% PREPROC_BANDSTOPFILTER applies a band-stop filter to the data and thereby -% removes the spectral components in the specified frequency band -% -% -% Use as -% [filt] = preproc_bandstopfilter(dat, Fsample, Fbp, N, type, dir) -% where -% dat data matrix (Nchans X Ntime) -% Fsample sampling frequency in Hz -% Fbp frequency band, specified as [Fhp Flp] -% N optional filter order, default is 4 (but) or 25 (fir) -% type optional filter type, can be -% 'but' Butterworth IIR filter (default) -% 'fir' FIR filter using Matlab fir1 function -% dir optional filter direction, can be -% 'onepass' forward filter only -% 'onepass-reverse' reverse filter only, i.e. backward in time -% 'twopass' zero-phase forward and reverse filter (default) -% -% Note that a one- or two-pass filter has consequences for the -% strength of the filter, i.e. a two-pass filter with the same filter -% order will attenuate the signal twice as strong. -% -% See also PREPROC - -% Copyright (c) 2007-2008, Robert Oostenveld -% -% $Log: preproc_bandstopfilter.m,v $ -% Revision 1.2 2008/05/23 09:13:58 roboos -% cleaned up code and documentation, ensure that all functions are consistent, added proper implementation to the scratch functions -% -% Revision 1.1 2008/05/23 06:54:21 roboos -% created initial scratch version of preprocessing module, to be used in fieldtrip or as stand-alone toolbox (e.g. in spm8 or braingain) -% some functions are copies of existing roboos/misc versions, some just contain some example code for the implementation -% -% Revision 1.1 2007/09/11 15:30:59 roboos -% new implementation based on bandpassfilter -% - -% set the default filter order later -if nargin<4 || isempty(N) - N = []; -end - -% set the default filter type -if nargin<5 || isempty(type) - type = 'but'; -end - -% set the default filter direction -if nargin<6|| isempty(dir) - dir = 'twopass'; -end - -% Nyquist frequency -Fn = Fs/2; - -% compute filter coefficients -switch type - case 'but' - if isempty(N) - N = 4; - end - [B, A] = butter(N, [min(Fbp)/Fn max(Fbp)/Fn], 'stop'); - case 'fir' - if isempty(N) - N = 25; - end - [B, A] = fir1(N, [min(Fbp)/Fn max(Fbp)/Fn], 'stop'); -end - -% apply filter to the data -switch dir - case 'onepass' - filt = filter(B, A, dat')'; - case 'onepass-reverse' - dat = fliplr(dat); - filt = filter(B, A, dat')'; - filt = fliplr(filt); - case 'twopass' - filt = filtfilt(B, A, dat')'; -end - diff --git a/external/fieldtrip/private/preproc_baselinecorrect.m b/external/fieldtrip/private/preproc_baselinecorrect.m deleted file mode 100644 index 9cb2262..0000000 --- a/external/fieldtrip/private/preproc_baselinecorrect.m +++ /dev/null @@ -1,58 +0,0 @@ -function [dat, baseline] = preproc_baselinecorrect(dat, begsample, endsample) - -% PREPROC_BASELINECORRECT performs a baseline correction, e.g. using the -% prestimulus interval of the data or using the complete data -% -% Use as -% [dat] = preproc_baselinecorrect(dat, begin, end) -% where -% dat data matrix (Nchans X Ntime) -% begsample index of the begin sample for the baseline estimate -% endsample index of the end sample for the baseline estimate -% -% If no begin and end sample are specified for the baseline estimate, it -% will be estimated on the complete data. -% -% See also PREPROC - -% Copyright (C) 1998-2008, Robert Oostenveld -% -% $Log: preproc_baselinecorrect.m,v $ -% Revision 1.2 2008/05/23 09:13:58 roboos -% cleaned up code and documentation, ensure that all functions are consistent, added proper implementation to the scratch functions -% -% Revision 1.1 2008/05/23 06:54:21 roboos -% created initial scratch version of preprocessing module, to be used in fieldtrip or as stand-alone toolbox (e.g. in spm8 or braingain) -% some functions are copies of existing roboos/misc versions, some just contain some example code for the implementation -% -% Revision 1.3 2003/03/14 10:17:28 roberto -% fixed bug that was introduced by last change, changend from repmat to for-loop -% -% Revision 1.2 2003/03/13 16:44:45 roberto -% fixed bug with multiple epochs and single channel data -% - -% determine the size of the data -[Nchans, Nsamples] = size(dat); - -% determine the interval to use for baseline correction -if nargin<2 || isempty(begsample) - begsample = 1; -end -if nargin<3 || isempty(endsample) - endsample = Nsamples; -end - -% estimate the baseline and subtract it -baseline = mean(dat(:,begsample:endsample), 2); - -% it is faster to loop over samples than over channels due to the internal memory representation of Matlab -% for chan=1:Nchans -% dat(chan,:) = dat(chan,:) - baseline(chan); -% end - -for sample=1:Nsamples - dat(:,sample) = dat(:,sample) - baseline; -end - - diff --git a/external/fieldtrip/private/preproc_denoise.m b/external/fieldtrip/private/preproc_denoise.m deleted file mode 100644 index 023e41b..0000000 --- a/external/fieldtrip/private/preproc_denoise.m +++ /dev/null @@ -1,50 +0,0 @@ -function [dat, w] = preproc_denoise(dat, refdat, hilbertflag) - -% PREPROC_DENOISE performs a regression of the matrix dat onto -% refdat, and subtracts the projected data. Tis is for the -% purpose of removing signals generated by coils during continuous -% head motion tracking, for exxample. -% -% Use as -% [dat] = preproc_denoise(dat, refdat, hilbertflag) -% where -% dat data matrix (Nchan1 X Ntime) -% refdat data matrix (Nchan2 X Ntime) -% hilbertflag specifying to regress out the real and imaginary parts of -% the hilbert transformed signal. Only meaningful for narrow -% band reference data -% -% See also PREPROC - -% Copyright (C) 2009, Jan-Mathijs Schoffelen -% -% $Log: preproc_denoise.m,v $ -% Revision 1.1 2009/03/13 13:32:50 jansch -% first commitment into cvs -% - -if nargin<3, - hilbertflag = 0; -end - -n1 = size(dat,2); -n2 = size(refdat,2); -m1 = mean(dat,2); -m2 = mean(refdat,2); - -%remove mean -refdat = refdat-m2(:,ones(n2,1)); -tmpdat = dat-m1(:,ones(n1,1)); - -%do hilbert transformation -if hilbertflag>0, - hrefdat = hilbert(refdat')'; - refdat = [real(hrefdat);imag(hrefdat)]; -end - -c12 = tmpdat*refdat'; %covariance between signals and references -c1 = refdat*refdat'; %covariance between references and references -w = (pinv(c1)*c12')'; %regression weights - -%subtract -dat = dat-w*refdat; diff --git a/external/fieldtrip/private/preproc_derivative.m b/external/fieldtrip/private/preproc_derivative.m deleted file mode 100644 index d29658c..0000000 --- a/external/fieldtrip/private/preproc_derivative.m +++ /dev/null @@ -1,53 +0,0 @@ -function [dat] = preproc_derivative(dat, order, padding) - -% PREPROC_DERIVATIVE computes the temporal Nth order derivative of the -% data -% -% Use as -% [dat] = preproc_derivative(dat, order, padding) -% where -% dat data matrix (Nchans X Ntime) -% order number representing the Nth derivative (default = 1) -% padding string that determines whether and how the data will be -% padded to keep the number of samples the same, can be -% 'none' do not apply padding, the output will be N samples shorter -% 'both' apply padding to both sides -% 'beg' apply padding at the beginning of the data -% 'end' apply padding at the end of the data (default) -% -% See also PREPROC - -% Copyright (C) 2008, Robert Oostenveld -% -% $Log: preproc_derivative.m,v $ -% Revision 1.2 2008/05/23 09:13:58 roboos -% cleaned up code and documentation, ensure that all functions are consistent, added proper implementation to the scratch functions -% - -% determine the size of the data -[Nchans, Nsamples] = size(dat); - -% set the defaults if options are not specified -if nargin<2 || isempty(order) - order = 1; -end -if nargin<3 || isempty(padding) - padding = 'end'; -end - -% compute the derivative -dat = diff(dat, order, 2); - -% pad the resulting data to keep the number of samples the same -switch padding - case 'beg' - dat = cat(2, zeros(Nchans, order), dat); - case 'end' - dat = cat(2, dat, zeros(Nchans, order)); - case 'both' - if rem(order,2) - error('padding can only be applied to both sides if the order is an even number'); - end - dat = cat(2, zeros(Nchans, order/2), dat, zeros(Nchans, order/2)); -end - diff --git a/external/fieldtrip/private/preproc_detrend.m b/external/fieldtrip/private/preproc_detrend.m deleted file mode 100644 index 9b1f44f..0000000 --- a/external/fieldtrip/private/preproc_detrend.m +++ /dev/null @@ -1,54 +0,0 @@ -function [dat, beta, x] = preproc_detrend(dat, begsample, endsample, order) - -% PREPROC_DETREND removes linear or higher order polynomial trends from the -% data using using General Linear Modeling -% -% Use as -% [dat] = preproc_detrend(dat, begin, end, order) -% where -% dat data matrix (Nchans X Ntime) -% begsample index of the begin sample for the trend estimate -% endsample index of the end sample for the trend estimate -% order number representing the polynomial order (default = 1, i.e. linear) -% -% If no begin and end sample are specified for the trend estimate, it -% will be estimated on the complete data. -% -% See also PREPROC - -% Copyright (C) 2008, Robert Oostenveld -% -% $Log: preproc_detrend.m,v $ -% Revision 1.3 2008/06/10 16:03:40 roboos -% fixed small bug and typ, thanks to Saskia -% -% Revision 1.2 2008/05/23 09:13:58 roboos -% cleaned up code and documentation, ensure that all functions are consistent, added proper implementation to the scratch functions -% - -% determine the size of the data -[Nchans, Nsamples] = size(dat); - -% determine the interval to use for baseline correction -if nargin<2 || isempty(begsample) - begsample = 1; -end -if nargin<3 || isempty(endsample) - endsample = Nsamples; -end - -% determine the order of the polynomial trend to be removed, default is linear -if nargin<4 || isempty(order) - order = 1; -end - -% create a matrix with regressor components -basis = 1:Nsamples; -x = zeros(order+1,Nsamples); -for i=0:order - x(i+1,:) = basis.^(i); -end -% estimate the polynomial trend using General Linear Modeling, where dat=beta*x+noise -beta = dat(:,begsample:endsample)/x(:,begsample:endsample); -% subtract the trend from the complete data -dat = dat - beta*x; diff --git a/external/fieldtrip/private/preproc_dftfilter.m b/external/fieldtrip/private/preproc_dftfilter.m deleted file mode 100644 index 07bd7e7..0000000 --- a/external/fieldtrip/private/preproc_dftfilter.m +++ /dev/null @@ -1,84 +0,0 @@ -function [filt] = preproc_dftfilter(dat, Fs, Fl) - -% PREPROC_DFTFILTER applies a notch filter to the data to remove the 50Hz -% or 60Hz line noise components. This is done by fitting a sine and cosine -% at the specified frequency to the data and subsequently subtracting the -% estimated components. The longer the data is, the sharper the spectral -% notch will be that is removed from the data. -% -% Use as -% [filt] = preproc_dftfilter(dat, Fsample, Fline) -% where -% dat data matrix (Nchans X Ntime) -% Fsample sampling frequency in Hz -% Fline line noise frequency -% -% The line frequency should be specified as a single number. -% If omitted, a European default of 50Hz will be assumed. -% -% Preferaby the data should have a length that is a multiple of the -% oscillation period of the line noise (i.e. 20ms for 50Hz noise). If the -% data is of different lenght, then only the first N complete periods are -% used to estimate the line noise. The estimate is subtracted from the -% complete data. -% -% See also PREPROC - -% original Copyright (C) 2003, Pascal Fries -% modifications Copyright (C) 2003-2008, Robert Oostenveld -% -% $Log: preproc_dftfilter.m,v $ -% Revision 1.3 2009/09/30 13:01:10 jansch -% included temporary mean subtraction to avoid leakage (with large DC-offsets) this could still be an issue -% -% Revision 1.2 2008/05/23 09:13:58 roboos -% cleaned up code and documentation, ensure that all functions are consistent, added proper implementation to the scratch functions -% -% Revision 1.1 2008/05/23 06:54:21 roboos -% created initial scratch version of preprocessing module, to be used in fieldtrip or as stand-alone toolbox (e.g. in spm8 or braingain) -% some functions are copies of existing roboos/misc versions, some just contain some example code for the implementation -% -% Revision 1.6 2005/01/27 17:06:22 roboos -% fixed bug in normalization of sine and cosine amplitude estimate in case number of samples in the data does not match with an integer number of cycles -% -% Revision 1.5 2004/11/17 09:00:01 roboos -% added selection of data to ensure that the sine wave is estimated on an integer number of line-noise cycles -% all data is filtered, only amplitude estimation is done on this selection -% -% Revision 1.4 2003/12/01 08:47:59 roberto -% updated copyright statement -% -% Revision 1.3 2003/10/01 08:46:25 roberto -% updated help -% -% Revision 1.2 2003/10/01 08:45:23 roberto -% updated help -% -% Revision 1.1 2003/10/01 08:45:03 roberto -% first implementation as separate function, used to be notchfilter -% - -% determine the size of the data -[Nchans, Nsamples] = size(dat); - -% set the default filter frequency -if nargin<3 || isempty(Fl) - Fl = 50; -end - -% determine the largest integer number of line-noise cycles that fits in the data -sel = 1:round(floor(Nsamples * Fl/Fs) * Fs/Fl); - -% temporarily remove mean to avoid leakage -mdat = mean(dat(:,sel),2); -dat = dat - mdat(:,ones(1,Nsamples)); - -% fit a sin and cos to the signal and subtract them -time = (0:Nsamples-1)/Fs; -tmp = exp(j*2*pi*Fl*time); % complex sin and cos -% ampl = 2*dat*tmp'/Nsamples; % estimated amplitude of complex sin and cos -ampl = 2*dat(:,sel)*tmp(sel)'/length(sel); % estimated amplitude of complex sin and cos on integer number of cycles -est = ampl*tmp; % estimated signal at this frequency -%filt = dat - est; % subtract estimated signal -filt = dat - est + mdat(:,ones(1,Nsamples)); -filt = real(filt); diff --git a/external/fieldtrip/private/preproc_highpassfilter.m b/external/fieldtrip/private/preproc_highpassfilter.m deleted file mode 100644 index 0212fa5..0000000 --- a/external/fieldtrip/private/preproc_highpassfilter.m +++ /dev/null @@ -1,102 +0,0 @@ -function [filt] = preproc_highpassfilter(dat,Fs,Fhp,N,type,dir) - -% PREPROC_HIGHPASSFILTER applies a high-pass filter to the data and thereby -% removes the low frequency components in the data -% -% Use as -% [filt] = preproc_highpassfilter(dat, Fsample, Fhp, N, type, dir) -% where -% dat data matrix (Nchans X Ntime) -% Fsample sampling frequency in Hz -% Fhp filter frequency -% N optional filter order, default is 6 (but) or 25 (fir) -% type optional filter type, can be -% 'but' Butterworth IIR filter (default) -% 'fir' FIR filter using Matlab fir1 function -% dir optional filter direction, can be -% 'onepass' forward filter only -% 'onepass-reverse' reverse filter only, i.e. backward in time -% 'twopass' zero-phase forward and reverse filter (default) -% -% Note that a one- or two-pass filter has consequences for the -% strength of the filter, i.e. a two-pass filter with the same filter -% order will attenuate the signal twice as strong. -% -% See also PREPROC - -% Copyright (c) 2003-2008, Robert Oostenveld -% -% $Log: preproc_highpassfilter.m,v $ -% Revision 1.2 2008/05/23 09:13:58 roboos -% cleaned up code and documentation, ensure that all functions are consistent, added proper implementation to the scratch functions -% -% Revision 1.1 2008/05/23 06:54:22 roboos -% created initial scratch version of preprocessing module, to be used in fieldtrip or as stand-alone toolbox (e.g. in spm8 or braingain) -% some functions are copies of existing roboos/misc versions, some just contain some example code for the implementation -% -% Revision 1.6 2006/08/31 07:57:22 roboos -% implemented onepass-reverse filter: usefull for stimulus artifacts, e.g. TMS or electrical stimulation -% -% Revision 1.5 2006/06/15 08:46:34 roboos -% fixed bug: added dir to input argument list -% -% Revision 1.4 2006/06/14 12:36:20 roboos -% added the filter direction as additional option, default is 'twopass', i.e. using filtfilt -% -% Revision 1.3 2004/02/11 08:55:13 roberto -% added optional fir1 filter (default still is butterworth), changed -% layout of code for better support of multiple optional arguments, -% extended documentation -% -% Revision 1.2 2003/06/12 08:40:44 roberto -% added variable option to determine filter order -% changed default order from 6 to 4 for notch and bandpass -% -% Revision 1.1 2003/04/04 09:53:37 roberto -% new implementation, using 6th order Butterworth FIR filter -% - -% set the default filter order later -if nargin<4 || isempty(N) - N = []; -end - -% set the default filter type -if nargin<5 || isempty(type) - type = 'but'; -end - -% set the default filter direction -if nargin<6|| isempty(dir) - dir = 'twopass'; -end - -% Nyquist frequency -Fn = Fs/2; - -% compute filter coefficients -switch type - case 'but' - if isempty(N) - N = 6; - end - [B, A] = butter(N, max(Fhp)/Fn, 'high'); - case 'fir' - if isempty(N) - N = 25; - end - [B, A] = fir1(N, max(Fhp)/Fn, 'high'); -end - -% apply filter to the data -switch dir - case 'onepass' - filt = filter(B, A, dat')'; - case 'onepass-reverse' - dat = fliplr(dat); - filt = filter(B, A, dat')'; - filt = fliplr(filt); - case 'twopass' - filt = filtfilt(B, A, dat')'; -end - diff --git a/external/fieldtrip/private/preproc_hilbert.m b/external/fieldtrip/private/preproc_hilbert.m deleted file mode 100644 index e121c91..0000000 --- a/external/fieldtrip/private/preproc_hilbert.m +++ /dev/null @@ -1,59 +0,0 @@ -function [dat] = preproc_hilbert(dat, option) - -% PREPROC_HILBERT computes the Hilbert transpose of the data and optionally -% performs post-processing on the complex representation, e.g. the absolute -% value of the Hilbert transform of a band-pass filtered signal corresponds -% with the amplitude envelope. -% -% Use as -% [dat] = preproc_hilbert(dat, option) -% where -% dat data matrix (Nchans X Ntime) -% option string that determines whether and how the Hilbert transform -% should be post-processed, can be -% 'abs' -% 'complex' -% 'real' -% 'imag' -% 'absreal' -% 'absimag' -% 'angle' -% -% The default is to return the absolute value of the Hilbert transform. -% -% See also PREPROC - -% Copyright (C) 2008, Robert Oostenveld -% -% $Log: preproc_hilbert.m,v $ -% Revision 1.2 2008/05/23 09:13:58 roboos -% cleaned up code and documentation, ensure that all functions are consistent, added proper implementation to the scratch functions -% - -% set the defaults if option is not specified -if nargin<2 || isempty(option) - option = 'abs'; -end - -% use the non-conjugate transpose to be sure -dat = transpose(hilbert(transpose(dat))); - -% do postprocessing of the complex representation -switch option - case {'yes' 'abs'} - dat = abs(dat); % this is the default if 'yes' is specified - case {'no' 'complex'} - dat = dat; % this is the default if 'no' is specified - case 'real' - dat = real(dat); - case 'imag' - dat = imag(dat); - case 'absreal' - dat = abs(real(dat)); - case 'absimag' - dat = abs(imag(dat)); - case 'angle' - dat = unwrap(angle(dat)); - otherwise - error('incorrect specification of the optional input argument'); -end diff --git a/external/fieldtrip/private/preproc_lowpassfilter.m b/external/fieldtrip/private/preproc_lowpassfilter.m deleted file mode 100644 index 2a09ddf..0000000 --- a/external/fieldtrip/private/preproc_lowpassfilter.m +++ /dev/null @@ -1,99 +0,0 @@ -function [filt] = preproc_lowpassfilter(dat,Fs,Flp,N,type,dir) - -% PREPROC_LOWPASSFILTER applies a low-pass filter to the data and thereby -% removes all high frequency components in the data -% -% Use as -% [filt] = preproc_lowpassfilter(dat, Fsample, Flp, N, type, dir) -% where -% dat data matrix (Nchans X Ntime) -% Fsample sampling frequency in Hz -% Flp filter frequency -% N optional filter order, default is 6 (but) or 25 (fir) -% type optional filter type, can be -% 'but' Butterworth IIR filter (default) -% 'fir' FIR filter using Matlab fir1 function -% dir optional filter direction, can be -% 'onepass' forward filter only -% 'onepass-reverse' reverse filter only, i.e. backward in time -% 'twopass' zero-phase forward and reverse filter (default) -% -% Note that a one- or two-pass filter has consequences for the -% strength of the filter, i.e. a two-pass filter with the same filter -% order will attenuate the signal twice as strong. -% -% See also PREPROC - -% Copyright (c) 2003-2008, Robert Oostenveld -% -% $Log: preproc_lowpassfilter.m,v $ -% Revision 1.2 2008/05/23 09:13:58 roboos -% cleaned up code and documentation, ensure that all functions are consistent, added proper implementation to the scratch functions -% -% Revision 1.1 2008/05/23 06:54:22 roboos -% created initial scratch version of preprocessing module, to be used in fieldtrip or as stand-alone toolbox (e.g. in spm8 or braingain) -% some functions are copies of existing roboos/misc versions, some just contain some example code for the implementation -% -% Revision 1.5 2006/08/31 07:57:22 roboos -% implemented onepass-reverse filter: usefull for stimulus artifacts, e.g. TMS or electrical stimulation -% -% Revision 1.4 2006/06/14 12:36:21 roboos -% added the filter direction as additional option, default is 'twopass', i.e. using filtfilt -% -% Revision 1.3 2004/02/11 08:55:13 roberto -% added optional fir1 filter (default still is butterworth), changed -% layout of code for better support of multiple optional arguments, -% extended documentation -% -% Revision 1.2 2003/06/12 08:40:44 roberto -% added variable option to determine filter order -% changed default order from 6 to 4 for notch and bandpass -% -% Revision 1.1 2003/04/04 09:53:37 roberto -% new implementation, using 6th order Butterworth FIR filter -% - -% set the default filter order later -if nargin<4 || isempty(N) - N = []; -end - -% set the default filter type -if nargin<5 || isempty(type) - type = 'but'; -end - -% set the default filter direction -if nargin<6|| isempty(dir) - dir = 'twopass'; -end - -% Nyquist frequency -Fn = Fs/2; - -% compute filter coefficients -switch type - case 'but' - if isempty(N) - N = 6; - end - [B, A] = butter(N, max(Flp)/Fn); - case 'fir' - if isempty(N) - N = 25; - end - [B, A] = fir1(N, max(Flp)/Fn); -end - -% apply filter to the data -switch dir - case 'onepass' - filt = filter(B, A, dat')'; - case 'onepass-reverse' - dat = fliplr(dat); - filt = filter(B, A, dat')'; - filt = fliplr(filt); - case 'twopass' - filt = filtfilt(B, A, dat')'; -end - diff --git a/external/fieldtrip/private/preproc_medianfilter.m b/external/fieldtrip/private/preproc_medianfilter.m deleted file mode 100644 index ebc3728..0000000 --- a/external/fieldtrip/private/preproc_medianfilter.m +++ /dev/null @@ -1,27 +0,0 @@ -function dat = preproc_medianfilter(dat, order); - -% PREPROC_MEDIANFILTER applies a median filter, which smooths the data with -% a boxcar-like kernel except that it keeps steps in the data. This -% function requires the Matlab Signal Processing toolbox. -% -% Use as -% [dat] = preproc_medianfilter(dat, order) -% where -% dat data matrix (Nchans X Ntime) -% order number, the length of the median filter kernel (default = 25) -% -% See also PREPROC - -% Copyright (C) 2008, Robert Oostenveld -% -% $Log: preproc_medianfilter.m,v $ -% Revision 1.2 2008/05/23 09:13:58 roboos -% cleaned up code and documentation, ensure that all functions are consistent, added proper implementation to the scratch functions -% - -% set the default filter order -if nargin<2 || isempty(order) - order = 25; -end - -dat = medfilt1(dat, order, [], 2); diff --git a/external/fieldtrip/private/preproc_rectify.m b/external/fieldtrip/private/preproc_rectify.m deleted file mode 100644 index 95357bf..0000000 --- a/external/fieldtrip/private/preproc_rectify.m +++ /dev/null @@ -1,20 +0,0 @@ -function [dat] = preproc_rectify(dat) - -% PREPROC_RECTIFY rectifies the data, i.e. converts all samples with a -% negative value into the similar magnitude positive value -% -% Use as -% [dat] = preproc_rectify(dat) -% where -% dat data matrix (Nchans X Ntime) -% -% See also PREPROC - -% Copyright (C) 2008, Robert Oostenveld -% -% $Log: preproc_rectify.m,v $ -% Revision 1.2 2008/05/23 09:13:58 roboos -% cleaned up code and documentation, ensure that all functions are consistent, added proper implementation to the scratch functions -% - -dat = abs(dat); diff --git a/external/fieldtrip/private/preproc_rereference.m b/external/fieldtrip/private/preproc_rereference.m deleted file mode 100644 index 65e9961..0000000 --- a/external/fieldtrip/private/preproc_rereference.m +++ /dev/null @@ -1,48 +0,0 @@ -function [dat, ref] = preproc_rereference(dat, refchan) - -% PREPROC_REREFERENCE computes the average reference over all EEG channels -% or rereferences the data to the selected channeld -% -% Use as -% [dat] = preproc_rereference(dat, refchan) -% where -% dat data matrix (Nchans X Ntime) -% refchan vector with indices of the new reference channels -% -% If the new reference channel is not specified, the data will be -% rereferenced to the average of all channels. -% -% See also PREPROC - -% Copyright (C) 1998-2008, Robert Oostenveld -% -% $Log: preproc_rereference.m,v $ -% Revision 1.3 2009/01/07 12:44:18 roboos -% also allow refchan='all' -% -% Revision 1.2 2008/05/23 09:13:58 roboos -% cleaned up code and documentation, ensure that all functions are consistent, added proper implementation to the scratch functions -% -% Revision 1.1 2008/05/23 06:54:22 roboos -% created initial scratch version of preprocessing module, to be used in fieldtrip or as stand-alone toolbox (e.g. in spm8 or braingain) -% some functions are copies of existing roboos/misc versions, some just contain some example code for the implementation -% -% Revision 1.2 2003/03/17 10:37:28 roberto -% improved general help comments and added copyrights -% - -% determine the size of the data -[Nchans, Nsamples] = size(dat); - -% determine the new reference channels -if nargin<2 || isempty(refchan) || (ischar(refchan) && strcmp(refchan, 'all')) - refchan = 1:Nchans; -end - -% compute the average value over the reference channels -ref = mean(dat(refchan,:), 1); - -% apply the new reference to the data -for chan=1:Nchans - dat(chan,:) = dat(chan,:) - ref; -end diff --git a/external/fieldtrip/private/preproc_standardize.m b/external/fieldtrip/private/preproc_standardize.m deleted file mode 100644 index 5ceb2b3..0000000 --- a/external/fieldtrip/private/preproc_standardize.m +++ /dev/null @@ -1,44 +0,0 @@ -function x = preproc_standardize(x, begsample, endsample) - -% PREPROC_STANDARDIZE performs a z-transformation or standardization -% of the data. The standardized data will have a zero-mean and a unit -% standard deviation. -% -% Use as -% [dat] = preproc_standardize(dat, begsample, endsample) -% where -% dat data matrix (Nchans X Ntime) -% begsample index of the begin sample for the mean and stdev estimate -% endsample index of the end sample for the mean and stdev estimate -% -% If no begin and end sample are specified, it will be estimated on the -% complete data. -% -% See also PREPROC - -% Copyright (C) 2008, Robert Oostenveld -% -% $Log: preproc_standardize.m,v $ -% Revision 1.2 2009/09/30 13:02:03 jansch -% fixed typo in comment -% -% Revision 1.1 2008/11/10 20:58:32 roboos -% new function, original was used in trialfun_emg -% - -% determine the size of the input data: nChans X nSamples -[m,n] = size(x); - -% this function operates along the 2nd dimension -dim = 2; - -if nargin>1 - mx = mean(x(:,begsample:endsample),dim); - sx = std(x(:,begsample:endsample),0,dim); -else - mx = mean(x,dim); - sx = std(x,0,dim); -end - -x = (x - repmat(mx,[1 n]))./repmat(sx,[1 n]); - diff --git a/external/fieldtrip/private/preprocessing.m b/external/fieldtrip/private/preprocessing.m deleted file mode 100644 index 9dc402e..0000000 --- a/external/fieldtrip/private/preprocessing.m +++ /dev/null @@ -1,701 +0,0 @@ -function [data] = preprocessing(cfg, data); - -% PREPROCESSING reads MEG and/or EEG data according to user-specified trials -% and applies several user-specified preprocessing steps to the signals. -% -% Use as -% [data] = preprocessing(cfg) -% or -% [data] = preprocessing(cfg, data) -% -% The first input argument "cfg" is the configuration structure, which -% contains all details for the dataset filenames, trials and the -% preprocessing options. You can only do preprocessing after defining the -% segments of data to be read from the file (i.e. the trials), which is for -% example done based on the occurence of a trigger in the data. -% -% If you are calling PREPROCESSING with only the configuration as first -% input argument and the data still has to be read from file, you should -% specify -% cfg.dataset = string with the filename -% cfg.trl = Nx3 matrix with the trial definition, see DEFINETRIAL -% cfg.padding = length to which the trials are padded for filtering -% cfg.continuous = 'yes' or 'no' whether the file contains continuous data -% (default is determined automatic) -% -% Instead of specifying the dataset, you can also explicitely specify the -% name of the file containing the header information and the name of the -% file containing the data, using -% cfg.datafile = string with the filename -% cfg.headerfile = string with the filename -% -% If you are calling PREPROCESSING with also the second input argument -% "data", then that should contain data that was already read from file in -% a previous call to PREPROCESSING. In that case only the configuration -% options below apply. -% -% The channels that will be read and/or preprocessed are specified with -% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), -% see CHANNELSELECTION for details -% -% The preprocessing options for the selected channels are specified with -% cfg.lpfilter = 'no' or 'yes' lowpass filter -% cfg.hpfilter = 'no' or 'yes' highpass filter -% cfg.bpfilter = 'no' or 'yes' bandpass filter -% cfg.bsfilter = 'no' or 'yes' bandstop filter -% cfg.dftfilter = 'no' or 'yes' line noise removal using discrete fourier transform -% cfg.medianfilter = 'no' or 'yes' jump preserving median filter -% cfg.lpfreq = lowpass frequency in Hz -% cfg.hpfreq = highpass frequency in Hz -% cfg.bpfreq = bandpass frequency range, specified as [low high] in Hz -% cfg.bsfreq = bandstop frequency range, specified as [low high] in Hz -% cfg.dftfreq = line noise frequencies for DFT filter, default [50 100 150] Hz -% cfg.lpfiltord = lowpass filter order -% cfg.hpfiltord = highpass filter order -% cfg.bpfiltord = bandpass filter order -% cfg.bsfiltord = bandstop filter order -% cfg.lpfilttype = digital filter type, 'but' (default) or 'fir' -% cfg.hpfilttype = digital filter type, 'but' (default) or 'fir' -% cfg.bpfilttype = digital filter type, 'but' (default) or 'fir' -% cfg.bsfilttype = digital filter type, 'but' (default) or 'fir' -% cfg.lpfiltdir = filter direction, 'twopass' (default), 'onepass' or 'onepass-reverse' -% cfg.hpfiltdir = filter direction, 'twopass' (default), 'onepass' or 'onepass-reverse' -% cfg.bpfiltdir = filter direction, 'twopass' (default), 'onepass' or 'onepass-reverse' -% cfg.bsfiltdir = filter direction, 'twopass' (default), 'onepass' or 'onepass-reverse' -% cfg.medianfiltord = length of median filter -% cfg.blc = 'no' or 'yes' -% cfg.blcwindow = [begin end] in seconds, the default is the complete trial -% cfg.detrend = 'no' or 'yes', this is done on the complete trial -% cfg.polyremoval = 'no' or 'yes', this is done on the complete trial -% cfg.polyorder = polynome order (default = 2) -% cfg.derivative = 'no' (default) or 'yes', computes the first order derivative of the data -% cfg.hilbert = 'no', 'abs', 'complex', 'real', 'imag', 'absreal', 'absimag' or 'angle' (default = 'no') -% cfg.rectify = 'no' or 'yes' -% cfg.precision = 'single' or 'double' (default = 'double') -% -% Preprocessing options that you should only use for EEG data are -% cfg.reref = 'no' or 'yes' (default = 'no') -% cfg.refchannel = cell-array with new EEG reference channel(s) -% cfg.implicitref = 'label' or empty, add the implicit EEG reference as zeros (default = []) -% cfg.montage = 'no' or a montage structure (default = 'no') -% -% Preprocessing options that you should only use when you are calling PREPROCESSING with -% also the second input argument "data" are -% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') - -% Undocumented local options: -% cfg.artfctdef -% cfg.removemcg -% cfg.output.dataset -% cfg.output.dataformat -% -% This function depends on PREPROC which has the following options: -% cfg.absdiff -% cfg.boxcar -% cfg.polyremoval, documented -% cfg.polyorder, documented -% cfg.blc, documented -% cfg.blcwindow, documented -% cfg.bpfilter, documented -% cfg.bpfiltord, documented -% cfg.bpfilttype, documented -% cfg.bpfreq, documented -% cfg.bsfilter, documented -% cfg.bsfiltord, documented -% cfg.bsfilttype, documented -% cfg.bsfreq, documented -% cfg.derivative, documented -% cfg.detrend, documented -% cfg.dftfilter, documented -% cfg.dftfreq, documented -% cfg.hilbert, documented -% cfg.hpfilter, documented -% cfg.hpfiltord, documented -% cfg.hpfilttype, documented -% cfg.hpfreq, documented -% cfg.implicitref, documented -% cfg.lpfilter, documented -% cfg.lpfiltord, documented -% cfg.lpfilttype, documented -% cfg.lpfreq, documented -% cfg.medianfilter, documented -% cfg.medianfiltord, documented -% cfg.rectify, documented -% cfg.refchannel, documented -% cfg.reref, documented - -% Copyright (C) 2003-2007, Robert Oostenveld, SMI, FCDC -% -% $Log: preprocessing.m,v $ -% Revision 1.111 2009/10/08 19:03:28 roboos -% in case of continuous, also use hdr.nSamplesPre for reading in complete data as single trial -% -% Revision 1.110 2009/10/01 11:39:36 jansch -% also put offset-field in output if nargin>1 and hasoffset -% -% Revision 1.109 2009/09/08 14:23:21 roboos -% changed the syntaxt for concatenation of implicitref to cfg.channel -% -% Revision 1.108 2009/06/17 13:44:14 roboos -% fixed output label in case of rereferencing with a montage -% -% Revision 1.107 2009/06/17 10:14:26 roboos -% added support for preprocessing data from disk and immediate writing to disk (trial by trial), which allows for preprocessing very large datasets without having them completely in memory (e.g. rereferencing sdma datasets) -% -% Revision 1.106 2009/01/28 10:24:04 jansch -% changed dataformat in call to checkdata into datatype -% -% Revision 1.105 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.104 2009/01/14 11:31:57 sashae -% changed handling of cfg.datatype -% -% Revision 1.103 2008/12/02 15:28:49 estmee -% Changes to make cfg.datatype deprecated. -% -% Revision 1.102 2008/11/11 18:59:25 sashae -% added call to checkconfig at end of function (trackconfig and checksize) -% -% Revision 1.101 2008/10/13 13:42:02 sashae -% added call to checkconfig -% -% Revision 1.100 2008/10/10 14:41:22 sashae -% replaced call to dataset2files with checkconfig -% -% Revision 1.99 2008/09/23 14:12:22 sashae -% checkconfig: checks if the input cfg is valid for this function -% -% Revision 1.98 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.97 2008/07/30 07:44:14 roboos -% changed some whitespace and comments -% -% Revision 1.96 2008/07/21 20:10:05 roboos -% added explicit error in case trialdef is present without cfg.trl -% -% Revision 1.95 2008/07/11 13:18:40 roboos -% removed all lnfilter references, added error to preprocessing and preproc -% -% Revision 1.94 2008/07/08 08:15:11 sashae -% updated documentation, removed lnfilter -% -% Revision 1.93 2008/06/26 15:31:34 roboos -% added cfg.headerformat and dataformat, these are passed to low-level readers and allow overriding the auto-detected format -% -% Revision 1.92 2008/06/25 06:36:49 roboos -% use new API for read_data instead of old one -% -% Revision 1.91 2008/06/24 12:47:12 roboos -% added cfg.montage as alternative for rereferencing -% -% Revision 1.90 2008/05/13 15:37:24 roboos -% switched to using read_data/header instead of the read_fcdc_data/header wrapper functions -% -% Revision 1.89 2008/05/06 15:43:46 sashae -% change in trial selection, cfg.trials can be logical -% -% Revision 1.88 2008/03/04 16:37:04 roboos -% automatically read continuous or trial based data, this reads all data into memory -% -% Revision 1.87 2008/02/06 16:23:05 sashae -% added option for trial selection (only pertains to call of preprocessing with already preprocessed data) -% -% Revision 1.86 2007/11/21 23:57:02 roboos -% added default cfg.bsfilter=no -% -% Revision 1.85 2007/11/14 13:15:44 roboos -% fixed bug: also use filter padding for bandstopfilter, thanks to Saskia -% -% Revision 1.84 2007/11/08 10:09:50 roboos -% allow other versions of the hilbert transformed signal to be computed (e.g. complex, real, imag) -% -% Revision 1.83 2007/09/24 10:11:13 ingnie -% relevant fields of input data are copied to output data when preprocessing is done on data which is already read, try catch replaced be if isfield -% -% Revision 1.82 2007/09/20 12:58:23 roboos -% added possibility for preprocessing data that was already preprocessed (i.e. filter sequentially) -% -% Revision 1.81 2007/08/01 15:12:51 ingnie -% added documentation on polyremoval option -% -% Revision 1.80 2007/07/03 15:57:13 roboos -% added hack to support 32 bit Neuroscan cnt format, thanks to Nathan Weisz -% -% Revision 1.79 2007/05/30 13:24:43 roboos -% renamed the hidden option cfg.datatype to cfg.continuous=yes/no and added it to the documentation -% -% Revision 1.78 2007/05/02 15:23:07 roboos -% added option for bandstopfiltering -% -% Revision 1.77 2007/01/09 09:49:53 roboos -% allow numeric channel selections, give warning when cfg.rejectxxx is present (since deprecated) -% -% Revision 1.76 2007/01/04 17:07:37 roboos -% only call definetrial and rejectartifact if really needed, give a warning in that case (is deprecated) -% -% Revision 1.75 2006/11/29 09:06:36 roboos -% renamed all cfg options with "sgn" into "channel", added backward compatibility when required -% updated documentation, mainly in the artifact detection routines -% -% Revision 1.74 2006/10/04 07:10:07 roboos -% updated documentation -% -% Revision 1.73 2006/08/31 07:56:05 roboos -% added onepass-reverse filter to documentation -% -% Revision 1.72 2006/06/14 12:51:01 roboos -% updated documentation -% -% Revision 1.71 2006/06/14 12:43:54 roboos -% removed the documentation for cfg.lnfilttype, since that option is not supported by preproc -% -% Revision 1.70 2006/06/14 11:52:06 roboos -% changed some comments, minor change to the handling of cfg.padding -% -% Revision 1.69 2006/06/13 14:48:09 ingnie -% updated documentation -% -% Revision 1.68 2006/05/30 20:57:15 roboos -% updated documentation -% -% Revision 1.67 2006/04/27 11:18:34 chrhes -% reinstated the default setting for the 'medianfilter' option since that was still broken, and changed a few words in the documentation. -% -% Revision 1.66 2006/04/25 20:20:46 roboos -% moved some of the sanity checks from preprocessing to private/preproc -% reinserted the default of some of the cfg settings, since that was broken -% -% Revision 1.65 2006/04/25 17:03:17 ingnie -% updated documentation and removed defaults that were also present in preproc.m from code -% -% Revision 1.64 2006/04/20 09:58:34 roboos -% updated documentation -% -% Revision 1.63 2005/11/23 10:44:11 roboos -% added bp/lp/hp/lnfilttype to the documentation -% -% Revision 1.62 2005/09/14 07:47:11 roboos -% added support for single precision data as output -% -% Revision 1.61 2005/09/02 13:51:39 roboos -% added defaulf cfg.dftfreq=[50 100 150], added new option to documentation -% -% Revision 1.60 2005/08/05 09:16:22 roboos -% removed the obsolete data.offset -% -% Revision 1.59 2005/05/17 17:50:37 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.58 2005/05/04 07:28:41 roboos -% changed fprintf into progress, added cfg.feedback default -% -% Revision 1.57 2005/04/13 08:48:38 roboos -% changed tab to space in a comment -% -% Revision 1.56 2005/01/25 13:59:57 roboos -% added check for cfg.datatype=continous and extended the call to read_fcdc_data with the boundary check for non-continous data -% -% Revision 1.55 2005/01/21 15:23:31 roboos -% added default for medianfilter and medianfilterord -% -% Revision 1.54 2005/01/21 09:53:11 roboos -% implemented median filter in preproc, updated help -% -% Revision 1.53 2005/01/10 16:52:11 roboos -% modifield the piece of code that does the actual preprocessing to use the -% private/preproc function. This ensures consistency with all other functions -% that perform filtering, etc. -% -% Revision 1.52 2004/12/06 12:43:03 roboos -% added warning for inconsistent EEG-rereferencing configuration -% -% Revision 1.51 2004/11/17 08:58:02 roboos -% re-ordered help and included description of cfg.detrend -% changed order of preprocessing: hilbert and rectify as last options -% removed the modification of the padding for integer number of line-noise cycles, this only worked if padding was unequal to 0 -% the dftfilter function now takes care of ensuring that the sine wave is estimated on a integer number of line-noise cycles -% -% Revision 1.50 2004/11/15 09:17:14 roboos -% moved dataset to filename conversion into separate function (private/dataset2files) -% -% Revision 1.49 2004/10/01 09:53:45 roboos -% added one line of comments -% -% Revision 1.48 2004/09/22 10:20:27 roboos -% converted to use external subfunctions time2offset and offset2time -% and add offset field to data structure if it is missing -% -% Revision 1.47 2004/09/14 11:10:48 jansch -% fixed bug in sanity check concerning bpfiltering in conjunction with -% hilbert-transformation -% -% Revision 1.46 2004/08/20 06:57:19 roboos -% removed channel specific processing options for EMG and EEG, these are now applied to all channels -% updated and restructured help, added some extra configuration checks -% -% Revision 1.45 2004/08/05 08:58:51 roboos -% added reference to DEFINETRIAL in help -% -% Revision 1.44 2004/06/28 15:03:28 olejen -% removed empty line -% -% Revision 1.43 2004/06/28 15:02:01 roboos -% added empty line to demonstrate Ole -% -% Revision 1.42 2004/06/24 12:09:50 roberto -% removed old version information -% -% Revision 1.41 2004/06/24 10:13:43 roberto -% cosmetical changes in comments only -% -% Revision 1.40 2004/06/03 15:50:20 roberto -% removed experimental event handling, should be part of definetrial and further users own responsibility -% -% Revision 1.39 2004/05/27 15:48:56 roberto -% added cfg.removeeog and added handle for functino that should be implemented by Ali - -fieldtripdefs - -cfg = checkconfig(cfg, 'trackconfig', 'on'); - -% set the defaults -if ~isfield(cfg, 'channel'), cfg.channel = {'all'}; end -if ~isfield(cfg, 'removemcg'), cfg.removemcg = 'no'; end -if ~isfield(cfg, 'removeeog'), cfg.removeeog = 'no'; end -if ~isfield(cfg, 'feedback'), cfg.feedback = 'text'; end -if ~isfield(cfg, 'precision'), cfg.precision = 'double'; end -if ~isfield(cfg, 'padding'), cfg.padding = 0; end % padding is only done when filtering -if ~isfield(cfg, 'headerformat'), cfg.headerformat = []; end % is passed to low-level function, empty implies autodetection -if ~isfield(cfg, 'dataformat'), cfg.dataformat = []; end % is passed to low-level function, empty implies autodetection - -% these options relate to the actual preprocessing, it is neccessary to specify here because of padding -if ~isfield(cfg, 'dftfilter'), cfg.dftfilter = 'no'; end -if ~isfield(cfg, 'lpfilter'), cfg.lpfilter = 'no'; end -if ~isfield(cfg, 'hpfilter'), cfg.hpfilter = 'no'; end -if ~isfield(cfg, 'bpfilter'), cfg.bpfilter = 'no'; end -if ~isfield(cfg, 'bsfilter'), cfg.bsfilter = 'no'; end -if ~isfield(cfg, 'medianfilter'), cfg.medianfilter = 'no'; end -% these options relate to the actual preprocessing, it is neccessary to specify here because of channel selection -if ~isfield(cfg, 'reref'), cfg.reref = 'no'; end -if ~isfield(cfg, 'refchannel'), cfg.refchannel = {}; end -if ~isfield(cfg, 'implicitref'), cfg.implicitref = []; end - -% support for the following options was removed on 20 August 2004 in Revision 1.46 -if isfield(cfg, 'emgchannel'), error('EMG specific preprocessing is not supported any more'); end -if isfield(cfg, 'emghpfreq'), error('EMG specific preprocessing is not supported any more'); end -if isfield(cfg, 'emgrectify'), error('EMG specific preprocessing is not supported any more'); end -if isfield(cfg, 'emghilbert'), error('EMG specific preprocessing is not supported any more'); end -if isfield(cfg, 'eegchannel'), error('EEG specific preprocessing is not supported any more'); end -if isfield(cfg, 'resamplefs'), error('resampling is not supported any more, see RESAMPLEDATA'); end - -if isfield(cfg, 'lnfilter') && strcmp(cfg.lnfilter, 'yes') - error('line noise filtering using the option cfg.lnfilter is not supported any more, use cfg.bsfilter instead') -end - -if nargin>1 - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % do preprocessing of data that has already been read - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - % the input data must be raw - data = checkdata(data, 'datatype', 'raw', 'hasoffset', 'yes'); - - % check if the input cfg is valid for this function - cfg = checkconfig(cfg, 'forbidden', {'trl', 'dataset', 'datafile', 'headerfile'}); - - if cfg.padding>0 - error('cfg.padding should be zero, since filter padding is only possible while reading the data from file'); - end - - % set the defaults - if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end - - % select trials of interest - if ~strcmp(cfg.trials, 'all') - if islogical(cfg.trials), cfg.trials=find(cfg.trials); end - fprintf('selecting %d trials\n', length(cfg.trials)); - data.trial = data.trial(cfg.trials); - data.time = data.time(cfg.trials); - data.offset = data.offset(cfg.trials); - end - - % translate the channel groups (like 'all' and 'MEG') into real labels - cfg.channel = channelselection(cfg.channel, data.label); - rawindx = match_str(data.label, cfg.channel); - - % this will contain the newly processed data - dataout = []; - - progress('init', cfg.feedback, 'preprocessing'); - ntrl = length(data.trial); - for i=1:ntrl - progress(i/ntrl, 'preprocessing trial %d from %d\n', i, ntrl); - % do the preprocessing on the selected channels - [dataout.trial{i}, dataout.label, dataout.time{i}, cfg] = preproc(data.trial{i}(rawindx,:), data.label(rawindx), data.fsample, cfg, data.offset(i)); - - if isfield(cfg, 'output') && ~isempty(cfg.output) - % write the processed data to file - newhdr = []; - newhdr.Fs = hdr.Fs; - newhdr.label = label; - newhdr.nChans = length(newhdr.label); - - % only append for the second and consecutive trials - write_data(cfg.output.dataset, dataout.trial{i}, 'dataformat', cfg.output.dataformat, 'header', newhdr, 'append', i~=1); - - if nargout==0 - % don't keep the data in memory - dataout.trial{i} = []; - end - end - - end % for all trials - progress('close'); - - % update the trial definition (trl) in case of trial selection - if ~strcmp(cfg.trials, 'all') - % try to locate the trl in the nested configuration - if isfield(data, 'cfg') - trl = findcfg(data.cfg, 'trl'); - else - trl = []; - end - if isempty(trl) - % a trial definition is expected in each continuous data set - warning('could not locate the trial definition ''trl'' in the data structure'); - else - cfg.trlold=trl; - cfg.trl=trl(cfg.trials,:); - end - end - - % get the output cfg - cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - - % remember the configuration details of the input data - if isfield(data, 'cfg'); cfg.previous = data.cfg; end - - % take along relevant fields of input data to output data - if isfield(data, 'hdr'), dataout.hdr = data.hdr; end - if isfield(data, 'fsample'), dataout.fsample = data.fsample; end - if isfield(data, 'grad'), dataout.grad = data.grad; end - if isfield(data, 'elec'), dataout.elec = data.elec; end - if isfield(data, 'offset'), dataout.offset = data.offset; end - - % replace the input data with the output data - data = dataout; - -else - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % read the data from file and do the preprocessing - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - if isfield(cfg, 'trialdef') && ~isfield(cfg, 'trl') - error('you must call DEFINETRIAL prior to PREPROCESSING'); - end - - % check if the input cfg is valid for this function - cfg = checkconfig(cfg, 'dataset2files', {'yes'}); - cfg = checkconfig(cfg, 'required', {'headerfile', 'datafile'}); - cfg = checkconfig(cfg, 'renamed', {'datatype', 'continuous'}); - cfg = checkconfig(cfg, 'renamedval', {'continuous', 'continuous', 'yes'}); - - % read the header - hdr = read_header(cfg.headerfile, 'headerformat', cfg.headerformat); - - % this option relates to reading over trial boundaries in a pseudo-continuous dataset - if ~isfield(cfg, 'continuous') - if hdr.nTrials==1 - cfg.continuous = 'yes'; - else - cfg.continuous = 'no'; - end - end - - % this should be a cell array - if ~iscell(cfg.channel) && ischar(cfg.channel) - cfg.channel = {cfg.channel}; - end - - % this should be a cell array - if ~iscell(cfg.refchannel) && ischar(cfg.refchannel) - cfg.refchannel = {cfg.refchannel}; - end - - % do a sanity check for the re-referencing - if strcmp(cfg.reref, 'no') && ~isempty(cfg.refchannel) - warning('no re-referencing is performed'); - cfg.refchannel = {}; - end - - % translate the channel groups (like 'all' and 'MEG') into real labels - cfg.channel = channelselection(cfg.channel, hdr.label); - - if ~isempty(cfg.implicitref) - % add the label of the implicit reference channel to these cell-arrays - cfg.channel = cat(1, cfg.channel(:), cfg.implicitref); - end - cfg.refchannel = channelselection(cfg.refchannel, cfg.channel); - - % determine the length in samples to which the data should be padded before filtering is applied - % the filter padding is done by reading a longer segment of data from the original data file - if cfg.padding>0 - if strcmp(cfg.dftfilter, 'yes') || ... - strcmp(cfg.lpfilter, 'yes') || ... - strcmp(cfg.hpfilter, 'yes') || ... - strcmp(cfg.bpfilter, 'yes') || ... - strcmp(cfg.bsfilter, 'yes') || ... - strcmp(cfg.medianfilter, 'yes') - padding = round(cfg.padding * hdr.Fs); - else - % no filtering will be done, hence no padding is neccessary - padding = 0; - end - % update the configuration (in seconds) for external reference - cfg.padding = padding / hdr.Fs; - else - % no padding was requested - padding = 0; - end - - if ~isfield(cfg, 'trl') - % treat the data as continuous if possible, otherwise define all trials as indicated in the header - if strcmp(cfg.continuous, 'yes') - trl = zeros(1, 3); - trl(1,1) = 1; - trl(1,2) = hdr.nSamples*hdr.nTrials; - trl(1,3) = -hdr.nSamplesPre; - else - trl = zeros(hdr.nTrials, 3); - for i=1:hdr.nTrials - trl(i,1) = (i-1)*hdr.nSamples + 1; - trl(i,2) = (i )*hdr.nSamples ; - trl(i,3) = -hdr.nSamplesPre; - end - end - cfg.trl = trl; - end - - if any(strmatch('reject', fieldnames(cfg))) || ... - any(strmatch('rejecteog', fieldnames(cfg))) || ... - any(strmatch('rejectmuscle', fieldnames(cfg))) || ... - any(strmatch('rejectjump', fieldnames(cfg))) - % this is only for backward compatibility - error('you should call REJECTARTIFACT prior to PREPROCESSING, please update your scripts'); - end - - ntrl = size(cfg.trl,1); - if ntrl<1 - error('no trials were selected for preprocessing, see DEFINETRIAL for help'); - end - - % compute the template for MCG and the QRS latency indices, and add it to the configuration - if strcmp(cfg.removemcg, 'yes') - cfg = template_mcg(cfg); - mcgchannel = channelselection(cfg.artfctdef.mcg.channel, hdr.label); - mcgindx = match_str(cfg.channel, mcgchannel); - for i=1:length(mcgchannel) - fprintf('removing mcg on channel %s\n', mcgchannel{i}); - end - end - - % determine the channel numbers of interest for preprocessing - [chnindx, rawindx] = match_str(cfg.channel, hdr.label); - - progress('init', cfg.feedback, 'reading and preprocessing'); - for i=1:ntrl - progress(i/ntrl, 'reading and preprocessing trial %d from %d\n', i, ntrl); - % non-zero padding is used for filtering and line noise removal - nsamples = cfg.trl(i,2)-cfg.trl(i,1)+1; - if nsamples>padding - % the trial is already longer than the total lenght requested - begsample = cfg.trl(i,1); - endsample = cfg.trl(i,2); - begpadding = 0; - endpadding = 0; - else - % begpadding+nsamples+endpadding = total length of raw data that will be read - begpadding = ceil((padding-nsamples)/2); - endpadding = floor((padding-nsamples)/2); - begsample = cfg.trl(i,1) - begpadding; - endsample = cfg.trl(i,2) + endpadding; - if begsample<1 - warning('cannot apply enough padding at begin of file'); - begpadding = begpadding - (1 - begsample); - begsample = 1; - end - if endsample>(hdr.nSamples*hdr.nTrials) - warning('cannot apply enough padding at end of file'); - endpadding = endpadding - (endsample - hdr.nSamples*hdr.nTrials); - endsample = hdr.nSamples*hdr.nTrials; - end - end - - % ONLY RELEVANT FOR NEUROSCAN CNT - if ~isfield(cfg, 'nsdf') - hdr.nsdf=16; - else - hdr.nsdf=cfg.nsdf; - end - - % read the raw data with padding on both sides of the trial - dat = read_data(cfg.datafile, 'header', hdr, 'begsample', begsample, 'endsample', endsample, 'chanindx', rawindx, 'checkboundary', strcmp(cfg.continuous, 'no'), 'dataformat', cfg.dataformat); - - % do the preprocessing on the padded trial data and remove the padding after filtering - [cutdat{i}, label, time{i}, cfg] = preproc(dat, hdr.label(rawindx), hdr.Fs, cfg, cfg.trl(i,3), begpadding, endpadding); - - if isfield(cfg, 'output') && ~isempty(cfg.output) - % write the processed data to file - newhdr = []; - newhdr.Fs = hdr.Fs; - newhdr.label = label; - newhdr.nChans = length(newhdr.label); - - % only append for the second and consecutive trials - write_data(cfg.output.dataset, cutdat{i}, 'dataformat', cfg.output.dataformat, 'header', newhdr, 'append', i~=1); - - if nargout==0 - % don't keep the data in memory - cutdat{i} = []; - end - end - - % ONLY RELEVANT FOR NEUROSCAN CNT - hdr=rmfield(hdr,'nsdf'); - - end % for all trials - progress('close'); - - % collect the results - data.hdr = hdr; % header details of the datafile - data.label = label; % labels of channels that have been read, can be different from labels in file due to montage - data.trial = cutdat; % cell-array with TIMExCHAN - data.time = time; % vector with the timeaxis for each individual trial - data.fsample = hdr.Fs; - if isfield(hdr, 'grad') - data.grad = hdr.grad; % gradiometer system in head coordinates - end - - % get the output cfg - cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -end % if nargin>1 - -% add the version details of this function call to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: preprocessing.m,v 1.111 2009/10/08 19:03:28 roboos Exp $'; -% remember the exact configuration details in the output -data.cfg = cfg; - diff --git a/external/fieldtrip/private/procrustes_trans.m b/external/fieldtrip/private/procrustes_trans.m new file mode 100644 index 0000000..d4ff21a --- /dev/null +++ b/external/fieldtrip/private/procrustes_trans.m @@ -0,0 +1,80 @@ +function [h] = procrustes_trans(input,target) + +% PROCRUSTES_TRANS returns the homogenous coordinate transformation matrix +% that warps the specified input points to the target points. +% +% Use as +% [h] = procrustes_trans(input, target) +% where +% input Nx3 matrix with coordinates +% target Nx3 matrix with coordinates +% +% The algorithm used for the calculation of the rotation matrix is knonwn +% as the Procrustes method. Its use for MEG coordinate transformation has +% been suggested in Fuchs et al. TBME vol. 42, 1995, p. 416ff. +% +% See also WARP_OPTIM, HEADCOORDINATES + +% Copyright (C) 2010, Tilmann Sander-Thoemmes +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id$ + +ninp = size(input,1); +ntarg = size(target,1); + +% do basic checks +if ninp ~= ntarg, + error('you must specify same number of points for input and target'); +end +if ninp < 3, + error('you must specify at least three points for matching'); +end + +% calculate the center fo gravity +ctr_grav_inp = mean(input); +ctr_grav_targ = mean(target); + +% subtract center of gravity from points: set of directions is obtained +ipnt=input-repmat(ctr_grav_inp,ninp,1); +tpnt=target-repmat(ctr_grav_targ,ninp,1); + +% Procrustes: Calculate the best rotation matrix that transforms +% input to target directions in the least squares sense +P = ipnt'*tpnt; +[U,S,V] = svd(P); +% U*S*V' + +rotm = V*U'; +% det(rotm) +% Correcting for negative determinant: See Wikipedia on Orthogonal +% Procrustes Problem +if det(rotm)<0 + mirror=eye(3); + mirror(3,3) = -1; + rotm = V*mirror*U'; +end + +% With the rotation matrix the translation can be calculated +trans = ctr_grav_targ'-rotm*ctr_grav_inp'; + +% compute the full homogenous transformation matrix +h = eye(4); +h(1:3,1:3) = rotm; +h(1:3,4) = trans'; + diff --git a/external/fieldtrip/private/progress.m b/external/fieldtrip/private/progress.m deleted file mode 100644 index 1dd07ce..0000000 --- a/external/fieldtrip/private/progress.m +++ /dev/null @@ -1,264 +0,0 @@ -function progress(varargin) - -% PROGRESS shows a graphical or non-graphical progress indication similar -% to the standard Matlab WAITBAR function, but with the extra option of -% printing it in the command window as a plain text string or as a rotating -% dial. Alternatively, you can also specify it not to give feedback on the -% progress. -% -% Prior to the for-loop, you should call either -% progress('init', 'none', 'Please wait...') -% progress('init', 'gui', 'Please wait...') -% progress('init', 'etf', 'Please wait...') % estimated time to finish -% progress('init', 'dial', 'Please wait...') % rotating dial -% progress('init', 'textbar', 'Please wait...') % ascii progress bar -% progress('init', 'text', 'Please wait...') -% progress('init', 'textcr', 'Please wait...') % force cariage return -% progress('init', 'textnl', 'Please wait...') % force newline -% -% In each iteration of the for-loop, you should call either -% progress(x) % only show percentage -% progress(x, 'Processing event %d from %d', i, N) % show string, x=i/N -% -% After finishing the for-loop, you should call -% progress('close') -% -% Here is an example for the use of a progress indicator -% progress('init', 'etf', 'Please wait...'); -% for i=1:42 -% progress(i/42, 'Processing event %d from %d', i, 42); -% pause(0.1); -% end -% progress('close') - -% Copyright (C) 2004-2008, Robert Oostenveld -% -% $Log: progress.m,v $ -% Revision 1.2 2008/11/13 10:59:19 roboos -% added estimated time to finish (etf) and example -% -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.8 2007/05/08 20:55:03 roboos -% replaced all single & by double &&, hopefully resulting in a small speedup -% -% Revision 1.7 2006/12/11 10:52:32 roboos -% removed "feature accel off", since it was not solving the problem. -% The acceleration feature has to be disabled BEFORE this function -% is called the first time. -% -% Revision 1.6 2006/10/26 10:44:00 roboos -% fixed bug in double variable use -% -% Revision 1.5 2006/10/26 09:27:06 roboos -% added "feature accel off" to prevent matlab 7.3 from crashing -% -% Revision 1.4 2006/06/12 11:07:39 roboos -% modified the 1% update criterium, fixed a bug in the length of the textbar -% -% Revision 1.3 2005/03/31 12:22:38 roboos -% added ascii-art "textbar" option using the full screen width -% -% Revision 1.2 2004/10/22 07:23:39 roboos -% improved help, comments and code layout -% -% Revision 1.1 2004/10/21 17:37:17 roboos -% new implementation, to be used to replace subfunction in beamformer scan -% and in other fieldtrip functions -% - -persistent p % the previous value of the progress -persistent c % counter for the number of updates that is done -persistent t0 % initial time, required for ETF -persistent p0 % initial percentage, required for ETF -persistent t % type of feedback, string with none, gui, text, textcr, textnl -persistent h % the handle of the dialog (in case of type=gui) -persistent a % the angle in degrees, for dial or textbar -persistent s % the string containing the title - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if nargin>1 && ischar(varargin{1}) && strcmp(varargin{1}, 'init') - a = 0; - p = 0; - h = 0; - c = 0; - % determine the type of feedback - t = varargin{2}; - % determine the title of the dialog - if nargin>2 - s = varargin{3}; - else - s = ''; - end - switch t - case 'gui' - % initialise the waitbar dialog - if ~isempty(s) - h = waitbar(0, s); - else - h = waitbar(0, 'Please wait'); - end - case {'text', 'textnl', 'textcr'} - if ~isempty(s) - % print the title to the screen and go to the next line - fprintf('%s\n', s) - end - end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif nargin==1 && ischar(varargin{1}) && strcmp(varargin{1}, 'close') - switch t - case 'gui' - % close the waitbar dialog - close(h); - case {'textcr', 'dial', 'textbar'} - % finish by going to the next line - fprintf('\n'); - end - % reset these to the defaults - a = 0; - h = 0; - p = 0; - t = 'none'; - s = ''; - t0 = []; - p0 = []; - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -else - if strcmp(t, 'dial') - % display should always be updated for the dial - % continue; - elseif (varargin{1}-p)<0.01 && strcmp(t, 'gui') - % display should not be updated it the difference is less than one percent - return; - elseif (varargin{1}-p)<0.01 && strcmp(t, 'textbar') - % display should not be updated it the difference is less than one percent - return; - elseif (varargin{1}-p)<0.01 && strcmp(t, 'etf') - % display should not be updated it the difference is less than one percent - return; - end - - % count the number of updates, for debugging - c = c+1; - - % remember the current value for the next function call - p = varargin{1}; - - switch t - case 'gui' - % update the the length of the bar in the waitbar dialog - waitbar(varargin{1}, h); - - case 'etf' - % compute the estimated time that the computation still needs to finish - if isempty(t0) || isempty(p0) - t0 = clock; - p0 = p; - end - elapsed = etime(clock, t0); - if nargin>1 && ~isempty(varargin{2}) - % include the specified string - fprintf(varargin{2:end}); - fprintf(' - estimated time to finish is %d seconds\n', round(elapsed*(1-p)/(p-p0))); - else - % only print the estimated time to finish - fprintf(' - estimated time to finish is %d seconds\n', round(elapsed*(1-p)/(p-p0))); - end - - case 'dial' - dial = '|/-\|/-\'; - if ~isempty(s) - % print the title and draw a new hand of the rotating dial - fprintf('\r%s %s', s, dial(1+a/45)); - else - % draw a new hand of the rotating dial - fprintf('\r%s', dial(1+a/45)); - end - % increment the angle with 45 degrees - a = a + 45; - if a==360 - % reset the angle to 0 degrees - a = 0; - end - - case 'textbar' - dial = '|/-\|/-\'; - % construct the line looking like [------/ ] - len = 75 - length(s) - 3; - len1 = round(p*len); % number of '-' characters before the dial - len2 = len - len1; % number of ' ' characters after the dial - line = [s, ' [' repmat('-',1,len1), dial(1+a/45), repmat(' ',1,len2) ,']']; - fprintf('\r%s', line); - % increment the angle with 45 degrees - a = a + 45; - if a==360 - % reset the angle to 0 degrees - a = 0; - end - - case 'text' - if nargin>1 - % print the string as it is - fprintf(varargin{2:end}); - else - fprintf('%6.2f %%\n', 100*varargin{1}); - end - - case 'textnl' - if nargin>1 - % ensure that the string ends with a newline - if length(varargin{2})>1 && all(varargin{2}((end-1):end) == '\r') - varargin{2}((end-1):end) = '\n'; - elseif length(varargin{2})>1 && ~all(varargin{2}((end-1):end) == '\n') - varargin{2}((end+1):(end+2)) = '\n'; - elseif length(varargin{2})<2 - varargin{2}((end+1):(end+2)) = '\n'; - end - fprintf(varargin{2:end}); - else - fprintf('%6.2f %%\n', 100*varargin{1}); - end - - case 'textcr' - if nargin>1 - % ensure that the string ends with a cariage return - if length(varargin{2})>1 && all(varargin{2}((end-1):end) == '\n') - varargin{2}((end-1):end) = '\r'; - elseif length(varargin{2})>1 && ~all(varargin{2}((end-1):end) == '\r') - varargin{2}((end+1):(end+2)) = '\r'; - elseif length(varargin{2})<2 - varargin{2}((end+1):(end+2)) = '\r'; - end - fprintf(varargin{2:end}); - else - fprintf('%6.2f %%\r', 100*varargin{1}); - end - - end % case gui, dial, text, textnl, textcr -end % updating the displayed value - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% some test code follows -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% progress('init', 'gui'); for i=1:100, progress(i/100, '%d/%d\r', i, 100); end; progress('close') -% progress('init', 'dial'); for i=1:100, progress(i/100, '%d/%d\r', i, 100); end; progress('close') -% progress('init', 'none'); for i=1:100, progress(i/100, '%d/%d\r', i, 100); end; progress('close') - -% progress('init', 'text'); for i=1:100, progress(i/100, '%d/%d' , i, 100); end; progress('close') -% progress('init', 'text'); for i=1:100, progress(i/100, '%d/%d\n', i, 100); end; progress('close') -% progress('init', 'text'); for i=1:100, progress(i/100, '%d/%d\r', i, 100); end; progress('close') - -% progress('init', 'textnl'); for i=1:100, progress(i/100, '%d/%d' , i, 100); end; progress('close') -% progress('init', 'textnl'); for i=1:100, progress(i/100, '%d/%d\n', i, 100); end; progress('close') -% progress('init', 'textnl'); for i=1:100, progress(i/100, '%d/%d\r', i, 100); end; progress('close') - -% progress('init', 'textcr'); for i=1:100, progress(i/100, '%d/%d' , i, 100); end; progress('close') -% progress('init', 'textcr'); for i=1:100, progress(i/100, '%d/%d\n', i, 100); end; progress('close') -% progress('init', 'textcr'); for i=1:100, progress(i/100, '%d/%d\r', i, 100); end; progress('close') - - diff --git a/external/fieldtrip/private/project_elec.m b/external/fieldtrip/private/project_elec.m index 43961b6..6ff36e0 100644 --- a/external/fieldtrip/private/project_elec.m +++ b/external/fieldtrip/private/project_elec.m @@ -11,13 +11,23 @@ % Copyright (C) 1999-2002, Robert Oostenveld % -% $Log: project_elec.m,v $ -% Revision 1.1 2009/01/21 10:32:38 roboos -% moved from forwinv/* and forwinv/mex/* directory to forwinv/private/* to make the CVS layout consistent with the release version +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.2 2003/03/11 14:45:37 roberto -% updated help and copyrights +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: project_elec.m 946 2010-04-21 17:51:16Z roboos $ Nelc = size(elc,1); Npnt = size(pnt,1); diff --git a/external/fieldtrip/private/projecttri.m b/external/fieldtrip/private/projecttri.m index bd65a91..4529776 100644 --- a/external/fieldtrip/private/projecttri.m +++ b/external/fieldtrip/private/projecttri.m @@ -10,16 +10,23 @@ % Copyright (C) 2006, Robert Oostenveld % -% $Log: projecttri.m,v $ -% Revision 1.3 2009/09/23 09:05:39 roboos -% added delaunay method +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.2 2007/05/08 07:36:42 roboos -% updated help +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.1 2006/12/12 11:27:45 roboos -% created subfunction into a seperate function +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: projecttri.m 952 2010-04-21 18:29:51Z roboos $ if nargin<2 method = 'convhull'; diff --git a/external/fieldtrip/private/ptriproj.m b/external/fieldtrip/private/ptriproj.m index 6338e99..e8f6c54 100644 --- a/external/fieldtrip/private/ptriproj.m +++ b/external/fieldtrip/private/ptriproj.m @@ -1,29 +1,72 @@ -function [proj, dist] = ptriproj(v1, v2, v3, r, flag); +function [varargout] = funname(varargin) % PTRIPROJ projects a point onto the plane going through a triangle % -% [proj, dist] = ptriproj(v1, v2, v3, r, flag) -% +% Use as +% [proj, dist] = ptriproj(v1, v2, v3, r, flag) % where v1, v2 and v3 are three vertices of the triangle, and r is % the point that is projected onto the plane spanned by the vertices % % the optional flag can be: % 0 (default) project the point anywhere on the complete plane % 1 project the point within or on the edge of the triangle -% -% implemented as MEX file -% Copyright (C) 2002, Robert Oostenveld +% Copyright (C) 2002-2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% $Log: ptriproj.m,v $ -% Revision 1.4 2003/03/19 12:22:23 roberto -% fixed bug in function definition (added flag input parameter) +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.3 2003/03/11 15:35:20 roberto -% converted all files from DOS to UNIX +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.2 2003/03/04 21:46:19 roberto -% added CVS log entry and synchronized all copyright labels +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: ptriproj.m 946 2010-04-21 17:51:16Z roboos $ + +% compile the missing mex file on the fly +% remember the original working directory +pwdir = pwd; + +% determine the name and full path of this function +funname = mfilename('fullpath'); +mexsrc = [funname '.c']; +[mexdir, mexname] = fileparts(funname); + +try + % try to compile the mex file on the fly + warning('trying to compile MEX file from %s', mexsrc); + cd(mexdir); + + if ispc + mex -I. -c geometry.c + mex -I. -c ptriproj.c ; mex ptriproj.c ptriproj.obj geometry.obj + else + mex -I. -c geometry.c + mex -I. -c ptriproj.c ; mex -o ptriproj ptriproj.o geometry.o + end + + cd(pwdir); + success = true; + +catch + % compilation failed + disp(lasterr); + error('could not locate MEX file for %s', mexname); + cd(pwdir); + success = false; +end -error(sprintf('could not locate MEX file for %s', mfilename)) +if success + % execute the mex file that was juist created + funname = mfilename; + funhandle = str2func(funname); + [varargout{1:nargout}] = funhandle(varargin{:}); +end diff --git a/external/fieldtrip/private/ptriproj.mexmaci b/external/fieldtrip/private/ptriproj.mexmaci index 4a89244..7301ba5 100755 Binary files a/external/fieldtrip/private/ptriproj.mexmaci and b/external/fieldtrip/private/ptriproj.mexmaci differ diff --git a/external/fieldtrip/private/ptriproj.mexw32 b/external/fieldtrip/private/ptriproj.mexw32 index 6931de7..93b0df9 100644 Binary files a/external/fieldtrip/private/ptriproj.mexw32 and b/external/fieldtrip/private/ptriproj.mexw32 differ diff --git a/external/fieldtrip/private/ptriproj.mexw64 b/external/fieldtrip/private/ptriproj.mexw64 index 6c5676d..8ce7aab 100644 Binary files a/external/fieldtrip/private/ptriproj.mexw64 and b/external/fieldtrip/private/ptriproj.mexw64 differ diff --git a/external/fieldtrip/private/randsample.m b/external/fieldtrip/private/randsample.m index 386058d..49ce696 100644 --- a/external/fieldtrip/private/randsample.m +++ b/external/fieldtrip/private/randsample.m @@ -14,10 +14,23 @@ % Copyright (C) 2007, Robert Oostenveld % -% $Log: randsample.m,v $ -% Revision 1.1 2007/07/04 16:06:10 roboos -% first implementation, thanks to the shower in Toulouse +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: randsample.m 952 2010-04-21 18:29:51Z roboos $ if nargin>2 error('only two input variables are supported'); diff --git a/external/fieldtrip/private/randstatprob.m b/external/fieldtrip/private/randstatprob.m index fd2ed5a..fcf9777 100644 --- a/external/fieldtrip/private/randstatprob.m +++ b/external/fieldtrip/private/randstatprob.m @@ -23,19 +23,23 @@ % Copyright (C) 2004-2005, Robert Oostenveld % -% $Log: randstatprob.m,v $ -% Revision 1.4 2005/11/16 09:10:21 roboos -% added support for multiple comparison correction using ordered statistics +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.3 2005/03/18 15:27:25 roboos -% renamed the first two input variable names to avoid confusion with the rand function +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.2 2004/11/15 11:17:55 roboos -% added multiple comparison correction +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.1 2004/11/11 17:24:19 roboos -% new implementation +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: randstatprob.m 952 2010-04-21 18:29:51Z roboos $ if nargin<3 tail = 0; diff --git a/external/fieldtrip/private/raw2data.m b/external/fieldtrip/private/raw2data.m index 5443a21..9e1eaaa 100644 --- a/external/fieldtrip/private/raw2data.m +++ b/external/fieldtrip/private/raw2data.m @@ -8,23 +8,23 @@ % Copyright (C) 2005, Robert Oostenveld % -% $Log: raw2data.m,v $ -% Revision 1.5 2006/02/24 15:37:14 roboos -% added the dimord to the output data +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.4 2006/02/01 12:26:04 roboos -% made all uses of dimord consistent with the common definition of data dimensions, see the fixdimord() function +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.3 2005/06/30 14:01:52 roboos -% fixed bug in output assignment of avg.time (should not be cell array), thanks to Ingrid +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.2 2005/06/02 15:29:22 roboos -% fixed error (a variable was called interp instead of data) -% -% Revision 1.1 2005/06/02 12:14:10 roboos -% new implementation for consistent conversion of averaged data (with either keepsubject or keepindividual) to raw trials as they come out of preprocessing -% these two helper functions are from now on used in freqanalysis, megplanar, megrealign, megrepair and in combineplanar +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: raw2data.m 952 2010-04-21 18:29:51Z roboos $ if isempty(dimord) % no conversion is needed diff --git a/external/fieldtrip/private/readBESAbsa.m b/external/fieldtrip/private/readBESAbsa.m deleted file mode 100644 index 43a9927..0000000 --- a/external/fieldtrip/private/readBESAbsa.m +++ /dev/null @@ -1,66 +0,0 @@ -function bsa = readBESAbsa(filename) - -% readBESAbsa reads information from a *.bsa file -% -% Use as -% bsa = readBESAbsa(filename) -% -% The output is a structure containing the following fields: -% CoordinateSystem: Coordinate System: -% HC = Head Coordinates -% US = Unit Sphere -% TC = Talairach Coordinates -% DC = Device Coordinates -% Coords: [Nsources x 3] matrix with source coordinates -% Orientation: [Nsources x 3] matrix with source orientations -% (x,y,z) -% (Orientation = [0 0 0] for regional sources) -% SourceType: Type of source: -% SngDip = Single Dipole -% RegSrc = Regional Source -% SptCmp = Spatial Component -% Labels: Source Labels (if assigned in BESA) -% -% Last modified April 26, 2006 Robert Oostenveld - -if isempty(findstr(filename,'.')) - filename = [filename,'.bsa']; -end -fp = fopen(filename); - -% Read the file -if (fp) - % Read header of .swf file - header = fgetl(fp); - if header(end-3)=='|' - bsa.CoordinateSystem = 'US'; - else - bsa.CoordinateSystem = header(end-1:end); - end - fgetl(fp); - fgetl(fp); - - for i=1:1000 - try % check if there is another waveform - Typ = cellstr(fscanf(fp,'%s',1)); - bsa.Coords(i,1) = fscanf(fp,'%f',1); - bsa.Coords(i,2) = fscanf(fp,'%f',1); - bsa.Coords(i,3) = fscanf(fp,'%f',1); - bsa.Orientation(i,1) = fscanf(fp,'%f',1); - bsa.Orientation(i,2) = fscanf(fp,'%f',1); - bsa.Orientation(i,3) = fscanf(fp,'%f',1); - bsa.SourceType(i) = Typ; - a = fgetl(fp); - b = a(findstr(a,'Label:')+6:end); - if ~isempty(b) - bsa.Labels(i) = cellstr(sscanf(b,'%s',1)); - else - bsa.Labels(i) = cellstr(''); - end - catch % stop if end of file is reached - break - end - end -end - -fclose(fp); \ No newline at end of file diff --git a/external/fieldtrip/private/readBESAimage.m b/external/fieldtrip/private/readBESAimage.m deleted file mode 100644 index a4b8ad3..0000000 --- a/external/fieldtrip/private/readBESAimage.m +++ /dev/null @@ -1,164 +0,0 @@ -function image = readBESAImage(filename) - -% readBESAimage reads information from exported BESA images (MSBF, BSPS, -% Sensitivity, Minimum Norm). -% -% Use as -% image = readBESAimage(filename) -% -% The output is a structure containing the following fields: -% Condition -% Coordinates -% Data -% DataFile -% DepthWeighting -% Dimension -% Frequency -% Imagemode -% Imagetype -% Latency -% Locations -% NoiseEstimation -% NoiseScaleFactor -% NoiseWeighting -% SelMeanNoise -% Source -% SpTmpWeighting -% SpTmpWeightingType -% Time -% TimeSamples -% Units -% Version -% -% Modified April 26, 2006 Robert Oostenveld -% Modified November 6, 2006 Karsten Hoechstetter - -if isempty(findstr(filename,'.')) - filename = [filename,'.dat']; -end -fp = fopen(filename); - -ImageVersion = fgetl(fp); - -% Check Version Number -% image.Version = str2num(ImageVersion(findstr(ImageVersion,':')+1:length(ImageVersion))); - -% Check type of Image -Imageinfo = ''; -if ~isempty(findstr(ImageVersion,'MN')) - image.Imagetype = 'Minimum Norm'; - image.Imagemode = ''; -else - fgetl(fp); - ImageInfo = fgetl(fp); - - if ~isempty(findstr(ImageInfo,'Sens.')) - image.Imagetype = 'Sensitivity'; - image.Imagemode = ''; - elseif ~isempty(findstr(ImageInfo,'MSBF')) - image.Imagetype = 'MSBF'; - if ~isempty(findstr(ImageInfo,'Image (TF)')) - image.Imagemode = 'Time-Frequency'; - else - image.Imagemode = 'Time'; - end - elseif ~isempty(findstr(ImageInfo,'MSPS')) - image.Imagetype = 'MSPS'; - if ~isempty(findstr(ImageInfo,'Image (TF)')) - image.Imagemode = 'Time-Frequency'; - else - image.Imagemode = 'Time'; - end - else - image.Imagetype = 'Unknown'; - image.Imagemode = 'Unknown'; - end - - if ImageInfo(end-3:end) == '[dB]' - image.Units = 'dB'; - else - image.Units = '%'; - end -end - -% Extract additional information (time and frequency, source, MN Info) -if strcmp(image.Imagemode,'Time-Frequency') - TimeSeparator = findstr(ImageInfo,' : '); - Blanks = findstr(ImageInfo,' '); - [x,Index] = min(abs(Blanks-TimeSeparator)); - TimeIndex=Blanks(Index-1); - image.Time = sscanf(ImageInfo(TimeIndex:end),'%s',4); - image.Frequency = sscanf(ImageInfo(findstr(ImageInfo,'ms')+3:end),'%s',2); -elseif strcmp(image.Imagetype,'Sensitivity') - image.Source = ImageInfo(findstr(ImageInfo,' - ')+3:end); -elseif strcmp(image.Imagetype,'Minimum Norm') - fgetl(fp); - h = fgetl(fp); image.DataFile = h(21:end); - h = fgetl(fp); image.Condition = h(21:end); - fgetl(fp); - h = fgetl(fp); image.DepthWeighting = h(21:end); - h = fgetl(fp); image.SpTmpWeighting = h(21:end); - h = fgetl(fp); image.SpTmpWeightingType = h(21:end); - h = fgetl(fp); image.Dimension = str2num(h(21:end)); - h = fgetl(fp); image.NoiseEstimation = h(21:end); - h = fgetl(fp); image.NoiseWeighting = h(21:end); - h = fgetl(fp); image.NoiseScaleFactor = str2num(h(21:end)); - h = fgetl(fp); image.SelMeanNoise = h(21:end); - fgetl(fp); - h = fgetl(fp); image.Locations = str2num(h(21:end)); - h = fgetl(fp); image.TimeSamples = str2num(h(21:end)); - fgetl(fp); fgetl(fp); fgetl(fp); -end - -% Get Coordinates and Data -if ~isempty(strmatch(image.Imagetype,strvcat('MSPS','MSBF','Sensitivity'))) - % Get Coordinates - fgetl(fp); fgetl(fp); - h = fgetl(fp); - hx = sscanf(h,'X: %f %f %d'); - xmin = hx(1); - xmax = hx(2); - xnum = hx(3); - h = fgetl(fp); - hy = sscanf(h,'Y: %f %f %d'); - ymin = hy(1); - ymax = hy(2); - ynum = hy(3); - h = fgetl(fp); - hz = sscanf(h,'Z: %f %f %d'); - zmin = hz(1); - zmax = hz(2); - znum = hz(3); - fgetl(fp); - - image.Coordinates=struct('X',{[xmin:floor((xmax-xmin)/(xnum-1)*10000)/10000:xmax]},... - 'Y',{[ymin:floor((ymax-ymin)/(ynum-1)*10000)/10000:ymax]},... - 'Z',{[zmin:floor((zmax-zmin)/(znum-1)*10000)/10000:zmax]}); - - % Get Data - image.Data = zeros(xnum,ynum,znum); - for z=1:znum - fgetl(fp); - a=fscanf(fp,'%f',[xnum,ynum]); - for x=1:xnum - for y=1:ynum - image.Data(x,y,z)=a(x,y); - end - end - fgetl(fp);fgetl(fp); - end - - % Minimum Norm Image -elseif ~isempty(strmatch(image.Imagetype,('Minimum Norm'))) - h = fscanf(fp,'Latency (milliseconds):'); - image.Latency = fscanf(fp,'%f',[1,image.TimeSamples]); - image.Coordinates = zeros(image.Locations,3); - image.Data = zeros(image.Locations,image.TimeSamples); - for i=1:image.Locations - h=fscanf(fp,'%f',[1,3]); - image.Coordinates(i,:) = h; - image.Data(i,:)=fscanf(fp,'%f',[1,image.TimeSamples]); - end -end - -fclose(fp); diff --git a/external/fieldtrip/private/readBESAmul.m b/external/fieldtrip/private/readBESAmul.m deleted file mode 100644 index 24d879d..0000000 --- a/external/fieldtrip/private/readBESAmul.m +++ /dev/null @@ -1,43 +0,0 @@ -function mul = readBESAmul(filename) - -% readBESAmul read information from a *.mul file -% -% Use as -% mul = readBESAMul(filename) -% -% The output is a structure containing the following fields: -% Npts: number of sample ponts -% TSB: latency of the first sample in the data files -% DI: time interval between two sample points -% Scale: scaling factor -% ChannelLabels: Channel labels -% Data: data matrix [Npts x Number of Channels] -% -% Last modified April 26, 2006 Robert Oostenveld - -if isempty(findstr(filename,'.')) - filename = [filename,'.mul']; -end - -fp = fopen(filename); - -% Read the file -if (fp) - % Read header of .swf file - headline=fscanf(fp,'TimePoints=%f Channels=%f BeginSweep[ms]=%f SamplingInterval[ms]=%f Bins/uV=%f'); - mul.Npts=headline(1); - NChan=headline(2); - mul.TSB=headline(3); - mul.DI=headline(4); - mul.Scale=headline(5); - fgets(fp); - for Channel=1:NChan - mul.ChannelLabels(Channel) = cellstr(fscanf(fp,'%s ',1)); - end - - mul.data=zeros(mul.Npts,NChan); - for i=1:mul.Npts - mul.data(i,:)=fscanf(fp,'%f',[1 NChan]); - end -end -fclose(fp); diff --git a/external/fieldtrip/private/readBESAsb.m b/external/fieldtrip/private/readBESAsb.m deleted file mode 100644 index a0bc21a..0000000 --- a/external/fieldtrip/private/readBESAsb.m +++ /dev/null @@ -1,56 +0,0 @@ -function [time,data,nEpochs] = readBESAsb(filename) - -% readBESAsb reads information from a *.dat, i.e. a simple binary data file -% -% This function requires a file with the same basename as the data name but -% suffix '.generic' or '.gen' to be located in the same folder. This file is -% generated automatically by BESA during file export. -% -% Use as -% [time,data,nEpochs] = readBESAsb(filename) -% -% The following output is generated: -% time: a vector containing the time points corresponding to the data -% points. Negative times are prestimulus -% data: The data matrix with dimension [nChannels x nEpochs x nSamples], -% where nChannels is the number of Channels and nSamples the number -% of samples within one epoch -% nEpochs (optional): The number of epochs contained in the file -% -% Last modified February 21, 2007 Karsten Hoechstetter - -if isempty(findstr(filename,'.dat')) - filename = [filename,'.dat']; -end - -fid=fopen([filename(1:end-4),'.generic'],'r'); -if fid==-1 - fid=fopen([filename(1:end-4),'.gen'],'r'); -end - -fscanf(fid,'BESA Generic Data\n'); -nChannels = fscanf(fid,'nChannels=%i\n'); -sRate = fscanf(fid,'sRate=%f\n'); -nSamples = fscanf(fid,'nSamples=%i\n'); -format = fscanf(fid,'format=%s'); -file = fscanf(fid,'\nfile=%s'); -prestimulus = fscanf(fid,'prestimulus=%f\n'); -epochs = fscanf(fid,'epochs=%i\n'); -fclose(fid); - -if isempty(epochs) - epochs=1; -end - -time=[-prestimulus:1/sRate*1000:(nSamples/epochs-1)*1000/sRate-prestimulus]; - -fid=fopen(filename, 'r', 'ieee-le'); -xdata=fread(fid,[nChannels,nSamples],'float32'); -fclose(fid); - -data=zeros(nChannels,epochs,nSamples/epochs); -for i=1:epochs - data(:,i,:)=xdata(:,1+(i-1)*nSamples/epochs:i*nSamples/epochs); -end -nEpochs=epochs; - diff --git a/external/fieldtrip/private/readBESAswf.m b/external/fieldtrip/private/readBESAswf.m deleted file mode 100644 index 8a1f8bb..0000000 --- a/external/fieldtrip/private/readBESAswf.m +++ /dev/null @@ -1,81 +0,0 @@ -function swf = readBESAswf(filename) - -% readBESAswf read all information from an *.swf file -% -% Note that the *.swf file must contain waveforms in rows and not in -% columns. -% -% Use as -% swf = readBESAswf(filename) -% -% The output is a structure containing the following fields: -% Npts: Number of time points -% Time: array of sampled time instants -% wavename: Labels of the different sources -% data: matrix of data points [Number of sources x Npts] -% -% Modified April 26, 2006 Robert Oostenveld -% Modified June 27, 2006 Karsten Hoechstetter: Function reads now both -% column and row swf formats - -if isempty(findstr(filename,'.')) - filename = [filename,'.swf']; -end -fp = fopen(filename); - -% Read the file -if (fp) - % Read header of .swf file - headline = fscanf(fp,'Npts= %f TSB= %f DI= %f SB= %f'); - % New BESA versions include more information in the .swf file header; skip that - i=1; - while i<1000 - a = fscanf(fp,'%c',1); - if strcmp(a,sprintf('\n')) - i=1000; - end - i=i+1; - end - swf.Npts=headline(1); - TSB=headline(2); - DI=headline(3); - swf.Time = [TSB:DI:TSB+(swf.Npts-1)*DI]; - - % Read first line after header to decide whether swf's are in rows or - % columns - row=1; - SecondLine = fgets(fp); - a=strfind(SecondLine,': '); - if a(end) >= length(SecondLine)-10 %swf's are in columns (because there is a ":" within the last 11 characters of the second line) - row=0; - end - - % Read data and labels - if row == 1 % swf's in rows - Name = sscanf(SecondLine,'%s',1); - swf.data(1,:) = sscanf(SecondLine(length(Name)+1:end),'%f',[1 headline(1)]); - swf.waveName(1) = cellstr(Name(1:length(Name)-1)); - for i=2:1000 - try % check if there is another waveform - Name = fscanf(fp,'%s',1); - swf.data(i,:) = fscanf(fp,'%f',[1,headline(1)]); - swf.waveName(i) = cellstr(Name(1:length(Name)-1)); - catch % stop if end of file is reached - break - end - end - else % swf's in columns - temp1 = SecondLine(1:a(1)-1); - temp2 = deblank(temp1(end:-1:1)); - swf.waveName(1) = cellstr(temp2(end:-1:1)); - for i=2:length(a) - temp1 = SecondLine(a(i-1)+2:a(i)-1); - temp2 = deblank(temp1(end:-1:1)); - swf.waveName(i) = cellstr(temp2(end:-1:1)); - end - swf.data = fscanf(fp,'%f',[length(a),headline(1)]); - i=length(a)+1; - end -end - -fclose(fp); \ No newline at end of file diff --git a/external/fieldtrip/private/readBESAtfc.m b/external/fieldtrip/private/readBESAtfc.m deleted file mode 100644 index cf6e3ce..0000000 --- a/external/fieldtrip/private/readBESAtfc.m +++ /dev/null @@ -1,86 +0,0 @@ -function tfc = readBESAtfc(filename) - -% readBESAtfc reads all information from a *.tfc file -% -% Use as -% tfc = readBESATFC(filename) -% -% The output is a structure containing the following fields: -% ChannelLabels: character array of channel labels -% Time: array of sampled time instants -% Frequency: array of sampled frequencies -% Data: 3D data matrix with indices (channel,time,frequency) -% DataType: type of the exported data -% ConditionName: name of analyzed condition -% NumberOfTrials: Number of trials on which the data is based -% StatisticsCorrection: Type of statistics correction for multiple testing -% EvokedSignalSubtraction: Type of evoked signal subtraction -% -% Last modified April 25, 2006 Karsten Hoechstetter -% Last modified April 26, 2006 Robert Oostenveld - -if isempty(findstr(filename,'.')) - filename = [filename,'.tfc']; -end -fp = fopen(filename); - -VersionNumber = fscanf(fp,'VersionNumber=%s '); -tfc.DataType = fscanf(fp,'DataType=%s '); -tfc.ConditionName = fscanf(fp,'ConditionName=%s '); - -% If the user has not specified a condition name, BESA defaults to -% "Condition 1" etc. This is the only instance where the condition -% name can have a blank -if strcmp(tfc.ConditionName,'Condition') - tfc.ConditionName = [tfc.ConditionName,' ',num2str(fscanf(fp,'%i '))]; -end -temp = fscanf(fp,'NumberTrials=%f NumberTimeSamples=%f TimeStartInMS=%f IntervalInMS=%f NumberFrequencies=%f FreqStartInHz=%f FreqIntervalInHz=%f NumberChannels=%i ' ); -tfc.NumberOfTrials = temp(1); -NumberTimeSamples = temp(2); -TimeStartInMS = temp(3); -TimeIntervalInMS = temp(4); -NumberFrequencies = temp(5); -FreqStartInHZ = temp(6); -FreqIntervalInHZ = temp(7); -NumberChannels = temp(8); - -% New file versions (BESA 5.0.8 and higher) include more information in the .tfc file header; skip that -vers=0; % new tfc file format -try - tfc.StatisticsCorrection = fscanf(fp,'StatisticsCorrection=%s '); - tfc.EvokedSignalSubtraction = fscanf(fp,'EvokedSignalSubtraction=%s'); -catch - vers=1; % old tfc file format -end - -% Handle possible future extensions of the tfc file header -i=1; -while i<1000 - a = fscanf(fp,'%c',1); - if strcmp(a,sprintf('\n')) - i=1000; - end - i=i+1; -end - -% Generate return values -tfc.Time = TimeStartInMS:TimeIntervalInMS:(NumberTimeSamples-1)*TimeIntervalInMS+TimeStartInMS; -tfc.Frequency = FreqStartInHZ:FreqIntervalInHZ:(NumberFrequencies-1)*FreqIntervalInHZ+FreqStartInHZ; - -if isempty(findstr(tfc.DataType,'COH')) - for Channel=1:NumberChannels - tfc.ChannelLabels(Channel) = cellstr(fscanf(fp,'%s ',1)); - end -else - for Channel=1:NumberChannels - tfc.ChannelLabels(Channel) = cellstr(fscanf(fp,'%s ',3)); - end -end - -tfc.ChannelLabels=char(tfc.ChannelLabels); - -tfc.Data = zeros(NumberChannels,NumberTimeSamples,NumberFrequencies); -for Channel=1:NumberChannels - tfc.Data(Channel,:,:) = fscanf(fp,'%f',[NumberTimeSamples,NumberFrequencies]); -end -fclose(fp); diff --git a/external/fieldtrip/private/read_24bit.m b/external/fieldtrip/private/read_24bit.m deleted file mode 100644 index 5f1503a..0000000 --- a/external/fieldtrip/private/read_24bit.m +++ /dev/null @@ -1,42 +0,0 @@ -function [varargout] = funname(varargin) - -% READ_24BIT read a stream of 24 bit values and converts them to doubles -% This function is designed for Biosemi BDF files and is implemented as mex -% file for efficiency. -% -% Use as -% [dat] = read_24bit(filename, offset, numwords); -% -% See also READ_16BIT - -% remember the original working directory -pwdir = pwd; - -% determine the name and full path of this function -funname = mfilename('fullpath'); -mexsrc = [funname '.c']; -[mexdir, mexname] = fileparts(funname); - -try - % try to compile the mex file on the fly - warning('trying to compile MEX file from %s', mexsrc); - cd(mexdir); - mex(mexsrc); - cd(pwdir); - success = true; - -catch - % compilation failed - disp(lasterr); - error('could not locate MEX file for %s', mexname); - cd(pwdir); - success = false; -end - -if success - % execute the mex file that was juist created - funname = mfilename; - funhandle = str2func(funname); - [varargout{1:nargout}] = funhandle(varargin{:}); -end - diff --git a/external/fieldtrip/private/read_24bit.mexmaci b/external/fieldtrip/private/read_24bit.mexmaci deleted file mode 100755 index 1d9ce51..0000000 Binary files a/external/fieldtrip/private/read_24bit.mexmaci and /dev/null differ diff --git a/external/fieldtrip/private/read_24bit.mexw32 b/external/fieldtrip/private/read_24bit.mexw32 deleted file mode 100644 index 43e3eb0..0000000 Binary files a/external/fieldtrip/private/read_24bit.mexw32 and /dev/null differ diff --git a/external/fieldtrip/private/read_24bit.mexw64 b/external/fieldtrip/private/read_24bit.mexw64 deleted file mode 100644 index 6511424..0000000 Binary files a/external/fieldtrip/private/read_24bit.mexw64 and /dev/null differ diff --git a/external/fieldtrip/private/read_4d_hdr.m b/external/fieldtrip/private/read_4d_hdr.m deleted file mode 100644 index 9e8ae63..0000000 --- a/external/fieldtrip/private/read_4d_hdr.m +++ /dev/null @@ -1,482 +0,0 @@ -function [header] = read_4d_hdr(datafile, configfile) - -% hdr=READ_4D_HDR(datafile, configfile) -% Collects the required Fieldtrip header data from the data file 'filename' -% and the associated 'config' file for that data. -% -% Adapted from the MSI>>Matlab code written by Eugene Kronberg - -% Copyright (C) 2008-2009, Centre for Cognitive Neuroimaging, Glasgow, Gavin Paterson & J.M.Schoffelen -% -% $Log: read_4d_hdr.m,v $ -% Revision 1.3 2009/04/03 07:56:46 jansch -% changed reading of user_block B_weights_used. there's a version 1 and 2, -% probably related to whether data were acquired with a 2500 or 3600 system -% -% Revision 1.2 2009/03/30 13:53:17 jansch -% Change with respect to handling of user blocks. User block data will be stored -% in a cell-array of structures, rather than the initial structure-array. Added -% log in m-file -% - -%read header -if nargin ~= 2 - error('Wrong number of input arguments'); -end - -if ~isempty(datafile), - %always big endian - fid = fopen(datafile, 'r', 'b'); - - if fid == -1 - error('Cannot open file %s', datafile); - end - - fseek(fid, 0, 'eof'); - header_end = ftell(fid); - %last 8 bytes of the pdf is header offset - fseek(fid, -8, 'eof'); - header_offset = fread(fid,1,'uint64'); - - %first byte of the header - fseek(fid, header_offset, 'bof'); - - % read header data - align_file_pointer(fid) - header.header_data.FileType = fread(fid, 1, 'uint16=>uint16'); - file_type = char(fread(fid, 5, 'uchar'))'; - header.header_data.file_type = file_type(file_type>0); - fseek(fid, 1, 'cof'); - format = fread(fid, 1, 'int16=>int16'); - switch format - case 1 - header.header_data.Format = 'SHORT'; - case 2 - header.header_data.Format = 'LONG'; - case 3 - header.header_data.Format = 'FLOAT'; - case 4 - header.header_data.Format ='DOUBLE'; - end - header.header_data.acq_mode = fread(fid, 1, 'uint16=>uint16'); - header.header_data.TotalEpochs = fread(fid, 1, 'uint32=>double'); - header.header_data.input_epochs = fread(fid, 1, 'uint32=>uint32'); - header.header_data.TotalEvents = fread(fid, 1, 'uint32=>uint32'); - header.header_data.total_fixed_events = fread(fid, 1, 'uint32=>uint32'); - header.header_data.SamplePeriod = fread(fid, 1, 'float32=>float64'); - header.header_data.SampleFrequency = 1/header.header_data.SamplePeriod; - xaxis_label = char(fread(fid, 16, 'uchar'))'; - header.header_data.xaxis_label = xaxis_label(xaxis_label>0); - header.header_data.total_processes = fread(fid, 1, 'uint32=>uint32'); - header.header_data.TotalChannels = fread(fid, 1, 'uint16=>double'); - fseek(fid, 2, 'cof'); - header.header_data.checksum = fread(fid, 1, 'int32=>int32'); - header.header_data.total_ed_classes = fread(fid, 1, 'uint32=>uint32'); - header.header_data.total_associated_files = fread(fid, 1, 'uint16=>uint16'); - header.header_data.last_file_index = fread(fid, 1, 'uint16=>uint16'); - header.header_data.timestamp = fread(fid, 1, 'uint32=>uint32'); - header.header_data.reserved = fread(fid, 20, 'uchar')'; - fseek(fid, 4, 'cof'); - - %read epoch_data - for epoch = 1:header.header_data.TotalEpochs; - align_file_pointer(fid) - - header.epoch_data(epoch).pts_in_epoch = fread(fid, 1, 'uint32=>uint32'); - header.epoch_data(epoch).epoch_duration = fread(fid, 1, 'float32=>float32'); - header.epoch_data(epoch).expected_iti = fread(fid, 1, 'float32=>float32'); - header.epoch_data(epoch).actual_iti = fread(fid, 1, 'float32=>float32'); - header.epoch_data(epoch).total_var_events = fread(fid, 1, 'uint32=>uint32'); - header.epoch_data(epoch).checksum = fread(fid, 1, 'int32=>int32'); - header.epoch_data(epoch).epoch_timestamp = fread(fid, 1, 'int32=>int32'); - header.epoch_data(epoch).reserved = fread(fid, 28, 'uchar')'; - header.header_data.SlicesPerEpoch = double(header.epoch_data(1).pts_in_epoch); - - %read event data (var_events) - for event = 1:header.epoch_data(epoch).total_var_events - align_file_pointer(fid) - - event_name = char(fread(fid, 16, 'uchar'))'; - header.epoch_data(epoch).var_event{event}.event_name = event_name(event_name>0); - header.epoch_data(epoch).var_event{event}.start_lat = fread(fid, 1, 'float32=>float32'); - header.epoch_data(epoch).var_event{event}.end_lat = fread(fid, 1, 'float32=>float32'); - header.epoch_data(epoch).var_event{event}.step_size = fread(fid, 1, 'float32=>float32'); - header.epoch_data(epoch).var_event{event}.fixed_event = fread(fid, 1, 'uint16=>uint16'); - fseek(fid, 2, 'cof'); - header.epoch_data(epoch).var_event{event}.checksum = fread(fid, 1, 'int32=>int32'); - header.epoch_data(epoch).var_event{event}.reserved = fread(fid, 32, 'uchar')'; - fseek(fid, 4, 'cof'); - end - end - - %read channel ref data - for channel = 1:header.header_data.TotalChannels - align_file_pointer(fid) - - chan_label = (fread(fid, 16, 'uint8=>char'))'; - header.channel_data(channel).chan_label = chan_label(chan_label>0); - header.channel_data(channel).chan_no = fread(fid, 1, 'uint16=>uint16'); - header.channel_data(channel).attributes = fread(fid, 1, 'uint16=>uint16'); - header.channel_data(channel).scale = fread(fid, 1, 'float32=>float32'); - yaxis_label = char(fread(fid, 16, 'uint8=>char'))'; - header.channel_data(channel).yaxis_label = yaxis_label(yaxis_label>0); - header.channel_data(channel).valid_min_max = fread(fid, 1, 'uint16=>uint16'); - fseek(fid, 6, 'cof'); - header.channel_data(channel).ymin = fread(fid, 1, 'float64'); - header.channel_data(channel).ymax = fread(fid, 1, 'float64'); - header.channel_data(channel).index = fread(fid, 1, 'uint32=>uint32'); - header.channel_data(channel).checksum = fread(fid, 1, 'int32=>int32'); - header.channel_data(channel).whatisit = char(fread(fid, 4, 'uint8=>char'))'; - header.channel_data(channel).reserved = fread(fid, 28, 'uint8')'; - end - - %read event data - for event = 1:header.header_data.total_fixed_events - align_file_pointer(fid) - event_name = char(fread(fid, 16, 'uchar'))'; - header.event_data(event).event_name = event_name(event_name>0); - header.event_data(event).start_lat = fread(fid, 1, 'float32=>float32'); - header.event_data(event).end_lat = fread(fid, 1, 'float32=>float32'); - header.event_data(event).step_size = fread(fid, 1, 'float32=>float32'); - header.event_data(event).fixed_event = fread(fid, 1, 'uint16=>uint16'); - fseek(fid, 2, 'cof'); - header.event_data(event).checksum = fread(fid, 1, 'int32=>int32'); - header.event_data(event).reserved = fread(fid, 32, 'uchar')'; - fseek(fid, 4, 'cof'); - end - header.header_data.FirstLatency = double(header.event_data(1).start_lat); - - %experimental: read process information - for np = 1:header.header_data.total_processes - align_file_pointer(fid) - nbytes = fread(fid, 1, 'uint32=>uint32'); - fp = ftell(fid); - header.process(np).hdr.nbytes = nbytes; - type = char(fread(fid, 20, 'uchar'))'; - header.process(np).hdr.type = type(type>0); - header.process(np).hdr.checksum = fread(fid, 1, 'int32=>int32'); - user = char(fread(fid, 32, 'uchar'))'; - header.process(np).user = user(user>0); - header.process(np).timestamp = fread(fid, 1, 'uint32=>uint32'); - fname = char(fread(fid, 32, 'uchar'))'; - header.process(np).filename = fname(fname>0); - fseek(fid, 28*8, 'cof'); %dont know - header.process(np).totalsteps = fread(fid, 1, 'uint32=>uint32'); - header.process(np).checksum = fread(fid, 1, 'int32=>int32'); - header.process(np).reserved = fread(fid, 32, 'uchar')'; - for ns = 1:header.process(np).totalsteps - header.process(np).step(ns).hdr.nbytes = fread(fid, 1, 'uint32=>uint32'); - type = char(fread(fid, 20, 'uchar'))'; - header.process(np).step(ns).hdr.type = type(type>0); %dont know how to interpret the first two - header.process(np).step(ns).hdr.checksum = fread(fid, 1, 'int32=>int32'); - header.process(np).step(ns).userblocksize = fread(fid, 1, 'int32=>int32'); - fseek(fid, 32, 'cof'); %needed until next step FIXME make more robust, the total number of read bytes - %should be equal to the nbytes computed earlier on - if strcmp(header.process(np).step(ns).hdr.type, 'PDF_Weight_Table'), - warning('reading in weight table: no warranty that this is correct. it seems to work for the Glasgow 248-magnetometer system. if you have some code yourself, and/or would like to test it on your own data, please contact Jan-Mathijs'); - tmpfp = ftell(fid); - tmp = fread(fid, 1, 'uint8'); - Nchan = fread(fid, 1, 'uint32'); - Nref = fread(fid, 1, 'uint32'); - for k = 1:Nref - name = fread(fid, 17, 'uchar'); %strange, but true - header.process(np).step(ns).RefChan{k,1} = char(name(name>0))'; - end - fseek(fid, 152, 'cof'); - for k = 1:Nchan - name = fread(fid, 17, 'uchar'); - header.process(np).step(ns).Chan{k,1} = char(name(name>0))'; - end - %fseek(fid, 20, 'cof'); - %fseek(fid, 4216, 'cof'); - header.process(np).step(ns).stuff1 = fread(fid, 4236, 'uint8'); - name = fread(fid, 16, 'uchar'); - header.process(np).step(ns).Creator = char(name(name>0))'; - %some stuff I don't understand yet - %fseek(fid, 136, 'cof'); - header.process(np).step(ns).stuff2 = fread(fid, 136, 'uint8'); - %now something strange is going to happen: the weights are probably little-endian encoded. - %here we go: check whether this applies to the whole PDF weight table - fp = ftell(fid); - fclose(fid); - fid = fopen(datafile, 'r', 'l'); - fseek(fid, fp, 'bof'); - for k = 1:Nchan - header.process(np).step(ns).Weights(k,:) = fread(fid, 23, 'float32=>float32')'; - fseek(fid, 36, 'cof'); - end - else - end - end - end - fclose(fid); -end -%end read header - -%read config file -fid = fopen(configfile, 'r', 'b'); - -if fid == -1 - error('Cannot open config file'); -end - -header.config_data.version = fread(fid, 1, 'uint16=>uint16'); -site_name = char(fread(fid, 32, 'uchar'))'; -header.config_data.site_name = site_name(site_name>0); -dap_hostname = char(fread(fid, 16, 'uchar'))'; -header.config_data.dap_hostname = dap_hostname(dap_hostname>0); -header.config_data.sys_type = fread(fid, 1, 'uint16=>uint16'); -header.config_data.sys_options = fread(fid, 1, 'uint32=>uint32'); -header.config_data.supply_freq = fread(fid, 1, 'uint16=>uint16'); -header.config_data.total_chans = fread(fid, 1, 'uint16=>uint16'); -header.config_data.system_fixed_gain = fread(fid, 1, 'float32=>float32'); -header.config_data.volts_per_bit = fread(fid, 1, 'float32=>float32'); -header.config_data.total_sensors = fread(fid, 1, 'uint16=>uint16'); -header.config_data.total_user_blocks = fread(fid, 1, 'uint16=>uint16'); -header.config_data.next_derived_channel_number = fread(fid, 1, 'uint16=>uint16'); -fseek(fid, 2, 'cof'); -header.config_data.checksum = fread(fid, 1, 'int32=>int32'); -header.config_data.reserved = fread(fid, 32, 'uchar=>uchar')'; - -header.config.Xfm = fread(fid, [4 4], 'double'); - -%user blocks -for ub = 1:header.config_data.total_user_blocks - align_file_pointer(fid) - header.user_block_data{ub}.hdr.nbytes = fread(fid, 1, 'uint32=>uint32'); - type = char(fread(fid, 20, 'uchar'))'; - header.user_block_data{ub}.hdr.type = type(type>0); - header.user_block_data{ub}.hdr.checksum = fread(fid, 1, 'int32=>int32'); - user = char(fread(fid, 32, 'uchar'))'; - header.user_block_data{ub}.user = user(user>0); - header.user_block_data{ub}.timestamp = fread(fid, 1, 'uint32=>uint32'); - header.user_block_data{ub}.user_space_size = fread(fid, 1, 'uint32=>uint32'); - header.user_block_data{ub}.reserved = fread(fid, 32, 'uchar=>uchar')'; - fseek(fid, 4, 'cof'); - user_space_size = double(header.user_block_data{ub}.user_space_size); - if strcmp(type(type>0), 'B_weights_used'), - %warning('reading in weight table: no warranty that this is correct. it seems to work for the Glasgow 248-magnetometer system. if you have some code yourself, and/or would like to test it on your own data, please contact Jan-Mathijs'); - tmpfp = ftell(fid); - %read user_block_data weights - %there is information in the 4th and 8th byte, these might be related to the settings? - version = fread(fid, 1, 'uint32'); - header.user_block_data{ub}.version = version; - if version==1, - Nbytes = fread(fid,1,'uint32'); - Nchan = fread(fid,1,'uint32'); - Position = fread(fid, 32, 'uchar'); - header.user_block_data{ub}.position = char(Position(Position>0))'; - fseek(fid,tmpfp+user_space_size - Nbytes*Nchan, 'bof'); - Ndigital = floor((Nbytes - 4*2) / 4); - Nanalog = 3; %lucky guess? - % how to know number of analog weights vs digital weights??? - for ch = 1:Nchan - % for Konstanz -- comment for others? - header.user_block_data{ub}.aweights(ch,:) = fread(fid, [1 Nanalog], 'int16')'; - fseek(fid,2,'cof'); % alignment - header.user_block_data{ub}.dweights(ch,:) = fread(fid, [1 Ndigital], 'single=>double')'; - end - fseek(fid, tmpfp, 'bof'); - %there is no information with respect to the channels here. - %the best guess would be to assume the order identical to the order in header.config.channel_data - %for the digital weights it would be the order of the references in that list - %for the analog weights I would not know - elseif version==2, - unknown2 = fread(fid, 1, 'uint32'); - Nchan = fread(fid, 1, 'uint32'); - Position = fread(fid, 32, 'uchar'); - header.user_block_data{ub}.position = char(Position(Position>0))'; - fseek(fid, tmpfp+124, 'bof'); - Nanalog = fread(fid, 1, 'uint32'); - Ndigital = fread(fid, 1, 'uint32'); - fseek(fid, tmpfp+204, 'bof'); - for k = 1:Nchan - Name = fread(fid, 16, 'uchar'); - header.user_block_data{ub}.channames{k,1} = char(Name(Name>0))'; - end - for k = 1:Nanalog - Name = fread(fid, 16, 'uchar'); - header.user_block_data{ub}.arefnames{k,1} = char(Name(Name>0))'; - end - for k = 1:Ndigital - Name = fread(fid, 16, 'uchar'); - header.user_block_data{ub}.drefnames{k,1} = char(Name(Name>0))'; - end - - header.user_block_data{ub}.dweights = fread(fid, [Ndigital Nchan], 'single=>double')'; - header.user_block_data{ub}.aweights = fread(fid, [Nanalog Nchan], 'int16')'; - fseek(fid, tmpfp, 'bof'); - end - elseif strcmp(type(type>0), 'B_E_table_used'), - %warning('reading in weight table: no warranty that this is correct'); - %tmpfp = ftell(fid); - %fseek(fid, 4, 'cof'); %there's info here dont know how to interpret - %Nx = fread(fid, 1, 'uint32'); - %Nchan = fread(fid, 1, 'uint32'); - %type = fread(fid, 32, 'uchar'); %don't know whether correct - %header.user_block_data{ub}.type = char(type(type>0))'; - %fseek(fid, 16, 'cof'); - %for k = 1:Nchan - % name = fread(fid, 16, 'uchar'); - % header.user_block_data{ub}.name{k,1} = char(name(name>0))'; - %end - elseif strcmp(type(type>0), 'B_COH_Points'), - tmpfp = ftell(fid); - Ncoil = fread(fid, 1, 'uint32'); - N = fread(fid, 1, 'uint32'); - coils = fread(fid, [7 Ncoil], 'double'); - - header.user_block_data{ub}.pnt = coils(1:3,:)'; - header.user_block_data{ub}.ori = coils(4:6,:)'; - header.user_block_data{ub}.Ncoil = Ncoil; - header.user_block_data{ub}.N = N; - tmp = fread(fid, (904-288)/8, 'double'); - header.user_block_data{ub}.tmp = tmp; %FIXME try to find out what these bytes mean - fseek(fid, tmpfp, 'bof'); - elseif strcmp(type(type>0), 'b_ccp_xfm_block'), - tmpfp = ftell(fid); - tmp1 = fread(fid, 1, 'uint32'); - %tmp = fread(fid, [4 4], 'double'); - %tmp = fread(fid, [4 4], 'double'); - %the next part seems to be in little endian format (at least when I tried) - tmp = fread(fid, 128, 'uint8'); - tmp = uint8(reshape(tmp, [8 16])'); - xfm = zeros(4,4); - for k = 1:size(tmp,1) - xfm(k) = typecast(tmp(k,:), 'double'); - if abs(xfm(k))<1e-10 | abs(xfm(k))>1e10, xfm(k) = typecast(fliplr(tmp(k,:)), 'double');end - end - fseek(fid, tmpfp, 'bof'); %FIXME try to find out why this looks so strange - elseif strcmp(type(type>0), 'b_eeg_elec_locs'), - %this block contains the digitized coil positions - tmpfp = ftell(fid); - Npoints = user_space_size./40; - for k = 1:Npoints - tmp = fread(fid, 16, 'uchar'); - tmplabel = char(tmp(tmp>0)'); - if strmatch('Coil', tmplabel), - label{k} = tmplabel(1:5); - elseif ismember(tmplabel(1), {'L' 'R' 'C' 'N' 'I'}), - label{k} = tmplabel(1); - else - label{k} = ''; - end - tmp = fread(fid, 3, 'double'); - pnt(k,:) = tmp(:)'; - end - header.user_block_data{ub}.label = label(:); - header.user_block_data{ub}.pnt = pnt; - fseek(fid, tmpfp, 'bof'); - end - fseek(fid, user_space_size, 'cof'); -end - -%channels -for ch = 1:header.config_data.total_chans - align_file_pointer(fid) - name = char(fread(fid, 16, 'uchar'))'; - header.config.channel_data(ch).name = name(name>0); - %FIXME this is a very dirty fix to get the reading in of continuous headlocalization - %correct. At the moment, the numbering of the hmt related channels seems to start with 1000 - %which I don't understand, but seems rather nonsensical. - chan_no = fread(fid, 1, 'uint16=>uint16'); - if chan_no > header.config_data.total_chans, - - %FIXME fix the number in header.channel_data as well - sel = find([header.channel_data.chan_no]== chan_no); - if ~isempty(sel), - chan_no = ch; - header.channel_data(sel).chan_no = chan_no; - header.channel_data(sel).chan_label = header.config.channel_data(ch).name; - else - %does not matter - end - end - header.config.channel_data(ch).chan_no = chan_no; - header.config.channel_data(ch).type = fread(fid, 1, 'uint16=>uint16'); - header.config.channel_data(ch).sensor_no = fread(fid, 1, 'int16=>int16'); - fseek(fid, 2, 'cof'); - header.config.channel_data(ch).gain = fread(fid, 1, 'float32=>float32'); - header.config.channel_data(ch).units_per_bit = fread(fid, 1, 'float32=>float32'); - yaxis_label = char(fread(fid, 16, 'uchar'))'; - header.config.channel_data(ch).yaxis_label = yaxis_label(yaxis_label>0); - header.config.channel_data(ch).aar_val = fread(fid, 1, 'double'); - header.config.channel_data(ch).checksum = fread(fid, 1, 'int32=>int32'); - header.config.channel_data(ch).reserved = fread(fid, 32, 'uchar=>uchar')'; - fseek(fid, 4, 'cof'); - - align_file_pointer(fid) - header.config.channel_data(ch).device_data.hdr.size = fread(fid, 1, 'uint32=>uint32'); - header.config.channel_data(ch).device_data.hdr.checksum = fread(fid, 1, 'int32=>int32'); - header.config.channel_data(ch).device_data.hdr.reserved = fread(fid, 32, 'uchar=>uchar')'; - - switch header.config.channel_data(ch).type - case {1, 3}%meg/ref - - header.config.channel_data(ch).device_data.inductance = fread(fid, 1, 'float32=>float32'); - fseek(fid, 4, 'cof'); - header.config.channel_data(ch).device_data.Xfm = fread(fid, [4 4], 'double'); - header.config.channel_data(ch).device_data.xform_flag = fread(fid, 1, 'uint16=>uint16'); - header.config.channel_data(ch).device_data.total_loops = fread(fid, 1, 'uint16=>uint16'); - header.config.channel_data(ch).device_data.reserved = fread(fid, 32, 'uchar=>uchar')'; - fseek(fid, 4, 'cof'); - - for loop = 1:header.config.channel_data(ch).device_data.total_loops - align_file_pointer(fid) - header.config.channel_data(ch).device_data.loop_data(loop).position = fread(fid, 3, 'double'); - header.config.channel_data(ch).device_data.loop_data(loop).direction = fread(fid, 3, 'double'); - header.config.channel_data(ch).device_data.loop_data(loop).radius = fread(fid, 1, 'double'); - header.config.channel_data(ch).device_data.loop_data(loop).wire_radius = fread(fid, 1, 'double'); - header.config.channel_data(ch).device_data.loop_data(loop).turns = fread(fid, 1, 'uint16=>uint16'); - fseek(fid, 2, 'cof'); - header.config.channel_data(ch).device_data.loop_data(loop).checksum = fread(fid, 1, 'int32=>int32'); - header.config.channel_data(ch).device_data.loop_data(loop).reserved = fread(fid, 32, 'uchar=>uchar')'; - end - case 2%eeg - header.config.channel_data(ch).device_data.impedance = fread(fid, 1, 'float32=>float32'); - fseek(fid, 4, 'cof'); - header.config.channel_data(ch).device_data.Xfm = fread(fid, [4 4], 'double'); - header.config.channel_data(ch).device_data.reserved = fread(fid, 32, 'uchar=>uchar')'; - case 4%external - header.config.channel_data(ch).device_data.user_space_size = fread(fid, 1, 'uint32=>uint32'); - header.config.channel_data(ch).device_data.reserved = fread(fid, 32, 'uchar=>uchar')'; - fseek(fid, 4, 'cof'); - case 5%TRIGGER - header.config.channel_data(ch).device_data.user_space_size = fread(fid, 1, 'uint32=>uint32'); - header.config.channel_data(ch).device_data.reserved = fread(fid, 32, 'uchar=>uchar')'; - fseek(fid, 4, 'cof'); - case 6%utility - header.config.channel_data(ch).device_data.user_space_size = fread(fid, 1, 'uint32=>uint32'); - header.config.channel_data(ch).device_data.reserved = fread(fid, 32, 'uchar=>uchar')'; - fseek(fid, 4, 'cof'); - case 7%derived - header.config.channel_data(ch).device_data.user_space_size = fread(fid, 1, 'uint32=>uint32'); - header.config.channel_data(ch).device_data.reserved = fread(fid, 32, 'uchar=>uchar')'; - fseek(fid, 4, 'cof'); - case 8%shorted - header.config.channel_data(ch).device_data.reserved = fread(fid, 32, 'uchar=>uchar')'; - otherwise - error('Unknown device type: %d\n', header.config.channel_data(ch).type); - end -end - -fclose(fid); -%end read config file - -header.header_data.FileDescriptor = 0; %no obvious field to take this from -header.header_data.Events = 1;%no obvious field to take this from -header.header_data.EventCodes = 0;%no obvious field to take this from - -if isfield(header, 'channel_data'), - header.ChannelGain = double([header.config.channel_data([header.channel_data.chan_no]).gain]'); - header.ChannelUnitsPerBit = double([header.config.channel_data([header.channel_data.chan_no]).units_per_bit]'); - header.Channel = {header.config.channel_data([header.channel_data.chan_no]).name}'; - header.Format = header.header_data.Format; -end - -function align_file_pointer(fid) -current_position = ftell(fid); -if mod(current_position, 8) ~= 0 - offset = 8 - mod(current_position,8); - fseek(fid, offset, 'cof'); -end diff --git a/external/fieldtrip/private/read_asa.m b/external/fieldtrip/private/read_asa.m deleted file mode 100644 index dce0181..0000000 --- a/external/fieldtrip/private/read_asa.m +++ /dev/null @@ -1,177 +0,0 @@ -function [val] = read_asa(filename, elem, format, number, token) - -% READ_ASA reads a specified element from an ASA file -% -% val = read_asa(filename, element, type, number) -% -% where the element is a string such as -% NumberSlices -% NumberPositions -% Rows -% Columns -% etc. -% -% and format specifies the datatype according to -% %d (integer value) -% %f (floating point value) -% %s (string) -% -% number is optional to specify how many lines of data should be read -% The default is 1 for strings and Inf for numbers. -% -% token is optional to specifiy a character that separates the values from -% anything not wanted. - -% Copyright (C) 2002, Robert Oostenveld -% -% $Log: read_asa.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.7 2008/11/17 17:38:43 roboos -% replaced line==-1 with isequal, to work around && bug -% -% Revision 1.6 2008/11/14 07:49:19 roboos -% use standard matlab strtrim function instead of deblank2 -% -% Revision 1.5 2008/11/14 07:21:45 roboos -% newer ASA versions write the labels in front of the positions, like "FPz: 10.4 1.3 -2" -% added support for this, thanks to Thomas Hartmann -% use strcmpi instead of strcmp(lower()) -% -% Revision 1.4 2005/11/30 11:38:33 roboos -% fixed bug: close file before returning to calling function (thanks to Gijs) -% -% Revision 1.3 2004/03/29 15:15:12 roberto -% unknown change, seems related to handling of empty lines ? -% -% Revision 1.2 2003/03/11 15:24:51 roberto -% updated help and copyrights -% - -fid = fopen(filename, 'rt'); -if fid==-1 - error(sprintf('could not open file %s', filename)); -end - -if nargin<4 - if strcmp(format, '%s') - number = 1; - else - number = Inf; - end -end - -if nargin<5 - token = ''; -end - - -val = []; -elem = strtrim(lower(elem)); - -while (1) - line = fgetl(fid); - if ~isempty(line) && isequal(line, -1) - % prematurely reached end of file - fclose(fid); - return - end - line = strtrim(line); - lower_line = lower(line); - if strmatch(elem, lower_line) - data = line((length(elem)+1):end); - break - end -end - -while isempty(data) - line = fgetl(fid); - if isequal(line, -1) - % prematurely reached end of file - fclose(fid); - return - end - data = strtrim(line); -end - -if strcmp(format, '%s') - if number==1 - % interpret the data as a single string, create char-array - val = detoken(strtrim(data), token); - fclose(fid); - return - end - % interpret the data as a single string, create cell-array - val{1} = detoken(strtrim(data), token); - count = 1; - % read the remaining strings - while count LPA -% PointOnNegativeYAxis -> RPA -% PointOnPositiveXAxis -> nasion - -% Copyright (C) 2002, Robert Oostenveld -% -% $Log: read_asa_mri.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry -% -% Revision 1.6 2008/11/12 17:02:03 roboos -% explicitely specify ieee-le in fopen() -% -% Revision 1.5 2005/11/16 13:46:32 roboos -% added segmentatino to output, changed from warpo3d to warp_apply -% -% Revision 1.4 2004/01/19 14:24:13 roberto -% numerous changes, cannot remember the details -% -% Revision 1.3 2003/08/04 09:26:46 roberto -% added homgenous coordinate transformation matrices to header -% support for VoxelOn... instead of PointOn... -% -% Revision 1.2 2003/03/11 15:24:51 roberto -% updated help and copyrights -% - -hdr.Nrows = read_asa(fn, 'NumberRows=', '%d'); -hdr.Ncolumns = read_asa(fn, 'NumberColumns=', '%d'); -hdr.Nslices = read_asa(fn, 'NumberSlices=', '%d'); -hdr.rows = read_asa(fn, 'Rows=', '%s'); -hdr.columns = read_asa(fn, 'Columns=', '%s'); -hdr.slices = read_asa(fn, 'Slices=', '%s'); -hdr.distance = read_asa(fn, 'Distance=', '%f', 3); -hdr.mrifile = read_asa(fn, 'Matrix', '%s'); -hdr.segfile = read_asa(fn, 'Segmentation', '%s'); -hdr.posy = read_asa(fn, 'PointOnPositiveYAxis', '%f', 3); -hdr.negy = read_asa(fn, 'PointOnNegativeYAxis', '%f', 3); -hdr.posx = read_asa(fn, 'PointOnPositiveXAxis', '%f', 3); -hdr.voxposy = read_asa(fn, 'VoxelOnPositiveYAxis', '%f', 3); -hdr.voxnegy = read_asa(fn, 'VoxelOnNegativeYAxis', '%f', 3); -hdr.voxposx = read_asa(fn, 'VoxelOnPositiveXAxis', '%f', 3); -hdr.segfile = read_asa(fn, 'Segmentation', '%s', 1); - -dim = [hdr.Ncolumns hdr.Nrows hdr.Nslices]; -mri = []; -seg = []; - -% the data files are at the same location as the mri file, locate path -[path, name, ext] = fileparts(fn); - -% this temporary needs 8x as much storage!!! -if ~isempty(hdr.mrifile) - mrifile = fullfile(path, hdr.mrifile); - mri = zeros(dim); - fid = fopen(mrifile, 'rb', 'ieee-le'); - mri(:) = fread(fid, prod(dim), 'uint8'); - mri = uint8(mri); - fclose(fid); -end - -% this temporary needs 8x as much storage!!! -if ~isempty(hdr.segfile) - segfile = fullfile(path, hdr.segfile); - seg = zeros(dim); - fid = fopen(segfile, 'rb', 'ieee-le'); - seg(:) = fread(fid, prod(dim), 'uint8'); - seg = uint8(seg); - fclose(fid); -end - -% flip the orientation of the MRI data, the result should be -% 'coronal(occipital-frontal)' -% 'horizontal(inferior-superior)' -% 'sagittal(right-left)' - -if strcmp(hdr.columns, 'coronal(frontal-occipital)') - hdr.columns = 'coronal(occipital-frontal)'; - mri = flipdim(mri, 1); - seg = flipdim(seg, 1); -elseif strcmp(hdr.columns, 'horizontal(superior-inferior)') - hdr.columns = 'horizontal(inferior-superior)'; - mri = flipdim(mri, 1); - seg = flipdim(seg, 1); -elseif strcmp(hdr.columns, 'sagittal(left-right)') - hdr.columns = 'sagittal(right-left)'; - mri = flipdim(mri, 1); - seg = flipdim(seg, 1); -end - -if strcmp(hdr.rows, 'coronal(frontal-occipital)') - hdr.rows = 'coronal(occipital-frontal)'; - mri = flipdim(mri, 2); - seg = flipdim(seg, 2); -elseif strcmp(hdr.rows, 'horizontal(superior-inferior)') - hdr.rows = 'horizontal(inferior-superior)'; - mri = flipdim(mri, 2); - seg = flipdim(seg, 2); -elseif strcmp(hdr.rows, 'sagittal(left-right)') - hdr.rows = 'sagittal(right-left)'; - mri = flipdim(mri, 2); - seg = flipdim(seg, 2); -end - -if strcmp(hdr.slices, 'coronal(frontal-occipital)') - hdr.slices = 'coronal(occipital-frontal)'; - mri = flipdim(mri, 3); - seg = flipdim(seg, 3); -elseif strcmp(hdr.slices, 'horizontal(superior-inferior)') - hdr.slices = 'horizontal(inferior-superior)'; - mri = flipdim(mri, 3); - seg = flipdim(seg, 3); -elseif strcmp(hdr.slices, 'sagittal(left-right)') - hdr.slices = 'sagittal(right-left)'; - mri = flipdim(mri, 3); - seg = flipdim(seg, 3); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% swap the orientations of the MRI data, the result should be fixed -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% 1st dimension corresponds to columns, which should be 'coronal(occipital-frontal)' -% 2st dimension corresponds to rows, which should be 'sagittal(right-left)' -% 3rd dimension corresponds to slices, which should be 'horizontal(inferior-superior)' - -if strcmp(hdr.columns, 'coronal(occipital-frontal)') - orientation(1) = 1; -elseif strcmp(hdr.columns, 'sagittal(right-left)') - orientation(1) = 2; -elseif strcmp(hdr.columns, 'horizontal(inferior-superior)') - orientation(1) = 3; -end - -if strcmp(hdr.rows, 'coronal(occipital-frontal)') - orientation(2) = 1; -elseif strcmp(hdr.rows, 'sagittal(right-left)') - orientation(2) = 2; -elseif strcmp(hdr.rows, 'horizontal(inferior-superior)') - orientation(2) = 3; -end - -if strcmp(hdr.slices, 'coronal(occipital-frontal)') - orientation(3) = 1; -elseif strcmp(hdr.slices, 'sagittal(right-left)') - orientation(3) = 2; -elseif strcmp(hdr.slices, 'horizontal(inferior-superior)') - orientation(3) = 3; -end - -mri = ipermute(mri, orientation); -seg = ipermute(seg, orientation); -hdr.rows = 'sagittal(right-left)'; -hdr.columns = 'coronal(occipital-frontal)'; -hdr.slices = 'horizontal(inferior-superior)'; - -% recompute the dimensions after all the swapping -hdr.Nrows = size(mri, 1); -hdr.Ncolumns = size(mri, 2); -hdr.Nslices = size(mri, 3); -dim = size(mri); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% if possible, create the accompanying homogenous coordinate transformation matrix -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -if exist('headcoordinates', 'file') - % In case of PointOn..., ASA counts voxels from the center of the MRI - % and in case of VoxelOn..., ASA counts voxels from the corner of the MRI - % In both cases, ASA starts counting at [0 0 0], which is C convention - % whereas I want to count from the 1st voxel and number that with [1 1 1] - if ~isempty(hdr.posx) & ~isempty(hdr.negy) & ~isempty(hdr.posy) - offset = (dim + [1 1 1])/2; - hdr.fiducial.mri.nas = hdr.posx + offset; - hdr.fiducial.mri.lpa = hdr.posy + offset; - hdr.fiducial.mri.rpa = hdr.negy + offset; - else - offset = [1 1 1]; - hdr.fiducial.mri.nas = hdr.voxposx + offset; - hdr.fiducial.mri.lpa = hdr.voxposy + offset; - hdr.fiducial.mri.rpa = hdr.voxnegy + offset; - end - - % use the headcoordinates function (roboos/misc) to compute the transformaton matrix - hdr.transformMRI2Head = headcoordinates(hdr.fiducial.mri.nas, hdr.fiducial.mri.lpa, hdr.fiducial.mri.rpa, 1); - hdr.transformHead2MRI = inv(hdr.transformMRI2Head); - - % compute the fiducials in head coordinates - hdr.fiducial.head.nas = warp_apply(hdr.transformMRI2Head, hdr.fiducial.mri.nas, 'homogenous'); - hdr.fiducial.head.lpa = warp_apply(hdr.transformMRI2Head, hdr.fiducial.mri.lpa, 'homogenous'); - hdr.fiducial.head.rpa = warp_apply(hdr.transformMRI2Head, hdr.fiducial.mri.rpa, 'homogenous'); -end - diff --git a/external/fieldtrip/private/read_asa_msr.m b/external/fieldtrip/private/read_asa_msr.m deleted file mode 100644 index 0e44bce..0000000 --- a/external/fieldtrip/private/read_asa_msr.m +++ /dev/null @@ -1,76 +0,0 @@ -function data = read_asa_msr(fn); - -% READ_ASA_MSR reads EEG or MEG data from an ASA data file -% converting the units to uV or fT - -% Copyright (C) 2002, Robert Oostenveld -% -% $Log: read_asa_msr.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry -% -% Revision 1.5 2008/11/14 07:41:17 roboos -% only whitespace, no functional change -% -% Revision 1.4 2008/11/14 07:36:24 roboos -% use strcmpi instead of strcmp(lower()) -% -% Revision 1.3 2008/11/12 17:02:03 roboos -% explicitely specify ieee-le in fopen() -% -% Revision 1.2 2003/03/11 15:24:51 roberto -% updated help and copyrights -% - -Npnt = read_asa(fn, 'NumberPositions=', '%d'); -Ntime = read_asa(fn, 'NumberTimesteps=', '%d'); -UnitT = read_asa(fn, 'UnitTime', '%s'); -UnitM = read_asa(fn, 'UnitMeas', '%s'); -Timesteps = read_asa(fn, 'Timesteps', '%s'); -lab = read_asa(fn, 'Labels', '%s', Npnt); - -val = read_asa(fn, 'Values', '%f'); -if any(size(val)~=[Npnt,Ntime]) - msm_file = read_asa(fn, 'Values', '%s'); - [path, name, ext] = fileparts(fn); - fid = fopen(fullfile(path, msm_file), 'rb', 'ieee-le'); - val = fread(fid, [Ntime, Npnt], 'float32')'; - fclose(fid); -end - -tmp = sscanf(Timesteps, '%f(%f)%f'); -time = linspace(tmp(1), tmp(3), Ntime); - -if strcmpi(UnitT,'ms') - time = 1*time; -elseif strcmpi(UnitT,'s') - time = 1000*time; -elseif ~isempty(UnitT) - error(sprintf('Unknown unit of time (%s)', UnitT)); -end - -if strcmpi(UnitM,'uv') - val = 1*val; -elseif strcmpi(UnitM,'?v') - val = 1*val; -elseif strcmpi(UnitM,'mv') - val = 1000*val; -elseif strcmpi(UnitM,'v') - val = 1000000*val; -elseif strcmpi(UnitM,'ft') - val = 1*val; -elseif strcmpi(UnitM,'pt') - val = 1000*val; -elseif ~isempty(UnitM) - error(sprintf('Unknown unit of measurement (%s)', UnitM)); -end - -if length(size(lab))==2 - lab = tokenize(lab{1}); -end - -data.time = time; -data.data = val; -data.label = lab; - - diff --git a/external/fieldtrip/private/read_asa_vol.m b/external/fieldtrip/private/read_asa_vol.m deleted file mode 100644 index 0461280..0000000 --- a/external/fieldtrip/private/read_asa_vol.m +++ /dev/null @@ -1,120 +0,0 @@ -function vol = read_asa_vol(fn); - -% READ_ASA_VOL reads an ASA volume conductor file -% -% all data is converted to the following units -% vertices mm -% conductivities S/m - -% Copyright (C) 2002, Robert Oostenveld -% -% $Log: read_asa_vol.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.4 2008/11/14 07:36:24 roboos -% use strcmpi instead of strcmp(lower()) -% -% Revision 1.3 2003/12/16 10:24:31 roberto -% added ieee-le to binary reading of mat file to fix problem on Mac -% -% Revision 1.2 2003/03/11 15:24:51 roberto -% updated help and copyrights -% - -Nbnd = read_asa(fn, 'NumberBoundaries=', '%d'); -UnitC = read_asa(fn, 'UnitConduct', '%s'); -UnitP = read_asa(fn, 'UnitPosition', '%s'); -cond = read_asa(fn, 'Conductivities', '%f'); -radii = read_asa(fn, 'Radii', '%f'); -pos = read_asa(fn, 'Positions', '%f'); -bnd1 = read_asa(fn, 'Boundary1', '%s'); -bnd2 = read_asa(fn, 'Boundary2', '%s'); -bnd3 = read_asa(fn, 'Boundary3', '%s'); -bnd4 = read_asa(fn, 'Boundary4', '%s'); - -if ~isempty(radii) | ~isempty(pos) - % this appears to be a spherical volume conductor - if strcmpi(UnitP,'mm') - radii = 1*radii; - pos = 1*pos; - elseif strcmpi(UnitP,'cm') - radii = 100*radii; - pos = 100*pos; - elseif strcmpi(UnitP,'m') - radii = 1000*radii; - pos = 1000*pos; - else - error(sprintf('Unknown unit of distance for volume (%s)', UnitP)); - end -end - -if strcmpi(UnitC,'s/m') - cond = cond/1; -elseif strcmpi(UnitC,'s/cm') - cond = cond/100; -elseif strcmpi(UnitC,'s/mm') - cond = cond/1000; -else - error(sprintf('Unknown unit of conductivity for volume (%s)', UnitC)); -end - -if ~isempty(radii) - % this appears to be a spherical volume conductor - vol.radius = radii; - vol.cond = cond; - vol.center = pos; -else - % this appears to be a realistical volume conductor - [path, name, ext] = fileparts(fn); - if Nbnd>=1 - vol.bnd(1) = read_asa_bnd(fullfile(path, bnd1)); - end - if Nbnd>=2 - vol.bnd(2) = read_asa_bnd(fullfile(path, bnd2)); - end - if Nbnd>=3 - vol.bnd(3) = read_asa_bnd(fullfile(path, bnd3)); - end - if Nbnd>=4 - vol.bnd(4) = read_asa_bnd(fullfile(path, bnd4)); - end - if Nbnd>=5 - error('cannot read more than 4 boundaries'); - end - - % if there is a precomputed matrix, read it from an external file - mat_file = read_asa(fn, 'Matrix', '%s'); - if ~isempty(mat_file) - nr = read_asa(fullfile(path, mat_file), 'NumberRows=', '%d'); - nc = read_asa(fullfile(path, mat_file), 'NumberColumns=', '%d'); - mab_file = read_asa(fullfile(path, mat_file), 'Matrix', '%s'); - fid = fopen(fullfile(path, mab_file), 'rb', 'ieee-le'); - if fid==-1 - error(sprintf('could not open file %s', mab_file)); - else - vol.mat = fread(fid, [nr nc], 'float32'); - fclose(fid); - % remove the factor 2 that ASA assumes in the system matrix - vol.mat = vol.mat/2; - % scale the system matrix corresponding to vertex coordinates in mm - vol.mat = vol.mat*100; - end - end - - vol.cond = cond; -end - -% remove all empty fields -field=fieldnames(vol); -for i=1:length(field) - if isempty(getfield(vol, field{i})) - vol = rmfield(vol, field{i}); - end -end - diff --git a/external/fieldtrip/private/read_besa_avr.m b/external/fieldtrip/private/read_besa_avr.m index 73a6f8f..b1c2432 100644 --- a/external/fieldtrip/private/read_besa_avr.m +++ b/external/fieldtrip/private/read_besa_avr.m @@ -18,28 +18,23 @@ % Copyright (C) 2003-2006, Robert Oostenveld % -% $Log: read_besa_avr.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.4 2008/03/25 10:57:34 roboos -% get channel names from ela file if present +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.3 2006/10/05 08:53:22 roboos -% added support for another header extension (for Vladimir) +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.2 2005/04/25 11:10:27 roboos -% changed output labels into cell-array -% added support for reading channel labels from accompanying elp file -% -% Revision 1.1 2005/03/31 07:09:37 roboos -% old implementation, but new implementation of support for avr files that contain channel names +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: read_besa_avr.m 945 2010-04-21 17:41:20Z roboos $ fid = fopen(filename, 'rt'); diff --git a/external/fieldtrip/private/read_besa_mul.m b/external/fieldtrip/private/read_besa_mul.m index 96893e4..a2c922d 100644 --- a/external/fieldtrip/private/read_besa_mul.m +++ b/external/fieldtrip/private/read_besa_mul.m @@ -7,16 +7,23 @@ % Copyright (C) 2005, Robert Oostenveld % -% $Log: read_besa_mul.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.2 2008/11/14 07:42:13 roboos -% use general tokenize function instead of local copy, removed tokenize as subfunction +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.1 2005/07/29 13:32:38 roboos -% new implementation +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_besa_mul.m 945 2010-04-21 17:41:20Z roboos $ dat = []; fid = fopen(filename, 'rt'); @@ -42,7 +49,9 @@ hdr1 = fgetl(fid); % split the first header line into separate elements -tmp = tokenize(hdr1, ' '); +%!!! 2009/09/25 +%tmp = tokenize(hdr1, ' '); +tmp = tokenize(hdr1, ' ',1); for i=1:length(tmp) % extract the information from each element dum = tokenize(tmp{i}, '='); @@ -83,7 +92,9 @@ hdr2 = fgetl(fid); % split the second header line into channel/source labels -dat.label = tokenize(hdr2, ' '); +%!!! 2009/09/25 +%dat.label = tokenize(hdr2, ' '); +dat.label = tokenize(hdr2, ' ',1); % read the actual data dat.data = fscanf(fid, '%g'); diff --git a/external/fieldtrip/private/read_besa_pdg.m b/external/fieldtrip/private/read_besa_pdg.m index c2a66f0..82f9446 100644 --- a/external/fieldtrip/private/read_besa_pdg.m +++ b/external/fieldtrip/private/read_besa_pdg.m @@ -11,20 +11,23 @@ % Copyright (C) 2005, Vladimir Litvak 6/4/05 % -% $Log: read_besa_pdg.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.2 2005/07/28 14:08:06 roboos -% converted from partially dos/unix into pure unix (i.e. removed CRs) +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.1 2005/07/28 13:59:09 roboos -% renamed read_pdg.m into read_besa_pdg.m +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.2 2005/07/28 13:58:10 roboos -% added copyrights, added log -% updated to latest version from Vladimir (1/7/05) +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: read_besa_pdg.m 945 2010-04-21 17:41:20Z roboos $ data_type=1; % needs to be 1 for EEG, 2 for MEG diff --git a/external/fieldtrip/private/read_besa_src.m b/external/fieldtrip/private/read_besa_src.m index 31198dc..b13e7e7 100644 --- a/external/fieldtrip/private/read_besa_src.m +++ b/external/fieldtrip/private/read_besa_src.m @@ -10,16 +10,23 @@ % Copyright (C) 2005, Robert Oostenveld % -% $Log: read_besa_src.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.2 2005/10/05 06:32:08 roboos -% removed forced reading of (incorrect) condition label +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.1 2005/09/01 09:22:35 roboos -% new implementation, only tested on a single file +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_besa_src.m 945 2010-04-21 17:41:20Z roboos $ src = []; fid = fopen(filename, 'rt'); diff --git a/external/fieldtrip/private/read_besa_swf.m b/external/fieldtrip/private/read_besa_swf.m index 4e7bc07..a38e930 100644 --- a/external/fieldtrip/private/read_besa_swf.m +++ b/external/fieldtrip/private/read_besa_swf.m @@ -15,24 +15,23 @@ % Copyright (C) 2006, Robert Oostenveld % -% $Log: read_besa_swf.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.3 2006/06/22 15:03:07 roboos -% fixed bug, data was transposed in case of row-formatted file +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.2 2006/03/20 08:39:13 roboos -% 2 small bug fixes, thanks to Vladimir +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.1 2006/03/16 17:31:42 roboos -% new implementation, supports both rows and columns +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: read_besa_swf.m 945 2010-04-21 17:41:20Z roboos $ fid = fopen(filename); line = fgetl(fid); diff --git a/external/fieldtrip/private/read_besa_tfc.m b/external/fieldtrip/private/read_besa_tfc.m index 4cd5539..96f71f0 100644 --- a/external/fieldtrip/private/read_besa_tfc.m +++ b/external/fieldtrip/private/read_besa_tfc.m @@ -21,20 +21,23 @@ % Copyright (C) 2005, Vladimir Litvak % -% $Log: read_besa_tfc.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.3 2006/04/05 15:36:13 roboos -% documented bug that was reported for matlab72, not yet fixed +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.2 2005/07/29 13:26:49 roboos -% removed printing of the channel number (too noisy on screen) +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.1 2005/07/28 14:09:22 roboos -% implementation done by Vladimir Litvak -% renamed from ReadBESATFC into read_besa_tfc +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: read_besa_tfc.m 945 2010-04-21 17:41:20Z roboos $ fp = fopen(FILENAME); diff --git a/external/fieldtrip/private/read_biosemi_bdf.m b/external/fieldtrip/private/read_biosemi_bdf.m deleted file mode 100644 index a40fc88..0000000 --- a/external/fieldtrip/private/read_biosemi_bdf.m +++ /dev/null @@ -1,307 +0,0 @@ -function dat = read_biosemi_bdf(filename, hdr, begsample, endsample, chanindx); - -% READ_BIOSEMI_BDF reads specified samples from a BDF continous datafile -% It neglects all trial boundaries as if the data was acquired in -% non-continous mode. -% -% Use as -% [hdr] = read_biosemi_bdf(filename); -% where -% filename name of the datafile, including the .bdf extension -% This returns a header structure with the following elements -% hdr.Fs sampling frequency -% hdr.nChans number of channels -% hdr.nSamples number of samples per trial -% hdr.nSamplesPre number of pre-trigger samples in each trial -% hdr.nTrials number of trials -% hdr.label cell-array with labels of each channel -% hdr.orig detailled EDF header information -% -% Or use as -% [dat] = read_biosemi_bdf(filename, hdr, begsample, endsample, chanindx); -% where -% filename name of the datafile, including the .bdf extension -% hdr header structure, see above -% begsample index of the first sample to read -% endsample index of the last sample to read -% chanindx index of channels to read (optional, default is all) -% This returns a Nchans X Nsamples data matrix - -% Copyright (C) 2006, Robert Oostenveld -% -% $Log: read_biosemi_bdf.m,v $ -% Revision 1.2 2009/10/12 12:14:23 roboos -% fixed small typo in readLowLevel fnuction, thanks to Philip -% -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.7 2008/10/06 08:42:17 roboos -% added missing "end" in subfunction -% -% Revision 1.6 2008/10/03 12:20:57 roboos -% use matlab reading instead of mex file in case file >2GB, thanks to Philip -% -% Revision 1.5 2008/09/30 07:47:04 roboos -% replaced all occurences of setstr() with char(), because setstr is deprecated by Matlab -% -% Revision 1.4 2007/10/01 13:44:21 roboos -% changed a detail in the calibration (in case of one channel the output would remain sparse) -% -% Revision 1.3 2007/09/13 09:52:20 roboos -% removed section of code regarding idx1/2/3 which was slow but unneeded -% avoid confusion between EDF and hdr.orig -% implemented much faster reading for a single channel (efficient when reading status channel) -% -% Revision 1.2 2007/09/12 12:52:09 roboos -% calibrate the data -% -% Revision 1.1 2006/02/01 08:18:48 roboos -% new implementation, based on some EEGLAB code and a mex file for the binary part of the data -% - -if nargin==1 - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % read the header, this code is from EEGLAB's openbdf - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - FILENAME = filename; - - % defines Seperator for Subdirectories - SLASH='/'; - BSLASH=char(92); - - cname=computer; - if cname(1:2)=='PC' SLASH=BSLASH; end; - - fid=fopen(FILENAME,'r','ieee-le'); - if fid<0 - fprintf(2,['Error LOADEDF: File ' FILENAME ' not found\n']); - return; - end; - - EDF.FILE.FID=fid; - EDF.FILE.OPEN = 1; - EDF.FileName = FILENAME; - - PPos=min([max(find(FILENAME=='.')) length(FILENAME)+1]); - SPos=max([0 find((FILENAME=='/') | (FILENAME==BSLASH))]); - EDF.FILE.Ext = FILENAME(PPos+1:length(FILENAME)); - EDF.FILE.Name = FILENAME(SPos+1:PPos-1); - if SPos==0 - EDF.FILE.Path = pwd; - else - EDF.FILE.Path = FILENAME(1:SPos-1); - end; - EDF.FileName = [EDF.FILE.Path SLASH EDF.FILE.Name '.' EDF.FILE.Ext]; - - H1=char(fread(EDF.FILE.FID,256,'char')'); % - EDF.VERSION=H1(1:8); % 8 Byte Versionsnummer - %if 0 fprintf(2,'LOADEDF: WARNING Version EDF Format %i',ver); end; - EDF.PID = deblank(H1(9:88)); % 80 Byte local patient identification - EDF.RID = deblank(H1(89:168)); % 80 Byte local recording identification - %EDF.H.StartDate = H1(169:176); % 8 Byte - %EDF.H.StartTime = H1(177:184); % 8 Byte - EDF.T0=[str2num(H1(168+[7 8])) str2num(H1(168+[4 5])) str2num(H1(168+[1 2])) str2num(H1(168+[9 10])) str2num(H1(168+[12 13])) str2num(H1(168+[15 16])) ]; - - % Y2K compatibility until year 2090 - if EDF.VERSION(1)=='0' - if EDF.T0(1) < 91 - EDF.T0(1)=2000+EDF.T0(1); - else - EDF.T0(1)=1900+EDF.T0(1); - end; - else ; - % in a future version, this is hopefully not needed - end; - - EDF.HeadLen = str2num(H1(185:192)); % 8 Byte Length of Header - % reserved = H1(193:236); % 44 Byte - EDF.NRec = str2num(H1(237:244)); % 8 Byte # of data records - EDF.Dur = str2num(H1(245:252)); % 8 Byte # duration of data record in sec - EDF.NS = str2num(H1(253:256)); % 8 Byte # of signals - - EDF.Label = char(fread(EDF.FILE.FID,[16,EDF.NS],'char')'); - EDF.Transducer = char(fread(EDF.FILE.FID,[80,EDF.NS],'char')'); - EDF.PhysDim = char(fread(EDF.FILE.FID,[8,EDF.NS],'char')'); - - EDF.PhysMin= str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); - EDF.PhysMax= str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); - EDF.DigMin = str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); - EDF.DigMax = str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); - - % check validity of DigMin and DigMax - if (length(EDF.DigMin) ~= EDF.NS) - fprintf(2,'Warning OPENEDF: Failing Digital Minimum\n'); - EDF.DigMin = -(2^15)*ones(EDF.NS,1); - end - if (length(EDF.DigMax) ~= EDF.NS) - fprintf(2,'Warning OPENEDF: Failing Digital Maximum\n'); - EDF.DigMax = (2^15-1)*ones(EDF.NS,1); - end - if (any(EDF.DigMin >= EDF.DigMax)) - fprintf(2,'Warning OPENEDF: Digital Minimum larger than Maximum\n'); - end - % check validity of PhysMin and PhysMax - if (length(EDF.PhysMin) ~= EDF.NS) - fprintf(2,'Warning OPENEDF: Failing Physical Minimum\n'); - EDF.PhysMin = EDF.DigMin; - end - if (length(EDF.PhysMax) ~= EDF.NS) - fprintf(2,'Warning OPENEDF: Failing Physical Maximum\n'); - EDF.PhysMax = EDF.DigMax; - end - if (any(EDF.PhysMin >= EDF.PhysMax)) - fprintf(2,'Warning OPENEDF: Physical Minimum larger than Maximum\n'); - EDF.PhysMin = EDF.DigMin; - EDF.PhysMax = EDF.DigMax; - end - EDF.PreFilt= char(fread(EDF.FILE.FID,[80,EDF.NS],'char')'); % - tmp = fread(EDF.FILE.FID,[8,EDF.NS],'char')'; % samples per data record - EDF.SPR = str2num(char(tmp)); % samples per data record - - fseek(EDF.FILE.FID,32*EDF.NS,0); - - EDF.Cal = (EDF.PhysMax-EDF.PhysMin)./(EDF.DigMax-EDF.DigMin); - EDF.Off = EDF.PhysMin - EDF.Cal .* EDF.DigMin; - tmp = find(EDF.Cal < 0); - EDF.Cal(tmp) = ones(size(tmp)); - EDF.Off(tmp) = zeros(size(tmp)); - - EDF.Calib=[EDF.Off';(diag(EDF.Cal))]; - %EDF.Calib=sparse(diag([1; EDF.Cal])); - %EDF.Calib(1,2:EDF.NS+1)=EDF.Off'; - - EDF.SampleRate = EDF.SPR / EDF.Dur; - - EDF.FILE.POS = ftell(EDF.FILE.FID); - if EDF.NRec == -1 % unknown record size, determine correct NRec - fseek(EDF.FILE.FID, 0, 'eof'); - endpos = ftell(EDF.FILE.FID); - EDF.NRec = floor((endpos - EDF.FILE.POS) / (sum(EDF.SPR) * 2)); - fseek(EDF.FILE.FID, EDF.FILE.POS, 'bof'); - H1(237:244)=sprintf('%-8i',EDF.NRec); % write number of records - end; - - EDF.Chan_Select=(EDF.SPR==max(EDF.SPR)); - for k=1:EDF.NS - if EDF.Chan_Select(k) - EDF.ChanTyp(k)='N'; - else - EDF.ChanTyp(k)=' '; - end; - if findstr(upper(EDF.Label(k,:)),'ECG') - EDF.ChanTyp(k)='C'; - elseif findstr(upper(EDF.Label(k,:)),'EKG') - EDF.ChanTyp(k)='C'; - elseif findstr(upper(EDF.Label(k,:)),'EEG') - EDF.ChanTyp(k)='E'; - elseif findstr(upper(EDF.Label(k,:)),'EOG') - EDF.ChanTyp(k)='O'; - elseif findstr(upper(EDF.Label(k,:)),'EMG') - EDF.ChanTyp(k)='M'; - end; - end; - - EDF.AS.spb = sum(EDF.SPR); % Samples per Block - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % convert the header to Fieldtrip-style - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - if any(EDF.SampleRate~=EDF.SampleRate(1)) - error('channels with different sampling rate not supported'); - end - hdr.Fs = EDF.SampleRate(1); - hdr.nChans = EDF.NS; - hdr.label = cellstr(EDF.Label); - % it is continuous data, therefore append all records in one trial - hdr.nTrials = 1; - hdr.nSamples = EDF.NRec * EDF.Dur * EDF.SampleRate(1); - hdr.nSamplesPre = 0; - hdr.orig = EDF; - - % return the header - dat = hdr; - -else - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % read the data - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % retrieve the original header - EDF = hdr.orig; - - % determine the trial containing the begin and end sample - epochlength = EDF.Dur * EDF.SampleRate(1); - begepoch = floor((begsample-1)/epochlength) + 1; - endepoch = floor((endsample-1)/epochlength) + 1; - nepochs = endepoch - begepoch + 1; - nchans = EDF.NS; - - if nargin<5 - chanindx = 1:nchans; - end - - % allocate memory to hold the data - dat = zeros(length(chanindx),nepochs*epochlength); - - % read and concatenate all required data epochs - for i=begepoch:endepoch - offset = EDF.HeadLen + (i-1)*epochlength*nchans*3; - if length(chanindx)==1 - % this is more efficient if only one channel has to be read, e.g. the status channel - offset = offset + (chanindx-1)*epochlength*3; - buf = readLowLevel(filename, offset, epochlength); % see below in subfunction - dat(:,((i-begepoch)*epochlength+1):((i-begepoch+1)*epochlength)) = buf; - else - % read the data from all channels and then select the desired channels - buf = readLowLevel(filename, offset, epochlength*nchans); % see below in subfunction - buf = reshape(buf, epochlength, nchans); - dat(:,((i-begepoch)*epochlength+1):((i-begepoch+1)*epochlength)) = buf(:,chanindx)'; - end - end - - % select the desired samples - begsample = begsample - (begepoch-1)*epochlength; % correct for the number of bytes that were skipped - endsample = endsample - (begepoch-1)*epochlength; % correct for the number of bytes that were skipped - dat = dat(:, begsample:endsample); - - % Calibrate the data - if length(chanindx)>1 - % using a sparse matrix speeds up the multiplication - calib = sparse(diag(EDF.Cal(chanindx,:))); - dat = calib * dat; - else - % in case of one channel the calibration would result in a sparse array - calib = diag(EDF.Cal(chanindx,:)); - dat = calib * dat; - end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION for reading the 24 bit values -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function buf = readLowLevel(filename, offset, numwords); -if offset < 2*1024^3 - % use the external mex file, only works for <2GB - buf = read_24bit(filename, offset, numwords); - % this would be the only difference between the bdf and edf implementation - % buf = read_16bit(filename, offset, numwords); -else - % use plain matlab, thanks to Philip van der Broek - fp = fopen(filename,'r','ieee-le'); - status = fseek(fp, offset, 'bof'); - if status - error(['failed seeking ' filename]); - end - [buf,num] = fread(fp,numwords,'bit24=>double'); - fclose(fp); - if (num4 - % select the channels of interest - dat = dat(chanindx,:); -end diff --git a/external/fieldtrip/private/read_biosig_header.m b/external/fieldtrip/private/read_biosig_header.m deleted file mode 100644 index 4927e43..0000000 --- a/external/fieldtrip/private/read_biosig_header.m +++ /dev/null @@ -1,132 +0,0 @@ -function [hdr] = read_biosig_header(filename) - -% READ_BIOSIG_HEADER reads header from EEG file using the BIOSIG -% toolbox and returns it in the FCDC framework standard format -% -% Use as -% [hdr] = read_biosig_header(filename) -% -% The following data formats are supported: EDF, BKR, CNT, BDF, GDF, -% see for full documentation http://biosig.sourceforge.net/ -% -% See also READ_BIOSIG_DATA - -% This program is free software; you can redistribute it and/or -% modify it under the terms of the GNU General Public License -% as published by the Free Software Foundation; either version 2 -% of the License, or (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program; if not, write to the Free Software -% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -% Copyright (C) 2004, Robert Oostenveld -% -% $Log: read_biosig_header.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.3 2008/04/10 09:36:14 roboos -% biosig labels are already cell array -% -% Revision 1.2 2004/03/11 10:18:57 roberto -% fixed bug in number of samples (should be the same in all channels) -% -% Revision 1.1 2004/03/10 11:50:31 roberto -% new implementation of wrapper functions around the BIOSIG toolbox (specifically section T200) -% - -% open the file, read the header and close it again -biosig = sopen(filename,'r'); -sclose(biosig); - -% the BIOSIG header is defined in full detail below -% the FCDC header should at least contain the following fields -% hdr.Fs sampling frequency -% hdr.nChans number of channels -% hdr.nSamples number of samples per trial -% hdr.nSamplesPre number of pre-trigger samples in each trial -% hdr.nTrials number of trials -% hdr.label cell-array with labels of each channel - -if length(biosig.SampleRate)>1 & any(diff(biosig.SampleRate)) - error('channels with different sampling rates are not supported'); -else - hdr.Fs = biosig.SampleRate(1); -end - -if length(biosig.SPR)>1 & any(diff(biosig.SPR)) - error('channels with different number of samples are not supported'); -else - hdr.nSamples = biosig.SPR(1); -end - -hdr.nChans = biosig.NS; -hdr.nTrials = biosig.NRec; -hdr.nSamplesPre = 0; % this one is not in the biosig header -hdr.label = {}; % start with empty labels and fill them below - -if isfield(biosig, 'Label') - hdr.label = biosig.Label; -end - -if length(hdr.label)~=hdr.nChans - % make default channel labels - hdr.label = {}; - for i=1:hdr.nChans - hdr.label{i} = sprintf('%d', i); - end -end - -% I prefer to have them as column vector -hdr.label = hdr.label(:); - -% also remember the biosig header details -hdr.orig = biosig; -return; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% the BIOSIG header always contains these elements -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% HDR.TYPE string type of data format -% HDR.VERSION string (depends on data format) -% HDR.T0 float[1..6] [yyyy mm dd hh MM ss.cc] see HELP CLOCK -% HDR.NS integer number of channels -% HDR.SampleRate integer sampling frequency in [Hz] -% HDR.NRec integer number of records or blocks; 1 for continous data -% HDR.SPR integer samples per record -% HDR.Dur float Duration (in [s]) of minimal block length -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% the BIOSIG header optinally contains the following elements -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% HDR.Filter.LowPass float [Hz] -% HDR.Filter.HighPass float [Hz] -% HDR.Filter.Notch int8 0=Off, 1=ON -% HDR.PreFilt string filter setting -% HDR.Label char-array z.B. '+C3a - C3p ' -% HDR.PhysDim string physical dimension e.g. 'uV' -% HDR.PhysMax float physical maximum -% HDR.DigMax integer digital maximum -% HDR.PhysMin float physical minimum -% HDR.DigMin integer digital minimum -% HDR.FLAG.TRIGGERED int 0=no, 1=yes -% HDR.FLAG.REFERENCE string COM, CAR: common average reference; LOC,LAR local average ref; LAP Laplacian derivation, WGT weighted average -% HDR.Classlabel int 0: left, 1: right, etc. -% HDR.ID.Doctor Identification of doctor -% HDR.ID.Hospital Identification of Hospital -% HDR.Patient.Name Name of Patient -% HDR.Patient.Age Age of Patient -% HDR.Patient.Sex Patient Gender -% HDR.Patient.Handedness Patient Handedness -% HDR.Patient.Medication Medication -% HDR.Patient.Classification Classification of Patient diff --git a/external/fieldtrip/private/read_brainvision_eeg.m b/external/fieldtrip/private/read_brainvision_eeg.m deleted file mode 100644 index cde8cd5..0000000 --- a/external/fieldtrip/private/read_brainvision_eeg.m +++ /dev/null @@ -1,129 +0,0 @@ -function [dat] = read_brainvision_eeg(filename, hdr, begsample, endsample); - -% READ_BRAINVISION_EEG reads raw data from an EEG file -% and returns it as a Nchans x Nsamples matrix -% -% Use as -% dat = read_brainvision_eeg(filename, hdr, begsample, endsample) -% where the header should be first read using read_brainvision_vhdr -% -% See also READ_BRAINVISION_VHDR, READ_BRAINVISION_VMRK - -% Copyright (C) 2003, Robert Oostenveld -% -% $Log: read_brainvision_eeg.m,v $ -% Revision 1.2 2009/03/13 07:13:28 roboos -% added feedback to vectorized ascii subformat -% fixed problem in vectorized ascii subformat when lines would start with the channel label -% -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.5 2008/04/09 10:10:58 roboos -% added support for int_32 -% renamed nChans into the original form -% -% Revision 1.4 2007/06/13 08:08:19 roboos -% changed single & into && -% -% Revision 1.3 2004/03/30 11:47:50 roberto -% dos->unix, fixed bug in multiplexed binary -% -% Revision 1.2 2004/03/30 08:22:19 roberto -% fixed bug due to renaming NumberOfChannels -> nChans -% -% Revision 1.1 2004/03/30 07:23:28 roberto -% added to CVS repository, copyrights added and implemented multiple file -% formats -% - -if strcmpi(hdr.DataFormat, 'binary') && strcmpi(hdr.DataOrientation, 'multiplexed') && strcmpi(hdr.BinaryFormat, 'int_16') - fid = fopen(filename, 'rb', 'ieee-le'); - fseek(fid, hdr.NumberOfChannels*2*(begsample-1), 'cof'); - [dat, siz] = fread(fid, [hdr.NumberOfChannels, (endsample-begsample+1)], 'int16'); - fclose(fid); - % compute real microvolts using the calibration factor (resolution) - res = sparse(diag(hdr.resolution)); - dat = res * dat; - -elseif strcmpi(hdr.DataFormat, 'binary') && strcmpi(hdr.DataOrientation, 'multiplexed') && strcmpi(hdr.BinaryFormat, 'int_32') - fid = fopen(filename, 'rb', 'ieee-le'); - fseek(fid, hdr.NumberOfChannels*4*(begsample-1), 'cof'); - [dat, siz] = fread(fid, [hdr.NumberOfChannels, (endsample-begsample+1)], 'int32'); - fclose(fid); - % compute real microvolts using the calibration factor (resolution) - res = sparse(diag(hdr.resolution)); - dat = res * dat; - -elseif strcmpi(hdr.DataFormat, 'binary') && strcmpi(hdr.DataOrientation, 'multiplexed') && strcmpi(hdr.BinaryFormat, 'ieee_float_32') - fid = fopen(filename, 'rb', 'ieee-le'); - fseek(fid, hdr.NumberOfChannels*4*(begsample-1), 'cof'); - [dat, siz] = fread(fid, [hdr.NumberOfChannels, (endsample-begsample+1)], 'float32'); - fclose(fid); - -elseif strcmpi(hdr.DataFormat, 'binary') && strcmpi(hdr.DataOrientation, 'vectorized') && strcmpi(hdr.BinaryFormat, 'ieee_float_32') - fid = fopen(filename, 'rb', 'ieee-le'); - fseek(fid, 0, 'eof'); - hdr.nSamples = ftell(fid)/(4*hdr.NumberOfChannels); - fseek(fid, 0, 'bof'); - numsamples = (endsample-begsample+1); - for chan=1:hdr.NumberOfChannels - fseek(fid, (begsample-1)*4, 'cof'); % skip the first N samples - [tmp, siz] = fread(fid, numsamples, 'float32'); % read these samples - fseek(fid, (hdr.nSamples-endsample)*4, 'cof'); % skip the last M samples - dat(chan,:) = tmp(:)'; - end - fclose(fid); - -elseif strcmpi(hdr.DataFormat, 'ascii') && strcmpi(hdr.DataOrientation, 'multiplexed') - fid = fopen(filename, 'rt'); - for line=1:(begsample-1) - % read first lines and discard the data in them - str = fgets(fid); - end - dat = zeros(endsample-begsample+1, hdr.NumberOfChannels); - for line=1:(endsample-begsample+1) - str = fgets(fid); % read a single line with Nchan samples - str(find(str==',')) = '.'; % replace comma with point - dat(line,:) = str2num(str); - end - fclose(fid); - % transpose the data - dat = dat'; - -elseif strcmpi(hdr.DataFormat, 'ascii') && strcmpi(hdr.DataOrientation, 'vectorized') - % this is a very inefficient fileformat to read data from, since it requires to - % read in all the samples of each channel and then select only the samples of interest - fid = fopen(filename, 'rt'); - dat = zeros(hdr.NumberOfChannels, endsample-begsample+1); - for chan=1:hdr.NumberOfChannels - % this is very slow, so better give some feedback to indicate that something is happening - fprintf('reading channel %d from ascii file to get data from sample %d to %d\n', chan, begsample, endsample); - - str = fgets(fid); % read all samples of a single channel - str(find(str==',')) = '.'; % replace comma with point - - if ~isempty(regexp(str(1:10), '[a-zA-Z]', 'once')) - % the line starts with letters, not numbers: probably it is a channel label - % find the first number and remove the preceding part - sel = regexp(str(1:10), ' [-0-9]'); % find the first number, or actually the last space before the first number - label = str(1:(sel)); % this includes the space - str = str((sel+1):end); % keep only the numbers - end - - % convert the string into numbers and copy the desired samples over - % into the data matrix - tmp = str2num(str); - dat(chan,:) = tmp(begsample:endsample); - end - fclose(fid); - -else - error('unsupported sub-fileformat'); -end - diff --git a/external/fieldtrip/private/read_brainvision_marker.m b/external/fieldtrip/private/read_brainvision_marker.m index 5f270bc..0aca199 100644 --- a/external/fieldtrip/private/read_brainvision_marker.m +++ b/external/fieldtrip/private/read_brainvision_marker.m @@ -10,16 +10,23 @@ % Copyright (C) 2004, Robert Oostenveld & Doug Davidson % -% $Log: read_brainvision_marker.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.2 2004/09/24 15:57:20 roboos -% implemented suggested change by Doug Davidson: get sampling rate from file instead of having it hard coded +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.1 2004/08/26 15:53:18 roboos -% new implementation by Doug Davidson, based upon read_eep_rej +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_brainvision_marker.m 945 2010-04-21 17:41:20Z roboos $ rej = []; diff --git a/external/fieldtrip/private/read_brainvision_pos.m b/external/fieldtrip/private/read_brainvision_pos.m deleted file mode 100644 index fdd7613..0000000 --- a/external/fieldtrip/private/read_brainvision_pos.m +++ /dev/null @@ -1,62 +0,0 @@ -function [elec] = read_brainvision_pos(filename); - -% READ_BRAINVISION_POS reads electrode positions measured with the Polhemus -% tracker in one of the F.C. Donders EEG labs. The polhemus software is actually -% not from Brainvision. -% -% Use as: -% [elec] = read_brainvision_pos(filename) -% -% This returns an electrode structure with -% elec.label cell-array with electrode labels (strings) -% elec.pnt position of each electrode - -% Copyright (C) 2004, Robert Oostenveld -% -% $Log: read_brainvision_pos.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.1 2004/03/18 09:34:34 roberto -% also read in the fiducials if present at the end of the file -% - -fid = fopen(filename, 'rt'); -line = fgetl(fid); -Nchan = str2double(line); - -for i=1:Nchan - line = fgetl(fid); - [t, r] = strtok(line); - elec.label{i} = char(t); - elec.pnt(i,:) = sscanf(r, '%f')'; -end -elec.label = elec.label(:); - -try - % read the fiducials - line = fgetl(fid); - [t, r] = strtok(line); - fiducial.label{1} = char(t); - fiducial.pnt(1,:) = sscanf(r, '%f')'; - line = fgetl(fid); - [t, r] = strtok(line); - fiducial.label{2} = char(t); - fiducial.pnt(2,:) = sscanf(r, '%f')'; - line = fgetl(fid); - [t, r] = strtok(line); - fiducial.label{3} = char(t); - fiducial.pnt(3,:) = sscanf(r, '%f')'; - % add the fiducials to the electrode array - elec.label = cat(1, elec.label(:), fiducial.label(:)); - elec.pnt = cat(1, elec.pnt, fiducial.pnt); -catch - % do nothing -end - -fclose(fid); \ No newline at end of file diff --git a/external/fieldtrip/private/read_brainvision_seg.m b/external/fieldtrip/private/read_brainvision_seg.m deleted file mode 100644 index 847865e..0000000 --- a/external/fieldtrip/private/read_brainvision_seg.m +++ /dev/null @@ -1,51 +0,0 @@ -function [dat] = read_brainvision_seg(filename, hdr, begsample, endsample); - -% READ_BRAINVISION_SEG reads raw data from an segmented EEG file -% and returns it as a Nchans x Nsamples matrix. The data is read -% as if it were continuous data, this function does not check whether -% the specified begin and endsample are withing the same segment. -% -% Use as -% dat = read_brainvision_seg(filename, hdr, begsample, endsample) -% where the header should be first read using read_brainvision_vhdr -% -% See also READ_BRAINVISION_VHDR, READ_BRAINVISION_VMRK - -% Copyright (C) 2003, Robert Oostenveld -% -% $Log: read_brainvision_seg.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.4 2008/04/09 10:11:23 roboos -% renamed nChans into the original form, converted from dos to unix -% -% Revision 1.3 2007/06/13 08:08:19 roboos -% changed single & into && -% -% Revision 1.2 2004/03/30 08:22:19 roberto -% fixed bug due to renaming NumberOfChannels -> nChans -% -% Revision 1.1 2004/03/30 07:23:28 roberto -% added to CVS repository, copyrights added and implemented multiple file -% formats -% - -if strcmpi(hdr.DataFormat, 'binary') && strcmpi(hdr.DataOrientation, 'multiplexed') && strcmpi(hdr.BinaryFormat, 'int_16') - % this is a fileformat that I understand - fid = fopen(filename, 'rb', 'ieee-le'); - fseek(fid, hdr.NumberOfChannels*2*(begsample-1), 'cof'); - [dat, siz] = fread(fid, [hdr.NumberOfChannels, (endsample-begsample+1)], 'int16'); - fclose(fid); - % compute real microvolts using the calibration factor (resolution) - res = sparse(diag(hdr.resolution)); - dat = res * dat; -else - error('unsupported sub-fileformat'); -end - diff --git a/external/fieldtrip/private/read_brainvision_vhdr.m b/external/fieldtrip/private/read_brainvision_vhdr.m deleted file mode 100644 index 82210f9..0000000 --- a/external/fieldtrip/private/read_brainvision_vhdr.m +++ /dev/null @@ -1,109 +0,0 @@ -function [hdr] = read_brainvision_vhdr(filename); - -% READ_BRAINVISION_VHDR reads the known items from the BrainVision EEG -% header file and returns them in a structure -% -% Use as -% hdr = read_brainvision_vhdr(filename) -% -% See also READ_BRAINVISION_EEG, READ_BRAINVISION_VMRK - -% Copyright (C) 2003, Robert Oostenveld -% -% $Log: read_brainvision_vhdr.m,v $ -% Revision 1.2 2009/03/12 17:09:31 roboos -% improved the warning in case number of samples cannot be determined (applies to ascii *.seg data) -% -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.7 2008/11/14 07:42:13 roboos -% use general tokenize function instead of local copy, removed tokenize as subfunction -% -% Revision 1.6 2008/07/10 07:15:30 roboos -% also determine data file size if on another directory, thanks to Paul -% -% Revision 1.5 2008/04/16 07:51:11 roboos -% added fixme comment -% -% Revision 1.4 2008/04/09 10:08:28 roboos -% added detection of number of samples, based on filesize (only if binary) -% -% Revision 1.3 2008/04/09 10:06:50 roboos -% renamed nChans into NumberOfChannels to stay as close as possible to the ascii header -% -% Revision 1.2 2004/03/30 11:23:50 roberto -% fixed bug in cutting channel info into pieces, added local tokenize function -% -% Revision 1.1 2004/03/30 07:23:28 roberto -% added to CVS repository, copyrights added and implemented multiple file -% formats -% - -hdr.DataFile = read_asa(filename, 'DataFile=', '%s'); -hdr.MarkerFile = read_asa(filename, 'MarkerFile=', '%s'); -hdr.DataFormat = read_asa(filename, 'DataFormat=', '%s'); -hdr.DataOrientation = read_asa(filename, 'DataOrientation=', '%s'); -hdr.BinaryFormat = read_asa(filename, 'BinaryFormat=', '%s'); -hdr.NumberOfChannels = read_asa(filename, 'NumberOfChannels=', '%d'); -hdr.SamplingInterval = read_asa(filename, 'SamplingInterval=', '%f'); % microseconds - -if ~isempty(hdr.NumberOfChannels) - for i=1:hdr.NumberOfChannels - chan_str = sprintf('Ch%d=', i); - chan_info = read_asa(filename, chan_str, '%s'); - t = tokenize(chan_info, ','); - hdr.label{i} = t{1}; - hdr.reference{i} = t{2}; - resolution = str2num(t{3}); % in microvolt - if ~isempty(resolution) - hdr.resolution(i) = resolution; - else - hdr.resolution(i) = nan; - end - end -end - -% compute the sampling rate in Hz -hdr.Fs = 1e6/(hdr.SamplingInterval); - -% the number of samples is unkown to start with -hdr.nSamples = Inf; - -% determine the number of samples by looking at the binary file -if strcmp(hdr.DataFormat, 'BINARY') - % the data file is supposed to be located in the same directory as the header file - % but that might be on another location than the present working directory - [p, f, x] = fileparts(filename); - datafile = fullfile(p, hdr.DataFile); - info = dir(datafile); - if isempty(info) - error('cannot determine the location of the data file %s', hdr.DataFile); - end - switch lower(hdr.BinaryFormat) - case 'int_16'; - hdr.nSamples = info.bytes./(hdr.NumberOfChannels*2); - case 'int_32'; - hdr.nSamples = info.bytes./(hdr.NumberOfChannels*4); - case 'ieee_float_32'; - hdr.nSamples = info.bytes./(hdr.NumberOfChannels*4); - end -end - -if isinf(hdr.nSamples) - warning('cannot determine number of samples for this sub-fileformat'); -end - -% the number of trials is unkown, assume continuous data -hdr.nTrials = 1; -hdr.nSamplesPre = 0; - -% ensure that the labels are in a column -hdr.label = hdr.label(:); -hdr.reference = hdr.reference(:); -hdr.resolution = hdr.resolution(:); diff --git a/external/fieldtrip/private/read_brainvision_vmrk.m b/external/fieldtrip/private/read_brainvision_vmrk.m deleted file mode 100644 index 86bb49d..0000000 --- a/external/fieldtrip/private/read_brainvision_vmrk.m +++ /dev/null @@ -1,80 +0,0 @@ -function [stimulus, response, segment, timezero] = read_brainvision_vmrk(filename); - -% READ_BRAINVISION_VMRK reads the markers and latencies -% it returns the stimulus/response code and latency in ms. -% -% Use as -% [stim, resp, segment, timezero] = read_brainvision_vmrk(filename) -% -% This function needs to read the header from a separate file and -% assumes that it is located at the same location. -% -% See also READ_BRAINVISION_VHDR, READ_BRAINVISION_EEG - -% original M. Schulte 31.07.2003 -% modifications R. Oostenveld 14.08.2003 -% -% $Log: read_brainvision_vmrk.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry -% -% Revision 1.3 2008/07/24 12:05:12 roboos -% changed end ot line to unix style -% -% Revision 1.2 2004/03/30 07:23:28 roberto -% added to CVS repository, copyrights added and implemented multiple file -% formats -% - -stimulus=[]; -response=[]; -segment=[]; -timezero=[]; - -% read the header belonging to this marker file -hdr=read_brainvision_vhdr([filename(1:(end-4)) 'vhdr']); - -fid=fopen(filename,'rt'); -if fid==-1, - error('cannot open marker file') -end - -line=1; -while line~=-1, - line=fgetl(fid); - % pause - if ~isempty(line), - if ~isempty(findstr(line,'Mk')), - if ~isempty(findstr(line,'Stimulus')) - [token,rem] = strtok(line,','); - type=sscanf(rem,',S %i'); - [token,rem] = strtok(rem,','); - time=(sscanf(rem,', %i')-1)/hdr.Fs*1000; - stimulus=[stimulus; type time(1)]; - - elseif ~isempty(findstr(line,'Response')) - [token,rem] = strtok(line,','); - type=sscanf(rem,',R %i'); - [token,rem] = strtok(rem,','); - time=(sscanf(rem,', %i')-1)/hdr.Fs*1000; - response=[response; type, time(1)]; - - elseif ~isempty(findstr(line,'New Segment')) - [token,rem] = strtok(line,','); - time=(sscanf(rem,',,%i')-1)/hdr.Fs*1000; - segment=[segment; time(1)]; - - elseif ~isempty(findstr(line,'Time 0')) - [token,rem] = strtok(line,','); - time=(sscanf(rem,',,%i')-1)/hdr.Fs*1000; - timezero=[timezero; time(1)]; - - end - end - else - line=1; - end -end - -fclose(fid); - diff --git a/external/fieldtrip/private/read_bti_ascii.m b/external/fieldtrip/private/read_bti_ascii.m deleted file mode 100644 index 09a80bf..0000000 --- a/external/fieldtrip/private/read_bti_ascii.m +++ /dev/null @@ -1,72 +0,0 @@ -function [file] = read_bti_ascii(filename); - -% READ_BTI_ASCII reads general data from a BTI configuration file -% -% The file should be formatted like -% Group: -% item1 : value1a value1b value1c -% item2 : value2a value2b value2c -% item3 : value3a value3b value3c -% item4 : value4a value4b value4c -% - -% Copyright (C) 2004, Robert Oostenveld -% -% $Log: read_bti_ascii.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry -% -% Revision 1.2 2008/11/14 07:49:19 roboos -% use standard matlab strtrim function instead of deblank2 -% -% Revision 1.1 2005/04/18 13:47:05 roboos -% added some old and infrequently used functions to the cvs repository -% -% Revision 1.1 2005/04/18 13:43:34 roboos -% included some old functions in the cvs repository, this ensures consistency of the functions between the different network locations -% - -fid = fopen(filename, 'r'); -if fid==-1 - error(sprintf('could not open file %s', filename)); -end - -line = ''; -while ischar(line) - line = cleanline(fgetl(fid)) - - if isempty(line) | line==-1 | isempty(findstr(line, ':')) - continue - end - - % the line is not empty, which means that we have encountered a chunck of information - if findstr(line, ':')~=length(line) - [item, value] = strtok(line, ':'); - value(1) = ' '; % remove the : - value = strtrim(value); - item = strtrim(item); - item(findstr(item, '.')) = '_'; - item(findstr(item, ' ')) = '_'; - if ischar(item) - eval(sprintf('file.%s = ''%s'';', item, value)); - else - eval(sprintf('file.%s = %s;', item, value)); - end - else - subline = cleanline(fgetl(fid)); - error, the rest has not been implemented (yet) - - end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function line = cleanline(line) -if isempty(line) | line==-1 - return -end -comment = findstr(line, '//'); -if ~isempty(comment) - line(min(comment):end) = ' '; -end -line = strtrim(line); - diff --git a/external/fieldtrip/private/read_bti_hs.m b/external/fieldtrip/private/read_bti_hs.m deleted file mode 100644 index 2eb3467..0000000 --- a/external/fieldtrip/private/read_bti_hs.m +++ /dev/null @@ -1,57 +0,0 @@ -function [output, firstIndexPoint] = read_hs_file( filename, outfile) - -%read_hs_file Reads in BTI-Headshape files -% filename: file with the headshape informations -% outfile: if present, a ctf ".shape" file is written -% output: if present, a 3xN matrix containing the headshape-points -% -% (C) 2007 by Thomas Hartmann - -% $Log: read_bti_hs.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.3 2008/05/11 16:29:57 vlalit -% Changed the function to also output fiducials -% -% Revision 1.2 2007/08/06 09:23:57 roboos -% removed debug output, transposed output to Nx3 -% -% Revision 1.1 2007/08/06 09:03:42 roboos -% version as obtained from Nathan Weisz on 1-Aug-2007 -% - -if nargin == 1 - outfile = []; -end %if - -fid = fopen(filename, 'r', 'b'); -version = fread(fid, 1, '*uint32'); -timestamp = fread(fid, 1, '*int32'); -checksum = fread(fid, 1, '*int32'); -nPoints = fread(fid, 1, '*int32'); - -firstIndexPoint = fread(fid, [3, 5], 'double')'; - -points = fread(fid, [3, double(nPoints)], 'double'); - -fclose(fid); - -if(nargout > 0) - output = points'; -end %if - -if(nargin == 2) - fid = fopen(outfile, 'wt'); - fprintf(fid, '%d\n', nPoints); - for i = 1:size(points, 2) - fprintf(fid, '%.3f\t%.3f\t%.3f\n', points(1, i), points(2, i), points(3, i)); - end %for - fclose(fid); - -end %if diff --git a/external/fieldtrip/private/read_bti_m4d.m b/external/fieldtrip/private/read_bti_m4d.m deleted file mode 100644 index 4837e1e..0000000 --- a/external/fieldtrip/private/read_bti_m4d.m +++ /dev/null @@ -1,176 +0,0 @@ -function [msi] = read_bti_m4d(filename); - -% READ_BTI_M4D -% -% Use as -% msi = read_bti_m4d(filename) - -% Copyright (C) 2007, Robert Oostenveld -% -% $Log: read_bti_m4d.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.3 2008/11/14 07:49:19 roboos -% use standard matlab strtrim function instead of deblank2 -% -% Revision 1.2 2008/08/12 12:56:08 jansch -% fixed assignment of msi.grad. in original implementation only the references were -% stored. in the future this part should be taken care of by bti2grad so that the -% gradiometer references will be correctly handled in the tra-matrix -% -% Revision 1.1 2007/07/03 15:51:46 roboos -% new implementation, only tested on two datasets -% - -[p, f, x] = fileparts(filename); -if ~strcmp(x, '.m4d') - % add the extension of the header - filename = [filename '.m4d']; -end - -fid = fopen(filename, 'r'); -if fid==-1 - error(sprintf('could not open file %s', filename)); -end - -% start with an empty header structure -msi = struct; - -% these header elements contain strings and should be converted in a cell-array -strlist = { - 'MSI.ChannelOrder' - }; - -% these header elements contain numbers and should be converted in a numeric array -% 'MSI.ChannelScale' -% 'MSI.ChannelGain' -% 'MSI.FileType' -% 'MSI.TotalChannels' -% 'MSI.TotalEpochs' -% 'MSI.SamplePeriod' -% 'MSI.SampleFrequency' -% 'MSI.FirstLatency' -% 'MSI.SlicesPerEpoch' -% the conversion to numeric arrays is implemented in a general fashion -% and all the fields above are automatically converted -numlist = {}; - -line = ''; - -msi.grad.label = {}; -msi.grad.pnt = zeros(0,3); -msi.grad.ori = zeros(0,3); -while ischar(line) - line = cleanline(fgetl(fid)); - if isempty(line) || (length(line)==1 && all(line==-1)) - continue - end - - sep = strfind(line, ':'); - if length(sep)==1 - key = line(1:(sep-1)); - val = line((sep+1):end); - elseif length(sep)>1 - % assume that the first separator is the relevant one, and that the - % next ones are part of the value string (e.g. a channel with a ':' in - % its name - sep = sep(1); - key = line(1:(sep-1)); - val = line((sep+1):end); - elseif length(sep)<1 - % this is not what I would expect - error('unexpected content in m4d file'); - end - - if ~isempty(strfind(line, 'Begin')) - sep = strfind(key, '.'); - sep = sep(end); - key = key(1:(sep-1)); - - % if the key ends with begin and there is no value, then there is a block - % of numbers following that relates to the magnetometer/gradiometer information. - % All lines in that Begin-End block should be treated seperately - val = {}; - lab = {}; - num = {}; - ind = 0; - while isempty(strfind(line, 'End')) - line = cleanline(fgetl(fid)); - if isempty(line) || (length(line)==1 && all(line==-1)) || ~isempty(strfind(line, 'End')) - continue - end - ind = ind+1; - % remember the line itself, and also cut it into pieces - val{ind} = line; - % the line is tab-separated and looks like this - % A68 0.0873437 -0.075789 0.0891512 0.471135 -0.815532 0.336098 - sep = find(line==9); % the ascii value of a tab is 9 - sep = sep(1); - lab{ind} = line(1:(sep-1)); - num{ind} = str2num(line((sep+1):end)); - - end % parsing Begin-End block - val = val(:); - lab = lab(:); - num = num(:); - num = cell2mat(num); - % the following is FieldTrip specific - if size(num,2)==6 - msi.grad.label = [msi.grad.label; lab(:)]; - % the numbers represent position and orientation of each magnetometer coil - msi.grad.pnt = [msi.grad.pnt; num(:,1:3)]; - msi.grad.ori = [msi.grad.ori; num(:,4:6)]; - else - error('unknown gradiometer design') - end - end - - % the key looks like 'MSI.fieldname.subfieldname' - fieldname = key(5:end); - - % remove spaces from the begin and end of the string - val = strtrim(val); - - % try to convert the value string into something more usefull - if ~iscell(val) - % the value can contain a variety of elements, only some of which are decoded here - if ~isempty(strfind(key, 'Index')) || ~isempty(strfind(key, 'Count')) || any(strcmp(key, numlist)) - % this contains a single number or a comma-separated list of numbers - val = str2num(val); - elseif ~isempty(strfind(key, 'Names')) || any(strcmp(key, strlist)) - % this contains a comma-separated list of strings - val = tokenize(val, ','); - else - tmp = str2num(val); - if ~isempty(tmp) - val = tmp; - end - end - end - - % assign this header element to the structure - msi = setsubfield(msi, fieldname, val); - -end % while ischar(line) - -fclose(fid); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION to remove spaces from the begin and end -% and to remove comments from the lines -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function line = cleanline(line) -if isempty(line) || (length(line)==1 && all(line==-1)) - return -end -comment = findstr(line, '//'); -if ~isempty(comment) - line(min(comment):end) = ' '; -end -line = strtrim(line); diff --git a/external/fieldtrip/private/read_ced_son.m b/external/fieldtrip/private/read_ced_son.m deleted file mode 100644 index 0916666..0000000 --- a/external/fieldtrip/private/read_ced_son.m +++ /dev/null @@ -1,318 +0,0 @@ -function [out] = read_ced_son(datafile,varargin); - -% READ_CED_SON -% -% [OUT] = read_ced_son(DATAFILE,VARARGIN); -% -% Reads a analog and event data from a CED SON file -% (SON files are created by Spike2 software). Currently, only -% analog channels and event data can be read. -% -% Optional parameter Default -% 'readevents' 'no' -% 'readdata' 'no' -% 'readtimestamps' 'no' -% 'begsample' -1 -% 'endsample' -1 -% 'channels' [] -% -% Please note that CED DAQ systems do a sequential ADC, thus -% channels do not share the same time axis: The timestamps of the -% analog channels differ on a subsample level. Use the 'readtimestamps' -% input parameter to get a matrix with time axes corresponding -% to the data channels. -% -% Use begsample and endsample parameters to specify the boundaries -% of the requested data chunk. Setting these parameters to -1 will -% return data from the start or until the end of the datafile, -% respectively. -% -% Specifying [1,2] for 'channels' will load the 1st and the 2nd -% analog channel, __regardless of the actual channel number__ -% If, for example channel 1,2,3 are event channels, 4 as an analog -% channel, 5 is an event channel, and 6 is and analog channel, -% specifying [1 2] for 'channels' will load analog channel 4 and 6. -% Specifying [] for channels will return all analog channels. -% -% Setting 'readtimestamps' to 'yes' will return a time vector for -% each analog channel. -% -% Depending on the input parameters, the function will return a structure -% with fields: -% 'header' Header information of the SON file -% 'event' All data from event channels are pooled -% and stored in this structure. -% 'data' Cell-array with analog data -% 'time' Cell-array with time vectors corresponding to 'data' -% -% Uses Neuroshare libraries to read Spike2 SON data -% (see: http://neuroshare.sourceforge.net) - -% Gijs van Elswijk - 2005 (v0.1) - -% $Log: read_ced_son.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.4 2008/11/14 07:36:24 roboos -% use strcmpi instead of strcmp(lower()) -% -% Revision 1.3 2006/12/04 13:56:02 roboos -% incorporated modifications by Gijs van Elswijk: -% evt.type will be set to event channel label (was always 'trigger') -% evt.value will be set to event value (was event channel label) -% Bug fix: Channel index of source and target channels for timestep sizes were incorrect (bug found by Vladimir Litvak) -% -% Revision 1.4 2006/12/04 11:25:08 gijsve -% evt.type will be set to event channel label (was always 'trigger') -% evt.value will be set to event value (was event channel label) -% -% Revision 1.3 2006/11/25 15:33:53 gijsve -% - Bug fix: Channel index of source and target channels for timestep sizes were incorrect (bug found by Vladimir Litvak) -% -% Revision 1.2 2006/09/13 11:00:32 roboos -% explicitely load the nsCedSon.dll plugin, converted from DOS to UNIX ascii -% -% Revision 1.1 2005/11/24 16:02:08 roboos -% new implementation for Fieldtrip, thanks to Gijs van Elswijk -% -% Revision 1.2 2005/11/24 14:02:20 gijsve -% Removed temporal realignment -% Added analog timestamps as output -% Updated help documentation -% -% Revision 1.1 2005/11/17 22:12:48 gijsve -% First version in CVS: Helper function to read Spike2 data into fieldtrip -% - -MODE = 'continuous'; % assume continuous now - -% process in put parameters -if ~isempty(varargin) pars=struct(varargin{:}); else pars=[]; end; -if ~isfield(pars,'readdata'), pars = setfield(pars,'readdata','no'); end; -if ~isfield(pars,'readevents'), pars = setfield(pars,'readevents','no'); end; -if ~isfield(pars,'readtimestamps'), pars = setfield(pars,'readtimestamps','no'); end; -if ~isfield(pars,'begsample'), pars = setfield(pars,'begsample',-1); end; -if ~isfield(pars,'endsample'), pars = setfield(pars,'endsample',-1); end; -if ~isfield(pars,'channels'), pars = setfield(pars,'channels',[]); end; - -% set all fields string values to lowercase -fields = fieldnames(pars); -for idx=1:length(fields) - if isstr(getfield(pars,fields{idx})), - pars=setfield(pars,fields{idx},lower(getfield(pars,fields{idx}))); - end; -end; - -% First, check if NeuroShare DLL can be loaded -if filetype(datafile, 'ced_son') - % TODO other DLLs for other binary formats could be supported here as well - ns_RESULT = ns_SetLibrary(which('nsCedSon.dll')); -end -[st,libinfo] = ns_GetLibraryInfo; -if st, - error(['Could not get NeuroShare library info, please use the NS_SETLIBRARY function.']); -else, - disp(['Loading file ' datafile ' using NeuroShare library v',... - num2str(libinfo.LibVersionMaj),'.',num2str(libinfo.LibVersionMin),' ...']); -end; - -% open file -[st,fhandle] = ns_OpenFile(datafile); -if st, - [st,mesg] = ns_GetLastErrorMsg; - error(mesg); -end; - -try, - % file header - [st,fheader] = ns_GetFileInfo(fhandle); - if st, - [st,mesg] = ns_GetLastErrorMsg; - ns_CloseFile(fhandle); - error(mesg); - end; - - % Build catalogue of entities - [st, entityinfo] = ns_GetEntityInfo(fhandle, [1:fheader.EntityCount]); - - % get the channel numbers of analogue and event channels - % Neuroshare entity types: - % Unknown entity 0 - % Event entity 1 - % Analog entity 2 - % Segment entity 3 - % Neural event entity 4 - eventlist = find([entityinfo.EntityType] == 1); - analoglist = find([entityinfo.EntityType] == 2); - - % How many of a particular entity do we have - n_event = length(eventlist); - n_analog = length(analoglist); - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % HEADER - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % Fieldtrip uses: - % hdr.Fs sampling frequency - % hdr.nChans number of channels - % hdr.nSamples number of samples per trial - % hdr.nSamplesPre number of pre-trigger samples in each trial - % hdr.nTrials number of trials - % hdr.label cell-array with labels of each channel - cnt = 0; - for channr = analoglist(:)' - cnt = cnt+1; - [st,einfo] = ns_GetEntityInfo(fhandle,channr); - [st,ainfo] = ns_GetAnalogInfo(fhandle,channr); - % Until now, I haven't found a way to check whether the SON files - % are recorded in continuous or triggered mode by using header - % information only. Therefore, mode is explicitly set to continuous now. - % When reading a segment of analog data however, the NeuroShare - % routines provide information about the continuity of the - % read segment. If a discontinuity is detected a warning will - % be given in the command window. - if strcmpi(MODE,'continuous') - out.header(cnt).label = einfo.EntityLabel; - out.header(cnt).nsamples = einfo.ItemCount; - out.header(cnt).index = cnt; - out.header(cnt).sonentityid = channr; % this is the actual channr in the SON file - out.header(cnt).ntrials = 1; - out.header(cnt).samplerate = ainfo.SampleRate; - out.header(cnt).units = ainfo.Units; - out.header(cnt).mode = 'continuous'; - elseif strcmpi(MODE,'triggered'), - warning(['Triggered channel mode not implemented yet']); - out = []; - return - else, - error(['Unknown channel mode for channel ',num2str(channr)]); - end; - end; - out.header = orderfields(out.header); - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % EVENTS - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % Fieldtrip uses: - % event.type = string - % event.sample = expressed in samples, first sample of file is 1 - % event.value = number or string - % event.offset = expressed in samples - % event.duration = expressed in samples - if strcmp(pars.readevents,'yes') - cnt = 0; - for channr = eventlist(:)' - [st,einfo] = ns_GetEntityInfo(fhandle,channr); - [st,evtime,evdata] = ns_GetEventData(fhandle,channr,[1:einfo.ItemCount]); - - for trignr = 1:einfo.ItemCount, - cnt = cnt+1; - out.events(cnt).type = einfo.EntityLabel; - out.events(cnt).timestamp = evtime(trignr); - % Convert timestamp to sample nr. First analog channel's - % sample numbers are used as the reference for all - % timestamps. - [st,tmp] = ns_GetIndexByTime(fhandle,analoglist(1),evtime(trignr),0); - out.events(cnt).sample = tmp; - if iscell(evdata(trignr)) - out.events(cnt).value = evdata{trignr}; % cell2str - else - out.events(cnt).value = evdata(trignr); - end; - out.events(cnt).offset = 0; - out.events(cnt).duration = 0; - end; - end; - out.events = orderfields(out.events); - end; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % DATA - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - if strcmp(pars.readdata,'yes') - - % if no channels specified default to all analog channels - if isempty(pars.channels), - pars.channels = analoglist; - else, % renumber requested channels to entityIDs - if length(pars.channels)>length(analoglist), - error(['Requested more analog channels than present in datafile']); - else, - pars.channels = analoglist(pars.channels); - end; - end; - - % use first analog channel as reference channel - targetchan = analoglist(1); - [st,einfo] = ns_GetEntityInfo(fhandle,targetchan); - - %if no begsample specified default to start of channel - if pars.begsample<0, begsample=1; else begsample=pars.begsample; end; - %if no endsample specified default to end of channel - if pars.endsample<0, endsample=einfo.ItemCount; else endsample=pars.endsample; end; - - % calculate number of samples needed (for all requested channels) - itemcount = endsample-begsample+1; - targetstep = out.header([out.header.sonentityid]==targetchan).samplerate; - [st,targetbegin] = ns_GetTimeByIndex(fhandle,targetchan,begsample); - - cnt = 0; - for channr = pars.channels(:)', - cnt = cnt+1; - - % Cut out the data of channels 1-N in the following way - % - % begtime itemcount - % analog 1 [x..|x..x..x..x..x..x..x..x..x..x..x|..] - % analog 2 [.x.|.x..x..x..x..x..x..x..x..x..x..x|.] - % analog N [..x|..x..x..x..x..x..x..x..x..x..x..x|] - % - % All channels will have the same number of samples, - % but timestamps of the channels are offset on subsample - % level, due to asynchronous sampling of the CED DAQ - % hardware. - - % return the sample nr occuring after and inclusive of begtime. - [st,begsample] = ns_GetIndexByTime(fhandle,channr,targetbegin,1); - % get the same number of samples as in the target channel - endsample = begsample + itemcount-1; - [st,contcount,chandata] = ns_GetAnalogData(fhandle,channr, begsample,itemcount); - if contcount~=itemcount, warning(['Discontinuity in data']); end; - - % make a time scale - [st,begtime] = ns_GetTimeByIndex(fhandle,channr,begsample); - [st,endtime] = ns_GetTimeByIndex(fhandle,channr,endsample); - sourcestep = out.header([out.header.sonentityid]==channr).samplerate; - - if sourcestep~=targetstep, warning(['Source and target channels have time steps of different size']); end; - chantime = [begtime:1/sourcestep:endtime]; - - out.data{cnt} = chandata(:)'; - if strcmp(pars.readtimestamps,'yes') out.time{cnt} = chantime(:)'; end; - end; - end; - - % close file - [st] = ns_CloseFile(fhandle); - if st, - [st,mesg] = ns_GetLastErrorMsg; - disp(mesg); - end; - -% use catch to close any opened files before terminating -catch, - % fclose(fid); - [st] = ns_CloseFile(fhandle); - if st, - [st,mesg] = ns_GetLastErrorMsg; - disp(mesg); - end; - error(lasterr); -end; - diff --git a/external/fieldtrip/private/read_ctf_ascii.m b/external/fieldtrip/private/read_ctf_ascii.m deleted file mode 100644 index 016b8f8..0000000 --- a/external/fieldtrip/private/read_ctf_ascii.m +++ /dev/null @@ -1,118 +0,0 @@ -function [file] = read_ctf_ascii(filename); - -% READ_CTF_ASCII reads general data from an CTF configuration file -% -% The file should be formatted like -% Group -% { -% item1 : value1a value1b value1c -% item2 : value2a value2b value2c -% item3 : value3a value3b value3c -% item4 : value4a value4b value4c -% } -% -% This fileformat structure is used in -% params.avg -% default.hdm -% multiSphere.hdm -% processing.cfg -% and maybe for other files as well. - -% Copyright (C) 2003, Robert Oostenveld -% -% $Log: read_ctf_ascii.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.10 2008/11/14 07:49:19 roboos -% use standard matlab strtrim function instead of deblank2 -% -% Revision 1.9 2006/08/29 11:08:41 roboos -% close file after reading from it -% -% Revision 1.8 2006/03/06 10:46:53 roboos -% fixed bug (again) in shortcirquited || -% -% Revision 1.7 2006/03/06 09:40:53 roboos -% changed a | into a || -% -% Revision 1.6 2006/02/24 15:43:43 roboos -% fixed bug in shortcirquited || which was not boolean on both sides -% -% Revision 1.5 2006/02/09 08:36:33 roboos -% changed single | into || since it is a boolean evaluation (thanks to Tom) -% -% Revision 1.4 2004/08/02 13:06:09 roboos -% fixed bug that occurred for hdm files based on markers: structs cannot have fields that have a name which consists of a single number, so in that case use the fieldname "item_1" etc. -% -% Revision 1.3 2004/06/28 07:32:28 roberto -% added warning off/on around text reading and conversion -% -% Revision 1.2 2003/04/17 12:38:08 roberto -% *** empty log message *** -% -% Revision 1.1 2003/03/24 12:30:42 roberto -% new implementation -% - -fid = fopen(filename, 'r'); -if fid==-1 - error(sprintf('could not open file %s', filename)); -end - -line = ''; -while ischar(line) - line = cleanline(fgetl(fid)); - if isempty(line) || (length(line)==1 && all(line==-1)) - continue - end - - % the line is not empty, which means that we have encountered a chunck of information - subline = cleanline(fgetl(fid)); % read the { - subline = cleanline(fgetl(fid)); % read the first item - while isempty(findstr(subline, '}')) - if ~isempty(subline) - [item, value] = strtok(subline, ':'); - value(1) = ' '; % remove the : - value = strtrim(value); - item = strtrim(item); - warning off - - % the item name should be a real string, otherwise I cannot put it into the structure - if strcmp(sprintf('%d', str2num(deblank(item))), deblank(item)) - % add something to the start of the string to distinguish it from a number - item = ['item_' item]; - end - - % the value can be either a number or a string, and is put into the structure accordingly - if isempty(str2num(value)) - % the value appears to be a string - eval(sprintf('file.%s.%s = [ ''%s'' ];', line, item, value)); - else - % the value appears to be a number or a list of numbers - eval(sprintf('file.%s.%s = [ %s ];', line, item, value)); - end - warning on - end - subline = cleanline(fgetl(fid)); % read the first item - end -end - -fclose(fid); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function line = cleanline(line) - if isempty(line) || (length(line)==1 && all(line==-1)) - return - end - comment = findstr(line, '//'); - if ~isempty(comment) - line(min(comment):end) = ' '; - end - line = strtrim(line); - diff --git a/external/fieldtrip/private/read_ctf_cls.m b/external/fieldtrip/private/read_ctf_cls.m deleted file mode 100644 index a4e5bfd..0000000 --- a/external/fieldtrip/private/read_ctf_cls.m +++ /dev/null @@ -1,74 +0,0 @@ -function [condNumbers,condLabels] = read_ctf_cls(fname) - -% READ_CTF_CLS reads the classification file from a CTF dataset - -% Copyright (C) 2003, Ole Jensen -% -% $Log: read_ctf_cls.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.2 2006/04/20 12:07:31 roboos -% fixed bug when a class had no trials associated to it, changed output format for condNumbers from cell-array with cells into a cell-array with numeric arrays -% -% Revision 1.1 2004/09/27 15:34:30 roboos -% copy from the readClassFile that Ole wrote -% added help comments and cleaned up white space -% no code changes -% - -condNumbers = []; -% condLabels = []; - -fid = fopen(fname,'r'); - -if fid == -1 - condNumbers = []; - condLabels = []; - return -end - -nCondition = 0; -readBad = 0; -readList = 0; -S2 = '*'; -S1 = '*'; -while ~isempty(S1) - S3 = S2; - S2 = S1; - S1 =fscanf(fid,'%s',1); - - if readList - if ~isempty(S1) & ~isempty(str2num(S1(2:end))) - k = k + 1; - condTmp = [condTmp 1+str2num(S1(2:end))]; - else - readList = 0; - end - condNumbers{nCondition} = condTmp; - end - - if strcmp(S2,'NAME:') - % New condition found! - % fprintf('%s\n',S1); - nCondition = nCondition+1; - condLabels(nCondition) = {S1} ; - end - - if strcmp(S1,'NUMBER') & strcmp(S2,'TRIAL') - if ~isempty(S1) - readList = 1; - k = 0; - condTmp = []; - else - readList = 0; - end - end - -end % ~isempty(S1) - diff --git a/external/fieldtrip/private/read_ctf_hdm.m b/external/fieldtrip/private/read_ctf_hdm.m deleted file mode 100644 index 58d705c..0000000 --- a/external/fieldtrip/private/read_ctf_hdm.m +++ /dev/null @@ -1,66 +0,0 @@ -function [vol] = read_ctf_hdm(filename); - -% READ_CTF_HDM reads the head volume conductor model from a *.hdm file -% -% vol = read_ctf_hdm(filename) - -% Copyright (C) 2003, Robert Oostenveld -% -% $Log: read_ctf_hdm.m,v $ -% Revision 1.2 2009/03/26 15:00:38 roboos -% remember all original details, required for 3rd gradient multisphere models -% -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.3 2006/02/09 08:37:23 roboos -% remove the fields SEARCH_RADIUS and HEADSHAPE_FILE regardless of where they are, do not assume that they are at location 1 and 2 (thanks to Tom) -% -% Revision 1.2 2004/06/28 07:32:55 roberto -% added units=cm for the volume model -% -% Revision 1.1 2003/03/24 12:30:42 roberto -% new implementation -% - -vol = []; -ascii = read_ctf_ascii(filename); - -% remember all original details -vol.orig = ascii; - -if isfield(ascii, 'MultiSphere_Data') - chans = fieldnames(ascii.MultiSphere_Data); - % remove the fields SEARCH_RADIUS and HEADSHAPE_FILE - chans = chans(~(strcmp(chans, 'SEARCH_RADIUS') | strcmp(chans, 'HEADSHAPE_FILE'))); - for i=1:length(chans) - tmp = getfield(ascii.MultiSphere_Data, chans{i}); - vol.label{i} = chans{i}; - vol.r(i) = tmp(4); - vol.o(i, :) = tmp(1:3); - end - vol.r = vol.r(:); % ensure column vector -elseif isfield(ascii, 'MEG_Sphere') - vol.r = ascii.MEG_Sphere.RADIUS; - vol.o(1) = ascii.MEG_Sphere.ORIGIN_X; - vol.o(2) = ascii.MEG_Sphere.ORIGIN_Y; - vol.o(3) = ascii.MEG_Sphere.ORIGIN_Z; -else - error('no headmodel information found'); -end - -% add the fiducials, these are in raw MRI coordinates -if isfield(ascii, 'Fid_Points') - vol.mri.nas = ascii.Fid_Points.NASION; - vol.mri.lpa = ascii.Fid_Points.LEFT_EAR; - vol.mri.rpa = ascii.Fid_Points.RIGHT_EAR; -end - -% add the units in which the volume conductor is defined -vol.unit = 'cm'; - diff --git a/external/fieldtrip/private/read_ctf_meg4.m b/external/fieldtrip/private/read_ctf_meg4.m deleted file mode 100644 index a2d6e2d..0000000 --- a/external/fieldtrip/private/read_ctf_meg4.m +++ /dev/null @@ -1,192 +0,0 @@ -function [meg] = read_ctf_meg4(fname, hdr, begsample, endsample, chanindx) - -% READ_CTF_MEG4 reads specified samples from a CTF continous datafile -% It neglects all trial boundaries as if the data was acquired in -% non-continous mode. -% -% Use as -% [meg] = read_ctf_meg4(filename, hdr, begsample, endsample, chanindx) -% where -% filename name of the datafile, including the .meg4 extension -% header with all data information (from read_ctf_meg4) -% begsample index of the first sample to read -% endsample index of the last sample to read -% chanindx index of channels to read (optional, default is all) -% -% See also READ_CTF_MEG4 - -% "VSM MedTech Ltd. authorizes the release into public domain under the -% GPL licence of the Matlab source code files "read_ctf_res4.m" and -% "read_ctf_meg4.m" by the authors of said files from the F.C. Donders -% Centre, Nijmegen, The Netherlands." - -% Author(s): Jim McKay November 1999 -% Last revision: Jim McKay -% Copyright (c) 1999-2000 CTF Systems Inc. All Rights Reserved. -% -% modifications Copyright (C) 2002, Ole Jensen -% modifications Copyright (C) 2003, Robert Oostenveld -% -% $Log: read_ctf_meg4.m,v $ -% Revision 1.2 2009/05/07 13:25:16 roboos -% added support for old 64-channel CTF files -% -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.16 2008/09/30 07:47:04 roboos -% replaced all occurences of setstr() with char(), because setstr is deprecated by Matlab -% -% Revision 1.15 2007/09/11 12:18:23 jansch -% new clean implementation to account for very big datasets > 4GB -% -% Revision 1.14 2005/10/04 15:52:09 roboos -% fixed bug that occured when data is split over more than two files (thanks to flodlan) -% -% Revision 1.13 2005/02/18 13:16:58 roboos -% VSM MedTech Ltd. authorised the release of this code in the public domain -% updated the copyrights, updated the help -% -% Revision 1.12 2004/06/21 19:33:08 roberto -% made 2GB warning dependent on global fb flag -% -% Revision 1.11 2003/07/23 15:02:27 roberto -% added check on valid input for read_ctf_meg4, other changes unknown -% -% Revision 1.10 2003/05/22 09:09:41 roberto -% fixed another bug for >2GB files when selected data in within one trial -% -% Revision 1.7 2003/05/21 13:52:29 roberto -% re-implemented support for >2GB files -% improved checking of input arguments -% fixed bug in chanindx indexing for raw data -% -% Revision 1.6 2003/05/19 15:18:50 roberto -% fixed bugs in memory-efficient reading of continuous data -% -% Revision 1.4 2003/04/17 12:37:41 roberto -% changed error for non-continuous files into warning -% -% Revision 1.3 2003/04/01 06:53:35 roberto -% added support for channel selection -% fixed bug with data allocation over multiple trials -% -% Revision 1.2 2003/03/27 08:30:54 roberto -% fixed bug in reading non-multiplexed trial data -% added error checking -% -% Revision 1.1 2003/03/26 13:34:05 roberto -% new implementation -% - -% use global flag for feedback -global fb -if isempty(fb) - fb = 0; -end - -nsmp = hdr.nSamples; -ntrl = hdr.nTrials; -nchn = hdr.nChans; - -if begsample<1, error('cannot read before the start of the data'); end -if endsample>nsmp*ntrl*nchn, error('cannot read beyond the end of the data'); end -if begsample>endsample, error('cannot read a negative number of samples'); end -if nargin<5, chanindx = 1:nchn; end -if isempty(chanindx), error('no channels were specified for reading CTF data'); end - -%open the .meg4 file -fid = fopen(fname,'r','ieee-be'); -if fid == -1, - error('could not open datafile'); -end - -%check whether it is a known format -CTFformat=char(fread(fid, 8, 'uint8'))'; -% This function was written for MEG41RS, but also seems to work for some other formats -if ~strcmp(CTFformat(1,1:7),'MEG41CP') && ~strcmp(CTFformat(1,1:7),'MEG4CPT') - warning('meg4 format (%s) is not supported for file %s, trying anyway...', CTFformat(1,1:7), fname); -end - -%determine size of .meg4 file -fseek(fid, 0, 'eof'); -nbytes = ftell(fid); - -%number of trials per 2GB file FIXME assumes constancy across the .meg4 files -ntrlfile = round((nbytes-8)/(4*nchn*nsmp)); -%ntrlfile = (nbytes-8)/(4*nchn*nsmp); -openfile = 0; - -%determine which trials have to be read -begtrial = ceil(begsample/nsmp); -endtrial = ceil(endsample/nsmp); -trials = begtrial:endtrial; - -%to ensure correct sample handling in the case of multiple trials -sumsmp = [(begtrial-1):(endtrial-1)]*nsmp; -rawbeg = 1; - -minchn = min(chanindx); %to ensure correct channel handling in the case of blockwise reading -maxchn = max(chanindx); -loopchn = length(trials)==1 || (maxchn-minchn+1)<=nchn; %decide whether to read in blockwise, or the specified samples per channel - -raw = zeros(endsample-begsample+1, length(chanindx)); %allocate memory -for trllop = 1:length(trials) - trlnr = trials(trllop); - filenr = floor(trlnr/(ntrlfile+0.1)); - - %ensure that the correct .meg4 file is open - if filenr~=openfile && filenr>0, - fclose(fid); - nextname = sprintf('%s.%d_meg4', fname(1:(end-5)), filenr); - if fb - fprintf('data goes beyond 2GB file boundary, continuing with %s\n', nextname); - end - fid = fopen(nextname,'r','ieee-be'); - fseek(fid, 0, 'eof'); - openfile = filenr; - end - - %this is relative to the current datafile - rawtrl = mod(trlnr-1, ntrlfile) + 1; - offset = 8 + 4*(rawtrl-1)*nsmp*nchn; - - %begin and endsamples expressed as samples with respect to the current trial - tmpbeg = max(begsample-sumsmp(trllop), 1); - tmpend = min(endsample-sumsmp(trllop), nsmp); - rawend = rawbeg+tmpend-tmpbeg; - - %either read per channel or read entire trialblock and postselect the channels - if loopchn, - for chnlop = 1:length(chanindx) - %this is relative to the current trial - chanoffset = 4*(chanindx(chnlop)-1)*nsmp; - sampoffset = 4*(tmpbeg-1); - fseek(fid, offset+chanoffset+sampoffset, 'bof'); - [tmp, count] = fread(fid,[tmpend-tmpbeg+1,1],'int32'); - raw(rawbeg:rawend, chnlop) = tmp; - end - else - %this is relative to the current trial - chanoffset = 4*(minchn-1)*nsmp; - fseek(fid, offset+chanoffset, 'bof'); - ntmpchn = maxchn - minchn + 1; - [tmp, count] = fread(fid,[nsmp,length(ntmpchn)],'int32'); - selchn = chanindx - minchn + 1; %relative to the first channel to be read - raw(rawbeg:rawend, :) = tmp(tmpbeg:tmpend, selchn); - end - rawbeg = rawend+1; -end -fclose(fid); - -% multiply the dimensionless values with the calibration value -gain = hdr.gainV(chanindx); % only for selected channels -meg = raw'; % transpose the raw data -for i=1:size(meg,1) - meg(i,:) = gain(i)*meg(i,:); -end diff --git a/external/fieldtrip/private/read_ctf_mri.m b/external/fieldtrip/private/read_ctf_mri.m deleted file mode 100644 index 5b3f1c0..0000000 --- a/external/fieldtrip/private/read_ctf_mri.m +++ /dev/null @@ -1,149 +0,0 @@ -function [mri, hdr] = read_ctf_mri(filename); - -% READ_CTF_MRI reads header and imnage data from CTF format MRI file -% -% [mri, hdr] = read_ctf_mri(filename) -% -% See also READ_CTF_MEG4, READ_CTF_RES4 - -% Copyright (C) 2003 Robert Oostenveld -% -% $Log: read_ctf_mri.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry -% -% Revision 1.4 2008/09/30 07:47:04 roboos -% replaced all occurences of setstr() with char(), because setstr is deprecated by Matlab -% -% Revision 1.3 2005/08/26 13:49:03 roboos -% changed warp3d into warp_apply -% -% Revision 1.2 2003/07/23 15:02:27 roberto -% added check on valid input for read_ctf_meg4, other changes unknown -% -% Revision 1.1 2003/06/10 08:14:54 roberto -% new implementation -% - -fid = fopen(filename,'rb', 'ieee-be'); - -if fid<=0 - error(sprintf('could not open MRI file: %s\n', filename)); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% READ THE IMAGE HEADER -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -warning off -% general header information -hdr.identifierString = char(fread(fid,32,'char'))'; % CTF_MRI_FORMAT VER 2.2 -hdr.imageSize = fread(fid,1,'int16'); % always = 256 -hdr.dataSize = fread(fid,1,'int16'); % 1 or 2(bytes) -hdr.clippingRange = fread(fid,1,'int16'); % max.integer value of data -hdr.imageOrientation = fread(fid,1,'int16'); % eg., 0 = left on left, 1 = left on right -hdr.mmPerPixel_sagittal = fread(fid,1,'float'); % voxel dimensions in mm -hdr.mmPerPixel_coronal = fread(fid,1,'float'); % voxel dimensions in mm -hdr.mmPerPixel_axial = fread(fid,1,'float'); % voxel dimensions in mm - -% HeadModel_Info specific header items -hdr.HeadModel.Nasion_Sag = fread(fid,1,'int16'); % fid.point coordinate(in voxels) for nasion - sagittal -hdr.HeadModel.Nasion_Cor = fread(fid,1,'int16'); % nasion - coronal -hdr.HeadModel.Nasion_Axi = fread(fid,1,'int16'); % nasion - axial -hdr.HeadModel.LeftEar_Sag = fread(fid,1,'int16'); % left ear - sagittal -hdr.HeadModel.LeftEar_Cor = fread(fid,1,'int16'); % left ear - coronal -hdr.HeadModel.LeftEar_Axi = fread(fid,1,'int16'); % left ear - axial -hdr.HeadModel.RightEar_Sag = fread(fid,1,'int16'); % right ear - sagittal -hdr.HeadModel.RightEar_Cor = fread(fid,1,'int16'); % right ear - coronal -hdr.HeadModel.RightEar_Axi = fread(fid,1,'int16'); % right ear - axial -fread(fid,2,'char'); % padding to 4 byte boundary -hdr.HeadModel.defaultSphereX = fread(fid,1,'float'); % sphere origin x coordinate(in mm) -hdr.HeadModel.defaultSphereY = fread(fid,1,'float'); % sphere origin y coordinate(in mm) -hdr.HeadModel.defaultSphereZ = fread(fid,1,'float'); % sphere origin z coordinate(in mm) -hdr.HeadModel.defaultSphereRadius = fread(fid,1,'float'); % default sphere radius(in mm) - -% Image_Info specific header items -hdr.Image.modality = fread(fid,1,'int16'); % 0 = MRI, 1 = CT, 2 = PET, 3 = SPECT, 4 = OTHER -hdr.Image.manufacturerName = char(fread(fid,64,'char'))'; -hdr.Image.instituteName = char(fread(fid,64,'char'))'; -hdr.Image.patientID = char(fread(fid,32,'char'))'; -hdr.Image.dateAndTime = char(fread(fid,32,'char'))'; -hdr.Image.scanType = char(fread(fid,32,'char'))'; -hdr.Image.contrastAgent = char(fread(fid,32,'char'))'; -hdr.Image.imagedNucleus = char(fread(fid,32,'char'))'; -fread(fid,2,'char'); % padding to 4 byte boundary -hdr.Image.Frequency = fread(fid,1,'float'); -hdr.Image.FieldStrength = fread(fid,1,'float'); -hdr.Image.EchoTime = fread(fid,1,'float'); -hdr.Image.RepetitionTime = fread(fid,1,'float'); -hdr.Image.InversionTime = fread(fid,1,'float'); -hdr.Image.FlipAngle = fread(fid,1,'float'); -hdr.Image.NoExcitations = fread(fid,1,'int16'); -hdr.Image.NoAcquisitions = fread(fid,1,'int16'); -hdr.Image.commentString = char(fread(fid,256,'char'))'; -hdr.Image.forFutureUse = char(fread(fid,64,'char'))'; - -% continuation general header -hdr.headOrigin_sagittal = fread(fid,1,'float'); % voxel location of head origin -hdr.headOrigin_coronal = fread(fid,1,'float'); % voxel location of head origin -hdr.headOrigin_axial = fread(fid,1,'float'); % voxel location of head origin -% euler angles to align MR to head coordinate system(angles in degrees !) -hdr.rotate_coronal = fread(fid,1,'float'); % 1. rotate in coronal plane by this angle -hdr.rotate_sagittal = fread(fid,1,'float'); % 2. rotate in sagittal plane by this angle -hdr.rotate_axial = fread(fid,1,'float'); % 3. rotate in axial plane by this angle -hdr.orthogonalFlag = fread(fid,1,'int16'); % if set then image is orthogonal -hdr.interpolatedFlag = fread(fid,1,'int16'); % if set than image was interpolated -hdr.originalSliceThickness = fread(fid,1,'float'); % original spacing between slices before interpolation -transformMatrix = fread(fid,[4 4],'float')'; % transformation matrix head->MRI[column][row] -fread(fid,204,'char'); % unused, padding to 1028 bytes -warning on - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% READ THE IMAGE DATA -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -if hdr.dataSize==1 - mri = uint8(fread(fid, 256*256*256, 'uint8')); -elseif hdr.dataSize==2 - mri = uint16(fread(fid, 256*256*256, 'uint16')); -else - error('unknown datasize in CTF mri file'); -end -mri = reshape(mri, [256 256 256]); -fclose(fid); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% DO POST-PROCESSING -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% reorient the image data to obtain corresponding image data and transformation matrix -mri = permute(mri, [3 1 2]); % this was determined by trial and error - -% reorient the image data and the transformation matrix along the left-right direction -% remember that the fiducials in voxel coordinates also have to be flipped (see down) -mri = flipdim(mri, 1); -flip = [-1 0 0 256 - 0 1 0 0 - 0 0 1 0 - 0 0 0 1 ]; -transformMatrix = flip*transformMatrix; - -% re-compute the homogeneous transformation matrices (apply voxel scaling) -scale = eye(4); -scale(1,1) = hdr.mmPerPixel_sagittal; -scale(2,2) = hdr.mmPerPixel_coronal; -scale(3,3) = hdr.mmPerPixel_axial; -hdr.transformHead2MRI = transformMatrix*inv(scale); -hdr.transformMRI2Head = scale*inv(transformMatrix); - -% determint location of fiducials in MRI voxel coordinates -% flip the fiducials in voxel coordinates to correspond to the previous flip along left-right -hdr.fiducial.mri.nas = [256 - hdr.HeadModel.Nasion_Sag hdr.HeadModel.Nasion_Cor hdr.HeadModel.Nasion_Axi]; -hdr.fiducial.mri.lpa = [256 - hdr.HeadModel.LeftEar_Sag hdr.HeadModel.LeftEar_Cor hdr.HeadModel.LeftEar_Axi]; -hdr.fiducial.mri.rpa = [256 - hdr.HeadModel.RightEar_Sag hdr.HeadModel.RightEar_Cor hdr.HeadModel.RightEar_Axi]; - -% compute location of fiducials in MRI and HEAD coordinates -hdr.fiducial.head.nas = warp_apply(hdr.transformMRI2Head, hdr.fiducial.mri.nas, 'homogenous'); -hdr.fiducial.head.lpa = warp_apply(hdr.transformMRI2Head, hdr.fiducial.mri.lpa, 'homogenous'); -hdr.fiducial.head.rpa = warp_apply(hdr.transformMRI2Head, hdr.fiducial.mri.rpa, 'homogenous'); - diff --git a/external/fieldtrip/private/read_ctf_mri4.m b/external/fieldtrip/private/read_ctf_mri4.m deleted file mode 100644 index ad42567..0000000 --- a/external/fieldtrip/private/read_ctf_mri4.m +++ /dev/null @@ -1,252 +0,0 @@ -function [mri, hdr, cpersist] = read_ctf_mri4(filename); - -% READ_CTF_MRI reads header and imnage data from CTF format MRI file -% -% [mri, hdr] = read_ctf_mri(filename) -% -% See also READ_CTF_MEG4, READ_CTF_RES4 - -% Copyright (C) 2008 Ivar Clemens -% -% $Log: read_ctf_mri4.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry -% -% Revision 1.1 2008/11/28 10:25:05 roboos -% new implementation by Ivar, based on the version 2 reader -% -% Revision 1.1 2008/11/21 13:00:42 ivacle -% Adapted read_ctf_mri to read the 'new' CTF MRI format -% - -fid = fopen(filename,'rb', 'ieee-be'); - -if fid<=0 - error(sprintf('could not open MRI file: %s\n', filename)); -end - -[cpersist] = read_cpersist(fid); - -warning off - -% general header information -hdr.identifierString = get_value(cpersist, '_CTFMRI_VERSION'); % CTF_MRI_FORMAT VER 4.1 -hdr.imageSize = get_value(cpersist, '_CTFMRI_SIZE'); % 256 -hdr.dataSize = get_value(cpersist, '_CTFMRI_DATASIZE'); % 1 or 2(bytes) -hdr.orthogonalFlag = get_value(cpersist, '_CTFMRI_ORTHOGONALFLAG'); % if set then image is orthogonal -hdr.interpolatedFlag = get_value(cpersist, '_CTFMRI_INTERPOLATEDFLAG'); % if set than image was interpolated -hdr.comment = get_value(cpersist, '_CTFMRI_COMMENT'); - -hdr.Image.modality = get_value(cpersist, '_SERIES_MODALITY'); -hdr.Image.manufacturerName = get_value(cpersist, '_EQUIP_MANUFACTURER'); -hdr.Image.instituteName = get_value(cpersist, '_EQUIP_INSTITUTION'); -hdr.Image.imagedNucleus = get_value(cpersist, '_MRIMAGE_IMAGEDNUCLEUS'); -hdr.Image.FieldStrength = get_value(cpersist, '_MRIMAGE_FIELDSTRENGTH'); -hdr.Image.EchoTime = get_value(cpersist, '_MRIMAGE_ECHOTIME'); -hdr.Image.RepetitionTime = get_value(cpersist, '_MRIMAGE_REPETITIONTIME'); -hdr.Image.InversionTime = get_value(cpersist, '_MRIMAGE_INVERSIONTIME'); -hdr.Image.FlipAngle = get_value(cpersist, '_MRIMAGE_FLIPANGLE'); - -% euler angles to align MR to head coordinate system(angles in degrees !) -rotation = split_nvalue(get_value(cpersist, '_CTFMRI_ROTATE')); -hdr.rotate_coronal = rotation(1); -hdr.rotate_sagittal = rotation(2); -hdr.rotate_axial = rotation(3); - -transformMatrix = split_nvalue(get_value(cpersist, '_CTFMRI_TRANSFORMMATRIX')); -transformMatrix = reshape(transformMatrix, 4, 4)'; - -mmPerPixel = split_nvalue(get_value(cpersist, '_CTFMRI_MMPERPIXEL')); -hdr.mmPerPixel_sagittal = mmPerPixel(1); -hdr.mmPerPixel_coronal = mmPerPixel(2); -hdr.mmPerPixel_axial = mmPerPixel(3); - -% HeadModel_Info specific header items -hmNasion = split_nvalue(get_value(cpersist, '_HDM_NASION')); -hdr.HeadModel.Nasion_Sag = hmNasion(1); -hdr.HeadModel.Nasion_Cor = hmNasion(2); -hdr.HeadModel.Nasion_Axi = hmNasion(3); - -hmLeftEar = split_nvalue(get_value(cpersist, '_HDM_LEFTEAR')); -hdr.HeadModel.LeftEar_Sag = hmLeftEar(1); -hdr.HeadModel.LeftEar_Cor = hmLeftEar(2); -hdr.HeadModel.LeftEar_Axi = hmLeftEar(3); - -hmRightEar = split_nvalue(get_value(cpersist, '_HDM_RIGHTEAR')); -hdr.HeadModel.RightEar_Sag = hmRightEar(1); -hdr.HeadModel.RightEar_Cor = hmRightEar(2); -hdr.HeadModel.RightEar_Axi = hmRightEar(3); - -hmSphere = split_nvalue(get_value(cpersist, '_HDM_DEFAULTSPHERE')); -hdr.HeadModel.defaultSphereX = hmSphere(1); -hdr.HeadModel.defaultSphereY = hmSphere(2); -hdr.HeadModel.defaultSphereZ = hmSphere(3); -hdr.HeadModel.defaultSphereRadius = hmSphere(4); - -hmOrigin = split_nvalue(get_value(cpersist, '_HDM_HEADORIGIN')); -hdr.headOrigin_sagittal = hmOrigin(1); -hdr.headOrigin_coronal = hmOrigin(2); -hdr.headOrigin_axial = hmOrigin(3); - -%fread(fid,204,'char'); % unused, padding to 1028 bytes -warning on - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% READ THE IMAGE DATA -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -mri = zeros(256, 256, 256); - -for slice = 1:256 - name = sprintf('_CTFMRI_SLICE_DATA#%.5d', slice); - offset = get_value(cpersist, name); - - fseek(fid, offset, 'bof'); - - if(hdr.dataSize == 1) - slicedata = uint8(fread(fid, [256 256], 'uint8')); - elseif(hdr.dataSize == 2) - slicedata = uint16(fread(fid, [256 256], 'uint16')); - else - error('Unknown datasize in CTF MRI file'); - end; - - mri(:, :, slice) = slicedata; -end; - -%mri = reshape(mri, [256 256 256]); -fclose(fid); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% DO POST-PROCESSING -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% reorient the image data to obtain corresponding image data and transformation matrix -mri = permute(mri, [3 1 2]); % this was determined by trial and error - -% reorient the image data and the transformation matrix along the left-right direction -% remember that the fiducials in voxel coordinates also have to be flipped (see down) -mri = flipdim(mri, 1); -flip = [-1 0 0 256 - 0 1 0 0 - 0 0 1 0 - 0 0 0 1 ]; -transformMatrix = flip*transformMatrix; - -% re-compute the homogeneous transformation matrices (apply voxel scaling) -scale = eye(4); -scale(1,1) = hdr.mmPerPixel_sagittal; -scale(2,2) = hdr.mmPerPixel_coronal; -scale(3,3) = hdr.mmPerPixel_axial; -hdr.transformHead2MRI = transformMatrix*inv(scale); -hdr.transformMRI2Head = scale*inv(transformMatrix); - -% determint location of fiducials in MRI voxel coordinates -% flip the fiducials in voxel coordinates to correspond to the previous flip along left-right -hdr.fiducial.mri.nas = [256 - hdr.HeadModel.Nasion_Sag hdr.HeadModel.Nasion_Cor hdr.HeadModel.Nasion_Axi]; -hdr.fiducial.mri.lpa = [256 - hdr.HeadModel.LeftEar_Sag hdr.HeadModel.LeftEar_Cor hdr.HeadModel.LeftEar_Axi]; -hdr.fiducial.mri.rpa = [256 - hdr.HeadModel.RightEar_Sag hdr.HeadModel.RightEar_Cor hdr.HeadModel.RightEar_Axi]; - -% compute location of fiducials in MRI and HEAD coordinates -hdr.fiducial.head.nas = warp_apply(hdr.transformMRI2Head, hdr.fiducial.mri.nas, 'homogenous'); -hdr.fiducial.head.lpa = warp_apply(hdr.transformMRI2Head, hdr.fiducial.mri.lpa, 'homogenous'); -hdr.fiducial.head.rpa = warp_apply(hdr.transformMRI2Head, hdr.fiducial.mri.rpa, 'homogenous'); - -% -% Reads a series of delimited numbers from a string -% -% @param input string Delimited string to process -% @param delim string The delimiter (default: \\) -% -% @return values matrix Array containing the numbers found -% - function [values] = split_nvalue(input, delim) - if(nargin < 2), delim = '\\'; end; - - remain = input; - values = []; - - while(numel(remain > 0)) - [value, remain] = strtok(remain, delim); - values(end + 1) = str2num(value); - end; - end - -% -% Reads a value from the CPersist structure -% -% @param cpersist struct-array The CPersist structure -% @param key string The name of the parameter -% -% @return value mixed The value of the named parameter -% - function [value] = get_value(cpersist, key) - idx = find(strcmp({cpersist.key}, key)); - - if(numel(idx) < 1), error('Specified key does not exist.'); end; - if(numel(idx) > 1), error('Specified key is not unique.'); end; - - value = cpersist(idx).value; - end - -% -% Processes the CTF CPersist structure into a struct-array -% -% @param fid numeric File handle from which to read the CPersist structure -% @return cpersist struct-array -% - function [cpersist] = read_cpersist(fid) - magic = char(fread(fid, 4, 'char'))'; - - if(~strcmp(magic, 'WS1_')), error('Invalid CPersist header'); end; - - cpersist = struct('key', {}, 'value', {}); - - while(~feof(fid)) - % Read label - lsize = fread(fid, 1, 'int32'); - ltext = char(fread(fid, lsize, 'char'))'; - - % Last label in file is always EndOfParameters - if(strcmp(ltext, 'EndOfParameters')), return; end; - - % Read value - vtype = fread(fid, 1, 'int32'); - value = read_cpersist_value(fid, vtype); - - cpersist(end + 1).key = ltext; - cpersist(end).value = value; - end - end - -% -% Reads a single value of type (vtype) from fid -% -% @param fid numeric The file to read the value from -% @param vtype numeric The type of value to read -% -% @return value mixed The read value -% - function [value] = read_cpersist_value(fid, vtype) - switch vtype - case 3 - vsize = fread(fid, 1, 'int32'); - value = ftell(fid); - fseek(fid, vsize, 'cof'); - case 4 - value = fread(fid, 1, 'double'); - case 5 - value = fread(fid, 1, 'int32'); - case 6 - value = fread(fid, 1, 'int16'); - case 10 - vsize = fread(fid, 1, 'int32'); - value = char(fread(fid, vsize, 'char'))'; - otherwise - error(['Unsupported valuetype (' num2str(vtype) ') found in CPersist object']); - return - end - end - -end - diff --git a/external/fieldtrip/private/read_ctf_res4.m b/external/fieldtrip/private/read_ctf_res4.m deleted file mode 100644 index de4f07c..0000000 --- a/external/fieldtrip/private/read_ctf_res4.m +++ /dev/null @@ -1,252 +0,0 @@ -function [hdr] = read_ctf_res4(fname) - -% READ_CTF_RES4 reads the header in RES4 format from a CTF dataset -% -% Use as -% [hdr] = read_ctf_res4(filename) -% -% See also READ_CTF_MEG4 - -% "VSM MedTech Ltd. authorizes the release into public domain under the -% GPL licence of the Matlab source code files "read_ctf_res4.m" and -% "read_ctf_meg4.m" by the authors of said files from the F.C. Donders -% Centre, Nijmegen, The Netherlands." - -% Author(s): Jim McKay November 1999 -% Last revision: Jim McKay -% Copyright (c) 1999-2000 CTF Systems Inc. All Rights Reserved. -% -% modifications Copyright (C) 2002, Ole Jensen -% modifications Copyright (C) 2003, Robert Oostenveld -% -% $Log: read_ctf_res4.m,v $ -% Revision 1.2 2009/05/07 13:25:16 roboos -% added support for old 64-channel CTF files -% -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.17 2008/09/30 07:47:04 roboos -% replaced all occurences of setstr() with char(), because setstr is deprecated by Matlab -% -% Revision 1.16 2008/07/24 08:51:43 roboos -% added the function declaration to the top, which was accidentaly removed by the previous commit -% -% Revision 1.15 2008/07/24 07:22:49 roboos -% replaced fread..char with uint8, solves problem with 16 bit wide characters (thanks to Erick Ortiz) -% -% Revision 1.14 2007/03/07 08:58:46 roboos -% Do not determine the MEG, REF and EEG channels based on the first character of the channel label, removed rowMEG etc from the header. The relevant information is contained in hdr.sensType. -% -% Revision 1.13 2006/03/06 09:41:23 roboos -% changed some |s into ||s -% -% Revision 1.12 2005/07/28 15:12:27 roboos -% fixed bug in hdr.timeVec (thanks to Sanja Kovacevic) -% -% Revision 1.11 2005/05/26 09:58:08 roboos -% removed the construction of grad, that is now done in a separate fieldtrip function (ctf2grad) -% -% Revision 1.10 2005/05/24 07:34:37 roboos -% added sensType to the output header -% -% Revision 1.9 2005/05/23 11:20:17 roboos -% fixed bug for run description which is longer than 256 characters, improved reading of filter information (thanks to Durk Talsma) -% -% Revision 1.8 2005/04/27 06:18:21 roboos -% added support for MEG42RS format, which seems to work (only tested on a single dataset from MIND Institute in Albuquerque, NM, USA) -% -% Revision 1.7 2005/02/18 13:16:58 roboos -% VSM MedTech Ltd. authorised the release of this code in the public domain -% updated the copyrights, updated the help -% -% Revision 1.6 2004/07/02 11:43:32 roboos -% typographic change in comment -% -% Revision 1.5 2004/06/28 07:34:41 roberto -% added some extra low-level output fields to header, added cm units -% -% Revision 1.4 2003/04/01 07:51:53 roberto -% fixed bug in gradiometer channel labels -% -% Revision 1.3 2003/03/28 17:27:27 roberto -% renamed output gradiometer from gradHC to grad -% -% Revision 1.2 2003/03/24 12:34:33 roberto -% minor changes -% -% Revision 1.1 2003/03/13 14:27:09 roberto -% separated read_ctf_ds into res4-header part and data part -% restructured the res4 part, using (incorrect) CTF documentation -% - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% read header information -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -fid = fopen(fname,'r','ieee-be'); - -% Check if header file exist -if fid == -1 - errMsg = strcat('Could not open header file:',fname); - error(errMsg); -end - -% First 8 bytes contain filetype, check is fileformat is correct. -% This function was written for MEG41RS, but also seems to work for some other formats -CTFformat=char(fread(fid,8,'uint8'))'; -if ~strcmp(CTFformat(1,1:7),'MEG41RS') && ~strcmp(CTFformat(1,1:7),'MEG42RS') && ~strcmp(CTFformat(1,1:7),'MEG3RES') - warning('res4 format (%s) is not supported for file %s, trying anyway...', CTFformat(1,1:7), fname); -end - -% Read the initial parameters -appName = char(fread(fid,256,'uint8'))' ; -dataOrigin = char(fread(fid,256,'uint8'))' ; -dataDescrip = char(fread(fid,256,'uint8'))' ; -no_trial_avgd = fread(fid,1,'int16') ; -data_time = char(fread(fid,255,'uint8'))'; -data_date = char(fread(fid,255,'uint8'))'; - -fseek(fid,1288,'bof'); -% Read the general recording parameters -no_samples = fread(fid,1,'int32'); -no_channels = fread(fid,1,'int16'); -fseek(fid,2,'cof'); % hole of 2 bytes due to improper alignment -sample_rate = fread(fid,1,'double'); -epoch = fread(fid,1,'double'); -no_trials = fread(fid,1,'int16'); -fseek(fid,2,'cof'); % hole of 2 bytes due to improper alignment -preTrigpts=fread(fid,1,'int32'); - -fseek(fid,1360,'bof'); -% read in the meg4Filesetup structure -run_name = char(fread(fid,32,'uint8')'); -run_title = char(fread(fid,256,'uint8')'); -instruments = char(fread(fid,32,'uint8')'); -coll_desc = char(fread(fid,32,'uint8')'); -subj_id = char(fread(fid,32,'uint8')'); -operator = char(fread(fid,32,'uint8')') ; -sensFilename = char(fread(fid,60,'uint8')') ; - -% not nececssary to seek, the file pointer is already at the desired location -% fseek(fid,1836,'bof'); - -% Read in the run description length -rd_len=fread(fid,1,'uint32'); -% Go to the run description and read it in -fseek(fid,1844,'bof'); -run_desc=char(fread(fid,rd_len,'uint8')'); - -% read in the filter information -num_filt=fread(fid,1,'uint16'); -for fi=0:(num_filt-1), - %filt_info=fread(fid,18,'uint8'); - filt_freq =fread(fid,1, 'double'); - filt_class=fread(fid,1, 'uint32'); - filt_type =fread(fid,1, 'uint32'); - num_fparm=fread(fid, 1, 'uint16'); - %num_fparm=filt_info(18); - if num_fparm ~= 0, - filt_parm=fread(fid,8*num_fparm,'uint8'); - end % if -end % for fi - -% Read in the channel names -for i=1:no_channels, - temp=fread(fid,32,'uint8')'; - temp(find(temp<32 )) = ' '; % remove non-printable characters - temp(find(temp>126)) = ' '; % remove non-printable characters - endstr = findstr(temp, '-'); temp(endstr:end) = ' '; % cut off at '-' - endstr = findstr(temp, ' '); temp(endstr:end) = ' '; % cut off at ' ' - chan_name(i,:) = char(temp); % as char array - chan_label{i} = deblank(char(temp)); % as cell array -end %for - -% pre-allocate some memory space -sensGain = zeros([no_channels,1]); -qGain = zeros([no_channels,1]); -ioGain = zeros([no_channels,1]); -sensType = zeros([no_channels,1]); - -% Read in the sensor information -fp = ftell(fid); -for chan=1:no_channels, - fread(fid,1,'uint8'); % Read and ignore 1 byte from enum - sensType(chan)=fread(fid,1,'uint8'); % Read sensor type - fread(fid,2,'uint8'); % Read and ignore originalRunNum - fread(fid,4,'uint8'); % Read and ignore coilShape - sensGain(chan)=fread(fid,1,'double'); % Read sensor gain in Phi0/Tesla - qGain(chan)=fread(fid,1,'double'); % Read qxx gain (usually 2^20 for Q20) - ioGain(chan)=fread(fid,1,'double'); % Read i/o gain of special sensors (usually 1.0) - ioOffset(chan)=fread(fid,1,'double'); - numCoils(chan)=fread(fid,1,'int16'); - grad_order_no(chan)=fread(fid,1,'int16'); - fread(fid,4,'uint8'); - - % read the coil positions and orientations - for i=1:8 - Chan(chan).coil(i).pos = fread(fid,3,'double')'; - fread(fid,1,'double'); - Chan(chan).coil(i).ori = fread(fid,3,'double')'; - fread(fid,3,'double'); - end - - % read the coil positions and orientations in head coordinates(?) - for i=1:8 - Chan(chan).coilHC(i).pos = fread(fid,3,'double')'; - fread(fid,1,'double'); - Chan(chan).coilHC(i).ori = fread(fid,3,'double')'; - fread(fid,3,'double'); - end - - % jump to the next sensor info record - fseek(fid, fp+chan*1328, 'bof'); -end % for chan - -% close the header file -fclose(fid); - -% according to Tom Holroyd, the sensor types are -% -% meg channels are 5, refmag 0, refgrad 1, adcs 18. -% UPPT001 is 11 -% UTRG001 is 11 -% SCLK01 is 17 -% STIM is 11 -% SCLK01 is 17 -% EEG057 is 9 -% ADC06 is 18 -% ADC07 is 18 -% ADC16 is 18 -% V0 is 15 - -% assign all the variables that should be outputted as header information -hdr.Fs = sample_rate; -hdr.nChans = no_channels; -hdr.nSamples = no_samples; -hdr.nSamplesPre = preTrigpts; -hdr.timeVec = (1:no_samples)/sample_rate - preTrigpts/sample_rate - 1/sample_rate; -hdr.nTrials = no_trials; -hdr.gainV = ioGain./(qGain.*sensGain); -hdr.ioGain = ioGain; -hdr.qGain = qGain; -hdr.sensGain = sensGain; -hdr.sensType = sensType; - -hdr.label = chan_label(:); -hdr.nameALL = chan_name; -hdr.Chan = Chan; -% hdr.rowMEG = rowMEG; -% hdr.rowEEG = rowEEG; -% hdr.rowTRIG = rowTRIG; -% hdr.rowREF = rowREF; -% hdr.nameEEG = []; -% hdr.nameMEG = []; -% hdr.nameEOG = []; -% hdr.trigV = []; -% hdr.SwapData = []; diff --git a/external/fieldtrip/private/read_ctf_shape.m b/external/fieldtrip/private/read_ctf_shape.m deleted file mode 100644 index cf015c6..0000000 --- a/external/fieldtrip/private/read_ctf_shape.m +++ /dev/null @@ -1,39 +0,0 @@ -function [shape] = read_ctf_shape(filename); - -% READ_CTF_SHAPE reads headshape points and header information -% from a CTF *.shape teh accompanying *.shape_info file. -% -% Use as -% [shape] = read_ctf_shape(filename) -% where filename should have the .shape extension - -% Copyright (C) 2003, Robert Oostenveld -% -% $Log: read_ctf_shape.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.2 2008/11/12 16:59:51 roboos -% open explicitely as text using fopen 'rt' -% -% Revision 1.1 2003/10/08 15:28:03 roberto -% *** empty log message *** -% - -shape = read_ctf_ascii([filename '_info']); - -if ~strcmp(shape.MRI_Info.COORDINATES, 'HEAD') - warning('points on head shape are NOT in headcoordinates') -end - -fid = fopen(filename, 'rt'); -num = fscanf(fid, '%d', 1); -shape.pnt = fscanf(fid, '%f', inf); -shape.pnt = reshape(shape.pnt, [3 num])'; -fclose(fid); - diff --git a/external/fieldtrip/private/read_ctf_trigger.m b/external/fieldtrip/private/read_ctf_trigger.m deleted file mode 100644 index f3925e2..0000000 --- a/external/fieldtrip/private/read_ctf_trigger.m +++ /dev/null @@ -1,105 +0,0 @@ -function [backpanel, frontpanel] = read_ctf_trigger(dataset) - -% READ_CTF_TRIGGER reads the STIM channel from a dataset and detects -% the trigger moments and values -% -% [backpanel, frontpanel] = read_ctf_trigger(dataset) -% -% This returns all samples of the STIM channel, converted to backpanel -% and frontpanel trigger values. Triggers are placed at the rising flank -% of the STIM channel. -% -% Triggers should be at least 9 samples long (for 1200Hz samplerate) and -% should not overlap each other. -% -% See also READ_CTF_MEG4, READ_CTF_RES4 - -% Copyright (C) 2003, Robert Oostenveld -% -% $Log: read_ctf_trigger.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.8 2006/02/06 09:02:35 roboos -% added support for triggers in UPPT001, USPT001, UTRG001 (thanks to Tom) -% -% Revision 1.7 2004/03/12 11:21:19 roberto -% The function outputs backpanel and frontpanel seperately. However -% it performs the upflank/kernel-convolution-correction of the -% trigger-channel on the the full 32-bit data. Usually the frontpanel -% is used to record responses while the backpanel is used for recording -% stimulus-trigger. While the timecourse of backpanel-triggers can -% be fully controlled the temporal overlap of these triggers with -% subject-responses can not. Therefore I think read_ctf_trigger should -% do the correction on the splitted data as done in the attached -% version of the function. This version works as before for nonoverlapping -% cases but can also handle backpanel-frontpanel overlap. -% -% Revision 1.6 2004/02/18 13:55:39 roberto -% fixed most significant bit, which was messed up by reading the data as signed int -% -% Revision 1.5 2004/02/12 09:55:35 roberto -% fixed bug, length of trigger was trigshift samples too short -% -% Revision 1.4 2003/10/14 12:37:17 roberto -% made teh trigshift adaptive to sampling frequency -% -% Revision 1.3 2003/09/12 09:27:11 roberto -% added comment to help about how triggers are supposed to behave -% -% Revision 1.2 2003/05/21 10:59:52 roberto -% fixed bugs in front/backpanel -% -% Revision 1.1 2003/05/19 14:40:32 roberto -% new implementation, replaces inline code in framework/preprocessing -% - -[path, file, ext] = fileparts(dataset); -datafile = fullfile(dataset, [file '.meg4']); -headerfile = fullfile(dataset, [file '.res4']); - -% read the header from the raw CTF data -hdr = read_ctf_res4(headerfile); - -% number of samples to shift the assesment of the trigger value -% this is needed because it takes some time for the rising flank to get to the correct value -trigshift = fix(hdr.Fs * 9/1200); - -% read the stimulus channel from raw CTF data: with the new electronics -% control console used at NIH, there is now no longer any channel -% named "STIM". Instead, there are a variety of channel names. The -% electronics used at FCDC still uses the "STIM" channel. -stimindx = find(strcmp(hdr.label, 'UPPT001')); -if isempty(stimindx) - stimindx = find(strcmp(hdr.label, 'USPT001')); -end -if isempty(stimindx) - stimindx = find(strcmp(hdr.label, 'UTRG001')); -end -if isempty(stimindx) - stimindx = find(strcmp(hdr.label, 'STIM')); -end -stim = read_ctf_meg4(datafile, hdr, 1, hdr.nTrials*hdr.nSamples, stimindx); - -% correct for reading stimulus channel as signed integer, whereas it should be an unsigned int -stim(find(stim<0)) = stim(find(stim<0)) + 2^32; - -% split backpanel and frontpanel data -bpstim = fix(stim / 2^16); -fpstim = double(bitand(uint32(stim), 2^16-1)); - -% determine the precise timing of the triggers -bpupflank = [0 (diff(bpstim)>0 & bpstim(1:(end-1))==0)]; -backpanel = bpupflank(1:(end-trigshift)).*bpstim((1+trigshift):end); -fpupflank = [0 (diff(fpstim)>0 & fpstim(1:(end-1))==0)]; -frontpanel = fpupflank(1:(end-trigshift)).*fpstim((1+trigshift):end); - -% pad with zeros to ensure same length as data -backpanel(length(stim)) = 0; -frontpanel(length(stim)) = 0; - diff --git a/external/fieldtrip/private/read_data.m b/external/fieldtrip/private/read_data.m deleted file mode 100644 index bfe0a10..0000000 --- a/external/fieldtrip/private/read_data.m +++ /dev/null @@ -1,1217 +0,0 @@ -function [dat] = read_data(filename, varargin); - -% READ_DATA reads electrophysiological data from a variety of EEG, -% MEG and LFP files and represents it in a common data-independent -% format. The supported formats are listed in the accompanying -% READ_HEADER function. -% -% Use as -% dat = read_data(filename, ...) -% -% Additional options should be specified in key-value pairs and can be -% 'header' header structure, see READ_HEADER -% 'begsample' first sample to read -% 'endsample' last sample to read -% 'begtrial' first trial to read, mutually exclusive with begsample+endsample -% 'endtrial' last trial to read, mutually exclusive with begsample+endsample -% 'chanindx' list with channel indices to read -% 'checkboundary' boolean, whether to check for reading segments over a trial boundary -% 'cache' boolean, whether to use caching for multiple reads -% 'dataformat' string -% 'headerformat' string -% 'fallback' can be empty or 'biosig' (default = []) -% -% This function returns a 2-D matrix of size Nchans*Nsamples for -% continuous data when begevent and endevent are specified, or a 3-D -% matrix of size Nchans*Nsamples*Ntrials for epoched or trial-based -% data when begtrial and endtrial are specified. -% -% See also READ_HEADER, READ_EVENT, WRITE_DATA, WRITE_EVENT - -% Copyright (C) 2003-2007, Robert Oostenveld, F.C. Donders Centre -% -% $Log: read_data.m,v $ -% Revision 1.89 2009/10/16 07:31:18 roboos -% renamed chieti into itab for consistency with other formats -% -% Revision 1.88 2009/10/13 10:12:51 roboos -% added support for chieti_raw -% -% Revision 1.87 2009/10/08 11:13:40 roevdmei -% added support for nmc_archive_k -% -% Revision 1.86 2009/10/07 12:45:32 roevdmei -% minor spelling correction -% -% Revision 1.85 2009/04/29 10:52:17 jansch -% incorporated handling of unsegmented egi simple binaries -% -% Revision 1.84 2009/03/23 12:09:07 vlalit -% Minor changes to make the ctf_old option fully functional. -% -% Revision 1.83 2009/03/13 07:12:09 roboos -% also use read_brainvision_eeg low-level function for *.seg files, obsoleted the read_brainvision_seg function -% -% Revision 1.82 2009/03/02 10:44:38 roboos -% switched default for fif files to use the MNE reading routines in case of neuromag_fif -% the user can make his own choise by specifying the format as neuromag_mne (for the MNE routines) or neuromag_mex (for the meg-pd mex files) -% -% Revision 1.81 2009/02/25 12:59:30 marvger -% removed calls to filetype and replaced with strcmp(dataformat,x) for -% efficiency -% -% Revision 1.80 2009/02/13 08:02:21 roboos -% ensure that the requested sample and trial numbers are integers -% -% Revision 1.79 2009/02/12 11:47:23 vlalit -% Added support for neuro prax (eldith) EEG format based on functions from the manufacturer -% used with permission from the company's representative Mr. Klaus Schellhorn. -% -% Revision 1.78 2009/02/09 14:21:00 roboos -% added inport of micromed_trc data -% -% Revision 1.77 2009/02/09 13:35:16 roboos -% implemented efficient caching for bci2000, -% it should be initiated in read_header, subsequently read_data and read_event will reuse the details from the header -% -% Revision 1.76 2009/02/09 12:42:27 vlalit -% Added a check for discontinuous boundary in the case of neuromag_mne evoked data. -% -% Revision 1.75 2009/02/06 10:12:20 roboos -% incorporated the latest suggestions of Laurence Hunt for neuromag_mne -% -% Revision 1.74 2009/02/04 09:09:59 roboos -% fixed filename to headerfile/datafile cvonversion in case of ctf_old -% -% Revision 1.73 2009/01/23 16:18:36 roboos -% cleaned up neuromag_mne -% -% Revision 1.72 2009/01/23 10:32:55 vlalit -% New reader for Neuromag fif format using the MNE toolbox (http://www.nmr.mgh.harvard.edu/martinos/userInfo/data/sofMNE.php) implemented by Laurence Hunt. -% -% Revision 1.71 2009/01/20 21:50:20 roboos -% use mxDeserialize instead of eval(string) in mysql -% -% Revision 1.70 2009/01/19 15:05:47 roboos -% added skeleton support for reading fif files using mne functions -% -% Revision 1.69 2009/01/06 09:12:03 roboos -% use true/false instead of 1/0 -% -% Revision 1.68 2008/12/16 21:25:57 roboos -% removed the backward compatibility handling of the read_fcdc_data input arguments, these are now done in read_fcdc_data (i.e. keep it clean) -% -% Revision 1.67 2008/12/15 13:10:38 roboos -% fixed bug in biosig fallback, header would be read instead of data -% -% Revision 1.66 2008/12/01 14:49:59 roboos -% ensure that input arguments are double precision and not integers, otherwise the subsequent computations will be messed up (learned this in Lyon) -% -% Revision 1.65 2008/11/13 21:50:11 roboos -% also read 4d data in case ChannelUnitsPerBit is missing from header (give warning and set calibration to 1) -% -% Revision 1.64 2008/11/13 21:20:58 roboos -% use dataformat=ns_cnt16/32 to specify 16/32 bit format for reading neuroscan cnt files -% -% Revision 1.63 2008/11/02 10:59:41 roboos -% some more changes for ctf_ds in case of empty path -% -% Revision 1.62 2008/11/02 10:42:25 roboos -% improved handling of empty path in case of ctf dataset -% -% Revision 1.61 2008/09/29 21:46:02 roboos -% Implemented data caching in a data-format independent manner, using fetch_data and a persistent variable. -% Not yet suitable for inclusion in fileio release, hence the default is not to use caching. -% -% Revision 1.60 2008/09/29 08:37:44 roboos -% fixed bug when reading short segments of CTF data (errors were given on screen, so the bug was apparent) -% -% Revision 1.59 2008/09/25 11:53:48 roboos -% more efficient handling for CTF in real continuous datasets (i.e. one long trial) and in case all samples are within the same trial -% detected and fixed a bug that would case faulure of the code when reading a data segment that extends over more than two trials -% -% Revision 1.58 2008/09/24 16:26:17 roboos -% swiched from old fcdc import routines for CTF to the p-files supplied by CTF -% these new reading routines support synthetic gradients -% the format 'ctf_new' is not supported any more, because that is now the default -% -% Revision 1.57 2008/09/24 07:01:49 roboos -% fixed begsample for neuralynx_ncs (thanks to Martin) -% -% Revision 1.56 2008/07/24 08:44:20 roboos -% added initial support for nimh_cortex, not yet complete -% -% Revision 1.55 2008/07/01 16:23:02 roboos -% added read_combined_data (new implementation) -% -% Revision 1.54 2008/07/01 12:59:42 roboos -% explicit blockread 1 for ns_cnt -% -% Revision 1.53 2008/06/26 15:50:56 roboos -% tread ctf_new just as ctf_ds w.r.t. mapping of the filenames -% -% Revision 1.52 2008/06/20 07:25:56 roboos -% added check for presence of BCI2000 load_bcidat mex file -% -% Revision 1.51 2008/06/18 08:24:33 roboos -% added support for BCI2000 -% -% Revision 1.50 2008/06/10 10:22:12 jansch -% removed sparse from calibration for 4d data, this is not necessary. added -% possibility for filnames including '.' for 4d data -% -% Revision 1.49 2008/05/29 13:54:52 roboos -% also work when no path is specified -% -% Revision 1.48 2008/05/29 13:51:11 roboos -% use strcmp instead of strmatch, thanks to Marinka -% -% Revision 1.47 2008/05/29 07:30:42 roboos -% small change in renaming header/data and filename in case of ctf, this prevents a warning if the res4 or meg4 are not positioned in a xxx.ds directory (see email Jo) -% -% Revision 1.46 2008/05/27 16:12:26 vlalit -% Changed type name to ced_spike6mat -% -% Revision 1.45 2008/05/27 11:58:20 vlalit -% Added support of Matlab files exported from Spike 6 -% -% Revision 1.44 2008/05/15 15:10:56 roboos -% added ctf_new implementation, using p-files, this supports synthetic gradients -% some changes to the filename handling, merged nihm2grad into ctf2grad -% -% Revision 1.43 2008/05/02 17:45:10 vlalit -% Some bug fixes after testing the SPM fileo code -% -% Revision 1.41 2008/04/28 19:27:11 roboos -% fixed dimord and selection of eeglab set data -% -% Revision 1.40 2008/04/21 11:50:52 roboos -% added support for egi_sbin, thanks to Joseph Dien -% -% Revision 1.39 2008/04/18 14:07:45 roboos -% added eeglab_set -% -% Revision 1.38 2008/04/11 07:23:15 roboos -% updated docu -% -% Revision 1.37 2008/04/10 09:34:51 roboos -% added fallback option for biosig, implemented biosig also for edf -% -% Revision 1.36 2008/04/09 16:50:02 roboos -% added fallback option to biosig (not default) -% -% Revision 1.35 2008/04/09 14:10:34 roboos -% added placeholder for biosig (not yet implemented) -% -% Revision 1.34 2008/04/09 10:09:45 roboos -% pass the hdr.orig to the low-level brainvision readers -% -% Revision 1.33 2008/02/19 10:08:13 roboos -% added support for fcdc_buffer -% -% Revision 1.32 2008/01/31 20:12:51 roboos -% On line 322 the cell element 4D was added to the existing case -% designed for the handling of 4D_bti data. This is necessary to -% allow this identified filetype to cause execution of this case. -% [thanks to Gavin] -% -% Revision 1.31 2008/01/10 12:57:34 roboos -% give explicit errors with msgid FILEIO:Something -% -% Revision 1.30 2007/12/17 13:03:52 roboos -% Vladimir found and fixed some bugs pertaining to the nexstim_nxe format -% -% Revision 1.29 2007/12/17 08:24:28 roboos -% added support for nexstim_nxe, thanks to Vladimir -% the low-level code has not been tested by myself -% -% Revision 1.28 2007/12/12 16:50:15 roboos -% added support for neuralynx_bin -% -% Revision 1.27 2007/11/07 10:49:06 roboos -% cleaned up the reading and writing from/to mysql database, using db_xxx helper functions (see mysql directory) -% -% Revision 1.26 2007/11/05 17:01:42 roboos -% added implementation for fcdc_mysql, not yet finished -% -% Revision 1.25 2007/09/24 15:14:02 roboos -% fixed bug in calibration of 4D/bti data, which is different for float than for short format data files (thanks to Nathan) -% -% Revision 1.24 2007/09/13 09:55:42 roboos -% use read_biosemi_bdf instead of openbdf/readbdf -% -% Revision 1.23 2007/08/01 12:24:40 roboos -% updated comments -% -% Revision 1.22 2007/08/01 09:57:01 roboos -% moved all code related to ctf shared memory to seperate functions -% -% Revision 1.21 2007/07/27 12:24:52 roboos -% implemented support for ctf_shm -% removed a double check for the presence of the file -% -% Revision 1.20 2007/07/19 14:49:21 roboos -% switched the default reader for nex files from read_nex_data to read_plexon_nex, the old one is still supported if explicitely mentioned as data/headerformat -% added support for multiple fragments of continuous AD data in nex files, holes are filled with NaNs -% -% Revision 1.19 2007/07/04 13:20:51 roboos -% added support for egi_egis/egia, thanks to Joseph Dien -% -% Revision 1.18 2007/07/03 16:10:48 roboos -% added a hack for 32 bit neuroscan format (hdr.nsdf=16|32), this should actually be be done using autodetection -% -% Revision 1.17 2007/07/03 15:53:46 roboos -% switched from using Cristian Wienbruchs BTi toolbox to a new ascii header reading function (read_bti_m4d) -% -% Revision 1.16 2007/06/13 08:06:21 roboos -% updated help -% -% Revision 1.15 2007/04/16 16:06:50 roboos -% fixed bug in selection of trials from an epoched file, when samples are requested (thanks to Vladimir) -% -% Revision 1.14 2007/03/26 12:41:18 roboos -% deal with continuous channels in nex files that have different starting samples/timestamps -% small modification in plexon_plx to account fo the change in the API of the underlying function -% -% Revision 1.13 2007/03/21 17:24:01 roboos -% added plexon_ds -% -% Revision 1.12 2007/03/19 17:03:14 roboos -% added chanindx for read_neuralynx_dma -% implemented an alternative reader for nex files (read_plexon_nex), the old reader is still the default -% -% Revision 1.11 2007/02/21 09:53:44 roboos -% changed the rearrangement of the data in case of neuralynx_ncs to reflect the changed representation (2D numeric array instead of 1D cell array) -% -% Revision 1.10 2007/01/09 09:37:48 roboos -% added neuralynx_nte, added spike channels for plexon_plx -% -% Revision 1.9 2007/01/04 17:12:36 roboos -% implemented plexon_plx, only continuous channels -% -% Revision 1.8 2007/01/04 12:21:36 roboos -% updated the neuralynx section to reflect the new reading functions and to use read_neuralynx_cds -% -% Revision 1.7 2006/12/04 10:38:12 roboos -% added support for ns_avg -% fixed long-outstanding problem for reading multiple trials from ns_eeg data -% -% Revision 1.6 2006/09/18 21:47:54 roboos -% implemented support for fcdc_matbin, i.e. a dataset consisting of a matlab file with header and events and a seperate binary datafile -% added smart default for reading all data when no selection given -% -% Revision 1.5 2006/09/18 14:22:54 roboos -% implemented support for 4D-BTi dataformat -% -% Revision 1.4 2006/08/28 10:12:22 roboos -% use seperate filetype_check_extension instead of (missing) check_extension subfunction (thanks to Thilo for reporting this bug) -% -% Revision 1.3 2006/06/19 10:31:47 roboos -% translate continuous option into checkboundary (complements), added documentation -% -% Revision 1.2 2006/06/19 08:14:17 roboos -% updated documentation -% -% Revision 1.1 2006/06/07 09:32:20 roboos -% new implementation based on the read_fcdc_xxx functions, now with -% variable (key-val) input arguments, changed the control structure -% in the rpobram (switch instead of ifs), allow the user to specify -% the file format, allow the user to specify either a sample selection -% or a block selection. The reading functionality should not have -% changed compared to the read_fcdc_xxx versions. -% - -persistent cachedata % for caching -persistent db_blob % for fcdc_mysql - -if isempty(db_blob) - db_blob = 0; -end - -% get the optional input arguments -hdr = keyval('header', varargin); -begsample = keyval('begsample', varargin); -endsample = keyval('endsample', varargin); -begtrial = keyval('begtrial', varargin); -endtrial = keyval('endtrial', varargin); -chanindx = keyval('chanindx', varargin); -checkboundary = keyval('checkboundary', varargin); -dataformat = keyval('dataformat', varargin); -headerformat = keyval('headerformat', varargin); -fallback = keyval('fallback', varargin); -cache = keyval('cache', varargin); if isempty(cache), cache = 0; end - -% determine the filetype -if isempty(dataformat) - dataformat = filetype(filename); -end - -% test whether the file or directory exists -if ~exist(filename, 'file') && ~strcmp(dataformat, 'ctf_shm') && ~strcmp(dataformat, 'fcdc_mysql') && ... - ~strcmp(dataformat, 'fcdc_buffer') - error('FILEIO:InvalidFileName', 'file or directory ''%s'' does not exist', filename); -end - -% ensure that these are double precision and not integers, otherwise the subsequent computations will be messed up -begsample = double(begsample); -endsample = double(endsample); -begtrial = double(begtrial); -endtrial = double(endtrial); - -% ensure that the requested sample and trial numbers are integers -if ~isempty(begsample) && mod(begsample, 1) - warning('rounding "begsample" to the nearest integer'); - begsample = round(begsample); -end -if ~isempty(endsample) && mod(endsample, 1) - warning('rounding "endsample" to the nearest integer'); - endsample = round(endsample); -end -if ~isempty(begtrial) && mod(begtrial, 1) - warning('rounding "begtrial" to the nearest integer'); - begtrial = round(begtrial); -end -if ~isempty(endtrial) && mod(endtrial, 1) - warning('rounding "endtrial" to the nearest integer'); - endtrial = round(endtrial); -end - -switch dataformat - case '4d_pdf' - datafile = filename; - headerfile = [datafile '.m4d']; - sensorfile = [datafile '.xyz']; - case {'4d_m4d', '4d_xyz'} - datafile = filename(1:(end-4)); % remove the extension - headerfile = [datafile '.m4d']; - sensorfile = [datafile '.xyz']; - case '4d' - [path, file, ext] = fileparts(filename); - datafile = fullfile(path, [file,ext]); - headerfile = fullfile(path, [file,ext]); - configfile = fullfile(path, 'config'); - case {'ctf_ds', 'ctf_old'} - % convert CTF filename into filenames - [path, file, ext] = fileparts(filename); - if any(strcmp(ext, {'.res4' '.meg4', '.1_meg4' '.2_meg4' '.3_meg4' '.4_meg4' '.5_meg4' '.6_meg4' '.7_meg4' '.8_meg4' '.9_meg4'})) - filename = path; - [path, file, ext] = fileparts(filename); - end - if isempty(path) && isempty(file) - % this means that the dataset was specified as the present working directory, i.e. only with '.' - filename = pwd; - [path, file, ext] = fileparts(filename); - end - headerfile = fullfile(filename, [file '.res4']); - datafile = fullfile(filename, [file '.meg4']); - if length(path)>3 && strcmp(path(end-2:end), '.ds') - filename = path; % this is the *.ds directory - end - case 'ctf_meg4' - [path, file, ext] = fileparts(filename); - if isempty(path) - path = pwd; - end - headerfile = fullfile(path, [file '.res4']); - datafile = fullfile(path, [file '.meg4']); - if length(path)>3 && strcmp(path(end-2:end), '.ds') - filename = path; % this is the *.ds directory - end - case 'ctf_res4' - [path, file, ext] = fileparts(filename); - if isempty(path) - path = pwd; - end - headerfile = fullfile(path, [file '.res4']); - datafile = fullfile(path, [file '.meg4']); - if length(path)>3 && strcmp(path(end-2:end), '.ds') - filename = path; % this is the *.ds directory - end - case 'brainvision_vhdr' - [path, file, ext] = fileparts(filename); - headerfile = fullfile(path, [file '.vhdr']); - if exist(fullfile(path, [file '.eeg'])) - datafile = fullfile(path, [file '.eeg']); - elseif exist(fullfile(path, [file '.seg'])) - datafile = fullfile(path, [file '.seg']); - elseif exist(fullfile(path, [file '.dat'])) - datafile = fullfile(path, [file '.dat']); - end - case 'brainvision_eeg' - [path, file, ext] = fileparts(filename); - headerfile = fullfile(path, [file '.vhdr']); - datafile = fullfile(path, [file '.eeg']); - case 'brainvision_seg' - [path, file, ext] = fileparts(filename); - headerfile = fullfile(path, [file '.vhdr']); - datafile = fullfile(path, [file '.seg']); - case 'brainvision_dat' - [path, file, ext] = fileparts(filename); - headerfile = fullfile(path, [file '.vhdr']); - datafile = fullfile(path, [file '.dat']); - case 'fcdc_matbin' - [path, file, ext] = fileparts(filename); - headerfile = fullfile(path, [file '.mat']); - datafile = fullfile(path, [file '.bin']); - case 'nmc_archive_k' - [path, file, ext] = fileparts(filename); - headerfile = [path '/' file 'newparams.txt']; - if isempty(headerformat) - headerformat = 'nmc_archive_k'; - end - if isempty(hdr) - hdr = read_header(headerfile, 'headerformat', headerformat); - end - datafile = filename; - otherwise - % convert filename into filenames, assume that the header and data are the same - datafile = filename; - headerfile = filename; -end - -if ~strcmp(filename, datafile) && ~ismember(dataformat, {'ctf_ds', 'ctf_old'}) - filename = datafile; % this function will read the data - dataformat = filetype(filename); % update the filetype -end - -% for backward compatibility, default is to check when it is not continous -if isempty(checkboundary) - checkboundary = ~keyval('continuous', varargin); -end - -% read the header if it is not provided -if isempty(hdr) - hdr = read_header(filename, 'headerformat', headerformat); -end - -% set the default channel selection, which is all channels -if isempty(chanindx) - chanindx = 1:hdr.nChans; -end - -% read untill the end of the file if the endsample is "inf" -if any(isinf(endsample)) && any(endsample>0) - endsample = hdr.nSamples*hdr.nTrials; -end - -% test whether the requested channels can be accomodated -if min(chanindx)<1 || max(chanindx)>hdr.nChans - error('FILEIO:InvalidChanIndx', 'selected channels are not present in the data'); -end - -% test whether the requested data segment is not outside the file -if any(begsample<1) - error('FILEIO:InvalidBegSample', 'cannot read data before the begin of the file'); -elseif any(endsample>(hdr.nSamples*hdr.nTrials)) - error('FILEIO:InvalidEndSample', 'cannot read data after the end of the file'); -end - -requesttrials = isempty(begsample) && isempty(endsample); -requestsamples = isempty(begtrial) && isempty(endtrial); - -if cache && requesttrials - error('caching is not supported when reading trials') -end - -if isempty(begsample) && isempty(endsample) && isempty(begtrial) && isempty(endtrial) - % neither samples nor trials are specified, set the defaults to read the complete data trial-wise (also works for continuous) - requestsamples = 0; - requesttrials = 1; - begtrial = 1; - endtrial = hdr.nTrials; -end - -% set the default, which is to assume that it is should check for boundaries when samples are requested -if isempty(checkboundary) && requesttrials - checkboundary = false; -elseif isempty(checkboundary) && requestsamples - checkboundary = true; -end - -if requesttrials && requestsamples - error('you cannot select both trials and samples at the same time'); -elseif requesttrials - % this allows for support using a continuous reader - if isinf(hdr.nSamples) && begtrial==1 - begsample = 1; % computing it here does not work (0*inf=nan) - else - begsample = (begtrial-1)*hdr.nSamples + 1; % compute it the normal way - end - endsample = (endtrial )*hdr.nSamples; -elseif requestsamples - % this allows for support using a trial-based reader - begtrial = floor((begsample-1)/hdr.nSamples)+1; - endtrial = floor((endsample-1)/hdr.nSamples)+1; -else - error('you should either specify begin/end trial or begin/end sample'); -end - -% test whether the requested data segment does not extend over a discontinuous trial boundary -if checkboundary && hdr.nTrials>1 - if begtrial~=endtrial - error('requested data segment extends over a discontinuous trial boundary'); - end -end - -if strcmp(dataformat, 'bci2000_dat') - % caching for BCI2000 is handled in the main section and in read_header -else - % implement the caching in a data-format independent way - if cache && isempty(cachedata) - % create a new FieldTrip raw data structure that will hold the data - cachedata.label = hdr.label(chanindx); - cachedata.fsample = hdr.Fs; - cachedata.time = {}; - cachedata.trial = {}; - cachedata.cfg = []; - cachedata.cfg.trl = zeros(0,3); - elseif cache && ~isempty(cachedata) - % try to fetch the requested segment from the cache - try - dat = fetch_data(cachedata, 'begsample', begsample', 'endsample', endsample); - % fprintf('caching succeeded\n'); - return - catch - % fprintf('caching failed\n'); - end - end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% read the data with the low-level reading function -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -switch dataformat - - case {'4d' '4d_pdf', '4d_m4d', '4d_xyz'} - [fid,message] = fopen(datafile,'rb','ieee-be'); - % determine the type and size of the samples - sampletype = lower(hdr.orig.Format); - switch sampletype - case 'short' - samplesize = 2; - case 'long' - samplesize = 4; - case 'float' - samplesize = 4; - case 'double' - samplesize = 8; - otherwise - error('unsupported data format'); - end - % 4D/BTi MEG data is multiplexed, can be epoched/discontinuous - offset = (begsample-1)*samplesize*hdr.nChans; - numsamples = endsample-begsample+1; - gain = hdr.orig.ChannelGain; - if isfield(hdr.orig, 'ChannelUnitsPerBit') - upb = hdr.orig.ChannelUnitsPerBit; - else - warning('cannot determine ChannelUnitsPerBit'); - upb = 1; - end - % jump to the desired data - fseek(fid, offset, 'cof'); - % read the desired data - if length(chanindx)==1 - % read only one channel - fseek(fid, (chanindx-1)*samplesize, 'cof'); % seek to begin of channel - dat = fread(fid, numsamples, ['1*' sampletype], (hdr.nChans-1)*samplesize)'; % read one channel, skip the rest - else - % read all channels - dat = fread(fid, [hdr.nChans, numsamples], sampletype); - end - fclose(fid); - if length(chanindx)==1 - % only one channel was selected, which is managed by the code above - % nothing to do - elseif length(chanindx)==hdr.nChans - % all channels have been selected - % nothing to do - else - % select the desired channel(s) - dat = dat(chanindx,:); - end - % determine how to calibrate the data - switch sampletype - case {'short', 'long'} - % include both the gain values and the integer-to-double conversion in the calibration - calib = diag(gain(chanindx) .* upb(chanindx)); - case {'float', 'double'} - % only include the gain values in the calibration - calib = diag(gain(chanindx)); - otherwise - error('unsupported data format'); - end - % calibrate the data - dat = calib*dat; - - case 'bci2000_dat' - % this requires the load_bcidat mex file to be present on the path - hastoolbox('BCI2000', 1); - % this is inefficient, since it reads the complete data - if isfield(hdr.orig, 'signal') && isfield(hdr.orig, 'states') - % assume that the complete data is stored in the header, this speeds up subsequent read operations - signal = hdr.orig.signal; - states = hdr.orig.states; - parameters = hdr.orig.parameters; - total_samples = hdr.orig.total_samples; - else - [signal, states, parameters, total_samples] = load_bcidat(filename); - end - % apply the callibration from AD units to uV - dat = double(signal(begsample:endsample,chanindx)'); - for i=chanindx(:)' - dat(i,:) = dat(i,:).* parameters.SourceChGain.NumericValue(i) + parameters.SourceChOffset.NumericValue(i); - end - dimord = 'chans_samples'; - - case 'besa_avr' - % BESA average data - orig = read_besa_avr(filename); - dat = orig.data(chanindx, begsample:endsample); - - case 'besa_swf' - % BESA source waveform - orig = read_besa_swf(filename); - dat = orig.data(chanindx, begsample:endsample); - - case {'biosemi_bdf', 'bham_bdf'} - % this uses a mex file for reading the 24 bit data - dat = read_biosemi_bdf(filename, hdr, begsample, endsample, chanindx); - - case {'biosemi_old'} - % this uses the openbdf and readbdf functions that I copied from the EEGLAB toolbox - epochlength = hdr.orig.Head.SampleRate(1); - % it has already been checked in read_header that all channels have the same sampling rate - begepoch = floor((begsample-1)/epochlength) + 1; - endepoch = floor((endsample-1)/epochlength) + 1; - nepochs = endepoch - begepoch + 1; - orig = openbdf(filename); - dat = zeros(length(chanindx),nepochs*epochlength); - for i=begepoch:endepoch - % read and concatenate all required data epochs - [orig, buf] = readbdf(orig, i, 0); - if size(buf,2)~=hdr.nChans || size(buf,1)~=epochlength - error('error reading selected data from bdf-file'); - else - dat(:,((i-begepoch)*epochlength+1):((i-begepoch+1)*epochlength)) = buf(:,chanindx)'; - end - end - begsample = begsample - (begepoch-1)*epochlength; % correct for the number of bytes that were skipped - endsample = endsample - (begepoch-1)*epochlength; % correct for the number of bytes that were skipped - dat = dat(:, begsample:endsample); - % close the file between seperate read operations - fclose(orig.Head.FILE.FID); - - case {'biosig', 'edf'} - % use the biosig toolbox if available - hastoolbox('BIOSIG', 1); - dat = read_biosig_data(filename, hdr, begsample, endsample, chanindx); - - case {'brainvision_eeg', 'brainvision_dat', 'brainvision_seg'} - dat = read_brainvision_eeg(filename, hdr.orig, begsample, endsample); - dat = dat(chanindx,:); % select the desired channels - - case 'ced_son' - % chek the availability of the required low-level toolbox - hastoolbox('neuroshare', 1); - % use the reading function supplied by Gijs van Elswijk - % - % CED ADC is done in sequence, thus the analog channels - % do not share the same time axis. This is _ignored_ here. - % - % Set the READ_CED_SON parameter 'readtimestamps' to - % 'yes' to get time axis for each data channel returned. - % This time information can be used to do - % a temporal realignment of the data. - tmp = read_ced_son(filename,'readdata','yes',... - 'begsample',begsample,... - 'endsample',endsample,... - 'channels',chanindx); - dat = cell2mat(tmp.data'); - - case 'itab_raw' - % check the presence of the required low-level toolbox - hastoolbox('lc-libs', 1); - chansel = hdr.orig.chansel; % these are the channels that are visible to fieldtrip - % read the data using the dll - dat = lcReadData(chansel, begsample, endsample, filename); - % take the subset of channels that is selected by the user - dat = dat(chanindx, :); - - case 'combined_ds' - dat = read_combined_ds(filename, hdr, begsample, endsample, chanindx); - - case {'ctf_ds', 'ctf_meg4', 'ctf_res4'} - % check that the required low-level toolbox is available - hastoolbox('ctf', 1); - % this returns SQUIDs in T, EEGs in V, ADC's and DACS in V, HLC channels in m, clock channels in s. - if begtrial==endtrial - % specify selection as 3x1 vector - trlbegsample = begsample - hdr.nSamples*(begtrial-1); % within the trial - trlendsample = endsample - hdr.nSamples*(begtrial-1); % within the trial - dat = getCTFdata(hdr.orig, [trlbegsample; trlendsample; begtrial], chanindx, 'T', 'double'); - dimord = 'samples_chans'; - else - % specify selection as 1xN vector - dat = getCTFdata(hdr.orig, [begtrial:endtrial], chanindx, 'T', 'double'); - dimord = 'samples_chans_trials'; - end - - case {'ctf_old', 'read_ctf_meg4'} - % read it using the open-source matlab code that originates from CTF and that was modified by the FCDC - dat = read_ctf_meg4(datafile, hdr.orig, begsample, endsample, chanindx); - - case 'ctf_read_meg4' - % check that the required low-level toolbox is available - hastoolbox('eegsf', 1); - % read it using the CTF importer from the NIH and Daren Weber - tmp = ctf_read_meg4(filename, hdr.orig, chanindx, 'all', begtrial:endtrial); - dat = cat(3, tmp.data{:}); - % the data is shaped in a 3-D array - dimord = 'samples_chans_trials'; - - case 'ctf_shm' - % contact Robert Oostenveld if you are interested in real-time acquisition on the CTF system - % read the data from shared memory - [dat, dimord] = read_shm_data(hdr, chanindx, begtrial, endtrial); - - case 'eeglab_set' - dat = read_eeglabdata(filename, 'header', hdr, 'begtrial', begtrial, 'endtrial', endtrial, 'chanindx', chanindx); - dimord = 'chans_samples_trials'; - - case 'spmeeg_mat' - dat = read_spmeeg_data(filename, 'header', hdr, 'begsample', begsample, 'endsample', endsample, 'chanindx', chanindx); - - case 'ced_spike6mat' - dat = read_spike6mat_data(filename, 'header', hdr, 'begsample', begsample, 'endsample', endsample, 'chanindx', chanindx); - - case 'eep_avr' - % check that the required low-level toolbos ix available - hastoolbox('eeprobe', 1); - dat = read_eep_avr(filename); - dat = dat.data(chanindx,begsample:endsample); % select the desired channels and samples - - case 'eep_cnt' - % check that the required low-level toolbos ix available - hastoolbox('eeprobe', 1); - dat = read_eep_cnt(filename, begsample, endsample); - dat = dat.data(chanindx,:); % select the desired channels - - case 'fcdc_buffer' - % read from a networked buffer for realtime analysis - - [host, port] = filetype_check_uri(filename); - dat = buffer('get_dat', [begsample-1 endsample-1], host, port); % indices should be zero-offset - dat = dat.buf(chanindx,:); % select the desired channels - - case 'fcdc_matbin' - % multiplexed data in a *.bin file, accompanied by a matlab file containing the header - offset = begsample-1; - numsamples = endsample-begsample+1; - samplesize = 8; - sampletype = 'double'; - [fid,message] = fopen(datafile,'rb','ieee-le'); - % jump to the desired data - fseek(fid, offset*samplesize*hdr.nChans, 'cof'); - % read the desired data - if length(chanindx)==1 - % read only one channel - fseek(fid, (chanindx-1)*samplesize, 'cof'); % seek to begin of channel - dat = fread(fid, numsamples, ['1*' sampletype], (hdr.nChans-1)*samplesize)'; % read one channel, skip the rest - else - % read all channels - dat = fread(fid, [hdr.nChans, numsamples], sampletype); - end - fclose(fid); - if length(chanindx)==1 - % only one channel was selected, which is managed by the code above - % nothing to do - elseif length(chanindx)==hdr.nChans - % all channels have been selected - % nothing to do - else - % select the desired channel(s) - dat = dat(chanindx,:); - end - - case 'fcdc_mysql' - % read from a MySQL server listening somewhere else on the network - db_open(filename); - if db_blob - error('not implemented'); - else - for i=begtrial:endtrial - s = db_select('fieldtrip.data', {'nChans', 'nSamples', 'data'}, i); - dum{i-begtrial+1} = mxDeserialize(s.data); - end - dat = zeros(length(chanindx), s.nSamples, endtrial-begtrial+1); - for i=begtrial:endtrial - dat(:,:,i-begtrial+1) = dum{i-begtrial+1}(chanindx,:); - end - dimord = 'chans_samples_trials'; - end - - case {'egi_egia', 'egi_egis'} - dat = read_egis_data(filename, hdr, begtrial, endtrial, chanindx); - dimord = 'chans_samples_trials'; - - case {'egi_sbin'} - if mod(hdr.orig.header_array(1),2)==0, - %unsegmented data contains only 1 trial, don't read the whole file - dat = read_sbin_data(filename, hdr, begsample, endsample, chanindx); - requestsamples = 0; - else - %segmented data - dat = read_sbin_data(filename, hdr, begtrial, endtrial, chanindx); - end - dimord = 'chans_samples_trials'; - - case 'micromed_trc' - dat = read_micromed_trc(filename, begsample, endsample); - dat = dat(chanindx,:); - dimord = 'chans_samples'; - - case {'mpi_ds', 'mpi_dap'} - [hdr, dat] = read_mpi_ds(filename); - dat = dat(chanindx, begsample:endsample); % select the desired channels and samples - - case 'neuralynx_dma' - dat = read_neuralynx_dma(filename, begsample, endsample, chanindx); - - case 'neuralynx_sdma' - dat = read_neuralynx_sdma(filename, begsample, endsample, chanindx); - - case 'neuralynx_ncs' - NRecords = hdr.nSamples/512; - begrecord = ceil(begsample/512); - endrecord = ceil(endsample/512); - % read the records that contain the desired samples - ncs = read_neuralynx_ncs(filename, begrecord, endrecord); - % cut out the desired samples - begsample = begsample - (begrecord-1)*512; - endsample = endsample - (begrecord-1)*512; - % this also reshape the data from 512 X records into a linear array - dat = ncs.dat(begsample:endsample); - - case 'neuralynx_nse' - % read all records - nse = read_neuralynx_nse(filename); - % convert timestamps to samples - sample = round((nse.TimeStamp - hdr.FirstTimeStamp)./hdr.TimeStampPerSample + 1); - % select the timestamps that are between begin and endsample - sample = sample(sample>=begsample & sample<=endsample) - begsample + 1; - dat = zeros(1,endsample-begsample+1); - dat(sample) = 1; - - case 'neuralynx_nte' - % read all records - nte = read_neuralynx_nte(filename); - % convert timestamps to samples - sample = round((nte.TimeStamp - hdr.FirstTimeStamp)./hdr.TimeStampPerSample + 1); - % select the timestamps that are between begin and endsample - sample = sample(sample>=begsample & sample<=endsample) - begsample + 1; - dat = zeros(1,endsample-begsample+1); - dat(sample) = 1; - - case {'neuralynx_ttl', 'neuralynx_tsl', 'neuralynx_tsh'} - % single channel files - dat = read_neuralynx_ttl(filename, begsample, endsample); - - case 'neuralynx_bin' - % single channel files - dat = read_neuralynx_bin(filename, begsample, endsample); - - case 'neuralynx_ds' - dat = read_neuralynx_ds(filename, hdr, begsample, endsample, chanindx); - - case 'neuralynx_cds' - dat = read_neuralynx_cds(filename, hdr, begsample, endsample, chanindx); - - case 'nexstim_nxe' - dat = read_nexstim_nxe(filename, begsample, endsample, chanindx); - - case 'nimh_cortex' - keyboard - - case 'ns_avg' - % NeuroScan average data - orig = read_ns_avg(filename); - dat = orig.data(chanindx, begsample:endsample); - - case {'ns_cnt' 'ns_cnt16', 'ns_cnt32'} - % Neuroscan continuous data - sample1 = begsample-1; - ldnsamples = endsample-begsample+1; % number of samples to read - ldchan = 1:hdr.nChans; % must be row vector - chanoi = chanindx(:)'; % channels of interest - if sample1<0 - error('begin sample cannot be for the beginning of the file'); - end - % the hdr.nsdf was the initial fieldtrip hack to get 32 bit support, now it is realized using a extended dataformat string - if isfield(hdr, 'nsdf') && hdr.nsdf==16 - dataformat = 'ns_cnt16'; - elseif isfield(hdr, 'nsdf') && hdr.nsdf==32 - dataformat = 'ns_cnt32'; - end - % read_ns_cnt originates from the EEGLAB package (loadcnt.m) but is - % an old version since the new version is not compatible any more - % all data is read, and only the relevant data is kept. - if strcmp(dataformat, 'ns_cnt') - tmp = read_ns_cnt(filename, 'sample1', sample1, 'ldnsamples', ldnsamples, 'ldchan', ldchan, 'blockread', 1); - elseif strcmp(dataformat, 'ns_cnt16') - tmp = read_ns_cnt(filename, 'sample1', sample1, 'ldnsamples', ldnsamples, 'ldchan', ldchan, 'blockread', 1, 'format', 16); - elseif strcmp(dataformat, 'ns_cnt32') - tmp = read_ns_cnt(filename, 'sample1', sample1, 'ldnsamples', ldnsamples, 'ldchan', ldchan, 'blockread', 1, 'format', 32); - end - dat = tmp.dat(chanoi,:); - - case 'ns_eeg' - % Neuroscan epoched file - tmp = read_ns_eeg(filename, begtrial:endtrial); - siz = [(endtrial-begtrial+1) hdr.nChans hdr.nSamples]; - dat = reshape(tmp.data, siz); % ensure 3-D array - dat = dat(:,chanindx,:); % select channels - dimord = 'trials_chans_samples'; % selection using begsample and endsample will be done later - - case {'neuromag_fif' 'neuromag_mne'} - % check that the required low-level toolbox is available - hastoolbox('mne', 1); - if (hdr.orig.iscontinuous) - dat = fiff_read_raw_segment(hdr.orig.raw,begsample+hdr.nSamplesPre-1,endsample+hdr.nSamplesPre-1,chanindx); - dimord = 'chans_samples'; - elseif (hdr.orig.isaverage) - dat = cat(2, hdr.orig.evoked.epochs); % concatenate all epochs, this works both when they are of constant or variable length - if checkboundary - trialnumber = []; - for i = 1:numel(hdr.orig.evoked) - trialnumber = [trialnumber i*ones(size(hdr.orig.evoked(i).times))]; - end - if trialnumber(begsample) ~= trialnumber(endsample) - error('requested data segment extends over a discontinuous trial boundary'); - end - end - dat = dat(chanindx, begsample:endsample); % select the desired channels and samples - dimord = 'chans_samples'; - elseif (hdr.orig.isepoched) - error('Support for epoched *.fif data is not yet implemented.') - end - - case 'neuromag_mex' - % check that the required low-level toolbox is available - hastoolbox('meg-pd', 1); - begtime = (begsample-1)/hdr.Fs; - begepoch = floor((begsample-1)/hdr.nSamples) + 1; - endepoch = floor((endsample-1)/hdr.nSamples) + 1; - rawdata('any',filename); - rawdata('goto', begtime); - dat = []; - for i=begepoch:endepoch - [buf, status] = rawdata('next'); - if ~strcmp(status, 'ok') - error('error reading selected data from fif-file'); - else - dat(:,((i-begepoch)*hdr.nSamples+1):((i-begepoch+1)*hdr.nSamples)) = buf(chanindx,:); - end - end - rawdata('close'); - begsample = begsample - (begepoch-1)*hdr.nSamples; % correct for the number of bytes that were skipped - endsample = endsample - (begepoch-1)*hdr.nSamples; % correct for the number of bytes that were skipped - dat = dat(:, begsample:endsample); - - case 'neuroprax_eeg' - tmp = np_readdata(filename, hdr.orig, begsample - 1, endsample - begsample + 1, 'samples'); - dat = tmp.data'; - - case 'plexon_ds' - dat = read_plexon_ds(filename, hdr, begsample, endsample, chanindx); - - case 'plexon_ddt' - dat = read_plexon_ddt(filename, begsample, endsample); - dat = dat.data(chanindx,:); - - case {'read_nex_data'} % this is an alternative reader for nex files - dat = read_nex_data(filename, hdr, begsample, endsample, chanindx); - - case {'read_plexon_nex' 'plexon_nex'} % this is the default reader for nex files - dat = zeros(length(chanindx), endsample-begsample+1); - for i=1:length(chanindx) - if hdr.orig.VarHeader(chanindx(i)).Type==5 - % this is a continuous channel - if hdr.orig.VarHeader(chanindx(i)).Count==1 - [nex, chanhdr] = read_plexon_nex(filename, 'header', hdr.orig, 'channel', chanindx(i), 'tsonly', 1); - % the AD channel contains a single fragment - % determine the sample offset into this fragment - offset = round(double(nex.ts-hdr.FirstTimeStamp)./hdr.TimeStampPerSample); - chanbegsmp = begsample - offset; - chanendsmp = endsample - offset; - if chanbegsmp<1 - % the first sample of this channel is later than the beginning of the dataset - % and we are trying to read the beginning of the dataset - [nex, chanhdr] = read_plexon_nex(filename, 'header', hdr.orig, 'channel', chanindx(i), 'tsonly', 0, 'begsample', 1, 'endsample', chanendsmp); - % padd the beginning of this channel with NaNs - nex.dat = [nan(1,offset) nex.dat]; - else - [nex, chanhdr] = read_plexon_nex(filename, 'header', hdr.orig, 'channel', chanindx(i), 'tsonly', 0, 'begsample', chanbegsmp, 'endsample', chanendsmp); - end - % copy the desired samples into the output matrix - dat(i,:) = nex.dat; - else - % the AD channel contains multiple fragments - [nex, chanhdr] = read_plexon_nex(filename, 'header', hdr.orig, 'channel', chanindx(i), 'tsonly', 0); - % reconstruct the full AD timecourse with NaNs at all missing samples - offset = round(double(nex.ts-hdr.FirstTimeStamp)./hdr.TimeStampPerSample); % of each fragment, in AD samples - nsample = diff([nex.indx length(nex.dat)]); % of each fragment, in AD samples - % allocate memory to hold the complete continuous record - cnt = nan(1, offset(end)+nsample(end)); - for j=1:length(offset) - cntbegsmp = offset(j) + 1; - cntendsmp = offset(j) + nsample(j); - fragbegsmp = nex.indx(j) + 1; - fragendsmp = nex.indx(j) + nsample(j); - cnt(cntbegsmp:cntendsmp) = nex.dat(fragbegsmp:fragendsmp); - end - % copy the desired samples into the output matrix - dat(i,:) = cnt(begsample:endsample); - end - elseif any(hdr.orig.VarHeader(chanindx(i)).Type==[0 1 3]) - % it is a neuron(0), event(1) or waveform(3) channel and therefore it has timestamps - [nex, chanhdr] = read_plexon_nex(filename, 'header', hdr.orig, 'channel', chanindx(i), 'tsonly', 1); - % convert the timestamps to samples - sample = round(double(nex.ts - hdr.FirstTimeStamp)./hdr.TimeStampPerSample) + 1; - % select only timestamps that are between begin and endsample - sample = sample(sample>=begsample & sample<=endsample) - begsample + 1; - for j=sample(:)' - dat(i,j) = dat(i,j) + 1; - end - end - end - if any(isnan(dat(:))) - warning('data has been padded with NaNs'); - end - - case 'plexon_plx' - % determine the continuous channels - contlabel = {hdr.orig.SlowChannelHeader.Name}; - for i=1:length(contlabel) - contlabel{i} = deblank(contlabel{i}); - end - [contindx, contsel] = match_str(contlabel, hdr.label(chanindx)); - - % determine the channels with spike waveforms - spikelabel = {hdr.orig.ChannelHeader.Name}; - for i=1:length(spikelabel) - spikelabel{i} = deblank(spikelabel{i}); - end - [spikeindx, spikesel] = match_str(spikelabel, hdr.label(chanindx)); - - if (length(contindx)+length(spikeindx))=begsample & sample<=endsample) - begsample + 1; - for j=sample(:)' - dat(spikesel(i),j) = dat(spikesel(i),j) + 1; - end - end - - case {'yokogawa_ave', 'yokogawa_con', 'yokogawa_raw'} - % check that the required low-level toolbox is available - hastoolbox('yokogawa', 1); - dat = read_yokogawa_data(filename, hdr, begsample, endsample, chanindx); - - case 'nmc_archive_k' - dat = read_nmc_archive_k_data(filename, hdr, begsample, endsample, chanindx); - - - otherwise - if strcmp(fallback, 'biosig') && hastoolbox('BIOSIG', 1) - dat = read_biosig_data(filename, hdr, begsample, endsample, chanindx); - else - error('unsupported data format'); - end - -end - -if ~exist('dimord', 'var') - dimord = 'chans_samples'; % almost all low-level readers return the data as 2D array -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% reshape the 2-D or 3-D matrix to a common order of the dimensions -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -switch dimord - case {'chans_samples', 'chans_samples_trials'} - % nothing to do - case 'samples_chans' - dat = permute(dat, [2 1]); - dimord = 'chans_samples'; - case 'samples_chans_trials' - dat = permute(dat, [2 1 3]); - dimord = 'chans_samples_trials'; - case 'trials_samples_chans' - dat = permute(dat, [3 2 1]); - dimord = 'chans_samples_trials'; - case 'trials_chans_samples' - dat = permute(dat, [2 3 1]); - dimord = 'chans_samples_trials'; - otherwise - error('unexpected dimord'); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% convert between 3-D trial based and 2-D continuous output -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if requesttrials && strcmp(dimord, 'chans_samples') - % reformat the continuous representation into trials - nchans = size(dat,1); - nsamples = hdr.nSamples; - ntrials = size(dat,2)/hdr.nSamples; - dat = reshape(dat, [nchans nsamples ntrials]); % convert into a 3-D array - -elseif requestsamples && strcmp(dimord, 'chans_samples_trials') - % reformat the trials into a continuous representation - nchans = size(dat,1); - nsamples = size(dat,2); - ntrials = size(dat,3); - dat = reshape(dat, [nchans nsamples*ntrials]); % convert into a 2-D array - % determine the selection w.r.t. the data as it is on disk - begselection = (begtrial-1)*hdr.nSamples + 1; - endselection = (endtrial )*hdr.nSamples; - % determine the selection w.r.t. the data that has been read in - begselection2 = begsample - begselection + 1; - endselection2 = endsample - begselection + 1; - dat = dat(:,begselection2:endselection2); -end - -if strcmp(dataformat, 'bci2000_dat') - % caching for BCI2000 is handled in the main section and in read_header -else - % implement caching in a data independent way - if cache && requestsamples - % add the new segment to the cache - % FIMXE the cache size should be limited - cachedata.cfg.trl(end+1,:) = [begsample endsample 0]; - cachedata.trial{end+1} = dat; - cachedata.time{end+1} = (1:size(dat,2))/cachedata.fsample; - end -end diff --git a/external/fieldtrip/private/read_eeglabdata.m b/external/fieldtrip/private/read_eeglabdata.m deleted file mode 100644 index 4c2f13e..0000000 --- a/external/fieldtrip/private/read_eeglabdata.m +++ /dev/null @@ -1,118 +0,0 @@ -% read_eeglabdata() - import EEGLAB dataset files -% -% Usage: -% >> dat = read_eeglabdata(filename); -% -% Inputs: -% filename - [string] file name -% -% Optional inputs: -% 'begtrial' - [integer] first trial to read -% 'endtrial' - [integer] last trial to read -% 'chanindx' - [integer] list with channel indices to read -% 'header' - FILEIO structure header -% -% Outputs: -% dat - data over the specified range -% -% Author: Arnaud Delorme, SCCN, INC, UCSD, 2008- - -%123456789012345678901234567890123456789012345678901234567890123456789012 - -% Copyright (C) 2008 Arnaud Delorme, SCCN, INC, UCSD, arno@salk.edu -% -% This program is free software; you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation; either version 2 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program; if not, write to the Free Software -% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -% $Log: read_eeglabdata.m,v $ -% Revision 1.3 2009/07/01 15:35:19 vlalit -% Try several different ways of looking for the data file -% before giving up (fix suggested by Jakob Scherer) -% -% Revision 1.2 2009/02/27 12:03:09 vlalit -% Arno's fix for a bug reported by Antanas Spokas -% -% Revision 1.1 2009/01/30 04:01:19 arno -% *** empty log message *** -% -% Revision 1.2 2008/04/21 18:45:23 roboos -% fixed bug due to sample/trial selection mixup -% only read the selected trials -% -% Revision 1.1 2008/04/18 14:04:48 roboos -% new implementation by Arno, shoudl be tested -% - -function dat = read_eeglabdata(filename, varargin); - -if nargin < 1 - help read_eeglabdata; - return; -end; - -header = keyval('header', varargin); -begsample = keyval('begsample', varargin); -endsample = keyval('endsample', varargin); -begtrial = keyval('begtrial', varargin); -endtrial = keyval('endtrial', varargin); -chanindx = keyval('chanindx', varargin); - -if isempty(header) - header = read_eeglabheader(filename); -end; - -if ischar(header.orig.data) - if strcmpi(header.orig.data(end-2:end), 'set'), - header.ori = load('-mat', filename); - else - - % assuming that the data file is in the current directory - fid = fopen(header.orig.data); - - % assuming the .dat and .set files are located in the same directory - if fid == -1 - pathstr = fileparts(filename); - fid = fopen(fullfile(pathstr, header.orig.data)); - end - - if fid == -1 - fid = fopen(fullfile(header.orig.filepath, header.orig.data)); % - end - - if fid == -1, error('Cannot not find data file'); end; - - % only read the desired trials - if strcmpi(header.orig.data(end-2:end), 'dat') - dat = fread(fid,[header.nSamples*header.nTrials header.nChans],'float32')'; - else - dat = fread(fid,[header.nChans header.nSamples*header.nTrials],'float32')'; - end; - dat = reshape(dat, header.nChans, header.nSamples, header.nTrials); - fclose(fid); - end; -else - dat = header.orig.data; - dat = reshape(dat, header.nChans, header.nSamples, header.nTrials); -end; - -if isempty(begtrial), begtrial = 1; end; -if isempty(endtrial), endtrial = header.nTrials; end; -if isempty(begsample), begsample = 1; end; -if isempty(endsample), endsample = header.nSamples; end; -dat = dat(:,begsample:endsample,begtrial:endtrial); - -if ~isempty(chanindx) - % select the desired channels - dat = dat(chanindx,:,:); -end diff --git a/external/fieldtrip/private/read_eeglabevent.m b/external/fieldtrip/private/read_eeglabevent.m deleted file mode 100644 index 28c0f6a..0000000 --- a/external/fieldtrip/private/read_eeglabevent.m +++ /dev/null @@ -1,93 +0,0 @@ -% read_eeglabevent() - import EEGLAB dataset events -% -% Usage: -% >> header = read_eeglabevent(filename); -% -% Inputs: -% filename - [string] file name -% -% Optional inputs: -% 'header' - FILEIO structure header -% -% Outputs: -% event - FILEIO toolbox event structure -% -% Author: Arnaud Delorme, SCCN, INC, UCSD, 2008- - -%123456789012345678901234567890123456789012345678901234567890123456789012 - -% Copyright (C) 2008 Arnaud Delorme, SCCN, INC, UCSD, arno@salk.edu -% -% This program is free software; you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation; either version 2 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program; if not, write to the Free Software -% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -% $Log: read_eeglabevent.m,v $ -% Revision 1.4 2009/08/29 05:11:31 josdie -% After consultation with Arno, changed so that value (when present) and type fields in EEGlab .set files are treated as being reversed from value and type fields in FieldTrip files. -% -% Revision 1.3 2009/08/09 01:45:24 josdie -% Changed event value to equal EEGlab's event value rather than type. -% -% Revision 1.2 2009/02/02 20:45:34 josdie -% FieldTrip's .value field now set to EEGlab's .type field. FieldTrip's .type field set to 'trigger'. FieldTrip's .duration field set to 0 rather than empty. -% -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.1 2008/04/18 14:04:48 roboos -% new implementation by Arno, shoudl be tested -% - -function event = read_eeglabevent(filename, varargin) - -if nargin < 1 - help read_eeglabheader; - return; -end; - -header = keyval('header', varargin); - -if isempty(header) - header = read_eeglabheader(filename); -end; - -event = []; -oldevent = header.orig.event; -for index = 1:length(oldevent) - event(index).value = num2str( oldevent(index).type ); - if isfield(oldevent,'code') - event(index).type = oldevent(index).code; - elseif isfield(oldevent,'value') - event(index).type = oldevent(index).value; - else - event(index).type = 'trigger'; - end; -if header.nTrials > 1 - event(index).sample = oldevent(index).latency-header.nSamplesPre; - event(index).offset = header.nSamplesPre; - else - event(index).sample = oldevent(index).latency; - event(index).offset = 0; - end; - if isfield(oldevent, 'duration') - event(index).duration = oldevent(index).duration; - else - event(index).duration = 0; - end; -end; diff --git a/external/fieldtrip/private/read_eeglabheader.m b/external/fieldtrip/private/read_eeglabheader.m deleted file mode 100644 index 5ab7e60..0000000 --- a/external/fieldtrip/private/read_eeglabheader.m +++ /dev/null @@ -1,112 +0,0 @@ -% read_eeglabheader() - import EEGLAB dataset files -% -% Usage: -% >> header = read_eeglabheader(filename); -% -% Inputs: -% filename - [string] file name -% -% Outputs: -% header - FILEIO toolbox type structure -% -% Author: Arnaud Delorme, SCCN, INC, UCSD, 2008- - -%123456789012345678901234567890123456789012345678901234567890123456789012 - -% Copyright (C) 2008 Arnaud Delorme, SCCN, INC, UCSD, arno@salk.edu -% -% This program is free software; you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation; either version 2 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program; if not, write to the Free Software -% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -% $Log: read_eeglabheader.m,v $ -% Revision 1.6 2009/08/08 04:07:02 josdie -% Bug in Joe's brain fixed. Change to header.nSamplesPre calculation changed back. -% -% Revision 1.5 2009/08/08 03:17:26 josdie -% Fixed bug that was causing hdr.label to have as many labels as there are time points rather than matching the number of channels. -% -% Revision 1.4 2009/08/08 03:05:29 josdie -% Fixed bug in calculation of header.nSamplesPre. -% -% Revision 1.3 2009/07/01 16:08:21 vlalit -% Fixing a bug in converting channel locations to elec struct (reproted by Jakib Scherer) -% -% Revision 1.2 2009/01/23 15:35:46 roboos -% create default channel names if EEG.chanlocs.labels is missing -% -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.2 2008/04/21 18:45:59 roboos -% fixed bug, ori should be orig -% -% Revision 1.1 2008/04/18 14:04:48 roboos -% new implementation by Arno, shoudl be tested -% - -function header = read_eeglabheader(filename) - -if nargin < 1 - help read_eeglabheader; - return; -end; - -if ~isstruct(filename) - load('-mat', filename); -else - EEG = filename; -end; - -header.Fs = EEG.srate; -header.nChans = EEG.nbchan; -header.nSamples = EEG.pnts; -header.nSamplesPre = -EEG.xmin*EEG.srate; -header.nTrials = EEG.trials; -try - header.label = { EEG.chanlocs.labels }'; -catch - warning('creating default channel names'); - for i=1:header.nChans - header.label{i} = sprintf('chan%03d', i); - end -end -ind = 1; -for i = 1:length( EEG.chanlocs ) - if ~isempty(EEG.chanlocs(i).X) - header.elec.label{ind, 1} = EEG.chanlocs(i).labels; - % this channel has a position - header.elec.pnt(ind,1) = EEG.chanlocs(i).X; - header.elec.pnt(ind,2) = EEG.chanlocs(i).Y; - header.elec.pnt(ind,3) = EEG.chanlocs(i).Z; - ind = ind+1; - end; -end; - -% remove data -% ----------- -%if isfield(EEG, 'datfile') -% if ~isempty(EEG.datfile) -% EEG.data = EEG.datfile; -% end; -%else -% EEG.data = 'in set file'; -%end; -EEG.icaact = []; - -header.orig = EEG; diff --git a/external/fieldtrip/private/read_egis_data.m b/external/fieldtrip/private/read_egis_data.m deleted file mode 100755 index 8db5e45..0000000 --- a/external/fieldtrip/private/read_egis_data.m +++ /dev/null @@ -1,121 +0,0 @@ -function dat = read_egis_data(filename, hdr, begtrial, endtrial, chanindx); - -% READ_EGIS_DATA reads the data from an EGI EGIS format file -% -% Use as -% dat = read_egis_data(filename, hdr, begtrial, endtrial, chanindx); -% where -% filename name of the input file -% hdr header structure, see READ_HEADER -% begtrial first trial to read, mutually exclusive with begsample+endsample -% endtrial last trial to read, mutually exclusive with begsample+endsample -% chanindx list with channel indices to read -% -% This function returns a 3-D matrix of size Nchans*Nsamples*Ntrials. -% Note that EGIS session files are defined as always being epoched. -% For session files the trials are organized with the members of each cell grouped -% together. For average files the "trials" (subjects) are organized with the cells -% also grouped together (e.g., "cell1sub1, cell1sub2, ...). -%_______________________________________________________________________ -% -% -% Modified from EGI's EGI Toolbox with permission 2007-06-28 Joseph Dien - -% $Log: read_egis_data.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.6 2008/11/04 08:16:11 roboos -% previous fix did not work, this one should work, thanks to Joe -% -% -% Revision 1.6 2008/11/03 23:28:00 jdien -% Fixed bug in workaround -% -% Revision 1.5 2008/11/03 10:51:00 jdien -% Workaround for fileheader size field overflow for large files -% -% Revision 1.4 2008/04/21 11:44:58 roboos -% preallocate space for the data (thanks to Joseph) -% -% Revision 1.3 2007/12/20 08:21:22 roboos -% changed from returning a 2d to a 3d matrix, thanks to Joseph -% -% Revision 1.2 2007/07/16 07:24:40 roboos -% only read the desired trials, updated documentation -% -% Revision 1.1 2007/07/04 13:22:06 roboos -% initial implementation by Joseph Dien with some corrections by Robert -% - -fh=fopen([filename],'r'); -if fh==-1 - error('wrong filename') -end -fclose(fh); - -[fhdr,chdr,ename,cnames,fcom,ftext] = read_egis_header(filename); -fh=fopen([filename],'r'); -fhdr(1)=fread(fh,1,'int32'); %BytOrd -[str,maxsize,cEndian]=computer; -if fhdr(1)==16909060 - if cEndian == 'B' - endian = 'ieee-be'; - elseif cEndian == 'L' - endian = 'ieee-le'; - end; -elseif fhdr(1)==67305985 - if cEndian == 'B' - endian = 'ieee-le'; - elseif cEndian == 'L' - endian = 'ieee-be'; - end; -else - error('This is not an EGIS average file.'); -end; - -if fhdr(2) == -1 - fileType = 'ave'; -elseif fhdr(2) == 3 - fileType = 'ses'; -else - error('This is not an EGIS file.'); -end; - -dat=zeros(hdr.nChans,hdr.nSamples,endtrial-begtrial+1); - -%read to end of file header -status=fseek(fh,(130+(2*fhdr(18))+(4*fhdr(19))),'bof'); -status=fseek(fh,2,'cof'); -for loop=1:fhdr(18) - temp=fread(fh,80,'char'); - theName=strtok(temp); - theName=strtok(theName,char(0)); - cnames{loop}=deblank(char(theName))'; - status=fseek(fh,fhdr(24+(loop-1))-80,'cof'); -end -fcom=fread(fh,fhdr(20),'char'); -ftext=fread(fh,fhdr(21),'char'); -fpad=fread(fh,fhdr(22),'char'); -status=fseek(fh,-2,'cof'); - -%read to start of desired data -fseek(fh, ((begtrial-1)*hdr.nChans*hdr.nSamples*2), 'cof'); - -for segment=1:(endtrial-begtrial+1) - dat(:,:,segment) = fread(fh, [hdr.nChans, hdr.nSamples],'int16',endian); -end -dat=dat(chanindx, :,:); - -if fileType == 'ave' - dat=dat/fhdr(12); %convert to microvolts -elseif fileType == 'ses' - dat=dat/5; %convert to microvolts (EGIS sess files created by NetStation use a 5 bins per microvolt scaling) -end; - -fclose(fh); diff --git a/external/fieldtrip/private/read_egis_header.m b/external/fieldtrip/private/read_egis_header.m deleted file mode 100755 index de2141c..0000000 --- a/external/fieldtrip/private/read_egis_header.m +++ /dev/null @@ -1,129 +0,0 @@ -function [fhdr,chdr,ename,cnames,fcom,ftext] = read_egis_header(filename) - -% READ_EGIS_HEADER reads the header information from an EGI EGIS format file -% -% Use as -% [fhdr chdr] = read_egia_header(filename) -% with -% fhdr - the file header information -% chdr - the cell header information -% ename - experiment name -% cnames - cell names -% fcom - comments -% ftext - general text -% and -% filename - the name of the data file -%_______________________________________________________________________ -% -% -% Modified from EGI's EGI Toolbox with permission 2007-06-28 Joseph Dien - -% $Log: read_egis_header.m,v $ -% Revision 1.2 2009/01/22 19:54:32 josdie -% Cell names were being truncated if they contained a space. Fixed. -% -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.3 2008/11/04 08:16:11 roboos -% previous fix did not work, this one should work, thanks to Joe -% -% Revision 1.3 2008/11/03 21:31:00 jdien -% Workaround for fileheader size field overflow for large files -% -% Revision 1.2 2008/09/30 07:47:04 roboos -% replaced all occurences of setstr() with char(), because setstr is deprecated by Matlab -% -% Revision 1.1 2007/07/04 13:22:06 roboos -% initial implementation by Joseph Dien with some corrections by Robert -% - -fh=fopen([filename],'r'); -if fh==-1 - error('wrong filename') -end - -%Prep file for reading -fhdr=zeros(1,23); -status=fseek(fh,0,'bof'); - -%Read in fhdr fields. -fhdr(1)=fread(fh,1,'int32'); %BytOrd -[str,maxsize,cEndian]=computer; -if fhdr(1)==16909060 - if cEndian == 'B' - endian = 'ieee-be'; - elseif cEndian == 'L' - endian = 'ieee-le'; - end; -elseif fhdr(1)==67305985 - if cEndian == 'B' - endian = 'ieee-le'; - elseif cEndian == 'L' - endian = 'ieee-be'; - end; -else - error('This is not an EGIS average file.'); -end; - -fhdr(2)=fread(fh,1,'int16',endian); %HdrVer - -if (fhdr(2) ~= -1) && (fhdr(2) ~= 3) - error('This is not an EGIS average file.'); -end; - -fhdr(3)=fread(fh,1,'uint16',endian); %LHeader -fhdr(4)=fread(fh,1,'uint32',endian); %LData -status=fseek(fh,80,'cof'); %Skip ExptNam -fhdr(5:10)=fread(fh,6,'int16',endian); %RunDate and RunTime - -fhdr(11:23)=fread(fh,13,'int16',endian); %Everything else up to LCellHdr - -fhdr(24:(24+fhdr(18)-1))=fread(fh,fhdr(18),'uint16',endian); %LCellHdr for each cell - -%Read in chdr -chdr=zeros(fhdr(18),5); -status=fseek(fh,(4*fhdr(19)),'cof'); -for loop=1:fhdr(18) - chdr(loop,1)=fread(fh,1,'int16',endian); - status=fseek(fh,80,'cof'); - chdr(loop, 2:5)=(fread(fh,4,'int16',endian))'; - lspectot=(chdr(loop,2)*(chdr(loop,5)/2)); - lastcol=(6+lspectot-1); - if lastcol >= 6 - chdr(loop,lastcol)=0; - chdr(loop,6:lastcol)=(fread(fh,lspectot,'int16',endian))'; - end -end - -%Read experiment name -status=fseek(fh,12,'bof'); -tempstr=fread(fh,80,'char'); -ename=char(tempstr); - -%Read cellnames -status=fseek(fh,(130+(2*fhdr(18))+(4*fhdr(19))),'bof'); -status=fseek(fh,2,'cof'); -for loop=1:fhdr(18) - temp=fread(fh,80,'char'); - theName=strtok(temp,0); - cnames{loop}=deblank(char(theName))'; - status=fseek(fh,fhdr(24+(loop-1))-80,'cof'); -end - -%Read comment -%status=fseek(fh,fhdr(3),'bof'); -%status=fseek(fh,-(fhdr(22)+fhdr(21)+fhdr(20)),'cof'); -fcom=fread(fh,fhdr(20),'char'); - -%Read text -%status=fseek(fh,fhdr(3),'bof'); -%status=fseek(fh,-(fhdr(22)+fhdr(21)),'cof'); -ftext=fread(fh,fhdr(21),'char'); - -fclose(fh); diff --git a/external/fieldtrip/private/read_event.m b/external/fieldtrip/private/read_event.m deleted file mode 100644 index df9d3b2..0000000 --- a/external/fieldtrip/private/read_event.m +++ /dev/null @@ -1,1658 +0,0 @@ -function [event] = read_event(filename, varargin) - -% READ_EVENT reads all events from an EEG/MEG dataset and returns -% them in a well defined structure. It is a wrapper around different -% EEG/MEG file importers, directly supported formats are CTF, Neuromag, -% EEP, BrainVision, Neuroscan and Neuralynx. -% -% Use as -% [event] = read_event(filename, ...) -% -% Additional options should be specified in key-value pairs and can be -% 'eventformat' string -% 'header' structure, see READ_HEADER -% 'detectflank' string, can be 'up', 'down' or 'both' (default = 'up') -% 'trigshift' integer, number of samples to shift from flank to detect trigger value (default = 0) -% Furthermore, you can specify optional arguments as key-value pairs for -% filtering the events, e.g. to select only events of a specific type. See -% FILTER_EVENT for more details. -% -% Some data formats have trigger channels that are sampled continuously with -% the same rate as the electrophysiological data. The default is to detect -% only the up-going TTL flanks. The trigger events will correspond with the -% first sample where the TTL value is up. This behaviour can be changed -% using the 'detectflank' option, which also allows for detecting the -% down-going flank or both. In case of detecting the down-going flank, the -% sample number of the event will correspond with the first sample at which -% the TTF went down, and the value will correspond to the TTL value just -% prior to going down. -% -% This function returns an event structure with the following fields -% event.type = string -% event.sample = expressed in samples, the first sample of a recording is 1 -% event.value = number or string -% event.offset = expressed in samples -% event.duration = expressed in samples -% event.timestamp = expressed in timestamp units, which vary over systems (optional) -% -% The event type and sample fields are always defined, other fields can be empty, -% depending on the type of event file. Events are sorted by the sample on -% which they occur. After reading the event structure, you can use the -% following tricks to extract information about those events in which you -% are interested. -% -% Determine the different event types -% unique({event.type}) -% -% Get the index of all trial events -% find(strcmp('trial', {event.type})) -% -% Make a vector with all triggers that occurred on the backpanel -% [event(find(strcmp('backpanel trigger', {event.type}))).value] -% -% Find the events that occurred in trial 26 -% t=26; samples_trials = [event(find(strcmp('trial', {event.type}))).sample]; -% find([event.sample]>samples_trials(t) & [event.sample]char) into uint8=>char to ensure that the -% chars are read as 8 bits and not as extended 16 bit characters. The -% 16 bit handling causes problems on some internationalized OS/Matlab -% combinations. -% -% the help of fread specifies "If the precision is 'char' or 'char*1', MATLAB -% reads characters using the encoding scheme associated with the file. -% See FOPEN for more information". -% -% Revision 1.70 2008/09/25 12:02:22 roboos -% fixed FIL type of events for the new ctf reader (thanks to Vladimir) -% -% Revision 1.69 2008/07/24 08:44:20 roboos -% added initial support for nimh_cortex, not yet complete -% -% Revision 1.68 2008/06/30 15:35:20 roboos -% changed ns_eeg events following a suggestion by Monika Mellem -% -% Revision 1.67 2008/06/20 07:25:56 roboos -% added check for presence of BCI2000 load_bcidat mex file -% -% Revision 1.66 2008/06/18 08:24:33 roboos -% added support for BCI2000 -% -% Revision 1.65 2008/06/18 06:21:59 roboos -% added support for other event.value types (i.e. int/single/double etc) by introducing a wordsize cell-array -% -% Revision 1.64 2008/06/03 15:29:06 jansch -% changed extracting trigger index from original hdr into extracting it from -% the labels, for 4D data -% -% Revision 1.63 2008/05/14 15:58:33 roboos -% typecast to uint32 for tsl and tsh obtained from neuralynx_dma file (*.nrd) -% -% Revision 1.62 2008/05/13 16:48:23 roboos -% added option trigshift (default = 0) for cases where the trigger value should be assigned from a sample not directly after/before the upgoing/downgoing flank -% -% Revision 1.61 2008/05/06 13:29:46 vlalit -% Changed the code to only give a warning and not an error for Biosemi when detectflank = 'both' is specified and change it to 'up'. -% -% Revision 1.60 2008/05/02 14:23:04 vlalit -% Added readers for SPM5 and SPM8 EEG formats -% -% Revision 1.59 2008/04/29 13:58:53 roboos -% switched to read_trigger helper function for ctf, neuromag and bti -% -% Revision 1.58 2008/04/21 11:50:52 roboos -% added support for egi_sbin, thanks to Joseph Dien -% -% Revision 1.57 2008/04/18 14:07:45 roboos -% added eeglab_set -% -% Revision 1.56 2008/02/20 12:32:00 roboos -% allow empty events from buffer -% -% Revision 1.55 2008/02/19 10:08:13 roboos -% added support for fcdc_buffer -% -% Revision 1.54 2008/01/31 20:13:46 roboos -% On line 291 the cell element 4D was added to the existing case -% designed for the handling of 4D_bti data. This is necessary to -% allow this identified filetype to cause execution of this case. -% [thanks to Gavin] -% -% Revision 1.53 2008/01/30 10:40:54 roboos -% moved catevent to seperate function and renamed to appendevent -% -% Revision 1.52 2008/01/30 08:42:13 roboos -% fixed two bugs for ttl.bin in online session with Thilo (both were due to the code being untested) -% -% Revision 1.51 2007/12/20 19:06:57 roboos -% Added filtering base on event number (minnumber and maxnumber), implemented in low level for neuralynx_nev and for the rest of the formats in filter event. If event.number is not present everything still should work as it used to. -% -% Revision 1.50 2007/12/19 15:24:37 roboos -% fixed typo, ttl should be bin -% -% Revision 1.49 2007/12/19 11:25:59 roboos -% fixed typo, added "(", thanks to Mahdi -% -% Revision 1.48 2007/12/19 09:29:29 roboos -% implmenented events for neuralynx_sdma file, and merged it with the dma, ttl and bin formats -% cleaned up the consistent handling of the ttl values for dma, ttl and bin formats -% -% Revision 1.47 2007/12/18 16:57:35 roboos -% use value=trigger instead of ttl (which was a change in the previous commit) to avoid breaking Thilo's scripts -% -% Revision 1.46 2007/12/18 16:51:34 roboos -% added some filtering options -% some minor changes to neuralynx_nev, related to the changes in teh low level function -% added support for neuralynx_bin, which is treated similar as ttl and dma -% -% Revision 1.45 2007/12/17 12:59:52 roboos -% reimplemented the event detection for ttl and dma after discussion with Thilo, also merged the two implementations -% -% Revision 1.44 2007/12/17 08:24:28 roboos -% added support for nexstim_nxe, thanks to Vladimir -% the low-level code has not been tested by myself -% -% Revision 1.43 2007/12/12 16:51:07 roboos -% made a faster implementation for a nev file inside a neuralynx_ds dataset directory, but strings are not supported any more -% -% Revision 1.42 2007/12/12 11:29:06 roboos -% chedk for presence of timestamp prior to trying to concatenate events -% -% Revision 1.41 2007/12/12 11:10:55 roboos -% moved declaration of global variable to the begin of the function -% -% Revision 1.40 2007/12/12 11:09:22 roboos -% added selective reading of events for some files (dma, ttl, bdf, 4d, ctf partially) -% -% Revision 1.39 2007/11/07 10:49:06 roboos -% cleaned up the reading and writing from/to mysql database, using db_xxx helper functions (see mysql directory) -% -% Revision 1.38 2007/11/05 17:02:07 roboos -% some cosmetic changes, nothing functional -% -% Revision 1.37 2007/10/16 12:34:12 roboos -% use recursion to read from multiple event sources -% implemented fcdc_global -% -% Revision 1.36 2007/10/02 16:07:13 roboos -% fixed conversion of negative status values and reasignment of bit24 (thanks to Philip) -% -% Revision 1.35 2007/10/02 09:28:06 roboos -% removed teh double rtepresentatino of trigger for bdf, since STATUS is also good enough -% -% Revision 1.34 2007/10/02 09:13:43 roboos -% biosemi_bdf: make sure that the sign bit is propperly re-inserted as bit24 for the status channel -% -% Revision 1.33 2007/10/01 13:43:21 roboos -% reimplemented the biosemi bdf trigger detection, now also for the status bits -% -% Revision 1.32 2007/09/13 09:49:34 roboos -% moved declaration of persistent variale to beginning -% added inactive piece of code for bdf (see NICI version) -% -% Revision 1.31 2007/08/21 17:00:57 chrhes -% updated some documentation, removed the commented-out section of code to do -% with the event filtering options; these are used "as is" in the call to -% FILTER_EVENT at the end of the function -% -% Revision 1.30 2007/08/01 12:24:22 roboos -% added filename as argument to read_shm_event, added comments, disabled unused -% keyval filtering arguments -% -% Revision 1.29 2007/08/01 09:57:01 roboos -% moved all code related to ctf shared memory to seperate functions -% -% Revision 1.28 2007/07/30 12:14:59 roboos -% updated documentation for filtering -% implemented filtering for ctf_shm -% -% Revision 1.27 2007/07/27 12:17:20 roboos -% fixed big in ctf raw trigger channel, which caused a trigger with value=1 not -% to be detected implemented support for ctf_shm -% reuse the file header if specified as optional input argument and do not read -% again -% -% Revision 1.26 2007/07/04 13:20:51 roboos -% added support for egi_egis/egia, thanks to Joseph Dien -% -% Revision 1.25 2007/06/13 13:33:54 roboos -% changed the mysql code to reflect the updated event table structure -% removed type and subtype from the insert query -% added a call to filter_event at the end of the function -% -% Revision 1.24 2007/06/13 09:57:32 roboos -% only test for presence of fields if event is not empty -% fixed bug in mysql, in case event table is empty -% -% Revision 1.23 2007/06/13 08:06:21 roboos -% updated help -% -% Revision 1.22 2007/06/12 19:35:52 roboos -% implemented support for reading events from mysql database -% -% Revision 1.21 2007/06/11 13:52:24 roboos -% split the event reading from neuralynx_dma and neuralynx_ttl -% read timestamps from tsl/tsh files, optionally use pre-specified header to -% correct the sample numbers -% -% Revision 1.20 2007/06/07 12:44:28 chrhes -% updated some documentation -% -% Revision 1.19 2007/06/06 21:55:37 chrhes -% fixed a small bug to do with a string comparison -% -% Revision 1.18 2007/06/06 18:19:07 chrhes -% added initial implementation of reading events from the serial port -% -% Revision 1.17 2007/06/06 07:12:48 roboos -% switched to using filetype_check_uri for detection and parsing of filename -% -% Revision 1.16 2007/05/31 09:53:21 roboos -% implemented reading events from a plain matlab file -% -% Revision 1.15 2007/05/31 09:15:13 roboos -% added placeholder for tcpsocket -% -% Revision 1.14 2007/05/15 15:01:44 roboos -% changed handling of the seperate brainvision header and marker file -% -% Revision 1.13 2006/12/13 15:40:10 roboos -% renamed Parallel_in into ttl for neuralynx_dma -% renamed the function read_neuralynx_event into read_neuralynx_nev (consistent -% with the file extension) -% -% Revision 1.12 2006/12/04 10:37:27 roboos -% added support for ns_avg -% -% Revision 1.11 2006/09/18 21:51:38 roboos -% implemented support for fcdc_matbin, i.e. a dataset consisting of a matlab -% file with header and events and a seperate binary datafile -% -% Revision 1.10 2006/09/18 14:22:54 roboos -% implemented support for 4D-BTi dataformat -% -% Revision 1.9 2006/08/28 10:13:03 roboos -% use seperate filetype_check_extension function instead of subfunction, removed -% subfunction -% -% Revision 1.8 2006/07/26 07:51:33 roboos -% fixed bug for brainvision_vmrk in case second field is empty (thanks to -% Stephan Bickel) -% -% Revision 1.7 2006/06/26 08:46:37 roboos -% read stim channels from CTF as continuous -% -% Revision 1.6 2006/06/22 07:54:34 roboos -% do not read the complete data for ns_cnt but only the header (includes the -% events), thanks to Gijs -% -% Revision 1.5 2006/06/20 11:23:00 roboos -% fixed bug for ctf, sensSype was moved to hdr.orig -% -% Revision 1.4 2006/06/19 10:32:16 roboos -% added documentation -% -% Revision 1.3 2006/06/19 08:14:17 roboos -% updated documentation -% -% Revision 1.2 2006/06/07 10:16:47 roboos -% changed one occurence of read_fcdc_header into read_header -% -% Revision 1.1 2006/06/07 09:32:20 roboos -% new implementation based on the read_fcdc_xxx functions, now with -% variable (key-val) input arguments, changed the control structure -% in the rpobram (switch instead of ifs), allow the user to specify -% the file format, allow the user to specify either a sample selection -% or a block selection. The reading functionality should not have -% changed compared to the read_fcdc_xxx versions. -% - -persistent sock % for fcdc_tcp - -global event_queue % for fcdc_global -persistent db_blob % for fcdc_mysql -if isempty(db_blob) - db_blob = 0; -end - -if iscell(filename) - % use recursion to read from multiple event sources - event = []; - for i=1:numel(filename) - tmp = read_event(filename{i}, varargin{:}); - event = appendevent(event(:), tmp(:)); - end - return -end - -% get the options -eventformat = keyval('eventformat', varargin); -hdr = keyval('header', varargin); -detectflank = keyval('detectflank', varargin); % up, down or both -trigshift = keyval('trigshift', varargin); % default is assigned in subfunction -headerformat = keyval('headerformat', varargin); -dataformat = keyval('dataformat', varargin); - -% this allows to read only events in a certain range, supported for selected data formats only -flt_type = keyval('type', varargin); -flt_value = keyval('value', varargin); -flt_minsample = keyval('minsample', varargin); -flt_maxsample = keyval('maxsample', varargin); -flt_mintimestamp = keyval('mintimestamp', varargin); -flt_maxtimestamp = keyval('maxtimestamp', varargin); -flt_minnumber = keyval('minnumber', varargin); -flt_maxnumber = keyval('maxnumber', varargin); - - -% determine the filetype -if isempty(eventformat) - eventformat = filetype(filename); -end - -% default is to search only for rising or up-going flanks -if isempty(detectflank) - detectflank = 'up'; -end - -switch eventformat - case 'brainvision_vhdr' - % read the headerfile belonging to the dataset and try to determine the corresponding markerfile - eventformat = 'brainvision_vmrk'; - hdr = read_brainvision_vhdr(filename); - % replace the filename with the filename of the markerfile - if ~isfield(hdr, 'MarkerFile') || isempty(hdr.MarkerFile) - filename = []; - else - [p, f, e] = fileparts(filename); - filename = fullfile(p, hdr.MarkerFile); - end -end - -% start with an empty event structure -event = []; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% read the events with the low-level reading function -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -switch eventformat - - case 'fcdc_global' - event = event_queue; - - case {'4d' '4d_pdf', '4d_m4d', '4d_xyz'} - if isempty(hdr) - hdr = read_header(filename); - end - % add the trials to the event structure - for i=1:hdr.nTrials - event(end+1).type = 'trial'; - event(end ).sample = (i-1)*hdr.nSamples + 1; - event(end ).value = []; - event(end ).offset = -hdr.nSamplesPre; - event(end ).duration = hdr.nSamples; - end - % read the trigger channel and do flank detection - trgindx = match_str(hdr.label, 'TRIGGER'); - if isfield(hdr, 'orig') && isfield(hdr.orig, 'config_data') && strcmp(hdr.orig.config_data.site_name, 'Glasgow'), - trigger = read_trigger(filename, 'header', hdr, 'begsample', flt_minsample, 'endsample', flt_maxsample, 'chanindx', trgindx, 'detectflank', detectflank, 'trigshift', trigshift,'fix4dglasgow',1); - else - trigger = read_trigger(filename, 'header', hdr, 'begsample', flt_minsample, 'endsample', flt_maxsample, 'chanindx', trgindx, 'detectflank', detectflank, 'trigshift', trigshift,'fix4dglasgow',0); - end - event = appendevent(event, trigger); - - respindx = match_str(hdr.label, 'RESPONSE'); - if ~isempty(respindx) - response = read_trigger(filename, 'header', hdr, 'begsample', flt_minsample, 'endsample', flt_maxsample, 'chanindx', respindx, 'detectflank', detectflank, 'trigshift', trigshift); - event = appendevent(event, response); - end - - case 'bci2000_dat' - % this requires the load_bcidat mex file to be present on the path - hastoolbox('BCI2000', 1); - if isfield(hdr.orig, 'signal') && isfield(hdr.orig, 'states') - % assume that the complete data is stored in the header, this speeds up subsequent read operations - signal = hdr.orig.signal; - states = hdr.orig.states; - parameters = hdr.orig.parameters; - total_samples = hdr.orig.total_samples; - else - [signal, states, parameters, total_samples] = load_bcidat(filename); - end - - list = fieldnames(states); - % loop over all states and detect the flanks, the following code was taken from read_trigger - for i=1:length(list) - channel = list{i}; - trig = double(getfield(states, channel)); - pad = trig(1); - trigshift = 0; - begsample = 1; - - switch detectflank - case 'up' - % convert the trigger into an event with a value at a specific sample - for j=find(diff([pad trig(:)'])>0) - event(end+1).type = channel; - event(end ).sample = j + begsample - 1; % assign the sample at which the trigger has gone down - event(end ).value = trig(j+trigshift); % assign the trigger value just _after_ going up - end - case 'down' - % convert the trigger into an event with a value at a specific sample - for j=find(diff([pad trig(:)'])<0) - event(end+1).type = channel; - event(end ).sample = j + begsample - 1; % assign the sample at which the trigger has gone down - event(end ).value = trig(j-1-trigshift); % assign the trigger value just _before_ going down - end - case 'both' - % convert the trigger into an event with a value at a specific sample - for j=find(diff([pad trig(:)'])>0) - event(end+1).type = [channel '_up']; % distinguish between up and down flank - event(end ).sample = j + begsample - 1; % assign the sample at which the trigger has gone down - event(end ).value = trig(j+trigshift); % assign the trigger value just _after_ going up - end - % convert the trigger into an event with a value at a specific sample - for j=find(diff([pad trig(:)'])<0) - event(end+1).type = [channel '_down']; % distinguish between up and down flank - event(end ).sample = j + begsample - 1; % assign the sample at which the trigger has gone down - event(end ).value = trig(j-1-trigshift); % assign the trigger value just _before_ going down - end - otherwise - error('incorrect specification of ''detectflank'''); - end - end - - case {'besa_avr', 'besa_swf'} - if isempty(hdr) - hdr = read_header(filename); - end - event(end+1).type = 'average'; - event(end ).sample = 1; - event(end ).duration = hdr.nSamples; - event(end ).offset = -hdr.nSamplesPre; - event(end ).value = []; - - case {'biosemi_bdf', 'bham_bdf'} - % read the header, required to determine the stimulus channels and trial specification - if isempty(hdr) - hdr = read_header(filename); - end - - % specify the range to search for triggers, default is the complete file - if ~isempty(flt_minsample) - begsample = flt_minsample; - else - begsample = 1; - end - if ~isempty(flt_maxsample) - endsample = flt_maxsample; - else - endsample = hdr.nSamples*hdr.nTrials; - end - - if ~strcmp(detectflank, 'up') - if strcmp(detectflank, 'both') - warning('only up-going flanks are supported for Biosemi'); - detectflank = 'up'; - else - error('only up-going flanks are supported for Biosemi'); - % FIXME the next section on trigger detection should be merged with the - % READ_CTF_TRIGGER (which also does masking with bit-patterns) into the - % READ_TRIGGER function - end - end - - % find the STATUS channel and read the values from it - schan = find(strcmpi(hdr.label,'STATUS')); - sdata = read_data(filename, 'header', hdr, 'begsample', begsample, 'endsample', endsample, 'chanindx', schan); - - % find indices of negative numbers - bit24i = find(sdata < 0); - % make number positive and preserve bits 0-22 - sdata(bit24i) = bitcmp(abs(sdata(bit24i))-1,24); - % re-insert the sign bit on its original location, i.e. bit24 - sdata(bit24i) = sdata(bit24i)+(2^(24-1)); - % typecast the data to ensure that the status channel is represented in 32 bits - sdata = uint32(sdata); - - byte1 = 2^8 - 1; - byte2 = 2^16 - 1 - byte1; - byte3 = 2^24 - 1 - byte1 - byte2; - - % get the respective status and trigger bits - trigger = bitand(sdata, bitor(byte1, byte2)); % contained in the lower two bytes - epoch = int8(bitget(sdata, 16+1)); - cmrange = int8(bitget(sdata, 20+1)); - battery = int8(bitget(sdata, 22+1)); - - % determine when the respective status bits go up or down - flank_trigger = diff([0 trigger]); - flank_epoch = diff([0 epoch ]); - flank_cmrange = diff([0 cmrange]); - flank_battery = diff([0 battery]); - - for i=find(flank_trigger>0) - event(end+1).type = 'STATUS'; - event(end ).sample = i + begsample - 1; - event(end ).value = double(trigger(i)); - end - - for i=find(flank_epoch==1) - event(end+1).type = 'Epoch'; - event(end ).sample = i; - end - - for i=find(flank_cmrange==1) - event(end+1).type = 'CM_in_range'; - event(end ).sample = i; - end - - for i=find(flank_cmrange==-1) - event(end+1).type = 'CM_out_of_range'; - event(end ).sample = i; - end - - for i=find(flank_battery==1) - event(end+1).type = 'Battery_low'; - event(end ).sample = i; - end - - for i=find(flank_battery==-1) - event(end+1).type = 'Battery_ok'; - event(end ).sample = i; - end - - case 'brainvision_vmrk' - fid=fopen(filename,'rt'); - if fid==-1, - error('cannot open BrainVision marker file') - end - line = []; - while ischar(line) || isempty(line) - line = fgetl(fid); - if ~isempty(line) && ~(isnumeric(line) && line==-1) - if strncmpi(line, 'Mk', 2) - % this line contains a marker - tok = tokenize(line, '=', 0); % do not squeeze repetitions of the seperator - if length(tok)~=2 - warning('skipping unexpected formatted line in BrainVision marker file'); - else - % the line looks like "MkXXX=YYY", which is ok - % the interesting part now is in the YYY, i.e. the second token - tok = tokenize(tok{2}, ',', 0); % do not squeeze repetitions of the seperator - if isempty(tok{1}) - tok{1} = []; - end - if isempty(tok{2}) - tok{2} = []; - end - event(end+1).type = tok{1}; - event(end ).value = tok{2}; - event(end ).sample = str2num(tok{3}); - event(end ).duration = str2num(tok{4}); - end - end - end - end - fclose(fid); - - case 'ced_son' - % check that the required low-level toolbox is available - hastoolbox('neuroshare', 1); - orig = read_ced_son(filename,'readevents','yes'); - event = struct('type', {orig.events.type},... - 'sample', {orig.events.sample},... - 'value', {orig.events.value},... - 'offset', {orig.events.offset},... - 'duration', {orig.events.duration}); - - case {'ctf_ds', 'ctf_meg4', 'ctf_res4', 'ctf_old'} - % obtain the dataset name - if filetype(filename, 'ctf_meg4') || filetype(filename, 'ctf_res4') - filename = fileparts(filename); - end - [path, name, ext] = fileparts(filename); - headerfile = fullfile(path, [name ext], [name '.res4']); - datafile = fullfile(path, [name ext], [name '.meg4']); - classfile = fullfile(path, [name ext], 'ClassFile.cls'); - markerfile = fullfile(path, [name ext], 'MarkerFile.mrk'); - - % in case ctf_old was specified as eventformat, the other reading functions should also know about that - if strcmp(eventformat, 'ctf_old') - dataformat = 'ctf_old'; - headerformat = 'ctf_old'; - end - - % read the header, required to determine the stimulus channels and trial specification - if isempty(hdr) - hdr = read_header(headerfile, 'headerformat', headerformat); - end - - try - % read the trigger codes from the STIM channel, usefull for (pseudo) continuous data - % this splits the trigger channel into the lowers and highest 16 bits, - % corresponding with the front and back panel of the electronics cabinet at the Donders Centre - [backpanel, frontpanel] = read_ctf_trigger(filename); - for i=find(backpanel(:)') - event(end+1).type = 'backpanel trigger'; - event(end ).sample = i; - event(end ).value = backpanel(i); - end - for i=find(frontpanel(:)') - event(end+1).type = 'frontpanel trigger'; - event(end ).sample = i; - event(end ).value = frontpanel(i); - end - end - - % determine the trigger channels from the header - if isfield(hdr, 'orig') && isfield(hdr.orig, 'sensType') - origSensType = hdr.orig.sensType; - elseif isfield(hdr, 'orig') && isfield(hdr.orig, 'res4') - origSensType = [hdr.orig.res4.senres.sensorTypeIndex]; - else - origSensType = []; - end - % meg channels are 5, refmag 0, refgrad 1, adcs 18, trigger 11, eeg 9 - trigchanindx = find(origSensType==11); - if ~isempty(trigchanindx) - % read the trigger channel and do flank detection - trigger = read_trigger(filename, 'header', hdr, 'begsample', flt_minsample, 'endsample', flt_maxsample, 'chanindx', trigchanindx, 'dataformat', dataformat, 'detectflank', detectflank, 'trigshift', trigshift, 'fixctf', 1); - event = appendevent(event, trigger); - end - - % make an event for each trial as defined in the header - for i=1:hdr.nTrials - event(end+1).type = 'trial'; - event(end ).sample = (i-1)*hdr.nSamples + 1; - event(end ).offset = -hdr.nSamplesPre; - event(end ).duration = hdr.nSamples; - event(end ).value = []; - end - - % read the classification file and make an event for each classified trial - [condNumbers,condLabels] = read_ctf_cls(classfile); - if ~isempty(condNumbers) - Ncond = length(condLabels); - for i=1:Ncond - for j=1:length(condNumbers{i}) - event(end+1).type = 'classification'; - event(end ).value = condLabels{i}; - event(end ).sample = (condNumbers{i}(j)-1)*hdr.nSamples + 1; - event(end ).offset = -hdr.nSamplesPre; - event(end ).duration = hdr.nSamples; - end - end - end - - if exist(markerfile,'file') - % read the marker file and make an event for each marker - % this depends on the readmarkerfile function that I got from Tom Holroyd - % I have not tested this myself extensively, since at the FCDC we - % don't use the marker files - mrk = readmarkerfile(filename); - for i=1:mrk.number_markers - for j=1:mrk.number_samples(i) - % determine the location of the marker, expressed in samples - trialnum = mrk.trial_times{i}(j,1); - synctime = mrk.trial_times{i}(j,2); - begsample = (trialnum-1)*hdr.nSamples + 1; % of the trial, relative to the start of the datafile - endsample = (trialnum )*hdr.nSamples; % of the trial, relative to the start of the datafile - offset = round(synctime*hdr.Fs); % this is the offset (in samples) relative to time t=0 for this trial - offset = offset + hdr.nSamplesPre; % and time t=0 corrsponds with the nSamplesPre'th sample - % store this marker as an event - event(end+1).type = mrk.marker_names{i}; - event(end ).value = []; - event(end ).sample = begsample + offset; - event(end ).duration = 0; - event(end ).offset = offset; - end - end - end - - case 'ctf_shm' - % contact Robert Oostenveld if you are interested in real-time acquisition on the CTF system - % read the events from shared memory - event = read_shm_event(filename, varargin{:}); - - case 'eeglab_set' - event = read_eeglabevent(filename, 'header', hdr); - - case 'spmeeg_mat' - event = read_spmeeg_event(filename, 'header', hdr); - - case 'eep_avr' - % check that the required low-level toolbox is available - hastoolbox('eeprobe', 1); - % the headerfile and datafile are the same - if isempty(hdr) - hdr = read_header(filename); - end - event(end+1).type = 'average'; - event(end ).sample = 1; - event(end ).duration = hdr.nSamples; - event(end ).offset = -hdr.nSamplesPre; - event(end ).value = []; - - case 'eep_cnt' - % check that the required low-level toolbox is available - hastoolbox('eeprobe', 1); - % try to read external trigger file in EEP format - trgfile = [filename(1:(end-3)), 'trg']; - if exist(trgfile, 'file') - if isempty(hdr) - hdr = read_header(filename); - end - tmp = read_eep_trg(trgfile); - % translate the EEProbe trigger codes to events - for i=1:length(tmp) - event(i).type = 'trigger'; - event(i).sample = round((tmp(i).time/1000) * hdr.Fs) + 1; % convert from ms to samples - event(i).value = tmp(i).code; - event(i).offset = 0; - event(i).duration = 0; - end - else - warning('no triggerfile was found'); - end - - case 'egi_egis' - if isempty(hdr) - hdr = read_header(filename); - end - fhdr = hdr.orig.fhdr; - chdr = hdr.orig.chdr; - ename = hdr.orig.ename; - cnames = hdr.orig.cnames; - fcom = hdr.orig.fcom; - ftext = hdr.orig.ftext; - eventCount=0; - for cell=1:fhdr(18) - for trial=1:chdr(cell,2) - eventCount=eventCount+1; - event(eventCount).type = 'trial'; - event(eventCount).sample = (eventCount-1)*hdr.nSamples + 1; - event(eventCount).offset = -hdr.nSamplesPre; - event(eventCount).duration = hdr.nSamples; - event(eventCount).value = cnames{cell}; - end - end - - case 'egi_egia' - if isempty(hdr) - hdr = read_header(filename); - end - fhdr = hdr.orig.fhdr; - chdr = hdr.orig.chdr; - ename = hdr.orig.ename; - cnames = hdr.orig.cnames; - fcom = hdr.orig.fcom; - ftext = hdr.orig.ftext; - eventCount=0; - for cell=1:fhdr(18) - for subject=1:chdr(cell,2) - eventCount=eventCount+1; - event(eventCount).type = 'trial'; - event(eventCount).sample = (eventCount-1)*hdr.nSamples + 1; - event(eventCount).offset = -hdr.nSamplesPre; - event(eventCount).duration = hdr.nSamples; - event(eventCount).value = ['S' sprintf('%03d',subject) cnames{cell}]; - end - end - - case 'egi_sbin' - if ~exist('segHdr','var') - [EventCodes, segHdr, eventData] = read_sbin_events(filename); - end - if ~exist('header_array','var') - [header_array, CateNames, CatLengths, preBaseline] = read_sbin_header(filename); - end - if isempty(hdr) - hdr = read_header(filename,'headerformat','egi_sbin'); - end - version = header_array(1); - unsegmented = ~mod(version, 2); - - eventCount=0; - if unsegmented - tmp = zeros(1,size(eventData,2)); - for k = 1:size(eventData,1) - sel = find(eventData(k,:)==1 & [0 eventData(k,1:end-1)==0]); - tmp(sel) = k; - end - sel = find(tmp); - for k = 1:length(sel) - event(k).sample = sel(k); - event(k).offset = []; - event(k).duration = 0; - event(k).type = 'trigger'; - event(k).value = char(EventCodes(tmp(sel(k)),:)); - end - else - for theEvent=1:size(eventData,1) - for segment=1:hdr.nTrials - if any(eventData(theEvent,((segment-1)*hdr.nSamples +1):segment*hdr.nSamples)) - eventCount=eventCount+1; - event(eventCount).sample = (segment-1)*hdr.nSamples + 1; - event(eventCount).offset = -min(find(eventData(theEvent,((segment-1)*hdr.nSamples +1):segment*hdr.nSamples)))+1; - event(eventCount).duration = length(find(eventData(theEvent,((segment-1)*hdr.nSamples +1):segment*hdr.nSamples )>0))-1; - if event(eventCount).duration == 0 - event(eventCount).type = 'trigger'; - else - event(eventCount).type = 'trial'; - end; - event(eventCount).value = char(EventCodes(theEvent,:)); - end - end - end - end - - for segment=1:hdr.nTrials % cell information - eventCount=eventCount+1; - event(eventCount).type = 'trial'; - event(eventCount).sample = (segment-1)*hdr.nSamples + 1; - event(eventCount).offset = -hdr.nSamplesPre; - event(eventCount).duration = hdr.nSamples; - if unsegmented, - event(eventCount).value = []; - else - event(eventCount).value = char([CateNames{segHdr(segment,1)}(1:CatLengths(segHdr(segment,1)))]); - end - end - - case 'fcdc_buffer' - % read from a networked buffer for realtime analysis - [host, port] = filetype_check_uri(filename); - - evt = buffer('get_evt', [], host, port); % indices should be zero-offset - % FIXME it should be possible to specify event numbers - - type = { - 'char' - 'uint8' - 'uint16' - 'uint32' - 'uint64' - 'int8' - 'int16' - 'int32' - 'int64' - 'single' - 'double' - }; - - wordsize = { - 1 % 'char' - 1 % 'uint8' - 2 % 'uint16' - 4 % 'uint32' - 8 % 'uint64' - 1 % 'int8' - 2 % 'int16' - 4 % 'int32' - 8 % 'int64' - 4 % 'single' - 8 % 'double' - }; - - for i=1:length(evt) - % convert the field "type" into the Matlab representation - this_type = type{evt(i).type_type+1}; - this_size = wordsize{evt(i).type_type+1} * evt(i).type_numel; - sel = 1:this_size; - if strcmp(this_type, 'char') - event(i).type = char(evt(i).buf(sel)); - else - event(i).type = typecast(evt(i).buf(sel), this_type); - end - - % convert the field "value" into the Matlab representation - this_type = type{evt(i).value_type+1}; - this_size = wordsize{evt(i).value_type+1} * evt(i).value_numel; - sel = sel(end) + (1:this_size); - if strcmp(this_type, 'char') - event(i).value = char(evt(i).buf(sel)); - else - event(i).value = typecast(evt(i).buf(sel), this_type); - end - - % the other fields are simple, because they have a fixed type and only a single elements - event(i).sample = evt(i).sample; - event(i).offset = evt(i).offset; - event(i).duration = evt(i).duration; - end - - case 'fcdc_matbin' - % this is multiplexed data in a *.bin file, accompanied by a matlab file containing the header and event - [path, file, ext] = fileparts(filename); - filename = fullfile(path, [file '.mat']); - % read the events from the Matlab file - tmp = load(filename, 'event'); - event = tmp.event; - - - case 'fcdc_fifo' - - - fifo = filetype_check_uri(filename); - - if ~exist(fifo,'file') - warning('the FIFO %s does not exist; attempting to create it', fifo); - system(sprintf('mkfifo -m 0666 %s',fifo)); - end - - fid = fopen(fifo, 'r'); - msg = fread(fid, inf, 'uint8'); - fclose(fid); - - try - event = mxDeserialize(uint8(msg)); - catch - warning(lasterr); - end - - case 'fcdc_tcp' - % requires tcp/udp/ip-toolbox - hastoolbox('TCP_UDP_IP', 1); - [host, port] = filetype_check_uri(filename); - if isempty(sock) - sock=pnet('tcpsocket',port); - end - con = pnet(sock, 'tcplisten'); - if con~=-1 - try - pnet(con,'setreadtimeout',10); - % read packet - msg=pnet(con,'readline'); %,1000,'uint8','network'); - if ~isempty(msg) - event = mxDeserialize(uint8(str2num(msg))); - end -% catch -% warning(lasterr); - end - pnet(con,'close'); - end - con = []; - - case 'fcdc_udp' - % requires tcp/udp/ip-toolbox - hastoolbox('TCP_UDP_IP', 1); - [host, port] = filetype_check_uri(filename); - try - % read from localhost - udp=pnet('udpsocket',port); - % Wait/Read udp packet to read buffer - len=pnet(udp,'readpacket'); - if len>0, - % if packet larger then 1 byte then read maximum of 1000 doubles in network byte order - msg=pnet(udp,'read',1000,'uint8'); - if ~isempty(msg) - event = mxDeserialize(uint8(msg)); - end - end - catch - warning(lasterr); - end - % On break or error close connection - pnet(udp,'close'); - - case 'fcdc_serial' - % serial port on windows or linux platform - [port, opt] = filetype_check_uri(filename); - % determine whether any serial port objects are already associated with the - % target serial port - s = []; - temp = instrfind; - if isa(temp,'instrument') - % find all serial ports - i1 = strcmpi({temp(:).Type},'serial'); - if any(i1) - % find all serial ports whose name matches that of the specified port - i2 = strmatch(lower(port),lower({temp(find(i1)).Name})); - % set s to the (first) matching port if present (and open if necessary) - if ~isempty(i2) - s = temp(i2(1)); - if ~strcmp(s.Status,'open'), fopen(s); end; - end - end - end - % create, configure a serial port object if necessary and open the port - if ~isa(s,'serial') - s = serial(port); - if ~isempty(opt) && iscell(opt), s = set(s,opt); end; - fopen(s); - end - % try to read a message from the serial port - msg = []; - % FIXME: this currently assumes that all messages are terminated by the - % "newline" character (ascii character 10) - try - msg = fscanf(s,'%s\n'); - end; - % convert message to event structure - event = msg2struct(msg); - - case 'fcdc_mysql' - % read from a MySQL server listening somewhere else on the network - db_open(filename); - if db_blob - event = db_select_blob('fieldtrip.event', 'msg'); - else - event = db_select('fieldtrip.event', {'type', 'value', 'sample', 'offset', 'duration'}); - end - - case 'itab_raw' - error('suppoport for events in this fileformat is not yet implemented') - - case 'matlab' - % read the events from a normal Matlab file - tmp = load(filename, 'event'); - event = tmp.event; - - case {'mpi_ds', 'mpi_dap'} - if isempty(hdr) - hdr = read_header(filename); - end - % determine the DAP files that compromise this dataset - if isdir(filename) - ls = dir(filename); - dapfile = {}; - for i=1:length(ls) - if ~isempty(regexp(ls(i).name, '.dap$', 'once' )) - dapfile{end+1} = fullfile(filename, ls(i).name); - end - end - dapfile = sort(dapfile); - elseif iscell(filename) - dapfile = filename; - else - dapfile = {filename}; - end - % assume that each DAP file is accompanied by a dat file - % read the trigger values from the separate dat files - trg = []; - for i=1:length(dapfile) - datfile = [dapfile{i}(1:(end-4)) '.dat']; - trg = cat(1, trg, textread(datfile, '', 'headerlines', 1)); - end - % construct a event structure, one 'trialcode' event per trial - for i=1:length(trg) - event(i).type = 'trialcode'; % string - event(i).sample = (i-1)*hdr.nSamples + 1; % expressed in samples, first sample of file is 1 - event(i).value = trg(i); % number or string - event(i).offset = 0; % expressed in samples - event(i).duration = hdr.nSamples; % expressed in samples - end - - - case {'neuromag_fif' 'neuromag_mne' 'neuromag_mex'} - if strcmp(eventformat, 'neuromag_fif') - % the default is to use the MNE reader for fif files - eventformat = 'neuromag_mne'; - end - if strcmp(eventformat, 'neuromag_mex') - % check that the required low-level toolbox is available - hastoolbox('meg-pd', 1); - if isempty(headerformat), headerformat = eventformat; end - if isempty(dataformat), dataformat = eventformat; end - elseif strcmp(eventformat, 'neuromag_mne') - % check that the required low-level toolbox is available - hastoolbox('mne', 1); - if isempty(headerformat), headerformat = eventformat; end - if isempty(dataformat), dataformat = eventformat; end - end - - if isempty(hdr) - hdr = read_header(filename, 'headerformat', headerformat); - end - - % note below we've had to include some chunks of code that are only - % called if the file is an averaged file, or if the file is continuous. - % These are defined in hdr by read_header for neuromag_mne, but do not - % exist for neuromag_fif, hence we run the code anyway if the fields do - % not exist (this is what happened previously anyway). - - if strcmp(eventformat, 'neuromag_mex') - iscontinuous = 1; - isaverage = 0; - isepoched = 0; - elseif strcmp(eventformat, 'neuromag_mne') - iscontinuous = hdr.orig.iscontinuous; - isaverage = hdr.orig.isaverage; - isepoched = hdr.orig.isepoched; - end - - - - if iscontinuous - analogindx = find(strcmp(chantype(hdr), 'analog trigger')); - binaryindx = find(strcmp(chantype(hdr), 'digital trigger')); - - - if isempty(binaryindx)&&isempty(analogindx) - % included in case of problems with older systems and MNE reader: - % use a predefined set of channel names - binary = {'STI 014', 'STI 015', 'STI 016'}; - binaryindx = match_str(hdr.label, binary); - end - - if ~isempty(binaryindx) - trigger = read_trigger(filename, 'header', hdr, 'dataformat', dataformat, 'begsample', flt_minsample, 'endsample', flt_maxsample, 'chanindx', binaryindx, 'detectflank', detectflank, 'trigshift', trigshift, 'fixneuromag', 0); - event = appendevent(event, trigger); - end - if ~isempty(analogindx) - % add the triggers to the event structure based on trigger channels with the name "STI xxx" - % there are some issues with noise on these analog trigger - % channels, on older systems only - % read the trigger channel and do flank detection - trigger = read_trigger(filename, 'header', hdr, 'dataformat', dataformat, 'begsample', flt_minsample, 'endsample', flt_maxsample, 'chanindx', analogindx, 'detectflank', detectflank, 'trigshift', trigshift, 'fixneuromag', 1); - event = appendevent(event, trigger); - end - - if hdr.nTrials>1 - % make an event for each trial as defined in the header - for i=1:hdr.nTrials - event(end+1).type = 'trial'; - event(end ).sample = (i-1)*hdr.nSamples + 1; - event(end ).offset = -hdr.nSamplesPre; - event(end ).duration = hdr.nSamples; - event(end ).value = []; - end - end - - elseif isaverage - % the length of each average can be variable - nsamples = zeros(1, length(hdr.orig.evoked)); - for i=1:length(hdr.orig.evoked) - nsamples(i) = size(hdr.orig.evoked(i).epochs, 2); - end - begsample = cumsum([1 nsamples]); - for i=1:length(hdr.orig.evoked) - event(end+1).type = 'average'; - event(end ).sample = begsample(i); - event(end ).value = hdr.orig.evoked(i).comment; % this is a descriptive string - event(end ).offset = hdr.orig.evoked(i).first; - event(end ).duration = hdr.orig.evoked(i).last - hdr.orig.evoked(i).first + 1; - end - - elseif isepoched - error('Support for epoched *.fif data is not yet implemented.') - end - - - case {'neuralynx_ttl' 'neuralynx_bin' 'neuralynx_dma' 'neuralynx_sdma'} - if isempty(hdr) - hdr = read_header(filename); - end - - % specify the range to search for triggers, default is the complete file - if ~isempty(flt_minsample) - begsample = flt_minsample; - else - begsample = 1; - end - if ~isempty(flt_maxsample) - endsample = flt_maxsample; - else - endsample = hdr.nSamples*hdr.nTrials; - end - - if strcmp(eventformat, 'neuralynx_dma') - % read the Parallel_in channel from the DMA log file - ttl = read_neuralynx_dma(filename, begsample, endsample, 'ttl'); - elseif strcmp(eventformat, 'neuralynx_sdma') - % determine the seperate files with the trigger and timestamp information - [p, f, x] = fileparts(filename); - ttlfile = fullfile(filename, [f '.ttl.bin']); - tslfile = fullfile(filename, [f '.tsl.bin']); - tshfile = fullfile(filename, [f '.tsh.bin']); - if ~exist(ttlfile) && ~exist(tslfile) && ~exist(tshfile) - % perhaps it is an old splitted dma dataset? - ttlfile = fullfile(filename, [f '.ttl']); - tslfile = fullfile(filename, [f '.tsl']); - tshfile = fullfile(filename, [f '.tsh']); - end - if ~exist(ttlfile) && ~exist(tslfile) && ~exist(tshfile) - % these files must be present in a splitted dma dataset - error('could not locate the individual ttl, tsl and tsh files'); - end - % read the trigger values from the seperate file - ttl = read_neuralynx_bin(ttlfile, begsample, endsample); - elseif strcmp(eventformat, 'neuralynx_ttl') - % determine the optional files with timestamp information - tslfile = [filename(1:(end-4)) '.tsl']; - tshfile = [filename(1:(end-4)) '.tsh']; - % read the triggers from a seperate *.ttl file - ttl = read_neuralynx_ttl(filename, begsample, endsample); - elseif strcmp(eventformat, 'neuralynx_bin') - % determine the optional files with timestamp information - tslfile = [filename(1:(end-8)) '.tsl.bin']; - tshfile = [filename(1:(end-8)) '.tsh.bin']; - % read the triggers from a seperate *.ttl.bin file - ttl = read_neuralynx_bin(filename, begsample, endsample); - end - - ttl = int32(ttl / (2^16)); % parallel port provides int32, but word resolution is int16. Shift the bits and typecast to signed integer. - d1 = (diff(ttl)~=0); % determine the flanks, which can be multiple samples long (this looses one sample) - d2 = (diff(d1)==1); % determine the onset of the flanks (this looses one sample) - smp = find(d2)+2; % find the onset of the flanks, add the two samples again - val = ttl(smp+5); % look some samples further for the trigger value, to avoid the flank - clear d1 d2 ttl - ind = find(val~=0); % look for triggers tith a non-zero value, this avoids downgoing flanks going to zero - smp = smp(ind); % discard triggers with a value of zero - val = val(ind); % discard triggers with a value of zero - - if ~isempty(smp) - % try reading the timestamps - if strcmp(eventformat, 'neuralynx_dma') - tsl = read_neuralynx_dma(filename, 1, max(smp), 'tsl'); - tsl = typecast(tsl(smp), 'uint32'); - tsh = read_neuralynx_dma(filename, 1, max(smp), 'tsh'); - tsh = typecast(tsh(smp), 'uint32'); - ts = timestamp_neuralynx(tsl, tsh); - elseif exist(tslfile) && exist(tshfile) - tsl = read_neuralynx_bin(tslfile, 1, max(smp)); - tsl = tsl(smp); - tsh = read_neuralynx_bin(tshfile, 1, max(smp)); - tsh = tsh(smp); - ts = timestamp_neuralynx(tsl, tsh); - else - ts = []; - end - - % reformat the values as cell array, since the struct function can work with those - type = repmat({'trigger'},size(smp)); - value = num2cell(val); - sample = num2cell(smp + begsample - 1); - duration = repmat({[]},size(smp)); - offset = repmat({[]},size(smp)); - if ~isempty(ts) - timestamp = reshape(num2cell(ts),size(smp)); - else - timestamp = repmat({[]},size(smp)); - end - % convert it into a structure array, this can be done in one go - event = struct('type', type, 'value', value, 'sample', sample, 'timestamp', timestamp, 'offset', offset, 'duration', duration); - clear type value sample timestamp offset duration - end - - if (strcmp(eventformat, 'neuralynx_bin') || strcmp(eventformat, 'neuralynx_ttl')) && isfield(hdr, 'FirstTimeStamp') - % the header was obtained from an external dataset which could be at a different sampling rate - % use the timestamps to redetermine the sample numbers - fprintf('using sample number of the downsampled file to reposition the TTL events\n'); - % convert the timestamps into samples, keeping in mind the FirstTimeStamp and TimeStampPerSample - smp = round(double(ts - uint64(hdr.FirstTimeStamp))./hdr.TimeStampPerSample + 1); - for i=1:length(event) - % update the sample number - event(i).sample = smp(i); - end - end - - case 'neuralynx_ds' - % read the header of the dataset - if isempty(hdr) - hdr = read_header(filename); - end - % the event file is contained in the dataset directory - if exist(fullfile(filename, 'Events.Nev')) - filename = fullfile(filename, 'Events.Nev'); - elseif exist(fullfile(filename, 'Events.nev')) - filename = fullfile(filename, 'Events.nev'); - elseif exist(fullfile(filename, 'events.Nev')) - filename = fullfile(filename, 'events.Nev'); - elseif exist(fullfile(filename, 'events.nev')) - filename = fullfile(filename, 'events.nev'); - end - % read the events, apply filter is applicable - nev = read_neuralynx_nev(filename, 'type', flt_type, 'value', flt_value, 'mintimestamp', flt_mintimestamp, 'maxtimestamp', flt_maxtimestamp, 'minnumber', flt_minnumber, 'maxnumber', flt_maxnumber); - - % now get the values as cell array, since the struct function can work with those - value = {nev.TTLValue}; - timestamp = {nev.TimeStamp}; - number = {nev.EventNumber}; - type = repmat({'trigger'},size(value)); - duration = repmat({[]},size(value)); - offset = repmat({[]},size(value)); - sample = num2cell(round(double(cell2mat(timestamp) - hdr.FirstTimeStamp)/hdr.TimeStampPerSample + 1)); - % convert it into a structure array - event = struct('type', type, 'value', value, 'sample', sample, 'timestamp', timestamp, 'duration', duration, 'offset', offset, 'number', number); - - case 'neuralynx_cds' - % this is a combined Neuralynx dataset with seperate subdirectories for the LFP, MUA and spike channels - dirlist = dir(filename); - %haslfp = any(filetype_check_extension({dirlist.name}, 'lfp')); - %hasmua = any(filetype_check_extension({dirlist.name}, 'mua')); - %hasspike = any(filetype_check_extension({dirlist.name}, 'spike')); - %hastsl = any(filetype_check_extension({dirlist.name}, 'tsl')); % seperate file with original TimeStampLow - %hastsh = any(filetype_check_extension({dirlist.name}, 'tsh')); % seperate file with original TimeStampHi - hasttl = any(filetype_check_extension({dirlist.name}, 'ttl')); % seperate file with original Parallel_in - hasnev = any(filetype_check_extension({dirlist.name}, 'nev')); % original Events.Nev file - hasmat = 0; - if hasttl - eventfile = fullfile(filename, dirlist(find(filetype_check_extension({dirlist.name}, 'ttl'))).name); - % read the header from the combined dataset - if isempty(hdr) - hdr = read_header(filename); - end - % read the events from the *.ttl file - event = read_event(eventfile); - % convert the sample numbers from the dma or ttl file to the downsampled dataset - % assume that the *.ttl file is sampled at 32556Hz and is aligned with the rest of the data - for i=1:length(event) - event(i).sample = round((event(i).sample-1) * hdr.Fs/32556 + 1); - end - % elseif hasnev - % FIXME, do something here - % elseif hasmat - % FIXME, do something here - else - error('no event file found'); - end - - % The sample number is missingin the code below, since it is not available - % without looking in the continuously sampled data files. Therefore - % sorting the events (later in this function) based on the sample number - % fails and no events can be returned. - % - % case 'neuralynx_nev' - % [nev] = read_neuralynx_nev(filename); - % % select only the events with a TTL value - % ttl = [nev.TTLValue]; - % sel = find(ttl~=0); - % % now get the values as cell array, since teh struct function can work with those - % value = {nev(sel).TTLValue}; - % timestamp = {nev(sel).TimeStamp}; - % event = struct('value', value, 'timestamp', timestamp); - % for i=1:length(event) - % % assign the other fixed elements - % event(i).type = 'trigger'; - % event(i).offset = []; - % event(i).duration = []; - % event(i).sample = []; - % end - - - case {'neuroprax_eeg', 'neuroprax_mrk'} - tmp = np_readmarker (filename, 0, inf, 'samples'); - event = []; - for i = 1:numel(tmp.marker) - if isempty(tmp.marker{i}) - break; - end - event = [event struct('type', tmp.markernames(i),... - 'sample', num2cell(tmp.marker{i}),... - 'value', {tmp.markertyp(i)})]; - end - - case 'nexstim_nxe' - event = read_nexstim_event(filename); - - case 'nimh_cortex' - if isempty(hdr) - hdr = read_header(filename); - end - cortex = hdr.orig.trial; - for i=1:length(cortex) - % add one 'trial' event for every trial and add the trigger events - event(end+1).type = 'trial'; - event(end ).sample = nan; - event(end ).duration = nan; - event(end ).offset = nan; - event(end ).value = i; % use the trial number as value - for j=1:length(cortex(i).event) - event(end+1).type = 'trigger'; - event(end ).sample = nan; - event(end ).duration = nan; - event(end ).offset = nan; - event(end ).value = cortex(i).event(j); - end - end - - case 'ns_avg' - if isempty(hdr) - hdr = read_header(filename); - end - event(end+1).type = 'average'; - event(end ).sample = 1; - event(end ).duration = hdr.nSamples; - event(end ).offset = -hdr.nSamplesPre; - event(end ).value = []; - - case {'ns_cnt', 'ns_cnt16', 'ns_cnt32'} - % read the header, the original header includes the event table - if isempty(hdr) - hdr = read_header(filename, 'headerformat', eventformat); - end - % translate the event table into known FieldTrip event types - for i=1:hdr.orig.nevent - event(i).type = 'trigger'; - event(i).sample = hdr.orig.event.frame(i); - event(i).value = hdr.orig.event.stimtype(i); - event(i).offset = 0; - event(i).duration = 0; - end - - case 'ns_eeg' - if isempty(hdr) - hdr = read_header(filename); - end - for i=1:hdr.nTrials - % the *.eeg file has a fixed trigger value for each trial - % furthermore each trial has the label 'accept' or 'reject' - tmp = read_ns_eeg(filename, i); - % create an event with the trigger value - event(end+1).type = 'trial'; - event(end ).sample = (i-1)*hdr.nSamples + 1; - event(end ).value = tmp.sweep.type; % trigger value - event(end ).offset = -hdr.nSamplesPre; - event(end ).duration = hdr.nSamples; - % create an event with the boolean accept/reject code - event(end+1).type = 'accept'; - event(end ).sample = (i-1)*hdr.nSamples + 1; - event(end ).value = tmp.sweep.accept; % boolean value indicating accept/reject - event(end ).offset = -hdr.nSamplesPre; - event(end ).duration = hdr.nSamples; - end - - case 'plexon_nex' - event = read_nex_event(filename); - - case 'yokogawa_ave' - % check that the required low-level toolbox is available - hastoolbox('yokogawa', 1); - if isempty(hdr) - hdr = read_header(filename); - end - event(end+1).type = 'average'; - event(end ).sample = 1; - event(end ).duration = hdr.nSamples; - event(end ).offset = -hdr.nSamplesPre; - event(end ).value = []; - - case 'yokogawa_con' - % check that the required low-level toolbox is available - % hastoolbox('yokogawa', 1); - error('events still need to be implemented for the yokogawa_con format'); - - case 'yokogawa_raw' - % check that the required low-level toolbox is available - hastoolbox('yokogawa', 1); - % read the trigger id from all trials - value = GetMeg160TriggerEventM(filename); - % create a "trial" event for each trial and assign it the corresponding trigger value - for i=1:hdr.nTrials - event(end+1).type = 'trial'; - event(end ).sample = (i-1)*hdr.nSamples + 1; - event(end ).offset = -hdr.nSamplesPre; - event(end ).duration = hdr.nSamples; - event(end ).value = value(i); - end - - case 'nmc_archive_k' - event = read_nmc_archive_k_event(filename); - - - otherwise - error('unsupported event format'); -end - -if ~isempty(event) - % make sure that all required elements are present - if ~isfield(event, 'type'), error('type field not defined for each event'); end - if ~isfield(event, 'sample'), error('sample field not defined for each event'); end - if ~isfield(event, 'value'), for i=1:length(event), event(i).value = []; end; end - if ~isfield(event, 'offset'), for i=1:length(event), event(i).offset = []; end; end - if ~isfield(event, 'duration'), for i=1:length(event), event(i).duration = []; end; end -end - -% make sure that all numeric values are double -if ~isempty(event) - for i=1:length(event) - if isnumeric(event(i).value) - event(i).value = double(event(i).value); - end - event(i).sample = double(event(i).sample); - event(i).offset = double(event(i).offset); - event(i).duration = double(event(i).duration); - end -end - -if ~isempty(event) - % sort the events on the sample on which they occur - % this has the side effect that events without a sample number are discarded - [dum, indx] = sort([event.sample]); - event = event(indx); -% else -% warning(sprintf('no events found in %s', filename)); -end - -% apply the optional filters -event = filter_event(event, varargin{:}); - - diff --git a/external/fieldtrip/private/read_fcdc_data.m b/external/fieldtrip/private/read_fcdc_data.m deleted file mode 100644 index 5696043..0000000 --- a/external/fieldtrip/private/read_fcdc_data.m +++ /dev/null @@ -1,26 +0,0 @@ -function [dat] = read_fcdc_data(filename, header, begsample, endsample, chanindx, continuous) - -% this function is deprecated, please use the read_data function instead - -% Copyright (C) 2003-2009, Robert Oostenveld, F.C. Donders Centre -% -% $Log: read_fcdc_data.m,v $ -% Revision 1.45 2009/05/07 14:21:29 roboos -% deprecated the read_fcdc and write_fcdc functions, give warning and mention the correct function to be used -% - -fieldtripdefs - -warning('this function is deprecated, please use the read_data function instead'); - -% set the defaults for the optional input arguments -if nargin<5 - chanindx = []; -end -if nargin<6 || isempty(continuous) - continuous = false; -end - -% use the low-level reading function -[dat] = read_data(filename, 'header', header, 'begsample', begsample, 'endsample', endsample, 'chanindx', chanindx, 'checkboundary', ~continuous); - diff --git a/external/fieldtrip/private/read_fcdc_elec.m b/external/fieldtrip/private/read_fcdc_elec.m deleted file mode 100644 index e5b6c3f..0000000 --- a/external/fieldtrip/private/read_fcdc_elec.m +++ /dev/null @@ -1,18 +0,0 @@ -function [sens] = read_fcdc_elec(filename) - -% this function is deprecated, please use the read_sens function instead - -% Copyright (C) 2005-200, Robert Oostenveld -% -% $Log: read_fcdc_elec.m,v $ -% Revision 1.12 2009/05/07 14:21:29 roboos -% deprecated the read_fcdc and write_fcdc functions, give warning and mention the correct function to be used -% - -fieldtripdefs - -warning('this function is deprecated, please use the read_sens function instead'); - -% use the low-level reading function -[sens] = read_sens(filename); - diff --git a/external/fieldtrip/private/read_fcdc_event.m b/external/fieldtrip/private/read_fcdc_event.m deleted file mode 100644 index 2c595e7..0000000 --- a/external/fieldtrip/private/read_fcdc_event.m +++ /dev/null @@ -1,18 +0,0 @@ -function [event] = read_fcdc_event(filename) - -% this function is deprecated, please use the read_event function instead - -% Copyright (C) 2004-2009, Robert Oostenveld -% -% $Log: read_fcdc_event.m,v $ -% Revision 1.50 2009/05/07 14:21:29 roboos -% deprecated the read_fcdc and write_fcdc functions, give warning and mention the correct function to be used -% - -fieldtripdefs - -warning('this function is deprecated, please use the read_event function instead'); - -% use the low-level reading function -[event] = read_event(filename); - diff --git a/external/fieldtrip/private/read_fcdc_header.m b/external/fieldtrip/private/read_fcdc_header.m deleted file mode 100644 index c058419..0000000 --- a/external/fieldtrip/private/read_fcdc_header.m +++ /dev/null @@ -1,18 +0,0 @@ -function [hdr] = read_fcdc_header(filename) - -% this function is deprecated, please use the read_header function instead - -% Copyright (C) 2003-2009, Robert Oostenveld -% -% $Log: read_fcdc_header.m,v $ -% Revision 1.49 2009/05/07 14:21:29 roboos -% deprecated the read_fcdc and write_fcdc functions, give warning and mention the correct function to be used -% - -fieldtripdefs - -warning('this function is deprecated, please use the read_header function instead'); - -% use the low-level reading function -[hdr] = read_header(filename); - diff --git a/external/fieldtrip/private/read_fcdc_mri.m b/external/fieldtrip/private/read_fcdc_mri.m deleted file mode 100644 index f3499b8..0000000 --- a/external/fieldtrip/private/read_fcdc_mri.m +++ /dev/null @@ -1,18 +0,0 @@ -function [mri] = read_fcdc_mri(filename) - -% this function is deprecated, please use the read_mri function instead - -% Copyright (C) 2004-2009, Robert Oostenveld -% -% $Log: read_fcdc_mri.m,v $ -% Revision 1.21 2009/05/07 14:21:29 roboos -% deprecated the read_fcdc and write_fcdc functions, give warning and mention the correct function to be used -% - -fieldtripdefs - -warning('this function is deprecated, please use the read_mri function instead'); - -% use the low-level reading function -[mri] = read_mri(filename); - diff --git a/external/fieldtrip/private/read_fcdc_spike.m b/external/fieldtrip/private/read_fcdc_spike.m deleted file mode 100644 index 9115a9f..0000000 --- a/external/fieldtrip/private/read_fcdc_spike.m +++ /dev/null @@ -1,18 +0,0 @@ -function [spike] = read_fcdc_spike(filename) - -% this function is deprecated, please use the read_spike function instead - -% Copyright (C) 2007-2009, Robert Oostenveld -% -% $Log: read_fcdc_spike.m,v $ -% Revision 1.5 2009/05/07 14:21:29 roboos -% deprecated the read_fcdc and write_fcdc functions, give warning and mention the correct function to be used -% - -fieldtripdefs - -warning('this function is deprecated, please use the read_spike function instead'); - -% use the low-level reading function -[spike] = read_spike(filename); - diff --git a/external/fieldtrip/private/read_header.m b/external/fieldtrip/private/read_header.m deleted file mode 100644 index 77effa3..0000000 --- a/external/fieldtrip/private/read_header.m +++ /dev/null @@ -1,1516 +0,0 @@ -function [hdr] = read_header(filename, varargin) - -% READ_HEADER reads header information from a variety of EEG, MEG and LFP -% files and represents the header information in a common data-indepentend -% format. The supported formats are listed below. -% -% Use as -% hdr = read_header(filename, ...) -% -% Additional options should be specified in key-value pairs and can be -% 'headerformat' string -% 'fallback' can be empty or 'biosig' (default = []) -% -% This returns a header structure with the following elements -% hdr.Fs sampling frequency -% hdr.nChans number of channels -% hdr.nSamples number of samples per trial -% hdr.nSamplesPre number of pre-trigger samples in each trial -% hdr.nTrials number of trials -% hdr.label cell-array with labels of each channel -% hdr.FirstTimeStamp integer, only available for some subformats (mainly animal electrophisiology systems) -% hdr.TimeStampPerSample integer, only available for some subformats (mainly animal electrophisiology systems) -% -% For continuous data, nSamplesPre=0 and nTrials=1. -% -% Depending on the file format, additional header information can be -% returned in the hdr.orig subfield. -% -% The following MEG dataformats are supported -% CTF - VSM MedTech (*.ds, *.res4, *.meg4) -% Neuromag - Elektra (*.m4d, *.pdf, *.xyz) -% BTi - 4D Neuroimaging (*.m4d, *.pdf, *.xyz) -% Yokogawa (*.ave, *.con, *.raw) -% -% The following EEG dataformats are supported -% ANT - Advanced Neuro Technology, EEProbe (*.avr, *.eeg, *.cnt) -% Biosemi (*.bdf) -% CED - Cambridge Electronic Design (*. smr) -% Electrical Geodesics, Inc. (*.egis, *.ave, *.gave, *.ses, *.raw) -% Megis/BESA (*.avr, *.swf) -% NeuroScan (*.eeg, *.cnt, *.avg) -% Nexstim (*.nxe) -% BrainVision (*.eeg, *.seg, *.dat, *.vhdr, *.vmrk) -% -% The following spike and LFP dataformats are supported (with some limitations) -% Plextor (*.nex, *.plx, *.ddt) -% Neuralynx (*.ncs, *.nse, *.nts, *.nev, DMA log files) -% CED - Cambridge Electronic Design (*.smr) -% MPI - Max Planck Institute (*.dap) -% -% See also READ_DATA, READ_EVENT, WRITE_DATA, WRITE_EVENT - -% TODO channel renaming should be made a general option (see bham_bdf) - -% Copyright (C) 2003-2008, Robert Oostenveld, F.C. Donders Centre -% -% $Log: read_header.m,v $ -% Revision 1.102 2009/10/16 12:27:53 roboos -% some small changes pertaining to the itab/chieti format -% -% Revision 1.101 2009/10/16 07:31:18 roboos -% renamed chieti into itab for consistency with other formats -% -% Revision 1.100 2009/10/13 10:12:51 roboos -% added support for chieti_raw -% -% Revision 1.99 2009/10/08 11:17:44 roevdmei -% added support for nmc_archive_k -% -% Revision 1.98 2009/08/05 00:26:38 josdie -% Workaround for defect in number of subjects field in EGIS average files generated by NetStation. -% -% Revision 1.97 2009/07/19 19:49:21 josdie -% Deleted egi_egis changing a zero hdr.nSamplesPre to a one. -% -% Revision 1.96 2009/07/09 10:00:45 roboos -% no leading spaces for fake channel names in fcdc_buffer -% -% Revision 1.95 2009/06/17 13:43:20 roboos -% don't include LastTimeStamp in output -% -% Revision 1.94 2009/04/20 17:19:01 vlalit -% Changed the MNE reader not to set hdr.elec when there are no EEG channels. -% -% Revision 1.93 2009/03/02 10:44:38 roboos -% switched default for fif files to use the MNE reading routines in case of neuromag_fif -% the user can make his own choise by specifying the format as neuromag_mne (for the MNE routines) or neuromag_mex (for the meg-pd mex files) -% -% Revision 1.92 2009/02/12 11:47:23 vlalit -% Added support for neuro prax (eldith) EEG format based on functions from the manufacturer -% used with permission from the company's representative Mr. Klaus Schellhorn. -% -% Revision 1.91 2009/02/09 14:21:00 roboos -% added inport of micromed_trc data -% -% Revision 1.90 2009/02/09 13:35:16 roboos -% implemented efficient caching for bci2000, -% it should be initiated in read_header, subsequently read_data and read_event will reuse the details from the header -% -% Revision 1.89 2009/02/06 10:12:20 roboos -% incorporated the latest suggestions of Laurence Hunt for neuromag_mne -% -% Revision 1.88 2009/02/04 13:29:03 roboos -% deal with missing BalanceCoefs in the file using try-catch and isfield (e.g. ArtifactMEG.ds) -% -% Revision 1.87 2009/02/04 09:09:59 roboos -% fixed filename to headerfile/datafile cvonversion in case of ctf_old -% -% Revision 1.86 2009/01/23 16:22:44 roboos -% changed indentation and whitespace -% changed input arguments to mne2grad -% -% Revision 1.85 2009/01/23 10:32:55 vlalit -% New reader for Neuromag fif format using the MNE toolbox (http://www.nmr.mgh.harvard.edu/martinos/userInfo/data/sofMNE.php) implemented by Laurence Hunt. -% -% Revision 1.84 2009/01/21 20:22:42 roboos -% implemented retry for fcdc_buffer -% -% Revision 1.83 2009/01/20 21:50:20 roboos -% use mxDeserialize instead of eval(string) in mysql -% -% Revision 1.82 2009/01/20 21:20:04 roboos -% typo -% -% Revision 1.81 2009/01/19 15:05:47 roboos -% added skeleton support for reading fif files using mne functions -% -% Revision 1.80 2009/01/15 12:06:46 marvger -% removed keyboard command -% -% Revision 1.79 2009/01/15 09:42:05 marvger -% determining meg4 filesize based on all files conforming to REGEXP *.*meg4 -% -% Revision 1.78 2009/01/14 21:16:52 marvger -% changes related to realtime processing -% -% Revision 1.77 2009/01/12 13:47:50 roboos -% adedd suggestion from Doug to fix number of samples on specific configuation of OS/matlab and mex rawdata mex file -% -% Revision 1.76 2009/01/08 16:53:34 roboos -% alternatively use orig.ChannelNames for bci2000 channel count and channel names -% -% Revision 1.75 2008/12/01 14:50:42 roboos -% ensure that header elements are double precision and not integers, otherwise -% subsequent computations that depend on these might be messed up (learned in Lyon) -% -% Revision 1.74 2008/11/20 12:59:37 roboos -% added ns_cnt16 and ns_cnt32 as possible header formats, consistent with read_data -% -% Revision 1.73 2008/11/02 10:59:41 roboos -% some more changes for ctf_ds in case of empty path -% -% Revision 1.72 2008/11/02 10:37:43 roboos -% improved handling of empty path in case of ctf dataset -% -% Revision 1.71 2008/10/08 16:09:14 jansch -% changed allocation of hdr.label for 4d data. in the original implementation this -% only worked correctly for 248-channel systems, and not for the 148-channel system -% -% Revision 1.70 2008/10/07 16:21:39 roboos -% implemented caching, usefull when simulating BCI while reading from file -% -% Revision 1.69 2008/10/01 19:23:44 roboos -% fixed problem with old bci2000 dat files, changed fake channel names (no zero-prefix) -% -% Revision 1.68 2008/09/24 16:26:17 roboos -% swiched from old fcdc import routines for CTF to the p-files supplied by CTF -% these new reading routines support synthetic gradients -% the format 'ctf_new' is not supported any more, because that is now the default -% -% Revision 1.67 2008/09/04 15:35:49 vlalit -% Updates to EGI reading functions thanks to Joseph Dien -% -% Revision 1.66 2008/07/24 08:44:20 roboos -% added initial support for nimh_cortex, not yet complete -% -% Revision 1.65 2008/07/01 16:23:02 roboos -% added read_combined_data (new implementation) -% -% Revision 1.64 2008/06/26 15:50:56 roboos -% tread ctf_new just as ctf_ds w.r.t. mapping of the filenames -% -% Revision 1.63 2008/06/20 07:25:56 roboos -% added check for presence of BCI2000 load_bcidat mex file -% -% Revision 1.62 2008/06/18 08:24:33 roboos -% added support for BCI2000 -% -% Revision 1.61 2008/06/06 12:45:50 jansch -% changed filename-construction for 4d-datafiles to accommodate for filtered -% data -% -% Revision 1.60 2008/06/03 10:05:16 jansch -% removed minus-sign in nSamplesPre for 4d-data. -% -% Revision 1.59 2008/05/29 13:54:52 roboos -% also work when no path is specified -% -% Revision 1.58 2008/05/29 13:51:12 roboos -% use strcmp instead of strmatch, thanks to Marinka -% -% Revision 1.57 2008/05/29 07:30:42 roboos -% small change in renaming header/data and filename in case of ctf, this prevents a warning if the res4 or meg4 are not positioned in a xxx.ds directory (see email Jo) -% -% Revision 1.56 2008/05/27 16:12:26 vlalit -% Changed type name to ced_spike6mat -% -% Revision 1.55 2008/05/27 11:58:20 vlalit -% Added support of Matlab files exported from Spike 6 -% -% Revision 1.54 2008/05/21 11:06:05 roboos -% changed the fif reading to store all available info (including channel type) in hdr.orig -% -% Revision 1.53 2008/05/19 15:24:12 jansch -% re-entered handling of '4d' which disappeared after last commit by someone -% else -% -% Revision 1.52 2008/05/15 15:10:56 roboos -% added ctf_new implementation, using p-files, this supports synthetic gradients -% some changes to the filename handling, merged nihm2grad into ctf2grad -% -% Revision 1.51 2008/05/14 10:21:34 jansch -% included function call to bti2grad for 'm4d' and 'xyz' headers -% -% Revision 1.50 2008/05/08 11:08:57 jansch -% made changes in support for raw 4d-files -% -% Revision 1.49 2008/05/02 14:23:05 vlalit -% Added readers for SPM5 and SPM8 EEG formats -% -% Revision 1.48 2008/04/29 07:33:19 roboos -% changed low level function call for buffer -% -% Revision 1.47 2008/04/21 11:50:52 roboos -% added support for egi_sbin, thanks to Joseph Dien -% -% Revision 1.46 2008/04/18 14:07:45 roboos -% added eeglab_set -% -% Revision 1.45 2008/04/11 07:12:57 roboos -% updated docu, added list of supported file formats -% -% Revision 1.44 2008/04/10 09:34:51 roboos -% added fallback option for biosig, implemented biosig also for edf -% -% Revision 1.43 2008/04/09 16:50:02 roboos -% added fallback option to biosig (not default) -% -% Revision 1.42 2008/04/09 14:10:12 roboos -% updated docu, added placeholder for biosig (not yet implemented) -% -% Revision 1.41 2008/04/09 10:09:20 roboos -% only keep main fields for brainvision, remainder in orig -% added channel labels to hdr for ns_avg (thanks to Vladimir) -% -% Revision 1.40 2008/03/20 12:18:49 roboos -% warn only once for channel names in besa avr -% -% Revision 1.39 2008/02/19 10:08:13 roboos -% added support for fcdc_buffer -% -% Revision 1.38 2008/01/31 20:14:35 roboos -% A 4D case has been added to the existing switch statement to allow -% the execution of the new read_4D_hdr.m script to read the data -% from the pdf file. Header and grad structures are returned by the -% new function. [thanks to Gavin] -% -% Revision 1.37 2008/01/10 12:57:34 roboos -% give explicit errors with msgid FILEIO:Something -% -% Revision 1.36 2007/12/17 16:17:16 roboos -% updated some comments in the code, no functional change -% -% Revision 1.35 2007/12/17 08:24:28 roboos -% added support for nexstim_nxe, thanks to Vladimir -% the low-level code has not been tested by myself -% -% Revision 1.34 2007/12/12 16:50:15 roboos -% added support for neuralynx_bin -% -% Revision 1.33 2007/11/07 10:49:07 roboos -% cleaned up the reading and writing from/to mysql database, using db_xxx helper functions (see mysql directory) -% -% Revision 1.32 2007/11/05 17:01:21 roboos -% added implementation for fcdc_mysql -% -% Revision 1.31 2007/09/13 09:57:03 roboos -% use read_biosemi_bdf instead of openbdf/readbdf -% some small changes as sugegsted by the matlab editor (e.g. comma, semicolon) -% -% Revision 1.30 2007/08/01 12:24:40 roboos -% updated comments -% -% Revision 1.29 2007/08/01 09:57:01 roboos -% moved all code related to ctf shared memory to seperate functions -% -% Revision 1.28 2007/07/30 12:17:21 roboos -% ctf_shm: convert number of samples to double, otherwise problems with floor() in read_data -% -% Revision 1.27 2007/07/27 12:19:56 roboos -% added ctf_shm -% -% Revision 1.26 2007/07/19 14:49:30 roboos -% switched the default reader for nex files from read_nex_data to read_plexon_nex, the old one is still supported if explicitely mentioned as data/headerformat -% -% Revision 1.25 2007/07/04 13:20:51 roboos -% added support for egi_egis/egia, thanks to Joseph Dien -% -% Revision 1.24 2007/07/03 15:53:46 roboos -% switched from using Cristian Wienbruchs BTi toolbox to a new ascii header reading function (read_bti_m4d) -% -% Revision 1.23 2007/06/13 08:06:22 roboos -% updated help -% -% Revision 1.22 2007/06/06 12:39:43 roboos -% added try-catch for ctf2grad, to allow working with incomplete recordings on the new 275ch system -% -% Revision 1.21 2007/04/16 16:06:11 roboos -% add labels for neuroscan eeg format (thanks to Vladimir) -% -% Revision 1.20 2007/03/21 17:24:01 roboos -% added plexon_ds -% -% Revision 1.19 2007/03/19 17:07:19 roboos -% implemented an alternative reader for NEX (read_plexon_nex), the old implementation is still the default -% -% Revision 1.18 2007/02/21 09:54:21 roboos -% added timestamp details to header in case of neuralynx_ncs -% -% Revision 1.17 2007/01/10 17:29:54 roboos -% moved the fieldtrip specific handling of header information into -% read_header -% -% Revision 1.16 2007/01/09 09:38:40 roboos -% added spike channels for plexon_plx, moved plexon timestamp combination code to seperate function -% -% Revision 1.15 2007/01/04 17:13:19 roboos -% finished timestamp stuff for plexon_plx, only return the continuous channels that have data -% -% Revision 1.14 2007/01/04 12:20:26 roboos -% updated the neuralynx section to reflect the new reading functions and to use read_neuralynx_cds -% implemented recursive reading function for nested dataset directories -% -% Revision 1.13 2007/01/04 12:06:36 roboos -% added plexon_plx, not yet completely finished -% -% Revision 1.12 2006/12/04 10:37:10 roboos -% added support for ns_avg -% fixed bug in ns_eeg (hdr.nSamplesPre was negative) -% -% Revision 1.11 2006/10/09 15:39:51 roboos -% renamed BTi channels from 'MEGxxx' into 'Axxx' -% -% Revision 1.10 2006/09/18 21:48:33 roboos -% implemented support for fcdc_matbin, i.e. a dataset consisting of a matlab file with header and events and a seperate binary datafile -% -% Revision 1.9 2006/09/18 14:52:14 roboos -% implemented bti2grad and added it to header -% -% Revision 1.8 2006/09/18 14:22:54 roboos -% implemented support for 4D-BTi dataformat -% -% Revision 1.7 2006/09/13 11:01:01 roboos -% changed text in a error message -% -% Revision 1.6 2006/08/28 10:13:03 roboos -% use seperate filetype_check_extension function instead of subfunction, removed subfunction -% -% Revision 1.5 2006/06/22 15:07:39 roboos -% fiuxed bug in label assignment for tsl/tsh/ttl -% -% Revision 1.4 2006/06/22 13:51:47 roboos -% fixed typo in code: datatype instead of datatyppe, thanks to Thilo -% -% Revision 1.3 2006/06/22 07:53:46 roboos -% remember the original neuroscan cnt header -% -% Revision 1.2 2006/06/19 10:32:16 roboos -% added documentation -% -% Revision 1.1 2006/06/07 09:32:20 roboos -% new implementation based on the read_fcdc_xxx functions, now with -% variable (key-val) input arguments, changed the control structure -% in the rpobram (switch instead of ifs), allow the user to specify -% the file format, allow the user to specify either a sample selection -% or a block selection. The reading functionality should not have -% changed compared to the read_fcdc_xxx versions. -% - -persistent cacheheader % for caching -persistent db_blob % for fcdc_mysql - -if isempty(db_blob) - db_blob = 0; -end - -% test whether the file or directory exists -if ~exist(filename, 'file') && ~strcmp(filetype(filename), 'ctf_shm') && ~strcmp(filetype(filename), 'fcdc_mysql') && ~strcmp(filetype(filename), 'fcdc_buffer') - error('FILEIO:InvalidFileName', 'file or directory ''%s'' does not exist', filename); -end - -% get the options -headerformat = keyval('headerformat', varargin); -fallback = keyval('fallback', varargin); -cache = keyval('cache', varargin); if isempty(cache), cache = false; end -retry = keyval('retry', varargin); if isempty(retry), retry = false; end % for fcdc_buffer - -% determine the filetype -if isempty(headerformat) - headerformat = filetype(filename); -end - -% start with an empty header -hdr = []; - -switch headerformat - case '4d_pdf' - datafile = filename; - headerfile = [datafile '.m4d']; - sensorfile = [datafile '.xyz']; - case {'4d_m4d', '4d_xyz'} - datafile = filename(1:(end-4)); % remove the extension - headerfile = [datafile '.m4d']; - sensorfile = [datafile '.xyz']; - case '4d' - [path, file, ext] = fileparts(filename); - datafile = fullfile(path, [file,ext]); - headerfile = fullfile(path, [file,ext]); - configfile = fullfile(path, 'config'); - case {'ctf_ds', 'ctf_old'} - % convert CTF filename into filenames - [path, file, ext] = fileparts(filename); - if any(strcmp(ext, {'.res4' '.meg4', '.1_meg4' '.2_meg4' '.3_meg4' '.4_meg4' '.5_meg4' '.6_meg4' '.7_meg4' '.8_meg4' '.9_meg4'})) - filename = path; - [path, file, ext] = fileparts(filename); - end - if isempty(path) && isempty(file) - % this means that the dataset was specified as the present working directory, i.e. only with '.' - filename = pwd; - [path, file, ext] = fileparts(filename); - end - headerfile = fullfile(filename, [file '.res4']); - datafile = fullfile(filename, [file '.meg4']); - if length(path)>3 && strcmp(path(end-2:end), '.ds') - filename = path; % this is the *.ds directory - end - case 'ctf_meg4' - [path, file, ext] = fileparts(filename); - if isempty(path) - path = pwd; - end - headerfile = fullfile(path, [file '.res4']); - datafile = fullfile(path, [file '.meg4']); - if length(path)>3 && strcmp(path(end-2:end), '.ds') - filename = path; % this is the *.ds directory - end - case 'ctf_res4' - [path, file, ext] = fileparts(filename); - if isempty(path) - path = pwd; - end - headerfile = fullfile(path, [file '.res4']); - datafile = fullfile(path, [file '.meg4']); - if length(path)>3 && strcmp(path(end-2:end), '.ds') - filename = path; % this is the *.ds directory - end - case 'brainvision_vhdr' - [path, file, ext] = fileparts(filename); - headerfile = fullfile(path, [file '.vhdr']); - if exist(fullfile(path, [file '.eeg'])) - datafile = fullfile(path, [file '.eeg']); - elseif exist(fullfile(path, [file '.seg'])) - datafile = fullfile(path, [file '.seg']); - elseif exist(fullfile(path, [file '.dat'])) - datafile = fullfile(path, [file '.dat']); - end - case 'brainvision_eeg' - [path, file, ext] = fileparts(filename); - headerfile = fullfile(path, [file '.vhdr']); - datafile = fullfile(path, [file '.eeg']); - case 'brainvision_seg' - [path, file, ext] = fileparts(filename); - headerfile = fullfile(path, [file '.vhdr']); - datafile = fullfile(path, [file '.seg']); - case 'brainvision_dat' - [path, file, ext] = fileparts(filename); - headerfile = fullfile(path, [file '.vhdr']); - datafile = fullfile(path, [file '.dat']); - case 'fcdc_matbin' - [path, file, ext] = fileparts(filename); - headerfile = fullfile(path, [file '.mat']); - datafile = fullfile(path, [file '.bin']); - case 'nmc_archive_k' - headerfile = filename; - otherwise - % convert filename into filenames, assume that the header and data are the same - datafile = filename; - headerfile = filename; -end - -if ~strcmp(filename, headerfile) && ~filetype(filename, 'ctf_ds') - filename = headerfile; % this function will read the header - headerformat = filetype(filename); % update the filetype -end - - -% implement the caching in a data-format independent way -if cache && exist(headerfile, 'file') && ~isempty(cacheheader) - % try to get the header from cache - details = dir(headerfile); - if isequal(details, cacheheader.details) - % the header file has not been updated, fetch it from the cache - % fprintf('got header from cache\n'); - hdr = rmfield(cacheheader, 'details'); - - switch filetype(datafile) - case {'ctf_ds' 'ctf_meg4' 'ctf_old' 'read_ctf_res4'} - % for realtime analysis EOF chasing the res4 does not correctly - % estimate the number of samples, so we compute it on the fly - sz = 0; - files = dir([filename '/*.*meg4']); - for j=1:numel(files) - sz = sz + files(j).bytes; - end - hdr.nTrials = floor((sz - 8) / (hdr.nChans*4) / hdr.nSamples); - end - - return; - end % if the details correspond -end % if cache - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% read the data with the low-level reading function -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -switch headerformat - case '4d' - orig = read_4d_hdr(datafile, configfile); - hdr.Fs = orig.header_data.SampleFrequency; - hdr.nChans = orig.header_data.TotalChannels; - hdr.nSamples = orig.header_data.SlicesPerEpoch; - hdr.nSamplesPre = round(orig.header_data.FirstLatency*orig.header_data.SampleFrequency); - hdr.nTrials = orig.header_data.TotalEpochs; - %hdr.label = {orig.channel_data(:).chan_label}'; - hdr.label = orig.Channel; - hdr.grad = bti2grad(orig); - % remember original header details - hdr.orig = orig; - - case {'4d_pdf', '4d_m4d', '4d_xyz'} - orig = read_bti_m4d(filename); - hdr.Fs = orig.SampleFrequency; - hdr.nChans = orig.TotalChannels; - hdr.nSamples = orig.SlicesPerEpoch; - hdr.nSamplesPre = round(orig.FirstLatency*orig.SampleFrequency); - hdr.nTrials = orig.TotalEpochs; - hdr.label = orig.ChannelOrder(:); - hdr.grad = bti2grad(orig); - % remember original header details - hdr.orig = orig; - - case 'bci2000_dat' - % this requires the load_bcidat mex file to be present on the path - hastoolbox('BCI2000', 1); - % this is inefficient, since it reads the complete data - [signal, states, parameters, total_samples] = load_bcidat(filename); - % convert into a FieldTrip-like header - hdr = []; - hdr.nChans = size(signal,2); - hdr.nSamples = total_samples; - hdr.nSamplesPre = 0; % it is continuous - hdr.nTrials = 1; % it is continuous - hdr.Fs = parameters.SamplingRate.NumericValue; - % there are some differences in the fields that are present in the - % *.dat files, probably due to different BCI2000 versions - if isfield(parameters, 'ChannelNames') && isfield(parameters.ChannelNames, 'Value') && ~isempty(parameters.ChannelNames.Value) - hdr.label = parameters.ChannelNames.Value; - elseif isfield(parameters, 'ChannelNames') && isfield(parameters.ChannelNames, 'Values') && ~isempty(parameters.ChannelNames.Values) - hdr.label = parameters.ChannelNames.Values; - else - warning('creating fake channel names'); - for i=1:hdr.nChans - hdr.label{i} = sprintf('%d', i); - end - end - - % remember the original header details - hdr.orig.parameters = parameters; - % also remember the complete data upon request - if cache - hdr.orig.signal = signal; - hdr.orig.states = states; - hdr.orig.total_samples = total_samples; - end - - case 'besa_avr' - orig = read_besa_avr(filename); - hdr.Fs = 1000/orig.di; - hdr.nChans = size(orig.data,1); - hdr.nSamples = size(orig.data,2); - hdr.nSamplesPre = -(hdr.Fs * orig.tsb/1000); % convert from ms to samples - hdr.nTrials = 1; - if isfield(orig, 'label') && iscell(orig.label) - hdr.label = orig.label; - elseif isfield(orig, 'label') && ischar(orig.label) - hdr.label = tokenize(orig.label, ' '); - else - warning('creating fake channel names'); - for i=1:hdr.nChans - hdr.label{i} = sprintf('%d', i); - end - end - - case 'besa_swf' - orig = read_besa_swf(filename); - hdr.Fs = 1000/orig.di; - hdr.nChans = size(orig.data,1); - hdr.nSamples = size(orig.data,2); - hdr.nSamplesPre = -(hdr.Fs * orig.tsb/1000); % convert from ms to samples - hdr.nTrials = 1; - hdr.label = orig.label; - - case {'biosig', 'edf'} - % use the biosig toolbox if available - hastoolbox('BIOSIG', 1); - hdr = read_biosig_header(filename); - - case {'biosemi_bdf', 'bham_bdf'} - hdr = read_biosemi_bdf(filename); - if any(diff(hdr.orig.SampleRate)) - error('channels with different sampling rate not supported'); - end - if filetype(filename, 'bham_bdf') - % TODO channel renaming should be made a general option - % this is for the Biosemi system used at the University of Birmingham - labelold = { 'A1' 'A2' 'A3' 'A4' 'A5' 'A6' 'A7' 'A8' 'A9' 'A10' 'A11' 'A12' 'A13' 'A14' 'A15' 'A16' 'A17' 'A18' 'A19' 'A20' 'A21' 'A22' 'A23' 'A24' 'A25' 'A26' 'A27' 'A28' 'A29' 'A30' 'A31' 'A32' 'B1' 'B2' 'B3' 'B4' 'B5' 'B6' 'B7' 'B8' 'B9' 'B10' 'B11' 'B12' 'B13' 'B14' 'B15' 'B16' 'B17' 'B18' 'B19' 'B20' 'B21' 'B22' 'B23' 'B24' 'B25' 'B26' 'B27' 'B28' 'B29' 'B30' 'B31' 'B32' 'C1' 'C2' 'C3' 'C4' 'C5' 'C6' 'C7' 'C8' 'C9' 'C10' 'C11' 'C12' 'C13' 'C14' 'C15' 'C16' 'C17' 'C18' 'C19' 'C20' 'C21' 'C22' 'C23' 'C24' 'C25' 'C26' 'C27' 'C28' 'C29' 'C30' 'C31' 'C32' 'D1' 'D2' 'D3' 'D4' 'D5' 'D6' 'D7' 'D8' 'D9' 'D10' 'D11' 'D12' 'D13' 'D14' 'D15' 'D16' 'D17' 'D18' 'D19' 'D20' 'D21' 'D22' 'D23' 'D24' 'D25' 'D26' 'D27' 'D28' 'D29' 'D30' 'D31' 'D32' 'EXG1' 'EXG2' 'EXG3' 'EXG4' 'EXG5' 'EXG6' 'EXG7' 'EXG8' 'Status'}; - labelnew = { 'P9' 'PPO9h' 'PO7' 'PPO5h' 'PPO3h' 'PO5h' 'POO9h' 'PO9' 'I1' 'OI1h' 'O1' 'POO1' 'PO3h' 'PPO1h' 'PPO2h' 'POz' 'Oz' 'Iz' 'I2' 'OI2h' 'O2' 'POO2' 'PO4h' 'PPO4h' 'PO6h' 'POO10h' 'PO10' 'PO8' 'PPO6h' 'PPO10h' 'P10' 'P8' 'TPP9h' 'TP7' 'TTP7h' 'CP5' 'TPP7h' 'P7' 'P5' 'CPP5h' 'CCP5h' 'CP3' 'P3' 'CPP3h' 'CCP3h' 'CP1' 'P1' 'Pz' 'CPP1h' 'CPz' 'CPP2h' 'P2' 'CPP4h' 'CP2' 'CCP4h' 'CP4' 'P4' 'P6' 'CPP6h' 'CCP6h' 'CP6' 'TPP8h' 'TP8' 'TPP10h' 'T7' 'FTT7h' 'FT7' 'FC5' 'FCC5h' 'C5' 'C3' 'FCC3h' 'FC3' 'FC1' 'C1' 'CCP1h' 'Cz' 'FCC1h' 'FCz' 'FFC1h' 'Fz' 'FFC2h' 'FC2' 'FCC2h' 'CCP2h' 'C2' 'C4' 'FCC4h' 'FC4' 'FC6' 'FCC6h' 'C6' 'TTP8h' 'T8' 'FTT8h' 'FT8' 'FT9' 'FFT9h' 'F7' 'FFT7h' 'FFC5h' 'F5' 'AFF7h' 'AF7' 'AF5h' 'AFF5h' 'F3' 'FFC3h' 'F1' 'AF3h' 'Fp1' 'Fpz' 'Fp2' 'AFz' 'AF4h' 'F2' 'FFC4h' 'F4' 'AFF6h' 'AF6h' 'AF8' 'AFF8h' 'F6' 'FFC6h' 'FFT8h' 'F8' 'FFT10h' 'FT10'}; - % rename the channel labels - for i=1:length(labelnew) - chan = strcmp(labelold(i), hdr.label); - hdr.label(chan) = labelnew(chan); - end - end - - case {'biosemi_old'} - % this uses the openbdf and readbdf functions that I copied from the EEGLAB toolbox - orig = openbdf(filename); - if any(orig.Head.SampleRate~=orig.Head.SampleRate(1)) - error('channels with different sampling rate not supported'); - end - hdr.Fs = orig.Head.SampleRate(1); - hdr.nChans = orig.Head.NS; - hdr.label = cellstr(orig.Head.Label); - % it is continuous data, therefore append all records in one trial - hdr.nSamples = orig.Head.NRec * orig.Head.Dur * orig.Head.SampleRate(1); - hdr.nSamplesPre = 0; - hdr.nTrials = 1; - hdr.orig = orig; - % close the file between seperate read operations - fclose(orig.Head.FILE.FID); - - case {'brainvision_vhdr', 'brainvision_seg', 'brainvision_eeg', 'brainvision_dat'} - orig = read_brainvision_vhdr(filename); - hdr.Fs = orig.Fs; - hdr.nChans = orig.NumberOfChannels; - hdr.label = orig.label; - hdr.nSamples = orig.nSamples; - hdr.nSamplesPre = orig.nSamplesPre; - hdr.nTrials = orig.nTrials; - hdr.orig = orig; - - case 'ced_son' - % check that the required low-level toolbox is available - hastoolbox('neuroshare', 1); - % use the reading function supplied by Gijs van Elswijk - orig = read_ced_son(filename,'readevents','no','readdata','no'); - orig = orig.header; - % In Spike2, channels can have different sampling rates, units, length - % etc. etc. Here, channels need to have to same properties. - if length(unique([orig.samplerate]))>1, - error('channels with different sampling rates are not supported'); - else - hdr.Fs = orig(1).samplerate; - end; - hdr.nChans = length(orig); - % nsamples of the channel with least samples - hdr.nSamples = min([orig.nsamples]); - hdr.nSamplesPre = 0; - % only continuous data supported - if sum(strcmpi({orig.mode},'continuous')) < hdr.nChans, - error('not all channels contain continuous data'); - else - hdr.nTrials = 1; - end; - hdr.label = {orig.label}; - - case 'itab_raw' - % check the presence of the required low-level toolbox - hastoolbox('lc-libs', 1); - - header_info = lcReadHeader(filename); - - % some channels don't have a label and are not supported by fieldtrip - chansel = true(size(header_info.ch)); - for i=1:length(chansel) - chansel(i) = ~isempty(header_info.ch(i).label); - end - % convert into numeric array with indices - chansel = find(chansel); - - % convert the header information into a fieldtrip compatible format - hdr.nChans = length(chansel); - hdr.label = {header_info.ch(chansel).label}; - hdr.label = hdr.label(:); % should be column vector - hdr.Fs = header_info.smpfq; - if header_info.nsmpl==0 - % for continuous data - hdr.nSamples = header_info.ntpdata; - hdr.nSamplesPre = 0; % it is a single continuous trial - hdr.nTrials = 1; % it is a single continuous trial - else - error('epoched data in a itab_raw file is not yet supported (but should be easy to add)'); - end - % keep the original details AND the list of channels as used by fieldtrip - hdr.orig = header_info; - hdr.orig.chansel = chansel; - % add the gradiometer definition - hdr.grad = itab2grad(header_info); - - case 'combined_ds' - hdr = read_combined_ds(filename); - - case {'ctf_ds', 'ctf_meg4', 'ctf_res4'} - % check the presence of the required low-level toolbox - hastoolbox('ctf', 1); - orig = readCTFds(filename); - hdr.Fs = orig.res4.sample_rate; - hdr.nChans = orig.res4.no_channels; - hdr.nSamples = orig.res4.no_samples; - hdr.nSamplesPre = orig.res4.preTrigPts; - hdr.nTrials = orig.res4.no_trials; - hdr.label = cellstr(orig.res4.chanNames); - for i=1:numel(hdr.label) - % remove the site-specific numbers from each channel name, e.g. 'MZC01-1706' becomes 'MZC01' - hdr.label{i} = strtok(hdr.label{i}, '-'); - end - % read the balance coefficients, these are used to compute the synthetic gradients - try - [alphaMEG,MEGlist,Refindex] = getCTFBalanceCoefs(orig,'NONE', 'T'); - orig.BalanceCoefs.none.alphaMEG = alphaMEG; - orig.BalanceCoefs.none.MEGlist = MEGlist; - orig.BalanceCoefs.none.Refindex = Refindex; - catch - warning('cannot read balancing coefficients for NONE'); - end - try - [alphaMEG,MEGlist,Refindex] = getCTFBalanceCoefs(orig,'G1BR', 'T'); - orig.BalanceCoefs.G1BR.alphaMEG = alphaMEG; - orig.BalanceCoefs.G1BR.MEGlist = MEGlist; - orig.BalanceCoefs.G1BR.Refindex = Refindex; - catch - warning('cannot read balancing coefficients for G1BR'); - end - try - [alphaMEG,MEGlist,Refindex] = getCTFBalanceCoefs(orig,'G2BR', 'T'); - orig.BalanceCoefs.G2BR.alphaMEG = alphaMEG; - orig.BalanceCoefs.G2BR.MEGlist = MEGlist; - orig.BalanceCoefs.G2BR.Refindex = Refindex; - catch - warning('cannot read balancing coefficients for G2BR'); - end - try - [alphaMEG,MEGlist,Refindex] = getCTFBalanceCoefs(orig,'G3BR', 'T'); - orig.BalanceCoefs.G3BR.alphaMEG = alphaMEG; - orig.BalanceCoefs.G3BR.MEGlist = MEGlist; - orig.BalanceCoefs.G3BR.Refindex = Refindex; - catch - warning('cannot read balancing coefficients for G3BR'); - end - % add a gradiometer structure for forward and inverse modelling - try - hdr.grad = ctf2grad(orig); - catch - % this fails if the res4 file is not correctly closed, e.g. during realtime processing - tmp = lasterror; - disp(tmp.message); - warning('could not construct gradiometer definition from the header'); - end - - % for realtime analysis EOF chasing the res4 does not correctly - % estimate the number of samples, so we compute it on the fly from the - % meg4 file sizes. - sz = 0; - files = dir([filename '/*.*meg4']); - for j=1:numel(files) - sz = sz + files(j).bytes; - end - hdr.nTrials = floor((sz - 8) / (hdr.nChans*4) / hdr.nSamples); - - % add the original header details - hdr.orig = orig; - - case {'ctf_old', 'read_ctf_res4'} - % read it using the open-source matlab code that originates from CTF and that was modified by the FCDC - orig = read_ctf_res4(headerfile); - hdr.Fs = orig.Fs; - hdr.nChans = orig.nChans; - hdr.nSamples = orig.nSamples; - hdr.nSamplesPre = orig.nSamplesPre; - hdr.nTrials = orig.nTrials; - hdr.label = orig.label; - % add a gradiometer structure for forward and inverse modelling - try - hdr.grad = ctf2grad(orig); - catch - % this fails if the res4 file is not correctly closed, e.g. during realtime processing - tmp = lasterror; - disp(tmp.message); - warning('could not construct gradiometer definition from the header'); - end - % add the original header details - hdr.orig = orig; - - case 'ctf_read_res4' - % check that the required low-level toolbos ix available - hastoolbox('eegsf', 1); - % read it using the CTF importer from the NIH and Daren Weber - orig = ctf_read_res4(filename, 0); - % convert the header into a structure that FieldTrip understands - hdr = []; - hdr.Fs = orig.setup.sample_rate; - hdr.nChans = length(orig.sensor.info); - hdr.nSamples = orig.setup.number_samples; - hdr.nSamplesPre = orig.setup.pretrigger_samples; - hdr.nTrials = orig.setup.number_trials; - for i=1:length(orig.sensor.info) - hdr.label{i} = orig.sensor.info(i).label; - end - hdr.label = hdr.label(:); - % add a gradiometer structure for forward and inverse modelling - try - hdr.grad = ctf2grad(orig); - catch - % this fails if the res4 file is not correctly closed, e.g. during realtime processing - tmp = lasterror; - disp(tmp.message); - warning('could not construct gradiometer definition from the header'); - end - % add the original header details - hdr.orig = orig; - - case 'ctf_shm' - % contact Robert Oostenveld if you are interested in real-time acquisition on the CTF system - % read the header information from shared memory - hdr = read_shm_header(filename); - - case 'eep_avr' - % check that the required low-level toolbox is available - hastoolbox('eeprobe', 1); - % read the whole average and keep only header info (it is a bit silly, but the easiest to do here) - hdr = read_eep_avr(filename); - hdr.Fs = hdr.rate; - hdr.nChans = size(hdr.data,1); - hdr.nSamples = size(hdr.data,2); - hdr.nSamplesPre = hdr.xmin*hdr.rate/1000; - hdr.nTrials = 1; % it can always be interpreted as continuous data - % remove the data and variance if present - hdr = rmfield(hdr, 'data'); - try, hdr = rmfield(hdr, 'variance'); end - - case 'eeglab_set' - hdr = read_eeglabheader(filename); - - case 'spmeeg_mat' - hdr = read_spmeeg_header(filename); - - case 'ced_spike6mat' - hdr = read_spike6mat_header(filename); - - case 'eep_cnt' - % check that the required low-level toolbox is available - hastoolbox('eeprobe', 1); - % read the first sample from the continous data, which will also return the header - hdr = read_eep_cnt(filename, 1, 1); - hdr.Fs = hdr.rate; - hdr.nSamples = hdr.nsample; - hdr.nSamplesPre = 0; - hdr.nChans = hdr.nchan; - hdr.nTrials = 1; % it can always be interpreted as continuous data - - case 'egi_egia' - [fhdr,chdr,ename,cnames,fcom,ftext] = read_egis_header(filename); - [p, f, x] = fileparts(filename); - - if any(chdr(:,4)-chdr(1,4)) - error('Sample rate not the same for all cells.'); - end; - - hdr.Fs = chdr(1,4); %making assumption that sample rate is same for all cells - hdr.nChans = fhdr(19); - for i = 1:hdr.nChans - hdr.label{i} = ['e' num2str(i)]; - end; - %since NetStation does not properly set the fhdr(11) field, use the number of subjects from the chdr instead - hdr.nTrials = chdr(1,2)*fhdr(18); %number of trials is numSubjects * numCells - hdr.nSamplesPre = ceil(fhdr(14)/(1000/hdr.Fs)); - - if any(chdr(:,3)-chdr(1,3)) - error('Number of samples not the same for all cells.'); - end; - - hdr.nSamples = chdr(1,3); %making assumption that number of samples is same for all cells - - % remember the original header details - hdr.orig.fhdr = fhdr; - hdr.orig.chdr = chdr; - hdr.orig.ename = ename; - hdr.orig.cnames = cnames; - hdr.orig.fcom = fcom; - hdr.orig.ftext = ftext; - - case 'egi_egis' - [fhdr,chdr,ename,cnames,fcom,ftext] = read_egis_header(filename); - [p, f, x] = fileparts(filename); - - if any(chdr(:,4)-chdr(1,4)) - error('Sample rate not the same for all cells.'); - end; - - hdr.Fs = chdr(1,4); %making assumption that sample rate is same for all cells - hdr.nChans = fhdr(19); - for i = 1:hdr.nChans - hdr.label{i} = ['e' num2str(i)]; - end; - hdr.nTrials = sum(chdr(:,2)); - hdr.nSamplesPre = ceil(fhdr(14)/(1000/hdr.Fs)); - % assuming that a utility was used to insert the correct baseline - % duration into the header since it is normally absent. This slot is - % actually allocated to the age of the subject, although NetStation - % does not use it when generating an EGIS session file. - - if any(chdr(:,3)-chdr(1,3)) - error('Number of samples not the same for all cells.'); - end; - - hdr.nSamples = chdr(1,3); %making assumption that number of samples is same for all cells - - % remember the original header details - hdr.orig.fhdr = fhdr; - hdr.orig.chdr = chdr; - hdr.orig.ename = ename; - hdr.orig.cnames = cnames; - hdr.orig.fcom = fcom; - hdr.orig.ftext = ftext; - - case 'egi_sbin' - % segmented type only - [header_array, CateNames, CatLengths, preBaseline] = read_sbin_header(filename); - [p, f, x] = fileparts(filename); - - hdr.Fs = header_array(9); - hdr.nChans = header_array(10); - for i = 1:hdr.nChans - hdr.label{i} = ['e' num2str(i)]; - end; - hdr.nTrials = header_array(15); - hdr.nSamplesPre = preBaseline; - - if hdr.nSamplesPre == 0 - hdr.nSamplesPre = 1; % If baseline was left as zero, then change to "1" to avoid possible issues with software expecting a non-zero baseline. - end; - - hdr.nSamples = header_array(16); % making assumption that number of samples is same for all cells - - % remember the original header details - hdr.orig.header_array = header_array; - hdr.orig.CateNames = CateNames; - hdr.orig.CatLengths = CatLengths; - - case 'fcdc_buffer' - % read from a networked buffer for realtime analysis - [host, port] = filetype_check_uri(filename); - if retry - orig = []; - while isempty(orig) - try - % try reading the header, catch the error and retry - orig = buffer('get_hdr', [], host, port); - catch - warning('could not read header from %s, retrying in 1 second', filename); - pause(1); - end - end % while - else - % try reading the header only once, give error if it fails - orig = buffer('get_hdr', [], host, port); - end % if retry - hdr.Fs = orig.fsample; - hdr.nChans = orig.nchans; - hdr.nSamples = orig.nsamples; - hdr.nSamplesPre = 0; % since continuous - hdr.nTrials = 1; % since continuous - warning('creating fake channel names'); - for i=1:hdr.nChans - hdr.label{i} = sprintf('%d', i); - end - % this should be a column vector - hdr.label = hdr.label(:); - % remember the original header details - hdr.orig = orig; - - case 'fcdc_matbin' - % this is multiplexed data in a *.bin file, accompanied by a matlab file containing the header - load(headerfile, 'hdr'); - - case 'fcdc_mysql' - % read from a MySQL server listening somewhere else on the network - db_open(filename); - if db_blob - hdr = db_select_blob('fieldtrip.header', 'msg', 1); - else - hdr = db_select('fieldtrip.header', {'nChans', 'nSamples', 'nSamplesPre', 'Fs', 'label'}, 1); - hdr.label = mxDeserialize(hdr.label); - end - - case 'micromed_trc' - orig = read_micromed_trc(filename); - hdr = []; - hdr.Fs = orig.Rate_Min; % FIXME is this correct? - hdr.nChans = orig.Num_Chan; - hdr.nSamples = orig.Num_Samples; - hdr.nSamplesPre = 0; % continuous - hdr.nTrials = 1; % continuous - warning('creating fake channel names'); - for i=1:hdr.nChans - hdr.label{i} = sprintf('%3d', i); - end - % this should be a column vector - hdr.label = hdr.label(:); - % remember the original header details - hdr.orig = orig; - - case {'mpi_ds', 'mpi_dap'} - hdr = read_mpi_ds(filename); - - case 'neuralynx_dma' - hdr = read_neuralynx_dma(filename); - - case 'neuralynx_sdma' - hdr = read_neuralynx_sdma(filename); - - case 'neuralynx_ncs' - ncs = read_neuralynx_ncs(filename, 1, 0); - [p, f, x] = fileparts(filename); - hdr.Fs = ncs.hdr.SamplingFrequency; - hdr.label = {f}; - hdr.nChans = 1; - hdr.nTrials = 1; - hdr.nSamplesPre = 0; - hdr.nSamples = ncs.NRecords * 512; - hdr.orig = ncs.hdr; - FirstTimeStamp = ncs.hdr.FirstTimeStamp; % this is the first timestamp of the first block - LastTimeStamp = ncs.hdr.LastTimeStamp; % this is the first timestamp of the last block, i.e. not the timestamp of the last sample - hdr.TimeStampPerSample = double(LastTimeStamp - FirstTimeStamp) ./ ((ncs.NRecords-1)*512); - hdr.FirstTimeStamp = FirstTimeStamp; - - case 'neuralynx_nse' - nse = read_neuralynx_nse(filename, 1, 0); - [p, f, x] = fileparts(filename); - hdr.Fs = nse.hdr.SamplingFrequency; - hdr.label = {f}; - hdr.nChans = 1; - hdr.nTrials = nse.NRecords; % each record contains one waveform - hdr.nSamples = 32; % there are 32 samples in each waveform - hdr.nSamplesPre = 0; - hdr.orig = nse.hdr; - % FIXME add hdr.FirstTimeStamp and hdr.TimeStampPerSample - - case {'neuralynx_ttl', 'neuralynx_tsl', 'neuralynx_tsh'} - % these are hardcoded, they contain an 8-byte header and int32 values for a single channel - % FIXME this should be done similar as neuralynx_bin, i.e. move the hdr into the function - hdr = []; - hdr.Fs = 32556; - hdr.nChans = 1; - hdr.nSamples = (filesize(filename)-8)/4; - hdr.nSamplesPre = 1; - hdr.nTrials = 1; - hdr.label = {headerformat((end-3):end)}; - - case 'neuralynx_bin' - hdr = read_neuralynx_bin(filename); - - case 'neuralynx_ds' - hdr = read_neuralynx_ds(filename); - - case 'neuralynx_cds' - hdr = read_neuralynx_cds(filename); - - case 'nexstim_nxe' - hdr = read_nexstim_nxe(filename); - - case {'neuromag_fif' 'neuromag_mne'} - % check that the required low-level toolbox is available - hastoolbox('mne', 1); - - orig = fiff_read_meas_info(filename); - % convert to fieldtrip format header - hdr.label = orig.ch_names(:); - hdr.nChans = orig.nchan; - hdr.Fs = orig.sfreq; - % add a gradiometer structure for forward and inverse modelling - try - [hdr.grad, elec] = mne2grad(orig); - if ~isempty(elec) - hdr.elec = elec; - end - catch - disp(lasterr); - end - - for i = 1:hdr.nChans % make a cell array of units for each channel - switch orig.chs(i).unit - case 201 % defined as constants by MNE, see p. 217 of MNE manual - hdr.unit{i} = 'T/m'; - case 112 - hdr.unit{i} = 'T'; - case 107 - hdr.unit{i} = 'V'; - case 202 - hdr.unit{i} = 'Am'; - otherwise - hdr.unit{i} = 'unknown'; - end - end - - iscontinuous = 0; - isaverage = 0; - isepoched = 0; % FIXME don't know how to determine this, or whether epoched .fif data exists! - - if isempty(fiff_find_evoked(filename)) % true if file contains no evoked responses - iscontinuous = 1; - else - isaverage = 1; - end - - if iscontinuous - raw = fiff_setup_read_raw(filename); - hdr.nSamples = raw.last_samp - raw.first_samp + 1; % number of samples per trial - hdr.nSamplesPre = raw.first_samp; - hdr.nTrials = 1; - orig.raw = raw; % keep all the details - - elseif isaverage - evoked_data = fiff_read_evoked_all(filename); - vartriallength = any(diff([evoked_data.evoked.first])) || any(diff([evoked_data.evoked.last])); - if vartriallength - % there are trials averages with variable durations in the file - warning('EVOKED FILE with VARIABLE TRIAL LENGTH! - check data have been processed accurately'); - hdr.nSamples = 0; - for i=1:length(evoked_data.evoked) - hdr.nSamples = hdr.nSamples + size(evoked_data.evoked(i).epochs, 2); - end - % represent it as a continuous file with a single trial - % all trial average details will be available through read_event - hdr.nSamplesPre = 0; - hdr.nTrials = 1; - orig.evoked = evoked_data.evoked; % this is used by read_data to get the actual data, i.e. to prevent re-reading - orig.info = evoked_data.info; % keep all the details - orig.vartriallength = 1; - else - % represent it as a file with multiple trials, each trial has the same length - % all trial average details will be available through read_event - hdr.nSamples = evoked_data.evoked(1).last - evoked_data.evoked(1).first + 1; - hdr.nSamplesPre = evoked_data.evoked(1).first; - hdr.nTrials = length(evoked_data.evoked); - orig.evoked = evoked_data.evoked; % this is used by read_data to get the actual data, i.e. to prevent re-reading - orig.info = evoked_data.info; % keep all the details - orig.vartriallength = 0; - end - - elseif isepoched - error('Support for epoched *.fif data is not yet implemented.') - end - - % remember the original header details - hdr.orig = orig; - - % these are useful to know in read_event - hdr.orig.isaverage = isaverage; - hdr.orig.iscontinuous = iscontinuous; - hdr.orig.isepoched = isepoched; - - case 'neuromag_mex' - % check that the required low-level toolbox is available - hastoolbox('meg-pd', 1); - rawdata('any',filename); - rawdata('goto', 0); - megmodel('head',[0 0 0],filename); - % get the available information from the fif file - [orig.rawdata.range,orig.rawdata.calib] = rawdata('range'); - [orig.rawdata.sf] = rawdata('sf'); - [orig.rawdata.samples] = rawdata('samples'); - [orig.chaninfo.N,orig.chaninfo.S,orig.chaninfo.T] = chaninfo; % Numbers, names & places - [orig.chaninfo.TY,orig.chaninfo.NA] = chaninfo('type'); % Coil type - [orig.chaninfo.NO] = chaninfo('noise'); % Default noise level - [orig.channames.NA,orig.channames.KI,orig.channames.NU] = channames(filename); % names, kind, logical numbers - % read a single trial to determine the data size - [buf, status] = rawdata('next'); - rawdata('close'); - - % This is to solve a problem reported by Doug Davidson: The problem - % is that rawdata('samples') is not returning the number of samples - % correctly. It appears that the example script rawchannels in meg-pd - % might work, however, so I want to use rawchannels to read in one - % channel of data in order to get the number of samples in the file: - if orig.rawdata.samples<0 - tmpchannel = 1; - tmpvar = rawchannels(filename,tmpchannel); - [orig.rawdata.samples] = size(tmpvar,2); - clear tmpvar tmpchannel; - end - - % convert to fieldtrip format header - hdr.label = orig.channames.NA; - hdr.Fs = orig.rawdata.sf; - hdr.nSamplesPre = 0; % I don't know how to get this out of the file - hdr.nChans = size(buf,1); - hdr.nSamples = size(buf,2); % number of samples per trial - hdr.nTrials = orig.rawdata.samples ./ hdr.nSamples; - % add a gradiometer structure for forward and inverse modelling - hdr.grad = fif2grad(filename); - % remember the original header details - hdr.orig = orig; - - case 'neuroprax_eeg' - orig = np_readfileinfo(filename); - - hdr.Fs = orig.fa; - hdr.nChans = orig.K; - hdr.nSamples = orig.N; - hdr.nSamplesPre = 0; % continuous - hdr.nTrials = 1; % continuous - hdr.label = orig.channels(:); - hdr.unit = orig.units(:); - - % remember the original header details - hdr.orig = orig; - - case 'nimh_cortex' - cortex = read_nimh_cortex(filename, 'epp', 'no', 'eog', 'no'); - % look at the first trial to determine whether it contains data in the EPP and EOG channels - trial1 = read_nimh_cortex(filename, 'epp', 'yes', 'eog', 'yes', 'begtrial', 1, 'endtrial', 1); - hasepp = ~isempty(trial1.epp); - haseog = ~isempty(trial1.eog); - if hasepp - warning('EPP channels are not yet supported'); - end - % at the moment only the EOG channels are supported here - if haseog - hdr.label = {'EOGx' 'EOGy'}; - hdr.nChans = 2; - else - hdr.label = {}; - hdr.nChans = 0; - end - hdr.nTrials = length(cortex); - hdr.nSamples = inf; - hdr.nSamplesPre = 0; - hdr.orig.trial = cortex; - hdr.orig.hasepp = hasepp; - hdr.orig.haseog = haseog; - - case 'ns_avg' - orig = read_ns_hdr(filename); - % do some reformatting/renaming of the header items - hdr.Fs = orig.rate; - hdr.nSamples = orig.npnt; - hdr.nSamplesPre = round(-orig.rate*orig.xmin/1000); - hdr.nChans = orig.nchan; - hdr.label = orig.label(:); - hdr.nTrials = 1; % the number of trials in this datafile is only one, i.e. the average - % remember the original header details - hdr.orig = orig; - - case {'ns_cnt' 'ns_cnt16', 'ns_cnt32'} - % read_ns_cnt originates from the EEGLAB package (loadcnt.m) but is - % an old version since the new version is not compatible any more - if strcmp(headerformat, 'ns_cnt') - orig = read_ns_cnt(filename, 'ldheaderonly', 1); - elseif strcmp(headerformat, 'ns_cnt16') - orig = read_ns_cnt(filename, 'ldheaderonly', 1, 'format', 16); - elseif strcmp(headerformat, 'ns_cnt32') - orig = read_ns_cnt(filename, 'ldheaderonly', 1, 'format', 32); - end - % do some reformatting/renaming of the header items - hdr.Fs = orig.rate; - hdr.nChans = orig.nchannels; - hdr.nSamples = orig.nsamples; - hdr.nSamplesPre = 0; - hdr.nTrials = 1; - for i=1:hdr.nChans - hdr.label{i} = deblank(orig.chan.names(i,:)); - end - % remember the original header details - hdr.orig = orig; - - case 'ns_eeg' - orig = read_ns_hdr(filename); - % do some reformatting/renaming of the header items - hdr.label = orig.label; - hdr.Fs = orig.rate; - hdr.nSamples = orig.npnt; - hdr.nSamplesPre = round(-orig.rate*orig.xmin/1000); - hdr.nChans = orig.nchan; - hdr.nTrials = orig.nsweeps; - % remember the original header details - hdr.orig = orig; - - case 'plexon_ds' - hdr = read_plexon_ds(filename); - - case 'plexon_ddt' - orig = read_plexon_ddt(filename); - hdr.nChans = orig.NChannels; - hdr.Fs = orig.Freq; - hdr.nSamples = orig.NSamples; - hdr.nSamplesPre = 0; % continuous - hdr.nTrials = 1; % continuous - warning('creating fake channel names'); - for i=1:hdr.nChans - hdr.label{i} = sprintf('%d', i); - end - % also remember the original header - hdr.orig = orig; - - case {'read_nex_data'} % this is an alternative reader for nex files - orig = read_nex_header(filename); - % assign the obligatory items to the output FCDC header - numsmp = cell2mat({orig.varheader.numsmp}); - adindx = find(cell2mat({orig.varheader.typ})==5); - if isempty(adindx) - error('file does not contain continuous channels'); - end - hdr.nChans = length(orig.varheader); - hdr.Fs = orig.varheader(adindx(1)).wfrequency; % take the sampling frequency from the first A/D channel - hdr.nSamples = max(numsmp(adindx)); % take the number of samples from the longest A/D channel - hdr.nTrials = 1; % it can always be interpreted as continuous data - hdr.nSamplesPre = 0; % and therefore it is not trial based - for i=1:hdr.nChans - hdr.label{i} = deblank(char(orig.varheader(i).nam)); - end - hdr.label = hdr.label(:); - % also remember the original header details - hdr.orig = orig; - - case {'read_plexon_nex' 'plexon_nex'} % this is the default reader for nex files - orig = read_plexon_nex(filename); - numsmp = cell2mat({orig.VarHeader.NPointsWave}); - adindx = find(cell2mat({orig.VarHeader.Type})==5); - if isempty(adindx) - error('file does not contain continuous channels'); - end - hdr.nChans = length(orig.VarHeader); - hdr.Fs = orig.VarHeader(adindx(1)).WFrequency; % take the sampling frequency from the first A/D channel - hdr.nSamples = max(numsmp(adindx)); % take the number of samples from the longest A/D channel - hdr.nTrials = 1; % it can always be interpreted as continuous data - hdr.nSamplesPre = 0; % and therefore it is not trial based - for i=1:hdr.nChans - hdr.label{i} = deblank(char(orig.VarHeader(i).Name)); - end - hdr.label = hdr.label(:); - hdr.FirstTimeStamp = orig.FileHeader.Beg; - hdr.TimeStampPerSample = orig.FileHeader.Frequency ./ hdr.Fs; - % also remember the original header details - hdr.orig = orig; - - case 'plexon_plx' - orig = read_plexon_plx(filename); - if orig.NumSlowChannels==0 - error('file does not contain continuous channels'); - end - fsample = [orig.SlowChannelHeader.ADFreq]; - if any(fsample~=fsample(1)) - error('different sampling rates in continuous data not supported'); - end - for i=1:length(orig.SlowChannelHeader) - label{i} = deblank(orig.SlowChannelHeader(i).Name); - end - % continuous channels don't always contain data, remove the empty ones - sel = [orig.DataBlockHeader.Type]==5; % continuous - chan = [orig.DataBlockHeader.Channel]; - for i=1:length(label) - chansel(i) = any(chan(sel)==orig.SlowChannelHeader(i).Channel); - end - chansel = find(chansel); % this is required for timestamp selection - label = label(chansel); - % only the continuous channels are returned as visible - hdr.nChans = length(label); - hdr.Fs = fsample(1); - hdr.label = label; - % also remember the original header - hdr.orig = orig; - - % select the first continuous channel that has data - sel = ([orig.DataBlockHeader.Type]==5 & [orig.DataBlockHeader.Channel]==orig.SlowChannelHeader(chansel(1)).Channel); - % get the timestamps that correspond with the continuous data - tsl = [orig.DataBlockHeader(sel).TimeStamp]'; - tsh = [orig.DataBlockHeader(sel).UpperByteOf5ByteTimestamp]'; - ts = timestamp_plexon(tsl, tsh); % use helper function, this returns an uint64 array - - % determine the number of samples in the continuous channels - num = [orig.DataBlockHeader(sel).NumberOfWordsInWaveform]; - hdr.nSamples = sum(num); - hdr.nSamplesPre = 0; % continuous - hdr.nTrials = 1; % continuous - - % the timestamps indicate the beginning of each block, hence the timestamp of the last block corresponds with the end of the previous block - hdr.TimeStampPerSample = double(ts(end)-ts(1))/sum(num(1:(end-1))); - hdr.FirstTimeStamp = ts(1); % the timestamp of the first continuous sample - - % also make the spike channels visible - for i=1:length(orig.ChannelHeader) - hdr.label{end+1} = deblank(orig.ChannelHeader(i).Name); - end - hdr.label = hdr.label(:); - hdr.nChans = length(hdr.label); - - case {'yokogawa_ave', 'yokogawa_con', 'yokogawa_raw'} - % chek that the required low-level toolbox is available - hastoolbox('yokogawa', 1); - hdr = read_yokogawa_header(filename); - % add a gradiometer structure for forward and inverse modelling - hdr.grad = yokogawa2grad(hdr); - - case 'nmc_archive_k' - hdr = read_nmc_archive_k_hdr(filename); - - otherwise - if strcmp(fallback, 'biosig') && hastoolbox('BIOSIG', 1) - hdr = read_biosig_header(filename); - else - error('unsupported header format'); - end -end - -% ensure that these are double precision and not integers, otherwise -% subsequent computations that depend on these might be messed up -hdr.Fs = double(hdr.Fs); -hdr.nSamples = double(hdr.nSamples); -hdr.nSamplesPre = double(hdr.nSamplesPre); -hdr.nTrials = double(hdr.nTrials); -hdr.nChans = double(hdr.nChans); - -if cache && exist(headerfile, 'file') - % put the header in the cache - cacheheader = hdr; - % update the header details (including time stampp, size and name) - cacheheader.details = dir(headerfile); - % fprintf('added header to cache\n'); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION to determine the file size in bytes -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [siz] = filesize(filename) -l = dir(filename); -if l.isdir - error(sprintf('"%s" is not a file', filename)); -end -siz = l.bytes; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION to determine the file size in bytes -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [hdr] = recursive_read_header(filename) -[p, f, x] = fileparts(filename); -ls = dir(filename); -ls = ls(~strcmp({ls.name}, '.')); % exclude this directory -ls = ls(~strcmp({ls.name}, '..')); % exclude parent directory -for i=1:length(ls) - % make sure that the directory listing includes the complete path - ls(i).name = fullfile(filename, ls(i).name); -end -lst = {ls.name}; -hdr = cell(size(lst)); -sel = zeros(size(lst)); -for i=1:length(lst) - % read the header of each individual file - try - thishdr = read_header(lst{i}); - if isstruct(thishdr) - thishdr.filename = lst{i}; - end - catch - thishdr = []; - warning(lasterr); - fprintf('while reading %s\n\n', lst{i}); - end - if ~isempty(thishdr) - hdr{i} = thishdr; - sel(i) = true; - else - sel(i) = false; - end -end -sel = logical(sel(:)); -hdr = hdr(sel); -tmp = {}; -for i=1:length(hdr) - if isstruct(hdr{i}) - tmp = cat(1, tmp, hdr(i)); - elseif iscell(hdr{i}) - tmp = cat(1, tmp, hdr{i}{:}); - end -end -hdr = tmp; - diff --git a/external/fieldtrip/private/read_headshape.m b/external/fieldtrip/private/read_headshape.m deleted file mode 100644 index 92b2f02..0000000 --- a/external/fieldtrip/private/read_headshape.m +++ /dev/null @@ -1,267 +0,0 @@ -function [shape] = read_headshape(filename, varargin) - -% READ_HEADSHAPE reads the fiducials and/or the measured headshape -% from a variety of files (like CTF and Polhemus). The headshape and -% fiducials can for example be used for coregistration. -% -% Use as -% [shape] = read_headshape(filename) -% -% See also READ_VOL, READ_SENS - -% Copyright (C) 2008, Robert Oostenveld -% -% $Log: read_headshape.m,v $ -% Revision 1.13 2009/09/26 10:46:25 vlalit -% Added 4d_pdf to the list of BTi formats -% -% Revision 1.12 2009/04/01 16:59:43 vlalit -% Slight fix for JMs fix to assign unique names to the other BTi fiducials. Also make -% sure that fid.label is a column cell array. -% -% Revision 1.11 2009/03/31 12:18:48 jansch -% added additional fiducials to shape.fid for 4D hs_files -% -% Revision 1.10 2009/03/23 12:09:07 vlalit -% Minor changes to make the ctf_old option fully functional. -% -% Revision 1.9 2009/03/17 10:58:13 vlalit -% Switched to MNE reader as default for Neuromag in read_headshape -% -% Revision 1.8 2009/01/28 18:29:07 vlalit -% Added '4d' type to BTi case -% -% Revision 1.7 2009/01/23 10:32:55 vlalit -% New reader for Neuromag fif format using the MNE toolbox (http://www.nmr.mgh.harvard.edu/martinos/userInfo/data/sofMNE.php) implemented by Laurence Hunt. -% -% Revision 1.6 2008/10/07 16:22:32 roboos -% added option to specify coordinates to be obtained from ctf hc file -% -% Revision 1.5 2008/05/22 14:33:18 vlalit -% Changes related to generalization of fiducials' handling in SPM. -% -% Revision 1.4 2008/05/11 16:30:30 vlalit -% Improved the support of 4d and neuromag -% -% Revision 1.3 2008/04/16 08:04:03 roboos -% allow headshape to be extracted from BEM volume conduction model -% -% Revision 1.2 2008/04/14 20:52:11 roboos -% ensure consistent output for all file formats (thanks to Vladimir) -% added convert_units -% -% Revision 1.1 2008/04/11 12:04:55 roboos -% new impoementation, required for clean interface towards SPM -% - -% test whether the file exists -if ~exist(filename) - error(sprintf('file ''%s'' does not exist', filename)); -end - -% get the options -fileformat = keyval('fileformat', varargin); -coordinates = keyval('coordinates', varargin); if isempty(coordinates), coordinates = 'head'; end - -if isempty(fileformat) - fileformat = filetype(filename); -end - -% start with an empty structure -shape = []; -shape.pnt = []; -shape.fid.pnt = []; -shape.fid.label = {}; - -switch fileformat - case {'ctf_ds', 'ctf_hc', 'ctf_meg4', 'ctf_res4', 'ctf_old'} - [p, f, x] = fileparts(filename); - - if strcmp(fileformat, 'ctf_old') - fileformat = filetype(filename); - end - - if strcmp(fileformat, 'ctf_ds') - filename = fullfile(p, [f x], [f '.hc']); - elseif strcmp(fileformat, 'ctf_meg4') - filename = fullfile(p, [f '.hc']); - elseif strcmp(fileformat, 'ctf_res4') - filename = fullfile(p, [f '.hc']); - end - - orig = read_ctf_hc(filename); - switch coordinates - case 'head' - shape.fid.pnt = cell2mat(struct2cell(orig.head)); - case 'dewar' - shape.fid.pnt = cell2mat(struct2cell(orig.dewar)); - otherwise - error('incorrect coordinates specified'); - end - shape.fid.label = fieldnames(orig.head); - - case 'ctf_shape' - orig = read_ctf_shape(filename); - shape.pnt = orig.pnt; - shape.fid.label = {'NASION', 'LEFT_EAR', 'RIGHT_EAR'}; - for i = 1:numel(shape.fid.label) - shape.fid.pnt = cat(1, shape.fid.pnt, ... - getfield(orig.MRI_Info, shape.fid.label{i})); - end - - case {'4d_xyz', '4d_m4d', '4d_hs', '4d', '4d_pdf'} - [p, f, x] = fileparts(filename); - if ~strcmp(fileformat, '4d_hs') - filename = fullfile(p, 'hs_file'); - end - [shape.pnt, fid] = read_bti_hs(filename); - - % I'm making some assumptions here - % which I'm not sure will work on all 4D systems - - %fid = fid(1:3, :); - - [junk, NZ] = max(fid(1:3,1)); - [junk, L] = max(fid(1:3,2)); - [junk, R] = min(fid(1:3,2)); - rest = setdiff(1:size(fid,1),[NZ L R]); - - shape.fid.pnt = fid([NZ L R rest], :); - shape.fid.label = {'NZ', 'L', 'R'}; - if ~isempty(rest), - for i = 4:size(fid,1) - shape.fid.label{i} = ['fiducial' num2str(i)]; - %in a 5 coil configuration this corresponds with Cz and Inion - end - end - case 'neuromag_mex' - [co,ki,nu] = hpipoints(filename); - fid = co(:,find(ki==1))'; - - [junk, NZ] = max(fid(:,2)); - [junk, L] = min(fid(:,1)); - [junk, R] = max(fid(:,1)); - - shape.fid.pnt = fid([NZ L R], :); - shape.fid.label = {'NZ', 'L', 'R'}; - - case {'neuromag_mne', 'neuromag_fif'} - hdr = read_header(filename,'headerformat','neuromag_mne'); - nFid = size(hdr.orig.dig,2); %work out number of fiducials - switch coordinates - case 'head' % digitiser points should be stored in head coordinates by default - - fidN=1; - pntN=1; - for i=1:nFid %loop over fiducials - %check this point is in head coordinates: - if hdr.orig.dig(i).coord_frame~=4 % 4 is MNE constant for head coordinates - error(['Digitiser point (' num2str(i) ') not stored in head coordinates!']); - end - - - switch hdr.orig.dig(i).kind % constants defined in MNE - see p.215 of MNE manual - case 1 % Cardinal point (nasion, LPA or RPA) - %get location of fiducial: - shape.fid.pnt(fidN,1:3) = hdr.orig.dig(i).r*100; %multiply by 100 to convert to cm - switch hdr.orig.dig(i).ident - case 1 % LPA - shape.fid.label{fidN} = 'LPA'; - case 2 % nasion - shape.fid.label{fidN} = 'Nasion'; - case 3 % RPA - shape.fid.label{fidN} = 'RPA'; - otherwise - error('Unidentified cardinal point in file!'); - end - fidN = fidN + 1; - - case 2 % HPI coil - shape.pnt(pntN,1:3) = hdr.orig.dig(i).r*100; - pntN = pntN + 1; - case 3 % EEG electrode location (or ECG) - shape.pnt(pntN,1:3) = hdr.orig.dig(i).r*100; - pntN = pntN + 1; - case 4 % Additional head point - shape.pnt(pntN,1:3) = hdr.orig.dig(i).r*100; - pntN = pntN + 1; - otherwise - warning('Unidentified digitiser point in file!'); - end - - end - shape.fid.label=shape.fid.label'; - - case 'dewar' - error('Dewar coordinates not supported for headshape yet (MNE toolbox)'); - otherwise - error('Incorrect coordinates specified'); - end - - case 'polhemus_fil' - [shape.fid.pnt, shape.pnt, shape.fid.label] = read_polhemus_fil(filename, 0); - - case 'spmeeg_mat' - tmp = load(filename); - if isfield(tmp.D, 'fiducials') && ~isempty(tmp.D.fiducials) - shape = tmp.D.fiducials; - else - error('no headshape found in SPM EEG file'); - end - - case 'matlab' - tmp = load(filename); - if isfield(tmp, 'shape') - shape = tmp.shape; - elseif isfield(tmp, 'elec') - shape.fid.pnt = tmp.elec.pnt; - shape.fid.label = tmp.elec.label; - else - error('no headshape found in Matlab file'); - end - - otherwise - - success = 0; - if ~success - % try reading it as electrode positions - % and treat those as fiducials - try - elec = read_sens(filename); - if ~senstype(elec, 'eeg') - error('headshape information can not be read from MEG gradiometer file'); - else - shape.fid.pnt = elec.pnt; - shape.fid.label = elec.label; - success = 1; - end - end - end - - if ~success - % try reading it as volume conductor - % and treat the skin surface as headshape - try - vol = read_vol(filename); - if ~voltype(vol, 'bem') - error('skin surface can only be extracted from boundary element model'); - else - if ~isfield(vol, 'skin') - vol.skin = find_outermost_boundary(vol.bnd); - end - shape.pnt = vol.bnd(vol.skin).pnt; - shape.tri = vol.bnd(vol.skin).tri; % also return the triangulation - success = 1; - end - end - end - - if ~success - error('unknown fileformat for head shape information'); - end -end - -shape.fid.label = shape.fid.label(:); - -% this will add the units to the head shape -shape = convert_units(shape); diff --git a/external/fieldtrip/private/read_labview_dtlg.m b/external/fieldtrip/private/read_labview_dtlg.m new file mode 100644 index 0000000..dd2d5de --- /dev/null +++ b/external/fieldtrip/private/read_labview_dtlg.m @@ -0,0 +1,154 @@ +function [dat] = read_labview_dtlg(filename, datatype); + +% READ_LABVIEW_DTLG +% +% Use as +% dat = read_labview_dtlg(filename, datatype) +% where datatype can be 'int32' or 'int16' +% +% The output of this function is a structure. + +% Copyright (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_labview_dtlg.m 945 2010-04-21 17:41:20Z roboos $ + + +fid = fopen(filename, 'r', 'ieee-be'); + +header = fread(fid, 4, 'uint8=>char')'; +if ~strcmp(header, 'DTLG') + error('unsupported file, header should start with DTLG'); +end + +version = fread(fid, 4, 'char')'; % clear version +nd = fread(fid, 1, 'int32'); +p = fread(fid, 1, 'int32'); + +% the following seems to work for files with version [7 0 128 0] +% but in files files with version [8 0 128 0] the length of the descriptor is not correct +ld = fread(fid, 1, 'int16'); +descriptor = fread(fid, ld, 'uint8=>char')'; + +% ROBOOS: the descriptor should ideally be decoded, since it contains the variable +% name, type and size + +% The first offset block always starts immediately after the data descriptor (at offset p, which should ideally be equal to 16+ld) +if nd<=128 + % The first offset block contains the offsets for all data sets. + % In this case P points to the start of the offset block. + fseek(fid, p, 'bof'); + offset = fread(fid, 128, 'uint32')'; +else + % The first offset block contains the offsets for the first 128 data sets. + % The entries for the remaining data sets are stored in additional offset blocks. + % The locations of those blocks are contained in a block table starting at P. + offset = []; + fseek(fid, p, 'bof'); + additional = fread(fid, 128, 'uint32'); + for i=1:sum(additional>0) + fseek(fid, additional(i), 'bof'); + tmp = fread(fid, 128, 'uint32')'; + offset = cat(2, offset, tmp); + end + clear additional i tmp +end + +% ROBOOS: remove the zeros in the offset array for non-existing datasets +offset = offset(1:nd); + +% ROBOOS: how to determine the data datatype? +switch datatype + case 'uint32' + datasize = 4; + case 'int32' + datasize = 4; + case 'uint16' + datasize = 2; + case 'int16' + datasize = 2; + otherwise + error('unsupported datatype'); +end + +% If the data sets are n-dimensional arrays, the first n u32 longwords in each data +% set contain the array dimensions, imediately followed by the data values. + +% ROBOOS: how to determine whether they are n-dimensional arrays? + +% determine the number of dimensions by looking at the first array +% assume that all subsequent arrays have the same number of dimensions +if nd>1 + estimate = (offset(2)-offset(1)); % initial estimate for the number of datasize in the array + fseek(fid, offset(1), 'bof'); + n = fread(fid, 1, 'int32'); + while mod(estimate-4*length(n), (datasize*prod(n)))~=0 + % determine the number and size of additional array dimensions + n = cat(1, n, fread(fid, 1, 'int32')); + if datasize*prod(n)>estimate + error('could not determine array size'); + end + end + ndim = length(n); + clear estimate n +else + estimate = filesize(fid)-offset; + fseek(fid, offset(1), 'bof'); + n = fread(fid, 1, 'int32'); + while mod(estimate-4*length(n), (datasize*prod(n)))~=0 + % determine the number and size of additional array dimensions + n = cat(1, n, fread(fid, 1, 'int32')); + if datasize*prod(n)>estimate + error('could not determine array size'); + end + end + ndim = length(n); + clear estimate n +end + +% read the dimensions and the data from each array +for i=1:nd + fseek(fid, offset(i), 'bof'); + n = fread(fid, ndim, 'int32')'; + % Labview uses the C-convention for storing data, and Matlab uses the Fortran convention + n = fliplr(n); + data{i} = fread(fid, n, datatype); +end +clear i n ndim + +fclose(fid); + +% put all local variables into a structure, this is a bit unusual programming style +% the output structure is messy, but contains all relevant information +tmp = whos; +dat = []; +for i=1:length(tmp) + if isempty(strmatch(tmp(i).name, {'tmp', 'fid', 'ans', 'handles'})) + dat = setfield(dat, tmp(i).name, eval(tmp(i).name)); + end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% local helper function to determine the size of the file +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function siz = filesize(fid) +fp = ftell(fid); +fseek(fid, 0, 'eof'); +siz = ftell(fid); +fseek(fid, fp, 'bof'); + diff --git a/external/fieldtrip/private/read_lay.m b/external/fieldtrip/private/read_lay.m deleted file mode 100644 index 2eee348..0000000 --- a/external/fieldtrip/private/read_lay.m +++ /dev/null @@ -1,14 +0,0 @@ -function [X,Y,Width,Height,Lbl] = read_lay(layoutname); - -% READ_LAY reads an electrode or gradiometer layout file -% Layout files are used for topoplotting and multiplotting. -% -% Use as -% [X, Y, Width, Height, Lbl] = read_lay(layoutname) - -if ~exist(layoutname, 'file') - error(sprintf('could not open layout file: %s', layoutname)); -end - -% discard the channel number -[chNum,X,Y,Width,Height,Lbl] = textread(layoutname,'%f %f %f %f %f %q'); diff --git a/external/fieldtrip/private/read_mpi_ds.m b/external/fieldtrip/private/read_mpi_ds.m deleted file mode 100644 index 8d98d28..0000000 --- a/external/fieldtrip/private/read_mpi_ds.m +++ /dev/null @@ -1,89 +0,0 @@ -function [hdr, dat] = read_mpi_ds(dirname) - -% READ_MPI_DS reads all DAP files from a directory containing files or -% alternatively a single DAP file and returns it in a simplified FieldTrip -% format. The analog channels and spike channels are both returned in a -% continuous format. -% -% Use as -% [hdr, dat] = read_mpi_ds(dirname) -% or -% [hdr, dat] = read_mpi_ds(filename) -% -% See also READ_MPI_DAP - -% Copyright (C) 2005-2007, Robert Oostenveld -% -% $Log: read_mpi_ds.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry -% -% Revision 1.4 2007/03/19 16:53:49 roboos -% allow for multiple spikes at the same sample (i.e. increment by 1 for each spike) -% - -hdr = []; -dat = []; - -if isdir(dirname) - ls = dir(dirname); - dapfile = {}; - for i=1:length(ls) - if ~isempty(regexp(ls(i).name, '.dap$')) - dapfile{end+1} = fullfile(dirname, ls(i).name); - end - end - dapfile = sort(dapfile); -elseif iscell(dirname) - dapfile = dirname; -else - dapfile = {dirname}; -end - -for i=1:length(dapfile) - dap = read_mpi_dap(dapfile{i}); - siz = size(dap.analoghdr); - nanalog = dap.filehdr.nanalog; - nspike = dap.filehdr.nspike; - nexp(i) = siz(1); - nsweep(i) = siz(2); - nsample(i) = length(dap.analog{1}); - analog = zeros(nanalog, nsample(i)*nsweep(i)*nexp(i)); - spike = zeros(nspike , nsample(i)*nsweep(i)*nexp(i)); - % only collect the data when required - if nargout>1 - % collect all analog data of all sweeps in a single matrix - for e=1:nexp(i) - for s=1:nsweep(i) - for c=1:nanalog - begsample = (e*s-1) * nsample(i) + 1; - endsample = (e*s ) * nsample(i); - analog(c,begsample:endsample) = dap.analog{e,s,c}(:)'; - end - end - end - % collect all spike data of all sweeps in a single matrix - for e=1:nexp(i) - for s=1:nsweep(i) - for c=1:nspike - spike(c,dap.spike{e,s,c} + (e*s-1) * nsample(i)) = spike(c,dap.spike{e,s,c} + (e*s-1) * nsample(i)) + 1; - end - end - end - dat = cat(1, analog, spike); - end % if nargout -end - -hdr.Fs = 1000; % sampling frequency -hdr.nChans = nanalog+nspike; % number of channels -hdr.nSamples = nsample(1); % number of samples per trial -hdr.nSamplesPre = 0; % number of pre-trigger samples in each trial -hdr.nTrials = sum(nsweep.*nexp); % number of trials -hdr.label = {}; % cell-array with labels of each channel -for i=1:nanalog - hdr.label{i} = sprintf('analog%02d', i); -end -for i=1:nspike - hdr.label{nanalog+i} = sprintf('spike%02d', i); -end - diff --git a/external/fieldtrip/private/read_mri.m b/external/fieldtrip/private/read_mri.m deleted file mode 100644 index ecf08de..0000000 --- a/external/fieldtrip/private/read_mri.m +++ /dev/null @@ -1,319 +0,0 @@ -function [mri] = read_mri(filename) - -% READ_MRI reads anatomical and functional MRI data from different -% file formats. The output data is structured in such a way that it is -% comparable to a FieldTrip source reconstruction. -% -% Use as -% [mri] = read_mri(filename) -% -% The output MRI may have a homogenous transformation matrix that converts -% the coordinates of each voxel (in xgrid/ygrid/zgrid) into head -% coordinates. -% -% See also READ_DATA, READ_HEADER, READ_EVENT - -% Copyright (C) 2004-2009, Robert Oostenveld -% -% $Log: read_mri.m,v $ -% Revision 1.11 2009/07/16 12:57:12 roboos -% fixed fprintf feedback for dicom reader -% -% Revision 1.10 2009/07/09 15:07:59 roboos -% use another coordinate transformation matrix for fif MRI -% -% Revision 1.9 2009/07/08 08:08:45 roboos -% also support mne toolbox fiff_read_mri function -% -% Revision 1.8 2009/07/07 10:40:37 roboos -% Improved handling of sequence of files, also when the files don't have nice names. -% Use SeriesNumber from the DICOM header to figure out which slices go together. -% -% Revision 1.7 2009/07/02 15:04:09 roboos -% construct transformation matrix for dicom files -% -% Revision 1.6 2009/03/11 15:02:18 vlalit -% Use either SPM5 or SPM8 to read *.nii files. -% -% Revision 1.5 2009/02/17 11:33:18 roboos -% renamed read_fcdc_mri to read_mri and moved to fileio -% -% Revision 1.19 2008/12/16 21:22:23 roboos -% changed some comments and documentation -% -% Revision 1.18 2008/11/28 10:25:51 roboos -% added ctf_mri4, thanks to Ivar -% -% Revision 1.17 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.16 2007/05/06 09:09:18 roboos -% added support for nifti, requires SPM5 -% -% Revision 1.15 2007/02/21 10:00:37 roboos -% give a more meaningfull warning when trying to read a mnc file without spm2 on the path -% -% Revision 1.14 2006/07/27 08:01:32 roboos -% use the hastoolbox function to detect the required toolboxes -% -% Revision 1.13 2006/04/19 15:46:43 roboos -% fixed bug for dicom when files are in another directory -% -% Revision 1.12 2006/04/19 07:54:51 roboos -% added support foir multifile DICOM format (searching for similar files) -% removed the trivial x/y/zgrid in the output structure -% -% Revision 1.11 2006/01/05 13:27:59 roboos -% change for avw_img_read(): force reading LAS* and flip the 1st dimension -% -% Revision 1.10 2005/09/08 07:32:48 roboos -% changed & into && -% modified hasafni to check for BrikInfo instead of WriteBrik -% -% Revision 1.9 2005/08/17 19:35:30 roboos -% added a check for the presence of the file, give error if not present -% -% Revision 1.8 2005/07/20 15:33:35 roboos -% added a homogenous transformation matrix to AFNI import section -% I am not sure whether it is correct, but it works like this for the TTatlas -% -% Revision 1.7 2005/05/17 17:50:38 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.6 2004/10/28 09:41:20 roboos -% added preliminary support for AFNI mri files (no transformation matrix yet) using external afni_matlab toolbox -% -% Revision 1.5 2004/09/06 13:29:05 roboos -% fixed bug in transform for neuromag -% -% Revision 1.4 2004/09/03 09:17:49 roboos -% added support for neuromag MRI from fif file -% -% Revision 1.3 2004/08/26 12:12:50 roboos -% added transformation matrix for ASA files -% -% Revision 1.2 2004/08/26 11:57:22 roboos -% added support for MINC using SPM -% added support for Analyze using SPM -% -% Revision 1.1 2004/08/24 13:52:50 roboos -% new implementation, currently implemented are CTF, ASA and Analyze (with mri-toolbox) -% - -fieldtripdefs - -% test for the presence of some external functions from other toolboxes -hasmri = hastoolbox('mri'); % from Darren Weber, see http://eeg.sourceforge.net/ -hasspm2 = hastoolbox('spm2'); % see http://www.fil.ion.ucl.ac.uk/spm/ -hasspm5 = hastoolbox('spm5'); % see http://www.fil.ion.ucl.ac.uk/spm/ -hasspm8 = hastoolbox('spm8'); % see http://www.fil.ion.ucl.ac.uk/spm/ -hasspm = (hasspm2 || hasspm5 || hasspm8); -hasafni = hastoolbox('afni'); % see http://afni.nimh.nih.gov/ - -% test whether the file exists -if ~exist(filename) - error(sprintf('file ''%s'' does not exist', filename)); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if filetype(filename, 'ctf_mri') - [img, hdr] = read_ctf_mri(filename); - transform = hdr.transformMRI2Head; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif filetype(filename, 'ctf_mri4') - [img, hdr] = read_ctf_mri4(filename); - transform = hdr.transformMRI2Head; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif filetype(filename, 'asa_mri') - [img, seg, hdr] = read_asa_mri(filename); - transform = hdr.transformMRI2Head; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif filetype(filename, 'minc') - if ~hasspm - error('the SPM2 or SPM5 toolbox is required to read *.mnc files'); - end - % use the functions from SPM - hdr = spm_vol_minc(filename); - img = spm_read_vols(hdr); - transform = hdr.mat; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif filetype(filename, 'nifti') - if ~(hasspm5 || hasspm8) - error('the SPM5 or SPM8 toolbox is required to read *.nii files'); - end - % use the functions from SPM - hdr = spm_vol_nifti(filename); - img = spm_read_vols(hdr); - transform = hdr.mat; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif (filetype(filename, 'analyze_img') || filetype(filename, 'analyze_hdr')) && hasspm - % use the image file instead of the header - filename((end-2):end) = 'img'; - % use the functions from SPM to read the Analyze MRI - hdr = spm_vol(filename); - img = spm_read_vols(hdr); - transform = hdr.mat; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif (filetype(filename, 'analyze_hdr') || filetype(filename, 'analyze_img')) && hasmri - % use the functions from Darren Weber's mri_toolbox to read the Analyze MRI - avw = avw_img_read(filename, 0); % returned volume is LAS* - img = avw.img; - hdr = avw.hdr; - % The default Analyze orientation is axial unflipped (LAS*), which means - % that the resulting volume is according to the radiological convention. - % Most other fMRI and EEG/MEG software (except Mayo/Analyze) uses - % neurological conventions and a right-handed coordinate system, hence - % the first axis of the 3D volume (right-left) should be flipped to make - % the coordinate system comparable to SPM - warning('flipping 1st dimension (L-R) to obtain volume in neurological convention'); - img = flipdim(img, 1); - % FIXME: here I should also implement a homogenous transformation matrix, - % using the voxel dimensions that are specified in hdr.dime.pixdim - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif (filetype(filename, 'afni_brik') || filetype(filename, 'afni_head')) && hasafni - [err, img, hdr, ErrMessage] = BrikLoad(filename); - if err - error('could not read AFNI file'); - end - - % FIXME: this should be checked, but I only have a single BRIK file - % construct the homogenous transformation matrix that defines the axes - warning('homogenous transformation might be incorrect for AFNI file'); - transform = eye(4); - transform(1:3,4) = hdr.ORIGIN(:); - transform(1,1) = hdr.DELTA(1); - transform(2,2) = hdr.DELTA(2); - transform(3,3) = hdr.DELTA(3); - - % FIXME: I am not sure about the "RAI" image orientation - img = flipdim(img,1); - img = flipdim(img,2); - dim = size(img); - transform(1,4) = -dim(1) - transform(1,4); - transform(2,4) = -dim(2) - transform(2,4); - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif filetype(filename, 'neuromag_fif') && hastoolbox('mne') - % use the mne functions to read the Neuromag MRI - hdr = fiff_read_mri(filename); - img = cat(3, hdr.slices.data); - hdr.slices = rmfield(hdr.slices, 'data'); % remove the image data to save memory - % hmm, which transformation matrix should I use? - if issubfield(hdr.voxel_trans, 'trans') - transform = hdr.voxel_trans.trans; - elseif issubfield(hdr.trans, 'trans') - transform = hdr.trans.trans; - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif filetype(filename, 'neuromag_fif') && hastoolbox('meg_pd') - % use the meg_pd functions to read the Neuromag MRI - [img,coords] = loadmri(filename); - dev = loadtrans(filename,'MRI','HEAD'); - transform = dev*coords; - hdr.coords = coords; - hdr.dev = dev; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif filetype(filename, 'neuromag_fif') - error('reading MRI data from a fif file requires either the MNE toolbox or the meg_pd toolbox to be installed'); - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif filetype(filename, 'dicom') - % this uses the Image processing toolbox - % the DICOM file probably represents a stack of slices, possibly even multiple volumes - orig = dicominfo(filename); - dim(1) = orig.Rows; - dim(2) = orig.Columns; - - [p, f] = fileparts(filename); - - % this works for the Siemens scanners at the FCDC - tok = tokenize(f, '.'); - for i=5:length(tok) - tok{i} = '*'; - end - filename = sprintf('%s.', tok{:}); % reconstruct the filename with wildcards and '.' between the segments - filename = filename(1:end-1); % remove the last '.' - dirlist = dir(fullfile(p, filename)); - dirlist = {dirlist.name}; - - if length(dirlist)==1 - % try something else to get a list of all the slices - dirlist = dir(fullfile(p, '*')); - dirlist = {dirlist(~[dirlist.isdir]).name}; - end - - keep = false(1, length(dirlist)); - for i=1:length(dirlist) - filename = char(fullfile(p, dirlist{i})); - if ~filetype(filename, 'dicom') - keep(i) = false; - fprintf('skipping ''%s'' because of incorrect filetype\n', filename); - end - % read the header information - info = dicominfo(filename); - if info.SeriesNumber~=orig.SeriesNumber - keep(i) = false; - fprintf('skipping ''%s'' because of different SeriesNumber\n', filename); - else - keep(i) = true; - hdr(i) = info; - end - end - % remove the files that were skipped - hdr = hdr(keep); - dirlist = dirlist(keep); - - % pre-allocate enough space for the subsequent slices - dim(3) = length(dirlist); - img = zeros(dim(1), dim(2), dim(3)); - for i=1:length(dirlist) - filename = char(fullfile(p, dirlist{i})); - fprintf('reading image data from ''%s''\n', filename); - img(:,:,i) = dicomread(hdr(i)); - end - - % reorder the slices - [z, indx] = sort(cell2mat({hdr.SliceLocation})); - hdr = hdr(indx); - img = img(:,:,indx); - - try - % construct a homgenous transformation matrix that performs the scaling from voxels to mm - dx = hdr(1).PixelSpacing(1); - dy = hdr(1).PixelSpacing(2); - dz = hdr(2).SliceLocation - hdr(1).SliceLocation; - transform = eye(4); - transform(1,1) = dx; - transform(2,2) = dy; - transform(3,3) = dz; - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -else - error(sprintf('unrecognized filetype of ''%s''', filename)); -end - -% set up the axes of the volume in voxel coordinates -nx = size(img,1); -ny = size(img,2); -nz = size(img,3); -mri.dim = [nx ny nz]; -% store the anatomical data -mri.anatomy = img; -% store the header with all fileformat specific details -mri.hdr = hdr; -try - % if present, store the homogenous transformation matrix - mri.transform = transform; -end - diff --git a/external/fieldtrip/private/read_neuralynx_bin.m b/external/fieldtrip/private/read_neuralynx_bin.m index f329568..0dfbab6 100644 --- a/external/fieldtrip/private/read_neuralynx_bin.m +++ b/external/fieldtrip/private/read_neuralynx_bin.m @@ -27,41 +27,23 @@ % Copyright (C) 2007-2008, Robert Oostenveld % -% $Log: read_neuralynx_bin.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.5 2008/09/30 08:01:04 roboos -% replaced all fread(char=>char) into uint8=>char to ensure that the -% chars are read as 8 bits and not as extended 16 bit characters. The -% 16 bit handling causes problems on some internationalized OS/Matlab -% combinations. +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% the help of fread specifies "If the precision is 'char' or 'char*1', MATLAB -% reads characters using the encoding scheme associated with the file. -% See FOPEN for more information". +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.4 2008/07/01 13:00:58 roboos -% optionally read the 16384 byte ascii header instead of hard-coded defaults -% -% Revision 1.3 2008/05/27 13:04:58 roboos -% switched to the 3rd version of the file format, which includes the downscale/calibration value to recover from int32->int16 compression -% added explicit support for version 1, 2 and 3 of the fileformat -% added original details to the output header -% -% Revision 1.2 2007/12/17 16:23:44 roboos -% fixed bug in jumping to correct begin sample -% added support for determining channel name from filename like this "dataset.chanlabel.bin" -% added support for old splitted dma files, which have an 8 byte header with the channel label and are always int32 -% -% Revision 1.1 2007/12/12 16:28:42 roboos -% first implementation +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: read_neuralynx_bin.m 945 2010-04-21 17:41:20Z roboos $ needhdr = (nargin==1); needdat = (nargin>=2); diff --git a/external/fieldtrip/private/read_neuralynx_cds.m b/external/fieldtrip/private/read_neuralynx_cds.m deleted file mode 100644 index e5c5b7b..0000000 --- a/external/fieldtrip/private/read_neuralynx_cds.m +++ /dev/null @@ -1,150 +0,0 @@ -function [dat] = read_neuralynx_cds(filename, hdr, begsample, endsample, chanindx); - -% READ_NEURALYNX_CDS reads selected samples and channels from a combined Neuralynx dataset with seperate subdirectories for the LFP, MUA and spike channels -% -% Use as -% hdr = read_neuralynx_cds(parentdir) -% dat = read_neuralynx_cds(parentdir, hdr, begsample, endsample, chanindx) - -% Copyright (C) 2006, Robert Oostenveld -% -% $Log: read_neuralynx_cds.m,v $ -% Revision 1.1 2006/12/13 15:45:57 roboos -% new implementation, partially based on the old read_neuralynx_data and header function, but now more strongly relying on the xxx_ds function that reads header and data information from all datasets that are combined -% - -needhdr = (nargin==1); -needdat = (nargin>=2); - -dirlist = dir(filename); -haslfp = any(filetype_check_extension({dirlist.name}, 'lfp')); -hasmua = any(filetype_check_extension({dirlist.name}, 'mua')); -hasspike = any(filetype_check_extension({dirlist.name}, 'spike')); -%hasttl = any(filetype_check_extension({dirlist.name}, 'ttl')); % seperate file with original Parallel_in -%hastsl = any(filetype_check_extension({dirlist.name}, 'tsl')); % seperate file with original TimeStampLow -%hastsh = any(filetype_check_extension({dirlist.name}, 'tsh')); % seperate file with original TimeStampHi - -if needhdr - % read the header from the LFP dataset - if haslfp - lfpdir = fullfile(filename, dirlist(find(filetype_check_extension({dirlist.name}, 'lfp'))).name); - lfphdr = read_header(lfpdir); - lfpfil = lfphdr.filename; - for i=1:lfphdr.nChans - lfplab{i} = sprintf('lfp_%s', lfphdr.label{i}); - end - else - lfphdr = []; - lfpfil = {}; - lfplab = {}; - end - - % read the header from the MUA dataset - if hasmua - muadir = fullfile(filename, dirlist(find(filetype_check_extension({dirlist.name}, 'mua'))).name); - muahdr = read_header(muadir); - muafil = muahdr.filename; - for i=1:muahdr.nChans - mualab{i} = sprintf('mua_%s', muahdr.label{i}); - end - else - muahdr = []; - muafil = {}; - mualab = {}; - end - - % read the header from the SPIKE dataset - if hasspike - spikedir = fullfile(filename, dirlist(find(filetype_check_extension({dirlist.name}, 'spike'))).name); - spikehdr = read_header(spikedir); - spikefil = spikehdr.filename; - for i=1:spikehdr.nChans - spikelab{i} = sprintf('spike_%s', spikehdr.label{i}); - end - else - spikehdr = []; - spikefil = {}; - spikelab = {}; - end - - if haslfp - % assume that the LFP header describes the MUA and the spikes as well - hdr = lfphdr; - else hasmua - % assume that the MUA header describes the spikes as well - hdr = muahdr; - end - - % concatenate the lfp/mua/spike channels, they have already been renamed - hdr.label = cat(1, lfplab(:), mualab(:), spikelab(:)); - hdr.filename = cat(1, lfpfil(:), muafil(:), spikefil(:)); - hdr.nChans = length(hdr.label); - % remember the original header details - hdr.orig = {}; - hdr.orig{1} = lfphdr; - hdr.orig{2} = muahdr; - hdr.orig{3} = spikehdr; - - % return the header - dat = hdr; -else - - % use the original header details - lfphdr = hdr.orig{1}; - muahdr = hdr.orig{2}; - spikehdr = hdr.orig{3}; - % the spike header does not contain these, but requires them from the LFP or MUA - spikehdr.FirstTimeStamp = hdr.FirstTimeStamp; - spikehdr.TimeStampPerSample = hdr.TimeStampPerSample; - - if ~isempty(lfphdr) - Nlfp = lfphdr.nChans; - else - Nlfp = 0; - end - - if ~isempty(muahdr) - Nmua = muahdr.nChans; - else - Nmua = 0; - end - - if ~isempty(spikehdr) - Nspike = spikehdr.nChans; - else - Nspike = 0; - end - - % determine which files should be read from each respective dataset - selchan = zeros(hdr.nChans,1); - selchan(chanindx) = 1; - sellfp = find(selchan(1:Nlfp)); - selmua = find(selchan((Nlfp+1):(Nlfp+Nmua))); - selspike = find(selchan((Nlfp+Nmua+1):(Nlfp+Nmua+Nspike))); - - if haslfp - % the header contains the relevant file names - lfpdat = read_neuralynx_ds([], lfphdr, begsample, endsample, sellfp); - else - lfpdat = []; - end - - if hasmua - % the header contains the relevant file names - muadat = read_neuralynx_ds([], muahdr, begsample, endsample, selmua); - else - muadat = []; - end - - if hasspike - % the header contains the relevant file names - spikedat = read_neuralynx_ds([], spikehdr, begsample, endsample, selspike); - else - spikedat = []; - end - - % combine all data into a single array - dat = cat(1, lfpdat, muadat, spikedat); - -end - diff --git a/external/fieldtrip/private/read_neuralynx_dma.m b/external/fieldtrip/private/read_neuralynx_dma.m index 996d472..14df813 100644 --- a/external/fieldtrip/private/read_neuralynx_dma.m +++ b/external/fieldtrip/private/read_neuralynx_dma.m @@ -17,82 +17,23 @@ % Copyright (C) 2005-2008, Robert Oostenveld % -% $Log: read_neuralynx_dma.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.21 2008/12/15 09:40:33 roboos -% added comment in help about scaling in AD values +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.20 2008/06/13 12:47:23 roboos -% added check on STX to detect discontinuous recordings (and give error) +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.19 2007/12/12 11:30:28 roboos -% remember the offset of the data (header+jumk) in hdr.orig.Offset +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % -% Revision 1.18 2007/10/31 14:11:26 roboos -% fixed CRC problem with the file format that was introduced in Cheetah 5.0, where the first packet could be incomplete and hence all subsequent packets are shifted -% fixed bug in getting the LastTimestamp (read as uint32 instead of int32) -% -% Revision 1.17 2007/10/25 12:48:27 roboos -% moved the reading of the ascii header to another place in the code, no functional change -% -% Revision 1.16 2007/06/13 18:53:07 roboos -% fixed bug: in the detection of header size and channel count the file was opened but not closed due to missing fclose() -% -% Revision 1.15 2007/04/02 15:12:56 roboos -% fixed detextion of ascii header (>32 should be >31) -% -% Revision 1.14 2007/03/26 12:38:19 roboos -% also detect ascii headers that do not start with '####' -% -% Revision 1.13 2007/03/19 16:57:36 roboos -% fixed bug due to hard-coded number of boards (nchans is now flexible and not always 274) -% -% Revision 1.12 2007/02/21 09:55:06 roboos -% fixed bug in TimeStampsPerSample (should be divided by nsamples-1) -% -% Revision 1.11 2007/02/20 08:55:00 roboos -% implemented automatic detection of the number of boards and channels by using the CRC value -% added the ascii header to the output -% -% Revision 1.10 2007/01/09 09:41:49 roboos -% read low and high timestamp as uint32, use seperate function to combaine them into a uint64 -% -% Revision 1.9 2006/12/12 11:37:08 roboos -% read either header or data from the file -% treat datachannels and special channels the same (i.e. a file now consists of 274 'channels') -% cleaned up code, made more consistent with other functions -% allow specification of channels using either channel labels, or using channel indices -% -% Revision 1.8 2006/04/24 12:19:19 roboos -% added support for reading all channels, including the status channels -% -% Revision 1.7 2006/03/14 10:28:45 roboos -% fixed bug in read_neuralynx_dma: when reading a single (special) channel with begsample~=1 it did not skip to the begin sample -% -% Revision 1.6 2006/03/10 12:26:08 roboos -% fixed bug in reading of LastTimeStamp -% -% Revision 1.5 2006/03/06 09:50:45 roboos -% added support for reading a single special channel at a time, using the skip parameter in fread (usefull for ttl) -% -% Revision 1.4 2006/03/02 08:46:11 roboos -% account for the optional 16384 byte header introduced in v4.80 -% -% Revision 1.3 2005/10/14 07:05:10 roboos -% added the first and last timestamp to the output header -% -% Revision 1.2 2005/09/09 12:32:00 roboos -% changed spacing and indentation, no functional change -% -% Revision 1.1 2005/09/05 13:05:44 roboos -% new implementation +% $Id: read_neuralynx_dma.m 945 2010-04-21 17:41:20Z roboos $ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % The data is simply a stream of constant size records, the size of the diff --git a/external/fieldtrip/private/read_neuralynx_ds.m b/external/fieldtrip/private/read_neuralynx_ds.m index 0c1c606..ba84a59 100644 --- a/external/fieldtrip/private/read_neuralynx_ds.m +++ b/external/fieldtrip/private/read_neuralynx_ds.m @@ -25,45 +25,23 @@ % Copyright (C) 2006-2007, Robert Oostenveld % -% $Log: read_neuralynx_ds.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.9 2008/07/01 13:36:17 roboos -% SubSamplingInterleave is not always present +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.8 2008/01/24 19:54:40 roboos -% fixed bug in begrecord, thanks to Thilo +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.7 2008/01/10 12:53:11 roboos -% small change in reading of the header of teh subfiles, use SubSamplingInterleave for downsampled fsample, implemented wortkaround for Matlab bug in comparing uint64 values -% -% Revision 1.6 2007/12/20 17:59:05 roboos -% fixed bug in determining begin record for ncs -% -% Revision 1.5 2007/12/19 09:27:39 roboos -% more explicit handling of the three different filetypes -% give error if FirstTimestamp is not the same for ncs files -% -% Revision 1.4 2007/12/12 16:46:04 roboos -% do not read records from files, get first and last timestamp from file headers -% -% Revision 1.3 2007/03/21 17:06:57 roboos -% updated the documentation -% -% Revision 1.2 2006/12/13 15:49:33 roboos -% many changes, cleaned up code, removed subfunctions, explicitely implement teh computation fo timestamp stuff using a mix of double and uint64 precision (using overloaded mex functions in @uint64 toolbox) -% -% Revision 1.1 2006/03/29 14:39:20 roboos -% New implementation, replaces the previous seperate read_neuralynx_header -% and read_neuralynx_data. Instead of reimplementing the reading code, this -% function calls the specialized subfunctions. +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: read_neuralynx_ds.m 988 2010-04-28 12:18:00Z roevdmei $ needhdr = (nargin==1); needdat = (nargin>=2); @@ -79,11 +57,11 @@ ftype = zeros(length(fname), 1); for i=1:length(fname) - if filetype(fname{i}, 'neuralynx_ncs') + if ft_filetype(fname{i}, 'neuralynx_ncs') ftype(i) = 1; - elseif filetype(fname{i}, 'neuralynx_nse') + elseif ft_filetype(fname{i}, 'neuralynx_nse') ftype(i) = 2; - elseif filetype(fname{i}, 'neuralynx_nts') + elseif ft_filetype(fname{i}, 'neuralynx_nts') ftype(i) = 3; end end @@ -216,7 +194,7 @@ for i=1:nchan thischan = chanindx(i); thisfile = hdr.filename{thischan}; - switch filetype(thisfile) + switch ft_filetype(thisfile) case 'neuralynx_ncs' % determine the records that contain the sample numbers of the requested segment begrecord = ceil(begsample/512); @@ -244,7 +222,7 @@ sample = sample(sample>=begsample & sample<=endsample) - begsample + 1; dat(i,sample) = dat(i,sample) + 1; - end % switch filetype + end % switch ft_filetype end % for nchan end % reading data diff --git a/external/fieldtrip/private/read_neuralynx_ncs.m b/external/fieldtrip/private/read_neuralynx_ncs.m index 2386c18..d9bb0b9 100644 --- a/external/fieldtrip/private/read_neuralynx_ncs.m +++ b/external/fieldtrip/private/read_neuralynx_ncs.m @@ -8,59 +8,23 @@ % Copyright (C) 2005-2007, Robert Oostenveld % -% $Log: read_neuralynx_ncs.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.13 2008/04/29 07:52:31 roboos -% fixed windows related bug -% be consistent with begin and end timestamp in header +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.12 2008/01/10 12:51:57 roboos -% ensure that it is possible to read only the header, using beg/end = 0/0 +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.11 2007/03/21 17:06:57 roboos -% updated the documentation -% -% Revision 1.10 2006/12/13 15:46:31 roboos -% read and keep timestamps as uint64 -% -% Revision 1.9 2006/12/12 11:31:31 roboos -% cleaned up the code, made code more consistent with other neuralynx functions, moved subfunctions to seperate files, use numeric arrays instead of cell-arrays for storing the data -% -% Revision 1.8 2006/03/29 15:01:30 roboos -% fix for previous update: only apply the scaling to uV if data has been read -% -% Revision 1.7 2006/03/29 14:43:26 roboos -% scale the output data to uV, using ADBitVolts and an additional 1e6 -% -% Revision 1.6 2006/03/23 18:02:13 roboos -% change endrecord from inf into the actual number present -% -% Revision 1.5 2006/03/13 16:02:55 roboos -% added first and last timestamp to the output header -% -% Revision 1.4 2006/03/10 12:32:24 roboos -% preallocate enough memory for all elements (prevent repeated memory-reallocatoin and copying) -% -% Revision 1.3 2005/11/23 08:05:23 roboos -% changed while into for-loop -% added error check for end of file in fseek -% check validity of selected begin and end record -% -% Revision 1.2 2005/09/09 12:29:38 roboos -% changed from dox to unix ascii -% changed the looping over the records -% add the number of records in the output -% -% Revision 1.1 2005/05/20 06:39:35 roboos -% new implementation of single file readers +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: read_neuralynx_ncs.m 945 2010-04-21 17:41:20Z roboos $ if nargin<2 begrecord = 1; diff --git a/external/fieldtrip/private/read_neuralynx_nev.m b/external/fieldtrip/private/read_neuralynx_nev.m index 761928d..e22848b 100644 --- a/external/fieldtrip/private/read_neuralynx_nev.m +++ b/external/fieldtrip/private/read_neuralynx_nev.m @@ -19,44 +19,23 @@ % Copyright (C) 2005, Robert Oostenveld % -% $Log: read_neuralynx_nev.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.6 2008/04/29 07:52:31 roboos -% fixed windows related bug -% be consistent with begin and end timestamp in header +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.5 2008/03/04 11:17:48 roboos -% read ttl value as uint16 instead of int16 +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.4 2007/12/20 19:05:31 roboos -% implemented filtering of events based on number (minnumber and maxnumber), this speeds up the reading since the events are each exactly 184 bytes large -% -% Revision 1.3 2007/12/18 16:41:16 roboos -% reimplemented the reading, now by buffering all data in memory and using typecasting and byte swapping (largely implemented in the cstructdecode function) -% implemented filtering on timestamp and value -% -% Revision 1.2 2007/12/12 16:30:10 roboos -% keep timestamps as uint64, fixed problem with case of filename (nev/Nev) -% -% Revision 1.1 2006/12/13 15:43:49 roboos -% renamed read_neuralynx_event into xxx_nev, consistent with the file extension -% -% Revision 1.3 2005/09/05 13:08:52 roboos -% implemented a faster way of reading all events, needed in the case of many triggers (e.g. each refresh) -% -% Revision 1.2 2005/06/24 06:57:32 roboos -% added PktStart to the record header reading, this shifts all fields by two bytes (thanks to Thilo) -% -% Revision 1.1 2005/05/19 07:09:58 roboos -% new implementation +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: read_neuralynx_nev.m 945 2010-04-21 17:41:20Z roboos $ % get the optional input arguments flt_value = keyval('value', varargin); diff --git a/external/fieldtrip/private/read_neuralynx_nse.m b/external/fieldtrip/private/read_neuralynx_nse.m index 2bbc367..8a4d013 100644 --- a/external/fieldtrip/private/read_neuralynx_nse.m +++ b/external/fieldtrip/private/read_neuralynx_nse.m @@ -8,50 +8,23 @@ % Copyright (C) 2005-2007, Robert Oostenveld % -% $Log: read_neuralynx_nse.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.11 2008/04/29 07:52:31 roboos -% fixed windows related bug -% be consistent with begin and end timestamp in header +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.10 2008/01/10 12:51:57 roboos -% ensure that it is possible to read only the header, using beg/end = 0/0 +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.9 2007/12/12 16:29:20 roboos -% add first and last timestamp to header, also when no records are read -% -% Revision 1.8 2007/03/21 17:06:57 roboos -% updated the documentation -% -% Revision 1.7 2006/12/13 15:46:31 roboos -% read and keep timestamps as uint64 -% -% Revision 1.6 2006/12/12 11:31:31 roboos -% cleaned up the code, made code more consistent with other neuralynx functions, moved subfunctions to seperate files, use numeric arrays instead of cell-arrays for storing the data -% -% Revision 1.5 2006/03/29 15:01:30 roboos -% fix for previous update: only apply the scaling to uV if data has been read -% -% Revision 1.4 2006/03/29 14:43:26 roboos -% scale the output data to uV, using ADBitVolts and an additional 1e6 -% -% Revision 1.3 2006/03/23 18:02:44 roboos -% change endrecord from inf into the actual number present -% preallocate memory to hold the results -% -% Revision 1.2 2005/09/09 12:30:08 roboos -% implemented the core functionality -% -% Revision 1.1 2005/08/05 13:41:39 roboos -% new implementation +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: read_neuralynx_nse.m 945 2010-04-21 17:41:20Z roboos $ if nargin<2 begrecord = 1; diff --git a/external/fieldtrip/private/read_neuralynx_nst.m b/external/fieldtrip/private/read_neuralynx_nst.m index c473688..84a0974 100644 --- a/external/fieldtrip/private/read_neuralynx_nst.m +++ b/external/fieldtrip/private/read_neuralynx_nst.m @@ -8,17 +8,23 @@ % Copyright (C) 2005, Robert Oostenveld % -% $Log: read_neuralynx_nst.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.2 2008/04/29 07:52:31 roboos -% fixed windows related bug -% be consistent with begin and end timestamp in header +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.1 2008/03/04 11:15:15 roboos -% new implementation, based on ntt but with only two subchannels +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_neuralynx_nst.m 945 2010-04-21 17:41:20Z roboos $ if nargin<2 begrecord = 1; diff --git a/external/fieldtrip/private/read_neuralynx_nts.m b/external/fieldtrip/private/read_neuralynx_nts.m index e20352d..9d3b5bb 100644 --- a/external/fieldtrip/private/read_neuralynx_nts.m +++ b/external/fieldtrip/private/read_neuralynx_nts.m @@ -8,40 +8,23 @@ % Copyright (C) 2006-2007, Robert Oostenveld % -% $Log: read_neuralynx_nts.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.4 2008/04/29 07:52:31 roboos -% fixed windows related bug -% be consistent with begin and end timestamp in header +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.3 2008/01/10 12:51:58 roboos -% ensure that it is possible to read only the header, using beg/end = 0/0 +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.2 2007/12/12 16:29:19 roboos -% add first and last timestamp to header, also when no records are read -% -% Revision 1.1 2007/03/21 17:12:04 roboos -% renamed NTE in NTS (filenames and function names) -% -% Revision 1.4 2007/03/21 17:06:57 roboos -% updated the documentation -% -% Revision 1.3 2007/03/21 12:54:37 roboos -% included the 2nd and 3rd input arguments in the function declaration -% -% Revision 1.2 2007/03/19 16:58:08 roboos -% implemented the actual reading of the data from file -% -% Revision 1.1 2006/12/13 15:52:26 roboos -% added empty function, only containing help but no usefull code yet +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: read_neuralynx_nts.m 945 2010-04-21 17:41:20Z roboos $ if nargin<2 begrecord = 1; diff --git a/external/fieldtrip/private/read_neuralynx_ntt.m b/external/fieldtrip/private/read_neuralynx_ntt.m index 2f5eb16..7447656 100644 --- a/external/fieldtrip/private/read_neuralynx_ntt.m +++ b/external/fieldtrip/private/read_neuralynx_ntt.m @@ -8,33 +8,23 @@ % Copyright (C) 2005, Robert Oostenveld % -% $Log: read_neuralynx_ntt.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.7 2008/04/29 07:52:31 roboos -% fixed windows related bug -% be consistent with begin and end timestamp in header +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.6 2008/03/04 11:16:11 roboos -% do not convert to uV, since ADBitVolts seems not always to be present in the header -% fixed bug in output assignment of Nrecords +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.5 2008/01/10 12:51:58 roboos -% ensure that it is possible to read only the header, using beg/end = 0/0 -% -% Revision 1.4 2006/12/13 15:46:31 roboos -% read and keep timestamps as uint64 -% -% Revision 1.3 2006/12/12 11:31:31 roboos -% cleaned up the code, made code more consistent with other neuralynx functions, moved subfunctions to seperate files, use numeric arrays instead of cell-arrays for storing the data -% -% Revision 1.2 2006/03/29 15:00:46 roboos -% changed some whitespace -% -% Revision 1.1 2005/05/20 06:39:35 roboos -% new implementation of single file readers +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: read_neuralynx_ntt.m 945 2010-04-21 17:41:20Z roboos $ if nargin<2 begrecord = 1; diff --git a/external/fieldtrip/private/read_neuralynx_sdma.m b/external/fieldtrip/private/read_neuralynx_sdma.m deleted file mode 100644 index 1b60c51..0000000 --- a/external/fieldtrip/private/read_neuralynx_sdma.m +++ /dev/null @@ -1,459 +0,0 @@ -function [dat] = read_neuralynx_sdma(dataset, begsample, endsample, chanindx); - -% READ_NEURALYNX_SDMA read specified channels and samples from a Neuralynx splitted DMA dataset -% -% Use as -% [hdr] = read_neuralynx_sdma(dataset) -% [dat] = read_neuralynx_sdma(dataset, begsample, endsample, chanindx) -% -% The splitted DMA dataset is not a formal Neuralynx format, but at -% the FCDC we use it in conjunction with SPIKEDOWNSAMPLE. The dataset -% directory contains files, one for each channel, each containing a -% 8-byte header followed by the binary values for all samples. Commonly -% the binary values are represented as int32, but it is possible to use -% int16 or other numeric representations. The 8-byte header specifies the -% numeric representation and the bitshift that should be applied (in case -% of integer representations). - -% Copyright (C) 2006-2008, Robert Oostenveld -% -% $Log: read_neuralynx_sdma.m,v $ -% Revision 1.9 2008/07/01 13:36:41 roboos -% only whitespace -% -% Revision 1.8 2008/07/01 13:02:33 roboos -% optionally read the 16384 byte ascii header (if present as txt file) -% remember channel specific header details in hdr.orig.chan and general details in hdr.orig.dataset -% -% Revision 1.7 2008/05/27 13:03:00 roboos -% remember the original header details -% -% Revision 1.6 2007/12/17 16:29:43 roboos -% switched to read_neuralynx_bin for reading the file content, thereby adding support for int16 etc. -% changed handling fo files in directory, be more explicit on which file is used where -% changed reading of timestamps -% -% Revision 1.5 2007/02/21 09:57:13 roboos -% fixed bug in TimeStampsPerSample (should be divided by nsamples-1) -% implemented re-ordering of channel names (i.e. not on ascii-order) to match the channel ordering to the original unspiltted DMA file -% -% Revision 1.4 2007/01/09 09:42:29 roboos -% read low and high timestamp as uint32, use subfunction to combine them into a uint64 -% -% Revision 1.3 2006/12/12 11:39:57 roboos -% cleaned up code, changed handling of channel names (now based on file extension), directory listing determines channel ordering -% -% Revision 1.2 2006/12/04 20:26:02 roboos -% change in whitespace -% -% Revision 1.1 2006/04/24 12:21:14 roboos -% new implementation -% - -needhdr = (nargin==1); -needdat = (nargin>=2); - -if ~isdir(dataset) - error('dataset should be a directory'); -end - -% determine the content of the dataset directory -dirlist = dir(dataset); - -% determine the correspondence between files and channels -label = cell(length(dirlist),1); -filesel = zeros(length(dirlist),1); -headerfile = []; -[pd, nd, xd] = fileparts(dataset); -for i=1:length(dirlist) - [pf, nf, x1] = fileparts(dirlist(i).name); - [pf, nf, x2] = fileparts(nf); - % compare the name of the channel with the name of the dataset and look at the file extention - % the file should be called "dataset/dataset.chanlabel" or "dataset/dataset.chanlabel.bin" - if strcmp(nf, nd) && ~isempty(x1) - if ~isempty(x2) - label{i} = x2(2:end); - filesel(i) = 1; - elseif strcmp(x1, '.txt') - % this is not a proper channel, but an ascii file with header info - label{i} = []; - filesel(i) = 0; - headerfile = fullfile(dataset, dirlist(i).name); - else - label{i} = x1(2:end); - filesel(i) = 1; - end - else - label{i} = []; - filesel(i) = 0; - end -end -label = label(filesel==1); -bytes = cell2mat({dirlist(filesel==1).bytes}); % number of bytes in each file -filelist = {dirlist(filesel==1).name}; % filename excluding the path -clear dirlist filesel pd nd xd - -for i=1:length(filelist) - % include the full path in the filename - filelist{i} = fullfile(dataset, filelist{i}); -end - -% there is a preferred ordering, which corresponds with the channel order in the non-splitted DMA file -preferred = { - 'stx' - 'pid' - 'siz' - 'tsh' - 'tsl' - 'cpu' - 'ttl' - 'x01' - 'x02' - 'x03' - 'x04' - 'x05' - 'x06' - 'x07' - 'x08' - 'x09' - 'x10' - 'csc001' - 'csc002' - 'csc003' - 'csc004' - 'csc005' - 'csc006' - 'csc007' - 'csc008' - 'csc009' - 'csc010' - 'csc011' - 'csc012' - 'csc013' - 'csc014' - 'csc015' - 'csc016' - 'csc017' - 'csc018' - 'csc019' - 'csc020' - 'csc021' - 'csc022' - 'csc023' - 'csc024' - 'csc025' - 'csc026' - 'csc027' - 'csc028' - 'csc029' - 'csc030' - 'csc031' - 'csc032' - 'csc033' - 'csc034' - 'csc035' - 'csc036' - 'csc037' - 'csc038' - 'csc039' - 'csc040' - 'csc041' - 'csc042' - 'csc043' - 'csc044' - 'csc045' - 'csc046' - 'csc047' - 'csc048' - 'csc049' - 'csc050' - 'csc051' - 'csc052' - 'csc053' - 'csc054' - 'csc055' - 'csc056' - 'csc057' - 'csc058' - 'csc059' - 'csc060' - 'csc061' - 'csc062' - 'csc063' - 'csc064' - 'csc065' - 'csc066' - 'csc067' - 'csc068' - 'csc069' - 'csc070' - 'csc071' - 'csc072' - 'csc073' - 'csc074' - 'csc075' - 'csc076' - 'csc077' - 'csc078' - 'csc079' - 'csc080' - 'csc081' - 'csc082' - 'csc083' - 'csc084' - 'csc085' - 'csc086' - 'csc087' - 'csc088' - 'csc089' - 'csc090' - 'csc091' - 'csc092' - 'csc093' - 'csc094' - 'csc095' - 'csc096' - 'csc097' - 'csc098' - 'csc099' - 'csc100' - 'csc101' - 'csc102' - 'csc103' - 'csc104' - 'csc105' - 'csc106' - 'csc107' - 'csc108' - 'csc109' - 'csc110' - 'csc111' - 'csc112' - 'csc113' - 'csc114' - 'csc115' - 'csc116' - 'csc117' - 'csc118' - 'csc119' - 'csc120' - 'csc121' - 'csc122' - 'csc123' - 'csc124' - 'csc125' - 'csc126' - 'csc127' - 'csc128' - 'csc129' - 'csc130' - 'csc131' - 'csc132' - 'csc133' - 'csc134' - 'csc135' - 'csc136' - 'csc137' - 'csc138' - 'csc139' - 'csc140' - 'csc141' - 'csc142' - 'csc143' - 'csc144' - 'csc145' - 'csc146' - 'csc147' - 'csc148' - 'csc149' - 'csc150' - 'csc151' - 'csc152' - 'csc153' - 'csc154' - 'csc155' - 'csc156' - 'csc157' - 'csc158' - 'csc159' - 'csc160' - 'csc161' - 'csc162' - 'csc163' - 'csc164' - 'csc165' - 'csc166' - 'csc167' - 'csc168' - 'csc169' - 'csc170' - 'csc171' - 'csc172' - 'csc173' - 'csc174' - 'csc175' - 'csc176' - 'csc177' - 'csc178' - 'csc179' - 'csc180' - 'csc181' - 'csc182' - 'csc183' - 'csc184' - 'csc185' - 'csc186' - 'csc187' - 'csc188' - 'csc189' - 'csc190' - 'csc191' - 'csc192' - 'csc193' - 'csc194' - 'csc195' - 'csc196' - 'csc197' - 'csc198' - 'csc199' - 'csc200' - 'csc201' - 'csc202' - 'csc203' - 'csc204' - 'csc205' - 'csc206' - 'csc207' - 'csc208' - 'csc209' - 'csc210' - 'csc211' - 'csc212' - 'csc213' - 'csc214' - 'csc215' - 'csc216' - 'csc217' - 'csc218' - 'csc219' - 'csc220' - 'csc221' - 'csc222' - 'csc223' - 'csc224' - 'csc225' - 'csc226' - 'csc227' - 'csc228' - 'csc229' - 'csc230' - 'csc231' - 'csc232' - 'csc233' - 'csc234' - 'csc235' - 'csc236' - 'csc237' - 'csc238' - 'csc239' - 'csc240' - 'csc241' - 'csc242' - 'csc243' - 'csc244' - 'csc245' - 'csc246' - 'csc247' - 'csc248' - 'csc249' - 'csc250' - 'csc251' - 'csc252' - 'csc253' - 'csc254' - 'csc255' - 'csc256' - 'crc' - }; - -[sel1, sel2] = match_str(preferred, label); -if length(sel2)==length(label) - % all reorder the labels/files - label = label(sel2); - bytes = bytes(sel2); - filelist = filelist(sel2); -else - % not all files in this SDMA dataset could be accounted for in the - % preference list, hence do not attempt to apply the preferred ordering -end - -if needhdr - % construct a general header for the complete dataset - if ~isempty(headerfile) - orig = neuralynx_getheader(headerfile); - hdr.Fs = orig.SamplingFrequency; - hdr.nSamples = []; % see below - hdr.nSamplesPre = 0; % number of pre-trigger samples in each trial - hdr.nTrials = 1; % number of trials - hdr.label = label; - hdr.nChans = length(label); - hdr.orig.dataset = orig; % keep the header details - else - % some parts of the header have to be hardcoded, since the splitted dataset does not contain all header information - hdr.Fs = 32556; % sampling frequency - hdr.nSamples = []; % see below - hdr.nSamplesPre = 0; % number of pre-trigger samples in each trial - hdr.nTrials = 1; % number of trials - hdr.label = label; - hdr.nChans = length(label); - end - - % read the header of each individual file, i.e. for each variable - clear orig - for i=1:length(filelist) - orig(i) = read_neuralynx_bin(filelist{i}); - end - - % determine the number of samples for each channel - nsamples = cell2mat({orig.nSamples}); - if any(nsamples~=nsamples(1)) - error('different number of samples over channels are not supported'); - else - hdr.nSamples = nsamples(1); - end - - % determine the sampling frequency for each channel - fsample = cell2mat({orig.Fs}); - if any(diff(fsample)) - error('different sampling rates over channels are not supported'); - elseif any(fsample~=hdr.Fs) - error('inconsistent sampling rates'); - end - - % determine the first and last timestamp, by reading them from the timestamp channels - tslfile = filelist{find(strcmp('tsl', label))}; - tshfile = filelist{find(strcmp('tsh', label))}; - beg_tsl = read_neuralynx_bin(tslfile, 1, 1); - beg_tsh = read_neuralynx_bin(tshfile, 1, 1); - end_tsl = read_neuralynx_bin(tslfile, hdr.nSamples, hdr.nSamples); - end_tsh = read_neuralynx_bin(tshfile, hdr.nSamples, hdr.nSamples); - hdr.FirstTimeStamp = timestamp_neuralynx(beg_tsl, beg_tsh); - hdr.LastTimeStamp = timestamp_neuralynx(end_tsl, end_tsh); - hdr.TimeStampPerSample = double(hdr.LastTimeStamp-hdr.FirstTimeStamp)./(hdr.nSamples-1); % this should be double, since it can be fractional - - % also remember the original header details - hdr.orig.chan = orig; - - % only return the header information - dat = hdr; - -else - % allocate memory for all data - dat = zeros(length(chanindx), endsample-begsample+1); - - % read all channels, one small chunk at at time, and write it to seperate files - for i=1:length(chanindx) - j = chanindx(i); - dat(i,:) = double(read_neuralynx_bin(filelist{j}, begsample, endsample)); - end -end diff --git a/external/fieldtrip/private/read_neuralynx_tsh.m b/external/fieldtrip/private/read_neuralynx_tsh.m index f48e482..dea692e 100644 --- a/external/fieldtrip/private/read_neuralynx_tsh.m +++ b/external/fieldtrip/private/read_neuralynx_tsh.m @@ -11,13 +11,23 @@ % Copyright (C) 2006, Robert Oostenveld % -% $Log: read_neuralynx_tsh.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.3 2006/12/12 11:32:22 roboos -% read the data as uint32 instead of signed integers +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_neuralynx_tsh.m 945 2010-04-21 17:41:20Z roboos $ fid = fopen(filename, 'rb', 'ieee-le'); diff --git a/external/fieldtrip/private/read_neuralynx_tsl.m b/external/fieldtrip/private/read_neuralynx_tsl.m index 2c53712..196adc5 100644 --- a/external/fieldtrip/private/read_neuralynx_tsl.m +++ b/external/fieldtrip/private/read_neuralynx_tsl.m @@ -11,13 +11,23 @@ % Copyright (C) 2006, Robert Oostenveld % -% $Log: read_neuralynx_tsl.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.3 2006/12/12 11:32:22 roboos -% read the data as uint32 instead of signed integers +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_neuralynx_tsl.m 945 2010-04-21 17:41:20Z roboos $ fid = fopen(filename, 'rb', 'ieee-le'); diff --git a/external/fieldtrip/private/read_neuralynx_ttl.m b/external/fieldtrip/private/read_neuralynx_ttl.m index bbe1476..b58c514 100644 --- a/external/fieldtrip/private/read_neuralynx_ttl.m +++ b/external/fieldtrip/private/read_neuralynx_ttl.m @@ -11,18 +11,23 @@ % Copyright (C) 2006, Robert Oostenveld % -% $Log: read_neuralynx_ttl.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.3 2006/12/12 11:32:22 roboos -% read the data as uint32 instead of signed integers +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: read_neuralynx_ttl.m 945 2010-04-21 17:41:20Z roboos $ fid = fopen(filename, 'rb', 'ieee-le'); diff --git a/external/fieldtrip/private/read_nex_data.m b/external/fieldtrip/private/read_nex_data.m deleted file mode 100644 index de2a642..0000000 --- a/external/fieldtrip/private/read_nex_data.m +++ /dev/null @@ -1,82 +0,0 @@ -function [dat] = read_nex_data(filename, hdr, begsample, endsample, chanindx) - -% READ_NEX_DATA for Plexon *.nex file -% -% Use as -% [dat] = read_nex_data(filename, hdr, begsample, endsample, chanindx) -% -% See also READ_NEX_HEADER, READ_NEX_EVENT - -try, - % work with the original header, not the FieldTrip one - hdr = hdr.orig; -catch - % assume that we got the original header -end - -numsmp = cell2mat({hdr.varheader.numsmp}); -adindx = find(cell2mat({hdr.varheader.typ})==5); -smpfrq = hdr.varheader(adindx(1)).wfrequency; -sgn = chanindx; -nsmp = (endsample-begsample+1); -dat = zeros(length(sgn), nsmp); - -fid = fopen(filename, 'r', 'ieee-le'); -for sgnlop=1:length(sgn) - - if hdr.varheader(sgn(sgnlop)).typ == 0 - % read a spike channel - status = fseek(fid,hdr.varheader(sgn(sgnlop)).offset,'bof'); - - % read the sample indices at which spikes occurred - tim = fread(fid,hdr.varheader(sgn(sgnlop)).cnt,'int32'); - % downsample from 40kHz to the A/D sampling frequency - tim = (tim ./ hdr.filheader.frequency) * smpfrq + 1; % add one sample, since ts=0 corresponds to sample=1 - tim = round(tim); % needed because of the edges in histc - % select only samples between the desired begin and end - % tim = tim(find(tim>=begsample & tim<=endsample)); - % convert sample indices into a continuous signal - if ~isempty(tim) - dum = histc(tim-begsample, 0:(nsmp-1), 1); - dat(sgnlop,:) = dum(:)'; - end - - elseif hdr.varheader(sgn(sgnlop)).typ == 5 - % read an A/D channel - status = fseek(fid,hdr.varheader(sgn(sgnlop)).offset,'bof'); - - % this just reads the times of LFP starts - tim = fread(fid,hdr.varheader(sgn(sgnlop)).cnt,'int32'); - % this just reads the indices of LFP starts - ind = fread(fid,hdr.varheader(sgn(sgnlop)).cnt,'int32'); - if length(ind)>1 - error('multiple A/D segments are not supported'); - end - - % convert from timestamps to samples, expressed in the sampling frequency of the AD channels - tim = (tim ./ hdr.filheader.frequency) * smpfrq; - tim = round(tim); - - ch_begsample = begsample - tim; - ch_endsample = endsample - tim; - - if (ch_begsample<1) - error(sprintf('cannot read before the begin of the recorded data (channel %d)', sgn(sgnlop))); - elseif (ch_endsample>hdr.varheader(sgn(sgnlop)).numsmp) - error(sprintf('cannot read beyond the end of the recorded data (channel %d)', sgn(sgnlop))); - end - - % seek to the beginning of the interesting data, correct for the A/D card initialisation delay - fseek(fid,(ch_begsample-1)*2, 'cof'); - % read the actual data for the whole channel - dum = fread(fid,nsmp,'int16'); - % convert to mV - dat(sgnlop,:) = dum(:)' * hdr.varheader(sgn(sgnlop)).adtomv; - - else - % warning(sprintf('unsupported data format for channel %s', hdr.label{sgn(sgnlop)})); - end - -end -status = fclose(fid); - diff --git a/external/fieldtrip/private/read_nex_event.m b/external/fieldtrip/private/read_nex_event.m deleted file mode 100644 index c94b4a6..0000000 --- a/external/fieldtrip/private/read_nex_event.m +++ /dev/null @@ -1,56 +0,0 @@ -function [event] = read_nex_event(filename) - -% READ_NEX_EVENT for Plexon *.nex file -% -% Use as -% [event] = read_nex_event(filename) -% -% The sample numbers returned in event.sample correspond with the -% timestamps, correcting for the difference in sampling frequency in the -% continuous LFP channels and the system sampling frequency. Assuming 40kHz -% sampling frequency for the system and 1kHz for the LFP channels, it is -% event.sample = timestamp / (40000/1000); -% -% See also READ_NEX_HEADER, READ_NEX_DATA - -% Copyright (C) 2005-2007, Robert Oostenveld -% -% $Log: read_nex_event.m,v $ -% Revision 1.2 2007/01/11 12:46:56 roboos -% modified to keep consistent with read_nex_header, added copyright and log -% - -hdr = read_nex_header(filename); -adindx = find(cell2mat({hdr.varheader.typ})==5); -smpfrq = hdr.varheader(adindx(1)).wfrequency; - -% find the channel with the strobed trigger -mrkvarnum = find([hdr.varheader.typ] == 6); - -fid=fopen(filename,'r','ieee-le'); -status = fseek(fid,hdr.varheader(mrkvarnum).offset,'bof'); - -% read the time of the triggers -dum = fread(fid,hdr.varheader(mrkvarnum).cnt,'int32'); -dum = dum ./(hdr.filheader.frequency./smpfrq); -mrk.tim = round(dum); - -% read the value of the triggers -status = fseek(fid,64,'cof'); -dum = fread(fid,[hdr.varheader(mrkvarnum).mrklen,hdr.varheader(mrkvarnum).cnt],'uchar'); -mrk.val = str2num(char(dum(1:5,:)')); - -status = fclose(fid); - -% translate into an FCDC event structure -Nevent = length(mrk.tim); -event = struct('sample', num2cell(mrk.tim), 'value', num2cell(mrk.val)); -for i=1:Nevent - % the code above with the struct and num2cell is much faster - % event(i).sample = mrk.tim(i); - % event(i).value = mrk.val(i); - event(i).type = hdr.varheader(mrkvarnum).nam; - event(i).duration = 1; - event(i).offset = 0; -end - diff --git a/external/fieldtrip/private/read_nex_header.m b/external/fieldtrip/private/read_nex_header.m deleted file mode 100644 index d7b4aa7..0000000 --- a/external/fieldtrip/private/read_nex_header.m +++ /dev/null @@ -1,49 +0,0 @@ -function [hdr] = read_nex_header(filename) - -% READ_NEX_HEADER for Plexon *.nex file -% -% Use as -% [hdr] = read_nex_header(filename) -% -% See also RAD_NEX_DATA, READ_NEX_EVENT - -fid = fopen(filename, 'r', 'ieee-le'); - -% reading the file header -filheader.magicnumber = fread(fid,4,'uint8=>char')'; -filheader.version = fread(fid,1,'int32'); -filheader.comment = fread(fid,256,'uint8=>char')'; -filheader.frequency = fread(fid,1,'double'); -filheader.begvar = fread(fid,1,'int32'); -filheader.endvar = fread(fid,1,'int32'); -filheader.numvar = fread(fid,1,'int32'); -filheader.nextfileheader = fread(fid,1,'int32'); -filheader.padding = fread(fid,256,'uint8=>char')'; - -% reading the variable headers -for varlop=1:filheader.numvar - varheader(varlop).typ = fread(fid,1,'int32'); - varheader(varlop).version = fread(fid,1,'int32'); - varheader(varlop).nam = fread(fid,64,'uint8=>char')'; - varheader(varlop).offset = fread(fid,1,'int32'); - varheader(varlop).cnt = fread(fid,1,'int32'); - varheader(varlop).wirenumber = fread(fid,1,'int32'); - varheader(varlop).unitnumber = fread(fid,1,'int32'); - varheader(varlop).gain = fread(fid,1,'int32'); - varheader(varlop).filter = fread(fid,1,'int32'); - varheader(varlop).xpos = fread(fid,1,'double'); - varheader(varlop).ypos = fread(fid,1,'double'); - varheader(varlop).wfrequency = fread(fid,1,'double'); - varheader(varlop).adtomv = fread(fid,1,'double'); - varheader(varlop).numsmp = fread(fid,1,'int32'); - varheader(varlop).nummrk = fread(fid,1,'int32'); - varheader(varlop).mrklen = fread(fid,1,'int32'); - padding = fread(fid,68,'uint8=>char')'; -end - -status = fclose(fid); - -% put them together into one struct -hdr.fil = filename; -hdr.filheader = filheader; -hdr.varheader = varheader; diff --git a/external/fieldtrip/private/read_nexstim_event.m b/external/fieldtrip/private/read_nexstim_event.m deleted file mode 100644 index decb6a1..0000000 --- a/external/fieldtrip/private/read_nexstim_event.m +++ /dev/null @@ -1,72 +0,0 @@ -function [event] = read_nexstim_event(filename) - -% Use as -% [event] = read_nexstim_event(filename) - -% Written by Vladimir Litvak based on the function nxeGetTriggers -% provided by Nexstim -% -% Copyright (C) 2007, Vladimir Litvak -% -% $Log: read_nexstim_event.m,v $ -% Revision 1.2 2007/12/17 13:03:52 roboos -% Vladimir found and fixed some bugs pertaining to the nexstim_nxe format -% -% Revision 1.1 2007/12/17 08:24:28 roboos -% added support for nexstim_nxe, thanks to Vladimir -% the low-level code has not been tested by myself -% - -% trigLine - either 1(GATE), 2(TRIG1) or 3(TRIG2) -% trigEdge - either 'rising' or 'falling' - -fid=fopen(filename,'r','l'); - -numChannels = 64; -blockSamples = 14500; -trigThreshold = 2000; -trigChannels = [1 2 3]; % Is fixed for the present Nexstim format. - -fseek(fid,0,'eof'); -numBytes = ftell(fid); -numSamples = (numBytes/2)/numChannels; -numBlocks = ceil(numSamples/blockSamples); - -fseek(fid,0,'bof'); -trigPos=[]; - -event=[]; -for i = 1:numBlocks - blockPos=(i-1)*blockSamples; - data = fread(fid,[numChannels blockSamples+1],'int16'); - - for trigLine=1:length(trigChannels); - trigPosRising = find(diff(data(trigChannels(trigLine),:))>trigThreshold)+blockPos; - trigPosFalling = find(diff(data(trigChannels(trigLine),:))<-trigThreshold)+blockPos; - - if ~isempty(trigPosRising) - for i=1:length(trigPosRising) - event(end+1).type = 'rising'; - event(end ).sample = trigPosRising(i); - event(end ).value = trigLine; - event(end ).offset = []; - event(end ).duration = []; - end - end - - if ~isempty(trigPosFalling) - for i=1:length(trigPosFalling) - event(end+1).type = 'falling'; - event(end ).sample = trigPosFalling(i); - event(end ).value = trigLine; - event(end ).offset = []; - event(end ).duration = []; - end - end - - end - fseek(fid,-(2*numChannels),'cof'); -end - -fclose(fid); - diff --git a/external/fieldtrip/private/read_nexstim_nxe.m b/external/fieldtrip/private/read_nexstim_nxe.m deleted file mode 100644 index e7cccc7..0000000 --- a/external/fieldtrip/private/read_nexstim_nxe.m +++ /dev/null @@ -1,152 +0,0 @@ -function [dat] = read_nexstim_nxe(filename, begsample, endsample, chanindx) - -% READ_NEXSTIM_NXE reads specified samples from a NXE continous datafile -% -% Use as -% [hdr] = read_nexstim_nxe(filename) -% where -% filename name of the datafile, including the .bdf extension -% This returns a header structure with the following elements -% hdr.Fs sampling frequency -% hdr.nChans number of channels -% hdr.nSamples number of samples per trial -% hdr.nSamplesPre number of pre-trigger samples in each trial -% hdr.nTrials number of trials -% hdr.label cell-array with labels of each channel -% -% Or use as -% [dat] = read_nexstim_nxe(filename, begsample, endsample, chanindx) -% where -% filename name of the datafile, including the .nxe extension -% begsample index of the first sample to read -% endsample index of the last sample to read -% chanindx index of channels to read (optional, default is all) -% This returns a Nchans X Nsamples data matrix - -% Written by Vladimir Litvak based on functions provided by Nexstim -% -% Copyright (C) 2007, Vladimir Litvak -% -% $Log: read_nexstim_nxe.m,v $ -% Revision 1.3 2007/12/17 13:03:52 roboos -% Vladimir found and fixed some bugs pertaining to the nexstim_nxe format -% -% Revision 1.2 2007/12/17 08:42:34 roboos -% fixed typo -% -% Revision 1.1 2007/12/17 08:24:28 roboos -% added support for nexstim_nxe, thanks to Vladimir -% the low-level code has not been tested by myself -% - -if nargin==1 - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % read the header - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - hdr.Fs = 1450; - hdr.nChans = 64; - hdr.label = cell(64,1); - hdr.label(1:4)= {'GATE', 'TRIG1', 'TRIG2','EOG'}; - hdr.label(5:64) = { - 'Fp1' - 'Fpz' - 'Fp2' - 'AF1' - 'AFz' - 'AF2' - 'F7' - 'F3' - 'F1' - 'Fz' - 'F2' - 'F4' - 'F8' - 'FT9' - 'FT7' - 'FC5' - 'FC3' - 'FC1' - 'FCz' - 'FC2' - 'FC4' - 'FC6' - 'FT8' - 'FT10' - 'T7' - 'C5' - 'C3' - 'C1' - 'Cz' - 'C2' - 'C4' - 'C6' - 'T8' - 'TP9' - 'TP7' - 'CP5' - 'CP3' - 'CP1' - 'CPz' - 'CP2' - 'CP4' - 'CP6' - 'TP8' - 'TP10' - 'P9' - 'P7' - 'P3' - 'P1' - 'Pz' - 'P2' - 'P4' - 'P8' - 'P10' - 'PO3' - 'POz' - 'PO4' - 'O1' - 'Oz' - 'O2' - 'Iz'}; - - % it is continuous data, therefore append all records in one trial - hdr.nTrials = 1; - - fid=fopen(filename,'r','l'); - fseek(fid,0,'eof'); - numBytes = ftell(fid); - hdr.nSamples = (numBytes/2)/hdr.nChans; - - hdr.nSamplesPre = 0; - - fclose(fid); - - % return the header - dat = hdr; - -else - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % read the data - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - sfEEG = (1/2000) * (10/65535) * 1000000; - sfEOG = (1/400) * (10/65535) * 1000000; - sfTRIG = 10 * (10/65535); - - numChannels = 64; - - fid = fopen(filename,'r','l'); - fseek(fid, 2*numChannels*begsample,'bof'); - data = fread(fid,[numChannels endsample-begsample+1],'short'); - fclose(fid); - - data(1:3,:) = sfTRIG.*data(1:3,:); - data(4,:) = sfEOG.*data(4,:); - data(5:64,:) = sfEEG.*data(5:64,:); - - if nargin<4 - chanindx = 1:numChannels; - end - - dat = data(chanindx,:); -end - diff --git a/external/fieldtrip/private/read_nimh_cortex.m b/external/fieldtrip/private/read_nimh_cortex.m deleted file mode 100644 index 19e58a1..0000000 --- a/external/fieldtrip/private/read_nimh_cortex.m +++ /dev/null @@ -1,178 +0,0 @@ -function cortex = read_nimh_cortex(filename, varargin) - -% READ_NIMH_CORTEX -% -% Use as -% cortex = read_nimh_cortex(filename, ...) -% -% Optional input arguments should come in key-value pairs and may -% include -% begtrial = number (default = 1) -% endtrial = number (default = inf) -% epp = read the EPP data, 'yes' or 'no' (default = 'yes') -% eog = read the EOG data, 'yes' or 'no' (default = 'yes') -% feedback = display the progress on the screen, 'yes' or 'no' (default = 'no') -% -% The output is a structure array with one structure for every trial that was read. - -% $Log: read_nimh_cortex.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.1 2008/07/24 08:47:05 roboos -% new implementation in fieldtrip style, based on code that I got from Conrado -% - -% get the optional input arguments -feedback = keyval('feedback', varargin); if isempty(feedback), feedback = 'no'; end -begtrial = keyval('begtrial', varargin); if isempty(begtrial), begtrial = 1; end -endtrial = keyval('endtrial', varargin); if isempty(endtrial), endtrial = inf; end -% reading the epp and eog data is optional -epp = keyval('epp', varargin); if isempty(epp), epp = 'yes'; end -eog = keyval('eog', varargin); if isempty(eog), eog = 'yes'; end - -skipepp = strcmp(epp, 'no'); -skipeog = strcmp(eog, 'no'); -clear epp eog - -% this will hold the result -cortex = struct; - -% trials are counted with zero-offset -trial = 0; - -i_fid = fopen(filename, 'rb', 'ieee-le'); - -% read until the end of file or until the specified trial number -while ( ~feof (i_fid) && trial=begtrial - fprintf('reading trial %d\n', trial+1); - end - - % Number of bytes for each variable. - hd(1,1:8)= (fread(i_fid, 8, 'ushort'))'; - - % Convert bytes to number of float point values (4 bytes apiece in windows and FreeBSD). - hd(1,5)=hd(1,5)/4; - % Convert bytes to number of short values (2 bytes apiece in windows and FreeBSD). - hd(1,6)=hd(1,6)/2; - hd(1,7)=hd(1,7)/2; - hd(1,8)=hd(1,8)/2; - - header.cond_no = hd(1,1); - header.repeat_no = hd(1,2); - header.block_no = hd(1,3); - header.trial_no = hd(1,4); - header.isi_size = hd(1,5); - header.code_size = hd(1,6); - header.eog_size = hd(1,7); - header.epp_size = hd(1,8); - - hd(1,9:10) = (fread(i_fid, 2, 'uchar'))'; - - header.kHz_resolution = hd(1,9); - header.eye_storage_rate = hd(1,10); - - hd(1,11:13) = (fread(i_fid, 3, 'ushort'))'; - - header.expected_response = hd(1,11); - header.response = hd(1,12); - header.response_error = hd(1,13); - - if skiptrial - fseek(i_fid,header.isi_size, 'cof'); - fseek (i_fid,header.code_size, 'cof'); - else - time = (fread (i_fid,header.isi_size, 'ulong')); - event = (fread (i_fid,header.code_size, 'ushort')); - end % if skiptrial - - if skipepp || skiptrial - epp1 = []; - epp2 = []; - fseek (i_fid,header.epp_size * 2, 'cof'); - - else - epp = fread (i_fid,header.epp_size, 'short'); - epp1 = zeros(1,header.epp_size/2); - epp2 = zeros(1,header.epp_size/2); - - % fprintf(o_fid, '\nepp(x)\tepp(y)\n\n'); - - for i = 1:2:header.epp_size - % Must extract the data from the raw epp values. - % The epp value is made up of 12-bits of data, and 4-bits (the - % low-order 4 bits) of the channel number. - % To extract the data, must right shift the raw data by 4 bits (to - % get rid of the channel number and put the data value in the proper - % location). After this conversion, you must still add or subtract - % 2048, since otherwise the value is not right. (I think that this - % is because of the way that matlab handles negative values during - % the bitwise operations.) - % These calculations cause the results of ctx2txt.m to be the same as - % for cortview.exe for the EOG and EPP values. - - s = (i+1)/2; - epp1(s) = bitshift(epp(i), -4); - epp2(s) = bitshift(epp(i+1), -4); - - if (epp1(s) < 0) - epp1(s) = epp1(s) + 2047; - else - epp1(s) = epp1(s) - 2048; - end; - - if (epp2(s) < 0) - epp2(s) = epp2(s) + 2047; - else - epp2(s) = epp2(s) - 2048; - end; - end; - end; % if skipepp - - if skipeog || skiptrial - eog = []; - fseek (i_fid,header.eog_size * 2, 'cof'); - else - eog = fread (i_fid,header.eog_size, 'short'); - eog = reshape(eog, 2, header.eog_size/2); - end % if skipeog - - if ~skiptrial - % collect the headers of all trials in a structure array - cortex(trial+1).header = header; - cortex(trial+1).length = length; - cortex(trial+1).time = time; - cortex(trial+1).event = event; - cortex(trial+1).epp = [epp1; epp2]; - cortex(trial+1).eog = eog; - end - - trial = trial+1; - end; % if ~isempty(length) -end; - -fclose(i_fid); - -% remove the initial empty trials, i.e. the ones that were skipped -cortex = cortex(begtrial:end); - diff --git a/external/fieldtrip/private/read_ns_avg.m b/external/fieldtrip/private/read_ns_avg.m deleted file mode 100644 index 9755628..0000000 --- a/external/fieldtrip/private/read_ns_avg.m +++ /dev/null @@ -1,92 +0,0 @@ -function [avg] = read_ns_avg(filename) - -% READ_NS_AVG read a NeuroScan 3.x or 4.x AVG File -% -% [avg] = read_ns_avg(filename) -% -% The output data structure avg has the fields: -% avg.data - ERP signal in uV (Nchan x Npnt) -% avg.nsweeps - number of accepted trials/sweeps in avg -% avg.variance - variance of the signal (Nchan x Npnt) -% avg.label - electrode labels -% avg.nchan - number of channels -% avg.npnt - number of samplepoints in ERP waveform -% avg.rate - sample rate (Hz) -% avg.time - time for each sample OR -% avg.frequency - frequency for each sample -% hdr.domain - flag indicating time (0) or frequency (1) domain -% avg.xmin - prestimulus epoch start (e.g., -100 msec) -% avg.xmax - poststimulus epoch end (e.g., 900 msec) - -% This program is free software; you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation; either version 2 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program; if not, write to the Free Software -% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -% Copyright (C) 2002, Robert Oostenveld -% -% $Log: read_ns_avg.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.3 2004/06/28 07:36:53 roberto -% changed from DOS to UNIX linefeeds, I am not completely sure whether I made other changes as well -% -% Revision 1.2 2003/03/11 15:24:51 roberto -% updated help and copyrights -% - -% read the neuroscan header -avg = read_ns_hdr(filename); - -% create a time or frequency axis -if avg.domain==1 - avg.frequency = linspace(avg.xmin, avg.xmax, avg.npnt) / 1000; % in Hz instead of mili-Hz -else - avg.time = linspace(avg.xmin, avg.xmax, avg.npnt); % in ms -end - -% open the file and seek towards the place where the raw data is -fid = fopen(filename,'r','ieee-le'); -if fid<0 - error(['cannot open ', filename]); -else - fseek(fid, 900, 'cof'); % skip general header - fseek(fid, 75*avg.nchan, 'cof'); % skip channel headers -end; - -% read raw signal data and convert to uV -avg.data = zeros(avg.nchan, avg.npnt); -for elec = 1:avg.nchan - fseek(fid, 5, 'cof'); % skip sweeps header - raw = fread(fid, avg.npnt, 'float32'); - avg.data(elec,:) = (raw' - avg.baseline(elec)) * avg.calib(elec) / avg.nsweeps; -end; - -% read signal variance if present -if avg.variance - variance = zeros(avg.npnt, avg.nchan); - for elec = 1:avg.nchan, - variance(:, elec) = fread(fid, avg.npnt, 'float32'); - end; - avg.variance = variance'; -else - avg.variance = []; -end; - -fclose(fid); - diff --git a/external/fieldtrip/private/read_ns_cnt.m b/external/fieldtrip/private/read_ns_cnt.m deleted file mode 100644 index 95ff73f..0000000 --- a/external/fieldtrip/private/read_ns_cnt.m +++ /dev/null @@ -1,360 +0,0 @@ -% READ_NS_CNT loads header and/or data from a Neuroscan continuous EEG file -% -% Usage: -% >> cnt = read_ns_cnt(file, varargin) -% -% Inputs: -% filename - name of the file with extension -% -% Optional inputs: -% 't1' - start at time t1, default 0 -% 'sample1' - start at sample1, default 0, overrides t1 -% 'lddur' - duration of segment to load, default = whole file -% 'ldnsamples' - number of samples to load, default = whole file, -% overrides lddur -% 'blockread' - size of the blocks to read. Default is 1. -% 'avgref' - ['yes'|'no'] average reference. Default 'no'. -% 'avrefchan' - reference channels. Default none. -% 'format' - 16 or 32. Default 16. -% -% Outputs: -% cnt - structure with the continuous data and other informations -% -% Known limitations: -% Initially I couldn't get the continuous data as they would appear -% using CNTTOASC or CNTTOBIN (www.neuro.com/neuroscan/download.html). -% We don't have the code for these functions, so we don't really know how -% the raw data is read. After extensive searches, I realized that for -% my continuous CNT files, data was stored in blocks of 40 unsigned short -% integers for each channel. I couldn't find where this parameter was -% specified in the header, so I added the option 'blockread' and input -% the number 40 by hand { cnt = read_ns_cnt('file.cnt', 'blockread', 40) }. -% By default the size of the block is 1 and this work for most CNT -% files. For more see http://www.cnl.salk.edu/~arno/cntload/index.html -% -% Authors: Andrew James & Arnaud Delorme 2000-2001 - -%123456789012345678901234567890123456789012345678901234567890123456789012 - -% Copyright (C) 2000 Andrew James, CERCO, Toulouse, France -% Copyright (C) 2001 Arnaud Delorme, Salk Institute, arno@salk.edu -% -% This program is free software; you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation; either version 2 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program; if not, write to the Free Software -% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -% $Log: read_ns_cnt.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.10 2008/11/20 12:59:01 roboos -% correct the number of samples in case of 32 bit file -% -% Revision 1.9 2008/11/13 21:20:08 roboos -% read chars as uint8, this solves problem with i18n (2-byte unicode) and recent matlab versions -% -% Revision 1.8 2008/09/30 07:47:04 roboos -% replaced all occurences of setstr() with char(), because setstr is deprecated by Matlab -% -% Revision 1.7 2007/10/31 16:46:13 roboos -% revert to short format as default -% -% Revision 1.6 2007/07/03 16:10:48 roboos -% added a hack for 32 bit neuroscan format (hdr.nsdf=16|32), this should actually be be done using autodetection -% -% Revision 1.5 2005/10/11 08:35:41 roboos -% close file when only header was read (thanks to Durk) -% fixed typo in help -% -% Revision 1.4 2004/06/28 07:36:53 roberto -% changed from DOS to UNIX linefeeds, I am not completely sure whether I made other changes as well -% -% Revision 1.4 2003/04/10 17:56:09 arno -% removing debuging message -% -% Revision 1.3 2003/04/10 17:50:11 arno -% adding error message -% -% Revision 1.2 2002/10/22 23:53:23 arno -% fopen ieee-le for Mac -% -% Revision 1.1 2002/04/05 17:39:45 jorn -% Initial revision -% -% original function by a.c.james 2000-2001 -% 'blockread' by arno@salk.edu, Arnaud Delorme, CNL / Salk Institute, 2001 - -function r=read_ns_cnt(file, varargin) - -if nargin < 1 - help read_ns_cnt; - return; -end; - -% defaults -[datdir,name,ext]=fileparts(file); -if ~isempty(varargin) - r=struct(varargin{:}); -end; - -% add defaults -warning off; -try, r.t1; catch, r.t1=0; end -warning on; -try, r.avrefchan; catch, r.avrefchan=[]; end -try, r.blockread; catch, r.blockread=1; end -try, r.avgref; catch, r.avgref='non'; end - -if ~any(file=='.'), file=[file '.cnt']; end - -disp(['Loading file ' file ' ...']) - -f=fopen(file, 'rb', 'ieee-le'); -if f==-1, error([file ' not found']), end - -r.filename=file; -r.rev=freadat(f, 0, 20, 'text'); -i=find(r.rev==0); try, r.rev(i(1):end)=''; end - -r.nchannels=freadat(f, 370, 1, 'ushort'); -numsamples=freadat(f, 864, 1, 'long'); % not accurate, see calculation below -samplespos=900 + 75*r.nchannels; -event.tablepos=freadat(f, 886, 1, 'long'); -r.nsamples=(event.tablepos - samplespos)/(2*r.nchannels); - -%%%%NEW CHANGE TO READ 32 BIT -if isfield(r, 'format') && r.format == 32 - r.nsamples = r.nsamples / 2; -elseif isfield(r, 'format') && r.format == 16 - r.nsamples = r.nsamples / 1; -else - r.nsamples = r.nsamples / 1; -end - -r.rate=freadat(f, 376, 1, 'ushort'); -r.channeloffset=freadat(f, 932, 1, 'long'); -r.dt=1/r.rate; -r.scale=freadat(f, 378, 1, 'double'); -r.ampsensitivity=freadat(f, 438, 1, 'float'); -r.refelectrode=freadat(f, 540, 10, 'text'); -if all(r.refelectrode==0), - %%disp('No reference electrode set in file, setting to CZ') - r.refelectrode(1:2)='CZ'; -end - -% reading all parameters -% ---------------------- -%a = freadat(f, 0, 1, 'short'); -%for i=1:470 -% a = freadat(f, [], 1, 'short'); -% fprintf('offset %3d value %3d\n', i*2, a); -% %if mod(i, 10) == 0, fprintf('\n'); end; -%end; - -% channel parameters -chandat=freadat(f, 900, [75 r.nchannels], 'char'); -r.chan.names=char(chandat(1:9,:))'; -r.chan.reference=chandat(11,:); -r.chan.gain=chandat(1+63,:); -r.chan.baseline=freadat(f, 900+47, [1 r.nchannels], 'short', 75); -r.chan.sensitivity=freadat(f, 900+59, [1 r.nchannels], 'float', 75); -r.chan.calib=freadat(f, 900+71, [1 r.nchannels], 'float', 75); -r.microvoltscalar=r.chan.sensitivity.*r.chan.calib/204.8; - -r.nevent=0; -fseek(f, event.tablepos, 'bof'); -r.event.type=fread(f, 1, 'char'); -event.size=fread(f, 1, 'long'); -%event.offset=fread(f, 1, 'long') - -if r.event.type==1 - event.bytes=8; -elseif r.event.type==2 - event.bytes=19; -else - error('File format error'); -end - -r.nevent=event.size/event.bytes; -r.event.stimtype=freadat(f, event.tablepos+9, r.nevent, 'short', event.bytes); % stimtype -r.event.keyboard=freadat(f, event.tablepos+9+2, r.nevent, 'uchar', event.bytes); % keyboard -r.event.keypadaccept=freadat(f, event.tablepos+9+3, r.nevent, 'uchar', event.bytes); % keypadaccept -offset=freadat(f, event.tablepos+9+4, r.nevent, 'long', event.bytes); % offset -r.event.frame=(offset-samplespos)/(r.nchannels*2); % samplenumber -r.event.time=r.event.frame/r.rate; - -try, - if r.ldheaderonly==1 - fclose(f); - return - end -end - -try, - sample1=r.sample1; - r.t1=r.sample1*r.dt; -catch, - try - startstim=r.startstim; % startstim = [stimtype occurrence] - j=find(r.event.stimtype==startstim(1)); - if length(startstim)>1 - j=j(startstim(2)); - else - j=j(1); - end - r.t1=r.event.time(j); - end - sample1=round(r.t1/r.dt); % first sample to read, zero-based -end -startpos=samplespos+sample1*2*r.nchannels; - -try, ldnsamples=r.ldnsamples; catch, try, ldnsamples=round(r.lddur/r.dt); catch, ldnsamples=r.nsamples; end, end -try, ldchan=r.ldchan; catch, ldchan=[1:r.nchannels]; end -if ~isempty(ldchan) & ldchan==-1, ldchan=[1:r.nchannels]; end -r.ldchan=ldchan; - -% clip events to read window -i=~(sample1<=r.event.frame & r.event.framechar) into uint8=>char to ensure that the -% chars are read as 8 bits and not as extended 16 bit characters. The -% 16 bit handling causes problems on some internationalized OS/Matlab -% combinations. -% -% the help of fread specifies "If the precision is 'char' or 'char*1', MATLAB -% reads characters using the encoding scheme associated with the file. -% See FOPEN for more information". -% -% Revision 1.7 2007/10/08 12:59:51 roboos -% give error if no channels present -% -% Revision 1.6 2007/07/19 14:41:56 roboos -% changed indentation and whitespace -% -% Revision 1.5 2007/07/19 08:49:34 roboos -% only give error for multiple continuous segments if specific samples were requested -% -% Revision 1.4 2007/03/26 12:42:20 roboos -% implemented tsonly option to read only the timestamps -% implemented the selection of begin and endsample for continuous channels -% -% Revision 1.3 2007/03/21 12:59:01 roboos -% updated the documentation -% keep timestamps as int32 -% convert the AD values to uV for type=3 and 5 -% give error instead of warning in case of multiple continuous segments -% -% Revision 1.2 2007/03/14 11:46:16 roboos -% only some whitespace changed -% -% Revision 1.1 2007/01/10 17:28:23 roboos -% new implementation, reusing the code from read_nex_xxx but now with complete support for all known data elements -% - -% parse the optional input arguments -hdr = keyval('header', varargin); -channel = keyval('channel', varargin); -feedback = keyval('feedback', varargin); -tsonly = keyval('tsonly', varargin); -begsample = keyval('begsample', varargin); -endsample = keyval('endsample', varargin); - -% set the defaults -if isempty(feedback) - feedback=0; -end -if isempty(tsonly) - tsonly=0; -end -if isempty(begsample) - begsample=1; -end -if isempty(endsample) - endsample=Inf; -end - -% start with empty return values and empty data -varargout = {}; - -% read header info from file, use Matlabs for automatic byte-ordering -fid = fopen(filename, 'r', 'ieee-le'); -fseek(fid, 0, 'eof'); -siz = ftell(fid); -fseek(fid, 0, 'bof'); - -if isempty(hdr) - if feedback, fprintf('reading header from %s\n', filename); end - % a NEX file consists of a file header, followed by a number of variable headers - % sizeof(NexFileHeader) = 544 - % sizeof(NexVarHeader) = 208 - hdr.FileHeader = NexFileHeader(fid); - if hdr.FileHeader.NumVars<1 - error('no channels present in file'); - end - hdr.VarHeader = NexVarHeader(fid, hdr.FileHeader.NumVars); -end - -for i=1:length(channel) - chan = channel(i); - vh = hdr.VarHeader(chan); - clear buf - fseek(fid, vh.DataOffset, 'bof'); - switch vh.Type - case 0 - % Neurons, only timestamps - buf.ts = fread(fid, [1 vh.Count], 'int32=>int32'); - - case 1 - % Events, only timestamps - buf.ts = fread(fid, [1 vh.Count], 'int32=>int32'); - - case 2 - % Interval variables - buf.begs = fread(fid, [1 vh.Count], 'int32=>int32'); - buf.ends = fread(fid, [1 vh.Count], 'int32=>int32'); - - case 3 - % Waveform variables - buf.ts = fread(fid, [1 vh.Count], 'int32=>int32'); - if ~tsonly - buf.dat = fread(fid, [vh.NPointsWave vh.Count], 'int16'); - % convert the AD values to miliVolt, subsequently convert from miliVolt to microVolt - buf.dat = buf.dat * (vh.ADtoMV * 1000); - end - - case 4 - % Population vector - error('population vectors are not supported'); - - case 5 - % Continuously recorded variables - buf.ts = fread(fid, [1 vh.Count], 'int32=>int32'); - buf.indx = fread(fid, [1 vh.Count], 'int32=>int32'); - if vh.Count>1 && (begsample~=1 || endsample~=inf) - error('reading selected samples from multiple AD segments is not supported'); - end - if ~tsonly - numsample = min(endsample - begsample + 1, vh.NPointsWave); - fseek(fid, (begsample-1)*2, 'cof'); - buf.dat = fread(fid, [1 numsample], 'int16'); - % convert the AD values to miliVolt, subsequently convert from miliVolt to microVolt - buf.dat = buf.dat * (vh.ADtoMV * 1000); - end - - case 6 - % Markers - ts = fread(fid, [1 vh.Count], 'int32=>int32'); - for j=1:vh.NMarkers - buf.MarkerNames{j,1} = fread(fid, [1 64], 'uint8=>char'); - for k=1:vh.Count - buf.MarkerValues{j,k} = fread(fid, [1 vh.MarkerLength], 'uint8=>char'); - end - end - - otherwise - error('incorrect channel type'); - end % switch channel type - - % return the data of this channel - varargout{i} = buf; -end % for channel - -% always return the header as last -varargout{end+1} = hdr; - -fclose(fid); -return - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function hdr = NexFileHeader(fid); -hdr.NexFileHeader = fread(fid,4,'uint8=>char')'; % string NEX1 -hdr.Version = fread(fid,1,'int32'); -hdr.Comment = fread(fid,256,'uint8=>char')'; -hdr.Frequency = fread(fid,1,'double'); % timestamped freq. - tics per second -hdr.Beg = fread(fid,1,'int32'); % usually 0 -hdr.End = fread(fid,1,'int32'); % maximum timestamp + 1 -hdr.NumVars = fread(fid,1,'int32'); % number of variables in the first batch -hdr.NextFileHeader = fread(fid,1,'int32'); % position of the next file header in the file, not implemented yet -Padding = fread(fid,256,'uint8=>char')'; % future expansion - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function hdr = NexVarHeader(fid, numvar); -for varlop=1:numvar - hdr(varlop).Type = fread(fid,1,'int32'); % 0 - neuron, 1 event, 2- interval, 3 - waveform, 4 - pop. vector, 5 - continuously recorded - hdr(varlop).Version = fread(fid,1,'int32'); % 100 - hdr(varlop).Name = fread(fid,64,'uint8=>char')'; % variable name - hdr(varlop).DataOffset = fread(fid,1,'int32'); % where the data array for this variable is located in the file - hdr(varlop).Count = fread(fid,1,'int32'); % number of events, intervals, waveforms or weights - hdr(varlop).WireNumber = fread(fid,1,'int32'); % neuron only, not used now - hdr(varlop).UnitNumber = fread(fid,1,'int32'); % neuron only, not used now - hdr(varlop).Gain = fread(fid,1,'int32'); % neuron only, not used now - hdr(varlop).Filter = fread(fid,1,'int32'); % neuron only, not used now - hdr(varlop).XPos = fread(fid,1,'double'); % neuron only, electrode position in (0,100) range, used in 3D - hdr(varlop).YPos = fread(fid,1,'double'); % neuron only, electrode position in (0,100) range, used in 3D - hdr(varlop).WFrequency = fread(fid,1,'double'); % waveform and continuous vars only, w/f sampling frequency - hdr(varlop).ADtoMV = fread(fid,1,'double'); % waveform continuous vars only, coeff. to convert from A/D values to Millivolts - hdr(varlop).NPointsWave = fread(fid,1,'int32'); % waveform only, number of points in each wave - hdr(varlop).NMarkers = fread(fid,1,'int32'); % how many values are associated with each marker - hdr(varlop).MarkerLength = fread(fid,1,'int32'); % how many characters are in each marker value - Padding = fread(fid,68,'uint8=>char')'; -end diff --git a/external/fieldtrip/private/read_sbin_data.m b/external/fieldtrip/private/read_sbin_data.m deleted file mode 100644 index 108c6b5..0000000 --- a/external/fieldtrip/private/read_sbin_data.m +++ /dev/null @@ -1,87 +0,0 @@ -function [trialData] = read_sbin_data(filename, hdr, begtrial, endtrial, chanindx) - -% READ_SBIN_DATA reads the data from an EGI segmented simple binary format file -% -% Use as -% [trialData] = read_sbin_data(filename, hdr, begtrial, endtrial, chanindx) -% with -% filename name of the input file -% hdr header structure, see READ_HEADER -% begtrial first trial to read, mutually exclusive with begsample+endsample -% endtrial last trial to read, mutually exclusive with begsample+endsample -% chanindx list with channel indices to read -% -% This function returns a 3-D matrix of size Nchans*Nsamples*Ntrials. -%_______________________________________________________________________ -% -% -% Modified from EGI's readEGLY.m with permission 2008-03-31 Joseph Dien -% - -% $Log: read_sbin_data.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.4 2008/12/08 09:36:49 roboos -% added cvs log to the matlab files -% - -fh=fopen([filename],'r'); -if fh==-1 - error('wrong filename') -end - -version = fread(fh,1,'int32'); - -%check byteorder -[str,maxsize,cEndian]=computer; -if version < 7 - if cEndian == 'B' - endian = 'ieee-be'; - elseif cEndian == 'L' - endian = 'ieee-le'; - end; -elseif (version > 6) && ~bitand(version,6) - if cEndian == 'B' - endian = 'ieee-le'; - elseif cEndian == 'L' - endian = 'ieee-be'; - end; - version = swapbytes(uint32(version)); %hdr.orig.header_array is already byte-swapped -else - error('ERROR: This is not a simple binary file. Note that NetStation does not successfully directly convert EGIS files to simple binary format.\n'); -end; - -precision = bitand(version,6); -Nevents=hdr.orig.header_array(17); - -switch precision - case 2 - trialLength=2*hdr.nSamples*(hdr.nChans+Nevents)+6; - dataType='int16'; - case 4 - trialLength=4*hdr.nSamples*(hdr.nChans+Nevents)+6; - dataType='single'; - case 6 - trialLength=8*hdr.nSamples*(hdr.nChans+Nevents)+6; - dataType='double'; -end - -fseek(fh, 40+length(hdr.orig.CatLengths)+sum(hdr.orig.CatLengths)+Nevents*4, 'bof'); %skip over header -fseek(fh, (begtrial-1)*trialLength, 'cof'); %skip over initial segments - -trialData=zeros(hdr.nChans,hdr.nSamples,endtrial-begtrial+1); - -for segment=1:(endtrial-begtrial+1) - fseek(fh, 6, 'cof'); %skip over segment info - temp = fread(fh, [(hdr.nChans+Nevents), hdr.nSamples],dataType,endian); - trialData(:,:,segment) = temp(1:hdr.nChans,:); -end -trialData=trialData(chanindx, :,:); - -fclose(fh); diff --git a/external/fieldtrip/private/read_sbin_events.m b/external/fieldtrip/private/read_sbin_events.m deleted file mode 100644 index eaf4012..0000000 --- a/external/fieldtrip/private/read_sbin_events.m +++ /dev/null @@ -1,117 +0,0 @@ -function [EventCodes, segHdr, eventData] = read_sbin_events(filename) - -% READ_SBIN_EVENTS reads the events information from an EGI segmented simple binary format file -% -% Use as -% [EventCodes, segHdr, eventData] = read_sbin_events(filename) -% with -% EventCodes - if NEvent (from header_array) != 0, then array of 4-char event names -% segHdr - condition codes and time stamps for each segment -% eventData - if NEvent != 0 then event state for each sample, else 'none' -% and -% filename - the name of the data file -%_______________________________________________________________________ -% -% -% Modified from EGI's readEGLY.m with permission 2008-03-31 Joseph Dien -% - -% $Log: read_sbin_events.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.5 2008/12/08 09:36:49 roboos -% added cvs log to the matlab files -% - -fid=fopen([filename],'r'); -if fid==-1 - error('wrong filename') -end - -version = fread(fid,1,'int32'); - -%check byteorder -[str,maxsize,cEndian]=computer; -if version < 7 - if cEndian == 'B' - endian = 'ieee-be'; - elseif cEndian == 'L' - endian = 'ieee-le'; - end; -elseif (version > 6) && ~bitand(version,6) - if cEndian == 'B' - endian = 'ieee-le'; - elseif cEndian == 'L' - endian = 'ieee-be'; - end; - version = swapbytes(uint32(version)); -else - error('ERROR: This is not a simple binary file. Note that NetStation does not successfully directly convert EGIS files to simple binary format.\n'); -end; - -precision = bitand(version,6); -if precision == 0 - error('File precision is not defined.'); -end; - -% read header... -year = fread(fid,1,'int16',endian); -month = fread(fid,1,'int16',endian); -day = fread(fid,1,'int16',endian); -hour = fread(fid,1,'int16',endian); -minute = fread(fid,1,'int16',endian); -second = fread(fid,1,'int16',endian); -millisecond = fread(fid,1,'int32',endian); -Samp_Rate = fread(fid,1,'int16',endian); -NChan = fread(fid,1,'int16',endian); -Gain = fread(fid,1,'int16',endian); -Bits = fread(fid,1,'int16',endian); -Range = fread(fid,1,'int16',endian); -NumCategors = fread(fid,1,'int16',endian); -for j = 1:NumCategors - CatLengths(j) = fread(fid,1,'int8',endian); - for i = 1:CatLengths(j) - CateNames(j,i) = char(fread(fid,1,'char',endian)); - end -end -NSegments = fread(fid,1,'int16',endian); -NSamples = fread(fid,1,'int32',endian); % samples per segment -NEvent = fread(fid,1,'int16',endian); % num events per segment -EventCodes = []; -for j = 1:NEvent - EventCodes(j,1:4) = char(fread(fid,[1,4],'char',endian)); -end - - -readNumSegments = NSegments; % If first and last segments not specified, read all of them. - - -header_array = double([version year month day hour minute second millisecond Samp_Rate NChan Gain Bits Range NumCategors, NSegments, NSamples, NEvent]); - -eventData = zeros(NEvent,readNumSegments*NSamples); -segHdr = zeros(readNumSegments,2); - - -for j = 1:readNumSegments - [segHdr(j,1), count] = fread(fid, 1,'int16',endian); %cell - [segHdr(j,2), count] = fread(fid, 1,'int32',endian); %time stamp - switch precision - case 2 - [temp,count] = fread(fid,[NChan+NEvent, NSamples],'int16',endian); - case 4 - [temp,count] = fread(fid,[NChan+NEvent, NSamples],'single',endian); - case 6 - [temp,count] = fread(fid,[NChan+NEvent, NSamples],'double',endian); - end - if (NEvent ~= 0) - eventData(:,((j-1)*NSamples+1):j*NSamples) = temp( (NChan+1):(NChan+NEvent), 1:NSamples); - end -end -fclose(fid); - diff --git a/external/fieldtrip/private/read_sbin_header.m b/external/fieldtrip/private/read_sbin_header.m deleted file mode 100644 index dd2b661..0000000 --- a/external/fieldtrip/private/read_sbin_header.m +++ /dev/null @@ -1,126 +0,0 @@ -function [header_array, CateNames, CatLengths, preBaseline] = read_sbin_header(filename) - -% READ_SBIN_HEADER reads the header information from an EGI segmented simple binary format file -% -% Use as -% [header_array, CateNames, CatLengths, preBaseline] = read_sbin_header(filename) -% with -% header_array - differs between versions, read code for details -% CateNames - category names -% CatLengths - length of category names -% preBaseline - number of samples in the baseline prior to the baseline event -% and -% filename - the name of the data file -% -% Since there is no unique event code for the segmentation event, and hence the baseline period, -% the first event code in the list will be assumed to be the segmentation event. -% NetStation itself simply ignores possible baseline information when importing simple binary files. -%_______________________________________________________________________ -% -% -% Modified from EGI's readEGLY.m with permission 2008-03-31 Joseph Dien -% - -% $Log: read_sbin_header.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.4 2008/12/08 09:36:49 roboos -% added cvs log to the matlab files -% - -fid=fopen([filename],'r'); -if fid==-1 - error('wrong filename') -end - -version = fread(fid,1,'int32'); - -%check byteorder -[str,maxsize,cEndian]=computer; -if version < 7 - if cEndian == 'B' - endian = 'ieee-be'; - elseif cEndian == 'L' - endian = 'ieee-le'; - end; -elseif (version > 6) && ~bitand(version,6) - if cEndian == 'B' - endian = 'ieee-le'; - elseif cEndian == 'L' - endian = 'ieee-be'; - end; - version = swapbytes(uint32(version)); -else - error('ERROR: This is not a simple binary file. Note that NetStation does not successfully directly convert EGIS files to simple binary format.\n'); -end; - -if bitand(version,1) == 0 - error('ERROR: This is an unsegmented file, which is not supported.\n'); -end; - -precision = bitand(version,6); -if precision == 0 - error('File precision is not defined.'); -end; - -% read header... -year = fread(fid,1,'int16',endian); -month = fread(fid,1,'int16',endian); -day = fread(fid,1,'int16',endian); -hour = fread(fid,1,'int16',endian); -minute = fread(fid,1,'int16',endian); -second = fread(fid,1,'int16',endian); -millisecond = fread(fid,1,'int32',endian); -Samp_Rate = fread(fid,1,'int16',endian); -NChan = fread(fid,1,'int16',endian); -Gain = fread(fid,1,'int16',endian); -Bits = fread(fid,1,'int16',endian); -Range = fread(fid,1,'int16',endian); -NumCategors = fread(fid,1,'int16',endian); -for j = 1:NumCategors - CatLengths(j) = fread(fid,1,'int8',endian); - for i = 1:CatLengths(j) - CateNames(j,i) = char(fread(fid,1,'char',endian)); - end -end -NSegments = fread(fid,1,'int16',endian); -NSamples = fread(fid,1,'int32',endian); % samples per segment -NEvent = fread(fid,1,'int16',endian); % num events per segment -EventCodes = []; -for j = 1:NEvent - EventCodes(j,1:4) = char(fread(fid,[1,4],'char',endian)); -end - -header_array = double([version year month day hour minute second millisecond Samp_Rate NChan Gain Bits Range NumCategors, NSegments, NSamples, NEvent]); - -preBaseline=0; -if NEvent > 0 - - %read the first segment to determine baseline length (assuming all segments have the same baseline). - j=1; - [temp1] = fread(fid, 1,'int16',endian); %cell - [temp2] = fread(fid, 1,'int32',endian); %time stamp - switch precision - case 2 - [temp,count] = fread(fid,[NChan+NEvent, NSamples],'int16',endian); - case 4 - [temp,count] = fread(fid,[NChan+NEvent, NSamples],'single',endian); - case 6 - [temp,count] = fread(fid,[NChan+NEvent, NSamples],'double',endian); - end - eventData = temp( (NChan+1):(NChan+NEvent), 1:NSamples); - theEvent=find(eventData(1,:)>0); %assume the first event code is the segmentation event - theEvent=theEvent(1); - preBaseline=theEvent-1; - if preBaseline == -1 - preBaseline =0; - end; -end - -fclose(fid); diff --git a/external/fieldtrip/private/read_sens.m b/external/fieldtrip/private/read_sens.m deleted file mode 100644 index 9caf54a..0000000 --- a/external/fieldtrip/private/read_sens.m +++ /dev/null @@ -1,259 +0,0 @@ -function [sens] = read_sens(filename, varargin) - -% READ_SENS read sensor positions from various manufacturer specific files. -% Currently supported are ASA, BESA, Polhemus and Matlab for EEG -% electrodes and CTF and Neuromag for MEG gradiometers. -% -% Use as -% grad = read_sens(filename, ...) % for gradiometers -% elec = read_sens(filename, ...) % for electrodes -% -% Additional options should be specified in key-value pairs and can be -% 'fileformat' string -% -% An electrode definition contain the following fields -% elec.pnt Nx3 matrix with carthesian (x,y,z) coordinates of each electrodes -% elec.label cell-array of length N with the label of each electrode -% -% A gradiometer definition generally consists of multiple coils per -% channel, e.g.two coils for a 1st order gradiometer in which the -% orientation of the coils is opposite. Each coil is described -% separately and a large "tra" matrix (can be sparse) has to be -% given that defines how the forward computed field is combined over -% the coils to generate the output of each channel. The gradiometer -% definition constsis of the following fields -% grad.pnt Mx3 matrix with the position of each coil -% grad.ori Mx3 matrix with the orientation of each coil -% grad.tra NxM matrix with the weight of each coil into each channel -% grad.label cell-array of length N with the label of each of the channels -% -% See also TRANSFORM_SENS, PREPARE_VOL_SENS, COMPUTE_LEADFIELD - -% Copyright (C) 2005-2008, Robert Oostenveld -% -% $Log: read_sens.m,v $ -% Revision 1.16 2009/10/16 07:32:08 roboos -% renamed chieti into itab for consistency with other formats -% -% Revision 1.15 2009/10/13 10:12:51 roboos -% added support for chieti_raw -% -% Revision 1.14 2009/07/02 10:34:21 vlalit -% Added eeglab_set to the list of formats where electrode locations can be found in -% the header. -% -% Revision 1.13 2009/06/03 09:52:15 roboos -% added zebris_sfp -% -% Revision 1.12 2009/02/02 16:10:15 vlalit -% Provide the 'headertype' argument to the internal read_header call. -% -% Revision 1.11 2009/01/23 10:32:55 vlalit -% New reader for Neuromag fif format using the MNE toolbox (http://www.nmr.mgh.harvard.edu/martinos/userInfo/data/sofMNE.php) implemented by Laurence Hunt. -% -% Revision 1.10 2008/09/18 10:38:33 vlalit -% Added 4D formats to be recognized by read_sens -% -% Revision 1.9 2008/05/22 14:33:18 vlalit -% Changes related to generalization of fiducials' handling in SPM. -% -% Revision 1.8 2008/04/14 20:51:36 roboos -% added convert_units -% -% Revision 1.7 2008/04/11 16:17:22 roboos -% added polhemus_fil -% -% Revision 1.6 2008/03/20 13:43:14 roboos -% added support for besa_pos -% -% Revision 1.5 2008/03/18 12:34:30 roboos -% fixed bug: added varargin to input arguments, thanks to Juan -% -% Revision 1.4 2008/03/06 09:27:54 roboos -% updated documentation -% -% Revision 1.3 2008/03/05 11:06:11 roboos -% test the presence of the fileio toolbox, needed when this function is included in forwinv -% -% Revision 1.2 2008/03/05 10:54:05 roboos -% added optional argument for fileformat -% some documentation changes -% -% Revision 1.1 2008/01/28 20:10:11 roboos -% new functions based on existing fieldtrip code -% - -% test whether the file exists -if ~exist(filename) - error(sprintf('file ''%s'' does not exist', filename)); -end - -% get the options -fileformat = keyval('fileformat', varargin); - -% determine the filetype -if isempty(fileformat) - fileformat = filetype(filename); -end - -switch fileformat - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % read the content from various files that contain EEG electrode positions - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - case 'asa_elc' - sens = read_asa_elc(filename); - - case 'polhemus_pos' - sens = read_brainvision_pos(filename); - - case 'besa_pos' - tmp = importdata(filename); - if ~isnumeric(tmp) - error('unexpected file format for fileformat=besa_pos') - end - [nchan,nrow] = size(tmp); - if nrow==3 - sens.pnt = tmp; - elseif nrow==9 - pnt1 = tmp(:,1:3); % bottom coil - pnt2 = tmp(:,4:6); % top coil - ori = tmp(:,7:9); % orientation of bottom coil - sens.pnt = [pnt1; pnt2]; - sens.ori = [ori; ori]; - sens.tra = [eye(nchan) -eye(nchan)]; - else - error('unexpected file format for fileformat=besa_pos') - end - [p, f, x] = fileparts(filename); - elpfile = fullfile(p, [f '.elp']); - elafile = fullfile(p, [f '.ela']); - if exist(elpfile, 'file') - warning(sprintf('reading channel labels from %s', elpfile)); - % read the channel names from the accompanying ELP file - lbl = importdata(elpfile); - sens.label = strrep(lbl.textdata(:,2) ,'''', ''); - elseif exist(elafile, 'file') - warning(sprintf('reading channel labels from %s', elafile)); - % read the channel names from the accompanying ELA file - lbl = importdata(elafile); - lbl = strrep(lbl, 'MEG ', ''); % remove the channel type - lbl = strrep(lbl, 'EEG ', ''); % remove the channel type - sens.label = lbl; - else - % the file does not have channel labels in it - warning('creating fake channel names for besa_pos'); - for i=1:nchan - sens.label{i} = sprintf('%03d', i); - end - end - - case 'besa_sfp' - fid = fopen(filename); - tmp = textscan(fid, ' %[^ \t]%n%n%n'); - fclose(fid); - sens.label = tmp{1}; - sens.pnt = [tmp{2:4}]; - - case 'itab_raw' - hastoolbox('fileio'); - hdr = read_header(filename); - sens = hdr.grad; - - case 'neuromag_mne' - hastoolbox('fileio'); - hdr = read_header(filename,'headerformat','neuromag_mne'); - sens = hdr.elec; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % gradiometer information is always stored in the header of the MEG dataset - % hence uses the standard fieldtrip/fileio read_header function - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - case {'ctf_ds', 'ctf_res4', 'neuromag_fif', '4d', '4d_pdf', '4d_m4d', '4d_xyz', 'yokogawa_ave', 'yokogawa_con', 'yokogawa_raw'} - % check the availability of the required low-level toolbox - % this is required because the read_sens function is also on itself included in the forwinv toolbox - hastoolbox('fileio'); - hdr = read_header(filename, 'headerformat', fileformat); - sens = hdr.grad; - - - case 'neuromag_mne_grad' - hastoolbox('fileio'); - hdr = read_header(filename,'headerformat','neuromag_mne'); - sens = hdr.grad; - - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % This is for EEG formats where electrode positions can be stored with the data - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - case {'spmeeg_mat', 'eeglab_set'} - % check the availability of the required low-level toolbox - % this is required because the read_sens function is also on itself included in the forwinv toolbox - hastoolbox('fileio'); - hdr = read_header(filename); - - if isfield(hdr, 'grad') - sens = hdr.grad; - elseif isfield(hdr, 'elec') - sens = hdr.elec; - else - error('no electrodes or gradiometers found in the file') - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % these are created at the FIL in London with a polhemus tracker - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - case 'polhemus_fil' - [sens.fid, sens.pnt] = read_polhemus_fil(filename, 0); - - % the file does not have channel labels in it - warning('no channel names in polhemus file, using numbers instead'); - for i=1:size(sens.pnt, 1) - sens.label{i} = sprintf('%03d', i); - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % matlab files can contain either electrodes or gradiometers - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - case 'matlab' - matfile = filename; % this solves a problem with the matlab compiler v3 - warning('off', 'MATLAB:load:variableNotFound'); - tmp = load(matfile, 'elec', 'grad', 'sens', 'elc'); - warning('on', 'MATLAB:load:variableNotFound'); - if isfield(tmp, 'grad') - sens = getfield(tmp, 'grad'); - elseif isfield(tmp, 'elec') - sens = getfield(tmp, 'elec'); - elseif isfield(tmp, 'sens') - sens = getfield(tmp, 'sens'); - elseif isfield(tmp, 'elc') - sens = getfield(tmp, 'elc'); - else - error('no electrodes or gradiometers found in Matlab file'); - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % these are created by a Zebris tracker, at CRC in Liege at least. - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - case 'zebris_sfp' - [sens.fid, sens.pnt, sens.fid_label, sens.label] = read_zebris(filename, 0); - - otherwise - error('unknown fileformat for electrodes or gradiometers'); -end - -if senstype(sens, 'eeg') - % only keep positions and labels in case of EEG electrodes - dum = sens; - sens = []; - sens.pnt = dum.pnt; - sens.label = dum.label; -end - -% this will add the units to the sensor array -sens = convert_units(sens); diff --git a/external/fieldtrip/private/read_spike.m b/external/fieldtrip/private/read_spike.m deleted file mode 100644 index 40a3c92..0000000 --- a/external/fieldtrip/private/read_spike.m +++ /dev/null @@ -1,226 +0,0 @@ -function [spike] = read_spike(filename, varargin); - -% READ_SPIKE reads spike timestamps and waveforms from various data -% formats. -% -% Use as -% [spike] = read_spike(filename, ...) -% -% Additional options should be specified in key-value pairs and can be -% 'spikeformat' -% -% The output spike structure contains -% spike.label = 1xNchans cell-array, with channel labels -% spike.waveform = 1xNchans cell-array, each element contains a matrix (Nsamples X Nspikes) -% spike.timestamp = 1xNchans cell-array, each element contains a vector (1 X Nspikes) -% spike.unit = 1xNchans cell-array, each element contains a vector (1 X Nspikes) -% -% See also READ_HEADER, READ_DATA, READ_EVENT - -% Copyright (C) 2007-2008, Robert Oostenveld -% -% $Log: read_spike.m,v $ -% Revision 1.16 2009/03/04 07:49:43 roboos -% moved from private to main fileio -% -% Revision 1.1 2009/01/14 09:33:10 roboos -% moved even more files from fileio to fileio/private, see previous log entry -% -% Revision 1.14 2009/01/14 08:51:34 roboos -% fixed *.nts extension (was *.nte), applies to filetype, name of low-level function and name of data structure -% -% Revision 1.13 2008/11/12 17:02:03 roboos -% explicitely specify ieee-le in fopen() -% -% Revision 1.12 2008/07/09 12:16:38 roboos -% added mclust_t -% -% Revision 1.11 2008/03/25 10:59:02 roboos -% use either NLX_Base_Class_Name or AcqEntName, whichever is available -% -% Revision 1.10 2008/03/04 11:17:07 roboos -% added support for neuralynx_nst (tested) and neuralynx_ntt (untested) -% -% Revision 1.9 2007/03/26 12:32:41 roboos -% changed the API for plexon_plx -% -% Revision 1.8 2007/03/21 13:00:02 roboos -% keep the original data header in the output structure -% -% Revision 1.7 2007/03/19 17:08:57 roboos -% implemented neuralynx_nte -% use timestamp_plexon as low level function instead of replicating the typecasting here -% -% Revision 1.6 2007/03/18 22:02:41 roboos -% also deal with plexon plx spike channels that do not contain any data -% -% Revision 1.5 2007/03/13 14:32:47 roboos -% removed header as optional argument, since read_header does not support spike-only files -% in case of plexon_plx, read the header from the file using low-level importer -% implemented support for plexon_nex, type 0 and 3 -% -% Revision 1.4 2007/02/27 09:56:28 roboos -% added some documentation -% -% Revision 1.3 2007/01/09 09:40:38 roboos -% added neuralynx_nse -% -% Revision 1.2 2007/01/04 17:14:12 roboos -% deblank channel labels, renamed data to waveform -% -% Revision 1.1 2007/01/04 12:10:14 roboos -% new implementation, sofar only for plexon_plx -% - -% get the options -spikeformat = keyval('spikeformat', varargin); - -% determine the filetype -if isempty(spikeformat) - spikeformat = filetype(filename); -end - -switch spikeformat - case {'neuralynx_ncs' 'plexon_ddt'} - % these files only contain continuous data - error('file does not contain spike timestamps or waveforms'); - - case 'matlab' - % plain matlab file with a single variable in it - load(filename, 'spike'); - - case 'mclust_t' - fp = fopen(filename, 'rb', 'ieee-le'); - H = ReadHeader(fp); - fclose(fp); - % read only from one file - S = LoadSpikes({filename}); - spike.hdr = H(:); - spike.timestamp = S; - [p, f, x] = fileparts(filename); - spike.label = {f}; % use the filename as label for the spike channel - spike.waveform = {}; % this is unknown - spike.unit = {}; % this is unknown - - case 'neuralynx_nse' - % single channel file, read all records - nse = read_neuralynx_nse(filename); - if isfield(nse.hdr, 'NLX_Base_Class_Name') - spike.label = {nse.hdr.NLX_Base_Class_Name}; - else - spike.label = {nse.hdr.AcqEntName}; - end - spike.timestamp = {nse.TimeStamp}; - spike.waveform = {nse.dat}; - spike.unit = {nse.CellNumber}; - spike.hdr = nse.hdr; - - case 'neuralynx_nst' - % single channel stereotrode file, read all records - nst = read_neuralynx_nst(filename, 1, inf); - if isfield(nst.hdr, 'NLX_Base_Class_Name') - spike.label = {nst.hdr.NLX_Base_Class_Name}; - else - spike.label = {nst.hdr.AcqEntName}; - end - spike.timestamp = {nst.TimeStamp}; - spike.waveform = {nst.dat}; - spike.unit = {nst.CellNumber}; - spike.hdr = nst.hdr; - - case 'neuralynx_ntt' - % single channel stereotrode file, read all records - ntt = read_neuralynx_ntt(filename); - if isfield(ntt.hdr, 'NLX_Base_Class_Name') - spike.label = {ntt.hdr.NLX_Base_Class_Name}; - else - spike.label = {ntt.hdr.AcqEntName}; - end - spike.timestamp = {ntt.TimeStamp}; - spike.waveform = {ntt.dat}; - spike.unit = {ntt.CellNumber}; - spike.hdr = ntt.hdr; - - case 'neuralynx_nts' - % single channel file, read all records - nts = read_neuralynx_nts(filename); - if isfield(nte.hdr, 'NLX_Base_Class_Name') - spike.label = {nts.hdr.NLX_Base_Class_Name}; - else - spike.label = {nts.hdr.AcqEntName}; - end - spike.timestamp = {nts.TimeStamp(:)'}; - spike.waveform = {zeros(0,length(nts.TimeStamp))}; % does not contain waveforms - spike.unit = {zeros(0,length(nts.TimeStamp))}; % does not contain units - spike.hdr = nts.hdr; - - case 'plexon_nex' - % a single file can contain multiple channels of different types - hdr = read_plexon_nex(filename); - typ = [hdr.VarHeader.Type]; - chan = 0; - - spike.label = {}; - spike.waveform = {}; - spike.unit = {}; - spike.timestamp = {}; - - for i=1:length(typ) - if typ(i)==0 - % neurons, only timestamps - nex = read_plexon_nex(filename, 'channel', i); - nspike = length(nex.ts); - chan = chan + 1; - spike.label{chan} = deblank(hdr.VarHeader(i).Name); - spike.waveform{chan} = zeros(0, nspike); - spike.unit{chan} = nan*ones(1,nspike); - spike.timestamp{chan} = nex.ts; - elseif typ(i)==3 - % neurons, timestamps and waveforms - nex = read_plexon_nex(filename, 'channel', i); - chan = chan + 1; - nspike = length(nex.ts); - spike.label{chan} = deblank(hdr.VarHeader(i).Name); - spike.waveform{chan} = nex.dat; - spike.unit{chan} = nan*ones(1,nspike); - spike.timestamp{chan} = nex.ts; - end - end - spike.hdr = hdr; - - case 'plexon_plx' - % read the header information - hdr = read_plexon_plx(filename); - nchan = length(hdr.ChannelHeader); - typ = [hdr.DataBlockHeader.Type]; - unit = [hdr.DataBlockHeader.Unit]; - chan = [hdr.DataBlockHeader.Channel]; - - for i=1:nchan - % select the data blocks that contain spike waveforms and that belong to this channel - sel = (typ==1 & chan==hdr.ChannelHeader(i).Channel); - - if any(sel) - % get the timestamps that correspond with this spike channel - tsl = [hdr.DataBlockHeader(sel).TimeStamp]; - tsh = [hdr.DataBlockHeader(sel).UpperByteOf5ByteTimestamp]; - % convert the 16 bit high timestamp into a 32 bit integer - ts = timestamp_plexon(tsl, tsh); - spike.timestamp{i} = ts; - spike.unit{i} = unit(sel); - else - % this spike channel is empty - spike.timestamp{i} = []; - spike.unit{i} = []; - end - end - for i=1:nchan - spike.label{i} = deblank(hdr.ChannelHeader(i).Name); - spike.waveform{i} = read_plexon_plx(filename, 'ChannelIndex', i, 'header', hdr); - end - spike.hdr = hdr; - - otherwise - error('unsupported data format'); -end - diff --git a/external/fieldtrip/private/read_spike6mat_data.m b/external/fieldtrip/private/read_spike6mat_data.m deleted file mode 100644 index 9343d12..0000000 --- a/external/fieldtrip/private/read_spike6mat_data.m +++ /dev/null @@ -1,56 +0,0 @@ -function dat = read_spike6mat_data(filename, varargin) -% read_spike6mat_data() - read Matlab files exported from Spike 6 -% -% Usage: -% >> header = read_spike6mat_data(filename, varargin); -% -% Inputs: -% filename - [string] file name -% -% Optional inputs: -% 'begsample' first sample to read -% 'endsample' last sample to read -% 'chanindx' - list with channel indices to read -% 'header' - FILEIO structure header -% -% Outputs: -% dat - data over the specified range -% _______________________________________________________________________ -% Copyright (C) 2008 Institute of Neurology, UCL -% Vladimir Litvak - - - -if nargin < 1 - help read_spike6mat_data; - return; -end; - -header = keyval('header', varargin); -begsample = keyval('begsample', varargin); -endsample = keyval('endsample', varargin); -chanindx = keyval('chanindx', varargin); - - -if isempty(header) - header = read_spike6mat_header(filename); -end - -if isempty(begsample), begsample = 1; end; -if isempty(endsample), endsample = header.nSamples; end; - -try - vars = struct2cell(load(filename)); -catch - error('File not found or wrong format.'); -end - -if isempty(chanindx) - chanindx = 1:numel(vars); -end - -dat = zeros(length(chanindx), endsample-begsample+1); - -for i = 1:length(chanindx) - dat(i, :) = vars{chanindx(i)}.values(begsample:endsample); -end diff --git a/external/fieldtrip/private/read_spike6mat_header.m b/external/fieldtrip/private/read_spike6mat_header.m deleted file mode 100644 index e7eb297..0000000 --- a/external/fieldtrip/private/read_spike6mat_header.m +++ /dev/null @@ -1,55 +0,0 @@ -function header = read_spike6mat_header(filename) - -% read_spike6mat_header() - read Matlab files exported from Spike 6 -% -% Usage: -% >> header = read_spike6mat_header(filename); -% -% Inputs: -% filename - [string] file name -% -% Outputs: -% header - FILEIO toolbox type structure -% _______________________________________________________________________ -% Copyright (C) 2008 Institute of Neurology, UCL -% Vladimir Litvak - -if nargin < 1 - help read_spike6mat_header; - return; -end; - -try - vars = struct2cell(load(filename)); -catch - error('File not found or wrong format.'); -end - -header = []; -header.nChans = length(vars); -header.label = {}; - -fsample = []; -onsets = []; -lengths = []; -for i = 1:numel(vars) - fsample(i) = round(1./vars{i}.interval); - onsets(i) = 1e-3*round(1e3*vars{i}.times(1)); - lengths(i) = vars{i}.length; - header.label{i} = vars{i}.title; -end - -if length(unique(fsample))>1 || length(unique(onsets))>1 || length(unique(lengths))>1 - error('Only files with identical channel parameters are supported'); -end - -header.Fs = unique(fsample); - -header.nSamples = unique(lengths); - -header.nSamplesPre = -round(unique(onsets)*header.Fs); - -header.nTrials = 1; - -header.label = header.label(:); - \ No newline at end of file diff --git a/external/fieldtrip/private/read_spmeeg_data.m b/external/fieldtrip/private/read_spmeeg_data.m deleted file mode 100644 index 21c9991..0000000 --- a/external/fieldtrip/private/read_spmeeg_data.m +++ /dev/null @@ -1,99 +0,0 @@ -function dat = read_spmeeg_data(filename, varargin) -% read_spmeeg_data() - import SPM5 and SPM8 meeg datasets -% -% Usage: -% >> header = read_spmeeg_data(filename, varargin); -% -% Inputs: -% filename - [string] file name -% -% Optional inputs: -% 'begsample' first sample to read -% 'endsample' last sample to read -% 'chanindx' - list with channel indices to read -% 'header' - FILEIO structure header -% -% Outputs: -% dat - data over the specified range -% _______________________________________________________________________ -% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% Vladimir Litvak - - - -if nargin < 1 - help read_spmeeg_data; - return; -end; - - -typenames = {'uint8','int16','int32','float32','float64','int8','uint16','uint32'}; -typesizes = [1 2 4 4 8 1 2 4]; - -header = keyval('header', varargin); -begsample = keyval('begsample', varargin); -endsample = keyval('endsample', varargin); -chanindx = keyval('chanindx', varargin); - -if isempty(header) - header = read_spmeeg_header([filename(1:(end-3)) 'mat']); -end - -if isempty(begsample), begsample = 1; end; -if isempty(endsample), endsample = header.nSamples; end; - - - -datatype = 'float32-le'; -scale = []; -if isfield(header, 'orig') - if isfield(header.orig, 'data') && isnumeric(header.orig.data) ... - && ~isempty(header.orig.data) - try - dat = reshape(header.orig.data(chanindx, :, :), length(chanindx), []); - dat = dat(:, begsample:endsample); - return; - end - end - - if isfield(header.orig, 'datatype') - datatype = header.orig.datatype; - elseif isfield(header.orig.data, 'datatype') - datatype = header.orig.data.datatype; - end - if isfield(header.orig, 'scale') - scale = header.orig.scale; - elseif isfield(header.orig.data, 'scale') - scale = header.orig.data.scale; - end -end - -stepsize = typesizes(strmatch(strtok(datatype, '-'), typenames)); - -filename = [filename(1:(end-3)) 'dat']; - -fid = fopen(filename, 'r'); -fseek(fid, stepsize*header.nChans*(begsample-1), 'bof'); -[dat, siz] = fread(fid, [header.nChans, (endsample-begsample+1)], strtok(datatype, '-')); -fclose(fid); - -if ~isempty(chanindx) - % select the desired channels - dat = dat(chanindx,:); -end - -if ~isempty(scale) && ~ismember(strtok(datatype, '-'), {'float32', 'float64'}) - - % This is a somewhat complicated mechanism to figure out which scaling - % coefficients go with which data points in a generic way - - trlind = floor(((begsample:endsample)-1)/header.nSamples)+1; - - utrlind = unique(trlind); - - for i = 1:length(utrlind) - dat(:, trlind == utrlind(i)) = dat(:, trlind == utrlind(i)).* ... - repmat(squeeze(scale(chanindx,:,utrlind(i))), 1, sum(trlind == utrlind(i))); - end - -end diff --git a/external/fieldtrip/private/read_spmeeg_event.m b/external/fieldtrip/private/read_spmeeg_event.m deleted file mode 100644 index 2ceec76..0000000 --- a/external/fieldtrip/private/read_spmeeg_event.m +++ /dev/null @@ -1,81 +0,0 @@ -function event = read_spmeeg_event(filename, varargin) - -% read_spmeeg_event() - import evtns from SPM5 and SPM8 meeg datasets -% -% Usage: -% >> header = read_spmeeg_event(filename); -% -% Inputs: -% filename - [string] file name -% -% Outputs: -% event - FILEIO toolbox event structure -% _______________________________________________________________________ -% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% Vladimir Litvak - -if nargin < 1 - help read_spmeeg_event; - return; -end; - -header = keyval('header', varargin); - -if isempty(header) - header = read_spmeeg_header(filename); -end; - -D = header.orig; - -event = []; - -if isfield(D, 'Radc') % SPM5 - for i = 1:D.Nevents - if isfield(D, 'events') && isfield(D.events, 'code') && length(D.events.code) == D.Nevents - value = D.events.code(i); - else - value = []; - end - - event = [event struct('type', 'trial', 'sample', (i-1)*header.nSamples + 1,... - 'value', value, 'offset', -header.nSamplesPre, 'duration', header.nSamples)]; - end - - if D.Nevents == 1 && isfield(D, 'events') && isfield(D.events, 'time') - event = [event struct('type', 'spm5_event', 'sample', num2cell(D.events.time),... - 'value', num2cell(D.events.code), 'offset', -header.nSamplesPre, 'duration', header.nSamples)]; - end - -elseif all(isfield(D, {'type', 'Nsamples', 'Fsample', 'timeOnset'})) % SPM8 - - for i = 1:numel(D.trials) - event = [event struct('type', 'trial', 'sample', (i-1)*header.nSamples + 1,... - 'value', D.trials(i).label, 'offset', -header.nSamplesPre, 'duration', header.nSamples)]; - - if isfield(D.trials, 'events') - cevent = D.trials(i).events; - if ~isempty(cevent) - for j = 1:numel(cevent) - if ~strcmp(cevent(j).type, 'trial') - csample = (cevent(j).time - D.trials(i).onset)*header.Fs + 1; - if csample > 0 && csample <= header.nSamples - tmp = rmfield(cevent(j), 'time'); - if strcmp(D.type, 'continuous') && (D.timeOnset ~= 0) - tmp.sample = (cevent(j).time - D.timeOnset)* header.Fs + 1; - else - tmp.sample = cevent(j).time*header.Fs; - end - tmp.sample = round(tmp.sample); - tmp.offset = 0; - event = [event tmp]; - end - end - end - end - end - end - -else - error('Cannot recognize an SPM EEG header format'); -end - diff --git a/external/fieldtrip/private/read_trigger.m b/external/fieldtrip/private/read_trigger.m deleted file mode 100644 index b5dee93..0000000 --- a/external/fieldtrip/private/read_trigger.m +++ /dev/null @@ -1,171 +0,0 @@ -function [event] = read_trigger(filename, varargin) - -% READ_TRIGGER extracts the events from a continuous trigger channel -% This function is a helper function to read_event and can be used for all -% dataformats that have one or multiple continuously sampled TTL channels -% in the data. -% -% The optional trigshift (default is 0) causes the value of the -% trigger to be obtained from a sample that is shifted N samples away -% from the actual flank. -% -% This is a helper function for READ_EVENT -% -% TODO -% - merge read_ctf_trigger into this function (requires trigshift and bitmasking option) -% - merge biosemi code into this function (requires bitmasking option) - -% Copyright (C) 2008, Robert Oostenveld -% -% $Log: read_trigger.m,v $ -% Revision 1.7 2009/05/14 18:53:22 roboos -% bail out immediately if the data is empty -% -% Revision 1.6 2009/02/24 14:25:52 jansch -% added option fix4dglasgow to take the synchronization trigger with value 8192 -% out of the trigger-data, prior to flank detection -% -% Revision 1.5 2009/02/09 13:32:36 roboos -% only whitespace -% -% Revision 1.4 2009/01/23 16:18:15 roboos -% changed indentation -% -% Revision 1.3 2009/01/23 12:22:15 vlalit -% A fix to avoid an 'almost infinite' loop in case of noisy event channels. -% -% Revision 1.2 2009/01/23 10:32:55 vlalit -% New reader for Neuromag fif format using the MNE toolbox (http://www.nmr.mgh.harvard.edu/martinos/userInfo/data/sofMNE.php) implemented by Laurence Hunt. -% -% Revision 1.1 2009/01/14 09:12:16 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.6 2008/05/20 15:12:50 vlalit -% Added trigpadding option to handle channels with baseline different from zero -% -% Revision 1.5 2008/05/15 18:38:53 vlalit -% Fixed the problems with discontinuous files and baseline different than zero -% -% Revision 1.4 2008/05/13 16:48:24 roboos -% added option trigshift (default = 0) for cases where the trigger value should be assigned from a sample not directly after/before the upgoing/downgoing flank -% -% Revision 1.3 2008/05/08 18:32:45 vlalit -% Fixed a bug -% -% Revision 1.2 2008/04/29 14:54:39 roboos -% explicit specification of begsample and endsample, otherwise event.sample remains empty -% -% Revision 1.1 2008/04/29 13:53:50 roboos -% new implementation, works for ctf, bti and neuromag -% - -event = []; - -% get the optional input arguments -hdr = keyval('header', varargin); -dataformat = keyval('dataformat', varargin); -begsample = keyval('begsample', varargin); -endsample = keyval('endsample', varargin); -chanindx = keyval('chanindx', varargin); -detectflank = keyval('detectflank', varargin); -denoise = keyval('denoise', varargin); if isempty(denoise), denoise = 1; end -trigshift = keyval('trigshift', varargin); if isempty(trigshift), trigshift = 0; end -trigpadding = keyval('trigpadding', varargin); if isempty(trigpadding), trigpadding = 1; end -fixctf = keyval('fixctf', varargin); if isempty(fixctf), fixctf = 0; end -fixneuromag = keyval('fixneuromag', varargin); if isempty(fixneuromag), fixneuromag = 0; end -fix4dglasgow= keyval('fix4dglasgow', varargin); if isempty(fix4dglasgow), fix4dglasgow = 0; end - -if isempty(begsample) - begsample = 1; -end - -if isempty(endsample) - endsample = hdr.nSamples*hdr.nTrials; -end - -% read the trigger channel as raw data, can safely assume that it is continuous -dat = read_data(filename, 'header', hdr, 'dataformat', dataformat, 'begsample', begsample, 'endsample', endsample, 'chanindx', chanindx, 'checkboundary', 0); - -if isempty(dat) - % there are no triggers to detect - return -end - -% Detect situations where the channel value changes almost at every time -% step which are likely to be noise -if denoise - for i=1:length(chanindx) - if (sum(diff(find(diff(dat(i,:))~=0)) == 1)/length(dat(i,:))) > 0.8 - warning(['trigger channel ' hdr.label{chanindx(i)} ' looks like noise and will be ignored']); - dat(i,:) = 0; - end - end -end - -if fixctf - % correct for reading the data as signed 32-bit integer, whereas it should be interpreted as an unsigned int - dat(dat<0) = dat(dat<0) + 2^32; -end - -if fixneuromag - % according to Joachim Gross, real events always have triggers > 5 - % this is probably to avoid the noisefloor - dat(dat<5) = 0; -end - -if fix4dglasgow - % synchronization pulses have a value of 8192 and are set to 0 - dat = dat - bitand(dat, 8192); - %% triggers containing the first bit assume a value of 4096 when sent by presentation - %% this does not seem to hold for matlab; check this - %dat = dat - bitand(dat, 4096)*4095/4096; -end - -for i=1:length(chanindx) - % process each trigger channel independently - channel = hdr.label{chanindx(i)}; - trig = dat(i,:); - - if trigpadding - pad = trig(1); - else - pad = 0; - end - - switch detectflank - case 'up' - % convert the trigger into an event with a value at a specific sample - for j=find(diff([pad trig(:)'])>0) - event(end+1).type = channel; - event(end ).sample = j + begsample - 1; % assign the sample at which the trigger has gone down - event(end ).value = trig(j+trigshift); % assign the trigger value just _after_ going up - end - case 'down' - % convert the trigger into an event with a value at a specific sample - for j=find(diff([pad trig(:)'])<0) - event(end+1).type = channel; - event(end ).sample = j + begsample - 1; % assign the sample at which the trigger has gone down - event(end ).value = trig(j-1-trigshift); % assign the trigger value just _before_ going down - end - case 'both' - % convert the trigger into an event with a value at a specific sample - for j=find(diff([pad trig(:)'])>0) - event(end+1).type = [channel '_up']; % distinguish between up and down flank - event(end ).sample = j + begsample - 1; % assign the sample at which the trigger has gone down - event(end ).value = trig(j+trigshift); % assign the trigger value just _after_ going up - end - % convert the trigger into an event with a value at a specific sample - for j=find(diff([pad trig(:)'])<0) - event(end+1).type = [channel '_down']; % distinguish between up and down flank - event(end ).sample = j + begsample - 1; % assign the sample at which the trigger has gone down - event(end ).value = trig(j-1-trigshift); % assign the trigger value just _before_ going down - end - otherwise - error('incorrect specification of ''detectflank'''); - end -end diff --git a/external/fieldtrip/private/read_vol.m b/external/fieldtrip/private/read_vol.m deleted file mode 100644 index 1e71eea..0000000 --- a/external/fieldtrip/private/read_vol.m +++ /dev/null @@ -1,85 +0,0 @@ -function [vol] = read_vol(filename, varargin) - -% READ_VOL reads a volume conduction model from various manufacturer -% specific files. Currently supported are ASA, CTF, Neuromag, MBFYS -% and Matlab. -% -% Use as -% vol = read_vol(filename, ...) -% -% Additional options should be specified in key-value pairs and can be -% 'fileformat' string -% -% The volume conduction model is represented as a structure, and its -% contents depend on the type of model. -% -% See also TRANSFORM_VOL, PREPARE_VOL_SENS, COMPUTE_LEADFIELD - -% Copyright (C) 2008, Robert Oostenveld -% -% $Log: read_vol.m,v $ -% Revision 1.4 2008/04/14 20:51:19 roboos -% fixed dependency for dipoli/ama -% added convert_units -% -% Revision 1.3 2008/03/06 09:27:54 roboos -% updated documentation -% -% Revision 1.2 2008/01/31 20:15:24 roboos -% added optional fileformat argument -% -% Revision 1.1 2008/01/28 20:10:11 roboos -% new functions based on existing fieldtrip code -% - -% test whether the file exists -if ~exist(filename) - error(sprintf('file ''%s'' does not exist', filename)); -end - -% get the options -fileformat = keyval('fileformat', varargin); - -% determine the filetype -if isempty(fileformat) - fileformat = filetype(filename); -end - -switch fileformat - case 'matlab' - matfile = filename; % this solves a problem with the matlab compiler v3 - warning('off', 'MATLAB:load:variableNotFound'); - tmp = load(matfile, 'vol'); - warning('on', 'MATLAB:load:variableNotFound'); - vol = getfield(tmp, 'vol'); - - case 'ctf_hdm' - vol = read_ctf_hdm(filename); - - case 'asa_vol' - vol = read_asa_vol(filename); - vol.type = 'asa'; - - case 'mbfys_ama' - ama = loadama(filename); - vol = ama2vol(ama); - - case 'neuromag_fif' - % do not read the volume into Matlab, but use external Neuromag toolbox - vol.type = 'neuromag'; - vol.filename = filename; - vol.chansel = []; % this is defined later based on the channels present in the data - % initialize the Neuromag toolbox, this requires a gradfile and hdmfile - fprintf('using Neuromag volume conductor from %s\n', filename); - fprintf('using Neuromag gradiometer definition from %s\n', cfg.gradfile); - megmodel('head', cfg.gradfile, filename); - % read the triangulated boundary from the neuromag BEM model - [vol.bnd.pnt, vol.bnd.tri, vol.bnd.nrm] = loadtri(vol.filename); - vol.bnd.pnt = vol.bnd.pnt*100; % convert to cm - - otherwise - error('unknown fileformat for volume conductor model'); -end - -% this will add the units to the volume conductor model -vol = convert_units(vol); diff --git a/external/fieldtrip/private/read_yokogawa_data.m b/external/fieldtrip/private/read_yokogawa_data.m deleted file mode 100644 index fc69f98..0000000 --- a/external/fieldtrip/private/read_yokogawa_data.m +++ /dev/null @@ -1,302 +0,0 @@ -function [dat] = read_yokogawa_data(filename, hdr, begsample, endsample, chanindx) - -% READ_YOKAGAWA_DATA reads continuous, epoched or averaged MEG data -% that has been generated by the Yokogawa MEG system and software -% and allows that data to be used in combination with FieldTrip. -% -% Use as -% [dat] = read_yokogawa_data(filename, hdr, begsample, endsample, chanindx) -% -% This is a wrapper function around the functions -% GetMeg160ContinuousRawDataM -% GetMeg160EvokedAverageDataM -% GetMeg160EvokedRawDataM -% -% See also READ_YOKOGAWA_HEADER, READ_YOKOGAWA_EVENT - -% Copyright (C) 2005, Robert Oostenveld -% -% $Log: read_yokogawa_data.m,v $ -% Revision 1.1 2009/01/14 09:12:16 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.6 2008/04/21 14:19:38 roboos -% move teh channel selection to _after_ the calibration, otherwise calibration fails (thanks to Vladimir) -% -% Revision 1.5 2008/04/10 09:59:39 roboos -% define sample_length for Raw data -% -% Revision 1.4 2006/11/30 10:03:00 roboos -% fixed small bug -> extra ")" -% -% Revision 1.3 2005/11/16 13:48:29 roboos -% added suggestions by Masahiro, mainly calibration to physical units -% -% Revision 1.2 2005/09/08 16:54:36 roboos -% added some ;s to the end of lines -% fixed a bug in removing the first sample for raw data -% -% Revision 1.1 2005/09/06 08:54:01 roboos -% new implementations for the Yokogawa 160 channel MEG syste, -% - -% hdr = read_yokogawa_header(filename); -hdr = hdr.orig; % use the original Yokogawa header, not the FieldTrip header - -% default is to select all channels -if nargin<5 - chanindx = 1:hdr.channel_count; -end - -handles = definehandles; -fid = fopen(filename, 'rb', 'ieee-le'); - -switch hdr.acq_type - case handles.AcqTypeEvokedAve - % Data is returned by double. - start_sample = begsample - 1; % samples start at 0 - sample_length = endsample - begsample + 1; - epoch_count = 1; - start_epoch = 0; - dat = double(GetMeg160EvokedAverageDataM( fid, start_sample, sample_length )); - % the first extra sample is the channel number - channum = dat(:,1); - dat = dat(:,2:end); - - case handles.AcqTypeContinuousRaw - % Data is returned by int16. - start_sample = begsample - 1; % samples start at 0 - sample_length = endsample - begsample + 1; - epoch_count = 1; - start_epoch = 0; - dat = double(GetMeg160ContinuousRawDataM( fid, start_sample, sample_length )); - % the first extra sample is the channel number - channum = dat(:,1); - dat = dat(:,2:end); - - case handles.AcqTypeEvokedRaw - % Data is returned by int16. - begtrial = ceil(begsample/hdr.sample_count); - endtrial = ceil(endsample/hdr.sample_count); - if begtrial<1 - error('cannot read before the begin of the file'); - elseif endtrial>hdr.actual_epoch_count - error('cannot read beyond the end of the file'); - end - epoch_count = endtrial-begtrial+1; - start_epoch = begtrial-1; - % read all the neccessary trials that contain the desired samples - dat = double(GetMeg160EvokedRawDataM( fid, start_epoch, epoch_count )); - % the first extra sample is the channel number - channum = dat(:,1); - dat = dat(:,2:end); - if size(dat,2)~=epoch_count*hdr.sample_count - error('could not read all epochs'); - end - rawbegsample = begsample - (begtrial-1)*hdr.sample_count; - rawendsample = endsample - (begtrial-1)*hdr.sample_count; - sample_length = rawendsample - rawbegsample + 1; - % select the desired samples from the complete trials - dat = dat(:,rawbegsample:rawendsample); - - otherwise - error('unknown data type'); -end - -fclose(fid); - -if size(dat,1)~=hdr.channel_count - error('could not read all channels'); -elseif size(dat,2)~=(endsample-begsample+1) - error('could not read all samples'); -end - -% Count of AxialGradioMeter -ch_type = hdr.channel_info(:,2); -index = find(ch_type==[handles.AxialGradioMeter]); -axialgradiometer_index_tmp = index; -axialgradiometer_ch_count = length(index); - -% Count of PlannerGradioMeter -ch_type = hdr.channel_info(:,2); -index = find(ch_type==[handles.PlannerGradioMeter]); -plannergradiometer_index_tmp = index; -plannergradiometer_ch_count = length(index); - -% Count of EegChannel -ch_type = hdr.channel_info(:,2); -index = find(ch_type==[handles.EegChannel]); -eegchannel_index_tmp = index; -eegchannel_ch_count = length(index); - -% Count of NullChannel -ch_type = hdr.channel_info(:,2); -index = find(ch_type==[handles.NullChannel]); -nullchannel_index_tmp = index; -nullchannel_ch_count = length(index); - -%%% Pulling out AxialGradioMeter and value conversion to physical units. -if ~isempty(axialgradiometer_index_tmp) - % Acquisition of channel information - axialgradiometer_index = axialgradiometer_index_tmp; - ch_info = hdr.channel_info; - axialgradiometer_ch_info = ch_info(axialgradiometer_index, :); - - % Value conversion - % B = ( ADValue * VoltRange / ADRange - Offset ) * Sensitivity / FLLGain - calib = hdr.calib_info; - amp_gain = hdr.amp_gain(1); - tmp_ch_no = channum(axialgradiometer_index, 1); - tmp_data = dat(axialgradiometer_index, 1:sample_length); - tmp_offset = calib(axialgradiometer_index, 3) * ones(1,sample_length); - ad_range = 5/2048; - tmp_data = ( tmp_data * ad_range - tmp_offset ); - clear tmp_offset; - tmp_gain = calib(axialgradiometer_index, 2) * ones(1,sample_length); - tmp_data = tmp_data .* tmp_gain / amp_gain; - dat(axialgradiometer_index, 1:sample_length) = tmp_data; - clear tmp_gain; - - % Deletion of Inf row - index = find(axialgradiometer_ch_info(1,:) == Inf); - axialgradiometer_ch_info(:,index) = []; - - % Deletion of channel_type row - axialgradiometer_ch_info(:,2) = []; - - % Outputs to the global variable - handles.sqd.axialgradiometer_ch_info = axialgradiometer_ch_info; - handles.sqd.axialgradiometer_ch_no = tmp_ch_no; - handles.sqd.axialgradiometer_data = [ tmp_ch_no tmp_data]; - clear tmp_data; -end - -%%% Pulling out PlannerGradioMeter and value conversion to physical units. -if ~isempty(plannergradiometer_index_tmp) - % Acquisition of channel information - plannergradiometer_index = plannergradiometer_index_tmp; - ch_info = hdr.channel_info; - plannergradiometer_ch_info = ch_info(plannergradiometer_index, :); - - % Value conversion - % B = ( ADValue * VoltRange / ADRange - Offset ) * Sensitivity / FLLGain - calib = hdr.calib_info; - amp_gain = hdr.amp_gain(1); - tmp_ch_no = channum(plannergradiometer_index, 1); - tmp_data = dat(plannergradiometer_index, 1:sample_length); - tmp_offset = calib(plannergradiometer_index, 3) * ones(1,sample_length); - ad_range = 5/2048; - tmp_data = ( tmp_data * ad_range - tmp_offset ); - clear tmp_offset; - tmp_gain = calib(plannergradiometer_index, 2) * ones(1,sample_length); - tmp_data = tmp_data .* tmp_gain / amp_gain; - dat(plannergradiometer_index, 1:sample_length) = tmp_data; - clear tmp_gain; - - % Deletion of Inf row - index = find(plannergradiometer_ch_info(1,:) == Inf); - plannergradiometer_ch_info(:,index) = []; - - % Deletion of channel_type row - plannergradiometer_ch_info(:,2) = []; - - % Outputs to the global variable - handles.sqd.plannergradiometer_ch_info = plannergradiometer_ch_info; - handles.sqd.plannergradiometer_ch_no = tmp_ch_no; - handles.sqd.plannergradiometer_data = [ tmp_ch_no tmp_data]; - clear tmp_data; -end - -%%% Pulling out EegChannel Channel and value conversion to Volt units. -if ~isempty(eegchannel_index_tmp) - % Acquisition of channel information - eegchannel_index = eegchannel_index_tmp; - - % Value conversion - % B = ADValue * VoltRange / ADRange - tmp_ch_no = channum(eegchannel_index, 1); - tmp_data = dat(eegchannel_index, 1:sample_length); - ad_range = 5/2048; - tmp_data = tmp_data * ad_range; - dat(eegchannel_index, 1:sample_length) = tmp_data; - - % Outputs to the global variable - handles.sqd.eegchannel_ch_no = tmp_ch_no; - handles.sqd.eegchannel_data = [ tmp_ch_no tmp_data]; - clear tmp_data; -end - -%%% Pulling out Null Channel and value conversion to Volt units. -if ~isempty(nullchannel_index_tmp) - % Acquisition of channel information - nullchannel_index = nullchannel_index_tmp; - - % Value conversion - % B = ADValue * VoltRange / ADRange - tmp_ch_no = channum(nullchannel_index, 1); - tmp_data = dat(nullchannel_index, 1:sample_length); - ad_range = 5/2048; - tmp_data = tmp_data * ad_range; - dat(nullchannel_index, 1:sample_length) = tmp_data; - - % Outputs to the global variable - handles.sqd.nullchannel_ch_no = tmp_ch_no; - handles.sqd.nullchannel_data = [ tmp_ch_no tmp_data]; - clear tmp_data; -end - -% select only the desired channels -dat = dat(chanindx,:); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% this defines some usefull constants -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function handles = definehandles -handles.output = []; -handles.sqd_load_flag = false; -handles.mri_load_flag = false; -handles.NullChannel = 0; -handles.MagnetoMeter = 1; -handles.AxialGradioMeter = 2; -handles.PlannerGradioMeter = 3; -handles.RefferenceChannelMark = hex2dec('0100'); -handles.RefferenceMagnetoMeter = bitor( handles.RefferenceChannelMark, handles.MagnetoMeter ); -handles.RefferenceAxialGradioMeter = bitor( handles.RefferenceChannelMark, handles.AxialGradioMeter ); -handles.RefferencePlannerGradioMeter = bitor( handles.RefferenceChannelMark, handles.PlannerGradioMeter ); -handles.TriggerChannel = -1; -handles.EegChannel = -2; -handles.EcgChannel = -3; -handles.EtcChannel = -4; -handles.NonMegChannelNameLength = 32; -handles.DefaultMagnetometerSize = (4.0/1000.0); % Square of 4.0mm in length -handles.DefaultAxialGradioMeterSize = (15.5/1000.0); % Circle of 15.5mm in diameter -handles.DefaultPlannerGradioMeterSize = (12.0/1000.0); % Square of 12.0mm in length -handles.AcqTypeContinuousRaw = 1; -handles.AcqTypeEvokedAve = 2; -handles.AcqTypeEvokedRaw = 3; -handles.sqd = []; -handles.sqd.selected_start = []; -handles.sqd.selected_end = []; -handles.sqd.axialgradiometer_ch_no = []; -handles.sqd.axialgradiometer_ch_info = []; -handles.sqd.axialgradiometer_data = []; -handles.sqd.plannergradiometer_ch_no = []; -handles.sqd.plannergradiometer_ch_info = []; -handles.sqd.plannergradiometer_data = []; -handles.sqd.eegchannel_ch_no = []; -handles.sqd.eegchannel_data = []; -handles.sqd.nullchannel_ch_no = []; -handles.sqd.nullchannel_data = []; -handles.sqd.selected_time = []; -handles.sqd.sample_rate = []; -handles.sqd.sample_count = []; -handles.sqd.pretrigger_length = []; -handles.sqd.matching_info = []; -handles.sqd.source_info = []; -handles.sqd.mri_info = []; -handles.mri = []; diff --git a/external/fieldtrip/private/read_yokogawa_event.m b/external/fieldtrip/private/read_yokogawa_event.m deleted file mode 100644 index a26017b..0000000 --- a/external/fieldtrip/private/read_yokogawa_event.m +++ /dev/null @@ -1,107 +0,0 @@ -function [event] = read_yokogawa_event(filename); - -% READ_YOKOGAWA_EVENT reads event information from continuous, -% epoched or averaged MEG data that has been generated by the Yokogawa -% MEG system and software and allows those events to be used in -% combination with FieldTrip. -% -% Use as -% [event] = read_yokogawa_event(filename) -% -% See also READ_YOKOGAWA_HEADER, READ_YOKOGAWA_DATA - -% Copyright (C) 2005, Robert Oostenveld -% -% $Log: read_yokogawa_event.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry -% -% Revision 1.3 2005/11/16 13:48:59 roboos -% updated the handles subfunction, no functional change -% -% Revision 1.2 2005/09/08 09:27:13 roboos -% added an 'average' event for an averaged ERF dataset -% -% Revision 1.1 2005/09/06 08:54:01 roboos -% new implementations for the Yokogawa 160 channel MEG syste, -% - -event = []; -handles = definehandles; - -% use the standard FieldTrip header for trial events -hdr = read_yokogawa_header(filename); - -if hdr.orig.acq_type==handles.AcqTypeEvokedRaw - % make an event for each trial as defined in the header - for i=1:hdr.nTrials - event(end+1).type = 'trial'; - event(end ).sample = (i-1)*hdr.nSamples + 1; - event(end ).offset = -hdr.nSamplesPre; - event(end ).duration = hdr.nSamples; - end - -elseif hdr.orig.acq_type==handles.AcqTypeEvokedAve - % make an event for the average - event(1).type = 'average'; - event(1).sample = 1; - event(1).offset = -hdr.nSamplesPre; - event(1).duration = hdr.nSamples; -end - -% continue with the original Yokogawa header, not the FieldTrip header -hdr = hdr.orig; -% these might contain usefull information -sel_etc = find(hdr.channel_info(:,2)==handles.EtcChannel); -sel_trg = find(hdr.channel_info(:,2)==handles.TriggerChannel); - -% FIXME, do something with the triggers... - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% this defines some usefull constants -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function handles = definehandles; -handles.output = []; -handles.sqd_load_flag = false; -handles.mri_load_flag = false; -handles.NullChannel = 0; -handles.MagnetoMeter = 1; -handles.AxialGradioMeter = 2; -handles.PlannerGradioMeter = 3; -handles.RefferenceChannelMark = hex2dec('0100'); -handles.RefferenceMagnetoMeter = bitor( handles.RefferenceChannelMark, handles.MagnetoMeter ); -handles.RefferenceAxialGradioMeter = bitor( handles.RefferenceChannelMark, handles.AxialGradioMeter ); -handles.RefferencePlannerGradioMeter = bitor( handles.RefferenceChannelMark, handles.PlannerGradioMeter ); -handles.TriggerChannel = -1; -handles.EegChannel = -2; -handles.EcgChannel = -3; -handles.EtcChannel = -4; -handles.NonMegChannelNameLength = 32; -handles.DefaultMagnetometerSize = (4.0/1000.0); % Square of 4.0mm in length -handles.DefaultAxialGradioMeterSize = (15.5/1000.0); % Circle of 15.5mm in diameter -handles.DefaultPlannerGradioMeterSize = (12.0/1000.0); % Square of 12.0mm in length -handles.AcqTypeContinuousRaw = 1; -handles.AcqTypeEvokedAve = 2; -handles.AcqTypeEvokedRaw = 3; -handles.sqd = []; -handles.sqd.selected_start = []; -handles.sqd.selected_end = []; -handles.sqd.axialgradiometer_ch_no = []; -handles.sqd.axialgradiometer_ch_info = []; -handles.sqd.axialgradiometer_data = []; -handles.sqd.plannergradiometer_ch_no = []; -handles.sqd.plannergradiometer_ch_info = []; -handles.sqd.plannergradiometer_data = []; -handles.sqd.eegchannel_ch_no = []; -handles.sqd.eegchannel_data = []; -handles.sqd.nullchannel_ch_no = []; -handles.sqd.nullchannel_data = []; -handles.sqd.selected_time = []; -handles.sqd.sample_rate = []; -handles.sqd.sample_count = []; -handles.sqd.pretrigger_length = []; -handles.sqd.matching_info = []; -handles.sqd.source_info = []; -handles.sqd.mri_info = []; -handles.mri = []; diff --git a/external/fieldtrip/private/read_yokogawa_header.m b/external/fieldtrip/private/read_yokogawa_header.m deleted file mode 100644 index b94d8a4..0000000 --- a/external/fieldtrip/private/read_yokogawa_header.m +++ /dev/null @@ -1,191 +0,0 @@ -function hdr = read_yokogawa_header(filename); - - -% READ_YOKOGAWA_HEADER reads the header information from continuous, -% epoched or averaged MEG data that has been generated by the Yokogawa -% MEG system and software and allows that data to be used in combination -% with FieldTrip. -% -% Use as -% [hdr] = read_yokogawa_header(filename) -% -% This is a wrapper function around the functions -% GetMeg160SystemInfoM -% GetMeg160ChannelCountM -% GetMeg160ChannelInfoM -% GetMeg160CalibInfoM -% GetMeg160AmpGainM -% GetMeg160DataAcqTypeM -% GetMeg160ContinuousAcqCondM -% GetMeg160EvokedAcqCondM -% -% See also READ_YOKOGAWA_DATA, READ_YOKOGAWA_EVENT - -% this function also calls -% GetMeg160MriInfoM -% GetMeg160MatchingInfoM -% GetMeg160SourceInfoM -% but I don't know whether to use the information provided by those - -% Copyright (C) 2005, Robert Oostenveld -% -% $Log: read_yokogawa_header.m,v $ -% Revision 1.1 2009/01/14 09:12:16 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.2 2005/09/29 00:48:57 roboos -% fixed hdr.nSamplesPre, corrected error in help -% -% Revision 1.1 2005/09/06 08:54:01 roboos -% new implementations for the Yokogawa 160 channel MEG syste, -% - -% FIXED -% txt -> m -% fopen iee-le - -handles = definehandles; -fid = fopen(filename, 'rb', 'ieee-le'); - -% these are always present -[id ver rev sys_name] = GetMeg160SystemInfoM(fid); -channel_count = GetMeg160ChannelCountM(fid); -channel_info = GetMeg160ChannelInfoM(fid); -calib_info = GetMeg160CalibInfoM(fid); -amp_gain = GetMeg160AmpGainM(fid); -acq_type = GetMeg160DataAcqTypeM(fid); - -% these depend on the data type -sample_rate = []; -sample_count = []; -pretrigger_length = []; -averaged_count = []; -actual_epoch_count = []; - -switch acq_type - case handles.AcqTypeContinuousRaw - [sample_rate, sample_count] = GetMeg160ContinuousAcqCondM(fid); - if isempty(sample_rate) | isempty(sample_count) - fclose(fid); - return; - end - pretrigger_length = 0; - averaged_count = 1; - - case handles.AcqTypeEvokedAve - [sample_rate, sample_count, pretrigger_length, averaged_count] = GetMeg160EvokedAcqCondM( fid ); - if isempty(sample_rate) | isempty(sample_count) | isempty(pretrigger_length) | isempty(averaged_count) - fclose(fid); - return; - end - - case handles.AcqTypeEvokedRaw - [sample_rate, sample_count, pretrigger_length, actual_epoch_count] = GetMeg160EvokedAcqCondM( fid ); - if isempty(sample_rate) | isempty(sample_count) | isempty(pretrigger_length) | isempty(actual_epoch_count) - fclose(fid); - return; - end - - otherwise - error('unknown data type'); -end - -% these are always present -mri_info = GetMeg160MriInfoM(fid); -matching_info = GetMeg160MatchingInfoM(fid); -source_info = GetMeg160SourceInfoM(fid); - -fclose(fid); - -% put all local variables into a structure, this is a bit unusual matlab programming style -tmp = whos; -orig = []; -for i=1:length(tmp) - if isempty(strmatch(tmp(i).name, {'tmp', 'fid', 'ans', 'handles'})) - orig = setfield(orig, tmp(i).name, eval(tmp(i).name)); - end -end - -% convert the original header information into something that FieldTrip understands -hdr = []; -hdr.orig = orig; % also store the original full header information -hdr.Fs = orig.sample_rate; % sampling frequency -hdr.nChans = orig.channel_count; % number of channels -hdr.nSamples = []; % number of samples per trial -hdr.nSamplesPre = []; % number of pre-trigger samples in each trial -hdr.nTrials = []; % number of trials - -switch orig.acq_type - case handles.AcqTypeEvokedAve - hdr.nSamples = orig.sample_count; - hdr.nSamplesPre = orig.pretrigger_length; - hdr.nTrials = 1; % only the average, which can be considered as a single trial - case handles.AcqTypeContinuousRaw - hdr.nSamples = orig.sample_count; - hdr.nSamplesPre = 0; % there is no fixed relation between triggers and data - hdr.nTrials = 1; % the continuous data can be considered as a single very long trial - case handles.AcqTypeEvokedRaw - hdr.nSamples = orig.sample_count; - hdr.nSamplesPre = orig.pretrigger_length; - hdr.nTrials = orig.actual_epoch_count; - otherwise - error('unknown acquisition type'); -end - -% construct a cell-array with labels of each channel -for i=1:hdr.nChans - hdr.label{i} = sprintf('%03d', i); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% this defines some usefull constants -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function handles = definehandles; -handles.output = []; -handles.sqd_load_flag = false; -handles.mri_load_flag = false; -handles.NullChannel = 0; -handles.MagnetoMeter = 1; -handles.AxialGradioMeter = 2; -handles.PlannerGradioMeter = 3; -handles.RefferenceChannelMark = hex2dec('0100'); -handles.RefferenceMagnetoMeter = bitor( handles.RefferenceChannelMark, handles.MagnetoMeter ); -handles.RefferenceAxialGradioMeter = bitor( handles.RefferenceChannelMark, handles.AxialGradioMeter ); -handles.RefferencePlannerGradioMeter = bitor( handles.RefferenceChannelMark, handles.PlannerGradioMeter ); -handles.TriggerChannel = -1; -handles.EegChannel = -2; -handles.EcgChannel = -3; -handles.EtcChannel = -4; -handles.NonMegChannelNameLength = 32; -handles.DefaultMagnetometerSize = (4.0/1000.0); % Square of 4.0mm in length -handles.DefaultAxialGradioMeterSize = (15.5/1000.0); % Circle of 15.5mm in diameter -handles.DefaultPlannerGradioMeterSize = (12.0/1000.0); % Square of 12.0mm in length -handles.AcqTypeContinuousRaw = 1; -handles.AcqTypeEvokedAve = 2; -handles.AcqTypeEvokedRaw = 3; -handles.sqd = []; -handles.sqd.selected_start = []; -handles.sqd.selected_end = []; -handles.sqd.axialgradiometer_ch_no = []; -handles.sqd.axialgradiometer_ch_info = []; -handles.sqd.axialgradiometer_data = []; -handles.sqd.plannergradiometer_ch_no = []; -handles.sqd.plannergradiometer_ch_info = []; -handles.sqd.plannergradiometer_data = []; -handles.sqd.eegchannel_ch_no = []; -handles.sqd.eegchannel_data = []; -handles.sqd.nullchannel_ch_no = []; -handles.sqd.nullchannel_data = []; -handles.sqd.selected_time = []; -handles.sqd.sample_rate = []; -handles.sqd.sample_count = []; -handles.sqd.pretrigger_length = []; -handles.sqd.matching_info = []; -handles.sqd.source_info = []; -handles.sqd.mri_info = []; -handles.mri = []; diff --git a/external/fieldtrip/private/readbdf.m b/external/fieldtrip/private/readbdf.m index 1e75bcf..28d56df 100644 --- a/external/fieldtrip/private/readbdf.m +++ b/external/fieldtrip/private/readbdf.m @@ -16,10 +16,10 @@ % % See also: openbdf(), sdfopen(), sdfread(), eeglab() -% Version 2.11 -% 03.02.1998 -% Copyright (c) 1997,98 by Alois Schloegl -% a.schloegl@ieee.org +% Version 2.11 +% 03.02.1998 +% Copyright (c) 1997,98 by Alois Schloegl +% a.schloegl@ieee.org % This program is free software; you can redistribute it and/or % modify it under the terms of the GNU General Public License @@ -58,11 +58,11 @@ for nrec=1:length(Records), - NREC=(DAT.Idx(nrec)-1); - if NREC<0 fprintf(2,'Warning READEDF: invalid Record Number %i \n',NREC);end; + NREC=(DAT.Idx(nrec)-1); + if NREC<0 fprintf(2,'Warning READEDF: invalid Record Number %i \n',NREC);end; - fseek(EDF.FILE.FID,(EDF.HeadLen+NREC*EDF.AS.spb*3),'bof'); - [s, count]=fread(EDF.FILE.FID,EDF.AS.spb,'bit24'); + fseek(EDF.FILE.FID,(EDF.HeadLen+NREC*EDF.AS.spb*3),'bof'); + [s, count]=fread(EDF.FILE.FID,EDF.AS.spb,'bit24'); try, S(EDF.AS.IDX2)=s; @@ -70,25 +70,25 @@ error('File is incomplete (try reading begining of file)'); end; - %%%%% Test on Over- (Under-) Flow -% V=sum([(S'==EDF.DigMax(:,ones(RecLen,1))) + (S'==EDF.DigMin(:,ones(RecLen,1)))])==0; - V=sum([(S(:,EDF.Chan_Select)'>=EDF.DigMax(EDF.Chan_Select,ones(RecLen,1))) + ... - (S(:,EDF.Chan_Select)'<=EDF.DigMin(EDF.Chan_Select,ones(RecLen,1)))])==0; - EDF.ERROR.DigMinMax_Warning(find(sum([(S'>EDF.DigMax(:,ones(RecLen,1))) + (S'0))=1; - % invalid=[invalid; find(V==0)+l*k]; + %%%%% Test on Over- (Under-) Flow +% V=sum([(S'==EDF.DigMax(:,ones(RecLen,1))) + (S'==EDF.DigMin(:,ones(RecLen,1)))])==0; + V=sum([(S(:,EDF.Chan_Select)'>=EDF.DigMax(EDF.Chan_Select,ones(RecLen,1))) + ... + (S(:,EDF.Chan_Select)'<=EDF.DigMin(EDF.Chan_Select,ones(RecLen,1)))])==0; + EDF.ERROR.DigMinMax_Warning(find(sum([(S'>EDF.DigMax(:,ones(RecLen,1))) + (S'0))=1; + % invalid=[invalid; find(V==0)+l*k]; - if floor(Mode/2)==1 - for k=1:EDF.NS, - DAT.Record(nrec*EDF.SPR(k)+(1-EDF.SPR(k):0),k)=S(1:EDF.SPR(k),k); - end; - else - DAT.Record(nrec*RecLen+(1-RecLen:0),:)=S; - end; + if floor(Mode/2)==1 + for k=1:EDF.NS, + DAT.Record(nrec*EDF.SPR(k)+(1-EDF.SPR(k):0),k)=S(1:EDF.SPR(k),k); + end; + else + DAT.Record(nrec*RecLen+(1-RecLen:0),:)=S; + end; - DAT.Valid(nrec*RecLen+(1-RecLen:0))=V; + DAT.Valid(nrec*RecLen+(1-RecLen:0))=V; end; -if rem(Mode,2)==0 % Autocalib - DAT.Record=[ones(RecLen*length(Records),1) DAT.Record]*EDF.Calib; +if rem(Mode,2)==0 % Autocalib + DAT.Record=[ones(RecLen*length(Records),1) DAT.Record]*EDF.Calib; end; DAT.Record=DAT.Record'; diff --git a/external/fieldtrip/private/readmarkerfile.m b/external/fieldtrip/private/readmarkerfile.m index 1b60585..2faa71c 100644 --- a/external/fieldtrip/private/readmarkerfile.m +++ b/external/fieldtrip/private/readmarkerfile.m @@ -16,7 +16,7 @@ while true l = fgetl(f); if ~isstr(l) - break + break end markfile{end + 1} = l; end @@ -36,7 +36,7 @@ for i = 1:length(nsamples) if nsamples(i) == 0 - warning('marker %s in %s has zero samples', names{i}, folder); + warning('marker %s in %s has zero samples', names{i}, folder); end end @@ -47,10 +47,10 @@ % Convert from index origin 0 to 1 if nsamples(i) ~= 0 - marks{i}(:, 1) = marks{i}(:, 1) + 1; + marks{i}(:, 1) = marks{i}(:, 1) + 1; end end data = struct('number_markers', {nmarkers}, 'number_samples', {nsamples}, ... - 'marker_names', {names}, 'trial_times', {marks}); + 'marker_names', {names}, 'trial_times', {marks}); diff --git a/external/fieldtrip/private/recodeevent.m b/external/fieldtrip/private/recodeevent.m deleted file mode 100644 index 94ca5de..0000000 --- a/external/fieldtrip/private/recodeevent.m +++ /dev/null @@ -1,229 +0,0 @@ -function [ev] = recodeevent(cfg, event, trl) - -% RECODEEVENT will recode the event structure, given the trial -% definition that was analyzed -% -% In FieldTrip, you always start with defining a "trl" field containing -% the samples in the raw datafile that you want to analyze. That "trl" -% is based on the events in the dataset. After artifact rejection, it may -% be the case that trials have been removed completely, or that trials -% have been cut into pieces. This complicates finding a match between the -% original events and the pieces of data that are analyzed. This functino -% restores that match. -% -% Use as -% [ev] = recodeevent(cfg, data) -% where cfg is a structure with configuration settings and data contains the -% (nested) configuration that describes the original trial definition and -% event structure. -% -% Alternatively, you can also specify the event structure and trial definition -% yourself with -% [ev] = recodeevent(cfg, event, trl) -% -% the configuration can contain -% cfg.eventtype = empty, 'string' or cell-array with multiple strings -% cfg.eventvalue = empty or a list of event values (can be numeric or string) -% -% cfg.searchrange = 'anywhere' search anywhere for the event, (default) -% 'insidetrial' only search inside -% 'outsidetrial' only search outside -% 'beforetrial' only search before the trial -% 'aftertrial' only search after the trial -% 'beforezero' only search before time t=0 of each trial -% 'afterzero' only search after time t=0 of each trial -% -% cfg.nearestto = 'trialzero' compare with time t=0 for each trial (default) -% 'trialbegin' compare with the begin of each trial -% 'trialend' compare with the end of each trial -% -% cfg.match = 'exact' or 'nearest' -% -% cfg.output = 'event' the event itself -% 'eventvalue' the value of the event -% 'eventnumber' the number of the event -% 'samplenumber' the sample at which the event is located -% 'samplefromoffset' number of samples from t=0 (c.f. response time) -% 'samplefrombegin' number of samples from the begin of the trial -% 'samplefromend' number of samples from the end of the trial - -% Copyright (C) 2005, Robert Oostenveld -% -% $Log: recodeevent.m,v $ -% Revision 1.4 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.3 2006/07/24 11:29:29 roboos -% use private/findcfg function for locating the trl and event in the nested (previous) cfgs -% -% Revision 1.2 2005/07/01 13:11:18 roboos -% rewrite of initial version, using input from Markus, which makes it more intuitive to use -% - -fieldtripdefs - -% set the defaults -if ~isfield(cfg, 'eventtype'), cfg.eventtype = []; end -if ~isfield(cfg, 'eventvalue'), cfg.eventvalue = []; end -if ~isfield(cfg, 'searchrange'),cfg.searchrange = 'anywhere'; end -if ~isfield(cfg, 'nearestto'), cfg.nearestto = 'trialzero'; end -if ~isfield(cfg, 'match'), cfg.match = 'nearest'; end -if ~isfield(cfg, 'output'), cfg.output = 'eventvalue'; end - -% these should be numeric lists or cell-arrays with strings -if ischar(cfg.eventtype) - cfg.eventtype = {cfg.eventtype}; -end -if ischar(cfg.eventvalue) - cfg.eventvalue = {cfg.eventvalue}; -end - -if nargin==2 - % event and trl are not specified in the function call, but the data is given -> - % try to locate event and trl in the configuration - data = event; % rename the input variable - event = findcfg(data.cfg, 'event'); % search for the event field - trl = findcfg(data.cfg, 'trl'); % search for the trl field - if isempty(event) - error('could not locate event structure in the data'); - elseif isempty(trl) - error('could not locate trial definition in the data'); - end -elseif nargin~=3 - error('incorrect number of input arguments'); -end - -Ntrl = size(trl,1); -Nevent = length(event); - -% select the events of interest -fprintf('trial definition describes %d trials\n', Ntrl); -fprintf('original event structure contains %d events\n', Nevent); -selecttype = zeros(Nevent,1); -selectvalue = zeros(Nevent,1); -for i=1:Nevent - % test whether this event should be selected - if ~isempty(cfg.eventtype) - selecttype(i) = ~isempty(intersect(cfg.eventtype, event(i).type)); - else - selecttype(i) = 1; - end - % test whether this event should be selected - if ~isempty(cfg.eventvalue) - selectvalue(i) = ~isempty(intersect(cfg.eventvalue, event(i).value)); - else - selectvalue(i) = 1; - end -end -fprintf('selected %d events based on event type\n', sum(selecttype)); -fprintf('selected %d events based on event value\n', sum(selectvalue)); -fprintf('selected %d events based on event type and value\n', sum(selecttype.*selectvalue)); -eventnum = find(selecttype.*selectvalue); -event = event(eventnum); -Nevent = length(event); - -if Nevent<1 - error('there are no events to analyze'); -end - -% make a list with the sample, offset and duration of each event -% and sort the events according to the sample at which they occurred -sample = zeros(Nevent,1); -offset = zeros(Nevent,1); -duration = zeros(Nevent,1); -for i=1:Nevent - sample(i) = event(i).sample; - if ~isempty(event(i).offset) - offset(i) = event(i).offset; - else - offset(i) = nan; - end - if ~isempty(event(i).duration) - duration(i) = event(i).duration; - else - duration(i) = nan; - end -end -[sample, indx] = sort(sample); % sort the samples -offset = offset(indx); % sort the offset accordingly -duration = duration(indx); % sort the duration accordingly -event = event(indx); % sort the events accordingly -eventnum = eventnum(indx); % sort the numbers of the original events - -for i=1:Ntrl - trlbeg = trl(i,1); - trlend = trl(i,2); - trloffset = trl(i,3); - trlzero = trlbeg - trloffset; % the sample that corresponds with t=0 - - if strcmp(cfg.nearestto, 'trialzero') - trlsample = trlzero; % the sample that corresponds with t=0 - elseif strcmp(cfg.nearestto, 'trialbegin') - trlsample = trlbeg; % the sample at which the trial begins - elseif strcmp(cfg.nearestto, 'trialend') - trlsample = trlend; % the sample at which the trial ends - else - error('incorrect specification of cfg.nearestto') - end - - % compute a "distance" measure for each event towards this trial - switch cfg.searchrange - case 'anywhere' - distance = abs(sample - trlsample); - case 'beforezero' - distance = abs(sample - trlsample); - distance(find(sample>=trlzero)) = inf; - case 'afterzero' - distance = abs(sample - trlsample); - distance(find(sample<=trlzero)) = inf; - case 'beforetrial' - distance = abs(sample - trlsample); - distance(find(sample>=trlbeg)) = inf; - case 'aftertrial' - distance = abs(sample - trlsample); - distance(find(sample<=trlend)) = inf; - case 'insidetrial' - distance = abs(sample - trlsample); - distance(find((sampletrlend))) = inf; - case 'outsidetrial' - distance = abs(sample - trlsample); - distance(find((sample>=trlbeg) & (sample<=trlend))) = inf; - otherwise - error('incorrect specification of cfg.searchrange'); - end - - % determine the event that has the shortest distance towards this trial - [mindist, minindx] = min(distance); - if length(find(distance==mindist))>1 - error('multiple events are at the same distance from the trial'); - end - - if isinf(mindist) - % no event was found - ev(i) = nan; - elseif mindist~=0 && strcmp(cfg.match, 'exact') - % the event is not an exact match - ev(i) = nan; - else - switch cfg.output - case 'event' - ev(i) = event(minindx); - case 'eventvalue' - ev(i) = event(minindx).value; - case 'eventnumber' - ev(i) = eventnum(minindx); - case 'samplenumber' - ev(i) = event(minindx).sample; - case 'samplefromoffset' - ev(i) = event(minindx).sample - trlzero; - case 'samplefrombegin' - ev(i) = event(minindx).sample - trlbeg; - case 'samplefromend' - ev(i) = event(minindx).sample - trlend; - otherwise - error('incorrect specification of cfg.output'); - end - end - -end % looping over all trials - diff --git a/external/fieldtrip/private/redefinetrial.m b/external/fieldtrip/private/redefinetrial.m deleted file mode 100644 index 9e48b48..0000000 --- a/external/fieldtrip/private/redefinetrial.m +++ /dev/null @@ -1,326 +0,0 @@ -function [data] = redefinetrial(cfg, data) - -% REDEFINETRIAL allows you to adjust the time axis of your data, i.e. to -% change from stimulus-locked to response-locked. Furthermore, it allows -% you to select a time window of interest, or to resegment your long trials -% into shorter fragments. -% -% Use as -% data = redefinetrial(cfg, data) -% where the input data should correspond to the output of PREPROCESSING and -% the configuration should be specified as explained below. Note that some -% options are mutually exclusive, and require two calls to this function to -% avoid confucion about the order in which they are applied. -% -% For selecting a subset of trials you can specify -% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') -% -% For selecting trials with a minimum length you can specify -% cfg.minlength = length in seconds, can be 'maxperlen' (default = []) -% -% For realiging the time axes of all trials to a new reference time -% point (i.e. change the definition for t=0) you can use the following -% configuration option -% cfg.offset = single number or Nx1 vector, expressed in samples relative to current t=0 -% -% For selecting a specific subsection of (i.e. cut out a time window -% of interest) you can select a time window in seconds that is common -% in all trials -% cfg.toilim = [tmin tmax] to specify a latency window in seconds -% -% Alternatively you can specify the begin and end sample in each trial -% cfg.begsample = single number or Nx1 vector, expressed in samples relative to the start of the input trial -% cfg.endsample = single number or Nx1 vector, expressed in samples relative to the start of the input trial -% -% Alternatively you can specify a new trial definition, expressed in -% samples relative to the original recording -% cfg.trl = Nx3 matrix with the trial definition, see DEFINETRIAL -% -% See also DEFINETRIAL, RECODEEVENT, PREPROCESSING - -% Copyright (C) 2006-2008, Robert Oostenveld -% -% $Log: redefinetrial.m,v $ -% Revision 1.25 2009/08/13 20:47:02 jansch -% changed typo in key-value pair 'hdr',hdr. this should read 'header',hdr and -% speeds up the function considerably -% -% Revision 1.24 2009/01/14 15:11:22 roboos -% corrected documentation for cfg.begsample/endsample -% fixed bug in output data.cfg.trl (one sample too long at the end) for input cfg.toilim and input cfg.begsample/endsample -% cleaned up the code for cfg.trl (use default variable names) -% -% Revision 1.23 2008/11/10 10:48:55 jansch -% removed typo -% -% Revision 1.22 2008/11/10 10:47:16 jansch -% added 1 to recomputed time-axes if cfg.trl. before, the time-axis was one -% sample too short -% -% Revision 1.21 2008/11/10 10:01:58 jansch -% ensured correct trial-definition in output data.cfg.trl if cfg.trl -% -% Revision 1.20 2008/11/10 09:41:21 jansch -% added sampling-frequency to output if cfg.trl is specified -% -% Revision 1.19 2008/10/07 16:08:11 estmee -% Changed the way fetch_data is called. -% -% Revision 1.18 2008/10/07 08:58:51 roboos -% committed the changes that Esther made recently, related to the support of data as input argument to the artifact detection functions. I hope that this does not break the functions too seriously. -% -% Revision 1.17 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.16 2008/07/30 07:43:40 roboos -% determine max sample number correctly, also if trials are ordered differently, i.e. trl(end,:) does not have to be the last one in the recording -% -% Revision 1.15 2008/06/25 06:37:57 roboos -% change in whitespace -% -% Revision 1.14 2008/05/06 14:03:10 sashae -% change in trial selection, cfg.trials can be a logical -% -% Revision 1.13 2008/04/21 14:27:12 jansch -% changed trlnew into trl to be able to output the new trl-matrix correctly -% and elegantly into the output-structure -% -% Revision 1.12 2008/04/15 16:11:54 estmee -% updated documentation -% -% Revision 1.11 2008/04/15 16:07:24 estmee -% inserted code that creates new trials based on cfg.trl -% -% Revision 1.10 2008/04/14 14:59:31 roboos -% added test for correct cfg.trl -% -% Revision 1.9 2008/04/08 20:21:32 roboos -% updated documentation, made some room in the code to plug in the new functionality from Esther -% -% Revision 1.8 2007/12/18 16:21:02 sashae -% added option for trial selection, updated documentation and fixed some old code, -% now uses findcfg for finding the trl -% -% Revision 1.7 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.6 2007/03/30 17:05:40 ingnie -% checkinput; only proceed when input data is allowed datatype -% -% Revision 1.5 2007/02/07 12:09:56 roboos -% fixed some small bugs, thanks to Nienke -% -% Revision 1.4 2007/01/04 12:18:05 roboos -% changed a print statement -% -% Revision 1.3 2007/01/02 09:48:06 roboos -% fixed some small typos, prevent the selection of data that is completely outside teh toilim, implemented support for cfg.minlength -% -% Revision 1.2 2006/10/24 06:48:45 roboos -% small changes and bugfixes to make it work, updated documentation -% -% Revision 1.1 2006/10/19 16:06:51 roboos -% new implementation -% - -fieldtripdefs - -% set the defaults -if ~isfield(cfg, 'offset'), cfg.offset = []; end -if ~isfield(cfg, 'toilim'), cfg.toilim = []; end -if ~isfield(cfg, 'begsample'), cfg.begsample = []; end -if ~isfield(cfg, 'endsample'), cfg.endsample = []; end -if ~isfield(cfg, 'minlength'), cfg.minlength = []; end -if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end -if ~isfield(cfg, 'feedback'), cfg.feedback = 'yes'; end -if ~isfield(cfg, 'trl'), cfg.trl = []; end - -% check if the input data is valid for this function -data = checkdata(data, 'datatype', 'raw', 'feedback', cfg.feedback); -fb = strcmp(cfg.feedback, 'yes'); - -% trl is not specified in the function call, but the data is given -> -% try to locate the trial definition (trl) in the nested configuration -if isfield(data,'cfg') - trl = findcfg(data.cfg, 'trl'); - if length(data.trial)~=size(trl,1) || length(data.time)~=size(trl,1) - error('the trial definition is inconsistent with the data'); - end -else - trl = []; -end -trlold = trl; - -% select trials of interest -if ~strcmp(cfg.trials, 'all') - if islogical(cfg.trials), cfg.trials=find(cfg.trials); end - if fb, fprintf('selecting %d trials\n', length(cfg.trials)); end - data.trial = data.trial(cfg.trials); - data.time = data.time(cfg.trials); - trl = trl(cfg.trials,:); - if length(cfg.offset)>1 && length(cfg.offset)~=length(cfg.trials) - cfg.offset=cfg.offset(cfg.trials); - end - if length(cfg.begsample)>1 && length(cfg.begsample)~=length(cfg.trials) - cfg.begsample=cfg.begsample(cfg.trials); - end - if length(cfg.endsample)>1 && length(cfg.endsample)~=length(cfg.trials) - cfg.endsample=cfg.endsample(cfg.trials); - end -end -Ntrial = size(trl,1); - -% check the input arguments, only one method for processing is allowed -numoptions = ~isempty(cfg.toilim) + ~isempty(cfg.offset) + (~isempty(cfg.begsample) || ~isempty(cfg.endsample)) + ~isempty(cfg.trl); -if numoptions>1 - error('you should specify only one of the options for redefining the data segments'); -end -if numoptions==0 && isempty(cfg.minlength) && strcmp(cfg.trials, 'all') - error('you should specify at least one configuration option'); -end - -% start processing -if ~isempty(cfg.toilim) - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % select a latency window from each trial - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - begsample = zeros(Ntrial,1); - endsample = zeros(Ntrial,1); - skiptrial = zeros(Ntrial,1); - for i=1:Ntrial - if cfg.toilim(1)>data.time{i}(end) || cfg.toilim(2). +% +% $Id: refine.m 952 2010-04-21 18:29:51Z roboos $ if nargin<3 method = 'banks'; @@ -40,9 +47,9 @@ ndhk = size(dhk,1); insert = spalloc(3*npnt,3*npnt,3*ndhk); - dhkr = zeros(4*ndhk,3); % allocate memory for the new triangles - pntr = zeros(npnt+3*ndhk,3); % allocate memory for the maximum number of new vertices - pntr(1:npnt,:) = pnt; % insert the original vertices + dhkr = zeros(4*ndhk,3); % allocate memory for the new triangles + pntr = zeros(npnt+3*ndhk,3); % allocate memory for the maximum number of new vertices + pntr(1:npnt,:) = pnt; % insert the original vertices current = npnt; for i=1:ndhk diff --git a/external/fieldtrip/private/rejectartifact.m b/external/fieldtrip/private/rejectartifact.m deleted file mode 100644 index abb2e36..0000000 --- a/external/fieldtrip/private/rejectartifact.m +++ /dev/null @@ -1,478 +0,0 @@ -function [cfg] = rejectartifact(cfg,data) - -% REJECTARTIFACT removes data segments containing artifacts. It returns a -% configuration structure with a modified trial definition which can be -% used for preprocessing of only the clean data. -% -% You should start by detecting the artifacts in the data using the -% function ARTIFACT_xxx where xxx is the type of artifact. Subsequently -% REJECTARTIFACT looks at the detected artifacts and removes them from -% the trial definition or from the data. -% -% Use as -% cfg = rejectartifact(cfg) -% with the cfg as obtained from DEFINETRIAL, or as -% data = rejectartifact(cfg, data) -% with the data as obtained from PREPROCESSING -% -% The following configuration options are supported: -% cfg.artfctdef.reject = 'none', 'partial' or 'complete' (default = 'complete') -% cfg.artfctdef.minaccepttim = length in seconds (default = 0.1) -% cfg.artfctdef.feedback = 'yes' or 'no' (default = 'no') -% cfg.artfctdef.eog.artifact = Nx2 matrix with artifact segments, this is added to the cfg by using ARTIFACT_EOG -% cfg.artfctdef.jump.artifact = Nx2 matrix with artifact segments, this is added to the cfg by using ARTIFACT_JUMP -% cfg.artfctdef.muscle.artifact = Nx2 matrix with artifact segments, this is added to the cfg by using ARTIFACT_MUSCLE -% cfg.artfctdef.zvalue.artifact = Nx2 matrix with artifact segments, this is added to the cfg by using ARTIFACT_ZVALUE -% cfg.artfctdef.xxx.artifact = Nx2 matrix with artifact segments, this should be added by your own artifact detection function -% -% A trial that contains an artifact can be rejected completely or -% partially. In case of partial rejection, a minimum length of the -% resulting sub-trials can be specified. -% -% Output: -% If cfg is used as the only input parameter, a cfg with a new trl is the output. -% If cfg and data are both input parameters, a new raw data structure with only the clean data segments is the output. -% -% See also ARTIFACT_EOG, ARTIFACT_MUSCLE, ARTIFACT_JUMP, ARTIFACT_MANUAL, ARTIFACT_THRESHOLD, ARTIFACT_CLIP, ARTIFACT_ECG - -% Undocumented local options: -% cfg.headerfile -% cfg.reject -% cfg.trl -% cfg.trlold -% cfg.version -% These old configuration options are still supported -% cfg.rejectmuscle = 'no' or 'yes' -% cfg.rejecteog = 'no' or 'yes' -% cfg.rejectjump = 'no' or 'yes' -% cfg.rejectfile = string with filename -% cfg.artfctdef.writerej = filename of rejection file -% cfg.artfctdef.type = cell-array with strings, e.g. {'eog', 'muscle' 'jump'} - -% Copyright (C) 2003-2007, Robert Oostenveld -% -% $Log: rejectartifact.m,v $ -% Revision 1.48 2009/06/23 18:33:17 roboos -% use the trl from the input data and not from the config in case of nargin>1 -% -% Revision 1.47 2009/03/23 21:20:10 roboos -% removed extra ; -% -% Revision 1.46 2009/01/27 17:11:42 roboos -% updated the help -% -% Revision 1.45 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.44 2009/01/14 11:29:55 sashae -% temporarily disabled previous revision -% -% Revision 1.43 2009/01/13 10:14:58 sashae -% changed handling of the output cfg: now the cfg also has cfg.previous fields, -% similar to data.cfg.previous. this way the output of definetrial and the -% artifact functions is kept separately from subsequent preprocessing steps -% -% Revision 1.42 2008/10/13 13:54:38 estmee -% Documentation is updated and added fetch_header (used when there are 2 input arguments). -% -% Revision 1.41 2008/10/13 13:05:07 sashae -% replaced call to dataset2files with checkconfig -% -% Revision 1.40 2008/10/07 16:06:27 estmee -% added error when "no trials left" -% -% Revision 1.39 2008/10/07 08:58:51 roboos -% committed the changes that Esther made recently, related to the support of data as input argument to the artifact detection functions. I hope that this does not break the functions too seriously. -% -% Revision 1.38 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.37 2008/05/13 15:37:24 roboos -% switched to using read_data/header instead of the read_fcdc_data/header wrapper functions -% -% Revision 1.36 2007/03/06 16:15:43 roboos -% keep the values of the 4th and subsequent column in the trl matrix, also when doing partial artifact rejection -% -% Revision 1.35 2007/01/04 17:08:36 roboos -% some reordering of code, no functional change -% added try-catch around the reading of the events -% -% Revision 1.34 2006/09/18 18:37:15 roboos -% updated documentation -% -% Revision 1.33 2006/06/26 15:17:33 roboos -% small change for supporting the rejectxxx backward compatible stuff, concatenate explicitely with cat function along 1st dimension, removed warnings -% -% Revision 1.32 2006/06/20 12:56:57 roboos -% updated documentation, removed unused variable in code -% -% Revision 1.31 2006/04/20 09:58:34 roboos -% updated documentation -% -% Revision 1.30 2006/02/24 16:40:53 roboos -% added one fprintf information -% -% Revision 1.29 2006/01/17 12:28:58 roboos -% add version information to the cfg.artfctdef substructure -% -% Revision 1.28 2006/01/12 17:18:18 roboos -% fixed bug in testing which sub-structures contain artifacts -% -% Revision 1.27 2006/01/12 14:22:03 roboos -% fixed bug in negation of boolean rejectall vector -% -% Revision 1.26 2006/01/12 14:12:53 roboos -% convert rejectall vector containing artifact type into logical before proceeding with old code -% -% Revision 1.25 2006/01/12 13:48:14 roboos -% get the detected artifacts from the configuration structure instead of from the artifact_xxx function -% implemented graphical feedback using two plots (using cfg.artfctdef.feedback) -% - -fieldtripdefs - -if 0 - % this code snippet ensures that these functions are included in the - % documentation as dependencies - try, dum = artifact_ecg; end - try, dum = artifact_eog; end - try, dum = artifact_muscle; end - try, dum = artifact_jump; end - try, dum = artifact_clip; end - try, dum = artifact_manual; end - try, dum = artifact_threshold; end -end - -% check if the input cfg is valid for this function -cfg = checkconfig(cfg, 'trackconfig', 'on'); -cfg = checkconfig(cfg, 'dataset2files', {'yes'}); - -% set the defaults -if ~isfield(cfg, 'artfctdef'), cfg.artfctdef = []; end -if ~isfield(cfg.artfctdef,'type'), cfg.artfctdef.type = {}; end -if ~isfield(cfg.artfctdef,'reject'), cfg.artfctdef.reject = 'complete'; end -if ~isfield(cfg.artfctdef,'minaccepttim'), cfg.artfctdef.minaccepttim = 0.1; end -if ~isfield(cfg.artfctdef,'feedback'), cfg.artfctdef.feedback = 'no'; end - -% convert from old-style to new-style configuration -if isfield(cfg,'reject') - warning('converting from old-style artifact configuration to new-style'); - cfg.artfctdef.reject = cfg.reject; - cfg = rmfield(cfg, 'reject'); -end - -% convert from old-style to new-style configuration -if isfield(cfg.artfctdef,'common') - warning('converting from old-style artifact configuration to new-style'); - if isfield(cfg.artfctdef.common,'minaccepttim') - cfg.artfctdef.minaccepttim = cfg.artfctdef.common.minaccepttim; - cfg.artfctdef = rmfield(cfg.artfctdef, 'common'); - end -end - -% ensure that it is a cell array -if ischar(cfg.artfctdef.type) - cfg.artfctdef.type = {cfg.artfctdef.type}; -end - -% support the rejectXXX cfg settings for backward compatibility -if isfield(cfg, 'rejectmuscle') - dum = strmatch('muscle', cfg.artfctdef.type, 'exact'); - if strcmp(cfg.rejectmuscle,'yes') && isempty(dum) - % this overrules the other setting, add it to the type-list - cfg.artfctdef.type = cat(1, {'muscle'}, cfg.artfctdef.type(:)); - elseif strcmp(cfg.rejectmuscle,'no') && ~isempty(dum) - % this overrules the other setting, remove it from the type-list - cfg.artfctdef.type(dum) = []; - end - cfg = rmfield(cfg, 'rejectmuscle'); -end - -% support the rejectXXX cfg settings for backward compatibility -if isfield(cfg, 'rejecteog') - dum = strmatch('eog', cfg.artfctdef.type, 'exact'); - if strcmp(cfg.rejecteog,'yes') && isempty(dum) - % this overrules the other setting, add it to the type-list - cfg.artfctdef.type = cat(1, {'eog'}, cfg.artfctdef.type(:)); - elseif strcmp(cfg.rejecteog,'no') && ~isempty(dum) - % this overrules the other setting, remove it from the type-list - cfg.artfctdef.type(dum) = []; - end - cfg = rmfield(cfg, 'rejecteog'); -end - -% support the rejectXXX cfg settings for backward compatibility -if isfield(cfg, 'rejectjump') - dum = strmatch('jump', cfg.artfctdef.type, 'exact'); - if strcmp(cfg.rejectjump,'yes') && isempty(dum) - % this overrules the other setting, add it to the type-list - cfg.artfctdef.type = cat(1, {'jump'}, cfg.artfctdef.type(:)); - elseif strcmp(cfg.rejectjump,'no') && ~isempty(dum) - % this overrules the other setting, remove it from the type-list - cfg.artfctdef.type(dum) = []; - end - cfg = rmfield(cfg, 'rejectjump'); -end - -% support the rejectXXX cfg settings for backward compatibility -if isfield(cfg, 'rejectfile') - % this is slightly different to the ones above, since rejectfile is either 'no' or contains the filename - dum = strmatch('file', cfg.artfctdef.type, 'exact'); - if ~strcmp(cfg.rejectfile,'no') && isempty(dum) - % this overrules the other setting, add it to the type-list - cfg.artfctdef.type = cat(1, {'file'}, cfg.artfctdef.type(:)); - elseif strcmp(cfg.rejectfile,'no') && ~isempty(dum) - % this overrules the other setting, remove it from the type-list - cfg.artfctdef.type(dum) = []; - end -end - -if nargin>1 - trl = findcfg(data.cfg, 'trl'); -elseif isfield(cfg, 'trl') - trl = cfg.trl; -end - -% ensure that there are trials that can be scanned for artifacts and/or rejected -if isempty(trl) - error('no trials were selected, cannot perform artifact detection/rejection'); -end - -% prevent double occurences of artifact types, ensure that the order remains the same -[dum, i] = unique(cfg.artfctdef.type); -cfg.artfctdef.type = cfg.artfctdef.type(sort(i)); -% ensure that it is a row vector -cfg.artfctdef.type = cfg.artfctdef.type(:)'; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% call the appropriate function for each of the artifact types -% this will produce a Nx2 matrix with the begin and end sample of artifacts -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -for type=1:length(cfg.artfctdef.type) - fprintf('evaluating artifact_%s\n', cfg.artfctdef.type{type}); - % each call to artifact_xxx adds cfg.artfctdef.xxx.artifact - cfg = feval(sprintf('artifact_%s', cfg.artfctdef.type{type}), cfg); -end - -% collect the artifacts that have been detected from cfg.artfctdef.xxx.artifact -dum = fieldnames(cfg.artfctdef); -sel = []; -artifact = {}; -for i=1:length(dum) - sel(i) = issubfield(cfg.artfctdef, dum{i}) && issubfield(cfg.artfctdef, [dum{i} '.artifact']); - if sel(i) - artifact{end+1} = getsubfield(cfg.artfctdef, [dum{i} '.artifact']); - num = size(artifact{end}, 1); - if isempty(num) - num = 0; - end - fprintf('detected %3d %s artifacts\n', num, dum{i}); - end -end -% update the configuration to reflect the artifacts types that were scanned -cfg.artfctdef.type = dum(find(sel)); - -% combine all trials into a single boolean vector -trialall = zeros(1,max(trl(:,2))); -for j=1:size(trl,1) - trialall(trl(j,1):trl(j,2)) = 1; -end - -% combine all artifacts into a single boolean vector -rejectall = zeros(1,max(trl(:,2))); -for i=1:length(cfg.artfctdef.type) - dum = artifact{i}; - for j=1:size(dum,1) - rejectall(dum(j,1):dum(j,2)) = i; % the artifact type is coded here - end -end - -% ensure that both vectors are the same length -if length(trialall)>length(rejectall) - rejectall(length(trialall)) = 0; -elseif length(trialall)1 - if isempty(cfg.trl) - error('No trials left after artifact rejection.') - else - tmpcfg = []; - tmpcfg.trl = cfg.trl; - data = redefinetrial(tmpcfg,data); - % remember the configuration details, this overwrites the stored configuration of redefinetrial - data.cfg = cfg; - % return the data instead of the cfg - cfg = data; - end -end - diff --git a/external/fieldtrip/private/rejectcomponent.m b/external/fieldtrip/private/rejectcomponent.m deleted file mode 100644 index 9c090fa..0000000 --- a/external/fieldtrip/private/rejectcomponent.m +++ /dev/null @@ -1,196 +0,0 @@ -function [data] = rejectcomponent(cfg, comp, data) - -% REJECTCOMPONENT backprojects an ICA (or similar) decomposition to the -% channel level after removing the independent components that contain -% the artifacts. This function does not automatically detect the artifact -% components, you will have to do that yourself. -% -% Use as -% [data] = rejectcomponent(cfg, comp) -% or as -% [data] = rejectcomponent(cfg, comp, data) -% -% where the input comp is the result of COMPONENTANALYSIS. The output -% data will have the same format as the output of PREFPROCESSING. -% An optional input argument data can be provided. In that case -% componentanalysis will do a subspace projection of the input data -% onto the space which is spanned by the topographies in the unmixing -% matrix in comp, after removal of the artifact components. -% -% The configuration should contain -% cfg.component = list of components to remove, e.g. [1 4 7] -% -% See also COMPONENTANALYSIS, PREFPROCESSING - -% Copyright (C) 2005-2009, Robert Oostenveld -% -% $Log: rejectcomponent.m,v $ -% Revision 1.12 2009/08/14 09:30:20 jansch -% also pass configuration of input data-structure to the output data.cfg in -% case of nargin==3 -% -% Revision 1.11 2009/03/26 13:21:50 jansch -% ensure correct montage in the case of hasdata -% -% Revision 1.10 2009/03/26 10:53:34 jansch -% added functionality to use a comp structure to remove components from a -% data structure. in addition the function now relies on apply_montage and -% it also attempts to balance the grad structure in the data, which is -% required for the correct computation of the leadfields when sourceanalysis -% is done on these data -% -% Revision 1.9 2009/03/23 20:03:50 roboos -% removed obsolete and non-functional code -% -% Revision 1.8 2008/11/04 20:20:34 roboos -% added optional baseline correction -% -% Revision 1.7 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.6 2007/03/04 14:45:28 chrhes -% fixed a small bug by adding the third input argument 'data' to the function -% interface (declaration) in the first line of the file. Also added an error -% message as a reminder that component removal from incomplete decompositions -% is not yet implemented: it is not clear how this should work, probably the -% optimal approach is to estimate the component waveforms using MMSE, but the -% question is whether to use a global cross-covariance estimate or a local -% (trial based) estimate to compute the adaptive spatial filter. -% -% Revision 1.5 2006/04/20 09:58:34 roboos -% updated documentation -% -% Revision 1.4 2006/01/30 17:00:46 roboos -% added initial support for incomplete decompositions (requires input data) -% -% Revision 1.3 2005/10/27 09:37:55 jansch -% fixed bug in assignment of labels -% -% Revision 1.2 2005/10/06 07:11:09 roboos -% changed from DOS to UNIX ascii format -% -% Revision 1.1 2005/09/29 16:23:24 jansch -% first implementation -% - -fieldtripdefs - -if ~isfield(cfg, 'component'), cfg.component = []; end - -comp = checkdata(comp, 'datatype', 'comp'); -ncomps = length(comp.label); -hasdata = nargin==3; - -if hasdata, - ntrials = length(data.trial); - data = checkdata(data, 'datatype', 'raw'); - label = data.label; -else - ntrials = length(comp.trial); - label = comp.topolabel; -end - -if min(cfg.component)<1 - error('you cannot remove components that are not present in the data'); -end - -if max(cfg.component)>ncomps - error('you cannot remove components that are not present in the data'); -end - -% set the rejected component amplitudes to zero -fprintf('removing %d components\n', length(cfg.component)); -fprintf('keeping %d components\n', ncomps-length(cfg.component)); - -%create a projection matrix by subtracting the subspace spanned by the -%topographies of the to-be-removed components from identity -[seldat, selcomp] = match_str(label, comp.topolabel); - -if length(seldat)~=length(label) && hasdata, - warning('the subspace projection is not guaranteed to be correct for non-orthogonal components'); -end - -if hasdata, - topo = comp.topo(selcomp,:); - invtopo = pinv(topo); - tra = eye(length(selcomp)) - topo(:, cfg.component)*invtopo(cfg.component, :); - %I am not sure about this, but it gives comparable results to the ~hasdata case - %when comp contains non-orthogonal (=ica) topographies, and contains a complete decomposition - - %the following is incorrect - %topo = comp.topo(selcomp, cfg.component); - %tra = eye(size(topo,1)) - topo*pinv(topo); - - %we are going from data to components, and back again - labelorg = comp.topolabel(selcomp); - labelnew = comp.topolabel(selcomp); - - keepunused = 'yes'; %keep the original data which are not present in the mixing provided -else - topo = comp.topo(selcomp, :); - topo(:, cfg.component) = 0; - tra = topo; - - %we are going from components to data - labelorg = comp.label; - labelnew = comp.topolabel(selcomp); - - %create data structure - data = []; - data.trial = comp.trial; - data.time = comp.time; - data.label = comp.label; - data.fsample = comp.fsample; - try, data.grad = comp.grad; end - - keepunused = 'no'; %don't need to keep the original rejected components -end - -%OLD CODE -% recontruct the trials -%for i=1:ntrials -% data.trial{i} = projector * data.trial{i}(seldat,:); -%end -%data.label = data.label(seldat); - -%create montage and apply this to data and grad -montage = []; -montage.tra = tra; -montage.labelorg = labelorg; -montage.labelnew = labelnew; -data = apply_montage(data, montage, 'keepunused', keepunused); -if isfield(data, 'grad'), - data.grad.balance.component = montage; - data.grad.balance.current = 'component'; - data.grad = apply_montage(data.grad, montage, 'keepunused', 'yes'); -else - warning('the gradiometer description does not match the data anymore'); -end - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% add the version details of this function call to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: rejectcomponent.m,v 1.12 2009/08/14 09:30:20 jansch Exp $'; -if nargin==2, - % remember the configuration details of the input data - try, cfg.previous = comp.cfg; end -elseif nargin==3, - try, cfg.previous{2} = comp.cfg; end - try, cfg.previous{1} = data.cfg; end - %the configuration of the data is relatively more important - %potential use of findcfg in subsequent analysis steps looks into - %the previous{1} first -end - -% keep the configuration in the output -data.cfg = cfg; - diff --git a/external/fieldtrip/private/rejectvisual.m b/external/fieldtrip/private/rejectvisual.m deleted file mode 100644 index 1508e08..0000000 --- a/external/fieldtrip/private/rejectvisual.m +++ /dev/null @@ -1,442 +0,0 @@ -function [data] = rejectvisual(cfg, data); - -% REJECTVISUAL shows the preprocessed data in all channels and/or trials to -% allow the user to make a visual selection of the data that should be -% rejected. The data can be displayed in a "summary" mode, in which case -% the variance (or another metric) in each channel and each trial is -% computed. Alternatively, all channels can be shown at once allowing -% paging through the trials, or all trials can be shown, allowing paging -% through the channels. -% -% Use as -% [data] = rejectvisual(cfg, data) -% -% The configuration can contain -% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), -% see CHANNELSELECTION for details -% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') -% cfg.latency = [begin end] in seconds, or 'minperlength', 'maxperlength', -% 'prestim', 'poststim' (default = 'maxperlength') -% cfg.method = string, describes how the data should be shown, this can be -% 'summary' show a single number for each channel and trial (default) -% 'channel' show the data per channel, all trials at once -% 'trial' show the data per trial, all channels at once -% cfg.keepchannel = string, determines how to deal with channels that are -% not selected, can be -% 'no' completely remove unselected channels from the data (default) -% 'yes' keep unselected channels in the output data -% 'nan' fill the channels that are unselected with NaNs -% cfg.metric = string, describes the metric that should be computed in summary mode -% for each channel in each trial, can be -% 'var' variance within each channel (default) -% 'min' minimum value in each channel -% 'max' maximum value each channel -% 'absmax' maximum absolute value in each channel -% 'range' range from min to max in each channel -% 'kurtosis' kurtosis, i.e. measure of peakedness of the amplitude distribution -% cfg.alim = value that determines the amplitude scaling for the -% channel and trial display, if empty then the amplitude -% scaling is automatic (default = []) -% cfg.eegscale = number, scaling to apply to the EEG channels prior to display -% cfg.eogscale = number, scaling to apply to the EOG channels prior to display -% cfg.ecgscale = number, scaling to apply to the ECG channels prior to display -% cfg.megscale = number, scaling to apply to the MEG channels prior to display -% -% The scaling to the EEG, EOG, ECG and MEG channels is optional and can -% be used to bring the absolute numbers of the different channel types in -% the same range (e.g. fT and uV). The channel types are determined from -% the input data using CHANNELSELECTION. -% -% Optionally, the raw data is preprocessed (filtering etc.) prior to -% displaying it or prior to computing the summary metric. The -% preprocessing and the selection of the latency window is NOT applied -% to the output data. -% -% The following settings are usefull for identifying EOG artifacts: -% cfg.bpfilter = 'yes' -% cfg.bpfilttype = 'but' -% cfg.bpfreq = [1 15] -% cfg.bpfiltord = 4 -% cfg.rectify = 'yes' -% -% The following settings are usefull for identifying muscle artifacts: -% cfg.bpfilter = 'yes' -% cfg.bpfreq = [110 140] -% cfg.bpfiltord = 10 -% cfg.bpfilttype = 'but' -% cfg.rectify = 'yes' -% cfg.boxcar = 0.2 -% -% See also REJECTARTIFACT, REJECTCOMPONENT - -% Undocumented local options: -% cfg.feedback -% -% This function depends on PREPROC which has the following options: -% cfg.absdiff -% cfg.blc -% cfg.blcwindow -% cfg.boxcar -% cfg.bpfilter -% cfg.bpfiltord -% cfg.bpfilttype -% cfg.bpfreq -% cfg.derivative -% cfg.detrend -% cfg.dftfilter -% cfg.dftfreq -% cfg.hilbert -% cfg.hpfilter -% cfg.hpfiltord -% cfg.hpfilttype -% cfg.hpfreq -% cfg.implicitref -% cfg.lnfilter -% cfg.lnfiltord -% cfg.lnfreq -% cfg.lpfilter -% cfg.lpfiltord -% cfg.lpfilttype -% cfg.lpfreq -% cfg.medianfilter -% cfg.medianfiltord -% cfg.rectify -% cfg.refchannel -% cfg.reref - -% Copyright (C) 2005-2006, Markus Bauer, Robert Oostenveld -% -% $Log: rejectvisual.m,v $ -% Revision 1.29 2009/07/21 08:33:15 crimic -% corrected typo -% -% Revision 1.28 2009/03/31 18:39:43 roboos -% don't print removed if empty (thanks to Irina) -% -% Revision 1.27 2009/03/23 21:17:31 roboos -% at end of function print a report with removed channels and trial-numbers -% -% Revision 1.26 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.25 2008/12/03 14:06:50 roboos -% added kurtosis as cfg.measure for summary -% -% Revision 1.24 2008/11/21 10:39:10 sashae -% added call to checkconfig -% -% Revision 1.23 2008/10/02 15:32:21 sashae -% replaced call to createsubcfg with checkconfig -% -% Revision 1.22 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.21 2008/08/12 16:02:20 roboos -% added cfg option for scaling eeg, eog, ecg and meg channels prior to display -% -% Revision 1.20 2008/05/06 14:03:10 sashae -% change in trial selection, cfg.trials can be a logical -% -% Revision 1.19 2007/12/18 17:52:20 sashae -% added option for trial selection, replaced some old code by call to findcfg -% -% Revision 1.18 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.17 2007/03/30 17:05:40 ingnie -% checkinput; only proceed when input data is allowed datatype -% -% Revision 1.16 2007/03/20 16:57:16 roboos -% added a fixme statement -% -% Revision 1.15 2007/01/18 10:08:18 roboos -% remove data.offset if present (old datasets) -% -% Revision 1.14 2007/01/11 13:53:13 roboos -% imlemented cfg.alim, which allows manual specificationh of the amplitude limits in the channel and trial display -% -% Revision 1.13 2007/01/10 11:46:01 roboos -% implemented selection of time window using cfg.latency -% -% Revision 1.12 2006/11/30 13:58:11 roboos -% implemented two new interactive methods: channel and trial browsing -% -% Revision 1.11 2006/11/07 08:29:56 roboos -% also allow trls with more than 3 columns -% -% Revision 1.10 2006/11/01 08:22:37 roboos -% made the default for cfg.channel consistent with documentation -> all instead of MEG -% -% Revision 1.9 2006/10/04 07:05:57 roboos -% added option keepchannel, can be no|yes|nan -% -% Revision 1.8 2006/08/29 14:26:27 roboos -% fixed bug: remove rejected trials from cfg.trl, and add the original trl as trlold to make it compatible with REJECTARTIFACT (thanks to Floris) -% -% Revision 1.7 2006/08/15 15:49:12 roboos -% implemented the deselection of channels in datasets, i.e. bad channels are removed (thanks to Markus Bauer) -% -% -% Revision 1.7 2006/06/14 12:44:00 marbau -% implemented the deselection of channels in datasets -% -% Revision 1.6 2006/06/14 12:44:00 roboos -% removed the documentation for cfg.lnfilttype, since that option is not supported by preproc -% -% Revision 1.5 2006/06/14 11:53:08 roboos -% switched to using cfg.preproc substructure -% -% Revision 1.4 2006/06/12 12:06:31 roboos -% added interactive option for plotting selected trials in a seperate figure (i.e. for detailled visual inspection) -% -% Revision 1.3 2006/06/12 11:20:30 roboos -% improved search for trl -% -% Revision 1.2 2006/06/12 07:51:10 roboos -% use local copy of offset, do not add to output data -% -% Revision 1.1 2006/05/17 14:45:42 roboos -% renamed rejecttrial into rejectvisual, added modified data (i.e. trials rejected) as output, implemented visual selection of bad trials using mouse, implemented manual selection of bad trials using keyboard -% -% Revision 1.2 2006/04/20 09:58:34 roboos -% updated documentation -% -% Revision 1.1 2005/11/11 14:39:28 roboos -% new implementation based on old code from Markus -% - -fieldtripdefs - -cfg = checkconfig(cfg, 'trackconfig', 'on'); - -% check if the input data is valid for this function -data = checkdata(data, 'datatype', 'raw', 'feedback', 'yes'); - -if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end -if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end -if ~isfield(cfg, 'latency'), cfg.latency = 'maxperlength'; end -if ~isfield(cfg, 'keepchannel'), cfg.keepchannel = 'no'; end -if ~isfield(cfg, 'feedback'), cfg.feedback = 'textbar'; end -if ~isfield(cfg, 'method'), cfg.method = 'summary'; end -if ~isfield(cfg, 'alim'), cfg.alim = []; end -if ~isfield(cfg, 'eegscale'), cfg.eegscale = []; end -if ~isfield(cfg, 'eogscale'), cfg.eogscale = []; end -if ~isfield(cfg, 'ecgscale'), cfg.ecgscale = []; end -if ~isfield(cfg, 'megscale'), cfg.megscale = []; end - -% for backward compatibility -if ~isfield(cfg, 'metric') && any(strcmp(cfg.method, {'var', 'min', 'max', 'absmax', 'range'})) - cfg.metric = cfg.method; - cfg.method = 'summary'; -end - -if ~isfield(cfg, 'metric') - cfg.metric = 'var'; -end - -% select trials of interest -if ~strcmp(cfg.trials, 'all') - if islogical(cfg.trials), cfg.trials=find(cfg.trials); end - fprintf('selecting %d trials\n', length(cfg.trials)); - data.trial = data.trial(cfg.trials); - data.time = data.time(cfg.trials); -end - -% determine the duration of each trial -for i=1:length(data.time) - begsamplatency(i) = min(data.time{i}); - endsamplatency(i) = max(data.time{i}); -end - -% determine the latency window which is possible in all trials -minperlength = [max(begsamplatency) min(endsamplatency)]; -maxperlength = [min(begsamplatency) max(endsamplatency)]; - -% latency window for averaging and variance computation is given in seconds -if (strcmp(cfg.latency, 'minperlength')) - cfg.latency = []; - cfg.latency(1) = minperlength(1); - cfg.latency(2) = minperlength(2); -elseif (strcmp(cfg.latency, 'maxperlength')) - cfg.latency = []; - cfg.latency(1) = maxperlength(1); - cfg.latency(2) = maxperlength(2); -elseif (strcmp(cfg.latency, 'prestim')) - cfg.latency = []; - cfg.latency(1) = maxperlength(1); - cfg.latency(2) = 0; -elseif (strcmp(cfg.latency, 'poststim')) - cfg.latency = []; - cfg.latency(1) = 0; - cfg.latency(2) = maxperlength(2); -end - -% ensure that the preproc specific options are located in the cfg.preproc substructure -cfg = checkconfig(cfg, 'createsubcfg', {'preproc'}); - -% apply scaling to the selected channel types to equate the absolute numbers (i.e. fT and uV) -% make a seperate copy to prevent the original data from being scaled -tmpdata = data; -scaled = 0; -if ~isempty(cfg.eegscale) - scaled = 1; - chansel = match_str(tmpdata.label, channelselection('EEG', tmpdata.label)); - for i=1:length(tmpdata.trial) - tmpdata.trial{i}(chansel,:) = tmpdata.trial{i}(chansel,:) .* cfg.eegscale; - end -end -if ~isempty(cfg.eogscale) - scaled = 1; - chansel = match_str(tmpdata.label, channelselection('EOG', tmpdata.label)); - for i=1:length(tmpdata.trial) - tmpdata.trial{i}(chansel,:) = tmpdata.trial{i}(chansel,:) .* cfg.eogscale; - end -end -if ~isempty(cfg.ecgscale) - scaled = 1; - chansel = match_str(tmpdata.label, channelselection('ECG', tmpdata.label)); - for i=1:length(tmpdata.trial) - tmpdata.trial{i}(chansel,:) = tmpdata.trial{i}(chansel,:) .* cfg.ecgscale; - end -end -if ~isempty(cfg.megscale) - scaled = 1; - chansel = match_str(tmpdata.label, channelselection('MEG', tmpdata.label)); - for i=1:length(tmpdata.trial) - tmpdata.trial{i}(chansel,:) = tmpdata.trial{i}(chansel,:) .* cfg.megscale; - end -end - -if strcmp(cfg.method, 'channel') - if scaled - fprintf('showing the scaled data per channel, all trials at once\n'); - else - fprintf('showing the data per channel, all trials at once\n'); - end - [chansel, trlsel, cfg] = rejectvisual_channel(cfg, tmpdata); -elseif strcmp(cfg.method, 'trial') - if scaled - fprintf('showing the scaled per trial, all channels at once\n'); - else - fprintf('showing the data per trial, all channels at once\n'); - end - [chansel, trlsel, cfg] = rejectvisual_trial(cfg, tmpdata); -elseif strcmp(cfg.method, 'summary') - if scaled - fprintf('showing a summary of the scaled data for all channels and trials\n'); - else - fprintf('showing a summary of the data for all channels and trials\n'); - end - - [chansel, trlsel, cfg] = rejectvisual_summary(cfg, tmpdata); -end - -fprintf('%d trials marked as GOOD, %d trials marked as BAD\n', sum(trlsel), sum(~trlsel)); -fprintf('%d channels marked as GOOD, %d channels marked as BAD\n', sum(chansel), sum(~chansel)); - -% trl is not specified in the function call, but the data is given -> -% try to locate the trial definition (trl) in the nested configuration -if isfield(data, 'cfg') - trl = findcfg(data.cfg, 'trl'); -else - trl = []; -end -if isempty(trl) - % a trial definition is expected in each continuous data set - warning('could not locate the trial definition ''trl'' in the data structure'); -end -trlold=trl; - -% construct an artifact matrix from the trl matrix -if ~isempty(trl) - % remember the sample numbers (begin and end) of each trial and each artifact - % updating the trl and creating a trlold makes it compatible with REJECTARTIFACT - if ~strcmp(cfg.trials, 'all') - trl=trl(cfg.trials,:); - end - cfg.artifact = trl(~trlsel,1:2); - cfg.trl = trl( trlsel,:); - cfg.trlold = trlold; -else - % since sample numbers are unknown, it is not possible to remember them here - cfg.artifact = []; - cfg.trl = []; - cfg.trlold = []; -end - -% show the user which trials are removed -removed = find(~trlsel); -if ~isempty(removed) - fprintf('the following trials were removed: '); - for i=1:(length(removed)-1) - fprintf('%d, ', removed(i)); - end - fprintf('%d\n', removed(end)); -else - fprintf('no trials were removed\n'); -end - -% remove the selected trials from the data -data.time = data.time(trlsel); -data.trial = data.trial(trlsel); - -% remove the offset vector if present (only applies to datasets that have been preprocessed a long time ago) -if isfield(data, 'offset') - data = rmfield(data, 'offset'); -end - - -if ~all(chansel) - switch cfg.keepchannel - case 'no' - % show the user which channels are removed - removed = find(~chansel); - fprintf('the following channels were removed: '); - for i=1:(length(removed)-1) - fprintf('%s, ', data.label{removed(i)}); - end - fprintf('%s\n', data.label{removed(end)}); - - % remove channels that are not selected - for i=1:length(data.trial) - data.trial{i} = data.trial{i}(chansel,:); - end - data.label = data.label(chansel); - case 'nan' - % show the user which channels are removed - removed = find(~chansel); - fprintf('the following channels were filled with NANs: '); - for i=1:(length(removed)-1) - fprintf('%s, ', data.label{removed(i)}); - end - fprintf('%s\n', data.label{removed(end)}); - - % fill the data from the bad channels with nans - for i=1:length(data.trial) - data.trial{i}(~chansel,:) = nan; - end - case 'yes' - % keep all channels, also when they are not selected - end -end - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: rejectvisual.m,v 1.29 2009/07/21 08:33:15 crimic Exp $'; -% remember the configuration details of the input data -try, cfg.previous = data.cfg; end -% remember the exact configuration details in the output -data.cfg = cfg; - diff --git a/external/fieldtrip/private/rejectvisual_channel.m b/external/fieldtrip/private/rejectvisual_channel.m index c405c2e..ceeb7d6 100644 --- a/external/fieldtrip/private/rejectvisual_channel.m +++ b/external/fieldtrip/private/rejectvisual_channel.m @@ -4,24 +4,28 @@ % Copyright (C) 2006, Robert Oostenveld % -% $Log: rejectvisual_channel.m,v $ -% Revision 1.4 2007/01/11 13:53:13 roboos -% imlemented cfg.alim, which allows manual specificationh of the amplitude limits in the channel and trial display +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.3 2007/01/10 11:46:01 roboos -% implemented selection of time window using cfg.latency +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.2 2006/12/11 10:53:43 roboos -% corrected the internal name of the function (thanks to John Iversen) +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.1 2006/11/30 13:57:21 roboos -% new implementation, code moved to seperate subfunctions +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: rejectvisual_channel.m 1427 2010-07-19 11:44:01Z vlalit $ % determine the initial selection of trials and channels nchan = length(data.label); ntrl = length(data.trial); -cfg.channel = channelselection(cfg.channel, data.label); +cfg.channel = ft_channelselection(cfg.channel, data.label); trlsel = logical(ones(1,ntrl)); chansel = logical(zeros(1,nchan)); chansel(match_str(data.label, cfg.channel)) = 1; diff --git a/external/fieldtrip/private/rejectvisual_summary.m b/external/fieldtrip/private/rejectvisual_summary.m index dabb43f..0a67bef 100644 --- a/external/fieldtrip/private/rejectvisual_summary.m +++ b/external/fieldtrip/private/rejectvisual_summary.m @@ -5,7 +5,7 @@ % determine the initial selection of trials and channels nchan = length(data.label); ntrl = length(data.trial); -cfg.channel = channelselection(cfg.channel, data.label); +cfg.channel = ft_channelselection(cfg.channel, data.label); trlsel = logical(ones(1,ntrl)); chansel = logical(zeros(1,nchan)); chansel(match_str(data.label, cfg.channel)) = 1; @@ -39,7 +39,7 @@ level(:,i) = min(dat, [], 2); case 'max' level(:,i) = max(dat, [], 2); - case 'absmax' + case 'maxabs' level(:,i) = max(abs(dat), [], 2); case 'range' level(:,i) = max(dat, [], 2) - min(dat, [], 2); diff --git a/external/fieldtrip/private/resampledata.m b/external/fieldtrip/private/resampledata.m deleted file mode 100644 index c12d630..0000000 --- a/external/fieldtrip/private/resampledata.m +++ /dev/null @@ -1,283 +0,0 @@ -function [data] = resampledata(cfg, data); - -% RESAMPLEDATA performs a resampling or downsampling of the data -% -% Use as -% [data] = resampledata(cfg, data) -% -% The data should be organised in a structure as obtained from -% the PREPROCESSING function. The configuration should contain -% cfg.resamplefs = frequency at which the data will be resampled (default = 256 Hz) -% cfg.detrend = 'no' or 'yes', detrend the data prior to resampling (no default specified, see below) -% cfg.blc = 'no' or 'yes', baseline correct the data prior to resampling (default = 'no') -% cfg.feedback = 'no', 'text', 'textbar', 'gui' (default = 'text') -% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') -% -% Instead of specifying cfg.resamplefs, you can also specify a time axis on -% which you want the data to be resampled. This is usefull for merging data -% from two acquisition devides, after resampledata you can call APPENDDATA -% to concatenate the channles from the different acquisition devices. -% cfg.time = cell-array with one time axis per trial (i.e. from another dataset) -% cfg.method = interpolation method, see INTERP1 (default = 'pchip') -% -% Previously this function used to detrend the data by default. The -% motivation for this is that the data is filtered prior to resampling -% to avoid aliassing and detrending prevents occasional edge artifacts -% of the filters. Detrending is fine for removing slow drifts in data -% priot to frequency analysis, but detrending is not good if you -% subsequenlty want to look at the evoked fields. Therefore the old -% default value 'yes' has been removed. You now explicitely have to -% specify whether you want to detrend (probably so if you want to -% keep your analysis compatible with previous analyses that you did), -% or if you do not want to detrent (recommended in most cases). -% If you observe edge artifacts after detrending, it is recommended -% to apply a baseline correction to the data. -% -% The following fields in the structure 'data' are modified by this function -% data.fsample -% data.trial -% data.time -% -% See also PREPROCESSING - -% Copyright (C) 2003-2006, FC Donders Centre, Markus Siegel -% Copyright (C) 2004-2009, FC Donders Centre, Robert Oostenveld -% -% $Log: resampledata.m,v $ -% Revision 1.22 2009/08/14 09:35:45 jansch -% pass an updated trl matrix to the output as cfg.resampletrl, containing a -% 'consistent' trial description matrix relative to the new sampling rate. -% this is needed if in a later step fetch_data is invoked -% -% Revision 1.21 2009/04/03 08:06:35 jansch -% included possibility to resample data structures with an original non-integer -% sampling rate -% -% Revision 1.20 2009/03/31 15:31:00 jansch -% added the possibility to upsample a single value per trial; interp1 crashes -% in that case. instead now use repmat -% -% Revision 1.19 2009/03/26 14:28:04 jansch -% fixed incorrect check of defaults -% -% Revision 1.18 2009/03/26 14:26:57 jansch -% *** empty log message *** -% -% Revision 1.17 2009/03/11 13:29:33 roboos -% added option for resampling the data onto the time axis of another dataset. This supports both down- and upsampling. -% -% Revision 1.16 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.15 2008/06/10 18:20:17 sashae -% replaced blc and detrend with preproc modules -% -% Revision 1.14 2008/05/06 14:03:10 sashae -% change in trial selection, cfg.trials can be a logical -% -% Revision 1.13 2008/04/07 16:02:33 roboos -% changed default for detrending, added baselinecorrection -% -% Revision 1.12 2008/01/29 16:30:35 sashae -% moved some code, no functional changes -% -% Revision 1.11 2007/12/21 16:40:29 sashae -% added option for trial selection -% -% Revision 1.10 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.9 2007/03/30 17:05:40 ingnie -% checkinput; only proceed when input data is allowed datatype -% -% Revision 1.8 2006/08/16 08:24:18 roboos -% replaced fprintf by progress(), added cfg.feedback, updated documentation -% -% Revision 1.7 2005/09/15 11:31:07 roboos -% added support for single precision data, by temporarily converting to double precision -% -% Revision 1.6 2005/08/08 14:09:27 roboos -% fixed bug (data.origfsample was used but not defined) -% renamed cfg.originalfs to cfg.origfs -% -% Revision 1.5 2005/08/05 09:06:04 roboos -% removed the offset field in the output -% changed the way in which the new time-axis is computed -% -% Revision 1.4 2005/06/29 12:46:29 roboos -% the following changes were done on a large number of files at the same time, not all of them may apply to this specific file -% - added try-catch around the inclusion of input data configuration -% - moved cfg.version, cfg.previous and the assignment of the output cfg to the end -% - changed help comments around the configuration handling -% - some changes in whitespace -% -% Revision 1.3 2004/11/02 14:32:28 roboos -% included cfg.detrend in help -% fixed bug in timeaxis (inconsistent with offset due to rounding error) -% added cfg, cfg.version and cfg.previous to output -% -% Revision 1.2 2004/09/02 09:42:43 marsie -% initial CVS release -% included linear detrending (default) -% - -fieldtripdefs - -cfg = checkconfig(cfg, 'trackconfig', 'on'); - -% check if the input data is valid for this function -data = checkdata(data, 'datatype', 'raw', 'feedback', 'yes'); - -% set the defaults -if ~isfield(cfg, 'resamplefs'), cfg.resamplefs = []; end -if ~isfield(cfg, 'time'), cfg.time = {}; end -if ~isfield(cfg, 'detrend'), cfg.detrend = []; end % no default to enforce people to consider backward compatibility problem, see below -if ~isfield(cfg, 'blc'), cfg.blc = 'no'; end -if ~isfield(cfg, 'feedback'), cfg.feedback = 'text'; end -if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end -if ~isfield(cfg, 'method'), cfg.method = 'pchip'; end % interpolation method - -if isempty(cfg.detrend) - error('The previous default to apply detrending has been changed. Recommended is to apply a baseline correction instead of detrending. See the help of this function for more details.'); -end - -%set default resampling frequency -if isempty(cfg.resamplefs) && isempty(cfg.time), - cfg.resamplefs = 256; -end - -% this is needed if only a subset of trials is requested, -% and for an attempt to pass in the output a trl matrix -% which contains the indexing in the updated sampling rate -if isfield(data, 'cfg') % try to locate the trl in the nested configuration - trl = findcfg(data.cfg, 'trl'); -else - trl = []; -end - -% select trials of interest -if ~strcmp(cfg.trials, 'all') - if islogical(cfg.trials), cfg.trials=find(cfg.trials); end - fprintf('selecting %d trials\n', length(cfg.trials)); - data.trial = data.trial(cfg.trials); - data.time = data.time(cfg.trials); - % update the trial definition (trl) - if isempty(trl) - % a trial definition is expected in each continuous data set - warning('could not locate the trial definition ''trl'' in the data structure'); - else - cfg.trlold=trl; - cfg.trl=trl(cfg.trials,:); - end -end - -usefsample = ~isempty(cfg.resamplefs); -usetime = ~isempty(cfg.time); - -if usefsample && usetime - error('you should either specify cfg.resamplefs or cfg.time') -end - -% remember the original sampling frequency in the configuration -cfg.origfs = data.fsample; - -if usefsample - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % resample based on new sampling frequency - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - ntr = length(data.trial); - - progress('init', cfg.feedback, 'resampling data'); - [fsorig, fsres] = rat(cfg.origfs./cfg.resamplefs);%account for non-integer fs - cfg.resamplefs = cfg.origfs.*(fsres./fsorig);%get new fs exact - for itr = 1:ntr - progress(itr/ntr, 'resampling data in trial %d from %d\n', itr, ntr); - if strcmp(cfg.blc,'yes') - data.trial{itr} = preproc_baselinecorrect(data.trial{itr}); - end - if strcmp(cfg.detrend,'yes') - data.trial{itr} = preproc_detrend(data.trial{itr}); - end - % perform the resampling - if isa(data.trial{itr}, 'single') - % temporary convert this trial to double precision - data.trial{itr} = single(resample(double(data.trial{itr})',fsres,fsorig))'; - else - data.trial{itr} = resample(transpose(data.trial{itr}),fsres,fsorig)'; - end - % update the time axis - nsmp = size(data.trial{itr},2); - data.time{itr} = data.time{itr}(1) + (0:(nsmp-1))/cfg.resamplefs; - end % for itr - progress('close'); - - % specify the new sampling frequency in the output - data.fsample = cfg.resamplefs; - -elseif usetime - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % resample based on new time axes for each trial - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - ntr = length(data.trial); - - progress('init', cfg.feedback, 'resampling data'); - for itr = 1:ntr - progress(itr/ntr, 'resampling data in trial %d from %d\n', itr, ntr); - if strcmp(cfg.blc,'yes') - data.trial{itr} = preproc_baselinecorrect(data.trial{itr}); - end - if strcmp(cfg.detrend,'yes') - data.trial{itr} = preproc_detrend(data.trial{itr}); - end - % perform the resampling - if length(data.time{itr})>1, - data.trial{itr} = interp1(data.time{itr}', data.trial{itr}', cfg.time{itr}', cfg.method)'; - else - data.trial{itr} = repmat(data.trial{itr}, [1 length(cfg.time{itr}')]); - end - % update the time axis - data.time{itr} = cfg.time{itr}; - end % for itr - progress('close'); - - % specify the new sampling frequency in the output - t1 = cfg.time{1}(1); - t2 = cfg.time{1}(2); - data.fsample = 1/(t2-t1); - -end % if usefsample or usetime - -%try to give an updated trl matrix, which is necessary to fool -%fetch_data and fetch_header at a potential later stage of the -%analysis pipeline -%FIXME this is only done in case of usefsample, think of whether -%it is possible as well in the other case -if ~isempty(trl) && usefsample, - trlorig = trl; - offsindx = round((trl(:,1)-trl(:,3)).*(fsres./fsorig)); - offs = round(trl(:,3).*(fsres./fsorig)); - nsmp = cellfun('size',data.trial,2)'; - trl = [offsindx+offs offsindx+offs+nsmp-1 offs]; - cfg.resampletrl = trl; -end - -fprintf('original sampling rate = %d Hz\nnew sampling rate = %d Hz\n', cfg.origfs, data.fsample); - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: resampledata.m,v 1.22 2009/08/14 09:35:45 jansch Exp $'; -% remember the configuration details of the input data -try, cfg.previous = data.cfg; end -% remember the exact configuration details in the output -data.cfg = cfg; - diff --git a/external/fieldtrip/private/resampledesign.m b/external/fieldtrip/private/resampledesign.m index ce787f6..75dbf0a 100644 --- a/external/fieldtrip/private/resampledesign.m +++ b/external/fieldtrip/private/resampledesign.m @@ -20,43 +20,23 @@ % Copyright (C) 2005-2007, Robert Oostenveld % -% $Log: resampledesign.m,v $ -% Revision 1.5 2009/10/01 13:02:05 jansch -% added check for double occurrences of bootstrap samples if the number of -% replicates is <20 +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.4 2009/01/12 15:16:47 jansch -% enabled bootstrap-resampling for repeated measures +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.3 2007/07/18 15:07:54 roboos -% changed output, now also reindexing matrix for permutation (just like in case of bootstrap) instead of the permuted design itself -% implemented control variable for constraining the resampling within blocks -% changed the check for overlapping ivar/uvar/wvar/cvar -% updated documentation +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.2 2007/07/17 10:37:29 roboos -% updated help -% -% Revision 1.1 2007/07/04 16:04:53 roboos -% renamed randomizedesign to resampledesign -% first implementation of bootstrapping, sofar only for unpaired data -% added cfg.resampling=bootstrap/permutation -% -% Revision 1.7 2006/10/30 10:09:48 roboos -% removed the check that each repeated measurement should have the same number of elements (for uvar) -% -% Revision 1.6 2006/07/14 07:10:26 roboos -% do not treat uvar and wvar the same, wvar is not dealt with yet -% -% Revision 1.5 2006/06/13 11:36:11 roboos -% renamed cfg.bvar into cfg.wvar (within-block variable) -% -% Revision 1.4 2006/06/07 12:55:14 roboos -% changed a print statement -% -% Revision 1.3 2006/06/07 09:27:12 roboos -% rewrote most of the function, added support for uvar and cvar (instead of unitfactor), added support for a block variable cfg.wvar (for keeping all tapers within a trial together) +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: resampledesign.m 952 2010-04-21 18:29:51Z roboos $ if ~isfield(cfg, 'ivar'), cfg.ivar = []; end if ~isfield(cfg, 'uvar'), cfg.uvar = []; end diff --git a/external/fieldtrip/private/retriangulate.m b/external/fieldtrip/private/retriangulate.m index 873a9d9..bd9d61c 100644 --- a/external/fieldtrip/private/retriangulate.m +++ b/external/fieldtrip/private/retriangulate.m @@ -6,8 +6,8 @@ % Use as % [pnt, tri] = retriangulate(pnt1, tri1, pnt2, tri2, flag) % where -% pnt1, tri1 describe the desired triagulated surface shape -% pnt2, tri2 describe the triangulation that will be projected +% pnt1, tri1 describe the desired triagulated surface shape +% pnt2, tri2 describe the triangulation that will be projected % % The optional flag can be 0/1/2 and determines whether the center % of the triangulations should be shifted to the origin before the @@ -65,10 +65,12 @@ pnt3(indx(i),:) = pnt3(indx(i),:) + pnt1(i,:); end -warning off MATLAB:divideByZero +% turn the warning off +ws = warning('off', 'MATLAB:divideByZero'); pnt3 = pnt3 ./ [count count count]; -warning on MATLAB:divideByZero tri3 = tri2; +% revert to previous warning state +warning(ws) exception=find(count==0); if ~isempty(exception) diff --git a/external/fieldtrip/private/rigidbody.m b/external/fieldtrip/private/rigidbody.m index d65a39f..bcf90e9 100644 --- a/external/fieldtrip/private/rigidbody.m +++ b/external/fieldtrip/private/rigidbody.m @@ -31,18 +31,23 @@ % along with this program; if not, write to the Free Software % Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -% $Log: rigidbody.m,v $ -% Revision 1.4 2006/04/13 10:37:38 roboos -% added a ; to the end of a line +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.3 2005/08/15 08:15:32 roboos -% reimplemented the rotate function, which contained an error (the error is in the AIR technical reference) -% changed all functions to be dependent on the rotate, translate and scale function -% all functions now behave consistenly, which also means that they are not compleetly backward compatible w.r.t. the order of the rotations +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.2 2004/05/19 09:57:07 roberto -% added GPL copyright statement, added CVS log item +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: rigidbody.m 952 2010-04-21 18:29:51Z roboos $ % compute the homogenous transformation matrix for the translation T = translate(f([1 2 3])); diff --git a/external/fieldtrip/private/rmsubfield.m b/external/fieldtrip/private/rmsubfield.m deleted file mode 100644 index f0dd5fc..0000000 --- a/external/fieldtrip/private/rmsubfield.m +++ /dev/null @@ -1,36 +0,0 @@ -function [s] = rmsubfield(s, f, v); - -% RMSUBFIELD removes the contents of the specified field from a structure -% just like the standard Matlab RMFIELD function, except that you can also -% specify nested fields using a '.' in the fieldname. The nesting can be -% arbitrary deep. -% -% Use as -% s = rmsubfield(s, 'fieldname') -% or as -% s = rmsubfield(s, 'fieldname.subfieldname') -% -% See also SETFIELD, GETSUBFIELD, ISSUBFIELD - -% Copyright (C) 2006, Robert Oostenveld -% -% $Log: rmsubfield.m,v $ -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.1 2006/11/27 15:38:45 roboos -% new implementation -% - -if ~isstr(f) - error('incorrect input argument for fieldname'); -end - -% remove the nested subfield using recursion -[t, f] = strtok(f, '.'); -if any(f=='.') - u = rmsubfield(getfield(s, t), f); - s = setfield(s, t, u); -else - s = rmfield(s, t); -end diff --git a/external/fieldtrip/private/rotate.m b/external/fieldtrip/private/rotate.m index c303811..8bfb30e 100644 --- a/external/fieldtrip/private/rotate.m +++ b/external/fieldtrip/private/rotate.m @@ -7,8 +7,8 @@ % Use as % [H] = rotate(R) % where -% R [rx, ry, rz] in degrees -% H corresponding homogenous transformation matrix +% R [rx, ry, rz] in degrees +% H corresponding homogenous transformation matrix % % Note that the order in which the rotations are performs matters. The % rotation is first done around the z-axis, then the y-axis and finally the @@ -30,18 +30,23 @@ % along with this program; if not, write to the Free Software % Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -% $Log: rotate.m,v $ -% Revision 1.5 2006/09/12 13:35:28 roboos -% convert input rotation from degrees (according to documentation) into radians (needed for computations) +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.4 2005/08/15 08:15:33 roboos -% reimplemented the rotate function, which contained an error (the error is in the AIR technical reference) -% changed all functions to be dependent on the rotate, translate and scale function -% all functions now behave consistenly, which also means that they are not compleetly backward compatible w.r.t. the order of the rotations +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.3 2004/05/19 09:57:07 roberto -% added GPL copyright statement, added CVS log item +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: rotate.m 952 2010-04-21 18:29:51Z roboos $ % convert degrees to radians R = D*pi/180; diff --git a/external/fieldtrip/private/routlm.m b/external/fieldtrip/private/routlm.m index 0154dc8..f133497 100644 --- a/external/fieldtrip/private/routlm.m +++ b/external/fieldtrip/private/routlm.m @@ -1,23 +1,75 @@ -function [proj] = routlm(v1, v2, v3, la, mu); +function [varargout] = funname(varargin) % ROUTLM computes the projection of a point from its la/mu parameters % these equal the "Barycentric" coordinates % -% [proj] = routlm(v1, v2, v3, la, mu) -% +% Use as +% [proj] = routlm(v1, v2, v3, la, mu) % where v1, v2 and v3 are three vertices of the triangle -% -% also implemented as MEX file -% Copyright (C) 2002, Robert Oostenveld +% Copyright (C) 2002-2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% $Log: routlm.m,v $ -% Revision 1.4 2003/03/11 15:35:20 roberto -% converted all files from DOS to UNIX +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.3 2003/03/04 21:46:19 roberto -% added CVS log entry and synchronized all copyright labels +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: routlm.m 952 2010-04-21 18:29:51Z roboos $ + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% This is the native Matlab implementation. +% The mex file is many times faster and is therefore preferred. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% function [proj] = routlm(v1, v2, v3, la, mu); +% proj = (1-la-mu)*v1 + la*v2 + mu*v3; + +% compile the missing mex file on the fly +% remember the original working directory +pwdir = pwd; + +% determine the name and full path of this function +funname = mfilename('fullpath'); +mexsrc = [funname '.c']; +[mexdir, mexname] = fileparts(funname); + +try + % try to compile the mex file on the fly + warning('trying to compile MEX file from %s', mexsrc); + cd(mexdir); + + if ispc + mex -I. -c geometry.c + mex -I. -c routlm.c ; mex routlm.c routlm.obj geometry.obj + else + mex -I. -c geometry.c + mex -I. -c routlm.c ; mex -o routlm routlm.o geometry.o + end + + cd(pwdir); + success = true; + +catch + % compilation failed + disp(lasterr); + error('could not locate MEX file for %s', mexname); + cd(pwdir); + success = false; +end -% determine the projection onto the plane of the triangle -proj = (1-la-mu)*v1 + la*v2 + mu*v3; +if success + % execute the mex file that was juist created + funname = mfilename; + funhandle = str2func(funname); + [varargout{1:nargout}] = funhandle(varargin{:}); +end diff --git a/external/fieldtrip/private/routlm.mexmaci b/external/fieldtrip/private/routlm.mexmaci index 0d5e7a1..6224a3e 100755 Binary files a/external/fieldtrip/private/routlm.mexmaci and b/external/fieldtrip/private/routlm.mexmaci differ diff --git a/external/fieldtrip/private/routlm.mexw32 b/external/fieldtrip/private/routlm.mexw32 index 157b3c7..af0441e 100644 Binary files a/external/fieldtrip/private/routlm.mexw32 and b/external/fieldtrip/private/routlm.mexw32 differ diff --git a/external/fieldtrip/private/routlm.mexw64 b/external/fieldtrip/private/routlm.mexw64 index 66ef871..a8f011b 100644 Binary files a/external/fieldtrip/private/routlm.mexw64 and b/external/fieldtrip/private/routlm.mexw64 differ diff --git a/external/fieldtrip/private/rv.m b/external/fieldtrip/private/rv.m index 35f9b3e..21bceff 100644 --- a/external/fieldtrip/private/rv.m +++ b/external/fieldtrip/private/rv.m @@ -6,10 +6,23 @@ % Copyright (C) 1999, Robert Oostenveld % -% $Log: rv.m,v $ -% Revision 1.2 2003/03/11 14:45:37 roberto -% updated help and copyrights +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: rv.m 952 2010-04-21 18:29:51Z roboos $ retval = sum((d1-d2).^2) ./ sum(d1.^2); diff --git a/external/fieldtrip/private/savevar.m b/external/fieldtrip/private/savevar.m new file mode 100644 index 0000000..8bc4320 --- /dev/null +++ b/external/fieldtrip/private/savevar.m @@ -0,0 +1,12 @@ +function savevar(filename, varname, value) + +% LOADVAR is a helper function for cfg.inputfile + +% Copyright (C) 2010, Robert Oostenveld +% +% $Id: savevar.m 1083 2010-05-18 09:27:10Z roboos $ + +fprintf('writing ''%s'' to file ''%s''\n', varname, filename); + +eval(sprintf('%s = value;', varname)); +save(filename, varname); diff --git a/external/fieldtrip/private/scale.m b/external/fieldtrip/private/scale.m index 65e685f..d2b8202 100644 --- a/external/fieldtrip/private/scale.m +++ b/external/fieldtrip/private/scale.m @@ -6,8 +6,8 @@ % Use as % [H] = translate(S) % where -% S [sx, sy, sz] scaling along each of the axes -% H corresponding homogenous transformation matrix +% S [sx, sy, sz] scaling along each of the axes +% H corresponding homogenous transformation matrix % Copyright (C) 2000-2005, Robert Oostenveld % @@ -25,15 +25,23 @@ % along with this program; if not, write to the Free Software % Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -% $Log: scale.m,v $ -% Revision 1.2 2005/08/15 08:15:33 roboos -% reimplemented the rotate function, which contained an error (the error is in the AIR technical reference) -% changed all functions to be dependent on the rotate, translate and scale function -% all functions now behave consistenly, which also means that they are not compleetly backward compatible w.r.t. the order of the rotations +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.1 2004/05/19 09:57:07 roberto -% added GPL copyright statement, added CVS log item +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: scale.m 952 2010-04-21 18:29:51Z roboos $ H = [ S(1) 0 0 0 @@ -42,4 +50,4 @@ 0 0 0 1 ]; - \ No newline at end of file + diff --git a/external/fieldtrip/private/scalpcurrentdensity.m b/external/fieldtrip/private/scalpcurrentdensity.m deleted file mode 100644 index 04a7434..0000000 --- a/external/fieldtrip/private/scalpcurrentdensity.m +++ /dev/null @@ -1,306 +0,0 @@ -function [scd] = scalpcurrentdensity(cfg, data); - -% SCALPCURRENTDENSITY computes an estimate of the SCD using the -% second-order derivative (the surface Laplacian) of the EEG potential -% distribution -% -% Use as -% [data] = scalpcurrentdensity(cfg, data) -% or -% [timelock] = scalpcurrentdensity(cfg, timelock) -% where the input data is obtained from PREPROCESSING or from -% TIMELOCKANALYSIS. The output data has the same format as the input -% and can be used in combination with most other FieldTrip functions -% (e.g. FREQNALYSIS or TOPOPLOTER). -% -% The configuration can contain -% cfg.method = 'finite' for finite-difference method or -% 'spline' for spherical spline method -% 'hjorth' for Hjorth approximation method -% cfg.elecfile = string, file containing the electrode definition -% cfg.elec = structure with electrode definition -% cfg.conductivity = conductivity of the skin (default = 0.33 S/m) -% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') -% -% Note that the skin conductivity, electrode dimensions and the potential -% all have to be expressed in the same SI units, otherwise the units of -% the SCD values are not scaled correctly. The spatial distribution still -% will be correct. -% -% The 'finite' method implements -% TF Oostendorp, A van Oosterom; The surface Laplacian of the potential: -% theory and application. IEEE Trans Biomed Eng, 43(4): 394-405, 1996. -% G Huiskamp; Difference formulas for the surface Laplacian on a -% triangulated sphere. Journal of Computational Physics, 2(95): 477-496, -% 1991. -% -% The 'spline' method implements -% F. Perrin, J. Pernier, O. Bertrand, and J. F. Echallier. -% Spherical splines for scalp potential and curernt density mapping. -% Electroencephalogr Clin Neurophysiol, 72:184-187, 1989 -% including their corrections in -% F. Perrin, J. Pernier, O. Bertrand, and J. F. Echallier. -% Corrigenda: EEG 02274, Electroencephalography and Clinical -% Neurophysiology 76:565. -% -% The 'hjorth' method implements -% B. Hjort; An on-line transformation of EEG ccalp potentials into -% orthogonal source derivation. Electroencephalography and Clinical -% Neurophysiology 39:526-530, 1975. - -% Copyright (C) 2004-2006, Robert Oostenveld -% -% $Log: scalpcurrentdensity.m,v $ -% Revision 1.25 2008/11/12 19:26:17 roboos -% documented hjorth, added support for layout in constructing of hjorth -% -% Revision 1.24 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.23 2008/07/21 13:19:05 roboos -% implemented Hjorth filtering, using neighbourselection and apply_warp -% changed finite method to use apply_warp -% -% Revision 1.22 2008/05/06 14:23:32 sashae -% change in trial selection, cfg.trials can be a logical -% -% Revision 1.21 2008/04/29 14:35:20 roboos -% fixed bug in looping over trials, thanks to Manuel -% -% Revision 1.20 2008/03/05 10:46:36 roboos -% moved electrode reading functionality from read_fcdc_elec to read_sens, switched to the use of the new function -% -% Revision 1.19 2008/01/31 17:20:17 sashae -% added option for trial selection -% -% Revision 1.18 2007/05/30 07:19:27 roboos -% ensure that the input is not MEG data -% -% Revision 1.17 2007/05/02 15:59:13 roboos -% be more strict on the input and output data: It is now the task of -% the private/checkdata function to convert the input data to raw -% data (i.e. as if it were coming straight from preprocessing). -% Furthermore, the output data is NOT converted back any more to the -% input data, i.e. the output data is the same as what it would be -% on raw data as input, regardless of the actual input. -% -% Revision 1.16 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.15 2007/03/27 11:05:19 ingnie -% changed call to fixdimord in call to checkinput -% -% Revision 1.14 2006/09/07 12:31:00 roboos -% updated documentation -% -% Revision 1.13 2006/04/20 09:58:34 roboos -% updated documentation -% -% Revision 1.12 2006/02/23 10:28:16 roboos -% changed dimord strings for consistency, changed toi and foi into time and freq, added fixdimord where neccessary -% -% Revision 1.11 2005/08/05 08:51:14 roboos -% switched to use of read_fcdc_elec subfunction for reading electrodes -% switched to use of data2raw and raw2data subfunctions for converting between avg and raw -% -% Revision 1.10 2005/06/29 12:46:29 roboos -% the following changes were done on a large number of files at the same time, not all of them may apply to this specific file -% - added try-catch around the inclusion of input data configuration -% - moved cfg.version, cfg.previous and the assignment of the output cfg to the end -% - changed help comments around the configuration handling -% - some changes in whitespace -% -% Revision 1.9 2005/06/28 19:50:38 roboos -% minor change to solve problem when compiling to c-code, functionality is the same -% load(cfg.filename) gives compilation error, so first copy the string with the filename from the structure in a plain variable and then load(...) -% -% Revision 1.8 2004/05/05 13:55:20 roberto -% fixed bug that occured when average data was made with keeptrials=yes -% -% Revision 1.7 2004/04/13 16:31:09 roberto -% fixed bug in dbstack selection of function filename for Matlab 6.1 -% -% Revision 1.6 2004/04/13 14:25:24 roberto -% wrapped code-snippet around mfilename to make it compatible with Matlab 6.1 -% -% Revision 1.5 2004/03/29 15:10:18 roberto -% monor update to handling of average data -% -% Revision 1.4 2004/03/22 15:56:35 roberto -% restructured version information in output configuration -% -% Revision 1.3 2004/03/22 15:43:17 roberto -% attempt to fix CVS version -% -% Revision 1.2 2004/03/22 15:36:00 roberto -% added version information to cfg -% -% Revision 1.1 2004/03/22 15:35:08 roberto -% first version -% - -fieldtripdefs - -% check if the input data is valid for this function -data = checkdata(data, 'datatype', 'raw', 'feedback', 'yes', 'ismeg', 'no'); - -% set the defaults -if ~isfield(cfg, 'method'), cfg.method = 'spline'; end -if ~isfield(cfg, 'conductivity'), cfg.conductivity = 0.33; end % in S/m -if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end - -% select trials of interest -if ~strcmp(cfg.trials, 'all') - if islogical(cfg.trials), cfg.trials=find(cfg.trials); end - fprintf('selecting %d trials\n', length(cfg.trials)); - data.trial = data.trial(cfg.trials); - data.time = data.time(cfg.trials); - % update the trial definition (trl) - if isfield(data, 'cfg') % try to locate the trl in the nested configuration - trl = findcfg(data.cfg, 'trl'); - else - trl = []; - end - if isempty(trl) - % a trial definition is expected in each continuous data set - warning('could not locate the trial definition ''trl'' in the data structure'); - else - cfg.trlold=trl; - cfg.trl=trl(cfg.trials,:); - end -end - -% get the electrode positions -if isfield(cfg, 'elecfile') - fprintf('reading electrodes from file %s\n', cfg.elecfile); - elec = read_sens(cfg.elecfile); -elseif isfield(cfg, 'elec') - fprintf('using electrodes specified in the configuration\n'); - elec = cfg.elec; -elseif isfield(data, 'elec') - fprintf('using electrodes specified in the data\n'); - elec = data.elec; -elseif isfield(cfg, 'layout') - fprintf('using the 2-D layout to determine the neighbours\n'); - cfg.layout = prepare_layout(cfg); - cfg.neighbours = neighbourselection(cfg, data); - % create a dummy electrode structure, this is needed for channel selection - elec = []; - elec.label = cfg.layout.label; - elec.pnt = cfg.layout.pos; - elec.pnt(:,3) = 0; -else - error('electrode positions were not specified'); -end - -% remove all junk fields from the electrode array -tmp = elec; -elec = []; -elec.pnt = tmp.pnt; -elec.label = tmp.label; - -% find matching electrode positions and channels in the data -[dataindx, elecindx] = match_str(data.label, elec.label); -data.label = data.label(dataindx); -elec.label = elec.label(elecindx); -elec.pnt = elec.pnt(elecindx, :); -Ntrials = length(data.trial); -for trlop=1:Ntrials - data.trial{trlop} = data.trial{trlop}(dataindx,:); -end - -% compute SCD for each trial -if strcmp(cfg.method, 'spline') - for trlop=1:Ntrials - % do not compute intrepolation, but only one value at [0 0 1] - % this also gives L1, the laplacian of the original data in which we - % are interested here - fprintf('computing SCD for trial %d\n', trlop); - [V2, L2, L1] = splint(elec.pnt, data.trial{trlop}, [0 0 1]); - scd.trial{trlop} = L1; - end - -elseif strcmp(cfg.method, 'finite') - % the finite difference approach requires a triangulation - prj = elproj(elec.pnt); - tri = delaunay(prj(:,1), prj(:,2)); - % the new electrode montage only needs to be computed once for all trials - montage.tra = lapcal(elec.pnt, tri); - montage.labelorg = data.label; - montage.labelnew = data.label; - % apply the montage to the data, also update the electrode definition - scd = apply_montage(data, montage); - elec = apply_montage(elec, montage); - -elseif strcmp(cfg.method, 'hjorth') - % the Hjorth filter requires a specification of the neighbours - if ~isfield(cfg, 'neighbours') - tmpcfg = []; - tmpcfg.elec = elec; - cfg.neighbours = neighbourselection(tmpcfg, data); - end - % convert the neighbourhood structure into a montage - labelnew = {}; - labelorg = {}; - for i=1:length(cfg.neighbours) - labelnew = cat(2, labelnew, cfg.neighbours{i}.label); - labelorg = cat(2, labelorg, cfg.neighbours{i}.neighblabel(:)'); - end - labelorg = cat(2, labelnew, labelorg); - labelorg = unique(labelorg); - tra = zeros(length(labelnew), length(labelorg)); - for i=1:length(cfg.neighbours) - thischan = match_str(labelorg, cfg.neighbours{i}.label); - thisneighb = match_str(labelorg, cfg.neighbours{i}.neighblabel); - tra(i, thischan) = 1; - tra(i, thisneighb) = -1/length(thisneighb); - end - % combine it in a montage - montage.tra = tra; - montage.labelorg = labelorg; - montage.labelnew = labelnew; - % apply the montage to the data, also update the electrode definition - scd = apply_montage(data, montage); - elec = apply_montage(elec, montage); - -else - error('unknown method for SCD computation'); -end - -if strcmp(cfg.method, 'spline') || strcmp(cfg.method, 'finite') - % correct the units - warning('trying to correct the units, assuming uV and mm'); - for trlop=1:Ntrials - % The surface laplacian is proportional to potential divided by squared distance which means that, if - % - input potential is in uV, which is 10^6 too large - % - units of electrode positions are in mm, which is 10^3 too large - % these two cancel out against each other. Hence the computed laplacian - % is in SI units (MKS). - scd.trial{trlop} = cfg.conductivity * -1 * scd.trial{trlop}; - end - fprintf('output surface laplacian is in V/m^2'); -else - fprintf('output Hjorth filtered potential is in uV'); -end - -% collect the results -scd.elec = elec; -scd.time = data.time; -scd.label = data.label; -scd.fsample = data.fsample; - -% store the configuration of this function call, including that of the previous function call -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: scalpcurrentdensity.m,v 1.25 2008/11/12 19:26:17 roboos Exp $'; -% remember the configuration details of the input data -try, cfg.previous = data.cfg; end -% remember the exact configuration details in the output -scd.cfg = cfg; - diff --git a/external/fieldtrip/private/segmentvolume.m b/external/fieldtrip/private/segmentvolume.m deleted file mode 100644 index 05a7190..0000000 --- a/external/fieldtrip/private/segmentvolume.m +++ /dev/null @@ -1,22 +0,0 @@ -function [segment] = segmentvolume(cfg, mri) - -% VOLUMESEGMENT segments an anatomical MRI into gray matter, white -% matter, and CSF compartments. -% -% Warning: this function is deprecated, it has been renamed to VOLUMESEGMENT -% Warning: backward compatibility will be removed in the future - -% Copyright (C) 2005-2006, F.C. Donders Centre -% -% $Log: segmentvolume.m,v $ -% Revision 1.13 2007/01/09 09:52:07 roboos -% changed the warning a bit -% -% Revision 1.12 2006/03/14 08:09:22 roboos -% added copyrigth and cvs log statement -% - -warning('This function is deprecated, it has been renamed to VOLUMESEGMENT'); -warning('backward compatibility will be removed in the future'); - -[volume] = volumesegment(cfg, volume) diff --git a/external/fieldtrip/private/sel50p.m b/external/fieldtrip/private/sel50p.m new file mode 100644 index 0000000..714c453 --- /dev/null +++ b/external/fieldtrip/private/sel50p.m @@ -0,0 +1,52 @@ +function [grid] = sel50p(cfg, grid, sens); + +% This function will add the field "subspace" to the grid definition. +% +% The subspace projection corresponds to selecting 50% of the +% channels that are the closest to the dipole. + +% set the defaults +if ~isfield(cfg, 'feedback'), cfg.feedback = 'text'; end + +Ninside = length(grid.inside); +Nchans = size(grid.leadfield{grid.inside(1)}, 1); + +if isfield(sens, 'tra') + % there is a transformation matrix for magnetometers fo gradiometers + % weigh each magnetometer coil position with its absolute contribution to + % the field + tra = abs(sens.tra); + sumx = tra * sens.pnt(:,1); + sumy = tra * sens.pnt(:,2); + sumz = tra * sens.pnt(:,3); + pnt = [sumx./sum(tra,2) sumy./sum(tra,2) sumz./sum(tra,2)]; +else + pnt = sens.pnt; +end + +% make a selection matrix for all channels +e = sparse(eye(Nchans)); + +progress('init', cfg.feedback, 'computing channel selection'); +for dipindx=1:Ninside + % renumber the loop-index variable to make it easier to print the progress bar + i = grid.inside(dipindx); + + % compute the distance from this dipole to each sensor + dist = sqrt(sum((pnt-repmat(grid.pos(i,:), [Nchans 1])).^2, 2)); + + % define the channels of interest for this dipole + [dum, indx] = sort(dist); + sel = indx(1:round(Nchans/2)); + Nsel = length(sel); + progress(dipindx/Ninside, 'computing channel selection %d/%d, Nsel=%d\n', dipindx, Ninside, Nsel); + + % make a slelection matrix for the 50% nearest-by channels + grid.subspace{grid.inside(dipindx)} = e(sel,:); +end +progress('close'); + +% fill the positions outside the brain with NaNs +for dipindx=grid.outside(:)' + grid.subspace{dipindx} = nan; +end diff --git a/external/fieldtrip/private/select2d.m b/external/fieldtrip/private/select2d.m index fcbc49a..5f0db02 100644 --- a/external/fieldtrip/private/select2d.m +++ b/external/fieldtrip/private/select2d.m @@ -11,10 +11,23 @@ % Copyright (C) 2006, Robert Oostenveld % -% $Log: select2d.m,v $ -% Revision 1.1 2006/05/17 14:38:09 roboos -% new implementation +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: select2d.m 952 2010-04-21 18:29:51Z roboos $ k = waitforbuttonpress; point1 = get(gca,'CurrentPoint'); % button down detected diff --git a/external/fieldtrip/private/select_box.m b/external/fieldtrip/private/select_box.m deleted file mode 100644 index 460ceed..0000000 --- a/external/fieldtrip/private/select_box.m +++ /dev/null @@ -1,53 +0,0 @@ -function [x, y] = select_box(handle, eventdata, varargin) - -% SELECT_BOX helper function for selecting a rectangular region -% in the current figure using the mouse. -% -% Use as -% [x, y] = select_box(...) -% -% It returns a 2-element vector x and a 2-element vector y -% with the corners of the selected region. -% -% Optional input arguments should come in key-value pairs and can include -% 'multiple' true/false, make multiple selections by dragging, clicking -% in one will finalize the selection (default = false) - -% Copyright (C) 2006, Robert Oostenveld -% -% $Log: select_box.m,v $ -% Revision 1.6 2009/07/14 13:18:33 roboos -% updated channel selection, use select_range and two local helper functions, also support multiple selections -% -% Revision 1.5 2009/06/04 10:50:50 roboos -% changed handling of inputs -% -% Revision 1.4 2009/06/03 11:21:49 crimic -% bug fixes -% -% Revision 1.3 2009/05/29 15:56:08 roboos -% added input argument handling for 'multiple', the actual implementation does not support it yet -% -% Revision 1.2 2009/04/15 12:34:29 crimic -% added code of original select2d.m function -% -% Revision 1.1 2006/05/17 14:38:09 roboos -% new implementation - -% get the optional arguments -multiple = keyval('multiple', varargin); if isempty(multiple), multiple = false; end - -if multiple - error('not yet implemented'); -else - k = waitforbuttonpress; - point1 = get(gca,'CurrentPoint'); % button down detected - finalRect = rbbox; % return figure units - point2 = get(gca,'CurrentPoint'); % button up detected - point1 = point1(1,1:2); % extract x and y - point2 = point2(1,1:2); - x = sort([point1(1) point2(1)]); - y = sort([point1(2) point2(2)]); -end - - diff --git a/external/fieldtrip/private/select_channel.m b/external/fieldtrip/private/select_channel.m deleted file mode 100644 index 5ecbc18..0000000 --- a/external/fieldtrip/private/select_channel.m +++ /dev/null @@ -1,155 +0,0 @@ -function select_channel(handle, eventdata, varargin) - -% SELECT_CHANNEL is a helper function that can be used as callback function -% in a figure. It allows the user to select a channel. The channel labels -% are returned. -% -% Use as -% label = select_channel(h, eventdata, ...) -% The first two arguments are automatically passed by Matlab to any -% callback function. -% -% Additional options should be specified in key-value pairs and can be -% 'callback' = function handle to be executed after channels have been selected -% -% You can pass additional arguments to the callback function in a cell-array -% like {@function_handle,arg1,arg2} -% -% Example -% % create a figure -% lay = prepare_layout([]) -% plot_lay(lay) -% -% % add the required guidata -% info = guidata(gcf) -% info.x = lay.pos(:,1); -% info.y = lay.pos(:,2); -% info.label = lay.label -% guidata(gcf, info) -% -% % add this function as the callback to make a single selection -% set(gcf, 'WindowButtonDownFcn', {@select_channel, 'callback', @disp}) -% -% % or to make multiple selections -% set(gcf, 'WindowButtonDownFcn', {@select_channel, 'multiple', true, 'callback', @disp, 'event', 'WindowButtonDownFcn'}) -% set(gcf, 'WindowButtonUpFcn', {@select_channel, 'multiple', true, 'callback', @disp, 'event', 'WindowButtonDownFcn'}) -% set(gcf, 'WindowButtonMotionFcn', {@select_channel, 'multiple', true, 'callback', @disp, 'event', 'WindowButtonDownFcn'}) -% -% Subsequently you can click in the figure and you'll see that the disp -% function is executed as callback and that it displays the selected -% channels. - -% Copyright (C) 2009, Robert Oostenveld -% -% $Log: select_channel.m,v $ -% Revision 1.4 2009/10/16 09:18:48 jansch -% ensure column representation in select_channel_multiple to avoid crash when -% called from multiplotER -% -% Revision 1.3 2009/07/14 13:18:33 roboos -% updated channel selection, use select_range and two local helper functions, also support multiple selections -% -% Revision 1.2 2009/05/12 18:10:43 roboos -% added handling of follow-up callback function -% -% Revision 1.1 2009/05/12 12:49:33 roboos -% new implementation of helper function that can be used as callback in a figure -% - -% get optional input arguments -callback = keyval('callback', varargin); -multiple = keyval('multiple', varargin); if isempty(multiple), multiple = false; end - -% convert 'yes/no' string to boolean value -multiple = istrue(multiple); - -if multiple - % the selection is done using select_range, which will subsequently call select_channel_multiple - set(gcf, 'WindowButtonDownFcn', {@select_range, 'multiple', true, 'callback', {@select_channel_multiple, callback}, 'event', 'WindowButtonDownFcn'}); - set(gcf, 'WindowButtonUpFcn', {@select_range, 'multiple', true, 'callback', {@select_channel_multiple, callback}, 'event', 'WindowButtonUpFcn'}); - set(gcf, 'WindowButtonMotionFcn', {@select_range, 'multiple', true, 'callback', {@select_channel_multiple, callback}, 'event', 'WindowButtonMotionFcn'}); -else - % the selection is done using select_channel_single - pos = get(gca, 'CurrentPoint'); - pos = pos(1,1:2); - select_channel_single(pos, callback) -end % if multiple - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION to assist in the selection of a single channel -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function select_channel_single(pos, callback) - -info = guidata(gcf); -x = info.x; -y = info.y; -label = info.label; - -% compute a tolerance measure -distance = dist([x y]'); -distance = triu(distance, 1); -distance = distance(:); -distance = distance(distance>0); -distance = median(distance); -tolerance = 0.3*distance; - -% compute the distance between the clicked point and all channels -dx = x - pos(1); -dy = y - pos(2); -dd = sqrt(dx.^2 + dy.^2); -[d, i] = min(dd); -if d=range(i, 1) & x<=range(i, 2) & y>=range(i, 3) & y<=range(i, 4)); -end -label = label(select); - -% execute the original callback with the selected channels as input argument -if any(select) - if ~isempty(callback) - if isa(callback, 'cell') - % the callback specifies a function and additional arguments - funhandle = callback{1}; - funargs = callback(2:end); - feval(funhandle, label, funargs{:}); - else - % the callback only specifies a function - funhandle = callback; - feval(funhandle, label); - end - end -end diff --git a/external/fieldtrip/private/select_channel_list.m b/external/fieldtrip/private/select_channel_list.m index f24f285..c213bfa 100644 --- a/external/fieldtrip/private/select_channel_list.m +++ b/external/fieldtrip/private/select_channel_list.m @@ -7,20 +7,33 @@ % select = select_channel_list(label, initial, titlestr) % % with -% initial indices of channels that are initially selected -% label cell array with channel labels (strings) -% titlestr title for dialog (optional) +% initial indices of channels that are initially selected +% label cell array with channel labels (strings) +% titlestr title for dialog (optional) % and -% select indices of selected channels +% select indices of selected channels % % If the user presses cancel, the initial selection will be returned. % Copyright (C) 2003, Robert Oostenveld % -% $Log: select_channel_list.m,v $ -% Revision 1.1 2007/01/22 10:18:24 roboos -% this is a copy of select_multiple_dlg, fixed titlestr +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: select_channel_list.m 952 2010-04-21 18:29:51Z roboos $ if nargin<3 titlestr = 'Select'; @@ -30,7 +43,7 @@ pos(3:4) = [290 300]; dlg = dialog('Name', titlestr, 'Position', pos); -select = select(:)'; % ensure that it is a row array +select = select(:)'; % ensure that it is a row array userdata.label = label; userdata.select = select; userdata.unselect = setdiff(1:length(label), select); diff --git a/external/fieldtrip/private/select_circle.m b/external/fieldtrip/private/select_circle.m deleted file mode 100644 index e69de29..0000000 diff --git a/external/fieldtrip/private/select_contour.m b/external/fieldtrip/private/select_contour.m deleted file mode 100644 index e69de29..0000000 diff --git a/external/fieldtrip/private/select_point.m b/external/fieldtrip/private/select_point.m deleted file mode 100644 index d1ceaa3..0000000 --- a/external/fieldtrip/private/select_point.m +++ /dev/null @@ -1,113 +0,0 @@ -function [selected] = select_point(pos, varargin) - -% SELECT_POINT helper function for selecting a one or multiple points -% in the current figure using the mouse. -% -% Use as -% [selected] = select_point(pos, ...) -% -% It returns a list of the [x y] coordinates of the selected points. -% -% Optional input arguments should come in key-value pairs and can include -% 'multiple' true/false, make multiple selections, pressing "q" on the keyboard finalizes the selection (default = false) -% 'nearest' true/false (default = true) -% -% Example use -% pos = randn(10,2); -% figure -% plot(pos(:,1), pos(:,2), '.') -% select_point(pos) - -% $Log: select_point.m,v $ -% Revision 1.2 2009/06/30 11:46:15 roboos -% fixed docu -% -% Revision 1.1 2009/06/30 11:44:34 roboos -% renamed select_pointd into select_point for consistency with plot_topo -% -% Revision 1.7 2009/06/22 12:33:11 crimic -% minor change -% -% Revision 1.6 2009/06/16 08:17:40 crimic -% added check on input -% -% Revision 1.5 2009/06/15 15:46:45 roboos -% first implementation of point3d, multiple changes to point2d, still some work to be done to make them consistent -% -% Revision 1.4 2009/06/15 13:43:27 roboos -% reimplemented from scratch -% -% Revision 1.3 2009/06/04 10:51:09 roboos -% only whitespace -% -% Revision 1.2 2009/06/03 11:23:46 crimic -% first implementation -% - - -% get optional input arguments -nearest = keyval('nearest', varargin); if isempty(nearest), nearest = true; end -multiple = keyval('multiple', varargin); if isempty(multiple), multiple = false; end - -% ensure that it is boolean -nearest = istrue(nearest); -multiple = istrue(multiple); - -if multiple - fprintf('select multiple points by clicking in the figure, press "q" if you are done\n'); -end - -x = []; -y = []; -done = false; - -selected = zeros(0,3); - -% ensure that "q" is not the current character, which happens if you reuse the same figure -set(gcf, 'CurrentCharacter', 'x') - -while ~done - k = waitforbuttonpress; - point = get(gca,'CurrentPoint'); % button down detected - key = get(gcf,'CurrentCharacter'); % which key was pressed (if any)? - if strcmp(key, 'q') - % we are done with the clicking - done = true; - else - % add the current point - x(end+1) = point(1,1); - y(end+1) = point(1,2); - end - - if ~multiple - done = true; - end -end - -if nearest && ~isempty(pos) - % determine the points that are the nearest to the displayed points - selected = []; - - % compute the distance between the points to get an estimate of the tolerance - dp = dist(pos'); - dp = triu(dp, 1); - dp = dp(:); - dp = dp(dp>0); - % allow for some tolerance in the clicking - dp = median(dp); - tolerance = 0.3*dp; - - for i=1:length(x) - % compute the distance between the clicked position and all points - dx = pos(:,1) - x(i); - dy = pos(:,2) - y(i); - dd = sqrt(dx.^2 + dy.^2); - [d, i] = min(dd); - if d0); - % allow for some tolerance in the clicking - dp = median(dp); - tolerance = 0.3*dp; - - for i=1:length(x) - % compute the distance between the clicked position and all points - dx = pos(:,1) - x(i); - dy = pos(:,2) - y(i); - dd = sqrt(dx.^2 + dy.^2); - [d, i] = min(dd); - if d1 - warning('using the first patch object in the figure'); - h = h(1); -end - -selected = zeros(0,3); - -done = false; -while ~done - k = waitforbuttonpress; - [p v vi facev facei] = select3d(h); - key = get(gcf,'CurrentCharacter'); % which key was pressed (if any)? - - if strcmp(key, 'q') - % finished selecting points - done = true; - else - % a new point was selected - if nearest - selected(end+1,:) = v; - else - selected(end+1,:) = p; - end % if nearest - fprintf('selected point at [%f %f %f]\n', selected(end,1), selected(end,2), selected(end,3)); - end - - if ~multiple - done = true; - end -end - diff --git a/external/fieldtrip/private/select_range.m b/external/fieldtrip/private/select_range.m deleted file mode 100644 index f1e535a..0000000 --- a/external/fieldtrip/private/select_range.m +++ /dev/null @@ -1,239 +0,0 @@ -function select_range(handle, eventdata, varargin) - -% SELECT_RANGE is a helper function that can be used as callback function -% in a figure. It allows the user to select a horizontal or a vertical -% range, or one or multiple boxes. -% -% Example -% x = randn(10,1); -% y = randn(10,1); -% figure; plot(x, y, '.'); -% -% set(gcf, 'WindowButtonDownFcn', {@select_range, 'multiple', true, 'callback', @disp, 'event', 'WindowButtonDownFcn'}); -% set(gcf, 'WindowButtonUpFcn', {@select_range, 'multiple', true, 'callback', @disp, 'event', 'WindowButtonUpFcn'}); -% set(gcf, 'WindowButtonMotionFcn', {@select_range, 'multiple', true, 'callback', @disp, 'event', 'WindowButtonMotionFcn'}); -% -% set(gcf, 'WindowButtonDownFcn', {@select_range, 'multiple', false, 'xrange', false, 'yrange', false, 'callback', @disp, 'event', 'WindowButtonDownFcn'}); -% set(gcf, 'WindowButtonUpFcn', {@select_range, 'multiple', false, 'xrange', false, 'yrange', false, 'callback', @disp, 'event', 'WindowButtonUpFcn'}); -% set(gcf, 'WindowButtonMotionFcn', {@select_range, 'multiple', false, 'xrange', false, 'yrange', false, 'callback', @disp, 'event', 'WindowButtonMotionFcn'}); - -% Copyright (C) 2009, Robert Oostenveld -% -% $Log: select_range.m,v $ -% Revision 1.5 2009/08/04 11:56:55 roboos -% again a change in the handling user data -% added explicit option for clearing the user data in the figure -% -% Revision 1.4 2009/08/03 20:39:16 roboos -% reverted to revision 1.2 and changed the setappdata handling -% -% Revision 1.2 2009/07/30 19:10:25 ingnie -% deleted disp(callback) -% -% Revision 1.1 2009/07/14 13:17:41 roboos -% implemented new function, to be used as callback in interactive data selection -% - -% get the optional arguments -event = keyval('event', varargin); -callback = keyval('callback', varargin); -multiple = keyval('multiple', varargin); if isempty(multiple), multiple = false; end -xrange = keyval('xrange', varargin); if isempty(xrange), xrange = true; end -yrange = keyval('yrange', varargin); if isempty(yrange), yrange = true; end -clear = keyval('clear', varargin); if isempty(clear), clear = false; end - -% convert 'yes/no' string to boolean value -multiple = istrue(multiple); -xrange = istrue(xrange); -yrange = istrue(yrange); - -p = handle; -while ~isequal(p, 0) - handle = p; - p = get(handle, 'parent'); -end - -if ishandle(handle) - userData = getappdata(handle, 'select_range_m'); -else - userData = []; -end - -if isempty(userData) - userData.range = []; % this is a Nx4 matrix with the selection range - userData.box = []; % this is a Nx1 vector with the line handle -end - -p = get(gca, 'CurrentPoint'); -p = p(1,1:2); - -abc = axis; -xLim = abc(1:2); -yLim = abc(3:4); - -% limit cursor coordinates -if p(1)xLim(2), p(1)=xLim(2); end; -if p(2)yLim(2), p(2)=yLim(2); end; - -% determine whether the user is currently making a selection -selecting = numel(userData.range)>0 && any(isnan(userData.range(end,:))); -pointonly = ~xrange && ~yrange; - -if pointonly && multiple - warning('multiple selections are not possible for a point'); - multiple = false; -end - -switch event - case 'WindowButtonDownFcn' - if inSelection(p, userData.range) - % the user has clicked in one of the existing selections - evalCallback(callback, userData.range); - if clear - delete(userData.box(ishandle(userData.box))); - userData.range = []; - userData.box = []; - set(handle, 'Pointer', 'crosshair'); - end - - else - if ~multiple - % start with a new selection - delete(userData.box(ishandle(userData.box))); - userData.range = []; - userData.box = []; - end - - % add a new selection range - userData.range(end+1,1:4) = nan; - userData.range(end,1) = p(1); - userData.range(end,3) = p(2); - - % add a new selection box - xData = [nan nan nan nan nan]; - yData = [nan nan nan nan nan]; - userData.box(end+1) = line(xData, yData); - end - - case 'WindowButtonUpFcn' - if selecting - % select the other corner of the box - userData.range(end,2) = p(1); - userData.range(end,4) = p(2); - end - - if multiple && ~isempty(userData.range) && ~diff(userData.range(end,1:2)) && ~diff(userData.range(end,3:4)) - % start with a new selection - delete(userData.box(ishandle(userData.box))); - userData.range = []; - userData.box = []; - end - - if ~isempty(userData.range) - % ensure that the selection is sane - if diff(userData.range(end,1:2))<0 - userData.range(end,1:2) = userData.range(end,[2 1]); - end - if diff(userData.range(end,3:4))<0 - userData.range(end,3:4) = userData.range(end,[4 3]); - end - if pointonly - % only select a single point - userData.range(end,2) = userData.range(end,1); - userData.range(end,4) = userData.range(end,3); - elseif ~xrange - % only select along the y-axis - userData.range(end,1:2) = [-inf inf]; - elseif ~yrange - % only select along the x-axis - userData.range(end,3:4) = [-inf inf]; - end - end - - if pointonly && ~multiple - evalCallback(callback, userData.range); - if clear - delete(userData.box(ishandle(userData.box))); - userData.range = []; - userData.box = []; - set(handle, 'Pointer', 'crosshair'); - end - end - - case 'WindowButtonMotionFcn' - if selecting && ~pointonly - % update the selection box - if xrange - x1 = userData.range(end,1); - x2 = p(1); - else - x1 = xLim(1); - x2 = xLim(2); - end - if yrange - y1 = userData.range(end,3); - y2 = p(2); - else - y1 = yLim(1); - y2 = yLim(2); - end - - xData = [x1 x2 x2 x1 x1]; - yData = [y1 y1 y2 y2 y1]; - set(userData.box(end), 'xData', xData); - set(userData.box(end), 'yData', yData); - set(userData.box(end), 'Color', [0 0 0]); - set(userData.box(end), 'EraseMode', 'xor'); - set(userData.box(end), 'LineStyle', '--'); - set(userData.box(end), 'LineWidth', 1.5); - set(userData.box(end), 'Visible', 'on'); - - else - % update the cursor - if inSelection(p, userData.range) - set(handle, 'Pointer', 'hand'); - else - set(handle, 'Pointer', 'crosshair'); - end - end - - otherwise - error('unexpected event "%s"', event); - -end % switch event - -% put the modified selections back into the figure -if ishandle(handle) - setappdata(handle, 'select_range_m', userData); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function retval = inSelection(p, range) -if isempty(range) - retval = false; -else - retval = (p(1)>=range(:,1) & p(1)<=range(:,2) & p(2)>=range(:,3) & p(2)<=range(:,4)); - retval = any(retval); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function evalCallback(callback, val) -if ~isempty(callback) - if isa(callback, 'cell') - % the callback specifies a function and additional arguments - funhandle = callback{1}; - funargs = callback(2:end); - feval(funhandle, val, funargs{:}); - else - % the callback only specifies a function - funhandle = callback; - feval(funhandle, val); - end -end - diff --git a/external/fieldtrip/private/selectdata.m b/external/fieldtrip/private/selectdata.m deleted file mode 100644 index cbf56ec..0000000 --- a/external/fieldtrip/private/selectdata.m +++ /dev/null @@ -1,437 +0,0 @@ -function [data] = selectdata(varargin) - -% this function serves to concatenate the input data-structures along the -% compatible dimensions and thus is a more general implementation of -% appenddata, which only raw data. Moreover, it can be used to equate the -% data of different conditions to match e.g. in channels time-axis etc -% Moreover, it can be used as a generalization to ...average with 'keepindividual' -% -% Finally, this function serves to subselect regions-of-interest from the input data, -% either or not averaging across the specified dimensions. -% -% Supported input data: -% freq -% timelock -% source (not yet) -% volume (not yet) -% -% supported options: -% foilim -% toilim -% roi -% channel (FIXME this is also done by preprocessing?) -% avgoverchan -% avgoverfreq -% avgovertime -% avgoverroi -% avgoverrpt - -% Copyright (C) 2009, Jan-Mathijs Schoffelen -% -% $Log: selectdata.m,v $ -% Revision 1.13 2009/10/17 18:06:43 jansch -% built-in support to compute jackknife samples -% -% Revision 1.12 2009/10/17 17:50:25 jansch -% allowed conversion back to raw datatype -% -% Revision 1.11 2009/10/01 12:14:05 jansch -% some changes -% -% Revision 1.10 2009/08/18 09:55:46 jansch -% included possibility to concatenate over grid positions, allowing for cutting -% the dipole grid and glueing it together later on -% -% Revision 1.9 2009/08/17 08:41:19 jansch -% multiple changes -% -% Revision 1.8 2009/07/15 12:11:57 jansch -% fixed small bug -% -% Revision 1.7 2009/07/06 09:41:18 jansch -% multiple changes. allowing for selection of rpt in frequency data when input -% data has rpttap. allowing for grandaveraging functionality in the case of -% multiple inputs with the same dimensionalities. this is equivalent to the -% XXXgrandaverage functions with keepindividual = 'yes'. -% -% Revision 1.6 2009/04/14 18:29:32 roboos -% deleted the subfunction istrue, since it now is a seperate function -% -% Revision 1.5 2009/03/18 19:49:54 roboos -% use the smart xxxdim functions -% -% Revision 1.4 2009/01/26 20:53:11 roboos -% ensure that some options are true|false -% changes some whitespace -% -% Revision 1.3 2009/01/12 17:05:58 roboos -% fixed some whitespace -% - -% check the input data and options -isdata = find(cellfun(@isstruct,varargin)); -keyvals = setdiff(1:length(varargin),isdata); - -data = varargin(isdata); -kvp = varargin(keyvals); -dtype = cell(1,length(data)); -dimord = cell(1,length(data)); - -for k = 1:length(data) - data{k} = checkdata(data{k}, 'datatype', {'freq' 'timelock' 'source', 'volume', 'freqmvar', 'raw'}); - [dtype{k}, dimord{k}] = datatype(data{k}); - if strcmp(dtype{k}, 'raw'), - %convert to timelock and keep track of this - israw = 1; - data{k} = checkdata(data{k}, 'datatype', 'timelock'); - [dtype{k}, dimord{k}] = datatype(data{k}); - else - israw = 0; - end -end - -if any(~strmatch(dtype{1},dtype)) - error('different types of input data is not supported'); -end - -% check consistency of input data -if any(~strmatch(dimord{1},dimord)) - error('a different dimord in the input data is not supported'); -end - -isfreq = datatype(data{1},'freq'); -istlck = datatype(data{1},'timelock'); -issource = datatype(data{1},'source'); -isvolume = datatype(data{1},'volume'); -isfreqmvar = datatype(data{1},'freqmvar'); - -selchan = keyval('channel', kvp); selectchan = ~isempty(selchan); -selfoi = keyval('foilim', kvp); selectfoi = ~isempty(selfoi); -seltoi = keyval('toilim', kvp); selecttoi = ~isempty(seltoi); -selroi = keyval('roi', kvp); selectroi = ~isempty(selroi); -selrpt = keyval('rpt', kvp); selectrpt = ~isempty(selrpt); -param = keyval('param', kvp); if isempty(param), param = 'all'; end - -avgoverchan = keyval('avgoverchan', kvp); if isempty(avgoverchan), avgoverchan = false; end -avgoverfreq = keyval('avgoverfreq', kvp); if isempty(avgoverfreq), avgoverfreq = false; end -avgovertime = keyval('avgovertime', kvp); if isempty(avgovertime), avgovertime = false; end -avgoverroi = keyval('avgoverroi', kvp); if isempty(avgoverroi), avgoverroi = false; end -avgoverrpt = keyval('avgoverrpt', kvp); if isempty(avgoverrpt), avgoverrpt = false; end -dojack = keyval('jackknife', kvp); if isempty(dojack), dojack = false; end - -% create anonymous function and apply it to the boolean input arguments -istrue = @(x)(ischar(x) && (strcmpi(x, 'yes') || strcmpi(x, 'true')) || (~isempty(x) && numel(x)==1 && x==1)); - -% ensure that these are boolean arguments, optionally convert from "yes"/"no" to true/false -avgoverchan = istrue(avgoverchan); -avgoverfreq = istrue(avgoverfreq); -avgovertime = istrue(avgovertime); -avgoverroi = istrue(avgoverroi); -avgoverrpt = istrue(avgoverrpt); -dojack = istrue(dojack); - -if dojack && avgoverrpt, - error('it is not possible to do both a jackknife and to average across replicates'); -end - -if length(data)>1 && selectrpt, - error('multiple data structures as input is not supported in combination with subselection of trials'); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% concatenate the data -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -if length(data)>1, - % determine the way to concatenate - - if issource || isvolume, - param = parameterselection(param, data{1}); % FIXME check consistency across input data of presence of specific parameters - else - param = {param}; - end - - dimtok = tokenize(dimord{1}, '_'); - dimtok(strmatch('chan', dimtok)) = {'label'}; % data.chan does not exist - - dimmat = zeros(length(dimtok), length(data)); - dimmat(:,1) = 1; - for k = 1:length(dimtok) - if isempty(strfind(dimtok{k},'rpt')), - dimdat = getfield(data{1}, dimtok{k}); - else - % dimtok is 'rpt' or 'rpttap' - dimdat = size(getsubfield(data{1}, param{1}),1); - end - for m = 2:length(data) - if isempty(strfind(dimtok{k},'rpt')), - dimdat2 = getfield(data{m},dimtok{k}); - else - % dimtok is 'rpt' or 'rpttap' - dimdat2 = size(getsubfield(data{m}, param{1}),1); - end - try, dimmat(k,m) = all(dimdat(:)==dimdat2(:)); catch end; - try, dimmat(k,m) = all(cellfun(@isequal,dimdat,dimdat2)); catch end; - end - end - catdim = find(sum(dimmat,2)1, - error('ambiguous dimensions for concatenation'); - elseif isempty(catdim) && isempty(strmatch('rpt',dimtok)) && isempty(strmatch('rpttap',dimtok)), - %treat as individual observations: prepend a first dimension 'rpt' - %(so this part should be able to cover the functionality of ...grandaverage) - catdim = 0; - elseif isempty(catdim) && (~isempty(strmatch('rpt',dimtok)) || ~isempty(strmatch('rpttap',dimtok))) - %append observations - catdim = 1; - elseif isempty(catdim) - error('don''t know how to concatenate the data'); - end - - % concatenate the data - for k = 1:length(param) - tmp = cell(1,length(data)); - for m = 1:length(tmp) - tmp{m} = getsubfield(data{m},param{k}); - end - if catdim==0, - ndim = length(size(tmp{1})); - data{1} = setsubfield(data{1}, param{k}, permute(cat(ndim+1,tmp{:}),[ndim+1 1:ndim])); - else - data{1} = setsubfield(data{1}, param{k}, cat(catdim,tmp{:})); - end - end - - if catdim==0, - %a dimension has been prepended - dimtok = ['rpt' dimtok]; - catdim = 1; - dimord{1} = ['rpt_',dimord{1}]; - if issubfield(data{1}, 'dim'), - dim = [length(data) data{1}.dim]; - end - else - if issubfield(data{1}, 'dim'), - dim = data{1}.dim; - end - end - - % concatenate the relevant descriptive fields in the data-structure - if ~strcmp(dimtok{catdim},'rpt') && ~strcmp(dimtok{catdim},'rpttap'), - for k = 1:length(data) - if k==1, - tmp = getsubfield(data{k}, dimtok{catdim}); - if strcmp(dimtok{catdim},'pos') && isfield(data{k},'inside'), - tmpinside = getfield(data{k}, 'inside'); - tmpoutside = getfield(data{k}, 'outside'); - tmpnvox = numel(tmpinside)+numel(tmpoutside); - end - else - if strcmp(dimtok{catdim},'pos'), - tmp = [tmp; getsubfield(data{k}, dimtok{catdim})]; sortflag = 0; - - %FIXME make this robust, now inside as vector is assumed - if exist('tmpinside', 'var') - tmpx = getfield(data{k}, 'inside'); - tmpx2 = getfield(data{k}, 'outside'); - tmpnvox = numel(tmpinside)+numel(tmpoutside); - tmpinside = [tmpinside(:)' tmpnvox(end)+tmpx(:)']; - tmpoutside = [tmpoutside(:)' tmpnvox(end)+tmpx2(:)']; - end - else - tmp = [tmp getsubfield(data{k}, dimtok{catdim})]; sortflag = 1; - end - end - end - data{1} = setsubfield(data{1}, dimtok{catdim}, tmp); - if exist('tmpinside', 'var') - data{1} = setfield(data{1}, 'inside', tmpinside); - data{1} = setfield(data{1}, 'outside', tmpoutside); - end - %FIXME think about this - tryfields = {'dof'}; - else - % no such field as {'label','time','freq','pos'} has to be concatenated - sortflag = 0; - tryfields = {'cumsumcnt','cumtapcnt'}; - end - - % concatenate the relevant descriptive fields in the data-structure (continued) - for k = 1:length(tryfields) - try, - for m = 1:length(data) - if m==1, - tmpfield = getfield(data{m}, tryfields{k}); - else - tmpfield = [tmpfield; getfield(data{m}, tryfields{k})]; - end - end - data{1} = setfield(data{1}, tryfields{k}, tmpfield); - catch - end - end - - % FIXME this is ugly: solve it - %if issource || isvolume, - % data{1}.dim(catdim) = max(size(tmp)); - %end - - % sort concatenated data FIXME this is also ugly and depends on tmp - if sortflag && ~iscell(tmp), - [srt, ind] = sort(tmp, 2); - data{1} = setsubfield(data{1}, dimtok{catdim}, tmp(ind)); - for k = 1:length(param) - tmp = getsubfield(data{1}, param{k}); - tmp = permute(tmp, [catdim setdiff(1:length(size(tmp)), catdim)]); - tmp = ipermute(tmp(ind,:,:,:,:), [catdim setdiff(1:length(size(tmp)), catdim)]); - data{1} = setsubfield(data{1}, param{k}, tmp); - end - elseif exist('tmp', 'var') && iscell(tmp) - %in this case (ugly!) tmp is probably a cell-array containing functional data - end - - % remove unspecified parameters - rmparam = setdiff(parameterselection('all',data{1}),[param 'pos' 'inside' 'outside']); - for k = 1:length(rmparam) - data{1} = rmsubfield(data{1}, rmparam{k}); - end - - % keep the first structure only - data = data{1}; - dimord = dimord{1}; - data.dimord = dimord; - if isfield(data, 'dim'), - %data.dim = dim; - data.dim = size(data.(param{1})); - end - -else - % nothing to do - data = data{1}; - dimord = dimord{1}; -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% from here on the data is concatenated -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% determine the subselection in the data -if selectrpt, - dimtok = tokenize(data.dimord, '_'); - if strcmp(dimtok{1}, 'rpttap'), - %account for the tapers - sumtapcnt = [0;cumsum(data.cumtapcnt(:))]; - begtapcnt = sumtapcnt(1:end-1)+1; - endtapcnt = sumtapcnt(2:end); - begtapcnt = begtapcnt(selrpt); - endtapcnt = endtapcnt(selrpt); - tapers = zeros(1,sumtapcnt(end)); - for k = 1:length(begtapcnt) - tapers(begtapcnt(k):endtapcnt(k)) = 1; - end - selrpt = find(tapers); - else - % do nothing - end -end - -if selectchan, - selchan = match_str(data.label, channelselection(selchan, data.label)); -end - -if selectfoi, - if length(selfoi)==1, selfoi(2) = selfoi; end; - if length(selfoi)==2, - %treat selfoi as lower limit and upper limit - selfoi = nearest(data.freq, selfoi(1)):nearest(data.freq, selfoi(2)); - else - %treat selfoi as a list of frequencies - for k=1:length(selfoi) - tmpfoi(k) = nearest(data.freq, selfoi(k)); - end - selfoi = tmpfoi; - end -end - -if selecttoi, - if length(seltoi)==1, seltoi(2) = seltoi; end; - seltoi = nearest(data.time, seltoi(1)):nearest(data.time, seltoi(2)); -end - -if selectroi, - error('not yet implemented'); -end - -if isfreq, - if isfield(data, 'labelcmb'), - %there is a crsspctrm field, this will only be selectdimmed - %if we apply a trick - tmpdata = data; - tmpdata.label = data.labelcmb; - if selectrpt, tmpdata = seloverdim(tmpdata, 'rpt', selrpt); end - if selectchan, tmpdata = seloverdim(tmpdata, 'chan', selchan); end - if selectfoi, tmpdata = seloverdim(tmpdata, 'freq', selfoi); end - if selecttoi, tmpdata = seloverdim(tmpdata, 'time', seltoi); end - % average over dimensions - if avgoverrpt, tmpdata = avgoverdim(tmpdata, 'rpt'); end - if avgoverfreq, tmpdata = avgoverdim(tmpdata, 'freq'); end - if avgovertime, tmpdata = avgoverdim(tmpdata, 'time'); end - if dojack, tmpdata = leaveoneout(tmpdata); end - crsspctrm = tmpdata.crsspctrm; clear tmpdata; - else - crsspctrm = []; - end - % make the subselection - if selectrpt, data = seloverdim(data, 'rpt', selrpt); end - if selectchan, data = seloverdim(data, 'chan', selchan); end - if selectfoi, data = seloverdim(data, 'freq', selfoi); end - if selecttoi, data = seloverdim(data, 'time', seltoi); end - % average over dimensions - if avgoverrpt, data = avgoverdim(data, 'rpt'); end - if avgoverchan, data = avgoverdim(data, 'chan'); end - if avgoverfreq, data = avgoverdim(data, 'freq'); end - if avgovertime, data = avgoverdim(data, 'time'); end - if dojack, data = leaveoneout(data); end - if ~isempty(crsspctrm), data.crsspctrm = crsspctrm; end - -elseif istlck, - % make the subselection - if selectrpt, data = seloverdim(data, 'rpt', selrpt); end - if selectchan, data = seloverdim(data, 'chan', selchan); end - if selectfoi, data = seloverdim(data, 'freq', selfoi); end - if selecttoi, data = seloverdim(data, 'time', seltoi); end - % average over dimensions - if avgoverrpt, data = avgoverdim(data, 'rpt'); end - if avgoverchan, data = avgoverdim(data, 'chan'); end - if avgoverfreq, data = avgoverdim(data, 'freq'); end - if avgovertime, data = avgoverdim(data, 'time'); end - if dojack, data = leaveoneout(data); end - -elseif issource, - %FIXME fill in everything - if selectrpt, data = seloverdim(data, 'rpt', selrpt); end - if selectfoi, data = seloverdim(data, 'freq', selfoi); end - if avgoverrpt, data = avgoverdim(data, 'rpt'); end - if avgoverfreq, data = avgoverdim(data, 'freq'); end - -elseif isvolume, - error('this is not yet implemented'); -elseif isfreqmvar, - % make the subselection - if selectrpt, data = seloverdim(data, 'rpt', selrpt); end - if selectchan, data = seloverdim(data, 'chan', selchan); end - if selectfoi, data = seloverdim(data, 'freq', selfoi); end - if selecttoi, data = seloverdim(data, 'time', seltoi); end - % average over dimensions - if avgoverrpt, data = avgoverdim(data, 'rpt'); end - if avgoverchan, data = avgoverdim(data, 'chan'); end - if avgoverfreq, data = avgoverdim(data, 'freq'); end - if avgovertime, data = avgoverdim(data, 'time'); end - if dojack, data = leaveoneout(data); end -end - -%convert back to raw -if israw - data = checkdata(data, 'datatype', 'raw'); -end diff --git a/external/fieldtrip/private/senslabel.m b/external/fieldtrip/private/senslabel.m deleted file mode 100644 index 45c59a5..0000000 --- a/external/fieldtrip/private/senslabel.m +++ /dev/null @@ -1,2018 +0,0 @@ -function label = senslabel(type) - -% SENLABEL returns a list of sensor labels given the MEEG system type -% -% Use as -% label = senslabel(type) -% -% The input type can be any of the following -% 'biosemi64' -% 'biosemi128' -% 'biosemi256' -% 'bti148' -% 'bti148_planar' -% 'bti248' -% 'bti248_planar' -% 'btiref' -% 'ctf151' -% 'ctf151_planar' -% 'ctf275' -% 'ctf275_planar' -% 'ctfheadloc' -% 'ctfref' -% 'eeg1005' -% 'eeg1010' -% 'eeg1020' -% 'egi128' -% 'egi256' -% 'egi32' -% 'egi64' -% 'ext1020' -% 'neuromag122' -% 'neuromag122alt' -% 'neuromag306' -% 'neuromag306alt' -% 'itab153' -% 'itab153_planar' -% -% See also SENSTYPE, CHANNELSELECTION - -% FIXME one channel is missing for ctf275 - -% Copyright (C) 2007-2008, Robert Oostenveld -% Copyright (C) 2008, Vladimir Litvak -% -% $Log: senslabel.m,v $ -% Revision 1.6 2009/10/16 12:27:53 roboos -% some small changes pertaining to the itab/chieti format -% -% Revision 1.4 2009/07/29 07:07:59 roboos -% use caching of input and output arguments to speed up the handling of multiple calls with the same input argument -% -% Revision 1.3 2009/06/19 16:51:50 vlalit -% Added biosemi64 system of Diane Whitmer, I don't know how generic it is. -% -% Revision 1.2 2009/05/07 13:34:09 roboos -% added ctf64 -% -% Revision 1.1 2009/01/21 10:32:38 roboos -% moved from forwinv/* and forwinv/mex/* directory to forwinv/private/* to make the CVS layout consistent with the release version -% -% Revision 1.4 2008/09/17 19:35:07 roboos -% ensure that it returns column array -% -% Revision 1.3 2008/09/10 09:12:11 roboos -% added alternative definition of channel names without a space in the label for neuromag 122 and 306 -% -% Revision 1.2 2008/09/10 08:33:36 roboos -% speeded up with factor 5 by performing an initial check on the desired type and subsequently only defining the related variables -% -% Revision 1.1 2008/09/10 07:53:27 roboos -% moved definition of channel label sets to seperate function -% - -% these are for remembering the type on subsequent calls with the same input arguments -persistent previous_argin previous_argout - -if nargin<1 - % ensure that all input arguments are defined - type = []; -end - -current_argin = {type}; -if isequal(current_argin, previous_argin) - % don't do the type detection again, but return the previous values from cache - label = previous_argout{1}; - return -end - -% prevent defining all possible labels if not needed -isbiosemi = ~isempty(regexp(type, '^biosemi', 'once')); -isbti = ~isempty(regexp(type, '^bti', 'once')); -isctf = ~isempty(regexp(type, '^ctf', 'once')); -iseeg = ~isempty(regexp(type, '^eeg', 'once')); -isext = ~isempty(regexp(type, '^ext', 'once')); -isegi = ~isempty(regexp(type, '^egi', 'once')); -isneuromag = ~isempty(regexp(type, '^neuromag', 'once')); -isitab = ~isempty(regexp(type, '^itab', 'once')); - -if isbti - btiref = { - 'MRxA' - 'MRyA' - 'MRzA' - 'MLxA' - 'MLyA' - 'MLzA' - 'MCxA' - 'MCyA' - 'MCzA' - 'MRxaA' - 'MRyaA' - 'MRzaA' - 'MLxaA' - 'MLyaA' - 'MLzaA' - 'MCxaA' - 'MCyaA' - 'MCzaA' - 'GxxA' - 'GyxA' - 'GzxA' - 'GyyA' - 'GzyA' - }; - - bti148 = cell(148,1); - for i=1:148 - bti148{i,1} = sprintf('A%d', i); - end - - bti148_planar = cell(148,1); - for i=1:148 - bti148_planar{i,1} = sprintf('A%d_dH', i); - bti148_planar{i,2} = sprintf('A%d_dV', i); - end - - bti248 = cell(248,1); - for i=1:248 - bti248{i,1} = sprintf('A%d', i); - end - - bti248_planar = cell(248,2); - for i=1:248 - bti248_planar{i,1} = sprintf('A%d_dH', i); - bti248_planar{i,2} = sprintf('A%d_dV', i); - end -end % if isbti - -if isctf - ctfref = { - 'BG1' - 'BG2' - 'BG3' - 'BP1' - 'BP2' - 'BP3' - 'BR1' - 'BR2' - 'BR3' - 'G11' - 'G12' - 'G13' - 'G22' - 'G23' - 'P11' - 'P12' - 'P13' - 'P22' - 'P23' - 'Q11' - 'Q12' - 'Q13' - 'Q22' - 'Q23' - 'R11' - 'R12' - 'R13' - 'R22' - 'R23' - }; - - ctfheadloc = { - 'HLC0011' - 'HLC0012' - 'HLC0013' - 'HLC0021' - 'HLC0022' - 'HLC0023' - 'HLC0031' - 'HLC0032' - 'HLC0033' - 'HLC0018' - 'HLC0028' - 'HLC0038' - 'HLC0014' - 'HLC0015' - 'HLC0016' - 'HLC0017' - 'HLC0024' - 'HLC0025' - 'HLC0026' - 'HLC0027' - 'HLC0034' - 'HLC0035' - 'HLC0036' - 'HLC0037' - }; - - ctf64 = { - 'SL11' - 'SL12' - 'SL13' - 'SL14' - 'SL15' - 'SL16' - 'SL17' - 'SL18' - 'SL19' - 'SL21' - 'SL22' - 'SL23' - 'SL24' - 'SL25' - 'SL26' - 'SL27' - 'SL28' - 'SL29' - 'SL31' - 'SL32' - 'SL33' - 'SL34' - 'SL35' - 'SL41' - 'SL42' - 'SL43' - 'SL44' - 'SL45' - 'SL46' - 'SL47' - 'SL51' - 'SL52' - 'SR11' - 'SR12' - 'SR13' - 'SR14' - 'SR15' - 'SR16' - 'SR17' - 'SR18' - 'SR19' - 'SR21' - 'SR22' - 'SR23' - 'SR24' - 'SR25' - 'SR26' - 'SR27' - 'SR28' - 'SR29' - 'SR31' - 'SR32' - 'SR33' - 'SR34' - 'SR35' - 'SR41' - 'SR42' - 'SR43' - 'SR44' - 'SR45' - 'SR46' - 'SR47' - 'SR51' - 'SR52' - }; - - ctf151 = { - 'MLC11' - 'MLC12' - 'MLC13' - 'MLC14' - 'MLC15' - 'MLC21' - 'MLC22' - 'MLC23' - 'MLC24' - 'MLC31' - 'MLC32' - 'MLC33' - 'MLC41' - 'MLC42' - 'MLC43' - 'MLF11' - 'MLF12' - 'MLF21' - 'MLF22' - 'MLF23' - 'MLF31' - 'MLF32' - 'MLF33' - 'MLF34' - 'MLF41' - 'MLF42' - 'MLF43' - 'MLF44' - 'MLF45' - 'MLF51' - 'MLF52' - 'MLO11' - 'MLO12' - 'MLO21' - 'MLO22' - 'MLO31' - 'MLO32' - 'MLO33' - 'MLO41' - 'MLO42' - 'MLO43' - 'MLP11' - 'MLP12' - 'MLP13' - 'MLP21' - 'MLP22' - 'MLP31' - 'MLP32' - 'MLP33' - 'MLP34' - 'MLT11' - 'MLT12' - 'MLT13' - 'MLT14' - 'MLT15' - 'MLT16' - 'MLT21' - 'MLT22' - 'MLT23' - 'MLT24' - 'MLT25' - 'MLT26' - 'MLT31' - 'MLT32' - 'MLT33' - 'MLT34' - 'MLT35' - 'MLT41' - 'MLT42' - 'MLT43' - 'MLT44' - 'MRC11' - 'MRC12' - 'MRC13' - 'MRC14' - 'MRC15' - 'MRC21' - 'MRC22' - 'MRC23' - 'MRC24' - 'MRC31' - 'MRC32' - 'MRC33' - 'MRC41' - 'MRC42' - 'MRC43' - 'MRF11' - 'MRF12' - 'MRF21' - 'MRF22' - 'MRF23' - 'MRF31' - 'MRF32' - 'MRF33' - 'MRF34' - 'MRF41' - 'MRF42' - 'MRF43' - 'MRF44' - 'MRF45' - 'MRF51' - 'MRF52' - 'MRO11' - 'MRO12' - 'MRO21' - 'MRO22' - 'MRO31' - 'MRO32' - 'MRO33' - 'MRO41' - 'MRO42' - 'MRO43' - 'MRP11' - 'MRP12' - 'MRP13' - 'MRP21' - 'MRP22' - 'MRP31' - 'MRP32' - 'MRP33' - 'MRP34' - 'MRT11' - 'MRT12' - 'MRT13' - 'MRT14' - 'MRT15' - 'MRT16' - 'MRT21' - 'MRT22' - 'MRT23' - 'MRT24' - 'MRT25' - 'MRT26' - 'MRT31' - 'MRT32' - 'MRT33' - 'MRT34' - 'MRT35' - 'MRT41' - 'MRT42' - 'MRT43' - 'MRT44' - 'MZC01' - 'MZC02' - 'MZF01' - 'MZF02' - 'MZF03' - 'MZO01' - 'MZO02' - 'MZP01' - 'MZP02' - }; - - ctf151_planar = cell(151, 2); - for i=1:151 - ctf151_planar{i,1} = sprintf('%s_dH', ctf151{i}); - ctf151_planar{i,2} = sprintf('%s_dV', ctf151{i}); - end - - ctf275 = { - 'MLC11' - 'MLC12' - 'MLC13' - 'MLC14' - 'MLC15' - 'MLC16' - 'MLC17' - 'MLC21' - 'MLC22' - 'MLC23' - 'MLC24' - 'MLC25' - 'MLC31' - 'MLC32' - 'MLC41' - 'MLC42' - 'MLC51' - 'MLC52' - 'MLC53' - 'MLC54' - 'MLC55' - 'MLC61' - 'MLC62' - 'MLC63' - 'MLF11' - 'MLF12' - 'MLF13' - 'MLF14' - 'MLF21' - 'MLF22' - 'MLF23' - 'MLF24' - 'MLF25' - 'MLF31' - 'MLF32' - 'MLF33' - 'MLF34' - 'MLF35' - 'MLF41' - 'MLF42' - 'MLF43' - 'MLF44' - 'MLF45' - 'MLF46' - 'MLF51' - 'MLF52' - 'MLF53' - 'MLF54' - 'MLF55' - 'MLF56' - 'MLF61' - 'MLF62' - 'MLF63' - 'MLF64' - 'MLF65' - 'MLF66' - 'MLF67' - 'MLO11' - 'MLO12' - 'MLO13' - 'MLO14' - 'MLO21' - 'MLO22' - 'MLO23' - 'MLO24' - 'MLO31' - 'MLO32' - 'MLO33' - 'MLO34' - 'MLO41' - 'MLO42' - 'MLO43' - 'MLO44' - 'MLO51' - 'MLO52' - 'MLO53' - 'MLP11' - 'MLP12' - 'MLP21' - 'MLP22' - 'MLP23' - 'MLP31' - 'MLP32' - 'MLP33' - 'MLP34' - 'MLP35' - 'MLP41' - 'MLP42' - 'MLP43' - 'MLP44' - 'MLP45' - 'MLP51' - 'MLP52' - 'MLP53' - 'MLP54' - 'MLP55' - 'MLP56' - 'MLP57' - 'MLT11' - 'MLT12' - 'MLT13' - 'MLT14' - 'MLT15' - 'MLT16' - 'MLT21' - 'MLT22' - 'MLT23' - 'MLT24' - 'MLT25' - 'MLT26' - 'MLT27' - 'MLT31' - 'MLT32' - 'MLT33' - 'MLT34' - 'MLT35' - 'MLT36' - 'MLT37' - 'MLT41' - 'MLT42' - 'MLT43' - 'MLT44' - 'MLT45' - 'MLT46' - 'MLT47' - 'MLT51' - 'MLT52' - 'MLT53' - 'MLT54' - 'MLT55' - 'MLT56' - 'MLT57' - 'MRC11' - 'MRC12' - 'MRC13' - 'MRC14' - 'MRC15' - 'MRC16' - 'MRC17' - 'MRC21' - 'MRC22' - 'MRC23' - 'MRC24' - 'MRC25' - 'MRC31' - 'MRC32' - 'MRC41' - 'MRC42' - 'MRC51' - 'MRC52' - 'MRC53' - 'MRC54' - 'MRC55' - 'MRC61' - 'MRC62' - 'MRC63' - 'MRF11' - 'MRF12' - 'MRF13' - 'MRF14' - 'MRF21' - 'MRF22' - 'MRF23' - 'MRF24' - 'MRF25' - 'MRF31' - 'MRF32' - 'MRF33' - 'MRF34' - 'MRF35' - 'MRF41' - 'MRF42' - 'MRF43' - 'MRF44' - 'MRF45' - 'MRF46' - 'MRF51' - 'MRF52' - 'MRF53' - 'MRF54' - 'MRF55' - 'MRF56' - 'MRF61' - 'MRF62' - 'MRF63' - 'MRF64' - 'MRF65' - 'MRF66' - 'MRF67' - 'MRO11' - 'MRO12' - 'MRO13' - 'MRO14' - 'MRO21' - 'MRO22' - 'MRO23' - 'MRO24' - 'MRO31' - 'MRO32' - 'MRO33' - 'MRO34' - 'MRO41' - 'MRO42' - 'MRO43' - 'MRO44' - 'MRO51' - 'MRO52' - 'MRO53' - 'MRP11' - 'MRP12' - 'MRP21' - 'MRP22' - 'MRP23' - 'MRP32' - 'MRP33' - 'MRP34' - 'MRP35' - 'MRP41' - 'MRP42' - 'MRP43' - 'MRP44' - 'MRP45' - 'MRP51' - 'MRP52' - 'MRP53' - 'MRP54' - 'MRP55' - 'MRP56' - 'MRP57' - 'MRT11' - 'MRT12' - 'MRT13' - 'MRT14' - 'MRT15' - 'MRT16' - 'MRT21' - 'MRT22' - 'MRT23' - 'MRT24' - 'MRT25' - 'MRT26' - 'MRT27' - 'MRT31' - 'MRT32' - 'MRT33' - 'MRT34' - 'MRT35' - 'MRT36' - 'MRT37' - 'MRT41' - 'MRT42' - 'MRT43' - 'MRT44' - 'MRT45' - 'MRT46' - 'MRT47' - 'MRT51' - 'MRT52' - 'MRT53' - 'MRT54' - 'MRT55' - 'MRT56' - 'MRT57' - 'MZC01' - 'MZC02' - 'MZC03' - 'MZC04' - 'MZF01' - 'MZF02' - 'MZF03' - 'MZO01' - 'MZO02' - 'MZO03' - 'MZP01' - }; - - % f.ck, apparently one channel is missing - ctf275_planar = cell(274,2); - for i=1:274 - ctf275_planar{i,1} = sprintf('%s_dH', ctf275{i}); - ctf275_planar{i,2} = sprintf('%s_dV', ctf275{i}); - end -end % if issctf - -if isneuromag - neuromag122 = { - 'MEG 001' 'MEG 002' - 'MEG 003' 'MEG 004' - 'MEG 005' 'MEG 006' - 'MEG 007' 'MEG 008' - 'MEG 009' 'MEG 010' - 'MEG 011' 'MEG 012' - 'MEG 013' 'MEG 014' - 'MEG 015' 'MEG 016' - 'MEG 017' 'MEG 018' - 'MEG 019' 'MEG 020' - 'MEG 021' 'MEG 022' - 'MEG 023' 'MEG 024' - 'MEG 025' 'MEG 026' - 'MEG 027' 'MEG 028' - 'MEG 029' 'MEG 030' - 'MEG 031' 'MEG 032' - 'MEG 033' 'MEG 034' - 'MEG 035' 'MEG 036' - 'MEG 037' 'MEG 038' - 'MEG 039' 'MEG 040' - 'MEG 041' 'MEG 042' - 'MEG 043' 'MEG 044' - 'MEG 045' 'MEG 046' - 'MEG 047' 'MEG 048' - 'MEG 049' 'MEG 050' - 'MEG 051' 'MEG 052' - 'MEG 053' 'MEG 054' - 'MEG 055' 'MEG 056' - 'MEG 057' 'MEG 058' - 'MEG 059' 'MEG 060' - 'MEG 061' 'MEG 062' - 'MEG 063' 'MEG 064' - 'MEG 065' 'MEG 066' - 'MEG 067' 'MEG 068' - 'MEG 069' 'MEG 070' - 'MEG 071' 'MEG 072' - 'MEG 073' 'MEG 074' - 'MEG 075' 'MEG 076' - 'MEG 077' 'MEG 078' - 'MEG 079' 'MEG 080' - 'MEG 081' 'MEG 082' - 'MEG 083' 'MEG 084' - 'MEG 085' 'MEG 086' - 'MEG 087' 'MEG 088' - 'MEG 089' 'MEG 090' - 'MEG 091' 'MEG 092' - 'MEG 093' 'MEG 094' - 'MEG 095' 'MEG 096' - 'MEG 097' 'MEG 098' - 'MEG 099' 'MEG 100' - 'MEG 101' 'MEG 102' - 'MEG 103' 'MEG 104' - 'MEG 105' 'MEG 106' - 'MEG 107' 'MEG 108' - 'MEG 109' 'MEG 110' - 'MEG 111' 'MEG 112' - 'MEG 113' 'MEG 114' - 'MEG 115' 'MEG 116' - 'MEG 117' 'MEG 118' - 'MEG 119' 'MEG 120' - 'MEG 121' 'MEG 122' - }; - - % this is an alternative set of labels without a space in them - neuromag122alt = { - 'MEG001' 'MEG002' - 'MEG003' 'MEG004' - 'MEG005' 'MEG006' - 'MEG007' 'MEG008' - 'MEG009' 'MEG010' - 'MEG011' 'MEG012' - 'MEG013' 'MEG014' - 'MEG015' 'MEG016' - 'MEG017' 'MEG018' - 'MEG019' 'MEG020' - 'MEG021' 'MEG022' - 'MEG023' 'MEG024' - 'MEG025' 'MEG026' - 'MEG027' 'MEG028' - 'MEG029' 'MEG030' - 'MEG031' 'MEG032' - 'MEG033' 'MEG034' - 'MEG035' 'MEG036' - 'MEG037' 'MEG038' - 'MEG039' 'MEG040' - 'MEG041' 'MEG042' - 'MEG043' 'MEG044' - 'MEG045' 'MEG046' - 'MEG047' 'MEG048' - 'MEG049' 'MEG050' - 'MEG051' 'MEG052' - 'MEG053' 'MEG054' - 'MEG055' 'MEG056' - 'MEG057' 'MEG058' - 'MEG059' 'MEG060' - 'MEG061' 'MEG062' - 'MEG063' 'MEG064' - 'MEG065' 'MEG066' - 'MEG067' 'MEG068' - 'MEG069' 'MEG070' - 'MEG071' 'MEG072' - 'MEG073' 'MEG074' - 'MEG075' 'MEG076' - 'MEG077' 'MEG078' - 'MEG079' 'MEG080' - 'MEG081' 'MEG082' - 'MEG083' 'MEG084' - 'MEG085' 'MEG086' - 'MEG087' 'MEG088' - 'MEG089' 'MEG090' - 'MEG091' 'MEG092' - 'MEG093' 'MEG094' - 'MEG095' 'MEG096' - 'MEG097' 'MEG098' - 'MEG099' 'MEG100' - 'MEG101' 'MEG102' - 'MEG103' 'MEG104' - 'MEG105' 'MEG106' - 'MEG107' 'MEG108' - 'MEG109' 'MEG110' - 'MEG111' 'MEG112' - 'MEG113' 'MEG114' - 'MEG115' 'MEG116' - 'MEG117' 'MEG118' - 'MEG119' 'MEG120' - 'MEG121' 'MEG122' - }; - - neuromag306 = { - 'MEG 0113' 'MEG 0112' 'MEG 0111' - 'MEG 0122' 'MEG 0123' 'MEG 0121' - 'MEG 0132' 'MEG 0133' 'MEG 0131' - 'MEG 0143' 'MEG 0142' 'MEG 0141' - 'MEG 0213' 'MEG 0212' 'MEG 0211' - 'MEG 0222' 'MEG 0223' 'MEG 0221' - 'MEG 0232' 'MEG 0233' 'MEG 0231' - 'MEG 0243' 'MEG 0242' 'MEG 0241' - 'MEG 0313' 'MEG 0312' 'MEG 0311' - 'MEG 0322' 'MEG 0323' 'MEG 0321' - 'MEG 0333' 'MEG 0332' 'MEG 0331' - 'MEG 0343' 'MEG 0342' 'MEG 0341' - 'MEG 0413' 'MEG 0412' 'MEG 0411' - 'MEG 0422' 'MEG 0423' 'MEG 0421' - 'MEG 0432' 'MEG 0433' 'MEG 0431' - 'MEG 0443' 'MEG 0442' 'MEG 0441' - 'MEG 0513' 'MEG 0512' 'MEG 0511' - 'MEG 0523' 'MEG 0522' 'MEG 0521' - 'MEG 0532' 'MEG 0533' 'MEG 0531' - 'MEG 0542' 'MEG 0543' 'MEG 0541' - 'MEG 0613' 'MEG 0612' 'MEG 0611' - 'MEG 0622' 'MEG 0623' 'MEG 0621' - 'MEG 0633' 'MEG 0632' 'MEG 0631' - 'MEG 0642' 'MEG 0643' 'MEG 0641' - 'MEG 0713' 'MEG 0712' 'MEG 0711' - 'MEG 0723' 'MEG 0722' 'MEG 0721' - 'MEG 0733' 'MEG 0732' 'MEG 0731' - 'MEG 0743' 'MEG 0742' 'MEG 0741' - 'MEG 0813' 'MEG 0812' 'MEG 0811' - 'MEG 0822' 'MEG 0823' 'MEG 0821' - 'MEG 0913' 'MEG 0912' 'MEG 0911' - 'MEG 0923' 'MEG 0922' 'MEG 0921' - 'MEG 0932' 'MEG 0933' 'MEG 0931' - 'MEG 0942' 'MEG 0943' 'MEG 0941' - 'MEG 1013' 'MEG 1012' 'MEG 1011' - 'MEG 1023' 'MEG 1022' 'MEG 1021' - 'MEG 1032' 'MEG 1033' 'MEG 1031' - 'MEG 1043' 'MEG 1042' 'MEG 1041' - 'MEG 1112' 'MEG 1113' 'MEG 1111' - 'MEG 1123' 'MEG 1122' 'MEG 1121' - 'MEG 1133' 'MEG 1132' 'MEG 1131' - 'MEG 1142' 'MEG 1143' 'MEG 1141' - 'MEG 1213' 'MEG 1212' 'MEG 1211' - 'MEG 1223' 'MEG 1222' 'MEG 1221' - 'MEG 1232' 'MEG 1233' 'MEG 1231' - 'MEG 1243' 'MEG 1242' 'MEG 1241' - 'MEG 1312' 'MEG 1313' 'MEG 1311' - 'MEG 1323' 'MEG 1322' 'MEG 1321' - 'MEG 1333' 'MEG 1332' 'MEG 1331' - 'MEG 1342' 'MEG 1343' 'MEG 1341' - 'MEG 1412' 'MEG 1413' 'MEG 1411' - 'MEG 1423' 'MEG 1422' 'MEG 1421' - 'MEG 1433' 'MEG 1432' 'MEG 1431' - 'MEG 1442' 'MEG 1443' 'MEG 1441' - 'MEG 1512' 'MEG 1513' 'MEG 1511' - 'MEG 1522' 'MEG 1523' 'MEG 1521' - 'MEG 1533' 'MEG 1532' 'MEG 1531' - 'MEG 1543' 'MEG 1542' 'MEG 1541' - 'MEG 1613' 'MEG 1612' 'MEG 1611' - 'MEG 1622' 'MEG 1623' 'MEG 1621' - 'MEG 1632' 'MEG 1633' 'MEG 1631' - 'MEG 1643' 'MEG 1642' 'MEG 1641' - 'MEG 1713' 'MEG 1712' 'MEG 1711' - 'MEG 1722' 'MEG 1723' 'MEG 1721' - 'MEG 1732' 'MEG 1733' 'MEG 1731' - 'MEG 1743' 'MEG 1742' 'MEG 1741' - 'MEG 1813' 'MEG 1812' 'MEG 1811' - 'MEG 1822' 'MEG 1823' 'MEG 1821' - 'MEG 1832' 'MEG 1833' 'MEG 1831' - 'MEG 1843' 'MEG 1842' 'MEG 1841' - 'MEG 1912' 'MEG 1913' 'MEG 1911' - 'MEG 1923' 'MEG 1922' 'MEG 1921' - 'MEG 1932' 'MEG 1933' 'MEG 1931' - 'MEG 1943' 'MEG 1942' 'MEG 1941' - 'MEG 2013' 'MEG 2012' 'MEG 2011' - 'MEG 2023' 'MEG 2022' 'MEG 2021' - 'MEG 2032' 'MEG 2033' 'MEG 2031' - 'MEG 2042' 'MEG 2043' 'MEG 2041' - 'MEG 2113' 'MEG 2112' 'MEG 2111' - 'MEG 2122' 'MEG 2123' 'MEG 2121' - 'MEG 2133' 'MEG 2132' 'MEG 2131' - 'MEG 2143' 'MEG 2142' 'MEG 2141' - 'MEG 2212' 'MEG 2213' 'MEG 2211' - 'MEG 2223' 'MEG 2222' 'MEG 2221' - 'MEG 2233' 'MEG 2232' 'MEG 2231' - 'MEG 2242' 'MEG 2243' 'MEG 2241' - 'MEG 2312' 'MEG 2313' 'MEG 2311' - 'MEG 2323' 'MEG 2322' 'MEG 2321' - 'MEG 2332' 'MEG 2333' 'MEG 2331' - 'MEG 2343' 'MEG 2342' 'MEG 2341' - 'MEG 2412' 'MEG 2413' 'MEG 2411' - 'MEG 2423' 'MEG 2422' 'MEG 2421' - 'MEG 2433' 'MEG 2432' 'MEG 2431' - 'MEG 2442' 'MEG 2443' 'MEG 2441' - 'MEG 2512' 'MEG 2513' 'MEG 2511' - 'MEG 2522' 'MEG 2523' 'MEG 2521' - 'MEG 2533' 'MEG 2532' 'MEG 2531' - 'MEG 2543' 'MEG 2542' 'MEG 2541' - 'MEG 2612' 'MEG 2613' 'MEG 2611' - 'MEG 2623' 'MEG 2622' 'MEG 2621' - 'MEG 2633' 'MEG 2632' 'MEG 2631' - 'MEG 2642' 'MEG 2643' 'MEG 2641' - }; - - % this is an alternative set of labels without a space in them - neuromag306alt = { - 'MEG0113' 'MEG0112' 'MEG0111' - 'MEG0122' 'MEG0123' 'MEG0121' - 'MEG0132' 'MEG0133' 'MEG0131' - 'MEG0143' 'MEG0142' 'MEG0141' - 'MEG0213' 'MEG0212' 'MEG0211' - 'MEG0222' 'MEG0223' 'MEG0221' - 'MEG0232' 'MEG0233' 'MEG0231' - 'MEG0243' 'MEG0242' 'MEG0241' - 'MEG0313' 'MEG0312' 'MEG0311' - 'MEG0322' 'MEG0323' 'MEG0321' - 'MEG0333' 'MEG0332' 'MEG0331' - 'MEG0343' 'MEG0342' 'MEG0341' - 'MEG0413' 'MEG0412' 'MEG0411' - 'MEG0422' 'MEG0423' 'MEG0421' - 'MEG0432' 'MEG0433' 'MEG0431' - 'MEG0443' 'MEG0442' 'MEG0441' - 'MEG0513' 'MEG0512' 'MEG0511' - 'MEG0523' 'MEG0522' 'MEG0521' - 'MEG0532' 'MEG0533' 'MEG0531' - 'MEG0542' 'MEG0543' 'MEG0541' - 'MEG0613' 'MEG0612' 'MEG0611' - 'MEG0622' 'MEG0623' 'MEG0621' - 'MEG0633' 'MEG0632' 'MEG0631' - 'MEG0642' 'MEG0643' 'MEG0641' - 'MEG0713' 'MEG0712' 'MEG0711' - 'MEG0723' 'MEG0722' 'MEG0721' - 'MEG0733' 'MEG0732' 'MEG0731' - 'MEG0743' 'MEG0742' 'MEG0741' - 'MEG0813' 'MEG0812' 'MEG0811' - 'MEG0822' 'MEG0823' 'MEG0821' - 'MEG0913' 'MEG0912' 'MEG0911' - 'MEG0923' 'MEG0922' 'MEG0921' - 'MEG0932' 'MEG0933' 'MEG0931' - 'MEG0942' 'MEG0943' 'MEG0941' - 'MEG1013' 'MEG1012' 'MEG1011' - 'MEG1023' 'MEG1022' 'MEG1021' - 'MEG1032' 'MEG1033' 'MEG1031' - 'MEG1043' 'MEG1042' 'MEG1041' - 'MEG1112' 'MEG1113' 'MEG1111' - 'MEG1123' 'MEG1122' 'MEG1121' - 'MEG1133' 'MEG1132' 'MEG1131' - 'MEG1142' 'MEG1143' 'MEG1141' - 'MEG1213' 'MEG1212' 'MEG1211' - 'MEG1223' 'MEG1222' 'MEG1221' - 'MEG1232' 'MEG1233' 'MEG1231' - 'MEG1243' 'MEG1242' 'MEG1241' - 'MEG1312' 'MEG1313' 'MEG1311' - 'MEG1323' 'MEG1322' 'MEG1321' - 'MEG1333' 'MEG1332' 'MEG1331' - 'MEG1342' 'MEG1343' 'MEG1341' - 'MEG1412' 'MEG1413' 'MEG1411' - 'MEG1423' 'MEG1422' 'MEG1421' - 'MEG1433' 'MEG1432' 'MEG1431' - 'MEG1442' 'MEG1443' 'MEG1441' - 'MEG1512' 'MEG1513' 'MEG1511' - 'MEG1522' 'MEG1523' 'MEG1521' - 'MEG1533' 'MEG1532' 'MEG1531' - 'MEG1543' 'MEG1542' 'MEG1541' - 'MEG1613' 'MEG1612' 'MEG1611' - 'MEG1622' 'MEG1623' 'MEG1621' - 'MEG1632' 'MEG1633' 'MEG1631' - 'MEG1643' 'MEG1642' 'MEG1641' - 'MEG1713' 'MEG1712' 'MEG1711' - 'MEG1722' 'MEG1723' 'MEG1721' - 'MEG1732' 'MEG1733' 'MEG1731' - 'MEG1743' 'MEG1742' 'MEG1741' - 'MEG1813' 'MEG1812' 'MEG1811' - 'MEG1822' 'MEG1823' 'MEG1821' - 'MEG1832' 'MEG1833' 'MEG1831' - 'MEG1843' 'MEG1842' 'MEG1841' - 'MEG1912' 'MEG1913' 'MEG1911' - 'MEG1923' 'MEG1922' 'MEG1921' - 'MEG1932' 'MEG1933' 'MEG1931' - 'MEG1943' 'MEG1942' 'MEG1941' - 'MEG2013' 'MEG2012' 'MEG2011' - 'MEG2023' 'MEG2022' 'MEG2021' - 'MEG2032' 'MEG2033' 'MEG2031' - 'MEG2042' 'MEG2043' 'MEG2041' - 'MEG2113' 'MEG2112' 'MEG2111' - 'MEG2122' 'MEG2123' 'MEG2121' - 'MEG2133' 'MEG2132' 'MEG2131' - 'MEG2143' 'MEG2142' 'MEG2141' - 'MEG2212' 'MEG2213' 'MEG2211' - 'MEG2223' 'MEG2222' 'MEG2221' - 'MEG2233' 'MEG2232' 'MEG2231' - 'MEG2242' 'MEG2243' 'MEG2241' - 'MEG2312' 'MEG2313' 'MEG2311' - 'MEG2323' 'MEG2322' 'MEG2321' - 'MEG2332' 'MEG2333' 'MEG2331' - 'MEG2343' 'MEG2342' 'MEG2341' - 'MEG2412' 'MEG2413' 'MEG2411' - 'MEG2423' 'MEG2422' 'MEG2421' - 'MEG2433' 'MEG2432' 'MEG2431' - 'MEG2442' 'MEG2443' 'MEG2441' - 'MEG2512' 'MEG2513' 'MEG2511' - 'MEG2522' 'MEG2523' 'MEG2521' - 'MEG2533' 'MEG2532' 'MEG2531' - 'MEG2543' 'MEG2542' 'MEG2541' - 'MEG2612' 'MEG2613' 'MEG2611' - 'MEG2623' 'MEG2622' 'MEG2621' - 'MEG2633' 'MEG2632' 'MEG2631' - 'MEG2642' 'MEG2643' 'MEG2641' - }; -end % if isneuromag - -if iseeg || isext - eeg1020 = { - 'Fp1' - 'Fpz' - 'Fp2' - 'F7' - 'F3' - 'Fz' - 'F4' - 'F8' - 'T7' - 'C3' - 'Cz' - 'C4' - 'T8' - 'P7' - 'P3' - 'Pz' - 'P4' - 'P8' - 'O1' - 'Oz' - 'O2'}; - - eeg1010 = { - 'Fp1' - 'Fpz' - 'Fp2' - 'AF9' - 'AF7' - 'AF5' - 'AF3' - 'AF1' - 'AFz' - 'AF2' - 'AF4' - 'AF6' - 'AF8' - 'AF10' - 'F9' - 'F7' - 'F5' - 'F3' - 'F1' - 'Fz' - 'F2' - 'F4' - 'F6' - 'F8' - 'F10' - 'FT9' - 'FT7' - 'FC5' - 'FC3' - 'FC1' - 'FCz' - 'FC2' - 'FC4' - 'FC6' - 'FT8' - 'FT10' - 'T9' - 'T7' - 'C5' - 'C3' - 'C1' - 'Cz' - 'C2' - 'C4' - 'C6' - 'T8' - 'T10' - 'TP9' - 'TP7' - 'CP5' - 'CP3' - 'CP1' - 'CPz' - 'CP2' - 'CP4' - 'CP6' - 'TP8' - 'TP10' - 'P9' - 'P7' - 'P5' - 'P3' - 'P1' - 'Pz' - 'P2' - 'P4' - 'P6' - 'P8' - 'P10' - 'PO9' - 'PO7' - 'PO5' - 'PO3' - 'PO1' - 'POz' - 'PO2' - 'PO4' - 'PO6' - 'PO8' - 'PO10' - 'O1' - 'Oz' - 'O2' - 'I1' - 'Iz' - 'I2' - }; - - eeg1005 = { - 'Fp1' - 'Fpz' - 'Fp2' - 'AF9' - 'AF7' - 'AF5' - 'AF3' - 'AF1' - 'AFz' - 'AF2' - 'AF4' - 'AF6' - 'AF8' - 'AF10' - 'F9' - 'F7' - 'F5' - 'F3' - 'F1' - 'Fz' - 'F2' - 'F4' - 'F6' - 'F8' - 'F10' - 'FT9' - 'FT7' - 'FC5' - 'FC3' - 'FC1' - 'FCz' - 'FC2' - 'FC4' - 'FC6' - 'FT8' - 'FT10' - 'T9' - 'T7' - 'C5' - 'C3' - 'C1' - 'Cz' - 'C2' - 'C4' - 'C6' - 'T8' - 'T10' - 'TP9' - 'TP7' - 'CP5' - 'CP3' - 'CP1' - 'CPz' - 'CP2' - 'CP4' - 'CP6' - 'TP8' - 'TP10' - 'P9' - 'P7' - 'P5' - 'P3' - 'P1' - 'Pz' - 'P2' - 'P4' - 'P6' - 'P8' - 'P10' - 'PO9' - 'PO7' - 'PO5' - 'PO3' - 'PO1' - 'POz' - 'PO2' - 'PO4' - 'PO6' - 'PO8' - 'PO10' - 'O1' - 'Oz' - 'O2' - 'I1' - 'Iz' - 'I2' - 'AFp9h' - 'AFp7h' - 'AFp5h' - 'AFp3h' - 'AFp1h' - 'AFp2h' - 'AFp4h' - 'AFp6h' - 'AFp8h' - 'AFp10h' - 'AFF9h' - 'AFF7h' - 'AFF5h' - 'AFF3h' - 'AFF1h' - 'AFF2h' - 'AFF4h' - 'AFF6h' - 'AFF8h' - 'AFF10h' - 'FFT9h' - 'FFT7h' - 'FFC5h' - 'FFC3h' - 'FFC1h' - 'FFC2h' - 'FFC4h' - 'FFC6h' - 'FFT8h' - 'FFT10h' - 'FTT9h' - 'FTT7h' - 'FCC5h' - 'FCC3h' - 'FCC1h' - 'FCC2h' - 'FCC4h' - 'FCC6h' - 'FTT8h' - 'FTT10h' - 'TTP9h' - 'TTP7h' - 'CCP5h' - 'CCP3h' - 'CCP1h' - 'CCP2h' - 'CCP4h' - 'CCP6h' - 'TTP8h' - 'TTP10h' - 'TPP9h' - 'TPP7h' - 'CPP5h' - 'CPP3h' - 'CPP1h' - 'CPP2h' - 'CPP4h' - 'CPP6h' - 'TPP8h' - 'TPP10h' - 'PPO9h' - 'PPO7h' - 'PPO5h' - 'PPO3h' - 'PPO1h' - 'PPO2h' - 'PPO4h' - 'PPO6h' - 'PPO8h' - 'PPO10h' - 'POO9h' - 'POO7h' - 'POO5h' - 'POO3h' - 'POO1h' - 'POO2h' - 'POO4h' - 'POO6h' - 'POO8h' - 'POO10h' - 'OI1h' - 'OI2h' - 'Fp1h' - 'Fp2h' - 'AF9h' - 'AF7h' - 'AF5h' - 'AF3h' - 'AF1h' - 'AF2h' - 'AF4h' - 'AF6h' - 'AF8h' - 'AF10h' - 'F9h' - 'F7h' - 'F5h' - 'F3h' - 'F1h' - 'F2h' - 'F4h' - 'F6h' - 'F8h' - 'F10h' - 'FT9h' - 'FT7h' - 'FC5h' - 'FC3h' - 'FC1h' - 'FC2h' - 'FC4h' - 'FC6h' - 'FT8h' - 'FT10h' - 'T9h' - 'T7h' - 'C5h' - 'C3h' - 'C1h' - 'C2h' - 'C4h' - 'C6h' - 'T8h' - 'T10h' - 'TP9h' - 'TP7h' - 'CP5h' - 'CP3h' - 'CP1h' - 'CP2h' - 'CP4h' - 'CP6h' - 'TP8h' - 'TP10h' - 'P9h' - 'P7h' - 'P5h' - 'P3h' - 'P1h' - 'P2h' - 'P4h' - 'P6h' - 'P8h' - 'P10h' - 'PO9h' - 'PO7h' - 'PO5h' - 'PO3h' - 'PO1h' - 'PO2h' - 'PO4h' - 'PO6h' - 'PO8h' - 'PO10h' - 'O1h' - 'O2h' - 'I1h' - 'I2h' - 'AFp9' - 'AFp7' - 'AFp5' - 'AFp3' - 'AFp1' - 'AFpz' - 'AFp2' - 'AFp4' - 'AFp6' - 'AFp8' - 'AFp10' - 'AFF9' - 'AFF7' - 'AFF5' - 'AFF3' - 'AFF1' - 'AFFz' - 'AFF2' - 'AFF4' - 'AFF6' - 'AFF8' - 'AFF10' - 'FFT9' - 'FFT7' - 'FFC5' - 'FFC3' - 'FFC1' - 'FFCz' - 'FFC2' - 'FFC4' - 'FFC6' - 'FFT8' - 'FFT10' - 'FTT9' - 'FTT7' - 'FCC5' - 'FCC3' - 'FCC1' - 'FCCz' - 'FCC2' - 'FCC4' - 'FCC6' - 'FTT8' - 'FTT10' - 'TTP9' - 'TTP7' - 'CCP5' - 'CCP3' - 'CCP1' - 'CCPz' - 'CCP2' - 'CCP4' - 'CCP6' - 'TTP8' - 'TTP10' - 'TPP9' - 'TPP7' - 'CPP5' - 'CPP3' - 'CPP1' - 'CPPz' - 'CPP2' - 'CPP4' - 'CPP6' - 'TPP8' - 'TPP10' - 'PPO9' - 'PPO7' - 'PPO5' - 'PPO3' - 'PPO1' - 'PPOz' - 'PPO2' - 'PPO4' - 'PPO6' - 'PPO8' - 'PPO10' - 'POO9' - 'POO7' - 'POO5' - 'POO3' - 'POO1' - 'POOz' - 'POO2' - 'POO4' - 'POO6' - 'POO8' - 'POO10' - 'OI1' - 'OIz' - 'OI2' - }; - - % Add also alternative labels that are used in some systems - ext1020 = cat(1, eeg1005, {'A1' 'A2' 'M1' 'M2' 'T3' 'T4' 'T5' 'T6'}'); - - % This is to account for all variants of case in 1020 systems - ext1020 = unique(cat(1, ext1020, upper(ext1020), lower(ext1020))); -end % if iseeg || isext - -if isbiosemi - biosemi64 = { - 'A1' - 'A2' - 'A3' - 'A4' - 'A5' - 'A6' - 'A7' - 'A8' - 'A9' - 'A10' - 'A11' - 'A12' - 'A13' - 'A14' - 'A15' - 'A16' - 'A17' - 'A18' - 'A19' - 'A20' - 'A21' - 'A22' - 'A23' - 'A24' - 'A25' - 'A26' - 'A27' - 'A28' - 'A29' - 'A30' - 'A31' - 'A32' - 'B1' - 'B2' - 'B3' - 'B4' - 'B5' - 'B6' - 'B7' - 'B8' - 'B9' - 'B10' - 'B11' - 'B12' - 'B13' - 'B14' - 'B15' - 'B16' - 'B17' - 'B18' - 'B19' - 'B20' - 'B21' - 'B22' - 'B23' - 'B24' - 'B25' - 'B26' - 'B27' - 'B28' - 'B29' - 'B30' - 'B31' - 'B32' - }; - - biosemi128 = { - 'A1' - 'A2' - 'A3' - 'A4' - 'A5' - 'A6' - 'A7' - 'A8' - 'A9' - 'A10' - 'A11' - 'A12' - 'A13' - 'A14' - 'A15' - 'A16' - 'A17' - 'A18' - 'A19' - 'A20' - 'A21' - 'A22' - 'A23' - 'A24' - 'A25' - 'A26' - 'A27' - 'A28' - 'A29' - 'A30' - 'A31' - 'A32' - 'B1' - 'B2' - 'B3' - 'B4' - 'B5' - 'B6' - 'B7' - 'B8' - 'B9' - 'B10' - 'B11' - 'B12' - 'B13' - 'B14' - 'B15' - 'B16' - 'B17' - 'B18' - 'B19' - 'B20' - 'B21' - 'B22' - 'B23' - 'B24' - 'B25' - 'B26' - 'B27' - 'B28' - 'B29' - 'B30' - 'B31' - 'B32' - 'C1' - 'C2' - 'C3' - 'C4' - 'C5' - 'C6' - 'C7' - 'C8' - 'C9' - 'C10' - 'C11' - 'C12' - 'C13' - 'C14' - 'C15' - 'C16' - 'C17' - 'C18' - 'C19' - 'C20' - 'C21' - 'C22' - 'C23' - 'C24' - 'C25' - 'C26' - 'C27' - 'C28' - 'C29' - 'C30' - 'C31' - 'C32' - 'D1' - 'D2' - 'D3' - 'D4' - 'D5' - 'D6' - 'D7' - 'D8' - 'D9' - 'D10' - 'D11' - 'D12' - 'D13' - 'D14' - 'D15' - 'D16' - 'D17' - 'D18' - 'D19' - 'D20' - 'D21' - 'D22' - 'D23' - 'D24' - 'D25' - 'D26' - 'D27' - 'D28' - 'D29' - 'D30' - 'D31' - 'D32' - }; - - biosemi256 = { - 'A1' - 'A2' - 'A3' - 'A4' - 'A5' - 'A6' - 'A7' - 'A8' - 'A9' - 'A10' - 'A11' - 'A12' - 'A13' - 'A14' - 'A15' - 'A16' - 'A17' - 'A18' - 'A19' - 'A20' - 'A21' - 'A22' - 'A23' - 'A24' - 'A25' - 'A26' - 'A27' - 'A28' - 'A29' - 'A30' - 'A31' - 'A32' - 'B1' - 'B2' - 'B3' - 'B4' - 'B5' - 'B6' - 'B7' - 'B8' - 'B9' - 'B10' - 'B11' - 'B12' - 'B13' - 'B14' - 'B15' - 'B16' - 'B17' - 'B18' - 'B19' - 'B20' - 'B21' - 'B22' - 'B23' - 'B24' - 'B25' - 'B26' - 'B27' - 'B28' - 'B29' - 'B30' - 'B31' - 'B32' - 'C1' - 'C2' - 'C3' - 'C4' - 'C5' - 'C6' - 'C7' - 'C8' - 'C9' - 'C10' - 'C11' - 'C12' - 'C13' - 'C14' - 'C15' - 'C16' - 'C17' - 'C18' - 'C19' - 'C20' - 'C21' - 'C22' - 'C23' - 'C24' - 'C25' - 'C26' - 'C27' - 'C28' - 'C29' - 'C30' - 'C31' - 'C32' - 'D1' - 'D2' - 'D3' - 'D4' - 'D5' - 'D6' - 'D7' - 'D8' - 'D9' - 'D10' - 'D11' - 'D12' - 'D13' - 'D14' - 'D15' - 'D16' - 'D17' - 'D18' - 'D19' - 'D20' - 'D21' - 'D22' - 'D23' - 'D24' - 'D25' - 'D26' - 'D27' - 'D28' - 'D29' - 'D30' - 'D31' - 'D32' - 'E1' - 'E2' - 'E3' - 'E4' - 'E5' - 'E6' - 'E7' - 'E8' - 'E9' - 'E10' - 'E11' - 'E12' - 'E13' - 'E14' - 'E15' - 'E16' - 'E17' - 'E18' - 'E19' - 'E20' - 'E21' - 'E22' - 'E23' - 'E24' - 'E25' - 'E26' - 'E27' - 'E28' - 'E29' - 'E30' - 'E31' - 'E32' - 'F1' - 'F2' - 'F3' - 'F4' - 'F5' - 'F6' - 'F7' - 'F8' - 'F9' - 'F10' - 'F11' - 'F12' - 'F13' - 'F14' - 'F15' - 'F16' - 'F17' - 'F18' - 'F19' - 'F20' - 'F21' - 'F22' - 'F23' - 'F24' - 'F25' - 'F26' - 'F27' - 'F28' - 'F29' - 'F30' - 'F31' - 'F32' - 'G1' - 'G2' - 'G3' - 'G4' - 'G5' - 'G6' - 'G7' - 'G8' - 'G9' - 'G10' - 'G11' - 'G12' - 'G13' - 'G14' - 'G15' - 'G16' - 'G17' - 'G18' - 'G19' - 'G20' - 'G21' - 'G22' - 'G23' - 'G24' - 'G25' - 'G26' - 'G27' - 'G28' - 'G29' - 'G30' - 'G31' - 'G32' - 'H1' - 'H2' - 'H3' - 'H4' - 'H5' - 'H6' - 'H7' - 'H8' - 'H9' - 'H10' - 'H11' - 'H12' - 'H13' - 'H14' - 'H15' - 'H16' - 'H17' - 'H18' - 'H19' - 'H20' - 'H21' - 'H22' - 'H23' - 'H24' - 'H25' - 'H26' - 'H27' - 'H28' - 'H29' - 'H30' - 'H31' - 'H32' - }; - -end % if isbiosemi - -if isegi - egi256 = cell(256, 1); - for i = 1:256 - egi256{i} = sprintf('e%d', i); - end - % the others are subsets - egi32 = egi256(1:32); - egi64 = egi256(1:64); - egi128 = egi256(1:128); -end % if isegi - -if isitab - itab153 = cell(153,1); - itab153_planar = cell(153,2); - for i=1:153 - % channel names start counting at zero - itab153{i} = sprintf('MAG_%03d', i-1); - itab153_planar{i,1} = sprintf('MAG_%03d_dH', i-1); - itab153_planar{i,2} = sprintf('MAG_%03d_dV', i-1); - end -end % if isitab - -% search for the requested definition of channel labels -if exist(type, 'var') - label = eval(type); - label = label(:); -else - error('the requested sensor type is not supported'); -end - -% remember the current input and output arguments, so that they can be -% reused on a subsequent call in case the same input argument is given -current_argout = {label}; -if isempty(previous_argin) - previous_argin = current_argin; - previous_argout = current_argout; -end - diff --git a/external/fieldtrip/private/sensortype.m b/external/fieldtrip/private/sensortype.m index db9f7c4..e07551b 100644 --- a/external/fieldtrip/private/sensortype.m +++ b/external/fieldtrip/private/sensortype.m @@ -27,36 +27,23 @@ % Copyright (C) 2004-2006, Robert Oostenveld % -% $Log: sensortype.m,v $ -% Revision 1.6 2007/12/12 10:39:45 roboos -% added try-end in case no pnt present, return 'unknown' as string instead of [] +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.5 2007/06/11 09:38:01 roboos -% added some code for yokogawa160, not yet complete, since yokogawa2grad is not yet implemented fully +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.4 2007/06/11 09:17:34 roboos -% imporved detection for bti, better use of labels (start with 'A'), thanks to Nathan +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.3 2007/05/06 09:08:20 roboos -% return warning instead of error when type is not detected -% -% Revision 1.2 2006/10/04 12:08:31 jansch -% changed variable name sens into grad consistently -% -% Revision 1.1 2006/10/04 08:00:29 roboos -% renamed megsystem to sensortype, added support for bti148 and EEG electrodes, renamed 'simulated magnetometer' into 'magnetometer' -% -% Revision 1.7 2006/08/31 08:03:24 roboos -% add explicit support for data as input (use data.grad), thanks to Floris -% -% Revision 1.6 2006/08/29 20:47:01 roboos -% added support for a simple simulated magnetometer system -% -% Revision 1.5 2006/01/30 14:06:04 roboos -% added square brackets around output variable in function definition -% added copyrights and log -% cleaned up help documentation +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: sensortype.m 952 2010-04-21 18:29:51Z roboos $ % the input may be a data structure which then contains a grad/elec structure if isfield(grad, 'grad') @@ -73,7 +60,7 @@ % detect the different MEG sensor types description = { - 'ctf151' % 1 + 'ctf151' % 1 'ctf275' % 2 'ctf151_planar' % 3 'ctf275_planar' % 4 diff --git a/external/fieldtrip/private/senstype.m b/external/fieldtrip/private/senstype.m deleted file mode 100644 index bc46a71..0000000 --- a/external/fieldtrip/private/senstype.m +++ /dev/null @@ -1,365 +0,0 @@ -function [type] = senstype(input, desired) - -% SENSTYPE determines the type of sensors by looking at the channel names -% and comparing them with predefined lists. -% -% Use as -% [type] = senstype(sens) -% to get a string describing the type, or -% [flag] = senstype(sens, desired) -% to get a boolean value. -% -% The output type can be any of the following -% 'electrode' -% 'magnetometer' -% 'biosemi64' -% 'biosemi128' -% 'biosemi256' -% 'bti148' -% 'bti148_planar' -% 'bti248' -% 'bti248_planar' -% 'ctf151' -% 'ctf151_planar' -% 'ctf275' -% 'ctf275_planar' -% 'egi128' -% 'egi256' -% 'egi32' -% 'egi64' -% 'ext1020' -% 'neuromag122' -% 'neuromag306' -% 'yokogawa160' -% 'yokogawa160_planar' -% 'plexon' -% 'itab153' -% 'itab153_planar' -% -% The optional input argument for the desired type can be any of the above, -% or any of the following -% 'eeg' -% 'meg' -% 'meg_planar' -% 'meg_axial' -% 'ctf' -% 'bti' -% 'neuromag' -% 'yokogawa' -% -% Besides specifiying a grad or elec structure as input, also allowed is -% giving a data structure containing a grad or elec field, or giving a list -% of channel names (as cell-arrray). I.e. assuming a FieldTrip data -% structure, all of the following calls would be correct. -% senstype(data) -% senstype(data.label) -% senstype(data.grad) -% senstype(data.grad.label) -% -% See also READ_SENS, COMPUTE_LEADFIELD - -% Copyright (C) 2007-2008, Robert Oostenveld -% -% $Log: senstype.m,v $ -% Revision 1.21 2009/10/16 12:27:53 roboos -% some small changes pertaining to the itab/chieti format -% -% Revision 1.20 2009/10/13 10:39:19 roboos -% added support for 153 channel itab system -% -% Revision 1.19 2009/07/29 08:04:38 roboos -% cleaned up the code, no functional change -% -% Revision 1.18 2009/07/28 11:16:23 roboos -% removed keyboard statement, thanks to Jurrian -% -% Revision 1.17 2009/07/28 10:17:41 roboos -% make distinction between only label, label+pnt and label+pnt+ori -% -% Revision 1.16 2009/07/27 16:04:51 roboos -% improved distinction between eeg and meg, fixes problem with biosemi-eeg being detected as "ctf" due to reference channel match -% -% Revision 1.15 2009/06/19 16:51:50 vlalit -% Added biosemi64 system of Diane Whitmer, I don't know how generic it is. -% -% Revision 1.14 2009/05/07 13:34:09 roboos -% added ctf64 -% -% Revision 1.13 2009/04/01 06:51:43 roboos -% implemented caching for the type detection in case the same input is given multiple times -% this uses a persistent variable -% -% Revision 1.12 2009/03/06 08:50:23 roboos -% added handling of plexon header -% -% Revision 1.11 2009/02/02 16:27:41 roboos -% changed order of detecting sens.grad/elec on Vladimirs request, don't know why -% -% Revision 1.10 2008/09/10 09:12:11 roboos -% added alternative definition of channel names without a space in the label for neuromag 122 and 306 -% -% Revision 1.9 2008/09/10 07:53:27 roboos -% moved definition of channel label sets to seperate function -% -% Revision 1.8 2008/03/18 13:40:27 roboos -% added quick fix for ctf275_planar, the problem is that one channel is missing from the ctf275 list (i.e. it is only 274 long) -% -% Revision 1.7 2008/03/18 12:25:06 roboos -% use sens.type if available, this requires that the content of sens.type is consistent with the strings returned by this function -% preallocate cell-arrays -% -% Revision 1.6 2008/02/29 15:25:31 roboos -% fixed bug for eeg (thanks to Doug), updated documentation -% -% Revision 1.5 2008/02/29 14:04:42 roboos -% added gradiometers to btiref -% added general types to the checks at the end -% -% Revision 1.4 2008/02/29 13:52:12 roboos -% added bti248 and planar -% changed order of arguments for ismember, needed when a lot of EEG channels are present in ctf151 -% changed order in which checks are performed, first ctf275 and only then ctf151 -% -% Revision 1.3 2008/02/28 09:16:35 roboos -% fixed bug due to many trigger and headloc channels in ctf275 labels -% -% Revision 1.2 2008/02/27 17:01:54 roboos -% added a whole list of channel names, fixed some bugs -% -% Revision 1.1 2007/07/25 08:31:12 roboos -% implemented new helper function -% - -% these are for remembering the type on subsequent calls with the same input arguments -persistent previous_argin previous_argout - -if nargin<2 - % ensure that all input arguments are defined - desired = []; -end - -current_argin = {input, desired}; -if isequal(current_argin, previous_argin) - % don't do the type detection again, but return the previous values from cache - type = previous_argout{1}; - return -end - -isdata = isa(input, 'struct') && isfield(input, 'hdr') && isfield(input.hdr, 'label'); -isheader = isa(input, 'struct') && isfield(input, 'label') && isfield(input, 'Fs'); -isgrad = isa(input, 'struct') && isfield(input, 'pnt') && isfield(input, 'ori'); -iselec = isa(input, 'struct') && isfield(input, 'pnt') && ~isfield(input, 'ori'); -islabel = isa(input, 'cell') && isa(input{1}, 'char'); - -% the input may be a data structure which then contains a grad/elec structure -if isdata - if isfield(input.hdr, 'grad') - sens = input.hdr.grad; - isgrad = true; - elseif isfield(input.hdr, 'elec') - sens = input.hdr.elec; - iselec = true; - else - sens.label = input.hdr.label; - islabel = true; - end -elseif isheader - if isfield(input, 'grad') - sens = input.grad; - isgrad = true; - elseif isfield(input, 'elec') - sens = input.elec; - iselec = true; - else - sens.label = input.label; - islabel = true; - end -elseif isgrad - sens = input; -elseif iselec - sens = input; -elseif islabel - sens.label = input; -else - sens = []; -end - -if isfield(sens, 'type') - % preferably the structure specifies its own type - type = sens.type; - -elseif issubfield(sens, 'orig.FileHeader') && issubfield(sens, 'orig.VarHeader') - % this is a complete header that was read from a Plexon *.nex file using read_plexon_nex - type = 'plexon'; - -else - % start with unknown, then try to determine the proper type by looking at the labels - type = 'unknown'; - - if isgrad - % probably this is MEG, determine the type of magnetometer/gradiometer system - % note that the order here is important: first check whether it matches a 275 channel system, then a 151 channel system, since the 151 channels are a subset of the 275 - if (mean(ismember(senslabel('ctf275'), sens.label)) > 0.8) - type = 'ctf275'; - elseif (mean(ismember(senslabel('ctfheadloc'), sens.label)) > 0.8) % look at the head localization channels - type = 'ctf275'; - elseif (mean(ismember(senslabel('ctf151'), sens.label)) > 0.8) - type = 'ctf151'; - elseif (mean(ismember(senslabel('ctf64'), sens.label)) > 0.8) - type = 'ctf64'; - elseif (mean(ismember(senslabel('ctf275_planar'), sens.label)) > 0.8) - type = 'ctf275_planar'; - elseif (mean(ismember(senslabel('ctf151_planar'), sens.label)) > 0.8) - type = 'ctf151_planar'; - elseif (mean(ismember(senslabel('bti248'), sens.label)) > 0.8) - type = 'bti248'; - elseif (mean(ismember(senslabel('bti148'), sens.label)) > 0.8) - type = 'bti148'; - elseif (mean(ismember(senslabel('bti248_planar'), sens.label)) > 0.8) - type = 'bti248_planar'; - elseif (mean(ismember(senslabel('bti148_planar'), sens.label)) > 0.8) - type = 'bti148_planar'; - elseif (mean(ismember(senslabel('itab153'), sens.label)) > 0.8) - type = 'itab153'; - elseif (mean(ismember(senslabel('itab153_planar'), sens.label)) > 0.8) - type = 'itab153_planar'; - elseif (mean(ismember(senslabel('neuromag306'), sens.label)) > 0.8) - type = 'neuromag306'; - elseif (mean(ismember(senslabel('neuromag306alt'),sens.label)) > 0.8) % an alternative set without spaces in the name - type = 'neuromag306'; - elseif (mean(ismember(senslabel('neuromag122'), sens.label)) > 0.8) - type = 'neuromag122'; - elseif (mean(ismember(senslabel('neuromag122alt'),sens.label)) > 0.8) % an alternative set without spaces in the name - type = 'neuromag122'; - elseif any(ismember(senslabel('btiref'), sens.label)) - type = 'bti'; % it might be 148 or 248 channels - elseif any(ismember(senslabel('ctfref'), sens.label)) - type = 'ctf'; % it might be 151 or 275 channels - elseif isfield(sens, 'pnt') && isfield(sens, 'ori') && numel(sens.label)==numel(sens.pnt) - type = 'magnetometer'; - else - type = 'meg'; - end - - elseif iselec - % probably this is EEG - if (mean(ismember(senslabel('biosemi256'), sens.label)) > 0.8) - type = 'biosemi256'; - elseif (mean(ismember(senslabel('biosemi128'), sens.label)) > 0.8) - type = 'biosemi128'; - elseif (mean(ismember(senslabel('biosemi64'), sens.label)) > 0.8) - type = 'biosemi64'; - elseif (mean(ismember(senslabel('egi256'), sens.label)) > 0.8) - type = 'egi256'; - elseif (mean(ismember(senslabel('egi128'), sens.label)) > 0.8) - type = 'egi128'; - elseif (mean(ismember(senslabel('egi64'), sens.label)) > 0.8) - type = 'egi64'; - elseif (mean(ismember(senslabel('egi32'), sens.label)) > 0.8) - type = 'egi32'; - elseif (sum(ismember(sens.label, senslabel('eeg1005'))) > 10) % Otherwise it's not even worth recognizing - type = 'ext1020'; - else - type = 'electrode'; - end - - elseif islabel - % look only at the channel labels - if (mean(ismember(senslabel('ctf275'), sens.label)) > 0.8) - type = 'ctf275'; - elseif (mean(ismember(senslabel('ctfheadloc'), sens.label)) > 0.8) % look at the head localization channels - type = 'ctf275'; - elseif (mean(ismember(senslabel('ctf151'), sens.label)) > 0.8) - type = 'ctf151'; - elseif (mean(ismember(senslabel('ctf64'), sens.label)) > 0.8) - type = 'ctf64'; - elseif (mean(ismember(senslabel('ctf275_planar'), sens.label)) > 0.8) - type = 'ctf275_planar'; - elseif (mean(ismember(senslabel('ctf151_planar'), sens.label)) > 0.8) - type = 'ctf151_planar'; - elseif (mean(ismember(senslabel('bti248'), sens.label)) > 0.8) - type = 'bti248'; - elseif (mean(ismember(senslabel('bti148'), sens.label)) > 0.8) - type = 'bti148'; - elseif (mean(ismember(senslabel('bti248_planar'), sens.label)) > 0.8) - type = 'bti248_planar'; - elseif (mean(ismember(senslabel('bti148_planar'), sens.label)) > 0.8) - type = 'bti148_planar'; - elseif (mean(ismember(senslabel('itab153'), sens.label)) > 0.8) - type = 'itab153'; - elseif (mean(ismember(senslabel('itab153_planar'), sens.label)) > 0.8) - type = 'itab153_planar'; - elseif (mean(ismember(senslabel('neuromag306'), sens.label)) > 0.8) - type = 'neuromag306'; - elseif (mean(ismember(senslabel('neuromag306alt'),sens.label)) > 0.8) % an alternative set without spaces in the name - type = 'neuromag306'; - elseif (mean(ismember(senslabel('neuromag122'), sens.label)) > 0.8) - type = 'neuromag122'; - elseif (mean(ismember(senslabel('neuromag122alt'),sens.label)) > 0.8) % an alternative set without spaces in the name - type = 'neuromag122'; - elseif (mean(ismember(senslabel('biosemi256'), sens.label)) > 0.8) - type = 'biosemi256'; - elseif (mean(ismember(senslabel('biosemi128'), sens.label)) > 0.8) - type = 'biosemi128'; - elseif (mean(ismember(senslabel('biosemi64'), sens.label)) > 0.8) - type = 'biosemi64'; - elseif (mean(ismember(senslabel('egi256'), sens.label)) > 0.8) - type = 'egi256'; - elseif (mean(ismember(senslabel('egi128'), sens.label)) > 0.8) - type = 'egi128'; - elseif (mean(ismember(senslabel('egi64'), sens.label)) > 0.8) - type = 'egi64'; - elseif (mean(ismember(senslabel('egi32'), sens.label)) > 0.8) - type = 'egi32'; - elseif (sum(ismember(sens.label, senslabel('eeg1005'))) > 10) % Otherwise it's not even worth recognizing - type = 'ext1020'; - elseif any(ismember(senslabel('btiref'), sens.label)) - type = 'bti'; % it might be 148 or 248 channels - elseif any(ismember(senslabel('ctfref'), sens.label)) - type = 'ctf'; % it might be 151 or 275 channels - end - - end % look at label, ori and/or pnt -end % if isfield(sens, 'type') - -if ~isempty(desired) - % return a boolean flag - switch desired - case 'eeg' - type = any(strcmp(type, {'eeg' 'electrode' 'biosemi64' 'biosemi128' 'biosemi256' 'egi32' 'egi64' 'egi128' 'egi256' 'ext1020'})); - case 'biosemi' - type = any(strcmp(type, {'biosemi64' 'biosemi128' 'biosemi256'})); - case 'egi' - type = any(strcmp(type, {'egi64' 'egi128' 'egi256'})); - case 'meg' - type = any(strcmp(type, {'meg' 'magnetometer' 'ctf' 'bti' 'ctf151' 'ctf275' 'ctf151_planar' 'ctf275_planar' 'neuromag122' 'neuromag306' 'bti148' 'bti148_planar' 'bti248' 'bti248_planar' 'yokogawa160' 'yokogawa160_planar'})); - case 'ctf' - type = any(strcmp(type, {'ctf' 'ctf151' 'ctf275' 'ctf151_planar' 'ctf275_planar'})); - case 'bti' - type = any(strcmp(type, {'bti' 'bti148' 'bti148_planar' 'bti248' 'bti248_planar'})); - case 'neuromag' - type = any(strcmp(type, {'neuromag122' 'neuromag306'})); - case 'yokogawa' - type = any(strcmp(type, {'yokogawa160' 'yokogawa160_planar'})); - case 'itab' - type = any(strcmp(type, {'itab153' 'itab153_planar'})); - case 'meg_axial' - % note that neuromag306 is mixed planar and axial - type = any(strcmp(type, {'magnetometer' 'neuromag306' 'ctf151' 'ctf275' 'bti148' 'bti248' 'yokogawa160'})); - case 'meg_planar' - % note that neuromag306 is mixed planar and axial - type = any(strcmp(type, {'neuromag122' 'neuromag306' 'ctf151_planar' 'ctf275_planar' 'bti148_planar' 'bti248_planar' 'yokogawa160_planar'})); - otherwise - type = any(strcmp(type, desired)); - end % switch desired -end % detemine the correspondence to the desired type - -% remember the current input and output arguments, so that they can be -% reused on a subsequent call in case the same input argument is given -current_argout = {type}; -if isempty(previous_argin) - previous_argin = current_argin; - previous_argout = current_argout; -end - -return % senstype main() diff --git a/external/fieldtrip/private/setsubfield.m b/external/fieldtrip/private/setsubfield.m deleted file mode 100644 index 8b53257..0000000 --- a/external/fieldtrip/private/setsubfield.m +++ /dev/null @@ -1,36 +0,0 @@ -function [s] = setsubfield(s, f, v); - -% SETSUBFIELD sets the contents of the specified field to a specified value -% just like the standard Matlab SETFIELD function, except that you can also -% specify nested fields using a '.' in the fieldname. The nesting can be -% arbitrary deep. -% -% Use as -% s = setsubfield(s, 'fieldname', value) -% or as -% s = setsubfield(s, 'fieldname.subfieldname', value) -% -% See also SETFIELD, GETSUBFIELD, ISSUBFIELD - -% Copyright (C) 2005, Robert Oostenveld -% -% $Log: setsubfield.m,v $ -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.1 2005/02/08 09:30:18 roboos -% new implementations to make it easier to work with nested structures -% - -if ~isstr(f) - error('incorrect input argument for fieldname'); -end - -t = {}; -while (1) - [t{end+1}, f] = strtok(f, '.'); - if isempty(f) - break - end -end -s = setfield(s, t{:}, v); diff --git a/external/fieldtrip/private/shiftpredict.m b/external/fieldtrip/private/shiftpredict.m new file mode 100644 index 0000000..5a39f3a --- /dev/null +++ b/external/fieldtrip/private/shiftpredict.m @@ -0,0 +1,261 @@ +function [prb, cohobs, mcohrnd] = shiftpredict(cfg, dat, datindx, refindx, trltapcnt); + +% SHIFTPREDICT implements a shift-predictor for testing significance +% of coherence within a single condition. This function is a subfunction +% for SOURCESTATISTICS_SHIFTPREDICT and FREQSTATISTICS_SHIFTPREDICT. +% +% cfg.method +% cfg.numrandomization +% cfg.method +% cfg.method +% cfg.loopdim +% cfg.feedback +% cfg.method +% cfg.loopdim +% cfg.correctm +% cfg.tail + +% TODO this function should be reimplemented as statfun_shiftpredict for the general statistics framework + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: shiftpredict.m 952 2010-04-21 18:29:51Z roboos $ + +nsgn = size(dat,1); +ntap = size(dat,2); % total number of tapers over all trials +nfrq = size(dat,3); + +if nargin<4 + % assume that each trial consists of a single taper only + ntrl = size(dat,2); + trltapcnt = ones(1,ntrl); + fprintf('assuming one taper per trial\n'); +else + % each trial contains multiple tapers + ntrl = length(trltapcnt); + trltapcnt = trltapcnt(:)'; + fprintf('number of tapers varies from %d to %d\n', min(trltapcnt), max(trltapcnt)); +end + +% allocate memory to hold the probabilities +if version('-release')>=14 + prb_pos = zeros(length(refindx),length(datindx),nfrq, 'single'); + prb_neg = zeros(length(refindx),length(datindx),nfrq, 'single'); +else + prb_pos = zeros(length(refindx),length(datindx),nfrq); + prb_neg = zeros(length(refindx),length(datindx),nfrq); +end + +% compute the power per taper, per trial, and in total +pow_tap = (abs(dat).^2); +pow_trl = zeros(nsgn,ntrl,nfrq); +for i=1:ntrl + % this is the taper selection if the number of tapers per trial is different + tapbeg = 1 + sum([0 trltapcnt(1:(i-1))]); + tapend = sum([0 trltapcnt(1:(i ))]); + % this would be the taper selection if the number of tapers per trial is identical + % tapbeg = 1 + (i-1)*ntap; + % tapend = (i )*ntap; + % average the power per trial over the tapers in that trial + pow_trl(:,i,:) = mean(pow_tap(:,tapbeg:tapend,:),2); +end +pow_tot = reshape(mean(pow_trl,2), nsgn, nfrq); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% normalise the data, also see the COMPUTECOH subfunction +switch cfg.method +case {'abscoh', 'imagcoh', 'absimagcoh', 'atanh', 'atanh_randphase'} + % normalise, so that the complex conjugate multiplication immediately results in coherence + if ~all(trltapcnt==trltapcnt(1)) + error('all trials should have the same number of tapers'); + end + for i=1:nsgn + for k=1:nfrq + dat(i,:,k) = dat(i,:,k) ./ sqrt(pow_tot(i,k)*ntrl*trltapcnt(1)); + end + end + +case {'amplcorr', 'absamplcorr'} + % normalize so that the multiplication immediately results in correlation + % this uses the amplitude, which is the sqrt of the power per trial + dat = sqrt(pow_trl); + % each signal should have zero mean + fa = reshape(mean(dat,2), nsgn, nfrq); % mean over trials + for i=1:ntrl + dat(:,i,:) = (dat(:,i,:) - fa); + end + % each signal should have unit variance + fs = reshape(sqrt(sum(dat.^2,2)/ntrl), nsgn, nfrq); % standard deviation over trials + for i=1:ntrl + dat(:,i,:) = dat(:,i,:)./fs; + end + % also normalize for the number of trials + dat = dat./sqrt(ntrl); + +otherwise + error('unknown method for shift-predictor') +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% create the random shuffling index vectors +nrnd = cfg.numrandomization; +randsel = []; +switch cfg.method +case {'abscoh', 'imagcoh', 'absimagcoh', 'atanh'} + for i=1:nrnd + % the number of tapers is identical for each trial + randsel(i,:) = randblockshift(1:sum(trltapcnt), trltapcnt(1)); + end +case {'amplcorr', 'absamplcorr'} + for i=1:nrnd + randsel(i,:) = randperm(ntrl); + end +case {'atanh_randphase'}, + for i=1:nrnd + rndphs = exp(j.*2.*pi.*rand(length(unique(cfg.origtrl)))); + randsel(i,:) = rndphs(cfg.origtrl); + end +end + +% select the subset of reference signals +if all(refindx(:)'==1:size(dat,1)) + % only make a shallow copy to save memory + datref = dat; +else + % make a deep copy of the selected data + datref = dat(refindx,:,:); +end + +% select the subset of target signals +if all(datindx(:)'==1:size(dat,1)) + % only make a shallow copy to save memory + dat = dat; +else + % make a deep copy of the selected data + dat = dat(datindx,:,:); +end + +% compute the observed coherence +cohobs = computecoh(datref, dat, cfg.method, cfg.loopdim); +mcohrnd = zeros(size(cohobs)); + +progress('init', cfg.feedback, 'Computing shift-predicted coherence'); +for i=1:nrnd + progress(i/nrnd, 'Computing shift-predicted coherence %d/%d\n', i, nrnd); + % randomize the reference signal and re-compute coherence + if all(isreal(randsel(i,:))), + datrnd = datref(:,randsel(i,:),:); + else + datrnd = datref.*conj(repmat(randsel(i,:), [size(datref,1) 1 size(datref,3)])); + end + cohrnd = computecoh(datrnd, dat, cfg.method, cfg.loopdim); + mcohrnd = cohrnd + mcohrnd; + % compare the observed coherence with the randomized one + if strcmp(cfg.correctm, 'yes') + prb_pos = prb_pos + (cohobsmin(cohrnd(:))); + else + prb_pos = prb_pos + (cohobscohrnd); + end +end +progress('close'); +mcohrnd = mcohrnd./nrnd; + +if cfg.tail==1 + clear prb_neg % not needed any more, free some memory + prb = prb_pos./nrnd; +elseif cfg.tail==-1 + clear prb_pos % not needed any more, free some memory + prb = prb_neg./nrnd; +else + prb_neg = prb_neg./nrnd; + prb_pos = prb_pos./nrnd; + % for each observation select the tail that corresponds with the lowest probability + prb = min(prb_neg, prb_pos); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +% this assumes that the data is properly normalised +% and assumes that all trials have the same number of tapers +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function coh = computecoh(datref, dat, method, loopdim) +nref = size(datref,1); +nsgn = size(dat,1); +nfrq = size(dat,3); +coh = zeros(nref,nsgn,nfrq); +switch loopdim +case 3 + % for each frequency, simultaneously compute coherence between all reference and target signals + for i=1:nfrq + switch method + case 'abscoh' + coh(:,:,i) = abs( datref(:,:,i) * dat(:,:,i)'); + case 'imagcoh' + coh(:,:,i) = imag(datref(:,:,i) * dat(:,:,i)'); + case 'absimagcoh' + coh(:,:,i) = abs(imag(datref(:,:,i) * dat(:,:,i)')); + case {'atanh' 'atanh_randphase'} + coh(:,:,i) = atanh(abs(datref(:,:,i)* dat(:,:,i)')); + case 'amplcorr' + coh(:,:,i) = datref(:,:,i) * dat(:,:,i)'; + case 'absamplcorr' + coh(:,:,i) = abs( datref(:,:,i) * dat(:,:,i)'); + otherwise + error('unsupported method'); + end + end + +case 1 + % for each reference and target signal, simultaneously compute coherence over all frequencies + for i=1:nref + for k=1:nsgn + switch method + case 'abscoh' + coh(i,k,:) = abs( sum(datref(i,:,:) .* conj(dat(k,:,:)), 2)); + case 'imagcoh' + coh(i,k,:) = imag(sum(datref(i,:,:) .* conj(dat(k,:,:)), 2)); + case 'absimagcoh' + coh(i,k,:) = abs(imag(sum(datref(i,:,:) .* conj(dat(k,:,:)), 2))); + case {'atanh' 'atanh_randphase'} + coh(i,k,:) = atanh(abs(sum(datref(i,:,:).* conj(dat(k,:,:)), 2))); + case 'amplcorr' + coh(i,k,:) = sum(datref(i,:,:) .* conj(dat(k,:,:)), 2); + case 'absamplcorr' + coh(i,k,:) = abs( sum(datref(i,:,:) .* conj(dat(k,:,:)), 2)); + otherwise + error('unsupported method'); + end + end + end +otherwise + error('unsupported loopdim'); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION that shuffles in blocks +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [out] = randblockshift(n, k); +n = n(:); +nbin = length(n)/k; +n = reshape(n, [k nbin]); +n = n(:,randperm(nbin)); +out = n(:); + diff --git a/external/fieldtrip/private/sine_taper.m b/external/fieldtrip/private/sine_taper.m index 8b0dcb9..8c9b8e5 100644 --- a/external/fieldtrip/private/sine_taper.m +++ b/external/fieldtrip/private/sine_taper.m @@ -6,10 +6,23 @@ % Copyright (C) 2006, Tom Holroyd % -% $Log: sine_taper.m,v $ -% Revision 1.1 2006/03/06 09:28:38 roboos -% new implementation by Tom Holroyd +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: sine_taper.m 952 2010-04-21 18:29:51Z roboos $ if nargin < 2 error('usage: sine_taper(n, k)'); diff --git a/external/fieldtrip/private/singleplotER.m b/external/fieldtrip/private/singleplotER.m deleted file mode 100644 index fd94614..0000000 --- a/external/fieldtrip/private/singleplotER.m +++ /dev/null @@ -1,469 +0,0 @@ -function [cfg] = singleplotER(cfg, varargin) - -% singleplotER plots the event-related fields or potentials of a single channel -% or the average over multiple channels. Multiple datasets can be overlayed. -% -% Use as: -% sinlgeplotER(cfg, data) -% singleplotER(cfg, data1, data2, ..., dataN) -% -% The data can be an ERP/ERF produced by TIMELOCKANALYSIS, a powerspectrum -% produced by FREQANALYSIS or a coherencespectrum produced by FREQDESCRIPTIVES. -% If you specify multiple datasets they must contain the same channels, etc. -% -% The configuration can have the following parameters: -% cfg.xparam = field to be plotted on x-axis (default depends on data.dimord) -% 'time' or 'freq' -% cfg.zparam = field to be plotted on y-axis (default depends on data.dimord) -% 'avg', 'powspctrm' or 'cohspctrm' -% cfg.maskparameter = field in the first dataset to be used for opacity masking of data -% (not possible for mean over multiple channels) -% cfg.xlim = 'maxmin' or [xmin xmax] (default = 'maxmin') -% cfg.ylim = 'maxmin' or [ymin ymax] (default = 'maxmin') -% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), -% see CHANNELSELECTION for details -% cfg.cohrefchannel = name of reference channel for visualising coherence, can be 'gui' -% cfg.baseline = 'yes','no' or [time1 time2] (default = 'no'), see TIMELOCKBASELINE or FREQBASELINE -% cfg.baselinetype = 'absolute' or 'relative' (default = 'absolute') -% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') -% cfg.fontsize = font size of title (default = 8) -% cfg.interactive = Interactive plot 'yes' or 'no' (default = 'no') -% In a interactive plot you can select areas and produce a new -% interactive plot when a selected area is clicked. Multiple areas -% can be selected by holding down the SHIFT key. -% cfg.renderer = 'painters', 'zbuffer',' opengl' or 'none' (default = 'opengl') -% -% See also: -% singleplotTFR, multiplotER, multiplotTFR, topoplotER, topoplotTFR. - -% Undocumented local options: -% cfg.GraphCol -% cfg.graphcolor -% -% This function depends on TIMELOCKBASELINE which has the following options: -% cfg.baseline, documented -% cfg.channel -% cfg.blcwindow -% cfg.previous -% cfg.version -% -% This function depends on FREQBASELINE which has the following options: -% cfg.baseline, documented -% cfg.baselinetype - -% Copyright (C) 2003-2006, Ole Jensen -% -% $Log: singleplotER.m,v $ -% Revision 1.41 2009/07/14 13:51:31 roboos -% some small changes related to the new interactive data selection -% -% Revision 1.40 2009/07/14 13:21:09 roboos -% changed the interactive plotting: instead of using plotSelection it now uses the selection function from the new plotting module (select_range and select_channel) and uses a local subfunction to update the cfg and call the next figure -% -% Revision 1.39 2009/07/13 13:25:52 crimic -% inserted new plotting tool functions -% -% Revision 1.38 2009/06/17 13:44:52 roboos -% cleaned up help -% -% Revision 1.37 2009/05/12 18:21:37 roboos -% added handling of cfg.cohrefchannel='gui' for manual/interactive selection -% -% Revision 1.36 2009/02/26 10:52:12 ingnie -% made 'maxmin' scaling of zparam according to xlim -% -% Revision 1.35 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.34 2008/12/16 14:59:12 sashae -% plot functions can now give cfg as output -% added checkconfig to start and end of function, configtracking possible -% -% Revision 1.33 2008/12/16 13:17:05 sashae -% replaced backward compatibility code by call to checkconfig -% removed obsolete subfunction pwrspctm2cohspctrm -% -% Revision 1.32 2008/11/28 22:08:19 sashae -% allow averaging over rpt/subj also for other fields than zparam=powspctrm (thanks to Jurrian) -% -% Revision 1.31 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.30 2008/01/29 19:43:33 sashae -% added option for trial selection; plot functions now also accept data with -% repetitions (either trials or subjects), the avg is computed and plotted -% removed some old code -% -% Revision 1.29 2008/01/03 16:03:02 ingnie -% channel selection per dataset, to allow plotting datasets with different amount -% of channels -% -% Revision 1.28 2007/12/18 15:57:51 ingnie -% Fixed baseline correction. Should depend on xparam not yparam (thanks to Ian). Also not possible for powerspectra , therefore removed changed into warning -% -% Revision 1.27 2007/11/08 12:10:01 ingnie -% fixed cfg.fontsize, wasn't used in making title before -% -% Revision 1.26 2007/06/19 14:01:54 ingnie -% added cfg.maskparameter, changed some white spaces -% -% Revision 1.25 2007/06/05 16:13:33 ingnie -% added dimord rpt_chan_time -% -% Revision 1.24 2007/04/19 10:26:11 roboos -% Added a warning to the "Apply baseline correction" sections. If a user doesn't set yparam, baselining is not applied. (thanks to Doug) -% -% Revision 1.23 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.22 2007/03/27 11:05:19 ingnie -% changed call to fixdimord in call to checkinput -% -% Revision 1.21 2007/01/09 10:41:43 roboos -% Added the option cfg.renderer, default is opengl. Interactive plotting -% on linux/VNC sometimes does not work, using cfg.renderer='painters' -% seems to fix it. -% -% Revision 1.20 2006/10/04 07:10:07 roboos -% updated documentation -% -% Revision 1.19 2006/06/19 11:11:37 roboos -% fixed small bug in the conversion of coherence data: first select labels for the channels, then for the channelcombinations -% -% Revision 1.18 2006/06/07 10:24:34 ingnie -% added error when no channels are selected -% -% Revision 1.17 2006/06/06 16:24:04 ingnie -% replaced cfg.channelindex and cfg.channelname with cfg.channel for consistency -% with other functions -% -% Revision 1.16 2006/05/30 14:18:02 ingnie -% fixed bug that appeared when plotting single channel, updated documentation -% -% Revision 1.15 2006/05/19 15:39:39 ingnie -% fixed bug that appeared when cfg.channelindex is more than one channel -% -% Revision 1.14 2006/05/03 08:12:51 ingnie -% updated documentation -% -% Revision 1.13 2006/04/27 16:01:30 ingnie -% added dimord subj_chan_time -% -% Revision 1.12 2006/04/20 09:58:34 roboos -% updated documentation -% -% Revision 1.11 2006/04/07 23:12:51 chrhes -% changed "clf" to "cla" at the beginning to allow use in conjunction with subplot in matlab -% -% Revision 1.10 2006/03/17 14:47:15 denpas -% Updated documentation. -% -% Revision 1.9 2006/03/17 14:43:10 denpas -% Fixed cfg.yparam / cfg.zparam bug. Either param may now be used to specify -% the y-axis in case of 2D data. Also implemented data.dimord awareness. -% -% Revision 1.8 2006/03/10 09:24:16 jansch -% made a fix in assigning a default to zparam, this has to be cleaned up! -% -% Revision 1.7 2006/03/02 13:54:59 jansch -% fixed multiple small bugs -% -% Revision 1.6 2006/02/28 12:43:15 roboos -% made plotting of coherence consistent between all xxxplotER functions -% made baselining consistent, use cfg.xparam to decide between freqbaseline and timelockbaseline -% -% Revision 1.5 2006/02/27 15:03:03 denpas -% many changes, most important is added interactive functionality -% made data selection consistent between different plot functions -% changed dimord for consistency -% -% Revision 1.3 2005/05/17 17:50:38 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.2 2005/04/17 18:51:05 olejen -% Option colorgraph added -% -% Revision 1.1 2005/04/06 13:59:05 olejen -% Plot EF for a single channel. Modified from multiplotER.m -% -% Revision 1.5 2005/02/07 17:12:00 roboos -% changed handling of layout files (using new function createlayout), now also supports automatic layout creation based on gradiometer/electrode definition in data, updated help, cleaned up indentation -% -% Revision 1.4 2005/01/27 09:31:49 roboos -% applied autoindentation on code, removed many empty lines and spaces, -% replaced layoutfile reading with read_lay, applied doudavs code to all input arguments -% implemented automatic detection of arguments to plot, -% updated help, changed input from p1, p2, p3... to varargin -% -% Revision 1.3 2004/09/24 15:54:54 roboos -% included the suggested improvements by Doug Davidson: added option cfg.cohtargetchannel -% and updated the help -% -% Revision 1.2 2004/09/01 17:59:28 roboos -% added copyright statements to all filed -% added cfg.version to all functions that give configuration in their output -% added cfg.previous to all functions with input data containing configuration details -% - -fieldtripdefs - -cfg = checkconfig(cfg, 'trackconfig', 'on'); - -cla - -% for backward compatibility with old data structures -for i=1:length(varargin) - varargin{i} = checkdata(varargin{i}); -end - -% set the defaults: -if ~isfield(cfg,'baseline'), cfg.baseline = 'no'; end -if ~isfield(cfg,'trials'), cfg.trials = 'all'; end -if ~isfield(cfg,'xlim'), cfg.xlim = 'maxmin'; end -if ~isfield(cfg,'ylim'), cfg.ylim = 'maxmin'; end -if ~isfield(cfg,'fontsize'), cfg.fontsize = 8; end -if ~isfield(cfg,'graphcolor') cfg.graphcolor = ['brgkywrgbkywrgbkywrgbkyw'];end -if ~isfield(cfg,'interactive'), cfg.interactive = 'no'; end -if ~isfield(cfg,'renderer'), cfg.renderer = 'opengl'; end -if ~isfield(cfg,'maskparameter'), cfg.maskparameter = []; end - -GRAPHCOLOR = ['k' cfg.graphcolor ]; - -% Set x/y/zparam defaults according to varargin{1}.dimord value: -if strcmp(varargin{1}.dimord, 'chan_time') - if ~isfield(cfg, 'xparam'), cfg.xparam='time'; end - if ~isfield(cfg, 'zparam'), cfg.zparam='avg'; end -elseif strcmp(varargin{1}.dimord, 'chan_freq') - if ~isfield(cfg, 'xparam'), cfg.xparam='freq'; end - if ~isfield(cfg, 'zparam'), cfg.zparam='powspctrm'; end -elseif strcmp(varargin{1}.dimord, 'subj_chan_time') || strcmp(varargin{1}.dimord, 'rpt_chan_time') - tmpcfg = []; - tmpcfg.trials = cfg.trials; - for i=1:(nargin-1) - varargin{i} = timelockanalysis(tmpcfg, varargin{i}); - end - if ~isfield(cfg, 'xparam'), cfg.xparam='time'; end - if ~isfield(cfg, 'zparam'), cfg.zparam='avg'; end -elseif strcmp(varargin{1}.dimord, 'subj_chan_freq') || strcmp(varargin{1}.dimord, 'rpt_chan_freq') - tmpcfg = []; - tmpcfg.trials = cfg.trials; - tmpcfg.jackknife = 'no'; - if isfield(cfg, 'zparam') && strcmp(cfg.zparam,'cohspctrm') - % on the fly computation of coherence spectrum is not supported - elseif isfield(cfg, 'zparam') && ~strcmp(cfg.zparam,'powspctrm') - % freqdesctiptives will only work on the powspctrm field, hence a temporary copy of the data is needed - for i=1:(nargin-1) - tempdata.dimord = varargin{i}.dimord; - tempdata.freq = varargin{i}.freq; - tempdata.label = varargin{i}.label; - tempdata.powspctrm = varargin{i}.(cfg.zparam); - tempdata.cfg = varargin{i}.cfg; - tempdata = freqdescriptives(tmpcfg, tempdata); - varargin{i}.(cfg.zparam) = tempdata.powspctrm; - clear tempdata - end - else - for i=1:(nargin-1) - if isfield(varargin{i}, 'crsspctrm'), varargin{i} = rmfield(varargin{i}, 'crsspctrm'); end % on the fly computation of coherence spectrum is not supported - varargin{i} = freqdescriptives(tmpcfg, varargin{i}); - end - end - if ~isfield(cfg, 'xparam'), cfg.xparam='freq'; end - if ~isfield(cfg, 'zparam'), cfg.zparam='powspctrm'; end -end - -% Make sure cfg.yparam and cfg.zparam become equivalent if only one is defined: -if (isfield(cfg, 'yparam')) && (~isfield(cfg, 'zparam')) - cfg.zparam = cfg.yparam; -elseif (~isfield(cfg, 'yparam')) && (isfield(cfg, 'zparam')) - cfg.yparam = cfg.zparam; -end - -% Old style coherence plotting with cohtargetchannel is no longer supported: -cfg = checkconfig(cfg, 'unused', {'cohtargetchannel'}); - -for k=1:length(varargin) - % Check for unconverted coherence spectrum data: - if (strcmp(cfg.zparam,'cohspctrm')) && (isfield(varargin{k}, 'labelcmb')) - % A reference channel is required: - if ~isfield(cfg,'cohrefchannel'), - error('no reference channel specified'); - end - - if strcmp(cfg.cohrefchannel, 'gui') - % Open a single figure with the channel layout, the user can click on a reference channel - h = clf; - lay = prepare_layout(cfg, varargin{1}); - cfg.layout = lay; - plot_lay(cfg.layout, 'box', false); - title('Select the reference channel by clicking on it...'); - % add the channel information to the figure - info = guidata(h); - info.x = lay.pos(:,1); - info.y = lay.pos(:,2); - info.label = lay.label; - guidata(h, info); - set(gcf, 'WindowButtonUpFcn', {@select_channel, 'callback', {@select_singleplotER, cfg, varargin{:}}}); - return - end - - % Convert 2-dimensional channel matrix to a single dimension: - sel1 = strmatch(cfg.cohrefchannel, varargin{k}.labelcmb(:,2)); - sel2 = strmatch(cfg.cohrefchannel, varargin{k}.labelcmb(:,1)); - fprintf('selected %d channels for coherence\n', length(sel1)+length(sel2)); - varargin{k}.cohspctrm = varargin{k}.cohspctrm([sel1;sel2],:,:); - varargin{k}.label = [varargin{k}.labelcmb(sel1,1);varargin{k}.labelcmb(sel2,2)]; - varargin{k}.labelcmb = varargin{k}.labelcmb([sel1;sel2],:); - varargin{k} = rmfield(varargin{k}, 'labelcmb'); - end - - % Apply baseline correction: - if ~strcmp(cfg.baseline, 'no') - if strcmp(cfg.xparam, 'time') - varargin{k} = timelockbaseline(cfg, varargin{k}); - elseif strcmp(cfg.xparam, 'freq') - warning('Baseline correction not possible for powerspectra'); - else - warning('Baseline not applied, please set cfg.xparam'); - end - end -end - -% Determine x-axis range: -if strcmp(cfg.xlim,'maxmin') - % Find maxmin throughout all varargins: - xmin = []; - xmax = []; - for i=1:length(varargin) - xmin = min([xmin varargin{i}.(cfg.xparam)]); - xmax = max([xmax varargin{i}.(cfg.xparam)]); - end -else - xmin = cfg.xlim(1); - xmax = cfg.xlim(2); -end - -% Pick the channel(s) -if ~isfield(cfg,'channel') - % set the default - cfg.channel = 'all'; - % for backward compatibility - cfg = checkconfig(cfg, 'renamed', {'channelindex', 'channel'}); - cfg = checkconfig(cfg, 'renamed', {'channelname', 'channel'}); -end - -% Convert the layout to Ole's style of variable names: -cfg.GraphCol = GRAPHCOLOR(1); - -hold on; -colorLabels = []; -ymin = []; -ymax = []; - -% Plot one line for each data set: -for k=2:nargin - % Get data matrix: - P = varargin{k-1}.(cfg.zparam); - labels = getfield(varargin{k-1}, 'label'); - - % User colored labels if more than one data set is plotted: - if nargin > 2 - colorLabels = [colorLabels inputname(k) '=' GRAPHCOLOR(k) ' ']; - end - - % select channels - cfg.channel = channelselection(cfg.channel, varargin{k-1}.label); - if isempty(cfg.channel) - error('no channels selected'); - else - chansel = match_str(varargin{k-1}.label, cfg.channel); - end - - % Average across selected channels: - P = squeeze(mean(P(chansel,:), 1)); - - % select mask - if ~isempty(cfg.maskparameter) %&& masking - M = varargin{1}.(cfg.maskparameter); % mask always from only first dataset - M = squeeze(mean(M(chansel,:), 1)); - else - M = []; - end - - % Update ymin and ymax for the current data set: - if strcmp(cfg.ylim, 'maxmin') - ind_xmin = nearest(varargin{k-1}.(cfg.xparam), xmin); - ind_xmax = nearest(varargin{k-1}.(cfg.xparam), xmax); - ymin = min([ymin P(ind_xmin:ind_xmax)]); - ymax = max([ymax P(ind_xmin:ind_xmax)]); - else - ymin = cfg.ylim(1); - ymax = cfg.ylim(2); - end - - style = GRAPHCOLOR(k); - plot_vector(varargin{k-1}.(cfg.xparam), P, 'style', style, 'highlight', M); -end - -% Set xlim and ylim: -xlim([xmin xmax]); -ylim([ymin ymax]); - -% Make the figure interactive -if strcmp(cfg.interactive, 'yes') - set(gcf, 'WindowButtonUpFcn', {@select_range, 'multiple', false, 'yrange', false, 'callback', {@select_topoplotER, cfg, varargin{:}}, 'event', 'WindowButtonUpFcn'}); - set(gcf, 'WindowButtonDownFcn', {@select_range, 'multiple', false, 'yrange', false, 'callback', {@select_topoplotER, cfg, varargin{:}}, 'event', 'WindowButtonDownFcn'}); - set(gcf, 'WindowButtonMotionFcn', {@select_range, 'multiple', false, 'yrange', false, 'callback', {@select_topoplotER, cfg, varargin{:}}, 'event', 'WindowButtonMotionFcn'}); -end - -% Create title text containing channel name(s) and channel number(s): -if length(chansel) == 1 - t = [char(cfg.channel) ' / ' num2str(chansel) ]; -else - t = sprintf('mean(%0s)', join(',', cfg.channel)); -end -h = title(t,'fontsize', cfg.fontsize); - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function t = join(separator,cells) -if isempty(cells) - t = ''; - return; -end -t = char(cells{1}); - -for i=2:length(cells) - t = [t separator char(cells{i})]; -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION which is called by select_channel in case cfg.cohrefchannel='gui' -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function select_singleplotER(label, cfg, varargin) -cfg.cohrefchannel = label; -fprintf('selected cfg.cohrefchannel = ''%s''\n', cfg.cohrefchannel); -p = get(gcf, 'Position'); -f = figure; -set(f, 'Position', p); -singleplotER(cfg, varargin{:}); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION which is called after selecting a time range -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function select_topoplotER(range, cfg, varargin) -cfg.comment = 'auto'; -cfg.yparam = []; -cfg.xlim = range(1:2); -fprintf('selected cfg.xlim = [%f %f]\n', cfg.xlim(1), cfg.xlim(2)); -p = get(gcf, 'Position'); -f = figure; -set(f, 'Position', p); -topoplotER(cfg, varargin{:}); diff --git a/external/fieldtrip/private/singleplotTFR.m b/external/fieldtrip/private/singleplotTFR.m deleted file mode 100644 index d8ac05b..0000000 --- a/external/fieldtrip/private/singleplotTFR.m +++ /dev/null @@ -1,435 +0,0 @@ -function [cfg] = singleplotTFR(cfg, data) - -% singleplotTFR plots the time-frequency representations of power of a -% single channel or the average over multiple channels. -% -% Use as: -% singleplotTFR(cfg,data) -% -% The data can be a time-frequency representation of power that was -% computed using the FREQANALYSIS function. -% -% The configuration can have the following parameters: -% cfg.xparam = field to be plotted on x-axis, e.g. 'time' (default depends on data.dimord) -% cfg.yparam = field to be plotted on y-axis, e.g. 'freq' (default depends on data.dimord) -% cfg.zparam = field to be plotted on y-axis, e.g. 'powspcrtrm' (default depends on data.dimord) -% cfg.maskparameter = field in the data to be used for opacity masking of data -% (not possible for mean over multiple channels) -% cfg.xlim = 'maxmin' or [xmin xmax] (default = 'maxmin') -% cfg.ylim = 'maxmin' or [ymin ymax] (default = 'maxmin') -% cfg.zlim = 'maxmin','absmax' or [zmin zmax] (default = 'maxmin') -% cfg.baseline = 'yes','no' or [time1 time2] (default = 'no'), see FREQBASELINE -% cfg.baselinetype = 'absolute' or 'relative' (default = 'absolute') -% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') -% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), -% see CHANNELSELECTION for details -% cfg.cohrefchannel = name of reference channel for visualising coherence, can be 'gui' -% cfg.fontsize = font size of title (default = 8) -% cfg.colormap = any sized colormap, see COLORMAP -% cfg.colorbar = 'yes', 'no' (default = 'yes') -% cfg.interactive = Interactive plot 'yes' or 'no' (default = 'no') -% In a interactive plot you can select areas and produce a new -% interactive plot when a selected area is clicked. Multiple areas -% can be selected by holding down the SHIFT key. -% cfg.renderer = 'painters', 'zbuffer',' opengl' or 'none' (default = []) -% cfg.masknans = 'yes' or 'no' (default = 'yes') -% -% See also: -% singleplotER, multiplotER, multiplotTFR, topoplotER, topoplotTFR. - -% This function depends on FREQBASELINE which has the following options: -% cfg.baseline, documented -% cfg.baselinetype, documented - -% Copyright (C) 2005-2006, F.C. Donders Centre -% -% $Log: singleplotTFR.m,v $ -% Revision 1.37 2009/07/14 13:52:16 roboos -% changed the interactive plotting: instead of using plotSelection it now uses the selection function from the new plotting module (select_range and select_channel) and uses a local subfunction to update the cfg and call the next figure -% -% Revision 1.36 2009/07/14 13:27:25 roboos -% consistent handling of cfg.renderer, default is to let matlab decide -% -% Revision 1.35 2009/06/17 13:44:52 roboos -% cleaned up help -% -% Revision 1.34 2009/05/12 18:47:23 roboos -% added general suppoprt for cfg.cohrefchannel and -% added handling of cfg.cohrefchannel='gui' for manual/interactive selection -% -% Revision 1.33 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.32 2008/12/16 14:59:12 sashae -% plot functions can now give cfg as output -% added checkconfig to start and end of function, configtracking possible -% -% Revision 1.31 2008/12/16 13:17:06 sashae -% replaced backward compatibility code by call to checkconfig -% removed obsolete subfunction pwrspctm2cohspctrm -% -% Revision 1.30 2008/11/28 16:33:58 sashae -% allow averaging over rpt/subj also for other fields than zparam=powspctrm (thanks to Jurrian) -% -% Revision 1.29 2008/10/28 14:24:05 ingnie -% fixed bug: data.time/freq should be data.(cfg.xparam/yparam) -% -% Revision 1.28 2008/10/27 12:00:02 ingnie -% change imagesc back to uimagesc, plotting with non linearly spaced axis possible now. -% -% Revision 1.27 2008/10/27 10:56:39 ingnie -% temporarily changed back uimagesc to imagesc, because adding of uimage files did not work -% -% Revision 1.26 2008/10/27 10:01:50 ingnie -% switched from using matlabs IMAGESC to UIMAGESC. Now also non linear spaced axis possible. -% Also simplified masking code, which made local variable -masking- unnecessary. -% -% Revision 1.25 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.24 2008/01/29 19:43:33 sashae -% added option for trial selection; plot functions now also accept data with -% repetitions (either trials or subjects), the avg is computed and plotted -% removed some old code -% -% Revision 1.23 2007/06/19 15:57:51 ingnie -% fixed bug in cfg.maskparameter, thanks to Saskia -% -% Revision 1.22 2007/06/19 14:01:54 ingnie -% added cfg.maskparameter, changed some white spaces -% -% Revision 1.21 2007/06/14 12:23:48 ingnie -% added cfg.colormap option -% -% Revision 1.20 2007/04/26 09:58:46 ingnie -% default masknans to 'yes' -% -% Revision 1.19 2007/04/25 17:25:06 ingnie -% added cfg.masknans option -% -% Revision 1.18 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.17 2007/03/27 11:05:19 ingnie -% changed call to fixdimord in call to checkinput -% -% Revision 1.16 2007/01/09 10:41:43 roboos -% Added the option cfg.renderer, default is opengl. Interactive plotting -% on linux/VNC sometimes does not work, using cfg.renderer='painters' -% seems to fix it. -% -% Revision 1.15 2006/10/24 12:09:54 ingnie -% added colorbar yes/no option -% -% Revision 1.14 2006/10/04 07:10:07 roboos -% updated documentation -% -% Revision 1.13 2006/06/07 10:24:34 ingnie -% added error when no channels are selected -% -% Revision 1.12 2006/06/06 16:24:06 ingnie -% replaced cfg.channelindex and cfg.channelname with cfg.channel for consistency -% with other functions -% -% Revision 1.11 2006/05/30 14:18:02 ingnie -% fixed bug that appeared when plotting single channel, updated documentation -% -% Revision 1.10 2006/05/09 17:33:57 ingnie -% fixed bug that appeared when cfg.channelindex is more than one channel -% -% Revision 1.9 2006/05/03 08:12:51 ingnie -% updated documentation -% -% Revision 1.8 2006/04/20 09:57:53 roboos -% changed formatting of the code from DOS into UNIX, i.e. removed the -% -% Revision 1.7 2006/04/07 23:45:23 chrhes -% changed clf to cla at beginning of function to allow use in subplots -% -% Revision 1.6 2006/03/22 18:56:57 jansch -% removed hard-coded selection of the powerspectrum in the to be plotted data -% -% Revision 1.5 2006/03/14 08:09:22 roboos -% added copyrigth and cvs log statement -% - -fieldtripdefs - -cfg = checkconfig(cfg, 'trackconfig', 'on'); - -cla - -% For backward compatibility with old data structures: -data = checkdata(data); - -% Set the defaults: -if ~isfield(cfg,'baseline'), cfg.baseline = 'no'; end -if ~isfield(cfg,'baselinetype'), cfg.baselinetype = 'absolute'; end -if ~isfield(cfg,'trials'), cfg.trials = 'all'; end -if ~isfield(cfg,'xlim'), cfg.xlim = 'maxmin'; end -if ~isfield(cfg,'ylim'), cfg.ylim = 'maxmin'; end -if ~isfield(cfg,'zlim'), cfg.zlim = 'maxmin'; end -if ~isfield(cfg,'fontsize'), cfg.fontsize = 8; end -if ~isfield(cfg,'colorbar'), cfg.colorbar = 'yes'; end -if ~isfield(cfg,'interactive'), cfg.interactive = 'no'; end -if ~isfield(cfg,'renderer'), cfg.renderer = []; end -if ~isfield(cfg,'masknans'), cfg.masknans = 'yes'; end -if ~isfield(cfg,'maskparameter'), cfg.maskparameter = []; end - -% Set x/y/zparam defaults according to data.dimord value: -if strcmp(data.dimord, 'chan_freq_time') - if ~isfield(cfg, 'xparam'), cfg.xparam='time'; end - if ~isfield(cfg, 'yparam'), cfg.yparam='freq'; end - if ~isfield(cfg, 'zparam'), cfg.zparam='powspctrm'; end -elseif strcmp(data.dimord, 'subj_chan_freq_time') || strcmp(data.dimord, 'rpt_chan_freq_time') - if isfield(data, 'crsspctrm'), data = rmfield(data, 'crsspctrm'); end % on the fly computation of coherence spectrum is not supported - tmpcfg = []; - tmpcfg.trials = cfg.trials; - tmpcfg.jackknife = 'no'; - if isfield(cfg, 'zparam') && strcmp(cfg.zparam,'cohspctrm') - % on the fly computation of coherence spectrum is not supported - elseif isfield(cfg, 'zparam') && ~strcmp(cfg.zparam,'powspctrm') - % freqdesctiptives will only work on the powspctrm field, hence a temporary copy of the data is needed - tempdata.dimord = data.dimord; - tempdata.freq = data.freq; - tempdata.time = data.time; - tempdata.label = data.label; - tempdata.powspctrm = data.(cfg.zparam); - tempdata.cfg = data.cfg; - tempdata = freqdescriptives(tmpcfg, tempdata); - data.(cfg.zparam) = tempdata.powspctrm; - clear tempdata - else - data = freqdescriptives(tmpcfg, data); - end - if ~isfield(cfg, 'xparam'), cfg.xparam='time'; end - if ~isfield(cfg, 'yparam'), cfg.yparam='freq'; end - if ~isfield(cfg, 'zparam'), cfg.zparam='powspctrm'; end -end - -% Pick the channel(s) -if ~isfield(cfg,'channel') - % set the default - cfg.channel = 'all'; - % for backward compatibility - cfg = checkconfig(cfg, 'renamed', {'channelindex', 'channel'}); - cfg = checkconfig(cfg, 'renamed', {'channelname', 'channel'}); -end - -% Check for unconverted coherence spectrum data -if (strcmp(cfg.zparam,'cohspctrm')) && (isfield(data, 'labelcmb')) - % A reference channel is required: - if ~isfield(cfg,'cohrefchannel'), - error('no reference channel specified'); - end - - if strcmp(cfg.cohrefchannel, 'gui') - % Open a single figure with the channel layout, the user can click on a reference channel - h = clf; - lay = prepare_layout(cfg, data); - cfg.layout = lay; - plot_lay(lay, 'box', false); - title('Select the reference channel by clicking on it...'); - % add the channel information to the figure - info = guidata(h); - info.x = lay.pos(:,1); - info.y = lay.pos(:,2); - info.label = lay.label; - guidata(h, info); - set(gcf, 'WindowButtonUpFcn', {@select_channel, 'callback', {@select_singleplotTFR, cfg, data}}); - return - end - - % Convert 2-dimensional channel matrix to a single dimension: - sel1 = strmatch(cfg.cohrefchannel, data.labelcmb(:,2)); - sel2 = strmatch(cfg.cohrefchannel, data.labelcmb(:,1)); - fprintf('selected %d channels for coherence\n', length(sel1)+length(sel2)); - data.cohspctrm = data.cohspctrm([sel1;sel2],:,:); - data.label = [data.labelcmb(sel1,1);data.labelcmb(sel2,2)]; - data.labelcmb = data.labelcmb([sel1;sel2],:); - data = rmfield(data, 'labelcmb'); -end - -cfg.channel = channelselection(cfg.channel, data.label); -if isempty(cfg.channel) - error('no channels selected'); -else - chansel = match_str(data.label, cfg.channel); -end - -% cfg.maskparameter only possible for single channel -if length(chansel) > 1 && ~isempty(cfg.maskparameter) - warning('no masking possible for average over multiple channels -> cfg.maskparameter cleared') - cfg.maskparameter = []; -end - -% Apply baseline correction: -if ~strcmp(cfg.baseline, 'no') - data = freqbaseline(cfg, data); -end - -% Get physical x-axis range: -if strcmp(cfg.xlim,'maxmin') - xmin = min(data.(cfg.xparam)); - xmax = max(data.(cfg.xparam)); -else - xmin = cfg.xlim(1); - xmax = cfg.xlim(2); -end - -% Find corresponding x-axis bins: -xidc = find(data.(cfg.xparam) >= xmin & data.(cfg.xparam) <= xmax); - -% Align physical x-axis range to the array bins: -xmin = data.(cfg.xparam)(xidc(1)); -xmax = data.(cfg.xparam)(xidc(end)); - -% Get physical y-axis range: -if strcmp(cfg.ylim,'maxmin') - ymin = min(data.(cfg.yparam)); - ymax = max(data.(cfg.yparam)); -else - ymin = cfg.ylim(1); - ymax = cfg.ylim(2); -end - -% Find corresponding y-axis bins: -yidc = find(data.(cfg.yparam) >= ymin & data.(cfg.yparam) <= ymax); - -% Align physical y-axis range to the array bins: -ymin = data.(cfg.yparam)(yidc(1)); -ymax = data.(cfg.yparam)(yidc(end)); - -% Get TFR data averaged across selected channels, within the selected x/y-range: -dat = getsubfield(data, cfg.zparam); -TFR = squeeze(mean(dat(chansel,yidc,xidc), 1)); -if ~isempty(cfg.maskparameter) - mas = getsubfield(data, cfg.maskparameter); - mdata = squeeze(mas(chansel,yidc,xidc)); -end - -% Get physical z-axis range (color axis): -if strcmp(cfg.zlim,'maxmin') - zmin = min(TFR(:)); - zmax = max(TFR(:)); -elseif strcmp(cfg.zlim,'absmax') - zmin = -max(abs(TFR(:))); - zmax = max(abs(TFR(:))); -else - zmin = cfg.zlim(1); - zmax = cfg.zlim(2); -end - -% test if X and Y are linearly spaced (to within 10^-12): % FROM UIMAGE -x = data.(cfg.xparam)(xidc); -y = data.(cfg.yparam)(yidc); -dx = min(diff(x)); % smallest interval for X -dy = min(diff(y)); % smallest interval for Y -evenx = all(abs(diff(x)/dx-1)<1e-12); % true if X is linearly spaced -eveny = all(abs(diff(y)/dy-1)<1e-12); % true if Y is linearly spaced - -% masking only possible for evenly spaced axis -if strcmp(cfg.masknans, 'yes') && (~evenx || ~eveny) - warning('(one of the) axis are not evenly spaced -> nans cannot be masked out -> cfg.masknans is set to ''no'';') - cfg.masknans = 'no'; -end -if ~isempty(cfg.maskparameter) && (~evenx || ~eveny) - warning('(one of the) axis are not evenly spaced -> no masking possible -> cfg.maskparameter cleared') - cfg.maskparameter = []; -end - -% Draw plot: -hold on; -h = uimagesc(data.(cfg.xparam)(xidc), data.(cfg.yparam)(yidc), TFR, [zmin,zmax]); -% Mask Nan's and maskfield -if isequal(cfg.masknans,'yes') && isempty(cfg.maskparameter) - mask = ~isnan(TFR); - mask = double(mask); - set(h,'AlphaData',mask, 'AlphaDataMapping', 'scaled'); - alim([0 1]); -elseif isequal(cfg.masknans,'yes') && ~isempty(cfg.maskparameter) - mask = ~isnan(TFR); - mask = mask .* mdata; - mask = double(mask); - set(h,'AlphaData',mask, 'AlphaDataMapping', 'scaled'); - alim([0 1]); -elseif isequal(cfg.masknans,'no') && ~isempty(cfg.maskparameter) - mask = mdata; - mask = double(mask); - set(h,'AlphaData',mask, 'AlphaDataMapping', 'scaled'); - alim([0 1]); -end -axis xy; - -% set colormap -if isfield(cfg,'colormap') - if size(cfg.colormap,2)~=3, error('singleplotTFR(): Colormap must be a n x 3 matrix'); end - colormap(cfg.colormap); -end; - -if isequal(cfg.colorbar,'yes') - colorbar; -end - -% Make the figure interactive: -if strcmp(cfg.interactive, 'yes') - set(gcf, 'WindowButtonUpFcn', {@select_range, 'multiple', false, 'callback', {@select_topoplotTFR, cfg, data}, 'event', 'WindowButtonUpFcn'}); - set(gcf, 'WindowButtonDownFcn', {@select_range, 'multiple', false, 'callback', {@select_topoplotTFR, cfg, data}, 'event', 'WindowButtonDownFcn'}); - set(gcf, 'WindowButtonMotionFcn', {@select_range, 'multiple', false, 'callback', {@select_topoplotTFR, cfg, data}, 'event', 'WindowButtonMotionFcn'}); -end - -% Create title text containing channel name(s) and channel number(s): -if length(chansel) == 1 - t = [char(cfg.channel) ' / ' num2str(chansel) ]; -else - t = sprintf('mean(%0s)', join(',', cfg.channel)); -end -h = title(t,'fontsize', cfg.fontsize); - -axis tight; -hold off; - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function t = join(separator,cells) -if isempty(cells) - t = ''; - return; -end -t = char(cells{1}); - -for i=2:length(cells) - t = [t separator char(cells{i})]; -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION which is called by select_channel in case cfg.cohrefchannel='gui' -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function select_singleplotTFR(label, cfg, varargin) -cfg.cohrefchannel = label; -fprintf('selected cfg.cohrefchannel = ''%s''\n', cfg.cohrefchannel); -p = get(gcf, 'Position'); -f = figure; -set(f, 'Position', p); -singleplotTFR(cfg, varargin{:}); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION which is called after selecting a time range -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function select_topoplotTFR(range, cfg, varargin) -cfg.comment = 'auto'; -cfg.xlim = range(1:2); -cfg.ylim = range(3:4); -fprintf('selected cfg.xlim = [%f %f]\n', cfg.xlim(1), cfg.xlim(2)); -fprintf('selected cfg.ylim = [%f %f]\n', cfg.ylim(1), cfg.ylim(2)); -p = get(gcf, 'Position'); -f = figure; -set(f, 'Position', p); -topoplotER(cfg, varargin{:}); diff --git a/external/fieldtrip/private/sliceinterp.m b/external/fieldtrip/private/sliceinterp.m deleted file mode 100644 index 91f22a5..0000000 --- a/external/fieldtrip/private/sliceinterp.m +++ /dev/null @@ -1,548 +0,0 @@ -function [outim]=sliceinterp(cfg, ininterp) - -% SLICEINTERP plots a 2D-montage of source reconstruction and anatomical MRI -% after these have been interpolated onto the same grid. -% -% Use as -% sliceinterp(cfg, interp) -% or -% [rgbimage] = sliceinterp(cfg, interp), rgbimage is the monatage image -% -% where interp is the output of sourceinterpolate and cfg is a structure -% with any of the following fields: -% -% cfg.funparameter string with the functional parameter of interest (default = 'source') -% cfg.maskparameter parameter used as opacity mask (default = 'none') -% cfg.clipmin value or 'auto' (clipping of source data) -% cfg.clipmax value or 'auto' (clipping of source data) -% cfg.clipsym 'yes' or 'no' (default) symmetrical clipping -% cfg.colormap colormap for source overlay (default is jet(128)) -% cfg.colmin source value mapped to the lowest color (default = 'auto') -% cfg.colmax source value mapped to the highest color (default = 'auto') -% cfg.maskclipmin value or 'auto' (clipping of mask data) -% cfg.maskclipmax value or 'auto' (clipping of mask data) -% cfg.maskclipsym 'yes' or 'no' (default) symmetrical clipping -% cfg.maskmap opacitymap for source overlay -% (default is linspace(0,1,128)) -% cfg.maskcolmin mask value mapped to the lowest opacity, i.e. -% completely transparent (default ='auto') -% cfg.maskcolmin mask value mapped to the highest opacity, i.e. -% non-transparent (default = 'auto') -% cfg.alpha value between 0 and 1 or 'adaptive' (default) -% cfg.nslices integer value, default is 20 -% cfg.dim integer value, default is 3 (dimension to slice) -% cfg.spacemin 'auto' (default) or integer (first slice position) -% cfg.spacemax 'auto' (default) or integer (last slice position) -% cfg.resample integer value, default is 1 (for resolution reduction) -% cfg.rotate number of ccw 90 deg slice rotations (default = 0) -% cfg.title optional title (default is '') -% cfg.whitebg 'yes' or 'no' (default = 'yes') -% cfg.flipdim flip data along the sliced dimension, 'yes' or 'no' -% (default = 'no') -% cfg.marker [Nx3] array defining N marker positions to display -% cfg.markersize radius of markers (default = 5); -% cfg.markercolor [1x3] marker color in RGB (default = [1 1 1], i.e. white) -% cfg.interactive 'yes' or 'no' (default), interactive coordinates -% and source values -% -% if cfg.alpha is set to 'adaptive' the opacity of the source overlay -% linearly follows the source value: maxima are opaque and minima are -% transparent. -% -% if cfg.spacemin and/or cfg.spacemax are set to 'auto' the sliced -% space is automatically restricted to the evaluated source-space -% -% if cfg.colmin and/or cfg.colmax are set to 'auto' the colormap is mapped -% to source values the following way: if source values are either all -% positive or all negative the colormap is mapped to from -% min(source) to max(source). If source values are negative and positive -% the colormap is symmetrical mapped around 0 from -max(abs(source)) to -% +max(abs(source)). -% -% If cfg.maskparameter specifies a parameter to be used as an opacity mask -% cfg.alpha is not used. Instead the mask values are maped to an opacitymap -% that can be specified using cfg.maskmap. The mapping onto that -% opacitymap is controlled as for the functional data using the -% corresponding clipping and min/max options. -% -% if cfg.whitebg is set to 'yes' the function estimates the head volume and -% displays a white background outside the head, which can save a lot of black -% printer toner. -% -% if cfg.interactive is set to 'yes' a button will be displayed for -% interactive data evaluation and coordinate reading. After clicking the -% button named 'coords' you can click on any position in the slice montage. -% After clicking these coordinates and their source value are displayed in -% a text box below the button. The coordinates correspond to indeces in the -% input data array: -% -% f = interp.source(coord_1,coord_2,coord_3) -% -% The coordinates are not affected by any transformations used for displaying -% the data such as cfg.dim, cfg.rotate,cfg.flipdim or cfg.resample. - -% Copyright (C) 2004, Markus Siegel, markus.siegel@fcdonders.kun.nl -% -% $Log: sliceinterp.m,v $ -% Revision 1.15 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.14 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.13 2007/03/30 17:05:40 ingnie -% checkinput; only proceed when input data is allowed datatype -% -% Revision 1.12 2006/09/13 06:46:13 roboos -% ensure that functional and mask data are double (problem if one is logical) -% -% Revision 1.11 2006/05/31 07:07:15 roboos -% updated documentation -% -% Revision 1.10 2006/01/05 13:28:43 roboos -% changed parameterselection subfunction, select the first element from the cell-array -% -% Revision 1.9 2005/09/02 10:16:11 roboos -% fixed 3D reshape of functional data, which accidentaly broke in yesterdays change -% changed getfield to getsubfield for cfg.maskparameter -% -% Revision 1.8 2005/09/01 09:48:44 roboos -% switched to using parameterselection subfunction -% -% Revision 1.7 2005/05/17 17:50:38 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.6 2005/02/08 13:54:11 roboos -% added 3D reshape around functional, anatomical and mask volume -% -% Revision 1.5 2005/02/08 12:25:29 roboos -% changed handling of subfields to obtain functional data -% -% Revision 1.4 2004/10/19 11:58:41 roboos -% added support for a string as cfg.colormap -% -% Revision 1.3 2004/08/31 10:03:56 roboos -% added support for new volume layout of source, with source.avg.pow etc. -% -% Revision 1.2 2004/08/25 16:31:41 marsie -% initial CVS commit -% - default of cfg.whitebg is set to 'yes' -% - bugfix for cfg.colormap -% - reformatted help -% - -fieldtripdefs - -% check if the input data is valid for this function -ininterp = checkdata(ininterp, 'datatype', 'volume', 'feedback', 'yes'); - -if ~isfield(cfg, 'clipmin'); cfg.clipmin = 'auto'; end -if ~isfield(cfg, 'clipmax'); cfg.clipmax = 'auto'; end -if ~isfield(cfg, 'clipsym'); cfg.clipsym = 'no'; end -if ~isfield(cfg, 'alpha'); cfg.alpha = 'adaptive'; end -if ~isfield(cfg, 'nslices'); cfg.nslices = 20; end -if ~isfield(cfg, 'dim'); cfg.dim = 3; end -if ~isfield(cfg, 'colormap'); cfg.colormap = jet(128); end -if ~isfield(cfg, 'spacemin'); cfg.spacemin = 'auto'; end -if ~isfield(cfg, 'spacemax'); cfg.spacemax = 'auto'; end -if ~isfield(cfg, 'colmin'); cfg.colmin = 'auto'; end -if ~isfield(cfg, 'colmax'); cfg.colmax = 'auto'; end -if ~isfield(cfg, 'resample'); cfg.resample = 1; end -if ~isfield(cfg, 'rotate'); cfg.rotate = 0; end -if ~isfield(cfg, 'title'); cfg.title = ''; end -if ~isfield(cfg, 'whitebg'); cfg.whitebg = 'no'; end -if ~isfield(cfg, 'flipdim'); cfg.flipdim = 'no'; end -if ~isfield(cfg, 'marker'); cfg.marker = []; end -if ~isfield(cfg, 'markersize'); cfg.markersize = 5; end -if ~isfield(cfg, 'markercolor'); cfg.markercolor = [1,1,1]; end -if ~isfield(cfg, 'interactive'); cfg.interactive = 'no'; end -if ~isfield(cfg, 'maskclipmin'); cfg.maskclipmin = 'auto'; end -if ~isfield(cfg, 'maskclipmax'); cfg.maskclipmax = 'auto'; end -if ~isfield(cfg, 'maskclipsym'); cfg.maskclipsym = 'no'; end -if ~isfield(cfg, 'maskmap'); cfg.maskmap = linspace(0,1,128); end -if ~isfield(cfg, 'maskcolmin'); cfg.maskcolmin = 'auto'; end -if ~isfield(cfg, 'maskcolmax'); cfg.maskcolmax = 'auto'; end -if ~isfield(cfg, 'maskparameter');cfg.maskparameter = []; end - -% perform some checks on the configuration for backward compatibility -if ~isfield(cfg, 'funparameter') && isfield(ininterp, 'source') - % if present, the default behavior should be to use this field for plotting - cfg.funparameter = 'source'; -end - -% make the selection of functional and mask data consistent with the data -cfg.funparameter = parameterselection(cfg.funparameter, ininterp); -cfg.maskparameter = parameterselection(cfg.maskparameter, ininterp); -% only a single parameter should be selected -try, cfg.funparameter = cfg.funparameter{1}; end -try, cfg.maskparameter = cfg.maskparameter{1}; end - -% check anatomical data -if isfield(ininterp,'anatomy'); - interp.anatomy = reshape(ininterp.anatomy, ininterp.dim); -else - error('no anatomical data supplied'); -end - -% check functional data -if ~isempty(cfg.funparameter) - interp.source = double(reshape(getsubfield(ininterp, cfg.funparameter), ininterp.dim)); -else - error('no functional data supplied'); -end - -% check mask data -if ~isempty(cfg.maskparameter) - interp.mask = double(reshape(getsubfield(ininterp,cfg.maskparameter), ininterp.dim)); - maskdat = 1; -else - fprintf('no opacity mask data supplied\n'); - interp.mask = []; - maskdat = 0; -end - -% only work with the copy of the relevant parameters in "interp" -clear ininterp; - -% convert anatomy data type and optimize contrast -if isa(interp.anatomy, 'uint8') || isa(interp.anatomy, 'uint16') - fprintf('converting anatomy to floating point values...'); - interp.anatomy = double(interp.anatomy); - fprintf('done\n'); -end -fprintf('optimizing contrast of anatomical data ...'); -minana = min(interp.anatomy(:)); -maxana = max(interp.anatomy(:)); -interp.anatomy = (interp.anatomy-minana)./(maxana-minana); -fprintf('done\n'); - -% store original data if 'interactive' mode -if strcmp(cfg.interactive,'yes') - data.source = interp.source; -end - -% place markers -marker = zeros(size(interp.anatomy)); -if ~isempty(cfg.marker) - fprintf('placing markers ...'); - [x,y,z] = ndgrid([1:size(interp.anatomy,1)],[1:size(interp.anatomy,2)],[1:size(interp.anatomy,3)]); - for imarker = 1:size(cfg.marker,1) - marker(find(sqrt((x-cfg.marker(imarker,1)).^2 + (y-cfg.marker(imarker,2)).^2 + (z-cfg.marker(imarker,3)).^2)<=cfg.markersize)) = 1; - end - fprintf('done\n'); -end - -% shift dimensions -fprintf('sorting dimensions...'); -interp.anatomy = shiftdim(interp.anatomy,cfg.dim-1); -interp.source = shiftdim(interp.source,cfg.dim-1); -interp.mask = shiftdim(interp.mask,cfg.dim-1); -marker = shiftdim(marker,cfg.dim-1); -fprintf('done\n'); - -% flip dimensions -if strcmp(cfg.flipdim,'yes') - fprintf('flipping dimensions...'); - interp.anatomy = flipdim(interp.anatomy,1); - interp.source = flipdim(interp.source,1); - interp.mask = flipdim(interp.mask,1); - marker = flipdim(marker,1); - fprintf('done\n'); -end - -% set slice space -if ischar(cfg.spacemin) - fprintf('setting first slice position...'); - spacemin = min(find(~isnan(max(max(interp.source,[],3),[],2)))); - fprintf('%d...done\n',spacemin); -else - spacemin = cfg.spacemin; -end - -if ischar(cfg.spacemax) - fprintf('setting last slice position...'); - spacemax = max(find(~isnan(max(max(interp.source,[],3),[],2)))); - fprintf('%d...done\n',spacemax); -else - spacemax = cfg.spacemax; -end - -% clip funtional data -if ~ischar(cfg.clipmin) - fprintf('clipping functional minimum...'); - switch cfg.clipsym - case 'no' - interp.source(find(interp.sourcecfg.clipmax)) = nan; - case 'yes' - interp.source(find(abs(interp.source)>cfg.clipmax)) = nan; - end - fprintf('done\n'); -end - -% clip mask data -if maskdat - if ~ischar(cfg.maskclipmin) - fprintf('clipping mask minimum...'); - switch cfg.maskclipsym - case 'no' - interp.mask(find(interp.maskcfg.maskclipmax)) = nan; - case 'yes' - interp.mask(find(abs(interp.mask)>cfg.maskclipmax)) = nan; - end - fprintf('done\n'); - end -end - -% scale functional data -fprintf('scaling functional data...'); -fmin = min(interp.source(:)); -fmax = max(interp.source(:)); -if ~ischar(cfg.colmin) - fcolmin = cfg.colmin; -else - if sign(fmin)==sign(fmax) - fcolmin = fmin; - else - fcolmin = -max(abs([fmin,fmax])); - end -end -if ~ischar(cfg.colmax) - fcolmax = cfg.colmax; -else - if sign(fmin)==sign(fmax) - fcolmax = fmax; - else - fcolmax = max(abs([fmin,fmax])); - end -end -interp.source = (interp.source-fcolmin)./(fcolmax-fcolmin); -if ~ischar(cfg.colmax) - interp.source(find(interp.source>1)) = 1; -end -if ~ischar(cfg.colmin) - interp.source(find(interp.source<0)) = 0; -end -fprintf('done\n'); - -% scale mask data -if maskdat - fprintf('scaling mask data...'); - fmin = min(interp.mask(:)); - fmax = max(interp.mask(:)); - if ~ischar(cfg.maskcolmin) - mcolmin = cfg.maskcolmin; - else - if sign(fmin)==sign(fmax) - mcolmin = fmin; - else - mcolmin = -max(abs([fmin,fmax])); - end - end - if ~ischar(cfg.maskcolmax) - mcolmax = cfg.maskcolmax; - else - if sign(fmin)==sign(fmax) - mcolmax = fmax; - else - mcolmax = max(abs([fmin,fmax])); - end - end - interp.mask = (interp.mask-mcolmin)./(mcolmax-mcolmin); - if ~ischar(cfg.maskcolmax) - interp.mask(find(interp.mask>1)) = 1; - end - if ~ischar(cfg.maskcolmin) - interp.mask(find(interp.mask<0)) = 0; - end - fprintf('done\n'); -end - -% merge anatomy, functional data and mask -fprintf('constructing overlay...'); -if ischar(cfg.colormap) - % replace string by colormap using standard Matlab function - cfg.colormap = colormap(cfg.colormap); -end -cmap = cfg.colormap; -cmaplength = size(cmap,1); -maskmap = cfg.maskmap(:); -maskmaplength = size(maskmap,1); -indslice = round(linspace(spacemin,spacemax,cfg.nslices)); -nvox1 = length(1:cfg.resample:size(interp.anatomy,2)); -nvox2 = length(1:cfg.resample:size(interp.anatomy,3)); -if mod(cfg.rotate,2) - dummy = nvox1; - nvox1 = nvox2; - nvox2 = dummy; -end -out = zeros(nvox1,nvox2,3,cfg.nslices); -for islice = 1:cfg.nslices - dummy1 = squeeze(interp.anatomy(indslice(islice),1:cfg.resample:end,1:cfg.resample:end)); - dummy2 = squeeze(interp.source(indslice(islice),1:cfg.resample:end,1:cfg.resample:end)); - indmarker = find(squeeze(marker(indslice(islice),1:cfg.resample:end,1:cfg.resample:end))); - indsource = find(~isnan(dummy2)); - if maskdat - dummymask = squeeze(interp.mask(indslice(islice),1:cfg.resample:end,1:cfg.resample:end)); - indsource = find(~isnan(dummy2) & ~isnan(dummymask)); - end - for icol = 1:3 - dummy3 = dummy1; - if not(maskdat) - if ~ischar(cfg.alpha) - try - dummy3(indsource) = ... - (1-cfg.alpha) * dummy3(indsource) + ... - cfg.alpha * cmap(round(dummy2(indsource)*(cmaplength-1))+1,icol); - end - else - try - dummy3(indsource) = ... - (1-dummy2(indsource)) .* dummy3(indsource) + ... - dummy2(indsource) .* cmap(round(dummy2(indsource)*(cmaplength-1))+1,icol); - end - end - else - dummy3(indsource) = ... - (1-maskmap(round(dummymask(indsource)*(maskmaplength-1))+1)).* ... - dummy3(indsource) + ... - maskmap(round(dummymask(indsource)*(maskmaplength-1))+1) .* ... - cmap(round(dummy2(indsource)*(cmaplength-1))+1,icol); - end - dummy3(indmarker) = cfg.markercolor(icol); - out(:,:,icol,islice) = rot90(dummy3,cfg.rotate); - end - if strcmp(cfg.whitebg,'yes') - bgmask = zeros(nvox1,nvox2); - bgmask(find(conv2(mean(out(:,:,:,islice),3),ones(round((nvox1+nvox2)/8))/(round((nvox1+nvox2)/8).^2),'same')<0.1)) = 1; - for icol = 1:3 - out(:,:,icol,islice) = bgmask.*ones(nvox1,nvox2) + (1-bgmask).* out(:,:,icol,islice); - end - end -end -fprintf('done\n'); - -clf; -fprintf('plotting...'); -axes('position',[0.9 0.3 0.02 0.4]); -image(permute(cmap,[1 3 2])); -set(gca,'YAxisLocation','right'); -set(gca,'XTick',[]); -set(gca,'YDir','normal'); -set(gca,'YTick',linspace(1,cmaplength,5)); -set(gca,'YTickLabel',linspace(fcolmin,fcolmax,5)); -set(gca,'Box','on'); -axes('position',[0.01 0.01 0.88 0.90]); -[h,nrows,ncols]=slicemon(out); -xlim=get(gca,'XLim'); -ylim=get(gca,'YLim'); -text(diff(xlim)/2,-diff(ylim)/100,cfg.title,'HorizontalAlignment','center','Interpreter','none'); -drawnow; -fprintf('done\n'); -if nargout > 0 - outim=get(h,'CData'); -end - -if strcmp(cfg.interactive,'yes') - data.sin = size(interp.source); - data.nrows = nrows; - data.ncols = ncols; - data.out = out; - data.indslice = indslice; - data.cfg = cfg; - data.hfig = gcf; - uicontrol('Units','norm', 'Position', [0.9 0.2 0.08 0.05], 'Style','pushbutton', 'String','coords',... - 'Callback',@getcoords,'FontSize',7); - data.hcoords = uicontrol('Units','norm', 'Position', [0.9 0.05 0.08 0.13], 'Style','text', 'String','','HorizontalAlign','left','FontSize',7); - guidata(data.hfig,data); -end - -% ---------------- subfunctions ---------------- - -function getcoords(h,eventdata,handles,varargin) -data = guidata(gcf); -[xi,yi] = ginput(1); - -co(2,1) = round(mod(yi,size(data.out,1))); -co(3,1) = round(mod(xi,size(data.out,2))); -switch mod(data.cfg.rotate,4) -case 1, - t1 = co(2); - co(2) = co(3); - co(3) = data.sin(3)-t1; -case 2, - co(2) = data.sin(2)-co(2); - co(3) = data.sin(3)-co(3); -case 3, - t1 = co(3); - co(3) = co(2); - co(2) = data.sin(2)-t1; -end - -try - co(1) = data.indslice(fix(xi/size(data.out,2)) + fix(yi/size(data.out,1))*data.ncols + 1); -catch - co(1) = NaN; -end - -if strcmp(data.cfg.flipdim, 'yes') - co(1) = data.sin(1) - co(1) + 1; -end -co = co(:); - -co(2:3) = round(co(2:3)*data.cfg.resample); -for ishift = 1:data.cfg.dim-1 - co = [co(3);co(1);co(2)]; -end -set(data.hcoords,'String',sprintf('1: %d\n2: %d\n3: %d\nf: %0.4f',co(1),co(2),co(3),data.source(co(1),co(2),co(3)))); - -function [h,nrows,ncols] = slicemon(a) % display the montage w/o image_toolbox -siz = [size(a,1) size(a,2) size(a,4)]; -nn = sqrt(prod(siz))/siz(2); -mm = siz(3)/nn; -if (ceil(nn)-nn) < (ceil(mm)-mm), - nn = ceil(nn); mm = ceil(siz(3)/nn); -else - mm = ceil(mm); nn = ceil(siz(3)/mm); -end -b = a(1,1); -b(1,1) = 0; -b = repmat(b, [mm*siz(1), nn*siz(2), size(a,3), 1]); -rows = 1:siz(1); cols = 1:siz(2); -for i=0:mm-1, - for j=0:nn-1, - k = j+i*nn+1; - if k<=siz(3), - b(rows+i*siz(1),cols+j*siz(2),:) = a(:,:,:,k); - end - end -end -hh = image(b); -axis image; -box off; -set(gca,'XTick',[],'YTick',[],'Visible','off'); -if nargout > 0 - h = hh; - nrows = mm; - ncols = nn; -end diff --git a/external/fieldtrip/private/smartinput.m b/external/fieldtrip/private/smartinput.m index fa92a68..35bad9b 100644 --- a/external/fieldtrip/private/smartinput.m +++ b/external/fieldtrip/private/smartinput.m @@ -9,22 +9,23 @@ % Copyright (C) 2006, Robert Oostenveld % -% $Log: smartinput.m,v $ -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.4 2006/06/01 12:52:21 roboos -% allow for vector and matrix input +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.3 2006/05/02 19:13:14 roboos -% allow empty oldvalue input +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.2 2006/05/01 19:17:24 roboos -% better support for string inputs -% -% Revision 1.1 2006/05/01 19:14:12 roboos -% first implementation as stand-alone function +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: smartinput.m 952 2010-04-21 18:29:51Z roboos $ if ischar(oldval) newval = input(question, 's'); diff --git a/external/fieldtrip/private/solid_angle.m b/external/fieldtrip/private/solid_angle.m index 0e506a0..93a3c77 100644 --- a/external/fieldtrip/private/solid_angle.m +++ b/external/fieldtrip/private/solid_angle.m @@ -1,4 +1,4 @@ -function [w] = solid_angle(r1, r2, r3); +function [varargout] = funname(varargin) % SOLID_ANGLE of a planar triangle as seen from the origin % @@ -6,63 +6,119 @@ % area W of a unit sphere covered by the surface's projection onto the % sphere. Solid angle is measured in steradians, and the solid angle % corresponding to all of space being subtended is 4*pi sterradians. -% -% Use: -% [w] = solid_angle(v1, v2, v3) or +% +% Use: +% [w] = solid_angle(v1, v2, v3) +% or % [w] = solid_angle(pnt, tri) % where v1, v2 and v3 are the vertices of a single triangle in 3D or % pnt and tri contain a description of a triangular mesh (this will % compute the solid angle for each triangle) -% -% also implemented as MEX file -% Copyright (C) 2003, Robert Oostenveld +% Copyright (C) 2003-2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% $Log: solid_angle.m,v $ -% Revision 1.3 2003/03/21 13:32:53 roberto -% created mex implementation +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.2 2003/03/04 21:46:19 roberto -% added CVS log entry and synchronized all copyright labels +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: solid_angle.m 946 2010-04-21 17:51:16Z roboos $ + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% The first section contains the plain Matlab implementation. The mex file +% is many times faster and this function is called so frequently (for +% large meshes), that the mex file should be used in all practical cases. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% function [w] = solid_angle(r1, r2, r3); +% +% if nargin==2 +% % reassign the input arguments +% pnt = r1; +% tri = r2; +% npnt = size(pnt,1); +% ntri = size(tri,1); +% w = zeros(ntri,1); +% % compute solid angle for each triangle +% for i=1:ntri +% r1 = pnt(tri(i,1),:); +% r2 = pnt(tri(i,2),:); +% r3 = pnt(tri(i,3),:); +% w(i) = solid_angle(r1, r2, r3); +% end +% return +% elseif nargin==3 +% % compute the solid angle for this triangle +% cp23_x = r2(2) * r3(3) - r2(3) * r3(2); +% cp23_y = r2(3) * r3(1) - r2(1) * r3(3); +% cp23_z = r2(1) * r3(2) - r2(2) * r3(1); +% nom = cp23_x * r1(1) + cp23_y * r1(2) + cp23_z * r1(3); +% n1 = sqrt (r1(1) * r1(1) + r1(2) * r1(2) + r1(3) * r1(3)); +% n2 = sqrt (r2(1) * r2(1) + r2(2) * r2(2) + r2(3) * r2(3)); +% n3 = sqrt (r3(1) * r3(1) + r3(2) * r3(2) + r3(3) * r3(3)); +% ip12 = r1(1) * r2(1) + r1(2) * r2(2) + r1(3) * r2(3); +% ip23 = r2(1) * r3(1) + r2(2) * r3(2) + r2(3) * r3(3); +% ip13 = r1(1) * r3(1) + r1(2) * r3(2) + r1(3) * r3(3); +% den = n1 * n2 * n3 + ip12 * n3 + ip23 * n1 + ip13 * n2; +% if (nom == 0) +% if (den <= 0) +% w = nan; +% return +% end +% end +% w = 2 * atan2 (nom, den); +% return +% else +% error('invalid input'); +% end + +% compile the missing mex file on the fly +% remember the original working directory +pwdir = pwd; -if nargin==2 - % reassign the input arguments - pnt = r1; - tri = r2; - npnt = size(pnt,1); - ntri = size(tri,1); - w = zeros(ntri,1); - % compute solid angle for each triangle - for i=1:ntri - r1 = pnt(tri(i,1),:); - r2 = pnt(tri(i,2),:); - r3 = pnt(tri(i,3),:); - w(i) = solid_angle(r1, r2, r3); - end - return -elseif nargin==3 - % compute the solid angle for this triangle - cp23_x = r2(2) * r3(3) - r2(3) * r3(2); - cp23_y = r2(3) * r3(1) - r2(1) * r3(3); - cp23_z = r2(1) * r3(2) - r2(2) * r3(1); - nom = cp23_x * r1(1) + cp23_y * r1(2) + cp23_z * r1(3); - n1 = sqrt (r1(1) * r1(1) + r1(2) * r1(2) + r1(3) * r1(3)); - n2 = sqrt (r2(1) * r2(1) + r2(2) * r2(2) + r2(3) * r2(3)); - n3 = sqrt (r3(1) * r3(1) + r3(2) * r3(2) + r3(3) * r3(3)); - ip12 = r1(1) * r2(1) + r1(2) * r2(2) + r1(3) * r2(3); - ip23 = r2(1) * r3(1) + r2(2) * r3(2) + r2(3) * r3(3); - ip13 = r1(1) * r3(1) + r1(2) * r3(2) + r1(3) * r3(3); - den = n1 * n2 * n3 + ip12 * n3 + ip23 * n1 + ip13 * n2; - if (nom == 0) - if (den <= 0) - w = nan; - return - end +% determine the name and full path of this function +funname = mfilename('fullpath'); +mexsrc = [funname '.c']; +[mexdir, mexname] = fileparts(funname); + +try + % try to compile the mex file on the fly + warning('trying to compile MEX file from %s', mexsrc); + cd(mexdir); + + if ispc + mex -I. -c geometry.c + mex -I. -c solid_angle.c ; mex solid_angle.c solid_angle.obj geometry.obj + else + mex -I. -c geometry.c + mex -I. -c solid_angle.c ; mex -o solid_angle solid_angle.o geometry.o end - w = 2 * atan2 (nom, den); - return -else - error('invalid input'); + + cd(pwdir); + success = true; + +catch + % compilation failed + disp(lasterr); + error('could not locate MEX file for %s', mexname); + cd(pwdir); + success = false; +end + +if success + % execute the mex file that was juist created + funname = mfilename; + funhandle = str2func(funname); + [varargout{1:nargout}] = funhandle(varargin{:}); end diff --git a/external/fieldtrip/private/solid_angle.mexmaci b/external/fieldtrip/private/solid_angle.mexmaci index f499b3f..26b57e0 100755 Binary files a/external/fieldtrip/private/solid_angle.mexmaci and b/external/fieldtrip/private/solid_angle.mexmaci differ diff --git a/external/fieldtrip/private/solid_angle.mexw32 b/external/fieldtrip/private/solid_angle.mexw32 index 87154fb..688b8a3 100644 Binary files a/external/fieldtrip/private/solid_angle.mexw32 and b/external/fieldtrip/private/solid_angle.mexw32 differ diff --git a/external/fieldtrip/private/solid_angle.mexw64 b/external/fieldtrip/private/solid_angle.mexw64 index 94b0fab..0a6a9a0 100644 Binary files a/external/fieldtrip/private/solid_angle.mexw64 and b/external/fieldtrip/private/solid_angle.mexw64 differ diff --git a/external/fieldtrip/private/source2full.m b/external/fieldtrip/private/source2full.m deleted file mode 100644 index c801b8f..0000000 --- a/external/fieldtrip/private/source2full.m +++ /dev/null @@ -1,265 +0,0 @@ -function [source] = source2full(source); - -% SOURCE2FULL recreates the grid locations outside the brain in the source -% reconstruction, so that the source volume again describes the full grid. -% This undoes the memory savings that can be achieved using SOURC2SPARSE -% and makes it possible again to plot the source volume and save it to an -% external file. -% -% Use as -% [source] = source2full(source) -% -% See also SOURCE2SPARSE - -% Copyright (C) 2004, Robert Oostenveld -% -% $Log: source2full.m,v $ -% Revision 1.19 2009/10/12 14:20:19 jansch -% removed necessity to have xgrid etc in the input -% -% Revision 1.18 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.17 2008/07/21 20:09:23 roboos -% use islogical and iscell -% -% Revision 1.16 2006/07/12 08:25:59 roboos -% added support for coherence-like matrices (Nvox X Nvox) -% -% Revision 1.15 2006/01/31 12:57:20 jansch -% replaced explicit checking of all known parameters by parameterselection -% -% Revision 1.14 2005/09/09 17:08:21 jansch -% support for ref as an input-field -% -% Revision 1.13 2005/09/08 06:50:21 jansch -% admit stat as an input field -% -% Revision 1.12 2005/08/23 13:15:16 jansch -% added source.avg.csd and noisecsd -% -% Revision 1.11 2005/06/29 12:46:29 roboos -% the following changes were done on a large number of files at the same time, not all of them may apply to this specific file -% - added try-catch around the inclusion of input data configuration -% - moved cfg.version, cfg.previous and the assignment of the output cfg to the end -% - changed help comments around the configuration handling -% - some changes in whitespace -% -% Revision 1.10 2005/05/17 17:50:38 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.9 2005/03/13 13:03:39 jansch -% added outside nans for var and sem. -% -% Revision 1.8 2005/02/09 13:03:09 roboos -% fixed bug for matlab 70 (mask is logical) -% -% Revision 1.7 2005/01/31 13:49:15 roboos -% fixed bug in sem.nai -% -% Revision 1.6 2005/01/25 11:08:44 roboos -% added var and sem as fields containing source parameters -% -% Revision 1.5 2004/09/23 15:07:16 roboos -% added support for lbex as cell-array in the source structure -% -% Revision 1.4 2004/09/08 08:56:17 jansch -% included correct inside/outside for trialA/trialB, which is necessary for potential subsequent randcluster statistics. -% -% Revision 1.3 2004/08/26 12:14:49 roboos -% *** empty log message *** -% -% Revision 1.2 2004/08/05 15:37:05 roboos -% added support for statistical parameters, fixed bug in leadfield -% -% Revision 1.1 2004/08/03 09:06:19 roboos -% initial implementation of these helper functions for beamformer sourceanalysis -% - -fieldtripdefs - -if ~isfield(source, 'inside') || ... - ~isfield(source, 'outside') || ... - ~isfield(source, 'dim') - error('one of the required fields is missing in the source structure'); -end - -if ~isfield(source, 'pos') && (~isfield(source, 'xgrid') || ~isfield(source, 'ygrid') || ... - ~isfield(source, 'zgrid')) - error('the input data needs at least a ''pos'' field, or ''x/y/zgrid'''); -end - -if isfield(source, 'xgrid'), - xgrid = source.xgrid; - ygrid = source.ygrid; - zgrid = source.zgrid; -else - %FIXME this assumes that the voxel data are ordered as if in a regularly spaced 3D grid, - %but with only the inside voxels present - xgrid = 1:source.dim(1); - ygrid = 1:source.dim(2); - zgrid = 1:source.dim(3); -end -% recreate the positions of the dipole grid -[X, Y, Z] = ndgrid(xgrid, ygrid, zgrid); -pos = [X(:) Y(:) Z(:)]; - -Nsparse = length(source.inside); -siz = source.dim; -Nfull = prod(siz); - -% determine the size that each slice takes in memory -sx = 1; -sy = siz(1); -sz = siz(1) * siz(2); - -if isfield(source, 'inside') && isfield(source, 'outside') && size(source.pos,1)==Nfull - % it contains all source positions - inside = source.inside; - outside = source.outside; -else - % it only contains the inside source positions, which are all inside the brain - % reconstruct the original inside and outside grid locations - for i=1:Nsparse - fx = find(source.xgrid==source.pos(i,1)); - fy = find(source.ygrid==source.pos(i,2)); - fz = find(source.zgrid==source.pos(i,3)); - inside(i) = (fx-1)*sx + (fy-1)*sy + (fz-1)*sz + 1; - end - outside = setdiff(1:Nfull, inside); -end - -fprintf('total number of dipoles : %d\n', length(inside)+length(outside)); -fprintf('number of dipoles inside brain: %d\n', length(inside)); -fprintf('number of dipoles outside brain: %d\n', length(outside)); - -% first do the non-trial fields -source.dim = [1 length(inside) 1]; %to fool parameterselection -[param] = parameterselection('all', source); -trlparam = strmatch('trial', param); -sel = setdiff(1:length(param), trlparam); -param = param(sel); - -for j = 1:length(param) - dat = getsubfield(source, param{j}); - if islogical(dat), - tmp = false(1,Nfull); - tmp(inside) = dat; - elseif iscell(dat), - tmp = cell(1,Nfull); - tmp(inside) = dat; - %tmp(outside) = nan; - else - tmp = zeros(1,Nfull) + nan; - tmp(inside) = dat; - end - source = setsubfield(source, param{j}, tmp); -end - -% then do the trial fields -if isfield(source, 'trial' ), - for j = 1:length(source.trial) - tmpsource = source.trial(j); - tmpsource.dim = source.dim; % to fool parameterselection - tmpparam = parameterselection('all', tmpsource); - for k = 1:length(tmpparam) - dat = getsubfield(tmpsource, tmpparam{k}); - if strcmp(class(dat), 'logical'), - tmp = logical(zeros(1,Nfull)); - tmp(inside) = dat; - elseif strcmp(class(dat), 'cell'), - tmp = cell(1,Nfull); - tmp(inside) = dat; - %tmp(outside) = nan; - else - tmp = zeros(1,Nfull) + nan; - tmp(inside) = dat; - end - tmpsource = setsubfield(tmpsource, tmpparam{k}, tmp); - end - tmpsource = rmfield(tmpsource, 'dim'); - source.trial(j) = tmpsource; - end -elseif isfield(source, 'trialA'), - for j = 1:length(source.trialA) - tmpsource = source.trialA(j); - tmpsource.dim = source.dim; % to fool parameterselection - tmpparam = parameterselection('all', tmpsource); - for k = 1:length(tmpparam) - dat = getsubfield(tmpsource, tmpparam{k}); - if strcmp(class(dat), 'logical'), - tmp = logical(zeros(1,Nfull)); - tmp(inside) = dat; - elseif strcmp(class(dat), 'cell'), - tmp = cell(1,Nfull); - tmp(inside) = dat; - %tmp(outside) = nan; - else - tmp = zeros(1,Nfull) + nan; - tmp(inside) = dat; - end - tmpsource = setsubfield(tmpsource, tmpparam{k}, tmp); - end - tmpsource = rmfield(tmpsource, 'dim'); - source.trialA(j) = tmpsource; - end -elseif isfield(source, 'trialB'), - for j = 1:length(source.trialB) - tmpsource = source.trialB(j); - tmpsource.dim = source.dim; % to fool parameterselection - tmpparam = parameterselection('all', tmpsource); - for k = 1:length(tmpparam) - dat = getsubfield(tmpsource, tmpparam{k}); - if strcmp(class(dat), 'logical'), - tmp = logical(zeros(1,Nfull)); - tmp(inside) = dat; - elseif strcmp(class(dat), 'cell'), - tmp = cell(1,Nfull); - tmp(inside) = dat; - %tmp(outside) = nan; - else - tmp = zeros(1,Nfull) + nan; - tmp(inside) = dat; - end - tmpsource = setsubfield(tmpsource, tmpparam{k}, tmp); - end - tmpsource = rmfield(tmpsource, 'dim'); - source.trialB(j) = tmpsource; - end -end - -% and finally do the coherence-like matrices (size Nvox X Nvox) -fn = fieldnames(source); -for i=1:length(fn) - d = getfield(source, fn{i}); - m = size(d, 1); - n = size(d, 2); - if m==Nsparse && n==Nsparse - tmp = nan*zeros(Nfull,Nfull); - tmp(inside,inside) = d; - source = setfield(source, fn{i}, tmp); - end -end - -% update the inside and outside definitions -source.inside = inside; -source.outside = outside; -source.pos = pos; -source.dim = siz; - -cfg = []; -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: source2full.m,v 1.19 2009/10/12 14:20:19 jansch Exp $'; -% remember the configuration details of the input data -try, cfg.previous = source.cfg; end -% remember the exact configuration details in the output -source.cfg = cfg; diff --git a/external/fieldtrip/private/source2grid.m b/external/fieldtrip/private/source2grid.m deleted file mode 100644 index da305a0..0000000 --- a/external/fieldtrip/private/source2grid.m +++ /dev/null @@ -1,58 +0,0 @@ -function [grid] = source2grid(source) - -% SOURCE2GRID removes the fields from a source structure that are -% not neccessary to reuse the dipole grid in another source estimation. -% -% Use as -% [grid] = source2grid(source); -% -% The resulting grid can be used in the configuration of another -% run of SOURCANALYSIS. -% -% See also SOURCE2SPARSE, SOURCE2FULL - -% Copyright (C) 2004, Robert Oostenveld -% -% $Log: source2grid.m,v $ -% Revision 1.5 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.4 2008/07/25 07:03:15 roboos -% xgrid/ygrid/zgrid and dim do not always have to be present, hence made them optional -% -% Revision 1.3 2006/05/17 08:41:18 roboos -% also keep the filters if present -% -% Revision 1.2 2004/09/01 17:59:28 roboos -% added copyright statements to all filed -% added cfg.version to all functions that give configuration in their output -% added cfg.previous to all functions with input data containing configuration details -% -% Revision 1.1 2004/08/03 09:06:19 roboos -% initial implementation of these helper functions for beamformer sourceanalysis -% - -fieldtripdefs - -% these are always supposed to be present -grid.pos = source.pos; -grid.inside = source.inside; -grid.outside = source.outside; - -% these are optional -try, grid.xgrid = source.xgrid; end -try, grid.ygrid = source.ygrid; end -try, grid.zgrid = source.zgrid; end -try, grid.dim = source.dim; end - -if issubfield(source, 'filter') - grid.filter = source.filter; -elseif issubfield(source, 'avg.filter') - grid.filter = source.avg.filter; -elseif issubfield(source, 'trial.filter') - error('single trial filters are not supported here'); -end - -if isfield(source, 'leadfield') - grid.leadfield = source.leadfield; -end diff --git a/external/fieldtrip/private/source2sparse.m b/external/fieldtrip/private/source2sparse.m deleted file mode 100644 index 00b1f3e..0000000 --- a/external/fieldtrip/private/source2sparse.m +++ /dev/null @@ -1,150 +0,0 @@ -function [source] = source2sparse(source); - -% SOURCE2SPARCE removes the grid locations outside the brain from the source -% reconstruction, thereby saving memory. -% -% This invalidates the fields that describe the grid, and also makes it -% more difficult to make a plot of each of the slices of the source volume. -% The original source structure can be recreated using SOURCE2FULL. -% -% Use as -% [source] = source2sparse(source) -% -% See also SOURCE2FULL - -% Copyright (C) 2004, Robert Oostenveld -% -% $Log: source2sparse.m,v $ -% Revision 1.10 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.9 2006/03/30 12:24:33 roboos -% Implemented private/fixinside, which facilitates consistent -% handling of source/volume data. Improved documentation. Fixed some -% bugs related to inconsistent handling of ROIs (i.e. inside/outside) -% -% Revision 1.8 2006/01/31 12:57:20 jansch -% replaced explicit checking of all known parameters by parameterselection -% -% Revision 1.7 2005/08/23 13:15:16 jansch -% added source.avg.csd and noisecsd -% -% Revision 1.6 2005/06/29 12:46:29 roboos -% the following changes were done on a large number of files at the same time, not all of them may apply to this specific file -% - added try-catch around the inclusion of input data configuration -% - moved cfg.version, cfg.previous and the assignment of the output cfg to the end -% - changed help comments around the configuration handling -% - some changes in whitespace -% -% Revision 1.5 2005/01/25 11:08:23 roboos -% added var and sem as fields containing sourceparameters -% -% Revision 1.4 2004/09/23 15:07:16 roboos -% added support for lbex as cell-array in the source structure -% -% Revision 1.3 2004/08/26 12:15:25 roboos -% added some extra fprintf information -% -% Revision 1.2 2004/08/05 15:37:05 roboos -% added support for statistical parameters, fixed bug in leadfield -% -% Revision 1.1 2004/08/03 09:06:19 roboos -% initial implementation of these helper functions for beamformer sourceanalysis -% - -fieldtripdefs - -if ~isfield(source, 'inside') - warning('no gridpoints defined inside the brain'); - source.inside = []; -end - -if ~isfield(source, 'outside') - warning('no gridpoints defined outside the brain'); - source.outside = []; -end - -inside = source.inside; -outside = source.outside; - -fprintf('total number of dipoles : %d\n', length(inside)+length(outside)); -fprintf('number of dipoles inside brain: %d\n', length(inside)); -fprintf('number of dipoles outside brain: %d\n', length(outside)); - -% first do the non-trial fields -[param] = parameterselection('all', source); -trlparam = strmatch('trial', param); -sel = setdiff(1:length(param), trlparam); -param = param(sel); - -for j = 1:length(param) - dat = getsubfield(source, param{j}); - source = setsubfield(source, param{j}, dat(inside)); -end - -% then do the trial fields -if isfield(source, 'trial'), - for j = 1:length(source.trial) - tmpsource = source.trial(j); - tmpsource.dim = source.dim; % to fool parameterselection - tmpparam = parameterselection('all', tmpsource); - for k = 1:length(tmpparam) - dat = getsubfield(tmpsource, tmpparam{k}); - tmpsource = setsubfield(tmpsource, tmpparam{k}, dat(inside)); - end - tmpsource = rmfield(tmpsource, 'dim'); - source.trial(j) = tmpsource; - end -elseif isfield(source, 'trialA'), - for j = 1:length(source.trialA) - tmpsource = source.trialA(j); - tmpsource.dim = source.dim; % to fool parameterselection - tmpparam = parameterselection('all', tmpsource); - for k = 1:length(tmpparam) - dat = getsubfield(tmpsource, tmpparam{k}); - tmpsource = setsubfield(tmpsource, tmpparam{k}, dat(inside)); - end - tmpsource = rmfield(tmpsource, 'dim'); - source.trialA(j) = tmpsource; - end -elseif isfield(source, 'trialB'), - for j = 1:length(source.trialB) - tmpsource = source.trialB(j); - tmpsource.dim = source.dim; % to fool parameterselection - tmpparam = parameterselection('all', tmpsource); - for k = 1:length(tmpparam) - dat = getsubfield(tmpsource, tmpparam{k}); - tmpsource = setsubfield(tmpsource, tmpparam{k}, dat(inside)); - end - tmpsource = rmfield(tmpsource, 'dim'); - source.trialB(j) = tmpsource; - end -end - -% update the inside, outside and source position -if isfield(source, 'inside') - source.inside = 1:length(inside); -end -if isfield(source, 'outside') - source.outside = []; -end -if isfield(source, 'pos') - source.pos = source.pos(inside,:); -end - -cfg = []; -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: source2sparse.m,v 1.10 2008/09/22 20:17:44 roboos Exp $'; -% remember the configuration details of the input data -try, cfg.previous = source.cfg; end -% remember the exact configuration details in the output -source.cfg = cfg; - diff --git a/external/fieldtrip/private/sourceanalysis.m b/external/fieldtrip/private/sourceanalysis.m deleted file mode 100644 index 9042578..0000000 --- a/external/fieldtrip/private/sourceanalysis.m +++ /dev/null @@ -1,1359 +0,0 @@ -function [source] = sourceanalysis(cfg, data, baseline); - -% SOURCEANALYSIS performs beamformer dipole analysis on EEG or MEG data -% after preprocessing and a timelocked or frequency analysis -% -% Use as either -% [source] = sourceanalysis(cfg, freq) -% [source] = sourceanalysis(cfg, timelock) -% -% where the data in freq or timelock should be organised in a structure -% as obtained from the FREQANALYSIS or TIMELOCKANALYSIS function. The -% configuration "cfg" is a structure containing information about -% source positions and other options. -% -% The different source reconstruction algorithms that are implemented -% are -% cfg.method = 'lcmv' linear constrained minimum variance beamformer -% 'sam' synthetic aperture magnetometry -% 'dics' dynamic imaging of coherent sources -% 'pcc' partial cannonical correlation/coherence -% 'mne' minimum norm estimation -% 'loreta' minimum norm estimation with smoothness constraint -% 'rv' scan residual variance with single dipole -% 'music' multiple signal classification -% 'mvl' multivariate Laplace source localization -% The DICS and PCC methods are for frequency domain data, all other methods -% are for time domain data. -% -% The positions of the sources can be specified as a regular 3-D -% grid that is aligned with the axes of the head coordinate system -% cfg.grid.xgrid = vector (e.g. -20:1:20) or 'auto' (default = 'auto') -% cfg.grid.ygrid = vector (e.g. -20:1:20) or 'auto' (default = 'auto') -% cfg.grid.zgrid = vector (e.g. 0:1:20) or 'auto' (default = 'auto') -% cfg.grid.resolution = number (e.g. 1 cm) for automatic grid generation -% Alternatively the position of a few sources at locations of interest can -% be specified, for example obtained from an anatomical or functional MRI -% cfg.grid.pos = Nx3 matrix with position of each source -% cfg.grid.dim = [Nx Ny Nz] vector with dimensions in case of 3-D grid (optional) -% cfg.grid.inside = vector with indices of the sources inside the brain (optional) -% cfg.grid.outside = vector with indices of the sources outside the brain (optional) -% You can also use the PREPARE_LEADFIELD function to create a grid with -% dipole positions and with precomputed leadfields. -% -% The following strategies are supported to obtain statistics for the source parameters using -% multiple trials in the data, either directly or through a resampling-based approach -% cfg.singletrial = 'no' or 'yes' construct filter from average, apply to single trials -% cfg.rawtrial = 'no' or 'yes' construct filter from single trials, apply to single trials -% cfg.jackknife = 'no' or 'yes' jackknife resampling of trials -% cfg.pseudovalue = 'no' or 'yes' pseudovalue resampling of trials -% cfg.bootstrap = 'no' or 'yes' bootstrap resampling of trials -% cfg.numbootstrap = number of bootstrap replications (e.g. number of original trials) -% If none of these options is specified, the average over the trials will -% be computed prior to computing the source reconstruction. -% -% To obtain statistics over the source parameters between two conditions, you -% can also use a resampling procedure that reshuffles the trials over both -% conditions. In that case, you should call the function with two datasets -% containing single trial data like -% [source] = sourceanalysis(cfg, freqA, freqB) -% [source] = sourceanalysis(cfg, timelockA, timelockB) -% and you should specify -% cfg.randomization = 'no' or 'yes' -% cfg.permutation = 'no' or 'yes' -% cfg.numrandomization = number, e.g. 500 -% cfg.numpermutation = number, e.g. 500 or 'all' -% -% You should specify the volume conductor model with -% cfg.hdmfile = string, file containing the volume conduction model -% or alternatively -% cfg.vol = structure with volume conduction model -% -% If the sensor information is not contained in the data itself you should -% also specify the sensor information using -% cfg.gradfile = string, file containing the gradiometer definition -% cfg.elecfile = string, file containing the electrode definition -% or alternatively -% cfg.grad = structure with gradiometer definition -% cfg.elec = structure with electrode definition -% -% If you have not specified a grid with pre-computed leadfields, -% the leadfield for each grid location will be computed on the fly. -% In that case you can modify the leadfields by reducing the rank -% (i.e. remove the weakest orientation), or by normalizing each -% column. -% cfg.reducerank = 'no', or number (default = 3 for EEG, 2 for MEG) -% cfg.normalize = 'no' or 'yes' (default = 'no') -% -% Other configuration options are -% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), -% see CHANNELSELECTION for details -% cfg.frequency = single number (in Hz) -% cfg.latency = single number in seconds, for time-frequency analysis -% cfg.lambda = number or empty for automatic default -% cfg.refchan = reference channel label (for coherence) -% cfg.refdip = reference dipole location (for coherence) -% cfg.supchan = suppressed channel label(s) -% cfg.supdip = suppressed dipole location(s) -% cfg.keeptrials = 'no' or 'yes' -% cfg.keepleadfield = 'no' or 'yes' -% cfg.projectnoise = 'no' or 'yes' -% cfg.keepfilter = 'no' or 'yes' -% cfg.keepcsd = 'no' or 'yes' -% cfg.keepmom = 'no' or 'yes' -% cfg.feedback = 'no', 'text', 'textbar', 'gui' (default = 'text') -% -% See also SOURCEDESCRIPTIVES, SOURCESTATISTICS, PREPARE_LEADFIELD - -% Undocumented local options: -% cfg.numcomponents -% cfg.refchannel -% cfg.trialweight = 'equal' or 'proportional' -% cfg.powmethod = 'lambda1' or 'trace' -% -% This function depends on PREPARE_DIPOLE_GRID which has the following options: -% cfg.grid.xgrid (default set in PREPARE_DIPOLE_GRID: cfg.grid.xgrid = 'auto'), documented -% cfg.grid.ygrid (default set in PREPARE_DIPOLE_GRID: cfg.grid.ygrid = 'auto'), documented -% cfg.grid.zgrid (default set in PREPARE_DIPOLE_GRID: cfg.grid.zgrid = 'auto'), documented -% cfg.grid.resolution, documented -% cfg.grid.pos, documented -% cfg.grid.dim, documented -% cfg.grid.inside, documented -% cfg.grid.outside, documented -% cfg.mri -% cfg.mriunits -% cfg.smooth -% cfg.sourceunits -% cfg.threshold -% cfg.symmetry -% -% This function depends on PREPARE_FREQ_MATRICES which has the following options: -% cfg.channel (default set in SOURCEANALYSIS: cfg.channel = 'all'), documented -% cfg.dicsfix -% cfg.frequency, documented -% cfg.latency, documented -% cfg.refchan, documented -% -% This function depends on PREPARE_RESAMPLED_DATA which has the following options: -% cfg.jackknife (default set in SOURCEANALYSIS: cfg.jackknife = 'no'), documented -% cfg.numbootstrap, documented -% cfg.numcondition (set in SOURCEANALYSIS: cfg.numcondition = 2) -% cfg.numpermutation (default set in SOURCEANALYSIS: cfg.numpermutation = 100), documented -% cfg.numrandomization (default set in SOURCEANALYSIS: cfg.numrandomization = 100), documented -% cfg.permutation (default set in SOURCEANALYSIS: cfg.permutation = 'no'), documented -% cfg.pseudovalue (default set in SOURCEANALYSIS: cfg.pseudovalue = 'no'), documented -% cfg.randomization (default set in SOURCEANALYSIS: cfg.randomization = 'no'), documented -% -% This function depends on PREPARE_VOL_SENS which has the following options: -% cfg.channel, (default set in SOURCEANALYSIS: cfg.channel = 'all'), documented -% cfg.elec, documented -% cfg.elecfile, documented -% cfg.grad, documented -% cfg.gradfile, documented -% cfg.hdmfile, documented -% cfg.order -% cfg.vol, documented -% -% This function depends on PREPARE_LEADFIELD which has the following options: -% cfg.feedback, (default set in SOURCEANALYSIS: cfg.feedback = 'text'), documented -% cfg.grid, documented -% cfg.lbex -% cfg.normalize (default set in SOURCEANALYSIS), documented -% cfg.previous -% cfg.reducerank (default set in SOURCEANALYSIS), documented -% cfg.sel50p -% cfg.version - -% Copyright (c) 2003-2008, Robert Oostenveld, F.C. Donders Centre -% -% $Log: sourceanalysis.m,v $ -% Revision 1.141 2009/10/12 14:44:07 jansch -% built in possibility (undocumented) to efficiently project single trial estimates -% through precomputed lcmv filters -% -% Revision 1.140 2009/06/04 13:37:28 marvger -% changed mvlap name to mvl to make it consistent with literature -% -% Revision 1.139 2009/05/20 16:53:30 marvger -% added support for mvlap method (tentative) -% -% Revision 1.138 2009/03/26 13:32:12 roboos -% added SAM as beamformer method -% fixed bug in the default assignment of reducerank, which for some MEG systems caused the reducerank default to be 3 instead of 2 (which is preferred) -% -% Revision 1.137 2009/03/11 11:27:34 roboos -% added a comment and removed a now obsolete channelselection call -% -% Revision 1.136 2009/03/06 13:02:59 sashae -% changed default cfg.projectnoise='yes' to 'no' -% -% Revision 1.135 2009/02/06 10:53:10 jansch -% added experimental possibility to apply prewhitening. fixed incorrect -% conjugate transposition and replaced by explicit transpose() -% -% Revision 1.134 2009/02/05 10:22:07 roboos -% better support for single-trial data, thanks to Vladimir -% -% Revision 1.133 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.132 2009/01/19 12:29:51 roboos -% preallocate the fake covariance matrix in case it is absent in the data -% ensure that length(size(cov))==2 in case of Ntrials==1 (i.e. when keeptrials=yes and only one trial in the data) -% -% Revision 1.131 2008/11/21 13:21:35 sashae -% added call to checkconfig at start and end of fucntion -% -% Revision 1.130 2008/10/02 15:32:21 sashae -% replaced call to createsubcfg with checkconfig -% -% Revision 1.129 2008/09/26 12:42:18 sashae -% checkconfig: checks if the input cfg is valid for this function -% -% Revision 1.128 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.127 2008/07/15 19:56:44 roboos -% moved cfg details for dipole grid to subcfg (cfg.grid)subcfg (cfg.grid.xxx) -% -% Revision 1.126 2008/07/07 12:37:42 roboos -% fixed bug in channelordering in case sens.label and data.label were inconsistent -% -% Revision 1.125 2008/04/10 08:03:11 roboos -% renamed the fieldtrip/private/prepare_vol_sens function into prepare_headmodel -% -% Revision 1.124 2007/05/15 07:01:29 roboos -% updated help -% -% Revision 1.123 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.122 2007/03/30 17:05:40 ingnie -% checkinput; only proceed when input data is allowed datatype -% -% Revision 1.121 2007/03/27 11:05:19 ingnie -% changed call to fixdimord in call to checkinput -% -% Revision 1.120 2007/03/05 15:31:37 roboos -% added empty defaults for refchan/supchan in case of method=pcc -% -% Revision 1.119 2006/10/19 15:19:14 roboos -% switched to using beamformer_lcmv and beamformer_dics for the specific methods -% -% Revision 1.118 2006/10/12 13:04:34 roboos -% updated documentation -% -% Revision 1.117 2006/10/04 08:10:51 roboos -% changed default for cfg.reducerank, new default is 2 for MEG and 3 for EEG -% -% Revision 1.116 2006/10/04 07:10:07 roboos -% updated documentation -% -% Revision 1.115 2006/10/02 13:01:21 roboos -% also recognize rpttap as part of the dimord -% -% Revision 1.114 2006/08/16 08:23:36 roboos -% updated documentation -% -% Revision 1.113 2006/07/05 10:34:52 roboos -% minor change in documentation -% -% Revision 1.112 2006/07/05 10:32:14 roboos -% minor change in documentation -% -% Revision 1.111 2006/07/05 10:26:11 roboos -% updated documentation, the cfg.xgrid/ygrid/zgrid options have moved to cfg.grid substructure -% removed default 'auto' values for xgrid/ygrid/zgrid (were similar to the default values in prepare_dipole_grid) -% -% Revision 1.110 2006/07/04 17:06:23 ingnie -% updated documentation -% -% Revision 1.109 2006/07/04 16:04:50 roboos -% renamed option 'jacknife' into 'jackknife' for consistency, maintain backward compatibility with cfgs and old data -% -% Revision 1.108 2006/06/26 09:26:03 ingnie -% fixed bug (forgotten "end") -% -% Revision 1.107 2006/06/22 12:27:41 roboos -% optionally pass the covariance as input argument to MUSIC -% -% Revision 1.106 2006/06/20 16:25:56 ingnie -% updated documentation -% -% Revision 1.105 2006/06/14 11:55:07 roboos -% switched from construct_optarg() subfunction to the new createsubcfg function -% -% Revision 1.104 2006/06/13 14:48:09 ingnie -% updated documentation -% -% Revision 1.103 2006/05/23 10:15:31 roboos -% Changed the initial construction of the dipole grid, either with or -% without precomputed leadfields (there was a case in which the automatic -% grid would not be tight). Improved documentation around the disabled -% section for singletrial=yes. Some other small changes. -% -% Revision 1.102 2006/05/10 08:14:09 roboos -% removed support for parallelization on cluster, only precompute leadfields -% if not already present, implemented subfunction construct_optarg() for -% clean and consistent construction of key-value arguments for the low-level -% inverse methods, allow additional arguments to be passed transparently -% to the low-level inverse methods by means of cfg.xxx.key=value, where -% xxx=pcc/lcmv/dics/rv/music/loreta/mne -% -% Revision 1.101 2006/05/03 15:10:11 roboos -% only define submethod in the case of method=dics -% -% Revision 1.100 2006/04/20 09:58:34 roboos -% updated documentation -% -% Revision 1.99 2006/04/12 08:38:01 ingnie -% updated documentation -% -% Revision 1.98 2006/04/10 16:33:46 ingnie -% updated documentation -% -% Revision 1.97 2006/04/06 16:17:10 ingnie -% updated documentation -% -% Revision 1.96 2006/03/22 07:53:06 roboos -% small change in documentation -% -% Revision 1.95 2006/03/09 08:19:06 roboos -% apply fixdimord to the baseline condition data if present -% -% Revision 1.94 2006/02/24 16:41:39 roboos -% changed foi and toi into freq and time for frequency data -% -% Revision 1.93 2006/02/23 10:28:16 roboos -% changed dimord strings for consistency, changed toi and foi into time and freq, added fixdimord where neccessary -% -% Revision 1.92 2006/02/07 22:21:01 roboos -% changed the xgrid/ygrid/zgrid and dim in the output source structure (from cfg to grid), they can be different from the cfg since prepare_dipole_grid will make the box tight -% -% Revision 1.91 2006/02/07 20:08:23 roboos -% changed all occurences of a dimord with chancmb (was previous sgncmb) into chan -% -% Revision 1.90 2006/02/01 12:26:00 roboos -% made all uses of dimord consistent with the common definition of data dimensions, see the fixdimord() function -% -% Revision 1.89 2006/01/24 20:51:57 roboos -% fixed obvious typo -% -% Revision 1.88 2006/01/24 20:02:50 roboos -% renamed dics_cohrefdip and cohrefchan into cfg.method=dics (backwards compatible) -% added extra local variable "submethod" that indicates the details for dics -% -% Revision 1.87 2006/01/24 14:28:33 roboos -% small change in documentation -% -% Revision 1.86 2005/11/24 16:25:16 roboos -% added average or single trial ERF to the input of PCC beamformer in timedomain -% -% Revision 1.85 2005/11/16 09:07:03 roboos -% added option cfg.powmethod to determine whether lambda1 or trace is used in beamformer -% -% Revision 1.84 2005/11/08 11:07:13 roboos -% added support for normalize and reducerank, by passing these options on to the beamformer subfunction -% -% Revision 1.83 2005/09/29 00:45:00 roboos -% added multiple signal classification as reconstruction technique for timelocked data -% -% Revision 1.82 2005/10/25 08:42:56 roboos -% changed the detection of either frequency or timelock data using flags (isfreq, iscomp, istimelock) instead of by renaming the input data object to freq/timelock -% renamed the freq/timelock variable throughout the code into "data" -% added support for freq/comp data to the non-beamforming timelocked source reconstruction methods -% -% Revision 1.81 2005/10/14 15:47:03 roboos -% add an identity covariance matrix to timelocked data if not present -% some cosmetic changes -% -% Revision 1.80 2005/10/05 11:14:11 roboos -% updated documentation -% added support for LORETA (still experimental) -% removed all code that referred to unimplemented parallelization for some of the reconstruction methods -% -% Revision 1.79 2005/09/05 06:36:56 jansch -% keep cumtapcnt of freq-input in output -% -% Revision 1.78 2005/08/16 13:15:55 jansch -% *** empty log message *** -% -% Revision 1.77 2005/08/16 12:43:03 jansch -% included possibility to have 'rpttap_sgncmb_frq' as input -% -% Revision 1.76 2005/06/29 12:46:29 roboos -% the following changes were done on a large number of files at the same time, not all of them may apply to this specific file -% - added try-catch around the inclusion of input data configuration -% - moved cfg.version, cfg.previous and the assignment of the output cfg to the end -% - changed help comments around the configuration handling -% - some changes in whitespace -% -% Revision 1.75 2005/06/17 09:01:13 roboos -% moved implementation of keepmom and keepcsd over to beamformer subfunction -% -% Revision 1.74 2005/05/17 17:56:38 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% implemented support for projecting the single trial fft matrix through the filters of beamformer_pcc -% -% Revision 1.73 2005/04/25 16:05:11 roboos -% includedupdated options for cortex segmentation based grid in the documentation (not in main documentation) -% -% Revision 1.72 2005/03/03 13:57:29 roboos -% implemented pseudovalue resampling, i.e. a combination of jackknife and the complete average -% -% Revision 1.71 2005/03/03 10:57:43 roboos -% Renamed the source analysis methods, the submethods for dics are now -% recognized by their additional required fields (refchan/refdip). Added -% support for experimental pcc method (not yet implemented in a clean way), -% pcc is now a re3cognised submethod of the standard beamformer function. -% Included mne method in the documentation. -% -% Revision 1.70 2005/02/14 21:53:14 roboos -% changed assignment of empty struct to dip into 'clear dip' (for mentat-style parallelization) -% -% Revision 1.69 2005/01/26 08:38:50 roboos -% extended and fixed the experimental partcanoncorr code -% -% Revision 1.68 2005/01/11 12:43:03 roboos -% added temporary hack to support partcanoncorr as a beamformer method -% -% Revision 1.67 2005/01/10 17:26:46 roboos -% added support for 2nd method of parallelizing the code, separated -% two methods by the name of the backend toolbox (beowulf or mentat) -% -% Revision 1.66 2004/12/08 18:00:13 roboos -% implemented consistent method of selecting a subset of channels for -% forward and inverse computations using cfg.channel and updated the -% ducumentation -% -% Revision 1.65 2004/10/21 09:01:34 roboos -% added numcondition=2 for averaging two conditions while resampling -% -% Revision 1.64 2004/09/28 08:01:03 roboos -% added residual variance scanning with single dipole (cfg.method=rv) -% added 'yes' as allowed value for cfg.parallel -% -% Revision 1.63 2004/09/21 14:30:07 roboos -% fixed bug in DICS/power for two conditions (Nbaseline~=Ntrials) -% -% Revision 1.62 2004/09/21 13:22:15 roboos -% in the previous revision (1.61) initial support for MNE was added but accidentally not logged in CVS -% this revision only adds a single comment line with the undocumented method=mne option -% -% Revision 1.61 2004/09/21 13:15:32 roboos -% *** empty log message *** -% -% Revision 1.60 2004/09/21 12:49:00 roboos -% fixed a bug in averaging of 2 input conditions using prepare_resampled_data (using cfg2) -% -% Revision 1.59 2004/09/14 16:28:49 roboos -% incorporated the changes on the "exp-resampling-parallel" branch -% new implementation of resampling/randomization -% new implementation of parallellization -% -% Revision 1.58.4.5 2004/09/08 16:36:00 roboos -% fixed many bugs that stopped execution through rigorous testing -% correctness of the output still has to be evaluated -% non-proportional trial weighing is not implemented yet -% -% Revision 1.58.4.4 2004/09/08 12:25:13 roboos -% auto-indented code using matlab editor, fixed one incorrect "end" -% -% Revision 1.58.4.3 2004/09/08 09:35:49 roboos -% implemented prepare_resampled_data and new evalwulf for DICS, some related changes to LCMV -% -% Revision 1.58.4.2 2004/09/06 16:32:28 roboos -% implemented new prepare_resampled_data for a few resampling strategies and lcmv only, untested -% -% Revision 1.58.4.1 2004/09/06 16:10:26 roboos -% disabled parallelization over grid (still in code) -% moved documentation for paralellization to hidden location -% fixed bug in jackknife+lcmv -% -% Revision 1.58 2004/08/16 12:14:33 roboos -% fixed small bug that was introduced in the previous update -% -% Revision 1.57 2004/08/16 10:53:09 roboos -% fixed bug for lcmv together with randomization (trial assignment was oubviously wrong) -% -% Revision 1.56 2004/08/16 10:01:23 roboos -% updated help, fixed bug in output assignment with permutation, changed handling of keepleadfield and precomputed leadfields -% -% Revision 1.55 2004/08/06 12:23:04 roboos -% fixed small bug in default setting for cfg.permutation -% -% Revision 1.54 2004/08/05 07:14:25 roboos -% implemented permutation analogous to randomization, updated and restructured help -% -% Revision 1.53 2004/08/05 06:37:29 roboos -% extra removal of leadfield in output source and cfg, removed old revision comments -% -% Revision 1.52 2004/08/04 11:53:03 roboos -% updated the help -% -% Revision 1.51 2004/06/09 10:07:19 roberto -% added version information and input data configuration to output cfg -% -% Revision 1.50 2004/03/01 11:01:55 roberto -% added precomputed filters to grid and using these, implemented singletrial for dics -% -% Revision 1.49 2004/02/05 12:19:36 roberto -% moved the code that was common with dipolefitting into separate prepare_grid and prepare_sens_vol functions -% also renamed internal subfunction freq_to_matrices to prepare_freq_matrices and moved into separate function -% -% Revision 1.48 2004/02/02 10:48:11 roberto -% fixed two bugs in randomization for lcmv & timelocked data -% -% Revision 1.47 2004/01/26 09:04:54 roberto -% fixed serious bug in selection of spheres for multi-sphere volume model -% selection was based on wrong indices, causing reference magnetometer spheres -% and gradiometer spheres to be mixed up -% -% Revision 1.46 2004/01/22 10:50:55 roberto -% fixed bug in cfg.keepmom -% improved handling of pre-computation of leadfield without scanning -% -% Revision 1.45 2004/01/21 13:07:52 roberto -% added a fprintf-line to indicate the progress in randomization (which takes quite some time) -% -% Revision 1.44 2004/01/20 09:09:45 roberto -% added computation of leadfield in case not provided and multiple trials have to -% be scanned -% -% Revision 1.43 2004/01/14 14:29:43 roberto -% changed handling of sgncmbindx etc inside freq_to_matrices subfunction -% mainly cosmetical changes, but also fixed bug in refindx for pow_refchan -% -% Revision 1.42 2004/01/14 08:50:05 roberto -% changed the name of output variables for randomization -% -% Revision 1.41 2004/01/08 09:25:35 roberto -% canged cfg.label into freq.sgn inside freq_to_matrices subfunction to fix bug -% -% Revision 1.40 2004/01/08 09:14:49 roberto -% added option keepmom to save memory, default is 'yes' - -fieldtripdefs - -% set a timer to determine how long the sourceanalysis takes in total -tic; - -cfg = checkconfig(cfg, 'trackconfig', 'on'); - -% check if the input data is valid for this function -data = checkdata(data, 'datatype', {'timelock', 'freq', 'comp'}, 'feedback', 'yes'); -if nargin>2 - baseline = checkdata(baseline, 'datatype', {'timelock', 'freq', 'comp'}, 'feedback', 'yes'); -end - -% check if the input cfg is valid for this function -cfg = checkconfig(cfg, 'renamed', {'jacknife', 'jackknife'}); -cfg = checkconfig(cfg, 'renamed', {'refchannel', 'refchan'}); -cfg = checkconfig(cfg, 'renamedval', {'method', 'power', 'dics'}); -cfg = checkconfig(cfg, 'renamedval', {'method', 'coh_refchan', 'dics'}); -cfg = checkconfig(cfg, 'renamedval', {'method', 'coh_refdip', 'dics'}); -cfg = checkconfig(cfg, 'renamedval', {'method', 'dics_cohrefchan', 'dics'}); -cfg = checkconfig(cfg, 'renamedval', {'method', 'dics_cohrefdip', 'dics'}); -cfg = checkconfig(cfg, 'forbidden', {'parallel'}); - -% determine the type of input data -if isfield(data, 'freq') - isfreq = 1; - iscomp = 0; - istimelock = 0; -elseif isfield(data, 'topo') - isfreq = 0; - iscomp = 1; - istimelock = 0; -elseif isfield(data, 'time') - iscomp = 0; - isfreq = 0; - istimelock = 1; -else - error('input data is not recognized'); -end - -% set the defaults -if ~isfield(cfg, 'method') && istimelock, cfg.method = 'lcmv'; end -if ~isfield(cfg, 'method') && isfreq, cfg.method = 'dics'; end -if ~isfield(cfg, 'keeptrials') cfg.keeptrials = 'no'; end -if ~isfield(cfg, 'keepfilter') cfg.keepfilter = 'no'; end -if ~isfield(cfg, 'keepleadfield') cfg.keepleadfield = 'no'; end -if ~isfield(cfg, 'keepcsd') cfg.keepcsd = 'no'; end -if ~isfield(cfg, 'keepmom') cfg.keepmom = 'yes'; end -if ~isfield(cfg, 'projectnoise') cfg.projectnoise = 'no'; end -if ~isfield(cfg, 'trialweight') cfg.trialweight = 'equal'; end -if ~isfield(cfg, 'jackknife'), cfg.jackknife = 'no'; end -if ~isfield(cfg, 'pseudovalue'), cfg.pseudovalue = 'no'; end -if ~isfield(cfg, 'bootstrap'), cfg.bootstrap = 'no'; end -if ~isfield(cfg, 'singletrial'), cfg.singletrial = 'no'; end -if ~isfield(cfg, 'rawtrial'), cfg.rawtrial = 'no'; end -if ~isfield(cfg, 'randomization'), cfg.randomization = 'no'; end -if ~isfield(cfg, 'numrandomization'), cfg.numrandomization = 100; end -if ~isfield(cfg, 'permutation'), cfg.permutation = 'no'; end -if ~isfield(cfg, 'numpermutation'), cfg.numpermutation = 100; end -if ~isfield(cfg, 'wakewulf'), cfg.wakewulf = 'yes'; end -if ~isfield(cfg, 'killwulf'), cfg.killwulf = 'yes'; end -if ~isfield(cfg, 'feedback'), cfg.feedback = 'text'; end -if ~isfield(cfg, 'supdip'), cfg.supdip = []; end -if ~isfield(cfg, 'lambda'), cfg.lambda = []; end -if ~isfield(cfg, 'powmethod'), cfg.powmethod = []; end -if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end -if ~isfield(cfg, 'normalize'), cfg.normalize = 'no'; end -if ~isfield(cfg, 'prewhiten'), cfg.prewhiten = 'no'; end -% if ~isfield(cfg, 'reducerank'), cfg.reducerank = 'no'; end % the default for this depends on EEG/MEG and is set below - -% put the low-level options pertaining to the source reconstruction method in their own field -% put the low-level options pertaining to the dipole grid in their own field -cfg = checkconfig(cfg, 'createsubcfg', {cfg.method, 'grid'}); - -convertfreq = 0; -convertcomp = 0; -if ~istimelock && (strcmp(cfg.method, 'mne') || strcmp(cfg.method, 'loreta') || strcmp(cfg.method, 'rv') || strcmp(cfg.method, 'music')) - % these timelock methods are also supported for frequency or component data - if isfreq - [data, cfg] = freq2timelock(cfg, data); - convertfreq = 1; % flag indicating that the data was converted - elseif iscomp - [data, cfg] = comp2timelock(cfg, data); - convertcomp = 1; % flag indicating that the data was converted - end - istimelock = 1; % from now on the data can be treated as timelocked - isfreq = 0; - iscomp = 0; -end - -% select only those channels that are present in the data -cfg.channel = channelselection(cfg.channel, data.label); - -if nargin>2 && (strcmp(cfg.randomization, 'no') && strcmp(cfg.permutation, 'no') && strcmp(cfg.prewhiten, 'no')) - error('input of two conditions only makes sense if you want to randomize or permute, or if you want to prewhiten'); -elseif nargin<3 && (strcmp(cfg.randomization, 'yes') || strcmp(cfg.permutation, 'yes')) - error('randomization or permutation requires that you give two conditions as input'); -end - -if isfield(cfg, 'latency') && istimelock - error('specification of cfg.latency is only required for time-frequency data'); -end - -if sum([strcmp(cfg.jackknife, 'yes'), strcmp(cfg.bootstrap, 'yes'), strcmp(cfg.pseudovalue, 'yes'), strcmp(cfg.singletrial, 'yes'), strcmp(cfg.rawtrial, 'yes'), strcmp(cfg.randomization, 'yes'), strcmp(cfg.permutation, 'yes')])>1 - error('jackknife, bootstrap, pseudovalue, singletrial, rawtrial, randomization and permutation are mutually exclusive'); -end - -if isfreq - if ~strcmp(data.dimord, 'chan_freq') && ... - ~strcmp(data.dimord, 'chan_freq_time') && ... - ~strcmp(data.dimord, 'rpt_chan_freq') && ... - ~strcmp(data.dimord, 'rpt_chan_freq_time') && ... - ~strcmp(data.dimord, 'rpttap_chan_freq') && ... - ~strcmp(data.dimord, 'rpttap_chan_freq_time') - error('dimord of input frequency data is not recognized'); - end -end - -% collect and preprocess the electrodes/gradiometer and head model -[vol, sens, cfg] = prepare_headmodel(cfg, data); - -% It might be that the number of channels in the data, the number of -% channels in the electrode/gradiometer definition and the number of -% channels in the multisphere volume conduction model are different. -% Hence a subset of the data channels will be used. -Nchans = length(cfg.channel); - -% set the default for reducing the rank of the leadfields, this is an -% option to the specific method and will be passed on to the low-level -% function -if ~isfield(cfg.(cfg.method), 'reducerank') - if senstype(sens, 'meg') - cfg.(cfg.method).reducerank = 2; - else - cfg.(cfg.method).reducerank = 3; - end -end - -if strcmp(cfg.keepleadfield, 'yes') && (~isfield(cfg, 'grid') || ~isfield(cfg.grid, 'leadfield')) - % precompute the leadfields upon the users request - fprintf('precomputing leadfields\n'); - [grid, cfg] = prepare_leadfield(cfg, data); -elseif (strcmp(cfg.permutation, 'yes') || ... - strcmp(cfg.randomization, 'yes') || ... - strcmp(cfg.bootstrap, 'yes') || ... - strcmp(cfg.jackknife, 'yes') || ... - strcmp(cfg.pseudovalue, 'yes') || ... - strcmp(cfg.singletrial, 'yes') || ... - strcmp(cfg.rawtrial, 'yes')) && (~isfield(cfg, 'grid') || ~isfield(cfg.grid, 'leadfield')) - % also precompute the leadfields if multiple trials have to be processed - fprintf('precomputing leadfields for efficient handling of multiple trials\n'); - [grid, cfg] = prepare_leadfield(cfg, data); -else - % only prepare the grid positions, the leadfield will be computed on the fly if not present - [grid, cfg] = prepare_dipole_grid(cfg, vol, sens); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% do frequency domain source reconstruction -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if isfreq && any(strcmp(cfg.method, {'dics', 'pcc'})) - - if strcmp(cfg.method, 'pcc') - % HACK: requires some extra defaults - if ~isfield(cfg, 'refdip'), cfg.refdip = []; end - if ~isfield(cfg, 'supdip'), cfg.supdip = []; end - if ~isfield(cfg, 'refchan'), cfg.refchan = []; end - if ~isfield(cfg, 'supchan'), cfg.supchan = []; end - cfg.refchan = channelselection(cfg.refchan, data.label); - cfg.supchan = channelselection(cfg.supchan, data.label); - - % HACK: use some experimental code - if nargin>2 && strcmp(cfg.prewhiten, 'no'), - error('not supported') - end - tmpcfg = cfg; - tmpcfg.refchan = ''; % prepare_freq_matrices should not know explicitly about the refchan - tmpcfg.channel = cfg.channel(:)'; - if isfield(cfg, 'refchan') - % add the refchan implicitely - tmpcfg.channel = [tmpcfg.channel cfg.refchan(:)']; - end - if isfield(cfg, 'supchan') - % add the supchan implicitely - tmpcfg.channel = [tmpcfg.channel cfg.supchan(:)']; - end - - % select the data in the channels and the frequency of interest - [Cf, Cr, Pr, Ntrials, tmpcfg] = prepare_freq_matrices(tmpcfg, data); - if strcmp(cfg.prewhiten, 'yes'), - [Cfb, Crb, Prb, Ntrialsb, tmpcfgb] = prepare_freq_matrices(tmpcfg, baseline); - Cf = prewhitening_filter2(squeeze(mean(Cf,1)), squeeze(mean(Cfb,1))); - Ntrials = 1; - end - - if isfield(cfg, 'refchan') && ~isempty(cfg.refchan) - [dum, refchanindx] = match_str(cfg.refchan, tmpcfg.channel); - else - refchanindx = []; - end - if isfield(cfg, 'supchan') && ~isempty(cfg.supchan) - [dum, supchanindx] = match_str(cfg.supchan,tmpcfg.channel); - else - supchanindx = []; - end - Nchans = length(tmpcfg.channel); % update the number of channels - - % if the input data has a complete fourier spectrum, project it through the filters - % FIXME it was incorrect , since the - % ' leads to a conjugate transposition check this in beamformer_pcc - if isfield(data, 'fourierspctrm') - [dum, datchanindx] = match_str(tmpcfg.channel, data.label); - fbin = nearest(data.freq, cfg.frequency); - if strcmp(data.dimord, 'chan_freq') - avg = data.fourierspctrm(datchanindx, fbin); - elseif strcmp(data.dimord, 'rpt_chan_freq') || strcmp(data.dimord, 'rpttap_chan_freq'), - %avg = data.fourierspctrm(:, datchanindx, fbin)'; - avg = transpose(data.fourierspctrm(:, datchanindx, fbin)); - elseif strcmp(data.dimord, 'chan_freq_time') - tbin = nearest(data.time, cfg.latency); - avg = data.fourierspctrm(datchanindx, fbin, tbin); - elseif strcmp(data.dimord, 'rpt_chan_freq_time') || strcmp(data.dimord, 'rpttap_chan_freq_time'), - tbin = nearest(data.time, cfg.latency); - %avg = data.fourierspctrm(:, datchanindx, fbin, tbin)'; - avg = transpose(data.fourierspctrm(:, datchanindx, fbin, tbin)); - end - else - avg = []; - end - - else - % HACK: use the default code - % convert the input data, so that Cf, Cr and Pr contain either the average over all trials (if Ntrials==1) - % or the individual cross-spectral-densities/powers of each individual trial (if Ntrials>1) - [Cf, Cr, Pr, Ntrials, cfg] = prepare_freq_matrices(cfg, data); - end - - if strcmp(cfg.method, 'dics') - % assign a descriptive name to each of the dics sub-methods, the default is power only - if strcmp(cfg.method, 'dics') && isfield(cfg, 'refdip') && ~isempty(cfg.refdip); - submethod = 'dics_refdip'; - elseif strcmp(cfg.method, 'dics') && isfield(cfg, 'refchan') && ~isempty(cfg.refchan); - submethod = 'dics_refchan'; - else - submethod = 'dics_power'; - end - end - - % fill these with NaNs, so that I dont have to treat them separately - if isempty(Cr), Cr = nan*zeros(Ntrials, Nchans, 1); end - if isempty(Pr), Pr = nan*zeros(Ntrials, 1, 1); end - - if nargin>2 - % repeat the conversion for the baseline condition - [bCf, bCr, bPr, Nbaseline, cfg] = prepare_freq_matrices(cfg, baseline); - % fill these with NaNs, so that I dont have to treat them separately - if isempty(bCr), bCr = nan*zeros(Nbaseline, Nchans, 1); end - if isempty(bPr), bPr = nan*zeros(Nbaseline, 1, 1); end - % rename the active condition for convenience - aCf = Cf; - aCr = Cr; - aPr = Pr; - % this is required for averaging 2 conditions using prepare_resampled_data - cfg2 = []; - cfg2.numcondition = 2; - % this is required for randomizing/permuting 2 conditions using prepare_resampled_data - cfg.numcondition = 2; - end - - % prepare the resampling of the trials, or average the data if multiple trials are present and no resampling is neccessary - if (Ntrials<=1) && (strcmp(cfg.jackknife, 'yes') || strcmp(cfg.bootstrap, 'yes') || strcmp(cfg.pseudovalue, 'yes') || strcmp(cfg.singletrial, 'yes') || strcmp(cfg.rawtrial, 'yes') || strcmp(cfg.randomization, 'yes') || strcmp(cfg.permutation, 'yes')) - error('multiple trials required in the data\n'); - - elseif strcmp(cfg.permutation, 'yes') - % compute the cross-spectral density matrix without resampling - [dum, avg_aCf, avg_aCr, avg_aPr, avg_bCf, avg_bCr, avg_bPr] = prepare_resampled_data(cfg2 , aCf, aCr, aPr, bCf, bCr, bPr); - % compute the cross-spectral density matrix with random permutation - [dum, rnd_aCf, rnd_aCr, rnd_aPr, rnd_bCf, rnd_bCr, rnd_bPr] = prepare_resampled_data(cfg, aCf, aCr, aPr, bCf, bCr, bPr); - % concatenate the different resamplings - Cf = cat(1, reshape(avg_aCf, [1 Nchans Nchans]), reshape(avg_bCf, [1 Nchans Nchans]), rnd_aCf, rnd_bCf); - Cr = cat(1, reshape(avg_aCr, [1 Nchans 1 ]), reshape(avg_bCr, [1 Nchans 1 ]), rnd_aCr, rnd_bCr); - Pr = cat(1, reshape(avg_aPr, [1 1 1 ]), reshape(avg_bPr, [1 1 1 ]), rnd_aPr, rnd_bPr); - % clear temporary working copies - clear avg_aCf avg_aCr avg_aPr avg_bCf avg_bCr avg_bPr - clear rnd_aCf rnd_aCr rnd_aPr rnd_bCf rnd_bCr rnd_bPr - % the order of the resamplings should be [avgA avgB rndA rndB rndA rndB rndA rndB ....] - Nrepetitions = 2*cfg.numpermutation + 2; - order = [1 2 3:2:Nrepetitions 4:2:Nrepetitions]; - Cf = Cf(order,:,:); - Cr = Cr(order,:,:); - Pr = Pr(order,:,:); - - elseif strcmp(cfg.randomization, 'yes') - % compute the cross-spectral density matrix without resampling - [dum, avg_aCf, avg_aCr, avg_aPr, avg_bCf, avg_bCr, avg_bPr] = prepare_resampled_data(cfg2 , aCf, aCr, aPr, bCf, bCr, bPr); - % compute the cross-spectral density matrix with random resampling - [dum, rnd_aCf, rnd_aCr, rnd_aPr, rnd_bCf, rnd_bCr, rnd_bPr] = prepare_resampled_data(cfg, aCf, aCr, aPr, bCf, bCr, bPr); - % concatenate the different resamplings - Cf = cat(1, reshape(avg_aCf, [1 Nchans Nchans]), reshape(avg_bCf, [1 Nchans Nchans]), rnd_aCf, rnd_bCf); - Cr = cat(1, reshape(avg_aCr, [1 Nchans 1 ]), reshape(avg_bCr, [1 Nchans 1 ]), rnd_aCr, rnd_bCr); - Pr = cat(1, reshape(avg_aPr, [1 1 1 ]), reshape(avg_bPr, [1 1 1 ]), rnd_aPr, rnd_bPr); - % clear temporary working copies - clear avg_aCf avg_aCr avg_aPr avg_bCf avg_bCr avg_bPr - clear rnd_aCf rnd_aCr rnd_aPr rnd_bCf rnd_bCr rnd_bPr - % the order of the resamplings should be [avgA avgB rndA rndB rndA rndB rndA rndB ....] - Nrepetitions = 2*cfg.numrandomization + 2; - order = [1 2 3:2:Nrepetitions 4:2:Nrepetitions]; - Cf = Cf(order,:,:); - Cr = Cr(order,:,:); - Pr = Pr(order,:,:); - - elseif strcmp(cfg.jackknife, 'yes') - % compute the cross-spectral density matrix with jackknife resampling - [cfg, Cf, Cr, Pr] = prepare_resampled_data(cfg, Cf, Cr, Pr); - Nrepetitions = Ntrials; - - elseif strcmp(cfg.bootstrap, 'yes') - % compute the cross-spectral density matrix with bootstrap resampling - [cfg, Cf, Cr, Pr] = prepare_resampled_data(cfg, Cf, Cr, Pr); - Nrepetitions = cfg.numbootstrap; - - elseif strcmp(cfg.pseudovalue, 'yes') - % compute the cross-spectral density matrix with pseudovalue resampling - [cfg, Cf, Cr, Pr] = prepare_resampled_data(cfg, Cf, Cr, Pr); - Nrepetitions = Ntrials+1; - - elseif strcmp(cfg.singletrial, 'yes') - % The idea is that beamformer uses the average covariance to construct the - % filter and applies it to the single trial covariance/csd. The problem - % is that beamformer will use the averaged covariance/csd to estimate the - % power and not the single trial covariance/csd - error('this option contains a bug, and is therefore not supported at the moment'); - Cf = Cf; % FIXME, should be averaged and repeated for each trial - Cr = Cr; % FIXME, should be averaged and repeated for each trial - Pr = Pr; % FIXME, should be averaged and repeated for each trial - Nrepetitions = Ntrials; - - elseif strcmp(cfg.rawtrial, 'yes') - % keep all the individual trials, do not average them - Cf = Cf; - Cr = Cr; - Pr = Pr; - Nrepetitions = Ntrials; - - elseif Ntrials>1 - % compute the average from the individual trials - Cf = reshape(sum(Cf, 1) / Ntrials, [Nchans Nchans]); - Cr = reshape(sum(Cr, 1) / Ntrials, [Nchans 1]); - Pr = reshape(sum(Pr, 1) / Ntrials, [1 1]); - Nrepetitions = 1; - - elseif Ntrials==1 - % no rearrangement of trials is neccesary, the data already represents the average - Cf = Cf; - Cr = Cr; - Pr = Pr; - Nrepetitions = 1; - end - - % reshape so that it also looks like one trial (out of many) - if Nrepetitions==1 - Cf = reshape(Cf , [1 Nchans Nchans]); - Cr = reshape(Cr , [1 Nchans 1]); - Pr = reshape(Pr , [1 1 1]); - end - - % get the relevant low level options from the cfg and convert into key-value pairs - optarg = cfg2keyval(getfield(cfg, cfg.method)); - - for i=1:Nrepetitions - fprintf('scanning repetition %d\n', i); - if strcmp(cfg.method, 'dics') && strcmp(submethod, 'dics_power') - dip(i) = beamformer_dics(grid, sens, vol, [], squeeze(Cf(i,:,:)), optarg{:}); - elseif strcmp(cfg.method, 'dics') && strcmp(submethod, 'dics_refchan') - dip(i) = beamformer_dics(grid, sens, vol, [], squeeze(Cf(i,:,:)), optarg{:}, 'Cr', Cr(i,:), 'Pr', Pr(i)); - elseif strcmp(cfg.method, 'dics') && strcmp(submethod, 'dics_refdip') - dip(i) = beamformer_dics(grid, sens, vol, [], squeeze(Cf(i,:,:)), optarg{:}, 'refdip', cfg.refdip); - elseif strcmp(cfg.method, 'pcc') - dip(i) = beamformer_pcc(grid, sens, vol, avg, squeeze(Cf(i,:,:)), optarg{:}, 'refdip', cfg.refdip, 'refchan', refchanindx, 'supdip', cfg.supdip, 'supchan', supchanindx); - else - error(sprintf('method ''%s'' is unsupported for source reconstruction in the frequency domain', cfg.method)); - end - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % do time domain source reconstruction - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif istimelock && any(strcmp(cfg.method, {'lcmv', 'sam', 'mne', 'loreta', 'rv', 'music', 'pcc', 'mvl'})) - - % determine the size of the data - Nsamples = size(data.avg,2); - Nchans = length(data.label); - if isfield(data, 'cov') && length(size(data.cov))==3 - Ntrials = size(data.cov,1); - elseif isfield(data, 'trial') && length(size(data.trial))==3 - Ntrials = size(data.trial,1); - else - Ntrials = 1; - end - - if isfield(data, 'cov') - % use the estimated data covariance matrix - hascovariance = 1; - else - % add a identity covariance matrix, this simplifies the handling of the different source reconstruction methods - % since the covariance is only used by some reconstruction methods and might not allways be present in the data - if Ntrials==1 - data.cov = eye(Nchans); - else - data.cov = zeros(Ntrials,Nchans,Nchans); - for i=1:Ntrials - data.cov(i,:,:) = eye(Nchans); - end - end - hascovariance = 0; - end - - if strcmp(cfg.method, 'pcc') - % HACK: requires some extra defaults - if ~isfield(cfg, 'refdip'), cfg.refdip = []; end - if ~isfield(cfg, 'supdip'), cfg.supdip = []; end - - % HACK: experimental code - if nargin>2 - error('not supported') - end - tmpcfg = []; - tmpcfg.channel = cfg.channel(:)'; - if isfield(cfg, 'refchan') - tmpcfg.channel = [tmpcfg.channel cfg.refchan(:)']; - end - if isfield(cfg, 'supchan') - tmpcfg.channel = [tmpcfg.channel cfg.supchan(:)']; - end - - % select the data in the channels of interest - [dum, datchanindx] = match_str(tmpcfg.channel, data.label); - if Ntrials==1 - data.avg = data.avg(datchanindx,:); - data.cov = data.cov(datchanindx,datchanindx); - else - data.avg = data.avg(datchanindx,:); - data.cov = data.cov(:,datchanindx,datchanindx); - data.trial = data.trial(:,datchanindx,:); - end - data.label = data.label(datchanindx); - - if isfield(cfg, 'refchan') && ~isempty(cfg.refchan) - [dum, refchanindx] = match_str(cfg.refchan, data.label); - else - refchanindx = []; - end - if isfield(cfg, 'supchan') && ~isempty(cfg.supchan) - [dum, supchanindx] = match_str(cfg.supchan, data.label); - else - supchanindx = []; - end - Nchans = length(tmpcfg.channel); % update the number of channels - - else - % HACK: use the default code - % select the channels of interest - [dum, datchanindx] = match_str(cfg.channel, data.label); - if strcmp(data.dimord, 'chan_time') - % It is in principle possible to have timelockanalysis with - % keeptrial=yes and only a single trial in the raw data. - % In that case the covariance should be represented as Nchan*Nchan - data.avg = data.avg(datchanindx,:); - data.cov = reshape(data.cov, length(datchanindx), length(datchanindx)); - data.cov = data.cov(datchanindx,datchanindx); - else - data.avg = data.avg(datchanindx,:); - data.cov = data.cov(:,datchanindx,datchanindx); - data.trial = data.trial(:,datchanindx,:); - end - data.label = data.label(datchanindx); - Nchans = length(data.label); - end - - if nargin>2 - % baseline and active are only available together for resampling purposes, - % hence I assume here that there are multiple trials in both - baseline.avg = baseline.avg(datchanindx,:); - baseline.cov = baseline.cov(:,datchanindx,datchanindx); - baseline.trial = baseline.trial(:,datchanindx,:); - % this is required for averaging 2 conditions using prepare_resampled_data - cfg2 = []; - cfg2.numcondition = 2; - end - - % prepare the resampling of the trials, or average the data if multiple trials are present and no resampling is neccessary - if (strcmp(cfg.jackknife, 'yes') || strcmp(cfg.bootstrap, 'yes') || strcmp(cfg.pseudovalue, 'yes') || strcmp(cfg.singletrial, 'yes') || strcmp(cfg.rawtrial, 'yes') || strcmp(cfg.randomization, 'yes')) && ~strcmp(data.dimord, 'rpt_chan_time') - error('multiple trials required in the data\n'); - - elseif strcmp(cfg.permutation, 'yes') - % compute the average and covariance without resampling - [dum, avgA, covA, avgB, covB] = prepare_resampled_data(cfg2 , data.trial, data.cov, baseline.trial, baseline.cov); - % compute the average and covariance with random permutation - [cfg, avRA, coRA, avRB, coRB] = prepare_resampled_data(cfg, data.trial, data.cov, baseline.trial, baseline.cov); - % concatenate the different resamplings - avg = cat(1, reshape(avgA, [1 Nchans Nsamples]), reshape(avgB, [1 Nchans Nsamples]), avRA, avRB); - Cy = cat(1, reshape(covA, [1 Nchans Nchans ]), reshape(covB, [1 Nchans Nchans ]), coRA, coRB); - % clear temporary working copies - clear avgA avgB covA covB - clear avRA avRB coRA coRB - % the order of the resamplings should be [avgA avgB randA randB randA randB randA randB ....] - Nrepetitions = 2*cfg.numpermutation + 2; - order = [1 2 3:2:Nrepetitions 4:2:Nrepetitions]; - avg = avg(order,:,:); - Cy = Cy (order,:,:); - - elseif strcmp(cfg.randomization, 'yes') - % compute the average and covariance without resampling - [dum, avgA, covA, avgB, covB] = prepare_resampled_data(cfg2 , data.trial, data.cov, baseline.trial, baseline.cov); - % compute the average and covariance with random resampling - [cfg, avRA, coRA, avRB, coRB] = prepare_resampled_data(cfg, data.trial, data.cov, baseline.trial, baseline.cov); - % concatenate the different resamplings - avg = cat(1, reshape(avgA, [1 Nchans Nsamples]), reshape(avgB, [1 Nchans Nsamples]), avRA, avRB); - Cy = cat(1, reshape(covA, [1 Nchans Nchans ]), reshape(covB, [1 Nchans Nchans ]), coRA, coRB); - % clear temporary working copies - clear avgA avgB covA covB - clear avRA avRB coRA coRB - % the order of the resamplings should be [avgA avgB randA randB randA randB randA randB ....] - Nrepetitions = 2*cfg.numrandomization + 2; - order = [1 2 3:2:Nrepetitions 4:2:Nrepetitions]; - avg = avg(order,:,:); - Cy = Cy (order,:,:); - - elseif strcmp(cfg.jackknife, 'yes') - % compute the jackknife repetitions for the average and covariance - [cfg, avg, Cy] = prepare_resampled_data(cfg, data.trial, data.cov); - Nrepetitions = Ntrials; - - elseif strcmp(cfg.bootstrap, 'yes') - % compute the bootstrap repetitions for the average and covariance - [cfg, avg, Cy] = prepare_resampled_data(cfg, data.trial, data.cov); - Nrepetitions = cfg.numbootstrap; - - elseif strcmp(cfg.pseudovalue, 'yes') - % compute the pseudovalue repetitions for the average and covariance - [cfg, avg, Cy] = prepare_resampled_data(cfg, data.trial, data.cov); - Nrepetitions = Ntrials+1; - - elseif strcmp(cfg.singletrial, 'yes') - % The idea is that beamformer uses the average covariance to construct the - % filter and applies it to the single trial covariance/csd. The problem - % is that beamformer will use the averaged covariance/csd to estimate the - % power and not the single trial covariance/csd - error('this option contains a bug, and is therefore not supported at the moment'); - % average the single-trial covariance matrices - Cy = mean(data.cov,1); - % copy the average covariance matrix for every individual trial - Cy = repmat(Cy, [Ntrials 1 1]); - % keep the single-trial ERFs, rename them to avg for convenience - avg = data.trial; - Nrepetitions = Ntrials; - - elseif strcmp(cfg.rawtrial, 'yes') - % do not do any resampling, keep the single-trial covariances - Cy = data.cov; - % do not do any resampling, keep the single-trial ERFs (rename them to avg for convenience) - avg = data.trial; - Nrepetitions = Ntrials; - - elseif Ntrials>1 - % average the single-trial covariance matrices - Cy = reshape(mean(data.cov,1), [Nchans Nchans]); - % select the average ERF - avg = data.avg; - Nrepetitions = 1; - - elseif Ntrials==1 - % select the average covariance matrix - Cy = data.cov; - % select the average ERF - avg = data.avg; - Nrepetitions = 1; - end - - % reshape so that it also looks like one trial (out of many) - if Nrepetitions==1 - Cy = reshape(Cy , [1 Nchans Nchans]); - avg = reshape(avg, [1 Nchans Nsamples]); - end - - % get the relevant low level options from the cfg and convert into key-value pairs - optarg = cfg2keyval(getfield(cfg, cfg.method)); - - if strcmp(cfg.method, 'lcmv') && ~isfield(grid, 'filter'), - for i=1:Nrepetitions - fprintf('scanning repetition %d\n', i); - dip(i) = beamformer_lcmv(grid, sens, vol, squeeze(avg(i,:,:)), squeeze(Cy(i,:,:)), optarg{:}); - end - elseif strcmp(cfg.method, 'lcmv') - %don't loop over repetitions (slow), but reshape the input data to obtain single trial timecourses efficiently - %in the presence of filters pre-computed on the average (or whatever) - siz = size(avg); - tmpavg = reshape(permute(avg,[2 3 1]),[siz(2) siz(3)*siz(1)]); - tmpdip = beamformer_lcmv(grid, sens, vol, tmpavg, squeeze(mean(Cy,1)), optarg{:}); - for i=1:length(tmpdip.inside) - indx = tmpdip.inside(i); - tmpdip.mom{indx} = reshape(tmpdip.mom{indx}, [siz(3) siz(1)])'; - end - try, tmpdip = rmfield(tmpdip, 'pow'); end - try, tmpdip = rmfield(tmpdip, 'cov'); end - try, tmpdip = rmfield(tmpdip, 'noise'); end - for i=1:Nrepetitions - dip(i).pos = tmpdip.pos; - dip(i).inside = tmpdip.inside; - dip(i).outside = tmpdip.outside; - dip(i).mom = cell(1,size(tmpdip.pos,1)); - for ii=1:length(tmpdip.inside) - indx = tmpdip.inside(ii); - dip(i).mom{indx} = tmpdip.mom{indx}(i,:); - end - end - elseif strcmp(cfg.method, 'sam') - for i=1:Nrepetitions - fprintf('scanning repetition %d\n', i); - dip(i) = beamformer_sam(grid, sens, vol, squeeze(avg(i,:,:)), squeeze(Cy(i,:,:)), optarg{:}); - end - elseif strcmp(cfg.method, 'pcc') - for i=1:Nrepetitions - fprintf('scanning repetition %d\n', i); - dip(i) = beamformer_pcc(grid, sens, vol, squeeze(avg(i,:,:)), squeeze(Cy(i,:,:)), optarg{:}, 'refdip', cfg.refdip, 'refchan', refchanindx, 'supchan', supchanindx); - end - elseif strcmp(cfg.method, 'mne') - for i=1:Nrepetitions - fprintf('estimating current density distribution for repetition %d\n', i); - dip(i) = minimumnormestimate(grid, sens, vol, squeeze(avg(i,:,:)), optarg{:}); - end - elseif strcmp(cfg.method, 'loreta') - for i=1:Nrepetitions - fprintf('estimating LORETA current density distribution for repetition %d\n', i); - dip(i) = loreta( grid, sens, vol, squeeze(avg(i,:,:)), optarg{:}); - end - elseif strcmp(cfg.method, 'rv') - for i=1:Nrepetitions - fprintf('estimating residual variance at each grid point for repetition %d\n', i); - dip(i) = residualvariance( grid, sens, vol, squeeze(avg(i,:,:)), optarg{:}); - end - elseif strcmp(cfg.method, 'music') - for i=1:Nrepetitions - fprintf('computing multiple signal classification for repetition %d\n', i); - if hascovariance - dip(i) = music(grid, sens, vol, squeeze(avg(i,:,:)), 'cov', squeeze(Cy(i,:,:)), optarg{:}); - else - dip(i) = music(grid, sens, vol, squeeze(avg(i,:,:)), optarg{:}); - end - end - elseif strcmp(cfg.method, 'mvl') - for i=1:Nrepetitions - fprintf('estimating current density distribution for repetition %d\n', i); - fns = fieldnames(cfg); - optarg = cell(1,length(fns)); - n=1; - for c=1:length(fns) - optarg{n} = fns{c}; - optarg{n+1} = cfg.(fns{c}); - n=n+2; - end - dip(i) = mvlestimate(grid, sens, vol, squeeze(avg(i,:,:)), optarg{:}); - end - else - error(sprintf('method ''%s'' is unsupported for source reconstruction in the time domain', cfg.method)); - end - -end % if freq or timelock data - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% clean up and collect the results -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -if isfield(grid, 'xgrid') - % the dipoles are placed on a regular grid that is aligned with the carthesian axes - % copy the description of the grid axes - source.xgrid = grid.xgrid; - source.ygrid = grid.ygrid; - source.zgrid = grid.zgrid; - source.dim = [length(source.xgrid) length(source.ygrid) length(source.zgrid)]; -else - source.dim = [size(grid.pos,1) 1]; -end - -source.vol = vol; -if exist('grad', 'var') - source.grad = grad; -elseif exist('elec', 'var') - source.elec = elec; -end - -if istimelock - % add the time axis to the output - source.time = data.time; -elseif iscomp - % FIXME, add the component numbers to the output -elseif isfreq - % add the frequency axis to the output - cfg.frequency = data.freq(nearest(data.freq, cfg.frequency)); - source.frequency = cfg.frequency; - if isfield(data, 'time') && isfield(cfg, 'latency') - cfg.latency = data.time(nearest(data.time, cfg.latency)); - source.latency = cfg.latency; - end - if isfield(data, 'cumtapcnt'), - source.cumtapcnt = data.cumtapcnt; - end -end - -if exist('dip', 'var') - % do some cleaning up, keep the dipole positions etc. in the global structure and not in each trial - source.pos = dip(1).pos; - source.inside = dip(1).inside; - source.outside = dip(1).outside; - dip = rmfield(dip, 'pos'); - dip = rmfield(dip, 'inside'); - dip = rmfield(dip, 'outside'); - if isfield(dip(1), 'leadfield') - source.leadfield = dip(1).leadfield; - dip = rmfield(dip, 'leadfield'); - end -elseif exist('grid', 'var') - % no scanning has been done, probably only the leadfield has been computed - try, source.pos = grid.pos; end - try, source.inside = grid.inside; end - try, source.outside = grid.outside; end - try, source.leadfield = grid.leadfield; end -end - -if strcmp(cfg.keepleadfield, 'yes') && ~isfield(source, 'leadfield') - % add the precomputed leadfields to the output source - source.leadfield = grid.leadfield; -elseif strcmp(cfg.keepleadfield, 'no') && isfield(source, 'leadfield') - % remove the precomputed leadfields from the output source - source = rmfield(source, 'leadfield'); -end - -% remove the precomputed leadfields from the cfg regardless of what keepleadfield is saying -% it should not be kept in cfg, since there it takes up too much space -if isfield(cfg, 'grid') && isfield(cfg.grid, 'leadfield') - cfg.grid = rmfield(cfg.grid, 'leadfield'); -end - -if convertfreq - % FIXME, convert the source reconstruction back to a frequency representation -elseif convertcomp - % FIXME, convert the source reconstruction back to a component representation -end - -if strcmp(cfg.jackknife, 'yes') - source.method = 'jackknife'; - source.trial = dip; - source.df = Ntrials; -elseif strcmp(cfg.bootstrap, 'yes') - source.method = 'bootstrap'; - source.trial = dip; - source.df = Ntrials; -elseif strcmp(cfg.pseudovalue, 'yes') - source.method = 'pseudovalue'; - source.trial = dip; -elseif strcmp(cfg.singletrial, 'yes') - source.method = 'singletrial'; - source.trial = dip; - source.df = Ntrials; % is this correct? -elseif strcmp(cfg.rawtrial, 'yes') - source.method = 'rawtrial'; - source.trial = dip; - source.df = Ntrials; % is this correct? -elseif strcmp(cfg.randomization, 'yes') - % assign the randomized resamplings to the output, keeping the special meaning of trial 1 and 2 in mind - source.method = 'randomization'; - source.avgA = dip(1); - source.avgB = dip(2); - source.trialA = dip(1+2*(1:cfg.numrandomization)); - source.trialB = dip(2+2*(1:cfg.numrandomization)); -elseif strcmp(cfg.permutation, 'yes') - % assign the randomized resamplings to the output, keeping the special meaning of trial 1 and 2 in mind - source.method = 'permutation'; - source.avgA = dip(1); - source.avgB = dip(2); - source.trialA = dip(1+2*(1:cfg.numpermutation)); - source.trialB = dip(2+2*(1:cfg.numpermutation)); -elseif exist('dip', 'var') - % it looks like beamformer analysis was done on an average input, keep the average source reconstruction - source.method = 'average'; - source.avg = dip; -else - % apparently no computations were performed -end - -if (strcmp(cfg.jackknife, 'yes') || strcmp(cfg.bootstrap, 'yes') || strcmp(cfg.pseudovalue, 'yes') || strcmp(cfg.singletrial, 'yes') || strcmp(cfg.rawtrial, 'yes')) && strcmp(cfg.keeptrials, 'yes') - % keep the source reconstruction for each repeated or resampled trial - source.trial = dip; -end - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: sourceanalysis.m,v 1.141 2009/10/12 14:44:07 jansch Exp $'; -% remember the configuration details of the input data -if nargin==2 - try, cfg.previous = data.cfg; end -elseif nargin==3 - cfg.previous = []; - try, cfg.previous{1} = data.cfg; end - try, cfg.previous{2} = baseline.cfg; end -end -% remember the exact configuration details in the output -source.cfg = cfg; - -fprintf('total time in sourceanalysis %.1f seconds\n', toc); - diff --git a/external/fieldtrip/private/sourcedepth.m b/external/fieldtrip/private/sourcedepth.m deleted file mode 100644 index 01af870..0000000 --- a/external/fieldtrip/private/sourcedepth.m +++ /dev/null @@ -1,94 +0,0 @@ -function [depth] = sourcedepth(pos, vol) - -% SOURCEDEPTH computes the distance from the source to the surface of -% the source compartment (usually the brain). -% -% Use as -% depth = sourcedepth(pos, vol); -% where -% pos Nx3 matrix with the position of N sources -% vol structure describing volume condition model -% -% A negative depth indicates that the source is inside the source -% compartment, positive indicates outside. -% -% See also FIND_INSIDE_VOL - -% Copyright (C) 2007-2008, Robert Oostenveld -% -% $Log: sourcedepth.m,v $ -% Revision 1.5 2009/02/06 08:31:19 roboos -% added bemcp as volume type -% -% Revision 1.4 2008/04/21 12:09:47 roboos -% small change to documentation -% -% Revision 1.3 2008/04/15 20:36:21 roboos -% added explicit handling of various BEM implementations, i.e. for all voltype variants -% -% Revision 1.2 2007/11/05 12:02:28 roboos -% medged arno's changed into my copy -% -% Revision 1.2 2007/11/03 01:12:38 arno -% copying functions inline -% -% Revision 1.1 2007/09/24 23:40:28 nima -% Initial revision -% -% Revision 1.1 2007/07/25 08:34:48 roboos -% new implementation -% - -% determine the type of volume conduction model -switch voltype(vol) - -% single-sphere or multiple concentric spheres -case {'singlesphere', 'concentric'} - if ~isfield(vol, 'source') - % locate the innermost compartment and remember it - [dum, vol.source] = min(vol.r); - end - if isfield(vol, 'o') - % shift dipole positions toward origin of sphere - tmp = pos - repmat(vol.o, size(pos,1), 1); - else - tmp = pos; - end - depth = sqrt(sum(tmp.^2, 2))-vol.r(vol.source); % positive if outside, negative if inside - -% boundary element model -case {'bem' 'dipoli', 'bemcp', 'asa', 'avo', 'nolte', 'neuromag'} - if isfield(vol, 'source') - % use the specified source compartment - pnt = vol.bnd(vol.source).pnt; - tri = vol.bnd(vol.source).tri; - else - % locate the innermost compartment and remember it - vol.source = find_innermost_boundary(vol.bnd); - pnt = vol.bnd(vol.source).pnt; - tri = vol.bnd(vol.source).tri; - end - inside = bounding_mesh(pos, pnt, tri); - ntri = size(tri,1); - npos = size(pos,1); - dist = zeros(ntri, 1); - depth = zeros(npos, 1); - for i=1:npos - for j=1:ntri - v1 = pnt(tri(j,1),:); - v2 = pnt(tri(j,2),:); - v3 = pnt(tri(j,3),:); - [proj, dist(j)] = ptriproj(v1, v2, v3, pos(i,:), 1); - end - if inside(i) - depth(i) = -min(dist); - else - depth(i) = min(dist); - end - end - -% unsupported volume conductor model -otherwise - error('upsupported volume conductor model'); -end - diff --git a/external/fieldtrip/private/sourcedescriptives.m b/external/fieldtrip/private/sourcedescriptives.m deleted file mode 100644 index 7b4d6ca..0000000 --- a/external/fieldtrip/private/sourcedescriptives.m +++ /dev/null @@ -1,945 +0,0 @@ -function [source] = sourcedescriptives(cfg, source) - -% SOURCEDESCRIPTIVES computes descriptive parameters of the beamformer source -% analysis results. -% -% Use as: -% [source] = sourcedescriptives(cfg, source) -% -% where cfg is a structure with the configuration details and source is the -% result from a beamformer source estimation. The configuration can contain -% cfg.cohmethod = 'regular', 'lambda1', 'canonical' -% cfg.powmethod = 'regular', 'lambda1', 'trace', 'none' -% cfg.supmethod = string -% cfg.projectmom = 'yes' or 'no' (default = 'no') -% cfg.eta = 'yes' or 'no' (default = 'no') -% cfg.kurtosis = 'yes' or 'no' (default = 'no') -% cfg.keeptrials = 'yes' or 'no' (default = 'no') -% cfg.resolutionmatrix = 'yes' or 'no' (default = 'no') -% cfg.feedback = 'no', 'text', 'textbar', 'gui' (default = 'text') -% -% The following option only applies to LCMV single-trial timecourses. -% cfg.fixedori = 'within_trials' or 'over_trials' (default = 'over_trials') -% -% You can apply a custom mathematical transformation such as a log-transform -% on the estimated power using -% cfg.transform = string describing the transformation (default is []) -% The nai, i.e. neural activity index (power divided by projected noise), -% is computed prior to applying the optional transformation. Subsequently, -% the transformation is applied on the power and on the projected noise -% using "feval". A usefull transformation is for example 'log' or 'log10'. -% -% If repeated trials are present that have undergone some sort of -% resampling (i.e. jackknife, bootstrap, singletrial or rawtrial), the mean, -% variance and standard error of mean will be computed for all source -% parameters. This is done after applying the optional transformation -% on the power and projected noise. -% -% See also SOURCEANALYSIS, SOURCESTATISTICS - -% Copyright (C) 2004-2007, Robert Oostenveld & Jan-Mathijs Schoffelen -% -% $Log: sourcedescriptives.m,v $ -% Revision 1.45 2009/10/12 14:40:24 jansch -% multiple changes, most important being to use cellfun rather than repeated -% subfunction calls in a loop over voxels, and defining hasrefdip etc, to -% avoid multiple isempty evaluations -% -% Revision 1.44 2009/04/08 08:35:50 roboos -% ensure that the nai is based on the vectorised power and noise (otherwise the element-wise division fails) -% -% Revision 1.43 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.42 2008/11/21 13:21:35 sashae -% added call to checkconfig at start and end of fucntion -% -% Revision 1.41 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.40 2008/09/11 13:21:13 jansch -% included output of ori if cfg.eta = 'yes' -% -% Revision 1.39 2008/07/21 11:02:51 roboos -% removed a try-catch whose purpose was unclear and that caused a problem with nai computation to remain invisible -% -% Revision 1.38 2008/04/09 14:14:30 roboos -% updated docu -% -% Revision 1.37 2008/02/20 14:22:54 roboos -% in allocating sumdip and sqrdip, only make the ourside voxels nan to start with -% -% Revision 1.36 2007/05/08 21:04:40 roboos -% initialize all new elements with nans instead of with zeros, outside values will remain nan -% -% Revision 1.35 2007/05/08 20:53:35 roboos -% added computation of kurtosis for lcmv dipole moments, default is off -% -% Revision 1.34 2007/04/19 17:14:11 roboos -% adde th projectmom dipole otientation to the output for pcc -% added temporary fix for nai in case of lcmv -% -% Revision 1.33 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.32 2007/03/30 17:05:40 ingnie -% checkinput; only proceed when input data is allowed datatype -% -% Revision 1.31 2007/01/17 17:07:41 roboos -% implemented support for lcmv beamformer timecourses, added option for powmethod=none, added cfg.fixedori -% when keeptrials=yes then do not output the average and variance (it is either/or) -% -% Revision 1.30 2007/01/17 13:19:14 roboos -% Many changes, mainly a complete redesign of the pcc section, keeptrials/powmethod/submethod/projectmom stuff changed. -% This is a bit a kamikaze commit, since I don't have a complete overview of al changes by jansch and me and not everything has been exhaustively tested. -% -% Revision 1.29 2006/07/04 16:04:50 roboos -% renamed option 'jacknife' into 'jackknife' for consistency, maintain backward compatibility with cfgs and old data -% - -fieldtripdefs - -cfg = checkconfig(cfg, 'trackconfig', 'on'); - -% check if the input data is valid for this function -source = checkdata(source, 'datatype', 'source', 'feedback', 'yes'); - -% set the defaults -if ~isfield(cfg, 'transform'), cfg.transform = []; end -if ~isfield(cfg, 'projectmom'), cfg.projectmom = 'no'; end % if yes -> svdfft -if ~isfield(cfg, 'numcomp'), cfg.numcomp = 1; end -if ~isfield(cfg, 'powmethod'), cfg.powmethod = []; end % see below -if ~isfield(cfg, 'cohmethod'), cfg.cohmethod = []; end % see below -if ~isfield(cfg, 'feedback'), cfg.feedback = 'textbar'; end -if ~isfield(cfg, 'supmethod'), cfg.supmethod = 'none'; end -if ~isfield(cfg, 'resolutionmatrix'), cfg.resolutionmatrix = 'no'; end -if ~isfield(cfg, 'eta'), cfg.eta = 'no'; end -if ~isfield(cfg, 'fa'), cfg.fa = 'no'; end -if ~isfield(cfg, 'kurtosis'), cfg.kurtosis = 'no'; end -if ~isfield(cfg, 'keeptrials'), cfg.keeptrials = 'no'; end -if ~isfield(cfg, 'keepcsd'), cfg.keepcsd = 'no'; end -if ~isfield(cfg, 'fixedori'), cfg.fixedori = 'over_trials'; end - -% this is required for backward compatibility with the old sourceanalysis -if isfield(source, 'method') && strcmp(source.method, 'randomized') - source.method = 'randomization'; -elseif isfield(source, 'method') && strcmp(source.method, 'permuted') - source.method = 'permutation'; -elseif isfield(source, 'method') && strcmp(source.method, 'jacknife') - source.method = 'jackknife'; -end - -% determine the type of data, this is only relevant for a few specific types -ispccdata = isfield(source, 'avg') && isfield(source.avg, 'csdlabel'); -islcmvavg = isfield(source, 'avg') && isfield(source, 'time') && isfield(source.avg, 'mom'); -islcmvtrl = isfield(source, 'trial') && isfield(source, 'time') && isfield(source.trial, 'mom'); - -% check the consistency of the defaults -if strcmp(cfg.projectmom, 'yes') - if isempty(cfg.powmethod) - cfg.powmethod = 'regular'; % set the default - elseif ~strcmp(cfg.powmethod, 'regular') - error('unsupported powmethod in combination with projectmom'); - end - if isempty(cfg.cohmethod) - cfg.cohmethod = 'regular';% set the default - elseif ~strcmp(cfg.cohmethod, 'regular') - error('unsupported cohmethod in combination with projectmom'); - end -else - if isempty(cfg.powmethod) - cfg.powmethod = 'lambda1'; % set the default - end - if isempty(cfg.cohmethod) - cfg.cohmethod = 'lambda1'; % set the default - end -end - -% this is required for backward compatibility with an old version of sourcedescriptives -if isfield(cfg, 'singletrial'), cfg.keeptrials = cfg.singletrial; end - -% do a validity check on the input data and specified options -if strcmp(cfg.resolutionmatrix, 'yes') - if ~isfield(source.avg, 'filter') - error('The computation of the resolution matrix requires keepfilter=''yes'' in sourceanalysis.'); - elseif ~isfield(source, 'leadfield') - error('The computation of the resolution matrix requires keepleadfield=''yes'' in sourceanalysis.'); - end -end - -if strcmp(cfg.eta, 'yes') && strcmp(cfg.cohmethod, 'svdfft'), - error('eta cannot be computed in combination with the application of svdfft'); -end - -if strcmp(cfg.keeptrials, 'yes') && ~strcmp(cfg.supmethod, 'none'), - error('you cannot keep trials when you want to partialize something'); -end - -% set some flags for convenience -isnoise = isfield(source, 'avg') && isfield(source.avg, 'noisecsd'); -keeptrials = strcmp(cfg.keeptrials, 'yes'); -projectmom = strcmp(cfg.projectmom, 'yes'); - -% determine the subfunction used for computing power -switch cfg.powmethod - case 'regular' - powmethodfun = @powmethod_regular; - case 'lambda1' - powmethodfun = @powmethod_lambda1; - case 'trace' - powmethodfun = @powmethod_trace; - case 'none' - powmethodfun = []; - otherwise - error('unsupported powmethod'); -end - -if ispccdata - % the source reconstruction was computed using the pcc beamformer - Ndipole = length(source.inside) + length(source.outside); - dipsel = match_str(source.avg.csdlabel, 'scandip'); - refchansel = match_str(source.avg.csdlabel, 'refchan'); - refdipsel = match_str(source.avg.csdlabel, 'refdip'); - supchansel = match_str(source.avg.csdlabel, 'supchan'); - supdipsel = match_str(source.avg.csdlabel, 'supdip'); - - % cannot handle reference channels and reference dipoles simultaneously - if length(refchansel)>0 && length(refdipsel)>0 - error('cannot simultaneously handle reference channels and reference dipole'); - end - - % these are only used to count the number of reference/suppression dipoles and channels - refsel = [refdipsel refchansel]; - supsel = [supdipsel supchansel]; - - if projectmom - source.avg.ori = cell(1, Ndipole); - progress('init', cfg.feedback, 'projecting dipole moment'); - for diplop=1:length(source.inside) - progress(diplop/length(source.inside), 'projecting dipole moment %d/%d\n', diplop, length(source.inside)); - i = source.inside(diplop); - mom = source.avg.mom{i}(dipsel, :); - ref = source.avg.mom{i}(refdipsel, :); - sup = source.avg.mom{i}(supdipsel, :); - refchan = source.avg.mom{i}(refchansel, :); - supchan = source.avg.mom{i}(supchansel, :); - % compute the projection of the scanning dipole along the direction of the dominant amplitude - if length(dipsel)>1, [mom, rmom] = svdfft(mom, cfg.numcomp, source.cumtapcnt); else rmom = []; end - source.avg.ori{source.inside(diplop)} = rmom; - % compute the projection of the reference dipole along the direction of the dominant amplitude - if length(refdipsel)>1, [ref, rref] = svdfft(ref, 1, source.cumtapcnt); else rref = []; end - % compute the projection of the supression dipole along the direction of the dominant amplitude - if length(supdipsel)>1, [sup, rsup] = svdfft(sup, 1, source.cumtapcnt); else rsup = []; end - - % compute voxel-level fourier-matrix - source.avg.mom{i} = cat(1, mom, ref, sup, refchan, supchan); - - % create rotation-matrix - rotmat = zeros(0, length(source.avg.csdlabel)); - if ~isempty(rmom), - rotmat = [rotmat; rmom zeros(1,length([refsel(:);supsel(:)]))]; - end - if ~isempty(rref), - rotmat = [rotmat; zeros(1, length([dipsel])), rref, zeros(1,length([refchansel(:);supsel(:)]))]; - end - if ~isempty(rsup), - rotmat = [rotmat; zeros(1, length([dipsel(:);refdipsel(:)])), rsup, zeros(1,length([refchansel(:);supchansel(:)]))]; - end - for j=1:length(supchansel) - rotmat(end+1,:) = 0; - rotmat(end,length([dipsel(:);refdipsel(:);supdipsel(:)])+j) = 1; - end - for j=1:length(refchansel) - rotmat(end+1,:) = 0; - rotmat(end,length([dipsel(:);refdipsel(:);supdipsel(:);supchansel(:)])+j) = 1; - end - - % compute voxel-level csd-matrix - source.avg.csd{i} = rotmat * source.avg.csd{i} * rotmat'; - % compute voxel-level noisecsd-matrix - if isfield(source.avg, 'noisecsd'), source.avg.noisecsd{i} = rotmat * source.avg.noisecsd{i} * rotmat'; end - % compute rotated filter - if isfield(source.avg, 'filter'), source.avg.filter{i} = rotmat * source.avg.filter{i}; end - % compute rotated leadfield - % FIXME in the presence of a refdip and/or supdip, this does not work; leadfield is Nx3 - if isfield(source, 'leadfield'), - %FIXME this is a proposed dirty fix - n1 = size(source.leadfield{i},2); - %n2 = size(rotmat,2) - n1; - n2 = size(rotmat,2) - n1 +1; %added 1 JM - source.leadfield{i} = source.leadfield{i} * rotmat(1:n2, 1:n1)'; - end - end %for diplop - progress('close'); - - % remember what the interpretation is of all CSD output components - scandiplabel = repmat({'scandip'}, 1, cfg.numcomp); % only one dipole orientation remains - refdiplabel = repmat({'refdip'}, 1, length(refdipsel)>0); % for svdfft at max. only one dipole orientation remains - supdiplabel = repmat({'supdip'}, 1, length(supdipsel)>0); % for svdfft at max. only one dipole orientation remains - refchanlabel = repmat({'refchan'}, 1, length(refchansel)); - supchanlabel = repmat({'supchan'}, 1, length(supchansel)); - % concatenate all the labels - source.avg.csdlabel = cat(2, scandiplabel, refdiplabel, supdiplabel, refchanlabel, supchanlabel); - % update the indices - dipsel = match_str(source.avg.csdlabel, 'scandip'); - refchansel = match_str(source.avg.csdlabel, 'refchan'); - refdipsel = match_str(source.avg.csdlabel, 'refdip'); - supchansel = match_str(source.avg.csdlabel, 'supchan'); - supdipsel = match_str(source.avg.csdlabel, 'supdip'); - refsel = [refdipsel refchansel]; - supsel = [supdipsel supchansel]; - end % if projectmom - - if keeptrials - cumtapcnt = source.cumtapcnt(:); - sumtapcnt = cumsum([0;cumtapcnt]); - Ntrial = length(cumtapcnt); - - progress('init', cfg.feedback, 'computing singletrial voxel-level cross-spectral densities'); - for triallop = 1:Ntrial - source.trial(triallop).csd = cell(Ndipole, 1); % allocate memory for this trial - source.trial(triallop).mom = cell(Ndipole, 1); % allocate memory for this trial - - progress(triallop/Ntrial, 'computing singletrial voxel-level cross-spectral densities %d%d\n', triallop, Ntrial); - for diplop=1:length(source.inside) - i = source.inside(diplop); - dat = source.avg.mom{i}; - tmpmom = dat(:, sumtapcnt(triallop)+1:sumtapcnt(triallop+1)); - tmpcsd = [tmpmom * tmpmom'] ./cumtapcnt(triallop); - source.trial(triallop).mom{i} = tmpmom; - source.trial(triallop).csd{i} = tmpcsd; - end %for diplop - end % for triallop - progress('close'); - % remove the average, continue with separate trials - source = rmfield(source, 'avg'); - else - fprintf('using average voxel-level cross-spectral densities\n'); - end % if keeptrials - - hasrefdip = ~isempty(refdipsel); - hasrefchan = ~isempty(refchansel); - hassupdip = ~isempty(supdipsel); - hassupchan = ~isempty(supchansel); - - if keeptrials - % do the processing of the CSD matrices for each trial - if ~strcmp(cfg.supmethod, 'none') - error('suppression is only supported for average CSD'); - end - dipselcell = mat2cell(repmat(dipsel(:)', [Ndipole 1]), ones(Ndipole,1), length(dipsel)); - if hasrefdip, refdipselcell = mat2cell(repmat(refdipsel(:)', [Ndipole 1]), ones(Ndipole,1), length(refdipsel)); end - if hasrefchan, refchanselcell = mat2cell(repmat(refchansel(:)', [Ndipole 1]), ones(Ndipole,1), length(refchansel)); end - if hassupdip, supdipselcell = mat2cell(repmat(supdipsel(:)', [Ndipole 1]), ones(Ndipole,1), length(supdipsel)); end - if hassupchan, supchanselcell = mat2cell(repmat(supchansel(:)', [Ndipole 1]), ones(Ndipole,1), length(supchansel)); end - - progress('init', cfg.feedback, 'computing singletrial voxel-level power'); - for triallop = 1:Ntrial - %initialize the variables - source.trial(triallop).pow = zeros(Ndipole, 1); - if hasrefdip, source.trial(triallop).refdippow = zeros(Ndipole, 1); end - if hasrefchan, source.trial(triallop).refchanpow = zeros(Ndipole, 1); end - if hassupdip, source.trial(triallop).supdippow = zeros(Ndipole, 1); end - if hassupchan, source.trial(triallop).supchanpow = zeros(Ndipole, 1); end - - progress(triallop/Ntrial, 'computing singletrial voxel-level power %d%d\n', triallop, Ntrial); - source.trial(triallop).pow(source.inside) = cellfun(powmethodfun, source.trial(triallop).csd(source.inside), dipselcell(source.inside)); - if hasrefdip, source.trial(triallop).refdippow(source.inside) = cellfun(powmethodfun,source.trial(triallop).csd(source.inside), refdipselcell(source.inside)); end - if hassupdip, source.trial(triallop).supdippow(source.inside) = cellfun(powmethodfun,source.trial(triallop).csd(source.inside), supdipselcell(source.inside)); end - if hasrefchan, source.trial(triallop).refchanpow(source.inside) = cellfun(powmethodfun,source.trial(triallop).csd(source.inside), refchanselcell(source.inside)); end - if hassupchan, source.trial(triallop).supchanpow(source.inside) = cellfun(powmethodfun,source.trial(triallop).csd(source.inside), supchanselcell(source.inside)); end - %FIXME kan volgens mij niet - if isnoise && isfield(source.trial(triallop), 'noisecsd'), - % compute the power of the noise projected on each source component - source.trial(triallop).noise = cellfun(powmethodfun,source.trial(triallop).csd, dipselcell); - if hasrefdip, source.trial(triallop).refdipnoise = cellfun(powmethodfun,source.trial(triallop).noisecsd, refdipselcell); end - if hassupdip, source.trial(triallop).supdipnoise = cellfun(powmethodfun,source.trial(triallop).noisecsd, supdipselcell); end - if hasrefchan, source.trial(triallop).refchannoise = cellfun(powmethodfun,source.trial(triallop).noisecsd, refchanselcell); end - if hassupchan, source.trial(triallop).supchannoise = cellfun(powmethodfun,source.trial(triallop).noisecsd, supchanselcell); end - end % if isnoise - end % for triallop - progress('close'); - - if strcmp(cfg.keepcsd, 'no') - source.trial = rmfield(source.trial, 'csd'); - end - else - % do the processing of the average CSD matrix - for diplop = 1:length(source.inside) - i = source.inside(diplop); - switch cfg.supmethod - case 'chan_dip' - supindx = [supdipsel supchansel]; - if diplop==1, refsel = refsel - length(supdipsel); end%adjust index only once - case 'chan' - supindx = [supchansel]; - case 'dip' - supindx = [supdipsel]; - if diplop==1, refsel = refsel - length(supdipsel); end - case 'none' - % do nothing - supindx = []; - end - tmpcsd = source.avg.csd{i}; - scnindx = setdiff(1:size(tmpcsd,1), supindx); - tmpcsd = tmpcsd(scnindx, scnindx) - [tmpcsd(scnindx, supindx)*pinv(tmpcsd(supindx, supindx))*tmpcsd(supindx, scnindx)]; - source.avg.csd{i} = tmpcsd; - end % for diplop - source.avg.csdlabel = source.avg.csdlabel(scnindx); - - if isnoise && ~strcmp(cfg.supmethod, 'none') - source.avg = rmfield(source.avg, 'noisecsd'); - end - - % initialize the variables - source.avg.pow = nan*zeros(Ndipole, 1); - if ~isempty(refdipsel), source.avg.refdippow = nan*zeros(Ndipole, 1); end - if ~isempty(refchansel), source.avg.refchanpow = nan*zeros(Ndipole, 1); end - if ~isempty(supdipsel), source.avg.supdippow = nan*zeros(Ndipole, 1); end - if ~isempty(supchansel), source.avg.supchanpow = nan*zeros(Ndipole, 1); end - if isnoise - source.avg.noise = nan*zeros(Ndipole, 1); - if ~isempty(refdipsel), source.avg.refdipnoise = nan*zeros(Ndipole, 1); end - if ~isempty(refchansel), source.avg.refchannoise = nan*zeros(Ndipole, 1); end - if ~isempty(supdipsel), source.avg.supdipnoise = nan*zeros(Ndipole, 1); end - if ~isempty(supchansel), source.avg.supchannoise = nan*zeros(Ndipole, 1); end - end % if isnoise - if ~isempty(refsel), source.avg.coh = nan*zeros(Ndipole, 1); end - if strcmp(cfg.eta, 'yes'), - source.avg.eta = nan*zeros(Ndipole, 1); - source.avg.ori = cell(1, Ndipole); - end - if strcmp(cfg.eta, 'yes') && ~isempty(refsel), - source.avg.etacsd = nan*zeros(Ndipole, 1); - source.avg.ucsd = cell(1, Ndipole); - end - if strcmp(cfg.fa, 'yes'), - source.avg.fa = nan*zeros(Ndipole, 1); - end - - for diplop = 1:length(source.inside) - i = source.inside(diplop); - - % compute the power of each source component - if strcmp(cfg.projectmom, 'yes') && cfg.numcomp>1, - source.avg.pow(i) = powmethodfun(source.avg.csd{i}(dipsel,dipsel), 1); - else - source.avg.pow(i) = powmethodfun(source.avg.csd{i}(dipsel,dipsel)); - end - if ~isempty(refdipsel), source.avg.refdippow(i) = powmethodfun(source.avg.csd{i}(refdipsel,refdipsel)); end - if ~isempty(supdipsel), source.avg.supdippow(i) = powmethodfun(source.avg.csd{i}(supdipsel,supdipsel)); end - if ~isempty(refchansel), source.avg.refchanpow(i) = powmethodfun(source.avg.csd{i}(refchansel,refchansel)); end - if ~isempty(supchansel), source.avg.supchanpow(i) = powmethodfun(source.avg.csd{i}(supchansel,supchansel)); end - if isnoise - % compute the power of the noise projected on each source component - if strcmp(cfg.projectmom, 'yes') && cfg.numcomp>1, - source.avg.noise(i) = powmethodfun(source.avg.noisecsd{i}(dipsel,dipsel), 1); - else - source.avg.noise(i) = powmethodfun(source.avg.noisecsd{i}(dipsel,dipsel)); - end - if ~isempty(refdipsel), source.avg.refdipnoise(i) = powmethodfun(source.avg.noisecsd{i}(refdipsel,refdipsel)); end - if ~isempty(supdipsel), source.avg.supdipnoise(i) = powmethodfun(source.avg.noisecsd{i}(supdipsel,supdipsel)); end - if ~isempty(refchansel), source.avg.refchannoise(i) = powmethodfun(source.avg.noisecsd{i}(refchansel,refchansel)); end - if ~isempty(supchansel), source.avg.supchannoise(i) = powmethodfun(source.avg.noisecsd{i}(supchansel,supchansel)); end - end % if isnoise - - if ~isempty(refsel) - % compute coherence - csd = source.avg.csd{i}; - switch cfg.cohmethod - case 'regular' - % assume that all dipoles have been projected along the direction of maximum power - Pd = abs(csd(dipsel, dipsel)); - Pr = abs(csd(refsel, refsel)); - Cdr = csd(dipsel, refsel); - source.avg.coh(i) = (Cdr.^2) ./ (Pd*Pr); - case 'lambda1' - %compute coherence on Joachim Gross' way - Pd = lambda1(csd(dipsel, dipsel)); - Pr = lambda1(csd(refsel, refsel)); - Cdr = lambda1(csd(dipsel, refsel)); - source.avg.coh(i) = abs(Cdr).^2 ./ (Pd*Pr); - case 'canonical' - [ccoh, c2, v1, v2] = cancorr(csd, dipsel, refsel); - [cmax, indmax] = max(ccoh); - source.avg.coh(i) = ccoh(indmax); - otherwise - error('unsupported cohmethod'); - end % cohmethod - end - - % compute eta - if strcmp(cfg.eta, 'yes') - [source.avg.eta(i), source.avg.ori{i}] = csd2eta(source.avg.csd{i}(dipsel,dipsel)); - if ~isempty(refsel), - %FIXME this only makes sense when only a reference signal OR a dipole is selected - [source.avg.etacsd(i), source.avg.ucsd{i}] = csd2eta(source.avg.csd{i}(dipsel,refsel)); - end - end - - %compute fa - if strcmp(cfg.fa, 'yes') - source.avg.fa(i) = csd2fa(source.avg.csd{i}(dipsel,dipsel)); - end - end % for diplop - - if strcmp(cfg.keepcsd, 'no') - source.avg = rmfield(source.avg, 'csd'); - end - if strcmp(cfg.keepcsd, 'no') && isnoise - source.avg = rmfield(source.avg, 'noisecsd'); - end - end - -elseif islcmvavg - % the source reconstruction was computed using the lcmv beamformer and contains an average timecourse - - if projectmom - progress('init', cfg.feedback, 'projecting dipole moment'); - for diplop=1:length(source.inside) - progress(diplop/length(source.inside), 'projecting dipole moment %d/%d\n', diplop, length(source.inside)); - mom = source.avg.mom{source.inside(diplop)}; - [mom, rmom] = svdfft(mom, 1); - source.avg.mom{source.inside(diplop)} = mom; - source.avg.ori{source.inside(diplop)} = rmom; - end - progress('close'); - end - - if ~strcmp(cfg.powmethod, 'none') - fprintf('recomputing power based on dipole timecourse\n') - source.avg.pow = nan*zeros(size(source.pos,1),1); - for diplop=1:length(source.inside) - mom = source.avg.mom{source.inside(diplop)}; - cov = mom * mom'; - source.avg.pow(source.inside(diplop)) = powmethodfun(cov); - end - end - - if strcmp(cfg.kurtosis, 'yes') - fprintf('computing kurtosis based on dipole timecourse\n'); - source.avg.k2 = nan*zeros(size(source.pos,1),1); - for diplop=1:length(source.inside) - mom = source.avg.mom{source.inside(diplop)}; - if length(mom)~=prod(size(mom)) - error('kurtosis can only be computed for projected dipole moment'); - end - source.avg.k2(source.inside(diplop)) = kurtosis(mom); - end - end - -elseif islcmvtrl - % the source reconstruction was computed using the lcmv beamformer and contains a single-trial timecourse - ntrial = length(source.trial); - - if projectmom && strcmp(cfg.fixedori, 'within_trials') - % the dipole orientation is re-determined for each trial - progress('init', cfg.feedback, 'projecting dipole moment'); - for trllop=1:ntrial - progress(trllop/ntrial, 'projecting dipole moment %d/%d\n', trllop, ntrial); - for diplop=1:length(source.inside) - mom = source.trial(trllop).mom{source.inside(diplop)}; - [mom, rmom] = svdfft(mom, 1); - source.trial(trllop).mom{source.inside(diplop)} = mom; - source.trial(trllop).ori{source.inside(diplop)} = rmom; % remember the orientation - end - end - progress('close'); - elseif projectmom && strcmp(cfg.fixedori, 'over_trials') - progress('init', cfg.feedback, 'projecting dipole moment'); - % compute average covariance over all trials - for trllop=1:ntrial - for diplop=1:length(source.inside) - mom = source.trial(trllop).mom{source.inside(diplop)}; - if trllop==1 - cov{diplop} = mom*mom'./size(mom,2); - else - cov{diplop} = mom*mom'./size(mom,2) + cov{diplop}; - end - end - end - % compute source orientation over all trials - for diplop=1:length(source.inside) - [dum, ori{diplop}] = svdfft(cov{diplop}, 1); - end - % project the data in each trial - for trllop=1:ntrial - progress(trllop/ntrial, 'projecting dipole moment %d/%d\n', trllop, ntrial); - for diplop=1:length(source.inside) - mom = source.trial(trllop).mom{source.inside(diplop)}; - mom = ori{diplop}*mom; - source.trial(trllop).mom{source.inside(diplop)} = mom; - source.trial(trllop).ori{source.inside(diplop)} = ori{diplop}; - end - end - progress('close'); - end - - if ~strcmp(cfg.powmethod, 'none') - fprintf('recomputing power based on dipole timecourse\n') - for trllop=1:ntrial - for diplop=1:length(source.inside) - mom = source.trial(trllop).mom{source.inside(diplop)}; - cov = mom * mom'; - source.trial(trllop).pow(source.inside(diplop)) = powmethodfun(cov); - end - end - end - - if strcmp(cfg.kurtosis, 'yes') - fprintf('computing kurtosis based on dipole timecourse\n'); - for trllop=1:ntrial - source.trial(trllop).k2 = nan*zeros(size(source.pos,1),1); - for diplop=1:length(source.inside) - mom = source.trial(trllop).mom{source.inside(diplop)}; - if length(mom)~=prod(size(mom)) - error('kurtosis can only be computed for projected dipole moment'); - end - source.trial(trllop).k2(source.inside(diplop)) = kurtosis(mom); - end - end - end - -end % dealing with pcc or lcmv input - -if isfield(source, 'avg') && isfield(source.avg, 'pow') && isfield(source.avg, 'noise') - % compute the neural activity index for the average - source.avg.nai = source.avg.pow(:) ./ source.avg.noise(:); -end - -if isfield(source, 'trial') && isfield(source.trial, 'pow') && isfield(source.trial, 'noise') - % compute the neural activity index for the trials - ntrials = length(source.trial); - for trlop=1:ntrials - source.trial(trlop).nai = source.trial(trlop).pow ./ source.trial(trlop).noise; - end -end - -if strcmp(source.method, 'randomization') || strcmp(source.method, 'permutation') - % compute the neural activity index for the two randomized conditions - source.avgA.nai = source.avgA.pow ./ source.avgA.noise; - source.avgB.nai = source.avgB.pow ./ source.avgB.noise; - for trlop=1:length(source.trialA) - source.trialA(trlop).nai = source.trialA(trlop).pow ./ source.trialA(trlop).noise; - end - for trlop=1:length(source.trialB) - source.trialB(trlop).nai = source.trialB(trlop).pow ./ source.trialB(trlop).noise; - end -end - -if ~isempty(cfg.transform) - fprintf('applying %s transformation on the power and projected noise\n', cfg.transform); - % apply the specified transformation on the power - if isfield(source, 'avg' ) && isfield(source.avg , 'pow'), source.avg .pow = feval(cfg.transform, source.avg .pow); end - if isfield(source, 'avgA' ) && isfield(source.avgA , 'pow'), source.avgA.pow = feval(cfg.transform, source.avgA.pow); end - if isfield(source, 'avgB' ) && isfield(source.avgB , 'pow'), source.avgB.pow = feval(cfg.transform, source.avgB.pow); end - if isfield(source, 'trial' ) && isfield(source.trial , 'pow'), for i=1:length(source.trial ), source.trial (i).pow = feval(cfg.transform, source.trial (i).pow); end; end - if isfield(source, 'trialA') && isfield(source.trialA, 'pow'), for i=1:length(source.trialA), source.trialA(i).pow = feval(cfg.transform, source.trialA(i).pow); end; end - if isfield(source, 'trialB') && isfield(source.trialB, 'pow'), for i=1:length(source.trialB), source.trialB(i).pow = feval(cfg.transform, source.trialB(i).pow); end; end - % apply the specified transformation on the projected noise - if isfield(source, 'avg' ) && isfield(source.avg , 'noise'), source.avg .noise = feval(cfg.transform, source.avg .noise); end - if isfield(source, 'avgA' ) && isfield(source.avgA , 'noise'), source.avgA.noise = feval(cfg.transform, source.avgA.noise); end - if isfield(source, 'avgB' ) && isfield(source.avgB , 'noise'), source.avgB.noise = feval(cfg.transform, source.avgB.noise); end - if isfield(source, 'trial' ) && isfield(source.trial , 'noise'), for i=1:length(source.trial ), source.trial (i).noise = feval(cfg.transform, source.trial (i).noise); end; end - if isfield(source, 'trialA') && isfield(source.trialA, 'noise'), for i=1:length(source.trialA), source.trialA(i).noise = feval(cfg.transform, source.trialA(i).noise); end; end - if isfield(source, 'trialB') && isfield(source.trialB, 'noise'), for i=1:length(source.trialB), source.trialB(i).noise = feval(cfg.transform, source.trialB(i).noise); end; end -end - -if strcmp(source.method, 'pseudovalue') - % compute the pseudovalues for the beamformer output - avg = source.trial(1); % the first is the complete average - Ntrials = length(source.trial)-1; % the remaining are the leave-one-out averages - pseudoval = []; - if isfield(source.trial, 'pow') - allavg = getfield(avg, 'pow'); - for i=1:Ntrials - thisavg = getfield(source.trial(i+1), 'pow'); - thisval = Ntrials*allavg - (Ntrials-1)*thisavg; - pseudoval(i).pow = thisval; - end - end - if isfield(source.trial, 'coh') - allavg = getfield(avg, 'coh'); - for i=1:Ntrials - thisavg = getfield(source.trial(i+1), 'coh'); - thisval = Ntrials*allavg - (Ntrials-1)*thisavg; - pseudoval(i).coh = thisval; - end - end - if isfield(source.trial, 'nai') - allavg = getfield(avg, 'nai'); - for i=1:Ntrials - thisavg = getfield(source.trial(i+1), 'nai'); - thisval = Ntrials*allavg - (Ntrials-1)*thisavg; - pseudoval(i).nai = thisval; - end - end - if isfield(source.trial, 'noise') - allavg = getfield(avg, 'noise'); - for i=1:Ntrials - thisavg = getfield(source.trial(i+1), 'noise'); - thisval = Ntrials*allavg - (Ntrials-1)*thisavg; - pseudoval(i).noise = thisval; - end - end - % store the pseudovalues instead of the original values - source.trial = pseudoval; -end - -if strcmp(source.method, 'jackknife') || strcmp(source.method, 'bootstrap') || strcmp(source.method, 'pseudovalue') || strcmp(source.method, 'singletrial') || strcmp(source.method, 'rawtrial') - % compute descriptive statistics (mean, var, sem) for multiple trial data - % compute these for as many source parameters as possible - - % for convenience copy the trials out of the source structure - dip = source.trial; - - % determine the (original) number of trials in the data - if strcmp(source.method, 'bootstrap') %VERANDERD ER ZAT GEEN .RESAMPLE IN SOURCE - Ntrials = size(source.trial,2);% WAS size(source.resample, 2); - else - Ntrials = length(source.trial); - end - fprintf('original data contained %d trials\n', Ntrials); - - % allocate memory for all elements in the dipole structure - sumdip = []; - if isfield(dip(1), 'var'), sumdip.var = zeros(size(dip(1).var )); sumdip.var(source.outside)=nan; end - if isfield(dip(1), 'pow'), sumdip.pow = zeros(size(dip(1).pow )); sumdip.pow(source.outside)=nan; end - if isfield(dip(1), 'coh'), sumdip.coh = zeros(size(dip(1).coh )); sumdip.coh(source.outside)=nan; end - if isfield(dip(1), 'rv'), sumdip.rv = zeros(size(dip(1).rv )); sumdip.rv(source.outside)=nan; end - if isfield(dip(1), 'noise'), sumdip.noise = zeros(size(dip(1).noise)); sumdip.noise(source.outside)=nan; end - if isfield(dip(1), 'nai'), sumdip.nai = zeros(size(dip(1).nai )); sumdip.nai(source.outside)=nan; end - sqrdip = []; - if isfield(dip(1), 'var'), sqrdip.var = zeros(size(dip(1).var )); sqrdip.var(source.outside)=nan; end - if isfield(dip(1), 'pow'), sqrdip.pow = zeros(size(dip(1).pow )); sqrdip.pow(source.outside)=nan; end - if isfield(dip(1), 'coh'), sqrdip.coh = zeros(size(dip(1).coh )); sqrdip.coh(source.outside)=nan; end - if isfield(dip(1), 'rv'), sqrdip.rv = zeros(size(dip(1).rv )); sqrdip.rv(source.outside)=nan; end - if isfield(dip(1), 'noise'), sqrdip.noise = zeros(size(dip(1).noise)); sqrdip.noise(source.outside)=nan; end - if isfield(dip(1), 'nai'), sqrdip.nai = zeros(size(dip(1).nai )); sqrdip.nai(source.outside)=nan; end - if isfield(dip(1), 'mom') - sumdip.mom = cell(size(dip(1).mom)); - sqrdip.mom = cell(size(dip(1).mom)); - for i=1:length(dip(1).mom) - sumdip.mom{i} = nan*zeros(size(dip(1).mom{i})); - sqrdip.mom{i} = nan*zeros(size(dip(1).mom{i})); - end - end - if isfield(dip(1), 'csd') - sumdip.csd = cell(size(dip(1).csd)); - sqrdip.csd = cell(size(dip(1).csd)); - for i=1:length(dip(1).csd) - sumdip.csd{i} = nan*zeros(size(dip(1).csd{i})); - sqrdip.csd{i} = nan*zeros(size(dip(1).csd{i})); - end - end - - for trial=1:length(dip) - % compute the sum of all values - if isfield(dip(trial), 'var'), sumdip.var = sumdip.var + dip(trial).var; end - if isfield(dip(trial), 'pow'), sumdip.pow = sumdip.pow + dip(trial).pow; end - if isfield(dip(trial), 'coh'), sumdip.coh = sumdip.coh + dip(trial).coh; end - if isfield(dip(trial), 'rv'), sumdip.rv = sumdip.rv + dip(trial).rv; end - if isfield(dip(trial), 'noise'), sumdip.noise = sumdip.noise + dip(trial).noise; end - if isfield(dip(trial), 'nai'), sumdip.nai = sumdip.nai + dip(trial).nai; end - % compute the sum of squared values - if isfield(dip(trial), 'var'), sqrdip.var = sqrdip.var + (dip(trial).var ).^2; end - if isfield(dip(trial), 'pow'), sqrdip.pow = sqrdip.pow + (dip(trial).pow ).^2; end - if isfield(dip(trial), 'coh'), sqrdip.coh = sqrdip.coh + (dip(trial).coh ).^2; end - if isfield(dip(trial), 'rv'), sqrdip.rv = sqrdip.rv + (dip(trial).rv ).^2; end - if isfield(dip(trial), 'noise'), sqrdip.noise = sqrdip.noise + (dip(trial).noise).^2; end - if isfield(dip(trial), 'nai'), sqrdip.nai = sqrdip.nai + (dip(trial).nai ).^2; end - % do the same for the cell array with mom - if isfield(dip(trial), 'mom') - for i=1:length(dip(1).mom) - sumdip.mom{i} = sumdip.mom{i} + dip(trial).mom{i}; - sqrdip.mom{i} = sqrdip.mom{i} + (dip(trial).mom{i}).^2; - end - end - % do the same for the cell array with csd - if isfield(dip(trial), 'csd') - for i=1:length(dip(1).csd) - sumdip.csd{i} = sumdip.csd{i} + dip(trial).csd{i}; - sqrdip.csd{i} = sqrdip.csd{i} + (dip(trial).csd{i}).^2; - end - end - end - - % compute the mean over all repetitions - if isfield(sumdip, 'var'), dipmean.var = sumdip.var / length(dip); end - if isfield(sumdip, 'pow'), dipmean.pow = sumdip.pow / length(dip); end - if isfield(sumdip, 'coh'), dipmean.coh = sumdip.coh / length(dip); end - if isfield(sumdip, 'rv'), dipmean.rv = sumdip.rv / length(dip); end - if isfield(sumdip, 'noise'), dipmean.noise = sumdip.noise / length(dip); end - if isfield(sumdip, 'nai'), dipmean.nai = sumdip.nai / length(dip); end - % for the cell array with mom, this is done further below - % for the cell array with csd, this is done further below - - % the estimates for variance and SEM are biased if we are working with the jackknife/bootstrap - % determine the proper variance scaling that corrects for this bias - % note that Ntrials is not always the same as the length of dip, especially in case of the bootstrap - if strcmp(source.method, 'singletrial') - bias = 1; - elseif strcmp(source.method, 'rawtrial') - bias = 1; - elseif strcmp(source.method, 'jackknife') - % Effron gives SEM estimate for the jackknife method in equation 11.5 (paragraph 11.2) - % to get the variance instead of SEM, we also have to multiply with the number of trials - bias = (Ntrials - 1)^2; - elseif strcmp(source.method, 'bootstrap') - % Effron gives SEM estimate for the bootstrap method in algorithm 6.1 (equation 6.6) - % to get the variance instead of SEM, we also have to multiply with the number of trials - bias = Ntrials; - elseif strcmp(source.method, 'pseudovalue') - % note that I have not put any thought in this aspect yet - warning('don''t know how to compute bias for pseudovalue resampling'); - bias = 1; - end - - % compute the variance over all repetitions - if isfield(sumdip, 'var'), dipvar.var = bias*(sqrdip.var - (sumdip.var .^2)/length(dip))/(length(dip)-1); end - if isfield(sumdip, 'pow'), dipvar.pow = bias*(sqrdip.pow - (sumdip.pow .^2)/length(dip))/(length(dip)-1); end - if isfield(sumdip, 'coh'), dipvar.coh = bias*(sqrdip.coh - (sumdip.coh .^2)/length(dip))/(length(dip)-1); end - if isfield(sumdip, 'rv' ), dipvar.rv = bias*(sqrdip.rv - (sumdip.rv .^2)/length(dip))/(length(dip)-1); end - if isfield(sumdip, 'noise' ), dipvar.noise = bias*(sqrdip.noise - (sumdip.noise .^2)/length(dip))/(length(dip)-1); end - if isfield(sumdip, 'nai' ), dipvar.nai = bias*(sqrdip.nai - (sumdip.nai .^2)/length(dip))/(length(dip)-1); end - - % compute the SEM over all repetitions - if isfield(sumdip, 'var'), dipsem.var = (dipvar.var /Ntrials).^0.5; end - if isfield(sumdip, 'pow'), dipsem.pow = (dipvar.pow /Ntrials).^0.5; end - if isfield(sumdip, 'coh'), dipsem.coh = (dipvar.coh /Ntrials).^0.5; end - if isfield(sumdip, 'rv' ), dipsem.rv = (dipvar.rv /Ntrials).^0.5; end - if isfield(sumdip, 'noise' ), dipsem.noise = (dipvar.noise /Ntrials).^0.5; end - if isfield(sumdip, 'nai' ), dipsem.nai = (dipvar.nai /Ntrials).^0.5; end - - % compute the mean and SEM over all repetitions for the cell array with mom - if isfield(dip(trial), 'mom') - for i=1:length(dip(1).mom) - dipmean.mom{i} = sumdip.mom{i}/length(dip); - dipvar.mom{i} = bias*(sqrdip.mom{i} - (sumdip.mom{i}.^2)/length(dip))/(length(dip)-1); - dipsem.mom{i} = (dipvar.mom{i}/Ntrials).^0.5; - end - end - - % compute the mean and SEM over all repetitions for the cell array with csd - if isfield(dip(trial), 'csd') - for i=1:length(dip(1).csd) - dipmean.csd{i} = sumdip.csd{i}/length(dip); - dipvar.csd{i} = bias*(sqrdip.csd{i} - (sumdip.csd{i}.^2)/length(dip))/(length(dip)-1); - dipsem.csd{i} = (dipvar.csd{i}/Ntrials).^0.5; - end - end - - if strcmp(source.method, 'pseudovalue') - % keep the trials, since they have been converted to pseudovalues - % and hence the trials contain the interesting data - elseif keeptrials - % keep the trials upon request - else - % remove the original trials - source = rmfield(source, 'trial'); - % assign the descriptive statistics to the output source structure - source.avg = dipmean; - source.var = dipvar; - source.sem = dipsem; - end -end - -if strcmp(cfg.resolutionmatrix, 'yes') - % this is only implemented for pcc and no refdips/chans at the moment - Nchan = size(source.leadfield{source.inside(1)}, 1); - Ninside = length(source.inside); - allfilter = zeros(Ninside,Nchan); - allleadfield = zeros(Nchan,Ninside); - dipsel = match_str(source.avg.csdlabel, 'scandip'); - progress('init', cfg.feedback, 'computing resolution matrix'); - for diplop=1:length(source.inside) - progress(diplop/length(source.inside), 'computing resolution matrix %d/%d\n', diplop, length(source.inside)); - i = source.inside(diplop); - % concatenate all filters - allfilter(diplop,:) = source.avg.filter{i}(dipsel,:); - % concatenate all leadfields - allleadfield(:,diplop) = source.leadfield{i}; - end - progress('close'); - % multiply the filters and leadfields to obtain the resolution matrix - % see equation 1 and 2 in De Peralta-Menendez RG, Gonzalez-Andino SL: A critical analysis of linear inverse solutions to the neuroelectromagnetic inverse problem. IEEE Transactions on Biomedical Engineering 45: 440-448, 1998. - source.resolution = nan*zeros(Ndipole, Ndipole); - source.resolution(source.inside, source.inside) = allfilter*allleadfield; -end - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: sourcedescriptives.m,v 1.45 2009/10/12 14:40:24 jansch Exp $'; -% remember the configuration details of the input data -try, cfg.previous = source.cfg; end -% remember the exact configuration details in the output -source.cfg = cfg; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% helper function to compute eta from a csd-matrix -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [eta, u] = csd2eta(csd) -[u,s,v] = svd(real(csd)); -eta = s(2,2)./s(1,1); -u = u'; %orientation is defined in the rows - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% helper function to compute fa from a csd-matrix -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [fa] = csd2fa(csd) -s = svd(real(csd)); -ns = rank(real(csd)); -s = s(1:ns); -ms = mean(s); -fa = sqrt( (ns./(ns-1)) .* (sum((s-ms).^2))./(sum(s.^2)) ); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% helper function to compute power -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function p = powmethod_lambda1(x, ind); - -if nargin==1, - ind = 1:size(x,1); -end -s = svd(x(ind,ind)); -p = s(1); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% helper function to compute power -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function p = powmethod_trace(x, ind); - -if nargin==1, - ind = 1:size(x,1); -end -p = trace(x(ind,ind)); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% helper function to compute power -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function p = powmethod_regular(x, ind); - -if nargin==1, - ind = 1:size(x,1); -end -p = abs(x(ind,ind)); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% helper function to obtain the largest singular value or trace of the -% source CSD matrices resulting from DICS -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function s = lambda1(x); -s = svd(x); -s = s(1); diff --git a/external/fieldtrip/private/sourcegrandaverage.m b/external/fieldtrip/private/sourcegrandaverage.m deleted file mode 100644 index 13abfb4..0000000 --- a/external/fieldtrip/private/sourcegrandaverage.m +++ /dev/null @@ -1,307 +0,0 @@ -function [grandavg] = sourcegrandaverage(cfg, varargin); - -% SOUREGRANDAVERAGE averages source reconstructions over either multiple -% subjects or conditions. It computes the average and variance for all -% known source parameters. The output can be used in SOURCESTATISTICS -% with the method 'parametric'. -% -% Alternatively, it can construct an average for multiple input source -% reconstructions in two conditions after randomly reassigning the -% input data over the two conditions. The output then can be used in -% SOURCESTATISTICS with the method 'randomization' or 'randcluster'. -% -% The input source structures should be spatially alligned to each other -% and should have the same positions for the source grid. -% -% Use as -% [grandavg] = SOUREGRANDAVERAGE(cfg, source1, source2, ...) -% -% where the source structures are obtained from SOURCEANALYSIS or -% from VOLUMENORMALISE, and the configuration can contain the -% following fields: -% cfg.parameter = string, describing the functional data to be processed, e.g. 'pow', 'nai' or 'coh' -% cfg.keepindividual = 'no' or 'yes' -% -% See also SOURCEANALYSIS, VOLUMENORMALISE, SOURCESTATISTICS - -% Undocumented local options -% You can also use SOURCEGRANDAVERAGE to compute averages after -% randomizing the assignment of the functional data over two conditions. -% The resulting output can then be used in a statistical test just like -% the randomized single-subject source reconstruction that results from -% randomization in SOURCEANALYSIS. This involves the following options -% cfg.randomization = 'no' or 'yes' -% cfg.permutation = 'no' or 'yes' -% cfg.numrandomization = number, e.g. 500 -% cfg.numpermutation = number, e.g. 500 or 'all' -% cfg.c1 = list with subjects belonging to condition 1 (or A) -% cfg.c2 = list with subjects belonging to condition 2 (or B) - -% Copyright (C) 2005, Robert Oostenveld -% -% $Log: sourcegrandaverage.m,v $ -% Revision 1.21 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.20 2008/11/21 13:21:35 sashae -% added call to checkconfig at start and end of fucntion -% -% Revision 1.19 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.18 2008/09/17 15:02:36 roboos -% removed call to fixvolume function, checkdata now takes care of it -% -% Revision 1.17 2007/07/31 13:02:05 jansch -% built in option to concatenate sources, e.g. across frequency, with the option -% cfg.concatenate -% -% Revision 1.16 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.15 2007/04/03 10:04:20 roboos -% allow both source and volume data as input -% -% Revision 1.14 2007/03/30 17:05:40 ingnie -% checkinput; only proceed when input data is allowed datatype -% -% Revision 1.13 2006/09/04 15:41:11 roboos -% quick fix for missing parameterselection in case data not in avg.something, it should be fixed in a better way -% -% Revision 1.12 2006/07/05 10:21:56 roboos -% updaed documentation for consistency -% -% Revision 1.11 2006/05/23 14:03:27 roboos -% removed the fixvolume, since th evolumetric description does not hold for sparse source representations -% -% Revision 1.10 2006/05/23 10:20:09 roboos -% some changes to the help and comments, changed length(varargin) by Nsubject, added a fixvolume at the end -% -% Revision 1.9 2005/08/19 16:58:27 roboos -% fixed bug, the inside of the brain was filled with nans, that should be the outside -% -% Revision 1.8 2005/07/18 10:21:44 roboos -% corrected the inside/outside determination from all volumes -% -% Revision 1.7 2005/06/29 12:46:29 roboos -% the following changes were done on a large number of files at the same time, not all of them may apply to this specific file -% - added try-catch around the inclusion of input data configuration -% - moved cfg.version, cfg.previous and the assignment of the output cfg to the end -% - changed help comments around the configuration handling -% - some changes in whitespace -% -% Revision 1.6 2005/06/09 11:04:45 roboos -% replaced normal mean and std by their nan counterpart -% explicitely set voxels that are outside of the brain volume to nan for each subject prior to averaging -% added copyrights and cvs log statement -% - -fieldtripdefs - -cfg = checkconfig(cfg, 'trackconfig', 'on'); - -% check if the input data is valid for this function -for i=1:length(varargin) - varargin{i} = checkdata(varargin{i}, 'datatype', {'source', 'volume'}, 'feedback', 'no'); -end - -% set the defaults -if ~isfield(cfg, 'parameter'), cfg.parameter = 'pow'; end -if ~isfield(cfg, 'keepindividual'), cfg.keepindividual = 'no'; end -if ~isfield(cfg, 'concatenate'), cfg.concatenate = 'no'; end -if ~isfield(cfg, 'randomization'), cfg.randomization = 'no'; end -if ~isfield(cfg, 'permutation'), cfg.permutation = 'no'; end -if ~isfield(cfg, 'c1'), cfg.c1 = []; end -if ~isfield(cfg, 'c2'), cfg.c2 = []; end - -if strcmp(cfg.concatenate, 'yes') && strcmp(cfg.keepindividual, 'yes'), - error('you can either specify cfg.keepindividual or cfg.concatenate to be yes'); -end - -Nsubject = length(varargin); -Nvoxel = prod(varargin{1}.dim); -dat = zeros(Nvoxel, Nsubject); -inside = zeros(Nvoxel, Nsubject); - -if isfield(varargin{1}, 'pos') - % check that the source locations of each input source reconstruction are the same - for i=2:Nsubject - if size(varargin{i}.pos,1)~=size(varargin{1}.pos,1) || any(varargin{i}.pos(:)~=varargin{1}.pos(:)) - error('different grid locations in source reconstructions'); - end - end - grandavg.pos = varargin{1}.pos; -end - -if isfield(varargin{1}, 'dim') - % check that the dimensions of each input volume is the same - for i=2:Nsubject - if any(varargin{i}.dim(:)~=varargin{1}.dim(:)) - error('different dimensions of the source reconstructions'); - end - end - grandavg.dim = varargin{1}.dim; -end - -if isfield(varargin{1}, 'xgrid') && isfield(varargin{1}, 'ygrid') && isfield(varargin{1}, 'zgrid') - % check that the grid locations of each input volume are the same - for i=2:Nsubject - if length(varargin{i}.xgrid)~=length(varargin{1}.xgrid) || any(varargin{i}.xgrid~=varargin{1}.xgrid) - error('different xgrid in source reconstructions'); - elseif length(varargin{i}.ygrid)~=length(varargin{1}.ygrid) || any(varargin{i}.ygrid~=varargin{1}.ygrid) - error('different ygrid in source reconstructions'); - elseif length(varargin{i}.zgrid)~=length(varargin{1}.zgrid) || any(varargin{i}.zgrid~=varargin{1}.zgrid) - error('different zgrid in source reconstructions'); - end - end - grandavg.xgrid = varargin{1}.xgrid; - grandavg.ygrid = varargin{1}.ygrid; - grandavg.zgrid = varargin{1}.zgrid; -end - -if isfield(varargin{1}, 'transform') - % check that the homogenous transformation matrix of each input volume is the same - for i=2:Nsubject - if any(varargin{i}.transform(:)~=varargin{1}.transform(:)) - error('different homogenous transformation matrices in source reconstructions'); - end - end - grandavg.transform = varargin{1}.transform; -end - -% get the source parameter from each input source reconstruction -% get the inside parameter from each input source reconstruction -for i=1:Nsubject - % TODO this function should use parameterselection - if issubfield(varargin{i}, ['avg.' cfg.parameter]) - tmp = getsubfield(varargin{i}, ['avg.' cfg.parameter]); - else - tmp = getsubfield(varargin{i}, cfg.parameter); - end - dat(:,i) = tmp(:); - tmp = getsubfield(varargin{i}, 'inside'); - inside(tmp,i) = 1; -end -% ensure that voxels that are not in the scanned brain region are excluded from the averaging -dat(~inside) = nan; - -if strcmp(cfg.randomization, 'yes') || strcmp(cfg.permutation, 'yes') - if strcmp(cfg.keepindividual, 'yes') - error('you cannot keep individual data in combination with randomization or permutation'); - end - - % construct a design vector that contains the condition number 1 or 2 - design = zeros(1,Nsubject); - design(cfg.c1) = 1; - design(cfg.c2) = 2; - if any(design==0) - error('not all input source structures have been assigned to a condition'); - elseif length(design)~=Nsubject - error('not enough input source structures given cfg.c1 and cfg.c2'); - end - - % create a matrix with all randomized assignments to the two conditions - if strcmp(cfg.randomization, 'yes') - res = zeros(cfg.numrandomization, Nsubject); - for i=1:cfg.numrandomization - res(i,:) = design(randperm(Nsubject)); - end - elseif strcmp(cfg.permutation, 'yes') - sel1 = find(design==1); - sel2 = find(design==2); - if length(sel1)~=length(sel2) - error('permutation requires that there is an equal number of replications in each conditions') - end - res = zeros(cfg.numpermutation, Nsubject); - for i=1:cfg.numpermutation - flip = randn(1,length(sel1))>0; - res(i,sel1) = 1; - res(i,sel2) = 2; - res(i,sel1(find(flip))) = 2; - res(i,sel2(find(flip))) = 1; - end - end % randomization or permutation - - % randomize the input source parameter between the two conditions - clear trialA - clear trialB - for i=1:size(res,1) - selA = find(res(i,:)==1); - selB = find(res(i,:)==2); - % create the randomized averaged data - trialA(i) = setsubfield([], cfg.parameter, nan_mean(dat(:,selA),2)); - trialB(i) = setsubfield([], cfg.parameter, nan_mean(dat(:,selB),2)); - end - % create the observed average data - selA = find(design==1); - selB = find(design==2); - avgA = setsubfield([], cfg.parameter, nan_mean(dat(:,selA),2)); - avgB = setsubfield([], cfg.parameter, nan_mean(dat(:,selB),2)); - - % construct a source structure that can be fed into SOURCESTATISTICS_RANDOMIZATION or SOURCESTATISTICS_RANDCLUSTER - grandavg.trialA = trialA; - grandavg.trialB = trialB; - grandavg.avgA = avgA; - grandavg.avgB = avgB; - -else - if strcmp(cfg.concatenate, 'no'), - % compute a plain average and variance over all input source structures - grandavg.avg = setsubfield([], cfg.parameter, nan_mean(dat,2)); - grandavg.var = setsubfield([], cfg.parameter, nan_std(dat')'.^2); % nan_std operates over the first dimension - grandavg.dimord = 'voxel'; - else - grandavg.avg = setsubfield([], cfg.parameter, dat); - grandavg.dimord = 'voxel_freq'; - grandavg.dim = [grandavg.dim size(dat,2)]; - end - - if strcmp(cfg.keepindividual, 'yes') - clear trial - for i=1:Nsubject - trial(i) = setsubfield([], cfg.parameter, dat(:,i)); - end - grandavg.trial = trial; - end -end - -% determine which sources were inside or outside the brain in all subjects -allinside = find(all( inside,2)); -alloutside = find(all(~inside,2)); -someinside = find(any( inside,2)); -fprintf('%d voxels are inside the brain of all subjects\n', length(allinside)); -fprintf('%d voxels are inside the brain of some, but not all subjects\n', length(someinside)); -fprintf('%d voxels are outside the brain of all subjects\n', length(alloutside)); -warning('marking only voxels inside the brain of all subjects as ''inside'''); -if strcmp(cfg.concatenate, 'no'), - grandavg.inside = find(all( inside,2)); - grandavg.outside = find(any(~inside,2)); - grandavg.df = sum(inside,2); -else - grandavg.inside = find(inside(:)); - grandavg.outside = setdiff([1:prod(size(dat))]', grandavg.inside); -end - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: sourcegrandaverage.m,v 1.21 2009/01/20 13:01:31 sashae Exp $'; -% remember the configuration details of the input data -cfg.previous = []; -for i=1:Nsubject - try, cfg.previous{i} = varargin{i}.cfg; end -end -% remember the exact configuration details in the output -grandavg.cfg = cfg; - diff --git a/external/fieldtrip/private/sourceinterpolate.m b/external/fieldtrip/private/sourceinterpolate.m deleted file mode 100644 index e06148d..0000000 --- a/external/fieldtrip/private/sourceinterpolate.m +++ /dev/null @@ -1,414 +0,0 @@ -function [interp] = sourceinterpolate(cfg, functional, anatomical); - -% SOURCEINTERPOLATE reslices and interpolates a source reconstruction -% or a statistical distribution as an overlay onto an anatomical MRI. -% -% The source volume and the anatomical volume should be expressed in the -% same coordinate sytem, i.e. either both in CTF coordinates (NAS/LPA/RPA) -% or both in SPM coordinates (AC/PC). The output volume will contain a -% resliced source and anatomical volume that can be plotted together with -% SOURCEPLOT or SLICEINTERP, or that can be written to file using SOURCEWRITE. -% -% Use as -% [interp] = sourceinterpolate(cfg, source, mri) or -% [interp] = sourceinterpolate(cfg, stat, mri) -% where -% source is the output of SOURCEANALYSIS -% stat is the output of SOURCESTATISTICS -% mri is the output of READ_FCDC_MRI or the filename of a MRI -% and cfg is a structure with any of the following fields -% cfg.parameter = string, default is 'all' -% cfg.interpmethod = 'linear', 'cubic', 'nearest' or 'spline' -% cfg.sourceunits = 'mm' or 'cm' (default is 'cm') -% cfg.mriunits = 'mm' or 'cm' (default is 'mm') -% cfg.downsample = integer number (default = 1, i.e. no downsampling) -% -% See also SOURCEANALYSIS, SOURCESTATISTICS, READ_FCDC_MRI - -% Undocumented options -% cfg.voxelcoord = 'yes' (default) or 'no' determines whether the -% downsampled output anatomical MRI will have the x/y/zgrid converted or -% the homogenous transformation matrix - -% Copyright (C) 2003-2007, Robert Oostenveld -% -% $Log: sourceinterpolate.m,v $ -% Revision 1.54 2009/10/12 14:18:32 jansch -% allow for multidimensional sources containing frequency and/or time axes -% -% Revision 1.53 2009/07/09 16:08:22 vlalit -% replaced read_fcdc_mri with read_mri to avoid warning -% -% Revision 1.52 2009/03/11 11:30:45 roboos -% use autodetection of source and MRI units -% -% Revision 1.51 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.50 2009/01/12 13:05:20 sashae -% small change in call to checkconfig -% -% Revision 1.49 2008/11/21 13:56:12 sashae -% added call to checkconfig at start and end of function -% -% Revision 1.48 2008/10/10 15:45:41 sashae -% added call to checkconfig -% -% Revision 1.47 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.46 2008/08/20 11:03:53 ingnie -% fixed bug in extrapolating to outside, av changed into fv -% -% Revision 1.45 2008/08/01 18:32:37 ingnie -% inside always kept, added extrapolating to outside to optimize interpolation at the edges, all logical volumes (incl inside) are interpolated with method nearest and stay logicals, whole (irregular) outside of functional volumes set to NaN. -% -% Revision 1.44 2008/07/22 11:38:24 ingnie -% removed fixvolume, make full use of checkdata (also to ensure inside is logical volume) -% -% Revision 1.43 2007/04/18 10:30:41 roboos -% switched to interpolation in voxel indeices, since in some cases interpn had problems (esp when the coordinate axes were strongly rotated) -% apply the cm->mm scaling to the functional transfortmation matrix prior to computing voxel positions -% allow the interpolation of one anatomy onto another, i.e. do not overwrite anatomy if it was interpolated -% -% Revision 1.42 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.41 2007/03/30 17:05:40 ingnie -% checkinput; only proceed when input data is allowed datatype -% -% Revision 1.40 2007/02/27 15:24:57 ingnie -% sel from voxel index to logical index, ~sel volumes NaNs iso zeros (except inside) -% -% Revision 1.39 2006/07/27 08:30:01 roboos -% updated documentation -% -% Revision 1.38 2006/06/08 07:50:52 roboos -% updated the conversion between the source and MRI units (support mm,cm,dm,m for both) -% -% Revision 1.37 2006/03/09 08:19:44 roboos -% try not to interpolate cell-array volumes, e.g. mom, lf, csd -% -% Revision 1.36 2006/02/24 16:44:41 roboos -% switched to fixvolume function, with inside as 3d volume -% not neccessary any more to treat inside/outside seperately -% not neccessary any more to reshape volumes -% not neccessary any more to change from xgrid/etc into transform -% -% Revision 1.35 2006/02/07 22:21:47 roboos -% changed fprintf feedback into progress() function, added cfg.feedback -% -% Revision 1.34 2006/01/31 09:48:39 jansch -% fixed bug regarding last change -% -% Revision 1.33 2006/01/31 09:45:32 jansch -% changed else cfg.keepinside='no' into an elseif to prevent crashes -% -% Revision 1.32 2006/01/31 09:27:58 roboos -% in case of keepinside: instead of setting outside to [], remove it from structure -% -% Revision 1.31 2006/01/30 13:55:19 roboos -% changed the order in which the initial preparatory steps are taken -% related to inside-conversion, parameterselection and grid2transform -% -% Revision 1.30 2006/01/24 21:28:35 roboos -% removes obsolete tmpcfg.voxelcoord for downsample (default is now yes) -% updated the local voxelcoords() subfunction -% -% Revision 1.29 2006/01/05 13:38:23 roboos -% Changed the use of the parameterselection function which now always returns a cell-array. -% Use the private/grid2transform function to ensure that both the -% anatomical and functional volumes are described using the homogenous -% transformation matrix and not with xgrid/ygrid/zgrid. -% -% Revision 1.28 2005/11/10 10:02:14 roboos -% minor change in whitespace and help -% -% Revision 1.27 2005/10/14 15:48:57 roboos -% add inside to cfg.parameter if keepinside=yes and parameter~=all -% -% Revision 1.26 2005/08/29 10:18:16 roboos -% perform downsamplevolume with restricted copy of configuration and explicitely on parameter=anatomy -% -% Revision 1.25 2005/08/19 17:10:35 roboos -% completely new implementation from scratch. It now also supports interpolation of -% any volume to any volume, i.e. the function input does not have to be aligned with -% the axes of the coordinate system. -% -% Revision 1.24 2005/06/29 12:46:29 roboos -% the following changes were done on a large number of files at the same time, not all of them may apply to this specific file -% - added try-catch around the inclusion of input data configuration -% - moved cfg.version, cfg.previous and the assignment of the output cfg to the end -% - changed help comments around the configuration handling -% - some changes in whitespace -% -% Revision 1.23 2005/06/10 09:13:58 jansch -% fixed bug which was introduced during the last revision -% -% Revision 1.22 2005/06/03 08:59:59 roboos -% added support for interpolating already interpolated low-res stats structures back onto the high-res anatomy -% fixed bug in scaling of source positions (it always scaled them 10x, regardless of cfg.sourceunits) -% -% Revision 1.21 2005/05/17 17:50:38 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.20 2005/02/09 13:09:52 roboos -% explicitly emptied source.outside if keepinside=yes -% -% Revision 1.19 2005/02/08 11:45:00 roboos -% implemented cfg.mriunits (default mm) -% implemented cfg.keepinside (default yes) -% removed obsolete cfg.parameter -% changed handling of all volumes that should be interpolated (now through list with subfields) -% cleaned up code and help -% -% Revision 1.18 2004/10/13 14:11:30 roboos -% changed cfg.previous, now consistent over functions with try-statement -% and will also work if the input already had a cfg.previous -% -% Revision 1.17 2004/09/21 09:37:24 jansch -% fixed small bug due to yesterday's changes -% -% Revision 1.16 2004/09/20 09:32:15 roboos -% changed implementation of downsampling to use the external downsamplevolume function -% - -fieldtripdefs - -%% checkdata see below!!! %% - -% check if the input cfg is valid for this function -cfg = checkconfig(cfg, 'trackconfig', 'on'); -cfg = checkconfig(cfg, 'unused', {'keepinside'}); - -% set the defaults -if ~isfield(cfg, 'parameter'), cfg.parameter = 'all'; end -if ~isfield(cfg, 'interpmethod'); cfg.interpmethod = 'linear'; end -if ~isfield(cfg, 'downsample'); cfg.downsample = 1; end -if ~isfield(cfg, 'voxelcoord'), cfg.voxelcoord = 'yes'; end -if ~isfield(cfg, 'feedback'), cfg.feedback = 'text'; end - -% if ~isfield(cfg, 'sourceunits'); cfg.sourceunits = []; end % this is deprecated, since now autodetermined -% if ~isfield(cfg, 'mriunits'); cfg.mriunits = []; end % this is deprecated, since now autodetermined -cfg = checkconfig(cfg, 'deprecated', {'sourceunits', 'mriunits'}); - -if ischar(anatomical) - % read the anatomical MRI data from file - fprintf('reading MRI from file\n'); - anatomical = read_mri(anatomical); -end - -% check if the input data is valid for this function and ensure that the structures correctly describes a volume -functional = checkdata(functional, 'datatype', 'volume', 'inside', 'logical', 'feedback', 'yes'); -anatomical = checkdata(anatomical, 'datatype', 'volume', 'inside', 'logical', 'feedback', 'yes'); - -% this ensures that the geometrical units of both functional and anatomical data are specified -% FIMXE this probably should be moved into checkdata -functional = convert_units(functional); -anatomical = convert_units(anatomical); - -if isfield(cfg, 'sourceunits') && ~isempty(cfg.sourceunits) - % this uses a deprecated option - if ~strcmp(functional.unit, cfg.sourceunits) - warning('the automatically determined sourceunits (%s) do not match your specification (%s)', functional.unit, cfg.sourceunits); - functional.unit = cfg.sourceunits; % override the automatically determined units - end -end - -if isfield(cfg, 'mriunits') && ~isempty(cfg.mriunits) - % this uses a deprecated option - if ~strcmp(anatomical.unit, cfg.mriunits) - warning('the automatically determined mriunits (%s) do not match your specification (%s)', anatomical.unit, cfg.sourceunits); - anatomical.unit = cfg.mriunits; % override the automatically determined units - end -end - -if ~strcmp(functional.unit, anatomical.unit) - fprintf('converting functional data from %s into %s\n', functional.unit, anatomical.unit); - functional = convert_units(functional, anatomical.unit); -end - -% select the parameters that should be interpolated -cfg.parameter = parameterselection(cfg.parameter, functional); -cfg.parameter = setdiff(cfg.parameter, 'inside'); % inside is handled seperately - -% downsample the anatomical volume -tmpcfg = []; -tmpcfg.downsample = cfg.downsample; -tmpcfg.parameter = 'anatomy'; -anatomical = volumedownsample(tmpcfg, anatomical); - -% collect the functional volumes that should be converted -vol_name = {}; -vol_data = {}; -for i=1:length(cfg.parameter) - if ~iscell(getsubfield(functional, cfg.parameter{i})) - vol_name{end+1} = cfg.parameter{i}; - vol_data{end+1} = getsubfield(functional, cfg.parameter{i}); - else - fprintf('not interpolating %s, since it is not a scalar field\n', cfg.parameter{i}); - end -end - -% compute the position of each voxel in both volumes, expressed in headcoordinates -[fx, fy, fz] = voxelcoords(functional); -[ax, ay, az] = voxelcoords(anatomical); -% convert the anatomical voxel positions into voxel indices into the functional volume -pos = [ax(:) ay(:) az(:)]; -pos = warp_apply(inv(functional.transform), pos); -ax = reshape(pos(:,1), anatomical.dim); -ay = reshape(pos(:,2), anatomical.dim); -az = reshape(pos(:,3), anatomical.dim); -clear pos - -% estimate the subvolume of the anatomy that is spanned by the functional volume -minfx = 1; -minfy = 1; -minfz = 1; -maxfx = functional.dim(1); -maxfy = functional.dim(2); -maxfz = functional.dim(3); -sel = ax(:)>=minfx & ... - ax(:)<=maxfx & ... - ay(:)>=minfy & ... - ay(:)<=maxfy & ... - az(:)>=minfz & ... - az(:)<=maxfz; -fprintf('selecting subvolume of %.1f%%\n', 100*sum(sel)./prod(anatomical.dim)); - -% start with an empty output structure -interp = []; - -dimf = [functional.dim 1 1]; -allav = zeros([anatomical.dim dimf(4:end)]); -functional.inside = functional.inside(:,:,:,1,1); - -% reslice and interpolate inside -interp.inside = zeros(anatomical.dim); -% interpolate with method nearest -interp.inside( sel) = my_interpn(double(functional.inside), ax(sel), ay(sel), az(sel), 'nearest', cfg.feedback); -interp.inside(~sel) = 0; -interp.inside = logical(interp.inside); - -% reslice and interpolate all functional volumes -for i=1:length(vol_name) - fprintf('reslicing and interpolating %s\n', vol_name{i}); - for k=1:dimf(4) - for m=1:dimf(5) - fv = double(vol_data{i}(:,:,:,k,m)); - av = zeros(anatomical.dim); - % av( sel) = my_interpn(fx, fy, fz, fv, ax(sel), ay(sel), az(sel), cfg.interpmethod, cfg.feedback); - if islogical(vol_data{i}) - % interpolate always with method nearest - av( sel) = my_interpn(fv, ax(sel), ay(sel), az(sel), 'nearest', cfg.feedback); - av = logical(av); - else - % extrapolate the outside of the functional volumes for better interpolation at the edges - [xi, yi, zi] = ndgrid(1:functional.dim(1), 1:functional.dim(2),1:functional.dim(3)); - X = [xi(functional.inside(:)) yi(functional.inside(:)) zi(functional.inside(:))]; - Y = fv(functional.inside(:)); - XI = [xi(~functional.inside(:)) yi(~functional.inside(:)) zi(~functional.inside(:))]; - YI = griddatan(X, Y, XI, 'nearest'); - fv(~functional.inside) = YI; - % interpolate functional onto anatomical grid - av( sel) = my_interpn(fv, ax(sel), ay(sel), az(sel), cfg.interpmethod, cfg.feedback); - av(~sel) = nan; - av(~interp.inside) = nan; - end - allav(:,:,:,k,m) = av; - end - end - interp = setsubfield(interp, vol_name{i}, allav); -end - -% add the other parameters to the output -interp.dim = anatomical.dim; -interp.transform = anatomical.transform; -if ~any(strcmp(cfg.parameter, 'anatomy')) - % copy the anatomy into the functional data - interp.anatomy = anatomical.anatomy; -end - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: sourceinterpolate.m,v 1.54 2009/10/12 14:18:32 jansch Exp $'; -% remember the configuration details of the input data -cfg.previous = []; -try, cfg.previous{1} = functional.cfg; end -try, cfg.previous{2} = anatomical.cfg; end -% remember the exact configuration details in the output -interp.cfg = cfg; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION this function computes the location of all voxels in head -% coordinates in a memory efficient manner -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [x, y, z] = voxelcoords(volume) -dim = volume.dim; -transform = volume.transform; -if isfield(volume, 'xgrid') - xgrid = volume.xgrid; - ygrid = volume.ygrid; - zgrid = volume.zgrid; -else - xgrid = 1:dim(1); - ygrid = 1:dim(2); - zgrid = 1:dim(3); -end -npix = prod(dim(1:2)); % number of voxels in a single slice -nvox = prod(dim); -x = zeros(dim); -y = zeros(dim); -z = zeros(dim); -X = zeros(1,npix); -Y = zeros(1,npix); -Z = zeros(1,npix); -E = ones(1,npix); -% determine the voxel locations per slice -for i=1:dim(3) - [X(:), Y(:), Z(:)] = ndgrid(xgrid, ygrid, zgrid(i)); - tmp = transform*[X; Y; Z; E]; - x((1:npix)+(i-1)*npix) = tmp(1,:); - y((1:npix)+(i-1)*npix) = tmp(2,:); - z((1:npix)+(i-1)*npix) = tmp(3,:); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION for memory efficient interpolation -% the only reason for this function is that it does the interpolation in smaller chuncks -% this prevents memory problems that I often encountered here -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% function [av] = my_interpn(fx, fy, fz, fv, ax, ay, az, interpmethod, feedback); -function [av] = my_interpn(fv, ax, ay, az, interpmethod, feedback); -num = numel(ax); % total number of voxels -blocksize = floor(num/20); % number of voxels to interpolate at once, split it into 20 chuncks -lastblock = 0; % boolean flag for while loop -sel = 1:blocksize; % selection of voxels that are interpolated, this is the first chunck -progress('init', feedback, 'interpolating'); -while (1) - progress(sel(1)/num, 'interpolating %.1f%%\n', 100*sel(1)/num); - if sel(end)>num - sel = sel(1):num; - lastblock = 1; - end - av(sel) = interpn(fv, ax(sel), ay(sel), az(sel), interpmethod); - if lastblock - break - end - sel = sel + blocksize; -end -progress('close'); - diff --git a/external/fieldtrip/private/sourceplot.m b/external/fieldtrip/private/sourceplot.m deleted file mode 100644 index 90d2980..0000000 --- a/external/fieldtrip/private/sourceplot.m +++ /dev/null @@ -1,1223 +0,0 @@ -function [cfg] = sourceplot(cfg, data) - -% SOURCEPLOT plots functional source reconstruction data on slices or on a -% surface, optionally as an overlay on anatomical MRI data, where -% statistical data can be used to determine the opacity of the mask. -% -% Use as: -% sourceplot(cfg, data) -% -% The data can contain functional data, anatomical MRI data and statistical data, -% interpolated onto the same grid. -% -% The configuration should contain: -% cfg.method = 'slice', plots the data on a number of slices in the same plane -% 'ortho', plots the data on three orthogonal slices -% 'surface', plots the data on a 3D brain surface -% -% cfg.anaparameter = string, field in data with the anatomical data (default = 'anatomy' if present in data) -% cfg.funparameter = string, field in data with the functional parameter of interest (default = []) -% cfg.maskparameter = string, field in the data to be used for opacity masking of fun data (default = []) -% If values are between 0 and 1, zero is fully transparant and one is fully opaque. -% If values in the field are not between 0 and 1 they will be scaled depending on the values -% of cfg.opacitymap and cfg.opacitylim (see below) -% You can use masking in several ways, f.i. -% - use outcome of statistics to show only the significant values and mask the insignificant -% NB see also cfg.opacitymap and cfg.opacitylim below -% - use the functional data itself as mask, the highest value (and/or lowest when negative) -% will be opaque and the value closest to zero transparent -% - Make your own field in the data with values between 0 and 1 to control opacity directly -% -% The following parameters can be used in all methods: -% cfg.downsample = downsampling for resolution reduction, integer value (default = 1) (orig: from surface) -% cfg.atlas = string, filename of atlas to use (default = []) SEE PREPARE_ATLAS -% for ROI masking (see "masking" below) or in interactive mode (see "ortho-plotting" below) -% cfg.inputcoord = 'mni' or 'tal', coordinate system of data used to lookup the label from the atlas -% -% The following parameters can be used for the functional data: -% cfg.funcolormap = colormap for functional data, see COLORMAP (default = 'auto') -% 'auto', depends structure funparameter, or on funcolorlim -% - funparameter: only positive values, or funcolorlim:'zeromax' -> 'hot' -% - funparameter: only negative values, or funcolorlim:'minzero' -> 'cool' -% - funparameter: both pos and neg values, or funcolorlim:'maxabs' -> 'jet' -% - funcolorlim: [min max] if min & max pos-> 'hot', neg-> 'cool', both-> 'jet' -% cfg.funcolorlim = color range of the functional data (default = 'auto') -% [min max] -% 'maxabs', from -max(abs(funparameter)) to +max(abs(funparameter)) -% 'zeromax', from 0 to max(abs(funparameter)) -% 'minzero', from min(abs(funparameter)) to 0 -% 'auto', if funparameter values are all positive: 'zeromax', -% all negative: 'minzero', both possitive and negative: 'maxabs' -% cfg.colorbar = 'yes' or 'no' (default = 'yes') -% -% The following parameters can be used for the masking data: -% cfg.opacitymap = opacitymap for mask data, see ALPHAMAP (default = 'auto') -% 'auto', depends structure maskparameter, or on opacitylim -% - maskparameter: only positive values, or opacitylim:'zeromax' -> 'rampup' -% - maskparameter: only negative values, or opacitylim:'minzero' -> 'rampdown' -% - maskparameter: both pos and neg values, or opacitylim:'maxabs' -> 'vdown' -% - opacitylim: [min max] if min & max pos-> 'rampup', neg-> 'rampdown', both-> 'vdown' -% - NB. to use p-values use 'rampdown' to get lowest p-values opaque and highest transparent -% cfg.opacitylim = range of mask values to which opacitymap is scaled (default = 'auto') -% [min max] -% 'maxabs', from -max(abs(maskparameter)) to +max(abs(maskparameter)) -% 'zeromax', from 0 to max(abs(maskparameter)) -% 'minzero', from min(abs(maskparameter)) to 0 -% 'auto', if maskparameter values are all positive: 'zeromax', -% all negative: 'minzero', both possitive and negative: 'maxabs' -% cfg.roi = string or cell of strings, region(s) of interest from anatomical atlas (see cfg.atlas above) -% everything is masked except for ROI -% -% The folowing parameters apply for ortho-plotting -% cfg.location = location of cut, (default = 'auto') -% 'auto', 'center' if only anatomy, 'max' if functional data -% 'min' and 'max' position of min/max funparameter -% 'center' of the brain -% [x y z], coordinates in voxels or head, see cfg.locationcoordinates -% cfg.locationcoordinates = coordinate system used in cfg.location, 'head' or 'voxel' (default = 'head') -% 'head', headcoordinates from anatomical MRI -% 'voxel', voxelcoordinates -% cfg.crosshair = 'yes' or 'no' (default = 'yes') -% cfg.axis = 'on' or 'off' (default = 'on') -% cfg.interactive = 'yes' or 'no' (default = 'no') -% in interactive mode cursor click determines location of cut -% cfg.queryrange = number, in atlas voxels (default 3) -% -% -% The folowing parameters apply for slice-plotting -% cfg.nslices = number of slices, (default = 20) -% cfg.slicerange = range of slices in data, (default = 'auto') -% 'auto', full range of data -% [min max], coordinates of first and last slice in voxels -% cfg.slicedim = dimension to slice 1 (x-axis) 2(y-axis) 3(z-axis) (default = 3) -% cfg.title = string, title of the figure window -% -% The folowing parameters apply for surface-plotting -% cfg.surffile = string, file that contains the surface (default = 'single_subj_T1.mat') -% 'single_subj_T1.mat' contains a triangulation that corresponds with the -% SPM anatomical template in MNI coordinates -% cfg.surfinflated = string, file that contains the inflated surface (default = []) -% cfg.surfdownsample = number (default = 1, i.e. no downsampling) -% cfg.projmethod = projection method, how functional volume data is projected onto surface -% 'nearest', 'sphere_avg', 'sphere_weighteddistance' -% cfg.sphereradius = maximum distance from each voxel to the surface to be -% included in the sphere projection methods, expressed in mm -% cfg.distmat = precomputed distance matrix (default = []) -% cfg.camlight = 'yes' or 'no' (default = 'yes') -% cfg.renderer = 'painters', 'zbuffer',' opengl' or 'none' (default = 'opengl') -% When using opacity the OpenGL renderer is required. - -% TODO have to be built in: -% cfg.marker = [Nx3] array defining N marker positions to display (orig: from sliceinterp) -% cfg.markersize = radius of markers (default = 5) -% cfg.markercolor = [1x3] marker color in RGB (default = [1 1 1], i.e. white) (orig: from sliceinterp) -% white background option - -% undocumented TODO -% slice in all directions -% surface also optimal when inside present -% come up with a good glass brain projection - -% Copyright (C) 2007-2008, Robert Oostenveld, Ingrid Nieuwenhuis -% -% $Log: sourceplot.m,v $ -% Revision 1.76 2009/10/12 14:16:15 jansch -% added correct output in interactive mode when time dimension present -% -% Revision 1.75 2009/08/30 14:58:42 crimic -% typo corrected -% -% Revision 1.74 2009/08/24 09:15:07 jansch -% included (experimental and undocumented) possibility to use image, rather than -% imagesc for the plotting, allowing for coding different aspects of the data in -% rgb-space -% -% Revision 1.73 2009/07/14 07:27:30 roboos -% replaced read_fcdc_mri with read_mri to avoid warning -% -% Revision 1.72 2009/07/08 08:10:29 roboos -% also detect int8 and int16 anatomical MRI and convert to double -% -% Revision 1.71 2009/06/17 14:05:25 roboos -% use ischar instead of isstr -% -% Revision 1.70 2009/06/17 14:03:41 roboos -% consistent handling of ginput in case figure is closed -% -% Revision 1.69 2009/05/29 14:12:32 ingnie -% only do intelligent masking (meaning opacity=0.5 when anatomy present) if not method = surface -% -% Revision 1.68 2009/05/14 12:03:59 jansch -% some changes to experimentally plot 4D and 5D volumes, undocumented -% -% Revision 1.67 2009/05/07 08:17:44 roboos -% renderer applies to gcf and not to gca (figure instead of axes) -% -% Revision 1.66 2009/05/06 15:50:51 roboos -% always set the renderer -% -% Revision 1.65 2009/03/26 13:17:33 roboos -% deal with key=[] in case apple key is pressed -% -% Revision 1.64 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.63 2008/12/16 15:02:46 sashae -% added checkconfig to start and end of function, configtracking possible -% -% Revision 1.62 2008/12/05 13:49:20 ingnie -% Replaced atlas_init by prepare_atlas. Replaced atlas_mask by volume_lookup. Updated help -% -% Revision 1.61 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.60 2008/09/17 14:49:40 roboos -% no need to add identity transform, checkdata takes care of it being a volume -% -% Revision 1.59 2008/09/17 14:48:15 jansch -% included functionality to scroll in the otrho-method, using the keys 'i' 'j' -% 'k' 'm' -% -% Revision 1.58 2008/07/31 16:28:34 roboos -% reshaping the volumes is not needed any more, thanks to checkdata -% -% Revision 1.57 2008/07/31 16:27:25 roboos -% removed grid2transform and removed xgrid etc from source representation -% let checkdata handle the conversion of any input to a volumetric representation -% -% Revision 1.56 2008/07/31 15:44:48 ingnie -% removed some comments, build in region of interest masking, moved hasatlas part up. -% -% Revision 1.55 2008/07/31 12:03:16 ingnie -% removed some comments in code, changed from using TTatlas_* to atlas_* therefor also WFU atlasses possible in interactive mode. -% -% Revision 1.54 2008/07/30 07:44:14 roboos -% changed some whitespace and comments -% -% Revision 1.53 2008/07/22 09:33:01 roboos -% added cfg.renderer option -% -% Revision 1.52 2008/07/02 18:23:43 roboos -% reinserted TTlookup code -% -% Revision 1.51 2007/11/26 09:08:57 roboos -% give instructive error if nothing is selected to be plotted -% -% Revision 1.50 2007/06/06 08:47:19 ingnie -% added possibility to turn lights off by cfg.camlight -% -% Revision 1.49 2007/05/06 12:10:08 roboos -% switched from interp_ungridded to interp_gridded, which is much faster -% added cfg.surfinflated for inflated surface -% use surface curvature (if available) for color -% -% Revision 1.48 2007/05/02 15:23:39 roboos -% only changes in whitespace -% -% Revision 1.47 2007/05/02 09:20:41 ingnie -% fixed bug; make local dim variable after downsampling -% -% Revision 1.46 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.45 2007/03/30 16:53:03 ingnie -% added checkinput; only proceed when data is allowed datatype, added error in method 'slice' when no ana and no fun, fixed typo in error -% -% Revision 1.44 2007/03/20 07:24:17 roboos -% comverted from DOS ascii to UNIX ascii -% -% Revision 1.43 2007/03/08 17:04:53 ingnie -% added colorbar option for surfaceplot -% -% Revision 1.42 2007/03/08 16:26:05 ingnie -% fixed bug in surface plotting; added hasfun and hasmsk around colormap and alphamap setting -% -% Revision 1.41 2007/02/22 18:02:59 ingnie -% added intelligent mask which prevents outside from being plotted if no maskparam specified, fixed bug that appeared when mask islogical, only transparent fun when hasana -% -% Revision 1.40 2007/02/16 16:12:02 ingnie -% added cla, fixed bug with opacitymap -% -% Revision 1.39 2007/02/08 16:47:50 ingnie -% Whole new implementation; combining sliceinterp, surfaceplot and sourceplot_old -% - -fieldtripdefs - -cfg = checkconfig(cfg, 'trackconfig', 'on'); - -%%% checkdata see below!!! %%% - -% set the common defaults -if ~isfield(cfg, 'method'), cfg.method = 'ortho'; end -if ~isfield(cfg, 'anaparameter'), - if isfield(data, 'anatomy'), - cfg.anaparameter = 'anatomy'; - else - cfg.anaparameter = []; - end -end - -% all methods -if ~isfield(cfg, 'funparameter'), cfg.funparameter = []; end -if ~isfield(cfg, 'maskparameter'), cfg.maskparameter = []; end -if ~isfield(cfg, 'downsample'), cfg.downsample = 1; end -if ~isfield(cfg, 'title'), cfg.title = ''; end -if ~isfield(cfg, 'atlas'), cfg.atlas = []; end -if ~isfield(cfg, 'marker'), cfg.marker = []; end %TODO implement marker -if ~isfield(cfg, 'markersize'), cfg.markersize = 5; end -if ~isfield(cfg, 'markercolor'), cfg.markercolor = [1,1,1]; end - -% set the common defaults for the functional data -if ~isfield(cfg, 'funcolormap'), cfg.funcolormap = 'auto'; end -if ~isfield(cfg, 'funcolorlim'), cfg.funcolorlim = 'auto'; end; - -% set the common defaults for the statistical data -if ~isfield(cfg, 'opacitymap'), cfg.opacitymap = 'auto'; end; -if ~isfield(cfg, 'opacitylim'), cfg.opacitylim = 'auto'; end; -if ~isfield(cfg, 'roi'), cfg.roi = []; end; - -% set the defaults per method -% ortho -if ~isfield(cfg, 'location'), cfg.location = 'auto'; end -if ~isfield(cfg, 'locationcoordinates'), cfg.locationcoordinates = 'head'; end -if ~isfield(cfg, 'crosshair'), cfg.crosshair = 'yes'; end -if ~isfield(cfg, 'colorbar'), cfg.colorbar = 'yes'; end -if ~isfield(cfg, 'axis'), cfg.axis = 'on'; end -if ~isfield(cfg, 'interactive'), cfg.interactive = 'no'; end -if ~isfield(cfg, 'queryrange'); cfg.queryrange = 3; end -if ~isfield(cfg, 'inputcoord'); cfg.inputcoord = []; end -if isfield(cfg, 'TTlookup'), - error('TTlookup is old; now specify cfg.atlas, see help!'); -end -% slice -if ~isfield(cfg, 'nslices'); cfg.nslices = 20; end -if ~isfield(cfg, 'slicedim'); cfg.slicedim = 3; end -if ~isfield(cfg, 'slicerange'); cfg.slicerange = 'auto'; end -% surface -if ~isfield(cfg, 'downsample'), cfg.downsample = 1; end -if ~isfield(cfg, 'surfdownsample'), cfg.surfdownsample = 1; end -if ~isfield(cfg, 'surffile'), cfg.surffile = 'single_subj_T1.mat'; end % use a triangulation that corresponds with the collin27 anatomical template in MNI coordinates -if ~isfield(cfg, 'surfinflated'), cfg.surfinflated = []; end -if ~isfield(cfg, 'sphereradius'), cfg.sphereradius = []; end -if ~isfield(cfg, 'distmat'), cfg.distmat = []; end -if ~isfield(cfg, 'camlight'), cfg.camlight = 'yes'; end -if ~isfield(cfg, 'renderer'), cfg.renderer = 'opengl'; end -if isequal(cfg.method,'surface') - if ~isfield(cfg, 'projmethod'), error('specify cfg.projmethod'); end -end - -% for backward compatibility -if strcmp(cfg.location, 'interactive') - cfg.location = 'auto'; - cfg.interactive = 'yes'; -end - -%%%%%%% -if ischar(data) - % read the anatomical MRI data from file - filename = data; - fprintf('reading MRI from file\n'); - data = read_mri(filename); -end - -% check if the input data is valid for this function -data = checkdata(data, 'datatype', 'volume', 'feedback', 'yes'); - -% select the functional and the mask parameter -cfg.funparameter = parameterselection(cfg.funparameter, data); -cfg.maskparameter = parameterselection(cfg.maskparameter, data); -% only a single parameter should be selected -try, cfg.funparameter = cfg.funparameter{1}; end -try, cfg.maskparameter = cfg.maskparameter{1}; end - -% downsample all volumes -tmpcfg = []; -tmpcfg.parameter = {cfg.funparameter, cfg.maskparameter, 'anatomy'}; -tmpcfg.downsample = cfg.downsample; -data = volumedownsample(tmpcfg, data); - -%%% make the local variables: -dim = data.dim; - -hasatlas = 0; -if ~isempty(cfg.atlas) - % initialize the atlas - hasatlas = 1; - [p, f, x] = fileparts(cfg.atlas); - fprintf(['reading ', f,' atlas coordinates and labels\n']); - atlas = prepare_atlas(cfg.atlas); -end - -hasroi = 0; -if ~isempty(cfg.roi) - if ~hasatlas - error('specify cfg.atlas which belongs to cfg.roi') - else - % get mask - hasroi = 1; - tmpcfg.roi = cfg.roi; - tmpcfg.atlas = cfg.atlas; - tmpcfg.inputcoord = cfg.inputcoord; - roi = volumelookup(tmpcfg,data); - end -end - -%%% anaparameter -if isequal(cfg.anaparameter,'anatomy') - if isfield(data, 'anatomy') - hasana = 1; - % convert integers to single precision float if neccessary - if isa(data.anatomy, 'uint8') || isa(data.anatomy, 'uint16') || isa(data.anatomy, 'int8') || isa(data.anatomy, 'int16') - fprintf('converting anatomy to double\n'); - ana = double(data.anatomy); - else - ana = data.anatomy; - end - else - warning('no anatomical volume present, not plotting anatomy\n') - hasana = 0; - end -elseif isempty(cfg.anaparameter); - hasana = 0; - fprintf('not plotting anatomy\n'); -else - warning('do not understand cfg.anaparameter, not plotting anatomy\n') - hasana = 0; -end - -%%% funparameter -% has fun? -if ~isempty(cfg.funparameter) - if issubfield(data, cfg.funparameter) - hasfun = 1; - fun = getsubfield(data, cfg.funparameter); - else - error('cfg.funparameter not found in data'); - end -else - hasfun = 0; - fprintf('no functional parameter\n'); -end - -% handle fun -if hasfun && issubfield(data, 'dimord') && strcmp(data.dimord(end-2:end),'rgb') - % treat functional data as rgb values - if any(fun(:)>1 | fun(:)<0) - %scale - tmpdim = size(fun); - nvox = prod(tmpdim(1:end-1)); - tmpfun = reshape(fun,[nvox tmpdim(end)]); - m1 = max(tmpfun,[],1); - m2 = min(tmpfun,[],1); - tmpfun = (tmpfun-m2(ones(nvox,1),:))./(m1(ones(nvox,1),:)-m2(ones(nvox,1),:)); - fun = reshape(tmpfun, tmpdim); - end - qi = 1; - hasfreq = 0; - hastime = 0; - - doimage = 1; - fcolmin = 0; - fcolmax = 1; -elseif hasfun - % determine scaling min and max (fcolmin fcolmax) and funcolormap - funmin = min(fun(:)); - funmax = max(fun(:)); - % smart lims: make from auto other string - if isequal(cfg.funcolorlim,'auto') - if sign(funmin)>-1 && sign(funmax)>-1 - cfg.funcolorlim = 'zeromax'; - elseif sign(funmin)<1 && sign(funmax)<1 - cfg.funcolorlim = 'minzero'; - else - cfg.funcolorlim = 'maxabs'; - end - end - if ischar(cfg.funcolorlim) - % limits are given as string - if isequal(cfg.funcolorlim,'maxabs') - fcolmin = -max(abs([funmin,funmax])); - fcolmax = max(abs([funmin,funmax])); - if isequal(cfg.funcolormap,'auto'); cfg.funcolormap = 'jet'; end; - elseif isequal(cfg.funcolorlim,'zeromax') - fcolmin = 0; - fcolmax = funmax; - if isequal(cfg.funcolormap,'auto'); cfg.funcolormap = 'hot'; end; - elseif isequal(cfg.funcolorlim,'minzero') - fcolmin = funmin; - fcolmax = 0; - if isequal(cfg.funcolormap,'auto'); cfg.funcolormap = 'cool'; end; - else - error('do not understand cfg.funcolorlim'); - end - else - % limits are numeric - fcolmin = cfg.funcolorlim(1); - fcolmax = cfg.funcolorlim(2); - % smart colormap - if isequal(cfg.funcolormap,'auto') - if sign(fcolmin) == -1 && sign(fcolmax) == 1 - cfg.funcolormap = 'jet'; - else - if fcolmin < 0 - cfg.funcolormap = 'cool'; - else - cfg.funcolormap = 'hot'; - end - end - end - end %if ischar - clear funmin funmax; - % ensure that the functional data is real - if ~isreal(fun) - fprintf('taking absolute value of complex data\n'); - fun = abs(fun); - end - - %what if fun is 4D? - if ndims(fun)>3, - if isfield(data, 'time') && isfield(data, 'freq'), - %data contains timefrequency representation - qi = [1 1]; - hasfreq = 1; - hastime = 1; - elseif isfield(data, 'time') - %data contains evoked field - qi = 1; - hasfreq = 0; - hastime = 1; - elseif isfield(data, 'freq') - %data contains frequency spectra - qi = 1; - hasfreq = 1; - hastime = 0; - end - else - %do nothing - qi = 1; - hasfreq = 0; - hastime = 0; - end - - doimage = 0; -else - qi = 1; - hasfreq = 0; - hastime = 0; - - doimage = 0; -end % handle fun - -%%% maskparameter -% has mask? -if ~isempty(cfg.maskparameter) - if issubfield(data, cfg.maskparameter) - if ~hasfun - error('you can not have a mask without functional data') - else - hasmsk = 1; - msk = getsubfield(data, cfg.maskparameter); - if islogical(msk) %otherwise sign() not posible - msk = double(msk); - end - end - else - error('cfg.maskparameter not found in data'); - end -else - hasmsk = 0; - fprintf('no masking parameter\n'); -end -% handle mask -if hasmsk - % determine scaling and opacitymap - mskmin = min(msk(:)); - mskmax = max(msk(:)); - % determine the opacity limits and the opacity map - % smart lims: make from auto other string, or equal to funcolorlim if funparameter == maskparameter - if isequal(cfg.opacitylim,'auto') - if isequal(cfg.funparameter,cfg.maskparameter) - cfg.opacitylim = cfg.funcolorlim; - else - if sign(mskmin)>-1 && sign(mskmax)>-1 - cfg.opacitylim = 'zeromax'; - elseif sign(mskmin)<1 && sign(mskmax)<1 - cfg.opacitylim = 'minzero'; - else - cfg.opacitylim = 'maxabs'; - end - end - end - if ischar(cfg.opacitylim) - % limits are given as string - switch cfg.opacitylim - case 'zeromax' - opacmin = 0; - opacmax = mskmax; - if isequal(cfg.opacitymap,'auto'), cfg.opacitymap = 'rampup'; end; - case 'minzero' - opacmin = mskmin; - opacmax = 0; - if isequal(cfg.opacitymap,'auto'), cfg.opacitymap = 'rampdown'; end; - case 'maxabs' - opacmin = -max(abs([mskmin, mskmax])); - opacmax = max(abs([mskmin, mskmax])); - if isequal(cfg.opacitymap,'auto'), cfg.opacitymap = 'vdown'; end; - otherwise - error('incorrect specification of cfg.opacitylim'); - end % switch opacitylim - else - % limits are numeric - opacmin = cfg.opacitylim(1); - opacmax = cfg.opacitylim(2); - if isequal(cfg.opacitymap,'auto') - if sign(opacmin)>-1 && sign(opacmax)>-1 - cfg.opacitymap = 'rampup'; - elseif sign(opacmin)<1 && sign(opacmax)<1 - cfg.opacitymap = 'rampdown'; - else - cfg.opacitymap = 'vdown'; - end - end - end % handling opacitylim and opacitymap - clear mskmin mskmax; -end - -% prevent outside fun from being plotted in slice and orthoplot -if hasfun && isfield(data,'inside') && ~hasmsk && ~isequal(cfg.method,'surface') - hasmsk = 1; - msk = zeros(dim); - cfg.opacitymap = 'rampup'; - opacmin = 0; - opacmax = 1; - % make intelligent mask - if hasana - msk(data.inside) = 0.5; %so anatomy is visible - else - msk(data.inside) = 1; - end; -end; - -% if region of interest is specified, mask everything besides roi -if hasfun && hasroi && ~hasmsk - hasmsk = 1; - msk = roi; - cfg.opacitymap = 'rampup'; - opacmin = 0; - opacmax = 1; -elseif hasfun && hasroi && hasmsk - msk = roi .* msk; -elseif hasroi - error('you can not have a roi without functional data') -end; - -%%% set color and opacity mapping for this figure -if hasfun - cfg.funcolormap = colormap(cfg.funcolormap); - colormap(cfg.funcolormap); -end -if hasmsk - cfg.opacitymap = alphamap(cfg.opacitymap); - alphamap(cfg.opacitymap); -end - -%%% determine what has to be plotted, depends on method -if isequal(cfg.method,'ortho') - if ~ischar(cfg.location) - if strcmp(cfg.locationcoordinates, 'head') - % convert the headcoordinates location into voxel coordinates - loc = inv(data.transform) * [cfg.location(:); 1]; - loc = round(loc(1:3)); - elseif strcmp(cfg.locationcoordinates, 'voxel') - % the location is already in voxel coordinates - loc = round(cfg.location(1:3)); - else - error('you should specify cfg.locationcoordinates'); - end - else - if isequal(cfg.location,'auto') - if hasfun - if isequal(cfg.funcolorlim,'maxabs'); - loc = 'max'; - elseif isequal(cfg.funcolorlim, 'zeromax'); - loc = 'max'; - elseif isequal(cfg.funcolorlim, 'minzero'); - loc = 'min'; - else %if numerical - loc = 'max'; - end - else - loc = 'center'; - end; - else - loc = cfg.location; - end - end - - % determine the initial intersection of the cursor (xi yi zi) - if ischar(loc) && strcmp(loc, 'min') - if isempty(cfg.funparameter) - error('cfg.location is min, but no functional parameter specified'); - end - [minval, minindx] = min(fun(:)); - [xi, yi, zi] = ind2sub(dim, minindx); - elseif ischar(loc) && strcmp(loc, 'max') - if isempty(cfg.funparameter) - error('cfg.location is max, but no functional parameter specified'); - end - [maxval, maxindx] = max(fun(:)); - [xi, yi, zi] = ind2sub(dim, maxindx); - elseif ischar(loc) && strcmp(loc, 'center') - xi = round(dim(1)/2); - yi = round(dim(2)/2); - zi = round(dim(3)/2); - elseif ~ischar(loc) - % using nearest instead of round ensures that the position remains within the volume - xi = nearest(1:dim(1), loc(1)); - yi = nearest(1:dim(2), loc(2)); - zi = nearest(1:dim(3), loc(3)); - end - - %% do the actual plotting %% - nas = []; - lpa = []; - rpa = []; - interactive_flag = 1; % it happens at least once - while(interactive_flag) - interactive_flag = strcmp(cfg.interactive, 'yes'); - - xi = round(xi); xi = max(xi, 1); xi = min(xi, dim(1)); - yi = round(yi); yi = max(yi, 1); yi = min(yi, dim(2)); - zi = round(zi); zi = max(zi, 1); zi = min(zi, dim(3)); - - if interactive_flag - fprintf('\n'); - fprintf('click with mouse button to reposition the cursor\n'); - fprintf('press n/l/r on keyboard to record a fiducial position\n'); - fprintf('press q on keyboard to quit interactive mode\n'); - end - - ijk = [xi yi zi 1]'; - xyz = data.transform * ijk; - if hasfun && ~hasatlas - val = fun(xi, yi, zi, qi); - if ~hasfreq && ~hastime, - fprintf('voxel %d, indices [%d %d %d], location [%.1f %.1f %.1f], value %f\n', sub2ind(dim, xi, yi, zi), ijk(1:3), xyz(1:3), val); - elseif hastime && hasfreq, - val = fun(xi, yi, zi, qi(1), qi(2)); - fprintf('voxel %d, indices [%d %d %d %d %d], %s coordinates [%.1f %.1f %.1f %.1f %.1f], value %f\n', [sub2ind(dim(1:3), xi, yi, zi), ijk(1:3)', qi], cfg.inputcoord, [xyz(1:3)' data.freq(qi(1)) data.time(qi(2))], val); - elseif hastime, - fprintf('voxel %d, indices [%d %d %d %d], %s coordinates [%.1f %.1f %.1f %.1f], value %f\n', [sub2ind(dim(1:3), xi, yi, zi), ijk(1:3)', qi], cfg.inputcoord, [xyz(1:3)', data.time(qi(1))], val); - elseif hasfreq, - fprintf('voxel %d, indices [%d %d %d %d], %s coordinates [%.1f %.1f %.1f %.1f], value %f\n', [sub2ind(dim(1:3), xi, yi, zi), ijk(1:3)', qi], cfg.inputcoord, [xyz(1:3)', data.freq(qi)], val); - end - elseif hasfun && hasatlas - val = fun(xi, yi, zi, qi); - fprintf('voxel %d, indices [%d %d %d], %s coordinates [%.1f %.1f %.1f], value %f\n', sub2ind(dim, xi, yi, zi), ijk(1:3), cfg.inputcoord, xyz(1:3), val); - elseif ~hasfun && ~hasatlas - fprintf('voxel %d, indices [%d %d %d], location [%.1f %.1f %.1f]\n', sub2ind(dim, xi, yi, zi), ijk(1:3), xyz(1:3)); - elseif ~hasfun && hasatlas - fprintf('voxel %d, indices [%d %d %d], %s coordinates [%.1f %.1f %.1f]\n', sub2ind(dim, xi, yi, zi), ijk(1:3), cfg.inputcoord, xyz(1:3)); - end - - if hasatlas - % determine the anatomical label of the current position - lab = atlas_lookup(atlas, (xyz(1:3)), 'inputcoord', cfg.inputcoord, 'queryrange', cfg.queryrange); - if isempty(lab) - fprintf([f,' labels: not found\n']); - else - fprintf([f,' labels: ']) - fprintf('%s', lab{1}); - for i=2:length(lab) - fprintf(', %s', lab{i}); - end - fprintf('\n'); - end - end - - % make vols and scales, containes volumes to be plotted (fun, ana, msk) - vols = {}; - if hasana; vols{1} = ana; scales{1} = []; end; % needed when only plotting ana - if hasfun; vols{2} = fun; scales{2} = [fcolmin fcolmax]; end; - if hasmsk; vols{3} = msk; scales{3} = [opacmin opacmax]; end; - - if isempty(vols) - % this seems to be a problem that people often have - error('no anatomy is present and no functional data is selected, please check your cfg.funparameter'); - end - - h1 = subplot(2,2,1); - [vols2D] = handle_ortho(vols, [xi yi zi qi], 2, dim, doimage); - plot2D(vols2D, scales, doimage); - xlabel('i'); ylabel('k'); axis(cfg.axis); - if strcmp(cfg.crosshair, 'yes'), crosshair([xi zi]); end - - h2 = subplot(2,2,2); - [vols2D] = handle_ortho(vols, [xi yi zi qi], 1, dim, doimage); - plot2D(vols2D, scales, doimage); - xlabel('j'); ylabel('k'); axis(cfg.axis); - if strcmp(cfg.crosshair, 'yes'), crosshair([yi zi]); end - - h3 = subplot(2,2,3); - [vols2D] = handle_ortho(vols, [xi yi zi qi], 3, dim, doimage); - plot2D(vols2D, scales, doimage); - xlabel('i'); ylabel('j'); axis(cfg.axis); - if strcmp(cfg.crosshair, 'yes'), crosshair([xi yi]); end - - if hasfreq && hastime && hasfun, - h=subplot(2,2,4); - %uimagesc(data.time, data.freq, squeeze(vols{2}(xi,yi,zi,:,:))');axis xy; - tmpdat = double(squeeze(vols{2}(xi,yi,zi,:,:))); - pcolor(double(data.time), double(data.freq), double(squeeze(vols{2}(xi,yi,zi,:,:)))); - shading('interp'); - xlabel('time'); ylabel('freq'); - caxis([-1 1].*max(abs(caxis))); - colorbar; - %caxis([fcolmin fcolmax]); - %set(gca, 'Visible', 'off'); - elseif hasfreq && hasfun, - subplot(2,2,4); - plot(data.freq, squeeze(vols{2}(xi,yi,zi,:))); xlabel('freq'); - axis([data.freq(1) data.freq(end) scales{2}]); - elseif hastime && hasfun, - subplot(2,2,4); - plot(data.time, squeeze(vols{2}(xi,yi,zi,:))); xlabel('time'); - axis([data.time(1) data.time(end) scales{2}]); - elseif strcmp(cfg.colorbar, 'yes'), - if hasfun - % vectorcolorbar = linspace(fcolmin, fcolmax,length(cfg.funcolormap)); - % imagesc(vectorcolorbar,1,vectorcolorbar);colormap(cfg.funcolormap); - subplot(2,2,4); - % use a normal Matlab colorbar, attach it to the invisible 4th subplot - caxis([fcolmin fcolmax]); - hc = colorbar; - set(hc, 'YLim', [fcolmin fcolmax]); - set(gca, 'Visible', 'off'); - else - warning('no colorbar possible without functional data') - end - end - - set(gcf, 'renderer', cfg.renderer); % ensure that this is done in interactive mode - drawnow; - - if interactive_flag - try - [d1, d2, key] = ginput(1); - catch - % this happens if the figure is closed - key='q'; - end - - if isempty(key) - % this happens if you press the apple key - key = ''; - end - switch key - case '' - % do nothing - case 'q' - break; - case 'l' - lpa = [xi yi zi]; - case 'r' - rpa = [xi yi zi]; - case 'n' - nas = [xi yi zi]; - case {'i' 'j''k' 'm'} - % update the view to a new position - if l1=='i' && l2=='k' && key=='i', zi = zi+1; - elseif l1=='i' && l2=='k' && key=='j', xi = xi-1; - elseif l1=='i' && l2=='k' && key=='k', xi = xi+1; - elseif l1=='i' && l2=='k' && key=='m', zi = zi-1; - elseif l1=='i' && l2=='j' && key=='i', yi = yi+1; - elseif l1=='i' && l2=='j' && key=='j', xi = xi-1; - elseif l1=='i' && l2=='j' && key=='k', xi = xi+1; - elseif l1=='i' && l2=='j' && key=='m', yi = yi-1; - elseif l1=='j' && l2=='k' && key=='i', zi = zi+1; - elseif l1=='j' && l2=='k' && key=='j', yi = yi-1; - elseif l1=='j' && l2=='k' && key=='k', yi = yi+1; - elseif l1=='j' && l2=='k' && key=='m', zi = zi-1; - end; - otherwise - % update the view to a new position - l1 = get(get(gca, 'xlabel'), 'string'); - l2 = get(get(gca, 'ylabel'), 'string'); - switch l1, - case 'i' - xi = d1; - case 'j' - yi = d1; - case 'k' - zi = d1; - case 'freq' - qi = nearest(data.freq,d1); - case 'time' - qi = nearest(data.time,d1); - end - switch l2, - case 'i' - xi = d2; - case 'j' - yi = d2; - case 'k' - zi = d2; - case 'freq' - qi = [nearest(data.freq,d2) qi(1)]; - end - end % switch key - end % if interactive_flag - if ~isempty(nas), fprintf('nas = [%f %f %f]\n', nas); cfg.fiducial.nas = nas; else fprintf('nas = undefined\n'); end - if ~isempty(lpa), fprintf('lpa = [%f %f %f]\n', lpa); cfg.fiducial.lpa = lpa; else fprintf('lpa = undefined\n'); end - if ~isempty(rpa), fprintf('rpa = [%f %f %f]\n', rpa); cfg.fiducial.rpa = rpa; else fprintf('rpa = undefined\n'); end - end % while interactive_flag - -elseif isequal(cfg.method,'glassbrain') - tmpcfg = []; - tmpcfg.funparameter = cfg.funparameter; - tmpcfg.method = 'ortho'; - tmpcfg.location = [1 1 1]; - tmpcfg.funcolorlim = cfg.funcolorlim; - tmpcfg.funcolormap = cfg.funcolormap; - tmpcfg.opacitylim = cfg.opacitylim; - tmpcfg.locationcoordinates = 'voxel'; - tmpcfg.maskparameter = 'inside'; - tmpcfg.axis = cfg.axis; - tmpcfg.renderer = cfg.renderer; - if hasfun, - fun = getsubfield(data, cfg.funparameter); - fun(1,:,:) = max(fun, [], 1); - fun(:,1,:) = max(fun, [], 2); - fun(:,:,1) = max(fun, [], 3); - data = setsubfield(data, cfg.funparameter, fun); - end - - if hasana, - ana = getsubfield(data, 'anatomy'); - %ana(1,:,:) = max(ana, [], 1); - %ana(:,1,:) = max(ana, [], 2); - %ana(:,:,1) = max(ana, [], 3); - data = setsubfield(data, 'anatomy', ana); - end - - if hasmsk, - msk = getsubfield(data, 'inside'); - msk(1,:,:) = squeeze(fun(1,:,:))>0 & imfill(abs(squeeze(ana(1,:,:))-1))>0; - msk(:,1,:) = squeeze(fun(:,1,:))>0 & imfill(abs(squeeze(ana(:,1,:))-1))>0; - msk(:,:,1) = squeeze(fun(:,:,1))>0 & imfill(abs(ana(:,:,1)-1))>0; - data = setsubfield(data, 'inside', msk); - end - - sourceplot(tmpcfg, data); - -elseif isequal(cfg.method,'surface') - - % read the triangulated cortical surface from file - tmp = load(cfg.surffile, 'bnd'); - surf = tmp.bnd; - if isfield(surf, 'transform'), - % compute the surface vertices in head coordinates - surf.pnt = warp_apply(surf.transform, surf.pnt); - end - - % downsample the cortical surface - if cfg.surfdownsample > 1 - if ~isempty(cfg.surfinflated) - error('downsampling the surface is not possible in combination with an inflated surface'); - end - fprintf('downsampling surface from %d vertices\n', size(surf.pnt,1)); - [surf.tri, surf.pnt] = reducepatch(surf.tri, surf.pnt, 1/cfg.surfdownsample); - end - - % these are required - if ~isfield(data, 'inside') - data.inside = true(dim); - end - - fprintf('%d voxels in functional data\n', prod(dim)); - fprintf('%d vertices in cortical surface\n', size(surf.pnt,1)); - - if hasfun - [interpmat, cfg.distmat] = interp_gridded(data.transform, fun, surf.pnt, 'projmethod', cfg.projmethod, 'distmat', cfg.distmat, 'sphereradius', cfg.sphereradius, 'inside', data.inside); - % interpolate the functional data - val = interpmat * fun(data.inside(:)); - if hasmsk - % also interpolate the opacity mask - maskval = interpmat * msk(data.inside(:)); - end - end - - if ~isempty(cfg.surfinflated) - % read the inflated triangulated cortical surface from file - tmp = load(cfg.surfinflated, 'bnd'); - surf = tmp.bnd; - if isfield(surf, 'transform'), - % compute the surface vertices in head coordinates - surf.pnt = warp_apply(surf.transform, surf.pnt); - end - end - - %------do the plotting - cortex_light = [0.781 0.762 0.664]; - cortex_dark = [0.781 0.762 0.664]/2; - if isfield(surf, 'curv') - % the curvature determines the color of gyri and sulci - color = surf.curv(:) * cortex_light + (1-surf.curv(:)) * cortex_dark; - else - color = repmat(cortex_light, size(surf.pnt,1), 1); - end - - h1 = patch('Vertices', surf.pnt, 'Faces', surf.tri, 'FaceVertexCData', color , 'FaceColor', 'interp'); - set(h1, 'EdgeColor', 'none'); - axis off; - axis vis3d; - axis equal; - - h2 = patch('Vertices', surf.pnt, 'Faces', surf.tri, 'FaceVertexCData', val , 'FaceColor', 'interp'); - set(h2, 'EdgeColor', 'none'); - if hasmsk - set(h2, 'FaceVertexAlphaData', maskval); - set(h2, 'FaceAlpha', 'interp'); - set(h2, 'AlphaDataMapping', 'scaled'); - alim(gca, [opacmin opacmax]); - end - caxis(gca,[fcolmin fcolmax]); - - lighting gouraud - if hasfun - colormap(cfg.funcolormap); - end - if hasmsk - alphamap(cfg.opacitymap); - end - - if strcmp(cfg.camlight,'yes') - camlight - end - - if strcmp(cfg.colorbar, 'yes'), - if hasfun - % use a normal Matlab colorbar - hc = colorbar; - set(hc, 'YLim', [fcolmin fcolmax]); - else - warning('no colorbar possible without functional data') - end - end - -elseif isequal(cfg.method,'slice') - % white BG => mskana - - %% TODO: HERE THE FUNCTION THAT MAKES TO SLICE DIMENSION ALWAYS THE THIRD - %% DIMENSION, AND ALSO KEEP TRANSFORMATION MATRIX UP TO DATE - % zoiets - %if hasana; ana = shiftdim(ana,cfg.slicedim-1); end; - %if hasfun; fun = shiftdim(fun,cfg.slicedim-1); end; - %if hasmsk; msk = shiftdim(msk,cfg.slicedim-1); end; - %%%%% select slices - if ~ischar(cfg.slicerange) - ind_fslice = cfg.slicerange(1); - ind_lslice = cfg.slicerange(2); - elseif isequal(cfg.slicerange, 'auto') - if hasfun %default - if isfield(data,'inside') - ind_fslice = min(find(max(max(data.inside,[],1),[],2))); - ind_lslice = max(find(max(max(data.inside,[],1),[],2))); - else - ind_fslice = min(find(~isnan(max(max(fun,[],1),[],2)))); - ind_lslice = max(find(~isnan(max(max(fun,[],1),[],2)))); - end - elseif hasana %if only ana, no fun - ind_fslice = min(find(max(max(ana,[],1),[],2))); - ind_lslice = max(find(max(max(ana,[],1),[],2))); - else - error('no functional parameter and no anatomical parameter, can not plot'); - end - else - error('do not understand cfg.slicerange'); - end - ind_allslice = linspace(ind_fslice,ind_lslice,cfg.nslices); - ind_allslice = round(ind_allslice); - % make new ana, fun, msk, mskana with only the slices that will be plotted (slice dim is always third dimension) - if hasana; new_ana = ana(:,:,ind_allslice); clear ana; ana=new_ana; clear new_ana; end; - if hasfun; new_fun = fun(:,:,ind_allslice); clear fun; fun=new_fun; clear new_fun; end; - if hasmsk; new_msk = msk(:,:,ind_allslice); clear msk; msk=new_msk; clear new_msk; end; - %if hasmskana; new_mskana = mskana(:,:,ind_allslice); clear mskana; mskana=new_mskana; clear new_mskana; end; - - % update the dimensions of the volume - if hasana; dim=size(ana); else dim=size(fun); end; - - %%%%% make "quilts", that contain all slices on 2D patched sheet - % Number of patches along sides of Quilt (M and N) - % Size (in voxels) of side of patches of Quilt (m and n) - m = dim(1); - n = dim(2); - M = ceil(sqrt(dim(3))); - N = ceil(sqrt(dim(3))); - num_patch = N*M; - if cfg.slicedim~=3 - error('only supported for slicedim=3'); - end - num_slice = (dim(cfg.slicedim)); - num_empt = num_patch-num_slice; - % put empty slides on ana, fun, msk, mskana to fill Quilt up - if hasana; ana(:,:,end+1:num_patch)=0; end; - if hasfun; fun(:,:,end+1:num_patch)=0; end; - if hasmsk; msk(:,:,end+1:num_patch)=0; end; - %if hasmskana; mskana(:,:,end:num_patch)=0; end; - % put the slices in the quilt - for iSlice = 1:num_slice - xbeg = floor((iSlice-1)./M); - ybeg = mod(iSlice-1, M); - if hasana - quilt_ana(ybeg.*m+1:(ybeg+1).*m, xbeg.*n+1:(xbeg+1).*n)=squeeze(ana(:,:,iSlice)); - end - if hasfun - quilt_fun(ybeg.*m+1:(ybeg+1).*m, xbeg.*n+1:(xbeg+1).*n)=squeeze(fun(:,:,iSlice)); - end - if hasmsk - quilt_msk(ybeg.*m+1:(ybeg+1).*m, xbeg.*n+1:(xbeg+1).*n)=squeeze(msk(:,:,iSlice)); - end - % if hasmskana - % quilt_mskana(ybeg.*m+1:(ybeg+1).*m, xbeg.*n+1:(xbeg+1).*n)=squeeze(mskana(:,:,iSlice)); - % end - end - % make vols and scales, containes volumes to be plotted (fun, ana, msk) %added ingnie - if hasana; vols2D{1} = quilt_ana; scales{1} = []; end; % needed when only plotting ana - if hasfun; vols2D{2} = quilt_fun; scales{2} = [fcolmin fcolmax]; end; - if hasmsk; vols2D{3} = quilt_msk; scales{3} = [opacmin opacmax]; end; - plot2D(vols2D, scales, doimage); - axis off - if strcmp(cfg.colorbar, 'yes'), - if hasfun - % use a normal Matlab coorbar - hc = colorbar; - set(hc, 'YLim', [fcolmin fcolmax]); - else - warning('no colorbar possible without functional data') - end - end - -end - -title(cfg.title); -set(gcf, 'renderer', cfg.renderer); - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% handle_ortho makes an overlay of 3D anatomical, functional and probability -% volumes. The three volumes must be scaled between 0 and 1. -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [vols2D] = handle_ortho(vols, indx, slicedir, dim, doimage) - -% put 2Dvolumes in fun, ana and msk -if length(vols)>=1 && isempty(vols{1}); hasana=0; else ana=vols{1}; hasana=1; end; -if length(vols)>=2 - if isempty(vols{2}); hasfun=0; else fun=vols{2}; hasfun=1; end; -else hasfun=0; end -if length(vols)>=3 - if isempty(vols{3}); hasmsk=0; else msk=vols{3}; hasmsk=1; end; -else hasmsk=0; end - -% select the indices of the intersection -xi = indx(1); -yi = indx(2); -zi = indx(3); -qi = indx(4); -if length(indx)>4, - qi(2) = indx(5); -else - qi(2) = 1; -end - -% select the slice to plot -if slicedir==1 - yi = 1:dim(2); - zi = 1:dim(3); -elseif slicedir==2 - xi = 1:dim(1); - zi = 1:dim(3); -elseif slicedir==3 - xi = 1:dim(1); - yi = 1:dim(2); -end - -% cut out the slice of interest -if hasana; ana = squeeze(ana(xi,yi,zi)); end; -if hasfun; - if doimage - fun = squeeze(fun(xi,yi,zi,:)); - else - fun = squeeze(fun(xi,yi,zi,qi(1),qi(2))); - end -end -if hasmsk && length(size(msk))>3 - msk = squeeze(msk(xi,yi,zi,qi(1),qi(2))); -elseif hasmsk - msk = squeeze(msk(xi,yi,zi)); -end; - -%put fun, ana and msk in vols2D -if hasana; vols2D{1} = ana; end; -if hasfun; vols2D{2} = fun; end; -if hasmsk; vols2D{3} = msk; end; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% plot2D plots a two dimensional plot, used in ortho and slice -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function plot2D(vols2D, scales, doimage); -cla; -% put 2D volumes in fun, ana and msk -hasana = length(vols2D)>0 && ~isempty(vols2D{1}); -hasfun = length(vols2D)>1 && ~isempty(vols2D{2}); -hasmsk = length(vols2D)>2 && ~isempty(vols2D{3}); - -% the transpose is needed for displaying the matrix using the Matlab image() function -if hasana; ana = vols2D{1}'; end; -if hasfun && ~doimage; fun = vols2D{2}'; end; -if hasfun && doimage; fun = permute(vols2D{2},[2 1 3]); end; -if hasmsk; msk = vols2D{3}'; end; - - -if hasana - % scale anatomy between 0 and 1 - fprintf('scaling anatomy\n'); - amin = min(ana(:)); - amax = max(ana(:)); - ana = (ana-amin)./(amax-amin); - clear amin amax; - % convert anatomy into RGB values - ana = cat(3, ana, ana, ana); - ha = imagesc(ana); -end -hold on - -if hasfun - - if doimage - hf = image(fun); - else - hf = imagesc(fun); - caxis(scales{2}); - % apply the opacity mask to the functional data - if hasmsk - % set the opacity - set(hf, 'AlphaData', msk) - set(hf, 'AlphaDataMapping', 'scaled') - alim(scales{3}); - elseif hasana - set(hf, 'AlphaData', 0.5) - end - - end -end - -axis equal -axis tight -axis xy - diff --git a/external/fieldtrip/private/sourceplot_old.m b/external/fieldtrip/private/sourceplot_old.m deleted file mode 100644 index 2f0fdd2..0000000 --- a/external/fieldtrip/private/sourceplot_old.m +++ /dev/null @@ -1,678 +0,0 @@ -function sourceplot(cfg, interp) - -% SOURCEPLOT displays three orthogonal slices of anatomical and/or functional -% volume data. If an anatomical volume is present in the input, it will -% always be plotted. The source parameter that is specified in the -% configuration will be plotted as an overlay on the anatomy, where the -% mask parameter can be used to determine the opacity. -% -% Use as -% sourceplot(cfg, functional) -% where the functional data is the output of SOURCEANALYSIS, -% SOURCESTATISTICS, SOURCEINTERPOLATE or NORMALISEVOLUME and -% the configuration contains any of the following fields -% cfg.location = 'min', 'max', 'interactive' or [x y z] -% cfg.locationcoordinates = 'head' or 'voxel' (default = 'head') -% cfg.funparameter = string with the functional parameter of interest -% cfg.maskparameter = string with an optional mask parameter -% cfg.maskcolmin = mask value mapped to the lowest opacity, i.e. completely transparent (default ='auto') -% cfg.maskcolmax = mask value mapped to the highest opacity, i.e. non-transparent (default = 'auto') -% cfg.colmin = source value mapped to the lowest color (default = 'auto') -% cfg.colmax = source value mapped to the highest color (default = 'auto') -% -% See also SOURCEANALYSIS, SOURCESTATISTICS, SOURCEINTERPOLATE - -% Undocumented local options: -% cfg.TTlookup = 'yes' or 'no' (default) -% cfg.TTqueryrange = number (default 3) -% cfg.colormap -% cfg.axis = 'on' (default) or 'off' -% cfg.crosshair = 'on' (default) or 'off' -% cfg.colorbar = 'on' (default) or 'off' -% cfg.location = 'maxproject', creates a glass-brain representation with an outline of a template brain only works with 1mm resolution normalised images! ask JM - -% Copyright (C) 2003, Robert Oostenveld -% -% $Log: sourceplot_old.m,v $ -% Revision 1.2 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.1 2007/02/08 12:34:26 roboos -% this is a copy of the sourcelot function just prior to Ingrid rewriting it -% -% Revision 1.38 2006/09/18 14:04:45 jansch -% implemented maxproject as an undocumented option for cfg.location. This gives -% a 'glass-brain' projection of the functional data -% -% Revision 1.37 2006/07/13 08:48:46 ingnie -% fixed typo's in documentation -% -% Revision 1.36 2006/05/31 07:07:15 roboos -% updated documentation -% -% Revision 1.35 2006/04/20 09:58:34 roboos -% updated documentation -% -% Revision 1.34 2006/03/29 16:14:44 roboos -% do a cla (clear axes) in each subplot when plotting interactive (thanks to Vladimir) -% -% Revision 1.33 2006/03/07 08:33:29 roboos -% removed debugging keyboard statement -% -% Revision 1.32 2006/03/07 08:32:42 roboos -% removed mm units from the print statement about the location on screen -% removed the cfg.flipdim option, it invalidated the reported position -% -% Revision 1.31 2006/03/02 13:21:25 jansch -% downgraded version 1.30 to version 1.27 since the newer version was buggy -% -% Revision 1.27 2006/01/30 17:11:04 roboos -% added cfg.flipdim option, flips the 3rd dimension -% -% Revision 1.26 2006/01/25 11:01:04 roboos -% add xgrid/ygrid/zgrid in voxel coordinates -% -% Revision 1.25 2006/01/24 21:26:09 roboos -% fixed tmpcfg.parameter for downsample -% moved parameterselection up in the code -% -% Revision 1.24 2006/01/24 14:32:23 roboos -% list cfg.TTqueryrange and cfg.TTlookup as undocumented options (not in main help, but just below it) -% -% Revision 1.23 2006/01/05 13:35:41 roboos -% Changed parameterselection subfunction, select the first element -% from the cell-array. -% Do not add xgrid/ygrid/zgrid or transform, call the private function -% grid2transform to ensure that the volume is described using the -% homogenous coordinate transformation matrix. -% Always pass the volume to the downsamplevolume function, that -% function is smart enough to notice cfg.downsample=1. -% -% Revision 1.22 2005/10/14 15:48:01 roboos -% added support for cfg.maskcolmin and cfg.maskcolmax, similar to sliceinterp -% -% Revision 1.21 2005/08/19 16:57:48 roboos -% changed the default opacity to 0.5 -% use the new subfunction parameterselection() for selecting the functional and mask volume -% -% Revision 1.20 2005/08/17 19:22:09 roboos -% removed obsolete reference to cfg.TTmask -% -% Revision 1.19 2005/07/29 13:23:10 roboos -% renamed searchrange to queryrange -% added coordinate translation using mni2tal() -% -% Revision 1.18 2005/07/20 15:32:28 roboos -% added experimental code to print the anatomical labels from the TT atlas -% -% Revision 1.17 2005/06/17 10:59:38 roboos -% add x/y/zgrid if not present in input data -% -% Revision 1.16 2005/05/17 17:50:38 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.15 2005/03/07 17:09:21 roboos -% added a custom colorbar for the functional data in the 4th subplot (thanks to Markus) -% -% Revision 1.14 2005/03/07 15:07:59 roboos -% added option cfg.locationcoordinates, can be 'head' (default) or 'voxel' -% -% Revision 1.13 2005/03/03 10:38:26 roboos -% changed axes labels from x/y/z into i/j/k, since axes correspond with voxel indices -% -% Revision 1.12 2005/02/28 17:58:59 roboos -% fixed bug in selection of empty funparameter -% -% Revision 1.11 2005/02/21 12:29:08 roboos -% removed incorrect inv() from interp.transform when interactive plotting -% -% Revision 1.10 2005/02/11 17:59:01 roboos -% fixed bug in computation of headcoordinates (removed inv) -% -% Revision 1.9 2005/02/11 14:49:11 roboos -% moved clipping and scaling from subfunction to mainfunction -% implemented cfg.downsample -% -% Revision 1.8 2005/02/11 13:28:53 roboos -% completely new implementation, basically based upon misc/volplot and on Nienke's singleplot -% -% Revision 1.7 2004/08/26 10:48:25 roboos -% modified to make it consistent again with the new volume (source+mri) structure -% removed dependency on warp3d, implemented homogenous transform directly - -fieldtripdefs - -% sometimes it is desirable to specify the cfg as a cell array -if iscell(cfg) - var = cfg(1:2:length(cfg)); % select the odd elements - val = cfg(2:2:length(cfg)); % select the even elements - % convert the configuration to a structure - cfg = cell2struct(val, var, 2); -end - -% set the defaults -if ~isfield(cfg, 'location'), cfg.location = 'interactive'; end -if ~isfield(cfg, 'locationcoordinates'), cfg.locationcoordinates = 'head'; end -if ~isfield(cfg, 'funparameter'), cfg.funparameter = []; end -if ~isfield(cfg, 'maskparameter'), cfg.maskparameter = []; end -if ~isfield(cfg, 'colormap'), cfg.colormap = 'jet'; end -if ~isfield(cfg, 'downsample'), cfg.downsample = 1; end -if ~isfield(cfg, 'maskcolmin'), cfg.maskcolmin = 'auto'; end -if ~isfield(cfg, 'maskcolmax'), cfg.maskcolmax = 'auto'; end -if ~isfield(cfg, 'colmin'), cfg.colmin = 'auto'; end -if ~isfield(cfg, 'colmax'), cfg.colmax = 'auto'; end -if ~isfield(cfg, 'axis'), cfg.axis = 'on'; end -if ~isfield(cfg, 'crosshair'), cfg.crosshair = 'on'; end -if ~isfield(cfg, 'colorbar'), cfg.colorbar = 'on'; end - -% experimental options -if ~isfield(cfg, 'TTlookup'); cfg.TTlookup = 'no'; end -if ~isfield(cfg, 'TTqueryrange'); cfg.TTqueryrange = 3; end - -if isfield(cfg, 'flipdim') - % FIXME the flipdim should be implemented cleanly, i.e. the volume - % including the transformation should be flipped. For the moment I have - % removed the flipdim code from this function. - error('cfg.flipdim invalidates the location and voxel coordinates that are printed on screen\n'); -end - -if strcmp(cfg.TTlookup, 'yes') - fprintf('reading Talairach-Tournoux atlas coordinates and labels\n'); - tlrc = TTatlas_init; -end - -if isstr(interp) - % read the anatomical MRI data from file - filename = interp; - fprintf('reading MRI from file\n'); - interp = read_fcdc_mri(filename); -end - -% collect the volumes that will be plotted -ana = []; -fun = []; -msk = []; - -% convert the coordinates along the axes (i.e. xgrid/ygrid/zgrid) into a homogenous transformation matrix -interp = grid2transform(interp); - -% select the functional and the mask parameter -cfg.funparameter = parameterselection(cfg.funparameter, interp); -cfg.maskparameter = parameterselection(cfg.maskparameter, interp); -% only a single parameter should be selected -try, cfg.funparameter = cfg.funparameter{1}; end -try, cfg.maskparameter = cfg.maskparameter{1}; end - -% downsample all volumes -tmpcfg = []; -tmpcfg.parameter = {cfg.funparameter, cfg.maskparameter, 'anatomy'}; -tmpcfg.downsample = cfg.downsample; -interp = volumedownsample(tmpcfg, interp); -interp.xgrid = 1:interp.dim(1); -interp.ygrid = 1:interp.dim(2); -interp.zgrid = 1:interp.dim(3); - -if isfield(interp, 'anatomy') - hasana = 1; - mri8 = isa(interp.anatomy, 'uint8'); - mri16 = isa(interp.anatomy, 'uint16'); - % convert integers to single precision float if neccessary - if mri8 || mri16 - fprintf('converting anatomy to double\n'); - ana = double(interp.anatomy); - else - ana = interp.anatomy; - end -else - hasana = 0; - fprintf('no anatomical volume present\n'); - ana = ones(interp.dim); -end - -if ~isempty(cfg.funparameter) && issubfield(interp, cfg.funparameter) - hasfun = 1; - fun = getsubfield(interp, cfg.funparameter); -else - hasfun = 0; - cfg.funparameter = []; - fun = zeros(interp.dim); - fprintf('no functional parameter\n'); -end - -% scale functional data -fprintf('scaling functional data...'); -fmin = min(fun(:)); -fmax = max(fun(:)); -if ~ischar(cfg.colmin) - fcolmin = cfg.colmin; -else - if sign(fmin)==sign(fmax) - fcolmin = fmin; - else - fcolmin = -max(abs([fmin,fmax])); - end -end -if ~ischar(cfg.colmax) - fcolmax = cfg.colmax; -else - if sign(fmin)==sign(fmax) - fcolmax = fmax; - else - fcolmax = max(abs([fmin,fmax])); - end -end -fun = (fun-fcolmin)./(fcolmax-fcolmin); -if ~ischar(cfg.colmax) - fun(find(fun>1)) = 1; -end -if ~ischar(cfg.colmin) - fun(find(fun<0)) = 0; -end -fprintf('done\n'); - -if ~isempty(cfg.maskparameter) && issubfield(interp, cfg.maskparameter) - hasmsk = 1; - msk = getsubfield(interp, cfg.maskparameter); - fprintf('scaling mask data...'); - mmin = min(msk(:)); - mmax = max(msk(:)); - if ~ischar(cfg.maskcolmin) - mcolmin = cfg.maskcolmin; - else - if sign(mmin)==sign(mmax) - mcolmin = mmin; - else - mcolmin = -max(abs([mmin,mmax])); - end - end - if ~ischar(cfg.maskcolmax) - mcolmax = cfg.maskcolmax; - else - if sign(mmin)==sign(mmax) - mcolmax = mmax; - else - mcolmax = max(abs([mmin,mmax])); - end - end - msk = (msk-mcolmin)./(mcolmax-mcolmin); - if ~ischar(cfg.maskcolmax) - msk(find(msk>1)) = 1; - end - if ~ischar(cfg.maskcolmin) - msk(find(msk<0)) = 0; - end - fprintf('done\n'); -else - hasmsk = 0; - cfg.maskparameter = []; - if isempty(cfg.funparameter) - msk = zeros(interp.dim); - else - msk = 0.5 * ones(interp.dim); - end - fprintf('no masking parameter\n'); -end - -% ensure that they are all 3D volumes -ana = reshape(ana, interp.dim); -fun = reshape(fun, interp.dim); -msk = reshape(msk, interp.dim); - -% ensure that the functional data is real -if ~isreal(fun) - fprintf('taking absolute value of complex data\n'); - fun = abs(fun); -end - -anasc = []; -funsc = []; -msksc = []; - -% automatically determine the interesting range of values that should be plotted -if isempty(anasc) && hasana - anasc(1) = 0; - anasc(2) = max(ana(:)); -else - anasc = [0 1]; -end -if isempty(funsc) && hasfun - funsc(1) = min(fun(:)); - funsc(2) = max(fun(:)); -else - funsc = [0 1]; -end -if isempty(msksc) && hasmsk - msksc(1) = 0; - msksc(2) = 1; -else - msksc = [0 1]; -end - -x = interp.xgrid; -y = interp.ygrid; -z = interp.zgrid; -dim = interp.dim; - -if ~isstr(cfg.location) - if strcmp(cfg.locationcoordinates, 'head') - % convert the headcoordinates location into voxel coordinates - sel = inv(interp.transform) * [cfg.location(:); 1]; - sel = round(sel(1:3)); - elseif strcmp(cfg.locationcoordinates, 'voxel') - % the location is already in voxel coordinates - sel = round(cfg.location(1:3)); - end -else - sel = cfg.location; -end - -% determine the initial intersection of the cursor -if isstr(sel) && strcmp(sel, 'min') - if isempty(cfg.funparameter) - error('no functional parameter specified'); - end - [minval, minindx] = min(fun(:)); - [xi, yi, zi] = ind2sub(interp.dim, minindx); -elseif isstr(sel) && strcmp(sel, 'max') - if isempty(cfg.funparameter) - error('no functional parameter specified'); - end - [maxval, maxindx] = max(fun(:)); - [xi, yi, zi] = ind2sub(interp.dim, maxindx); -elseif isstr(sel) && strcmp(sel, 'maxproject') - if isempty(cfg.funparameter) - error('no functional parameter specified'); - end - % take [1 1 1] and project the maxima and contour of brain onto fun and ana. - xi = 1; - yi = 1; - zi = 1; - - load /home/coherence/jansch/matlab/fieldtrip/private/brainedges - - %create dummy anatomy with the outline of the brain in the first slices - ana = zeros(size(ana)); - %postprocess edges - sagittal(find(isnan(sagittal))) = 0; - tmp = imfill(imdilate(sagittal==1, strel('diamond', 2)), [100 100]); - sagittal = imerode(tmp, strel('diamond', 2)); - ana(1,:,:) = double(~(tmp - sagittal)); - - coronal(find(isnan(coronal))) = 0; - tmp = imfill(imdilate(coronal==1, strel('diamond', 2)), [100 100]); - coronal = imerode(tmp, strel('diamond', 2)); - ana(:,1,:) = double(~(tmp - coronal)); - - axial(find(isnan(axial))) = 0; - tmp = imfill(imdilate(axial==1, strel('diamond', 2)), [100 100]); - axial = imerode(tmp, strel('diamond', 2)); - ana(:,:,1) = double(~(tmp - axial)); - - anasc = [0 1]; - - %postprocess functional data and keep edges visible - fun(1,:,:) = squeeze(max(fun, [], 1)).*double(sagittal); - fun(:,1,:) = squeeze(max(fun, [], 2)).*double(coronal); - fun(:,:,1) = squeeze(max(fun, [], 3)).*double(axial); - - msk(1,:,:) = squeeze(max(msk, [], 1)).*double(sagittal); - msk(:,1,:) = squeeze(max(msk, [], 2)).*double(coronal); - msk(:,:,1) = squeeze(max(msk, [], 3)).*double(axial); - -elseif isstr(sel) && strcmp(sel, 'center') - xi = round(length(x)/2); - yi = round(length(y)/2); - zi = round(length(z)/2); -elseif isstr(sel) && strcmp(sel, 'interactive') - % start at the center - xi = round(length(x)/2); - yi = round(length(y)/2); - zi = round(length(z)/2); -elseif ~isstr(sel) - xi = nearest(x, sel(1)); - yi = nearest(y, sel(2)); - zi = nearest(z, sel(3)); -end - -% define the colormap for the functional data -funcolormap = colormap(cfg.colormap); - -nas = []; -lpa = []; -rpa = []; - -%if ~strcmp(cfg.location, 'interactive') && ~strcmp(cfg.location, 'maxproject'), -if ~strcmp(cfg.location, 'interactive'), - % plot only once - xi = round(xi); xi = max(xi, 1); xi = min(xi, dim(1)); - yi = round(yi); yi = max(yi, 1); yi = min(yi, dim(2)); - zi = round(zi); zi = max(zi, 1); zi = min(zi, dim(3)); - - ijk = [xi yi zi 1]'; - xyz = interp.transform * ijk; - val = fun(xi, yi, zi); - fprintf('voxel %d, indices [%d %d %d], location [%.1f %.1f %.1f], value %f\n', sub2ind(interp.dim, xi, yi, zi), ijk(1:3), xyz(1:3), val); - - if strcmp(cfg.TTlookup, 'yes') - lab = TTatlas_lookup(tlrc, mni2tal(xyz(1:3)), cfg.TTqueryrange); - if isempty(lab) - fprintf('Talairach-Tournoux labels: not found\n'); - else - fprintf('Talairach-Tournoux labels: ') - fprintf('%s', lab{1}); - for i=2:length(lab) - fprintf(', %s', lab{i}); - end - fprintf('\n'); - end - end - - subplot(2,2,1); singleplot(ana, fun, msk, anasc, funsc, msksc, [xi yi zi], 2, funcolormap); xlabel('i'); ylabel('k'); axis(cfg.axis); - if strcmp(cfg.crosshair, 'on'), crosshair([xi zi]); end - subplot(2,2,2); singleplot(ana, fun, msk, anasc, funsc, msksc, [xi yi zi], 1, funcolormap); xlabel('j'); ylabel('k'); axis(cfg.axis); - if strcmp(cfg.crosshair, 'on'), crosshair([yi zi]); end - subplot(2,2,3); singleplot(ana, fun, msk, anasc, funsc, msksc, [xi yi zi], 3, funcolormap); xlabel('i'); ylabel('j'); axis(cfg.axis); - if strcmp(cfg.crosshair, 'on'), crosshair([xi yi]); end - if strcmp(cfg.colorbar, 'on'), - vectorcolorbar = linspace(funsc(1),funsc(2),length(funcolormap)); - subplot(2,2,4);imagesc(vectorcolorbar,1,vectorcolorbar);colormap(funcolormap); - end - - drawnow; -%elseif strcmp(cfg.location, 'maxproject'), -% % make a 'glass-brain' projection -% % this part is rough and experimental -% xi = 1; -% yi = 1; -% zi = 1; -% keyboard -% load /home/coherence/jansch/matlab/fieldtrip/private/brainedges -% ana(1,:,:) = sagittal; -% ana(:,1,:) = coronal; -% ana(:,:,1) = axial; -% -% % make a 'glass-brain' projection -% % this part is rough and experimental -% load /home/coherence/jansch/matlab/fieldtrip/private/brainedges -% -% %sagittal -% [Xs,Ys] = ndgrid(1:size(sagittal,1),1:size(sagittal,2)); -% Zs = squeeze(max(fun, [], 1)); -% tmp = sagittal; -% tmp(find(tmp==0)) = nan; -% tmp(find(~isnan(tmp))) = 1; -% subplot(2,2,2); hold on; contour(Xs, Ys, sagittal, 1, 'k', 'LineWidth', 2); axis equal -% subplot(2,2,2); h1 = surface(Xs, Ys, zeros(size(Zs)), Zs.*tmp, 'EdgeColor', 'none'); -% set(h1, 'AlphaData', squeeze(max(msk, [], 1))); -% set(h1, 'FaceAlpha', 'interp'); -% axis off -% -% %coronal -% [Xs,Ys] = ndgrid(1:size(coronal,1),1:size(coronal,2)); -% Zs = squeeze(max(fun, [], 2)); -% tmp = coronal; -% tmp(find(tmp==0)) = nan; -% tmp(find(~isnan(tmp))) = 1; -% subplot(2,2,1); hold on; contour(Xs, Ys, coronal, 1, 'k', 'LineWidth', 2); axis equal -% subplot(2,2,1); h2 = surface(Xs, Ys, zeros(size(Zs)), Zs.*tmp, 'EdgeColor', 'none'); -% set(h2, 'AlphaData', msk); -% set(h2, 'AlphaData', squeeze(max(msk, [], 2))); -% set(h2, 'FaceAlpha', 'interp'); -% axis off -% -% %axial -% [Xs,Ys] = ndgrid(1:size(axial,1),1:size(axial,2)); -% Zs = squeeze(max(fun, [], 3)); -% tmp = axial; -% tmp(find(tmp==0)) = nan; -% tmp(find(~isnan(tmp))) = 1; -% subplot(2,2,3); hold on; contour(Xs, Ys, axial, 1, 'k', 'LineWidth', 2); axis equal -% subplot(2,2,3); h3 = surface(Xs, Ys, zeros(size(Zs)), Zs.*tmp, 'EdgeColor', 'none'); -% set(h3, 'AlphaData', squeeze(max(msk, [], 3))); -% set(h3, 'FaceAlpha', 'interp'); -% axis off -else - % keep on plotting until the user presses quit - while(1) - - xi = round(xi); xi = max(xi, 1); xi = min(xi, dim(1)); - yi = round(yi); yi = max(yi, 1); yi = min(yi, dim(2)); - zi = round(zi); zi = max(zi, 1); zi = min(zi, dim(3)); - - fprintf('\n'); - fprintf('click with mouse button to reposition the cursor\n'); - fprintf('press q on keyboard to quit interactive mode\n'); - if ~isempty(nas), fprintf('nas = [%f %f %f]\n', nas); end - if ~isempty(lpa), fprintf('lpa = [%f %f %f]\n', lpa); end - if ~isempty(rpa), fprintf('rpa = [%f %f %f]\n', rpa); end - - ijk = [xi yi zi 1]'; - xyz = interp.transform * ijk; - val = fun(xi, yi, zi); - fprintf('voxel %d, indices [%d %d %d], location [%.1f %.1f %.1f], value %f\n', sub2ind(interp.dim, xi, yi, zi), ijk(1:3), xyz(1:3), val); - - if strcmp(cfg.TTlookup, 'yes') - lab = TTatlas_lookup(tlrc, mni2tal(xyz(1:3)), cfg.TTqueryrange); - if isempty(lab) - fprintf('Talairach-Tournoux labels: not found\n'); - else - fprintf('Talairach-Tournoux labels: ') - fprintf('%s', lab{1}); - for i=2:length(lab) - fprintf(', %s', lab{i}); - end - fprintf('\n'); - end - end - - subplot(2,2,1); cla; singleplot(ana, fun, msk, anasc, funsc, msksc, [xi yi zi], 2, funcolormap); xlabel('i'); ylabel('k'); crosshair([xi zi]); - subplot(2,2,2); cla; singleplot(ana, fun, msk, anasc, funsc, msksc, [xi yi zi], 1, funcolormap); xlabel('j'); ylabel('k'); crosshair([yi zi]); - subplot(2,2,3); cla; singleplot(ana, fun, msk, anasc, funsc, msksc, [xi yi zi], 3, funcolormap); xlabel('i'); ylabel('j'); crosshair([xi yi]); - vectorcolorbar = linspace(funsc(1),funsc(2),length(funcolormap)); - subplot(2,2,4);imagesc(vectorcolorbar,1,vectorcolorbar);colormap(funcolormap); - drawnow; - - try, [d1, d2, key] = ginput(1); catch, key='q'; end - if key=='q' - break; - elseif key=='l' - lpa = [xi yi zi]; - elseif key=='r' - rpa = [xi yi zi]; - elseif key=='n' - nas = [xi yi zi]; - else - % update the view to a new position - l1 = get(get(gca, 'xlabel'), 'string'); - l2 = get(get(gca, 'ylabel'), 'string'); - switch l1, - case 'i' - xi = d1; - case 'j' - yi = d1; - case 'k' - zi = d1; - end - switch l2, - case 'i' - xi = d2; - case 'j' - yi = d2; - case 'k' - zi = d2; - end - end - end -end - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SINGLEPLOT makes an overlay of 3D anatomical, functional and probability -% volumes. The three volumes must be scaled between 0 and 1. -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function singleplot(ana, fun, msk, anasc, funsc, msksc, indx, dimension ,funcolormap); - -% select the indices of the intersection -xi = indx(1); -yi = indx(2); -zi = indx(3); - -% select the slice to plot -if dimension==1 - yi = 1:size(ana,2); - zi = 1:size(ana,3); -elseif dimension==2 - xi = 1:size(ana,1); - zi = 1:size(ana,3); -elseif dimension==3 - xi = 1:size(ana,1); - yi = 1:size(ana,2); -end - -% cut out the slice of interest -ana = squeeze(ana(xi,yi,zi)); -fun = squeeze(fun(xi,yi,zi)); -msk = squeeze(msk(xi,yi,zi)); - -% fprintf('scaling and clipping anatomy\n'); -ana(find(ana(:)anasc(2))) = anasc(2); % clip to maximal interesting values -ana = (ana-anasc(1))./(anasc(2)-anasc(1)); % scale interesting range to 0-1 -% fprintf('scaling and clipping functional\n'); -fun(find(fun(:)funsc(2))) = funsc(2); % clip to maximal values -fun = (fun-funsc(1))./(funsc(2)-funsc(1)); % scale interesting range to 0-1 -% fprintf('scaling and clipping mask\n'); -msk(find(msk(:)msksc(2))) = msksc(2); % clip to maximal interesting values -msk = (msk-msksc(1))./(msksc(2)-msksc(1)); % scale interesting range to 0-1 - -% this is needed for displaying the matrix using the Matlab image() function -ana = ana'; -fun = fun'; -msk = msk'; -dim = size(ana); - -% convert anatomy into RGB values -ana = cat(3, ana, ana, ana); - -% convert functional into RGB values -fun = floor((size(funcolormap,1)-1) * fun)+1; % scale interesting range to 1-64 -fun(find(isnan(fun(:)))) = 1; -r = zeros(dim); -g = zeros(dim); -b = zeros(dim); -r(:) = funcolormap(fun(:), 1); % find the matching color (Rgb) -g(:) = funcolormap(fun(:), 2); % find the matching color (rGb) -b(:) = funcolormap(fun(:), 3); % find the matching color (rgB) -fun = cat(3, r, g, b); - -ha = image(ana); -hold on -hf = image(fun); -set(hf, 'AlphaData', msk); % apply the opacity mask to the functional data -axis equal -axis tight -axis xy - diff --git a/external/fieldtrip/private/sourcestatistics.m b/external/fieldtrip/private/sourcestatistics.m deleted file mode 100644 index 3405e1e..0000000 --- a/external/fieldtrip/private/sourcestatistics.m +++ /dev/null @@ -1,191 +0,0 @@ -function [stat] = sourcestatistics(cfg, varargin) - -% SOURCESTATISTICS computes the probability for a given null-hypothesis using -% a parametric statistical test or using a non-parametric randomization test. -% -% Use as -% [stat] = sourcestatistics(cfg, source1, source2, ...) -% where the input data is the result from SOURCEANALYSIS, SOURCEDESCRIPTIVES -% or SOURCEGRANDAVERAGE. The source structures should be spatially alligned -% to each other and should have the same positions for the source grid. -% -% The configuration should contain the following option for data selection -% cfg.parameter = string, describing the functional data to be processed, e.g. 'pow', 'nai' or 'coh' -% -% Furthermore, the configuration should contain: -% cfg.method = different methods for calculating the probability of the null-hypothesis, -% 'montecarlo' uses a non-parametric randomization test to get a Monte-Carlo estimate of the probability, -% 'analytic' uses a parametric test that results in analytic probability, -% 'glm' uses a general linear model approach, -% 'stats' uses a parametric test from the Matlab statistics toolbox, -% 'parametric' uses the Matlab statistics toolbox (very similar to 'stats'), -% 'randomization' uses randomization of the data prior to source reconstruction, -% 'randcluster' uses randomization of the data prior to source reconstruction -% in combination with spatial clusters. -% -% You can restrict the statistical analysis to regions of interest (ROIs) -% or to the average value inside ROIs using the following options: -% cfg.atlas = filename of the atlas -% cfg.roi = string or cell of strings, region(s) of interest from anatomical atlas -% cfg.avgoverroi = 'yes' or 'no' (default = 'no') -% cfg.hemisphere = 'left', 'right', 'both', 'combined', specifying this is -% required when averaging over regions -% cfg.inputcoord = 'mni' or 'tal', the coordinate system in which your source -% reconstruction is expressed -% -% The other cfg options depend on the method that you select. You -% should read the help of the respective subfunction STATISTICS_XXX -% for the corresponding configuration options and for a detailed -% explanation of each method. -% -% -% See also SOURCEANALYSIS, SOURCEDESCRIPTIVES, SOURCEGRANDAVERAGE - -% Undocumented local options: -% cfg.statistic - -% Copyright (C) 2005-2008, Robert Oostenveld -% -% $Log: sourcestatistics.m,v $ -% Revision 1.44 2009/10/07 10:06:21 jansch -% temporary workaround to work with private copy statistics_wrapperJM, in order to develop some code (of coures with the eventual benefit for all). users whose (part of their) username contains 'jan' may run into problems, and have to uncomment lines 157, 161-163 -% -% Revision 1.43 2009/04/08 15:57:08 roboos -% moved the handling of the output cfg (with all history details) from wrapper to main function -% -% Revision 1.42 2008/12/05 14:47:05 ingnie -% updated help on cfg.roi -% -% Revision 1.41 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.40 2008/07/31 16:22:52 roboos -% added documentation pertaining to atlas ROIs and added check on input in case of ROI -% -% Revision 1.39 2007/05/30 07:08:08 roboos -% use checkdata instead of fixinside -% -% Revision 1.38 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.37 2007/04/03 10:04:20 roboos -% allow both source and volume data as input -% -% Revision 1.36 2007/03/30 17:05:40 ingnie -% checkinput; only proceed when input data is allowed datatype -% -% Revision 1.35 2006/10/19 15:05:51 roboos -% updated documentation -% -% Revision 1.34 2006/07/12 09:17:58 roboos -% improved documentation, fixed small bug in converting cfg option -% -% Revision 1.33 2006/07/05 10:21:56 roboos -% updaed documentation for consistency -% -% Revision 1.32 2006/06/13 14:48:10 ingnie -% updated documentation -% -% Revision 1.31 2006/04/20 09:58:34 roboos -% updated documentation -% -% Revision 1.30 2006/03/30 12:24:33 roboos -% Implemented private/fixinside, which facilitates consistent -% handling of source/volume data. Improved documentation. Fixed some -% bugs related to inconsistent handling of ROIs (i.e. inside/outside) -% -% Revision 1.29 2005/10/05 11:06:30 roboos -% documentation change -% -% Revision 1.28 2005/05/17 17:50:39 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.27 2005/05/12 07:20:06 roboos -% fixed backward compatibility approach/method translation for randcluster -% -% Revision 1.26 2005/05/09 14:20:02 roboos -% made the check on cfg.method optional, so that it also works when only the approach is specified -% -% Revision 1.25 2005/04/07 17:12:21 roboos -% improved the general help documentation, no code changes -% -% Revision 1.24 2005/04/06 14:29:41 roboos -% added copyrights and a log message placeholder -% - -fieldtripdefs - -% this wrapper should be compatible with the already existing statistical -% functions that only work for source input data - -% check if the input data is valid for this function -for i=1:length(varargin) - if isfield(cfg, 'roi') && ~isempty(cfg.roi) - varargin{i} = checkdata(varargin{i}, 'datatype', 'source', 'feedback', 'no', 'inside', 'index'); - else - varargin{i} = checkdata(varargin{i}, 'datatype', {'source', 'volume'}, 'feedback', 'no', 'inside', 'index'); - end -end - -if isfield(cfg, 'method') - % call the appropriate subfunction - if (strcmp(cfg.method, 'zero-baseline') || ... - strcmp(cfg.method, 'nai') || ... - strcmp(cfg.method, 'pseudo-t') || ... - strcmp(cfg.method, 'difference') || ... - strcmp(cfg.method, 'anova1') || ... - strcmp(cfg.method, 'kruskalwallis')) - % these are all statistical methods that are implemented in the old SOURCESTATISTICS_PARAMETRIC subfunction - cfg.statistic = cfg.method; - cfg.method = 'parametric'; - elseif strcmp(cfg.method, 'randomization') - cfg.method = 'randomization'; - elseif strcmp(cfg.method, 'randcluster') - cfg.method = 'randcluster'; - end -end - -if strcmp(cfg.method, 'parametric') - % use the source-specific statistical subfunction - stat = sourcestatistics_parametric(cfg, varargin{:}); -elseif strcmp(cfg.method, 'randomization') - % use the source-specific statistical subfunction - stat = sourcestatistics_randomization(cfg, varargin{:}); -elseif strcmp(cfg.method, 'randcluster') - % use the source-specific statistical subfunction - stat = sourcestatistics_randcluster(cfg, varargin{:}); -else - [status,output] = system('whoami'); - if isempty(strfind(output,'jan')), - % use the data-indepentend statistical wrapper function - % this will collect the data and subsequently call STATISTICS_XXX - [stat, cfg] = statistics_wrapper(cfg, varargin{:}); - else - [stat, cfg] = statistics_wrapperJM(cfg, varargin{:}); - end -end - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: sourcestatistics.m,v 1.44 2009/10/07 10:06:21 jansch Exp $'; - -% remember the configuration of the input data -cfg.previous = []; -for i=1:length(varargin) - if isfield(varargin{i}, 'cfg') - cfg.previous{i} = varargin{i}.cfg; - else - cfg.previous{i} = []; - end -end - -% remember the exact configuration details -stat.cfg = cfg; diff --git a/external/fieldtrip/private/sourcestatistics_parametric.m b/external/fieldtrip/private/sourcestatistics_parametric.m deleted file mode 100644 index 5038eb2..0000000 --- a/external/fieldtrip/private/sourcestatistics_parametric.m +++ /dev/null @@ -1,337 +0,0 @@ -function [stat] = sourcestatistics_parametric(cfg, varargin) - -% SOURCESTATISTICS_PARAMETRIC performs statistical analysis of the -% beamformer source reconstruction results using parametric methods. -% -% Use as -% [stat] = sourcestatistics(cfg, source1, source2, source3, ...) -% where cfg is a structure with the configuration details and sourceN -% is the source reconstruction for a particular active, baseline or -% noise condition. -% -% The general configuration items are -% cfg.method = 'randomization' -% cfg.statistic = string, see below -% cfg.parameter = string, describing the functional data to be processed, e.g. 'pow', 'nai' or 'coh' -% cfg.bonferoni = 'yes' or 'no', use Bonferoni correction for multiple comparisons -% cfg.threshold = the p-value with respect to the reference distribution at which -% an observed difference will be considered significant (default = 0.05) -% -% cfg.statistic = 'zero-baseline' performs t-test against the assumption of the signal being zero -% [stat] = sourcestatistics(cfg, active) -% This requires a variance estimate for the source parameters -% -% cfg.statistic = 'difference' performs t-test on the difference -% [stat] = sourcestatistics(cfg, condition1, condition2) -% This compares condition1 and condition2, and requires a variance estimate for the -% source parameters. -% -% cfg.statistic = 'anova1' -% [stat] = sourcestatistics(cfg, condition1, condition2, ...) -% This performs a one-way ANOVA for comparing the means of two or more -% source reconstructions. It requires the source reconstruction to contain -% single trials. -% -% cfg.statistic = 'kruskalwallis' -% [stat] = sourcestatistics(cfg, condition1, condition2, ...) -% This performs a non-parametric one-way ANOVA for comparing the means of two -% or more source reconstructions. It requires the source reconstruction to -% contain single trials. - -% FIXME this function should use parameterselection and getsubfield -% -% Undocumented local options: -% cfg.equalvar -% cfg.tscore - -% Copyright (C) 2003, Robert Oostenveld -% -% $Log: sourcestatistics_parametric.m,v $ -% Revision 1.18 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.17 2008/02/20 14:25:16 roboos -% fixed prob for tscores, thanks to Nathan -% -% Revision 1.16 2007/05/30 07:04:05 roboos -% use the checkdata function to avlidate the input and to convert the inside vector to indices -% -% Revision 1.15 2006/07/05 10:21:56 roboos -% updaed documentation for consistency -% -% Revision 1.14 2006/04/20 09:58:34 roboos -% updated documentation -% -% Revision 1.13 2006/03/30 12:24:33 roboos -% Implemented private/fixinside, which facilitates consistent -% handling of source/volume data. Improved documentation. Fixed some -% bugs related to inconsistent handling of ROIs (i.e. inside/outside) -% -% Revision 1.12 2006/02/07 22:22:48 roboos -% source.df can be vector as wel as single number, added support for that (element-wise * and /) -% -% Revision 1.11 2005/06/29 12:46:29 roboos -% the following changes were done on a large number of files at the same time, not all of them may apply to this specific file -% - added try-catch around the inclusion of input data configuration -% - moved cfg.version, cfg.previous and the assignment of the output cfg to the end -% - changed help comments around the configuration handling -% - some changes in whitespace -% -% Revision 1.10 2005/06/03 08:57:28 roboos -% transfer homogenous transformation matrix from input to output (if present) -% -% Revision 1.9 2005/05/17 17:50:39 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.8 2005/05/09 14:14:46 roboos -% made the assignment of the output stat fields that describe the grid (like pos, xgrid, dim ...) optional, so that it won't fail when one of these fields is not present -% -% Revision 1.7 2005/04/05 08:30:35 roboos -% fixed bug for counting the number of conditions and for krusakwallis -% -% Revision 1.6 2004/10/13 14:11:30 roboos -% changed cfg.previous, now consistent over functions with try-statement -% and will also work if the input already had a cfg.previous -% -% Revision 1.5 2004/08/19 07:10:31 roboos -% removed nai and pseudo-t -% changed interpretation of cfg.threshold for consistency with other functions -% removed inconsistent and untested conversion from t- to z-score -% added version information to the configuration -% -% Revision 1.4 2004/03/22 11:40:40 roberto -% fixed typo in tHreshold -% -% Revision 1.3 2004/03/19 17:43:58 roberto -% fixed two bugs: df is not always present, and a variable was named incorrectly -% -% Revision 1.2 2004/03/06 12:58:56 roberto -% undo the name change from alpha-threshold back into threshold. -% some cosmetic changes. funtion has not been tested yet. -% -% Revision 1.1 2004/03/06 12:19:15 roberto -% new implementation based on code that was coppied out of sourecstatistics.m -% some cosmetic and structure changes, no differences in actual computation -% - -fieldtripdefs - -% check if the input data is valid for this function -for i=1:length(varargin) - varargin{i} = checkdata(varargin{i}, 'datatype', {'source', 'volume'}, 'feedback', 'no', 'inside', 'index'); -end - -% set the defaults -if ~isfield(cfg, 'threshold'), cfg.threshold = 0.05; end -if ~isfield(cfg, 'bonferoni'), cfg.bonferoni = 'no'; end -if ~isfield(cfg, 'equalvar'), cfg.equalvar ='no'; end - -% for backward comparibility -if isfield(cfg, 'method') && ~strcmp(cfg.method, 'parametric') - warning('the configuration options cfg.method has been renamed in cfg.statistic, please read the documentation'); - cfg.statistic = cfg.method; - cfg.method = 'parametric'; -end - -% check for potential backward incomparibilities -if isfield(cfg, 'zscore') - warning('transformation from t-score to zcore is not supported any more'); -end - -% check for potential backward incomparibilities -if isfield(cfg, 'tscore') - warning('the option cfg.tscore is not used, please check your configuration'); -end - -% check for potential backward incomparibilities -if isfield(cfg, 'threshold') && cfg.threshold>0.5 - cfg.threshold = 1 - cfg.threshold; - warning('the interpretation of cfg.threshold has changed from (1-P) to P, for consistency with other functions') - warning(sprintf('assuming that you want to test your null-hypothesis with an alpha of %f', cfg.threshold)); -end - -% check whether a valid statistical test has been selected -if ~isfield(cfg, 'method') - error('no method specified for the statistical test'); -elseif strcmp(cfg.statistic, 'descriptive') - error('descriptive is not supported any more, use SOURCEDESCRIPTIVES'); -elseif strcmp(cfg.statistic, 'nai') - error('pseudostatistics such as neural activity index are not supported any more, use SOURCEDESCRIPTIVES'); -elseif strcmp(cfg.statistic, 'pseudo-t') - error('pseudostatistics such as pseudo-t are not supported any more, use SOURCEDESCRIPTIVES'); -elseif ~(strcmp(cfg.statistic, 'zero-baseline') || ... - strcmp(cfg.statistic, 'difference') || ... - strcmp(cfg.statistic, 'anova1') || ... - strcmp(cfg.statistic, 'kruskalwallis')) - error('unsupported statistical method'); -end - -% remember the definition of the volume, assume that they are identical for all input arguments -try, stat.dim = varargin{1}.dim; end -try, stat.xgrid = varargin{1}.xgrid; end -try, stat.ygrid = varargin{1}.ygrid; end -try, stat.zgrid = varargin{1}.zgrid; end -try, stat.inside = varargin{1}.inside; end -try, stat.outside = varargin{1}.outside; end -try, stat.pos = varargin{1}.pos; end -try, stat.transform = varargin{1}.transform; end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% preprocess the input data and extract the parameter of interest -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% count the dimensions of all items that we might loop over -Nconditions = length(varargin); -Nvoxels = prod(varargin{1}.dim); -if isfield(varargin{1}, 'trial') - for condition=1:Nconditions - Ntrials(condition) = length(varargin{condition}.trial); - end -else - Ntrials(1:Nconditions) = 0; -end - -% collect the data to perform the statistics on, the resulting array will contain -% source(i).df -% source(i).avg -% source(i).var optionally -% source(i).sem optionally -% source(i).trial optionally - -for condition=1:Nconditions - % source.df contains the number of repetitions used in computing the average and variance - source(condition).avg = getfield(varargin{condition}.avg, cfg.parameter); - try, source(condition).df = varargin{condition}.df; end - if isfield(varargin{condition}, 'var') && isfield(varargin{condition}.var, cfg.parameter) - source(condition).var = getfield(varargin{condition}.var, cfg.parameter); - end - if isfield(varargin{condition}, 'sem') && isfield(varargin{condition}.sem, cfg.parameter) - source(condition).sem = getfield(varargin{condition}.sem, cfg.parameter); - end - for trloop=1:Ntrials(condition) - % if trial data for this parameter is not present, Ntrials will be zero - % reformat all the trials into a matrix, each column is a trial - source(condition).trial(trloop,:) = getfield(varargin{condition}.trial(trloop), cfg.parameter); - end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% perform the statistical test, this is the method specific part -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -switch lower(cfg.statistic) - - case 'zero-baseline' - % compute difference between source parameter and zero, using Students t-score - if Nconditions>1 - error('only one source reconstruction allowed for zero-baseline comparison'); - end - tscore = source.avg./(source.var./source.df).^0.5; - combineddf = source.df - 1; - prob = 1-tcdf(tscore, combineddf); - - case 'difference' - % compute difference between two conditions using Students t-score - if Nconditions~=2 - error('exactly two source reconstructions required to compute difference statistic'); - end - condition1 = source(1); - condition2 = source(2); - difference = condition1.avg - condition2.avg; - v1 = condition1.var; - N1 = condition1.df; - v2 = condition2.var; - N2 = condition2.df; - if strcmp(cfg.equalvar, 'yes') - % assume equal variances for both conditions - combinedvar = ((N1-1)*v1 + (N2-1)*v2)/(N1 + N2 - 2); - combineddf = N1 + N2 - 2; - tscore = difference ./ sqrt(combinedvar*(1/N1 + 1/N2)); - else - % do not assume equal variances - tscore = difference ./ sqrt(v1./N1 + v2./N2); - % use Welch-Satterthwaite approximation for the combined degrees of freedom (see NIST handbook) - % FIXME this leads to a different df for each source location - combineddf = (v1./N1 + v2./N2).^2./((v1.^2)./(N1.^2.*(N1-1)) + (v2.^2)./(N2.^2.*(N2-1))); - end - prob = 1-tcdf(tscore, combineddf); - - case 'anova1' - if Nconditions<2 - error('at least two source inputs required for one-way Anova test'); - end - for voxel=1:Nvoxels - % perform a one-way Anova test for each voxel - value = []; - group = []; - for condition=1:Nconditions - N = size(source(condition).trial,2); % number of resamplings or single trials - value = [value; source(condition).trial(voxel,:)]; - group = [group; condition * ones(N,1)]; - end - % use a function from the Matlab statistics toolbox for the computation - prob(voxel) = anova1(value, group, 'off'); - end - prob = 1 - prob; - - case 'kruskalwallis' - if Nconditions<2 - error('at least two source inputs required for Kruskal-Wallis test'); - end - for voxel=1:Nvoxels - % perform a Kruskal-Wallis test for each voxel - value = []; - group = []; - for condition=1:Nconditions - tmp = source(condition).trial(:,voxel); - value = [value; tmp(:)]; - group = [group; condition * ones(Ntrials(condition),1)]; - end - % use a function from the Matlab statistics toolbox for the computation - prob(voxel) = kruskalwallis(value, group, 'off'); - end - prob = 1 - prob; -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% ready with the method specific part -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% compute the significance as boolean value -if exist('prob', 'var') - if strcmp(cfg.bonferoni, 'no') - fprintf('not correcting for multiple comparisons\n'); - mask = prob < cfg.threshold; - else - fprintf('performing Bonferoni correction for multiple comparisons\n'); - mask = prob < (cfg.threshold/length(stat.inside)); - end -else - warning('no statistical probablity value was computed'); -end - -% collect the non-descriptive statistics, probability and significance -if exist('tscore', 'var'), stat.tscore = tscore; end -if exist('prob', 'var'), stat.prob = prob; end -if exist('nai', 'var'), stat.nai = nai; end -if exist('mask', 'var'), stat.mask = mask; end - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: sourcestatistics_parametric.m,v 1.18 2008/09/22 20:17:44 roboos Exp $'; -% remember the configuration details of the input data -cfg.previous = []; -for i=1:length(varargin) - try, cfg.previous{i} = varargin{i}.cfg; end -end -% remember the exact configuration details in the output -stat.cfg = cfg; - diff --git a/external/fieldtrip/private/sourcestatistics_randcluster.m b/external/fieldtrip/private/sourcestatistics_randcluster.m deleted file mode 100644 index 1173dad..0000000 --- a/external/fieldtrip/private/sourcestatistics_randcluster.m +++ /dev/null @@ -1,316 +0,0 @@ -function [stat] = sourcestatistics_randcluster(cfg,source) - -% SOURCESTATISTICS_RANDCLUSTER performs statistics on the output of SOURCEANALYSIS, -% provided the randomization-method has been applied. It will be called from within the -% SOURCESTATISTICS function, when cfg.method is set to 'randcluster'. See also SOURCESTATISTICS -% for additional information. -% -% Use as -% [stat] = sourcestatistics(cfg,source) -% where cfg is a structure containing the configuration details, and source is a structure containing -% the fields trialA and trialB, obtained with the 'randomization'-method in sourceanalysis, -% or -% [stat] = sourcestatistics(cfg,stat) -% where cfg is a structure containing the configuration details, and stat is the output of -% sourcestatistics, by using the 'randcluster'-method, and using the 'intermediate'-option. -% -% For each randomization repetition, the difference volume between condition A and B is computed. -% In each volume p-values are computed for each voxel, with respect to the randomization distribution -% for that particular voxel (uncorrected for multiple comparisons). Subsequently, a clustering -% algorithm (with a voxel connectivity of 6) locates the biggest cluster, within each randomization -% volume, with p-values smaller than a predefined value. This yields a reference distribution of -% cluster sizes, against which the size of the clusters in the observed data (by using the same cluster -% threshold) are tested. In this way, correction for multiple comparisons is achieved. -% -% The following parameters are mandatory: -% cfg.method = 'randcluster' -% cfg.parameter = string, describing the functional data to be processed, e.g. 'pow', 'nai' or 'coh' -% The following parameters are optional: -% cfg.comparestat = 'difference' (default), or 'relchange' (relative change) -% cfg.clusterthreshold = the a priori threshold at which the individual volumes will be -% thresholded (default = 0.05); -% cfg.threshold = the p-value with respect to the reference distribution at which -% an observed cluster will be considered significant. (default = 0.05) -% cfg.intermediate = if set to 'yes' (default), it keeps the uncorrected p-values in -% the output structure, so that the function's output can directly -% be used again as an input, which will save quite some computation time -% if you want to evaluate the effect of a different clusterthreshold. -% cfg.tail = 0, -1, or 1. -% if cfg.tail = 0, the alternative for a rejected null-hypothesis will be: -% condition A and B are different. (default) -% if cfg.tail = -1,the alternative for a rejected null-hypothesis will be: -% condition A < B. -% if cfg.tail = 1, the alternative for a rejected null-hypothesis will be: -% condition A > B. -% cfg.ztransform = 'no' (default), or 'yes'. This z-transforms the tested parameter based on the -% randomization variance estimate for each voxel. -% The function outputs the structure stat, containing the following fields: -% stat.cluster: information about the clusters in the observed data -% nVox: the number of voxels. -% prob: the p-value against the reference distribution. -% shape: the shape of the cluster, voxels belonging to the cluster -% are set to 1, the rest will be 0. -% significance: the significance of the cluster against cfg.threshold. -% stat.dist: the reference distribution of maximum cluster-sizes against which the observed -% data has been tested. -% stat.mask: a volume-reconstruction with the same size as source.dim, with the significant -% clusters put to 1, and the rest will be 0. Can be used as a mask for displaying -% purposes. -% stat.intermediate: (if specified in the configuration) -% prob_obs is a vector containing for each voxel the p-values (uncorrected) against -% the randomization-distribution for that particular voxel. -% prob_rand is a matrix of number of randomizations times number of voxels, containing -% for each randomization and voxel the p-values (uncorrected) against the randomization -% distribution for that particular voxel. - -% FIXME this function should use parameterselection and getsubfield - -% Copyright (C) 2004, Jan-Mathijs Schoffelen -% -% $Log: sourcestatistics_randcluster.m,v $ -% Revision 1.15 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.14 2007/05/30 07:04:05 roboos -% use the checkdata function to avlidate the input and to convert the inside vector to indices -% -% Revision 1.13 2006/07/05 10:21:56 roboos -% updaed documentation for consistency -% -% Revision 1.12 2006/03/30 12:24:33 roboos -% Implemented private/fixinside, which facilitates consistent -% handling of source/volume data. Improved documentation. Fixed some -% bugs related to inconsistent handling of ROIs (i.e. inside/outside) -% -% Revision 1.11 2005/06/29 12:46:29 roboos -% the following changes were done on a large number of files at the same time, not all of them may apply to this specific file -% - added try-catch around the inclusion of input data configuration -% - moved cfg.version, cfg.previous and the assignment of the output cfg to the end -% - changed help comments around the configuration handling -% - some changes in whitespace -% -% Revision 1.10 2005/06/03 08:58:07 roboos -% transfer homogenous transformation matrix from input to output (if present) -% added an extra method of counting the number of dipoles/voxels in the input source structure -% -% Revision 1.9 2005/05/17 17:50:39 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.8 2005/05/12 12:17:23 roboos -% added a reshape around the source parameter to ensure that it is a row vector -% if source.pos is not available, determine the number of dipoles from source.dim -% -% Revision 1.7 2005/05/09 14:14:46 roboos -% made the assignment of the output stat fields that describe the grid (like pos, xgrid, dim ...) optional, so that it won't fail when one of these fields is not present -% -% Revision 1.6 2005/03/18 14:36:15 roboos -% fixed bug in two sided testing by replacing the relevant code by the RANDSTATPROB private subfunction -% -% Revision 1.5 2004/11/09 15:23:10 jansch -% fixed nasty bug which led to systematic underestimation of the max-cluster- -% size in the randomized volumes. -% -% Revision 1.4 2004/10/20 10:37:55 roboos -% fixed bug that occurred if avg.pow was not a row-vector -% -% Revision 1.3 2004/09/22 14:09:52 roboos -% renamed method=randomized into method=randomization, with backward compatibility -% -% Revision 1.2 2004/09/08 13:31:56 jansch -% changed some code. added version information -% - -fieldtripdefs - -% check if the input data is valid for this function -source = checkdata(source, 'datatype', {'source', 'volume'}, 'feedback', 'no', 'inside', 'index'); - -% set the defaults -if ~isfield(cfg,'threshold'), cfg.threshold = 0.05; end -if ~isfield(cfg,'clusterthreshold'), cfg.clusterthreshold = 0.05; end -if ~isfield(cfg,'tail'), cfg.tail = 0; end -if ~isfield(cfg,'intermediate'), cfg.intermediate = 'yes'; end -if ~isfield(cfg,'comparestat'), cfg.comparestat = 'difference'; end -if ~isfield(cfg, 'ztransform'), cfg.ztransform = 'no'; end - -% this is required for backward compatibility with the old sourceanalysis -if isfield(source, 'method') && strcmp(source.method, 'randomized') - source.method = 'randomization'; -elseif isfield(source, 'method') && strcmp(source.method, 'permuted') - source.method = 'permutation'; -end - -if ~isfield(cfg,'parameter') - error('no parameter to do statistics on has been specified'); -end - -if ~strcmp(cfg.intermediate,'yes') && ~strcmp(source.method,'randomization'), - error('the data are not suited to do randomization statistics on'); -end - -if ~isfield(source,'intermediate'), - if isfield(source, 'pos') - % count the number of dipole positions, which can be either on a regular or an irregular grid - nDipole = size(source.pos,1); - elseif isfield(source, 'dim') - % individual dipole positions are not available after spatial normalisation to a template anatomical MRI - nDipole = prod(source.dim); - else - % count the number of functional values, which should be the same as the number of dipoles - dum = getfield(source.avgA,cfg.parameter); - nDipole = prod(size(dum)); - end - - % get the data to work on in nice arrays - nTrial = size(source.trialA,2); - strialA = zeros(nTrial,nDipole); - strialB = zeros(nTrial,nDipole); - for j = 1:nTrial - % reshape to ensure that the functional parameter for all voxels is arranged in a row-vector - strialA(j,:) = reshape(getfield(source.trialA,{j},cfg.parameter), [1 nDipole]); - strialB(j,:) = reshape(getfield(source.trialB,{j},cfg.parameter), [1 nDipole]); - end - % reshape to ensure that the functional parameter for all voxels is arranged in a row-vector - savgA = reshape(getfield(source.avgA,cfg.parameter), [1 nDipole]); - savgB = reshape(getfield(source.avgB,cfg.parameter), [1 nDipole]); - % transform to z-scores if requested - if strcmp(cfg.ztransform,'yes') - inside = source.inside; - meanA = repmat(mean(strialA(:,inside)),size(strialA,1),1); - meanB = repmat(mean(strialB(:,inside)),size(strialB,1),1); - stdA = repmat(std(strialA(:,inside)),size(strialA,1),1); - stdB = repmat(std(strialB(:,inside)),size(strialB,1),1); - strialA(:,inside) = (strialA(:,inside) - meanA) ./ stdA; - strialB(:,inside) = (strialB(:,inside) - meanB) ./ stdB; - savgA(1,inside) = (savgA(1,inside) - meanA(1,:)) ./ stdA(1,:); - savgB(1,inside) = (savgB(1,inside) - meanB(1,:)) ./ stdB(1,:); - end - % normalize by condition B if requested - if strcmp(cfg.comparestat,'difference'), - randobs = strialA-strialB; - realobs = savgA-savgB; - elseif strcmp(cfg.comparestat,'relchange'), - randobs = (strialA-strialB)./strialB; - realobs = (savgA-savgB)./savgB; - end; -else - % only the number of trials needs to be determined, the preprocessing up to - % the per-voxel-probability computation already have been performed before - nTrial = size(source.trialA,2); -end - -inside = source.inside; -outside = source.outside; -c = zeros(nTrial,1); -maxC = zeros(nTrial,1); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%compute the maximum-cluster size on the thresholded p-values -%for each randomization -%%%%%%%%%%%%%%%%%%%%%%% - -for k = 1:nTrial - fprintf('trial %d of %d\n',k,nTrial); - - if ~isfield(source,'intermediate'), - % compute p-values - intermediate.prob_rand(k,inside) = randstatprob(randobs(:,inside)', randobs(k,inside)', cfg.tail, 0)'; - intermediate.prob_rand(k,outside) = nan; - else - % reuse the previously computed p-values - intermediate.prob_rand = source.intermediate.prob_rand; - end - - dum = intermediate.prob_rand(k,:); % take the probability over all voxels - dum = find(dumcluster(k).nVox))+1)./(nTrial); - cluster(k).shape= remember{k}; - cluster(k).significance = logical(cluster(k).prob < cfg.threshold); - if cluster(k).significance - mask = (mask | cluster(k).shape); - end - end - [srt,indx] = sort([cluster(:).nVox]); - cluster=cluster(indx); -end - -%%%%%%%%%%%%%%%%%%%% -%collect the results -%%%%%%%%%%%%%%%%%%%% - -try, stat.dim = source.dim; end -try, stat.xgrid = source.xgrid; end -try, stat.ygrid = source.ygrid; end -try, stat.zgrid = source.zgrid; end -try, stat.inside = source.inside; end -try, stat.outside = source.outside; end -try, stat.pos = source.pos; end -try, stat.transform = source.transform; end - -stat.cluster = cluster; -stat.dist = maxC; -stat.mask = mask; -if strcmp(cfg.intermediate,'yes'), stat.intermediate = intermediate; end - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: sourcestatistics_randcluster.m,v 1.15 2008/09/22 20:17:44 roboos Exp $'; -% remember the configuration details of the input data -try, cfg.previous = source.cfg ; end -% remember the exact configuration details in the output -stat.cfg = cfg; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%subfunction for finding connectivity -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function remember = findconnect(onoff) - -seg = bwlabeln(onoff, 6); -for i=1:max(seg(:)); - remember{i} = (seg==i); -end diff --git a/external/fieldtrip/private/sourcestatistics_randomization.m b/external/fieldtrip/private/sourcestatistics_randomization.m deleted file mode 100644 index 456784b..0000000 --- a/external/fieldtrip/private/sourcestatistics_randomization.m +++ /dev/null @@ -1,199 +0,0 @@ -function [stat] = sourcestatistics_randomization(cfg, source) - -% SOURCESTATISTICS_RANDOMIZATION performs statistics on the output of SOURCEANALYSIS, -% provided the randomization-method has been applied. It will be called from within the -% SOURCESTATISTICS function, when cfg.method is set to 'randomization'. See also SOURCESTATISTICS -% for additional information. -% -% Use as -% [stat] = sourcestatistics(cfg,source) -% where cfg is a structure containing the configuration details, and source is a structure containing -% the fields trialA and trialB, obtained with the 'randomization'-method in sourceanalysis. -% -% The function performs a non-parametric randomization test for comparing the -% means of two randomized source reconstructions A and B. -% -% The following parameters are mandatory: -% cfg.method = 'randomization' -% cfg.parameter = string, describing the functional data to be processed, e.g. 'pow', 'nai' or 'coh' -% -% The following parameters are optional: -% The computation of a one- or two-tailed test can be specified with -% cfg.tail = 0 (test A~=B, default), 1 (test A>B), -1 (test A. +% +% $Id: spearman_binned.m 952 2010-04-21 18:29:51Z roboos $ + +if ~isfield(cfg, 'factor') & prod(size(design)) ~= max(size(design)), + error('cannot determine the labeling of the trials'); +elseif ~isfield(cfg, 'factor') + cfg.ivar = 1; +end + +nsgn = size(dat,1); +nrpt = size(dat,2); +if length(size(dat))==3, + nfrq = 1; + n = size(dat,3); +elseif length(size(dat))==4, + nfrq = size(dat,3); + n = size(dat,4); +end + +if n ~= 2, + error('the last dimension of the input should be 2'); +end + +cnd = unique(design(cfg.ivar, :)); +ncnd = length(cnd); + + +for k = 1:nsgn + for j = 1:nfrq + for m = 1:ncnd + sel = find(design(cfg.ivar, :) == cnd(m)); + dumdat = squeeze(dat(k, sel, j, :)); + [srt, ind] = sort(dumdat); + dumdat(ind(:,1),1) = [1:size(dumdat,1)]'; %do the rank-transformation + dumdat(ind(:,2),2) = [1:size(dumdat,1)]'; + denom = size(dumdat,1) * (size(dumdat,1)^2-1) / 6; + rcc(k, j, m) = 1 - sum(diff(dumdat, [], 2).^2) / denom; + end + end +end + +s = rcc; + diff --git a/external/fieldtrip/private/spearman_diff.m b/external/fieldtrip/private/spearman_diff.m new file mode 100644 index 0000000..92613e6 --- /dev/null +++ b/external/fieldtrip/private/spearman_diff.m @@ -0,0 +1,83 @@ +function s = spearman_diff(cfg, dat, design) + +%SPEARMAN_DIFF computes the difference in rank-correlation +%coefficient between two variables, between conditions '1' +%and '2' as they are labeled by design + +%The input-data should be formatted as follows: +% first dimension : signals (or signal-combinations) +% second dimension: repetitions +% third dimension : frequencies (optional), or the two signals which will be correlated +% fourth dimension (optional): the two signals which will be correlated +% the last dimension should have length two, since this dimension contains the two variables +% that are to be rank-correlated + +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: spearman_diff.m 952 2010-04-21 18:29:51Z roboos $ + +if ~isfield(cfg, 'factor') & prod(size(design)) ~= max(size(design)), + error('cannot determine the labeling of the trials'); +elseif ~isfield(cfg, 'factor') + cfg.ivar = 1; +end + +nsgn = size(dat,1); +nrpt = size(dat,2); +if length(size(dat))==3, + nfrq = 1; + n = size(dat,3); +else + nfrq = size(dat,3); + n = size(dat,4); +end + +if n ~= 2, + error('the last dimension of the input should be 2'); +end + +selA = find(design(cfg.ivar, :) == 1); +selB = find(design(cfg.ivar, :) == 2); + +%if length(selA) ~= length(selB) +% error('inappropriate design'); +%end +%NONSENSE + +for k = 1:nsgn + for j = 1:nfrq + datA = squeeze(dat(k, selA, j, :)); %datA = trials x 2 + datB = squeeze(dat(k, selB, j, :)); %datB = trials x 2 + + [srtA, indA] = sort(datA); + datA(indA(:,1),1) = [1:size(datA,1)]'; + datA(indA(:,2),2) = [1:size(datA,1)]'; + + [srtB, indB] = sort(datB); + datB(indB(:,1),1) = [1:size(datB,1)]'; + datB(indB(:,2),2) = [1:size(datB,1)]'; + + denomA = size(datA,1) * (size(datA,1)^2-1) / 6; + rccA(k, j) = 1 - sum(diff(datA, [], 2).^2) / denomA; + + denomB = size(datB,1) * (size(datB,1)^2-1) / 6; + rccB(k, j) = 1 - sum(diff(datB, [], 2).^2) / denomB; + end +end + +s = rccA - rccB; + diff --git a/external/fieldtrip/private/specest_hilbert.m b/external/fieldtrip/private/specest_hilbert.m new file mode 100644 index 0000000..715b387 --- /dev/null +++ b/external/fieldtrip/private/specest_hilbert.m @@ -0,0 +1,96 @@ +function [spectrum,freqoi,timeoi] = specest_hilbert(dat, time, varargin) + +% SPECEST_HILBERT performs a spectral estimation of data by repeatedly +% applying a bandpass filter and then doing a hilbert transform. +% +% Use as +% [spectrum,freqoi,timeoi] = specest_hilbert(dat,time,...) +% +% dat = matrix of chan*sample +% time = vector, containing time in seconds for each sample +% spectrum = matrix of taper*chan*freqoi*timeoi of fourier coefficients +% freqoi = vector of frequencies in spectrum +% timeoi = vector of timebins in spectrum +% +% +% +% +% Optional arguments should be specified in key-value pairs and can include: +% timeoi = vector, containing time points of interest (in seconds) +% freqoi = vector, containing frequencies (in Hz) +% width = +% filttype = +% filtorder = +% filtdir = +% +% +% +% +% See also SPECEST_MTMFFT, SPECEST_TFR, SPECEST_MTMCONVOL, SPECEST_MTMWELCH, SPECEST_NANFFT, SPECEST_MVAR, SPECEST_WLTCONVOL + +% Copyright (C) 2010, Robert Oostenveld +% +% $Rev: 1180 $ + +% get the optional input arguments +keyvalcheck(varargin, 'optional', {'freqoi','timeoi','width','filttype','filtorder','filtdir'}); +freqoi = keyval('freqoi', varargin); +timeoi = keyval('timeoi', varargin); if isempty(timeoi), timeoi = 'all'; end +width = keyval('width', varargin); if isempty(width), width = 1; end +filttype = keyval('filttype', varargin); +filtorder = keyval('filtorder', varargin); +filtdir = keyval('filtdir', varargin); + + +% Set n's +[nchan,ndatsample] = size(dat); + + +% Determine fsample and set total time-length of data +fsample = 1/(time(2)-time(1)); + + +% set a default sampling for the frequencies-of-interest +if isempty(freqoi), + freqoi = linspace(2*width, (fsample/3), 50); +end +% check for freqoi = 0 and remove it +if any(freqoi==0) + freqoi(freqoi==0) = []; +end +nfreq = length(freqoi); + + +% Set timeboi and timeoi +offset = round(time(1)*fsample); +if isnumeric(timeoi) % if input is a vector + timeboi = round(timeoi .* fsample - offset) + 1; + ntimeboi = length(timeboi); + timeoi = round(timeoi .* fsample) ./ fsample; +elseif strcmp(timeoi,'all') % if input was 'all' + timeboi = 1:length(time); + ntimeboi = length(timeboi); + timeoi = time; +end + + +% each frequency can have its own width +if numel(width)==1 + width = width*ones(size(freqoi)); +end + +% preallocate the result +spectrum = complex(zeros(nchans, nfreq, ntime)); + +for i=1:nfreq + flt = preproc_bandpassfilter(dat, fsample, [freqoi(i)-width(i) freqoi(i)+width(i)], filtorder, filttype, filtdir); + spectrum(:,i,:) = transpose(hilbert(transpose(flt))); +end + +% get timeboi out of spectrum +spectrum = spectrum(:,:,timeboi); + + + + + diff --git a/external/fieldtrip/private/specest_mtmconvol.m b/external/fieldtrip/private/specest_mtmconvol.m new file mode 100644 index 0000000..64e53f3 --- /dev/null +++ b/external/fieldtrip/private/specest_mtmconvol.m @@ -0,0 +1,275 @@ +function [spectrum,ntaper,freqoi,timeoi] = specest_mtmconvol(dat, time, varargin) + +% SPECEST_MTMCONVOL performs wavelet convolution in the time domain by multiplication in the frequency domain +% +% +% Use as +% [spectrum,ntaper,freqoi,timeoi] = specest_mtmconvol(dat,time,...) +% +% dat = matrix of chan*sample +% time = vector, containing time in seconds for each sample +% spectrum = matrix of taper*chan*freqoi*timeoi of fourier coefficients +% ntaper = vector containing number of tapers per element of freqoi +% freqoi = vector of frequencies in spectrum +% timeoi = vector of timebins in spectrum +% +% +% +% +% Optional arguments should be specified in key-value pairs and can include: +% taper = 'dpss', 'hanning' or many others, see WINDOW (default = 'dpss') +% pad = number, indicating time-length of data to be padded out to in seconds +% timeoi = vector, containing time points of interest (in seconds) +% timwin = vector, containing length of time windows (in seconds) +% freqoi = vector, containing frequencies (in Hz) +% tapsmofrq = vector, the amount of spectral smoothing through multi-tapering. Note: 4 Hz smoothing means plus-minus 4 Hz, i.e. a 8 Hz smoothing box +% +% +% +% +% +% FFT SPEED NOT YET OPTIMIZED (e.g. matlab version, transpose or not) +% IF FREQOI CONTAINS 0 (we should either remove it or allow the creation of a wavelet which is a straigth line, it's removed now) +% SHOULD FREQOI = 'ALL' BE REMOVED OR NOT? +% +% See also SPECEST_MTMFFT, SPECEST_TFR, SPECEST_HILBERT, SPECEST_MTMWELCH, SPECEST_NANFFT, SPECEST_MVAR, SPECEST_WLTCONVOL + + +% get the optional input arguments +keyvalcheck(varargin, 'optional', {'taper','pad','timeoi','timwin','freqoi','tapsmofrq'}); +taper = keyval('taper', varargin); if isempty(taper), taper = 'dpss'; end +pad = keyval('pad', varargin); +timeoi = keyval('timeoi', varargin); if isempty(timeoi), timeoi = 'all'; end +timwin = keyval('timwin', varargin); +freqoi = keyval('freqoi', varargin); if isempty(freqoi), freqoi = 'all'; end +tapsmofrq = keyval('tapsmofrq', varargin); + +% throw errors for required input +if isempty(tapsmofrq) && strcmp(taper, 'dpss') + error('you need to specify tapsmofrq when using dpss tapers') +end +if isempty(timwin) + error('you need to specify timwin') +elseif (length(timwin) ~= length(freqoi) && ~strcmp(freqoi,'all')) + error('timwin should be of equal length as freqoi') +end + + +% Set n's +[nchan,ndatsample] = size(dat); + + +% Determine fsample and set total time-length of data +fsample = 1/(time(2)-time(1)); +dattime = ndatsample / fsample; % total time in seconds of input data + +% Zero padding +if pad < dattime + error('the padding that you specified is shorter than the data'); +end +if isempty(pad) % if no padding is specified padding is equal to current data length + pad = dattime; +end +postpad = zeros(1,round((pad - dattime) * fsample)); +endnsample = pad * fsample; % total number of samples of padded data +endtime = pad; % total time in seconds of padded data + + + + +% Set freqboi and freqoi +if isnumeric(freqoi) % if input is a vector + freqboi = round(freqoi ./ (fsample ./ endnsample)) + 1; + freqoi = (freqboi-1) ./ endtime; % boi - 1 because 0 Hz is included in fourier output +elseif strcmp(freqoi,'all') + freqboilim = round([0 fsample/2] ./ (fsample ./ endnsample)) + 1; + freqboi = freqboilim(1):1:freqboilim(2); + freqoi = (freqboi-1) ./ endtime; +end +% check for freqoi = 0 and remove it, there is no wavelet for freqoi = 0 +if freqoi(1)==0 + freqoi(1) = []; + freqboi(1) = []; + if length(timwin) == (length(freqoi) + 1) + timwin(1) = []; + end +end +nfreqboi = length(freqboi); +nfreqoi = length(freqoi); + + + +% Set timeboi and timeoi +offset = round(time(1)*fsample); +if isnumeric(timeoi) % if input is a vector + timeboi = round(timeoi .* fsample - offset) + 1; + ntimeboi = length(timeboi); + timeoi = round(timeoi .* fsample) ./ fsample; +elseif strcmp(timeoi,'all') % if input was 'all' + timeboi = 1:length(time); + ntimeboi = length(timeboi); + timeoi = time; +end + + +% set number of samples per time-window (timwin is in seconds) +timwinsample = round(timwin .* fsample); + + + +% Compute tapers per frequency, multiply with wavelets and compute their fft +wltspctrm = cell(nfreqoi,1); +ntaper = zeros(nfreqoi,1); +for ifreqoi = 1:nfreqoi + + switch taper + case 'dpss' + % create a sequence of DPSS tapers, ensure that the input arguments are double precision + tap = double_dpss(timwinsample(ifreqoi), timwinsample(ifreqoi) .* (tapsmofrq(ifreqoi) ./ fsample))'; + % remove the last taper because the last slepian taper is always messy + tap = tap(1:(end-1), :); + + % give error/warning about number of tapers + if isempty(tap) + error('datalength to short for specified smoothing\ndatalength: %.3f s, smoothing: %.3f Hz, minimum smoothing: %.3f Hz',ndatsample/fsample,tapsmofrq(ifreqoi),fsample/fsample); + elseif size(tap,1) == 1 + warning('using only one taper for specified smoothing') + end + + + case 'sine' + tap = sine_taper(timwinsample(ifreqoi), timwinsample(ifreqoi) .* (tapsmofrq(ifreqoi) ./ fsample))'; + + case 'alpha' + tap = alpha_taper(timwinsample(ifreqoi), freqoi(ifreqoi)./ fsample)'; + tap = tap./norm(tap)'; + + otherwise + % create a single taper according to the window specification as a replacement for the DPSS (Slepian) sequence + tap = window(taper, timwinsample(ifreqoi))'; + tap = tap ./ norm(tap,'fro'); % make it explicit that the frobenius norm is being used + end + + % set number of tapers + ntaper(ifreqoi) = size(tap,1); + + % Wavelet construction + tappad = ceil(endnsample ./ 2) - floor(timwinsample(ifreqoi) ./ 2); + prezero = zeros(1,tappad); + postzero = zeros(1,round(endnsample) - ((tappad-1) + timwinsample(ifreqoi))-1); + anglein = (0:timwinsample(ifreqoi)-1)' .* ((2.*pi./fsample) .* freqoi(ifreqoi)); + wltspctrm{ifreqoi} = complex(zeros(size(tap,1),round(endnsample))); + + + % the following code determines the phase-shift needed so that the centre of each wavelet has angle = 0. This code can probably be optimized greatly. + % determine appropriate phase-shift so angle(wavelet) at center approximates 0 NOTE: this procedure becomes inaccurate when there are very few samples per cycle (i.e. 4-5) + cyclefraction = anglein / (2*pi); % transform angle to fraction of cycles + if ((length(cyclefraction(cyclefraction<1))-1) < 5) % could be more robust + warning('number of samples per wavelet cycle is less than 5') + end + fullcyclenum = floor(max(cyclefraction)); % get the number of complete cycles in angle + [dum fractind] = min(abs(cyclefraction - fullcyclenum)); % determine closest breakpoint in angle for which the last uncomplete cycle starts (closest so angle(wavelet) at centre gets closest to 0) + if cyclefraction(fractind) < fullcyclenum % if index is from the last full cycle, shift it by 1. should be integrated in above line + fractind = fractind + 1; + end + fractind = fractind + (length(prezero) - length(postzero)); % correct for unevend zero-padding (which shift the wavelet itself) + fractind = (fractind + 1):length(anglein); % shift one sample upwards and fill indices (why again?) + if length(fractind) > 1 % only continue if more than one sample can be split up + % create new anglein with non-full cycly being split to both sides of the (resulting) wavelet + nsplit = length(fractind) / 2; + anglestart = -(floor(nsplit):-1:1) .* ((2.*pi./fsample) .* freqoi(ifreqoi)); % using floor(nsplit) here, as the beginning of anglein is always at the exact start of sin/cos + angleind = 1:fractind(ceil(nsplit)); % using ceil(nsplit) here, as the end of anglein is nearly never at the end of a sin/cos, so an extra sample in case of non-integer-nsplit would do the most good here + anglein = [anglestart' ; anglein(angleind)]; + end + + for itap = 1:ntaper(ifreqoi) + try % this try loop tries to fit the wavelet into wltspctrm, when its length is smaller than ndatsample, the rest is 'filled' with zeros because of above code + % if a wavelet is longer than ndatsample, it doesn't fit and it is kept at zeros, which is translated to NaN's in the output + % construct the complex wavelet + coswav = horzcat(prezero, tap(itap,:) .* cos(anglein)', postzero); + sinwav = horzcat(prezero, tap(itap,:) .* sin(anglein)', postzero); + + % consistency: cos must always be 1 at centre (necessary for angle(wavelet) at centre approximates 0), and sin must always be centered in upgoing flank (arbitrary), and + centreind = round(length(coswav) / 2); + % first the cos + if coswav(centreind) < 0 + coswav = -coswav; + end + % now the sin + if sinwav(centreind) > sinwav(centreind+1) + sinwav = -sinwav; + end + wavelet = complex(coswav, sinwav); + % debug plotting + %figure; subplot(2,1,1);hold on;plot(real(wavelet));plot(imag(wavelet),'color','r'); tline = length(wavelet)/2;line([tline tline],[-0.2 0.2]); subplot(2,1,2);plot(angle(wavelet),'color','g');line([tline tline],[-pi pi]) + % store the fft of the complex wavelet + wltspctrm{ifreqoi}(itap,:) = fft(wavelet,[],2); + end + end +end + + +% compute fft, major speed increases are possible here, depending on which matlab is being used whether or not it helps, which mainly focuses on orientation of the to be fft'd matrix +spectrum = complex(nan([sum(ntaper),nchan,nfreqoi,ntimeboi])); +datspectrum = fft([dat repmat(postpad,[nchan, 1])],[],2); +for ifreqoi = 1:nfreqoi + fprintf('processing frequency %d (%.2f Hz), %d tapers\n', ifreqoi,freqoi(ifreqoi),ntaper(ifreqoi)); + for itap = 1:ntaper(ifreqoi) + for ichan = 1:nchan + % compute indices that will be used to extracted the requested fft output + nsamplefreqoi = timwin(ifreqoi) .* fsample; + reqtimeboiind = find((timeboi >= (nsamplefreqoi ./ 2)) & (timeboi < ndatsample - (nsamplefreqoi ./2))); + reqtimeboi = timeboi(reqtimeboiind); + + % compute datspectrum*wavelet, if there are reqtimeboi's that have data + if ~isempty(reqtimeboi) + dum = fftshift(ifft(datspectrum(ichan,:) .* wltspctrm{ifreqoi}(itap,:),[],2)); % fftshift is necessary because of post zero-padding, not necessary when pre-padding + spectrum(itap,ichan,ifreqoi,reqtimeboiind) = dum(reqtimeboi); + end + end + end +end + + + + + + + + + + + + + + + + + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION ensure that the first two input arguments are of double +% precision this prevents an instability (bug) in the computation of the +% tapers for Matlab 6.5 and 7.0 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [tap] = double_dpss(a, b, varargin) +tap = dpss(double(a), double(b), varargin{:}); + + + + + + + + + + + + + + + + + diff --git a/external/fieldtrip/private/specest_mtmfft.m b/external/fieldtrip/private/specest_mtmfft.m new file mode 100644 index 0000000..7f72fdc --- /dev/null +++ b/external/fieldtrip/private/specest_mtmfft.m @@ -0,0 +1,159 @@ +function [spectrum,ntaper,freqoi] = specest_mtmfft(dat, time, varargin) + +% SPECEST_MTMFFT computes a fast Fourier transform using many possible tapers +% +% +% Use as +% [spectrum,freqoi] = specest_mtmfft(dat,time...) +% +% dat = matrix of chan*sample +% time = vector, containing time in seconds for each sample +% spectrum = matrix of taper*chan*freqoi of fourier coefficients +% ntaper = vector containing number of tapers per element of freqoi +% freqoi = vector of frequencies in spectrum +% +% +% +% +% Optional arguments should be specified in key-value pairs and can include: +% taper = 'dpss', 'hanning' or many others, see WINDOW (default = 'dpss') +% pad = number, total length of data after zero padding (in seconds) +% freqoi = vector, containing frequencies of interest +% tapsmofrq = the amount of spectral smoothing through multi-tapering. Note: 4 Hz smoothing means plus-minus 4 Hz, i.e. a 8 Hz smoothing box +% +% +% +% +% FFT SPEED NOT YET OPTIMIZED (e.g. matlab version, transpose or not) +% SHOULD FREQOI = 'ALL' BE REMOVED OR NOT? +% +% +% See also SPECEST_MTMCONVOL, SPECEST_TFR, SPECEST_HILBERT, SPECEST_MTMWELCH, SPECEST_NANFFT, SPECEST_MVAR, SPECEST_WLTCONVOL + + +% get the optional input arguments +keyvalcheck(varargin, 'optional', {'taper','pad','freqoi','tapsmofrq'}); +taper = keyval('taper', varargin); if isempty(taper), error('You must specify a taper'); end +pad = keyval('pad', varargin); +freqoi = keyval('freqoi', varargin); if isempty(freqoi), freqoi = 'all'; end +tapsmofrq = keyval('tapsmofrq', varargin); + +% throw errors for required input +if isempty(tapsmofrq) && strcmp(taper, 'dpss') + error('you need to specify tapsmofrq when using dpss tapers') +end + + + +% Set n's +[nchan,ndatsample] = size(dat); + + +% Determine fsample and set total time-length of data +fsample = 1/(time(2)-time(1)); +dattime = ndatsample / fsample; % total time in seconds of input data + +% Zero padding +if pad < dattime + error('the padding that you specified is shorter than the data'); +end +if isempty(pad) % if no padding is specified padding is equal to current data length + pad = dattime; +end +postpad = zeros(1,ceil((pad - dattime) * fsample)); +endnsample = round(pad * fsample); % total number of samples of padded data +endtime = pad; % total time in seconds of padded data +postpad = []; + + +% Set freqboi and freqoi +if isnumeric(freqoi) % if input is a vector + freqboi = round(freqoi ./ (fsample ./ endnsample)) + 1; + freqoi = (freqboi-1) ./ endtime; % boi - 1 because 0 Hz is included in fourier output +elseif strcmp(freqoi,'all') % if input was 'all' + freqboilim = round([0 fsample/2] ./ (fsample ./ endnsample)) + 1; + freqboi = freqboilim(1):1:freqboilim(2); + freqoi = (freqboi-1) ./ endtime; +end +nfreqboi = length(freqboi); +nfreqoi = length(freqoi); + + + + +% create tapers +switch taper + + case 'dpss' + % create a sequence of DPSS tapers, ensure that the input arguments are double precision + tap = double_dpss(ndatsample,ndatsample*(tapsmofrq./fsample))'; + % remove the last taper because the last slepian taper is always messy + tap = tap(1:(end-1), :); + + % give error/warning about number of tapers + if isempty(tap) + error('datalength to short for specified smoothing\ndatalength: %.3f s, smoothing: %.3f Hz, minimum smoothing: %.3f Hz',ndatsample/fsample,tapsmofrq,fsample/fsample); + elseif size(tap,1) == 1 + warning('using only one taper for specified smoothing') + end + + case 'sine' + tap = sine_taper(ndatsample, ndatsample*(tapsmofrq./fsample))'; + + case 'alpha' + error('not yet implemented'); + + otherwise + % create the taper and ensure that it is normalized + tap = window(taper, ndatsample)'; + tap = tap ./ norm(tap,'fro'); + +end % switch taper +ntaper = size(tap,1); + + +% determine phase-shift so that for all frequencies angle(t=0) = 0 +timedelay = abs(time(1)); % phase shift is equal for both negative and positive offsets +if timedelay ~= 0 + angletransform = complex(zeros(1,nfreqoi)); + for ifreqoi = 1:nfreqoi + missedsamples = length(0:1/fsample:timedelay); + % determine angle of freqoi if oscillation started at 0 + % the angle of wavelet(cos,sin) = 0 at the first point of a cycle, with sin being in upgoing flank, which is the same convention as in mtmconvol + anglein = (missedsamples-1) .* ((2.*pi./fsample) .* freqoi(ifreqoi)); + coswav = cos(anglein); + sinwav = sin(anglein); + angletransform(ifreqoi) = angle(complex(coswav,sinwav)); + end +end + + +% compute fft, major speed increases are possible here, depending on which matlab is being used whether or not it helps, which mainly focuses on orientation of the to be fft'd matrix +spectrum = complex(zeros(ntaper,nchan,nfreqboi),zeros(ntaper,nchan,nfreqboi)); +for itap = 1:ntaper + for ichan = 1:nchan + dum = fft([dat(ichan,:) .* tap(itap,:) postpad],[],2); + dum = dum(freqboi); + % phase-shift according to above angles + if timedelay ~= 0 + dum = dum .* (exp(-1i*(angle(dum) - angletransform))); + end + spectrum(itap,ichan,:) = dum; + end +end +fprintf('nfft: %d samples, taper length: %d samples, %d tapers\n',endnsample,ndatsample,ntaper); + + + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION ensure that the first two input arguments are of double +% precision this prevents an instability (bug) in the computation of the +% tapers for Matlab 6.5 and 7.0 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [tap] = double_dpss(a, b, varargin) +tap = dpss(double(a), double(b), varargin{:}); + + diff --git a/external/fieldtrip/private/specest_mtmwelch.m b/external/fieldtrip/private/specest_mtmwelch.m new file mode 100644 index 0000000..91c806d --- /dev/null +++ b/external/fieldtrip/private/specest_mtmwelch.m @@ -0,0 +1,2 @@ +function [spectrum] = specest_mtmwelch(dat, time, varargin) +% placeholder \ No newline at end of file diff --git a/external/fieldtrip/private/specest_mvar.m b/external/fieldtrip/private/specest_mvar.m new file mode 100644 index 0000000..146e158 --- /dev/null +++ b/external/fieldtrip/private/specest_mvar.m @@ -0,0 +1,2 @@ +function [spectrum] = specest_mvar(dat, time, varargin) +% placeholder \ No newline at end of file diff --git a/external/fieldtrip/private/specest_nanfft.m b/external/fieldtrip/private/specest_nanfft.m index c6b1717..8a2502e 100644 --- a/external/fieldtrip/private/specest_nanfft.m +++ b/external/fieldtrip/private/specest_nanfft.m @@ -1,49 +1,78 @@ -function [y, opt] = specest_nanfft(x, varargin) +function [spectrum] = specest_nanfft(dat, time, varargin) % SPECEST_NANFFT computes a fast Fourier transform in the presence of NaNs % in the data % % Use as -% [y] = specest_nanfft(x, ...) +% [spectrum] = specest_nanfft(dat, ...) % -% Optional arguments should be specified in key-value pairs and can include +% +% dat = matrix of chan*sample +% time = vector, containing time in seconds for each sample +% spectrum = matrix of taper*chan*foi*toi of fourier coefficients +% +% +% +% +% Optional arguments should be specified in key-value pairs and can include: % basis = precomputes set of basis functions (sines/cosines) % datataype = 0, 1, 2 +% +% +% +% +% FFT SPEED NOT YET OPTIMIZED (e.g. matlab version, transpose or not) +% FUNCTION IS RECURSIVE, SHOULD BE AVOIDED IN FAVOR OF TRANSPARANCY +% +% +% See also SPECEST_MTMFFT, SPECEST_TFR, SPECEST_HILBERT, SPECEST_MTMWELCH, SPECEST_MTMCONVOL, SPECEST_MVAR, SPECEST_WLTCONVOL + + % Copyright (C) 2008, Robert Oostenveld % -% $Log: specest_nanfft.m,v $ -% Revision 1.4 2008/10/01 13:17:36 roboos -% correct number of channels for zeros, deal with case when all data is nan (thanks to Thilo) +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.3 2008/10/01 11:24:13 roboos -% implemented spectral estimate for data with odd number of samples (sofar only an even number of samples would work) +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.2 2008/10/01 08:19:45 roboos -% complete update, variable nan-locations are supported, using pseudo-inverse +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: specest_nanfft.m 1159 2010-05-28 11:53:46Z roevdmei $ % get the optional arguments basis = keyval('basis', varargin); datatype = keyval('datatype', varargin); -[m, n] = size(x); +% determine the data characteristics +[nchan, nsample] = size(dat); +fsample = 1/(time(2)-time(1)); + -if mod(n,2)==0 +if mod(nsample,2)==0 % the number of samples is even - k = n/2+1; + k = nsample/2+1; else % the number of samples is odd - k = floor(n/2+1); + k = floor(nsample/2+1); end % determine the type of data and thereby the most suitable algorithm to use -nancount = sum(isnan(x), 1); +nancount = sum(isnan(dat), 1); if isempty(datatype) if all(nancount==0) % there is no missing data datatype = 0; - elseif all(nancount==0 | nancount==m) + elseif all(nancount==0 | nancount==nchan) % the missing data is at the same location for all channels datatype = 1; else @@ -57,30 +86,30 @@ elseif datatype~=0 && isempty(basis) % create a seperate set of basis functions for the cosine and sine - basis_c = zeros(k, n); - basis_s = zeros(k, n); + basis_c = zeros(k, nsample); + basis_s = zeros(k, nsample); % create the time axis - t = linspace(0, 2*pi, n+1); + t = linspace(0, 2*pi, nsample+1); t = t(1:end-1); for w=1:k c = cos((w-1)*t); s = sin((w-1)*t); - if w==1 || (w==(k) && mod(n,2)==0) + if w==1 || (w==(k) && mod(nsample,2)==0) % the normalization for the lowest (DC) and the highest frequency component is different - s = s/(n); - c = c/(n); + s = s/(nsample); + c = c/(nsample); else - s = s/(n/2); - c = c/(n/2); + s = s/(nsample/2); + c = c/(nsample/2); end basis_c(w,:) = c; basis_s(w,:) = s; end % concatenate the sine and cosine basis functions % leaving the first and last sine functions out, since those are all zero - if mod(n,2)==0 + if mod(nsample,2)==0 % the number of samples is even -> the last sine wave basis function is zero basis = cat(1, basis_c, basis_s(2:end-1, :)); else @@ -94,36 +123,36 @@ case 0 % there is no missing data % use the standard FFT implementation - y = fft(x, [], 2); + y = fft(dat, [], 2); case 1 % the missing data is at the same location for all channels % remove that piece from the data and from the basis functions and use linear estimation - keep = ~isnan(x(1,:)); + keep = ~isnan(dat(1,:)); if all(~keep) % the data is all NaN, no reason to try to estimate the basis % functions - y = nan(size(x)); + y = nan(size(dat)); return end basis = basis(:,keep); - x = x(:,keep); + dat = dat(:,keep); - % do the linear estimation based on x=y*basis - % y = x / basis; - y = x * pinv(basis); + % do the linear estimation based on dat=y*basis + % y = dat / basis; + y = dat * pinv(basis); % disentagle the estimated components - if mod(n,2)==0 + if mod(nsample,2)==0 % the number of samples is even -> the last sine wave basis function is zero sel1 = 1; % lowest cosine, i.e. DC sel2 = 2:(k-1); % all cosines in between sel3 = k; % highest cosine - sel4 = (k+1):n; % all sines + sel4 = (k+1):nsample; % all sines est1 = y(:,sel1); est2 = y(:,sel2); @@ -132,14 +161,14 @@ % combine the various estimates into a complex representation compatible with standard FFT y_real = cat(2, est1, est2, est3, fliplr(est2)); - y_imag = cat(2, zeros(m,1), -est4, zeros(m,1), fliplr(est4)); + y_imag = cat(2, zeros(nchan,1), -est4, zeros(nchan,1), fliplr(est4)); y = y_real + i*y_imag; else % the number of samples is odd -> also include the last sine wave basis function sel1 = 1; % lowest cosine, i.e. DC sel2 = 2:k; % all other cosines - sel3 = (k+1):n; % all sines + sel3 = (k+1):nsample; % all sines est1 = y(:,sel1); est2 = y(:,sel2); @@ -147,18 +176,22 @@ % combine the various estimates into a complex representation compatible with standard FFT y_real = cat(2, est1, est2, fliplr(est2)); - y_imag = cat(2, zeros(m,1), -est3, fliplr(est3)); + y_imag = cat(2, zeros(nchan,1), -est3, fliplr(est3)); y = y_real + i*y_imag; end case 2 % the missing data is at different timepoints for different channels % use recursion to compute the nanfft for each channel - y = zeros(size(x)); - for k=1:m - y(k,:) = specest_nanfft(x(k,:), 'basis', basis); + y = zeros(size(dat)); + for k=1:nchan + y(k,:) = specest_nanfft(dat(k,:), 'basis', basis); end otherwise error('unsupported configuration of NaNs in the data'); end + +% set output +spectrum = y; + diff --git a/external/fieldtrip/private/specest_tfr.m b/external/fieldtrip/private/specest_tfr.m new file mode 100644 index 0000000..7e0e199 --- /dev/null +++ b/external/fieldtrip/private/specest_tfr.m @@ -0,0 +1,240 @@ +function [spectrum, freqoi, timeoi] = specest_tfr(dat, time, varargin) + +% SPECEST_TFR performs wavelet convolution in the time domain by convolution with Morlet's wavelets. +% +% +% Use as +% [spectrum,freqoi,timeoi] = specest_tfr(dat,time,...) +% +% dat = matrix of chan*sample +% time = vector, containing time in seconds for each sample +% spectrum = matrix of chan*freqoi*timeoi of fourier coefficients +% freqoi = vector of frequencies in spectrum +% timeoi = vector of timebins in spectrum +% +% +% +% +% Optional arguments should be specified in key-value pairs and can include: +% timeoi = vector, containing time points of interest (in seconds, analysis window will be centered around these time points) +% freqoi = vector, containing frequencies (in Hz) +% waveletwidth = number, 'width' of wavelets expressed in cycles (default = 7) +% +% +% +% +% OPTION DOWNSAMPLE: this looks like something that would fit in better in the (freqanalysis) wrapper I think +% OPTION LATENCY, WHAT TO DO WITH THIS? +% HOW TO MAKE CONSISTENT freqoi'S OVER TRIALS (e.g. multiple runs of this function)? ZERO-PADDING NOT AN OPTION... YET WE SHOULD STILL ONLY HAVE freqoi'S THAT ACTUALLY MATCH THE FREQUENCIES IN OUTPUT +% +% +% See also SPECEST_MTMFFT, SPECEST_MTMCONVOL, SPECEST_HILBERT, SPECEST_MTMWELCH, SPECEST_NANFFT, SPECEST_MVAR, SPECEST_WLTCONVOL + + + + +% get the optional input arguments +keyvalcheck(varargin, 'optional', {'waveletwidth','pad','timeoi','freqoi'}); +timeoi = keyval('timeoi', varargin); if isempty(timeoi), timeoi = 'all'; end +freqoi = keyval('freqoi', varargin); if isempty(freqoi), freqoi = 'all'; end +waveletwidth = keyval('waveletwidth', varargin); if isempty(waveletwidth), waveletwidth = 7; end + + +% Set n's +[nchan,ndatsample] = size(dat); + + +% Determine fsample and set total time-length of data +fsample = 1/(time(2)-time(1)); +dattime = ndatsample / fsample; % total time in seconds of input data +endnsample = ndatsample; % for consistency with mtmconvol and mtmfft +endtime = dattime; % for consistency with mtmconvol and mtmfft + + +% Set freqboi and freqoi +if isnumeric(freqoi) % if input is a vector + freqboi = round(freqoi ./ (fsample ./ endnsample)) + 1; + freqoi = (freqboi-1) ./ endtime; % boi - 1 because 0 Hz is included in fourier output +elseif strcmp(freqoi,'all') + freqboilim = round([0 fsample/2] ./ (fsample ./ endnsample)) + 1; + freqboi = freqboilim(1):1:freqboilim(2); + freqoi = (freqboi-1) ./ endtime; +end +nfreqboi = length(freqboi); +nfreqoi = length(freqoi); + + +% Set timeboi and timeoi +offset = round(time(1)*fsample); +if isnumeric(timeoi) % if input is a vector + timeboi = round(timeoi .* fsample - offset) + 1; + ntimeboi = length(timeboi); + timeoi = round(timeoi .* fsample) ./ fsample; +elseif strcmp(timeoi,'all') % if input was 'all' + timeboi = 1:length(time); + ntimeboi = length(timeboi); + timeoi = time; +end + + + +% compute wavelet family +wavfam = waveletfam(freqoi,fsample,waveletwidth); + + +% compute spectrum by convolving the wavelets with the data +spectrum = zeros(nchan, nfreqoi, nsample); +for ifreqoi = 1:nfreqoi + wavelet = wavfam{ifreqoi}; + for ichan = 1:nchan + spectrum(ichan,ifreqoi,:) = conv(dat(ichan,:), wavelet, 'same'); + end + % pad the edges with nans to indicate that the wavelet was not fully immersed in the data THERE ARE NO NANS ADDED IN FREQANALYSIS_TFR? + nanpad = ceil(length(wavfam{ifreqoi})/2); + % the padding should not be longer than the actual data + nanpad = min(nanpad, nsample); + begnanpad = 1:nanpad; + endnanpad = (nsample-nanpad+1):nsample; + spectrum(:,ifreqoi,begnanpad) = nan; + spectrum(:,ifreqoi,endnanpad) = nan; +end + +% select the samples for the output +spectrum = spectrum(:,:,timeboi); + + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION for waveletanalysis +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function M = waveletfam(foi,fsample,waveletwidth) +dt = 1/fsample; +for k=1:length(foi) + sf = foi(k)/waveletwidth; + st = 1/(2*pi*sf); + toi = -3.5*st:dt:3.5*st; + A = 1/sqrt(st*sqrt(pi)); + M{k}= A*exp(-toi.^2/(2*st^2)).*exp(i*2*pi*foi(k).*toi); +end + + + + + + + + + + + + + + + + + +% state = keyval('state', varargin); +% waveletwidth = keyval('waveletwidth', varargin); if isempty(waveletwidth), waveletwidth = 7; end +% downsample = keyval('downsample', varargin); +% time = keyval('time', varargin); +% toi = keyval('toi', varargin); +% +% % FIXME add width +% +% if ~isempty(downsample) && ~isempty(toi) +% error('the downsample and toi options are mutually exclusive'); +% end +% +% nchans = size(dat,1); +% nsamples = size(dat,2); +% +% if isempty(time) +% if ~isempty(toi) +% error('specification of toi without time is not permitted'); +% end +% time = (0:(nsamples-1))/fsample; +% end +% +% if ~isempty(state) && isequal(state.fsample, fsample) && isequal(state.foi, foi) && isequal(state.waveletwidth, waveletwidth) +% % reuse the wavelet family from the previous state +% disp('using previous state'); +% M = state.M; +% else +% if ~isempty(state) +% state = []; +% warning('recomputing the state'); +% end +% % recompute the wavelet family +% M = waveletfam(foi,fsample,waveletwidth); +% end +% +% % compute freq by convolving the wavelets with the data +% nfreq = length(foi); +% spectrum = zeros(nchans, nsamples, nfreq); +% +% for f=1:nfreq +% wavelet = M{f}; +% for c=1:nchans +% spectrum(c,:,f) = conv(dat(c,:), wavelet, 'same'); +% end +% % pad the edges with nans to indicate that the wavelet was not fully immersed in the data +% pad = ceil(length(M{f})/2); +% % the padding should not be longer than the actual data +% pad = min(pad, nsamples); +% begpad = 1:pad; +% endpad = (nsamples-pad+1):nsamples; +% spectrum(:,begpad,f) = nan; +% spectrum(:,endpad,f) = nan; +% end +% +% if ~isempty(downsample) +% % this would be done in case of downsample +% tbin = 1:downsample:nsamples; +% elseif ~isempty(toi) +% % this would be done in case of toi/time specification +% tbin = zeros(size(toi)); +% for i=1:length(tbin) +% tbin = nearest(time, toi(i)); +% end +% else +% tbin = 1:nsamples; +% end +% +% % select the samples for the output +% spectrum = spectrum(:,tbin,:); +% +% % remember the wavelets so that they can be reused in a subsequent call +% state.fsample = fsample; +% state.foi = foi; +% state.waveletwidth = waveletwidth; +% state.M = M; +% +% % %convolves data in chan by time matrix (from one trial) with 1 wavelet for +% % %each specified frequency of interest +% % spectrum = zeros(size(data,1),length(foi), size(data,2)); +% % for k=1:size(data,1) %nchans +% % for j=1:length(foi) +% % cTmp = conv(data(k,:),M{j}); +% % cTmp = 2*(abs(cTmp).^2)/fsample; +% % cTmp = cTmp(ceil(length(M{j})/2):length(cTmp)-floor(length(M{j})/2)); +% % spectrum(k,j,:) = cTmp; +% % end +% % +% % end +% +% %output should be chan by freq by time + + + + + + + + + + + + + diff --git a/external/fieldtrip/private/specest_wltconvol.m b/external/fieldtrip/private/specest_wltconvol.m new file mode 100644 index 0000000..28d6d36 --- /dev/null +++ b/external/fieldtrip/private/specest_wltconvol.m @@ -0,0 +1,166 @@ +function [spectrum,freqoi,timeoi] = specest_wltconvol(dat, time, varargin) + +% SPECEST_WLTCONVOL performs time-frequency analysis on any time series trial data using the 'wavelet method' based on Morlet wavelets, +% doing convolution in the time domain by multiplaction in the frequency domain +% +% +% Use as +% [spectrum,freqoi,timoei] = specest_wltconvol(dat,time...) +% +% dat = matrix of chan*sample +% time = vector, containing time in seconds for each sample +% spectrum = matrix of chan*freqoi*timeoi of fourier coefficients +% freqoi = vector of frequencies in spectrum +% timeoi = vector of timebins in spectrum +% +% +% +% Optional arguments should be specified in key-value pairs and can include: +% pad = number, total length of data after zero padding (in seconds) +% freqoi = vector, containing frequencies of interest +% timeoi = vector, containing time points of interest (in seconds) +% width = +% gwidth = +% +% +% +% +% +% FFT SPEED NOT YET OPTIMIZED (e.g. matlab version, transpose or not) +% SHOULD FREQOI = 'ALL' BE REMOVED OR NOT? +% +% +% See also SPECEST_MTMCONVOL, SPECEST_TFR, SPECEST_HILBERT, SPECEST_MTMWELCH, SPECEST_NANFFT, SPECEST_MVAR, SPECEST_MTMCONVOL + + +% get the optional input arguments +keyvalcheck(varargin, 'optional', {'pad','width','gwidth','freqoi','timeoi'}); +freqoi = keyval('freqoi', varargin); if isempty(freqoi), freqoi = 'all'; end +timeoi = keyval('timeoi', varargin); if isempty(timeoi), timeoi = 'all'; end +width = keyval('width', varargin); if isempty(width), width = 7; end +gwidth = keyval('gwidth', varargin); if isempty(gwidth), gwidth = 3; end +pad = keyval('pad', varargin); + + + +% Set n's +[nchan,ndatsample] = size(dat); + + +% Determine fsample and set total time-length of data +fsample = 1/(time(2)-time(1)); +dattime = ndatsample / fsample; % total time in seconds of input data + + + +% Zero padding +if pad < dattime + error('the padding that you specified is shorter than the data'); +end +if isempty(pad) % if no padding is specified padding is equal to current data length + pad = dattime; +end +prepad = zeros(1,floor((pad - dattime) * fsample ./ 2)); +postpad = zeros(1,ceil((pad - dattime) * fsample ./ 2)); +endnsample = pad * fsample; % total number of samples of padded data +endtime = pad; % total time in seconds of padded data + + + +% Set freqboi and freqoi +if isnumeric(freqoi) % if input is a vector + freqboi = round(freqoi ./ (fsample ./ endnsample)) + 1; + freqoi = (freqboi-1) ./ endtime; % boi - 1 because 0 Hz is included in fourier output +elseif strcmp(freqoi,'all') % if input was 'all' + freqboilim = round([0 fsample/2] ./ (fsample ./ endnsample)) + 1; + freqboi = freqboilim(1):1:freqboilim(2); + freqoi = (freqboi-1) ./ endtime; +end +% check for freqoi = 0 and remove it, there is no wavelet for freqoi = 0 +if freqoi(1)==0 + freqoi(1) = []; + freqboi(1) = []; +end +nfreqboi = length(freqboi); +nfreqoi = length(freqoi); +% expand width to array if constant width +if numel(width) == 1 + width = ones(1,nfreqoi) * width; +end + + +% Set timeboi and timeoi +offset = round(time(1)*fsample); +if isnumeric(timeoi) % if input is a vector + timeboi = round(timeoi .* fsample - offset) + 1; + ntimeboi = length(timeboi); + timeoi = round(timeoi .* fsample) ./ fsample; +elseif strcmp(timeoi,'all') % if input was 'all' + timeboi = 1:length(time); + ntimeboi = length(timeboi); + timeoi = time; +end + + +% minoffset = min(data.offset); +% timboi = round(cfg.toi .* data.fsample - minoffset); +% toi = round(cfg.toi .* data.fsample) ./ data.fsample; +% numtoi = length(toi); +% numfoi = length(cfg.foi); + + + +% Creating wavelets +wltspctrm = cell(nfreqoi,1); +for ifreqoi = 1:nfreqoi + dt = 1/fsample; + sf = freqoi(ifreqoi) / width(ifreqoi); + st = 1/(2*pi*sf); + toi2 = -gwidth*st:dt:gwidth*st; + A = 1/sqrt(st*sqrt(pi)); + tap = (A*exp(-toi2.^2/(2*st^2)))'; + acttapnumsmp = size(tap,1); + taplen(ifreqoi) = acttapnumsmp; + ins = ceil(endnsample./2) - floor(acttapnumsmp./2); + prezer = zeros(ins,1); + pstzer = zeros(endnsample - ((ins-1) + acttapnumsmp)-1,1); + ind = (0:acttapnumsmp-1)' .* ((2.*pi./fsample) .* freqoi(ifreqoi)); + wltspctrm{ifreqoi} = complex(zeros(1,endnsample)); + wltspctrm{ifreqoi} = fft(complex(vertcat(prezer,tap.*cos(ind),pstzer), vertcat(prezer,tap.*sin(ind),pstzer)),[],1)'; +end + + +% Compute fft +spectrum = complex(nchan,nfreqoi,ntimeboi); +datspectrum = fft([repmat(prepad,[nchan, 1]) dat repmat(postpad,[nchan, 1])],[],2); +for ifreqoi = 1:nfreqoi + fprintf('processing frequency %d (%.2f Hz)\n', ifreqoi,freqoi(ifreqoi)); + for ichan = 1:nchan + % compute indices that will be used to extracted the requested fft output + nsamplefreqoi = taplen(ifreqoi) .* fsample; + reqtimeboiind = find((timeboi >= (nsamplefreqoi ./ 2)) & (timeboi < ndatsample - (nsamplefreqoi ./2))); + reqtimeboi = timeboi(reqtimeboiind); + + % compute datspectrum*wavelet, if there are reqtimeboi's that have data + if ~isempty(reqtimeboi) + dum = fftshift(ifft(datspectrum(ichan,:) .* wltspctrm{ifreqoi},[],2)); % why is this fftshift necessary? + spectrum(ichan,ifreqoi,reqtimeboiind) = dum(reqtimeboi); + end + end +end + + + + + + + + + + + + + + + + diff --git a/external/fieldtrip/private/sphfit.m b/external/fieldtrip/private/sphfit.m index 3d68776..5b4b61d 100644 --- a/external/fieldtrip/private/sphfit.m +++ b/external/fieldtrip/private/sphfit.m @@ -21,6 +21,26 @@ % successive estimates of the radius. % If rel_diff<1e-6 (default of use fixed), then break out. +% Copyright (C) 2003, Guido Nolte +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: sphfit.m 946 2010-04-21 17:51:16Z roboos $ + if nargin<2 || isempty(Ni) Ni = 20; end diff --git a/external/fieldtrip/private/spikeanalysis.m b/external/fieldtrip/private/spikeanalysis.m deleted file mode 100644 index 330e4a0..0000000 --- a/external/fieldtrip/private/spikeanalysis.m +++ /dev/null @@ -1,198 +0,0 @@ -function [spike] = spikeanalysis(cfg, data); - -% SPIKEANALYSIS performs analysis on spike data -% -% Use as -% [spike] = spikeanalysis(cfg, data); -% -% The following configuration options are supported -% cfg.method = 'rate' (default), or 'spikephase' -% -% in combination with cfg.method = 'rate', -% cfg.toi = the spike-rate is computed in a window surrounding the time-points in cfg.toi -% cfg.timwin = window width -% -% if cfg.toi and cfg.timwin are not specified, the average rate across each trial is computed. -% -% in combination with cfg.method = 'spikephase' -% cfg.channelcmb = cell-array, see CHANNELCOMBINATION -% cfg.bpfilter = 'no' or 'yes' bandpass filter -% cfg.bpfreq = bandpass frequency range, specified as [low high] in Hz -% cfg.bpfiltord = bandpass filter order - -% Undocumented local options: -% cfg.bpfilttype -% cfg.channel -% cfg.foi -% cfg.keeptrials -% cfg.output -% cfg.pad -% cfg.previous -% cfg.taper -% cfg.tapsmofrq -% cfg.version - -% Copyright (C) 2005, Robert Oostenveld -% -% $Log: spikeanalysis.m,v $ -% Revision 1.4 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.3 2006/04/20 09:58:34 roboos -% updated documentation -% -% Revision 1.2 2006/01/11 12:47:10 jansch -% implemented option 'rate', which computes either the average rate within each -% trial, or uses freqanalysis_mtmconvol to estimate a windowed spikerate. -% -% Revision 1.1 2005/12/05 10:33:38 roboos -% new implementation after an idea of Thilo -% - -fieldtripdefs - -% set the defaults -if ~isfield(cfg, 'method'), cfg.method = 'rate'; end -if ~isfield(cfg, 'channelcmb'), cfg.channelcmb = {'all', 'all'}; end -if ~isfield(cfg, 'bpfilter'), cfg.bpfilter = 'yes'; end -if ~isfield(cfg, 'bpfiltord'), cfg.bpfiltord = 4; end -if ~isfield(cfg, 'bpfilttype'), cfg.bpfilttype = 'but'; end -if ~isfield(cfg, 'bpfreq'), cfg.bpfreq = [30 90]; end - -if strcmp(cfg.method, 'rate'), - ntrials = length(data.trial); - nchans = length(data.label); - spikechan = zeros(nchans,1); - for i=1:ntrials - for j=1:nchans - spikechan(j) = spikechan(j) + all(data.trial{i}(j,:)==0 | data.trial{i}(j,:)==1); - end - end - chanindx = find(spikechan==ntrials); - nchans = length(chanindx); - label = data.label(chanindx); - - if ~isfield(cfg, 'toi'), - %compute the number of spikes within each trial and normalise for the triallength - rate = zeros(ntrials, nchans); - for i=1:ntrials - rate(i, :) = data.fsample*sum(data.trial{i}(chanindx, :), 2)/size(data.trial{i},2)'; - end - - spike = []; - spike.label = label(:); - spike.rate = rate; - elseif isfield(cfg, 'toi'), - if ~isfield(cfg, 'timwin'), error('no timewindow specified'); end; - %compute the spike-rate based on the DC-bin after fourier-transformation. CAVE: the - %data should NOT be baseline corrected. - tmpcfg = []; - tmpcfg.method = 'mtmconvol'; - tmpcfg.output = 'pow'; - tmpcfg.keeptrials= 'yes'; - tmpcfg.toi = cfg.toi; - tmpcfg.t_ftimwin = cfg.timwin; - tmpcfg.tapsmofrq = nan; - tmpcfg.taper = 'rectwin'; - tmpcfg.foi = 0; - tmpcfg.channel = label; - tmpcfg.pad = 'maxperlen'; - tmpfreq = freqanalysis(tmpcfg, data); - rate = sqrt(squeeze(tmpfreq.powspctrm)/2)*data.fsample; - - spike = []; - spike.label = label(:); - spike.rate = rate; - end -elseif strcmp(cfg.method, 'spikephase'), - % select the combination of spike and lfp channels to be analyzed - if isfield(cfg, 'channelcmb') - cfg.channelcmb = channelcombination(cfg.channelcmb, data.label); - end - - % check whether the selection of channels is valid - ntrials = length(data.trial); - nchans = length(data.label); - spikechan = zeros(nchans,1); - for i=1:ntrials - for j=1:nchans - spikechan(j) = spikechan(j) + all(data.trial{i}(j,:)==0 | data.trial{i}(j,:)==1); - end - end - spikechan = spikechan==ntrials; - cmbsel = ones(size(cfg.channelcmb,1), 1); - for i=1:size(cfg.channelcmb,1) - cmbsel(i) = spikechan(strmatch(cfg.channelcmb{i,1}, data.label))==1 & ... - spikechan(strmatch(cfg.channelcmb{i,2}, data.label))==0; - end - - % select only the valid combinations - cfg.channelcmb = cfg.channelcmb(find(cmbsel),:); - fprintf('selected %d channel combinations\n', size(cfg.channelcmb,1)); - - spksel = unique(match_str(data.label, cfg.channelcmb(:,1))); - lfpsel = unique(match_str(data.label, cfg.channelcmb(:,2))); - fprintf('selected %d spike channels\n', length(spksel)); - fprintf('selected %d lfp channels\n', length(lfpsel)); - - % allocate the output structure - for i=1:size(cfg.channelcmb,1) - spike.phase{i} = []; - spike.amplitude{i} = []; - spike.trlnum{i} = []; - end - - for lfplop=lfpsel(:)' - fprintf('processing lfp channel %s ', data.label{lfplop}); - for i=1:ntrials - % perform the bandpass filter and hilbert transform - lfp = bandpassfilter(data.trial{i}(lfplop,:), data.fsample, cfg.bpfreq, cfg.bpfiltord, cfg.bpfilttype); - lfp = hilbert(lfp); - for spklop=spksel(:)' - % find the output combination - outputcmb = find(strcmp(data.label{lfplop}, cfg.channelcmb(:,2)) & strcmp(data.label{spklop}, cfg.channelcmb(:,1))); - if isempty(outputcmb) - % this analog channel is not combined with this spike channel - continue - else - fprintf('.'); - % find all spikes in this channel and this trial - sel = find(data.trial{i}(spklop,:)); - % remember the instantaneous phase and amplitude of the lfp channel - spike.phase{outputcmb} = [spike.phase{outputcmb} phase(lfp(sel)) ]; - spike.amplitude{outputcmb} = [spike.amplitude{outputcmb} abs(lfp(sel)) ]; - % remember the trial number in which the spike occurred - spike.trlnum{outputcmb} = [spike.trlnum{outputcmb} i*ones(1,length(sel))]; - end - end - end - fprintf('\n'); - end - - % wrap the phase estimate between 0 and 2*pi - for i=1:size(cfg.channelcmb,1) - tmp = spike.phase{i}; - tmp = rem(tmp, 2*pi); - tmp(tmp<0) = tmp(tmp<0) + 2*pi; - spike.phase{i} = tmp; - end - - % append the other information to the output - spike.channelcmb = cfg.channelcmb; -end - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: spikeanalysis.m,v 1.4 2008/09/22 20:17:44 roboos Exp $'; -% remember the configuration details of the input data -try, cfg.previous = data.cfg; end -% remember the exact configuration details in the output -spike.cfg = cfg; - diff --git a/external/fieldtrip/private/spikedetection.m b/external/fieldtrip/private/spikedetection.m deleted file mode 100644 index 26e13ed..0000000 --- a/external/fieldtrip/private/spikedetection.m +++ /dev/null @@ -1,500 +0,0 @@ -function [cfg, spike] = spikedetection(cfg) - -% SPIKEDETECTION -% -% Use as -% cfg = spikedetection(cfg) -% -% The configuration options can contain -% cfg.dataset = string with the input dataset -% cfg.output = string with the output dataset (default is determined automatic) -% cfg.dataformat = string with the output dataset format, see WRITE_FCDC_SPIKE -% cfg.method = string with the method to use, can be 'all', 'zthresh', 'ztrig', 'flank' -% cfg.interactive = 'yes' or 'no' -% cfg.timestampdefinition = 'orig' or 'sample' -% -% The default is to process the full dataset. You can select a latency range with -% cfg.latency = [begin end], default is [0 inf] -% or you can specify multiple latency segments with -% cfg.latency = [b1 e1; b2 e2; ...] -% -% Specific settings for the zthresh spike detection method are -% cfg.zthresh.neg = negative threshold, e.g. -3 -% cfg.zthresh.pos = positive threshold, e.g. 3 -% cfg.zthresh.offset = number of samples before peak (default = 16) -% cfg.zthresh.mindist = mininum distance in samples between detected peaks -% -% Specific settings for the flank spike detection method are -% cfg.flank.value = positive or negative threshold -% cfg.flank.offset = number of samples before peak -% cfg.flank.ztransform = 'yes' or 'no' -% cfg.flank.mindist = mininum distance in samples between detected peaks -% -% Furthermore, the configuration can contain options for preprocessing -% cfg.preproc.lpfilter = 'no' or 'yes' lowpass filter -% cfg.preproc.hpfilter = 'no' or 'yes' highpass filter -% cfg.preproc.bpfilter = 'no' or 'yes' bandpass filter -% cfg.preproc.lnfilter = 'no' or 'yes' line noise removal using notch filter -% cfg.preproc.dftfilter = 'no' or 'yes' line noise removal using discrete fourier transform -% cfg.preproc.medianfilter = 'no' or 'yes' jump preserving median filter -% cfg.preproc.lpfreq = lowpass frequency in Hz -% cfg.preproc.hpfreq = highpass frequency in Hz -% cfg.preproc.bpfreq = bandpass frequency range, specified as [low high] in Hz -% cfg.preproc.lnfreq = line noise frequency in Hz, default 50Hz -% cfg.preproc.lpfiltord = lowpass filter order -% cfg.preproc.hpfiltord = highpass filter order -% cfg.preproc.bpfiltord = bandpass filter order -% cfg.preproc.lnfiltord = line noise notch filter order -% cfg.preproc.medianfiltord = length of median filter -% cfg.preproc.lpfilttype = digital filter type, 'but' (default) or 'fir' -% cfg.preproc.hpfilttype = digital filter type, 'but' (default) or 'fir' -% cfg.preproc.bpfilttype = digital filter type, 'but' (default) or 'fir' -% cfg.preproc.lpfiltdir = filter direction, 'twopass' (default) or 'onepass' -% cfg.preproc.hpfiltdir = filter direction, 'twopass' (default) or 'onepass' -% cfg.preproc.bpfiltdir = filter direction, 'twopass' (default) or 'onepass' -% cfg.preproc.detrend = 'no' or 'yes' -% cfg.preproc.blc = 'no' or 'yes' -% cfg.preproc.blcwindow = [begin end] in seconds, the default is the complete trial -% cfg.preproc.hilbert = 'no' or 'yes' -% cfg.preproc.rectify = 'no' or 'yes' - -% Copyright (C) 2005-2008, Robert Oostenveld -% -% $Log: spikedetection.m,v $ -% Revision 1.11 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.10 2009/01/16 17:21:20 sashae -% added config tracking -% -% Revision 1.9 2009/01/07 10:15:19 roboos -% changed the read_data call to make consistent with the new (and now enforced) API of read_data instead of read_fcdc_data -% -% Revision 1.8 2008/10/02 15:32:21 sashae -% replaced call to createsubcfg with checkconfig -% -% Revision 1.7 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.6 2008/05/13 15:37:24 roboos -% switched to using read_data/header instead of the read_fcdc_data/header wrapper functions -% -% Revision 1.5 2008/02/04 17:17:34 roboos -% fixed begsample for multiple segments, thanks to Thilo -% -% Revision 1.4 2008/01/30 10:50:41 roboos -% added cfg.timestampdefinition -% -% Revision 1.3 2008/01/14 21:34:39 roboos -% removed automatic output directory -% added cfg.channelprefix, default is empty -% icleaned up the defaults -% -% Revision 1.2 2008/01/14 20:12:30 roboos -% fixed bug in call to createsubcfg for preproc -% -% Revision 1.1 2008/01/14 17:07:36 roboos -% new version, based on functionality lifted from spikedownsample -% -% Revision 1.33 2007/03/21 17:27:30 roboos -% updated documentation - -fieldtripdefs -cfg = checkconfig(cfg, 'trackconfig', 'on'); - -% set the general defaults -if ~isfield(cfg, 'dataset'), cfg.dataset = []; end -if ~isfield(cfg, 'output'), cfg.output = []; end -if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end -if ~isfield(cfg, 'channelprefix'), cfg.channelprefix = []; end -if ~isfield(cfg, 'latency'), cfg.latency = [0 inf]; end -% set the specific defaults -if ~isfield(cfg, 'method'), cfg.method = 'zthresh'; end -if ~isfield(cfg, 'adjustselection'), cfg.adjustselection = 'yes'; end -if ~isfield(cfg, 'interactive'), cfg.interactive = 'no'; end -if ~isfield(cfg, 'chanvals'), cfg.chanvals = []; end - -% set the defaults for the various spike detection methods -switch cfg.method - case 'all' - if ~isfield(cfg, 'all'), cfg.all = []; end - case 'zthresh' - if ~isfield(cfg, 'zthresh'), cfg.zthresh = []; end - if ~isfield(cfg.zthresh, 'neg'), cfg.zthresh.neg = -3; end - if ~isfield(cfg.zthresh, 'pos'), cfg.zthresh.pos = 3; end - if ~isfield(cfg.zthresh, 'offset'), cfg.zthresh.offset = -16; end % in samples - if ~isfield(cfg.zthresh, 'mindist'), cfg.zthresh.mindist = 0; end % in samples - case 'flank' - if ~isfield(cfg, 'flank'), cfg.flank = []; end - if ~isfield(cfg.flank, 'ztransform'), cfg.flank.ztransform = 'yes'; end - if ~isfield(cfg.flank, 'value'), cfg.flank.value = 1.5; end % trigger threshold value - if ~isfield(cfg.flank, 'offset'), cfg.flank.offset = 6; end % in samples - if ~isfield(cfg.flank, 'mindist'), cfg.flank.mindist = 0; end % in samples - otherwise - error('unsupported option for cfg.method'); -end - -% ensure that the preproc specific options are located in the preproc substructure -cfg = checkconfig(cfg, 'createsubcfg', {'preproc'}); - -status = mkdir(cfg.output); -if ~status - error(sprintf('error creating spike output dataset %s', cfg.output)); -end - -% read the header of the completete dataset -hdr = read_header(cfg.dataset); -cfg.channel = channelselection(cfg.channel, hdr.label); -chansel = match_str(hdr.label, cfg.channel); - -if strcmp(cfg.timestampdefinition, 'sample') - % the default would be to keep the original definition of timestamps as determined from looking at the file - % here the definition of timestamps is changed to correspond with samples at the original sampling rate - hdr.TimeStampPerSample = 1; - hdr.FirstTimeStamp = 1; - hdr.LastTimeStamp = hdr.nSamples*hdr.nTrials; -end - -if hdr.nSamples<1 - error('the input dataset contains no samples'); -elseif length(chansel)<1 - error('the input selection contains no channels'); -end - -% give some feedback, based on the complete data -fprintf('data contains %10d channels\n', hdr.nChans); -fprintf('selected %10d channels\n', length(chansel)); -numsample = []; -numsegment = size(cfg.latency,1); -for j=1:numsegment - begsample(j) = max(round(cfg.latency(j,1) * hdr.Fs + 1), 1); - endsample(j) = min(round(cfg.latency(j,2) * hdr.Fs ), hdr.nSamples); - numsample(j) = endsample(j) - begsample(j) + 1; - cfg.latency(j,1) = (begsample(j)-1)/hdr.Fs; - cfg.latency(j,2) = (endsample(j) )/hdr.Fs; -end -numsample = sum(numsample); -fprintf('data contains %10d samples\n', hdr.nSamples); -fprintf('selected %10d samples in %d segments\n', numsample, numsegment); - -s = floor(hdr.nSamples ./ hdr.Fs); -m = floor(s/60); -h = floor(m/60); -m = m - 60*h; -s = s - 60*m - 60*60*h; -fprintf('duration of data %02dh:%02dm:%02ds\n', h, m, s); - -s = floor(numsample ./ hdr.Fs); -m = floor(s/60); -h = floor(m/60); -m = m - 60*h; -s = s - 60*m - 60*60*h; -fprintf('duration of selection %02dh:%02dm:%02ds\n', h, m, s); - -fprintf('estimated memory usage %d MB\n', round((numsample*(8+8+2))/(1024^2))); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% process each channel separetely -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -for i=chansel(:)' - fprintf('processing channel %d, ''%s''\n', i, hdr.label{i}); - - % remain in the interactive phase as long as the user desires - % the interactive loop is also used once when imediately writing to file - runloop = true; - newdata = true; - - while runloop - % the loop is used once when writing to file, or multiple times for interactive use - runloop = false; - - % reading and filtering may be repeatedly done if the user interactively specified another latency selection - if newdata - fprintf('++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n'); - numsegment = size(cfg.latency,1); - clear begsample endsample numsample - for j=1:numsegment - begsample(j) = max(round(cfg.latency(j,1) * hdr.Fs + 1), 1); - endsample(j) = min(round(cfg.latency(j,2) * hdr.Fs ), hdr.nSamples); - numsample(j) = endsample(j) - begsample(j) + 1; - cfg.latency(j,1) = (begsample(j)-1)/hdr.Fs; - cfg.latency(j,2) = (endsample(j) )/hdr.Fs; - end - % read from a single channel and concatenate the segments into one vector - org = zeros(1,sum(numsample)); - for j=1:numsegment - fprintf('reading channel %s, latency from %f to %f\n', hdr.label{i}, cfg.latency(j,1), cfg.latency(j,2)); - buf = read_data(cfg.dataset, 'header', hdr, 'begsample', begsample(j), 'endsample', endsample(j), 'chanindx', i); - if j==1 - begsegment = 1; - endsegment = numsample(j); - else - begsegment = sum(numsample(1:j-1)) + 1; - endsegment = sum(numsample(1:j )) ; - end - % concatenate the data into one large vector - org(begsegment:endsegment) = buf; - clear buf; - end - % apply preprocessing - fprintf('applying preprocessing options\n'); - dat = preproc(org, hdr.label(i), hdr.Fs, cfg.preproc); - end % if newdata - - peaks = []; - - % this while loop is used to automatically adjust the spike threshold - % if too few/ too many waveforms were selected - % it will break out of the while loop at the end - numadjustment = 1; - while (1) - - switch cfg.method - case 'all' - % place a spike marker at each 32 samples in the signal - % this makes a lot of waveforms that together reconstruct the complete continuous data - for j=1:32:(length(dat)-32) - peaks = [peaks j]; - end - - case 'zthresh' - % do peak detection on z-transformed signal - zdat = (dat-mean(dat))./std(dat); - if ~isinf(cfg.zthresh.neg) - % mindist is expressed in samples rather than sec - dum = peakdetect3(-zdat, -cfg.zthresh.neg, cfg.zthresh.mindist); - peaks = [peaks dum]; - end - if ~isinf(cfg.zthresh.pos) - % mindist is expressed in samples rather than sec - dum = peakdetect3( zdat, cfg.zthresh.pos, cfg.zthresh.mindist); - peaks = [peaks dum]; - end - % the mindist is not honored for spikes followed immediately by a spike of the other sign - peaks = sort(peaks); - % the begin of each waveform is shifted, to ensure that the spike is in the middle - peaks = peaks - cfg.zthresh.offset; - % ensure that no spikes are found within the first and last segment of the data - % since it is not possible to extract complete waveforms there - peaks(find(peaks<32)) = []; - peaks(find((length(dat)-peaks)<32)) = []; - - % --- store the thres val for current channnel - cfg.chanvals(find(chansel==i),1:3) = [cfg.zthresh.neg cfg.zthresh.pos cfg.zthresh.mindist]; - - case 'flank' - if strcmp(cfg.flank.ztransform, 'yes') - zdat = (dat-mean(dat))./std(dat); - else - zdat = dat; - end - if cfg.flank.value>0 - peaks = find(diff(zdat>cfg.flank.value)==1); - elseif cfg.flank.value<0 - peaks = find(diff(zdatcfg.flank.mindist); - end - - % the flanks are shifted by one sample due to the diff - peaks = peaks + 1; - % the begin of each waveform is shifted, to ensure that the spike is in the middle - peaks = peaks - cfg.flank.offset; - % ensure that no spikes are found within the first and last segment of the data - % since it is not possible to extract complete waveforms there - peaks(find(peaks<32)) = []; - peaks(find((length(dat)-peaks)<32)) = []; - - % --- store the thres val for current channnel - cfg.chanvals(find(chansel==i),1:3) = [cfg.flank.value NaN cfg.flank.mindist]; - - end % cfg.method - - fprintf('detected %d (avg. rate: %.2f)', length(peaks), (length(peaks) / (length(dat)/hdr.Fs) )); - - % check that n detected spikes is "reasonable" (more than 5 - % percent, less than 80%), otherwise changes the settings - % note: 32 samples per waveform, length(dat)/32 possible waveforms, hdr.Fs - if ~strcmp(cfg.adjustselection, 'yes') - % no automatic adjustment needs to be done - break; - elseif numadjustment>10 - % do not auto-adjust more than 10 times - break; - else - adjustValue = []; - if ( (length(peaks) / (length(dat)/hdr.Fs) ) < 4) - fprintf(', less than avg. rate of 4 spikes per sec. detected.\n'); - adjustValue = 1+(numadjustment*0.1); - elseif ~strcmp(cfg.method,'all') & ( (length(peaks) / (length(dat)/hdr.Fs) ) > 600) - fprintf(', more than avg. rate of 600 spikes per sec. detected.\n'); - adjustValue = 1-(numadjustment*0.1); - else - % the detected spike rate is "reasonable", no further adjustments neccessary - break; - end - - if ~isempty(adjustValue) - maxDat = max(abs(zdat))*0.95; % the minimum threshold value to ensure thres. is in correct range - if strcmp(cfg.method,'zthresh') - cfg.zthresh.neg = max([cfg.zthresh.neg*adjustValue -maxDat]); - cfg.zthresh.pos = min([cfg.zthresh.pos*adjustValue maxDat]); - fprintf('... adjusted thresh. to %.2f / %.2f\n',cfg.zthresh.neg, cfg.zthresh.pos); - elseif strcmp(cfg.method,'flank') - cfg.flank.value = min([cfg.flank.value*adjustValue maxDat]); - fprintf('... adjusted thresh. to %.2f\n',cfg.flank.value); - end - end - numadjustment = numadjustment + 1; - end - - end % while automatic threshold adjustment - - if strcmp(cfg.interactive, 'no') - % construct a structure like this - % spike.label = 1xNchans cell-array, with channel labels - % spike.waveform = 1xNchans cell-array, each element contains a matrix (Nsamples X Nspikes), can be empty - % spike.timestamp = 1xNchans cell-array, each element contains a vector (1 X Nspikes) - % spike.unit = 1xNchans cell-array, each element contains a vector (1 X Nspikes) - % note that it only contains a single channel - - spike = []; - if isempty(cfg.channelprefix) - % the label should be a cell-array of length one - spike.label = hdr.label(i); - else - % add a prefix to the channel name - spike.label = {[cfg.channelprefix '_' hdr.label{i}]}; - end - spike.waveform = {zeros(32,length(peaks))}; % FIXME implement variable length waveforms - spike.timestamp = {zeros(1,length(peaks), class(hdr.FirstTimeStamp))}; - spike.unit = {zeros(1,length(peaks))}; - - for j=1:length(peaks) - begsmp = peaks(j); - endsmp = peaks(j) + 32 - 1; % FIXME implement a peak shift - spike.waveform{1}(:,j) = dat(begsmp:endsmp); - spike.timestamp{1}(j) = hdr.FirstTimeStamp + typecast((peaks(j)-1)*hdr.TimeStampPerSample, class(hdr.FirstTimeStamp)); - end - - % write the spike data to a new file - datafile = fullfile(cfg.output, spike.label{1}); % this is without filename extension - fprintf(', writing to %s\n', datafile); - write_fcdc_spike(datafile, spike, 'dataformat', cfg.dataformat, 'fsample', hdr.Fs, 'TimeStampPerSample', hdr.TimeStampPerSample*hdr.Fs); - - % jump out of the interactive loop - runloop = false; - newdata = false; - - elseif strcmp(cfg.interactive, 'yes') - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % show the spike data on screen - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - clf - fprintf('\n\n'); - fprintf('------------------------------------------------------------\n'); - fprintf('Channel %s, detected spike rate is %d per second, ', hdr.label{i}, round(length(peaks)./(cfg.latency(2)-cfg.latency(1)))); - fprintf('change settings or press return to accept\n'); - fprintf('------------------------------------------------------------\n'); - - % use the z-transformed data - dat = zdat; - - subplot('position', [0.1 0.3 0.1 0.6]); - [hdat, hval] = hist(double(dat), 256); - h = plot(hdat, hval); - x = [0 max(hdat)*2]; - if strcmp(cfg.method, 'zthresh') - y = [cfg.zthresh.neg cfg.zthresh.neg]; - line(x, y, 'color', 'g'); - y = [cfg.zthresh.pos cfg.zthresh.pos]; - line(x, y, 'color', 'g'); - elseif strcmp(cfg.method, 'flank') - y = [cfg.flank.value cfg.flank.value]; - line(x, y, 'color', 'g'); - end - abc = axis; abc(1) = 0; abc(2) = 1.2*max(hdat); axis(abc); - - subplot('position', [0.3 0.3 0.6 0.6]); - - if size(cfg.latency,1)==1 - % create a time axis that matches the data - time = linspace(cfg.latency(1,1), cfg.latency(1,2), length(dat)); - else - % the data consiss of multiple concatenated segments, create a dummy time axis - warning('the displayed time axis does not represent real time in the recording'); - time = (0:(length(dat)-1))/hdr.Fs; - end - h = plot(time, dat); - - if strcmp(cfg.method, 'zthresh') - x = [time(1) time(end)]; - y = [cfg.zthresh.neg cfg.zthresh.neg]; - line(x, y, 'color', 'g'); - x = [time(1) time(end)]; - y = [cfg.zthresh.pos cfg.zthresh.pos]; - line(x, y, 'color', 'g'); - elseif strcmp(cfg.method, 'flank') - x = [time(1) time(end)]; - y = [cfg.flank.value cfg.flank.value]; - line(x, y, 'color', 'g'); - end - - spiketime = (peaks-1)/hdr.Fs; - spiketime = spiketime + time(1); - hold on - plot(spiketime, zeros(size(peaks)), 'r.'); - hold off - abc = axis; abc(1) = time(1); abc(2) = time(end); axis(abc); - - subplot('position', [0.3 0.1 0.6 0.1]); - plot(spiketime, zeros(size(peaks)), '.'); - abc = axis; abc(1) = time(1); abc(2) = time(end); axis(abc); - - % start with a wider figure already, this prevents manual resizing - set(gcf,'Position',[42 302 879 372],'Color','w') - - % ask for a new latency selection - tmp=(cfg.latency'); oldval = sprintf('%.1f %.1f, ',tmp(:)); - [cfg.latency, newdata] = smartinput(['cfg.latency [' oldval '] = '], cfg.latency); - runloop = newdata; - - fn = fieldnames(getfield(cfg, cfg.method)); - for k=1:length(fn) - eval(['oldval = cfg.' cfg.method '.' fn{k} ';']); - if isnumeric(oldval), oldvalinf = sprintf('%.1f',oldval); else, oldvalinf = oldval; end - [newval, changed] = smartinput(sprintf('cfg.%s.%s [%s]= ', cfg.method, fn{k},oldvalinf), oldval); - eval(['cfg.' cfg.method '.' fn{k} ' = newval;']); - runloop = (runloop | changed); - end - - if ~runloop - warning('detected spikes are not written to disk in interactive mode'); - end - - end % elseif interactive - - end % while runloop - -end % for each file - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% add the version details of this function call to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: spikedetection.m,v 1.11 2009/01/20 13:01:31 sashae Exp $'; diff --git a/external/fieldtrip/private/spikedownsample.m b/external/fieldtrip/private/spikedownsample.m deleted file mode 100644 index 8eebd82..0000000 --- a/external/fieldtrip/private/spikedownsample.m +++ /dev/null @@ -1,350 +0,0 @@ -function [cfg] = spikedownsample(cfg) - -% SPIKEDOWNSAMPLE takes electrophysiological data that was continuoudly -% sampled at 32KHz and preprocesses and downsamples it to obtain the LFP -% data, which can subsequently be processed in more detail. -% -% Use as -% [cfg] = spikedownsample(cfg) -% -% The configuration should contain -% cfg.dataset = string with the input dataset -% cfg.output = string with the output dataset (default is determined automatic) -% cfg.dataformat = string with the output dataset format, see WRITE_DATA -% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), -% see CHANNELSELECTION for details -% cfg.fsample = desired sampling frequency in Hz (default = 1000) -% cfg.method = resampling method, can be 'resample', 'decimate' or 'downsample' -% cfg.timestampdefinition = 'orig' or 'sample' -% cfg.channelprefix = string, will be added to channel name, e.g. 'lfp' -> 'lfp_ncs001' (default = []) -% cfg.calibration = optional scaling factor to apply to the data to convert it in uV, see below -% -% The Neuralynx acquisition system at the FCDC in Nijmegen makes use of -% Plexon headstages which have a amplification of 20x. The data that is -% written by the Neuralynx acquisition software therefore is 20x larger -% than the true microvolt values. When operating SPIKEDOWNSAMPLE on the -% *.ncs files that are recorded with the Neuralynx Cheetah software, the -% calibration should be set to 1/20. The raw dma file (*.nrd) and the -% splitted DMA files contains AD values that are not scaled in uV and -% require an additional factor of 64x. If you operate SPIKEDOWNSAMPLE on -% raw dma files or on splitted DMA files, the calibration should be set to -% 1/(64*20). -% -% The default is to process the full dataset. You can select a latency range with -% cfg.latency = [begin end], default is [0 inf] -% or you can specify multiple latency segments with -% cfg.latency = [b1 e1; b2 e2; ...] -% -% Furthermore, the configuration can contain the following preprocessing options -% cfg.preproc.lpfilter = 'no' or 'yes' lowpass filter -% cfg.preproc.hpfilter = 'no' or 'yes' highpass filter -% cfg.preproc.bpfilter = 'no' or 'yes' bandpass filter -% cfg.preproc.lnfilter = 'no' or 'yes' line noise removal using notch filter -% cfg.preproc.dftfilter = 'no' or 'yes' line noise removal using discrete fourier transform -% cfg.preproc.medianfilter = 'no' or 'yes' jump preserving median filter -% cfg.preproc.lpfreq = lowpass frequency in Hz -% cfg.preproc.hpfreq = highpass frequency in Hz -% cfg.preproc.bpfreq = bandpass frequency range, specified as [low high] in Hz -% cfg.preproc.lnfreq = line noise frequency in Hz, default 50Hz -% cfg.preproc.lpfiltord = lowpass filter order -% cfg.preproc.hpfiltord = highpass filter order -% cfg.preproc.bpfiltord = bandpass filter order -% cfg.preproc.lnfiltord = line noise notch filter order -% cfg.preproc.medianfiltord = length of median filter -% cfg.preproc.lpfilttype = digital filter type, 'but' (default) or 'fir' -% cfg.preproc.hpfilttype = digital filter type, 'but' (default) or 'fir' -% cfg.preproc.bpfilttype = digital filter type, 'but' (default) or 'fir' -% cfg.preproc.lpfiltdir = filter direction, 'twopass' (default) or 'onepass' -% cfg.preproc.hpfiltdir = filter direction, 'twopass' (default) or 'onepass' -% cfg.preproc.bpfiltdir = filter direction, 'twopass' (default) or 'onepass' -% cfg.preproc.detrend = 'no' or 'yes' -% cfg.preproc.blc = 'no' or 'yes' -% cfg.preproc.blcwindow = [begin end] in seconds, the default is the complete trial -% cfg.preproc.hilbert = 'no' or 'yes' -% cfg.preproc.rectify = 'no' or 'yes' - -% Copyright (C) 2005-2009, Robert Oostenveld -% -% $Log: spikedownsample.m,v $ -% Revision 1.46 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.45 2009/01/16 17:21:20 sashae -% added config tracking -% -% Revision 1.44 2009/01/07 10:45:35 roboos -% improved the documentation -% -% Revision 1.43 2009/01/07 10:37:19 roboos -% replaced ADtoUV with cfg.calibration, added explaination to the help -% added some configuration checking -% -% Revision 1.42 2008/12/15 15:07:42 roboos -% give error if cfg.ADtoUV is missing in case of neuralynx_dma or neuralynx_sdma -% -% Revision 1.41 2008/12/15 14:57:06 roboos -% added option cfg.ADtoUV, needed for neuralynx_dma and neuralynx_sdma input datasets -% -% Revision 1.40 2008/10/02 15:32:21 sashae -% replaced call to createsubcfg with checkconfig -% -% Revision 1.39 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.38 2008/09/22 19:43:36 roboos -% switched from write_fcdc_data to write_data -% -% Revision 1.37 2008/07/21 20:10:47 roboos -% updated documentation -% -% Revision 1.36 2008/05/13 15:37:24 roboos -% switched to using read_data/header instead of the read_fcdc_data/header wrapper functions -% -% Revision 1.35 2008/01/30 10:50:41 roboos -% added cfg.timestampdefinition -% -% Revision 1.34 2008/01/14 21:38:01 roboos -% the functionality of the downsampling should have remained the same, but the cfg is not backward compatible -% removed all code related to spikes and mua, only downsampling once remains -% moved all cfg.lfp options into cfg directly -% removed automatic output directory generation -% added cfg.channelprefix to distinguish the channels and the output files -% the function will not return a data structure any more, only the cfg -% -% Revision 1.33 2007/03/21 17:27:30 roboos -% updated documentation - -fieldtripdefs -cfg = checkconfig(cfg, 'trackconfig', 'on'); - -% set the general defaults -if ~isfield(cfg, 'dataset'), cfg.dataset = []; end -if ~isfield(cfg, 'output'), cfg.output = []; end -if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end -if ~isfield(cfg, 'channelprefix'), cfg.channelprefix = []; end -if ~isfield(cfg, 'latency'), cfg.latency = [0 inf]; end -% set the specific defaults -if ~isfield(cfg, 'fsample'), cfg.fsample = 1000; end -%if ~isfield(cfg, 'method'), cfg.method = []; end - -if ~isfield(cfg, 'calibration') - if filetype(cfg.dataset, 'neuralynx_dma') || filetype(cfg.dataset, 'neuralynx_sdma') - error('You must specify cfg.calibration in case of neuralynx_dma or neuralynx_sdma'); - else - cfg.calibration = 1; - end -end - -% check that the input cfg is valid for this function -cfg = checkconfig(cfg, 'required', {'method', 'calibration', 'dataformat'}); -cfg = checkconfig(cfg, 'forbidden', {'ADtoUV'}); - -% ensure that the preproc specific options are located in the preproc substructure -cfg = checkconfig(cfg, 'createsubcfg', {'preproc'}); - -status = mkdir(cfg.output); -if ~status - error(sprintf('error creating LFP output dataset %s', cfg.output)); -end - -% read the header of the completete dataset -hdr = read_header(cfg.dataset); -cfg.channel = channelselection(cfg.channel, hdr.label); -chansel = match_str(hdr.label, cfg.channel); - -if strcmp(cfg.timestampdefinition, 'sample') - % the default would be to keep the original definition of timestamps as determined from looking at the file - % here the definition of timestamps is changed to correspond with samples at the original sampling rate - hdr.TimeStampPerSample = 1; - hdr.FirstTimeStamp = 1; - hdr.LastTimeStamp = hdr.nSamples*hdr.nTrials; -end - -if hdr.nSamples<1 - error('the input dataset contains no samples'); -elseif length(chansel)<1 - error('the input selection contains no channels'); -end - -% give some feedback, based on the complete data -fprintf('data contains %10d channels\n', hdr.nChans); -fprintf('selected %10d channels\n', length(chansel)); -numsample = []; -numsegment = size(cfg.latency,1); -for j=1:numsegment - begsample(j) = max(round(cfg.latency(j,1) * hdr.Fs + 1), 1); - endsample(j) = min(round(cfg.latency(j,2) * hdr.Fs ), hdr.nSamples); - numsample(j) = endsample(j) - begsample(j) + 1; - cfg.latency(j,1) = (begsample(j)-1)/hdr.Fs; - cfg.latency(j,2) = (endsample(j) )/hdr.Fs; -end -numsample = sum(numsample); -fprintf('data contains %10d samples\n', hdr.nSamples); -fprintf('selected %10d samples in %d segments\n', numsample, numsegment); - -s = floor(hdr.nSamples ./ hdr.Fs); -m = floor(s/60); -h = floor(m/60); -m = m - 60*h; -s = s - 60*m - 60*60*h; -fprintf('duration of data %02dh:%02dm:%02ds\n', h, m, s); - -s = floor(numsample ./ hdr.Fs); -m = floor(s/60); -h = floor(m/60); -m = m - 60*h; -s = s - 60*m - 60*60*h; -fprintf('duration of selection %02dh:%02dm:%02ds\n', h, m, s); - -fprintf('estimated memory usage %d MB\n', round((numsample*(8+8+2))/(1024^2))); - -% determine the exact sampling frequency for the LFP and MUA -fac = hdr.Fs/cfg.fsample; -if strcmp(cfg.method, 'resample'); - % this works with arbitrary changes in the frequency -else - % this requires an integer downsampling fraction - fac = round(fac); - cfg.fsample = hdr.Fs/fac; -end - -if numsegment==1 - % determine the timestamps of the first and last sample after downsampling - tsoff = cast(0, class(hdr.FirstTimeStamp)); - tsbeg = double(hdr.FirstTimeStamp - tsoff); - tsend = double(hdr.LastTimeStamp - tsoff); - tsdif = (tsend-tsbeg)/(hdr.nSamples-1); % should be the same as hdr.TimeStampPerSample - % this applies to all samples in the datafile, i.e. not on the selected latency window - resampled_tsbeg = tsbeg + ((fac-1)/2)*tsdif; - resampled_tsend = tsend - ((fac-1)/2)*tsdif; - resampled_tsdif = fac * tsdif; - % this applies to the selected latency window - selected_tsbeg = double(hdr.FirstTimeStamp - tsoff) + (begsample-1)*tsdif; - selected_tsend = double(hdr.FirstTimeStamp - tsoff) + (endsample-1)*tsdif; - resampled_selected_tsbeg = selected_tsbeg + ((fac-1)/2)*tsdif; - resampled_selected_tsend = selected_tsend - ((fac-1)/2)*tsdif; - % these should be integers, but will be casted to uint32 or uint64 later - resampled_selected_tsbeg = round(resampled_selected_tsbeg); - resampled_selected_tsend = round(resampled_selected_tsend); - resampled_tsdif ; % this remains a double -else - warning('multiple data segments were selected, timestamps are invalid'); -end - -% process each channel separetely -for i=chansel(:)' - fprintf('reading channel %d, ''%s''\n', i, hdr.label{i}); - - % read the data of a single channel and concatenate into one vector - org = zeros(1,sum(numsample)); - for j=1:numsegment - buf = read_data(cfg.dataset, 'header', hdr, 'begsample', begsample(j), 'endsample', endsample(j), 'chanindx', i); - - % apply the optional calibration to the data to ensure that the numbers represent uV - if cfg.calibration~=1 - buf = cfg.calibration * buf; - end - - if j==1 - begsegment = 1; - endsegment = numsample(j); - else - begsegment = numsample(j-1) + 1; - endsegment = sum(numsample(1:j)); - end - % concatenate the data into one large vector - org(begsegment:endsegment) = buf; - clear buf; - end - label = hdr.label(i); % this should be cell-array for preproc - - % apply preprocessing and downsample - fprintf('preprocessing\n'); - dat = preproc(org, label, hdr.Fs, cfg.preproc); - dat = myresample(dat, hdr.Fs, cfg.fsample, cfg.method); - - chanhdr = []; - chanhdr.nChans = 1; - chanhdr.nTrials = 1; % since continuous - chanhdr.nSamplesPre = 1; % since continuous - chanhdr.Fs = cfg.fsample; - chanhdr.nSamples = length(dat); - if isempty(cfg.channelprefix) - % the label should be a cell-array of length one - chanhdr.label = hdr.label(i); - else - % add a prefix to the channel name - chanhdr.label = {[cfg.channelprefix '_' hdr.label{i}]}; - end - if numsegment==1 - chanhdr.FirstTimeStamp = resampled_selected_tsbeg; - chanhdr.LastTimeStamp = resampled_selected_tsend; - chanhdr.TimeStampPerSample = resampled_tsdif; - else - % these are not defined in case of multiple segments - warning('multiple data segments were selected, timestamps are invalid'); - chanhdr.FirstTimeStamp = nan; - chanhdr.LastTimeStamp = nan; - chanhdr.TimeStampPerSample = nan; - end - - % the output file contains the new channel name - datafile = fullfile(cfg.output, chanhdr.label{1}); % this is without filename extension - fprintf('writing to file ''%s''\n', datafile); - write_data(datafile, dat, 'header', chanhdr, 'dataformat', cfg.dataformat); - - % keep memory tidy - clear dat - -end % for each file - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% add the version details of this function call to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: spikedownsample.m,v 1.46 2009/01/20 13:01:31 sashae Exp $'; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION for the resampling -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function dat = myresample(dat, Fold, Fnew, method); -if Fold==Fnew - return -end -switch method - case 'resample' - if ~isa(dat, 'double') - typ = class(dat); - dat = typecast(dat, 'double'); - dat = resample(dat, Fnew, Fold); % this requires a double array - dat = typecast(dat, typ); - else - dat = resample(dat, Fnew, Fold); - end - case 'decimate' - fac = round(Fold/Fnew); - if ~isa(dat, 'double') - typ = class(dat); - dat = typecast(dat, 'double'); - dat = decimate(dat, fac); % this requires a double array - dat = typecast(dat, typ); - else - dat = decimate(dat, fac); % this requires a double array - end - case 'downsample' - fac = Fold/Fnew; - dat = decimate(dat, fac); - otherwise - error('unsupported resampling method'); -end - diff --git a/external/fieldtrip/private/spikefixdmafile.m b/external/fieldtrip/private/spikefixdmafile.m deleted file mode 100644 index f19d964..0000000 --- a/external/fieldtrip/private/spikefixdmafile.m +++ /dev/null @@ -1,116 +0,0 @@ -function spikefixdmafile(cfg) - -% SPIKEFIXDMAFILE fixes the problem in DMA files due to stopping -% and restarting the acquisition. It takes one Neuralynx DMA file and -% and creates seperate DMA files, each corresponding with one continuous -% section of the recording. -% -% Use as -% spikefixdmafile(cfg); -% where the configuration should contain -% cfg.dataset = string with the name of the DMA log file -% cfg.output = string with the name of the DMA log file, (default is determined automatic) -% cfg.numchans = number of channels (default = 256) -% -% See also SPIKESPLITTING - -% Copyright (C) 2008, Robert Oostenveld -% -% $Log: spikefixdmafile.m,v $ -% Revision 1.6 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.5 2008/08/13 14:20:59 roboos -% fixed some bugs -% -% Revision 1.4 2008/08/13 10:38:50 roboos -% fixed fprintf bug and number of additional channels to 18 -% -% Revision 1.3 2008/08/13 10:22:40 roboos -% changed the logic for jumping in the file -% -% Revision 1.2 2008/08/11 14:11:30 roboos -% added option cfg.numchans -% -% Revision 1.1 2008/06/16 18:47:05 roboos -% new implementation -% - -fieldtripdefs - -% set the general defaults -if ~isfield(cfg, 'dataset'), cfg.dataset = []; end -if ~isfield(cfg, 'output'), cfg.output = []; end -if ~isfield(cfg, 'numchans'), cfg.numchans = 256; end - -if isempty(cfg.output) - [p, f, x] = fileparts(cfg.dataset); - cfg.output = fullfile(p, f); % without the extension -end - -try - hdr = read_header(cfg.dataset); -catch - disp(lasterr); -end - -nchan = cfg.numchans+18; -fsample = 32556; -hdroffset = 16384; -count = 0; - -fin = fopen(cfg.dataset, 'rb'); -header = fread(fin, hdroffset, 'uchar=>uchar'); - - -% skip the part that has been processed sofar -fseek(fin, hdroffset, 'bof'); - -ok = 1; -while (ok) - - % find the beginning of the next section in the file - buf = zeros(1, nchan); - while (buf(1)~=2048 && buf(2)~=1) - % read a single block - buf = fread(fin, nchan, 'uint32=>uint32'); - if feof(fin) || length(buf)~=nchan - ok = 0; - break; - end - if (buf(1)~=2048 && buf(2)~=1) - % jump back to the original location and slide one sample forward to try again - fseek(fin, -(nchan-1)*4, 'cof'); - else - % jump back to the original location and continue with the copying to the new file - fseek(fin, -nchan*4, 'cof'); - end - end - - % the first file gets an "a" appended, the second a "b", etc. - count = count + 1; - filename = sprintf('%s%s.nrd', cfg.output, char(96+count)); - fprintf('writing section %d to "%s"\n', count, filename); - - fout = fopen(filename, 'wb'); - fwrite(fout, header, 'uchar'); - - while (buf(1)==2048 && buf(2)==1) - % read a single blockr - buf = fread(fin, nchan, 'uint32=>uint32'); - if feof(fin) || length(buf)~=nchan - ok = 0; - break; - end - if (buf(1)==2048 && buf(2)==1) - % write the block to the other file - fwrite(fout, buf, 'uint32'); - end - end - - fclose(fout); - -end % while ok - -fclose(fin); - diff --git a/external/fieldtrip/private/spikesimulation.m b/external/fieldtrip/private/spikesimulation.m deleted file mode 100644 index 81649a6..0000000 --- a/external/fieldtrip/private/spikesimulation.m +++ /dev/null @@ -1,136 +0,0 @@ -function data = spikesimulation(cfg) - -% SPIKESIMULATION -% -% Use as -% data = spikesimulation(cfg) -% and please look in the code for the cfg details. -% -% See also DIPOLESIMULATION, FREQSIMULATION - -% Copyright (C) 2007, Robert Oostenveld -% -% $Log: spikesimulation.m,v $ -% Revision 1.7 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.6 2008/06/17 16:13:18 sashae -% now using preproc_modules -% -% Revision 1.5 2007/12/12 10:03:31 roboos -% fixed a cvs conflict, not sure whether this version is operational -% -% Revision 1.4 2007/11/05 09:43:54 roboos -% some cleanup -% -% Revision 1.3 2007/11/01 16:33:57 roboos -% added cfg to output -% -% Revision 1.2 2007/11/01 16:32:21 roboos -% updated documentation, some small fixes -% - -fieldtripdefs - -% set the defaults -if ~isfield(cfg, 'trlduration'), cfg.trlduration = 1; end % in seconds -if ~isfield(cfg, 'nlfpchan'), cfg.nlfpchan = 10; end -if ~isfield(cfg, 'nspikechan'), cfg.nspikechan = 10; end -if ~isfield(cfg, 'spikerate'), cfg.spikerate = ones(cfg.nspikechan,1)*10; end -if ~isfield(cfg, 'ntrial'), cfg.ntrial = 10; end -if ~isfield(cfg, 'bpfreq'), cfg.bpfreq = [40 80]; end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% define the parameters -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% cfg.spikerate = [ 10 50 100 200]; -% cfg.nspikechan = 4; -% nlfpchan = 2; -% cfg.ntrial = 10; -% cfg.bpfreq = [40 80]; -% cfg.trlduration = 1; - -spikemix = eye(cfg.nspikechan, cfg.nlfpchan); -spikemix(5,1:2) = [0.5 0.5]; % mix with lfp chan 1 and 2 -spikemix(6,1:2) = [0.5 0.5]; % mix with lfp chan 1 and 2 - -% cfg.spikerate = 100*ones(1,cfg.nspikechan); % for each channel, per second -% cfg.spikerate = [100 100 300 300 100 300]; -fsample = 1000; -nsample = cfg.trlduration*fsample; -nchan = cfg.nlfpchan + cfg.nspikechan; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% create the data -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% start with empty data -data = []; -data.fsample = fsample; - -% create channel labels -k = 1; -for i=1:cfg.nlfpchan, data.label{k} = sprintf('lfp%02d', i); k=k+1; end -for i=1:cfg.nspikechan, data.label{k} = sprintf('spike%02d', i); k=k+1; end -data.label = data.label(:); - -for t=1:cfg.ntrial - fprintf('creating trial %d\n', t); - data.time{t} = (1:nsample)./fsample; - lfp = zeros(cfg.nlfpchan, nsample); - spike = zeros(cfg.nspikechan, nsample); - - for i=1:cfg.nlfpchan, - lfp(i,:) = preproc_bandpassfilter(randn(1,nsample), fsample, cfg.bpfreq); - end - - for i=1:cfg.nspikechan - % the spikes are generated from a probabilistic mix of the LFP channels - x = spikemix(i,:) * lfp; - % apply a non-linear mapping to the spike probablility, output should be defined between 0 and 1 - x = mapping(x); - % normalize the total probability to one - x = x./sum(x); - % randomly assign the spikes over the time series - spike(i,:) = ((cfg.spikerate(i)*nsample/fsample)*x)>=rand(size(x)); - end - - data.time{t} = (1:nsample)./fsample; - data.trial{t} = [lfp; spike]; - clear lfp spike -end - -% add the version details of this function call to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: spikesimulation.m,v 1.7 2008/09/22 20:17:44 roboos Exp $'; -% remember the configuration details -data.cfg = cfg; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION to strengthen the temporal strucure in the spike train -% by a non-linear modulation of the spike probability -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function y = mapping(x) -x = 6*(x-mean(x))/std(x); -y = 1./(1+exp(-x)); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% IIRFILTER simple brick wall filter in the frequency domain -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function s = myiirfilter(s, fs, fb, a) -f = fft(s); -ax = linspace(0, fs, length(s)); -fl = nearest(ax, fb(1))-1; -fh = nearest(ax, fb(2))+1; -f(1:fl) = a.*f(1:fl); -f(fh:end) = a.*f(fh:end); -s = real(ifft(f)); - diff --git a/external/fieldtrip/private/spikesort.m b/external/fieldtrip/private/spikesort.m new file mode 100644 index 0000000..cdf7ddf --- /dev/null +++ b/external/fieldtrip/private/spikesort.m @@ -0,0 +1,194 @@ +function [numA, numB, indA, indB] = spikesort(numA, numB, varargin); + +% SPIKESORT uses a variation on the cocktail sort algorithm in combination +% with a city block distance to achieve N-D trial pairing between spike +% counts. The sorting is not guaranteed to result in the optimal pairing. A +% linear pre-sorting algorithm is used to create good initial starting +% positions. +% +% The goal of this function is to achieve optimal trial-pairing prior to +% stratifying the spike numbers in two datasets by random removal of some +% spikes in the trial and channel with the largest numnber of spikes. +% Pre-sorting based on the city-block distance between the spike count +% ensures that as few spikes as possible are lost. +% +% Use as +% [srtA, srtB, indA, indB] = spikesort(numA, numB, ...) +% +% Optional arguments should be specified as key-value pairs and can include +% 'presort' number representing the column, 'rowwise' or 'global' +% +% Example +% numA = reshape(randperm(100*3), 100, 3); +% numB = reshape(randperm(100*3), 100, 3); +% [srtA, srtB, indA, indB] = spikesort(numA, numB); +% % check that the order is correct, the following should be zero +% numA(indA,:) - srtA +% numB(indB,:) - srtB +% +% See also COCKTAILSORT + +% Copyright (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: spikesort.m 952 2010-04-21 18:29:51Z roboos $ + + +% use global flag for debugging +global fb +if isempty(fb) + fb = 0; +end + +% get the options +presort = keyval('presort', varargin); + +if any(size(numA)~=size(numB)) + error('input dimensions should be the same'); +end + +bottom = 1; +top = size(numA,1); +swapped = true; +dist = zeros(1,top); % this will hold the distance between the trials in each pair +distswap = zeros(1,2); % this will hold the distance for two trials after swapping + +% this is to keep track of the row-ordering during sorting +sel = 1:size(numA,2); +numA(:,end+1) = 1:top; +numB(:,end+1) = 1:top; + +% compute the initial distance between the trial pairs using city block distance metric +for i=1:top + dist(i) = sum(abs(numA(i,sel)-numB(i,sel))); +end + +if fb + fprintf('initial cost = %d\n', sum(dist)); +end + +if isnumeric(presort) + % start by pre-sorting on the first column only + [dum, indA] = sort(numA(:,presort)); + [dum, indB] = sort(numB(:,presort)); + numA = numA(indA,:); + numB = numB(indB,:); +elseif strcmp(presort, 'rowwise') + full = cityblock(numA(:,sel), numB(:,sel)); + link = zeros(1,top); + for i=1:top + d = full(i,:); + d(link(1:(i-1))) = inf; + [m, ind] = min(d); + link(i) = ind; + end + indA = 1:top; + indB = link; + numB = numB(link,:); +elseif strcmp(presort, 'global') + full = cityblock(numA(:,sel), numB(:,sel)); + link = zeros(1,top); + while ~all(link) + [m, i] = min(full(:)); + [j, k] = ind2sub(size(full), i); + full(j,:) = inf; + full(:,k) = inf; + link(j) = k; + end + indA = 1:top; + indB = link; + numB = numB(link,:); +end + +% compute the initial distance between the trial pairs +% using city block distance metric +for i=1:top + dist(i) = sum(abs(numA(i,sel)-numB(i,sel))); +end + +if fb + fprintf('cost after pre-sort = %d\n', sum(dist)); +end + +while swapped + swapped = false; + + for i=bottom:(top-1) + + % compute the distances between the trials after swapping + % using city block distance metric + distswap(1) = sum(abs(numA(i,sel)-numB(i+1,sel))); + distswap(2) = sum(abs(numA(i+1,sel)-numB(i,sel))); + + costNow = sum(dist([i i+1])); + costSwp = sum(distswap); + + if costNow>costSwp % test whether the two elements are in the correct order + numB([i i+1], :) = numB([i+1 i], :); % let the two elements change places + dist([i i+1]) = distswap; % update the distance vector + swapped = true; + end + end + + % decreases `top` because the element with the largest value in the unsorted + % part of the list is now on the position top + top = top - 1; + + for i=top:-1:(bottom+1) + + % compute the distances between the trials after swapping + % using city block distance metric + distswap(1) = sum(abs(numA(i,sel)-numB(i-1,sel))); + distswap(2) = sum(abs(numA(i-1,sel)-numB(i,sel))); + costNow = sum(dist([i i-1])); + costSwp = sum(distswap); + + if costNow>costSwp + numB([i i-1], :) = numB([i-1 i], :); % let the two elements change places + dist([i i-1]) = distswap; % update the distance vector + swapped = true; + end + end + + % increases `bottom` because the element with the smallest value in the unsorted + % part of the list is now on the position bottom + bottom = bottom + 1; + +end % while swapped + +if fb + fprintf('final cost = %d\n', sum(dist)); +end + +indA = numA(:,end); +numA = numA(:,sel); +indB = numB(:,end); +numB = numB(:,sel); +end % function spikesort + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function d = cityblock(a, b) +d = zeros(size(a,1), size(b,1)); +for i=1:size(a,1) + for j=1:size(b,1) + d(i,j) = sum(abs(a(i,:)-b(j,:))); + end +end +end % function cityblock diff --git a/external/fieldtrip/private/spikesorting.m b/external/fieldtrip/private/spikesorting.m deleted file mode 100644 index 8cfe0c8..0000000 --- a/external/fieldtrip/private/spikesorting.m +++ /dev/null @@ -1,172 +0,0 @@ -function [spike] = spikesorting(cfg, spike); - -% SPIKESORTING performs clustering of spike-waveforms and returns the unit number to which each spike belongs. -% -% Use as -% [spike] = spikesorting(cfg, spike) -% -% The configuration can contain -% cfg.channel cell-array with channel selection (default = 'all'), see CHANNELSELECTION for details -% cfg.method 'kmeans', 'ward' -% cfg.feedback 'no', 'text', 'textbar', 'gui' (default = 'textbar') -% cfg.kmeans substructure with additional low-level options for this method -% cfg.ward substructure with additional low-level options for this method -% cfg.ward.distance 'L1', 'L2', 'correlation', 'cosine' -% -% The input spike structure can be imported using READ_FCDC_SPIKE and should contain -% spike.label = 1 x Nchans cell-array, with channel labels -% spike.waveform = 1 x Nchans cell-array, each element contains a matrix (Nsamples x Nspikes), can be empty -% spike.timestamp = 1 x Nchans cell-array, each element contains a vector (1 x Nspikes) -% spike.unit = 1 x Nchans cell-array, each element contains a vector (1 x Nspikes) -% -% See also READ_FCDC_SPIKE, SPIKEDOWNSAMPLE - -% Copyright (C) 2006-2007, Robert Oostenveld -% -% $Log: spikesorting.m,v $ -% Revision 1.5 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.4 2007/05/02 16:04:30 roboos -% added implementation of kmeans clustering, changed the function to reflect the updated data type -% -% Revision 1.3 2007/01/09 09:53:31 roboos -% removed neuralynx_ds, added plexon_plx -% the code currently is broken due to the changed behaviour of the reading functions -% -% Revision 1.2 2006/04/20 09:58:34 roboos -% updated documentation -% -% Revision 1.1 2006/03/10 13:43:08 roboos -% initial implementation, only ward clustering sofar -% - -fieldtripdefs - -% set the defaults -if ~isfield(cfg, 'feedback'), cfg.feedback = 'textbar'; end -if ~isfield(cfg, 'method'), cfg.method = 'ward'; end -if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end - -if isequal(cfg.method, 'ward') - if ~isfield(cfg, 'ward'), cfg.ward = []; end - if ~isfield(cfg.ward, 'distance'), cfg.ward.distance = 'L2'; end - if ~isfield(cfg.ward, 'optie'), cfg.ward.optie = 'ward'; end - if ~isfield(cfg.ward, 'aantal'), cfg.ward.aantal = 10; end - if ~isfield(cfg.ward, 'absoluut'), cfg.ward.absoluut = 1; end -end - -if isequal(cfg.method, 'kmeans') - if ~isfield(cfg, 'kmeans'), cfg.kmeans = []; end - if ~isfield(cfg.kmeans, 'aantal'), cfg.kmeans.aantal = 10; end -end - -% select the channels -cfg.channel = channelselection(cfg.channel, spike.label); -sel = match_str(spike.label, cfg.channel); -spike.label = spike.label(sel); -spike.waveform = spike.waveform(sel); -spike.timestamp = spike.timestamp(sel); -spike.unit = {}; % this will be assigned by the clustering - -nchan = length(spike.label); -for chanlop=1:nchan - label = spike.label{chanlop}; - waveform = spike.waveform{chanlop}; - timestamp = spike.timestamp{chanlop}; - nspike = size(waveform,2); - unit = zeros(1,nspike); - fprintf('sorting %d spikes in channel %s\n', nspike, label); - - switch cfg.method - case 'ward' - dist = ward_distance(cfg, waveform); - [grootte,ordening] = cluster_ward(dist,cfg.ward.optie,cfg.ward.absoluut,cfg.ward.aantal); - for i=1:cfg.ward.aantal - begsel = sum([1 grootte(1:(i-1))]); - endsel = sum([0 grootte(1:(i ))]); - unit(ordening(begsel:endsel)) = i; - end - - case 'kmeans' - unit = kmeans(waveform', cfg.kmeans.aantal)'; - - % 'sqEuclidean' - Squared Euclidean distance - % 'cityblock' - Sum of absolute differences, a.k.a. L1 - % 'cosine' - One minus the cosine of the included angle - % between points (treated as vectors) - % 'correlation' - One minus the sample correlation between - % points (treated as sequences of values) - - otherwise - error('unsupported clustering method'); - end - - % remember the sorted units - spike.unit{chanlop} = unit; -end - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: spikesorting.m,v 1.5 2008/09/22 20:17:44 roboos Exp $'; -% remember the configuration details of the input data -try, cfg.previous = spike.cfg; end -% remember the configuration -spike.cfg = cfg; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION that computes the distance between all spike waveforms -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [dist] = ward_distance(cfg, waveform); -nspike = size(waveform,2); -dist = zeros(nspike, nspike); -progress('init', cfg.feedback, 'computing distance'); -switch lower(cfg.ward.distance) - case 'l1' - for i=1:nspike - progress((i-1)/nspike, 'computing distance for spike %d/%d', i, nspike); - for j=2:nspike - dist(i,j) = sum(abs(waveform(:,j)-waveform(:,i))); - dist(j,i) = dist(i,j); - end - end - case 'l2' - for i=1:nspike - progress((i-1)/nspike, 'computing distance for spike %d/%d', i, nspike); - for j=2:nspike - dist(i,j) = sqrt(sum((waveform(:,j)-waveform(:,i)).^2)); - dist(j,i) = dist(i,j); - end - end - case 'correlation' - for i=1:nspike - progress((i-1)/nspike, 'computing distance for spike %d/%d', i, nspike); - for j=2:nspike - dist(i,j) = corrcoef(waveform(:,j),waveform(:,i)); - dist(j,i) = dist(i,j); - end - end - case 'cosine' - for i=1:nspike - progress((i-1)/nspike, 'computing distance for spike %d/%d', i, nspike); - for j=2:nspike - x = waveform(:,j); - y = waveform(:,i); - x = x./norm(x); - y = y./norm(y); - dist(i,j) = dot(x, y); - dist(j,i) = dist(i,j); - end - end - - otherwise - error('unsupported distance metric'); -end -progress('close'); diff --git a/external/fieldtrip/private/spikesplitting.m b/external/fieldtrip/private/spikesplitting.m deleted file mode 100644 index dd6b411..0000000 --- a/external/fieldtrip/private/spikesplitting.m +++ /dev/null @@ -1,290 +0,0 @@ -function [cfg] = spikesplitting(cfg); - -% SPIKESPLITTING reads a single Neuralynx DMA log file and writes each -% individual channel to a seperate file. -% -% Use as -% [cfg] = spikesplitting(cfg) -% -% The configuration should contain -% cfg.dataset = string with the name of the DMA log file -% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), see CHANNELSELECTION for details -% cfg.output = string with the name of the splitted DMA dataset directory, (default is determined automatic) -% cfg.latency = [begin end], (default = 'all') -% cfg.feedback = string, (default = 'textbar') -% cfg.format = 'int16' or 'int32' (default = 'int32') -% cfg.downscale = single number or vector (for each channel), corresponding to the number of bits removed from the LSB side (default = 0) -% -% This function expects the DMA file to be read as AD units (and not in uV) -% and will write the same AD values to the splitted DMA files. If you -% subsequently want to process the splitted DMA, you should look up the -% details of the headstage amplification and the Neuralynx amplifier and -% scale the values accordingly. -% -% See also SPIKEDOWNSAMPLE, SPIKEANALYSIS - -% Copyright (C) 2007-2008, Robert Oostenveld -% -% $Log: spikesplitting.m,v $ -% Revision 1.12 2008/12/15 15:08:01 roboos -% updated documentation -% -% Revision 1.11 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.10 2008/07/01 12:58:13 roboos -% write the original 16384 byte header to a txt file in the output directory -% -% Revision 1.9 2008/05/28 06:51:40 roboos -% add downsampling factor to file header, to ensure that scaling remains correct -% -% Revision 1.8 2008/02/26 15:26:16 roboos -% fixed some bugs in channelselection, thanks to Thilo (see email 26 Jan) -% -% Revision 1.7 2008/02/25 09:48:20 roboos -% added channel selection -% -% Revision 1.6 2008/02/04 10:16:45 roboos -% fixed bug in cfg.format (unsigned should be signed), thanks to Thilo -% -% Revision 1.5 2008/02/04 08:31:45 roboos -% added cfg.downscale -% -% Revision 1.4 2008/02/01 13:13:34 roboos -% added cfg.format, can be int16 or int32 -% -% Revision 1.3 2007/12/19 09:19:28 roboos -% fixed bug in writing uint32 data in case the most significant a.k.a. sign bit was set, this influenced the tsl channel -% -% Revision 1.2 2007/12/17 16:42:01 roboos -% This version incorpotares many small changes. One important change -% is that of the output file format: it now writes the status data -% to uint32 and continuous data to int16 format files. Also the file -% extension has been changed, and now corresponds with -% "dataset.chanlabel.bin". -% -% Revision 1.1 2007/02/19 16:16:05 roboos -% new function, basically copy and paste from selected functionality from spikedownsample -% - -fieldtripdefs - -% set the general defaults -if ~isfield(cfg, 'dataset'), cfg.dataset = []; end -if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end -if ~isfield(cfg, 'latency'), cfg.latency = [0 inf]; end -if ~isfield(cfg, 'feedback'), cfg.feedback = 'textbar'; end -if ~isfield(cfg, 'output'), cfg.output = []; end % see below -if ~isfield(cfg, 'format'), cfg.format = 'int32'; end -if ~isfield(cfg, 'downscale'), cfg.downscale = 0; end - -if isempty(cfg.output) - % set smart defaults for the output - [p, f, x] = fileparts(cfg.dataset); - cfg.output = fullfile(p, [f '.sdma']); -end - -status = mkdir(cfg.output); -if ~status - error(sprintf('error creating splitted DMA output dataset %s', cfg.output)); -end -fprintf('writing to output directory ''%s''\n', cfg.output); - -% read the header of the completete dataset -hdr = read_header(cfg.dataset); - -if isfield(hdr, 'orig') && isfield(hdr.orig, 'Header') - [p, f, x] = fileparts(cfg.output); - headerfile = fullfile(cfg.output, [f '.txt']); - fprintf('writing header information to %s\n', headerfile); - fid = fopen(headerfile, 'wb'); - fwrite(fid, hdr.orig.Header, 'char'); - fclose(fid); -end - -if hdr.nSamples<1 - error('the input dataset contains no samples'); -end - -if numel(cfg.downscale)==1 - % each channel should have its own downscale factor - cfg.downscale = repmat(cfg.downscale, 1, hdr.nChans); -end - -% determine the selected channels -cfg.channel = channelselection(cfg.channel, hdr.label); -chansel = match_str(hdr.label, cfg.channel); % this is a list with the indices of the selected channels -writechan = zeros(1,hdr.nChans); -writechan(chansel) = 1; % this is a logical/boolean vector with a 0/1 for each channel - -if numel(cfg.downscale) ~= numel(writechan) - error('the downscale factor should be specified for all channels, not only for the selected ones'); -end - -if isequal(cfg.latency, 'all') - begsample = 1; - endsample = hdr.nSamples; -elseif numel(cfg.latency)==2 - begsample = max(round(cfg.latency(1) * hdr.Fs + 1), 1); - endsample = min(round(cfg.latency(2) * hdr.Fs ), hdr.nSamples); -else - errror('incorrect specification of cfg.latency'); -end - -numsample = endsample - begsample + 1; -cfg.latency(1) = (begsample-1)/hdr.Fs; -cfg.latency(2) = (endsample )/hdr.Fs; - -% give some feedback, based on the complete data -fprintf('data contains %10d samples\n', hdr.nSamples); -fprintf('data selected %10d samples\n', numsample); - -s = floor(hdr.nSamples ./ hdr.Fs); -m = floor(s/60); -h = floor(m/60); -m = m - 60*h; -s = s - 60*m - 60*60*h; -fprintf('duration of data %02dh:%02dm:%02ds\n', h, m, s); - -s = floor(numsample ./ hdr.Fs); -m = floor(s/60); -h = floor(m/60); -m = m - 60*h; -s = s - 60*m - 60*60*h; -fprintf('duration of selection %02dh:%02dm:%02ds\n', h, m, s); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% split the DMA file into seperate channels -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if ~filetype(cfg.dataset, 'neuralynx_dma') - error('unsupported data format for DMA splitting'); -end - -statuslabel = { - 'stx' - 'pid' - 'siz' - 'tsh' - 'tsl' - 'cpu' - 'ttl' - 'x01' - 'x02' - 'x03' - 'x04' - 'x05' - 'x06' - 'x07' - 'x08' - 'x09' - 'x10' - 'crc' - }; - -% the output files will have an extension that is based on the channel name like "dataset.channame.bin" -[p, f, x] = fileparts(cfg.output); -filename = cell(hdr.nChans,1); -format = cell(hdr.nChans,1); -for i=1:hdr.nChans - filename{i} = fullfile(cfg.output, [f '.' hdr.label{i} '.bin']); - if strmatch(hdr.label{i}, statuslabel) - format{i} = 'uint32'; - elseif strcmp(cfg.format, 'int16') - format{i} = 'int16'; - elseif strcmp(cfg.format, 'int32') - format{i} = 'int32'; - else - error('incorrect specification of cfg.format'); - end -end - -% the status channels are written in their original format -for i=1:hdr.nChans - if strcmp(format{i}, 'uint32') && cfg.downscale(i)~=0 - warning('not downscaling status channel (%s)', hdr.label{i}); - cfg.downscale(i) = 0; - end -end - -% read and write the data in one-second segments -begsample = max(cfg.latency(1) * hdr.Fs + 1, 1); -endsample = min(cfg.latency(2) * hdr.Fs + 1, hdr.nSamples); -segment = begsample:hdr.Fs:endsample; -if segment(end)~=endsample - segment(end+1) = endsample; % the last segment should end on the end sample -end - -% The first version of this file format contained in the first 8 bytes the -% channel label as string. Subsequently it contained 32 bit integer values. -% -% The second version of this file format starts with 8 bytes describing (as -% a space-padded string) the data type. The channel label is contained in -% the filename as dataset.chanlabel.bin. -% -% The third version of this file format starts with 7 bytes describing (as -% a zero-padded string) the data type, followed by the 8th byte which -% describes the downscaling for the 8 and 16 bit integer representations. -% The downscaling itself is represented as uint8 and should be interpreted as -% the number of bits to shift. The channel label is contained in the -% filename as dataset.chanlabel.bin. - -% open the output files, one for each selected channel -fid = zeros(hdr.nChans,1); -for j=1:hdr.nChans - if writechan(j) - fid(j) = fopen(filename{j}, 'wb', 'ieee-le'); % open the file - magic = format{j}; % this used to be the channel name - magic((end+1):8) = 0; % pad with zeros - magic(8) = cfg.downscale(j); % number of bits to shift - fwrite(fid(j), magic(1:8)); % write the 8-byte file header - end -end - -progress('init', cfg.feedback, 'splitting data'); -for i=1:(length(segment)-1) - % read one segment of data - begsample = segment(i); - endsample = segment(i+1)-1; % the begin of the next segment minus one - progress(i/(length(segment)-1), 'splitting data segment %d from %d\n', i, length(segment)-1); - buf = read_neuralynx_dma(cfg.dataset, begsample, endsample, 'all'); - if ~isa(buf, 'int32') - error('the buffer is expected to be int32'); - end - % apply the scaling, this corresponds to bit shifting - for j=1:hdr.nChans - buf(j,:) = buf(j,:) ./ (2^cfg.downscale(j)); - end - % write the segment of data to each of the 274 output files - % the data is casted into the desired output format - for j=1:hdr.nChans - if writechan(j) - if strcmp(format{j}, 'uint32') - % the individual file header specifies that it should be interpreted as uint32 - % write the int32 data from the buffer as it is, during reading the sign bit will again be correctly interpreted - fwrite(fid(j), buf(j,:), 'int32', 'ieee-le'); - else - fwrite(fid(j), buf(j,:), format{j}, 'ieee-le'); - end - end - end -end -progress('close'); - -% close all output files -for j=1:hdr.nChans - if writechan(j) - fclose(fid(j)); - end -end - -% add the version details of this function call to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: spikesplitting.m,v 1.12 2008/12/15 15:08:01 roboos Exp $'; - diff --git a/external/fieldtrip/private/spiketriggeredaverage.m b/external/fieldtrip/private/spiketriggeredaverage.m deleted file mode 100644 index e4abe24..0000000 --- a/external/fieldtrip/private/spiketriggeredaverage.m +++ /dev/null @@ -1,200 +0,0 @@ -function [timelock] = spiketriggeredaverage(cfg, data) - -% SPIKETRIGGEREDAVERAGE computes the avererage of teh LFP around the spikes. -% -% Use as -% [timelock] = spiketriggeredaverage(cfg, data) -% -% The input data should be organised in a structure as obtained from -% the PREPROCESSING function. The configuration should be according to -% -% cfg.timwin = [begin end], time around each spike (default = [-0.1 0.1]) -% cfg.spikechannel = string, name of single spike channel to trigger on -% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), -% see CHANNELSELECTION for details -% cfg.keeptrials = 'yes' or 'no', return individual trials or average (default = 'no') -% cfg.feedback = 'no', 'text', 'textbar', 'gui' (default = 'no') - -% Copyright (C) 2008, Robert Oostenveld -% -% $Log: spiketriggeredaverage.m,v $ -% Revision 1.5 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.4 2008/04/09 14:39:22 roboos -% remove trials without data (too close to trial border) from the output -% -% Revision 1.3 2008/04/09 14:20:31 roboos -% replicate double spikes, for keeptrials -% give error if spike count >5 -% -% Revision 1.2 2008/03/18 21:56:56 roboos -% fixed bug in keeptrials, nans were allocated at the wrong moment -% -% Revision 1.1 2008/03/17 15:08:16 roboos -% new implementation, based on discussion with Thilo about desired functionality replication of spikeanalysis -% - -fieldtripdefs - -% set the defaults -if ~isfield(cfg, 'timwin'), cfg.timwin = [-0.1 0.1]; end -if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end -if ~isfield(cfg, 'spikechannel'), cfg.spikechannel = []; end -if ~isfield(cfg, 'keeptrials'), cfg.keeptrials = 'no'; end -if ~isfield(cfg, 'feedback'), cfg.feedback = 'no'; end - -% autodetect the spike channels -ntrial = length(data.trial); -nchans = length(data.label); -spikechan = zeros(nchans,1); -for i=1:ntrial - for j=1:nchans - spikechan(j) = spikechan(j) + all(data.trial{i}(j,:)==0 | data.trial{i}(j,:)==1 | data.trial{i}(j,:)==2); - end -end -spikechan = (spikechan==ntrial); - -% determine the channels to be averaged -cfg.channel = channelselection(cfg.channel, data.label); -chansel = match_str(data.label, cfg.channel); -nchansel = length(cfg.channel); % number of channels - -% determine the spike channel on which will be triggered -cfg.spikechannel = channelselection(cfg.spikechannel, data.label); -spikesel = match_str(data.label, cfg.spikechannel); -nspikesel = length(cfg.spikechannel); % number of channels - -if nspikesel==0 - error('no spike channel selected'); -end - -if nspikesel>1 - error('only supported for a single spike channel'); -end - -if ~spikechan(spikesel) - error('the selected spike channel seems to contain continuous data'); -end - -begpad = round(cfg.timwin(1)*data.fsample); -endpad = round(cfg.timwin(2)*data.fsample); -numsmp = endpad - begpad + 1; - -singletrial = cell(1,ntrial); -spiketime = cell(1,ntrial); -spiketrial = cell(1,ntrial); -cumsum = zeros(nchansel, numsmp); -cumcnt = 0; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% compute the average -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -for i=1:ntrial - spikesmp = find(data.trial{i}(spikesel,:)); - spikecnt = data.trial{i}(spikesel,spikesmp); - - if any(spikecnt>5) || any(spikecnt<0) - error('the spike count lies out of the regular bounds'); - end - - % instead of doing the bookkeeping of double spikes below, replicate the double spikes by looking at spikecnt - sel = find(spikecnt>1); - tmp = zeros(1,sum(spikecnt(sel))); - n = 1; - for j=1:length(sel) - for k=1:spikecnt(sel(j)) - tmp(n) = spikesmp(sel(j)); - n = n + 1; - end - end - spikesmp(sel) = []; % remove the double spikes - spikecnt(sel) = []; % remove the double spikes - spikesmp = [spikesmp tmp]; % add the double spikes as replicated single spikes - spikecnt = [spikecnt ones(size(tmp))]; % add the double spikes as replicated single spikes - spikesmp = sort(spikesmp); % sort them to keep the original ordering (not needed on spikecnt, since that is all ones) - - spiketime{i} = data.time{i}(spikesmp); - spiketrial{i} = i*ones(size(spikesmp)); - fprintf('processing trial %d of %d (%d spikes)\n', i, ntrial, sum(spikecnt)); - - if strcmp(cfg.keeptrials, 'yes') - if any(spikecnt>1) - error('overlapping spikes not supported with cfg.keeptrials=yes'); - end - % initialize the memory for this trial - singletrial{i} = nan*zeros(length(spikesmp), nchansel, numsmp); - end - - progress('init', cfg.feedback, 'averaging spikes'); - for j=1:length(spikesmp) - progress(i/ntrial, 'averaging spike %d of %d\n', j, length(spikesmp)); - begsmp = spikesmp(j) + begpad; - endsmp = spikesmp(j) + endpad; - - if begsmp<1 - % a possible alternative would be to pad the begin with nan - % this excludes the complete segment - continue - elseif endsmp>size(data.trial{i},2) - % possible alternative would be to pad the end with nan - % this excludes the complete segment - continue - else - segment = data.trial{i}(chansel,begsmp:endsmp); - end - if strcmp(cfg.keeptrials, 'yes') - singletrial{i}(j,:,:) = segment; - end - - cumsum = cumsum + spikecnt(j)*segment; - cumcnt = cumcnt + spikecnt(j); - - end % for each spike in this trial - progress('close'); - -end % for each trial - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% collect the results -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -timelock.time = offset2time(begpad, data.fsample, numsmp); -timelock.avg = cumsum ./ cumcnt; -timelock.label = data.label(chansel); - -if (strcmp(cfg.keeptrials, 'yes')) - timelock.dimord = 'rpt_chan_time'; - % concatenate all the single spike snippets - timelock.trial = cat(1, singletrial{:}); - timelock.origtime = cat(2,spiketime{:})'; % this deviates from the standard output, but is included for reference - timelock.origtrial = cat(2,spiketrial{:})'; % this deviates from the standard output, but is included for reference - - % select all trials that do not contain data in the first sample - sel = isnan(timelock.trial(:,1,1)); - fprintf('removing %d trials from the output that do not contain data\n', sum(sel)); - % remove the selected trials from the output - timelock.trial = timelock.trial(~sel,:,:); - timelock.origtime = timelock.origtime(~sel); - timelock.origtrial = timelock.origtrial(~sel); -else - timelock.dimord = 'chan_time'; -end - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: spiketriggeredaverage.m,v 1.5 2008/09/22 20:17:44 roboos Exp $'; -% remember the configuration details of the input data -try, cfg.previous = data.cfg; end -% remember the exact configuration details in the output -timelock.cfg = cfg; - - diff --git a/external/fieldtrip/private/spiketriggeredinterpolation.m b/external/fieldtrip/private/spiketriggeredinterpolation.m deleted file mode 100644 index 8c51a47..0000000 --- a/external/fieldtrip/private/spiketriggeredinterpolation.m +++ /dev/null @@ -1,172 +0,0 @@ -function [data] = spiketriggeredinterpolation(cfg, data) - -% SPIKETRIGGEREDINTERPOLATION interpolates the data in the LFP channels -% around the spikes that are detected in the spike channels, or replaces -% the LFP around the spike with NaNs. -% -% Use as -% [data] = spiketriggeredinterpolation(cfg, data) -% -% The input data should be organised in a structure as obtained from the -% PREPROCESSING function. The configuration should be according to -% -% cfg.method = string, The interpolation method can be 'nan', -% 'cubic', 'linear', 'nearest', spline', 'pchip' -% (default = 'nan'). See INTERP1 for more details. -% cfg.timwin = [begin end], time around each spike (default = [-0.001 0.002]) -% cfg.interptoi = value, time in seconds used for interpolation, which -% must be larger than timwin (default = 0.01) -% cfg.spikechannel = string, name of single spike channel to trigger on -% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), -% see CHANNELSELECTION for details -% cfg.feedback = 'no', 'text', 'textbar', 'gui' (default = 'no') -% -% The output will contain all channels of the input, only the data in the -% selected channels will be interpolated or replaced with NaNs. -% -% See also SPIKETRIGGEREDSPECTRUM, SPIKETRIGGEREDAVERAGE - -% Copyright (C) 2008, Thilo Womelsdorf -% -% $Log: spiketriggeredinterpolation.m,v $ -% Revision 1.2 2008/09/24 08:04:50 roboos -% added example output, fixed some bugs -% -% Revision 1.1 2008/09/18 09:50:36 roboos -% new implementation, thanks to Thilo -% - -% set the defaults -if ~isfield(cfg, 'timwin'), cfg.timwin = [-0.001 0.002]; end -if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end -if ~isfield(cfg, 'method'), cfg.method = 'nan'; end -if ~isfield(cfg, 'spikechannel'), cfg.spikechannel = []; end -if ~isfield(cfg, 'outputexamples'), cfg.outputexamples = 'no'; end -if ~isfield(cfg, 'feedback'), cfg.feedback = 'no'; end - -if strcmp(cfg.method, 'nan') - cfg.interptoi = 0; -else - cfg.interptoi = 0.010; -end - -% autodetect the spike channels -ntrial = length(data.trial); -nchans = length(data.label); -spikechan = zeros(nchans,1); -for i=1:ntrial - for j=1:nchans - spikechan(j) = spikechan(j) + all(data.trial{i}(j,:)==0 | data.trial{i}(j,:)==1 | data.trial{i}(j,:)==2); - end -end -spikechan = (spikechan==ntrial); - -% determine the channels for interpolation -cfg.channel = channelselection(cfg.channel, data.label); -chansel = match_str(data.label, cfg.channel); - -% determine the spike channel on which will be triggered -cfg.spikechannel = channelselection(cfg.spikechannel, data.label); -spikesel = match_str(data.label, cfg.spikechannel); -nspikesel = length(cfg.spikechannel); % number of spike channels - -if nspikesel==0 - error('no spike channel selected'); -end - -if nspikesel>1 - error('only supported for a single spike channel'); -end - -if ~spikechan(spikesel) - error('the selected spike channel seems to contain continuous data'); -end - -% this determines the segment that will be replaced around each spike -begpad = round(cfg.timwin(1)*data.fsample); -endpad = round(cfg.timwin(2)*data.fsample); - -% this determines the segment that is used for the inperpolation around each spike -interppad = round( cfg.interptoi*data.fsample); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% interpolate the LFP around the spikes -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% this is for storing the examples -cnte = 0; -spkexample = {}; - -for i=1:ntrial - spikesmp = find(data.trial{i}(spikesel,:)); - - fprintf('processing trial %d of %d (%d spikes)\n', i, ntrial, length(spikesmp)); - - progress('init', cfg.feedback, 'interpolating spikes'); - for j=1:length(spikesmp) - progress(i/ntrial, 'interpolating spike %d of %d\n', j, length(spikesmp)); - begsmp = spikesmp(j) + begpad; - endsmp = spikesmp(j) + endpad; - - begsmp_interp = begsmp - interppad; - endsmp_interp = endsmp + interppad; - - if begsmp_interp<1 - continue, - end - if endsmp_interp>size(data.trial{i},2) - continue, - end - - if strcmp(cfg.method,'nan') - % only replace with NaNs - data.trial{i}(chansel,begsmp:endsmp) = NaN; - - else - % interpolate the data around the spike - xall = [begsmp_interp : endsmp_interp]; - x = [begsmp_interp:begsmp-1 endsmp+1:endsmp_interp]; - y = data.trial{i}(chansel,x) ; - yi = interp1(x,y,xall,cfg.method); - - % store the interpolated segment back in the data - data.trial{i}(chansel,xall) = yi; - - if strcmp(cfg.outputexamples, 'yes') && (cnte<100) - yall = data.trial{i}(chansel,xall); - cnte = cnte+1; - spkexample{cnte} = [ xall; yall; yi]; - % plot(x,y,'r.',xall,yall,'bo',xall,yi,'g-d') - end - - end % if strcmp(cfg.method) - - end % for each spike in this trial - progress('close'); - -end % for each trial - -if strcmp(cfg.outputexamples, 'yes') - data.spkexample = spkexample; -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% the data has been modified on the fly, only update the configuration -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: spiketriggeredinterpolation.m,v 1.2 2008/09/24 08:04:50 roboos Exp $'; -% remember the configuration details of the input data -try, cfg.previous = data.cfg; end -% remember the exact configuration details in the output -data.cfg = cfg; - - diff --git a/external/fieldtrip/private/spiketriggeredspectrum.m b/external/fieldtrip/private/spiketriggeredspectrum.m deleted file mode 100644 index 9dd9885..0000000 --- a/external/fieldtrip/private/spiketriggeredspectrum.m +++ /dev/null @@ -1,239 +0,0 @@ -function [freq] = spiketriggeredspectrum(cfg, data) - -% SPIKETRIGGEREDSPECTRUM computes the Fourier spectrup of the LFP around the spikes. -% -% Use as -% [freq] = spiketriggeredspectrum(cfg, data) -% -% The input data should be organised in a structure as obtained from -% the APPENDSPIKE function. The configuration should be according to -% -% cfg.timwin = [begin end], time around each spike (default = [-0.1 0.1]) -% cfg.foilim = [begin end], frequency band of interest (default = [0 150]) -% cfg.taper = 'dpss', 'hanning' or many others, see WINDOW (default = 'hanning') -% cfg.spikechannel = string, name of single spike channel to trigger on -% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), -% see CHANNELSELECTION for details -% cfg.feedback = 'no', 'text', 'textbar', 'gui' (default = 'no') -% -% If the triggered spike leads a spike in another channel, then the angle -% of the Fourier spectrum of that other channel will be negative. NOTE that -% this should be checked for consistency. - -% Copyright (C) 2008, Robert Oostenveld -% -% $Log: spiketriggeredspectrum.m,v $ -% Revision 1.8 2009/01/20 16:53:29 roboos -% fixed problem with fft handle not expecting key-value input arguments (thanks to Thilo) -% -% Revision 1.7 2008/10/01 08:23:05 roboos -% use specest_nanfft as default -% -% Revision 1.6 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.5 2008/07/15 18:17:57 roboos -% fixed documentation -% -% Revision 1.4 2008/04/09 14:39:22 roboos -% remove trials without data (too close to trial border) from the output -% -% Revision 1.3 2008/04/09 14:23:15 roboos -% replicate double spikes, for keeptrials -% give error if spike count >5 -% -% Revision 1.2 2008/03/18 21:58:18 roboos -% added normalization of the spectrum by the number of samples, and rotation of the phase to correct for t=0 being in the middle of the segment instead of at the begin -% -% Revision 1.1 2008/03/17 16:42:35 roboos -% initial implementation, phase rotation still needs to be built in -% - -fieldtripdefs - -% set the defaults -if ~isfield(cfg, 'timwin'), cfg.timwin = [-0.1 0.1]; end -if ~isfield(cfg, 'foilim'), cfg.foilim = [0 150]; end -if ~isfield(cfg, 'taper'), cfg.taper = 'hanning'; end -if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end -if ~isfield(cfg, 'spikechannel'), cfg.spikechannel = []; end -% if ~isfield(cfg, 'keeptrials'), cfg.keeptrials = 'no'; end -if ~isfield(cfg, 'feedback'), cfg.feedback = 'no'; end - -if strcmp(cfg.taper, 'dpss') && strcmp(cfg.taper, 'sine') - error('sorry, multitapering is not yet implemented'); -end - -% see subfunction below, which demonstrates the expected function behaviour -% my_fft = @fft_along_rows; - -% use a NaN-aware spectral estimation technique, which will default to the -% standard Matlab FFT routine if no NaNs are present -my_fft = @specest_nanfft; - -% autodetect the spike channels -ntrial = length(data.trial); -nchans = length(data.label); -spikechan = zeros(nchans,1); -for i=1:ntrial - for j=1:nchans - spikechan(j) = spikechan(j) + all(data.trial{i}(j,:)==0 | data.trial{i}(j,:)==1 | data.trial{i}(j,:)==2); - end -end -spikechan = (spikechan==ntrial); - -% determine the channels to be averaged -cfg.channel = channelselection(cfg.channel, data.label); -chansel = match_str(data.label, cfg.channel); -nchansel = length(cfg.channel); % number of channels - -% determine the spike channel on which will be triggered -cfg.spikechannel = channelselection(cfg.spikechannel, data.label); -spikesel = match_str(data.label, cfg.spikechannel); -nspikesel = length(cfg.spikechannel); % number of channels - -if nspikesel==0 - error('no spike channel selected'); -end - -if nspikesel>1 - error('only supported for a single spike channel'); -end - -if ~spikechan(spikesel) - error('the selected spike channel seems to contain continuous data'); -end - -begpad = round(cfg.timwin(1)*data.fsample); -endpad = round(cfg.timwin(2)*data.fsample); -numsmp = endpad - begpad + 1; -taper = window('hanning', numsmp); -taper = taper./norm(taper); -taper = sparse(diag(taper)); - -spectrum = cell(1,ntrial); -spiketime = cell(1,ntrial); -spiketrial = cell(1,ntrial); -cumsum = zeros(nchansel, numsmp); -cumcnt = 0; - -timeaxis = linspace(cfg.timwin(1),cfg.timwin(2), numsmp); -freqaxis = linspace(0, data.fsample, numsmp); -fbeg = nearest(freqaxis, cfg.foilim(1)); -fend = nearest(freqaxis, cfg.foilim(2)); -% update the configuration to acocunt for rounding off differences -cfg.foilim(1) = freqaxis(fbeg); -cfg.foilim(2) = freqaxis(fend); - -% make a representation of the spike, this is used for the phase rotation -spike = zeros(1,numsmp); -spike(1-begpad) = 1; -spike_fft = my_fft(spike); -spike_fft = spike_fft(fbeg:fend); -spike_fft = spike_fft./abs(spike_fft); -rephase = sparse(diag(conj(spike_fft))); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% compute the spectra -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -for i=1:ntrial - spikesmp = find(data.trial{i}(spikesel,:)); - spikecnt = data.trial{i}(spikesel,spikesmp); - - if any(spikecnt>5) || any(spikecnt<0) - error('the spike count lies out of the regular bounds'); - end - - % instead of doing the bookkeeping of double spikes below, replicate the double spikes by looking at spikecnt - sel = find(spikecnt>1); - tmp = zeros(1,sum(spikecnt(sel))); - n = 1; - for j=1:length(sel) - for k=1:spikecnt(sel(j)) - tmp(n) = spikesmp(sel(j)); - n = n + 1; - end - end - spikesmp(sel) = []; % remove the double spikes - spikecnt(sel) = []; % remove the double spikes - spikesmp = [spikesmp tmp]; % add the double spikes as replicated single spikes - spikecnt = [spikecnt ones(size(tmp))]; % add the double spikes as replicated single spikes - spikesmp = sort(spikesmp); % sort them to keep the original ordering (not needed on spikecnt, since that is all ones) - - spiketime{i} = data.time{i}(spikesmp); - spiketrial{i} = i*ones(size(spikesmp)); - fprintf('processing trial %d of %d (%d spikes)\n', i, ntrial, sum(spikecnt)); - - spectrum{i} = zeros(length(spikesmp), nchansel, fend-fbeg+1); - - progress('init', cfg.feedback, 'spectrally decomposing data around spikes'); - for j=1:length(spikesmp) - progress(i/ntrial, 'spectrally decomposing data around spike %d of %d\n', j, length(spikesmp)); - begsmp = spikesmp(j) + begpad; - endsmp = spikesmp(j) + endpad; - - if (begsmp<1) - segment = nan*zeros(nchansel, numsmp); - elseif endsmp>size(data.trial{i},2) - segment = nan*zeros(nchansel, numsmp); - else - segment = data.trial{i}(chansel,begsmp:endsmp); - end - - % taper the data segment around the spike and compute the fft - segment_fft = my_fft(segment * taper); - - % select the desired output frquencies and normalize - segment_fft = segment_fft(:,fbeg:fend) ./ sqrt(numsmp/2); - - % rotate the estimated phase at each frequency to correct for the segment t=0 not being at the first sample - segment_fft = segment_fft * rephase; - - % store the result for this spike in this trial - spectrum{i}(j,:,:) = segment_fft; - - end % for each spike in this trial - progress('close'); - -end % for each trial - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% collect the results -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -freq.label = data.label(chansel); -freq.freq = freqaxis(fbeg:fend); -freq.dimord = 'rpt_chan_freq'; - -freq.fourierspctrm = cat(1, spectrum{:}); -freq.origtime = cat(2,spiketime{:})'; % this deviates from the standard output, but is included for reference -freq.origtrial = cat(2,spiketrial{:})'; % this deviates from the standard output, but is included for reference - -% select all trials that do not contain data in the first sample -sel = isnan(freq.fourierspctrm(:,1,1)); -fprintf('removing %d trials from the output that do not contain data\n', sum(sel)); -% remove the selected trials from the output -freq.fourierspctrm = freq.fourierspctrm(~sel,:,:); -freq.origtime = freq.origtime(~sel); -freq.origtrial = freq.origtrial(~sel); - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: spiketriggeredspectrum.m,v 1.8 2009/01/20 16:53:29 roboos Exp $'; -% remember the configuration details of the input data -try, cfg.previous = data.cfg; end -% remember the exact configuration details in the output -freq.cfg = cfg; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function y = fft_along_rows(x) -y = fft(x, [], 2); % use normal Matlab function to compute the fft along 2nd dimension - diff --git a/external/fieldtrip/private/splint.m b/external/fieldtrip/private/splint.m index 7d7c56d..6a9b6b8 100644 --- a/external/fieldtrip/private/splint.m +++ b/external/fieldtrip/private/splint.m @@ -6,13 +6,13 @@ % Use as % [V2, L2, L1] = splint(elc1, V1, elc2) % where -% elc1 electrode positions where potential is known -% elc2 electrode positions where potential is not known -% V1 known potential +% elc1 electrode positions where potential is known +% elc2 electrode positions where potential is not known +% V1 known potential % and -% V2 potential at electrode locations in elc2 -% L2 laplacian of potential at electrode locations in elc2 -% L1 laplacian of potential at electrode locations in elc1 +% V2 potential at electrode locations in elc2 +% L2 laplacian of potential at electrode locations in elc2 +% L1 laplacian of potential at electrode locations in elc1 % % See also LAPINT, LAPINTMAT, LAPCAL @@ -27,33 +27,28 @@ % Copyright (C) 2003, Robert Oostenveld % -% $Log: splint.m,v $ -% Revision 1.7 2006/09/07 12:32:53 roboos -% minor change in documentation +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.6 2004/06/28 07:37:40 roberto -% tested and improved computation of legendre polynomials +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.5 2004/01/27 12:43:30 roberto -% re-included splint_gh as subfunction and made it adaptive to the number of electrodes -% added laplacian L1 on elc1 to outpu of function +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.4 2003/06/03 08:29:39 roberto -% *** empty log message *** -% -% Revision 1.3 2003/04/10 09:48:13 roberto -% fixed bug in construction of matrix H (removes the need for avgref) -% fixed minor bug in gh() subfunction (preallocation of space) -% changed from SVD to Gaussian Elimination to solve for coefficients -% -% Revision 1.2 2003/03/11 14:45:37 roberto -% updated help and copyrights +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: splint.m 952 2010-04-21 18:29:51Z roboos $ -N = size(elc1,1); % number of known electrodes -M = size(elc2,1); % number of unknown electrodes -T = size(V1,2); % number of timepoints in the potential -Z = V1; % potential on known electrodes, can be matrix +N = size(elc1,1); % number of known electrodes +M = size(elc2,1); % number of unknown electrodes +T = size(V1,2); % number of timepoints in the potential +Z = V1; % potential on known electrodes, can be matrix % remember the actual size of the sphere sphere1_scale = mean(sqrt(sum(elc1.^2,2))); diff --git a/external/fieldtrip/private/splint_gh.m b/external/fieldtrip/private/splint_gh.m index d71a8e5..3b10b11 100644 --- a/external/fieldtrip/private/splint_gh.m +++ b/external/fieldtrip/private/splint_gh.m @@ -5,12 +5,23 @@ % Copyright (C) 2004-2009, Robert Oostenveld % -% $Log: splint_gh.m,v $ -% Revision 1.1 2009/03/12 11:03:23 roboos -% first time commit to CVS, although the m-function already existed since 2004 -% somehow it was always excluded from CVS because the mex files would do the work -% iin this version the original code is commented out and autocompilation of the mex file is attempted +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: splint_gh.m 952 2010-04-21 18:29:51Z roboos $ % compile the missing mex file on the fly % remember the original working directory diff --git a/external/fieldtrip/private/splint_gh.mexmaci b/external/fieldtrip/private/splint_gh.mexmaci index 4f4ccb9..ce0463a 100755 Binary files a/external/fieldtrip/private/splint_gh.mexmaci and b/external/fieldtrip/private/splint_gh.mexmaci differ diff --git a/external/fieldtrip/private/splint_gh.mexw32 b/external/fieldtrip/private/splint_gh.mexw32 index 7fa83fa..ae2ccf8 100644 Binary files a/external/fieldtrip/private/splint_gh.mexw32 and b/external/fieldtrip/private/splint_gh.mexw32 differ diff --git a/external/fieldtrip/private/splint_gh.mexw64 b/external/fieldtrip/private/splint_gh.mexw64 index 7ba5eca..868c94c 100644 Binary files a/external/fieldtrip/private/splint_gh.mexw64 and b/external/fieldtrip/private/splint_gh.mexw64 differ diff --git a/external/fieldtrip/private/standardise.m b/external/fieldtrip/private/standardise.m index 335f71a..69815cd 100644 --- a/external/fieldtrip/private/standardise.m +++ b/external/fieldtrip/private/standardise.m @@ -1,25 +1,50 @@ -function [x,mx,sx] = standardise(x,dim) +function [x,mx,sx] = standardise(x,dim,lim) % X = STANDARDISE(X, DIM) computes the zscore of a matrix along dimension dim -% has extended functionality as compared to the stats-toolbox's zscore function +% has similar functionality as the stats-toolbox's zscore function % Copyright (C) 2009, Jan-Mathijs Schoffelen % -% $Log: standardise.m,v $ -% Revision 1.2 2009/06/16 15:44:29 jansch -% added automatic dim detection (first non singular dimension) for nargin==1. -% added mean and std to output +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.1 2009/05/19 15:59:11 jansch -% first commitment into cvs +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: standardise.m 952 2010-04-21 18:29:51Z roboos $ + +if nargin == 1, + dim = find(size(x)>1,1,'first'); + lim = [1 size(x,dim)]; +elseif nargin == 2, + lim = [1 size(x,dim)]; +end -if nargin == 1, dim = find(size(x)>1,1,'first'); end +ndim = numel(size(x)); +ix = cell(1,6); +for k = 1:numel(ix) + if k>ndim + ix{k} = 1; + else + ix{k} = 1:size(x,k); + end +end +ix{dim} = lim(1):lim(2); -n = size(x,dim); -mx = mean(x,dim); +n = numel(ix{dim}); +mx = mean(x(ix{1},ix{2},ix{3},ix{4},ix{5},ix{6}),dim); %sx = std(x,0,dim); -sx = std(x,1,dim); -repvec = ones(1,length(size(x))); -repvec(dim) = n; +sx = std(x(ix{1},ix{2},ix{3},ix{4},ix{5},ix{6}),1,dim); +repvec = ones(1,ndim); +repvec(dim) = size(x,dim); x = (x - repmat(mx,repvec))./repmat(sx,repvec); diff --git a/external/fieldtrip/private/statfun_depsamplesregrT.m b/external/fieldtrip/private/statfun_depsamplesregrT.m deleted file mode 100644 index 19ac863..0000000 --- a/external/fieldtrip/private/statfun_depsamplesregrT.m +++ /dev/null @@ -1,151 +0,0 @@ -function [s,cfg] = statfun_depsamplesregrT(cfg, dat, design); - -% STATFUN_depsamplesregrT calculates dependent samples regression T-statistic -% on the biological data in dat (the dependent variable), using the information on -% the independent variable (iv) in design. -% -% The external interface of this function has to be -% [s,cfg] = statfun_depsamplesregrT(cfg, dat, design); -% where -% dat contains the biological data, Nsamples x Nreplications -% design contains the independent variable (iv) and the unit-of-observation (UO) -% factor, Nreplications x Nvar -% -% Configuration options: -% cfg.computestat = 'yes' or 'no', calculate the statistic (default='yes') -% cfg.computecritval = 'yes' or 'no', calculate the critical values of the test statistics (default='no') -% cfg.computeprob = 'yes' or 'no', calculate the p-values (default='no') -% -% The following options are relevant if cfg.computecritval='yes' and/or -% cfg.computeprob='yes'. -% cfg.alpha = critical alpha-level of the statistical test (default=0.05) -% cfg.tail = -1, 0, or 1, left, two-sided, or right (default=1) -% cfg.tail in combination with cfg.computecritval='yes' -% determines whether the critical value is computed at -% quantile cfg.alpha (with cfg.tail=-1), at quantiles -% cfg.alpha/2 and (1-cfg.alpha/2) (with cfg.tail=0), or at -% quantile (1-cfg.alpha) (with cfg.tail=1). -% -% Design specification: -% cfg.ivar = row number of the design that contains the independent variable. -% cfg.uvar = row number of design that contains the labels of the UOs (subjects or trials) -% (default=2). The labels are assumed to be integers ranging from 1 to -% the number of UOs. -% - -% Copyright (C) 2006, Eric Maris -% -% $Log: statfun_depsamplesregrT.m,v $ -% Revision 1.1 2008/09/23 07:31:15 roboos -% Moved all statfuns and trialfuns to their own directories, where they will be easier to find for the end-user. Also updated fieldtripdefs accordingly. -% -% Revision 1.10 2007/08/24 10:40:28 erimar -% Correct a bug (omission of a unit selection variable), detected by -% Vladimir Litvak, -% -% Revision 1.9 2007/08/16 10:15:31 erimar -% Added functionality with respect to control variables (specified in -% cfg.design and addressed via cfg.cvar). The contribution of control -% variables to the dependent variable (the biological data) can be -% partialled out. -% -% Revision 1.8 2007/08/16 10:12:30 erimar -% *** empty log message *** -% -% Revision 1.7 2006/09/12 12:13:07 roboos -% removed default values for cfg.ivar and uvar, defaults should be specified elsewhere -% -% Revision 1.6 2006/06/07 12:51:18 roboos -% renamed cfg.ivrownr into cfg.ivar -% renamed cfg.uorownr into cfg.uvar -% renamed pval into prob for consistency with other fieldtrip functions -% -% Revision 1.5 2006/05/17 11:59:55 erimar -% Corrected bugs after extensive checking of the properties of this -% statfun. -% -% Revision 1.4 2006/05/12 15:32:40 erimar -% Added functionality to calculate one- and two-sided critical values and -% p-values. -% -% Revision 1.3 2006/05/05 13:08:54 erimar -% Renamed several options and variables to make this statfun consistent with other -% statfuns. -% -% Revision 1.2 2006/04/11 16:17:27 roboos -% renamed some cfg options, changed the handling of whether to compute stat and/or critical values, changed the output into a stucture containing stat and/or critval -% - -% set defaults -if ~isfield(cfg, 'computestat'), cfg.computestat='yes'; end; -if ~isfield(cfg, 'computecritval'), cfg.computecritval='no'; end; -if ~isfield(cfg, 'computeprob'), cfg.computeprob='no'; end; -if ~isfield(cfg, 'alpha'), cfg.alpha=0.05; end; -if ~isfield(cfg, 'tail'), cfg.tail=1; end; - -% perform some checks on the configuration -if strcmp(cfg.computeprob,'yes') & strcmp(cfg.computestat,'no') - error('P-values can only be calculated if the test statistics are calculated.'); -end; - -if ~isempty(cfg.cvar) - condlabels=unique(design(cfg.cvar,:)); - nblocks=length(condlabels); -else - nblocks=1; -end; - -nunits = max(design(cfg.uvar,:)); -df = nunits - 1; -if nunits<2 - error('The data must contain at least two units-of-observation (usually subjects).') -end; - -if strcmp(cfg.computestat,'yes') -% compute the statistic - regrweights=zeros(size(dat,1),nunits); - for indx=1:nunits - unitselvec=find(design(cfg.uvar,:)==indx); - indvar=design(cfg.ivar,unitselvec); - if isempty(cfg.cvar) - designmat=[ones(1,length(indvar));indvar]; - else - designmat=zeros((nblocks+1),length(indvar)); - for blockindx=1:nblocks - blockselvec=find(design(cfg.cvar,unitselved)==condlabels(blockindx)); - designmat(blockindx,blockselvec)=1; - end; - designmat((nblocks+1),:)=indvar; - end; - coeff=(designmat*designmat')\(designmat*dat(:,unitselvec)'); - regrweights(:,indx)=coeff((nblocks+1),:)'; - end; - avgw=mean(regrweights,2); - varw=var(regrweights,0,2); - s.stat=sqrt(nunits)*avgw./sqrt(varw); -end; - -if strcmp(cfg.computecritval,'yes') - % also compute the critical values - s.df = df; - if cfg.tail==-1 - s.critval = tinv(cfg.alpha,df); - elseif cfg.tail==0 - s.critval = [tinv(cfg.alpha/2,df),tinv(1-cfg.alpha/2,df)]; - elseif cfg.tail==1 - s.critval = tinv(1-cfg.alpha,df); - end; -end - -if strcmp(cfg.computeprob,'yes') - % also compute the p-values - s.df = df; - if cfg.tail==-1 - s.prob = tcdf(s.stat,s.df); - elseif cfg.tail==0 - s.prob = 2*tcdf(-abs(s.stat),s.df); - elseif cfg.tail==1 - s.prob = 1-tcdf(s.stat,s.df); - end; -end - diff --git a/external/fieldtrip/private/statfun_indepsamplesT.m b/external/fieldtrip/private/statfun_indepsamplesT.m deleted file mode 100644 index de3f513..0000000 --- a/external/fieldtrip/private/statfun_indepsamplesT.m +++ /dev/null @@ -1,133 +0,0 @@ -function [s,cfg] = statfun_indepsamplesT(cfg, dat, design); - -% STATFUN_indepsamplesT calculates the independent samples T-statistic -% on the biological data in dat (the dependent variable), using the information on -% the independent variable (iv) in design. -% -% The external interface of this function has to be -% [s,cfg] = statfun_indepsamplesT(cfg, dat, design); -% where -% dat contains the biological data, Nsamples x Nreplications -% design contains the independent variable (iv), Nfac x Nreplications -% -% Configuration options: -% cfg.computestat = 'yes' or 'no', calculate the statistic (default='yes') -% cfg.computecritval = 'yes' or 'no', calculate the critical values of the test statistics (default='no') -% cfg.computeprob = 'yes' or 'no', calculate the p-values (default='no') -% -% The following options are relevant if cfg.computecritval='yes' and/or -% cfg.computeprob='yes'. -% cfg.alpha = critical alpha-level of the statistical test (default=0.05) -% cfg.tail = -1, 0, or 1, left, two-sided, or right (default=1) -% cfg.tail in combination with cfg.computecritval='yes' -% determines whether the critical value is computed at -% quantile cfg.alpha (with cfg.tail=-1), at quantiles -% cfg.alpha/2 and (1-cfg.alpha/2) (with cfg.tail=0), or at -% quantile (1-cfg.alpha) (with cfg.tail=1). -% -% Design specification: -% cfg.ivar = row number of the design that contains the labels of the conditions that must be -% compared (default=1). The labels are the numbers 1 and 2. -% - -% Copyright (C) 2006, Eric Maris -% -% $Log: statfun_indepsamplesT.m,v $ -% Revision 1.1 2008/09/23 07:31:15 roboos -% Moved all statfuns and trialfuns to their own directories, where they will be easier to find for the end-user. Also updated fieldtripdefs accordingly. -% -% Revision 1.10 2007/01/10 08:55:01 jansch -% fixed bug on line 97 and added a comment on why nreplc should be vectors -% -% Revision 1.9 2006/12/22 11:36:49 jansch -% *** empty log message *** -% -% Revision 1.8 2006/09/12 12:13:07 roboos -% removed default values for cfg.ivar and uvar, defaults should be specified elsewhere -% -% Revision 1.7 2006/06/07 12:51:18 roboos -% renamed cfg.ivrownr into cfg.ivar -% renamed cfg.uorownr into cfg.uvar -% renamed pval into prob for consistency with other fieldtrip functions -% -% Revision 1.6 2006/05/16 10:26:38 erimar -% Corrected bug involving sample sizes. -% -% Revision 1.5 2006/05/12 15:32:40 erimar -% Added functionality to calculate one- and two-sided critical values and -% p-values. -% -% Revision 1.4 2006/05/05 13:04:14 erimar -% Renamed several options and variables to make them consistent with other statfuns. -% -% Revision 1.3 2006/04/12 12:13:44 roboos -% added degrees of freedom to output if critvals is requested -% -% Revision 1.2 2006/04/11 16:17:27 roboos -% renamed some cfg options, changed the handling of whether to compute stat and/or critical values, changed the output into a stucture containing stat and/or critval -% - -% set defaults -if ~isfield(cfg, 'computestat'), cfg.computestat='yes'; end; -if ~isfield(cfg, 'computecritval'), cfg.computecritval='no'; end; -if ~isfield(cfg, 'computeprob'), cfg.computeprob='no'; end; -if ~isfield(cfg, 'alpha'), cfg.alpha=0.05; end; -if ~isfield(cfg, 'tail'), cfg.tail=1; end; - -% perform some checks on the configuration -if strcmp(cfg.computeprob,'yes') && strcmp(cfg.computestat,'no') - % probabilities can only be calculated if the test statistics are calculated - cfg.computestat = 'yes'; -end; - -% perform some checks on the design -sel1 = find(design(cfg.ivar,:)==1); -sel2 = find(design(cfg.ivar,:)==2); -nreplc1 = sum(~isnan(dat(:,sel1)), 2); -nreplc2 = sum(~isnan(dat(:,sel2)), 2); -nrepl = nreplc1 + nreplc2; -if any(nrepl. % -% Revision 1.50 2008/09/22 19:44:11 roboos -% update documentation -% -% Revision 1.49 2008/08/20 19:16:56 jansch -% removed keyboard-statement. oops -% -% Revision 1.48 2008/08/20 19:03:12 jansch -% experimental fix in get_source_trial. earlier changes caused sourcestatistics -% to crash (reproduced with grandaverage as an input). this was tracked down to -% happen in checkdata, which keeps a volumetric representation of the functional -% data, in the case that the input data contains both a transformation matrix, and -% a list of dipole positions (isvolume && issource). this fixed, led to a crash -% in get_source_trial, in which the dimensionality was incorrectly assigned -% -% Revision 1.47 2008/07/31 20:26:39 roboos -% fixed bug in roi/roilabel (thanks to Ingrid) -% -% Revision 1.46 2008/07/31 16:25:16 roboos -% added support for the specification of atlas ROIs, masking the data in that region or averaging the data in ROIs (seperate or combined over hemispheres) -% probably this will not yet fully work for all possible input source reconstruction data -% -% Revision 1.45 2008/04/09 14:14:09 roboos -% only make neighbours if clustering is required -% better detection of mom for pcc (thanks to Till) -% -% Revision 1.44 2008/01/15 09:49:06 roboos -% more robust detection of number of output methods of statmethod (for matlab 6.5) -% -% Revision 1.43 2007/08/06 10:15:44 roboos -% do not automatically add cfg.dim in case of source_trials, since -% after sourcegrandaverage the code makes an incorrect guess about -% the dimensions (which was the problem that caused stripes in the source -% reconstructions of Juan) -% -% Revision 1.42 2007/07/31 08:32:03 jansch -% added support for managing single trial beamed csds -% -% Revision 1.41 2007/05/30 07:08:11 roboos -% use checkdata instead of fixinside -% -% Revision 1.40 2007/05/08 08:22:50 roboos -% only test for the dimension of the source volume if present -% -% Revision 1.39 2007/04/03 11:47:26 roboos -% removed the specific handling for actvsblT, shoul dnow be done with redefinetrial -% -% Revision 1.38 2007/03/27 15:32:18 erimar -% Passed the dimord to called function. Updated help. -% -% Revision 1.37 2007/02/27 09:52:59 roboos -% added check on the size of the design matrix -% -% Revision 1.36 2007/02/12 16:54:45 ingnie -% fixed bug for singleton time and/or frequency dimension (channel data) -% -% Revision 1.35 2007/01/29 11:08:22 roboos -% changed the reformatting of the output (thanks to Juan for reporting a bug) -% it now works correctly for each combination of avgoverchan/avgoverfreq/avgovertime -% -% Revision 1.34 2006/09/05 18:50:25 roboos -% fixed two small bugs in get_source_avg subfunction -% -% Revision 1.33 2006/08/07 12:34:36 jansch -% fixed bug in assignment of dimensionality in case of source.trial -% -% Revision 1.32 2006/07/27 12:23:48 roboos -% add cfg.dim and cfg.inside in case of source data -% -% Revision 1.31 2006/07/20 15:33:54 roboos -% added other relevant defaults for prepare_timefreq_data -% VS: ---------------------------------------------------------------------- -% -% Revision 1.30 2006/07/12 14:24:58 roboos -% added any to isnan -% -% Revision 1.29 2006/07/12 14:19:09 roboos -% neighbourselection output changed, hence modification needed here as well -% -% Revision 1.28 2006/07/06 12:44:33 jansch -% removed a bug in the assignment of the volume's dimension to the configuration -% in the case of sources as inputs -% -% Revision 1.27 2006/06/27 10:53:26 roboos -% replaced nan(n,m) by nan*zeros(n,m) for compatibility with matlab versions prior to 7.0 -% -% Revision 1.26 2006/06/21 10:34:45 roboos -% removed part of the old cvs history -% moved the selection of source data to seperate subfunctions -% -% Revision 1.25 2006/06/13 14:55:27 ingnie -% added defaults cfg.channel = 'all', and cfg.latency = 'all' -% -% Revision 1.24 2006/06/09 12:32:50 erimar -% Correct typo. -% -% Revision 1.23 2006/06/09 12:23:45 erimar -% Added call to NEIGHBOURSELECTION, for construction of the neighbourhood -% geometry in cfg.neighbours. -% -% Revision 1.22 2006/06/07 18:31:52 roboos -% the stat.mask cannot contain nans because it is logical, therefore fill the outside voxels with "false" values -% -% Revision 1.21 2006/06/07 12:56:26 roboos -% ensure that the design is horizontal, i.e. Nvar X Nrepl +% $Id: statistics_wrapper.m 1087 2010-05-18 12:00:14Z sashae $ % check if the input cfg is valid for this function cfg = checkconfig(cfg, 'renamed', {'approach', 'method'}); @@ -180,9 +79,9 @@ caller_ext = ''; end % evalin('caller', 'mfilename') does not work for Matlab 6.1 and 6.5 - istimelock = strcmp(caller_name,'timelockstatistics'); - isfreq = strcmp(caller_name,'freqstatistics'); - issource = strcmp(caller_name,'sourcestatistics'); + istimelock = strcmp(caller_name,'ft_timelockstatistics'); + isfreq = strcmp(caller_name,'ft_freqstatistics'); + issource = strcmp(caller_name,'ft_sourcestatistics'); else % cannot determine the calling function in Octave, try looking at the % data instead @@ -379,11 +278,20 @@ num = 1; end -% perform the statistical test -if num>1 - [stat, cfg] = statmethod(cfg, dat, cfg.design); +% perform the statistical test +if strcmp(func2str(statmethod),'statistics_montecarlo') % because statistics_montecarlo (or to be precise, clusterstat) requires to know whether it is getting source data, + % the following (ugly) work around is necessary + if num>1 + [stat, cfg] = statmethod(cfg, dat, cfg.design, 'issource',issource); + else + [stat] = statmethod(cfg, dat, cfg.design, 'issource', issource); + end else - [stat] = statmethod(cfg, dat, cfg.design); + if num>1 + [stat, cfg] = statmethod(cfg, dat, cfg.design); + else + [stat] = statmethod(cfg, dat, cfg.design); + end end if isstruct(stat) @@ -402,14 +310,14 @@ if issource if isempty(cfg.roi) || strcmp(cfg.avgoverroi, 'no') % remember the definition of the volume, assume that they are identical for all input arguments - try, stat.dim = varargin{1}.dim; end - try, stat.xgrid = varargin{1}.xgrid; end - try, stat.ygrid = varargin{1}.ygrid; end - try, stat.zgrid = varargin{1}.zgrid; end - try, stat.inside = varargin{1}.inside; end - try, stat.outside = varargin{1}.outside; end - try, stat.pos = varargin{1}.pos; end - try, stat.transform = varargin{1}.transform; end + try stat.dim = varargin{1}.dim; end + try stat.xgrid = varargin{1}.xgrid; end + try stat.ygrid = varargin{1}.ygrid; end + try stat.zgrid = varargin{1}.zgrid; end + try stat.inside = varargin{1}.inside; end + try stat.outside = varargin{1}.outside; end + try stat.pos = varargin{1}.pos; end + try stat.transform = varargin{1}.transform; end else stat.inside = 1:length(roilabel); stat.outside = []; @@ -501,7 +409,7 @@ % SUBFUNCTION for extracting the data of interest % data resemples PCC beamed source reconstruction, multiple trials are coded in mom %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [dat, cfg] = get_source_pcc_mom(cfg, varargin); +function [dat, cfg] = get_source_pcc_mom(cfg, varargin) Nsource = length(varargin); Nvoxel = length(varargin{1}.inside) + length(varargin{1}.outside); Ninside = length(varargin{1}.inside); @@ -526,7 +434,7 @@ % SUBFUNCTION for extracting the data of interest % data resemples LCMV beamed source reconstruction, mom contains timecourse %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [dat, cfg] = get_source_lcmv_mom(cfg, varargin); +function [dat, cfg] = get_source_lcmv_mom(cfg, varargin) Nsource = length(varargin); Nvoxel = length(varargin{1}.inside) + length(varargin{1}.outside); Ntime = length(varargin{1}.avg.mom{varargin{1}.inside(1)}); @@ -551,7 +459,7 @@ % SUBFUNCTION for extracting the data of interest % data contains single-trial or single-subject source reconstructions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [dat, cfg] = get_source_trial(cfg, varargin); +function [dat, cfg] = get_source_trial(cfg, varargin) Nsource = length(varargin); Nvoxel = length(varargin{1}.inside) + length(varargin{1}.outside); @@ -568,12 +476,12 @@ else dim = [Nvoxel size(tmp{varargin{i}.inside(1)})]; end - if i==1 && j==1 && prod(size(tmp))~=Nvoxel, + if i==1 && j==1 && numel(tmp)~=Nvoxel, warning('the input-data contains more entries than the number of voxels in the volume, the data will be concatenated'); dat = zeros(prod(dim), sum(Ntrial)); %FIXME this is old code should be removed elseif i==1 && j==1 && iscell(tmp), warning('the input-data contains more entries than the number of voxels in the volume, the data will be concatenated'); - dat = zeros(Nvoxel*prod(size(tmp{varargin{i}.inside(1)})), sum(Ntrial)); + dat = zeros(Nvoxel*numel(tmp{varargin{i}.inside(1)}), sum(Ntrial)); elseif i==1 && j==1, dat = zeros(Nvoxel, sum(Ntrial)); end @@ -584,11 +492,11 @@ %tmpvec = (varargin{i}.inside-1)*prod(size(tmp{varargin{i}.inside(1)})); tmpvec = varargin{i}.inside; insidevec = []; - for m = 1:prod(size(tmp{varargin{i}.inside(1)})) + for m = 1:numel(tmp{varargin{i}.inside(1)}) insidevec = [insidevec; tmpvec(:)+(m-1)*Nvoxel]; end insidevec = insidevec(:)'; - tmpdat = reshape(permute(cat(3,tmp{varargin{1}.inside}), [3 1 2]), [Ninside prod(size(tmp{varargin{1}.inside(1)}))]); + tmpdat = reshape(permute(cat(3,tmp{varargin{1}.inside}), [3 1 2]), [Ninside numel(tmp{varargin{1}.inside(1)})]); dat(insidevec, k) = tmpdat(:); end % add original dimensionality of the data to the configuration, is required for clustering @@ -614,7 +522,7 @@ % SUBFUNCTION for extracting the data of interest % get the average source reconstructions, the repetitions are in multiple input arguments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [dat, cfg] = get_source_avg(cfg, varargin); +function [dat, cfg] = get_source_avg(cfg, varargin) Nsource = length(varargin); Nvoxel = length(varargin{1}.inside) + length(varargin{1}.outside); dim = varargin{1}.dim; @@ -636,14 +544,14 @@ % SUBFUNCTION for creating a design matrix % should be called in the code above, or in prepare_design %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [cfg] = get_source_design_pcc_mom(cfg, varargin); +function [cfg] = get_source_design_pcc_mom(cfg, varargin) % should be implemented -function [cfg] = get_source_design_lcmv_mom(cfg, varargin); +function [cfg] = get_source_design_lcmv_mom(cfg, varargin) % should be implemented -function [cfg] = get_source_design_trial(cfg, varargin); +function [cfg] = get_source_design_trial(cfg, varargin) % should be implemented -function [cfg] = get_source_design_avg(cfg, varargin); +function [cfg] = get_source_design_avg(cfg, varargin) % should be implemented diff --git a/external/fieldtrip/private/surfaceorientation.m b/external/fieldtrip/private/surfaceorientation.m index 22b3506..fe782df 100644 --- a/external/fieldtrip/private/surfaceorientation.m +++ b/external/fieldtrip/private/surfaceorientation.m @@ -11,10 +11,23 @@ % Copyright (C) 2007, Robert Oostenveld % -% $Log: surfaceorientation.m,v $ -% Revision 1.1 2007/05/16 11:45:59 roboos -% new implementation +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: surfaceorientation.m 952 2010-04-21 18:29:51Z roboos $ if nargin<3 ori = normals(pnt, tri, 'vertex'); diff --git a/external/fieldtrip/private/surfaceplot.m b/external/fieldtrip/private/surfaceplot.m deleted file mode 100644 index c190895..0000000 --- a/external/fieldtrip/private/surfaceplot.m +++ /dev/null @@ -1,260 +0,0 @@ -function [cfg] = surfaceplot(cfg, vol, surf) - -% SURFACEPLOT plot functional data on a rendered cortical surface. The -% distance between every voxel in the functional data to each surface point -% on the cortex is computed. Based on this distance, a weighted projection -% of the functional data onto the cortical surface is performed. Activity -% slightly below or otherwise misaligned with the cortical surface is -% therefore also projected onto the surface. The weighted projection also -% smooths the functional data. -% -% Use as -% surfaceplot(cfg, functional) or -% surfaceplot(cfg, functional, surface) -% where the functional data is obtained from SOURCEANALYSIS, -% SOURCEINTERPOLATE or VOLUMENORMALIZE. -% -% The configuration can contain -% cfg.method = 'nearest' 'sphere_avg', 'sphere_weighteddistance' -% cfg.sphereradius = maximum distance from each voxel to the surface to be -% included in the sphere projection methods, expressed in mm -% cfg.surffile = string, default is 'single_subj_T1.mat' which contains -% a triangulation that corresponds with the SPM anatomical -% template in MNI coordinates -% cfg.distmat = precomputed distance matrix (default = []) -% cfg.funparameter = string with the functional parameter of interest -% cfg.colmin = functional value mapped to the lowest color (default = 'auto') -% cfg.colmax = functional value mapped to the highest color (default = 'auto') -% cfg.maskparameter = string with an optional mask parameter -% cfg.maskcolmin = mask value mapped to the lowest opacity, i.e. completely transparent (default ='auto') -% cfg.maskcolmax = mask value mapped to the highest opacity, i.e. non-transparent (default = 'auto') -% cfg.downsample = number (default = 1, i.e. no downsampling) -% cfg.surfdownsample = number (default = 1, i.e. no downsampling) -% -% The resulting plot can be rotated in 3-D, or you can change the viewpoint -% using the VIEW command. -% -% See also SOURCEPLOT, SLICEINTERP - -% Copyright (C) 2006, Jan-Mathijs Schoffelen -% $Log: surfaceplot.m,v $ -% Revision 1.7 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.6 2006/07/13 08:48:46 ingnie -% fixed typo's in documentation -% -% Revision 1.5 2006/05/31 10:12:39 roboos -% fixed bug for inside voxels, renamed maxprojdist into sphereradius -% -% Revision 1.4 2006/05/31 07:00:39 roboos -% cleaned up surfaceplot, added options for downsampling volume and surface data, reimplemented nearest neighbour interpolation using distance matrix, flipped dimensions of collin27 surface, added transformation matrix -% -% Revision 1.3 2006/05/29 08:22:28 jansch -% made some changes -% -% Revision 1.2 2006/04/20 09:58:34 roboos -% updated documentation -% -% Revision 1.1 2006/01/27 15:41:24 jansch -% first implementation -% - -fieldtripdefs - -% set the defaults -if ~isfield(cfg, 'funparameter'), error('cfg.funparameter should be specified'); end -if ~isfield(cfg, 'sphereradius'), cfg.sphereradius = []; end -if ~isfield(cfg, 'maskparameter'), cfg.maskparameter = []; end -if ~isfield(cfg, 'colmin'), cfg.colmin = []; end -if ~isfield(cfg, 'colmax'), cfg.colmax = []; end -if ~isfield(cfg, 'maskcolmin'), cfg.maskcolmin = []; end -if ~isfield(cfg, 'maskcolmax'), cfg.maskcolmax = []; end -if ~isfield(cfg, 'distmat'), cfg.distmat = []; end -if ~isfield(cfg, 'downsample'), cfg.downsample = 1; end -if ~isfield(cfg, 'surfdownsample'), cfg.surfdownsample = 1; end - -% downsample the functional data -tmpcfg = []; -tmpcfg.downsample = cfg.downsample; -vol = volumedownsample(tmpcfg, vol); - -hasmask = ~isempty(cfg.maskparameter); - -if nargin<3 - % default is to use a triangulation that corresponds with the collin27 - % anatomical template in MNI coordinates - if ~isfield(cfg, 'surffile'), cfg.surffile = 'single_subj_T1.mat'; end - tmp = load(cfg.surffile, 'bnd'); - surf = tmp.bnd; -else - % the cortical surface is supplied by the user -end - -if ~isfield(vol, 'transform'), - vol.transform = eye(4); -end -if ~isfield(surf, 'transform'), - surf.transform = eye(4); -end - -%------extract the stuff that is needed from the input -param = parameterselection(cfg.funparameter, vol); -dat = getsubfield(vol, param{1}); -if hasmask, - maskparam = parameterselection(cfg.maskparameter, vol); - mask = getsubfield(vol, maskparam{1}); -end -dim = size(dat); -dimres = svd(vol.transform(1:3,1:3)); -if isfield(vol, 'inside') - inside = vol.inside; -else - inside = true(dim); -end -inside = inside(:); - -if isempty(cfg.colmin) - cfg.colmin = min(dat(:)); -end -if isempty(cfg.colmax) - cfg.colmax = max(dat(:)); -end - -if hasmask && isempty(cfg.maskcolmin) - cfg.maskcolmin = min(mask(:)); -end -if hasmask && isempty(cfg.maskcolmax) - cfg.maskcolmax = max(mask(:)); -end - -%------create a matrix, containing the functional voxels in head-coordinates -[X,Y,Z] = ndgrid(1:dim(1), 1:dim(2), 1:dim(3)); -pos = [X(:) Y(:) Z(:)]; clear X Y Z; -npos = size(pos,1); -pos = warp_apply(vol.transform, pos, 'homogenous'); - -%------create a matrix, containing the surface positions in head-coordinates -tri = surf.tri; -pnt = surf.pnt; -if cfg.surfdownsample>1 - [tri, pnt] = reducepatch(tri, pnt, 1/cfg.surfdownsample); -end -pnt = warp_apply(surf.transform, pnt, 'homogenous'); -npnt = size(pnt,1); - -fprintf('%d vertices in surface\n', npnt); -fprintf('%d voxels in functional data\n', npos); - -if ~isempty(cfg.distmat) - %------use the precomputed distance matrix - distmat = cfg.distmat; -else - %------compute a distance matrix - switch cfg.method - case 'nearest' - if ~isempty(cfg.sphereradius) - warning('cfg.sphereradius is not used for method''nearest'''); - end - % determine the nearest voxel for each surface point - sub = round(warp_apply(inv(vol.transform), pnt, 'homogenous')); % express surface vertices in voxel coordinates - sub(sub(:)<1) = 1; - sub(sub(:,1)>dim(1),1) = dim(1); - sub(sub(:,2)>dim(2),2) = dim(2); - sub(sub(:,3)>dim(3),3) = dim(3); - ind = sub2ind(dim, sub(:,1), sub(:,2), sub(:,3)); - distmat = sparse(1:npnt, ind, ones(size(ind)), npnt, npos); - % only voxels inside the brain contain a meaningful functional value - distmat = distmat(:, inside); - case {'sphere_avg', 'sphere_weighteddistance', 'sphere_weightedprojection'} - if isempty(cfg.sphereradius) - error('cfg.sphereradius should be specified'); - end - % the distance only has to be computed to voxels inside the brain - pos = pos(inside,:); - npos = size(pos,1); - % compute the distance between voxels and each surface point - dpntsq = sum(pnt.^2,2); % squared distance to origin - dpossq = sum(pos.^2,2); % squared distance to origin - maxnpnt = double(npnt*ceil(4/3*pi*(cfg.sphereradius/max(dimres))^3)); % initial estimate of nonzero entries - distmat = spalloc(npnt, npos, maxnpnt); - progress('init', 'textbar', 'computing distance matrix'); - for j = 1:npnt - progress(j/npnt); - d = sqrt(dpntsq(j) + dpossq - 2 * pos * pnt(j,:)'); - sel = find(dcfg.maskcolmax)) = cfg.maskcolmax; end - %if ~isempty(cfg.maskcolmin), maskval(find(maskval. % +% $Id: svdfft.m 952 2010-04-21 18:29:51Z roboos $ if nargin == 1, n = size(f,1); diff --git a/external/fieldtrip/private/swapmemfile.m b/external/fieldtrip/private/swapmemfile.m index 33c007b..547e824 100644 --- a/external/fieldtrip/private/swapmemfile.m +++ b/external/fieldtrip/private/swapmemfile.m @@ -20,21 +20,23 @@ % Copyright (C) 2004, Robert Oostenveld % -% $Log: swapmemfile.m,v $ -% Revision 1.4 2006/04/10 16:35:20 ingnie -% updated documentation +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.3 2005/05/17 17:50:50 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.2 2004/11/08 11:37:36 roboos -% switched file detection from Matlab function "matfinfo" to own function "filetype" -% since matfinfo caused troubles between different matlab versions +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.1 2004/10/29 11:37:56 roboos -% new implementation, required for prepare_timefreq_data on very large datasets that do not fit into memory simultaneously +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: swapmemfile.m 952 2010-04-21 18:29:51Z roboos $ % this variable will be empty at the first call persistent file diff --git a/external/fieldtrip/private/syntheticgradient.m b/external/fieldtrip/private/syntheticgradient.m deleted file mode 100644 index 021e9a8..0000000 --- a/external/fieldtrip/private/syntheticgradient.m +++ /dev/null @@ -1,186 +0,0 @@ -function [data] = syntheticgradient(cfg, data); - -% SYNTHETICGRADIENT applies CTFs higher-order synthetic gradients -% to preprocessed or averaged data and to the corresponding -% gradiometer definition. -% -% Use as -% [data] = syntheticgradient(cfg, data); -% where data should come from PREPROCESSING or TIMELOCKANALYSIS -% and the configuration should contain -% -% cfg.input = 'none', 'G1BR', 'G2BR' or 'G3BR' specifies the balancing -% of the input data (default is 'none') -% -% cfg.output = 'none', 'G1BR', 'G2BR' or 'G3BR' specifies the balancing -% of the output data (default is 'none') -% -% Currently it is not possible to determine the balancing of the data from -% the preprocessed data or from the CTF *.res4 header. Therefore it is -% important to specify the balancing of the input data correctly. - -% Copyright (C) 2004-2006, Robert Oostenveld -% -% $Log: syntheticgradient.m,v $ -% Revision 1.8 2006/03/29 08:40:26 roboos -% fixed documentation -% -% Revision 1.7 2005/06/29 12:46:29 roboos -% the following changes were done on a large number of files at the same time, not all of them may apply to this specific file -% - added try-catch around the inclusion of input data configuration -% - moved cfg.version, cfg.previous and the assignment of the output cfg to the end -% - changed help comments around the configuration handling -% - some changes in whitespace -% -% Revision 1.6 2005/05/17 17:50:39 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.5 2004/07/02 13:48:36 roboos -% detected a bug in the grad computation and added an error messgae there -% the bug is still not fixed -% -% Revision 1.4 2004/07/02 12:37:52 roboos -% removed the default for the input and output -% added support for averaged data -% -% Revision 1.3 2004/07/02 11:51:17 roboos -% fixed some small bugs -% -% Revision 1.2 2004/07/02 11:40:26 roboos -% fixed bug in switch-otherwise -% -% Revision 1.1 2004/07/02 11:32:50 roboos -% new implementation, requires external coefficients file for the transformation -% - -% these MUST be specified, since they cannot be determined from the data itself -if ~isfield(cfg, 'input') - error('you must specify the balancing of the input data'); -end -if ~isfield(cfg, 'output') - error('you must specify the balancing of the output data'); -end - -% read the coefficients from the FCDC specific file -load ctf_coef - -if isfield(data, 'avg') - % treat the average just as if it was a single trial - data.trial = {}; - data.trial{1} = data.avg; - isavgdata = 1; -else - isavgdata = 0; -end - -% find the matching channels, channel order corresponds to coef -[selcoef, seldat] = match_str(coef.label, data.label); - -if length(seldat). +% +% $Id: time2offset.m 952 2010-04-21 18:29:51Z roboos $ offset = round(time(1)*fsample); diff --git a/external/fieldtrip/private/timelock2freq.m b/external/fieldtrip/private/timelock2freq.m index de21698..304987b 100644 --- a/external/fieldtrip/private/timelock2freq.m +++ b/external/fieldtrip/private/timelock2freq.m @@ -8,10 +8,23 @@ % Copyright (C) 2005, Robert Oostenveld % -% $Log: timelock2freq.m,v $ -% Revision 1.1 2005/10/14 15:50:08 roboos -% new implementation, used by dipolefitting in case of frequency or ICA data +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: timelock2freq.m 952 2010-04-21 18:29:51Z roboos $ n = size(mom,2)/2; diff --git a/external/fieldtrip/private/timelockanalysis.m b/external/fieldtrip/private/timelockanalysis.m deleted file mode 100644 index 73c8759..0000000 --- a/external/fieldtrip/private/timelockanalysis.m +++ /dev/null @@ -1,694 +0,0 @@ -function [timelock] = timelockanalysis(cfg, data) - -% TIMELOCKANALYSIS performs timelocked analysis such as averaging -% and covariance computation -% -% [timelock] = timelockanalysis(cfg, data) -% -% The data should be organised in a structure as obtained from the -% PREPROCESSING function. The configuration should be according to -% -% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), -% see CHANNELSELECTION for details -% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') -% cfg.latency = [begin end] in seconds, or 'minperlength', 'maxperlength', -% 'prestim', 'poststim' (default = 'maxperlength') -% cfg.covariance = 'no' or 'yes' -% cfg.covariancewindow = [begin end] -% cfg.blcovariance = 'no' or 'yes' -% cfg.blcovariancewindow = [begin end] -% cfg.keeptrials = 'yes' or 'no', return individual trials or average (default = 'no') -% cfg.normalizevar = 'N' or 'N-1' (default = 'N-1') -% cfg.removemean = 'no' or 'yes' for covariance computation (default = 'yes') -% cfg.vartrllength = 0, 1 or 2 (see below) -% -% Depending on cfg.vartrllength, variable trials and missing values -% are treated differently: -% 0 - do not accept variable length trials [default] -% 1 - accept variable length trials, but only take those trials in which -% data is present in both the average and the covariance window -% 2 - accept variable length trials, use all available trials -% the available samples in every trial will be used for the -% average and covariance computation. Missing values are replaced -% by NaN and are not included in the computation. - -% FIXME if input is one raw trial, the covariance is not computed correctly -% -% Undocumented local options: -% cfg.feedback -% cfg.normalizecov -% cfg.preproc -% -% This function depends on PREPROC which has the following options: -% cfg.absdiff -% cfg.blc -% cfg.blcwindow -% cfg.boxcar -% cfg.bpfilter -% cfg.bpfiltord -% cfg.bpfilttype -% cfg.bpfreq -% cfg.derivative -% cfg.detrend -% cfg.dftfilter -% cfg.dftfreq -% cfg.hilbert -% cfg.hpfilter -% cfg.hpfiltord -% cfg.hpfilttype -% cfg.hpfreq -% cfg.implicitref -% cfg.lpfilter -% cfg.lpfiltord -% cfg.lpfilttype -% cfg.lpfreq -% cfg.medianfilter -% cfg.medianfiltord -% cfg.rectify -% cfg.refchannel -% cfg.reref - -% Copyright (C) 2003-2006, Markus Bauer -% Copyright (C) 2003-2006, Robert Oostenveld -% -% $Log: timelockanalysis.m,v $ -% Revision 1.60 2009/03/23 21:21:16 roboos -% removed defaults for covariancewindow and blcovariancewindow, since the defaults were not optimal for most cases. Now the user is forced to specify the window. -% -% Revision 1.59 2009/02/04 16:44:06 roboos -% remove numsamples, numcovsamples and numblcovsamples from the output, since these are not used anywhere -% -% Revision 1.58 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.57 2009/01/12 13:05:20 sashae -% small change in call to checkconfig -% -% Revision 1.56 2008/11/11 18:59:26 sashae -% added call to checkconfig at end of function (trackconfig and checksize) -% -% Revision 1.55 2008/10/01 15:51:26 sashae -% call to checkconfig instead of createsubcfg -% -% Revision 1.54 2008/09/26 12:42:18 sashae -% checkconfig: checks if the input cfg is valid for this function -% -% Revision 1.53 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.52 2008/07/11 13:18:40 roboos -% removed all lnfilter references, added error to preprocessing and preproc -% -% Revision 1.51 2008/06/10 16:45:04 sashae -% replaced call to blc function with preproc_baselinecorrect -% -% Revision 1.50 2008/05/06 15:43:46 sashae -% change in trial selection, cfg.trials can be logical -% -% Revision 1.49 2008/01/29 18:06:13 sashae -% added option for trial selection -% removed some old code -% adding of offset field now done with checkdata (hasoffset='yes') -% -% Revision 1.48 2007/10/31 17:05:00 roboos -% represent dof as matrix instead of vector -% -% Revision 1.47 2007/05/30 11:41:10 roboos -% renamed dofvec into dof -% -% Revision 1.46 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.45 2007/03/30 17:05:40 ingnie -% checkinput; only proceed when input data is allowed datatype -% -% Revision 1.44 2006/10/04 07:10:08 roboos -% updated documentation -% -% Revision 1.43 2006/06/14 12:44:03 roboos -% removed the documentation for cfg.lnfilttype, since that option is not supported by preproc -% -% Revision 1.42 2006/06/14 11:53:54 roboos -% switched to using cfg.preproc substructure -% -% Revision 1.41 2006/06/13 14:48:11 ingnie -% updated documentation -% -% Revision 1.40 2006/06/06 16:57:51 ingnie -% updated documentation -% -% Revision 1.39 2006/04/25 17:06:28 ingnie -% updated documentation -% -% Revision 1.38 2006/04/20 09:58:34 roboos -% updated documentation -% -% Revision 1.37 2006/02/01 12:26:00 roboos -% made all uses of dimord consistent with the common definition of data dimensions, see the fixdimord() function -% -% Revision 1.36 2005/11/21 11:57:37 roboos -% replaced sum by nan_sum in computation of covariance for variable length data -% -% Revision 1.35 2005/06/29 12:46:29 roboos -% the following changes were done on a large number of files at the same time, not all of them may apply to this specific file -% - added try-catch around the inclusion of input data configuration -% - moved cfg.version, cfg.previous and the assignment of the output cfg to the end -% - changed help comments around the configuration handling -% - some changes in whitespace -% -% Revision 1.34 2005/06/17 10:56:12 roboos -% switched from local implementation of data conversion towards new data2raw private function -% this also fixed a problem that I observed with some simulated data, but I did not look into detail in that problem -% -% Revision 1.33 2005/05/17 17:50:39 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.32 2005/04/25 09:53:16 roboos -% fixed important bug in channel label ordering when specifying own cfg.channel -% fixed small bug for trials containing only one sample (these were left out) -% changed output cfg assignment of preprocessing cfg options -% -% Revision 1.31 2005/04/07 17:05:36 roboos -% replaced fprintf feedback by more flexible progress indicator -% -% Revision 1.30 2005/04/05 19:12:48 roboos -% added support for average input (converted to single trial) to allow for more interactive playing around with filter and blc settings for figures -% fixed error in preproc when cfg.implicitref was specified (implicitref was not included in the outpu of timelockanalysis) -% -% Revision 1.29 2005/02/16 08:44:11 roboos -% fixed weird typo in numsamples, don't know when that was introduced -% -% Revision 1.28 2004/12/09 17:33:06 roboos -% removed blc and bpfilter -% implemented filtering and all other preprocessing options with new private/preproc function -% -% Revision 1.27 2004/11/02 14:30:39 roboos -% changed indentation of the code, no functional changes -% -% Revision 1.26 2004/10/25 10:02:34 roboos -% fixed bug in covariance computation for 1 trial -% cleaned up the definition and detection of the length of the time axis in the input data -% -% Revision 1.25 2004/10/22 16:18:41 roboos -% also added dimord if keeptrials=no -% -% Revision 1.24 2004/09/22 10:20:27 roboos -% converted to use external subfunctions time2offset and offset2time -% and add offset field to data structure if it is missing -% -% Revision 1.23 2004/08/06 06:26:29 roboos -% only stylistic changes, nu functionality change -% -% Revision 1.22 2004/06/24 10:14:46 roberto -% implemented baselinecorrection (as undocumented/advanced feature) -% keep data.elec in output average just as data.grad -% -% Revision 1.21 2004/04/13 16:31:09 roberto -% fixed bug in dbstack selection of function filename for Matlab 6.1 -% -% Revision 1.20 2004/04/13 14:25:24 roberto -% wrapped code-snippet around mfilename to make it compatible with Matlab 6.1 -% -% Revision 1.19 2004/03/29 15:08:18 roberto -% added cfg.bpfilttype = fir|but to documentation -% -% Revision 1.18 2004/03/22 15:57:37 roberto -% restructured version output in configuration -% -% Revision 1.17 2004/03/22 15:47:23 roberto -% added version and previous cfg to output cfg -% -% Revision 1.16 2004/03/10 12:55:26 roberto -% fixed bug in output dimord, should be trial_chan_time instead of chan_time_trial -% -% Revision 1.15 2004/03/03 15:27:32 roberto -% incorporated couple of bug-fixes from Markus B. and one from Markus S. -% improved and restructured help -% -% Revision 1.14 2004/02/27 13:13:08 roberto -% fixed small error in the documentation -% -% Revision 1.13 2004/02/23 08:50:29 roberto -% added a dimord string to the output -% -% Revision 1.12 2004/02/17 15:36:47 roberto -% fixed multiple bugs that were still outstanding ue to the recent added support for variable trial length -% -% Revision 1.11 2004/02/17 09:30:05 roberto -% corrected automatic updating of latency windows -% -% Revision 1.10 2004/02/16 17:02:42 roberto -% added support for variable length trials, this required many changes -% -% Revision 1.9 2004/02/11 09:05:09 roberto -% removed default bandpass frequencies, changed default bpfiltord to -% 4 (from 25), added support for other filter types, removed the -% filtering options from the visible help -% -% Revision 1.8 2004/01/26 16:48:39 roberto -% added check for valid latency window -% -% Revision 1.7 2003/11/17 15:57:22 roberto -% fixed bug in counting number of channels in output data -% -% Revision 1.6 2003/11/17 15:15:02 roberto -% renamed default cfg item bpfltord into bpfiltord to fix code inconsistency -% -% Revision 1.5 2003/10/31 11:39:41 roberto -% switched from translate_channel_list to channelselection function -% -% Revision 1.4 2003/10/23 06:41:14 roberto -% added Markus' bandpass filtering -% -% Revision 1.3 2003/09/11 21:53:47 roberto -% switched to new channel group selection with translate_channel_list() -% fixed bug caused by removing too much code -% -% Revision 1.2 2003/04/23 10:14:32 roberto -% fixed some small bugs that I thought were fixed already earlier (!?) -% -% Revision 1.1.1.1 2003/04/17 12:35:19 roberto -% initial version under CVS control -% - -fieldtripdefs - -% check if the input data is valid for this function -data = checkdata(data, 'datatype', {'raw', 'comp'}, 'feedback', 'yes', 'hasoffset', 'yes'); - -% check if the input cfg is valid for this function -cfg = checkconfig(cfg, 'trackconfig', 'on'); -cfg = checkconfig(cfg, 'deprecated', {'normalizecov', 'normalizevar'}); - -% set the defaults -if ~isfield(cfg, 'channel'), cfg.channel = 'all'; end -if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end -if ~isfield(cfg, 'keeptrials'), cfg.keeptrials = 'no'; end -if ~isfield(cfg, 'latency'), cfg.latency = 'maxperlength'; end -if ~isfield(cfg, 'covariance'), cfg.covariance = 'no'; end -if ~isfield(cfg, 'blcovariance'), cfg.blcovariance = 'no'; end -if ~isfield(cfg, 'removemean'), cfg.removemean = 'yes'; end -if ~isfield(cfg, 'vartrllength'), cfg.vartrllength = 0; end -if ~isfield(cfg, 'feedback'), cfg.feedback = 'text'; end - -% convert average to raw data for convenience, the output will be an average again -% the purpose of this is to allow for repeated baseline correction, filtering and other preproc options that timelockanalysis supports -data = data2raw(data); - -% select trials of interest -if ~strcmp(cfg.trials, 'all') - if islogical(cfg.trials), cfg.trials=find(cfg.trials); end - fprintf('selecting %d trials\n', length(cfg.trials)); - data.trial = data.trial(cfg.trials); - data.time = data.time(cfg.trials); - data.offset = data.offset(cfg.trials); - % update the trial definition (trl) - if isfield(data, 'cfg') % try to locate the trl in the nested configuration - trl = findcfg(data.cfg, 'trl'); - else - trl = []; - end - if isempty(trl) - % a trial definition is expected in each continuous data set - warning('could not locate the trial definition ''trl'' in the data structure'); - else - cfg.trlold=trl; - cfg.trl=trl(cfg.trials,:); - end -end - -ntrial = length(data.trial); - -% ensure that the preproc specific options are located in the cfg.preproc substructure -cfg = checkconfig(cfg, 'createsubcfg', {'preproc'}); - -% preprocess the data, i.e. apply filtering, baselinecorrection, etc. -fprintf('applying preprocessing options\n'); -for i=1:ntrial - [data.trial{i}, data.label, data.time{i}, cfg.preproc] = preproc(data.trial{i}, data.label, data.fsample, cfg.preproc, data.offset(i)); -end - -% determine the channels of interest -cfg.channel = channelselection(cfg.channel, data.label); -chansel = match_str(data.label, cfg.channel); -nchan = length(cfg.channel); % number of channels -numsamples = zeros(ntrial,1); % number of selected samples in each trial, is determined later - -% determine the duration of each trial -for i=1:ntrial - begsamplatency(i) = min(data.time{i}); - endsamplatency(i) = max(data.time{i}); -end - -% automatically determine the latency window which is possible in all trials -minperlength = [max(begsamplatency) min(endsamplatency)]; -maxperlength = [min(begsamplatency) max(endsamplatency)]; -maxtrllength = round((max(endsamplatency)-min(begsamplatency))*data.fsample) + 1; % in samples -abstimvec = ([1:maxtrllength] + min(data.offset) -1)./data.fsample; % in seconds - -% latency window for averaging and variance computation is given in seconds -if (strcmp(cfg.latency, 'minperlength')) - cfg.latency = []; - cfg.latency(1) = minperlength(1); - cfg.latency(2) = minperlength(2); -end -if (strcmp(cfg.latency, 'maxperlength')) - cfg.latency = []; - cfg.latency(1) = maxperlength(1); - cfg.latency(2) = maxperlength(2); -end -if (strcmp(cfg.latency, 'prestim')) - cfg.latency = []; - cfg.latency(1) = maxperlength(1); - cfg.latency(2) = 0; -end -if (strcmp(cfg.latency, 'poststim')) - cfg.latency = []; - cfg.latency(1) = 0; - cfg.latency(2) = maxperlength(2); -end - -% check whether trial type (varlength) matches the user-specified type -switch cfg.vartrllength - case 0 - if ~all(minperlength==maxperlength) - error('data has variable trial lengths, you specified not to accept that !'); - end - case 1 - if all(minperlength==maxperlength) - disp('data is of type fixed length !'); - end - case 2 - if strcmp(cfg.keeptrials,'yes') - disp('processing and keeping variable length single trials'); - end - otherwise - error('unknown value for vartrllength'); -end - -% check whether the time window fits with the data -if (cfg.latency(1) < maxperlength(1)) cfg.latency(1) = maxperlength(1); - warning('Correcting begin latency of averaging window'); -end -if (cfg.latency(2) > maxperlength(2)) cfg.latency(2) = maxperlength(2); - warning('Correcting end latency of averaging window'); -end -if cfg.latency(1)>cfg.latency(2) - error('invalid latency window specified'); -end - -if strcmp(cfg.covariance, 'yes') - if ~isfield(cfg, 'covariancewindow') - % this used to be by default 'poststim', but that is not ideal as default - error('the option cfg.covariancewindow is required'); - end - % covariance window is given in seconds - if (strcmp(cfg.covariancewindow, 'minperlength')) - cfg.covariancewindow = []; - cfg.covariancewindow(1) = minperlength(1); - cfg.covariancewindow(2) = minperlength(2); - end - if (strcmp(cfg.covariancewindow, 'maxperlength')) - cfg.covariancewindow = []; - cfg.covariancewindow(1) = maxperlength(1); - cfg.covariancewindow(2) = maxperlength(2); - end - if (strcmp(cfg.covariancewindow, 'prestim')) - cfg.covariancewindow = []; - cfg.covariancewindow(1) = maxperlength(1); - cfg.covariancewindow(2) = 0; - end - if (strcmp(cfg.covariancewindow, 'poststim')) - cfg.covariancewindow = []; - cfg.covariancewindow(1) = 0; - cfg.covariancewindow(2) = maxperlength(2); - end - % check whether the time window fits with the data - if (cfg.covariancewindow(1) < maxperlength(1)) - cfg.covariancewindow(1) = maxperlength(1); - warning('Correcting begin latency of covariance window'); - end - if (cfg.covariancewindow(2) > maxperlength(2)) - cfg.covariancewindow(2) = maxperlength(2); - warning('Correcting end latency of covariance window'); - end - if cfg.covariancewindow(1)==cfg.covariancewindow(2) - error('Cannot compute covariance over a window of only one sample'); - end - if cfg.covariancewindow(1)>cfg.covariancewindow(2) - error('Cannot compute covariance over negative timewindow'); - end -end - -if strcmp(cfg.blcovariance, 'yes') - if ~isfield(cfg, 'blcovariancewindow') - % this used to be by default 'prestim', but that is not ideal as default - error('the option cfg.blcovariancewindow is required'); - end - % covariance window is given in seconds - if (strcmp(cfg.blcovariancewindow, 'minperlength')) - cfg.blcovariancewindow = []; - cfg.blcovariancewindow(1) = minperlength(1); - cfg.blcovariancewindow(2) = minperlength(2); - end - if (strcmp(cfg.blcovariancewindow, 'maxperlength')) - cfg.blcovariancewindow = []; - cfg.blcovariancewindow(1) = maxperlength(1); - cfg.blcovariancewindow(2) = maxperlength(2); - end - if (strcmp(cfg.blcovariancewindow, 'prestim')) - cfg.blcovariancewindow = []; - cfg.blcovariancewindow(1) = maxperlength(1); - cfg.blcovariancewindow(2) = 0; - end - if (strcmp(cfg.blcovariancewindow, 'poststim')) - cfg.blcovariancewindow = []; - cfg.blcovariancewindow(1) = 0; - cfg.blcovariancewindow(2) = maxperlength(2); - end - % check whether the time window fits with the data - if (cfg.blcovariancewindow(1) < maxperlength(1)) - cfg.blcovariancewindow(1) = maxperlength(1); - warning('Correcting begin latency of covariance window'); - end - if (cfg.blcovariancewindow(2) > maxperlength(2)) - cfg.blcovariancewindow(2) = maxperlength(2); - warning('Correcting end latency of covariance window'); - end - if cfg.blcovariancewindow(1)==cfg.blcovariancewindow(2) - error('Cannot compute covariance over a window of only one sample'); - end - if cfg.blcovariancewindow(1)>cfg.blcovariancewindow(2) - error('Cannot compute covariance over negative timewindow'); - end -end - -% pre-allocate some memory space for the covariance matrices -if strcmp(cfg.covariance, 'yes') - covsig = nan*zeros(ntrial, nchan, nchan); - numcovsigsamples = zeros(ntrial,1); -end -if strcmp(cfg.blcovariance, 'yes') - covbl = nan*zeros(ntrial, nchan, nchan); - numcovblsamples = zeros(ntrial,1); -end - -begsampl = nearest(abstimvec, cfg.latency(1)); -endsampl = nearest(abstimvec, cfg.latency(2)); -maxwin = endsampl-begsampl+1; -s = zeros(nchan, maxwin); % this will contain the sum -ss = zeros(nchan, maxwin); % this will contain the squared sum -dof = zeros(1, maxwin); -if (strcmp(cfg.keeptrials,'yes')) - singtrial = nan*zeros(ntrial, nchan, maxwin); -end - -progress('init', cfg.feedback, 'averaging trials'); -% do all the computations -for i=1:ntrial - % fprintf('averaging trial %d of %d\n', i, ntrial); - progress(i/ntrial, 'averaging trial %d of %d\n', i, ntrial); - - % determine whether the data in this trial can be used for all the requested computations - switch cfg.vartrllength - case 0 - % include this trial in any case since validation of data already done - usetrial = 1; - case 1 - % include this trial only if the data are complete in all specified windows - usetrial = 1; - if (begsamplatency(i)>cfg.latency(1) || endsamplatency(i)cfg.covariancewindow(1) || endsamplatency(i)cfg.blcovariancewindow(1) || endsamplatency(i)= cfg.latency(1)) - begsampl = nearest(data.time{i}, cfg.latency(1)); - endsampl = nearest(data.time{i}, cfg.latency(2)); - numsamples(i) = endsampl-begsampl+1; - if (cfg.latency(1) cfg.latency(1) - cfg.latency(1) = min(varargin{s}.time); - end - if max(varargin{s}.time) < cfg.latency(2) - cfg.latency(2) = max(varargin{s}.time); - end - end -end - -%SELECT TIME WINDOW -idxs = nearest(varargin{1}.time, min(cfg.latency)); -idxe = nearest(varargin{1}.time, max(cfg.latency)); -% shift start and end index in case of flipped time axis (potentially introduced for response time locked data) -if idxe < idxs - ResultsTimeSelectCases = idxe:idxs; -else - ResultsTimeSelectCases = idxs:idxe; -end -ResultsNTimePoints = length(ResultsTimeSelectCases); -ResultsTime = varargin{1}.time(ResultsTimeSelectCases); - -%UPDATE CFG STRUCTURE WITH TIME THAT WAS FINALLY USED -cfg.latency = [ResultsTime(1), ResultsTime(end)]; - -%DETERMINE WHICH CHANNELS ARE AVAILABLE FOR ALL SUBJECTS -for i=1:Nsubj - cfg.channel = channelselection(cfg.channel, varargin{i}.label); -end -ResultNChannels = size(cfg.channel, 1); - -%REDUCE DATASET TO INTERSECTION OF DESIRED AND AVAILABLE CHANNELS -for i=1:Nsubj - % select channel indices in this average, sorted according to configuration - [dum, chansel] = match_str(cfg.channel, varargin{i}.label); - varargin{i}.avg = varargin{i}.avg(chansel,:); - varargin{i}.label = varargin{i}.label(chansel); - try, varargin{i}.trial = varargin{i}.trial(chansel,:,:); end -end - -%PREALLOCATE -avgmat = zeros(Nsubj, ResultNChannels, ResultsNTimePoints); -%FILL MATRIX, MAY BE DONE MORE EFFECTIVELY WITH DEAL COMMAND -for s = 1:Nsubj - avgmat(s, :, :) = varargin{s}.avg(:, ResultsTimeSelectCases); -end - -%AVERAGE ACROSS SUBJECT DIMENSION -ResultGrandavg = mean(avgmat, 1); -ResultGrandavg = reshape(ResultGrandavg, [ResultNChannels, ResultsNTimePoints]); - -%COMPUTE VARIANCE ACROSS SUBJECT DIMENSION -%THIS LOOKS AWKWARD (std.^2) BUT IS FAST DUE TO BUILT IN FUNCTIONS -switch cfg.normalizevar - case 'N-1' - sdflag = 0; - case 'N' - sdflag = 1; -end -ResultVar = std(avgmat, sdflag, 1).^2; -ResultVar = reshape(ResultVar, [ResultNChannels, ResultsNTimePoints]); - -%-------------------------------------------- -% % collect the results -%-------------------------------------------- - -%SWITCH CHANNEL TO LABEL? -grandavg.label = cfg.channel; % cell-array -grandavg.fsample = varargin{1}.fsample; -grandavg.avg = ResultGrandavg; % Nchan x Nsamples -grandavg.var = ResultVar; % Nchan x Nsamples -grandavg.time = ResultsTime; % 1 x Nsamples - -%KEEP INDIVIDUAL MEANS? -if strcmp(cfg.keepindividual, 'yes') - grandavg.individual = avgmat; % Nsubj x Nchan x Nsamples - grandavg.dimord = 'subj_chan_time'; -else - grandavg.dimord = 'chan_time'; -end - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: timelockgrandaverage.m,v 1.21 2009/01/20 13:01:31 sashae Exp $'; -% remember the configuration details of the input data -cfg.previous = []; -for i=1:length(varargin) - try, cfg.previous{i} = varargin{i}.cfg; end -end -% remember the exact configuration details in the output -grandavg.cfg = cfg; - diff --git a/external/fieldtrip/private/timelockstatistics.m b/external/fieldtrip/private/timelockstatistics.m deleted file mode 100644 index c82df31..0000000 --- a/external/fieldtrip/private/timelockstatistics.m +++ /dev/null @@ -1,139 +0,0 @@ -function [stat] = timelockstatistics(cfg, varargin) - -% TIMELOCKSTATISTICS computes significance probabilities and/or critical values of a parametric statistical test -% or a non-parametric permutation test. -% -% Use as -% [stat] = timelockstatistics(cfg, timelock1, timelock2, ...) -% where the input data is the result from either TIMELOCKANALYSIS or -% TIMELOCKGRANDAVERAGE. -% -% The configuration can contain the following options for data selection -% cfg.channel = Nx1 cell-array with selection of channels (default = 'all'), -% see CHANNELSELECTION for details -% cfg.latency = [begin end] in seconds or 'all' (default = 'all') -% cfg.avgoverchan = 'yes' or 'no' (default = 'no') -% cfg.avgovertime = 'yes' or 'no' (default = 'no') -% cfg.parameter = string (default = 'trial' or 'avg') -% -% Furthermore, the configuration should contain -% cfg.method = different methods for calculating the significance probability and/or critical value -% 'montecarlo' get Monte-Carlo estimates of the significance probabilities and/or critical values from the permutation distribution, -% 'analytic' get significance probabilities and/or critical values from the analytic reference distribution (typically, the sampling distribution under the null hypothesis), -% 'stats' use a parametric test from the Matlab statistics toolbox, -% 'glm' use a general linear model approach. -% -% The other cfg options depend on the method that you select. You -% should read the help of the respective subfunction STATISTICS_XXX -% for the corresponding configuration options and for a detailed -% explanation of each method. -% -% See also TIMELOCKANALYSIS, TIMELOCKGRANDAVERAGE - -% This function depends on STATISTICS_WRAPPER - -% Copyright (C) 2005-2006, Robert Oostenveld -% -% $Log: timelockstatistics.m,v $ -% Revision 1.25 2009/04/08 15:57:08 roboos -% moved the handling of the output cfg (with all history details) from wrapper to main function -% -% Revision 1.24 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.23 2007/05/10 10:18:39 ingnie -% disabled checkinput for the time being, since timelock data can contain stat/zvalue/tvalue instead of an avg -% -% Revision 1.22 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.21 2007/03/30 17:05:40 ingnie -% checkinput; only proceed when input data is allowed datatype -% -% Revision 1.20 2007/03/27 15:19:14 erimar -% Updated help (replaced "p-value" by "significance probability". -% -% Revision 1.19 2006/11/27 15:38:20 roboos -% implemented support for cfg.parameter, by locally renaming the field in the data structure -% -% Revision 1.18 2006/10/19 15:05:51 roboos -% updated documentation -% -% Revision 1.17 2006/10/04 07:10:08 roboos -% updated documentation -% -% Revision 1.16 2006/07/12 09:18:17 roboos -% improved documentation -% -% Revision 1.15 2006/06/20 12:57:51 roboos -% updated documentation, removed support for Jens' old options -% -% Revision 1.14 2006/06/13 14:48:12 ingnie -% updated documentation - -fieldtripdefs - -% check if the input data is valid for this function -for i=1:length(varargin) - % FIXME at this moment (=10 May) this does not work, because the input might not always have an avg - % See freqstatistics - %varargin{i} = checkdata(varargin{i}, 'datatype', 'timelock', 'feedback', 'no'); -end - -% the low-level data selection function does not know how to deal with other parameters, so work around it -if isfield(cfg, 'parameter') - if strcmp(cfg.parameter, 'trial') || strcmp(cfg.parameter, 'individual') - % this is dealt with correctly in the low-level code, even if an average is present - elseif strcmp(cfg.parameter, 'avg') - % this is only dealt with in the low-level code if no single-trial/individual data is present - for i=1:length(varargin) - if isfield(varargin{i}, 'trial') - varargin{i} = rmfield(varargin{i}, 'trial'); - end - if isfield(varargin{i}, 'individual') - varargin{i} = rmfield(varargin{i}, 'individual'); - end - end - else - % rename the parameter of interest into 'avg' - fprintf('renaming parameter ''%s'' into ''avg''\n', cfg.parameter); - for i=1:length(varargin) - dat = getsubfield(varargin{i}, cfg.parameter); - varargin{i} = rmsubfield (varargin{i}, cfg.parameter); - varargin{i} = setsubfield(varargin{i}, 'avg', dat); - if isfield(varargin{i}, 'trial') - varargin{i} = rmfield(varargin{i}, 'trial'); - end - if isfield(varargin{i}, 'individual') - varargin{i} = rmfield(varargin{i}, 'individual'); - end - end - end -end - -% call the general function -[stat, cfg] = statistics_wrapper(cfg, varargin{:}); - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: timelockstatistics.m,v 1.25 2009/04/08 15:57:08 roboos Exp $'; - -% remember the configuration of the input data -cfg.previous = []; -for i=1:length(varargin) - if isfield(varargin{i}, 'cfg') - cfg.previous{i} = varargin{i}.cfg; - else - cfg.previous{i} = []; - end -end - -% remember the exact configuration details -stat.cfg = cfg; diff --git a/external/fieldtrip/private/timestamp_neuralynx.m b/external/fieldtrip/private/timestamp_neuralynx.m index 17cacf5..0c2ee64 100644 --- a/external/fieldtrip/private/timestamp_neuralynx.m +++ b/external/fieldtrip/private/timestamp_neuralynx.m @@ -1,11 +1,31 @@ -function [ts] = timestamp_neuralynx(tsl, tsh); +function [ts] = timestamp_neuralynx(tsl, tsh) % TIMESTAMP_NEURALYNX merge the low and high part of Neuralynx timestamps % into a single uint64 value -if ~isa(tsl, 'uint32') +% Copyright (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: timestamp_neuralynx.m 945 2010-04-21 17:41:20Z roboos $ + +if ~isa(tsl, 'uint32') && ~isa(tsl, 'int32') error('invalid input'); -elseif ~isa(tsh, 'uint32') +elseif ~isa(tsh, 'uint32') && ~isa(tsl, 'int32') error('invalid input'); end diff --git a/external/fieldtrip/private/timestamp_plexon.m b/external/fieldtrip/private/timestamp_plexon.m index c019daa..3bbbdd7 100644 --- a/external/fieldtrip/private/timestamp_plexon.m +++ b/external/fieldtrip/private/timestamp_plexon.m @@ -1,8 +1,28 @@ -function [ts] = timestamp_plexon(tsl, tsh); +function [ts] = timestamp_plexon(tsl, tsh) % TIMESTAMP_PLEXON merge the low and high part of the timestamps % into a single uint64 value +% Copyright (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: timestamp_plexon.m 945 2010-04-21 17:41:20Z roboos $ + if ~isa(tsl, 'uint32') error('invalid input'); elseif ~isa(tsh, 'uint16') diff --git a/external/fieldtrip/private/tinv.m b/external/fieldtrip/private/tinv.m index 8d3ff33..e113b8a 100644 --- a/external/fieldtrip/private/tinv.m +++ b/external/fieldtrip/private/tinv.m @@ -9,16 +9,23 @@ % This is an open source function that was assembled by Eric Maris using % open source subfunctions found on the web. -% $Log: tinv.m,v $ -% Revision 1.6 2008/07/24 12:00:22 roboos -% changed end of line to unix style +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.5 2006/01/05 12:06:06 erimar -% This is an open source function that was assembled by Eric Maris using -% open source subfunctions found on the web. This function should behave -% as TINV.M of the Matlab Statistics Toolbox. A previous version of this -% open source tinv was accidentily removed, and this is now corrected. +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: tinv.m 952 2010-04-21 18:29:51Z roboos $ if nargin < 2, error('Requires two input arguments.'); diff --git a/external/fieldtrip/private/tokenize.m b/external/fieldtrip/private/tokenize.m deleted file mode 100644 index 5cfbaca..0000000 --- a/external/fieldtrip/private/tokenize.m +++ /dev/null @@ -1,69 +0,0 @@ -function [tok] = tokenize(str, sep, rep) - -% TOKENIZE cuts a string into pieces, returning the pieces in a cell array -% -% Use as -% t = tokenize(str) -% t = tokenize(str, sep) -% t = tokenize(str, sep, rep) -% where -% str = the string that you want to cut into pieces -% sep = the separator at which to cut (default is whitespace) -% rep = whether to treat repeating seperator characters as one (default is false) -% -% With the optional boolean flag "rep" you can specify whether repeated -% seperator characters should be squeezed together (e.g. multiple -% spaces between two words). The default is rep=1, i.e. repeated -% seperators are treated as one. -% -% See also STRTOK, TEXTSCAN - -% Copyright (C) 2003-2008, Robert Oostenveld -% -% $Log: tokenize.m,v $ -% Revision 1.3 2008/11/20 15:46:04 roboos -% fixed bug in the default for the 3rd argument (whether repeated seperators should be treated as one). This bug caused some trouble with reading brainvision header files over the last two weeks. -% -% Revision 1.2 2008/11/14 07:37:05 roboos -% use whitespace if no seperator is specified -% -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.5 2006/05/10 07:15:22 roboos -% allow for squeezing multiple separators into one -% -% Revision 1.4 2006/01/30 14:56:41 roboos -% fixed another stupid bug in previous cvs commit -% -% Revision 1.3 2006/01/30 14:55:44 roboos -% fixed stupid bug in previous cvs commit -% -% Revision 1.2 2006/01/30 13:38:18 roboos -% replaced dependency on strtok by more simple code -% changed from dos to unix -% -% Revision 1.1 2005/05/23 13:47:51 roboos -% old implementation, new addition to CVS for fieldtrip release -% - -if nargin<2 - sep = [9:13 32]; % White space characters -end - -if nargin<3 - rep = false; -end - -tok = {}; -f = find(ismember(str, sep)); -f = [0, f, length(str)+1]; -for i=1:(length(f)-1) - tok{i} = str((f(i)+1):(f(i+1)-1)); -end - -if rep - % remove empty cells, which occur if the separator is repeated (e.g. multiple spaces) - tok(cellfun('isempty', tok))=[]; -end - diff --git a/external/fieldtrip/private/topoplot.m b/external/fieldtrip/private/topoplot.m deleted file mode 100644 index e845252..0000000 --- a/external/fieldtrip/private/topoplot.m +++ /dev/null @@ -1,681 +0,0 @@ -function [handle] = topoplot(varargin) - -% TOPOPLOT plots a topographic map of an EEG or MEG field as a 2-D -% circular view (looking down at the top of the head) using interpolation -% on a fine cartesian grid. -% -% This function is called by topoplotER or topoplotTFR -% -% You can also call this function directly as follows: -% topoplot(cfg, datavector) -% topoplot(cfg, X, Y, datavector) -% topoplot(cfg, X, Y, datavector, Labels) -% topoplot(datavector,'Key1','Value1','Key2','Value2',...) -% -% Inputs can be either: -% datavector = vector of values to be plotted as color -% cfg = configuration structure containing the (optional) -% parameters -% X = x-coordinates for channels in datavector -% Y = y-coordinates for channels in datavector -% Labels = labels for channels in datavector -% or the inputs can be key-value pairs containing the (optional) parameters. -% Every cfg field can be specified using the fieldname as a key in the -% key-value pairs. -% -% if X, Y and Labels are given, cfg.layout is NOT used. If X, Y, and Labels -% are not given, cfg.layout must be given and it is assumed that the -% channels in the datavector exactly mach the channels in the layout. -% -% The layout defines how the channels will be arranged in the 2-D plane. -% You can specify the layout in a variety of ways: -% - you can give the name of an ascii layout file with extension *.lay -% - you can give the name of an electrode file -% - you can give an electrode definition, i.e. "elec" structure -% - you can give a gradiometer definition, i.e. "grad" structure -% If you do not specify any of these, and if the data structure contains an -% electrode or gradiometer structure, that will be used for creating a -% layout. -% -% Optional Parameters and Values -% -% cfg.colormap = any sized colormap, see COLORMAP -% cfg.colorbar = 'yes' -% 'no' (default) -% 'North' inside plot box near top -% 'South' inside bottom -% 'East' inside right -% 'West' inside left -% 'NorthOutside' outside plot box near top -% 'SouthOutside' outside bottom -% 'EastOutside' outside right -% 'WestOutside' outside left -% cfg.interplimits = limits for interpolation (default = 'head') -% 'electrodes' to furthest electrode -% 'head' to edge of head -% cfg.gridscale = scaling grid size (default = 67) -% determines resolution of figure -% cfg.maplimits = 'absmax' +/- the absolute-max (default = 'absmax') -% 'maxmin' scale to data range -% [clim1, clim2] user-defined lo/hi -% cfg.style = topoplot style (default = 'both') -% 'straight' colormap only -% 'contour' contour lines only -% 'both' (default) both colormap and contour lines -% 'fill' constant color between lines -% 'blank' just head and electrodes -% cfg.contournum = number of contour lines (default = 6), see CONTOUR -% cfg.shading = 'flat' 'interp' (default = 'flat') -% cfg.interpolation = 'linear','cubic','nearest','v4' (default = 'v4') see GRIDDATA -% cfg.headcolor = Color of head cartoon (default = [0,0,0]) -% cfg.hlinewidth = number, Linewidth of the drawn head, nose and ears (default = 2) -% cfg.contcolor = Contourline color (default = [0 0 0]) -% cfg.electrodes = 'on','off','labels','numbers','highlights' or 'dotnum' (default = 'on') -% cfg.emarker = Marker symbol (default = 'o') -% cfg.ecolor = Marker color (default = [0 0 0] (black)) -% cfg.emarkersize = Marker size (default = 2) -% cfg.efontsize = Font size of electrode labels/numbers (default = 8 pt) -% when cfg.electrodes = 'numbers' or 'labels' -% cfg.comment = string of text -% cfg.commentpos = position of comment (default = 'leftbottom') -% 'lefttop' 'leftbottom' 'middletop' 'middlebottom' 'righttop' 'rightbottom' -% or [x y] coordinates -% or 'title' to place comment as title -% cfg.fontsize = Font size of comment (default = 8 pt) -% cfg.highlight = 'off' or the channel numbers you want to highlight (default = 'off'). -% These numbers should correspond with the channels in the data, not in -% the layout file. -% cfg.hlmarker = Highlight marker symbol (default = 'o') -% cfg.hlcolor = Highlight marker color (default = [0 0 0] (black)) -% cfg.hlmarkersize = Highlight marker size (default = 6) -% cfg.hllinewidth = Highlight marker linewidth (default = 3) -% cfg.outline = 'scalp' or 'ECog' (default = 'scalp') -% -% Note: topoplot() only works when map limits are >= the max and min -% interpolated data values. - -% Undocumented local options: -% cfg.grid -% cfg.maxchans -% cfg.showlabels -% cfg.zlim -% cfg.mask for opacity masking, e.g. with statistical significance - -% Copyright (C) 1996, Andy Spydell, Colin Humphries & Arnaud Delorme, CNL / Salk Institute -% Copyright (C) 2004-2009, F.C. Donders Centre, New implementation by Geerten Kramer, based on versions of Ole Jensen and Jan-Mathijs Schoffelen -% -% This program is free software; you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation; either version 2 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program; if not, write to the Free Software -% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -% $Log: topoplot.m,v $ -% Revision 1.46 2009/09/30 12:34:54 jansch -% *** empty log message *** -% -% Revision 1.45 2009/09/08 07:11:42 roboos -% fixed bug in masking, thanks to Stephan Moratti -% -% Revision 1.44 2009/04/27 16:26:33 ingnie -% fixed bug in plotting electrodes when cfg.highlight is cell. -% -% Revision 1.43 2009/02/02 09:56:34 roboos -% there was still some confusion in the code w.r.t. x/y swapping to -% position the nose at the top of the figure. That is now completely -% being taken care of in the prepare_layout function. The x/y swapping -% caused a layout of conrado not to work, hence I have removed the -% x/y swapping alltogether. -% -% Revision 1.42 2009/01/19 11:56:24 roboos -% moved the command to plot the contour line to after the one to plot the surface, to ensure that the contour lines remain on top also when you export with painters rendering (thanks to Paolo Toffanin) -% some small cleanups -% -% Revision 1.41 2008/12/18 13:49:29 roboos -% fixed problem with interplimits, should not be based on circle with radius 0.5 but on layout.mask -% fixed problem with masking in case of multiple masks -% -% Revision 1.40 2008/12/02 16:09:04 sashae -% replaced backward compatibility code by call to checkconfig, -% renamed cfg options in code to make them consistent with documentation -% -% Revision 1.39 2008/12/02 15:34:37 jansch -% added support for configurations of the class config -% -% Revision 1.38 2008/12/02 15:33:36 jansch -% *** empty log message *** -% -% Revision 1.37 2008/11/12 19:24:03 roboos -% added some code to speed up realtime plotting/updating -% -% Revision 1.36 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.35 2008/09/22 15:12:01 roboos -% fixed bug with highlights (thanks to Tineke) -% -% Revision 1.34 2008/09/22 12:34:10 roboos -% changed handling of the layout -% changed inside/outside detection using layout.mask -% moved the construction of the head outline (i.e. circle, nose and ears) to prepare_layout, using layout.outline -% moved the responsibility for scaling of the layout to prepare_layout (for backward compatibility with old layout files) -% give error on obsolete option cfg.outline=miriam/ecog -% -% Revision 1.33 2008/05/29 13:45:40 roboos -% added hack for Miriam, should be finished by ingnie -% -% Revision 1.32 2008/04/24 10:29:38 roboos -% Added cfg.outline, which can be used to toggle between scalp-mode (default) and ecog mode. This affects the masking and the outline of the head. -% -% Revision 1.31 2007/10/29 16:08:22 marvger -% added the possibility to define the colorbar location (with documentation) -% -% Revision 1.30 2007/10/29 16:01:00 marvger -% suppressed colorbar when all data is equal (this led to an error) -% -% Revision 1.29 2007/10/24 06:13:08 roboos -% improved the documentation for highlights, thanks to Nicholas -% -% Revision 1.28 2007/08/08 07:02:25 roboos -% extended the detection of eeglab-style inputs, see mail from and to Arno on 8 Aug 2007 -% -% Revision 1.27 2007/07/24 16:23:49 ingnie -% fixed cfg.contcolor, did not work previously now only works when is string -% -% Revision 1.26 2007/03/21 12:44:29 roboos -% added detection of EEGLAB-style input arguments and give a long error message that explains the path setting -% -% Revision 1.25 2007/03/14 08:43:12 roboos -% replaced call to createlayout to prepare_layout, made some small changes to the lay structure - -fieldtripdefs - -% Try to detect EEGLAB-style input and give an informative error -% message. The EEGLAB documentation describes the usage as -% >> topoplot(datavector, EEG.chanlocs); % plot a map using an EEG chanlocs structure -% >> topoplot(datavector, 'my_chan.locs'); % read a channel locations file and plot a map -% >> topoplot('example'); % give an example of an electrode location file -% >> [h grid_or_val plotrad_or_grid, xmesh, ymesh]= ... -% topoplot(datavector, chan_locs, 'Input1','Value1', ...); - -if nargin==2 && isvector(varargin{1}) && isstruct(varargin{2}) && isfield(varargin{2}, 'labels') - eeglab = 1; -elseif nargin==2 && isvector(varargin{1}) && ischar(varargin{2}) - eeglab = 1; -elseif nargin==1 && isequal(varargin{1}, 'example') - eeglab = 1; -elseif nargin>2 && isvector(varargin{1}) && mod(nargin,2)==0 && isstruct(varargin{2}) && isfield(varargin{2}, 'labels') - eeglab = 1; -else - eeglab = 0; -end - -if eeglab - % the input resembles the input of the EEGLAB topoplot function - error('Unrecognized input, please look at "help topoplot", "which topoplot" and "path". The input looks as if you expect the EEGLAB version of the topoplot function. Your path settings may be incorrect and the FieldTrip and EEGLAB version of the "topoplot" function may be confused.') -end - -% deal with the different types of input syntax that this function can get -if mod(nargin,2) && isnumeric(varargin{1}) && ischar(varargin{2}) - % topoplot(data, key, val, ...) - cfg = keyval2cfg(varargin(2:end)); - data = varargin{1}; - OldStyleSyntax=0; -elseif nargin==2 - % topoplot(cfg,data) - OldStyleSyntax=0; - cfg = varargin{1}; - data = varargin{2}; - err = 0; - if ~isempty(cfg), - err = err + double(~isstruct(cfg) && ~strcmp(class(cfg), 'config')); - end - err = err + ~isnumeric(data); - if err - errmsg=['\n']; - errmsg=[errmsg,'When two input arguments are supplied, the following syntax should be used:\n']; - errmsg=[errmsg,'topoplot(cfg,datavector);\n']; - error(sprintf(errmsg)); - end; -elseif nargin==4 - % topoplot(cfg,X,Y,data) - OldStyleSyntax=1; - cfg = varargin{1}; - chanX = varargin{2}; - chanY = varargin{3}; - data = varargin{4}; - err = 0; - if ~isempty(cfg), - err = err + double(~isstruct(cfg) && ~strcmp(class(cfg), 'config')); - end - err = err + ~isnumeric(data); - err = err + ~isnumeric(chanX); - err = err + ~isnumeric(chanY); - if err - errmsg=['\n']; - errmsg=[errmsg,'When four input arguments are supplied, the following syntax should be used:\n']; - errmsg=[errmsg,'topoplot(cfg,X,Y,datavector);\n']; - error(sprintf(errmsg)); - end; -elseif nargin==5 - % topoplot(cfg,X,Y,data,labels) - OldStyleSyntax=1; - cfg = varargin{1}; - chanX = varargin{2}; - chanY = varargin{3}; - data = varargin{4}; - chanLabels = varargin{5}; - err = 0; - if ~isempty(cfg), - err = err + double(~isstruct(cfg) && ~strcmp(class(cfg), 'config')); - end - err = err + ~isnumeric(data); - err = err + ~isnumeric(chanX); - err = err + ~isnumeric(chanY); - err = err + ~iscell(chanLabels); - err = err + numel(chanLabels)~=numel(chanX); - err = err + numel(chanLabels)~=numel(chanY); - if err - errmsg=['\n']; - errmsg=[errmsg,'When five input arguments are supplied, the following syntax should be used:\n']; - errmsg=[errmsg,'topoplot(cfg,X,Y,datavector,Labels);\n']; - error(sprintf(errmsg)); - end; -else - error('unrecognized input, please look at the help of this function') -end - -% set the defaults -if ~isfield(cfg, 'maxchans') cfg.maxchans = 256; end; -if ~isfield(cfg, 'maplimits') cfg.maplimits = 'absmax'; end; % absmax, maxmin, [values] -if ~isfield(cfg, 'interplimits') cfg.interplimits ='head'; end; % head, electrodes -if ~isfield(cfg, 'gridscale') cfg.gridscale = 67; end; % 67 in original -if ~isfield(cfg, 'contournum') cfg.contournum = 6; end; -if ~isfield(cfg, 'colorbar') cfg.colorbar = 'no'; end; -if ~isfield(cfg, 'style') cfg.style = 'both'; end; % both,straight,fill,contour,blank -if ~isfield(cfg, 'headcolor') cfg.headcolor = [0 0 0]; end; -if ~isfield(cfg, 'contcolor') cfg.contcolor = 'k'; end; -if ~isfield(cfg, 'hlinewidth') cfg.hlinewidth = 2; end; -if ~isfield(cfg, 'shading') cfg.shading = 'flat'; end; % flat or interp -if ~isfield(cfg, 'interpolation') cfg.interpolation = 'v4'; end; -if ~isfield(cfg, 'fontsize'), cfg.fontsize = 8; end; -if ~isfield(cfg, 'commentpos'), cfg.commentpos = 'leftbottom'; end; -if ~isfield(cfg, 'mask'), cfg.mask = []; end; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% try to update the existing figure, this is to speed up realtime plotting -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if isfield(cfg, 'update') && strcmp(cfg.update, 'yes') - update = guidata(gcf); - if ~isempty(update) - Xi = update.Xi; - Yi = update.Yi; - x = update.x; - y = update.y; - xi = update.xi; - yi = update.yi; - % Interpolate the topographic data - Zi = griddata(x', y, data, xi', yi, cfg.interpolation); - % keep the same NaNs - Zi(isnan(update.Zi)) = NaN; - deltax = xi(2)-xi(1); % length of grid entry - deltay = yi(2)-yi(1); % length of grid entry - surface(Xi-deltax/2,Yi-deltay/2,zeros(size(Zi)),Zi,'EdgeColor','none','FaceColor',cfg.shading); - return - end -end - -if ~isfield(cfg,'layout') - if ~OldStyleSyntax - error('Specify at least the field or key "layout".'); - end; -end; - -if ~ischar(cfg.contcolor) cfg.contcolor = 'k'; warning('cfg.contcolor must be string, put to ''k'''); end; - -if ~isfield(cfg,'electrodes') cfg.electrodes = 'on'; end; % on,off,label,numbers or highlights -if ~isfield(cfg,'showlabels') % for compatibility with OLDSTYLE - cfg.showlabels = ''; -else - cfg.electrodes = ''; -end; - -if ~isfield(cfg,'emarker') cfg.emarker = 'o'; end; -if ~isfield(cfg,'ecolor') cfg.ecolor = [0 0 0]; end; -if ~isfield(cfg,'emarkersize') cfg.emarkersize = 2; end; -if ~isfield(cfg,'efontsize') cfg.efontsize = get(0,'DefaultAxesFontSize');end; - -if ~isfield(cfg,'highlight') cfg.highlight = 'off'; end; % 'off' or the electrodenumbers. -if ~isfield(cfg,'hlmarker') cfg.hlmarker = 'o'; end; -if ~isfield(cfg,'hlcolor') cfg.hlcolor = [0 0 0]; end; -if ~isfield(cfg,'hlmarkersize') cfg.hlmarkersize = 6; end; -if ~isfield(cfg,'hllinewidth') cfg.hllinewidth = 3; end; -if ~isfield(cfg,'hlfacecolor') cfg.hlfacecolor = cfg.hlcolor; end; - -if isfield(cfg,'colormap') - if size(cfg.colormap,2)~=3, error('topoplot(): Colormap must be a n x 3 matrix'); end - colormap(cfg.colormap); -end; - -% check if the input cfg is valid for this function -cfg = checkconfig(cfg, 'renamed', {'grid_scale', 'gridscale'}); -cfg = checkconfig(cfg, 'renamed', {'interpolate', 'interpolation'}); -cfg = checkconfig(cfg, 'renamed', {'numcontour', 'contournum'}); -cfg = checkconfig(cfg, 'renamed', {'electrod', 'electrodes'}); -cfg = checkconfig(cfg, 'renamed', {'hcolor', 'headcolor'}); -cfg = checkconfig(cfg, 'renamed', {'electcolor', 'ecolor'}); -cfg = checkconfig(cfg, 'renamed', {'emsize', 'emarkersize'}); -cfg = checkconfig(cfg, 'renamed', {'efsize', 'efontsize'}); -cfg = checkconfig(cfg, 'renamed', {'headlimits', 'interplimits'}); - -if isfield(cfg,'interplimits') - if ~ischar(cfg.interplimits), error('topoplot(): interplimits value must be a string'); end - cfg.interplimits = lower(cfg.interplimits); - if ~strcmp(cfg.interplimits,'electrodes') && ~strcmp(cfg.interplimits,'head') && ~strcmp(cfg.interplimits,'headleft'), - error('topoplot(): Incorrect value for interplimits'); - end -end; - -if isfield(cfg,'shading') - cfg.shading = lower(cfg.shading); - if ~any(strcmp(cfg.shading,{'flat','interp'})), error('Invalid Shading Parameter'); end -end - -% for compatibility with topoplotXXX functions -if isfield(cfg,'zlim') - cfg.maplimits = cfg.zlim; - cfg = rmfield(cfg,'zlim'); -end; - -[numChan,numTime] = size(data); -if numChan && numTime>1 - error('topoplot(): data should be a column vector\n'); -end - -if ~OldStyleSyntax - % create layout including channel positions, labels and anatomical mask and outline - cfg.layout = prepare_layout(cfg); - chanX = cfg.layout.pos(:,1); - chanY = cfg.layout.pos(:,2); - chanLabels = cfg.layout.label(:); -else - % create layout including channel positions, labels and anatomical mask and outline - cfg.layout.pos = [chanX chanY]; - cfg.layout.label = chanLabels; - cfg.layout = prepare_layout(cfg); -end -clear chanX chanY - -% The whole figure will be created with the x-axis along the horizontal -% dimension of the figure and the y-axis along the vertical dimension. This -% means that for data coming from a system with a head-coordinate system in -% which the x-axis points to the nose (e.g. CTF), the layout should be 90 -% degrees rotated relative to the head coordinates. -x = cfg.layout.pos(:,1); -y = cfg.layout.pos(:,2); - -if isfield(cfg, 'outline') - error('the option cfg.outline is not supported any more, please contact Robert for a detailled explanation'); -end - -if exist('chanLabels', 'var'), - ind_SCALE = strmatch('SCALE', chanLabels); - if length(ind_SCALE)==1 - % remember the position of the scale - X_SCALE = cfg.layout.pos(ind_SCALE, 1); - Y_SCALE = cfg.layout.pos(ind_SCALE, 2); - x(ind_SCALE) = []; - y(ind_SCALE) = []; - chanLabels(ind_SCALE) = []; - end - ind_COMNT = strmatch('COMNT', chanLabels); - if length(ind_COMNT)==1 - % remember the position of the comment - X_COMNT = cfg.layout.pos(ind_COMNT, 1); - Y_COMNT = cfg.layout.pos(ind_COMNT, 1); - x(ind_COMNT) = []; - y(ind_COMNT) = []; - chanLabels(ind_COMNT) = []; - end -end - -% Set coordinates for comment -if strcmp(cfg.commentpos,'lefttop') - x_COMNT = -0.7; - y_COMNT = 0.6; - HorAlign = 'left'; - VerAlign = 'top'; -elseif strcmp(cfg.commentpos,'leftbottom') - x_COMNT = -0.6; - y_COMNT = -0.6; - HorAlign = 'left'; - VerAlign = 'bottom'; -elseif strcmp(cfg.commentpos,'middletop') - x_COMNT = 0; - y_COMNT = 0.75; - HorAlign = 'center'; - VerAlign = 'top'; -elseif strcmp(cfg.commentpos,'middlebottom') - x_COMNT = 0; - y_COMNT = -0.7; - HorAlign = 'center'; - VerAlign = 'bottom'; -elseif strcmp(cfg.commentpos,'righttop') - x_COMNT = 0.65; - y_COMNT = 0.6; - HorAlign = 'right'; - VerAlign = 'top'; -elseif strcmp(cfg.commentpos,'rightbottom') - x_COMNT = 0.6; - y_COMNT = -0.6; - HorAlign = 'right'; - VerAlign = 'bottom'; -elseif isnumeric(cfg.commentpos) - x_COMNT = cfg.commentpos(1); - y_COMNT = cfg.commentpos(2); - HorAlign = 'left'; - VerAlign = 'middle'; - x_COMNT = 0.9*((x_COMNT-min(x))/(max(x)-min(x))-0.5); - y_COMNT = 0.9*((y_COMNT-min(y))/(max(y)-min(y))-0.5); -end - -gca; -cla; -hold on - -if ~strcmp(cfg.style,'blank') - % find limits for interpolation: - if strcmp(cfg.interplimits,'head') - xmin = +inf; - xmax = -inf; - ymin = +inf; - ymax = -inf; - for i=1:length(cfg.layout.mask) - xmin = min([xmin; cfg.layout.mask{i}(:,1)]); - xmax = max([xmax; cfg.layout.mask{i}(:,1)]); - ymin = min([ymin; cfg.layout.mask{i}(:,2)]); - ymax = max([ymax; cfg.layout.mask{i}(:,2)]); - end - elseif strcmp(cfg.interplimits,'headleft') - xmin = +inf; - xmax = -inf; - ymin = +inf; - ymax = -inf; - for i=1:length(cfg.layout.mask) - xmin = min([xmin; cfg.layout.mask{i}(:,1)]); - xmax = 0.02; - ymin = min([ymin; cfg.layout.mask{i}(:,2)]); - ymax = max([ymax; cfg.layout.mask{i}(:,2)]); - end - else - xmin = min(cfg.layout.pos(:,1)); - xmax = max(cfg.layout.pos(:,1)); - ymin = min(cfg.layout.pos(:,2)); - ymax = max(cfg.layout.pos(:,2)); - end - - xi = linspace(xmin,xmax,cfg.gridscale); % x-axis for interpolation (row vector) - yi = linspace(ymin,ymax,cfg.gridscale); % y-axis for interpolation (row vector) - [Xi,Yi,Zi] = griddata(x', y, data, xi', yi, cfg.interpolation); % Interpolate the topographic data - - % calculate colormap limits - m = size(colormap,1); - if ischar(cfg.maplimits) - if strcmp(cfg.maplimits,'absmax') - amin = -max(max(abs(Zi))); - amax = max(max(abs(Zi))); - elseif strcmp(cfg.maplimits,'maxmin') - amin = min(min(Zi)); - amax = max(max(Zi)); - end - else - amin = cfg.maplimits(1); - amax = cfg.maplimits(2); - end - deltax = xi(2)-xi(1); % length of grid entry - deltay = yi(2)-yi(1); % length of grid entry - - if isfield(cfg.layout, 'mask') - % apply anatomical mask to the data, i.e. that determines that the interpolated data outside the circle is not displayed - maskA = false(size(Zi)); - for i=1:length(cfg.layout.mask) - cfg.layout.mask{i}(end+1,:) = cfg.layout.mask{i}(1,:); % force them to be closed - maskA(inside_contour([Xi(:) Yi(:)], cfg.layout.mask{i})) = true; - end - Zi(~maskA) = NaN; - end - - if ~isempty(cfg.mask), - % this mask is based on some statistical feature of the data itself, e.g. significance and is not related to the anatomical mask - [maskX,maskY,maskZ] = griddata(x', y, double(cfg.mask), xi', yi, cfg.interpolation); - % mask should be scaled between 0 and 1, clip the values that ly outside that range - maskZ(isnan(maskZ)) = 0; - maskZ(isinf(maskZ)) = 0; - maskZ(maskZ<0) = 0; - maskZ(maskZ>1) = 1; - end - - % Draw topoplot on head - if strcmp(cfg.style,'contour') - contour(Xi,Yi,Zi,cfg.contournum,cfg.contcolor); - elseif strcmp(cfg.style,'both') - % first draw the surface, then the contour, to ensure that after exporting the contour lines are "on top" - h = surface(Xi-deltax/2,Yi-deltay/2,zeros(size(Zi)),Zi,'EdgeColor','none', 'FaceColor',cfg.shading); - if exist('maskZ','var'), - set(h, 'AlphaData', maskZ); - alim([0 1]); - set(h, 'FaceAlpha', 'interp'); - end - contour(Xi,Yi,Zi,cfg.contournum,cfg.contcolor); - elseif strcmp(cfg.style,'straight') - h = surface(Xi-deltax/2,Yi-deltay/2,zeros(size(Zi)),Zi,'EdgeColor','none', 'FaceColor',cfg.shading); - if exist('maskZ','var'), - set(h, 'AlphaData', maskZ); - alim([0 1]); - set(h, 'FaceAlpha', 'interp'); - end - elseif strcmp(cfg.style,'fill') - contourf(Xi,Yi,Zi,cfg.contournum,cfg.contcolor); - else - error('Invalid style') - end - caxis([amin amax]); % set coloraxis -end - -% Plot electrodes: -if strcmp(cfg.electrodes,'on') || strcmp(cfg.showlabels,'markers') - if ischar(cfg.highlight) - plot(x,y,cfg.emarker,'Color',cfg.ecolor,'markersize',cfg.emarkersize); - elseif isnumeric(cfg.highlight) - normal = setdiff(1:length(x), cfg.highlight); - plot(x(normal), y(normal), cfg.emarker, 'Color', cfg.ecolor, 'markersize', cfg.emarkersize); - plot(x(cfg.highlight), y(cfg.highlight), cfg.hlmarker, 'Color', cfg.hlcolor, 'markersize', cfg.hlmarkersize, 'linewidth', cfg.hllinewidth, 'markerfacecolor', cfg.hlfacecolor); - elseif iscell(cfg.highlight) - plot(x,y,cfg.emarker,'Color',cfg.ecolor,'markersize',cfg.emarkersize); - for iCell = 1:length(cfg.highlight) - plot(x(cfg.highlight{iCell}), y(cfg.highlight{iCell}), cfg.hlmarker{iCell}, 'Color', cfg.hlcolor{iCell}, 'markersize', cfg.hlmarkersize{iCell},'linewidth', cfg.hllinewidth{iCell}, 'markerfacecolor', cfg.hlfacecolor{iCell}); - end - else - error('Unknown highlight type'); - end; -elseif any(strcmp(cfg.electrodes,{'highlights','highlight'})) - if isnumeric(cfg.highlight) - plot(x(cfg.highlight), y(cfg.highlight), cfg.hlmarker, 'Color', cfg.hlcolor, 'markersize', cfg.hlmarkersize, 'linewidth',cfg.hllinewidth, 'markerfacecolor', cfg.hlfacecolor); - else - error('Unknown highlight type'); - end; -elseif strcmp(cfg.electrodes,'labels') || strcmp(cfg.showlabels,'yes') - for i = 1:numChan - text(x(i), y(i), chanLabels{i}, 'HorizontalAlignment', 'center', 'VerticalAlignment', 'middle', 'Color', cfg.ecolor, 'FontSize', cfg.efontsize); - end -elseif strcmp(cfg.electrodes,'numbers') || strcmp(cfg.showlabels,'numbers') - for i = 1:numChan - text(x(i), y(i), int2str(i), 'HorizontalAlignment', 'center', 'VerticalAlignment', 'middle', 'Color', cfg.ecolor, 'FontSize',cfg.efontsize); - end -elseif strcmp(cfg.electrodes,'dotnum') - for i = 1:numChan - text(x(i), y(i), int2str(i), 'HorizontalAlignment', 'left', 'VerticalAlignment', 'bottom', 'Color', cfg.ecolor, 'FontSize', cfg.efontsize); - end - if ischar(cfg.highlight) - plot(x, y, cfg.emarker, 'Color', cfg.ecolor, 'markersize', cfg.emarkersize); - elseif isnumeric(cfg.highlight) - normal = setdiff(1:length(x), cfg.highlight); - plot(x(normal) , y(normal), cfg.emarker, 'Color', cfg.ecolor, 'markersize', cfg.emarkersize); - plot(x(cfg.highlight), y(cfg.highlight), cfg.hlmarker, 'Color', cfg.hlcolor, 'markersize', cfg.hlmarkersize, 'linewidth', cfg.hllinewidth, 'markerfacecolor', cfg.hlfacecolor); - else - error('Unknown highlight type'); - end; -end - -if isfield(cfg.layout, 'outline') - % plot the outline of the head, ears and nose - for i=1:length(cfg.layout.outline) - plot(cfg.layout.outline{i}(:,1), cfg.layout.outline{i}(:,2), 'Color', cfg.headcolor, 'LineWidth', cfg.hlinewidth) - end -end - -% Write comment: -if isfield(cfg, 'comment') - if strcmp(cfg.commentpos, 'title') - title(cfg.comment, 'Fontsize', cfg.fontsize); - else - text(x_COMNT, y_COMNT, cfg.comment, 'Fontsize', cfg.fontsize, 'HorizontalAlignment', HorAlign, 'VerticalAlignment', VerAlign); - end -end - -% plot colorbar: -if isfield(cfg, 'colorbar') && ~all(data == data(1)) - if strcmp(cfg.colorbar, 'yes') - colorbar; - elseif ~strcmp(cfg.colorbar, 'no') - colorbar(cfg.colorbar); - end -end - -hold off -axis off -axis tight -axis equal - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% this allows to update the existing figure, this is to speed up realtime -% plotting -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if isfield(cfg, 'update') && strcmp(cfg.update, 'yes') - update.Xi = Xi; - update.Yi = Yi; - update.Zi = Zi; - update.xi = xi; - update.yi = yi; - update.x = x; - update.y = y; - guidata(gcf, update); -end diff --git a/external/fieldtrip/private/topoplotCC.m b/external/fieldtrip/private/topoplotCC.m deleted file mode 100644 index 19de822..0000000 --- a/external/fieldtrip/private/topoplotCC.m +++ /dev/null @@ -1,200 +0,0 @@ -function cfg = topoplotCC(cfg, freq) - -% TOPOPLOTCC plots the connections between significantly coherent -% sensor pairs -% -% Use as -% topoplotCC(cfg, freq) -% -% The configuration should contain: -% cfg.feedback = string (default = 'textbar') -% cfg.layout = specification of the layout, see PREPARE_LAYOUT -% cfg.foi = the frequency of interest which is to be plotted (default is the first frequency bin) -% cfg.widthparam = string, parameter to be used to control the line width -% cfg.alphaparam = string, parameter to be used to control the opacity -% cfg.colorparam = string, parameter to be used to control the line color -% -% The widthparam should be indicated in pixels, e.g. usefull numbers are 1 -% and larger. -% -% The alphaparam should be indicated as opacity between 0 (fully transparent) -% and 1 (fully opaque). -% -% See also: PREPARE_LAYOUT, MULTIPLOTCC - -% $Log: topoplotCC.m,v $ -% Revision 1.11 2009/06/15 12:57:39 roboos -% added checkdata and checkconfig calls -% changed default colorparam into cohspctrm -% changed default width into 1 -% updated documentation -% -% Revision 1.10 2009/04/15 13:07:14 roboos -% largely rewritten the whole function to work with dimord=chan_chan_freq -% now also with specification of the width, opacity and color for each line -% -% Revision 1.9 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.8 2007/03/21 15:44:05 chrhes -% updated documentation regarding the fact that cfg.layout can also contain a -% layout structure obtained using the function prepare_layout.m -% -% Revision 1.7 2007/03/14 08:43:12 roboos -% replaced call to createlayout to prepare_layout, made some small changes to the lay structure -% -% Revision 1.6 2006/06/26 10:13:15 ingnie -% now works also if no stat.freq present -% -% Revision 1.5 2006/04/20 09:58:34 roboos -% updated documentation -% -% Revision 1.4 2006/03/09 08:20:54 roboos -% changed freq.foi into freq.freq -% -% Revision 1.3 2005/10/01 16:19:04 jansch -% added some help-information. have fun! -% -% Revision 1.2 2005/09/05 06:40:44 jansch -% added defaults in configuration -% -% Revision 1.1 2005/08/25 10:59:37 jansch -% New implementation -% - -fieldtripdefs - -% check if the input data is valid for this function -freq = checkdata(freq, 'cmbrepresentation', 'full'); - -% check if the input configuration is valid for this function -cfg = checkconfig(cfg, 'trackconfig', 'on'); -cfg = checkconfig(cfg, 'required', {'foi', 'layout'}); - -% set the defaults -if ~isfield(cfg, 'feedback'), cfg.feedback = 'textbar'; end -if ~isfield(cfg, 'alphaparam'), cfg.alphaparam = []; end -if ~isfield(cfg, 'widthparam'), cfg.widthparam = []; end -if ~isfield(cfg, 'colorparam'), cfg.colorparam = 'cohspctrm'; end - -lay = prepare_layout(cfg, freq); - -reflabel = freq.label; -chanlabel = freq.label; -refindx = match_str(lay.label, reflabel); -chanindx = match_str(lay.label, chanlabel); -nref = length(refindx); -nchan = length(chanindx); - -% select the data to be used in the figure -fbin = nearest(freq.freq, cfg.foi); - -if isfield(freq, cfg.widthparam) - widthparam = freq.(cfg.widthparam)(:,:,fbin); -else - widthparam = ones(nref,nchan); -end - -if isfield(freq, cfg.alphaparam) - alphaparam = freq.(cfg.alphaparam)(:,:,fbin); -else - alphaparam = []; -end - -if isfield(freq, cfg.colorparam) - colorparam = freq.(cfg.colorparam)(:,:,fbin); -else - colorparam = []; -end - -k = 0; -progress('init', cfg.feedback, 'plotting connections...'); - -figure -hold on - -rgb = colormap; -cmin = min(colorparam(:)); -cmax = max(colorparam(:)); -colorparam = (colorparam - cmin)./(cmax-cmin); -colorparam = round(colorparam * (size(rgb,1)-1) + 1); - -for i=1:nref - for j=1:nchan - if i==j - % don't plot the connection with itself - continue - end - k = k+1; - - progress(k/(nref*nchan), 'plotting connection %d from %d (%d -> %d)\n',k, nref*nchan, i, j); - - if widthparam(i,j)>0 - xbeg = lay.pos(refindx(i),1); - ybeg = lay.pos(refindx(i),2); - xend = lay.pos(chanindx(j),1); - yend = lay.pos(chanindx(j),2); - x = [xbeg xend]'; - y = [ybeg yend]'; - % h = line(x, y); - h = patch(x, y, 1); - - if ~isempty(widthparam) - set(h, 'LineWidth', widthparam(i,j)); - end - - if ~isempty(alphaparam) - set(h, 'EdgeAlpha', alphaparam(i,j)); - end - - if ~isempty(colorparam) - set(h, 'EdgeColor', rgb(colorparam(i,j),:)); - end - - end - end -end -progress('close'); - -% also plot the position of the electrodes -plot(lay.pos(:,1), lay.pos(:,2), 'k.'); - -% also plot the outline, i.e. head shape or sulci -if isfield(lay, 'outline') - fprintf('solid lines indicate the outline, e.g. head shape or sulci\n'); - for i=1:length(lay.outline) - if ~isempty(lay.outline{i}) - X = lay.outline{i}(:,1); - Y = lay.outline{i}(:,2); - h = line(X, Y); - set(h, 'color', 'k'); - set(h, 'linewidth', 1.5); - set(h, 'linestyle', '-'); - end - end -end - -% also plot the mask, i.e. global outline for masking the topoplot -if isfield(lay, 'mask') - fprintf('dashed lines indicate the mask for topograpic interpolation\n'); - for i=1:length(lay.mask) - if ~isempty(lay.mask{i}) - X = lay.mask{i}(:,1); - Y = lay.mask{i}(:,2); - % the polygon representing the mask should be closed - X(end+1) = X(1); - Y(end+1) = Y(1); - h = line(X, Y); - set(h, 'color', 'k'); - set(h, 'linewidth', 1.5); - set(h, 'linestyle', '-'); - end - end -end - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -if nargout<1 - clear cfg -end diff --git a/external/fieldtrip/private/topoplotER.m b/external/fieldtrip/private/topoplotER.m deleted file mode 100644 index 98fdd8d..0000000 --- a/external/fieldtrip/private/topoplotER.m +++ /dev/null @@ -1,558 +0,0 @@ -function [cfg] = topoplotER(cfg, varargin) - -% TOPOPLOTER plots the topographic distribution of 2-Dimensional datatypes as -% event-related fields (ERF), potentials (ERP), the powerspectrum or coherence spectum -% that was computed using the TIMELOCKALYSIS, TIMELOCKGRANDAVERAGE, FREQANALYSIS or -% FREQDESCRIPTIVES functions, as a 2-D circular view (looking down at the top of the head). -% -% Use as: -% topoplotER(cfg, data) -% -% cfg.xparam = first dimension in data in which a selection is made -% 'time' or 'freq' (default depends on data.dimord) -% cfg.zparam = field that contains the data to be plotted as color -% 'avg', 'powspctrm' or 'cohspctrm' (default depends on data.dimord) -% cfg.xlim = 'maxmin' or [xmin xmax] (default = 'maxmin') -% cfg.zlim = 'maxmin', 'absmax' or [zmin zmax] (default = 'maxmin') -% cfg.cohrefchannel = name of reference channel for visualising coherence, can be 'gui' -% cfg.baseline = 'yes','no' or [time1 time2] (default = 'no'), see TIMELOCKBASELINE or FREQBASELINE -% cfg.baselinetype = 'absolute' or 'relative' (default = 'absolute') -% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') -% cfg.comment = string 'no' 'auto' or 'xlim' (default = 'auto') -% 'auto': date, xparam and zparam limits are printed -% 'xlim': only xparam limits are printed -% cfg.commentpos = string or two numbers, position of comment (default 'leftbottom') -% 'lefttop' 'leftbottom' 'middletop' 'middlebottom' 'righttop' 'rightbottom' -% 'title' to place comment as title -% 'layout' to place comment as specified for COMNT in layout -% [x y] coordinates -% cfg.interactive = Interactive plot 'yes' or 'no' (default = 'no') -% In a interactive plot you can select areas and produce a new -% interactive plot when a selected area is clicked. Multiple areas -% can be selected by holding down the SHIFT key. -% cfg.layout = specification of the layout, see below -% -% The layout defines how the channels are arranged. You can specify the -% layout in a variety of ways: -% - you can provide a pre-computed layout structure (see prepare_layout) -% - you can give the name of an ascii layout file with extension *.lay -% - you can give the name of an electrode file -% - you can give an electrode definition, i.e. "elec" structure -% - you can give a gradiometer definition, i.e. "grad" structure -% If you do not specify any of these and the data structure contains an -% electrode or gradiometer structure, that will be used for creating a -% layout. If you want to have more fine-grained control over the layout -% of the subplots, you should create your own layout file. -% -% TOPOPLOTER calls the function TOPOPLOT to do the actual plotting. See -% the help of that function for more configuration options. -% -% See also: -% topoplot, topoplotTFR, singleplotER, multiplotER, prepare_layout - -% Undocumented local options: -% cfg.layoutname -% The following additional cfg parameters are used when plotting 3-dimensional -% data (i.e. when topoplotTFR calls topoplotER): -% cfg.yparam field to be plotted on y-axis -% cfg.ylim 'maxmin' or [ymin ymax] (default = 'maxmin') - -% This function depends on TIMELOCKBASELINE which has the following options: -% cfg.baseline, documented -% cfg.channel -% cfg.blcwindow -% cfg.previous -% cfg.version -% -% This function depends on FREQBASELINE which has the following options: -% cfg.baseline, documented -% cfg.baselinetype - -% Copyright (C) 2005-2006, F.C. Donders Centre -% -% $Log: topoplotER.m,v $ -% Revision 1.58 2009/07/14 13:51:32 roboos -% some small changes related to the new interactive data selection -% -% Revision 1.57 2009/07/14 13:21:09 roboos -% changed the interactive plotting: instead of using plotSelection it now uses the selection function from the new plotting module (select_range and select_channel) and uses a local subfunction to update the cfg and call the next figure -% -% Revision 1.56 2009/06/17 14:05:25 roboos -% use ischar instead of isstr -% -% Revision 1.55 2009/06/17 13:44:52 roboos -% cleaned up help -% -% Revision 1.54 2009/05/12 18:58:49 roboos -% added handling of cfg.cohrefchannel='gui' for manual/interactive selection -% -% Revision 1.53 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.52 2008/12/16 15:31:42 sashae -% plot functions can now give cfg as output -% added checkconfig to start and end of function, configtracking possible -% -% Revision 1.51 2008/12/02 16:09:04 sashae -% replaced backward compatibility code by call to checkconfig, -% renamed cfg options in code to make them consistent with documentation -% -% Revision 1.50 2008/11/28 21:43:27 sashae -% allow averaging over rpt/subj also for other fields than zparam=powspctrm (thanks to Jurrian) -% added call to checkconfig -% -% Revision 1.49 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.48 2008/09/22 14:24:33 roboos -% fixed bug that was visible in case of interactive=yes, removed the scaling of the channels to unit sphere, since that is now done in prepare_layout. -% -% Revision 1.47 2008/09/22 12:31:58 roboos -% changed handling of the layout -% -% Revision 1.46 2008/04/09 07:36:09 marvger -% regular update -% -% Revision 1.45 2008/01/29 19:43:33 sashae -% added option for trial selection; plot functions now also accept data with -% repetitions (either trials or subjects), the avg is computed and plotted -% removed some old code -% -% Revision 1.44 2007/06/05 16:13:33 ingnie -% added dimord rpt_chan_time -% -% Revision 1.43 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.42 2007/03/27 11:05:19 ingnie -% changed call to fixdimord in call to checkinput -% -% Revision 1.41 2007/03/21 15:40:07 chrhes -% updated documentation regarding the fact that cfg.layout can also contain a -% layout structure obtained using the function prepare_layout.m -% -% Revision 1.40 2007/03/14 10:45:57 chrhes -% fixed a small bug before call to topoplot to do with removal of the field -% cfg.layout from tmpcfg -% -% Revision 1.39 2007/03/14 08:43:12 roboos -% replaced call to createlayout to prepare_layout, made some small changes to the lay structure -% -% Revision 1.38 2007/01/09 10:41:43 roboos -% Added the option cfg.renderer, default is opengl. Interactive plotting -% on linux/VNC sometimes does not work, using cfg.renderer='painters' -% seems to fix it. -% -% Revision 1.37 2006/07/20 18:50:18 ingnie -% minor change to axis scaling -% -% Revision 1.36 2006/07/17 12:39:08 ingnie -% added absmax option for cfg.zlim, updated documentation -% -% Revision 1.35 2006/06/19 11:11:37 roboos -% fixed small bug in the conversion of coherence data: first select labels for the channels, then for the channelcombinations -% -% Revision 1.34 2006/05/30 14:16:42 ingnie -% updated documentation -% -% Revision 1.33 2006/05/26 12:47:28 ingnie -% added error when labels in layout and labels in data do not match and therefore -% no data is selected to be plotted -% -% Revision 1.32 2006/05/23 16:05:21 ingnie -% updated documentation -% -% Revision 1.31 2006/05/09 12:21:23 ingnie -% use OldStyle way to call topoplot.m, added some comment options, added comment -% position, updated help -% -% Revision 1.30 2006/04/27 11:42:39 jansch -% removed taking the absolute in the case of coherence-spectra -% -% Revision 1.29 2006/04/27 09:37:04 ingnie -% changed comment options, fixed bug when style=blank, added dimord -% subj_chan_time, updated documentation -% -% Revision 1.28 2006/04/20 09:58:34 roboos -% updated documentation -% -% Revision 1.27 2006/03/22 19:09:19 jansch -% removed overwriting of cfg.layout with chanX and chanY, caused unexplicable -% crashed if toggling more than once between singleplotTFR and topoplotER in -% the interactive mode. -% -% Revision 1.26 2006/03/17 14:30:38 denpas -% Removed local drawTopoplot subroutine. topoplotER.m now calls topoplot.m to -% plot the topoplot. -% -% Revision 1.25 2006/03/14 14:55:09 roboos -% fixed detection of datatype for timelockbaseline or ferqbaseline -% changed from DOS into UNIX format -% -% Revision 1.24 2006/03/14 08:09:22 roboos -% added copyrigth and cvs log statement -% - -fieldtripdefs - -cfg = checkconfig(cfg, 'trackconfig', 'on'); -cfg = checkconfig(cfg, 'unused', {'cohtargetchannel'}); - -cla - -% Multiple data sets are not supported for topoplot: -if length(varargin)>1 - error('Multiple data sets are not supported for topoplotER/topoplotTFR.'); -end - -data = varargin{1}; - -% For backward compatibility with old data structures: -data = checkdata(data); - -% Set other config defaults: -if ~isfield(cfg, 'xlim'), cfg.xlim = 'maxmin'; end -if ~isfield(cfg, 'ylim'), cfg.ylim = 'maxmin'; end -if ~isfield(cfg, 'zlim'), cfg.zlim = 'maxmin'; end -if ~isfield(cfg, 'style'), cfg.style = 'both'; end -if ~isfield(cfg, 'gridscale'), cfg.gridscale = 67; end -if ~isfield(cfg, 'interplimits'), cfg.interplimits = 'head'; end -if ~isfield(cfg, 'interpolation'), cfg.interpolation = 'v4'; end -if ~isfield(cfg, 'contournum'), cfg.contournum = 6; end -if ~isfield(cfg, 'shading'), cfg.shading = 'flat'; end -if ~isfield(cfg, 'comment'), cfg.comment = 'auto'; end -if ~isfield(cfg, 'commentpos'), cfg.commentpos = 'leftbottom'; end -if ~isfield(cfg, 'ecolor'), cfg.ecolor = [0 0 0]; end -if ~isfield(cfg, 'emarker'), cfg.emarker = 'o'; end -if ~isfield(cfg, 'emarkersize'), cfg.emarkersize = 2; end -if ~isfield(cfg, 'fontsize'), cfg.fontsize = 8; end -if ~isfield(cfg, 'headcolor'), cfg.headcolor = [0 0 0]; end -if ~isfield(cfg, 'hlinewidth'), cfg.hlinewidth = 2; end -if ~isfield(cfg, 'baseline'), cfg.baseline = 'no'; end %to avoid warning in timelock/freqbaseline -if ~isfield(cfg, 'trials'), cfg.trials = 'all'; end -if ~isfield(cfg, 'interactive'), cfg.interactive = 'no'; end -if ~isfield(cfg, 'renderer'), cfg.renderer = 'opengl'; end - -% Set x/y/zparam defaults according to data.dimord value: -if strcmp(data.dimord, 'chan_time') - if ~isfield(cfg, 'xparam'), cfg.xparam='time'; end - if ~isfield(cfg, 'yparam'), cfg.yparam=''; end - if ~isfield(cfg, 'zparam'), cfg.zparam='avg'; end -elseif strcmp(data.dimord, 'chan_freq') - if ~isfield(cfg, 'xparam'), cfg.xparam='freq'; end - if ~isfield(cfg, 'yparam'), cfg.yparam=''; end - if ~isfield(cfg, 'zparam'), cfg.zparam='powspctrm'; end -elseif strcmp(data.dimord, 'subj_chan_time') || strcmp(data.dimord, 'rpt_chan_time') - tmpcfg = []; - tmpcfg.trials = cfg.trials; - data = timelockanalysis(tmpcfg, data); - if ~isfield(cfg, 'xparam'), cfg.xparam='time'; end - if ~isfield(cfg, 'yparam'), cfg.yparam=''; end - if ~isfield(cfg, 'zparam'), cfg.zparam='avg'; end -elseif strcmp(data.dimord, 'subj_chan_freq') || strcmp(data.dimord, 'rpt_chan_freq') - if isfield(data, 'crsspctrm'), data = rmfield(data, 'crsspctrm'); end % on the fly computation of coherence spectrum is not supported - tmpcfg = []; - tmpcfg.trials = cfg.trials; - tmpcfg.jackknife = 'no'; - if isfield(cfg, 'zparam') && strcmp(cfg.zparam,'cohspctrm') - % on the fly computation of coherence spectrum is not supported - elseif isfield(cfg, 'zparam') && ~strcmp(cfg.zparam,'powspctrm') - % freqdesctiptives will only work on the powspctrm field, hence a temporary copy of the data is needed - tempdata.dimord = data.dimord; - tempdata.freq = data.freq; - tempdata.label = data.label; - tempdata.powspctrm = data.(cfg.zparam); - tempdata.cfg = data.cfg; - tempdata = freqdescriptives(tmpcfg, tempdata); - data.(cfg.zparam) = tempdata.powspctrm; - clear tempdata - else - data = freqdescriptives(tmpcfg, data); - end - if ~isfield(cfg, 'xparam'), cfg.xparam='freq'; end - if ~isfield(cfg, 'yparam'), cfg.yparam=''; end - if ~isfield(cfg, 'zparam'), cfg.zparam='powspctrm'; end -elseif strcmp(data.dimord, 'chan_freq_time') - if ~isfield(cfg, 'xparam'), cfg.xparam='time'; end - if ~isfield(cfg, 'yparam'), cfg.yparam='freq'; end - if ~isfield(cfg, 'zparam'), cfg.zparam='powspctrm'; end -elseif strcmp(data.dimord, 'subj_chan_freq_time') || strcmp(data.dimord, 'rpt_chan_freq_time') - if isfield(data, 'crsspctrm'), data = rmfield(data, 'crsspctrm'); end % on the fly computation of coherence spectrum is not supported - tmpcfg = []; - tmpcfg.trials = cfg.trials; - tmpcfg.jackknife = 'no'; - if isfield(cfg, 'zparam') && strcmp(cfg.zparam,'cohspctrm') - % on the fly computation of coherence spectrum is not supported - elseif isfield(cfg, 'zparam') && ~strcmp(cfg.zparam,'powspctrm') - % freqdesctiptives will only work on the powspctrm field, hence a temporary copy of the data is needed - tempdata.dimord = data.dimord; - tempdata.freq = data.freq; - tempdata.time = data.time; - tempdata.label = data.label; - tempdata.powspctrm = data.(cfg.zparam); - tempdata.cfg = data.cfg; - tempdata = freqdescriptives(tmpcfg, tempdata); - data.(cfg.zparam) = tempdata.powspctrm; - clear tempdata - else - data = freqdescriptives(tmpcfg, data); - end - if ~isfield(cfg, 'xparam'), cfg.xparam='time'; end - if ~isfield(cfg, 'yparam'), cfg.yparam='freq'; end - if ~isfield(cfg, 'zparam'), cfg.zparam='powspctrm'; end -elseif strcmp(data.dimord, 'chan_comp') - % Add a pseudo-axis with the component numbers: - data.comp = 1:size(data.topo,2); - % Rename the field with topographic label information: - data.label = data.topolabel; - if ~isfield(cfg, 'xparam'), cfg.xparam='comp'; end - if ~isfield(cfg, 'yparam'), cfg.yparam=''; end - if ~isfield(cfg, 'zparam'), cfg.zparam='topo'; end -end - -% Read or create the layout that will be used for plotting: -lay = prepare_layout(cfg, data); -cfg.layout = lay; - -% Create time-series of small topoplots: -if ~ischar(cfg.xlim) && length(cfg.xlim)>2 - % Switch off interactive mode: - cfg.interactive = 'no'; - xlims = cfg.xlim; - % Iteratively call topoplotER with different xlim values: - for i=1:length(xlims)-1 - subplot(ceil(sqrt(length(xlims)-1)), ceil(sqrt(length(xlims)-1)), i); - cfg.xlim = xlims(i:i+1); - topoplotER(cfg, data); - end - return -end - -% Check for unconverted coherence spectrum data: -if (strcmp(cfg.zparam,'cohspctrm')) && isfield(data, 'labelcmb') - % A reference channel is required: - if ~isfield(cfg,'cohrefchannel'), - error('no reference channel specified'); - end - - if strcmp(cfg.cohrefchannel, 'gui') - % Open a single figure with the channel layout, the user can click on a reference channel - h = clf; - plot_lay(lay, 'box', false); - title('Select the reference channel by clicking on it...'); - % add the channel information to the figure - info = guidata(gcf); - info.x = lay.pos(:,1); - info.y = lay.pos(:,2); - info.label = lay.label; - guidata(h, info); - set(gcf, 'WindowButtonUpFcn', {@select_channel, 'callback', {@select_topoplotER, cfg, data}}); - return - end - - % Convert 2-dimensional channel matrix to a single dimension: - sel1 = strmatch(cfg.cohrefchannel, data.labelcmb(:,2)); - sel2 = strmatch(cfg.cohrefchannel, data.labelcmb(:,1)); - fprintf('selected %d channels for coherence\n', length(sel1)+length(sel2)); - data.cohspctrm = data.cohspctrm([sel1;sel2],:,:); - data.label = [data.labelcmb(sel1,1);data.labelcmb(sel2,2)]; - data.labelcmb = data.labelcmb([sel1;sel2],:); - data = rmfield(data, 'labelcmb'); -end - -% Apply baseline correction: -if ~strcmp(cfg.baseline, 'no') - if strcmp(cfg.xparam, 'freq') || strcmp(cfg.yparam, 'freq') - data = freqbaseline(cfg, data); - else - data = timelockbaseline(cfg, data); - end -end - -% Get physical min/max range of x: -if strcmp(cfg.xlim,'maxmin') - xmin = min(getsubfield(data, cfg.xparam)); - xmax = max(getsubfield(data, cfg.xparam)); -else - xmin = cfg.xlim(1); - xmax = cfg.xlim(2); -end - -% Replace value with the index of the nearest bin -xmin = nearest(getsubfield(data, cfg.xparam), xmin); -xmax = nearest(getsubfield(data, cfg.xparam), xmax); - -% Get physical min/max range of y: -if ~isempty(cfg.yparam) - if strcmp(cfg.ylim,'maxmin') - ymin = min(getsubfield(data, cfg.yparam)); - ymax = max(getsubfield(data, cfg.yparam)); - else - ymin = cfg.ylim(1); - ymax = cfg.ylim(2); - end - - % Replace value with the index of the nearest bin: - ymin = nearest(getsubfield(data, cfg.yparam), ymin); - ymax = nearest(getsubfield(data, cfg.yparam), ymax); -end - -% make dat structure with one value for each channel -dat = getsubfield(data, cfg.zparam); -if ~isempty(cfg.yparam), - dat = dat(:, ymin:ymax, xmin:xmax); - dat = nanmean(nanmean(dat, 2), 3); -else - dat = dat(:, xmin:xmax); - dat = nanmean(dat, 2); -end -dat = dat(:); - -% Select the channels in the data that match with the layout: -[seldat, sellay] = match_str(data.label, cfg.layout.label); -if isempty(seldat) - error('labels in data and labels in layout do not match'); -end -datavector = dat(seldat); -% Select x and y coordinates and labels of the channels in the data -chanX = cfg.layout.pos(sellay,1); -chanY = cfg.layout.pos(sellay,2); -chanLabels = cfg.layout.label(sellay); - -% Get physical min/max range of z: -if strcmp(cfg.zlim,'maxmin') - zmin = min(datavector); - zmax = max(datavector); -elseif strcmp(cfg.zlim,'absmax') - zmin = -max(max(abs(datavector))); - zmax = max(max(abs(datavector))); -else - zmin = cfg.zlim(1); - zmax = cfg.zlim(2); -end - -% specify the x and y coordinates of the comment as stated in the layout -if strcmp(cfg.commentpos,'layout') - cfg.commentpos = []; - ind_COMNT = strmatch('COMNT', cfg.layout.label); - cfg.commentpos(1) = cfg.layout.pos(ind_COMNT,1); - cfg.commentpos(2) = cfg.layout.pos(ind_COMNT,2); -end - -% make cfg.comment for topoplot.m -if strcmp(cfg.comment, 'no') - cfg = rmfield(cfg,'comment'); -elseif strcmp(cfg.comment, 'auto') - comment = date; - if ~isempty(cfg.xparam) - if strcmp(cfg.xlim,'maxmin') - comment = sprintf('%0s\n%0s=[%.3g %.3g]', comment, cfg.xparam, data.(cfg.xparam)(xmin), data.(cfg.xparam)(xmax)); - else - comment = sprintf('%0s\n%0s=[%.3g %.3g]', comment, cfg.xparam, cfg.xlim(1), cfg.xlim(2)); - end - end - if ~isempty(cfg.yparam) - if strcmp(cfg.ylim,'maxmin') - comment = sprintf('%0s\n%0s=[%.3g %.3g]', comment, cfg.yparam, data.(cfg.yparam)(ymin), data.(cfg.yparam)(ymax)); - else - comment = sprintf('%0s\n%0s=[%.3g %.3g]', comment, cfg.yparam, cfg.ylim(1), cfg.ylim(2)); - end - end - if ~isempty(cfg.zparam) - comment = sprintf('%0s\n%0s=[%.3g %.3g]', comment, cfg.zparam, zmin, zmax); - end - cfg.comment = comment; -elseif strcmp(cfg.comment, 'xlim') - if strcmp(cfg.xlim,'maxmin') - comment = sprintf('%0s=[%.3g %.3g]', cfg.xparam, data.(cfg.xparam)(xmin), data.(cfg.xparam)(xmax)); - else - comment = sprintf('%0s=[%.3g %.3g]', cfg.xparam, cfg.xlim(1), cfg.xlim(2)); - end - cfg.comment = comment; -elseif ~ischar(cfg.comment) - error('cfg.comment must be string'); -end - -% Draw topoplot: -topoplot(cfg,chanX,chanY,datavector,chanLabels); - -% The remainder of the code is meant to make the figure interactive -hold on; - -% Make the figure interactive -if strcmp(cfg.interactive, 'yes') - % add the channel information to the figure - info = guidata(gcf); - info.x = lay.pos(:,1); - info.y = lay.pos(:,2); - info.label = lay.label; - guidata(gcf, info); - - if any(strcmp(data.dimord, {'chan_time', 'chan_freq', 'subj_chan_time', 'rpt_chan_time'})) - set(gcf, 'WindowButtonUpFcn', {@select_channel, 'multiple', true, 'callback', {@select_singleplotER, cfg, varargin{:}}, 'event', 'WindowButtonUpFcn'}); - set(gcf, 'WindowButtonDownFcn', {@select_channel, 'multiple', true, 'callback', {@select_singleplotER, cfg, varargin{:}}, 'event', 'WindowButtonDownFcn'}); - set(gcf, 'WindowButtonMotionFcn', {@select_channel, 'multiple', true, 'callback', {@select_singleplotER, cfg, varargin{:}}, 'event', 'WindowButtonMotionFcn'}); - elseif any(strcmp(data.dimord, {'chan_freq_time', 'subj_chan_freq_time', 'rpt_chan_freq_time', 'rpttap_chan_freq_time'})) - set(gcf, 'WindowButtonUpFcn', {@select_channel, 'multiple', true, 'callback', {@select_singleplotTFR, cfg, varargin{:}}, 'event', 'WindowButtonUpFcn'}); - set(gcf, 'WindowButtonDownFcn', {@select_channel, 'multiple', true, 'callback', {@select_singleplotTFR, cfg, varargin{:}}, 'event', 'WindowButtonDownFcn'}); - set(gcf, 'WindowButtonMotionFcn', {@select_channel, 'multiple', true, 'callback', {@select_singleplotTFR, cfg, varargin{:}}, 'event', 'WindowButtonMotionFcn'}); - else - error('unsupported dimord "%" for interactive plotting', data.dimord); - end -end - -axis off; -hold off; - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION which is called after selecting channels in case of cfg.cohrefchannel='gui' -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function select_topoplotER(label, cfg, varargin) -cfg.cohrefchannel = label; -fprintf('selected cfg.cohrefchannel = ''%s''\n', cfg.cohrefchannel); -p = get(gcf, 'Position'); -f = figure; -set(f, 'Position', p); -topoplotER(cfg, varargin{:}); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION which is called after selecting channels in case of cfg.interactive='yes' -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function select_singleplotER(label, cfg, varargin) -if ~isempty(label) - cfg.xlim = 'maxmin'; - cfg.channel = label; - fprintf('selected cfg.channel = {'); - for i=1:(length(cfg.channel)-1) - fprintf('''%s'', ', cfg.channel{i}); - end - fprintf('''%s''}\n', cfg.channel{end}); - p = get(gcf, 'Position'); - f = figure; - set(f, 'Position', p); - singleplotER(cfg, varargin{:}); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION which is called after selecting channels in case of cfg.interactive='yes' -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function select_singleplotTFR(label, cfg, varargin) -if ~isempty(label) - cfg.xlim = 'maxmin'; - cfg.ylim = 'maxmin'; - cfg.channel = label; - fprintf('selected cfg.channel = {'); - for i=1:(length(cfg.channel)-1) - fprintf('''%s'', ', cfg.channel{i}); - end - fprintf('''%s''}\n', cfg.channel{end}); - p = get(gcf, 'Position'); - f = figure; - set(f, 'Position', p); - singleplotTFR(cfg, varargin{:}); -end diff --git a/external/fieldtrip/private/topoplotTFR.m b/external/fieldtrip/private/topoplotTFR.m deleted file mode 100644 index f24d692..0000000 --- a/external/fieldtrip/private/topoplotTFR.m +++ /dev/null @@ -1,98 +0,0 @@ -function [cfg] = topoplotTFR(cfg, varargin) - -% TOPOPLOTTFR plots the topographic distribution of 3-Dimensional datatypes as -% the time-frequency representation of power or coherence that was computed -% using the FREQANALYSIS or FREQDESCRIPTIVES functions, as a 2-D circular -% view (looking down at the top of the head). -% -% Use as: -% topoplotTFR(cfg, data) -% -% The configuration can have the following parameters: -% cfg.xparam = first dimension in data in which a selection is made -% 'time' (default depends on data.dimord) -% cfg.yparam = second dimension in data in which a selection is made -% 'freq' (default depends on data.dimord) -% cfg.zparam = field that contains the data to be plotted as color -% 'powspctrm' or 'cohspctrm' (default depends on data.dimord) -% cfg.xlim = 'maxmin' or [xmin xmax] (default = 'maxmin') -% cfg.ylim = 'maxmin' or [ymin ymax] (default = 'maxmin') -% cfg.zlim = 'maxmin', 'absmax' or [zmin zmax] (default = 'maxmin') -% cfg.cohrefchannel = name of reference channel for visualising coherence, can be 'gui' -% cfg.baseline = 'yes','no' or [time1 time2] (default = 'no'), see FREQBASELINE -% cfg.baselinetype = 'absolute' or 'relative' (default = 'absolute') -% cfg.trials = 'all' or a selection given as a 1xN vector (default = 'all') -% cfg.comment = string 'no' 'auto' or 'xlim' (default = 'auto') -% 'auto': date, xparam, yparam and zparam limits are printed -% 'xlim': only xparam limits are printed -% cfg.commentpos = string or two numbers, position of comment (default 'leftbottom') -% 'lefttop' 'leftbottom' 'middletop' 'middlebottom' 'righttop' 'rightbottom' -% 'title' to place comment as title -% 'layout' to place comment as specified for COMNT in layout -% [x y] coordinates -% cfg.interactive = Interactive plot 'yes' or 'no' (default = 'no') -% In a interactive plot you can select areas and produce a new -% interactive plot when a selected area is clicked. Multiple areas -% can be selected by holding down the SHIFT key. -% cfg.layout = specification of the layout, see below -% -% The layout defines how the channels are arranged. You can specify the -% layout in a variety of ways: -% - you can provide a pre-computed layout structure (see prepare_layout) -% - you can give the name of an ascii layout file with extension *.lay -% - you can give the name of an electrode file -% - you can give an electrode definition, i.e. "elec" structure -% - you can give a gradiometer definition, i.e. "grad" structure -% If you do not specify any of these and the data structure contains an -% electrode or gradiometer structure, that will be used for creating a -% layout. If you want to have more fine-grained control over the layout -% of the subplots, you should create your own layout file. -% -% TOPOPLOTTFR calls the function TOPOPLOT to do the actual plotting. See -% the help of that function for more configuration options. -% -% See also: -% topoplot, topoplotER, singleplotTFR, multiplotTFR, prepare_layout - -% Copyright (C) 2005-2006, F.C. Donders Centre -% -% $Log: topoplotTFR.m,v $ -% Revision 1.21 2009/06/17 13:44:52 roboos -% cleaned up help -% -% Revision 1.20 2008/12/16 15:31:42 sashae -% plot functions can now give cfg as output -% added checkconfig to start and end of function, configtracking possible -% -% Revision 1.19 2008/01/29 19:43:33 sashae -% added option for trial selection; plot functions now also accept data with -% repetitions (either trials or subjects), the avg is computed and plotted -% removed some old code -% -% Revision 1.18 2007/03/21 15:36:36 chrhes -% updated documentation regarding the fact that cfg.layout can also contain a -% layout structure obtained using the function prepare_layout.m -% -% Revision 1.17 2006/07/17 12:39:47 ingnie -% updated documentation -% -% Revision 1.16 2006/05/30 14:21:00 ingnie -% updated documentation -% -% Revision 1.15 2006/05/23 16:05:21 ingnie -% updated documentation -% -% Revision 1.14 2006/05/09 12:21:41 ingnie -% updated help -% -% Revision 1.13 2006/04/27 09:35:49 ingnie -% updated documentation -% -% Revision 1.12 2006/03/14 14:55:16 roboos -% changed from DOS into UNIX format -% -% Revision 1.11 2006/03/14 08:09:22 roboos -% added copyrigth and cvs log statement -% - -cfg=topoplotER(cfg, varargin{:}); diff --git a/external/fieldtrip/private/traditional.m b/external/fieldtrip/private/traditional.m index 54236b0..3149dea 100644 --- a/external/fieldtrip/private/traditional.m +++ b/external/fieldtrip/private/traditional.m @@ -38,21 +38,23 @@ % along with this program; if not, write to the Free Software % Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -% $Log: traditional.m,v $ -% Revision 1.5 2005/08/15 08:15:33 roboos -% reimplemented the rotate function, which contained an error (the error is in the AIR technical reference) -% changed all functions to be dependent on the rotate, translate and scale function -% all functions now behave consistenly, which also means that they are not compleetly backward compatible w.r.t. the order of the rotations +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.4 2005/08/11 07:57:14 roboos -% fixed bug in y-rotation +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.3 2005/04/21 08:28:45 roboos -% fixed bug in rotation matrix (thanks to Arno) +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.2 2004/05/19 09:57:07 roberto -% added GPL copyright statement, added CVS log item +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: traditional.m 952 2010-04-21 18:29:51Z roboos $ % compute the homogenous transformation matrix for the translation T = translate(f([1 2 3])); diff --git a/external/fieldtrip/private/transfer_elec.m b/external/fieldtrip/private/transfer_elec.m index 0d0dbf7..6d244ef 100644 --- a/external/fieldtrip/private/transfer_elec.m +++ b/external/fieldtrip/private/transfer_elec.m @@ -11,13 +11,23 @@ % Copyright (C) 1998-2002, Robert Oostenveld % -% $Log: transfer_elec.m,v $ -% Revision 1.1 2009/01/21 10:32:38 roboos -% moved from forwinv/* and forwinv/mex/* directory to forwinv/private/* to make the CVS layout consistent with the release version +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.2 2003/03/11 14:45:37 roberto -% updated help and copyrights +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: transfer_elec.m 946 2010-04-21 17:51:16Z roboos $ Npnt = size(pnt,1); Ntri = size(tri,1); diff --git a/external/fieldtrip/private/transform2grid.m b/external/fieldtrip/private/transform2grid.m new file mode 100644 index 0000000..e60831e --- /dev/null +++ b/external/fieldtrip/private/transform2grid.m @@ -0,0 +1,50 @@ +function [volume] = transform2grid(volume); + +% TRANSFORM2GRID ensures that the volume contains the definition of the +% cardian axes, i.e. xgrid/ygrid/zgrid. If the voluyme contains a +% homogenous coordinate transformation axis that is unequal to eye(4), it +% will try to construct the cardinal axis from that transformation matrix. +% +% See also GRID2TRANSFORM + +if ~isfield(volume, 'xgrid'), volume.xgrid=1:volume.dim(1); end +if ~isfield(volume, 'ygrid'), volume.ygrid=1:volume.dim(2); end +if ~isfield(volume, 'zgrid'), volume.zgrid=1:volume.dim(3); end +if ~isfield(volume, 'transform'), volume.transform=eye(4); end + +if all(all(volume.transform==eye(4))) + % nothing needs to be done, since the homogenous transformation matrix already + % corresponds to the identity matrix +else + fprintf('updating values along the cardinal axes\n'); + % check whether it is possible to convert the homogenous transformation + % matrix into the cardinal axes that are described with xgrid/ygrid/zgrid + dum = volume.transform .* [ + 0 1 1 0 + 1 0 1 0 + 1 1 0 0 + 1 1 1 0 ]; + if any(dum(:)~=0) + error('rotated coordinate system, cannot compute xgrid/ygrid/zgrid'); + end + + % apply the homogenous coordinate transformation to each of the cardinal axes + x = (volume.transform * ([volume.xgrid(:) zeros(volume.dim(1),1) zeros(volume.dim(1),1) ones(volume.dim(1),1)]'))'; + x = x(:,1); + y = (volume.transform * ([zeros(volume.dim(2),1) volume.ygrid(:) zeros(volume.dim(2),1) ones(volume.dim(2),1)]'))'; + y = y(:,2); + z = (volume.transform * ([zeros(volume.dim(3),1) zeros(volume.dim(3),1) volume.zgrid(:) ones(volume.dim(3),1)]'))'; + z = z(:,3); + + % update the definition of the cardinal axes of the volume + volume.xgrid = x; + volume.ygrid = y; + volume.zgrid = z; + + % and update the homogenous transformation matrix + % volume.transform = eye(4); +end + +% remove the homogenous transformation matrix, since it has become trivial +volume = rmfield(volume, 'transform'); + diff --git a/external/fieldtrip/private/transform_headshape.m b/external/fieldtrip/private/transform_headshape.m deleted file mode 100644 index 45eb8b6..0000000 --- a/external/fieldtrip/private/transform_headshape.m +++ /dev/null @@ -1,55 +0,0 @@ -function [shape] = transform_headshape(transform, shape) - -% TRANSFORM_HEADSHAPE applies a homogenous coordinate transformation to a -% structure with headshape and fiducial information. -% -% Use as -% shape = transform_headshape(transform, shape) -% -% See also READ_HEADSHAPE - -% Copyright (C) 2008, Robert Oostenveld -% -% $Log: transform_headshape.m,v $ -% Revision 1.3 2008/07/21 20:31:00 roboos -% also support gradiometer coil orientation (only rotate) -% -% Revision 1.2 2008/04/15 15:33:58 roboos -% fixed small bug (thanks to Vladimir) -% -% Revision 1.1 2008/04/11 16:14:03 roboos -% first implementation, simple helper function for spm integration and symmetry with vol and sens -% - -if any(transform(4,:) ~= [0 0 0 1]) - error('invalid transformation matrix'); -end - -if isfield(shape, 'pnt') && ~isempty(shape.pnt) - % this also works if the structure describes electrode or gradiometer positions instead of a headshape - shape.pnt = apply(transform, shape.pnt); -end - -if isfield(shape, 'ori') - % gradiometer coil orientations should only be rotated and not translated - rotation = eye(4); - rotation(1:3,1:3) = transform(1:3,1:3); - if abs(det(rotation)-1)>10*eps - error('only a rigid body transformation without rescaling is allowed for MEG sensors'); - end - % apply the rotation to the coil orientations - shape.ori = apply(rotation, sens.ori); -end - -if isfield(shape, 'fid') && isfield(shape.fid, 'pnt') - % apply the same transformation on the fiducials - shape.fid.pnt = apply(transform, shape.fid.pnt); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION that applies the homogenous transformation -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [new] = apply(transform, old) -old(:,4) = 1; -new = old * transform'; -new = new(:,1:3); diff --git a/external/fieldtrip/private/transform_sens.m b/external/fieldtrip/private/transform_sens.m deleted file mode 100644 index bb6808b..0000000 --- a/external/fieldtrip/private/transform_sens.m +++ /dev/null @@ -1,63 +0,0 @@ -function [sens] = transform_sens(transform, sens) - -% TRANSFORM_SENS applies a homogenous coordinate transformation to a -% structure with EEG electrodes or MEG gradiometers. For MEG gradiometers -% the homogenous transformation matrix should be limited to a rigid-body -% translation plus rotation. -% -% Use as -% sens = transform_sens(transform, sens) -% -% See also READ_SENS, PREPARE_VOL_SENS, COMPUTE_LEADFIELD - -% Copyright (C) 2008, Robert Oostenveld -% -% $Log: transform_sens.m,v $ -% Revision 1.4 2008/07/21 20:31:35 roboos -% updated documentation -% -% Revision 1.3 2008/03/06 09:27:30 roboos -% updated documentation -% -% Revision 1.2 2008/03/05 15:18:41 roboos -% the previous version was still empty, I now made a proper implementation for the translation of various objects -% -% Revision 1.1 2008/01/28 20:31:28 roboos -% initial implementation, empty stubs - -if any(transform(4,:) ~= [0 0 0 1]) - error('invalid transformation matrix'); -end - -if senstype(sens, 'eeg') - - % any normal coordinate transformation is in principle fine - % apply the translation, rotation and possibly scaling to the electrode positions - sens.pnt = apply(transform, sens.pnt); - -elseif senstype(sens, 'meg') - - % only a rigid body transformation (translation+rotation) without rescaling is allowed - rotation = eye(4); - rotation(1:3,1:3) = transform(1:3,1:3); - - if abs(det(rotation)-1)>10*eps - error('only a rigid body transformation without rescaling is allowed for MEG sensors'); - end - - % apply the translation and rotation to the coil positions - sens.pnt = apply(transform, sens.pnt); - % the sensor coil orientations should be rotated but not translated - sens.ori = apply(rotation, sens.ori); - -else - error('unsupported or unrecognized type of sensors'); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION that applies the homogenous transformation -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [new] = apply(transform, old) -old(:,4) = 1; -new = old * transform'; -new = new(:,1:3); diff --git a/external/fieldtrip/private/transform_vol.m b/external/fieldtrip/private/transform_vol.m deleted file mode 100644 index 90f345c..0000000 --- a/external/fieldtrip/private/transform_vol.m +++ /dev/null @@ -1,84 +0,0 @@ -function [vol] = transform_vol(transform, vol) - -% TRANSFORM_VOL applies a homogenous coordinate transformation to -% a structure with an EEG or MEG colume conduction model. The homogenous -% transformation matrix should be limited to a rigid-body translation -% plus rotation and a global rescaling. -% -% Use as -% vol = transform_vol(transform, vol) -% -% See also READ_VOL, PREPARE_VOL_SENS, COMPUTE_LEADFIELD - -% Copyright (C) 2008, Robert Oostenveld -% -% $Log: transform_vol.m,v $ -% Revision 1.6 2009/02/06 08:31:19 roboos -% added bemcp as volume type -% -% Revision 1.5 2008/04/18 13:16:25 roboos -% removed check for scaling -% -% Revision 1.4 2008/04/15 20:36:21 roboos -% added explicit handling of various BEM implementations, i.e. for all voltype variants -% -% Revision 1.3 2008/03/06 09:27:31 roboos -% updated documentation -% -% Revision 1.2 2008/03/05 15:18:41 roboos -% the previous version was still empty, I now made a proper implementation for the translation of various objects -% -% Revision 1.1 2008/01/28 20:31:28 roboos -% initial implementation, empty stubs -% - -if any(transform(4,:) ~= [0 0 0 1]) - error('invalid transformation matrix'); -end - -% only a rigid body transformation without rescaling is allowed -rotation = eye(4); -rotation(1:3,1:3) = transform(1:3,1:3); - -% FIXME insert check for nonuniform scaling, should give an error - -% if abs(det(rotation)-1)>10*eps -% error('only a rigid body transformation without rescaling is allowed'); -% end - -switch voltype(vol) - - case {'singlesphere' 'multisphere' 'concentric'} - if isfield(vol, 'o') - % shift the center of the spheres, an optional rotation does not affect them - vol.o = apply(transform, vol.o); - end - - case {'bem', 'dipoli', 'bemcp', 'asa', 'avo', 'nolte'} - for i=1:length(vol.bnd) - % apply the transformation to each of the triangulated surface descriptions - vol.bnd(i).pnt = apply(transform, vol.bnd(i).pnt); - if isfield(vol.bnd(i), 'nrm') - % also apply it to the surface normals - vol.bnd(i).nrm = apply(transform, vol.bnd(i).nrm); - end - end - - case 'infinite' - % nothing to do, since it is an infinite vacuum - - case 'neuromag' - error('not supported for neuromag forward model'); - - otherwise - error('unsupported or unrecognized type of volume conductor model'); -end % switch - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION that applies the homogenous transformation -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [new] = apply(transform, old) -old(:,4) = 1; -new = old * transform'; -new = new(:,1:3); diff --git a/external/fieldtrip/private/translate.m b/external/fieldtrip/private/translate.m index 234e397..fc722a9 100644 --- a/external/fieldtrip/private/translate.m +++ b/external/fieldtrip/private/translate.m @@ -25,15 +25,23 @@ % along with this program; if not, write to the Free Software % Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -% $Log: translate.m,v $ -% Revision 1.4 2005/08/15 08:15:33 roboos -% reimplemented the rotate function, which contained an error (the error is in the AIR technical reference) -% changed all functions to be dependent on the rotate, translate and scale function -% all functions now behave consistenly, which also means that they are not compleetly backward compatible w.r.t. the order of the rotations +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.3 2004/05/19 09:57:07 roberto -% added GPL copyright statement, added CVS log item +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: translate.m 952 2010-04-21 18:29:51Z roboos $ H = [ 1 0 0 T(1) diff --git a/external/fieldtrip/private/trialfun_brainvision.m b/external/fieldtrip/private/trialfun_brainvision.m deleted file mode 100644 index 983621c..0000000 --- a/external/fieldtrip/private/trialfun_brainvision.m +++ /dev/null @@ -1,73 +0,0 @@ -function [trl] = trialfun_brainvision(cfg); - -% For continuous BrainVision data, the trialdef structure should contain -% cfg.trialdef.stim = 2 stimulus trigger code, can be a list -% cfg.trialdef.resp = 2 response trigger code, can be a list -% cfg.trialdef.segment = 'no' / 'yes' use the segment markers as onset -% cfg.trialdef.timezero = 'no' / 'yes' use the "Time 0" markers as onset -% cfg.trialdef.prestim = 0.300 pre-marker latency in seconds -% cfg.trialdef.poststim = 0.700 post-marker latency in seconds -% cfg.trialdef.trgfile = filename of the marker file -% -% Warning: this function is deprecated, since it is file-format specific. - -warning('This function is deprecated, see http://www2.ru.nl/fcdonders/fieldtrip/doku.php?id=fieldtrip:development:deprecated for more details.'); - -% read the header information -hdr = read_fcdc_header(cfg.headerfile); - -% read the external marker file in BrainVision format -[stim, resp, segment, timezero] = read_brainvision_vmrk(cfg.trialdef.trgfile); -% set the default marker elements that can be converted into trials -if ~isfield(cfg.trialdef, 'stim') - cfg.trialdef.stim = []; -end -if ~isfield(cfg.trialdef, 'resp') - cfg.trialdef.resp = []; -end -if ~isfield(cfg.trialdef, 'segment') - cfg.trialdef.segment = 'no'; -end -if ~isfield(cfg.trialdef, 'timezero') - cfg.trialdef.timezero = 'no'; -end -trl = []; -for i=1:size(stim,1) - if ismember(stim(i,1),cfg.trialdef.stim) - trlbegin = round((stim(i,2)/1000-cfg.trialdef.prestim)*hdr.Fs)+1; - trlend = round((stim(i,2)/1000+cfg.trialdef.poststim)*hdr.Fs)+1; - trloffset = round(-cfg.trialdef.prestim*hdr.Fs); - trl = [trl; trlbegin trlend trloffset]; - end -end -fprintf('%d stimulus markers converted into %d trials\n', size(stim,1), size(trl,1)); -tmp = size(trl,1); -for i=1:size(resp,1) - if ismember(resp(i,1),cfg.trialdef.resp) - trlbegin = round((resp(i,2)/1000-cfg.trialdef.prestim)*hdr.Fs)+1; - trlend = round((resp(i,2)/1000+cfg.trialdef.poststim)*hdr.Fs)+1; - trloffset = round(-cfg.trialdef.prestim*hdr.Fs); - trl = [trl; trlbegin trlend trloffset]; - end -end -fprintf('%d response markers converted into %d trials\n', size(resp,1), size(trl,1)-tmp); -tmp = size(trl,1); -if strcmp(cfg.trialdef.segment, 'yes') - for i=1:size(segment,1) - trlbegin = round((segment(i)/1000-cfg.trialdef.prestim)*hdr.Fs)+1; - trlend = round((segment(i)/1000+cfg.trialdef.poststim)*hdr.Fs)+1; - trloffset = round(-cfg.trialdef.prestim*hdr.Fs); - trl = [trl; trlbegin trlend trloffset]; - end -end -fprintf('%d segment markers converted into %d trials\n', size(segment,1), size(trl,1)-tmp); -tmp = size(trl,1); -if strcmp(cfg.trialdef.timezero, 'yes') - for i=1:size(timezero,1) - trlbegin = round((timezero(i)/1000-cfg.trialdef.prestim)*hdr.Fs)+1; - trlend = round((timezero(i)/1000+cfg.trialdef.poststim)*hdr.Fs)+1; - trloffset = round(-cfg.trialdef.prestim*hdr.Fs); - trl = [trl; trlbegin trlend trloffset]; - end -end -fprintf('%d "Time 0" markers converted into %d trials\n', size(timezero,1), size(trl,1)-tmp); diff --git a/external/fieldtrip/private/trialfun_ctf_continuous.m b/external/fieldtrip/private/trialfun_ctf_continuous.m deleted file mode 100644 index cecf4a0..0000000 --- a/external/fieldtrip/private/trialfun_ctf_continuous.m +++ /dev/null @@ -1,39 +0,0 @@ -function [trl] = trialfun_ctf_continuous(cfg); - -% For continuous CTF data, the trialdef structure should contain -% cfg.trialdef.trigger = 2 trigger code, can be an array -% cfg.trialdef.prestim = 0.300 latency in seconds -% cfg.trialdef.poststim = 0.700 latency in seconds -% cfg.trialdef.panel = 'front' or 'back' (optional, back is the default) - -% read the header information -hdr = read_fcdc_header(cfg.headerfile); - -% read the triggers from the STIM channel -fprintf('reading stimulus channel and detecting trigger onset\n'); -[backpanel, frontpanel] = read_ctf_trigger(cfg.dataset); -if isfield(cfg.trialdef, 'panel') - if strcmp(cfg.trialdef.panel, 'back') - trigger = backpanel; - elseif strcmp(cfg.trialdef.panel, 'front') - trigger = frontpanel; - elseif strcmp(cfg.trialdef.panel, 'both') - % recombine the triggers on back and frontpanel into a single trigger value - trigger = frontpanel + (2^16)*backpanel; - else - error('unrecognized option for cfg.trialdef.panel'); - end -else - % default is to use the backpanel where the Presentations PC is plugged into - trigger = backpanel; -end -fprintf('total number of triggers is %d\n', length(find(trigger))); -% find the samples at which the specified trigger occured -trigindx = find(ismember(trigger, cfg.trialdef.trigger)); -% convert the trigger moments into trials -trl(:,1) = trigindx(:) - round(cfg.trialdef.prestim*hdr.Fs); % define begin of each trial (in samples) -trl(:,2) = trigindx(:) + round(cfg.trialdef.poststim*hdr.Fs); % define end of each trial (in samples) -trl(:,3) = round(-cfg.trialdef.prestim*hdr.Fs); % define the trial offset relative to latency zero (in samples) -trl(find(trl(:,1)<1), :) = []; % remove trials beginning before the start of the file -trl(find(trl(:,2)>hdr.nTrials*hdr.nSamples), :) = []; % remove trials after the end of the file -fprintf('%d triggers converted into %d trials\n', length(trigindx), size(trl,1)); diff --git a/external/fieldtrip/private/trialfun_ctf_epoched.m b/external/fieldtrip/private/trialfun_ctf_epoched.m deleted file mode 100644 index d47a75b..0000000 --- a/external/fieldtrip/private/trialfun_ctf_epoched.m +++ /dev/null @@ -1,137 +0,0 @@ -function [trl] = trialfun_ctf_epoched(cfg); - -% For epoched CTF data, the trialdef structure should contain -% cfg.trialdef.includeTrigger = array, e.g. [3 7] -% cfg.trialdef.excludeTrigger = array -% cfg.trialdef.includeConditions = cell-array, e.g. {'C1', 'C2'} -% cfg.trialdef.excludeConditions = cell-array, e.g. {'BAD'} -% cfg.trialdef.prestim = 0.300 latency in seconds -% cfg.trialdef.poststim = 0.700 latency in seconds -% Note that definitions according to the trigger values in the stimulus -% channel can be combined with contitions defined in the CTF DataEditor. -% -% Warning: this function is deprecated, since it is file-format specific. - -warning('This function is deprecated, see http://www2.ru.nl/fcdonders/fieldtrip/doku.php?id=fieldtrip:development:deprecated for more details.'); - -% read the header information -hdr = read_fcdc_header(cfg.headerfile); - -% set empty defaults for the fields that do not exist -if ~isfield(cfg.trialdef, 'includeTrigger'), cfg.trialdef.includeTrigger = []; end -if ~isfield(cfg.trialdef, 'excludeTrigger'), cfg.trialdef.excludeTrigger = []; end -if ~isfield(cfg.trialdef, 'includeConditions'), cfg.trialdef.includeConditions = {}; end -if ~isfield(cfg.trialdef, 'excludeConditions'), cfg.trialdef.excludeConditions = {}; end -% ensure that these are cell-arrays -if ischar(cfg.trialdef.includeConditions), cfg.trialdef.includeConditions = {cfg.trialdef.includeConditions}; end -if ischar(cfg.trialdef.excludeConditions), cfg.trialdef.excludeConditions = {cfg.trialdef.excludeConditions}; end -% Read trial definitions from the ClassFile.cls in the dataset -[condNumbers,condLabels] = read_ctf_cls(fullfile(cfg.dataset, 'ClassFile.cls')); -% Read trigger list from datafile -triggerChan = read_ctf_trigger(cfg.dataset); -% Shorten trials according to pre and poststim -if isfield(cfg.trialdef,'prestim') - nSamplesPreTmp = round(cfg.trialdef.prestim*hdr.Fs); - nPreCorr = hdr.nSamplesPre - nSamplesPreTmp; - if nPreCorr < 0 - error('You have defined cfg.traildef.nsamplePre too large'); - end -else - nPreCorr = 0; -end -if isfield(cfg.trialdef,'poststim') - nSamplesPostTmp = round(cfg.trialdef.poststim*hdr.Fs) ; - nPostCorr = (hdr.nSamples-hdr.nSamplesPre) - nSamplesPostTmp; - if nPostCorr < 0 - error('You have defined cfg.traildef.nsamplePost too large'); - end -else - nPostCorr = 0; -end -% Extract the relevant trials from CTF data -trl = []; -l = 0; -for k=1:hdr.nTrials - if approveTrial(cfg,k,condNumbers,condLabels) - % search 5 samples around where the trigger should be - tbeg = (k-1)*hdr.nSamples+1 + hdr.nSamplesPre-2; - tend = (k-1)*hdr.nSamples+1 + hdr.nSamplesPre+2; - % be carefull not to to search outside of the data - tbeg = max(tbeg, 1); - tend = min(tend, hdr.nSamples*hdr.nTrials); - % Pull out the trigger chan for trial k and find the trigger value, - trigVal = max(triggerChan(tbeg:tend)); - if approveTrigger(cfg,trigVal) - l = l + 1; - trl(l,1) = 1+(k-1)*hdr.nSamples + nPreCorr; - trl(l,2) = k*hdr.nSamples - nPostCorr; - trl(l,3) = -hdr.nSamplesPre + nPreCorr; - end - end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION for single trial definition in case of CTF data -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [ok] = approveTrigger(cfg,trigVal) -ok = 1; -if isempty(cfg.trialdef.includeTrigger) - ok = 1; -else - ok = 0; - for k=1:length(cfg.trialdef.includeTrigger) - if trigVal == cfg.trialdef.includeTrigger(k) - ok = 1; - end - end -end -if ~isempty(cfg.trialdef.excludeTrigger) - for k=1:length(cfg.trialdef.excludeTrigger) - if trigVal == cfg.trialdef.excludeTrigger(k) - ok = 0; - end - end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION for single trial definition in case of CTF data -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [ok] = approveTrial(cfg,Trial,condNumbers,condLabels) -if isempty(condLabels) - ok = 1; - return -end -ok = 0; -if isfield(cfg.trialdef,'includeConditions') && ~isempty(cfg.trialdef.includeConditions) - for k=1:length(cfg.trialdef.includeConditions) - for l=1:length(condLabels) - if iscell(condNumbers{l}) - dum = cell2mat(condNumbers{l}); - else - dum = condNumbers{l}; - end - if strcmp(char(condLabels{l}),char(cfg.trialdef.includeConditions{k})) && ismember(Trial,dum) - fprintf('Including trial %d; Label: %s\n',Trial,char(cfg.trialdef.includeConditions{k})); - ok = 1; - end - end - end -else - ok = 1; -end -if isfield(cfg.trialdef,'excludeConditions') && ~isempty(cfg.trialdef.excludeConditions) - for k=1:length(cfg.trialdef.excludeConditions) - for l=1:length(condLabels) - if iscell(condNumbers{l}) - dum = cell2mat(condNumbers{l}); - else - dum = condNumbers{l}; - end - if strcmp(char(condLabels{l}),char(cfg.trialdef.excludeConditions{k})) && ismember(Trial,dum) - fprintf('Excluding trial %d; Label: %s\n',Trial,char(cfg.trialdef.excludeConditions{k})); - ok = 0; - end - end - end -end - diff --git a/external/fieldtrip/private/trialfun_eeprobe_avr.m b/external/fieldtrip/private/trialfun_eeprobe_avr.m deleted file mode 100644 index 797b3ae..0000000 --- a/external/fieldtrip/private/trialfun_eeprobe_avr.m +++ /dev/null @@ -1,15 +0,0 @@ -function [trl] = trialfun_eeprobe_avr(cfg); - -% For averaged EEProbe data, the trialdef structure should not contain anything -% cfg.trialdef = [] -% -% Warning: this function is deprecated, since it is file-format specific. - -warning('This function is deprecated, see http://www2.ru.nl/fcdonders/fieldtrip/doku.php?id=fieldtrip:development:deprecated for more details.'); - -% read the header information -hdr = read_fcdc_header(cfg.headerfile); - -trl(1) = 1; -trl(2) = hdr.nSamples; -trl(3) = -hdr.nSamplesPre; diff --git a/external/fieldtrip/private/trialfun_eeprobe_cnt.m b/external/fieldtrip/private/trialfun_eeprobe_cnt.m deleted file mode 100644 index b013861..0000000 --- a/external/fieldtrip/private/trialfun_eeprobe_cnt.m +++ /dev/null @@ -1,27 +0,0 @@ -function [trl] = trialfun_eeprobe_cnt(cfg); - -% For continuous EEProbe data, the trialdef structure should contain -% cfg.trialdef.trigger = 2 trigger code, can be a list -% cfg.trialdef.prestim = 0.300 latency in seconds -% cfg.trialdef.poststim = 0.700 latency in seconds -% cfg.trialdef.trgfile = filename of the trigger file -% -% Warning: this function is deprecated, since it is file-format specific. - -warning('This function is deprecated, see http://www2.ru.nl/fcdonders/fieldtrip/doku.php?id=fieldtrip:development:deprecated for more details.'); - -% read the header information -hdr = read_fcdc_header(cfg.headerfile); - -% read external trigger file in EEP format -trg = read_eep_trg(cfg.trialdef.trgfile); -trl = []; -for i=1:length(trg) - if ismember(trg(i).type,cfg.trialdef.trigger) - trlbegin = round((trg(i).time/1000-cfg.trialdef.prestim)*hdr.Fs)+1; - trlend = round((trg(i).time/1000+cfg.trialdef.poststim)*hdr.Fs)+1; - trloffset = round(-cfg.trialdef.prestim*hdr.Fs); - trl = [trl; trlbegin trlend trloffset]; - end -end -fprintf('%d triggers converted into %d trials\n', length(trg), size(trl,1)); diff --git a/external/fieldtrip/private/trialfun_neuromag.m b/external/fieldtrip/private/trialfun_neuromag.m deleted file mode 100644 index a64b6ef..0000000 --- a/external/fieldtrip/private/trialfun_neuromag.m +++ /dev/null @@ -1,32 +0,0 @@ -function [trl] = trialfun_neuromag(cfg); - -% For Neuromag data, the trialdef structure should contain -% cfg.trialdef.trgchan = channel label, e.g. 'STI 001' -% cfg.trialdef.prestim = 0.300 latency in seconds -% cfg.trialdef.poststim = 0.700 latency in seconds -% -% Warning: this function is deprecated, since it is file-format specific. - -warning('This function is deprecated, see http://www2.ru.nl/fcdonders/fieldtrip/doku.php?id=fieldtrip:development:deprecated for more details.'); - -% read the header information -hdr = read_fcdc_header(cfg.headerfile); - -chanindx = match_str(hdr.label, cfg.trialdef.trgchan); -nsamples = hdr.nTrials * hdr.nSamples; -if ~isfield(cfg, 'datatype') || ~strcmp(cfg.datatype, 'continuous') - % datatype is unknown or not continuous, perform epoch boundary check - iscontinuous = 0; -else - % do not perform epoch boundary check, usefull for pseudo-continuous data - iscontinuous = strcmp(cfg.datatype, 'continuous'); -end -read_fcdc_data(cfg.datafile, hdr, 1, nsamples, chanindx, iscontinuous); -trigindx = find(trigger & [0 diff(trigger)]); -trl(:,1) = trigindx(:) - round(cfg.trialdef.prestim*hdr.Fs); % define begin of each trial (in samples) -trl(:,2) = trigindx(:) + round(cfg.trialdef.poststim*hdr.Fs); % define end of each trial (in samples) -trl(:,3) = round(-cfg.trialdef.prestim*hdr.Fs); % define the trial offset relative to latency zero (in samples) -trl(find(trl(:,1)<1), :) = []; % remove trials beginning before the start of the file -trl(find(trl(:,2)>hdr.nTrials*hdr.nSamples), :) = []; % remove trials after the end of the file -fprintf('%d triggers converted into %d trials\n', length(trigindx), size(trl,1)); - diff --git a/external/fieldtrip/private/trialfun_neuroscan_cnt.m b/external/fieldtrip/private/trialfun_neuroscan_cnt.m deleted file mode 100644 index 2f68229..0000000 --- a/external/fieldtrip/private/trialfun_neuroscan_cnt.m +++ /dev/null @@ -1,22 +0,0 @@ -function [trl] = trialfun_ns_cnt(cfg); - -% For continuous NeuroScan data, the trialdef structure should contain -% cfg.trialdef.trigger = number or list with triggers -% cfg.trialdef.prestim = pre-stimulus in seconds -% cfg.trialdef.poststim = post-stimulus in seconds -% -% Warning: this function is deprecated, since it is file-format specific. - -warning('This function is deprecated, see http://www2.ru.nl/fcdonders/fieldtrip/doku.php?id=fieldtrip:development:deprecated for more details.'); - -% read the header information -hdr = read_fcdc_header(cfg.headerfile); - -% read the header and the event table from the continuous file -tmp = read_ns_cnt(cfg.datafile, 'ldheaderonly', 1); -fprintf('found %d events in continuous neuroscan file\n', length(tmp.event.frame)); -eventindx = find(ismember(tmp.event.stimtype, cfg.trialdef.trigger)); -trl(:,1) = tmp.event.frame(eventindx) - round(cfg.trialdef.prestim*tmp.rate) + 1; % begin sample -trl(:,2) = tmp.event.frame(eventindx) + round(cfg.trialdef.poststim*tmp.rate) + 1; % end sample -trl(:,3) = -round(cfg.trialdef.prestim*tmp.rate); % offset -fprintf('selected %d events based on triggercode\n', size(trl,1)); diff --git a/external/fieldtrip/private/trialfun_neuroscan_eeg.m b/external/fieldtrip/private/trialfun_neuroscan_eeg.m deleted file mode 100644 index 738a18e..0000000 --- a/external/fieldtrip/private/trialfun_neuroscan_eeg.m +++ /dev/null @@ -1,32 +0,0 @@ -function [trl] = trialfun_ns_eeg(cfg); - -% For epoched NeuroScan data, the trialdef structure should not contain anything -% cfg.trialdef = [] -% -% Warning: this function is deprecated, since it is file-format specific. - -warning('This function is deprecated, see http://www2.ru.nl/fcdonders/fieldtrip/doku.php?id=fieldtrip:development:deprecated for more details.'); - -% read the header information -hdr = read_fcdc_header(cfg.headerfile); - -for k=1:hdr.nsweeps - trl(k,1) = 1+(k-1)*hdr.npnt; - trl(k,2) = k*hdr.npnt; - trl(k,3) = (hdr.rate*hdr.xmin/1000); -end -fprintf('found %d trials in epoched neuroscan file\n', size(trl,1)); -fprintf('looking for manually accepted/rejected trials '); -accept = ones(1,hdr.nsweeps); -for k=1:hdr.nsweeps - tmp = read_ns_eeg(cfg.datafile, k); - accept(k) = tmp.sweep.accept; - if accept(k) - fprintf('.'); - else - fprintf('R'); - end -end -fprintf('\n'); -trl = trl(find(accept), :); -fprintf('accepted %d trials, rejected %d trials\n', sum(accept==1), sum(accept==0)); diff --git a/external/fieldtrip/private/trialfun_realtime.m b/external/fieldtrip/private/trialfun_realtime.m deleted file mode 100644 index f567cd2..0000000 --- a/external/fieldtrip/private/trialfun_realtime.m +++ /dev/null @@ -1,126 +0,0 @@ -function trl = trialfun_realtime(cfg) -% TRIALFUN_REALTIME can be used in conjunction with rt_process to read realtime -% data. Trials are defined as [begsample endsample offset condition] -% -% options: -% cfg.minsample = the last sample number that was already considered (passed from rt_process) -% cfg.blocksize = [offset length] in seconds. In case of events, offset is -% wrt the trigger. In case of no events, offset is wrt -% prevSample. E.g., [-0.9 1] will read 1 second blocks with -% 0.9 second overlap (default = [0 1]). -% cfg.bufferdata = {'first' 'last'}. If 'last' then only the last block of -% interest is read. Otherwise, all well-defined blocks are read (default = 'first') -% -% Copyright (C) 2009, Marcel van Gerven -% -% $Log: trialfun_realtime.m,v $ -% Revision 1.6 2009/02/10 10:53:29 marvger -% default blocksize set to 0.1 (100 ms blocks as in the realtime protocol) -% -% Revision 1.5 2009/02/04 13:59:46 marvger -% removed keyboard command -% -% Revision 1.4 2009/01/29 10:35:48 marvger -% more error checking -% -% Revision 1.3 2009/01/28 20:46:44 marvger -% samples are forced to be > 0 -% -% Revision 1.2 2009/01/28 10:56:39 marvger -% we do not consider samples before minsample+1 in asynchronous mode -% -% Revision 1.1 2009/01/28 09:52:01 marvger -% generic trialfun for realtime processing -% - - if ~isfield(cfg,'minsample'), cfg.minsample = 0; end - if ~isfield(cfg,'blocksize'), cfg.blocksize = [0 0.1]; end - if ~isfield(cfg,'bufferdata'), cfg.bufferdata = 'first'; end - if ~isfield(cfg,'triggers'), cfg.triggers = []; end - - % blocksize in terms of samples - cfg.blocksize = round(cfg.blocksize * cfg.hdr.Fs); - - % retrieve trials of interest - if isempty(cfg.event) % asynchronous mode - trl = trialfun_asynchronous(cfg); - else % synchronous mode - trl = trialfun_synchronous(cfg); - end -end - -function trl = trialfun_asynchronous(cfg) - - trl = []; - - prevSample = cfg.minsample; - - if strcmp(cfg.bufferdata, 'last') % only get last block - - % begsample starts blocksize(2) samples before the end - begsample = cfg.hdr.nSamples*cfg.hdr.nTrials - cfg.blocksize(2); - - % begsample should be blocksize(1) samples away from the previous read - if begsample >= (prevSample + cfg.blocksize(1)) - - endsample = cfg.hdr.nSamples*cfg.hdr.nTrials; - - if begsample < endsample && begsample > 0 - trl = [begsample endsample 0 nan]; - end - end - - else % get all blocks - - while true - - % see whether new samples are available - newsamples = (cfg.hdr.nSamples*cfg.hdr.nTrials-prevSample); - - % if newsamples exceeds the offset plus length specified in blocksize - if newsamples>=sum(cfg.blocksize) - - % we do not consider samples < 1 - begsample = max(1,prevSample+cfg.blocksize(1)); - endsample = max(1,prevSample+sum(cfg.blocksize)); - - if begsample < endsample && endsample <= cfg.hdr.nSamples*cfg.hdr.nTrials - trl = [trl; [begsample endsample 0 nan]]; - end - prevSample = endsample; - - else - break; - end - end - end -end - -function trl = trialfun_synchronous(cfg) - - trl = []; - offset = cfg.hdr.Fs * cfg.blocksize(1); - - % process all events - for j=1:length(cfg.event) - - if isempty(cfg.triggers) - curtrig = cfg.event(j).value; - else - [m1,curtrig] = ismember(cfg.event(j).value,cfg.triggers); - end - - if isempty(curtrig), curtrig = nan; end - - if isempty(cfg.triggers) || (~isempty(m1) && m1) - % catched a trigger of interest - - % we do not consider samples < 1 - begsample = max(1,cfg.event(j).sample + cfg.blocksize(1)); - endsample = max(1,begsample + cfg.blocksize(2)); - - trl = [trl; [begsample endsample begsample + offset curtrig]]; - - end - end -end diff --git a/external/fieldtrip/private/trialfun_trial.m b/external/fieldtrip/private/trialfun_trial.m deleted file mode 100644 index 1e21190..0000000 --- a/external/fieldtrip/private/trialfun_trial.m +++ /dev/null @@ -1,21 +0,0 @@ -function [trl, event] = trialfun_trial(cfg); - -if isfield(cfg, 'event') - % for BCI applications events should be specified in the cfg - % to prevent reading the same events many times - event = cfg.event; -else - event = read_event(cfg.dataset); -end - -trl = []; -sel = find(strcmp({event.type}, 'trial')); - -for i=1:length(sel) - begsample = event(sel(i)).sample; - endsample = begsample + event(sel(i)).duration - 1; - offset = event(sel(i)).offset; - % add it to the list - trl = [trl; [begsample endsample offset]]; -end - diff --git a/external/fieldtrip/private/triangle4pt.m b/external/fieldtrip/private/triangle4pt.m old mode 100755 new mode 100644 index cbfa6c2..1b93570 --- a/external/fieldtrip/private/triangle4pt.m +++ b/external/fieldtrip/private/triangle4pt.m @@ -33,14 +33,8 @@ % % written by Christophe Phillips, 2009/01/19 % Cyclotron Research Centre, University of li?ge, belgium - -% $Log: triangle4pt.m,v $ -% Revision 1.4 2009/04/30 16:59:49 vlalit -% Bug fix for the problem of too flat mesh surfaces as suggested by Christophe -% -% Revision 1.3 2009/04/01 13:26:05 roboos -% use Taubin's method of sphere fitting (fitsphere) instead of the iterative implementation by Guido Nolte % +% $Id: triangle4pt.m 946 2010-04-21 17:51:16Z roboos $ Ns = length(vol.bnd); for ii=1:Ns % treat each mesh one at a time diff --git a/external/fieldtrip/private/triangulate_seg.m b/external/fieldtrip/private/triangulate_seg.m index 5e09274..ac29929 100644 --- a/external/fieldtrip/private/triangulate_seg.m +++ b/external/fieldtrip/private/triangulate_seg.m @@ -12,19 +12,23 @@ % Copyright (C) 2005, Robert Oostenveld % -% $Log: triangulate_seg.m,v $ -% Revision 1.4 2009/01/19 12:20:04 roboos -% incorporated suggestion by Jon Iversen to fix bug in case sel=[] +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.3 2006/07/26 11:05:58 roboos -% use find('last') for matlab 7 and higher, and regular find for older matlab versions +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.2 2006/04/03 10:39:24 roboos -% added origin of the projection towards the surface as third (optional) input argument +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.1 2005/11/03 11:12:32 roboos -% new implementation, using a projection of a ksphere triangulation from the center of the volume +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: triangulate_seg.m 952 2010-04-21 18:29:51Z roboos $ seg = (seg~=0); dim = size(seg); diff --git a/external/fieldtrip/private/triplot.m b/external/fieldtrip/private/triplot.m index 730122a..7b28e8f 100644 --- a/external/fieldtrip/private/triplot.m +++ b/external/fieldtrip/private/triplot.m @@ -37,26 +37,23 @@ % Copyright (C) 2001=2006, Robert Oostenveld % -% $Log: triplot.m,v $ -% Revision 1.7 2008/06/24 13:37:51 roboos -% added option faces_blue -% always return handle to objects that were plotted +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.6 2007/01/03 17:00:35 roboos -% updated documentation, changed layout of code and comments +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.5 2006/09/19 16:11:35 roboos -% added support for line segments, removed "axis equal" at end +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.4 2006/05/02 19:15:28 roboos -% added 'faces_red' style -% -% Revision 1.3 2004/06/28 07:51:39 roberto -% improved documentation, added faces_skin -% -% Revision 1.2 2003/03/17 10:37:29 roberto -% improved general help comments and added copyrights +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: triplot.m 952 2010-04-21 18:29:51Z roboos $ % start with empty return values hs = []; @@ -130,9 +127,9 @@ v(1) = triangle_val(tri_indx,1); v(2) = triangle_val(tri_indx,2); v(3) = triangle_val(tri_indx,3); - la(1) = (cnt-v(1)) / (v(2)-v(1)); % abcissa between vertex 1 and 2 - la(2) = (cnt-v(2)) / (v(3)-v(2)); % abcissa between vertex 2 and 3 - la(3) = (cnt-v(3)) / (v(1)-v(3)); % abcissa between vertex 1 and 2 + la(1) = (cnt-v(1)) / (v(2)-v(1)); % abcissa between vertex 1 and 2 + la(2) = (cnt-v(2)) / (v(3)-v(2)); % abcissa between vertex 2 and 3 + la(3) = (cnt-v(3)) / (v(1)-v(3)); % abcissa between vertex 1 and 2 abc(1,:) = pos(1,:) + la(1) * (pos(2,:) - pos(1,:)); abc(2,:) = pos(2,:) + la(2) * (pos(3,:) - pos(2,:)); abc(3,:) = pos(3,:) + la(3) * (pos(1,:) - pos(3,:)); @@ -342,7 +339,7 @@ hc = [hc; h1]; end -end % switch +end % switch axis off axis vis3d diff --git a/external/fieldtrip/private/uidisplaytext.m b/external/fieldtrip/private/uidisplaytext.m index 901ea1a..1289a0a 100644 --- a/external/fieldtrip/private/uidisplaytext.m +++ b/external/fieldtrip/private/uidisplaytext.m @@ -8,10 +8,23 @@ function uidisplaytext(str, title) % Copyright (C) 2009, Robert Oostenveld % -% $Log: uidisplaytext.m,v $ -% Revision 1.1 2009/03/05 09:02:54 roboos -% created helper function for cfg2script +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: uidisplaytext.m 952 2010-04-21 18:29:51Z roboos $ if nargin<2 title = 'unknown'; diff --git a/external/fieldtrip/private/uilayout.m b/external/fieldtrip/private/uilayout.m deleted file mode 100644 index 934ef32..0000000 --- a/external/fieldtrip/private/uilayout.m +++ /dev/null @@ -1,163 +0,0 @@ -function uilayout(h, varargin) - -% UILAYOUT is a helper function to facilitate the layout of multiple -% usercontrol elements - -% Copyright (C) 2009, Robert Oostenveld -% -% $Log: uilayout.m,v $ -% Revision 1.3 2009/08/04 12:42:34 ingnie -% fixed typo -% -% Revision 1.2 2009/08/04 12:29:29 ingnie -% fixed small typo -% -% Revision 1.1 2009/08/04 11:57:47 roboos -% implemented helper function for consistent setting of uicontrol details and for consistent and/or automatic layouting -% - -% these are used to make a selection of uicontrol elements -tag = keyval('tag', varargin{:}); -style = keyval('style', varargin{:}); - -% determine all children -if ~isempty(tag) && ~isempty(style) - c = findall(h, 'tag', tag, 'style', style); -elseif ~isempty(tag) - c = findall(h, 'tag', tag); -elseif ~isempty(style) - c = findall(h, 'style', style); -else - c = findall(h); -end -c = flipud(c); -% fprintf('selected %d elements\n', numel(c)); - -% these are the normal features of an uicontrol -BackgroundColor = keyval('BackgroundColor', varargin{:}); -CallBack = keyval('CallBack', varargin{:}); -Clipping = keyval('Clipping', varargin{:}); -Enable = keyval('Enable', varargin{:}); -FontAngle = keyval('FontAngle', varargin{:}); -FontName = keyval('FontName', varargin{:}); -FontSize = keyval('FontSize', varargin{:}); -FontUnits = keyval('FontUnits', varargin{:}); -FontWeight = keyval('FontWeight', varargin{:}); -ForegroundColor = keyval('ForegroundColor', varargin{:}); -HorizontalAlignment = keyval('HorizontalAlignment', varargin{:}); -Max = keyval('Max', varargin{:}); -Min = keyval('Min', varargin{:}); -Position = keyval('Position', varargin{:}); -Selected = keyval('Selected', varargin{:}); -String = keyval('String', varargin{:}); -Units = keyval('Units', varargin{:}); -Value = keyval('Value', varargin{:}); -Visible = keyval('Visible', varargin{:}); -Tag = keyval('retag', varargin{:}); % this is to change the tag on the selected items -Style = keyval('restyle', varargin{:}); % this is to change the style on the selected items - -feature = { - 'BackgroundColor' - 'CallBack' - 'Clipping' - 'Enable' - 'FontAngle' - 'FontName' - 'FontSize' - 'FontUnits' - 'FontWeight' - 'ForegroundColor' - 'HorizontalAlignment' - 'Max' - 'Min' - 'Position' - 'Selected' - 'String' - 'Units' - 'Value' - 'Visible' - 'Tag' - 'Style' - }; - -for i=1:length(feature) - val = eval(feature{i}); - if ~isempty(val) - % fprintf('setting %s\n', feature{i}); - for j=1:length(c) - set(c(j), feature{i}, val) - end - end -end - -% these are special features to help with the positioning of the elements -hpos = keyval('hpos', varargin{:}); -vpos = keyval('vpos', varargin{:}); -width = keyval('width', varargin{:}); -height = keyval('height', varargin{:}); - -if isempty(hpos) && isempty(vpos) && isempty(width) && isempty(height) - % re-positioning of the elements is not needed - return -end - -pos = zeros(length(c), 4); -for i=1:length(c) - pos(i,:) = get(c(i), 'position'); -end - -if ~isempty(width) - pos(:,3) = width; -end -width = pos(:,3); - -if ~isempty(height) - pos(:,4) = height; -end -height = pos(:,4); - -if ~isempty(hpos) - if isequal(hpos, 'auto') - scale = (1 - 0.01 - 0.01*length(c)) / sum(width); - if scale>0 && scale<1 - % fprintf('adjusting width with %f\n', scale); - width = width*scale; - pos(:,3) = width; - end - hpos = cumsum([0.01; width+0.01]); - hpos = hpos(1:end-1); - elseif isequal(hpos, 'align') - hpos = pos(1,2); % the position of the first element - elseif isequal(hpos, 'distribute') - minpos = min(pos(:,1)); - maxpos = max(pos(:,1)); - hpos = linspace(minpos, maxpos, length(c)); - end - pos(:,1) = hpos; - pos(:,3) = width; -end % hpos - -if ~isempty(vpos) - if isequal(vpos, 'auto') - scale = (1 - 0.01 - 0.01*length(c)) / sum(height); - if scale>0 && scale<1 - % fprintf('adjusting height with %f\n', scale); - height = height*scale; - pos(:,4) = height; - end - vpos = cumsum([0.01; width]); - vpos = vpos(1:end-1); - elseif isequal(vpos, 'align') - vpos = pos(1,2); % the position of the first element - elseif isequal(vpos, 'distribute') - minpos = min(pos(:,2)); - maxpos = max(pos(:,2)); - vpos = linspace(minpos, maxpos, length(c)); - end - pos(:,2) = vpos; -end % vpos - -% assign the new/automatic position to each of the elements -for i=1:length(c) - set(c(i), 'position', pos(i,:)); -end diff --git a/external/fieldtrip/private/val2nearestchan.m b/external/fieldtrip/private/val2nearestchan.m index b150896..bbeee24 100644 --- a/external/fieldtrip/private/val2nearestchan.m +++ b/external/fieldtrip/private/val2nearestchan.m @@ -9,10 +9,23 @@ % Copyright (C) 2009, Ingrid Nieuwenhuis % -% $Log: val2nearestchan.m,v $ -% Revision 1.1 2009/10/09 12:05:06 ingnie -% first implementation, used by databrowser +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: val2nearestchan.m 952 2010-04-21 18:29:51Z roboos $ fieldtripdefs @@ -41,4 +54,4 @@ channame = data.label{chanNb}; - \ No newline at end of file + diff --git a/external/fieldtrip/private/volplot.m b/external/fieldtrip/private/volplot.m index bf98cad..e033984 100644 --- a/external/fieldtrip/private/volplot.m +++ b/external/fieldtrip/private/volplot.m @@ -1,4 +1,4 @@ -function [h, lpa, rpa] = volplot(x, y, z, dat, sel, cscale) +function [dat] = volplot(x, y, z, dat, sel, cscale) % VOLPLOT make 2D or 3D plot of volumetric data (e.g. MRI) % that is defined on a regular orthogonal grid @@ -24,51 +24,23 @@ % Copyright (C) 2003, Robert Oostenveld % -% $Log: volplot.m,v $ -% Revision 1.15 2007/01/04 12:26:11 roboos -% added linear index of the voxel as selection method +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.14 2006/05/02 19:14:19 roboos -% default to interactive when only one 3D input +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.13 2004/06/28 07:52:42 roberto -% fixed some minor bugs, changed crosshair color from black to yello +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.12 2004/01/29 09:14:03 roberto -% added an interactive mode to localize nas/lpa/rpa -% -% Revision 1.11 2004/01/21 12:55:49 roberto -% added voxel number to printed output, easy find back maximum source -% -% Revision 1.10 2004/01/19 14:50:13 roberto -% added option 'center' -% -% Revision 1.9 2004/01/13 09:24:13 roberto -% added input option for color axis -% -% Revision 1.8 2003/11/03 11:42:36 roberto -% added SUMPROJECT (i.e. glassbrain type of projection) -% fixed bug with fprintf of uint8 -% -% Revision 1.7 2003/09/22 10:33:39 roberto -% added fprintf statement indicating value and position -% -% Revision 1.6 2003/09/03 09:53:21 roberto -% removed automatic scaling of montage display -% -% Revision 1.5 2003/04/23 10:20:49 roberto -% fixed 2 bugs related to 1D input data -% -% Revision 1.4 2003/03/24 13:15:04 roberto -% added support for 1D data (automatically converted to 3D) -% -% Revision 1.3 2003/03/21 14:04:31 roberto -% added axis xy to montage plot -% -% Revision 1.2 2003/03/17 10:23:04 roberto -% added montage display -% added automatic min/max selection of intersection point +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: volplot.m 1360 2010-07-06 08:38:59Z roboos $ if nargin<2 dat = x; @@ -160,6 +132,16 @@ rpa = [xc yc zc]; elseif key=='n' nas = [xc yc zc]; + elseif key=='x' + selx= round((xc-0):(xc+0)); + sely= round((yc-0):(yc+0)); + selz= round((zc-0):(zc+0)); + dat(selx,sely,selz) = 0; + elseif key=='X' + selx= round((xc-1):(xc+1)); + sely= round((yc-1):(yc+1)); + selz= round((zc-1):(zc+1)); + dat(selx,sely,selz) = 0; else % update the view to a new position l1 = get(get(gca, 'xlabel'), 'string'); @@ -199,11 +181,11 @@ elseif strcmp(sel, 'sumproject') % make plot of integrated-value projection along the thee orthogonal directions - delete(subplot(2,2,4)); % delete the old colorbar + delete(subplot(2,2,4)); % delete the old colorbar h1 = subplot(2,2,1); h2 = subplot(2,2,2); h3 = subplot(2,2,3); - h4 = subplot(2,2,4); % this will be the new colorbar + h4 = subplot(2,2,4); % this will be the new colorbar % change not-a-number values to zero dat(find(isnan(dat(:)))) = 0; @@ -232,11 +214,11 @@ elseif strcmp(sel, 'maxproject') % make plot of maximum-value projection along the thee orthogonal directions - delete(subplot(2,2,4)); % delete the old colorbar + delete(subplot(2,2,4)); % delete the old colorbar h1 = subplot(2,2,1); h2 = subplot(2,2,2); h3 = subplot(2,2,3); - h4 = subplot(2,2,4); % this will be the new colorbar + h4 = subplot(2,2,4); % this will be the new colorbar subplot(h1); imagesc(x, z, squeeze(max(dat, [], 2))'); set(gca, 'ydir', 'normal') @@ -268,11 +250,11 @@ fprintf('value of %f in voxel %d at [%.02f %.02f %.02f]\n', double(dat(xi, yi, zi)), sub2ind(dim, xi, yi, zi), x(xi), y(yi), z(zi)); - delete(subplot(2,2,4)); % delete the old colorbar + delete(subplot(2,2,4)); % delete the old colorbar h1 = subplot(2,2,1); h2 = subplot(2,2,2); h3 = subplot(2,2,3); - h4 = subplot(2,2,4); % this will be the new colorbar + h4 = subplot(2,2,4); % this will be the new colorbar subplot(h1); imagesc(x, z, squeeze(dat(:,yi,:))'); set(gca, 'ydir', 'normal') diff --git a/external/fieldtrip/private/voltype.m b/external/fieldtrip/private/voltype.m deleted file mode 100644 index c707aa6..0000000 --- a/external/fieldtrip/private/voltype.m +++ /dev/null @@ -1,115 +0,0 @@ -function [type] = voltype(vol, desired) - -% VOLTYPE determines the type of volume conduction model -% -% Use as -% [type] = voltype(vol) -% to get a string describing the type, or -% [flag] = voltype(vol, desired) -% to get a boolean value. -% -% See also READ_VOL, COMPUTE_LEADFIELD - -% Copyright (C) 2007-2008, Robert Oostenveld -% -% $Log: voltype.m,v $ -% Revision 1.4 2009/04/01 06:51:43 roboos -% implemented caching for the type detection in case the same input is given multiple times -% this uses a persistent variable -% -% Revision 1.3 2009/02/02 13:05:22 roboos -% small fix in cpbem->bemcp -% -% Revision 1.2 2009/02/02 12:58:27 roboos -% added bemcp implementation -% -% Revision 1.1 2009/01/21 10:32:38 roboos -% moved from forwinv/* and forwinv/mex/* directory to forwinv/private/* to make the CVS layout consistent with the release version -% -% Revision 1.7 2008/04/30 13:40:34 roboos -% improved detection concentric eeg -% -% Revision 1.6 2008/04/16 08:04:33 roboos -% be flexible in determining whether it is bem -% -% Revision 1.5 2008/04/14 19:31:05 roboos -% return 'unknown' if the type cannot be determined -% -% Revision 1.4 2008/04/10 10:59:38 roboos -% better detection of multisphere meg (after preparing) -% -% Revision 1.3 2008/03/18 12:39:24 roboos -% change in comment, nothing functional -% -% Revision 1.2 2008/03/05 15:24:44 roboos -% changed the detection of various spherical models, added infinite vacuum -% -% Revision 1.1 2007/07/25 08:31:12 roboos -% implemented new helper function -% - -% these are for remembering the type on subsequent calls with the same input arguments -persistent previous_argin previous_argout - -if nargin<2 - % ensure that all input arguments are defined - desired = []; -end - -current_argin = {vol, desired}; -if isequal(current_argin, previous_argin) - % don't do the type detection again, but return the previous values from cache - type = previous_argout{1}; - return -end - -if isfield(vol, 'type') - % preferably the structure specifies its own type - type = vol.type; - -elseif isfield(vol, 'r') && numel(vol.r)==1 && ~isfield(vol, 'label') - type = 'singlesphere'; - -elseif isfield(vol, 'r') && isfield(vol, 'o') && isfield(vol, 'label') - % this is before the spheres have been assigned to the coils - % and every sphere is still associated with a channel - type = 'multisphere'; - -elseif isfield(vol, 'r') && isfield(vol, 'o') && size(vol.r,1)==size(vol.o,1) && size(vol.r,1)>4 - % this is after the spheres have been assigned to the coils - % note that this one is easy to confuse with the concentric one - type = 'multisphere'; - -elseif isfield(vol, 'r') && numel(vol.r)>=2 && ~isfield(vol, 'label') - type = 'concentric'; - -elseif isfield(vol, 'bnd') - type = 'bem'; - -elseif isempty(vol) - type = 'infinite'; - -else - type = 'unknown'; - -end % if isfield(vol, 'type') - -if ~isempty(desired) - % return a boolean flag - switch desired - case 'bem' - type = any(strcmp(type, {'bem', 'dipoli', 'asa', 'avo', 'bemcp'})); - otherwise - type = any(strcmp(type, desired)); - end -end - -% remember the current input and output arguments, so that they can be -% reused on a subsequent call in case the same input argument is given -current_argout = {type}; -if isempty(previous_argin) - previous_argin = current_argin; - previous_argout = current_argout; -end - -return % voltype main() diff --git a/external/fieldtrip/private/volumedownsample.m b/external/fieldtrip/private/volumedownsample.m deleted file mode 100644 index caf0084..0000000 --- a/external/fieldtrip/private/volumedownsample.m +++ /dev/null @@ -1,250 +0,0 @@ -function [down] = volumedownsample(cfg, source); - -% VOLUMEDOWNSAMPLE downsamples an anatomical MRI or source reconstruction -% and optionally normalizes its coordinate axes, keeping the homogenous -% transformation matrix correct. -% -% Use as -% [volume] = volumedownsample(cfg, volume) -% where the cconfiguration can contain -% cfg.downsample = integer number (default = 1, i.e. no downsampling) -% cfg.smooth = 'no' or the FWHM of the gaussian kernel in voxels (default = 'no') -% -% This function is used by SOUREINTERPOLATE, SOURCEREAD and SOURCENORMALIZE. - -% Copyright (C) 2004, Robert Oostenveld -% -% $Log: volumedownsample.m,v $ -% Revision 1.26 2009/10/01 12:48:16 jansch -% allow for volumetric data with dimensionality > 3 -% -% Revision 1.25 2009/05/19 15:22:30 jansch -% remove functional paramters prior to downsampling -% -% Revision 1.24 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.23 2009/01/12 13:05:20 sashae -% small change in call to checkconfig -% -% Revision 1.22 2008/11/21 13:56:12 sashae -% added call to checkconfig at start and end of function -% -% Revision 1.21 2008/10/02 14:40:36 sashae -% checkconfig: checks if the input cfg is valid for this function -% -% Revision 1.20 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.19 2008/09/17 14:53:34 roboos -% removed fixvolume (and underlying grid2transform), not needed any more because checkdata has the possibility of converting a pos to a transform -% -% Revision 1.18 2007/04/18 10:27:44 roboos -% no feedback for checkdata -% -% Revision 1.17 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.16 2007/03/30 17:05:40 ingnie -% checkinput; only proceed when input data is allowed datatype -% -% Revision 1.15 2006/09/13 09:49:15 roboos -% introduced(?) parameterselection function -% -% Revision 1.14 2006/08/16 10:52:53 marsie -% fixed use of spm_smooth -% -% Revision 1.13 2006/07/27 08:29:09 roboos -% updated documentation -% -% Revision 1.12 2006/07/27 08:01:53 roboos -% improved documentation -% -% Revision 1.11 2006/07/25 11:26:33 roboos -% fixed name of variable -% -% Revision 1.10 2006/07/19 12:22:53 jansch -% implemented smoothing for functional volumes -% -% Revision 1.9 2006/04/03 14:09:22 jansch -% removed conversion of inside-volume into vector of indices. -% -% Revision 1.8 2006/02/24 16:45:48 roboos -% switched to fixvolume function, with inside as 3d volume -% not neccessary any more to treat inside/outside seperately -% not neccessary any more to reshape volumes -% -% Revision 1.7 2006/01/31 09:57:38 jansch -% changed if-statement before reformatting the inside-volume into a vector, -% into explicitly checking for the presence of an inside-volume. -% -% Revision 1.6 2006/01/31 09:48:39 jansch -% fixed bug regarding last change -% -% Revision 1.5 2006/01/31 09:45:32 jansch -% changed else cfg.keepinside='no' into an elseif to prevent crashes -% -% Revision 1.4 2006/01/31 09:27:58 roboos -% in case of keepinside: instead of setting outside to [], remove it from structure -% -% Revision 1.3 2006/01/30 13:48:04 roboos -% switched order of parameterselection() and grid2transform() for consistency with other functions -% -% Revision 1.2 2006/01/24 14:20:35 roboos -% removed the obsolete option cfg.voxelcoord, new behaviour is that it is always 'yes' -% -% Revision 1.1 2006/01/05 12:58:19 roboos -% This function (VOLUMExxx) replaces a function with the name xxxVOLUME. -% The fields xgrid/ygrid/zgrid are removed (this is from now on handled by -% grid2transform and the VOLUMExxx function should only work on volumes that -% are described using a transformation matrix). -% Writing of spm/analyze volumes is handled by private/volumewrite_spm. -% -% Revision 1.9 2005/11/10 12:31:01 roboos -% prevent from downsampling if the requested downsampling is 1x -% this also prevents the double allocation of memory for the same data -% -% Revision 1.8 2005/09/29 00:35:20 roboos -% ensure that cfg.parameter is cell array -% add 'inside' to cfg.parameter if desired -% -% Revision 1.7 2005/08/19 16:05:08 roboos -% added default cfg.parameter=all -% switched to parameterselection() subfunction for looping over all interesting volumes -% -% Revision 1.6 2005/08/19 12:03:36 roboos -% add xgrid/ygrid/zgrid if not yet present -% -% Revision 1.5 2005/06/29 12:46:29 roboos -% the following changes were done on a large number of files at the same time, not all of them may apply to this specific file -% - added try-catch around the inclusion of input data configuration -% - moved cfg.version, cfg.previous and the assignment of the output cfg to the end -% - changed help comments around the configuration handling -% - some changes in whitespace -% -% Revision 1.4 2005/05/17 17:50:37 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.3 2005/02/16 15:10:05 roboos -% added new volume fields from pcc beamformer -% -% Revision 1.2 2005/02/08 08:44:38 roboos -% fixed error in computation of new homogenous coordinate transformation matrix (in case of voxelcoords=yes), moved code to separate function (transformgrid) -% replaced computation for all scalar volumes by a for-loop over a parameter list -% implemented downsampling of inside/outside field in same way as the other volumes (keepinside=yes|no) -% -% Revision 1.1 2004/09/08 12:38:33 jansch -% Inserted version information, and moved function out of private folder. The -% function is the same to /private/downsamplevolume.m in older versions of the -% toolbox. -% -% Revision 1.2 2004/08/26 11:12:56 roboos -% added support for all known source parameters, updated help -% -% Revision 1.1 2004/08/26 09:12:26 roboos -% new implementation, to be used by different sourceXXX functions -% - -fieldtripdefs - -%% checkdata see below!!! %% - -% check if the input cfg is valid for this function -cfg = checkconfig(cfg, 'trackconfig', 'on'); -cfg = checkconfig(cfg, 'unused', {'voxelcoord'}); - -if ~isfield(cfg, 'downsample'), cfg.downsample = 1; end -if ~isfield(cfg, 'keepinside'), cfg.keepinside = 'yes'; end -if ~isfield(cfg, 'parameter'), cfg.parameter = 'all'; end -if ~isfield(cfg, 'smooth'), cfg.smooth = 'no'; end - -if strcmp(cfg.keepinside, 'yes') - % add inside to the list of parameters - if ~iscell(cfg.parameter), - cfg.parameter = {cfg.parameter 'inside'}; - else - cfg.parameter(end+1) = {'inside'}; - end -end - -% check if the input data is valid for this function -source = checkdata(source, 'datatype', 'volume', 'feedback', 'no'); - -%make local copy of source and remove all functional parameters -param = parameterselection('all', source); -down = source; -for k = 1:length(param) - down = rmsubfield(down, param{k}); -end - -% select the parameters that should be downsampled -cfg.parameter = parameterselection(cfg.parameter, source); - -% select the voxels that will be kept in the downsampled output volume -xsel = 1:cfg.downsample:source.dim(1); -ysel = 1:cfg.downsample:source.dim(2); -zsel = 1:cfg.downsample:source.dim(3); - -% store the coordinate transformation and downsampled axes definition -down.transform = source.transform; -down.xgrid = xsel; -down.ygrid = ysel; -down.zgrid = zsel; -down.dim = [length(xsel) length(ysel) length(zsel)]; -if length(source.dim)>3, - down.dim = [down.dim source.dim(4:end)]; -end - -% update the downsampled homogenous transformation matrix -down = grid2transform(down); - -% smooth functional parameters, excluding anatomy and inside -if ~strcmp(cfg.smooth, 'no'), - for j = 1:length(cfg.parameter) - if strcmp(cfg.parameter{j}, 'inside') - fprintf('not smoothing %s\n', cfg.parameter{j}); - elseif strcmp(cfg.parameter{j}, 'anatomy') - fprintf('not smoothing %s\n', cfg.parameter{j}); - else - fprintf('smoothing %s with a kernel of %d voxels\n', cfg.parameter{j}, cfg.smooth); - tmp = double(getsubfield(source, cfg.parameter{j})); - spm_smooth(tmp, tmp, cfg.smooth); - setsubfield(source, cfg.parameter{j}, tmp); - end - end -end - -% downsample each of the parameters -if cfg.downsample~=1 - for i=1:length(cfg.parameter) - fprintf('downsampling %s\n', cfg.parameter{i}); - tmp = getsubfield(source, cfg.parameter{i}); - down = setsubfield(down, cfg.parameter{i}, tmp(xsel, ysel, zsel)); % downsample the volume - end -else - for i=1:length(cfg.parameter) - fprintf('not downsampling %s\n', cfg.parameter{i}); - down = setsubfield(down, cfg.parameter{i}, reshape(getsubfield(source, cfg.parameter{i}), source.dim)); - end -end - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: volumedownsample.m,v 1.26 2009/10/01 12:48:16 jansch Exp $'; -% remember the configuration details of the input data -try, cfg.previous = source.cfg; end -% remember the exact configuration details in the output -down.cfg = cfg; diff --git a/external/fieldtrip/private/volumelookup.m b/external/fieldtrip/private/volumelookup.m deleted file mode 100755 index 543ce9e..0000000 --- a/external/fieldtrip/private/volumelookup.m +++ /dev/null @@ -1,276 +0,0 @@ -function [output] = volumelookup(cfg, volume) - -% VOLUMELOOKUP can be used in two directions. (1) It creates a mask -% according to a label from a given atlas, or a sphere or box around a -% point of interest. (2) It gives the labels from a given atlas according -% to a given mask. -% -% Use as -% (1) [mask] = volumelookup(cfg, volume) -% or -% (2) [labels] = volumelookup(cfg, volume) -% -% where volume can be: -% mri is the output of READ_FCDC_MRI -% source is the output of SOURCEANALYSIS -% stat is the output of SOURCESTATISTICS -% -% configuration options for a mask according to an atlas: -% cfg.inputcoord = 'mni' or 'tal', coordinate system of the mri/source/stat -% cfg.atlas = string, filename of atlas to use, either the AFNI -% brik file that is available from http://afni.nimh.nih.gov/afni/doc/misc/ttatlas_tlrc, -% or the WFU atlasses available from http://fmri.wfubmc.edu. see PREPARE_ATLAS -% cfg.roi = string or cell of strings, region(s) of interest from anatomical atlas -% configuration options for a spherical/box mask around a point of interest: -% cfg.roi = Nx3 vector, coordinates of the points of interest -% cfg.sphere = radius of each sphere in cm/mm dep on unit of input -% cfg.box = Nx3 vector, size of each box in cm/mm dep on unit of input -% cfg.round2nearestvoxel = 'yes' or 'no' (default = 'no'), voxel closest to point of interest is calculated -% and box/sphere is centered around coordinates of that voxel -% configuration options for labels from a mask: -% cfg.inputcoord = 'mni' or 'tal', coordinate system of the mri/source/stat -% cfg.atlas = string, filename of atlas to use, either the AFNI -% brik file that is available from http://afni.nimh.nih.gov/afni/doc/misc/ttatlas_tlrc, -% or the WFU atlasses available from http://fmri.wfubmc.edu. see PREPARE_ATLAS -% cfg.maskparameter = string, field in volume to be lookedup, data in field should be logical -% cfg.maxqueryrange = number, should be 1, 3, 5 (default = 1) -% -% The label output has a field "names", a field "count" and a field "usedqueryrange" -% To get a list of areas of the given mask you can do for instance: -% [tmp ind] = sort(labels.count,1,'descend'); -% sel = find(tmp); -% for j = 1:length(sel) -% found_areas{j,1} = [num2str(labels.count(ind(j))) ': ' labels.name{ind(j)}]; -% end -% in found_areas you can then see how many times which labels are found -% NB in the AFNI brick one location can have 2 labels! -% -% Dependent on the input coordinates and the coordinates of the atlas, the -% input MRI is transformed betweem MNI and Talairach-Tournoux coordinates -% See http://www.mrc-cbu.cam.ac.uk/Imaging/Common/mnispace.shtml for more details. - -% Copyright (C) 2008, Robert Oostenveld, Ingrid Nieuwenhuis -% -% $Log: volumelookup.m,v $ -% Revision 1.5 2009/08/03 15:20:19 ingnie -% updated help -% -% Revision 1.4 2009/01/29 13:54:57 ingnie -% changed help -% -% Revision 1.3 2009/01/27 10:09:49 ingnie -% added mask2label functionality -% -% Revision 1.2 2008/12/16 20:42:33 roboos -% converted from dos to unix text file -% -% Revision 1.1 2008/12/05 13:39:38 ingnie -% new implementation based om atlas_mask, added possibility to make spherical and box masks. -% - -fieldtripdefs - -roi2mask = 0; -mask2label = 0; -if isfield(cfg, 'roi'); - roi2mask = 1; -elseif isfield(cfg, 'maskparameter') - mask2label = 1; -else - error('either specify cfg.roi, or cfg.maskparameter') -end - -if roi2mask - % only for volume data - volume = checkdata(volume, 'datatype', 'volume'); - - % set the defaults - if ~isfield(cfg, 'round2nearestvoxel'), cfg.round2nearestvoxel = 'no'; end - - if iscell(cfg.roi) || ischar(cfg.roi) - checkconfig(cfg, 'forbidden', {'sphere' 'box'}, 'required', {'atlas' 'inputcoord'}); - isatlas = 1; - ispoi = 0; - elseif isnumeric(cfg.roi) - checkconfig(cfg, 'forbidden', {'atlas' 'inputcoord'}); - isatlas = 0; - ispoi = 1; - else - error('do not understand cfg.roi') - end - - % determine location of each anatomical voxel in its own voxel coordinates - dim = volume.dim; - i = 1:dim(1); - j = 1:dim(2); - k = 1:dim(3); - [I, J, K] = ndgrid(i, j, k); - ijk = [I(:) J(:) K(:) ones(prod(dim),1)]'; - % determine location of each anatomical voxel in head coordinates - xyz = volume.transform * ijk; % note that this is 4xN - - if isatlas - atlas = prepare_atlas(cfg.atlas); - - if ischar(cfg.roi) - cfg.roi = {cfg.roi}; - end - - sel = []; - for i = 1:length(cfg.roi) - sel = [sel; strmatch(cfg.roi{i}, atlas.descr.name, 'exact')]; - end - - fprintf('found %d matching anatomical labels\n', length(sel)); - - brick = atlas.descr.brick(sel); - value = atlas.descr.value(sel); - - % convert between MNI head coordinates and TAL head coordinates - % coordinates should be expressed compatible with the atlas - if strcmp(cfg.inputcoord, 'mni') && strcmp(atlas.coord, 'tal') - xyz(1:3,:) = mni2tal(xyz(1:3,:)); - elseif strcmp(cfg.inputcoord, 'mni') && strcmp(atlas.coord, 'mni') - % nothing to do - elseif strcmp(cfg.inputcoord, 'tal') && strcmp(atlas.coord, 'tal') - % nothing to do - elseif strcmp(cfg.inputcoord, 'tal') && strcmp(atlas.coord, 'mni') - xyz(1:3,:) = tal2mni(xyz(1:3,:)); - end - - % determine location of each anatomical voxel in atlas voxel coordinates - ijk = inv(atlas.transform) * xyz; - ijk = round(ijk(1:3,:))'; - - inside_vol = ijk(:,1)>=1 & ijk(:,1)<=atlas.dim(1) & ... - ijk(:,2)>=1 & ijk(:,2)<=atlas.dim(2) & ... - ijk(:,3)>=1 & ijk(:,3)<=atlas.dim(3); - inside_vol = find(inside_vol); - - % convert the selection inside the atlas volume into linear indices - ind = sub2ind(atlas.dim, ijk(inside_vol,1), ijk(inside_vol,2), ijk(inside_vol,3)); - - brick0_val = zeros(prod(dim),1); - brick1_val = zeros(prod(dim),1); - % search the two bricks for the value of each voxel - brick0_val(inside_vol) = atlas.brick0(ind); - brick1_val(inside_vol) = atlas.brick1(ind); - - mask = zeros(prod(dim),1); - for i=1:length(sel) - fprintf('constructing mask for %s\n', atlas.descr.name{sel(i)}); - if brick(i)==0 - mask = mask | (brick0_val==value(i)); - elseif brick(i)==1 - mask = mask | (brick1_val==value(i)); - end - end - - elseif ispoi - - if strcmp(cfg.round2nearestvoxel, 'yes') - for i=1:size(cfg.roi,1) - cfg.roi(i,:) = poi2voi(cfg.roi(i,:), xyz); - end - end - - % sphere(s) - if isfield(cfg, 'sphere') - mask = zeros(1,prod(dim)); - for i=1:size(cfg.roi,1) - dist = sqrt( (xyz(1,:) - cfg.roi(i,1)).^2 + (xyz(2,:) - cfg.roi(i,2)).^2 + (xyz(3,:) - cfg.roi(i,3)).^2 ); - mask = mask | (dist <= cfg.sphere(i)); - end - % box(es) - elseif isfield(cfg, 'box') - mask = zeros(1, prod(dim)); - for i=1:size(cfg.roi,1) - mask = mask | ... - (xyz(1,:) <= (cfg.roi(i,1) + cfg.box(i,1)./2) & xyz(1,:) >= (cfg.roi(i,1) - cfg.box(i,1)./2)) & ... - (xyz(2,:) <= (cfg.roi(i,2) + cfg.box(i,2)./2) & xyz(2,:) >= (cfg.roi(i,2) - cfg.box(i,2)./2)) & ... - (xyz(3,:) <= (cfg.roi(i,3) + cfg.box(i,3)./2) & xyz(3,:) >= (cfg.roi(i,3) - cfg.box(i,3)./2)); - end - else - error('either specify cfg.sphere or cfg.box') - end - end - - mask = reshape(mask, dim); - fprintf('%i voxels in mask, which is %.3f %% of total volume\n', sum(mask(:)), 100*mean(mask(:))); - output = mask; - -elseif mask2label - % convert to source representation (easier to work with) - volume = checkdata(volume, 'datatype', 'source'); - checkconfig(cfg, 'required', {'atlas' 'inputcoord'}); - - % set defaults - if ~isfield(cfg, 'maxqueryrange'), cfg.maxqueryrange = 1; end - - if isempty(intersect(cfg.maxqueryrange, [1 3 5])) - error('incorrect query range, should be one of [1 3 5]'); - end - - atlas = prepare_atlas(cfg.atlas); - sel = find(volume.(cfg.maskparameter)(:)); - labels.name = atlas.descr.name; - labels.name{end+1} = 'no_label_found'; - labels.count = zeros(length(labels.name),1); - for iLab = 1:length(labels.name) - labels.usedqueryrange{iLab} = []; - end - - for iVox = 1:length(sel) - usedQR = 1; - label = atlas_lookup(atlas, [volume.pos(sel(iVox),1) volume.pos(sel(iVox),2) volume.pos(sel(iVox),3)], 'inputcoord', cfg.inputcoord, 'queryrange', 1); - if isempty(label) && cfg.maxqueryrange > 1 - label = atlas_lookup(atlas, [volume.pos(sel(iVox),1) volume.pos(sel(iVox),2) volume.pos(sel(iVox),3)], 'inputcoord', cfg.inputcoord, 'queryrange', 3); - usedQR = 3; - end - if isempty(label) && cfg.maxqueryrange > 3 - label = atlas_lookup(atlas, [volume.pos(sel(iVox),1) volume.pos(sel(iVox),2) volume.pos(sel(iVox),3)], 'inputcoord', cfg.inputcoord, 'queryrange', 5); - usedQR = 5; - end - if isempty(label) - label = {'no_label_found'}; - elseif length(label) == 1 - label = {label}; - end - - ind_lab = []; - for iLab = 1:length(label) - ind_lab = [ind_lab find(strcmp(label{iLab}, labels.name))]; - end - - labels.count(ind_lab) = labels.count(ind_lab) + (1/length(ind_lab)); - for iFoundLab = 1:length(ind_lab) - if isempty(labels.usedqueryrange{ind_lab(iFoundLab)}) - labels.usedqueryrange{ind_lab(iFoundLab)} = usedQR; - else - labels.usedqueryrange{ind_lab(iFoundLab)} = [labels.usedqueryrange{ind_lab(iFoundLab)} usedQR]; - end - end - end %iVox - - output = labels; - -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION point of interest to voxel of interest -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function voi = poi2voi(poi, xyz) -xmin = min(abs(xyz(1,:) - poi(1))); xcl = round(abs(xyz(1,:) - poi(1))) == round(xmin); -ymin = min(abs(xyz(2,:) - poi(2))); ycl = round(abs(xyz(2,:) - poi(2))) == round(ymin); -zmin = min(abs(xyz(3,:) - poi(3))); zcl = round(abs(xyz(3,:) - poi(3))) == round(zmin); -xyzcls = xcl + ycl + zcl; ind_voi = xyzcls == 3; -if sum(ind_voi) > 1; - fprintf('%i voxels at same distance of poi, taking first voxel\n', sum(ind_voi)) - ind_voi_temp = find(ind_voi); ind_voi_temp = ind_voi_temp(1); - ind_voi = zeros(size(ind_voi)); - ind_voi(ind_voi_temp) = 1; - ind_voi = logical(ind_voi); -end -voi = xyz(1:3,ind_voi); -fprintf('coordinates of voi: %.1f %.1f %.1f\n', voi(1), voi(2), voi(3)); - diff --git a/external/fieldtrip/private/volumenormalise.m b/external/fieldtrip/private/volumenormalise.m deleted file mode 100644 index 3ed4ae7..0000000 --- a/external/fieldtrip/private/volumenormalise.m +++ /dev/null @@ -1,354 +0,0 @@ -function [normalise] = volumenormalise(cfg, interp) - -% VOLUMENORMALISE normalises anatomical and functional volume data -% to a template anatomical MRI. -% -% Use as -% [volume] = volumenormalise(cfg, volume) -% -% The input volume should be the result from SOURCEINTERPOLATE. -% Alternatively, the input can contain a single anatomical MRI that -% was read with READ_FCDC_MRI, or you can specify a filename of an -% anatomical MRI. -% -% Configuration options are: -% cfg.template = string with filename (default = '/home/common/matlab/spm2/templates/T1.mnc') -% cfg.parameter = cell-array with the functional data which has to -% be normalised, can be 'all' -% cfg.downsample = integer number (default = 1, i.e. no downsampling) -% cfg.coordinates = 'spm, 'ctf' or empty for interactive (default = []) -% cfg.name = string for output filename -% cfg.write = 'no' (default) or 'yes', writes the segmented volumes to SPM2 -% compatible analyze-file, with the suffix -% _anatomy for the anatomical MRI volume -% _param for each of the functional volumes -% cfg.nonlinear = 'yes' (default) or 'no', estimates a nonlinear transformation -% in addition to the linear affine registration. If a reasonably -% accurate normalisation is sufficient, a purely linearly transformed -% image allows for 'reverse-normalisation', which might come in handy -% when for example a region of interest is defined on the normalised -% group-average. - -% Undocumented local options: -% cfg.keepintermediate = 'yes' or 'no' -% cfg.intermediatename = prefix of the the coregistered images and of the -% original images in the original headcoordinate system -% cfg.spmparams = one can feed in parameters from a prior normalisation - -% Copyright (C) 2004-2006, Jan-Mathijs Schoffelen -% -% $Log: volumenormalise.m,v $ -% Revision 1.21 2009/07/14 07:27:30 roboos -% replaced read_fcdc_mri with read_mri to avoid warning -% -% Revision 1.20 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.19 2008/12/15 15:08:34 roboos -% fixed bug in case of parameterselection with anatomy for config object -% -% Revision 1.18 2008/11/21 13:56:12 sashae -% added call to checkconfig at start and end of function -% -% Revision 1.17 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.16 2008/09/17 14:53:35 roboos -% removed fixvolume (and underlying grid2transform), not needed any more because checkdata has the possibility of converting a pos to a transform -% -% Revision 1.15 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.14 2007/03/30 17:05:40 ingnie -% checkinput; only proceed when input data is allowed datatype -% -% Revision 1.13 2006/07/27 08:29:09 roboos -% updated documentation -% -% Revision 1.12 2006/07/25 10:07:06 roboos -% Changed the method to check for spm2, add automatically to path if possible. -% Moved the interactive questions regarding coordinate system to a subfunction. -% Not only determine input source coordinates, but also template coordinates. -% Start with a well defined "initial" transform, and end with a "final" transform, both are stored in the output cfg. -% Use a hard-coded initial transform for ctf2spm instead of align_ctf2spm function. -% Renamed the internal variable names for the volumes for consistency with SPM. -% Removed old log comments. -% -% Revision 1.11 2006/07/19 12:22:52 jansch -% implemented smoothing for functional volumes - -fieldtripdefs - -cfg = checkconfig(cfg, 'trackconfig', 'on'); - -%% checkdata see below!!! %% - -% check the availability of the required SPM2 toolbox -hastoolbox('spm2', 1); - -% set the defaults -if ~isfield(cfg,'template'), cfg.template = '/home/common/matlab/spm2/templates/T1.mnc'; end; -if ~isfield(cfg,'parameter'), cfg.parameter = 'all'; end; -if ~isfield(cfg,'downsample'), cfg.downsample = 1; end; -if ~isfield(cfg,'write'), cfg.write = 'no'; end; -if ~isfield(cfg,'keepinside'), cfg.keepinside = 'yes'; end; -if ~isfield(cfg,'keepintermediate'), cfg.keepintermediate = 'no'; end; -if ~isfield(cfg,'coordinates'), cfg.coordinates = []; end; -if ~isfield(cfg,'initial'), cfg.initial = []; end; -if ~isfield(cfg,'nonlinear'), cfg.nonlinear = 'yes'; end; -if ~isfield(cfg,'smooth'), cfg.smooth = 'no'; end; - -if strcmp(cfg.keepinside, 'yes') - % add inside to the list of parameters - if ~iscell(cfg.parameter), - cfg.parameter = {cfg.parameter 'inside'}; - else - cfg.parameter(end+1) = {'inside'}; - end -end - -if ~isfield(cfg,'intermediatename') - cfg.intermediatename = tempname; -end - -if ~isfield(cfg,'name') && strcmp(cfg.write,'yes') - error('you must specify the output filename in cfg.name'); -end - -if isempty(cfg.template), - error('you must specify a template anatomical MRI'); -end - -if ~isfield(interp,'anatomy'), - error('no anatomical information available, this is required for normalisation'); -end - -if isfield(cfg, 'coordinates') - source_coordinates = cfg.coordinates; -end - -% the template anatomy should always be stored in a SPM-compatible file -if filetype(cfg.template, 'analyze_hdr') || filetype(cfg.template, 'analyze_img') || filetype(cfg.template, 'minc') - % based on the filetype assume that the coordinates correspond with MNI/SPM convention - template_coordinates = 'spm'; -end - -% the source anatomy can be in a file that is not understood by SPM (e.g. in the -% native CTF *.mri format), therefore start by reading it into memory -if ischar(interp), - fprintf('reading source MRI from file\n'); - filename = interp; - interp = read_mri(filename); - if filetype(filename, 'ctf_mri') - % based on the filetype assume that the coordinates correspond with CTF convention - source_coordinates = 'ctf'; - end -end - -% check if the input data is valid for this function -interp = checkdata(interp, 'datatype', 'volume', 'feedback', 'yes'); - -% select the parameters that should be normalised -cfg.parameter = parameterselection(cfg.parameter, interp); - -% the anatomy should always be normalised as the first volume -sel = strcmp(cfg.parameter, 'anatomy'); -if ~any(sel) - cfg.parameter = {'anatomy' cfg.parameter{:}}; -else - [dum, indx] = sort(sel); - cfg.parameter = cfg.parameter(fliplr(indx)); -end - -% downsample the volume -tmpcfg = []; -tmpcfg.downsample = cfg.downsample; -tmpcfg.parameter = cfg.parameter; -tmpcfg.smooth = cfg.smooth; -interp = volumedownsample(tmpcfg, interp); - -if isempty(source_coordinates) - source_coordinates = determine_coordinates('input'); % use interactive helper-function -end -if isempty(template_coordinates) - template_coordinates = determine_coordinates('template'); % use interactive helper-function -end - -% ensure that the source volume is approximately aligned with the template -if strcmp(source_coordinates, 'ctf') && strcmp(template_coordinates, 'spm') - fprintf('converting input coordinates from CTF into approximate SPM coordinates\n'); - initial = [ - 0.0000 -1.0000 0.0000 0.0000 - 0.9987 0.0000 -0.0517 -32.0000 - 0.0517 0.0000 0.9987 -54.0000 - 0.0000 0.0000 0.0000 1.0000 ]; -elseif strcmp(source_coordinates, template_coordinates) - fprintf('not converting input coordinates\n'); - initial = eye(4); -else - error('cannot determine the approximate alignmenmt of the source coordinates with the template'); -end - -% apply the approximate transformatino prior to passing it to SPM -interp.transform = initial * interp.transform; - -warning off; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% here the normalisation starts -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% create an spm-compatible header for the anatomical volume data -VF = volumewrite_spm([cfg.intermediatename,'_anatomy.img'], interp.anatomy, interp.transform); - -% create an spm-compatible file for each of the functional volumes -for parlop=2:length(cfg.parameter) % skip the anatomy - tmp = cfg.parameter{parlop}; - data = reshape(getsubfield(interp, tmp), interp.dim); - tmp(find(tmp=='.')) = '_'; - volumewrite_spm([cfg.intermediatename,'_' tmp '.img'], data, interp.transform); -end - -% read the template anatomical volume -if strcmp(char(cfg.template(end-2:end)),'mnc'), - VG = spm_vol_minc(cfg.template); -elseif strcmp(char(cfg.template(end-2:end)),'img'), - VG = spm_vol(cfg.template); -else - error('Unknown template'); -end - -fprintf('performing the normalisation\n'); -% do spatial normalisation according to these steps -% step 1: read header information for template and source image -% step 2: compute transformation parameters -% step 3: write the results to a file with prefix 'w' - -if ~isfield(cfg, 'spmparams') && strcmp(cfg.nonlinear, 'yes'), - fprintf('warping the invdividual anatomy to the template anatomy\n'); - % compute the parameters by warping the individual anatomy - VF = spm_vol([cfg.intermediatename,'_anatomy.img']); - params = spm_normalise(VG,VF); -elseif ~isfield(cfg, 'spmparams') && strcmp(cfg.nonlinear, 'no'), - fprintf('warping the invdividual anatomy to the template anatomy, using only linear transformations\n'); - % compute the parameters by warping the individual anatomy - VF = spm_vol([cfg.intermediatename,'_anatomy.img']); - flags.nits = 0; %put number of non-linear iterations to zero - params = spm_normalise(VG,VF,[],[],[],flags); -else - fprintf('using the parameters specified in the configuration\n'); - % use the externally specified parameters - params = cfg.spmparams; -end -flags.vox = [cfg.downsample,cfg.downsample,cfg.downsample]; -files = {}; - -% determine the affine source->template coordinate transformation -final = VG.mat * inv(params.Affine) * inv(VF.mat) * initial; - -% apply the normalisation parameters to each of the volumes -for parlop=1:length(cfg.parameter) - fprintf('creating normalised analyze-file for %s\n', cfg.parameter{parlop}); - tmp = cfg.parameter{parlop}; - tmp(find(tmp=='.')) = '_'; - files{parlop} = sprintf('%s_%s.img', cfg.intermediatename, tmp); - [p, f, x] = fileparts(files{parlop}); - wfiles{parlop} = fullfile(p, ['w' f x]); -end -spm_write_sn(char(files),params,flags); % this creates the 'w' prefixed files - -normalise = []; - -% read the normalised results from the 'w' prefixed files -V = spm_vol(char(wfiles)); -for vlop=1:length(V) - normalise = setsubfield(normalise, cfg.parameter{vlop}, spm_read_vols(V(vlop))); -end - -normalise.transform = V(1).mat; -normalise.dim = size(normalise.anatomy); - -if isfield(normalise, 'inside') - % convert back to a logical volume - normalise.inside = abs(normalise.inside-1)<=10*eps; -end - -% flip and permute the dimensions to align the volume with the headcoordinate axes -normalise = align_ijk2xyz(normalise); - -if strcmp(cfg.write,'yes') - % create an spm-compatible file for each of the normalised volumes - for parlop=1:length(cfg.parameter) % include the anatomy - tmp = cfg.parameter{parlop}; - data = reshape(getsubfield(normalise, tmp), normalise.dim); - tmp(find(tmp=='.')) = '_'; - volumewrite_spm([cfg.name,'_' tmp '.img'], data, normalise.transform); - end -end - -if strcmp(cfg.keepintermediate,'no') - % remove the intermediate files - for flop=1:length(files) - [p, f, x] = fileparts(files{flop}); - delete(fullfile(p, [f, '.*'])); - [p, f, x] = fileparts(wfiles{flop}); - delete(fullfile(p, [f, '.*'])); - end -end - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% remember the normalisation parameters in the configuration -cfg.spmparams = params; -cfg.initial = initial; -cfg.final = final; - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: volumenormalise.m,v 1.21 2009/07/14 07:27:30 roboos Exp $'; -% remember the configuration details of the input data -try, cfg.previous = interp.cfg; end -% remember the exact configuration details in the output -normalise.cfg = cfg; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% HELPER FUNCTION that asks a few questions to determine the coordinate system -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [coordinates] = determine_coordinates(str); -fprintf('Please determine the coordinate system of the %s anatomical volume.\n', str); -% determine in which direction the nose is pointing -nosedir = []; -while isempty(nosedir) - response = input('Is the nose pointing in the positive X- or Y-direction? [x/y] ','s'); - if strcmp(response, 'x'), - nosedir = 'positivex'; - elseif strcmp(response, 'y'), - nosedir = 'positivey'; - end -end -% determine where the origin is -origin = []; -while isempty(origin) - response = input('Is the origin on the Anterior commissure or between the Ears? [a/e] ','s'); - if strcmp(response, 'e'), - origin = 'interauricular'; - elseif strcmp(response, 'a'), - origin = 'ant_comm'; - end -end -% determine the coordinate system of the MRI volume -if strcmp(origin, 'interauricular') && strcmp(nosedir, 'positivex') - coordinates = 'ctf'; -elseif strcmp(origin, 'ant_comm') && strcmp(nosedir, 'positivey') - coordinates = 'spm'; -end diff --git a/external/fieldtrip/private/volumerealign.m b/external/fieldtrip/private/volumerealign.m deleted file mode 100644 index b77bf78..0000000 --- a/external/fieldtrip/private/volumerealign.m +++ /dev/null @@ -1,256 +0,0 @@ -function [mri] = volumerealign(cfg, mri); - -% VOLUMEREALIGN spatially aligns an anatomical MRI with head coordinates based on -% external fiducials. This function does not change the volume -% itself, but adjusts the homogenous transformation matrix that -% describes the coordinate system. -% -% This function only changes the coordinate system of an anatomical -% MRI, it does not change the MRI as such. For spatial normalisation -% (warping) of an MRI to a template brain you should use the -% VOLUMENORMALISE function. -% -% Use as -% [mri] = volumerealign(cfg, mri) -% where mri is an anatomical volume (i.e. MRI) or a functional -% volume (i.e. source recunstruction that has been interpolated on -% an MRI). -% -% The configuration can contain the following options -% cfg.clim = [min max], scaling of the anatomy color (default -% is to adjust to the minimum and maximum) -% cfg.method = different methods for aligning the electrodes -% 'realignfiducial' realign the volume to the fiducials -% 'interactive' manually using graphical user interface -% -% For realigning to the fiducials, you should specify the position of the -% fiducials in voxel indices. -% cfg.fiducial.nas = [i j k], position of nasion -% cfg.fiducial.lpa = [i j k], position of LPA -% cfg.fiducial.rpa = [i j k], position of RPA -% -% By specifying the fiducial coordinates either in the cfg or interactively, the -% anatomical MRI volume is realigned according to the folowing convention: -% - the origin is exactly between LPA and RPA -% - the X-axis goes towards NAS -% - the Y-axis goes approximately towards LPA, orthogonal to X and in the plane spanned by the fiducials -% - the Z-axis goes approximately towards the vertex, orthogonal to X and Y -% -% -% See also READ_MRI, ELECTRODEREALIGN - -% Copyright (C) 2006-2009, Robert Oostenveld -% -% $Log: volumerealign.m,v $ -% Revision 1.12 2009/07/31 13:43:36 jansch -% now really fixed a bug (unlike last time) -% -% Revision 1.11 2009/07/30 14:22:00 jansch -% fixed bug in input arguments for volplot -% -% Revision 1.10 2009/07/29 13:53:49 roboos -% added cfg.clim for color scaling, thanks to Hanneke -% -% Revision 2 2009/07/29 13:00:00 hanvdij -% Added colorscaling option in the volplot function at the end of this -% script. -% -% Revision 1.9 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.8 2008/11/21 13:56:12 sashae -% added call to checkconfig at start and end of function -% -% Revision 1.7 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.6 2007/05/02 15:22:37 roboos -% cfg.parameter should never be a cell -% -% Revision 1.5 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.4 2007/03/30 17:05:40 ingnie -% checkinput; only proceed when input data is allowed datatype -% -% Revision 1.3 2006/10/10 16:21:10 roboos -% fixed bug in default setting for method -% -% Revision 1.2 2006/10/10 13:38:31 roboos -% added some help, thanks to Till -% -% Revision 1.1 2006/10/10 10:25:59 roboos -% new impementation -% - -fieldtripdefs - -cfg = checkconfig(cfg, 'trackconfig', 'on'); - -% check if the input data is valid for this function -mri = checkdata(mri, 'datatype', 'volume', 'feedback', 'yes'); - -% set the defaults -if ~isfield(cfg, 'fiducial'), cfg.fiducial = []; end -if ~isfield(cfg, 'parameter'), cfg.parameter = 'anatomy'; end -if ~isfield(cfg, 'clim'), cfg.clim = []; end - -if ~isfield(cfg, 'method') - if ~isempty(cfg.fiducial) - cfg.method = 'realignfiducial'; - else - cfg.method = 'interactive'; - end -end - -% select the parameter that should be displayed -cfg.parameter = parameterselection(cfg.parameter, mri); -if iscell(cfg.parameter) - cfg.parameter = cfg.parameter{1}; -end - -switch cfg.method - case 'realignfiducial' - % do nothing - case 'interactive' - dat = getsubfield(mri, cfg.parameter); - nas = []; - lpa = []; - rpa = []; - x = 1:mri.dim(1); - y = 1:mri.dim(2); - z = 1:mri.dim(3); - xc = round(mri.dim(1)/2); - yc = round(mri.dim(2)/2); - zc = round(mri.dim(3)/2); - while(1) % break when 'q' is pressed - fprintf('============================================================\n'); - fprintf('click with mouse button to reslice the display to a new position\n'); - fprintf('press n/l/r on keyboard to record the current position as fiducial location\n'); - fprintf('press q on keyboard to quit interactive mode\n'); - xc = round(xc); - yc = round(yc); - zc = round(zc); - volplot(x, y, z, dat, [xc yc zc], cfg.clim); - drawnow; - try, [d1, d2, key] = ginput(1); catch, key='q'; end - if key=='q' - break; - elseif key=='l' - lpa = [xc yc zc]; - elseif key=='r' - rpa = [xc yc zc]; - elseif key=='n' - nas = [xc yc zc]; - else - % update the view to a new position - l1 = get(get(gca, 'xlabel'), 'string'); - l2 = get(get(gca, 'ylabel'), 'string'); - switch l1, - case 'i' - xc = d1; - case 'j' - yc = d1; - case 'k' - zc = d1; - end - switch l2, - case 'i' - xc = d2; - case 'j' - yc = d2; - case 'k' - zc = d2; - end - end - if ~isempty(nas), fprintf('nas = [%f %f %f]\n', nas); else fprintf('nas = undefined\n'); end - if ~isempty(lpa), fprintf('lpa = [%f %f %f]\n', lpa); else fprintf('lpa = undefined\n'); end - if ~isempty(rpa), fprintf('rpa = [%f %f %f]\n', rpa); else fprintf('rpa = undefined\n'); end - end - - cfg.fiducial.nas = nas; - cfg.fiducial.lpa = lpa; - cfg.fiducial.rpa = rpa; - - otherwise - error('unsupported method'); -end - -% compute the homogenous transformation matrix describing the new coordinate system -vox2head = headcoordinates(cfg.fiducial.nas, cfg.fiducial.lpa, cfg.fiducial.rpa); - -if ~isfield(mri, 'transform') - mri.transform = vox2head; -elseif all(all(mri.transform==eye(4))) - mri.transform = vox2head; -else - warning('removing old transformation matrix'); - scale = eye(4); - %FIXME check whether the following is ever necessary - %origvox2head = mri.transform; - %scale(1:3,1:3) = diag(sqrt(sum(origvox2head(1:3,1:3).^2,2))); - mri.transform = scale*vox2head; -end - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i); -end -cfg.version.id = '$Id: volumerealign.m,v 1.12 2009/07/31 13:43:36 jansch Exp $'; - -% remember the configuration -mri.cfg = cfg; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% helper function to show three orthogonal slices -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function volplot(x, y, z, dat, c, cscale); -xi = c(1); -yi = c(2); -zi = c(3); - -% manual color scaling of anatomy data is usefull in case of some pixel noise -if nargin<6 || isempty(cscale) - cmin = min(dat(:)); - cmax = max(dat(:)); -else - cmin = cscale(1); - cmax = cscale(2); -end - -h1 = subplot(2,2,1); -h2 = subplot(2,2,2); -h3 = subplot(2,2,3); - -subplot(h1); -imagesc(x, z, squeeze(dat(:,yi,:))'); set(gca, 'ydir', 'normal') -axis equal; axis tight; -xlabel('i'); ylabel('k'); -caxis([cmin cmax]); -crosshair([x(xi) z(zi)], 'color', 'yellow'); - -subplot(h2); -imagesc(y, z, squeeze(dat(xi,:,:))'); set(gca, 'ydir', 'normal') -axis equal; axis tight; -xlabel('j'); ylabel('k'); -caxis([cmin cmax]); -crosshair([y(yi) z(zi)], 'color', 'yellow'); - -subplot(h3); -imagesc(x, y, squeeze(dat(:,:,zi))'); set(gca, 'ydir', 'normal') -axis equal; axis tight; -xlabel('i'); ylabel('j'); -caxis([cmin cmax]); -crosshair([x(xi) y(yi)], 'color', 'yellow'); - -colormap gray diff --git a/external/fieldtrip/private/volumesegment.m b/external/fieldtrip/private/volumesegment.m deleted file mode 100644 index 406c5a2..0000000 --- a/external/fieldtrip/private/volumesegment.m +++ /dev/null @@ -1,344 +0,0 @@ -function [segment] = volumesegment(cfg, mri) - -% VOLUMESEGMENT segments an anatomical MRI into gray matter, white matter, -% and cerebro-spinal fluid compartments. -% -% This function the SPM2 toolbox, see http://www.fil.ion.ucl.ac.uk/spm/ -% -% Use as -% [segment] = volumesegment(cfg, mri) -% -% The input arguments are a configuration structure (see below) and an -% anatomical MRI structure. Instead of an MRI structure, you can also -% specify a string with a filename of an MRI file. -% -% The configuration options are -% cfg.template = filename of the template anatomical MRI (default is '/home/common/matlab/spm2/templates/T1.mnc') -% cfg.name = string for output filename -% cfg.write = 'no' or 'yes' (default = 'no'), -% writes the segmented volumes to SPM2 compatible analyze-file with the suffix -% _seg1, for the gray matter segmentation -% _seg2, for the white matter segmentation -% _seg3, for the csf segmentation -% cfg.smooth = 'no' or the FWHM of the gaussian kernel in voxels (default = 'no') -% cfg.coordinates = 'spm, 'ctf' or empty for interactive (default = []) -% -% As the first step the coordinate frame of the input MRI has to -% be approximately aligned to the template. For this, a homogeneous -% transformation matrix is used, which makes the assumption that the -% template mri is defined in SPM/MNI-coordinates: -% x-axis pointing to the right ear -% y-axis along the acpc-line -% z-axis pointing to the top of the head -% origin in the anterior commissure. -% Note that the segmentation only works if the template MRI is in SPM -% coordinates. -% -% If the input mri is a string pointing to a CTF *.mri file, the -% x-axis is assumed to point to the nose, and the origin is assumed -% to be on the interauricular line. -% -% If the input mri is a string pointing to another fileformat, or a -% structure containing an anatomical MRI in Matlab memory, the user will -% be asked about the axis-definition and the origin of the coordinate system. -% -% As a second step, the segmentation is performed, using the -% default parameters from SPM. The output volume is in the original -% coordinate-frame. -% -% As a third and optional step, you can perform a smoothing of the segmented -% volumes. - -% undocumented options -% cfg.keepintermediate = 'yes' or 'no' -% cfg.segment = 'yes' or 'no' - -% $Log: volumesegment.m,v $ -% Revision 1.14 2009/07/14 07:27:30 roboos -% replaced read_fcdc_mri with read_mri to avoid warning -% -% Revision 1.13 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.12 2008/11/21 13:56:12 sashae -% added call to checkconfig at start and end of function -% -% Revision 1.11 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.10 2008/09/17 14:53:35 roboos -% removed fixvolume (and underlying grid2transform), not needed any more because checkdata has the possibility of converting a pos to a transform -% -% Revision 1.9 2007/07/31 13:00:05 jansch -% minor change in save-directory for temporary files -% -% Revision 1.8 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.7 2007/03/30 17:05:40 ingnie -% checkinput; only proceed when input data is allowed datatype -% -% Revision 1.6 2006/08/01 10:06:35 marsie -% fixed bug in using spm_smooth -% -% Revision 1.5 2006/07/27 08:28:46 roboos -% use spm_smooth instead of spm_conv, updated documentation -% -% Revision 1.4 2006/03/06 09:31:43 roboos -% changed the default template from /opt to /home/common -% -% Revision 1.3 2006/02/24 16:47:19 roboos -% use fixvolume instead of grid2transform -% -% Revision 1.2 2006/01/30 13:47:31 roboos -% change in whitespace -% -% Revision 1.1 2006/01/05 12:58:20 roboos -% This function (VOLUMExxx) replaces a function with the name xxxVOLUME. -% The fields xgrid/ygrid/zgrid are removed (this is from now on handled by -% grid2transform and the VOLUMExxx function should only work on volumes that -% are described using a transformation matrix). -% Writing of spm/analyze volumes is handled by private/volumewrite_spm. -% -% Revision 1.10 2005/06/29 12:46:29 roboos -% the following changes were done on a large number of files at the same time, not all of them may apply to this specific file -% - added try-catch around the inclusion of input data configuration -% - moved cfg.version, cfg.previous and the assignment of the output cfg to the end -% - changed help comments around the configuration handling -% - some changes in whitespace -% -% Revision 1.9 2005/05/17 17:50:38 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.8 2005/04/25 16:06:23 roboos -% added the documentation for cfg.smooth and cfg.coordinates to the help -% fixed small bugsmooth due to which it would never smooth -% -% Revision 1.7 2005/03/03 10:48:16 roboos -% Cleaned up the function in total. It now uses a different (hopefully -% more robust) initial pre-alignment of the input volume with the SPM -% template. Also the type-detection (i.e. either SPM or CTF) of the input -% volume has been changed. -% -% Revision 1.6 2004/10/14 07:01:33 jansch -% included preprocessing of input-mri, to get an approximate aligmnent with -% the spm-templates used, prior to the segmentation. -% -% Revision 1.5 2004/10/13 20:28:44 jansch -% added the computation of a transformation-matrix, in order to align the -% to-be-segmented volume with the template and the segmentation-masks -% -% Revision 1.4 2004/09/22 10:46:31 roboos -% ensure that the coordinate transformation is from 1:N to headcoordinates -% -% Revision 1.3 2004/09/20 13:29:42 roboos -% fixed some small bugs, changed layout of help and comments -% -% Revision 1.2 2004/09/17 13:47:02 jansch -% inserted some changes suggested by robert -% -% Revision 1.1 2004/09/17 11:23:59 jansch -% first implementation -% - -fieldtripdefs - -cfg = checkconfig(cfg, 'trackconfig', 'on'); - -%% checkdata see below!!! %% - -% check if spm2 is in your path: -hasspm = (exist('spm_vol') & exist('spm_write_vol') & exist('spm_segment')); -if ~hasspm - error('the SPM2 toolbox is not installed, see: http://www.fil.ion.ucl.ac.uk/spm/'); -end - -% set the defaults -if ~isfield(cfg,'segment'), cfg.segment = 'yes'; end; -if ~isfield(cfg,'smooth'), cfg.smooth = 'no'; end; -if ~isfield(cfg,'template'), cfg.template = '/home/common/matlab/spm2/templates/T1.mnc'; end; -if ~isfield(cfg,'write'), cfg.write = 'no'; end; -if ~isfield(cfg,'keepintermediate'),cfg.keepintermediate = 'no'; end; -if ~isfield(cfg,'coordinates'), cfg.coordinates = []; end; - -if ~isfield(cfg,'name') - if ~strcmp(cfg.write,'yes') - tmp = tempname; - %[path,file] = fileparts(tmp); - %cfg.name = file; - cfg.name = tmp; - else - error('you must specify the output filename in cfg.name'); - end -end - -if ischar(mri), - % read the anatomical MRI data from file - filename = mri; - fprintf('reading MRI from file\n'); - mri = read_mri(filename); - if filetype(filename, 'ctf_mri') && isempty(cfg.coordinates) - % based on the filetype assume that the coordinates correspond with CTF convention - cfg.coordinates = 'ctf'; - end -end - -% check if the input data is valid for this function -mri = checkdata(mri, 'datatype', 'volume', 'feedback', 'yes'); - -% remember the original transformation matrix -original.transform = mri.transform; -original.nosedir = []; -original.origin = []; - -if isempty(cfg.coordinates) - % determine in which direction the nose is pointing - while isempty(original.nosedir) - response = input('Is the nose pointing in the positive X- or Y-direction? [x/y] ','s'); - if strcmp(response, 'x'), - original.nosedir = 'positivex'; - elseif strcmp(response, 'y'), - original.nosedir = 'positivey'; - end - end - - % determine where the origin is - while isempty(original.origin) - response = input('Is the origin on the Anterior commissure or between the Ears? [a/e] ','s'); - if strcmp(response, 'e'), - original.origin = 'interauricular'; - elseif strcmp(response, 'a'), - original.origin = 'ant_comm'; - end - end - - % determine the coordinatesystem of the input MRI volume - if strcmp(original.origin, 'interauricular') && strcmp(original.nosedir, 'positivex') - cfg.coordinates = 'ctf'; - elseif strcmp(original.origin, 'ant_comm') && strcmp(original.nosedir, 'positivey') - cfg.coordinates = 'spm'; - end -end - -% ensure that the input MRI volume is approximately aligned with the SPM template -if strcmp(cfg.coordinates, 'ctf') - fprintf('assuming CTF coordinates for input, i.e. positive X-axis towards nasion and Y-axis through ears\n'); - % flip, rotate and translate the CTF mri so that it approximately corresponds with SPM coordinates - % this only involves a manipulation of the coordinate tarnsformation matrix - mri = align_ctf2spm(mri); - % also flip and permute the 3D volume itself, so that the voxel and headcoordinates approximately correspond - % this seems to improve the convergence of the segmentation algorithm - mri = align_ijk2xyz(mri); -elseif strcmp(cfg.coordinates, 'spm') - fprintf('assuming that the input MRI is already approximately alligned with SPM coordinates\n'); - % nothing needs to be done -else - error('cannot determine the (approximate) alignmenmt of the input MRI with the SPM template'); -end - -if strcmp(cfg.segment, 'yes') - % convert and write the volume to an analyze format, so that it can be handled by spm - Va = volumewrite_spm([cfg.name,'.img'], mri.anatomy, mri.transform); - - % spm is quite noisy, prevent the warnings from displaying on screen - % warning off; - - % set the spm segmentation defaults (from /opt/spm2/spm_defaults.m script) - defaults.segment.estimate.priors = str2mat(... - fullfile(spm('Dir'),'apriori','gray.mnc'),... - fullfile(spm('Dir'),'apriori','white.mnc'),... - fullfile(spm('Dir'),'apriori','csf.mnc')); - defaults.segment.estimate.reg = 0.01; - defaults.segment.estimate.cutoff = 30; - defaults.segment.estimate.samp = 3; - defaults.segment.estimate.bb = [[-88 88]' [-122 86]' [-60 95]']; - defaults.segment.estimate.affreg.smosrc = 8; - defaults.segment.estimate.affreg.regtype = 'mni'; - %defaults.segment.estimate.affreg.weight = fullfile(spm('Dir'),'apriori','brainmask.mnc'); - defaults.segment.estimate.affreg.weight = ''; - defaults.segment.write.cleanup = 1; - defaults.segment.write.wrt_cor = 1; - flags = defaults.segment; - - % perform the segmentation - fprintf('performing the segmentation on the specified volume\n'); - spm_segment(Va,cfg.template,flags); - Vtmp = spm_vol({[cfg.name,'_seg1.img'];... - [cfg.name,'_seg2.img'];... - [cfg.name,'_seg3.img']}); - - % read the resulting volumes - for j = 1:3 - vol = spm_read_vols(Vtmp{j}); - Vtmp{j}.dat = vol; - V(j) = struct(Vtmp{j}); - end - - % keep or remove the files according to the configuration - if strcmp(cfg.keepintermediate,'no'), - delete([cfg.name,'.img']); - delete([cfg.name,'.hdr']); - delete([cfg.name,'.mat']); - end - if strcmp(cfg.write,'no'), - delete([cfg.name,'_seg1.hdr']); - delete([cfg.name,'_seg2.hdr']); - delete([cfg.name,'_seg3.hdr']); - delete([cfg.name,'_seg1.img']); - delete([cfg.name,'_seg2.img']); - delete([cfg.name,'_seg3.img']); - delete([cfg.name,'_seg1.mat']); - delete([cfg.name,'_seg2.mat']); - delete([cfg.name,'_seg3.mat']); - elseif strcmp(cfg.write,'yes'), - for j = 1:3 - % put the original transformation-matrix in the headers - V(j).mat = original.transform; - % write the updated header information back to file ??????? - V(j) = spm_create_vol(V(j)); - end - end - -else - % the volume is already segmented, put it in an SPM structure - V = mri; - V.dat = V.anatomy; - V.mat = V.transform; - V = rmfield(V,'anatomy'); -end - -if ~strcmp(cfg.smooth, 'no'), - fprintf('smoothing with a %d-pixel FWHM kernel\n',cfg.smooth); - spm_smooth(V(1).dat, V(1).dat, cfg.smooth); % smooth the gray matter - if length(V)>1, spm_smooth(V(2).dat, V(2).dat, cfg.smooth); end % smooth the white matter - if length(V)>2, spm_smooth(V(3).dat, V(3).dat, cfg.smooth); end % smooth the csf -end - -% collect the results -segment.dim = size(V(1).dat); -segment.transform = original.transform; % use the original transformation-matrix -segment.gray = V(1).dat; -if length(V)>1, segment.white = V(2).dat; end -if length(V)>2, segment.csf = V(3).dat; end - -% get the output cfg -cfg = checkconfig(cfg, 'trackconfig', 'off', 'checksize', 'yes'); - -% add version information to the configuration -try - % get the full name of the function - cfg.version.name = mfilename('fullpath'); -catch - % required for compatibility with Matlab versions prior to release 13 (6.5) - [st, i] = dbstack; - cfg.version.name = st(i).name; -end -cfg.version.id = '$Id: volumesegment.m,v 1.14 2009/07/14 07:27:30 roboos Exp $'; -% remember the configuration details of the input data -try, cfg.previous = mri.cfg; end -% remember the exact configuration details in the output -segment.cfg = cfg; - diff --git a/external/fieldtrip/private/volumewrite.m b/external/fieldtrip/private/volumewrite.m deleted file mode 100644 index 580a5f8..0000000 --- a/external/fieldtrip/private/volumewrite.m +++ /dev/null @@ -1,459 +0,0 @@ -function volumewrite(cfg, volume) - -% VOLUMEWRITE exports anatomical or functional volume data to a Analyze -% or BrainVoyager file. The data in the resulting file(s) can be -% further analyzed and/or visualized in MRIcro, SPM, BrainVoyager, -% AFNI or similar packages. -% -% Use as -% volumewrite(cfg, volume) -% -% The volume structure should contain a source reconstruction that originates -% from SOURCANALYSIS, a statistical parameter from SOURCESTATISTICS or an -% interpolated and re-aligned anatomical MRI source reconstruction -% from SOURCEINTERPOLATE. -% -% The configuration structure should contain the following elements -% cfg.parameter = string, describing the functional data to be processed, e.g. 'pow', 'coh' or 'nai' -% cfg.filename = filename without the extension -% cfg.filetype = 'analyze', 'spm', 'vmp' or 'vmr' -% cfg.vmpversion = 1 or 2 (default) version of the vmp-format to use -% cfg.coordinates = 'spm, 'ctf' or empty for interactive (default = []) -% -% The default fileformat is 'spm', which means that a *.hdr and *.img file -% will be written using the SPM2 toolbox. The SPM format supports a -% homogenous transformation matrix, the other file formats do not support a -% homogenous coordinate transformation matrix and hence will be written in -% their native coordinate system. -% -% You can specify the datatype for the spm and analyze formats using -% cfg.datatype = 'bit1', 'uint8', 'int16', 'int32', 'float' or 'double' -% -% By default, integer datatypes will be scaled to the maximum value of the -% physical or statistical parameter, floating point datatypes will not be -% scaled. This can be modified with -% cfg.scaling = 'yes' or 'no' -% -% Optional configuration items are -% cfg.downsample = integer number (default = 1, i.e. no downsampling) -% cfg.fiducial.nas = [x y z] position of nasion -% cfg.fiducial.lpa = [x y z] position of LPA -% cfg.fiducial.rpa = [x y z] position of RPA -% cfg.markfiducial = 'yes' or 'no', mark the fiducials -% cfg.markorigin = 'yes' or 'no', mark the origin -% cfg.markcorner = 'yes' or 'no', mark the first corner of the volume -% -% See also SOURCEANALYSIS, SOURCESTATISTICS, SOURCEINTERPOLATE - -% Undocumented local options: -% cfg.parameter - -% Copyright (C) 2003-2006, Robert Oostenveld, Markus Siegel -% -% $Log: volumewrite.m,v $ -% Revision 1.15 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.14 2008/09/17 14:53:35 roboos -% removed fixvolume (and underlying grid2transform), not needed any more because checkdata has the possibility of converting a pos to a transform -% -% Revision 1.13 2007/04/03 15:37:07 roboos -% renamed the checkinput function to checkdata -% -% Revision 1.12 2007/03/30 17:05:40 ingnie -% checkinput; only proceed when input data is allowed datatype -% -% Revision 1.11 2006/08/02 17:14:08 marsie -% fixed bug in dimension alignment when exporting vmp/vmr from spm-coordinates -% -% Revision 1.10 2006/08/02 15:28:46 marsie -% corrected max scaling for .vmr output -% -% Revision 1.9 2006/07/27 08:29:09 roboos -% updated documentation -% -% Revision 1.8 2006/07/13 08:48:46 ingnie -% fixed typo's in documentation -% -% Revision 1.7 2006/04/20 09:58:34 roboos -% updated documentation -% -% Revision 1.6 2006/03/07 08:02:33 roboos -% changed incorrectly named variable functional into volume -% -% Revision 1.5 2006/02/24 16:50:18 roboos -% switched from grid2transform to fixvolume, not neccessary to reshape any more -% -% Revision 1.4 2006/01/30 14:19:33 jansch -% added a fclose in the case of brainvoyager data -% -% Revision 1.3 2006/01/30 13:48:04 roboos -% switched order of parameterselection() and grid2transform() for consistency with other functions -% -% Revision 1.2 2006/01/24 14:20:35 roboos -% removed the obsolete option cfg.voxelcoord, new behaviour is that it is always 'yes' -% -% Revision 1.1 2006/01/05 12:58:20 roboos -% This function (VOLUMExxx) replaces a function with the name xxxVOLUME. -% The fields xgrid/ygrid/zgrid are removed (this is from now on handled by -% grid2transform and the VOLUMExxx function should only work on volumes that -% are described using a transformation matrix). -% Writing of spm/analyze volumes is handled by private/volumewrite_spm. -% -% Revision 1.8 2005/08/19 16:56:45 roboos -% add xgrid/ygrid/zgrid to the volume if not present -% swithched the selection of the functional volume to use the new subfunction parameterselection() -% -% Revision 1.7 2005/05/17 17:50:39 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.6 2005/05/04 07:33:37 roboos -% made chaling optional for int datatypes, added cfg.scaling option -% -% Revision 1.5 2004/10/14 09:33:11 roboos -% added nai, prob and mask as parameters -% improved documentation -% -% Revision 1.4 2003/12/18 22:21:35 roberto -% added "See also" line to the online help -% -% Revision 1.3 2003/12/08 12:33:47 roberto -% only layout changes in code -% -% Revision 1.2 2003/10/28 15:12:04 roberto -% fixed bug: switch...otherwise (instead of switch...default) -% -% Revision 1.1 2003/07/23 09:11:15 roberto -% fixed bug in integer scaling -% - -fieldtripdefs - -%% checkdata see below!!! %% - -% check some of the cfg fields -if ~isfield(cfg, 'filename'), error('No output filename specified'); end -if ~isfield(cfg, 'parameter'), error('No parameter specified'); end -if isempty(cfg.filename), error('Empty output filename'); end - -% set the defaults -if ~isfield(cfg, 'filetype'), cfg.filetype = 'spm'; end -if ~isfield(cfg, 'datatype') cfg.datatype = 'int16'; end -if ~isfield(cfg, 'downsample'), cfg.downsample = 1; end -if ~isfield(cfg, 'markorigin') cfg.markorigin = 'no'; end -if ~isfield(cfg, 'markfiducial') cfg.markfiducial = 'no'; end -if ~isfield(cfg, 'markcorner') cfg.markcorner = 'no'; end - -if ~isfield(cfg, 'scaling'), - if any(strmatch(cfg.datatype, {'int8', 'int16', 'int32'})) - cfg.scaling = 'yes'; - else - cfg.scaling = 'no'; - end -end - -if ~isfield(cfg, 'coordinates') - fprintf('assuming CTF coordinates\n'); - cfg.coordinates = 'ctf'; -end - -if ~isfield(cfg, 'vmpversion') & strcmp(cfg.filetype, 'vmp'); - fprintf('using BrainVoyager version 2 VMP format\n'); - cfg.vmpversion = 2; -end - -% check if the input data is valid for this function -volume = checkdata(volume, 'datatype', 'volume', 'feedback', 'yes'); - -% select the parameter that should be written -cfg.parameter = parameterselection(cfg.parameter, volume); -% only a single parameter should be selected -try, cfg.parameter = cfg.parameter{1}; end - -% downsample the volume -tmpcfg = []; -tmpcfg.downsample = cfg.downsample; -tmpcfg.parameter = cfg.parameter; -volume = volumedownsample(tmpcfg, volume); - -% copy the data and convert into double values so that it can be scaled later -transform = volume.transform; -data = double(getsubfield(volume, cfg.parameter)); -maxval = max(data(:)); -% ensure that the original volume is not used any more -clear volume - -if strcmp(cfg.markfiducial, 'yes') - % FIXME determine the voxel index of the fiducials - nas = cfg.fiducial.nas; - lpa = cfg.fiducial.lpa; - rpa = cfg.fiducial.rpa; - if any(nasmaxxyz) - warning('nasion does not ly within volume, using nearest voxel'); - end - if any(lpamaxxyz) - warning('LPA does not ly within volume, using nearest voxel'); - end - if any(rpamaxxyz) - warning('RPA does not ly within volume, using nearest voxel'); - end - idx_nas = [nearest(x, nas(1)) nearest(y, nas(2)) nearest(z, nas(3))]; - idx_lpa = [nearest(x, lpa(1)) nearest(y, lpa(2)) nearest(z, lpa(3))]; - idx_rpa = [nearest(x, rpa(1)) nearest(y, rpa(2)) nearest(z, rpa(3))]; - fprintf('NAS corresponds to voxel [%d, %d, %d]\n', idx_nas); - fprintf('LPA corresponds to voxel [%d, %d, %d]\n', idx_lpa); - fprintf('RPA corresponds to voxel [%d, %d, %d]\n', idx_rpa); - % set the voxel of the fiducials to the maximum value - data(idx_nas(1), idx_nas(2), idx_nas(3)) = maxval; - data(idx_lpa(1), idx_lpa(2), idx_lpa(3)) = maxval; - data(idx_rpa(1), idx_rpa(2), idx_rpa(3)) = maxval; -end - -if strcmp(cfg.markorigin, 'yes') - % FIXME determine the voxel index of the coordinate system origin - ori = [0 0 0]; - if any(orimaxxyz) - warning('origin does not ly within volume, using nearest voxel'); - end - idx_ori = [nearest(x, ori(1)) nearest(y, ori(2)) nearest(z, ori(3))]; - fprintf('origin corresponds to voxel [%d, %d, %d]\n', idx_ori); - % set the voxel of the origin to the maximum value - data(idx_ori(1), idx_ori(2), idx_ori(3)) = maxval; -end - -if strcmp(cfg.markcorner, 'yes') - % set the voxel of the first corner to the maximum value - data(1:2, 1:1, 1:1) = maxval; % length 2 along x-axis - data(1:1, 1:3, 1:1) = maxval; % length 3 along y-axis - data(1:1, 1:1, 1:4) = maxval; % length 4 along z-axis -end - -% set not-a-number voxels to zero -data(isnan(data)) = 0; - -if strcmp(cfg.scaling, 'yes') - % scale the data so that it fits in the desired numerical data format - switch lower(cfg.datatype) - case 'bit1' - data = (data~=0); - case 'uint8' - data = uint8((2^8-1) * data./maxval); - case 'int16' - data = int16((2^15-1) * data./maxval); - case 'int32' - data = int32((2^31-1) * data./maxval); - case 'float' - data = float(data ./ maxval); - case 'double' - data = double(data ./ maxval); - otherwise - error('unknown datatype'); - end -end - -% The coordinate system employed by the ANALYZE programs is left-handed, -% with the coordinate origin in the lower left corner. Thus, with the -% subject lying supine, the coordinate origin is on the right side of -% the body (x), at the back (y), and at the feet (z). - -% Analyze x = right-left -% Analyze y = post-ant -% Analyze z = inf-sup - -% SPM/MNI x = left-right -% SPM/MNI y = post-ant -% SPM/MNI z = inf-sup - -% CTF x = post-ant -% CTF y = right-left -% CTF z = inf-sup - -% The BrainVoyager and Analyze format do not support the specification of -% the coordinate system using a homogenous transformation axis, therefore -% the dimensions of the complete volume has to be reordered by flipping and -% permuting to correspond with their native coordinate system. -switch cfg.filetype - case {'vmp', 'vmr'} - % the reordering for BrainVoyager has been figured out by Markus Siegel - if strcmp(cfg.coordinates, 'ctf') - data = permute(data, [2 3 1]); - elseif strcmp(cfg.coordinates, 'spm') - data = permute(data, [2 3 1]); - data = flipdim(data, 1); - data = flipdim(data, 2); - end - siz = size(data); - case {'analyze'} - % the reordering of the Analyze format is according to documentation from Darren Webber - if strcmp(cfg.coordinates, 'ctf') - data = permute(data, [2 1 3]); - elseif strcmp(cfg.coordinates, 'spm') - data = flipdim(data, 1); - end - siz = size(data); - case 'spm' - % this format supports a homogenous transformation matrix - % nothing needs to be changed - otherwise - fprintf('unknown fileformat\n'); -end - -% write the volume data to file -switch cfg.filetype - case 'vmp' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % write in BrainVoyager VMP format - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - fid = fopen(sprintf('%s.vmp', cfg.filename),'w'); - if fid < 0, - error('Cannot write to file %s.vmp\n',cfg.filename); - end - - switch cfg.vmpversion - case 1 - % write the header - fwrite(fid, 1, 'short'); % version - fwrite(fid, 1, 'short'); % number of maps - fwrite(fid, 1, 'short'); % map type - fwrite(fid, 0, 'short'); % lag - - fwrite(fid, 0, 'short'); % cluster size - fwrite(fid, 1, 'float'); % thresh min - fwrite(fid, maxval, 'float'); % thresh max - fwrite(fid, 0, 'short'); % df1 - fwrite(fid, 0, 'short'); % df2 - fwrite(fid, 0, 'char'); % name - - fwrite(fid, siz, 'short'); % size - fwrite(fid, 0, 'short'); - fwrite(fid, siz(1)-1, 'short'); - fwrite(fid, 0, 'short'); - fwrite(fid, siz(2)-1, 'short'); - fwrite(fid, 0, 'short'); - fwrite(fid, siz(3)-1, 'short'); - fwrite(fid, 1, 'short'); % resolution - - % write the data - fwrite(fid, data, 'float'); - case 2 - % determine relevant subvolume - % FIXME, this is not functional at the moment, since earlier in this function all nans have been replaced by zeros - minx = min(find(~isnan(max(max(data,[],3),[],2)))); - maxx = max(find(~isnan(max(max(data,[],3),[],2)))); - miny = min(find(~isnan(max(max(data,[],3),[],1)))); - maxy = max(find(~isnan(max(max(data,[],3),[],1)))); - minz = min(find(~isnan(max(max(data,[],1),[],2)))); - maxz = max(find(~isnan(max(max(data,[],1),[],2)))); - - % write the header - fwrite(fid, 2, 'short'); % version - fwrite(fid, 1, 'int'); % number of maps - fwrite(fid, 1, 'int'); % map type - fwrite(fid, 0, 'int'); % lag - - fwrite(fid, 0, 'int'); % cluster size - fwrite(fid, 0, 'char'); % cluster enable - fwrite(fid, 1, 'float'); % thresh - fwrite(fid, maxval, 'float'); % thresh - fwrite(fid, 0, 'int'); % df1 - fwrite(fid, 0, 'int'); % df2 - fwrite(fid, 0, 'int'); % bonf - fwrite(fid, [255,0,0], 'uchar'); % col1 - fwrite(fid, [255,255,0], 'uchar'); % col2 - fwrite(fid, 1, 'char'); % enable SMP - fwrite(fid, 1, 'float'); % transparency - fwrite(fid, 0, 'char'); % name - - fwrite(fid, siz, 'int'); % original size - fwrite(fid, minx-1, 'int'); - fwrite(fid, maxx-1, 'int'); - fwrite(fid, miny-1, 'int'); - fwrite(fid, maxy-1, 'int'); - fwrite(fid, minz-1, 'int'); - fwrite(fid, maxz-1, 'int'); - fwrite(fid, 1, 'int'); % resolution - - % write the data - fwrite(fid, data(minx:maxx,miny:maxy,minz:maxz), 'float'); - end - - case 'vmr' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % write in BrainVoyager VMR format - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - fid = fopen(sprintf('%s.vmr',cfg.filename),'w'); - if fid < 0, - error('Cannot write to file %s.vmr\n',cfg.filename); - end - - % data should be scaled between 0 and 225 - data = data - min(data(:)); - data = round(225*data./max(data(:))); - - % write the header - fwrite(fid, siz, 'ushort'); - % write the data - fwrite(fid, data, 'uint8'); - fclose(fid); - case 'analyze' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % write in Analyze format, using some functions from Darren Webbers toolbox - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - avw = avw_hdr_make; - - % specify the image data and dimensions - avw.hdr.dime.dim(2:4) = siz; - avw.img = data; - - % orientation 0 means transverse unflipped (axial, radiological) - % X direction first, progressing from patient right to left, - % Y direction second, progressing from patient posterior to anterior, - % Z direction third, progressing from patient inferior to superior. - avw.hdr.hist.orient = 0; - - % specify voxel size - avw.hdr.dime.pixdim(2:4) = [1 1 1]; - % FIXME, this currently does not work due to all flipping and permuting - % resx = x(2)-x(1); - % resy = y(2)-y(1); - % resz = z(2)-z(1); - % avw.hdr.dime.pixdim(2:4) = [resy resx resz]; - - % specify the data type - switch lower(cfg.datatype) - case 'bit1' - avw.hdr.dime.datatype = 1; - avw.hdr.dime.bitpix = 1; - case 'uint8' - avw.hdr.dime.datatype = 2; - avw.hdr.dime.bitpix = 8; - case 'int16' - avw.hdr.dime.datatype = 4; - avw.hdr.dime.bitpix = 16; - case 'int32' - avw.hdr.dime.datatype = 8; - avw.hdr.dime.bitpix = 32; - case 'float' - avw.hdr.dime.datatype = 16; - avw.hdr.dime.bitpix = 32; - case 'double' - avw.hdr.dime.datatype = 64; - avw.hdr.dime.bitpix = 64; - otherwise - error('unknown datatype'); - end - - % write the header and image data - avw_img_write(avw, cfg.filename, [], 'ieee-le'); - - case 'spm' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % write in SPM format, using functions from the SPM2 toolbox - % this format supports a homogenous transformation matrix - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - volumewrite_spm(cfg.filename, data, transform); - - otherwise - fprintf('unknown fileformat\n'); -end diff --git a/external/fieldtrip/private/volumewrite_spm.m b/external/fieldtrip/private/volumewrite_spm.m index 39e0af2..3f83aac 100644 --- a/external/fieldtrip/private/volumewrite_spm.m +++ b/external/fieldtrip/private/volumewrite_spm.m @@ -1,4 +1,4 @@ -function [Va] = volumewrite_spm(filename, data, transform) +function [Va] = volumewrite_spm(filename, data, transform, spmversion) % VOLUMEWRITE_SPM write a anatomical or functional volume to img/hdr file % using the SPM toolbox @@ -8,23 +8,14 @@ % Copyright (C) 2006, Robert Oostenveld % -% $Log: volumewrite_spm.m,v $ -% Revision 1.4 2006/06/07 09:34:19 roboos -% changed checktoolbox into hastoolbox -% -% Revision 1.3 2006/05/08 10:05:50 roboos -% fixed writing of volumes of an unsupported datatype by converting them to double -% -% Revision 1.2 2006/05/03 15:08:12 jansch -% temporary fix in the case of logical input; spm does not know how to handle this -% -% Revision 1.1 2006/01/05 13:43:02 roboos -% New function, is used by all functions that write to hdr/img file -% using SPM (volumenormalise, volumesegment and volumewrite). -% +% Subversion does not use the Log keyword, use 'svn log ' or 'svn -v log | less' to get detailled information -% check whether the required SPM2 toolbox is available -hastoolbox('SPM2', 1); +if nargin<4, + spmversion = 'SPM2'; +end + +% check whether the required SPM toolbox is available +hastoolbox(upper(spmversion), 1); if 0 % not all datatypes are supported by SPM, this can be checked with @@ -44,20 +35,34 @@ spm_type('uint64') % -- 64-bit unsigned integer array end -if isnan(spm_type(class(data))) +typ = spm_type(class(data)); +dim = size(data); +if isnan(typ) % convert every unsupported data type into double - data = double(data); + data = double(data); end -typ = spm_type(class(data)); -dim = size(data); -Va = []; -Va.mat = transform; -Va.fname = filename; -Va.dim = [dim typ]; -Va.n = 1; -Va.pinfo = [1 0 0]'; -Va.private.hdr.dime.datatype = typ; +switch lower(spmversion) +case {'spm2'} + %see spm_vol + Va = []; + Va.mat = transform; + Va.fname = filename; + Va.dim = [dim typ]; + Va.n = 1; + Va.pinfo = [1 0 0]'; + Va.private.hdr.dime.datatype = typ; +case {'spm8'} + Va = []; + Va.mat = transform; + Va.fname = filename; + Va.dim = dim; + Va.n = 1; + Va.pinfo = [1 0 0]'; + %Va.dt = [typ 1]; % this is not necessary because assigned in spm_create_vol +otherwise + error('unsupported version of spm requested'); +end Va = spm_create_vol(Va); Va = spm_write_vol(Va,data); diff --git a/external/fieldtrip/private/warp_apply.m b/external/fieldtrip/private/warp_apply.m index f7a8af7..290a991 100644 --- a/external/fieldtrip/private/warp_apply.m +++ b/external/fieldtrip/private/warp_apply.m @@ -38,44 +38,23 @@ % Copyright (C) 2000-2005, Robert Oostenveld % -% This program is free software; you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation; either version 2 of the License, or -% (at your option) any later version. +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% You should have received a copy of the GNU General Public License -% along with this program; if not, write to the Free Software -% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -% $Log: warp_apply.m,v $ -% Revision 1.3 2009/04/16 12:58:37 roboos -% allow for 2D input points, the output will also be 2D but the computations are done in 3D -% allow for 2D homogenous transformation matrix -% -% Revision 1.2 2006/09/13 09:47:41 roboos -% auto-detect homogeneous transformation if method not given -% -% Revision 1.1 2005/08/15 08:10:07 roboos -% renamed warp3d into warp_apply -% -% Revision 1.5 2005/03/21 15:35:38 roboos -% added support for nonlin0 up to nonlin5 as method-string (equivalent to nonlinear) -% extended help, added some comments and error checks -% -% Revision 1.4 2004/05/19 09:57:07 roberto -% added GPL copyright statement, added CVS log item -% -% Revision 1.3 2004/05/19 09:48:01 roberto -% *** empty log message *** +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.2 2003/03/12 16:07:18 roberto -% improved help documentation +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: warp_apply.m 945 2010-04-21 17:41:20Z roboos $ if nargin<3 && all(size(M)==4) % no specific transformation mode has been selected diff --git a/external/fieldtrip/private/warp_error.m b/external/fieldtrip/private/warp_error.m index 7dd9099..1f36fc7 100644 --- a/external/fieldtrip/private/warp_error.m +++ b/external/fieldtrip/private/warp_error.m @@ -26,23 +26,23 @@ % along with this program; if not, write to the Free Software % Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -% $Log: warp_error.m,v $ -% Revision 1.4 2006/09/12 15:20:02 roboos -% added support for warping the input points to a triangulated surface +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.3 2006/04/13 10:50:34 roboos -% renamed calls to warp3d into warp_apply +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.2 2006/04/13 10:46:09 roboos -% updated the documentation +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.1 2005/08/15 08:11:20 roboos -% Renamed warpfun into warp_error, which is a better description of -% its use. This is a companion function for warp_optim. -% -% Revision 1.2 2004/05/19 09:57:08 roberto -% added GPL copyright statement, added CVS log item +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: warp_error.m 952 2010-04-21 18:29:51Z roboos $ if ~isempty(M) % apply the warp to the input positions diff --git a/external/fieldtrip/private/warp_optim.m b/external/fieldtrip/private/warp_optim.m index 7020110..2b796e0 100644 --- a/external/fieldtrip/private/warp_optim.m +++ b/external/fieldtrip/private/warp_optim.m @@ -33,40 +33,23 @@ % along with this program; if not, write to the Free Software % Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -% $Log: warp_optim.m,v $ -% Revision 1.8 2009/04/16 12:55:15 roboos -% small change in handling of the optimizer function +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.7 2006/11/23 11:34:51 roboos -% use optimization toolbox if possible, othewise use the standard fminsearch function +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.6 2006/09/13 09:55:58 roboos -% fixed bug (typo) in rigidbody +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.5 2006/04/13 12:55:45 roboos -% added a str2func to solve a problem with feval and private -% -% Revision 1.4 2006/04/13 10:50:34 roboos -% renamed calls to warp3d into warp_apply -% -% Revision 1.3 2006/04/13 10:47:39 roboos -% renamed all calls to warpfun into warp_error -% -% Revision 1.2 2006/04/13 10:38:24 roboos -% fixed a problem due to find/strmatch -% -% Revision 1.1 2005/08/15 08:12:40 roboos -% Renamed warp_pnt into warp_optim for consistency with other functions. -% Also changed the code, the subsequent ordering of the simple to -% more complex warps is handled more clean. -% -% Revision 1.4 2005/03/21 15:43:42 roboos -% fixed bug in output for nonlinear warping -% added support for rigidbody or globalrescale warp -% -% Revision 1.3 2004/05/19 09:57:08 roberto -% added GPL copyright statement, added CVS log item +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: warp_optim.m 952 2010-04-21 18:29:51Z roboos $ global fb; @@ -153,7 +136,7 @@ % do a first order nonlinear transformation, if fb; disp('1st order nonlinear...'); end e1i = traditional(tf); - e1i = [e1i(1:3,4) e1i(1:3,1:3)]; % reshuffle from homogenous into nonlinear + e1i = [e1i(1:3,4) e1i(1:3,1:3)]; % reshuffle from homogenous into nonlinear e1f = optimfun(warp_error, e1i, options, pos1, pos2); if fb; fprintf('distance = %f\n', warp_error(e1f, pos1, pos2, 'nonlinear')); end end diff --git a/external/fieldtrip/private/wizard_base.m b/external/fieldtrip/private/wizard_base.m new file mode 100644 index 0000000..0188254 --- /dev/null +++ b/external/fieldtrip/private/wizard_base.m @@ -0,0 +1,358 @@ +function h = wizard_gui(filename) + +% This is the low level wizard function. It evaluates the matlab content +% in the workspace of the calling function. To prevent overwriting +% variables in the BASE workspace, this function should be called from a +% wrapper function. The wrapper function whoudl pause execution untill the +% wizard figure is deleted. + +% Copyright (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: wizard_base.m 952 2010-04-21 18:29:51Z roboos $ + +% create a new figure +h = figure('Name','Wizard',... + 'NumberTitle','off',... + 'MenuBar','none',... + 'KeyPressFcn', @cb_keyboard,... + 'resizeFcn', @cb_resize,... + 'closeRequestFcn', @cb_cancel); +% movegui(h,'center'); +% set(h, 'ToolBar', 'figure'); + +if nargin>0 + filename = which(filename); + [p, f, x] = fileparts(filename); + data = []; + data.path = p; + data.file = f; + data.ext = x; + data.current = 0; + data.script = script_parse(filename); + guidata(h, data); % attach the data to the GUI figure +else + data = []; + data.path = []; + data.file = []; + data.ext = []; + data.current = 0; + data.script = script_parse([]); + guidata(h, data); % attach the data to the GUI figure + cb_load(h); +end +cb_show(h); % show the GUI figure +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function cb_keyboard(h, eventdata) +h = parentfig(h); +dbstack +if isequal(eventdata.Key, 'o') && isequal(eventdata.Modifier, {'control'}) + cb_load(h); +elseif isequal(eventdata.Key, 's') && isequal(eventdata.Modifier, {'control'}) + cb_save(h); +elseif isequal(eventdata.Key, 'e') && isequal(eventdata.Modifier, {'control'}) + cb_edit(h); +elseif isequal(eventdata.Key, 'p') && isequal(eventdata.Modifier, {'control'}) + cb_prev(h); +elseif isequal(eventdata.Key, 'n') && isequal(eventdata.Modifier, {'control'}) + cb_next(h); +elseif isequal(eventdata.Key, 'q') && isequal(eventdata.Modifier, {'control'}) + cb_cancel(h); +elseif isequal(eventdata.Key, 'x') && isequal(eventdata.Modifier, {'control'}) + % FIXME this does not work + cb_done(h); +elseif isequal(eventdata.Key, 'n') && any(strcmp(eventdata.Modifier, 'shift')) && any(strcmp(eventdata.Modifier, 'control')) + % FIXME this does not always work correctly + cb_skip(h); +end +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function cb_show(h, eventdata) +h = parentfig(h); +data = guidata(h); +clf(h); +if data.current<1 + % introduction, construct the GUI elements + ui_next = uicontrol(h, 'tag', 'ui_next', 'KeyPressFcn', @cb_keyboard, 'style', 'pushbutton', 'string', 'next >', 'callback', @cb_next); + ui_help = uicontrol(h, 'tag', 'ui_help', 'KeyPressFcn', @cb_keyboard, 'style', 'text', 'max', 10, 'horizontalAlignment', 'left', 'FontName', '', 'backgroundColor', get(h, 'color')); + % display the introduction text + title = cat(2, data.file, ' - introduction'); + tmp = {data.script.title}; + help = sprintf('%s\n', tmp{:}); + help = sprintf('This wizard will help you through the following steps:\n\n%s', help); + set(ui_help, 'string', help); + set(h, 'Name', title); +elseif data.current>length(data.script) + % finalization, construct the GUI elements + ui_prev = uicontrol(h, 'tag', 'ui_prev', 'KeyPressFcn', @cb_keyboard, 'style', 'pushbutton', 'string', '< prev', 'callback', @cb_prev); + ui_next = uicontrol(h, 'tag', 'ui_next', 'KeyPressFcn', @cb_keyboard, 'style', 'pushbutton', 'string', 'finish', 'callback', @cb_done); + ui_help = uicontrol(h, 'tag', 'ui_help', 'KeyPressFcn', @cb_keyboard, 'style', 'text', 'max', 10, 'horizontalAlignment', 'left', 'FontName', '', 'backgroundColor', get(h, 'color')); + % display the finalization text + title = cat(2, data.file, ' - finish'); + help = sprintf('If you click finish, the variables created by the script will be exported to the Matlab workspace\n'); + set(ui_help, 'string', help); + set(h, 'Name', title); +else + % normal wizard step, construct the GUI elements + ui_prev = uicontrol(h, 'tag', 'ui_prev', 'KeyPressFcn', @cb_keyboard, 'style', 'pushbutton', 'string', '< prev', 'callback', @cb_prev); + ui_next = uicontrol(h, 'tag', 'ui_next', 'KeyPressFcn', @cb_keyboard, 'style', 'pushbutton', 'string', 'next >', 'callback', @cb_next); + ui_help = uicontrol(h, 'tag', 'ui_help', 'KeyPressFcn', @cb_keyboard, 'style', 'text', 'max', 10, 'horizontalAlignment', 'left', 'FontName', '', 'backgroundColor', get(h, 'color')); + ui_code = uicontrol(h, 'tag', 'ui_code', 'KeyPressFcn', @cb_keyboard, 'style', 'edit', 'max', 10, 'horizontalAlignment', 'left', 'FontName', 'Courier', 'backgroundColor', 'white'); + % display the current wizard content + help = data.script(data.current).help; + code = data.script(data.current).code; + title = cat(2, data.file, ' - ', data.script(data.current).title); + set(ui_help, 'string', help); + set(ui_code, 'string', code); + set(h, 'Name', title); +end +cb_resize(h); +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function cb_resize(h, eventdata) +h = parentfig(h); +ui_prev = findobj(h, 'tag', 'ui_prev'); +ui_next = findobj(h, 'tag', 'ui_next'); +ui_help = findobj(h, 'tag', 'ui_help'); +ui_code = findobj(h, 'tag', 'ui_code'); +siz = get(h, 'position'); +x = siz(3); +y = siz(4); +w = (y-40-20)/2; +if ~isempty(ui_prev) + set(ui_prev, 'position', [x-150 10 60 20]); +end +if ~isempty(ui_next) + set(ui_next, 'position', [x-080 10 60 20]); +end +if ~isempty(ui_code) && ~isempty(ui_help) + set(ui_code, 'position', [10 40 x-20 w]); + set(ui_help, 'position', [10 50+w x-20 w]); +else + set(ui_help, 'position', [10 40 x-20 y-50]); +end +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function cb_prev(h, eventdata) +h = parentfig(h); +cb_disable(h); +data = guidata(h); +if data.current>0 + data.current = data.current - 1; +end +guidata(h, data); +cb_show(h); +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function cb_next(h, eventdata) +h = parentfig(h); +cb_disable(h); +data = guidata(h); +if data.current>0 + title = cat(2, data.file, ' - busy'); + set(h, 'Name', title); + ui_code = findobj(h, 'tag', 'ui_code'); + code = get(ui_code, 'string'); + try + for i=1:size(code,1) + evalin('caller', code(i,:)); + end + catch + lasterr; + end + data.script(data.current).code = code; +end +data.current = data.current+1; +guidata(h, data); +cb_show(h); +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function cb_skip(h, eventdata) +h = parentfig(h); +cb_disable(h); +data = guidata(h); +data.current = data.current+1; +guidata(h, data); +cb_show(h); +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function cb_disable(h, eventdata) +h = parentfig(h); +ui_prev = findobj(h, 'tag', 'ui_prev'); +ui_next = findobj(h, 'tag', 'ui_next'); +ui_help = findobj(h, 'tag', 'ui_help'); +ui_code = findobj(h, 'tag', 'ui_code'); +set(ui_prev, 'Enable', 'off'); +set(ui_next, 'Enable', 'off'); +set(ui_help, 'Enable', 'off'); +set(ui_code, 'Enable', 'off'); +drawnow +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function cb_enable(h, eventdata) +h = parentfig(h); +ui_prev = findobj(h, 'tag', 'ui_prev'); +ui_next = findobj(h, 'tag', 'ui_next'); +ui_help = findobj(h, 'tag', 'ui_help'); +ui_code = findobj(h, 'tag', 'ui_code'); +set(ui_prev, 'Enable', 'on'); +set(ui_next, 'Enable', 'on'); +set(ui_help, 'Enable', 'on'); +set(ui_code, 'Enable', 'on'); +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function cb_edit(h, eventdata) +h = parentfig(h); +data = guidata(h); +filename = fullfile(data.path, [data.file data.ext]); +edit(filename); +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function cb_load(h, eventdata) +h = parentfig(h); +cb_disable(h); +[f, p] = uigetfile('*.m', 'Load script from an M-file'); +if ~isequal(f,0) + data = guidata(h); + filename = fullfile(p, f); + [p, f, x] = fileparts(filename); + str = script_parse(filename); + data.script = str; + data.current = 0; + data.path = p; + data.file = f; + data.ext = x; + guidata(h, data); + cb_show(h); +end +cb_enable(h); +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function cb_save(h, eventdata) +cb_disable(h); +data = guidata(h); +filename = fullfile(data.path, [data.file data.ext]); +[f, p] = uiputfile('*.m', 'Save script to an M-file', filename); +if ~isequal(f,0) + filename = fullfile(p, f); + [p, f, x] = fileparts(filename); + fid = fopen(filename, 'wt'); + script = data.script; + for k=1:length(script) + fprintf(fid, '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n'); + for i=1:size(script(k).help, 1) + fprintf(fid, '%% %s\n', deblank(script(k).help(i,:))); + end + for i=1:size(script(k).code, 1) + fprintf(fid, '%s\n', deblank(script(k).code(i,:))); + end + end + fclose(fid); + data.path = p; + data.file = f; + data.ext = x; + guidata(h, data); + cb_show(h); +end +cb_enable(h); +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function cb_done(h, eventdata) +h = parentfig(h); +cb_disable(h); +assignin('caller', 'wizard_ok', 1); +delete(h); +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function cb_cancel(h, eventdata) +h = parentfig(h); +cb_disable(h); +assignin('caller', 'wizard_ok', 0); +delete(h); +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function script = script_parse(filename) +if isempty(filename) + script.title = ''; + script.help = ''; + script.code = ''; + return +end +fid = fopen(filename); +str = {}; +while ~feof(fid) + str{end+1} = fgetl(fid); +end +str = str(:); +fclose(fid); +i = 1; % line number +k = 1; % block number +script = []; +while i<=length(str) + script(k).title = {}; + script(k).help = {}; + script(k).code = {}; + while i<=length(str) && ~isempty(regexp(str{i}, '^%%%%', 'once')) + % skip the seperator lines + i = i+1; + end + while i<=length(str) && ~isempty(regexp(str{i}, '^%', 'once')) + script(k).help{end+1} = str{i}(2:end); + i = i+1; + end + while i<=length(str) && isempty(regexp(str{i}, '^%%%%', 'once')) + script(k).code{end+1} = str{i}; + i = i+1; + end + k = k+1; +end +sel = false(size(script)); +for k=1:length(script) + sel(k) = isempty(script(k).help) && isempty(script(k).code); + if length(script(k).help)>0 + script(k).title = char(script(k).help{1}); + else + script(k).title = ''; + end + script(k).help = char(script(k).help(:)); + script(k).code = char(script(k).code(:)); +end +script(sel) = []; +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function h = parentfig(h) +while get(h, 'parent') + h = get(h, 'parent'); +end +return diff --git a/external/fieldtrip/private/write_brainvision_eeg.m b/external/fieldtrip/private/write_brainvision_eeg.m index 23a5aa0..044ce7d 100644 --- a/external/fieldtrip/private/write_brainvision_eeg.m +++ b/external/fieldtrip/private/write_brainvision_eeg.m @@ -11,21 +11,23 @@ % Copyright (C) 2007, Robert Oostenveld % -% $Log: write_brainvision_eeg.m,v $ -% Revision 1.1 2009/01/14 09:12:16 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.2 2007/07/23 14:37:58 roboos -% fixed channel count for multi-trial data +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.1 2007/06/13 08:07:32 roboos -% initial implementation +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: write_brainvision_eeg.m 1350 2010-07-05 06:59:27Z roboos $ if length(size(dat))>2 ntrl = size(dat,1); @@ -66,30 +68,30 @@ fclose(fid); % open the header file and write the ascii header information -fid = fopen(headerfile, 'wt'); -fprintf(fid, 'Brain Vision Data Exchange Header File Version 1.0\n'); -fprintf(fid, '; Data created by FieldTrip\n'); -fprintf(fid, '\n'); -fprintf(fid, '[Common Infos]\n'); -fprintf(fid, 'DataFile=%s\n', datafile); +fid = fopen(headerfile, 'wb'); +fprintf(fid, 'Brain Vision Data Exchange Header File Version 1.0\r\n'); +fprintf(fid, '; Data created by FieldTrip\r\n'); +fprintf(fid, '\r\n'); +fprintf(fid, '[Common Infos]\r\n'); +fprintf(fid, 'DataFile=%s\r\n', datafile); if ~isempty(markerfile) - fprintf(fid, 'MarkerFile=%s\n', markerfile); + fprintf(fid, 'MarkerFile=%s\r\n', markerfile); end -fprintf(fid, 'DataFormat=%s\n', hdr.DataFormat); -fprintf(fid, 'DataOrientation=%s\n', hdr.DataOrientation); -fprintf(fid, 'NumberOfChannels=%d\n', hdr.nChans); +fprintf(fid, 'DataFormat=%s\r\n', hdr.DataFormat); +fprintf(fid, 'DataOrientation=%s\r\n', hdr.DataOrientation); +fprintf(fid, 'NumberOfChannels=%d\r\n', hdr.nChans); % Sampling interval in microseconds -fprintf(fid, 'SamplingInterval=%d\n', round(1e6/hdr.Fs)); -fprintf(fid, '\n'); -fprintf(fid, '[Binary Infos]\n'); -fprintf(fid, 'BinaryFormat=%s\n', hdr.BinaryFormat); -fprintf(fid, '\n'); -fprintf(fid, '[Channel Infos]\n'); +fprintf(fid, 'SamplingInterval=%d\r\n', round(1e6/hdr.Fs)); +fprintf(fid, '\r\n'); +fprintf(fid, '[Binary Infos]\r\n'); +fprintf(fid, 'BinaryFormat=%s\r\n', hdr.BinaryFormat); +fprintf(fid, '\r\n'); +fprintf(fid, '[Channel Infos]\r\n'); % Each entry: Ch=,,,... % Fields are delimited by commas, some fields might be omitted (empty). % Commas in channel names should be coded as "\1", but are not supported here for i=1:hdr.nChans - fprintf(fid, 'Ch%d=%s,,%g\n', i, hdr.label{i}, hdr.resolution(i)); + fprintf(fid, 'Ch%d=%s,,%g\r\n', i, hdr.label{i}, hdr.resolution(i)); end fclose(fid); diff --git a/external/fieldtrip/private/write_ctf_shm.m b/external/fieldtrip/private/write_ctf_shm.m new file mode 100644 index 0000000..80689c0 --- /dev/null +++ b/external/fieldtrip/private/write_ctf_shm.m @@ -0,0 +1,62 @@ +function [varargout] = funname(varargin) + +% WRITE_CTF_SHM writes metainformation and data as a packet to shared memory. +% This function can be used for real-time processing of data while it is +% being acquired. +% +% Use as +% write_ctf_shm(msgType, msgId, sampleNumber, numSamples, numChannels, data); +% +% See also READ_CTF_SHM + +% Copyright (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: write_ctf_shm.m 945 2010-04-21 17:41:20Z roboos $ + +% remember the original working directory +pwdir = pwd; + +% determine the name and full path of this function +funname = mfilename('fullpath'); +mexsrc = [funname '.c']; +[mexdir, mexname] = fileparts(funname); + +try + % try to compile the mex file on the fly + warning('trying to compile MEX file from %s', mexsrc); + cd(mexdir); + mex(mexsrc); + cd(pwdir); + success = true; + +catch + % compilation failed + disp(lasterr); + error('could not locate MEX file for %s', mexname); + cd(pwdir); + success = false; +end + +if success + % execute the mex file that was juist created + funname = mfilename; + funhandle = str2func(funname); + [varargout{1:nargout}] = funhandle(varargin{:}); +end + diff --git a/external/fieldtrip/private/write_data.m b/external/fieldtrip/private/write_data.m deleted file mode 100644 index 7b2f15b..0000000 --- a/external/fieldtrip/private/write_data.m +++ /dev/null @@ -1,625 +0,0 @@ -function write_data(filename, dat, varargin) - -% WRITE_DATA exports electrophysiological data to a file. The input data is -% assumed to be scaled in microVolt. -% -% Use as -% write_data(filename, dat, ...) -% -% The specified filename can already contain the filename extention, -% but that is not required since it will be added automatically. -% -% Additional options should be specified in key-value pairs and can be -% 'header' header structure, see READ_HEADER -% 'dataformat' string, see below -% 'append' boolean, not supported for all formats -% 'chanindx' 1xN array -% -% The supported dataformats are -% brainvision_eeg -% matlab -% riff_wave -% fcdc_matbin -% fcdc_mysql -% fcdc_buffer -% plexon_nex -% neuralynx_ncs -% neuralynx_sdma -% -% See also READ_HEADER, READ_DATA, READ_EVEN, WRITE_EVENT - -% Copyright (C) 2007-2008, Robert Oostenveld -% -% $Log: write_data.m,v $ -% Revision 1.23 2009/06/17 10:15:43 roboos -% added support for neuralynx_sdma, only for 32 bit integer data -% -% Revision 1.22 2009/05/19 18:29:48 roboos -% give instructive error if the fieldtrip buffer mex file is not on the path -% -% Revision 1.21 2009/01/21 21:20:01 roboos -% improved check to detect missing ft buffer, only start if certain about socket error and if localhost or 127.0.0.1 -% -% Revision 1.20 2009/01/21 11:34:23 marvger -% update in hostname detection for fcdc_buffer -% -% Revision 1.19 2009/01/20 21:46:24 roboos -% use mxSerialize instead of serialize in mysql -% -% Revision 1.18 2009/01/14 21:16:52 marvger -% changes related to realtime processing -% -% Revision 1.17 2008/12/16 15:36:34 roboos -% prevent append to be used twice in the key-value list for fcdc_buffer -% -% Revision 1.16 2008/12/15 14:52:57 roboos -% updated help: be explicit about the function expecting uV input data (also for plexon) -% removed the obsolete code for writing to ctf meg4 files -% -% Revision 1.15 2008/11/03 21:34:11 roboos -% split large segments into multiple smaller ones prior to calling the buffer mex file -% -% Revision 1.14 2008/10/30 10:45:46 roboos -% added format=disp for debugging -% try to initialize a tcpserver if first write to socket fails -% -% Revision 1.13 2008/10/30 10:43:29 roboos -% allow chanindx for buffer -% -% Revision 1.12 2008/10/23 09:09:55 roboos -% improved appending for format=matlab -% added fcdc_global for debugging (consistent with write_event) -% -% Revision 1.11 2008/10/22 10:43:41 roboos -% removed obsolete option subformat -% added option append and implemented for format=matlab (i.e. read, append, write) -% completed the implementation for fcdc_buffer -% -% Revision 1.10 2008/06/19 20:50:35 roboos -% added initial support for fcdc_buffer, sofar only for the header -% -% Revision 1.9 2008/01/31 20:05:05 roboos -% removed fcdc_ftc -% updated documentation -% -% Revision 1.8 2007/12/12 14:40:33 roboos -% added riff_wave using standard matlab function -% -% Revision 1.7 2007/12/06 17:09:06 roboos -% added fcdc_ftc -% -% Revision 1.6 2007/11/07 10:49:07 roboos -% cleaned up the reading and writing from/to mysql database, using db_xxx helper functions (see mysql directory) -% -% Revision 1.5 2007/11/05 17:02:45 roboos -% made first implementation for writing header and data to fcdc_mysql -% -% Revision 1.4 2007/10/01 13:49:11 roboos -% added skeleton implementation for ctf_meg4, not yet tested -% -% Revision 1.3 2007/06/13 08:14:58 roboos -% updated documentation -% -% Revision 1.2 2007/06/13 08:07:14 roboos -% added autodetection of dataformat -% added support for write_brainvision_eeg -% -% Revision 1.1 2007/06/13 06:44:13 roboos -% moved the content of the write_fcdc_data to the low-level write_data function -% updated the help -% - -global data_queue % for fcdc_global -global header_queue % for fcdc_global -global db_blob % for fcdc_mysql -if isempty(db_blob) - db_blob = 0; -end - -% get the options -dataformat = keyval('dataformat', varargin); if isempty(dataformat), dataformat = filetype(filename); end -append = keyval('append', varargin); if isempty(append), append = false; end -nbits = keyval('nbits', varargin); % for riff_wave -chanindx = keyval('chanindx', varargin); -hdr = keyval('header', varargin); - -% determine the data size -[nchans, nsamples] = size(dat); - -switch dataformat - case 'disp' - % display it on screen, this is only for debugging - disp('new data arived'); - - case 'fcdc_global' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % store it in a global variable, this is only for debugging - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - if ~isempty(hdr) - header_queue = hdr; - end - if isempty(data_queue) || ~append - data_queue = dat; - else - data_queue = cat(2, data_queue, dat); - end - - case 'fcdc_buffer' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % network transparent buffer - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - if ~isempty(chanindx) - % assume that the header corresponds to the original multichannel - % file and that the data represents a subset of channels - hdr.label = hdr.label(chanindx); - hdr.nChans = length(chanindx); - end - - [host, port] = filetype_check_uri(filename); - - type = { - 'char' - 'uint8' - 'uint16' - 'uint32' - 'uint64' - 'int8' - 'int16' - 'int32' - 'int64' - 'single' - 'double' - }; - - wordsize = { - 1 % 'char' - 1 % 'uint8' - 2 % 'uint16' - 4 % 'uint32' - 8 % 'uint64' - 1 % 'int8' - 2 % 'int16' - 4 % 'int32' - 8 % 'int64' - 4 % 'single' - 8 % 'double' - }; - - % this should only be done the first time - if ~append && ~isempty(hdr) - % reformat the header into a buffer-compatible format - packet.fsample = hdr.Fs; - packet.nchans = hdr.nChans; - packet.nsamples = 0; - packet.nevents = 0; - packet.data_type = find(strcmp(type, class(dat))) - 1; % zero-offset - - % try to put_hdr and initialize if necessary - try - % try writing the packet - buffer('put_hdr', packet, host, port); - - catch - if ~isempty(strfind(lasterr, 'Buffer size N must be an integer-valued scalar double.')) - % this happens if the MATLAB75/toolbox/signal/signal/buffer - % function is used instead of the fieldtrip buffer - error('the FieldTrip buffer mex file was not found on your path, it should be in fieldtrip/fileio/private'); - - elseif ~isempty(strfind(lasterr, 'failed to create socket')) && (strcmp(host, 'localhost') || strcmp(host, '127.0.0.1')) - - % start a local instance of the TCP server - warning('starting fieldtrip buffer on %s:%d', host, port); - buffer('tcpserver', 'init', host, port); - pause(1); - - % rewrite the packet until success - success = false; - while ~success - try - % it may take some time before the TCP server is fully initialized - % try writing the packet again - buffer('put_hdr', packet, host, port); - success = true; - catch - success = false; - end - end - end % if strfind... - - end % try - - end % writing header - - if ~isempty(dat) - max_nsamples = 32556; - if size(dat,2)>max_nsamples - % FIXME this is a hack to split large writes into multiple smaller writes - % this is to work around a problem observed in the neuralynx proxy - % when sampling 32 channels at 32KHz - begsample = 1; - while begsample<=size(dat,2) - endsample = begsample - 1 + max_nsamples; - endsample = min(endsample, size(dat,2)); - % if append is already one of the arguments, remove it from varargin - indx = find(strcmp(varargin, 'append')); % find the "append" key - if ~isempty(indx) - indx = [indx indx+1]; % remove the key and the value - varargin(indx) = []; - end - write_data(filename, dat(:,begsample:endsample), varargin{:}, 'append', false); - begsample = endsample + 1; - end - else - % FIXME this is the normal code, which will also be used recursively - % reformat the data into a buffer-compatible format - packet.nchans = size(dat,1); - packet.nsamples = size(dat,2); - packet.data_type = find(strcmp(type, class(dat))) - 1; % zero-offset - packet.bufsize = numel(dat) * wordsize{find(strcmp(type, class(dat)))}; - packet.buf = dat; - buffer('put_dat', packet, host, port); - end % if data larger than chuncksize - end - - case 'brainvision_eeg' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % combination of *.eeg and *.vhdr file - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - if append - error('appending data is not yet supported for this data format'); - end - - if nchans~=hdr.nChans && length(chanindx)==nchans - % assume that the header corresponds to the original multichannel - % file and that the data represents a subset of channels - hdr.label = hdr.label(chanindx); - hdr.nChans = length(chanindx); - end - % the header should at least contain the following fields - % hdr.label - % hdr.nChans - % hdr.Fs - write_brainvision_eeg(filename, hdr, dat); - - case 'fcdc_matbin' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % multiplexed data in a *.bin file (ieee-le, 64 bit floating point values), - % accompanied by a matlab V6 file containing the header - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - if append - error('appending data is not yet supported for this data format'); - end - - [path, file, ext] = fileparts(filename); - headerfile = fullfile(path, [file '.mat']); - datafile = fullfile(path, [file '.bin']); - if nchans~=hdr.nChans && length(chanindx)==nchans - % assume that the header corresponds to the original multichannel - % file and that the data represents a subset of channels - hdr.label = hdr.label(chanindx); - hdr.nChans = length(chanindx); - end - % write the header file - save(headerfile, 'hdr', '-v6'); - % write the data file - [fid,message] = fopen(datafile,'wb','ieee-le'); - fwrite(fid, dat, 'double'); - fclose(fid); - - case 'fcdc_mysql' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % write to a MySQL server listening somewhere else on the network - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - db_open(filename); - if ~isempty(hdr) && isempty(dat) - % insert the header information into the database - if db_blob - % insert the structure into the database table as a binary blob - db_insert_blob('fieldtrip.header', 'msg', hdr); - else - % make a structure with the same elements as the fields in the database table - s = struct; - s.Fs = hdr.Fs; % sampling frequency - s.nChans = hdr.nChans; % number of channels - s.nSamples = hdr.nSamples; % number of samples per trial - s.nSamplesPre = hdr.nSamplesPre; % number of pre-trigger samples in each trial - s.nTrials = hdr.nTrials; % number of trials - s.label = mxSerialize(hdr.label); - try - s.msg = mxSerialize(hdr); - catch - warning(lasterr); - end - db_insert('fieldtrip.header', s); - end - - elseif isempty(hdr) && ~isempty(dat) - dim = size(dat); - if numel(dim)==2 - % ensure that the data dimensions correspond to ntrials X nchans X samples - dim = [1 dim]; - dat = reshape(dat, dim); - end - ntrials = dim(1); - for i=1:ntrials - if db_blob - % insert the data into the database table as a binary blob - db_insert_blob('fieldtrip.data', 'msg', reshape(dat(i,:,:), dim(2:end))); - else - % create a structure with the same fields as the database table - s = struct; - s.nChans = dim(2); - s.nSamples = dim(3); - try - s.data = mxSerialize(reshape(dat(i,:,:), dim(2:end))); - catch - warning(lasterr); - end - % insert the structure into the database - db_insert('fieldtrip.data', s); - end - end - - else - error('you should specify either the header or the data when writing to a MySQL database'); - end - - case 'matlab' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % plain matlab file - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - [path, file, ext] = fileparts(filename); - filename = fullfile(path, [file '.mat']); - if append && exist(filename, 'file') - % read the previous header and data from matlab file - prev = load(filename); - if ~isempty(hdr) && ~isequal(hdr, prev.hdr) - error('inconsistent header'); - else - % append the new data to that from the matlab file - dat = cat(2, prev.dat, dat); - end - elseif append && ~exist(filename, 'file') - % file does not yet exist, which is not a problem - elseif ~append && exist(filename, 'file') - warning(sprintf('deleting existing file ''%s''', filename)); - delete(filename); - elseif ~append && ~exist(filename, 'file') - % file does not yet exist, which is not a problem - end - save(filename, 'dat', 'hdr'); - - case 'neuralynx_sdma' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % The first version of this file format contained in the first 8 bytes the - % channel label as string. Subsequently it contained 32 bit integer values. - % - % The second version of this file format starts with 8 bytes describing (as - % a space-padded string) the data type. The channel label is contained in - % the filename as dataset.chanlabel.bin. - % - % The third version of this file format starts with 7 bytes describing (as - % a zero-padded string) the data type, followed by the 8th byte which - % describes the downscaling for the 8 and 16 bit integer representations. - % The downscaling itself is represented as uint8 and should be interpreted as - % the number of bits to shift. The channel label is contained in the - % filename as dataset.chanlabel.bin. - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - statuschannel = { - 'stx' - 'pid' - 'siz' - 'tsh' - 'tsl' - 'cpu' - 'ttl' - 'x01' - 'x02' - 'x03' - 'x04' - 'x05' - 'x06' - 'x07' - 'x08' - 'x09' - 'x10' - 'crc' - }; - - dirname = filename; - clear filename - [path, file] = fileparts(dirname); - for i=1:hdr.nChans - downscale(i) = 0; - if ~isempty(strmatch(hdr.label{i}, statuschannel)) - format{i} = 'uint32'; - else - format{i} = 'int32'; - end - filename{i} = fullfile(dirname, [file '.' hdr.label{i} '.bin']); - end - - if ~isdir(dirname) - mkdir(dirname); - end - - % open and write to the output files, one for each selected channel - fid = zeros(hdr.nChans,1); - for j=1:hdr.nChans - - if append==false - fid(j) = fopen(filename{j}, 'wb', 'ieee-le'); % open the file - magic = format{j}; % this used to be the channel name - magic((end+1):8) = 0; % pad with zeros - magic(8) = downscale(j); % number of bits to shift - fwrite(fid(j), magic(1:8)); % write the 8-byte file header - else - fid(j) = fopen(filename{j}, 'ab', 'ieee-le'); % open the file for appending - end % if append - - % convert the data into the correct class - buf = dat(j,:); - if ~strcmp(class(buf), format{j}) - switch format{j} - case 'int16' - buf = int16(buf); - case 'int32' - buf = int32(buf); - case 'single' - buf = single(buf); - case 'double' - buf = double(buf); - case 'uint32' - buf = uint32(buf); - otherwise - error('unsupported format conversion'); - end - end - - % apply the scaling, this corresponds to bit shifting - buf = buf ./ (2^downscale(j)); - - % write the segment of data to the output file - fwrite(fid(j), buf, format{j}, 'ieee-le'); - - fclose(fid(j)); - end % for each channel - - case 'riff_wave' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % This writes data Y to a Windows WAVE file specified by the file name - % WAVEFILE, with a sample rate of FS Hz and with NBITS number of bits. - % NBITS must be 8, 16, 24, or 32. For NBITS < 32, amplitude values - % outside the range [-1,+1] are clipped - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - if append - error('appending data is not yet supported for this data format'); - end - - if nchans~=hdr.nChans && length(chanindx)==nchans - % assume that the header corresponds to the original multichannel - % file and that the data represents a subset of channels - hdr.label = hdr.label(chanindx); - hdr.nChans = length(chanindx); - end - if nchans~=1 - error('this format only supports single channel continuous data'); - end - wavwrite(dat, hdr.Fs, nbits, filename); - - case 'plexon_nex' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % single or mulitple channel Plexon NEX file - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - if append - error('appending data is not yet supported for this data format'); - end - - [path, file] = fileparts(filename); - filename = fullfile(path, [file, '.nex']); - if nchans~=1 - error('only supported for single-channel data'); - end - % construct a NEX structure with the required parts of the header - nex.hdr.VarHeader.Type = 5; % continuous - nex.hdr.VarHeader.Name = hdr.label{1}; - nex.hdr.VarHeader.WFrequency = hdr.Fs; - if isfield(hdr, 'FirstTimeStamp') - nex.hdr.FileHeader.Frequency = hdr.Fs * hdr.TimeStampPerSample; - nex.var.ts = hdr.FirstTimeStamp; - else - warning('no timestamp information available'); - nex.hdr.FileHeader.Frequency = nan; - nex.var.ts = nan; - end - nex.var.indx = 0; - nex.var.dat = dat; - - write_plexon_nex(filename, nex); - - if 0 - % the following code snippet can be used for testing - nex2 = []; - [nex2.var, nex2.hdr] = read_plexon_nex(filename, 'channel', 1); - end - - case 'neuralynx_ncs' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % single channel Neuralynx NCS file - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - if append - error('appending data is not yet supported for this data format'); - end - - if nchans>1 - error('only supported for single-channel data'); - end - - [path, file, ext] = fileparts(filename); - filename = fullfile(path, [file, '.ncs']); - - if nchans~=hdr.nChans && length(chanindx)==nchans - % assume that the header corresponds to the original multichannel - % file and that the data represents a subset of channels - % WARNING the AD channel index assumes that the data was read from a DMA or SDMA file - % the first 17 channels contain status info, this number is zero-offset - ADCHANNEL = chanindx - 17 - 1; - LABEL = hdr.label{chanindx}; - elseif hdr.nChans==1 - ADCHANNEL = -1; % unknown - LABEL = hdr.label{1}; % single channel - else - error('cannot determine channel label'); - end - - FSAMPLE = hdr.Fs; - RECORDNSMP = 512; - RECORDSIZE = 1044; - - % cut the downsampled LFP data into record-size pieces - nrecords = ceil(nsamples/RECORDNSMP); - fprintf('construct ncs with %d records\n', nrecords); - - % construct a ncs structure with all header details and the data in it - ncs = []; - ncs.NumValidSamp = ones(1,nrecords) * RECORDNSMP; % except for the last block - ncs.ChanNumber = ones(1,nrecords) * ADCHANNEL; - ncs.SampFreq = ones(1,nrecords) * FSAMPLE; - ncs.TimeStamp = zeros(1,nrecords,'uint64'); - - if rem(nsamples, RECORDNSMP)>0 - % the data length is not an integer number of records, pad the last record with zeros - dat = cat(2, dat, zeros(nchans, nrecords*RECORDNSMP-nsamples)); - ncs.NumValidSamp(end) = rem(nsamples, RECORDNSMP); - end - - ncs.dat = reshape(dat, RECORDNSMP, nrecords); - - for i=1:nrecords - % timestamps should be 64 bit unsigned integers - ncs.TimeStamp(i) = uint64(hdr.FirstTimeStamp) + uint64((i-1)*RECORDNSMP*hdr.TimeStampPerSample); - end - - % add the elements that will go into the ascii header - ncs.hdr.CheetahRev = '4.23.0'; - ncs.hdr.NLX_Base_Class_Type = 'CscAcqEnt'; - ncs.hdr.NLX_Base_Class_Name = LABEL; - ncs.hdr.RecordSize = RECORDSIZE; - ncs.hdr.ADChannel = ADCHANNEL; - ncs.hdr.SamplingFrequency = FSAMPLE; - - % write it to a file - fprintf('writing to %s\n', filename); - write_neuralynx_ncs(filename, ncs); - - if 0 - % the following code snippet can be used for testing - ncs2 = read_neuralynx_ncs(filename, 1, inf); - end - - otherwise - error('unsupported data format'); -end % switch dataformat - diff --git a/external/fieldtrip/private/write_event.m b/external/fieldtrip/private/write_event.m deleted file mode 100644 index de6e702..0000000 --- a/external/fieldtrip/private/write_event.m +++ /dev/null @@ -1,527 +0,0 @@ -function write_event(filename, event, varargin) - -% WRITE_EVENT writes an event structure to a file, a message daemon -% listening on a network socked, or to another computer connected through -% the serial port. -% -% Use as -% write_event(filename, event, ...) -% -% The first argument is a string containing the filename. The second -% argument is a structure with the event. Multiple events can be -% represented as a structure array. -% -% Events are represented as -% event.type string -% event.sample expressed in samples, the first sample of a recording is 1 -% event.value number or string -% event.offset expressed in samples -% event.duration expressed in samples -% event.timestamp expressed in timestamp units, which vary over systems (optional) -% -% Events can also be written to special communication streams -% by specifying the target as URI instead of a filename. Supported are -% buffer://: -% fifo:// -% tcp://: -% udp://: -% mysql://:@: -% rfb://@: -% serial:?key1=value1&key2=value2&... -% rfb://@: -% -% See also READ_HEADER, READ_DATA, READ_EVENT, WRITE_DATA - -% Copyright (C) 2007, Robert Oostenveld -% -% $Log: write_event.m,v $ -% Revision 1.35 2009/05/22 09:02:29 marvger -% changed tcp handling -% -% Revision 1.34 2009/04/28 08:33:05 marvger -% small changes -% -% Revision 1.33 2009/01/22 15:31:59 marvger -% updated catch handling -% -% Revision 1.32 2009/01/21 11:34:44 marvger -% update in hostname detection for fcdc_buffer -% -% Revision 1.31 2009/01/20 08:56:51 marvger -% fixed catch me bug (illegal syntax in older matlab versions) -% -% Revision 1.30 2009/01/16 11:38:51 marvger -% update tcp/udp -% -% Revision 1.29 2009/01/14 21:16:52 marvger -% changes related to realtime processing -% -% Revision 1.28 2008/12/19 14:39:25 marvger -% added support for udp, tcp and fifo -% -% Revision 1.27 2008/06/19 19:31:44 roboos -% made fcdc_buffer more robust -% -% Revision 1.26 2008/06/18 06:22:24 roboos -% added support for fcdc_buffer -% -% Revision 1.25 2008/01/30 10:40:54 roboos -% moved catevent to seperate function and renamed to appendevent -% -% Revision 1.24 2007/12/12 11:29:07 roboos -% chedk for presence of timestamp prior to trying to concatenate events -% -% Revision 1.23 2007/11/07 11:03:58 roboos -% added line of documentation -% -% Revision 1.22 2007/11/07 10:49:07 roboos -% cleaned up the reading and writing from/to mysql database, using db_xxx helper functions (see mysql directory) -% -% Revision 1.21 2007/11/05 17:04:03 roboos -% moved insert_query to seperate function -% ved declarationof persistent and global variables to the beginning of the function -% some cosmetic changes -% -% Revision 1.20 2007/10/30 20:47:04 roboos -% added support for remote frame buffer (rfb), i.e. VNC server -% -% Revision 1.19 2007/10/16 12:34:43 roboos -% use recursion to write to multiple event sources -% implemented fcdc_global -% -% Revision 1.18 2007/09/15 14:36:26 chrhes -% changed the default mode for writing to a serial port to synchronous -% -% Revision 1.17 2007/08/16 14:28:59 chrhes -% removed the try-catches introduced in previous revision: the relevant error -% is now dealt with elsewhere -% -% Revision 1.16 2007/08/16 14:03:20 chrhes -% put some try-catches around the save command in the default option -% -% Revision 1.15 2007/06/19 11:11:28 chrhes -% changed the implementation of how the target serial port is located if it -% exists -% -% Revision 1.14 2007/06/19 10:11:37 chrhes -% restricted the functionality of serial port writing such that only the -% content of the field event.value is written as a character array -% -% Revision 1.13 2007/06/13 14:46:35 roboos -% removed type/subtype, added type/value/sample for mysql -% -% Revision 1.12 2007/06/13 08:06:45 roboos -% updated help -% -% Revision 1.11 2007/06/12 19:37:28 roboos -% added support for mysql port specification (default is 3306) -% added support for writing multiple events to mysql, each requires a single query -% -% Revision 1.10 2007/06/12 16:34:49 roboos -% first implementation of writing to a mysql database: approx. 30ms per event -% -% Revision 1.9 2007/06/07 12:43:38 chrhes -% added an option for specifying the maximum length of the event queue for -% the case where the events are being written (appended) to a .mat file -% -% Revision 1.8 2007/06/06 20:14:49 chrhes -% fixed a small bug to do with sting comparison -% -% Revision 1.7 2007/06/06 16:00:31 chrhes -% updated some documentation -% -% Revision 1.6 2007/06/06 15:55:30 chrhes -% extended functionality for serial port writing so that the code recognises -% when to write the whole event structure or only a single control character -% -% Revision 1.5 2007/06/06 15:45:53 chrhes -% implemented option for writing events to the serial port -% -% Revision 1.4 2007/06/06 12:38:57 roboos -% write events to uncompressed matlab v6 file -% -% Revision 1.3 2007/06/06 07:14:29 roboos -% switched to using filetype_check_uri for detection and parsing of filename -% switched to using external struct2msg function -% implemented fcdc_fifo -% added optinoal input arguments (key-value pairs) -% -% Revision 1.2 2007/05/31 09:54:05 roboos -% implemented writing events to a plain matlab file, the default is to append them -% -% Revision 1.1 2007/05/31 09:14:34 roboos -% initial implementation, sofar only tcpsocket -% - -global event_queue % for fcdc_global -global db_blob % for fcdc_mysql -if isempty(db_blob) - db_blob = 0; -end - -if iscell(filename) - % use recursion to write to multiple event targets - for i=1:numel(filename) - write_event(filename{i}, event, varargin); - end - return -end - -% set the defaults -eventformat = keyval('eventformat', varargin); if isempty(eventformat), eventformat = filetype(filename); end -swapping = keyval('swapping', varargin); if isempty(swapping), swapping = 'native'; end -append = keyval('append', varargin); if isempty(append), append = 'yes'; end -maxqlength = keyval('maxqlength', varargin); if isempty(maxqlength), maxqlength = Inf; end - -switch eventformat - case 'disp' - % display it on screen, this is only for debugging - disp(event); - - case 'fcdc_global' - % store it in a global variable, this is only for debugging - if isempty(event_queue) || ~isstruct(event_queue) - event_queue = event; - else - event_queue = appendevent(event_queue, event); - end - - case 'fcdc_rfb' - % remote frame buffer, i.e. VNC server on another computer - [password, host, port] = filetype_check_uri(filename); - rfbevent(sprintf('%s:%d', host, port), password, event.type, event.value); - - case 'fcdc_buffer' - % read from a networked buffer for realtime analysis - [host, port] = filetype_check_uri(filename); - - type = { - 'char' - 'uint8' - 'uint16' - 'uint32' - 'uint64' - 'int8' - 'int16' - 'int32' - 'int64' - 'single' - 'double' - }; - - wordsize = { - 1 % 'char' - 1 % 'uint8' - 2 % 'uint16' - 4 % 'uint32' - 8 % 'uint64' - 1 % 'int8' - 2 % 'int16' - 4 % 'int32' - 8 % 'int64' - 4 % 'single' - 8 % 'double' - }; - - for i=1:length(event) - evt = []; - buf = []; - bufsize = 0; - - % convert the field "type" into the message representation - this_type = class(event(i).type); - this_size = numel(event(i).type); - switch this_type - case 'char' - buf = cat(2, buf, event(i).type); - otherwise - buf = cat(2, buf, typecast(event(i).type, 'uint8')); - end - bufsize = bufsize + wordsize{strcmp(type, this_type)}*this_size; - evt.type_type = find(strcmp(type, this_type))-1; % zero-offset - evt.type_numel = this_size; - - % convert the field "value" into the message representation - this_type = class(event(i).value); - this_size = numel(event(i).value); - event(i).value = event(i).value(:)'; % it must be represented as a vector - switch this_type - case 'char' - buf = cat(2, buf, event(i).value); - otherwise - buf = cat(2, buf, typecast(event(i).value, 'uint8')); - end - bufsize = bufsize + wordsize{strcmp(type, this_type)}*this_size; - evt.value_type = find(strcmp(type, this_type))-1; % zero-offset - evt.value_numel = this_size; - - % although sample, offset and duration do not play a role in BCI2000, - % they must exist for the buffer - if ~isfield(event(i), 'sample') || isempty(event(i).sample) - event(i).sample = 0; - end - if ~isfield(event(i), 'offset') || isempty(event(i).offset) - event(i).offset = 0; - end - if ~isfield(event(i), 'duration') || isempty(event(i).duration) - event(i).duration = 0; - end - - % the other fields are simple, because they have a fixed type and only a single elements - evt.sample = int32(event(i).sample); - evt.offset = int32(event(i).offset); - evt.duration = int32(event(i).duration); - - evt.bufsize = bufsize; - evt.buf = uint8(buf); - - % check if buffer is open and keep trying to fill it... - try - - if strcmp(append,'no') - buffer('flush_evt', [], host, port); % flush event - end - - buffer('put_evt', evt, host, port); % indices should be zero-offset - - catch - - % retrieve hostname - [ret, hname] = system('hostname'); - if ret ~= 0, - if ispc - hname = getenv('COMPUTERNAME'); - else - hname = getenv('HOSTNAME'); - end - end - - if strcmpi(host,'localhost') || strcmpi(host,hname) - - warning('starting fieldtrip buffer on localhost'); - - % try starting a local buffer - buffer('tcpserver', 'init', host, port); - pause(1); - - % write packet until succeed - bhdr = false; - while ~bhdr - try - bhdr = true; - - % try writing a dummy header - dumhdr.fsample = 0; - dumhdr.nchans = 0; - dumhdr.nsamples = 0; - dumhdr.nevents = 0; - dumhdr.data_type = 0; - - buffer('put_hdr', dumhdr, host, port); - buffer('put_evt', evt, host, port); % indices should be zero-offset - - catch - bhdr = false; - end - end - end - end - end - - case 'fcdc_serial' - % serial port on windows or linux platform - s = []; - [port, opt] = filetype_check_uri(filename); - % determine whether any serial port objects are already associated with the - % target serial port - temp = instrfind; - if isa(temp,'instrument') - % find all serial ports - i1 = strcmp('serial',{temp(:).Type}); - if any(i1) - % find all serial ports whose name matches that of the specified port - i2 = strmatch(lower(['Serial-',port]),lower({temp(find(i1)==1).Name})); - % set s to the (first) matching port if present (and open if necessary) - if ~isempty(i2) - s = temp(i2(1)); - if ~strcmp(s.Status,'open'), fopen(s); end; - end - end - end - % create, configure a serial port object if necessary and open the port - if ~isa(s,'serial') - s = serial(port); - if ~isempty(opt) && iscell(opt), s = set(s,opt); end; - fopen(s); - end - - % % convert the event structure into an appropriate message - % if isfield(event,'type') && strcmp(event.type,'ctrlchar') - % % use only a single control character - % msg = char(event.value(1)); - % else - % % convert the entire event structure into a message - % msg = struct2msg(event); - % end - - % write the contents of the field event.value to the serial port as a string - if isfield(event,'value') && ~isempty(event.value) - msg = char(event.value); - else - msg = []; - end - % write the message to the serial port - if ~isempty(msg) && isa(s,'serial') && strcmp(s.Status,'open') - %fprintf(s,msg,'async'); - fprintf(s,msg); - else - error('could not write event to serial port'); - end - - case 'fcdc_mysql' - % write to a MySQL server listening somewhere else on the network - db_open(filename); - for i=1:length(event) - if db_blob - % insert the structure into the database table as a binary blob - db_insert_blob('fieldtrip.event', 'msg', event(i)); - else - % make a structure with the same elements as the fields in the database table - s = struct; - % these fields also exist as elements in the table and as such can be used for filtering - if isa(event(i).type, 'char') - s.type = event(i).type; - end - if isa(event(i).value, 'numeric') && numel(event(i).value)==1 - s.value = event(i).value; - end - if isa(event(i).sample, 'numeric') && numel(event(i).sample)==1 - s.sample = event(i).sample; - end - if isa(event(i).sample, 'numeric') && numel(event(i).offset)==1 - s.offset = event(i).offset; - end - if isa(event(i).sample, 'numeric') && numel(event(i).duration)==1 - s.duration = event(i).duration; - end - % insert the structure into the database table - db_insert('fieldtrip.event', s); - end - end - - case 'fcdc_fifo' - - % these are opened in blocking mode, i.e. reading/writing will block until boths sides are connected - fifo = filetype_check_uri(filename); - - if ~exist(fifo,'file') - warning('the FIFO %s does not exist; attempting to create it', fifo); - system(sprintf('mkfifo -m 0666 %s',fifo)); - end - - fid = fopen(fifo, 'w'); - for i=1:length(event) - - try - % convert the event into a network message - msg = mxSerialize(event(i)); - num = fwrite(fid, msg, 'uint8'); - catch - warning(lasterr); - end - - if num~=length(msg) - error('problem writing to FIFO %s', fifo); - end - end - fclose(fid); - - case 'fcdc_tcp' - - % TCP network socket - [host, port] = filetype_check_uri(filename); - - con=pnet('tcpconnect',host,port); - - pnet(con,'setwritetimeout',1); - - if con~=-1, - - try % Failsafe - - for i=1:length(event) - - % convert the event into a network message - msg = mxSerialize(event(i)); - - % tell the message daemon that a message will be sent, and send it - pnet(con,'printf',num2str(msg)); - pnet(con,'printf','\n'); - end -% catch -% warning(lasterr); - end - - pnet(con,'close'); - end - - case 'fcdc_udp' - - % UDP network socket - - [host, port] = filetype_check_uri(filename); - udp=pnet('udpsocket',port); - - if udp~=-1, - try % Failsafe - - for i=1:length(event) - - % convert the event into a network message - msg = mxSerialize(event(i)); - - % tell the message daemon that a message will be sent, and send it - pnet(udp,'write',uint8(msg),1000); - pnet(udp,'writepacket',host,port); % Send buffer as UDP packet to host - end - - catch - warning(lasterr); - end - pnet(udp,'close'); - end - - - otherwise - % assume that it is a file. Since the file probably does not yet - % exist, determine its type by only looking at the extension - if filetype_check_extension(filename, '.mat') - % write the events to a matlab file - if exist(filename,'file') && strcmp(append, 'yes') - try - tmp = load(filename, 'event'); - event = cat(1, tmp.event(:), event(:)); - catch - event = event(:); - end - % optionally restric the length of the event queue to flush old events - if isfinite(maxqlength) && isreal(maxqlength) && (maxqlength>0) && (length(event)>maxqlength) - event = event(end-maxqlength+1:end); - % NOTE: this could be done using the filter event function, but - % then this is just a temporary solution that will probably be - % removed in a future versions of the code - end - save(filename, 'event', '-append', '-v6'); - % NOTE: the -append option in this call to the save function does - % not actually do anything useful w.r.t. the event variable since the - % events are being appended in the code above and the the save function - % will just overwrite the existing event variable in the file. - % However, if there are other variables in the file (whatever) then the - % append option preservs them - else - save(filename, 'event', '-v6'); - end - else - error('unsupported file type') - end -end diff --git a/external/fieldtrip/private/write_fcdc_data.m b/external/fieldtrip/private/write_fcdc_data.m deleted file mode 100644 index d227f7a..0000000 --- a/external/fieldtrip/private/write_fcdc_data.m +++ /dev/null @@ -1,48 +0,0 @@ -function write_fcdc_data(varargin) - -% WRITE_FCDC_DATA exports electrophysiological data to a file -% -% Use as -% write_fcdc_data(filename, dat, ...) -% -% The specified filename can already contain the filename extention, -% but that is not required since it will be added automatically. -% -% Additional options should be specified in key-value pairs and can be -% 'dataformat' string, see below -% 'header' header structure, see READ_FCDC_HEADER -% 'chanindx' 1xN array, selection of channels from the header -% -% The supported dataformats are -% brainvision_eeg -% neuralynx_ncs -% plexon_nex -% fcdc_matbin -% matlab - -% Copyright (C) 2007, Robert Oostenveld -% -% $Log: write_fcdc_data.m,v $ -% Revision 1.5 2007/06/13 08:14:31 roboos -% updated documentation -% -% Revision 1.4 2007/06/13 06:39:37 roboos -% moved the content of the write_fcdc_data to the low-level write_data function -% updated the help -% -% Revision 1.3 2007/03/20 17:05:40 roboos -% removed unused subfunction for fixing the file extension -% -% Revision 1.2 2007/03/20 17:04:27 roboos -% reimplemented plexon_nex with a nex-structure -% ensure that the extension is correct -% added plain matlab as output format -% moved the scaling and conversion to int16 into the low-level function (for neuralynx) -% updated the documentation -% -% Revision 1.1 2007/02/21 09:50:56 roboos -% initial implementation with support for fcdc_matbin, neuralynx_ncs, plexon_nex -% - -% use the low-level writing function -write_data(varargin{:}); diff --git a/external/fieldtrip/private/write_fcdc_spike.m b/external/fieldtrip/private/write_fcdc_spike.m deleted file mode 100644 index 734bb50..0000000 --- a/external/fieldtrip/private/write_fcdc_spike.m +++ /dev/null @@ -1,18 +0,0 @@ -function write_fcdc_spike(varargin) - -% this function is deprecated, please use the write_spike function instead - -% Copyright (C) 2007-2009, Robert Oostenveld -% -% $Log: write_fcdc_spike.m,v $ -% Revision 1.6 2009/05/07 14:21:29 roboos -% deprecated the read_fcdc and write_fcdc functions, give warning and mention the correct function to be used -% - -fieldtripdefs - -warning('this function is deprecated, please use the write_spike function instead'); - -% use the low-level writing function -write_spike(varargin{:}); - diff --git a/external/fieldtrip/private/write_neuralynx_ncs.m b/external/fieldtrip/private/write_neuralynx_ncs.m index a4907b1..81ff4bd 100644 --- a/external/fieldtrip/private/write_neuralynx_ncs.m +++ b/external/fieldtrip/private/write_neuralynx_ncs.m @@ -10,36 +10,23 @@ % Copyright (C) 2005-2007, Robert Oostenveld % -% $Log: write_neuralynx_ncs.m,v $ -% Revision 1.1 2009/01/14 09:12:16 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.7 2007/03/21 12:51:20 roboos -% included the scaling to int16 AD values into this function, i.e. the input data should be uV (double) +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.6 2007/03/19 16:54:52 roboos -% changed numeric representation of something in the ascii header +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.5 2007/02/21 09:52:27 roboos -% changed the writing of the data to reflect t he changed representation (2D numeric array instead of 1D cell array) -% -% Revision 1.4 2007/01/09 09:40:03 roboos -% write timestamps as unsigned (uint64 instead of int64) -% -% Revision 1.3 2005/12/02 09:01:42 roboos -% fixed a comment -% -% Revision 1.2 2005/09/09 12:27:02 roboos -% cleaned up the code, changed the looping over records, added the number of records to the output -% -% Revision 1.1 2005/08/05 13:41:39 roboos -% new implementation +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: write_neuralynx_ncs.m 945 2010-04-21 17:41:20Z roboos $ if ~isa(ncs.TimeStamp, 'uint64') error('timestamps should be uint64'); diff --git a/external/fieldtrip/private/write_neuralynx_nse.m b/external/fieldtrip/private/write_neuralynx_nse.m index 89b507c..d0aeafd 100644 --- a/external/fieldtrip/private/write_neuralynx_nse.m +++ b/external/fieldtrip/private/write_neuralynx_nse.m @@ -10,25 +10,23 @@ % Copyright (C) 2005-2007, Robert Oostenveld % -% $Log: write_neuralynx_nse.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.5 2007/03/21 15:55:31 roboos -% fixed typo in variable name +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.4 2007/03/21 12:53:21 roboos -% included the scaling to int16 AD values into this function, i.e. the input data should be uV (double) +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.3 2007/03/19 16:56:21 roboos -% changed representation of waveforms from cell array into nsample X nspikes numeric array -% -% Revision 1.2 2005/09/09 12:27:15 roboos -% implemented the core functionality of the function -% -% Revision 1.1 2005/08/05 13:41:39 roboos -% new implementation +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: write_neuralynx_nse.m 952 2010-04-21 18:29:51Z roboos $ if ~isa(nse.TimeStamp, 'uint64') error('timestamps should be uint64'); diff --git a/external/fieldtrip/private/write_neuralynx_nts.m b/external/fieldtrip/private/write_neuralynx_nts.m deleted file mode 100644 index 6577562..0000000 --- a/external/fieldtrip/private/write_neuralynx_nts.m +++ /dev/null @@ -1,60 +0,0 @@ -function write_neuralynx_nts(filename, nts); - -% WRITE_NEURALYNX_NTS writes spike timestamps to a NTS file -% -% Use as -% write_neuralynx_nts(filename, nts) -% -% See also READ_NEURALYNX_NTS - -% Copyright (C) 2007, Robert Oostenveld -% -% $Log: write_neuralynx_nts.m,v $ -% Revision 1.1 2007/03/21 17:12:04 roboos -% renamed NTE in NTS (filenames and function names) -% -% Revision 1.2 2007/03/21 12:53:51 roboos -% updated the documentation -% -% Revision 1.1 2007/03/14 16:08:09 roboos -% new implementation -% - -if ~isa(nts.TimeStamp, 'uint64') - error('timestamps should be uint64'); -end - -fid = fopen(filename, 'wb', 'ieee-le'); - -% construct the header -buf = []; -buf = [buf sprintf('######## Neuralynx Data File Header\r\n')]; -buf = [buf sprintf('## File Name: %s\r\n', filename)]; -buf = [buf sprintf('## Time Opened: (m/d/y): %s At Time: %s\r\n', datestr(clock, 'mm/dd/yy'), datestr(clock, 'HH:MM:SS'))]; -f = fieldnames(nts.hdr); -for i=1:length(f) - v = getfield(nts.hdr, f{i}); - switch class(v) - case 'char' - buf = [buf sprintf('-%s\t%s\r\n', f{i}, v)]; - case 'double' - buf = [buf sprintf('-%s\t%g\r\n', f{i}, v)]; - otherwise - error('unknown class in writing header'); - end -end - -% pad the rest of the header with zeros and write it to file -buf((end+1):16384) = 0; -fwrite(fid, buf); - -% The format of a clustered electrode record is -% int64 TimeStamp - -fwrite(fid, nts.TimeStamp, 'uint64'); - -% close the file -fclose(fid); - - - diff --git a/external/fieldtrip/private/write_plexon_nex.m b/external/fieldtrip/private/write_plexon_nex.m new file mode 100644 index 0000000..09456aa --- /dev/null +++ b/external/fieldtrip/private/write_plexon_nex.m @@ -0,0 +1,215 @@ +function write_plexon_nex(filename, nex) + +% WRITE_PLEXON_NEX writes a Plexon *.nex file, which is a file +% containing action-potential (spike) timestamps and waveforms (spike +% channels), event timestamps (event channels), and continuous variable +% data (continuous A/D channels). +% +% Use as +% write_plexon_nex(filename, nex); +% +% The data structure should contain +% nex.hdr.FileHeader.Frequency = TimeStampFreq +% nex.hdr.VarHeader.Type = type, 5 for continuous +% nex.hdr.VarHeader.Name = label, padded to length 64 +% nex.hdr.VarHeader.WFrequency = sampling rate of continuous channel +% nex.var.dat = data +% nex.var.ts = timestamps +% +% See also READ_PLEXON_NEX, READ_PLEXON_PLX, READ_PLEXON_DDT + +% Copyright (C) 2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: write_plexon_nex.m 945 2010-04-21 17:41:20Z roboos $ + +% get the optional arguments, these are all required +% FirstTimeStamp = keyval('FirstTimeStamp', varargin); +% TimeStampFreq = keyval('TimeStampFreq', varargin); + +hdr = nex.hdr; + +UVtoMV = 1/1000; + +switch hdr.VarHeader.Type + case 5 + dat = nex.var.dat; % this is in microVolt + buf = zeros(size(dat), 'int16'); + nchans = size(dat,1); + nsamples = size(dat,2); + nwaves = 1; % only one continuous datasegment is supported + if length(hdr.VarHeader)~=nchans + error('incorrect number of channels'); + end + % convert the data from floating point into int16 values + % each channel gets its own optimal calibration factor + for varlop=1:nchans + ADMaxValue = double(intmax('int16')); + ADMaxUV = max(abs(dat(varlop,:))); % this is in microVolt + ADMaxMV = ADMaxUV/1000; % this is in miliVolt + if isa(dat, 'int16') + % do not rescale data that is already 16 bit + MVtoAD = 1; + elseif ADMaxMV==0 + % do not rescale the data if the data is zero + MVtoAD = 1; + elseif ADMaxMV>0 + % rescale the data so that it fits into the 16 bits with as little loss as possible + MVtoAD = ADMaxValue / ADMaxMV; + end + buf(varlop,:) = int16(double(dat) * UVtoMV * MVtoAD); + % remember the calibration value, it should be stored in the variable header + ADtoMV(varlop) = 1/MVtoAD; + end + dat = buf; + clear buf; + + case 3 + dat = nex.var.dat; % this is in microVolt + nchans = 1; % only one channel is supported + nsamples = size(dat,1); + nwaves = size(dat,2); + if length(hdr.VarHeader)~=nchans + error('incorrect number of channels'); + end + % convert the data from floating point into int16 values + ADMaxValue = double(intmax('int16')); + ADMaxUV = max(abs(dat(:))); % this is in microVolt + ADMaxMV = ADMaxUV/1000; % this is in miliVolt + if isa(dat, 'int16') + % do not rescale data that is already 16 bit + MVtoAD = 1; + elseif ADMaxMV==0 + % do not rescale the data if the data is zero + MVtoAD = 1; + elseif ADMaxMV>0 + % rescale the data so that it fits into the 16 bits with as little loss as possible + MVtoAD = ADMaxValue / ADMaxMV; + end + dat = int16(double(dat) * UVtoMV * MVtoAD); + % remember the calibration value, it should be stored in the variable header + ADtoMV = 1/MVtoAD; + + otherwise + error('unsupported data type') +end % switch type + +% determine the first and last timestamp +ts = nex.var.ts; +ts_beg = min(ts); +ts_end = 0; % FIXME + +fid = fopen(filename, 'wb', 'ieee-le'); + +% write the file header +write_NexFileHeader; + +% write the variable headers +for varlop=1:nchans + write_NexVarHeader; +end + +% write the variable data +for varlop=1:nchans + write_NexVarData; +end + +fclose(fid); +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% nested function for writing the details +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + function write_NexFileHeader + % prepare the two char buffers + buf1 = padstr('$Id: write_plexon_nex.m 945 2010-04-21 17:41:20Z roboos $', 256); + buf2 = char(zeros(1, 256)); + % write the stuff to the file + fwrite(fid, 'NEX1' , 'char'); % NexFileHeader = string NEX1 + fwrite(fid, 100 , 'int32'); % Version = version + fwrite(fid, buf1 , 'char'); % Comment = comment, 256 bytes + fwrite(fid, hdr.FileHeader.Frequency, 'double'); % Frequency = timestamped freq. - tics per second + fwrite(fid, ts_beg, 'int32'); % Beg = usually 0, minimum of all the timestamps in the file + fwrite(fid, ts_end, 'int32'); % End = maximum timestamp + 1 + fwrite(fid, nchans, 'int32'); % NumVars = number of variables in the first batch + fwrite(fid, 0 , 'int32'); % NextFileHeader = position of the next file header in the file, not implemented yet + fwrite(fid, buf2 , 'char'); % Padding = future expansion + end % of the nested function + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% nested function for writing the details +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + function write_NexVarHeader + filheadersize = 544; + varheadersize = 208; + offset = filheadersize + nchans*varheadersize + (varlop-1)*nsamples; + calib = ADtoMV(varlop); + % prepare the two char buffers + buf1 = padstr(hdr.VarHeader(varlop).Name, 64); + buf2 = char(zeros(1, 68)); + % write the continuous variable to the file + fwrite(fid, hdr.VarHeader.Type, 'int32'); % Type = 0 - neuron, 1 event, 2- interval, 3 - waveform, 4 - pop. vector, 5 - continuously recorded + fwrite(fid, 100, 'int32'); % Version = 100 + fwrite(fid, buf1, 'char'); % Name = variable name, 1x64 char + fwrite(fid, offset, 'int32'); % DataOffset = where the data array for this variable is located in the file + fwrite(fid, nwaves, 'int32'); % Count = number of events, intervals, waveforms or weights + fwrite(fid, 0, 'int32'); % WireNumber = neuron only, not used now + fwrite(fid, 0, 'int32'); % UnitNumber = neuron only, not used now + fwrite(fid, 0, 'int32'); % Gain = neuron only, not used now + fwrite(fid, 0, 'int32'); % Filter = neuron only, not used now + fwrite(fid, 0, 'double'); % XPos = neuron only, electrode position in (0,100) range, used in 3D + fwrite(fid, 0, 'double'); % YPos = neuron only, electrode position in (0,100) range, used in 3D + fwrite(fid, hdr.VarHeader.WFrequency, 'double'); % WFrequency = waveform and continuous vars only, w/f sampling frequency + fwrite(fid, calib, 'double'); % ADtoMV = waveform continuous vars only, coeff. to convert from A/D values to Millivolts + fwrite(fid, nsamples, 'int32'); % NPointsWave = waveform only, number of points in each wave + fwrite(fid, 0, 'int32'); % NMarkers = how many values are associated with each marker + fwrite(fid, 0, 'int32'); % MarkerLength = how many characters are in each marker value + fwrite(fid, buf2, 'char'); % Padding, 1x68 char + end % of the nested function + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% nested function for writing the details +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + function write_NexVarData + switch hdr.VarHeader.Type + case 5 + % this code only supports one continuous segment + index = 0; + fwrite(fid, ts , 'int32'); % timestamps, one for each continuous segment + fwrite(fid, index , 'int32'); % where to cut the segments, zero offset + fwrite(fid, dat(varlop,:) , 'int16'); % data + case 3 + fwrite(fid, ts , 'int32'); % timestamps, one for each spike + fwrite(fid, dat , 'int16'); % waveforms, one for each spike + otherwise + error('unsupported data type'); + end % switch + end % of the nested function + +end % of the primary function + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% subfunction for zero padding a char array to fixed length +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function str = padstr(str, num); +if length(str)>num + str = str(1:num); +else + str((end+1):num) = 0; +end +end % of the padstr subfunction diff --git a/external/fieldtrip/private/yokogawa2grad.m b/external/fieldtrip/private/yokogawa2grad.m index 379affd..3431688 100644 --- a/external/fieldtrip/private/yokogawa2grad.m +++ b/external/fieldtrip/private/yokogawa2grad.m @@ -8,33 +8,31 @@ % Copyright (C) 2005-2008, Robert Oostenveld % -% $Log: yokogawa2grad.m,v $ -% Revision 1.1 2009/01/14 09:12:16 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.5 2008/12/24 13:49:25 roboos -% added suggested changes by Kaoru Amano, see email 19 Dec 2008 +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.4 2008/12/18 11:53:20 roboos -% changed some comments and some slight cleanups, no functional change +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.3 2008/12/18 08:31:23 roboos -% incorporated gradiometer, thanks to Kaoru Amano +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % -% Revision 1.2 2008/05/15 13:20:36 roboos -% updated documentation -% -% Revision 1.1 2006/08/31 13:32:11 roboos -% moved from fieldtrip to fileio module -% -% Revision 1.1 2005/09/06 08:54:30 roboos -% new implementations for the Yokogawa 160 channel MEG system +% $Id: yokogawa2grad.m 1246 2010-06-17 09:35:04Z tilsan $ +if ~hasyokogawa('16bitBeta6') + error('cannot determine whether Yokogawa toolbox is present'); +end + +if isfield(hdr, 'label') + label = hdr.label; % keep for later use +end if isfield(hdr, 'orig') hdr = hdr.orig; % use the original header, not the FieldTrip header @@ -47,18 +45,23 @@ % 4 position y (in m) % 5 position z (in m) % 6 orientation of first coil (theta in deg) -% 7 orientation from the 1st to 2nd coil for gradiometer (theta in deg) -% 8 orientation of first coil (phi in deg) +% 7 orientation of first coil (phi in deg) +% 8 orientation from the 1st to 2nd coil for gradiometer (theta in deg) % 9 orientation from the 1st to 2nd coil for gradiometer (phi in deg) % 10 coil size (in m) % 11 baseline (in m) handles = definehandles; -isgrad = (hdr.channel_info(:,2)==handles.AxialGradioMeter | hdr.channel_info(:,2)==handles.PlannerGradioMeter); +isgrad = (hdr.channel_info(:,2)==handles.AxialGradioMeter | ... + hdr.channel_info(:,2)==handles.PlannerGradioMeter | hdr.channel_info(:,2)==handles.MagnetoMeter | ... + hdr.channel_info(:,2)==handles.RefferenceAxialGradioMeter | hdr.channel_info(:,2)==handles.RefferencePlannerGradioMeter | ... + hdr.channel_info(:,2)==handles.RefferenceMagnetoMeter); +isgrad_handles = hdr.channel_info(isgrad,2); +ismag = (isgrad_handles(:)==handles.MagnetoMeter | isgrad_handles(:)==handles.RefferenceMagnetoMeter); grad.pnt = hdr.channel_info(isgrad,3:5)*100; % cm % Get orientation of the 1st coil -ori_1st = hdr.channel_info(find(isgrad),[6 8]); +ori_1st = hdr.channel_info(find(isgrad),[6 7]); % polar to x,y,z coordinates ori_1st = ... [sin(ori_1st(:,1)/180*pi).*cos(ori_1st(:,2)/180*pi) ... @@ -67,7 +70,7 @@ grad.ori = ori_1st; % Get orientation from the 1st to 2nd coil for gradiometer -ori_1st_to_2nd = hdr.channel_info(find(isgrad),[7 9]); +ori_1st_to_2nd = hdr.channel_info(find(isgrad),[8 9]); % polar to x,y,z coordinates ori_1st_to_2nd = ... [sin(ori_1st_to_2nd(:,1)/180*pi).*cos(ori_1st_to_2nd(:,2)/180*pi) ... @@ -77,28 +80,53 @@ baseline = hdr.channel_info(isgrad,size(hdr.channel_info,2)); % Define the location and orientation of 2nd coil +info = hdr.channel_info(isgrad,2); for i=1:sum(isgrad) - if hdr.channel_info(i,2) == handles.AxialGradioMeter + if (info(i) == handles.AxialGradioMeter || info(i) == handles.RefferenceAxialGradioMeter ) grad.pnt(i+sum(isgrad),:) = [grad.pnt(i,:)+ori_1st(i,:)*baseline(i)*100]; grad.ori(i+sum(isgrad),:) = -ori_1st(i,:); - elseif hdr.channel_info(i,2) == handles.PlannerGradioMeter + elseif (info(i) == handles.PlannerGradioMeter || info(i) == handles.RefferencePlannerGradioMeter) grad.pnt(i+sum(isgrad),:) = [grad.pnt(i,:)+ori_1st_to_2nd(i,:)*baseline(i)*100]; - grad.ori(i+sum(isgrad),:) = ori_1st(i,:); + grad.ori(i+sum(isgrad),:) = -ori_1st(i,:); + else + grad.pnt(i+sum(isgrad),:) = [0 0 0]; + grad.ori(i+sum(isgrad),:) = [0 0 0]; end end % Define the pair of 1st and 2nd coils for each gradiometer grad.tra = repmat(diag(ones(1,size(grad.pnt,1)/2),0),1,2); +% for mangetometers change tra as there is no second coil +if any(ismag) + sz_pnt = size(grad.pnt,1)/2; + % create logical variable + not_2nd_coil = ([diag(zeros(sz_pnt),0)' ismag']~=0); + grad.tra(ismag,not_2nd_coil) = 0; +end + % Make the matrix sparse to speed up the multiplication in the forward % computation with the coil-leadfield matrix to get the channel leadfield grad.tra = sparse(grad.tra); -tmp = hdr.channel_info(isgrad,1); -for i=1:size(tmp,1) - grad.label{i,1} = num2str(tmp(i)+1); +% the gradiometer labels should be consistent with the channel labels in +% read_yokogawa_header, the predefined list of channel names in ft_senslabel +% and with ft_channelselection +% ONLY consistent with read_yokogawa_header as NO FIXED relation between +% channel index and type of channel exists for Yokogawa systems. Therefore +% all have individual label sequences: No useful support in ft_senslabel possible +if ~isempty(label) + grad.label = label(isgrad); +else + % this is only backup, if something goes wrong above. + label = cell(size(isgrad)); + for i=1:length(label) + label{i} = sprintf('AG%03d', i); + end + grad.label = label(isgrad); end -grad.unit='cm'; +grad.unit = 'cm'; + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % this defines some usefull constants @@ -120,9 +148,9 @@ handles.EcgChannel = -3; handles.EtcChannel = -4; handles.NonMegChannelNameLength = 32; -handles.DefaultMagnetometerSize = (4.0/1000.0); % ????4.0mm???????` -handles.DefaultAxialGradioMeterSize = (15.5/1000.0); % ???a15.5mm???~?? -handles.DefaultPlannerGradioMeterSize = (12.0/1000.0); % ????12.0mm???????` +handles.DefaultMagnetometerSize = (4.0/1000.0); % ????4.0mm???????` +handles.DefaultAxialGradioMeterSize = (15.5/1000.0); % ???a15.5mm???~?? +handles.DefaultPlannerGradioMeterSize = (12.0/1000.0); % ????12.0mm???????` handles.AcqTypeContinuousRaw = 1; handles.AcqTypeEvokedAve = 2; handles.AcqTypeEvokedRaw = 3; diff --git a/external/fieldtrip/private/yokogawa2vol.m b/external/fieldtrip/private/yokogawa2vol.m deleted file mode 100644 index c5b01f6..0000000 --- a/external/fieldtrip/private/yokogawa2vol.m +++ /dev/null @@ -1,23 +0,0 @@ -function [vol] = yokogawa2vol(hdr); - -% YOKOGAWA2VOL converts a spherical volume conductor model that can -% be present in the header of a datafile into a structure that can -% be used by FieldTrip. - -% Copyright (C) 2005, Robert Oostenveld -% -% $Log: yokogawa2vol.m,v $ -% Revision 1.1 2005/09/06 08:54:30 roboos -% new implementations for the Yokogawa 160 channel MEG system -% - -% hdr = read_yokogawa_header(filename); -hdr = hdr.orig; % use the original Yokogawa header, not the FieldTrip header - -if isfield(hdr.mri_info, 'model_name') && strcmp(hdr.mri_info.model_name, 'SphericalModel') - % single sphere volume conduction model - vol.r = hdr.mri_info.r; - vol.o = [hdr.mri_info.cx hdr.mri_info.cy hdr.mri_info.cz]; -else - error('unsupported volume conductor model'); -end diff --git a/external/fieldtrip/public/cfg2keyval.m b/external/fieldtrip/public/cfg2keyval.m new file mode 100644 index 0000000..4cde73d --- /dev/null +++ b/external/fieldtrip/public/cfg2keyval.m @@ -0,0 +1,34 @@ +function [optarg] = cfg2keyval(cfg); + +% CFG2KEYVAL converts between a structure and a cell-array with key-value +% pairs which can be used for optional input arguments. +% +% Use as +% [optarg] = cfg2keyval(cfg) + +% Copyright (C) 2006, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: cfg2keyval.m 951 2010-04-21 18:24:01Z roboos $ + +if ~isempty(cfg) + optarg = [fieldnames(cfg) struct2cell(cfg)]'; + optarg = optarg(:)'; +else + optarg = {}; +end diff --git a/external/fieldtrip/private/checkconfig.m b/external/fieldtrip/public/checkconfig.m similarity index 80% rename from external/fieldtrip/private/checkconfig.m rename to external/fieldtrip/public/checkconfig.m index 2b71823..d2431eb 100644 --- a/external/fieldtrip/private/checkconfig.m +++ b/external/fieldtrip/public/checkconfig.m @@ -43,134 +43,23 @@ % Copyright (C) 2007-2008, Robert Oostenveld, Saskia Haegens % -% $Log: checkconfig.m,v $ -% Revision 1.18 2009/08/05 13:03:55 roboos -% changed selection of file based on 'gui' +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.17 2009/07/15 12:10:07 jansch -% added subspace and keepsubspace for subcfg dics and lcmv +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.16 2009/06/04 13:41:33 marvger -% renamed mvlap case +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.15 2009/05/22 13:20:18 marvger -% added case for mvlap method -% -% Revision 1.14 2009/05/14 18:54:39 roboos -% added sam for createsubcfg -% -% Revision 1.13 2009/04/03 08:09:31 jansch -% added denoise for preproc and subspace -% -% Revision 1.12 2009/03/12 17:10:38 roboos -% fixed bug in cfg.dataformat/headerformat (dataset2files) which applied to vhdr as input filename with a *.seg containing the data -% -% Revision 1.11 2009/02/04 09:09:59 roboos -% fixed filename to headerfile/datafile cvonversion in case of ctf_old -% -% Revision 1.10 2009/01/21 11:27:02 marvger -% automatically set dataformat and headerformat if unspecified -% -% Revision 1.9 2009/01/20 15:55:54 sashae -% cfg.trkcfgcount keeps track of number of times that trackconfig has been turned on/off, -% to prevent that nested functions turn off configtracking (i.e. only at end of the main function -% report/cleanup should be given) -% -% Revision 1.8 2009/01/20 13:01:31 sashae -% changed configtracking such that it is only enabled when BOTH explicitly allowed at start -% of the fieldtrip function AND requested by the user -% in all other cases configtracking is disabled -% -% Revision 1.7 2008/12/16 15:37:23 sashae -% if cfg.checkconfig='silent' do not display report for trackconfig -% -% Revision 1.6 2008/12/04 19:11:11 sashae -% added silent/loose/pedantic feedback for 'renamed' and 'renamedval' -% -% Revision 1.5 2008/12/04 11:47:03 jansch -% added fixedori when beamformer_dics -% -% Revision 1.4 2008/12/02 17:51:28 sashae -% added artfctdef to 'ignorefields' -% -% Revision 1.3 2008/11/21 13:16:10 jansch -% added fixedori to be passed on in the case of lcmv (thanks to Joachim). -% -% Revision 1.2 2008/11/21 10:14:30 sashae -% added list of fields that should be ignored by trackconfig and checksize -% -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.21 2008/11/12 11:20:52 sashae -% change in configtracking: now ignores cfg.checksize -% -% Revision 1.20 2008/11/11 18:29:45 sashae -% some changes in configtracking -% -% Revision 1.19 2008/11/11 15:24:16 sashae -% updated documentation, improved checksize -% -% Revision 1.18 2008/11/11 13:12:59 roboos -% added/improved size checking -% -% Revision 1.17 2008/11/11 10:40:59 sashae -% first implementation of checksize: checks for large fields in the cfg and removes them -% -% Revision 1.16 2008/11/10 12:16:12 roboos -% clarified the handling of the configuration tracking options -% -% Revision 1.15 2008/11/06 15:19:23 sashae -% several updates in configuration tracking -% -% Revision 1.14 2008/11/02 10:56:34 roboos -% explicit sharing of code for dataset2files with fileio read_header/data -% -% Revision 1.13 2008/10/28 19:20:18 sashae -% configtracking can be turned on/off with trackconfig. -% user can request report on unused options with cfg.trackconfig='report', or get cleaned cfg with cfg.trackconfig='cleanup'. -% -% Revision 1.12 2008/10/13 13:38:59 sashae -% change in dataset2files code: empty dataset/headerfile/datafile fields are removed -% -% Revision 1.11 2008/10/13 12:41:33 jansch -% added projectmom for lcmv (in contrast to pcc the projection is done within -% beamformer_lcmv, instead of in sourcedescriptives). Probably this should -% change back when a clean version of sourcedescriptives is implemented. -% -% Revision 1.10 2008/10/10 12:33:04 sashae -% incorporated dataset2files -% -% Revision 1.9 2008/10/10 10:50:34 sashae -% updated documentation -% -% Revision 1.8 2008/10/02 14:06:21 roboos -% get the fields from ft_default and add them to the cfg structure -% implemented cfg.checkconfig=silent/loose/pedantic (default is in ft_default, i.e. fieldtripdefs function) -% -% Revision 1.7 2008/10/02 12:35:14 roboos -% added option "unused", renamed tracking to configtracking -% -% Revision 1.6 2008/10/01 15:45:29 sashae -% incorporated createsubcfg -% -% Revision 1.5 2008/09/30 13:05:19 roboos -% adedd first version of configuration tracking for testing -% -% Revision 1.4 2008/09/23 12:05:33 sashae -% some small changes; checkconfig can now handle empty cfgs -% -% Revision 1.3 2008/09/18 10:01:57 sashae -% added 'renamedval' which checks/adjusts renamed values -% -% Revision 1.2 2008/09/18 08:33:48 sashae -% new version: checks required, renamed, deprecated and forbidden configuration options, -% adjusts where possible and gives warning/error messages. to be implemented in all main -% fieldtrip functions, comparable to checkdata -% -% Revision 1.1 2008/07/08 15:39:22 roboos -% initial version for Saskia to work on +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: checkconfig.m 1357 2010-07-06 08:33:38Z roboos $ if isempty(cfg) cfg = struct; % ensure that it is an empty struct, not empty double @@ -251,9 +140,9 @@ if silent % don't mention it elseif loose - warning(sprintf('use cfg.%s=%s instead of cfg.%s=%s', renamedval{1}, renamedval{3}, renamedval{1}, renamedval{2})); + warning(sprintf('use cfg.%s=''%s'' instead of cfg.%s=''%s''', renamedval{1}, renamedval{3}, renamedval{1}, renamedval{2})); elseif pedantic - error(sprintf('use cfg.%s=%s instead of cfg.%s=%s', renamedval{1}, renamedval{3}, renamedval{1}, renamedval{2})); + error(sprintf('use cfg.%s=''%s'' instead of cfg.%s=''%s''', renamedval{1}, renamedval{3}, renamedval{1}, renamedval{2})); end end end @@ -361,7 +250,7 @@ 'bsfiltord' 'bsfilttype' 'bsfreq' - 'denoise' + 'denoise' 'dftfilter' 'dftfreq' 'hpfiltdir' @@ -412,8 +301,8 @@ 'reducerank' 'keepcsd' 'realfilter' - 'subspace' - 'keepsubspace' + 'subspace' + 'keepsubspace' }; case 'lcmv' @@ -430,8 +319,8 @@ 'projectmom' 'reducerank' 'keepcov' - 'subspace' - 'keepsubspace' + 'subspace' + 'keepsubspace' }; case 'pcc' @@ -459,7 +348,7 @@ 'feedback' 'numcomponent' }; - + case 'sam' fieldname = { 'meansphereorigin' @@ -473,7 +362,7 @@ case 'mvl' fieldname = {}; - + otherwise error('unexpected name of the subfunction'); fieldname = {}; @@ -527,7 +416,7 @@ filename = cfg.dataset; datafile = []; headerfile = []; - switch filetype(filename) + switch ft_filetype(filename) case '4d_pdf' datafile = filename; headerfile = [datafile '.m4d']; @@ -600,10 +489,28 @@ [path, file, ext] = fileparts(filename); headerfile = fullfile(path, [file '.vhdr']); datafile = fullfile(path, [file '.dat']); + case 'itab_raw' + [path, file, ext] = fileparts(filename); + headerfile = fullfile(path, [file '.raw.mhd']); + datafile = fullfile(path, [file '.raw']); case 'fcdc_matbin' [path, file, ext] = fileparts(filename); headerfile = fullfile(path, [file '.mat']); datafile = fullfile(path, [file '.bin']); + case {'tdt_tsq' 'tdt_tev'} + [path, file, ext] = fileparts(filename); + headerfile = fullfile(path, [file '.tsq']); + datafile = fullfile(path, [file '.tev']); + case 'nmc_archive_k' + [path, file, ext] = fileparts(filename); + headerfile = [path '/' file 'newparams.txt']; + if isempty(headerformat) + headerformat = 'nmc_archive_k'; + end + if isempty(hdr) + hdr = ft_read_header(headerfile, 'headerformat', headerformat); + end + datafile = filename; otherwise % convert filename into filenames, assume that the header and data are the same datafile = filename; @@ -617,14 +524,14 @@ % fill dataformat if unspecified if ~isfield(cfg,'dataformat') || isempty(cfg.dataformat) - cfg.dataformat = filetype(datafile); + cfg.dataformat = ft_filetype(datafile); end % fill dataformat if unspecified if ~isfield(cfg,'headerformat') || isempty(cfg.headerformat) - cfg.headerformat = filetype(headerfile); + cfg.headerformat = ft_filetype(headerfile); end - + elseif ~isempty(cfg.datafile) && isempty(cfg.headerfile); % assume that the datafile also contains the header cfg.headerfile = cfg.datafile; diff --git a/external/fieldtrip/public/checkdata.m b/external/fieldtrip/public/checkdata.m new file mode 100644 index 0000000..58b9232 --- /dev/null +++ b/external/fieldtrip/public/checkdata.m @@ -0,0 +1,854 @@ +function [data] = checkdata(data, varargin) + +% CHECKDATA checks the input data of the main FieldTrip functions, e.g. whether +% the type of data strucure corresponds with the required data. If neccessary +% and possible, this function will adjust the data structure to the input +% requirements (e.g. change dimord, average over trials, convert inside from +% index into logical). +% +% If the input data does NOT correspond to the requirements, this function +% is supposed to give a elaborate warning message and if applicable point +% the user to external documentation (link to website). +% +% Use as +% [data] = checkdata(data, ...) +% +% Optional input arguments should be specified as key-value pairs and can include +% feedback = yes, no +% datatype = raw, freq, timelock, comp, spike, source, volume, dip +% dimord = any combination of time, freq, chan, refchan, rpt, subj, chancmb, rpttap, pos +% senstype = ctf151, ctf275, ctf151_planar, ctf275_planar, neuromag122, neuromag306, bti148, bti248, bti248_planar, magnetometer, electrode +% inside = logical, index +% ismeg = yes, no +% hastrials = yes, no +% hasunits = yes, no +% hastrialdef = yes, no +% hasoffset = yes, no (only applies to raw data) +% hascumtapcnt = yes, no (only applies to freq data) +% hasdof = yes, no +% cmbrepresentation = sparse, full (applies to covariance and cross-spectral density) +% +% For some options you can specify multiple values, e.g. +% [data] = checkdata(data, 'senstype', {'ctf151', 'ctf275'}), e.g. in megrealign +% [data] = checkdata(data, 'datatype', {'timelock', 'freq'}), e.g. in sourceanalysis + +% Copyright (C) 2007-2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: checkdata.m 1028 2010-05-04 10:47:38Z jansch $ + +% in case of an error this function could use dbstack for more detailled +% user feedback +% +% this function should replace/encapsulate +% fixdimord +% fixinside +% fixprecision +% fixvolume +% data2raw +% raw2data +% grid2transform +% transform2grid +% fourier2crsspctrm +% freq2cumtapcnt +% sensortype +% time2offset +% offset2time +% +% other potential uses for this function: +% time -> offset in freqanalysis +% average over trials +% csd as matrix + +% get the optional input arguments +feedback = keyval('feedback', varargin); if isempty(feedback), feedback = 'no'; end +dtype = keyval('datatype', varargin); % should not conflict with the datatype function +dimord = keyval('dimord', varargin); +stype = keyval('senstype', varargin); % senstype is a function name which should not be masked +ismeg = keyval('ismeg', varargin); +inside = keyval('inside', varargin); % can be logical or index +hastrials = keyval('hastrials', varargin); +hasunits = keyval('hasunits', varargin); +hastrialdef = keyval('hastrialdef', varargin); if isempty(hastrialdef), hastrialdef = 'no'; end +hasoffset = keyval('hasoffset', varargin); if isempty(hasoffset), hasoffset = 'no'; end +hasdimord = keyval('hasdimord', varargin); if isempty(hasdimord), hasdimord = 'no'; end +hascumtapcnt = keyval('hascumtapcnt', varargin); +hasdof = keyval('hasdof', varargin); if isempty(hasdof), hasdof = 'no'; end +haspow = keyval('haspow', varargin); if isempty(haspow), haspow = 'no'; end +cmbrepresentation = keyval('cmbrepresentation', varargin); +channelcmb = keyval('channelcmb', varargin); +sourcedimord = keyval('sourcedimord', varargin); +sourcerepresentation = keyval('sourcerepresentation', varargin); +keepoutside = keyval('keepoutside', varargin); + +% determine the type of input data +% this can be raw, freq, timelock, comp, spike, source, volume, dip +israw = datatype(data, 'raw'); +isfreq = datatype(data, 'freq'); +istimelock = datatype(data, 'timelock'); +iscomp = datatype(data, 'comp'); +isspike = datatype(data, 'spike'); +isvolume = datatype(data, 'volume'); +issource = datatype(data, 'source'); +isdip = datatype(data, 'dip'); +ismvar = datatype(data, 'mvar'); +isfreqmvar = datatype(data, 'freqmvar'); + +% FIXME use the istrue function on ismeg and hasxxx options + +if ~isequal(feedback, 'no') + if israw + nchan = length(data.label); + ntrial = length(data.trial); + fprintf('the input is raw data with %d channels and %d trials\n', nchan, ntrial); + elseif isfreq + nchan = length(data.label); + nfreq = length(data.freq); + if isfield(data, 'time'), ntime = num2str(length(data.time)); else ntime = 'no'; end + fprintf('the input is freq data with %d channels, %d frequencybins and %s timebins\n', nchan, nfreq, ntime); + elseif istimelock + nchan = length(data.label); + ntime = length(data.time); + fprintf('the input is timelock data with %d channels and %d timebins\n', nchan, ntime); + elseif iscomp + ncomp = length(data.label); + nchan = length(data.topolabel); + fprintf('the input is component data with %d components and %d original channels\n', ncomp, nchan); + elseif isspike + nchan = length(data.label); + fprintf('the input is spike data\n'); + elseif isvolume + fprintf('the input is volume data with dimensions [%d %d %d]\n', data.dim(1), data.dim(2), data.dim(3)); + elseif issource + nsource = size(data.pos, 1); + fprintf('the input is source data with %d positions\n', nsource); + elseif isdip + fprintf('the input is dipole data\n'); + elseif ismvar + fprintf('the input is mvar data\n'); + elseif isfreqmvar + fprintf('the input is freqmvar data\n'); + end +end % give feedback + +if isfreq || istimelock || iscomp || issource || isvolume + % ensure consistency between the dimord string and the axes that describe the data dimensions + data = fixdimord(data, strcmp(sourcerepresentation, 'new')); +end + +if istimelock + % remove the unwanted fields + if isfield(data, 'numsamples'), data = rmfield(data, 'numsamples'); end + if isfield(data, 'numcovsamples'), data = rmfield(data, 'numcovsamples'); end + if isfield(data, 'numblcovsamples'), data = rmfield(data, 'numblcovsamples'); end +end + +if issource && isvolume + % it should be either one or the other + % the choice here is to represent it as volume description since that is simpler to handle + % remove the unwanted fields + if isfield(data, 'pos'), data = rmfield(data, 'pos'); end + if isfield(data, 'xgrid'), data = rmfield(data, 'xgrid'); end + if isfield(data, 'ygrid'), data = rmfield(data, 'ygrid'); end + if isfield(data, 'zgrid'), data = rmfield(data, 'zgrid'); end + issource = false; +end + +if issource || isvolume + % these don't contain a dimord in the old representation + % but in the frequency domain case they could + % contain a .frequency field rather than a .freq field + if isfield(data, 'frequency'), + data.freq = data.frequency; + data = rmfield(data, 'frequency'); + end +end + +if ~isempty(dtype) + if ~isa(dtype, 'cell') + dtype = {dtype}; + end + + okflag = 0; + for i=1:length(dtype) + % check that the data matches with one or more of the required datatypes + switch dtype{i} + case 'raw' + okflag = okflag + israw; + case 'freq' + okflag = okflag + isfreq; + case 'timelock' + okflag = okflag + istimelock; + case 'comp' + okflag = okflag + iscomp; + case 'spike' + okflag = okflag + isspike; + case 'volume' + okflag = okflag + isvolume; + case 'source' + okflag = okflag + issource; + case 'dip' + okflag = okflag + isdip; + case 'mvar' + okflag = okflag + ismvar; + case 'freqmvar' + okflag = okflag + isfreqmvar; + end % switch dtype + end % for dtype + + if ~okflag + % try to convert the data + for iCell = 1:length(dtype) + if isequal(dtype(iCell), {'source'}) && isvolume + data = volume2source(data); + isvolume = 0; + issource = 1; + okflag = 1; + elseif isequal(dtype(iCell), {'volume'}) && issource + data = source2volume(data); + isvolume = 1; + issource = 0; + okflag = 1; + elseif isequal(dtype(iCell), {'raw'}) && issource + data = data2raw(data); + issource = 0; + israw = 1; + okflag = 1; + elseif isequal(dtype(iCell), {'raw'}) && istimelock + data = timelock2raw(data); + istimelock = 0; + israw = 1; + okflag = 1; + elseif isequal(dtype(iCell), {'timelock'}) && israw + data = raw2timelock(data); + israw = 0; + istimelock = 1; + okflag = 1; + elseif isequal(dtype(iCell), {'raw'}) && isfreq + data = freq2raw(data); + isfreq = 0; + israw = 1; + okflag = 1; + elseif isequal(dtype(iCell), {'raw'}) && iscomp + data = comp2raw(data); + iscomp = 0; + israw = 1; + okflag = 1; + end + end % for iCell + end % if okflag + + if ~okflag + % construct an error message + if length(dtype)>1 + str = sprintf('%s, ', dtype{1:(end-2)}); + str = sprintf('%s%s or %s', str, dtype{end-1}, dtype{end}); + else + str = dtype{1}; + end + str = sprintf('This function requires %s data as input.', str); + error(str); + end % if okflag +end + +if ~isempty(dimord) + if ~isa(dimord, 'cell') + dimord = {dimord}; + end + + if isfield(data, 'dimord') + okflag = any(strcmp(data.dimord, dimord)); + else + okflag = 0; + end + + if ~okflag + % construct an error message + if length(dimord)>1 + str = sprintf('%s, ', dimord{1:(end-2)}); + str = sprintf('%s%s or %s', str, dimord{end-1}, dimord{end}); + else + str = dimord{1}; + end + str = sprintf('This function requires data with a dimord of %s.', str); + error(str); + end % if okflag +end + +if ~isempty(stype) + if ~isa(stype, 'cell') + stype = {stype}; + end + + if isfield(data, 'grad') || isfield(data, 'elec') + if any(strcmp(ft_senstype(data), stype)); + okflag = 1; + else + okflag = 0; + end + else + okflag = 0; + end + + if ~okflag + % construct an error message + if length(stype)>1 + str = sprintf('%s, ', stype{1:(end-2)}); + str = sprintf('%s%s or %s', str, stype{end-1}, stype{end}); + else + str = stype{1}; + end + str = sprintf('This function requires %s data as input, but you are giving %s data.', str, ft_senstype(data)); + error(str); + end % if okflag +end + +if ~isempty(ismeg) + if isequal(ismeg, 'yes') + okflag = isfield(data, 'grad'); + elseif isequal(ismeg, 'no') + okflag = ~isfield(data, 'grad'); + end + + if ~okflag && isequal(ismeg, 'yes') + error('This function requires MEG data with a ''grad'' field'); + elseif ~okflag && isequal(ismeg, 'no') + error('This function should not be given MEG data with a ''grad'' field'); + end % if okflag +end + +if ~isempty(inside) + % TODO absorb the fixinside function into this code + data = fixinside(data, inside); + okflag = isfield(data, 'inside'); + + if ~okflag + % construct an error message + error('This function requires data with an ''inside'' field.'); + end % if okflag +end + +%if isvolume +% % ensure consistent dimensions of the volumetric data +% % reshape each of the volumes that is found into a 3D array +% param = parameterselection('all', data); +% dim = data.dim; +% for i=1:length(param) +% tmp = getsubfield(data, param{i}); +% tmp = reshape(tmp, dim); +% data = setsubfield(data, param{i}, tmp); +% end +%end + +if issource || isvolume, + % these are not used any more + if isfield(data, 'xgrid'), data = rmfield(data, 'xgrid'); end + if isfield(data, 'ygrid'), data = rmfield(data, 'ygrid'); end + if isfield(data, 'zgrid'), data = rmfield(data, 'zgrid'); end + + if isequal(hasunits, 'yes') && ~isfield(data, 'units') + % calling convert_units with only the input data adds the units without converting + data = ft_convert_units(data); + end + + % the following section is to make a dimord-consistent representation of + % volume and source data, taking trials, time and frequency into account + if isequal(hasdimord, 'yes') && (~isfield(data, 'dimord') || ~strcmp(data.dimord,sourcedimord)) + + % determine the size of the data + if isfield(data, 'dimord'), + dimtok = tokenize(data.dimord, '_'); + if ~isempty(strmatch('time', dimtok)), Ntime = length(data.time); else Ntime = 1; end + if ~isempty(strmatch('freq', dimtok)), Nfreq = length(data.freq); else Nfreq = 1; end + else + Nfreq = 1; + Ntime = 1; + end + + %convert old style source representation into new style + if isfield(data, 'avg') && isfield(data.avg, 'mom') && (isfield(data, 'freq') || isfield(data, 'frequency')) && strcmp(sourcedimord, 'rpt_pos'), + %frequency domain source representation convert to single trial power + Npos = size(data.pos,1); + Nrpt = length(data.cumtapcnt); + tmpmom = zeros(Npos, size(data.avg.mom{data.inside(1)},2)); + tmpmom(data.inside,:) = cat(1,data.avg.mom{data.inside}); + tmppow = zeros(Npos, Nrpt); + tapcnt = [0;cumsum(data.cumtapcnt)]; + for k = 1:Nrpt + Ntap = tapcnt(k+1)-tapcnt(k); + tmppow(data.inside,k) = sum(abs(tmpmom(data.inside,(tapcnt(k)+1):tapcnt(k+1))).^2,2)./Ntap; + end + data.pow = tmppow'; + data = rmfield(data, 'avg'); + if strcmp(inside, 'logical'), + data = fixinside(data, 'logical'); + data.inside = repmat(data.inside(:)',[Nrpt 1]); + end + elseif isfield(data, 'avg') && isfield(data.avg, 'mom') && (isfield(data, 'freq') || isfield(data, 'frequency')) && strcmp(sourcedimord, 'rpttap_pos'), + %frequency domain source representation convert to single taper fourier coefficients + Npos = size(data.pos,1); + Nrpt = sum(data.cumtapcnt); + data.fourierspctrm = complex(zeros(Nrpt, Npos), zeros(Nrpt, Npos)); + data.fourierspctrm(:, data.inside) = transpose(cat(1, data.avg.mom{data.inside})); + data = rmfield(data, 'avg'); + elseif isfield(data, 'avg') && isfield(data.avg, 'mom') && isfield(data, 'time') && strcmp(sourcedimord, 'pos_time'), + Npos = size(data.pos,1); + Nrpt = 1; + tmpmom = zeros(Npos, size(data.avg.mom{data.inside(1)},2)); + tmpmom(data.inside,:) = cat(1,data.avg.mom{data.inside}); + data.mom = tmpmom; + if isfield(data.avg, 'noise'), + tmpnoise = data.avg.noise(:); + data.noise = tmpnoise(:,ones(1,size(tmpmom,2))); + end + data = rmfield(data, 'avg'); + Ntime = length(data.time); + elseif isfield(data, 'trial') && isfield(data.trial(1), 'mom') && isfield(data, 'time') && strcmp(sourcedimord, 'rpt_pos_time'), + Npos = size(data.pos,1); + Nrpt = length(data.trial); + Ntime = length(data.time); + tmpmom = zeros(Nrpt, Npos, Ntime); + for k = 1:Nrpt + tmpmom(k,data.inside,:) = cat(1,data.trial(k).mom{data.inside}); + end + data = rmfield(data, 'trial'); + data.mom = tmpmom; + elseif isfield(data, 'trial') && isstruct(data.trial) + Nrpt = length(data.trial); + else + Nrpt = 1; + end + + % start with an initial specification of the dimord and dim + if (~isfield(data, 'dim') || ~isfield(data, 'dimord')) + if issource + % at least it should have a Nx3 pos + data.dim = size(data.pos, 1); + data.dimord = 'pos'; + elseif isvolume + % at least it should have a 1x3 dim + data.dim = data.dim; + data.dimord = 'dim1_dim2_dim3'; + end + end + + % add the additional dimensions + if Nfreq>1 + data.dimord = [data.dimord '_freq']; + data.dim = [data.dim Nfreq]; + end + if Ntime>1 + data.dimord = [data.dimord '_time']; + data.dim = [data.dim Ntime]; + end + if Nrpt>1 && strcmp(sourcedimord, 'rpt_pos'), + data.dimord = ['rpt_' data.dimord]; + data.dim = [Nrpt data.dim ]; + elseif Nrpt>1 && strcmp(sourcedimord, 'rpttap_pos'), + data.dimord = ['rpttap_' data.dimord]; + data.dim = [Nrpt data.dim ]; + end + + % the nested trial structure is not compatible with dimord + if isfield(data, 'trial') && isstruct(data.trial) + param = fieldnames(data.trial); + for i=1:length(param) + if isa(data.trial(1).(param{i}), 'cell') + concat = cell(data.dim(1), prod(data.dim(2:end))); + else + concat = zeros(data.dim(1), prod(data.dim(2:end))); + end + for j=1:length(data.trial) + tmp = data.trial(j).(param{i}); + concat(j,:) = tmp(:); + end % for each trial + data.trial = rmfield(data.trial, param{i}); + data.(param{i}) = reshape(concat, data.dim); + end % for each param + data = rmfield(data, 'trial'); + end + end + + % ensure consistent dimensions of the source reconstructed data + % reshape each of the source reconstructed parameters + if issource && prod(data.dim)==size(data.pos,1) + dim = [prod(data.dim) 1]; + elseif issource && any(~cellfun('isempty',strfind(fieldnames(data), 'dimord'))) + dim = [size(data.pos,1) 1]; %sparsely represented source structure new style + elseif isfield(data, 'dim'), + dim = [data.dim 1]; + elseif isfield(data, 'dimord'), + %HACK + dimtok = tokenize(data.dimord, '_'); + for i=1:length(dimtok) + if strcmp(dimtok(i), 'pos') + dim(1,i) = size(getsubfield(data,dimtok{i}),1); + elseif strcmp(dimtok(i), 'rpt') + dim(1,i) = nan; + else + dim(1,i) = length(getsubfield(data,dimtok{i})); + end + end + i = find(isnan(dim)); + if ~isempty(i) + n = fieldnames(data); + for ii=1:length(n) + numels(1,ii) = numel(getfield(data,n{ii})); + end + nrpt = numels./prod(dim(setdiff(1:length(dim),i))); + nrpt = nrpt(nrpt==round(nrpt)); + dim(i) = max(nrpt); + end + if numel(dim)==1, dim(1,2) = 1; end; + end + + % these fields should not be reshaped + exclude = {'cfg' 'fwhm' 'leadfield' 'q' 'rough'}; + if ~strcmp(inside, 'logical') + % also exclude the inside/outside from being reshaped + exclude = cat(2, exclude, {'inside' 'outside'}); + end + + param = setdiff(parameterselection('all', data), exclude); + for i=1:length(param) + if any(param{i}=='.') + % the parameter is nested in a substructure, which can have multiple elements (e.g. source.trial(1).pow, source.trial(2).pow, ...) + % loop over the substructure array and reshape for every element + tok = tokenize(param{i}, '.'); + sub1 = tok{1}; % i.e. this would be 'trial' + sub2 = tok{2}; % i.e. this would be 'pow' + tmp1 = getfield(data, sub1); + for j=1:numel(tmp1) + tmp2 = getfield(tmp1(j), sub2); + tmp2 = reshape(tmp2, dim); + tmp1(j) = setfield(tmp1(j), sub2, tmp2); + end + data = setfield(data, sub1, tmp1); + else + tmp = getfield(data, param{i}); + tmp = reshape(tmp, dim); + data = setfield(data, param{i}, tmp); + end + end + +end + +if isequal(hastrials, 'yes') + okflag = isfield(data, 'trial'); + if ~okflag + error('This function requires data with a ''trial'' field'); + end % if okflag +end + +if isequal(hastrialdef, 'yes') + data = fixtrialdef(data); +end + +if isequal(hasoffset, 'yes') + okflag = isfield(data, 'offset'); + + if ~okflag && isfield(data, 'time') && isa(data.time, 'cell') + if ~isfield(data, 'fsample') + data.fsample = 1/(data.time{1}(2)-data.time{1}(1)); + end + for i=1:length(data.time); + data.offset(i) = time2offset(data.time{i}, data.fsample); + end + okflag = 1; + elseif ~okflag && datatype(data, 'mvar') + data.offset = 0; + okflag = 1; + end + + if ~okflag + error('This function requires data with an ''offset'' field'); + end % if okflag + +elseif isequal(hasoffset, 'no') && isfield(data, 'offset') + data = rmfield(data, 'offset'); +end % if hasoffset + +if isequal(hascumtapcnt, 'yes') && ~isfield(data, 'cumtapcnt') + error('This function requires data with a ''cumtapcnt'' field'); +elseif isequal(hascumtapcnt, 'no') && isfield(data, 'cumtapcnt') + data = rmfield(data, 'cumtapcnt'); +end % if hascumtapcnt + +if isequal(hasdof, 'yes') && ~isfield(data, 'hasdof') + error('This function requires data with a ''dof'' field'); +elseif isequal(hasdof, 'no') && isfield(data, 'hasdof') + data = rmfield(data, 'cumtapcnt'); +end % if hasdof + +if ~isempty(cmbrepresentation) + if istimelock + data = fixcov(data, cmbrepresentation); + elseif isfreq + data = fixcsd(data, cmbrepresentation, channelcmb); + elseif isfreqmvar + data = fixcsd(data, cmbrepresentation, channelcmb); + else + error('This function requires data with a covariance, coherence or cross-spectrum'); + end +end % cmbrepresentation + +if issource && strcmp(keepoutside, 'no'), + % remove all grid points that are marked as outside + data = source2sparse(data); +end + +if issource && ~isempty(sourcerepresentation) + data = fixsource(data, 'type', sourcerepresentation); +end + +if issource && ~strcmp(haspow, 'no') + data = fixsource(data, 'type', sourcerepresentation, 'haspow', haspow); +end + +if isfield(data, 'grad') + % ensure that the gradiometer balancing is specified + if ~isfield(data.grad, 'balance') || ~isfield(data.grad.balance, 'current') + data.grad.balance.current = 'none'; + end +end + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% represent the covariance matrix in a particular manner +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function data = fixcov(data, desired) +if isfield(data, 'cov') && ~isfield(data, 'labelcmb') + current = 'full'; +elseif isfield(data, 'cov') && isfield(data, 'labelcmb') + current = 'sparse'; +else + error('Could not determine the current representation of the covariance matrix'); +end +if isequal(current, desired) + % nothing to do +elseif strcmp(current, 'full') && strcmp(desired, 'sparse') + % FIXME should be implemented + error('not yet implemented'); +elseif strcmp(current, 'sparse') && strcmp(desired, 'full') + % FIXME should be implemented + error('not yet implemented'); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% convert between datatypes +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function data = comp2raw(data) +% just remove the component topographies +data = rmfield(data, 'topo'); +data = rmfield(data, 'topolabel'); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% convert between datatypes +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function data = volume2source(data) +if isfield(data, 'dimord') + % it is a modern source description +else + % it is an old-fashioned source description + xgrid = 1:data.dim(1); + ygrid = 1:data.dim(2); + zgrid = 1:data.dim(3); + [x y z] = ndgrid(xgrid, ygrid, zgrid); + data.pos = warp_apply(data.transform, [x(:) y(:) z(:)]); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% convert between datatypes +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function data = source2volume(data) + +if isfield(data, 'dimord') + % it is a modern source description + + %this part depends on the assumption that the list of positions is describing a full 3D volume in + %an ordered way which allows for the extraction of a transformation matrix + %i.e. slice by slice + try, + if isfield(data, 'dim'), + data.dim = pos2dim3d(data.pos, data.dim); + else + data.dim = pos2dim3d(data); + end + catch + end +end + +if isfield(data, 'dim') && length(data.dim)>=3, + % it is an old-fashioned source description, or the source describes a regular 3D volume in pos + xgrid = 1:data.dim(1); + ygrid = 1:data.dim(2); + zgrid = 1:data.dim(3); + [x y z] = ndgrid(xgrid, ygrid, zgrid); + ind = [x(:) y(:) z(:)]; % these are the positions expressed in voxel indices along each of the three axes + pos = data.pos; % these are the positions expressed in head coordinates + % represent the positions in a manner that is compatible with the homogeneous matrix multiplication, + % i.e. pos = H * ind + ind = ind'; ind(4,:) = 1; + pos = pos'; pos(4,:) = 1; + % recompute the homogeneous transformation matrix + data.transform = pos / ind; +end + +% remove the unwanted fields +if isfield(data, 'pos'), data = rmfield(data, 'pos'); end +if isfield(data, 'xgrid'), data = rmfield(data, 'xgrid'); end +if isfield(data, 'ygrid'), data = rmfield(data, 'ygrid'); end +if isfield(data, 'zgrid'), data = rmfield(data, 'zgrid'); end + +% make inside a volume +data = fixinside(data, 'logical'); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% convert between datatypes +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function data = freq2raw(freq) + +if strcmp(freq.dimord, 'rpt_chan_freq_time') + dat = freq.powspctrm; +elseif strcmp(freq.dimord, 'rpttap_chan_freq_time') + warning('converting fourier representation into raw data format. this is experimental code'); + dat = freq.fourierspctrm; +else + error('this only works for dimord=''rpt_chan_freq_time'''); +end + +nrpt = size(dat,1); +nchan = size(dat,2); +nfreq = size(dat,3); +ntime = size(dat,4); +data = []; +% create the channel labels like "MLP11@12Hz"" +k = 0; +for i=1:nfreq + for j=1:nchan + k = k+1; + data.label{k} = sprintf('%s@%dHz', freq.label{j}, freq.freq(i)); + end +end +% reshape and copy the data as if it were timecourses only +for i=1:nrpt + data.time{i} = freq.time; + data.trial{i} = reshape(dat(i,:,:,:), nchan*nfreq, ntime); + if any(isnan(data.trial{i}(1,:))), + tmp = data.trial{i}(1,:); + begsmp = find(isfinite(tmp),1, 'first'); + endsmp = find(isfinite(tmp),1, 'last' ); + data.trial{i} = data.trial{i}(:, begsmp:endsmp); + data.time{i} = data.time{i}(begsmp:endsmp); + end +end +nsmp = cellfun('size',data.time,2); +seln = find(nsmp>1,1, 'first'); +data.fsample = 1/(data.time{seln}(2)-data.time{seln}(1)); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% convert between datatypes +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [data] = raw2timelock(data) +ntrial = numel(data.trial); +nchan = numel(data.label); +if ntrial==1 + data.time = data.time{1}; + data.avg = data.trial{1}; + data = rmfield(data, 'trial'); + data.dimord = 'chan_time'; +else + % determine the location of the trials relative to the resulting combined time axis + begtime = cellfun(@min, data.time); + endtime = cellfun(@max, data.time); + begsmp = round((begtime - min(begtime)) * data.fsample) + 1; + endsmp = round((endtime - min(begtime)) * data.fsample) + 1; + + % create a combined time axis and concatenate all trials + tmptime = min(begtime):(1/data.fsample):max(endtime); + tmptrial = zeros(ntrial, nchan, length(tmptime)) + nan; + for i=1:ntrial + tmptrial(i,:,begsmp(i):endsmp(i)) = data.trial{i}; + end + + % update the trial definition + trl = findcfg(data.cfg, 'trl'); + if ~isempty(trl) + begpad = begsmp - min(begsmp); % number of nan-samples added to the begin + endpad = max(endsmp) - endsmp; % number of nan-samples added to the end + data.cfg.trlold = trl; + trl(:,1) = trl(:,1) - begpad(:); + trl(:,2) = trl(:,2) + endpad(:); + trl(:,3) = trl(:,3) - begpad(:); + data.cfg.trl = trl; + end + + % construct the output timelocked data + % data.avg = reshape(nanmean(tmptrial, 1), nchan, length(tmptime)); + % data.var = reshape(nanvar (tmptrial, [], 1), nchan, length(tmptime)) + % data.dof = reshape(sum(~isnan(tmptrial), 1), nchan, length(tmptime)); + data.trial = tmptrial; + data.time = tmptime; + data.dimord = 'rpt_chan_time'; +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% convert between datatypes +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [data] = timelock2raw(data) +switch data.dimord + case 'chan_time' + data.trial{1} = data.avg; + data.time = {data.time}; + data = rmfield(data, 'avg'); + case 'rpt_chan_time' + tmptrial = {}; + tmptime = {}; + ntrial = size(data.trial,1); + nchan = size(data.trial,2); + ntime = size(data.trial,3); + for i=1:ntrial + tmptrial{i} = reshape(data.trial(i,:,:), [nchan, ntime]); + tmptime{i} = data.time; + end + data = rmfield(data, 'trial'); + data.trial = tmptrial; + data.time = tmptime; + case 'subj_chan_time' + tmptrial = {}; + tmptime = {}; + ntrial = size(data.individual,1); + nchan = size(data.individual,2); + ntime = size(data.individual,3); + for i=1:ntrial + tmptrial{i} = reshape(data.individual(i,:,:), [nchan, ntime]); + tmptime{i} = data.time; + end + data = rmfield(data, 'individual'); + data.trial = tmptrial; + data.time = tmptime; + otherwise + error('unsupported dimord'); +end +% remove the unwanted fields +if isfield(data, 'avg'), data = rmfield(data, 'avg'); end +if isfield(data, 'var'), data = rmfield(data, 'var'); end +if isfield(data, 'cov'), data = rmfield(data, 'cov'); end +if isfield(data, 'dimord'), data = rmfield(data, 'dimord'); end +if isfield(data, 'numsamples'), data = rmfield(data, 'numsamples'); end +if isfield(data, 'dof'), data = rmfield(data, 'dof'); end diff --git a/external/fieldtrip/public/datatype.m b/external/fieldtrip/public/datatype.m new file mode 100644 index 0000000..2c9a917 --- /dev/null +++ b/external/fieldtrip/public/datatype.m @@ -0,0 +1,87 @@ +function [type, dimord] = datatype(data, desired) + +% DATATYPE determines the type of data represented in a FieldTrip data +% structure and returns a string with raw, freq, timelock source, comp, +% spike, source, volume, dip. +% +% Use as +% [type, dimord] = datatype(data) +% [type, dimord] = datatype(data, desired) +% +% See also CHANTYPE, FILETYPE, SENSTYPE, VOLTYPE + +% Copyright (C) 2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: datatype.m 951 2010-04-21 18:24:01Z roboos $ + +% determine the type of input data, this can be raw, freq, timelock, comp, spike, source, volume, dip +israw = isfield(data, 'label') && isfield(data, 'time') && isa(data.time, 'cell') && isfield(data, 'trial') && isa(data.trial, 'cell'); +isfreq = (isfield(data, 'label') || isfield(data, 'labelcmb')) && isfield(data, 'freq'); %&& (isfield(data, 'powspctrm') || isfield(data, 'crsspctrm') || isfield(data, 'cohspctrm') || isfield(data, 'fourierspctrm') || isfield(data, 'powcovspctrm')); +istimelock = isfield(data, 'label') && isfield(data, 'time') && ~isfield(data, 'freq') && ((isfield(data, 'avg') && isnumeric(data.avg)) || (isfield(data, 'trial') && isnumeric(data.trial) || (isfield(data, 'cov') && isnumeric(data.cov)))); +iscomp = isfield(data, 'topo') || isfield(data, 'topolabel'); +isspike = isfield(data, 'label') && isfield(data, 'waveform') && isa(data.waveform, 'cell') && isfield(data, 'timestamp') && isa(data.timestamp, 'cell'); +isvolume = isfield(data, 'transform') && isfield(data, 'dim'); +issource = isfield(data, 'pos'); +isdip = isfield(data, 'dip'); +ismvar = isfield(data, 'dimord') && ~isempty(strfind(data.dimord, 'lag')); +isfreqmvar = isfield(data, 'freq') && isfield(data, 'transfer'); + +if iscomp + type = 'comp'; + %comp should conditionally go before raw, otherwise the returned datatype + %will be raw +elseif isfreqmvar + type = 'freqmvar'; + %freqmvar should conditionally go before freq, otherwise the returned datatype + %will be freq in the case of frequency mvar data +elseif ismvar + type = 'mvar'; +elseif israw + type = 'raw'; +elseif isfreq + type = 'freq'; +elseif istimelock + type = 'timelock'; +elseif isspike + type = 'spike'; +elseif isvolume + type = 'volume'; +elseif issource + type = 'source'; +elseif isdip + type = 'dip'; +else + type = 'unknown'; +end + +if nargin>1 + % return a boolean value + type = strcmp(type, desired); + return; +end + +if nargout>1 + % also return the dimord of the input data + if isfield(data, 'dimord') + dimord = data.dimord; + else + dimord = 'unknown'; + end +end + diff --git a/external/fieldtrip/public/fetch_data.m b/external/fieldtrip/public/fetch_data.m new file mode 100644 index 0000000..e70e9d1 --- /dev/null +++ b/external/fieldtrip/public/fetch_data.m @@ -0,0 +1,164 @@ +function [dat] = fetch_data(data, varargin) + +% FETCH_DATA mimics the behaviour of READ_DATA, but for a FieldTrip +% raw data structure instead of a file on disk. +% +% Use as +% [dat] = fetch_data(data, ...) +% +% See also READ_DATA, FETCH_HEADER, FETCH_EVENT + +% Copyright (C) 2008, Esther Meeuwissen +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: fetch_data.m 1328 2010-07-01 12:39:39Z jansch $ + +% check whether input is data +data = checkdata(data, 'datatype', 'raw', 'hastrialdef', 'yes'); + +% get the options +hdr = keyval('header', varargin); +begsample = keyval('begsample', varargin); +endsample = keyval('endsample', varargin); +chanindx = keyval('chanindx', varargin); + +if isempty(hdr) + hdr = fetch_header(data); +end + +if isempty(begsample) || isempty(endsample) + error('begsample and endsample must be specified'); +end + +if isempty(chanindx) + chanindx = 1:hdr.nChans; +end + +% get trial definition according to original data file +if isfield(data, 'trialdef') + trl = data.trialdef; +else + error('data does not contain a consistent trial definition, fetching data is not possible'); +end +trlnum = length(data.trial); + +if trlnum>1, + % original implementation + + trllen = zeros(trlnum,1); + for trllop=1:trlnum + trllen(trllop) = size(data.trial{trllop},2); + end + + % check whether data.trial is consistent with trl + if size(trl,1)~=length(data.trial) + error('trial definition is not internally consistent') + elseif any(trllen~=(trl(:,2)-trl(:,1)+1)) + error('trial definition is not internally consistent') + end + + minchan = min(chanindx); + maxchan = max(chanindx); + if minchan<1 || maxchan>hdr.nChans + error('selected channels are not present in the data') + end + + % these are for bookkeeping + maxsample = max(trl(:,2)); + count = zeros(1, maxsample, 'int32'); + trialnum = zeros(1, maxsample, 'int32'); + samplenum = zeros(1, maxsample, 'int32'); + + % determine for each sample in the data where it originates from + for trllop=1:trlnum + trlbeg = trl(trllop,1); + trlend = trl(trllop,2); + if trlbeg>endsample || trlend Nan + trialnum(trlbeg:trlend) = trllop; + % make samplenum vector with samplenrs for each sample in the old trials + samplenum(trlbeg:trlend) = 1:trllen(trllop); + end + + % overlap --> NaN + %trialnum(count>1) = NaN; + %samplenum(count>1) = NaN; + + % make a subselection for the desired samples + count = count(begsample:endsample); + trialnum = trialnum(begsample:endsample); + samplenum = samplenum(begsample:endsample); + + % check if all samples are present and are not present twice or more + if any(count==0) + warning('not all requested samples are present in the data, filling with NaNs'); + elseif any(count>1) + error('some of the requested samples occur twice in the data'); + end + + % construct the output data array + %dat = nan(length(chanindx), length(samplenum)); + %for smplop=1:length(samplenum) + % if samplenum(smplop)==0 + % dat(:, smplop) = nan; + % else + % dat(:, smplop) = data.trial{trialnum(smplop)}(chanindx,samplenum(smplop)); + % end + %end + + % the following piece of code achieves the same as the commented code above, + % but much smaller. rather than looping over samples it loops over the blocks + % of samples defined by the original trials + utrl = unique(trialnum); + utrl(~isfinite(utrl)) = 0; + utrl(utrl==0) = []; + if length(utrl)==1, + ok = trialnum==utrl; + smps = samplenum(ok); + dat(:,ok) = data.trial{utrl}(chanindx,smps); + else + for xlop=1:length(utrl) + ok = trialnum==utrl(xlop); + smps = samplenum(ok); + dat(:,ok) = data.trial{utrl(xlop)}(chanindx,smps); + end + end + +else + % only 1 trial present in the input data, so it's quite simple + % and can be done fast + + % check whether the requested samples are present in the input + if endsample>trl(2) || begsample. +% +% $Id: fetch_event.m 951 2010-04-21 18:24:01Z roboos $ + +% check whether input is data +data = checkdata(data, 'datatype', 'raw'); + +% locate the event structure +event = findcfg(data.cfg, 'event'); + diff --git a/external/fieldtrip/public/fetch_header.m b/external/fieldtrip/public/fetch_header.m new file mode 100644 index 0000000..f67e6a4 --- /dev/null +++ b/external/fieldtrip/public/fetch_header.m @@ -0,0 +1,67 @@ +function [hdr] = fetch_header(data) + +% FETCH_HEADER mimics the behaviour of READ_HEADER, but for a FieldTrip +% raw data structure instead of a file on disk. +% +% Use as +% [hdr] = fetch_header(data) +% +% See also READ_HEADER, FETCH_DATA, FETCH_EVENT + +% Copyright (C) 2008, Esther Meeuwissen +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: fetch_header.m 1328 2010-07-01 12:39:39Z jansch $ + +% check whether input is data +data = checkdata(data, 'datatype', 'raw', 'hastrialdef', 'yes'); + +trlnum = length(data.trial); +trllen = zeros(trlnum,1); +for trllop=1:trlnum + trllen(trllop) = size(data.trial{trllop},2); +end + +% try to get trial definition according to original data file +if isfield(data, 'trialdef') + trl = data.trialdef; +else + trl = [1 sum(trllen)]; +end + +% fill in hdr.nChans +hdr.nChans = length(data.label); + +% fill in hdr.label +hdr.label = data.label; + +% fill in hdr.Fs (sample frequency) +hdr.Fs = data.fsample; + +% determine hdr.nSamples, hdr.nSamplesPre, hdr.nTrials +% always pretend that it is continuous data +hdr.nSamples = max(trl(:,2)); +hdr.nSamplesPre = 0; +hdr.nTrials = 1; + +% fill in hdr.grad or hdr.elec +if isfield(data, 'grad') + hdr.grad=data.grad; +elseif isfield(data, 'elec') + hdr.elec=data.elec; +end diff --git a/external/fieldtrip/public/findcfg.m b/external/fieldtrip/public/findcfg.m new file mode 100644 index 0000000..6e378e2 --- /dev/null +++ b/external/fieldtrip/public/findcfg.m @@ -0,0 +1,59 @@ +function [val, status] = findcfg(cfg, var); + +% FINDCFG searches for an element in the cfg structure +% or in the nested previous cfgs +% +% Use as +% [val] = findcfg(cfg, var) +% where the name of the variable should be specified as string. +% +% e.g. +% trl = findcfg(cfg, 'trl') +% event = findcfg(cfg, 'event') + +% Copyright (C) 2006, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: findcfg.m 951 2010-04-21 18:24:01Z roboos $ + +if var(1)~='.' + var = ['.' var]; +end +val = []; +depth = 0; +status = 0; + +while ~status + depth = depth + 1; + if issubfield(cfg, var) + val = getsubfield(cfg, var); + status = 1; + elseif issubfield(cfg, '.previous'); + [val, status] = findcfg(cfg.previous, var); + if status, break; end; + elseif iscell(cfg) + for i=1:length(cfg) + [val, status] = findcfg(cfg{i}, var); + if status, break; end; + end + else + status = -1; + break + end +end + diff --git a/external/fieldtrip/public/getsubfield.m b/external/fieldtrip/public/getsubfield.m new file mode 100644 index 0000000..690e299 --- /dev/null +++ b/external/fieldtrip/public/getsubfield.m @@ -0,0 +1,45 @@ +function [s] = getsubfield(s, f); + +% GETSUBFIELD returns a field from a structure just like the standard +% Matlab GETFIELD function, except that you can also specify nested fields +% using a '.' in the fieldname. The nesting can be arbitrary deep. +% +% Use as +% f = getsubfield(s, 'fieldname') +% or as +% f = getsubfield(s, 'fieldname.subfieldname') +% +% See also GETFIELD, ISSUBFIELD, SETSUBFIELD + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: getsubfield.m 951 2010-04-21 18:24:01Z roboos $ + +if ~isstr(f) + error('incorrect input argument for fieldname'); +end + +t = {}; +while (1) + [t{end+1}, f] = strtok(f, '.'); + if isempty(f) + break + end +end +s = getfield(s, t{:}); diff --git a/external/fieldtrip/public/hastoolbox.m b/external/fieldtrip/public/hastoolbox.m new file mode 100644 index 0000000..311bb7e --- /dev/null +++ b/external/fieldtrip/public/hastoolbox.m @@ -0,0 +1,321 @@ +function [status] = hastoolbox(toolbox, autoadd, silent) + +% HASTOOLBOX tests whether an external toolbox is installed. Optionally +% it will try to determine the path to the toolbox and install it +% automatically. +% +% Use as +% [status] = hastoolbox(toolbox, autoadd, silent) +% +% autoadd = 0 means that it will not be added +% autoadd = 1 means that give an error if it cannot be added +% autoadd = 2 means that give a warning if it cannot be added +% autoadd = 3 means that it try to add it silently + +% Copyright (C) 2005-2010, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: hastoolbox.m 1411 2010-07-14 11:00:12Z jansch $ + +% this function is called many times in FieldTrip and associated toolboxes +% use efficient handling if the same toolbox has been investigated before +persistent previous previouspath + +if ~isequal(previouspath, matlabpath) + previous = []; +end + +if isempty(previous) + previous = struct; +elseif isfield(previous, fixname(toolbox)) + status = previous.(fixname(toolbox)); + return +end + +% this points the user to the website where he/she can download the toolbox +url = { + 'AFNI' 'see http://afni.nimh.nih.gov' + 'DSS' 'see http://www.cis.hut.fi/projects/dss' + 'EEGLAB' 'see http://www.sccn.ucsd.edu/eeglab' + 'NWAY' 'see http://www.models.kvl.dk/source/nwaytoolbox' + 'SPM99' 'see http://www.fil.ion.ucl.ac.uk/spm' + 'SPM2' 'see http://www.fil.ion.ucl.ac.uk/spm' + 'SPM5' 'see http://www.fil.ion.ucl.ac.uk/spm' + 'SPM8' 'see http://www.fil.ion.ucl.ac.uk/spm' + 'MEG-PD' 'see http://www.kolumbus.fi/kuutela/programs/meg-pd' + 'MEG-CALC' 'this is a commercial toolbox from Neuromag, see http://www.neuromag.com' + 'BIOSIG' 'see http://biosig.sourceforge.net' + 'EEG' 'see http://eeg.sourceforge.net' + 'EEGSF' 'see http://eeg.sourceforge.net' % alternative name + 'MRI' 'see http://eeg.sourceforge.net' % alternative name + 'NEUROSHARE' 'see http://www.neuroshare.org' + 'BESA' 'see http://www.megis.de, or contact Karsten Hoechstetter' + 'EEPROBE' 'see http://www.ant-neuro.com, or contact Maarten van der Velde' + 'YOKOGAWA' 'see http://www.yokogawa.co.jp, or contact Nobuhiko Takahashi' + 'BEOWULF' 'see http://oostenveld.net, or contact Robert Oostenveld' + 'MENTAT' 'see http://oostenveld.net, or contact Robert Oostenveld' + 'SON2' 'see http://www.kcl.ac.uk/depsta/biomedical/cfnr/lidierth.html, or contact Malcolm Lidierth' + '4D-VERSION' 'contact Christian Wienbruch' + 'SIGNAL' 'see http://www.mathworks.com/products/signal' + 'OPTIM' 'see http://www.mathworks.com/products/optim' + 'IMAGE' 'see http://www.mathworks.com/products/image' + 'SPLINES' 'see http://www.mathworks.com/products/splines' + 'FASTICA' 'see http://www.cis.hut.fi/projects/ica/fastica' + 'BRAINSTORM' 'see http://neuroimage.ucs.edu/brainstorm' + 'FILEIO' 'see http://www.ru.nl/neuroimaging/fieldtrip' + 'FORWINV' 'see http://www.ru.nl/neuroimaging/fieldtrip' + 'PLOTTING' 'see http://www.ru.nl/neuroimaging/fieldtrip' + 'DENOISE' 'see http://lumiere.ens.fr/Audition/adc/meg, or contact Alain de Cheveigne' + 'BCI2000' 'see http://bci2000.org' + 'NLXNETCOM' 'see http://www.neuralynx.com' + 'DIPOLI' 'see ftp://ftp.fcdonders.nl/pub/fieldtrip/external' + 'MNE' 'see http://www.nmr.mgh.harvard.edu/martinos/userInfo/data/sofMNE.php' + 'TCP_UDP_IP' 'see http://www.mathworks.com/matlabcentral/fileexchange/345, or contact Peter Rydes?ter' + 'BEMCP' 'contact Christophe Phillips' + 'OPENMEEG' 'see http://gforge.inria.fr/projects/openmeeg' + 'PRTOOLS' 'see http://www.prtools.org' + 'ITAB' 'contact Stefania Della Penna' + 'BSMART' 'see http://www.brain-smart.org' + 'PEER' 'see http://fieldtrip.fcdonders.nl/development/peer' + }; + +if nargin<2 + % default is not to add the path automatically + autoadd = 0; +end + +if nargin<3 + % default is not to be silent + silent = 0; +end + +% determine whether the toolbox is installed +toolbox = upper(toolbox); +switch toolbox + case 'AFNI' + status = (exist('BrikLoad') && exist('BrikInfo')); + case 'DSS' + status = exist('dss', 'file') && exist('dss_create_state', 'file'); + case 'EEGLAB' + status = exist('runica', 'file'); + case 'NWAY' + status = exist('parafac', 'file'); + case 'SPM99' + status = exist('spm.m') && strcmp(spm('ver'),'SPM99'); + case 'SPM2' + status = exist('spm.m') && strcmp(spm('ver'),'SPM2'); + case 'SPM5' + status = exist('spm.m') && strcmp(spm('ver'),'SPM5'); + case 'SPM8' + status = exist('spm.m') && strncmp(spm('ver'),'SPM8', 4); + case 'MEG-PD' + status = (exist('rawdata') && exist('channames')); + case 'MEG-CALC' + status = (exist('megmodel') && exist('megfield') && exist('megtrans')); + case 'BIOSIG' + status = (exist('sopen') && exist('sread')); + case 'EEG' + status = (exist('ctf_read_res4') && exist('ctf_read_meg4')); + case 'EEGSF' % alternative name + status = (exist('ctf_read_res4') && exist('ctf_read_meg4')); + case 'MRI' % other functions in the mri section + status = (exist('avw_hdr_read') && exist('avw_img_read')); + case 'NEUROSHARE' + status = (exist('ns_OpenFile') && exist('ns_SetLibrary') && exist('ns_GetAnalogData')); + case 'BESA' + status = (exist('readBESAtfc') && exist('readBESAswf')); + case 'EEPROBE' + status = (exist('read_eep_avr') && exist('read_eep_cnt')); + case 'YOKOGAWA' + status = hasyokogawa('16bitBeta6'); + case 'BEOWULF' + status = (exist('evalwulf') && exist('evalwulf') && exist('evalwulf')); + case 'MENTAT' + status = (exist('pcompile') && exist('pfor') && exist('peval')); + case 'SON2' + status = (exist('SONFileHeader') && exist('SONChanList') && exist('SONGetChannel')); + case '4D-VERSION' + status = (exist('read4d') && exist('read4dhdr')); + case 'SIGNAL' + status = hasfunction('medfilt1', toolbox) && exist('butter', 'file'); % also check the availability of a toolbox license + case 'OPTIM' + status = hasfunction('fmincon', toolbox) && exist('fminunc', 'file'); % also check the availability of a toolbox license + case 'SPLINES' + status = hasfunction('bspline', toolbox) && exist('csape', 'file'); % also check the availability of a toolbox license + case 'IMAGE' + status = hasfunction('bwlabeln', toolbox); % also check the availability of a toolbox license + case 'FASTICA' + status = exist('fastica', 'file'); + case 'BRAINSTORM' + status = exist('bem_xfer'); + case 'FILEIO' + status = (exist('read_header') && exist('read_data') && exist('read_event') && exist('read_sens')); + case 'FORWINV' + status = (exist('compute_leadfield') && exist('prepare_vol_sens')); + case 'DENOISE' + status = (exist('tsr') && exist('sns')); + case 'CTF' + status = (exist('getCTFBalanceCoefs') && exist('getCTFdata')); + case 'BCI2000' + status = exist('load_bcidat'); + case 'NLXNETCOM' + status = (exist('MatlabNetComClient') && exist('NlxConnectToServer') && exist('NlxGetNewCSCData')); + case 'DIPOLI' + status = exist('dipoli.m', 'file'); + case 'MNE' + status = (exist('fiff_read_meas_info', 'file') && exist('fiff_setup_read_raw', 'file')); + case 'TCP_UDP_IP' + status = (exist('pnet', 'file') && exist('pnet_getvar', 'file') && exist('pnet_putvar', 'file')); + case 'BEMCP' + status = (exist('bem_Cij_cog', 'file') && exist('bem_Cij_lin', 'file') && exist('bem_Cij_cst', 'file')); + case 'OPENMEEG' + status = exist('openmeeg.m', 'file'); + case 'PLOTTING' + status = (exist('plot_topo', 'file') && exist('plot_mesh', 'file') && exist('plot_matrix', 'file')); + case 'PRTOOLS' + status = (exist('prversion', 'file') && exist('dataset', 'file') && exist('svc', 'file')); + case 'ITAB' + status = (exist('lcReadHeader', 'file') && exist('lcReadData', 'file')); + case 'BSMART' + status = exist('bsmart'); + case 'PEER' + status = exist('peerslave', 'file') && exist('peermaster', 'file'); + case 'CONNECTIVITY' + status = exist('ft_connectivity_corr', 'file') && exist('ft_connectivity_granger', 'file'); + otherwise + if ~silent, warning(sprintf('cannot determine whether the %s toolbox is present', toolbox)); end + status = 0; +end + +% it should be a boolean value +status = (status~=0); + +% try to determine the path of the requested toolbox +if autoadd>0 && ~status + + % for core fieldtrip modules + prefix = fileparts(which('fieldtripdefs')); + if ~status + status = myaddpath(fullfile(prefix, lower(toolbox)), silent); + end + + % for external fieldtrip modules + prefix = fullfile(fileparts(which('fieldtripdefs')), 'external'); + if ~status + status = myaddpath(fullfile(prefix, lower(toolbox)), silent); + end + + % for linux computers in the F.C. Donders Centre + prefix = '/home/common/matlab'; + if ~status && (strcmp(computer, 'GLNX86') || strcmp(computer, 'GLNXA64')) + status = myaddpath(fullfile(prefix, lower(toolbox)), silent); + end + + % for windows computers in the F.C. Donders Centre + prefix = 'h:\common\matlab'; + if ~status && (strcmp(computer, 'PCWIN') || strcmp(computer, 'PCWIN64')) + status = myaddpath(fullfile(prefix, lower(toolbox)), silent); + end + + % use the matlab subdirectory in your homedirectory, this works on unix and mac + prefix = [getenv('HOME') '/matlab']; + if ~status + status = myaddpath(fullfile(prefix, lower(toolbox)), silent); + end + + if ~status + % the toolbox is not on the path and cannot be added + sel = find(strcmp(url(:,1), toolbox)); + if ~isempty(sel) + msg = sprintf('the %s toolbox is not installed, %s', toolbox, url{sel, 2}); + else + msg = sprintf('the %s toolbox is not installed', toolbox); + end + if autoadd==1 + error(msg); + elseif autoadd==2 + warning(msg); + else + % fail silently + end + end +end + +% this function is called many times in FieldTrip and associated toolboxes +% use efficient handling if the same toolbox has been investigated before +if status + previous.(fixname(toolbox)) = status; +end + +% remember the previous path, allows us to determine on the next call +% whether the path has been modified outise of this function +previouspath = matlabpath; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% helper function +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function status = myaddpath(toolbox, silent) +if exist(toolbox, 'dir') + if ~silent, warning(sprintf('adding %s toolbox to your Matlab path', toolbox)); end + addpath(toolbox); + status = 1; +else + status = 0; +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% helper function +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function out = fixname(toolbox) +out = lower(toolbox); +out(out=='-') = '_'; % fix dashes +out(out==' ') = '_'; % fix spaces +out(out=='/') = '_'; % fix forward slashes +out(out=='\') = '_'; % fix backward slashes + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% helper function +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function status = hasfunction(funname, toolbox) +try + % call the function without any input arguments, which probably is inapropriate + feval(funname); + % it might be that the function without any input already works fine + status = true; +catch + % either the function returned an error, or the function is not available + % availability is influenced by the function being present and by having a + % license for the function, i.e. in a concurrent licensing setting it might + % be that all toolbox licenses are in use + m = lasterror; + if strcmp(m.identifier, 'MATLAB:license:checkouterror') + if nargin>1 + warning('the %s toolbox is available, but you don''t have a license for it', toolbox); + else + warning('the function ''%s'' is available, but you don''t have a license for it', funname); + end + status = false; + elseif strcmp(m.identifier, 'MATLAB:UndefinedFunction') + status = false; + else + % the function seems to be available and it gave an unknown error, + % which is to be expected with inappropriate input arguments + status = true; + end +end + diff --git a/external/fieldtrip/public/hasyokogawa.m b/external/fieldtrip/public/hasyokogawa.m new file mode 100644 index 0000000..f4c9545 --- /dev/null +++ b/external/fieldtrip/public/hasyokogawa.m @@ -0,0 +1,89 @@ +function [version] = hasyokogawa(desired) + +% HASYOKOGAWA tests whether the data input toolbox for MEG systems by +% Yokogawa (www.yokogawa.com, designed by KIT/EagleTechnology) is +% installed. Only the newest version of the toolbox is accepted. +% +% Use as +% [string] = hasyokogawa; +% which returns a string describing the toolbox version, e.g. "12bitBeta3", +% "16bitBeta3", or "16bitBeta6". An empty string is returned if the toolbox +% is not installed. The string "unknown" is returned if it is installed but +% the version is unknown. +% +% Alternatively you can use it as +% [boolean] = hasyokogawa(desired); +% where desired is a string with the desired version. +% +% See also READ_YOKOGAWA_HEADER, READ_YOKOGAWA_DATA, READ_YOKOGAWA_EVENT, +% YOKOGAWA2GRAD + +% Copyright (C) 2010, Tilmann Sander-Thoemmes +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id$ + +% return empty if not present +version = []; + +try + warning('off', 'MATLAB:pfileOlderThanMfile'); + % Call some functions with input argument "Inf": If + % the functions are present they return their revision number. + % Call first GetMeg160ADbitInfoM as this is not present in + % the 12bit library, in case of error the "catch" part will take over. + % The code below is intentionally very literal for easy of reading. + res = textscan(evalc('GetMeg160ADbitInfoM(Inf);'),'%s %s %c %s %s %d'); + rev_ADbitInfoM = res{6}; + res = textscan(evalc('GetMeg160ChannelInfoM(Inf);'),'%s %s %c %s %s %d'); + rev_ChannelInfoM = res{6}; + res = textscan(evalc('GetMeg160AmpGainM(Inf);'),'%s %s %c %s %s %d'); + rev_AmpGainM = res{6}; + res = textscan(evalc('GetMeg160MatchingInfoM(Inf);'),'%s %s %c %s %s %d'); + rev_MatchingInfoM = res{6}; + if [0 2 1 5] == [rev_ADbitInfoM rev_ChannelInfoM rev_AmpGainM rev_MatchingInfoM] + version='16bitBeta3'; + elseif [0 2 2 5] == [rev_ADbitInfoM rev_ChannelInfoM rev_AmpGainM rev_MatchingInfoM] + version='16bitBeta6'; + else + warning('Yokogawa toolbox is installed, but the version cannot be determined.'); + version = 'unknown'; + end + if nargin>0 + version = strcmpi(version, desired); + if ~version + warning('The required version of the Yokogawa input toolbox (%s) is not installed.', desired); + end + end + warning('on', 'MATLAB:pfileOlderThanMfile'); +catch + warning('on', 'MATLAB:pfileOlderThanMfile'); + m = lasterror; + m.identifier; + if strcmp(m.identifier, 'MATLAB:UndefinedFunction') || strcmp(m.identifier, 'MATLAB:FileIO:InvalidFid') + if (exist('GetMeg160ChannelInfoM') && exist('GetMeg160ContinuousRawDataM')); + version = '12bitBeta3'; + else + version = 'unknown'; + end + end + if nargin>0 + version = 0; % logical output + end + +end diff --git a/external/fieldtrip/public/issubfield.m b/external/fieldtrip/public/issubfield.m new file mode 100644 index 0000000..ff54060 --- /dev/null +++ b/external/fieldtrip/public/issubfield.m @@ -0,0 +1,42 @@ +function [r] = issubfield(s, f) + +% ISSUBFIELD tests for the presence of a field in a structure just like the standard +% Matlab ISFIELD function, except that you can also specify nested fields +% using a '.' in the fieldname. The nesting can be arbitrary deep. +% +% Use as +% f = issubfield(s, 'fieldname') +% or as +% f = issubfield(s, 'fieldname.subfieldname') +% +% This function returns true if the field is present and false if the field +% is not present. +% +% See also ISFIELD, GETSUBFIELD, SETSUBFIELD + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: issubfield.m 951 2010-04-21 18:24:01Z roboos $ + +try + getsubfield(s, f); % if this works, then the subfield must be present + r = true; +catch + r = false; % apparently the subfield is not present +end diff --git a/external/fieldtrip/public/istrue.m b/external/fieldtrip/public/istrue.m new file mode 100644 index 0000000..9b60c44 --- /dev/null +++ b/external/fieldtrip/public/istrue.m @@ -0,0 +1,42 @@ +function y = istrue(x) + +% ISTRUE ensures that a true/false input argument like "yes", "true" +% or "on" is converted into a boolean + +% Copyright (C) 2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: istrue.m 951 2010-04-21 18:24:01Z roboos $ + +true_list = {'yes' 'true' 'on' 'y' }; +false_list = {'no' 'false' 'off' 'n' 'none'}; + +if ischar(x) + % convert string to boolean value + if any(strcmpi(x, true_list)) + y = true; + elseif any(strcmpi(x, false_list)) + y = false; + else + error('cannot determine whether "%s" should be interpreted as true or false', x); + end +else + % convert numerical value to boolean + y = logical(x); +end + diff --git a/external/fieldtrip/public/keep.m b/external/fieldtrip/public/keep.m new file mode 100644 index 0000000..a5f7be0 --- /dev/null +++ b/external/fieldtrip/public/keep.m @@ -0,0 +1,49 @@ +function keep(varargin) + +% KEEP clears all the variables in the workspace except the ones you specify +% after the keep command. It works just like clear, but only for variables +% +% KEEP is a modified version of the KEEP M-file written by +% Xiaoning (David) Yang (1998). It allows the use of the wildcard * as in the +% clear command +% +% Examples: +% keep set1data set2data set3data +% keep *data +% +% Martin Barugel (mbarugel@utdt.edu) + +% Keep all +if isempty(varargin) | sum(strcmp('*',varargin))>=1 + return +end + +% See what are in caller workspace +wh = evalin('caller','who'); + +del=' '; +for i=1:length(wh) + del=[del wh{i} ' ']; +end + +% Check workspace variables +if isempty(wh) + error(' There is nothing to keep!') +end + +% Create string of variables to be cleared +for i=1:length(varargin) + name=varargin{i}; + name=strrep(name,'*','\w*'); + [s,f]=regexp(del,['\s' name '\s']); + for j=1:length(s) + del(s(j):f(j))=char(32*ones(1,f(j)-s(j)+1)); + end +end + +% Clear them +if length(del)==sum(isspace(del)) + return +else + evalin('caller',['clear ' del]); +end diff --git a/external/fieldtrip/public/keyval.m b/external/fieldtrip/public/keyval.m new file mode 100644 index 0000000..36422c0 --- /dev/null +++ b/external/fieldtrip/public/keyval.m @@ -0,0 +1,70 @@ +function [val, remaining] = keyval(key, varargin) + +% KEYVAL returns the value that corresponds to the requested key in a +% key-value pair list of variable input arguments +% +% Use as +% [val] = keyval(key, varargin) +% +% See also VARARGIN + +% Copyright (C) 2005-2007, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: keyval.m 1394 2010-07-10 21:02:48Z roboos $ + +if length(varargin)==1 && iscell(varargin{1}) + varargin = varargin{1}; +end + +if mod(length(varargin),2) + error('optional input arguments should come in key-value pairs, i.e. there should be an even number'); +end + +% the 1st, 3rd, etc. contain the keys, the 2nd, 4th, etc. contain the values +keys = varargin(1:2:end); +vals = varargin(2:2:end); + +% the following is faster than cellfun(@isstr, keys) +valid = false(size(keys)); +for i=1:numel(keys) + valid = ischar(keys{i}); +end + +if ~all(valid) + error('optional input arguments should come in key-value pairs, the optional input argument %d is invalid (should be a string)', i); +end + +hit = find(strcmpi(key, keys)); +if isempty(hit) + % the requested key was not found + val = []; +elseif length(hit)==1 + % the requested key was found + val = vals{hit}; +else + error('multiple input arguments with the same name'); +end + +if nargout>1 + % return the remaining input arguments with the key-value pair removed + keys(hit) = []; + vals(hit) = []; + remaining = cat(1, keys(:)', vals(:)'); + remaining = remaining(:)'; +end diff --git a/external/fieldtrip/public/keyval2cfg.m b/external/fieldtrip/public/keyval2cfg.m new file mode 100644 index 0000000..fbb3677 --- /dev/null +++ b/external/fieldtrip/public/keyval2cfg.m @@ -0,0 +1,36 @@ +function [cfg] = keyval2cfg(varargin); + +% KEYVAL2CFG converts between a structure and a cell-array with key-value +% pairs which can be used for optional input arguments. +% +% Use as +% [cfg] = keyval2cfg(varargin) + +% Copyright (C) 2006, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: keyval2cfg.m 951 2010-04-21 18:24:01Z roboos $ + +if iscell(varargin) && length(varargin)==1 + varargin = varargin{1}; +end + +% assign the optional key-value arguments to a configuration structure +var = varargin(1:2:length(varargin)); % get the odd arguments +val = varargin(2:2:length(varargin)); % get the even arguments +cfg = cell2struct(val(:), var(:), 1); diff --git a/external/fieldtrip/public/keyvalcheck.m b/external/fieldtrip/public/keyvalcheck.m new file mode 100644 index 0000000..dd4f5a1 --- /dev/null +++ b/external/fieldtrip/public/keyvalcheck.m @@ -0,0 +1,82 @@ +function keyvalcheck(arglist, varargin) + +% KEYVALCHECK is a helper function for parsing optional key-value input pairs. +% +% Use as +% keyvalcheck(argin, 'required', {'key1', 'key2', ...}) +% keyvalcheck(argin, 'forbidden', {'key1', 'key2', ...}) +% keyvalcheck(argin, 'optional', {'key1', 'key2', ...}) +% +% See also KEYVAL + +% Copyright (C) 2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: keyvalcheck.m 951 2010-04-21 18:24:01Z roboos $ + +% this is to speed up subsequent calls with the same input arguments +persistent previous_argin + +current_argin = {arglist, varargin{:}}; +if ~isempty(previous_argin) && isequal(previous_argin, current_argin) + % the input is the same to the previous input, and that was OK + return +end + +required = keyval('required', varargin); +forbidden = keyval('forbidden', varargin); +optional = keyval('optional', varargin); + +keys = arglist(1:2:end); +vals = arglist(2:2:end); + +if numel(keys)~=numel(vals) + error('optional input arguments should come in key-value pairs, i.e. there should be an even number'); +end + +keys = cellfun(@lower, keys, 'UniformOutput', false); + +if ~isempty(required) + % only check if specified + required = cellfun(@lower, required, 'UniformOutput', false); + set = intersect(keys, required); + if numel(set)~=numel(required) + error('the required input argument ''%s'' was not specified', set{:}); + end +end + +if ~isempty(forbidden) + % only check if specified + forbidden = cellfun(@lower, forbidden, 'UniformOutput', false); + set = intersect(keys, forbidden); + if numel(set)~=0 + error('the input argument ''%s'' is forbidden', set{:}); + end +end + +if ~isempty(optional) + % only check if specified + optional = cellfun(@lower, optional, 'UniformOutput', false); + set = setdiff(keys, optional); + if numel(set)>0 + error('the input argument ''%s'' is forbidden', set{:}); + end +end + +% remember the current input arguments, which appear to be OK +previous_argin = current_argin; diff --git a/external/fieldtrip/public/match_str.m b/external/fieldtrip/public/match_str.m new file mode 100644 index 0000000..602b2f1 --- /dev/null +++ b/external/fieldtrip/public/match_str.m @@ -0,0 +1,75 @@ +function [sel1, sel2] = match_str(a, b); + +% MATCH_STR looks for matching labels in two listst of strings +% and returns the indices into both the 1st and 2nd list of the matches. +% They will be ordered according to the first input argument. +% +% [sel1, sel2] = match_str(strlist1, strlist2) +% +% The strings can be stored as a char matrix or as an vertical array of +% cells, the matching is done for each row. + +% Copyright (C) 2000, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: match_str.m 951 2010-04-21 18:24:01Z roboos $ + +% ensure that both are cell-arrays +if isempty(a) + a = {}; +elseif ~iscell(a) + a = cellstr(a); +end +if isempty(b) + b = {}; +elseif ~iscell(b) + b = cellstr(b); +end + +% regardless of what optimizations are implemented, the code should remain +% functionally compatible to the original, which is +% for i=1:length(a) +% for j=1:length(b) +% if strcmp(a(i),b(j)) +% sel1 = [sel1; i]; +% sel2 = [sel2; j]; +% end +% end +% end + +% ensure that both are column vectors +a = a(:); +b = b(:); +Na = numel(a); +Nb = numel(b); + +% replace all unique strings by a unique number and use the fact that +% numeric comparisons are much faster than string comparisons +[dum1, dum2, c] = unique([a; b]); +a = c(1:Na); +b = c((Na+1):end); + +sel1 = []; +sel2 = []; +for i=1:length(a) + % s = find(strcmp(a(i), b)); % for string comparison + s = find(a(i)==b); % for numeric comparison + sel2 = [sel2; s]; + s(:) = i; + sel1 = [sel1; s]; +end diff --git a/external/fieldtrip/public/nearest.m b/external/fieldtrip/public/nearest.m new file mode 100644 index 0000000..ebf16fa --- /dev/null +++ b/external/fieldtrip/public/nearest.m @@ -0,0 +1,73 @@ +function [i] = nearest(array, val) + +% NEAREST return the index of an array nearest to a scalar +% +% [indx] = nearest(array, val) + +% Copyright (C) 2002, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: nearest.m 951 2010-04-21 18:24:01Z roboos $ + +mbreal(array); +mbreal(val); + +mbvector(array); +mbscalar(val); + +% ensure that it is a column vector +array = array(:); + +if isnan(val) + error('incorrect value') +end + +if val>max(array) + % return the last occurence of the nearest number + [dum, i] = max(flipud(array)); + i = length(array) + 1 - i; +else + % return the first occurence of the nearest number + [mindist, i] = min(abs(array(:) - val)); +end + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function mbreal(a) +if ~isreal(a) + error('Argument to mbreal must be real'); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function mbscalar(a) +if ~all(size(a)==1) + error('Argument to mbscalar must be scalar'); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function mbvector(a) +if ndims(a) > 2 | (size(a, 1) > 1 & size(a, 2) > 1) + error('Argument to mbvector must be a vector'); +end + diff --git a/external/fieldtrip/public/printstruct.m b/external/fieldtrip/public/printstruct.m new file mode 100644 index 0000000..30bd610 --- /dev/null +++ b/external/fieldtrip/public/printstruct.m @@ -0,0 +1,153 @@ +function str = printstruct(name, val) + +% PRINTSTRUCT converts a Matlab structure to text which can be +% interpreted by Matlab, resulting in the original structure. + +% Copyright (C) 2006, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: printstruct.m 951 2010-04-21 18:24:01Z roboos $ + +str = []; +if isstruct(val) + if numel(val)>1 + % this function cannot print struct arrays with multiple elements + str = sprintf('%s = ''FIXME'';', name); + return + else + % print it as a named structure + fn = fieldnames(val); + for i=1:length(fn) + fv = getfield(val, fn{i}); + switch class(fv) + case 'char' + % line = sprintf('%s = ''%s'';\n', fn{i}, fv); + % line = [name '.' line]; + line = printstr([name '.' fn{i}], fv); + str = [str line]; + case {'single' 'double'} + line = printmat([name '.' fn{i}], fv); + str = [str line]; + case {'int8' 'int16' 'int32' 'int64' 'uint8' 'uint16' 'uint32' 'uint64'} + line = printmat([name '.' fn{i}], fv); + str = [str line]; + case 'cell' + line = printcell([name '.' fn{i}], fv); + str = [str line]; + case 'struct' + line = printstruct([name '.' fn{i}], fv); + str = [str line]; + otherwise + error('unsupported'); + end + end + end +elseif ~isstruct(val) + % print it as a named variable + switch class(val) + case 'char' + str = printstr(name, val); + case 'double' + str = printmat(name, val); + case {'int8' 'int16' 'int32' 'int64' 'uint8' 'uint16' 'uint32' 'uint64'} + str = printmat(name, val); + case 'cell' + str = printcell(name, val); + otherwise + error('unsupported'); + end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function str = printcell(name, val) +str = []; +siz = size(val); +if isempty(val) + str = sprintf('%s = {};\n', name); + return; +end +for i=1:prod(siz) + typ{i} = class(val{i}); +end +for i=2:prod(siz) + if ~strcmp(typ{i}, typ{1}) + warning('different elements in cell array'); + return + end +end +if all(size(val)==1) + str = sprintf('%s = { %s };\n', name, printval(val{1})); +else + str = sprintf('%s = {\n', name); + for i=1:siz(1) + dum = ''; + for j=1:siz(2) + dum = [dum ' ' printval(val{i,j})]; + end + str = sprintf('%s%s\n', str, dum); + end + str = sprintf('%s};\n', str); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function str = printmat(name, val) +str = []; +siz = size(val); +if any(size(val)==0) + str = sprintf('%s = [];\n', name); +elseif all(size(val)==1) + str = sprintf('%s = %s;\n', name, printval(val)); +elseif size(val,1)==1 + dum = sprintf('%g ', str, val(:)); + str = sprintf('%s = [%s];\n', name, dum); +else + str = sprintf('%s = [\n', name); + for i=1:siz(1) + dum = sprintf('%g ', val(i,:)); + str = sprintf('%s %s\n', str, dum); + end + str = sprintf('%s];\n', str); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function str = printstr(name, val) +str = []; +siz = size(val); +if siz(1)~=1 + str = sprintf('%s = \n', name); + for i=1:siz(1) + str = [str sprintf(' %s\n', printval(val(i,:)))]; + end +else + str = sprintf('%s = %s;\n', name, printval(val)); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function str = printval(val) +str = []; +switch class(val) + case 'char' + str = sprintf('''%s''', val); + case 'double' + str = sprintf('%g', val); + case {'int8' 'int16' 'int32' 'int64' 'uint8' 'uint16' 'uint32' 'uint64'} + str = sprintf('%d', val); + case 'struct' + str = '''FIXME'''; +end + diff --git a/external/fieldtrip/public/private/avgoverdim.m b/external/fieldtrip/public/private/avgoverdim.m new file mode 100644 index 0000000..466d6ab --- /dev/null +++ b/external/fieldtrip/public/private/avgoverdim.m @@ -0,0 +1,125 @@ +function data = avgoverdim(data, avgdim) + +% get all XXXdimord fields +fn = fieldnames(data); +selfn = find(~cellfun('isempty', strfind(fn, 'dimord'))); +fn = fn(selfn); +for k = 1:numel(fn) + fndimord{k} = data.(fn{k}); +end + +% check which XXXdimord fields contain the avgdim and keep only those +selx = ~cellfun('isempty', strfind(fndimord, avgdim)); +fn = fn(selx); +fndimord = fndimord(selx); + +% extract the selected dimension as number +for k = 1:numel(fn) + dimtok = tokenize(fndimord{k}, '_'); + avgdimnum{k} = find(strcmp(avgdim, dimtok)); % the selected dimension as number + if numel(avgdimnum{k})<1 && strcmp(avgdim, 'rpt'), + %try 'rpttap' + avgdimnum{k} = find(strcmp('rpttap', dimtok)); + avgdim = 'rpttap'; + end +end + +if sum(~cellfun('isempty', avgdimnum))<1 + error('the "%s" dimension is not present in the data', avgdim) +elseif any(cellfun(@numel, avgdimnum)>1) + error('cannot average over multiple dimensions at the same time') +end + +[reduceddim, fntmp] = dimlength(data); +selx = find(ismember(fntmp, fn)); +reduceddim = reduceddim(selx); +fntmp = fntmp(selx); + +% extract the fieldnames of the parameters of interest +if numel(fntmp)==1 && strcmp(fntmp{1}, 'dimord'), + % data is not source data + param = selparam(data); + reduceddim = repmat(reduceddim, [1 numel(param)]); + avgdimnum = repmat(avgdimnum, [1 numel(param)]); +else + for k = 1:numel(fntmp) + param{1,k} = fntmp{k}(1:end-6); + end +end + +for i = 1:numel(param) + fprintf('averaging %s over %s\n', param{i}, avgdim); + + reduceddim{i}(avgdimnum{i}) = 1; + tmp = data.(param{i}); + iscelltmp = iscell(tmp); + if ~iscelltmp, + %temporarily convert to cell + tmp = {tmp}; + else + %keep cells but reduce avgdimnum + avgdimnum{i} = avgdimnum{i} - 1; %FIXME this only works if cell is 1D + reduceddim{i} = [reduceddim{i}(2:end) 1]; + end + + if avgdimnum{i}>0, + % average each of the cells + for j = 1:numel(tmp) + tmp{j} = reshape(nanmean(tmp{j}, avgdimnum{i}), reduceddim{i}); + end + else + % not yet implemented + error('averaging across cells is not yet possible'); + end + + if ~iscelltmp, + tmp = tmp{1}; + end + data.(param{i}) = tmp; +end + +switch avgdim + case 'rpt' + for i = 1:length(param) + fprintf('removing dimension %s from %s\n', avgdim, param{i}); + tmp = data.(param{i}); + tmp = reshape(tmp, [reduceddim{i}(2:end) 1]); + data.(param{i}) = tmp; + end + data.dimord = ''; + for i = 2:length(dimtok) + data.dimord = [data.dimord,'_',dimtok{i}]; + end + data.dimord = data.dimord(2:end); + if isfield(data, 'cumsumcnt'), data.cumsumcnt = sum(data.cumsumcnt); end + if isfield(data, 'cumtapcnt'), data.cumtapcnt = sum(data.cumtapcnt); end + + case 'rpttap' + for i=1:length(param) + fprintf('removing dimension %s from %s\n', avgdim, param{i}); + warning('this is only allowed for cross-spectra and power-spectra'); + tmp = data.(param{i}); + tmp = reshape(tmp, [reduceddim{i}(2:end) 1]); + data.(param{i}) = tmp; + end + data.dimord = ''; + for i=2:length(dimtok) + data.dimord = [data.dimord,'_',dimtok{i}]; + end + data.dimord = data.dimord(2:end); + if isfield(data, 'cumsumcnt'), data.cumsumcnt = sum(data.cumsumcnt); end + if isfield(data, 'cumtapcnt'), data.cumtapcnt = sum(data.cumtapcnt); end + + case 'chan' + data.label = avgoverlabel(data.label); + case 'freq' + data.freq = mean(data.freq); + case 'time' + data.time = mean(data.time); + otherwise + error('unknown dimension "%s"', avgdim); +end + +if isfield(data, 'dim'), + data.dim(avgdimnum{1}) = []; +end diff --git a/external/fieldtrip/public/private/avgoverlabel.m b/external/fieldtrip/public/private/avgoverlabel.m new file mode 100644 index 0000000..5dff077 --- /dev/null +++ b/external/fieldtrip/public/private/avgoverlabel.m @@ -0,0 +1,6 @@ +function str = avgoverlabel(label) + +str = sprintf('%s, ', label{:}); +str = str(1:(end-2)); +str = sprintf('mean(%s)', str); +str = {str}; diff --git a/external/fieldtrip/public/private/data2raw.m b/external/fieldtrip/public/private/data2raw.m new file mode 100644 index 0000000..f54b427 --- /dev/null +++ b/external/fieldtrip/public/private/data2raw.m @@ -0,0 +1,166 @@ +function [data, dimord] = data2raw(data); + +% DATA2RAW is a helper function that converts various types of averages to +% raw data. This function is used to apply the analysis steps that were +% written for use on preprocessed data also on averaged data. +% +% This function is used in FREQANALYSIS, MEGREALIGN, MEGPLANAR, MEGREPAIR + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: data2raw.m 952 2010-04-21 18:29:51Z roboos $ + +% determine the type of input data +if isfield(data, 'label') && ~isfield(data, 'avg') && isfield(data, 'trial') && iscell(data.trial) + dimord = []; % output of PREPROCESSING +elseif isfield(data, 'label') && isfield(data, 'avg') && ~isfield(data, 'trial') && ~isfield(data, 'individual') + dimord = 'chan_time'; % output of TIMELOCKANALYSIS with keeptrials=no or TIMELOCKGRANDAVERAGE with keepindividual=no +elseif isfield(data, 'label') && isfield(data, 'avg') && isfield(data, 'trial') && ~isfield(data, 'individual') + dimord = 'rpt_chan_time'; % output of TIMELOCKANALYSIS with keeptrials=yes +elseif isfield(data, 'label') && isfield(data, 'avg') && ~isfield(data, 'trial') && isfield(data, 'individual') + dimord = 'subj_chan_time'; % output of TIMELOCKGRANDAVERAGE with keepindividual=yes +elseif isfield(data, 'pos') && isfield(data, 'avg') && isfield(data.avg, 'mom') + % determine the number of source components or orientations + mom = data.avg.mom{data.inside(1)}; + if size(mom,1)==1 + dimord = 'source_time'; + else + error('the source activity should be projected on a single orientation'); + end +elseif isfield(data, 'pos') && isfield(data, 'trial') && isfield(data.trial, 'mom') + % determine the number of source components or orientations + mom = data.trial(1).mom{data.inside(1)}; + if size(mom,1)==1 + dimord = 'rpt_source_time'; + else + error('the source activity should be projected on a single orientation'); + end +else + warning('unrecognized input data'); + dimord = []; +end + +if isempty(dimord) + % nothing to do + return +end + +% convert the input data into raw output, which resembles the output of PREPROCESSING +switch dimord + case 'chan_time' + fprintf('converting average to raw data with only a single trial\n'); + data.trial{1} = data.avg; + data.time = {data.time}; + data = rmfield(data, 'avg'); + + case 'rpt_chan_time' + fprintf('converting timelocked trials to raw trials\n'); + tmptrial = {}; + tmptime = {}; + ntrial = size(data.trial,1); + nchan = size(data.trial,2); + ntime = size(data.trial,3); + for i=1:ntrial + tmptrial{i} = reshape(data.trial(i,:,:), [nchan, ntime]); + tmptime{i} = data.time; + end + data = rmfield(data, 'trial'); + data.trial = tmptrial; + data.time = tmptime; + + case 'subj_chan_time' + fprintf('converting individual subject averages to raw trials\n'); + tmptrial = {}; + tmptime = {}; + ntrial = size(data.individual,1); + nchan = size(data.individual,2); + ntime = size(data.individual,3); + for i=1:ntrial + tmptrial{i} = reshape(data.individual(i,:,:), [nchan, ntime]); + tmptime{i} = data.time; + end + data = rmfield(data, 'individual'); + data.trial = tmptrial; + data.time = tmptime; + + case 'source_time' + fprintf('converting average source reconstructed timecourse to a raw trial\n'); + nsource = length(data.inside); + ntime = size(data.avg.mom{data.inside(1)},2); % use the first dipole to determine the length + tmptrial = {}; + tmptime = {}; + tmptrial{1} = zeros(nsource, ntime); + for j=1:nsource + mom = data.avg.mom{data.inside(j)}; + tmptrial{1}(j,:) = mom; + end + tmptime{1} = data.time; + data = rmfield(data, 'avg'); + % add fake raw channel data to the original data structure + data.trial = tmptrial; + data.time = tmptime; + % add fake channel labels + data.label = {}; + for i=1:length(data.inside) + data.label{i} = sprintf('source%d', data.inside(i)); + end + data.label = data.label(:); + + case 'rpt_source_time' + fprintf('converting single-trial source reconstructed timecourses to raw trials\n'); + ntrial = length(data.trial); + nsource = length(data.inside); + ntime = size(data.trial(1).mom{data.inside(1)},2); % use the first trial and dipole to determine the length + tmptrial = {}; + tmptime = {}; + for i=1:ntrial + tmptrial{i} = zeros(nsource, ntime); + for j=1:nsource + mom = data.trial(i).mom{data.inside(j)}; + tmptrial{i}(j,:) = mom; + end + tmptime{i} = data.time; + end + data = rmfield(data, 'trial'); + % add fake raw channel data to the original data structure + data.trial = tmptrial; + data.time = tmptime; + % add fake channel labels + data.label = {}; + for i=1:length(data.inside) + data.label{i} = sprintf('source%d', data.inside(i)); + end + data.label = data.label(:); + + otherwise + % nothing to do + +end + +% raw data is supposed to contain the sampling frequency +if ~isfield(data, 'fsample') + % compute the sampling frequency from the first two timepoints + data.fsample = 1/(data.time{1}(2)-data.time{1}(1)); +end + +% these fields cannot be used by the external functions that want the data in raw format +if isfield(data, 'avg'), data = rmfield(data, 'avg'); end +if isfield(data, 'var'), data = rmfield(data, 'var'); end +if isfield(data, 'cov'), data = rmfield(data, 'cov'); end +if isfield(data, 'blcov'), data = rmfield(data, 'blcov'); end diff --git a/external/fieldtrip/public/private/dimlength.m b/external/fieldtrip/public/private/dimlength.m new file mode 100644 index 0000000..9078793 --- /dev/null +++ b/external/fieldtrip/public/private/dimlength.m @@ -0,0 +1,163 @@ +function [n, fn] = dimlength(data, seldim, fld) + +% DIMLENGTH(DATA, SELDIM, FLD) is a helper function to obtain n, the number of elements +% along dimension seldim from the appropriate field from the input data containing +% functional data. The output n It can be called with one input argument only. In that case +% If called with one input argument only, it will output two cell arrays containing the size +% of the functional fields, based on the XXXdimord, and the corresponding XXXdimord fields. +% When the data contains a single dimord field (everything except source data), the cell-arrays +% in the output only contain one element. + +if nargin<3 + fld = 'dimord'; +end + +% get all fields of the data structure +fn = fieldnames(data); + +% get all dimord like fields +selfn = find(~cellfun('isempty', strfind(fn, 'dimord'))); +fn = fn(selfn); +for k = 1:numel(fn) + fndimord{k} = data.(fn{k}); +end + +% call recursively to get the dimensionality of all fields XXX +% which are accompanied by a XXXdimord field +% or of the dimord (if not source data) +if nargin==1 + for k = 1:numel(fndimord) + dimtok = tokenize(fndimord{k}, '_'); + ndim = numel(dimtok); + n{k,1} = zeros(1, ndim); + for i = 1:ndim + n{k}(i) = dimlength(data, dimtok{i}, fn{k}); + end + end + return +end + +switch seldim + case 'rpt' + if numel(fld)>6 && isfield(data, fld(1:end-6)), + % source level data + dimtok = tokenize(data.(fld), '_'); + tmp = data.(fld(1:end-6)); + if iscell(tmp) + if isfield(data, 'inside'), + ix = data.inside(1); + else + ix = 1; + end + tmp = tmp{ix}; + dimtok = dimtok(2:end); + end + ix = find(~cellfun('isempty', strfind(dimtok, seldim))); + n = size(tmp, ix); + + elseif strcmp(data.(fld), 'rpt_pos') + %HACK to be fixed + x = setdiff(fld(data),'inside'); + for k = 1:length(x) + dims = size(getsubfield(data,x{k})); + if dims(2)==size(data.pos,1) && numel(dims)==2, + n = dims(1); + return + end + end + + elseif strcmp(data.(fld), 'rpt_pos_freq'), + %HACK to be fixed + x = fld(data); + for k = 1:length(x) + dims = size(getsubfield(data,x{k})); + if dims(2)==size(data.pos,1) && (numel(dims)==2 || dims(3)==length(data.freq)), + n = dims(1); + return + end + end + + elseif strcmp(data.(fld), 'rpt_pos_time'), + %HACK to be fixed + x = fld(data); + for k = 1:length(x) + dims = size(getsubfield(data,x{k})); + if dims(2)==size(data.pos,1) && (numel(dims)==2 || dims(3)==length(data.time)), + n = dims(1); + return + end + end + + elseif strcmp(data.(fld)(1:4), 'rpt_') + n = []; + if isfield(data, 'cov'), n = [n size(data.cov, 1)]; end + if isfield(data, 'crsspctrm'), n = [n size(data.crsspctrm, 1)]; end + if isfield(data, 'powcovspctrm'), n = [n size(data.powcovspctrm, 1)]; end + if isfield(data, 'powspctrm'), n = [n size(data.powspctrm, 1)]; end + if isfield(data, 'trial'), n = [n size(data.trial, 1)]; end + if isfield(data, 'fourierspctrm'), n = [n size(data.fourierspctrm, 1)]; end + + if ~all(n==n(1)), error('inconsistent number of repetitions for dim "%s"', seldim); end + n = n(1); + else + %error('cannot determine number of repetitions for dim "%s"', seldim); + n = nan; + end + + case 'rpttap' + if numel(fld)>6 && isfield(data, fld(1:end-6)), + dimtok = tokenize(data.(fld), '_'); + tmp = data.(fld(1:end-6)); + if iscell(tmp) + if isfield(data, 'inside'), + ix = data.inside(1); + else + ix = 1; + end + tmp = tmp{ix}; + dimtok = dimtok(2:end); + end + ix = find(~cellfun('isempty', strfind(dimtok, seldim))); + n = size(tmp, ix); + + elseif strcmp(data.(fld)(1:7), 'rpttap_') + n = []; + if isfield(data, 'cov'), n = [n size(data.cov, 1)]; end + if isfield(data, 'crsspctrm'), n = [n size(data.crsspctrm, 1)]; end + if isfield(data, 'powcovspctrm'), n = [n size(data.powcovspctrm, 1)]; end + if isfield(data, 'powspctrm'), n = [n size(data.powspctrm, 1)]; end + if isfield(data, 'trial'), n = [n size(data.trial, 1)]; end + if isfield(data, 'fourierspctrm'), n = [n size(data.fourierspctrm, 1)]; end + + if ~all(n==n(1)), error('inconsistent number of repetitions for dim "%s"', seldim); end + n = n(1); + else + %error('cannot determine number of repetitions for dim "%s"', seldim); + n = nan; + end + + case 'chan' + if ~isfield(data, 'inside'), + try, + n = length(data.label); + catch + n = size(data.labelcmb, 1); + end + else + n = nan; %FIXME discuss appending label to source-like data + end + case 'freq' + n = length(data.freq); + case 'time' + n = length(data.time); + case {'pos' '{pos}'} + n = size(data.pos,1); + case {'ori'} + if isfield(data, 'ori'), + n = size(data.ori,1); + else + n = 1; + end + otherwise + error('unsupported dim "%s"', seldim); +end diff --git a/external/fieldtrip/public/private/fixcsd.m b/external/fieldtrip/public/private/fixcsd.m new file mode 100644 index 0000000..102d19f --- /dev/null +++ b/external/fieldtrip/public/private/fixcsd.m @@ -0,0 +1,356 @@ +function [data] = fixcsd(data, desired, channelcmb) + +% FIXCSD converts univariate frequency domain data (fourierspctrm) into a bivariate +% representation (crsspctrm), or changes the representation of bivariate frequency +% domain data (sparse/full/sparsewithpow, sparsewithpow only works for crsspctrm or +% fourierspctrm) + +% Copyright (C) 2010, Jan-Mathijs Schoffelen, Robert Oostenveld + +if isfield(data, 'crsspctrm') && isfield(data, 'powspctrm') + current = 'sparsewithpow'; +elseif isfield(data, 'powspctrm') + current = 'sparsewithpow'; +elseif isfield(data, 'fourierspctrm') && ~isfield(data, 'labelcmb') + current = 'fourier'; +elseif ~isfield(data, 'labelcmb') + current = 'full'; +elseif isfield(data, 'labelcmb') + current = 'sparse'; +else + error('Could not determine the current representation of the %s matrix', param); +end + +% first go from univariate fourier to the required bivariate representation +if strcmp(current, 'fourier') && strcmp(desired, 'fourier') + % nothing to do +elseif strcmp(current, 'fourier') && strcmp(desired, 'sparsewithpow') + dimtok = tokenize(data.dimord, '_'); + if ~isempty(strmatch('rpttap', dimtok)), + nrpt = length(data.cumtapcnt); + flag = 0; + else + nrpt = 1; + flag = 1; + end + if ~isempty(strmatch('freq', dimtok)), nfrq=length(data.freq); else nfrq = 1; end + if ~isempty(strmatch('time', dimtok)), ntim=length(data.time); else ntim = 1; end + + fastflag = all(data.cumtapcnt(:)==data.cumtapcnt(1)); + + %create auto-spectra + nchan = length(data.label); + if fastflag + % all trials have the same amount of tapers + powspctrm = zeros(nrpt,nchan,nfrq,ntim); + ntap = data.cumtapcnt(1); + for p = 1:ntap + powspctrm = powspctrm + abs(data.fourierspctrm(p:ntap:end,:,:,:,:)).^2; + end + powspctrm = powspctrm./ntap; + else + % different amount of tapers + powspctrm = zeros(nrpt,nchan,nfrq,ntim)+i.*zeros(nrpt,nchan,nfrq,ntim); + sumtapcnt = [0;cumsum(data.cumtapcnt(:))]; + for p = 1:nrpt + indx = (sumtapcnt(p)+1):sumtapcnt(p+1); + tmpdat = data.fourierspctrm(indx,:,:,:); + powspctrm(p,:,:,:) = (sum(tmpdat.*conj(tmpdat),1))./data.cumtapcnt(p); + end + end + + %create cross-spectra + if ~isempty(channelcmb), + ncmb = size(channelcmb,1); + cmbindx = zeros(ncmb,2); + labelcmb = cell(ncmb,2); + for k = 1:ncmb + ch1 = find(strcmp(data.label, channelcmb(k,1))); + ch2 = find(strcmp(data.label, channelcmb(k,2))); + if ~isempty(ch1) && ~isempty(ch2), + cmbindx(k,:) = [ch1 ch2]; + labelcmb(k,:) = data.label([ch1 ch2])'; + end + end + + crsspctrm = zeros(nrpt,ncmb,nfrq,ntim)+i.*zeros(nrpt,ncmb,nfrq,ntim); + if fastflag + for p = 1:ntap + tmpdat1 = data.fourierspctrm(p:ntap:end,cmbindx(:,1),:,:,:); + tmpdat2 = data.fourierspctrm(p:ntap:end,cmbindx(:,2),:,:,:); + crsspctrm = crsspctrm + tmpdat1.*conj(tmpdat2); + end + crsspctrm = crsspctrm./ntap; + else + for p = 1:nrpt + indx = (sumtapcnt(p)+1):sumtapcnt(p+1); + tmpdat1 = data.fourierspctrm(indx,cmbindx(:,1),:,:); + tmpdat2 = data.fourierspctrm(indx,cmbindx(:,2),:,:); + crsspctrm(p,:,:,:) = (sum(tmpdat1.*conj(tmpdat2),1))./data.cumtapcnt(p); + end + end + data.crsspctrm = crsspctrm; + data.labelcmb = labelcmb; + end + data.powspctrm = powspctrm; + data = rmfield(data, 'fourierspctrm'); + if ntim>1, + data.dimord = 'chan_freq_time'; + else + data.dimord = 'chan_freq'; + end + + if nrpt>1, + data.dimord = ['rpt_',data.dimord]; + end + + if flag, siz = size(data.crsspctrm); data.crsspctrm = reshape(data.crsspctrm, siz(2:end)); end +elseif strcmp(current, 'fourier') && strcmp(desired, 'sparse') + + if isempty(channelcmb), error('no channel combinations are specified'); end + dimtok = tokenize(data.dimord, '_'); + if ~isempty(strmatch('rpttap', dimtok)), + nrpt = length(data.cumtapcnt); + flag = 0; + else + nrpt = 1; + flag = 1; + end + if ~isempty(strmatch('freq', dimtok)), nfrq=length(data.freq); else nfrq = 1; end + if ~isempty(strmatch('time', dimtok)), ntim=length(data.time); else ntim = 1; end + ncmb = size(channelcmb,1); + cmbindx = zeros(ncmb,2); + labelcmb = cell(ncmb,2); + for k = 1:ncmb + ch1 = find(strcmp(data.label, channelcmb(k,1))); + ch2 = find(strcmp(data.label, channelcmb(k,2))); + if ~isempty(ch1) && ~isempty(ch2), + cmbindx(k,:) = [ch1 ch2]; + labelcmb(k,:) = data.label([ch1 ch2])'; + end + end + + crsspctrm = zeros(nrpt,ncmb,nfrq,ntim)+i.*zeros(nrpt,ncmb,nfrq,ntim); + sumtapcnt = [0;cumsum(data.cumtapcnt(:))]; + for p = 1:nrpt + indx = (sumtapcnt(p)+1):sumtapcnt(p+1); + tmpdat1 = data.fourierspctrm(indx,cmbindx(:,1),:,:); + tmpdat2 = data.fourierspctrm(indx,cmbindx(:,2),:,:); + crsspctrm(p,:,:,:) = (sum(tmpdat1.*conj(tmpdat2),1))./data.cumtapcnt(p); + end + data.crsspctrm = crsspctrm; + data.labelcmb = labelcmb; + data = rmfield(data, 'fourierspctrm'); + data = rmfield(data, 'label'); + if ntim>1, + data.dimord = 'chan_freq_time'; + else + data.dimord = 'chan_freq'; + end + + if nrpt>1, + data.dimord = ['rpt_',data.dimord]; + end + + if flag, siz = size(data.crsspctrm); data.crsspctrm = reshape(data.crsspctrm, siz(2:end)); end +elseif strcmp(current, 'fourier') && strcmp(desired, 'full') + + % this is how it is currently and the desired functionality of prepare_freq_matrices + dimtok = tokenize(data.dimord, '_'); + if ~isempty(strmatch('rpttap', dimtok)), + nrpt = length(data.cumtapcnt); + flag = 0; + else + nrpt = 1; + flag = 1; + end + if ~isempty(strmatch('rpttap',dimtok)), nrpt=length(data.cumtapcnt); else nrpt = 1; end + if ~isempty(strmatch('freq', dimtok)), nfrq=length(data.freq); else nfrq = 1; end + if ~isempty(strmatch('time', dimtok)), ntim=length(data.time); else ntim = 1; end + nchan = length(data.label); + crsspctrm = zeros(nrpt,nchan,nchan,nfrq,ntim); + sumtapcnt = [0;cumsum(data.cumtapcnt(:))]; + for k = 1:ntim + for m = 1:nfrq + for p = 1:nrpt + indx = (sumtapcnt(p)+1):sumtapcnt(p+1); + tmpdat = transpose(data.fourierspctrm(indx,:,m,k)); + crsspctrm(p,:,:,m,k) = (tmpdat*tmpdat')./data.cumtapcnt(p); + clear tmpdat; + end + end + end + data.crsspctrm = crsspctrm; + data = rmfield(data, 'fourierspctrm'); + + if ntim>1, + data.dimord = 'chan_chan_freq_time'; + else + data.dimord = 'chan_chan_freq'; + end + + if nrpt>1, + data.dimord = ['rpt_',data.dimord]; + end + + if flag, siz = size(data.crsspctrm); data.crsspctrm = reshape(data.crsspctrm, siz(2:end)); end + +end % from fourier to the requested bivariate representation + +% from one bivariate representation to another +if isequal(current, desired) + % nothing to do + +elseif (strcmp(current, 'full') && strcmp(desired, 'fourier')) || ... + (strcmp(current, 'sparse') && strcmp(desired, 'fourier')) || ... + (strcmp(current, 'sparsewithpow') && strcmp(desired, 'fourier')) + % this is not possible + error('converting the cross-spectrum into a Fourier representation is not possible'); + +elseif strcmp(current, 'full') && strcmp(desired, 'sparsewithpow') + error('not yet implemented'); +elseif strcmp(current, 'sparse') && strcmp(desired, 'sparsewithpow') + % convert back to crsspctrm/powspctrm representation: useful for plotting functions etc + error( 'not yet implemented'); +elseif strcmp(current, 'full') && strcmp(desired, 'sparse') + dimtok = tokenize(data.dimord, '_'); + if ~isempty(strmatch('rpt', dimtok)), nrpt=numel(data.cumtapcnt); else nrpt = 1; end + if ~isempty(strmatch('freq', dimtok)), nfrq=numel(data.freq); else nfrq = 1; end + if ~isempty(strmatch('time', dimtok)), ntim=numel(data.time); else ntim = 1; end + nchan = length(data.label); + ncmb = nchan*nchan; + labelcmb = cell(ncmb, 2); + cmbindx = zeros(nchan, nchan); + k = 1; + for j=1:nchan + for m=1:nchan + labelcmb{k, 1} = data.label{m}; + labelcmb{k, 2} = data.label{j}; + cmbindx(m,j) = k; + k = k+1; + end + end + + % reshape all possible fields + fn = fieldnames(data); + for ii=1:numel(fn) + if numel(data.(fn{ii})) == nrpt*ncmb*nfrq*ntim; + if nrpt>1, + data.(fn{ii}) = reshape(data.(fn{ii}), nrpt, ncmb, nfrq, ntim); + else + data.(fn{ii}) = reshape(data.(fn{ii}), ncmb, nfrq, ntim); + end + end + end + % remove obsolete fields + data = rmfield(data, 'label'); + try, data = rmfield(data, 'dof'); end + % replace updated fields + data.labelcmb = labelcmb; + if ntim>1, + data.dimord = 'chancmb_freq_time'; + else + data.dimord = 'chancmb_freq'; + end + + if nrpt>1, + data.dimord = ['rpt_',data.dimord]; + end + +elseif strcmp(current, 'sparsewithpow') && strcmp(desired, 'sparse') + + % this representation for sparse data contains autospectra + % as e.g. {'A' 'A'} in labelcmb + if isfield(data, 'crsspctrm'), + dimtok = tokenize(data.dimord, '_'); + catdim = match_str(dimtok, {'chan' 'chancmb'}); + data.crsspctrm = cat(catdim, data.powspctrm, data.crsspctrm); + data.labelcmb = [data.label(:) data.label(:); data.labelcmb]; + data = rmfield(data, 'powspctrm'); + else + data.crsspctrm = data.powspctrm; + data.labelcmb = [data.label(:) data.label(:)]; + data = rmfield(data, 'powspctrm'); + end + data = rmfield(data, 'label'); + +elseif strcmp(current, 'sparse') && strcmp(desired, 'full') + dimtok = tokenize(data.dimord, '_'); + if ~isempty(strmatch('rpt', dimtok)), nrpt=numel(data.cumtapcnt); else nrpt = 1; end + if ~isempty(strmatch('freq', dimtok)), nfrq=numel(data.freq); else nfrq = 1; end + if ~isempty(strmatch('time', dimtok)), ntim=numel(data.time); else ntim = 1; end + + if ~isfield(data, 'label') + data.label = unique(data.labelcmb(:)); + end + + nchan = length(data.label); + ncmb = size(data.labelcmb,1); + cmbindx = zeros(nchan,nchan); + + for k = 1:size(data.labelcmb,1) + ch1 = find(strcmp(data.label, data.labelcmb(k,1))); + ch2 = find(strcmp(data.label, data.labelcmb(k,2))); + if ~isempty(ch1) && ~isempty(ch2), + cmbindx(ch1,ch2) = k; + end + end + + complete = all(cmbindx(:)~=0); + + fn = fieldnames(data); + for ii=1:numel(fn) + if numel(data.(fn{ii})) == nrpt*ncmb*nfrq*ntim; + if nrpt==1, + data.(fn{ii}) = reshape(data.(fn{ii}), [nrpt ncmb nfrq ntim]); + end + + tmpall = nan(nrpt,nchan,nchan,nfrq,ntim); + + for j = 1:nrpt + for k = 1:ntim + for m = 1:nfrq + tmpdat = nan(nchan,nchan); + indx = find(cmbindx); + if ~complete + % this realizes the missing combinations to be represented as the + % conjugate of the corresponding combination across the diagonal + tmpdat(indx) = reshape(data.(fn{ii})(j,cmbindx(indx),m,k),[numel(indx) 1]); + tmpdat = ctranspose(tmpdat); + end + tmpdat(indx) = reshape(data.(fn{ii})(j,cmbindx(indx),m,k),[numel(indx) 1]); + tmpall(j,:,:,m,k) = tmpdat; + end % for m + end % for k + end % for j + + % replace the data in the old representation with the new representation + if nrpt>1, + data.(fn{ii}) = tmpall; + else + data.(fn{ii}) = reshape(tmpall, [nchan nchan nfrq ntim]); + end + end % if numel + end % for ii + + % remove obsolete fields + try, data = rmfield(data, 'powspctrm'); end + try, data = rmfield(data, 'labelcmb'); end + try, data = rmfield(data, 'dof'); end + + if ntim>1, + data.dimord = 'chan_chan_freq_time'; + else + data.dimord = 'chan_chan_freq'; + end + + if nrpt>1, + data.dimord = ['rpt_',data.dimord]; + end + +elseif strcmp(current, 'sparsewithpow') && strcmp(desired, 'full') + % this is how is currently done in prepare_freq_matrices + data = checkdata(data, 'cmbrepresentation', 'sparse'); + data = checkdata(data, 'cmbrepresentation', 'full'); + +end diff --git a/external/fieldtrip/public/private/fixdimord.m b/external/fieldtrip/public/private/fixdimord.m new file mode 100644 index 0000000..36c3dba --- /dev/null +++ b/external/fieldtrip/public/private/fixdimord.m @@ -0,0 +1,172 @@ +function [data] = fixdimord(data, keepsourcedimord); + +% FIXDIMORD ensures consistency between the dimord string and the axes +% that describe the data dimensions. The main purpose of this function +% is to ensure backward compatibility of all functions with data that has +% been processed by older FieldTrip versions +% +% Use as +% [data] = fixdimord(data) +% This will modify the data.dimord field to ensure consistency. +% The name of the axis is the same as the name of the dimord, i.e. if +% dimord='freq_time', then data.freq and data.time should be present. +% +% The default dimensions in the data are described by +% 'time' +% 'freq' +% 'chan' +% 'refchan' +% 'rpt' +% 'subj' +% 'chancmb' +% 'rpttap' + +% Copyright (C) 2009, Robert Oostenveld, Jan-Mathijs Schoffelen +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: fixdimord.m 1018 2010-05-03 15:07:06Z jansch $ + +if nargin<2, keepsourcedimord = 0; end + +if strcmp('volume', datatype(data)) || strcmp('source', datatype(data)); + if isfield(data, 'dimord') && ~keepsourcedimord + % data should not have a dimord (is not implemented yet, but some + % functions add a dimord to these data which leads to unexpected behavior) + warning(sprintf('unexpected dimord "%s", dimord is removed from data', data.dimord)); + data = rmfield(data, 'dimord'); + return + else + %is okay + return + end +end + +if ~isfield(data, 'dimord') + if ~isfield(data, 'trial') || ~iscell(data.trial) || ... + ~isfield(data, 'time') || ~iscell(data.time) || ... + ~isfield(data, 'label') || ~iscell(data.label) + error('The data does not contain a dimord, but it also does not resemble raw data'); + elseif isfield(data, 'topo') + % the data resembles a component decomposition + data.dimord = 'chan_comp'; + else + % the data does not contain a dimord, but it resembles raw data -> that's ok + return + end +end + +dimtok = tokenize(data.dimord, '_'); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +for i=1:length(dimtok) + switch dimtok{i} + case {'tim' 'time' 'toi' 'latency'} + dimtok{i} = 'time'; + + case {'frq' 'freq' 'foi' 'frequency'} + dimtok{i} = 'freq'; + + case {'sgn' 'label' 'chan'} + dimtok{i} = 'chan'; + + case {'rpt' 'trial'} + dimtok{i} = 'rpt'; + + case {'subj' 'subject'} + dimtok{i} = 'subj'; + + case {'comp'} + % don't change, it is ok + + case {'sgncmb' 'labelcmb' 'chancmb'} + dimtok{i} = 'chan'; + + case {'rpttap'} + % this is a 2-D field, coding trials and tapers along the same dimension + % don't change, it is ok + + case {'refchan'} + % don't change, it is ok + + case {'vox' 'repl' 'wcond'} + % these are used in some fieldtrip functions, but are not considered standard + warning(sprintf('unexpected dimord "%s"', data.dimord)); + + case {'pos'} + % this will be the future default for simple sources + + otherwise + error(sprintf('unexpected dimord "%s"', data.dimord)); + + end % switch dimtok +end % for length dimtok + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +if isfield(data, 'tim'), data.time = data.tim ; data = rmfield(data, 'tim') ; end +if isfield(data, 'toi'), data.time = data.toi ; data = rmfield(data, 'toi') ; end +if isfield(data, 'latency'), data.time = data.latency ; data = rmfield(data, 'latency') ; end +if isfield(data, 'frq'), data.freq = data.frq ; data = rmfield(data, 'frq') ; end +if isfield(data, 'foi'), data.freq = data.foi ; data = rmfield(data, 'foi') ; end +if isfield(data, 'frequency'), data.freq = data.frequency ; data = rmfield(data, 'frequency') ; end +if isfield(data, 'sgn'), data.label = data.sgn ; data = rmfield(data, 'sgn') ; end +if isfield(data, 'chan'), data.label = data.chan ; data = rmfield(data, 'chan') ; end +% if isfield(data, 'trial'), data.rpt = data.trial ; data = rmfield(data, 'trial') ; end % DO NOT CONVERT -> this is an exception +if isfield(data, 'subject'), data.subj = data.subject ; data = rmfield(data, 'subject') ; end +if isfield(data, 'sgncmb'), data.labelcmb = data.sgncmb ; data = rmfield(data, 'sgncmb') ; end +if isfield(data, 'chancmb'), data.labelcmb = data.chancmb ; data = rmfield(data, 'chancmb') ; end + +% ensure that it is a column +if isfield(data, 'label') + data.label = data.label(:); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% if isfield(data, 'trial') +% mat = data.trial; +% elseif isfield(data, 'individual') +% mat = data.individual; +% elseif isfield(data, 'avg') +% mat = data.avg; +% elseif isfield(data, 'crsspctrm') +% mat = data.crsspctrm; +% elseif isfield(data, 'powspctrm') +% mat = data.powspctrm; +% elseif isfield(data, 'fourierspctrm') +% mat = data.fourierspctrm; +% end +% +% add the descriptive axis for each dimension +% for i=1:length(dimtok) +% if isfield(data, dimtok{i}) +% % the dimension is already described with its own axis +% % data = setfield(data, dimtok{i}, getfield(data, dimtok{i})); +% else +% % add an axis to the output data +% data = setfield(data, dimtok{i}, 1:size(mat,i)); +% end +% end + +% undo the tokenization +data.dimord = dimtok{1}; +for i=2:length(dimtok) + data.dimord = [data.dimord '_' dimtok{i}]; +end + diff --git a/external/fieldtrip/public/private/fixdipole.m b/external/fieldtrip/public/private/fixdipole.m new file mode 100644 index 0000000..363fd34 --- /dev/null +++ b/external/fieldtrip/public/private/fixdipole.m @@ -0,0 +1,52 @@ +function dip = fixdipole(dip) + +% FIXDIPOLE ensures that the dipole position and moment are +% consistently represented throughout FieldTrip functions. + +% Copyright (C) 2009, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: fixdipole.m 946 2010-04-21 17:51:16Z roboos $ + +[m, n] = size(dip.pos); + +if n==3 + % the input representation is Nx3, which is what we want +elseif m==3 + % it is possible to translate it into a Nx3 unambiguously + warning('input dipole positions should be specified as Nx3 matrix'); + dip.pos = dip.pos'; +elseif m==1 + % it is possible to translate it into a Nx3 unambiguously + warning('input dipole positions should be specified as Nx3 matrix'); + dip.pos = reshape(dip.pos, 3, n/3)'; +else + % it is not clear how to convert to a Nx3 matrix + error('input dipole positions should be specified as Nx3 matrix'); +end + +if isfield(dip, 'mom') + ndip = size(dip.pos,1); + if numel(dip.mom)==ndip*3 + ntime = 1; + else + ntime = numel(dip.mom)/(ndip*3); + end + dip.mom = reshape(dip.mom, ndip*3, ntime); +end + diff --git a/external/fieldtrip/public/private/fixinside.m b/external/fieldtrip/public/private/fixinside.m new file mode 100644 index 0000000..c7b91d8 --- /dev/null +++ b/external/fieldtrip/public/private/fixinside.m @@ -0,0 +1,81 @@ +function [source] = fixinside(source, opt); + +% FIXINSIDE ensures that the region of interest (which is indicated by the +% field "inside") is consistently defined for source structures and volume +% structures. Furthermore, it solves backward compatibility problems. +% +% Use as +% [source] = fixinside(source, 'logical'); +% or +% [source] = fixinside(source, 'index'); + +% Copyright (C) 2006, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: fixinside.m 952 2010-04-21 18:29:51Z roboos $ + + +if nargin<2 + opt = 'logical'; +end + +if ~isfield(source, 'inside') + if isfield(source, 'pos') + % assume that all positions are inside the region of interest + source.inside = [1:size(source.pos,1)]'; + source.outside = []; + elseif isfield(source, 'dim') + source.inside = [1:prod(source.dim)]'; + source.outside = []; + end +end + +if ~isfield(source, 'inside') + % nothing to do + return; +end + +% determine the format +if isa(source.inside, 'logical') + logicalfmt = 1; +elseif all(source.inside(:)==0 | source.inside(:)==1) + source.inside = logical(source.inside); + logicalfmt = 1; +else + logicalfmt = 0; +end + +if ~logicalfmt && strcmp(opt, 'logical') + % convert to a logical array + if ~isfield(source, 'outside') + source.outside = []; + end + inside(source.inside) = (1==1); % true + inside(source.outside) = (1==0); % false + source.inside = inside(:); + if isfield(source, 'outside') + source = rmfield(source, 'outside'); + end +elseif logicalfmt && strcmp(opt, 'index') + % convert to a vectors with indices + tmp = source.inside; + source.inside = find( tmp(:)); + source.outside = find(~tmp(:)); +else + % nothing to do +end diff --git a/external/fieldtrip/public/private/fixsource.m b/external/fieldtrip/public/private/fixsource.m new file mode 100644 index 0000000..76af965 --- /dev/null +++ b/external/fieldtrip/public/private/fixsource.m @@ -0,0 +1,320 @@ +function [output] = fixsource(input, varargin) + +% FIXSOURCE converts old style source structures into new style source structures and the +% other way around +% +% Use as: +% sourcerestyle(input, type) +% where input is a source structure, +% +% Typically, old style source structures contain +% avg.XXX or trial.XXX fields +% +% The ne wstyle source structure contains: +% source.pos +% source.dim (optional, if the list of positions describes a 3D volume +% source.XXX the old style subfields in avg/trial +% source.XXXdimord string how to interpret the respective XXX field: +% e.g. source.leadfield = cell(1,Npos), source.leadfielddimord = '{pos}_chan_ori' +% source.mom = cell(1,Npos), source.momdimord = '{pos}_ori_rpttap' + +type = keyval('type', varargin{:}); +haspow = keyval('haspow', varargin{:}); + +if isempty(type), type = 'old'; end +if isempty(haspow), haspow = 'no'; end + +fnames = fieldnames(input); +tmp = cell2mat(strfind(fnames, 'dimord')); %get dimord like fields +if any(tmp>1), + current = 'new'; +elseif any(tmp==1), + %don't know what to do yet data is JM's own invention + current = 'old'; +else + current = 'old'; +end + +if strcmp(current, type), + %do nothing + output = input; + + %return +elseif strcmp(current, 'old') && strcmp(type, 'new'), + %go from old to new + + if isfield(input, 'avg'), + stuff = getfield(input, 'avg'); + output = rmfield(input, 'avg'); + elseif isfield(input, 'trial'), + stuff = getfield(input, 'trial'); + output = rmfield(input, 'trial'); + else + %this could occur later in the pipeline, e.g. when doing group statistics using individual subject + %descriptive statistics + error('the input does not contain an avg or trial field'); + end + + %------------------------------------------------- + %remove and rename the specified fields if present + removefields = {'xgrid';'ygrid';'zgrid';'method'}; + renamefields = {'frequency' 'freq'; 'csdlabel' 'orilabel'}; + fnames = fieldnames(output); + for k = 1:numel(fnames) + ix = strmatch(fnames{k}, removefields); + if ~isempty(ix), + output = rmfield(output, fnames{k}); + end + ix = strmatch(fnames{k}, renamefields(:,1), 'exact'); + if ~isempty(ix), + output = setfield(output, renamefields{ix,2}, ... + getfield(output, renamefields{ix,1})); + output = rmfield(output, fnames{k}); + end + end + + %---------------------------------------------------------------------- + %put the stuff originally in avg or trial one level up in the structure + fnames = fieldnames(stuff(1)); + npos = size(input.pos,1); + nrpt = numel(stuff); + for k = 1:numel(fnames) + if nrpt>1, + %multiple trials + %(or subjects FIXME not yet implemented, nor tested) + tmp = getfield(stuff(1), fnames{k}); + siz = size(tmp); + if isfield(input, 'cumtapcnt') && strcmp(fnames{k}, 'mom') + %pcc based mom is orixrpttap + %tranpose to keep manageable + for kk = 1:numel(input.inside) + indx = input.inside(kk); + tmp{indx} = permute(tmp{indx}, [2 1 3]); + end + nrpttap = sum(input.cumtapcnt); + sizvox = [size(tmp{input.inside(1)}) 1]; + sizvox = [nrpttap sizvox(2:end)]; + elseif strcmp(fnames{k}, 'mom'), + %this is then probably not a frequency based mom + nrpttap = numel(stuff); + sizvox = [size(tmp{input.inside(1)}) 1]; + sizvox = [nrpttap sizvox]; + elseif iscell(tmp) + nrpttap = numel(stuff); + sizvox = [size(tmp{input.inside(1)}) 1]; + sizvox = [nrpttap sizvox]; + end + + if siz(1) ~= npos && siz(2) ==npos, + tmp = transpose(tmp); + end + + if iscell(tmp) + %allocate memory for cell-array + tmpall = cell(npos,1); + for n = 1:numel(input.inside) + tmpall{input.inside(n)} = zeros(sizvox); + end + else + %allocate memory for matrix + tmpall = zeros([npos nrpt siz(2:end)]); + end + + cnt = 0; + for m = 1:nrpt + tmp = getfield(stuff(m), fnames{k}); + siz = size(tmp); + if siz(1) ~= npos && siz(2) ==npos, + tmp = transpose(tmp); + end + + if ~iscell(tmp), + tmpall(:,m,:,:,:) = tmp; + else + for n = 1:numel(input.inside) + indx = input.inside(n); + tmpdat = tmp{indx}; + if isfield(input, 'cumtapcnt') && strcmp(fnames{k}, 'mom'), + if n==1, siz1 = size(tmpdat,2); end + else + if n==1, siz1 = 1; end + end + tmpall{indx}(cnt+[1:siz1],:,:,:,:) = tmpdat; + if n==numel(input.inside), cnt = cnt + siz1; end + end + end + end + output = setfield(output, fnames{k}, tmpall); + newdimord = createdimord(output, fnames{k}, 1); + if ~isempty(newdimord) + output = setfield(output, [fnames{k},'dimord'], newdimord); + end + + else + tmp = getfield(stuff, fnames{k}); + siz = size(tmp); + if isfield(input, 'cumtapcnt') && strcmp(fnames{k}, 'mom') + %pcc based mom is orixrpttap + %tranpose to keep manageable + for kk = 1:numel(input.inside) + indx = input.inside(kk); + tmp{indx} = permute(tmp{indx}, [2 1 3]); + end + end + if siz(1) ~= npos && siz(2) ==npos, + tmp = transpose(tmp); + end + output = setfield(output, fnames{k}, tmp); + newdimord = createdimord(output, fnames{k}); + if ~isempty(newdimord) + output = setfield(output, [fnames{k},'dimord'], newdimord); + end + end + end + + if isfield(output, 'csdlabel') + output = setfield(output, 'orilabel', getfield(output, 'csdlabel')); + output = rmfield(output, 'csdlabel'); + end + + if isfield(output, 'leadfield') + % add dimord to leadfield as well. since the leadfield is not in + % the original .avg or .trial field it has not yet been taken care of + output.leadfielddimord = createdimord(output, 'leadfield'); + end + + if isfield(output, 'ori') + % convert cell-array ori into matrix + ori = zeros(3,npos) + nan; + try, + ori(:,output.inside) = cat(2, output.ori{output.inside}); + catch + %when oris are in wrong orientation (row rather than column) + for k = 1:numel(output.inside) + ori(:,output.inside(k)) = output.ori{output.inside(k)}'; + end + end + output.ori = ori; + end + current = 'new'; + +elseif strcmp(current, 'new') && strcmp(type, 'old') + %go from new to old + error('not implemented yet'); +end + +if strcmp(current, 'new') && strcmp(haspow, 'yes'), + + %---------------------------------------------- + %convert mom into pow if requested and possible + convert = 0; + if isfield(output, 'mom') && size(output.mom{output.inside(1)},2)==1, + convert = 1; + else + warning('conversion from mom to pow is not possible, either because there is no mom in the data, or because the dimension of mom>1. in that case call ft_sourcedescriptives first with cfg.projectmom'); + end + + if isfield(output, 'cumtapcnt') + convert = 1 & convert; + else + warning('conversion from mom to pow will not be done, because cumtapcnt is missing'); + end + + if convert, + npos = size(output.pos,1); + nrpt = numel(output.cumtapcnt); + tmpmom = cat(2,output.mom{output.inside}); + tmppow = zeros(npos, nrpt); + tapcnt = [0;cumsum(output.cumtapcnt(:))]; + for k = 1:nrpt + ntap = tapcnt(k+1)-tapcnt(k); + tmppow(output.inside,k) = sum(abs(tmpmom((tapcnt(k)+1):tapcnt(k+1),:)).^2,1)./ntap; + end + output.pow = tmppow; + output.powdimord = ['pos_rpt_freq']; + end + +elseif strcmp(current, 'old') && strcmp(haspow, 'yes') + warning('construction of single trial power estimates is not implemented here using old style source representation'); + +end + + +%-------------------------------------------------------- +function [dimord] = createdimord(output, fname, rptflag); + +if nargin==2, rptflag = 0; end + +tmp = getfield(output, fname); + +dimord = ''; +dimnum = 1; +hasori = isfield(output, 'ori'); %if not, this is probably singleton and not relevant at the end + +if iscell(tmp) && (size(output.pos,1)==size(tmp,dimnum) || size(output.pos,1)==size(tmp,2)) + dimord = [dimord,'{pos}']; + dimnum = dimnum + 1; +elseif ~iscell(tmp) && size(output.pos,1)==size(tmp,dimnum) + dimord = [dimord,'pos']; + dimnum = dimnum + 1; +end + +switch fname + case 'cov' + if hasori, dimord = [dimord,'_ori_ori']; end; + case 'csd' + if hasori, dimord = [dimord,'_ori_ori']; end; + case 'csdlabel' + dimord = dimord; + case 'filter' + dimord = [dimord,'_ori_chan']; + case 'leadfield' + if hasori, + dimord = [dimord,'_chan_ori']; + else + dimord = [dimord,'_chan']; + end + case 'mom' + if isfield(output, 'cumtapcnt') && sum(output.cumtapcnt)==size(tmp{output.inside(1)},1) + if hasori, + dimord = [dimord,'_rpttap_ori']; + else + dimord = [dimord,'_rpttap']; + end + elseif isfield(output, 'time') + if rptflag, + dimord = [dimord,'_rpt']; + dimnum = dimnum + 1; + end + if numel(output.time)==size(tmp{output.inside(1)},dimnum) + dimord = [dimord,'_ori_time']; + end + end + + if isfield(output, 'freq') && numel(output.freq)>1, + dimord = [dimord,'_freq']; + end + case 'nai' + if isfield(output, 'freq') && numel(output.freq)==size(tmp,dimnum) + dimord = [dimord,'_freq']; + end + case 'noise' + if isfield(output, 'freq') && numel(output.freq)==size(tmp,dimnum) + dimord = [dimord,'_freq']; + end + case 'noisecsd' + if hasori, dimord = [dimord,'_ori_ori']; end + case 'ori' + dimord = ''; + case 'pow' + if isfield(output, 'cumtapcnt') && numel(output.cumtapcnt)==size(tmp,dimnum) + dimord = [dimord,'_rpt']; + dimnum = dimnum + 1; + end + + if isfield(output, 'freq') && numel(output.freq)>1 && numel(output.freq)==size(tmp,dimnum) + dimord = [dimord,'_freq']; + end + otherwise + error(sprintf('unknown fieldname %s', fname)); +end diff --git a/external/fieldtrip/public/private/fixtrialdef.m b/external/fieldtrip/public/private/fixtrialdef.m new file mode 100644 index 0000000..5637fe6 --- /dev/null +++ b/external/fieldtrip/public/private/fixtrialdef.m @@ -0,0 +1,79 @@ +function data = fixtrialdef(data) + +% FIXTRIALDEF adds a trl matrix to the raw data configuration +% which is constructed on the fly, assuming that the trials are +% consecutive segments of a continuous recording + +% Copyright (C) 2009-2010, Robert Oostenveld and Jan-Mathijs Schoffelen + +if isfield(data, 'trialdef') + return; +end + +if ~isfield(data, 'cfg') + % fieldtrip raw data structures are expected to have a cfg + data.cfg = []; +end + +hastrial = isfield(data, 'trial'); + +if hastrial, + ntrial = length(data.trial); +else + ntrial = dimlength(data, 'rpt'); + if ~isfinite(ntrial) && strcmp(data.dimord(1:6), 'rpttap') && isfield(data, 'cumtapcnt'), + ntrial = numel(data.cumtapcnt); + elseif ~isfinite(ntrial) + ntrial = 1; + end +end + +trl = findcfg(data.cfg, 'trl'); + +nsmp = zeros(ntrial,1); +if hastrial, + for i=1:ntrial + nsmp(i) = size(data.trial{i}, 2); + end +elseif ~isempty(trl) + nsmp = trl(:,2) - trl(:,1) + 1; +end + +if isempty(trl) + warning('the data does not contain a trial definition, assuming that the trials are consecutive segments of a continuous recording'); + % construct a trial definition on the fly, assume that the trials are + % consecutive segments of a continuous recording + if ntrial==1, + begsample = 1; + else + begsample = cat(1, 0, cumsum(nsmp(1:end-1))) + 1; + end + endsample = begsample + nsmp - 1; + offset = zeros(ntrial,1); + for i=1:ntrial + offset(i) = time2offset(data.time{i}, data.fsample); + end + trl = [begsample endsample offset]; + +elseif size(trl,1)~=ntrial + warning('the trial definition in the configuration is inconsistent with the actual data'); + trl = []; +elseif nsmp~=(trl(:,2)-trl(:,1)+1) + warning('the trial definition in the configuration is inconsistent with the actual data'); + trl = []; +end + +if ~isfield(data, 'trialdef') && ~isempty(trl) + data.trialdef = trl(:, 1:2); +elseif ~isfield(data, 'trialdef') && isempty(trl) + warning('failed to create trialdef field'); +end + +if (~isfield(data, 'trialinfo') || isempty(data.trialinfo)) && ~isempty(trl) && size(trl, 2) > 3, + data.trialinfo = trl(:, 4:end); +end + +% if data is not raw then it does not make sense to keep the trialdef +if ~hastrial && isfield(data, 'trialdef') + data = rmfield(data, 'trialdef'); +end diff --git a/external/fieldtrip/public/private/leaveoneout.m b/external/fieldtrip/public/private/leaveoneout.m new file mode 100644 index 0000000..f34e07d --- /dev/null +++ b/external/fieldtrip/public/private/leaveoneout.m @@ -0,0 +1,33 @@ +function data = leaveoneout(data) + +dimtok = tokenize(data.dimord, '_'); +rptdim = find(strcmp('rpt', dimtok)); % the selected dimension as number + +if length(rptdim)<1 + error('the ''rpt'' dimension is not present in the data'); +elseif length(rptdim)>1 + error('cannot jackknife over multiple dimensions at the same time'); +elseif rptdim~=1 + error('jackknife only works if replicates are in the first dimension of the data'); +end + +[reduceddim, fn] = dimlength(data); +if numel(fn)==1 && strcmp(fn{1}, 'dimord'), + %data is not source data + reduceddim = reduceddim{1}; +end +reduceddim(rptdim) = 1; + +param = selparam(data); +for i=1:length(param) + fprintf('computing jackknife %s\n', param{i}); + tmp = data.(param{i}); + nrpt = size(tmp, rptdim); + sumtmp = reshape(nansum(tmp, rptdim), reduceddim); + for k = 1:nrpt + tmp(k,:,:,:,:,:,:) = (sumtmp - tmp(k,:,:,:,:,:,:))./(nrpt-1); + end + data.(param{i}) = tmp; +end + +data.method = 'jackknife'; diff --git a/external/fieldtrip/public/private/nanmean.m b/external/fieldtrip/public/private/nanmean.m new file mode 100644 index 0000000..04a6912 --- /dev/null +++ b/external/fieldtrip/public/private/nanmean.m @@ -0,0 +1,61 @@ +% nanmean() - Average, not considering NaN values +% +% Usage: same as mean() + +% Author: Arnaud Delorme, CNL / Salk Institute, 16 Oct 2002 + +%123456789012345678901234567890123456789012345678901234567890123456789012 + +% Copyright (C) 2001 Arnaud Delorme, Salk Institute, arno@salk.edu +% +% This program is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: nanmean.m 952 2010-04-21 18:29:51Z roboos $ + +function out = nanmean(in, dim) + +if nargin < 1 + help nanmean; + return; +end; +if nargin < 2 + if size(in,1) ~= 1 + dim = 1; + elseif size(in,2) ~= 1 + dim = 2; + else + dim = 3; + end; +end; +tmpin = in; +tmpin(find(isnan(in(:)))) = 0; +out = sum(tmpin, dim) ./ sum(~isnan(in),dim); + diff --git a/external/fieldtrip/public/private/offset2time.m b/external/fieldtrip/public/private/offset2time.m new file mode 100644 index 0000000..df5c5d5 --- /dev/null +++ b/external/fieldtrip/public/private/offset2time.m @@ -0,0 +1,42 @@ +function time = offset2time(offset, fsample, nsamples); + +% OFFSET2TIME converts the offset of a trial definition into a time-axis +% according to the definition from DEFINETRIAL +% +% Use as +% [time] = offset2time(offset, fsample, nsamples) +% +% The trialdefinition "trl" is an Nx3 matrix. The first column contains +% the sample-indices of the begin of the trial relative to the begin +% of the raw data , the second column contains the sample_indices of +% the end of the trials, and the third column contains the offset of +% the trigger with respect to the trial. An offset of 0 means that +% the first sample of the trial corresponds to the trigger. A positive +% offset indicates that the first sample is later than the triger, a +% negative offset indicates a trial beginning before the trigger. + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: offset2time.m 952 2010-04-21 18:29:51Z roboos $ + +% ensure that these are not integers +offset = double(offset); +nsamples = double(nsamples); + +time = (offset + (0:(nsamples-1)))/fsample; diff --git a/external/fieldtrip/public/private/parameterselection.m b/external/fieldtrip/public/private/parameterselection.m new file mode 100644 index 0000000..71a47ce --- /dev/null +++ b/external/fieldtrip/public/private/parameterselection.m @@ -0,0 +1,113 @@ +function [select] = parameterselection(param, data); + +% PARAMETERSELECTION selects the parameters that are present as a volume in the data +% add that have a dimension that is compatible with the specified dimensions of the +% volume, i.e. either as a vector or as a 3D volume. +% +% Use as +% [select] = parameterselection(param, data) +% where +% param cell-array, or single string, can be 'all' +% data structure with anatomical or functional data +% select returns the selected parameters as a cell-array + +% Copyright (C) 2005-2008, Robert oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: parameterselection.m 952 2010-04-21 18:29:51Z roboos $ + +if ischar(param) + param = {param}; % it should be a cell-array +elseif isempty(param) + param = {}; % even being empty, it should be a cell-array +end + +sel = find(strcmp(param, 'all')); +if ~isempty(sel) + % the old default was a list of all known volume parameters + % the new default is to try all fields present in the data + allparam = fieldnames(data); + % fields can be nested in source.avg + if isfield(data, 'avg') + tmp = fieldnames(data.avg); + for i=1:length(tmp) + tmp{i} = ['avg.' tmp{i}]; + end + allparam = cat(1, allparam, tmp); + end + % fields can be nested in source.trial + if isfield(data, 'trial') + tmp = fieldnames(data.trial); + for i=1:length(tmp) + tmp{i} = ['trial.' tmp{i}]; + end + allparam = cat(1, allparam, tmp); + end + param(sel) = []; % remove the 'all' + param = [param(:)' allparam(:)']; % add the list of all possible parameters, these will be tested later +else + % check all specified parameters and give support for some parameters like 'pow' and 'coh' + % which most often will indicate 'avg.pow' and 'avg.coh' + for i=1:length(param) + if ~issubfield(data, param{i}) && issubfield(data, ['avg.' param{i}]) + % replace the parameter xxx by avg.xxx + param{i} = ['avg.' param{i}]; + end + end +end + +% remove empty fields +param(find(cellfun('isempty', param))) = []; + +% ensure that there are no double entries +param = unique(param); + +select = {}; +for i=1:length(param) + if issubfield(data, param{i}) + % the field is present, check whether the dimension is correct + dim = size(getsubfield(data, param{i})); + if isfield(data, 'dim') && isequal(dim(:), data.dim(:)) + select{end+1} = param{i}; + elseif isfield(data, 'dim') && prod(dim)==prod(data.dim) + select{end+1} = param{i}; + elseif isfield(data, 'pos') && prod(dim)==size(data.pos, 1) + select{end+1} = param{i}; + elseif isfield(data, 'dimord') && (isfield(data, 'pos') || isfield(data, 'transform')), + dimtok = tokenize(data.dimord, '_'); + nels = 1; + for k=1:numel(dimtok) + if strcmp(dimtok{k}, 'rpt') || strcmp(dimtok{k}, 'rpttap') + nels = nels*dim(k); + elseif strcmp(dimtok{k}, 'pos') && isfield(data, 'pos') + %for source structure + nels = nels*size(data.pos,1); + elseif strcmp(dimtok{k}, 'pos') + %for volume structure FIXME 'pos' in dimord is not OK + nels = nels*prod(data.dim(1:3)); + else + nels = nels*numel(getfield(data, dimtok{k})); + end + end + if nels==prod(dim), + select{end+1} = param{i}; + end + end + end +end + diff --git a/external/fieldtrip/public/private/pos2dim3d.m b/external/fieldtrip/public/private/pos2dim3d.m new file mode 100644 index 0000000..fb19efd --- /dev/null +++ b/external/fieldtrip/public/private/pos2dim3d.m @@ -0,0 +1,47 @@ +function [dim] = pos2dim3d(pos,dimold) + +% POS2DIM3D reconstructs the volumetric dimensions from an ordered list of +% positions. optionally, the original dim can be provided, and the (2:end) +% elements are appended to the output. +% +% Use as +% [dim] = pos2dim3d(pos, dimold) where pos is an ordered list of positions +% and dimold optionally the original dimensionality of the functional data +% The output dim is a 3+ element vector of which the first three elements +% correspond to the 3D volumetric dimensions + +% Copyright (C) 2009, Jan-Mathijs Schoffelen + +if nargin==1 && ~isstruct(pos), + dimold = zeros(0,2); +elseif isstruct(pos), + %the input is a structure + dimord = pos.dimord; + dimtok = tokenize(dimord, '_'); + for i = 1:length(dimtok) + if strcmp(dimtok{i},'pos'), + dimold(i,1) = size(pos.pos,1); + else + dimold(i,1) = numel(getfield(pos, dimtok{i})); + end + end + pos = pos.pos; +else + if size(pos,1)~=dimold(1), + error('the first element in the second input should be equal to the number of positions'); + end +end + +%this part depends on the assumption that the list of positions is describing a full 3D volume in +%an ordered way which allows for the extraction of a transformation matrix +%i.e. slice by slice +npos = size(pos,1); +dpos = zscore(abs(diff(pos,[],1))); + +[tmp, ind] = max(dpos,[],2); +tmpdim(1) = find(tmp>2,1,'first'); +dpos = dpos(tmpdim:tmpdim:npos-1,:); +[tmp, ind] = max(dpos(:,setdiff(1:3, ind(tmpdim))),[],2); +tmpdim(2) = find(tmp>1.1*min(tmp),1,'first'); %this threshold seems to work on what I tried out +tmpdim(3) = npos./prod(tmpdim); +dim = [tmpdim dimold(2:end)]; diff --git a/external/fieldtrip/public/private/pos2transform.m b/external/fieldtrip/public/private/pos2transform.m new file mode 100644 index 0000000..d04489e --- /dev/null +++ b/external/fieldtrip/public/private/pos2transform.m @@ -0,0 +1,23 @@ +function [transform] = pos2transform(pos) + +% POS2TRANSFORM reconstructs a transformation matrix from an ordered list +% of positions. +% +% Use as +% [transform] = pos2transform(pos, dim) where pos is an ordered list of positions +% and should specify a full 3D volume +% +% The output transform is a 4x4 homogenous transformation matrix which transforms +% from 'voxelspace' into the positions provided in the input + +% Copyright (C) 2009, Jan-Mathijs Schoffelen + +dim = pos2dim3d(pos); +x = 1:dim(1); +y = 1:dim(2); +z = 1:dim(3); +[X,Y,Z] = ndgrid(x, y, z); +ind = [X(:) Y(:) Z(:)]; +ind = ind';ind(4,:) = 1; +pos = pos';pos(4,:) = 1; +transform = pos/ind; diff --git a/external/fieldtrip/public/private/selfromraw.m b/external/fieldtrip/public/private/selfromraw.m new file mode 100644 index 0000000..d732e90 --- /dev/null +++ b/external/fieldtrip/public/private/selfromraw.m @@ -0,0 +1,37 @@ +function [data] = selfromraw(data, varargin) + +selrpt = keyval('rpt', varargin{:}); selectrpt = ~isempty(strmatch(varargin(cellfun(@ischar, varargin)), 'rpt')); +selchan = keyval('chan', varargin{:}); selectchan = ~isempty(strmatch(varargin(cellfun(@ischar, varargin)), 'chan')); + +if selectrpt, + fprintf('selecting %d trials\n', numel(selrpt)); + data.trial = data.trial(selrpt); + data.time = data.time(selrpt); + + % this is new style keeping track of trialdef and trialinfo + if isfield(data, 'trialdef'), data.trialdef = data.trialdef(selrpt, :); end + if isfield(data, 'trialinfo'), data.trialinfo = data.trialinfo(selrpt, :); end + if isfield(data, 'offset'), data.offset = data.offset(selrpt); end + + % this is old style keeping track of trl-matrix + if isfield(data, 'cfg') + trl = findcfg(data.cfg, 'trl'); + else + trl = []; + end + + if isempty(trl) + warning('could not locate the correct trial definition ''trl'' in the data structure'); + else + data.cfg.trlold = trl; + data.cfg.trl = trl(selrpt,:); + end + +end + +if selectchan, + for k = 1:numel(data.trial) + data.trial{k} = data.trial{k}(selchan, :); + end + data.label = data.label(selchan); +end diff --git a/external/fieldtrip/public/private/seloverdim.m b/external/fieldtrip/public/private/seloverdim.m new file mode 100644 index 0000000..d6b12cd --- /dev/null +++ b/external/fieldtrip/public/private/seloverdim.m @@ -0,0 +1,155 @@ +function data = seloverdim(data, seldim, sel) + +% get all XXXdimord fields +fn = fieldnames(data); +selfn = find(~cellfun('isempty', strfind(fn, 'dimord'))); +fn = fn(selfn); +for k = 1:numel(fn) + fndimord{k} = data.(fn{k}); +end + +% check which XXXdimord fields contain the seldim and keep only those +selx = ~cellfun('isempty', strfind(fndimord, seldim)); +fn = fn(selx); +fndimord = fndimord(selx); + +% extract the selected dimension as number +for k = 1:numel(fn) + dimtok = tokenize(fndimord{k}, '_'); + seldimnum{k} = find(strcmp(seldim, dimtok)); % the selected dimension as number + if numel(seldimnum{k})<1 && strcmp(seldim, 'rpt'), + %try rpttap + seldimnum{k} = find(strcmp([seldim,'tap'], dimtok)); + tapflag = 1; + else + tapflag = 0; + end +end + +if sum(~cellfun('isempty', seldimnum))<1 + error('the "%s" dimension is not present in the data', seldim) +elseif any(cellfun(@numel, seldimnum)>1) + error('cannot select over multiple dimensions at the same time') +end + +[reduceddim, fntmp] = dimlength(data); +selx = find(ismember(fntmp, fn)); +reduceddim = reduceddim(selx); +fntmp = fntmp(selx); + +% extract the fieldnames of the parameters of interest +if numel(fntmp)==1 && strcmp(fntmp{1}, 'dimord'), + % data is not source data + param = selparam(data); + reduceddim = repmat(reduceddim, [1 numel(param)]); + seldimnum = repmat(seldimnum, [1 numel(param)]); +else + for k = 1:numel(fntmp) + param{1,k} = fntmp{k}(1:end-6); + end +end + +% make the subselection +for i = 1:numel(param) + fprintf('selection %s along dimension %d\n', param{i}, seldimnum{i}); + + reduceddim{i}(seldimnum{i}) = numel(sel); + tmp = data.(param{i}); + iscelltmp = iscell(tmp); + if ~iscelltmp, + %temporarily convert to cell + tmp = {tmp}; + else + %keep cells but reduce seldimnum + seldimnum{i} = seldimnum{i} - 1; %FIXME this only works if cell is 1D + reduceddim{i} = [reduceddim{i}(2:end) 1]; + end + + if seldimnum{i}>0, + % subselection from each of the cells + for j = 1:numel(tmp) + if ~isempty(tmp{j}), + switch seldimnum{i} + case 1 + tmp{j} = tmp{j}(sel,:,:,:,:,:,:,:,:); + case 2 + tmp{j} = tmp{j}(:,sel,:,:,:,:,:,:,:); + case 3 + tmp{j} = tmp{j}(:,:,sel,:,:,:,:,:,:); + case 4 + tmp{j} = tmp{j}(:,:,:,sel,:,:,:,:,:); + case 5 + tmp{j} = tmp{j}(:,:,:,:,sel,:,:,:,:); + case 6 + tmp{j} = tmp{j}(:,:,:,:,:,sel,:,:,:); + case 7 + tmp{j} = tmp{j}(:,:,:,:,:,:,sel,:,:); + case 8 + tmp{j} = tmp{j}(:,:,:,:,:,:,:,sel,:); + case 9 + tmp{j} = tmp{j}(:,:,:,:,:,:,:,:,sel); + otherwise + error('the number of dimensions is too high'); + end + tmp{j} = reshape(tmp{j}, reduceddim{i}); + end + end + else + % subselection of cells + tmp = tmp(sel); + end + + if ~iscelltmp, + tmp = tmp{1}; + end + data.(param{i}) = tmp; +end + +switch seldim + case 'rpt' + if tapflag && isfield(data, 'cumtapcnt'), + sumtapcnt = cumsum([0;data.cumtapcnt(:)]); + tapers = zeros(1, sumtapcnt(end)); + for i=1:length(data.cumtapcnt) + tapers(sumtapcnt(i)+1:sumtapcnt(i+1)) = i; + end + tmpsel = unique(tapers(sel)); + else + tmpsel = sel; + end + if isfield(data, 'cumtapcnt'), data.cumtapcnt = data.cumtapcnt(tmpsel); end + if isfield(data, 'cumsumcnt'), data.cumsumcnt = data.cumsumcnt(tmpsel); end + + % also try to adjust the trialinfo in the data + if isfield(data, 'trialinfo') + data.trialinfo = data.trialinfo(tmpsel, :); + end + + % also try to adjust the trl description in the configuration + if isfield(data, 'cfg'), %try to locate the trl in the nested configuration + trl = findcfg(data.cfg, 'trl'); + else + trl = []; + end + if isempty(trl) || size(trl,1)1, + %data is source data new style + error('selparam only works with input data which is not of type ''source'''); +end +ndim = length(dim); + +% remove all 1's at the right side of dim +for i=ndim:-1:3 + if dim(i)==1, + dim(i) = []; + ndim = ndim-1; + else + break + end +end + +fn = fieldnames(data); +sel = false(size(fn)); +for i=1:numel(fn) + siz = size(data.(fn{i})); + nsiz = numel(siz); + sel(i) = (nsiz==ndim) && all(siz==dim); +end +param = fn(sel); + +% some fields should be excluded +param = setdiff(param, {'time', 'freq', 'channel','inside'}); diff --git a/external/fieldtrip/public/private/time2offset.m b/external/fieldtrip/public/private/time2offset.m new file mode 100644 index 0000000..5471ed0 --- /dev/null +++ b/external/fieldtrip/public/private/time2offset.m @@ -0,0 +1,38 @@ +function offset = time2offset(time, fsample); + +% TIME2OFFSET converts a time-axis of a trial into the offset in samples +% according to the definition from DEFINETRIAL +% +% Use as +% [offset] = time2offset(time, fsample) +% +% The trialdefinition "trl" is an Nx3 matrix. The first column contains +% the sample-indices of the begin of the trial relative to the begin +% of the raw data , the second column contains the sample_indices of +% the end of the trials, and the third column contains the offset of +% the trigger with respect to the trial. An offset of 0 means that +% the first sample of the trial corresponds to the trigger. A positive +% offset indicates that the first sample is later than the triger, a +% negative offset indicates a trial beginning before the trigger. + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: time2offset.m 952 2010-04-21 18:29:51Z roboos $ + +offset = round(time(1)*fsample); diff --git a/external/fieldtrip/public/progress.m b/external/fieldtrip/public/progress.m new file mode 100644 index 0000000..b39afd9 --- /dev/null +++ b/external/fieldtrip/public/progress.m @@ -0,0 +1,247 @@ +function progress(varargin) + +% PROGRESS shows a graphical or non-graphical progress indication similar +% to the standard Matlab WAITBAR function, but with the extra option of +% printing it in the command window as a plain text string or as a rotating +% dial. Alternatively, you can also specify it not to give feedback on the +% progress. +% +% Prior to the for-loop, you should call either +% progress('init', 'none', 'Please wait...') +% progress('init', 'gui', 'Please wait...') +% progress('init', 'etf', 'Please wait...') % estimated time to finish +% progress('init', 'dial', 'Please wait...') % rotating dial +% progress('init', 'textbar', 'Please wait...') % ascii progress bar +% progress('init', 'text', 'Please wait...') +% progress('init', 'textcr', 'Please wait...') % force cariage return +% progress('init', 'textnl', 'Please wait...') % force newline +% +% In each iteration of the for-loop, you should call either +% progress(x) % only show percentage +% progress(x, 'Processing event %d from %d', i, N) % show string, x=i/N +% +% After finishing the for-loop, you should call +% progress('close') +% +% Here is an example for the use of a progress indicator +% progress('init', 'etf', 'Please wait...'); +% for i=1:42 +% progress(i/42, 'Processing event %d from %d', i, 42); +% pause(0.1); +% end +% progress('close') + +% Copyright (C) 2004-2008, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: progress.m 951 2010-04-21 18:24:01Z roboos $ + +persistent p % the previous value of the progress +persistent c % counter for the number of updates that is done +persistent t0 % initial time, required for ETF +persistent p0 % initial percentage, required for ETF +persistent t % type of feedback, string with none, gui, text, textcr, textnl +persistent h % the handle of the dialog (in case of type=gui) +persistent a % the angle in degrees, for dial or textbar +persistent s % the string containing the title + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +if nargin>1 && ischar(varargin{1}) && strcmp(varargin{1}, 'init') + a = 0; + p = 0; + h = 0; + c = 0; + % determine the type of feedback + t = varargin{2}; + % determine the title of the dialog + if nargin>2 + s = varargin{3}; + else + s = ''; + end + switch t + case 'gui' + % initialise the waitbar dialog + if ~isempty(s) + h = waitbar(0, s); + else + h = waitbar(0, 'Please wait'); + end + case {'text', 'textnl', 'textcr'} + if ~isempty(s) + % print the title to the screen and go to the next line + fprintf('%s\n', s) + end + end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +elseif nargin==1 && ischar(varargin{1}) && strcmp(varargin{1}, 'close') + switch t + case 'gui' + % close the waitbar dialog + close(h); + case {'textcr', 'dial', 'textbar'} + % finish by going to the next line + fprintf('\n'); + end + % reset these to the defaults + a = 0; + h = 0; + p = 0; + t = 'none'; + s = ''; + t0 = []; + p0 = []; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +else + if strcmp(t, 'dial') + % display should always be updated for the dial + % continue; + elseif (varargin{1}-p)<0.01 && strcmp(t, 'gui') + % display should not be updated it the difference is less than one percent + return; + elseif (varargin{1}-p)<0.01 && strcmp(t, 'textbar') + % display should not be updated it the difference is less than one percent + return; + elseif (varargin{1}-p)<0.01 && strcmp(t, 'etf') + % display should not be updated it the difference is less than one percent + return; + end + + % count the number of updates, for debugging + c = c+1; + + % remember the current value for the next function call + p = varargin{1}; + + switch t + case 'gui' + % update the the length of the bar in the waitbar dialog + waitbar(varargin{1}, h); + + case 'etf' + % compute the estimated time that the computation still needs to finish + if isempty(t0) || isempty(p0) + t0 = clock; + p0 = p; + end + elapsed = etime(clock, t0); + if nargin>1 && ~isempty(varargin{2}) + % include the specified string + fprintf(varargin{2:end}); + fprintf(' - estimated time to finish is %d seconds\n', round(elapsed*(1-p)/(p-p0))); + else + % only print the estimated time to finish + fprintf(' - estimated time to finish is %d seconds\n', round(elapsed*(1-p)/(p-p0))); + end + + case 'dial' + dial = '|/-\|/-\'; + if ~isempty(s) + % print the title and draw a new hand of the rotating dial + fprintf('\r%s %s', s, dial(1+a/45)); + else + % draw a new hand of the rotating dial + fprintf('\r%s', dial(1+a/45)); + end + % increment the angle with 45 degrees + a = a + 45; + if a==360 + % reset the angle to 0 degrees + a = 0; + end + + case 'textbar' + dial = '|/-\|/-\'; + % construct the line looking like [------/ ] + len = 75 - length(s) - 3; + len1 = round(p*len); % number of '-' characters before the dial + len2 = len - len1; % number of ' ' characters after the dial + line = [s, ' [' repmat('-',1,len1), dial(1+a/45), repmat(' ',1,len2) ,']']; + fprintf('\r%s', line); + % increment the angle with 45 degrees + a = a + 45; + if a==360 + % reset the angle to 0 degrees + a = 0; + end + + case 'text' + if nargin>1 + % print the string as it is + fprintf(varargin{2:end}); + else + fprintf('%6.2f %%\n', 100*varargin{1}); + end + + case 'textnl' + if nargin>1 + % ensure that the string ends with a newline + if length(varargin{2})>1 && all(varargin{2}((end-1):end) == '\r') + varargin{2}((end-1):end) = '\n'; + elseif length(varargin{2})>1 && ~all(varargin{2}((end-1):end) == '\n') + varargin{2}((end+1):(end+2)) = '\n'; + elseif length(varargin{2})<2 + varargin{2}((end+1):(end+2)) = '\n'; + end + fprintf(varargin{2:end}); + else + fprintf('%6.2f %%\n', 100*varargin{1}); + end + + case 'textcr' + if nargin>1 + % ensure that the string ends with a cariage return + if length(varargin{2})>1 && all(varargin{2}((end-1):end) == '\n') + varargin{2}((end-1):end) = '\r'; + elseif length(varargin{2})>1 && ~all(varargin{2}((end-1):end) == '\r') + varargin{2}((end+1):(end+2)) = '\r'; + elseif length(varargin{2})<2 + varargin{2}((end+1):(end+2)) = '\r'; + end + fprintf(varargin{2:end}); + else + fprintf('%6.2f %%\r', 100*varargin{1}); + end + + end % case gui, dial, text, textnl, textcr +end % updating the displayed value + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% some test code follows +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% progress('init', 'gui'); for i=1:100, progress(i/100, '%d/%d\r', i, 100); end; progress('close') +% progress('init', 'dial'); for i=1:100, progress(i/100, '%d/%d\r', i, 100); end; progress('close') +% progress('init', 'none'); for i=1:100, progress(i/100, '%d/%d\r', i, 100); end; progress('close') + +% progress('init', 'text'); for i=1:100, progress(i/100, '%d/%d' , i, 100); end; progress('close') +% progress('init', 'text'); for i=1:100, progress(i/100, '%d/%d\n', i, 100); end; progress('close') +% progress('init', 'text'); for i=1:100, progress(i/100, '%d/%d\r', i, 100); end; progress('close') + +% progress('init', 'textnl'); for i=1:100, progress(i/100, '%d/%d' , i, 100); end; progress('close') +% progress('init', 'textnl'); for i=1:100, progress(i/100, '%d/%d\n', i, 100); end; progress('close') +% progress('init', 'textnl'); for i=1:100, progress(i/100, '%d/%d\r', i, 100); end; progress('close') + +% progress('init', 'textcr'); for i=1:100, progress(i/100, '%d/%d' , i, 100); end; progress('close') +% progress('init', 'textcr'); for i=1:100, progress(i/100, '%d/%d\n', i, 100); end; progress('close') +% progress('init', 'textcr'); for i=1:100, progress(i/100, '%d/%d\r', i, 100); end; progress('close') + + diff --git a/external/fieldtrip/public/rmsubfield.m b/external/fieldtrip/public/rmsubfield.m new file mode 100644 index 0000000..4d8752f --- /dev/null +++ b/external/fieldtrip/public/rmsubfield.m @@ -0,0 +1,46 @@ +function [s] = rmsubfield(s, f, v); + +% RMSUBFIELD removes the contents of the specified field from a structure +% just like the standard Matlab RMFIELD function, except that you can also +% specify nested fields using a '.' in the fieldname. The nesting can be +% arbitrary deep. +% +% Use as +% s = rmsubfield(s, 'fieldname') +% or as +% s = rmsubfield(s, 'fieldname.subfieldname') +% +% See also SETFIELD, GETSUBFIELD, ISSUBFIELD + +% Copyright (C) 2006, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: rmsubfield.m 951 2010-04-21 18:24:01Z roboos $ + +if ~isstr(f) + error('incorrect input argument for fieldname'); +end + +% remove the nested subfield using recursion +[t, f] = strtok(f, '.'); +if any(f=='.') + u = rmsubfield(getfield(s, t), f); + s = setfield(s, t, u); +else + s = rmfield(s, t); +end diff --git a/external/fieldtrip/public/selectdata.m b/external/fieldtrip/public/selectdata.m new file mode 100644 index 0000000..234b602 --- /dev/null +++ b/external/fieldtrip/public/selectdata.m @@ -0,0 +1,517 @@ +function [data] = selectdata(varargin) + +% this function serves to concatenate the input data-structures along the +% compatible dimensions and thus is a more general implementation of +% appenddata, which deals only with raw data. Moreover, it can be used to equate the +% data of different conditions to match e.g. in channels time-axis etc +% Moreover, it can be used as a generalization to ...average with 'keepindividual' +% +% Finally, this function serves to subselect regions-of-interest from the input data, +% either or not averaging across the specified dimensions. +% +% Supported input data: +% freq +% timelock +% source +% volume (not yet) +% +% supported options: +% foilim +% toilim +% roi +% channel (FIXME this is also done by preprocessing?) +% avgoverchan +% avgoverfreq +% avgovertime +% avgoverroi +% avgoverrpt + +% Copyright (C) 2009, Jan-Mathijs Schoffelen +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: selectdata.m 1338 2010-07-02 09:59:06Z jansch $ + +% check the input data and options +isdata = find(cellfun(@isstruct,varargin)); +keyvals = setdiff(1:length(varargin),isdata); + +data = varargin(isdata); +kvp = varargin(keyvals); +dtype = cell(1,length(data)); +dimord = cell(1,length(data)); + +for k = 1:length(data) + data{k} = checkdata(data{k}, 'datatype', {'freq' 'timelock' 'source', 'volume', 'freqmvar', 'raw'}); + [dtype{k}, dimord{k}] = datatype(data{k}); + if strcmp(dtype{k}, 'raw'), + %ensure it to have an offset + data{k} = checkdata(data{k}, 'datatype', 'raw', 'hasoffset', 'yes'); + end + if strcmp(dtype{k}, 'source'), + data{k} = checkdata(data{k}, 'sourcerepresentation', 'new'); + end +end + +if any(~strmatch(dtype{1},dtype)) + error('different types of input data is not supported'); +end + +% check consistency of input data +if any(~strmatch(dimord{1},dimord)) + error('a different dimord in the input data is not supported'); +end + +israw = strcmp(dtype{1},'raw'); +isfreq = strcmp(dtype{1},'freq'); +istlck = strcmp(dtype{1},'timelock'); +issource = strcmp(dtype{1},'source'); +isvolume = strcmp(dtype{1},'volume'); +isfreqmvar = strcmp(dtype{1},'freqmvar'); + +selchan = keyval('channel', kvp); selectchan = ~isempty(strmatch(kvp(cellfun(@ischar, kvp)), 'channel')); +selfoi = keyval('foilim', kvp); selectfoi = ~isempty(strmatch(kvp(cellfun(@ischar, kvp)), 'foilim')); +seltoi = keyval('toilim', kvp); selecttoi = ~isempty(strmatch(kvp(cellfun(@ischar, kvp)), 'toilim')); +selroi = keyval('roi', kvp); selectroi = ~isempty(strmatch(kvp(cellfun(@ischar, kvp)), 'roi')); +selrpt = keyval('rpt', kvp); selectrpt = ~isempty(strmatch(kvp(cellfun(@ischar, kvp)), 'rpt')); +selpos = keyval('pos', kvp); selectpos = ~isempty(strmatch(kvp(cellfun(@ischar, kvp)), 'pos')); +param = keyval('param', kvp); if isempty(param), param = 'all'; end % FIXME think about this + +avgoverchan = keyval('avgoverchan', kvp); if isempty(avgoverchan), avgoverchan = false; end +avgoverfreq = keyval('avgoverfreq', kvp); if isempty(avgoverfreq), avgoverfreq = false; end +avgovertime = keyval('avgovertime', kvp); if isempty(avgovertime), avgovertime = false; end +avgoverroi = keyval('avgoverroi', kvp); if isempty(avgoverroi), avgoverroi = false; end +avgoverrpt = keyval('avgoverrpt', kvp); if isempty(avgoverrpt), avgoverrpt = false; end +dojack = keyval('jackknife', kvp); if isempty(dojack), dojack = false; end + +% create anonymous function and apply it to the boolean input arguments +istrue = @(x)(ischar(x) && (strcmpi(x, 'yes') || strcmpi(x, 'true')) || (~isempty(x) && numel(x)==1 && x==1)); + +% ensure that these are boolean arguments, optionally convert from "yes"/"no" to true/false +avgoverchan = istrue(avgoverchan); +avgoverfreq = istrue(avgoverfreq); +avgovertime = istrue(avgovertime); +avgoverroi = istrue(avgoverroi); +avgoverrpt = istrue(avgoverrpt); +dojack = istrue(dojack); + +if dojack && avgoverrpt, + error('it is not possible to do both a jackknife and to average across replicates'); +end + +if length(data)>1 && selectrpt, + error('multiple data structures as input is not supported in combination with subselection of trials'); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% concatenate the data +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +if length(data)>1 && ~israw, + % determine the way to concatenate + if issource, + if isfield(data{1}, 'inside') + isboolean = islogical(data{1}.inside); + if isboolean, + for k = 1:numel(data) + data{k} = fixinside(data{k}, 'index'); + end + end + end + end + + %if issource || isvolume, + % param = parameterselection(param, data{1}); % FIXME check consistency across input data of presence of specific parameters + %else + if ~iscell(param), param = {param}; end + %end + if issource || isvolume + if numel(param)>1, + error('selectdata for source inputs works only for one parameter at a time'); + end + dimord(:) = {getfield(data{1}, [param{1},'dimord'])}; + end + dimtok = tokenize(dimord{1}, '_'); + dimtok(strmatch('chan', dimtok)) = {'label'}; % data.chan does not exist + + dimmat = zeros(length(dimtok), length(data)); + dimmat(:,1) = 1; + for k = 1:length(dimtok) + if isempty(strfind(dimtok{k},'rpt')) && isempty(strfind(dimtok{k},'{pos}')) && isempty(strfind(dimtok{k},'ori')), + dimdat = getfield(data{1}, dimtok{k}); + elseif ~isempty(strfind(dimtok{k},'{pos}')), + dimdat = getfield(data{1}, dimtok{k}(2:end-1)); + elseif isempty(strfind(dimtok{k},'ori')), + % dimtok is 'rpt' or 'rpttap' + dimdat = size(getfield(data{1}, param{1}),1); + end + for m = 2:length(data) + if isempty(strfind(dimtok{k},'rpt')) && isempty(strfind(dimtok{k}, '{pos}')) && isempty(strfind(dimtok{k},'ori')), + dimdat2 = getfield(data{m},dimtok{k}); + elseif ~isempty(strfind(dimtok{k},'{pos}')), + dimdat2 = getfield(data{m},dimtok{k}(2:end-1)); + elseif isempty(strfind(dimtok{k},'ori')), + % dimtok is 'rpt' or 'rpttap' + dimdat2 = size(getfield(data{m}, param{1}),1); + end + try, dimmat(k,m) = all(dimdat(:)==dimdat2(:)); catch end; + try, dimmat(k,m) = all(cellfun(@isequal,dimdat,dimdat2)); catch end; + end + end + catdim = find(sum(dimmat,2)1, + error('ambiguous dimensions for concatenation'); + elseif isempty(catdim) && isempty(strmatch('rpt',dimtok)) && isempty(strmatch('rpttap',dimtok)), + %treat as individual observations: prepend a first dimension 'rpt' + %(so this part should be able to cover the functionality of ...grandaverage) + catdim = 0; + elseif isempty(catdim) && (~isempty(strmatch('rpt',dimtok)) || ~isempty(strmatch('rpttap',dimtok))) + %append observations + catdim = 1; + elseif ~isempty(strfind(dimtok{catdim},'pos')) + dimtok{catdim} = 'pos'; + elseif isempty(catdim) + error('don''t know how to concatenate the data'); + end + + % concatenate the data + % FIXME this works for source data, does this also work for volume data? + for k = 1:length(param) + tmp = cell(1,length(data)); + for m = 1:length(tmp) + tmp{m} = getfield(data{m},param{k}); + end + if ~iscell(tmp{1}), + % this is for the 'normal' case + if catdim==0, + ndim = length(size(tmp{1})); + data{1} = setfield(data{1}, param{k}, permute(cat(ndim+1,tmp{:}),[ndim+1 1:ndim])); + else + data{1} = setfield(data{1}, param{k}, cat(catdim,tmp{:})); + end + else + % this is for source data with the positions in a cell-array + npos = numel(tmp{1}); + if catdim==0, + error('not implemented yet'); + elseif catdim==1, + data{1}.(param{k}) = cat(1, tmp{:}); + else + for kk = 1:npos + tmpsiz = size(tmp{1}{kk}); + if ~all(tmpsiz==0) + for kkk = 1:numel(data) + tmp2{kkk} = tmp{kkk}{kk}; + end + data{1}.(param{k}){kk} = cat(catdim-1, tmp2{:}); + else + %keep empty + end + end %for kk = 1:npos + end %if catdim==0 + end %if ~iscell(tmp{1}) + paramdimord{k} = [param{k},'dimord']; + end %for k = 1:numel(param) + + if catdim==0, + %a dimension has been prepended + dimtok = ['rpt' dimtok]; + catdim = 1; + dimord{1} = ['rpt_',dimord{1}]; + if issubfield(data{1}, 'dim'), + dim = [length(data) data{1}.dim]; + end + else + if issubfield(data{1}, 'dim'), + dim = data{1}.dim; + end + end + + % concatenate the relevant descriptive fields in the data-structure + if ~strcmp(dimtok{catdim},'rpt') && ~strcmp(dimtok{catdim},'rpttap'), + for k = 1:length(data) + if k==1, + tmp = getsubfield(data{k}, dimtok{catdim})'; + if isfield(data{k}, 'inside'), + tmpnvox = numel(data{k}.inside)+numel(data{k}.outside); + tmpinside = data{k}.inside(:); + end + else + if strcmp(dimtok{catdim},'pos') + tmp = [tmp; getsubfield(data{k}, dimtok{catdim})]; + tmpinside = [tmpinside; data{k}.inside(:)+tmpnvox]; + tmpnvox = tmpnvox+numel(data{k}.inside)+numel(data{k}.outside); + sortflag = 0; + else + tmp = [tmp getsubfield(data{k}, dimtok{catdim})']; + sortflag = 1; + end + end + end + data{1} = setsubfield(data{1}, dimtok{catdim}, tmp); + if isfield(data{1}, 'inside'), + data{1} = setsubfield(data{1}, 'inside', tmpinside); + data{1} = setsubfield(data{1}, 'outside', setdiff(1:size(data{1}.pos,1)', tmpinside)); + end + + %FIXME think about this + tryfields = {'dof'}; + else + % no such field as {'label','time','freq','pos'} has to be concatenated + sortflag = 0; + tryfields = {'cumsumcnt','cumtapcnt','trialinfo'}; + end + + % concatenate the relevant descriptive fields in the data-structure (continued) + for k = 1:length(tryfields) + try, + for m = 1:length(data) + if m==1, + tmpfield = getfield(data{m}, tryfields{k}); + else + tmpfield = [tmpfield; getfield(data{m}, tryfields{k})]; + end + end + data{1} = setfield(data{1}, tryfields{k}, tmpfield); + catch + end + end + % FIXME handle inside in previous loop + + % FIXME this is ugly: solve it + %if issource || isvolume, + % data{1}.dim(catdim) = max(size(tmp)); + %end + + % sort concatenated data FIXME this is also ugly and depends on tmp + % FIXME if functional data in cell-array no sorting takes place + if sortflag && ~iscell(tmp) && ~iscell(data{1}.(param{1})), + [srt, ind] = sort(tmp, 2); + data{1} = setfield(data{1}, dimtok{catdim}, tmp(ind)); + for k = 1:length(param) + tmp = getsubfield(data{1}, param{k}); + tmp = permute(tmp, [catdim setdiff(1:length(size(tmp)), catdim)]); + tmp = ipermute(tmp(ind,:,:,:,:), [catdim setdiff(1:length(size(tmp)), catdim)]); + data{1} = setfield(data{1}, param{k}, tmp); + end + elseif exist('tmp', 'var') && iscell(tmp) + %in this case (ugly!) tmp is probably a cell-array containing functional data + end + % remove unspecified parameters + if ~issource, + rmparam = setdiff(parameterselection('all',data{1}),[param 'pos' 'inside' 'outside']); + else + rmparam = setdiff(fieldnames(data{1}), [param(:)' paramdimord(:)' 'pos' 'inside' 'outside' 'dim' 'cfg' 'vol' 'cumtapcnt' 'orilabel']); + end + for k = 1:length(rmparam) + data{1} = rmfield(data{1}, rmparam{k}); + end + + % keep the first structure only + data = data{1}; + dimord = dimord{1}; + if ~issource, + data.dimord = dimord; + else + data.([param{1},'dimord']) = dimord; + end + if isfield(data, 'dim') & ~issource, + %data.dim = dim; + data.dim = size(data.(param{1})); + elseif isfield(data, 'dim') + data = rmfield(data, 'dim'); %source data should not contain a dim + %FIXME this should be handled by checkdata once the source structure is + %unequivocally defined + end + +elseif length(data)>1 && israw + error('concatenation of several raw data-structures is done by ''ft_appenddata'''); +else + % nothing to do + data = data{1}; + dimord = dimord{1}; +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% from here on the data is concatenated +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% determine the subselection in the data +if selectrpt && ~israw + if islogical(selrpt), + selrpt = find(selrpt); + elseif isempty(selrpt), + warning('you request all repetitions to be thrown away'); + end + + if ~issource + rpttapflag = ~isempty(strfind(data.dimord, 'rpttap')); + rptflag = ~isempty(strfind(data.dimord, 'rpt')) && ~rpttapflag; + else + fn = fieldnames(data); + selfn = find(~cellfun('isempty', strfind(fn, 'dimord'))); + fn = fn(selfn); + for k = 1:numel(fn) + rpttapflag(k,1) = ~isempty(strfind(data.(fn{k}), 'rpttap')); + rptflag(k,1) = ~isempty(strfind(data.(fn{k}), 'rpt')) && ~rpttapflag(k,1); + end + end + + if any(rpttapflag), + %account for the tapers + sumtapcnt = [0;cumsum(data.cumtapcnt(:))]; + begtapcnt = sumtapcnt(1:end-1)+1; + endtapcnt = sumtapcnt(2:end); + begtapcnt = begtapcnt(selrpt); + endtapcnt = endtapcnt(selrpt); + tapers = zeros(1,sumtapcnt(end)); + for k = 1:length(begtapcnt) + tapers(begtapcnt(k):endtapcnt(k)) = 1; + end + selrpt = find(tapers); + else + % do nothing + end +elseif selectrpt && israw + if islogical(selrpt), + selrpt = find(selrpt); + elseif isempty(selrpt), + warning('you request all repetitions to be thrown away'); + end +end + +if selectchan, + %FIXME give selchan according to the order requested in selchan + %this does not work + tmp = ft_channelselection(selchan, data.label); + [dum, selchan] = match_str(tmp, data.label); +end + +if selectfoi, + if numel(selfoi)==1, selfoi(2) = selfoi; end; + if numel(selfoi)==2, + %treat selfoi as lower limit and upper limit + selfoi = nearest(data.freq, selfoi(1)):nearest(data.freq, selfoi(2)); + else + %treat selfoi as a list of frequencies + for k=1:length(selfoi) + tmpfoi(k) = nearest(data.freq, selfoi(k)); + end + selfoi = tmpfoi; + end +end + +if selecttoi, + if length(seltoi)==1, seltoi(2) = seltoi; end; + seltoi = nearest(data.time, seltoi(1)):nearest(data.time, seltoi(2)); +end + +if selectroi, + error('not yet implemented'); +end + +if israw, + if selectrpt, + data = selfromraw(data, 'rpt', selrpt); + end + + if selectchan, + data = selfromraw(data, 'chan', selchan); + end + +elseif isfreq, + if isfield(data, 'labelcmb') && isfield(data, 'label') && (selectchan || avgoverchan) + error('selection of or averaging across channels in the presence of both label and labelcmb is ambiguous'); + end + + if isfield(data, 'labelcmb'), + %there is a crsspctrm or powcovspctrm field, + %this will only be selectdimmed + %if we apply a trick + tmpdata = data; + tmpdata.label = data.labelcmb; + if selectrpt, tmpdata = seloverdim(tmpdata, 'rpt', selrpt); end + if selectchan, tmpdata = seloverdim(tmpdata, 'chan', selchan); end + if selectfoi, tmpdata = seloverdim(tmpdata, 'freq', selfoi); end + if selecttoi, tmpdata = seloverdim(tmpdata, 'time', seltoi); end + % average over dimensions + if avgoverrpt, tmpdata = avgoverdim(tmpdata, 'rpt'); end + if avgoverfreq, tmpdata = avgoverdim(tmpdata, 'freq'); end + if avgovertime, tmpdata = avgoverdim(tmpdata, 'time'); end + if avgoverchan, error('avgoverchan not yet implemented in this case'); end + if dojack, tmpdata = leaveoneout(tmpdata); end + + if isfield(tmpdata, 'crsspctrm'), crsspctrm = tmpdata.crsspctrm; end + if isfield(tmpdata, 'powcovspctrm'), crsspctrm = tmpdata.powcovspctrm; end + if isfield(tmpdata, 'crsspctrm') || isfield(tmpdata, 'powcovspctrm'), clear tmpdata; end + else + crsspctrm = []; + end + % make the subselection + if selectrpt, data = seloverdim(data, 'rpt', selrpt); end + if selectchan, data = seloverdim(data, 'chan', selchan); end + if selectfoi, data = seloverdim(data, 'freq', selfoi); end + if selecttoi, data = seloverdim(data, 'time', seltoi); end + % average over dimensions + if avgoverrpt, data = avgoverdim(data, 'rpt'); end + if avgoverchan, data = avgoverdim(data, 'chan'); end + if avgoverfreq, data = avgoverdim(data, 'freq'); end + if avgovertime, data = avgoverdim(data, 'time'); end + if dojack, data = leaveoneout(data); end + + if ~isempty(crsspctrm), + if isfield(data, 'crsspctrm'), data.crsspctrm = crsspctrm; end + if isfield(data, 'powcovspctrm'), data.powcovspctrm = crsspctrm; end + end + +elseif istlck, + % make the subselection + if selectrpt, data = seloverdim(data, 'rpt', selrpt); end + if selectchan, data = seloverdim(data, 'chan', selchan); end + if selectfoi, data = seloverdim(data, 'freq', selfoi); end + if selecttoi, data = seloverdim(data, 'time', seltoi); end + % average over dimensions + if avgoverrpt, data = avgoverdim(data, 'rpt'); end + if avgoverchan, data = avgoverdim(data, 'chan'); end + if avgoverfreq, data = avgoverdim(data, 'freq'); end + if avgovertime, data = avgoverdim(data, 'time'); end + if dojack, data = leaveoneout(data); end + +elseif issource, + %FIXME fill in everything + if selectrpt, data = seloverdim(data, 'rpt', selrpt); end + if selectfoi, data = seloverdim(data, 'freq', selfoi); end + if selectpos, data = seloverdim(data, 'pos', selpos); end + if avgoverrpt, data = avgoverdim(data, 'rpt'); end + if avgoverfreq, data = avgoverdim(data, 'freq'); end + +elseif isvolume, + error('this is not yet implemented'); +elseif isfreqmvar, + % make the subselection + if selectrpt, data = seloverdim(data, 'rpt', selrpt); end + if selectchan, data = seloverdim(data, 'chan', selchan); end + if selectfoi, data = seloverdim(data, 'freq', selfoi); end + if selecttoi, data = seloverdim(data, 'time', seltoi); end + % average over dimensions + if avgoverrpt, data = avgoverdim(data, 'rpt'); end + if avgoverchan, data = avgoverdim(data, 'chan'); end + if avgoverfreq, data = avgoverdim(data, 'freq'); end + if avgovertime, data = avgoverdim(data, 'time'); end + if dojack, data = leaveoneout(data); end +end diff --git a/external/fieldtrip/public/setsubfield.m b/external/fieldtrip/public/setsubfield.m new file mode 100644 index 0000000..18f4793 --- /dev/null +++ b/external/fieldtrip/public/setsubfield.m @@ -0,0 +1,46 @@ +function [s] = setsubfield(s, f, v); + +% SETSUBFIELD sets the contents of the specified field to a specified value +% just like the standard Matlab SETFIELD function, except that you can also +% specify nested fields using a '.' in the fieldname. The nesting can be +% arbitrary deep. +% +% Use as +% s = setsubfield(s, 'fieldname', value) +% or as +% s = setsubfield(s, 'fieldname.subfieldname', value) +% +% See also SETFIELD, GETSUBFIELD, ISSUBFIELD + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: setsubfield.m 951 2010-04-21 18:24:01Z roboos $ + +if ~isstr(f) + error('incorrect input argument for fieldname'); +end + +t = {}; +while (1) + [t{end+1}, f] = strtok(f, '.'); + if isempty(f) + break + end +end +s = setfield(s, t{:}, v); diff --git a/external/fieldtrip/public/source2full.m b/external/fieldtrip/public/source2full.m new file mode 100644 index 0000000..3e589a0 --- /dev/null +++ b/external/fieldtrip/public/source2full.m @@ -0,0 +1,320 @@ +function [source] = source2full(source); + +% SOURCE2FULL recreates the grid locations outside the brain in the source +% reconstruction, so that the source volume again describes the full grid. +% This undoes the memory savings that can be achieved using SOURC2SPARSE +% and makes it possible again to plot the source volume and save it to an +% external file. +% +% Use as +% [source] = source2full(source) +% +% See also SOURCE2SPARSE + +% Copyright (C) 2004, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: source2full.m 1402 2010-07-12 19:41:58Z roboos $ + +fieldtripdefs + +if ~isfield(source, 'inside') || ... + ~isfield(source, 'outside') || ... + ~isfield(source, 'dim') + error('one of the required fields is missing in the source structure'); +end + +if ~isfield(source, 'pos') && (~isfield(source, 'xgrid') || ~isfield(source, 'ygrid') || ... + ~isfield(source, 'zgrid')) + error('the input data needs at least a ''pos'' field, or ''x/y/zgrid'''); +end + +if isfield(source, 'xgrid'), + xgrid = source.xgrid; + ygrid = source.ygrid; + zgrid = source.zgrid; + sparsepos = source.pos; + + % recreate the positions of the dipole grid + [X, Y, Z] = ndgrid(xgrid, ygrid, zgrid); + pos = [X(:) Y(:) Z(:)]; +else + %FIXME this assumes that the voxel data are ordered as if in a regularly spaced 3D grid, + %but with only the inside voxels present + warning('assuming the voxel data to be ordered as if in a regularly spaced 3D grid'); + xgrid = 1:source.dim(1); + ygrid = 1:source.dim(2); + zgrid = 1:source.dim(3); + + %establish a homogeneous transformation matrix from voxels to headspace based on the sparse positions + sparsepos = source.pos; + ok = 0; + cnt = 0; + while ok==0, + cnt = cnt+1; + dpos = sparsepos - sparsepos(cnt*ones(size(sparsepos,1),1),:); + [srt, indx] = sort(sum(dpos.^2,2)); + srt = dpos(indx,:); + tmpsrt = abs(srt(2:7,:)); + csrt = tmpsrt*tmpsrt'; + sel = find(sum(csrt==0)>=2); + if numel(sel)>=3, + ok = 1; + end + end + tmppos = sparsepos(indx([1 sel(:)'+1]),:); + tmpdpos = dpos(indx([1 sel(:)'+1]),:); + + %FIXME the following is a bit experimental and not fully tested yet it works in general case + %rotation + M = pinv(tmpdpos(2:4,:)); + + %get rotation such that maxima are on diagonal and positive + m(1) = find(M(1,:)==max(abs(M(1,:)))); + m(2) = find(M(2,:)==max(abs(M(2,:)))); + m(3) = find(M(3,:)==max(abs(M(3,:)))); + [srt, indx] = sort(m); + M = M(indx,:); + M = M*diag(sign(diag(M))); + sparsepos = sparsepos*M; + + %translation + T = -min(sparsepos,[],1)+1; + sparsepos = sparsepos + T(ones(size(sparsepos,1),1), :); + + % recreate the positions of the dipole grid + [X, Y, Z] = ndgrid(xgrid, ygrid, zgrid); + pos = [X(:) Y(:) Z(:)]; + pos = warp_apply(inv([M T(:);0 0 0 1]), pos); +end + +Nsparse = length(source.inside); +siz = source.dim; +Nfull = prod(siz); + +% determine the size that each slice takes in memory +sx = 1; +sy = siz(1); +sz = siz(1) * siz(2); + +if isfield(source, 'inside') && isfield(source, 'outside') && size(source.pos,1)==Nfull + % it contains all source positions + inside = source.inside; + outside = source.outside; +else + % it only contains the inside source positions, which are all inside the brain + % reconstruct the original inside and outside grid locations + inside = zeros(Nsparse,1); + for i=1:Nsparse + fx = find(xgrid==sparsepos(i,1)); + fy = find(ygrid==sparsepos(i,2)); + fz = find(zgrid==sparsepos(i,3)); + inside(i) = (fx-1)*sx + (fy-1)*sy + (fz-1)*sz + 1; + end + outside = setdiff([1:Nfull]', inside); +end + +fprintf('total number of dipoles : %d\n', length(inside)+length(outside)); +fprintf('number of dipoles inside brain: %d\n', length(inside)); +fprintf('number of dipoles outside brain: %d\n', length(outside)); + +% determine whether the source is old or new style +fnames = fieldnames(source); +if any(~cellfun('isempty', strfind(fnames, 'dimord'))), + stype = 'new'; +else + stype = 'old'; +end + +if strcmp(stype, 'old'), + % original code + % first do the non-trial fields + source.dim = [1 length(inside) 1]; %to fool parameterselection + [param] = parameterselection('all', source); + trlparam = strmatch('trial', param); + sel = setdiff(1:length(param), trlparam); + param = param(sel); + + for j = 1:length(param) + dat = getsubfield(source, param{j}); + if islogical(dat), + tmp = false(1,Nfull); + tmp(inside) = dat; + elseif iscell(dat), + tmp = cell(1,Nfull); + tmp(inside) = dat; + %tmp(outside) = nan; + else + tmp = zeros(1,Nfull) + nan; + tmp(inside) = dat; + end + source = setsubfield(source, param{j}, tmp); + end + + % then do the trial fields + if isfield(source, 'trial' ), + for j = 1:length(source.trial) + tmpsource = source.trial(j); + tmpsource.dim = source.dim; % to fool parameterselection + tmpparam = parameterselection('all', tmpsource); + for k = 1:length(tmpparam) + dat = getsubfield(tmpsource, tmpparam{k}); + if strcmp(class(dat), 'logical'), + tmp = logical(zeros(1,Nfull)); + tmp(inside) = dat; + elseif strcmp(class(dat), 'cell'), + tmp = cell(1,Nfull); + tmp(inside) = dat; + %tmp(outside) = nan; + else + tmp = zeros(1,Nfull) + nan; + tmp(inside) = dat; + end + tmpsource = setsubfield(tmpsource, tmpparam{k}, tmp); + end + tmpsource = rmfield(tmpsource, 'dim'); + source.trial(j) = tmpsource; + end + elseif isfield(source, 'trialA'), + for j = 1:length(source.trialA) + tmpsource = source.trialA(j); + tmpsource.dim = source.dim; % to fool parameterselection + tmpparam = parameterselection('all', tmpsource); + for k = 1:length(tmpparam) + dat = getsubfield(tmpsource, tmpparam{k}); + if strcmp(class(dat), 'logical'), + tmp = logical(zeros(1,Nfull)); + tmp(inside) = dat; + elseif strcmp(class(dat), 'cell'), + tmp = cell(1,Nfull); + tmp(inside) = dat; + %tmp(outside) = nan; + else + tmp = zeros(1,Nfull) + nan; + tmp(inside) = dat; + end + tmpsource = setsubfield(tmpsource, tmpparam{k}, tmp); + end + tmpsource = rmfield(tmpsource, 'dim'); + source.trialA(j) = tmpsource; + end + elseif isfield(source, 'trialB'), + for j = 1:length(source.trialB) + tmpsource = source.trialB(j); + tmpsource.dim = source.dim; % to fool parameterselection + tmpparam = parameterselection('all', tmpsource); + for k = 1:length(tmpparam) + dat = getsubfield(tmpsource, tmpparam{k}); + if strcmp(class(dat), 'logical'), + tmp = logical(zeros(1,Nfull)); + tmp(inside) = dat; + elseif strcmp(class(dat), 'cell'), + tmp = cell(1,Nfull); + tmp(inside) = dat; + %tmp(outside) = nan; + else + tmp = zeros(1,Nfull) + nan; + tmp(inside) = dat; + end + tmpsource = setsubfield(tmpsource, tmpparam{k}, tmp); + end + tmpsource = rmfield(tmpsource, 'dim'); + source.trialB(j) = tmpsource; + end + end + + % and finally do the coherence-like matrices (size Nvox X Nvox) + fn = fieldnames(source); + for i=1:length(fn) + d = getfield(source, fn{i}); + m = size(d, 1); + n = size(d, 2); + if m==Nsparse && n==Nsparse + tmp = nan*zeros(Nfull,Nfull); + tmp(inside,inside) = d; + source = setfield(source, fn{i}, tmp); + end + end + + % update the inside and outside definitions + source.inside = inside; + source.outside = outside; + source.pos = pos; + source.dim = siz; +elseif strcmp(stype, 'new') + % new style conversion + fn = fieldnames(source); + for i=1:numel(fn) + if any(size(source.(fn{i}))==Nsparse), + if iscell(source.(fn{i})), + indx = find(size(source.(fn{i}))==Nsparse); + if all(indx==1), + tmp = cell(Nfull,1); + tmp(inside,1) = source.(fn{i}); + source.(fn{i}) = tmp; + elseif all(indx==2), + tmp = cell(1,Nfull); + tmp(1,inside) = source.(fn{i}); + source.(fn{i}) = tmp; + else + warning(sprintf('sparse to full conversion failed for field %s\n', fn{i})); + end + else + indx = find(size(source.(fn{i}))==Nsparse); + if all(indx==1), + tmpsiz = [size(source.(fn{i})) 1]; + tmp = zeros([Nfull tmpsiz(2:end)]) + nan; + tmp(inside,:,:,:,:) = source.(fn{i}); + elseif all(indx==2), + tmpsiz = [size(source.(fn{i})) 1]; + tmp = zeros([tmpsiz(1) Nfull tmpsiz(3:end)]) + nan; + tmp(:,inside,:,:,:) = source.(fn{i}); + elseif all(indx==[1 2]), + % bivariate matrix + tmpsiz = [size(source.(fn{i})) 1]; + tmp = zeros([Nfull Nfull tmpsiz(3:end)]) + nan; + tmp(inside,inside,:,:,:) = source.(fn{i}); + else + warning(sprintf('sparse to full conversion failed for field %s\n', fn{i})); + end + end + % nothing to do + end + end + + % update the inside and outside definitions and pos + source.inside = inside; + source.outside = outside; + source.pos = pos; + +end +cfg = []; +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: source2full.m 1402 2010-07-12 19:41:58Z roboos $'; +% remember the configuration details of the input data +try, cfg.previous = source.cfg; end +% remember the exact configuration details in the output +source.cfg = cfg; diff --git a/external/fieldtrip/public/source2grid.m b/external/fieldtrip/public/source2grid.m new file mode 100644 index 0000000..c561a80 --- /dev/null +++ b/external/fieldtrip/public/source2grid.m @@ -0,0 +1,57 @@ +function [grid] = source2grid(source) + +% SOURCE2GRID removes the fields from a source structure that are +% not neccessary to reuse the dipole grid in another source estimation. +% +% Use as +% [grid] = source2grid(source); +% +% The resulting grid can be used in the configuration of another +% run of SOURCANALYSIS. +% +% See also SOURCE2SPARSE, SOURCE2FULL + +% Copyright (C) 2004, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: source2grid.m 1402 2010-07-12 19:41:58Z roboos $ + +fieldtripdefs + +% these are always supposed to be present +grid.pos = source.pos; +grid.inside = source.inside; +grid.outside = source.outside; + +% these are optional +try, grid.xgrid = source.xgrid; end +try, grid.ygrid = source.ygrid; end +try, grid.zgrid = source.zgrid; end +try, grid.dim = source.dim; end + +if issubfield(source, 'filter') + grid.filter = source.filter; +elseif issubfield(source, 'avg.filter') + grid.filter = source.avg.filter; +elseif issubfield(source, 'trial.filter') + error('single trial filters are not supported here'); +end + +if isfield(source, 'leadfield') + grid.leadfield = source.leadfield; +end diff --git a/external/fieldtrip/public/source2sparse.m b/external/fieldtrip/public/source2sparse.m new file mode 100644 index 0000000..63d1f9b --- /dev/null +++ b/external/fieldtrip/public/source2sparse.m @@ -0,0 +1,165 @@ +function [source] = source2sparse(source); + +% SOURCE2SPARSE removes the grid locations outside the brain from the source +% reconstruction, thereby saving memory. +% +% This invalidates the fields that describe the grid, and also makes it +% more difficult to make a plot of each of the slices of the source volume. +% The original source structure can be recreated using SOURCE2FULL. +% +% Use as +% [source] = source2sparse(source) +% +% See also SOURCE2FULL + +% Copyright (C) 2004, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: source2sparse.m 1402 2010-07-12 19:41:58Z roboos $ + +fieldtripdefs + +if ~isfield(source, 'inside') + warning('no gridpoints defined inside the brain'); + source.inside = []; +end + +if ~isfield(source, 'outside') + warning('no gridpoints defined outside the brain'); + source.outside = []; +end + +inside = source.inside; +outside = source.outside; + +fprintf('total number of dipoles : %d\n', length(inside)+length(outside)); +fprintf('number of dipoles inside brain: %d\n', length(inside)); +fprintf('number of dipoles outside brain: %d\n', length(outside)); + +% determine whether the source is old or new style +fnames = fieldnames(source); +if any(~cellfun('isempty', strfind(fnames, 'dimord'))), + stype = 'new'; +else + stype = 'old'; +end + +if strcmp(stype, 'old'), + % original code + % first do the non-trial fields + [param] = parameterselection('all', source); + trlparam = strmatch('trial', param); + sel = setdiff(1:length(param), trlparam); + param = param(sel); + + for j = 1:length(param) + dat = getsubfield(source, param{j}); + source = setsubfield(source, param{j}, dat(inside)); + end + + % then do the trial fields + if isfield(source, 'trial'), + for j = 1:length(source.trial) + tmpsource = source.trial(j); + tmpsource.dim = source.dim; % to fool parameterselection + tmpparam = parameterselection('all', tmpsource); + for k = 1:length(tmpparam) + dat = getsubfield(tmpsource, tmpparam{k}); + tmpsource = setsubfield(tmpsource, tmpparam{k}, dat(inside)); + end + tmpsource = rmfield(tmpsource, 'dim'); + source.trial(j) = tmpsource; + end + elseif isfield(source, 'trialA'), + for j = 1:length(source.trialA) + tmpsource = source.trialA(j); + tmpsource.dim = source.dim; % to fool parameterselection + tmpparam = parameterselection('all', tmpsource); + for k = 1:length(tmpparam) + dat = getsubfield(tmpsource, tmpparam{k}); + tmpsource = setsubfield(tmpsource, tmpparam{k}, dat(inside)); + end + tmpsource = rmfield(tmpsource, 'dim'); + source.trialA(j) = tmpsource; + end + elseif isfield(source, 'trialB'), + for j = 1:length(source.trialB) + tmpsource = source.trialB(j); + tmpsource.dim = source.dim; % to fool parameterselection + tmpparam = parameterselection('all', tmpsource); + for k = 1:length(tmpparam) + dat = getsubfield(tmpsource, tmpparam{k}); + tmpsource = setsubfield(tmpsource, tmpparam{k}, dat(inside)); + end + tmpsource = rmfield(tmpsource, 'dim'); + source.trialB(j) = tmpsource; + end + end + + % update the inside, outside and source position + if isfield(source, 'inside') + source.inside = [1:length(inside)]'; + end + if isfield(source, 'outside') + source.outside = []; + end + if isfield(source, 'pos') + source.pos = source.pos(inside,:); + end +elseif strcmp(stype, 'new') + % new style conversion + nvox = numel(inside) + numel(outside); + for k = 1:numel(fnames) + tmpsiz = size(source.(fnames{k})); + if any(tmpsiz==nvox) + tmpsel = find(tmpsiz==nvox); + if tmpsel==1, + source.(fnames{k}) = source.(fnames{k})(inside,:,:,:,:); + elseif tmpsel==2, + source.(fnames{k}) = source.(fnames{k})(:,inside,:,:,:); + else + warning('not subselecting voxels, because location of pos-dimension is unexpected'); + end + end + end + + % update the inside and outside + if isfield(source, 'inside') + source.inside = [1:length(inside)]'; + end + if isfield(source, 'outside') + source.outside = []; + end +end + +cfg = []; +% add version information to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: source2sparse.m 1402 2010-07-12 19:41:58Z roboos $'; +% remember the configuration details of the input data +try, cfg.previous = source.cfg; end +% remember the exact configuration details in the output +source.cfg = cfg; + diff --git a/external/fieldtrip/public/sourcerestyle.m b/external/fieldtrip/public/sourcerestyle.m new file mode 100644 index 0000000..ac135e4 --- /dev/null +++ b/external/fieldtrip/public/sourcerestyle.m @@ -0,0 +1,226 @@ +function [output] = sourcerestyle(input, type) + +% SOURCERESTYLE converts old style source structures into new style source structures and the +% other way around +% +% Use as: +% sourcerestyle(input, type) +% where input is a source structure, +% +% Typically, old style source structures contain +% avg.XXX or trial.XXX fields +% +% The ne wstyle source structure contains: +% source.pos +% source.dim (optional, if the list of positions describes a 3D volume +% source.XXX the old style subfields in avg/trial +% source.XXXdimord string how to interpret the respective XXX field: +% e.g. source.leadfield = cell(1,Npos), source.leadfielddimord = '{pos}_chan_ori' +% source.mom = cell(1,Npos), source.momdimord = '{pos}_ori_rpttap' + +if nargin==1, + type = 'old'; +end + +fnames = fieldnames(input); +tmp = cell2mat(strfind(fnames, 'dimord')); %get dimord like fields +if any(tmp>1), + current = 'new'; +elseif any(tmp==1), + %don't know what to do yet data is JM's own invention +else + current = 'old'; +end + +if strcmp(current, type), + %do nothing + return +elseif strcmp(current, 'old') && strcmp(type, 'new'), + %go from old to new + + if isfield(input, 'avg'), + stuff = getfield(input, 'avg'); + output = rmfield(input, 'avg'); + elseif isfield(input, 'trial'), + stuff = getfield(input, 'trial'); + output = rmfield(input, 'trial'); + else + %this could occur later in the pipeline, e.g. when doing group statistics using individual subject + %descriptive statistics + error('the input does not contain an avg or trial field'); + end + + %remove and rename the specified fields if present + removefields = {'xgrid';'ygrid';'zgrid';'method'}; + renamefields = {'frequency' 'freq'; 'csdlabel' 'orilabel'}; + fnames = fieldnames(output); + for k = 1:numel(fnames) + ix = strmatch(fnames{k}, removefields); + if ~isempty(ix), + output = rmfield(output, fnames{k}); + end + ix = strmatch(fnames{k}, renamefields(:,1)); + if ~isempty(ix), + output = setfield(output, renamefields{ix,2}, ... + getfield(output, renamefields{ix,1})); + output = rmfield(output, fnames{k}); + end + end + + %put the stuff originally in avg or trial one level up in the structure + fnames = fieldnames(stuff(1)); + npos = size(input.pos,1); + nrpt = numel(stuff); + for k = 1:numel(fnames) + if nrpt>1, + %multiple trials + %(or subjects FIXME not yet implemented, nor tested) + tmp = getfield(stuff(1), fnames{k}); + siz = size(tmp); + if isfield(input, 'cumtapcnt') && strcmp(fnames{k}, 'mom'), + %pcc based mom is special case: rpttap rather than rpt + %and single voxel mom = ori x rpttap + nrpttap = sum(input.cumtapcnt); + sizvox = [size(tmp{input.inside(1)}) 1]; + sizvox = [sizvox(1) nrpttap sizvox(3:end)]; + rptstring = 'rpttap'; + elseif iscell(tmp) + nrpttap = numel(stuff); + sizvox = [size(tmp{input.inside(1)}) 1]; + sozvpx = [sizvox(1) nrpttap sizvox(3:end)]; + rptstring = 'rpt'; + end + + if siz(1) ~= npos && siz(2) ==npos, + tmp = transpose(tmp); + end + + if iscell(tmp) + %allocate memory for cell-array + tmpall = cell(npos,1); + for n = 1:numel(input.inside) + tmpall{input.inside(n)} = zeros(sizvox); + end + else + %allocate memory for matrix + tmpall = zeros([npos nrpt siz(2:end)]); + end + + cnt = 0; + for m = 1:nrpt + tmp = getfield(stuff(m), fnames{k}); + siz = size(tmp); + if siz(1) ~= npos && siz(2) ==npos, + tmp = transpose(tmp); + end + + if ~iscell(tmp), + tmpall(:,m,:,:,:) = tmp; + else + for n = 1:numel(input.inside) + indx = input.inside(n); + tmpdat = tmp{indx}; + if isfield(input, 'cumtapcnt') && strcmp(fnames{k}, 'mom'), + if n==1, siz1 = size(tmpdat,2); end + else + if n==1, siz1 = 1; end + end + tmpall{indx}(:,cnt+[1:siz1],:,:,:) = tmpdat; + if n==numel(input.inside), cnt = cnt + siz1; end + end + end + end + output = setfield(output, fnames{k}, tmpall); + newdimord = createdimord(output, fnames{k}, 1); + if ~isempty(newdimord) + output = setfield(output, [fnames{k},'dimord'], newdimord); + end + + else + tmp = getfield(stuff, fnames{k}); + siz = size(tmp); + if siz(1) ~= npos && siz(2) ==npos, + tmp = transpose(tmp); + end + output = setfield(output, fnames{k}, tmp); + newdimord = createdimord(output, fnames{k}); + if ~isempty(newdimord) + output = setfield(output, [fnames{k},'dimord'], newdimord); + end + end + end + + if isfield(output, 'csdlabel') + output = setfield(output, 'orilabel', getfield(output, 'csdlabel')); + output = rmfield(output, 'csdlabel'); + end + +elseif strcmp(current, 'new') && strcmp(type, 'old') + %go from new to old + error('not implemented yet'); +end + + +%----------------------------------------------- +function [dimord] = createdimord(output, fname, rptflag); + +if nargin==2, rptflag = 1; end + +tmp = getfield(output, fname); + +dimord = ''; +dimnum = 1; + +if iscell(tmp) && size(output.pos,1)==size(tmp,dimnum) + dimord = [dimord,'{pos}']; + dimnum = dimnum + 1; +elseif ~iscell(tmp) && size(output.pos,1)==size(tmp,dimnum) + dimord = [dimord,'pos']; + dimnum = dimnum + 1; +end + +switch fname + case 'csd' + dimord = [dimord,'_ori_ori']; + case 'csdlabel' + dimord = dimord; + case 'filter' + dimord = [dimord,'_ori_chan']; + case 'leadfield' + dimord = [dimord,'_chan_ori']; + case 'mom' + if isfield(output, 'cumtapcnt') && sum(output.cumtapcnt)==size(tmp{output.inside(1)},2) + dimord = [dimord,'_ori_rpttap']; + elseif isfield(output, 'time') && numel(output.time)==size(tmp{output.inside(1)},2) + dimord = [dimord,'_ori_time']; + end + + if isfield(output, 'freq') + dimord = [dimord,'_freq']; + end + case 'nai' + if isfield(output, 'freq') && numel(output.freq)==size(tmp,dimnum) + dimord = [dimord,'_freq']; + end + case 'noise' + if isfield(output, 'freq') && numel(output.freq)==size(tmp,dimnum) + dimord = [dimord,'_freq']; + end + case 'noisecsd' + dimord = [dimord,'_ori_ori']; + case 'ori' + %this field is equivalent to a pos-field + %FIXME should this be matricized (size is not that big) + dimord = ''; + case 'pow' + if isfield(output, 'cumtapcnt') && numel(output.cumtapcnt)==size(tmp,dimnum) + dimord = [dimord,'_rpt']; + dimnum = dimnum + 1; + end + + if isfield(output, 'freq') && numel(output.freq)==size(tmp,dimnum) + dimord = [dimord,'_freq']; + end + otherwise + error(sprintf('unknown fieldname %s', fname)); +end diff --git a/external/fieldtrip/public/struct2double.m b/external/fieldtrip/public/struct2double.m new file mode 100644 index 0000000..eb740a9 --- /dev/null +++ b/external/fieldtrip/public/struct2double.m @@ -0,0 +1,88 @@ +function [x] = struct2double(x, maxdepth); + +% STRUCT2DOUBLE converts all single precision numeric data in a structure +% into double precision. It will also convert plain matrices and +% cell-arrays. +% +% Use as +% x = struct2double(x); +% +% Starting from Matlab 7.0, you can use single precision data in your +% computations, i.e. you do not have to convert back to double precision. +% +% Matlab version 6.5 and older only support single precision for storing +% data in memory or on disk, but do not allow computations on single +% precision data. Therefore you should converted your data from single to +% double precision after reading from file. +% +% See also STRUCT2SINGLE + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id$ + +if nargin<2 + maxdepth = inf; +end + +% convert the data, work recursively through the complete structure +x = convert(x, 0, maxdepth); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% this subfunction does the actual work +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [a] = convert(a, depth, maxdepth); + +if depth>maxdepth + error('recursive depth exceeded'); +end + +switch class(a) + case 'struct' + % process all fields of the structure recursively + fna = fieldnames(a); + % process all elements of the array + for j=1:length(a(:)) + % warning, this is a recursive call to traverse nested structures + for i=1:length(fna) + fn = fna{i}; + ra = getfield(a(j), fn); + ra = convert(ra, depth+1, maxdepth); + a(j) = setfield(a(j), fn, ra); + end + end + + case 'cell' + % process all elements of the cell-array recursively + % warning, this is a recursive call to traverse nested structures + for i=1:length(a(:)) + a{i} = convert(a{i}, depth+1, maxdepth); + end + + case {'single' 'int32' 'uint32' 'int16' 'uint16'} + % convert the values to double precision + a = double(a); + + case 'double' + % keep as it is + + otherwise + warning('not converting class %s', class(a)) + % do nothing +end diff --git a/external/fieldtrip/public/struct2single.m b/external/fieldtrip/public/struct2single.m new file mode 100644 index 0000000..ff74317 --- /dev/null +++ b/external/fieldtrip/public/struct2single.m @@ -0,0 +1,85 @@ +function [x] = struct2single(x, maxdepth); + +% STRUCT2SINGLE converts all double precision numeric data in a structure +% into single precision, which takes up half the amount of memory compared +% to double precision. It will also convert plain matrices and cell-arrays. +% +% Use as +% x = struct2single(x); +% +% Starting from Matlab 7.0, you can use single precision data in your +% computations, i.e. you do not have to convert back to double precision. +% +% Matlab version 6.5 and older only support single precision for storing +% data in memory or on disk, but do not allow computations on single +% precision data. After reading a single precision structure from file, you +% can convert it back with STRUCT2DOUBLE. +% +% See also STRUCT2DOUBLE + +% Copyright (C) 2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id$ + +if nargin<2 + maxdepth = inf; +end + +% convert the data, work recursively through the complete structure +x = convert(x, 0, maxdepth); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% this subfunction does the actual work +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [a] = convert(a, depth, maxdepth); + +if depth>maxdepth + error('recursive depth exceeded'); +end + +switch class(a) + case 'struct' + % process all fields of the structure recursively + fna = fieldnames(a); + % process all elements of the array + for j=1:length(a(:)) + % warning, this is a recursive call to traverse nested structures + for i=1:length(fna) + fn = fna{i}; + ra = getfield(a(j), fn); + ra = convert(ra, depth+1, maxdepth); + a(j) = setfield(a(j), fn, ra); + end + end + + case 'cell' + % process all elements of the cell-array recursively + % warning, this is a recursive call to traverse nested structures + for i=1:length(a(:)) + a{i} = convert(a{i}, depth+1, maxdepth); + end + + case {'double' 'int32' 'uint32' 'int16' 'uint16'} + % convert the values to single precision + a = single(a); + + otherwise + warning('not converting class %s', class(a)) + % do nothing +end diff --git a/external/fieldtrip/public/tokenize.m b/external/fieldtrip/public/tokenize.m new file mode 100644 index 0000000..43b900e --- /dev/null +++ b/external/fieldtrip/public/tokenize.m @@ -0,0 +1,76 @@ +function [tok] = tokenize(str, sep, rep) + +% TOKENIZE cuts a string into pieces, returning the pieces in a cell array +% +% Use as +% t = tokenize(str) +% t = tokenize(str, sep) +% t = tokenize(str, sep, rep) +% where +% str = the string that you want to cut into pieces +% sep = the separator at which to cut (default is whitespace) +% rep = whether to treat repeating seperator characters as one (default is false) +% +% With the optional boolean flag "rep" you can specify whether repeated +% seperator characters should be squeezed together (e.g. multiple +% spaces between two words). The default is rep=1, i.e. repeated +% seperators are treated as one. +% +% See also STRTOK, TEXTSCAN + +% Copyright (C) 2003-2010, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: tokenize.m 1388 2010-07-10 09:12:47Z roboos $ + +% these are for remembering the type on subsequent calls with the same input arguments +persistent previous_argin previous_argout + +if nargin<2 + sep = [9:13 32]; % White space characters +end + +if nargin<3 + rep = false; +end + +current_argin = {str, sep, rep}; +if isequal(current_argin, previous_argin) + % don't do the processing again, but return the previous values from cache + tok = previous_argout; + return +end + +tok = {}; +f = find(ismember(str, sep)); +f = [0, f, length(str)+1]; +for i=1:(length(f)-1) + tok{i} = str((f(i)+1):(f(i+1)-1)); +end + +if rep + % remove empty cells, which occur if the separator is repeated (e.g. multiple spaces) + tok(cellfun('isempty', tok))=[]; +end + +% remember the current input and output arguments, so that they can be +% reused on a subsequent call in case the same input argument is given +current_argout = tok; +previous_argin = current_argin; +previous_argout = current_argout; + diff --git a/external/fieldtrip/private/uimage.m b/external/fieldtrip/public/uimage.m similarity index 89% rename from external/fieldtrip/private/uimage.m rename to external/fieldtrip/public/uimage.m index 85ddf41..8077133 100644 --- a/external/fieldtrip/private/uimage.m +++ b/external/fieldtrip/public/uimage.m @@ -37,20 +37,14 @@ % Revision: 1.03, Date: 2006/06/14. % % See also IMAGE, IMAGESC, UIMAGESC. +% % This function is downloaded on Oct 24th 2008 from www.mathworks.com/matlabcentral/fileexchange/11368 % History: -% 2006/06/12: v1.00, first version. -% 2006/06/14: v1.03, minor bug fixed; works in ML6. -% -%$Log: uimage.m,v $ -%Revision 1.1 2008/11/13 09:55:36 roboos -%moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -%Revision 1.1 2008/10/27 09:26:53 ingnie -%file from matlabcentral. addon to matlab IMAGE function, also works with unevenly spaced -%axis (fi log). If axis are evenly spaced it just calles IMAGE +% 2006/06/12: v1.00, first version. +% 2006/06/14: v1.03, minor bug fixed; works in ML6. % +% $Id: uimage.m 951 2010-04-21 18:24:01Z roboos $ error(nargchk(3,inf,nargin)); diff --git a/external/fieldtrip/private/uimagesc.m b/external/fieldtrip/public/uimagesc.m similarity index 81% rename from external/fieldtrip/private/uimagesc.m rename to external/fieldtrip/public/uimagesc.m index 7fb25a3..74dcca8 100644 --- a/external/fieldtrip/private/uimagesc.m +++ b/external/fieldtrip/public/uimagesc.m @@ -10,19 +10,13 @@ % Revision: 1.01, Date: 2006/06/13. % % See also IMAGE, IMAGESC, UIMAGE. +% % This function is downloaded on Oct 24th 2008 from www.mathworks.com/matlabcentral/fileexchange/11368 % History: -% 2006/06/12: v1.00, first version. -% -%$Log: uimagesc.m,v $ -%Revision 1.1 2008/11/13 09:55:36 roboos -%moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -%Revision 1.1 2008/10/27 09:29:45 ingnie -%file from matlabcentral. addon to matlab IMAGESC function, also works with unevenly spaced -%axis (fi log). +% 2006/06/12: v1.00, first version. % +% $Id: uimagesc.m 951 2010-04-21 18:24:01Z roboos $ clim = []; switch (nargin), diff --git a/external/fieldtrip/public/warp_apply.m b/external/fieldtrip/public/warp_apply.m new file mode 100644 index 0000000..290a991 --- /dev/null +++ b/external/fieldtrip/public/warp_apply.m @@ -0,0 +1,166 @@ +function [warped] = warp_apply(M, input, method); + +% WARP_APPLY performs a 3D linear or nonlinear transformation on the input +% coordinates, similar to those in AIR 3.08. You can find technical +% documentation on warping in general at http://bishopw.loni.ucla.edu/AIR3 +% +% Use as +% [warped] = warp_apply(M, input, method) +% where +% M vector or matrix with warping parameters +% input Nx3 matrix with coordinates +% warped Nx3 matrix with coordinates +% method string describing the warping method +% +% The methods 'nonlin0', 'nonlin2' ... 'nonlin5' specify a +% polynomial transformation. The size of the transformation matrix +% depends on the order of the warp +% zeroth order : 1 parameter per coordinate (translation) +% first order : 4 parameters per coordinate (total 12, affine) +% second order : 10 parameters per coordinate +% third order : 20 parameters per coordinate +% fourth order : 35 parameters per coordinate +% fifth order : 56 parameters per coordinate (total 168) +% The size of M should be 3xP, where P is the number of parameters +% per coordinate. Alternatively, you can specify the method to be +% 'nonlinear', where the order will be determined from teh size of +% the matrix M. +% +% If the method 'homogeneous' is selected, the input matrix M should be +% a 4x4 homogenous transformation matrix. +% +% If any other method is selected, it is assumed that it specifies +% the name of an auxiliary function that will, when given the input +% parameter vector M, return an 4x4 homogenous transformation +% matrix. Supplied functions in teh warping toolbox are translate, +% rotate, scale, rigidbody, globalrescale, traditional, affine, +% perspective. + +% Copyright (C) 2000-2005, Robert Oostenveld +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: warp_apply.m 945 2010-04-21 17:41:20Z roboos $ + +if nargin<3 && all(size(M)==4) + % no specific transformation mode has been selected + % it looks like a homogenous transformation matrix + method = 'homogenous'; +elseif nargin<3 + % the default method is 'nonlinear' + method = 'nonlinear'; +end + +if size(input,2)==2 + % convert the input points from 2D to 3D representation + input(:,3) = 0; + input3d = false; +else + input3d = true; +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% nonlinear warping +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +if any(strcmp(method, {'nonlinear', 'nonlin0', 'nonlin1', 'nonlin2', 'nonlin3', 'nonlin4', 'nonlin5'})) + x = input(:,1); + y = input(:,2); + z = input(:,3); + s = size(M); + + if s(1)~=3 + error('invalid size of nonlinear transformation matrix'); + elseif strcmp(method, 'nonlin0') & s(2)~=1 + error('invalid size of nonlinear transformation matrix'); + elseif strcmp(method, 'nonlin1') & s(2)~=4 + error('invalid size of nonlinear transformation matrix'); + elseif strcmp(method, 'nonlin2') & s(2)~=10 + error('invalid size of nonlinear transformation matrix'); + elseif strcmp(method, 'nonlin3') & s(2)~=20 + error('invalid size of nonlinear transformation matrix'); + elseif strcmp(method, 'nonlin4') & s(2)~=35 + error('invalid size of nonlinear transformation matrix'); + elseif strcmp(method, 'nonlin5') & s(2)~=56 + error('invalid size of nonlinear transformation matrix'); + end + + if s(2)==1 + % this is a translation, which in a strict sense is not the 0th order nonlinear transformation + xx = M(1,1) + x; + yy = M(2,1) + y; + zz = M(3,1) + z; + elseif s(2)==4 + xx = M(1,1) + M(1,2)*x + M(1,3)*y + M(1,4)*z; + yy = M(2,1) + M(2,2)*x + M(2,3)*y + M(2,4)*z; + zz = M(3,1) + M(3,2)*x + M(3,3)*y + M(3,4)*z; + elseif s(2)==10 + xx = M(1,1) + M(1,2)*x + M(1,3)*y + M(1,4)*z + M(1,5)*x.*x + M(1,6)*x.*y + M(1,7)*x.*z + M(1,8)*y.*y + M(1,9)*y.*z + M(1,10)*z.*z; + yy = M(2,1) + M(2,2)*x + M(2,3)*y + M(2,4)*z + M(2,5)*x.*x + M(2,6)*x.*y + M(2,7)*x.*z + M(2,8)*y.*y + M(2,9)*y.*z + M(2,10)*z.*z; + zz = M(3,1) + M(3,2)*x + M(3,3)*y + M(3,4)*z + M(3,5)*x.*x + M(3,6)*x.*y + M(3,7)*x.*z + M(3,8)*y.*y + M(3,9)*y.*z + M(3,10)*z.*z; + elseif s(2)==20 + xx = M(1,1) + M(1,2)*x + M(1,3)*y + M(1,4)*z + M(1,5)*x.*x + M(1,6)*x.*y + M(1,7)*x.*z + M(1,8)*y.*y + M(1,9)*y.*z + M(1,10)*z.*z + M(1,11)*x.*x.*x + M(1,12)*x.*x.*y + M(1,13)*x.*x.*z + M(1,14)*x.*y.*y + M(1,15)*x.*y.*z + M(1,16)*x.*z.*z + M(1,17)*y.*y.*y + M(1,18)*y.*y.*z + M(1,19)*y.*z.*z + M(1,20)*z.*z.*z; + yy = M(2,1) + M(2,2)*x + M(2,3)*y + M(2,4)*z + M(2,5)*x.*x + M(2,6)*x.*y + M(2,7)*x.*z + M(2,8)*y.*y + M(2,9)*y.*z + M(2,10)*z.*z + M(2,11)*x.*x.*x + M(2,12)*x.*x.*y + M(2,13)*x.*x.*z + M(2,14)*x.*y.*y + M(2,15)*x.*y.*z + M(2,16)*x.*z.*z + M(2,17)*y.*y.*y + M(2,18)*y.*y.*z + M(2,19)*y.*z.*z + M(2,20)*z.*z.*z; + zz = M(3,1) + M(3,2)*x + M(3,3)*y + M(3,4)*z + M(3,5)*x.*x + M(3,6)*x.*y + M(3,7)*x.*z + M(3,8)*y.*y + M(3,9)*y.*z + M(3,10)*z.*z + M(3,11)*x.*x.*x + M(3,12)*x.*x.*y + M(3,13)*x.*x.*z + M(3,14)*x.*y.*y + M(3,15)*x.*y.*z + M(3,16)*x.*z.*z + M(3,17)*y.*y.*y + M(3,18)*y.*y.*z + M(3,19)*y.*z.*z + M(3,20)*z.*z.*z; + elseif s(2)==35 + xx = M(1,1) + M(1,2)*x + M(1,3)*y + M(1,4)*z + M(1,5)*x.*x + M(1,6)*x.*y + M(1,7)*x.*z + M(1,8)*y.*y + M(1,9)*y.*z + M(1,10)*z.*z + M(1,11)*x.*x.*x + M(1,12)*x.*x.*y + M(1,13)*x.*x.*z + M(1,14)*x.*y.*y + M(1,15)*x.*y.*z + M(1,16)*x.*z.*z + M(1,17)*y.*y.*y + M(1,18)*y.*y.*z + M(1,19)*y.*z.*z + M(1,20)*z.*z.*z + M(1,21)*x.*x.*x.*x + M(1,22)*x.*x.*x.*y + M(1,23)*x.*x.*x.*z + M(1,24)*x.*x.*y.*y + M(1,25)*x.*x.*y.*z + M(1,26)*x.*x.*z.*z + M(1,27)*x.*y.*y.*y + M(1,28)*x.*y.*y.*z + M(1,29)*x.*y.*z.*z + M(1,30)*x.*z.*z.*z + M(1,31)*y.*y.*y.*y + M(1,32)*y.*y.*y.*z + M(1,33)*y.*y.*z.*z + M(1,34)*y.*z.*z.*z + M(1,35)*z.*z.*z.*z; + yy = M(2,1) + M(2,2)*x + M(2,3)*y + M(2,4)*z + M(2,5)*x.*x + M(2,6)*x.*y + M(2,7)*x.*z + M(2,8)*y.*y + M(2,9)*y.*z + M(2,10)*z.*z + M(2,11)*x.*x.*x + M(2,12)*x.*x.*y + M(2,13)*x.*x.*z + M(2,14)*x.*y.*y + M(2,15)*x.*y.*z + M(2,16)*x.*z.*z + M(2,17)*y.*y.*y + M(2,18)*y.*y.*z + M(2,19)*y.*z.*z + M(2,20)*z.*z.*z + M(2,21)*x.*x.*x.*x + M(2,22)*x.*x.*x.*y + M(2,23)*x.*x.*x.*z + M(2,24)*x.*x.*y.*y + M(2,25)*x.*x.*y.*z + M(2,26)*x.*x.*z.*z + M(2,27)*x.*y.*y.*y + M(2,28)*x.*y.*y.*z + M(2,29)*x.*y.*z.*z + M(2,30)*x.*z.*z.*z + M(2,31)*y.*y.*y.*y + M(2,32)*y.*y.*y.*z + M(2,33)*y.*y.*z.*z + M(2,34)*y.*z.*z.*z + M(2,35)*z.*z.*z.*z; + zz = M(3,1) + M(3,2)*x + M(3,3)*y + M(3,4)*z + M(3,5)*x.*x + M(3,6)*x.*y + M(3,7)*x.*z + M(3,8)*y.*y + M(3,9)*y.*z + M(3,10)*z.*z + M(3,11)*x.*x.*x + M(3,12)*x.*x.*y + M(3,13)*x.*x.*z + M(3,14)*x.*y.*y + M(3,15)*x.*y.*z + M(3,16)*x.*z.*z + M(3,17)*y.*y.*y + M(3,18)*y.*y.*z + M(3,19)*y.*z.*z + M(3,20)*z.*z.*z + M(3,21)*x.*x.*x.*x + M(3,22)*x.*x.*x.*y + M(3,23)*x.*x.*x.*z + M(3,24)*x.*x.*y.*y + M(3,25)*x.*x.*y.*z + M(3,26)*x.*x.*z.*z + M(3,27)*x.*y.*y.*y + M(3,28)*x.*y.*y.*z + M(3,29)*x.*y.*z.*z + M(3,30)*x.*z.*z.*z + M(3,31)*y.*y.*y.*y + M(3,32)*y.*y.*y.*z + M(3,33)*y.*y.*z.*z + M(3,34)*y.*z.*z.*z + M(3,35)*z.*z.*z.*z; + elseif s(2)==56 + xx = M(1,1) + M(1,2)*x + M(1,3)*y + M(1,4)*z + M(1,5)*x.*x + M(1,6)*x.*y + M(1,7)*x.*z + M(1,8)*y.*y + M(1,9)*y.*z + M(1,10)*z.*z + M(1,11)*x.*x.*x + M(1,12)*x.*x.*y + M(1,13)*x.*x.*z + M(1,14)*x.*y.*y + M(1,15)*x.*y.*z + M(1,16)*x.*z.*z + M(1,17)*y.*y.*y + M(1,18)*y.*y.*z + M(1,19)*y.*z.*z + M(1,20)*z.*z.*z + M(1,21)*x.*x.*x.*x + M(1,22)*x.*x.*x.*y + M(1,23)*x.*x.*x.*z + M(1,24)*x.*x.*y.*y + M(1,25)*x.*x.*y.*z + M(1,26)*x.*x.*z.*z + M(1,27)*x.*y.*y.*y + M(1,28)*x.*y.*y.*z + M(1,29)*x.*y.*z.*z + M(1,30)*x.*z.*z.*z + M(1,31)*y.*y.*y.*y + M(1,32)*y.*y.*y.*z + M(1,33)*y.*y.*z.*z + M(1,34)*y.*z.*z.*z + M(1,35)*z.*z.*z.*z + M(1,36)*x.*x.*x.*x.*x + M(1,37)*x.*x.*x.*x.*y + M(1,38)*x.*x.*x.*x.*z + M(1,39)*x.*x.*x.*y.*y + M(1,40)*x.*x.*x.*y.*z + M(1,41)*x.*x.*x.*z.*z + M(1,42)*x.*x.*y.*y.*y + M(1,43)*x.*x.*y.*y.*z + M(1,44)*x.*x.*y.*z.*z + M(1,45)*x.*x.*z.*z.*z + M(1,46)*x.*y.*y.*y.*y + M(1,47)*x.*y.*y.*y.*z + M(1,48)*x.*y.*y.*z.*z + M(1,49)*x.*y.*z.*z.*z + M(1,50)*x.*z.*z.*z.*z + M(1,51)*y.*y.*y.*y.*y + M(1,52)*y.*y.*y.*y.*z + M(1,53)*y.*y.*y.*z.*z + M(1,54)*y.*y.*z.*z.*z + M(1,55)*y.*z.*z.*z.*z + M(1,56)*z.*z.*z.*z.*z; + yy = M(2,1) + M(2,2)*x + M(2,3)*y + M(2,4)*z + M(2,5)*x.*x + M(2,6)*x.*y + M(2,7)*x.*z + M(2,8)*y.*y + M(2,9)*y.*z + M(2,10)*z.*z + M(2,11)*x.*x.*x + M(2,12)*x.*x.*y + M(2,13)*x.*x.*z + M(2,14)*x.*y.*y + M(2,15)*x.*y.*z + M(2,16)*x.*z.*z + M(2,17)*y.*y.*y + M(2,18)*y.*y.*z + M(2,19)*y.*z.*z + M(2,20)*z.*z.*z + M(2,21)*x.*x.*x.*x + M(2,22)*x.*x.*x.*y + M(2,23)*x.*x.*x.*z + M(2,24)*x.*x.*y.*y + M(2,25)*x.*x.*y.*z + M(2,26)*x.*x.*z.*z + M(2,27)*x.*y.*y.*y + M(2,28)*x.*y.*y.*z + M(2,29)*x.*y.*z.*z + M(2,30)*x.*z.*z.*z + M(2,31)*y.*y.*y.*y + M(2,32)*y.*y.*y.*z + M(2,33)*y.*y.*z.*z + M(2,34)*y.*z.*z.*z + M(2,35)*z.*z.*z.*z + M(2,36)*x.*x.*x.*x.*x + M(2,37)*x.*x.*x.*x.*y + M(2,38)*x.*x.*x.*x.*z + M(2,39)*x.*x.*x.*y.*y + M(2,40)*x.*x.*x.*y.*z + M(2,41)*x.*x.*x.*z.*z + M(2,42)*x.*x.*y.*y.*y + M(2,43)*x.*x.*y.*y.*z + M(2,44)*x.*x.*y.*z.*z + M(2,45)*x.*x.*z.*z.*z + M(2,46)*x.*y.*y.*y.*y + M(2,47)*x.*y.*y.*y.*z + M(2,48)*x.*y.*y.*z.*z + M(2,49)*x.*y.*z.*z.*z + M(2,50)*x.*z.*z.*z.*z + M(2,51)*y.*y.*y.*y.*y + M(2,52)*y.*y.*y.*y.*z + M(2,53)*y.*y.*y.*z.*z + M(2,54)*y.*y.*z.*z.*z + M(2,55)*y.*z.*z.*z.*z + M(2,56)*z.*z.*z.*z.*z; + zz = M(3,1) + M(3,2)*x + M(3,3)*y + M(3,4)*z + M(3,5)*x.*x + M(3,6)*x.*y + M(3,7)*x.*z + M(3,8)*y.*y + M(3,9)*y.*z + M(3,10)*z.*z + M(3,11)*x.*x.*x + M(3,12)*x.*x.*y + M(3,13)*x.*x.*z + M(3,14)*x.*y.*y + M(3,15)*x.*y.*z + M(3,16)*x.*z.*z + M(3,17)*y.*y.*y + M(3,18)*y.*y.*z + M(3,19)*y.*z.*z + M(3,20)*z.*z.*z + M(3,21)*x.*x.*x.*x + M(3,22)*x.*x.*x.*y + M(3,23)*x.*x.*x.*z + M(3,24)*x.*x.*y.*y + M(3,25)*x.*x.*y.*z + M(3,26)*x.*x.*z.*z + M(3,27)*x.*y.*y.*y + M(3,28)*x.*y.*y.*z + M(3,29)*x.*y.*z.*z + M(3,30)*x.*z.*z.*z + M(3,31)*y.*y.*y.*y + M(3,32)*y.*y.*y.*z + M(3,33)*y.*y.*z.*z + M(3,34)*y.*z.*z.*z + M(3,35)*z.*z.*z.*z + M(3,36)*x.*x.*x.*x.*x + M(3,37)*x.*x.*x.*x.*y + M(3,38)*x.*x.*x.*x.*z + M(3,39)*x.*x.*x.*y.*y + M(3,40)*x.*x.*x.*y.*z + M(3,41)*x.*x.*x.*z.*z + M(3,42)*x.*x.*y.*y.*y + M(3,43)*x.*x.*y.*y.*z + M(3,44)*x.*x.*y.*z.*z + M(3,45)*x.*x.*z.*z.*z + M(3,46)*x.*y.*y.*y.*y + M(3,47)*x.*y.*y.*y.*z + M(3,48)*x.*y.*y.*z.*z + M(3,49)*x.*y.*z.*z.*z + M(3,50)*x.*z.*z.*z.*z + M(3,51)*y.*y.*y.*y.*y + M(3,52)*y.*y.*y.*y.*z + M(3,53)*y.*y.*y.*z.*z + M(3,54)*y.*y.*z.*z.*z + M(3,55)*y.*z.*z.*z.*z + M(3,56)*z.*z.*z.*z.*z; + else + error('invalid size of nonlinear transformation matrix'); + end + + warped = [xx yy zz]; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % linear warping using homogenous coordinate transformation matrix + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +elseif strcmp(method, 'homogenous') || strcmp(method, 'homogeneous') + if all(size(M)==3) + % convert the 3x3 homogenous transformation matrix (corresponding with 2D) + % into a 4x4 homogenous transformation matrix (corresponding with 3D) + M = [ + M(1,1) M(1,2) 0 M(1,3) + M(2,1) M(2,2) 0 M(2,3) + 0 0 0 0 + M(3,1) M(3,2) 0 M(3,3) + ]; + end + + warped = M * [input'; ones(1, size(input, 1))]; + warped = warped(1:3,:)'; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % using external function that returns a homogenous transformation matrix + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +elseif exist(method, 'file') + % get the homogenous transformation matrix + H = feval(method, M); + warped = warp_apply(H, input, 'homogenous'); + +else + error('unrecognized transformation method'); +end + +if ~input3d + % convert from 3D back to 2D representation + warped = warped(:,1:2); +end + diff --git a/external/fieldtrip/spass2fieldtrip.m b/external/fieldtrip/spass2fieldtrip.m new file mode 100644 index 0000000..af23f78 --- /dev/null +++ b/external/fieldtrip/spass2fieldtrip.m @@ -0,0 +1,165 @@ +function [lfp, spike, stm, bhv] = spass2fieldtrip(dirname); + +% SPASS2FIELDTRIP reads data from a set of SPASS data files and converts +% the contents into data structures that FieldTrip understands. +% +% Use as +% [lfp, spike, stm, bhv] = spass2fieldtrip(dirname) +% +% The specified directory should contain the SPASS files, and the files should have +% the same name as the directory. +% +% The swa and sti input file are combined into the spike output structure. +% For the rest of the data it is trivial how the input and output relate. +% +% For example, if you specify +% [lfp, spike, bhv, stm] = spass2fieldtrip('jeb012a02') +% then the following files should exist: +% 'jeb012a02/jeb012a02.ana' +% 'jeb012a02/jeb012a02.swa' +% 'jeb012a02/jeb012a02.spi' +% 'jeb012a02/jeb012a02.stm' +% 'jeb012a02/jeb012a02.bhv' +% +% Subsequently you can analyze the data in fieldtrip, or write the spike +% waveforms to a nex file for offline sorting using +% write_fcdc_spike('jeb012a02_ch1.nex', spike, 'dataformat', 'plexon_nex', 'chanindx', 1) +% write_fcdc_spike('jeb012a02_ch2.nex', spike, 'dataformat', 'plexon_nex', 'chanindx', 2) +% write_fcdc_spike('jeb012a02_ch3.nex', spike, 'dataformat', 'plexon_nex', 'chanindx', 3) + +% Copyright (C) 2007, Robert Oostenveld +% +% $Log: spass2fieldtrip.m,v $ +% Revision 1.3 2008/09/22 20:17:44 roboos +% added call to fieldtripdefs to the begin of the function +% +% Revision 1.2 2007/10/08 13:01:12 roboos +% added glue to link spike timestamps and lfp continuous channels +% made change to reflect the transposed input data +% +% Revision 1.1 2007/10/04 11:58:28 roboos +% first implementation +% + +fieldtripdefs + +fsample_ana = 1000; +fsample_swa = 32000; + +anafile = fullfile(dirname, [dirname '.ana']); +swafile = fullfile(dirname, [dirname '.swa']); +spifile = fullfile(dirname, [dirname '.spi']); +stmfile = fullfile(dirname, [dirname '.stm']); +bhvfile = fullfile(dirname, [dirname '.bhv']); + +if ~exist(anafile, 'file'), error(sprintf('the file "%s" does not exist', anafile)); end +if ~exist(swafile, 'file'), error(sprintf('the file "%s" does not exist', swafile)); end +if ~exist(spifile, 'file'), error(sprintf('the file "%s" does not exist', spifile)); end +if ~exist(stmfile, 'file'), error(sprintf('the file "%s" does not exist', stmfile)); end +if ~exist(bhvfile, 'file'), error(sprintf('the file "%s" does not exist', bhvfile)); end + +% read the data +fprintf('reading %s\n', anafile); ana = read_labview_dtlg(anafile, 'int16'); +fprintf('reading %s\n', swafile); swa = read_labview_dtlg(swafile, 'int16'); +fprintf('reading %s\n', spifile); spi = read_labview_dtlg(spifile, 'int32'); +fprintf('reading %s\n', stmfile); stm = read_labview_dtlg(stmfile, 'int32'); +fprintf('reading %s\n', bhvfile); bhv = read_labview_dtlg(bhvfile, 'int32'); + +% determine the number of trials +ntrials = numel(bhv.data{1}); + +nchans = numel(ana.data)./ntrials; +ana.data = reshape(ana.data, [nchans, ntrials]); + +% prepare the continuous LFP data +lfp = []; +lfp.trial = {}; +lfp.time = {}; +lfp.label = {}; +lfp.fsample = fsample_ana; +for i=1:ntrials + tmp = cell2mat(ana.data(:,i)')'; + lfp.trial{i} = tmp; + lfp.time{i} = ((1:size(tmp,2))-1)/fsample_ana; + nsamples(i) = length(lfp.time{i}); +end +for i=1:size(ana.data,1) + lfp.label{i,1} = sprintf('chan%d', i); +end + +% the data is trial based, try to estimate teh time between subsequent +% trials, or better: the time between subsequent stimuli +isi = 10^ceil(log10(max(nsamples)+1)); + +nchans = numel(swa.data)./ntrials; +swa.data = reshape(swa.data, [nchans, ntrials]); +spi.data = reshape(spi.data, [nchans, ntrials]); + +% prepare the spike data +spike = []; +spike.label = {}; +spike.waveform = {}; % 1xnchans cell-array, each element contains a matrix (Nsamples X Nspikes), can be empty +spike.timestamp = {}; % 1xnchans cell-array, each element contains a vector (1 X Nspikes) +spike.unit = {}; % 1xnchans cell-array, each element contains a vector (1 X Nspikes) +for i=1:size(swa.data,1) + spike.label{i} = sprintf('chan%d', i); +end + +nspikes = zeros(nchans, ntrials); +for i=1:nchans + for j=1:ntrials + nspikes(i,j) = length(swa.data{i,j}); + end +end + +% reinsert the inter-trial intervals, this links both the LFP and the spike +% timestamps to a common continuous timeaxis +for j=1:nchans + for i=1:ntrials + spi.data{j,i} = spi.data{j,i} + (i-1)*(fsample_swa./fsample_ana)*isi; + end +end + +% convert the spike timestamps and waveforms to a fieldtrip-compatible format +for i=1:nchans + spike.waveform{i} = cell2mat(swa.data(i,:)); + spike.timestamp{i} = cell2mat(spi.data(i,:)')'; + spike.unit{i} = ones(size(spike.timestamp{i})); % since unsorted +end + +% prepare the other output +stm = stm.data{1}(:); +bhv = bhv.data{1}(:); + +cfg = []; + +% add the version details of this function call to the configuration +try + % get the full name of the function + cfg.version.name = mfilename('fullpath'); +catch + % required for compatibility with Matlab versions prior to release 13 (6.5) + [st, i] = dbstack; + cfg.version.name = st(i); +end +cfg.version.id = '$Id: spass2fieldtrip.m 1100 2010-05-19 14:51:31Z roboos $'; + +% remember the exact configuration details in the output +lfp.cfg = cfg; +spike.cfg = cfg; + +% remember where the lfp trials are on the imaginary continuous timeaxis, +% this links both the LFP and the spike timestamps to a common continuous +% timeaxis +trl = zeros(ntrials, 3); +for i=1:ntrials + begsample = (i-1)*isi+1; + endsample = begsample+nsamples(i)-1; + offset = 0; + trl(i,:) = [begsample endsample offset]; +end +lfp.cfg.trl = trl; +lfp.hdr.FirstTimeStamp = 0; +lfp.hdr.TimeStampPerSample = fsample_swa./fsample_ana; + + diff --git a/external/fieldtrip/statfun/private/nanmean.m b/external/fieldtrip/statfun/private/nanmean.m new file mode 100644 index 0000000..04a6912 --- /dev/null +++ b/external/fieldtrip/statfun/private/nanmean.m @@ -0,0 +1,61 @@ +% nanmean() - Average, not considering NaN values +% +% Usage: same as mean() + +% Author: Arnaud Delorme, CNL / Salk Institute, 16 Oct 2002 + +%123456789012345678901234567890123456789012345678901234567890123456789012 + +% Copyright (C) 2001 Arnaud Delorme, Salk Institute, arno@salk.edu +% +% This program is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: nanmean.m 952 2010-04-21 18:29:51Z roboos $ + +function out = nanmean(in, dim) + +if nargin < 1 + help nanmean; + return; +end; +if nargin < 2 + if size(in,1) ~= 1 + dim = 1; + elseif size(in,2) ~= 1 + dim = 2; + else + dim = 3; + end; +end; +tmpin = in; +tmpin(find(isnan(in(:)))) = 0; +out = sum(tmpin, dim) ./ sum(~isnan(in),dim); + diff --git a/external/fieldtrip/statfun/private/nanstd.m b/external/fieldtrip/statfun/private/nanstd.m new file mode 100644 index 0000000..bae32cf --- /dev/null +++ b/external/fieldtrip/statfun/private/nanstd.m @@ -0,0 +1,76 @@ +% nanstd() - std, not considering NaN values +% +% Usage: same as std() + +% Author: Arnaud Delorme, CNL / Salk Institute, Sept 2003 + +%123456789012345678901234567890123456789012345678901234567890123456789012 + +% Copyright (C) 2003 Arnaud Delorme, Salk Institute, arno@salk.edu +% +% This program is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: nanstd.m 952 2010-04-21 18:29:51Z roboos $ + +function out = nanstd(in, varargin) + +if nargin < 1 + help nanstd; + return; +end +if nargin == 1, flag = 0; end +if nargin < 3, + if size(in,1) ~= 1 + dim = 1; + elseif size(in,2) ~= 1 + dim = 2; + else + dim = 3; + end +end +if nargin == 2, flag = varargin{1}; end +if nargin == 3, + flag = varargin{1}; + dim = varargin{2}; +end +if isempty(flag), flag = 0; end + +nans = find(isnan(in)); +in(nans) = 0; + +nonnans = ones(size(in)); +nonnans(nans) = 0; +nonnans = sum(nonnans, dim); +nononnans = find(nonnans==0); +nonnans(nononnans) = 1; + +out = sqrt((sum(in.^2, dim)-sum(in, dim).^2./nonnans)./(nonnans-abs(flag-1))); +out(nononnans) = NaN; diff --git a/external/fieldtrip/statfun/private/nansum.m b/external/fieldtrip/statfun/private/nansum.m new file mode 100644 index 0000000..93f3479 --- /dev/null +++ b/external/fieldtrip/statfun/private/nansum.m @@ -0,0 +1,61 @@ +% nansum() - Take the sum, not considering NaN values +% +% Usage: same as sum() + +% Author: Arnaud Delorme, CNL / Salk Institute, 16 Oct 2002 + +%123456789012345678901234567890123456789012345678901234567890123456789012 + +% Copyright (C) 2001 Arnaud Delorme, Salk Institute, arno@salk.edu +% +% This program is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: nansum.m 952 2010-04-21 18:29:51Z roboos $ + +function out = nansum(in, dim) + +if nargin < 1 + help nansum; + return; +end; +if nargin < 2 + if size(in,1) ~= 1 + dim = 1; + elseif size(in,2) ~= 1 + dim = 2; + else + dim = 3; + end; +end; +tmpin = in; +tmpin(find(isnan(in(:)))) = 0; +out = sum(tmpin, dim); + diff --git a/external/fieldtrip/statfun/private/nanvar.m b/external/fieldtrip/statfun/private/nanvar.m new file mode 100644 index 0000000..e1474df --- /dev/null +++ b/external/fieldtrip/statfun/private/nanvar.m @@ -0,0 +1,76 @@ +% nanvar() - var, not considering NaN values +% +% Usage: same as var() + +% Author: Arnaud Delorme, CNL / Salk Institute, Sept 2003 + +%123456789012345678901234567890123456789012345678901234567890123456789012 + +% Copyright (C) 2003 Arnaud Delorme, Salk Institute, arno@salk.edu +% +% This program is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: nanvar.m 952 2010-04-21 18:29:51Z roboos $ + +function out = nanvar(in, varargin) + +if nargin < 1 + help nanvar; + return; +end +if nargin == 1, flag = 0; end +if nargin < 3, + if size(in,1) ~= 1 + dim = 1; + elseif size(in,2) ~= 1 + dim = 2; + else + dim = 3; + end +end +if nargin == 2, flag = varargin{1}; end +if nargin == 3, + flag = varargin{1}; + dim = varargin{2}; +end +if isempty(flag), flag = 0; end + +nans = find(isnan(in)); +in(nans) = 0; + +nonnans = ones(size(in)); +nonnans(nans) = 0; +nonnans = sum(nonnans, dim); +nononnans = find(nonnans==0); +nonnans(nononnans) = 1; + +out = (sum(in.^2, dim)-sum(in, dim).^2./nonnans)./(nonnans-abs(flag-1)); +out(nononnans) = NaN; diff --git a/external/fieldtrip/statfun/private/tcdf.m b/external/fieldtrip/statfun/private/tcdf.m new file mode 100644 index 0000000..e037b95 --- /dev/null +++ b/external/fieldtrip/statfun/private/tcdf.m @@ -0,0 +1,41 @@ +function p = tp(t,v); + +%TCDF Student's T cumulative distribution function (cdf). +% P = TCDF(X,V) computes the cdf for Student's T distribution +% with V degrees of freedom, at the values in X. V must be a +% scalar or have the same size as T. +% +% This is an alternative to the TCDF function that is implemented +% in the Matlab statistics toolbox. This version originates from +% http://www.statsci.org/matlab/statbox.html and originally was called TP. +% It has been renamed to TCDF for drop-in compatibility with the Matlab +% version. +% +% Gordon Smyth, University of Queensland, gks@maths.uq.edu.au +% 3 Apr 97 +% +% NaN compatible - Markus Bauer and Eric Maris, FCDC +% 27 Jan 2005 +% +% fixed bug concerning NaN compatibility +% 21 Aug 2006, Markus Siegel + +if v <= 0, error('Degrees of freedom must be positive.'); end; + +% resize v if necessary +if all(size(v)==1) + v = ones(size(t))*v; +end; + +%check for NaN's - don't do calculations on them, give those out as NaNs +if any( not(isfinite(t(:))) | not(isfinite(v(:))) ) + sel = find(isfinite(t) & isfinite(v)); + x=nan(size(t)); + p=nan(size(t)); + x(sel) = t(sel).^2 ./ (v(sel) + t(sel).^2) ; + p(sel) = 0.5 .* ( 1 + sign(t(sel)) .* betainc( x(sel), 0.5, 0.5*v(sel) ) ); +else + x = t.^2 ./ (v + t.^2) ; + p = 0.5 .* ( 1 + sign(t) .* betainc( x, 0.5, 0.5*v ) ); +end; + diff --git a/external/fieldtrip/statfun/private/tinv.m b/external/fieldtrip/statfun/private/tinv.m new file mode 100644 index 0000000..e113b8a --- /dev/null +++ b/external/fieldtrip/statfun/private/tinv.m @@ -0,0 +1,328 @@ +function x = tinv(p,v); +% TINV Inverse of Student's T cumulative distribution function (cdf). +% X=TINV(P,V) returns the inverse of Student's T cdf with V degrees +% of freedom, at the values in P. +% +% The size of X is the common size of P and V. A scalar input +% functions as a constant matrix of the same size as the other input. +% +% This is an open source function that was assembled by Eric Maris using +% open source subfunctions found on the web. + +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: tinv.m 952 2010-04-21 18:29:51Z roboos $ + +if nargin < 2, + error('Requires two input arguments.'); +end + +[errorcode p v] = distchck(2,p,v); + +if errorcode > 0 + error('Requires non-scalar arguments to match in size.'); +end + +% Initialize X to zero. +x=zeros(size(p)); + +k = find(v < 0 | v ~= round(v)); +if any(k) + tmp = NaN; + x(k) = tmp(ones(size(k))); +end + +k = find(v == 1); +if any(k) + x(k) = tan(pi * (p(k) - 0.5)); +end + +% The inverse cdf of 0 is -Inf, and the inverse cdf of 1 is Inf. +k0 = find(p == 0); +if any(k0) + tmp = Inf; + x(k0) = -tmp(ones(size(k0))); +end +k1 = find(p ==1); +if any(k1) + tmp = Inf; + x(k1) = tmp(ones(size(k1))); +end + +k = find(p >= 0.5 & p < 1); +if any(k) + z = betainv(2*(1-p(k)),v(k)/2,0.5); + x(k) = sqrt(v(k) ./ z - v(k)); +end + +k = find(p < 0.5 & p > 0); +if any(k) + z = betainv(2*(p(k)),v(k)/2,0.5); + x(k) = -sqrt(v(k) ./ z - v(k)); +end + +%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION distchck +%%%%%%%%%%%%%%%%%%%%%%%%% + +function [errorcode,varargout] = distchck(nparms,varargin) +%DISTCHCK Checks the argument list for the probability functions. + +errorcode = 0; +varargout = varargin; + +if nparms == 1 + return; +end + +% Get size of each input, check for scalars, copy to output +isscalar = (cellfun('prodofsize',varargin) == 1); + +% Done if all inputs are scalars. Otherwise fetch their common size. +if (all(isscalar)), return; end + +n = nparms; + +for j=1:n + sz{j} = size(varargin{j}); +end +t = sz(~isscalar); +size1 = t{1}; + +% Scalars receive this size. Other arrays must have the proper size. +for j=1:n + sizej = sz{j}; + if (isscalar(j)) + t = zeros(size1); + t(:) = varargin{j}; + varargout{j} = t; + elseif (~isequal(sizej,size1)) + errorcode = 1; + return; + end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION betainv +%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function x = betainv(p,a,b); +%BETAINV Inverse of the beta cumulative distribution function (cdf). +% X = BETAINV(P,A,B) returns the inverse of the beta cdf with +% parameters A and B at the values in P. +% +% The size of X is the common size of the input arguments. A scalar input +% functions as a constant matrix of the same size as the other inputs. +% +% BETAINV uses Newton's method to converge to the solution. + +% Reference: +% [1] M. Abramowitz and I. A. Stegun, "Handbook of Mathematical +% Functions", Government Printing Office, 1964. + +% B.A. Jones 1-12-93 + +if nargin < 3, + error('Requires three input arguments.'); +end + +[errorcode p a b] = distchck(3,p,a,b); + +if errorcode > 0 + error('Requires non-scalar arguments to match in size.'); +end + +% Initialize x to zero. +x = zeros(size(p)); + +% Return NaN if the arguments are outside their respective limits. +k = find(p < 0 | p > 1 | a <= 0 | b <= 0); +if any(k), + tmp = NaN; + x(k) = tmp(ones(size(k))); +end + +% The inverse cdf of 0 is 0, and the inverse cdf of 1 is 1. +k0 = find(p == 0 & a > 0 & b > 0); +if any(k0), + x(k0) = zeros(size(k0)); +end + +k1 = find(p==1); +if any(k1), + x(k1) = ones(size(k1)); +end + +% Newton's Method. +% Permit no more than count_limit interations. +count_limit = 100; +count = 0; + +k = find(p > 0 & p < 1 & a > 0 & b > 0); +pk = p(k); + +% Use the mean as a starting guess. +xk = a(k) ./ (a(k) + b(k)); + + +% Move starting values away from the boundaries. +if xk == 0, + xk = sqrt(eps); +end +if xk == 1, + xk = 1 - sqrt(eps); +end + + +h = ones(size(pk)); +crit = sqrt(eps); + +% Break out of the iteration loop for the following: +% 1) The last update is very small (compared to x). +% 2) The last update is very small (compared to 100*eps). +% 3) There are more than 100 iterations. This should NEVER happen. + +while(any(abs(h) > crit * abs(xk)) & max(abs(h)) > crit ... + & count < count_limit), + + count = count+1; + h = (betacdf(xk,a(k),b(k)) - pk) ./ betapdf(xk,a(k),b(k)); + xnew = xk - h; + +% Make sure that the values stay inside the bounds. +% Initially, Newton's Method may take big steps. + ksmall = find(xnew < 0); + klarge = find(xnew > 1); + if any(ksmall) | any(klarge) + xnew(ksmall) = xk(ksmall) /10; + xnew(klarge) = 1 - (1 - xk(klarge))/10; + end + + xk = xnew; +end + +% Return the converged value(s). +x(k) = xk; + +if count==count_limit, + fprintf('\nWarning: BETAINV did not converge.\n'); + str = 'The last step was: '; + outstr = sprintf([str,'%13.8f'],h); + fprintf(outstr); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION betapdf +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function y = betapdf(x,a,b) +%BETAPDF Beta probability density function. +% Y = BETAPDF(X,A,B) returns the beta probability density +% function with parameters A and B at the values in X. +% +% The size of Y is the common size of the input arguments. A scalar input +% functions as a constant matrix of the same size as the other inputs. + +% References: +% [1] M. Abramowitz and I. A. Stegun, "Handbook of Mathematical +% Functions", Government Printing Office, 1964, 26.1.33. + +if nargin < 3, + error('Requires three input arguments.'); +end + +[errorcode x a b] = distchck(3,x,a,b); + +if errorcode > 0 + error('Requires non-scalar arguments to match in size.'); +end + +% Initialize Y to zero. +y = zeros(size(x)); + +% Return NaN for parameter values outside their respective limits. +k1 = find(a <= 0 | b <= 0 | x < 0 | x > 1); +if any(k1) + tmp = NaN; + y(k1) = tmp(ones(size(k1))); +end + +% Return Inf for x = 0 and a < 1 or x = 1 and b < 1. +% Required for non-IEEE machines. +k2 = find((x == 0 & a < 1) | (x == 1 & b < 1)); +if any(k2) + tmp = Inf; + y(k2) = tmp(ones(size(k2))); +end + +% Return the beta density function for valid parameters. +k = find(~(a <= 0 | b <= 0 | x <= 0 | x >= 1)); +if any(k) + y(k) = x(k) .^ (a(k) - 1) .* (1 - x(k)) .^ (b(k) - 1) ./ beta(a(k),b(k)); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SUBFUNCTION betacdf +%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function p = betacdf(x,a,b); +%BETACDF Beta cumulative distribution function. +% P = BETACDF(X,A,B) returns the beta cumulative distribution +% function with parameters A and B at the values in X. +% +% The size of P is the common size of the input arguments. A scalar input +% functions as a constant matrix of the same size as the other inputs. +% +% BETAINC does the computational work. + +% Reference: +% [1] M. Abramowitz and I. A. Stegun, "Handbook of Mathematical +% Functions", Government Printing Office, 1964, 26.5. + +if nargin < 3, + error('Requires three input arguments.'); +end + +[errorcode x a b] = distchck(3,x,a,b); + +if errorcode > 0 + error('Requires non-scalar arguments to match in size.'); +end + +% Initialize P to 0. +p = zeros(size(x)); + +k1 = find(a<=0 | b<=0); +if any(k1) + tmp = NaN; + p(k1) = tmp(ones(size(k1))); +end + +% If is X >= 1 the cdf of X is 1. +k2 = find(x >= 1); +if any(k2) + p(k2) = ones(size(k2)); +end + +k = find(x > 0 & x < 1 & a > 0 & b > 0); +if any(k) + p(k) = betainc(x(k),a(k),b(k)); +end + +% Make sure that round-off errors never make P greater than 1. +k = find(p > 1); +p(k) = ones(size(k)); diff --git a/external/fieldtrip/private/statfun_actvsblT.m b/external/fieldtrip/statfun/statfun_actvsblT.m similarity index 81% rename from external/fieldtrip/private/statfun_actvsblT.m rename to external/fieldtrip/statfun/statfun_actvsblT.m index daaa0c7..88aaf09 100644 --- a/external/fieldtrip/private/statfun_actvsblT.m +++ b/external/fieldtrip/statfun/statfun_actvsblT.m @@ -43,38 +43,7 @@ % Copyright (C) 2006, Eric Maris % -% $Log: statfun_actvsblT.m,v $ -% Revision 1.1 2008/09/23 07:31:14 roboos -% Moved all statfuns and trialfuns to their own directories, where they will be easier to find for the end-user. Also updated fieldtripdefs accordingly. -% -% Revision 1.7 2007/04/02 20:40:32 erimar -% Corrected an error in the calculation of the time-average of the data. -% Updated help. -% -% Revision 1.6 2007/03/27 15:30:17 erimar -% Calculate the number of time samples on the basis of the information in -% cfg.dim and size(dat). -% -% Revision 1.5 2006/09/12 12:13:07 roboos -% removed default values for cfg.ivar and uvar, defaults should be specified elsewhere -% -% Revision 1.4 2006/06/07 12:51:18 roboos -% renamed cfg.ivrownr into cfg.ivar -% renamed cfg.uorownr into cfg.uvar -% renamed pval into prob for consistency with other fieldtrip functions -% -% Revision 1.3 2006/05/17 11:59:55 erimar -% Corrected bugs after extensive checking of the properties of this -% statfun. -% -% Revision 1.2 2006/05/12 15:29:44 erimar -% Added functionality to calculate one- and two-sided critical -% values and p-values. -% -% Revision 1.1 2006/05/05 13:09:47 erimar -% First version of statfun_actvsblT. -% -% +% Subversion does not use the Log keyword, use 'svn log ' or 'svn -v log | less' to get detailled information % set defaults if ~isfield(cfg, 'computestat'), cfg.computestat='yes'; end; diff --git a/external/fieldtrip/private/statfun_depsamplesF.m b/external/fieldtrip/statfun/statfun_depsamplesF.m similarity index 87% rename from external/fieldtrip/private/statfun_depsamplesF.m rename to external/fieldtrip/statfun/statfun_depsamplesF.m index c854c60..1869122 100644 --- a/external/fieldtrip/private/statfun_depsamplesF.m +++ b/external/fieldtrip/statfun/statfun_depsamplesF.m @@ -42,30 +42,7 @@ % Copyright (C) 2006, Eric Maris % -% $Log: statfun_depsamplesF.m,v $ -% Revision 1.1 2008/09/23 07:31:15 roboos -% Moved all statfuns and trialfuns to their own directories, where they will be easier to find for the end-user. Also updated fieldtripdefs accordingly. -% -% Revision 1.5 2006/09/12 12:13:07 roboos -% removed default values for cfg.ivar and uvar, defaults should be specified elsewhere -% -% Revision 1.4 2006/06/07 12:51:18 roboos -% renamed cfg.ivrownr into cfg.ivar -% renamed cfg.uorownr into cfg.uvar -% renamed pval into prob for consistency with other fieldtrip functions -% -% Revision 1.3 2006/05/17 11:59:55 erimar -% Corrected bugs after extensive checking of the properties of this -% statfun. -% -% Revision 1.2 2006/05/12 15:30:11 erimar -% Added functionality to calculate one- and two-sided critical -% values and p-values. -% -% Revision 1.1 2006/05/05 13:12:06 erimar -% First version of statfun_depsamplesF. -% -% +% Subversion does not use the Log keyword, use 'svn log ' or 'svn -v log | less' to get detailled information % set defaults if ~isfield(cfg, 'computestat'), cfg.computestat='yes'; end; diff --git a/external/fieldtrip/private/statfun_depsamplesT.m b/external/fieldtrip/statfun/statfun_depsamplesT.m similarity index 82% rename from external/fieldtrip/private/statfun_depsamplesT.m rename to external/fieldtrip/statfun/statfun_depsamplesT.m index 4d2be52..e0236bc 100644 --- a/external/fieldtrip/private/statfun_depsamplesT.m +++ b/external/fieldtrip/statfun/statfun_depsamplesT.m @@ -35,30 +35,7 @@ % Copyright (C) 2006, Eric Maris % -% $Log: statfun_depsamplesT.m,v $ -% Revision 1.1 2008/09/23 07:31:15 roboos -% Moved all statfuns and trialfuns to their own directories, where they will be easier to find for the end-user. Also updated fieldtripdefs accordingly. -% -% Revision 1.5 2006/09/12 12:13:07 roboos -% removed default values for cfg.ivar and uvar, defaults should be specified elsewhere -% -% Revision 1.4 2006/06/07 12:51:18 roboos -% renamed cfg.ivrownr into cfg.ivar -% renamed cfg.uorownr into cfg.uvar -% renamed pval into prob for consistency with other fieldtrip functions -% -% Revision 1.3 2006/05/17 11:59:55 erimar -% Corrected bugs after extensive checking of the properties of this -% statfun. -% -% Revision 1.2 2006/05/12 15:32:40 erimar -% Added functionality to calculate one- and two-sided critical values and -% p-values. -% -% Revision 1.1 2006/05/05 13:08:04 erimar -% First version of statfun_depsamplesT. -% -% +% Subversion does not use the Log keyword, use 'svn log ' or 'svn -v log | less' to get detailled information % set defaults if ~isfield(cfg, 'computestat'), cfg.computestat='yes'; end; diff --git a/external/fieldtrip/statfun/statfun_depsamplesregrT.m b/external/fieldtrip/statfun/statfun_depsamplesregrT.m new file mode 100644 index 0000000..8917578 --- /dev/null +++ b/external/fieldtrip/statfun/statfun_depsamplesregrT.m @@ -0,0 +1,112 @@ +function [s,cfg] = statfun_depsamplesregrT(cfg, dat, design); + +% STATFUN_depsamplesregrT calculates dependent samples regression T-statistic +% on the biological data in dat (the dependent variable), using the information on +% the independent variable (iv) in design. +% +% The external interface of this function has to be +% [s,cfg] = statfun_depsamplesregrT(cfg, dat, design); +% where +% dat contains the biological data, Nsamples x Nreplications +% design contains the independent variable (iv) and the unit-of-observation (UO) +% factor, Nreplications x Nvar +% +% Configuration options: +% cfg.computestat = 'yes' or 'no', calculate the statistic (default='yes') +% cfg.computecritval = 'yes' or 'no', calculate the critical values of the test statistics (default='no') +% cfg.computeprob = 'yes' or 'no', calculate the p-values (default='no') +% +% The following options are relevant if cfg.computecritval='yes' and/or +% cfg.computeprob='yes'. +% cfg.alpha = critical alpha-level of the statistical test (default=0.05) +% cfg.tail = -1, 0, or 1, left, two-sided, or right (default=1) +% cfg.tail in combination with cfg.computecritval='yes' +% determines whether the critical value is computed at +% quantile cfg.alpha (with cfg.tail=-1), at quantiles +% cfg.alpha/2 and (1-cfg.alpha/2) (with cfg.tail=0), or at +% quantile (1-cfg.alpha) (with cfg.tail=1). +% +% Design specification: +% cfg.ivar = row number of the design that contains the independent variable. +% cfg.uvar = row number of design that contains the labels of the UOs (subjects or trials) +% (default=2). The labels are assumed to be integers ranging from 1 to +% the number of UOs. +% + +% Copyright (C) 2006, Eric Maris +% +% Subversion does not use the Log keyword, use 'svn log ' or 'svn -v log | less' to get detailled information + +% set defaults +if ~isfield(cfg, 'computestat'), cfg.computestat='yes'; end; +if ~isfield(cfg, 'computecritval'), cfg.computecritval='no'; end; +if ~isfield(cfg, 'computeprob'), cfg.computeprob='no'; end; +if ~isfield(cfg, 'alpha'), cfg.alpha=0.05; end; +if ~isfield(cfg, 'tail'), cfg.tail=1; end; + +% perform some checks on the configuration +if strcmp(cfg.computeprob,'yes') & strcmp(cfg.computestat,'no') + error('P-values can only be calculated if the test statistics are calculated.'); +end; + +if ~isempty(cfg.cvar) + condlabels=unique(design(cfg.cvar,:)); + nblocks=length(condlabels); +else + nblocks=1; +end; + +nunits = max(design(cfg.uvar,:)); +df = nunits - 1; +if nunits<2 + error('The data must contain at least two units-of-observation (usually subjects).') +end; + +if strcmp(cfg.computestat,'yes') +% compute the statistic + regrweights=zeros(size(dat,1),nunits); + for indx=1:nunits + unitselvec=find(design(cfg.uvar,:)==indx); + indvar=design(cfg.ivar,unitselvec); + if isempty(cfg.cvar) + designmat=[ones(1,length(indvar));indvar]; + else + designmat=zeros((nblocks+1),length(indvar)); + for blockindx=1:nblocks + blockselvec=find(design(cfg.cvar,unitselved)==condlabels(blockindx)); + designmat(blockindx,blockselvec)=1; + end; + designmat((nblocks+1),:)=indvar; + end; + coeff=(designmat*designmat')\(designmat*dat(:,unitselvec)'); + regrweights(:,indx)=coeff((nblocks+1),:)'; + end; + avgw=mean(regrweights,2); + varw=var(regrweights,0,2); + s.stat=sqrt(nunits)*avgw./sqrt(varw); +end; + +if strcmp(cfg.computecritval,'yes') + % also compute the critical values + s.df = df; + if cfg.tail==-1 + s.critval = tinv(cfg.alpha,df); + elseif cfg.tail==0 + s.critval = [tinv(cfg.alpha/2,df),tinv(1-cfg.alpha/2,df)]; + elseif cfg.tail==1 + s.critval = tinv(1-cfg.alpha,df); + end; +end + +if strcmp(cfg.computeprob,'yes') + % also compute the p-values + s.df = df; + if cfg.tail==-1 + s.prob = tcdf(s.stat,s.df); + elseif cfg.tail==0 + s.prob = 2*tcdf(-abs(s.stat),s.df); + elseif cfg.tail==1 + s.prob = 1-tcdf(s.stat,s.df); + end; +end + diff --git a/external/fieldtrip/private/statfun_diff.m b/external/fieldtrip/statfun/statfun_diff.m similarity index 100% rename from external/fieldtrip/private/statfun_diff.m rename to external/fieldtrip/statfun/statfun_diff.m diff --git a/external/fieldtrip/private/statfun_diff_itc.m b/external/fieldtrip/statfun/statfun_diff_itc.m similarity index 84% rename from external/fieldtrip/private/statfun_diff_itc.m rename to external/fieldtrip/statfun/statfun_diff_itc.m index c780d20..862cfa5 100644 --- a/external/fieldtrip/private/statfun_diff_itc.m +++ b/external/fieldtrip/statfun/statfun_diff_itc.m @@ -19,13 +19,7 @@ % Copyright (C) 2008, Robert Oostenveld % -% $Log: statfun_diff_itc.m,v $ -% Revision 1.1 2008/09/23 07:31:15 roboos -% Moved all statfuns and trialfuns to their own directories, where they will be easier to find for the end-user. Also updated fieldtripdefs accordingly. -% -% Revision 1.3 2008/04/22 10:58:20 roboos -% added option cfg.complex, to allow testing the phase (upon request by Arno) -% +% Subversion does not use the Log keyword, use 'svn log ' or 'svn -v log | less' to get detailled information % set the defaults if ~isfield(cfg, 'complex'), cfg.complex = 'diffabs'; end diff --git a/external/fieldtrip/private/statfun_indepsamplesF.m b/external/fieldtrip/statfun/statfun_indepsamplesF.m similarity index 82% rename from external/fieldtrip/private/statfun_indepsamplesF.m rename to external/fieldtrip/statfun/statfun_indepsamplesF.m index c0345e8..df8bfea 100644 --- a/external/fieldtrip/private/statfun_indepsamplesF.m +++ b/external/fieldtrip/statfun/statfun_indepsamplesF.m @@ -32,29 +32,7 @@ % Copyright (C) 2006, Eric Maris % -% $Log: statfun_indepsamplesF.m,v $ -% Revision 1.1 2008/09/23 07:31:15 roboos -% Moved all statfuns and trialfuns to their own directories, where they will be easier to find for the end-user. Also updated fieldtripdefs accordingly. -% -% Revision 1.5 2006/09/12 12:13:07 roboos -% removed default values for cfg.ivar and uvar, defaults should be specified elsewhere -% -% Revision 1.4 2006/06/07 12:51:18 roboos -% renamed cfg.ivrownr into cfg.ivar -% renamed cfg.uorownr into cfg.uvar -% renamed pval into prob for consistency with other fieldtrip functions -% -% Revision 1.3 2006/05/17 11:59:55 erimar -% Corrected bugs after extensive checking of the properties of this -% statfun. -% -% Revision 1.2 2006/05/12 15:32:40 erimar -% Added functionality to calculate one- and two-sided critical values and -% p-values. -% -% Revision 1.1 2006/05/05 13:11:26 erimar -% First version of statfun_indepsamplesF. -% +% Subversion does not use the Log keyword, use 'svn log ' or 'svn -v log | less' to get detailled information % set defaults if ~isfield(cfg, 'computestat'), cfg.computestat='yes'; end; diff --git a/external/fieldtrip/statfun/statfun_indepsamplesT.m b/external/fieldtrip/statfun/statfun_indepsamplesT.m new file mode 100644 index 0000000..e7cf6fc --- /dev/null +++ b/external/fieldtrip/statfun/statfun_indepsamplesT.m @@ -0,0 +1,101 @@ +function [s,cfg] = statfun_indepsamplesT(cfg, dat, design); + +% STATFUN_indepsamplesT calculates the independent samples T-statistic +% on the biological data in dat (the dependent variable), using the information on +% the independent variable (iv) in design. +% +% The external interface of this function has to be +% [s,cfg] = statfun_indepsamplesT(cfg, dat, design); +% where +% dat contains the biological data, Nsamples x Nreplications +% design contains the independent variable (iv), Nfac x Nreplications +% +% Configuration options: +% cfg.computestat = 'yes' or 'no', calculate the statistic (default='yes') +% cfg.computecritval = 'yes' or 'no', calculate the critical values of the test statistics (default='no') +% cfg.computeprob = 'yes' or 'no', calculate the p-values (default='no') +% +% The following options are relevant if cfg.computecritval='yes' and/or +% cfg.computeprob='yes'. +% cfg.alpha = critical alpha-level of the statistical test (default=0.05) +% cfg.tail = -1, 0, or 1, left, two-sided, or right (default=1) +% cfg.tail in combination with cfg.computecritval='yes' +% determines whether the critical value is computed at +% quantile cfg.alpha (with cfg.tail=-1), at quantiles +% cfg.alpha/2 and (1-cfg.alpha/2) (with cfg.tail=0), or at +% quantile (1-cfg.alpha) (with cfg.tail=1). +% +% Design specification: +% cfg.ivar = row number of the design that contains the labels of the conditions that must be +% compared (default=1). The labels are the numbers 1 and 2. +% + +% Copyright (C) 2006, Eric Maris +% +% Subversion does not use the Log keyword, use 'svn log ' or 'svn -v log | less' to get detailled information + +% set defaults +if ~isfield(cfg, 'computestat'), cfg.computestat='yes'; end; +if ~isfield(cfg, 'computecritval'), cfg.computecritval='no'; end; +if ~isfield(cfg, 'computeprob'), cfg.computeprob='no'; end; +if ~isfield(cfg, 'alpha'), cfg.alpha=0.05; end; +if ~isfield(cfg, 'tail'), cfg.tail=1; end; + +% perform some checks on the configuration +if strcmp(cfg.computeprob,'yes') && strcmp(cfg.computestat,'no') + % probabilities can only be calculated if the test statistics are calculated + cfg.computestat = 'yes'; +end; + +% perform some checks on the design +sel1 = find(design(cfg.ivar,:)==1); +sel2 = find(design(cfg.ivar,:)==2); +nreplc1 = sum(~isnan(dat(:,sel1)), 2); +nreplc2 = sum(~isnan(dat(:,sel2)), 2); +nrepl = nreplc1 + nreplc2; +if any(nrepl' or 'svn -v log | less' to get detailled information % set defaults if ~isfield(cfg, 'computestat'), cfg.computestat='yes'; end; diff --git a/external/fieldtrip/private/statfun_indepsamplesregrT.m b/external/fieldtrip/statfun/statfun_indepsamplesregrT.m similarity index 78% rename from external/fieldtrip/private/statfun_indepsamplesregrT.m rename to external/fieldtrip/statfun/statfun_indepsamplesregrT.m index 45fde0c..a31c682 100644 --- a/external/fieldtrip/private/statfun_indepsamplesregrT.m +++ b/external/fieldtrip/statfun/statfun_indepsamplesregrT.m @@ -31,33 +31,7 @@ % Copyright (C) 2006, Eric Maris % -% $Log: statfun_indepsamplesregrT.m,v $ -% Revision 1.1 2008/09/23 07:31:15 roboos -% Moved all statfuns and trialfuns to their own directories, where they will be easier to find for the end-user. Also updated fieldtripdefs accordingly. -% -% Revision 1.6 2007/07/30 21:52:58 erimar -% Changed calculations such that control variables (specified in cfg.cvar) -% are also taken into account. -% -% Revision 1.5 2006/09/12 12:13:07 roboos -% removed default values for cfg.ivar and uvar, defaults should be specified elsewhere -% -% Revision 1.4 2006/06/07 12:51:18 roboos -% renamed cfg.ivrownr into cfg.ivar -% renamed cfg.uorownr into cfg.uvar -% renamed pval into prob for consistency with other fieldtrip functions -% -% Revision 1.3 2006/05/17 11:59:55 erimar -% Corrected bugs after extensive checking of the properties of this -% statfun. -% -% Revision 1.2 2006/05/12 15:32:40 erimar -% Added functionality to calculate one- and two-sided critical values and -% p-values. -% -% Revision 1.1 2006/05/05 13:05:24 erimar -% First version of statfun_indepsamplesregrT. -% +% Subversion does not use the Log keyword, use 'svn log ' or 'svn -v log | less' to get detailled information % set defaults if ~isfield(cfg, 'computestat'), cfg.computestat='yes'; end; diff --git a/external/fieldtrip/private/statfun_mean.m b/external/fieldtrip/statfun/statfun_mean.m similarity index 100% rename from external/fieldtrip/private/statfun_mean.m rename to external/fieldtrip/statfun/statfun_mean.m diff --git a/external/fieldtrip/private/statfun_pooledT.m b/external/fieldtrip/statfun/statfun_pooledT.m similarity index 100% rename from external/fieldtrip/private/statfun_pooledT.m rename to external/fieldtrip/statfun/statfun_pooledT.m diff --git a/external/fieldtrip/statfun/statfun_roc.m b/external/fieldtrip/statfun/statfun_roc.m new file mode 100644 index 0000000..8c49519 --- /dev/null +++ b/external/fieldtrip/statfun/statfun_roc.m @@ -0,0 +1,143 @@ +function [s, cfg] = statfun_roc(cfg, dat, design) + +% STATFUN_ROC computes the ROC (the 'area under the curve') of the separability +% of the data, which is divided over two conditions, as specified in the +% design. +% +% This function is called by STATISTICS_MONTECARLO, where you can specify +% cfg.statistic = 'xxx' which will be evaluated as statfun_xxx. +% +% The external interface of this function has to be +% [s] = statfun_xxx(cfg, dat, design); +% where +% dat contains the biological data, Nvoxels x Nreplications +% design contains the independent variable, 1 x Nreplications +% +% Additional settings can be passed through to this function using +% the cfg structure. +% +% Example +% a = randn(1,1000) + 1; +% b = randn(1,1000); +% design = [1*ones(1,1000) 2*ones(1,1000)]; +% auc = statfun_roc([], [a b], design); +% +% Note that this statfun performs a one sided test in which "a" is assumed +% to be larger than "b". + +if ~isfield(cfg, 'ivar'), cfg.ivar = 1; end +if ~isfield(cfg, 'logtransform'), cfg.logtransform = 'no'; end + +if strcmp(cfg.logtransform, 'yes'), + dat = log10(dat); +end + +if isfield(cfg, 'numbins') + % this function was completely reimplemented on 21 July 2008 by Robert Oostenveld + % the old function had a positive bias in the AUC (i.e. the expected value was not 0.5) + error('the option cfg.numbins is not supported any more'); +end + +% start with a quick test to see whether there appear to be NaNs +if any(isnan(dat(1,:))) + % exclude trials that contain NaNs for all observed data points + sel = all(isnan(dat),1); + dat = dat(:,~sel); + design = design(:,~sel); +end + +% logical indexing is faster than using find(...) +selA = (design(cfg.ivar,:)==1); +selB = (design(cfg.ivar,:)==2); +% select the data in the two classes +datA = dat(:, selA); +datB = dat(:, selB); + +nobs = size(dat,1); +na = size(datA,2); +nb = size(datB,2); +auc = zeros(nobs, 1); + +for k = 1:nobs + % compute the area under the curve for each channel/time/frequency + a = datA(k,:); + b = datB(k,:); + + % to speed up the AUC, the critical value is determined by the actual + % values in class B, which also ensures a regular sampling of the False Alarms + b = sort(b); + + ca = zeros(nb+1,1); + ib = zeros(nb+1,1); + % cb = zeros(nb+1,1); + % ia = zeros(nb+1,1); + + for i=1:nb + % for the first approach below, the critval could also be choosen based on e.g. linspace(min,max,n) + critval = b(i); + + % for each of the two distributions, determine the number of correct and incorrect assignments given the critical value + % ca(i) = sum(a>=critval); + % ib(i) = sum(b>=critval); + % cb(i) = sum(b=critval); % correct assignments to class A + ib(i) = nb-i+1; % incorrect assignments to class B + end + + % add the end point + ca(end) = 0; + ib(end) = 0; + % cb(end) = nb; + % ia(end) = na; + + hits = ca/na; + fa = ib/nb; + + % the numerical integration is faster if the points are sorted + hits = fliplr(hits); + fa = fliplr(fa); + + if true + % this part is optional and should only be used when exploring the data + figure + plot(fa, hits, '.-') + xlabel('false positive'); + ylabel('true positive'); + title('ROC-curve'); + end + + % compute the area under the curve using numerical integration + auc(k) = numint(fa, hits); + +end + +s.stat = auc; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% NUMINT computes a numerical integral of a set of sampled points using +% linear interpolation. Alugh the algorithm works for irregularly sampled points +% along the x-axis, it will perform best for regularly sampled points +% +% Use as +% z = numint(x, y) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function z = numint(x, y) +if ~all(diff(x)>=0) + % ensure that the points are sorted along the x-axis + [x, i] = sort(x); + y = y(i); +end +n = length(x); +z = 0; +for i=1:(n-1) + x0 = x(i); + y0 = y(i); + dx = x(i+1)-x(i); + dy = y(i+1)-y(i); + z = z + (y0 * dx) + (dy*dx/2); +end + + diff --git a/external/fieldtrip/private/statistics_analytic.m b/external/fieldtrip/statistics_analytic.m similarity index 85% rename from external/fieldtrip/private/statistics_analytic.m rename to external/fieldtrip/statistics_analytic.m index c3a9fb5..8a74fbb 100644 --- a/external/fieldtrip/private/statistics_analytic.m +++ b/external/fieldtrip/statistics_analytic.m @@ -40,31 +40,23 @@ % Copyright (C) 2006, Robert Oostenveld % -% $Log: statistics_analytic.m,v $ -% Revision 1.8 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.7 2007/03/27 15:36:37 erimar -% Updated help (replaced p-value by significance probability). +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.6 2006/11/23 11:08:19 roboos -% implemented Holms' correction method for multiple comparisons +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.5 2006/07/27 07:58:12 roboos -% improved documentation, added default for cfg.tail (default is two-sided) -% -% Revision 1.4 2006/07/20 15:03:11 roboos -% documentation change -% -% Revision 1.3 2006/07/14 06:29:29 roboos -% return cfg as output for later reference -% -% Revision 1.2 2006/06/07 12:58:05 roboos -% added some defaults, implemented FDR and Bonferoni -% -% Revision 1.1 2006/05/31 13:04:31 roboos -% new implementation +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: statistics_analytic.m 948 2010-04-21 18:02:21Z roboos $ fieldtripdefs diff --git a/external/fieldtrip/statistics_crossvalidate.m b/external/fieldtrip/statistics_crossvalidate.m new file mode 100644 index 0000000..9e691ae --- /dev/null +++ b/external/fieldtrip/statistics_crossvalidate.m @@ -0,0 +1,150 @@ +function stat = statistics_crossvalidate(cfg, dat, design) + +% STATISTICS_CROSSVALIDATE performs cross-validation using a prespecified +% multivariate analysis given by cfg.mva +% +% Options: +% cfg.metric = the metric to report (default = 'accuracy') +% cfg.cv = crossvalidator object +% overloads the following +% cfg.mva = a multivariate analysis (default = {standardizer svmmethod}) +% cfg.nfolds = number of folds (default = 10) +% cfg.compact = whether or not to save the mva procedure (true) +% cfg.model = whether or not to save the average model (true) +% +% Returns: +% stat.prob = computed using the specified metric +% stat.significance = w.r.t. the null-hypothesis that we do no better than a +% majority classifier +% stat.cv = the trained crossvalidator +% +% See also CROSSVALIDATE, MVA +% +% Requires: multivariate analysis toolbox + +% Copyright (c) 2007, Marcel van Gerven +% F.C. Donders Centre for Cognitive Neuroimaging, Nijmegen, NL +% +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. +% +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . +% +% $Id: statistics_crossvalidate.m 996 2010-04-28 19:48:40Z marvger $ + +fieldtripdefs + +% specify classification procedure +if isfield(cfg,'cv') + cv = cfg.cv; +else + + if ~isfield(cfg,'mva') + cfg.mva = mva({ ... + standardizer('verbose',true) ... + svmmethod('verbose',true) ... + }); + else + if ~isa(cfg.mva,'mva') + cfg.mva = mva(cfg.mva,'verbose',true); + end + end + + if ~isfield(cfg,'nfolds'), cfg.nfolds = 10; end + if ~isfield(cfg,'compact'), cfg.compact = true; end + if ~isfield(cfg,'model'), cfg.model = true; end + + for j=1:length(cfg.mva.mvmethods) + cfg.mva.mvmethods{j}.indims = cfg.dim; + end + + cv = crossvalidator('procedure',cfg.mva,'nfolds',cfg.nfolds,'compact',cfg.compact,'model',cfg.model,'verbose',true); + +end + +% specify metric returned in stat.prob +if ~isfield(cfg,'metric'), cfg.metric = 'accuracy'; end + +% check for transfer learning; this is implemented by cfg.dataset, +% indicating the dataset number for each element in the design matrix + +if isfield(cfg,'dataset') && ~isempty(cfg.dataset) + + % split up the datasets + + tmpdat = dat'; + tmpdesign = design'; + + n = max(cfg.dataset); + + dat = cell(1,n); + design = cell(1,n); + for c=1:n + dat{c} = tmpdat(cfg.dataset == c,:); + design{c} = tmpdesign(cfg.dataset == c,:); + end + +else + + dat = dat'; + design = design'; + +end + +% perform everything ;o) +cv = cv.validate(dat,design); + +% the statistic of interest +res = cv.evaluate('metric',cfg.metric); +stat.prob = res; + +% is the statistic significant? +stat.significance = cv.significance(); + +% get the models +if ~cfg.compact || cfg.model + + if cfg.model + m = cv.model; + desc = cv.desc; + else + [m,desc] = cv.getmodel(); + end + + for c=1:size(m,1) % iterate over parameter types + + if size(m,2) > 1 % transfer learning + + for j=1:size(m,2) + + if numel(m{c,j}) == prod(cfg.dim) + stat.(sprintf('model%d_%d',c,j)) = reshape(m{c,j},cfg.dim); + end + end + + else + if numel(m{c}) == prod(cfg.dim) + stat.(sprintf('model%d',c)) = reshape(m{c},cfg.dim); + end + end + end + + for c=1:size(desc,1) % iterate over parameter types + stat.(sprintf('desc%d',c)) = desc{c}; + end + +end + +% save crossvalidator object +stat.cv = cv; diff --git a/external/fieldtrip/private/statistics_montecarlo.m b/external/fieldtrip/statistics_montecarlo.m similarity index 77% rename from external/fieldtrip/private/statistics_montecarlo.m rename to external/fieldtrip/statistics_montecarlo.m index 0647590..1bf4f40 100644 --- a/external/fieldtrip/private/statistics_montecarlo.m +++ b/external/fieldtrip/statistics_montecarlo.m @@ -1,4 +1,4 @@ -function [stat, cfg] = statistics_montecarlo(cfg, dat, design) +function [stat, cfg] = statistics_montecarlo(cfg, dat, design, varargin) % STATISTICS_MONTECARLO performs a nonparametric statistical test by calculating % Monte-Carlo estimates of the significance probabilities and/or critical values from the @@ -23,8 +23,9 @@ % cfg.design = design matrix % cfg.numrandomization = number of randomizations, can be 'all' % cfg.correctm = apply multiple-comparison correction, 'no', 'max', cluster', 'bonferoni', 'holms', 'fdr' (default = 'no') -% cfg.alpha = critical value for rejecting the null-hypothesis (default = 0.05) +% cfg.alpha = critical value for rejecting the null-hypothesis per tail (default = 0.05) % cfg.tail = -1, 1 or 0 (default = 0) +% cfg.correcttail = correct p-values or alpha-values when doing a two-sided test, 'alpha','prob' or 'no' (default = 'no') % cfg.ivar = number or list with indices, independent variable(s) % cfg.uvar = number or list with indices, unit variable(s) % cfg.wvar = number or list with indices, within-cell variable(s) @@ -38,12 +39,12 @@ % value per cluster. % cfg.clusterstatistic = how to combine the single samples that belong to a cluster, 'maxsum', 'maxsize', 'wcm' (default = 'maxsum') % cfg.clusterthreshold = method for single-sample threshold, 'parametric', 'nonparametric_individual', 'nonparametric_common' (default = 'parametric') -% cfg.clusteralpha = for either parametric or nonparametric thresholding (default = 0.05) +% cfg.clusteralpha = for either parametric or nonparametric thresholding per tail (default = 0.05) % cfg.clustercritval = for parametric thresholding (default is determined by the statfun) % cfg.clustertail = -1, 1 or 0 (default = 0) % % To include the channel dimension for clustering, you should specify -% cfg.neighbours = structure with the neighbours of each channel, see NEIGHBOURHOODSELECTION +% cfg.neighbours = structure with the neighbours of each channel, see NEIGHBOURSELECTION % If you specify an empty neighbourhood structure, clustering will only be done % in frequency and time (if available) and not over neighbouring channels. % @@ -80,119 +81,23 @@ % Copyright (C) 2005-2007, Robert Oostenveld % -% $Log: statistics_montecarlo.m,v $ -% Revision 1.31 2009/08/06 08:31:31 roboos -% renamed some internal variables +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.30 2009/04/23 07:48:23 roboos -% added cfg.randomseed option, default is yes +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.29 2008/11/25 13:52:10 estmee -% Documentation update +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.28 2008/11/13 10:05:04 jansch -% included undocumented option to precondition the data. The preconditioning -% will be done within the statfun, and can be applied before, or after the -% computation of the observed statistic. -% -% Revision 1.27 2008/10/09 12:48:51 roboos -% added contrastcoefs to tmpcfg for determining critvals -% -% Revision 1.26 2008/10/02 12:37:33 roboos -% removed some old backward compatibility code, errors will be given in case the old cfg options are used -% use the "unused" option in checkconfig in case of correctm~=cluster to remove the cluster options -% -% Revision 1.25 2008/09/26 15:27:14 sashae -% checkconfig: checks if the input cfg is valid for this function -% -% Revision 1.24 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.23 2008/06/25 06:38:31 roboos -% removed backward compatibility cfg option rename anova->fstat -% -% Revision 1.22 2008/01/15 11:32:41 roboos -% implemented cfg.correctp, default is the same as before. Probably the -% old behaviour is UNDESIRED, but more discussion is needed and a thourough -% explanation should be provided on the mailing list and in the MEG meeting. -% -% Revision 1.21 2007/07/30 21:51:22 erimar -% Corrected a bug with respect to the copying of cfg.cvar in tmpcfg.cvar. -% In fact, cfg.cvar was not copied in tmpcfg.cvar. This is now corrected. -% -% Revision 1.20 2007/07/23 14:07:19 roboos -% fixed number of output arguments for statfun -% -% Revision 1.19 2007/07/23 13:26:52 jansch -% replaced feval by function-handle call -% -% Revision 1.18 2007/07/18 15:09:46 roboos -% Adjusted to the modified output of resampledesign, which now also returns -% the reindexing matrix for permutation (just like in case of bootstrap) -% instead of the permuted design itself. -% Renamed the "res" variable into "resample". -% Updated documentation with cfg.cvar. -% -% Revision 1.17 2007/07/17 10:37:06 roboos -% fixed bug for resampling dat in case of bootstrap (incorrect indexing) -% remember the cfg that is returned by clusterstat -% -% Revision 1.16 2007/07/04 16:04:53 roboos -% renamed randomizedesign to resampledesign -% first implementation of bootstrapping, sofar only for unpaired data -% added cfg.resampling=bootstrap/permutation -% -% Revision 1.15 2007/06/19 14:11:16 roboos -% only do backward compatibility for cfg.clusterthreshold if present -% -% Revision 1.14 2007/06/19 12:52:37 roboos -% implemented seperate common and individual nonparametric thresholds -% renamed the option cfg.clusterthreshold=nonparametric into nonparametric_individual, the new option is nonparametric_common -% updated documentation -% -% Revision 1.13 2007/03/27 15:38:00 erimar -% Passed cfg.dimord and cfg.dim to the called function. Updated help. -% -% Revision 1.12 2007/03/21 20:00:43 roboos -% Fixed bug (relates to cluster thresholding): also pass the clustertail -% to the statfun for computing the parametric clustercritval. The incorrect -% default was to use clustertail=0, also in case of one-tailed tests. -% -% Revision 1.11 2006/11/23 11:08:19 roboos -% implemented Holms' correction method for multiple comparisons -% -% Revision 1.10 2006/10/05 10:20:52 roboos -% updated cdocumentation -% -% Revision 1.9 2006/09/12 12:13:57 roboos -% fixed bug related to computation of clustercritval, ivar and uvar are needed for that -% -% Revision 1.8 2006/07/27 07:58:27 roboos -% improved documentation -% -% Revision 1.7 2006/07/20 15:35:47 roboos -% fixed a bug in the handling of some old cfgs -% added support for multi-field stat-structures as output of the statfun (only for statobs) -% -% Revision 1.6 2006/07/14 11:03:18 roboos -% remove clustertail from cfg in case no clustering is done -% -% Revision 1.5 2006/07/14 06:36:37 roboos -% changed handling of old cfg.correctm specification -% -% Revision 1.4 2006/07/14 06:29:29 roboos -% return cfg as output for later reference -% -% Revision 1.3 2006/07/12 15:53:25 roboos -% Moved all code and documentation from statistics_random to statistics_montecarlo as agreed with Eric -% The old functino is only there for backward compatibility, it gives an instructive warning -% -% Revision 1.2 2006/06/14 11:57:54 roboos -% changed documentation for cfg.correctm -% -% Revision 1.1 2006/05/31 13:04:31 roboos -% new implementation +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: statistics_montecarlo.m 948 2010-04-21 18:02:21Z roboos $ fieldtripdefs @@ -216,7 +121,7 @@ if ~isfield(cfg, 'uvar'), cfg.uvar = []; end if ~isfield(cfg, 'cvar'), cfg.cvar = []; end if ~isfield(cfg, 'wvar'), cfg.wvar = []; end -if ~isfield(cfg, 'correctp'), cfg.correctp = 'no'; end % for the number of tails in a two-sided test +if ~isfield(cfg, 'correcttail'), cfg.correcttail = 'no'; end % for the number of tails in a two-sided test if ~isfield(cfg, 'randomseed'), cfg.randomseed = 'yes'; end if ~isfield(cfg, 'precondition'), cfg.precondition = []; end @@ -232,6 +137,22 @@ cfg = checkconfig(cfg, 'unused', {'clusterstatistic', 'clusteralpha', 'clustercritval', 'clusterthreshold', 'clustertail', 'neighbours'}); end +% for backward compatibility and other warnings relating correcttail +if isfield(cfg,'correctp') && strcmp(cfg.correctp,'yes') + warning('cfg.correctp has been renamed to cfg.correcttail and the options have been changed') + disp('setting cfg.correcttail to ''prob''') + cfg.correcttail = 'prob'; + cfg = rmfield(cfg,'correctp'); +elseif isfield(cfg,'correctp') && strcmp(cfg.correctp,'no') + cfg = checkconfig(cfg, 'renamed', {'correctp', 'correcttail'}); +elseif strcmp(cfg.correcttail,'no') && cfg.tail==0 && cfg.alpha==0.05 + warning('doing a two-sided test without correcting p-values or alpha-level, p-values and alpha-level will reflect one-sided tests per tail') +end + +% get the single keyval for issource out +issource = keyval('issource', varargin); if isempty(issource), issource = 0; end + + % for backward compatibility if size(design,2)~=size(dat,2) design = transpose(design); @@ -397,7 +318,7 @@ if strcmp(cfg.correctm, 'cluster') % do the cluster postprocessing - [stat, cfg] = clusterstat(cfg, statrand, statobs); + [stat, cfg] = clusterstat(cfg, statrand, statobs,'issource',issource); else switch cfg.tail case 1 @@ -429,8 +350,11 @@ % achieved by multiplying the probability with a factor of two, prior to % thresholding it wich cfg.alpha. The advantage of this solution is that % it results in a p-value that corresponds with a parametric probability. -if strcmp(cfg.correctp, 'yes') && cfg.tail==0 +% Below both options are realized +if strcmp(cfg.correcttail, 'prob') && cfg.tail==0 stat.prob = stat.prob .* 2; +elseif strcmp(cfg.correcttail, 'alpha') && cfg.tail==0 + cfg.alpha = cfg.alpha / 2; end switch lower(cfg.correctm) diff --git a/external/fieldtrip/private/statistics_stats.m b/external/fieldtrip/statistics_stats.m similarity index 89% rename from external/fieldtrip/private/statistics_stats.m rename to external/fieldtrip/statistics_stats.m index 7005742..8a90722 100644 --- a/external/fieldtrip/private/statistics_stats.m +++ b/external/fieldtrip/statistics_stats.m @@ -12,7 +12,7 @@ % cfg.feedback = 'no', 'text', 'textbar', 'gui' % cfg.method = 'stats' % cfg.statistic = 'ttest' test against a mean of zero -% 'ttest2' compare the mean in two conditions +% 'ttest2' compare the mean in two conditions % 'paired-ttest' % 'anova1' % 'kruskalwallis' @@ -25,28 +25,23 @@ % Copyright (C) 2005, Robert Oostenveld % -% $Log: statistics_stats.m,v $ -% Revision 1.8 2008/09/22 20:17:44 roboos -% added call to fieldtripdefs to the begin of the function +% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip +% for the documentation and details. % -% Revision 1.7 2006/06/07 12:59:09 roboos -% fixed a bug in determining the size of the design matrix +% FieldTrip is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. % -% Revision 1.6 2006/04/20 09:58:34 roboos -% updated documentation +% FieldTrip is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. % -% Revision 1.5 2006/04/10 12:13:15 roboos -% besides prob, also return mask and stat when possible -% return cfg as second output argument -% -% Revision 1.4 2006/03/30 12:24:34 roboos -% Implemented private/fixinside, which facilitates consistent -% handling of source/volume data. Improved documentation. Fixed some -% bugs related to inconsistent handling of ROIs (i.e. inside/outside) -% -% Revision 1.3 2005/12/08 16:58:20 ingnie -% fixed bug paired ttest, added log +% You should have received a copy of the GNU General Public License +% along with FieldTrip. If not, see . % +% $Id: statistics_stats.m 948 2010-04-21 18:02:21Z roboos $ fieldtripdefs diff --git a/external/fieldtrip/private/trialfun_example1.m b/external/fieldtrip/trialfun/trialfun_example1.m similarity index 82% rename from external/fieldtrip/private/trialfun_example1.m rename to external/fieldtrip/trialfun/trialfun_example1.m index cea1d89..1979268 100644 --- a/external/fieldtrip/private/trialfun_example1.m +++ b/external/fieldtrip/trialfun/trialfun_example1.m @@ -7,12 +7,12 @@ % read the header information and the events from the data % this should always be done using the generic read_header % and read_event functions -hdr = read_fcdc_header(cfg.dataset); -event = read_fcdc_event(cfg.dataset); +hdr = read_header(cfg.dataset); +event = read_event(cfg.dataset); % search for "trigger" events -value = [event(find(strcmp('trigger', {event.type}))).value]'; -sample = [event(find(strcmp('trigger', {event.type}))).sample]'; +trigger = [event(find(strcmp('trigger', {event.type}))).value]'; +sample = [event(find(strcmp('trigger', {event.type}))).sample]'; % determine the number of samples before and after the trigger pretrig = -cfg.trialdef.pre * hdr.Fs; diff --git a/external/fieldtrip/private/trialfun_example2.m b/external/fieldtrip/trialfun/trialfun_example2.m similarity index 98% rename from external/fieldtrip/private/trialfun_example2.m rename to external/fieldtrip/trialfun/trialfun_example2.m index 819bc56..bacc413 100644 --- a/external/fieldtrip/private/trialfun_example2.m +++ b/external/fieldtrip/trialfun/trialfun_example2.m @@ -1,4 +1,4 @@ -function [dat] = trialfun_emgdetect(cfg); +function [dat] = trialfun_emgdetect(cfg) % TRIALFUN_EXAMPLE2 is an example trial function that detects muscle % activity in an EMG channel and defines variable length trials from the diff --git a/external/fieldtrip/private/trialfun_general.m b/external/fieldtrip/trialfun/trialfun_general.m similarity index 88% rename from external/fieldtrip/private/trialfun_general.m rename to external/fieldtrip/trialfun/trialfun_general.m index 31100da..c1c6b3d 100644 --- a/external/fieldtrip/private/trialfun_general.m +++ b/external/fieldtrip/trialfun/trialfun_general.m @@ -1,6 +1,6 @@ -function [trl, event] = trialfun_general(cfg); +function [trl, event] = trialfun_general(cfg) -% TRIALFUN_GENERAL determines trials/segments in the data that are +% TRIALFUN_GENERAL determines trials/segments in the data that are % interesting for analysis, using the general event structure returned % by read_event. This function is independent of the dataformat % @@ -17,35 +17,12 @@ % If you specify % cfg.trialdef.eventtype = '?' % a list with the events in your datafile will be displayed on screen. +% +% See also DEFINETRIAL, PREPROCESSING % Copyright (C) 2005-2008, Robert Oostenveld % -% $Log: trialfun_general.m,v $ -% Revision 1.6 2008/11/10 20:32:00 roboos -% reinserted trialfun that I accidentally removed -% -% Revision 1.4 2008/10/06 08:42:12 jansch -% included check for specifying trials across the boundaries of the datafile. -% Thanks to Joachim Gross. -% -% Revision 1.3 2008/10/01 11:00:06 ingnie -% fixed bug in gui part which appeared when eventvalue is list -% -% Revision 1.2 2008/09/29 08:39:38 roboos -% replaced read_fcdc_xxx with the new function names -% -% Revision 1.1 2008/09/23 07:31:15 roboos -% Moved all statfuns and trialfuns to their own directories, where they will be easier to find for the end-user. Also updated fieldtripdefs accordingly. -% -% Revision 1.6 2007/02/07 16:30:12 roboos -% do something with trials that overlap with teh beginning of the file (in case of gui) -% -% Revision 1.5 2007/02/07 07:30:30 roboos -% added gui option, thanks to Vladimir -% -% Revision 1.4 2007/01/09 09:47:25 roboos -% added warning about this function being deprecated, includes link to website documentation -% +% Subversion does not use the Log keyword, use 'svn log ' or 'svn -v log | less' to get detailled information % some events do not require the specification a type, pre or poststim period % in that case it is more convenient not to have them, instead of making them empty @@ -69,12 +46,25 @@ end end -% read the header and event information -hdr = read_header(cfg.headerfile); -try - event = read_event(cfg.headerfile); -catch - event = []; +% default rejection parameter +if ~isfield(cfg, 'eventformat'), cfg.eventformat = []; end +if ~isfield(cfg, 'headerformat'), cfg.headerformat = []; end +if ~isfield(cfg, 'dataformat'), cfg.dataformat = []; end + +% read the header, contains the sampling frequency +hdr = ft_read_header(cfg.headerfile, 'headerformat', cfg.headerformat); + +% read the events +if isfield(cfg, 'event') + fprintf('using the events from the configuration structure\n'); + event = cfg.event; +else + try + fprintf('reading the events from ''%s''\n', cfg.headerfile); + event = ft_read_event(cfg.headerfile, 'headerformat', cfg.headerformat, 'eventformat', cfg.eventformat); + catch + event = []; + end end % for the following, the trials do not depend on the events in the data diff --git a/external/fieldtrip/trialfun/trialfun_realtime.m b/external/fieldtrip/trialfun/trialfun_realtime.m new file mode 100644 index 0000000..8a37fee --- /dev/null +++ b/external/fieldtrip/trialfun/trialfun_realtime.m @@ -0,0 +1,111 @@ +function trl = trialfun_realtime(cfg) + +% TRIALFUN_REALTIME can be used in conjunction with rt_process to read realtime +% data. Trials are defined as [begsample endsample offset condition] +% +% The configuration structure can contain the following specifications +% cfg.minsample = the last sample number that was already considered (passed from rt_process) +% cfg.blocksize = in seconds. In case of events, offset is +% wrt the trigger. +% cfg.offset = the offset wrt the 0 point. In case of no events, offset is wrt +% prevSample. E.g., [-0.9 1] will read 1 second blocks with +% 0.9 second overlap +% cfg.bufferdata = {'first' 'last'}. If 'last' then only the last block of +% interest is read. Otherwise, all well-defined blocks are read (default = 'first') + +% Copyright (C) 2009, Marcel van Gerven +% +% Subversion does not use the Log keyword, use 'svn log ' or 'svn -v log | less' to get detailled information + + if ~isfield(cfg,'minsample'), cfg.minsample = 0; end + if ~isfield(cfg,'blocksize'), cfg.blocksize = 0.1; end + if ~isfield(cfg,'offset'), cfg.offset = 0; end + if ~isfield(cfg,'bufferdata'), cfg.bufferdata = 'first'; end + if ~isfield(cfg,'triggers'), cfg.triggers = []; end + + % blocksize and offset in terms of samples + cfg.blocksize = round(cfg.blocksize * cfg.hdr.Fs); + cfg.offset = round(cfg.offset * cfg.hdr.Fs); + + % retrieve trials of interest + if isempty(cfg.event) % asynchronous mode + trl = trialfun_asynchronous(cfg); + else % synchronous mode + trl = trialfun_synchronous(cfg); + end +end + +function trl = trialfun_asynchronous(cfg) + + trl = []; + + prevSample = cfg.minsample; + + if strcmp(cfg.bufferdata, 'last') % only get last block + + % begsample starts blocksize samples before the end + begsample = cfg.hdr.nSamples*cfg.hdr.nTrials - cfg.blocksize; + + % begsample should be offset samples away from the previous read + if begsample >= (prevSample + cfg.offset) + + endsample = cfg.hdr.nSamples*cfg.hdr.nTrials; + + if begsample < endsample && begsample > 0 + trl = [begsample endsample 0 nan]; + end + end + + else % get all blocks + + while true + + % see whether new samples are available + newsamples = (cfg.hdr.nSamples*cfg.hdr.nTrials-prevSample); + + % if newsamples exceeds the offset plus length specified in blocksize + if newsamples >= (cfg.offset+cfg.blocksize) + + % we do not consider samples < 1 + begsample = max(1,prevSample+cfg.offset); + endsample = max(1,prevSample+cfg.offset+cfg.blocksize); + + if begsample < endsample && endsample <= cfg.hdr.nSamples*cfg.hdr.nTrials + trl = [trl; [begsample endsample 0 nan]]; + end + prevSample = endsample; + + else + break; + end + end + end +end + +function trl = trialfun_synchronous(cfg) + + trl = []; + + % process all events + for j=1:length(cfg.event) + + if isempty(cfg.triggers) + curtrig = cfg.event(j).value; + else + [m1,curtrig] = ismember(cfg.event(j).value,cfg.triggers); + end + + if isempty(curtrig), curtrig = nan; end + + if isempty(cfg.triggers) || (~isempty(m1) && m1) + % catched a trigger of interest + + % we do not consider samples < 1 + begsample = max(1,cfg.event(j).sample + cfg.offset); + endsample = max(1,begsample + cfg.blocksize); + + trl = [trl; [begsample endsample cfg.offset curtrig]]; + + end + end +end diff --git a/external/fieldtrip/trialfun/trialfun_trial.m b/external/fieldtrip/trialfun/trialfun_trial.m new file mode 100644 index 0000000..a7c3afe --- /dev/null +++ b/external/fieldtrip/trialfun/trialfun_trial.m @@ -0,0 +1,24 @@ +function [trl, event] = trialfun_trial(cfg) + +% TRIALFUN_TRIAL creates a trial definition that corresponds to the +% events that are returned by READ_EVENT with type='trial' + +if isfield(cfg, 'event') + % for BCI applications events should be specified in the cfg + % to prevent reading the same events many times + event = cfg.event; +else + event = read_event(cfg.dataset); +end + +trl = []; +sel = find(strcmp({event.type}, 'trial')); + +for i=1:length(sel) + % determine the begin, end and offset for each trial and add it to the Nx3 matrix + begsample = event(sel(i)).sample; + endsample = begsample + event(sel(i)).duration - 1; + offset = event(sel(i)).offset; + trl = [trl; [begsample endsample offset]]; +end + diff --git a/external/fieldtrip/private/trialfun_twoclass_classification.m b/external/fieldtrip/trialfun/trialfun_twoclass_classification.m similarity index 86% rename from external/fieldtrip/private/trialfun_twoclass_classification.m rename to external/fieldtrip/trialfun/trialfun_twoclass_classification.m index 2e877ee..621d42b 100644 --- a/external/fieldtrip/private/trialfun_twoclass_classification.m +++ b/external/fieldtrip/trialfun/trialfun_twoclass_classification.m @@ -1,5 +1,7 @@ -function [trl] = trialfun_Subject01(cfg) +function [trl] = trialfun_twoclass_classification(cfg) +% TRIALFUN_TWOCLASS_CLASSIFICATION +% % This trial function can be used to train and test a real-time % classifier in offline and online mode. It selects pieces of data % in the two classes based on two trigger values. The first N occurences @@ -14,13 +16,7 @@ % cfg.trialdef.prestim = latency in seconds, e.g. 0.3 % cfg.trialdef.poststim = latency in seconds, e.g. 0.7 -% $Log: trialfun_twoclass_classification.m,v $ -% Revision 1.2 2009/06/04 15:36:21 roboos -% some small fixes -% -% Revision 1.1 2009/06/04 14:17:43 roboos -% first version, not yet tested -% +% Subversion does not use the Log keyword, use 'svn log ' or 'svn -v log | less' to get detailled information % these are used to count the number of training items in each class persistent numtrain1 @@ -36,13 +32,13 @@ if isfield(cfg, 'hdr') hdr = cfg.hdr; else - hdr = read_header(cfg.headerfile); + hdr = read_header(cfg.headerfile, 'headerformat', cfg.headerformat); end if isfield(cfg, 'event') event = cfg.event; else - event = read_event(cfg.headerfile); + event = read_event(cfg.headerfile, 'headerformat', cfg.headerformat); end baseline = round(cfg.trialdef.prestim*hdr.Fs); diff --git a/external/fileio/@uint64/abs.c b/external/fileio/@uint64/abs.c deleted file mode 100644 index 73fe53d..0000000 --- a/external/fileio/@uint64/abs.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * - * Copyright (C) 2006-2007, Robert Oostenveld - * - * This implements [y] = abs(x) - * - * This function does not check the occurence of integer overflowing. - * - */ - -#include -#include "mex.h" -#include "matrix.h" - -void -mexFunction (int nlhs, mxArray * plhs[], int nrhs, const mxArray * prhs[]) -{ - size_t M, N; - UINT64_T *x, *y; - int i; - - if (nlhs > 2) - mexErrMsgTxt ("Invalid number of output arguments"); - if (nrhs > 1) - mexErrMsgTxt ("Invalid number of input arguments"); - - if (!mxIsUint64(prhs[0])) - mexErrMsgTxt ("Invalid type of input arguments (should be uint64)"); - - M = mxGetM(prhs[0]); - N = mxGetN(prhs[0]); - - plhs[0] = (mxArray*)mxCreateNumericMatrix(M, N, mxUINT64_CLASS, mxREAL); - x = mxGetData(prhs[0]); - y = mxGetData(plhs[0]); - - for (i=0; i<(M*N); i++) - y[i] = x[i]; /* the absolute value of an unsigned integer is identical to the original value */ - - return; -} - diff --git a/external/fileio/@uint64/abs.m b/external/fileio/@uint64/abs.m deleted file mode 100644 index f4cc216..0000000 --- a/external/fileio/@uint64/abs.m +++ /dev/null @@ -1,35 +0,0 @@ -function [varargout] = funname(varargin) - -% FUNNAME compile the missing mex file on the fly - -% remember the original working directory -pwdir = pwd; - -% determine the name and full path of this function -funname = mfilename('fullpath'); -mexsrc = [funname '.c']; -[mexdir, mexname] = fileparts(funname); - -try - % try to compile the mex file on the fly - warning('trying to compile MEX file from %s', mexsrc); - cd(mexdir); - mex(mexsrc); - cd(pwdir); - success = true; - -catch - % compilation failed - disp(lasterr); - error('could not locate MEX file for %s', mexname); - cd(pwdir); - success = false; -end - -if success - % execute the mex file that was juist created - funname = mfilename; - funhandle = str2func(funname); - [varargout{1:nargout}] = funhandle(varargin{:}); -end - diff --git a/external/fileio/@uint64/abs.mexa64 b/external/fileio/@uint64/abs.mexa64 deleted file mode 100755 index f47894f..0000000 Binary files a/external/fileio/@uint64/abs.mexa64 and /dev/null differ diff --git a/external/fileio/@uint64/abs.mexglx b/external/fileio/@uint64/abs.mexglx deleted file mode 100755 index efc0622..0000000 Binary files a/external/fileio/@uint64/abs.mexglx and /dev/null differ diff --git a/external/fileio/@uint64/abs.mexmaci b/external/fileio/@uint64/abs.mexmaci deleted file mode 100755 index 064567a..0000000 Binary files a/external/fileio/@uint64/abs.mexmaci and /dev/null differ diff --git a/external/fileio/@uint64/abs.mexmaci64 b/external/fileio/@uint64/abs.mexmaci64 deleted file mode 100755 index 7f373d2..0000000 Binary files a/external/fileio/@uint64/abs.mexmaci64 and /dev/null differ diff --git a/external/fileio/@uint64/abs.mexw32 b/external/fileio/@uint64/abs.mexw32 deleted file mode 100644 index a21961e..0000000 Binary files a/external/fileio/@uint64/abs.mexw32 and /dev/null differ diff --git a/external/fileio/@uint64/abs.mexw64 b/external/fileio/@uint64/abs.mexw64 deleted file mode 100644 index 9f852ee..0000000 Binary files a/external/fileio/@uint64/abs.mexw64 and /dev/null differ diff --git a/external/fileio/@uint64/all.m b/external/fileio/@uint64/all.m deleted file mode 100644 index f9ebc62..0000000 --- a/external/fileio/@uint64/all.m +++ /dev/null @@ -1,42 +0,0 @@ -function y = any(x) - -% ALL True if all elements of a vector are nonzero. -% For vectors, ALL(V) returns logical 1 (TRUE) if none of the elements -% of the vector are zero. Otherwise it returns logical 0 (FALSE). For -% matrices, ALL(X) operates on the columns of X, returning a row vector -% of logical 1's and 0's. For N-D arrays, ALL(X) operates on the first -% non-singleton dimension. - -if nargin>1 - error('this implementation is only supported with one input argument'); -end - -siz = size(x); -if numel(siz)>2 - error('this implementation is only supported with vector or matrix input'); -end - -if siz(1)==1 || siz(2)==1 - y = true; - for i=1:prod(siz) - if ~x(i) - y = false; - break - end - end - -else - y = true(1,siz(2)); - for j=1:siz(2) - for i=1:siz(1) - if ~x(i,j) - y(1,j) = false; - break - end - end - end - -end - - - diff --git a/external/fileio/@uint64/any.m b/external/fileio/@uint64/any.m deleted file mode 100644 index 8569a0c..0000000 --- a/external/fileio/@uint64/any.m +++ /dev/null @@ -1,44 +0,0 @@ -function y = any(x) - -% ANY True if any element of a vector is a nonzero number or is -% logical 1 (TRUE). ANY ignores entries that are NaN (Not a Number). -% -% For vectors, ANY(V) returns logical 1 (TRUE) if any of the -% elements of the vector is a nonzero number or is logical 1 (TRUE). -% Otherwise it returns logical 0 (FALSE). For matrices, ANY(X) -% operates on the columns of X, returning a row vector of logical 1's -% and 0's. - -if nargin>1 - error('this implementation is only supported with one input argument'); -end - -siz = size(x); -if numel(siz)>2 - error('this implementation is only supported with vector or matrix input'); -end - -if siz(1)==1 || siz(2)==1 - y = false; - for i=1:prod(siz) - if x(i) - y = true; - break - end - end - -else - y = false(1,siz(2)); - for j=1:siz(2) - for i=1:siz(1) - if x(i,j) - y(1,j) = true; - break - end - end - end - -end - - - diff --git a/external/fileio/@uint64/diff.m b/external/fileio/@uint64/diff.m deleted file mode 100644 index 2746a64..0000000 --- a/external/fileio/@uint64/diff.m +++ /dev/null @@ -1,40 +0,0 @@ -function y = diff(x) - -% DIFF Difference and approximate derivative. -% DIFF(X), for a vector X, is [X(2)-X(1) X(3)-X(2) ... X(n)-X(n-1)]. -% DIFF(X), for a matrix X, is the matrix of row differences, -% [X(2:n,:) - X(1:n-1,:)]. -% DIFF(X), for an N-D array X, is the difference along the first -% non-singleton dimension of X. - -if nargin>1 - error('this implementation is only supported with one input argument'); -end - -siz = size(x); -if numel(siz)>2 - error('this implementation is only supported with vector or matrix input'); -end - -if siz(1)==1 - % derivative along the second dimension - y = x(:,1:end-1); - for i=1:(siz(2)-1) - y(:,i) = x(:,end) - y(:,i); - end - -elseif siz(2)==1 - % derivative along the first dimension - y = x(1:end-1,:); - for i=1:(siz(1)-1) - y(i,:) = x(end,:) - y(i,:); - end - -else - % derivative along the first dimension - y = x(1:end-1,:); - for i=1:(siz(1)-1) - y(i,:) = x(end,:) - y(i,:); - end -end - diff --git a/external/fileio/@uint64/max.c b/external/fileio/@uint64/max.c deleted file mode 100644 index 5e47baa..0000000 --- a/external/fileio/@uint64/max.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * - * Copyright (C) 2007, Robert Oostenveld - * - * This implements [y, i] = max(x) - * - * This function does not check the occurence of integer overflowing. - * - */ - -#include -#include "mex.h" -#include "matrix.h" - -void -mexFunction (int nlhs, mxArray * plhs[], int nrhs, const mxArray * prhs[]) -{ - size_t M, N, n; - UINT64_T *x, *m; - double *i; - - if (nlhs > 2) - mexErrMsgTxt ("Invalid number of output arguments"); - if (nrhs > 1) - mexErrMsgTxt ("Invalid number of input arguments"); - - if (!mxIsUint64(prhs[0])) - mexErrMsgTxt ("Invalid type of input arguments (should be uint64)"); - - M = mxGetM(prhs[0]); - N = mxGetN(prhs[0]); - - if (N>1 & M>1) - mexErrMsgTxt ("This works only on 1-D arrays (i.e. vectors)"); - - if (N==0 & M==0) - mexErrMsgTxt ("This works only on 1-D arrays (i.e. vectors)"); - - - plhs[0] = (mxArray*)mxCreateNumericMatrix(1, 1, mxUINT64_CLASS, mxREAL); - plhs[1] = (mxArray*)mxCreateDoubleMatrix(1, 1, mxREAL); - x = mxGetData(prhs[0]); - m = mxGetData(plhs[0]); - i = mxGetData(plhs[1]); - - n = 0; - m[0] = x[n]; - i[0] = n+1; /* offset by one */ - - for (n=1; n<(M*N); n++) - if (x[n]>m[0]) - { - m[0] = x[n]; - i[0] = n+1; /* offset by one */ - } - - return; -} - diff --git a/external/fileio/@uint64/max.m b/external/fileio/@uint64/max.m deleted file mode 100644 index f4cc216..0000000 --- a/external/fileio/@uint64/max.m +++ /dev/null @@ -1,35 +0,0 @@ -function [varargout] = funname(varargin) - -% FUNNAME compile the missing mex file on the fly - -% remember the original working directory -pwdir = pwd; - -% determine the name and full path of this function -funname = mfilename('fullpath'); -mexsrc = [funname '.c']; -[mexdir, mexname] = fileparts(funname); - -try - % try to compile the mex file on the fly - warning('trying to compile MEX file from %s', mexsrc); - cd(mexdir); - mex(mexsrc); - cd(pwdir); - success = true; - -catch - % compilation failed - disp(lasterr); - error('could not locate MEX file for %s', mexname); - cd(pwdir); - success = false; -end - -if success - % execute the mex file that was juist created - funname = mfilename; - funhandle = str2func(funname); - [varargout{1:nargout}] = funhandle(varargin{:}); -end - diff --git a/external/fileio/@uint64/max.mexa64 b/external/fileio/@uint64/max.mexa64 deleted file mode 100755 index c2c173a..0000000 Binary files a/external/fileio/@uint64/max.mexa64 and /dev/null differ diff --git a/external/fileio/@uint64/max.mexglx b/external/fileio/@uint64/max.mexglx deleted file mode 100755 index 03c1792..0000000 Binary files a/external/fileio/@uint64/max.mexglx and /dev/null differ diff --git a/external/fileio/@uint64/max.mexmaci b/external/fileio/@uint64/max.mexmaci deleted file mode 100755 index 13b2ae6..0000000 Binary files a/external/fileio/@uint64/max.mexmaci and /dev/null differ diff --git a/external/fileio/@uint64/max.mexmaci64 b/external/fileio/@uint64/max.mexmaci64 deleted file mode 100755 index 0d1fe29..0000000 Binary files a/external/fileio/@uint64/max.mexmaci64 and /dev/null differ diff --git a/external/fileio/@uint64/max.mexw32 b/external/fileio/@uint64/max.mexw32 deleted file mode 100644 index 0fccdd5..0000000 Binary files a/external/fileio/@uint64/max.mexw32 and /dev/null differ diff --git a/external/fileio/@uint64/max.mexw64 b/external/fileio/@uint64/max.mexw64 deleted file mode 100644 index b95bc2a..0000000 Binary files a/external/fileio/@uint64/max.mexw64 and /dev/null differ diff --git a/external/fileio/@uint64/min.c b/external/fileio/@uint64/min.c deleted file mode 100644 index e1033e7..0000000 --- a/external/fileio/@uint64/min.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * - * Copyright (C) 2007, Robert Oostenveld - * - * This implements [y, i] = min(x) - * - * This function does not check the occurence of integer overflowing. - * - */ - -#include -#include "mex.h" -#include "matrix.h" - -void -mexFunction (int nlhs, mxArray * plhs[], int nrhs, const mxArray * prhs[]) -{ - size_t M, N, n; - UINT64_T *x, *m; - double *i; - - if (nlhs > 2) - mexErrMsgTxt ("Invalid number of output arguments"); - if (nrhs > 1) - mexErrMsgTxt ("Invalid number of input arguments"); - - if (!mxIsUint64(prhs[0])) - mexErrMsgTxt ("Invalid type of input arguments (should be uint64)"); - - M = mxGetM(prhs[0]); - N = mxGetN(prhs[0]); - - if (N>1 & M>1) - mexErrMsgTxt ("This works only on 1-D arrays (i.e. vectors)"); - - if (N==0 & M==0) - mexErrMsgTxt ("This works only on 1-D arrays (i.e. vectors)"); - - - plhs[0] = (mxArray*)mxCreateNumericMatrix(1, 1, mxUINT64_CLASS, mxREAL); - plhs[1] = (mxArray*)mxCreateDoubleMatrix(1, 1, mxREAL); - x = mxGetData(prhs[0]); - m = mxGetData(plhs[0]); - i = mxGetData(plhs[1]); - - n = 0; - m[0] = x[n]; - i[0] = n+1; /* offset by one */ - - for (n=1; n<(M*N); n++) - if (x[n]> mex plus.c - * Error plus.c: 70 compiler error in _kids--Bad rule number 0 - * C:\PROGRA~1\MATLAB\R2007B\BIN\MEX.PL: Error: Compile of 'plus.c' failed. - * - */ - -#include -#include "mex.h" -#include "matrix.h" - -void -mexFunction (int nlhs, mxArray * plhs[], int nrhs, const mxArray * prhs[]) -{ - size_t M, N, i; - UINT64_T *a, *b, *c; - bool aScalar, bScalar; - - if (nlhs > 1) - mexErrMsgTxt ("Invalid number of output arguments"); - if (nrhs != 2) - mexErrMsgTxt ("Invalid number of input arguments"); - - if (!mxIsUint64(prhs[0])) - mexErrMsgTxt ("Invalid type of input arguments (should be uint64)"); - if (!mxIsUint64(prhs[1])) - mexErrMsgTxt ("Invalid type of input arguments (should be uint64)"); - - aScalar = ((mxGetN(prhs[0])==1) && (mxGetM(prhs[0])==1)); - bScalar = ((mxGetN(prhs[1])==1) && (mxGetM(prhs[1])==1)); - - if (!aScalar && !bScalar) - { - if (mxGetM(prhs[0]) != mxGetM(prhs[1])) - mexErrMsgTxt ("Invalid size of input arguments"); - if (mxGetN(prhs[0]) != mxGetN(prhs[1])) - mexErrMsgTxt ("Invalid size of input arguments"); - } - - if (aScalar) - { - M = mxGetM(prhs[1]); - N = mxGetN(prhs[1]); - } - else - { - M = mxGetM(prhs[0]); - N = mxGetN(prhs[0]); - } - - a = mxGetData(prhs[0]); - b = mxGetData(prhs[1]); - - plhs[0] = (mxArray*)mxCreateNumericMatrix(M, N, mxUINT64_CLASS, mxREAL); - c = mxGetData(plhs[0]); - - if (aScalar) - { - for (i=0; i<(M*N); i++) - c[i] = a[0]-b[i]; - } - else if (bScalar) - { - for (i=0; i<(M*N); i++) - c[i] = a[i]-b[0]; - } - else - { - for (i=0; i<(M*N); i++) - c[i] = a[i]-b[i]; - } - - return; -} - diff --git a/external/fileio/@uint64/minus.m b/external/fileio/@uint64/minus.m deleted file mode 100644 index f4cc216..0000000 --- a/external/fileio/@uint64/minus.m +++ /dev/null @@ -1,35 +0,0 @@ -function [varargout] = funname(varargin) - -% FUNNAME compile the missing mex file on the fly - -% remember the original working directory -pwdir = pwd; - -% determine the name and full path of this function -funname = mfilename('fullpath'); -mexsrc = [funname '.c']; -[mexdir, mexname] = fileparts(funname); - -try - % try to compile the mex file on the fly - warning('trying to compile MEX file from %s', mexsrc); - cd(mexdir); - mex(mexsrc); - cd(pwdir); - success = true; - -catch - % compilation failed - disp(lasterr); - error('could not locate MEX file for %s', mexname); - cd(pwdir); - success = false; -end - -if success - % execute the mex file that was juist created - funname = mfilename; - funhandle = str2func(funname); - [varargout{1:nargout}] = funhandle(varargin{:}); -end - diff --git a/external/fileio/@uint64/minus.mexa64 b/external/fileio/@uint64/minus.mexa64 deleted file mode 100755 index 9136535..0000000 Binary files a/external/fileio/@uint64/minus.mexa64 and /dev/null differ diff --git a/external/fileio/@uint64/minus.mexglx b/external/fileio/@uint64/minus.mexglx deleted file mode 100755 index 26d6843..0000000 Binary files a/external/fileio/@uint64/minus.mexglx and /dev/null differ diff --git a/external/fileio/@uint64/minus.mexmaci b/external/fileio/@uint64/minus.mexmaci deleted file mode 100755 index 03b1f08..0000000 Binary files a/external/fileio/@uint64/minus.mexmaci and /dev/null differ diff --git a/external/fileio/@uint64/minus.mexmaci64 b/external/fileio/@uint64/minus.mexmaci64 deleted file mode 100755 index 355c484..0000000 Binary files a/external/fileio/@uint64/minus.mexmaci64 and /dev/null differ diff --git a/external/fileio/@uint64/minus.mexw32 b/external/fileio/@uint64/minus.mexw32 deleted file mode 100644 index f9bc9af..0000000 Binary files a/external/fileio/@uint64/minus.mexw32 and /dev/null differ diff --git a/external/fileio/@uint64/minus.mexw64 b/external/fileio/@uint64/minus.mexw64 deleted file mode 100644 index 87a7570..0000000 Binary files a/external/fileio/@uint64/minus.mexw64 and /dev/null differ diff --git a/external/fileio/@uint64/plus.c b/external/fileio/@uint64/plus.c deleted file mode 100644 index 3554ac8..0000000 --- a/external/fileio/@uint64/plus.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * - * Copyright (C) 2006-2007, Robert Oostenveld - * - * This implements C = A + B for uint64 data types - * and either A and B have the same size or one of them is scalar. - * - * This function does not check the occurence of integer overflowing. - * - * Note that UINT64_T is used here because the Borland C++ compiler (free version 5.5) does not - * understand "unsigned long long", and the gcc compiler does not understand "unsigned __int64". - * Matlab solves that with UINT64_T - * - * Regardless of the declaration of UINT64_T variables I did not manage to compile this code using - * the LCC 2.4.1 compiler, which gives the following error - * >> mex plus.c - * Error plus.c: 70 compiler error in _kids--Bad rule number 0 - * C:\PROGRA~1\MATLAB\R2007B\BIN\MEX.PL: Error: Compile of 'plus.c' failed. - * - */ - -#include -#include "mex.h" -#include "matrix.h" - -void -mexFunction (int nlhs, mxArray * plhs[], int nrhs, const mxArray * prhs[]) -{ - size_t M, N, i; - UINT64_T *a, *b, *c; - bool aScalar, bScalar; - - if (nlhs > 1) - mexErrMsgTxt ("Invalid number of output arguments"); - if (nrhs != 2) - mexErrMsgTxt ("Invalid number of input arguments"); - - if (!mxIsUint64(prhs[0])) - mexErrMsgTxt ("Invalid type of input arguments (should be uint64)"); - if (!mxIsUint64(prhs[1])) - mexErrMsgTxt ("Invalid type of input arguments (should be uint64)"); - - aScalar = ((mxGetN(prhs[0])==1) && (mxGetM(prhs[0])==1)); - bScalar = ((mxGetN(prhs[1])==1) && (mxGetM(prhs[1])==1)); - - if (!aScalar && !bScalar) - { - if (mxGetM(prhs[0]) != mxGetM(prhs[1])) - mexErrMsgTxt ("Invalid size of input arguments"); - if (mxGetN(prhs[0]) != mxGetN(prhs[1])) - mexErrMsgTxt ("Invalid size of input arguments"); - } - - if (aScalar) - { - M = mxGetM(prhs[1]); - N = mxGetN(prhs[1]); - } - else - { - M = mxGetM(prhs[0]); - N = mxGetN(prhs[0]); - } - - a = mxGetData(prhs[0]); - b = mxGetData(prhs[1]); - - plhs[0] = (mxArray*)mxCreateNumericMatrix(M, N, mxUINT64_CLASS, mxREAL); - c = mxGetData(plhs[0]); - - if (aScalar) - { - for (i=0; i<(M*N); i++) - c[i] = a[0]+b[i]; - } - else if (bScalar) - { - for (i=0; i<(M*N); i++) - c[i] = a[i]+b[0]; - } - else - { - for (i=0; i<(M*N); i++) - c[i] = a[i]+b[i]; - } - - return; -} - diff --git a/external/fileio/@uint64/plus.m b/external/fileio/@uint64/plus.m deleted file mode 100644 index f4cc216..0000000 --- a/external/fileio/@uint64/plus.m +++ /dev/null @@ -1,35 +0,0 @@ -function [varargout] = funname(varargin) - -% FUNNAME compile the missing mex file on the fly - -% remember the original working directory -pwdir = pwd; - -% determine the name and full path of this function -funname = mfilename('fullpath'); -mexsrc = [funname '.c']; -[mexdir, mexname] = fileparts(funname); - -try - % try to compile the mex file on the fly - warning('trying to compile MEX file from %s', mexsrc); - cd(mexdir); - mex(mexsrc); - cd(pwdir); - success = true; - -catch - % compilation failed - disp(lasterr); - error('could not locate MEX file for %s', mexname); - cd(pwdir); - success = false; -end - -if success - % execute the mex file that was juist created - funname = mfilename; - funhandle = str2func(funname); - [varargout{1:nargout}] = funhandle(varargin{:}); -end - diff --git a/external/fileio/@uint64/plus.mexa64 b/external/fileio/@uint64/plus.mexa64 deleted file mode 100755 index bf2267c..0000000 Binary files a/external/fileio/@uint64/plus.mexa64 and /dev/null differ diff --git a/external/fileio/@uint64/plus.mexglx b/external/fileio/@uint64/plus.mexglx deleted file mode 100755 index 643adba..0000000 Binary files a/external/fileio/@uint64/plus.mexglx and /dev/null differ diff --git a/external/fileio/@uint64/plus.mexmaci b/external/fileio/@uint64/plus.mexmaci deleted file mode 100755 index 9052272..0000000 Binary files a/external/fileio/@uint64/plus.mexmaci and /dev/null differ diff --git a/external/fileio/@uint64/plus.mexmaci64 b/external/fileio/@uint64/plus.mexmaci64 deleted file mode 100755 index 6423e35..0000000 Binary files a/external/fileio/@uint64/plus.mexmaci64 and /dev/null differ diff --git a/external/fileio/@uint64/plus.mexw32 b/external/fileio/@uint64/plus.mexw32 deleted file mode 100644 index ab3dcfd..0000000 Binary files a/external/fileio/@uint64/plus.mexw32 and /dev/null differ diff --git a/external/fileio/@uint64/plus.mexw64 b/external/fileio/@uint64/plus.mexw64 deleted file mode 100644 index 64e73a6..0000000 Binary files a/external/fileio/@uint64/plus.mexw64 and /dev/null differ diff --git a/external/fileio/@uint64/rdivide.c b/external/fileio/@uint64/rdivide.c deleted file mode 100644 index dc6a896..0000000 --- a/external/fileio/@uint64/rdivide.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * - * Copyright (C) 2006-2007, Robert Oostenveld - * - * This implements C = A / B for uint64 data types - * and either A and B have the same size or one of them is scalar. - * - * This function does not check the occurence of integer overflowing. - * - */ - -#include "mex.h" -#include "matrix.h" -#include - -#if defined(_WIN32) || defined(_WIN64) -#include -#else -#include -#endif - -#ifndef UINT64_MAX -#define UINT64_MAX _UI64_MAX -#endif - -void -mexFunction (int nlhs, mxArray * plhs[], int nrhs, const mxArray * prhs[]) -{ - size_t M, N, i; - UINT64_T *a, *b, *c; - bool aScalar, bScalar; - - if (nlhs > 1) - mexErrMsgTxt ("Invalid number of output arguments"); - if (nrhs != 2) - mexErrMsgTxt ("Invalid number of input arguments"); - - if (!mxIsUint64(prhs[0])) - mexErrMsgTxt ("Invalid type of input arguments (should be uint64)"); - if (!mxIsUint64(prhs[1])) - mexErrMsgTxt ("Invalid type of input arguments (should be uint64)"); - - aScalar = ((mxGetN(prhs[0])==1) && (mxGetM(prhs[0])==1)); - bScalar = ((mxGetN(prhs[1])==1) && (mxGetM(prhs[1])==1)); - - if (!aScalar && !bScalar) - { - if (mxGetM(prhs[0]) != mxGetM(prhs[1])) - mexErrMsgTxt ("Invalid size of input arguments"); - if (mxGetN(prhs[0]) != mxGetN(prhs[1])) - mexErrMsgTxt ("Invalid size of input arguments"); - } - - if (aScalar) - { - M = mxGetM(prhs[1]); - N = mxGetN(prhs[1]); - } - else - { - M = mxGetM(prhs[0]); - N = mxGetN(prhs[0]); - } - - a = mxGetData(prhs[0]); - b = mxGetData(prhs[1]); - - plhs[0] = (mxArray*)mxCreateNumericMatrix(M, N, mxUINT64_CLASS, mxREAL); - c = mxGetData(plhs[0]); - - if (aScalar) - { - for (i=0; i<(M*N); i++) - if (b[i]==0) - { - mexWarnMsgTxt("Divide by zero."); - c[i] = UINT64_MAX; - } - else - c[i] = a[0]/b[i]; - } - else if (bScalar) - { - for (i=0; i<(M*N); i++) - if (b[0]==0) - { - mexWarnMsgTxt("Divide by zero."); - c[i] = UINT64_MAX; - } - else - c[i] = a[i]/b[0]; - } - else - { - for (i=0; i<(M*N); i++) - if (b[i]==0) - { - mexWarnMsgTxt("Divide by zero."); - c[i] = UINT64_MAX; - } - else - c[i] = a[i]/b[i]; - } - - return; -} - diff --git a/external/fileio/@uint64/rdivide.m b/external/fileio/@uint64/rdivide.m deleted file mode 100644 index f4cc216..0000000 --- a/external/fileio/@uint64/rdivide.m +++ /dev/null @@ -1,35 +0,0 @@ -function [varargout] = funname(varargin) - -% FUNNAME compile the missing mex file on the fly - -% remember the original working directory -pwdir = pwd; - -% determine the name and full path of this function -funname = mfilename('fullpath'); -mexsrc = [funname '.c']; -[mexdir, mexname] = fileparts(funname); - -try - % try to compile the mex file on the fly - warning('trying to compile MEX file from %s', mexsrc); - cd(mexdir); - mex(mexsrc); - cd(pwdir); - success = true; - -catch - % compilation failed - disp(lasterr); - error('could not locate MEX file for %s', mexname); - cd(pwdir); - success = false; -end - -if success - % execute the mex file that was juist created - funname = mfilename; - funhandle = str2func(funname); - [varargout{1:nargout}] = funhandle(varargin{:}); -end - diff --git a/external/fileio/@uint64/rdivide.mexa64 b/external/fileio/@uint64/rdivide.mexa64 deleted file mode 100755 index 1eb2a9b..0000000 Binary files a/external/fileio/@uint64/rdivide.mexa64 and /dev/null differ diff --git a/external/fileio/@uint64/rdivide.mexglx b/external/fileio/@uint64/rdivide.mexglx deleted file mode 100755 index ca07680..0000000 Binary files a/external/fileio/@uint64/rdivide.mexglx and /dev/null differ diff --git a/external/fileio/@uint64/rdivide.mexmaci b/external/fileio/@uint64/rdivide.mexmaci deleted file mode 100755 index 2c612e0..0000000 Binary files a/external/fileio/@uint64/rdivide.mexmaci and /dev/null differ diff --git a/external/fileio/@uint64/rdivide.mexmaci64 b/external/fileio/@uint64/rdivide.mexmaci64 deleted file mode 100755 index 35b26b6..0000000 Binary files a/external/fileio/@uint64/rdivide.mexmaci64 and /dev/null differ diff --git a/external/fileio/@uint64/rdivide.mexw32 b/external/fileio/@uint64/rdivide.mexw32 deleted file mode 100644 index 541b111..0000000 Binary files a/external/fileio/@uint64/rdivide.mexw32 and /dev/null differ diff --git a/external/fileio/@uint64/rdivide.mexw64 b/external/fileio/@uint64/rdivide.mexw64 deleted file mode 100644 index 3c80f38..0000000 Binary files a/external/fileio/@uint64/rdivide.mexw64 and /dev/null differ diff --git a/external/fileio/@uint64/times.c b/external/fileio/@uint64/times.c deleted file mode 100644 index 5ab6aa0..0000000 --- a/external/fileio/@uint64/times.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * - * Copyright (C) 2006-2007, Robert Oostenveld - * - * This implements C = A * B for uint64 data types - * and either A and B have the same size or one of them is scalar. - * - * This function does not check the occurence of integer overflowing. - * - */ - -#include -#include "mex.h" -#include "matrix.h" - -void -mexFunction (int nlhs, mxArray * plhs[], int nrhs, const mxArray * prhs[]) -{ - size_t M, N, i; - UINT64_T *a, *b, *c; - bool aScalar, bScalar; - - if (nlhs > 1) - mexErrMsgTxt ("Invalid number of output arguments"); - if (nrhs != 2) - mexErrMsgTxt ("Invalid number of input arguments"); - - if (!mxIsUint64(prhs[0])) - mexErrMsgTxt ("Invalid type of input arguments (should be uint64)"); - if (!mxIsUint64(prhs[1])) - mexErrMsgTxt ("Invalid type of input arguments (should be uint64)"); - - aScalar = ((mxGetN(prhs[0])==1) && (mxGetM(prhs[0])==1)); - bScalar = ((mxGetN(prhs[1])==1) && (mxGetM(prhs[1])==1)); - - if (!aScalar && !bScalar) - { - if (mxGetM(prhs[0]) != mxGetM(prhs[1])) - mexErrMsgTxt ("Invalid size of input arguments"); - if (mxGetN(prhs[0]) != mxGetN(prhs[1])) - mexErrMsgTxt ("Invalid size of input arguments"); - } - - if (aScalar) - { - M = mxGetM(prhs[1]); - N = mxGetN(prhs[1]); - } - else - { - M = mxGetM(prhs[0]); - N = mxGetN(prhs[0]); - } - - a = mxGetData(prhs[0]); - b = mxGetData(prhs[1]); - - plhs[0] = (mxArray*)mxCreateNumericMatrix(M, N, mxUINT64_CLASS, mxREAL); - c = mxGetData(plhs[0]); - - if (aScalar) - { - for (i=0; i<(M*N); i++) - c[i] = a[0]*b[i]; - } - else if (bScalar) - { - for (i=0; i<(M*N); i++) - c[i] = a[i]*b[0]; - } - else - { - for (i=0; i<(M*N); i++) - c[i] = a[i]*b[i]; - } - - return; -} - diff --git a/external/fileio/@uint64/times.m b/external/fileio/@uint64/times.m deleted file mode 100644 index f4cc216..0000000 --- a/external/fileio/@uint64/times.m +++ /dev/null @@ -1,35 +0,0 @@ -function [varargout] = funname(varargin) - -% FUNNAME compile the missing mex file on the fly - -% remember the original working directory -pwdir = pwd; - -% determine the name and full path of this function -funname = mfilename('fullpath'); -mexsrc = [funname '.c']; -[mexdir, mexname] = fileparts(funname); - -try - % try to compile the mex file on the fly - warning('trying to compile MEX file from %s', mexsrc); - cd(mexdir); - mex(mexsrc); - cd(pwdir); - success = true; - -catch - % compilation failed - disp(lasterr); - error('could not locate MEX file for %s', mexname); - cd(pwdir); - success = false; -end - -if success - % execute the mex file that was juist created - funname = mfilename; - funhandle = str2func(funname); - [varargout{1:nargout}] = funhandle(varargin{:}); -end - diff --git a/external/fileio/@uint64/times.mexa64 b/external/fileio/@uint64/times.mexa64 deleted file mode 100755 index 3ddbe7d..0000000 Binary files a/external/fileio/@uint64/times.mexa64 and /dev/null differ diff --git a/external/fileio/@uint64/times.mexglx b/external/fileio/@uint64/times.mexglx deleted file mode 100755 index ed48f66..0000000 Binary files a/external/fileio/@uint64/times.mexglx and /dev/null differ diff --git a/external/fileio/@uint64/times.mexmaci b/external/fileio/@uint64/times.mexmaci deleted file mode 100755 index fa0ac2d..0000000 Binary files a/external/fileio/@uint64/times.mexmaci and /dev/null differ diff --git a/external/fileio/@uint64/times.mexmaci64 b/external/fileio/@uint64/times.mexmaci64 deleted file mode 100755 index d0fd655..0000000 Binary files a/external/fileio/@uint64/times.mexmaci64 and /dev/null differ diff --git a/external/fileio/@uint64/times.mexw32 b/external/fileio/@uint64/times.mexw32 deleted file mode 100644 index 9fe7ea5..0000000 Binary files a/external/fileio/@uint64/times.mexw32 and /dev/null differ diff --git a/external/fileio/@uint64/times.mexw64 b/external/fileio/@uint64/times.mexw64 deleted file mode 100644 index 26046e0..0000000 Binary files a/external/fileio/@uint64/times.mexw64 and /dev/null differ diff --git a/external/fileio/README b/external/fileio/README deleted file mode 100644 index 56bf553..0000000 --- a/external/fileio/README +++ /dev/null @@ -1,24 +0,0 @@ -This is a special release of the FieldTrip FILEIO module for inclusion -in SPM8. It contains functions for reading EEG and MEG data from a -large variety of files. Furthermore, additional information such -as sensor positions can be read from file. - -This particular release has wrapper functions that adhere to the -spm_xxx function naming style. The public functions are available -as ft_xxx, whereas all dependencies are hidden in the private -directory. If you are interested in using this toolbox independent -of SPM8, I suggest that you visit http://www.ru.nl/fcdonders/fieldtrip -and download a normal and more complete version. - -For more information please visit http://www.ru.nl/fcdonders/fieldtrip -and http://www.fil.ion.ucl.ac.uk/spm. - -The FieldTrip software is free but copyrighted software, distributed -under the terms of the GNU General Public Licence as published by -the Free Software Foundation (either version 2, or at your option -any later version). See the file COPYING for more details. - -Copyright (C) 1999-2003, Department of Medical Physics, Radboud University Nijmegen, The Netherlands -Copyright (C) 2003-2005, Center for Sensory-Motor Interaction, Aalborg University, Denmark -Copyright (C) 2003-2008, F.C. Donders Centre for Cognitive Neuroimaging, Nijmegen, The Netherlands - diff --git a/external/fileio/fileio_chantype.m b/external/fileio/fileio_chantype.m deleted file mode 100644 index 37077be..0000000 --- a/external/fileio/fileio_chantype.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'fileio_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fileio/fileio_filetype.m b/external/fileio/fileio_filetype.m deleted file mode 100644 index 37077be..0000000 --- a/external/fileio/fileio_filetype.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'fileio_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fileio/fileio_read_data.m b/external/fileio/fileio_read_data.m deleted file mode 100644 index 37077be..0000000 --- a/external/fileio/fileio_read_data.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'fileio_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fileio/fileio_read_event.m b/external/fileio/fileio_read_event.m deleted file mode 100644 index 37077be..0000000 --- a/external/fileio/fileio_read_event.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'fileio_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fileio/fileio_read_header.m b/external/fileio/fileio_read_header.m deleted file mode 100644 index 37077be..0000000 --- a/external/fileio/fileio_read_header.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'fileio_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fileio/fileio_read_headshape.m b/external/fileio/fileio_read_headshape.m deleted file mode 100644 index 37077be..0000000 --- a/external/fileio/fileio_read_headshape.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'fileio_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fileio/fileio_read_mri.m b/external/fileio/fileio_read_mri.m deleted file mode 100644 index 37077be..0000000 --- a/external/fileio/fileio_read_mri.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'fileio_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fileio/fileio_read_sens.m b/external/fileio/fileio_read_sens.m deleted file mode 100644 index 37077be..0000000 --- a/external/fileio/fileio_read_sens.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'fileio_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fileio/fileio_read_vol.m b/external/fileio/fileio_read_vol.m deleted file mode 100644 index 37077be..0000000 --- a/external/fileio/fileio_read_vol.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'fileio_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/fileio/private/ama2vol.m b/external/fileio/private/ama2vol.m deleted file mode 100644 index c7e155d..0000000 --- a/external/fileio/private/ama2vol.m +++ /dev/null @@ -1,38 +0,0 @@ -function [vol] = ama2vol(ama) - -% AMA2VOL -% -% Use as -% vol = ama2vol(ama) - -% Copyright (C) 2008, Robert Oostenveld -% -% $Log: ama2vol.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.1 2008/01/28 19:56:13 roboos -% moved code from subfunction in prepare_bemmodel and prepare_vol_sens into seperate function -% renamed from convert_ama2vol -% - -vol = []; -ngeo = length(ama.geo); -for i=1:ngeo - vol.bnd(i).pnt = ama.geo(i).pnt; - vol.bnd(i).tri = ama.geo(i).dhk; - vol.cond(i) = ama.geo(i).sigmam; -end -vol.mat = ama.bi; -npnt = size(vol.mat,2); -if size(vol.mat,1) - - -% Comments -% The header format is flexible and can be extended for new -% user-defined data types. The essential structures of the header -% are the header_key and the image_dimension. -% - -% The required elements in the header_key substructure are: -% -% int sizeof_header Must indicate the byte size of the header file. -% int extents Should be 16384, the image file is created as -% contiguous with a minimum extent size. -% char regular Must be 'r' to indicate that all images and -% volumes are the same size. -% - -% The image_dimension substructure describes the organization and -% size of the images. These elements enable the database to reference -% images by volume and slice number. Explanation of each element follows: -% -% short int dim[ ]; /* Array of the image dimensions */ -% -% dim[0] Number of dimensions in database; usually 4. -% dim[1] Image X dimension; number of pixels in an image row. -% dim[2] Image Y dimension; number of pixel rows in slice. -% dim[3] Volume Z dimension; number of slices in a volume. -% dim[4] Time points; number of volumes in database. -% dim[5] Undocumented. -% dim[6] Undocumented. -% dim[7] Undocumented. -% -% char vox_units[4] Specifies the spatial units of measure for a voxel. -% char cal_units[8] Specifies the name of the calibration unit. -% short int unused1 /* Unused */ -% short int datatype /* Datatype for this image set */ -% /*Acceptable values for datatype are*/ -% #define DT_NONE 0 -% #define DT_UNKNOWN 0 /*Unknown data type*/ -% #define DT_BINARY 1 /*Binary ( 1 bit per voxel)*/ -% #define DT_UNSIGNED_CHAR 2 /*Unsigned character ( 8 bits per voxel)*/ -% #define DT_SIGNED_SHORT 4 /*Signed short (16 bits per voxel)*/ -% #define DT_SIGNED_INT 8 /*Signed integer (32 bits per voxel)*/ -% #define DT_FLOAT 16 /*Floating point (32 bits per voxel)*/ -% #define DT_COMPLEX 32 /*Complex (64 bits per voxel; 2 floating point numbers)/* -% #define DT_DOUBLE 64 /*Double precision (64 bits per voxel)*/ -% #define DT_RGB 128 /*A Red-Green-Blue datatype*/ -% #define DT_ALL 255 /*Undocumented*/ -% -% short int bitpix; /* Number of bits per pixel; 1, 8, 16, 32, or 64. */ -% short int dim_un0; /* Unused */ -% -% float pixdim[]; Parallel array to dim[], giving real world measurements in mm and ms. -% pixdim[0]; Pixel dimensions? -% pixdim[1]; Voxel width in mm. -% pixdim[2]; Voxel height in mm. -% pixdim[3]; Slice thickness in mm. -% pixdim[4]; timeslice in ms (ie, TR in fMRI). -% pixdim[5]; Undocumented. -% pixdim[6]; Undocumented. -% pixdim[7]; Undocumented. -% -% float vox_offset; Byte offset in the .img file at which voxels start. This value can be -% negative to specify that the absolute value is applied for every image -% in the file. -% -% float roi_scale; Specifies the Region Of Interest scale? -% float funused1; Undocumented. -% float funused2; Undocumented. -% -% float cal_max; Specifies the upper bound of the range of calibration values. -% float cal_min; Specifies the lower bound of the range of calibration values. -% -% int compressed; Undocumented. -% int verified; Undocumented. -% -% int glmax; The maximum pixel value for the entire database. -% int glmin; The minimum pixel value for the entire database. -% -% diff --git a/external/fileio/private/avw_hdr_write.m b/external/fileio/private/avw_hdr_write.m deleted file mode 100644 index 2e36ae1..0000000 --- a/external/fileio/private/avw_hdr_write.m +++ /dev/null @@ -1,427 +0,0 @@ -function avw_hdr_write(avw, fileprefix, machine, verbose) - -% AVW_HDR_WRITE - Write Analyze header file (*.hdr) -% -% avw_hdr_write(avw,[fileprefix],[machine],[verbose]) -% -% eg, avw_hdr_write(avw,'test'); -% -% avw - a struct with .hdr field, which itself is a struct, -% containing all fields of an Analyze header. -% For details, see avw_hdr_read.m -% -% fileprefix - a string, the filename without the .hdr extension. -% If empty, may use avw.fileprefix -% -% machine - a string, see machineformat in fread for details. -% The default here is 'ieee-le'. -% -% verbose - the default is to output processing information to the command -% window. If verbose = 0, this will not happen. -% -% See also, AVW_HDR_READ AVW_HDR_MAKE -% AVW_IMG_READ AVW_IMG_WRITE -% - -% $Revision: 1.1 $ $Date: 2009/01/14 09:24:45 $ - -% Licence: GNU GPL, no express or implied warranties -% History: 05/2002, Darren.Weber@flinders.edu.au -% 02/2003, Bennett.Landman@ieee.org -% - more specific data history var sizes -% - 02/2003 confirmed, Darren -% -% The Analyze format and c code below is copyright -% (c) Copyright, 1986-1995 -% Biomedical Imaging Resource, Mayo Foundation -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -if ~exist('verbose','var'), verbose = 1; end -if ~exist('machine','var'), machine = 'ieee-le'; end - -if verbose, - version = '[$Revision: 1.1 $]'; - fprintf('AVW_HDR_WRITE [v%s]\n',version(12:16)); tic; -end - -%---------------------------------------------------------------------------- -% Check inputs - -if ~exist('avw','var'), - warning('...no input avw - calling avw_hdr_make\n'); - avw = avw_hdr_make; -elseif isempty(avw), - warning('...empty input avw - calling avw_hdr_make\n'); - avw = avw_hdr_make; -elseif ~isfield(avw,'hdr'), - warning('...empty input avw.hdr - calling avw_hdr_make\n'); - avw = avw_hdr_make; -end -if ~isequal(avw.hdr.hk.sizeof_hdr,348), - msg = sprintf('...avw.hdr.hk.sizeof_hdr must be 348!\n'); - error(msg); -end - -quit = 0; -if ~exist('fileprefix','var'), - if isfield(avw,'fileprefix'), - if ~isempty(avw.fileprefix), - fileprefix = avw.fileprefix; - else, - quit = 1; - end - else - quit = 1; - end - if quit, - helpwin avw_hdr_write; - error('...no input fileprefix - see help avw_hdr_write\n\n'); - return; - end -end - -if findstr('.hdr',fileprefix), -% fprintf('AVW_HDR_WRITE: Removing .hdr extension from ''%s''\n',fileprefix); - fileprefix = strrep(fileprefix,'.hdr',''); -end - - - -%---------------------------------------------------------------------------- -% MAIN - -if verbose, tic; end - - -% % force volume to 4D if necessary; conforms to AVW standard. i lifted this -% % code from mri_toolbox/avw_hdr_read.m and modified it just a little bit -% % (using minDim = 4; etc) -% minDim = 4; -% currDim = double(avw.hdr.dime.dim(1)); -% if ( currDim < minDim ) -% % fprintf( 'Warning %s: Forcing %d dimensions in avw.hdr.dime.dim\n', ... -% % mfilename, minDim ); -% avw.hdr.dime.dim(1) = int16(minDim); -% avw.hdr.dime.dim(currDim+2:minDim+1) = int16(1); -% avw.hdr.dime.pixdim(1) = int16(minDim); -% avw.hdr.dime.pixdim(currDim+2:minDim+1) = int16(1); -% end; - - -fid = fopen(sprintf('%s.hdr',fileprefix),'w',machine); -if fid < 0, - msg = sprintf('Cannot write to file %s.hdr\n',fileprefix); - error(msg); -else - if verbose, fprintf('...writing %s Analyze header.\n',machine); end - write_header(fid,avw,verbose); -end - -if verbose, t=toc; fprintf('...done (%5.2f sec).\n\n',t); end - -return - - - - - -%---------------------------------------------------------------------------- - -function write_header(fid,avw,verbose) - - header_key(fid,avw.hdr.hk); - image_dimension(fid,avw.hdr.dime); - data_history(fid,avw.hdr.hist); - - % check the file size is 348 bytes - fbytes = ftell(fid); - fclose(fid); - if ~isequal(fbytes,348), - msg = sprintf('...file size is not 348 bytes!\n'); - warning(msg); - end - -return - -%---------------------------------------------------------------------------- - -function header_key(fid,hk) - - % Original header structures - ANALYZE 7.5 - % struct header_key /* header key */ - % { /* off + size */ - % int sizeof_hdr /* 0 + 4 */ - % char data_type[10]; /* 4 + 10 */ - % char db_name[18]; /* 14 + 18 */ - % int extents; /* 32 + 4 */ - % short int session_error; /* 36 + 2 */ - % char regular; /* 38 + 1 */ - % char hkey_un0; /* 39 + 1 */ - % }; /* total=40 bytes */ - - fseek(fid,0,'bof'); - - fwrite(fid, hk.sizeof_hdr(1), 'int32'); % must be 348! - - data_type = sprintf('%-10s',hk.data_type); % ensure it is 10 chars - fwrite(fid, hk.data_type(1:10), 'uchar'); - - db_name = sprintf('%-18s',hk.db_name); % ensure it is 18 chars - fwrite(fid, db_name(1:18), 'uchar'); - - fwrite(fid, hk.extents(1), 'int32'); - fwrite(fid, hk.session_error(1),'int16'); - - regular = sprintf('%1s',hk.regular); % ensure it is 1 char - fwrite(fid, regular(1), 'uchar'); % might be uint8 - - %hkey_un0 = sprintf('%1s',hk.hkey_un0); % ensure it is 1 char - %fwrite(fid, hkey_un0(1), 'uchar'); - fwrite(fid, hk.hkey_un0(1), 'uint8'); - - % >Would you set hkey_un0 as char or uint8? - % Really doesn't make any difference. As far as anyone here can remember, - % this was just to pad to an even byte boundary for that structure. I guess - % I'd suggest setting it to a uint8 value of 0 (i.e, truly zero-valued) so - % that it doesn't look like anything important! - % Denny - -return - -%---------------------------------------------------------------------------- - -function image_dimension(fid,dime) - - %struct image_dimension - % { /* off + size */ - % short int dim[8]; /* 0 + 16 */ - % char vox_units[4]; /* 16 + 4 */ - % char cal_units[8]; /* 20 + 8 */ - % short int unused1; /* 28 + 2 */ - % short int datatype; /* 30 + 2 */ - % short int bitpix; /* 32 + 2 */ - % short int dim_un0; /* 34 + 2 */ - % float pixdim[8]; /* 36 + 32 */ - % /* - % pixdim[] specifies the voxel dimensions: - % pixdim[1] - voxel width - % pixdim[2] - voxel height - % pixdim[3] - interslice distance - % ..etc - % */ - % float vox_offset; /* 68 + 4 */ - % float roi_scale; /* 72 + 4 */ - % float funused1; /* 76 + 4 */ - % float funused2; /* 80 + 4 */ - % float cal_max; /* 84 + 4 */ - % float cal_min; /* 88 + 4 */ - % int compressed; /* 92 + 4 */ - % int verified; /* 96 + 4 */ - % int glmax; /* 100 + 4 */ - % int glmin; /* 104 + 4 */ - % }; /* total=108 bytes */ - - fwrite(fid, dime.dim(1:8), 'int16'); - fwrite(fid, dime.vox_units(1:4),'uchar'); - fwrite(fid, dime.cal_units(1:8),'uchar'); - fwrite(fid, dime.unused1(1), 'int16'); - fwrite(fid, dime.datatype(1), 'int16'); - fwrite(fid, dime.bitpix(1), 'int16'); - fwrite(fid, dime.dim_un0(1), 'int16'); - fwrite(fid, dime.pixdim(1:8), 'float32'); - fwrite(fid, dime.vox_offset(1), 'float32'); - - % Ensure compatibility with SPM (according to MRIcro) - if dime.roi_scale == 0, dime.roi_scale = 0.00392157; end - fwrite(fid, dime.roi_scale(1), 'float32'); - - fwrite(fid, dime.funused1(1), 'float32'); - fwrite(fid, dime.funused2(1), 'float32'); - fwrite(fid, dime.cal_max(1), 'float32'); - fwrite(fid, dime.cal_min(1), 'float32'); - fwrite(fid, dime.compressed(1), 'int32'); - fwrite(fid, dime.verified(1), 'int32'); - fwrite(fid, dime.glmax(1), 'int32'); - fwrite(fid, dime.glmin(1), 'int32'); - -return - -%---------------------------------------------------------------------------- - -function data_history(fid,hist) - - % Original header structures - ANALYZE 7.5 - %struct data_history - % { /* off + size */ - % char descrip[80]; /* 0 + 80 */ - % char aux_file[24]; /* 80 + 24 */ - % char orient; /* 104 + 1 */ - % char originator[10]; /* 105 + 10 */ - % char generated[10]; /* 115 + 10 */ - % char scannum[10]; /* 125 + 10 */ - % char patient_id[10]; /* 135 + 10 */ - % char exp_date[10]; /* 145 + 10 */ - % char exp_time[10]; /* 155 + 10 */ - % char hist_un0[3]; /* 165 + 3 */ - % int views /* 168 + 4 */ - % int vols_added; /* 172 + 4 */ - % int start_field; /* 176 + 4 */ - % int field_skip; /* 180 + 4 */ - % int omax; /* 184 + 4 */ - % int omin; /* 188 + 4 */ - % int smax; /* 192 + 4 */ - % int smin; /* 196 + 4 */ - % }; /* total=200 bytes */ - - descrip = sprintf('%-80s', hist.descrip); % 80 chars - aux_file = sprintf('%-24s', hist.aux_file); % 24 chars - originator = sprintf('%-10s', hist.originator); % 10 chars - generated = sprintf('%-10s', hist.generated); % 10 chars - scannum = sprintf('%-10s', hist.scannum); % 10 chars - patient_id = sprintf('%-10s', hist.patient_id); % 10 chars - exp_date = sprintf('%-10s', hist.exp_date); % 10 chars - exp_time = sprintf('%-10s', hist.exp_time); % 10 chars - hist_un0 = sprintf( '%-3s', hist.hist_un0); % 3 chars - - % --- - % The following should not be necessary, but I actually - % found one instance where it was, so this totally anal - % retentive approach became necessary, despite the - % apparently elegant solution above to ensuring that variables - % are the right length. - - if length(descrip) < 80, - paddingN = 80-length(descrip); - padding = char(repmat(double(' '),1,paddingN)); - descrip = [descrip,padding]; - end - if length(aux_file) < 24, - paddingN = 24-length(aux_file); - padding = char(repmat(double(' '),1,paddingN)); - aux_file = [aux_file,padding]; - end - if length(originator) < 10, - paddingN = 10-length(originator); - padding = char(repmat(double(' '),1,paddingN)); - originator = [originator, padding]; - end - if length(generated) < 10, - paddingN = 10-length(generated); - padding = char(repmat(double(' '),1,paddingN)); - generated = [generated, padding]; - end - if length(scannum) < 10, - paddingN = 10-length(scannum); - padding = char(repmat(double(' '),1,paddingN)); - scannum = [scannum, padding]; - end - if length(patient_id) < 10, - paddingN = 10-length(patient_id); - padding = char(repmat(double(' '),1,paddingN)); - patient_id = [patient_id, padding]; - end - if length(exp_date) < 10, - paddingN = 10-length(exp_date); - padding = char(repmat(double(' '),1,paddingN)); - exp_date = [exp_date, padding]; - end - if length(exp_time) < 10, - paddingN = 10-length(exp_time); - padding = char(repmat(double(' '),1,paddingN)); - exp_time = [exp_time, padding]; - end - if length(hist_un0) < 10, - paddingN = 10-length(hist_un0); - padding = char(repmat(double(' '),1,paddingN)); - hist_un0 = [hist_un0, padding]; - end - - % -- if you thought that was anal, try this; - % -- lets check for unusual ASCII char values! - - if find(double(descrip)>128), - indexStrangeChar = find(double(descrip)>128); - descrip(indexStrangeChar) = ' '; - end - if find(double(aux_file)>128), - indexStrangeChar = find(double(aux_file)>128); - aux_file(indexStrangeChar) = ' '; - end - if find(double(originator)>128), - indexStrangeChar = find(double(originator)>128); - originator(indexStrangeChar) = ' '; - end - if find(double(generated)>128), - indexStrangeChar = find(double(generated)>128); - generated(indexStrangeChar) = ' '; - end - if find(double(scannum)>128), - indexStrangeChar = find(double(scannum)>128); - scannum(indexStrangeChar) = ' '; - end - if find(double(patient_id)>128), - indexStrangeChar = find(double(patient_id)>128); - patient_id(indexStrangeChar) = ' '; - end - if find(double(exp_date)>128), - indexStrangeChar = find(double(exp_date)>128); - exp_date(indexStrangeChar) = ' '; - end - if find(double(exp_time)>128), - indexStrangeChar = find(double(exp_time)>128); - exp_time(indexStrangeChar) = ' '; - end - if find(double(hist_un0)>128), - indexStrangeChar = find(double(hist_un0)>128); - hist_un0(indexStrangeChar) = ' '; - end - - - % --- finally, we write the fields - - fwrite(fid, descrip(1:80), 'uchar'); - fwrite(fid, aux_file(1:24), 'uchar'); - - - %orient = sprintf( '%1s', hist.orient); % 1 char - %fwrite(fid, orient(1), 'uchar'); - fwrite(fid, hist.orient(1), 'uint8'); % see note below on char - - fwrite(fid, originator(1:10), 'uchar'); - fwrite(fid, generated(1:10), 'uchar'); - fwrite(fid, scannum(1:10), 'uchar'); - fwrite(fid, patient_id(1:10), 'uchar'); - fwrite(fid, exp_date(1:10), 'uchar'); - fwrite(fid, exp_time(1:10), 'uchar'); - fwrite(fid, hist_un0(1:3), 'uchar'); - - fwrite(fid, hist.views(1), 'int32'); - fwrite(fid, hist.vols_added(1), 'int32'); - fwrite(fid, hist.start_field(1),'int32'); - fwrite(fid, hist.field_skip(1), 'int32'); - fwrite(fid, hist.omax(1), 'int32'); - fwrite(fid, hist.omin(1), 'int32'); - fwrite(fid, hist.smax(1), 'int32'); - fwrite(fid, hist.smin(1), 'int32'); - -return - - - -% Note on using char: -% The 'char orient' field in the header is intended to -% hold simply an 8-bit unsigned integer value, not the ASCII representation -% of the character for that value. A single 'char' byte is often used to -% represent an integer value in Analyze if the known value range doesn't -% go beyond 0-255 - saves a byte over a short int, which may not mean -% much in today's computing environments, but given that this format -% has been around since the early 1980's, saving bytes here and there on -% older systems was important! In this case, 'char' simply provides the -% byte of storage - not an indicator of the format for what is stored in -% this byte. Generally speaking, anytime a single 'char' is used, it is -% probably meant to hold an 8-bit integer value, whereas if this has -% been dimensioned as an array, then it is intended to hold an ASCII -% character string, even if that was only a single character. -% Denny - -% See other notes in avw_hdr_read diff --git a/external/fileio/private/avw_img_read.m b/external/fileio/private/avw_img_read.m deleted file mode 100644 index 0853e01..0000000 --- a/external/fileio/private/avw_img_read.m +++ /dev/null @@ -1,693 +0,0 @@ -function [ avw, machine ] = avw_img_read(fileprefix,IMGorient,machine,verbose) - -% avw_img_read - read Analyze format data image (*.img) -% -% [ avw, machine ] = avw_img_read(fileprefix,[orient],[machine],[verbose]) -% -% fileprefix - a string, the filename without the .img extension -% -% orient - read a specified orientation, integer values: -% -% '', use header history orient field -% 0, transverse unflipped (LAS*) -% 1, coronal unflipped (LA*S) -% 2, sagittal unflipped (L*AS) -% 3, transverse flipped (LPS*) -% 4, coronal flipped (LA*I) -% 5, sagittal flipped (L*AI) -% -% where * follows the slice dimension and letters indicate +XYZ -% orientations (L left, R right, A anterior, P posterior, -% I inferior, & S superior). -% -% Some files may contain data in the 3-5 orientations, but this -% is unlikely. For more information about orientation, see the -% documentation at the end of this .m file. See also the -% AVW_FLIP function for orthogonal reorientation. -% -% machine - a string, see machineformat in fread for details. -% The default here is 'ieee-le' but the routine -% will automatically switch between little and big -% endian to read any such Analyze header. It -% reports the appropriate machine format and can -% return the machine value. -% -% verbose - the default is to output processing information to the command -% window. If verbose = 0, this will not happen. -% -% Returned values: -% -% avw.hdr - a struct with image data parameters. -% avw.img - a 3D matrix of image data (double precision). -% -% A returned 3D matrix will correspond with the -% default ANALYZE coordinate system, which -% is Left-handed: -% -% X-Y plane is Transverse -% X-Z plane is Coronal -% Y-Z plane is Sagittal -% -% X axis runs from patient right (low X) to patient Left (high X) -% Y axis runs from posterior (low Y) to Anterior (high Y) -% Z axis runs from inferior (low Z) to Superior (high Z) -% -% The function can read a 4D Analyze volume, but only if it is in the -% axial unflipped orientation. -% -% See also: avw_hdr_read (called by this function), -% avw_view, avw_write, avw_img_write, avw_flip -% - - -% $Revision: 1.1 $ $Date: 2009/01/14 09:24:45 $ - -% Licence: GNU GPL, no express or implied warranties -% History: 05/2002, Darren.Weber@flinders.edu.au -% The Analyze format is copyright -% (c) Copyright, 1986-1995 -% Biomedical Imaging Resource, Mayo Foundation -% 01/2003, Darren.Weber@flinders.edu.au -% - adapted for matlab v5 -% - revised all orientation information and handling -% after seeking further advice from AnalyzeDirect.com -% 03/2003, Darren.Weber@flinders.edu.au -% - adapted for -ve pixdim values (non standard Analyze) -% 07/2004, chodkowski@kennedykrieger.org, added ability to -% read volumes with dimensionality greather than 3. -% a >3D volume cannot be flipped. and error is thrown if a volume of -% greater than 3D (ie, avw.hdr.dime.dim(1) > 3) requests a data flip -% (ie, avw.hdr.hist.orient ~= 0 ). i pulled the transfer of read-in -% data (tmp) to avw.img out of any looping mechanism. looping is not -% necessary as the data is already in its correct orientation. using -% 'reshape' rather than looping should be faster but, more importantly, -% it allows the reading in of N-D volumes. See lines 270-280. -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -if ~exist('IMGorient','var'), IMGorient = ''; end -if ~exist('machine','var'), machine = 'ieee-le'; end -if ~exist('verbose','var'), verbose = 1; end - -if isempty(IMGorient), IMGorient = ''; end -if isempty(machine), machine = 'ieee-le'; end -if isempty(verbose), verbose = 1; end - -if ~exist('fileprefix','var'), - msg = sprintf('...no input fileprefix - see help avw_img_read\n\n'); - error(msg); -end -if findstr('.hdr',fileprefix), - fileprefix = strrep(fileprefix,'.hdr',''); -end -if findstr('.img',fileprefix), - fileprefix = strrep(fileprefix,'.img',''); -end - -% MAIN - -% Read the file header -[ avw, machine ] = avw_hdr_read(fileprefix,machine,verbose); - -avw = read_image(avw,IMGorient,machine,verbose); - -return - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [ avw ] = read_image(avw,IMGorient,machine,verbose) - -fid = fopen(sprintf('%s.img',avw.fileprefix),'r',machine); -if fid < 0, - msg = sprintf('...cannot open file %s.img\n\n',avw.fileprefix); - error(msg); -end - -if verbose, - ver = '[$Revision: 1.1 $]'; - fprintf('\nAVW_IMG_READ [v%s]\n',ver(12:16)); tic; -end - -% short int bitpix; /* Number of bits per pixel; 1, 8, 16, 32, or 64. */ -% short int datatype /* Datatype for this image set */ -% /*Acceptable values for datatype are*/ -% #define DT_NONE 0 -% #define DT_UNKNOWN 0 /*Unknown data type*/ -% #define DT_BINARY 1 /*Binary ( 1 bit per voxel)*/ -% #define DT_UNSIGNED_CHAR 2 /*Unsigned character ( 8 bits per voxel)*/ -% #define DT_SIGNED_SHORT 4 /*Signed short (16 bits per voxel)*/ -% #define DT_SIGNED_INT 8 /*Signed integer (32 bits per voxel)*/ -% #define DT_FLOAT 16 /*Floating point (32 bits per voxel)*/ -% #define DT_COMPLEX 32 /*Complex (64 bits per voxel; 2 floating point numbers)/* -% #define DT_DOUBLE 64 /*Double precision (64 bits per voxel)*/ -% #define DT_RGB 128 /*A Red-Green-Blue datatype*/ -% #define DT_ALL 255 /*Undocumented*/ - -switch double(avw.hdr.dime.bitpix), - case 1, precision = 'bit1'; - case 8, precision = 'uchar'; - case 16, precision = 'int16'; - case 32, - if isequal(avw.hdr.dime.datatype, 8), precision = 'int32'; - else precision = 'single'; - end - case 64, precision = 'double'; - otherwise, - precision = 'uchar'; - if verbose, fprintf('...precision undefined in header, using ''uchar''\n'); end -end - -% read the whole .img file into matlab (faster) -if verbose, - fprintf('...reading %s Analyze %s image format.\n',machine,precision); -end -fseek(fid,0,'bof'); -% adjust for matlab version -ver = version; -ver = str2num(ver(1)); -if ver < 6, - tmp = fread(fid,inf,sprintf('%s',precision)); -else, - tmp = fread(fid,inf,sprintf('%s=>double',precision)); -end -fclose(fid); - -% Update the global min and max values -avw.hdr.dime.glmax = max(double(tmp)); -avw.hdr.dime.glmin = min(double(tmp)); - - -%--------------------------------------------------------------- -% Now partition the img data into xyz - -% --- first figure out the size of the image - -% short int dim[ ]; /* Array of the image dimensions */ -% -% dim[0] Number of dimensions in database; usually 4. -% dim[1] Image X dimension; number of pixels in an image row. -% dim[2] Image Y dimension; number of pixel rows in slice. -% dim[3] Volume Z dimension; number of slices in a volume. -% dim[4] Time points; number of volumes in database. - -PixelDim = double(avw.hdr.dime.dim(2)); -RowDim = double(avw.hdr.dime.dim(3)); -SliceDim = double(avw.hdr.dime.dim(4)); -TimeDim = double(avw.hdr.dime.dim(5)); - -PixelSz = double(avw.hdr.dime.pixdim(2)); -RowSz = double(avw.hdr.dime.pixdim(3)); -SliceSz = double(avw.hdr.dime.pixdim(4)); -TimeSz = double(avw.hdr.dime.pixdim(5)); - - - - -% ---- NON STANDARD ANALYZE... - -% Some Analyze files have been found to set -ve pixdim values, eg -% the MNI template avg152T1_brain in the FSL etc/standard folder, -% perhaps to indicate flipped orientation? If so, this code below -% will NOT handle the flip correctly! -if PixelSz < 0, - warning('X pixdim < 0 !!! resetting to abs(avw.hdr.dime.pixdim(2))'); - PixelSz = abs(PixelSz); - avw.hdr.dime.pixdim(2) = single(PixelSz); -end -if RowSz < 0, - warning('Y pixdim < 0 !!! resetting to abs(avw.hdr.dime.pixdim(3))'); - RowSz = abs(RowSz); - avw.hdr.dime.pixdim(3) = single(RowSz); -end -if SliceSz < 0, - warning('Z pixdim < 0 !!! resetting to abs(avw.hdr.dime.pixdim(4))'); - SliceSz = abs(SliceSz); - avw.hdr.dime.pixdim(4) = single(SliceSz); -end - -% ---- END OF NON STANDARD ANALYZE - - - - - -% --- check the orientation specification and arrange img accordingly -if ~isempty(IMGorient), - if ischar(IMGorient), - avw.hdr.hist.orient = uint8(str2num(IMGorient)); - else - avw.hdr.hist.orient = uint8(IMGorient); - end -end, - -if isempty(avw.hdr.hist.orient), - msg = [ '...unspecified avw.hdr.hist.orient, using default 0\n',... - ' (check image and try explicit IMGorient option).\n']; - fprintf(msg); - avw.hdr.hist.orient = uint8(0); -end - -% --- check if the orientation is to be flipped for a volume with more -% --- than 3 dimensions. this logic is currently unsupported so throw -% --- an error. volumes of any dimensionality may be read in *only* as -% --- unflipped, ie, avw.hdr.hist.orient == 0 -if ( TimeDim > 1 ) && (avw.hdr.hist.orient ~= 0 ), - msg = [ 'ERROR: This volume has more than 3 dimensions *and* ', ... - 'requires flipping the data. Flipping is not supported ', ... - 'for volumes with dimensionality greater than 3. Set ', ... - 'avw.hdr.hist.orient = 0 and flip your volume after ', ... - 'calling this function' ]; - msg = sprintf( '%s (%s).', msg, mfilename ); - error( msg ); -end - -switch double(avw.hdr.hist.orient), - - case 0, % transverse unflipped - - % orient = 0: The primary orientation of the data on disk is in the - % transverse plane relative to the object scanned. Most commonly, the fastest - % moving index through the voxels that are part of this transverse image would - % span the right-left extent of the structure imaged, with the next fastest - % moving index spanning the posterior-anterior extent of the structure. This - % 'orient' flag would indicate to Analyze that this data should be placed in - % the X-Y plane of the 3D Analyze Coordinate System, with the Z dimension - % being the slice direction. - - % For the 'transverse unflipped' type, the voxels are stored with - % Pixels in 'x' axis (varies fastest) - from patient right to left - % Rows in 'y' axis - from patient posterior to anterior - % Slices in 'z' axis - from patient inferior to superior - - if verbose, fprintf('...reading axial unflipped orientation\n'); end - - % -- This code will handle nD files - dims = double( avw.hdr.dime.dim(2:end) ); - % replace dimensions of 0 with 1 to be used in reshape - idx = find( dims == 0 ); - dims( idx ) = 1; - avw.img = reshape( tmp, dims ); - - % -- The code above replaces this - % avw.img = zeros(PixelDim,RowDim,SliceDim); - % - % n = 1; - % x = 1:PixelDim; - % for z = 1:SliceDim, - % for y = 1:RowDim, - % % load Y row of X values into Z slice avw.img - % avw.img(x,y,z) = tmp(n:n+(PixelDim-1)); - % n = n + PixelDim; - % end - % end - - - % no need to rearrange avw.hdr.dime.dim or avw.hdr.dime.pixdim - - -case 1, % coronal unflipped - - % orient = 1: The primary orientation of the data on disk is in the coronal - % plane relative to the object scanned. Most commonly, the fastest moving - % index through the voxels that are part of this coronal image would span the - % right-left extent of the structure imaged, with the next fastest moving - % index spanning the inferior-superior extent of the structure. This 'orient' - % flag would indicate to Analyze that this data should be placed in the X-Z - % plane of the 3D Analyze Coordinate System, with the Y dimension being the - % slice direction. - - % For the 'coronal unflipped' type, the voxels are stored with - % Pixels in 'x' axis (varies fastest) - from patient right to left - % Rows in 'z' axis - from patient inferior to superior - % Slices in 'y' axis - from patient posterior to anterior - - if verbose, fprintf('...reading coronal unflipped orientation\n'); end - - avw.img = zeros(PixelDim,SliceDim,RowDim); - - n = 1; - x = 1:PixelDim; - for y = 1:SliceDim, - for z = 1:RowDim, - % load Z row of X values into Y slice avw.img - avw.img(x,y,z) = tmp(n:n+(PixelDim-1)); - n = n + PixelDim; - end - end - - % rearrange avw.hdr.dime.dim or avw.hdr.dime.pixdim - avw.hdr.dime.dim(2:4) = int16([PixelDim,SliceDim,RowDim]); - avw.hdr.dime.pixdim(2:4) = single([PixelSz,SliceSz,RowSz]); - - - case 2, % sagittal unflipped - - % orient = 2: The primary orientation of the data on disk is in the sagittal - % plane relative to the object scanned. Most commonly, the fastest moving - % index through the voxels that are part of this sagittal image would span the - % posterior-anterior extent of the structure imaged, with the next fastest - % moving index spanning the inferior-superior extent of the structure. This - % 'orient' flag would indicate to Analyze that this data should be placed in - % the Y-Z plane of the 3D Analyze Coordinate System, with the X dimension - % being the slice direction. - - % For the 'sagittal unflipped' type, the voxels are stored with - % Pixels in 'y' axis (varies fastest) - from patient posterior to anterior - % Rows in 'z' axis - from patient inferior to superior - % Slices in 'x' axis - from patient right to left - - if verbose, fprintf('...reading sagittal unflipped orientation\n'); end - - avw.img = zeros(SliceDim,PixelDim,RowDim); - - n = 1; - y = 1:PixelDim; % posterior to anterior (fastest) - - for x = 1:SliceDim, % right to left (slowest) - for z = 1:RowDim, % inferior to superior - - % load Z row of Y values into X slice avw.img - avw.img(x,y,z) = tmp(n:n+(PixelDim-1)); - n = n + PixelDim; - end - end - - % rearrange avw.hdr.dime.dim or avw.hdr.dime.pixdim - avw.hdr.dime.dim(2:4) = int16([SliceDim,PixelDim,RowDim]); - avw.hdr.dime.pixdim(2:4) = single([SliceSz,PixelSz,RowSz]); - - - %-------------------------------------------------------------------------------- - % Orient values 3-5 have the second index reversed in order, essentially - % 'flipping' the images relative to what would most likely become the vertical - % axis of the displayed image. - %-------------------------------------------------------------------------------- - - case 3, % transverse/axial flipped - - % orient = 3: The primary orientation of the data on disk is in the - % transverse plane relative to the object scanned. Most commonly, the fastest - % moving index through the voxels that are part of this transverse image would - % span the right-left extent of the structure imaged, with the next fastest - % moving index spanning the *anterior-posterior* extent of the structure. This - % 'orient' flag would indicate to Analyze that this data should be placed in - % the X-Y plane of the 3D Analyze Coordinate System, with the Z dimension - % being the slice direction. - - % For the 'transverse flipped' type, the voxels are stored with - % Pixels in 'x' axis (varies fastest) - from patient right to Left - % Rows in 'y' axis - from patient anterior to Posterior * - % Slices in 'z' axis - from patient inferior to Superior - - if verbose, fprintf('...reading axial flipped (+Y from Anterior to Posterior)\n'); end - - avw.img = zeros(PixelDim,RowDim,SliceDim); - - n = 1; - x = 1:PixelDim; - for z = 1:SliceDim, - for y = RowDim:-1:1, % flip in Y, read A2P file into P2A 3D matrix - - % load a flipped Y row of X values into Z slice avw.img - avw.img(x,y,z) = tmp(n:n+(PixelDim-1)); - n = n + PixelDim; - end - end - - % no need to rearrange avw.hdr.dime.dim or avw.hdr.dime.pixdim - - - case 4, % coronal flipped - - % orient = 4: The primary orientation of the data on disk is in the coronal - % plane relative to the object scanned. Most commonly, the fastest moving - % index through the voxels that are part of this coronal image would span the - % right-left extent of the structure imaged, with the next fastest moving - % index spanning the *superior-inferior* extent of the structure. This 'orient' - % flag would indicate to Analyze that this data should be placed in the X-Z - % plane of the 3D Analyze Coordinate System, with the Y dimension being the - % slice direction. - - % For the 'coronal flipped' type, the voxels are stored with - % Pixels in 'x' axis (varies fastest) - from patient right to Left - % Rows in 'z' axis - from patient superior to Inferior* - % Slices in 'y' axis - from patient posterior to Anterior - - if verbose, fprintf('...reading coronal flipped (+Z from Superior to Inferior)\n'); end - - avw.img = zeros(PixelDim,SliceDim,RowDim); - - n = 1; - x = 1:PixelDim; - for y = 1:SliceDim, - for z = RowDim:-1:1, % flip in Z, read S2I file into I2S 3D matrix - - % load a flipped Z row of X values into Y slice avw.img - avw.img(x,y,z) = tmp(n:n+(PixelDim-1)); - n = n + PixelDim; - end - end - - % rearrange avw.hdr.dime.dim or avw.hdr.dime.pixdim - avw.hdr.dime.dim(2:4) = int16([PixelDim,SliceDim,RowDim]); - avw.hdr.dime.pixdim(2:4) = single([PixelSz,SliceSz,RowSz]); - - - case 5, % sagittal flipped - - % orient = 5: The primary orientation of the data on disk is in the sagittal - % plane relative to the object scanned. Most commonly, the fastest moving - % index through the voxels that are part of this sagittal image would span the - % posterior-anterior extent of the structure imaged, with the next fastest - % moving index spanning the *superior-inferior* extent of the structure. This - % 'orient' flag would indicate to Analyze that this data should be placed in - % the Y-Z plane of the 3D Analyze Coordinate System, with the X dimension - % being the slice direction. - - % For the 'sagittal flipped' type, the voxels are stored with - % Pixels in 'y' axis (varies fastest) - from patient posterior to Anterior - % Rows in 'z' axis - from patient superior to Inferior* - % Slices in 'x' axis - from patient right to Left - - if verbose, fprintf('...reading sagittal flipped (+Z from Superior to Inferior)\n'); end - - avw.img = zeros(SliceDim,PixelDim,RowDim); - - n = 1; - y = 1:PixelDim; - - for x = 1:SliceDim, - for z = RowDim:-1:1, % flip in Z, read S2I file into I2S 3D matrix - - % load a flipped Z row of Y values into X slice avw.img - avw.img(x,y,z) = tmp(n:n+(PixelDim-1)); - n = n + PixelDim; - end - end - - % rearrange avw.hdr.dime.dim or avw.hdr.dime.pixdim - avw.hdr.dime.dim(2:4) = int16([SliceDim,PixelDim,RowDim]); - avw.hdr.dime.pixdim(2:4) = single([SliceSz,PixelSz,RowSz]); - - otherwise - - error('unknown value in avw.hdr.hist.orient, try explicit IMGorient option.'); - -end - -if verbose, t=toc; fprintf('...done (%5.2f sec).\n\n',t); end - -return - - - - -% This function attempts to read the orientation of the -% Analyze file according to the hdr.hist.orient field of the -% header. Unfortunately, this field is optional and not -% all programs will set it correctly, so there is no guarantee, -% that the data loaded will be correctly oriented. If necessary, -% experiment with the 'orient' option to read the .img -% data into the 3D matrix of avw.img as preferred. -% - -% (Conventions gathered from e-mail with support@AnalyzeDirect.com) -% -% 0 transverse unflipped -% X direction first, progressing from patient right to left, -% Y direction second, progressing from patient posterior to anterior, -% Z direction third, progressing from patient inferior to superior. -% 1 coronal unflipped -% X direction first, progressing from patient right to left, -% Z direction second, progressing from patient inferior to superior, -% Y direction third, progressing from patient posterior to anterior. -% 2 sagittal unflipped -% Y direction first, progressing from patient posterior to anterior, -% Z direction second, progressing from patient inferior to superior, -% X direction third, progressing from patient right to left. -% 3 transverse flipped -% X direction first, progressing from patient right to left, -% Y direction second, progressing from patient anterior to posterior, -% Z direction third, progressing from patient inferior to superior. -% 4 coronal flipped -% X direction first, progressing from patient right to left, -% Z direction second, progressing from patient superior to inferior, -% Y direction third, progressing from patient posterior to anterior. -% 5 sagittal flipped -% Y direction first, progressing from patient posterior to anterior, -% Z direction second, progressing from patient superior to inferior, -% X direction third, progressing from patient right to left. - - -%---------------------------------------------------------------------------- -% From ANALYZE documentation... -% -% The ANALYZE coordinate system has an origin in the lower left -% corner. That is, with the subject lying supine, the coordinate -% origin is on the right side of the body (x), at the back (y), -% and at the feet (z). This means that: -% -% +X increases from right (R) to left (L) -% +Y increases from the back (posterior,P) to the front (anterior, A) -% +Z increases from the feet (inferior,I) to the head (superior, S) -% -% The LAS orientation is the radiological convention, where patient -% left is on the image right. The alternative neurological -% convention is RAS (also Talairach convention). -% -% A major advantage of the Analzye origin convention is that the -% coordinate origin of each orthogonal orientation (transverse, -% coronal, and sagittal) lies in the lower left corner of the -% slice as it is displayed. -% -% Orthogonal slices are numbered from one to the number of slices -% in that orientation. For example, a volume (x, y, z) dimensioned -% 128, 256, 48 has: -% -% 128 sagittal slices numbered 1 through 128 (X) -% 256 coronal slices numbered 1 through 256 (Y) -% 48 transverse slices numbered 1 through 48 (Z) -% -% Pixel coordinates are made with reference to the slice numbers from -% which the pixels come. Thus, the first pixel in the volume is -% referenced p(1,1,1) and not at p(0,0,0). -% -% Transverse slices are in the XY plane (also known as axial slices). -% Sagittal slices are in the ZY plane. -% Coronal slices are in the ZX plane. -% -%---------------------------------------------------------------------------- - - -%---------------------------------------------------------------------------- -% E-mail from support@AnalyzeDirect.com -% -% The 'orient' field in the data_history structure specifies the primary -% orientation of the data as it is stored in the file on disk. This usually -% corresponds to the orientation in the plane of acquisition, given that this -% would correspond to the order in which the data is written to disk by the -% scanner or other software application. As you know, this field will contain -% the values: -% -% orient = 0 transverse unflipped -% 1 coronal unflipped -% 2 sagittal unflipped -% 3 transverse flipped -% 4 coronal flipped -% 5 sagittal flipped -% -% It would be vary rare that you would ever encounter any old Analyze 7.5 -% files that contain values of 'orient' which indicate that the data has been -% 'flipped'. The 'flipped flag' values were really only used internal to -% Analyze to precondition data for fast display in the Movie module, where the -% images were actually flipped vertically in order to accommodate the raster -% paint order on older graphics devices. The only cases you will encounter -% will have values of 0, 1, or 2. -% -% As mentioned, the 'orient' flag only specifies the primary orientation of -% data as stored in the disk file itself. It has nothing to do with the -% representation of the data in the 3D Analyze coordinate system, which always -% has a fixed representation to the data. The meaning of the 'orient' values -% should be interpreted as follows: -% -% orient = 0: The primary orientation of the data on disk is in the -% transverse plane relative to the object scanned. Most commonly, the fastest -% moving index through the voxels that are part of this transverse image would -% span the right-left extent of the structure imaged, with the next fastest -% moving index spanning the posterior-anterior extent of the structure. This -% 'orient' flag would indicate to Analyze that this data should be placed in -% the X-Y plane of the 3D Analyze Coordinate System, with the Z dimension -% being the slice direction. -% -% orient = 1: The primary orientation of the data on disk is in the coronal -% plane relative to the object scanned. Most commonly, the fastest moving -% index through the voxels that are part of this coronal image would span the -% right-left extent of the structure imaged, with the next fastest moving -% index spanning the inferior-superior extent of the structure. This 'orient' -% flag would indicate to Analyze that this data should be placed in the X-Z -% plane of the 3D Analyze Coordinate System, with the Y dimension being the -% slice direction. -% -% orient = 2: The primary orientation of the data on disk is in the sagittal -% plane relative to the object scanned. Most commonly, the fastest moving -% index through the voxels that are part of this sagittal image would span the -% posterior-anterior extent of the structure imaged, with the next fastest -% moving index spanning the inferior-superior extent of the structure. This -% 'orient' flag would indicate to Analyze that this data should be placed in -% the Y-Z plane of the 3D Analyze Coordinate System, with the X dimension -% being the slice direction. -% -% Orient values 3-5 have the second index reversed in order, essentially -% 'flipping' the images relative to what would most likely become the vertical -% axis of the displayed image. -% -% Hopefully you understand the difference between the indication this 'orient' -% flag has relative to data stored on disk and the full 3D Analyze Coordinate -% System for data that is managed as a volume image. As mentioned previously, -% the orientation of patient anatomy in the 3D Analyze Coordinate System has a -% fixed orientation relative to each of the orthogonal axes. This orientation -% is completely described in the information that is attached, but the basics -% are: -% -% Left-handed coordinate system -% -% X-Y plane is Transverse -% X-Z plane is Coronal -% Y-Z plane is Sagittal -% -% X axis runs from patient right (low X) to patient left (high X) -% Y axis runs from posterior (low Y) to anterior (high Y) -% Z axis runs from inferior (low Z) to superior (high Z) -% -%---------------------------------------------------------------------------- - - - -%---------------------------------------------------------------------------- -% SPM2 NOTES from spm2 webpage: One thing to watch out for is the image -% orientation. The proper Analyze format uses a left-handed co-ordinate -% system, whereas Talairach uses a right-handed one. In SPM99, images were -% flipped at the spatial normalisation stage (from one co-ordinate system -% to the other). In SPM2b, a different approach is used, so that either a -% left- or right-handed co-ordinate system is used throughout. The SPM2b -% program is told about the handedness that the images are stored with by -% the spm_flip_analyze_images.m function and the defaults.analyze.flip -% parameter that is specified in the spm_defaults.m file. These files are -% intended to be customised for each site. If you previously used SPM99 -% and your images were flipped during spatial normalisation, then set -% defaults.analyze.flip=1. If no flipping took place, then set -% defaults.analyze.flip=0. Check that when using the Display facility -% (possibly after specifying some rigid-body rotations) that: -% -% 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. -%---------------------------------------------------------------------------- diff --git a/external/fileio/private/avw_img_write.m b/external/fileio/private/avw_img_write.m deleted file mode 100644 index c1a9c74..0000000 --- a/external/fileio/private/avw_img_write.m +++ /dev/null @@ -1,412 +0,0 @@ -function avw_img_write(avw, fileprefix, IMGorient, machine, verbose) - -% avw_img_write - write Analyze image files (*.img) -% -% avw_img_write(avw,fileprefix,[IMGorient],[machine],[verbose]) -% -% avw.img - a 3D matrix of image data (double precision). -% avw.hdr - a struct with image data parameters. If -% not empty, this function calls avw_hdr_write. -% -% fileprefix - a string, the filename without the .img -% extension. If empty, may use avw.fileprefix -% -% IMGorient - optional int, force writing of specified -% orientation, with values: -% -% [], if empty, will use avw.hdr.hist.orient field -% 0, transverse/axial unflipped (default, radiological) -% 1, coronal unflipped -% 2, sagittal unflipped -% 3, transverse/axial flipped, left to right -% 4, coronal flipped, anterior to posterior -% 5, sagittal flipped, superior to inferior -% -% This function will set avw.hdr.hist.orient and write the -% image data in a corresponding order. This function is -% in alpha development, so it has not been exhaustively -% tested (07/2003). See avw_img_read for more information -% and documentation on the orientation option. -% Orientations 3-5 are NOT recommended! They are part -% of the Analyze format, but only used in Analyze -% for faster raster graphics during movies. -% -% machine - a string, see machineformat in fread for details. -% The default here is 'ieee-le'. -% -% verbose - the default is to output processing information to the command -% window. If verbose = 0, this will not happen. -% -% Tip: to change the data type, set avw.hdr.dime.datatype to: -% -% 1 Binary ( 1 bit per voxel) -% 2 Unsigned character ( 8 bits per voxel) -% 4 Signed short ( 16 bits per voxel) -% 8 Signed integer ( 32 bits per voxel) -% 16 Floating point ( 32 bits per voxel) -% 32 Complex, 2 floats ( 64 bits per voxel), not supported -% 64 Double precision ( 64 bits per voxel) -% 128 Red-Green-Blue (128 bits per voxel), not supported -% -% See also: avw_write, avw_hdr_write, -% avw_read, avw_hdr_read, avw_img_read, avw_view -% - -% $Revision: 1.1 $ $Date: 2009/01/14 09:24:45 $ - -% Licence: GNU GPL, no express or implied warranties -% History: 05/2002, Darren.Weber@flinders.edu.au -% The Analyze format is copyright -% (c) Copyright, 1986-1995 -% Biomedical Imaging Resource, Mayo Foundation -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - -%------------------------------------------------------------------------ -% Check inputs - -if ~exist('avw','var'), - doc avw_img_write; - error('...no input avw.'); -elseif isempty(avw), - error('...empty input avw.'); -elseif ~isfield(avw,'img'), - error('...empty input avw.img'); -end - -if ~exist('fileprefix','var'), - if isfield(avw,'fileprefix'), - if ~isempty(avw.fileprefix), - fileprefix = avw.fileprefix; - else - fileprefix = []; - end - else - fileprefix = []; - end -end -if isempty(fileprefix), - [fileprefix, pathname, filterindex] = uiputfile('*.hdr','Specify an output Analyze .hdr file'); - if pathname, cd(pathname); end - if ~fileprefix, - doc avw_img_write; - error('no output .hdr file specified'); - end -end - -if findstr('.hdr',fileprefix), -% fprintf('AVW_IMG_WRITE: Removing .hdr extension from ''%s''\n',fileprefix); - fileprefix = strrep(fileprefix,'.hdr',''); -end -if findstr('.img',fileprefix), -% fprintf('AVW_IMG_WRITE: Removing .img extension from ''%s''\n',fileprefix); - fileprefix = strrep(fileprefix,'.img',''); -end - -if ~exist('IMGorient','var'), IMGorient = ''; end -if ~exist('machine','var'), machine = 'ieee-le'; end -if ~exist('verbose','var'), verbose = 1; end - -if isempty(IMGorient), IMGorient = ''; end -if isempty(machine), machine = 'ieee-le'; end -if isempty(verbose), verbose = 1; end - - - -%------------------------------------------------------------------------ -% MAIN -if verbose, - version = '[$Revision: 1.1 $]'; - fprintf('\nAVW_IMG_WRITE [v%s]\n',version(12:16)); tic; -end - -fid = fopen(sprintf('%s.img',fileprefix),'w',machine); -if fid < 0, - msg = sprintf('Cannot open file %s.img\n',fileprefix); - error(msg); -else - avw = write_image(fid,avw,fileprefix,IMGorient,machine,verbose); -end - -if verbose, - t=toc; fprintf('...done (%5.2f sec).\n\n',t); -end - -% MUST write header after the image, to ensure any -% orientation changes during image write are saved -% in the header -avw_hdr_write(avw,fileprefix,machine,verbose); - -return - - - - -%----------------------------------------------------------------------------------- - -function avw = write_image(fid,avw,fileprefix,IMGorient,machine,verbose) - -% short int bitpix; /* Number of bits per pixel; 1, 8, 16, 32, or 64. */ -% short int datatype /* Datatype for this image set */ -% /*Acceptable values for datatype are*/ -% #define DT_NONE 0 -% #define DT_UNKNOWN 0 /*Unknown data type*/ -% #define DT_BINARY 1 /*Binary ( 1 bit per voxel)*/ -% #define DT_UNSIGNED_CHAR 2 /*Unsigned character ( 8 bits per voxel)*/ -% #define DT_SIGNED_SHORT 4 /*Signed short (16 bits per voxel)*/ -% #define DT_SIGNED_INT 8 /*Signed integer (32 bits per voxel)*/ -% #define DT_FLOAT 16 /*Floating point (32 bits per voxel)*/ -% #define DT_COMPLEX 32 /*Complex,2 floats (64 bits per voxel)/* -% #define DT_DOUBLE 64 /*Double precision (64 bits per voxel)*/ -% #define DT_RGB 128 /*A Red-Green-Blue datatype*/ -% #define DT_ALL 255 /*Undocumented*/ - -switch double(avw.hdr.dime.datatype), -case 1, - avw.hdr.dime.bitpix = int16( 1); precision = 'bit1'; -case 2, - avw.hdr.dime.bitpix = int16( 8); precision = 'uchar'; -case 4, - avw.hdr.dime.bitpix = int16(16); precision = 'int16'; -case 8, - avw.hdr.dime.bitpix = int16(32); precision = 'int32'; -case 16, - avw.hdr.dime.bitpix = int16(32); precision = 'single'; -case 32, - error('...complex datatype not yet supported.\n'); -case 64, - avw.hdr.dime.bitpix = int16(64); precision = 'double'; -case 128, - error('...RGB datatype not yet supported.\n'); -otherwise - warning('...unknown datatype, using type 16 (32 bit floats).\n'); - avw.hdr.dime.datatype = int16(16); - avw.hdr.dime.bitpix = int16(32); precision = 'single'; -end - - -% write the .img file, depending on the .img orientation -if verbose, - fprintf('...writing %s precision Analyze image (%s).\n',precision,machine); -end - -fseek(fid,0,'bof'); - -% The standard image orientation is axial unflipped -if isempty(avw.hdr.hist.orient), - msg = [ '...avw.hdr.hist.orient ~= 0.\n',... - ' This function assumes the input avw.img is\n',... - ' in axial unflipped orientation in memory. This is\n',... - ' created by the avw_img_read function, which converts\n',... - ' any input file image to axial unflipped in memory.\n']; - warning(msg) -end - -if isempty(IMGorient), - if verbose, - fprintf('...no IMGorient specified, using avw.hdr.hist.orient value.\n'); - end - IMGorient = double(avw.hdr.hist.orient); -end - -if ~isfinite(IMGorient), - if verbose, - fprintf('...IMGorient is not finite!\n'); - end - IMGorient = 99; -end - -switch IMGorient, - -case 0, % transverse/axial unflipped - - % For the 'transverse unflipped' type, the voxels are stored with - % Pixels in 'x' axis (varies fastest) - from patient right to left - % Rows in 'y' axis - from patient posterior to anterior - % Slices in 'z' axis - from patient inferior to superior - - if verbose, fprintf('...writing axial unflipped\n'); end - - avw.hdr.hist.orient = uint8(0); - - SliceDim = double(avw.hdr.dime.dim(4)); % z - RowDim = double(avw.hdr.dime.dim(3)); % y - PixelDim = double(avw.hdr.dime.dim(2)); % x - SliceSz = double(avw.hdr.dime.pixdim(4)); - RowSz = double(avw.hdr.dime.pixdim(3)); - PixelSz = double(avw.hdr.dime.pixdim(2)); - - x = 1:PixelDim; - for z = 1:SliceDim, - for y = 1:RowDim, - fwrite(fid,avw.img(x,y,z),precision); - end - end - -case 1, % coronal unflipped - - % For the 'coronal unflipped' type, the voxels are stored with - % Pixels in 'x' axis (varies fastest) - from patient right to left - % Rows in 'z' axis - from patient inferior to superior - % Slices in 'y' axis - from patient posterior to anterior - - if verbose, fprintf('...writing coronal unflipped\n'); end - - avw.hdr.hist.orient = uint8(1); - - SliceDim = double(avw.hdr.dime.dim(3)); % y - RowDim = double(avw.hdr.dime.dim(4)); % z - PixelDim = double(avw.hdr.dime.dim(2)); % x - SliceSz = double(avw.hdr.dime.pixdim(3)); - RowSz = double(avw.hdr.dime.pixdim(4)); - PixelSz = double(avw.hdr.dime.pixdim(2)); - - x = 1:PixelDim; - for y = 1:SliceDim, - for z = 1:RowDim, - fwrite(fid,avw.img(x,y,z),precision); - end - end - -case 2, % sagittal unflipped - - % For the 'sagittal unflipped' type, the voxels are stored with - % Pixels in 'y' axis (varies fastest) - from patient posterior to anterior - % Rows in 'z' axis - from patient inferior to superior - % Slices in 'x' axis - from patient right to left - - if verbose, fprintf('...writing sagittal unflipped\n'); end - - avw.hdr.hist.orient = uint8(2); - - SliceDim = double(avw.hdr.dime.dim(2)); % x - RowDim = double(avw.hdr.dime.dim(4)); % z - PixelDim = double(avw.hdr.dime.dim(3)); % y - SliceSz = double(avw.hdr.dime.pixdim(2)); - RowSz = double(avw.hdr.dime.pixdim(4)); - PixelSz = double(avw.hdr.dime.pixdim(3)); - - y = 1:PixelDim; - for x = 1:SliceDim, - for z = 1:RowDim, - fwrite(fid,avw.img(x,y,z),precision); - end - end - -case 3, % transverse/axial flipped - - % For the 'transverse flipped' type, the voxels are stored with - % Pixels in 'x' axis (varies fastest) - from patient right to left - % Rows in 'y' axis - from patient anterior to posterior* - % Slices in 'z' axis - from patient inferior to superior - - if verbose, - fprintf('...writing axial flipped (+Y from Anterior to Posterior)\n'); - end - - avw.hdr.hist.orient = uint8(3); - - SliceDim = double(avw.hdr.dime.dim(4)); % z - RowDim = double(avw.hdr.dime.dim(3)); % y - PixelDim = double(avw.hdr.dime.dim(2)); % x - SliceSz = double(avw.hdr.dime.pixdim(4)); - RowSz = double(avw.hdr.dime.pixdim(3)); - PixelSz = double(avw.hdr.dime.pixdim(2)); - - x = 1:PixelDim; - for z = 1:SliceDim, - for y = RowDim:-1:1, % flipped in Y - fwrite(fid,avw.img(x,y,z),precision); - end - end - -case 4, % coronal flipped - - % For the 'coronal flipped' type, the voxels are stored with - % Pixels in 'x' axis (varies fastest) - from patient right to left - % Rows in 'z' axis - from patient inferior to superior - % Slices in 'y' axis - from patient anterior to posterior - - if verbose, - fprintf('...writing coronal flipped (+Z from Superior to Inferior)\n'); - end - - avw.hdr.hist.orient = uint8(4); - - SliceDim = double(avw.hdr.dime.dim(3)); % y - RowDim = double(avw.hdr.dime.dim(4)); % z - PixelDim = double(avw.hdr.dime.dim(2)); % x - SliceSz = double(avw.hdr.dime.pixdim(3)); - RowSz = double(avw.hdr.dime.pixdim(4)); - PixelSz = double(avw.hdr.dime.pixdim(2)); - - x = 1:PixelDim; - for y = 1:SliceDim, - for z = RowDim:-1:1, - fwrite(fid,avw.img(x,y,z),precision); - end - end - -case 5, % sagittal flipped - - % For the 'sagittal flipped' type, the voxels are stored with - % Pixels in 'y' axis (varies fastest) - from patient posterior to anterior - % Rows in 'z' axis - from patient superior to inferior - % Slices in 'x' axis - from patient right to left - - if verbose, - fprintf('...writing sagittal flipped (+Z from Superior to Inferior)\n'); - end - - avw.hdr.hist.orient = uint8(5); - - SliceDim = double(avw.hdr.dime.dim(2)); % x - RowDim = double(avw.hdr.dime.dim(4)); % z - PixelDim = double(avw.hdr.dime.dim(3)); % y - SliceSz = double(avw.hdr.dime.pixdim(2)); - RowSz = double(avw.hdr.dime.pixdim(4)); - PixelSz = double(avw.hdr.dime.pixdim(3)); - - y = 1:PixelDim; - for x = 1:SliceDim, - for z = RowDim:-1:1, % superior to inferior - fwrite(fid,avw.img(x,y,z),precision); - end - end - -otherwise, % transverse/axial unflipped - - % For the 'transverse unflipped' type, the voxels are stored with - % Pixels in 'x' axis (varies fastest) - from patient right to left - % Rows in 'y' axis - from patient posterior to anterior - % Slices in 'z' axis - from patient inferior to superior - - if verbose, - fprintf('...unknown orientation specified, assuming default axial unflipped\n'); - end - - avw.hdr.hist.orient = uint8(0); - - SliceDim = double(avw.hdr.dime.dim(4)); % z - RowDim = double(avw.hdr.dime.dim(3)); % y - PixelDim = double(avw.hdr.dime.dim(2)); % x - SliceSz = double(avw.hdr.dime.pixdim(4)); - RowSz = double(avw.hdr.dime.pixdim(3)); - PixelSz = double(avw.hdr.dime.pixdim(2)); - - x = 1:PixelDim; - for z = 1:SliceDim, - for y = 1:RowDim, - fwrite(fid,avw.img(x,y,z),precision); - end - end - -end - -fclose(fid); - -% Update the header -avw.hdr.dime.dim(2:4) = int16([PixelDim,RowDim,SliceDim]); -avw.hdr.dime.pixdim(2:4) = single([PixelSz,RowSz,SliceSz]); - -return diff --git a/external/fileio/private/buffer.m b/external/fileio/private/buffer.m deleted file mode 100644 index de4ad82..0000000 --- a/external/fileio/private/buffer.m +++ /dev/null @@ -1,127 +0,0 @@ -function [varargout] = buffer(varargin) - -% BUFFER manages and accesses the realtime data acquisition buffer -% This function is implented as mex file. -% -% Use as -% retval = buffer(cmd, detail, host, port) -% -% To read data from a buffer server over the network -% hdr = buffer('get_hdr', [], host, port) -% dat = buffer('get_dat', datsel, host, port) -% evt = buffer('get_evt', evtsel, host, port) -% -% The selection for data and events should be zero-offset and contain -% datsel = [begsample endsample] -% evtsel = [begevent endevent] -% -% To write data to a buffer server over the network -% buffer('put_hdr', hdr, host, port) -% buffer('put_dat', dat, host, port) -% buffer('put_evt', evt, host, port) -% -% To implement a local buffer server and have other clients -% connect to it at a specified network port -% buffer('tcpserver', 'init', [], port) -% buffer('tcpserver', 'exit', [], port) -% -% To implement a local acquisition client and have it buffer the -% data locally -% buffer(acqclient, 'init') -% buffer(acqclient, 'exit') -% -% To implement a local acquisition client and have it send the data -% through the network to a buffer server -% buffer(acqclient, 'init', host, port) -% buffer(acqclient, 'exit', host, port) -% -% Supported acquisition clients should be -% 'sinewave' -% 'ctf' -% 'brainamp' -% 'biosemi' -% 'tmsi' -% 'eldith' - -% Copyright (C) 2008, Robert Oostenveld -% -% $Log: buffer.m,v $ -% Revision 1.7 2009/01/21 19:58:07 roboos -% also call the function after compilation -% -% Revision 1.6 2009/01/20 15:38:37 roboos -% try to compile the mex file on the fly -% -% Revision 1.5 2008/10/24 07:32:05 roboos -% should be a function, not a script -% -% Revision 1.4 2008/07/08 20:31:34 roboos -% extended the list of acquisition threads in the mex file, also added all of them to thread stopping -% -% Revision 1.3 2008/05/22 09:23:09 roboos -% updated documentation -% -% Revision 1.2 2008/03/10 10:41:58 roboos -% updated documentation -% -% Revision 1.1 2008/03/09 22:53:04 roboos -% new function, only placeholder for the documentation since the actual implementation is in a mex file -% - -% remember the original working directory -pwdir = pwd; - -% determine the name and full path of this function -funname = mfilename('fullpath'); -mexsrc = [funname '.c']; -[mexdir, mexname] = fileparts(funname); - -try - warning('trying to compile MEX file from %s', mexsrc); - cd(mexdir); - - % the following is specific for this particular mex file - mex -I../src -I../../pthreads-win32/include -c buffer_gethdr.c - mex -I../src -I../../pthreads-win32/include -c buffer_getdat.c - mex -I../src -I../../pthreads-win32/include -c buffer_getevt.c - mex -I../src -I../../pthreads-win32/include -c buffer_getprp.c - mex -I../src -I../../pthreads-win32/include -c buffer_puthdr.c - mex -I../src -I../../pthreads-win32/include -c buffer_putdat.c - mex -I../src -I../../pthreads-win32/include -c buffer_putevt.c - mex -I../src -I../../pthreads-win32/include -c buffer_putprp.c - mex -I../src -I../../pthreads-win32/include -c buffer_flushhdr.c - mex -I../src -I../../pthreads-win32/include -c buffer_flushdat.c - mex -I../src -I../../pthreads-win32/include -c buffer_flushevt.c - - % this is for the demo acquisition threads - mex -I../src -I../../pthreads-win32/include -c ../test/sinewave.c - mex -I../src -I../../pthreads-win32/include -c ../test/event.c - - % link all the objects together into a mex file - if ispc - % this is needed for Borland on windows, but not for other platforms - mex -I../src -I../../pthreads-win32/include -c ../src/gettimeofday.c -I../src -I../../pthreads-win32/include - % link all the objects together into a mex file - mex -I../src -I../../pthreads-win32/include -L../src -L../../pthreads-win32/lib buffer.c event.obj sinewave.obj gettimeofday.obj buffer_gethdr.obj buffer_getdat.obj buffer_getevt.obj buffer_getprp.obj buffer_flushhdr.obj buffer_flushdat.obj buffer_flushevt.obj buffer_puthdr.obj buffer_putdat.obj buffer_putevt.obj buffer_putprp.obj -lbuffer -lpthreadVC2.bcb - else - % link all the objects together into a mex file - mex -I../src -L../src buffer.c event.o sinewave.o buffer_gethdr.o buffer_getdat.o buffer_getevt.o buffer_getprp.o buffer_flushhdr.o buffer_flushdat.o buffer_flushevt.o buffer_puthdr.o buffer_putdat.o buffer_putevt.o buffer_putprp.o -lbuffer - end - - cd(pwdir); - success = true; - -catch - % compilation failed - disp(lasterr); - error('could not locate MEX file for %s', mexname); - cd(pwdir); - success = false; -end - -if success - % execute the mex file that was juist created - funname = mfilename; - funhandle = str2func(funname); - [varargout{1:nargout}] = funhandle(varargin{:}); -end diff --git a/external/fileio/private/chantype.m b/external/fileio/private/chantype.m deleted file mode 100644 index 0b641f7..0000000 --- a/external/fileio/private/chantype.m +++ /dev/null @@ -1,407 +0,0 @@ -function type = chantype(input, desired) - -% CHANTYPE determines for each channel what type it is, e.g. planar/axial gradiometer or magnetometer -% -% Use as -% type = chantype(hdr) -% type = chantype(sens) -% type = chantype(label) -% or as -% type = chantype(hdr, desired) -% type = chantype(sens, desired) -% type = chantype(label, desired) - -% Copyright (C) 2008, Robert Oostenveld -% -% $Log: chantype.m,v $ -% Revision 1.15 2009/10/16 12:27:53 roboos -% some small changes pertaining to the itab/chieti format -% -% Revision 1.14 2009/10/13 10:39:03 roboos -% added support for 153 channel itab system -% -% Revision 1.13 2009/09/22 11:15:47 vlalit -% Changes by Laurence Hunt for distinguishing between analog and digital event channels for Neuromag. -% -% Revision 1.12 2009/03/30 17:53:38 vlalit -% Fixed a bug in BTi handling code from the last update -% -% Revision 1.11 2009/03/26 19:17:21 vlalit -% Some improvements for non-MEG channels in BTi -% -% Revision 1.10 2009/03/06 08:49:54 roboos -% added handling of plexon header -% -% Revision 1.9 2009/02/05 18:30:44 vlalit -% Updates by Laurence to recognize additional Neuromag sensor types -% -% Revision 1.8 2009/02/02 12:09:28 vlalit -% Added back support of generic desired types 'meg' and 'ref'. -% -% Revision 1.7 2009/01/29 18:51:53 vlalit -% Some cosmetic changes + detection of additional channel types based on label -% -% Revision 1.6 2009/01/29 16:42:31 vlalit -% Standardized all the names of MEG-related types accross different MEG system. -% -% Revision 1.5 2009/01/29 16:09:06 jansch -% added check for gradiometers in meg-sensors for bti -% -% Revision 1.4 2009/01/29 11:45:12 vlalit -% Basic support for BTi based on code from channelselection -% -% Revision 1.3 2009/01/23 10:32:55 vlalit -% New reader for Neuromag fif format using the MNE toolbox -% (http://www.nmr.mgh.harvard.edu/martinos/userInfo/data/sofMNE.php) -% implemented by Laurence Hunt. -% -% Revision 1.2 2009/01/21 16:42:41 vlalit -% Added support for EEG systems. -% -% Revision 1.7 2008/11/12 20:32:31 roboos -% refined ctf headloc channels -% -% Revision 1.6 2008/11/03 11:36:09 roboos -% added work-around for unusual/spm5 ctf headers -> give warning and keep all at unknown -% give error for weird input -% -% Revision 1.5 2008/10/22 07:22:46 roboos -% also detect refmag and refgrad from ctf labels, use regexp and local subfunction -% -% Revision 1.4 2008/10/21 20:32:47 roboos -% added second input argument (desired type) -% besides hdr, also allow grad and label input (ctf only sofar) -% -% Revision 1.3 2008/10/20 15:14:06 roboos -% added missing semicolon -% -% Revision 1.2 2008/09/10 10:06:07 roboos -% added ctf headloc -% -% Revision 1.1 2008/09/10 10:04:22 roboos -% new function -% - -% determine the type of input - -isheader = isa(input, 'struct') && isfield(input, 'label') && isfield(input, 'Fs'); -isgrad = isa(input, 'struct') && isfield(input, 'pnt') && isfield(input, 'ori'); -islabel = isa(input, 'cell') && isa(input{1}, 'char'); - -hdr = input; -grad = input; -label = input; - -if isheader - numchan = length(hdr.label); - if isfield(hdr, 'grad') - grad = hdr.grad; - end - label = hdr.label; -elseif isgrad - label = grad.label; - numchan = length(label); -elseif islabel - numchan = length(label); -else - error('the input that was provided to this function cannot be deciphered'); -end - -% start with unknown type -type = cell(numchan,1); -for i=1:length(type) - type{i} = 'unknown'; -end - -if senstype(input, 'neuromag') - % channames-KI is the channel kind, 1=meg, 202=eog, 2=eeg, 3=trigger (I am nut sure, but have inferred this from a single test file) - % chaninfo-TY is the Coil type (0=magnetometer, 1=planar gradiometer) - if isfield(hdr, 'orig') && isfield(hdr.orig, 'channames') - for sel=find(hdr.orig.channames.KI(:)==202)' - type{sel} = 'eog'; - end - for sel=find(hdr.orig.channames.KI(:)==2)' - type{sel} = 'eeg'; - end - for sel=find(hdr.orig.channames.KI(:)==3)' - type{sel} = 'digital trigger'; - end - % determinge the MEG channel subtype - selmeg=find(hdr.orig.channames.KI(:)==1)'; - for i=1:length(selmeg) - if hdr.orig.chaninfo.TY(i)==0 - type{selmeg(i)} = 'megmag'; - elseif hdr.orig.chaninfo.TY(i)==1 - type{selmeg(i)} = 'megplanar'; - end - end - - elseif isfield(hdr, 'orig') && isfield(hdr.orig, 'chs') && isfield(hdr.orig.chs, 'coil_type') - %all the chs.kinds and chs.coil_types are obtained from the MNE - %manual, p.210-211 - for sel=find([hdr.orig.chs.kind]==1 & [hdr.orig.chs.coil_type]==2)' %planar gradiometers - type(sel) = {'megplanar'}; %Neuromag-122 planar gradiometer - end - for sel=find([hdr.orig.chs.kind]==1 & [hdr.orig.chs.coil_type]==3012)' %planar gradiometers - type(sel) = {'megplanar'}; %Type T1 planar grad - end - for sel=find([hdr.orig.chs.kind]==1 & [hdr.orig.chs.coil_type]==3013)' %planar gradiometers - type(sel) = {'megplanar'}; %Type T2 planar grad - end - for sel=find([hdr.orig.chs.kind]==1 & [hdr.orig.chs.coil_type]==3014)' %planar gradiometers - type(sel) = {'megplanar'}; %Type T3 planar grad - end - for sel=find([hdr.orig.chs.kind]==1 & [hdr.orig.chs.coil_type]==3022)' %magnetometers - type(sel) = {'megmag'}; %Type T1 magenetometer - end - for sel=find([hdr.orig.chs.kind]==1 & [hdr.orig.chs.coil_type]==3023)' %magnetometers - type(sel) = {'megmag'}; %Type T2 magenetometer - end - for sel=find([hdr.orig.chs.kind]==1 & [hdr.orig.chs.coil_type]==3024)' %magnetometers - type(sel) = {'megmag'}; %Type T3 magenetometer - end - for sel=find([hdr.orig.chs.kind]==301)' %MEG reference channel, located far from head - type(sel) = {'ref'}; - end - for sel=find([hdr.orig.chs.kind]==2)' %EEG channels - type(sel) = {'eeg'}; - end - for sel=find([hdr.orig.chs.kind]==201)' %MCG channels - type(sel) = {'mcg'}; - end - for sel=find([hdr.orig.chs.kind]==3)' %Stim channels - if any([hdr.orig.chs(sel).logno] == 101) %new systems: 101 (and 102, if enabled) are digital; - %low numbers are 'pseudo-analog' (if enabled) - type(sel([hdr.orig.chs(sel).logno] == 101)) = {'digital trigger'}; - type(sel([hdr.orig.chs(sel).logno] == 102)) = {'digital trigger'}; - type(sel([hdr.orig.chs(sel).logno] <= 32)) = {'analog trigger'}; - others = [hdr.orig.chs(sel).logno] > 32 & [hdr.orig.chs(sel).logno] ~= 101 & ... - [hdr.orig.chs(sel).logno] ~= 102; - type(sel(others)) = {'other trigger'}; - elseif any([hdr.orig.chs(sel).logno] == 14) %older systems: STI 014/015/016 are digital; - %lower numbers 'pseudo-analog'(if enabled) - type(sel([hdr.orig.chs(sel).logno] == 14)) = {'digital trigger'}; - type(sel([hdr.orig.chs(sel).logno] == 15)) = {'digital trigger'}; - type(sel([hdr.orig.chs(sel).logno] == 16)) = {'digital trigger'}; - type(sel([hdr.orig.chs(sel).logno] <= 13)) = {'analog trigger'}; - others = [hdr.orig.chs(sel).logno] > 16; - type(sel(others)) = {'other trigger'}; - else - warning('There does not seem to be a suitable trigger channel.'); - type(sel) = {'other trigger'}; - end - end - for sel=find([hdr.orig.chs.kind]==202)' %EOG - type(sel) = {'eog'}; - end - for sel=find([hdr.orig.chs.kind]==302)' %EMG - type(sel) = {'emg'}; - end - for sel=find([hdr.orig.chs.kind]==402)' %ECG - type(sel) = {'ecg'}; - end - for sel=find([hdr.orig.chs.kind]==502)' %MISC - type(sel) = {'misc'}; - end - for sel=find([hdr.orig.chs.kind]==602)' %Resp - type(sel) = {'respiration'}; - end - end - -elseif senstype(input, 'ctf') && isheader - % meg channels are 5, refmag 0, refgrad 1, adcs 18, trigger 11, eeg 9 - if isfield(hdr, 'orig') && isfield(hdr.orig, 'sensType') - origSensType = hdr.orig.sensType; - elseif isfield(hdr, 'orig') && isfield(hdr.orig, 'res4') - origSensType = [hdr.orig.res4.senres.sensorTypeIndex]; - else - warning('could not determine channel type from the CTF header'); - origSensType = []; - end - - for sel=find(origSensType(:)==5)' - type{sel} = 'meggrad'; - end - for sel=find(origSensType(:)==0)' - type{sel} = 'refmag'; - end - for sel=find(origSensType(:)==1)' - type{sel} = 'refgrad'; - end - for sel=find(origSensType(:)==18)' - type{sel} = 'adc'; - end - for sel=find(origSensType(:)==11)' - type{sel} = 'trigger'; - end - for sel=find(origSensType(:)==9)' - type{sel} = 'eeg'; - end - for sel=find(origSensType(:)==29)' - type{sel} = 'reserved'; % these are "reserved for future use", but relate to head localization - end - for sel=find(origSensType(:)==13)' - type{sel} = 'headloc'; % these represent the x, y, z position of the head coils - end - for sel=find(origSensType(:)==28)' - type{sel} = 'headloc_gof'; % these represent the goodness of fit for the head coils - end - % for sel=find(origSensType(:)==23)' - % type{sel} = 'SPLxxxx'; % I have no idea what these are - % end - -elseif senstype(input, 'ctf') && isgrad - % in principle it is possible to look at the number of coils, but here the channels are identified based on their name - sel = myregexp('^M[ZLR][A-Z][0-9][0-9]$', grad.label); - type(sel) = {'meggrad'}; % normal gradiometer channels - sel = myregexp('^B[GPR][0-9]$', grad.label); - type(sel) = {'refmag'}; % reference magnetometers - sel = myregexp('^[GPQR][0-9][0-9]$', grad.label); - type(sel) = {'refgrad'}; % reference gradiometers - -elseif senstype(input, 'ctf') && islabel - % the channels have to be identified based on their name alone - sel = myregexp('^M[ZLR][A-Z][0-9][0-9]$', label); - type(sel) = {'meggrad'}; % normal gradiometer channels - sel = myregexp('^B[GPR][0-9]$', label); - type(sel) = {'refmag'}; % reference magnetometers - sel = myregexp('^[GPQR][0-9][0-9]$', label); - type(sel) = {'refgrad'}; % reference gradiometers - -elseif senstype(input, 'bti') - % all 4D-BTi MEG channels start with "A" - % all 4D-BTi reference channels start with M or G - % all 4D-BTi EEG channels start with E - type(strncmp('A', label, 1)) = {'meg'}; - type(strncmp('M', label, 1)) = {'refmag'}; - type(strncmp('G', label, 1)) = {'refgrad'}; - - - if isfield(grad, 'tra') - selchan = find(strcmp('mag', type)); - for k = 1:length(selchan) - ncoils = length(find(grad.tra(selchan(k),:)==1)); - if ncoils==1, - type{selchan(k)} = 'megmag'; - elseif ncoils==2, - type{selchan(k)} = 'meggrad'; - end - end - end - - % This is to allow setting additional channel types based on the names - if isheader && issubfield(hdr, 'orig.channel_data.chan_label') - tmplabel = {hdr.orig.channel_data.chan_label}; - tmplabel = tmplabel(:); - else - tmplabel = label; % might work - end - sel = strmatch('unknown', type, 'exact'); - if ~isempty(sel) - type(sel)= chantype(tmplabel(sel)); - sel = strmatch('unknown', type, 'exact'); - if ~isempty(sel) - type(sel(strncmp('E', label(sel), 1))) = {'eeg'}; - end - end - -elseif senstype(input, 'itab') && isheader - sel = ([hdr.orig.ch.type]==0); - type(sel) = {'unknown'}; - sel = ([hdr.orig.ch.type]==1); - type(sel) = {'unknown'}; - sel = ([hdr.orig.ch.type]==2); - type(sel) = {'megmag'}; - sel = ([hdr.orig.ch.type]==8); - type(sel) = {'megref'}; - sel = ([hdr.orig.ch.type]==16); - type(sel) = {'aux'}; - sel = ([hdr.orig.ch.type]==64); - type(sel) = {'digital'}; - % not all channels are actually processed by fieldtrip, so only return - % the types fopr the ones that read_header and read_data return - type = type(hdr.orig.chansel); - -elseif senstype(input, 'itab') && isgrad - % the channels have to be identified based on their name alone - sel = myregexp('^MAG_[0-9][0-9][0-9]$', label); - type(sel) = {'megmag'}; - sel = myregexp('^REF_[0-9][0-9][0-9]$', label); - type(sel) = {'megref'}; - sel = myregexp('^AUX.*$', label); - type(sel) = {'aux'}; - -elseif senstype(input, 'itab') && islabel - % the channels have to be identified based on their name alone - sel = myregexp('^MAG_[0-9][0-9][0-9]$', label); - type(sel) = {'megmag'}; - sel = myregexp('^REF_[0-9][0-9][0-9]$', label); - type(sel) = {'megref'}; - sel = myregexp('^AUX.*$', label); - type(sel) = {'aux'}; - -elseif senstype(input, 'eeg') && islabel - % use an external helper function to define the list with EEG channel names - type(match_str(label, senslabel(senstype(label)))) = {'eeg'}; - -elseif senstype(input, 'eeg') && isheader - % use an external helper function to define the list with EEG channel names - type(match_str(hdr.label, senslabel(senstype(hdr)))) = {'eeg'}; - -elseif senstype(input, 'plexon') && isheader - % this is a complete header that was read from a Plexon *.nex file using read_plexon_nex - for i=1:numchan - switch hdr.orig.VarHeader(i).Type - case 0 - type{i} = 'spike'; - case 1 - type{i} = 'event'; - case 2 - type{i} = 'interval'; % Interval variables? - case 3 - type{i} = 'waveform'; - case 4 - type{i} = 'population'; % Population variables ? - case 5 - type{i} = 'analog'; - otherwise - % keep the default 'unknown' type - end - end - -end % senstype - -% if possible, set additional types based on channel labels -label2type = { - {'ecg', 'ekg'}; - {'emg'}; - {'eog', 'heog', 'veog'}; - {'lfp'}; - {'eeg'}; - }; -for i = 1:numel(label2type) - for j = 1:numel(label2type{i}) - type(intersect(strmatch(label2type{i}{j}, lower(label)),... - strmatch('unknown', type, 'exact'))) = label2type{i}(1); - end -end - -if nargin>1 - % return a boolean vector - if isequal(desired, 'meg') || isequal(desired, 'ref') - type = strncmp(desired, type, 3); - else - type = strcmp(desired, type); - end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% helper function -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function match = myregexp(pat, list) -match = false(size(list)); -for i=1:numel(list) - match(i) = ~isempty(regexp(list{i}, pat, 'once')); -end - - diff --git a/external/fileio/private/convert_units.m b/external/fileio/private/convert_units.m deleted file mode 100644 index eb1366b..0000000 --- a/external/fileio/private/convert_units.m +++ /dev/null @@ -1,217 +0,0 @@ -function [obj] = convert_units(obj, target); - -% CONVERT_UNITS changes the geometrical dimension to the specified SI unit. -% The units of the input object is determined from the structure field -% object.unit, or is estimated based on the spatial extend of the structure, -% e.g. a volume conduction model of the head should be approximately 20 cm large. -% -% Use as -% [object] = convert_units(object, target) -% -% The following input objects are supported -% simple dipole position -% electrode definition -% gradiometer array definition -% volume conductor definition -% dipole grid definition -% anatomical mri -% -% Possible target units are 'm', 'dm', 'cm ' or 'mm'. -% -% See READ_VOL, READ_SENS - -% Copyright (C) 2005-2008, Robert Oostenveld -% -% $Log: convert_units.m,v $ -% Revision 1.8 2009/03/26 14:57:04 roboos -% moved the unit estimation to a seperate function -% -% Revision 1.7 2009/03/11 11:28:24 roboos -% detect as mm for very wide anatomical MRIs (happens at the fcdc with the ctf MRIs) -% -% Revision 1.6 2009/02/05 10:20:35 roboos -% added bemcp as volume type -% -% Revision 1.5 2009/01/08 17:18:45 roboos -% fixed bug mom->pos for source structures -% added unit detection for volumes with a transform and a dim -% -% Revision 1.4 2008/07/21 20:29:22 roboos -% small change in output on screen -% -% Revision 1.3 2008/04/14 20:53:58 roboos -% added detection for headshape and/or fiducials -% fixed bug in scaling of fiducials -% -% Revision 1.2 2008/04/14 19:29:58 roboos -% cleanded up code and added autodetection based on geometrical size of object -% changed interface, no forced input type is possible -% changed from dos to unix -% -% Revision 1.1 2005/03/03 11:01:39 roboos -% already old (and unused) implementation, but sofar this function was not included in CVS -% - -% This function consists of three parts: -% 1) determine the input units -% 2) determine the requested scaling factor to obtain the output units -% 3) try to apply the scaling to the known geometrical elements in the input object - -% determine the unit-of-dimension of the input object -if isfield(obj, 'unit') - % use the units specified in the object - unit = obj.unit; -else - % try to estimate the units from the object - type = voltype(obj); - if ~strcmp(type, 'unknown') - switch type - case 'infinite' - % there is nothing to do to convert the units - unit = target; - - case 'singlesphere' - size = obj.r; - - case 'multisphere' - size = median(obj.r); - - case 'concentric' - size = max(obj.r); - - case 'nolte' - size = norm(range(obj.bnd.pnt)); - - case {'bem' 'dipoli' 'bemcp' 'asa' 'avo'} - size = norm(range(obj.bnd(1).pnt)); - - otherwise - error('cannot determine geometrical units of volume conduction model'); - end % switch - - % determine the units by looking at the size - unit = estimate_units(size); - - elseif senstype(obj, 'meg') - size = norm(range(obj.pnt)); - unit = estimate_units(size); - - elseif senstype(obj, 'eeg') - size = norm(range(obj.pnt)); - unit = estimate_units(size); - - elseif isfield(obj, 'pnt') && ~isempty(obj.pnt) - size = norm(range(obj.pnt)); - unit = estimate_units(size); - - elseif isfield(obj, 'pos') && ~isempty(obj.pos) - size = norm(range(obj.pos)); - unit = estimate_units(size); - - elseif isfield(obj, 'transform') && ~isempty(obj.transform) - % construct the corner points of the voxel grid in head coordinates - xi = 1:obj.dim(1); - yi = 1:obj.dim(2); - zi = 1:obj.dim(3); - pos = [ - xi( 1) yi( 1) zi( 1) - xi( 1) yi( 1) zi(end) - xi( 1) yi(end) zi( 1) - xi( 1) yi(end) zi(end) - xi(end) yi( 1) zi( 1) - xi(end) yi( 1) zi(end) - xi(end) yi(end) zi( 1) - xi(end) yi(end) zi(end) - ]; - pos = warp_apply(obj.transform, pos); - size = norm(range(pos)); - unit = estimate_units(size); - - elseif isfield(obj, 'fid') && isfield(obj.fid, 'pnt') && ~isempty(obj.fid.pnt) - size = norm(range(obj.fid.pnt)); - unit = estimate_units(size); - - else - error('cannot determine geometrical units'); - - end % recognized type of volume conduction model or sensor array -end % determine input units - -if nargin<2 - % just remember the units in the output and return - obj.unit = unit; - return -elseif strcmp(unit, target) - % no conversion is needed - obj.unit = unit; - return -end - -% give some information about the conversion -fprintf('converting units from ''%s'' to ''%s''\n', unit, target) - -if strcmp(unit, 'm') - unit2meter = 1; -elseif strcmp(unit, 'dm') - unit2meter = 0.1; -elseif strcmp(unit, 'cm') - unit2meter = 0.01; -elseif strcmp(unit, 'mm') - unit2meter = 0.001; -end - -% determine the unit-of-dimension of the output object -if strcmp(target, 'm') - meter2target = 1; -elseif strcmp(target, 'dm') - meter2target = 10; -elseif strcmp(target, 'cm') - meter2target = 100; -elseif strcmp(target, 'mm') - meter2target = 1000; -end - -% combine the units into one scaling factor -scale = unit2meter * meter2target; - -% volume conductor model -if isfield(obj, 'r'), obj.r = scale * obj.r; end -if isfield(obj, 'o'), obj.o = scale * obj.o; end -if isfield(obj, 'bnd'), for i=1:length(obj.bnd), obj.bnd(i).pnt = scale * obj.bnd(i).pnt; end, end - -% gradiometer array -if isfield(obj, 'pnt1'), obj.pnt1 = scale * obj.pnt1; end -if isfield(obj, 'pnt2'), obj.pnt2 = scale * obj.pnt2; end -if isfield(obj, 'prj'), obj.prj = scale * obj.prj; end - -% gradiometer array, electrode array, head shape or dipole grid -if isfield(obj, 'pnt'), obj.pnt = scale * obj.pnt; end - -% fiducials -if isfield(obj, 'fid') && isfield(obj.fid, 'pnt'), obj.fid.pnt = scale * obj.fid.pnt; end - -% dipole grid -if isfield(obj, 'pos'), obj.pos = scale * obj.pos; end - -% anatomical MRI or functional volume -if isfield(obj, 'transform'), - H = diag([scale scale scale 1]); - obj.transform = H * obj.transform; -end - -% remember the unit -obj.unit = target; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION -% Use as -% r = range(x) -% or you can also specify the dimension along which to look by -% r = range(x, dim) -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function r = range(x, dim) -if nargin==1 - r = max(x) - min(x); -else - r = max(x, [], dim) - min(x, [], dim); -end diff --git a/external/fileio/private/cstructdecode.m b/external/fileio/private/cstructdecode.m deleted file mode 100644 index ff8e289..0000000 --- a/external/fileio/private/cstructdecode.m +++ /dev/null @@ -1,87 +0,0 @@ -function varargout = cstructdecode(buf, varargin); - -% CSTRUCTDECODE decodes a structure from a uint8 buffer -% -% See READ_NEURALYNX_NEV for an example - -% Copyright (C) 2007, Robert Oostenveld -% -% $Log: cstructdecode.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.2 2008/02/18 13:36:40 roboos -% added single and double -% -% Revision 1.1 2007/12/18 16:14:38 roboos -% new implementation -% - -if ~isa(buf, 'uint8') - error('incorrect type of input data, should be uint8'); -end - -nbytes = numel(buf); -nfield = length(varargin); - -wordsize = zeros(1,nfield); -for i=1:nfield - switch varargin{i} - case 'uint8' - wordsize(i) = 1; - case 'int8' - wordsize(i) = 1; - case 'uint16' - wordsize(i) = 2; - case 'int16' - wordsize(i) = 2; - case 'uint32' - wordsize(i) = 4; - case 'int32' - wordsize(i) = 4; - case 'uint64' - wordsize(i) = 8; - case 'int64' - wordsize(i) = 8; - case {'float32' 'single'} - varargin{i} = 'single'; - wordsize(i) = 4; - case {'float64' 'double'} - varargin{i} = 'double'; - wordsize(i) = 8; - otherwise - if strncmp(varargin{i}, 'char', 4) - if length(varargin{i})>4 - % assume a string like 'char128' which means 128 characters - wordsize(i) = str2num(varargin{i}(5:end)); - varargin{i} = 'char'; - else - wordsize(i) = 1; - end - else - error('incorrect type specification'); - end - end -end - -pklen = sum(wordsize); -pknum = nbytes/sum(wordsize); - -buf = reshape(buf, pklen, pknum); - -for i=1:nfield - rowbeg = sum(wordsize(1:(i-1)))+1; - rowend = sum(wordsize(1:(i-0)))+0; - sel = buf(rowbeg:rowend,:); - if strcmp(varargin{i}, 'char') - varargout{i} = char(sel)'; - else - varargout{i} = typecast(sel(:), varargin{i}); - end -end - diff --git a/external/fileio/private/deblank2.m b/external/fileio/private/deblank2.m deleted file mode 100644 index dfda927..0000000 --- a/external/fileio/private/deblank2.m +++ /dev/null @@ -1,18 +0,0 @@ -function [out] = deblank2(in) - -% DEBLANK2 removes all blanks from the beginning and end of a char array -% -% out = deblank2(in) - -% Copyright (C) 2002-2007, Robert Oostenveld -% -% $Log: deblank2.m,v $ -% Revision 1.3 2007/12/20 19:08:06 roboos -% changed some whitespace -% -% Revision 1.2 2003/03/17 10:37:28 roberto -% improved general help comments and added copyrights -% - -out = fliplr(deblank(fliplr(deblank(in)))); - diff --git a/external/fileio/private/estimate_units.m b/external/fileio/private/estimate_units.m deleted file mode 100644 index 2749632..0000000 --- a/external/fileio/private/estimate_units.m +++ /dev/null @@ -1,37 +0,0 @@ -function unit = estimate_units(size) - -% ESTIMATE_UNITS tries to determine the units of a geometrical object by -% looking at its size and by relating this to the size of the human -% brain. -% -% Use as -% unit = estimate_units(size) -% -% This function will return one of the following strings -% 'm' -% 'dm' -% 'cm' -% 'mm' - -% Copyright (C) 2009, Robert Oostenveld -% -% $Log: estimate_units.m,v $ -% Revision 1.1 2009/03/26 14:57:04 roboos -% moved the unit estimation to a seperate function -% - -% do some magic based on the size -unit = {'m', 'dm', 'cm', 'mm'}; -indx = round(log10(size)+2-0.2); - -if indx>length(unit) - indx = length(unit); - warning('assuming that the units are "%s"', unit{indx}); -end - -if indx<1 - indx = 1; - warning('assuming that the units are "%s"', unit{indx}); -end - -unit = unit{indx}; diff --git a/external/fileio/private/fetch_data.m b/external/fileio/private/fetch_data.m deleted file mode 100644 index e19c77d..0000000 --- a/external/fileio/private/fetch_data.m +++ /dev/null @@ -1,99 +0,0 @@ -function [dat] = fetch_data(data, varargin) - -% FETCH_DATA mimics the behaviour of READ_DATA, but for a FieldTrip -% raw data structure instead of a file on disk. -% -% Use as -% [event] = fetch_data(data, ...) -% -% See also READ_DATA, FETCH_HEADER, FETCH_EVENT - -% Copyright (C) 2008, Esther Meeuwissen -% -% $Log: fetch_data.m,v $ -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.2 2008/09/29 21:12:39 roboos -% cleaned up the code from Esther, added copyrights, updated documentation -% - -% check whether input is data -data = checkdata(data, 'datatype', 'raw'); - -% get the options -hdr = keyval('header', varargin); -begsample = keyval('begsample', varargin); -endsample = keyval('endsample', varargin); -chanindx = keyval('chanindx', varargin); - -if isempty(hdr) - hdr = fetch_header(data); -end - -if isempty(begsample) || isempty(endsample) - error('begsample and endsample must be specified'); -end - -if isempty(chanindx) - chanindx = 1:hdr.nChans; -end - -% get trial definition according to original data file -trl = findcfg(data.cfg, 'trl'); -trlnum = length(data.trial); -trllen = zeros(trlnum,1); -for trllop=1:trlnum - trllen(trllop) = size(data.trial{trllop},2); -end - -% check whether data.trial is consistent with trl -if size(trl,1)~=length(data.trial) - error('trial definition is not internally consistent') -elseif any(trllen~=(trl(:,2)-trl(:,1)+1)) - error('trial definition is not internally consistent') -end - -minchan = min(chanindx); -maxchan = max(chanindx); -if minchan<1 || maxchan>hdr.nChans - error('selected channels are not present in the data') -end - -% these are for bookkeeping -maxsample = max(trl(:,2)); -count = zeros(1, maxsample); -trialnum = NaN(1, maxsample); -samplenum = NaN(1, maxsample); - -for trllop=1:trlnum - % make vector with 0= no sample of old data, 1= one sample of old data, 2= two samples of old data, etc - count(trl(trllop,1):trl(trllop,2)) = count(trl(trllop,1):trl(trllop,2)) + 1; - % make vector with 1's if samples belong to trial 1, 2's if samples belong to trial 2 etc. overlap/ no data --> Nan - trialnum(trl(trllop,1):trl(trllop,2)) = trllop; - % make samplenum vector with samplenrs for each sample in the old trials - samplenum(trl(trllop,1):trl(trllop,2)) = 1:trllen(trllop); -end - -% overlap --> NaN -trialnum(count>1) = NaN; -samplenum(count>1) = NaN; - -% make a subselection for the desired samples -count = count(begsample:endsample); -trialnum = trialnum(begsample:endsample); -samplenum = samplenum(begsample:endsample); - -% check if all samples are present and are not present twice or more -if any(count==0) - error('not all requested samples are present in the data'); -elseif any(count>1) - error('some of the requested samples occur twice in the data'); -end - -% construct the output data array -dat = zeros(length(chanindx), length(samplenum)); -for smplop=1:length(samplenum) - dat(:, smplop) = data.trial{trialnum(smplop)}(chanindx,samplenum(smplop)); -end - diff --git a/external/fileio/private/fetch_event.m b/external/fileio/private/fetch_event.m deleted file mode 100644 index 12d1c22..0000000 --- a/external/fileio/private/fetch_event.m +++ /dev/null @@ -1,26 +0,0 @@ -function [event]=fetch_event(data) - -% FETCH_EVENT mimics the behaviour of READ_EVENT, but for a FieldTrip -% raw data structure instead of a file on disk. -% -% Use as -% [event] = fetch_event(data) -% -% See also READ_EVENT, FETCH_HEADER, FETCH_DATA - -% Copyright (C) 2008, Esther Meeuwissen -% -% $Log: fetch_event.m,v $ -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.2 2008/09/29 21:12:39 roboos -% cleaned up the code from Esther, added copyrights, updated documentation -% - -% check whether input is data -data = checkdata(data, 'datatype', 'raw'); - -% locate the event structure -event = findcfg(data.cfg, 'event'); - diff --git a/external/fileio/private/fetch_header.m b/external/fileio/private/fetch_header.m deleted file mode 100644 index bb6cb00..0000000 --- a/external/fileio/private/fetch_header.m +++ /dev/null @@ -1,60 +0,0 @@ -function [hdr] = fetch_header(data) - -% FETCH_HEADER mimics the behaviour of READ_HEADER, but for a FieldTrip -% raw data structure instead of a file on disk. -% -% Use as -% [event] = fetch_header(data) -% -% See also READ_HEADER, FETCH_DATA, FETCH_EVENT - -% Copyright (C) 2008, Esther Meeuwissen -% -% $Log: fetch_header.m,v $ -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.2 2008/09/29 21:12:39 roboos -% cleaned up the code from Esther, added copyrights, updated documentation -% - -% check whether input is data -data = checkdata(data, 'datatype', 'raw'); - -% get trial definition according to original data file -trl = findcfg(data.cfg, 'trl'); -trlnum = length(data.trial); -trllen = zeros(trlnum,1); -for trllop=1:trlnum - trllen(trllop) = size(data.trial{trllop},2); -end - -% check whether data.trial is consistent with trl -if size(trl,1)~=length(data.trial) - error('trial definition is not internally consistent') -elseif any(trllen~=(trl(:,2)-trl(:,1)+1)) - error('trial definition is not internally consistent') -end - -% fill in hdr.nChans -hdr.nChans = length(data.label); - -% fill in hdr.label -hdr.label = data.label; - -% fill in hdr.Fs (sample frequency) -hdr.Fs = data.fsample; - -% determine hdr.nSamples, hdr.nSamplesPre, hdr.nTrials -% always pretend that it is continuous data -hdr.nSamples = max(trl(:,2)); -hdr.nSamplesPre = 0; -hdr.nTrials = 1; - -% fill in hdr.grad or hdr.elec -if isfield(data, 'grad') - hdr.grad=data.grad; -elseif isfield(data, 'elec') - hdr.elec=data.elec; -end - diff --git a/external/fileio/private/fif2grad.m b/external/fileio/private/fif2grad.m deleted file mode 100644 index 51a6b39..0000000 --- a/external/fileio/private/fif2grad.m +++ /dev/null @@ -1,76 +0,0 @@ -function grad = fif2grad(filename); - -% FIF2GRAD constructs a gradiometer definition from a Neuromag *.fif file -% The resulting gradiometer definition can be used by Fieldtrip for forward -% and inverse computations. -% -% Use as -% grad = fif2grad(filename); -% -% See also READ_HEADER, CTF2GRAD, BTI2GRAD - -% Copyright (C) 2004, Joachim Gross -% -% $Log: fif2grad.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.3 2008/05/15 13:20:35 roboos -% updated documentation -% -% Revision 1.2 2007/03/15 12:44:42 roboos -% added try-catch to deal with fif files that do not contain coil information (code by chrhes) -% -% Revision 1.1 2006/08/31 13:32:11 roboos -% moved from fieldtrip to fileio module -% -% Revision 1.1 2004/09/20 13:53:04 roboos -% moved gradiometer definition for Neuromag fif files into separate function -% - -% this try-catch construct ensures that missing gradiometer information is -% handeled in a "graceful" way -grad = []; -try - megmodel('head',[0 0 0],filename); - [n,s,t]=chaninfo; - [TY,NA]=chaninfo('type'); - nCoils=sum(TY+1); % number of coils - nSensors=length(TY); % number of sensors - grad.pnt=zeros(nCoils,3); - grad.ori=zeros(nCoils,3); - grad.tra=zeros(nSensors,nCoils); - grad.unit='cm'; - % define coils - kCoil=1; - for k=1:nSensors, - if (TY(k)==0), %magnetometer - grad.pnt(kCoil,:)=100*(t{k}(1:3,4)); - grad.ori(kCoil,:)=t{k}(1:3,3); - grad.tra(k,kCoil)=1; - kCoil=kCoil+1; - grad.label{k}=deblank(s(k,:)); - elseif (TY(k) == 1), %planar gradiometer - grad.pnt(kCoil,:)=100*(t{k}(1:3,4)-0.008*t{k}(1:3,1)); % multiply with 100 to get cm - grad.ori(kCoil,:)=t{k}(1:3,3); - grad.tra(k,kCoil)=1; - kCoil=kCoil+1; - grad.pnt(kCoil,:)=100*(t{k}(1:3,4)+0.008*t{k}(1:3,1)); - grad.ori(kCoil,:)=t{k}(1:3,3); - grad.tra(k,kCoil)=-1; - kCoil=kCoil+1; - grad.label{k}=deblank(s(k,:)); - else - error('unknown sensor type'); - end - end -catch - warning(['gradiometer information could not be extracted from file']); - warning(['returning an empty grad structure']); - return; -end diff --git a/external/fileio/private/filetype.m b/external/fileio/private/filetype.m deleted file mode 100644 index 56f22ef..0000000 --- a/external/fileio/private/filetype.m +++ /dev/null @@ -1,1056 +0,0 @@ -function [type] = filetype(filename, desired, varargin) - -% FILETYPE determines the filetype of many EEG/MEG/MRI data files by -% looking at the name, extension and optionally (part of) its contents. -% It tries to determine the global type of file (which usually -% corresponds to the manufacturer, the recording system or to the -% software used to create the file) and the particular subtype (e.g. -% continuous, average). -% -% Use as -% type = filetype(filename) -% type = filetype(dirname) -% -% This gives you a descriptive string with the data type, and can be -% used in a switch-statement. The descriptive string that is returned -% usually is something like 'XXX_YYY'/ where XXX refers to the -% manufacturer and YYY to the type of the data. -% -% Alternatively, use as -% flag = filetype(filename, type) -% flag = filetype(dirname, type) -% This gives you a boolean flag (0 or 1) indicating whether the file -% is of the desired type, and can be used to check whether the -% user-supplied file is what your subsequent code expects. -% -% Alternatively, use as -% flag = filetype(dirlist, type) -% where the dirlist contains a list of files contained within one -% directory. This gives you a boolean vector indicating for each file -% whether it is of the desired type. -% -% Most filetypes of the following manufacturers and/or software programs are recognized -% - VSMMedtech/CTF -% - Elektra/Neuromag -% - Yokogawa -% - 4D/BTi -% - EDF -% - Neuroscan -% - Analyse -% - EEProbe -% - BrainVision -% - BESA -% - Curry -% - ASA -% - LORETA -% - Analyze/SPM -% - MINC -% - AFNI -% - Neuralynx -% - Plexon -% -% See also READ_XXX_YYY where XXX=manufacturer and YYY=subtype - -% Copyright (C) 2003-2007 Robert Oostenveld -% -% $Log: filetype.m,v $ -% Revision 1.101 2009/10/16 07:31:18 roboos -% renamed chieti into itab for consistency with other formats -% -% Revision 1.100 2009/10/13 10:12:51 roboos -% added support for chieti_raw -% -% Revision 1.99 2009/10/07 09:48:00 jansch -% added some lines to be able to deal with memory mapped files -% -% Revision 1.98 2009/07/07 10:38:38 roboos -% added header check for dicom -% -% Revision 1.97 2009/05/06 15:42:06 roboos -% also remember/check previous directory and don't do filetype caching in case type=unknown -% -% Revision 1.96 2009/04/01 06:53:23 roboos -% implemented caching for the type detection in case the same input is given multiple times -% this uses a persistent variable -% renamed the internal variable "ftype" into "type" -% removed the second output argument with the details, because sofar they have never been used in fieldtrip and therefore don't seem needed -% -% Revision 1.95 2009/02/12 11:47:23 vlalit -% Added support for neuro prax (eldith) EEG format based on functions from the manufacturer -% used with permission from the company's representative Mr. Klaus Schellhorn. -% -% Revision 1.94 2009/02/09 14:21:00 roboos -% added inport of micromed_trc data -% -% Revision 1.93 2009/01/07 10:37:55 roboos -% changed description for neuralynx_sdma, should not have any functional consequences -% -% Revision 1.92 2008/12/24 10:33:48 roboos -% fixed header for mbfys_ama -% -% Revision 1.91 2008/12/19 14:39:25 marvger -% added support for udp, tcp and fifo -% -% Revision 1.90 2008/12/18 11:24:30 vlalit -% Fixed detection of spike6 matlab file -% -% Revision 1.89 2008/12/09 16:50:41 roboos -% disabled detection of ced_spike6mat, because it contains an error. The error should be fixed by Vladimir. -% -% Revision 1.88 2008/11/28 10:24:24 roboos -% added ctf mri version 4, thanks to Ivar -% -% Revision 1.87 2008/11/12 16:50:26 roboos -% improved detection for BCI2000 -% -% Revision 1.86 2008/11/02 10:38:44 roboos -% added another check for ctf_ds (to deal with '.') -% -% Revision 1.85 2008/10/28 16:08:14 roboos -% additional check on yokogawa raw (first 4 bytes should be zero) -% -% Revision 1.84 2008/07/24 08:43:40 roboos -% added nimh_cortex -% -% Revision 1.83 2008/07/09 12:16:38 roboos -% added mclust_t -% -% Revision 1.82 2008/07/01 13:35:25 roboos -% moved long sequence for mat files onto single line (2x) -% -% Revision 1.81 2008/06/18 08:24:33 roboos -% added support for BCI2000 -% -% Revision 1.80 2008/05/27 16:12:26 vlalit -% Changed type name to ced_spike6mat -% -% Revision 1.79 2008/05/27 11:58:20 vlalit -% Added support of Matlab files exported from Spike 6 -% -% Revision 1.78 2008/05/21 13:31:34 vlalit -% Added check for existence of the file before the other spmeeg checks. -% -% Revision 1.77 2008/05/09 17:04:41 vlalit -% Added even more stringent criteria for recognition of SPM EEG mat files -% -% Revision 1.76 2008/05/06 14:36:23 roboos -% Added readers for SPM5 and SPM8 EEG formats (fix cvs conflict between jansch and vlalit) -% -% Revision 1.75 2008/05/06 12:00:38 jansch -% changed strcmp into strfind for 4d-data -% -% Revision 1.74 2008/05/06 09:24:36 jansch -% removed check for . in filename of 4D-files. necessary to read in data that -% are not DC-recorded. -% -% Revision 1.72 2008/04/21 11:50:51 roboos -% added support for egi_sbin, thanks to Joseph Dien -% -% Revision 1.71 2008/04/18 14:08:03 roboos -% added eeglab_set -% -% Revision 1.70 2008/04/11 12:09:18 roboos -% added polhemus_fil -% -% Revision 1.69 2008/03/04 11:14:26 roboos -% added neuralynx_nst -% -% Revision 1.68 2008/02/19 10:07:34 roboos -% replaced tcpsocket with buffer -% -% Revision 1.67 2008/01/31 20:10:22 roboos -% It is necessary to identify when it is necessary to execute the new -% read_4d_hdr.m function. To achieve this an extra IF statement was -% added from line 312. This statement checks for a passed filename -% which has no extension (not the case for .xyz or .m4d) and that the -% second to fourth characters in the filename are ,rf. If both of -% these conditions are met then the filetype and manufacturer are set -% to 4d. [thanks to Gavin] -% -% Revision 1.66 2008/01/25 07:41:57 roboos -% moved some code, no functional change -% -% Revision 1.65 2008/01/15 08:12:30 roboos -% more strict test for ctf_ds -% -% Revision 1.64 2007/12/19 07:17:26 roboos -% removed ftc, added txt -% -% Revision 1.63 2007/12/17 16:14:44 roboos -% added neuralynx_bin -% -% Revision 1.62 2007/12/17 08:25:04 roboos -% added nexstim_nxe -% -% Revision 1.61 2007/12/12 16:48:20 roboos -% deal with case of extension for nev/Nev -% fixed bug: correctly locate the events.nev file in the dataset directory -% -% Revision 1.60 2007/12/12 14:39:26 roboos -% added riff_wave -% -% Revision 1.59 2007/12/06 17:05:54 roboos -% added fcdc_ftc, only on file extension -% -% Revision 1.58 2007/10/25 12:47:31 roboos -% added *.nrd as neuralynx_dma, not sure yet whether this is correct -% -% Revision 1.57 2007/10/16 12:35:08 roboos -% implemented fcdc_global -% -% Revision 1.56 2007/10/15 16:02:46 roboos -% added rfb://@: -% -% Revision 1.55 2007/10/04 11:55:40 roboos -% added the various spass file formats -% -% Revision 1.54 2007/09/13 09:46:51 roboos -% adedd ctf_wts and svl -% -% Revision 1.53 2007/08/06 09:07:33 roboos -% added 4d_hs -% -% Revision 1.52 2007/07/27 12:17:47 roboos -% added ctf_shm -% -% Revision 1.51 2007/07/04 13:20:51 roboos -% added support for egi_egis/egia, thanks to Joseph Dien -% -% Revision 1.50 2007/06/06 07:10:16 roboos -% changed detection of BCI streams into using URI scheme -% changed deterction of BESA source waveform files -% -% Revision 1.49 2007/06/04 18:24:49 roboos -% added nifti -% -% Revision 1.48 2007/05/31 09:13:28 roboos -% added tcpsocket ans serial port -% -% Revision 1.47 2007/05/15 14:59:54 roboos -% try to separate besa *.dat from brainvision *.dat -% -% Revision 1.46 2007/04/25 15:27:28 roboos -% rmoved besa_gen, instead added besa_sb (simple binary), which comes with the *.gen or *.generic ascii header file -% -% Revision 1.45 2007/03/21 17:21:30 roboos -% remove . and .. from the file listing in case of a directory as input -% removed neuralynx_nte, the correct extension is *.nts -% added header check to neuralynx_nts -% implemented subfunction most, c.f. any -% swiched from using any(...) to most(...) for determining content of dataset directory -% implemented plexon_ds for directory with nex files in it -% made some additional small changes -% -% Revision 1.44 2007/03/19 16:52:37 roboos -% added neuralynx_nte -% -% Revision 1.43 2007/01/09 09:29:25 roboos -% small change -% -% Revision 1.42 2007/01/04 08:12:00 roboos -% fixed bug for besa_avr, renamed an incorrect tag into plexon_plx -% - -% these are for remembering the type on subsequent calls with the same input arguments -persistent previous_argin previous_argout previous_pwd - -if nargin<2 - % ensure that all input arguments are defined - desired = []; -end - -current_argin = {filename, desired, varargin{:}}; -current_pwd = pwd; -if isequal(current_argin, previous_argin) && isequal(current_pwd, previous_pwd) - % don't do the detection again, but return the previous value from cache - type = previous_argout{1}; - return -end - -if strcmp(class(filename), 'memmapfile'), - filename = filename.Filename; -end - -% % get the optional arguments -% checkheader = keyval('checkheader', varargin); if isempty(checkheader), checkheader=1; end -% -% if ~checkheader -% % assume that the header is always ok, e.g when the file does not yet exist -% % this replaces the normal function with a function that always returns true -% filetype_check_header = @filetype_true; -% end - -if iscell(filename) - % perform the test for each filename, return a boolean vector - type = false(size(filename)); - for i=1:length(filename) - if strcmp(filename{i}(end), '.') - % do not recurse into this directory or the parent directory - continue - else - type(i) = filetype(filename{i}, desired); - end - end - return -end - -% start with unknown values -type = 'unknown'; -manufacturer = 'unknown'; -content = 'unknown'; - -[p, f, x] = fileparts(filename); - -if isdir(filename) - % the directory listing is needed below - ls = dir(filename); - % remove the parent directory and the directory itself from the list - ls = ls(~strcmp({ls.name}, '.')); - ls = ls(~strcmp({ls.name}, '..')); - for i=1:length(ls) - % make sure that the directory listing includes the complete path - ls(i).name = fullfile(filename, ls(i).name); - end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% start determining the filetype -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% these are some streams for asynchronous BCI -if filetype_check_uri(filename, 'fifo') - type = 'fcdc_fifo'; - manufacturer = 'F.C. Donders Centre'; - content = 'stream'; -elseif filetype_check_uri(filename, 'buffer') - type = 'fcdc_buffer'; - manufacturer = 'F.C. Donders Centre'; - content = 'stream'; -elseif filetype_check_uri(filename, 'mysql') - type = 'fcdc_mysql'; - manufacturer = 'F.C. Donders Centre'; - content = 'stream'; -elseif filetype_check_uri(filename, 'tcp') - type = 'fcdc_tcp'; - manufacturer = 'F.C. Donders Centre'; - content = 'stream'; -elseif filetype_check_uri(filename, 'udp') - type = 'fcdc_udp'; - manufacturer = 'F.C. Donders Centre'; - content = 'stream'; -elseif filetype_check_uri(filename, 'rfb') - type = 'fcdc_rfb'; - manufacturer = 'F.C. Donders Centre'; - content = 'stream'; -elseif filetype_check_uri(filename, 'serial') - type = 'fcdc_serial'; - manufacturer = 'F.C. Donders Centre'; - content = 'stream'; -elseif filetype_check_uri(filename, 'global') - type = 'fcdc_global'; - manufacturer = 'F.C. Donders Centre'; - content = 'global variable'; -elseif filetype_check_uri(filename, 'shm') - type = 'ctf_shm'; - manufacturer = 'CTF'; - content = 'real-time shared memory buffer'; - - % known CTF file types -elseif isdir(filename) && filetype_check_extension(filename, '.ds') && exist(fullfile(filename, [f '.res4'])) - type = 'ctf_ds'; - manufacturer = 'CTF'; - content = 'MEG dataset'; -elseif isdir(filename) && ~isempty(dir(fullfile(filename, '*.res4'))) && ~isempty(dir(fullfile(filename, '*.meg4'))) - type = 'ctf_ds'; - manufacturer = 'CTF'; - content = 'MEG dataset'; -elseif filetype_check_extension(filename, '.res4') && (filetype_check_header(filename, 'MEG41RS') || filetype_check_header(filename, 'MEG42RS') || filetype_check_header(filename, 'MEG4RES')) - type = 'ctf_res4'; - manufacturer = 'CTF'; - content = 'MEG/EEG header information'; -elseif filetype_check_extension(filename, '.meg4') && filetype_check_header(filename, 'MEG41CP') - type = 'ctf_meg4'; - manufacturer = 'CTF'; - content = 'MEG/EEG'; -elseif filetype_check_extension(filename, '.mrk') && filetype_check_header(filename, 'PATH OF DATASET:') - type = 'ctf_mrk'; - manufacturer = 'CTF'; - content = 'marker file'; -elseif filetype_check_extension(filename, '.mri') && filetype_check_header(filename, 'CTF_MRI_FORMAT VER 2.2') - type = 'ctf_mri'; - manufacturer = 'CTF'; - content = 'MRI'; -elseif filetype_check_extension(filename, '.mri') && filetype_check_header(filename, 'CTF_MRI_FORMAT VER 4', 31) - type = 'ctf_mri4'; - manufacturer = 'CTF'; - content = 'MRI'; -elseif filetype_check_extension(filename, '.hdm') - type = 'ctf_hdm'; - manufacturer = 'CTF'; - content = 'volume conduction model'; -elseif filetype_check_extension(filename, '.hc') - type = 'ctf_hc'; - manufacturer = 'CTF'; - content = 'headcoil locations'; -elseif filetype_check_extension(filename, '.shape') - type = 'ctf_shape'; - manufacturer = 'CTF'; - content = 'headshape points'; -elseif filetype_check_extension(filename, '.shape_info') - type = 'ctf_shapeinfo'; - manufacturer = 'CTF'; - content = 'headshape information'; -elseif filetype_check_extension(filename, '.wts') - type = 'ctf_wts'; - manufacturer = 'CTF'; - content = 'SAM coefficients, i.e. spatial filter weights'; -elseif filetype_check_extension(filename, '.svl') - type = 'ctf_svl'; - manufacturer = 'CTF'; - content = 'SAM (pseudo-)statistic volumes'; - - % known Micromed file types -elseif filetype_check_extension(filename, '.trc') && filetype_check_header(filename, '* MICROMED') - type = 'micromed_trc'; - manufacturer = 'Micromed'; - content = 'Electrophysiological data'; - - % known Neuromag file types -elseif filetype_check_extension(filename, '.fif') - type = 'neuromag_fif'; - manufacturer = 'Neuromag'; - content = 'MEG header and data'; -elseif filetype_check_extension(filename, '.bdip') - type = 'neuromag_bdip'; - manufacturer = 'Neuromag'; - content = 'dipole model'; - - % known Yokogawa file types -elseif filetype_check_extension(filename, '.ave') || filetype_check_extension(filename, '.sqd') - type = 'yokogawa_ave'; - manufacturer = 'Yokogawa'; - content = 'averaged MEG data'; -elseif filetype_check_extension(filename, '.con') - type = 'yokogawa_con'; - manufacturer = 'Yokogawa'; - content = 'continuous MEG data'; -elseif filetype_check_extension(filename, '.raw') && filetype_check_header(filename, [char(0) char(0) char(0) char(0)]) - type = 'yokogawa_raw'; - manufacturer = 'Yokogawa'; - content = 'evoked/trialbased MEG data'; -elseif filetype_check_extension(filename, '.mri') && filetype_check_header(filename, '####') % FIXME, not correct - type = 'yokogawa_mri'; - manufacturer = 'Yokogawa'; - content = 'anatomical MRI'; - -elseif filetype_check_extension(filename, '.pdf') && filetype_check_header(filename, 'E|lk') % I am not sure whether this header always applies - type = '4d_pdf'; - manufacturer = '4D/BTI'; - content = 'raw MEG data (processed data file)'; -elseif exist([filename '.m4d'], 'file') && exist([filename '.xyz'], 'file') % these two ascii header files accompany the raw data - type = '4d_pdf'; - manufacturer = '4D/BTI'; - content = 'raw MEG data (processed data file)'; -elseif filetype_check_extension(filename, '.m4d') && exist([filename(1:(end-3)) 'xyz'], 'file') % these come in pairs - type = '4d_m4d'; - manufacturer = '4D/BTI'; - content = 'MEG header information'; -elseif filetype_check_extension(filename, '.xyz') && exist([filename(1:(end-3)) 'm4d'], 'file') % these come in pairs - type = '4d_xyz'; - manufacturer = '4D/BTI'; - content = 'MEG sensor positions'; -elseif isequal(f, 'hs_file') % the filename is "hs_file" - type = '4d_hs'; - manufacturer = '4D/BTI'; - content = 'head shape'; -elseif length(filename)>=4 && ~isempty(strfind(filename,',rf')) - type = '4d'; - manufacturer = '4D/BTi'; - content = ''; - - % known EEProbe file types -elseif filetype_check_extension(filename, '.cnt') && filetype_check_header(filename, 'RIFF') - type = 'eep_cnt'; - manufacturer = 'EEProbe'; - content = 'EEG'; -elseif filetype_check_extension(filename, '.avr') && filetype_check_header(filename, char([38 0 16 0])) - type = 'eep_avr'; - manufacturer = 'EEProbe'; - content = 'ERP'; -elseif filetype_check_extension(filename, '.trg') - type = 'eep_trg'; - manufacturer = 'EEProbe'; - content = 'trigger information'; -elseif filetype_check_extension(filename, '.rej') - type = 'eep_rej'; - manufacturer = 'EEProbe'; - content = 'rejection marks'; - - % known ASA file types -elseif filetype_check_extension(filename, '.elc') - type = 'asa_elc'; - manufacturer = 'ASA'; - content = 'electrode positions'; -elseif filetype_check_extension(filename, '.vol') - type = 'asa_vol'; - manufacturer = 'ASA'; - content = 'volume conduction model'; -elseif filetype_check_extension(filename, '.bnd') - type = 'asa_bnd'; - manufacturer = 'ASA'; - content = 'boundary element model details'; -elseif filetype_check_extension(filename, '.msm') - type = 'asa_msm'; - manufacturer = 'ASA'; - content = 'ERP'; -elseif filetype_check_extension(filename, '.msr') - type = 'asa_msr'; - manufacturer = 'ASA'; - content = 'ERP'; -elseif filetype_check_extension(filename, '.dip') - % FIXME, can also be CTF dipole file - type = 'asa_dip'; - manufacturer = 'ASA'; -elseif filetype_check_extension(filename, '.mri') - % FIXME, can also be CTF mri file - type = 'asa_mri'; - manufacturer = 'ASA'; - content = 'MRI image header'; -elseif filetype_check_extension(filename, '.iso') - type = 'asa_iso'; - manufacturer = 'ASA'; - content = 'MRI image data'; - - % known BCI2000 file types -elseif filetype_check_extension(filename, '.dat') && (filetype_check_header(filename, 'BCI2000') || filetype_check_header(filename, 'HeaderLen=')) - type = 'bci2000_dat'; - manufacturer = 'BCI2000'; - content = 'continuous EEG'; - - % known Neuroscan file types -elseif filetype_check_extension(filename, '.avg') && filetype_check_header(filename, 'Version 3.0') - type = 'ns_avg'; - manufacturer = 'Neuroscan'; - content = 'averaged EEG'; -elseif filetype_check_extension(filename, '.cnt') && filetype_check_header(filename, 'Version 3.0') - type = 'ns_cnt'; - manufacturer = 'Neuroscan'; - content = 'continuous EEG'; -elseif filetype_check_extension(filename, '.eeg') && filetype_check_header(filename, 'Version 3.0') - type = 'ns_eeg'; - manufacturer = 'Neuroscan'; - content = 'epoched EEG'; - -elseif filetype_check_extension(filename, '.eeg') && filetype_check_header(filename, 'V3.0') - type = 'neuroprax_eeg'; - manufacturer = 'eldith GmbH'; - content = 'continuous EEG'; -elseif filetype_check_extension(filename, '.ee_') - type = 'neuroprax_mrk'; - manufacturer = 'eldith GmbH'; - content = 'EEG markers'; - - % known Analyze & SPM file types -elseif filetype_check_extension(filename, '.hdr') - type = 'analyze_hdr'; - manufacturer = 'Mayo Analyze'; - content = 'PET/MRI image header'; -elseif filetype_check_extension(filename, '.img') - type = 'analyze_img'; - manufacturer = 'Mayo Analyze'; - content = 'PET/MRI image data'; -elseif filetype_check_extension(filename, '.mnc') - type = 'minc'; - content = 'MRI image data'; -elseif filetype_check_extension(filename, '.nii') - type = 'nifti'; - content = 'MRI image data'; - - % known LORETA file types -elseif filetype_check_extension(filename, '.lorb') - type = 'loreta_lorb'; - manufacturer = 'old LORETA'; - content = 'source reconstruction'; -elseif filetype_check_extension(filename, '.slor') - type = 'loreta_slor'; - manufacturer = 'sLORETA'; - content = 'source reconstruction'; - - % known AFNI file types -elseif filetype_check_extension(filename, '.brik') || filetype_check_extension(filename, '.BRIK') - type = 'afni_brik'; - content = 'MRI image data'; -elseif filetype_check_extension(filename, '.head') || filetype_check_extension(filename, '.HEAD') - type = 'afni_head'; - content = 'MRI header data'; - - % known BrainVison file types -elseif filetype_check_extension(filename, '.vhdr') - type = 'brainvision_vhdr'; - manufacturer = 'BrainProducts'; - content = 'EEG header'; -elseif filetype_check_extension(filename, '.vmrk') - type = 'brainvision_vmrk'; - manufacturer = 'BrainProducts'; - content = 'EEG markers'; -elseif filetype_check_extension(filename, '.vabs') - type = 'brainvision_vabs'; - manufacturer = 'BrainProducts'; - content = 'Brain Vison Analyzer macro'; -elseif filetype_check_extension(filename, '.eeg') - % FIXME, can also be Neuroscan epoched EEG data - type = 'brainvision_eeg'; - manufacturer = 'BrainProducts'; - content = 'continuous EEG data'; -elseif filetype_check_extension(filename, '.seg') - type = 'brainvision_seg'; - manufacturer = 'BrainProducts'; - content = 'segmented EEG data'; -elseif filetype_check_extension(filename, '.dat') && ~filetype_check_header(filename, 'HeaderLen=') && ~filetype_check_header(filename, 'BESA_SA_IMAGE') && ~(exist(fullfile(p, [f '.gen']), 'file') || exist(fullfile(p, [f '.generic']), 'file')) - % WARNING this is a very general name, it could be exported BrainVision - % data but also a BESA beamformer source reconstruction or BCI2000 - type = 'brainvision_dat'; - manufacturer = 'BrainProducts'; - content = 'exported EEG data'; -elseif filetype_check_extension(filename, '.marker') - type = 'brainvision_marker'; - manufacturer = 'BrainProducts'; - content = 'rejection markers'; - - % known Polhemus file types -elseif filetype_check_extension(filename, '.pos') - type = 'polhemus_pos'; - manufacturer = 'BrainProducts/CTF/Polhemus?'; % actually I don't know whose software it is - content = 'electrode positions'; - - % known Neuralynx file types -elseif filetype_check_extension(filename, '.nev') || filetype_check_extension(filename, '.Nev') - type = 'neuralynx_nev'; - manufacturer = 'Neuralynx'; - content = 'event information'; -elseif filetype_check_extension(filename, '.ncs') && filetype_check_header(filename, '####') - type = 'neuralynx_ncs'; - manufacturer = 'Neuralynx'; - content = 'continuous single channel recordings'; -elseif filetype_check_extension(filename, '.nse') && filetype_check_header(filename, '####') - type = 'neuralynx_nse'; - manufacturer = 'Neuralynx'; - content = 'spike waveforms'; -elseif filetype_check_extension(filename, '.nts') && filetype_check_header(filename, '####') - type = 'neuralynx_nts'; - manufacturer = 'Neuralynx'; - content = 'timestamps only'; -elseif filetype_check_extension(filename, '.nvt') - type = 'neuralynx_nvt'; - manufacturer = 'Neuralynx'; - content = 'video tracker'; -elseif filetype_check_extension(filename, '.nst') - type = 'neuralynx_nst'; - manufacturer = 'Neuralynx'; - content = 'continuous stereotrode recordings'; -elseif filetype_check_extension(filename, '.ntt') - type = 'neuralynx_ntt'; - manufacturer = 'Neuralynx'; - content = 'continuous tetrode recordings'; -elseif strcmpi(f, 'logfile') && strcmpi(x, '.txt') % case insensitive - type = 'neuralynx_log'; - manufacturer = 'Neuralynx'; - content = 'log information in ASCII format'; -elseif ~isempty(strfind(lower(f), 'dma')) && strcmpi(x, '.log') % this is not a very strong detection - type = 'neuralynx_dma'; - manufacturer = 'Neuralynx'; - content = 'raw aplifier data directly from DMA'; -elseif filetype_check_extension(filename, '.nrd') % see also above, since Cheetah 5.x the file extension has changed - type = 'neuralynx_dma'; - manufacturer = 'Neuralynx'; - content = 'raw aplifier data directly from DMA'; -elseif isdir(filename) && (any(filetype_check_extension({ls.name}, '.nev')) || any(filetype_check_extension({ls.name}, '.Nev'))) - % a regular Neuralynx dataset directory that contains an event file - type = 'neuralynx_ds'; - manufacturer = 'Neuralynx'; - content = 'dataset'; -elseif isdir(filename) && most(filetype_check_extension({ls.name}, '.ncs')) - % a directory containing continuously sampled channels in Neuralynx format - type = 'neuralynx_ds'; - manufacturer = 'Neuralynx'; - content = 'continuously sampled channels'; -elseif isdir(filename) && most(filetype_check_extension({ls.name}, '.nse')) - % a directory containing spike waveforms in Neuralynx format - type = 'neuralynx_ds'; - manufacturer = 'Neuralynx'; - content = 'spike waveforms'; -elseif isdir(filename) && most(filetype_check_extension({ls.name}, '.nte')) - % a directory containing spike timestamps in Neuralynx format - type = 'neuralynx_ds'; - manufacturer = 'Neuralynx'; - content = 'spike timestamps'; - - % these are formally not Neuralynx file formats, but at the FCDC we use them together with Neuralynx -elseif isdir(filename) && any(filetype({ls.name}, 'neuralynx_ds')) - % a downsampled Neuralynx DMA file can be split into three seperate lfp/mua/spike directories - % treat them as one combined dataset - type = 'neuralynx_cds'; - manufacturer = 'F.C. Donders Centre'; - content = 'dataset containing seperate lfp/mua/spike directories'; -elseif filetype_check_extension(filename, '.tsl') && filetype_check_header(filename, 'tsl') - type = 'neuralynx_tsl'; - manufacturer = 'F.C. Donders Centre'; - content = 'timestamps from DMA log file'; -elseif filetype_check_extension(filename, '.tsh') && filetype_check_header(filename, 'tsh') - type = 'neuralynx_tsh'; - manufacturer = 'F.C. Donders Centre'; - content = 'timestamps from DMA log file'; -elseif filetype_check_extension(filename, '.ttl') && filetype_check_header(filename, 'ttl') - type = 'neuralynx_ttl'; - manufacturer = 'F.C. Donders Centre'; - content = 'Parallel_in from DMA log file'; -elseif filetype_check_extension(filename, '.bin') && filetype_check_header(filename, {'uint8', 'uint16', 'uint32', 'int8', 'int16', 'int32', 'int64', 'float32', 'float64'}) - type = 'neuralynx_bin'; - manufacturer = 'F.C. Donders Centre'; - content = 'single channel continuous data'; -elseif isdir(filename) && any(filetype_check_extension({ls.name}, '.ttl')) && any(filetype_check_extension({ls.name}, '.tsl')) && any(filetype_check_extension({ls.name}, '.tsh')) - % a directory containing the split channels from a DMA logfile - type = 'neuralynx_sdma'; - manufacturer = 'F.C. Donders Centre'; - content = 'split DMA log file'; -elseif isdir(filename) && filetype_check_extension(filename, '.sdma') - % a directory containing the split channels from a DMA logfile - type = 'neuralynx_sdma'; - manufacturer = 'F.C. Donders Centre'; - content = 'split DMA log file'; - - % known Plexon file types -elseif filetype_check_extension(filename, '.nex') && filetype_check_header(filename, 'NEX1') - type = 'plexon_nex'; - manufacturer = 'Plexon'; - content = 'electrophysiological data'; -elseif filetype_check_extension(filename, '.plx') && filetype_check_header(filename, 'PLEX') - type = 'plexon_plx'; - manufacturer = 'Plexon'; - content = 'electrophysiological data'; -elseif filetype_check_extension(filename, '.ddt') - type = 'plexon_ddt'; - manufacturer = 'Plexon'; -elseif isdir(filename) && most(filetype_check_extension({ls.name}, '.nex')) && most(filetype_check_header({ls.name}, 'NEX1')) - % a directory containing multiple plexon NEX files - type = 'plexon_ds'; - manufacturer = 'Plexon'; - content = 'electrophysiological data'; - - % known Cambridge Electronic Design file types -elseif filetype_check_extension(filename, '.smr') - type = 'ced_son'; - manufacturer = 'Cambridge Electronic Design'; - content = 'Spike2 SON filing system'; - - % known BESA file types -elseif filetype_check_extension(filename, '.avr') && strcmp(type, 'unknown') - type = 'besa_avr'; % FIXME, can also be EEProbe average EEG - manufacturer = 'BESA'; - content = 'average EEG'; -elseif filetype_check_extension(filename, '.elp') - type = 'besa_elp'; - manufacturer = 'BESA'; - content = 'electrode positions'; -elseif filetype_check_extension(filename, '.eps') - type = 'besa_eps'; - manufacturer = 'BESA'; - content = 'digitizer information'; -elseif filetype_check_extension(filename, '.sfp') - type = 'besa_sfp'; - manufacturer = 'BESA'; - content = 'sensor positions'; -elseif filetype_check_extension(filename, '.ela') - type = 'besa_ela'; - manufacturer = 'BESA'; - content = 'sensor information'; -elseif filetype_check_extension(filename, '.pdg') - type = 'besa_pdg'; - manufacturer = 'BESA'; - content = 'paradigm file'; -elseif filetype_check_extension(filename, '.tfc') - type = 'besa_tfc'; - manufacturer = 'BESA'; - content = 'time frequency coherence'; -elseif filetype_check_extension(filename, '.mul') - type = 'besa_mul'; - manufacturer = 'BESA'; - content = 'multiplexed ascii format'; -elseif filetype_check_extension(filename, '.dat') && filetype_check_header(filename, 'BESA_SA') % header can start with BESA_SA_IMAGE or BESA_SA_MN_IMAGE - type = 'besa_src'; - manufacturer = 'BESA'; - content = 'beamformer source reconstruction'; -elseif filetype_check_extension(filename, '.swf') && filetype_check_header(filename, 'Npts=') - type = 'besa_swf'; - manufacturer = 'BESA'; - content = 'beamformer source waveform'; -elseif filetype_check_extension(filename, '.bsa') - type = 'besa_bsa'; - manufacturer = 'BESA'; - content = 'beamformer source locations and orientations'; -elseif exist(fullfile(p, [f '.dat']), 'file') && (exist(fullfile(p, [f '.gen']), 'file') || exist(fullfile(p, [f '.generic']), 'file')) - type = 'besa_sb'; - manufacturer = 'BESA'; - content = 'simple binary channel data with a seperate generic ascii header'; - - % old files from Pascal Fries' PhD research at the MPI -elseif filetype_check_extension(filename, '.dap') && filetype_check_header(filename, char(1)) - type = 'mpi_dap'; - manufacturer = 'MPI Frankfurt'; - content = 'electrophysiological data'; -elseif isdir(filename) && ~isempty(cell2mat(regexp({ls.name}, '.dap$'))) - type = 'mpi_ds'; - manufacturer = 'MPI Frankfurt'; - content = 'electrophysiological data'; - - % Frankfurt SPASS format, which uses the Labview Datalog (DTLG) format -elseif filetype_check_header(filename, 'DTLG') && filetype_check_extension(filename, '.ana') - type = 'spass_ana'; - manufacturer = 'MPI Frankfurt'; - content = 'electrophysiological data'; -elseif filetype_check_header(filename, 'DTLG') && filetype_check_extension(filename, '.swa') - type = 'spass_swa'; - manufacturer = 'MPI Frankfurt'; - content = 'electrophysiological data'; -elseif filetype_check_header(filename, 'DTLG') && filetype_check_extension(filename, '.spi') - type = 'spass_spi'; - manufacturer = 'MPI Frankfurt'; - content = 'electrophysiological data'; -elseif filetype_check_header(filename, 'DTLG') && filetype_check_extension(filename, '.stm') - type = 'spass_stm'; - manufacturer = 'MPI Frankfurt'; - content = 'electrophysiological data'; -elseif filetype_check_header(filename, 'DTLG') && filetype_check_extension(filename, '.bhv') - type = 'spass_bhv'; - manufacturer = 'MPI Frankfurt'; - content = 'electrophysiological data'; - - % known Chieti ITAB file types -elseif filetype_check_extension(filename, '.raw') && filetype_check_header(filename, 'FORMAT: ATB-BIOMAGDATA') - type = 'itab_raw'; - manufacturer = 'Chieti ITAB'; - content = 'MEG data, including sensor positions'; - - % known Nexstim file types -elseif filetype_check_extension(filename, '.nxe') - type = 'nexstim_nxe'; - manufacturer = 'Nexstim'; - content = 'electrophysiological data'; - - % known Curry V4 file types -elseif filetype_check_extension(filename, '.dap') - type = 'curry_dap'; % FIXME, can also be MPI Frankfurt electrophysiological data - manufacturer = 'Curry'; - content = 'data parameter file'; -elseif filetype_check_extension(filename, '.dat') - type = 'curry_dat'; - manufacturer = 'Curry'; - content = 'raw data file'; -elseif filetype_check_extension(filename, '.rs4') - type = 'curry_rs4'; - manufacturer = 'Curry'; - content = 'sensor geometry file'; -elseif filetype_check_extension(filename, '.par') - type = 'curry_par'; - manufacturer = 'Curry'; - content = 'data or image parameter file'; -elseif filetype_check_extension(filename, '.bd0') || filetype_check_extension(filename, '.bd1') || filetype_check_extension(filename, '.bd2') || filetype_check_extension(filename, '.bd3') || filetype_check_extension(filename, '.bd4') || filetype_check_extension(filename, '.bd5') || filetype_check_extension(filename, '.bd6') || filetype_check_extension(filename, '.bd7') || filetype_check_extension(filename, '.bd8') || filetype_check_extension(filename, '.bd9') - type = 'curry_bd'; - manufacturer = 'Curry'; - content = 'BEM description file'; -elseif filetype_check_extension(filename, '.bt0') || filetype_check_extension(filename, '.bt1') || filetype_check_extension(filename, '.bt2') || filetype_check_extension(filename, '.bt3') || filetype_check_extension(filename, '.bt4') || filetype_check_extension(filename, '.bt5') || filetype_check_extension(filename, '.bt6') || filetype_check_extension(filename, '.bt7') || filetype_check_extension(filename, '.bt8') || filetype_check_extension(filename, '.bt9') - type = 'curry_bt'; - manufacturer = 'Curry'; - content = 'BEM transfer matrix file'; -elseif filetype_check_extension(filename, '.bm0') || filetype_check_extension(filename, '.bm1') || filetype_check_extension(filename, '.bm2') || filetype_check_extension(filename, '.bm3') || filetype_check_extension(filename, '.bm4') || filetype_check_extension(filename, '.bm5') || filetype_check_extension(filename, '.bm6') || filetype_check_extension(filename, '.bm7') || filetype_check_extension(filename, '.bm8') || filetype_check_extension(filename, '.bm9') - type = 'curry_bm'; - manufacturer = 'Curry'; - content = 'BEM full matrix file'; -elseif filetype_check_extension(filename, '.dig') - type = 'curry_dig'; - manufacturer = 'Curry'; - content = 'digitizer file'; - - % known Curry V2 file types -elseif filetype_check_extension(filename, '.sp0') || filetype_check_extension(filename, '.sp1') || filetype_check_extension(filename, '.sp2') || filetype_check_extension(filename, '.sp3') || filetype_check_extension(filename, '.sp4') || filetype_check_extension(filename, '.sp5') || filetype_check_extension(filename, '.sp6') || filetype_check_extension(filename, '.sp7') || filetype_check_extension(filename, '.sp8') || filetype_check_extension(filename, '.sp9') - type = 'curry_sp'; - manufacturer = 'Curry'; - content = 'point list'; -elseif filetype_check_extension(filename, '.s10') || filetype_check_extension(filename, '.s11') || filetype_check_extension(filename, '.s12') || filetype_check_extension(filename, '.s13') || filetype_check_extension(filename, '.s14') || filetype_check_extension(filename, '.s15') || filetype_check_extension(filename, '.s16') || filetype_check_extension(filename, '.s17') || filetype_check_extension(filename, '.s18') || filetype_check_extension(filename, '.s19') || filetype_check_extension(filename, '.s20') || filetype_check_extension(filename, '.s21') || filetype_check_extension(filename, '.s22') || filetype_check_extension(filename, '.s23') || filetype_check_extension(filename, '.s24') || filetype_check_extension(filename, '.s25') || filetype_check_extension(filename, '.s26') || filetype_check_extension(filename, '.s27') || filetype_check_extension(filename, '.s28') || filetype_check_extension(filename, '.s29') || filetype_check_extension(filename, '.s30') || filetype_check_extension(filename, '.s31') || filetype_check_extension(filename, '.s32') || filetype_check_extension(filename, '.s33') || filetype_check_extension(filename, '.s34') || filetype_check_extension(filename, '.s35') || filetype_check_extension(filename, '.s36') || filetype_check_extension(filename, '.s37') || filetype_check_extension(filename, '.s38') || filetype_check_extension(filename, '.s39') - type = 'curry_s'; - manufacturer = 'Curry'; - content = 'triangle or tetraedra list'; -elseif filetype_check_extension(filename, '.pom') - type = 'curry_pom'; - manufacturer = 'Curry'; - content = 'anatomical localization file'; -elseif filetype_check_extension(filename, '.res') - type = 'curry_res'; - manufacturer = 'Curry'; - content = 'functional localization file'; - - % known MBFYS file types -elseif filetype_check_extension(filename, '.tri') - type = 'mbfys_tri'; - manufacturer = 'MBFYS'; - content = 'triangulated surface'; -elseif filetype_check_extension(filename, '.ama') && filetype_check_header(filename, [10 0 0 0]) - type = 'mbfys_ama'; - manufacturer = 'MBFYS'; - content = 'BEM volume conduction model'; - - % Electrical Geodesics Incorporated format -elseif (filetype_check_extension(filename, '.egis') || filetype_check_extension(filename, '.ave') || filetype_check_extension(filename, '.gave') || filetype_check_extension(filename, '.raw')) && (filetype_check_header(filename, [char(1) char(2) char(3) char(4) char(255) char(255)]) || filetype_check_header(filename, [char(3) char(4) char(1) char(2) char(255) char(255)])) - type = 'egi_egia'; - manufacturer = 'Electrical Geodesics Incorporated'; - content = 'averaged EEG data'; -elseif (filetype_check_extension(filename, '.egis') || filetype_check_extension(filename, '.ses') || filetype_check_extension(filename, '.raw')) && (filetype_check_header(filename, [char(1) char(2) char(3) char(4) char(0) char(3)]) || filetype_check_header(filename, [char(3) char(4) char(1) char(2) char(0) char(3)])) - type = 'egi_egis'; - manufacturer = 'Electrical Geodesics Incorporated'; - content = 'raw EEG data'; -elseif (filetype_check_extension(filename, '.sbin') || filetype_check_extension(filename, '.raw')) - % note that the Chieti MEG data format also has the extension *.raw - % but that can be detected by looking at the file header - type = 'egi_sbin'; - manufacturer = 'Electrical Geodesics Incorporated'; - content = 'averaged EEG data'; - - - % some other known file types -elseif length(filename)>4 && exist([filename(1:(end-4)) '.mat'], 'file') && exist([filename(1:(end-4)) '.bin'], 'file') - % this is a self-defined FCDC data format, consisting of two files - % there is a matlab V6 file with the header and a binary file with the data (multiplexed, ieee-le, double) - type = 'fcdc_matbin'; - manufacturer = 'F.C. Donders Centre'; - content = 'multiplexed electrophysiology data'; -elseif filetype_check_extension(filename, '.lay') - type = 'layout'; - manufacturer = 'Ole Jensen'; - content = 'layout of channels for plotting'; -elseif filetype_check_extension(filename, '.dcm') || filetype_check_extension(filename, '.ima') || filetype_check_header(filename, 'DICM', 128) - type = 'dicom'; - manufacturer = 'Dicom'; - content = 'image data'; -elseif filetype_check_extension(filename, '.trl') - type = 'fcdc_trl'; - manufacturer = 'F.C.Donders'; - content = 'trial definitions'; -elseif filetype_check_header(filename, [255 'BIOSEMI']) % filetype_check_extension(filename, '.bdf') - type = 'biosemi_bdf'; - % type = 'bham_bdf'; - manufacturer = 'Biosemi Data Format'; - content = 'electrophysiological data'; -elseif filetype_check_extension(filename, '.edf') - type = 'edf'; - manufacturer = 'European Data Format'; - content = 'electrophysiological data'; -elseif filetype_check_extension(filename, '.mat') && exist(filename, 'file') && exist([filename(1:(end-4)) '.dat'], 'file') && numel(whos('-file', filename))==1 && strcmp('D', getfield(whos('-file', filename), {1}, 'name')) && strcmp('struct', getfield(whos('-file', filename), {1}, 'class')) - type = 'spmeeg_mat'; - manufacturer = 'Wellcome Trust Centre for Neuroimaging, UCL, UK'; - content = 'electrophysiological data'; -elseif filetype_check_extension(filename, '.mat') && exist(filename, 'file') && filetype_check_ced_spike6mat(filename) - type = 'ced_spike6mat'; - manufacturer = 'Cambridge Electronic Design Limited'; - content = 'electrophysiological data'; -elseif filetype_check_extension(filename, '.mat') && filetype_check_header(filename, 'MATLAB') - type = 'matlab'; - manufacturer = 'Matlab'; - content = 'Matlab binary data'; -elseif filetype_check_header(filename, 'RIFF', 0) && filetype_check_header(filename, 'WAVE', 8) - type = 'riff_wave'; - manufacturer = 'Microsoft'; - content = 'audio'; -elseif filetype_check_extension(filename, '.txt') - type = 'ascii_txt'; - manufacturer = ''; - content = ''; -elseif filetype_check_extension(filename, '.pol') - type = 'polhemus_fil'; - manufacturer = 'Functional Imaging Lab, London, UK'; - content = 'headshape points'; -elseif filetype_check_extension(filename, '.set') - type = 'eeglab_set'; - manufacturer = 'Swartz Center for Computational Neuroscience, San Diego, USA'; - content = 'electrophysiological data'; -elseif filetype_check_extension(filename, '.t') && filetype_check_header(filename, '%%BEGINHEADER') - type = 'mclust_t'; - manufacturer = 'MClust'; - content = 'sorted spikes'; -elseif filetype_check_header(filename, 26) - type = 'nimh_cortex'; - manufacturer = 'NIMH Laboratory of Neuropsychology, http://www.cortex.salk.edu'; - content = 'events and eye channels'; -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% finished determining the filetype -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -if strcmp(type, 'unknown') - warning('could not determine filetype of %s', filename); -end - -if ~isempty(desired) - % return a boolean value instead of a descriptive string - type = strcmp(type, desired); -end - -% remember the current input and output arguments, so that they can be -% reused on a subsequent call in case the same input argument is given -current_argout = {type}; -if isempty(previous_argin) && ~strcmp(type, 'unknown') - previous_argin = current_argin; - previous_argout = current_argout; - previous_pwd = current_pwd; -else - % don't remember in case unknown - previous_argin = []; - previous_argout = []; - previous_pwd = []; -end - -return % filetype main() - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION that helps in deciding whether a directory with files should -% be treated as a "dataset". This function returns a logical 1 (TRUE) if more -% than half of the element of a vector are nonzero number or are logical 1 -% (TRUE). -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function y = most(x) -x = x(find(~isnan(x(:)))); -y = sum(x==0)char'); - fclose(fid); - for i=1:length(head) - val = strncmp(str, head{i}, len(i)); - if val - break - end - end - else - [str, siz] = fread(fid, length(head), 'uint8=>char'); - fclose(fid); - if siz~=length(head) - warning(sprintf('could not read the header from %s', filename)); - val = 0; - else - val = all(str(:)==head(:)); - end - end - end -end -return - diff --git a/external/fileio/private/filetype_check_uri.m b/external/fileio/private/filetype_check_uri.m deleted file mode 100644 index c6cec94..0000000 --- a/external/fileio/private/filetype_check_uri.m +++ /dev/null @@ -1,222 +0,0 @@ -function varargout = filetype_check_uri(filename, ftyp) - -% FILETYPE_CHECK_URI -% -% Supported URIs are -% shm:// -% fifo:// -% buffer://: -% tcp://: -% udp://: -% mysql://:@: -% rfb://@: -% serial:?key1=value1&key2=value2&... -% -% The URI schemes supproted by these function are not the official schemes. -% See the documentation included inside this function for more details. -% RFC4395 defines an IANA-maintained registry of URI Schemes. See also -% http://www.iana.org/assignments/uri-schemes.html and -% http://en.wikipedia.org/wiki/URI_scheme#Generic_syntax. - -% Copyright (C) 2007, Robert Oostenveld -% -% $Log: filetype_check_uri.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.7 2008/12/19 14:40:23 marvger -% added support for udp, tcp and fifo -% -% Revision 1.6 2008/02/19 10:07:34 roboos -% replaced tcpsocket with buffer -% -% Revision 1.5 2007/11/07 10:45:56 roboos -% made port optional for mysql -% -% Revision 1.4 2007/10/15 16:02:46 roboos -% added rfb://@: -% -% Revision 1.3 2007/07/27 12:18:50 roboos -% added ctf_shm -% -% Revision 1.2 2007/06/19 11:13:59 chrhes -% small change in how the serial port case is processed to allow for the -% possibility of no options being passed -% -% Revision 1.1 2007/06/06 07:10:36 roboos -% initial implementation -% - -sep = find(filename==':'); -if ~isempty(sep) - scheme = filename(1:(sep(1)-1)); -else - scheme = []; -end - -if nargin>1 - % only return true or false - varargout{1} = strcmp(scheme, ftyp); -else - % return the full details of this URI scheme - switch scheme - case 'shm' - % shm:// - % the filename is optional, usually it can and will be read from shared memory - if length(filename)>6 - varargout{1} = filename(7:end); - else - varargout{1} = []; - end - - case 'fifo' - % fifo:// - varargout{1} = filename(8:end); - - case 'buffer' - % buffer://: - tok = tokenize(filename(10:end), ':'); - varargout{1} = tok{1}; - varargout{2} = str2num(tok{2}); - - case 'tcp' - % tcp://: - tok = tokenize(filename(7:end), ':'); - varargout{1} = tok{1}; - varargout{2} = str2num(tok{2}); - - case 'udp' - % udp://: - tok = tokenize(filename(7:end), ':'); - varargout{1} = tok{1}; - varargout{2} = str2num(tok{2}); - - case 'rfb' - % rfb://@: - tok0 = tokenize(filename(7:end), '@'); - tok1 = tokenize(tok0{2}, ':'); - varargout{1} = tok0{1}; - varargout{2} = tok1{1}; - varargout{3} = str2num(tok1{2}); - - case 'mysql' - % mysql://:@: - tok0 = tokenize(filename(9:end), '@'); - tok1 = tokenize(tok0{1}, ':'); - tok2 = tokenize(tok0{2}, ':'); - varargout{1} = tok1{1}; - varargout{2} = tok1{2}; - varargout{3} = tok2{1}; - if length(tok2)>1 - varargout{4} = str2num(tok2{2}); - else - varargout{4} = []; - end - - case 'serial' - % serial:?key1=value1&key2=value2&... - % the supported optional arguments are - % BaudRate - % DataBits - % DataTerminalReady - % FlowControl - % Parity - % Port - % ReadAsyncMode - % RequestToSend - % StopBits - % Terminator - tok0 = tokenize(filename(8:end), '?'); - varargout{1} = tok0{1}; - varargout{2} = []; - if length(tok0)>1 - tok1 = tokenize(tok0{2}, '&'); - for i=1:length(tok1) - tok2 = tokenize(tok1{i}, '='); - opt{(i-1)*2+1} = tok2{1}; - opt{(i-1)*2+2} = tok2{2}; - end - varargout{2} = opt; - end - - - otherwise - error('unsupported scheme in URI') - end -end - -% RFC4395 defines an IANA-maintained registry of URI Schemes. -% see also http://www.iana.org/assignments/uri-schemes.html -% and http://en.wikipedia.org/wiki/URI_scheme#Generic_syntax -% -% Scheme Description Reference -% ------------------------------------------------------------- -% aaa Diameter Protocol [RFC3588] -% aaas Diameter Protocol with Secure Transport [RFC3588] -% acap application configuration access protocol [RFC2244] -% cap Calendar Access Protocol [RFC4324] -% cid content identifier [RFC2392] -% crid TV-Anytime Content Reference Identifier [RFC4078] -% data data [RFC2397] -% dav dav [RFC-ietf-webdav-rfc2518bis-18.txt] -% dict dictionary service protocol [RFC2229] -% dns Domain Name System [RFC4501] -% fax fax [RFC3966] -% file Host-specific file names [RFC1738] -% ftp File Transfer Protocol [RFC1738] -% go go [RFC3368] -% gopher The Gopher Protocol [RFC4266] -% h323 H.323 [RFC3508] -% http Hypertext Transfer Protocol [RFC2616] -% https Hypertext Transfer Protocol Secure [RFC2818] -% icap Internet Content Adaptation Protocol [RFC3507] -% im Instant Messaging [RFC3860] -% imap internet message access protocol [RFC2192] -% info Information Assets with Identifiers in Public Namespaces [RFC4452] -% ipp Internet Printing Protocol [RFC3510] -% iris Internet Registry Information Service [RFC3981] -% iris.beep iris.beep [RFC3983] -% iris.xpc iris.xpc [RFC-ietf-crisp-iris-xpc-06.txt] -% iris.xpcs iris.xpcs [RFC-ietf-crisp-iris-xpc-06.txt] -% iris.lwz iris.lwz [RFC-ietf-crisp-iris-lwz-08.txt] -% ldap Lightweight Directory Access Protocol [RFC4516] -% mailto Electronic mail address [RFC2368] -% mid message identifier [RFC2392] -% modem modem [RFC3966] -% msrp Message Session Relay Protocol [RFC-ietf-simple-message-sessions-19.txt] -% msrps Message Session Relay Protocol Secure [RFC-ietf-simple-message-sessions-19.txt] -% mtqp Message Tracking Query Protocol [RFC3887] -% mupdate Mailbox Update (MUPDATE) Protocol [RFC3656] -% news USENET news [RFC1738] -% nfs network file system protocol [RFC2224] -% nntp USENET news using NNTP access [RFC1738] -% opaquelocktoken opaquelocktokent [RFC-ietf-webdav-rfc2518bis-18.txt] -% pop Post Office Protocol v3 [RFC2384] -% pres Presence [RFC3859] -% rtsp real time streaming protocol [RFC2326] -% service service location [RFC2609] -% shttp Secure Hypertext Transfer Protocol [RFC2660] -% sip session initiation protocol [RFC3261] -% sips secure session initiation protocol [RFC3261] -% snmp Simple Network Management Protocol [RFC4088] -% soap.beep soap.beep [RFC3288] -% soap.beeps soap.beeps [RFC3288] -% tag tag [RFC4151] -% tel telephone [RFC3966] -% telnet Reference to interactive sessions [RFC4248] -% tftp Trivial File Transfer Protocol [RFC3617] -% thismessage multipart/related relative reference resolution [RFC2557] -% tip Transaction Internet Protocol [RFC2371] -% tv TV Broadcasts [RFC2838] -% urn Uniform Resource Names (click for registry) [RFC2141] -% vemmi versatile multimedia interface [RFC2122] -% xmlrpc.beep xmlrpc.beep [RFC3529] -% xmlrpc.beeps xmlrpc.beeps [RFC3529] -% xmpp Extensible Messaging and Presence Protocol [RFC4622] -% z39.50r Z39.50 Retrieval [RFC2056] -% z39.50s Z39.50 Session [RFC2056] diff --git a/external/fileio/private/filter_event.m b/external/fileio/private/filter_event.m deleted file mode 100644 index cbcbdb6..0000000 --- a/external/fileio/private/filter_event.m +++ /dev/null @@ -1,131 +0,0 @@ -function event = filter_event(event, varargin) - -% FILTER_EVENT does what its name implies -% -% Use as -% event = filter_event(event, ...) -% -% The optional arguments should come in key-value pairs and determine the -% filter characteristics: -% type = cell-array with strings -% value = numeric array -% sample = numeric array -% timestamp = numeric array -% offset = numeric array -% duration = numeric array -% minsample = value -% maxsample = value -% minduration = value -% maxduration = value -% mintimestamp = value -% maxtimestamp = value -% minnumber = value, applies only if event.number is present -% maxnmumber = value, applies only if event.number is present -% -% See also READ_EVEN, WRITE_EVENT - -% Copyright (C) 2007, Robert Oostenveld -% -% $Log: filter_event.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.8 2009/01/14 08:47:51 roboos -% moved to fileio -% -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.6 2007/12/20 19:04:12 roboos -% added filtering for minnumber and maxnumber (in line with read_neuralyns_nev) -% -% Revision 1.5 2007/12/19 08:28:50 roboos -% fixed bug for those filters which accept a numeric array (inserted any(..) around teh comparison) -% added teh missing code for filtering on timestamp value -% -% Revision 1.4 2007/08/21 16:56:03 chrhes -% fixed some logic (typo) bugs in relation to setting the testing flags -% -% Revision 1.3 2007/08/16 13:33:20 chrhes -% fixed some typos in the if statements implementing the event selection -% -% Revision 1.2 2007/07/30 12:16:17 roboos -% updated documentation -% implemented min and max timestamp -% -% Revision 1.1 2007/06/13 14:47:35 roboos -% moved filter_event from fieldtrip to fileio module -% -% Revision 1.1 2007/06/06 12:41:22 roboos -% new implementation -% - -% get the optional input arguments -type = keyval('type', varargin); -value = keyval('value', varargin); -sample = keyval('sample', varargin); -timestamp = keyval('timestamp', varargin); -offset = keyval('offset', varargin); -duration = keyval('duration', varargin); - -% the numeric fields can also be filtered on a range -minsample = keyval('minsample', varargin); -maxsample = keyval('maxsample', varargin); -minduration = keyval('minduration', varargin); -maxduration = keyval('maxduration', varargin); -mintimestamp = keyval('mintimestamp', varargin); -maxtimestamp = keyval('maxtimestamp', varargin); -minnumber = keyval('minnumber', varargin); -maxnumber = keyval('maxnumber', varargin); - -if ~isempty(type) - % this can be specified as string or as cell-array, convert to cell-array - if ~iscell(type) - type = {type}; - end -end - -% determine which filters to apply -testtype = ~isempty(type) && isfield(event, 'type'); -testvalue = ~isempty(value) && isfield(event, 'value'); -testsample = ~isempty(sample) && isfield(event, 'sample'); -testtimestamp = ~isempty(timestamp) && isfield(event, 'timestamp'); -testoffset = ~isempty(offset) && isfield(event, 'offset'); -testduration = ~isempty(duration) && isfield(event, 'duration'); -testminsample = ~isempty(minsample) && isfield(event, 'sample'); -testmaxsample = ~isempty(maxsample) && isfield(event, 'sample'); -testminduration = ~isempty(minduration) && isfield(event, 'duration'); -testmaxduration = ~isempty(maxduration) && isfield(event, 'duration'); -testmintimestamp = ~isempty(mintimestamp) && isfield(event, 'timestamp'); -testmaxtimestamp = ~isempty(maxtimestamp) && isfield(event, 'timestamp'); -testminnumber = ~isempty(minnumber) && isfield(event, 'number'); -testmaxnumber = ~isempty(maxnumber) && isfield(event, 'number'); - -% apply the filters -sel = true(length(event),1); -for i=1:length(event) - % test whether they match with the selected arrays - if testvalue, sel(i) = sel(i) && any(event(i).value == value); end - if testsample, sel(i) = sel(i) && any(event(i).sample == sample); end - if testtimestamp,sel(i) = sel(i) && any(event(i).timestamp == timestamp); end - if testoffset, sel(i) = sel(i) && any(event(i).offset == offset); end - if testduration, sel(i) = sel(i) && any(event(i).duration == duration); end - % test whether they lie within the specified range - if testminsample, sel(i) = sel(i) && (event(i).sample >= minsample); end - if testmaxsample, sel(i) = sel(i) && (event(i).sample <= maxsample); end - if testminduration, sel(i) = sel(i) && (event(i).duration >= minduration); end - if testmaxduration, sel(i) = sel(i) && (event(i).duration <= maxduration); end - if testmintimestamp, sel(i) = sel(i) && (event(i).timestamp >= mintimestamp); end - if testmaxtimestamp, sel(i) = sel(i) && (event(i).timestamp <= maxtimestamp); end - if testminnumber, sel(i) = sel(i) && (event(i).number >= minnumber); end - if testmaxnumber, sel(i) = sel(i) && (event(i).number <= maxnumber); end - % this is potentially the slowest test, hence do it the last - if testtype, sel(i) = sel(i) && any(strcmp(event(i).type, type)); end -end - -event = event(sel); \ No newline at end of file diff --git a/external/fileio/private/getsubfield.m b/external/fileio/private/getsubfield.m deleted file mode 100644 index b376a50..0000000 --- a/external/fileio/private/getsubfield.m +++ /dev/null @@ -1,35 +0,0 @@ -function [s] = getsubfield(s, f); - -% GETSUBFIELD returns a field from a structure just like the standard -% Matlab GETFIELD function, except that you can also specify nested fields -% using a '.' in the fieldname. The nesting can be arbitrary deep. -% -% Use as -% f = getsubfield(s, 'fieldname') -% or as -% f = getsubfield(s, 'fieldname.subfieldname') -% -% See also GETFIELD, ISSUBFIELD, SETSUBFIELD - -% Copyright (C) 2005, Robert Oostenveld -% -% $Log: getsubfield.m,v $ -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.1 2005/02/08 09:30:18 roboos -% new implementations to make it easier to work with nested structures -% - -if ~isstr(f) - error('incorrect input argument for fieldname'); -end - -t = {}; -while (1) - [t{end+1}, f] = strtok(f, '.'); - if isempty(f) - break - end -end -s = getfield(s, t{:}); diff --git a/external/fileio/private/hastoolbox.m b/external/fileio/private/hastoolbox.m deleted file mode 100644 index a4ca969..0000000 --- a/external/fileio/private/hastoolbox.m +++ /dev/null @@ -1,408 +0,0 @@ -function [status] = hastoolbox(toolbox, autoadd, silent) - -% HASTOOLBOX tests whether an external toolbox is installed. Optionally -% it will try to determine the path to the toolbox and install it -% automatically. -% -% Use as -% [status] = hastoolbox(toolbox, autoadd, silent) - -% Copyright (C) 2005-2008, Robert Oostenveld -% -% $Log: hastoolbox.m,v $ -% Revision 1.37 2009/10/13 10:11:06 roboos -% added lc-libs -% -% Revision 1.36 2009/09/08 14:34:01 roboos -% also detect 64 bit windows version (thanks to arno) -% -% Revision 1.35 2009/04/21 09:54:15 roboos -% added prtools -% -% Revision 1.34 2009/04/02 19:47:33 roboos -% added plotting module -% -% Revision 1.33 2009/03/30 15:06:14 roboos -% added the patch from Alexandre to support openmeeg -% -% Revision 1.32 2009/03/12 10:40:21 roboos -% added the splines toolbox (mainly for testing) and changed the warning message related to the license -% -% Revision 1.31 2009/03/12 10:33:35 roboos -% not only check that a function is available, also check whether a license for that function is available -% -% Revision 1.30 2009/03/11 21:26:27 roboos -% detect spm8b just as spm8 -% -% Revision 1.29 2009/03/11 10:35:19 roboos -% spm detection was confused with function and directory, explicitely check for "spm.m" which is the function -% -% Revision 1.28 2009/03/11 08:49:04 roboos -% improved the detection of the various spm versions -% -% Revision 1.27 2009/02/11 11:03:08 roboos -% changed naming of the functions of Chris in accordance with SPM8 -% -% Revision 1.26 2009/02/02 12:57:21 roboos -% added bemcp, image, tcp_udp_ip -% -% Revision 1.25 2009/01/19 15:02:21 roboos -% added mne for fiff access -% -% Revision 1.24 2009/01/08 17:00:02 roboos -% improved caching in case the toolbox is not present -% -% Revision 1.23 2008/12/24 09:10:46 roboos -% added dipoli -% -% Revision 1.22 2008/10/29 15:45:12 roboos -% fix dashes and spaces in directory names for caching -% -% Revision 1.21 2008/10/20 21:50:56 roboos -% added NlxNetCom -% -% Revision 1.20 2008/10/20 16:31:15 roboos -% fixed problem in case with dash "-" in the directory -% -% Revision 1.19 2008/09/29 09:00:19 roboos -% implemented smart handling of previously seen toolboxes using a persistent variable -% this should speed up fieldtrip and fileio (e.g. read_data checks the presence of ctf for every trial) -% -% Revision 1.18 2008/09/24 15:43:00 roboos -% added read_data and read_sens for fileio, should solve problem for MEEGfileio in spm5 -% -% Revision 1.17 2008/09/22 19:42:09 roboos -% added option for silent processing -% -% Revision 1.16 2008/08/11 16:11:19 roboos -% also automatically add to path for fieldtrip code and external modules -% -% Revision 1.15 2008/06/20 07:25:56 roboos -% added check for presence of BCI2000 load_bcidat mex file -% -% Revision 1.14 2008/05/15 10:52:29 roboos -% added ctf -% -% Revision 1.13 2008/03/17 08:29:40 roboos -% changed some contact addresses -% -% Revision 1.12 2008/03/14 10:20:29 roboos -% added denoise -% -% Revision 1.11 2008/03/05 10:59:14 roboos -% added fileio and forwinv -% -% Revision 1.10 2007/05/06 09:10:07 roboos -% added spm5 -% -% Revision 1.9 2007/02/26 13:41:07 roboos -% made small change to fastica detection (suggested by Sameer) -% -% Revision 1.8 2007/02/13 17:22:27 roboos -% added MRI from eeg.sf.net -% -% Revision 1.7 2007/02/13 14:01:26 roboos -% added brainstorm -% -% Revision 1.6 2007/02/12 19:43:23 roboos -% added fastica, optim -% -% Revision 1.5 2007/01/17 17:05:34 roboos -% added matlab signal processing toolbox -% -% Revision 1.4 2007/01/04 12:25:19 roboos -% added SON2 -% -% Revision 1.3 2007/01/03 17:01:15 roboos -% added 4d-version toolbox -% -% Revision 1.2 2006/06/07 10:48:02 roboos -% changed the "see xxx" string -% -% Revision 1.1 2006/06/07 09:28:41 roboos -% renamed fieldtrip/private/checktoolbox into misc/hastoolbox -% -% Revision 1.8 2006/06/06 14:18:22 roboos -% added neuroshare, eeprobe, yokogawa -% -% Revision 1.7 2006/05/31 08:56:24 roboos -% implemented detection of toolbox in users ~/matlab/toolboxname -% -% Revision 1.6 2006/05/23 10:20:46 roboos -% added beowulf and mentat toolboxes -% -% Revision 1.5 2006/04/26 11:37:22 roboos -% added besa toolbox -% -% Revision 1.4 2006/02/07 20:01:39 roboos -% aded biosig and meg-pd (neuromag) -% -% Revision 1.3 2006/01/17 14:05:54 roboos -% added GLNA64 for mentat000 -% -% Revision 1.2 2006/01/06 11:39:23 roboos -% added copyrigth and cvs logging, changed some comments -% - -% this function is called many times in FieldTrip and associated toolboxes -% use efficient handling if the same toolbox has been investigated before -persistent previous -if isempty(previous) - previous = struct; -elseif isfield(previous, fixname(toolbox)) - status = previous.(fixname(toolbox)); - return -end - -% this points the user to the website where he/she can download the toolbox -url = { - 'AFNI' 'see http://afni.nimh.nih.gov' - 'DSS' 'see http://www.cis.hut.fi/projects/dss' - 'EEGLAB' 'see http://www.sccn.ucsd.edu/eeglab' - 'NWAY' 'see http://www.models.kvl.dk/source/nwaytoolbox' - 'SPM99' 'see http://www.fil.ion.ucl.ac.uk/spm' - 'SPM2' 'see http://www.fil.ion.ucl.ac.uk/spm' - 'SPM5' 'see http://www.fil.ion.ucl.ac.uk/spm' - 'SPM8' 'see http://www.fil.ion.ucl.ac.uk/spm' - 'MEG-PD' 'see http://www.kolumbus.fi/kuutela/programs/meg-pd' - 'MEG-CALC' 'this is a commercial toolbox from Neuromag, see http://www.neuromag.com' - 'BIOSIG' 'see http://biosig.sourceforge.net' - 'EEG' 'see http://eeg.sourceforge.net' - 'EEGSF' 'see http://eeg.sourceforge.net' % alternative name - 'MRI' 'see http://eeg.sourceforge.net' % alternative name - 'NEUROSHARE' 'see http://www.neuroshare.org' - 'BESA' 'see http://www.megis.de, or contact Karsten Hoechstetter' - 'EEPROBE' 'see http://www.ant-neuro.com, or contact Maarten van der Velde' - 'YOKOGAWA' 'see http://www.yokogawa.co.jp, or contact Nobuhiko Takahashi' - 'BEOWULF' 'see http://oostenveld.net, or contact Robert Oostenveld' - 'MENTAT' 'see http://oostenveld.net, or contact Robert Oostenveld' - 'SON2' 'see http://www.kcl.ac.uk/depsta/biomedical/cfnr/lidierth.html, or contact Malcolm Lidierth' - '4D-VERSION' 'contact Christian Wienbruch' - 'SIGNAL' 'see http://www.mathworks.com/products/signal' - 'OPTIM' 'see http://www.mathworks.com/products/optim' - 'IMAGE' 'see http://www.mathworks.com/products/image' - 'SPLINES' 'see http://www.mathworks.com/products/splines' - 'FASTICA' 'see http://www.cis.hut.fi/projects/ica/fastica' - 'BRAINSTORM' 'see http://neuroimage.ucs.edu/brainstorm' - 'FILEIO' 'see http://www.ru.nl/neuroimaging/fieldtrip' - 'FORWINV' 'see http://www.ru.nl/neuroimaging/fieldtrip' - 'PLOTTING' 'see http://www.ru.nl/neuroimaging/fieldtrip' - 'DENOISE' 'see http://lumiere.ens.fr/Audition/adc/meg, or contact Alain de Cheveigne' - 'BCI2000' 'see http://bci2000.org' - 'NLXNETCOM' 'see http://www.neuralynx.com' - 'DIPOLI' 'see ftp://ftp.fcdonders.nl/pub/fieldtrip/external' - 'MNE' 'see http://www.nmr.mgh.harvard.edu/martinos/userInfo/data/sofMNE.php' - 'TCP_UDP_IP' 'see http://www.mathworks.com/matlabcentral/fileexchange/345, or contact Peter Rydes?ter' - 'BEMCP' 'contact Christophe Phillips' - 'OPENMEEG' 'see http://gforge.inria.fr/projects/openmeeg' - 'PRTOOLS' 'see http://www.prtools.org' - 'LC-LIBS' 'contact Stefania Della Penna' - }; - -if nargin<2 - % default is not to add the path automatically - autoadd = 0; -end - -if nargin<3 - % default is not to be silent - silent = 0; -end - -% determine whether the toolbox is installed -toolbox = upper(toolbox); -switch toolbox - case 'AFNI' - status = (exist('BrikLoad') && exist('BrikInfo')); - case 'DSS' - status = exist('dss', 'file') && exist('dss_create_state', 'file'); - case 'EEGLAB' - status = exist('runica', 'file'); - case 'NWAY' - status = exist('parafac', 'file'); - case 'SPM99' - status = exist('spm.m') && strcmp(spm('ver'),'SPM99'); - case 'SPM2' - status = exist('spm.m') && strcmp(spm('ver'),'SPM2'); - case 'SPM5' - status = exist('spm.m') && strcmp(spm('ver'),'SPM5'); - case 'SPM8' - status = exist('spm.m') && strncmp(spm('ver'),'SPM8', 3); - case 'MEG-PD' - status = (exist('rawdata') && exist('channames')); - case 'MEG-CALC' - status = (exist('megmodel') && exist('megfield') && exist('megtrans')); - case 'BIOSIG' - status = (exist('sopen') && exist('sread')); - case 'EEG' - status = (exist('ctf_read_res4') && exist('ctf_read_meg4')); - case 'EEGSF' % alternative name - status = (exist('ctf_read_res4') && exist('ctf_read_meg4')); - case 'MRI' % other functions in the mri section - status = (exist('avw_hdr_read') && exist('avw_img_read')); - case 'NEUROSHARE' - status = (exist('ns_OpenFile') && exist('ns_SetLibrary') && exist('ns_GetAnalogData')); - case 'BESA' - status = (exist('readBESAtfc') && exist('readBESAswf')); - case 'EEPROBE' - status = (exist('read_eep_avr') && exist('read_eep_cnt')); - case 'YOKOGAWA' - status = (exist('GetMeg160ChannelInfoM') && exist('GetMeg160ContinuousRawDataM')); - case 'BEOWULF' - status = (exist('evalwulf') && exist('evalwulf') && exist('evalwulf')); - case 'MENTAT' - status = (exist('pcompile') && exist('pfor') && exist('peval')); - case 'SON2' - status = (exist('SONFileHeader') && exist('SONChanList') && exist('SONGetChannel')); - case '4D-VERSION' - status = (exist('read4d') && exist('read4dhdr')); - case 'SIGNAL' - status = hasfunction('medfilt1', toolbox); % also check the availability of a toolbox license - case 'OPTIM' - status = hasfunction('fmincon', toolbox) && hasfunction('fminunc', toolbox); % also check the availability of a toolbox license - case 'SPLINES' - status = hasfunction('bspline', toolbox) && hasfunction('csape', toolbox); % also check the availability of a toolbox license - case 'IMAGE' - status = hasfunction('bwlabeln', toolbox); % also check the availability of a toolbox license - case 'FASTICA' - status = exist('fastica', 'file'); - case 'BRAINSTORM' - status = exist('bem_xfer'); - case 'FILEIO' - status = (exist('read_header') && exist('read_data') && exist('read_event') && exist('read_sens')); - case 'FORWINV' - status = (exist('compute_leadfield') && exist('prepare_vol_sens')); - case 'DENOISE' - status = (exist('tsr') && exist('sns')); - case 'CTF' - status = (exist('getCTFBalanceCoefs') && exist('getCTFdata')); - case 'BCI2000' - status = exist('load_bcidat'); - case 'NLXNETCOM' - status = (exist('MatlabNetComClient') && exist('NlxConnectToServer') && exist('NlxGetNewCSCData')); - case 'DIPOLI' - status = exist('dipoli.m', 'file'); - case 'MNE' - status = (exist('fiff_read_meas_info', 'file') && exist('fiff_setup_read_raw', 'file')); - case 'TCP_UDP_IP' - status = (exist('pnet', 'file') && exist('pnet_getvar', 'file') && exist('pnet_putvar', 'file')); - case 'BEMCP' - status = (exist('bem_Cij_cog', 'file') && exist('bem_Cij_lin', 'file') && exist('bem_Cij_cst', 'file')); - case 'OPENMEEG' - status = exist('openmeeg.m', 'file'); - case 'PLOTTING' - status = (exist('plot_topo', 'file') && exist('plot_mesh', 'file') && exist('plot_matrix', 'file')); - case 'PRTOOLS' - status = (exist('prversion', 'file') && exist('dataset', 'file') && exist('svc', 'file')); - case 'LC-LIBS' - status = (exist('lcReadHeader', 'file') && exist('lcReadData', 'file')); - otherwise - if ~silent, warning(sprintf('cannot determine whether the %s toolbox is present', toolbox)); end - status = 0; -end - -% it should be a boolean value -status = (status~=0); - -% try to determine the path of the requested toolbox -if autoadd && ~status - - % for core fieldtrip modules - prefix = fileparts(which('preprocessing')); - if ~status - status = myaddpath(fullfile(prefix, lower(toolbox)), silent); - end - - % for external fieldtrip modules - prefix = fullfile(fileparts(which('preprocessing')), 'external'); - if ~status - status = myaddpath(fullfile(prefix, lower(toolbox)), silent); - end - - % for linux computers in the F.C. Donders Centre - prefix = '/home/common/matlab'; - if ~status && (strcmp(computer, 'GLNX86') || strcmp(computer, 'GLNXA64')) - status = myaddpath(fullfile(prefix, lower(toolbox)), silent); - end - - % for windows computers in the F.C. Donders Centre - prefix = 'h:\common\matlab'; - if ~status && (strcmp(computer, 'PCWIN') || strcmp(computer, 'PCWIN64')) - status = myaddpath(fullfile(prefix, lower(toolbox)), silent); - end - - % use the matlab subdirectory in your homedirectory, this works on unix and mac - prefix = [getenv('HOME') '/matlab']; - if ~status - status = myaddpath(fullfile(prefix, lower(toolbox)), silent); - end - - if ~status - % the toolbox is not on the path and cannot be added - sel = find(strcmp(url(:,1), toolbox)); - if ~isempty(sel) - msg = sprintf('the %s toolbox is not installed, %s', toolbox, url{sel, 2}); - else - msg = sprintf('the %s toolbox is not installed', toolbox); - end - error(msg); - end -end - -% this function is called many times in FieldTrip and associated toolboxes -% use efficient handling if the same toolbox has been investigated before -if status - previous.(fixname(toolbox)) = status; -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% helper function -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function status = myaddpath(toolbox, silent) -if exist(toolbox, 'dir') - if ~silent, warning(sprintf('adding %s toolbox to your Matlab path', toolbox)); end - addpath(toolbox); - status = 1; -else - status = 0; -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% helper function -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function out = fixname(toolbox) -out = lower(toolbox); -out(out=='-') = '_'; % fix dashes -out(out==' ') = '_'; % fix spaces - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% helper function -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function status = hasfunction(funname, toolbox) -try - % call the function without any input arguments, which probably is inapropriate - feval(funname); - % it might be that the function without any input already works fine - status = true; -catch - % either the function returned an error, or the function is not available - % availability is influenced by the function being present and by having a - % license for the function, i.e. in a concurrent licensing setting it might - % be that all toolbox licenses are in use - m = lasterror; - if strcmp(m.identifier, 'MATLAB:license:checkouterror') - if nargin>1 - warning('the %s toolbox is available, but you don''t have a license for it', toolbox); - else - warning('the function ''%s'' is available, but you don''t have a license for it', funname); - end - status = false; - elseif strcmp(m.identifier, 'MATLAB:UndefinedFunction') - status = false; - else - % the function seems to be available and it gave an unknown error, - % which is to be expected with inappropriate input arguments - status = true; - end -end - diff --git a/external/fileio/private/issubfield.m b/external/fileio/private/issubfield.m deleted file mode 100644 index 60d94f4..0000000 --- a/external/fileio/private/issubfield.m +++ /dev/null @@ -1,35 +0,0 @@ -function [r] = issubfield(s, f) - -% ISSUBFIELD tests for the presence of a field in a structure just like the standard -% Matlab ISFIELD function, except that you can also specify nested fields -% using a '.' in the fieldname. The nesting can be arbitrary deep. -% -% Use as -% f = issubfield(s, 'fieldname') -% or as -% f = issubfield(s, 'fieldname.subfieldname') -% -% This function returns true if the field is present and false if the field -% is not present. -% -% See also ISFIELD, GETSUBFIELD, SETSUBFIELD - -% Copyright (C) 2005, Robert Oostenveld -% -% $Log: issubfield.m,v $ -% Revision 1.2 2009/07/30 20:11:44 ingnie -% made output boolian -% -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.1 2005/02/08 09:30:18 roboos -% new implementations to make it easier to work with nested structures -% - -try - getsubfield(s, f); % if this works, then the subfield must be present - r = true; -catch - r = false; % apparently the subfield is not present -end \ No newline at end of file diff --git a/external/fileio/private/keyval.m b/external/fileio/private/keyval.m deleted file mode 100644 index 106cf02..0000000 --- a/external/fileio/private/keyval.m +++ /dev/null @@ -1,62 +0,0 @@ -function [val] = keyval(key, varargin) - -% KEYVAL returns the value that corresponds to the requested key in a -% key-value pair list of variable input arguments -% -% Use as -% [val] = keyval(key, varargin) -% -% See also VARARGIN - -% Copyright (C) 2005-2007, Robert Oostenveld -% -% $Log: keyval.m,v $ -% Revision 1.5 2009/08/04 11:58:28 roboos -% perform a case-insensitive string comparison for keys -% -% Revision 1.4 2009/07/14 16:11:02 roboos -% speed up the input checks -% -% Revision 1.3 2009/05/14 19:24:02 roboos -% removed ; at end of function declaration -% -% Revision 1.2 2009/01/06 09:05:26 roboos -% added additional check on optional input arguments: the 1st, 3rd, etc. should be strings (keys) -% -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.2 2007/07/18 12:43:53 roboos -% test for an even number of optional input arguments -% -% Revision 1.1 2005/11/04 10:24:46 roboos -% new implementation -% - -if length(varargin)==1 && iscell(varargin{1}) - varargin = varargin{1}; -end - -if mod(length(varargin),2) - error('optional input arguments should come in key-value pairs, i.e. there should be an even number'); -end - -% the 1st, 3rd, etc. contain the keys, the 2nd, 4th, etc. contain the values -keys = varargin(1:2:end); -vals = varargin(2:2:end); - -if ~all(cellfun(@ischar, keys)) - error('optional input arguments should come in key-value pairs, the optional input argument %d is invalid (should be a string)', i); -end - -hit = find(strcmpi(key, keys)); -if isempty(hit) - % the requested key was not found - val = []; -elseif length(hit)==1 - % the requested key was found - val = vals{hit}; -else - error('multiple input arguments with the same name'); -end - diff --git a/external/fileio/private/loadama.m b/external/fileio/private/loadama.m deleted file mode 100644 index 6e68fe4..0000000 --- a/external/fileio/private/loadama.m +++ /dev/null @@ -1,109 +0,0 @@ -function [ama] = loadama(filename); - -% LOADAMA read an inverted A-matrix and associated geometry information -% from an ama file that was written by Tom Oostendorp's DIPOLI -% -% Use as -% [ama] = loadama(filename) -% -% See also LOADTRI, LOADMAT - -% Copyright (C) 2005, Robert Oostenveld -% -% $Log: loadama.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.2 2008/11/12 17:02:03 roboos -% explicitely specify ieee-le in fopen() -% -% Revision 1.1 2005/11/16 13:50:51 roboos -% new implementation -% - -fid = fopen(filename, 'rb', 'ieee-le'); - -version = fread(fid, 1, 'int'); -if version~=10 - error(sprintf('%s is either not an inverted A matrix, or one of an old version', filename)); -end - -mode = fread(fid, 1, 'int'); -ngeo = fread(fid, 1, 'int'); - -totpnt = 0; -totdhk = 0; -nrow = 0; - -% read the boundaries -geo = []; -for i=1:ngeo - geo(i).name = char(fread(fid, [1 80], 'uchar')); - geo(i).npnt = fread(fid, 1, 'int'); - geo(i).pnt = fread(fid, [3 geo(i).npnt], 'float')'; - geo(i).ndhk = fread(fid, 1, 'int'); - geo(i).dhk = fread(fid, [3 geo(i).ndhk], 'int')' + 1; % Matlab indexing starts at 1 - geo(i).sigmam = fread(fid, 1, 'float'); - geo(i).sigmap = fread(fid, 1, 'float'); - geo(i).geocon = fread(fid, ngeo, 'int'); - geo(i).deflat = fread(fid, ngeo, 'float'); - totpnt = totpnt + geo(i).npnt; - totdhk = totdhk + geo(i).ndhk; -end - -% read the electrodes -if mode~=1 - elec.name = char(fread(fid, [1 80], 'uchar')); - elec.npnt = fread(fid, 1, 'int'); - for i=1:(elec.npnt+1) - elec.el(i).dhk = fread(fid, 1, 'int') + 1; % Matlab indexing starts at 1 - elec.el(i).la = fread(fid, 1, 'float'); - elec.el(i).mu = fread(fid, 1, 'float'); - elec.el(i).name = char(fread(fid, [1 10], 'char')); - % the ELECTRODE c-structure is padded to word boundaries, i.e. to 4 bytes - dum = fread(fid, 2, 'char'); - end - elec.vertex = fread(fid, 1, 'int'); - elec.surface = fread(fid, 1, 'int'); - nrow = nrow + elec.npnt; -else - elec = []; -end - -% read the gradiometers -if mode~=0 - error('gradiometers not yet implemented'); -else - grad = []; -end - -% read the inverted A-matrix -bi = fread(fid, [totpnt nrow], 'float')'; - -% read the isolated source compartment information, if present -iso_sur = fread(fid, 1, 'int') + 1; % Matlab indexing starts at 1 -inner_only = fread(fid, 1, 'int'); -if iso_sur~=0 - iso_totpnt = geo(iso_sur).npnt; - iso_b = fread(fid, [iso_totpnt iso_totpnt], 'float')'; -else - iso_b = []; -end - -fclose(fid); - -% put all local variables into a structure, this is a bit unusual programming style -% the output structure is messy, but contains all relevant information -tmp = whos; -ama = []; -for i=1:length(tmp) - if isempty(strmatch(tmp(i).name, {'tmp', 'fid', 'ans', 'handles'})) - ama = setfield(ama, tmp(i).name, eval(tmp(i).name)); - end -end - diff --git a/external/fileio/private/match_str.m b/external/fileio/private/match_str.m deleted file mode 100644 index 9903621..0000000 --- a/external/fileio/private/match_str.m +++ /dev/null @@ -1,85 +0,0 @@ -function [sel1, sel2] = match_str(a, b); - -% MATCH_STR looks for matching labels in two listst of strings -% and returns the indices into both the 1st and 2nd list of the matches. -% They will be ordered according to the first input argument. -% -% [sel1, sel2] = match_str(strlist1, strlist2) -% -% The strings can be stored as a char matrix or as an vertical array of -% cells, the matching is done for each row. - -% Copyright (C) 2000, Robert Oostenveld -% -% $Log: match_str.m,v $ -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.7 2008/07/17 10:26:11 roboos -% cleaned up the code a little bit, no functional change -% -% Revision 1.6 2006/11/06 21:11:45 roboos -% also deal with empty [] input -% -% Revision 1.5 2004/11/10 17:11:40 roboos -% reverted to original implementation and reimplemented the speed up -% from scratch. The previous two revisions both were incompatible -% with the original implementation. -% -% Revision 1.4 2004/11/09 15:28:57 roboos -% fixed incompatibility that was introduced by previous speed increase: -% the original version gave back double occurences, and other fieldtrip -% functions (sourceanalysis) rely on this. The previously commited -% version only gave back one occurence of each hit, this is fixed by jansch -% in this version -% -% Revision 1.3 2004/10/22 15:59:41 roboos -% large speed increase by replacing 2 nested for loops by a standard matlab function (intersect) -% -% Revision 1.2 2003/03/17 10:37:28 roberto -% improved general help comments and added copyrights - -% ensure that both are cell-arrays -if isempty(a) - a = {}; -elseif ~iscell(a) - a = cellstr(a); -end -if isempty(b) - b = {}; -elseif ~iscell(b) - b = cellstr(b); -end - -% regardless of what optimizations are implemented, the code should remain -% functionally compatible to the original, which is -% for i=1:length(a) -% for j=1:length(b) -% if strcmp(a(i),b(j)) -% sel1 = [sel1; i]; -% sel2 = [sel2; j]; -% end -% end -% end - -% ensure that both are column vectors -a = a(:); -b = b(:); -Na = numel(a); -Nb = numel(b); - -% replace all unique strings by a unique number and use the fact that -% numeric comparisons are much faster than string comparisons -[dum1, dum2, c] = unique([a; b]); -a = c(1:Na); -b = c((Na+1):end); - -sel1 = []; -sel2 = []; -for i=1:length(a) - % s = find(strcmp(a(i), b)); % for string comparison - s = find(a(i)==b); % for numeric comparison - sel2 = [sel2; s]; - s(:) = i; - sel1 = [sel1; s]; -end diff --git a/external/fileio/private/mxDeserialize.m b/external/fileio/private/mxDeserialize.m deleted file mode 100644 index f4cc216..0000000 --- a/external/fileio/private/mxDeserialize.m +++ /dev/null @@ -1,35 +0,0 @@ -function [varargout] = funname(varargin) - -% FUNNAME compile the missing mex file on the fly - -% remember the original working directory -pwdir = pwd; - -% determine the name and full path of this function -funname = mfilename('fullpath'); -mexsrc = [funname '.c']; -[mexdir, mexname] = fileparts(funname); - -try - % try to compile the mex file on the fly - warning('trying to compile MEX file from %s', mexsrc); - cd(mexdir); - mex(mexsrc); - cd(pwdir); - success = true; - -catch - % compilation failed - disp(lasterr); - error('could not locate MEX file for %s', mexname); - cd(pwdir); - success = false; -end - -if success - % execute the mex file that was juist created - funname = mfilename; - funhandle = str2func(funname); - [varargout{1:nargout}] = funhandle(varargin{:}); -end - diff --git a/external/fileio/private/mxSerialize.m b/external/fileio/private/mxSerialize.m deleted file mode 100644 index f4cc216..0000000 --- a/external/fileio/private/mxSerialize.m +++ /dev/null @@ -1,35 +0,0 @@ -function [varargout] = funname(varargin) - -% FUNNAME compile the missing mex file on the fly - -% remember the original working directory -pwdir = pwd; - -% determine the name and full path of this function -funname = mfilename('fullpath'); -mexsrc = [funname '.c']; -[mexdir, mexname] = fileparts(funname); - -try - % try to compile the mex file on the fly - warning('trying to compile MEX file from %s', mexsrc); - cd(mexdir); - mex(mexsrc); - cd(pwdir); - success = true; - -catch - % compilation failed - disp(lasterr); - error('could not locate MEX file for %s', mexname); - cd(pwdir); - success = false; -end - -if success - % execute the mex file that was juist created - funname = mfilename; - funhandle = str2func(funname); - [varargout{1:nargout}] = funhandle(varargin{:}); -end - diff --git a/external/fileio/private/neuralynx_crc.m b/external/fileio/private/neuralynx_crc.m deleted file mode 100644 index 132bffb..0000000 --- a/external/fileio/private/neuralynx_crc.m +++ /dev/null @@ -1,34 +0,0 @@ -function crc = neuralynx_crc(dat, dim) - -% NEURALYNX_CRC computes a cyclic redundancy check -% -% Use as -% crc = neuralynx_crc(dat) -% -% Note that the CRC is computed along the first dimension. - -% Copyright (C) 2007, Robert Oostenveld -% -% $Log: neuralynx_crc.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.1 2007/02/20 08:52:04 roboos -% new implementation -% - - -nchans = size(dat,1); -nsamples = size(dat,2); - -crc = zeros(1,nsamples,class(dat)); - -for i=1:nchans - crc = bitxor(crc, dat(i,:)); -end - diff --git a/external/fileio/private/neuralynx_getheader.m b/external/fileio/private/neuralynx_getheader.m deleted file mode 100644 index dfc85be..0000000 --- a/external/fileio/private/neuralynx_getheader.m +++ /dev/null @@ -1,56 +0,0 @@ -function [hdr] = neuralynx_getheader(filename); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION for reading the 16384 byte header from any Neuralynx file -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -fid = fopen(filename, 'rb', 'ieee-le'); -buf = fread(fid, 16*1024, 'uint8=>char'); -fclose(fid); - -buf = buf(:)'; -nl = find(buf==10); % determine the new-lines -cr = find(buf==13); % determine the carriage-returns -begchar = [1 nl(1:(end-1))]; -endchar = nl - 1; -num = length(nl); - -hdr = []; -hdr.Header = buf; % remember the full header in its original format - -for i=1:num - line = fliplr(deblank(fliplr(deblank(char(buf(begchar(i):endchar(i))))))); - if numel(line)==0 - % line is empty - continue - elseif line(1)=='#' - % line contains a comment - continue - else - % strip the '-' sign - while line(1)=='-' - line = line(2:end); - end - % replace tabs with spaces - line(find(line==9)) = ' '; - % cut into pieces - item = strread(line, '%s'); - if length(item)==2 - key = item{1}; - val = item{2}; - if any(val(1)=='-01234567989') - % try to convert to number - val = str2num(val); - if isempty(val) - % revert to the original text - val = item{2}; - end - end - % remove unuseable characters from the variable name (key) - key = key(key~=':'); - % assign the value to the header structure - hdr = setfield(hdr, key, val); - end - end -end - diff --git a/external/fileio/private/neuralynx_numrecords.m b/external/fileio/private/neuralynx_numrecords.m deleted file mode 100644 index 7755516..0000000 --- a/external/fileio/private/neuralynx_numrecords.m +++ /dev/null @@ -1,22 +0,0 @@ -function [t] = neuralynx_numrecords(filename); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION for determining the number of records in a single channel Neualynx file -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -headersize = 16384; -switch filetype(filename) - case 'neuralynx_ncs' - recordsize = 1044; % in bytes - case 'neuralynx_nse' - recordsize = 112; % in bytes - case 'neuralynx_nts' - recordsize = 8; % in bytes - otherwise - error('unsupported filetype'); -end - -fid = fopen(filename, 'rb', 'ieee-le'); -fseek(fid, 0, 'eof'); -t = floor((ftell(fid) - headersize)/recordsize); -fclose(fid); diff --git a/external/fileio/private/neuralynx_timestamp.m b/external/fileio/private/neuralynx_timestamp.m deleted file mode 100644 index 94e6b91..0000000 --- a/external/fileio/private/neuralynx_timestamp.m +++ /dev/null @@ -1,48 +0,0 @@ -function [t] = neuralynx_timestamp(filename, num) - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION for reading a single timestamp of a single channel Neuralynx file -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -headersize = 16384; -switch filetype(filename) - case 'neuralynx_ncs' - recordsize = 1044; % in bytes - case 'neuralynx_nse' - recordsize = 112; % in bytes - case 'neuralynx_nst' - recordsize = 304; % in bytes - case 'neuralynx_nts' - recordsize = 8; % in bytes - case 'neuralynx_ntt' - recordsize = 304; % in bytes -end - -fid = fopen(filename, 'rb', 'ieee-le'); - -if (ispc) - % this is to fix a bug in the windwos version which does not want to do uint64=>uint64 - % however this code will fail if the MSB is set (only likely in very long recordings) - if ~isinf(num) - % read the timestamp of the indicated record - fseek(fid, headersize + (num-1)*recordsize, 'bof'); - t = fread(fid, 1, 'uint64=>integer*8'); - else - % read the timestamp of the last record - fseek(fid, -recordsize, 'eof'); - t = fread(fid, 1, 'uint64=>integer*8'); - end - t = uint64(t); -else - if ~isinf(num) - % read the timestamp of the indicated record - fseek(fid, headersize + (num-1)*recordsize, 'bof'); - t = fread(fid, 1, 'uint64=>uint64'); - else - % read the timestamp of the last record - fseek(fid, -recordsize, 'eof'); - t = fread(fid, 1, 'uint64=>uint64'); - end -end - -fclose(fid); diff --git a/external/fileio/private/nex_cont.m b/external/fileio/private/nex_cont.m deleted file mode 100644 index 20cf5ba..0000000 --- a/external/fileio/private/nex_cont.m +++ /dev/null @@ -1,114 +0,0 @@ -function [adfreq, n, ts, fn, d] = nex_cont(filename, varname) -% nex_cont(filename, varname): Read continuous variable from a .nex file -% -% [adfreq, n, ts, fn, d] = nex_cont(filename, varname) -% -% INPUT: -% filename - if empty string, will use File Open dialog -% varname - variable name -% -% continuous (a/d) data come in fragments. Each fragment has a timestamp -% and a number of a/d data points. The timestamp corresponds to -% the time of recording of the first a/d value in this fragment. -% All the data values stored in the vector d. -% OUTPUT: -% n - total number of data points -% ts - array of fragment timestamps (one timestamp for fragment, in seconds) -% fn - number of data points in each fragment -% d - array of a/d values (in millivolts) - -% original from Plexon, download from http://www.plexoninc.com (8/4/02) -% modifications by Robert Oostenveld -% -% $Log: nex_cont.m,v $ -% Revision 1.3 2008/09/30 07:47:04 roboos -% replaced all occurences of setstr() with char(), because setstr is deprecated by Matlab -% -% Revision 1.2 2008/07/24 12:03:23 roboos -% changed end of line to unix style -% -% Revision 1.1 2005/02/11 07:46:34 roboos -% downloaded from Plexon website, added support for reading nex files on Solaris and Mac OS X (fopen ieee-le), added log-section to the comments after the help -% - -n = 0; -adfreq = 0; -ts = 0; -fn = 0; -d = 0; - -if(nargin ~= 2) - disp('2 input arguments are required') - return -end - -if(ischar(filename) == 0) - disp('input arguments should be character arrays') - return -end - -if(ischar(varname) == 0) - disp('input arguments should be character arrays') - return -end - -if(length(filename) == 0) - [fname, pathname] = uigetfile('*.nex', 'Select a Nex file'); - filename = strcat(pathname, fname); -end - -fid = fopen(filename, 'r', 'ieee-le'); -if(fid == 0) - return -end - -disp(strcat('file = ', filename)); -magic = fread(fid, 1, 'int32'); -version = fread(fid, 1, 'int32'); -comment = fread(fid, 256, 'char'); -freq = fread(fid, 1, 'double'); -tbeg = fread(fid, 1, 'int32'); -tend = fread(fid, 1, 'int32'); -nvar = fread(fid, 1, 'int32'); -fseek(fid, 260, 'cof'); -name = zeros(1, 64); -found = 0; -for i=1:nvar - type = fread(fid, 1, 'int32'); - var_version = fread(fid, 1, 'int32'); - name = fread(fid, [1 64], 'char'); - offset = fread(fid, 1, 'int32'); - nf = fread(fid, 1, 'int32'); - dummy = fread(fid, 32, 'char'); - adfreq = fread(fid, 1, 'double'); - adtomv = fread(fid, 1, 'double'); - n = fread(fid, 1, 'int32'); - name = char(name); - name = deblank(name); - k = strcmp(name, deblank(varname)); - if(k == 1) - if type ~= 5 - disp(sprintf('%s is not a continuous variable', deblank(varname))); - return; - end - found = 1; - fseek(fid, offset, 'bof'); - ts = fread(fid, [1 nf], 'int32'); - fn = fread(fid, [1 nf], 'int32'); - d = fread(fid, [1 n], 'int16'); - break - end - dummy = fread(fid, 76, 'char'); -end - -fclose(fid); - -if found == 0 - disp('did not find variable in the file'); -else - ts = ts/freq; - d = d*adtomv; - fn(nf+1) = n; - fn = diff(fn); - disp(strcat('number of data points = ', num2str(n))); -end diff --git a/external/fileio/private/nex_info.m b/external/fileio/private/nex_info.m deleted file mode 100644 index 657689b..0000000 --- a/external/fileio/private/nex_info.m +++ /dev/null @@ -1,66 +0,0 @@ -function [nvar, names, types] = nex_info(filename) -% nex_info(filename) -- read and display .nex file info -% -% [nvar, names, types] = nex_info(filename) -% -% INPUT: -% filename - if empty string, will use File Open dialog -% OUTPUT: -% nvar - number of variables in the file -% names - [nvar 64] array of variable names -% types - [1 nvar] array of variable types -% Interpretation of type values: 0-neuron, 1-event, 2-interval, 3-waveform, -% 4-population vector, 5-continuous variable, 6 - marker - -% original from Plexon, download from http://www.plexoninc.com (8/4/02) -% modifications by Robert Oostenveld -% -% $Log: nex_info.m,v $ -% Revision 1.3 2008/09/30 07:47:04 roboos -% replaced all occurences of setstr() with char(), because setstr is deprecated by Matlab -% -% Revision 1.2 2008/07/24 12:03:23 roboos -% changed end of line to unix style -% -% Revision 1.1 2005/02/11 07:46:34 roboos -% downloaded from Plexon website, added support for reading nex files on Solaris and Mac OS X (fopen ieee-le), added log-section to the comments after the help -% - -if(nargin ~= 1) - disp('1 input arguments are required') - return -end - -if(length(filename) == 0) - [fname, pathname] = uigetfile('*.nex', 'Select a Nex file'); - filename = strcat(pathname, fname); -end - -fid = fopen(filename, 'r', 'ieee-le'); -if(fid == -1) - disp('cannot open file'); - return -end - -disp(strcat('file = ', filename)); -magic = fread(fid, 1, 'int32'); -version = fread(fid, 1, 'int32'); -comment = fread(fid, 256, 'char'); -freq = fread(fid, 1, 'double'); -tbeg = fread(fid, 1, 'int32'); -tend = fread(fid, 1, 'int32'); -nvar = fread(fid, 1, 'int32'); -fseek(fid, 260, 'cof'); -disp(strcat('version = ', num2str(version))); -disp(strcat('frequency = ', num2str(freq))); -disp(strcat('duration (sec) = ', num2str((tend - tbeg)/freq))); -disp(strcat('number of variables = ', num2str(nvar))); -names = zeros(1, 64); -for i=1:nvar - types(i) = fread(fid, 1, 'int32'); - var_version = fread(fid, 1, 'int32'); - names(i, :) = fread(fid, [1 64], 'char'); - dummy = fread(fid, 128+8, 'char'); -end -names = char(names); -fclose(fid); diff --git a/external/fileio/private/nex_int.m b/external/fileio/private/nex_int.m deleted file mode 100644 index 8afdc5d..0000000 --- a/external/fileio/private/nex_int.m +++ /dev/null @@ -1,100 +0,0 @@ -function [n, ts_left, ts_right] = nex_int(filename, varname) -% nex_int(filename, varname): Read interval variable from a .nex file -% -% [n, ts_left, ts_right] = nex_int(filename, varname) -% -% INPUT: -% filename - if empty string, will use File Open dialog -% varname - variable name -% OUTPUT: -% n - number of intervals -% ts_left - array of left ends of the intervals (in seconds) -% ts_right - array of right ends of the intervals (in seconds) - -% original from Plexon, download from http://www.plexoninc.com (8/4/02) -% modifications by Robert Oostenveld -% -% $Log: nex_int.m,v $ -% Revision 1.3 2008/09/30 07:47:04 roboos -% replaced all occurences of setstr() with char(), because setstr is deprecated by Matlab -% -% Revision 1.2 2008/07/24 12:03:23 roboos -% changed end of line to unix style -% -% Revision 1.1 2005/02/11 07:46:34 roboos -% downloaded from Plexon website, added support for reading nex files on Solaris and Mac OS X (fopen ieee-le), added log-section to the comments after the help -% - -n = 0; -ts_left = 0; -ts_right = 0; - -if(nargin ~= 2) - disp('2 input arguments are required') - return -end - -if(ischar(filename) == 0) - disp('input arguments should be character arrays') - return -end - -if(ischar(varname) == 0) - disp('input arguments should be character arrays') - return -end - -if(length(filename) == 0) - [fname, pathname] = uigetfile('*.nex', 'Select a Nex file'); - filename = strcat(pathname, fname); -end - -fid = fopen(filename, 'r', 'ieee-le'); -if(fid == -1) - disp('cannot open file'); - return -end - -disp(strcat('file = ', filename)); -magic = fread(fid, 1, 'int32'); -version = fread(fid, 1, 'int32'); -comment = fread(fid, 256, 'char'); -freq = fread(fid, 1, 'double'); -tbeg = fread(fid, 1, 'int32'); -tend = fread(fid, 1, 'int32'); -nvar = fread(fid, 1, 'int32'); -fseek(fid, 260, 'cof'); -name = zeros(1, 64); -found = 0; -for i=1:nvar - type = fread(fid, 1, 'int32'); - var_version = fread(fid, 1, 'int32'); - name = fread(fid, [1 64], 'char'); - offset = fread(fid, 1, 'int32'); - n = fread(fid, 1, 'int32'); - name = char(name); - name = deblank(name); - k = strcmp(name, deblank(varname)); - if(k == 1) - if type ~= 2 - disp(sprintf('%s is not an interval variable', deblank(varname))); - return; - end - found = 1; - fseek(fid, offset, 'bof'); - ts_left = fread(fid, [1 n], 'int32'); - ts_right = fread(fid, [1 n], 'int32'); - break - end - dummy = fread(fid, 128, 'char'); -end - -fclose(fid); - -if found == 0 - disp('did not find variable in the file'); -else - ts_left = ts_left/freq; - ts_right = ts_right/freq; - disp(strcat('number of intervals = ', num2str(n))); -end diff --git a/external/fileio/private/nex_marker.m b/external/fileio/private/nex_marker.m deleted file mode 100644 index f1593b2..0000000 --- a/external/fileio/private/nex_marker.m +++ /dev/null @@ -1,125 +0,0 @@ -function [n, nm, nl, ts, names, m] = nex_marker(filename, varname) -% nex_marker(filename, varname): Read a marker variable from a .nex file -% -% [n, nm, nl, ts, names, m] = nex_marker(filename, varname) -% -% INPUT: -% filename - if empty string, will use File Open dialog -% varname - variable name -% -% continuous (a/d) data come in fragments. Each fragment has a timestamp -% and a number of a/d data points. The timestamp corresponds to -% the time of recording of the first a/d value in this fragment. -% All the data values stored in the vector d. -% OUTPUT: -% n - number of markers -% nm - number of fields in each marker -% nl - number of characters in each marker field -% ts - array of marker timestamps (in seconds) -% names - names of marker fields ([nm 64] character array) -% m - character array of marker values [n nl nm] - -% original from Plexon, download from http://www.plexoninc.com (8/4/02) -% modifications by Robert Oostenveld -% -% $Log: nex_marker.m,v $ -% Revision 1.3 2008/09/30 07:47:04 roboos -% replaced all occurences of setstr() with char(), because setstr is deprecated by Matlab -% -% Revision 1.2 2008/07/24 11:57:57 roboos -% converted end of line into unix style -% -% Revision 1.1 2005/02/11 07:46:34 roboos -% downloaded from Plexon website, added support for reading nex files on Solaris and Mac OS X (fopen ieee-le), added log-section to the comments after the help -% - -n = 0; -nm = 0; -nl = 0; -ts = 0; -m = 0; -names = 0; - -if(nargin ~= 2) - disp('2 input arguments are required') - return -end - -if(ischar(filename) == 0) - disp('input arguments should be character arrays') - return -end - -if(ischar(varname) == 0) - disp('input arguments should be character arrays') - return -end - -if(length(filename) == 0) - [fname, pathname] = uigetfile('*.nex', 'Select a Nex file'); - filename = strcat(pathname, fname); -end - -fid = fopen(filename, 'r', 'ieee-le'); -if(fid == -1) - disp('cannot open file'); - return -end - -disp(strcat('file = ', filename)); -magic = fread(fid, 1, 'int32'); -version = fread(fid, 1, 'int32'); -comment = fread(fid, 256, 'char'); -freq = fread(fid, 1, 'double'); -tbeg = fread(fid, 1, 'int32'); -tend = fread(fid, 1, 'int32'); -nvar = fread(fid, 1, 'int32'); -fseek(fid, 260, 'cof'); -name = zeros(1, 64); -found = 0; -for i=1:nvar - type = fread(fid, 1, 'int32'); - var_version = fread(fid, 1, 'int32'); - name = fread(fid, [1 64], 'char'); - offset = fread(fid, 1, 'int32'); - n = fread(fid, 1, 'int32'); - dummy = fread(fid, 32, 'char'); - adfreq = fread(fid, 1, 'double'); - adtomv = fread(fid, 1, 'double'); - npw = fread(fid, 1, 'int32'); - nm = fread(fid, 1, 'int32'); - nl = fread(fid, 1, 'int32'); - dummy = fread(fid, 68, 'char'); - name = char(name); - name = deblank(name); - k = strcmp(name, deblank(varname)); - if(k == 1) - if type ~= 6 - disp(sprintf('%s is not a marker variable', deblank(varname))); - return; - end - found = 1; - fseek(fid, offset, 'bof'); - ts = fread(fid, [1 n], 'int32'); - names = zeros(1,64); - m = zeros(n, nl, nm); - for j=1:nm - names(j, :) = fread(fid, [1 64], 'char'); - for p = 1:n - m(p, :, j) = fread(fid, [1 nl], 'char'); - end - end - break - end -end - -fclose(fid); - -if found == 0 - disp('did not find variable in the file'); -else - names = char(names); - m = char(m); - ts = ts/freq; - disp(strcat('number of markers = ', num2str(n))); -end diff --git a/external/fileio/private/nex_ts.m b/external/fileio/private/nex_ts.m deleted file mode 100644 index 568cd22..0000000 --- a/external/fileio/private/nex_ts.m +++ /dev/null @@ -1,92 +0,0 @@ -function [n, ts] = nex_ts(filename, varname) -% nex_ts(filename, varname): Read timestamps from a .nex file -% -% [n, ts] = nex_ts(filename, varname) -% -% INPUT: -% filename - if empty string, will use File Open dialog -% varname - variable name -% OUTPUT: -% n - number of timestamps -% ts - array of timestamps (in seconds) - -% original from Plexon, download from http://www.plexoninc.com (8/4/02) -% modifications by Robert Oostenveld -% -% $Log: nex_ts.m,v $ -% Revision 1.3 2008/09/30 07:47:04 roboos -% replaced all occurences of setstr() with char(), because setstr is deprecated by Matlab -% -% Revision 1.2 2008/07/24 12:03:23 roboos -% changed end of line to unix style -% -% Revision 1.1 2005/02/11 07:46:34 roboos -% downloaded from Plexon website, added support for reading nex files on Solaris and Mac OS X (fopen ieee-le), added log-section to the comments after the help -% - -n = 0; -ts = 0; - -if(nargin ~= 2) - disp('2 input arguments are required') - return -end - -if(ischar(filename) == 0) - disp('input arguments should be character arrays') - return -end - -if(ischar(varname) == 0) - disp('input arguments should be character arrays') - return -end - -if(length(filename) == 0) - [fname, pathname] = uigetfile('*.nex', 'Select a Nex file'); - filename = strcat(pathname, fname); -end - -fid = fopen(filename, 'r', 'ieee-le'); -if(fid == -1) - disp('cannot open file'); - return -end - -disp(strcat('file = ', filename)); -magic = fread(fid, 1, 'int32'); -version = fread(fid, 1, 'int32'); -comment = fread(fid, 256, 'char'); -freq = fread(fid, 1, 'double'); -tbeg = fread(fid, 1, 'int32'); -tend = fread(fid, 1, 'int32'); -nvar = fread(fid, 1, 'int32'); -fseek(fid, 260, 'cof'); -name = zeros(1, 64); -found = 0; -for i=1:nvar - type = fread(fid, 1, 'int32'); - var_version = fread(fid, 1, 'int32'); - name = fread(fid, [1 64], 'char'); - offset = fread(fid, 1, 'int32'); - n = fread(fid, 1, 'int32'); - name = char(name); - name = deblank(name); - k = strcmp(name, deblank(varname)); - if(k == 1) - found = 1; - fseek(fid, offset, 'bof'); - ts = fread(fid, [1 n], 'int32'); - break - end - dummy = fread(fid, 128, 'char'); -end - -fclose(fid); - -if found == 0 - disp('did not find variable in the file'); -else - ts = ts/freq; - disp(strcat('number of timestamps = ', num2str(n))); -end diff --git a/external/fileio/private/nex_wf.m b/external/fileio/private/nex_wf.m deleted file mode 100644 index 4580189..0000000 --- a/external/fileio/private/nex_wf.m +++ /dev/null @@ -1,108 +0,0 @@ -function [adfreq, n, ts, nf, w] = nex_wf(filename, varname) -% nex_wf(filename, varname): Read waveform variable from a .nex file -% -% [adfreq, n, ts, nf, w] = nex_wf(filename, varname) -% -% INPUT: -% filename - if empty string, will use File Open dialog -% varname - variable name -% -% -% OUTPUT: -% n - number of waveforms -% ts - array of waveform timestamps (in seconds) -% nf - number of data points in each waveform -% w - matrix of waveform a/d values [n nf] (in millivolts) - -% original from Plexon, download from http://www.plexoninc.com (8/4/02) -% modifications by Robert Oostenveld -% -% $Log: nex_wf.m,v $ -% Revision 1.3 2008/09/30 07:47:04 roboos -% replaced all occurences of setstr() with char(), because setstr is deprecated by Matlab -% -% Revision 1.2 2008/07/24 12:02:01 roboos -% changed end of line to unix style -% -% Revision 1.1 2005/02/11 07:46:34 roboos -% downloaded from Plexon website, added support for reading nex files on Solaris and Mac OS X (fopen ieee-le), added log-section to the comments after the help -% - -n = 0; -adfreq = 0; -ts = 0; -nf = 0; -w = 0; - -if(nargin ~= 2) - disp('2 input arguments are required') - return -end - -if(ischar(filename) == 0) - disp('input arguments should be character arrays') - return -end - -if(ischar(varname) == 0) - disp('input arguments should be character arrays') - return -end - -if(length(filename) == 0) - [fname, pathname] = uigetfile('*.nex', 'Select a Nex file'); - filename = strcat(pathname, fname); -end - -fid = fopen(filename, 'r', 'ieee-le'); -if(fid == 0) - return -end - -disp(strcat('file = ', filename)); -magic = fread(fid, 1, 'int32'); -version = fread(fid, 1, 'int32'); -comment = fread(fid, 256, 'char'); -freq = fread(fid, 1, 'double'); -tbeg = fread(fid, 1, 'int32'); -tend = fread(fid, 1, 'int32'); -nvar = fread(fid, 1, 'int32'); -fseek(fid, 260, 'cof'); -name = zeros(1, 64); -found = 0; -for i=1:nvar - type = fread(fid, 1, 'int32'); - var_version = fread(fid, 1, 'int32'); - name = fread(fid, [1 64], 'char'); - offset = fread(fid, 1, 'int32'); - nf = fread(fid, 1, 'int32'); - dummy = fread(fid, 32, 'char'); - adfreq = fread(fid, 1, 'double'); - adtomv = fread(fid, 1, 'double'); - n = fread(fid, 1, 'int32'); - name = char(name); - name = deblank(name); - k = strcmp(name, deblank(varname)); - if(k == 1) - if type ~= 3 - disp(sprintf('%s is not a waveform variable', deblank(varname))); - return; - end - found = 1; - fseek(fid, offset, 'bof'); - ts = fread(fid, [1 nf], 'int32'); - w = fread(fid, [n nf], 'int16'); - break - end - dummy = fread(fid, 76, 'char'); -end - -fclose(fid); - -if found == 0 - disp('did not find variable in the file'); -else - ts = ts/freq; - w = w*adtomv; - disp(strcat('number of waveforms = ', num2str(nf))); -end diff --git a/external/fileio/private/nimh2grad.m b/external/fileio/private/nimh2grad.m deleted file mode 100644 index 32ff8da..0000000 --- a/external/fileio/private/nimh2grad.m +++ /dev/null @@ -1,88 +0,0 @@ -function [grad] = nimh2grad(hdr); - -% NIMH2GRAD constructs a gradiometer definition from the res4 header whish -% is read using the NIMH implementation of ctf_read_res4. The grad -% structure is compatible with FieldTrip and Robert Oostenveld's low-level -% forward and inverse routines. -% -% Use as -% hdr = ctf_read_res4(dataset); -% grad = nimh2grad(hdr; -% -% See also CTF2GRAD, FIF2GRAD - -% Copyright (C) 2005, Robert Oostenveld -% -% $Log: nimh2grad.m,v $ -% Revision 1.3 2007/03/07 08:37:55 roboos -% fixed typo -% -% Revision 1.2 2007/03/06 09:37:35 roboos -% small change in determining the MEG channels, thanks to Nicolas Robitaille -% -% Revision 1.1 2006/08/31 13:32:11 roboos -% moved from fieldtrip to fileio module -% -% Revision 1.1 2005/05/26 09:55:55 roboos -% new implementation to complement the NIMH ctf reading routines -% - -% only work on the MEG channels -if isfield(hdr.sensor.index, 'meg') - sel = hdr.sensor.index.meg; -else - sel = hdr.sensor.index.meg_sens; -end - -% start with an empty structure -grad.pnt = []; -grad.ori = []; -grad.tra = []; -grad.label = {}; - -for i=1:length(sel) - pnt = hdr.sensor.info(sel(i)).location'; - ori = hdr.sensor.info(sel(i)).orientation'; - numcoils(i) = size(pnt,1); - if size(ori,1)==1 && size(pnt,1)==1 - % one coil position with one orientation: magnetometer - ori = ori; - elseif size(ori,1)==1 && size(pnt,1)==2 - % two coil positions with one orientation: first order gradiometer - % assume that the orientation of the upper coil is opposite to the lower coil - ori = [ori; -ori]; - else - error('do not know how to deal with higher order gradiometer hardware') - end - - % add this channels coil positions and orientations - grad.pnt = [grad.pnt; pnt]; - grad.ori = [grad.ori; ori]; - grad.label{i} = hdr.sensor.info(sel(i)).label; - - % determine the contribution of each coil to each channel's output signal - if size(pnt,1)==1 - % one coil, assume that the orientation is correct, i.e. the weight is +1 - grad.tra(i,end+1) = 1; - elseif size(pnt,1)==2 - % two coils, assume that the orientation for each coil is correct, i.e. the weights are +1 and +1 - grad.tra(i,end+1) = 1; - grad.tra(i,end+1) = 1; - else - error('do not know how to deal with higher order gradiometer hardware') - end -end - -% prefer to have the labels in a column vector -grad.label = grad.label(:); - -% reorder the coils, such that the bottom coils are at the first N -% locations and the top coils at the last N positions. This makes it -% easier to use a selection of the coils for topographic plotting -if all(numcoils==2) - bot = 1:2:sum(numcoils); - top = 2:2:sum(numcoils); - grad.pnt = grad.pnt([bot top], :); - grad.ori = grad.ori([bot top], :); - grad.tra = grad.tra(:, [bot top]); -end diff --git a/external/fileio/private/readBESAbsa.m b/external/fileio/private/readBESAbsa.m deleted file mode 100644 index 43a9927..0000000 --- a/external/fileio/private/readBESAbsa.m +++ /dev/null @@ -1,66 +0,0 @@ -function bsa = readBESAbsa(filename) - -% readBESAbsa reads information from a *.bsa file -% -% Use as -% bsa = readBESAbsa(filename) -% -% The output is a structure containing the following fields: -% CoordinateSystem: Coordinate System: -% HC = Head Coordinates -% US = Unit Sphere -% TC = Talairach Coordinates -% DC = Device Coordinates -% Coords: [Nsources x 3] matrix with source coordinates -% Orientation: [Nsources x 3] matrix with source orientations -% (x,y,z) -% (Orientation = [0 0 0] for regional sources) -% SourceType: Type of source: -% SngDip = Single Dipole -% RegSrc = Regional Source -% SptCmp = Spatial Component -% Labels: Source Labels (if assigned in BESA) -% -% Last modified April 26, 2006 Robert Oostenveld - -if isempty(findstr(filename,'.')) - filename = [filename,'.bsa']; -end -fp = fopen(filename); - -% Read the file -if (fp) - % Read header of .swf file - header = fgetl(fp); - if header(end-3)=='|' - bsa.CoordinateSystem = 'US'; - else - bsa.CoordinateSystem = header(end-1:end); - end - fgetl(fp); - fgetl(fp); - - for i=1:1000 - try % check if there is another waveform - Typ = cellstr(fscanf(fp,'%s',1)); - bsa.Coords(i,1) = fscanf(fp,'%f',1); - bsa.Coords(i,2) = fscanf(fp,'%f',1); - bsa.Coords(i,3) = fscanf(fp,'%f',1); - bsa.Orientation(i,1) = fscanf(fp,'%f',1); - bsa.Orientation(i,2) = fscanf(fp,'%f',1); - bsa.Orientation(i,3) = fscanf(fp,'%f',1); - bsa.SourceType(i) = Typ; - a = fgetl(fp); - b = a(findstr(a,'Label:')+6:end); - if ~isempty(b) - bsa.Labels(i) = cellstr(sscanf(b,'%s',1)); - else - bsa.Labels(i) = cellstr(''); - end - catch % stop if end of file is reached - break - end - end -end - -fclose(fp); \ No newline at end of file diff --git a/external/fileio/private/readBESAimage.m b/external/fileio/private/readBESAimage.m deleted file mode 100644 index a4b8ad3..0000000 --- a/external/fileio/private/readBESAimage.m +++ /dev/null @@ -1,164 +0,0 @@ -function image = readBESAImage(filename) - -% readBESAimage reads information from exported BESA images (MSBF, BSPS, -% Sensitivity, Minimum Norm). -% -% Use as -% image = readBESAimage(filename) -% -% The output is a structure containing the following fields: -% Condition -% Coordinates -% Data -% DataFile -% DepthWeighting -% Dimension -% Frequency -% Imagemode -% Imagetype -% Latency -% Locations -% NoiseEstimation -% NoiseScaleFactor -% NoiseWeighting -% SelMeanNoise -% Source -% SpTmpWeighting -% SpTmpWeightingType -% Time -% TimeSamples -% Units -% Version -% -% Modified April 26, 2006 Robert Oostenveld -% Modified November 6, 2006 Karsten Hoechstetter - -if isempty(findstr(filename,'.')) - filename = [filename,'.dat']; -end -fp = fopen(filename); - -ImageVersion = fgetl(fp); - -% Check Version Number -% image.Version = str2num(ImageVersion(findstr(ImageVersion,':')+1:length(ImageVersion))); - -% Check type of Image -Imageinfo = ''; -if ~isempty(findstr(ImageVersion,'MN')) - image.Imagetype = 'Minimum Norm'; - image.Imagemode = ''; -else - fgetl(fp); - ImageInfo = fgetl(fp); - - if ~isempty(findstr(ImageInfo,'Sens.')) - image.Imagetype = 'Sensitivity'; - image.Imagemode = ''; - elseif ~isempty(findstr(ImageInfo,'MSBF')) - image.Imagetype = 'MSBF'; - if ~isempty(findstr(ImageInfo,'Image (TF)')) - image.Imagemode = 'Time-Frequency'; - else - image.Imagemode = 'Time'; - end - elseif ~isempty(findstr(ImageInfo,'MSPS')) - image.Imagetype = 'MSPS'; - if ~isempty(findstr(ImageInfo,'Image (TF)')) - image.Imagemode = 'Time-Frequency'; - else - image.Imagemode = 'Time'; - end - else - image.Imagetype = 'Unknown'; - image.Imagemode = 'Unknown'; - end - - if ImageInfo(end-3:end) == '[dB]' - image.Units = 'dB'; - else - image.Units = '%'; - end -end - -% Extract additional information (time and frequency, source, MN Info) -if strcmp(image.Imagemode,'Time-Frequency') - TimeSeparator = findstr(ImageInfo,' : '); - Blanks = findstr(ImageInfo,' '); - [x,Index] = min(abs(Blanks-TimeSeparator)); - TimeIndex=Blanks(Index-1); - image.Time = sscanf(ImageInfo(TimeIndex:end),'%s',4); - image.Frequency = sscanf(ImageInfo(findstr(ImageInfo,'ms')+3:end),'%s',2); -elseif strcmp(image.Imagetype,'Sensitivity') - image.Source = ImageInfo(findstr(ImageInfo,' - ')+3:end); -elseif strcmp(image.Imagetype,'Minimum Norm') - fgetl(fp); - h = fgetl(fp); image.DataFile = h(21:end); - h = fgetl(fp); image.Condition = h(21:end); - fgetl(fp); - h = fgetl(fp); image.DepthWeighting = h(21:end); - h = fgetl(fp); image.SpTmpWeighting = h(21:end); - h = fgetl(fp); image.SpTmpWeightingType = h(21:end); - h = fgetl(fp); image.Dimension = str2num(h(21:end)); - h = fgetl(fp); image.NoiseEstimation = h(21:end); - h = fgetl(fp); image.NoiseWeighting = h(21:end); - h = fgetl(fp); image.NoiseScaleFactor = str2num(h(21:end)); - h = fgetl(fp); image.SelMeanNoise = h(21:end); - fgetl(fp); - h = fgetl(fp); image.Locations = str2num(h(21:end)); - h = fgetl(fp); image.TimeSamples = str2num(h(21:end)); - fgetl(fp); fgetl(fp); fgetl(fp); -end - -% Get Coordinates and Data -if ~isempty(strmatch(image.Imagetype,strvcat('MSPS','MSBF','Sensitivity'))) - % Get Coordinates - fgetl(fp); fgetl(fp); - h = fgetl(fp); - hx = sscanf(h,'X: %f %f %d'); - xmin = hx(1); - xmax = hx(2); - xnum = hx(3); - h = fgetl(fp); - hy = sscanf(h,'Y: %f %f %d'); - ymin = hy(1); - ymax = hy(2); - ynum = hy(3); - h = fgetl(fp); - hz = sscanf(h,'Z: %f %f %d'); - zmin = hz(1); - zmax = hz(2); - znum = hz(3); - fgetl(fp); - - image.Coordinates=struct('X',{[xmin:floor((xmax-xmin)/(xnum-1)*10000)/10000:xmax]},... - 'Y',{[ymin:floor((ymax-ymin)/(ynum-1)*10000)/10000:ymax]},... - 'Z',{[zmin:floor((zmax-zmin)/(znum-1)*10000)/10000:zmax]}); - - % Get Data - image.Data = zeros(xnum,ynum,znum); - for z=1:znum - fgetl(fp); - a=fscanf(fp,'%f',[xnum,ynum]); - for x=1:xnum - for y=1:ynum - image.Data(x,y,z)=a(x,y); - end - end - fgetl(fp);fgetl(fp); - end - - % Minimum Norm Image -elseif ~isempty(strmatch(image.Imagetype,('Minimum Norm'))) - h = fscanf(fp,'Latency (milliseconds):'); - image.Latency = fscanf(fp,'%f',[1,image.TimeSamples]); - image.Coordinates = zeros(image.Locations,3); - image.Data = zeros(image.Locations,image.TimeSamples); - for i=1:image.Locations - h=fscanf(fp,'%f',[1,3]); - image.Coordinates(i,:) = h; - image.Data(i,:)=fscanf(fp,'%f',[1,image.TimeSamples]); - end -end - -fclose(fp); diff --git a/external/fileio/private/readBESAmul.m b/external/fileio/private/readBESAmul.m deleted file mode 100644 index 24d879d..0000000 --- a/external/fileio/private/readBESAmul.m +++ /dev/null @@ -1,43 +0,0 @@ -function mul = readBESAmul(filename) - -% readBESAmul read information from a *.mul file -% -% Use as -% mul = readBESAMul(filename) -% -% The output is a structure containing the following fields: -% Npts: number of sample ponts -% TSB: latency of the first sample in the data files -% DI: time interval between two sample points -% Scale: scaling factor -% ChannelLabels: Channel labels -% Data: data matrix [Npts x Number of Channels] -% -% Last modified April 26, 2006 Robert Oostenveld - -if isempty(findstr(filename,'.')) - filename = [filename,'.mul']; -end - -fp = fopen(filename); - -% Read the file -if (fp) - % Read header of .swf file - headline=fscanf(fp,'TimePoints=%f Channels=%f BeginSweep[ms]=%f SamplingInterval[ms]=%f Bins/uV=%f'); - mul.Npts=headline(1); - NChan=headline(2); - mul.TSB=headline(3); - mul.DI=headline(4); - mul.Scale=headline(5); - fgets(fp); - for Channel=1:NChan - mul.ChannelLabels(Channel) = cellstr(fscanf(fp,'%s ',1)); - end - - mul.data=zeros(mul.Npts,NChan); - for i=1:mul.Npts - mul.data(i,:)=fscanf(fp,'%f',[1 NChan]); - end -end -fclose(fp); diff --git a/external/fileio/private/readBESAsb.m b/external/fileio/private/readBESAsb.m deleted file mode 100644 index a0bc21a..0000000 --- a/external/fileio/private/readBESAsb.m +++ /dev/null @@ -1,56 +0,0 @@ -function [time,data,nEpochs] = readBESAsb(filename) - -% readBESAsb reads information from a *.dat, i.e. a simple binary data file -% -% This function requires a file with the same basename as the data name but -% suffix '.generic' or '.gen' to be located in the same folder. This file is -% generated automatically by BESA during file export. -% -% Use as -% [time,data,nEpochs] = readBESAsb(filename) -% -% The following output is generated: -% time: a vector containing the time points corresponding to the data -% points. Negative times are prestimulus -% data: The data matrix with dimension [nChannels x nEpochs x nSamples], -% where nChannels is the number of Channels and nSamples the number -% of samples within one epoch -% nEpochs (optional): The number of epochs contained in the file -% -% Last modified February 21, 2007 Karsten Hoechstetter - -if isempty(findstr(filename,'.dat')) - filename = [filename,'.dat']; -end - -fid=fopen([filename(1:end-4),'.generic'],'r'); -if fid==-1 - fid=fopen([filename(1:end-4),'.gen'],'r'); -end - -fscanf(fid,'BESA Generic Data\n'); -nChannels = fscanf(fid,'nChannels=%i\n'); -sRate = fscanf(fid,'sRate=%f\n'); -nSamples = fscanf(fid,'nSamples=%i\n'); -format = fscanf(fid,'format=%s'); -file = fscanf(fid,'\nfile=%s'); -prestimulus = fscanf(fid,'prestimulus=%f\n'); -epochs = fscanf(fid,'epochs=%i\n'); -fclose(fid); - -if isempty(epochs) - epochs=1; -end - -time=[-prestimulus:1/sRate*1000:(nSamples/epochs-1)*1000/sRate-prestimulus]; - -fid=fopen(filename, 'r', 'ieee-le'); -xdata=fread(fid,[nChannels,nSamples],'float32'); -fclose(fid); - -data=zeros(nChannels,epochs,nSamples/epochs); -for i=1:epochs - data(:,i,:)=xdata(:,1+(i-1)*nSamples/epochs:i*nSamples/epochs); -end -nEpochs=epochs; - diff --git a/external/fileio/private/readBESAswf.m b/external/fileio/private/readBESAswf.m deleted file mode 100644 index 8a1f8bb..0000000 --- a/external/fileio/private/readBESAswf.m +++ /dev/null @@ -1,81 +0,0 @@ -function swf = readBESAswf(filename) - -% readBESAswf read all information from an *.swf file -% -% Note that the *.swf file must contain waveforms in rows and not in -% columns. -% -% Use as -% swf = readBESAswf(filename) -% -% The output is a structure containing the following fields: -% Npts: Number of time points -% Time: array of sampled time instants -% wavename: Labels of the different sources -% data: matrix of data points [Number of sources x Npts] -% -% Modified April 26, 2006 Robert Oostenveld -% Modified June 27, 2006 Karsten Hoechstetter: Function reads now both -% column and row swf formats - -if isempty(findstr(filename,'.')) - filename = [filename,'.swf']; -end -fp = fopen(filename); - -% Read the file -if (fp) - % Read header of .swf file - headline = fscanf(fp,'Npts= %f TSB= %f DI= %f SB= %f'); - % New BESA versions include more information in the .swf file header; skip that - i=1; - while i<1000 - a = fscanf(fp,'%c',1); - if strcmp(a,sprintf('\n')) - i=1000; - end - i=i+1; - end - swf.Npts=headline(1); - TSB=headline(2); - DI=headline(3); - swf.Time = [TSB:DI:TSB+(swf.Npts-1)*DI]; - - % Read first line after header to decide whether swf's are in rows or - % columns - row=1; - SecondLine = fgets(fp); - a=strfind(SecondLine,': '); - if a(end) >= length(SecondLine)-10 %swf's are in columns (because there is a ":" within the last 11 characters of the second line) - row=0; - end - - % Read data and labels - if row == 1 % swf's in rows - Name = sscanf(SecondLine,'%s',1); - swf.data(1,:) = sscanf(SecondLine(length(Name)+1:end),'%f',[1 headline(1)]); - swf.waveName(1) = cellstr(Name(1:length(Name)-1)); - for i=2:1000 - try % check if there is another waveform - Name = fscanf(fp,'%s',1); - swf.data(i,:) = fscanf(fp,'%f',[1,headline(1)]); - swf.waveName(i) = cellstr(Name(1:length(Name)-1)); - catch % stop if end of file is reached - break - end - end - else % swf's in columns - temp1 = SecondLine(1:a(1)-1); - temp2 = deblank(temp1(end:-1:1)); - swf.waveName(1) = cellstr(temp2(end:-1:1)); - for i=2:length(a) - temp1 = SecondLine(a(i-1)+2:a(i)-1); - temp2 = deblank(temp1(end:-1:1)); - swf.waveName(i) = cellstr(temp2(end:-1:1)); - end - swf.data = fscanf(fp,'%f',[length(a),headline(1)]); - i=length(a)+1; - end -end - -fclose(fp); \ No newline at end of file diff --git a/external/fileio/private/readBESAtfc.m b/external/fileio/private/readBESAtfc.m deleted file mode 100644 index cf6e3ce..0000000 --- a/external/fileio/private/readBESAtfc.m +++ /dev/null @@ -1,86 +0,0 @@ -function tfc = readBESAtfc(filename) - -% readBESAtfc reads all information from a *.tfc file -% -% Use as -% tfc = readBESATFC(filename) -% -% The output is a structure containing the following fields: -% ChannelLabels: character array of channel labels -% Time: array of sampled time instants -% Frequency: array of sampled frequencies -% Data: 3D data matrix with indices (channel,time,frequency) -% DataType: type of the exported data -% ConditionName: name of analyzed condition -% NumberOfTrials: Number of trials on which the data is based -% StatisticsCorrection: Type of statistics correction for multiple testing -% EvokedSignalSubtraction: Type of evoked signal subtraction -% -% Last modified April 25, 2006 Karsten Hoechstetter -% Last modified April 26, 2006 Robert Oostenveld - -if isempty(findstr(filename,'.')) - filename = [filename,'.tfc']; -end -fp = fopen(filename); - -VersionNumber = fscanf(fp,'VersionNumber=%s '); -tfc.DataType = fscanf(fp,'DataType=%s '); -tfc.ConditionName = fscanf(fp,'ConditionName=%s '); - -% If the user has not specified a condition name, BESA defaults to -% "Condition 1" etc. This is the only instance where the condition -% name can have a blank -if strcmp(tfc.ConditionName,'Condition') - tfc.ConditionName = [tfc.ConditionName,' ',num2str(fscanf(fp,'%i '))]; -end -temp = fscanf(fp,'NumberTrials=%f NumberTimeSamples=%f TimeStartInMS=%f IntervalInMS=%f NumberFrequencies=%f FreqStartInHz=%f FreqIntervalInHz=%f NumberChannels=%i ' ); -tfc.NumberOfTrials = temp(1); -NumberTimeSamples = temp(2); -TimeStartInMS = temp(3); -TimeIntervalInMS = temp(4); -NumberFrequencies = temp(5); -FreqStartInHZ = temp(6); -FreqIntervalInHZ = temp(7); -NumberChannels = temp(8); - -% New file versions (BESA 5.0.8 and higher) include more information in the .tfc file header; skip that -vers=0; % new tfc file format -try - tfc.StatisticsCorrection = fscanf(fp,'StatisticsCorrection=%s '); - tfc.EvokedSignalSubtraction = fscanf(fp,'EvokedSignalSubtraction=%s'); -catch - vers=1; % old tfc file format -end - -% Handle possible future extensions of the tfc file header -i=1; -while i<1000 - a = fscanf(fp,'%c',1); - if strcmp(a,sprintf('\n')) - i=1000; - end - i=i+1; -end - -% Generate return values -tfc.Time = TimeStartInMS:TimeIntervalInMS:(NumberTimeSamples-1)*TimeIntervalInMS+TimeStartInMS; -tfc.Frequency = FreqStartInHZ:FreqIntervalInHZ:(NumberFrequencies-1)*FreqIntervalInHZ+FreqStartInHZ; - -if isempty(findstr(tfc.DataType,'COH')) - for Channel=1:NumberChannels - tfc.ChannelLabels(Channel) = cellstr(fscanf(fp,'%s ',1)); - end -else - for Channel=1:NumberChannels - tfc.ChannelLabels(Channel) = cellstr(fscanf(fp,'%s ',3)); - end -end - -tfc.ChannelLabels=char(tfc.ChannelLabels); - -tfc.Data = zeros(NumberChannels,NumberTimeSamples,NumberFrequencies); -for Channel=1:NumberChannels - tfc.Data(Channel,:,:) = fscanf(fp,'%f',[NumberTimeSamples,NumberFrequencies]); -end -fclose(fp); diff --git a/external/fileio/private/read_24bit.c b/external/fileio/private/read_24bit.c deleted file mode 100644 index fdb3b16..0000000 --- a/external/fileio/private/read_24bit.c +++ /dev/null @@ -1,154 +0,0 @@ - -/* - * Copyright (C) 2006, Robert Oostenveld, F.C. Donders Ccentre for Cognitive Neuroimaging - * Copyright (C) 2007, Peter Desain, Nijmegen Institute for Cognition and Information - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * $Log: read_24bit.c,v $ - * Revision 1.4 2009/06/08 16:33:08 roboos - * include sys/types.h for all platforms, not only WIN32/64, since also required for OSX 10.4 - * - * Revision 1.3 2009/03/30 07:23:03 roboos - * changed ifdef syntax - * - * Revision 1.2 2009/03/28 05:32:46 roboos - * changed ifdef handling to accomodate matlab71, which did not like the WIN32 || WIN64 combination - * - * Revision 1.1 2009/01/14 09:43:37 roboos - * moved source code for mex file from fileio/mex to file/private - * compiling the source code from within Matlab now ensures that the mex file will be located immediately at the right position - * - * Revision 1.7 2008/12/11 17:32:33 roboos - * added conditional include and define for win32 & 64, thanks to Guillaume - * - * Revision 1.6 2008/10/07 07:53:05 roboos - * replaced fseek with fseeko, which I had forgotten to fix yesterday - * - * Revision 1.5 2008/10/06 09:25:24 roboos - * changed from long int to off_t and included stdint for uint32_t and uint64_t - * this should allow the mex file also to work on large filed (>2GB) on supported platforms - * - * Revision 1.4 2008/04/09 10:10:20 roboos - * corrected the text of an error message - * - * Revision 1.3 2007/10/02 08:49:37 roboos - * added brackets around the bitshift operations - * - * Revision 1.2 2007/09/12 12:43:39 roboos - * added peter to copyright, merged suggestions from nici (see email 20070821), changed to using bitshift, changed the handing of the sign bit - * - * - */ - -/* - * _LARGEFILE_SOURCE takes care that the offset is represented as 64 bit on supported platforms - * it should be defined prior to including the system header files - */ - -#define _LARGEFILE_SOURCE - -#include -#include -#include "mex.h" -#include "matrix.h" - -#if defined(_WIN32) || defined(_WIN64) -#define int32_t INT32_T -#define int64_t INT64_T -#define fseeko fseek -#else -#include -#endif - -void -mexFunction (int nlhs, mxArray * plhs[], int nrhs, const mxArray * prhs[]) -{ - FILE *fp; - mxArray *dat; - double *dat_p; - char *filename, *buf; - int32_t fnlen, b1, b2, b3; - - /* these have to be able to handle large files (>2GB) on supported platforms */ - int64_t count, indx; - size_t num, numwords; - off_t offset; - - if (nrhs != 3) - mexErrMsgTxt ("Invalid number of input arguments"); - - if (mxGetM(prhs[1])!=1 || mxGetN(prhs[1])!=1) - mexErrMsgTxt ("Invalid dimension for input argument 2"); - if (mxGetM(prhs[2])!=1 || mxGetN(prhs[2])!=1) - mexErrMsgTxt ("Invalid dimension for input argument 3"); - - /* get the filename */ - fnlen = mxGetN(prhs[0]); - filename = mxCalloc(fnlen+1, sizeof(char)); - mxGetString(prhs[0], filename, fnlen+1); - - /* get values and typecast to integer */ - offset = (off_t)(mxGetScalar (prhs[1])); - numwords = (off_t)(mxGetScalar (prhs[2])); - - /* - printf("filename = %s\n", filename); - printf("fnlen = %d\n", fnlen); - printf("offset = %d\n", offset); - printf("numwords = %d\n", numwords); - */ - - /* open the file and read the desired bytes */ - fp = fopen(filename, "rb"); - if (fp==NULL) - { - printf("error opening file: %s\n", filename); - return; - } - fseeko(fp, offset, SEEK_SET); - - buf = mxCalloc(3*numwords, sizeof(char)); - count = fread(buf, sizeof(char), 3*numwords, fp); - if (count<3*numwords) - { - printf("error reading from %s\n", filename); - fclose(fp); - return; - } - else - { - fclose(fp); - } - - /* convert every thee bytes into one word */ - dat = mxCreateDoubleMatrix (1, numwords, mxREAL); - dat_p = mxGetData (dat); - - for (count=0; count>Matlab code written by Eugene Kronberg - -% Copyright (C) 2008-2009, Centre for Cognitive Neuroimaging, Glasgow, Gavin Paterson & J.M.Schoffelen -% -% $Log: read_4d_hdr.m,v $ -% Revision 1.3 2009/04/03 07:56:46 jansch -% changed reading of user_block B_weights_used. there's a version 1 and 2, -% probably related to whether data were acquired with a 2500 or 3600 system -% -% Revision 1.2 2009/03/30 13:53:17 jansch -% Change with respect to handling of user blocks. User block data will be stored -% in a cell-array of structures, rather than the initial structure-array. Added -% log in m-file -% - -%read header -if nargin ~= 2 - error('Wrong number of input arguments'); -end - -if ~isempty(datafile), - %always big endian - fid = fopen(datafile, 'r', 'b'); - - if fid == -1 - error('Cannot open file %s', datafile); - end - - fseek(fid, 0, 'eof'); - header_end = ftell(fid); - %last 8 bytes of the pdf is header offset - fseek(fid, -8, 'eof'); - header_offset = fread(fid,1,'uint64'); - - %first byte of the header - fseek(fid, header_offset, 'bof'); - - % read header data - align_file_pointer(fid) - header.header_data.FileType = fread(fid, 1, 'uint16=>uint16'); - file_type = char(fread(fid, 5, 'uchar'))'; - header.header_data.file_type = file_type(file_type>0); - fseek(fid, 1, 'cof'); - format = fread(fid, 1, 'int16=>int16'); - switch format - case 1 - header.header_data.Format = 'SHORT'; - case 2 - header.header_data.Format = 'LONG'; - case 3 - header.header_data.Format = 'FLOAT'; - case 4 - header.header_data.Format ='DOUBLE'; - end - header.header_data.acq_mode = fread(fid, 1, 'uint16=>uint16'); - header.header_data.TotalEpochs = fread(fid, 1, 'uint32=>double'); - header.header_data.input_epochs = fread(fid, 1, 'uint32=>uint32'); - header.header_data.TotalEvents = fread(fid, 1, 'uint32=>uint32'); - header.header_data.total_fixed_events = fread(fid, 1, 'uint32=>uint32'); - header.header_data.SamplePeriod = fread(fid, 1, 'float32=>float64'); - header.header_data.SampleFrequency = 1/header.header_data.SamplePeriod; - xaxis_label = char(fread(fid, 16, 'uchar'))'; - header.header_data.xaxis_label = xaxis_label(xaxis_label>0); - header.header_data.total_processes = fread(fid, 1, 'uint32=>uint32'); - header.header_data.TotalChannels = fread(fid, 1, 'uint16=>double'); - fseek(fid, 2, 'cof'); - header.header_data.checksum = fread(fid, 1, 'int32=>int32'); - header.header_data.total_ed_classes = fread(fid, 1, 'uint32=>uint32'); - header.header_data.total_associated_files = fread(fid, 1, 'uint16=>uint16'); - header.header_data.last_file_index = fread(fid, 1, 'uint16=>uint16'); - header.header_data.timestamp = fread(fid, 1, 'uint32=>uint32'); - header.header_data.reserved = fread(fid, 20, 'uchar')'; - fseek(fid, 4, 'cof'); - - %read epoch_data - for epoch = 1:header.header_data.TotalEpochs; - align_file_pointer(fid) - - header.epoch_data(epoch).pts_in_epoch = fread(fid, 1, 'uint32=>uint32'); - header.epoch_data(epoch).epoch_duration = fread(fid, 1, 'float32=>float32'); - header.epoch_data(epoch).expected_iti = fread(fid, 1, 'float32=>float32'); - header.epoch_data(epoch).actual_iti = fread(fid, 1, 'float32=>float32'); - header.epoch_data(epoch).total_var_events = fread(fid, 1, 'uint32=>uint32'); - header.epoch_data(epoch).checksum = fread(fid, 1, 'int32=>int32'); - header.epoch_data(epoch).epoch_timestamp = fread(fid, 1, 'int32=>int32'); - header.epoch_data(epoch).reserved = fread(fid, 28, 'uchar')'; - header.header_data.SlicesPerEpoch = double(header.epoch_data(1).pts_in_epoch); - - %read event data (var_events) - for event = 1:header.epoch_data(epoch).total_var_events - align_file_pointer(fid) - - event_name = char(fread(fid, 16, 'uchar'))'; - header.epoch_data(epoch).var_event{event}.event_name = event_name(event_name>0); - header.epoch_data(epoch).var_event{event}.start_lat = fread(fid, 1, 'float32=>float32'); - header.epoch_data(epoch).var_event{event}.end_lat = fread(fid, 1, 'float32=>float32'); - header.epoch_data(epoch).var_event{event}.step_size = fread(fid, 1, 'float32=>float32'); - header.epoch_data(epoch).var_event{event}.fixed_event = fread(fid, 1, 'uint16=>uint16'); - fseek(fid, 2, 'cof'); - header.epoch_data(epoch).var_event{event}.checksum = fread(fid, 1, 'int32=>int32'); - header.epoch_data(epoch).var_event{event}.reserved = fread(fid, 32, 'uchar')'; - fseek(fid, 4, 'cof'); - end - end - - %read channel ref data - for channel = 1:header.header_data.TotalChannels - align_file_pointer(fid) - - chan_label = (fread(fid, 16, 'uint8=>char'))'; - header.channel_data(channel).chan_label = chan_label(chan_label>0); - header.channel_data(channel).chan_no = fread(fid, 1, 'uint16=>uint16'); - header.channel_data(channel).attributes = fread(fid, 1, 'uint16=>uint16'); - header.channel_data(channel).scale = fread(fid, 1, 'float32=>float32'); - yaxis_label = char(fread(fid, 16, 'uint8=>char'))'; - header.channel_data(channel).yaxis_label = yaxis_label(yaxis_label>0); - header.channel_data(channel).valid_min_max = fread(fid, 1, 'uint16=>uint16'); - fseek(fid, 6, 'cof'); - header.channel_data(channel).ymin = fread(fid, 1, 'float64'); - header.channel_data(channel).ymax = fread(fid, 1, 'float64'); - header.channel_data(channel).index = fread(fid, 1, 'uint32=>uint32'); - header.channel_data(channel).checksum = fread(fid, 1, 'int32=>int32'); - header.channel_data(channel).whatisit = char(fread(fid, 4, 'uint8=>char'))'; - header.channel_data(channel).reserved = fread(fid, 28, 'uint8')'; - end - - %read event data - for event = 1:header.header_data.total_fixed_events - align_file_pointer(fid) - event_name = char(fread(fid, 16, 'uchar'))'; - header.event_data(event).event_name = event_name(event_name>0); - header.event_data(event).start_lat = fread(fid, 1, 'float32=>float32'); - header.event_data(event).end_lat = fread(fid, 1, 'float32=>float32'); - header.event_data(event).step_size = fread(fid, 1, 'float32=>float32'); - header.event_data(event).fixed_event = fread(fid, 1, 'uint16=>uint16'); - fseek(fid, 2, 'cof'); - header.event_data(event).checksum = fread(fid, 1, 'int32=>int32'); - header.event_data(event).reserved = fread(fid, 32, 'uchar')'; - fseek(fid, 4, 'cof'); - end - header.header_data.FirstLatency = double(header.event_data(1).start_lat); - - %experimental: read process information - for np = 1:header.header_data.total_processes - align_file_pointer(fid) - nbytes = fread(fid, 1, 'uint32=>uint32'); - fp = ftell(fid); - header.process(np).hdr.nbytes = nbytes; - type = char(fread(fid, 20, 'uchar'))'; - header.process(np).hdr.type = type(type>0); - header.process(np).hdr.checksum = fread(fid, 1, 'int32=>int32'); - user = char(fread(fid, 32, 'uchar'))'; - header.process(np).user = user(user>0); - header.process(np).timestamp = fread(fid, 1, 'uint32=>uint32'); - fname = char(fread(fid, 32, 'uchar'))'; - header.process(np).filename = fname(fname>0); - fseek(fid, 28*8, 'cof'); %dont know - header.process(np).totalsteps = fread(fid, 1, 'uint32=>uint32'); - header.process(np).checksum = fread(fid, 1, 'int32=>int32'); - header.process(np).reserved = fread(fid, 32, 'uchar')'; - for ns = 1:header.process(np).totalsteps - header.process(np).step(ns).hdr.nbytes = fread(fid, 1, 'uint32=>uint32'); - type = char(fread(fid, 20, 'uchar'))'; - header.process(np).step(ns).hdr.type = type(type>0); %dont know how to interpret the first two - header.process(np).step(ns).hdr.checksum = fread(fid, 1, 'int32=>int32'); - header.process(np).step(ns).userblocksize = fread(fid, 1, 'int32=>int32'); - fseek(fid, 32, 'cof'); %needed until next step FIXME make more robust, the total number of read bytes - %should be equal to the nbytes computed earlier on - if strcmp(header.process(np).step(ns).hdr.type, 'PDF_Weight_Table'), - warning('reading in weight table: no warranty that this is correct. it seems to work for the Glasgow 248-magnetometer system. if you have some code yourself, and/or would like to test it on your own data, please contact Jan-Mathijs'); - tmpfp = ftell(fid); - tmp = fread(fid, 1, 'uint8'); - Nchan = fread(fid, 1, 'uint32'); - Nref = fread(fid, 1, 'uint32'); - for k = 1:Nref - name = fread(fid, 17, 'uchar'); %strange, but true - header.process(np).step(ns).RefChan{k,1} = char(name(name>0))'; - end - fseek(fid, 152, 'cof'); - for k = 1:Nchan - name = fread(fid, 17, 'uchar'); - header.process(np).step(ns).Chan{k,1} = char(name(name>0))'; - end - %fseek(fid, 20, 'cof'); - %fseek(fid, 4216, 'cof'); - header.process(np).step(ns).stuff1 = fread(fid, 4236, 'uint8'); - name = fread(fid, 16, 'uchar'); - header.process(np).step(ns).Creator = char(name(name>0))'; - %some stuff I don't understand yet - %fseek(fid, 136, 'cof'); - header.process(np).step(ns).stuff2 = fread(fid, 136, 'uint8'); - %now something strange is going to happen: the weights are probably little-endian encoded. - %here we go: check whether this applies to the whole PDF weight table - fp = ftell(fid); - fclose(fid); - fid = fopen(datafile, 'r', 'l'); - fseek(fid, fp, 'bof'); - for k = 1:Nchan - header.process(np).step(ns).Weights(k,:) = fread(fid, 23, 'float32=>float32')'; - fseek(fid, 36, 'cof'); - end - else - end - end - end - fclose(fid); -end -%end read header - -%read config file -fid = fopen(configfile, 'r', 'b'); - -if fid == -1 - error('Cannot open config file'); -end - -header.config_data.version = fread(fid, 1, 'uint16=>uint16'); -site_name = char(fread(fid, 32, 'uchar'))'; -header.config_data.site_name = site_name(site_name>0); -dap_hostname = char(fread(fid, 16, 'uchar'))'; -header.config_data.dap_hostname = dap_hostname(dap_hostname>0); -header.config_data.sys_type = fread(fid, 1, 'uint16=>uint16'); -header.config_data.sys_options = fread(fid, 1, 'uint32=>uint32'); -header.config_data.supply_freq = fread(fid, 1, 'uint16=>uint16'); -header.config_data.total_chans = fread(fid, 1, 'uint16=>uint16'); -header.config_data.system_fixed_gain = fread(fid, 1, 'float32=>float32'); -header.config_data.volts_per_bit = fread(fid, 1, 'float32=>float32'); -header.config_data.total_sensors = fread(fid, 1, 'uint16=>uint16'); -header.config_data.total_user_blocks = fread(fid, 1, 'uint16=>uint16'); -header.config_data.next_derived_channel_number = fread(fid, 1, 'uint16=>uint16'); -fseek(fid, 2, 'cof'); -header.config_data.checksum = fread(fid, 1, 'int32=>int32'); -header.config_data.reserved = fread(fid, 32, 'uchar=>uchar')'; - -header.config.Xfm = fread(fid, [4 4], 'double'); - -%user blocks -for ub = 1:header.config_data.total_user_blocks - align_file_pointer(fid) - header.user_block_data{ub}.hdr.nbytes = fread(fid, 1, 'uint32=>uint32'); - type = char(fread(fid, 20, 'uchar'))'; - header.user_block_data{ub}.hdr.type = type(type>0); - header.user_block_data{ub}.hdr.checksum = fread(fid, 1, 'int32=>int32'); - user = char(fread(fid, 32, 'uchar'))'; - header.user_block_data{ub}.user = user(user>0); - header.user_block_data{ub}.timestamp = fread(fid, 1, 'uint32=>uint32'); - header.user_block_data{ub}.user_space_size = fread(fid, 1, 'uint32=>uint32'); - header.user_block_data{ub}.reserved = fread(fid, 32, 'uchar=>uchar')'; - fseek(fid, 4, 'cof'); - user_space_size = double(header.user_block_data{ub}.user_space_size); - if strcmp(type(type>0), 'B_weights_used'), - %warning('reading in weight table: no warranty that this is correct. it seems to work for the Glasgow 248-magnetometer system. if you have some code yourself, and/or would like to test it on your own data, please contact Jan-Mathijs'); - tmpfp = ftell(fid); - %read user_block_data weights - %there is information in the 4th and 8th byte, these might be related to the settings? - version = fread(fid, 1, 'uint32'); - header.user_block_data{ub}.version = version; - if version==1, - Nbytes = fread(fid,1,'uint32'); - Nchan = fread(fid,1,'uint32'); - Position = fread(fid, 32, 'uchar'); - header.user_block_data{ub}.position = char(Position(Position>0))'; - fseek(fid,tmpfp+user_space_size - Nbytes*Nchan, 'bof'); - Ndigital = floor((Nbytes - 4*2) / 4); - Nanalog = 3; %lucky guess? - % how to know number of analog weights vs digital weights??? - for ch = 1:Nchan - % for Konstanz -- comment for others? - header.user_block_data{ub}.aweights(ch,:) = fread(fid, [1 Nanalog], 'int16')'; - fseek(fid,2,'cof'); % alignment - header.user_block_data{ub}.dweights(ch,:) = fread(fid, [1 Ndigital], 'single=>double')'; - end - fseek(fid, tmpfp, 'bof'); - %there is no information with respect to the channels here. - %the best guess would be to assume the order identical to the order in header.config.channel_data - %for the digital weights it would be the order of the references in that list - %for the analog weights I would not know - elseif version==2, - unknown2 = fread(fid, 1, 'uint32'); - Nchan = fread(fid, 1, 'uint32'); - Position = fread(fid, 32, 'uchar'); - header.user_block_data{ub}.position = char(Position(Position>0))'; - fseek(fid, tmpfp+124, 'bof'); - Nanalog = fread(fid, 1, 'uint32'); - Ndigital = fread(fid, 1, 'uint32'); - fseek(fid, tmpfp+204, 'bof'); - for k = 1:Nchan - Name = fread(fid, 16, 'uchar'); - header.user_block_data{ub}.channames{k,1} = char(Name(Name>0))'; - end - for k = 1:Nanalog - Name = fread(fid, 16, 'uchar'); - header.user_block_data{ub}.arefnames{k,1} = char(Name(Name>0))'; - end - for k = 1:Ndigital - Name = fread(fid, 16, 'uchar'); - header.user_block_data{ub}.drefnames{k,1} = char(Name(Name>0))'; - end - - header.user_block_data{ub}.dweights = fread(fid, [Ndigital Nchan], 'single=>double')'; - header.user_block_data{ub}.aweights = fread(fid, [Nanalog Nchan], 'int16')'; - fseek(fid, tmpfp, 'bof'); - end - elseif strcmp(type(type>0), 'B_E_table_used'), - %warning('reading in weight table: no warranty that this is correct'); - %tmpfp = ftell(fid); - %fseek(fid, 4, 'cof'); %there's info here dont know how to interpret - %Nx = fread(fid, 1, 'uint32'); - %Nchan = fread(fid, 1, 'uint32'); - %type = fread(fid, 32, 'uchar'); %don't know whether correct - %header.user_block_data{ub}.type = char(type(type>0))'; - %fseek(fid, 16, 'cof'); - %for k = 1:Nchan - % name = fread(fid, 16, 'uchar'); - % header.user_block_data{ub}.name{k,1} = char(name(name>0))'; - %end - elseif strcmp(type(type>0), 'B_COH_Points'), - tmpfp = ftell(fid); - Ncoil = fread(fid, 1, 'uint32'); - N = fread(fid, 1, 'uint32'); - coils = fread(fid, [7 Ncoil], 'double'); - - header.user_block_data{ub}.pnt = coils(1:3,:)'; - header.user_block_data{ub}.ori = coils(4:6,:)'; - header.user_block_data{ub}.Ncoil = Ncoil; - header.user_block_data{ub}.N = N; - tmp = fread(fid, (904-288)/8, 'double'); - header.user_block_data{ub}.tmp = tmp; %FIXME try to find out what these bytes mean - fseek(fid, tmpfp, 'bof'); - elseif strcmp(type(type>0), 'b_ccp_xfm_block'), - tmpfp = ftell(fid); - tmp1 = fread(fid, 1, 'uint32'); - %tmp = fread(fid, [4 4], 'double'); - %tmp = fread(fid, [4 4], 'double'); - %the next part seems to be in little endian format (at least when I tried) - tmp = fread(fid, 128, 'uint8'); - tmp = uint8(reshape(tmp, [8 16])'); - xfm = zeros(4,4); - for k = 1:size(tmp,1) - xfm(k) = typecast(tmp(k,:), 'double'); - if abs(xfm(k))<1e-10 | abs(xfm(k))>1e10, xfm(k) = typecast(fliplr(tmp(k,:)), 'double');end - end - fseek(fid, tmpfp, 'bof'); %FIXME try to find out why this looks so strange - elseif strcmp(type(type>0), 'b_eeg_elec_locs'), - %this block contains the digitized coil positions - tmpfp = ftell(fid); - Npoints = user_space_size./40; - for k = 1:Npoints - tmp = fread(fid, 16, 'uchar'); - tmplabel = char(tmp(tmp>0)'); - if strmatch('Coil', tmplabel), - label{k} = tmplabel(1:5); - elseif ismember(tmplabel(1), {'L' 'R' 'C' 'N' 'I'}), - label{k} = tmplabel(1); - else - label{k} = ''; - end - tmp = fread(fid, 3, 'double'); - pnt(k,:) = tmp(:)'; - end - header.user_block_data{ub}.label = label(:); - header.user_block_data{ub}.pnt = pnt; - fseek(fid, tmpfp, 'bof'); - end - fseek(fid, user_space_size, 'cof'); -end - -%channels -for ch = 1:header.config_data.total_chans - align_file_pointer(fid) - name = char(fread(fid, 16, 'uchar'))'; - header.config.channel_data(ch).name = name(name>0); - %FIXME this is a very dirty fix to get the reading in of continuous headlocalization - %correct. At the moment, the numbering of the hmt related channels seems to start with 1000 - %which I don't understand, but seems rather nonsensical. - chan_no = fread(fid, 1, 'uint16=>uint16'); - if chan_no > header.config_data.total_chans, - - %FIXME fix the number in header.channel_data as well - sel = find([header.channel_data.chan_no]== chan_no); - if ~isempty(sel), - chan_no = ch; - header.channel_data(sel).chan_no = chan_no; - header.channel_data(sel).chan_label = header.config.channel_data(ch).name; - else - %does not matter - end - end - header.config.channel_data(ch).chan_no = chan_no; - header.config.channel_data(ch).type = fread(fid, 1, 'uint16=>uint16'); - header.config.channel_data(ch).sensor_no = fread(fid, 1, 'int16=>int16'); - fseek(fid, 2, 'cof'); - header.config.channel_data(ch).gain = fread(fid, 1, 'float32=>float32'); - header.config.channel_data(ch).units_per_bit = fread(fid, 1, 'float32=>float32'); - yaxis_label = char(fread(fid, 16, 'uchar'))'; - header.config.channel_data(ch).yaxis_label = yaxis_label(yaxis_label>0); - header.config.channel_data(ch).aar_val = fread(fid, 1, 'double'); - header.config.channel_data(ch).checksum = fread(fid, 1, 'int32=>int32'); - header.config.channel_data(ch).reserved = fread(fid, 32, 'uchar=>uchar')'; - fseek(fid, 4, 'cof'); - - align_file_pointer(fid) - header.config.channel_data(ch).device_data.hdr.size = fread(fid, 1, 'uint32=>uint32'); - header.config.channel_data(ch).device_data.hdr.checksum = fread(fid, 1, 'int32=>int32'); - header.config.channel_data(ch).device_data.hdr.reserved = fread(fid, 32, 'uchar=>uchar')'; - - switch header.config.channel_data(ch).type - case {1, 3}%meg/ref - - header.config.channel_data(ch).device_data.inductance = fread(fid, 1, 'float32=>float32'); - fseek(fid, 4, 'cof'); - header.config.channel_data(ch).device_data.Xfm = fread(fid, [4 4], 'double'); - header.config.channel_data(ch).device_data.xform_flag = fread(fid, 1, 'uint16=>uint16'); - header.config.channel_data(ch).device_data.total_loops = fread(fid, 1, 'uint16=>uint16'); - header.config.channel_data(ch).device_data.reserved = fread(fid, 32, 'uchar=>uchar')'; - fseek(fid, 4, 'cof'); - - for loop = 1:header.config.channel_data(ch).device_data.total_loops - align_file_pointer(fid) - header.config.channel_data(ch).device_data.loop_data(loop).position = fread(fid, 3, 'double'); - header.config.channel_data(ch).device_data.loop_data(loop).direction = fread(fid, 3, 'double'); - header.config.channel_data(ch).device_data.loop_data(loop).radius = fread(fid, 1, 'double'); - header.config.channel_data(ch).device_data.loop_data(loop).wire_radius = fread(fid, 1, 'double'); - header.config.channel_data(ch).device_data.loop_data(loop).turns = fread(fid, 1, 'uint16=>uint16'); - fseek(fid, 2, 'cof'); - header.config.channel_data(ch).device_data.loop_data(loop).checksum = fread(fid, 1, 'int32=>int32'); - header.config.channel_data(ch).device_data.loop_data(loop).reserved = fread(fid, 32, 'uchar=>uchar')'; - end - case 2%eeg - header.config.channel_data(ch).device_data.impedance = fread(fid, 1, 'float32=>float32'); - fseek(fid, 4, 'cof'); - header.config.channel_data(ch).device_data.Xfm = fread(fid, [4 4], 'double'); - header.config.channel_data(ch).device_data.reserved = fread(fid, 32, 'uchar=>uchar')'; - case 4%external - header.config.channel_data(ch).device_data.user_space_size = fread(fid, 1, 'uint32=>uint32'); - header.config.channel_data(ch).device_data.reserved = fread(fid, 32, 'uchar=>uchar')'; - fseek(fid, 4, 'cof'); - case 5%TRIGGER - header.config.channel_data(ch).device_data.user_space_size = fread(fid, 1, 'uint32=>uint32'); - header.config.channel_data(ch).device_data.reserved = fread(fid, 32, 'uchar=>uchar')'; - fseek(fid, 4, 'cof'); - case 6%utility - header.config.channel_data(ch).device_data.user_space_size = fread(fid, 1, 'uint32=>uint32'); - header.config.channel_data(ch).device_data.reserved = fread(fid, 32, 'uchar=>uchar')'; - fseek(fid, 4, 'cof'); - case 7%derived - header.config.channel_data(ch).device_data.user_space_size = fread(fid, 1, 'uint32=>uint32'); - header.config.channel_data(ch).device_data.reserved = fread(fid, 32, 'uchar=>uchar')'; - fseek(fid, 4, 'cof'); - case 8%shorted - header.config.channel_data(ch).device_data.reserved = fread(fid, 32, 'uchar=>uchar')'; - otherwise - error('Unknown device type: %d\n', header.config.channel_data(ch).type); - end -end - -fclose(fid); -%end read config file - -header.header_data.FileDescriptor = 0; %no obvious field to take this from -header.header_data.Events = 1;%no obvious field to take this from -header.header_data.EventCodes = 0;%no obvious field to take this from - -if isfield(header, 'channel_data'), - header.ChannelGain = double([header.config.channel_data([header.channel_data.chan_no]).gain]'); - header.ChannelUnitsPerBit = double([header.config.channel_data([header.channel_data.chan_no]).units_per_bit]'); - header.Channel = {header.config.channel_data([header.channel_data.chan_no]).name}'; - header.Format = header.header_data.Format; -end - -function align_file_pointer(fid) -current_position = ftell(fid); -if mod(current_position, 8) ~= 0 - offset = 8 - mod(current_position,8); - fseek(fid, offset, 'cof'); -end diff --git a/external/fileio/private/read_asa.m b/external/fileio/private/read_asa.m deleted file mode 100644 index dce0181..0000000 --- a/external/fileio/private/read_asa.m +++ /dev/null @@ -1,177 +0,0 @@ -function [val] = read_asa(filename, elem, format, number, token) - -% READ_ASA reads a specified element from an ASA file -% -% val = read_asa(filename, element, type, number) -% -% where the element is a string such as -% NumberSlices -% NumberPositions -% Rows -% Columns -% etc. -% -% and format specifies the datatype according to -% %d (integer value) -% %f (floating point value) -% %s (string) -% -% number is optional to specify how many lines of data should be read -% The default is 1 for strings and Inf for numbers. -% -% token is optional to specifiy a character that separates the values from -% anything not wanted. - -% Copyright (C) 2002, Robert Oostenveld -% -% $Log: read_asa.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.7 2008/11/17 17:38:43 roboos -% replaced line==-1 with isequal, to work around && bug -% -% Revision 1.6 2008/11/14 07:49:19 roboos -% use standard matlab strtrim function instead of deblank2 -% -% Revision 1.5 2008/11/14 07:21:45 roboos -% newer ASA versions write the labels in front of the positions, like "FPz: 10.4 1.3 -2" -% added support for this, thanks to Thomas Hartmann -% use strcmpi instead of strcmp(lower()) -% -% Revision 1.4 2005/11/30 11:38:33 roboos -% fixed bug: close file before returning to calling function (thanks to Gijs) -% -% Revision 1.3 2004/03/29 15:15:12 roberto -% unknown change, seems related to handling of empty lines ? -% -% Revision 1.2 2003/03/11 15:24:51 roberto -% updated help and copyrights -% - -fid = fopen(filename, 'rt'); -if fid==-1 - error(sprintf('could not open file %s', filename)); -end - -if nargin<4 - if strcmp(format, '%s') - number = 1; - else - number = Inf; - end -end - -if nargin<5 - token = ''; -end - - -val = []; -elem = strtrim(lower(elem)); - -while (1) - line = fgetl(fid); - if ~isempty(line) && isequal(line, -1) - % prematurely reached end of file - fclose(fid); - return - end - line = strtrim(line); - lower_line = lower(line); - if strmatch(elem, lower_line) - data = line((length(elem)+1):end); - break - end -end - -while isempty(data) - line = fgetl(fid); - if isequal(line, -1) - % prematurely reached end of file - fclose(fid); - return - end - data = strtrim(line); -end - -if strcmp(format, '%s') - if number==1 - % interpret the data as a single string, create char-array - val = detoken(strtrim(data), token); - fclose(fid); - return - end - % interpret the data as a single string, create cell-array - val{1} = detoken(strtrim(data), token); - count = 1; - % read the remaining strings - while count LPA -% PointOnNegativeYAxis -> RPA -% PointOnPositiveXAxis -> nasion - -% Copyright (C) 2002, Robert Oostenveld -% -% $Log: read_asa_mri.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry -% -% Revision 1.6 2008/11/12 17:02:03 roboos -% explicitely specify ieee-le in fopen() -% -% Revision 1.5 2005/11/16 13:46:32 roboos -% added segmentatino to output, changed from warpo3d to warp_apply -% -% Revision 1.4 2004/01/19 14:24:13 roberto -% numerous changes, cannot remember the details -% -% Revision 1.3 2003/08/04 09:26:46 roberto -% added homgenous coordinate transformation matrices to header -% support for VoxelOn... instead of PointOn... -% -% Revision 1.2 2003/03/11 15:24:51 roberto -% updated help and copyrights -% - -hdr.Nrows = read_asa(fn, 'NumberRows=', '%d'); -hdr.Ncolumns = read_asa(fn, 'NumberColumns=', '%d'); -hdr.Nslices = read_asa(fn, 'NumberSlices=', '%d'); -hdr.rows = read_asa(fn, 'Rows=', '%s'); -hdr.columns = read_asa(fn, 'Columns=', '%s'); -hdr.slices = read_asa(fn, 'Slices=', '%s'); -hdr.distance = read_asa(fn, 'Distance=', '%f', 3); -hdr.mrifile = read_asa(fn, 'Matrix', '%s'); -hdr.segfile = read_asa(fn, 'Segmentation', '%s'); -hdr.posy = read_asa(fn, 'PointOnPositiveYAxis', '%f', 3); -hdr.negy = read_asa(fn, 'PointOnNegativeYAxis', '%f', 3); -hdr.posx = read_asa(fn, 'PointOnPositiveXAxis', '%f', 3); -hdr.voxposy = read_asa(fn, 'VoxelOnPositiveYAxis', '%f', 3); -hdr.voxnegy = read_asa(fn, 'VoxelOnNegativeYAxis', '%f', 3); -hdr.voxposx = read_asa(fn, 'VoxelOnPositiveXAxis', '%f', 3); -hdr.segfile = read_asa(fn, 'Segmentation', '%s', 1); - -dim = [hdr.Ncolumns hdr.Nrows hdr.Nslices]; -mri = []; -seg = []; - -% the data files are at the same location as the mri file, locate path -[path, name, ext] = fileparts(fn); - -% this temporary needs 8x as much storage!!! -if ~isempty(hdr.mrifile) - mrifile = fullfile(path, hdr.mrifile); - mri = zeros(dim); - fid = fopen(mrifile, 'rb', 'ieee-le'); - mri(:) = fread(fid, prod(dim), 'uint8'); - mri = uint8(mri); - fclose(fid); -end - -% this temporary needs 8x as much storage!!! -if ~isempty(hdr.segfile) - segfile = fullfile(path, hdr.segfile); - seg = zeros(dim); - fid = fopen(segfile, 'rb', 'ieee-le'); - seg(:) = fread(fid, prod(dim), 'uint8'); - seg = uint8(seg); - fclose(fid); -end - -% flip the orientation of the MRI data, the result should be -% 'coronal(occipital-frontal)' -% 'horizontal(inferior-superior)' -% 'sagittal(right-left)' - -if strcmp(hdr.columns, 'coronal(frontal-occipital)') - hdr.columns = 'coronal(occipital-frontal)'; - mri = flipdim(mri, 1); - seg = flipdim(seg, 1); -elseif strcmp(hdr.columns, 'horizontal(superior-inferior)') - hdr.columns = 'horizontal(inferior-superior)'; - mri = flipdim(mri, 1); - seg = flipdim(seg, 1); -elseif strcmp(hdr.columns, 'sagittal(left-right)') - hdr.columns = 'sagittal(right-left)'; - mri = flipdim(mri, 1); - seg = flipdim(seg, 1); -end - -if strcmp(hdr.rows, 'coronal(frontal-occipital)') - hdr.rows = 'coronal(occipital-frontal)'; - mri = flipdim(mri, 2); - seg = flipdim(seg, 2); -elseif strcmp(hdr.rows, 'horizontal(superior-inferior)') - hdr.rows = 'horizontal(inferior-superior)'; - mri = flipdim(mri, 2); - seg = flipdim(seg, 2); -elseif strcmp(hdr.rows, 'sagittal(left-right)') - hdr.rows = 'sagittal(right-left)'; - mri = flipdim(mri, 2); - seg = flipdim(seg, 2); -end - -if strcmp(hdr.slices, 'coronal(frontal-occipital)') - hdr.slices = 'coronal(occipital-frontal)'; - mri = flipdim(mri, 3); - seg = flipdim(seg, 3); -elseif strcmp(hdr.slices, 'horizontal(superior-inferior)') - hdr.slices = 'horizontal(inferior-superior)'; - mri = flipdim(mri, 3); - seg = flipdim(seg, 3); -elseif strcmp(hdr.slices, 'sagittal(left-right)') - hdr.slices = 'sagittal(right-left)'; - mri = flipdim(mri, 3); - seg = flipdim(seg, 3); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% swap the orientations of the MRI data, the result should be fixed -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% 1st dimension corresponds to columns, which should be 'coronal(occipital-frontal)' -% 2st dimension corresponds to rows, which should be 'sagittal(right-left)' -% 3rd dimension corresponds to slices, which should be 'horizontal(inferior-superior)' - -if strcmp(hdr.columns, 'coronal(occipital-frontal)') - orientation(1) = 1; -elseif strcmp(hdr.columns, 'sagittal(right-left)') - orientation(1) = 2; -elseif strcmp(hdr.columns, 'horizontal(inferior-superior)') - orientation(1) = 3; -end - -if strcmp(hdr.rows, 'coronal(occipital-frontal)') - orientation(2) = 1; -elseif strcmp(hdr.rows, 'sagittal(right-left)') - orientation(2) = 2; -elseif strcmp(hdr.rows, 'horizontal(inferior-superior)') - orientation(2) = 3; -end - -if strcmp(hdr.slices, 'coronal(occipital-frontal)') - orientation(3) = 1; -elseif strcmp(hdr.slices, 'sagittal(right-left)') - orientation(3) = 2; -elseif strcmp(hdr.slices, 'horizontal(inferior-superior)') - orientation(3) = 3; -end - -mri = ipermute(mri, orientation); -seg = ipermute(seg, orientation); -hdr.rows = 'sagittal(right-left)'; -hdr.columns = 'coronal(occipital-frontal)'; -hdr.slices = 'horizontal(inferior-superior)'; - -% recompute the dimensions after all the swapping -hdr.Nrows = size(mri, 1); -hdr.Ncolumns = size(mri, 2); -hdr.Nslices = size(mri, 3); -dim = size(mri); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% if possible, create the accompanying homogenous coordinate transformation matrix -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -if exist('headcoordinates', 'file') - % In case of PointOn..., ASA counts voxels from the center of the MRI - % and in case of VoxelOn..., ASA counts voxels from the corner of the MRI - % In both cases, ASA starts counting at [0 0 0], which is C convention - % whereas I want to count from the 1st voxel and number that with [1 1 1] - if ~isempty(hdr.posx) & ~isempty(hdr.negy) & ~isempty(hdr.posy) - offset = (dim + [1 1 1])/2; - hdr.fiducial.mri.nas = hdr.posx + offset; - hdr.fiducial.mri.lpa = hdr.posy + offset; - hdr.fiducial.mri.rpa = hdr.negy + offset; - else - offset = [1 1 1]; - hdr.fiducial.mri.nas = hdr.voxposx + offset; - hdr.fiducial.mri.lpa = hdr.voxposy + offset; - hdr.fiducial.mri.rpa = hdr.voxnegy + offset; - end - - % use the headcoordinates function (roboos/misc) to compute the transformaton matrix - hdr.transformMRI2Head = headcoordinates(hdr.fiducial.mri.nas, hdr.fiducial.mri.lpa, hdr.fiducial.mri.rpa, 1); - hdr.transformHead2MRI = inv(hdr.transformMRI2Head); - - % compute the fiducials in head coordinates - hdr.fiducial.head.nas = warp_apply(hdr.transformMRI2Head, hdr.fiducial.mri.nas, 'homogenous'); - hdr.fiducial.head.lpa = warp_apply(hdr.transformMRI2Head, hdr.fiducial.mri.lpa, 'homogenous'); - hdr.fiducial.head.rpa = warp_apply(hdr.transformMRI2Head, hdr.fiducial.mri.rpa, 'homogenous'); -end - diff --git a/external/fileio/private/read_asa_msr.m b/external/fileio/private/read_asa_msr.m deleted file mode 100644 index c98f171..0000000 --- a/external/fileio/private/read_asa_msr.m +++ /dev/null @@ -1,73 +0,0 @@ -function data = read_asa_msr(fn); - -% READ_ASA_MSR reads EEG or MEG data from an ASA data file -% converting the units to uV or fT - -% Copyright (C) 2002, Robert Oostenveld -% -% $Log: read_asa_msr.m,v $ -% Revision 1.5 2008/11/14 07:41:17 roboos -% only whitespace, no functional change -% -% Revision 1.4 2008/11/14 07:36:24 roboos -% use strcmpi instead of strcmp(lower()) -% -% Revision 1.3 2008/11/12 17:02:03 roboos -% explicitely specify ieee-le in fopen() -% -% Revision 1.2 2003/03/11 15:24:51 roberto -% updated help and copyrights -% - -Npnt = read_asa(fn, 'NumberPositions=', '%d'); -Ntime = read_asa(fn, 'NumberTimesteps=', '%d'); -UnitT = read_asa(fn, 'UnitTime', '%s'); -UnitM = read_asa(fn, 'UnitMeas', '%s'); -Timesteps = read_asa(fn, 'Timesteps', '%s'); -lab = read_asa(fn, 'Labels', '%s', Npnt); - -val = read_asa(fn, 'Values', '%f'); -if any(size(val)~=[Npnt,Ntime]) - msm_file = read_asa(fn, 'Values', '%s'); - [path, name, ext] = fileparts(fn); - fid = fopen(fullfile(path, msm_file), 'rb', 'ieee-le'); - val = fread(fid, [Ntime, Npnt], 'float32')'; - fclose(fid); -end - -tmp = sscanf(Timesteps, '%f(%f)%f'); -time = linspace(tmp(1), tmp(3), Ntime); - -if strcmpi(UnitT,'ms') - time = 1*time; -elseif strcmpi(UnitT,'s') - time = 1000*time; -elseif ~isempty(UnitT) - error(sprintf('Unknown unit of time (%s)', UnitT)); -end - -if strcmpi(UnitM,'uv') - val = 1*val; -elseif strcmpi(UnitM,'?v') - val = 1*val; -elseif strcmpi(UnitM,'mv') - val = 1000*val; -elseif strcmpi(UnitM,'v') - val = 1000000*val; -elseif strcmpi(UnitM,'ft') - val = 1*val; -elseif strcmpi(UnitM,'pt') - val = 1000*val; -elseif ~isempty(UnitM) - error(sprintf('Unknown unit of measurement (%s)', UnitM)); -end - -if length(size(lab))==2 - lab = tokenize(lab{1}); -end - -data.time = time; -data.data = val; -data.label = lab; - - diff --git a/external/fileio/private/read_asa_vol.m b/external/fileio/private/read_asa_vol.m deleted file mode 100644 index 0461280..0000000 --- a/external/fileio/private/read_asa_vol.m +++ /dev/null @@ -1,120 +0,0 @@ -function vol = read_asa_vol(fn); - -% READ_ASA_VOL reads an ASA volume conductor file -% -% all data is converted to the following units -% vertices mm -% conductivities S/m - -% Copyright (C) 2002, Robert Oostenveld -% -% $Log: read_asa_vol.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.4 2008/11/14 07:36:24 roboos -% use strcmpi instead of strcmp(lower()) -% -% Revision 1.3 2003/12/16 10:24:31 roberto -% added ieee-le to binary reading of mat file to fix problem on Mac -% -% Revision 1.2 2003/03/11 15:24:51 roberto -% updated help and copyrights -% - -Nbnd = read_asa(fn, 'NumberBoundaries=', '%d'); -UnitC = read_asa(fn, 'UnitConduct', '%s'); -UnitP = read_asa(fn, 'UnitPosition', '%s'); -cond = read_asa(fn, 'Conductivities', '%f'); -radii = read_asa(fn, 'Radii', '%f'); -pos = read_asa(fn, 'Positions', '%f'); -bnd1 = read_asa(fn, 'Boundary1', '%s'); -bnd2 = read_asa(fn, 'Boundary2', '%s'); -bnd3 = read_asa(fn, 'Boundary3', '%s'); -bnd4 = read_asa(fn, 'Boundary4', '%s'); - -if ~isempty(radii) | ~isempty(pos) - % this appears to be a spherical volume conductor - if strcmpi(UnitP,'mm') - radii = 1*radii; - pos = 1*pos; - elseif strcmpi(UnitP,'cm') - radii = 100*radii; - pos = 100*pos; - elseif strcmpi(UnitP,'m') - radii = 1000*radii; - pos = 1000*pos; - else - error(sprintf('Unknown unit of distance for volume (%s)', UnitP)); - end -end - -if strcmpi(UnitC,'s/m') - cond = cond/1; -elseif strcmpi(UnitC,'s/cm') - cond = cond/100; -elseif strcmpi(UnitC,'s/mm') - cond = cond/1000; -else - error(sprintf('Unknown unit of conductivity for volume (%s)', UnitC)); -end - -if ~isempty(radii) - % this appears to be a spherical volume conductor - vol.radius = radii; - vol.cond = cond; - vol.center = pos; -else - % this appears to be a realistical volume conductor - [path, name, ext] = fileparts(fn); - if Nbnd>=1 - vol.bnd(1) = read_asa_bnd(fullfile(path, bnd1)); - end - if Nbnd>=2 - vol.bnd(2) = read_asa_bnd(fullfile(path, bnd2)); - end - if Nbnd>=3 - vol.bnd(3) = read_asa_bnd(fullfile(path, bnd3)); - end - if Nbnd>=4 - vol.bnd(4) = read_asa_bnd(fullfile(path, bnd4)); - end - if Nbnd>=5 - error('cannot read more than 4 boundaries'); - end - - % if there is a precomputed matrix, read it from an external file - mat_file = read_asa(fn, 'Matrix', '%s'); - if ~isempty(mat_file) - nr = read_asa(fullfile(path, mat_file), 'NumberRows=', '%d'); - nc = read_asa(fullfile(path, mat_file), 'NumberColumns=', '%d'); - mab_file = read_asa(fullfile(path, mat_file), 'Matrix', '%s'); - fid = fopen(fullfile(path, mab_file), 'rb', 'ieee-le'); - if fid==-1 - error(sprintf('could not open file %s', mab_file)); - else - vol.mat = fread(fid, [nr nc], 'float32'); - fclose(fid); - % remove the factor 2 that ASA assumes in the system matrix - vol.mat = vol.mat/2; - % scale the system matrix corresponding to vertex coordinates in mm - vol.mat = vol.mat*100; - end - end - - vol.cond = cond; -end - -% remove all empty fields -field=fieldnames(vol); -for i=1:length(field) - if isempty(getfield(vol, field{i})) - vol = rmfield(vol, field{i}); - end -end - diff --git a/external/fileio/private/read_besa_mul.m b/external/fileio/private/read_besa_mul.m deleted file mode 100644 index 7ffaabd..0000000 --- a/external/fileio/private/read_besa_mul.m +++ /dev/null @@ -1,90 +0,0 @@ -function [dat] = read_besa_mul(filename) - -% READ_BESA_MUL reads data from a BESA multiplexed (*.mul) file -% -% Use as -% dat = read_besa_mul(filename); - -% Copyright (C) 2005, Robert Oostenveld -% -% $Log: read_besa_mul.m,v $ -% Revision 1.2 2008/11/14 07:42:13 roboos -% use general tokenize function instead of local copy, removed tokenize as subfunction -% -% Revision 1.1 2005/07/29 13:32:38 roboos -% new implementation -% - -dat = []; -fid = fopen(filename, 'rt'); - -% According to the BESA documentation, the ASCII Multiplexed Format is as -% follows: -% -% The first of two header lines contains similar information to that of the -% BESA ASCII file: -% -% TimePoints= 200 Channels= 27 BeginSweep[ms]= -500.00 -% SamplingInterval[ms]= 5.000 Bins/uV= 1.000 SegmentName=Condition1 -% -% Note that the item 'SegmentName' is missing if no segment comment is -% specified when writing a segment to file. -% -% If an epoch of a continuous EEG is exported in ASCII multiplexed format, -% the first header line contains the additional item 'Time', which -% indicates the daytime of the first sample in the exported segment: -% -% TimePoints= 200 Channels= 27 BeginSweep[ms]= 0.00 SamplingInterval[ms]= -% 5.000 Bins/uV= 1.000 Time=22:02:53 SegmentName=Segment1 - -hdr1 = fgetl(fid); -% split the first header line into separate elements -tmp = tokenize(hdr1, ' '); -for i=1:length(tmp) - % extract the information from each element - dum = tokenize(tmp{i}, '='); - var = dum{1}; % this is the name of the header variable - val = dum{2}; % this is the value of the header variable - var(var=='/') = '_'; % replace characters that are not valid in a structure element name - var(var=='[') = '_'; % replace characters that are not valid in a structure element name - var(var==']') = '_'; % replace characters that are not valid in a structure element name - var(var=='.') = '_'; % replace characters that are not valid in a structure element name - num = str2num(val); - if ~isempty(num) - dat = setfield(dat, var, num); - else - dat = setfield(dat, var, val); - end -end - -% The second line of the header contains labels for each channel, which may -% be either the original channel names, or the names of the channels of the -% current montage, e.g. -% -% O1 Oz P3 T5 T3 C3 F7 F3 Fp1 Fz Cz Pz Fp2 F4 F8 C4 T4 T6 P4 Fpz O2 M2 M1 -% F10 F9 T10 T9 -% -% Each subsequent line contains values for all 'Channels' at one time -% point, in floating point or scientific format. Values are given for the -% current or the original montage, selected as described above. -% -% Labels for source montages have the following form: 'TAr-L'. -% -% The first two letters indicate the head region: -% -% The small letter indicates in part the orientation: r=radial, -% t=tangential, and in part the relative location of the basal temporal -% source: l=lateral, m=mesial. -% -% The final letter after the hyphen indicates L=left, M=middle, R=right. - -hdr2 = fgetl(fid); -% split the second header line into channel/source labels -dat.label = tokenize(hdr2, ' '); - -% read the actual data -dat.data = fscanf(fid, '%g'); -dat.data = reshape(dat.data, [dat.Channels dat.TimePoints]); - -fclose(fid); -return diff --git a/external/fileio/private/read_besa_src.m b/external/fileio/private/read_besa_src.m deleted file mode 100644 index 26fda87..0000000 --- a/external/fileio/private/read_besa_src.m +++ /dev/null @@ -1,61 +0,0 @@ -function [src] = read_besa_src(filename); - -% READ_BESA_SRC reads a beamformer source reconstruction from a BESA file -% -% Use as -% [src] = read_besa_src(filename) -% -% The output structure contains a minimal representation of the contents -% of the file. - -% Copyright (C) 2005, Robert Oostenveld -% -% $Log: read_besa_src.m,v $ -% Revision 1.2 2005/10/05 06:32:08 roboos -% removed forced reading of (incorrect) condition label -% -% Revision 1.1 2005/09/01 09:22:35 roboos -% new implementation, only tested on a single file -% - -src = []; -fid = fopen(filename, 'rt'); - -% read the header information -line = fgetl(fid); -while isempty(strmatch('BESA_SA_IMAGE', line)), line = fgetl(fid); check_feof(fid, filename); end -% while isempty(strmatch('sd' , line)), line = fgetl(fid); check_feof(fid, filename); end % this line contains condition information -while isempty(strmatch('Grid dimen' , line)), line = fgetl(fid); check_feof(fid, filename); end -while isempty(strmatch('X:' , line)), line = fgetl(fid); check_feof(fid, filename); end; linex = line; -while isempty(strmatch('Y:' , line)), line = fgetl(fid); check_feof(fid, filename); end; liney = line; -while isempty(strmatch('Z:' , line)), line = fgetl(fid); check_feof(fid, filename); end; linez = line; - -tok = tokenize(linex, ' '); -src.X = [str2num(tok{2}) str2num(tok{3}) str2num(tok{4})]; -tok = tokenize(liney, ' '); -src.Y = [str2num(tok{2}) str2num(tok{3}) str2num(tok{4})]; -tok = tokenize(linez, ' '); -src.Z = [str2num(tok{2}) str2num(tok{3}) str2num(tok{4})]; - -nx = src.X(3); -ny = src.Y(3); -nz = src.Z(3); - -src.vol = zeros(nx, ny, nz); - -for i=1:nz - % search up to the next slice - while isempty(strmatch(sprintf('Z: %d', i-1), line)), line = fgetl(fid); check_feof(fid, filename); end; - % read all the values for this slice - buf = fscanf(fid, '%f', [nx ny]); - src.vol(:,:,i) = buf; -end - -fclose(fid); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function check_feof(fid, filename) -if feof(fid) - error(sprintf('could not read all information from file ''%s''', filename)); -end - diff --git a/external/fileio/private/read_besa_swf.m b/external/fileio/private/read_besa_swf.m deleted file mode 100644 index 4e7bc07..0000000 --- a/external/fileio/private/read_besa_swf.m +++ /dev/null @@ -1,90 +0,0 @@ -function [swf] = read_besa_swf(filename); - -% READ_BESA_SWF -% -% Use as -% [swf] = read_besa_swf(filename) -% -% This will return a structure with the header information in -% swf.label cell array with labels -% swf.data data matrix, Nchan X Npnts -% swf.npnt -% swf.tsb -% swf.di -% swf.sb - -% Copyright (C) 2006, Robert Oostenveld -% -% $Log: read_besa_swf.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.3 2006/06/22 15:03:07 roboos -% fixed bug, data was transposed in case of row-formatted file -% -% Revision 1.2 2006/03/20 08:39:13 roboos -% 2 small bug fixes, thanks to Vladimir -% -% Revision 1.1 2006/03/16 17:31:42 roboos -% new implementation, supports both rows and columns -% - -fid = fopen(filename); -line = fgetl(fid); -head = sscanf(line,'Npts= %f TSB= %f DI= %f SB= %f'); % new BESA versions include more information in the .swf file header; skip that -Npts = head(1); -TSB = head(2); -DI = head(3); -SB = head(4); - -offset = ftell(fid); - -% try reading a label and a number -dum = textscan(fid, '%s %f', 1); -fseek(fid, offset, 'bof'); - -if isempty(dum{2}) - % first line contains all labels, each subsequent line is one timepoint for all channels - line = fgetl(fid); - line(line==' ') = []; - label = tokenize(line, ':')'; - if isempty(label{end}) - label = label(1:(end-1)); % the last one is empty - end - Nsrc = length(label); - dat = fscanf(fid, '%f', inf); - dat = reshape(dat, Nsrc, Npts); -else - % each line starts with a single label, followed by all timepoints for that channel - dat = []; - label = {}; - count = 0; - while ~feof(fid) - count = count+1; - % read one line at a time - line = fgetl(fid); - sel = find(line==':', 1); - label{count} = deblank(line(1:(sel-1))); - buf = sscanf(line((sel+1):end), '%f'); - dat(count,:) = buf(:); - end -end - -fclose(fid); - -% assign the output, should be similar as READ_BESA_AVR -swf.npnt = Npts; -swf.tsb = TSB; -swf.di = DI; -swf.sb = SB; -swf.label = label; -swf.data = dat; - -% FIXME, here combine the channels of the regional sources - - diff --git a/external/fileio/private/read_biosemi_bdf.m b/external/fileio/private/read_biosemi_bdf.m deleted file mode 100644 index a40fc88..0000000 --- a/external/fileio/private/read_biosemi_bdf.m +++ /dev/null @@ -1,307 +0,0 @@ -function dat = read_biosemi_bdf(filename, hdr, begsample, endsample, chanindx); - -% READ_BIOSEMI_BDF reads specified samples from a BDF continous datafile -% It neglects all trial boundaries as if the data was acquired in -% non-continous mode. -% -% Use as -% [hdr] = read_biosemi_bdf(filename); -% where -% filename name of the datafile, including the .bdf extension -% This returns a header structure with the following elements -% hdr.Fs sampling frequency -% hdr.nChans number of channels -% hdr.nSamples number of samples per trial -% hdr.nSamplesPre number of pre-trigger samples in each trial -% hdr.nTrials number of trials -% hdr.label cell-array with labels of each channel -% hdr.orig detailled EDF header information -% -% Or use as -% [dat] = read_biosemi_bdf(filename, hdr, begsample, endsample, chanindx); -% where -% filename name of the datafile, including the .bdf extension -% hdr header structure, see above -% begsample index of the first sample to read -% endsample index of the last sample to read -% chanindx index of channels to read (optional, default is all) -% This returns a Nchans X Nsamples data matrix - -% Copyright (C) 2006, Robert Oostenveld -% -% $Log: read_biosemi_bdf.m,v $ -% Revision 1.2 2009/10/12 12:14:23 roboos -% fixed small typo in readLowLevel fnuction, thanks to Philip -% -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.7 2008/10/06 08:42:17 roboos -% added missing "end" in subfunction -% -% Revision 1.6 2008/10/03 12:20:57 roboos -% use matlab reading instead of mex file in case file >2GB, thanks to Philip -% -% Revision 1.5 2008/09/30 07:47:04 roboos -% replaced all occurences of setstr() with char(), because setstr is deprecated by Matlab -% -% Revision 1.4 2007/10/01 13:44:21 roboos -% changed a detail in the calibration (in case of one channel the output would remain sparse) -% -% Revision 1.3 2007/09/13 09:52:20 roboos -% removed section of code regarding idx1/2/3 which was slow but unneeded -% avoid confusion between EDF and hdr.orig -% implemented much faster reading for a single channel (efficient when reading status channel) -% -% Revision 1.2 2007/09/12 12:52:09 roboos -% calibrate the data -% -% Revision 1.1 2006/02/01 08:18:48 roboos -% new implementation, based on some EEGLAB code and a mex file for the binary part of the data -% - -if nargin==1 - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % read the header, this code is from EEGLAB's openbdf - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - FILENAME = filename; - - % defines Seperator for Subdirectories - SLASH='/'; - BSLASH=char(92); - - cname=computer; - if cname(1:2)=='PC' SLASH=BSLASH; end; - - fid=fopen(FILENAME,'r','ieee-le'); - if fid<0 - fprintf(2,['Error LOADEDF: File ' FILENAME ' not found\n']); - return; - end; - - EDF.FILE.FID=fid; - EDF.FILE.OPEN = 1; - EDF.FileName = FILENAME; - - PPos=min([max(find(FILENAME=='.')) length(FILENAME)+1]); - SPos=max([0 find((FILENAME=='/') | (FILENAME==BSLASH))]); - EDF.FILE.Ext = FILENAME(PPos+1:length(FILENAME)); - EDF.FILE.Name = FILENAME(SPos+1:PPos-1); - if SPos==0 - EDF.FILE.Path = pwd; - else - EDF.FILE.Path = FILENAME(1:SPos-1); - end; - EDF.FileName = [EDF.FILE.Path SLASH EDF.FILE.Name '.' EDF.FILE.Ext]; - - H1=char(fread(EDF.FILE.FID,256,'char')'); % - EDF.VERSION=H1(1:8); % 8 Byte Versionsnummer - %if 0 fprintf(2,'LOADEDF: WARNING Version EDF Format %i',ver); end; - EDF.PID = deblank(H1(9:88)); % 80 Byte local patient identification - EDF.RID = deblank(H1(89:168)); % 80 Byte local recording identification - %EDF.H.StartDate = H1(169:176); % 8 Byte - %EDF.H.StartTime = H1(177:184); % 8 Byte - EDF.T0=[str2num(H1(168+[7 8])) str2num(H1(168+[4 5])) str2num(H1(168+[1 2])) str2num(H1(168+[9 10])) str2num(H1(168+[12 13])) str2num(H1(168+[15 16])) ]; - - % Y2K compatibility until year 2090 - if EDF.VERSION(1)=='0' - if EDF.T0(1) < 91 - EDF.T0(1)=2000+EDF.T0(1); - else - EDF.T0(1)=1900+EDF.T0(1); - end; - else ; - % in a future version, this is hopefully not needed - end; - - EDF.HeadLen = str2num(H1(185:192)); % 8 Byte Length of Header - % reserved = H1(193:236); % 44 Byte - EDF.NRec = str2num(H1(237:244)); % 8 Byte # of data records - EDF.Dur = str2num(H1(245:252)); % 8 Byte # duration of data record in sec - EDF.NS = str2num(H1(253:256)); % 8 Byte # of signals - - EDF.Label = char(fread(EDF.FILE.FID,[16,EDF.NS],'char')'); - EDF.Transducer = char(fread(EDF.FILE.FID,[80,EDF.NS],'char')'); - EDF.PhysDim = char(fread(EDF.FILE.FID,[8,EDF.NS],'char')'); - - EDF.PhysMin= str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); - EDF.PhysMax= str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); - EDF.DigMin = str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); - EDF.DigMax = str2num(char(fread(EDF.FILE.FID,[8,EDF.NS],'char')')); - - % check validity of DigMin and DigMax - if (length(EDF.DigMin) ~= EDF.NS) - fprintf(2,'Warning OPENEDF: Failing Digital Minimum\n'); - EDF.DigMin = -(2^15)*ones(EDF.NS,1); - end - if (length(EDF.DigMax) ~= EDF.NS) - fprintf(2,'Warning OPENEDF: Failing Digital Maximum\n'); - EDF.DigMax = (2^15-1)*ones(EDF.NS,1); - end - if (any(EDF.DigMin >= EDF.DigMax)) - fprintf(2,'Warning OPENEDF: Digital Minimum larger than Maximum\n'); - end - % check validity of PhysMin and PhysMax - if (length(EDF.PhysMin) ~= EDF.NS) - fprintf(2,'Warning OPENEDF: Failing Physical Minimum\n'); - EDF.PhysMin = EDF.DigMin; - end - if (length(EDF.PhysMax) ~= EDF.NS) - fprintf(2,'Warning OPENEDF: Failing Physical Maximum\n'); - EDF.PhysMax = EDF.DigMax; - end - if (any(EDF.PhysMin >= EDF.PhysMax)) - fprintf(2,'Warning OPENEDF: Physical Minimum larger than Maximum\n'); - EDF.PhysMin = EDF.DigMin; - EDF.PhysMax = EDF.DigMax; - end - EDF.PreFilt= char(fread(EDF.FILE.FID,[80,EDF.NS],'char')'); % - tmp = fread(EDF.FILE.FID,[8,EDF.NS],'char')'; % samples per data record - EDF.SPR = str2num(char(tmp)); % samples per data record - - fseek(EDF.FILE.FID,32*EDF.NS,0); - - EDF.Cal = (EDF.PhysMax-EDF.PhysMin)./(EDF.DigMax-EDF.DigMin); - EDF.Off = EDF.PhysMin - EDF.Cal .* EDF.DigMin; - tmp = find(EDF.Cal < 0); - EDF.Cal(tmp) = ones(size(tmp)); - EDF.Off(tmp) = zeros(size(tmp)); - - EDF.Calib=[EDF.Off';(diag(EDF.Cal))]; - %EDF.Calib=sparse(diag([1; EDF.Cal])); - %EDF.Calib(1,2:EDF.NS+1)=EDF.Off'; - - EDF.SampleRate = EDF.SPR / EDF.Dur; - - EDF.FILE.POS = ftell(EDF.FILE.FID); - if EDF.NRec == -1 % unknown record size, determine correct NRec - fseek(EDF.FILE.FID, 0, 'eof'); - endpos = ftell(EDF.FILE.FID); - EDF.NRec = floor((endpos - EDF.FILE.POS) / (sum(EDF.SPR) * 2)); - fseek(EDF.FILE.FID, EDF.FILE.POS, 'bof'); - H1(237:244)=sprintf('%-8i',EDF.NRec); % write number of records - end; - - EDF.Chan_Select=(EDF.SPR==max(EDF.SPR)); - for k=1:EDF.NS - if EDF.Chan_Select(k) - EDF.ChanTyp(k)='N'; - else - EDF.ChanTyp(k)=' '; - end; - if findstr(upper(EDF.Label(k,:)),'ECG') - EDF.ChanTyp(k)='C'; - elseif findstr(upper(EDF.Label(k,:)),'EKG') - EDF.ChanTyp(k)='C'; - elseif findstr(upper(EDF.Label(k,:)),'EEG') - EDF.ChanTyp(k)='E'; - elseif findstr(upper(EDF.Label(k,:)),'EOG') - EDF.ChanTyp(k)='O'; - elseif findstr(upper(EDF.Label(k,:)),'EMG') - EDF.ChanTyp(k)='M'; - end; - end; - - EDF.AS.spb = sum(EDF.SPR); % Samples per Block - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % convert the header to Fieldtrip-style - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - if any(EDF.SampleRate~=EDF.SampleRate(1)) - error('channels with different sampling rate not supported'); - end - hdr.Fs = EDF.SampleRate(1); - hdr.nChans = EDF.NS; - hdr.label = cellstr(EDF.Label); - % it is continuous data, therefore append all records in one trial - hdr.nTrials = 1; - hdr.nSamples = EDF.NRec * EDF.Dur * EDF.SampleRate(1); - hdr.nSamplesPre = 0; - hdr.orig = EDF; - - % return the header - dat = hdr; - -else - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % read the data - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % retrieve the original header - EDF = hdr.orig; - - % determine the trial containing the begin and end sample - epochlength = EDF.Dur * EDF.SampleRate(1); - begepoch = floor((begsample-1)/epochlength) + 1; - endepoch = floor((endsample-1)/epochlength) + 1; - nepochs = endepoch - begepoch + 1; - nchans = EDF.NS; - - if nargin<5 - chanindx = 1:nchans; - end - - % allocate memory to hold the data - dat = zeros(length(chanindx),nepochs*epochlength); - - % read and concatenate all required data epochs - for i=begepoch:endepoch - offset = EDF.HeadLen + (i-1)*epochlength*nchans*3; - if length(chanindx)==1 - % this is more efficient if only one channel has to be read, e.g. the status channel - offset = offset + (chanindx-1)*epochlength*3; - buf = readLowLevel(filename, offset, epochlength); % see below in subfunction - dat(:,((i-begepoch)*epochlength+1):((i-begepoch+1)*epochlength)) = buf; - else - % read the data from all channels and then select the desired channels - buf = readLowLevel(filename, offset, epochlength*nchans); % see below in subfunction - buf = reshape(buf, epochlength, nchans); - dat(:,((i-begepoch)*epochlength+1):((i-begepoch+1)*epochlength)) = buf(:,chanindx)'; - end - end - - % select the desired samples - begsample = begsample - (begepoch-1)*epochlength; % correct for the number of bytes that were skipped - endsample = endsample - (begepoch-1)*epochlength; % correct for the number of bytes that were skipped - dat = dat(:, begsample:endsample); - - % Calibrate the data - if length(chanindx)>1 - % using a sparse matrix speeds up the multiplication - calib = sparse(diag(EDF.Cal(chanindx,:))); - dat = calib * dat; - else - % in case of one channel the calibration would result in a sparse array - calib = diag(EDF.Cal(chanindx,:)); - dat = calib * dat; - end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION for reading the 24 bit values -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function buf = readLowLevel(filename, offset, numwords); -if offset < 2*1024^3 - % use the external mex file, only works for <2GB - buf = read_24bit(filename, offset, numwords); - % this would be the only difference between the bdf and edf implementation - % buf = read_16bit(filename, offset, numwords); -else - % use plain matlab, thanks to Philip van der Broek - fp = fopen(filename,'r','ieee-le'); - status = fseek(fp, offset, 'bof'); - if status - error(['failed seeking ' filename]); - end - [buf,num] = fread(fp,numwords,'bit24=>double'); - fclose(fp); - if (num4 - % select the channels of interest - dat = dat(chanindx,:); -end diff --git a/external/fileio/private/read_biosig_header.m b/external/fileio/private/read_biosig_header.m deleted file mode 100644 index 4927e43..0000000 --- a/external/fileio/private/read_biosig_header.m +++ /dev/null @@ -1,132 +0,0 @@ -function [hdr] = read_biosig_header(filename) - -% READ_BIOSIG_HEADER reads header from EEG file using the BIOSIG -% toolbox and returns it in the FCDC framework standard format -% -% Use as -% [hdr] = read_biosig_header(filename) -% -% The following data formats are supported: EDF, BKR, CNT, BDF, GDF, -% see for full documentation http://biosig.sourceforge.net/ -% -% See also READ_BIOSIG_DATA - -% This program is free software; you can redistribute it and/or -% modify it under the terms of the GNU General Public License -% as published by the Free Software Foundation; either version 2 -% of the License, or (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program; if not, write to the Free Software -% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -% Copyright (C) 2004, Robert Oostenveld -% -% $Log: read_biosig_header.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.3 2008/04/10 09:36:14 roboos -% biosig labels are already cell array -% -% Revision 1.2 2004/03/11 10:18:57 roberto -% fixed bug in number of samples (should be the same in all channels) -% -% Revision 1.1 2004/03/10 11:50:31 roberto -% new implementation of wrapper functions around the BIOSIG toolbox (specifically section T200) -% - -% open the file, read the header and close it again -biosig = sopen(filename,'r'); -sclose(biosig); - -% the BIOSIG header is defined in full detail below -% the FCDC header should at least contain the following fields -% hdr.Fs sampling frequency -% hdr.nChans number of channels -% hdr.nSamples number of samples per trial -% hdr.nSamplesPre number of pre-trigger samples in each trial -% hdr.nTrials number of trials -% hdr.label cell-array with labels of each channel - -if length(biosig.SampleRate)>1 & any(diff(biosig.SampleRate)) - error('channels with different sampling rates are not supported'); -else - hdr.Fs = biosig.SampleRate(1); -end - -if length(biosig.SPR)>1 & any(diff(biosig.SPR)) - error('channels with different number of samples are not supported'); -else - hdr.nSamples = biosig.SPR(1); -end - -hdr.nChans = biosig.NS; -hdr.nTrials = biosig.NRec; -hdr.nSamplesPre = 0; % this one is not in the biosig header -hdr.label = {}; % start with empty labels and fill them below - -if isfield(biosig, 'Label') - hdr.label = biosig.Label; -end - -if length(hdr.label)~=hdr.nChans - % make default channel labels - hdr.label = {}; - for i=1:hdr.nChans - hdr.label{i} = sprintf('%d', i); - end -end - -% I prefer to have them as column vector -hdr.label = hdr.label(:); - -% also remember the biosig header details -hdr.orig = biosig; -return; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% the BIOSIG header always contains these elements -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% HDR.TYPE string type of data format -% HDR.VERSION string (depends on data format) -% HDR.T0 float[1..6] [yyyy mm dd hh MM ss.cc] see HELP CLOCK -% HDR.NS integer number of channels -% HDR.SampleRate integer sampling frequency in [Hz] -% HDR.NRec integer number of records or blocks; 1 for continous data -% HDR.SPR integer samples per record -% HDR.Dur float Duration (in [s]) of minimal block length -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% the BIOSIG header optinally contains the following elements -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% HDR.Filter.LowPass float [Hz] -% HDR.Filter.HighPass float [Hz] -% HDR.Filter.Notch int8 0=Off, 1=ON -% HDR.PreFilt string filter setting -% HDR.Label char-array z.B. '+C3a - C3p ' -% HDR.PhysDim string physical dimension e.g. 'uV' -% HDR.PhysMax float physical maximum -% HDR.DigMax integer digital maximum -% HDR.PhysMin float physical minimum -% HDR.DigMin integer digital minimum -% HDR.FLAG.TRIGGERED int 0=no, 1=yes -% HDR.FLAG.REFERENCE string COM, CAR: common average reference; LOC,LAR local average ref; LAP Laplacian derivation, WGT weighted average -% HDR.Classlabel int 0: left, 1: right, etc. -% HDR.ID.Doctor Identification of doctor -% HDR.ID.Hospital Identification of Hospital -% HDR.Patient.Name Name of Patient -% HDR.Patient.Age Age of Patient -% HDR.Patient.Sex Patient Gender -% HDR.Patient.Handedness Patient Handedness -% HDR.Patient.Medication Medication -% HDR.Patient.Classification Classification of Patient diff --git a/external/fileio/private/read_brainvision_eeg.m b/external/fileio/private/read_brainvision_eeg.m deleted file mode 100644 index cde8cd5..0000000 --- a/external/fileio/private/read_brainvision_eeg.m +++ /dev/null @@ -1,129 +0,0 @@ -function [dat] = read_brainvision_eeg(filename, hdr, begsample, endsample); - -% READ_BRAINVISION_EEG reads raw data from an EEG file -% and returns it as a Nchans x Nsamples matrix -% -% Use as -% dat = read_brainvision_eeg(filename, hdr, begsample, endsample) -% where the header should be first read using read_brainvision_vhdr -% -% See also READ_BRAINVISION_VHDR, READ_BRAINVISION_VMRK - -% Copyright (C) 2003, Robert Oostenveld -% -% $Log: read_brainvision_eeg.m,v $ -% Revision 1.2 2009/03/13 07:13:28 roboos -% added feedback to vectorized ascii subformat -% fixed problem in vectorized ascii subformat when lines would start with the channel label -% -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.5 2008/04/09 10:10:58 roboos -% added support for int_32 -% renamed nChans into the original form -% -% Revision 1.4 2007/06/13 08:08:19 roboos -% changed single & into && -% -% Revision 1.3 2004/03/30 11:47:50 roberto -% dos->unix, fixed bug in multiplexed binary -% -% Revision 1.2 2004/03/30 08:22:19 roberto -% fixed bug due to renaming NumberOfChannels -> nChans -% -% Revision 1.1 2004/03/30 07:23:28 roberto -% added to CVS repository, copyrights added and implemented multiple file -% formats -% - -if strcmpi(hdr.DataFormat, 'binary') && strcmpi(hdr.DataOrientation, 'multiplexed') && strcmpi(hdr.BinaryFormat, 'int_16') - fid = fopen(filename, 'rb', 'ieee-le'); - fseek(fid, hdr.NumberOfChannels*2*(begsample-1), 'cof'); - [dat, siz] = fread(fid, [hdr.NumberOfChannels, (endsample-begsample+1)], 'int16'); - fclose(fid); - % compute real microvolts using the calibration factor (resolution) - res = sparse(diag(hdr.resolution)); - dat = res * dat; - -elseif strcmpi(hdr.DataFormat, 'binary') && strcmpi(hdr.DataOrientation, 'multiplexed') && strcmpi(hdr.BinaryFormat, 'int_32') - fid = fopen(filename, 'rb', 'ieee-le'); - fseek(fid, hdr.NumberOfChannels*4*(begsample-1), 'cof'); - [dat, siz] = fread(fid, [hdr.NumberOfChannels, (endsample-begsample+1)], 'int32'); - fclose(fid); - % compute real microvolts using the calibration factor (resolution) - res = sparse(diag(hdr.resolution)); - dat = res * dat; - -elseif strcmpi(hdr.DataFormat, 'binary') && strcmpi(hdr.DataOrientation, 'multiplexed') && strcmpi(hdr.BinaryFormat, 'ieee_float_32') - fid = fopen(filename, 'rb', 'ieee-le'); - fseek(fid, hdr.NumberOfChannels*4*(begsample-1), 'cof'); - [dat, siz] = fread(fid, [hdr.NumberOfChannels, (endsample-begsample+1)], 'float32'); - fclose(fid); - -elseif strcmpi(hdr.DataFormat, 'binary') && strcmpi(hdr.DataOrientation, 'vectorized') && strcmpi(hdr.BinaryFormat, 'ieee_float_32') - fid = fopen(filename, 'rb', 'ieee-le'); - fseek(fid, 0, 'eof'); - hdr.nSamples = ftell(fid)/(4*hdr.NumberOfChannels); - fseek(fid, 0, 'bof'); - numsamples = (endsample-begsample+1); - for chan=1:hdr.NumberOfChannels - fseek(fid, (begsample-1)*4, 'cof'); % skip the first N samples - [tmp, siz] = fread(fid, numsamples, 'float32'); % read these samples - fseek(fid, (hdr.nSamples-endsample)*4, 'cof'); % skip the last M samples - dat(chan,:) = tmp(:)'; - end - fclose(fid); - -elseif strcmpi(hdr.DataFormat, 'ascii') && strcmpi(hdr.DataOrientation, 'multiplexed') - fid = fopen(filename, 'rt'); - for line=1:(begsample-1) - % read first lines and discard the data in them - str = fgets(fid); - end - dat = zeros(endsample-begsample+1, hdr.NumberOfChannels); - for line=1:(endsample-begsample+1) - str = fgets(fid); % read a single line with Nchan samples - str(find(str==',')) = '.'; % replace comma with point - dat(line,:) = str2num(str); - end - fclose(fid); - % transpose the data - dat = dat'; - -elseif strcmpi(hdr.DataFormat, 'ascii') && strcmpi(hdr.DataOrientation, 'vectorized') - % this is a very inefficient fileformat to read data from, since it requires to - % read in all the samples of each channel and then select only the samples of interest - fid = fopen(filename, 'rt'); - dat = zeros(hdr.NumberOfChannels, endsample-begsample+1); - for chan=1:hdr.NumberOfChannels - % this is very slow, so better give some feedback to indicate that something is happening - fprintf('reading channel %d from ascii file to get data from sample %d to %d\n', chan, begsample, endsample); - - str = fgets(fid); % read all samples of a single channel - str(find(str==',')) = '.'; % replace comma with point - - if ~isempty(regexp(str(1:10), '[a-zA-Z]', 'once')) - % the line starts with letters, not numbers: probably it is a channel label - % find the first number and remove the preceding part - sel = regexp(str(1:10), ' [-0-9]'); % find the first number, or actually the last space before the first number - label = str(1:(sel)); % this includes the space - str = str((sel+1):end); % keep only the numbers - end - - % convert the string into numbers and copy the desired samples over - % into the data matrix - tmp = str2num(str); - dat(chan,:) = tmp(begsample:endsample); - end - fclose(fid); - -else - error('unsupported sub-fileformat'); -end - diff --git a/external/fileio/private/read_brainvision_marker.m b/external/fileio/private/read_brainvision_marker.m deleted file mode 100644 index de9b0e5..0000000 --- a/external/fileio/private/read_brainvision_marker.m +++ /dev/null @@ -1,41 +0,0 @@ -function [rej] = read_brainvision_marker(fn); - -% READ_BRAINVISION_MARKER reads rejection marks from a BrainVision file -% -% Use as -% [rej] = read_brainvision_marker(filename) -% -% This function returns a Nx2 matrix with the begin and end latency -% of N rejection marks. The latency is in miliseconds. - -% Copyright (C) 2004, Robert Oostenveld & Doug Davidson -% -% $Log: read_brainvision_marker.m,v $ -% Revision 1.2 2004/09/24 15:57:20 roboos -% implemented suggested change by Doug Davidson: get sampling rate from file instead of having it hard coded -% -% Revision 1.1 2004/08/26 15:53:18 roboos -% new implementation by Doug Davidson, based upon read_eep_rej -% - -rej = []; - -[x y] = textread(fn, '%s%s', 1, 'delimiter', ',:' ); - -p = mat2str(cell2mat(y)); -pos = findstr('Hz', p); - -samplingrate = str2num(p(1:pos-1)); - -s = 1./samplingrate; - -[col1 col2] = textread(fn, '%*s%*s%n%n%*[^\n]',... - 'delimiter', ',',... - 'headerlines', 2 ); - -% Start and end points in msec -startp = (col1*s)*1000; -endp = ((col2*s)+(col1*s))*1000; - -rej = [startp endp]; -clear x p pos samplingrate; diff --git a/external/fileio/private/read_brainvision_pos.m b/external/fileio/private/read_brainvision_pos.m deleted file mode 100644 index fdd7613..0000000 --- a/external/fileio/private/read_brainvision_pos.m +++ /dev/null @@ -1,62 +0,0 @@ -function [elec] = read_brainvision_pos(filename); - -% READ_BRAINVISION_POS reads electrode positions measured with the Polhemus -% tracker in one of the F.C. Donders EEG labs. The polhemus software is actually -% not from Brainvision. -% -% Use as: -% [elec] = read_brainvision_pos(filename) -% -% This returns an electrode structure with -% elec.label cell-array with electrode labels (strings) -% elec.pnt position of each electrode - -% Copyright (C) 2004, Robert Oostenveld -% -% $Log: read_brainvision_pos.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.1 2004/03/18 09:34:34 roberto -% also read in the fiducials if present at the end of the file -% - -fid = fopen(filename, 'rt'); -line = fgetl(fid); -Nchan = str2double(line); - -for i=1:Nchan - line = fgetl(fid); - [t, r] = strtok(line); - elec.label{i} = char(t); - elec.pnt(i,:) = sscanf(r, '%f')'; -end -elec.label = elec.label(:); - -try - % read the fiducials - line = fgetl(fid); - [t, r] = strtok(line); - fiducial.label{1} = char(t); - fiducial.pnt(1,:) = sscanf(r, '%f')'; - line = fgetl(fid); - [t, r] = strtok(line); - fiducial.label{2} = char(t); - fiducial.pnt(2,:) = sscanf(r, '%f')'; - line = fgetl(fid); - [t, r] = strtok(line); - fiducial.label{3} = char(t); - fiducial.pnt(3,:) = sscanf(r, '%f')'; - % add the fiducials to the electrode array - elec.label = cat(1, elec.label(:), fiducial.label(:)); - elec.pnt = cat(1, elec.pnt, fiducial.pnt); -catch - % do nothing -end - -fclose(fid); \ No newline at end of file diff --git a/external/fileio/private/read_brainvision_seg.m b/external/fileio/private/read_brainvision_seg.m deleted file mode 100644 index 847865e..0000000 --- a/external/fileio/private/read_brainvision_seg.m +++ /dev/null @@ -1,51 +0,0 @@ -function [dat] = read_brainvision_seg(filename, hdr, begsample, endsample); - -% READ_BRAINVISION_SEG reads raw data from an segmented EEG file -% and returns it as a Nchans x Nsamples matrix. The data is read -% as if it were continuous data, this function does not check whether -% the specified begin and endsample are withing the same segment. -% -% Use as -% dat = read_brainvision_seg(filename, hdr, begsample, endsample) -% where the header should be first read using read_brainvision_vhdr -% -% See also READ_BRAINVISION_VHDR, READ_BRAINVISION_VMRK - -% Copyright (C) 2003, Robert Oostenveld -% -% $Log: read_brainvision_seg.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.4 2008/04/09 10:11:23 roboos -% renamed nChans into the original form, converted from dos to unix -% -% Revision 1.3 2007/06/13 08:08:19 roboos -% changed single & into && -% -% Revision 1.2 2004/03/30 08:22:19 roberto -% fixed bug due to renaming NumberOfChannels -> nChans -% -% Revision 1.1 2004/03/30 07:23:28 roberto -% added to CVS repository, copyrights added and implemented multiple file -% formats -% - -if strcmpi(hdr.DataFormat, 'binary') && strcmpi(hdr.DataOrientation, 'multiplexed') && strcmpi(hdr.BinaryFormat, 'int_16') - % this is a fileformat that I understand - fid = fopen(filename, 'rb', 'ieee-le'); - fseek(fid, hdr.NumberOfChannels*2*(begsample-1), 'cof'); - [dat, siz] = fread(fid, [hdr.NumberOfChannels, (endsample-begsample+1)], 'int16'); - fclose(fid); - % compute real microvolts using the calibration factor (resolution) - res = sparse(diag(hdr.resolution)); - dat = res * dat; -else - error('unsupported sub-fileformat'); -end - diff --git a/external/fileio/private/read_brainvision_vhdr.m b/external/fileio/private/read_brainvision_vhdr.m deleted file mode 100644 index 82210f9..0000000 --- a/external/fileio/private/read_brainvision_vhdr.m +++ /dev/null @@ -1,109 +0,0 @@ -function [hdr] = read_brainvision_vhdr(filename); - -% READ_BRAINVISION_VHDR reads the known items from the BrainVision EEG -% header file and returns them in a structure -% -% Use as -% hdr = read_brainvision_vhdr(filename) -% -% See also READ_BRAINVISION_EEG, READ_BRAINVISION_VMRK - -% Copyright (C) 2003, Robert Oostenveld -% -% $Log: read_brainvision_vhdr.m,v $ -% Revision 1.2 2009/03/12 17:09:31 roboos -% improved the warning in case number of samples cannot be determined (applies to ascii *.seg data) -% -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.7 2008/11/14 07:42:13 roboos -% use general tokenize function instead of local copy, removed tokenize as subfunction -% -% Revision 1.6 2008/07/10 07:15:30 roboos -% also determine data file size if on another directory, thanks to Paul -% -% Revision 1.5 2008/04/16 07:51:11 roboos -% added fixme comment -% -% Revision 1.4 2008/04/09 10:08:28 roboos -% added detection of number of samples, based on filesize (only if binary) -% -% Revision 1.3 2008/04/09 10:06:50 roboos -% renamed nChans into NumberOfChannels to stay as close as possible to the ascii header -% -% Revision 1.2 2004/03/30 11:23:50 roberto -% fixed bug in cutting channel info into pieces, added local tokenize function -% -% Revision 1.1 2004/03/30 07:23:28 roberto -% added to CVS repository, copyrights added and implemented multiple file -% formats -% - -hdr.DataFile = read_asa(filename, 'DataFile=', '%s'); -hdr.MarkerFile = read_asa(filename, 'MarkerFile=', '%s'); -hdr.DataFormat = read_asa(filename, 'DataFormat=', '%s'); -hdr.DataOrientation = read_asa(filename, 'DataOrientation=', '%s'); -hdr.BinaryFormat = read_asa(filename, 'BinaryFormat=', '%s'); -hdr.NumberOfChannels = read_asa(filename, 'NumberOfChannels=', '%d'); -hdr.SamplingInterval = read_asa(filename, 'SamplingInterval=', '%f'); % microseconds - -if ~isempty(hdr.NumberOfChannels) - for i=1:hdr.NumberOfChannels - chan_str = sprintf('Ch%d=', i); - chan_info = read_asa(filename, chan_str, '%s'); - t = tokenize(chan_info, ','); - hdr.label{i} = t{1}; - hdr.reference{i} = t{2}; - resolution = str2num(t{3}); % in microvolt - if ~isempty(resolution) - hdr.resolution(i) = resolution; - else - hdr.resolution(i) = nan; - end - end -end - -% compute the sampling rate in Hz -hdr.Fs = 1e6/(hdr.SamplingInterval); - -% the number of samples is unkown to start with -hdr.nSamples = Inf; - -% determine the number of samples by looking at the binary file -if strcmp(hdr.DataFormat, 'BINARY') - % the data file is supposed to be located in the same directory as the header file - % but that might be on another location than the present working directory - [p, f, x] = fileparts(filename); - datafile = fullfile(p, hdr.DataFile); - info = dir(datafile); - if isempty(info) - error('cannot determine the location of the data file %s', hdr.DataFile); - end - switch lower(hdr.BinaryFormat) - case 'int_16'; - hdr.nSamples = info.bytes./(hdr.NumberOfChannels*2); - case 'int_32'; - hdr.nSamples = info.bytes./(hdr.NumberOfChannels*4); - case 'ieee_float_32'; - hdr.nSamples = info.bytes./(hdr.NumberOfChannels*4); - end -end - -if isinf(hdr.nSamples) - warning('cannot determine number of samples for this sub-fileformat'); -end - -% the number of trials is unkown, assume continuous data -hdr.nTrials = 1; -hdr.nSamplesPre = 0; - -% ensure that the labels are in a column -hdr.label = hdr.label(:); -hdr.reference = hdr.reference(:); -hdr.resolution = hdr.resolution(:); diff --git a/external/fileio/private/read_brainvision_vmrk.m b/external/fileio/private/read_brainvision_vmrk.m deleted file mode 100644 index f9e0881..0000000 --- a/external/fileio/private/read_brainvision_vmrk.m +++ /dev/null @@ -1,77 +0,0 @@ -function [stimulus, response, segment, timezero] = read_brainvision_vmrk(filename); - -% READ_BRAINVISION_VMRK reads the markers and latencies -% it returns the stimulus/response code and latency in ms. -% -% Use as -% [stim, resp, segment, timezero] = read_brainvision_vmrk(filename) -% -% This function needs to read the header from a separate file and -% assumes that it is located at the same location. -% -% See also READ_BRAINVISION_VHDR, READ_BRAINVISION_EEG - -% original M. Schulte 31.07.2003 -% modifications R. Oostenveld 14.08.2003 -% -% $Log: read_brainvision_vmrk.m,v $ -% Revision 1.3 2008/07/24 12:05:12 roboos -% changed end ot line to unix style -% -% Revision 1.2 2004/03/30 07:23:28 roberto -% added to CVS repository, copyrights added and implemented multiple file -% formats -% - -stimulus=[]; -response=[]; -segment=[]; -timezero=[]; - -% read the header belonging to this marker file -hdr=read_brainvision_vhdr([filename(1:(end-4)) 'vhdr']); - -fid=fopen(filename,'rt'); -if fid==-1, - error('cannot open marker file') -end - -line=1; -while line~=-1, - line=fgetl(fid); - % pause - if ~isempty(line), - if ~isempty(findstr(line,'Mk')), - if ~isempty(findstr(line,'Stimulus')) - [token,rem] = strtok(line,','); - type=sscanf(rem,',S %i'); - [token,rem] = strtok(rem,','); - time=(sscanf(rem,', %i')-1)/hdr.Fs*1000; - stimulus=[stimulus; type time(1)]; - - elseif ~isempty(findstr(line,'Response')) - [token,rem] = strtok(line,','); - type=sscanf(rem,',R %i'); - [token,rem] = strtok(rem,','); - time=(sscanf(rem,', %i')-1)/hdr.Fs*1000; - response=[response; type, time(1)]; - - elseif ~isempty(findstr(line,'New Segment')) - [token,rem] = strtok(line,','); - time=(sscanf(rem,',,%i')-1)/hdr.Fs*1000; - segment=[segment; time(1)]; - - elseif ~isempty(findstr(line,'Time 0')) - [token,rem] = strtok(line,','); - time=(sscanf(rem,',,%i')-1)/hdr.Fs*1000; - timezero=[timezero; time(1)]; - - end - end - else - line=1; - end -end - -fclose(fid); - diff --git a/external/fileio/private/read_bti_hs.m b/external/fileio/private/read_bti_hs.m deleted file mode 100644 index 2eb3467..0000000 --- a/external/fileio/private/read_bti_hs.m +++ /dev/null @@ -1,57 +0,0 @@ -function [output, firstIndexPoint] = read_hs_file( filename, outfile) - -%read_hs_file Reads in BTI-Headshape files -% filename: file with the headshape informations -% outfile: if present, a ctf ".shape" file is written -% output: if present, a 3xN matrix containing the headshape-points -% -% (C) 2007 by Thomas Hartmann - -% $Log: read_bti_hs.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.3 2008/05/11 16:29:57 vlalit -% Changed the function to also output fiducials -% -% Revision 1.2 2007/08/06 09:23:57 roboos -% removed debug output, transposed output to Nx3 -% -% Revision 1.1 2007/08/06 09:03:42 roboos -% version as obtained from Nathan Weisz on 1-Aug-2007 -% - -if nargin == 1 - outfile = []; -end %if - -fid = fopen(filename, 'r', 'b'); -version = fread(fid, 1, '*uint32'); -timestamp = fread(fid, 1, '*int32'); -checksum = fread(fid, 1, '*int32'); -nPoints = fread(fid, 1, '*int32'); - -firstIndexPoint = fread(fid, [3, 5], 'double')'; - -points = fread(fid, [3, double(nPoints)], 'double'); - -fclose(fid); - -if(nargout > 0) - output = points'; -end %if - -if(nargin == 2) - fid = fopen(outfile, 'wt'); - fprintf(fid, '%d\n', nPoints); - for i = 1:size(points, 2) - fprintf(fid, '%.3f\t%.3f\t%.3f\n', points(1, i), points(2, i), points(3, i)); - end %for - fclose(fid); - -end %if diff --git a/external/fileio/private/read_bti_m4d.m b/external/fileio/private/read_bti_m4d.m deleted file mode 100644 index 4837e1e..0000000 --- a/external/fileio/private/read_bti_m4d.m +++ /dev/null @@ -1,176 +0,0 @@ -function [msi] = read_bti_m4d(filename); - -% READ_BTI_M4D -% -% Use as -% msi = read_bti_m4d(filename) - -% Copyright (C) 2007, Robert Oostenveld -% -% $Log: read_bti_m4d.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.3 2008/11/14 07:49:19 roboos -% use standard matlab strtrim function instead of deblank2 -% -% Revision 1.2 2008/08/12 12:56:08 jansch -% fixed assignment of msi.grad. in original implementation only the references were -% stored. in the future this part should be taken care of by bti2grad so that the -% gradiometer references will be correctly handled in the tra-matrix -% -% Revision 1.1 2007/07/03 15:51:46 roboos -% new implementation, only tested on two datasets -% - -[p, f, x] = fileparts(filename); -if ~strcmp(x, '.m4d') - % add the extension of the header - filename = [filename '.m4d']; -end - -fid = fopen(filename, 'r'); -if fid==-1 - error(sprintf('could not open file %s', filename)); -end - -% start with an empty header structure -msi = struct; - -% these header elements contain strings and should be converted in a cell-array -strlist = { - 'MSI.ChannelOrder' - }; - -% these header elements contain numbers and should be converted in a numeric array -% 'MSI.ChannelScale' -% 'MSI.ChannelGain' -% 'MSI.FileType' -% 'MSI.TotalChannels' -% 'MSI.TotalEpochs' -% 'MSI.SamplePeriod' -% 'MSI.SampleFrequency' -% 'MSI.FirstLatency' -% 'MSI.SlicesPerEpoch' -% the conversion to numeric arrays is implemented in a general fashion -% and all the fields above are automatically converted -numlist = {}; - -line = ''; - -msi.grad.label = {}; -msi.grad.pnt = zeros(0,3); -msi.grad.ori = zeros(0,3); -while ischar(line) - line = cleanline(fgetl(fid)); - if isempty(line) || (length(line)==1 && all(line==-1)) - continue - end - - sep = strfind(line, ':'); - if length(sep)==1 - key = line(1:(sep-1)); - val = line((sep+1):end); - elseif length(sep)>1 - % assume that the first separator is the relevant one, and that the - % next ones are part of the value string (e.g. a channel with a ':' in - % its name - sep = sep(1); - key = line(1:(sep-1)); - val = line((sep+1):end); - elseif length(sep)<1 - % this is not what I would expect - error('unexpected content in m4d file'); - end - - if ~isempty(strfind(line, 'Begin')) - sep = strfind(key, '.'); - sep = sep(end); - key = key(1:(sep-1)); - - % if the key ends with begin and there is no value, then there is a block - % of numbers following that relates to the magnetometer/gradiometer information. - % All lines in that Begin-End block should be treated seperately - val = {}; - lab = {}; - num = {}; - ind = 0; - while isempty(strfind(line, 'End')) - line = cleanline(fgetl(fid)); - if isempty(line) || (length(line)==1 && all(line==-1)) || ~isempty(strfind(line, 'End')) - continue - end - ind = ind+1; - % remember the line itself, and also cut it into pieces - val{ind} = line; - % the line is tab-separated and looks like this - % A68 0.0873437 -0.075789 0.0891512 0.471135 -0.815532 0.336098 - sep = find(line==9); % the ascii value of a tab is 9 - sep = sep(1); - lab{ind} = line(1:(sep-1)); - num{ind} = str2num(line((sep+1):end)); - - end % parsing Begin-End block - val = val(:); - lab = lab(:); - num = num(:); - num = cell2mat(num); - % the following is FieldTrip specific - if size(num,2)==6 - msi.grad.label = [msi.grad.label; lab(:)]; - % the numbers represent position and orientation of each magnetometer coil - msi.grad.pnt = [msi.grad.pnt; num(:,1:3)]; - msi.grad.ori = [msi.grad.ori; num(:,4:6)]; - else - error('unknown gradiometer design') - end - end - - % the key looks like 'MSI.fieldname.subfieldname' - fieldname = key(5:end); - - % remove spaces from the begin and end of the string - val = strtrim(val); - - % try to convert the value string into something more usefull - if ~iscell(val) - % the value can contain a variety of elements, only some of which are decoded here - if ~isempty(strfind(key, 'Index')) || ~isempty(strfind(key, 'Count')) || any(strcmp(key, numlist)) - % this contains a single number or a comma-separated list of numbers - val = str2num(val); - elseif ~isempty(strfind(key, 'Names')) || any(strcmp(key, strlist)) - % this contains a comma-separated list of strings - val = tokenize(val, ','); - else - tmp = str2num(val); - if ~isempty(tmp) - val = tmp; - end - end - end - - % assign this header element to the structure - msi = setsubfield(msi, fieldname, val); - -end % while ischar(line) - -fclose(fid); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION to remove spaces from the begin and end -% and to remove comments from the lines -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function line = cleanline(line) -if isempty(line) || (length(line)==1 && all(line==-1)) - return -end -comment = findstr(line, '//'); -if ~isempty(comment) - line(min(comment):end) = ' '; -end -line = strtrim(line); diff --git a/external/fileio/private/read_ced_son.m b/external/fileio/private/read_ced_son.m deleted file mode 100644 index 0916666..0000000 --- a/external/fileio/private/read_ced_son.m +++ /dev/null @@ -1,318 +0,0 @@ -function [out] = read_ced_son(datafile,varargin); - -% READ_CED_SON -% -% [OUT] = read_ced_son(DATAFILE,VARARGIN); -% -% Reads a analog and event data from a CED SON file -% (SON files are created by Spike2 software). Currently, only -% analog channels and event data can be read. -% -% Optional parameter Default -% 'readevents' 'no' -% 'readdata' 'no' -% 'readtimestamps' 'no' -% 'begsample' -1 -% 'endsample' -1 -% 'channels' [] -% -% Please note that CED DAQ systems do a sequential ADC, thus -% channels do not share the same time axis: The timestamps of the -% analog channels differ on a subsample level. Use the 'readtimestamps' -% input parameter to get a matrix with time axes corresponding -% to the data channels. -% -% Use begsample and endsample parameters to specify the boundaries -% of the requested data chunk. Setting these parameters to -1 will -% return data from the start or until the end of the datafile, -% respectively. -% -% Specifying [1,2] for 'channels' will load the 1st and the 2nd -% analog channel, __regardless of the actual channel number__ -% If, for example channel 1,2,3 are event channels, 4 as an analog -% channel, 5 is an event channel, and 6 is and analog channel, -% specifying [1 2] for 'channels' will load analog channel 4 and 6. -% Specifying [] for channels will return all analog channels. -% -% Setting 'readtimestamps' to 'yes' will return a time vector for -% each analog channel. -% -% Depending on the input parameters, the function will return a structure -% with fields: -% 'header' Header information of the SON file -% 'event' All data from event channels are pooled -% and stored in this structure. -% 'data' Cell-array with analog data -% 'time' Cell-array with time vectors corresponding to 'data' -% -% Uses Neuroshare libraries to read Spike2 SON data -% (see: http://neuroshare.sourceforge.net) - -% Gijs van Elswijk - 2005 (v0.1) - -% $Log: read_ced_son.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.4 2008/11/14 07:36:24 roboos -% use strcmpi instead of strcmp(lower()) -% -% Revision 1.3 2006/12/04 13:56:02 roboos -% incorporated modifications by Gijs van Elswijk: -% evt.type will be set to event channel label (was always 'trigger') -% evt.value will be set to event value (was event channel label) -% Bug fix: Channel index of source and target channels for timestep sizes were incorrect (bug found by Vladimir Litvak) -% -% Revision 1.4 2006/12/04 11:25:08 gijsve -% evt.type will be set to event channel label (was always 'trigger') -% evt.value will be set to event value (was event channel label) -% -% Revision 1.3 2006/11/25 15:33:53 gijsve -% - Bug fix: Channel index of source and target channels for timestep sizes were incorrect (bug found by Vladimir Litvak) -% -% Revision 1.2 2006/09/13 11:00:32 roboos -% explicitely load the nsCedSon.dll plugin, converted from DOS to UNIX ascii -% -% Revision 1.1 2005/11/24 16:02:08 roboos -% new implementation for Fieldtrip, thanks to Gijs van Elswijk -% -% Revision 1.2 2005/11/24 14:02:20 gijsve -% Removed temporal realignment -% Added analog timestamps as output -% Updated help documentation -% -% Revision 1.1 2005/11/17 22:12:48 gijsve -% First version in CVS: Helper function to read Spike2 data into fieldtrip -% - -MODE = 'continuous'; % assume continuous now - -% process in put parameters -if ~isempty(varargin) pars=struct(varargin{:}); else pars=[]; end; -if ~isfield(pars,'readdata'), pars = setfield(pars,'readdata','no'); end; -if ~isfield(pars,'readevents'), pars = setfield(pars,'readevents','no'); end; -if ~isfield(pars,'readtimestamps'), pars = setfield(pars,'readtimestamps','no'); end; -if ~isfield(pars,'begsample'), pars = setfield(pars,'begsample',-1); end; -if ~isfield(pars,'endsample'), pars = setfield(pars,'endsample',-1); end; -if ~isfield(pars,'channels'), pars = setfield(pars,'channels',[]); end; - -% set all fields string values to lowercase -fields = fieldnames(pars); -for idx=1:length(fields) - if isstr(getfield(pars,fields{idx})), - pars=setfield(pars,fields{idx},lower(getfield(pars,fields{idx}))); - end; -end; - -% First, check if NeuroShare DLL can be loaded -if filetype(datafile, 'ced_son') - % TODO other DLLs for other binary formats could be supported here as well - ns_RESULT = ns_SetLibrary(which('nsCedSon.dll')); -end -[st,libinfo] = ns_GetLibraryInfo; -if st, - error(['Could not get NeuroShare library info, please use the NS_SETLIBRARY function.']); -else, - disp(['Loading file ' datafile ' using NeuroShare library v',... - num2str(libinfo.LibVersionMaj),'.',num2str(libinfo.LibVersionMin),' ...']); -end; - -% open file -[st,fhandle] = ns_OpenFile(datafile); -if st, - [st,mesg] = ns_GetLastErrorMsg; - error(mesg); -end; - -try, - % file header - [st,fheader] = ns_GetFileInfo(fhandle); - if st, - [st,mesg] = ns_GetLastErrorMsg; - ns_CloseFile(fhandle); - error(mesg); - end; - - % Build catalogue of entities - [st, entityinfo] = ns_GetEntityInfo(fhandle, [1:fheader.EntityCount]); - - % get the channel numbers of analogue and event channels - % Neuroshare entity types: - % Unknown entity 0 - % Event entity 1 - % Analog entity 2 - % Segment entity 3 - % Neural event entity 4 - eventlist = find([entityinfo.EntityType] == 1); - analoglist = find([entityinfo.EntityType] == 2); - - % How many of a particular entity do we have - n_event = length(eventlist); - n_analog = length(analoglist); - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % HEADER - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % Fieldtrip uses: - % hdr.Fs sampling frequency - % hdr.nChans number of channels - % hdr.nSamples number of samples per trial - % hdr.nSamplesPre number of pre-trigger samples in each trial - % hdr.nTrials number of trials - % hdr.label cell-array with labels of each channel - cnt = 0; - for channr = analoglist(:)' - cnt = cnt+1; - [st,einfo] = ns_GetEntityInfo(fhandle,channr); - [st,ainfo] = ns_GetAnalogInfo(fhandle,channr); - % Until now, I haven't found a way to check whether the SON files - % are recorded in continuous or triggered mode by using header - % information only. Therefore, mode is explicitly set to continuous now. - % When reading a segment of analog data however, the NeuroShare - % routines provide information about the continuity of the - % read segment. If a discontinuity is detected a warning will - % be given in the command window. - if strcmpi(MODE,'continuous') - out.header(cnt).label = einfo.EntityLabel; - out.header(cnt).nsamples = einfo.ItemCount; - out.header(cnt).index = cnt; - out.header(cnt).sonentityid = channr; % this is the actual channr in the SON file - out.header(cnt).ntrials = 1; - out.header(cnt).samplerate = ainfo.SampleRate; - out.header(cnt).units = ainfo.Units; - out.header(cnt).mode = 'continuous'; - elseif strcmpi(MODE,'triggered'), - warning(['Triggered channel mode not implemented yet']); - out = []; - return - else, - error(['Unknown channel mode for channel ',num2str(channr)]); - end; - end; - out.header = orderfields(out.header); - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % EVENTS - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % Fieldtrip uses: - % event.type = string - % event.sample = expressed in samples, first sample of file is 1 - % event.value = number or string - % event.offset = expressed in samples - % event.duration = expressed in samples - if strcmp(pars.readevents,'yes') - cnt = 0; - for channr = eventlist(:)' - [st,einfo] = ns_GetEntityInfo(fhandle,channr); - [st,evtime,evdata] = ns_GetEventData(fhandle,channr,[1:einfo.ItemCount]); - - for trignr = 1:einfo.ItemCount, - cnt = cnt+1; - out.events(cnt).type = einfo.EntityLabel; - out.events(cnt).timestamp = evtime(trignr); - % Convert timestamp to sample nr. First analog channel's - % sample numbers are used as the reference for all - % timestamps. - [st,tmp] = ns_GetIndexByTime(fhandle,analoglist(1),evtime(trignr),0); - out.events(cnt).sample = tmp; - if iscell(evdata(trignr)) - out.events(cnt).value = evdata{trignr}; % cell2str - else - out.events(cnt).value = evdata(trignr); - end; - out.events(cnt).offset = 0; - out.events(cnt).duration = 0; - end; - end; - out.events = orderfields(out.events); - end; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % DATA - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - if strcmp(pars.readdata,'yes') - - % if no channels specified default to all analog channels - if isempty(pars.channels), - pars.channels = analoglist; - else, % renumber requested channels to entityIDs - if length(pars.channels)>length(analoglist), - error(['Requested more analog channels than present in datafile']); - else, - pars.channels = analoglist(pars.channels); - end; - end; - - % use first analog channel as reference channel - targetchan = analoglist(1); - [st,einfo] = ns_GetEntityInfo(fhandle,targetchan); - - %if no begsample specified default to start of channel - if pars.begsample<0, begsample=1; else begsample=pars.begsample; end; - %if no endsample specified default to end of channel - if pars.endsample<0, endsample=einfo.ItemCount; else endsample=pars.endsample; end; - - % calculate number of samples needed (for all requested channels) - itemcount = endsample-begsample+1; - targetstep = out.header([out.header.sonentityid]==targetchan).samplerate; - [st,targetbegin] = ns_GetTimeByIndex(fhandle,targetchan,begsample); - - cnt = 0; - for channr = pars.channels(:)', - cnt = cnt+1; - - % Cut out the data of channels 1-N in the following way - % - % begtime itemcount - % analog 1 [x..|x..x..x..x..x..x..x..x..x..x..x|..] - % analog 2 [.x.|.x..x..x..x..x..x..x..x..x..x..x|.] - % analog N [..x|..x..x..x..x..x..x..x..x..x..x..x|] - % - % All channels will have the same number of samples, - % but timestamps of the channels are offset on subsample - % level, due to asynchronous sampling of the CED DAQ - % hardware. - - % return the sample nr occuring after and inclusive of begtime. - [st,begsample] = ns_GetIndexByTime(fhandle,channr,targetbegin,1); - % get the same number of samples as in the target channel - endsample = begsample + itemcount-1; - [st,contcount,chandata] = ns_GetAnalogData(fhandle,channr, begsample,itemcount); - if contcount~=itemcount, warning(['Discontinuity in data']); end; - - % make a time scale - [st,begtime] = ns_GetTimeByIndex(fhandle,channr,begsample); - [st,endtime] = ns_GetTimeByIndex(fhandle,channr,endsample); - sourcestep = out.header([out.header.sonentityid]==channr).samplerate; - - if sourcestep~=targetstep, warning(['Source and target channels have time steps of different size']); end; - chantime = [begtime:1/sourcestep:endtime]; - - out.data{cnt} = chandata(:)'; - if strcmp(pars.readtimestamps,'yes') out.time{cnt} = chantime(:)'; end; - end; - end; - - % close file - [st] = ns_CloseFile(fhandle); - if st, - [st,mesg] = ns_GetLastErrorMsg; - disp(mesg); - end; - -% use catch to close any opened files before terminating -catch, - % fclose(fid); - [st] = ns_CloseFile(fhandle); - if st, - [st,mesg] = ns_GetLastErrorMsg; - disp(mesg); - end; - error(lasterr); -end; - diff --git a/external/fileio/private/read_ctf_ascii.m b/external/fileio/private/read_ctf_ascii.m deleted file mode 100644 index 016b8f8..0000000 --- a/external/fileio/private/read_ctf_ascii.m +++ /dev/null @@ -1,118 +0,0 @@ -function [file] = read_ctf_ascii(filename); - -% READ_CTF_ASCII reads general data from an CTF configuration file -% -% The file should be formatted like -% Group -% { -% item1 : value1a value1b value1c -% item2 : value2a value2b value2c -% item3 : value3a value3b value3c -% item4 : value4a value4b value4c -% } -% -% This fileformat structure is used in -% params.avg -% default.hdm -% multiSphere.hdm -% processing.cfg -% and maybe for other files as well. - -% Copyright (C) 2003, Robert Oostenveld -% -% $Log: read_ctf_ascii.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.10 2008/11/14 07:49:19 roboos -% use standard matlab strtrim function instead of deblank2 -% -% Revision 1.9 2006/08/29 11:08:41 roboos -% close file after reading from it -% -% Revision 1.8 2006/03/06 10:46:53 roboos -% fixed bug (again) in shortcirquited || -% -% Revision 1.7 2006/03/06 09:40:53 roboos -% changed a | into a || -% -% Revision 1.6 2006/02/24 15:43:43 roboos -% fixed bug in shortcirquited || which was not boolean on both sides -% -% Revision 1.5 2006/02/09 08:36:33 roboos -% changed single | into || since it is a boolean evaluation (thanks to Tom) -% -% Revision 1.4 2004/08/02 13:06:09 roboos -% fixed bug that occurred for hdm files based on markers: structs cannot have fields that have a name which consists of a single number, so in that case use the fieldname "item_1" etc. -% -% Revision 1.3 2004/06/28 07:32:28 roberto -% added warning off/on around text reading and conversion -% -% Revision 1.2 2003/04/17 12:38:08 roberto -% *** empty log message *** -% -% Revision 1.1 2003/03/24 12:30:42 roberto -% new implementation -% - -fid = fopen(filename, 'r'); -if fid==-1 - error(sprintf('could not open file %s', filename)); -end - -line = ''; -while ischar(line) - line = cleanline(fgetl(fid)); - if isempty(line) || (length(line)==1 && all(line==-1)) - continue - end - - % the line is not empty, which means that we have encountered a chunck of information - subline = cleanline(fgetl(fid)); % read the { - subline = cleanline(fgetl(fid)); % read the first item - while isempty(findstr(subline, '}')) - if ~isempty(subline) - [item, value] = strtok(subline, ':'); - value(1) = ' '; % remove the : - value = strtrim(value); - item = strtrim(item); - warning off - - % the item name should be a real string, otherwise I cannot put it into the structure - if strcmp(sprintf('%d', str2num(deblank(item))), deblank(item)) - % add something to the start of the string to distinguish it from a number - item = ['item_' item]; - end - - % the value can be either a number or a string, and is put into the structure accordingly - if isempty(str2num(value)) - % the value appears to be a string - eval(sprintf('file.%s.%s = [ ''%s'' ];', line, item, value)); - else - % the value appears to be a number or a list of numbers - eval(sprintf('file.%s.%s = [ %s ];', line, item, value)); - end - warning on - end - subline = cleanline(fgetl(fid)); % read the first item - end -end - -fclose(fid); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function line = cleanline(line) - if isempty(line) || (length(line)==1 && all(line==-1)) - return - end - comment = findstr(line, '//'); - if ~isempty(comment) - line(min(comment):end) = ' '; - end - line = strtrim(line); - diff --git a/external/fileio/private/read_ctf_cls.m b/external/fileio/private/read_ctf_cls.m deleted file mode 100644 index a4e5bfd..0000000 --- a/external/fileio/private/read_ctf_cls.m +++ /dev/null @@ -1,74 +0,0 @@ -function [condNumbers,condLabels] = read_ctf_cls(fname) - -% READ_CTF_CLS reads the classification file from a CTF dataset - -% Copyright (C) 2003, Ole Jensen -% -% $Log: read_ctf_cls.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.2 2006/04/20 12:07:31 roboos -% fixed bug when a class had no trials associated to it, changed output format for condNumbers from cell-array with cells into a cell-array with numeric arrays -% -% Revision 1.1 2004/09/27 15:34:30 roboos -% copy from the readClassFile that Ole wrote -% added help comments and cleaned up white space -% no code changes -% - -condNumbers = []; -% condLabels = []; - -fid = fopen(fname,'r'); - -if fid == -1 - condNumbers = []; - condLabels = []; - return -end - -nCondition = 0; -readBad = 0; -readList = 0; -S2 = '*'; -S1 = '*'; -while ~isempty(S1) - S3 = S2; - S2 = S1; - S1 =fscanf(fid,'%s',1); - - if readList - if ~isempty(S1) & ~isempty(str2num(S1(2:end))) - k = k + 1; - condTmp = [condTmp 1+str2num(S1(2:end))]; - else - readList = 0; - end - condNumbers{nCondition} = condTmp; - end - - if strcmp(S2,'NAME:') - % New condition found! - % fprintf('%s\n',S1); - nCondition = nCondition+1; - condLabels(nCondition) = {S1} ; - end - - if strcmp(S1,'NUMBER') & strcmp(S2,'TRIAL') - if ~isempty(S1) - readList = 1; - k = 0; - condTmp = []; - else - readList = 0; - end - end - -end % ~isempty(S1) - diff --git a/external/fileio/private/read_ctf_hdm.m b/external/fileio/private/read_ctf_hdm.m deleted file mode 100644 index 58d705c..0000000 --- a/external/fileio/private/read_ctf_hdm.m +++ /dev/null @@ -1,66 +0,0 @@ -function [vol] = read_ctf_hdm(filename); - -% READ_CTF_HDM reads the head volume conductor model from a *.hdm file -% -% vol = read_ctf_hdm(filename) - -% Copyright (C) 2003, Robert Oostenveld -% -% $Log: read_ctf_hdm.m,v $ -% Revision 1.2 2009/03/26 15:00:38 roboos -% remember all original details, required for 3rd gradient multisphere models -% -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.3 2006/02/09 08:37:23 roboos -% remove the fields SEARCH_RADIUS and HEADSHAPE_FILE regardless of where they are, do not assume that they are at location 1 and 2 (thanks to Tom) -% -% Revision 1.2 2004/06/28 07:32:55 roberto -% added units=cm for the volume model -% -% Revision 1.1 2003/03/24 12:30:42 roberto -% new implementation -% - -vol = []; -ascii = read_ctf_ascii(filename); - -% remember all original details -vol.orig = ascii; - -if isfield(ascii, 'MultiSphere_Data') - chans = fieldnames(ascii.MultiSphere_Data); - % remove the fields SEARCH_RADIUS and HEADSHAPE_FILE - chans = chans(~(strcmp(chans, 'SEARCH_RADIUS') | strcmp(chans, 'HEADSHAPE_FILE'))); - for i=1:length(chans) - tmp = getfield(ascii.MultiSphere_Data, chans{i}); - vol.label{i} = chans{i}; - vol.r(i) = tmp(4); - vol.o(i, :) = tmp(1:3); - end - vol.r = vol.r(:); % ensure column vector -elseif isfield(ascii, 'MEG_Sphere') - vol.r = ascii.MEG_Sphere.RADIUS; - vol.o(1) = ascii.MEG_Sphere.ORIGIN_X; - vol.o(2) = ascii.MEG_Sphere.ORIGIN_Y; - vol.o(3) = ascii.MEG_Sphere.ORIGIN_Z; -else - error('no headmodel information found'); -end - -% add the fiducials, these are in raw MRI coordinates -if isfield(ascii, 'Fid_Points') - vol.mri.nas = ascii.Fid_Points.NASION; - vol.mri.lpa = ascii.Fid_Points.LEFT_EAR; - vol.mri.rpa = ascii.Fid_Points.RIGHT_EAR; -end - -% add the units in which the volume conductor is defined -vol.unit = 'cm'; - diff --git a/external/fileio/private/read_ctf_meg4.m b/external/fileio/private/read_ctf_meg4.m deleted file mode 100644 index a2d6e2d..0000000 --- a/external/fileio/private/read_ctf_meg4.m +++ /dev/null @@ -1,192 +0,0 @@ -function [meg] = read_ctf_meg4(fname, hdr, begsample, endsample, chanindx) - -% READ_CTF_MEG4 reads specified samples from a CTF continous datafile -% It neglects all trial boundaries as if the data was acquired in -% non-continous mode. -% -% Use as -% [meg] = read_ctf_meg4(filename, hdr, begsample, endsample, chanindx) -% where -% filename name of the datafile, including the .meg4 extension -% header with all data information (from read_ctf_meg4) -% begsample index of the first sample to read -% endsample index of the last sample to read -% chanindx index of channels to read (optional, default is all) -% -% See also READ_CTF_MEG4 - -% "VSM MedTech Ltd. authorizes the release into public domain under the -% GPL licence of the Matlab source code files "read_ctf_res4.m" and -% "read_ctf_meg4.m" by the authors of said files from the F.C. Donders -% Centre, Nijmegen, The Netherlands." - -% Author(s): Jim McKay November 1999 -% Last revision: Jim McKay -% Copyright (c) 1999-2000 CTF Systems Inc. All Rights Reserved. -% -% modifications Copyright (C) 2002, Ole Jensen -% modifications Copyright (C) 2003, Robert Oostenveld -% -% $Log: read_ctf_meg4.m,v $ -% Revision 1.2 2009/05/07 13:25:16 roboos -% added support for old 64-channel CTF files -% -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.16 2008/09/30 07:47:04 roboos -% replaced all occurences of setstr() with char(), because setstr is deprecated by Matlab -% -% Revision 1.15 2007/09/11 12:18:23 jansch -% new clean implementation to account for very big datasets > 4GB -% -% Revision 1.14 2005/10/04 15:52:09 roboos -% fixed bug that occured when data is split over more than two files (thanks to flodlan) -% -% Revision 1.13 2005/02/18 13:16:58 roboos -% VSM MedTech Ltd. authorised the release of this code in the public domain -% updated the copyrights, updated the help -% -% Revision 1.12 2004/06/21 19:33:08 roberto -% made 2GB warning dependent on global fb flag -% -% Revision 1.11 2003/07/23 15:02:27 roberto -% added check on valid input for read_ctf_meg4, other changes unknown -% -% Revision 1.10 2003/05/22 09:09:41 roberto -% fixed another bug for >2GB files when selected data in within one trial -% -% Revision 1.7 2003/05/21 13:52:29 roberto -% re-implemented support for >2GB files -% improved checking of input arguments -% fixed bug in chanindx indexing for raw data -% -% Revision 1.6 2003/05/19 15:18:50 roberto -% fixed bugs in memory-efficient reading of continuous data -% -% Revision 1.4 2003/04/17 12:37:41 roberto -% changed error for non-continuous files into warning -% -% Revision 1.3 2003/04/01 06:53:35 roberto -% added support for channel selection -% fixed bug with data allocation over multiple trials -% -% Revision 1.2 2003/03/27 08:30:54 roberto -% fixed bug in reading non-multiplexed trial data -% added error checking -% -% Revision 1.1 2003/03/26 13:34:05 roberto -% new implementation -% - -% use global flag for feedback -global fb -if isempty(fb) - fb = 0; -end - -nsmp = hdr.nSamples; -ntrl = hdr.nTrials; -nchn = hdr.nChans; - -if begsample<1, error('cannot read before the start of the data'); end -if endsample>nsmp*ntrl*nchn, error('cannot read beyond the end of the data'); end -if begsample>endsample, error('cannot read a negative number of samples'); end -if nargin<5, chanindx = 1:nchn; end -if isempty(chanindx), error('no channels were specified for reading CTF data'); end - -%open the .meg4 file -fid = fopen(fname,'r','ieee-be'); -if fid == -1, - error('could not open datafile'); -end - -%check whether it is a known format -CTFformat=char(fread(fid, 8, 'uint8'))'; -% This function was written for MEG41RS, but also seems to work for some other formats -if ~strcmp(CTFformat(1,1:7),'MEG41CP') && ~strcmp(CTFformat(1,1:7),'MEG4CPT') - warning('meg4 format (%s) is not supported for file %s, trying anyway...', CTFformat(1,1:7), fname); -end - -%determine size of .meg4 file -fseek(fid, 0, 'eof'); -nbytes = ftell(fid); - -%number of trials per 2GB file FIXME assumes constancy across the .meg4 files -ntrlfile = round((nbytes-8)/(4*nchn*nsmp)); -%ntrlfile = (nbytes-8)/(4*nchn*nsmp); -openfile = 0; - -%determine which trials have to be read -begtrial = ceil(begsample/nsmp); -endtrial = ceil(endsample/nsmp); -trials = begtrial:endtrial; - -%to ensure correct sample handling in the case of multiple trials -sumsmp = [(begtrial-1):(endtrial-1)]*nsmp; -rawbeg = 1; - -minchn = min(chanindx); %to ensure correct channel handling in the case of blockwise reading -maxchn = max(chanindx); -loopchn = length(trials)==1 || (maxchn-minchn+1)<=nchn; %decide whether to read in blockwise, or the specified samples per channel - -raw = zeros(endsample-begsample+1, length(chanindx)); %allocate memory -for trllop = 1:length(trials) - trlnr = trials(trllop); - filenr = floor(trlnr/(ntrlfile+0.1)); - - %ensure that the correct .meg4 file is open - if filenr~=openfile && filenr>0, - fclose(fid); - nextname = sprintf('%s.%d_meg4', fname(1:(end-5)), filenr); - if fb - fprintf('data goes beyond 2GB file boundary, continuing with %s\n', nextname); - end - fid = fopen(nextname,'r','ieee-be'); - fseek(fid, 0, 'eof'); - openfile = filenr; - end - - %this is relative to the current datafile - rawtrl = mod(trlnr-1, ntrlfile) + 1; - offset = 8 + 4*(rawtrl-1)*nsmp*nchn; - - %begin and endsamples expressed as samples with respect to the current trial - tmpbeg = max(begsample-sumsmp(trllop), 1); - tmpend = min(endsample-sumsmp(trllop), nsmp); - rawend = rawbeg+tmpend-tmpbeg; - - %either read per channel or read entire trialblock and postselect the channels - if loopchn, - for chnlop = 1:length(chanindx) - %this is relative to the current trial - chanoffset = 4*(chanindx(chnlop)-1)*nsmp; - sampoffset = 4*(tmpbeg-1); - fseek(fid, offset+chanoffset+sampoffset, 'bof'); - [tmp, count] = fread(fid,[tmpend-tmpbeg+1,1],'int32'); - raw(rawbeg:rawend, chnlop) = tmp; - end - else - %this is relative to the current trial - chanoffset = 4*(minchn-1)*nsmp; - fseek(fid, offset+chanoffset, 'bof'); - ntmpchn = maxchn - minchn + 1; - [tmp, count] = fread(fid,[nsmp,length(ntmpchn)],'int32'); - selchn = chanindx - minchn + 1; %relative to the first channel to be read - raw(rawbeg:rawend, :) = tmp(tmpbeg:tmpend, selchn); - end - rawbeg = rawend+1; -end -fclose(fid); - -% multiply the dimensionless values with the calibration value -gain = hdr.gainV(chanindx); % only for selected channels -meg = raw'; % transpose the raw data -for i=1:size(meg,1) - meg(i,:) = gain(i)*meg(i,:); -end diff --git a/external/fileio/private/read_ctf_mri.m b/external/fileio/private/read_ctf_mri.m deleted file mode 100644 index 5b3f1c0..0000000 --- a/external/fileio/private/read_ctf_mri.m +++ /dev/null @@ -1,149 +0,0 @@ -function [mri, hdr] = read_ctf_mri(filename); - -% READ_CTF_MRI reads header and imnage data from CTF format MRI file -% -% [mri, hdr] = read_ctf_mri(filename) -% -% See also READ_CTF_MEG4, READ_CTF_RES4 - -% Copyright (C) 2003 Robert Oostenveld -% -% $Log: read_ctf_mri.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry -% -% Revision 1.4 2008/09/30 07:47:04 roboos -% replaced all occurences of setstr() with char(), because setstr is deprecated by Matlab -% -% Revision 1.3 2005/08/26 13:49:03 roboos -% changed warp3d into warp_apply -% -% Revision 1.2 2003/07/23 15:02:27 roberto -% added check on valid input for read_ctf_meg4, other changes unknown -% -% Revision 1.1 2003/06/10 08:14:54 roberto -% new implementation -% - -fid = fopen(filename,'rb', 'ieee-be'); - -if fid<=0 - error(sprintf('could not open MRI file: %s\n', filename)); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% READ THE IMAGE HEADER -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -warning off -% general header information -hdr.identifierString = char(fread(fid,32,'char'))'; % CTF_MRI_FORMAT VER 2.2 -hdr.imageSize = fread(fid,1,'int16'); % always = 256 -hdr.dataSize = fread(fid,1,'int16'); % 1 or 2(bytes) -hdr.clippingRange = fread(fid,1,'int16'); % max.integer value of data -hdr.imageOrientation = fread(fid,1,'int16'); % eg., 0 = left on left, 1 = left on right -hdr.mmPerPixel_sagittal = fread(fid,1,'float'); % voxel dimensions in mm -hdr.mmPerPixel_coronal = fread(fid,1,'float'); % voxel dimensions in mm -hdr.mmPerPixel_axial = fread(fid,1,'float'); % voxel dimensions in mm - -% HeadModel_Info specific header items -hdr.HeadModel.Nasion_Sag = fread(fid,1,'int16'); % fid.point coordinate(in voxels) for nasion - sagittal -hdr.HeadModel.Nasion_Cor = fread(fid,1,'int16'); % nasion - coronal -hdr.HeadModel.Nasion_Axi = fread(fid,1,'int16'); % nasion - axial -hdr.HeadModel.LeftEar_Sag = fread(fid,1,'int16'); % left ear - sagittal -hdr.HeadModel.LeftEar_Cor = fread(fid,1,'int16'); % left ear - coronal -hdr.HeadModel.LeftEar_Axi = fread(fid,1,'int16'); % left ear - axial -hdr.HeadModel.RightEar_Sag = fread(fid,1,'int16'); % right ear - sagittal -hdr.HeadModel.RightEar_Cor = fread(fid,1,'int16'); % right ear - coronal -hdr.HeadModel.RightEar_Axi = fread(fid,1,'int16'); % right ear - axial -fread(fid,2,'char'); % padding to 4 byte boundary -hdr.HeadModel.defaultSphereX = fread(fid,1,'float'); % sphere origin x coordinate(in mm) -hdr.HeadModel.defaultSphereY = fread(fid,1,'float'); % sphere origin y coordinate(in mm) -hdr.HeadModel.defaultSphereZ = fread(fid,1,'float'); % sphere origin z coordinate(in mm) -hdr.HeadModel.defaultSphereRadius = fread(fid,1,'float'); % default sphere radius(in mm) - -% Image_Info specific header items -hdr.Image.modality = fread(fid,1,'int16'); % 0 = MRI, 1 = CT, 2 = PET, 3 = SPECT, 4 = OTHER -hdr.Image.manufacturerName = char(fread(fid,64,'char'))'; -hdr.Image.instituteName = char(fread(fid,64,'char'))'; -hdr.Image.patientID = char(fread(fid,32,'char'))'; -hdr.Image.dateAndTime = char(fread(fid,32,'char'))'; -hdr.Image.scanType = char(fread(fid,32,'char'))'; -hdr.Image.contrastAgent = char(fread(fid,32,'char'))'; -hdr.Image.imagedNucleus = char(fread(fid,32,'char'))'; -fread(fid,2,'char'); % padding to 4 byte boundary -hdr.Image.Frequency = fread(fid,1,'float'); -hdr.Image.FieldStrength = fread(fid,1,'float'); -hdr.Image.EchoTime = fread(fid,1,'float'); -hdr.Image.RepetitionTime = fread(fid,1,'float'); -hdr.Image.InversionTime = fread(fid,1,'float'); -hdr.Image.FlipAngle = fread(fid,1,'float'); -hdr.Image.NoExcitations = fread(fid,1,'int16'); -hdr.Image.NoAcquisitions = fread(fid,1,'int16'); -hdr.Image.commentString = char(fread(fid,256,'char'))'; -hdr.Image.forFutureUse = char(fread(fid,64,'char'))'; - -% continuation general header -hdr.headOrigin_sagittal = fread(fid,1,'float'); % voxel location of head origin -hdr.headOrigin_coronal = fread(fid,1,'float'); % voxel location of head origin -hdr.headOrigin_axial = fread(fid,1,'float'); % voxel location of head origin -% euler angles to align MR to head coordinate system(angles in degrees !) -hdr.rotate_coronal = fread(fid,1,'float'); % 1. rotate in coronal plane by this angle -hdr.rotate_sagittal = fread(fid,1,'float'); % 2. rotate in sagittal plane by this angle -hdr.rotate_axial = fread(fid,1,'float'); % 3. rotate in axial plane by this angle -hdr.orthogonalFlag = fread(fid,1,'int16'); % if set then image is orthogonal -hdr.interpolatedFlag = fread(fid,1,'int16'); % if set than image was interpolated -hdr.originalSliceThickness = fread(fid,1,'float'); % original spacing between slices before interpolation -transformMatrix = fread(fid,[4 4],'float')'; % transformation matrix head->MRI[column][row] -fread(fid,204,'char'); % unused, padding to 1028 bytes -warning on - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% READ THE IMAGE DATA -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -if hdr.dataSize==1 - mri = uint8(fread(fid, 256*256*256, 'uint8')); -elseif hdr.dataSize==2 - mri = uint16(fread(fid, 256*256*256, 'uint16')); -else - error('unknown datasize in CTF mri file'); -end -mri = reshape(mri, [256 256 256]); -fclose(fid); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% DO POST-PROCESSING -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% reorient the image data to obtain corresponding image data and transformation matrix -mri = permute(mri, [3 1 2]); % this was determined by trial and error - -% reorient the image data and the transformation matrix along the left-right direction -% remember that the fiducials in voxel coordinates also have to be flipped (see down) -mri = flipdim(mri, 1); -flip = [-1 0 0 256 - 0 1 0 0 - 0 0 1 0 - 0 0 0 1 ]; -transformMatrix = flip*transformMatrix; - -% re-compute the homogeneous transformation matrices (apply voxel scaling) -scale = eye(4); -scale(1,1) = hdr.mmPerPixel_sagittal; -scale(2,2) = hdr.mmPerPixel_coronal; -scale(3,3) = hdr.mmPerPixel_axial; -hdr.transformHead2MRI = transformMatrix*inv(scale); -hdr.transformMRI2Head = scale*inv(transformMatrix); - -% determint location of fiducials in MRI voxel coordinates -% flip the fiducials in voxel coordinates to correspond to the previous flip along left-right -hdr.fiducial.mri.nas = [256 - hdr.HeadModel.Nasion_Sag hdr.HeadModel.Nasion_Cor hdr.HeadModel.Nasion_Axi]; -hdr.fiducial.mri.lpa = [256 - hdr.HeadModel.LeftEar_Sag hdr.HeadModel.LeftEar_Cor hdr.HeadModel.LeftEar_Axi]; -hdr.fiducial.mri.rpa = [256 - hdr.HeadModel.RightEar_Sag hdr.HeadModel.RightEar_Cor hdr.HeadModel.RightEar_Axi]; - -% compute location of fiducials in MRI and HEAD coordinates -hdr.fiducial.head.nas = warp_apply(hdr.transformMRI2Head, hdr.fiducial.mri.nas, 'homogenous'); -hdr.fiducial.head.lpa = warp_apply(hdr.transformMRI2Head, hdr.fiducial.mri.lpa, 'homogenous'); -hdr.fiducial.head.rpa = warp_apply(hdr.transformMRI2Head, hdr.fiducial.mri.rpa, 'homogenous'); - diff --git a/external/fileio/private/read_ctf_mri4.m b/external/fileio/private/read_ctf_mri4.m deleted file mode 100644 index ad42567..0000000 --- a/external/fileio/private/read_ctf_mri4.m +++ /dev/null @@ -1,252 +0,0 @@ -function [mri, hdr, cpersist] = read_ctf_mri4(filename); - -% READ_CTF_MRI reads header and imnage data from CTF format MRI file -% -% [mri, hdr] = read_ctf_mri(filename) -% -% See also READ_CTF_MEG4, READ_CTF_RES4 - -% Copyright (C) 2008 Ivar Clemens -% -% $Log: read_ctf_mri4.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry -% -% Revision 1.1 2008/11/28 10:25:05 roboos -% new implementation by Ivar, based on the version 2 reader -% -% Revision 1.1 2008/11/21 13:00:42 ivacle -% Adapted read_ctf_mri to read the 'new' CTF MRI format -% - -fid = fopen(filename,'rb', 'ieee-be'); - -if fid<=0 - error(sprintf('could not open MRI file: %s\n', filename)); -end - -[cpersist] = read_cpersist(fid); - -warning off - -% general header information -hdr.identifierString = get_value(cpersist, '_CTFMRI_VERSION'); % CTF_MRI_FORMAT VER 4.1 -hdr.imageSize = get_value(cpersist, '_CTFMRI_SIZE'); % 256 -hdr.dataSize = get_value(cpersist, '_CTFMRI_DATASIZE'); % 1 or 2(bytes) -hdr.orthogonalFlag = get_value(cpersist, '_CTFMRI_ORTHOGONALFLAG'); % if set then image is orthogonal -hdr.interpolatedFlag = get_value(cpersist, '_CTFMRI_INTERPOLATEDFLAG'); % if set than image was interpolated -hdr.comment = get_value(cpersist, '_CTFMRI_COMMENT'); - -hdr.Image.modality = get_value(cpersist, '_SERIES_MODALITY'); -hdr.Image.manufacturerName = get_value(cpersist, '_EQUIP_MANUFACTURER'); -hdr.Image.instituteName = get_value(cpersist, '_EQUIP_INSTITUTION'); -hdr.Image.imagedNucleus = get_value(cpersist, '_MRIMAGE_IMAGEDNUCLEUS'); -hdr.Image.FieldStrength = get_value(cpersist, '_MRIMAGE_FIELDSTRENGTH'); -hdr.Image.EchoTime = get_value(cpersist, '_MRIMAGE_ECHOTIME'); -hdr.Image.RepetitionTime = get_value(cpersist, '_MRIMAGE_REPETITIONTIME'); -hdr.Image.InversionTime = get_value(cpersist, '_MRIMAGE_INVERSIONTIME'); -hdr.Image.FlipAngle = get_value(cpersist, '_MRIMAGE_FLIPANGLE'); - -% euler angles to align MR to head coordinate system(angles in degrees !) -rotation = split_nvalue(get_value(cpersist, '_CTFMRI_ROTATE')); -hdr.rotate_coronal = rotation(1); -hdr.rotate_sagittal = rotation(2); -hdr.rotate_axial = rotation(3); - -transformMatrix = split_nvalue(get_value(cpersist, '_CTFMRI_TRANSFORMMATRIX')); -transformMatrix = reshape(transformMatrix, 4, 4)'; - -mmPerPixel = split_nvalue(get_value(cpersist, '_CTFMRI_MMPERPIXEL')); -hdr.mmPerPixel_sagittal = mmPerPixel(1); -hdr.mmPerPixel_coronal = mmPerPixel(2); -hdr.mmPerPixel_axial = mmPerPixel(3); - -% HeadModel_Info specific header items -hmNasion = split_nvalue(get_value(cpersist, '_HDM_NASION')); -hdr.HeadModel.Nasion_Sag = hmNasion(1); -hdr.HeadModel.Nasion_Cor = hmNasion(2); -hdr.HeadModel.Nasion_Axi = hmNasion(3); - -hmLeftEar = split_nvalue(get_value(cpersist, '_HDM_LEFTEAR')); -hdr.HeadModel.LeftEar_Sag = hmLeftEar(1); -hdr.HeadModel.LeftEar_Cor = hmLeftEar(2); -hdr.HeadModel.LeftEar_Axi = hmLeftEar(3); - -hmRightEar = split_nvalue(get_value(cpersist, '_HDM_RIGHTEAR')); -hdr.HeadModel.RightEar_Sag = hmRightEar(1); -hdr.HeadModel.RightEar_Cor = hmRightEar(2); -hdr.HeadModel.RightEar_Axi = hmRightEar(3); - -hmSphere = split_nvalue(get_value(cpersist, '_HDM_DEFAULTSPHERE')); -hdr.HeadModel.defaultSphereX = hmSphere(1); -hdr.HeadModel.defaultSphereY = hmSphere(2); -hdr.HeadModel.defaultSphereZ = hmSphere(3); -hdr.HeadModel.defaultSphereRadius = hmSphere(4); - -hmOrigin = split_nvalue(get_value(cpersist, '_HDM_HEADORIGIN')); -hdr.headOrigin_sagittal = hmOrigin(1); -hdr.headOrigin_coronal = hmOrigin(2); -hdr.headOrigin_axial = hmOrigin(3); - -%fread(fid,204,'char'); % unused, padding to 1028 bytes -warning on - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% READ THE IMAGE DATA -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -mri = zeros(256, 256, 256); - -for slice = 1:256 - name = sprintf('_CTFMRI_SLICE_DATA#%.5d', slice); - offset = get_value(cpersist, name); - - fseek(fid, offset, 'bof'); - - if(hdr.dataSize == 1) - slicedata = uint8(fread(fid, [256 256], 'uint8')); - elseif(hdr.dataSize == 2) - slicedata = uint16(fread(fid, [256 256], 'uint16')); - else - error('Unknown datasize in CTF MRI file'); - end; - - mri(:, :, slice) = slicedata; -end; - -%mri = reshape(mri, [256 256 256]); -fclose(fid); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% DO POST-PROCESSING -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% reorient the image data to obtain corresponding image data and transformation matrix -mri = permute(mri, [3 1 2]); % this was determined by trial and error - -% reorient the image data and the transformation matrix along the left-right direction -% remember that the fiducials in voxel coordinates also have to be flipped (see down) -mri = flipdim(mri, 1); -flip = [-1 0 0 256 - 0 1 0 0 - 0 0 1 0 - 0 0 0 1 ]; -transformMatrix = flip*transformMatrix; - -% re-compute the homogeneous transformation matrices (apply voxel scaling) -scale = eye(4); -scale(1,1) = hdr.mmPerPixel_sagittal; -scale(2,2) = hdr.mmPerPixel_coronal; -scale(3,3) = hdr.mmPerPixel_axial; -hdr.transformHead2MRI = transformMatrix*inv(scale); -hdr.transformMRI2Head = scale*inv(transformMatrix); - -% determint location of fiducials in MRI voxel coordinates -% flip the fiducials in voxel coordinates to correspond to the previous flip along left-right -hdr.fiducial.mri.nas = [256 - hdr.HeadModel.Nasion_Sag hdr.HeadModel.Nasion_Cor hdr.HeadModel.Nasion_Axi]; -hdr.fiducial.mri.lpa = [256 - hdr.HeadModel.LeftEar_Sag hdr.HeadModel.LeftEar_Cor hdr.HeadModel.LeftEar_Axi]; -hdr.fiducial.mri.rpa = [256 - hdr.HeadModel.RightEar_Sag hdr.HeadModel.RightEar_Cor hdr.HeadModel.RightEar_Axi]; - -% compute location of fiducials in MRI and HEAD coordinates -hdr.fiducial.head.nas = warp_apply(hdr.transformMRI2Head, hdr.fiducial.mri.nas, 'homogenous'); -hdr.fiducial.head.lpa = warp_apply(hdr.transformMRI2Head, hdr.fiducial.mri.lpa, 'homogenous'); -hdr.fiducial.head.rpa = warp_apply(hdr.transformMRI2Head, hdr.fiducial.mri.rpa, 'homogenous'); - -% -% Reads a series of delimited numbers from a string -% -% @param input string Delimited string to process -% @param delim string The delimiter (default: \\) -% -% @return values matrix Array containing the numbers found -% - function [values] = split_nvalue(input, delim) - if(nargin < 2), delim = '\\'; end; - - remain = input; - values = []; - - while(numel(remain > 0)) - [value, remain] = strtok(remain, delim); - values(end + 1) = str2num(value); - end; - end - -% -% Reads a value from the CPersist structure -% -% @param cpersist struct-array The CPersist structure -% @param key string The name of the parameter -% -% @return value mixed The value of the named parameter -% - function [value] = get_value(cpersist, key) - idx = find(strcmp({cpersist.key}, key)); - - if(numel(idx) < 1), error('Specified key does not exist.'); end; - if(numel(idx) > 1), error('Specified key is not unique.'); end; - - value = cpersist(idx).value; - end - -% -% Processes the CTF CPersist structure into a struct-array -% -% @param fid numeric File handle from which to read the CPersist structure -% @return cpersist struct-array -% - function [cpersist] = read_cpersist(fid) - magic = char(fread(fid, 4, 'char'))'; - - if(~strcmp(magic, 'WS1_')), error('Invalid CPersist header'); end; - - cpersist = struct('key', {}, 'value', {}); - - while(~feof(fid)) - % Read label - lsize = fread(fid, 1, 'int32'); - ltext = char(fread(fid, lsize, 'char'))'; - - % Last label in file is always EndOfParameters - if(strcmp(ltext, 'EndOfParameters')), return; end; - - % Read value - vtype = fread(fid, 1, 'int32'); - value = read_cpersist_value(fid, vtype); - - cpersist(end + 1).key = ltext; - cpersist(end).value = value; - end - end - -% -% Reads a single value of type (vtype) from fid -% -% @param fid numeric The file to read the value from -% @param vtype numeric The type of value to read -% -% @return value mixed The read value -% - function [value] = read_cpersist_value(fid, vtype) - switch vtype - case 3 - vsize = fread(fid, 1, 'int32'); - value = ftell(fid); - fseek(fid, vsize, 'cof'); - case 4 - value = fread(fid, 1, 'double'); - case 5 - value = fread(fid, 1, 'int32'); - case 6 - value = fread(fid, 1, 'int16'); - case 10 - vsize = fread(fid, 1, 'int32'); - value = char(fread(fid, vsize, 'char'))'; - otherwise - error(['Unsupported valuetype (' num2str(vtype) ') found in CPersist object']); - return - end - end - -end - diff --git a/external/fileio/private/read_ctf_res4.m b/external/fileio/private/read_ctf_res4.m deleted file mode 100644 index de4f07c..0000000 --- a/external/fileio/private/read_ctf_res4.m +++ /dev/null @@ -1,252 +0,0 @@ -function [hdr] = read_ctf_res4(fname) - -% READ_CTF_RES4 reads the header in RES4 format from a CTF dataset -% -% Use as -% [hdr] = read_ctf_res4(filename) -% -% See also READ_CTF_MEG4 - -% "VSM MedTech Ltd. authorizes the release into public domain under the -% GPL licence of the Matlab source code files "read_ctf_res4.m" and -% "read_ctf_meg4.m" by the authors of said files from the F.C. Donders -% Centre, Nijmegen, The Netherlands." - -% Author(s): Jim McKay November 1999 -% Last revision: Jim McKay -% Copyright (c) 1999-2000 CTF Systems Inc. All Rights Reserved. -% -% modifications Copyright (C) 2002, Ole Jensen -% modifications Copyright (C) 2003, Robert Oostenveld -% -% $Log: read_ctf_res4.m,v $ -% Revision 1.2 2009/05/07 13:25:16 roboos -% added support for old 64-channel CTF files -% -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.17 2008/09/30 07:47:04 roboos -% replaced all occurences of setstr() with char(), because setstr is deprecated by Matlab -% -% Revision 1.16 2008/07/24 08:51:43 roboos -% added the function declaration to the top, which was accidentaly removed by the previous commit -% -% Revision 1.15 2008/07/24 07:22:49 roboos -% replaced fread..char with uint8, solves problem with 16 bit wide characters (thanks to Erick Ortiz) -% -% Revision 1.14 2007/03/07 08:58:46 roboos -% Do not determine the MEG, REF and EEG channels based on the first character of the channel label, removed rowMEG etc from the header. The relevant information is contained in hdr.sensType. -% -% Revision 1.13 2006/03/06 09:41:23 roboos -% changed some |s into ||s -% -% Revision 1.12 2005/07/28 15:12:27 roboos -% fixed bug in hdr.timeVec (thanks to Sanja Kovacevic) -% -% Revision 1.11 2005/05/26 09:58:08 roboos -% removed the construction of grad, that is now done in a separate fieldtrip function (ctf2grad) -% -% Revision 1.10 2005/05/24 07:34:37 roboos -% added sensType to the output header -% -% Revision 1.9 2005/05/23 11:20:17 roboos -% fixed bug for run description which is longer than 256 characters, improved reading of filter information (thanks to Durk Talsma) -% -% Revision 1.8 2005/04/27 06:18:21 roboos -% added support for MEG42RS format, which seems to work (only tested on a single dataset from MIND Institute in Albuquerque, NM, USA) -% -% Revision 1.7 2005/02/18 13:16:58 roboos -% VSM MedTech Ltd. authorised the release of this code in the public domain -% updated the copyrights, updated the help -% -% Revision 1.6 2004/07/02 11:43:32 roboos -% typographic change in comment -% -% Revision 1.5 2004/06/28 07:34:41 roberto -% added some extra low-level output fields to header, added cm units -% -% Revision 1.4 2003/04/01 07:51:53 roberto -% fixed bug in gradiometer channel labels -% -% Revision 1.3 2003/03/28 17:27:27 roberto -% renamed output gradiometer from gradHC to grad -% -% Revision 1.2 2003/03/24 12:34:33 roberto -% minor changes -% -% Revision 1.1 2003/03/13 14:27:09 roberto -% separated read_ctf_ds into res4-header part and data part -% restructured the res4 part, using (incorrect) CTF documentation -% - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% read header information -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -fid = fopen(fname,'r','ieee-be'); - -% Check if header file exist -if fid == -1 - errMsg = strcat('Could not open header file:',fname); - error(errMsg); -end - -% First 8 bytes contain filetype, check is fileformat is correct. -% This function was written for MEG41RS, but also seems to work for some other formats -CTFformat=char(fread(fid,8,'uint8'))'; -if ~strcmp(CTFformat(1,1:7),'MEG41RS') && ~strcmp(CTFformat(1,1:7),'MEG42RS') && ~strcmp(CTFformat(1,1:7),'MEG3RES') - warning('res4 format (%s) is not supported for file %s, trying anyway...', CTFformat(1,1:7), fname); -end - -% Read the initial parameters -appName = char(fread(fid,256,'uint8'))' ; -dataOrigin = char(fread(fid,256,'uint8'))' ; -dataDescrip = char(fread(fid,256,'uint8'))' ; -no_trial_avgd = fread(fid,1,'int16') ; -data_time = char(fread(fid,255,'uint8'))'; -data_date = char(fread(fid,255,'uint8'))'; - -fseek(fid,1288,'bof'); -% Read the general recording parameters -no_samples = fread(fid,1,'int32'); -no_channels = fread(fid,1,'int16'); -fseek(fid,2,'cof'); % hole of 2 bytes due to improper alignment -sample_rate = fread(fid,1,'double'); -epoch = fread(fid,1,'double'); -no_trials = fread(fid,1,'int16'); -fseek(fid,2,'cof'); % hole of 2 bytes due to improper alignment -preTrigpts=fread(fid,1,'int32'); - -fseek(fid,1360,'bof'); -% read in the meg4Filesetup structure -run_name = char(fread(fid,32,'uint8')'); -run_title = char(fread(fid,256,'uint8')'); -instruments = char(fread(fid,32,'uint8')'); -coll_desc = char(fread(fid,32,'uint8')'); -subj_id = char(fread(fid,32,'uint8')'); -operator = char(fread(fid,32,'uint8')') ; -sensFilename = char(fread(fid,60,'uint8')') ; - -% not nececssary to seek, the file pointer is already at the desired location -% fseek(fid,1836,'bof'); - -% Read in the run description length -rd_len=fread(fid,1,'uint32'); -% Go to the run description and read it in -fseek(fid,1844,'bof'); -run_desc=char(fread(fid,rd_len,'uint8')'); - -% read in the filter information -num_filt=fread(fid,1,'uint16'); -for fi=0:(num_filt-1), - %filt_info=fread(fid,18,'uint8'); - filt_freq =fread(fid,1, 'double'); - filt_class=fread(fid,1, 'uint32'); - filt_type =fread(fid,1, 'uint32'); - num_fparm=fread(fid, 1, 'uint16'); - %num_fparm=filt_info(18); - if num_fparm ~= 0, - filt_parm=fread(fid,8*num_fparm,'uint8'); - end % if -end % for fi - -% Read in the channel names -for i=1:no_channels, - temp=fread(fid,32,'uint8')'; - temp(find(temp<32 )) = ' '; % remove non-printable characters - temp(find(temp>126)) = ' '; % remove non-printable characters - endstr = findstr(temp, '-'); temp(endstr:end) = ' '; % cut off at '-' - endstr = findstr(temp, ' '); temp(endstr:end) = ' '; % cut off at ' ' - chan_name(i,:) = char(temp); % as char array - chan_label{i} = deblank(char(temp)); % as cell array -end %for - -% pre-allocate some memory space -sensGain = zeros([no_channels,1]); -qGain = zeros([no_channels,1]); -ioGain = zeros([no_channels,1]); -sensType = zeros([no_channels,1]); - -% Read in the sensor information -fp = ftell(fid); -for chan=1:no_channels, - fread(fid,1,'uint8'); % Read and ignore 1 byte from enum - sensType(chan)=fread(fid,1,'uint8'); % Read sensor type - fread(fid,2,'uint8'); % Read and ignore originalRunNum - fread(fid,4,'uint8'); % Read and ignore coilShape - sensGain(chan)=fread(fid,1,'double'); % Read sensor gain in Phi0/Tesla - qGain(chan)=fread(fid,1,'double'); % Read qxx gain (usually 2^20 for Q20) - ioGain(chan)=fread(fid,1,'double'); % Read i/o gain of special sensors (usually 1.0) - ioOffset(chan)=fread(fid,1,'double'); - numCoils(chan)=fread(fid,1,'int16'); - grad_order_no(chan)=fread(fid,1,'int16'); - fread(fid,4,'uint8'); - - % read the coil positions and orientations - for i=1:8 - Chan(chan).coil(i).pos = fread(fid,3,'double')'; - fread(fid,1,'double'); - Chan(chan).coil(i).ori = fread(fid,3,'double')'; - fread(fid,3,'double'); - end - - % read the coil positions and orientations in head coordinates(?) - for i=1:8 - Chan(chan).coilHC(i).pos = fread(fid,3,'double')'; - fread(fid,1,'double'); - Chan(chan).coilHC(i).ori = fread(fid,3,'double')'; - fread(fid,3,'double'); - end - - % jump to the next sensor info record - fseek(fid, fp+chan*1328, 'bof'); -end % for chan - -% close the header file -fclose(fid); - -% according to Tom Holroyd, the sensor types are -% -% meg channels are 5, refmag 0, refgrad 1, adcs 18. -% UPPT001 is 11 -% UTRG001 is 11 -% SCLK01 is 17 -% STIM is 11 -% SCLK01 is 17 -% EEG057 is 9 -% ADC06 is 18 -% ADC07 is 18 -% ADC16 is 18 -% V0 is 15 - -% assign all the variables that should be outputted as header information -hdr.Fs = sample_rate; -hdr.nChans = no_channels; -hdr.nSamples = no_samples; -hdr.nSamplesPre = preTrigpts; -hdr.timeVec = (1:no_samples)/sample_rate - preTrigpts/sample_rate - 1/sample_rate; -hdr.nTrials = no_trials; -hdr.gainV = ioGain./(qGain.*sensGain); -hdr.ioGain = ioGain; -hdr.qGain = qGain; -hdr.sensGain = sensGain; -hdr.sensType = sensType; - -hdr.label = chan_label(:); -hdr.nameALL = chan_name; -hdr.Chan = Chan; -% hdr.rowMEG = rowMEG; -% hdr.rowEEG = rowEEG; -% hdr.rowTRIG = rowTRIG; -% hdr.rowREF = rowREF; -% hdr.nameEEG = []; -% hdr.nameMEG = []; -% hdr.nameEOG = []; -% hdr.trigV = []; -% hdr.SwapData = []; diff --git a/external/fileio/private/read_ctf_shape.m b/external/fileio/private/read_ctf_shape.m deleted file mode 100644 index cf015c6..0000000 --- a/external/fileio/private/read_ctf_shape.m +++ /dev/null @@ -1,39 +0,0 @@ -function [shape] = read_ctf_shape(filename); - -% READ_CTF_SHAPE reads headshape points and header information -% from a CTF *.shape teh accompanying *.shape_info file. -% -% Use as -% [shape] = read_ctf_shape(filename) -% where filename should have the .shape extension - -% Copyright (C) 2003, Robert Oostenveld -% -% $Log: read_ctf_shape.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.2 2008/11/12 16:59:51 roboos -% open explicitely as text using fopen 'rt' -% -% Revision 1.1 2003/10/08 15:28:03 roberto -% *** empty log message *** -% - -shape = read_ctf_ascii([filename '_info']); - -if ~strcmp(shape.MRI_Info.COORDINATES, 'HEAD') - warning('points on head shape are NOT in headcoordinates') -end - -fid = fopen(filename, 'rt'); -num = fscanf(fid, '%d', 1); -shape.pnt = fscanf(fid, '%f', inf); -shape.pnt = reshape(shape.pnt, [3 num])'; -fclose(fid); - diff --git a/external/fileio/private/read_ctf_shm.m b/external/fileio/private/read_ctf_shm.m deleted file mode 100644 index 37c91d6..0000000 --- a/external/fileio/private/read_ctf_shm.m +++ /dev/null @@ -1,45 +0,0 @@ -function [varargout] = funname(varargin) - -% READ_CTF_SHM reads metainformation or selected blocks of data from -% shared memory. This function can be used for real-time processing of -% data while it is being acquired. -% -% Use as -% [msgType msgId sampleNumber numSamples numChannels] = read_ctf_shm; -% or -% [data] = read_ctf_shm(msgNumber); -% [data] = read_ctf_shm(msgNumber, numValues); -% -% See also WRITE_CTF_SHM - -% remember the original working directory -pwdir = pwd; - -% determine the name and full path of this function -funname = mfilename('fullpath'); -mexsrc = [funname '.c']; -[mexdir, mexname] = fileparts(funname); - -try - % try to compile the mex file on the fly - warning('trying to compile MEX file from %s', mexsrc); - cd(mexdir); - mex(mexsrc); - cd(pwdir); - success = true; - -catch - % compilation failed - disp(lasterr); - error('could not locate MEX file for %s', mexname); - cd(pwdir); - success = false; -end - -if success - % execute the mex file that was juist created - funname = mfilename; - funhandle = str2func(funname); - [varargout{1:nargout}] = funhandle(varargin{:}); -end - diff --git a/external/fileio/private/read_ctf_trigger.m b/external/fileio/private/read_ctf_trigger.m deleted file mode 100644 index f3925e2..0000000 --- a/external/fileio/private/read_ctf_trigger.m +++ /dev/null @@ -1,105 +0,0 @@ -function [backpanel, frontpanel] = read_ctf_trigger(dataset) - -% READ_CTF_TRIGGER reads the STIM channel from a dataset and detects -% the trigger moments and values -% -% [backpanel, frontpanel] = read_ctf_trigger(dataset) -% -% This returns all samples of the STIM channel, converted to backpanel -% and frontpanel trigger values. Triggers are placed at the rising flank -% of the STIM channel. -% -% Triggers should be at least 9 samples long (for 1200Hz samplerate) and -% should not overlap each other. -% -% See also READ_CTF_MEG4, READ_CTF_RES4 - -% Copyright (C) 2003, Robert Oostenveld -% -% $Log: read_ctf_trigger.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.8 2006/02/06 09:02:35 roboos -% added support for triggers in UPPT001, USPT001, UTRG001 (thanks to Tom) -% -% Revision 1.7 2004/03/12 11:21:19 roberto -% The function outputs backpanel and frontpanel seperately. However -% it performs the upflank/kernel-convolution-correction of the -% trigger-channel on the the full 32-bit data. Usually the frontpanel -% is used to record responses while the backpanel is used for recording -% stimulus-trigger. While the timecourse of backpanel-triggers can -% be fully controlled the temporal overlap of these triggers with -% subject-responses can not. Therefore I think read_ctf_trigger should -% do the correction on the splitted data as done in the attached -% version of the function. This version works as before for nonoverlapping -% cases but can also handle backpanel-frontpanel overlap. -% -% Revision 1.6 2004/02/18 13:55:39 roberto -% fixed most significant bit, which was messed up by reading the data as signed int -% -% Revision 1.5 2004/02/12 09:55:35 roberto -% fixed bug, length of trigger was trigshift samples too short -% -% Revision 1.4 2003/10/14 12:37:17 roberto -% made teh trigshift adaptive to sampling frequency -% -% Revision 1.3 2003/09/12 09:27:11 roberto -% added comment to help about how triggers are supposed to behave -% -% Revision 1.2 2003/05/21 10:59:52 roberto -% fixed bugs in front/backpanel -% -% Revision 1.1 2003/05/19 14:40:32 roberto -% new implementation, replaces inline code in framework/preprocessing -% - -[path, file, ext] = fileparts(dataset); -datafile = fullfile(dataset, [file '.meg4']); -headerfile = fullfile(dataset, [file '.res4']); - -% read the header from the raw CTF data -hdr = read_ctf_res4(headerfile); - -% number of samples to shift the assesment of the trigger value -% this is needed because it takes some time for the rising flank to get to the correct value -trigshift = fix(hdr.Fs * 9/1200); - -% read the stimulus channel from raw CTF data: with the new electronics -% control console used at NIH, there is now no longer any channel -% named "STIM". Instead, there are a variety of channel names. The -% electronics used at FCDC still uses the "STIM" channel. -stimindx = find(strcmp(hdr.label, 'UPPT001')); -if isempty(stimindx) - stimindx = find(strcmp(hdr.label, 'USPT001')); -end -if isempty(stimindx) - stimindx = find(strcmp(hdr.label, 'UTRG001')); -end -if isempty(stimindx) - stimindx = find(strcmp(hdr.label, 'STIM')); -end -stim = read_ctf_meg4(datafile, hdr, 1, hdr.nTrials*hdr.nSamples, stimindx); - -% correct for reading stimulus channel as signed integer, whereas it should be an unsigned int -stim(find(stim<0)) = stim(find(stim<0)) + 2^32; - -% split backpanel and frontpanel data -bpstim = fix(stim / 2^16); -fpstim = double(bitand(uint32(stim), 2^16-1)); - -% determine the precise timing of the triggers -bpupflank = [0 (diff(bpstim)>0 & bpstim(1:(end-1))==0)]; -backpanel = bpupflank(1:(end-trigshift)).*bpstim((1+trigshift):end); -fpupflank = [0 (diff(fpstim)>0 & fpstim(1:(end-1))==0)]; -frontpanel = fpupflank(1:(end-trigshift)).*fpstim((1+trigshift):end); - -% pad with zeros to ensure same length as data -backpanel(length(stim)) = 0; -frontpanel(length(stim)) = 0; - diff --git a/external/fileio/private/read_data.m b/external/fileio/private/read_data.m deleted file mode 100644 index bfe0a10..0000000 --- a/external/fileio/private/read_data.m +++ /dev/null @@ -1,1217 +0,0 @@ -function [dat] = read_data(filename, varargin); - -% READ_DATA reads electrophysiological data from a variety of EEG, -% MEG and LFP files and represents it in a common data-independent -% format. The supported formats are listed in the accompanying -% READ_HEADER function. -% -% Use as -% dat = read_data(filename, ...) -% -% Additional options should be specified in key-value pairs and can be -% 'header' header structure, see READ_HEADER -% 'begsample' first sample to read -% 'endsample' last sample to read -% 'begtrial' first trial to read, mutually exclusive with begsample+endsample -% 'endtrial' last trial to read, mutually exclusive with begsample+endsample -% 'chanindx' list with channel indices to read -% 'checkboundary' boolean, whether to check for reading segments over a trial boundary -% 'cache' boolean, whether to use caching for multiple reads -% 'dataformat' string -% 'headerformat' string -% 'fallback' can be empty or 'biosig' (default = []) -% -% This function returns a 2-D matrix of size Nchans*Nsamples for -% continuous data when begevent and endevent are specified, or a 3-D -% matrix of size Nchans*Nsamples*Ntrials for epoched or trial-based -% data when begtrial and endtrial are specified. -% -% See also READ_HEADER, READ_EVENT, WRITE_DATA, WRITE_EVENT - -% Copyright (C) 2003-2007, Robert Oostenveld, F.C. Donders Centre -% -% $Log: read_data.m,v $ -% Revision 1.89 2009/10/16 07:31:18 roboos -% renamed chieti into itab for consistency with other formats -% -% Revision 1.88 2009/10/13 10:12:51 roboos -% added support for chieti_raw -% -% Revision 1.87 2009/10/08 11:13:40 roevdmei -% added support for nmc_archive_k -% -% Revision 1.86 2009/10/07 12:45:32 roevdmei -% minor spelling correction -% -% Revision 1.85 2009/04/29 10:52:17 jansch -% incorporated handling of unsegmented egi simple binaries -% -% Revision 1.84 2009/03/23 12:09:07 vlalit -% Minor changes to make the ctf_old option fully functional. -% -% Revision 1.83 2009/03/13 07:12:09 roboos -% also use read_brainvision_eeg low-level function for *.seg files, obsoleted the read_brainvision_seg function -% -% Revision 1.82 2009/03/02 10:44:38 roboos -% switched default for fif files to use the MNE reading routines in case of neuromag_fif -% the user can make his own choise by specifying the format as neuromag_mne (for the MNE routines) or neuromag_mex (for the meg-pd mex files) -% -% Revision 1.81 2009/02/25 12:59:30 marvger -% removed calls to filetype and replaced with strcmp(dataformat,x) for -% efficiency -% -% Revision 1.80 2009/02/13 08:02:21 roboos -% ensure that the requested sample and trial numbers are integers -% -% Revision 1.79 2009/02/12 11:47:23 vlalit -% Added support for neuro prax (eldith) EEG format based on functions from the manufacturer -% used with permission from the company's representative Mr. Klaus Schellhorn. -% -% Revision 1.78 2009/02/09 14:21:00 roboos -% added inport of micromed_trc data -% -% Revision 1.77 2009/02/09 13:35:16 roboos -% implemented efficient caching for bci2000, -% it should be initiated in read_header, subsequently read_data and read_event will reuse the details from the header -% -% Revision 1.76 2009/02/09 12:42:27 vlalit -% Added a check for discontinuous boundary in the case of neuromag_mne evoked data. -% -% Revision 1.75 2009/02/06 10:12:20 roboos -% incorporated the latest suggestions of Laurence Hunt for neuromag_mne -% -% Revision 1.74 2009/02/04 09:09:59 roboos -% fixed filename to headerfile/datafile cvonversion in case of ctf_old -% -% Revision 1.73 2009/01/23 16:18:36 roboos -% cleaned up neuromag_mne -% -% Revision 1.72 2009/01/23 10:32:55 vlalit -% New reader for Neuromag fif format using the MNE toolbox (http://www.nmr.mgh.harvard.edu/martinos/userInfo/data/sofMNE.php) implemented by Laurence Hunt. -% -% Revision 1.71 2009/01/20 21:50:20 roboos -% use mxDeserialize instead of eval(string) in mysql -% -% Revision 1.70 2009/01/19 15:05:47 roboos -% added skeleton support for reading fif files using mne functions -% -% Revision 1.69 2009/01/06 09:12:03 roboos -% use true/false instead of 1/0 -% -% Revision 1.68 2008/12/16 21:25:57 roboos -% removed the backward compatibility handling of the read_fcdc_data input arguments, these are now done in read_fcdc_data (i.e. keep it clean) -% -% Revision 1.67 2008/12/15 13:10:38 roboos -% fixed bug in biosig fallback, header would be read instead of data -% -% Revision 1.66 2008/12/01 14:49:59 roboos -% ensure that input arguments are double precision and not integers, otherwise the subsequent computations will be messed up (learned this in Lyon) -% -% Revision 1.65 2008/11/13 21:50:11 roboos -% also read 4d data in case ChannelUnitsPerBit is missing from header (give warning and set calibration to 1) -% -% Revision 1.64 2008/11/13 21:20:58 roboos -% use dataformat=ns_cnt16/32 to specify 16/32 bit format for reading neuroscan cnt files -% -% Revision 1.63 2008/11/02 10:59:41 roboos -% some more changes for ctf_ds in case of empty path -% -% Revision 1.62 2008/11/02 10:42:25 roboos -% improved handling of empty path in case of ctf dataset -% -% Revision 1.61 2008/09/29 21:46:02 roboos -% Implemented data caching in a data-format independent manner, using fetch_data and a persistent variable. -% Not yet suitable for inclusion in fileio release, hence the default is not to use caching. -% -% Revision 1.60 2008/09/29 08:37:44 roboos -% fixed bug when reading short segments of CTF data (errors were given on screen, so the bug was apparent) -% -% Revision 1.59 2008/09/25 11:53:48 roboos -% more efficient handling for CTF in real continuous datasets (i.e. one long trial) and in case all samples are within the same trial -% detected and fixed a bug that would case faulure of the code when reading a data segment that extends over more than two trials -% -% Revision 1.58 2008/09/24 16:26:17 roboos -% swiched from old fcdc import routines for CTF to the p-files supplied by CTF -% these new reading routines support synthetic gradients -% the format 'ctf_new' is not supported any more, because that is now the default -% -% Revision 1.57 2008/09/24 07:01:49 roboos -% fixed begsample for neuralynx_ncs (thanks to Martin) -% -% Revision 1.56 2008/07/24 08:44:20 roboos -% added initial support for nimh_cortex, not yet complete -% -% Revision 1.55 2008/07/01 16:23:02 roboos -% added read_combined_data (new implementation) -% -% Revision 1.54 2008/07/01 12:59:42 roboos -% explicit blockread 1 for ns_cnt -% -% Revision 1.53 2008/06/26 15:50:56 roboos -% tread ctf_new just as ctf_ds w.r.t. mapping of the filenames -% -% Revision 1.52 2008/06/20 07:25:56 roboos -% added check for presence of BCI2000 load_bcidat mex file -% -% Revision 1.51 2008/06/18 08:24:33 roboos -% added support for BCI2000 -% -% Revision 1.50 2008/06/10 10:22:12 jansch -% removed sparse from calibration for 4d data, this is not necessary. added -% possibility for filnames including '.' for 4d data -% -% Revision 1.49 2008/05/29 13:54:52 roboos -% also work when no path is specified -% -% Revision 1.48 2008/05/29 13:51:11 roboos -% use strcmp instead of strmatch, thanks to Marinka -% -% Revision 1.47 2008/05/29 07:30:42 roboos -% small change in renaming header/data and filename in case of ctf, this prevents a warning if the res4 or meg4 are not positioned in a xxx.ds directory (see email Jo) -% -% Revision 1.46 2008/05/27 16:12:26 vlalit -% Changed type name to ced_spike6mat -% -% Revision 1.45 2008/05/27 11:58:20 vlalit -% Added support of Matlab files exported from Spike 6 -% -% Revision 1.44 2008/05/15 15:10:56 roboos -% added ctf_new implementation, using p-files, this supports synthetic gradients -% some changes to the filename handling, merged nihm2grad into ctf2grad -% -% Revision 1.43 2008/05/02 17:45:10 vlalit -% Some bug fixes after testing the SPM fileo code -% -% Revision 1.41 2008/04/28 19:27:11 roboos -% fixed dimord and selection of eeglab set data -% -% Revision 1.40 2008/04/21 11:50:52 roboos -% added support for egi_sbin, thanks to Joseph Dien -% -% Revision 1.39 2008/04/18 14:07:45 roboos -% added eeglab_set -% -% Revision 1.38 2008/04/11 07:23:15 roboos -% updated docu -% -% Revision 1.37 2008/04/10 09:34:51 roboos -% added fallback option for biosig, implemented biosig also for edf -% -% Revision 1.36 2008/04/09 16:50:02 roboos -% added fallback option to biosig (not default) -% -% Revision 1.35 2008/04/09 14:10:34 roboos -% added placeholder for biosig (not yet implemented) -% -% Revision 1.34 2008/04/09 10:09:45 roboos -% pass the hdr.orig to the low-level brainvision readers -% -% Revision 1.33 2008/02/19 10:08:13 roboos -% added support for fcdc_buffer -% -% Revision 1.32 2008/01/31 20:12:51 roboos -% On line 322 the cell element 4D was added to the existing case -% designed for the handling of 4D_bti data. This is necessary to -% allow this identified filetype to cause execution of this case. -% [thanks to Gavin] -% -% Revision 1.31 2008/01/10 12:57:34 roboos -% give explicit errors with msgid FILEIO:Something -% -% Revision 1.30 2007/12/17 13:03:52 roboos -% Vladimir found and fixed some bugs pertaining to the nexstim_nxe format -% -% Revision 1.29 2007/12/17 08:24:28 roboos -% added support for nexstim_nxe, thanks to Vladimir -% the low-level code has not been tested by myself -% -% Revision 1.28 2007/12/12 16:50:15 roboos -% added support for neuralynx_bin -% -% Revision 1.27 2007/11/07 10:49:06 roboos -% cleaned up the reading and writing from/to mysql database, using db_xxx helper functions (see mysql directory) -% -% Revision 1.26 2007/11/05 17:01:42 roboos -% added implementation for fcdc_mysql, not yet finished -% -% Revision 1.25 2007/09/24 15:14:02 roboos -% fixed bug in calibration of 4D/bti data, which is different for float than for short format data files (thanks to Nathan) -% -% Revision 1.24 2007/09/13 09:55:42 roboos -% use read_biosemi_bdf instead of openbdf/readbdf -% -% Revision 1.23 2007/08/01 12:24:40 roboos -% updated comments -% -% Revision 1.22 2007/08/01 09:57:01 roboos -% moved all code related to ctf shared memory to seperate functions -% -% Revision 1.21 2007/07/27 12:24:52 roboos -% implemented support for ctf_shm -% removed a double check for the presence of the file -% -% Revision 1.20 2007/07/19 14:49:21 roboos -% switched the default reader for nex files from read_nex_data to read_plexon_nex, the old one is still supported if explicitely mentioned as data/headerformat -% added support for multiple fragments of continuous AD data in nex files, holes are filled with NaNs -% -% Revision 1.19 2007/07/04 13:20:51 roboos -% added support for egi_egis/egia, thanks to Joseph Dien -% -% Revision 1.18 2007/07/03 16:10:48 roboos -% added a hack for 32 bit neuroscan format (hdr.nsdf=16|32), this should actually be be done using autodetection -% -% Revision 1.17 2007/07/03 15:53:46 roboos -% switched from using Cristian Wienbruchs BTi toolbox to a new ascii header reading function (read_bti_m4d) -% -% Revision 1.16 2007/06/13 08:06:21 roboos -% updated help -% -% Revision 1.15 2007/04/16 16:06:50 roboos -% fixed bug in selection of trials from an epoched file, when samples are requested (thanks to Vladimir) -% -% Revision 1.14 2007/03/26 12:41:18 roboos -% deal with continuous channels in nex files that have different starting samples/timestamps -% small modification in plexon_plx to account fo the change in the API of the underlying function -% -% Revision 1.13 2007/03/21 17:24:01 roboos -% added plexon_ds -% -% Revision 1.12 2007/03/19 17:03:14 roboos -% added chanindx for read_neuralynx_dma -% implemented an alternative reader for nex files (read_plexon_nex), the old reader is still the default -% -% Revision 1.11 2007/02/21 09:53:44 roboos -% changed the rearrangement of the data in case of neuralynx_ncs to reflect the changed representation (2D numeric array instead of 1D cell array) -% -% Revision 1.10 2007/01/09 09:37:48 roboos -% added neuralynx_nte, added spike channels for plexon_plx -% -% Revision 1.9 2007/01/04 17:12:36 roboos -% implemented plexon_plx, only continuous channels -% -% Revision 1.8 2007/01/04 12:21:36 roboos -% updated the neuralynx section to reflect the new reading functions and to use read_neuralynx_cds -% -% Revision 1.7 2006/12/04 10:38:12 roboos -% added support for ns_avg -% fixed long-outstanding problem for reading multiple trials from ns_eeg data -% -% Revision 1.6 2006/09/18 21:47:54 roboos -% implemented support for fcdc_matbin, i.e. a dataset consisting of a matlab file with header and events and a seperate binary datafile -% added smart default for reading all data when no selection given -% -% Revision 1.5 2006/09/18 14:22:54 roboos -% implemented support for 4D-BTi dataformat -% -% Revision 1.4 2006/08/28 10:12:22 roboos -% use seperate filetype_check_extension instead of (missing) check_extension subfunction (thanks to Thilo for reporting this bug) -% -% Revision 1.3 2006/06/19 10:31:47 roboos -% translate continuous option into checkboundary (complements), added documentation -% -% Revision 1.2 2006/06/19 08:14:17 roboos -% updated documentation -% -% Revision 1.1 2006/06/07 09:32:20 roboos -% new implementation based on the read_fcdc_xxx functions, now with -% variable (key-val) input arguments, changed the control structure -% in the rpobram (switch instead of ifs), allow the user to specify -% the file format, allow the user to specify either a sample selection -% or a block selection. The reading functionality should not have -% changed compared to the read_fcdc_xxx versions. -% - -persistent cachedata % for caching -persistent db_blob % for fcdc_mysql - -if isempty(db_blob) - db_blob = 0; -end - -% get the optional input arguments -hdr = keyval('header', varargin); -begsample = keyval('begsample', varargin); -endsample = keyval('endsample', varargin); -begtrial = keyval('begtrial', varargin); -endtrial = keyval('endtrial', varargin); -chanindx = keyval('chanindx', varargin); -checkboundary = keyval('checkboundary', varargin); -dataformat = keyval('dataformat', varargin); -headerformat = keyval('headerformat', varargin); -fallback = keyval('fallback', varargin); -cache = keyval('cache', varargin); if isempty(cache), cache = 0; end - -% determine the filetype -if isempty(dataformat) - dataformat = filetype(filename); -end - -% test whether the file or directory exists -if ~exist(filename, 'file') && ~strcmp(dataformat, 'ctf_shm') && ~strcmp(dataformat, 'fcdc_mysql') && ... - ~strcmp(dataformat, 'fcdc_buffer') - error('FILEIO:InvalidFileName', 'file or directory ''%s'' does not exist', filename); -end - -% ensure that these are double precision and not integers, otherwise the subsequent computations will be messed up -begsample = double(begsample); -endsample = double(endsample); -begtrial = double(begtrial); -endtrial = double(endtrial); - -% ensure that the requested sample and trial numbers are integers -if ~isempty(begsample) && mod(begsample, 1) - warning('rounding "begsample" to the nearest integer'); - begsample = round(begsample); -end -if ~isempty(endsample) && mod(endsample, 1) - warning('rounding "endsample" to the nearest integer'); - endsample = round(endsample); -end -if ~isempty(begtrial) && mod(begtrial, 1) - warning('rounding "begtrial" to the nearest integer'); - begtrial = round(begtrial); -end -if ~isempty(endtrial) && mod(endtrial, 1) - warning('rounding "endtrial" to the nearest integer'); - endtrial = round(endtrial); -end - -switch dataformat - case '4d_pdf' - datafile = filename; - headerfile = [datafile '.m4d']; - sensorfile = [datafile '.xyz']; - case {'4d_m4d', '4d_xyz'} - datafile = filename(1:(end-4)); % remove the extension - headerfile = [datafile '.m4d']; - sensorfile = [datafile '.xyz']; - case '4d' - [path, file, ext] = fileparts(filename); - datafile = fullfile(path, [file,ext]); - headerfile = fullfile(path, [file,ext]); - configfile = fullfile(path, 'config'); - case {'ctf_ds', 'ctf_old'} - % convert CTF filename into filenames - [path, file, ext] = fileparts(filename); - if any(strcmp(ext, {'.res4' '.meg4', '.1_meg4' '.2_meg4' '.3_meg4' '.4_meg4' '.5_meg4' '.6_meg4' '.7_meg4' '.8_meg4' '.9_meg4'})) - filename = path; - [path, file, ext] = fileparts(filename); - end - if isempty(path) && isempty(file) - % this means that the dataset was specified as the present working directory, i.e. only with '.' - filename = pwd; - [path, file, ext] = fileparts(filename); - end - headerfile = fullfile(filename, [file '.res4']); - datafile = fullfile(filename, [file '.meg4']); - if length(path)>3 && strcmp(path(end-2:end), '.ds') - filename = path; % this is the *.ds directory - end - case 'ctf_meg4' - [path, file, ext] = fileparts(filename); - if isempty(path) - path = pwd; - end - headerfile = fullfile(path, [file '.res4']); - datafile = fullfile(path, [file '.meg4']); - if length(path)>3 && strcmp(path(end-2:end), '.ds') - filename = path; % this is the *.ds directory - end - case 'ctf_res4' - [path, file, ext] = fileparts(filename); - if isempty(path) - path = pwd; - end - headerfile = fullfile(path, [file '.res4']); - datafile = fullfile(path, [file '.meg4']); - if length(path)>3 && strcmp(path(end-2:end), '.ds') - filename = path; % this is the *.ds directory - end - case 'brainvision_vhdr' - [path, file, ext] = fileparts(filename); - headerfile = fullfile(path, [file '.vhdr']); - if exist(fullfile(path, [file '.eeg'])) - datafile = fullfile(path, [file '.eeg']); - elseif exist(fullfile(path, [file '.seg'])) - datafile = fullfile(path, [file '.seg']); - elseif exist(fullfile(path, [file '.dat'])) - datafile = fullfile(path, [file '.dat']); - end - case 'brainvision_eeg' - [path, file, ext] = fileparts(filename); - headerfile = fullfile(path, [file '.vhdr']); - datafile = fullfile(path, [file '.eeg']); - case 'brainvision_seg' - [path, file, ext] = fileparts(filename); - headerfile = fullfile(path, [file '.vhdr']); - datafile = fullfile(path, [file '.seg']); - case 'brainvision_dat' - [path, file, ext] = fileparts(filename); - headerfile = fullfile(path, [file '.vhdr']); - datafile = fullfile(path, [file '.dat']); - case 'fcdc_matbin' - [path, file, ext] = fileparts(filename); - headerfile = fullfile(path, [file '.mat']); - datafile = fullfile(path, [file '.bin']); - case 'nmc_archive_k' - [path, file, ext] = fileparts(filename); - headerfile = [path '/' file 'newparams.txt']; - if isempty(headerformat) - headerformat = 'nmc_archive_k'; - end - if isempty(hdr) - hdr = read_header(headerfile, 'headerformat', headerformat); - end - datafile = filename; - otherwise - % convert filename into filenames, assume that the header and data are the same - datafile = filename; - headerfile = filename; -end - -if ~strcmp(filename, datafile) && ~ismember(dataformat, {'ctf_ds', 'ctf_old'}) - filename = datafile; % this function will read the data - dataformat = filetype(filename); % update the filetype -end - -% for backward compatibility, default is to check when it is not continous -if isempty(checkboundary) - checkboundary = ~keyval('continuous', varargin); -end - -% read the header if it is not provided -if isempty(hdr) - hdr = read_header(filename, 'headerformat', headerformat); -end - -% set the default channel selection, which is all channels -if isempty(chanindx) - chanindx = 1:hdr.nChans; -end - -% read untill the end of the file if the endsample is "inf" -if any(isinf(endsample)) && any(endsample>0) - endsample = hdr.nSamples*hdr.nTrials; -end - -% test whether the requested channels can be accomodated -if min(chanindx)<1 || max(chanindx)>hdr.nChans - error('FILEIO:InvalidChanIndx', 'selected channels are not present in the data'); -end - -% test whether the requested data segment is not outside the file -if any(begsample<1) - error('FILEIO:InvalidBegSample', 'cannot read data before the begin of the file'); -elseif any(endsample>(hdr.nSamples*hdr.nTrials)) - error('FILEIO:InvalidEndSample', 'cannot read data after the end of the file'); -end - -requesttrials = isempty(begsample) && isempty(endsample); -requestsamples = isempty(begtrial) && isempty(endtrial); - -if cache && requesttrials - error('caching is not supported when reading trials') -end - -if isempty(begsample) && isempty(endsample) && isempty(begtrial) && isempty(endtrial) - % neither samples nor trials are specified, set the defaults to read the complete data trial-wise (also works for continuous) - requestsamples = 0; - requesttrials = 1; - begtrial = 1; - endtrial = hdr.nTrials; -end - -% set the default, which is to assume that it is should check for boundaries when samples are requested -if isempty(checkboundary) && requesttrials - checkboundary = false; -elseif isempty(checkboundary) && requestsamples - checkboundary = true; -end - -if requesttrials && requestsamples - error('you cannot select both trials and samples at the same time'); -elseif requesttrials - % this allows for support using a continuous reader - if isinf(hdr.nSamples) && begtrial==1 - begsample = 1; % computing it here does not work (0*inf=nan) - else - begsample = (begtrial-1)*hdr.nSamples + 1; % compute it the normal way - end - endsample = (endtrial )*hdr.nSamples; -elseif requestsamples - % this allows for support using a trial-based reader - begtrial = floor((begsample-1)/hdr.nSamples)+1; - endtrial = floor((endsample-1)/hdr.nSamples)+1; -else - error('you should either specify begin/end trial or begin/end sample'); -end - -% test whether the requested data segment does not extend over a discontinuous trial boundary -if checkboundary && hdr.nTrials>1 - if begtrial~=endtrial - error('requested data segment extends over a discontinuous trial boundary'); - end -end - -if strcmp(dataformat, 'bci2000_dat') - % caching for BCI2000 is handled in the main section and in read_header -else - % implement the caching in a data-format independent way - if cache && isempty(cachedata) - % create a new FieldTrip raw data structure that will hold the data - cachedata.label = hdr.label(chanindx); - cachedata.fsample = hdr.Fs; - cachedata.time = {}; - cachedata.trial = {}; - cachedata.cfg = []; - cachedata.cfg.trl = zeros(0,3); - elseif cache && ~isempty(cachedata) - % try to fetch the requested segment from the cache - try - dat = fetch_data(cachedata, 'begsample', begsample', 'endsample', endsample); - % fprintf('caching succeeded\n'); - return - catch - % fprintf('caching failed\n'); - end - end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% read the data with the low-level reading function -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -switch dataformat - - case {'4d' '4d_pdf', '4d_m4d', '4d_xyz'} - [fid,message] = fopen(datafile,'rb','ieee-be'); - % determine the type and size of the samples - sampletype = lower(hdr.orig.Format); - switch sampletype - case 'short' - samplesize = 2; - case 'long' - samplesize = 4; - case 'float' - samplesize = 4; - case 'double' - samplesize = 8; - otherwise - error('unsupported data format'); - end - % 4D/BTi MEG data is multiplexed, can be epoched/discontinuous - offset = (begsample-1)*samplesize*hdr.nChans; - numsamples = endsample-begsample+1; - gain = hdr.orig.ChannelGain; - if isfield(hdr.orig, 'ChannelUnitsPerBit') - upb = hdr.orig.ChannelUnitsPerBit; - else - warning('cannot determine ChannelUnitsPerBit'); - upb = 1; - end - % jump to the desired data - fseek(fid, offset, 'cof'); - % read the desired data - if length(chanindx)==1 - % read only one channel - fseek(fid, (chanindx-1)*samplesize, 'cof'); % seek to begin of channel - dat = fread(fid, numsamples, ['1*' sampletype], (hdr.nChans-1)*samplesize)'; % read one channel, skip the rest - else - % read all channels - dat = fread(fid, [hdr.nChans, numsamples], sampletype); - end - fclose(fid); - if length(chanindx)==1 - % only one channel was selected, which is managed by the code above - % nothing to do - elseif length(chanindx)==hdr.nChans - % all channels have been selected - % nothing to do - else - % select the desired channel(s) - dat = dat(chanindx,:); - end - % determine how to calibrate the data - switch sampletype - case {'short', 'long'} - % include both the gain values and the integer-to-double conversion in the calibration - calib = diag(gain(chanindx) .* upb(chanindx)); - case {'float', 'double'} - % only include the gain values in the calibration - calib = diag(gain(chanindx)); - otherwise - error('unsupported data format'); - end - % calibrate the data - dat = calib*dat; - - case 'bci2000_dat' - % this requires the load_bcidat mex file to be present on the path - hastoolbox('BCI2000', 1); - % this is inefficient, since it reads the complete data - if isfield(hdr.orig, 'signal') && isfield(hdr.orig, 'states') - % assume that the complete data is stored in the header, this speeds up subsequent read operations - signal = hdr.orig.signal; - states = hdr.orig.states; - parameters = hdr.orig.parameters; - total_samples = hdr.orig.total_samples; - else - [signal, states, parameters, total_samples] = load_bcidat(filename); - end - % apply the callibration from AD units to uV - dat = double(signal(begsample:endsample,chanindx)'); - for i=chanindx(:)' - dat(i,:) = dat(i,:).* parameters.SourceChGain.NumericValue(i) + parameters.SourceChOffset.NumericValue(i); - end - dimord = 'chans_samples'; - - case 'besa_avr' - % BESA average data - orig = read_besa_avr(filename); - dat = orig.data(chanindx, begsample:endsample); - - case 'besa_swf' - % BESA source waveform - orig = read_besa_swf(filename); - dat = orig.data(chanindx, begsample:endsample); - - case {'biosemi_bdf', 'bham_bdf'} - % this uses a mex file for reading the 24 bit data - dat = read_biosemi_bdf(filename, hdr, begsample, endsample, chanindx); - - case {'biosemi_old'} - % this uses the openbdf and readbdf functions that I copied from the EEGLAB toolbox - epochlength = hdr.orig.Head.SampleRate(1); - % it has already been checked in read_header that all channels have the same sampling rate - begepoch = floor((begsample-1)/epochlength) + 1; - endepoch = floor((endsample-1)/epochlength) + 1; - nepochs = endepoch - begepoch + 1; - orig = openbdf(filename); - dat = zeros(length(chanindx),nepochs*epochlength); - for i=begepoch:endepoch - % read and concatenate all required data epochs - [orig, buf] = readbdf(orig, i, 0); - if size(buf,2)~=hdr.nChans || size(buf,1)~=epochlength - error('error reading selected data from bdf-file'); - else - dat(:,((i-begepoch)*epochlength+1):((i-begepoch+1)*epochlength)) = buf(:,chanindx)'; - end - end - begsample = begsample - (begepoch-1)*epochlength; % correct for the number of bytes that were skipped - endsample = endsample - (begepoch-1)*epochlength; % correct for the number of bytes that were skipped - dat = dat(:, begsample:endsample); - % close the file between seperate read operations - fclose(orig.Head.FILE.FID); - - case {'biosig', 'edf'} - % use the biosig toolbox if available - hastoolbox('BIOSIG', 1); - dat = read_biosig_data(filename, hdr, begsample, endsample, chanindx); - - case {'brainvision_eeg', 'brainvision_dat', 'brainvision_seg'} - dat = read_brainvision_eeg(filename, hdr.orig, begsample, endsample); - dat = dat(chanindx,:); % select the desired channels - - case 'ced_son' - % chek the availability of the required low-level toolbox - hastoolbox('neuroshare', 1); - % use the reading function supplied by Gijs van Elswijk - % - % CED ADC is done in sequence, thus the analog channels - % do not share the same time axis. This is _ignored_ here. - % - % Set the READ_CED_SON parameter 'readtimestamps' to - % 'yes' to get time axis for each data channel returned. - % This time information can be used to do - % a temporal realignment of the data. - tmp = read_ced_son(filename,'readdata','yes',... - 'begsample',begsample,... - 'endsample',endsample,... - 'channels',chanindx); - dat = cell2mat(tmp.data'); - - case 'itab_raw' - % check the presence of the required low-level toolbox - hastoolbox('lc-libs', 1); - chansel = hdr.orig.chansel; % these are the channels that are visible to fieldtrip - % read the data using the dll - dat = lcReadData(chansel, begsample, endsample, filename); - % take the subset of channels that is selected by the user - dat = dat(chanindx, :); - - case 'combined_ds' - dat = read_combined_ds(filename, hdr, begsample, endsample, chanindx); - - case {'ctf_ds', 'ctf_meg4', 'ctf_res4'} - % check that the required low-level toolbox is available - hastoolbox('ctf', 1); - % this returns SQUIDs in T, EEGs in V, ADC's and DACS in V, HLC channels in m, clock channels in s. - if begtrial==endtrial - % specify selection as 3x1 vector - trlbegsample = begsample - hdr.nSamples*(begtrial-1); % within the trial - trlendsample = endsample - hdr.nSamples*(begtrial-1); % within the trial - dat = getCTFdata(hdr.orig, [trlbegsample; trlendsample; begtrial], chanindx, 'T', 'double'); - dimord = 'samples_chans'; - else - % specify selection as 1xN vector - dat = getCTFdata(hdr.orig, [begtrial:endtrial], chanindx, 'T', 'double'); - dimord = 'samples_chans_trials'; - end - - case {'ctf_old', 'read_ctf_meg4'} - % read it using the open-source matlab code that originates from CTF and that was modified by the FCDC - dat = read_ctf_meg4(datafile, hdr.orig, begsample, endsample, chanindx); - - case 'ctf_read_meg4' - % check that the required low-level toolbox is available - hastoolbox('eegsf', 1); - % read it using the CTF importer from the NIH and Daren Weber - tmp = ctf_read_meg4(filename, hdr.orig, chanindx, 'all', begtrial:endtrial); - dat = cat(3, tmp.data{:}); - % the data is shaped in a 3-D array - dimord = 'samples_chans_trials'; - - case 'ctf_shm' - % contact Robert Oostenveld if you are interested in real-time acquisition on the CTF system - % read the data from shared memory - [dat, dimord] = read_shm_data(hdr, chanindx, begtrial, endtrial); - - case 'eeglab_set' - dat = read_eeglabdata(filename, 'header', hdr, 'begtrial', begtrial, 'endtrial', endtrial, 'chanindx', chanindx); - dimord = 'chans_samples_trials'; - - case 'spmeeg_mat' - dat = read_spmeeg_data(filename, 'header', hdr, 'begsample', begsample, 'endsample', endsample, 'chanindx', chanindx); - - case 'ced_spike6mat' - dat = read_spike6mat_data(filename, 'header', hdr, 'begsample', begsample, 'endsample', endsample, 'chanindx', chanindx); - - case 'eep_avr' - % check that the required low-level toolbos ix available - hastoolbox('eeprobe', 1); - dat = read_eep_avr(filename); - dat = dat.data(chanindx,begsample:endsample); % select the desired channels and samples - - case 'eep_cnt' - % check that the required low-level toolbos ix available - hastoolbox('eeprobe', 1); - dat = read_eep_cnt(filename, begsample, endsample); - dat = dat.data(chanindx,:); % select the desired channels - - case 'fcdc_buffer' - % read from a networked buffer for realtime analysis - - [host, port] = filetype_check_uri(filename); - dat = buffer('get_dat', [begsample-1 endsample-1], host, port); % indices should be zero-offset - dat = dat.buf(chanindx,:); % select the desired channels - - case 'fcdc_matbin' - % multiplexed data in a *.bin file, accompanied by a matlab file containing the header - offset = begsample-1; - numsamples = endsample-begsample+1; - samplesize = 8; - sampletype = 'double'; - [fid,message] = fopen(datafile,'rb','ieee-le'); - % jump to the desired data - fseek(fid, offset*samplesize*hdr.nChans, 'cof'); - % read the desired data - if length(chanindx)==1 - % read only one channel - fseek(fid, (chanindx-1)*samplesize, 'cof'); % seek to begin of channel - dat = fread(fid, numsamples, ['1*' sampletype], (hdr.nChans-1)*samplesize)'; % read one channel, skip the rest - else - % read all channels - dat = fread(fid, [hdr.nChans, numsamples], sampletype); - end - fclose(fid); - if length(chanindx)==1 - % only one channel was selected, which is managed by the code above - % nothing to do - elseif length(chanindx)==hdr.nChans - % all channels have been selected - % nothing to do - else - % select the desired channel(s) - dat = dat(chanindx,:); - end - - case 'fcdc_mysql' - % read from a MySQL server listening somewhere else on the network - db_open(filename); - if db_blob - error('not implemented'); - else - for i=begtrial:endtrial - s = db_select('fieldtrip.data', {'nChans', 'nSamples', 'data'}, i); - dum{i-begtrial+1} = mxDeserialize(s.data); - end - dat = zeros(length(chanindx), s.nSamples, endtrial-begtrial+1); - for i=begtrial:endtrial - dat(:,:,i-begtrial+1) = dum{i-begtrial+1}(chanindx,:); - end - dimord = 'chans_samples_trials'; - end - - case {'egi_egia', 'egi_egis'} - dat = read_egis_data(filename, hdr, begtrial, endtrial, chanindx); - dimord = 'chans_samples_trials'; - - case {'egi_sbin'} - if mod(hdr.orig.header_array(1),2)==0, - %unsegmented data contains only 1 trial, don't read the whole file - dat = read_sbin_data(filename, hdr, begsample, endsample, chanindx); - requestsamples = 0; - else - %segmented data - dat = read_sbin_data(filename, hdr, begtrial, endtrial, chanindx); - end - dimord = 'chans_samples_trials'; - - case 'micromed_trc' - dat = read_micromed_trc(filename, begsample, endsample); - dat = dat(chanindx,:); - dimord = 'chans_samples'; - - case {'mpi_ds', 'mpi_dap'} - [hdr, dat] = read_mpi_ds(filename); - dat = dat(chanindx, begsample:endsample); % select the desired channels and samples - - case 'neuralynx_dma' - dat = read_neuralynx_dma(filename, begsample, endsample, chanindx); - - case 'neuralynx_sdma' - dat = read_neuralynx_sdma(filename, begsample, endsample, chanindx); - - case 'neuralynx_ncs' - NRecords = hdr.nSamples/512; - begrecord = ceil(begsample/512); - endrecord = ceil(endsample/512); - % read the records that contain the desired samples - ncs = read_neuralynx_ncs(filename, begrecord, endrecord); - % cut out the desired samples - begsample = begsample - (begrecord-1)*512; - endsample = endsample - (begrecord-1)*512; - % this also reshape the data from 512 X records into a linear array - dat = ncs.dat(begsample:endsample); - - case 'neuralynx_nse' - % read all records - nse = read_neuralynx_nse(filename); - % convert timestamps to samples - sample = round((nse.TimeStamp - hdr.FirstTimeStamp)./hdr.TimeStampPerSample + 1); - % select the timestamps that are between begin and endsample - sample = sample(sample>=begsample & sample<=endsample) - begsample + 1; - dat = zeros(1,endsample-begsample+1); - dat(sample) = 1; - - case 'neuralynx_nte' - % read all records - nte = read_neuralynx_nte(filename); - % convert timestamps to samples - sample = round((nte.TimeStamp - hdr.FirstTimeStamp)./hdr.TimeStampPerSample + 1); - % select the timestamps that are between begin and endsample - sample = sample(sample>=begsample & sample<=endsample) - begsample + 1; - dat = zeros(1,endsample-begsample+1); - dat(sample) = 1; - - case {'neuralynx_ttl', 'neuralynx_tsl', 'neuralynx_tsh'} - % single channel files - dat = read_neuralynx_ttl(filename, begsample, endsample); - - case 'neuralynx_bin' - % single channel files - dat = read_neuralynx_bin(filename, begsample, endsample); - - case 'neuralynx_ds' - dat = read_neuralynx_ds(filename, hdr, begsample, endsample, chanindx); - - case 'neuralynx_cds' - dat = read_neuralynx_cds(filename, hdr, begsample, endsample, chanindx); - - case 'nexstim_nxe' - dat = read_nexstim_nxe(filename, begsample, endsample, chanindx); - - case 'nimh_cortex' - keyboard - - case 'ns_avg' - % NeuroScan average data - orig = read_ns_avg(filename); - dat = orig.data(chanindx, begsample:endsample); - - case {'ns_cnt' 'ns_cnt16', 'ns_cnt32'} - % Neuroscan continuous data - sample1 = begsample-1; - ldnsamples = endsample-begsample+1; % number of samples to read - ldchan = 1:hdr.nChans; % must be row vector - chanoi = chanindx(:)'; % channels of interest - if sample1<0 - error('begin sample cannot be for the beginning of the file'); - end - % the hdr.nsdf was the initial fieldtrip hack to get 32 bit support, now it is realized using a extended dataformat string - if isfield(hdr, 'nsdf') && hdr.nsdf==16 - dataformat = 'ns_cnt16'; - elseif isfield(hdr, 'nsdf') && hdr.nsdf==32 - dataformat = 'ns_cnt32'; - end - % read_ns_cnt originates from the EEGLAB package (loadcnt.m) but is - % an old version since the new version is not compatible any more - % all data is read, and only the relevant data is kept. - if strcmp(dataformat, 'ns_cnt') - tmp = read_ns_cnt(filename, 'sample1', sample1, 'ldnsamples', ldnsamples, 'ldchan', ldchan, 'blockread', 1); - elseif strcmp(dataformat, 'ns_cnt16') - tmp = read_ns_cnt(filename, 'sample1', sample1, 'ldnsamples', ldnsamples, 'ldchan', ldchan, 'blockread', 1, 'format', 16); - elseif strcmp(dataformat, 'ns_cnt32') - tmp = read_ns_cnt(filename, 'sample1', sample1, 'ldnsamples', ldnsamples, 'ldchan', ldchan, 'blockread', 1, 'format', 32); - end - dat = tmp.dat(chanoi,:); - - case 'ns_eeg' - % Neuroscan epoched file - tmp = read_ns_eeg(filename, begtrial:endtrial); - siz = [(endtrial-begtrial+1) hdr.nChans hdr.nSamples]; - dat = reshape(tmp.data, siz); % ensure 3-D array - dat = dat(:,chanindx,:); % select channels - dimord = 'trials_chans_samples'; % selection using begsample and endsample will be done later - - case {'neuromag_fif' 'neuromag_mne'} - % check that the required low-level toolbox is available - hastoolbox('mne', 1); - if (hdr.orig.iscontinuous) - dat = fiff_read_raw_segment(hdr.orig.raw,begsample+hdr.nSamplesPre-1,endsample+hdr.nSamplesPre-1,chanindx); - dimord = 'chans_samples'; - elseif (hdr.orig.isaverage) - dat = cat(2, hdr.orig.evoked.epochs); % concatenate all epochs, this works both when they are of constant or variable length - if checkboundary - trialnumber = []; - for i = 1:numel(hdr.orig.evoked) - trialnumber = [trialnumber i*ones(size(hdr.orig.evoked(i).times))]; - end - if trialnumber(begsample) ~= trialnumber(endsample) - error('requested data segment extends over a discontinuous trial boundary'); - end - end - dat = dat(chanindx, begsample:endsample); % select the desired channels and samples - dimord = 'chans_samples'; - elseif (hdr.orig.isepoched) - error('Support for epoched *.fif data is not yet implemented.') - end - - case 'neuromag_mex' - % check that the required low-level toolbox is available - hastoolbox('meg-pd', 1); - begtime = (begsample-1)/hdr.Fs; - begepoch = floor((begsample-1)/hdr.nSamples) + 1; - endepoch = floor((endsample-1)/hdr.nSamples) + 1; - rawdata('any',filename); - rawdata('goto', begtime); - dat = []; - for i=begepoch:endepoch - [buf, status] = rawdata('next'); - if ~strcmp(status, 'ok') - error('error reading selected data from fif-file'); - else - dat(:,((i-begepoch)*hdr.nSamples+1):((i-begepoch+1)*hdr.nSamples)) = buf(chanindx,:); - end - end - rawdata('close'); - begsample = begsample - (begepoch-1)*hdr.nSamples; % correct for the number of bytes that were skipped - endsample = endsample - (begepoch-1)*hdr.nSamples; % correct for the number of bytes that were skipped - dat = dat(:, begsample:endsample); - - case 'neuroprax_eeg' - tmp = np_readdata(filename, hdr.orig, begsample - 1, endsample - begsample + 1, 'samples'); - dat = tmp.data'; - - case 'plexon_ds' - dat = read_plexon_ds(filename, hdr, begsample, endsample, chanindx); - - case 'plexon_ddt' - dat = read_plexon_ddt(filename, begsample, endsample); - dat = dat.data(chanindx,:); - - case {'read_nex_data'} % this is an alternative reader for nex files - dat = read_nex_data(filename, hdr, begsample, endsample, chanindx); - - case {'read_plexon_nex' 'plexon_nex'} % this is the default reader for nex files - dat = zeros(length(chanindx), endsample-begsample+1); - for i=1:length(chanindx) - if hdr.orig.VarHeader(chanindx(i)).Type==5 - % this is a continuous channel - if hdr.orig.VarHeader(chanindx(i)).Count==1 - [nex, chanhdr] = read_plexon_nex(filename, 'header', hdr.orig, 'channel', chanindx(i), 'tsonly', 1); - % the AD channel contains a single fragment - % determine the sample offset into this fragment - offset = round(double(nex.ts-hdr.FirstTimeStamp)./hdr.TimeStampPerSample); - chanbegsmp = begsample - offset; - chanendsmp = endsample - offset; - if chanbegsmp<1 - % the first sample of this channel is later than the beginning of the dataset - % and we are trying to read the beginning of the dataset - [nex, chanhdr] = read_plexon_nex(filename, 'header', hdr.orig, 'channel', chanindx(i), 'tsonly', 0, 'begsample', 1, 'endsample', chanendsmp); - % padd the beginning of this channel with NaNs - nex.dat = [nan(1,offset) nex.dat]; - else - [nex, chanhdr] = read_plexon_nex(filename, 'header', hdr.orig, 'channel', chanindx(i), 'tsonly', 0, 'begsample', chanbegsmp, 'endsample', chanendsmp); - end - % copy the desired samples into the output matrix - dat(i,:) = nex.dat; - else - % the AD channel contains multiple fragments - [nex, chanhdr] = read_plexon_nex(filename, 'header', hdr.orig, 'channel', chanindx(i), 'tsonly', 0); - % reconstruct the full AD timecourse with NaNs at all missing samples - offset = round(double(nex.ts-hdr.FirstTimeStamp)./hdr.TimeStampPerSample); % of each fragment, in AD samples - nsample = diff([nex.indx length(nex.dat)]); % of each fragment, in AD samples - % allocate memory to hold the complete continuous record - cnt = nan(1, offset(end)+nsample(end)); - for j=1:length(offset) - cntbegsmp = offset(j) + 1; - cntendsmp = offset(j) + nsample(j); - fragbegsmp = nex.indx(j) + 1; - fragendsmp = nex.indx(j) + nsample(j); - cnt(cntbegsmp:cntendsmp) = nex.dat(fragbegsmp:fragendsmp); - end - % copy the desired samples into the output matrix - dat(i,:) = cnt(begsample:endsample); - end - elseif any(hdr.orig.VarHeader(chanindx(i)).Type==[0 1 3]) - % it is a neuron(0), event(1) or waveform(3) channel and therefore it has timestamps - [nex, chanhdr] = read_plexon_nex(filename, 'header', hdr.orig, 'channel', chanindx(i), 'tsonly', 1); - % convert the timestamps to samples - sample = round(double(nex.ts - hdr.FirstTimeStamp)./hdr.TimeStampPerSample) + 1; - % select only timestamps that are between begin and endsample - sample = sample(sample>=begsample & sample<=endsample) - begsample + 1; - for j=sample(:)' - dat(i,j) = dat(i,j) + 1; - end - end - end - if any(isnan(dat(:))) - warning('data has been padded with NaNs'); - end - - case 'plexon_plx' - % determine the continuous channels - contlabel = {hdr.orig.SlowChannelHeader.Name}; - for i=1:length(contlabel) - contlabel{i} = deblank(contlabel{i}); - end - [contindx, contsel] = match_str(contlabel, hdr.label(chanindx)); - - % determine the channels with spike waveforms - spikelabel = {hdr.orig.ChannelHeader.Name}; - for i=1:length(spikelabel) - spikelabel{i} = deblank(spikelabel{i}); - end - [spikeindx, spikesel] = match_str(spikelabel, hdr.label(chanindx)); - - if (length(contindx)+length(spikeindx))=begsample & sample<=endsample) - begsample + 1; - for j=sample(:)' - dat(spikesel(i),j) = dat(spikesel(i),j) + 1; - end - end - - case {'yokogawa_ave', 'yokogawa_con', 'yokogawa_raw'} - % check that the required low-level toolbox is available - hastoolbox('yokogawa', 1); - dat = read_yokogawa_data(filename, hdr, begsample, endsample, chanindx); - - case 'nmc_archive_k' - dat = read_nmc_archive_k_data(filename, hdr, begsample, endsample, chanindx); - - - otherwise - if strcmp(fallback, 'biosig') && hastoolbox('BIOSIG', 1) - dat = read_biosig_data(filename, hdr, begsample, endsample, chanindx); - else - error('unsupported data format'); - end - -end - -if ~exist('dimord', 'var') - dimord = 'chans_samples'; % almost all low-level readers return the data as 2D array -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% reshape the 2-D or 3-D matrix to a common order of the dimensions -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -switch dimord - case {'chans_samples', 'chans_samples_trials'} - % nothing to do - case 'samples_chans' - dat = permute(dat, [2 1]); - dimord = 'chans_samples'; - case 'samples_chans_trials' - dat = permute(dat, [2 1 3]); - dimord = 'chans_samples_trials'; - case 'trials_samples_chans' - dat = permute(dat, [3 2 1]); - dimord = 'chans_samples_trials'; - case 'trials_chans_samples' - dat = permute(dat, [2 3 1]); - dimord = 'chans_samples_trials'; - otherwise - error('unexpected dimord'); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% convert between 3-D trial based and 2-D continuous output -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if requesttrials && strcmp(dimord, 'chans_samples') - % reformat the continuous representation into trials - nchans = size(dat,1); - nsamples = hdr.nSamples; - ntrials = size(dat,2)/hdr.nSamples; - dat = reshape(dat, [nchans nsamples ntrials]); % convert into a 3-D array - -elseif requestsamples && strcmp(dimord, 'chans_samples_trials') - % reformat the trials into a continuous representation - nchans = size(dat,1); - nsamples = size(dat,2); - ntrials = size(dat,3); - dat = reshape(dat, [nchans nsamples*ntrials]); % convert into a 2-D array - % determine the selection w.r.t. the data as it is on disk - begselection = (begtrial-1)*hdr.nSamples + 1; - endselection = (endtrial )*hdr.nSamples; - % determine the selection w.r.t. the data that has been read in - begselection2 = begsample - begselection + 1; - endselection2 = endsample - begselection + 1; - dat = dat(:,begselection2:endselection2); -end - -if strcmp(dataformat, 'bci2000_dat') - % caching for BCI2000 is handled in the main section and in read_header -else - % implement caching in a data independent way - if cache && requestsamples - % add the new segment to the cache - % FIMXE the cache size should be limited - cachedata.cfg.trl(end+1,:) = [begsample endsample 0]; - cachedata.trial{end+1} = dat; - cachedata.time{end+1} = (1:size(dat,2))/cachedata.fsample; - end -end diff --git a/external/fileio/private/read_eeglabdata.m b/external/fileio/private/read_eeglabdata.m deleted file mode 100644 index 4c2f13e..0000000 --- a/external/fileio/private/read_eeglabdata.m +++ /dev/null @@ -1,118 +0,0 @@ -% read_eeglabdata() - import EEGLAB dataset files -% -% Usage: -% >> dat = read_eeglabdata(filename); -% -% Inputs: -% filename - [string] file name -% -% Optional inputs: -% 'begtrial' - [integer] first trial to read -% 'endtrial' - [integer] last trial to read -% 'chanindx' - [integer] list with channel indices to read -% 'header' - FILEIO structure header -% -% Outputs: -% dat - data over the specified range -% -% Author: Arnaud Delorme, SCCN, INC, UCSD, 2008- - -%123456789012345678901234567890123456789012345678901234567890123456789012 - -% Copyright (C) 2008 Arnaud Delorme, SCCN, INC, UCSD, arno@salk.edu -% -% This program is free software; you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation; either version 2 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program; if not, write to the Free Software -% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -% $Log: read_eeglabdata.m,v $ -% Revision 1.3 2009/07/01 15:35:19 vlalit -% Try several different ways of looking for the data file -% before giving up (fix suggested by Jakob Scherer) -% -% Revision 1.2 2009/02/27 12:03:09 vlalit -% Arno's fix for a bug reported by Antanas Spokas -% -% Revision 1.1 2009/01/30 04:01:19 arno -% *** empty log message *** -% -% Revision 1.2 2008/04/21 18:45:23 roboos -% fixed bug due to sample/trial selection mixup -% only read the selected trials -% -% Revision 1.1 2008/04/18 14:04:48 roboos -% new implementation by Arno, shoudl be tested -% - -function dat = read_eeglabdata(filename, varargin); - -if nargin < 1 - help read_eeglabdata; - return; -end; - -header = keyval('header', varargin); -begsample = keyval('begsample', varargin); -endsample = keyval('endsample', varargin); -begtrial = keyval('begtrial', varargin); -endtrial = keyval('endtrial', varargin); -chanindx = keyval('chanindx', varargin); - -if isempty(header) - header = read_eeglabheader(filename); -end; - -if ischar(header.orig.data) - if strcmpi(header.orig.data(end-2:end), 'set'), - header.ori = load('-mat', filename); - else - - % assuming that the data file is in the current directory - fid = fopen(header.orig.data); - - % assuming the .dat and .set files are located in the same directory - if fid == -1 - pathstr = fileparts(filename); - fid = fopen(fullfile(pathstr, header.orig.data)); - end - - if fid == -1 - fid = fopen(fullfile(header.orig.filepath, header.orig.data)); % - end - - if fid == -1, error('Cannot not find data file'); end; - - % only read the desired trials - if strcmpi(header.orig.data(end-2:end), 'dat') - dat = fread(fid,[header.nSamples*header.nTrials header.nChans],'float32')'; - else - dat = fread(fid,[header.nChans header.nSamples*header.nTrials],'float32')'; - end; - dat = reshape(dat, header.nChans, header.nSamples, header.nTrials); - fclose(fid); - end; -else - dat = header.orig.data; - dat = reshape(dat, header.nChans, header.nSamples, header.nTrials); -end; - -if isempty(begtrial), begtrial = 1; end; -if isempty(endtrial), endtrial = header.nTrials; end; -if isempty(begsample), begsample = 1; end; -if isempty(endsample), endsample = header.nSamples; end; -dat = dat(:,begsample:endsample,begtrial:endtrial); - -if ~isempty(chanindx) - % select the desired channels - dat = dat(chanindx,:,:); -end diff --git a/external/fileio/private/read_eeglabevent.m b/external/fileio/private/read_eeglabevent.m deleted file mode 100644 index 28c0f6a..0000000 --- a/external/fileio/private/read_eeglabevent.m +++ /dev/null @@ -1,93 +0,0 @@ -% read_eeglabevent() - import EEGLAB dataset events -% -% Usage: -% >> header = read_eeglabevent(filename); -% -% Inputs: -% filename - [string] file name -% -% Optional inputs: -% 'header' - FILEIO structure header -% -% Outputs: -% event - FILEIO toolbox event structure -% -% Author: Arnaud Delorme, SCCN, INC, UCSD, 2008- - -%123456789012345678901234567890123456789012345678901234567890123456789012 - -% Copyright (C) 2008 Arnaud Delorme, SCCN, INC, UCSD, arno@salk.edu -% -% This program is free software; you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation; either version 2 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program; if not, write to the Free Software -% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -% $Log: read_eeglabevent.m,v $ -% Revision 1.4 2009/08/29 05:11:31 josdie -% After consultation with Arno, changed so that value (when present) and type fields in EEGlab .set files are treated as being reversed from value and type fields in FieldTrip files. -% -% Revision 1.3 2009/08/09 01:45:24 josdie -% Changed event value to equal EEGlab's event value rather than type. -% -% Revision 1.2 2009/02/02 20:45:34 josdie -% FieldTrip's .value field now set to EEGlab's .type field. FieldTrip's .type field set to 'trigger'. FieldTrip's .duration field set to 0 rather than empty. -% -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.1 2008/04/18 14:04:48 roboos -% new implementation by Arno, shoudl be tested -% - -function event = read_eeglabevent(filename, varargin) - -if nargin < 1 - help read_eeglabheader; - return; -end; - -header = keyval('header', varargin); - -if isempty(header) - header = read_eeglabheader(filename); -end; - -event = []; -oldevent = header.orig.event; -for index = 1:length(oldevent) - event(index).value = num2str( oldevent(index).type ); - if isfield(oldevent,'code') - event(index).type = oldevent(index).code; - elseif isfield(oldevent,'value') - event(index).type = oldevent(index).value; - else - event(index).type = 'trigger'; - end; -if header.nTrials > 1 - event(index).sample = oldevent(index).latency-header.nSamplesPre; - event(index).offset = header.nSamplesPre; - else - event(index).sample = oldevent(index).latency; - event(index).offset = 0; - end; - if isfield(oldevent, 'duration') - event(index).duration = oldevent(index).duration; - else - event(index).duration = 0; - end; -end; diff --git a/external/fileio/private/read_eeglabheader.m b/external/fileio/private/read_eeglabheader.m deleted file mode 100644 index 5ab7e60..0000000 --- a/external/fileio/private/read_eeglabheader.m +++ /dev/null @@ -1,112 +0,0 @@ -% read_eeglabheader() - import EEGLAB dataset files -% -% Usage: -% >> header = read_eeglabheader(filename); -% -% Inputs: -% filename - [string] file name -% -% Outputs: -% header - FILEIO toolbox type structure -% -% Author: Arnaud Delorme, SCCN, INC, UCSD, 2008- - -%123456789012345678901234567890123456789012345678901234567890123456789012 - -% Copyright (C) 2008 Arnaud Delorme, SCCN, INC, UCSD, arno@salk.edu -% -% This program is free software; you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation; either version 2 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program; if not, write to the Free Software -% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -% $Log: read_eeglabheader.m,v $ -% Revision 1.6 2009/08/08 04:07:02 josdie -% Bug in Joe's brain fixed. Change to header.nSamplesPre calculation changed back. -% -% Revision 1.5 2009/08/08 03:17:26 josdie -% Fixed bug that was causing hdr.label to have as many labels as there are time points rather than matching the number of channels. -% -% Revision 1.4 2009/08/08 03:05:29 josdie -% Fixed bug in calculation of header.nSamplesPre. -% -% Revision 1.3 2009/07/01 16:08:21 vlalit -% Fixing a bug in converting channel locations to elec struct (reproted by Jakib Scherer) -% -% Revision 1.2 2009/01/23 15:35:46 roboos -% create default channel names if EEG.chanlocs.labels is missing -% -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.2 2008/04/21 18:45:59 roboos -% fixed bug, ori should be orig -% -% Revision 1.1 2008/04/18 14:04:48 roboos -% new implementation by Arno, shoudl be tested -% - -function header = read_eeglabheader(filename) - -if nargin < 1 - help read_eeglabheader; - return; -end; - -if ~isstruct(filename) - load('-mat', filename); -else - EEG = filename; -end; - -header.Fs = EEG.srate; -header.nChans = EEG.nbchan; -header.nSamples = EEG.pnts; -header.nSamplesPre = -EEG.xmin*EEG.srate; -header.nTrials = EEG.trials; -try - header.label = { EEG.chanlocs.labels }'; -catch - warning('creating default channel names'); - for i=1:header.nChans - header.label{i} = sprintf('chan%03d', i); - end -end -ind = 1; -for i = 1:length( EEG.chanlocs ) - if ~isempty(EEG.chanlocs(i).X) - header.elec.label{ind, 1} = EEG.chanlocs(i).labels; - % this channel has a position - header.elec.pnt(ind,1) = EEG.chanlocs(i).X; - header.elec.pnt(ind,2) = EEG.chanlocs(i).Y; - header.elec.pnt(ind,3) = EEG.chanlocs(i).Z; - ind = ind+1; - end; -end; - -% remove data -% ----------- -%if isfield(EEG, 'datfile') -% if ~isempty(EEG.datfile) -% EEG.data = EEG.datfile; -% end; -%else -% EEG.data = 'in set file'; -%end; -EEG.icaact = []; - -header.orig = EEG; diff --git a/external/fileio/private/read_egis_data.m b/external/fileio/private/read_egis_data.m deleted file mode 100644 index 8db5e45..0000000 --- a/external/fileio/private/read_egis_data.m +++ /dev/null @@ -1,121 +0,0 @@ -function dat = read_egis_data(filename, hdr, begtrial, endtrial, chanindx); - -% READ_EGIS_DATA reads the data from an EGI EGIS format file -% -% Use as -% dat = read_egis_data(filename, hdr, begtrial, endtrial, chanindx); -% where -% filename name of the input file -% hdr header structure, see READ_HEADER -% begtrial first trial to read, mutually exclusive with begsample+endsample -% endtrial last trial to read, mutually exclusive with begsample+endsample -% chanindx list with channel indices to read -% -% This function returns a 3-D matrix of size Nchans*Nsamples*Ntrials. -% Note that EGIS session files are defined as always being epoched. -% For session files the trials are organized with the members of each cell grouped -% together. For average files the "trials" (subjects) are organized with the cells -% also grouped together (e.g., "cell1sub1, cell1sub2, ...). -%_______________________________________________________________________ -% -% -% Modified from EGI's EGI Toolbox with permission 2007-06-28 Joseph Dien - -% $Log: read_egis_data.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.6 2008/11/04 08:16:11 roboos -% previous fix did not work, this one should work, thanks to Joe -% -% -% Revision 1.6 2008/11/03 23:28:00 jdien -% Fixed bug in workaround -% -% Revision 1.5 2008/11/03 10:51:00 jdien -% Workaround for fileheader size field overflow for large files -% -% Revision 1.4 2008/04/21 11:44:58 roboos -% preallocate space for the data (thanks to Joseph) -% -% Revision 1.3 2007/12/20 08:21:22 roboos -% changed from returning a 2d to a 3d matrix, thanks to Joseph -% -% Revision 1.2 2007/07/16 07:24:40 roboos -% only read the desired trials, updated documentation -% -% Revision 1.1 2007/07/04 13:22:06 roboos -% initial implementation by Joseph Dien with some corrections by Robert -% - -fh=fopen([filename],'r'); -if fh==-1 - error('wrong filename') -end -fclose(fh); - -[fhdr,chdr,ename,cnames,fcom,ftext] = read_egis_header(filename); -fh=fopen([filename],'r'); -fhdr(1)=fread(fh,1,'int32'); %BytOrd -[str,maxsize,cEndian]=computer; -if fhdr(1)==16909060 - if cEndian == 'B' - endian = 'ieee-be'; - elseif cEndian == 'L' - endian = 'ieee-le'; - end; -elseif fhdr(1)==67305985 - if cEndian == 'B' - endian = 'ieee-le'; - elseif cEndian == 'L' - endian = 'ieee-be'; - end; -else - error('This is not an EGIS average file.'); -end; - -if fhdr(2) == -1 - fileType = 'ave'; -elseif fhdr(2) == 3 - fileType = 'ses'; -else - error('This is not an EGIS file.'); -end; - -dat=zeros(hdr.nChans,hdr.nSamples,endtrial-begtrial+1); - -%read to end of file header -status=fseek(fh,(130+(2*fhdr(18))+(4*fhdr(19))),'bof'); -status=fseek(fh,2,'cof'); -for loop=1:fhdr(18) - temp=fread(fh,80,'char'); - theName=strtok(temp); - theName=strtok(theName,char(0)); - cnames{loop}=deblank(char(theName))'; - status=fseek(fh,fhdr(24+(loop-1))-80,'cof'); -end -fcom=fread(fh,fhdr(20),'char'); -ftext=fread(fh,fhdr(21),'char'); -fpad=fread(fh,fhdr(22),'char'); -status=fseek(fh,-2,'cof'); - -%read to start of desired data -fseek(fh, ((begtrial-1)*hdr.nChans*hdr.nSamples*2), 'cof'); - -for segment=1:(endtrial-begtrial+1) - dat(:,:,segment) = fread(fh, [hdr.nChans, hdr.nSamples],'int16',endian); -end -dat=dat(chanindx, :,:); - -if fileType == 'ave' - dat=dat/fhdr(12); %convert to microvolts -elseif fileType == 'ses' - dat=dat/5; %convert to microvolts (EGIS sess files created by NetStation use a 5 bins per microvolt scaling) -end; - -fclose(fh); diff --git a/external/fileio/private/read_egis_header.m b/external/fileio/private/read_egis_header.m deleted file mode 100644 index de2141c..0000000 --- a/external/fileio/private/read_egis_header.m +++ /dev/null @@ -1,129 +0,0 @@ -function [fhdr,chdr,ename,cnames,fcom,ftext] = read_egis_header(filename) - -% READ_EGIS_HEADER reads the header information from an EGI EGIS format file -% -% Use as -% [fhdr chdr] = read_egia_header(filename) -% with -% fhdr - the file header information -% chdr - the cell header information -% ename - experiment name -% cnames - cell names -% fcom - comments -% ftext - general text -% and -% filename - the name of the data file -%_______________________________________________________________________ -% -% -% Modified from EGI's EGI Toolbox with permission 2007-06-28 Joseph Dien - -% $Log: read_egis_header.m,v $ -% Revision 1.2 2009/01/22 19:54:32 josdie -% Cell names were being truncated if they contained a space. Fixed. -% -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.3 2008/11/04 08:16:11 roboos -% previous fix did not work, this one should work, thanks to Joe -% -% Revision 1.3 2008/11/03 21:31:00 jdien -% Workaround for fileheader size field overflow for large files -% -% Revision 1.2 2008/09/30 07:47:04 roboos -% replaced all occurences of setstr() with char(), because setstr is deprecated by Matlab -% -% Revision 1.1 2007/07/04 13:22:06 roboos -% initial implementation by Joseph Dien with some corrections by Robert -% - -fh=fopen([filename],'r'); -if fh==-1 - error('wrong filename') -end - -%Prep file for reading -fhdr=zeros(1,23); -status=fseek(fh,0,'bof'); - -%Read in fhdr fields. -fhdr(1)=fread(fh,1,'int32'); %BytOrd -[str,maxsize,cEndian]=computer; -if fhdr(1)==16909060 - if cEndian == 'B' - endian = 'ieee-be'; - elseif cEndian == 'L' - endian = 'ieee-le'; - end; -elseif fhdr(1)==67305985 - if cEndian == 'B' - endian = 'ieee-le'; - elseif cEndian == 'L' - endian = 'ieee-be'; - end; -else - error('This is not an EGIS average file.'); -end; - -fhdr(2)=fread(fh,1,'int16',endian); %HdrVer - -if (fhdr(2) ~= -1) && (fhdr(2) ~= 3) - error('This is not an EGIS average file.'); -end; - -fhdr(3)=fread(fh,1,'uint16',endian); %LHeader -fhdr(4)=fread(fh,1,'uint32',endian); %LData -status=fseek(fh,80,'cof'); %Skip ExptNam -fhdr(5:10)=fread(fh,6,'int16',endian); %RunDate and RunTime - -fhdr(11:23)=fread(fh,13,'int16',endian); %Everything else up to LCellHdr - -fhdr(24:(24+fhdr(18)-1))=fread(fh,fhdr(18),'uint16',endian); %LCellHdr for each cell - -%Read in chdr -chdr=zeros(fhdr(18),5); -status=fseek(fh,(4*fhdr(19)),'cof'); -for loop=1:fhdr(18) - chdr(loop,1)=fread(fh,1,'int16',endian); - status=fseek(fh,80,'cof'); - chdr(loop, 2:5)=(fread(fh,4,'int16',endian))'; - lspectot=(chdr(loop,2)*(chdr(loop,5)/2)); - lastcol=(6+lspectot-1); - if lastcol >= 6 - chdr(loop,lastcol)=0; - chdr(loop,6:lastcol)=(fread(fh,lspectot,'int16',endian))'; - end -end - -%Read experiment name -status=fseek(fh,12,'bof'); -tempstr=fread(fh,80,'char'); -ename=char(tempstr); - -%Read cellnames -status=fseek(fh,(130+(2*fhdr(18))+(4*fhdr(19))),'bof'); -status=fseek(fh,2,'cof'); -for loop=1:fhdr(18) - temp=fread(fh,80,'char'); - theName=strtok(temp,0); - cnames{loop}=deblank(char(theName))'; - status=fseek(fh,fhdr(24+(loop-1))-80,'cof'); -end - -%Read comment -%status=fseek(fh,fhdr(3),'bof'); -%status=fseek(fh,-(fhdr(22)+fhdr(21)+fhdr(20)),'cof'); -fcom=fread(fh,fhdr(20),'char'); - -%Read text -%status=fseek(fh,fhdr(3),'bof'); -%status=fseek(fh,-(fhdr(22)+fhdr(21)),'cof'); -ftext=fread(fh,fhdr(21),'char'); - -fclose(fh); diff --git a/external/fileio/private/read_event.m b/external/fileio/private/read_event.m deleted file mode 100644 index df9d3b2..0000000 --- a/external/fileio/private/read_event.m +++ /dev/null @@ -1,1658 +0,0 @@ -function [event] = read_event(filename, varargin) - -% READ_EVENT reads all events from an EEG/MEG dataset and returns -% them in a well defined structure. It is a wrapper around different -% EEG/MEG file importers, directly supported formats are CTF, Neuromag, -% EEP, BrainVision, Neuroscan and Neuralynx. -% -% Use as -% [event] = read_event(filename, ...) -% -% Additional options should be specified in key-value pairs and can be -% 'eventformat' string -% 'header' structure, see READ_HEADER -% 'detectflank' string, can be 'up', 'down' or 'both' (default = 'up') -% 'trigshift' integer, number of samples to shift from flank to detect trigger value (default = 0) -% Furthermore, you can specify optional arguments as key-value pairs for -% filtering the events, e.g. to select only events of a specific type. See -% FILTER_EVENT for more details. -% -% Some data formats have trigger channels that are sampled continuously with -% the same rate as the electrophysiological data. The default is to detect -% only the up-going TTL flanks. The trigger events will correspond with the -% first sample where the TTL value is up. This behaviour can be changed -% using the 'detectflank' option, which also allows for detecting the -% down-going flank or both. In case of detecting the down-going flank, the -% sample number of the event will correspond with the first sample at which -% the TTF went down, and the value will correspond to the TTL value just -% prior to going down. -% -% This function returns an event structure with the following fields -% event.type = string -% event.sample = expressed in samples, the first sample of a recording is 1 -% event.value = number or string -% event.offset = expressed in samples -% event.duration = expressed in samples -% event.timestamp = expressed in timestamp units, which vary over systems (optional) -% -% The event type and sample fields are always defined, other fields can be empty, -% depending on the type of event file. Events are sorted by the sample on -% which they occur. After reading the event structure, you can use the -% following tricks to extract information about those events in which you -% are interested. -% -% Determine the different event types -% unique({event.type}) -% -% Get the index of all trial events -% find(strcmp('trial', {event.type})) -% -% Make a vector with all triggers that occurred on the backpanel -% [event(find(strcmp('backpanel trigger', {event.type}))).value] -% -% Find the events that occurred in trial 26 -% t=26; samples_trials = [event(find(strcmp('trial', {event.type}))).sample]; -% find([event.sample]>samples_trials(t) & [event.sample]char) into uint8=>char to ensure that the -% chars are read as 8 bits and not as extended 16 bit characters. The -% 16 bit handling causes problems on some internationalized OS/Matlab -% combinations. -% -% the help of fread specifies "If the precision is 'char' or 'char*1', MATLAB -% reads characters using the encoding scheme associated with the file. -% See FOPEN for more information". -% -% Revision 1.70 2008/09/25 12:02:22 roboos -% fixed FIL type of events for the new ctf reader (thanks to Vladimir) -% -% Revision 1.69 2008/07/24 08:44:20 roboos -% added initial support for nimh_cortex, not yet complete -% -% Revision 1.68 2008/06/30 15:35:20 roboos -% changed ns_eeg events following a suggestion by Monika Mellem -% -% Revision 1.67 2008/06/20 07:25:56 roboos -% added check for presence of BCI2000 load_bcidat mex file -% -% Revision 1.66 2008/06/18 08:24:33 roboos -% added support for BCI2000 -% -% Revision 1.65 2008/06/18 06:21:59 roboos -% added support for other event.value types (i.e. int/single/double etc) by introducing a wordsize cell-array -% -% Revision 1.64 2008/06/03 15:29:06 jansch -% changed extracting trigger index from original hdr into extracting it from -% the labels, for 4D data -% -% Revision 1.63 2008/05/14 15:58:33 roboos -% typecast to uint32 for tsl and tsh obtained from neuralynx_dma file (*.nrd) -% -% Revision 1.62 2008/05/13 16:48:23 roboos -% added option trigshift (default = 0) for cases where the trigger value should be assigned from a sample not directly after/before the upgoing/downgoing flank -% -% Revision 1.61 2008/05/06 13:29:46 vlalit -% Changed the code to only give a warning and not an error for Biosemi when detectflank = 'both' is specified and change it to 'up'. -% -% Revision 1.60 2008/05/02 14:23:04 vlalit -% Added readers for SPM5 and SPM8 EEG formats -% -% Revision 1.59 2008/04/29 13:58:53 roboos -% switched to read_trigger helper function for ctf, neuromag and bti -% -% Revision 1.58 2008/04/21 11:50:52 roboos -% added support for egi_sbin, thanks to Joseph Dien -% -% Revision 1.57 2008/04/18 14:07:45 roboos -% added eeglab_set -% -% Revision 1.56 2008/02/20 12:32:00 roboos -% allow empty events from buffer -% -% Revision 1.55 2008/02/19 10:08:13 roboos -% added support for fcdc_buffer -% -% Revision 1.54 2008/01/31 20:13:46 roboos -% On line 291 the cell element 4D was added to the existing case -% designed for the handling of 4D_bti data. This is necessary to -% allow this identified filetype to cause execution of this case. -% [thanks to Gavin] -% -% Revision 1.53 2008/01/30 10:40:54 roboos -% moved catevent to seperate function and renamed to appendevent -% -% Revision 1.52 2008/01/30 08:42:13 roboos -% fixed two bugs for ttl.bin in online session with Thilo (both were due to the code being untested) -% -% Revision 1.51 2007/12/20 19:06:57 roboos -% Added filtering base on event number (minnumber and maxnumber), implemented in low level for neuralynx_nev and for the rest of the formats in filter event. If event.number is not present everything still should work as it used to. -% -% Revision 1.50 2007/12/19 15:24:37 roboos -% fixed typo, ttl should be bin -% -% Revision 1.49 2007/12/19 11:25:59 roboos -% fixed typo, added "(", thanks to Mahdi -% -% Revision 1.48 2007/12/19 09:29:29 roboos -% implmenented events for neuralynx_sdma file, and merged it with the dma, ttl and bin formats -% cleaned up the consistent handling of the ttl values for dma, ttl and bin formats -% -% Revision 1.47 2007/12/18 16:57:35 roboos -% use value=trigger instead of ttl (which was a change in the previous commit) to avoid breaking Thilo's scripts -% -% Revision 1.46 2007/12/18 16:51:34 roboos -% added some filtering options -% some minor changes to neuralynx_nev, related to the changes in teh low level function -% added support for neuralynx_bin, which is treated similar as ttl and dma -% -% Revision 1.45 2007/12/17 12:59:52 roboos -% reimplemented the event detection for ttl and dma after discussion with Thilo, also merged the two implementations -% -% Revision 1.44 2007/12/17 08:24:28 roboos -% added support for nexstim_nxe, thanks to Vladimir -% the low-level code has not been tested by myself -% -% Revision 1.43 2007/12/12 16:51:07 roboos -% made a faster implementation for a nev file inside a neuralynx_ds dataset directory, but strings are not supported any more -% -% Revision 1.42 2007/12/12 11:29:06 roboos -% chedk for presence of timestamp prior to trying to concatenate events -% -% Revision 1.41 2007/12/12 11:10:55 roboos -% moved declaration of global variable to the begin of the function -% -% Revision 1.40 2007/12/12 11:09:22 roboos -% added selective reading of events for some files (dma, ttl, bdf, 4d, ctf partially) -% -% Revision 1.39 2007/11/07 10:49:06 roboos -% cleaned up the reading and writing from/to mysql database, using db_xxx helper functions (see mysql directory) -% -% Revision 1.38 2007/11/05 17:02:07 roboos -% some cosmetic changes, nothing functional -% -% Revision 1.37 2007/10/16 12:34:12 roboos -% use recursion to read from multiple event sources -% implemented fcdc_global -% -% Revision 1.36 2007/10/02 16:07:13 roboos -% fixed conversion of negative status values and reasignment of bit24 (thanks to Philip) -% -% Revision 1.35 2007/10/02 09:28:06 roboos -% removed teh double rtepresentatino of trigger for bdf, since STATUS is also good enough -% -% Revision 1.34 2007/10/02 09:13:43 roboos -% biosemi_bdf: make sure that the sign bit is propperly re-inserted as bit24 for the status channel -% -% Revision 1.33 2007/10/01 13:43:21 roboos -% reimplemented the biosemi bdf trigger detection, now also for the status bits -% -% Revision 1.32 2007/09/13 09:49:34 roboos -% moved declaration of persistent variale to beginning -% added inactive piece of code for bdf (see NICI version) -% -% Revision 1.31 2007/08/21 17:00:57 chrhes -% updated some documentation, removed the commented-out section of code to do -% with the event filtering options; these are used "as is" in the call to -% FILTER_EVENT at the end of the function -% -% Revision 1.30 2007/08/01 12:24:22 roboos -% added filename as argument to read_shm_event, added comments, disabled unused -% keyval filtering arguments -% -% Revision 1.29 2007/08/01 09:57:01 roboos -% moved all code related to ctf shared memory to seperate functions -% -% Revision 1.28 2007/07/30 12:14:59 roboos -% updated documentation for filtering -% implemented filtering for ctf_shm -% -% Revision 1.27 2007/07/27 12:17:20 roboos -% fixed big in ctf raw trigger channel, which caused a trigger with value=1 not -% to be detected implemented support for ctf_shm -% reuse the file header if specified as optional input argument and do not read -% again -% -% Revision 1.26 2007/07/04 13:20:51 roboos -% added support for egi_egis/egia, thanks to Joseph Dien -% -% Revision 1.25 2007/06/13 13:33:54 roboos -% changed the mysql code to reflect the updated event table structure -% removed type and subtype from the insert query -% added a call to filter_event at the end of the function -% -% Revision 1.24 2007/06/13 09:57:32 roboos -% only test for presence of fields if event is not empty -% fixed bug in mysql, in case event table is empty -% -% Revision 1.23 2007/06/13 08:06:21 roboos -% updated help -% -% Revision 1.22 2007/06/12 19:35:52 roboos -% implemented support for reading events from mysql database -% -% Revision 1.21 2007/06/11 13:52:24 roboos -% split the event reading from neuralynx_dma and neuralynx_ttl -% read timestamps from tsl/tsh files, optionally use pre-specified header to -% correct the sample numbers -% -% Revision 1.20 2007/06/07 12:44:28 chrhes -% updated some documentation -% -% Revision 1.19 2007/06/06 21:55:37 chrhes -% fixed a small bug to do with a string comparison -% -% Revision 1.18 2007/06/06 18:19:07 chrhes -% added initial implementation of reading events from the serial port -% -% Revision 1.17 2007/06/06 07:12:48 roboos -% switched to using filetype_check_uri for detection and parsing of filename -% -% Revision 1.16 2007/05/31 09:53:21 roboos -% implemented reading events from a plain matlab file -% -% Revision 1.15 2007/05/31 09:15:13 roboos -% added placeholder for tcpsocket -% -% Revision 1.14 2007/05/15 15:01:44 roboos -% changed handling of the seperate brainvision header and marker file -% -% Revision 1.13 2006/12/13 15:40:10 roboos -% renamed Parallel_in into ttl for neuralynx_dma -% renamed the function read_neuralynx_event into read_neuralynx_nev (consistent -% with the file extension) -% -% Revision 1.12 2006/12/04 10:37:27 roboos -% added support for ns_avg -% -% Revision 1.11 2006/09/18 21:51:38 roboos -% implemented support for fcdc_matbin, i.e. a dataset consisting of a matlab -% file with header and events and a seperate binary datafile -% -% Revision 1.10 2006/09/18 14:22:54 roboos -% implemented support for 4D-BTi dataformat -% -% Revision 1.9 2006/08/28 10:13:03 roboos -% use seperate filetype_check_extension function instead of subfunction, removed -% subfunction -% -% Revision 1.8 2006/07/26 07:51:33 roboos -% fixed bug for brainvision_vmrk in case second field is empty (thanks to -% Stephan Bickel) -% -% Revision 1.7 2006/06/26 08:46:37 roboos -% read stim channels from CTF as continuous -% -% Revision 1.6 2006/06/22 07:54:34 roboos -% do not read the complete data for ns_cnt but only the header (includes the -% events), thanks to Gijs -% -% Revision 1.5 2006/06/20 11:23:00 roboos -% fixed bug for ctf, sensSype was moved to hdr.orig -% -% Revision 1.4 2006/06/19 10:32:16 roboos -% added documentation -% -% Revision 1.3 2006/06/19 08:14:17 roboos -% updated documentation -% -% Revision 1.2 2006/06/07 10:16:47 roboos -% changed one occurence of read_fcdc_header into read_header -% -% Revision 1.1 2006/06/07 09:32:20 roboos -% new implementation based on the read_fcdc_xxx functions, now with -% variable (key-val) input arguments, changed the control structure -% in the rpobram (switch instead of ifs), allow the user to specify -% the file format, allow the user to specify either a sample selection -% or a block selection. The reading functionality should not have -% changed compared to the read_fcdc_xxx versions. -% - -persistent sock % for fcdc_tcp - -global event_queue % for fcdc_global -persistent db_blob % for fcdc_mysql -if isempty(db_blob) - db_blob = 0; -end - -if iscell(filename) - % use recursion to read from multiple event sources - event = []; - for i=1:numel(filename) - tmp = read_event(filename{i}, varargin{:}); - event = appendevent(event(:), tmp(:)); - end - return -end - -% get the options -eventformat = keyval('eventformat', varargin); -hdr = keyval('header', varargin); -detectflank = keyval('detectflank', varargin); % up, down or both -trigshift = keyval('trigshift', varargin); % default is assigned in subfunction -headerformat = keyval('headerformat', varargin); -dataformat = keyval('dataformat', varargin); - -% this allows to read only events in a certain range, supported for selected data formats only -flt_type = keyval('type', varargin); -flt_value = keyval('value', varargin); -flt_minsample = keyval('minsample', varargin); -flt_maxsample = keyval('maxsample', varargin); -flt_mintimestamp = keyval('mintimestamp', varargin); -flt_maxtimestamp = keyval('maxtimestamp', varargin); -flt_minnumber = keyval('minnumber', varargin); -flt_maxnumber = keyval('maxnumber', varargin); - - -% determine the filetype -if isempty(eventformat) - eventformat = filetype(filename); -end - -% default is to search only for rising or up-going flanks -if isempty(detectflank) - detectflank = 'up'; -end - -switch eventformat - case 'brainvision_vhdr' - % read the headerfile belonging to the dataset and try to determine the corresponding markerfile - eventformat = 'brainvision_vmrk'; - hdr = read_brainvision_vhdr(filename); - % replace the filename with the filename of the markerfile - if ~isfield(hdr, 'MarkerFile') || isempty(hdr.MarkerFile) - filename = []; - else - [p, f, e] = fileparts(filename); - filename = fullfile(p, hdr.MarkerFile); - end -end - -% start with an empty event structure -event = []; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% read the events with the low-level reading function -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -switch eventformat - - case 'fcdc_global' - event = event_queue; - - case {'4d' '4d_pdf', '4d_m4d', '4d_xyz'} - if isempty(hdr) - hdr = read_header(filename); - end - % add the trials to the event structure - for i=1:hdr.nTrials - event(end+1).type = 'trial'; - event(end ).sample = (i-1)*hdr.nSamples + 1; - event(end ).value = []; - event(end ).offset = -hdr.nSamplesPre; - event(end ).duration = hdr.nSamples; - end - % read the trigger channel and do flank detection - trgindx = match_str(hdr.label, 'TRIGGER'); - if isfield(hdr, 'orig') && isfield(hdr.orig, 'config_data') && strcmp(hdr.orig.config_data.site_name, 'Glasgow'), - trigger = read_trigger(filename, 'header', hdr, 'begsample', flt_minsample, 'endsample', flt_maxsample, 'chanindx', trgindx, 'detectflank', detectflank, 'trigshift', trigshift,'fix4dglasgow',1); - else - trigger = read_trigger(filename, 'header', hdr, 'begsample', flt_minsample, 'endsample', flt_maxsample, 'chanindx', trgindx, 'detectflank', detectflank, 'trigshift', trigshift,'fix4dglasgow',0); - end - event = appendevent(event, trigger); - - respindx = match_str(hdr.label, 'RESPONSE'); - if ~isempty(respindx) - response = read_trigger(filename, 'header', hdr, 'begsample', flt_minsample, 'endsample', flt_maxsample, 'chanindx', respindx, 'detectflank', detectflank, 'trigshift', trigshift); - event = appendevent(event, response); - end - - case 'bci2000_dat' - % this requires the load_bcidat mex file to be present on the path - hastoolbox('BCI2000', 1); - if isfield(hdr.orig, 'signal') && isfield(hdr.orig, 'states') - % assume that the complete data is stored in the header, this speeds up subsequent read operations - signal = hdr.orig.signal; - states = hdr.orig.states; - parameters = hdr.orig.parameters; - total_samples = hdr.orig.total_samples; - else - [signal, states, parameters, total_samples] = load_bcidat(filename); - end - - list = fieldnames(states); - % loop over all states and detect the flanks, the following code was taken from read_trigger - for i=1:length(list) - channel = list{i}; - trig = double(getfield(states, channel)); - pad = trig(1); - trigshift = 0; - begsample = 1; - - switch detectflank - case 'up' - % convert the trigger into an event with a value at a specific sample - for j=find(diff([pad trig(:)'])>0) - event(end+1).type = channel; - event(end ).sample = j + begsample - 1; % assign the sample at which the trigger has gone down - event(end ).value = trig(j+trigshift); % assign the trigger value just _after_ going up - end - case 'down' - % convert the trigger into an event with a value at a specific sample - for j=find(diff([pad trig(:)'])<0) - event(end+1).type = channel; - event(end ).sample = j + begsample - 1; % assign the sample at which the trigger has gone down - event(end ).value = trig(j-1-trigshift); % assign the trigger value just _before_ going down - end - case 'both' - % convert the trigger into an event with a value at a specific sample - for j=find(diff([pad trig(:)'])>0) - event(end+1).type = [channel '_up']; % distinguish between up and down flank - event(end ).sample = j + begsample - 1; % assign the sample at which the trigger has gone down - event(end ).value = trig(j+trigshift); % assign the trigger value just _after_ going up - end - % convert the trigger into an event with a value at a specific sample - for j=find(diff([pad trig(:)'])<0) - event(end+1).type = [channel '_down']; % distinguish between up and down flank - event(end ).sample = j + begsample - 1; % assign the sample at which the trigger has gone down - event(end ).value = trig(j-1-trigshift); % assign the trigger value just _before_ going down - end - otherwise - error('incorrect specification of ''detectflank'''); - end - end - - case {'besa_avr', 'besa_swf'} - if isempty(hdr) - hdr = read_header(filename); - end - event(end+1).type = 'average'; - event(end ).sample = 1; - event(end ).duration = hdr.nSamples; - event(end ).offset = -hdr.nSamplesPre; - event(end ).value = []; - - case {'biosemi_bdf', 'bham_bdf'} - % read the header, required to determine the stimulus channels and trial specification - if isempty(hdr) - hdr = read_header(filename); - end - - % specify the range to search for triggers, default is the complete file - if ~isempty(flt_minsample) - begsample = flt_minsample; - else - begsample = 1; - end - if ~isempty(flt_maxsample) - endsample = flt_maxsample; - else - endsample = hdr.nSamples*hdr.nTrials; - end - - if ~strcmp(detectflank, 'up') - if strcmp(detectflank, 'both') - warning('only up-going flanks are supported for Biosemi'); - detectflank = 'up'; - else - error('only up-going flanks are supported for Biosemi'); - % FIXME the next section on trigger detection should be merged with the - % READ_CTF_TRIGGER (which also does masking with bit-patterns) into the - % READ_TRIGGER function - end - end - - % find the STATUS channel and read the values from it - schan = find(strcmpi(hdr.label,'STATUS')); - sdata = read_data(filename, 'header', hdr, 'begsample', begsample, 'endsample', endsample, 'chanindx', schan); - - % find indices of negative numbers - bit24i = find(sdata < 0); - % make number positive and preserve bits 0-22 - sdata(bit24i) = bitcmp(abs(sdata(bit24i))-1,24); - % re-insert the sign bit on its original location, i.e. bit24 - sdata(bit24i) = sdata(bit24i)+(2^(24-1)); - % typecast the data to ensure that the status channel is represented in 32 bits - sdata = uint32(sdata); - - byte1 = 2^8 - 1; - byte2 = 2^16 - 1 - byte1; - byte3 = 2^24 - 1 - byte1 - byte2; - - % get the respective status and trigger bits - trigger = bitand(sdata, bitor(byte1, byte2)); % contained in the lower two bytes - epoch = int8(bitget(sdata, 16+1)); - cmrange = int8(bitget(sdata, 20+1)); - battery = int8(bitget(sdata, 22+1)); - - % determine when the respective status bits go up or down - flank_trigger = diff([0 trigger]); - flank_epoch = diff([0 epoch ]); - flank_cmrange = diff([0 cmrange]); - flank_battery = diff([0 battery]); - - for i=find(flank_trigger>0) - event(end+1).type = 'STATUS'; - event(end ).sample = i + begsample - 1; - event(end ).value = double(trigger(i)); - end - - for i=find(flank_epoch==1) - event(end+1).type = 'Epoch'; - event(end ).sample = i; - end - - for i=find(flank_cmrange==1) - event(end+1).type = 'CM_in_range'; - event(end ).sample = i; - end - - for i=find(flank_cmrange==-1) - event(end+1).type = 'CM_out_of_range'; - event(end ).sample = i; - end - - for i=find(flank_battery==1) - event(end+1).type = 'Battery_low'; - event(end ).sample = i; - end - - for i=find(flank_battery==-1) - event(end+1).type = 'Battery_ok'; - event(end ).sample = i; - end - - case 'brainvision_vmrk' - fid=fopen(filename,'rt'); - if fid==-1, - error('cannot open BrainVision marker file') - end - line = []; - while ischar(line) || isempty(line) - line = fgetl(fid); - if ~isempty(line) && ~(isnumeric(line) && line==-1) - if strncmpi(line, 'Mk', 2) - % this line contains a marker - tok = tokenize(line, '=', 0); % do not squeeze repetitions of the seperator - if length(tok)~=2 - warning('skipping unexpected formatted line in BrainVision marker file'); - else - % the line looks like "MkXXX=YYY", which is ok - % the interesting part now is in the YYY, i.e. the second token - tok = tokenize(tok{2}, ',', 0); % do not squeeze repetitions of the seperator - if isempty(tok{1}) - tok{1} = []; - end - if isempty(tok{2}) - tok{2} = []; - end - event(end+1).type = tok{1}; - event(end ).value = tok{2}; - event(end ).sample = str2num(tok{3}); - event(end ).duration = str2num(tok{4}); - end - end - end - end - fclose(fid); - - case 'ced_son' - % check that the required low-level toolbox is available - hastoolbox('neuroshare', 1); - orig = read_ced_son(filename,'readevents','yes'); - event = struct('type', {orig.events.type},... - 'sample', {orig.events.sample},... - 'value', {orig.events.value},... - 'offset', {orig.events.offset},... - 'duration', {orig.events.duration}); - - case {'ctf_ds', 'ctf_meg4', 'ctf_res4', 'ctf_old'} - % obtain the dataset name - if filetype(filename, 'ctf_meg4') || filetype(filename, 'ctf_res4') - filename = fileparts(filename); - end - [path, name, ext] = fileparts(filename); - headerfile = fullfile(path, [name ext], [name '.res4']); - datafile = fullfile(path, [name ext], [name '.meg4']); - classfile = fullfile(path, [name ext], 'ClassFile.cls'); - markerfile = fullfile(path, [name ext], 'MarkerFile.mrk'); - - % in case ctf_old was specified as eventformat, the other reading functions should also know about that - if strcmp(eventformat, 'ctf_old') - dataformat = 'ctf_old'; - headerformat = 'ctf_old'; - end - - % read the header, required to determine the stimulus channels and trial specification - if isempty(hdr) - hdr = read_header(headerfile, 'headerformat', headerformat); - end - - try - % read the trigger codes from the STIM channel, usefull for (pseudo) continuous data - % this splits the trigger channel into the lowers and highest 16 bits, - % corresponding with the front and back panel of the electronics cabinet at the Donders Centre - [backpanel, frontpanel] = read_ctf_trigger(filename); - for i=find(backpanel(:)') - event(end+1).type = 'backpanel trigger'; - event(end ).sample = i; - event(end ).value = backpanel(i); - end - for i=find(frontpanel(:)') - event(end+1).type = 'frontpanel trigger'; - event(end ).sample = i; - event(end ).value = frontpanel(i); - end - end - - % determine the trigger channels from the header - if isfield(hdr, 'orig') && isfield(hdr.orig, 'sensType') - origSensType = hdr.orig.sensType; - elseif isfield(hdr, 'orig') && isfield(hdr.orig, 'res4') - origSensType = [hdr.orig.res4.senres.sensorTypeIndex]; - else - origSensType = []; - end - % meg channels are 5, refmag 0, refgrad 1, adcs 18, trigger 11, eeg 9 - trigchanindx = find(origSensType==11); - if ~isempty(trigchanindx) - % read the trigger channel and do flank detection - trigger = read_trigger(filename, 'header', hdr, 'begsample', flt_minsample, 'endsample', flt_maxsample, 'chanindx', trigchanindx, 'dataformat', dataformat, 'detectflank', detectflank, 'trigshift', trigshift, 'fixctf', 1); - event = appendevent(event, trigger); - end - - % make an event for each trial as defined in the header - for i=1:hdr.nTrials - event(end+1).type = 'trial'; - event(end ).sample = (i-1)*hdr.nSamples + 1; - event(end ).offset = -hdr.nSamplesPre; - event(end ).duration = hdr.nSamples; - event(end ).value = []; - end - - % read the classification file and make an event for each classified trial - [condNumbers,condLabels] = read_ctf_cls(classfile); - if ~isempty(condNumbers) - Ncond = length(condLabels); - for i=1:Ncond - for j=1:length(condNumbers{i}) - event(end+1).type = 'classification'; - event(end ).value = condLabels{i}; - event(end ).sample = (condNumbers{i}(j)-1)*hdr.nSamples + 1; - event(end ).offset = -hdr.nSamplesPre; - event(end ).duration = hdr.nSamples; - end - end - end - - if exist(markerfile,'file') - % read the marker file and make an event for each marker - % this depends on the readmarkerfile function that I got from Tom Holroyd - % I have not tested this myself extensively, since at the FCDC we - % don't use the marker files - mrk = readmarkerfile(filename); - for i=1:mrk.number_markers - for j=1:mrk.number_samples(i) - % determine the location of the marker, expressed in samples - trialnum = mrk.trial_times{i}(j,1); - synctime = mrk.trial_times{i}(j,2); - begsample = (trialnum-1)*hdr.nSamples + 1; % of the trial, relative to the start of the datafile - endsample = (trialnum )*hdr.nSamples; % of the trial, relative to the start of the datafile - offset = round(synctime*hdr.Fs); % this is the offset (in samples) relative to time t=0 for this trial - offset = offset + hdr.nSamplesPre; % and time t=0 corrsponds with the nSamplesPre'th sample - % store this marker as an event - event(end+1).type = mrk.marker_names{i}; - event(end ).value = []; - event(end ).sample = begsample + offset; - event(end ).duration = 0; - event(end ).offset = offset; - end - end - end - - case 'ctf_shm' - % contact Robert Oostenveld if you are interested in real-time acquisition on the CTF system - % read the events from shared memory - event = read_shm_event(filename, varargin{:}); - - case 'eeglab_set' - event = read_eeglabevent(filename, 'header', hdr); - - case 'spmeeg_mat' - event = read_spmeeg_event(filename, 'header', hdr); - - case 'eep_avr' - % check that the required low-level toolbox is available - hastoolbox('eeprobe', 1); - % the headerfile and datafile are the same - if isempty(hdr) - hdr = read_header(filename); - end - event(end+1).type = 'average'; - event(end ).sample = 1; - event(end ).duration = hdr.nSamples; - event(end ).offset = -hdr.nSamplesPre; - event(end ).value = []; - - case 'eep_cnt' - % check that the required low-level toolbox is available - hastoolbox('eeprobe', 1); - % try to read external trigger file in EEP format - trgfile = [filename(1:(end-3)), 'trg']; - if exist(trgfile, 'file') - if isempty(hdr) - hdr = read_header(filename); - end - tmp = read_eep_trg(trgfile); - % translate the EEProbe trigger codes to events - for i=1:length(tmp) - event(i).type = 'trigger'; - event(i).sample = round((tmp(i).time/1000) * hdr.Fs) + 1; % convert from ms to samples - event(i).value = tmp(i).code; - event(i).offset = 0; - event(i).duration = 0; - end - else - warning('no triggerfile was found'); - end - - case 'egi_egis' - if isempty(hdr) - hdr = read_header(filename); - end - fhdr = hdr.orig.fhdr; - chdr = hdr.orig.chdr; - ename = hdr.orig.ename; - cnames = hdr.orig.cnames; - fcom = hdr.orig.fcom; - ftext = hdr.orig.ftext; - eventCount=0; - for cell=1:fhdr(18) - for trial=1:chdr(cell,2) - eventCount=eventCount+1; - event(eventCount).type = 'trial'; - event(eventCount).sample = (eventCount-1)*hdr.nSamples + 1; - event(eventCount).offset = -hdr.nSamplesPre; - event(eventCount).duration = hdr.nSamples; - event(eventCount).value = cnames{cell}; - end - end - - case 'egi_egia' - if isempty(hdr) - hdr = read_header(filename); - end - fhdr = hdr.orig.fhdr; - chdr = hdr.orig.chdr; - ename = hdr.orig.ename; - cnames = hdr.orig.cnames; - fcom = hdr.orig.fcom; - ftext = hdr.orig.ftext; - eventCount=0; - for cell=1:fhdr(18) - for subject=1:chdr(cell,2) - eventCount=eventCount+1; - event(eventCount).type = 'trial'; - event(eventCount).sample = (eventCount-1)*hdr.nSamples + 1; - event(eventCount).offset = -hdr.nSamplesPre; - event(eventCount).duration = hdr.nSamples; - event(eventCount).value = ['S' sprintf('%03d',subject) cnames{cell}]; - end - end - - case 'egi_sbin' - if ~exist('segHdr','var') - [EventCodes, segHdr, eventData] = read_sbin_events(filename); - end - if ~exist('header_array','var') - [header_array, CateNames, CatLengths, preBaseline] = read_sbin_header(filename); - end - if isempty(hdr) - hdr = read_header(filename,'headerformat','egi_sbin'); - end - version = header_array(1); - unsegmented = ~mod(version, 2); - - eventCount=0; - if unsegmented - tmp = zeros(1,size(eventData,2)); - for k = 1:size(eventData,1) - sel = find(eventData(k,:)==1 & [0 eventData(k,1:end-1)==0]); - tmp(sel) = k; - end - sel = find(tmp); - for k = 1:length(sel) - event(k).sample = sel(k); - event(k).offset = []; - event(k).duration = 0; - event(k).type = 'trigger'; - event(k).value = char(EventCodes(tmp(sel(k)),:)); - end - else - for theEvent=1:size(eventData,1) - for segment=1:hdr.nTrials - if any(eventData(theEvent,((segment-1)*hdr.nSamples +1):segment*hdr.nSamples)) - eventCount=eventCount+1; - event(eventCount).sample = (segment-1)*hdr.nSamples + 1; - event(eventCount).offset = -min(find(eventData(theEvent,((segment-1)*hdr.nSamples +1):segment*hdr.nSamples)))+1; - event(eventCount).duration = length(find(eventData(theEvent,((segment-1)*hdr.nSamples +1):segment*hdr.nSamples )>0))-1; - if event(eventCount).duration == 0 - event(eventCount).type = 'trigger'; - else - event(eventCount).type = 'trial'; - end; - event(eventCount).value = char(EventCodes(theEvent,:)); - end - end - end - end - - for segment=1:hdr.nTrials % cell information - eventCount=eventCount+1; - event(eventCount).type = 'trial'; - event(eventCount).sample = (segment-1)*hdr.nSamples + 1; - event(eventCount).offset = -hdr.nSamplesPre; - event(eventCount).duration = hdr.nSamples; - if unsegmented, - event(eventCount).value = []; - else - event(eventCount).value = char([CateNames{segHdr(segment,1)}(1:CatLengths(segHdr(segment,1)))]); - end - end - - case 'fcdc_buffer' - % read from a networked buffer for realtime analysis - [host, port] = filetype_check_uri(filename); - - evt = buffer('get_evt', [], host, port); % indices should be zero-offset - % FIXME it should be possible to specify event numbers - - type = { - 'char' - 'uint8' - 'uint16' - 'uint32' - 'uint64' - 'int8' - 'int16' - 'int32' - 'int64' - 'single' - 'double' - }; - - wordsize = { - 1 % 'char' - 1 % 'uint8' - 2 % 'uint16' - 4 % 'uint32' - 8 % 'uint64' - 1 % 'int8' - 2 % 'int16' - 4 % 'int32' - 8 % 'int64' - 4 % 'single' - 8 % 'double' - }; - - for i=1:length(evt) - % convert the field "type" into the Matlab representation - this_type = type{evt(i).type_type+1}; - this_size = wordsize{evt(i).type_type+1} * evt(i).type_numel; - sel = 1:this_size; - if strcmp(this_type, 'char') - event(i).type = char(evt(i).buf(sel)); - else - event(i).type = typecast(evt(i).buf(sel), this_type); - end - - % convert the field "value" into the Matlab representation - this_type = type{evt(i).value_type+1}; - this_size = wordsize{evt(i).value_type+1} * evt(i).value_numel; - sel = sel(end) + (1:this_size); - if strcmp(this_type, 'char') - event(i).value = char(evt(i).buf(sel)); - else - event(i).value = typecast(evt(i).buf(sel), this_type); - end - - % the other fields are simple, because they have a fixed type and only a single elements - event(i).sample = evt(i).sample; - event(i).offset = evt(i).offset; - event(i).duration = evt(i).duration; - end - - case 'fcdc_matbin' - % this is multiplexed data in a *.bin file, accompanied by a matlab file containing the header and event - [path, file, ext] = fileparts(filename); - filename = fullfile(path, [file '.mat']); - % read the events from the Matlab file - tmp = load(filename, 'event'); - event = tmp.event; - - - case 'fcdc_fifo' - - - fifo = filetype_check_uri(filename); - - if ~exist(fifo,'file') - warning('the FIFO %s does not exist; attempting to create it', fifo); - system(sprintf('mkfifo -m 0666 %s',fifo)); - end - - fid = fopen(fifo, 'r'); - msg = fread(fid, inf, 'uint8'); - fclose(fid); - - try - event = mxDeserialize(uint8(msg)); - catch - warning(lasterr); - end - - case 'fcdc_tcp' - % requires tcp/udp/ip-toolbox - hastoolbox('TCP_UDP_IP', 1); - [host, port] = filetype_check_uri(filename); - if isempty(sock) - sock=pnet('tcpsocket',port); - end - con = pnet(sock, 'tcplisten'); - if con~=-1 - try - pnet(con,'setreadtimeout',10); - % read packet - msg=pnet(con,'readline'); %,1000,'uint8','network'); - if ~isempty(msg) - event = mxDeserialize(uint8(str2num(msg))); - end -% catch -% warning(lasterr); - end - pnet(con,'close'); - end - con = []; - - case 'fcdc_udp' - % requires tcp/udp/ip-toolbox - hastoolbox('TCP_UDP_IP', 1); - [host, port] = filetype_check_uri(filename); - try - % read from localhost - udp=pnet('udpsocket',port); - % Wait/Read udp packet to read buffer - len=pnet(udp,'readpacket'); - if len>0, - % if packet larger then 1 byte then read maximum of 1000 doubles in network byte order - msg=pnet(udp,'read',1000,'uint8'); - if ~isempty(msg) - event = mxDeserialize(uint8(msg)); - end - end - catch - warning(lasterr); - end - % On break or error close connection - pnet(udp,'close'); - - case 'fcdc_serial' - % serial port on windows or linux platform - [port, opt] = filetype_check_uri(filename); - % determine whether any serial port objects are already associated with the - % target serial port - s = []; - temp = instrfind; - if isa(temp,'instrument') - % find all serial ports - i1 = strcmpi({temp(:).Type},'serial'); - if any(i1) - % find all serial ports whose name matches that of the specified port - i2 = strmatch(lower(port),lower({temp(find(i1)).Name})); - % set s to the (first) matching port if present (and open if necessary) - if ~isempty(i2) - s = temp(i2(1)); - if ~strcmp(s.Status,'open'), fopen(s); end; - end - end - end - % create, configure a serial port object if necessary and open the port - if ~isa(s,'serial') - s = serial(port); - if ~isempty(opt) && iscell(opt), s = set(s,opt); end; - fopen(s); - end - % try to read a message from the serial port - msg = []; - % FIXME: this currently assumes that all messages are terminated by the - % "newline" character (ascii character 10) - try - msg = fscanf(s,'%s\n'); - end; - % convert message to event structure - event = msg2struct(msg); - - case 'fcdc_mysql' - % read from a MySQL server listening somewhere else on the network - db_open(filename); - if db_blob - event = db_select_blob('fieldtrip.event', 'msg'); - else - event = db_select('fieldtrip.event', {'type', 'value', 'sample', 'offset', 'duration'}); - end - - case 'itab_raw' - error('suppoport for events in this fileformat is not yet implemented') - - case 'matlab' - % read the events from a normal Matlab file - tmp = load(filename, 'event'); - event = tmp.event; - - case {'mpi_ds', 'mpi_dap'} - if isempty(hdr) - hdr = read_header(filename); - end - % determine the DAP files that compromise this dataset - if isdir(filename) - ls = dir(filename); - dapfile = {}; - for i=1:length(ls) - if ~isempty(regexp(ls(i).name, '.dap$', 'once' )) - dapfile{end+1} = fullfile(filename, ls(i).name); - end - end - dapfile = sort(dapfile); - elseif iscell(filename) - dapfile = filename; - else - dapfile = {filename}; - end - % assume that each DAP file is accompanied by a dat file - % read the trigger values from the separate dat files - trg = []; - for i=1:length(dapfile) - datfile = [dapfile{i}(1:(end-4)) '.dat']; - trg = cat(1, trg, textread(datfile, '', 'headerlines', 1)); - end - % construct a event structure, one 'trialcode' event per trial - for i=1:length(trg) - event(i).type = 'trialcode'; % string - event(i).sample = (i-1)*hdr.nSamples + 1; % expressed in samples, first sample of file is 1 - event(i).value = trg(i); % number or string - event(i).offset = 0; % expressed in samples - event(i).duration = hdr.nSamples; % expressed in samples - end - - - case {'neuromag_fif' 'neuromag_mne' 'neuromag_mex'} - if strcmp(eventformat, 'neuromag_fif') - % the default is to use the MNE reader for fif files - eventformat = 'neuromag_mne'; - end - if strcmp(eventformat, 'neuromag_mex') - % check that the required low-level toolbox is available - hastoolbox('meg-pd', 1); - if isempty(headerformat), headerformat = eventformat; end - if isempty(dataformat), dataformat = eventformat; end - elseif strcmp(eventformat, 'neuromag_mne') - % check that the required low-level toolbox is available - hastoolbox('mne', 1); - if isempty(headerformat), headerformat = eventformat; end - if isempty(dataformat), dataformat = eventformat; end - end - - if isempty(hdr) - hdr = read_header(filename, 'headerformat', headerformat); - end - - % note below we've had to include some chunks of code that are only - % called if the file is an averaged file, or if the file is continuous. - % These are defined in hdr by read_header for neuromag_mne, but do not - % exist for neuromag_fif, hence we run the code anyway if the fields do - % not exist (this is what happened previously anyway). - - if strcmp(eventformat, 'neuromag_mex') - iscontinuous = 1; - isaverage = 0; - isepoched = 0; - elseif strcmp(eventformat, 'neuromag_mne') - iscontinuous = hdr.orig.iscontinuous; - isaverage = hdr.orig.isaverage; - isepoched = hdr.orig.isepoched; - end - - - - if iscontinuous - analogindx = find(strcmp(chantype(hdr), 'analog trigger')); - binaryindx = find(strcmp(chantype(hdr), 'digital trigger')); - - - if isempty(binaryindx)&&isempty(analogindx) - % included in case of problems with older systems and MNE reader: - % use a predefined set of channel names - binary = {'STI 014', 'STI 015', 'STI 016'}; - binaryindx = match_str(hdr.label, binary); - end - - if ~isempty(binaryindx) - trigger = read_trigger(filename, 'header', hdr, 'dataformat', dataformat, 'begsample', flt_minsample, 'endsample', flt_maxsample, 'chanindx', binaryindx, 'detectflank', detectflank, 'trigshift', trigshift, 'fixneuromag', 0); - event = appendevent(event, trigger); - end - if ~isempty(analogindx) - % add the triggers to the event structure based on trigger channels with the name "STI xxx" - % there are some issues with noise on these analog trigger - % channels, on older systems only - % read the trigger channel and do flank detection - trigger = read_trigger(filename, 'header', hdr, 'dataformat', dataformat, 'begsample', flt_minsample, 'endsample', flt_maxsample, 'chanindx', analogindx, 'detectflank', detectflank, 'trigshift', trigshift, 'fixneuromag', 1); - event = appendevent(event, trigger); - end - - if hdr.nTrials>1 - % make an event for each trial as defined in the header - for i=1:hdr.nTrials - event(end+1).type = 'trial'; - event(end ).sample = (i-1)*hdr.nSamples + 1; - event(end ).offset = -hdr.nSamplesPre; - event(end ).duration = hdr.nSamples; - event(end ).value = []; - end - end - - elseif isaverage - % the length of each average can be variable - nsamples = zeros(1, length(hdr.orig.evoked)); - for i=1:length(hdr.orig.evoked) - nsamples(i) = size(hdr.orig.evoked(i).epochs, 2); - end - begsample = cumsum([1 nsamples]); - for i=1:length(hdr.orig.evoked) - event(end+1).type = 'average'; - event(end ).sample = begsample(i); - event(end ).value = hdr.orig.evoked(i).comment; % this is a descriptive string - event(end ).offset = hdr.orig.evoked(i).first; - event(end ).duration = hdr.orig.evoked(i).last - hdr.orig.evoked(i).first + 1; - end - - elseif isepoched - error('Support for epoched *.fif data is not yet implemented.') - end - - - case {'neuralynx_ttl' 'neuralynx_bin' 'neuralynx_dma' 'neuralynx_sdma'} - if isempty(hdr) - hdr = read_header(filename); - end - - % specify the range to search for triggers, default is the complete file - if ~isempty(flt_minsample) - begsample = flt_minsample; - else - begsample = 1; - end - if ~isempty(flt_maxsample) - endsample = flt_maxsample; - else - endsample = hdr.nSamples*hdr.nTrials; - end - - if strcmp(eventformat, 'neuralynx_dma') - % read the Parallel_in channel from the DMA log file - ttl = read_neuralynx_dma(filename, begsample, endsample, 'ttl'); - elseif strcmp(eventformat, 'neuralynx_sdma') - % determine the seperate files with the trigger and timestamp information - [p, f, x] = fileparts(filename); - ttlfile = fullfile(filename, [f '.ttl.bin']); - tslfile = fullfile(filename, [f '.tsl.bin']); - tshfile = fullfile(filename, [f '.tsh.bin']); - if ~exist(ttlfile) && ~exist(tslfile) && ~exist(tshfile) - % perhaps it is an old splitted dma dataset? - ttlfile = fullfile(filename, [f '.ttl']); - tslfile = fullfile(filename, [f '.tsl']); - tshfile = fullfile(filename, [f '.tsh']); - end - if ~exist(ttlfile) && ~exist(tslfile) && ~exist(tshfile) - % these files must be present in a splitted dma dataset - error('could not locate the individual ttl, tsl and tsh files'); - end - % read the trigger values from the seperate file - ttl = read_neuralynx_bin(ttlfile, begsample, endsample); - elseif strcmp(eventformat, 'neuralynx_ttl') - % determine the optional files with timestamp information - tslfile = [filename(1:(end-4)) '.tsl']; - tshfile = [filename(1:(end-4)) '.tsh']; - % read the triggers from a seperate *.ttl file - ttl = read_neuralynx_ttl(filename, begsample, endsample); - elseif strcmp(eventformat, 'neuralynx_bin') - % determine the optional files with timestamp information - tslfile = [filename(1:(end-8)) '.tsl.bin']; - tshfile = [filename(1:(end-8)) '.tsh.bin']; - % read the triggers from a seperate *.ttl.bin file - ttl = read_neuralynx_bin(filename, begsample, endsample); - end - - ttl = int32(ttl / (2^16)); % parallel port provides int32, but word resolution is int16. Shift the bits and typecast to signed integer. - d1 = (diff(ttl)~=0); % determine the flanks, which can be multiple samples long (this looses one sample) - d2 = (diff(d1)==1); % determine the onset of the flanks (this looses one sample) - smp = find(d2)+2; % find the onset of the flanks, add the two samples again - val = ttl(smp+5); % look some samples further for the trigger value, to avoid the flank - clear d1 d2 ttl - ind = find(val~=0); % look for triggers tith a non-zero value, this avoids downgoing flanks going to zero - smp = smp(ind); % discard triggers with a value of zero - val = val(ind); % discard triggers with a value of zero - - if ~isempty(smp) - % try reading the timestamps - if strcmp(eventformat, 'neuralynx_dma') - tsl = read_neuralynx_dma(filename, 1, max(smp), 'tsl'); - tsl = typecast(tsl(smp), 'uint32'); - tsh = read_neuralynx_dma(filename, 1, max(smp), 'tsh'); - tsh = typecast(tsh(smp), 'uint32'); - ts = timestamp_neuralynx(tsl, tsh); - elseif exist(tslfile) && exist(tshfile) - tsl = read_neuralynx_bin(tslfile, 1, max(smp)); - tsl = tsl(smp); - tsh = read_neuralynx_bin(tshfile, 1, max(smp)); - tsh = tsh(smp); - ts = timestamp_neuralynx(tsl, tsh); - else - ts = []; - end - - % reformat the values as cell array, since the struct function can work with those - type = repmat({'trigger'},size(smp)); - value = num2cell(val); - sample = num2cell(smp + begsample - 1); - duration = repmat({[]},size(smp)); - offset = repmat({[]},size(smp)); - if ~isempty(ts) - timestamp = reshape(num2cell(ts),size(smp)); - else - timestamp = repmat({[]},size(smp)); - end - % convert it into a structure array, this can be done in one go - event = struct('type', type, 'value', value, 'sample', sample, 'timestamp', timestamp, 'offset', offset, 'duration', duration); - clear type value sample timestamp offset duration - end - - if (strcmp(eventformat, 'neuralynx_bin') || strcmp(eventformat, 'neuralynx_ttl')) && isfield(hdr, 'FirstTimeStamp') - % the header was obtained from an external dataset which could be at a different sampling rate - % use the timestamps to redetermine the sample numbers - fprintf('using sample number of the downsampled file to reposition the TTL events\n'); - % convert the timestamps into samples, keeping in mind the FirstTimeStamp and TimeStampPerSample - smp = round(double(ts - uint64(hdr.FirstTimeStamp))./hdr.TimeStampPerSample + 1); - for i=1:length(event) - % update the sample number - event(i).sample = smp(i); - end - end - - case 'neuralynx_ds' - % read the header of the dataset - if isempty(hdr) - hdr = read_header(filename); - end - % the event file is contained in the dataset directory - if exist(fullfile(filename, 'Events.Nev')) - filename = fullfile(filename, 'Events.Nev'); - elseif exist(fullfile(filename, 'Events.nev')) - filename = fullfile(filename, 'Events.nev'); - elseif exist(fullfile(filename, 'events.Nev')) - filename = fullfile(filename, 'events.Nev'); - elseif exist(fullfile(filename, 'events.nev')) - filename = fullfile(filename, 'events.nev'); - end - % read the events, apply filter is applicable - nev = read_neuralynx_nev(filename, 'type', flt_type, 'value', flt_value, 'mintimestamp', flt_mintimestamp, 'maxtimestamp', flt_maxtimestamp, 'minnumber', flt_minnumber, 'maxnumber', flt_maxnumber); - - % now get the values as cell array, since the struct function can work with those - value = {nev.TTLValue}; - timestamp = {nev.TimeStamp}; - number = {nev.EventNumber}; - type = repmat({'trigger'},size(value)); - duration = repmat({[]},size(value)); - offset = repmat({[]},size(value)); - sample = num2cell(round(double(cell2mat(timestamp) - hdr.FirstTimeStamp)/hdr.TimeStampPerSample + 1)); - % convert it into a structure array - event = struct('type', type, 'value', value, 'sample', sample, 'timestamp', timestamp, 'duration', duration, 'offset', offset, 'number', number); - - case 'neuralynx_cds' - % this is a combined Neuralynx dataset with seperate subdirectories for the LFP, MUA and spike channels - dirlist = dir(filename); - %haslfp = any(filetype_check_extension({dirlist.name}, 'lfp')); - %hasmua = any(filetype_check_extension({dirlist.name}, 'mua')); - %hasspike = any(filetype_check_extension({dirlist.name}, 'spike')); - %hastsl = any(filetype_check_extension({dirlist.name}, 'tsl')); % seperate file with original TimeStampLow - %hastsh = any(filetype_check_extension({dirlist.name}, 'tsh')); % seperate file with original TimeStampHi - hasttl = any(filetype_check_extension({dirlist.name}, 'ttl')); % seperate file with original Parallel_in - hasnev = any(filetype_check_extension({dirlist.name}, 'nev')); % original Events.Nev file - hasmat = 0; - if hasttl - eventfile = fullfile(filename, dirlist(find(filetype_check_extension({dirlist.name}, 'ttl'))).name); - % read the header from the combined dataset - if isempty(hdr) - hdr = read_header(filename); - end - % read the events from the *.ttl file - event = read_event(eventfile); - % convert the sample numbers from the dma or ttl file to the downsampled dataset - % assume that the *.ttl file is sampled at 32556Hz and is aligned with the rest of the data - for i=1:length(event) - event(i).sample = round((event(i).sample-1) * hdr.Fs/32556 + 1); - end - % elseif hasnev - % FIXME, do something here - % elseif hasmat - % FIXME, do something here - else - error('no event file found'); - end - - % The sample number is missingin the code below, since it is not available - % without looking in the continuously sampled data files. Therefore - % sorting the events (later in this function) based on the sample number - % fails and no events can be returned. - % - % case 'neuralynx_nev' - % [nev] = read_neuralynx_nev(filename); - % % select only the events with a TTL value - % ttl = [nev.TTLValue]; - % sel = find(ttl~=0); - % % now get the values as cell array, since teh struct function can work with those - % value = {nev(sel).TTLValue}; - % timestamp = {nev(sel).TimeStamp}; - % event = struct('value', value, 'timestamp', timestamp); - % for i=1:length(event) - % % assign the other fixed elements - % event(i).type = 'trigger'; - % event(i).offset = []; - % event(i).duration = []; - % event(i).sample = []; - % end - - - case {'neuroprax_eeg', 'neuroprax_mrk'} - tmp = np_readmarker (filename, 0, inf, 'samples'); - event = []; - for i = 1:numel(tmp.marker) - if isempty(tmp.marker{i}) - break; - end - event = [event struct('type', tmp.markernames(i),... - 'sample', num2cell(tmp.marker{i}),... - 'value', {tmp.markertyp(i)})]; - end - - case 'nexstim_nxe' - event = read_nexstim_event(filename); - - case 'nimh_cortex' - if isempty(hdr) - hdr = read_header(filename); - end - cortex = hdr.orig.trial; - for i=1:length(cortex) - % add one 'trial' event for every trial and add the trigger events - event(end+1).type = 'trial'; - event(end ).sample = nan; - event(end ).duration = nan; - event(end ).offset = nan; - event(end ).value = i; % use the trial number as value - for j=1:length(cortex(i).event) - event(end+1).type = 'trigger'; - event(end ).sample = nan; - event(end ).duration = nan; - event(end ).offset = nan; - event(end ).value = cortex(i).event(j); - end - end - - case 'ns_avg' - if isempty(hdr) - hdr = read_header(filename); - end - event(end+1).type = 'average'; - event(end ).sample = 1; - event(end ).duration = hdr.nSamples; - event(end ).offset = -hdr.nSamplesPre; - event(end ).value = []; - - case {'ns_cnt', 'ns_cnt16', 'ns_cnt32'} - % read the header, the original header includes the event table - if isempty(hdr) - hdr = read_header(filename, 'headerformat', eventformat); - end - % translate the event table into known FieldTrip event types - for i=1:hdr.orig.nevent - event(i).type = 'trigger'; - event(i).sample = hdr.orig.event.frame(i); - event(i).value = hdr.orig.event.stimtype(i); - event(i).offset = 0; - event(i).duration = 0; - end - - case 'ns_eeg' - if isempty(hdr) - hdr = read_header(filename); - end - for i=1:hdr.nTrials - % the *.eeg file has a fixed trigger value for each trial - % furthermore each trial has the label 'accept' or 'reject' - tmp = read_ns_eeg(filename, i); - % create an event with the trigger value - event(end+1).type = 'trial'; - event(end ).sample = (i-1)*hdr.nSamples + 1; - event(end ).value = tmp.sweep.type; % trigger value - event(end ).offset = -hdr.nSamplesPre; - event(end ).duration = hdr.nSamples; - % create an event with the boolean accept/reject code - event(end+1).type = 'accept'; - event(end ).sample = (i-1)*hdr.nSamples + 1; - event(end ).value = tmp.sweep.accept; % boolean value indicating accept/reject - event(end ).offset = -hdr.nSamplesPre; - event(end ).duration = hdr.nSamples; - end - - case 'plexon_nex' - event = read_nex_event(filename); - - case 'yokogawa_ave' - % check that the required low-level toolbox is available - hastoolbox('yokogawa', 1); - if isempty(hdr) - hdr = read_header(filename); - end - event(end+1).type = 'average'; - event(end ).sample = 1; - event(end ).duration = hdr.nSamples; - event(end ).offset = -hdr.nSamplesPre; - event(end ).value = []; - - case 'yokogawa_con' - % check that the required low-level toolbox is available - % hastoolbox('yokogawa', 1); - error('events still need to be implemented for the yokogawa_con format'); - - case 'yokogawa_raw' - % check that the required low-level toolbox is available - hastoolbox('yokogawa', 1); - % read the trigger id from all trials - value = GetMeg160TriggerEventM(filename); - % create a "trial" event for each trial and assign it the corresponding trigger value - for i=1:hdr.nTrials - event(end+1).type = 'trial'; - event(end ).sample = (i-1)*hdr.nSamples + 1; - event(end ).offset = -hdr.nSamplesPre; - event(end ).duration = hdr.nSamples; - event(end ).value = value(i); - end - - case 'nmc_archive_k' - event = read_nmc_archive_k_event(filename); - - - otherwise - error('unsupported event format'); -end - -if ~isempty(event) - % make sure that all required elements are present - if ~isfield(event, 'type'), error('type field not defined for each event'); end - if ~isfield(event, 'sample'), error('sample field not defined for each event'); end - if ~isfield(event, 'value'), for i=1:length(event), event(i).value = []; end; end - if ~isfield(event, 'offset'), for i=1:length(event), event(i).offset = []; end; end - if ~isfield(event, 'duration'), for i=1:length(event), event(i).duration = []; end; end -end - -% make sure that all numeric values are double -if ~isempty(event) - for i=1:length(event) - if isnumeric(event(i).value) - event(i).value = double(event(i).value); - end - event(i).sample = double(event(i).sample); - event(i).offset = double(event(i).offset); - event(i).duration = double(event(i).duration); - end -end - -if ~isempty(event) - % sort the events on the sample on which they occur - % this has the side effect that events without a sample number are discarded - [dum, indx] = sort([event.sample]); - event = event(indx); -% else -% warning(sprintf('no events found in %s', filename)); -end - -% apply the optional filters -event = filter_event(event, varargin{:}); - - diff --git a/external/fileio/private/read_header.m b/external/fileio/private/read_header.m deleted file mode 100644 index 77effa3..0000000 --- a/external/fileio/private/read_header.m +++ /dev/null @@ -1,1516 +0,0 @@ -function [hdr] = read_header(filename, varargin) - -% READ_HEADER reads header information from a variety of EEG, MEG and LFP -% files and represents the header information in a common data-indepentend -% format. The supported formats are listed below. -% -% Use as -% hdr = read_header(filename, ...) -% -% Additional options should be specified in key-value pairs and can be -% 'headerformat' string -% 'fallback' can be empty or 'biosig' (default = []) -% -% This returns a header structure with the following elements -% hdr.Fs sampling frequency -% hdr.nChans number of channels -% hdr.nSamples number of samples per trial -% hdr.nSamplesPre number of pre-trigger samples in each trial -% hdr.nTrials number of trials -% hdr.label cell-array with labels of each channel -% hdr.FirstTimeStamp integer, only available for some subformats (mainly animal electrophisiology systems) -% hdr.TimeStampPerSample integer, only available for some subformats (mainly animal electrophisiology systems) -% -% For continuous data, nSamplesPre=0 and nTrials=1. -% -% Depending on the file format, additional header information can be -% returned in the hdr.orig subfield. -% -% The following MEG dataformats are supported -% CTF - VSM MedTech (*.ds, *.res4, *.meg4) -% Neuromag - Elektra (*.m4d, *.pdf, *.xyz) -% BTi - 4D Neuroimaging (*.m4d, *.pdf, *.xyz) -% Yokogawa (*.ave, *.con, *.raw) -% -% The following EEG dataformats are supported -% ANT - Advanced Neuro Technology, EEProbe (*.avr, *.eeg, *.cnt) -% Biosemi (*.bdf) -% CED - Cambridge Electronic Design (*. smr) -% Electrical Geodesics, Inc. (*.egis, *.ave, *.gave, *.ses, *.raw) -% Megis/BESA (*.avr, *.swf) -% NeuroScan (*.eeg, *.cnt, *.avg) -% Nexstim (*.nxe) -% BrainVision (*.eeg, *.seg, *.dat, *.vhdr, *.vmrk) -% -% The following spike and LFP dataformats are supported (with some limitations) -% Plextor (*.nex, *.plx, *.ddt) -% Neuralynx (*.ncs, *.nse, *.nts, *.nev, DMA log files) -% CED - Cambridge Electronic Design (*.smr) -% MPI - Max Planck Institute (*.dap) -% -% See also READ_DATA, READ_EVENT, WRITE_DATA, WRITE_EVENT - -% TODO channel renaming should be made a general option (see bham_bdf) - -% Copyright (C) 2003-2008, Robert Oostenveld, F.C. Donders Centre -% -% $Log: read_header.m,v $ -% Revision 1.102 2009/10/16 12:27:53 roboos -% some small changes pertaining to the itab/chieti format -% -% Revision 1.101 2009/10/16 07:31:18 roboos -% renamed chieti into itab for consistency with other formats -% -% Revision 1.100 2009/10/13 10:12:51 roboos -% added support for chieti_raw -% -% Revision 1.99 2009/10/08 11:17:44 roevdmei -% added support for nmc_archive_k -% -% Revision 1.98 2009/08/05 00:26:38 josdie -% Workaround for defect in number of subjects field in EGIS average files generated by NetStation. -% -% Revision 1.97 2009/07/19 19:49:21 josdie -% Deleted egi_egis changing a zero hdr.nSamplesPre to a one. -% -% Revision 1.96 2009/07/09 10:00:45 roboos -% no leading spaces for fake channel names in fcdc_buffer -% -% Revision 1.95 2009/06/17 13:43:20 roboos -% don't include LastTimeStamp in output -% -% Revision 1.94 2009/04/20 17:19:01 vlalit -% Changed the MNE reader not to set hdr.elec when there are no EEG channels. -% -% Revision 1.93 2009/03/02 10:44:38 roboos -% switched default for fif files to use the MNE reading routines in case of neuromag_fif -% the user can make his own choise by specifying the format as neuromag_mne (for the MNE routines) or neuromag_mex (for the meg-pd mex files) -% -% Revision 1.92 2009/02/12 11:47:23 vlalit -% Added support for neuro prax (eldith) EEG format based on functions from the manufacturer -% used with permission from the company's representative Mr. Klaus Schellhorn. -% -% Revision 1.91 2009/02/09 14:21:00 roboos -% added inport of micromed_trc data -% -% Revision 1.90 2009/02/09 13:35:16 roboos -% implemented efficient caching for bci2000, -% it should be initiated in read_header, subsequently read_data and read_event will reuse the details from the header -% -% Revision 1.89 2009/02/06 10:12:20 roboos -% incorporated the latest suggestions of Laurence Hunt for neuromag_mne -% -% Revision 1.88 2009/02/04 13:29:03 roboos -% deal with missing BalanceCoefs in the file using try-catch and isfield (e.g. ArtifactMEG.ds) -% -% Revision 1.87 2009/02/04 09:09:59 roboos -% fixed filename to headerfile/datafile cvonversion in case of ctf_old -% -% Revision 1.86 2009/01/23 16:22:44 roboos -% changed indentation and whitespace -% changed input arguments to mne2grad -% -% Revision 1.85 2009/01/23 10:32:55 vlalit -% New reader for Neuromag fif format using the MNE toolbox (http://www.nmr.mgh.harvard.edu/martinos/userInfo/data/sofMNE.php) implemented by Laurence Hunt. -% -% Revision 1.84 2009/01/21 20:22:42 roboos -% implemented retry for fcdc_buffer -% -% Revision 1.83 2009/01/20 21:50:20 roboos -% use mxDeserialize instead of eval(string) in mysql -% -% Revision 1.82 2009/01/20 21:20:04 roboos -% typo -% -% Revision 1.81 2009/01/19 15:05:47 roboos -% added skeleton support for reading fif files using mne functions -% -% Revision 1.80 2009/01/15 12:06:46 marvger -% removed keyboard command -% -% Revision 1.79 2009/01/15 09:42:05 marvger -% determining meg4 filesize based on all files conforming to REGEXP *.*meg4 -% -% Revision 1.78 2009/01/14 21:16:52 marvger -% changes related to realtime processing -% -% Revision 1.77 2009/01/12 13:47:50 roboos -% adedd suggestion from Doug to fix number of samples on specific configuation of OS/matlab and mex rawdata mex file -% -% Revision 1.76 2009/01/08 16:53:34 roboos -% alternatively use orig.ChannelNames for bci2000 channel count and channel names -% -% Revision 1.75 2008/12/01 14:50:42 roboos -% ensure that header elements are double precision and not integers, otherwise -% subsequent computations that depend on these might be messed up (learned in Lyon) -% -% Revision 1.74 2008/11/20 12:59:37 roboos -% added ns_cnt16 and ns_cnt32 as possible header formats, consistent with read_data -% -% Revision 1.73 2008/11/02 10:59:41 roboos -% some more changes for ctf_ds in case of empty path -% -% Revision 1.72 2008/11/02 10:37:43 roboos -% improved handling of empty path in case of ctf dataset -% -% Revision 1.71 2008/10/08 16:09:14 jansch -% changed allocation of hdr.label for 4d data. in the original implementation this -% only worked correctly for 248-channel systems, and not for the 148-channel system -% -% Revision 1.70 2008/10/07 16:21:39 roboos -% implemented caching, usefull when simulating BCI while reading from file -% -% Revision 1.69 2008/10/01 19:23:44 roboos -% fixed problem with old bci2000 dat files, changed fake channel names (no zero-prefix) -% -% Revision 1.68 2008/09/24 16:26:17 roboos -% swiched from old fcdc import routines for CTF to the p-files supplied by CTF -% these new reading routines support synthetic gradients -% the format 'ctf_new' is not supported any more, because that is now the default -% -% Revision 1.67 2008/09/04 15:35:49 vlalit -% Updates to EGI reading functions thanks to Joseph Dien -% -% Revision 1.66 2008/07/24 08:44:20 roboos -% added initial support for nimh_cortex, not yet complete -% -% Revision 1.65 2008/07/01 16:23:02 roboos -% added read_combined_data (new implementation) -% -% Revision 1.64 2008/06/26 15:50:56 roboos -% tread ctf_new just as ctf_ds w.r.t. mapping of the filenames -% -% Revision 1.63 2008/06/20 07:25:56 roboos -% added check for presence of BCI2000 load_bcidat mex file -% -% Revision 1.62 2008/06/18 08:24:33 roboos -% added support for BCI2000 -% -% Revision 1.61 2008/06/06 12:45:50 jansch -% changed filename-construction for 4d-datafiles to accommodate for filtered -% data -% -% Revision 1.60 2008/06/03 10:05:16 jansch -% removed minus-sign in nSamplesPre for 4d-data. -% -% Revision 1.59 2008/05/29 13:54:52 roboos -% also work when no path is specified -% -% Revision 1.58 2008/05/29 13:51:12 roboos -% use strcmp instead of strmatch, thanks to Marinka -% -% Revision 1.57 2008/05/29 07:30:42 roboos -% small change in renaming header/data and filename in case of ctf, this prevents a warning if the res4 or meg4 are not positioned in a xxx.ds directory (see email Jo) -% -% Revision 1.56 2008/05/27 16:12:26 vlalit -% Changed type name to ced_spike6mat -% -% Revision 1.55 2008/05/27 11:58:20 vlalit -% Added support of Matlab files exported from Spike 6 -% -% Revision 1.54 2008/05/21 11:06:05 roboos -% changed the fif reading to store all available info (including channel type) in hdr.orig -% -% Revision 1.53 2008/05/19 15:24:12 jansch -% re-entered handling of '4d' which disappeared after last commit by someone -% else -% -% Revision 1.52 2008/05/15 15:10:56 roboos -% added ctf_new implementation, using p-files, this supports synthetic gradients -% some changes to the filename handling, merged nihm2grad into ctf2grad -% -% Revision 1.51 2008/05/14 10:21:34 jansch -% included function call to bti2grad for 'm4d' and 'xyz' headers -% -% Revision 1.50 2008/05/08 11:08:57 jansch -% made changes in support for raw 4d-files -% -% Revision 1.49 2008/05/02 14:23:05 vlalit -% Added readers for SPM5 and SPM8 EEG formats -% -% Revision 1.48 2008/04/29 07:33:19 roboos -% changed low level function call for buffer -% -% Revision 1.47 2008/04/21 11:50:52 roboos -% added support for egi_sbin, thanks to Joseph Dien -% -% Revision 1.46 2008/04/18 14:07:45 roboos -% added eeglab_set -% -% Revision 1.45 2008/04/11 07:12:57 roboos -% updated docu, added list of supported file formats -% -% Revision 1.44 2008/04/10 09:34:51 roboos -% added fallback option for biosig, implemented biosig also for edf -% -% Revision 1.43 2008/04/09 16:50:02 roboos -% added fallback option to biosig (not default) -% -% Revision 1.42 2008/04/09 14:10:12 roboos -% updated docu, added placeholder for biosig (not yet implemented) -% -% Revision 1.41 2008/04/09 10:09:20 roboos -% only keep main fields for brainvision, remainder in orig -% added channel labels to hdr for ns_avg (thanks to Vladimir) -% -% Revision 1.40 2008/03/20 12:18:49 roboos -% warn only once for channel names in besa avr -% -% Revision 1.39 2008/02/19 10:08:13 roboos -% added support for fcdc_buffer -% -% Revision 1.38 2008/01/31 20:14:35 roboos -% A 4D case has been added to the existing switch statement to allow -% the execution of the new read_4D_hdr.m script to read the data -% from the pdf file. Header and grad structures are returned by the -% new function. [thanks to Gavin] -% -% Revision 1.37 2008/01/10 12:57:34 roboos -% give explicit errors with msgid FILEIO:Something -% -% Revision 1.36 2007/12/17 16:17:16 roboos -% updated some comments in the code, no functional change -% -% Revision 1.35 2007/12/17 08:24:28 roboos -% added support for nexstim_nxe, thanks to Vladimir -% the low-level code has not been tested by myself -% -% Revision 1.34 2007/12/12 16:50:15 roboos -% added support for neuralynx_bin -% -% Revision 1.33 2007/11/07 10:49:07 roboos -% cleaned up the reading and writing from/to mysql database, using db_xxx helper functions (see mysql directory) -% -% Revision 1.32 2007/11/05 17:01:21 roboos -% added implementation for fcdc_mysql -% -% Revision 1.31 2007/09/13 09:57:03 roboos -% use read_biosemi_bdf instead of openbdf/readbdf -% some small changes as sugegsted by the matlab editor (e.g. comma, semicolon) -% -% Revision 1.30 2007/08/01 12:24:40 roboos -% updated comments -% -% Revision 1.29 2007/08/01 09:57:01 roboos -% moved all code related to ctf shared memory to seperate functions -% -% Revision 1.28 2007/07/30 12:17:21 roboos -% ctf_shm: convert number of samples to double, otherwise problems with floor() in read_data -% -% Revision 1.27 2007/07/27 12:19:56 roboos -% added ctf_shm -% -% Revision 1.26 2007/07/19 14:49:30 roboos -% switched the default reader for nex files from read_nex_data to read_plexon_nex, the old one is still supported if explicitely mentioned as data/headerformat -% -% Revision 1.25 2007/07/04 13:20:51 roboos -% added support for egi_egis/egia, thanks to Joseph Dien -% -% Revision 1.24 2007/07/03 15:53:46 roboos -% switched from using Cristian Wienbruchs BTi toolbox to a new ascii header reading function (read_bti_m4d) -% -% Revision 1.23 2007/06/13 08:06:22 roboos -% updated help -% -% Revision 1.22 2007/06/06 12:39:43 roboos -% added try-catch for ctf2grad, to allow working with incomplete recordings on the new 275ch system -% -% Revision 1.21 2007/04/16 16:06:11 roboos -% add labels for neuroscan eeg format (thanks to Vladimir) -% -% Revision 1.20 2007/03/21 17:24:01 roboos -% added plexon_ds -% -% Revision 1.19 2007/03/19 17:07:19 roboos -% implemented an alternative reader for NEX (read_plexon_nex), the old implementation is still the default -% -% Revision 1.18 2007/02/21 09:54:21 roboos -% added timestamp details to header in case of neuralynx_ncs -% -% Revision 1.17 2007/01/10 17:29:54 roboos -% moved the fieldtrip specific handling of header information into -% read_header -% -% Revision 1.16 2007/01/09 09:38:40 roboos -% added spike channels for plexon_plx, moved plexon timestamp combination code to seperate function -% -% Revision 1.15 2007/01/04 17:13:19 roboos -% finished timestamp stuff for plexon_plx, only return the continuous channels that have data -% -% Revision 1.14 2007/01/04 12:20:26 roboos -% updated the neuralynx section to reflect the new reading functions and to use read_neuralynx_cds -% implemented recursive reading function for nested dataset directories -% -% Revision 1.13 2007/01/04 12:06:36 roboos -% added plexon_plx, not yet completely finished -% -% Revision 1.12 2006/12/04 10:37:10 roboos -% added support for ns_avg -% fixed bug in ns_eeg (hdr.nSamplesPre was negative) -% -% Revision 1.11 2006/10/09 15:39:51 roboos -% renamed BTi channels from 'MEGxxx' into 'Axxx' -% -% Revision 1.10 2006/09/18 21:48:33 roboos -% implemented support for fcdc_matbin, i.e. a dataset consisting of a matlab file with header and events and a seperate binary datafile -% -% Revision 1.9 2006/09/18 14:52:14 roboos -% implemented bti2grad and added it to header -% -% Revision 1.8 2006/09/18 14:22:54 roboos -% implemented support for 4D-BTi dataformat -% -% Revision 1.7 2006/09/13 11:01:01 roboos -% changed text in a error message -% -% Revision 1.6 2006/08/28 10:13:03 roboos -% use seperate filetype_check_extension function instead of subfunction, removed subfunction -% -% Revision 1.5 2006/06/22 15:07:39 roboos -% fiuxed bug in label assignment for tsl/tsh/ttl -% -% Revision 1.4 2006/06/22 13:51:47 roboos -% fixed typo in code: datatype instead of datatyppe, thanks to Thilo -% -% Revision 1.3 2006/06/22 07:53:46 roboos -% remember the original neuroscan cnt header -% -% Revision 1.2 2006/06/19 10:32:16 roboos -% added documentation -% -% Revision 1.1 2006/06/07 09:32:20 roboos -% new implementation based on the read_fcdc_xxx functions, now with -% variable (key-val) input arguments, changed the control structure -% in the rpobram (switch instead of ifs), allow the user to specify -% the file format, allow the user to specify either a sample selection -% or a block selection. The reading functionality should not have -% changed compared to the read_fcdc_xxx versions. -% - -persistent cacheheader % for caching -persistent db_blob % for fcdc_mysql - -if isempty(db_blob) - db_blob = 0; -end - -% test whether the file or directory exists -if ~exist(filename, 'file') && ~strcmp(filetype(filename), 'ctf_shm') && ~strcmp(filetype(filename), 'fcdc_mysql') && ~strcmp(filetype(filename), 'fcdc_buffer') - error('FILEIO:InvalidFileName', 'file or directory ''%s'' does not exist', filename); -end - -% get the options -headerformat = keyval('headerformat', varargin); -fallback = keyval('fallback', varargin); -cache = keyval('cache', varargin); if isempty(cache), cache = false; end -retry = keyval('retry', varargin); if isempty(retry), retry = false; end % for fcdc_buffer - -% determine the filetype -if isempty(headerformat) - headerformat = filetype(filename); -end - -% start with an empty header -hdr = []; - -switch headerformat - case '4d_pdf' - datafile = filename; - headerfile = [datafile '.m4d']; - sensorfile = [datafile '.xyz']; - case {'4d_m4d', '4d_xyz'} - datafile = filename(1:(end-4)); % remove the extension - headerfile = [datafile '.m4d']; - sensorfile = [datafile '.xyz']; - case '4d' - [path, file, ext] = fileparts(filename); - datafile = fullfile(path, [file,ext]); - headerfile = fullfile(path, [file,ext]); - configfile = fullfile(path, 'config'); - case {'ctf_ds', 'ctf_old'} - % convert CTF filename into filenames - [path, file, ext] = fileparts(filename); - if any(strcmp(ext, {'.res4' '.meg4', '.1_meg4' '.2_meg4' '.3_meg4' '.4_meg4' '.5_meg4' '.6_meg4' '.7_meg4' '.8_meg4' '.9_meg4'})) - filename = path; - [path, file, ext] = fileparts(filename); - end - if isempty(path) && isempty(file) - % this means that the dataset was specified as the present working directory, i.e. only with '.' - filename = pwd; - [path, file, ext] = fileparts(filename); - end - headerfile = fullfile(filename, [file '.res4']); - datafile = fullfile(filename, [file '.meg4']); - if length(path)>3 && strcmp(path(end-2:end), '.ds') - filename = path; % this is the *.ds directory - end - case 'ctf_meg4' - [path, file, ext] = fileparts(filename); - if isempty(path) - path = pwd; - end - headerfile = fullfile(path, [file '.res4']); - datafile = fullfile(path, [file '.meg4']); - if length(path)>3 && strcmp(path(end-2:end), '.ds') - filename = path; % this is the *.ds directory - end - case 'ctf_res4' - [path, file, ext] = fileparts(filename); - if isempty(path) - path = pwd; - end - headerfile = fullfile(path, [file '.res4']); - datafile = fullfile(path, [file '.meg4']); - if length(path)>3 && strcmp(path(end-2:end), '.ds') - filename = path; % this is the *.ds directory - end - case 'brainvision_vhdr' - [path, file, ext] = fileparts(filename); - headerfile = fullfile(path, [file '.vhdr']); - if exist(fullfile(path, [file '.eeg'])) - datafile = fullfile(path, [file '.eeg']); - elseif exist(fullfile(path, [file '.seg'])) - datafile = fullfile(path, [file '.seg']); - elseif exist(fullfile(path, [file '.dat'])) - datafile = fullfile(path, [file '.dat']); - end - case 'brainvision_eeg' - [path, file, ext] = fileparts(filename); - headerfile = fullfile(path, [file '.vhdr']); - datafile = fullfile(path, [file '.eeg']); - case 'brainvision_seg' - [path, file, ext] = fileparts(filename); - headerfile = fullfile(path, [file '.vhdr']); - datafile = fullfile(path, [file '.seg']); - case 'brainvision_dat' - [path, file, ext] = fileparts(filename); - headerfile = fullfile(path, [file '.vhdr']); - datafile = fullfile(path, [file '.dat']); - case 'fcdc_matbin' - [path, file, ext] = fileparts(filename); - headerfile = fullfile(path, [file '.mat']); - datafile = fullfile(path, [file '.bin']); - case 'nmc_archive_k' - headerfile = filename; - otherwise - % convert filename into filenames, assume that the header and data are the same - datafile = filename; - headerfile = filename; -end - -if ~strcmp(filename, headerfile) && ~filetype(filename, 'ctf_ds') - filename = headerfile; % this function will read the header - headerformat = filetype(filename); % update the filetype -end - - -% implement the caching in a data-format independent way -if cache && exist(headerfile, 'file') && ~isempty(cacheheader) - % try to get the header from cache - details = dir(headerfile); - if isequal(details, cacheheader.details) - % the header file has not been updated, fetch it from the cache - % fprintf('got header from cache\n'); - hdr = rmfield(cacheheader, 'details'); - - switch filetype(datafile) - case {'ctf_ds' 'ctf_meg4' 'ctf_old' 'read_ctf_res4'} - % for realtime analysis EOF chasing the res4 does not correctly - % estimate the number of samples, so we compute it on the fly - sz = 0; - files = dir([filename '/*.*meg4']); - for j=1:numel(files) - sz = sz + files(j).bytes; - end - hdr.nTrials = floor((sz - 8) / (hdr.nChans*4) / hdr.nSamples); - end - - return; - end % if the details correspond -end % if cache - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% read the data with the low-level reading function -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -switch headerformat - case '4d' - orig = read_4d_hdr(datafile, configfile); - hdr.Fs = orig.header_data.SampleFrequency; - hdr.nChans = orig.header_data.TotalChannels; - hdr.nSamples = orig.header_data.SlicesPerEpoch; - hdr.nSamplesPre = round(orig.header_data.FirstLatency*orig.header_data.SampleFrequency); - hdr.nTrials = orig.header_data.TotalEpochs; - %hdr.label = {orig.channel_data(:).chan_label}'; - hdr.label = orig.Channel; - hdr.grad = bti2grad(orig); - % remember original header details - hdr.orig = orig; - - case {'4d_pdf', '4d_m4d', '4d_xyz'} - orig = read_bti_m4d(filename); - hdr.Fs = orig.SampleFrequency; - hdr.nChans = orig.TotalChannels; - hdr.nSamples = orig.SlicesPerEpoch; - hdr.nSamplesPre = round(orig.FirstLatency*orig.SampleFrequency); - hdr.nTrials = orig.TotalEpochs; - hdr.label = orig.ChannelOrder(:); - hdr.grad = bti2grad(orig); - % remember original header details - hdr.orig = orig; - - case 'bci2000_dat' - % this requires the load_bcidat mex file to be present on the path - hastoolbox('BCI2000', 1); - % this is inefficient, since it reads the complete data - [signal, states, parameters, total_samples] = load_bcidat(filename); - % convert into a FieldTrip-like header - hdr = []; - hdr.nChans = size(signal,2); - hdr.nSamples = total_samples; - hdr.nSamplesPre = 0; % it is continuous - hdr.nTrials = 1; % it is continuous - hdr.Fs = parameters.SamplingRate.NumericValue; - % there are some differences in the fields that are present in the - % *.dat files, probably due to different BCI2000 versions - if isfield(parameters, 'ChannelNames') && isfield(parameters.ChannelNames, 'Value') && ~isempty(parameters.ChannelNames.Value) - hdr.label = parameters.ChannelNames.Value; - elseif isfield(parameters, 'ChannelNames') && isfield(parameters.ChannelNames, 'Values') && ~isempty(parameters.ChannelNames.Values) - hdr.label = parameters.ChannelNames.Values; - else - warning('creating fake channel names'); - for i=1:hdr.nChans - hdr.label{i} = sprintf('%d', i); - end - end - - % remember the original header details - hdr.orig.parameters = parameters; - % also remember the complete data upon request - if cache - hdr.orig.signal = signal; - hdr.orig.states = states; - hdr.orig.total_samples = total_samples; - end - - case 'besa_avr' - orig = read_besa_avr(filename); - hdr.Fs = 1000/orig.di; - hdr.nChans = size(orig.data,1); - hdr.nSamples = size(orig.data,2); - hdr.nSamplesPre = -(hdr.Fs * orig.tsb/1000); % convert from ms to samples - hdr.nTrials = 1; - if isfield(orig, 'label') && iscell(orig.label) - hdr.label = orig.label; - elseif isfield(orig, 'label') && ischar(orig.label) - hdr.label = tokenize(orig.label, ' '); - else - warning('creating fake channel names'); - for i=1:hdr.nChans - hdr.label{i} = sprintf('%d', i); - end - end - - case 'besa_swf' - orig = read_besa_swf(filename); - hdr.Fs = 1000/orig.di; - hdr.nChans = size(orig.data,1); - hdr.nSamples = size(orig.data,2); - hdr.nSamplesPre = -(hdr.Fs * orig.tsb/1000); % convert from ms to samples - hdr.nTrials = 1; - hdr.label = orig.label; - - case {'biosig', 'edf'} - % use the biosig toolbox if available - hastoolbox('BIOSIG', 1); - hdr = read_biosig_header(filename); - - case {'biosemi_bdf', 'bham_bdf'} - hdr = read_biosemi_bdf(filename); - if any(diff(hdr.orig.SampleRate)) - error('channels with different sampling rate not supported'); - end - if filetype(filename, 'bham_bdf') - % TODO channel renaming should be made a general option - % this is for the Biosemi system used at the University of Birmingham - labelold = { 'A1' 'A2' 'A3' 'A4' 'A5' 'A6' 'A7' 'A8' 'A9' 'A10' 'A11' 'A12' 'A13' 'A14' 'A15' 'A16' 'A17' 'A18' 'A19' 'A20' 'A21' 'A22' 'A23' 'A24' 'A25' 'A26' 'A27' 'A28' 'A29' 'A30' 'A31' 'A32' 'B1' 'B2' 'B3' 'B4' 'B5' 'B6' 'B7' 'B8' 'B9' 'B10' 'B11' 'B12' 'B13' 'B14' 'B15' 'B16' 'B17' 'B18' 'B19' 'B20' 'B21' 'B22' 'B23' 'B24' 'B25' 'B26' 'B27' 'B28' 'B29' 'B30' 'B31' 'B32' 'C1' 'C2' 'C3' 'C4' 'C5' 'C6' 'C7' 'C8' 'C9' 'C10' 'C11' 'C12' 'C13' 'C14' 'C15' 'C16' 'C17' 'C18' 'C19' 'C20' 'C21' 'C22' 'C23' 'C24' 'C25' 'C26' 'C27' 'C28' 'C29' 'C30' 'C31' 'C32' 'D1' 'D2' 'D3' 'D4' 'D5' 'D6' 'D7' 'D8' 'D9' 'D10' 'D11' 'D12' 'D13' 'D14' 'D15' 'D16' 'D17' 'D18' 'D19' 'D20' 'D21' 'D22' 'D23' 'D24' 'D25' 'D26' 'D27' 'D28' 'D29' 'D30' 'D31' 'D32' 'EXG1' 'EXG2' 'EXG3' 'EXG4' 'EXG5' 'EXG6' 'EXG7' 'EXG8' 'Status'}; - labelnew = { 'P9' 'PPO9h' 'PO7' 'PPO5h' 'PPO3h' 'PO5h' 'POO9h' 'PO9' 'I1' 'OI1h' 'O1' 'POO1' 'PO3h' 'PPO1h' 'PPO2h' 'POz' 'Oz' 'Iz' 'I2' 'OI2h' 'O2' 'POO2' 'PO4h' 'PPO4h' 'PO6h' 'POO10h' 'PO10' 'PO8' 'PPO6h' 'PPO10h' 'P10' 'P8' 'TPP9h' 'TP7' 'TTP7h' 'CP5' 'TPP7h' 'P7' 'P5' 'CPP5h' 'CCP5h' 'CP3' 'P3' 'CPP3h' 'CCP3h' 'CP1' 'P1' 'Pz' 'CPP1h' 'CPz' 'CPP2h' 'P2' 'CPP4h' 'CP2' 'CCP4h' 'CP4' 'P4' 'P6' 'CPP6h' 'CCP6h' 'CP6' 'TPP8h' 'TP8' 'TPP10h' 'T7' 'FTT7h' 'FT7' 'FC5' 'FCC5h' 'C5' 'C3' 'FCC3h' 'FC3' 'FC1' 'C1' 'CCP1h' 'Cz' 'FCC1h' 'FCz' 'FFC1h' 'Fz' 'FFC2h' 'FC2' 'FCC2h' 'CCP2h' 'C2' 'C4' 'FCC4h' 'FC4' 'FC6' 'FCC6h' 'C6' 'TTP8h' 'T8' 'FTT8h' 'FT8' 'FT9' 'FFT9h' 'F7' 'FFT7h' 'FFC5h' 'F5' 'AFF7h' 'AF7' 'AF5h' 'AFF5h' 'F3' 'FFC3h' 'F1' 'AF3h' 'Fp1' 'Fpz' 'Fp2' 'AFz' 'AF4h' 'F2' 'FFC4h' 'F4' 'AFF6h' 'AF6h' 'AF8' 'AFF8h' 'F6' 'FFC6h' 'FFT8h' 'F8' 'FFT10h' 'FT10'}; - % rename the channel labels - for i=1:length(labelnew) - chan = strcmp(labelold(i), hdr.label); - hdr.label(chan) = labelnew(chan); - end - end - - case {'biosemi_old'} - % this uses the openbdf and readbdf functions that I copied from the EEGLAB toolbox - orig = openbdf(filename); - if any(orig.Head.SampleRate~=orig.Head.SampleRate(1)) - error('channels with different sampling rate not supported'); - end - hdr.Fs = orig.Head.SampleRate(1); - hdr.nChans = orig.Head.NS; - hdr.label = cellstr(orig.Head.Label); - % it is continuous data, therefore append all records in one trial - hdr.nSamples = orig.Head.NRec * orig.Head.Dur * orig.Head.SampleRate(1); - hdr.nSamplesPre = 0; - hdr.nTrials = 1; - hdr.orig = orig; - % close the file between seperate read operations - fclose(orig.Head.FILE.FID); - - case {'brainvision_vhdr', 'brainvision_seg', 'brainvision_eeg', 'brainvision_dat'} - orig = read_brainvision_vhdr(filename); - hdr.Fs = orig.Fs; - hdr.nChans = orig.NumberOfChannels; - hdr.label = orig.label; - hdr.nSamples = orig.nSamples; - hdr.nSamplesPre = orig.nSamplesPre; - hdr.nTrials = orig.nTrials; - hdr.orig = orig; - - case 'ced_son' - % check that the required low-level toolbox is available - hastoolbox('neuroshare', 1); - % use the reading function supplied by Gijs van Elswijk - orig = read_ced_son(filename,'readevents','no','readdata','no'); - orig = orig.header; - % In Spike2, channels can have different sampling rates, units, length - % etc. etc. Here, channels need to have to same properties. - if length(unique([orig.samplerate]))>1, - error('channels with different sampling rates are not supported'); - else - hdr.Fs = orig(1).samplerate; - end; - hdr.nChans = length(orig); - % nsamples of the channel with least samples - hdr.nSamples = min([orig.nsamples]); - hdr.nSamplesPre = 0; - % only continuous data supported - if sum(strcmpi({orig.mode},'continuous')) < hdr.nChans, - error('not all channels contain continuous data'); - else - hdr.nTrials = 1; - end; - hdr.label = {orig.label}; - - case 'itab_raw' - % check the presence of the required low-level toolbox - hastoolbox('lc-libs', 1); - - header_info = lcReadHeader(filename); - - % some channels don't have a label and are not supported by fieldtrip - chansel = true(size(header_info.ch)); - for i=1:length(chansel) - chansel(i) = ~isempty(header_info.ch(i).label); - end - % convert into numeric array with indices - chansel = find(chansel); - - % convert the header information into a fieldtrip compatible format - hdr.nChans = length(chansel); - hdr.label = {header_info.ch(chansel).label}; - hdr.label = hdr.label(:); % should be column vector - hdr.Fs = header_info.smpfq; - if header_info.nsmpl==0 - % for continuous data - hdr.nSamples = header_info.ntpdata; - hdr.nSamplesPre = 0; % it is a single continuous trial - hdr.nTrials = 1; % it is a single continuous trial - else - error('epoched data in a itab_raw file is not yet supported (but should be easy to add)'); - end - % keep the original details AND the list of channels as used by fieldtrip - hdr.orig = header_info; - hdr.orig.chansel = chansel; - % add the gradiometer definition - hdr.grad = itab2grad(header_info); - - case 'combined_ds' - hdr = read_combined_ds(filename); - - case {'ctf_ds', 'ctf_meg4', 'ctf_res4'} - % check the presence of the required low-level toolbox - hastoolbox('ctf', 1); - orig = readCTFds(filename); - hdr.Fs = orig.res4.sample_rate; - hdr.nChans = orig.res4.no_channels; - hdr.nSamples = orig.res4.no_samples; - hdr.nSamplesPre = orig.res4.preTrigPts; - hdr.nTrials = orig.res4.no_trials; - hdr.label = cellstr(orig.res4.chanNames); - for i=1:numel(hdr.label) - % remove the site-specific numbers from each channel name, e.g. 'MZC01-1706' becomes 'MZC01' - hdr.label{i} = strtok(hdr.label{i}, '-'); - end - % read the balance coefficients, these are used to compute the synthetic gradients - try - [alphaMEG,MEGlist,Refindex] = getCTFBalanceCoefs(orig,'NONE', 'T'); - orig.BalanceCoefs.none.alphaMEG = alphaMEG; - orig.BalanceCoefs.none.MEGlist = MEGlist; - orig.BalanceCoefs.none.Refindex = Refindex; - catch - warning('cannot read balancing coefficients for NONE'); - end - try - [alphaMEG,MEGlist,Refindex] = getCTFBalanceCoefs(orig,'G1BR', 'T'); - orig.BalanceCoefs.G1BR.alphaMEG = alphaMEG; - orig.BalanceCoefs.G1BR.MEGlist = MEGlist; - orig.BalanceCoefs.G1BR.Refindex = Refindex; - catch - warning('cannot read balancing coefficients for G1BR'); - end - try - [alphaMEG,MEGlist,Refindex] = getCTFBalanceCoefs(orig,'G2BR', 'T'); - orig.BalanceCoefs.G2BR.alphaMEG = alphaMEG; - orig.BalanceCoefs.G2BR.MEGlist = MEGlist; - orig.BalanceCoefs.G2BR.Refindex = Refindex; - catch - warning('cannot read balancing coefficients for G2BR'); - end - try - [alphaMEG,MEGlist,Refindex] = getCTFBalanceCoefs(orig,'G3BR', 'T'); - orig.BalanceCoefs.G3BR.alphaMEG = alphaMEG; - orig.BalanceCoefs.G3BR.MEGlist = MEGlist; - orig.BalanceCoefs.G3BR.Refindex = Refindex; - catch - warning('cannot read balancing coefficients for G3BR'); - end - % add a gradiometer structure for forward and inverse modelling - try - hdr.grad = ctf2grad(orig); - catch - % this fails if the res4 file is not correctly closed, e.g. during realtime processing - tmp = lasterror; - disp(tmp.message); - warning('could not construct gradiometer definition from the header'); - end - - % for realtime analysis EOF chasing the res4 does not correctly - % estimate the number of samples, so we compute it on the fly from the - % meg4 file sizes. - sz = 0; - files = dir([filename '/*.*meg4']); - for j=1:numel(files) - sz = sz + files(j).bytes; - end - hdr.nTrials = floor((sz - 8) / (hdr.nChans*4) / hdr.nSamples); - - % add the original header details - hdr.orig = orig; - - case {'ctf_old', 'read_ctf_res4'} - % read it using the open-source matlab code that originates from CTF and that was modified by the FCDC - orig = read_ctf_res4(headerfile); - hdr.Fs = orig.Fs; - hdr.nChans = orig.nChans; - hdr.nSamples = orig.nSamples; - hdr.nSamplesPre = orig.nSamplesPre; - hdr.nTrials = orig.nTrials; - hdr.label = orig.label; - % add a gradiometer structure for forward and inverse modelling - try - hdr.grad = ctf2grad(orig); - catch - % this fails if the res4 file is not correctly closed, e.g. during realtime processing - tmp = lasterror; - disp(tmp.message); - warning('could not construct gradiometer definition from the header'); - end - % add the original header details - hdr.orig = orig; - - case 'ctf_read_res4' - % check that the required low-level toolbos ix available - hastoolbox('eegsf', 1); - % read it using the CTF importer from the NIH and Daren Weber - orig = ctf_read_res4(filename, 0); - % convert the header into a structure that FieldTrip understands - hdr = []; - hdr.Fs = orig.setup.sample_rate; - hdr.nChans = length(orig.sensor.info); - hdr.nSamples = orig.setup.number_samples; - hdr.nSamplesPre = orig.setup.pretrigger_samples; - hdr.nTrials = orig.setup.number_trials; - for i=1:length(orig.sensor.info) - hdr.label{i} = orig.sensor.info(i).label; - end - hdr.label = hdr.label(:); - % add a gradiometer structure for forward and inverse modelling - try - hdr.grad = ctf2grad(orig); - catch - % this fails if the res4 file is not correctly closed, e.g. during realtime processing - tmp = lasterror; - disp(tmp.message); - warning('could not construct gradiometer definition from the header'); - end - % add the original header details - hdr.orig = orig; - - case 'ctf_shm' - % contact Robert Oostenveld if you are interested in real-time acquisition on the CTF system - % read the header information from shared memory - hdr = read_shm_header(filename); - - case 'eep_avr' - % check that the required low-level toolbox is available - hastoolbox('eeprobe', 1); - % read the whole average and keep only header info (it is a bit silly, but the easiest to do here) - hdr = read_eep_avr(filename); - hdr.Fs = hdr.rate; - hdr.nChans = size(hdr.data,1); - hdr.nSamples = size(hdr.data,2); - hdr.nSamplesPre = hdr.xmin*hdr.rate/1000; - hdr.nTrials = 1; % it can always be interpreted as continuous data - % remove the data and variance if present - hdr = rmfield(hdr, 'data'); - try, hdr = rmfield(hdr, 'variance'); end - - case 'eeglab_set' - hdr = read_eeglabheader(filename); - - case 'spmeeg_mat' - hdr = read_spmeeg_header(filename); - - case 'ced_spike6mat' - hdr = read_spike6mat_header(filename); - - case 'eep_cnt' - % check that the required low-level toolbox is available - hastoolbox('eeprobe', 1); - % read the first sample from the continous data, which will also return the header - hdr = read_eep_cnt(filename, 1, 1); - hdr.Fs = hdr.rate; - hdr.nSamples = hdr.nsample; - hdr.nSamplesPre = 0; - hdr.nChans = hdr.nchan; - hdr.nTrials = 1; % it can always be interpreted as continuous data - - case 'egi_egia' - [fhdr,chdr,ename,cnames,fcom,ftext] = read_egis_header(filename); - [p, f, x] = fileparts(filename); - - if any(chdr(:,4)-chdr(1,4)) - error('Sample rate not the same for all cells.'); - end; - - hdr.Fs = chdr(1,4); %making assumption that sample rate is same for all cells - hdr.nChans = fhdr(19); - for i = 1:hdr.nChans - hdr.label{i} = ['e' num2str(i)]; - end; - %since NetStation does not properly set the fhdr(11) field, use the number of subjects from the chdr instead - hdr.nTrials = chdr(1,2)*fhdr(18); %number of trials is numSubjects * numCells - hdr.nSamplesPre = ceil(fhdr(14)/(1000/hdr.Fs)); - - if any(chdr(:,3)-chdr(1,3)) - error('Number of samples not the same for all cells.'); - end; - - hdr.nSamples = chdr(1,3); %making assumption that number of samples is same for all cells - - % remember the original header details - hdr.orig.fhdr = fhdr; - hdr.orig.chdr = chdr; - hdr.orig.ename = ename; - hdr.orig.cnames = cnames; - hdr.orig.fcom = fcom; - hdr.orig.ftext = ftext; - - case 'egi_egis' - [fhdr,chdr,ename,cnames,fcom,ftext] = read_egis_header(filename); - [p, f, x] = fileparts(filename); - - if any(chdr(:,4)-chdr(1,4)) - error('Sample rate not the same for all cells.'); - end; - - hdr.Fs = chdr(1,4); %making assumption that sample rate is same for all cells - hdr.nChans = fhdr(19); - for i = 1:hdr.nChans - hdr.label{i} = ['e' num2str(i)]; - end; - hdr.nTrials = sum(chdr(:,2)); - hdr.nSamplesPre = ceil(fhdr(14)/(1000/hdr.Fs)); - % assuming that a utility was used to insert the correct baseline - % duration into the header since it is normally absent. This slot is - % actually allocated to the age of the subject, although NetStation - % does not use it when generating an EGIS session file. - - if any(chdr(:,3)-chdr(1,3)) - error('Number of samples not the same for all cells.'); - end; - - hdr.nSamples = chdr(1,3); %making assumption that number of samples is same for all cells - - % remember the original header details - hdr.orig.fhdr = fhdr; - hdr.orig.chdr = chdr; - hdr.orig.ename = ename; - hdr.orig.cnames = cnames; - hdr.orig.fcom = fcom; - hdr.orig.ftext = ftext; - - case 'egi_sbin' - % segmented type only - [header_array, CateNames, CatLengths, preBaseline] = read_sbin_header(filename); - [p, f, x] = fileparts(filename); - - hdr.Fs = header_array(9); - hdr.nChans = header_array(10); - for i = 1:hdr.nChans - hdr.label{i} = ['e' num2str(i)]; - end; - hdr.nTrials = header_array(15); - hdr.nSamplesPre = preBaseline; - - if hdr.nSamplesPre == 0 - hdr.nSamplesPre = 1; % If baseline was left as zero, then change to "1" to avoid possible issues with software expecting a non-zero baseline. - end; - - hdr.nSamples = header_array(16); % making assumption that number of samples is same for all cells - - % remember the original header details - hdr.orig.header_array = header_array; - hdr.orig.CateNames = CateNames; - hdr.orig.CatLengths = CatLengths; - - case 'fcdc_buffer' - % read from a networked buffer for realtime analysis - [host, port] = filetype_check_uri(filename); - if retry - orig = []; - while isempty(orig) - try - % try reading the header, catch the error and retry - orig = buffer('get_hdr', [], host, port); - catch - warning('could not read header from %s, retrying in 1 second', filename); - pause(1); - end - end % while - else - % try reading the header only once, give error if it fails - orig = buffer('get_hdr', [], host, port); - end % if retry - hdr.Fs = orig.fsample; - hdr.nChans = orig.nchans; - hdr.nSamples = orig.nsamples; - hdr.nSamplesPre = 0; % since continuous - hdr.nTrials = 1; % since continuous - warning('creating fake channel names'); - for i=1:hdr.nChans - hdr.label{i} = sprintf('%d', i); - end - % this should be a column vector - hdr.label = hdr.label(:); - % remember the original header details - hdr.orig = orig; - - case 'fcdc_matbin' - % this is multiplexed data in a *.bin file, accompanied by a matlab file containing the header - load(headerfile, 'hdr'); - - case 'fcdc_mysql' - % read from a MySQL server listening somewhere else on the network - db_open(filename); - if db_blob - hdr = db_select_blob('fieldtrip.header', 'msg', 1); - else - hdr = db_select('fieldtrip.header', {'nChans', 'nSamples', 'nSamplesPre', 'Fs', 'label'}, 1); - hdr.label = mxDeserialize(hdr.label); - end - - case 'micromed_trc' - orig = read_micromed_trc(filename); - hdr = []; - hdr.Fs = orig.Rate_Min; % FIXME is this correct? - hdr.nChans = orig.Num_Chan; - hdr.nSamples = orig.Num_Samples; - hdr.nSamplesPre = 0; % continuous - hdr.nTrials = 1; % continuous - warning('creating fake channel names'); - for i=1:hdr.nChans - hdr.label{i} = sprintf('%3d', i); - end - % this should be a column vector - hdr.label = hdr.label(:); - % remember the original header details - hdr.orig = orig; - - case {'mpi_ds', 'mpi_dap'} - hdr = read_mpi_ds(filename); - - case 'neuralynx_dma' - hdr = read_neuralynx_dma(filename); - - case 'neuralynx_sdma' - hdr = read_neuralynx_sdma(filename); - - case 'neuralynx_ncs' - ncs = read_neuralynx_ncs(filename, 1, 0); - [p, f, x] = fileparts(filename); - hdr.Fs = ncs.hdr.SamplingFrequency; - hdr.label = {f}; - hdr.nChans = 1; - hdr.nTrials = 1; - hdr.nSamplesPre = 0; - hdr.nSamples = ncs.NRecords * 512; - hdr.orig = ncs.hdr; - FirstTimeStamp = ncs.hdr.FirstTimeStamp; % this is the first timestamp of the first block - LastTimeStamp = ncs.hdr.LastTimeStamp; % this is the first timestamp of the last block, i.e. not the timestamp of the last sample - hdr.TimeStampPerSample = double(LastTimeStamp - FirstTimeStamp) ./ ((ncs.NRecords-1)*512); - hdr.FirstTimeStamp = FirstTimeStamp; - - case 'neuralynx_nse' - nse = read_neuralynx_nse(filename, 1, 0); - [p, f, x] = fileparts(filename); - hdr.Fs = nse.hdr.SamplingFrequency; - hdr.label = {f}; - hdr.nChans = 1; - hdr.nTrials = nse.NRecords; % each record contains one waveform - hdr.nSamples = 32; % there are 32 samples in each waveform - hdr.nSamplesPre = 0; - hdr.orig = nse.hdr; - % FIXME add hdr.FirstTimeStamp and hdr.TimeStampPerSample - - case {'neuralynx_ttl', 'neuralynx_tsl', 'neuralynx_tsh'} - % these are hardcoded, they contain an 8-byte header and int32 values for a single channel - % FIXME this should be done similar as neuralynx_bin, i.e. move the hdr into the function - hdr = []; - hdr.Fs = 32556; - hdr.nChans = 1; - hdr.nSamples = (filesize(filename)-8)/4; - hdr.nSamplesPre = 1; - hdr.nTrials = 1; - hdr.label = {headerformat((end-3):end)}; - - case 'neuralynx_bin' - hdr = read_neuralynx_bin(filename); - - case 'neuralynx_ds' - hdr = read_neuralynx_ds(filename); - - case 'neuralynx_cds' - hdr = read_neuralynx_cds(filename); - - case 'nexstim_nxe' - hdr = read_nexstim_nxe(filename); - - case {'neuromag_fif' 'neuromag_mne'} - % check that the required low-level toolbox is available - hastoolbox('mne', 1); - - orig = fiff_read_meas_info(filename); - % convert to fieldtrip format header - hdr.label = orig.ch_names(:); - hdr.nChans = orig.nchan; - hdr.Fs = orig.sfreq; - % add a gradiometer structure for forward and inverse modelling - try - [hdr.grad, elec] = mne2grad(orig); - if ~isempty(elec) - hdr.elec = elec; - end - catch - disp(lasterr); - end - - for i = 1:hdr.nChans % make a cell array of units for each channel - switch orig.chs(i).unit - case 201 % defined as constants by MNE, see p. 217 of MNE manual - hdr.unit{i} = 'T/m'; - case 112 - hdr.unit{i} = 'T'; - case 107 - hdr.unit{i} = 'V'; - case 202 - hdr.unit{i} = 'Am'; - otherwise - hdr.unit{i} = 'unknown'; - end - end - - iscontinuous = 0; - isaverage = 0; - isepoched = 0; % FIXME don't know how to determine this, or whether epoched .fif data exists! - - if isempty(fiff_find_evoked(filename)) % true if file contains no evoked responses - iscontinuous = 1; - else - isaverage = 1; - end - - if iscontinuous - raw = fiff_setup_read_raw(filename); - hdr.nSamples = raw.last_samp - raw.first_samp + 1; % number of samples per trial - hdr.nSamplesPre = raw.first_samp; - hdr.nTrials = 1; - orig.raw = raw; % keep all the details - - elseif isaverage - evoked_data = fiff_read_evoked_all(filename); - vartriallength = any(diff([evoked_data.evoked.first])) || any(diff([evoked_data.evoked.last])); - if vartriallength - % there are trials averages with variable durations in the file - warning('EVOKED FILE with VARIABLE TRIAL LENGTH! - check data have been processed accurately'); - hdr.nSamples = 0; - for i=1:length(evoked_data.evoked) - hdr.nSamples = hdr.nSamples + size(evoked_data.evoked(i).epochs, 2); - end - % represent it as a continuous file with a single trial - % all trial average details will be available through read_event - hdr.nSamplesPre = 0; - hdr.nTrials = 1; - orig.evoked = evoked_data.evoked; % this is used by read_data to get the actual data, i.e. to prevent re-reading - orig.info = evoked_data.info; % keep all the details - orig.vartriallength = 1; - else - % represent it as a file with multiple trials, each trial has the same length - % all trial average details will be available through read_event - hdr.nSamples = evoked_data.evoked(1).last - evoked_data.evoked(1).first + 1; - hdr.nSamplesPre = evoked_data.evoked(1).first; - hdr.nTrials = length(evoked_data.evoked); - orig.evoked = evoked_data.evoked; % this is used by read_data to get the actual data, i.e. to prevent re-reading - orig.info = evoked_data.info; % keep all the details - orig.vartriallength = 0; - end - - elseif isepoched - error('Support for epoched *.fif data is not yet implemented.') - end - - % remember the original header details - hdr.orig = orig; - - % these are useful to know in read_event - hdr.orig.isaverage = isaverage; - hdr.orig.iscontinuous = iscontinuous; - hdr.orig.isepoched = isepoched; - - case 'neuromag_mex' - % check that the required low-level toolbox is available - hastoolbox('meg-pd', 1); - rawdata('any',filename); - rawdata('goto', 0); - megmodel('head',[0 0 0],filename); - % get the available information from the fif file - [orig.rawdata.range,orig.rawdata.calib] = rawdata('range'); - [orig.rawdata.sf] = rawdata('sf'); - [orig.rawdata.samples] = rawdata('samples'); - [orig.chaninfo.N,orig.chaninfo.S,orig.chaninfo.T] = chaninfo; % Numbers, names & places - [orig.chaninfo.TY,orig.chaninfo.NA] = chaninfo('type'); % Coil type - [orig.chaninfo.NO] = chaninfo('noise'); % Default noise level - [orig.channames.NA,orig.channames.KI,orig.channames.NU] = channames(filename); % names, kind, logical numbers - % read a single trial to determine the data size - [buf, status] = rawdata('next'); - rawdata('close'); - - % This is to solve a problem reported by Doug Davidson: The problem - % is that rawdata('samples') is not returning the number of samples - % correctly. It appears that the example script rawchannels in meg-pd - % might work, however, so I want to use rawchannels to read in one - % channel of data in order to get the number of samples in the file: - if orig.rawdata.samples<0 - tmpchannel = 1; - tmpvar = rawchannels(filename,tmpchannel); - [orig.rawdata.samples] = size(tmpvar,2); - clear tmpvar tmpchannel; - end - - % convert to fieldtrip format header - hdr.label = orig.channames.NA; - hdr.Fs = orig.rawdata.sf; - hdr.nSamplesPre = 0; % I don't know how to get this out of the file - hdr.nChans = size(buf,1); - hdr.nSamples = size(buf,2); % number of samples per trial - hdr.nTrials = orig.rawdata.samples ./ hdr.nSamples; - % add a gradiometer structure for forward and inverse modelling - hdr.grad = fif2grad(filename); - % remember the original header details - hdr.orig = orig; - - case 'neuroprax_eeg' - orig = np_readfileinfo(filename); - - hdr.Fs = orig.fa; - hdr.nChans = orig.K; - hdr.nSamples = orig.N; - hdr.nSamplesPre = 0; % continuous - hdr.nTrials = 1; % continuous - hdr.label = orig.channels(:); - hdr.unit = orig.units(:); - - % remember the original header details - hdr.orig = orig; - - case 'nimh_cortex' - cortex = read_nimh_cortex(filename, 'epp', 'no', 'eog', 'no'); - % look at the first trial to determine whether it contains data in the EPP and EOG channels - trial1 = read_nimh_cortex(filename, 'epp', 'yes', 'eog', 'yes', 'begtrial', 1, 'endtrial', 1); - hasepp = ~isempty(trial1.epp); - haseog = ~isempty(trial1.eog); - if hasepp - warning('EPP channels are not yet supported'); - end - % at the moment only the EOG channels are supported here - if haseog - hdr.label = {'EOGx' 'EOGy'}; - hdr.nChans = 2; - else - hdr.label = {}; - hdr.nChans = 0; - end - hdr.nTrials = length(cortex); - hdr.nSamples = inf; - hdr.nSamplesPre = 0; - hdr.orig.trial = cortex; - hdr.orig.hasepp = hasepp; - hdr.orig.haseog = haseog; - - case 'ns_avg' - orig = read_ns_hdr(filename); - % do some reformatting/renaming of the header items - hdr.Fs = orig.rate; - hdr.nSamples = orig.npnt; - hdr.nSamplesPre = round(-orig.rate*orig.xmin/1000); - hdr.nChans = orig.nchan; - hdr.label = orig.label(:); - hdr.nTrials = 1; % the number of trials in this datafile is only one, i.e. the average - % remember the original header details - hdr.orig = orig; - - case {'ns_cnt' 'ns_cnt16', 'ns_cnt32'} - % read_ns_cnt originates from the EEGLAB package (loadcnt.m) but is - % an old version since the new version is not compatible any more - if strcmp(headerformat, 'ns_cnt') - orig = read_ns_cnt(filename, 'ldheaderonly', 1); - elseif strcmp(headerformat, 'ns_cnt16') - orig = read_ns_cnt(filename, 'ldheaderonly', 1, 'format', 16); - elseif strcmp(headerformat, 'ns_cnt32') - orig = read_ns_cnt(filename, 'ldheaderonly', 1, 'format', 32); - end - % do some reformatting/renaming of the header items - hdr.Fs = orig.rate; - hdr.nChans = orig.nchannels; - hdr.nSamples = orig.nsamples; - hdr.nSamplesPre = 0; - hdr.nTrials = 1; - for i=1:hdr.nChans - hdr.label{i} = deblank(orig.chan.names(i,:)); - end - % remember the original header details - hdr.orig = orig; - - case 'ns_eeg' - orig = read_ns_hdr(filename); - % do some reformatting/renaming of the header items - hdr.label = orig.label; - hdr.Fs = orig.rate; - hdr.nSamples = orig.npnt; - hdr.nSamplesPre = round(-orig.rate*orig.xmin/1000); - hdr.nChans = orig.nchan; - hdr.nTrials = orig.nsweeps; - % remember the original header details - hdr.orig = orig; - - case 'plexon_ds' - hdr = read_plexon_ds(filename); - - case 'plexon_ddt' - orig = read_plexon_ddt(filename); - hdr.nChans = orig.NChannels; - hdr.Fs = orig.Freq; - hdr.nSamples = orig.NSamples; - hdr.nSamplesPre = 0; % continuous - hdr.nTrials = 1; % continuous - warning('creating fake channel names'); - for i=1:hdr.nChans - hdr.label{i} = sprintf('%d', i); - end - % also remember the original header - hdr.orig = orig; - - case {'read_nex_data'} % this is an alternative reader for nex files - orig = read_nex_header(filename); - % assign the obligatory items to the output FCDC header - numsmp = cell2mat({orig.varheader.numsmp}); - adindx = find(cell2mat({orig.varheader.typ})==5); - if isempty(adindx) - error('file does not contain continuous channels'); - end - hdr.nChans = length(orig.varheader); - hdr.Fs = orig.varheader(adindx(1)).wfrequency; % take the sampling frequency from the first A/D channel - hdr.nSamples = max(numsmp(adindx)); % take the number of samples from the longest A/D channel - hdr.nTrials = 1; % it can always be interpreted as continuous data - hdr.nSamplesPre = 0; % and therefore it is not trial based - for i=1:hdr.nChans - hdr.label{i} = deblank(char(orig.varheader(i).nam)); - end - hdr.label = hdr.label(:); - % also remember the original header details - hdr.orig = orig; - - case {'read_plexon_nex' 'plexon_nex'} % this is the default reader for nex files - orig = read_plexon_nex(filename); - numsmp = cell2mat({orig.VarHeader.NPointsWave}); - adindx = find(cell2mat({orig.VarHeader.Type})==5); - if isempty(adindx) - error('file does not contain continuous channels'); - end - hdr.nChans = length(orig.VarHeader); - hdr.Fs = orig.VarHeader(adindx(1)).WFrequency; % take the sampling frequency from the first A/D channel - hdr.nSamples = max(numsmp(adindx)); % take the number of samples from the longest A/D channel - hdr.nTrials = 1; % it can always be interpreted as continuous data - hdr.nSamplesPre = 0; % and therefore it is not trial based - for i=1:hdr.nChans - hdr.label{i} = deblank(char(orig.VarHeader(i).Name)); - end - hdr.label = hdr.label(:); - hdr.FirstTimeStamp = orig.FileHeader.Beg; - hdr.TimeStampPerSample = orig.FileHeader.Frequency ./ hdr.Fs; - % also remember the original header details - hdr.orig = orig; - - case 'plexon_plx' - orig = read_plexon_plx(filename); - if orig.NumSlowChannels==0 - error('file does not contain continuous channels'); - end - fsample = [orig.SlowChannelHeader.ADFreq]; - if any(fsample~=fsample(1)) - error('different sampling rates in continuous data not supported'); - end - for i=1:length(orig.SlowChannelHeader) - label{i} = deblank(orig.SlowChannelHeader(i).Name); - end - % continuous channels don't always contain data, remove the empty ones - sel = [orig.DataBlockHeader.Type]==5; % continuous - chan = [orig.DataBlockHeader.Channel]; - for i=1:length(label) - chansel(i) = any(chan(sel)==orig.SlowChannelHeader(i).Channel); - end - chansel = find(chansel); % this is required for timestamp selection - label = label(chansel); - % only the continuous channels are returned as visible - hdr.nChans = length(label); - hdr.Fs = fsample(1); - hdr.label = label; - % also remember the original header - hdr.orig = orig; - - % select the first continuous channel that has data - sel = ([orig.DataBlockHeader.Type]==5 & [orig.DataBlockHeader.Channel]==orig.SlowChannelHeader(chansel(1)).Channel); - % get the timestamps that correspond with the continuous data - tsl = [orig.DataBlockHeader(sel).TimeStamp]'; - tsh = [orig.DataBlockHeader(sel).UpperByteOf5ByteTimestamp]'; - ts = timestamp_plexon(tsl, tsh); % use helper function, this returns an uint64 array - - % determine the number of samples in the continuous channels - num = [orig.DataBlockHeader(sel).NumberOfWordsInWaveform]; - hdr.nSamples = sum(num); - hdr.nSamplesPre = 0; % continuous - hdr.nTrials = 1; % continuous - - % the timestamps indicate the beginning of each block, hence the timestamp of the last block corresponds with the end of the previous block - hdr.TimeStampPerSample = double(ts(end)-ts(1))/sum(num(1:(end-1))); - hdr.FirstTimeStamp = ts(1); % the timestamp of the first continuous sample - - % also make the spike channels visible - for i=1:length(orig.ChannelHeader) - hdr.label{end+1} = deblank(orig.ChannelHeader(i).Name); - end - hdr.label = hdr.label(:); - hdr.nChans = length(hdr.label); - - case {'yokogawa_ave', 'yokogawa_con', 'yokogawa_raw'} - % chek that the required low-level toolbox is available - hastoolbox('yokogawa', 1); - hdr = read_yokogawa_header(filename); - % add a gradiometer structure for forward and inverse modelling - hdr.grad = yokogawa2grad(hdr); - - case 'nmc_archive_k' - hdr = read_nmc_archive_k_hdr(filename); - - otherwise - if strcmp(fallback, 'biosig') && hastoolbox('BIOSIG', 1) - hdr = read_biosig_header(filename); - else - error('unsupported header format'); - end -end - -% ensure that these are double precision and not integers, otherwise -% subsequent computations that depend on these might be messed up -hdr.Fs = double(hdr.Fs); -hdr.nSamples = double(hdr.nSamples); -hdr.nSamplesPre = double(hdr.nSamplesPre); -hdr.nTrials = double(hdr.nTrials); -hdr.nChans = double(hdr.nChans); - -if cache && exist(headerfile, 'file') - % put the header in the cache - cacheheader = hdr; - % update the header details (including time stampp, size and name) - cacheheader.details = dir(headerfile); - % fprintf('added header to cache\n'); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION to determine the file size in bytes -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [siz] = filesize(filename) -l = dir(filename); -if l.isdir - error(sprintf('"%s" is not a file', filename)); -end -siz = l.bytes; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION to determine the file size in bytes -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [hdr] = recursive_read_header(filename) -[p, f, x] = fileparts(filename); -ls = dir(filename); -ls = ls(~strcmp({ls.name}, '.')); % exclude this directory -ls = ls(~strcmp({ls.name}, '..')); % exclude parent directory -for i=1:length(ls) - % make sure that the directory listing includes the complete path - ls(i).name = fullfile(filename, ls(i).name); -end -lst = {ls.name}; -hdr = cell(size(lst)); -sel = zeros(size(lst)); -for i=1:length(lst) - % read the header of each individual file - try - thishdr = read_header(lst{i}); - if isstruct(thishdr) - thishdr.filename = lst{i}; - end - catch - thishdr = []; - warning(lasterr); - fprintf('while reading %s\n\n', lst{i}); - end - if ~isempty(thishdr) - hdr{i} = thishdr; - sel(i) = true; - else - sel(i) = false; - end -end -sel = logical(sel(:)); -hdr = hdr(sel); -tmp = {}; -for i=1:length(hdr) - if isstruct(hdr{i}) - tmp = cat(1, tmp, hdr(i)); - elseif iscell(hdr{i}) - tmp = cat(1, tmp, hdr{i}{:}); - end -end -hdr = tmp; - diff --git a/external/fileio/private/read_headshape.m b/external/fileio/private/read_headshape.m deleted file mode 100644 index 92b2f02..0000000 --- a/external/fileio/private/read_headshape.m +++ /dev/null @@ -1,267 +0,0 @@ -function [shape] = read_headshape(filename, varargin) - -% READ_HEADSHAPE reads the fiducials and/or the measured headshape -% from a variety of files (like CTF and Polhemus). The headshape and -% fiducials can for example be used for coregistration. -% -% Use as -% [shape] = read_headshape(filename) -% -% See also READ_VOL, READ_SENS - -% Copyright (C) 2008, Robert Oostenveld -% -% $Log: read_headshape.m,v $ -% Revision 1.13 2009/09/26 10:46:25 vlalit -% Added 4d_pdf to the list of BTi formats -% -% Revision 1.12 2009/04/01 16:59:43 vlalit -% Slight fix for JMs fix to assign unique names to the other BTi fiducials. Also make -% sure that fid.label is a column cell array. -% -% Revision 1.11 2009/03/31 12:18:48 jansch -% added additional fiducials to shape.fid for 4D hs_files -% -% Revision 1.10 2009/03/23 12:09:07 vlalit -% Minor changes to make the ctf_old option fully functional. -% -% Revision 1.9 2009/03/17 10:58:13 vlalit -% Switched to MNE reader as default for Neuromag in read_headshape -% -% Revision 1.8 2009/01/28 18:29:07 vlalit -% Added '4d' type to BTi case -% -% Revision 1.7 2009/01/23 10:32:55 vlalit -% New reader for Neuromag fif format using the MNE toolbox (http://www.nmr.mgh.harvard.edu/martinos/userInfo/data/sofMNE.php) implemented by Laurence Hunt. -% -% Revision 1.6 2008/10/07 16:22:32 roboos -% added option to specify coordinates to be obtained from ctf hc file -% -% Revision 1.5 2008/05/22 14:33:18 vlalit -% Changes related to generalization of fiducials' handling in SPM. -% -% Revision 1.4 2008/05/11 16:30:30 vlalit -% Improved the support of 4d and neuromag -% -% Revision 1.3 2008/04/16 08:04:03 roboos -% allow headshape to be extracted from BEM volume conduction model -% -% Revision 1.2 2008/04/14 20:52:11 roboos -% ensure consistent output for all file formats (thanks to Vladimir) -% added convert_units -% -% Revision 1.1 2008/04/11 12:04:55 roboos -% new impoementation, required for clean interface towards SPM -% - -% test whether the file exists -if ~exist(filename) - error(sprintf('file ''%s'' does not exist', filename)); -end - -% get the options -fileformat = keyval('fileformat', varargin); -coordinates = keyval('coordinates', varargin); if isempty(coordinates), coordinates = 'head'; end - -if isempty(fileformat) - fileformat = filetype(filename); -end - -% start with an empty structure -shape = []; -shape.pnt = []; -shape.fid.pnt = []; -shape.fid.label = {}; - -switch fileformat - case {'ctf_ds', 'ctf_hc', 'ctf_meg4', 'ctf_res4', 'ctf_old'} - [p, f, x] = fileparts(filename); - - if strcmp(fileformat, 'ctf_old') - fileformat = filetype(filename); - end - - if strcmp(fileformat, 'ctf_ds') - filename = fullfile(p, [f x], [f '.hc']); - elseif strcmp(fileformat, 'ctf_meg4') - filename = fullfile(p, [f '.hc']); - elseif strcmp(fileformat, 'ctf_res4') - filename = fullfile(p, [f '.hc']); - end - - orig = read_ctf_hc(filename); - switch coordinates - case 'head' - shape.fid.pnt = cell2mat(struct2cell(orig.head)); - case 'dewar' - shape.fid.pnt = cell2mat(struct2cell(orig.dewar)); - otherwise - error('incorrect coordinates specified'); - end - shape.fid.label = fieldnames(orig.head); - - case 'ctf_shape' - orig = read_ctf_shape(filename); - shape.pnt = orig.pnt; - shape.fid.label = {'NASION', 'LEFT_EAR', 'RIGHT_EAR'}; - for i = 1:numel(shape.fid.label) - shape.fid.pnt = cat(1, shape.fid.pnt, ... - getfield(orig.MRI_Info, shape.fid.label{i})); - end - - case {'4d_xyz', '4d_m4d', '4d_hs', '4d', '4d_pdf'} - [p, f, x] = fileparts(filename); - if ~strcmp(fileformat, '4d_hs') - filename = fullfile(p, 'hs_file'); - end - [shape.pnt, fid] = read_bti_hs(filename); - - % I'm making some assumptions here - % which I'm not sure will work on all 4D systems - - %fid = fid(1:3, :); - - [junk, NZ] = max(fid(1:3,1)); - [junk, L] = max(fid(1:3,2)); - [junk, R] = min(fid(1:3,2)); - rest = setdiff(1:size(fid,1),[NZ L R]); - - shape.fid.pnt = fid([NZ L R rest], :); - shape.fid.label = {'NZ', 'L', 'R'}; - if ~isempty(rest), - for i = 4:size(fid,1) - shape.fid.label{i} = ['fiducial' num2str(i)]; - %in a 5 coil configuration this corresponds with Cz and Inion - end - end - case 'neuromag_mex' - [co,ki,nu] = hpipoints(filename); - fid = co(:,find(ki==1))'; - - [junk, NZ] = max(fid(:,2)); - [junk, L] = min(fid(:,1)); - [junk, R] = max(fid(:,1)); - - shape.fid.pnt = fid([NZ L R], :); - shape.fid.label = {'NZ', 'L', 'R'}; - - case {'neuromag_mne', 'neuromag_fif'} - hdr = read_header(filename,'headerformat','neuromag_mne'); - nFid = size(hdr.orig.dig,2); %work out number of fiducials - switch coordinates - case 'head' % digitiser points should be stored in head coordinates by default - - fidN=1; - pntN=1; - for i=1:nFid %loop over fiducials - %check this point is in head coordinates: - if hdr.orig.dig(i).coord_frame~=4 % 4 is MNE constant for head coordinates - error(['Digitiser point (' num2str(i) ') not stored in head coordinates!']); - end - - - switch hdr.orig.dig(i).kind % constants defined in MNE - see p.215 of MNE manual - case 1 % Cardinal point (nasion, LPA or RPA) - %get location of fiducial: - shape.fid.pnt(fidN,1:3) = hdr.orig.dig(i).r*100; %multiply by 100 to convert to cm - switch hdr.orig.dig(i).ident - case 1 % LPA - shape.fid.label{fidN} = 'LPA'; - case 2 % nasion - shape.fid.label{fidN} = 'Nasion'; - case 3 % RPA - shape.fid.label{fidN} = 'RPA'; - otherwise - error('Unidentified cardinal point in file!'); - end - fidN = fidN + 1; - - case 2 % HPI coil - shape.pnt(pntN,1:3) = hdr.orig.dig(i).r*100; - pntN = pntN + 1; - case 3 % EEG electrode location (or ECG) - shape.pnt(pntN,1:3) = hdr.orig.dig(i).r*100; - pntN = pntN + 1; - case 4 % Additional head point - shape.pnt(pntN,1:3) = hdr.orig.dig(i).r*100; - pntN = pntN + 1; - otherwise - warning('Unidentified digitiser point in file!'); - end - - end - shape.fid.label=shape.fid.label'; - - case 'dewar' - error('Dewar coordinates not supported for headshape yet (MNE toolbox)'); - otherwise - error('Incorrect coordinates specified'); - end - - case 'polhemus_fil' - [shape.fid.pnt, shape.pnt, shape.fid.label] = read_polhemus_fil(filename, 0); - - case 'spmeeg_mat' - tmp = load(filename); - if isfield(tmp.D, 'fiducials') && ~isempty(tmp.D.fiducials) - shape = tmp.D.fiducials; - else - error('no headshape found in SPM EEG file'); - end - - case 'matlab' - tmp = load(filename); - if isfield(tmp, 'shape') - shape = tmp.shape; - elseif isfield(tmp, 'elec') - shape.fid.pnt = tmp.elec.pnt; - shape.fid.label = tmp.elec.label; - else - error('no headshape found in Matlab file'); - end - - otherwise - - success = 0; - if ~success - % try reading it as electrode positions - % and treat those as fiducials - try - elec = read_sens(filename); - if ~senstype(elec, 'eeg') - error('headshape information can not be read from MEG gradiometer file'); - else - shape.fid.pnt = elec.pnt; - shape.fid.label = elec.label; - success = 1; - end - end - end - - if ~success - % try reading it as volume conductor - % and treat the skin surface as headshape - try - vol = read_vol(filename); - if ~voltype(vol, 'bem') - error('skin surface can only be extracted from boundary element model'); - else - if ~isfield(vol, 'skin') - vol.skin = find_outermost_boundary(vol.bnd); - end - shape.pnt = vol.bnd(vol.skin).pnt; - shape.tri = vol.bnd(vol.skin).tri; % also return the triangulation - success = 1; - end - end - end - - if ~success - error('unknown fileformat for head shape information'); - end -end - -shape.fid.label = shape.fid.label(:); - -% this will add the units to the head shape -shape = convert_units(shape); diff --git a/external/fileio/private/read_lay.m b/external/fileio/private/read_lay.m deleted file mode 100644 index 2eee348..0000000 --- a/external/fileio/private/read_lay.m +++ /dev/null @@ -1,14 +0,0 @@ -function [X,Y,Width,Height,Lbl] = read_lay(layoutname); - -% READ_LAY reads an electrode or gradiometer layout file -% Layout files are used for topoplotting and multiplotting. -% -% Use as -% [X, Y, Width, Height, Lbl] = read_lay(layoutname) - -if ~exist(layoutname, 'file') - error(sprintf('could not open layout file: %s', layoutname)); -end - -% discard the channel number -[chNum,X,Y,Width,Height,Lbl] = textread(layoutname,'%f %f %f %f %f %q'); diff --git a/external/fileio/private/read_mri.m b/external/fileio/private/read_mri.m deleted file mode 100644 index ecf08de..0000000 --- a/external/fileio/private/read_mri.m +++ /dev/null @@ -1,319 +0,0 @@ -function [mri] = read_mri(filename) - -% READ_MRI reads anatomical and functional MRI data from different -% file formats. The output data is structured in such a way that it is -% comparable to a FieldTrip source reconstruction. -% -% Use as -% [mri] = read_mri(filename) -% -% The output MRI may have a homogenous transformation matrix that converts -% the coordinates of each voxel (in xgrid/ygrid/zgrid) into head -% coordinates. -% -% See also READ_DATA, READ_HEADER, READ_EVENT - -% Copyright (C) 2004-2009, Robert Oostenveld -% -% $Log: read_mri.m,v $ -% Revision 1.11 2009/07/16 12:57:12 roboos -% fixed fprintf feedback for dicom reader -% -% Revision 1.10 2009/07/09 15:07:59 roboos -% use another coordinate transformation matrix for fif MRI -% -% Revision 1.9 2009/07/08 08:08:45 roboos -% also support mne toolbox fiff_read_mri function -% -% Revision 1.8 2009/07/07 10:40:37 roboos -% Improved handling of sequence of files, also when the files don't have nice names. -% Use SeriesNumber from the DICOM header to figure out which slices go together. -% -% Revision 1.7 2009/07/02 15:04:09 roboos -% construct transformation matrix for dicom files -% -% Revision 1.6 2009/03/11 15:02:18 vlalit -% Use either SPM5 or SPM8 to read *.nii files. -% -% Revision 1.5 2009/02/17 11:33:18 roboos -% renamed read_fcdc_mri to read_mri and moved to fileio -% -% Revision 1.19 2008/12/16 21:22:23 roboos -% changed some comments and documentation -% -% Revision 1.18 2008/11/28 10:25:51 roboos -% added ctf_mri4, thanks to Ivar -% -% Revision 1.17 2008/09/22 20:17:43 roboos -% added call to fieldtripdefs to the begin of the function -% -% Revision 1.16 2007/05/06 09:09:18 roboos -% added support for nifti, requires SPM5 -% -% Revision 1.15 2007/02/21 10:00:37 roboos -% give a more meaningfull warning when trying to read a mnc file without spm2 on the path -% -% Revision 1.14 2006/07/27 08:01:32 roboos -% use the hastoolbox function to detect the required toolboxes -% -% Revision 1.13 2006/04/19 15:46:43 roboos -% fixed bug for dicom when files are in another directory -% -% Revision 1.12 2006/04/19 07:54:51 roboos -% added support foir multifile DICOM format (searching for similar files) -% removed the trivial x/y/zgrid in the output structure -% -% Revision 1.11 2006/01/05 13:27:59 roboos -% change for avw_img_read(): force reading LAS* and flip the 1st dimension -% -% Revision 1.10 2005/09/08 07:32:48 roboos -% changed & into && -% modified hasafni to check for BrikInfo instead of WriteBrik -% -% Revision 1.9 2005/08/17 19:35:30 roboos -% added a check for the presence of the file, give error if not present -% -% Revision 1.8 2005/07/20 15:33:35 roboos -% added a homogenous transformation matrix to AFNI import section -% I am not sure whether it is correct, but it works like this for the TTatlas -% -% Revision 1.7 2005/05/17 17:50:38 roboos -% changed all "if" occurences of & and | into && and || -% this makes the code more compatible with Octave and also seems to be in closer correspondence with Matlab documentation on shortcircuited evaluation of sequential boolean constructs -% -% Revision 1.6 2004/10/28 09:41:20 roboos -% added preliminary support for AFNI mri files (no transformation matrix yet) using external afni_matlab toolbox -% -% Revision 1.5 2004/09/06 13:29:05 roboos -% fixed bug in transform for neuromag -% -% Revision 1.4 2004/09/03 09:17:49 roboos -% added support for neuromag MRI from fif file -% -% Revision 1.3 2004/08/26 12:12:50 roboos -% added transformation matrix for ASA files -% -% Revision 1.2 2004/08/26 11:57:22 roboos -% added support for MINC using SPM -% added support for Analyze using SPM -% -% Revision 1.1 2004/08/24 13:52:50 roboos -% new implementation, currently implemented are CTF, ASA and Analyze (with mri-toolbox) -% - -fieldtripdefs - -% test for the presence of some external functions from other toolboxes -hasmri = hastoolbox('mri'); % from Darren Weber, see http://eeg.sourceforge.net/ -hasspm2 = hastoolbox('spm2'); % see http://www.fil.ion.ucl.ac.uk/spm/ -hasspm5 = hastoolbox('spm5'); % see http://www.fil.ion.ucl.ac.uk/spm/ -hasspm8 = hastoolbox('spm8'); % see http://www.fil.ion.ucl.ac.uk/spm/ -hasspm = (hasspm2 || hasspm5 || hasspm8); -hasafni = hastoolbox('afni'); % see http://afni.nimh.nih.gov/ - -% test whether the file exists -if ~exist(filename) - error(sprintf('file ''%s'' does not exist', filename)); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if filetype(filename, 'ctf_mri') - [img, hdr] = read_ctf_mri(filename); - transform = hdr.transformMRI2Head; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif filetype(filename, 'ctf_mri4') - [img, hdr] = read_ctf_mri4(filename); - transform = hdr.transformMRI2Head; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif filetype(filename, 'asa_mri') - [img, seg, hdr] = read_asa_mri(filename); - transform = hdr.transformMRI2Head; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif filetype(filename, 'minc') - if ~hasspm - error('the SPM2 or SPM5 toolbox is required to read *.mnc files'); - end - % use the functions from SPM - hdr = spm_vol_minc(filename); - img = spm_read_vols(hdr); - transform = hdr.mat; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif filetype(filename, 'nifti') - if ~(hasspm5 || hasspm8) - error('the SPM5 or SPM8 toolbox is required to read *.nii files'); - end - % use the functions from SPM - hdr = spm_vol_nifti(filename); - img = spm_read_vols(hdr); - transform = hdr.mat; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif (filetype(filename, 'analyze_img') || filetype(filename, 'analyze_hdr')) && hasspm - % use the image file instead of the header - filename((end-2):end) = 'img'; - % use the functions from SPM to read the Analyze MRI - hdr = spm_vol(filename); - img = spm_read_vols(hdr); - transform = hdr.mat; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif (filetype(filename, 'analyze_hdr') || filetype(filename, 'analyze_img')) && hasmri - % use the functions from Darren Weber's mri_toolbox to read the Analyze MRI - avw = avw_img_read(filename, 0); % returned volume is LAS* - img = avw.img; - hdr = avw.hdr; - % The default Analyze orientation is axial unflipped (LAS*), which means - % that the resulting volume is according to the radiological convention. - % Most other fMRI and EEG/MEG software (except Mayo/Analyze) uses - % neurological conventions and a right-handed coordinate system, hence - % the first axis of the 3D volume (right-left) should be flipped to make - % the coordinate system comparable to SPM - warning('flipping 1st dimension (L-R) to obtain volume in neurological convention'); - img = flipdim(img, 1); - % FIXME: here I should also implement a homogenous transformation matrix, - % using the voxel dimensions that are specified in hdr.dime.pixdim - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif (filetype(filename, 'afni_brik') || filetype(filename, 'afni_head')) && hasafni - [err, img, hdr, ErrMessage] = BrikLoad(filename); - if err - error('could not read AFNI file'); - end - - % FIXME: this should be checked, but I only have a single BRIK file - % construct the homogenous transformation matrix that defines the axes - warning('homogenous transformation might be incorrect for AFNI file'); - transform = eye(4); - transform(1:3,4) = hdr.ORIGIN(:); - transform(1,1) = hdr.DELTA(1); - transform(2,2) = hdr.DELTA(2); - transform(3,3) = hdr.DELTA(3); - - % FIXME: I am not sure about the "RAI" image orientation - img = flipdim(img,1); - img = flipdim(img,2); - dim = size(img); - transform(1,4) = -dim(1) - transform(1,4); - transform(2,4) = -dim(2) - transform(2,4); - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif filetype(filename, 'neuromag_fif') && hastoolbox('mne') - % use the mne functions to read the Neuromag MRI - hdr = fiff_read_mri(filename); - img = cat(3, hdr.slices.data); - hdr.slices = rmfield(hdr.slices, 'data'); % remove the image data to save memory - % hmm, which transformation matrix should I use? - if issubfield(hdr.voxel_trans, 'trans') - transform = hdr.voxel_trans.trans; - elseif issubfield(hdr.trans, 'trans') - transform = hdr.trans.trans; - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif filetype(filename, 'neuromag_fif') && hastoolbox('meg_pd') - % use the meg_pd functions to read the Neuromag MRI - [img,coords] = loadmri(filename); - dev = loadtrans(filename,'MRI','HEAD'); - transform = dev*coords; - hdr.coords = coords; - hdr.dev = dev; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif filetype(filename, 'neuromag_fif') - error('reading MRI data from a fif file requires either the MNE toolbox or the meg_pd toolbox to be installed'); - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif filetype(filename, 'dicom') - % this uses the Image processing toolbox - % the DICOM file probably represents a stack of slices, possibly even multiple volumes - orig = dicominfo(filename); - dim(1) = orig.Rows; - dim(2) = orig.Columns; - - [p, f] = fileparts(filename); - - % this works for the Siemens scanners at the FCDC - tok = tokenize(f, '.'); - for i=5:length(tok) - tok{i} = '*'; - end - filename = sprintf('%s.', tok{:}); % reconstruct the filename with wildcards and '.' between the segments - filename = filename(1:end-1); % remove the last '.' - dirlist = dir(fullfile(p, filename)); - dirlist = {dirlist.name}; - - if length(dirlist)==1 - % try something else to get a list of all the slices - dirlist = dir(fullfile(p, '*')); - dirlist = {dirlist(~[dirlist.isdir]).name}; - end - - keep = false(1, length(dirlist)); - for i=1:length(dirlist) - filename = char(fullfile(p, dirlist{i})); - if ~filetype(filename, 'dicom') - keep(i) = false; - fprintf('skipping ''%s'' because of incorrect filetype\n', filename); - end - % read the header information - info = dicominfo(filename); - if info.SeriesNumber~=orig.SeriesNumber - keep(i) = false; - fprintf('skipping ''%s'' because of different SeriesNumber\n', filename); - else - keep(i) = true; - hdr(i) = info; - end - end - % remove the files that were skipped - hdr = hdr(keep); - dirlist = dirlist(keep); - - % pre-allocate enough space for the subsequent slices - dim(3) = length(dirlist); - img = zeros(dim(1), dim(2), dim(3)); - for i=1:length(dirlist) - filename = char(fullfile(p, dirlist{i})); - fprintf('reading image data from ''%s''\n', filename); - img(:,:,i) = dicomread(hdr(i)); - end - - % reorder the slices - [z, indx] = sort(cell2mat({hdr.SliceLocation})); - hdr = hdr(indx); - img = img(:,:,indx); - - try - % construct a homgenous transformation matrix that performs the scaling from voxels to mm - dx = hdr(1).PixelSpacing(1); - dy = hdr(1).PixelSpacing(2); - dz = hdr(2).SliceLocation - hdr(1).SliceLocation; - transform = eye(4); - transform(1,1) = dx; - transform(2,2) = dy; - transform(3,3) = dz; - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -else - error(sprintf('unrecognized filetype of ''%s''', filename)); -end - -% set up the axes of the volume in voxel coordinates -nx = size(img,1); -ny = size(img,2); -nz = size(img,3); -mri.dim = [nx ny nz]; -% store the anatomical data -mri.anatomy = img; -% store the header with all fileformat specific details -mri.hdr = hdr; -try - % if present, store the homogenous transformation matrix - mri.transform = transform; -end - diff --git a/external/fileio/private/read_neuralynx_cds.m b/external/fileio/private/read_neuralynx_cds.m deleted file mode 100644 index 9500d84..0000000 --- a/external/fileio/private/read_neuralynx_cds.m +++ /dev/null @@ -1,158 +0,0 @@ -function [dat] = read_neuralynx_cds(filename, hdr, begsample, endsample, chanindx); - -% READ_NEURALYNX_CDS reads selected samples and channels from a combined Neuralynx dataset with seperate subdirectories for the LFP, MUA and spike channels -% -% Use as -% hdr = read_neuralynx_cds(parentdir) -% dat = read_neuralynx_cds(parentdir, hdr, begsample, endsample, chanindx) - -% Copyright (C) 2006, Robert Oostenveld -% -% $Log: read_neuralynx_cds.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.1 2006/12/13 15:45:57 roboos -% new implementation, partially based on the old read_neuralynx_data and header function, but now more strongly relying on the xxx_ds function that reads header and data information from all datasets that are combined -% - -needhdr = (nargin==1); -needdat = (nargin>=2); - -dirlist = dir(filename); -haslfp = any(filetype_check_extension({dirlist.name}, 'lfp')); -hasmua = any(filetype_check_extension({dirlist.name}, 'mua')); -hasspike = any(filetype_check_extension({dirlist.name}, 'spike')); -%hasttl = any(filetype_check_extension({dirlist.name}, 'ttl')); % seperate file with original Parallel_in -%hastsl = any(filetype_check_extension({dirlist.name}, 'tsl')); % seperate file with original TimeStampLow -%hastsh = any(filetype_check_extension({dirlist.name}, 'tsh')); % seperate file with original TimeStampHi - -if needhdr - % read the header from the LFP dataset - if haslfp - lfpdir = fullfile(filename, dirlist(find(filetype_check_extension({dirlist.name}, 'lfp'))).name); - lfphdr = read_header(lfpdir); - lfpfil = lfphdr.filename; - for i=1:lfphdr.nChans - lfplab{i} = sprintf('lfp_%s', lfphdr.label{i}); - end - else - lfphdr = []; - lfpfil = {}; - lfplab = {}; - end - - % read the header from the MUA dataset - if hasmua - muadir = fullfile(filename, dirlist(find(filetype_check_extension({dirlist.name}, 'mua'))).name); - muahdr = read_header(muadir); - muafil = muahdr.filename; - for i=1:muahdr.nChans - mualab{i} = sprintf('mua_%s', muahdr.label{i}); - end - else - muahdr = []; - muafil = {}; - mualab = {}; - end - - % read the header from the SPIKE dataset - if hasspike - spikedir = fullfile(filename, dirlist(find(filetype_check_extension({dirlist.name}, 'spike'))).name); - spikehdr = read_header(spikedir); - spikefil = spikehdr.filename; - for i=1:spikehdr.nChans - spikelab{i} = sprintf('spike_%s', spikehdr.label{i}); - end - else - spikehdr = []; - spikefil = {}; - spikelab = {}; - end - - if haslfp - % assume that the LFP header describes the MUA and the spikes as well - hdr = lfphdr; - else hasmua - % assume that the MUA header describes the spikes as well - hdr = muahdr; - end - - % concatenate the lfp/mua/spike channels, they have already been renamed - hdr.label = cat(1, lfplab(:), mualab(:), spikelab(:)); - hdr.filename = cat(1, lfpfil(:), muafil(:), spikefil(:)); - hdr.nChans = length(hdr.label); - % remember the original header details - hdr.orig = {}; - hdr.orig{1} = lfphdr; - hdr.orig{2} = muahdr; - hdr.orig{3} = spikehdr; - - % return the header - dat = hdr; -else - - % use the original header details - lfphdr = hdr.orig{1}; - muahdr = hdr.orig{2}; - spikehdr = hdr.orig{3}; - % the spike header does not contain these, but requires them from the LFP or MUA - spikehdr.FirstTimeStamp = hdr.FirstTimeStamp; - spikehdr.TimeStampPerSample = hdr.TimeStampPerSample; - - if ~isempty(lfphdr) - Nlfp = lfphdr.nChans; - else - Nlfp = 0; - end - - if ~isempty(muahdr) - Nmua = muahdr.nChans; - else - Nmua = 0; - end - - if ~isempty(spikehdr) - Nspike = spikehdr.nChans; - else - Nspike = 0; - end - - % determine which files should be read from each respective dataset - selchan = zeros(hdr.nChans,1); - selchan(chanindx) = 1; - sellfp = find(selchan(1:Nlfp)); - selmua = find(selchan((Nlfp+1):(Nlfp+Nmua))); - selspike = find(selchan((Nlfp+Nmua+1):(Nlfp+Nmua+Nspike))); - - if haslfp - % the header contains the relevant file names - lfpdat = read_neuralynx_ds([], lfphdr, begsample, endsample, sellfp); - else - lfpdat = []; - end - - if hasmua - % the header contains the relevant file names - muadat = read_neuralynx_ds([], muahdr, begsample, endsample, selmua); - else - muadat = []; - end - - if hasspike - % the header contains the relevant file names - spikedat = read_neuralynx_ds([], spikehdr, begsample, endsample, selspike); - else - spikedat = []; - end - - % combine all data into a single array - dat = cat(1, lfpdat, muadat, spikedat); - -end - diff --git a/external/fileio/private/read_neuralynx_dma.m b/external/fileio/private/read_neuralynx_dma.m deleted file mode 100644 index 996d472..0000000 --- a/external/fileio/private/read_neuralynx_dma.m +++ /dev/null @@ -1,339 +0,0 @@ -function [dat] = read_neuralynx_dma(filename, begsample, endsample, channel); - -% READ_NEURALYNX_DMA reads specified samples and channels data from a Neuralynx DMA log file -% -% Use as -% [hdr] = read_neuralynx_dma(filename) -% [dat] = read_neuralynx_dma(filename, begsample, endsample) -% [dat] = read_neuralynx_dma(filename, begsample, endsample, chanindx) -% -% The channel specification can be a vector with indices, or a single string with the value -% 'all', 'stx', 'pid', 'siz', 'tsh', 'tsl', -% 'cpu', 'ttl', 'x01', ..., 'x10' -% -% This function returns the electrophysiological data in AD units -% and not in uV. You should look up the details of the headstage and -% the Neuralynx amplifier and scale the values accordingly. - -% Copyright (C) 2005-2008, Robert Oostenveld -% -% $Log: read_neuralynx_dma.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.21 2008/12/15 09:40:33 roboos -% added comment in help about scaling in AD values -% -% Revision 1.20 2008/06/13 12:47:23 roboos -% added check on STX to detect discontinuous recordings (and give error) -% -% Revision 1.19 2007/12/12 11:30:28 roboos -% remember the offset of the data (header+jumk) in hdr.orig.Offset -% -% Revision 1.18 2007/10/31 14:11:26 roboos -% fixed CRC problem with the file format that was introduced in Cheetah 5.0, where the first packet could be incomplete and hence all subsequent packets are shifted -% fixed bug in getting the LastTimestamp (read as uint32 instead of int32) -% -% Revision 1.17 2007/10/25 12:48:27 roboos -% moved the reading of the ascii header to another place in the code, no functional change -% -% Revision 1.16 2007/06/13 18:53:07 roboos -% fixed bug: in the detection of header size and channel count the file was opened but not closed due to missing fclose() -% -% Revision 1.15 2007/04/02 15:12:56 roboos -% fixed detextion of ascii header (>32 should be >31) -% -% Revision 1.14 2007/03/26 12:38:19 roboos -% also detect ascii headers that do not start with '####' -% -% Revision 1.13 2007/03/19 16:57:36 roboos -% fixed bug due to hard-coded number of boards (nchans is now flexible and not always 274) -% -% Revision 1.12 2007/02/21 09:55:06 roboos -% fixed bug in TimeStampsPerSample (should be divided by nsamples-1) -% -% Revision 1.11 2007/02/20 08:55:00 roboos -% implemented automatic detection of the number of boards and channels by using the CRC value -% added the ascii header to the output -% -% Revision 1.10 2007/01/09 09:41:49 roboos -% read low and high timestamp as uint32, use seperate function to combaine them into a uint64 -% -% Revision 1.9 2006/12/12 11:37:08 roboos -% read either header or data from the file -% treat datachannels and special channels the same (i.e. a file now consists of 274 'channels') -% cleaned up code, made more consistent with other functions -% allow specification of channels using either channel labels, or using channel indices -% -% Revision 1.8 2006/04/24 12:19:19 roboos -% added support for reading all channels, including the status channels -% -% Revision 1.7 2006/03/14 10:28:45 roboos -% fixed bug in read_neuralynx_dma: when reading a single (special) channel with begsample~=1 it did not skip to the begin sample -% -% Revision 1.6 2006/03/10 12:26:08 roboos -% fixed bug in reading of LastTimeStamp -% -% Revision 1.5 2006/03/06 09:50:45 roboos -% added support for reading a single special channel at a time, using the skip parameter in fread (usefull for ttl) -% -% Revision 1.4 2006/03/02 08:46:11 roboos -% account for the optional 16384 byte header introduced in v4.80 -% -% Revision 1.3 2005/10/14 07:05:10 roboos -% added the first and last timestamp to the output header -% -% Revision 1.2 2005/09/09 12:32:00 roboos -% changed spacing and indentation, no functional change -% -% Revision 1.1 2005/09/05 13:05:44 roboos -% new implementation - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% The data is simply a stream of constant size records, the size of the -% record is dependant on the number of Input Boards in the system. 8 in your -% case, there are 32 - 32 bit integers from each Input Board. -% -% // Digital Lynx Packets look like this for a 1 board system: -% // stx (or SOP) 0x00000800 -% // Packet ID 0x00000001 -% // siz 0x0000002A (# A/D data ints + #extra wds = 32+10) -% // TimeStamp Hi 1 32 bit word -% // TimeStamp Low 1 32 bit word -% // cpu 1 32 bit word -% // ttl 1 32 bit word -% // 10 extras 10 32 bit words -% // A/D data 32 32 bit words per board -% // CRC 1 32 bit XOR of the entire packet including stx -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -needhdr = (nargin==1); -needdat = (nargin>=2); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% since Cheetah 4.80 the DMS log files have a 16384 byte header -% determine whether that is the case in this file -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -fid = fopen(filename, 'rb', 'ieee-le'); -buf = fread(fid, 10, 'uchar=>uchar'); -if all(buf(1:4)==35) - % the file starts with "####" - hdroffset = 16384; -elseif all(buf>31 & buf<127) - % the file does not start with "####" but the header seems to be ascii anyway - hdroffset = 16384; -else - hdroffset = 0; -end - -if hdroffset - % read the ascii header from the file, it does not contain much usefull information - orig = neuralynx_getheader(filename); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% since Cheetah 5.0 the DMA log file does not always start with a complete -% packet but can start with an incomplete "junk" packet after the header. -% The junk due to that incomplete packet should then also be skipped. -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if hdroffset - % skip the standard ascii header - fseek(fid, hdroffset, 'bof'); - % read a single block - buf = fread(fid, 274, 'uint32=>uint32'); - % search for the first known values of a proper packet - junk = find((buf(1:(end-1))==2048) & (buf(2:(end-0))==1), 1) - 1; - if ~isempty(junk) - % add the additional junk samples to the header offset - hdroffset = hdroffset + junk*4; - end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% since modifying our hardware from 256 to 32 channel (19 March 2007), the -% number of channels in a DMA log file can vary. Start with the assumption -% that the file is from the 256 channel system with 8 boards that we have -% in Nijmegen and verify the CRC -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -nboards = 8; -nchanboard = 32; -blocksize = nboards*nchanboard+18; % in 4 byte words -fseek(fid, hdroffset, 'bof'); -% read a single block -buf = fread(fid, blocksize, 'uint32=>uint32'); -% determine the number of boards by systematically checking the CRC value -while (nboards>0) - if neuralynx_crc(buf(1:blocksize-1))==buf(blocksize) - % the CRC is correct for this number of boards - break - else - nboards = nboards - 1; % decrease by one - blocksize = nboards*nchanboard+18; % in 4 byte words - end -end -fclose(fid); - -if ~nboards - error('could not determine the number of boards and channels'); -end - -% deal with ascii and numeric input for the channel selection -if nargin>3 && ~ischar(channel) - chanindx = channel; - channel = 'selection'; -elseif nargin>3 && ischar(channel) - switch channel - case 'stx' - chanindx = 1; - case 'pid' - chanindx = 2; - case 'siz' - chanindx = 3; - case 'tsh' - chanindx = 4; - case 'tsl' - chanindx = 5; - case 'cpu' - chanindx = 6; - case 'ttl' - chanindx = 7; - case 'x01' - chanindx = 8; - case 'x02' - chanindx = 9; - case 'x03' - chanindx = 10; - case 'x04' - chanindx = 11; - case 'x05' - chanindx = 12; - case 'x06' - chanindx = 13; - case 'x07' - chanindx = 14; - case 'x08' - chanindx = 15; - case 'x09' - chanindx = 16; - case 'x10' - chanindx = 17; - case 'crc' - chanindx = blocksize; - case 'all' - chanindx = 1:blocksize; - otherwise - error('unknown value in channel'); - end -elseif nargin<4 - channel = 'all'; - chanindx = 1:blocksize; -end - -if needhdr - % these have to be hardcoded, since the DMA logfile does not contain header information - hdr = []; - if hdroffset - % remember the ascii header from the file, it does not contain much usefull information - hdr.orig = orig; - end - hdr.Fs = 32556; % sampling frequency - hdr.nChans = nboards*nchanboard; % number of analog channels - hdr.nSamples = inf; % number of samples per trial - hdr.nSamplesPre = 0; % number of pre-trigger samples in each trial - hdr.nTrials = 1; % number of trials - hdr.label = {}; % cell-array with labels of each channel - for i=1:hdr.nChans - chanlabel{i} = sprintf('csc%03d', i); - end - statuslabel = { - 'stx' - 'pid' - 'siz' - 'tsh' - 'tsl' - 'cpu' - 'ttl' - 'x01' - 'x02' - 'x03' - 'x04' - 'x05' - 'x06' - 'x07' - 'x08' - 'x09' - 'x10' - }; - hdr.label = cat(1, statuslabel(:), chanlabel(:), {'crc'}); % concatenate all channel labels - hdr.nChans = length(hdr.label); % this includes all channels - % determine the length of the file, expressed in samples - fid = fopen(filename, 'rb', 'ieee-le'); - fseek(fid, 0, 'eof'); - hdr.nSamples = floor((ftell(fid)-hdroffset)/(blocksize*4)); - - % determine the timestamp of the first and of the last sample - datoffset = 0*blocksize; - fseek(fid, hdroffset + datoffset, 'bof'); - buf = fread(fid, blocksize, 'uint32=>uint32'); - beg_stx = buf(1); - beg_tsh = buf(4); - beg_tsl = buf(5); - datoffset = (hdr.nSamples-1)*blocksize*4; - fseek(fid, hdroffset + datoffset, 'bof'); - buf = fread(fid, blocksize, 'uint32=>uint32'); - end_stx = buf(1); - end_tsh = buf(4); - end_tsl = buf(5); - fclose(fid); - % check that the junk at the beginning was correctly detected - if (beg_stx~=2048) - error('problem with STX at the begin of the file'); - end - % check that the file is truely continuous, i.e. no gaps with junk in between - if (end_stx~=2048) - error('problem with STX at the end of the file'); - end - % combine the two uint32 words into a uint64 - hdr.FirstTimeStamp = timestamp_neuralynx(beg_tsl, beg_tsh); - hdr.LastTimeStamp = timestamp_neuralynx(end_tsl, end_tsh); - hdr.TimeStampPerSample = double(hdr.LastTimeStamp-hdr.FirstTimeStamp)./(hdr.nSamples-1); % this should be double, since it can be fractional - - % only return the header information - dat = hdr; - dat.orig.Offset = hdroffset; - -elseif length(chanindx)>1 - % read the desired samples for all channels - fid = fopen(filename, 'rb', 'ieee-le'); - datoffset = (begsample-1)*blocksize*4; - fseek(fid, hdroffset + datoffset, 'bof'); % skip the header and samples that do not have to be read - % read the data - dat = fread(fid, [blocksize (endsample-begsample+1)], 'int32=>int32'); - fclose(fid); - if size(dat,2)<(endsample-begsample+1) - error('could not read all samples'); - end - if ~strcmp(channel, 'all') - % select the subset of desired channels - dat = dat(chanindx,:); - end - -elseif length(chanindx)==1 - % read the desired samples for only one channel - fid = fopen(filename, 'rb', 'ieee-le'); - datoffset = (begsample-1)*blocksize*4; - fseek(fid, hdroffset + datoffset, 'bof'); % skip the header and samples that do not have to be read - fseek(fid, (chanindx-1)*4, 'cof'); % skip to the channel of interest - % Note that the last block with 274*4 bytes can sometimes be incomplete, which is relevant when endsample=inf - dat = fread(fid, [1 (endsample-begsample+1)], 'int32=>int32', (nboards*32+18-1)*4); - if size(dat,2)<(endsample-begsample+1) - error('could not read all samples'); - end - fclose(fid); -end - diff --git a/external/fileio/private/read_neuralynx_ncs.m b/external/fileio/private/read_neuralynx_ncs.m deleted file mode 100644 index 2386c18..0000000 --- a/external/fileio/private/read_neuralynx_ncs.m +++ /dev/null @@ -1,142 +0,0 @@ -function [ncs] = read_neuralynx_ncs(filename, begrecord, endrecord) - -% READ_NEURALYNX_NCS reads a single continuous channel file -% -% Use as -% [ncs] = read_neuralynx_ncs(filename) -% [ncs] = read_neuralynx_ncs(filename, begrecord, endrecord) - -% Copyright (C) 2005-2007, Robert Oostenveld -% -% $Log: read_neuralynx_ncs.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.13 2008/04/29 07:52:31 roboos -% fixed windows related bug -% be consistent with begin and end timestamp in header -% -% Revision 1.12 2008/01/10 12:51:57 roboos -% ensure that it is possible to read only the header, using beg/end = 0/0 -% -% Revision 1.11 2007/03/21 17:06:57 roboos -% updated the documentation -% -% Revision 1.10 2006/12/13 15:46:31 roboos -% read and keep timestamps as uint64 -% -% Revision 1.9 2006/12/12 11:31:31 roboos -% cleaned up the code, made code more consistent with other neuralynx functions, moved subfunctions to seperate files, use numeric arrays instead of cell-arrays for storing the data -% -% Revision 1.8 2006/03/29 15:01:30 roboos -% fix for previous update: only apply the scaling to uV if data has been read -% -% Revision 1.7 2006/03/29 14:43:26 roboos -% scale the output data to uV, using ADBitVolts and an additional 1e6 -% -% Revision 1.6 2006/03/23 18:02:13 roboos -% change endrecord from inf into the actual number present -% -% Revision 1.5 2006/03/13 16:02:55 roboos -% added first and last timestamp to the output header -% -% Revision 1.4 2006/03/10 12:32:24 roboos -% preallocate enough memory for all elements (prevent repeated memory-reallocatoin and copying) -% -% Revision 1.3 2005/11/23 08:05:23 roboos -% changed while into for-loop -% added error check for end of file in fseek -% check validity of selected begin and end record -% -% Revision 1.2 2005/09/09 12:29:38 roboos -% changed from dox to unix ascii -% changed the looping over the records -% add the number of records in the output -% -% Revision 1.1 2005/05/20 06:39:35 roboos -% new implementation of single file readers -% - -if nargin<2 - begrecord = 1; -end -if nargin<3 - endrecord = inf; -end - -% the file starts with a 16*1024 bytes header in ascii, followed by a number of records -hdr = neuralynx_getheader(filename); -fid = fopen(filename, 'rb', 'ieee-le'); - -% determine the length of the file -fseek(fid, 0, 'eof'); -headersize = 16384; -recordsize = 1044; -NRecords = floor((ftell(fid) - headersize)/recordsize); - -if NRecords>0 - if (ispc), fclose(fid); end - % read the timestamp from the first and last record - hdr.FirstTimeStamp = neuralynx_timestamp(filename, 1); - hdr.LastTimeStamp = neuralynx_timestamp(filename, inf); - if (ispc), fid = fopen(filename, 'rb', 'ieee-le'); end -else - hdr.FirstTimeStamp = nan; - hdr.LastTimeStamp = nan; -end - -if begrecord==0 && endrecord==0 - % only read the header -elseif begrecord<1 - error('cannot read before the first record'); -elseif begrecord>NRecords - error('cannot read beyond the last record') -elseif endrecord>NRecords - endrecord = NRecords; -end - -if begrecord>=1 && endrecord>=begrecord - % rewind to the first record to be read - status = fseek(fid, headersize + (begrecord-1)*recordsize, 'bof'); - if status~=0 - error('cannot jump to the requested record'); - end - - numrecord = (endrecord-begrecord+1); - TimeStamp = zeros(1,numrecord,'uint64'); - ChanNumber = zeros(1,numrecord); - SampFreq = zeros(1,numrecord); - NumValidSamp = zeros(1,numrecord); - Samp = zeros(512,numrecord); % this allows easy reshaping into a 1xNsamples vector - - for k=1:numrecord - % read a single continuous data record - TimeStamp(k) = fread(fid, 1, 'uint64=>uint64'); - ChanNumber(k) = fread(fid, 1, 'int32'); - SampFreq(k) = fread(fid, 1, 'int32'); - NumValidSamp(k) = fread(fid, 1, 'int32'); - Samp(:,k) = fread(fid, 512, 'int16'); - % mark the invalid samples - Samp((NumValidSamp+1):end,k) = nan; - end - - % store the record data in the output structure - ncs.TimeStamp = TimeStamp; - ncs.ChanNumber = ChanNumber; - ncs.SampFreq = SampFreq; - ncs.NumValidSamp = NumValidSamp; - % apply the scaling factor from ADBitVolts and convert to uV - ncs.dat = Samp * hdr.ADBitVolts * 1e6; - -end -fclose(fid); - -% store the header info in the output structure -ncs.NRecords = NRecords; -ncs.hdr = hdr; - diff --git a/external/fileio/private/read_neuralynx_nse.m b/external/fileio/private/read_neuralynx_nse.m deleted file mode 100644 index 2bbc367..0000000 --- a/external/fileio/private/read_neuralynx_nse.m +++ /dev/null @@ -1,126 +0,0 @@ -function [nse] = read_neuralynx_nse(filename, begrecord, endrecord) - -% READ_NEURALYNX_NSE reads a single electrode waveform file -% -% Use as -% [nse] = read_neuralynx_nse(filename) -% [nse] = read_neuralynx_nse(filename, begrecord, endrecord) - -% Copyright (C) 2005-2007, Robert Oostenveld -% -% $Log: read_neuralynx_nse.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.11 2008/04/29 07:52:31 roboos -% fixed windows related bug -% be consistent with begin and end timestamp in header -% -% Revision 1.10 2008/01/10 12:51:57 roboos -% ensure that it is possible to read only the header, using beg/end = 0/0 -% -% Revision 1.9 2007/12/12 16:29:20 roboos -% add first and last timestamp to header, also when no records are read -% -% Revision 1.8 2007/03/21 17:06:57 roboos -% updated the documentation -% -% Revision 1.7 2006/12/13 15:46:31 roboos -% read and keep timestamps as uint64 -% -% Revision 1.6 2006/12/12 11:31:31 roboos -% cleaned up the code, made code more consistent with other neuralynx functions, moved subfunctions to seperate files, use numeric arrays instead of cell-arrays for storing the data -% -% Revision 1.5 2006/03/29 15:01:30 roboos -% fix for previous update: only apply the scaling to uV if data has been read -% -% Revision 1.4 2006/03/29 14:43:26 roboos -% scale the output data to uV, using ADBitVolts and an additional 1e6 -% -% Revision 1.3 2006/03/23 18:02:44 roboos -% change endrecord from inf into the actual number present -% preallocate memory to hold the results -% -% Revision 1.2 2005/09/09 12:30:08 roboos -% implemented the core functionality -% -% Revision 1.1 2005/08/05 13:41:39 roboos -% new implementation -% - -if nargin<2 - begrecord = 1; -end -if nargin<3 - endrecord = inf; -end - -% the file starts with a 16*1024 bytes header in ascii, followed by a number of records -hdr = neuralynx_getheader(filename); -fid = fopen(filename, 'rb', 'ieee-le'); - -% determine the length of the file -fseek(fid, 0, 'eof'); -headersize = 16384; -recordsize = 112; -NRecords = floor((ftell(fid) - headersize)/recordsize); - -if NRecords>0 - if (ispc), fclose(fid); end - % read the timestamp from the first and last record - hdr.FirstTimeStamp = neuralynx_timestamp(filename, 1); - hdr.LastTimeStamp = neuralynx_timestamp(filename, inf); - if (ispc), fid = fopen(filename, 'rb', 'ieee-le'); end -else - hdr.FirstTimeStamp = nan; - hdr.LastTimeStamp = nan; -end - -if begrecord==0 && endrecord==0 - % only read the header -elseif begrecord<1 - error('cannot read before the first record'); -elseif begrecord>NRecords - error('cannot read beyond the last record') -elseif endrecord>NRecords - endrecord = NRecords; -end - -if begrecord>=1 && endrecord>=begrecord - % rewind to the first record to be read - fseek(fid, headersize + (begrecord-1)*recordsize, 'bof'); - - numrecord = (endrecord-begrecord+1); - TimeStamp = zeros(1,numrecord,'uint64'); - ScNumber = zeros(1,numrecord); - CellNumber = zeros(1,numrecord); - Param = zeros(8,numrecord); - Samp = zeros(32,numrecord); - - k = 1; - while (begrecord+k-1)<=endrecord - % read a single electrode record - TimeStamp(k) = fread(fid, 1, 'uint64=>uint64'); - ScNumber(k) = fread(fid, 1, 'int32'); - CellNumber(k) = fread(fid, 1, 'int32'); - Param(:,k) = fread(fid, 8, 'int32'); - Samp(:,k) = fread(fid, 32, 'int16'); - k = k + 1; - end - - nse.TimeStamp = TimeStamp; - nse.ScNumber = ScNumber; - nse.CellNumber = CellNumber; - nse.Param = Param; - % apply the scaling factor from ADBitVolts and convert to uV - nse.dat = Samp * hdr.ADBitVolts * 1e6; -end -fclose(fid); - -nse.NRecords = NRecords; -nse.hdr = hdr; diff --git a/external/fileio/private/read_neuralynx_nts.m b/external/fileio/private/read_neuralynx_nts.m deleted file mode 100644 index e20352d..0000000 --- a/external/fileio/private/read_neuralynx_nts.m +++ /dev/null @@ -1,95 +0,0 @@ -function [nts] = read_neuralynx_nts(filename, begrecord, endrecord); - -% READ_NEURALYNX_NTS reads spike timestamps -% -% Use as -% [nts] = read_neuralynx_nts(filename) -% [nts] = read_neuralynx_nts(filename, begrecord, endrecord) - -% Copyright (C) 2006-2007, Robert Oostenveld -% -% $Log: read_neuralynx_nts.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.4 2008/04/29 07:52:31 roboos -% fixed windows related bug -% be consistent with begin and end timestamp in header -% -% Revision 1.3 2008/01/10 12:51:58 roboos -% ensure that it is possible to read only the header, using beg/end = 0/0 -% -% Revision 1.2 2007/12/12 16:29:19 roboos -% add first and last timestamp to header, also when no records are read -% -% Revision 1.1 2007/03/21 17:12:04 roboos -% renamed NTE in NTS (filenames and function names) -% -% Revision 1.4 2007/03/21 17:06:57 roboos -% updated the documentation -% -% Revision 1.3 2007/03/21 12:54:37 roboos -% included the 2nd and 3rd input arguments in the function declaration -% -% Revision 1.2 2007/03/19 16:58:08 roboos -% implemented the actual reading of the data from file -% -% Revision 1.1 2006/12/13 15:52:26 roboos -% added empty function, only containing help but no usefull code yet -% - -if nargin<2 - begrecord = 1; -end -if nargin<3 - endrecord = inf; -end - -% the file starts with a 16*1024 bytes header in ascii, followed by a number of records -hdr = neuralynx_getheader(filename); -fid = fopen(filename, 'rb', 'ieee-le'); - -% determine the length of the file -fseek(fid, 0, 'eof'); -headersize = 16384; -recordsize = 8; -NRecords = floor((ftell(fid) - headersize)/recordsize); - -if begrecord==0 && endrecord==0 - % only read the header -elseif begrecord<1 - error('cannot read before the first record'); -elseif begrecord>NRecords - error('cannot read beyond the last record') -elseif endrecord>NRecords - endrecord = NRecords; -end - -if NRecords>0 - if (ispc), fclose(fid); end - % read the timestamp from the first and last record - hdr.FirstTimeStamp = neuralynx_timestamp(filename, 1); - hdr.LastTimeStamp = neuralynx_timestamp(filename, inf); - if (ispc), fid = fopen(filename, 'rb', 'ieee-le'); end -else - hdr.FirstTimeStamp = nan; - hdr.LastTimeStamp = nan; -end - -if begrecord>=1 && endrecord>=begrecord - % rewind to the first record to be read - fseek(fid, headersize + (begrecord-1)*recordsize, 'bof'); - numrecord = (endrecord-begrecord+1); - TimeStamp = fread(fid, numrecord, 'uint64=>uint64'); - - nts.TimeStamp = TimeStamp; -end -fclose(fid); - -nts.NRecords = NRecords; -nts.hdr = hdr; diff --git a/external/fileio/private/read_neuralynx_ntt.m b/external/fileio/private/read_neuralynx_ntt.m deleted file mode 100644 index 018648d..0000000 --- a/external/fileio/private/read_neuralynx_ntt.m +++ /dev/null @@ -1,124 +0,0 @@ -function [ntt] = read_neuralynx_ntt(filename, begrecord, endrecord) - -% READ_NEURALYNX_NTT reads a single tetrode file -% -% Use as -% [ntt] = read_neuralynx_ntt(filename) -% [ntt] = read_neuralynx_ntt(filename, begrecord, endrecord) - -% Copyright (C) 2005, Robert Oostenveld -% -% $Log: read_neuralynx_ntt.m,v $ -% Revision 1.7 2008/04/29 07:52:31 roboos -% fixed windows related bug -% be consistent with begin and end timestamp in header -% -% Revision 1.6 2008/03/04 11:16:11 roboos -% do not convert to uV, since ADBitVolts seems not always to be present in the header -% fixed bug in output assignment of Nrecords -% -% Revision 1.5 2008/01/10 12:51:58 roboos -% ensure that it is possible to read only the header, using beg/end = 0/0 -% -% Revision 1.4 2006/12/13 15:46:31 roboos -% read and keep timestamps as uint64 -% -% Revision 1.3 2006/12/12 11:31:31 roboos -% cleaned up the code, made code more consistent with other neuralynx functions, moved subfunctions to seperate files, use numeric arrays instead of cell-arrays for storing the data -% -% Revision 1.2 2006/03/29 15:00:46 roboos -% changed some whitespace -% -% Revision 1.1 2005/05/20 06:39:35 roboos -% new implementation of single file readers -% - -if nargin<2 - begrecord = 1; -end -if nargin<3 - endrecord = inf; -end - -% The file starts with a 16*1024 bytes header in ascii, followed by a -% number of records (c.f. trials). - -% The format of a tetrode record is -% int64 TimeStamp -% int32 ScNumber -% int32 CellNumber -% int32 Param[0] ƒ ƒ int32 Param[7] -% int16 ChanW[0] -% int16 ChanX[0] -% int16 ChanY[0] -% int16 ChanZ[0] ƒ ƒ -% int16 ChanW[31] -% int16 ChanX[31] -% int16 ChanY[31] -% int16 ChanZ[31] - -hdr = neuralynx_getheader(filename); -fid = fopen(filename, 'rb', 'ieee-le'); - -% determine the length of the file -fseek(fid, 0, 'eof'); -headersize = 16384; -recordsize = 304; -NRecords = floor((ftell(fid) - headersize)/recordsize); - -if NRecords>0 - if (ispc), fclose(fid); end - % read the timestamp from the first and last record - hdr.FirstTimeStamp = neuralynx_timestamp(filename, 1); - hdr.LastTimeStamp = neuralynx_timestamp(filename, inf); - if (ispc), fid = fopen(filename, 'rb', 'ieee-le'); end -else - hdr.FirstTimeStamp = nan; - hdr.LastTimeStamp = nan; -end - -if begrecord==0 && endrecord==0 - % only read the header -elseif begrecord<1 - error('cannot read before the first record'); -elseif begrecord>NRecords - error('cannot read beyond the last record') -elseif endrecord>NRecords - endrecord = NRecords; -end - -if begrecord>=1 && endrecord>=begrecord - % rewind to the first record to be read - status = fseek(fid, headersize + (begrecord-1)*recordsize, 'bof'); - if status~=0 - error('cannot jump to the requested record'); - end - - numrecord = (endrecord-begrecord+1); - TimeStamp = zeros(1,numrecord,'uint64'); - ScNumber = zeros(1,numrecord); - CellNumber = zeros(1,numrecord); - Param = zeros(8,numrecord); - Samp = zeros(4,32,numrecord); - - for k=1:numrecord - TimeStamp(k) = fread(fid, 1, 'uint64=>uint64'); - ScNumber(k) = fread(fid, 1, 'int32'); - CellNumber(k) = fread(fid, 1, 'int32'); - Param(k,:) = fread(fid, 8, 'int32'); - Samp(:,:,k) = fread(fid, [4 32], 'int16'); % chan W, X, Y, Z - end - - ntt.TimeStamp = TimeStamp; - ntt.ScNumber = ScNumber; - ntt.CellNumber = CellNumber; - ntt.Param = Param; - % FIXME apply the scaling factor from ADBitVolts and convert to uV - % ntt.dat = Samp * 1e6 * hdr.ADBitVolts; - nst.dat = Samp; -end -fclose(fid); - -% store the header info in the output structure -ntt.NRecords = NRecords; -ntt.hdr = hdr; diff --git a/external/fileio/private/read_neuralynx_sdma.m b/external/fileio/private/read_neuralynx_sdma.m deleted file mode 100644 index 05bba34..0000000 --- a/external/fileio/private/read_neuralynx_sdma.m +++ /dev/null @@ -1,474 +0,0 @@ -function [dat] = read_neuralynx_sdma(dataset, begsample, endsample, chanindx); - -% READ_NEURALYNX_SDMA read specified channels and samples from a Neuralynx splitted DMA dataset -% -% Use as -% [hdr] = read_neuralynx_sdma(dataset) -% [dat] = read_neuralynx_sdma(dataset, begsample, endsample, chanindx) -% -% The splitted DMA dataset is not a formal Neuralynx format, but at -% the FCDC we use it in conjunction with SPIKEDOWNSAMPLE. The dataset -% directory contains files, one for each channel, each containing a -% 8-byte header followed by the binary values for all samples. Commonly -% the binary values are represented as int32, but it is possible to use -% int16 or other numeric representations. The 8-byte header specifies the -% numeric representation and the bitshift that should be applied (in case -% of integer representations). -% -% This function returns the electrophysiological data in AD units -% and not in uV. You should look up the details of the headstage and -% the Neuralynx amplifier and scale the values accordingly. - -% Copyright (C) 2006-2008, Robert Oostenveld -% -% $Log: read_neuralynx_sdma.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.10 2008/12/15 15:07:04 roboos -% updated documentation -% -% Revision 1.9 2008/07/01 13:36:41 roboos -% only whitespace -% -% Revision 1.8 2008/07/01 13:02:33 roboos -% optionally read the 16384 byte ascii header (if present as txt file) -% remember channel specific header details in hdr.orig.chan and general details in hdr.orig.dataset -% -% Revision 1.7 2008/05/27 13:03:00 roboos -% remember the original header details -% -% Revision 1.6 2007/12/17 16:29:43 roboos -% switched to read_neuralynx_bin for reading the file content, thereby adding support for int16 etc. -% changed handling fo files in directory, be more explicit on which file is used where -% changed reading of timestamps -% -% Revision 1.5 2007/02/21 09:57:13 roboos -% fixed bug in TimeStampsPerSample (should be divided by nsamples-1) -% implemented re-ordering of channel names (i.e. not on ascii-order) to match the channel ordering to the original unspiltted DMA file -% -% Revision 1.4 2007/01/09 09:42:29 roboos -% read low and high timestamp as uint32, use subfunction to combine them into a uint64 -% -% Revision 1.3 2006/12/12 11:39:57 roboos -% cleaned up code, changed handling of channel names (now based on file extension), directory listing determines channel ordering -% -% Revision 1.2 2006/12/04 20:26:02 roboos -% change in whitespace -% -% Revision 1.1 2006/04/24 12:21:14 roboos -% new implementation -% - -needhdr = (nargin==1); -needdat = (nargin>=2); - -if ~isdir(dataset) - error('dataset should be a directory'); -end - -% determine the content of the dataset directory -dirlist = dir(dataset); - -% determine the correspondence between files and channels -label = cell(length(dirlist),1); -filesel = zeros(length(dirlist),1); -headerfile = []; -[pd, nd, xd] = fileparts(dataset); -for i=1:length(dirlist) - [pf, nf, x1] = fileparts(dirlist(i).name); - [pf, nf, x2] = fileparts(nf); - % compare the name of the channel with the name of the dataset and look at the file extention - % the file should be called "dataset/dataset.chanlabel" or "dataset/dataset.chanlabel.bin" - if strcmp(nf, nd) && ~isempty(x1) - if ~isempty(x2) - label{i} = x2(2:end); - filesel(i) = 1; - elseif strcmp(x1, '.txt') - % this is not a proper channel, but an ascii file with header info - label{i} = []; - filesel(i) = 0; - headerfile = fullfile(dataset, dirlist(i).name); - else - label{i} = x1(2:end); - filesel(i) = 1; - end - else - label{i} = []; - filesel(i) = 0; - end -end -label = label(filesel==1); -bytes = cell2mat({dirlist(filesel==1).bytes}); % number of bytes in each file -filelist = {dirlist(filesel==1).name}; % filename excluding the path -clear dirlist filesel pd nd xd - -for i=1:length(filelist) - % include the full path in the filename - filelist{i} = fullfile(dataset, filelist{i}); -end - -% there is a preferred ordering, which corresponds with the channel order in the non-splitted DMA file -preferred = { - 'stx' - 'pid' - 'siz' - 'tsh' - 'tsl' - 'cpu' - 'ttl' - 'x01' - 'x02' - 'x03' - 'x04' - 'x05' - 'x06' - 'x07' - 'x08' - 'x09' - 'x10' - 'csc001' - 'csc002' - 'csc003' - 'csc004' - 'csc005' - 'csc006' - 'csc007' - 'csc008' - 'csc009' - 'csc010' - 'csc011' - 'csc012' - 'csc013' - 'csc014' - 'csc015' - 'csc016' - 'csc017' - 'csc018' - 'csc019' - 'csc020' - 'csc021' - 'csc022' - 'csc023' - 'csc024' - 'csc025' - 'csc026' - 'csc027' - 'csc028' - 'csc029' - 'csc030' - 'csc031' - 'csc032' - 'csc033' - 'csc034' - 'csc035' - 'csc036' - 'csc037' - 'csc038' - 'csc039' - 'csc040' - 'csc041' - 'csc042' - 'csc043' - 'csc044' - 'csc045' - 'csc046' - 'csc047' - 'csc048' - 'csc049' - 'csc050' - 'csc051' - 'csc052' - 'csc053' - 'csc054' - 'csc055' - 'csc056' - 'csc057' - 'csc058' - 'csc059' - 'csc060' - 'csc061' - 'csc062' - 'csc063' - 'csc064' - 'csc065' - 'csc066' - 'csc067' - 'csc068' - 'csc069' - 'csc070' - 'csc071' - 'csc072' - 'csc073' - 'csc074' - 'csc075' - 'csc076' - 'csc077' - 'csc078' - 'csc079' - 'csc080' - 'csc081' - 'csc082' - 'csc083' - 'csc084' - 'csc085' - 'csc086' - 'csc087' - 'csc088' - 'csc089' - 'csc090' - 'csc091' - 'csc092' - 'csc093' - 'csc094' - 'csc095' - 'csc096' - 'csc097' - 'csc098' - 'csc099' - 'csc100' - 'csc101' - 'csc102' - 'csc103' - 'csc104' - 'csc105' - 'csc106' - 'csc107' - 'csc108' - 'csc109' - 'csc110' - 'csc111' - 'csc112' - 'csc113' - 'csc114' - 'csc115' - 'csc116' - 'csc117' - 'csc118' - 'csc119' - 'csc120' - 'csc121' - 'csc122' - 'csc123' - 'csc124' - 'csc125' - 'csc126' - 'csc127' - 'csc128' - 'csc129' - 'csc130' - 'csc131' - 'csc132' - 'csc133' - 'csc134' - 'csc135' - 'csc136' - 'csc137' - 'csc138' - 'csc139' - 'csc140' - 'csc141' - 'csc142' - 'csc143' - 'csc144' - 'csc145' - 'csc146' - 'csc147' - 'csc148' - 'csc149' - 'csc150' - 'csc151' - 'csc152' - 'csc153' - 'csc154' - 'csc155' - 'csc156' - 'csc157' - 'csc158' - 'csc159' - 'csc160' - 'csc161' - 'csc162' - 'csc163' - 'csc164' - 'csc165' - 'csc166' - 'csc167' - 'csc168' - 'csc169' - 'csc170' - 'csc171' - 'csc172' - 'csc173' - 'csc174' - 'csc175' - 'csc176' - 'csc177' - 'csc178' - 'csc179' - 'csc180' - 'csc181' - 'csc182' - 'csc183' - 'csc184' - 'csc185' - 'csc186' - 'csc187' - 'csc188' - 'csc189' - 'csc190' - 'csc191' - 'csc192' - 'csc193' - 'csc194' - 'csc195' - 'csc196' - 'csc197' - 'csc198' - 'csc199' - 'csc200' - 'csc201' - 'csc202' - 'csc203' - 'csc204' - 'csc205' - 'csc206' - 'csc207' - 'csc208' - 'csc209' - 'csc210' - 'csc211' - 'csc212' - 'csc213' - 'csc214' - 'csc215' - 'csc216' - 'csc217' - 'csc218' - 'csc219' - 'csc220' - 'csc221' - 'csc222' - 'csc223' - 'csc224' - 'csc225' - 'csc226' - 'csc227' - 'csc228' - 'csc229' - 'csc230' - 'csc231' - 'csc232' - 'csc233' - 'csc234' - 'csc235' - 'csc236' - 'csc237' - 'csc238' - 'csc239' - 'csc240' - 'csc241' - 'csc242' - 'csc243' - 'csc244' - 'csc245' - 'csc246' - 'csc247' - 'csc248' - 'csc249' - 'csc250' - 'csc251' - 'csc252' - 'csc253' - 'csc254' - 'csc255' - 'csc256' - 'crc' - }; - -[sel1, sel2] = match_str(preferred, label); -if length(sel2)==length(label) - % all reorder the labels/files - label = label(sel2); - bytes = bytes(sel2); - filelist = filelist(sel2); -else - % not all files in this SDMA dataset could be accounted for in the - % preference list, hence do not attempt to apply the preferred ordering -end - -if needhdr - % construct a general header for the complete dataset - if ~isempty(headerfile) - orig = neuralynx_getheader(headerfile); - hdr.Fs = orig.SamplingFrequency; - hdr.nSamples = []; % see below - hdr.nSamplesPre = 0; % number of pre-trigger samples in each trial - hdr.nTrials = 1; % number of trials - hdr.label = label; - hdr.nChans = length(label); - hdr.orig.dataset = orig; % keep the header details - else - % some parts of the header have to be hardcoded, since the splitted dataset does not contain all header information - hdr.Fs = 32556; % sampling frequency - hdr.nSamples = []; % see below - hdr.nSamplesPre = 0; % number of pre-trigger samples in each trial - hdr.nTrials = 1; % number of trials - hdr.label = label; - hdr.nChans = length(label); - end - - % read the header of each individual file, i.e. for each variable - clear orig - for i=1:length(filelist) - orig(i) = read_neuralynx_bin(filelist{i}); - end - - % determine the number of samples for each channel - nsamples = cell2mat({orig.nSamples}); - if any(nsamples~=nsamples(1)) - error('different number of samples over channels are not supported'); - else - hdr.nSamples = nsamples(1); - end - - % determine the sampling frequency for each channel - fsample = cell2mat({orig.Fs}); - if any(diff(fsample)) - error('different sampling rates over channels are not supported'); - elseif any(fsample~=hdr.Fs) - error('inconsistent sampling rates'); - end - - % determine the first and last timestamp, by reading them from the timestamp channels - tslfile = filelist{find(strcmp('tsl', label))}; - tshfile = filelist{find(strcmp('tsh', label))}; - beg_tsl = read_neuralynx_bin(tslfile, 1, 1); - beg_tsh = read_neuralynx_bin(tshfile, 1, 1); - end_tsl = read_neuralynx_bin(tslfile, hdr.nSamples, hdr.nSamples); - end_tsh = read_neuralynx_bin(tshfile, hdr.nSamples, hdr.nSamples); - hdr.FirstTimeStamp = timestamp_neuralynx(beg_tsl, beg_tsh); - hdr.LastTimeStamp = timestamp_neuralynx(end_tsl, end_tsh); - hdr.TimeStampPerSample = double(hdr.LastTimeStamp-hdr.FirstTimeStamp)./(hdr.nSamples-1); % this should be double, since it can be fractional - - % also remember the original header details - hdr.orig.chan = orig; - - % only return the header information - dat = hdr; - -else - % allocate memory for all data - dat = zeros(length(chanindx), endsample-begsample+1); - - % read all channels, one small chunk at at time, and write it to seperate files - for i=1:length(chanindx) - j = chanindx(i); - dat(i,:) = double(read_neuralynx_bin(filelist{j}, begsample, endsample)); - end -end diff --git a/external/fileio/private/read_neuralynx_tsh.m b/external/fileio/private/read_neuralynx_tsh.m deleted file mode 100644 index 78e7446..0000000 --- a/external/fileio/private/read_neuralynx_tsh.m +++ /dev/null @@ -1,39 +0,0 @@ -function [dat] = read_neuralynx_tsl(filename, begsample, endsample); - -% READ_NEURALYNX_TSL reads the TimeStampLow values from a *.tsl file -% -% Use as -% [dat] = read_neuralynx_tsl(filename, begsample, endsample); -% -% The *.tsl file is not a formal Neuralynx file format, but at the -% F.C. Donders Centre we use it in conjunction with Neuralynx and -% SPIKEDOWNSAMPLE. - -% Copyright (C) 2006, Robert Oostenveld -% -% $Log: read_neuralynx_tsh.m,v $ -% Revision 1.3 2006/12/12 11:32:22 roboos -% read the data as uint32 instead of signed integers -% - -fid = fopen(filename, 'rb', 'ieee-le'); - -if begsample<1 - begsample = 1; -end - -if isinf(endsample) - fseek(fid, 0, 'eof'); - endsample = (ftell(fid)-8)/4; - fseek(fid, 0, 'bof'); -end - -fseek(fid, 8, 'cof'); % skip the 8-byte header with the filetype identifier -fseek(fid, begsample-1, 'cof'); % skip to the beginning of the interesting data -dat = fread(fid, endsample-begsample+1, 'uint32=>uint32')'; -if length(dat)<(endsample-begsample+1) - error('could not read the requested data'); -end - -fclose(fid); - diff --git a/external/fileio/private/read_neuralynx_tsl.m b/external/fileio/private/read_neuralynx_tsl.m deleted file mode 100644 index b5b8c17..0000000 --- a/external/fileio/private/read_neuralynx_tsl.m +++ /dev/null @@ -1,39 +0,0 @@ -function [dat] = read_neuralynx_tsh(filename, begsample, endsample); - -% READ_NEURALYNX_TTL reads the TimeStampHi values from a *.tsh file -% -% Use as -% [dat] = read_neuralynx_tsh(filename, begsample, endsample); -% -% The *.tsh file is not a formal Neuralynx file format, but at the -% F.C. Donders Centre we use it in conjunction with Neuralynx and -% SPIKEDOWNSAMPLE. - -% Copyright (C) 2006, Robert Oostenveld -% -% $Log: read_neuralynx_tsl.m,v $ -% Revision 1.3 2006/12/12 11:32:22 roboos -% read the data as uint32 instead of signed integers -% - -fid = fopen(filename, 'rb', 'ieee-le'); - -if begsample<1 - begsample = 1; -end - -if isinf(endsample) - fseek(fid, 0, 'eof'); - endsample = (ftell(fid)-8)/4; - fseek(fid, 0, 'bof'); -end - -fseek(fid, 8, 'cof'); % skip the 8-byte header with the filetype identifier -fseek(fid, begsample-1, 'cof'); % skip to the beginning of the interesting data -dat = fread(fid, endsample-begsample+1, 'uint32=>uint32')'; -if length(dat)<(endsample-begsample+1) - error('could not read the requested data'); -end - -fclose(fid); - diff --git a/external/fileio/private/read_neuralynx_ttl.m b/external/fileio/private/read_neuralynx_ttl.m deleted file mode 100644 index bbe1476..0000000 --- a/external/fileio/private/read_neuralynx_ttl.m +++ /dev/null @@ -1,47 +0,0 @@ -function [dat] = read_neuralynx_ttl(filename, begsample, endsample); - -% READ_NEURALYNX_TTL reads the Parallel_in values from a *.ttl file -% -% Use as -% [dat] = read_neuralynx_ttl(filename, begsample, endsample); -% -% The *.ttl file is not a formal Neuralynx file format, but at the -% F.C. Donders Centre we use it in conjunction with Neuralynx and -% SPIKEDOWNSAMPLE. - -% Copyright (C) 2006, Robert Oostenveld -% -% $Log: read_neuralynx_ttl.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.3 2006/12/12 11:32:22 roboos -% read the data as uint32 instead of signed integers -% - -fid = fopen(filename, 'rb', 'ieee-le'); - -if begsample<1 - begsample = 1; -end - -if isinf(endsample) - fseek(fid, 0, 'eof'); - endsample = (ftell(fid)-8)/4; - fseek(fid, 0, 'bof'); -end - -fseek(fid, 8, 'cof'); % skip the 8-byte header with the filetype identifier -fseek(fid, begsample-1, 'cof'); % skip to the beginning of the interesting data -dat = fread(fid, endsample-begsample+1, 'uint32=>uint32')'; -if length(dat)<(endsample-begsample+1) - error('could not read the requested data'); -end - -fclose(fid); - diff --git a/external/fileio/private/read_nex_data.m b/external/fileio/private/read_nex_data.m deleted file mode 100644 index de2a642..0000000 --- a/external/fileio/private/read_nex_data.m +++ /dev/null @@ -1,82 +0,0 @@ -function [dat] = read_nex_data(filename, hdr, begsample, endsample, chanindx) - -% READ_NEX_DATA for Plexon *.nex file -% -% Use as -% [dat] = read_nex_data(filename, hdr, begsample, endsample, chanindx) -% -% See also READ_NEX_HEADER, READ_NEX_EVENT - -try, - % work with the original header, not the FieldTrip one - hdr = hdr.orig; -catch - % assume that we got the original header -end - -numsmp = cell2mat({hdr.varheader.numsmp}); -adindx = find(cell2mat({hdr.varheader.typ})==5); -smpfrq = hdr.varheader(adindx(1)).wfrequency; -sgn = chanindx; -nsmp = (endsample-begsample+1); -dat = zeros(length(sgn), nsmp); - -fid = fopen(filename, 'r', 'ieee-le'); -for sgnlop=1:length(sgn) - - if hdr.varheader(sgn(sgnlop)).typ == 0 - % read a spike channel - status = fseek(fid,hdr.varheader(sgn(sgnlop)).offset,'bof'); - - % read the sample indices at which spikes occurred - tim = fread(fid,hdr.varheader(sgn(sgnlop)).cnt,'int32'); - % downsample from 40kHz to the A/D sampling frequency - tim = (tim ./ hdr.filheader.frequency) * smpfrq + 1; % add one sample, since ts=0 corresponds to sample=1 - tim = round(tim); % needed because of the edges in histc - % select only samples between the desired begin and end - % tim = tim(find(tim>=begsample & tim<=endsample)); - % convert sample indices into a continuous signal - if ~isempty(tim) - dum = histc(tim-begsample, 0:(nsmp-1), 1); - dat(sgnlop,:) = dum(:)'; - end - - elseif hdr.varheader(sgn(sgnlop)).typ == 5 - % read an A/D channel - status = fseek(fid,hdr.varheader(sgn(sgnlop)).offset,'bof'); - - % this just reads the times of LFP starts - tim = fread(fid,hdr.varheader(sgn(sgnlop)).cnt,'int32'); - % this just reads the indices of LFP starts - ind = fread(fid,hdr.varheader(sgn(sgnlop)).cnt,'int32'); - if length(ind)>1 - error('multiple A/D segments are not supported'); - end - - % convert from timestamps to samples, expressed in the sampling frequency of the AD channels - tim = (tim ./ hdr.filheader.frequency) * smpfrq; - tim = round(tim); - - ch_begsample = begsample - tim; - ch_endsample = endsample - tim; - - if (ch_begsample<1) - error(sprintf('cannot read before the begin of the recorded data (channel %d)', sgn(sgnlop))); - elseif (ch_endsample>hdr.varheader(sgn(sgnlop)).numsmp) - error(sprintf('cannot read beyond the end of the recorded data (channel %d)', sgn(sgnlop))); - end - - % seek to the beginning of the interesting data, correct for the A/D card initialisation delay - fseek(fid,(ch_begsample-1)*2, 'cof'); - % read the actual data for the whole channel - dum = fread(fid,nsmp,'int16'); - % convert to mV - dat(sgnlop,:) = dum(:)' * hdr.varheader(sgn(sgnlop)).adtomv; - - else - % warning(sprintf('unsupported data format for channel %s', hdr.label{sgn(sgnlop)})); - end - -end -status = fclose(fid); - diff --git a/external/fileio/private/read_nex_event.m b/external/fileio/private/read_nex_event.m deleted file mode 100644 index dfdfb36..0000000 --- a/external/fileio/private/read_nex_event.m +++ /dev/null @@ -1,64 +0,0 @@ -function [event] = read_nex_event(filename) - -% READ_NEX_EVENT for Plexon *.nex file -% -% Use as -% [event] = read_nex_event(filename) -% -% The sample numbers returned in event.sample correspond with the -% timestamps, correcting for the difference in sampling frequency in the -% continuous LFP channels and the system sampling frequency. Assuming 40kHz -% sampling frequency for the system and 1kHz for the LFP channels, it is -% event.sample = timestamp / (40000/1000); -% -% See also READ_NEX_HEADER, READ_NEX_DATA - -% Copyright (C) 2005-2007, Robert Oostenveld -% -% $Log: read_nex_event.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.2 2007/01/11 12:46:56 roboos -% modified to keep consistent with read_nex_header, added copyright and log -% - -hdr = read_nex_header(filename); -adindx = find(cell2mat({hdr.varheader.typ})==5); -smpfrq = hdr.varheader(adindx(1)).wfrequency; - -% find the channel with the strobed trigger -mrkvarnum = find([hdr.varheader.typ] == 6); - -fid=fopen(filename,'r','ieee-le'); -status = fseek(fid,hdr.varheader(mrkvarnum).offset,'bof'); - -% read the time of the triggers -dum = fread(fid,hdr.varheader(mrkvarnum).cnt,'int32'); -dum = dum ./(hdr.filheader.frequency./smpfrq); -mrk.tim = round(dum); - -% read the value of the triggers -status = fseek(fid,64,'cof'); -dum = fread(fid,[hdr.varheader(mrkvarnum).mrklen,hdr.varheader(mrkvarnum).cnt],'uchar'); -mrk.val = str2num(char(dum(1:5,:)')); - -status = fclose(fid); - -% translate into an FCDC event structure -Nevent = length(mrk.tim); -event = struct('sample', num2cell(mrk.tim), 'value', num2cell(mrk.val)); -for i=1:Nevent - % the code above with the struct and num2cell is much faster - % event(i).sample = mrk.tim(i); - % event(i).value = mrk.val(i); - event(i).type = hdr.varheader(mrkvarnum).nam; - event(i).duration = 1; - event(i).offset = 0; -end - diff --git a/external/fileio/private/read_nex_header.m b/external/fileio/private/read_nex_header.m deleted file mode 100644 index d7b4aa7..0000000 --- a/external/fileio/private/read_nex_header.m +++ /dev/null @@ -1,49 +0,0 @@ -function [hdr] = read_nex_header(filename) - -% READ_NEX_HEADER for Plexon *.nex file -% -% Use as -% [hdr] = read_nex_header(filename) -% -% See also RAD_NEX_DATA, READ_NEX_EVENT - -fid = fopen(filename, 'r', 'ieee-le'); - -% reading the file header -filheader.magicnumber = fread(fid,4,'uint8=>char')'; -filheader.version = fread(fid,1,'int32'); -filheader.comment = fread(fid,256,'uint8=>char')'; -filheader.frequency = fread(fid,1,'double'); -filheader.begvar = fread(fid,1,'int32'); -filheader.endvar = fread(fid,1,'int32'); -filheader.numvar = fread(fid,1,'int32'); -filheader.nextfileheader = fread(fid,1,'int32'); -filheader.padding = fread(fid,256,'uint8=>char')'; - -% reading the variable headers -for varlop=1:filheader.numvar - varheader(varlop).typ = fread(fid,1,'int32'); - varheader(varlop).version = fread(fid,1,'int32'); - varheader(varlop).nam = fread(fid,64,'uint8=>char')'; - varheader(varlop).offset = fread(fid,1,'int32'); - varheader(varlop).cnt = fread(fid,1,'int32'); - varheader(varlop).wirenumber = fread(fid,1,'int32'); - varheader(varlop).unitnumber = fread(fid,1,'int32'); - varheader(varlop).gain = fread(fid,1,'int32'); - varheader(varlop).filter = fread(fid,1,'int32'); - varheader(varlop).xpos = fread(fid,1,'double'); - varheader(varlop).ypos = fread(fid,1,'double'); - varheader(varlop).wfrequency = fread(fid,1,'double'); - varheader(varlop).adtomv = fread(fid,1,'double'); - varheader(varlop).numsmp = fread(fid,1,'int32'); - varheader(varlop).nummrk = fread(fid,1,'int32'); - varheader(varlop).mrklen = fread(fid,1,'int32'); - padding = fread(fid,68,'uint8=>char')'; -end - -status = fclose(fid); - -% put them together into one struct -hdr.fil = filename; -hdr.filheader = filheader; -hdr.varheader = varheader; diff --git a/external/fileio/private/read_nexstim_event.m b/external/fileio/private/read_nexstim_event.m deleted file mode 100644 index 3baa54c..0000000 --- a/external/fileio/private/read_nexstim_event.m +++ /dev/null @@ -1,80 +0,0 @@ -function [event] = read_nexstim_event(filename) - -% Use as -% [event] = read_nexstim_event(filename) - -% Written by Vladimir Litvak based on the function nxeGetTriggers -% provided by Nexstim -% -% Copyright (C) 2007, Vladimir Litvak -% -% $Log: read_nexstim_event.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.2 2007/12/17 13:03:52 roboos -% Vladimir found and fixed some bugs pertaining to the nexstim_nxe format -% -% Revision 1.1 2007/12/17 08:24:28 roboos -% added support for nexstim_nxe, thanks to Vladimir -% the low-level code has not been tested by myself -% - -% trigLine - either 1(GATE), 2(TRIG1) or 3(TRIG2) -% trigEdge - either 'rising' or 'falling' - -fid=fopen(filename,'r','l'); - -numChannels = 64; -blockSamples = 14500; -trigThreshold = 2000; -trigChannels = [1 2 3]; % Is fixed for the present Nexstim format. - -fseek(fid,0,'eof'); -numBytes = ftell(fid); -numSamples = (numBytes/2)/numChannels; -numBlocks = ceil(numSamples/blockSamples); - -fseek(fid,0,'bof'); -trigPos=[]; - -event=[]; -for i = 1:numBlocks - blockPos=(i-1)*blockSamples; - data = fread(fid,[numChannels blockSamples+1],'int16'); - - for trigLine=1:length(trigChannels); - trigPosRising = find(diff(data(trigChannels(trigLine),:))>trigThreshold)+blockPos; - trigPosFalling = find(diff(data(trigChannels(trigLine),:))<-trigThreshold)+blockPos; - - if ~isempty(trigPosRising) - for i=1:length(trigPosRising) - event(end+1).type = 'rising'; - event(end ).sample = trigPosRising(i); - event(end ).value = trigLine; - event(end ).offset = []; - event(end ).duration = []; - end - end - - if ~isempty(trigPosFalling) - for i=1:length(trigPosFalling) - event(end+1).type = 'falling'; - event(end ).sample = trigPosFalling(i); - event(end ).value = trigLine; - event(end ).offset = []; - event(end ).duration = []; - end - end - - end - fseek(fid,-(2*numChannels),'cof'); -end - -fclose(fid); - diff --git a/external/fileio/private/read_nexstim_nxe.m b/external/fileio/private/read_nexstim_nxe.m deleted file mode 100644 index b08e0df..0000000 --- a/external/fileio/private/read_nexstim_nxe.m +++ /dev/null @@ -1,163 +0,0 @@ -function [dat] = read_nexstim_nxe(filename, begsample, endsample, chanindx) - -% READ_NEXSTIM_NXE reads specified samples from a NXE continous datafile -% -% Use as -% [hdr] = read_nexstim_nxe(filename) -% where -% filename name of the datafile, including the .bdf extension -% This returns a header structure with the following elements -% hdr.Fs sampling frequency -% hdr.nChans number of channels -% hdr.nSamples number of samples per trial -% hdr.nSamplesPre number of pre-trigger samples in each trial -% hdr.nTrials number of trials -% hdr.label cell-array with labels of each channel -% -% Or use as -% [dat] = read_nexstim_nxe(filename, begsample, endsample, chanindx) -% where -% filename name of the datafile, including the .nxe extension -% begsample index of the first sample to read -% endsample index of the last sample to read -% chanindx index of channels to read (optional, default is all) -% This returns a Nchans X Nsamples data matrix - -% Written by Vladimir Litvak based on functions provided by Nexstim -% -% Copyright (C) 2007, Vladimir Litvak -% -% $Log: read_nexstim_nxe.m,v $ -% Revision 1.2 2009/02/27 12:42:03 vlalit -% Fix for a bug spotted by Miriam Klein -% -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.3 2007/12/17 13:03:52 roboos -% Vladimir found and fixed some bugs pertaining to the nexstim_nxe format -% -% Revision 1.2 2007/12/17 08:42:34 roboos -% fixed typo -% -% Revision 1.1 2007/12/17 08:24:28 roboos -% added support for nexstim_nxe, thanks to Vladimir -% the low-level code has not been tested by myself -% - -if nargin==1 - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % read the header - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - hdr.Fs = 1450; - hdr.nChans = 64; - hdr.label = cell(64,1); - hdr.label(1:4)= {'GATE', 'TRIG1', 'TRIG2','EOG'}; - hdr.label(5:64) = { - 'Fp1' - 'Fpz' - 'Fp2' - 'AF1' - 'AFz' - 'AF2' - 'F7' - 'F3' - 'F1' - 'Fz' - 'F2' - 'F4' - 'F8' - 'FT9' - 'FT7' - 'FC5' - 'FC3' - 'FC1' - 'FCz' - 'FC2' - 'FC4' - 'FC6' - 'FT8' - 'FT10' - 'T7' - 'C5' - 'C3' - 'C1' - 'Cz' - 'C2' - 'C4' - 'C6' - 'T8' - 'TP9' - 'TP7' - 'CP5' - 'CP3' - 'CP1' - 'CPz' - 'CP2' - 'CP4' - 'CP6' - 'TP8' - 'TP10' - 'P9' - 'P7' - 'P3' - 'P1' - 'Pz' - 'P2' - 'P4' - 'P8' - 'P10' - 'PO3' - 'POz' - 'PO4' - 'O1' - 'Oz' - 'O2' - 'Iz'}; - - % it is continuous data, therefore append all records in one trial - hdr.nTrials = 1; - - fid=fopen(filename,'r','l'); - fseek(fid,0,'eof'); - numBytes = ftell(fid); - hdr.nSamples = (numBytes/2)/hdr.nChans; - - hdr.nSamplesPre = 0; - - fclose(fid); - - % return the header - dat = hdr; - -else - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % read the data - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - sfEEG = (1/2000) * (10/65535) * 1000000; - sfEOG = (1/400) * (10/65535) * 1000000; - sfTRIG = 10 * (10/65535); - - numChannels = 64; - - fid = fopen(filename,'r','l'); - fseek(fid, 2*numChannels*(begsample-1),'bof'); - data = fread(fid,[numChannels endsample-begsample+1],'short'); - fclose(fid); - - data(1:3,:) = sfTRIG.*data(1:3,:); - data(4,:) = sfEOG.*data(4,:); - data(5:64,:) = sfEEG.*data(5:64,:); - - if nargin<4 - chanindx = 1:numChannels; - end - - dat = data(chanindx,:); -end - diff --git a/external/fileio/private/read_nimh_cortex.m b/external/fileio/private/read_nimh_cortex.m deleted file mode 100644 index 19e58a1..0000000 --- a/external/fileio/private/read_nimh_cortex.m +++ /dev/null @@ -1,178 +0,0 @@ -function cortex = read_nimh_cortex(filename, varargin) - -% READ_NIMH_CORTEX -% -% Use as -% cortex = read_nimh_cortex(filename, ...) -% -% Optional input arguments should come in key-value pairs and may -% include -% begtrial = number (default = 1) -% endtrial = number (default = inf) -% epp = read the EPP data, 'yes' or 'no' (default = 'yes') -% eog = read the EOG data, 'yes' or 'no' (default = 'yes') -% feedback = display the progress on the screen, 'yes' or 'no' (default = 'no') -% -% The output is a structure array with one structure for every trial that was read. - -% $Log: read_nimh_cortex.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.1 2008/07/24 08:47:05 roboos -% new implementation in fieldtrip style, based on code that I got from Conrado -% - -% get the optional input arguments -feedback = keyval('feedback', varargin); if isempty(feedback), feedback = 'no'; end -begtrial = keyval('begtrial', varargin); if isempty(begtrial), begtrial = 1; end -endtrial = keyval('endtrial', varargin); if isempty(endtrial), endtrial = inf; end -% reading the epp and eog data is optional -epp = keyval('epp', varargin); if isempty(epp), epp = 'yes'; end -eog = keyval('eog', varargin); if isempty(eog), eog = 'yes'; end - -skipepp = strcmp(epp, 'no'); -skipeog = strcmp(eog, 'no'); -clear epp eog - -% this will hold the result -cortex = struct; - -% trials are counted with zero-offset -trial = 0; - -i_fid = fopen(filename, 'rb', 'ieee-le'); - -% read until the end of file or until the specified trial number -while ( ~feof (i_fid) && trial=begtrial - fprintf('reading trial %d\n', trial+1); - end - - % Number of bytes for each variable. - hd(1,1:8)= (fread(i_fid, 8, 'ushort'))'; - - % Convert bytes to number of float point values (4 bytes apiece in windows and FreeBSD). - hd(1,5)=hd(1,5)/4; - % Convert bytes to number of short values (2 bytes apiece in windows and FreeBSD). - hd(1,6)=hd(1,6)/2; - hd(1,7)=hd(1,7)/2; - hd(1,8)=hd(1,8)/2; - - header.cond_no = hd(1,1); - header.repeat_no = hd(1,2); - header.block_no = hd(1,3); - header.trial_no = hd(1,4); - header.isi_size = hd(1,5); - header.code_size = hd(1,6); - header.eog_size = hd(1,7); - header.epp_size = hd(1,8); - - hd(1,9:10) = (fread(i_fid, 2, 'uchar'))'; - - header.kHz_resolution = hd(1,9); - header.eye_storage_rate = hd(1,10); - - hd(1,11:13) = (fread(i_fid, 3, 'ushort'))'; - - header.expected_response = hd(1,11); - header.response = hd(1,12); - header.response_error = hd(1,13); - - if skiptrial - fseek(i_fid,header.isi_size, 'cof'); - fseek (i_fid,header.code_size, 'cof'); - else - time = (fread (i_fid,header.isi_size, 'ulong')); - event = (fread (i_fid,header.code_size, 'ushort')); - end % if skiptrial - - if skipepp || skiptrial - epp1 = []; - epp2 = []; - fseek (i_fid,header.epp_size * 2, 'cof'); - - else - epp = fread (i_fid,header.epp_size, 'short'); - epp1 = zeros(1,header.epp_size/2); - epp2 = zeros(1,header.epp_size/2); - - % fprintf(o_fid, '\nepp(x)\tepp(y)\n\n'); - - for i = 1:2:header.epp_size - % Must extract the data from the raw epp values. - % The epp value is made up of 12-bits of data, and 4-bits (the - % low-order 4 bits) of the channel number. - % To extract the data, must right shift the raw data by 4 bits (to - % get rid of the channel number and put the data value in the proper - % location). After this conversion, you must still add or subtract - % 2048, since otherwise the value is not right. (I think that this - % is because of the way that matlab handles negative values during - % the bitwise operations.) - % These calculations cause the results of ctx2txt.m to be the same as - % for cortview.exe for the EOG and EPP values. - - s = (i+1)/2; - epp1(s) = bitshift(epp(i), -4); - epp2(s) = bitshift(epp(i+1), -4); - - if (epp1(s) < 0) - epp1(s) = epp1(s) + 2047; - else - epp1(s) = epp1(s) - 2048; - end; - - if (epp2(s) < 0) - epp2(s) = epp2(s) + 2047; - else - epp2(s) = epp2(s) - 2048; - end; - end; - end; % if skipepp - - if skipeog || skiptrial - eog = []; - fseek (i_fid,header.eog_size * 2, 'cof'); - else - eog = fread (i_fid,header.eog_size, 'short'); - eog = reshape(eog, 2, header.eog_size/2); - end % if skipeog - - if ~skiptrial - % collect the headers of all trials in a structure array - cortex(trial+1).header = header; - cortex(trial+1).length = length; - cortex(trial+1).time = time; - cortex(trial+1).event = event; - cortex(trial+1).epp = [epp1; epp2]; - cortex(trial+1).eog = eog; - end - - trial = trial+1; - end; % if ~isempty(length) -end; - -fclose(i_fid); - -% remove the initial empty trials, i.e. the ones that were skipped -cortex = cortex(begtrial:end); - diff --git a/external/fileio/private/read_nmc_archive_k_data.m b/external/fileio/private/read_nmc_archive_k_data.m deleted file mode 100644 index df0fb3f..0000000 --- a/external/fileio/private/read_nmc_archive_k_data.m +++ /dev/null @@ -1,73 +0,0 @@ -function [dat] = read_nmc_archive_k_data(datafile, hdr, begsample, endsample, channelsel) - -% READ_NMC_ARCHIVE_K_DATA reads data from nmc_archive_k datasets -% -% Used in read_data as -% dat = read_nmc_archive_k_data(datafile, hdr, begsample, endsample, channelsel); -% -% -% This function specifically only reads data from one of the archived -% datasets of the Neurophysiological Mechanisms of Cognition group of -% Eric Maris, at the Donders Centre for Cognition, Radboud University, -% Nijmegen, the Netherlands. It should not be used for any other data -% format. -% -% -% First version: 2009/09/31 - roevdmei -% - - -% Sanity checks (to be added) - - - -% Getting data-directory out of data-filename and check -datadir = datafile(1:(findstr(datafile, 'eeg.noreref')+11)); -if exist(datadir,'dir') ~= 7 - error('no proper data-directory provided, please check your paths'); -end - -% Getting session name + path out of data-filename -sessionpath = datafile(1:(end-4)); - - -% Build array containing channel file extensions to be used in reading the data -channelext = []; -% Remove the 'CH' from channel labels -chanlabnum = hdr.label; -for ichan = 1:length(chanlabnum) - chanlabnum{ichan} = chanlabnum(3:end); -end -for ichan = 1:length(channelsel) - if length(hdr.label{channelsel(ichan)}) == 3 - channelext{ichan} = ['.00' hdr.label{channelsel(ichan)}(3:end)]; - elseif length(hdr.label{channelsel(ichan)}) == 4 - channelext{ichan} = ['.0' hdr.label{channelsel(ichan)}(3:end)]; - elseif length(hdr.label{channelsel(ichan)}) == 5 - channelext{ichan} = ['.' hdr.label{channelsel(ichan)}(3:end)]; - end -end - -% Loop over channels while reading in data from file, 1 file per channel -dat = zeros(length(channelsel),(endsample-begsample+1)); -for ichan = 1:length(channelsel) - channelfile = [sessionpath channelext{ichan}]; - datafid = fopen(channelfile,'r','l'); - fseek(datafid,(hdr.nBytes*(begsample-1)),'bof'); - dat(ichan,:) = fread(datafid,(endsample-begsample+1),hdr.dataformat)'; - fclose(datafid); -end - - - - - - - - - - - - - - diff --git a/external/fileio/private/read_ns_avg.m b/external/fileio/private/read_ns_avg.m deleted file mode 100644 index 9755628..0000000 --- a/external/fileio/private/read_ns_avg.m +++ /dev/null @@ -1,92 +0,0 @@ -function [avg] = read_ns_avg(filename) - -% READ_NS_AVG read a NeuroScan 3.x or 4.x AVG File -% -% [avg] = read_ns_avg(filename) -% -% The output data structure avg has the fields: -% avg.data - ERP signal in uV (Nchan x Npnt) -% avg.nsweeps - number of accepted trials/sweeps in avg -% avg.variance - variance of the signal (Nchan x Npnt) -% avg.label - electrode labels -% avg.nchan - number of channels -% avg.npnt - number of samplepoints in ERP waveform -% avg.rate - sample rate (Hz) -% avg.time - time for each sample OR -% avg.frequency - frequency for each sample -% hdr.domain - flag indicating time (0) or frequency (1) domain -% avg.xmin - prestimulus epoch start (e.g., -100 msec) -% avg.xmax - poststimulus epoch end (e.g., 900 msec) - -% This program is free software; you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation; either version 2 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program; if not, write to the Free Software -% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -% Copyright (C) 2002, Robert Oostenveld -% -% $Log: read_ns_avg.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.3 2004/06/28 07:36:53 roberto -% changed from DOS to UNIX linefeeds, I am not completely sure whether I made other changes as well -% -% Revision 1.2 2003/03/11 15:24:51 roberto -% updated help and copyrights -% - -% read the neuroscan header -avg = read_ns_hdr(filename); - -% create a time or frequency axis -if avg.domain==1 - avg.frequency = linspace(avg.xmin, avg.xmax, avg.npnt) / 1000; % in Hz instead of mili-Hz -else - avg.time = linspace(avg.xmin, avg.xmax, avg.npnt); % in ms -end - -% open the file and seek towards the place where the raw data is -fid = fopen(filename,'r','ieee-le'); -if fid<0 - error(['cannot open ', filename]); -else - fseek(fid, 900, 'cof'); % skip general header - fseek(fid, 75*avg.nchan, 'cof'); % skip channel headers -end; - -% read raw signal data and convert to uV -avg.data = zeros(avg.nchan, avg.npnt); -for elec = 1:avg.nchan - fseek(fid, 5, 'cof'); % skip sweeps header - raw = fread(fid, avg.npnt, 'float32'); - avg.data(elec,:) = (raw' - avg.baseline(elec)) * avg.calib(elec) / avg.nsweeps; -end; - -% read signal variance if present -if avg.variance - variance = zeros(avg.npnt, avg.nchan); - for elec = 1:avg.nchan, - variance(:, elec) = fread(fid, avg.npnt, 'float32'); - end; - avg.variance = variance'; -else - avg.variance = []; -end; - -fclose(fid); - diff --git a/external/fileio/private/read_ns_cnt.m b/external/fileio/private/read_ns_cnt.m deleted file mode 100644 index 95ff73f..0000000 --- a/external/fileio/private/read_ns_cnt.m +++ /dev/null @@ -1,360 +0,0 @@ -% READ_NS_CNT loads header and/or data from a Neuroscan continuous EEG file -% -% Usage: -% >> cnt = read_ns_cnt(file, varargin) -% -% Inputs: -% filename - name of the file with extension -% -% Optional inputs: -% 't1' - start at time t1, default 0 -% 'sample1' - start at sample1, default 0, overrides t1 -% 'lddur' - duration of segment to load, default = whole file -% 'ldnsamples' - number of samples to load, default = whole file, -% overrides lddur -% 'blockread' - size of the blocks to read. Default is 1. -% 'avgref' - ['yes'|'no'] average reference. Default 'no'. -% 'avrefchan' - reference channels. Default none. -% 'format' - 16 or 32. Default 16. -% -% Outputs: -% cnt - structure with the continuous data and other informations -% -% Known limitations: -% Initially I couldn't get the continuous data as they would appear -% using CNTTOASC or CNTTOBIN (www.neuro.com/neuroscan/download.html). -% We don't have the code for these functions, so we don't really know how -% the raw data is read. After extensive searches, I realized that for -% my continuous CNT files, data was stored in blocks of 40 unsigned short -% integers for each channel. I couldn't find where this parameter was -% specified in the header, so I added the option 'blockread' and input -% the number 40 by hand { cnt = read_ns_cnt('file.cnt', 'blockread', 40) }. -% By default the size of the block is 1 and this work for most CNT -% files. For more see http://www.cnl.salk.edu/~arno/cntload/index.html -% -% Authors: Andrew James & Arnaud Delorme 2000-2001 - -%123456789012345678901234567890123456789012345678901234567890123456789012 - -% Copyright (C) 2000 Andrew James, CERCO, Toulouse, France -% Copyright (C) 2001 Arnaud Delorme, Salk Institute, arno@salk.edu -% -% This program is free software; you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation; either version 2 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program; if not, write to the Free Software -% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -% $Log: read_ns_cnt.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.10 2008/11/20 12:59:01 roboos -% correct the number of samples in case of 32 bit file -% -% Revision 1.9 2008/11/13 21:20:08 roboos -% read chars as uint8, this solves problem with i18n (2-byte unicode) and recent matlab versions -% -% Revision 1.8 2008/09/30 07:47:04 roboos -% replaced all occurences of setstr() with char(), because setstr is deprecated by Matlab -% -% Revision 1.7 2007/10/31 16:46:13 roboos -% revert to short format as default -% -% Revision 1.6 2007/07/03 16:10:48 roboos -% added a hack for 32 bit neuroscan format (hdr.nsdf=16|32), this should actually be be done using autodetection -% -% Revision 1.5 2005/10/11 08:35:41 roboos -% close file when only header was read (thanks to Durk) -% fixed typo in help -% -% Revision 1.4 2004/06/28 07:36:53 roberto -% changed from DOS to UNIX linefeeds, I am not completely sure whether I made other changes as well -% -% Revision 1.4 2003/04/10 17:56:09 arno -% removing debuging message -% -% Revision 1.3 2003/04/10 17:50:11 arno -% adding error message -% -% Revision 1.2 2002/10/22 23:53:23 arno -% fopen ieee-le for Mac -% -% Revision 1.1 2002/04/05 17:39:45 jorn -% Initial revision -% -% original function by a.c.james 2000-2001 -% 'blockread' by arno@salk.edu, Arnaud Delorme, CNL / Salk Institute, 2001 - -function r=read_ns_cnt(file, varargin) - -if nargin < 1 - help read_ns_cnt; - return; -end; - -% defaults -[datdir,name,ext]=fileparts(file); -if ~isempty(varargin) - r=struct(varargin{:}); -end; - -% add defaults -warning off; -try, r.t1; catch, r.t1=0; end -warning on; -try, r.avrefchan; catch, r.avrefchan=[]; end -try, r.blockread; catch, r.blockread=1; end -try, r.avgref; catch, r.avgref='non'; end - -if ~any(file=='.'), file=[file '.cnt']; end - -disp(['Loading file ' file ' ...']) - -f=fopen(file, 'rb', 'ieee-le'); -if f==-1, error([file ' not found']), end - -r.filename=file; -r.rev=freadat(f, 0, 20, 'text'); -i=find(r.rev==0); try, r.rev(i(1):end)=''; end - -r.nchannels=freadat(f, 370, 1, 'ushort'); -numsamples=freadat(f, 864, 1, 'long'); % not accurate, see calculation below -samplespos=900 + 75*r.nchannels; -event.tablepos=freadat(f, 886, 1, 'long'); -r.nsamples=(event.tablepos - samplespos)/(2*r.nchannels); - -%%%%NEW CHANGE TO READ 32 BIT -if isfield(r, 'format') && r.format == 32 - r.nsamples = r.nsamples / 2; -elseif isfield(r, 'format') && r.format == 16 - r.nsamples = r.nsamples / 1; -else - r.nsamples = r.nsamples / 1; -end - -r.rate=freadat(f, 376, 1, 'ushort'); -r.channeloffset=freadat(f, 932, 1, 'long'); -r.dt=1/r.rate; -r.scale=freadat(f, 378, 1, 'double'); -r.ampsensitivity=freadat(f, 438, 1, 'float'); -r.refelectrode=freadat(f, 540, 10, 'text'); -if all(r.refelectrode==0), - %%disp('No reference electrode set in file, setting to CZ') - r.refelectrode(1:2)='CZ'; -end - -% reading all parameters -% ---------------------- -%a = freadat(f, 0, 1, 'short'); -%for i=1:470 -% a = freadat(f, [], 1, 'short'); -% fprintf('offset %3d value %3d\n', i*2, a); -% %if mod(i, 10) == 0, fprintf('\n'); end; -%end; - -% channel parameters -chandat=freadat(f, 900, [75 r.nchannels], 'char'); -r.chan.names=char(chandat(1:9,:))'; -r.chan.reference=chandat(11,:); -r.chan.gain=chandat(1+63,:); -r.chan.baseline=freadat(f, 900+47, [1 r.nchannels], 'short', 75); -r.chan.sensitivity=freadat(f, 900+59, [1 r.nchannels], 'float', 75); -r.chan.calib=freadat(f, 900+71, [1 r.nchannels], 'float', 75); -r.microvoltscalar=r.chan.sensitivity.*r.chan.calib/204.8; - -r.nevent=0; -fseek(f, event.tablepos, 'bof'); -r.event.type=fread(f, 1, 'char'); -event.size=fread(f, 1, 'long'); -%event.offset=fread(f, 1, 'long') - -if r.event.type==1 - event.bytes=8; -elseif r.event.type==2 - event.bytes=19; -else - error('File format error'); -end - -r.nevent=event.size/event.bytes; -r.event.stimtype=freadat(f, event.tablepos+9, r.nevent, 'short', event.bytes); % stimtype -r.event.keyboard=freadat(f, event.tablepos+9+2, r.nevent, 'uchar', event.bytes); % keyboard -r.event.keypadaccept=freadat(f, event.tablepos+9+3, r.nevent, 'uchar', event.bytes); % keypadaccept -offset=freadat(f, event.tablepos+9+4, r.nevent, 'long', event.bytes); % offset -r.event.frame=(offset-samplespos)/(r.nchannels*2); % samplenumber -r.event.time=r.event.frame/r.rate; - -try, - if r.ldheaderonly==1 - fclose(f); - return - end -end - -try, - sample1=r.sample1; - r.t1=r.sample1*r.dt; -catch, - try - startstim=r.startstim; % startstim = [stimtype occurrence] - j=find(r.event.stimtype==startstim(1)); - if length(startstim)>1 - j=j(startstim(2)); - else - j=j(1); - end - r.t1=r.event.time(j); - end - sample1=round(r.t1/r.dt); % first sample to read, zero-based -end -startpos=samplespos+sample1*2*r.nchannels; - -try, ldnsamples=r.ldnsamples; catch, try, ldnsamples=round(r.lddur/r.dt); catch, ldnsamples=r.nsamples; end, end -try, ldchan=r.ldchan; catch, ldchan=[1:r.nchannels]; end -if ~isempty(ldchan) & ldchan==-1, ldchan=[1:r.nchannels]; end -r.ldchan=ldchan; - -% clip events to read window -i=~(sample1<=r.event.frame & r.event.frame=2); - -if needhdr - % get the list of filenames - ls = dir(dirname); - ls = ls(~cell2mat({ls.isdir})); - fname = {}; - for i=1:length(ls) - fname{i} = fullfile(dirname, ls(i).name); - end - - ftype = zeros(length(fname), 1); - for i=1:length(fname) - if filetype(fname{i}, 'plexon_nex') - ftype(i) = 1; - elseif filetype(fname{i}, 'plexon_plx') - ftype(i) = 2; - elseif filetype(fname{i}, 'plexon_ddt') - ftype(i) = 3; - end - end - - % only remember the filenames that are relevant - fname = fname(ftype>0); - ftype = ftype(ftype>0); - - if length(fname)==0 - error('the directory contains no supported files'); - elseif any(ftype~=1) - error('only nex files are supported in a plexon dataset directory'); - end - - for i=1:length(fname) - % this will only work if all files within a dataset return a similar header structure - switch ftype(i) - case 1 - orig(i) = read_plexon_nex(fname{i}); - case 'plexon_plx' - error('plx files are not supported in plexon dataset directory'); - case 'plexon_ddt' - error('ddt files are not supported in plexon dataset directory'); - otherwise - error('unsupported file in plexon dataset directory'); - end - end - - for i=1:length(fname) - if length(orig(i).VarHeader)>1 - error('multiple channels in a single NEX file not supported'); - else - % combine the information from the different files in a single header - label{i} = deblank(orig(i).VarHeader.Name); - Type(i) = orig(i).VarHeader.Type; - WFrequency(i) = orig(i).VarHeader.WFrequency; % of the waveform - ADBitVolts(i) = orig(i).VarHeader.ADtoMV; - NPointsWave(i) = orig(i).VarHeader.NPointsWave; - Beg(i) = orig(i).FileHeader.Beg; - End(i) = orig(i).FileHeader.End; - Frequency(i) = orig(i).FileHeader.Frequency; % of the timestamps - end - end - - if any(Type~=5) - error('not all channels contain continuous data'); - end - - if any(WFrequency~=WFrequency(1)) - warning('not all channels have the same sampling rate'); - end - - if any(Frequency~=Frequency(1)) - warning('not all channels have the same timestamp rate'); - end - - if any(Beg~=Beg(1)) - warning('not all channels start at the same time'); - end - - if any(End~=End(1)) - warning('not all channels end at the same time'); - end - - if any(NPointsWave~=NPointsWave(1)) - warning('not all channels have the same number of samples'); - end - - % construct the header that applies to all channels combined - hdr.label = label; - hdr.nChans = length(label); - hdr.nSamples = NPointsWave(1); - hdr.nSamplesPre = 0; % it is continuous - hdr.nTrials = 1; % it is continuous - hdr.Fs = WFrequency(1); - hdr.FirstTimeStamp = Beg(1); - hdr.LastTimeStamp = End(1); % FIXME this is often not correct - hdr.TimeStampPerSample = Frequency(1)/WFrequency(1); - hdr.filename = fname; - - % remember the original header details - hdr.orig = orig(:); - - % return the header - dat = hdr; - -else - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % read the data of the selected channels (i.e. files) - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - if nargin<5 - % select all channels - chanindx = 1:length(hdr.label); - end - nchan = length(chanindx); - nsample = endsample-begsample+1; - dat = zeros(nchan, nsample); - - for i=1:nchan - thischan = chanindx(i); - thisfile = hdr.filename{thischan}; - switch filetype(thisfile) - case 'plexon_nex' - buf = read_plexon_nex(thisfile, 'header', hdr.orig(thischan), 'channel', 1); % always read the first and only channel - dat(i,:) = buf.dat(begsample:endsample); - case 'plexon_plx' - error('plx files are not supported in plexon dataset directory'); - case 'plexon_ddt' - error('ddt files are not supported in plexon dataset directory'); - otherwise - error('unsupported file in plexon dataset directory'); - end - end -end diff --git a/external/fileio/private/read_plexon_nex.m b/external/fileio/private/read_plexon_nex.m deleted file mode 100644 index 8b33322..0000000 --- a/external/fileio/private/read_plexon_nex.m +++ /dev/null @@ -1,222 +0,0 @@ -function [varargout] = read_plexon_nex(filename, varargin) - -% READ_PLEXON_NEX reads header or data from a Plexon *.nex file, which -% is a file containing action-potential (spike) timestamps and waveforms -% (spike channels), event timestamps (event channels), and continuous -% variable data (continuous A/D channels). -% -% LFP and spike waveform data that is returned by this function is -% expressed in microVolt. -% -% Use as -% [hdr] = read_plexon_nex(filename) -% [dat] = read_plexon_nex(filename, ...) -% [dat1, dat2, dat3, hdr] = read_plexon_nex(filename, ...) -% -% Optional arguments should be specified in key-value pairs and can be -% header structure with header information -% feedback 0 or 1 -% tsonly 0 or 1, read only the timestamps and not the waveforms -% channel number, or list of numbers (that will result in multiple outputs) -% begsample number (for continuous only) -% endsample number (for continuous only) -% -% See also READ_PLEXON_PLX, READ_PLEXON_DDT - -% Copyright (C) 2007, Robert Oostenveld -% -% $Log: read_plexon_nex.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.9 2008/12/15 14:48:22 roboos -% read and write the data in uV/microvolt instead of in mV/milivolt -% -% Revision 1.8 2008/09/30 08:01:04 roboos -% replaced all fread(char=>char) into uint8=>char to ensure that the -% chars are read as 8 bits and not as extended 16 bit characters. The -% 16 bit handling causes problems on some internationalized OS/Matlab -% combinations. -% -% the help of fread specifies "If the precision is 'char' or 'char*1', MATLAB -% reads characters using the encoding scheme associated with the file. -% See FOPEN for more information". -% -% Revision 1.7 2007/10/08 12:59:51 roboos -% give error if no channels present -% -% Revision 1.6 2007/07/19 14:41:56 roboos -% changed indentation and whitespace -% -% Revision 1.5 2007/07/19 08:49:34 roboos -% only give error for multiple continuous segments if specific samples were requested -% -% Revision 1.4 2007/03/26 12:42:20 roboos -% implemented tsonly option to read only the timestamps -% implemented the selection of begin and endsample for continuous channels -% -% Revision 1.3 2007/03/21 12:59:01 roboos -% updated the documentation -% keep timestamps as int32 -% convert the AD values to uV for type=3 and 5 -% give error instead of warning in case of multiple continuous segments -% -% Revision 1.2 2007/03/14 11:46:16 roboos -% only some whitespace changed -% -% Revision 1.1 2007/01/10 17:28:23 roboos -% new implementation, reusing the code from read_nex_xxx but now with complete support for all known data elements -% - -% parse the optional input arguments -hdr = keyval('header', varargin); -channel = keyval('channel', varargin); -feedback = keyval('feedback', varargin); -tsonly = keyval('tsonly', varargin); -begsample = keyval('begsample', varargin); -endsample = keyval('endsample', varargin); - -% set the defaults -if isempty(feedback) - feedback=0; -end -if isempty(tsonly) - tsonly=0; -end -if isempty(begsample) - begsample=1; -end -if isempty(endsample) - endsample=Inf; -end - -% start with empty return values and empty data -varargout = {}; - -% read header info from file, use Matlabs for automatic byte-ordering -fid = fopen(filename, 'r', 'ieee-le'); -fseek(fid, 0, 'eof'); -siz = ftell(fid); -fseek(fid, 0, 'bof'); - -if isempty(hdr) - if feedback, fprintf('reading header from %s\n', filename); end - % a NEX file consists of a file header, followed by a number of variable headers - % sizeof(NexFileHeader) = 544 - % sizeof(NexVarHeader) = 208 - hdr.FileHeader = NexFileHeader(fid); - if hdr.FileHeader.NumVars<1 - error('no channels present in file'); - end - hdr.VarHeader = NexVarHeader(fid, hdr.FileHeader.NumVars); -end - -for i=1:length(channel) - chan = channel(i); - vh = hdr.VarHeader(chan); - clear buf - fseek(fid, vh.DataOffset, 'bof'); - switch vh.Type - case 0 - % Neurons, only timestamps - buf.ts = fread(fid, [1 vh.Count], 'int32=>int32'); - - case 1 - % Events, only timestamps - buf.ts = fread(fid, [1 vh.Count], 'int32=>int32'); - - case 2 - % Interval variables - buf.begs = fread(fid, [1 vh.Count], 'int32=>int32'); - buf.ends = fread(fid, [1 vh.Count], 'int32=>int32'); - - case 3 - % Waveform variables - buf.ts = fread(fid, [1 vh.Count], 'int32=>int32'); - if ~tsonly - buf.dat = fread(fid, [vh.NPointsWave vh.Count], 'int16'); - % convert the AD values to miliVolt, subsequently convert from miliVolt to microVolt - buf.dat = buf.dat * (vh.ADtoMV * 1000); - end - - case 4 - % Population vector - error('population vectors are not supported'); - - case 5 - % Continuously recorded variables - buf.ts = fread(fid, [1 vh.Count], 'int32=>int32'); - buf.indx = fread(fid, [1 vh.Count], 'int32=>int32'); - if vh.Count>1 && (begsample~=1 || endsample~=inf) - error('reading selected samples from multiple AD segments is not supported'); - end - if ~tsonly - numsample = min(endsample - begsample + 1, vh.NPointsWave); - fseek(fid, (begsample-1)*2, 'cof'); - buf.dat = fread(fid, [1 numsample], 'int16'); - % convert the AD values to miliVolt, subsequently convert from miliVolt to microVolt - buf.dat = buf.dat * (vh.ADtoMV * 1000); - end - - case 6 - % Markers - ts = fread(fid, [1 vh.Count], 'int32=>int32'); - for j=1:vh.NMarkers - buf.MarkerNames{j,1} = fread(fid, [1 64], 'uint8=>char'); - for k=1:vh.Count - buf.MarkerValues{j,k} = fread(fid, [1 vh.MarkerLength], 'uint8=>char'); - end - end - - otherwise - error('incorrect channel type'); - end % switch channel type - - % return the data of this channel - varargout{i} = buf; -end % for channel - -% always return the header as last -varargout{end+1} = hdr; - -fclose(fid); -return - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function hdr = NexFileHeader(fid); -hdr.NexFileHeader = fread(fid,4,'uint8=>char')'; % string NEX1 -hdr.Version = fread(fid,1,'int32'); -hdr.Comment = fread(fid,256,'uint8=>char')'; -hdr.Frequency = fread(fid,1,'double'); % timestamped freq. - tics per second -hdr.Beg = fread(fid,1,'int32'); % usually 0 -hdr.End = fread(fid,1,'int32'); % maximum timestamp + 1 -hdr.NumVars = fread(fid,1,'int32'); % number of variables in the first batch -hdr.NextFileHeader = fread(fid,1,'int32'); % position of the next file header in the file, not implemented yet -Padding = fread(fid,256,'uint8=>char')'; % future expansion - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function hdr = NexVarHeader(fid, numvar); -for varlop=1:numvar - hdr(varlop).Type = fread(fid,1,'int32'); % 0 - neuron, 1 event, 2- interval, 3 - waveform, 4 - pop. vector, 5 - continuously recorded - hdr(varlop).Version = fread(fid,1,'int32'); % 100 - hdr(varlop).Name = fread(fid,64,'uint8=>char')'; % variable name - hdr(varlop).DataOffset = fread(fid,1,'int32'); % where the data array for this variable is located in the file - hdr(varlop).Count = fread(fid,1,'int32'); % number of events, intervals, waveforms or weights - hdr(varlop).WireNumber = fread(fid,1,'int32'); % neuron only, not used now - hdr(varlop).UnitNumber = fread(fid,1,'int32'); % neuron only, not used now - hdr(varlop).Gain = fread(fid,1,'int32'); % neuron only, not used now - hdr(varlop).Filter = fread(fid,1,'int32'); % neuron only, not used now - hdr(varlop).XPos = fread(fid,1,'double'); % neuron only, electrode position in (0,100) range, used in 3D - hdr(varlop).YPos = fread(fid,1,'double'); % neuron only, electrode position in (0,100) range, used in 3D - hdr(varlop).WFrequency = fread(fid,1,'double'); % waveform and continuous vars only, w/f sampling frequency - hdr(varlop).ADtoMV = fread(fid,1,'double'); % waveform continuous vars only, coeff. to convert from A/D values to Millivolts - hdr(varlop).NPointsWave = fread(fid,1,'int32'); % waveform only, number of points in each wave - hdr(varlop).NMarkers = fread(fid,1,'int32'); % how many values are associated with each marker - hdr(varlop).MarkerLength = fread(fid,1,'int32'); % how many characters are in each marker value - Padding = fread(fid,68,'uint8=>char')'; -end diff --git a/external/fileio/private/read_sbin_data.m b/external/fileio/private/read_sbin_data.m deleted file mode 100644 index cd49620..0000000 --- a/external/fileio/private/read_sbin_data.m +++ /dev/null @@ -1,103 +0,0 @@ -function [trialData] = read_sbin_data(filename, hdr, begtrial, endtrial, chanindx) - -% READ_SBIN_DATA reads the data from an EGI segmented simple binary format file -% -% Use as -% [trialData] = read_sbin_data(filename, hdr, begtrial, endtrial, chanindx) -% with -% filename name of the input file -% hdr header structure, see READ_HEADER -% begtrial first trial to read, mutually exclusive with begsample+endsample -% endtrial last trial to read, mutually exclusive with begsample+endsample -% chanindx list with channel indices to read -% -% This function returns a 3-D matrix of size Nchans*Nsamples*Ntrials. -%_______________________________________________________________________ -% -% -% Modified from EGI's readEGLY.m with permission 2008-03-31 Joseph Dien -% - -% $Log: read_sbin_data.m,v $ -% Revision 1.2 2009/04/29 10:55:16 jansch -% incorporated handling of unsegmented files -% -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.4 2008/12/08 09:36:49 roboos -% added cvs log to the matlab files -% - -fh=fopen([filename],'r'); -if fh==-1 - error('wrong filename') -end - -version = fread(fh,1,'int32'); - -%check byteorder -[str,maxsize,cEndian]=computer; -if version < 7 - if cEndian == 'B' - endian = 'ieee-be'; - elseif cEndian == 'L' - endian = 'ieee-le'; - end; -elseif (version > 6) && ~bitand(version,6) - if cEndian == 'B' - endian = 'ieee-le'; - elseif cEndian == 'L' - endian = 'ieee-be'; - end; - version = swapbytes(uint32(version)); %hdr.orig.header_array is already byte-swapped -else - error('ERROR: This is not a simple binary file. Note that NetStation does not successfully directly convert EGIS files to simple binary format.\n'); -end; - -if bitand(version,1) == 0 - %error('ERROR: This is an unsegmented file, which is not supported.\n'); - unsegmented = 1; -else - unsegmented = 0; -end; - -precision = bitand(version,6); -Nevents=hdr.orig.header_array(17); - -switch precision - case 2 - trialLength=2*hdr.nSamples*(hdr.nChans+Nevents)+6; - dataType='int16'; - case 4 - trialLength=4*hdr.nSamples*(hdr.nChans+Nevents)+6; - dataType='single'; - case 6 - trialLength=8*hdr.nSamples*(hdr.nChans+Nevents)+6; - dataType='double'; -end - -if unsegmented - %interpret begtrial and endtrial as sample indices - fseek(fh, 36+Nevents*4, 'bof'); %skip over header - nSamples = endtrial-begtrial+1; - trialData = fread(fh, [hdr.nChans+Nevents, nSamples],dataType,endian); -else - fseek(fh, 40+length(hdr.orig.CatLengths)+sum(hdr.orig.CatLengths)+Nevents*4, 'bof'); %skip over header - fseek(fh, (begtrial-1)*trialLength, 'cof'); %skip over initial segments - - trialData=zeros(hdr.nChans,hdr.nSamples,endtrial-begtrial+1); - - for segment=1:(endtrial-begtrial+1) - fseek(fh, 6, 'cof'); %skip over segment info - temp = fread(fh, [(hdr.nChans+Nevents), hdr.nSamples],dataType,endian); - trialData(:,:,segment) = temp(1:hdr.nChans,:); - end -end -trialData=trialData(chanindx, :,:); -fclose(fh); diff --git a/external/fileio/private/read_sbin_events.m b/external/fileio/private/read_sbin_events.m deleted file mode 100644 index 69c4de2..0000000 --- a/external/fileio/private/read_sbin_events.m +++ /dev/null @@ -1,154 +0,0 @@ -function [EventCodes, segHdr, eventData] = read_sbin_events(filename) - -% READ_SBIN_EVENTS reads the events information from an EGI segmented simple binary format file -% -% Use as -% [EventCodes, segHdr, eventData] = read_sbin_events(filename) -% with -% EventCodes - if NEvent (from header_array) != 0, then array of 4-char event names -% segHdr - condition codes and time stamps for each segment -% eventData - if NEvent != 0 then event state for each sample, else 'none' -% and -% filename - the name of the data file -%_______________________________________________________________________ -% -% -% Modified from EGI's readEGLY.m with permission 2008-03-31 Joseph Dien -% - -% $Log: read_sbin_events.m,v $ -% Revision 1.4 2009/09/04 02:44:49 josdie -% Fixed crash for segmented files due to typo in last revision. -% -% Revision 1.3 2009/04/29 10:55:16 jansch -% incorporated handling of unsegmented files -% -% Revision 1.2 2009/03/11 16:12:34 josdie -% Changed category names to cell variables to better support names with differing lengths. -% -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.5 2008/12/08 09:36:49 roboos -% added cvs log to the matlab files -% - -fid=fopen([filename],'r'); -if fid==-1 - error('wrong filename') -end - -version = fread(fid,1,'int32'); - -%check byteorder -[str,maxsize,cEndian]=computer; -if version < 7 - if cEndian == 'B' - endian = 'ieee-be'; - elseif cEndian == 'L' - endian = 'ieee-le'; - end; -elseif (version > 6) && ~bitand(version,6) - if cEndian == 'B' - endian = 'ieee-le'; - elseif cEndian == 'L' - endian = 'ieee-be'; - end; - version = swapbytes(uint32(version)); -else - error('ERROR: This is not a simple binary file. Note that NetStation does not successfully directly convert EGIS files to simple binary format.\n'); -end; - -if bitand(version,1) == 0 - %error('ERROR: This is an unsegmented file, which is not supported.\n'); - unsegmented = 1; -else - unsegmented = 0; -end; - -precision = bitand(version,6); -if precision == 0 - error('File precision is not defined.'); -end; - -% read header... -year = fread(fid,1,'int16',endian); -month = fread(fid,1,'int16',endian); -day = fread(fid,1,'int16',endian); -hour = fread(fid,1,'int16',endian); -minute = fread(fid,1,'int16',endian); -second = fread(fid,1,'int16',endian); -millisecond = fread(fid,1,'int32',endian); -Samp_Rate = fread(fid,1,'int16',endian); -NChan = fread(fid,1,'int16',endian); -Gain = fread(fid,1,'int16',endian); -Bits = fread(fid,1,'int16',endian); -Range = fread(fid,1,'int16',endian); -if unsegmented, - NumCategors = 0; - NSegments = 1; - NSamples = fread(fid,1,'int32',endian); - NEvent = fread(fid,1,'int16',endian); - for j = 1:NEvent - EventCodes(j,1:4) = char(fread(fid,[1,4],'char',endian)); - end - CateNames = []; - CatLengths = []; - preBaseline = []; -else - NumCategors = fread(fid,1,'int16',endian); - for j = 1:NumCategors - CatLengths(j) = fread(fid,1,'int8',endian); - for i = 1:CatLengths(j) - CateNames{j}(i) = char(fread(fid,1,'char',endian)); - end - end - NSegments = fread(fid,1,'int16',endian); - NSamples = fread(fid,1,'int32',endian); % samples per segment - NEvent = fread(fid,1,'int16',endian); % num events per segment - EventCodes = []; - for j = 1:NEvent - EventCodes(j,1:4) = char(fread(fid,[1,4],'char',endian)); - end -end - -%read the actual events -if unsegmented - %data are multiplexed - nsmp = 1; -else - %data are organized in segments - nsmp = NSamples; -end - -eventData = zeros(NEvent,NSegments*NSamples); -segHdr = zeros(NSegments,2); - -for j = 1:NSegments*(NSamples/nsmp) - if unsegmented - %don't know yet - else - %read miniheader per segment - [segHdr(j,1), count] = fread(fid, 1,'int16',endian); %cell - [segHdr(j,2), count] = fread(fid, 1,'int32',endian); %time stamp - end - - switch precision - case 2 - [temp,count] = fread(fid,[NChan+NEvent, nsmp],'int16',endian); - case 4 - [temp,count] = fread(fid,[NChan+NEvent, nsmp],'single',endian); - case 6 - [temp,count] = fread(fid,[NChan+NEvent, nsmp],'double',endian); - end - if (NEvent ~= 0) - eventData(:,((j-1)*nsmp+1):j*nsmp) = temp( (NChan+1):(NChan+NEvent), 1:nsmp); - end -end -fclose(fid); - diff --git a/external/fileio/private/read_sbin_header.m b/external/fileio/private/read_sbin_header.m deleted file mode 100644 index ff467c1..0000000 --- a/external/fileio/private/read_sbin_header.m +++ /dev/null @@ -1,181 +0,0 @@ -function [header_array, CateNames, CatLengths, preBaseline] = read_sbin_header(filename) - -% READ_SBIN_HEADER reads the header information from an EGI segmented simple binary format file -% -% Use as -% [header_array, CateNames, CatLengths, preBaseline] = read_sbin_header(filename) -% with -% header_array - differs between versions, read code for details -% CateNames - category names -% CatLengths - length of category names -% preBaseline - number of samples in the baseline prior to the baseline event -% and -% filename - the name of the data file -% -% Since there is no unique event code for the segmentation event, and hence the baseline period, -% the first event code in the list will be assumed to be the segmentation event. -% NetStation itself simply ignores possible baseline information when importing simple binary files. -%_______________________________________________________________________ -% -% -% Modified from EGI's readEGLY.m with permission 2008-03-31 Joseph Dien -% - -% $Log: read_sbin_header.m,v $ -% Revision 1.5 2009/05/14 18:00:13 josdie -% Added error message to read_sbin_header to handle case where version is an empty set. -% -% Revision 1.4 2009/04/29 10:55:16 jansch -% incorporated handling of unsegmented files -% -% Revision 1.3 2009/03/11 16:12:09 josdie -% Changed category names to cell variables to better support names with differing lengths. -% -% Revision 1.2 2009/03/05 01:03:13 josdie -% Improved process of deducing what the stimulus onset latency is in files with multiple events. -% -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.4 2008/12/08 09:36:49 roboos -% added cvs log to the matlab files -% - -fid=fopen([filename],'r'); -if fid==-1 - error('wrong filename') -end - -version = fread(fid,1,'int32'); -if isempty(version) - error('ERROR: This is not a simple binary file. Note that NetStation does not successfully directly convert EGIS files to simple binary format.'); -end; - -%check byteorder -[str,maxsize,cEndian]=computer; -if version < 7 - if cEndian == 'B' - endian = 'ieee-be'; - elseif cEndian == 'L' - endian = 'ieee-le'; - end; -elseif (version > 6) && ~bitand(version,6) - if cEndian == 'B' - endian = 'ieee-le'; - elseif cEndian == 'L' - endian = 'ieee-be'; - end; - version = swapbytes(uint32(version)); -else - error('ERROR: This is not a simple binary file. Note that NetStation does not successfully directly convert EGIS files to simple binary format.'); -end; - -if bitand(version,1) == 0 - %error('ERROR: This is an unsegmented file, which is not supported.'); - unsegmented = 1; -else - unsegmented = 0; -end; - -precision = bitand(version,6); -if precision == 0 - error('File precision is not defined.'); -end; - -% read header... -year = fread(fid,1,'int16',endian); -month = fread(fid,1,'int16',endian); -day = fread(fid,1,'int16',endian); -hour = fread(fid,1,'int16',endian); -minute = fread(fid,1,'int16',endian); -second = fread(fid,1,'int16',endian); -millisecond = fread(fid,1,'int32',endian); -Samp_Rate = fread(fid,1,'int16',endian); -NChan = fread(fid,1,'int16',endian); -Gain = fread(fid,1,'int16',endian); -Bits = fread(fid,1,'int16',endian); -Range = fread(fid,1,'int16',endian); - -if unsegmented, - NumCategors = 0; - NSegments = 1; - NSamples = fread(fid,1,'int32',endian); - NEvent = fread(fid,1,'int16',endian); - for j = 1:NEvent - EventCodes(j,1:4) = char(fread(fid,[1,4],'char',endian)); - end - CateNames = []; - CatLengths = []; - preBaseline = []; -else - NumCategors = fread(fid,1,'int16',endian); - for j = 1:NumCategors - CatLengths(j) = fread(fid,1,'int8',endian); - for i = 1:CatLengths(j) - CateNames{j}(i) = char(fread(fid,1,'char',endian)); - end - end - NSegments = fread(fid,1,'int16',endian); - NSamples = fread(fid,1,'int32',endian); % samples per segment - NEvent = fread(fid,1,'int16',endian); % num events per segment - EventCodes = []; - for j = 1:NEvent - EventCodes(j,1:4) = char(fread(fid,[1,4],'char',endian)); - end - - - - preBaseline=0; - if NEvent > 0 - - for j = 1:NSegments - [segHdr(j,1), count] = fread(fid, 1,'int16',endian); %cell - [segHdr(j,2), count] = fread(fid, 1,'int32',endian); %time stamp - switch precision - case 2 - [temp,count] = fread(fid,[NChan+NEvent, NSamples],'int16',endian); - case 4 - [temp,count] = fread(fid,[NChan+NEvent, NSamples],'single',endian); - case 6 - [temp,count] = fread(fid,[NChan+NEvent, NSamples],'double',endian); - end - if (NEvent ~= 0) - eventData(:,((j-1)*NSamples+1):j*NSamples) = temp( (NChan+1):(NChan+NEvent), 1:NSamples); - end - end - - if NEvent == 1 - %assume this is the segmentation event - theEvent=find(eventData(1,:)>0); - theEvent=mod(theEvent(1),NSamples); - else - %assume the sample that always has an event is the baseline - %if more than one, choose the earliest one - baselineCandidates = unique(mod(find(eventData(:,:)'),NSamples)); - counters=zeros(1,length(baselineCandidates)); - totalEventSamples=mod(find(eventData(:,:)'),NSamples); - - for i = 1:length(totalEventSamples) - theMatch=find(ismember(baselineCandidates,totalEventSamples(i))); - counters(theMatch)=counters(theMatch)+1; - end; - theEvent=min(baselineCandidates(find(ismember(counters,NSegments)))); - end; - - preBaseline=theEvent-1; - if preBaseline == -1 - preBaseline =0; - end; - end -end - -fclose(fid); - -header_array = double([version year month day hour minute second millisecond Samp_Rate NChan Gain Bits Range NumCategors, NSegments, NSamples, NEvent]); - - diff --git a/external/fileio/private/read_sens.m b/external/fileio/private/read_sens.m deleted file mode 100644 index 9caf54a..0000000 --- a/external/fileio/private/read_sens.m +++ /dev/null @@ -1,259 +0,0 @@ -function [sens] = read_sens(filename, varargin) - -% READ_SENS read sensor positions from various manufacturer specific files. -% Currently supported are ASA, BESA, Polhemus and Matlab for EEG -% electrodes and CTF and Neuromag for MEG gradiometers. -% -% Use as -% grad = read_sens(filename, ...) % for gradiometers -% elec = read_sens(filename, ...) % for electrodes -% -% Additional options should be specified in key-value pairs and can be -% 'fileformat' string -% -% An electrode definition contain the following fields -% elec.pnt Nx3 matrix with carthesian (x,y,z) coordinates of each electrodes -% elec.label cell-array of length N with the label of each electrode -% -% A gradiometer definition generally consists of multiple coils per -% channel, e.g.two coils for a 1st order gradiometer in which the -% orientation of the coils is opposite. Each coil is described -% separately and a large "tra" matrix (can be sparse) has to be -% given that defines how the forward computed field is combined over -% the coils to generate the output of each channel. The gradiometer -% definition constsis of the following fields -% grad.pnt Mx3 matrix with the position of each coil -% grad.ori Mx3 matrix with the orientation of each coil -% grad.tra NxM matrix with the weight of each coil into each channel -% grad.label cell-array of length N with the label of each of the channels -% -% See also TRANSFORM_SENS, PREPARE_VOL_SENS, COMPUTE_LEADFIELD - -% Copyright (C) 2005-2008, Robert Oostenveld -% -% $Log: read_sens.m,v $ -% Revision 1.16 2009/10/16 07:32:08 roboos -% renamed chieti into itab for consistency with other formats -% -% Revision 1.15 2009/10/13 10:12:51 roboos -% added support for chieti_raw -% -% Revision 1.14 2009/07/02 10:34:21 vlalit -% Added eeglab_set to the list of formats where electrode locations can be found in -% the header. -% -% Revision 1.13 2009/06/03 09:52:15 roboos -% added zebris_sfp -% -% Revision 1.12 2009/02/02 16:10:15 vlalit -% Provide the 'headertype' argument to the internal read_header call. -% -% Revision 1.11 2009/01/23 10:32:55 vlalit -% New reader for Neuromag fif format using the MNE toolbox (http://www.nmr.mgh.harvard.edu/martinos/userInfo/data/sofMNE.php) implemented by Laurence Hunt. -% -% Revision 1.10 2008/09/18 10:38:33 vlalit -% Added 4D formats to be recognized by read_sens -% -% Revision 1.9 2008/05/22 14:33:18 vlalit -% Changes related to generalization of fiducials' handling in SPM. -% -% Revision 1.8 2008/04/14 20:51:36 roboos -% added convert_units -% -% Revision 1.7 2008/04/11 16:17:22 roboos -% added polhemus_fil -% -% Revision 1.6 2008/03/20 13:43:14 roboos -% added support for besa_pos -% -% Revision 1.5 2008/03/18 12:34:30 roboos -% fixed bug: added varargin to input arguments, thanks to Juan -% -% Revision 1.4 2008/03/06 09:27:54 roboos -% updated documentation -% -% Revision 1.3 2008/03/05 11:06:11 roboos -% test the presence of the fileio toolbox, needed when this function is included in forwinv -% -% Revision 1.2 2008/03/05 10:54:05 roboos -% added optional argument for fileformat -% some documentation changes -% -% Revision 1.1 2008/01/28 20:10:11 roboos -% new functions based on existing fieldtrip code -% - -% test whether the file exists -if ~exist(filename) - error(sprintf('file ''%s'' does not exist', filename)); -end - -% get the options -fileformat = keyval('fileformat', varargin); - -% determine the filetype -if isempty(fileformat) - fileformat = filetype(filename); -end - -switch fileformat - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % read the content from various files that contain EEG electrode positions - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - case 'asa_elc' - sens = read_asa_elc(filename); - - case 'polhemus_pos' - sens = read_brainvision_pos(filename); - - case 'besa_pos' - tmp = importdata(filename); - if ~isnumeric(tmp) - error('unexpected file format for fileformat=besa_pos') - end - [nchan,nrow] = size(tmp); - if nrow==3 - sens.pnt = tmp; - elseif nrow==9 - pnt1 = tmp(:,1:3); % bottom coil - pnt2 = tmp(:,4:6); % top coil - ori = tmp(:,7:9); % orientation of bottom coil - sens.pnt = [pnt1; pnt2]; - sens.ori = [ori; ori]; - sens.tra = [eye(nchan) -eye(nchan)]; - else - error('unexpected file format for fileformat=besa_pos') - end - [p, f, x] = fileparts(filename); - elpfile = fullfile(p, [f '.elp']); - elafile = fullfile(p, [f '.ela']); - if exist(elpfile, 'file') - warning(sprintf('reading channel labels from %s', elpfile)); - % read the channel names from the accompanying ELP file - lbl = importdata(elpfile); - sens.label = strrep(lbl.textdata(:,2) ,'''', ''); - elseif exist(elafile, 'file') - warning(sprintf('reading channel labels from %s', elafile)); - % read the channel names from the accompanying ELA file - lbl = importdata(elafile); - lbl = strrep(lbl, 'MEG ', ''); % remove the channel type - lbl = strrep(lbl, 'EEG ', ''); % remove the channel type - sens.label = lbl; - else - % the file does not have channel labels in it - warning('creating fake channel names for besa_pos'); - for i=1:nchan - sens.label{i} = sprintf('%03d', i); - end - end - - case 'besa_sfp' - fid = fopen(filename); - tmp = textscan(fid, ' %[^ \t]%n%n%n'); - fclose(fid); - sens.label = tmp{1}; - sens.pnt = [tmp{2:4}]; - - case 'itab_raw' - hastoolbox('fileio'); - hdr = read_header(filename); - sens = hdr.grad; - - case 'neuromag_mne' - hastoolbox('fileio'); - hdr = read_header(filename,'headerformat','neuromag_mne'); - sens = hdr.elec; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % gradiometer information is always stored in the header of the MEG dataset - % hence uses the standard fieldtrip/fileio read_header function - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - case {'ctf_ds', 'ctf_res4', 'neuromag_fif', '4d', '4d_pdf', '4d_m4d', '4d_xyz', 'yokogawa_ave', 'yokogawa_con', 'yokogawa_raw'} - % check the availability of the required low-level toolbox - % this is required because the read_sens function is also on itself included in the forwinv toolbox - hastoolbox('fileio'); - hdr = read_header(filename, 'headerformat', fileformat); - sens = hdr.grad; - - - case 'neuromag_mne_grad' - hastoolbox('fileio'); - hdr = read_header(filename,'headerformat','neuromag_mne'); - sens = hdr.grad; - - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % This is for EEG formats where electrode positions can be stored with the data - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - case {'spmeeg_mat', 'eeglab_set'} - % check the availability of the required low-level toolbox - % this is required because the read_sens function is also on itself included in the forwinv toolbox - hastoolbox('fileio'); - hdr = read_header(filename); - - if isfield(hdr, 'grad') - sens = hdr.grad; - elseif isfield(hdr, 'elec') - sens = hdr.elec; - else - error('no electrodes or gradiometers found in the file') - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % these are created at the FIL in London with a polhemus tracker - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - case 'polhemus_fil' - [sens.fid, sens.pnt] = read_polhemus_fil(filename, 0); - - % the file does not have channel labels in it - warning('no channel names in polhemus file, using numbers instead'); - for i=1:size(sens.pnt, 1) - sens.label{i} = sprintf('%03d', i); - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % matlab files can contain either electrodes or gradiometers - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - case 'matlab' - matfile = filename; % this solves a problem with the matlab compiler v3 - warning('off', 'MATLAB:load:variableNotFound'); - tmp = load(matfile, 'elec', 'grad', 'sens', 'elc'); - warning('on', 'MATLAB:load:variableNotFound'); - if isfield(tmp, 'grad') - sens = getfield(tmp, 'grad'); - elseif isfield(tmp, 'elec') - sens = getfield(tmp, 'elec'); - elseif isfield(tmp, 'sens') - sens = getfield(tmp, 'sens'); - elseif isfield(tmp, 'elc') - sens = getfield(tmp, 'elc'); - else - error('no electrodes or gradiometers found in Matlab file'); - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % these are created by a Zebris tracker, at CRC in Liege at least. - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - case 'zebris_sfp' - [sens.fid, sens.pnt, sens.fid_label, sens.label] = read_zebris(filename, 0); - - otherwise - error('unknown fileformat for electrodes or gradiometers'); -end - -if senstype(sens, 'eeg') - % only keep positions and labels in case of EEG electrodes - dum = sens; - sens = []; - sens.pnt = dum.pnt; - sens.label = dum.label; -end - -% this will add the units to the sensor array -sens = convert_units(sens); diff --git a/external/fileio/private/read_shm_data.m b/external/fileio/private/read_shm_data.m deleted file mode 100644 index b1e2358..0000000 --- a/external/fileio/private/read_shm_data.m +++ /dev/null @@ -1,96 +0,0 @@ -function [dat, dimord] = read_shm_data(hdr, chanindx, begtrial, endtrial) - -% READ_SHM_DATA reads the data in real-time from shared memory -% this is a helper function for READ_DATA - -% Copyright (C) 2007, Robert Oostenveld -% -% $Log: read_shm_data.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.2 2008/11/20 13:56:11 roboos -% fixed gain when header is read using ctf p-files -% -% Revision 1.1 2007/08/01 12:12:06 roboos -% moved the actual code from the normal functions into these helper functions -% fixed some bugs related to reading the header from a user-specified res4 file and setting the trigger detection -% use the new trigger detection in AcqBuffer when possible, use the old trigger detection if no setup buffer is present -% implemented caching of the data packets (using global variable ctf_shm) -% - -% read the data from shared memory, first the meta information only -[msgType msgId sampleNumber numSamples numChannels] = read_ctf_shm; - -% this global variable is used for caching in read_data -% which inproved the throughput when reading overlapping data segments -global ctf_shm -if isempty(ctf_shm) - ctf_shm.msgType = nan(size(msgType)); - ctf_shm.msgId = nan(size(msgId)); - ctf_shm.sampleNumber = nan(size(sampleNumber)); - ctf_shm.numSamples = nan(size(numSamples)); - ctf_shm.numChannels = nan(size(numChannels)); - ctf_shm.data = {}; - ctf_shm.hit = 0; - ctf_shm.mis = 0; -end - -% there seems to be a bug in Acq, causing the messageId to wrap around -% hence it cannot be used as index into the packets, so construct a new trial numbering vector -trlNum = nan(size(msgId)); -trlNum(msgType==1) = sampleNumber(msgType==1)./numSamples(msgType==1) + 1; - -% allocate memory for teh data, fill with NaNs -dat = nan(length(chanindx), hdr.nSamples, endtrial-begtrial+1); - -% determine which trials/packets to read -sel = find((trlNum>=begtrial) & (trlNum<=endtrial)); - -% this is for calibrating the integer values to physical values -if isfield(hdr, 'orig') && isfield(hdr.orig, 'gainV') - gain = sparse(diag(hdr.orig.gainV(chanindx))); -elseif isfield(hdr, 'orig') && isfield(hdr.orig, 'res4') - gain = sparse(diag([hdr.orig.res4.senres(chanindx).gain])); -end - -for i=1:length(sel) - % nchan = numChannels(i); - % nsmp = numSamples(i); - nchan = hdr.nChans; - nsmp = hdr.nSamples; - % buf = read_ctf_shm(sel(i)); - % buf = buf(1:nchan*nsmp); - if all([msgType(sel(i)) msgId(sel(i)) sampleNumber(sel(i)) numSamples(sel(i)) numChannels(sel(i))] == [ctf_shm.msgType(sel(i)) ctf_shm.msgId(sel(i)) ctf_shm.sampleNumber(sel(i)) ctf_shm.numSamples(sel(i)) ctf_shm.numChannels(sel(i))]) - % get the data from the cache - buf = ctf_shm.data{sel(i)}; - ctf_shm.hit = ctf_shm.hit+1; - else - % read the data from shared memory, update the cache - buf = read_ctf_shm(sel(i),nchan*nsmp); - ctf_shm.data{sel(i)} = buf; - ctf_shm.msgType(sel(i)) = msgType(sel(i)); - ctf_shm.msgId(sel(i)) = msgId(sel(i)); - ctf_shm.sampleNumber(sel(i)) = sampleNumber(sel(i)); - ctf_shm.numSamples(sel(i)) = numSamples(sel(i)); - ctf_shm.numChannels(sel(i)) = numChannels(sel(i)); - ctf_shm.mis = ctf_shm.mis+1; - end - buf = reshape(buf, nchan, nsmp); - thistrial = trlNum(sel(i)); - % apply calibration to the selected channels - dat(:,:,thistrial-begtrial+1) = gain * double(buf(chanindx,:)); -end - -% if any(isnan(dat(:))) -% warning('data has been padded with NaNs'); -% fprintf('trials present = %d - %d\n', min(trlNum), max(trlNum)); -% fprintf('trials requested = %d - %d\n', begtrial, endtrial); -% end - -dimord = 'chans_samples_trials'; diff --git a/external/fileio/private/read_shm_header.m b/external/fileio/private/read_shm_header.m deleted file mode 100644 index af526a1..0000000 --- a/external/fileio/private/read_shm_header.m +++ /dev/null @@ -1,103 +0,0 @@ -function [hdr] = read_shm_header(filename) - -% READ_SHM_HEADER reads the header information in real-time from shared memory -% this is a helper function for READ_HEADER - -% Copyright (C) 2007, Robert Oostenveld -% -% $Log: read_shm_header.m,v $ -% Revision 1.1 2009/01/14 09:12:15 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.5 2009/01/12 12:01:55 roboos -% determine number of samples and trials from only the data blocks, not all blocks. It seems that memcpy has changed, which now sometimes seems to cause a block to be "corupt" for a small amount of time. -% -% Revision 1.4 2008/12/02 08:28:40 roboos -% fixed typo, missing ) -% -% Revision 1.3 2008/11/20 13:58:11 roboos -% fixed hdr.nTrials and nSamples (ensure that it is read as blocks) -% use caching when reading header from file -% -% Revision 1.2 2008/10/08 10:08:06 roboos -% detect trigger channels also when header is read using ctf_new -% -% Revision 1.1 2007/08/01 12:12:06 roboos -% moved the actual code from the normal functions into these helper functions -% fixed some bugs related to reading the header from a user-specified res4 file and setting the trigger detection -% use the new trigger detection in AcqBuffer when possible, use the old trigger detection if no setup buffer is present -% implemented caching of the data packets (using global variable ctf_shm) -% - -% this global variable is used for caching in read_data, to improve the throughput when reading overlapping data segments -global ctf_shm -ctf_shm = []; - -% decode the filename, which looks like shm:// -headerfile = filetype_check_uri(filename); - -if ~isempty(headerfile) - % the headerfile has been specified by the user - hdr = read_header(headerfile, 'cache', true); - buf = []; - [msgType msgId sampleNumber numSamples numChannels] = read_ctf_shm; - sel = find(msgType==0); - if ~isempty(sel) - buf = read_ctf_shm(sel); - else - buf = []; - end -else - % get the name of the headerfile from shared memory - [msgType msgId sampleNumber numSamples numChannels] = read_ctf_shm; - sel = find(msgType==0); - if ~isempty(sel) - buf = read_ctf_shm(sel); - str = char(typecast(buf, 'uint8')); - pad = find(str==0); - headerfile = char(str(1:(pad(1)-1))); - hdr = read_header(headerfile, 'cache', true); - else - error('could not determine header file location from shared memory'); - end -end - -if ~isempty(buf) - % meg channels are 5, refmag 0, refgrad 1, adcs 18, trigger 11, eeg 9 - if isfield(hdr, 'orig') && isfield(hdr.orig, 'sensType') - origSensType = hdr.orig.sensType; - elseif isfield(hdr, 'orig') && isfield(hdr.orig, 'res4') - origSensType = [hdr.orig.res4.senres.sensorTypeIndex]; - end - % do online detection of triggers inside AcqBuffer - trgchan = find(origSensType(:)'==11); - if length(trgchan)>10 - error('online detection of triggers in AcqBuffer only works with up to 10 trigger channels'); - end - % specify the channel count and the trigger channels in the setup buffer - buf(28160-9011) = hdr.nChans; % tell the number of actual channels - buf(28160-9010) = length(trgchan); % tell the number of trigger channels - for i=1:length(trgchan) - buf(28160-9010+i) = trgchan(i)-1; % tell the index of the trigger channel, zero offset - end - % the setup packet may have moved in the meantine, determine its latest location - [msgType msgId sampleNumber numSamples numChannels] = read_ctf_shm; - sel = find(msgType==0); - % write the updated setup packet, this should cause AcqBuffer to do online trigger detection - write_ctf_shm(sel, 0, 0, 0, 0, 0, buf); -else - warning('no setup in shared memory, could not enable trigger detection'); -end - -% the following information is determined from shared memory -sel = find(msgType==1); % these are the data packets -hdr.nTrials = double(max(sampleNumber(sel)))/double(max(numSamples(sel))); -hdr.nSamples = double(max(numSamples(sel))); -hdr.nSamplesPre = 0; - - diff --git a/external/fileio/private/read_spike.m b/external/fileio/private/read_spike.m deleted file mode 100644 index 40a3c92..0000000 --- a/external/fileio/private/read_spike.m +++ /dev/null @@ -1,226 +0,0 @@ -function [spike] = read_spike(filename, varargin); - -% READ_SPIKE reads spike timestamps and waveforms from various data -% formats. -% -% Use as -% [spike] = read_spike(filename, ...) -% -% Additional options should be specified in key-value pairs and can be -% 'spikeformat' -% -% The output spike structure contains -% spike.label = 1xNchans cell-array, with channel labels -% spike.waveform = 1xNchans cell-array, each element contains a matrix (Nsamples X Nspikes) -% spike.timestamp = 1xNchans cell-array, each element contains a vector (1 X Nspikes) -% spike.unit = 1xNchans cell-array, each element contains a vector (1 X Nspikes) -% -% See also READ_HEADER, READ_DATA, READ_EVENT - -% Copyright (C) 2007-2008, Robert Oostenveld -% -% $Log: read_spike.m,v $ -% Revision 1.16 2009/03/04 07:49:43 roboos -% moved from private to main fileio -% -% Revision 1.1 2009/01/14 09:33:10 roboos -% moved even more files from fileio to fileio/private, see previous log entry -% -% Revision 1.14 2009/01/14 08:51:34 roboos -% fixed *.nts extension (was *.nte), applies to filetype, name of low-level function and name of data structure -% -% Revision 1.13 2008/11/12 17:02:03 roboos -% explicitely specify ieee-le in fopen() -% -% Revision 1.12 2008/07/09 12:16:38 roboos -% added mclust_t -% -% Revision 1.11 2008/03/25 10:59:02 roboos -% use either NLX_Base_Class_Name or AcqEntName, whichever is available -% -% Revision 1.10 2008/03/04 11:17:07 roboos -% added support for neuralynx_nst (tested) and neuralynx_ntt (untested) -% -% Revision 1.9 2007/03/26 12:32:41 roboos -% changed the API for plexon_plx -% -% Revision 1.8 2007/03/21 13:00:02 roboos -% keep the original data header in the output structure -% -% Revision 1.7 2007/03/19 17:08:57 roboos -% implemented neuralynx_nte -% use timestamp_plexon as low level function instead of replicating the typecasting here -% -% Revision 1.6 2007/03/18 22:02:41 roboos -% also deal with plexon plx spike channels that do not contain any data -% -% Revision 1.5 2007/03/13 14:32:47 roboos -% removed header as optional argument, since read_header does not support spike-only files -% in case of plexon_plx, read the header from the file using low-level importer -% implemented support for plexon_nex, type 0 and 3 -% -% Revision 1.4 2007/02/27 09:56:28 roboos -% added some documentation -% -% Revision 1.3 2007/01/09 09:40:38 roboos -% added neuralynx_nse -% -% Revision 1.2 2007/01/04 17:14:12 roboos -% deblank channel labels, renamed data to waveform -% -% Revision 1.1 2007/01/04 12:10:14 roboos -% new implementation, sofar only for plexon_plx -% - -% get the options -spikeformat = keyval('spikeformat', varargin); - -% determine the filetype -if isempty(spikeformat) - spikeformat = filetype(filename); -end - -switch spikeformat - case {'neuralynx_ncs' 'plexon_ddt'} - % these files only contain continuous data - error('file does not contain spike timestamps or waveforms'); - - case 'matlab' - % plain matlab file with a single variable in it - load(filename, 'spike'); - - case 'mclust_t' - fp = fopen(filename, 'rb', 'ieee-le'); - H = ReadHeader(fp); - fclose(fp); - % read only from one file - S = LoadSpikes({filename}); - spike.hdr = H(:); - spike.timestamp = S; - [p, f, x] = fileparts(filename); - spike.label = {f}; % use the filename as label for the spike channel - spike.waveform = {}; % this is unknown - spike.unit = {}; % this is unknown - - case 'neuralynx_nse' - % single channel file, read all records - nse = read_neuralynx_nse(filename); - if isfield(nse.hdr, 'NLX_Base_Class_Name') - spike.label = {nse.hdr.NLX_Base_Class_Name}; - else - spike.label = {nse.hdr.AcqEntName}; - end - spike.timestamp = {nse.TimeStamp}; - spike.waveform = {nse.dat}; - spike.unit = {nse.CellNumber}; - spike.hdr = nse.hdr; - - case 'neuralynx_nst' - % single channel stereotrode file, read all records - nst = read_neuralynx_nst(filename, 1, inf); - if isfield(nst.hdr, 'NLX_Base_Class_Name') - spike.label = {nst.hdr.NLX_Base_Class_Name}; - else - spike.label = {nst.hdr.AcqEntName}; - end - spike.timestamp = {nst.TimeStamp}; - spike.waveform = {nst.dat}; - spike.unit = {nst.CellNumber}; - spike.hdr = nst.hdr; - - case 'neuralynx_ntt' - % single channel stereotrode file, read all records - ntt = read_neuralynx_ntt(filename); - if isfield(ntt.hdr, 'NLX_Base_Class_Name') - spike.label = {ntt.hdr.NLX_Base_Class_Name}; - else - spike.label = {ntt.hdr.AcqEntName}; - end - spike.timestamp = {ntt.TimeStamp}; - spike.waveform = {ntt.dat}; - spike.unit = {ntt.CellNumber}; - spike.hdr = ntt.hdr; - - case 'neuralynx_nts' - % single channel file, read all records - nts = read_neuralynx_nts(filename); - if isfield(nte.hdr, 'NLX_Base_Class_Name') - spike.label = {nts.hdr.NLX_Base_Class_Name}; - else - spike.label = {nts.hdr.AcqEntName}; - end - spike.timestamp = {nts.TimeStamp(:)'}; - spike.waveform = {zeros(0,length(nts.TimeStamp))}; % does not contain waveforms - spike.unit = {zeros(0,length(nts.TimeStamp))}; % does not contain units - spike.hdr = nts.hdr; - - case 'plexon_nex' - % a single file can contain multiple channels of different types - hdr = read_plexon_nex(filename); - typ = [hdr.VarHeader.Type]; - chan = 0; - - spike.label = {}; - spike.waveform = {}; - spike.unit = {}; - spike.timestamp = {}; - - for i=1:length(typ) - if typ(i)==0 - % neurons, only timestamps - nex = read_plexon_nex(filename, 'channel', i); - nspike = length(nex.ts); - chan = chan + 1; - spike.label{chan} = deblank(hdr.VarHeader(i).Name); - spike.waveform{chan} = zeros(0, nspike); - spike.unit{chan} = nan*ones(1,nspike); - spike.timestamp{chan} = nex.ts; - elseif typ(i)==3 - % neurons, timestamps and waveforms - nex = read_plexon_nex(filename, 'channel', i); - chan = chan + 1; - nspike = length(nex.ts); - spike.label{chan} = deblank(hdr.VarHeader(i).Name); - spike.waveform{chan} = nex.dat; - spike.unit{chan} = nan*ones(1,nspike); - spike.timestamp{chan} = nex.ts; - end - end - spike.hdr = hdr; - - case 'plexon_plx' - % read the header information - hdr = read_plexon_plx(filename); - nchan = length(hdr.ChannelHeader); - typ = [hdr.DataBlockHeader.Type]; - unit = [hdr.DataBlockHeader.Unit]; - chan = [hdr.DataBlockHeader.Channel]; - - for i=1:nchan - % select the data blocks that contain spike waveforms and that belong to this channel - sel = (typ==1 & chan==hdr.ChannelHeader(i).Channel); - - if any(sel) - % get the timestamps that correspond with this spike channel - tsl = [hdr.DataBlockHeader(sel).TimeStamp]; - tsh = [hdr.DataBlockHeader(sel).UpperByteOf5ByteTimestamp]; - % convert the 16 bit high timestamp into a 32 bit integer - ts = timestamp_plexon(tsl, tsh); - spike.timestamp{i} = ts; - spike.unit{i} = unit(sel); - else - % this spike channel is empty - spike.timestamp{i} = []; - spike.unit{i} = []; - end - end - for i=1:nchan - spike.label{i} = deblank(hdr.ChannelHeader(i).Name); - spike.waveform{i} = read_plexon_plx(filename, 'ChannelIndex', i, 'header', hdr); - end - spike.hdr = hdr; - - otherwise - error('unsupported data format'); -end - diff --git a/external/fileio/private/read_spike6mat_data.m b/external/fileio/private/read_spike6mat_data.m deleted file mode 100644 index 9343d12..0000000 --- a/external/fileio/private/read_spike6mat_data.m +++ /dev/null @@ -1,56 +0,0 @@ -function dat = read_spike6mat_data(filename, varargin) -% read_spike6mat_data() - read Matlab files exported from Spike 6 -% -% Usage: -% >> header = read_spike6mat_data(filename, varargin); -% -% Inputs: -% filename - [string] file name -% -% Optional inputs: -% 'begsample' first sample to read -% 'endsample' last sample to read -% 'chanindx' - list with channel indices to read -% 'header' - FILEIO structure header -% -% Outputs: -% dat - data over the specified range -% _______________________________________________________________________ -% Copyright (C) 2008 Institute of Neurology, UCL -% Vladimir Litvak - - - -if nargin < 1 - help read_spike6mat_data; - return; -end; - -header = keyval('header', varargin); -begsample = keyval('begsample', varargin); -endsample = keyval('endsample', varargin); -chanindx = keyval('chanindx', varargin); - - -if isempty(header) - header = read_spike6mat_header(filename); -end - -if isempty(begsample), begsample = 1; end; -if isempty(endsample), endsample = header.nSamples; end; - -try - vars = struct2cell(load(filename)); -catch - error('File not found or wrong format.'); -end - -if isempty(chanindx) - chanindx = 1:numel(vars); -end - -dat = zeros(length(chanindx), endsample-begsample+1); - -for i = 1:length(chanindx) - dat(i, :) = vars{chanindx(i)}.values(begsample:endsample); -end diff --git a/external/fileio/private/read_spike6mat_header.m b/external/fileio/private/read_spike6mat_header.m deleted file mode 100644 index e7eb297..0000000 --- a/external/fileio/private/read_spike6mat_header.m +++ /dev/null @@ -1,55 +0,0 @@ -function header = read_spike6mat_header(filename) - -% read_spike6mat_header() - read Matlab files exported from Spike 6 -% -% Usage: -% >> header = read_spike6mat_header(filename); -% -% Inputs: -% filename - [string] file name -% -% Outputs: -% header - FILEIO toolbox type structure -% _______________________________________________________________________ -% Copyright (C) 2008 Institute of Neurology, UCL -% Vladimir Litvak - -if nargin < 1 - help read_spike6mat_header; - return; -end; - -try - vars = struct2cell(load(filename)); -catch - error('File not found or wrong format.'); -end - -header = []; -header.nChans = length(vars); -header.label = {}; - -fsample = []; -onsets = []; -lengths = []; -for i = 1:numel(vars) - fsample(i) = round(1./vars{i}.interval); - onsets(i) = 1e-3*round(1e3*vars{i}.times(1)); - lengths(i) = vars{i}.length; - header.label{i} = vars{i}.title; -end - -if length(unique(fsample))>1 || length(unique(onsets))>1 || length(unique(lengths))>1 - error('Only files with identical channel parameters are supported'); -end - -header.Fs = unique(fsample); - -header.nSamples = unique(lengths); - -header.nSamplesPre = -round(unique(onsets)*header.Fs); - -header.nTrials = 1; - -header.label = header.label(:); - \ No newline at end of file diff --git a/external/fileio/private/read_spmeeg_data.m b/external/fileio/private/read_spmeeg_data.m deleted file mode 100644 index 21c9991..0000000 --- a/external/fileio/private/read_spmeeg_data.m +++ /dev/null @@ -1,99 +0,0 @@ -function dat = read_spmeeg_data(filename, varargin) -% read_spmeeg_data() - import SPM5 and SPM8 meeg datasets -% -% Usage: -% >> header = read_spmeeg_data(filename, varargin); -% -% Inputs: -% filename - [string] file name -% -% Optional inputs: -% 'begsample' first sample to read -% 'endsample' last sample to read -% 'chanindx' - list with channel indices to read -% 'header' - FILEIO structure header -% -% Outputs: -% dat - data over the specified range -% _______________________________________________________________________ -% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% Vladimir Litvak - - - -if nargin < 1 - help read_spmeeg_data; - return; -end; - - -typenames = {'uint8','int16','int32','float32','float64','int8','uint16','uint32'}; -typesizes = [1 2 4 4 8 1 2 4]; - -header = keyval('header', varargin); -begsample = keyval('begsample', varargin); -endsample = keyval('endsample', varargin); -chanindx = keyval('chanindx', varargin); - -if isempty(header) - header = read_spmeeg_header([filename(1:(end-3)) 'mat']); -end - -if isempty(begsample), begsample = 1; end; -if isempty(endsample), endsample = header.nSamples; end; - - - -datatype = 'float32-le'; -scale = []; -if isfield(header, 'orig') - if isfield(header.orig, 'data') && isnumeric(header.orig.data) ... - && ~isempty(header.orig.data) - try - dat = reshape(header.orig.data(chanindx, :, :), length(chanindx), []); - dat = dat(:, begsample:endsample); - return; - end - end - - if isfield(header.orig, 'datatype') - datatype = header.orig.datatype; - elseif isfield(header.orig.data, 'datatype') - datatype = header.orig.data.datatype; - end - if isfield(header.orig, 'scale') - scale = header.orig.scale; - elseif isfield(header.orig.data, 'scale') - scale = header.orig.data.scale; - end -end - -stepsize = typesizes(strmatch(strtok(datatype, '-'), typenames)); - -filename = [filename(1:(end-3)) 'dat']; - -fid = fopen(filename, 'r'); -fseek(fid, stepsize*header.nChans*(begsample-1), 'bof'); -[dat, siz] = fread(fid, [header.nChans, (endsample-begsample+1)], strtok(datatype, '-')); -fclose(fid); - -if ~isempty(chanindx) - % select the desired channels - dat = dat(chanindx,:); -end - -if ~isempty(scale) && ~ismember(strtok(datatype, '-'), {'float32', 'float64'}) - - % This is a somewhat complicated mechanism to figure out which scaling - % coefficients go with which data points in a generic way - - trlind = floor(((begsample:endsample)-1)/header.nSamples)+1; - - utrlind = unique(trlind); - - for i = 1:length(utrlind) - dat(:, trlind == utrlind(i)) = dat(:, trlind == utrlind(i)).* ... - repmat(squeeze(scale(chanindx,:,utrlind(i))), 1, sum(trlind == utrlind(i))); - end - -end diff --git a/external/fileio/private/read_spmeeg_event.m b/external/fileio/private/read_spmeeg_event.m deleted file mode 100644 index 2ceec76..0000000 --- a/external/fileio/private/read_spmeeg_event.m +++ /dev/null @@ -1,81 +0,0 @@ -function event = read_spmeeg_event(filename, varargin) - -% read_spmeeg_event() - import evtns from SPM5 and SPM8 meeg datasets -% -% Usage: -% >> header = read_spmeeg_event(filename); -% -% Inputs: -% filename - [string] file name -% -% Outputs: -% event - FILEIO toolbox event structure -% _______________________________________________________________________ -% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% Vladimir Litvak - -if nargin < 1 - help read_spmeeg_event; - return; -end; - -header = keyval('header', varargin); - -if isempty(header) - header = read_spmeeg_header(filename); -end; - -D = header.orig; - -event = []; - -if isfield(D, 'Radc') % SPM5 - for i = 1:D.Nevents - if isfield(D, 'events') && isfield(D.events, 'code') && length(D.events.code) == D.Nevents - value = D.events.code(i); - else - value = []; - end - - event = [event struct('type', 'trial', 'sample', (i-1)*header.nSamples + 1,... - 'value', value, 'offset', -header.nSamplesPre, 'duration', header.nSamples)]; - end - - if D.Nevents == 1 && isfield(D, 'events') && isfield(D.events, 'time') - event = [event struct('type', 'spm5_event', 'sample', num2cell(D.events.time),... - 'value', num2cell(D.events.code), 'offset', -header.nSamplesPre, 'duration', header.nSamples)]; - end - -elseif all(isfield(D, {'type', 'Nsamples', 'Fsample', 'timeOnset'})) % SPM8 - - for i = 1:numel(D.trials) - event = [event struct('type', 'trial', 'sample', (i-1)*header.nSamples + 1,... - 'value', D.trials(i).label, 'offset', -header.nSamplesPre, 'duration', header.nSamples)]; - - if isfield(D.trials, 'events') - cevent = D.trials(i).events; - if ~isempty(cevent) - for j = 1:numel(cevent) - if ~strcmp(cevent(j).type, 'trial') - csample = (cevent(j).time - D.trials(i).onset)*header.Fs + 1; - if csample > 0 && csample <= header.nSamples - tmp = rmfield(cevent(j), 'time'); - if strcmp(D.type, 'continuous') && (D.timeOnset ~= 0) - tmp.sample = (cevent(j).time - D.timeOnset)* header.Fs + 1; - else - tmp.sample = cevent(j).time*header.Fs; - end - tmp.sample = round(tmp.sample); - tmp.offset = 0; - event = [event tmp]; - end - end - end - end - end - end - -else - error('Cannot recognize an SPM EEG header format'); -end - diff --git a/external/fileio/private/read_spmeeg_header.m b/external/fileio/private/read_spmeeg_header.m deleted file mode 100644 index 30d9ba9..0000000 --- a/external/fileio/private/read_spmeeg_header.m +++ /dev/null @@ -1,66 +0,0 @@ -function header = read_spmeeg_header(filename) - -% read_spmeeg_header() - import SPM5 and SPM8 meeg datasets -% -% Usage: -% >> header = read_spmeeg_header(filename); -% -% Inputs: -% filename - [string] file name -% -% Outputs: -% header - FILEIO toolbox type structure -% _______________________________________________________________________ -% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% Vladimir Litvak - -if nargin < 1 - help read_spmeeg_header; - return; -end; - -try - D = load(filename, 'D'); - D = D.D; -catch - error('File not found or wrong format.'); -end - -header = []; - -if isfield(D, 'Radc') % SPM5 - header.Fs = D.Radc; - header.nChans = D.Nchannels; - header.nSamples = D.Nsamples; - - if isfield(D, 'events') && isfield(D.events, 'start') - header.nSamplesPre = D.events.start; - else - header.nSamplesPre = 0; - end - - header.nTrials = D.Nevents; - header.label = D.channels.name'; - -elseif all(isfield(D, {'type', 'Nsamples', 'Fsample', 'timeOnset'})) % SPM8 - - header.Fs = D.Fsample; - header.nChans = numel(D.channels); - header.nSamples = D.Nsamples; - header.nSamplesPre = -D.timeOnset*D.Fsample; - header.nTrials = numel(D.trials); - header.label = {D.channels.label}'; - - if isfield(D.sensors, 'eeg') && ~isempty(D.sensors.eeg) - header.elec = D.sensors.eeg; - end - - if isfield(D.sensors, 'meg') && ~isempty(D.sensors.meg) - header.grad = D.sensors.meg; - end - -else - error('Cannot recognize an SPM EEG header format'); -end - -header.orig = D; diff --git a/external/fileio/private/read_trigger.m b/external/fileio/private/read_trigger.m deleted file mode 100644 index b5dee93..0000000 --- a/external/fileio/private/read_trigger.m +++ /dev/null @@ -1,171 +0,0 @@ -function [event] = read_trigger(filename, varargin) - -% READ_TRIGGER extracts the events from a continuous trigger channel -% This function is a helper function to read_event and can be used for all -% dataformats that have one or multiple continuously sampled TTL channels -% in the data. -% -% The optional trigshift (default is 0) causes the value of the -% trigger to be obtained from a sample that is shifted N samples away -% from the actual flank. -% -% This is a helper function for READ_EVENT -% -% TODO -% - merge read_ctf_trigger into this function (requires trigshift and bitmasking option) -% - merge biosemi code into this function (requires bitmasking option) - -% Copyright (C) 2008, Robert Oostenveld -% -% $Log: read_trigger.m,v $ -% Revision 1.7 2009/05/14 18:53:22 roboos -% bail out immediately if the data is empty -% -% Revision 1.6 2009/02/24 14:25:52 jansch -% added option fix4dglasgow to take the synchronization trigger with value 8192 -% out of the trigger-data, prior to flank detection -% -% Revision 1.5 2009/02/09 13:32:36 roboos -% only whitespace -% -% Revision 1.4 2009/01/23 16:18:15 roboos -% changed indentation -% -% Revision 1.3 2009/01/23 12:22:15 vlalit -% A fix to avoid an 'almost infinite' loop in case of noisy event channels. -% -% Revision 1.2 2009/01/23 10:32:55 vlalit -% New reader for Neuromag fif format using the MNE toolbox (http://www.nmr.mgh.harvard.edu/martinos/userInfo/data/sofMNE.php) implemented by Laurence Hunt. -% -% Revision 1.1 2009/01/14 09:12:16 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.6 2008/05/20 15:12:50 vlalit -% Added trigpadding option to handle channels with baseline different from zero -% -% Revision 1.5 2008/05/15 18:38:53 vlalit -% Fixed the problems with discontinuous files and baseline different than zero -% -% Revision 1.4 2008/05/13 16:48:24 roboos -% added option trigshift (default = 0) for cases where the trigger value should be assigned from a sample not directly after/before the upgoing/downgoing flank -% -% Revision 1.3 2008/05/08 18:32:45 vlalit -% Fixed a bug -% -% Revision 1.2 2008/04/29 14:54:39 roboos -% explicit specification of begsample and endsample, otherwise event.sample remains empty -% -% Revision 1.1 2008/04/29 13:53:50 roboos -% new implementation, works for ctf, bti and neuromag -% - -event = []; - -% get the optional input arguments -hdr = keyval('header', varargin); -dataformat = keyval('dataformat', varargin); -begsample = keyval('begsample', varargin); -endsample = keyval('endsample', varargin); -chanindx = keyval('chanindx', varargin); -detectflank = keyval('detectflank', varargin); -denoise = keyval('denoise', varargin); if isempty(denoise), denoise = 1; end -trigshift = keyval('trigshift', varargin); if isempty(trigshift), trigshift = 0; end -trigpadding = keyval('trigpadding', varargin); if isempty(trigpadding), trigpadding = 1; end -fixctf = keyval('fixctf', varargin); if isempty(fixctf), fixctf = 0; end -fixneuromag = keyval('fixneuromag', varargin); if isempty(fixneuromag), fixneuromag = 0; end -fix4dglasgow= keyval('fix4dglasgow', varargin); if isempty(fix4dglasgow), fix4dglasgow = 0; end - -if isempty(begsample) - begsample = 1; -end - -if isempty(endsample) - endsample = hdr.nSamples*hdr.nTrials; -end - -% read the trigger channel as raw data, can safely assume that it is continuous -dat = read_data(filename, 'header', hdr, 'dataformat', dataformat, 'begsample', begsample, 'endsample', endsample, 'chanindx', chanindx, 'checkboundary', 0); - -if isempty(dat) - % there are no triggers to detect - return -end - -% Detect situations where the channel value changes almost at every time -% step which are likely to be noise -if denoise - for i=1:length(chanindx) - if (sum(diff(find(diff(dat(i,:))~=0)) == 1)/length(dat(i,:))) > 0.8 - warning(['trigger channel ' hdr.label{chanindx(i)} ' looks like noise and will be ignored']); - dat(i,:) = 0; - end - end -end - -if fixctf - % correct for reading the data as signed 32-bit integer, whereas it should be interpreted as an unsigned int - dat(dat<0) = dat(dat<0) + 2^32; -end - -if fixneuromag - % according to Joachim Gross, real events always have triggers > 5 - % this is probably to avoid the noisefloor - dat(dat<5) = 0; -end - -if fix4dglasgow - % synchronization pulses have a value of 8192 and are set to 0 - dat = dat - bitand(dat, 8192); - %% triggers containing the first bit assume a value of 4096 when sent by presentation - %% this does not seem to hold for matlab; check this - %dat = dat - bitand(dat, 4096)*4095/4096; -end - -for i=1:length(chanindx) - % process each trigger channel independently - channel = hdr.label{chanindx(i)}; - trig = dat(i,:); - - if trigpadding - pad = trig(1); - else - pad = 0; - end - - switch detectflank - case 'up' - % convert the trigger into an event with a value at a specific sample - for j=find(diff([pad trig(:)'])>0) - event(end+1).type = channel; - event(end ).sample = j + begsample - 1; % assign the sample at which the trigger has gone down - event(end ).value = trig(j+trigshift); % assign the trigger value just _after_ going up - end - case 'down' - % convert the trigger into an event with a value at a specific sample - for j=find(diff([pad trig(:)'])<0) - event(end+1).type = channel; - event(end ).sample = j + begsample - 1; % assign the sample at which the trigger has gone down - event(end ).value = trig(j-1-trigshift); % assign the trigger value just _before_ going down - end - case 'both' - % convert the trigger into an event with a value at a specific sample - for j=find(diff([pad trig(:)'])>0) - event(end+1).type = [channel '_up']; % distinguish between up and down flank - event(end ).sample = j + begsample - 1; % assign the sample at which the trigger has gone down - event(end ).value = trig(j+trigshift); % assign the trigger value just _after_ going up - end - % convert the trigger into an event with a value at a specific sample - for j=find(diff([pad trig(:)'])<0) - event(end+1).type = [channel '_down']; % distinguish between up and down flank - event(end ).sample = j + begsample - 1; % assign the sample at which the trigger has gone down - event(end ).value = trig(j-1-trigshift); % assign the trigger value just _before_ going down - end - otherwise - error('incorrect specification of ''detectflank'''); - end -end diff --git a/external/fileio/private/read_vol.m b/external/fileio/private/read_vol.m deleted file mode 100644 index 1e71eea..0000000 --- a/external/fileio/private/read_vol.m +++ /dev/null @@ -1,85 +0,0 @@ -function [vol] = read_vol(filename, varargin) - -% READ_VOL reads a volume conduction model from various manufacturer -% specific files. Currently supported are ASA, CTF, Neuromag, MBFYS -% and Matlab. -% -% Use as -% vol = read_vol(filename, ...) -% -% Additional options should be specified in key-value pairs and can be -% 'fileformat' string -% -% The volume conduction model is represented as a structure, and its -% contents depend on the type of model. -% -% See also TRANSFORM_VOL, PREPARE_VOL_SENS, COMPUTE_LEADFIELD - -% Copyright (C) 2008, Robert Oostenveld -% -% $Log: read_vol.m,v $ -% Revision 1.4 2008/04/14 20:51:19 roboos -% fixed dependency for dipoli/ama -% added convert_units -% -% Revision 1.3 2008/03/06 09:27:54 roboos -% updated documentation -% -% Revision 1.2 2008/01/31 20:15:24 roboos -% added optional fileformat argument -% -% Revision 1.1 2008/01/28 20:10:11 roboos -% new functions based on existing fieldtrip code -% - -% test whether the file exists -if ~exist(filename) - error(sprintf('file ''%s'' does not exist', filename)); -end - -% get the options -fileformat = keyval('fileformat', varargin); - -% determine the filetype -if isempty(fileformat) - fileformat = filetype(filename); -end - -switch fileformat - case 'matlab' - matfile = filename; % this solves a problem with the matlab compiler v3 - warning('off', 'MATLAB:load:variableNotFound'); - tmp = load(matfile, 'vol'); - warning('on', 'MATLAB:load:variableNotFound'); - vol = getfield(tmp, 'vol'); - - case 'ctf_hdm' - vol = read_ctf_hdm(filename); - - case 'asa_vol' - vol = read_asa_vol(filename); - vol.type = 'asa'; - - case 'mbfys_ama' - ama = loadama(filename); - vol = ama2vol(ama); - - case 'neuromag_fif' - % do not read the volume into Matlab, but use external Neuromag toolbox - vol.type = 'neuromag'; - vol.filename = filename; - vol.chansel = []; % this is defined later based on the channels present in the data - % initialize the Neuromag toolbox, this requires a gradfile and hdmfile - fprintf('using Neuromag volume conductor from %s\n', filename); - fprintf('using Neuromag gradiometer definition from %s\n', cfg.gradfile); - megmodel('head', cfg.gradfile, filename); - % read the triangulated boundary from the neuromag BEM model - [vol.bnd.pnt, vol.bnd.tri, vol.bnd.nrm] = loadtri(vol.filename); - vol.bnd.pnt = vol.bnd.pnt*100; % convert to cm - - otherwise - error('unknown fileformat for volume conductor model'); -end - -% this will add the units to the volume conductor model -vol = convert_units(vol); diff --git a/external/fileio/private/read_yokogawa_data.m b/external/fileio/private/read_yokogawa_data.m deleted file mode 100644 index fc69f98..0000000 --- a/external/fileio/private/read_yokogawa_data.m +++ /dev/null @@ -1,302 +0,0 @@ -function [dat] = read_yokogawa_data(filename, hdr, begsample, endsample, chanindx) - -% READ_YOKAGAWA_DATA reads continuous, epoched or averaged MEG data -% that has been generated by the Yokogawa MEG system and software -% and allows that data to be used in combination with FieldTrip. -% -% Use as -% [dat] = read_yokogawa_data(filename, hdr, begsample, endsample, chanindx) -% -% This is a wrapper function around the functions -% GetMeg160ContinuousRawDataM -% GetMeg160EvokedAverageDataM -% GetMeg160EvokedRawDataM -% -% See also READ_YOKOGAWA_HEADER, READ_YOKOGAWA_EVENT - -% Copyright (C) 2005, Robert Oostenveld -% -% $Log: read_yokogawa_data.m,v $ -% Revision 1.1 2009/01/14 09:12:16 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.6 2008/04/21 14:19:38 roboos -% move teh channel selection to _after_ the calibration, otherwise calibration fails (thanks to Vladimir) -% -% Revision 1.5 2008/04/10 09:59:39 roboos -% define sample_length for Raw data -% -% Revision 1.4 2006/11/30 10:03:00 roboos -% fixed small bug -> extra ")" -% -% Revision 1.3 2005/11/16 13:48:29 roboos -% added suggestions by Masahiro, mainly calibration to physical units -% -% Revision 1.2 2005/09/08 16:54:36 roboos -% added some ;s to the end of lines -% fixed a bug in removing the first sample for raw data -% -% Revision 1.1 2005/09/06 08:54:01 roboos -% new implementations for the Yokogawa 160 channel MEG syste, -% - -% hdr = read_yokogawa_header(filename); -hdr = hdr.orig; % use the original Yokogawa header, not the FieldTrip header - -% default is to select all channels -if nargin<5 - chanindx = 1:hdr.channel_count; -end - -handles = definehandles; -fid = fopen(filename, 'rb', 'ieee-le'); - -switch hdr.acq_type - case handles.AcqTypeEvokedAve - % Data is returned by double. - start_sample = begsample - 1; % samples start at 0 - sample_length = endsample - begsample + 1; - epoch_count = 1; - start_epoch = 0; - dat = double(GetMeg160EvokedAverageDataM( fid, start_sample, sample_length )); - % the first extra sample is the channel number - channum = dat(:,1); - dat = dat(:,2:end); - - case handles.AcqTypeContinuousRaw - % Data is returned by int16. - start_sample = begsample - 1; % samples start at 0 - sample_length = endsample - begsample + 1; - epoch_count = 1; - start_epoch = 0; - dat = double(GetMeg160ContinuousRawDataM( fid, start_sample, sample_length )); - % the first extra sample is the channel number - channum = dat(:,1); - dat = dat(:,2:end); - - case handles.AcqTypeEvokedRaw - % Data is returned by int16. - begtrial = ceil(begsample/hdr.sample_count); - endtrial = ceil(endsample/hdr.sample_count); - if begtrial<1 - error('cannot read before the begin of the file'); - elseif endtrial>hdr.actual_epoch_count - error('cannot read beyond the end of the file'); - end - epoch_count = endtrial-begtrial+1; - start_epoch = begtrial-1; - % read all the neccessary trials that contain the desired samples - dat = double(GetMeg160EvokedRawDataM( fid, start_epoch, epoch_count )); - % the first extra sample is the channel number - channum = dat(:,1); - dat = dat(:,2:end); - if size(dat,2)~=epoch_count*hdr.sample_count - error('could not read all epochs'); - end - rawbegsample = begsample - (begtrial-1)*hdr.sample_count; - rawendsample = endsample - (begtrial-1)*hdr.sample_count; - sample_length = rawendsample - rawbegsample + 1; - % select the desired samples from the complete trials - dat = dat(:,rawbegsample:rawendsample); - - otherwise - error('unknown data type'); -end - -fclose(fid); - -if size(dat,1)~=hdr.channel_count - error('could not read all channels'); -elseif size(dat,2)~=(endsample-begsample+1) - error('could not read all samples'); -end - -% Count of AxialGradioMeter -ch_type = hdr.channel_info(:,2); -index = find(ch_type==[handles.AxialGradioMeter]); -axialgradiometer_index_tmp = index; -axialgradiometer_ch_count = length(index); - -% Count of PlannerGradioMeter -ch_type = hdr.channel_info(:,2); -index = find(ch_type==[handles.PlannerGradioMeter]); -plannergradiometer_index_tmp = index; -plannergradiometer_ch_count = length(index); - -% Count of EegChannel -ch_type = hdr.channel_info(:,2); -index = find(ch_type==[handles.EegChannel]); -eegchannel_index_tmp = index; -eegchannel_ch_count = length(index); - -% Count of NullChannel -ch_type = hdr.channel_info(:,2); -index = find(ch_type==[handles.NullChannel]); -nullchannel_index_tmp = index; -nullchannel_ch_count = length(index); - -%%% Pulling out AxialGradioMeter and value conversion to physical units. -if ~isempty(axialgradiometer_index_tmp) - % Acquisition of channel information - axialgradiometer_index = axialgradiometer_index_tmp; - ch_info = hdr.channel_info; - axialgradiometer_ch_info = ch_info(axialgradiometer_index, :); - - % Value conversion - % B = ( ADValue * VoltRange / ADRange - Offset ) * Sensitivity / FLLGain - calib = hdr.calib_info; - amp_gain = hdr.amp_gain(1); - tmp_ch_no = channum(axialgradiometer_index, 1); - tmp_data = dat(axialgradiometer_index, 1:sample_length); - tmp_offset = calib(axialgradiometer_index, 3) * ones(1,sample_length); - ad_range = 5/2048; - tmp_data = ( tmp_data * ad_range - tmp_offset ); - clear tmp_offset; - tmp_gain = calib(axialgradiometer_index, 2) * ones(1,sample_length); - tmp_data = tmp_data .* tmp_gain / amp_gain; - dat(axialgradiometer_index, 1:sample_length) = tmp_data; - clear tmp_gain; - - % Deletion of Inf row - index = find(axialgradiometer_ch_info(1,:) == Inf); - axialgradiometer_ch_info(:,index) = []; - - % Deletion of channel_type row - axialgradiometer_ch_info(:,2) = []; - - % Outputs to the global variable - handles.sqd.axialgradiometer_ch_info = axialgradiometer_ch_info; - handles.sqd.axialgradiometer_ch_no = tmp_ch_no; - handles.sqd.axialgradiometer_data = [ tmp_ch_no tmp_data]; - clear tmp_data; -end - -%%% Pulling out PlannerGradioMeter and value conversion to physical units. -if ~isempty(plannergradiometer_index_tmp) - % Acquisition of channel information - plannergradiometer_index = plannergradiometer_index_tmp; - ch_info = hdr.channel_info; - plannergradiometer_ch_info = ch_info(plannergradiometer_index, :); - - % Value conversion - % B = ( ADValue * VoltRange / ADRange - Offset ) * Sensitivity / FLLGain - calib = hdr.calib_info; - amp_gain = hdr.amp_gain(1); - tmp_ch_no = channum(plannergradiometer_index, 1); - tmp_data = dat(plannergradiometer_index, 1:sample_length); - tmp_offset = calib(plannergradiometer_index, 3) * ones(1,sample_length); - ad_range = 5/2048; - tmp_data = ( tmp_data * ad_range - tmp_offset ); - clear tmp_offset; - tmp_gain = calib(plannergradiometer_index, 2) * ones(1,sample_length); - tmp_data = tmp_data .* tmp_gain / amp_gain; - dat(plannergradiometer_index, 1:sample_length) = tmp_data; - clear tmp_gain; - - % Deletion of Inf row - index = find(plannergradiometer_ch_info(1,:) == Inf); - plannergradiometer_ch_info(:,index) = []; - - % Deletion of channel_type row - plannergradiometer_ch_info(:,2) = []; - - % Outputs to the global variable - handles.sqd.plannergradiometer_ch_info = plannergradiometer_ch_info; - handles.sqd.plannergradiometer_ch_no = tmp_ch_no; - handles.sqd.plannergradiometer_data = [ tmp_ch_no tmp_data]; - clear tmp_data; -end - -%%% Pulling out EegChannel Channel and value conversion to Volt units. -if ~isempty(eegchannel_index_tmp) - % Acquisition of channel information - eegchannel_index = eegchannel_index_tmp; - - % Value conversion - % B = ADValue * VoltRange / ADRange - tmp_ch_no = channum(eegchannel_index, 1); - tmp_data = dat(eegchannel_index, 1:sample_length); - ad_range = 5/2048; - tmp_data = tmp_data * ad_range; - dat(eegchannel_index, 1:sample_length) = tmp_data; - - % Outputs to the global variable - handles.sqd.eegchannel_ch_no = tmp_ch_no; - handles.sqd.eegchannel_data = [ tmp_ch_no tmp_data]; - clear tmp_data; -end - -%%% Pulling out Null Channel and value conversion to Volt units. -if ~isempty(nullchannel_index_tmp) - % Acquisition of channel information - nullchannel_index = nullchannel_index_tmp; - - % Value conversion - % B = ADValue * VoltRange / ADRange - tmp_ch_no = channum(nullchannel_index, 1); - tmp_data = dat(nullchannel_index, 1:sample_length); - ad_range = 5/2048; - tmp_data = tmp_data * ad_range; - dat(nullchannel_index, 1:sample_length) = tmp_data; - - % Outputs to the global variable - handles.sqd.nullchannel_ch_no = tmp_ch_no; - handles.sqd.nullchannel_data = [ tmp_ch_no tmp_data]; - clear tmp_data; -end - -% select only the desired channels -dat = dat(chanindx,:); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% this defines some usefull constants -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function handles = definehandles -handles.output = []; -handles.sqd_load_flag = false; -handles.mri_load_flag = false; -handles.NullChannel = 0; -handles.MagnetoMeter = 1; -handles.AxialGradioMeter = 2; -handles.PlannerGradioMeter = 3; -handles.RefferenceChannelMark = hex2dec('0100'); -handles.RefferenceMagnetoMeter = bitor( handles.RefferenceChannelMark, handles.MagnetoMeter ); -handles.RefferenceAxialGradioMeter = bitor( handles.RefferenceChannelMark, handles.AxialGradioMeter ); -handles.RefferencePlannerGradioMeter = bitor( handles.RefferenceChannelMark, handles.PlannerGradioMeter ); -handles.TriggerChannel = -1; -handles.EegChannel = -2; -handles.EcgChannel = -3; -handles.EtcChannel = -4; -handles.NonMegChannelNameLength = 32; -handles.DefaultMagnetometerSize = (4.0/1000.0); % Square of 4.0mm in length -handles.DefaultAxialGradioMeterSize = (15.5/1000.0); % Circle of 15.5mm in diameter -handles.DefaultPlannerGradioMeterSize = (12.0/1000.0); % Square of 12.0mm in length -handles.AcqTypeContinuousRaw = 1; -handles.AcqTypeEvokedAve = 2; -handles.AcqTypeEvokedRaw = 3; -handles.sqd = []; -handles.sqd.selected_start = []; -handles.sqd.selected_end = []; -handles.sqd.axialgradiometer_ch_no = []; -handles.sqd.axialgradiometer_ch_info = []; -handles.sqd.axialgradiometer_data = []; -handles.sqd.plannergradiometer_ch_no = []; -handles.sqd.plannergradiometer_ch_info = []; -handles.sqd.plannergradiometer_data = []; -handles.sqd.eegchannel_ch_no = []; -handles.sqd.eegchannel_data = []; -handles.sqd.nullchannel_ch_no = []; -handles.sqd.nullchannel_data = []; -handles.sqd.selected_time = []; -handles.sqd.sample_rate = []; -handles.sqd.sample_count = []; -handles.sqd.pretrigger_length = []; -handles.sqd.matching_info = []; -handles.sqd.source_info = []; -handles.sqd.mri_info = []; -handles.mri = []; diff --git a/external/fileio/private/read_yokogawa_event.m b/external/fileio/private/read_yokogawa_event.m deleted file mode 100644 index 7142157..0000000 --- a/external/fileio/private/read_yokogawa_event.m +++ /dev/null @@ -1,104 +0,0 @@ -function [event] = read_yokogawa_event(filename); - -% READ_YOKOGAWA_EVENT reads event information from continuous, -% epoched or averaged MEG data that has been generated by the Yokogawa -% MEG system and software and allows those events to be used in -% combination with FieldTrip. -% -% Use as -% [event] = read_yokogawa_event(filename) -% -% See also READ_YOKOGAWA_HEADER, READ_YOKOGAWA_DATA - -% Copyright (C) 2005, Robert Oostenveld -% -% $Log: read_yokogawa_event.m,v $ -% Revision 1.3 2005/11/16 13:48:59 roboos -% updated the handles subfunction, no functional change -% -% Revision 1.2 2005/09/08 09:27:13 roboos -% added an 'average' event for an averaged ERF dataset -% -% Revision 1.1 2005/09/06 08:54:01 roboos -% new implementations for the Yokogawa 160 channel MEG syste, -% - -event = []; -handles = definehandles; - -% use the standard FieldTrip header for trial events -hdr = read_yokogawa_header(filename); - -if hdr.orig.acq_type==handles.AcqTypeEvokedRaw - % make an event for each trial as defined in the header - for i=1:hdr.nTrials - event(end+1).type = 'trial'; - event(end ).sample = (i-1)*hdr.nSamples + 1; - event(end ).offset = -hdr.nSamplesPre; - event(end ).duration = hdr.nSamples; - end - -elseif hdr.orig.acq_type==handles.AcqTypeEvokedAve - % make an event for the average - event(1).type = 'average'; - event(1).sample = 1; - event(1).offset = -hdr.nSamplesPre; - event(1).duration = hdr.nSamples; -end - -% continue with the original Yokogawa header, not the FieldTrip header -hdr = hdr.orig; -% these might contain usefull information -sel_etc = find(hdr.channel_info(:,2)==handles.EtcChannel); -sel_trg = find(hdr.channel_info(:,2)==handles.TriggerChannel); - -% FIXME, do something with the triggers... - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% this defines some usefull constants -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function handles = definehandles; -handles.output = []; -handles.sqd_load_flag = false; -handles.mri_load_flag = false; -handles.NullChannel = 0; -handles.MagnetoMeter = 1; -handles.AxialGradioMeter = 2; -handles.PlannerGradioMeter = 3; -handles.RefferenceChannelMark = hex2dec('0100'); -handles.RefferenceMagnetoMeter = bitor( handles.RefferenceChannelMark, handles.MagnetoMeter ); -handles.RefferenceAxialGradioMeter = bitor( handles.RefferenceChannelMark, handles.AxialGradioMeter ); -handles.RefferencePlannerGradioMeter = bitor( handles.RefferenceChannelMark, handles.PlannerGradioMeter ); -handles.TriggerChannel = -1; -handles.EegChannel = -2; -handles.EcgChannel = -3; -handles.EtcChannel = -4; -handles.NonMegChannelNameLength = 32; -handles.DefaultMagnetometerSize = (4.0/1000.0); % Square of 4.0mm in length -handles.DefaultAxialGradioMeterSize = (15.5/1000.0); % Circle of 15.5mm in diameter -handles.DefaultPlannerGradioMeterSize = (12.0/1000.0); % Square of 12.0mm in length -handles.AcqTypeContinuousRaw = 1; -handles.AcqTypeEvokedAve = 2; -handles.AcqTypeEvokedRaw = 3; -handles.sqd = []; -handles.sqd.selected_start = []; -handles.sqd.selected_end = []; -handles.sqd.axialgradiometer_ch_no = []; -handles.sqd.axialgradiometer_ch_info = []; -handles.sqd.axialgradiometer_data = []; -handles.sqd.plannergradiometer_ch_no = []; -handles.sqd.plannergradiometer_ch_info = []; -handles.sqd.plannergradiometer_data = []; -handles.sqd.eegchannel_ch_no = []; -handles.sqd.eegchannel_data = []; -handles.sqd.nullchannel_ch_no = []; -handles.sqd.nullchannel_data = []; -handles.sqd.selected_time = []; -handles.sqd.sample_rate = []; -handles.sqd.sample_count = []; -handles.sqd.pretrigger_length = []; -handles.sqd.matching_info = []; -handles.sqd.source_info = []; -handles.sqd.mri_info = []; -handles.mri = []; diff --git a/external/fileio/private/read_yokogawa_header.m b/external/fileio/private/read_yokogawa_header.m deleted file mode 100644 index b94d8a4..0000000 --- a/external/fileio/private/read_yokogawa_header.m +++ /dev/null @@ -1,191 +0,0 @@ -function hdr = read_yokogawa_header(filename); - - -% READ_YOKOGAWA_HEADER reads the header information from continuous, -% epoched or averaged MEG data that has been generated by the Yokogawa -% MEG system and software and allows that data to be used in combination -% with FieldTrip. -% -% Use as -% [hdr] = read_yokogawa_header(filename) -% -% This is a wrapper function around the functions -% GetMeg160SystemInfoM -% GetMeg160ChannelCountM -% GetMeg160ChannelInfoM -% GetMeg160CalibInfoM -% GetMeg160AmpGainM -% GetMeg160DataAcqTypeM -% GetMeg160ContinuousAcqCondM -% GetMeg160EvokedAcqCondM -% -% See also READ_YOKOGAWA_DATA, READ_YOKOGAWA_EVENT - -% this function also calls -% GetMeg160MriInfoM -% GetMeg160MatchingInfoM -% GetMeg160SourceInfoM -% but I don't know whether to use the information provided by those - -% Copyright (C) 2005, Robert Oostenveld -% -% $Log: read_yokogawa_header.m,v $ -% Revision 1.1 2009/01/14 09:12:16 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.2 2005/09/29 00:48:57 roboos -% fixed hdr.nSamplesPre, corrected error in help -% -% Revision 1.1 2005/09/06 08:54:01 roboos -% new implementations for the Yokogawa 160 channel MEG syste, -% - -% FIXED -% txt -> m -% fopen iee-le - -handles = definehandles; -fid = fopen(filename, 'rb', 'ieee-le'); - -% these are always present -[id ver rev sys_name] = GetMeg160SystemInfoM(fid); -channel_count = GetMeg160ChannelCountM(fid); -channel_info = GetMeg160ChannelInfoM(fid); -calib_info = GetMeg160CalibInfoM(fid); -amp_gain = GetMeg160AmpGainM(fid); -acq_type = GetMeg160DataAcqTypeM(fid); - -% these depend on the data type -sample_rate = []; -sample_count = []; -pretrigger_length = []; -averaged_count = []; -actual_epoch_count = []; - -switch acq_type - case handles.AcqTypeContinuousRaw - [sample_rate, sample_count] = GetMeg160ContinuousAcqCondM(fid); - if isempty(sample_rate) | isempty(sample_count) - fclose(fid); - return; - end - pretrigger_length = 0; - averaged_count = 1; - - case handles.AcqTypeEvokedAve - [sample_rate, sample_count, pretrigger_length, averaged_count] = GetMeg160EvokedAcqCondM( fid ); - if isempty(sample_rate) | isempty(sample_count) | isempty(pretrigger_length) | isempty(averaged_count) - fclose(fid); - return; - end - - case handles.AcqTypeEvokedRaw - [sample_rate, sample_count, pretrigger_length, actual_epoch_count] = GetMeg160EvokedAcqCondM( fid ); - if isempty(sample_rate) | isempty(sample_count) | isempty(pretrigger_length) | isempty(actual_epoch_count) - fclose(fid); - return; - end - - otherwise - error('unknown data type'); -end - -% these are always present -mri_info = GetMeg160MriInfoM(fid); -matching_info = GetMeg160MatchingInfoM(fid); -source_info = GetMeg160SourceInfoM(fid); - -fclose(fid); - -% put all local variables into a structure, this is a bit unusual matlab programming style -tmp = whos; -orig = []; -for i=1:length(tmp) - if isempty(strmatch(tmp(i).name, {'tmp', 'fid', 'ans', 'handles'})) - orig = setfield(orig, tmp(i).name, eval(tmp(i).name)); - end -end - -% convert the original header information into something that FieldTrip understands -hdr = []; -hdr.orig = orig; % also store the original full header information -hdr.Fs = orig.sample_rate; % sampling frequency -hdr.nChans = orig.channel_count; % number of channels -hdr.nSamples = []; % number of samples per trial -hdr.nSamplesPre = []; % number of pre-trigger samples in each trial -hdr.nTrials = []; % number of trials - -switch orig.acq_type - case handles.AcqTypeEvokedAve - hdr.nSamples = orig.sample_count; - hdr.nSamplesPre = orig.pretrigger_length; - hdr.nTrials = 1; % only the average, which can be considered as a single trial - case handles.AcqTypeContinuousRaw - hdr.nSamples = orig.sample_count; - hdr.nSamplesPre = 0; % there is no fixed relation between triggers and data - hdr.nTrials = 1; % the continuous data can be considered as a single very long trial - case handles.AcqTypeEvokedRaw - hdr.nSamples = orig.sample_count; - hdr.nSamplesPre = orig.pretrigger_length; - hdr.nTrials = orig.actual_epoch_count; - otherwise - error('unknown acquisition type'); -end - -% construct a cell-array with labels of each channel -for i=1:hdr.nChans - hdr.label{i} = sprintf('%03d', i); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% this defines some usefull constants -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function handles = definehandles; -handles.output = []; -handles.sqd_load_flag = false; -handles.mri_load_flag = false; -handles.NullChannel = 0; -handles.MagnetoMeter = 1; -handles.AxialGradioMeter = 2; -handles.PlannerGradioMeter = 3; -handles.RefferenceChannelMark = hex2dec('0100'); -handles.RefferenceMagnetoMeter = bitor( handles.RefferenceChannelMark, handles.MagnetoMeter ); -handles.RefferenceAxialGradioMeter = bitor( handles.RefferenceChannelMark, handles.AxialGradioMeter ); -handles.RefferencePlannerGradioMeter = bitor( handles.RefferenceChannelMark, handles.PlannerGradioMeter ); -handles.TriggerChannel = -1; -handles.EegChannel = -2; -handles.EcgChannel = -3; -handles.EtcChannel = -4; -handles.NonMegChannelNameLength = 32; -handles.DefaultMagnetometerSize = (4.0/1000.0); % Square of 4.0mm in length -handles.DefaultAxialGradioMeterSize = (15.5/1000.0); % Circle of 15.5mm in diameter -handles.DefaultPlannerGradioMeterSize = (12.0/1000.0); % Square of 12.0mm in length -handles.AcqTypeContinuousRaw = 1; -handles.AcqTypeEvokedAve = 2; -handles.AcqTypeEvokedRaw = 3; -handles.sqd = []; -handles.sqd.selected_start = []; -handles.sqd.selected_end = []; -handles.sqd.axialgradiometer_ch_no = []; -handles.sqd.axialgradiometer_ch_info = []; -handles.sqd.axialgradiometer_data = []; -handles.sqd.plannergradiometer_ch_no = []; -handles.sqd.plannergradiometer_ch_info = []; -handles.sqd.plannergradiometer_data = []; -handles.sqd.eegchannel_ch_no = []; -handles.sqd.eegchannel_data = []; -handles.sqd.nullchannel_ch_no = []; -handles.sqd.nullchannel_data = []; -handles.sqd.selected_time = []; -handles.sqd.sample_rate = []; -handles.sqd.sample_count = []; -handles.sqd.pretrigger_length = []; -handles.sqd.matching_info = []; -handles.sqd.source_info = []; -handles.sqd.mri_info = []; -handles.mri = []; diff --git a/external/fileio/private/readbdf.m b/external/fileio/private/readbdf.m deleted file mode 100644 index 1e75bcf..0000000 --- a/external/fileio/private/readbdf.m +++ /dev/null @@ -1,96 +0,0 @@ -% readbdf() - Loads selected Records of an EDF or BDF File (European Data Format -% for Biosignals) into MATLAB -% Usage: -% >> [DAT,signal] = readedf(EDF_Struct,Records,Mode); -% Notes: -% Records - List of Records for Loading -% Mode - 0 Default -% 1 No AutoCalib -% 2 Concatenated (channels with lower sampling rate -% if more than 1 record is loaded) -% Output: -% DAT - EDF data structure -% signal - output signal -% -% Author: Alois Schloegl, 03.02.1998, updated T.S. Lorig Sept 6, 2002 for BDF read -% -% See also: openbdf(), sdfopen(), sdfread(), eeglab() - -% Version 2.11 -% 03.02.1998 -% Copyright (c) 1997,98 by Alois Schloegl -% a.schloegl@ieee.org - -% This program is free software; you can redistribute it and/or -% modify it under the terms of the GNU General Public License -% as published by the Free Software Foundation; either version 2 -% of the License, or (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program; if not, write to the Free Software -% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% This program has been modified from the original version for .EDF files -% The modifications are to the number of bytes read on line 53 (from 2 to -% 3) and to the type of data read - line 54 (from int16 to bit24). Finally the name -% was changed from readedf to readbdf -% T.S. Lorig Sept 6, 2002 -% -% Header modified for eeglab() compatibility - Arnaud Delorme 12/02 -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -function [DAT,S]=readbdf(DAT,Records,Mode) -if nargin<3 Mode=0; end; - -EDF=DAT.Head; -RecLen=max(EDF.SPR); - -S=NaN*zeros(RecLen,EDF.NS); -DAT.Record=zeros(length(Records)*RecLen,EDF.NS); -DAT.Valid=uint8(zeros(1,length(Records)*RecLen)); -DAT.Idx=Records(:)'; - -for nrec=1:length(Records), - - NREC=(DAT.Idx(nrec)-1); - if NREC<0 fprintf(2,'Warning READEDF: invalid Record Number %i \n',NREC);end; - - fseek(EDF.FILE.FID,(EDF.HeadLen+NREC*EDF.AS.spb*3),'bof'); - [s, count]=fread(EDF.FILE.FID,EDF.AS.spb,'bit24'); - - try, - S(EDF.AS.IDX2)=s; - catch, - error('File is incomplete (try reading begining of file)'); - end; - - %%%%% Test on Over- (Under-) Flow -% V=sum([(S'==EDF.DigMax(:,ones(RecLen,1))) + (S'==EDF.DigMin(:,ones(RecLen,1)))])==0; - V=sum([(S(:,EDF.Chan_Select)'>=EDF.DigMax(EDF.Chan_Select,ones(RecLen,1))) + ... - (S(:,EDF.Chan_Select)'<=EDF.DigMin(EDF.Chan_Select,ones(RecLen,1)))])==0; - EDF.ERROR.DigMinMax_Warning(find(sum([(S'>EDF.DigMax(:,ones(RecLen,1))) + (S'0))=1; - % invalid=[invalid; find(V==0)+l*k]; - - if floor(Mode/2)==1 - for k=1:EDF.NS, - DAT.Record(nrec*EDF.SPR(k)+(1-EDF.SPR(k):0),k)=S(1:EDF.SPR(k),k); - end; - else - DAT.Record(nrec*RecLen+(1-RecLen:0),:)=S; - end; - - DAT.Valid(nrec*RecLen+(1-RecLen:0))=V; -end; -if rem(Mode,2)==0 % Autocalib - DAT.Record=[ones(RecLen*length(Records),1) DAT.Record]*EDF.Calib; -end; - -DAT.Record=DAT.Record'; -return; - diff --git a/external/fileio/private/rmsubfield.m b/external/fileio/private/rmsubfield.m deleted file mode 100644 index f0dd5fc..0000000 --- a/external/fileio/private/rmsubfield.m +++ /dev/null @@ -1,36 +0,0 @@ -function [s] = rmsubfield(s, f, v); - -% RMSUBFIELD removes the contents of the specified field from a structure -% just like the standard Matlab RMFIELD function, except that you can also -% specify nested fields using a '.' in the fieldname. The nesting can be -% arbitrary deep. -% -% Use as -% s = rmsubfield(s, 'fieldname') -% or as -% s = rmsubfield(s, 'fieldname.subfieldname') -% -% See also SETFIELD, GETSUBFIELD, ISSUBFIELD - -% Copyright (C) 2006, Robert Oostenveld -% -% $Log: rmsubfield.m,v $ -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.1 2006/11/27 15:38:45 roboos -% new implementation -% - -if ~isstr(f) - error('incorrect input argument for fieldname'); -end - -% remove the nested subfield using recursion -[t, f] = strtok(f, '.'); -if any(f=='.') - u = rmsubfield(getfield(s, t), f); - s = setfield(s, t, u); -else - s = rmfield(s, t); -end diff --git a/external/fileio/private/senslabel.m b/external/fileio/private/senslabel.m deleted file mode 100644 index 45c59a5..0000000 --- a/external/fileio/private/senslabel.m +++ /dev/null @@ -1,2018 +0,0 @@ -function label = senslabel(type) - -% SENLABEL returns a list of sensor labels given the MEEG system type -% -% Use as -% label = senslabel(type) -% -% The input type can be any of the following -% 'biosemi64' -% 'biosemi128' -% 'biosemi256' -% 'bti148' -% 'bti148_planar' -% 'bti248' -% 'bti248_planar' -% 'btiref' -% 'ctf151' -% 'ctf151_planar' -% 'ctf275' -% 'ctf275_planar' -% 'ctfheadloc' -% 'ctfref' -% 'eeg1005' -% 'eeg1010' -% 'eeg1020' -% 'egi128' -% 'egi256' -% 'egi32' -% 'egi64' -% 'ext1020' -% 'neuromag122' -% 'neuromag122alt' -% 'neuromag306' -% 'neuromag306alt' -% 'itab153' -% 'itab153_planar' -% -% See also SENSTYPE, CHANNELSELECTION - -% FIXME one channel is missing for ctf275 - -% Copyright (C) 2007-2008, Robert Oostenveld -% Copyright (C) 2008, Vladimir Litvak -% -% $Log: senslabel.m,v $ -% Revision 1.6 2009/10/16 12:27:53 roboos -% some small changes pertaining to the itab/chieti format -% -% Revision 1.4 2009/07/29 07:07:59 roboos -% use caching of input and output arguments to speed up the handling of multiple calls with the same input argument -% -% Revision 1.3 2009/06/19 16:51:50 vlalit -% Added biosemi64 system of Diane Whitmer, I don't know how generic it is. -% -% Revision 1.2 2009/05/07 13:34:09 roboos -% added ctf64 -% -% Revision 1.1 2009/01/21 10:32:38 roboos -% moved from forwinv/* and forwinv/mex/* directory to forwinv/private/* to make the CVS layout consistent with the release version -% -% Revision 1.4 2008/09/17 19:35:07 roboos -% ensure that it returns column array -% -% Revision 1.3 2008/09/10 09:12:11 roboos -% added alternative definition of channel names without a space in the label for neuromag 122 and 306 -% -% Revision 1.2 2008/09/10 08:33:36 roboos -% speeded up with factor 5 by performing an initial check on the desired type and subsequently only defining the related variables -% -% Revision 1.1 2008/09/10 07:53:27 roboos -% moved definition of channel label sets to seperate function -% - -% these are for remembering the type on subsequent calls with the same input arguments -persistent previous_argin previous_argout - -if nargin<1 - % ensure that all input arguments are defined - type = []; -end - -current_argin = {type}; -if isequal(current_argin, previous_argin) - % don't do the type detection again, but return the previous values from cache - label = previous_argout{1}; - return -end - -% prevent defining all possible labels if not needed -isbiosemi = ~isempty(regexp(type, '^biosemi', 'once')); -isbti = ~isempty(regexp(type, '^bti', 'once')); -isctf = ~isempty(regexp(type, '^ctf', 'once')); -iseeg = ~isempty(regexp(type, '^eeg', 'once')); -isext = ~isempty(regexp(type, '^ext', 'once')); -isegi = ~isempty(regexp(type, '^egi', 'once')); -isneuromag = ~isempty(regexp(type, '^neuromag', 'once')); -isitab = ~isempty(regexp(type, '^itab', 'once')); - -if isbti - btiref = { - 'MRxA' - 'MRyA' - 'MRzA' - 'MLxA' - 'MLyA' - 'MLzA' - 'MCxA' - 'MCyA' - 'MCzA' - 'MRxaA' - 'MRyaA' - 'MRzaA' - 'MLxaA' - 'MLyaA' - 'MLzaA' - 'MCxaA' - 'MCyaA' - 'MCzaA' - 'GxxA' - 'GyxA' - 'GzxA' - 'GyyA' - 'GzyA' - }; - - bti148 = cell(148,1); - for i=1:148 - bti148{i,1} = sprintf('A%d', i); - end - - bti148_planar = cell(148,1); - for i=1:148 - bti148_planar{i,1} = sprintf('A%d_dH', i); - bti148_planar{i,2} = sprintf('A%d_dV', i); - end - - bti248 = cell(248,1); - for i=1:248 - bti248{i,1} = sprintf('A%d', i); - end - - bti248_planar = cell(248,2); - for i=1:248 - bti248_planar{i,1} = sprintf('A%d_dH', i); - bti248_planar{i,2} = sprintf('A%d_dV', i); - end -end % if isbti - -if isctf - ctfref = { - 'BG1' - 'BG2' - 'BG3' - 'BP1' - 'BP2' - 'BP3' - 'BR1' - 'BR2' - 'BR3' - 'G11' - 'G12' - 'G13' - 'G22' - 'G23' - 'P11' - 'P12' - 'P13' - 'P22' - 'P23' - 'Q11' - 'Q12' - 'Q13' - 'Q22' - 'Q23' - 'R11' - 'R12' - 'R13' - 'R22' - 'R23' - }; - - ctfheadloc = { - 'HLC0011' - 'HLC0012' - 'HLC0013' - 'HLC0021' - 'HLC0022' - 'HLC0023' - 'HLC0031' - 'HLC0032' - 'HLC0033' - 'HLC0018' - 'HLC0028' - 'HLC0038' - 'HLC0014' - 'HLC0015' - 'HLC0016' - 'HLC0017' - 'HLC0024' - 'HLC0025' - 'HLC0026' - 'HLC0027' - 'HLC0034' - 'HLC0035' - 'HLC0036' - 'HLC0037' - }; - - ctf64 = { - 'SL11' - 'SL12' - 'SL13' - 'SL14' - 'SL15' - 'SL16' - 'SL17' - 'SL18' - 'SL19' - 'SL21' - 'SL22' - 'SL23' - 'SL24' - 'SL25' - 'SL26' - 'SL27' - 'SL28' - 'SL29' - 'SL31' - 'SL32' - 'SL33' - 'SL34' - 'SL35' - 'SL41' - 'SL42' - 'SL43' - 'SL44' - 'SL45' - 'SL46' - 'SL47' - 'SL51' - 'SL52' - 'SR11' - 'SR12' - 'SR13' - 'SR14' - 'SR15' - 'SR16' - 'SR17' - 'SR18' - 'SR19' - 'SR21' - 'SR22' - 'SR23' - 'SR24' - 'SR25' - 'SR26' - 'SR27' - 'SR28' - 'SR29' - 'SR31' - 'SR32' - 'SR33' - 'SR34' - 'SR35' - 'SR41' - 'SR42' - 'SR43' - 'SR44' - 'SR45' - 'SR46' - 'SR47' - 'SR51' - 'SR52' - }; - - ctf151 = { - 'MLC11' - 'MLC12' - 'MLC13' - 'MLC14' - 'MLC15' - 'MLC21' - 'MLC22' - 'MLC23' - 'MLC24' - 'MLC31' - 'MLC32' - 'MLC33' - 'MLC41' - 'MLC42' - 'MLC43' - 'MLF11' - 'MLF12' - 'MLF21' - 'MLF22' - 'MLF23' - 'MLF31' - 'MLF32' - 'MLF33' - 'MLF34' - 'MLF41' - 'MLF42' - 'MLF43' - 'MLF44' - 'MLF45' - 'MLF51' - 'MLF52' - 'MLO11' - 'MLO12' - 'MLO21' - 'MLO22' - 'MLO31' - 'MLO32' - 'MLO33' - 'MLO41' - 'MLO42' - 'MLO43' - 'MLP11' - 'MLP12' - 'MLP13' - 'MLP21' - 'MLP22' - 'MLP31' - 'MLP32' - 'MLP33' - 'MLP34' - 'MLT11' - 'MLT12' - 'MLT13' - 'MLT14' - 'MLT15' - 'MLT16' - 'MLT21' - 'MLT22' - 'MLT23' - 'MLT24' - 'MLT25' - 'MLT26' - 'MLT31' - 'MLT32' - 'MLT33' - 'MLT34' - 'MLT35' - 'MLT41' - 'MLT42' - 'MLT43' - 'MLT44' - 'MRC11' - 'MRC12' - 'MRC13' - 'MRC14' - 'MRC15' - 'MRC21' - 'MRC22' - 'MRC23' - 'MRC24' - 'MRC31' - 'MRC32' - 'MRC33' - 'MRC41' - 'MRC42' - 'MRC43' - 'MRF11' - 'MRF12' - 'MRF21' - 'MRF22' - 'MRF23' - 'MRF31' - 'MRF32' - 'MRF33' - 'MRF34' - 'MRF41' - 'MRF42' - 'MRF43' - 'MRF44' - 'MRF45' - 'MRF51' - 'MRF52' - 'MRO11' - 'MRO12' - 'MRO21' - 'MRO22' - 'MRO31' - 'MRO32' - 'MRO33' - 'MRO41' - 'MRO42' - 'MRO43' - 'MRP11' - 'MRP12' - 'MRP13' - 'MRP21' - 'MRP22' - 'MRP31' - 'MRP32' - 'MRP33' - 'MRP34' - 'MRT11' - 'MRT12' - 'MRT13' - 'MRT14' - 'MRT15' - 'MRT16' - 'MRT21' - 'MRT22' - 'MRT23' - 'MRT24' - 'MRT25' - 'MRT26' - 'MRT31' - 'MRT32' - 'MRT33' - 'MRT34' - 'MRT35' - 'MRT41' - 'MRT42' - 'MRT43' - 'MRT44' - 'MZC01' - 'MZC02' - 'MZF01' - 'MZF02' - 'MZF03' - 'MZO01' - 'MZO02' - 'MZP01' - 'MZP02' - }; - - ctf151_planar = cell(151, 2); - for i=1:151 - ctf151_planar{i,1} = sprintf('%s_dH', ctf151{i}); - ctf151_planar{i,2} = sprintf('%s_dV', ctf151{i}); - end - - ctf275 = { - 'MLC11' - 'MLC12' - 'MLC13' - 'MLC14' - 'MLC15' - 'MLC16' - 'MLC17' - 'MLC21' - 'MLC22' - 'MLC23' - 'MLC24' - 'MLC25' - 'MLC31' - 'MLC32' - 'MLC41' - 'MLC42' - 'MLC51' - 'MLC52' - 'MLC53' - 'MLC54' - 'MLC55' - 'MLC61' - 'MLC62' - 'MLC63' - 'MLF11' - 'MLF12' - 'MLF13' - 'MLF14' - 'MLF21' - 'MLF22' - 'MLF23' - 'MLF24' - 'MLF25' - 'MLF31' - 'MLF32' - 'MLF33' - 'MLF34' - 'MLF35' - 'MLF41' - 'MLF42' - 'MLF43' - 'MLF44' - 'MLF45' - 'MLF46' - 'MLF51' - 'MLF52' - 'MLF53' - 'MLF54' - 'MLF55' - 'MLF56' - 'MLF61' - 'MLF62' - 'MLF63' - 'MLF64' - 'MLF65' - 'MLF66' - 'MLF67' - 'MLO11' - 'MLO12' - 'MLO13' - 'MLO14' - 'MLO21' - 'MLO22' - 'MLO23' - 'MLO24' - 'MLO31' - 'MLO32' - 'MLO33' - 'MLO34' - 'MLO41' - 'MLO42' - 'MLO43' - 'MLO44' - 'MLO51' - 'MLO52' - 'MLO53' - 'MLP11' - 'MLP12' - 'MLP21' - 'MLP22' - 'MLP23' - 'MLP31' - 'MLP32' - 'MLP33' - 'MLP34' - 'MLP35' - 'MLP41' - 'MLP42' - 'MLP43' - 'MLP44' - 'MLP45' - 'MLP51' - 'MLP52' - 'MLP53' - 'MLP54' - 'MLP55' - 'MLP56' - 'MLP57' - 'MLT11' - 'MLT12' - 'MLT13' - 'MLT14' - 'MLT15' - 'MLT16' - 'MLT21' - 'MLT22' - 'MLT23' - 'MLT24' - 'MLT25' - 'MLT26' - 'MLT27' - 'MLT31' - 'MLT32' - 'MLT33' - 'MLT34' - 'MLT35' - 'MLT36' - 'MLT37' - 'MLT41' - 'MLT42' - 'MLT43' - 'MLT44' - 'MLT45' - 'MLT46' - 'MLT47' - 'MLT51' - 'MLT52' - 'MLT53' - 'MLT54' - 'MLT55' - 'MLT56' - 'MLT57' - 'MRC11' - 'MRC12' - 'MRC13' - 'MRC14' - 'MRC15' - 'MRC16' - 'MRC17' - 'MRC21' - 'MRC22' - 'MRC23' - 'MRC24' - 'MRC25' - 'MRC31' - 'MRC32' - 'MRC41' - 'MRC42' - 'MRC51' - 'MRC52' - 'MRC53' - 'MRC54' - 'MRC55' - 'MRC61' - 'MRC62' - 'MRC63' - 'MRF11' - 'MRF12' - 'MRF13' - 'MRF14' - 'MRF21' - 'MRF22' - 'MRF23' - 'MRF24' - 'MRF25' - 'MRF31' - 'MRF32' - 'MRF33' - 'MRF34' - 'MRF35' - 'MRF41' - 'MRF42' - 'MRF43' - 'MRF44' - 'MRF45' - 'MRF46' - 'MRF51' - 'MRF52' - 'MRF53' - 'MRF54' - 'MRF55' - 'MRF56' - 'MRF61' - 'MRF62' - 'MRF63' - 'MRF64' - 'MRF65' - 'MRF66' - 'MRF67' - 'MRO11' - 'MRO12' - 'MRO13' - 'MRO14' - 'MRO21' - 'MRO22' - 'MRO23' - 'MRO24' - 'MRO31' - 'MRO32' - 'MRO33' - 'MRO34' - 'MRO41' - 'MRO42' - 'MRO43' - 'MRO44' - 'MRO51' - 'MRO52' - 'MRO53' - 'MRP11' - 'MRP12' - 'MRP21' - 'MRP22' - 'MRP23' - 'MRP32' - 'MRP33' - 'MRP34' - 'MRP35' - 'MRP41' - 'MRP42' - 'MRP43' - 'MRP44' - 'MRP45' - 'MRP51' - 'MRP52' - 'MRP53' - 'MRP54' - 'MRP55' - 'MRP56' - 'MRP57' - 'MRT11' - 'MRT12' - 'MRT13' - 'MRT14' - 'MRT15' - 'MRT16' - 'MRT21' - 'MRT22' - 'MRT23' - 'MRT24' - 'MRT25' - 'MRT26' - 'MRT27' - 'MRT31' - 'MRT32' - 'MRT33' - 'MRT34' - 'MRT35' - 'MRT36' - 'MRT37' - 'MRT41' - 'MRT42' - 'MRT43' - 'MRT44' - 'MRT45' - 'MRT46' - 'MRT47' - 'MRT51' - 'MRT52' - 'MRT53' - 'MRT54' - 'MRT55' - 'MRT56' - 'MRT57' - 'MZC01' - 'MZC02' - 'MZC03' - 'MZC04' - 'MZF01' - 'MZF02' - 'MZF03' - 'MZO01' - 'MZO02' - 'MZO03' - 'MZP01' - }; - - % f.ck, apparently one channel is missing - ctf275_planar = cell(274,2); - for i=1:274 - ctf275_planar{i,1} = sprintf('%s_dH', ctf275{i}); - ctf275_planar{i,2} = sprintf('%s_dV', ctf275{i}); - end -end % if issctf - -if isneuromag - neuromag122 = { - 'MEG 001' 'MEG 002' - 'MEG 003' 'MEG 004' - 'MEG 005' 'MEG 006' - 'MEG 007' 'MEG 008' - 'MEG 009' 'MEG 010' - 'MEG 011' 'MEG 012' - 'MEG 013' 'MEG 014' - 'MEG 015' 'MEG 016' - 'MEG 017' 'MEG 018' - 'MEG 019' 'MEG 020' - 'MEG 021' 'MEG 022' - 'MEG 023' 'MEG 024' - 'MEG 025' 'MEG 026' - 'MEG 027' 'MEG 028' - 'MEG 029' 'MEG 030' - 'MEG 031' 'MEG 032' - 'MEG 033' 'MEG 034' - 'MEG 035' 'MEG 036' - 'MEG 037' 'MEG 038' - 'MEG 039' 'MEG 040' - 'MEG 041' 'MEG 042' - 'MEG 043' 'MEG 044' - 'MEG 045' 'MEG 046' - 'MEG 047' 'MEG 048' - 'MEG 049' 'MEG 050' - 'MEG 051' 'MEG 052' - 'MEG 053' 'MEG 054' - 'MEG 055' 'MEG 056' - 'MEG 057' 'MEG 058' - 'MEG 059' 'MEG 060' - 'MEG 061' 'MEG 062' - 'MEG 063' 'MEG 064' - 'MEG 065' 'MEG 066' - 'MEG 067' 'MEG 068' - 'MEG 069' 'MEG 070' - 'MEG 071' 'MEG 072' - 'MEG 073' 'MEG 074' - 'MEG 075' 'MEG 076' - 'MEG 077' 'MEG 078' - 'MEG 079' 'MEG 080' - 'MEG 081' 'MEG 082' - 'MEG 083' 'MEG 084' - 'MEG 085' 'MEG 086' - 'MEG 087' 'MEG 088' - 'MEG 089' 'MEG 090' - 'MEG 091' 'MEG 092' - 'MEG 093' 'MEG 094' - 'MEG 095' 'MEG 096' - 'MEG 097' 'MEG 098' - 'MEG 099' 'MEG 100' - 'MEG 101' 'MEG 102' - 'MEG 103' 'MEG 104' - 'MEG 105' 'MEG 106' - 'MEG 107' 'MEG 108' - 'MEG 109' 'MEG 110' - 'MEG 111' 'MEG 112' - 'MEG 113' 'MEG 114' - 'MEG 115' 'MEG 116' - 'MEG 117' 'MEG 118' - 'MEG 119' 'MEG 120' - 'MEG 121' 'MEG 122' - }; - - % this is an alternative set of labels without a space in them - neuromag122alt = { - 'MEG001' 'MEG002' - 'MEG003' 'MEG004' - 'MEG005' 'MEG006' - 'MEG007' 'MEG008' - 'MEG009' 'MEG010' - 'MEG011' 'MEG012' - 'MEG013' 'MEG014' - 'MEG015' 'MEG016' - 'MEG017' 'MEG018' - 'MEG019' 'MEG020' - 'MEG021' 'MEG022' - 'MEG023' 'MEG024' - 'MEG025' 'MEG026' - 'MEG027' 'MEG028' - 'MEG029' 'MEG030' - 'MEG031' 'MEG032' - 'MEG033' 'MEG034' - 'MEG035' 'MEG036' - 'MEG037' 'MEG038' - 'MEG039' 'MEG040' - 'MEG041' 'MEG042' - 'MEG043' 'MEG044' - 'MEG045' 'MEG046' - 'MEG047' 'MEG048' - 'MEG049' 'MEG050' - 'MEG051' 'MEG052' - 'MEG053' 'MEG054' - 'MEG055' 'MEG056' - 'MEG057' 'MEG058' - 'MEG059' 'MEG060' - 'MEG061' 'MEG062' - 'MEG063' 'MEG064' - 'MEG065' 'MEG066' - 'MEG067' 'MEG068' - 'MEG069' 'MEG070' - 'MEG071' 'MEG072' - 'MEG073' 'MEG074' - 'MEG075' 'MEG076' - 'MEG077' 'MEG078' - 'MEG079' 'MEG080' - 'MEG081' 'MEG082' - 'MEG083' 'MEG084' - 'MEG085' 'MEG086' - 'MEG087' 'MEG088' - 'MEG089' 'MEG090' - 'MEG091' 'MEG092' - 'MEG093' 'MEG094' - 'MEG095' 'MEG096' - 'MEG097' 'MEG098' - 'MEG099' 'MEG100' - 'MEG101' 'MEG102' - 'MEG103' 'MEG104' - 'MEG105' 'MEG106' - 'MEG107' 'MEG108' - 'MEG109' 'MEG110' - 'MEG111' 'MEG112' - 'MEG113' 'MEG114' - 'MEG115' 'MEG116' - 'MEG117' 'MEG118' - 'MEG119' 'MEG120' - 'MEG121' 'MEG122' - }; - - neuromag306 = { - 'MEG 0113' 'MEG 0112' 'MEG 0111' - 'MEG 0122' 'MEG 0123' 'MEG 0121' - 'MEG 0132' 'MEG 0133' 'MEG 0131' - 'MEG 0143' 'MEG 0142' 'MEG 0141' - 'MEG 0213' 'MEG 0212' 'MEG 0211' - 'MEG 0222' 'MEG 0223' 'MEG 0221' - 'MEG 0232' 'MEG 0233' 'MEG 0231' - 'MEG 0243' 'MEG 0242' 'MEG 0241' - 'MEG 0313' 'MEG 0312' 'MEG 0311' - 'MEG 0322' 'MEG 0323' 'MEG 0321' - 'MEG 0333' 'MEG 0332' 'MEG 0331' - 'MEG 0343' 'MEG 0342' 'MEG 0341' - 'MEG 0413' 'MEG 0412' 'MEG 0411' - 'MEG 0422' 'MEG 0423' 'MEG 0421' - 'MEG 0432' 'MEG 0433' 'MEG 0431' - 'MEG 0443' 'MEG 0442' 'MEG 0441' - 'MEG 0513' 'MEG 0512' 'MEG 0511' - 'MEG 0523' 'MEG 0522' 'MEG 0521' - 'MEG 0532' 'MEG 0533' 'MEG 0531' - 'MEG 0542' 'MEG 0543' 'MEG 0541' - 'MEG 0613' 'MEG 0612' 'MEG 0611' - 'MEG 0622' 'MEG 0623' 'MEG 0621' - 'MEG 0633' 'MEG 0632' 'MEG 0631' - 'MEG 0642' 'MEG 0643' 'MEG 0641' - 'MEG 0713' 'MEG 0712' 'MEG 0711' - 'MEG 0723' 'MEG 0722' 'MEG 0721' - 'MEG 0733' 'MEG 0732' 'MEG 0731' - 'MEG 0743' 'MEG 0742' 'MEG 0741' - 'MEG 0813' 'MEG 0812' 'MEG 0811' - 'MEG 0822' 'MEG 0823' 'MEG 0821' - 'MEG 0913' 'MEG 0912' 'MEG 0911' - 'MEG 0923' 'MEG 0922' 'MEG 0921' - 'MEG 0932' 'MEG 0933' 'MEG 0931' - 'MEG 0942' 'MEG 0943' 'MEG 0941' - 'MEG 1013' 'MEG 1012' 'MEG 1011' - 'MEG 1023' 'MEG 1022' 'MEG 1021' - 'MEG 1032' 'MEG 1033' 'MEG 1031' - 'MEG 1043' 'MEG 1042' 'MEG 1041' - 'MEG 1112' 'MEG 1113' 'MEG 1111' - 'MEG 1123' 'MEG 1122' 'MEG 1121' - 'MEG 1133' 'MEG 1132' 'MEG 1131' - 'MEG 1142' 'MEG 1143' 'MEG 1141' - 'MEG 1213' 'MEG 1212' 'MEG 1211' - 'MEG 1223' 'MEG 1222' 'MEG 1221' - 'MEG 1232' 'MEG 1233' 'MEG 1231' - 'MEG 1243' 'MEG 1242' 'MEG 1241' - 'MEG 1312' 'MEG 1313' 'MEG 1311' - 'MEG 1323' 'MEG 1322' 'MEG 1321' - 'MEG 1333' 'MEG 1332' 'MEG 1331' - 'MEG 1342' 'MEG 1343' 'MEG 1341' - 'MEG 1412' 'MEG 1413' 'MEG 1411' - 'MEG 1423' 'MEG 1422' 'MEG 1421' - 'MEG 1433' 'MEG 1432' 'MEG 1431' - 'MEG 1442' 'MEG 1443' 'MEG 1441' - 'MEG 1512' 'MEG 1513' 'MEG 1511' - 'MEG 1522' 'MEG 1523' 'MEG 1521' - 'MEG 1533' 'MEG 1532' 'MEG 1531' - 'MEG 1543' 'MEG 1542' 'MEG 1541' - 'MEG 1613' 'MEG 1612' 'MEG 1611' - 'MEG 1622' 'MEG 1623' 'MEG 1621' - 'MEG 1632' 'MEG 1633' 'MEG 1631' - 'MEG 1643' 'MEG 1642' 'MEG 1641' - 'MEG 1713' 'MEG 1712' 'MEG 1711' - 'MEG 1722' 'MEG 1723' 'MEG 1721' - 'MEG 1732' 'MEG 1733' 'MEG 1731' - 'MEG 1743' 'MEG 1742' 'MEG 1741' - 'MEG 1813' 'MEG 1812' 'MEG 1811' - 'MEG 1822' 'MEG 1823' 'MEG 1821' - 'MEG 1832' 'MEG 1833' 'MEG 1831' - 'MEG 1843' 'MEG 1842' 'MEG 1841' - 'MEG 1912' 'MEG 1913' 'MEG 1911' - 'MEG 1923' 'MEG 1922' 'MEG 1921' - 'MEG 1932' 'MEG 1933' 'MEG 1931' - 'MEG 1943' 'MEG 1942' 'MEG 1941' - 'MEG 2013' 'MEG 2012' 'MEG 2011' - 'MEG 2023' 'MEG 2022' 'MEG 2021' - 'MEG 2032' 'MEG 2033' 'MEG 2031' - 'MEG 2042' 'MEG 2043' 'MEG 2041' - 'MEG 2113' 'MEG 2112' 'MEG 2111' - 'MEG 2122' 'MEG 2123' 'MEG 2121' - 'MEG 2133' 'MEG 2132' 'MEG 2131' - 'MEG 2143' 'MEG 2142' 'MEG 2141' - 'MEG 2212' 'MEG 2213' 'MEG 2211' - 'MEG 2223' 'MEG 2222' 'MEG 2221' - 'MEG 2233' 'MEG 2232' 'MEG 2231' - 'MEG 2242' 'MEG 2243' 'MEG 2241' - 'MEG 2312' 'MEG 2313' 'MEG 2311' - 'MEG 2323' 'MEG 2322' 'MEG 2321' - 'MEG 2332' 'MEG 2333' 'MEG 2331' - 'MEG 2343' 'MEG 2342' 'MEG 2341' - 'MEG 2412' 'MEG 2413' 'MEG 2411' - 'MEG 2423' 'MEG 2422' 'MEG 2421' - 'MEG 2433' 'MEG 2432' 'MEG 2431' - 'MEG 2442' 'MEG 2443' 'MEG 2441' - 'MEG 2512' 'MEG 2513' 'MEG 2511' - 'MEG 2522' 'MEG 2523' 'MEG 2521' - 'MEG 2533' 'MEG 2532' 'MEG 2531' - 'MEG 2543' 'MEG 2542' 'MEG 2541' - 'MEG 2612' 'MEG 2613' 'MEG 2611' - 'MEG 2623' 'MEG 2622' 'MEG 2621' - 'MEG 2633' 'MEG 2632' 'MEG 2631' - 'MEG 2642' 'MEG 2643' 'MEG 2641' - }; - - % this is an alternative set of labels without a space in them - neuromag306alt = { - 'MEG0113' 'MEG0112' 'MEG0111' - 'MEG0122' 'MEG0123' 'MEG0121' - 'MEG0132' 'MEG0133' 'MEG0131' - 'MEG0143' 'MEG0142' 'MEG0141' - 'MEG0213' 'MEG0212' 'MEG0211' - 'MEG0222' 'MEG0223' 'MEG0221' - 'MEG0232' 'MEG0233' 'MEG0231' - 'MEG0243' 'MEG0242' 'MEG0241' - 'MEG0313' 'MEG0312' 'MEG0311' - 'MEG0322' 'MEG0323' 'MEG0321' - 'MEG0333' 'MEG0332' 'MEG0331' - 'MEG0343' 'MEG0342' 'MEG0341' - 'MEG0413' 'MEG0412' 'MEG0411' - 'MEG0422' 'MEG0423' 'MEG0421' - 'MEG0432' 'MEG0433' 'MEG0431' - 'MEG0443' 'MEG0442' 'MEG0441' - 'MEG0513' 'MEG0512' 'MEG0511' - 'MEG0523' 'MEG0522' 'MEG0521' - 'MEG0532' 'MEG0533' 'MEG0531' - 'MEG0542' 'MEG0543' 'MEG0541' - 'MEG0613' 'MEG0612' 'MEG0611' - 'MEG0622' 'MEG0623' 'MEG0621' - 'MEG0633' 'MEG0632' 'MEG0631' - 'MEG0642' 'MEG0643' 'MEG0641' - 'MEG0713' 'MEG0712' 'MEG0711' - 'MEG0723' 'MEG0722' 'MEG0721' - 'MEG0733' 'MEG0732' 'MEG0731' - 'MEG0743' 'MEG0742' 'MEG0741' - 'MEG0813' 'MEG0812' 'MEG0811' - 'MEG0822' 'MEG0823' 'MEG0821' - 'MEG0913' 'MEG0912' 'MEG0911' - 'MEG0923' 'MEG0922' 'MEG0921' - 'MEG0932' 'MEG0933' 'MEG0931' - 'MEG0942' 'MEG0943' 'MEG0941' - 'MEG1013' 'MEG1012' 'MEG1011' - 'MEG1023' 'MEG1022' 'MEG1021' - 'MEG1032' 'MEG1033' 'MEG1031' - 'MEG1043' 'MEG1042' 'MEG1041' - 'MEG1112' 'MEG1113' 'MEG1111' - 'MEG1123' 'MEG1122' 'MEG1121' - 'MEG1133' 'MEG1132' 'MEG1131' - 'MEG1142' 'MEG1143' 'MEG1141' - 'MEG1213' 'MEG1212' 'MEG1211' - 'MEG1223' 'MEG1222' 'MEG1221' - 'MEG1232' 'MEG1233' 'MEG1231' - 'MEG1243' 'MEG1242' 'MEG1241' - 'MEG1312' 'MEG1313' 'MEG1311' - 'MEG1323' 'MEG1322' 'MEG1321' - 'MEG1333' 'MEG1332' 'MEG1331' - 'MEG1342' 'MEG1343' 'MEG1341' - 'MEG1412' 'MEG1413' 'MEG1411' - 'MEG1423' 'MEG1422' 'MEG1421' - 'MEG1433' 'MEG1432' 'MEG1431' - 'MEG1442' 'MEG1443' 'MEG1441' - 'MEG1512' 'MEG1513' 'MEG1511' - 'MEG1522' 'MEG1523' 'MEG1521' - 'MEG1533' 'MEG1532' 'MEG1531' - 'MEG1543' 'MEG1542' 'MEG1541' - 'MEG1613' 'MEG1612' 'MEG1611' - 'MEG1622' 'MEG1623' 'MEG1621' - 'MEG1632' 'MEG1633' 'MEG1631' - 'MEG1643' 'MEG1642' 'MEG1641' - 'MEG1713' 'MEG1712' 'MEG1711' - 'MEG1722' 'MEG1723' 'MEG1721' - 'MEG1732' 'MEG1733' 'MEG1731' - 'MEG1743' 'MEG1742' 'MEG1741' - 'MEG1813' 'MEG1812' 'MEG1811' - 'MEG1822' 'MEG1823' 'MEG1821' - 'MEG1832' 'MEG1833' 'MEG1831' - 'MEG1843' 'MEG1842' 'MEG1841' - 'MEG1912' 'MEG1913' 'MEG1911' - 'MEG1923' 'MEG1922' 'MEG1921' - 'MEG1932' 'MEG1933' 'MEG1931' - 'MEG1943' 'MEG1942' 'MEG1941' - 'MEG2013' 'MEG2012' 'MEG2011' - 'MEG2023' 'MEG2022' 'MEG2021' - 'MEG2032' 'MEG2033' 'MEG2031' - 'MEG2042' 'MEG2043' 'MEG2041' - 'MEG2113' 'MEG2112' 'MEG2111' - 'MEG2122' 'MEG2123' 'MEG2121' - 'MEG2133' 'MEG2132' 'MEG2131' - 'MEG2143' 'MEG2142' 'MEG2141' - 'MEG2212' 'MEG2213' 'MEG2211' - 'MEG2223' 'MEG2222' 'MEG2221' - 'MEG2233' 'MEG2232' 'MEG2231' - 'MEG2242' 'MEG2243' 'MEG2241' - 'MEG2312' 'MEG2313' 'MEG2311' - 'MEG2323' 'MEG2322' 'MEG2321' - 'MEG2332' 'MEG2333' 'MEG2331' - 'MEG2343' 'MEG2342' 'MEG2341' - 'MEG2412' 'MEG2413' 'MEG2411' - 'MEG2423' 'MEG2422' 'MEG2421' - 'MEG2433' 'MEG2432' 'MEG2431' - 'MEG2442' 'MEG2443' 'MEG2441' - 'MEG2512' 'MEG2513' 'MEG2511' - 'MEG2522' 'MEG2523' 'MEG2521' - 'MEG2533' 'MEG2532' 'MEG2531' - 'MEG2543' 'MEG2542' 'MEG2541' - 'MEG2612' 'MEG2613' 'MEG2611' - 'MEG2623' 'MEG2622' 'MEG2621' - 'MEG2633' 'MEG2632' 'MEG2631' - 'MEG2642' 'MEG2643' 'MEG2641' - }; -end % if isneuromag - -if iseeg || isext - eeg1020 = { - 'Fp1' - 'Fpz' - 'Fp2' - 'F7' - 'F3' - 'Fz' - 'F4' - 'F8' - 'T7' - 'C3' - 'Cz' - 'C4' - 'T8' - 'P7' - 'P3' - 'Pz' - 'P4' - 'P8' - 'O1' - 'Oz' - 'O2'}; - - eeg1010 = { - 'Fp1' - 'Fpz' - 'Fp2' - 'AF9' - 'AF7' - 'AF5' - 'AF3' - 'AF1' - 'AFz' - 'AF2' - 'AF4' - 'AF6' - 'AF8' - 'AF10' - 'F9' - 'F7' - 'F5' - 'F3' - 'F1' - 'Fz' - 'F2' - 'F4' - 'F6' - 'F8' - 'F10' - 'FT9' - 'FT7' - 'FC5' - 'FC3' - 'FC1' - 'FCz' - 'FC2' - 'FC4' - 'FC6' - 'FT8' - 'FT10' - 'T9' - 'T7' - 'C5' - 'C3' - 'C1' - 'Cz' - 'C2' - 'C4' - 'C6' - 'T8' - 'T10' - 'TP9' - 'TP7' - 'CP5' - 'CP3' - 'CP1' - 'CPz' - 'CP2' - 'CP4' - 'CP6' - 'TP8' - 'TP10' - 'P9' - 'P7' - 'P5' - 'P3' - 'P1' - 'Pz' - 'P2' - 'P4' - 'P6' - 'P8' - 'P10' - 'PO9' - 'PO7' - 'PO5' - 'PO3' - 'PO1' - 'POz' - 'PO2' - 'PO4' - 'PO6' - 'PO8' - 'PO10' - 'O1' - 'Oz' - 'O2' - 'I1' - 'Iz' - 'I2' - }; - - eeg1005 = { - 'Fp1' - 'Fpz' - 'Fp2' - 'AF9' - 'AF7' - 'AF5' - 'AF3' - 'AF1' - 'AFz' - 'AF2' - 'AF4' - 'AF6' - 'AF8' - 'AF10' - 'F9' - 'F7' - 'F5' - 'F3' - 'F1' - 'Fz' - 'F2' - 'F4' - 'F6' - 'F8' - 'F10' - 'FT9' - 'FT7' - 'FC5' - 'FC3' - 'FC1' - 'FCz' - 'FC2' - 'FC4' - 'FC6' - 'FT8' - 'FT10' - 'T9' - 'T7' - 'C5' - 'C3' - 'C1' - 'Cz' - 'C2' - 'C4' - 'C6' - 'T8' - 'T10' - 'TP9' - 'TP7' - 'CP5' - 'CP3' - 'CP1' - 'CPz' - 'CP2' - 'CP4' - 'CP6' - 'TP8' - 'TP10' - 'P9' - 'P7' - 'P5' - 'P3' - 'P1' - 'Pz' - 'P2' - 'P4' - 'P6' - 'P8' - 'P10' - 'PO9' - 'PO7' - 'PO5' - 'PO3' - 'PO1' - 'POz' - 'PO2' - 'PO4' - 'PO6' - 'PO8' - 'PO10' - 'O1' - 'Oz' - 'O2' - 'I1' - 'Iz' - 'I2' - 'AFp9h' - 'AFp7h' - 'AFp5h' - 'AFp3h' - 'AFp1h' - 'AFp2h' - 'AFp4h' - 'AFp6h' - 'AFp8h' - 'AFp10h' - 'AFF9h' - 'AFF7h' - 'AFF5h' - 'AFF3h' - 'AFF1h' - 'AFF2h' - 'AFF4h' - 'AFF6h' - 'AFF8h' - 'AFF10h' - 'FFT9h' - 'FFT7h' - 'FFC5h' - 'FFC3h' - 'FFC1h' - 'FFC2h' - 'FFC4h' - 'FFC6h' - 'FFT8h' - 'FFT10h' - 'FTT9h' - 'FTT7h' - 'FCC5h' - 'FCC3h' - 'FCC1h' - 'FCC2h' - 'FCC4h' - 'FCC6h' - 'FTT8h' - 'FTT10h' - 'TTP9h' - 'TTP7h' - 'CCP5h' - 'CCP3h' - 'CCP1h' - 'CCP2h' - 'CCP4h' - 'CCP6h' - 'TTP8h' - 'TTP10h' - 'TPP9h' - 'TPP7h' - 'CPP5h' - 'CPP3h' - 'CPP1h' - 'CPP2h' - 'CPP4h' - 'CPP6h' - 'TPP8h' - 'TPP10h' - 'PPO9h' - 'PPO7h' - 'PPO5h' - 'PPO3h' - 'PPO1h' - 'PPO2h' - 'PPO4h' - 'PPO6h' - 'PPO8h' - 'PPO10h' - 'POO9h' - 'POO7h' - 'POO5h' - 'POO3h' - 'POO1h' - 'POO2h' - 'POO4h' - 'POO6h' - 'POO8h' - 'POO10h' - 'OI1h' - 'OI2h' - 'Fp1h' - 'Fp2h' - 'AF9h' - 'AF7h' - 'AF5h' - 'AF3h' - 'AF1h' - 'AF2h' - 'AF4h' - 'AF6h' - 'AF8h' - 'AF10h' - 'F9h' - 'F7h' - 'F5h' - 'F3h' - 'F1h' - 'F2h' - 'F4h' - 'F6h' - 'F8h' - 'F10h' - 'FT9h' - 'FT7h' - 'FC5h' - 'FC3h' - 'FC1h' - 'FC2h' - 'FC4h' - 'FC6h' - 'FT8h' - 'FT10h' - 'T9h' - 'T7h' - 'C5h' - 'C3h' - 'C1h' - 'C2h' - 'C4h' - 'C6h' - 'T8h' - 'T10h' - 'TP9h' - 'TP7h' - 'CP5h' - 'CP3h' - 'CP1h' - 'CP2h' - 'CP4h' - 'CP6h' - 'TP8h' - 'TP10h' - 'P9h' - 'P7h' - 'P5h' - 'P3h' - 'P1h' - 'P2h' - 'P4h' - 'P6h' - 'P8h' - 'P10h' - 'PO9h' - 'PO7h' - 'PO5h' - 'PO3h' - 'PO1h' - 'PO2h' - 'PO4h' - 'PO6h' - 'PO8h' - 'PO10h' - 'O1h' - 'O2h' - 'I1h' - 'I2h' - 'AFp9' - 'AFp7' - 'AFp5' - 'AFp3' - 'AFp1' - 'AFpz' - 'AFp2' - 'AFp4' - 'AFp6' - 'AFp8' - 'AFp10' - 'AFF9' - 'AFF7' - 'AFF5' - 'AFF3' - 'AFF1' - 'AFFz' - 'AFF2' - 'AFF4' - 'AFF6' - 'AFF8' - 'AFF10' - 'FFT9' - 'FFT7' - 'FFC5' - 'FFC3' - 'FFC1' - 'FFCz' - 'FFC2' - 'FFC4' - 'FFC6' - 'FFT8' - 'FFT10' - 'FTT9' - 'FTT7' - 'FCC5' - 'FCC3' - 'FCC1' - 'FCCz' - 'FCC2' - 'FCC4' - 'FCC6' - 'FTT8' - 'FTT10' - 'TTP9' - 'TTP7' - 'CCP5' - 'CCP3' - 'CCP1' - 'CCPz' - 'CCP2' - 'CCP4' - 'CCP6' - 'TTP8' - 'TTP10' - 'TPP9' - 'TPP7' - 'CPP5' - 'CPP3' - 'CPP1' - 'CPPz' - 'CPP2' - 'CPP4' - 'CPP6' - 'TPP8' - 'TPP10' - 'PPO9' - 'PPO7' - 'PPO5' - 'PPO3' - 'PPO1' - 'PPOz' - 'PPO2' - 'PPO4' - 'PPO6' - 'PPO8' - 'PPO10' - 'POO9' - 'POO7' - 'POO5' - 'POO3' - 'POO1' - 'POOz' - 'POO2' - 'POO4' - 'POO6' - 'POO8' - 'POO10' - 'OI1' - 'OIz' - 'OI2' - }; - - % Add also alternative labels that are used in some systems - ext1020 = cat(1, eeg1005, {'A1' 'A2' 'M1' 'M2' 'T3' 'T4' 'T5' 'T6'}'); - - % This is to account for all variants of case in 1020 systems - ext1020 = unique(cat(1, ext1020, upper(ext1020), lower(ext1020))); -end % if iseeg || isext - -if isbiosemi - biosemi64 = { - 'A1' - 'A2' - 'A3' - 'A4' - 'A5' - 'A6' - 'A7' - 'A8' - 'A9' - 'A10' - 'A11' - 'A12' - 'A13' - 'A14' - 'A15' - 'A16' - 'A17' - 'A18' - 'A19' - 'A20' - 'A21' - 'A22' - 'A23' - 'A24' - 'A25' - 'A26' - 'A27' - 'A28' - 'A29' - 'A30' - 'A31' - 'A32' - 'B1' - 'B2' - 'B3' - 'B4' - 'B5' - 'B6' - 'B7' - 'B8' - 'B9' - 'B10' - 'B11' - 'B12' - 'B13' - 'B14' - 'B15' - 'B16' - 'B17' - 'B18' - 'B19' - 'B20' - 'B21' - 'B22' - 'B23' - 'B24' - 'B25' - 'B26' - 'B27' - 'B28' - 'B29' - 'B30' - 'B31' - 'B32' - }; - - biosemi128 = { - 'A1' - 'A2' - 'A3' - 'A4' - 'A5' - 'A6' - 'A7' - 'A8' - 'A9' - 'A10' - 'A11' - 'A12' - 'A13' - 'A14' - 'A15' - 'A16' - 'A17' - 'A18' - 'A19' - 'A20' - 'A21' - 'A22' - 'A23' - 'A24' - 'A25' - 'A26' - 'A27' - 'A28' - 'A29' - 'A30' - 'A31' - 'A32' - 'B1' - 'B2' - 'B3' - 'B4' - 'B5' - 'B6' - 'B7' - 'B8' - 'B9' - 'B10' - 'B11' - 'B12' - 'B13' - 'B14' - 'B15' - 'B16' - 'B17' - 'B18' - 'B19' - 'B20' - 'B21' - 'B22' - 'B23' - 'B24' - 'B25' - 'B26' - 'B27' - 'B28' - 'B29' - 'B30' - 'B31' - 'B32' - 'C1' - 'C2' - 'C3' - 'C4' - 'C5' - 'C6' - 'C7' - 'C8' - 'C9' - 'C10' - 'C11' - 'C12' - 'C13' - 'C14' - 'C15' - 'C16' - 'C17' - 'C18' - 'C19' - 'C20' - 'C21' - 'C22' - 'C23' - 'C24' - 'C25' - 'C26' - 'C27' - 'C28' - 'C29' - 'C30' - 'C31' - 'C32' - 'D1' - 'D2' - 'D3' - 'D4' - 'D5' - 'D6' - 'D7' - 'D8' - 'D9' - 'D10' - 'D11' - 'D12' - 'D13' - 'D14' - 'D15' - 'D16' - 'D17' - 'D18' - 'D19' - 'D20' - 'D21' - 'D22' - 'D23' - 'D24' - 'D25' - 'D26' - 'D27' - 'D28' - 'D29' - 'D30' - 'D31' - 'D32' - }; - - biosemi256 = { - 'A1' - 'A2' - 'A3' - 'A4' - 'A5' - 'A6' - 'A7' - 'A8' - 'A9' - 'A10' - 'A11' - 'A12' - 'A13' - 'A14' - 'A15' - 'A16' - 'A17' - 'A18' - 'A19' - 'A20' - 'A21' - 'A22' - 'A23' - 'A24' - 'A25' - 'A26' - 'A27' - 'A28' - 'A29' - 'A30' - 'A31' - 'A32' - 'B1' - 'B2' - 'B3' - 'B4' - 'B5' - 'B6' - 'B7' - 'B8' - 'B9' - 'B10' - 'B11' - 'B12' - 'B13' - 'B14' - 'B15' - 'B16' - 'B17' - 'B18' - 'B19' - 'B20' - 'B21' - 'B22' - 'B23' - 'B24' - 'B25' - 'B26' - 'B27' - 'B28' - 'B29' - 'B30' - 'B31' - 'B32' - 'C1' - 'C2' - 'C3' - 'C4' - 'C5' - 'C6' - 'C7' - 'C8' - 'C9' - 'C10' - 'C11' - 'C12' - 'C13' - 'C14' - 'C15' - 'C16' - 'C17' - 'C18' - 'C19' - 'C20' - 'C21' - 'C22' - 'C23' - 'C24' - 'C25' - 'C26' - 'C27' - 'C28' - 'C29' - 'C30' - 'C31' - 'C32' - 'D1' - 'D2' - 'D3' - 'D4' - 'D5' - 'D6' - 'D7' - 'D8' - 'D9' - 'D10' - 'D11' - 'D12' - 'D13' - 'D14' - 'D15' - 'D16' - 'D17' - 'D18' - 'D19' - 'D20' - 'D21' - 'D22' - 'D23' - 'D24' - 'D25' - 'D26' - 'D27' - 'D28' - 'D29' - 'D30' - 'D31' - 'D32' - 'E1' - 'E2' - 'E3' - 'E4' - 'E5' - 'E6' - 'E7' - 'E8' - 'E9' - 'E10' - 'E11' - 'E12' - 'E13' - 'E14' - 'E15' - 'E16' - 'E17' - 'E18' - 'E19' - 'E20' - 'E21' - 'E22' - 'E23' - 'E24' - 'E25' - 'E26' - 'E27' - 'E28' - 'E29' - 'E30' - 'E31' - 'E32' - 'F1' - 'F2' - 'F3' - 'F4' - 'F5' - 'F6' - 'F7' - 'F8' - 'F9' - 'F10' - 'F11' - 'F12' - 'F13' - 'F14' - 'F15' - 'F16' - 'F17' - 'F18' - 'F19' - 'F20' - 'F21' - 'F22' - 'F23' - 'F24' - 'F25' - 'F26' - 'F27' - 'F28' - 'F29' - 'F30' - 'F31' - 'F32' - 'G1' - 'G2' - 'G3' - 'G4' - 'G5' - 'G6' - 'G7' - 'G8' - 'G9' - 'G10' - 'G11' - 'G12' - 'G13' - 'G14' - 'G15' - 'G16' - 'G17' - 'G18' - 'G19' - 'G20' - 'G21' - 'G22' - 'G23' - 'G24' - 'G25' - 'G26' - 'G27' - 'G28' - 'G29' - 'G30' - 'G31' - 'G32' - 'H1' - 'H2' - 'H3' - 'H4' - 'H5' - 'H6' - 'H7' - 'H8' - 'H9' - 'H10' - 'H11' - 'H12' - 'H13' - 'H14' - 'H15' - 'H16' - 'H17' - 'H18' - 'H19' - 'H20' - 'H21' - 'H22' - 'H23' - 'H24' - 'H25' - 'H26' - 'H27' - 'H28' - 'H29' - 'H30' - 'H31' - 'H32' - }; - -end % if isbiosemi - -if isegi - egi256 = cell(256, 1); - for i = 1:256 - egi256{i} = sprintf('e%d', i); - end - % the others are subsets - egi32 = egi256(1:32); - egi64 = egi256(1:64); - egi128 = egi256(1:128); -end % if isegi - -if isitab - itab153 = cell(153,1); - itab153_planar = cell(153,2); - for i=1:153 - % channel names start counting at zero - itab153{i} = sprintf('MAG_%03d', i-1); - itab153_planar{i,1} = sprintf('MAG_%03d_dH', i-1); - itab153_planar{i,2} = sprintf('MAG_%03d_dV', i-1); - end -end % if isitab - -% search for the requested definition of channel labels -if exist(type, 'var') - label = eval(type); - label = label(:); -else - error('the requested sensor type is not supported'); -end - -% remember the current input and output arguments, so that they can be -% reused on a subsequent call in case the same input argument is given -current_argout = {label}; -if isempty(previous_argin) - previous_argin = current_argin; - previous_argout = current_argout; -end - diff --git a/external/fileio/private/senstype.m b/external/fileio/private/senstype.m deleted file mode 100644 index c6ccaeb..0000000 --- a/external/fileio/private/senstype.m +++ /dev/null @@ -1,368 +0,0 @@ -function [type] = senstype(input, desired) - -% SENSTYPE determines the type of sensors by looking at the channel names -% and comparing them with predefined lists. -% -% Use as -% [type] = senstype(sens) -% to get a string describing the type, or -% [flag] = senstype(sens, desired) -% to get a boolean value. -% -% The output type can be any of the following -% 'electrode' -% 'magnetometer' -% 'biosemi64' -% 'biosemi128' -% 'biosemi256' -% 'bti148' -% 'bti148_planar' -% 'bti248' -% 'bti248_planar' -% 'ctf151' -% 'ctf151_planar' -% 'ctf275' -% 'ctf275_planar' -% 'egi128' -% 'egi256' -% 'egi32' -% 'egi64' -% 'ext1020' -% 'neuromag122' -% 'neuromag306' -% 'yokogawa160' -% 'yokogawa160_planar' -% 'plexon' -% 'itab153' -% 'itab153_planar' -% -% The optional input argument for the desired type can be any of the above, -% or any of the following -% 'eeg' -% 'meg' -% 'meg_planar' -% 'meg_axial' -% 'ctf' -% 'bti' -% 'neuromag' -% 'yokogawa' -% -% Besides specifiying a grad or elec structure as input, also allowed is -% giving a data structure containing a grad or elec field, or giving a list -% of channel names (as cell-arrray). I.e. assuming a FieldTrip data -% structure, all of the following calls would be correct. -% senstype(data) -% senstype(data.label) -% senstype(data.grad) -% senstype(data.grad.label) -% -% See also READ_SENS, COMPUTE_LEADFIELD - -% Copyright (C) 2007-2008, Robert Oostenveld -% -% $Log: senstype.m,v $ -% Revision 1.22 2009/10/19 10:12:52 vlalit -% Fixed a bug that caused shape to be recognized as elec. -% -% Revision 1.21 2009/10/16 12:27:53 roboos -% some small changes pertaining to the itab/chieti format -% -% Revision 1.20 2009/10/13 10:39:19 roboos -% added support for 153 channel itab system -% -% Revision 1.19 2009/07/29 08:04:38 roboos -% cleaned up the code, no functional change -% -% Revision 1.18 2009/07/28 11:16:23 roboos -% removed keyboard statement, thanks to Jurrian -% -% Revision 1.17 2009/07/28 10:17:41 roboos -% make distinction between only label, label+pnt and label+pnt+ori -% -% Revision 1.16 2009/07/27 16:04:51 roboos -% improved distinction between eeg and meg, fixes problem with biosemi-eeg being detected as "ctf" due to reference channel match -% -% Revision 1.15 2009/06/19 16:51:50 vlalit -% Added biosemi64 system of Diane Whitmer, I don't know how generic it is. -% -% Revision 1.14 2009/05/07 13:34:09 roboos -% added ctf64 -% -% Revision 1.13 2009/04/01 06:51:43 roboos -% implemented caching for the type detection in case the same input is given multiple times -% this uses a persistent variable -% -% Revision 1.12 2009/03/06 08:50:23 roboos -% added handling of plexon header -% -% Revision 1.11 2009/02/02 16:27:41 roboos -% changed order of detecting sens.grad/elec on Vladimirs request, don't know why -% -% Revision 1.10 2008/09/10 09:12:11 roboos -% added alternative definition of channel names without a space in the label for neuromag 122 and 306 -% -% Revision 1.9 2008/09/10 07:53:27 roboos -% moved definition of channel label sets to seperate function -% -% Revision 1.8 2008/03/18 13:40:27 roboos -% added quick fix for ctf275_planar, the problem is that one channel is missing from the ctf275 list (i.e. it is only 274 long) -% -% Revision 1.7 2008/03/18 12:25:06 roboos -% use sens.type if available, this requires that the content of sens.type is consistent with the strings returned by this function -% preallocate cell-arrays -% -% Revision 1.6 2008/02/29 15:25:31 roboos -% fixed bug for eeg (thanks to Doug), updated documentation -% -% Revision 1.5 2008/02/29 14:04:42 roboos -% added gradiometers to btiref -% added general types to the checks at the end -% -% Revision 1.4 2008/02/29 13:52:12 roboos -% added bti248 and planar -% changed order of arguments for ismember, needed when a lot of EEG channels are present in ctf151 -% changed order in which checks are performed, first ctf275 and only then ctf151 -% -% Revision 1.3 2008/02/28 09:16:35 roboos -% fixed bug due to many trigger and headloc channels in ctf275 labels -% -% Revision 1.2 2008/02/27 17:01:54 roboos -% added a whole list of channel names, fixed some bugs -% -% Revision 1.1 2007/07/25 08:31:12 roboos -% implemented new helper function -% - -% these are for remembering the type on subsequent calls with the same input arguments -persistent previous_argin previous_argout - -if nargin<2 - % ensure that all input arguments are defined - desired = []; -end - -current_argin = {input, desired}; -if isequal(current_argin, previous_argin) - % don't do the type detection again, but return the previous values from cache - type = previous_argout{1}; - return -end - -isdata = isa(input, 'struct') && isfield(input, 'hdr') && isfield(input.hdr, 'label'); -isheader = isa(input, 'struct') && isfield(input, 'label') && isfield(input, 'Fs'); -isgrad = isa(input, 'struct') && isfield(input, 'pnt') && isfield(input, 'ori'); -iselec = isa(input, 'struct') && isfield(input, 'pnt') && isfield(input, 'label') && ~isfield(input, 'ori'); -islabel = isa(input, 'cell') && isa(input{1}, 'char'); - -% the input may be a data structure which then contains a grad/elec structure -if isdata - if isfield(input.hdr, 'grad') - sens = input.hdr.grad; - isgrad = true; - elseif isfield(input.hdr, 'elec') - sens = input.hdr.elec; - iselec = true; - else - sens.label = input.hdr.label; - islabel = true; - end -elseif isheader - if isfield(input, 'grad') - sens = input.grad; - isgrad = true; - elseif isfield(input, 'elec') - sens = input.elec; - iselec = true; - else - sens.label = input.label; - islabel = true; - end -elseif isgrad - sens = input; -elseif iselec - sens = input; -elseif islabel - sens.label = input; -else - sens = []; -end - -if isfield(sens, 'type') - % preferably the structure specifies its own type - type = sens.type; - -elseif issubfield(sens, 'orig.FileHeader') && issubfield(sens, 'orig.VarHeader') - % this is a complete header that was read from a Plexon *.nex file using read_plexon_nex - type = 'plexon'; - -else - % start with unknown, then try to determine the proper type by looking at the labels - type = 'unknown'; - - if isgrad - % probably this is MEG, determine the type of magnetometer/gradiometer system - % note that the order here is important: first check whether it matches a 275 channel system, then a 151 channel system, since the 151 channels are a subset of the 275 - if (mean(ismember(senslabel('ctf275'), sens.label)) > 0.8) - type = 'ctf275'; - elseif (mean(ismember(senslabel('ctfheadloc'), sens.label)) > 0.8) % look at the head localization channels - type = 'ctf275'; - elseif (mean(ismember(senslabel('ctf151'), sens.label)) > 0.8) - type = 'ctf151'; - elseif (mean(ismember(senslabel('ctf64'), sens.label)) > 0.8) - type = 'ctf64'; - elseif (mean(ismember(senslabel('ctf275_planar'), sens.label)) > 0.8) - type = 'ctf275_planar'; - elseif (mean(ismember(senslabel('ctf151_planar'), sens.label)) > 0.8) - type = 'ctf151_planar'; - elseif (mean(ismember(senslabel('bti248'), sens.label)) > 0.8) - type = 'bti248'; - elseif (mean(ismember(senslabel('bti148'), sens.label)) > 0.8) - type = 'bti148'; - elseif (mean(ismember(senslabel('bti248_planar'), sens.label)) > 0.8) - type = 'bti248_planar'; - elseif (mean(ismember(senslabel('bti148_planar'), sens.label)) > 0.8) - type = 'bti148_planar'; - elseif (mean(ismember(senslabel('itab153'), sens.label)) > 0.8) - type = 'itab153'; - elseif (mean(ismember(senslabel('itab153_planar'), sens.label)) > 0.8) - type = 'itab153_planar'; - elseif (mean(ismember(senslabel('neuromag306'), sens.label)) > 0.8) - type = 'neuromag306'; - elseif (mean(ismember(senslabel('neuromag306alt'),sens.label)) > 0.8) % an alternative set without spaces in the name - type = 'neuromag306'; - elseif (mean(ismember(senslabel('neuromag122'), sens.label)) > 0.8) - type = 'neuromag122'; - elseif (mean(ismember(senslabel('neuromag122alt'),sens.label)) > 0.8) % an alternative set without spaces in the name - type = 'neuromag122'; - elseif any(ismember(senslabel('btiref'), sens.label)) - type = 'bti'; % it might be 148 or 248 channels - elseif any(ismember(senslabel('ctfref'), sens.label)) - type = 'ctf'; % it might be 151 or 275 channels - elseif isfield(sens, 'pnt') && isfield(sens, 'ori') && numel(sens.label)==numel(sens.pnt) - type = 'magnetometer'; - else - type = 'meg'; - end - - elseif iselec - % probably this is EEG - if (mean(ismember(senslabel('biosemi256'), sens.label)) > 0.8) - type = 'biosemi256'; - elseif (mean(ismember(senslabel('biosemi128'), sens.label)) > 0.8) - type = 'biosemi128'; - elseif (mean(ismember(senslabel('biosemi64'), sens.label)) > 0.8) - type = 'biosemi64'; - elseif (mean(ismember(senslabel('egi256'), sens.label)) > 0.8) - type = 'egi256'; - elseif (mean(ismember(senslabel('egi128'), sens.label)) > 0.8) - type = 'egi128'; - elseif (mean(ismember(senslabel('egi64'), sens.label)) > 0.8) - type = 'egi64'; - elseif (mean(ismember(senslabel('egi32'), sens.label)) > 0.8) - type = 'egi32'; - elseif (sum(ismember(sens.label, senslabel('eeg1005'))) > 10) % Otherwise it's not even worth recognizing - type = 'ext1020'; - else - type = 'electrode'; - end - - elseif islabel - % look only at the channel labels - if (mean(ismember(senslabel('ctf275'), sens.label)) > 0.8) - type = 'ctf275'; - elseif (mean(ismember(senslabel('ctfheadloc'), sens.label)) > 0.8) % look at the head localization channels - type = 'ctf275'; - elseif (mean(ismember(senslabel('ctf151'), sens.label)) > 0.8) - type = 'ctf151'; - elseif (mean(ismember(senslabel('ctf64'), sens.label)) > 0.8) - type = 'ctf64'; - elseif (mean(ismember(senslabel('ctf275_planar'), sens.label)) > 0.8) - type = 'ctf275_planar'; - elseif (mean(ismember(senslabel('ctf151_planar'), sens.label)) > 0.8) - type = 'ctf151_planar'; - elseif (mean(ismember(senslabel('bti248'), sens.label)) > 0.8) - type = 'bti248'; - elseif (mean(ismember(senslabel('bti148'), sens.label)) > 0.8) - type = 'bti148'; - elseif (mean(ismember(senslabel('bti248_planar'), sens.label)) > 0.8) - type = 'bti248_planar'; - elseif (mean(ismember(senslabel('bti148_planar'), sens.label)) > 0.8) - type = 'bti148_planar'; - elseif (mean(ismember(senslabel('itab153'), sens.label)) > 0.8) - type = 'itab153'; - elseif (mean(ismember(senslabel('itab153_planar'), sens.label)) > 0.8) - type = 'itab153_planar'; - elseif (mean(ismember(senslabel('neuromag306'), sens.label)) > 0.8) - type = 'neuromag306'; - elseif (mean(ismember(senslabel('neuromag306alt'),sens.label)) > 0.8) % an alternative set without spaces in the name - type = 'neuromag306'; - elseif (mean(ismember(senslabel('neuromag122'), sens.label)) > 0.8) - type = 'neuromag122'; - elseif (mean(ismember(senslabel('neuromag122alt'),sens.label)) > 0.8) % an alternative set without spaces in the name - type = 'neuromag122'; - elseif (mean(ismember(senslabel('biosemi256'), sens.label)) > 0.8) - type = 'biosemi256'; - elseif (mean(ismember(senslabel('biosemi128'), sens.label)) > 0.8) - type = 'biosemi128'; - elseif (mean(ismember(senslabel('biosemi64'), sens.label)) > 0.8) - type = 'biosemi64'; - elseif (mean(ismember(senslabel('egi256'), sens.label)) > 0.8) - type = 'egi256'; - elseif (mean(ismember(senslabel('egi128'), sens.label)) > 0.8) - type = 'egi128'; - elseif (mean(ismember(senslabel('egi64'), sens.label)) > 0.8) - type = 'egi64'; - elseif (mean(ismember(senslabel('egi32'), sens.label)) > 0.8) - type = 'egi32'; - elseif (sum(ismember(sens.label, senslabel('eeg1005'))) > 10) % Otherwise it's not even worth recognizing - type = 'ext1020'; - elseif any(ismember(senslabel('btiref'), sens.label)) - type = 'bti'; % it might be 148 or 248 channels - elseif any(ismember(senslabel('ctfref'), sens.label)) - type = 'ctf'; % it might be 151 or 275 channels - end - - end % look at label, ori and/or pnt -end % if isfield(sens, 'type') - -if ~isempty(desired) - % return a boolean flag - switch desired - case 'eeg' - type = any(strcmp(type, {'eeg' 'electrode' 'biosemi64' 'biosemi128' 'biosemi256' 'egi32' 'egi64' 'egi128' 'egi256' 'ext1020'})); - case 'biosemi' - type = any(strcmp(type, {'biosemi64' 'biosemi128' 'biosemi256'})); - case 'egi' - type = any(strcmp(type, {'egi64' 'egi128' 'egi256'})); - case 'meg' - type = any(strcmp(type, {'meg' 'magnetometer' 'ctf' 'bti' 'ctf151' 'ctf275' 'ctf151_planar' 'ctf275_planar' 'neuromag122' 'neuromag306' 'bti148' 'bti148_planar' 'bti248' 'bti248_planar' 'yokogawa160' 'yokogawa160_planar'})); - case 'ctf' - type = any(strcmp(type, {'ctf' 'ctf151' 'ctf275' 'ctf151_planar' 'ctf275_planar'})); - case 'bti' - type = any(strcmp(type, {'bti' 'bti148' 'bti148_planar' 'bti248' 'bti248_planar'})); - case 'neuromag' - type = any(strcmp(type, {'neuromag122' 'neuromag306'})); - case 'yokogawa' - type = any(strcmp(type, {'yokogawa160' 'yokogawa160_planar'})); - case 'itab' - type = any(strcmp(type, {'itab153' 'itab153_planar'})); - case 'meg_axial' - % note that neuromag306 is mixed planar and axial - type = any(strcmp(type, {'magnetometer' 'neuromag306' 'ctf151' 'ctf275' 'bti148' 'bti248' 'yokogawa160'})); - case 'meg_planar' - % note that neuromag306 is mixed planar and axial - type = any(strcmp(type, {'neuromag122' 'neuromag306' 'ctf151_planar' 'ctf275_planar' 'bti148_planar' 'bti248_planar' 'yokogawa160_planar'})); - otherwise - type = any(strcmp(type, desired)); - end % switch desired -end % detemine the correspondence to the desired type - -% remember the current input and output arguments, so that they can be -% reused on a subsequent call in case the same input argument is given -current_argout = {type}; -if isempty(previous_argin) - previous_argin = current_argin; - previous_argout = current_argout; -end - -return % senstype main() diff --git a/external/fileio/private/setsubfield.m b/external/fileio/private/setsubfield.m deleted file mode 100644 index 8b53257..0000000 --- a/external/fileio/private/setsubfield.m +++ /dev/null @@ -1,36 +0,0 @@ -function [s] = setsubfield(s, f, v); - -% SETSUBFIELD sets the contents of the specified field to a specified value -% just like the standard Matlab SETFIELD function, except that you can also -% specify nested fields using a '.' in the fieldname. The nesting can be -% arbitrary deep. -% -% Use as -% s = setsubfield(s, 'fieldname', value) -% or as -% s = setsubfield(s, 'fieldname.subfieldname', value) -% -% See also SETFIELD, GETSUBFIELD, ISSUBFIELD - -% Copyright (C) 2005, Robert Oostenveld -% -% $Log: setsubfield.m,v $ -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.1 2005/02/08 09:30:18 roboos -% new implementations to make it easier to work with nested structures -% - -if ~isstr(f) - error('incorrect input argument for fieldname'); -end - -t = {}; -while (1) - [t{end+1}, f] = strtok(f, '.'); - if isempty(f) - break - end -end -s = setfield(s, t{:}, v); diff --git a/external/fileio/private/timestamp_neuralynx.m b/external/fileio/private/timestamp_neuralynx.m deleted file mode 100644 index 17cacf5..0000000 --- a/external/fileio/private/timestamp_neuralynx.m +++ /dev/null @@ -1,22 +0,0 @@ -function [ts] = timestamp_neuralynx(tsl, tsh); - -% TIMESTAMP_NEURALYNX merge the low and high part of Neuralynx timestamps -% into a single uint64 value - -if ~isa(tsl, 'uint32') - error('invalid input'); -elseif ~isa(tsh, 'uint32') - error('invalid input'); -end - -% convert the 32 bit low and 32 bit high timestamp into a 64 bit integer -dum = zeros(2, length(tsh), 'uint32'); -if littleendian - dum(1,:) = tsl; - dum(2,:) = tsh; -else - dum(1,:) = tsh; - dum(2,:) = tsl; -end - -ts = typecast(dum(:), 'uint64'); diff --git a/external/fileio/private/timestamp_plexon.m b/external/fileio/private/timestamp_plexon.m deleted file mode 100644 index c019daa..0000000 --- a/external/fileio/private/timestamp_plexon.m +++ /dev/null @@ -1,33 +0,0 @@ -function [ts] = timestamp_plexon(tsl, tsh); - -% TIMESTAMP_PLEXON merge the low and high part of the timestamps -% into a single uint64 value - -if ~isa(tsl, 'uint32') - error('invalid input'); -elseif ~isa(tsh, 'uint16') - error('invalid input'); -end - -% convert the 16 bit high timestamp into a 32 bit integer -dum = zeros(2, length(tsh), 'uint16'); -if littleendian - dum(1,:) = tsh(:); -else - dum(2,:) = tsh(:); -end -tsh = typecast(dum(:), 'uint32'); - -% convert the 32 bit low and 32 bit high timestamp into a 64 bit integer -dum = zeros(2, length(tsh), 'uint32'); -if littleendian - dum(1,:) = tsl; - dum(2,:) = tsh; -else - dum(1,:) = tsh; - dum(2,:) = tsl; -end - -ts = typecast(dum(:), 'uint64'); -ts = reshape(ts, size(tsl)); - diff --git a/external/fileio/private/tokenize.m b/external/fileio/private/tokenize.m deleted file mode 100644 index 5cfbaca..0000000 --- a/external/fileio/private/tokenize.m +++ /dev/null @@ -1,69 +0,0 @@ -function [tok] = tokenize(str, sep, rep) - -% TOKENIZE cuts a string into pieces, returning the pieces in a cell array -% -% Use as -% t = tokenize(str) -% t = tokenize(str, sep) -% t = tokenize(str, sep, rep) -% where -% str = the string that you want to cut into pieces -% sep = the separator at which to cut (default is whitespace) -% rep = whether to treat repeating seperator characters as one (default is false) -% -% With the optional boolean flag "rep" you can specify whether repeated -% seperator characters should be squeezed together (e.g. multiple -% spaces between two words). The default is rep=1, i.e. repeated -% seperators are treated as one. -% -% See also STRTOK, TEXTSCAN - -% Copyright (C) 2003-2008, Robert Oostenveld -% -% $Log: tokenize.m,v $ -% Revision 1.3 2008/11/20 15:46:04 roboos -% fixed bug in the default for the 3rd argument (whether repeated seperators should be treated as one). This bug caused some trouble with reading brainvision header files over the last two weeks. -% -% Revision 1.2 2008/11/14 07:37:05 roboos -% use whitespace if no seperator is specified -% -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.5 2006/05/10 07:15:22 roboos -% allow for squeezing multiple separators into one -% -% Revision 1.4 2006/01/30 14:56:41 roboos -% fixed another stupid bug in previous cvs commit -% -% Revision 1.3 2006/01/30 14:55:44 roboos -% fixed stupid bug in previous cvs commit -% -% Revision 1.2 2006/01/30 13:38:18 roboos -% replaced dependency on strtok by more simple code -% changed from dos to unix -% -% Revision 1.1 2005/05/23 13:47:51 roboos -% old implementation, new addition to CVS for fieldtrip release -% - -if nargin<2 - sep = [9:13 32]; % White space characters -end - -if nargin<3 - rep = false; -end - -tok = {}; -f = find(ismember(str, sep)); -f = [0, f, length(str)+1]; -for i=1:(length(f)-1) - tok{i} = str((f(i)+1):(f(i+1)-1)); -end - -if rep - % remove empty cells, which occur if the separator is repeated (e.g. multiple spaces) - tok(cellfun('isempty', tok))=[]; -end - diff --git a/external/fileio/private/voltype.m b/external/fileio/private/voltype.m deleted file mode 100644 index c707aa6..0000000 --- a/external/fileio/private/voltype.m +++ /dev/null @@ -1,115 +0,0 @@ -function [type] = voltype(vol, desired) - -% VOLTYPE determines the type of volume conduction model -% -% Use as -% [type] = voltype(vol) -% to get a string describing the type, or -% [flag] = voltype(vol, desired) -% to get a boolean value. -% -% See also READ_VOL, COMPUTE_LEADFIELD - -% Copyright (C) 2007-2008, Robert Oostenveld -% -% $Log: voltype.m,v $ -% Revision 1.4 2009/04/01 06:51:43 roboos -% implemented caching for the type detection in case the same input is given multiple times -% this uses a persistent variable -% -% Revision 1.3 2009/02/02 13:05:22 roboos -% small fix in cpbem->bemcp -% -% Revision 1.2 2009/02/02 12:58:27 roboos -% added bemcp implementation -% -% Revision 1.1 2009/01/21 10:32:38 roboos -% moved from forwinv/* and forwinv/mex/* directory to forwinv/private/* to make the CVS layout consistent with the release version -% -% Revision 1.7 2008/04/30 13:40:34 roboos -% improved detection concentric eeg -% -% Revision 1.6 2008/04/16 08:04:33 roboos -% be flexible in determining whether it is bem -% -% Revision 1.5 2008/04/14 19:31:05 roboos -% return 'unknown' if the type cannot be determined -% -% Revision 1.4 2008/04/10 10:59:38 roboos -% better detection of multisphere meg (after preparing) -% -% Revision 1.3 2008/03/18 12:39:24 roboos -% change in comment, nothing functional -% -% Revision 1.2 2008/03/05 15:24:44 roboos -% changed the detection of various spherical models, added infinite vacuum -% -% Revision 1.1 2007/07/25 08:31:12 roboos -% implemented new helper function -% - -% these are for remembering the type on subsequent calls with the same input arguments -persistent previous_argin previous_argout - -if nargin<2 - % ensure that all input arguments are defined - desired = []; -end - -current_argin = {vol, desired}; -if isequal(current_argin, previous_argin) - % don't do the type detection again, but return the previous values from cache - type = previous_argout{1}; - return -end - -if isfield(vol, 'type') - % preferably the structure specifies its own type - type = vol.type; - -elseif isfield(vol, 'r') && numel(vol.r)==1 && ~isfield(vol, 'label') - type = 'singlesphere'; - -elseif isfield(vol, 'r') && isfield(vol, 'o') && isfield(vol, 'label') - % this is before the spheres have been assigned to the coils - % and every sphere is still associated with a channel - type = 'multisphere'; - -elseif isfield(vol, 'r') && isfield(vol, 'o') && size(vol.r,1)==size(vol.o,1) && size(vol.r,1)>4 - % this is after the spheres have been assigned to the coils - % note that this one is easy to confuse with the concentric one - type = 'multisphere'; - -elseif isfield(vol, 'r') && numel(vol.r)>=2 && ~isfield(vol, 'label') - type = 'concentric'; - -elseif isfield(vol, 'bnd') - type = 'bem'; - -elseif isempty(vol) - type = 'infinite'; - -else - type = 'unknown'; - -end % if isfield(vol, 'type') - -if ~isempty(desired) - % return a boolean flag - switch desired - case 'bem' - type = any(strcmp(type, {'bem', 'dipoli', 'asa', 'avo', 'bemcp'})); - otherwise - type = any(strcmp(type, desired)); - end -end - -% remember the current input and output arguments, so that they can be -% reused on a subsequent call in case the same input argument is given -current_argout = {type}; -if isempty(previous_argin) - previous_argin = current_argin; - previous_argout = current_argout; -end - -return % voltype main() diff --git a/external/fileio/private/warp_apply.m b/external/fileio/private/warp_apply.m deleted file mode 100644 index f7a8af7..0000000 --- a/external/fileio/private/warp_apply.m +++ /dev/null @@ -1,187 +0,0 @@ -function [warped] = warp_apply(M, input, method); - -% WARP_APPLY performs a 3D linear or nonlinear transformation on the input -% coordinates, similar to those in AIR 3.08. You can find technical -% documentation on warping in general at http://bishopw.loni.ucla.edu/AIR3 -% -% Use as -% [warped] = warp_apply(M, input, method) -% where -% M vector or matrix with warping parameters -% input Nx3 matrix with coordinates -% warped Nx3 matrix with coordinates -% method string describing the warping method -% -% The methods 'nonlin0', 'nonlin2' ... 'nonlin5' specify a -% polynomial transformation. The size of the transformation matrix -% depends on the order of the warp -% zeroth order : 1 parameter per coordinate (translation) -% first order : 4 parameters per coordinate (total 12, affine) -% second order : 10 parameters per coordinate -% third order : 20 parameters per coordinate -% fourth order : 35 parameters per coordinate -% fifth order : 56 parameters per coordinate (total 168) -% The size of M should be 3xP, where P is the number of parameters -% per coordinate. Alternatively, you can specify the method to be -% 'nonlinear', where the order will be determined from teh size of -% the matrix M. -% -% If the method 'homogeneous' is selected, the input matrix M should be -% a 4x4 homogenous transformation matrix. -% -% If any other method is selected, it is assumed that it specifies -% the name of an auxiliary function that will, when given the input -% parameter vector M, return an 4x4 homogenous transformation -% matrix. Supplied functions in teh warping toolbox are translate, -% rotate, scale, rigidbody, globalrescale, traditional, affine, -% perspective. - -% Copyright (C) 2000-2005, Robert Oostenveld -% -% This program is free software; you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation; either version 2 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program; if not, write to the Free Software -% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -% $Log: warp_apply.m,v $ -% Revision 1.3 2009/04/16 12:58:37 roboos -% allow for 2D input points, the output will also be 2D but the computations are done in 3D -% allow for 2D homogenous transformation matrix -% -% Revision 1.2 2006/09/13 09:47:41 roboos -% auto-detect homogeneous transformation if method not given -% -% Revision 1.1 2005/08/15 08:10:07 roboos -% renamed warp3d into warp_apply -% -% Revision 1.5 2005/03/21 15:35:38 roboos -% added support for nonlin0 up to nonlin5 as method-string (equivalent to nonlinear) -% extended help, added some comments and error checks -% -% Revision 1.4 2004/05/19 09:57:07 roberto -% added GPL copyright statement, added CVS log item -% -% Revision 1.3 2004/05/19 09:48:01 roberto -% *** empty log message *** -% -% Revision 1.2 2003/03/12 16:07:18 roberto -% improved help documentation -% - -if nargin<3 && all(size(M)==4) - % no specific transformation mode has been selected - % it looks like a homogenous transformation matrix - method = 'homogenous'; -elseif nargin<3 - % the default method is 'nonlinear' - method = 'nonlinear'; -end - -if size(input,2)==2 - % convert the input points from 2D to 3D representation - input(:,3) = 0; - input3d = false; -else - input3d = true; -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% nonlinear warping -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if any(strcmp(method, {'nonlinear', 'nonlin0', 'nonlin1', 'nonlin2', 'nonlin3', 'nonlin4', 'nonlin5'})) - x = input(:,1); - y = input(:,2); - z = input(:,3); - s = size(M); - - if s(1)~=3 - error('invalid size of nonlinear transformation matrix'); - elseif strcmp(method, 'nonlin0') & s(2)~=1 - error('invalid size of nonlinear transformation matrix'); - elseif strcmp(method, 'nonlin1') & s(2)~=4 - error('invalid size of nonlinear transformation matrix'); - elseif strcmp(method, 'nonlin2') & s(2)~=10 - error('invalid size of nonlinear transformation matrix'); - elseif strcmp(method, 'nonlin3') & s(2)~=20 - error('invalid size of nonlinear transformation matrix'); - elseif strcmp(method, 'nonlin4') & s(2)~=35 - error('invalid size of nonlinear transformation matrix'); - elseif strcmp(method, 'nonlin5') & s(2)~=56 - error('invalid size of nonlinear transformation matrix'); - end - - if s(2)==1 - % this is a translation, which in a strict sense is not the 0th order nonlinear transformation - xx = M(1,1) + x; - yy = M(2,1) + y; - zz = M(3,1) + z; - elseif s(2)==4 - xx = M(1,1) + M(1,2)*x + M(1,3)*y + M(1,4)*z; - yy = M(2,1) + M(2,2)*x + M(2,3)*y + M(2,4)*z; - zz = M(3,1) + M(3,2)*x + M(3,3)*y + M(3,4)*z; - elseif s(2)==10 - xx = M(1,1) + M(1,2)*x + M(1,3)*y + M(1,4)*z + M(1,5)*x.*x + M(1,6)*x.*y + M(1,7)*x.*z + M(1,8)*y.*y + M(1,9)*y.*z + M(1,10)*z.*z; - yy = M(2,1) + M(2,2)*x + M(2,3)*y + M(2,4)*z + M(2,5)*x.*x + M(2,6)*x.*y + M(2,7)*x.*z + M(2,8)*y.*y + M(2,9)*y.*z + M(2,10)*z.*z; - zz = M(3,1) + M(3,2)*x + M(3,3)*y + M(3,4)*z + M(3,5)*x.*x + M(3,6)*x.*y + M(3,7)*x.*z + M(3,8)*y.*y + M(3,9)*y.*z + M(3,10)*z.*z; - elseif s(2)==20 - xx = M(1,1) + M(1,2)*x + M(1,3)*y + M(1,4)*z + M(1,5)*x.*x + M(1,6)*x.*y + M(1,7)*x.*z + M(1,8)*y.*y + M(1,9)*y.*z + M(1,10)*z.*z + M(1,11)*x.*x.*x + M(1,12)*x.*x.*y + M(1,13)*x.*x.*z + M(1,14)*x.*y.*y + M(1,15)*x.*y.*z + M(1,16)*x.*z.*z + M(1,17)*y.*y.*y + M(1,18)*y.*y.*z + M(1,19)*y.*z.*z + M(1,20)*z.*z.*z; - yy = M(2,1) + M(2,2)*x + M(2,3)*y + M(2,4)*z + M(2,5)*x.*x + M(2,6)*x.*y + M(2,7)*x.*z + M(2,8)*y.*y + M(2,9)*y.*z + M(2,10)*z.*z + M(2,11)*x.*x.*x + M(2,12)*x.*x.*y + M(2,13)*x.*x.*z + M(2,14)*x.*y.*y + M(2,15)*x.*y.*z + M(2,16)*x.*z.*z + M(2,17)*y.*y.*y + M(2,18)*y.*y.*z + M(2,19)*y.*z.*z + M(2,20)*z.*z.*z; - zz = M(3,1) + M(3,2)*x + M(3,3)*y + M(3,4)*z + M(3,5)*x.*x + M(3,6)*x.*y + M(3,7)*x.*z + M(3,8)*y.*y + M(3,9)*y.*z + M(3,10)*z.*z + M(3,11)*x.*x.*x + M(3,12)*x.*x.*y + M(3,13)*x.*x.*z + M(3,14)*x.*y.*y + M(3,15)*x.*y.*z + M(3,16)*x.*z.*z + M(3,17)*y.*y.*y + M(3,18)*y.*y.*z + M(3,19)*y.*z.*z + M(3,20)*z.*z.*z; - elseif s(2)==35 - xx = M(1,1) + M(1,2)*x + M(1,3)*y + M(1,4)*z + M(1,5)*x.*x + M(1,6)*x.*y + M(1,7)*x.*z + M(1,8)*y.*y + M(1,9)*y.*z + M(1,10)*z.*z + M(1,11)*x.*x.*x + M(1,12)*x.*x.*y + M(1,13)*x.*x.*z + M(1,14)*x.*y.*y + M(1,15)*x.*y.*z + M(1,16)*x.*z.*z + M(1,17)*y.*y.*y + M(1,18)*y.*y.*z + M(1,19)*y.*z.*z + M(1,20)*z.*z.*z + M(1,21)*x.*x.*x.*x + M(1,22)*x.*x.*x.*y + M(1,23)*x.*x.*x.*z + M(1,24)*x.*x.*y.*y + M(1,25)*x.*x.*y.*z + M(1,26)*x.*x.*z.*z + M(1,27)*x.*y.*y.*y + M(1,28)*x.*y.*y.*z + M(1,29)*x.*y.*z.*z + M(1,30)*x.*z.*z.*z + M(1,31)*y.*y.*y.*y + M(1,32)*y.*y.*y.*z + M(1,33)*y.*y.*z.*z + M(1,34)*y.*z.*z.*z + M(1,35)*z.*z.*z.*z; - yy = M(2,1) + M(2,2)*x + M(2,3)*y + M(2,4)*z + M(2,5)*x.*x + M(2,6)*x.*y + M(2,7)*x.*z + M(2,8)*y.*y + M(2,9)*y.*z + M(2,10)*z.*z + M(2,11)*x.*x.*x + M(2,12)*x.*x.*y + M(2,13)*x.*x.*z + M(2,14)*x.*y.*y + M(2,15)*x.*y.*z + M(2,16)*x.*z.*z + M(2,17)*y.*y.*y + M(2,18)*y.*y.*z + M(2,19)*y.*z.*z + M(2,20)*z.*z.*z + M(2,21)*x.*x.*x.*x + M(2,22)*x.*x.*x.*y + M(2,23)*x.*x.*x.*z + M(2,24)*x.*x.*y.*y + M(2,25)*x.*x.*y.*z + M(2,26)*x.*x.*z.*z + M(2,27)*x.*y.*y.*y + M(2,28)*x.*y.*y.*z + M(2,29)*x.*y.*z.*z + M(2,30)*x.*z.*z.*z + M(2,31)*y.*y.*y.*y + M(2,32)*y.*y.*y.*z + M(2,33)*y.*y.*z.*z + M(2,34)*y.*z.*z.*z + M(2,35)*z.*z.*z.*z; - zz = M(3,1) + M(3,2)*x + M(3,3)*y + M(3,4)*z + M(3,5)*x.*x + M(3,6)*x.*y + M(3,7)*x.*z + M(3,8)*y.*y + M(3,9)*y.*z + M(3,10)*z.*z + M(3,11)*x.*x.*x + M(3,12)*x.*x.*y + M(3,13)*x.*x.*z + M(3,14)*x.*y.*y + M(3,15)*x.*y.*z + M(3,16)*x.*z.*z + M(3,17)*y.*y.*y + M(3,18)*y.*y.*z + M(3,19)*y.*z.*z + M(3,20)*z.*z.*z + M(3,21)*x.*x.*x.*x + M(3,22)*x.*x.*x.*y + M(3,23)*x.*x.*x.*z + M(3,24)*x.*x.*y.*y + M(3,25)*x.*x.*y.*z + M(3,26)*x.*x.*z.*z + M(3,27)*x.*y.*y.*y + M(3,28)*x.*y.*y.*z + M(3,29)*x.*y.*z.*z + M(3,30)*x.*z.*z.*z + M(3,31)*y.*y.*y.*y + M(3,32)*y.*y.*y.*z + M(3,33)*y.*y.*z.*z + M(3,34)*y.*z.*z.*z + M(3,35)*z.*z.*z.*z; - elseif s(2)==56 - xx = M(1,1) + M(1,2)*x + M(1,3)*y + M(1,4)*z + M(1,5)*x.*x + M(1,6)*x.*y + M(1,7)*x.*z + M(1,8)*y.*y + M(1,9)*y.*z + M(1,10)*z.*z + M(1,11)*x.*x.*x + M(1,12)*x.*x.*y + M(1,13)*x.*x.*z + M(1,14)*x.*y.*y + M(1,15)*x.*y.*z + M(1,16)*x.*z.*z + M(1,17)*y.*y.*y + M(1,18)*y.*y.*z + M(1,19)*y.*z.*z + M(1,20)*z.*z.*z + M(1,21)*x.*x.*x.*x + M(1,22)*x.*x.*x.*y + M(1,23)*x.*x.*x.*z + M(1,24)*x.*x.*y.*y + M(1,25)*x.*x.*y.*z + M(1,26)*x.*x.*z.*z + M(1,27)*x.*y.*y.*y + M(1,28)*x.*y.*y.*z + M(1,29)*x.*y.*z.*z + M(1,30)*x.*z.*z.*z + M(1,31)*y.*y.*y.*y + M(1,32)*y.*y.*y.*z + M(1,33)*y.*y.*z.*z + M(1,34)*y.*z.*z.*z + M(1,35)*z.*z.*z.*z + M(1,36)*x.*x.*x.*x.*x + M(1,37)*x.*x.*x.*x.*y + M(1,38)*x.*x.*x.*x.*z + M(1,39)*x.*x.*x.*y.*y + M(1,40)*x.*x.*x.*y.*z + M(1,41)*x.*x.*x.*z.*z + M(1,42)*x.*x.*y.*y.*y + M(1,43)*x.*x.*y.*y.*z + M(1,44)*x.*x.*y.*z.*z + M(1,45)*x.*x.*z.*z.*z + M(1,46)*x.*y.*y.*y.*y + M(1,47)*x.*y.*y.*y.*z + M(1,48)*x.*y.*y.*z.*z + M(1,49)*x.*y.*z.*z.*z + M(1,50)*x.*z.*z.*z.*z + M(1,51)*y.*y.*y.*y.*y + M(1,52)*y.*y.*y.*y.*z + M(1,53)*y.*y.*y.*z.*z + M(1,54)*y.*y.*z.*z.*z + M(1,55)*y.*z.*z.*z.*z + M(1,56)*z.*z.*z.*z.*z; - yy = M(2,1) + M(2,2)*x + M(2,3)*y + M(2,4)*z + M(2,5)*x.*x + M(2,6)*x.*y + M(2,7)*x.*z + M(2,8)*y.*y + M(2,9)*y.*z + M(2,10)*z.*z + M(2,11)*x.*x.*x + M(2,12)*x.*x.*y + M(2,13)*x.*x.*z + M(2,14)*x.*y.*y + M(2,15)*x.*y.*z + M(2,16)*x.*z.*z + M(2,17)*y.*y.*y + M(2,18)*y.*y.*z + M(2,19)*y.*z.*z + M(2,20)*z.*z.*z + M(2,21)*x.*x.*x.*x + M(2,22)*x.*x.*x.*y + M(2,23)*x.*x.*x.*z + M(2,24)*x.*x.*y.*y + M(2,25)*x.*x.*y.*z + M(2,26)*x.*x.*z.*z + M(2,27)*x.*y.*y.*y + M(2,28)*x.*y.*y.*z + M(2,29)*x.*y.*z.*z + M(2,30)*x.*z.*z.*z + M(2,31)*y.*y.*y.*y + M(2,32)*y.*y.*y.*z + M(2,33)*y.*y.*z.*z + M(2,34)*y.*z.*z.*z + M(2,35)*z.*z.*z.*z + M(2,36)*x.*x.*x.*x.*x + M(2,37)*x.*x.*x.*x.*y + M(2,38)*x.*x.*x.*x.*z + M(2,39)*x.*x.*x.*y.*y + M(2,40)*x.*x.*x.*y.*z + M(2,41)*x.*x.*x.*z.*z + M(2,42)*x.*x.*y.*y.*y + M(2,43)*x.*x.*y.*y.*z + M(2,44)*x.*x.*y.*z.*z + M(2,45)*x.*x.*z.*z.*z + M(2,46)*x.*y.*y.*y.*y + M(2,47)*x.*y.*y.*y.*z + M(2,48)*x.*y.*y.*z.*z + M(2,49)*x.*y.*z.*z.*z + M(2,50)*x.*z.*z.*z.*z + M(2,51)*y.*y.*y.*y.*y + M(2,52)*y.*y.*y.*y.*z + M(2,53)*y.*y.*y.*z.*z + M(2,54)*y.*y.*z.*z.*z + M(2,55)*y.*z.*z.*z.*z + M(2,56)*z.*z.*z.*z.*z; - zz = M(3,1) + M(3,2)*x + M(3,3)*y + M(3,4)*z + M(3,5)*x.*x + M(3,6)*x.*y + M(3,7)*x.*z + M(3,8)*y.*y + M(3,9)*y.*z + M(3,10)*z.*z + M(3,11)*x.*x.*x + M(3,12)*x.*x.*y + M(3,13)*x.*x.*z + M(3,14)*x.*y.*y + M(3,15)*x.*y.*z + M(3,16)*x.*z.*z + M(3,17)*y.*y.*y + M(3,18)*y.*y.*z + M(3,19)*y.*z.*z + M(3,20)*z.*z.*z + M(3,21)*x.*x.*x.*x + M(3,22)*x.*x.*x.*y + M(3,23)*x.*x.*x.*z + M(3,24)*x.*x.*y.*y + M(3,25)*x.*x.*y.*z + M(3,26)*x.*x.*z.*z + M(3,27)*x.*y.*y.*y + M(3,28)*x.*y.*y.*z + M(3,29)*x.*y.*z.*z + M(3,30)*x.*z.*z.*z + M(3,31)*y.*y.*y.*y + M(3,32)*y.*y.*y.*z + M(3,33)*y.*y.*z.*z + M(3,34)*y.*z.*z.*z + M(3,35)*z.*z.*z.*z + M(3,36)*x.*x.*x.*x.*x + M(3,37)*x.*x.*x.*x.*y + M(3,38)*x.*x.*x.*x.*z + M(3,39)*x.*x.*x.*y.*y + M(3,40)*x.*x.*x.*y.*z + M(3,41)*x.*x.*x.*z.*z + M(3,42)*x.*x.*y.*y.*y + M(3,43)*x.*x.*y.*y.*z + M(3,44)*x.*x.*y.*z.*z + M(3,45)*x.*x.*z.*z.*z + M(3,46)*x.*y.*y.*y.*y + M(3,47)*x.*y.*y.*y.*z + M(3,48)*x.*y.*y.*z.*z + M(3,49)*x.*y.*z.*z.*z + M(3,50)*x.*z.*z.*z.*z + M(3,51)*y.*y.*y.*y.*y + M(3,52)*y.*y.*y.*y.*z + M(3,53)*y.*y.*y.*z.*z + M(3,54)*y.*y.*z.*z.*z + M(3,55)*y.*z.*z.*z.*z + M(3,56)*z.*z.*z.*z.*z; - else - error('invalid size of nonlinear transformation matrix'); - end - - warped = [xx yy zz]; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % linear warping using homogenous coordinate transformation matrix - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif strcmp(method, 'homogenous') || strcmp(method, 'homogeneous') - if all(size(M)==3) - % convert the 3x3 homogenous transformation matrix (corresponding with 2D) - % into a 4x4 homogenous transformation matrix (corresponding with 3D) - M = [ - M(1,1) M(1,2) 0 M(1,3) - M(2,1) M(2,2) 0 M(2,3) - 0 0 0 0 - M(3,1) M(3,2) 0 M(3,3) - ]; - end - - warped = M * [input'; ones(1, size(input, 1))]; - warped = warped(1:3,:)'; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % using external function that returns a homogenous transformation matrix - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif exist(method, 'file') - % get the homogenous transformation matrix - H = feval(method, M); - warped = warp_apply(H, input, 'homogenous'); - -else - error('unrecognized transformation method'); -end - -if ~input3d - % convert from 3D back to 2D representation - warped = warped(:,1:2); -end - diff --git a/external/fileio/private/write_brainvision_eeg.m b/external/fileio/private/write_brainvision_eeg.m deleted file mode 100644 index 23a5aa0..0000000 --- a/external/fileio/private/write_brainvision_eeg.m +++ /dev/null @@ -1,95 +0,0 @@ -function write_brainvision_eeg(filename, hdr, dat); - -% WRITE_BRAINVISION_EEG exports continuous EEG data to a BrainVision *.eeg -% and corresponding *.vhdr file. The samples in the exported file are -% multiplexed and stored in ieee-le float32 format. -% -% Use as -% write_brainvision_eeg(filename, hdr, dat) -% -% See also READ_BRAINVISION_EEG, READ_BRAINVISION_VHDR, READ_BRAINVISION_VMRK - -% Copyright (C) 2007, Robert Oostenveld -% -% $Log: write_brainvision_eeg.m,v $ -% Revision 1.1 2009/01/14 09:12:16 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.2 2007/07/23 14:37:58 roboos -% fixed channel count for multi-trial data -% -% Revision 1.1 2007/06/13 08:07:32 roboos -% initial implementation -% - -if length(size(dat))>2 - ntrl = size(dat,1); - nchan = size(dat,2); - nsmp = size(dat,3); -else - nchan = size(dat,1); - nsmp = size(dat,2); -end - -if hdr.nChans~=nchan - error('number of channels in in header does not match with the data'); -end - -% this is the only supported data format -hdr.DataFormat = 'BINARY'; -hdr.DataOrientation = 'MULTIPLEXED'; -hdr.BinaryFormat = 'IEEE_FLOAT_32'; -hdr.resolution = ones(size(hdr.label)); % no additional calibration needed, since float32 - -% determine the filenames -[p, f, x] = fileparts(filename); -headerfile = fullfile(p, [f '.vhdr']); -datafile = fullfile(p, [f '.eeg']); -markerfile = ''; - -% open the data file and write the binary data -fid = fopen(datafile, 'wb', 'ieee-le'); -if length(size(dat))>2 - warning('writing segmented data as if it were continuous'); - for i=1:ntrl - fwrite(fid, squeeze(dat(i,:,:)), 'float32'); - end -else - fwrite(fid, dat, 'float32'); -end - -fclose(fid); - -% open the header file and write the ascii header information -fid = fopen(headerfile, 'wt'); -fprintf(fid, 'Brain Vision Data Exchange Header File Version 1.0\n'); -fprintf(fid, '; Data created by FieldTrip\n'); -fprintf(fid, '\n'); -fprintf(fid, '[Common Infos]\n'); -fprintf(fid, 'DataFile=%s\n', datafile); -if ~isempty(markerfile) - fprintf(fid, 'MarkerFile=%s\n', markerfile); -end -fprintf(fid, 'DataFormat=%s\n', hdr.DataFormat); -fprintf(fid, 'DataOrientation=%s\n', hdr.DataOrientation); -fprintf(fid, 'NumberOfChannels=%d\n', hdr.nChans); -% Sampling interval in microseconds -fprintf(fid, 'SamplingInterval=%d\n', round(1e6/hdr.Fs)); -fprintf(fid, '\n'); -fprintf(fid, '[Binary Infos]\n'); -fprintf(fid, 'BinaryFormat=%s\n', hdr.BinaryFormat); -fprintf(fid, '\n'); -fprintf(fid, '[Channel Infos]\n'); -% Each entry: Ch=,,,... -% Fields are delimited by commas, some fields might be omitted (empty). -% Commas in channel names should be coded as "\1", but are not supported here -for i=1:hdr.nChans - fprintf(fid, 'Ch%d=%s,,%g\n', i, hdr.label{i}, hdr.resolution(i)); -end -fclose(fid); - diff --git a/external/fileio/private/write_ctf_shm.m b/external/fileio/private/write_ctf_shm.m deleted file mode 100644 index 0d0a091..0000000 --- a/external/fileio/private/write_ctf_shm.m +++ /dev/null @@ -1,42 +0,0 @@ -function [varargout] = funname(varargin) - -% WRITE_CTF_SHM writes metainformation and data as a packet to shared memory. -% This function can be used for real-time processing of data while it is -% being acquired. -% -% Use as -% write_ctf_shm(msgType, msgId, sampleNumber, numSamples, numChannels, data); -% -% See also READ_CTF_SHM - -% remember the original working directory -pwdir = pwd; - -% determine the name and full path of this function -funname = mfilename('fullpath'); -mexsrc = [funname '.c']; -[mexdir, mexname] = fileparts(funname); - -try - % try to compile the mex file on the fly - warning('trying to compile MEX file from %s', mexsrc); - cd(mexdir); - mex(mexsrc); - cd(pwdir); - success = true; - -catch - % compilation failed - disp(lasterr); - error('could not locate MEX file for %s', mexname); - cd(pwdir); - success = false; -end - -if success - % execute the mex file that was juist created - funname = mfilename; - funhandle = str2func(funname); - [varargout{1:nargout}] = funhandle(varargin{:}); -end - diff --git a/external/fileio/private/write_data.m b/external/fileio/private/write_data.m deleted file mode 100644 index 7b2f15b..0000000 --- a/external/fileio/private/write_data.m +++ /dev/null @@ -1,625 +0,0 @@ -function write_data(filename, dat, varargin) - -% WRITE_DATA exports electrophysiological data to a file. The input data is -% assumed to be scaled in microVolt. -% -% Use as -% write_data(filename, dat, ...) -% -% The specified filename can already contain the filename extention, -% but that is not required since it will be added automatically. -% -% Additional options should be specified in key-value pairs and can be -% 'header' header structure, see READ_HEADER -% 'dataformat' string, see below -% 'append' boolean, not supported for all formats -% 'chanindx' 1xN array -% -% The supported dataformats are -% brainvision_eeg -% matlab -% riff_wave -% fcdc_matbin -% fcdc_mysql -% fcdc_buffer -% plexon_nex -% neuralynx_ncs -% neuralynx_sdma -% -% See also READ_HEADER, READ_DATA, READ_EVEN, WRITE_EVENT - -% Copyright (C) 2007-2008, Robert Oostenveld -% -% $Log: write_data.m,v $ -% Revision 1.23 2009/06/17 10:15:43 roboos -% added support for neuralynx_sdma, only for 32 bit integer data -% -% Revision 1.22 2009/05/19 18:29:48 roboos -% give instructive error if the fieldtrip buffer mex file is not on the path -% -% Revision 1.21 2009/01/21 21:20:01 roboos -% improved check to detect missing ft buffer, only start if certain about socket error and if localhost or 127.0.0.1 -% -% Revision 1.20 2009/01/21 11:34:23 marvger -% update in hostname detection for fcdc_buffer -% -% Revision 1.19 2009/01/20 21:46:24 roboos -% use mxSerialize instead of serialize in mysql -% -% Revision 1.18 2009/01/14 21:16:52 marvger -% changes related to realtime processing -% -% Revision 1.17 2008/12/16 15:36:34 roboos -% prevent append to be used twice in the key-value list for fcdc_buffer -% -% Revision 1.16 2008/12/15 14:52:57 roboos -% updated help: be explicit about the function expecting uV input data (also for plexon) -% removed the obsolete code for writing to ctf meg4 files -% -% Revision 1.15 2008/11/03 21:34:11 roboos -% split large segments into multiple smaller ones prior to calling the buffer mex file -% -% Revision 1.14 2008/10/30 10:45:46 roboos -% added format=disp for debugging -% try to initialize a tcpserver if first write to socket fails -% -% Revision 1.13 2008/10/30 10:43:29 roboos -% allow chanindx for buffer -% -% Revision 1.12 2008/10/23 09:09:55 roboos -% improved appending for format=matlab -% added fcdc_global for debugging (consistent with write_event) -% -% Revision 1.11 2008/10/22 10:43:41 roboos -% removed obsolete option subformat -% added option append and implemented for format=matlab (i.e. read, append, write) -% completed the implementation for fcdc_buffer -% -% Revision 1.10 2008/06/19 20:50:35 roboos -% added initial support for fcdc_buffer, sofar only for the header -% -% Revision 1.9 2008/01/31 20:05:05 roboos -% removed fcdc_ftc -% updated documentation -% -% Revision 1.8 2007/12/12 14:40:33 roboos -% added riff_wave using standard matlab function -% -% Revision 1.7 2007/12/06 17:09:06 roboos -% added fcdc_ftc -% -% Revision 1.6 2007/11/07 10:49:07 roboos -% cleaned up the reading and writing from/to mysql database, using db_xxx helper functions (see mysql directory) -% -% Revision 1.5 2007/11/05 17:02:45 roboos -% made first implementation for writing header and data to fcdc_mysql -% -% Revision 1.4 2007/10/01 13:49:11 roboos -% added skeleton implementation for ctf_meg4, not yet tested -% -% Revision 1.3 2007/06/13 08:14:58 roboos -% updated documentation -% -% Revision 1.2 2007/06/13 08:07:14 roboos -% added autodetection of dataformat -% added support for write_brainvision_eeg -% -% Revision 1.1 2007/06/13 06:44:13 roboos -% moved the content of the write_fcdc_data to the low-level write_data function -% updated the help -% - -global data_queue % for fcdc_global -global header_queue % for fcdc_global -global db_blob % for fcdc_mysql -if isempty(db_blob) - db_blob = 0; -end - -% get the options -dataformat = keyval('dataformat', varargin); if isempty(dataformat), dataformat = filetype(filename); end -append = keyval('append', varargin); if isempty(append), append = false; end -nbits = keyval('nbits', varargin); % for riff_wave -chanindx = keyval('chanindx', varargin); -hdr = keyval('header', varargin); - -% determine the data size -[nchans, nsamples] = size(dat); - -switch dataformat - case 'disp' - % display it on screen, this is only for debugging - disp('new data arived'); - - case 'fcdc_global' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % store it in a global variable, this is only for debugging - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - if ~isempty(hdr) - header_queue = hdr; - end - if isempty(data_queue) || ~append - data_queue = dat; - else - data_queue = cat(2, data_queue, dat); - end - - case 'fcdc_buffer' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % network transparent buffer - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - if ~isempty(chanindx) - % assume that the header corresponds to the original multichannel - % file and that the data represents a subset of channels - hdr.label = hdr.label(chanindx); - hdr.nChans = length(chanindx); - end - - [host, port] = filetype_check_uri(filename); - - type = { - 'char' - 'uint8' - 'uint16' - 'uint32' - 'uint64' - 'int8' - 'int16' - 'int32' - 'int64' - 'single' - 'double' - }; - - wordsize = { - 1 % 'char' - 1 % 'uint8' - 2 % 'uint16' - 4 % 'uint32' - 8 % 'uint64' - 1 % 'int8' - 2 % 'int16' - 4 % 'int32' - 8 % 'int64' - 4 % 'single' - 8 % 'double' - }; - - % this should only be done the first time - if ~append && ~isempty(hdr) - % reformat the header into a buffer-compatible format - packet.fsample = hdr.Fs; - packet.nchans = hdr.nChans; - packet.nsamples = 0; - packet.nevents = 0; - packet.data_type = find(strcmp(type, class(dat))) - 1; % zero-offset - - % try to put_hdr and initialize if necessary - try - % try writing the packet - buffer('put_hdr', packet, host, port); - - catch - if ~isempty(strfind(lasterr, 'Buffer size N must be an integer-valued scalar double.')) - % this happens if the MATLAB75/toolbox/signal/signal/buffer - % function is used instead of the fieldtrip buffer - error('the FieldTrip buffer mex file was not found on your path, it should be in fieldtrip/fileio/private'); - - elseif ~isempty(strfind(lasterr, 'failed to create socket')) && (strcmp(host, 'localhost') || strcmp(host, '127.0.0.1')) - - % start a local instance of the TCP server - warning('starting fieldtrip buffer on %s:%d', host, port); - buffer('tcpserver', 'init', host, port); - pause(1); - - % rewrite the packet until success - success = false; - while ~success - try - % it may take some time before the TCP server is fully initialized - % try writing the packet again - buffer('put_hdr', packet, host, port); - success = true; - catch - success = false; - end - end - end % if strfind... - - end % try - - end % writing header - - if ~isempty(dat) - max_nsamples = 32556; - if size(dat,2)>max_nsamples - % FIXME this is a hack to split large writes into multiple smaller writes - % this is to work around a problem observed in the neuralynx proxy - % when sampling 32 channels at 32KHz - begsample = 1; - while begsample<=size(dat,2) - endsample = begsample - 1 + max_nsamples; - endsample = min(endsample, size(dat,2)); - % if append is already one of the arguments, remove it from varargin - indx = find(strcmp(varargin, 'append')); % find the "append" key - if ~isempty(indx) - indx = [indx indx+1]; % remove the key and the value - varargin(indx) = []; - end - write_data(filename, dat(:,begsample:endsample), varargin{:}, 'append', false); - begsample = endsample + 1; - end - else - % FIXME this is the normal code, which will also be used recursively - % reformat the data into a buffer-compatible format - packet.nchans = size(dat,1); - packet.nsamples = size(dat,2); - packet.data_type = find(strcmp(type, class(dat))) - 1; % zero-offset - packet.bufsize = numel(dat) * wordsize{find(strcmp(type, class(dat)))}; - packet.buf = dat; - buffer('put_dat', packet, host, port); - end % if data larger than chuncksize - end - - case 'brainvision_eeg' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % combination of *.eeg and *.vhdr file - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - if append - error('appending data is not yet supported for this data format'); - end - - if nchans~=hdr.nChans && length(chanindx)==nchans - % assume that the header corresponds to the original multichannel - % file and that the data represents a subset of channels - hdr.label = hdr.label(chanindx); - hdr.nChans = length(chanindx); - end - % the header should at least contain the following fields - % hdr.label - % hdr.nChans - % hdr.Fs - write_brainvision_eeg(filename, hdr, dat); - - case 'fcdc_matbin' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % multiplexed data in a *.bin file (ieee-le, 64 bit floating point values), - % accompanied by a matlab V6 file containing the header - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - if append - error('appending data is not yet supported for this data format'); - end - - [path, file, ext] = fileparts(filename); - headerfile = fullfile(path, [file '.mat']); - datafile = fullfile(path, [file '.bin']); - if nchans~=hdr.nChans && length(chanindx)==nchans - % assume that the header corresponds to the original multichannel - % file and that the data represents a subset of channels - hdr.label = hdr.label(chanindx); - hdr.nChans = length(chanindx); - end - % write the header file - save(headerfile, 'hdr', '-v6'); - % write the data file - [fid,message] = fopen(datafile,'wb','ieee-le'); - fwrite(fid, dat, 'double'); - fclose(fid); - - case 'fcdc_mysql' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % write to a MySQL server listening somewhere else on the network - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - db_open(filename); - if ~isempty(hdr) && isempty(dat) - % insert the header information into the database - if db_blob - % insert the structure into the database table as a binary blob - db_insert_blob('fieldtrip.header', 'msg', hdr); - else - % make a structure with the same elements as the fields in the database table - s = struct; - s.Fs = hdr.Fs; % sampling frequency - s.nChans = hdr.nChans; % number of channels - s.nSamples = hdr.nSamples; % number of samples per trial - s.nSamplesPre = hdr.nSamplesPre; % number of pre-trigger samples in each trial - s.nTrials = hdr.nTrials; % number of trials - s.label = mxSerialize(hdr.label); - try - s.msg = mxSerialize(hdr); - catch - warning(lasterr); - end - db_insert('fieldtrip.header', s); - end - - elseif isempty(hdr) && ~isempty(dat) - dim = size(dat); - if numel(dim)==2 - % ensure that the data dimensions correspond to ntrials X nchans X samples - dim = [1 dim]; - dat = reshape(dat, dim); - end - ntrials = dim(1); - for i=1:ntrials - if db_blob - % insert the data into the database table as a binary blob - db_insert_blob('fieldtrip.data', 'msg', reshape(dat(i,:,:), dim(2:end))); - else - % create a structure with the same fields as the database table - s = struct; - s.nChans = dim(2); - s.nSamples = dim(3); - try - s.data = mxSerialize(reshape(dat(i,:,:), dim(2:end))); - catch - warning(lasterr); - end - % insert the structure into the database - db_insert('fieldtrip.data', s); - end - end - - else - error('you should specify either the header or the data when writing to a MySQL database'); - end - - case 'matlab' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % plain matlab file - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - [path, file, ext] = fileparts(filename); - filename = fullfile(path, [file '.mat']); - if append && exist(filename, 'file') - % read the previous header and data from matlab file - prev = load(filename); - if ~isempty(hdr) && ~isequal(hdr, prev.hdr) - error('inconsistent header'); - else - % append the new data to that from the matlab file - dat = cat(2, prev.dat, dat); - end - elseif append && ~exist(filename, 'file') - % file does not yet exist, which is not a problem - elseif ~append && exist(filename, 'file') - warning(sprintf('deleting existing file ''%s''', filename)); - delete(filename); - elseif ~append && ~exist(filename, 'file') - % file does not yet exist, which is not a problem - end - save(filename, 'dat', 'hdr'); - - case 'neuralynx_sdma' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % The first version of this file format contained in the first 8 bytes the - % channel label as string. Subsequently it contained 32 bit integer values. - % - % The second version of this file format starts with 8 bytes describing (as - % a space-padded string) the data type. The channel label is contained in - % the filename as dataset.chanlabel.bin. - % - % The third version of this file format starts with 7 bytes describing (as - % a zero-padded string) the data type, followed by the 8th byte which - % describes the downscaling for the 8 and 16 bit integer representations. - % The downscaling itself is represented as uint8 and should be interpreted as - % the number of bits to shift. The channel label is contained in the - % filename as dataset.chanlabel.bin. - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - statuschannel = { - 'stx' - 'pid' - 'siz' - 'tsh' - 'tsl' - 'cpu' - 'ttl' - 'x01' - 'x02' - 'x03' - 'x04' - 'x05' - 'x06' - 'x07' - 'x08' - 'x09' - 'x10' - 'crc' - }; - - dirname = filename; - clear filename - [path, file] = fileparts(dirname); - for i=1:hdr.nChans - downscale(i) = 0; - if ~isempty(strmatch(hdr.label{i}, statuschannel)) - format{i} = 'uint32'; - else - format{i} = 'int32'; - end - filename{i} = fullfile(dirname, [file '.' hdr.label{i} '.bin']); - end - - if ~isdir(dirname) - mkdir(dirname); - end - - % open and write to the output files, one for each selected channel - fid = zeros(hdr.nChans,1); - for j=1:hdr.nChans - - if append==false - fid(j) = fopen(filename{j}, 'wb', 'ieee-le'); % open the file - magic = format{j}; % this used to be the channel name - magic((end+1):8) = 0; % pad with zeros - magic(8) = downscale(j); % number of bits to shift - fwrite(fid(j), magic(1:8)); % write the 8-byte file header - else - fid(j) = fopen(filename{j}, 'ab', 'ieee-le'); % open the file for appending - end % if append - - % convert the data into the correct class - buf = dat(j,:); - if ~strcmp(class(buf), format{j}) - switch format{j} - case 'int16' - buf = int16(buf); - case 'int32' - buf = int32(buf); - case 'single' - buf = single(buf); - case 'double' - buf = double(buf); - case 'uint32' - buf = uint32(buf); - otherwise - error('unsupported format conversion'); - end - end - - % apply the scaling, this corresponds to bit shifting - buf = buf ./ (2^downscale(j)); - - % write the segment of data to the output file - fwrite(fid(j), buf, format{j}, 'ieee-le'); - - fclose(fid(j)); - end % for each channel - - case 'riff_wave' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % This writes data Y to a Windows WAVE file specified by the file name - % WAVEFILE, with a sample rate of FS Hz and with NBITS number of bits. - % NBITS must be 8, 16, 24, or 32. For NBITS < 32, amplitude values - % outside the range [-1,+1] are clipped - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - if append - error('appending data is not yet supported for this data format'); - end - - if nchans~=hdr.nChans && length(chanindx)==nchans - % assume that the header corresponds to the original multichannel - % file and that the data represents a subset of channels - hdr.label = hdr.label(chanindx); - hdr.nChans = length(chanindx); - end - if nchans~=1 - error('this format only supports single channel continuous data'); - end - wavwrite(dat, hdr.Fs, nbits, filename); - - case 'plexon_nex' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % single or mulitple channel Plexon NEX file - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - if append - error('appending data is not yet supported for this data format'); - end - - [path, file] = fileparts(filename); - filename = fullfile(path, [file, '.nex']); - if nchans~=1 - error('only supported for single-channel data'); - end - % construct a NEX structure with the required parts of the header - nex.hdr.VarHeader.Type = 5; % continuous - nex.hdr.VarHeader.Name = hdr.label{1}; - nex.hdr.VarHeader.WFrequency = hdr.Fs; - if isfield(hdr, 'FirstTimeStamp') - nex.hdr.FileHeader.Frequency = hdr.Fs * hdr.TimeStampPerSample; - nex.var.ts = hdr.FirstTimeStamp; - else - warning('no timestamp information available'); - nex.hdr.FileHeader.Frequency = nan; - nex.var.ts = nan; - end - nex.var.indx = 0; - nex.var.dat = dat; - - write_plexon_nex(filename, nex); - - if 0 - % the following code snippet can be used for testing - nex2 = []; - [nex2.var, nex2.hdr] = read_plexon_nex(filename, 'channel', 1); - end - - case 'neuralynx_ncs' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % single channel Neuralynx NCS file - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - if append - error('appending data is not yet supported for this data format'); - end - - if nchans>1 - error('only supported for single-channel data'); - end - - [path, file, ext] = fileparts(filename); - filename = fullfile(path, [file, '.ncs']); - - if nchans~=hdr.nChans && length(chanindx)==nchans - % assume that the header corresponds to the original multichannel - % file and that the data represents a subset of channels - % WARNING the AD channel index assumes that the data was read from a DMA or SDMA file - % the first 17 channels contain status info, this number is zero-offset - ADCHANNEL = chanindx - 17 - 1; - LABEL = hdr.label{chanindx}; - elseif hdr.nChans==1 - ADCHANNEL = -1; % unknown - LABEL = hdr.label{1}; % single channel - else - error('cannot determine channel label'); - end - - FSAMPLE = hdr.Fs; - RECORDNSMP = 512; - RECORDSIZE = 1044; - - % cut the downsampled LFP data into record-size pieces - nrecords = ceil(nsamples/RECORDNSMP); - fprintf('construct ncs with %d records\n', nrecords); - - % construct a ncs structure with all header details and the data in it - ncs = []; - ncs.NumValidSamp = ones(1,nrecords) * RECORDNSMP; % except for the last block - ncs.ChanNumber = ones(1,nrecords) * ADCHANNEL; - ncs.SampFreq = ones(1,nrecords) * FSAMPLE; - ncs.TimeStamp = zeros(1,nrecords,'uint64'); - - if rem(nsamples, RECORDNSMP)>0 - % the data length is not an integer number of records, pad the last record with zeros - dat = cat(2, dat, zeros(nchans, nrecords*RECORDNSMP-nsamples)); - ncs.NumValidSamp(end) = rem(nsamples, RECORDNSMP); - end - - ncs.dat = reshape(dat, RECORDNSMP, nrecords); - - for i=1:nrecords - % timestamps should be 64 bit unsigned integers - ncs.TimeStamp(i) = uint64(hdr.FirstTimeStamp) + uint64((i-1)*RECORDNSMP*hdr.TimeStampPerSample); - end - - % add the elements that will go into the ascii header - ncs.hdr.CheetahRev = '4.23.0'; - ncs.hdr.NLX_Base_Class_Type = 'CscAcqEnt'; - ncs.hdr.NLX_Base_Class_Name = LABEL; - ncs.hdr.RecordSize = RECORDSIZE; - ncs.hdr.ADChannel = ADCHANNEL; - ncs.hdr.SamplingFrequency = FSAMPLE; - - % write it to a file - fprintf('writing to %s\n', filename); - write_neuralynx_ncs(filename, ncs); - - if 0 - % the following code snippet can be used for testing - ncs2 = read_neuralynx_ncs(filename, 1, inf); - end - - otherwise - error('unsupported data format'); -end % switch dataformat - diff --git a/external/fileio/private/write_event.m b/external/fileio/private/write_event.m deleted file mode 100644 index de6e702..0000000 --- a/external/fileio/private/write_event.m +++ /dev/null @@ -1,527 +0,0 @@ -function write_event(filename, event, varargin) - -% WRITE_EVENT writes an event structure to a file, a message daemon -% listening on a network socked, or to another computer connected through -% the serial port. -% -% Use as -% write_event(filename, event, ...) -% -% The first argument is a string containing the filename. The second -% argument is a structure with the event. Multiple events can be -% represented as a structure array. -% -% Events are represented as -% event.type string -% event.sample expressed in samples, the first sample of a recording is 1 -% event.value number or string -% event.offset expressed in samples -% event.duration expressed in samples -% event.timestamp expressed in timestamp units, which vary over systems (optional) -% -% Events can also be written to special communication streams -% by specifying the target as URI instead of a filename. Supported are -% buffer://: -% fifo:// -% tcp://: -% udp://: -% mysql://:@: -% rfb://@: -% serial:?key1=value1&key2=value2&... -% rfb://@: -% -% See also READ_HEADER, READ_DATA, READ_EVENT, WRITE_DATA - -% Copyright (C) 2007, Robert Oostenveld -% -% $Log: write_event.m,v $ -% Revision 1.35 2009/05/22 09:02:29 marvger -% changed tcp handling -% -% Revision 1.34 2009/04/28 08:33:05 marvger -% small changes -% -% Revision 1.33 2009/01/22 15:31:59 marvger -% updated catch handling -% -% Revision 1.32 2009/01/21 11:34:44 marvger -% update in hostname detection for fcdc_buffer -% -% Revision 1.31 2009/01/20 08:56:51 marvger -% fixed catch me bug (illegal syntax in older matlab versions) -% -% Revision 1.30 2009/01/16 11:38:51 marvger -% update tcp/udp -% -% Revision 1.29 2009/01/14 21:16:52 marvger -% changes related to realtime processing -% -% Revision 1.28 2008/12/19 14:39:25 marvger -% added support for udp, tcp and fifo -% -% Revision 1.27 2008/06/19 19:31:44 roboos -% made fcdc_buffer more robust -% -% Revision 1.26 2008/06/18 06:22:24 roboos -% added support for fcdc_buffer -% -% Revision 1.25 2008/01/30 10:40:54 roboos -% moved catevent to seperate function and renamed to appendevent -% -% Revision 1.24 2007/12/12 11:29:07 roboos -% chedk for presence of timestamp prior to trying to concatenate events -% -% Revision 1.23 2007/11/07 11:03:58 roboos -% added line of documentation -% -% Revision 1.22 2007/11/07 10:49:07 roboos -% cleaned up the reading and writing from/to mysql database, using db_xxx helper functions (see mysql directory) -% -% Revision 1.21 2007/11/05 17:04:03 roboos -% moved insert_query to seperate function -% ved declarationof persistent and global variables to the beginning of the function -% some cosmetic changes -% -% Revision 1.20 2007/10/30 20:47:04 roboos -% added support for remote frame buffer (rfb), i.e. VNC server -% -% Revision 1.19 2007/10/16 12:34:43 roboos -% use recursion to write to multiple event sources -% implemented fcdc_global -% -% Revision 1.18 2007/09/15 14:36:26 chrhes -% changed the default mode for writing to a serial port to synchronous -% -% Revision 1.17 2007/08/16 14:28:59 chrhes -% removed the try-catches introduced in previous revision: the relevant error -% is now dealt with elsewhere -% -% Revision 1.16 2007/08/16 14:03:20 chrhes -% put some try-catches around the save command in the default option -% -% Revision 1.15 2007/06/19 11:11:28 chrhes -% changed the implementation of how the target serial port is located if it -% exists -% -% Revision 1.14 2007/06/19 10:11:37 chrhes -% restricted the functionality of serial port writing such that only the -% content of the field event.value is written as a character array -% -% Revision 1.13 2007/06/13 14:46:35 roboos -% removed type/subtype, added type/value/sample for mysql -% -% Revision 1.12 2007/06/13 08:06:45 roboos -% updated help -% -% Revision 1.11 2007/06/12 19:37:28 roboos -% added support for mysql port specification (default is 3306) -% added support for writing multiple events to mysql, each requires a single query -% -% Revision 1.10 2007/06/12 16:34:49 roboos -% first implementation of writing to a mysql database: approx. 30ms per event -% -% Revision 1.9 2007/06/07 12:43:38 chrhes -% added an option for specifying the maximum length of the event queue for -% the case where the events are being written (appended) to a .mat file -% -% Revision 1.8 2007/06/06 20:14:49 chrhes -% fixed a small bug to do with sting comparison -% -% Revision 1.7 2007/06/06 16:00:31 chrhes -% updated some documentation -% -% Revision 1.6 2007/06/06 15:55:30 chrhes -% extended functionality for serial port writing so that the code recognises -% when to write the whole event structure or only a single control character -% -% Revision 1.5 2007/06/06 15:45:53 chrhes -% implemented option for writing events to the serial port -% -% Revision 1.4 2007/06/06 12:38:57 roboos -% write events to uncompressed matlab v6 file -% -% Revision 1.3 2007/06/06 07:14:29 roboos -% switched to using filetype_check_uri for detection and parsing of filename -% switched to using external struct2msg function -% implemented fcdc_fifo -% added optinoal input arguments (key-value pairs) -% -% Revision 1.2 2007/05/31 09:54:05 roboos -% implemented writing events to a plain matlab file, the default is to append them -% -% Revision 1.1 2007/05/31 09:14:34 roboos -% initial implementation, sofar only tcpsocket -% - -global event_queue % for fcdc_global -global db_blob % for fcdc_mysql -if isempty(db_blob) - db_blob = 0; -end - -if iscell(filename) - % use recursion to write to multiple event targets - for i=1:numel(filename) - write_event(filename{i}, event, varargin); - end - return -end - -% set the defaults -eventformat = keyval('eventformat', varargin); if isempty(eventformat), eventformat = filetype(filename); end -swapping = keyval('swapping', varargin); if isempty(swapping), swapping = 'native'; end -append = keyval('append', varargin); if isempty(append), append = 'yes'; end -maxqlength = keyval('maxqlength', varargin); if isempty(maxqlength), maxqlength = Inf; end - -switch eventformat - case 'disp' - % display it on screen, this is only for debugging - disp(event); - - case 'fcdc_global' - % store it in a global variable, this is only for debugging - if isempty(event_queue) || ~isstruct(event_queue) - event_queue = event; - else - event_queue = appendevent(event_queue, event); - end - - case 'fcdc_rfb' - % remote frame buffer, i.e. VNC server on another computer - [password, host, port] = filetype_check_uri(filename); - rfbevent(sprintf('%s:%d', host, port), password, event.type, event.value); - - case 'fcdc_buffer' - % read from a networked buffer for realtime analysis - [host, port] = filetype_check_uri(filename); - - type = { - 'char' - 'uint8' - 'uint16' - 'uint32' - 'uint64' - 'int8' - 'int16' - 'int32' - 'int64' - 'single' - 'double' - }; - - wordsize = { - 1 % 'char' - 1 % 'uint8' - 2 % 'uint16' - 4 % 'uint32' - 8 % 'uint64' - 1 % 'int8' - 2 % 'int16' - 4 % 'int32' - 8 % 'int64' - 4 % 'single' - 8 % 'double' - }; - - for i=1:length(event) - evt = []; - buf = []; - bufsize = 0; - - % convert the field "type" into the message representation - this_type = class(event(i).type); - this_size = numel(event(i).type); - switch this_type - case 'char' - buf = cat(2, buf, event(i).type); - otherwise - buf = cat(2, buf, typecast(event(i).type, 'uint8')); - end - bufsize = bufsize + wordsize{strcmp(type, this_type)}*this_size; - evt.type_type = find(strcmp(type, this_type))-1; % zero-offset - evt.type_numel = this_size; - - % convert the field "value" into the message representation - this_type = class(event(i).value); - this_size = numel(event(i).value); - event(i).value = event(i).value(:)'; % it must be represented as a vector - switch this_type - case 'char' - buf = cat(2, buf, event(i).value); - otherwise - buf = cat(2, buf, typecast(event(i).value, 'uint8')); - end - bufsize = bufsize + wordsize{strcmp(type, this_type)}*this_size; - evt.value_type = find(strcmp(type, this_type))-1; % zero-offset - evt.value_numel = this_size; - - % although sample, offset and duration do not play a role in BCI2000, - % they must exist for the buffer - if ~isfield(event(i), 'sample') || isempty(event(i).sample) - event(i).sample = 0; - end - if ~isfield(event(i), 'offset') || isempty(event(i).offset) - event(i).offset = 0; - end - if ~isfield(event(i), 'duration') || isempty(event(i).duration) - event(i).duration = 0; - end - - % the other fields are simple, because they have a fixed type and only a single elements - evt.sample = int32(event(i).sample); - evt.offset = int32(event(i).offset); - evt.duration = int32(event(i).duration); - - evt.bufsize = bufsize; - evt.buf = uint8(buf); - - % check if buffer is open and keep trying to fill it... - try - - if strcmp(append,'no') - buffer('flush_evt', [], host, port); % flush event - end - - buffer('put_evt', evt, host, port); % indices should be zero-offset - - catch - - % retrieve hostname - [ret, hname] = system('hostname'); - if ret ~= 0, - if ispc - hname = getenv('COMPUTERNAME'); - else - hname = getenv('HOSTNAME'); - end - end - - if strcmpi(host,'localhost') || strcmpi(host,hname) - - warning('starting fieldtrip buffer on localhost'); - - % try starting a local buffer - buffer('tcpserver', 'init', host, port); - pause(1); - - % write packet until succeed - bhdr = false; - while ~bhdr - try - bhdr = true; - - % try writing a dummy header - dumhdr.fsample = 0; - dumhdr.nchans = 0; - dumhdr.nsamples = 0; - dumhdr.nevents = 0; - dumhdr.data_type = 0; - - buffer('put_hdr', dumhdr, host, port); - buffer('put_evt', evt, host, port); % indices should be zero-offset - - catch - bhdr = false; - end - end - end - end - end - - case 'fcdc_serial' - % serial port on windows or linux platform - s = []; - [port, opt] = filetype_check_uri(filename); - % determine whether any serial port objects are already associated with the - % target serial port - temp = instrfind; - if isa(temp,'instrument') - % find all serial ports - i1 = strcmp('serial',{temp(:).Type}); - if any(i1) - % find all serial ports whose name matches that of the specified port - i2 = strmatch(lower(['Serial-',port]),lower({temp(find(i1)==1).Name})); - % set s to the (first) matching port if present (and open if necessary) - if ~isempty(i2) - s = temp(i2(1)); - if ~strcmp(s.Status,'open'), fopen(s); end; - end - end - end - % create, configure a serial port object if necessary and open the port - if ~isa(s,'serial') - s = serial(port); - if ~isempty(opt) && iscell(opt), s = set(s,opt); end; - fopen(s); - end - - % % convert the event structure into an appropriate message - % if isfield(event,'type') && strcmp(event.type,'ctrlchar') - % % use only a single control character - % msg = char(event.value(1)); - % else - % % convert the entire event structure into a message - % msg = struct2msg(event); - % end - - % write the contents of the field event.value to the serial port as a string - if isfield(event,'value') && ~isempty(event.value) - msg = char(event.value); - else - msg = []; - end - % write the message to the serial port - if ~isempty(msg) && isa(s,'serial') && strcmp(s.Status,'open') - %fprintf(s,msg,'async'); - fprintf(s,msg); - else - error('could not write event to serial port'); - end - - case 'fcdc_mysql' - % write to a MySQL server listening somewhere else on the network - db_open(filename); - for i=1:length(event) - if db_blob - % insert the structure into the database table as a binary blob - db_insert_blob('fieldtrip.event', 'msg', event(i)); - else - % make a structure with the same elements as the fields in the database table - s = struct; - % these fields also exist as elements in the table and as such can be used for filtering - if isa(event(i).type, 'char') - s.type = event(i).type; - end - if isa(event(i).value, 'numeric') && numel(event(i).value)==1 - s.value = event(i).value; - end - if isa(event(i).sample, 'numeric') && numel(event(i).sample)==1 - s.sample = event(i).sample; - end - if isa(event(i).sample, 'numeric') && numel(event(i).offset)==1 - s.offset = event(i).offset; - end - if isa(event(i).sample, 'numeric') && numel(event(i).duration)==1 - s.duration = event(i).duration; - end - % insert the structure into the database table - db_insert('fieldtrip.event', s); - end - end - - case 'fcdc_fifo' - - % these are opened in blocking mode, i.e. reading/writing will block until boths sides are connected - fifo = filetype_check_uri(filename); - - if ~exist(fifo,'file') - warning('the FIFO %s does not exist; attempting to create it', fifo); - system(sprintf('mkfifo -m 0666 %s',fifo)); - end - - fid = fopen(fifo, 'w'); - for i=1:length(event) - - try - % convert the event into a network message - msg = mxSerialize(event(i)); - num = fwrite(fid, msg, 'uint8'); - catch - warning(lasterr); - end - - if num~=length(msg) - error('problem writing to FIFO %s', fifo); - end - end - fclose(fid); - - case 'fcdc_tcp' - - % TCP network socket - [host, port] = filetype_check_uri(filename); - - con=pnet('tcpconnect',host,port); - - pnet(con,'setwritetimeout',1); - - if con~=-1, - - try % Failsafe - - for i=1:length(event) - - % convert the event into a network message - msg = mxSerialize(event(i)); - - % tell the message daemon that a message will be sent, and send it - pnet(con,'printf',num2str(msg)); - pnet(con,'printf','\n'); - end -% catch -% warning(lasterr); - end - - pnet(con,'close'); - end - - case 'fcdc_udp' - - % UDP network socket - - [host, port] = filetype_check_uri(filename); - udp=pnet('udpsocket',port); - - if udp~=-1, - try % Failsafe - - for i=1:length(event) - - % convert the event into a network message - msg = mxSerialize(event(i)); - - % tell the message daemon that a message will be sent, and send it - pnet(udp,'write',uint8(msg),1000); - pnet(udp,'writepacket',host,port); % Send buffer as UDP packet to host - end - - catch - warning(lasterr); - end - pnet(udp,'close'); - end - - - otherwise - % assume that it is a file. Since the file probably does not yet - % exist, determine its type by only looking at the extension - if filetype_check_extension(filename, '.mat') - % write the events to a matlab file - if exist(filename,'file') && strcmp(append, 'yes') - try - tmp = load(filename, 'event'); - event = cat(1, tmp.event(:), event(:)); - catch - event = event(:); - end - % optionally restric the length of the event queue to flush old events - if isfinite(maxqlength) && isreal(maxqlength) && (maxqlength>0) && (length(event)>maxqlength) - event = event(end-maxqlength+1:end); - % NOTE: this could be done using the filter event function, but - % then this is just a temporary solution that will probably be - % removed in a future versions of the code - end - save(filename, 'event', '-append', '-v6'); - % NOTE: the -append option in this call to the save function does - % not actually do anything useful w.r.t. the event variable since the - % events are being appended in the code above and the the save function - % will just overwrite the existing event variable in the file. - % However, if there are other variables in the file (whatever) then the - % append option preservs them - else - save(filename, 'event', '-v6'); - end - else - error('unsupported file type') - end -end diff --git a/external/fileio/private/write_neuralynx_ncs.m b/external/fileio/private/write_neuralynx_ncs.m deleted file mode 100644 index a4907b1..0000000 --- a/external/fileio/private/write_neuralynx_ncs.m +++ /dev/null @@ -1,108 +0,0 @@ -function write_neuralynx_ncs(filename, ncs); - -% WRITE_NEURALYNX_NCS writes continuous data to a NCS file -% The input data should be scaled in uV. -% -% Use as -% write_neuralynx_ncs(filename, ncs) -% -% See also READ_NEURALYNX_NCS - -% Copyright (C) 2005-2007, Robert Oostenveld -% -% $Log: write_neuralynx_ncs.m,v $ -% Revision 1.1 2009/01/14 09:12:16 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.7 2007/03/21 12:51:20 roboos -% included the scaling to int16 AD values into this function, i.e. the input data should be uV (double) -% -% Revision 1.6 2007/03/19 16:54:52 roboos -% changed numeric representation of something in the ascii header -% -% Revision 1.5 2007/02/21 09:52:27 roboos -% changed the writing of the data to reflect t he changed representation (2D numeric array instead of 1D cell array) -% -% Revision 1.4 2007/01/09 09:40:03 roboos -% write timestamps as unsigned (uint64 instead of int64) -% -% Revision 1.3 2005/12/02 09:01:42 roboos -% fixed a comment -% -% Revision 1.2 2005/09/09 12:27:02 roboos -% cleaned up the code, changed the looping over records, added the number of records to the output -% -% Revision 1.1 2005/08/05 13:41:39 roboos -% new implementation -% - -if ~isa(ncs.TimeStamp, 'uint64') - error('timestamps should be uint64'); -end - -% convert the data from uV into V -ncs.dat = ncs.dat * 1e-6; -% scale the data and convert to 16 bits, -% this has to be done prior to writing the header -ADMaxValue = double(intmax('int16')); -ADMaxVolts = max(abs(ncs.dat(:))); -if ADMaxVolts>0 - ADBitVolts = ADMaxVolts / ADMaxValue; -else - ADBitVolts = 1; -end -ncs.dat = int16(ncs.dat / ADBitVolts); -% update the header with the calibration values -ncs.hdr.ADBitVolts = ADBitVolts; -ncs.hdr.ADMaxValue = ADMaxValue; - -% construct the header -buf = []; -buf = [buf sprintf('######## Neuralynx Data File Header\r\n')]; -buf = [buf sprintf('## File Name: %s\r\n', filename)]; -buf = [buf sprintf('## Time Opened: (m/d/y): %s At Time: %s\r\n', datestr(clock, 'mm/dd/yy'), datestr(clock, 'HH:MM:SS'))]; -f = fieldnames(ncs.hdr); -for i=1:length(f) - v = getfield(ncs.hdr, f{i}); - switch class(v) - case 'char' - buf = [buf sprintf('-%s\t%s\r\n', f{i}, v)]; - case 'double' - buf = [buf sprintf('-%s\t%s\r\n', f{i}, num2str(v))]; - otherwise - error('unknown class in writing header'); - end -end - -% pad the rest of the header with zeros -buf((end+1):16384) = 0; - -% open the file and write the header -fid = fopen(filename, 'wb', 'ieee-le'); -fwrite(fid, buf); - -% The format of a continuous sampled record is -% int64 TimeStamp -% int32 ChanNumber -% int32 SampFreq -% int32 NumValidSamp -% int16 Samp[0] ... int16 Samp[511] -% Note that if NumValidSamp < 512, Samp[n], where n >= NumValidSamp, will -% contain random data. - -for i=1:size(ncs.dat,2) - % write a single continuous data record - fwrite(fid, ncs.TimeStamp(i) , 'uint64'); - fwrite(fid, ncs.ChanNumber(i) , 'int32'); - fwrite(fid, ncs.SampFreq(i) , 'int32'); - fwrite(fid, ncs.NumValidSamp(i), 'int32'); - fwrite(fid, ncs.dat(:,i) , 'int16'); -end - -% close the file -fclose(fid); diff --git a/external/fileio/private/write_neuralynx_nse.m b/external/fileio/private/write_neuralynx_nse.m deleted file mode 100644 index eb5b2a4..0000000 --- a/external/fileio/private/write_neuralynx_nse.m +++ /dev/null @@ -1,93 +0,0 @@ -function write_neuralynx_nse(filename, nse); - -% WRITE_NEURALYNX_NSE writes spike timestamps and waveforms to a NSE file -% The input data should be scaled in uV. -% -% Use as -% write_neuralynx_nse(filename, nse) -% -% See also READ_NEURALYNX_NSE - -% Copyright (C) 2005-2007, Robert Oostenveld -% -% $Log: write_neuralynx_nse.m,v $ -% Revision 1.5 2007/03/21 15:55:31 roboos -% fixed typo in variable name -% -% Revision 1.4 2007/03/21 12:53:21 roboos -% included the scaling to int16 AD values into this function, i.e. the input data should be uV (double) -% -% Revision 1.3 2007/03/19 16:56:21 roboos -% changed representation of waveforms from cell array into nsample X nspikes numeric array -% -% Revision 1.2 2005/09/09 12:27:15 roboos -% implemented the core functionality of the function -% -% Revision 1.1 2005/08/05 13:41:39 roboos -% new implementation -% - -if ~isa(nse.TimeStamp, 'uint64') - error('timestamps should be uint64'); -end - -% convert the data from uV into V -nse.dat = nse.dat * 1e-6; -% scale the data and convert to 16 bits, -% this has to be done prior to writing the header -ADMaxValue = double(intmax('int16')); -ADMaxVolts = max(abs(nse.dat(:))); -if ADMaxVolts>0 - ADBitVolts = ADMaxVolts / ADMaxValue; -else - ADBitVolts = 1; -end -nse.dat = int16(nse.dat / ADBitVolts); -% update the header with the calibration values -nse.hdr.ADBitVolts = ADBitVolts; -nse.hdr.ADMaxValue = ADMaxValue; - -% construct the header -buf = []; -buf = [buf sprintf('######## Neuralynx Data File Header\r\n')]; -buf = [buf sprintf('## File Name: %s\r\n', filename)]; -buf = [buf sprintf('## Time Opened: (m/d/y): %s At Time: %s\r\n', datestr(clock, 'mm/dd/yy'), datestr(clock, 'HH:MM:SS'))]; -f = fieldnames(nse.hdr); -for i=1:length(f) - v = getfield(nse.hdr, f{i}); - switch class(v) - case 'char' - buf = [buf sprintf('-%s\t%s\r\n', f{i}, v)]; - case 'double' - buf = [buf sprintf('-%s\t%g\r\n', f{i}, v)]; - otherwise - error('unknown class in writing header'); - end -end - -% pad the rest of the header with zeros -buf((end+1):16384) = 0; - -% write the header to file -fid = fopen(filename, 'wb', 'ieee-le'); -fwrite(fid, buf); - -% The format of a single electrode record is -% int64 TimeStamp -% int32 ScNumber -% int32 CellNumber -% int32 Param[0] ... Param[7] -% int16 Samp[0] ... int16 Samp[31] - -for i=1:size(nse.dat,2) - % write a single continuous data record - fwrite(fid, nse.TimeStamp(i) , 'int64'); - fwrite(fid, nse.ScNumber(i) , 'int32'); - fwrite(fid, nse.CellNumber(i), 'int32'); - fwrite(fid, nse.Param(:,i) , 'int32'); - fwrite(fid, nse.dat(:,i) , 'int16'); -end - -% close the file -fclose(fid); - diff --git a/external/fileio/private/write_neuralynx_nts.m b/external/fileio/private/write_neuralynx_nts.m deleted file mode 100644 index 1f16ec8..0000000 --- a/external/fileio/private/write_neuralynx_nts.m +++ /dev/null @@ -1,68 +0,0 @@ -function write_neuralynx_nts(filename, nts); - -% WRITE_NEURALYNX_NTS writes spike timestamps to a NTS file -% -% Use as -% write_neuralynx_nts(filename, nts) -% -% See also READ_NEURALYNX_NTS - -% Copyright (C) 2007, Robert Oostenveld -% -% $Log: write_neuralynx_nts.m,v $ -% Revision 1.1 2009/01/14 09:12:16 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.1 2007/03/21 17:12:04 roboos -% renamed NTE in NTS (filenames and function names) -% -% Revision 1.2 2007/03/21 12:53:51 roboos -% updated the documentation -% -% Revision 1.1 2007/03/14 16:08:09 roboos -% new implementation -% - -if ~isa(nts.TimeStamp, 'uint64') - error('timestamps should be uint64'); -end - -fid = fopen(filename, 'wb', 'ieee-le'); - -% construct the header -buf = []; -buf = [buf sprintf('######## Neuralynx Data File Header\r\n')]; -buf = [buf sprintf('## File Name: %s\r\n', filename)]; -buf = [buf sprintf('## Time Opened: (m/d/y): %s At Time: %s\r\n', datestr(clock, 'mm/dd/yy'), datestr(clock, 'HH:MM:SS'))]; -f = fieldnames(nts.hdr); -for i=1:length(f) - v = getfield(nts.hdr, f{i}); - switch class(v) - case 'char' - buf = [buf sprintf('-%s\t%s\r\n', f{i}, v)]; - case 'double' - buf = [buf sprintf('-%s\t%g\r\n', f{i}, v)]; - otherwise - error('unknown class in writing header'); - end -end - -% pad the rest of the header with zeros and write it to file -buf((end+1):16384) = 0; -fwrite(fid, buf); - -% The format of a clustered electrode record is -% int64 TimeStamp - -fwrite(fid, nts.TimeStamp, 'uint64'); - -% close the file -fclose(fid); - - - diff --git a/external/fileio/private/write_plexon_nex.m b/external/fileio/private/write_plexon_nex.m deleted file mode 100644 index d0bd72b..0000000 --- a/external/fileio/private/write_plexon_nex.m +++ /dev/null @@ -1,225 +0,0 @@ -function write_plexon_nex(filename, nex) - -% WRITE_PLEXON_NEX writes a Plexon *.nex file, which is a file -% containing action-potential (spike) timestamps and waveforms (spike -% channels), event timestamps (event channels), and continuous variable -% data (continuous A/D channels). -% -% Use as -% write_plexon_nex(filename, nex); -% -% The data structure should contain -% nex.hdr.FileHeader.Frequency = TimeStampFreq -% nex.hdr.VarHeader.Type = type, 5 for continuous -% nex.hdr.VarHeader.Name = label, padded to length 64 -% nex.hdr.VarHeader.WFrequency = sampling rate of continuous channel -% nex.var.dat = data -% nex.var.ts = timestamps -% -% See also READ_PLEXON_NEX, READ_PLEXON_PLX, READ_PLEXON_DDT - -% Copyright (C) 2007, Robert Oostenveld -% -% $Log: write_plexon_nex.m,v $ -% Revision 1.1 2009/01/14 09:24:45 roboos -% moved even more files from fileio to fileio/privtae, see previous log entry -% -% Revision 1.7 2009/01/08 13:03:09 roboos -% fixed bug in scaling of data, causing it to be clipped (thanks to Conrado) -% fixed bug in seperate scaling of data, the old code was not incorrect, but suboptimal -% -% Revision 1.6 2008/12/15 14:48:22 roboos -% read and write the data in uV/microvolt instead of in mV/milivolt -% -% Revision 1.5 2008/02/04 14:59:00 roboos -% do not rescale the input data if it is int16 already -% -% Revision 1.4 2007/10/08 13:00:24 roboos -% fixed small bug in including cvs identifier as comment in file header -% -% Revision 1.3 2007/03/21 13:01:37 roboos -% reimplemented the calibration and conversion into int16 values -% fixed a bug in the padding of the channel name to 64 chars -% -% Revision 1.2 2007/03/19 17:10:38 roboos -% implemented writing spike waveform data -% -% Revision 1.1 2007/02/21 09:50:51 roboos -% initial implementation -% - -% get the optional arguments, these are all required -% FirstTimeStamp = keyval('FirstTimeStamp', varargin); -% TimeStampFreq = keyval('TimeStampFreq', varargin); - -hdr = nex.hdr; - -UVtoMV = 1/1000; - -switch hdr.VarHeader.Type - case 5 - dat = nex.var.dat; % this is in microVolt - buf = zeros(size(dat), 'int16'); - nchans = size(dat,1); - nsamples = size(dat,2); - nwaves = 1; % only one continuous datasegment is supported - if length(hdr.VarHeader)~=nchans - error('incorrect number of channels'); - end - % convert the data from floating point into int16 values - % each channel gets its own optimal calibration factor - for varlop=1:nchans - ADMaxValue = double(intmax('int16')); - ADMaxUV = max(abs(dat(varlop,:))); % this is in microVolt - ADMaxMV = ADMaxUV/1000; % this is in miliVolt - if isa(dat, 'int16') - % do not rescale data that is already 16 bit - MVtoAD = 1; - elseif ADMaxMV==0 - % do not rescale the data if the data is zero - MVtoAD = 1; - elseif ADMaxMV>0 - % rescale the data so that it fits into the 16 bits with as little loss as possible - MVtoAD = ADMaxValue / ADMaxMV; - end - buf(varlop,:) = int16(double(dat) * UVtoMV * MVtoAD); - % remember the calibration value, it should be stored in the variable header - ADtoMV(varlop) = 1/MVtoAD; - end - dat = buf; - clear buf; - - case 3 - dat = nex.var.dat; % this is in microVolt - nchans = 1; % only one channel is supported - nsamples = size(dat,1); - nwaves = size(dat,2); - if length(hdr.VarHeader)~=nchans - error('incorrect number of channels'); - end - % convert the data from floating point into int16 values - ADMaxValue = double(intmax('int16')); - ADMaxUV = max(abs(dat(:))); % this is in microVolt - ADMaxMV = ADMaxUV/1000; % this is in miliVolt - if isa(dat, 'int16') - % do not rescale data that is already 16 bit - MVtoAD = 1; - elseif ADMaxMV==0 - % do not rescale the data if the data is zero - MVtoAD = 1; - elseif ADMaxMV>0 - % rescale the data so that it fits into the 16 bits with as little loss as possible - MVtoAD = ADMaxValue / ADMaxMV; - end - dat = int16(double(dat) * UVtoMV * MVtoAD); - % remember the calibration value, it should be stored in the variable header - ADtoMV = 1/MVtoAD; - - otherwise - error('unsupported data type') -end % switch type - -% determine the first and last timestamp -ts = nex.var.ts; -ts_beg = min(ts); -ts_end = 0; % FIXME - -fid = fopen(filename, 'wb', 'ieee-le'); - -% write the file header -write_NexFileHeader; - -% write the variable headers -for varlop=1:nchans - write_NexVarHeader; -end - -% write the variable data -for varlop=1:nchans - write_NexVarData; -end - -fclose(fid); -return - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% nested function for writing the details -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - function write_NexFileHeader - % prepare the two char buffers - buf1 = padstr('$Id: write_plexon_nex.m,v 1.1 2009/01/14 09:24:45 roboos Exp $', 256); - buf2 = char(zeros(1, 256)); - % write the stuff to the file - fwrite(fid, 'NEX1' , 'char'); % NexFileHeader = string NEX1 - fwrite(fid, 100 , 'int32'); % Version = version - fwrite(fid, buf1 , 'char'); % Comment = comment, 256 bytes - fwrite(fid, hdr.FileHeader.Frequency, 'double'); % Frequency = timestamped freq. - tics per second - fwrite(fid, ts_beg, 'int32'); % Beg = usually 0, minimum of all the timestamps in the file - fwrite(fid, ts_end, 'int32'); % End = maximum timestamp + 1 - fwrite(fid, nchans, 'int32'); % NumVars = number of variables in the first batch - fwrite(fid, 0 , 'int32'); % NextFileHeader = position of the next file header in the file, not implemented yet - fwrite(fid, buf2 , 'char'); % Padding = future expansion - end % of the nested function - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% nested function for writing the details -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - function write_NexVarHeader - filheadersize = 544; - varheadersize = 208; - offset = filheadersize + nchans*varheadersize + (varlop-1)*nsamples; - calib = ADtoMV(varlop); - % prepare the two char buffers - buf1 = padstr(hdr.VarHeader(varlop).Name, 64); - buf2 = char(zeros(1, 68)); - % write the continuous variable to the file - fwrite(fid, hdr.VarHeader.Type, 'int32'); % Type = 0 - neuron, 1 event, 2- interval, 3 - waveform, 4 - pop. vector, 5 - continuously recorded - fwrite(fid, 100, 'int32'); % Version = 100 - fwrite(fid, buf1, 'char'); % Name = variable name, 1x64 char - fwrite(fid, offset, 'int32'); % DataOffset = where the data array for this variable is located in the file - fwrite(fid, nwaves, 'int32'); % Count = number of events, intervals, waveforms or weights - fwrite(fid, 0, 'int32'); % WireNumber = neuron only, not used now - fwrite(fid, 0, 'int32'); % UnitNumber = neuron only, not used now - fwrite(fid, 0, 'int32'); % Gain = neuron only, not used now - fwrite(fid, 0, 'int32'); % Filter = neuron only, not used now - fwrite(fid, 0, 'double'); % XPos = neuron only, electrode position in (0,100) range, used in 3D - fwrite(fid, 0, 'double'); % YPos = neuron only, electrode position in (0,100) range, used in 3D - fwrite(fid, hdr.VarHeader.WFrequency, 'double'); % WFrequency = waveform and continuous vars only, w/f sampling frequency - fwrite(fid, calib, 'double'); % ADtoMV = waveform continuous vars only, coeff. to convert from A/D values to Millivolts - fwrite(fid, nsamples, 'int32'); % NPointsWave = waveform only, number of points in each wave - fwrite(fid, 0, 'int32'); % NMarkers = how many values are associated with each marker - fwrite(fid, 0, 'int32'); % MarkerLength = how many characters are in each marker value - fwrite(fid, buf2, 'char'); % Padding, 1x68 char - end % of the nested function - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% nested function for writing the details -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - function write_NexVarData - switch hdr.VarHeader.Type - case 5 - % this code only supports one continuous segment - index = 0; - fwrite(fid, ts , 'int32'); % timestamps, one for each continuous segment - fwrite(fid, index , 'int32'); % where to cut the segments, zero offset - fwrite(fid, dat(varlop,:) , 'int16'); % data - case 3 - fwrite(fid, ts , 'int32'); % timestamps, one for each spike - fwrite(fid, dat , 'int16'); % waveforms, one for each spike - otherwise - error('unsupported data type'); - end % switch - end % of the nested function - -end % of the primary function - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% subfunction for zero padding a char array to fixed length -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function str = padstr(str, num); -if length(str)>num - str = str(1:num); -else - str((end+1):num) = 0; -end -end % of the padstr subfunction diff --git a/external/fileio/private/yokogawa2grad.m b/external/fileio/private/yokogawa2grad.m deleted file mode 100644 index 379affd..0000000 --- a/external/fileio/private/yokogawa2grad.m +++ /dev/null @@ -1,148 +0,0 @@ -function grad = yokogawa2grad(hdr) - -% YOKOGAWA2GRAD converts the position and weights of all coils that -% compromise a gradiometer system into a structure that can be used -% by FieldTrip. -% -% See also READ_HEADER, CTF2GRAD, BTI2GRAD, FIF2GRAD - -% Copyright (C) 2005-2008, Robert Oostenveld -% -% $Log: yokogawa2grad.m,v $ -% Revision 1.1 2009/01/14 09:12:16 roboos -% The directory layout of fileio in cvs sofar did not include a -% private directory, but for the release of fileio all the low-level -% functions were moved to the private directory to make the distinction -% between the public API and the private low level functions. To fix -% this, I have created a private directory and moved all appropriate -% files from fileio to fileio/private. -% -% Revision 1.5 2008/12/24 13:49:25 roboos -% added suggested changes by Kaoru Amano, see email 19 Dec 2008 -% -% Revision 1.4 2008/12/18 11:53:20 roboos -% changed some comments and some slight cleanups, no functional change -% -% Revision 1.3 2008/12/18 08:31:23 roboos -% incorporated gradiometer, thanks to Kaoru Amano -% -% Revision 1.2 2008/05/15 13:20:36 roboos -% updated documentation -% -% Revision 1.1 2006/08/31 13:32:11 roboos -% moved from fieldtrip to fileio module -% -% Revision 1.1 2005/09/06 08:54:30 roboos -% new implementations for the Yokogawa 160 channel MEG system - - -if isfield(hdr, 'orig') - hdr = hdr.orig; % use the original header, not the FieldTrip header -end - -% The "channel_info" contains -% 1 channel number, zero offset -% 2 channel type, type of gradiometer -% 3 position x (in m) -% 4 position y (in m) -% 5 position z (in m) -% 6 orientation of first coil (theta in deg) -% 7 orientation from the 1st to 2nd coil for gradiometer (theta in deg) -% 8 orientation of first coil (phi in deg) -% 9 orientation from the 1st to 2nd coil for gradiometer (phi in deg) -% 10 coil size (in m) -% 11 baseline (in m) - -handles = definehandles; -isgrad = (hdr.channel_info(:,2)==handles.AxialGradioMeter | hdr.channel_info(:,2)==handles.PlannerGradioMeter); -grad.pnt = hdr.channel_info(isgrad,3:5)*100; % cm - -% Get orientation of the 1st coil -ori_1st = hdr.channel_info(find(isgrad),[6 8]); -% polar to x,y,z coordinates -ori_1st = ... - [sin(ori_1st(:,1)/180*pi).*cos(ori_1st(:,2)/180*pi) ... - sin(ori_1st(:,1)/180*pi).*sin(ori_1st(:,2)/180*pi) ... - cos(ori_1st(:,1)/180*pi)]; -grad.ori = ori_1st; - -% Get orientation from the 1st to 2nd coil for gradiometer -ori_1st_to_2nd = hdr.channel_info(find(isgrad),[7 9]); -% polar to x,y,z coordinates -ori_1st_to_2nd = ... - [sin(ori_1st_to_2nd(:,1)/180*pi).*cos(ori_1st_to_2nd(:,2)/180*pi) ... - sin(ori_1st_to_2nd(:,1)/180*pi).*sin(ori_1st_to_2nd(:,2)/180*pi) ... - cos(ori_1st_to_2nd(:,1)/180*pi)]; -% Get baseline -baseline = hdr.channel_info(isgrad,size(hdr.channel_info,2)); - -% Define the location and orientation of 2nd coil -for i=1:sum(isgrad) - if hdr.channel_info(i,2) == handles.AxialGradioMeter - grad.pnt(i+sum(isgrad),:) = [grad.pnt(i,:)+ori_1st(i,:)*baseline(i)*100]; - grad.ori(i+sum(isgrad),:) = -ori_1st(i,:); - elseif hdr.channel_info(i,2) == handles.PlannerGradioMeter - grad.pnt(i+sum(isgrad),:) = [grad.pnt(i,:)+ori_1st_to_2nd(i,:)*baseline(i)*100]; - grad.ori(i+sum(isgrad),:) = ori_1st(i,:); - end -end - -% Define the pair of 1st and 2nd coils for each gradiometer -grad.tra = repmat(diag(ones(1,size(grad.pnt,1)/2),0),1,2); - -% Make the matrix sparse to speed up the multiplication in the forward -% computation with the coil-leadfield matrix to get the channel leadfield -grad.tra = sparse(grad.tra); - -tmp = hdr.channel_info(isgrad,1); -for i=1:size(tmp,1) - grad.label{i,1} = num2str(tmp(i)+1); -end -grad.unit='cm'; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% this defines some usefull constants -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function handles = definehandles; -handles.output = []; -handles.sqd_load_flag = false; -handles.mri_load_flag = false; -handles.NullChannel = 0; -handles.MagnetoMeter = 1; -handles.AxialGradioMeter = 2; -handles.PlannerGradioMeter = 3; -handles.RefferenceChannelMark = hex2dec('0100'); -handles.RefferenceMagnetoMeter = bitor( handles.RefferenceChannelMark, handles.MagnetoMeter ); -handles.RefferenceAxialGradioMeter = bitor( handles.RefferenceChannelMark, handles.AxialGradioMeter ); -handles.RefferencePlannerGradioMeter = bitor( handles.RefferenceChannelMark, handles.PlannerGradioMeter ); -handles.TriggerChannel = -1; -handles.EegChannel = -2; -handles.EcgChannel = -3; -handles.EtcChannel = -4; -handles.NonMegChannelNameLength = 32; -handles.DefaultMagnetometerSize = (4.0/1000.0); % ????4.0mm???????` -handles.DefaultAxialGradioMeterSize = (15.5/1000.0); % ???a15.5mm???~?? -handles.DefaultPlannerGradioMeterSize = (12.0/1000.0); % ????12.0mm???????` -handles.AcqTypeContinuousRaw = 1; -handles.AcqTypeEvokedAve = 2; -handles.AcqTypeEvokedRaw = 3; -handles.sqd = []; -handles.sqd.selected_start = []; -handles.sqd.selected_end = []; -handles.sqd.axialgradiometer_ch_no = []; -handles.sqd.axialgradiometer_ch_info = []; -handles.sqd.axialgradiometer_data = []; -handles.sqd.plannergradiometer_ch_no = []; -handles.sqd.plannergradiometer_ch_info = []; -handles.sqd.plannergradiometer_data = []; -handles.sqd.nullchannel_ch_no = []; -handles.sqd.nullchannel_data = []; -handles.sqd.selected_time = []; -handles.sqd.sample_rate = []; -handles.sqd.sample_count = []; -handles.sqd.pretrigger_length = []; -handles.sqd.matching_info = []; -handles.sqd.source_info = []; -handles.sqd.mri_info = []; -handles.mri = []; - diff --git a/external/forwinv/README b/external/forwinv/README deleted file mode 100644 index 8a23bb6..0000000 --- a/external/forwinv/README +++ /dev/null @@ -1,25 +0,0 @@ -This is a special release of the FieldTrip FORWINV module for -inclusion in SPM8. It contains functions for forward and inverse -modelling of EEG and MEG data (i.e. source estimation), based on a -choise of volume conduction models, including spherical and realistic -models. - -This particular release has wrapper functions that adhere to the -spm_xxx function naming style. The public functions are available -as ft_xxx, whereas all dependencies are hidden in the private -directory. If you are interested in using this toolbox independent -of SPM8, I suggest that you visit http://www.ru.nl/fcdonders/fieldtrip -and download a normal and more complete version. - -For more information please visit http://www.ru.nl/fcdonders/fieldtrip -and www.fil.ion.ucl.ac.uk/spm. - -The FieldTrip software is free but copyrighted software, distributed -under the terms of the GNU General Public Licence as published by -the Free Software Foundation (either version 2, or at your option -any later version). See the file COPYING for more details. - -Copyright (C) 1999-2003, Department of Medical Physics, Radboud University Nijmegen, The Netherlands -Copyright (C) 2003-2005, Center for Sensory-Motor Interaction, Aalborg University, Denmark -Copyright (C) 2003-2008, F.C. Donders Centre for Cognitive Neuroimaging, Nijmegen, The Netherlands - diff --git a/external/forwinv/forwinv_apply_montage.m b/external/forwinv/forwinv_apply_montage.m deleted file mode 100644 index 8c9c0ae..0000000 --- a/external/forwinv/forwinv_apply_montage.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'forwinv_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/forwinv/forwinv_beamformer_dics.m b/external/forwinv/forwinv_beamformer_dics.m deleted file mode 100644 index 8c9c0ae..0000000 --- a/external/forwinv/forwinv_beamformer_dics.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'forwinv_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/forwinv/forwinv_beamformer_lcmv.m b/external/forwinv/forwinv_beamformer_lcmv.m deleted file mode 100644 index 8c9c0ae..0000000 --- a/external/forwinv/forwinv_beamformer_lcmv.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'forwinv_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/forwinv/forwinv_beamformer_pcc.m b/external/forwinv/forwinv_beamformer_pcc.m deleted file mode 100644 index 8c9c0ae..0000000 --- a/external/forwinv/forwinv_beamformer_pcc.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'forwinv_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/forwinv/forwinv_compute_leadfield.m b/external/forwinv/forwinv_compute_leadfield.m deleted file mode 100644 index 8c9c0ae..0000000 --- a/external/forwinv/forwinv_compute_leadfield.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'forwinv_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/forwinv/forwinv_convert_units.m b/external/forwinv/forwinv_convert_units.m deleted file mode 100644 index 8c9c0ae..0000000 --- a/external/forwinv/forwinv_convert_units.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'forwinv_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/forwinv/forwinv_dipole_fit.m b/external/forwinv/forwinv_dipole_fit.m deleted file mode 100644 index 8c9c0ae..0000000 --- a/external/forwinv/forwinv_dipole_fit.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'forwinv_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/forwinv/forwinv_inside_vol.m b/external/forwinv/forwinv_inside_vol.m deleted file mode 100644 index 8c9c0ae..0000000 --- a/external/forwinv/forwinv_inside_vol.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'forwinv_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/forwinv/forwinv_minimumnormestimate.m b/external/forwinv/forwinv_minimumnormestimate.m deleted file mode 100644 index 8c9c0ae..0000000 --- a/external/forwinv/forwinv_minimumnormestimate.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'forwinv_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/forwinv/forwinv_music.m b/external/forwinv/forwinv_music.m deleted file mode 100644 index 8c9c0ae..0000000 --- a/external/forwinv/forwinv_music.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'forwinv_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/forwinv/forwinv_prepare_vol_sens.m b/external/forwinv/forwinv_prepare_vol_sens.m deleted file mode 100644 index 8c9c0ae..0000000 --- a/external/forwinv/forwinv_prepare_vol_sens.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'forwinv_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/forwinv/forwinv_residualvariance.m b/external/forwinv/forwinv_residualvariance.m deleted file mode 100644 index 8c9c0ae..0000000 --- a/external/forwinv/forwinv_residualvariance.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'forwinv_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/forwinv/forwinv_senstype.m b/external/forwinv/forwinv_senstype.m deleted file mode 100644 index 8c9c0ae..0000000 --- a/external/forwinv/forwinv_senstype.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'forwinv_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/forwinv/forwinv_sourcedepth.m b/external/forwinv/forwinv_sourcedepth.m deleted file mode 100644 index 8c9c0ae..0000000 --- a/external/forwinv/forwinv_sourcedepth.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'forwinv_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/forwinv/forwinv_transform_headshape.m b/external/forwinv/forwinv_transform_headshape.m deleted file mode 100644 index 8c9c0ae..0000000 --- a/external/forwinv/forwinv_transform_headshape.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'forwinv_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/forwinv/forwinv_transform_sens.m b/external/forwinv/forwinv_transform_sens.m deleted file mode 100644 index 8c9c0ae..0000000 --- a/external/forwinv/forwinv_transform_sens.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'forwinv_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/forwinv/forwinv_transform_vol.m b/external/forwinv/forwinv_transform_vol.m deleted file mode 100644 index 8c9c0ae..0000000 --- a/external/forwinv/forwinv_transform_vol.m +++ /dev/null @@ -1,11 +0,0 @@ -function varargout = funname(varargin); - -% this is a SPM wrapper around a FieldTrip function - -% this part is variable -prefix = 'forwinv_'; - -% this part is fixed -funname = mfilename; -funhandle = str2func(funname((length(prefix)+1):end)); -[varargout{1:nargout}] = funhandle(varargin{:}); diff --git a/external/forwinv/private/apply_montage.m b/external/forwinv/private/apply_montage.m deleted file mode 100644 index ccf0716..0000000 --- a/external/forwinv/private/apply_montage.m +++ /dev/null @@ -1,226 +0,0 @@ -function [sens] = apply_montage(sens, montage, varargin) - -% APPLY_MONTAGE changes the montage of an electrode or gradiometer array. A -% montage can be used for EEG rereferencing, MEG synthetic gradients, MEG -% planar gradients or unmixing using ICA. This function applies the montage -% to the sensor array. The sensor array can subsequently be used for -% forward computation and source reconstruction of the data. -% -% Use as -% [sens] = apply_montage(sens, montage, ...) -% [data] = apply_montage(data, montage, ...) -% [montage] = apply_montage(montage1, montage2, ...) -% where the input is a FieldTrip sensor definition as obtained from READ_SENS -% or a FieldTrip raw data structure as obtained from PREPROCESSING. -% -% A montage is specified as a structure with the fields -% montage.tra = MxN matrix -% montage.labelnew = Mx1 cell-array -% montage.labelorg = Nx1 cell-array -% -% Additional options should be specified in key-value pairs and can be -% 'keepunused' string, 'yes' or 'no' (default = 'no') -% 'inverse' string, 'yes' or 'no' (default = 'no') -% -% If the first input is a montage, then the second input montage will be -% applied to the first. In effect the resulting montage will first do -% montage1, then montage2. -% -% See also READ_SENS, TRANSFORM_SENS - -% Copyright (C) 2008, Robert Oostenveld -% -% $Log: apply_montage.m,v $ -% Revision 1.19 2009/07/02 16:14:15 roboos -% allow to apply one montage on another one -% -% Revision 1.18 2009/07/02 09:18:41 vlalit -% Fixing a bug in building an inverse montage (confusion between 'montage' and 'tra') -% -% Revision 1.17 2009/07/01 09:21:37 roboos -% changed handling of rank-reduced montage for inversion, give warning -% removed the modification by vladimir for the sequential application of montages -% -% Revision 1.16 2009/06/27 13:24:54 vlalit -% Additional fixes to make custom balancing work. -% -% Revision 1.15 2009/06/26 17:39:17 vlalit -% Added the possiblity to handle custom montages applied to MEG sensors (for removing -% spatial confounds). Hopefully there won't be major side effects. -% -% Revision 1.14 2009/06/17 10:13:05 roboos -% improved documentation -% -% Revision 1.13 2009/03/26 11:07:40 roboos -% start with an explicit check on the channel number -% -% Revision 1.12 2009/03/26 11:02:01 jansch -% changed order of unused channels (was initially sorted alphabetically) into -% how the appear in the input data -% -% Revision 1.11 2008/12/15 12:58:56 roboos -% convert from sparse to full when data is single precision -% -% Revision 1.10 2008/09/10 08:42:23 roboos -% fixed small bug, thanks to Vladimir -% -% Revision 1.9 2008/08/21 12:03:37 roboos -% fixed small typo related to last commit -% -% Revision 1.8 2008/08/21 12:01:47 roboos -% selection of rows and columns to be removed had to be inverted, thanks to Thilo -% -% Revision 1.7 2008/08/13 16:14:46 roboos -% remove columns and rows for montage channels that are not present in the data -% -% Revision 1.6 2008/07/17 14:46:06 roboos -% check on presence of channels required for montage was incorrect -% -% Revision 1.5 2008/05/15 15:08:51 roboos -% added support for applying the inverse montage (i.e. undo a previous montage) -% added support for applying the montage to preprocessed/raw data -% -% Revision 1.4 2008/05/13 11:43:27 roboos -% fixed bug in selempty -% -% Revision 1.3 2008/05/13 09:08:19 roboos -% fixed bug in assignment -% added option keepunused=yes|no -% -% Revision 1.2 2008/04/28 14:14:29 roboos -% added closing bracket -% -% Revision 1.1 2008/04/14 20:16:37 roboos -% new implementation, required for spm integration -% - -% get optional input arguments -keepunused = keyval('keepunused', varargin{:}); if isempty(keepunused), keepunused = 'no'; end -inverse = keyval('inverse', varargin{:}); if isempty(inverse), inverse = 'no'; end - -% check the consistency of the input sensor array or data -if isfield(sens, 'labelorg') && isfield(sens, 'labelnew') - % the input data structure is also a montage, i.e. apply the montages sequentially - sens.label = sens.labelnew; -end - -% check the consistency of the montage -if size(montage.tra,1)~=length(montage.labelnew) - error('the number of channels in the montage is inconsistent'); -elseif size(montage.tra,2)~=length(montage.labelorg) - error('the number of channels in the montage is inconsistent'); -end - -if strcmp(inverse, 'yes') - % apply the inverse montage, i.e. undo a previously applied montage - tmp.labelnew = montage.labelorg; % swap around - tmp.labelorg = montage.labelnew; % swap around - tmp.tra = full(montage.tra); - if rank(tmp.tra) < length(tmp.tra) - warning('the linear projection for the montage is not full-rank, the resulting data will have reduced dimensionality'); - tmp.tra = pinv(tmp.tra); - else - tmp.tra = inv(tmp.tra); - end - montage = tmp; -end - -% use default transfer from sensors to channels if not specified -if ~isfield(sens, 'tra') && ~isfield(sens, 'trial') - nchan = size(sens.pnt,1); - sens.tra = sparse(eye(nchan)); -end - -% select and keep the columns that are non-empty, i.e. remove the empty columns -selcol = find(~all(montage.tra==0, 1)); -montage.tra = montage.tra(:,selcol); -montage.labelorg = montage.labelorg(selcol); -clear selcol - -% select and remove the columns corresponding to channels that are not present in the original data -remove = setdiff(montage.labelorg, intersect(montage.labelorg, sens.label)); -selcol = match_str(montage.labelorg, remove); -% we cannot just remove the colums, all rows that depend on it should also be removed -selrow = false(length(montage.labelnew),1); -for i=1:length(selcol) - selrow = selrow & (montage.tra(:,selcol(i))~=0); -end -% convert from indices to logical vector -selcol = indx2logical(selcol, length(montage.labelorg)); -% remove rows and columns -montage.labelorg = montage.labelorg(~selcol); -montage.labelnew = montage.labelnew(~selrow); -montage.tra = montage.tra(~selrow, ~selcol); -clear remove selcol selrow i -% add columns for the channels that are present in the data but not involved in the montage, and stick to the original order in the data -[add, ix] = setdiff(sens.label, montage.labelorg); -add = sens.label(sort(ix)); -m = size(montage.tra,1); -n = size(montage.tra,2); -k = length(add); -if strcmp(keepunused, 'yes') - % add the channels that are not rereferenced to the input and output - montage.tra((m+(1:k)),(n+(1:k))) = eye(k); - montage.labelorg = cat(1, montage.labelorg(:), add(:)); - montage.labelnew = cat(1, montage.labelnew(:), add(:)); -else - % add the channels that are not rereferenced to the input montage only - montage.tra(:,(n+(1:k))) = zeros(m,k); - montage.labelorg = cat(1, montage.labelorg(:), add(:)); -end -clear add m n k - -% determine whether all channels are unique -m = size(montage.tra,1); -n = size(montage.tra,2); -if length(unique(montage.labelnew))~=m - error('not all output channels of the montage are unique'); -end -if length(unique(montage.labelorg))~=n - error('not all input channels of the montage are unique'); -end - -% determine whether all channels that have to be rereferenced are available -if length(intersect(sens.label, montage.labelorg))~=length(montage.labelorg) - error('not all channels that are required in the montage are available in the data'); -end - -% reorder the columns of the montage matrix -[selsens, selmont] = match_str(sens.label, montage.labelorg); -montage.tra = sparse(montage.tra(:,selmont)); -montage.labelorg = montage.labelorg(selmont); - -if isfield(sens, 'labelorg') && isfield(sens, 'labelnew') - % apply the montage on top of the other montage - sens = rmfield(sens, 'label'); - sens.tra = montage.tra * sens.tra; - sens.labelnew = montage.labelnew; - -elseif isfield(sens, 'tra') - % apply the montage to the sensor array - sens.tra = montage.tra * sens.tra; - sens.label = montage.labelnew; - -elseif isfield(sens, 'trial') - % apply the montage to the data that was preprocessed using fieldtrip - Ntrials = numel(sens.trial); - for i=1:Ntrials - fprintf('processing trial %d from %d\n', i, Ntrials); - if isa(sens.trial{i}, 'single') - % sparse matrices and single precision do not match - sens.trial{i} = full(montage.tra) * sens.trial{i}; - else - sens.trial{i} = montage.tra * sens.trial{i}; - end - end - sens.label = montage.labelnew; -else - error('unrecognized input'); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% HELPER FUNCTION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function y = indx2logical(x, n) -y = false(1,n); -y(x) = true; diff --git a/external/forwinv/private/avgref.m b/external/forwinv/private/avgref.m deleted file mode 100644 index 558db08..0000000 --- a/external/forwinv/private/avgref.m +++ /dev/null @@ -1,46 +0,0 @@ -function [data] = avgref(data, sel); - -% AVGREF computes the average reference in each column -% [data] = avgref(data) -% -% or it computes the re-referenced data relative to the -% average over the selected channels -% [data] = avgref(data, sel) - -% Copyright (C) 1998-2002, Robert Oostenveld -% -% $Log: avgref.m,v $ -% Revision 1.2 2003/03/17 10:37:28 roberto -% improved general help comments and added copyrights -% - -% determine the dimension of the data -if length(size(data))==3 - % multiple epochs - dim=3; -else - % single epoch with multiple channels - dim=2; -end - -if nargin==1 - % default is to use all channels for average referencing - if dim==3 - sel=1:size(data,2); - else - sel=1:size(data,1); - end -end - -if dim==3 - % the data contains multiple epochs - for epoch=1:size(data,1) - reference = mean(squeeze(data(epoch,sel,:)), 1); - data(epoch,:,:) = squeeze(data(epoch,:,:)) - repmat(reference, size(data,2), 1); - end -else - % the data contains a single epoch - reference = mean(data(sel,:), 1); - data = data - repmat(reference, size(data,1), 1); -end - diff --git a/external/forwinv/private/beamformer_dics.m b/external/forwinv/private/beamformer_dics.m deleted file mode 100644 index 3cf9393..0000000 --- a/external/forwinv/private/beamformer_dics.m +++ /dev/null @@ -1,536 +0,0 @@ -function [dipout] = beamformer_dics(dip, grad, vol, dat, Cf, varargin) - -% BEAMFORMER_DICS scans on pre-defined dipole locations with a single dipole -% and returns the beamformer spatial filter output for a dipole on every -% location. Dipole locations that are outside the head will return a -% NaN value. -% -% Use as -% [dipout] = beamformer_dics(dipin, grad, vol, dat, cov, varargin) -% where -% dipin is the input dipole model -% grad is the gradiometer definition -% vol is the volume conductor definition -% dat is the data matrix with the ERP or ERF -% cov is the data covariance or cross-spectral density matrix -% and -% dipout is the resulting dipole model with all details -% -% The input dipole model consists of -% dipin.pos positions for dipole, e.g. regular grid -% dipin.mom dipole orientation (optional) -% -% Additional options should be specified in key-value pairs and can be -% 'Pr' = power of the external reference channel -% 'Cr' = cross spectral density between all data channels and the external reference channel -% 'refdip' = location of dipole with which coherence is computed -% 'lambda' = regularisation parameter -% 'powmethod' = can be 'trace' or 'lambda1' -% 'feedback' = give progress indication, can be 'text', 'gui' or 'none' -% 'fixedori' = use fixed or free orientation, can be 'yes' or 'no' -% 'projectnoise' = project noise estimate through filter, can be 'yes' or 'no' -% 'realfilter' = construct a real-valued filter, can be 'yes' or 'no' -% 'keepfilter' = remember the beamformer filter, can be 'yes' or 'no' -% 'keepleadfield' = remember the forward computation, can be 'yes' or 'no' -% 'keepcsd' = remember the estimated cross-spectral density, can be 'yes' or 'no' -% -% These options influence the forward computation of the leadfield -% 'reducerank' = reduce the leadfield rank, can be 'no' or a number (e.g. 2) -% 'normalize' = normalize the leadfield -% 'normalizeparam' = parameter for depth normalization (default = 0.5) -% -% If the dipole definition only specifies the dipole location, a rotating -% dipole (regional source) is assumed on each location. If a dipole moment -% is specified, its orientation will be used and only the strength will -% be fitted to the data. - -% Copyright (C) 2003-2008, Robert Oostenveld -% -% $Log: beamformer_dics.m,v $ -% Revision 1.15 2009/06/17 13:40:37 roboos -% small change in the order of the code for subspace projection -% -% Revision 1.14 2009/05/14 19:25:12 roboos -% added a FIXME comment -% -% Revision 1.13 2009/03/24 13:13:33 roboos -% fixed bug for coh_refchan in case trace was used for power estimate -% -% Revision 1.12 2009/01/06 10:25:32 roboos -% fixed a bug for leadfield computation in case a pre-specified dipole -% orientation is present. The bug would have caused a crash in case -% the particular combination of options would have been used. -% -% Revision 1.11 2008/12/04 16:44:29 jansch -% fixed typo in line 260 (thanks to Jurrian) -% -% Revision 1.10 2008/12/04 11:45:13 jansch -% fixed bug in fixedori -% -% Revision 1.9 2008/08/13 16:13:38 roboos -% added option fixedori, not yet fully tested -% -% Revision 1.8 2008/08/13 13:47:42 roboos -% updated documentation -% -% Revision 1.7 2008/07/02 07:57:33 roboos -% allow specification of percentage noise in lambda, relative to trace(cov)/nchans -% -% Revision 1.6 2008/03/18 13:01:17 roboos -% added optional argument normalizeparam, is passed onto compute_leadfield -% -% Revision 1.5 2007/12/11 11:17:49 roboos -% fixed bug in handling of prespecified dipole moment -% -% Revision 1.4 2006/10/16 15:18:35 roboos -% small change in comment -% -% Revision 1.3 2006/10/16 15:17:24 roboos -% fixed bug for powlambda/powtrace computation of noise (powlambda was hardcoded) -% also keep noise csd matrix if requested (projectnoise & keepcsd) -% fixed obvious bug in progress indicator -% -% Revision 1.2 2006/10/12 10:17:31 roboos -% fixed bug in selecting dipoles on the inside positions only -% output cell-arrays are [] for outside points -% removed catch for mom, fixed dipoles should also work -% -% Revision 1.1 2006/10/12 09:07:07 roboos -% moved code from beamformer into stand-alone functions, for easier use and maintenance -% - -if mod(nargin-5,2) - % the first 5 arguments are fixed, the other arguments should come in pairs - error('invalid number of optional arguments'); -end - -% these optional settings do not have defaults -Pr = keyval('Pr', varargin); -Cr = keyval('Cr', varargin); -refdip = keyval('refdip', varargin); -powmethod = keyval('powmethod', varargin); % the default for this is set below -realfilter = keyval('realfilter', varargin); % the default for this is set below -% these settings pertain to the forward model, the defaults are set in compute_leadfield -reducerank = keyval('reducerank', varargin); -normalize = keyval('normalize', varargin); -normalizeparam = keyval('normalizeparam', varargin); -% these optional settings have defaults -feedback = keyval('feedback', varargin); if isempty(feedback), feedback = 'text'; end -keepcsd = keyval('keepcsd', varargin); if isempty(keepcsd), keepcsd = 'no'; end -keepfilter = keyval('keepfilter', varargin); if isempty(keepfilter), keepfilter = 'no'; end -keepleadfield = keyval('keepleadfield', varargin); if isempty(keepleadfield), keepleadfield = 'no'; end -lambda = keyval('lambda', varargin); if isempty(lambda ), lambda = 0; end -projectnoise = keyval('projectnoise', varargin); if isempty(projectnoise), projectnoise = 'yes'; end -fixedori = keyval('fixedori', varargin); if isempty(fixedori), fixedori = 'no'; end - -% convert the yes/no arguments to the corresponding logical values -keepcsd = strcmp(keepcsd, 'yes'); -keepfilter = strcmp(keepfilter, 'yes'); -keepleadfield = strcmp(keepleadfield, 'yes'); -projectnoise = strcmp(projectnoise, 'yes'); -fixedori = strcmp(fixedori, 'yes'); -% FIXME besides regular/complex lambda1, also implement a real version - -% default is to use the largest singular value of the csd matrix, see Gross 2001 -if isempty(powmethod) - powmethod = 'lambda1'; -end - -% default is to be consistent with the original description of DICS in Gross 2001 -if isempty(realfilter) - realfilter = 'no'; -end - -% use these two logical flags instead of doing the string comparisons each time again -powtrace = strcmp(powmethod, 'trace'); -powlambda1 = strcmp(powmethod, 'lambda1'); - -if ~isempty(Cr) - % ensure that the cross-spectral density with the reference signal is a column matrix - Cr = Cr(:); -end - -if isfield(dip, 'mom') && fixedori - error('you cannot specify a dipole orientation and fixedmom simultaneously'); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% find the dipole positions that are inside/outside the brain -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if ~isfield(dip, 'inside') && ~isfield(dip, 'outside'); - [dip.inside, dip.outside] = find_inside_vol(dip.pos, vol); -elseif isfield(dip, 'inside') && ~isfield(dip, 'outside'); - dip.outside = setdiff(1:size(dip.pos,1), dip.inside); -elseif ~isfield(dip, 'inside') && isfield(dip, 'outside'); - dip.inside = setdiff(1:size(dip.pos,1), dip.outside); -end - -% select only the dipole positions inside the brain for scanning -dip.origpos = dip.pos; -dip.originside = dip.inside; -dip.origoutside = dip.outside; -if isfield(dip, 'mom') - dip.mom = dip.mom(:,dip.inside); -end -if isfield(dip, 'leadfield') - fprintf('using precomputed leadfields\n'); - dip.leadfield = dip.leadfield(dip.inside); -end -if isfield(dip, 'filter') - fprintf('using precomputed filters\n'); - dip.filter = dip.filter(dip.inside); -end -if isfield(dip, 'subspace') - fprintf('using subspace projection\n'); - dip.subspace = dip.subspace(dip.inside); -end -dip.pos = dip.pos(dip.inside, :); -dip.inside = 1:size(dip.pos,1); -dip.outside = []; - -% dics has the following sub-methods, which depend on the function input arguments -% power only, cortico-muscular coherence and cortico-cortical coherence -if ~isempty(Cr) && ~isempty(Pr) && isempty(refdip) - % compute cortico-muscular coherence, using reference cross spectral density - submethod = 'dics_refchan'; -elseif isempty(Cr) && isempty(Pr) && ~isempty(refdip) - % compute cortico-cortical coherence with a dipole at the reference position - submethod = 'dics_refdip'; -elseif isempty(Cr) && isempty(Pr) && isempty(refdip) - % only compute power of a dipole at the grid positions - submethod = 'dics_power'; -else - error('invalid combination of input arguments for dics'); -end - -isrankdeficient = (rank(Cf) m - X = pinv(A',varargin{:})'; -else - [U,S,V] = svd(A,0); - if m > 1, s = diag(S); - elseif m == 1, s = S(1); - else s = 0; - end - if nargin == 2 - tol = varargin{1}; - else - tol = 10 * max(m,n) * max(s) * eps; - end - r = sum(s > tol); - if (r == 0) - X = zeros(size(A'),class(A)); - else - s = diag(ones(r,1)./s(1:r)); - X = V(:,1:r)*s*U(:,1:r)'; - end -end - diff --git a/external/forwinv/private/beamformer_lcmv.m b/external/forwinv/private/beamformer_lcmv.m deleted file mode 100644 index 260846a..0000000 --- a/external/forwinv/private/beamformer_lcmv.m +++ /dev/null @@ -1,422 +0,0 @@ -function [dipout] = beamformer_lcmv(dip, grad, vol, dat, Cy, varargin) - -% BEAMFORMER_LCMV scans on pre-defined dipole locations with a single dipole -% and returns the beamformer spatial filter output for a dipole on every -% location. Dipole locations that are outside the head will return a -% NaN value. -% -% Use as -% [dipout] = beamformer_lcmv(dipin, grad, vol, dat, cov, varargin) -% where -% dipin is the input dipole model -% grad is the gradiometer definition -% vol is the volume conductor definition -% dat is the data matrix with the ERP or ERF -% cov is the data covariance or cross-spectral density matrix -% and -% dipout is the resulting dipole model with all details -% -% The input dipole model consists of -% dipin.pos positions for dipole, e.g. regular grid -% dipin.mom dipole orientation (optional) -% -% Additional options should be specified in key-value pairs and can be -% 'lambda' = regularisation parameter -% 'powmethod' = can be 'trace' or 'lambda1' -% 'feedback' = give progress indication, can be 'text', 'gui' or 'none' (default) -% 'fixedori' = use fixed or free orientation, can be 'yes' or 'no' -% 'projectnoise' = project noise estimate through filter, can be 'yes' or 'no' -% 'projectmom' = project the dipole moment timecourse on the direction of maximal power, can be 'yes' or 'no' -% 'keepfilter' = remember the beamformer filter, can be 'yes' or 'no' -% 'keepleadfield' = remember the forward computation, can be 'yes' or 'no' -% 'keepmom' = remember the estimated dipole moment, can be 'yes' or 'no' -% 'keepcov' = remember the estimated dipole covariance, can be 'yes' or 'no' -% -% These options influence the forward computation of the leadfield -% 'reducerank' = reduce the leadfield rank, can be 'no' or a number (e.g. 2) -% 'normalize' = normalize the leadfield -% 'normalizeparam' = parameter for depth normalization (default = 0.5) -% -% If the dipole definition only specifies the dipole location, a rotating -% dipole (regional source) is assumed on each location. If a dipole moment -% is specified, its orientation will be used and only the strength will -% be fitted to the data. - -% Copyright (C) 2003-2008, Robert Oostenveld -% -% $Log: beamformer_lcmv.m,v $ -% Revision 1.14 2009/03/23 21:14:42 roboos -% some whitespace changes, nothing functional -% -% Revision 1.13 2009/02/11 10:25:43 jansch -% added some comments -% -% Revision 1.12 2009/02/10 10:51:02 jansch -% implemented subspace projection (for eigenspace bf, sensor-array subsampling etc) -% -% Revision 1.11 2008/12/04 11:45:57 jansch -% made minor change in fixedori for consistency of code with respect to -% beamformer_dics (added real() and ctranspose) -% -% Revision 1.10 2008/08/13 16:13:38 roboos -% added option fixedori, not yet fully tested -% -% Revision 1.9 2008/08/13 13:47:42 roboos -% updated documentation -% -% Revision 1.8 2008/07/02 16:02:01 roboos -% fixed bug in % lambda -% -% Revision 1.7 2008/07/02 07:57:33 roboos -% allow specification of percentage noise in lambda, relative to trace(cov)/nchans -% -% Revision 1.6 2008/03/18 13:01:17 roboos -% added optional argument normalizeparam, is passed onto compute_leadfield -% -% Revision 1.5 2008/03/05 16:28:26 roboos -% added some dummy code for subspace projection, not yet finished -% -% Revision 1.4 2007/12/11 11:17:49 roboos -% fixed bug in handling of prespecified dipole moment -% -% Revision 1.3 2006/10/16 15:19:44 roboos -% added keepcov option, also in combination with projectnoise -% fixed obvious bug for progress indicator -% -% Revision 1.2 2006/10/12 10:17:31 roboos -% fixed bug in selecting dipoles on the inside positions only -% output cell-arrays are [] for outside points -% removed catch for mom, fixed dipoles should also work -% -% Revision 1.1 2006/10/12 09:07:07 roboos -% moved code from beamformer into stand-alone functions, for easier use and maintenance -% - -if mod(nargin-5,2) - % the first 5 arguments are fixed, the other arguments should come in pairs - error('invalid number of optional arguments'); -end - -% these optional settings do not have defaults -powmethod = keyval('powmethod', varargin); % the default for this is set below -subspace = keyval('subspace', varargin); % used to implement an "eigenspace beamformer" as described in Sekihara et al. 2002 in HBM -% these settings pertain to the forward model, the defaults are set in compute_leadfield -reducerank = keyval('reducerank', varargin); -normalize = keyval('normalize', varargin); -normalizeparam = keyval('normalizeparam', varargin); -% these optional settings have defaults -feedback = keyval('feedback', varargin); if isempty(feedback), feedback = 'text'; end -keepfilter = keyval('keepfilter', varargin); if isempty(keepfilter), keepfilter = 'no'; end -keepleadfield = keyval('keepleadfield', varargin); if isempty(keepleadfield), keepleadfield = 'no'; end -keepcov = keyval('keepcov', varargin); if isempty(keepcov), keepcov = 'no'; end -keepmom = keyval('keepmom', varargin); if isempty(keepmom), keepmom = 'yes'; end -lambda = keyval('lambda', varargin); if isempty(lambda ), lambda = 0; end -projectnoise = keyval('projectnoise', varargin); if isempty(projectnoise), projectnoise = 'yes'; end -projectmom = keyval('projectmom', varargin); if isempty(projectmom), projectmom = 'no'; end -fixedori = keyval('fixedori', varargin); if isempty(fixedori), fixedori = 'no'; end - -% convert the yes/no arguments to the corresponding logical values -keepfilter = strcmp(keepfilter, 'yes'); -keepleadfield = strcmp(keepleadfield, 'yes'); -keepcov = strcmp(keepcov, 'yes'); -keepmom = strcmp(keepmom, 'yes'); -projectnoise = strcmp(projectnoise, 'yes'); -projectmom = strcmp(projectmom, 'yes'); -fixedori = strcmp(fixedori, 'yes'); - -% default is to use the trace of the covariance matrix, see Van Veen 1997 -if isempty(powmethod) - powmethod = 'trace'; -end - -% use these two logical flags instead of doing the string comparisons each time again -powtrace = strcmp(powmethod, 'trace'); -powlambda1 = strcmp(powmethod, 'lambda1'); - -if isfield(dip, 'mom') && fixedori - error('you cannot specify a dipole orientation and fixedmom simultaneously'); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% find the dipole positions that are inside/outside the brain -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if ~isfield(dip, 'inside') && ~isfield(dip, 'outside'); - [dip.inside, dip.outside] = find_inside_vol(dip.pos, vol); -elseif isfield(dip, 'inside') && ~isfield(dip, 'outside'); - dip.outside = setdiff(1:size(dip.pos,1), dip.inside); -elseif ~isfield(dip, 'inside') && isfield(dip, 'outside'); - dip.inside = setdiff(1:size(dip.pos,1), dip.outside); -end - -% select only the dipole positions inside the brain for scanning -dip.origpos = dip.pos; -dip.originside = dip.inside; -dip.origoutside = dip.outside; -if isfield(dip, 'mom') - dip.mom = dip.mom(:, dip.inside); -end -if isfield(dip, 'leadfield') - fprintf('using precomputed leadfields\n'); - dip.leadfield = dip.leadfield(dip.inside); -end -if isfield(dip, 'filter') - fprintf('using precomputed filters\n'); - dip.filter = dip.filter(dip.inside); -end -if isfield(dip, 'subspace') - fprintf('using subspace projection\n'); - dip.subspace = dip.subspace(dip.inside); -end -dip.pos = dip.pos(dip.inside, :); -dip.inside = 1:size(dip.pos,1); -dip.outside = []; - -isrankdeficient = (rank(Cy)=1 it is the number of largest eigenvalues - dat_pre_subspace = dat; - Cy_pre_subspace = Cy; - [u, s, v] = svd(real(Cy)); - if subspace<1, - sel = find(diag(s)./s(1,1) > subspace); - subspace = max(sel); - else - Cy = s(1:subspace,1:subspace); - % this is equivalent to subspace*Cy*subspace' but behaves well numerically - % by construction. - invCy = diag(1./diag(Cy)); - subspace = u(:,1:subspace)'; - dat = subspace*dat; - end - else - dat_pre_subspace = dat; - Cy_pre_subspace = Cy; - Cy = subspace*Cy*subspace'; % here the subspace can be different from - % the singular vectors of Cy, so we have to do the sandwiching as opposed - % to line 216 - invCy = pinv(Cy); - dat = subspace*dat; - end -end - -% start the scanning with the proper metric -progress('init', feedback, 'scanning grid'); - -for i=1:size(dip.pos,1) - if isfield(dip, 'leadfield') - % reuse the leadfield that was previously computed - lf = dip.leadfield{i}; - elseif isfield(dip, 'mom') - % compute the leadfield for a fixed dipole orientation - lf = compute_leadfield(dip.pos(i,:), grad, vol, 'reducerank', reducerank, 'normalize', normalize, 'normalizeparam', normalizeparam) * dip.mom(:,i); - else - % compute the leadfield - lf = compute_leadfield(dip.pos(i,:), grad, vol, 'reducerank', reducerank, 'normalize', normalize, 'normalizeparam', normalizeparam); - end - - if isfield(dip, 'subspace') - % do subspace projection of the forward model - lf = dip.subspace{i} * lf; - % the data and the covariance become voxel dependent due to the projection - dat = dip.subspace{i} * dat_pre_subspace; - Cy = dip.subspace{i} * (Cy_pre_subspace + lambda * eye(size(Cy_pre_subspace))) * dip.subspace{i}'; - invCy = pinv(dip.subspace{i} * (Cy_pre_subspace + lambda * eye(size(Cy_pre_subspace))) * dip.subspace{i}'); - elseif ~isempty(subspace) - % do subspace projection of the forward model only - lforig = lf; - lf = subspace * lf; - - % according to Kensuke's paper, the eigenspace bf boils down to projecting - % the 'traditional' filter onto the subspace - % spanned by the first k eigenvectors [u,s,v] = svd(Cy); filt = ESES*filt; - % ESES = u(:,1:k)*u(:,1:k)'; - % however, even though it seems that the shape of the filter is identical to - % the shape it is obtained with the following code, the w*lf=I does not hold. - end - - if fixedori - % compute the leadfield for the optimal dipole orientation - % subsequently the leadfield for only that dipole orientation will be used for the final filter computation - % filt = pinv(lf' * invCy * lf) * lf' * invCy; - % [u, s, v] = svd(real(filt * Cy * ctranspose(filt))); - % in this step the filter computation is not necessary, use the quick way to compute the voxel level covariance (cf. van Veen 1997) - [u, s, v] = svd(real(pinv(lf' * invCy *lf))); - eta = u(:,1); - lf = lf * eta; - if ~isempty(subspace), lforig = lforig * eta; end - dipout.ori{i} = eta; - end - - if isfield(dip, 'filter') - % use the provided filter - filt = dip.filter{i}; - else - % construct the spatial filter - filt = pinv(lf' * invCy * lf) * lf' * invCy; % van Veen eqn. 23, use PINV/SVD to cover rank deficient leadfield - end - if projectmom - [u, s, v] = svd(filt * Cy * ctranspose(filt)); - mom = u(:,1); - filt = (mom') * filt; - end - if powlambda1 - % dipout.pow(i) = lambda1(pinv(lf' * invCy * lf)); % this is more efficient if the filters are not present - dipout.pow(i) = lambda1(filt * Cy * ctranspose(filt)); % this is more efficient if the filters are present - elseif powtrace - % dipout.pow(i) = trace(pinv(lf' * invCy * lf)); % this is more efficient if the filters are not present, van Veen eqn. 24 - dipout.pow(i) = trace(filt * Cy * ctranspose(filt)); % this is more efficient if the filters are present - end - if keepcov - % compute the source covariance matrix - dipout.cov{i} = filt * Cy * ctranspose(filt); - end - if keepmom && ~isempty(dat) - % estimate the instantaneous dipole moment at the current position - dipout.mom{i} = filt * dat; - end - if projectnoise - % estimate the power of the noise that is projected through the filter - if powlambda1 - dipout.noise(i) = noise * lambda1(filt * ctranspose(filt)); - elseif powtrace - dipout.noise(i) = noise * trace(filt * ctranspose(filt)); - end - if keepcov - dipout.noisecov{i} = noise * filt * ctranspose(filt); - end - end - if keepfilter - if ~isempty(subspace) - dipout.filter{i} = filt*subspace; - else - dipout.filter{i} = filt; - end - end - if keepleadfield - if ~isempty(subspace) - dipout.leadfield{i} = lforig; - else - dipout.leadfield{i} = lf; - end - end - progress(i/size(dip.pos,1), 'scanning grid %d/%d\n', i, size(dip.pos,1)); -end - -progress('close'); - -dipout.inside = dip.originside; -dipout.outside = dip.origoutside; -dipout.pos = dip.origpos; - -% reassign the scan values over the inside and outside grid positions -if isfield(dipout, 'leadfield') - dipout.leadfield(dipout.inside) = dipout.leadfield; - dipout.leadfield(dipout.outside) = {[]}; -end -if isfield(dipout, 'filter') - dipout.filter(dipout.inside) = dipout.filter; - dipout.filter(dipout.outside) = {[]}; -end -if isfield(dipout, 'mom') - dipout.mom(dipout.inside) = dipout.mom; - dipout.mom(dipout.outside) = {[]}; -end -if isfield(dipout, 'ori') - dipout.ori(dipout.inside) = dipout.ori; - dipout.ori(dipout.outside) = {[]}; -end -if isfield(dipout, 'cov') - dipout.cov(dipout.inside) = dipout.cov; - dipout.cov(dipout.outside) = {[]}; -end -if isfield(dipout, 'noisecov') - dipout.noisecov(dipout.inside) = dipout.noisecov; - dipout.noisecov(dipout.outside) = {[]}; -end -if isfield(dipout, 'pow') - dipout.pow(dipout.inside) = dipout.pow; - dipout.pow(dipout.outside) = nan; -end -if isfield(dipout, 'noise') - dipout.noise(dipout.inside) = dipout.noise; - dipout.noise(dipout.outside) = nan; -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% helper function to obtain the largest singular value -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function s = lambda1(x) -% determine the largest singular value, which corresponds to the power along the dominant direction -s = svd(x); -s = s(1); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% helper function to compute the pseudo inverse. This is the same as the -% standard Matlab function, except that the default tolerance is twice as -% high. -% Copyright 1984-2004 The MathWorks, Inc. -% $Revision: 1.14 $ $Date: 2009/03/23 21:14:42 $ -% default tolerance increased by factor 2 (Robert Oostenveld, 7 Feb 2004) -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function X = pinv(A,varargin) -[m,n] = size(A); -if n > m - X = pinv(A',varargin{:})'; -else - [U,S,V] = svd(A,0); - if m > 1, s = diag(S); - elseif m == 1, s = S(1); - else s = 0; - end - if nargin == 2 - tol = varargin{1}; - else - tol = 10 * max(m,n) * max(s) * eps; - end - r = sum(s > tol); - if (r == 0) - X = zeros(size(A'),class(A)); - else - s = diag(ones(r,1)./s(1:r)); - X = V(:,1:r)*s*U(:,1:r)'; - end -end - diff --git a/external/forwinv/private/bounding_mesh.m b/external/forwinv/private/bounding_mesh.m deleted file mode 100644 index 781b29c..0000000 --- a/external/forwinv/private/bounding_mesh.m +++ /dev/null @@ -1,99 +0,0 @@ -function [inside] = bounding_mesh(pos, pnt, tri); - -% BOUNDING_MESH determines if a point is inside/outside a triangle mesh -% whereby the bounding triangle mesh should be closed. -% -% [inside] = bounding_mesh(pos, pnt, tri) -% -% where -% pos position of point of interest (can be 1x3 or Nx3) -% pnt bounding mesh vertices -% tri bounding mesh triangles -% -% See also SOLID_ANGLE - -% Copyright (C) 2003, Robert Oostenveld -% -% $Log: bounding_mesh.m,v $ -% Revision 1.11 2006/03/06 09:44:34 roboos -% changed a | into a || -% -% Revision 1.10 2003/07/24 09:18:17 roberto -% added abs to solid angle to make it invariant for triange orientation -% -% Revision 1.9 2003/03/21 13:40:29 roberto -% fixed small bug (unmatched end) -% -% Revision 1.8 2003/03/21 13:38:46 roberto -% solid angle computation is now available in very fast mex file -% removed projection along x/y/z axes -% -% Revision 1.7 2003/03/21 12:32:35 roberto -% added projection along y and x, similar to z -% -% Revision 1.6 2003/03/21 12:15:23 roberto -% added new approach to determine inside/outside (proj along z) -% -% Revision 1.5 2003/03/21 08:26:46 roberto -% changed to percent (100x) -% -% Revision 1.4 2003/03/21 08:26:08 roberto -% fixed typo -% -% Revision 1.3 2003/03/21 08:25:34 roberto -% small modification to feedback/debugging info -% -% Revision 1.2 2003/03/04 21:35:26 roberto -% added CVS Log keyword -% - -global fb; -if isempty(fb) - fb = 0; -end - -npos = size(pos, 1); -npnt = size(pnt, 1); -ntri = size(tri, 1); - -% determine a cube that encompases the boundary triangulation -bound_min = min(pnt); -bound_max = max(pnt); - -% determine a sphere that is completely inside the boundary triangulation -bound_org = mean(pnt); -bound_rad = sqrt(min(sum((pnt - repmat(bound_org, size(pnt,1), 1)).^2, 2))); - -inside = zeros(npos, 1); -for i=1:npos - if fb - fprintf('%6.2f%%', 100*i/npos); - end - if any(pos(i,:)bound_max) - % the point is outside the bounding cube - inside(i) = 0; - if fb, fprintf(' outside the bounding cube\n'); end - elseif sqrt(sum((pos(i,:)-bound_org).^2, 2))0 - % total solid angle is (approximately) plus or minus 4*pi - inside(i) = 1; - end - if fb, fprintf(' solid angle\n'); end - end -end - diff --git a/external/forwinv/private/compute_leadfield.m b/external/forwinv/private/compute_leadfield.m deleted file mode 100644 index 6684da2..0000000 --- a/external/forwinv/private/compute_leadfield.m +++ /dev/null @@ -1,534 +0,0 @@ -function [lf] = compute_leadfield(pos, sens, vol, varargin) - -% COMPUTE_LEADFIELD computes a forward solution for a dipole in a a volume -% conductor model. The forward solution is expressed as the leadfield -% matrix (Nchan*3), where each column corresponds with the potential or field -% distributions on all sensors for one of the x,y,z-orientations of the -% dipole. -% -% Use as -% [lf] = compute_leadfield(pos, sens, vol, ...) -% with input arguments -% pos position dipole (1x3 or Nx3) -% sens structure with gradiometer or electrode definition -% vol structure with volume conductor definition -% -% The vol structure represents a volume conductor model, its contents -% depend on the type of model. The sens structure represents a sensor -% arary, i.e. EEG electrodes or MEG gradiometers. -% -% It is possible to compute a simultaneous forward solution for EEG and MEG -% by specifying sens and grad as two cell-arrays, e.g. -% sens = {senseeg, sensmeg} -% vol = {voleeg, volmeg } -% This results in the computation of the leadfield of the first element of -% sens and vol, followed by the second, etc. The leadfields of the -% different imaging modalities are concatenated. -% -% Additional input arguments can be specified as key-value pairs, supported -% optional arguments are -% 'reducerank' = 'no' or number -% 'normalize' = 'no', 'yes' or 'column' -% 'normalizeparam' = parameter for depth normalization (default = 0.5) -% -% Depending on the specific input arguments for the sensor and volume, this -% function will select the appropriate low-level EEG or MEG forward model. -% The leadfield matrix for EEG will have an average reference over all the -% electrodes. -% -% The supported forward solutions for MEG are -% single sphere (Cuffin and Cohen, 1977) -% multiple spheres with one sphere per channel (Huang et al, 1999) -% realistic single shell using superposition of basis functions (Nolte, 2003) -% using leadfield interpolation on precomputed grid -% Boundary Element Method (BEM) using Neuromag meg_calc toolbox -% -% The supported forward solutions for EEG are -% single sphere -% multiple concentric spheres (max. 4) -% using leadfield interpolation on precomputed grid -% Boundary Element Method (BEM) using ASA to precompute the sytem matrix -% Boundary Element Method (BEM) using Neuromag meg_calc toolbox -% -% References to implemented methods: -% Cuffin BN, Cohen D. -% Magnetic fields of a dipole in special volume conductor shapes -% IEEE Trans Biomed Eng. 1977 Jul;24(4):372-81. -% -% Nolte G. -% The magnetic lead field theorem in the quasi-static approximation and its use for magnetoencephalography forward calculation in realistic volume conductors -% Phys Med Biol. 2003 Nov 21;48(22):3637-52 -% -% Huang MX, Mosher JC, Leahy RM. -% A sensor-weighted overlapping-sphere head model and exhaustive head model comparison for MEG -% Phys Med Biol. 1999 Feb;44(2):423-40 - -% Copyright (C) 2004-2008, Robert Oostenveld -% -% $Log: compute_leadfield.m,v $ -% Revision 1.30 2009/05/25 08:17:15 roboos -% small change in consistency test for multisphere MEG volume conductor -% -% Revision 1.29 2009/03/30 15:06:14 roboos -% added the patch from Alexandre to support openmeeg -% -% Revision 1.28 2009/02/02 13:05:44 roboos -% addec bemcp -% give warning once in case of eeg infinite medium -% -% Revision 1.27 2008/07/22 10:17:15 roboos -% replaced identical with strcmp -% -% Revision 1.26 2008/07/21 20:28:44 roboos -% added check on units (mm/cm/m) of the sensor array and volume conductor, give error if inconsistent -% -% Revision 1.25 2008/05/13 19:24:11 roboos -% consistently removed support for pnt1/pnt2 gradiometer description -% -% Revision 1.24 2008/04/30 13:47:20 roboos -% removed support for pnt1+pnt2 -% -% Revision 1.23 2008/04/15 20:36:21 roboos -% added explicit handling of various BEM implementations, i.e. for all voltype variants -% -% Revision 1.22 2008/04/11 13:16:16 roboos -% added support for simultaneous EEG and MEG -% -% Revision 1.21 2008/03/18 13:20:42 roboos -% updated documentation and some error messages -% -% Revision 1.20 2008/03/05 16:24:30 roboos -% use the voltype helper function -% added option for 'normalizeparam' -% -% Revision 1.19 2007/07/25 08:32:25 roboos -% switched to using senstype helper function -% -% Revision 1.18 2006/10/16 15:21:04 roboos -% small change in a comment -% -% Revision 1.17 2006/10/12 08:57:34 roboos -% added support for multiple dipoles for which the positions are in one long 1x(3*N) vector -% changed the functino call to neuromag megfield (not verified) -% renamed some internal variables -% only determine the number of dipoles (Ndipoles) once, and not in every section again -% -% Revision 1.16 2006/10/04 08:12:40 roboos -% changed some '&' into '&&', only apply reducerank when smaller than number of leadfield components (for efficiency) -% -% Revision 1.15 2006/09/07 12:43:22 roboos -% added code for multisphere, contributed by Punita Christopher (based on BrainStorm) -% -% Revision 1.14 2006/03/21 11:24:16 roboos -% multiply the nolte leadfield with sens.tra to transform from coils to gradiometers -% -% Revision 1.13 2006/03/21 09:40:08 roboos -% implemented support for Guido Nolte's method directly using his code -% improved documentation, added literature references -% -% Revision 1.12 2006/02/28 13:35:14 roboos -% added column-wise normalization for leadfield -% -% Revision 1.11 2006/02/14 09:42:31 roboos -% added a snippet of code to support forward computations using the Neuromag meg-calc toolbox -% -% Revision 1.10 2006/01/20 09:41:49 roboos -% changed assignment of sens.pnt (add structure field to existing double) according to matlab 7.1. recommendation (prevents warning) -% -% Revision 1.9 2005/11/16 09:56:17 roboos -% added a semicolon to prevent output on screen -% -% Revision 1.8 2005/11/08 11:05:14 roboos -% added support for normalize and reducerank as additional options (using key-value varargin) -% -% Revision 1.7 2005/07/29 07:19:47 roboos -% improved detection of meg data (ismeg if has ori and pos) -% -% Revision 1.6 2005/06/08 16:35:15 roboos -% corrected the check for the number of spheres in the grad and volume -% -% Revision 1.5 2005/02/21 08:01:19 roboos -% removed spaces at the end of line, no code changes -% -% Revision 1.4 2005/02/08 11:59:14 roboos -% added an extra check on the input -% -% Revision 1.3 2004/10/25 16:20:13 roboos -% fixed bug in selection of electrode positions from sens structure -% -% Revision 1.2 2004/09/21 15:31:51 roboos -% renamed grad into sens -% -% Revision 1.1 2004/08/19 08:18:20 roboos -% new implementations, generalized for EEG and MEG -% - -persistent warning_issued; - -if iscell(sens) && iscell(vol) && numel(sens)==numel(vol) - % this represents combined EEG and MEG sensors, where each modality has its own volume conduction model - lf = cell(1,numel(sens)); - for i=1:length(sens) - lf{i} = compute_leadfield(pos, sens{i}, vol{i}, varargin{:}); - end - lf = cat(1, lf{:}); - return; -end - -if ~isstruct(sens) && size(sens,2)==3 - % definition of electrode positions only, restructure it - sens = struct('pnt', sens); -end - -% determine whether it is EEG or MEG -iseeg = senstype(sens, 'eeg'); -ismeg = senstype(sens, 'meg'); - -% get the optional input arguments -reducerank = keyval('reducerank', varargin); if isempty(reducerank), reducerank = 'no'; end -normalize = keyval('normalize' , varargin); if isempty(normalize ), normalize = 'no'; end -normalizeparam = keyval('normalizeparam', varargin); if isempty(normalizeparam ), normalizeparam = 0.5; end - -% multiple dipoles can be represented either as a 1x(N*3) vector or as a -% as a Nx3 matrix, i.e. [x1 y1 z1 x2 y2 z2] or [x1 y1 z1; x2 y2 z2] -Ndipoles = numel(pos)/3; -if all(size(pos)==[1 3*Ndipoles]) - pos = reshape(pos, 3, Ndipoles)'; -end - -if isfield(vol, 'unit') && isfield(sens, 'unit') && ~strcmp(vol.unit, sens.unit) - error('inconsistency in the units of the volume conductor and the sensor array'); -end - -if ismeg && iseeg - % this is something that could be implemented relatively easily - error('simultaneous EEG and MEG not supported'); - -elseif ~ismeg && ~iseeg - error('the input does not look like EEG, nor like MEG'); - -elseif ismeg - switch voltype(vol) - - case 'singlesphere' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % MEG single-sphere volume conductor model - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - pnt = sens.pnt; % position of each coil - ori = sens.ori; % orientation of each coil - - if isfield(vol, 'o') - % shift dipole and magnetometers to origin of sphere - pos = pos - repmat(vol.o, Ndipoles, 1); - pnt = pnt - repmat(vol.o, size(pnt,1), 1); - end - - if Ndipoles>1 - % loop over multiple dipoles - lf = zeros(size(pnt,1),3*Ndipoles); - for i=1:Ndipoles - lf(:,(3*i-2):(3*i)) = meg_leadfield1(pos(i,:), pnt, ori); - end - else - % only single dipole - lf = meg_leadfield1(pos, pnt, ori); - end - - if isfield(sens, 'tra') - % this appears to be the modern complex gradiometer definition - % construct the channels from a linear combination of all magnetometers - lf = sens.tra * lf; - end - - case 'multisphere' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % MEG multi-sphere volume conductor model - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - ncoils = length(sens.pnt); - - if size(vol.r, 1)~=ncoils - error('number of spheres is not equal to the number of coils') - end - - if size(vol.o, 1)~=ncoils - error('number of spheres is not equal to the number of coils'); - end - - lf = zeros(ncoils, 3*Ndipoles); - for chan=1:ncoils - for dip=1:Ndipoles - % shift dipole and magnetometer coil to origin of sphere - dippos = pos(dip,:) - vol.o(chan,:); - chnpos = sens.pnt(chan,:) - vol.o(chan,:); - tmp = meg_leadfield1(dippos, chnpos, sens.ori(chan,:)); - lf(chan,(3*dip-2):(3*dip)) = tmp; - end - end - - if isfield(sens, 'tra') - % this appears to be the modern complex gradiometer definition - % construct the channels from a linear combination of all magnetometers - lf = sens.tra * lf; - end - - case 'neuromag' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % use external Neuromag toolbox for forward computation - % this requires that "megmodel" is initialized, which is done in PREPARE_VOL_SENS - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % compute the forward model for all channels - % tmp1 = ones(1, Ndipoles); - % tmp2 = 0.01*pos'; %convert to cm - % lf = megfield([tmp2 tmp2 tmp2],[[1 0 0]'*tmp1 [0 1 0]'*tmp1 [0 0 1]'*tmp1]); - for dip=1:Ndipoles - R = 0.01*pos(i,:)'; % convert from cm to m - Qx = [1 0 0]; - Qy = [0 1 0]; - Qz = [0 0 1]; - lf(:,(3*(dip-1)+1)) = megfield(R, Qx); - lf(:,(3*(dip-1)+2)) = megfield(R, Qy); - lf(:,(3*(dip-1)+3)) = megfield(R, Qz); - end - % select only those channels from the forward model that are part of the gradiometer definition - lf = lf(vol.chansel,:); - - case 'nolte' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % use code from Guido Nolte for the forward computation - % this requires that "meg_ini" is initialized, which is done in PREPARE_VOL_SENS - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % the dipole position and orientation should be combined in a single matrix - % furthermore, here I want to compute the leadfield for each of the - % orthogonzl x/y/z directions - dippar = zeros(Ndipoles*3, 6); - for i=1:Ndipoles - dippar((i-1)*3+1,:) = [pos(i,:) 1 0 0]; % single dipole, x-orientation - dippar((i-1)*3+2,:) = [pos(i,:) 0 1 0]; % single dipole, y-orientation - dippar((i-1)*3+3,:) = [pos(i,:) 0 0 1]; % single dipole, z-orientation - end - % compute the leadfield for each individual coil - lf = meg_forward(dippar,vol.forwpar); - if isfield(sens, 'tra') - % compute the leadfield for each gradiometer (linear combination of coils) - lf = sens.tra * lf; - end - - case 'infinite' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % magnetic dipole instead of electric (current) dipole in an infinite vacuum - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - if isempty(warning_issued) - % give the warning only once - warning('assuming magnetic dipole in an infinite vacuum'); - warning_issued = 1; - end - - pnt = sens.pnt; % position of each coil - ori = sens.ori; % orientation of each coil - - if Ndipoles>1 - % loop over multiple dipoles - lf = zeros(size(pnt,1),3*Ndipoles); - for i=1:Ndipoles - lf(:,(3*i-2):(3*i)) = magnetic_dipole(pos(i,:), pnt, ori); - end - else - % only single dipole - lf = magnetic_dipole(pos, pnt, ori); - end - - if isfield(sens, 'tra') - % construct the channels from a linear combination of all magnetometer coils - lf = sens.tra * lf; - end - - otherwise - error('unsupported volume conductor model for MEG'); - end % switch voltype for MEG - -elseif iseeg - switch voltype(vol) - - case 'multisphere' - % Based on the approximation of the potential due to a single dipole in - % a multishell sphere by three dipoles in a homogeneous sphere, code - % contributed by Punita Christopher - - Nelec = size(sens.pnt,1); - Nspheres = length(vol.r); - - % the center of the spherical volume conduction model does not have - % to be in the origin, therefore shift the spheres, the electrodes - % and the dipole - if isfield(vol, 'o') - center = vol.o; - else - center = [0 0 0]; - end - - % sort the spheres from the smallest to the largest - % furthermore, the radius should be one (?) - [radii, indx] = sort(vol.r/max(vol.r)); - sigma = vol.c(indx); - r = (sens.pnt-repmat(center, Nelec, 1))./max(vol.r); - pos = pos./max(vol.r); - - if Ndipoles>1 - % loop over multiple dipoles - lf = zeros(Nelec,3*Ndipoles); - for i=1:Ndipoles - rq = pos(i,:) - center; - % compute the potential for each dipole ortientation - % it would be much more efficient to change the punita function - q1 = [1 0 0]; lf(:,(3*i-2)) = multisphere(Nspheres, radii, sigma, r, rq, q1); - q1 = [0 1 0]; lf(:,(3*i-1)) = multisphere(Nspheres, radii, sigma, r, rq, q1); - q1 = [0 0 1]; lf(:,(3*i )) = multisphere(Nspheres, radii, sigma, r, rq, q1); - end - else - % only single dipole - lf = zeros(Nelec,3); - rq = pos - center; - % compute the potential for each dipole ortientation - % it would be much more efficient to change the punita function - q1 = [1 0 0] ; lf(:,1) = multisphere(Nspheres, radii, sigma, r, rq, q1); - q1 = [0 1 0] ; lf(:,2) = multisphere(Nspheres, radii, sigma, r, rq, q1); - q1 = [0 0 1] ; lf(:,3) = multisphere(Nspheres, radii, sigma, r, rq, q1); - end - - case {'singlesphere', 'concentric'} - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % EEG spherical volume conductor model - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - % FIXME, this is not consistent between spherical and BEM - % sort the spheres from the smallest to the largest - [vol.r, indx] = sort(vol.r); - vol.c = vol.c(indx); - - Nspheres = length(vol.c); - if length(vol.r)~=Nspheres - error('the number of spheres in the volume conductor model is ambiguous'); - end - - if isfield(vol, 'o') - % shift the origin of the spheres, electrodes and dipole - sens.pnt = sens.pnt - repmat(vol.o, size(sens.pnt,1), 1); - pos = pos - repmat(vol.o, Ndipoles, 1); - end - - if Nspheres==1 - if Ndipoles>1 - % loop over multiple dipoles - lf = zeros(size(sens.pnt,1),3*Ndipoles); - for i=1:Ndipoles - lf(:,(3*i-2):(3*i)) = eeg_leadfield1(pos(i,:), sens.pnt, vol); - end - else - % only single dipole - lf = eeg_leadfield1(pos, sens.pnt, vol); - end - - elseif Nspheres==2 - vol.r = [vol.r(1) vol.r(2) vol.r(2) vol.r(2)]; - vol.c = [vol.c(1) vol.c(2) vol.c(2) vol.c(2)]; - if Ndipoles>1 - % loop over multiple dipoles - lf = zeros(size(sens.pnt,1),3*Ndipoles); - for i=1:Ndipoles - lf(:,(3*i-2):(3*i)) = eeg_leadfield4(pos(i,:), sens.pnt, vol); - end - else - % only single dipole - lf = eeg_leadfield4(pos, sens.pnt, vol); - end - - elseif Nspheres==3 - vol.r = [vol.r(1) vol.r(2) vol.r(3) vol.r(3)]; - vol.c = [vol.c(1) vol.c(2) vol.c(3) vol.c(3)]; - if Ndipoles>1 - % loop over multiple dipoles - lf = zeros(size(sens.pnt,1),3*Ndipoles); - for i=1:Ndipoles - lf(:,(3*i-2):(3*i)) = eeg_leadfield4(pos(i,:), sens.pnt, vol); - end - else - % only single dipole - lf = eeg_leadfield4(pos, sens.pnt, vol); - end - - elseif Nspheres==4 - if Ndipoles>1 - % loop over multiple dipoles - lf = zeros(size(sens.pnt,1),3*Ndipoles); - for i=1:Ndipoles - lf(:,(3*i-2):(3*i)) = eeg_leadfield4(pos(i,:), sens.pnt, vol); - end - else - % only single dipole - lf = eeg_leadfield4(pos, sens.pnt, vol); - end - - else - error('more than 4 concentric spheres are not supported'); - end - - case {'bem', 'dipoli', 'asa', 'avo', 'bemcp', 'openmeeg'} - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % EEG boundary element method volume conductor model - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - lf = eeg_leadfieldb(pos, sens.pnt, vol); - - case 'infinite' - % the conductivity of the medium is not known - if isempty(warning_issued) - % give the warning only once - warning('assuming electric dipole in an infinite medium with unit conductivity'); - warning_issued = 1; - end - lf = inf_medium_leadfield(pos, sens.pnt, 1); - - otherwise - error('unsupported volume conductor model for EEG'); - end % switch voltype for EEG - - % compute average reference for EEG leadfield - avg = mean(lf, 1); - lf = lf - repmat(avg, size(lf,1), 1); - -end % iseeg or ismeg - -% optionally apply leadfield rank reduction -if ~strcmp(reducerank, 'no') && reducerank0 - lf = lf ./ nrm; - end -elseif strcmp(normalize, 'column') - % normalize each column of the leadfield by its norm - for j=1:size(lf,2) - nrm = sum(lf(:,j).^2)^normalizeparam; - lf(:,j) = lf(:,j)./nrm; - end -end diff --git a/external/forwinv/private/convert_units.m b/external/forwinv/private/convert_units.m deleted file mode 100644 index eb1366b..0000000 --- a/external/forwinv/private/convert_units.m +++ /dev/null @@ -1,217 +0,0 @@ -function [obj] = convert_units(obj, target); - -% CONVERT_UNITS changes the geometrical dimension to the specified SI unit. -% The units of the input object is determined from the structure field -% object.unit, or is estimated based on the spatial extend of the structure, -% e.g. a volume conduction model of the head should be approximately 20 cm large. -% -% Use as -% [object] = convert_units(object, target) -% -% The following input objects are supported -% simple dipole position -% electrode definition -% gradiometer array definition -% volume conductor definition -% dipole grid definition -% anatomical mri -% -% Possible target units are 'm', 'dm', 'cm ' or 'mm'. -% -% See READ_VOL, READ_SENS - -% Copyright (C) 2005-2008, Robert Oostenveld -% -% $Log: convert_units.m,v $ -% Revision 1.8 2009/03/26 14:57:04 roboos -% moved the unit estimation to a seperate function -% -% Revision 1.7 2009/03/11 11:28:24 roboos -% detect as mm for very wide anatomical MRIs (happens at the fcdc with the ctf MRIs) -% -% Revision 1.6 2009/02/05 10:20:35 roboos -% added bemcp as volume type -% -% Revision 1.5 2009/01/08 17:18:45 roboos -% fixed bug mom->pos for source structures -% added unit detection for volumes with a transform and a dim -% -% Revision 1.4 2008/07/21 20:29:22 roboos -% small change in output on screen -% -% Revision 1.3 2008/04/14 20:53:58 roboos -% added detection for headshape and/or fiducials -% fixed bug in scaling of fiducials -% -% Revision 1.2 2008/04/14 19:29:58 roboos -% cleanded up code and added autodetection based on geometrical size of object -% changed interface, no forced input type is possible -% changed from dos to unix -% -% Revision 1.1 2005/03/03 11:01:39 roboos -% already old (and unused) implementation, but sofar this function was not included in CVS -% - -% This function consists of three parts: -% 1) determine the input units -% 2) determine the requested scaling factor to obtain the output units -% 3) try to apply the scaling to the known geometrical elements in the input object - -% determine the unit-of-dimension of the input object -if isfield(obj, 'unit') - % use the units specified in the object - unit = obj.unit; -else - % try to estimate the units from the object - type = voltype(obj); - if ~strcmp(type, 'unknown') - switch type - case 'infinite' - % there is nothing to do to convert the units - unit = target; - - case 'singlesphere' - size = obj.r; - - case 'multisphere' - size = median(obj.r); - - case 'concentric' - size = max(obj.r); - - case 'nolte' - size = norm(range(obj.bnd.pnt)); - - case {'bem' 'dipoli' 'bemcp' 'asa' 'avo'} - size = norm(range(obj.bnd(1).pnt)); - - otherwise - error('cannot determine geometrical units of volume conduction model'); - end % switch - - % determine the units by looking at the size - unit = estimate_units(size); - - elseif senstype(obj, 'meg') - size = norm(range(obj.pnt)); - unit = estimate_units(size); - - elseif senstype(obj, 'eeg') - size = norm(range(obj.pnt)); - unit = estimate_units(size); - - elseif isfield(obj, 'pnt') && ~isempty(obj.pnt) - size = norm(range(obj.pnt)); - unit = estimate_units(size); - - elseif isfield(obj, 'pos') && ~isempty(obj.pos) - size = norm(range(obj.pos)); - unit = estimate_units(size); - - elseif isfield(obj, 'transform') && ~isempty(obj.transform) - % construct the corner points of the voxel grid in head coordinates - xi = 1:obj.dim(1); - yi = 1:obj.dim(2); - zi = 1:obj.dim(3); - pos = [ - xi( 1) yi( 1) zi( 1) - xi( 1) yi( 1) zi(end) - xi( 1) yi(end) zi( 1) - xi( 1) yi(end) zi(end) - xi(end) yi( 1) zi( 1) - xi(end) yi( 1) zi(end) - xi(end) yi(end) zi( 1) - xi(end) yi(end) zi(end) - ]; - pos = warp_apply(obj.transform, pos); - size = norm(range(pos)); - unit = estimate_units(size); - - elseif isfield(obj, 'fid') && isfield(obj.fid, 'pnt') && ~isempty(obj.fid.pnt) - size = norm(range(obj.fid.pnt)); - unit = estimate_units(size); - - else - error('cannot determine geometrical units'); - - end % recognized type of volume conduction model or sensor array -end % determine input units - -if nargin<2 - % just remember the units in the output and return - obj.unit = unit; - return -elseif strcmp(unit, target) - % no conversion is needed - obj.unit = unit; - return -end - -% give some information about the conversion -fprintf('converting units from ''%s'' to ''%s''\n', unit, target) - -if strcmp(unit, 'm') - unit2meter = 1; -elseif strcmp(unit, 'dm') - unit2meter = 0.1; -elseif strcmp(unit, 'cm') - unit2meter = 0.01; -elseif strcmp(unit, 'mm') - unit2meter = 0.001; -end - -% determine the unit-of-dimension of the output object -if strcmp(target, 'm') - meter2target = 1; -elseif strcmp(target, 'dm') - meter2target = 10; -elseif strcmp(target, 'cm') - meter2target = 100; -elseif strcmp(target, 'mm') - meter2target = 1000; -end - -% combine the units into one scaling factor -scale = unit2meter * meter2target; - -% volume conductor model -if isfield(obj, 'r'), obj.r = scale * obj.r; end -if isfield(obj, 'o'), obj.o = scale * obj.o; end -if isfield(obj, 'bnd'), for i=1:length(obj.bnd), obj.bnd(i).pnt = scale * obj.bnd(i).pnt; end, end - -% gradiometer array -if isfield(obj, 'pnt1'), obj.pnt1 = scale * obj.pnt1; end -if isfield(obj, 'pnt2'), obj.pnt2 = scale * obj.pnt2; end -if isfield(obj, 'prj'), obj.prj = scale * obj.prj; end - -% gradiometer array, electrode array, head shape or dipole grid -if isfield(obj, 'pnt'), obj.pnt = scale * obj.pnt; end - -% fiducials -if isfield(obj, 'fid') && isfield(obj.fid, 'pnt'), obj.fid.pnt = scale * obj.fid.pnt; end - -% dipole grid -if isfield(obj, 'pos'), obj.pos = scale * obj.pos; end - -% anatomical MRI or functional volume -if isfield(obj, 'transform'), - H = diag([scale scale scale 1]); - obj.transform = H * obj.transform; -end - -% remember the unit -obj.unit = target; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION -% Use as -% r = range(x) -% or you can also specify the dimension along which to look by -% r = range(x, dim) -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function r = range(x, dim) -if nargin==1 - r = max(x) - min(x); -else - r = max(x, [], dim) - min(x, [], dim); -end diff --git a/external/forwinv/private/dipole_fit.m b/external/forwinv/private/dipole_fit.m deleted file mode 100644 index 04137f1..0000000 --- a/external/forwinv/private/dipole_fit.m +++ /dev/null @@ -1,341 +0,0 @@ -function [dipout] = dipole_fit(dip, sens, vol, dat, varargin) - -% DIPOLE_FIT performs an equivalent current dipole fit with a single -% or a small number of dipoles to explain an EEG or MEG scalp topography. -% -% Use as -% [dipout] = dipole_fit(dip, sens, vol, dat, ...) -% -% Additional input arguments should be specified as key-value pairs and can include -% 'constr' = Structure with constraints -% 'display' = Level of display [ off | iter | notify | final ] -% 'optimfun' = Function to use [fminsearch | fminunc ] -% 'maxiter' = Maximum number of function evaluations allowed [ positive integer ] -% 'metric' = Error measure to be minimised [ rv | var | abs ] -% 'checkinside' = Boolean flag to check whether dipole is inside source compartment [ 0 | 1 ] -% 'weight' = weight matrix for maximum likelihood estimation, e.g. inverse noise covariance -% -% The following optional input arguments relate to the computation of the leadfields -% 'reducerank' = 'no' or number -% 'normalize' = 'no', 'yes' or 'column' -% 'normalizeparam' = parameter for depth normalization (default = 0.5) -% -% The maximum likelihood estimation implements -% Lutkenhoner B. "Dipole source localization by means of maximum -% likelihood estimation I. Theory and simulations" Electroencephalogr Clin -% Neurophysiol. 1998 Apr;106(4):314-21. - -% Copyright (C) 2003-2008, Robert Oostenveld -% -% $Log: dipole_fit.m,v $ -% Revision 1.15 2009/07/02 15:38:06 roboos -% use fixdipole for consistent dipole structure representation -% -% Revision 1.14 2009/03/13 07:24:52 roboos -% changed handling of optimization function (fminunc/fminsearch), now uses hastoolbox which is also able to check the availablity of a license for the optimimization toolbox -% -% Revision 1.13 2009/02/17 10:57:57 roboos -% use senstype to determine eeg/meg -% fixed bug in input pos/mom checking (thanks to Vladimir) -% -% Revision 1.12 2009/01/19 12:07:42 roboos -% fixed bug for symmetry constrained dipole fitting in case of multiple dipoles (thanks to John Iversen) -% added some checks on the input dipole position and moment -% -% Revision 1.11 2008/04/30 13:48:57 roboos -% finished implementation of MLE fitting, renamed cov into weight (inverse should be done outside this function) -% -% Revision 1.10 2008/04/29 15:41:53 roboos -% added skelleton for MAP estimation, but the covariance is not passed yet to lower level function -% -% Revision 1.9 2008/01/09 12:43:25 roboos -% added optional input arguments for reducerank, normalize and normalizeparam, these are directly passed on to compute_leadfield -% -% Revision 1.8 2007/12/18 13:01:55 roboos -% added support for fitting fixed orientation dipoles (constr.fixedori=1) -% -% Revision 1.7 2007/07/23 10:16:00 roboos -% implemented options for changing the error metric and for checking taht the dipole is inside the brain -% -% Revision 1.6 2007/03/21 11:13:29 roboos -% added MaxFunEvals to the optimization options -% -% Revision 1.5 2007/01/02 10:51:23 roboos -% renamed the output argument to dipout, no functional changes -% -% Revision 1.4 2006/09/07 12:39:51 roboos -% included optional input arguments to documentation -% -% Revision 1.3 2006/05/11 07:16:44 roboos -% Added additional input argument 'optimfun', can be fminunc or -% fminsearch. Changed the default maxiter to 500 for fminsearch. -% Changed the assignment of sens.pnt as structure (prevents warning -% in matlab7). -% -% Revision 1.2 2006/05/10 10:48:21 roboos -% Changed the order of the input arguments for consistency with -% other inverse functions, and switched to specifying optional inputs -% using key-value pairs. The old-style input is supported for backward -% compatibility with EEGLAB and dipfit1. Added optional input arguments -% for maxiter (default=100, just as before) and display (default='iter', -% just as before). -% -% Revision 1.1 2005/11/01 09:34:27 roboos -% replaced EEG/MEG specific dipole fit routines with a single general function -% -% Revision 1.7 2004/02/05 11:55:30 roberto -% fixed clearly apparent bug in error function (would not run) -% -% Revision 1.6 2003/09/12 08:45:41 roberto -% added error if maximum number of iterations is exceeded -% -% Revision 1.5 2003/09/02 13:01:18 roberto -% implemented constrained dipole fitting -% -% Revision 1.4 2003/06/16 10:03:31 roberto -% added check in error function for gui interrupt request (for eeglab) -% -% Revision 1.3 2003/03/13 13:41:00 roberto -% fixed bug in e/meg_error_func in assignment of Nchan -% -% Revision 1.2 2003/03/11 14:45:36 roberto -% updated help and copyrights -% - -% It is neccessary to provide backward compatibility support for the old function call -% in case people want to use it in conjunction with EEGLAB and the dipfit1 plugin. -% old style: function [dipout] = dipole_fit(dip, dat, sens, vol, constr), where constr is optional -% new style: function [dipout] = dipole_fit(dip, sens, vol, dat, varargin), where varargin is in key-value pairs -if nargin==4 && ~isstruct(sens) && isstruct(dat) - % looks like old style, the order of the input arguments has to be changed - warning('converting from old style input\n'); - olddat = sens; - oldsens = vol; - oldvol = dat; - dat = olddat; - sens = oldsens; - vol = oldvol; -elseif nargin==5 && ~isstruct(sens) && isstruct(dat) - % looks like old style, the order of the input arguments has to be changed - % furthermore the additional constraint has to be fixed - warning('converting from old style input\n'); - olddat = sens; - oldsens = vol; - oldvol = dat; - dat = olddat; - sens = oldsens; - vol = oldvol; - varargin = {'constr', varargin{1}}; % convert into a key-value pair -else - % looks like new style, i.e. with optional key-value arguments - % this is dealt with below -end - -constr = keyval('constr', varargin); % default is not to have constraints -metric = keyval('metric', varargin); if isempty(metric), metric = 'rv'; end -checkinside = keyval('checkinside', varargin); if isempty(checkinside), checkinside = 0; end -display = keyval('display', varargin); if isempty(display), display = 'iter'; end -optimfun = keyval('optimfun', varargin); if isa(optimfun, 'char'), optimfun = str2fun(optimfun); end -maxiter = keyval('maxiter', varargin); -reducerank = keyval('reducerank', varargin); % for leadfield computation -normalize = keyval('normalize' , varargin); % for leadfield computation -normalizeparam = keyval('normalizeparam', varargin); % for leadfield computation -weight = keyval('weight', varargin); % for maximum likelihood estimation - -if isempty(optimfun) - % determine whether the Matlab Optimization toolbox is available and can be used - if hastoolbox('optim') - optimfun = @fminunc; - else - optimfun = @fminsearch; - end -end - -if isempty(maxiter) - % set a default for the maximum number of iterations, depends on the optimization function - if isequal(optimfun, @fminunc) - maxiter = 100; - else - maxiter = 500; - end -end - -% determine whether it is EEG or MEG -iseeg = senstype(sens, 'eeg'); -ismeg = senstype(sens, 'meg'); - -if ismeg && iseeg - % this is something that I might implement in the future - error('simultaneous EEG and MEG not supported'); -elseif iseeg - % ensure that the potential data is average referenced, just like the model potential - dat = avgref(dat); -end - -% ensure correct dipole position and moment specification -dip = fixdipole(dip); - -% reformat the position parameters in case of multiple dipoles, this -% should result in the matrix changing from [x1 y1 z1; x2 y2 z2] to -% [x1 y1 z1 x2 y2 z2] for the constraints to work -numdip = size(dip.pos, 1); -param = dip.pos'; -param = param(:)'; - -% add the orientation to the nonlinear parameters -if isfield(constr, 'fixedori') && constr.fixedori - for i=1:numdip - % add the orientation to the list of parameters - [th, phi, r] = cart2sph(dip.mom(1,i), dip.mom(2,i), dip.mom(3,i)); - param = [param th phi]; - end -end - -% reduce the number of parameters to be fitted according to the constraints -if isfield(constr, 'mirror') - param = param(constr.reduce); -end - -% set the parameters for the optimization function -if isequal(optimfun, @fminunc) - options = optimset(... - 'TolFun',1e-9,... - 'TypicalX',ones(size(param)),... - 'LargeScale','off',... - 'HessUpdate','bfgs',... - 'MaxIter',maxiter,... - 'MaxFunEvals',2*maxiter*length(param),... - 'Display',display); -elseif isequal(optimfun, @fminsearch) - options = optimset(... - 'MaxIter',maxiter,... - 'MaxFunEvals',2*maxiter*length(param),... - 'Display',display); -else - warning('unknown optimization function "%s", using default parameters', func2str(optimfun)); -end - -% perform the optimization with either the fminsearch or fminunc function -[param, fval, exitflag, output] = optimfun(@dipfit_error, param, options, dat, sens, vol, constr, metric, checkinside, reducerank, normalize, normalizeparam, weight); - -if exitflag==0 - error('Maximum number of iterations exceeded before reaching the minimum, please try with another initial guess.') -end - -% do linear optimization of dipole moment parameters -[err, mom] = dipfit_error(param, dat, sens, vol, constr, metric, checkinside, reducerank, normalize, normalizeparam, weight); - -% expand the number of parameters according to the constraints -if isfield(constr, 'mirror') - param = constr.mirror .* param(constr.expand); -end - -% get the dipole position and orientation -if isfield(constr, 'fixedori') && constr.fixedori - numdip = numel(param)/5; - ori = zeros(3,numdip); - for i=1:numdip - th = param(end-(2*i)+1); - phi = param(end-(2*i)+2); - [ori(1,i), ori(2,i), ori(3,i)] = sph2cart(th, phi, 1); - end - pos = reshape(param(1:(numdip*3)), 3, numdip)'; -else - numdip = numel(param)/3; - pos = reshape(param, 3, numdip)'; -end - -% return the optimal dipole parameters -dipout.pos = pos; -if isfield(constr, 'fixedori') && constr.fixedori - dipout.mom = ori; % dipole orientation as vector - dipout.ampl = mom; % dipole strength -else - dipout.mom = mom; % dipole moment as vector or matrix, which represents both the orientation and strength as vector -end - -% ensure correct dipole position and moment specification -dipout = fixdipole(dipout); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% DIPFIT_ERROR computes the error between measured and model data -% and can be used for non-linear fitting of dipole position -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [err, mom] = dipfit_error(param, dat, sens, vol, constr, metric, checkinside, reducerank, normalize, normalizeparam, weight) - -% flush pending graphics events, ensure that fitting is interruptible -drawnow; -if ~isempty(get(0, 'currentfigure')) && strcmp(get(gcf, 'tag'), 'stop') - % interrupt the fitting - close; - error('USER ABORT'); -end; - -% expand the number of parameters according to the constraints -if isfield(constr, 'mirror') - param = constr.mirror .* param(constr.expand); -end - -% get the dipole positions and optionally also the orientation -if isfield(constr, 'fixedori') && constr.fixedori - numdip = numel(param)/5; - ori = zeros(3,numdip); - for i=1:numdip - th = param(end-(2*i)+1); - phi = param(end-(2*i)+2); - [ori(1,i), ori(2,i), ori(3,i)] = sph2cart(th, phi, 1); - end - pos = reshape(param(1:(numdip*3)), 3, numdip)'; -else - numdip = numel(param)/3; - pos = reshape(param, 3, numdip)'; -end - -% check whether the dipole is inside the source compartment -if checkinside - [inside, outside] = find_inside_vol(pos, vol); - if ~isempty(outside) - error('Dipole is outside the source compartment'); - end -end - -% construct the leadfield matrix for all dipoles -lf = compute_leadfield(pos, sens, vol, 'reducerank', reducerank, 'normalize', normalize, 'normalizeparam', normalizeparam); -if isfield(constr, 'fixedori') && constr.fixedori - lf = lf * ori; -end - -% compute the optimal dipole moment and the model error -if ~isempty(weight) - % maximum likelihood estimation using the weigth matrix - mom = pinv(lf'*weight*lf)*lf'*weight*dat; % Lutkenhoner equation 5 - dif = dat - lf*mom; - % compute the generalized goodness-of-fit measure - switch metric - case 'rv' % relative residual variance - num = dif' * weight * dif; - denom = dat' * weight * dat; - err = sum(num(:)) ./ sum(denom(:)); % Lutkenhonner equation 7, except for the gof=1-rv - case 'var' % residual variance - num = dif' * weight * dif'; - err = sum(num(:)); - otherwise - error('Unsupported error metric for maximum likelihood dipole fitting'); - end -else - % ordinary least squares, this is the same as MLE with weight=eye(nchans,nchans) - mom = pinv(lf)*dat; - dif = dat - lf*mom; - % compute the ordinary goodness-of-fit measures - switch metric - case 'rv' % relative residual variance - err = sum(dif(:).^2) / sum(dat(:).^2); - case 'var' % residual variance - err = sum(dif(:).^2); - case 'abs' % absolute difference - err = sum(abs(dif)); - otherwise - error('Unsupported error metric for dipole fitting'); - end -end - diff --git a/external/forwinv/private/eeg_leadfield.m b/external/forwinv/private/eeg_leadfield.m deleted file mode 100644 index 99b0ecf..0000000 --- a/external/forwinv/private/eeg_leadfield.m +++ /dev/null @@ -1,146 +0,0 @@ -function [lf] = eeg_leadfield(pos, elc, vol) - -% EEG_LEADFIELD electric leadfield for a dipole in spherical or realistic -% volume conductor. This provides a wrapper around the functions EEG_LEADFIELD1 -% and EEG_LEADFIELD4 for spherical models and EEG_LEADFIELDB for models based on -% the boundary element method. -% -% [lf] = eeg_leadfield(pos, elc, vol) -% -% with the input arguments -% pos position dipole (1x3 or Nx3) -% elc position electrodes -% vol structure defining the volume conductor model -% -% a spherical volume conductor model should have the fields -% vol.r radius of spheres -% vol.c conductivity of spheres -% vol.o origin of sphere (can be omitted) -% vol.t constant factors for 4-sphere series expansion (can be omitted) -% -% a realistical volume conductor model should have the fields -% vol.bnd structure array with vertices and triangles of each boundary -% vol.cond conductivity of all compartments -% vol.mat system matrix, which can include the electrode interpolation -% vol.tra transfer matrix for interpolation from vertices to electrodes -% the BEM compartment boundaries are described by a structure array with -% vol.bnd(i).pnt -% vol.bnd(i).pnt -% -% See also MEG_LEADFIELD, READ_ASA_VOL - -% Copyright (C) 2002, Robert Oostenveld -% -% $Log: eeg_leadfield.m,v $ -% Revision 1.5 2003/10/07 08:40:43 roberto -% moved BEM specific code into a separate function -% -% Revision 1.4 2003/07/29 11:54:02 roberto -% removed ellipsiod support (untested/unused sofar) -% renamed volume into vol -% updated help and comments -% -% Revision 1.3 2003/06/03 08:29:39 roberto -% *** empty log message *** -% -% Revision 1.2 2003/03/11 14:45:36 roberto -% updated help and copyrights -% - -% approximate timing per EEG channel on a PIII/800Hz -% m-code p-code mex-file -% 1 sphere 0.30 0.30 0.15 -% 4 sphere 0.56 0.56 1.84 (!!) with Nmax=10 -% 4 sphere 1.46 1.46 5.36 (!!) with Nmax=30 - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% spherical volume conductor model -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if isfield(vol, 'r') - - % FIXME, this is not consistent between spherical and BEM - % sort the spheres from the smallest to the largest - [vol.r, indx] = sort(vol.r); - vol.c = vol.c(indx); - - Nspheres = length(vol.c); - if length(vol.r)~=Nspheres - error('the number of spheres in the volume conductor model is ambiguous'); - end - - if isfield(vol, 'o') - % shift the origin of the spheres, electrodes and dipole - elc = elc - repmat(vol.o, size(elc,1), 1); - pos = pos - repmat(vol.o, size(pos,1), 1); - end - - if Nspheres==1 - if size(pos,1)>1 - % loop over multiple dipoles - lf = zeros(size(elc,1),3*size(pos,1)); - for i=1:size(pos,1) - lf(:,(3*i-2):(3*i)) = eeg_leadfield1(pos(i,:), elc, vol); - end - else - % only single dipole - lf = eeg_leadfield1(pos, elc, vol); - end - - elseif Nspheres==2 - vol.r = [vol.r(1) vol.r(2) vol.r(2) vol.r(2)]; - vol.c = [vol.c(1) vol.c(2) vol.c(2) vol.c(2)]; - if size(pos,1)>1 - % loop over multiple dipoles - lf = zeros(size(elc,1),3*size(pos,1)); - for i=1:size(pos,1) - lf(:,(3*i-2):(3*i)) = eeg_leadfield4(pos(i,:), elc, vol); - end - else - % only single dipole - lf = eeg_leadfield4(pos, elc, vol); - end - - elseif Nspheres==3 - vol.r = [vol.r(1) vol.r(2) vol.r(3) vol.r(3)]; - vol.c = [vol.c(1) vol.c(2) vol.c(3) vol.c(3)]; - if size(pos,1)>1 - % loop over multiple dipoles - lf = zeros(size(elc,1),3*size(pos,1)); - for i=1:size(pos,1) - lf(:,(3*i-2):(3*i)) = eeg_leadfield4(pos(i,:), elc, vol); - end - else - % only single dipole - lf = eeg_leadfield4(pos, elc, vol); - end - - elseif Nspheres==4 - if size(pos,1)>1 - % loop over multiple dipoles - lf = zeros(size(elc,1),3*size(pos,1)); - for i=1:size(pos,1) - lf(:,(3*i-2):(3*i)) = eeg_leadfield4(pos(i,:), elc, vol); - end - else - % only single dipole - lf = eeg_leadfield4(pos, elc, vol); - end - - else - error('more than 4 concentric spheres are not supported'); - end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% realistic BEM volume conductor model -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif isfield(vol, 'bnd') - - lf = eeg_leadfieldb(pos, elc, vol); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% unrecognized volume conductor model -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -else - error('unrecognized volume conductor model'); -end - diff --git a/external/forwinv/private/eeg_leadfield1.m b/external/forwinv/private/eeg_leadfield1.m deleted file mode 100644 index b0628db..0000000 --- a/external/forwinv/private/eeg_leadfield1.m +++ /dev/null @@ -1,124 +0,0 @@ -function [lf, lforig] = eeg_leadfield1(R, elc, vol); - -% EEG_LEADFIELD1 electric leadfield for a dipole in a single sphere -% -% [lf] = eeg_leadfield1(R, elc, vol) -% -% with input arguments -% R position dipole (vector of length 3) -% elc position electrodes -% and vol being a structure with the elements -% vol.r radius of sphere -% vol.c conductivity of sphere - -% Copyright (C) 2002, Robert Oostenveld -% -% this implementation is adapted from -% Luetkenhoener, Habilschrift '92 -% the original reference is -% R. Kavanagh, T. M. Darccey, D. Lehmann, and D. H. Fender. Evaluation of methods for three-dimensional localization of electric sources in the human brain. IEEE Trans Biomed Eng, 25:421-429, 1978. -% -% $Log: eeg_leadfield1.m,v $ -% Revision 1.1 2009/01/21 10:32:38 roboos -% moved from forwinv/* and forwinv/mex/* directory to forwinv/private/* to make the CVS layout consistent with the release version -% -% Revision 1.11 2008/12/24 13:33:45 roboos -% fixed typo in documentation -% -% Revision 1.10 2006/02/09 08:30:28 roboos -% scale with conductivity in case of dipole in the origin (thanks to Denise van Barneveld) -% -% Revision 1.9 2006/01/20 09:40:09 roboos -% disabled the dipole-inside-brain check (for EEGLAB) -% use precomputed c5 to capture divide by zero situation -% -% Revision 1.8 2004/10/25 16:25:25 roboos -% re-enabled check for dipole outside head -% -% Revision 1.7 2003/12/05 09:48:45 roberto -% disabled error check for dipole outside brain [for EEGLAB] -% -% Revision 1.6 2003/12/04 10:43:51 roberto -% added error when dipole is outside brain compartment -% -% Revision 1.5 2003/07/29 16:04:55 roberto -% fixed bug in determining whether electrodes are lying on sphere surface -% -% Revision 1.4 2003/07/29 15:53:09 roberto -% minor change to the projection of the electrodes to the sphere (now default) -% -% Revision 1.3 2003/07/29 15:42:03 roberto -% found and fixed a bug in the handling of electrodes and dipoles on one line -% changed the name of the constants and added a constant -% -% Revision 1.2 2003/03/11 14:45:36 roberto -% updated help and copyrights -% - -Nchans = size(elc, 1); -lf = zeros(Nchans,3); - -% always take the outermost sphere, this makes comparison with the 4-sphere computation easier -[vol.r, indx] = max(vol.r); -vol.c = vol.c(indx); - -% check whether the electrode ly on the sphere, allowing 0.5% tolerance -dist = sqrt(sum(elc.^2,2)); -if any(abs(dist-vol.r)>vol.r*0.005) - warning('electrodes do not ly on sphere surface -> using projection') -end -elc = vol.r * elc ./ [dist dist dist]; - -% check whether the dipole is inside the brain [disabled for EEGLAB] -% if sqrt(sum(R.^2))>=vol.r -% error('dipole is outside the brain compartment'); -% end - -c0 = norm(R); -c1 = vol.r; -c2 = 4*pi*c0^2*vol.c; - -if c0==0 - % the dipole is in the origin, this can and should be handeled as an exception - [phi, el] = cart2sph(elc(:,1), elc(:,2), elc(:,3)); - theta = pi/2 - el; - lf(:,1) = sin(theta).*cos(phi); - lf(:,2) = sin(theta).*sin(phi); - lf(:,3) = cos(theta); - % the potential in a homogenous sphere is three times the infinite medium potential - lf = 3/(c1^2*4*pi*vol.c)*lf; - -else - for i=1:Nchans - % use another name for the electrode, in accordance with lutkenhoner1992 - r = elc(i,:); - - c3 = r-R; - c4 = norm(c3); - c5 = c1^2 * c0^2 - dot(r,R)^2; % lutkenhoner A.11 - c6 = c0^2*r - dot(r,R)*R; % lutkenhoner, just after A.17 - - % the original code reads (cf. lutkenhoner1992 equation A.17) - % lf(i,:) = ((dot(R, r/norm(r) - (r-R)/norm(r-R))/(norm(cross(r,R))^2) + 2/(norm(r-R)^3)) * cross(R, cross(r, R)) + ((norm(r)^2-norm(R)^2)/(norm(r-R)^3) - 1/norm(r)) * R) / (4*pi*vol.c(1)*norm(R)^2); - - % but more efficient execution of the code is achieved by some precomputations - if c5<1000*eps - % the dipole lies on a single line with the electrode - lf(i,:) = (2/c4^3 * c6 + ((c1^2-c0^2)/c4^3 - 1/c1) * R) / c2; - else - % nothing wrong, do the complete computation - lf(i,:) = ((dot(R, r/c1 - c3/c4)/c5 + 2/c4^3) * c6 + ((c1^2-c0^2)/c4^3 - 1/c1) * R) / c2; - end - end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% fast cross product -function [c] = cross(a,b) -c = [a(2)*b(3)-a(3)*b(2) a(3)*b(1)-a(1)*b(3) a(1)*b(2)-a(2)*b(1)]; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% fast dot product -function [c] = dot(a,b) -c = sum(a.*b); - diff --git a/external/forwinv/private/eeg_leadfield4.m b/external/forwinv/private/eeg_leadfield4.m deleted file mode 100644 index 754fc09..0000000 --- a/external/forwinv/private/eeg_leadfield4.m +++ /dev/null @@ -1,150 +0,0 @@ -function [lf, vol] = eeg_leadfield4(R, elc, vol) - -% EEG_LEADFIELD4 electric leadfield for a dipole in 4 concentric spheres -% -% [lf] = eeg_leadfield4(R, elc, vol) -% -% with input arguments -% R position of the dipole -% elc position of the electrodes -% and vol being a structure with the elements -% vol.r radius of the 4 spheres -% vol.c conductivity of the 4 spheres -% vol.t constant factors for series expansion (optional) -% -% See also EEG_LEADFIELD4_PREPARE for precomputing the constant factors, -% which can save time when multiple leadfield computations are done. - -% Copyright (C) 2002, Robert Oostenveld -% -% this implementation is adapted from -% Lutkenhoner, Habilschrift 1992. -% the original reference is -% Cuffin BN, Cohen D. Comparison of the magnetoencephalogram and electroencephalogram. Electroencephalogr Clin Neurophysiol. 1979 Aug;47(2):132-46. -% -% $Log: eeg_leadfield4.m,v $ -% Revision 1.1 2009/01/21 10:32:38 roboos -% moved from forwinv/* and forwinv/mex/* directory to forwinv/private/* to make the CVS layout consistent with the release version -% -% Revision 1.8 2008/12/24 13:33:27 roboos -% changed some & and | into && and || -% -% Revision 1.7 2006/05/01 08:13:51 roboos -% fixed literature reference -% -% Revision 1.6 2003/12/05 09:48:45 roberto -% disabled error check for dipole outside brain [for EEGLAB] -% -% Revision 1.5 2003/12/04 10:43:51 roberto -% added error when dipole is outside brain compartment -% -% Revision 1.4 2003/07/29 16:04:55 roberto -% fixed bug in determining whether electrodes are lying on sphere surface -% -% Revision 1.3 2003/07/29 15:52:44 roberto -% fixed a bug in the implementation of eeg_leadfield4, caused by mixing the constants of -% lutkenhoner and cuffin -% furthermore multiple cosmetic changes and default projection of electrodes to sphere -% -% Revision 1.2 2003/03/11 14:45:36 roberto -% updated help and copyrights -% - -% sort the spheres from the smallest to the largest -[vol.r, indx] = sort(vol.r); -[vol.c] = vol.c(indx); - -% use more convenient names for the radii and conductivity -r1 = vol.r(1); c1 = vol.c(1); -r2 = vol.r(2); c2 = vol.c(2); -r3 = vol.r(3); c3 = vol.c(3); -r4 = vol.r(4); c4 = vol.c(4); - -% check whether the electrode ly on the sphere, allowing 0.5% tolerance -dist = sqrt(sum(elc.^2,2)); -if any(abs(dist-r4)>r4*0.005) - warning('electrodes do not ly on sphere surface -> using projection') -end -elc = r4 * elc ./ [dist dist dist]; - -% check whether the dipole is inside the brain [disabled for EEGLAB] -% if sqrt(sum(R.^2))>=r1 -% error('dipole is outside the brain compartment'); -% end - -% rotate everything so that the dipole is along the pos. z-axis -% only if the dipole is not in the origin or along the positive z-axis -if R(1)~=0 | R(2)~=0 - % compute the rotation matrix - % the inverse rotation matrix is the transposed of this one - val1 = norm(R); - val2 = norm(R(1:2)); - rot(1,1) = R(1) * R(3) / (val1 * val2); - rot(1,2) = R(2) * R(3) / (val1 * val2); - rot(1,3) = -1.0 * val2 / val1; - rot(2,1) = -1.0 * R(2) / val2; - rot(2,2) = R(1) / val2; - rot(2,3) = 0; - rot(3,:) = R ./ val1; - % rotate the electrodes - elc = elc*rot'; -elseif R(1)==0 && R(2)==0 && R(3)<0 - % dipole on negative z-axis, rotation is very simple: around x-axis - elc(2,:) = -elc(2,:); - elc(3,:) = -elc(3,:); -else - % dipole is on positive z-axis, nothing has to be done -end - -% compute the constant factors for the sphere configuration if needed -if ~isfield(vol, 't') - vol.t = eeg_leadfield4_prepare(vol); -end - -Nchans = size(elc,1); -lf = zeros(Nchans,3); -Nmax = length(vol.t); -n = 1:Nmax; -f = norm(R)/r4; % following cuffin1979 -% c = r2/r4; % following cuffin1979 -% d = r3/r4; % following cuffin1979 - -% this code is to cross-validate the lutkenhoner and cuffin implementations -% [lut_t, cuf_t] = eeg_leadfield4_prepare(vol); -% lut_c = (2*n+1).^4.*f.^(n-1) ./ (lut_t.*4*pi*c4*r4^2); -% cuf_c = (2*n+1).^4.*f.^(n-1) .*(c*d).^(2.*n+1) ./ (cuf_t.*4*pi*c4*r4^2); - -% given a fixed volume conductor, these only need to be computed once for all electrodes -const = (2*n+1).^4.*f.^(n-1) ./ (vol.t.*4*pi*c4*r4^2); - -for i=1:Nchans - % convert the position of the electrodes to spherical coordinates - [phi, el] = cart2sph(elc(i,1), elc(i,2), elc(i,3)); - - % change from colatitude to latitude and compute the cosine - cos_theta = cos(pi/2-el); - - % the series summation starts at zero - s_x = 0; - s_z = 0; - - for n=1:Nmax - P0 = plgndr(n,0,cos_theta); % zero'th order Legendre - P1 = plgndr(n,1,cos_theta); % first order Legendre - s_x = s_x + const(n)*P1/n; % s_y is identical - s_z = s_z + const(n)*P0; - end - - lf(i,1) = -cos(phi) * s_x; - lf(i,2) = -sin(phi) * s_x; % s_y is identical to s_x - lf(i,3) = 1 * s_z; -end - -% apply the inverse rotation to the leadfield matrix -if R(1)~=0 || R(2)~=0 - lf = lf*rot; -elseif R(1)==0 && R(2)==0 && R(3)<0 - lf(2,:) = -lf(2,:); - lf(3,:) = -lf(3,:); -end - diff --git a/external/forwinv/private/eeg_leadfield4_prepare.m b/external/forwinv/private/eeg_leadfield4_prepare.m deleted file mode 100644 index 0486904..0000000 --- a/external/forwinv/private/eeg_leadfield4_prepare.m +++ /dev/null @@ -1,85 +0,0 @@ -function [lut_t, cuf_t] = eeg_leadfield4_prepare(vol, Nmax); - -% EEG_LEADFIELD4_PREPARE computes constant factors for series expansion -% for the 4 concentric sphere electric leadfield computation -% -% use this function prior to repeated calls of eeg_leadfield4 according to -% vol.t = eeg_leadfield4_prepare(vol, N); -% where -% vol.r radius of the 4 spheres -% vol.c conductivity of the 4 spheres -% and N is the number of terms for the series (default 60). The constant -% factors t then do not have to be computed each time in eeg_leadfield4. -% -% See also EEG_LEADFIELD4 - -% Copyright (C) 2002, Robert Oostenveld -% -% this implementation is adapted from -% Lutkenhoner, Habilschrift 1992. -% which again is taken from -% B. N. Cuffin and D. Cohen. Comparion of the Magnetoencephalogram and the Electroencephalogram. Electroencephalogr Clin Neurophysiol, 47:131-146, 1979. -% -% $Log: eeg_leadfield4_prepare.m,v $ -% Revision 1.4 2003/07/29 16:02:07 roberto -% minor cosmetic change in the constants -% -% Revision 1.3 2003/07/29 15:52:44 roberto -% fixed a bug in the implementation of eeg_leadfield4, caused by mixing the constants of -% lutkenhoner and cuffin -% furthermore multiple cosmetic changes and default projection of electrodes to sphere -% -% Revision 1.2 2003/03/11 14:45:36 roberto -% updated help and copyrights -% - -% sort the spheres from the smallest to the largest -[vol.r, indx] = sort(vol.r); -[vol.c] = vol.c(indx); - -r1 = vol.r(1); c1 = vol.c(1); -r2 = vol.r(2); c2 = vol.c(2); -r3 = vol.r(3); c3 = vol.c(3); -r4 = vol.r(4); c4 = vol.c(4); - -if nargin==1 - Nmax = 60; -end - -% these are the constants of cuffin1979 -k1 = c1/c2; -k2 = c2/c3; -k3 = c3/c4; - -for n=1:Nmax - % according to lutkenhoner1992 the constant C is - % lut_t(n) = ((n*c1/c2+n+1)*(n*c2/c3+n+1)+n*(n+1)*(c1/c2-1)*(c2/c3-1)*(r1/r2)^(2*n+1)) * ... - % ((n*c3/c4+n+1)+(n+1)*(c3/c4-1)*(r3/r4)^(2*n+1)) + ... - % ((c1/c2-1)*((n+1)*c2/c3+n)*(r1/r3)^(2*n+1)+(n*c1/c2+n+1)*(c2/c3-1)*(r2/r3)^(2*n+1)) * ... - % (n+1)*(n*(c3/c4-1)+((n+1)*c3/c4+n)*(r3/r4)^(2*n+1)); - % which can be rewritten as - lut_t(n) = ((n*k1+n+1)*(n*k2+n+1)+n*(n+1)*(k1-1)*(k2-1)*(r1/r2)^(2*n+1)) * ... - ((n*k3+n+1)+(n+1)*(k3-1)*(r3/r4)^(2*n+1)) + ... - ((k1-1)*((n+1)*k2+n)*(r1/r3)^(2*n+1)+(n*k1+n+1)*(k2-1)*(r2/r3)^(2*n+1)) * ... - (n+1)*(n*(k3-1)+((n+1)*k3+n)*(r3/r4)^(2*n+1)); - -end - -% for debugging purposes, it can also give the constants of cuffin19979 -if nargout>1 - % some extra constants of cuffin1979 - b = r1/r4; - c = r2/r4; - d = r3/r4; - - % according to cuffin1979 the constant Tau is (re-entered on 25 sept 2002) - % but this requires also slightly other constants in the eeg_leadfield4 function - for n=1:Nmax - cuf_t(n) = d^(2*n+1) * (b^(2*n+1)*n*(k1-1)*(k2-1)*(n+1)... - + c^(2*n+1)*(k1*n+n+1)*(k2*n+n+1))... - *((k3*n+n+1)+(n+1)*(k3-1)*d^(2*n+1))... - +(n+1)*c^(2*n+1)*(b^(2*n+1)*(k1-1)*(k2*n+k2+n)... - +c^(2*n+1)*(k1*n+n+1)*(k2-1))... - *(n*(k3-1)+(k3*n+k3+n)*d^(2*n+1)); - end -end diff --git a/external/forwinv/private/eeg_leadfieldb.m b/external/forwinv/private/eeg_leadfieldb.m deleted file mode 100644 index 3d62a54..0000000 --- a/external/forwinv/private/eeg_leadfieldb.m +++ /dev/null @@ -1,148 +0,0 @@ -function [lf] = eeg_leadfieldb(pos, elc, vol) - -% EEG_LEADFIELDB computes the electric leadfield for a dipole in a volume -% using the boundary element method -% -% [lf] = eeg_leadfieldb(pos, elc, vol) -% -% with the input arguments -% pos position dipole (1x3 or Nx3) -% elc position electrodes (optional, can be empty) -% vol volume conductor model -% -% the volume conductor model is a structure and should have the fields -% vol.bnd structure array with vertices and triangles of each boundary -% vol.cond conductivity of all compartments -% vol.mat system matrix, which can include the electrode interpolation -% -% the compartment boundaries are described by a structure array with -% vol.bnd(i).pnt -% vol.bnd(i).pnt - -% Copyright (C) 2003, Robert Oostenveld -% -% $Log: eeg_leadfieldb.m,v $ -% Revision 1.5 2009/04/23 15:06:14 roboos -% added patch from Cristiano -% -% Revision 1.4 2009/03/30 15:06:14 roboos -% added the patch from Alexandre to support openmeeg -% -% Revision 1.3 2009/02/02 13:12:53 roboos -% small fix, cpbem->bemcp -% -% Revision 1.2 2009/02/02 12:59:26 roboos -% added bemcp implementation, do not use vol.tra any more, made some changes to the checks on the input structures, use voltype in switch ladder -% -% Revision 1.1 2009/01/21 10:32:38 roboos -% moved from forwinv/* and forwinv/mex/* directory to forwinv/private/* to make the CVS layout consistent with the release version -% -% Revision 1.3 2008/04/14 20:54:35 roboos -% be more explicit about BEM type -% -% Revision 1.2 2005/12/06 11:41:07 roboos -% added support for dipoli models -% restructured the whole code -% combine electrode transfer and system matrix in a single matrix to speed forward computations up -% -% Revision 1.1 2003/10/07 08:40:22 roberto -% made separate function for BEM, based on part of eeg_leadfield.m -% - - -% do some sanity checks -if ~isfield(vol, 'bnd') - error('there are no compartment boundaries present'); -end - -if length(vol.bnd)~=length(vol.cond) - error('the number of compartments in the volume in ambiguous'); -end - -if ~isfield(vol, 'mat') - error('there is no BEM system matrix present'); -end - -% determine the number of compartments -ncmp = length(vol.bnd); - -% the number of rows in the leadfield matrix should either correspond to -% the number of electrodes, to the number of vertices of the skin -% compartment or to the total number of vertices -nelc = size(elc, 1); -nskin = size(vol.bnd(vol.skin).pnt,1); -nall = 0; -for i=1:ncmp - nall = nall + size(vol.bnd(i).pnt,1); -end -if size(vol.mat,1)==nelc - % the output leadfield corresponds to the number of electrodes -elseif size(vol.mat,1)==nskin - % the output leadfield corresponds to the number skin vertices -elseif size(vol.mat,1)==nall - % the output leadfield corresponds to the total number of vertices -elseif strcmp(voltype(vol),'openmeeg') - % this is handled differently, although at the moment I don't know why -else - error('unexpected size of vol.mat') -end - -% determine the conductivity of the source compartment -cond = vol.cond(vol.source); - -% compute the infinite medium potential on all vertices -switch voltype(vol) - case 'avo' - % the system matrix was computed using code from Adriaan van Oosterom - % the code by Adriaan van Oosterom does not implement isolated source approach - lf = []; - for i=1:ncmp - lf = [lf; inf_medium_leadfield(pos, vol.bnd(i).pnt, mean(vol.sigmas(i,:)))]; - end - - case 'dipoli' - % the system matrix was computed using Thom Oostendorp's DIPOLI - % concatenate the vertices of all compartment boundaries in a single Nx3 matrix - pnt = []; - for i=1:ncmp - pnt = [pnt; vol.bnd(i).pnt]; - end - % dipoli incorporates the conductivity into the system matrix - lf = inf_medium_leadfield(pos, pnt, 1); - - case 'asa' - % the system matrix was computed using ASA from www.ant-neuro.com - % concatenate the vertices of all compartment boundaries in a single Nx3 matrix - pnt = []; - for i=1:ncmp - pnt = [pnt; vol.bnd(i).pnt]; - end - % assume that isolated potential approach was used - lf = inf_medium_leadfield(pos, pnt, cond); - - case 'bemcp' - % the system matrix was computed using code from Christopher Phillips - cond = [vol.cond 0]; % add the conductivity of air for simplicity - lf = cell(1,ncmp); - % loop over boundaries and compute the leadfield for each - for i=1:ncmp - co = (cond(i)+cond(i+1))/2 ; - lf{i} = inf_medium_leadfield(pos, vol.bnd(i).pnt, co); - end - % concatenate the leadfields - lf = cat(1, lf{:}); - - case 'openmeeg' - % the system matrix is computed using OpenMEEG (Symmetric BEM) - lf = openmeeg_lf_eeg(pos, elc, vol); - - otherwise - error('unsupported type of volume conductor (%s)\n', voltype(vol)); -end % switch voltype - -if isfield(vol, 'mat') && ~voltype(vol, 'openmeeg') - % compute the bounded medium potential on all vertices - % this may include the bilinear interpolation from vertices towards electrodes - lf = vol.mat * lf; -end - diff --git a/external/forwinv/private/estimate_units.m b/external/forwinv/private/estimate_units.m deleted file mode 100644 index 2749632..0000000 --- a/external/forwinv/private/estimate_units.m +++ /dev/null @@ -1,37 +0,0 @@ -function unit = estimate_units(size) - -% ESTIMATE_UNITS tries to determine the units of a geometrical object by -% looking at its size and by relating this to the size of the human -% brain. -% -% Use as -% unit = estimate_units(size) -% -% This function will return one of the following strings -% 'm' -% 'dm' -% 'cm' -% 'mm' - -% Copyright (C) 2009, Robert Oostenveld -% -% $Log: estimate_units.m,v $ -% Revision 1.1 2009/03/26 14:57:04 roboos -% moved the unit estimation to a seperate function -% - -% do some magic based on the size -unit = {'m', 'dm', 'cm', 'mm'}; -indx = round(log10(size)+2-0.2); - -if indx>length(unit) - indx = length(unit); - warning('assuming that the units are "%s"', unit{indx}); -end - -if indx<1 - indx = 1; - warning('assuming that the units are "%s"', unit{indx}); -end - -unit = unit{indx}; diff --git a/external/forwinv/private/filetype.m b/external/forwinv/private/filetype.m deleted file mode 100644 index 57d83ee..0000000 --- a/external/forwinv/private/filetype.m +++ /dev/null @@ -1,846 +0,0 @@ -function [ftype, detail] = filetype(filename, desired, varargin); - -% FILETYPE determines the filetype of many EEG/MEG/MRI data files by -% looking at the name, extension and optionally (part of) its contents. -% It tries to determine the global type of file (which usually -% corresponds to the manufacturer, the recording system or to the -% software used to create the file) and the particular subtype (e.g. -% continuous, average). -% -% Use as -% type = filetype(filename) -% type = filetype(dirname) -% -% This gives you a descriptive string with the data type, and can be -% used in a switch-statement. The descriptive string that is returned -% usually is something like 'XXX_YYY'/ where XXX refers to the -% manufacturer and YYY to the type of the data. -% -% Alternatively, use as -% flag = filetype(filename, type) -% flag = filetype(dirname, type) -% This gives you a boolean flag (0 or 1) indicating whether the file -% is of the desired type, and can be used to check whether the -% user-supplied file is what your subsequent code expects. -% -% Alternatively, use as -% flag = filetype(dirlist, type) -% where the dirlist contains a list of files contained within one -% directory. This gives you a boolean vector indicating for each file -% whether it is of the desired type. -% -% Most filetypes of the following manufacturers and/or software programs are recognized -% - VSMMedtech/CTF -% - Elektra/Neuromag -% - Yokogawa -% - 4D/BTi -% - EDF -% - Neuroscan -% - Analyse -% - EEProbe -% - BrainVision -% - BESA -% - Curry -% - ASA -% - LORETA -% - Analyze/SPM -% - MINC -% - AFNI -% - Neuralynx -% - Plexon -% -% See also READ_XXX_YYY where XXX=manufacturer and YYY=subtype - -% Copyright (C) 2003-2007 Robert Oostenveld -% -% $Log: filetype.m,v $ -% Revision 1.72 2008/04/21 11:50:51 roboos -% added support for egi_sbin, thanks to Joseph Dien -% -% Revision 1.71 2008/04/18 14:08:03 roboos -% added eeglab_set -% -% Revision 1.70 2008/04/11 12:09:18 roboos -% added polhemus_fil -% -% Revision 1.69 2008/03/04 11:14:26 roboos -% added neuralynx_nst -% -% Revision 1.68 2008/02/19 10:07:34 roboos -% replaced tcpsocket with buffer -% -% Revision 1.67 2008/01/31 20:10:22 roboos -% It is necessary to identify when it is necessary to execute the new -% read_4d_hdr.m function. To achieve this an extra IF statement was -% added from line 312. This statement checks for a passed filename -% which has no extension (not the case for .xyz or .m4d) and that the -% second to fourth characters in the filename are ,rf. If both of -% these conditions are met then the filetype and manufacturer are set -% to 4d. [thanks to Gavin] -% -% Revision 1.66 2008/01/25 07:41:57 roboos -% moved some code, no functional change -% -% Revision 1.65 2008/01/15 08:12:30 roboos -% more strict test for ctf_ds -% -% Revision 1.64 2007/12/19 07:17:26 roboos -% removed ftc, added txt -% -% Revision 1.63 2007/12/17 16:14:44 roboos -% added neuralynx_bin -% -% Revision 1.62 2007/12/17 08:25:04 roboos -% added nexstim_nxe -% -% Revision 1.61 2007/12/12 16:48:20 roboos -% deal with case of extension for nev/Nev -% fixed bug: correctly locate the events.nev file in the dataset directory -% -% Revision 1.60 2007/12/12 14:39:26 roboos -% added riff_wave -% -% Revision 1.59 2007/12/06 17:05:54 roboos -% added fcdc_ftc, only on file extension -% -% Revision 1.58 2007/10/25 12:47:31 roboos -% added *.nrd as neuralynx_dma, not sure yet whether this is correct -% -% Revision 1.57 2007/10/16 12:35:08 roboos -% implemented fcdc_global -% -% Revision 1.56 2007/10/15 16:02:46 roboos -% added rfb://@: -% -% Revision 1.55 2007/10/04 11:55:40 roboos -% added the various spass file formats -% -% Revision 1.54 2007/09/13 09:46:51 roboos -% adedd ctf_wts and svl -% -% Revision 1.53 2007/08/06 09:07:33 roboos -% added 4d_hs -% -% Revision 1.52 2007/07/27 12:17:47 roboos -% added ctf_shm -% -% Revision 1.51 2007/07/04 13:20:51 roboos -% added support for egi_egis/egia, thanks to Joseph Dien -% -% Revision 1.50 2007/06/06 07:10:16 roboos -% changed detection of BCI streams into using URI scheme -% changed deterction of BESA source waveform files -% -% Revision 1.49 2007/06/04 18:24:49 roboos -% added nifti -% -% Revision 1.48 2007/05/31 09:13:28 roboos -% added tcpsocket ans serial port -% -% Revision 1.47 2007/05/15 14:59:54 roboos -% try to separate besa *.dat from brainvision *.dat -% -% Revision 1.46 2007/04/25 15:27:28 roboos -% rmoved besa_gen, instead added besa_sb (simple binary), which comes with the *.gen or *.generic ascii header file -% -% Revision 1.45 2007/03/21 17:21:30 roboos -% remove . and .. from the file listing in case of a directory as input -% removed neuralynx_nte, the correct extension is *.nts -% added header check to neuralynx_nts -% implemented subfunction most, c.f. any -% swiched from using any(...) to most(...) for determining content of dataset directory -% implemented plexon_ds for directory with nex files in it -% made some additional small changes -% -% Revision 1.44 2007/03/19 16:52:37 roboos -% added neuralynx_nte -% -% Revision 1.43 2007/01/09 09:29:25 roboos -% small change -% -% Revision 1.42 2007/01/04 08:12:00 roboos -% fixed bug for besa_avr, renamed an incorrect tag into plexon_plx -% - -if nargin<2 - desired = []; -end - -% % get the optional arguments -% checkheader = keyval('checkheader', varargin); if isempty(checkheader), checkheader=1; end -% -% if ~checkheader -% % assume that the header is always ok, e.g when the file does not yet exist -% % this replaces the normal function with a function that always returns true -% filetype_check_header = @filetype_true; -% end - -if iscell(filename) - % perform the test for each filename, return a boolean vector - ftype = false(size(filename)); - for i=1:length(filename) - if strcmp(filename{i}(end), '.') - % do not recurse into this directory or the parent directory - continue - else - ftype(i) = filetype(filename{i}, desired); - end - end - return -end - -% start with unknown values -ftype = 'unknown'; -manufacturer = 'unknown'; -content = 'unknown'; - -[p, f, x] = fileparts(filename); - -if isdir(filename) - % the directory listing is needed below - ls = dir(filename); - % remove the parent directory and the directory itself from the list - ls = ls(~strcmp({ls.name}, '.')); - ls = ls(~strcmp({ls.name}, '..')); - for i=1:length(ls) - % make sure that the directory listing includes the complete path - ls(i).name = fullfile(filename, ls(i).name); - end -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% start determining the filetype -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% these are some streams for asynchronous BCI -if filetype_check_uri(filename, 'fifo') - ftype = 'fcdc_fifo'; - manufacturer = 'F.C. Donders Centre'; - content = 'stream'; -elseif filetype_check_uri(filename, 'buffer') - ftype = 'fcdc_buffer'; - manufacturer = 'F.C. Donders Centre'; - content = 'stream'; -elseif filetype_check_uri(filename, 'mysql') - ftype = 'fcdc_mysql'; - manufacturer = 'F.C. Donders Centre'; - content = 'stream'; -elseif filetype_check_uri(filename, 'rfb') - ftype = 'fcdc_rfb'; - manufacturer = 'F.C. Donders Centre'; - content = 'stream'; -elseif filetype_check_uri(filename, 'serial') - ftype = 'fcdc_serial'; - manufacturer = 'F.C. Donders Centre'; - content = 'stream'; -elseif filetype_check_uri(filename, 'global') - ftype = 'fcdc_global'; - manufacturer = 'F.C. Donders Centre'; - content = 'global variable'; -elseif filetype_check_uri(filename, 'shm') - ftype = 'ctf_shm'; - manufacturer = 'CTF'; - content = 'real-time shared memory buffer'; - - % known CTF file types -elseif isdir(filename) && filetype_check_extension(filename, '.ds') && exist(fullfile(filename, [f '.res4'])) - ftype = 'ctf_ds'; - manufacturer = 'CTF'; - content = 'MEG dataset'; -elseif filetype_check_extension(filename, '.res4') && (filetype_check_header(filename, 'MEG41RS') || filetype_check_header(filename, 'MEG42RS') || filetype_check_header(filename, 'MEG4RES')) - ftype = 'ctf_res4'; - manufacturer = 'CTF'; - content = 'MEG/EEG header information'; -elseif filetype_check_extension(filename, '.meg4') && filetype_check_header(filename, 'MEG41CP') - ftype = 'ctf_meg4'; - manufacturer = 'CTF'; - content = 'MEG/EEG'; -elseif filetype_check_extension(filename, '.mrk') && filetype_check_header(filename, 'PATH OF DATASET:') - ftype = 'ctf_mrk'; - manufacturer = 'CTF'; - content = 'marker file'; -elseif filetype_check_extension(filename, '.mri') && filetype_check_header(filename, 'CTF_MRI_FORMAT VER 2.2') - ftype = 'ctf_mri'; - manufacturer = 'CTF'; - content = 'MRI'; -elseif filetype_check_extension(filename, '.hdm') - ftype = 'ctf_hdm'; - manufacturer = 'CTF'; - content = 'volume conduction model'; -elseif filetype_check_extension(filename, '.hc') - ftype = 'ctf_hc'; - manufacturer = 'CTF'; - content = 'headcoil locations'; -elseif filetype_check_extension(filename, '.shape') - ftype = 'ctf_shape'; - manufacturer = 'CTF'; - content = 'headshape points'; -elseif filetype_check_extension(filename, '.shape_info') - ftype = 'ctf_shapeinfo'; - manufacturer = 'CTF'; - content = 'headshape information'; -elseif filetype_check_extension(filename, '.wts') - ftype = 'ctf_wts'; - manufacturer = 'CTF'; - content = 'SAM coefficients, i.e. spatial filter weights'; -elseif filetype_check_extension(filename, '.svl') - ftype = 'ctf_svl'; - manufacturer = 'CTF'; - content = 'SAM (pseudo-)statistic volumes'; - - % known Neuromag file types -elseif filetype_check_extension(filename, '.fif') - ftype = 'neuromag_fif'; - manufacturer = 'Neuromag'; - content = 'MEG header and data'; -elseif filetype_check_extension(filename, '.bdip') - ftype = 'neuromag_bdip'; - manufacturer = 'Neuromag'; - content = 'dipole model'; - - % known Yokogawa file types -elseif filetype_check_extension(filename, '.ave') || filetype_check_extension(filename, '.sqd') - ftype = 'yokogawa_ave'; - manufacturer = 'Yokogawa'; - content = 'averaged MEG data'; -elseif filetype_check_extension(filename, '.con') - ftype = 'yokogawa_con'; - manufacturer = 'Yokogawa'; - content = 'continuous MEG data'; -elseif filetype_check_extension(filename, '.raw') - ftype = 'yokogawa_raw'; - manufacturer = 'Yokogawa'; - content = 'evoked/trialbased MEG data'; -elseif filetype_check_extension(filename, '.mri') && filetype_check_header(filename, '####') % FIXME, not correct - ftype = 'yokogawa_mri'; - manufacturer = 'Yokogawa'; - content = 'anatomical MRI'; - -elseif filetype_check_extension(filename, '.pdf') && filetype_check_header(filename, 'E|lk') % I am not sure whether this header always applies - ftype = '4d_pdf'; - manufacturer = '4D/BTI'; - content = 'raw MEG data (processed data file)'; -elseif exist([filename '.m4d'], 'file') && exist([filename '.xyz'], 'file') % these two ascii header files accompany the raw data - ftype = '4d_pdf'; - manufacturer = '4D/BTI'; - content = 'raw MEG data (processed data file)'; -elseif filetype_check_extension(filename, '.m4d') && exist([filename(1:(end-3)) 'xyz'], 'file') % these come in pairs - ftype = '4d_m4d'; - manufacturer = '4D/BTI'; - content = 'MEG header information'; -elseif filetype_check_extension(filename, '.xyz') && exist([filename(1:(end-3)) 'm4d'], 'file') % these come in pairs - ftype = '4d_xyz'; - manufacturer = '4D/BTI'; - content = 'MEG sensor positions'; -elseif isequal(f, 'hs_file') % the filename is "hs_file" - ftype = '4d_hs'; - manufacturer = '4D/BTI'; - content = 'head shape'; -elseif isempty(find(filename=='.')) && length(filename)>=4 && strcmp(filename(2:4),',rf') - ftype = '4d'; - manufacturer = '4D/BTi'; - content = ''; - - % known EEProbe file types -elseif filetype_check_extension(filename, '.cnt') && filetype_check_header(filename, 'RIFF') - ftype = 'eep_cnt'; - manufacturer = 'EEProbe'; - content = 'EEG'; -elseif filetype_check_extension(filename, '.avr') && filetype_check_header(filename, char([38 0 16 0])) - ftype = 'eep_avr'; - manufacturer = 'EEProbe'; - content = 'ERP'; -elseif filetype_check_extension(filename, '.trg') - ftype = 'eep_trg'; - manufacturer = 'EEProbe'; - content = 'trigger information'; -elseif filetype_check_extension(filename, '.rej') - ftype = 'eep_rej'; - manufacturer = 'EEProbe'; - content = 'rejection marks'; - - % known ASA file types -elseif filetype_check_extension(filename, '.elc') - ftype = 'asa_elc'; - manufacturer = 'ASA'; - content = 'electrode positions'; -elseif filetype_check_extension(filename, '.vol') - ftype = 'asa_vol'; - manufacturer = 'ASA'; - content = 'volume conduction model'; -elseif filetype_check_extension(filename, '.bnd') - ftype = 'asa_bnd'; - manufacturer = 'ASA'; - content = 'boundary element model details'; -elseif filetype_check_extension(filename, '.msm') - ftype = 'asa_msm'; - manufacturer = 'ASA'; - content = 'ERP'; -elseif filetype_check_extension(filename, '.msr') - ftype = 'asa_msr'; - manufacturer = 'ASA'; - content = 'ERP'; -elseif filetype_check_extension(filename, '.dip') - % FIXME, can also be CTF dipole file - ftype = 'asa_dip'; - manufacturer = 'ASA'; -elseif filetype_check_extension(filename, '.mri') - % FIXME, can also be CTF mri file - ftype = 'asa_mri'; - manufacturer = 'ASA'; - content = 'MRI image header'; -elseif filetype_check_extension(filename, '.iso') - ftype = 'asa_iso'; - manufacturer = 'ASA'; - content = 'MRI image data'; - - % known Neuroscan file types -elseif filetype_check_extension(filename, '.avg') && filetype_check_header(filename, 'Version 3.0') - ftype = 'ns_avg'; - manufacturer = 'Neuroscan'; - content = 'averaged EEG'; -elseif filetype_check_extension(filename, '.cnt') && filetype_check_header(filename, 'Version 3.0') - ftype = 'ns_cnt'; - manufacturer = 'Neuroscan'; - content = 'continuous EEG'; -elseif filetype_check_extension(filename, '.eeg') && filetype_check_header(filename, 'Version 3.0') - ftype = 'ns_eeg'; - manufacturer = 'Neuroscan'; - content = 'epoched EEG'; - - % known Analyze & SPM file types -elseif filetype_check_extension(filename, '.hdr') - ftype = 'analyze_hdr'; - manufacturer = 'Mayo Analyze'; - content = 'PET/MRI image header'; -elseif filetype_check_extension(filename, '.img') - ftype = 'analyze_img'; - manufacturer = 'Mayo Analyze'; - content = 'PET/MRI image data'; -elseif filetype_check_extension(filename, '.mnc') - ftype = 'minc'; - content = 'MRI image data'; -elseif filetype_check_extension(filename, '.nii') - ftype = 'nifti'; - content = 'MRI image data'; - - % known LORETA file types -elseif filetype_check_extension(filename, '.lorb') - ftype = 'loreta_lorb'; - manufacturer = 'old LORETA'; - content = 'source reconstruction'; -elseif filetype_check_extension(filename, '.slor') - ftype = 'loreta_slor'; - manufacturer = 'sLORETA'; - content = 'source reconstruction'; - - % known AFNI file types -elseif filetype_check_extension(filename, '.brik') || filetype_check_extension(filename, '.BRIK') - ftype = 'afni_brik'; - content = 'MRI image data'; -elseif filetype_check_extension(filename, '.head') || filetype_check_extension(filename, '.HEAD') - ftype = 'afni_head'; - content = 'MRI header data'; - - % known BrainVison file types -elseif filetype_check_extension(filename, '.vhdr') - ftype = 'brainvision_vhdr'; - manufacturer = 'BrainProducts'; - content = 'EEG header'; -elseif filetype_check_extension(filename, '.vmrk') - ftype = 'brainvision_vmrk'; - manufacturer = 'BrainProducts'; - content = 'EEG markers'; -elseif filetype_check_extension(filename, '.vabs') - ftype = 'brainvision_vabs'; - manufacturer = 'BrainProducts'; - content = 'Brain Vison Analyzer macro'; -elseif filetype_check_extension(filename, '.eeg') - % FIXME, can also be Neuroscan epoched EEG data - ftype = 'brainvision_eeg'; - manufacturer = 'BrainProducts'; - content = 'continuous EEG data'; -elseif filetype_check_extension(filename, '.seg') - ftype = 'brainvision_seg'; - manufacturer = 'BrainProducts'; - content = 'segmented EEG data'; -elseif filetype_check_extension(filename, '.dat') && ~filetype_check_header(filename, 'BESA_SA_IMAGE') && ~(exist(fullfile(p, [f '.gen']), 'file') || exist(fullfile(p, [f '.generic']), 'file')) - % WARNING this is a very general name, it could be exported BrainVision - % data but also a BESA beamformer source reconstruction - ftype = 'brainvision_dat'; - manufacturer = 'BrainProducts'; - content = 'exported EEG data'; -elseif filetype_check_extension(filename, '.marker') - ftype = 'brainvision_marker'; - manufacturer = 'BrainProducts'; - content = 'rejection markers'; - - % known Polhemus file types -elseif filetype_check_extension(filename, '.pos') - ftype = 'polhemus_pos'; - manufacturer = 'BrainProducts/CTF/Polhemus?'; % actually I don't know whose software it is - content = 'electrode positions'; - - % known Neuralynx file types -elseif filetype_check_extension(filename, '.nev') || filetype_check_extension(filename, '.Nev') - ftype = 'neuralynx_nev'; - manufacturer = 'Neuralynx'; - content = 'event information'; -elseif filetype_check_extension(filename, '.ncs') && filetype_check_header(filename, '####') - ftype = 'neuralynx_ncs'; - manufacturer = 'Neuralynx'; - content = 'continuous single channel recordings'; -elseif filetype_check_extension(filename, '.nse') && filetype_check_header(filename, '####') - ftype = 'neuralynx_nse'; - manufacturer = 'Neuralynx'; - content = 'spike waveforms'; -elseif filetype_check_extension(filename, '.nts') && filetype_check_header(filename, '####') - ftype = 'neuralynx_nts'; - manufacturer = 'Neuralynx'; - content = 'timestamps only'; -elseif filetype_check_extension(filename, '.nvt') - ftype = 'neuralynx_nvt'; - manufacturer = 'Neuralynx'; - content = 'video tracker'; -elseif filetype_check_extension(filename, '.nst') - ftype = 'neuralynx_nst'; - manufacturer = 'Neuralynx'; - content = 'continuous stereotrode recordings'; -elseif filetype_check_extension(filename, '.ntt') - ftype = 'neuralynx_ntt'; - manufacturer = 'Neuralynx'; - content = 'continuous tetrode recordings'; -elseif strcmpi(f, 'logfile') && strcmpi(x, '.txt') % case insensitive - ftype = 'neuralynx_log'; - manufacturer = 'Neuralynx'; - content = 'log information in ASCII format'; -elseif ~isempty(strfind(lower(f), 'dma')) && strcmpi(x, '.log') % this is not a very strong detection - ftype = 'neuralynx_dma'; - manufacturer = 'Neuralynx'; - content = 'raw aplifier data directly from DMA'; -elseif filetype_check_extension(filename, '.nrd') % see also above, since Cheetah 5.x the file extension has changed - ftype = 'neuralynx_dma'; - manufacturer = 'Neuralynx'; - content = 'raw aplifier data directly from DMA'; -elseif isdir(filename) && (any(filetype_check_extension({ls.name}, '.nev')) || any(filetype_check_extension({ls.name}, '.Nev'))) - % a regular Neuralynx dataset directory that contains an event file - ftype = 'neuralynx_ds'; - manufacturer = 'Neuralynx'; - content = 'dataset'; -elseif isdir(filename) && most(filetype_check_extension({ls.name}, '.ncs')) - % a directory containing continuously sampled channels in Neuralynx format - ftype = 'neuralynx_ds'; - manufacturer = 'Neuralynx'; - content = 'continuously sampled channels'; -elseif isdir(filename) && most(filetype_check_extension({ls.name}, '.nse')) - % a directory containing spike waveforms in Neuralynx format - ftype = 'neuralynx_ds'; - manufacturer = 'Neuralynx'; - content = 'spike waveforms'; -elseif isdir(filename) && most(filetype_check_extension({ls.name}, '.nte')) - % a directory containing spike timestamps in Neuralynx format - ftype = 'neuralynx_ds'; - manufacturer = 'Neuralynx'; - content = 'spike timestamps'; - - % these are formally not Neuralynx file formats, but at the FCDC we use them together with Neuralynx -elseif isdir(filename) && any(filetype({ls.name}, 'neuralynx_ds')) - % a downsampled Neuralynx DMA file can be split into three seperate lfp/mua/spike directories - % treat them as one combined dataset - ftype = 'neuralynx_cds'; - manufacturer = 'F.C. Donders Centre'; - content = 'dataset containing seperate lfp/mua/spike directories'; -elseif filetype_check_extension(filename, '.tsl') && filetype_check_header(filename, 'tsl') - ftype = 'neuralynx_tsl'; - manufacturer = 'F.C. Donders Centre'; - content = 'timestamps from DMA log file'; -elseif filetype_check_extension(filename, '.tsh') && filetype_check_header(filename, 'tsh') - ftype = 'neuralynx_tsh'; - manufacturer = 'F.C. Donders Centre'; - content = 'timestamps from DMA log file'; -elseif filetype_check_extension(filename, '.ttl') && filetype_check_header(filename, 'ttl') - ftype = 'neuralynx_ttl'; - manufacturer = 'F.C. Donders Centre'; - content = 'Parallel_in from DMA log file'; -elseif filetype_check_extension(filename, '.bin') && filetype_check_header(filename, {'uint8', 'uint16', 'uint32', 'int8', 'int16', 'int32', 'int64', 'float32', 'float64'}) - ftype = 'neuralynx_bin'; - manufacturer = 'F.C. Donders Centre'; - content = 'single channel continuous data'; -elseif isdir(filename) && any(filetype_check_extension({ls.name}, '.ttl')) && any(filetype_check_extension({ls.name}, '.tsl')) && any(filetype_check_extension({ls.name}, '.tsh')) - % a directory containing the split channels from a DMA logfile - ftype = 'neuralynx_sdma'; - manufacturer = 'F.C. Donders Centre'; - content = 'dataset'; -elseif isdir(filename) && filetype_check_extension(filename, '.sdma') - % a directory containing the split channels from a DMA logfile - ftype = 'neuralynx_sdma'; - manufacturer = 'F.C. Donders Centre'; - content = 'split DMA log file'; - - % known Plexon file types -elseif filetype_check_extension(filename, '.nex') && filetype_check_header(filename, 'NEX1') - ftype = 'plexon_nex'; - manufacturer = 'Plexon'; - content = 'electrophysiological data'; -elseif filetype_check_extension(filename, '.plx') && filetype_check_header(filename, 'PLEX') - ftype = 'plexon_plx'; - manufacturer = 'Plexon'; - content = 'electrophysiological data'; -elseif filetype_check_extension(filename, '.ddt') - ftype = 'plexon_ddt'; - manufacturer = 'Plexon'; -elseif isdir(filename) && most(filetype_check_extension({ls.name}, '.nex')) && most(filetype_check_header({ls.name}, 'NEX1')) - % a directory containing multiple plexon NEX files - ftype = 'plexon_ds'; - manufacturer = 'Plexon'; - content = 'electrophysiological data'; - - % known Cambridge Electronic Design file types -elseif filetype_check_extension(filename, '.smr') - ftype = 'ced_son'; - manufacturer = 'Cambridge Electronic Design'; - content = 'Spike2 SON filing system'; - - % known BESA file types -elseif filetype_check_extension(filename, '.avr') && strcmp(ftype, 'unknown') - ftype = 'besa_avr'; % FIXME, can also be EEProbe average EEG - manufacturer = 'BESA'; - content = 'average EEG'; -elseif filetype_check_extension(filename, '.elp') - ftype = 'besa_elp'; - manufacturer = 'BESA'; - content = 'electrode positions'; -elseif filetype_check_extension(filename, '.eps') - ftype = 'besa_eps'; - manufacturer = 'BESA'; - content = 'digitizer information'; -elseif filetype_check_extension(filename, '.sfp') - ftype = 'besa_sfp'; - manufacturer = 'BESA'; - content = 'sensor positions'; -elseif filetype_check_extension(filename, '.ela') - ftype = 'besa_ela'; - manufacturer = 'BESA'; - content = 'sensor information'; -elseif filetype_check_extension(filename, '.pdg') - ftype = 'besa_pdg'; - manufacturer = 'BESA'; - content = 'paradigm file'; -elseif filetype_check_extension(filename, '.tfc') - ftype = 'besa_tfc'; - manufacturer = 'BESA'; - content = 'time frequency coherence'; -elseif filetype_check_extension(filename, '.mul') - ftype = 'besa_mul'; - manufacturer = 'BESA'; - content = 'multiplexed ascii format'; -elseif filetype_check_extension(filename, '.dat') && filetype_check_header(filename, 'BESA_SA') % header can start with BESA_SA_IMAGE or BESA_SA_MN_IMAGE - ftype = 'besa_src'; - manufacturer = 'BESA'; - content = 'beamformer source reconstruction'; -elseif filetype_check_extension(filename, '.swf') && filetype_check_header(filename, 'Npts=') - ftype = 'besa_swf'; - manufacturer = 'BESA'; - content = 'beamformer source waveform'; -elseif filetype_check_extension(filename, '.bsa') - ftype = 'besa_bsa'; - manufacturer = 'BESA'; - content = 'beamformer source locations and orientations'; -elseif exist(fullfile(p, [f '.dat']), 'file') && (exist(fullfile(p, [f '.gen']), 'file') || exist(fullfile(p, [f '.generic']), 'file')) - ftype = 'besa_sb'; - manufacturer = 'BESA'; - content = 'simple binary channel data with a seperate generic ascii header'; - - % old files from Pascal Fries' PhD research at the MPI -elseif filetype_check_extension(filename, '.dap') && filetype_check_header(filename, char(1)) - ftype = 'mpi_dap'; - manufacturer = 'MPI Frankfurt'; - content = 'electrophysiological data'; -elseif isdir(filename) && ~isempty(cell2mat(regexp({ls.name}, '.dap$'))) - ftype = 'mpi_ds'; - manufacturer = 'MPI Frankfurt'; - content = 'electrophysiological data'; - - % Frankfurt SPASS format, which uses the Labview Datalog (DTLG) format -elseif filetype_check_header(filename, 'DTLG') && filetype_check_extension(filename, '.ana') - ftype = 'spass_ana'; - manufacturer = 'MPI Frankfurt'; - content = 'electrophysiological data'; -elseif filetype_check_header(filename, 'DTLG') && filetype_check_extension(filename, '.swa') - ftype = 'spass_swa'; - manufacturer = 'MPI Frankfurt'; - content = 'electrophysiological data'; -elseif filetype_check_header(filename, 'DTLG') && filetype_check_extension(filename, '.spi') - ftype = 'spass_spi'; - manufacturer = 'MPI Frankfurt'; - content = 'electrophysiological data'; -elseif filetype_check_header(filename, 'DTLG') && filetype_check_extension(filename, '.stm') - ftype = 'spass_stm'; - manufacturer = 'MPI Frankfurt'; - content = 'electrophysiological data'; -elseif filetype_check_header(filename, 'DTLG') && filetype_check_extension(filename, '.bhv') - ftype = 'spass_bhv'; - manufacturer = 'MPI Frankfurt'; - content = 'electrophysiological data'; - - % known Nexstim file types -elseif filetype_check_extension(filename, '.nxe') - ftype = 'nexstim_nxe'; - manufacturer = 'Nexstim'; - content = 'electrophysiological data'; - - % known Curry V4 file types -elseif filetype_check_extension(filename, '.dap') - ftype = 'curry_dap'; % FIXME, can also be MPI Frankfurt electrophysiological data - manufacturer = 'Curry'; - content = 'data parameter file'; -elseif filetype_check_extension(filename, '.dat') - ftype = 'curry_dat'; - manufacturer = 'Curry'; - content = 'raw data file'; -elseif filetype_check_extension(filename, '.rs4') - ftype = 'curry_rs4'; - manufacturer = 'Curry'; - content = 'sensor geometry file'; -elseif filetype_check_extension(filename, '.par') - ftype = 'curry_par'; - manufacturer = 'Curry'; - content = 'data or image parameter file'; -elseif filetype_check_extension(filename, '.bd0') || filetype_check_extension(filename, '.bd1') || filetype_check_extension(filename, '.bd2') || filetype_check_extension(filename, '.bd3') || filetype_check_extension(filename, '.bd4') || filetype_check_extension(filename, '.bd5') || filetype_check_extension(filename, '.bd6') || filetype_check_extension(filename, '.bd7') || filetype_check_extension(filename, '.bd8') || filetype_check_extension(filename, '.bd9') - ftype = 'curry_bd'; - manufacturer = 'Curry'; - content = 'BEM description file'; -elseif filetype_check_extension(filename, '.bt0') || filetype_check_extension(filename, '.bt1') || filetype_check_extension(filename, '.bt2') || filetype_check_extension(filename, '.bt3') || filetype_check_extension(filename, '.bt4') || filetype_check_extension(filename, '.bt5') || filetype_check_extension(filename, '.bt6') || filetype_check_extension(filename, '.bt7') || filetype_check_extension(filename, '.bt8') || filetype_check_extension(filename, '.bt9') - ftype = 'curry_bt'; - manufacturer = 'Curry'; - content = 'BEM transfer matrix file'; -elseif filetype_check_extension(filename, '.bm0') || filetype_check_extension(filename, '.bm1') || filetype_check_extension(filename, '.bm2') || filetype_check_extension(filename, '.bm3') || filetype_check_extension(filename, '.bm4') || filetype_check_extension(filename, '.bm5') || filetype_check_extension(filename, '.bm6') || filetype_check_extension(filename, '.bm7') || filetype_check_extension(filename, '.bm8') || filetype_check_extension(filename, '.bm9') - ftype = 'curry_bm'; - manufacturer = 'Curry'; - content = 'BEM full matrix file'; -elseif filetype_check_extension(filename, '.dig') - ftype = 'curry_dig'; - manufacturer = 'Curry'; - content = 'digitizer file'; - - % known Curry V2 file types -elseif filetype_check_extension(filename, '.sp0') || filetype_check_extension(filename, '.sp1') || filetype_check_extension(filename, '.sp2') || filetype_check_extension(filename, '.sp3') || filetype_check_extension(filename, '.sp4') || filetype_check_extension(filename, '.sp5') || filetype_check_extension(filename, '.sp6') || filetype_check_extension(filename, '.sp7') || filetype_check_extension(filename, '.sp8') || filetype_check_extension(filename, '.sp9') - ftype = 'curry_sp'; - manufacturer = 'Curry'; - content = 'point list'; -elseif filetype_check_extension(filename, '.s10') || filetype_check_extension(filename, '.s11') || filetype_check_extension(filename, '.s12') || filetype_check_extension(filename, '.s13') || filetype_check_extension(filename, '.s14') || filetype_check_extension(filename, '.s15') || filetype_check_extension(filename, '.s16') || filetype_check_extension(filename, '.s17') || filetype_check_extension(filename, '.s18') || filetype_check_extension(filename, '.s19') || filetype_check_extension(filename, '.s20') || filetype_check_extension(filename, '.s21') || filetype_check_extension(filename, '.s22') || filetype_check_extension(filename, '.s23') || filetype_check_extension(filename, '.s24') || filetype_check_extension(filename, '.s25') || filetype_check_extension(filename, '.s26') || filetype_check_extension(filename, '.s27') || filetype_check_extension(filename, '.s28') || filetype_check_extension(filename, '.s29') || filetype_check_extension(filename, '.s30') || filetype_check_extension(filename, '.s31') || filetype_check_extension(filename, '.s32') || filetype_check_extension(filename, '.s33') || filetype_check_extension(filename, '.s34') || filetype_check_extension(filename, '.s35') || filetype_check_extension(filename, '.s36') || filetype_check_extension(filename, '.s37') || filetype_check_extension(filename, '.s38') || filetype_check_extension(filename, '.s39') - ftype = 'curry_s'; - manufacturer = 'Curry'; - content = 'triangle or tetraedra list'; -elseif filetype_check_extension(filename, '.pom') - ftype = 'curry_pom'; - manufacturer = 'Curry'; - content = 'anatomical localization file'; -elseif filetype_check_extension(filename, '.res') - ftype = 'curry_res'; - manufacturer = 'Curry'; - content = 'functional localization file'; - - % known MBFYS file types -elseif filetype_check_extension(filename, '.tri') - ftype = 'mbfys_tri'; - manufacturer = 'MBFYS'; - content = 'triangulated surface'; -elseif filetype_check_extension(filename, '.ama') && filetype_check_header(filename, [0 0 0 10]) - ftype = 'mbfys_ama'; - manufacturer = 'MBFYS'; - content = 'BEM volume conduction model'; - - % Electrical Geodesics Incorporated format -elseif (filetype_check_extension(filename, '.egis') || filetype_check_extension(filename, '.ave') || filetype_check_extension(filename, '.gave') || filetype_check_extension(filename, '.raw')) && (filetype_check_header(filename, [char(1) char(2) char(3) char(4) char(255) char(255)]) || filetype_check_header(filename, [char(3) char(4) char(1) char(2) char(255) char(255)])) - ftype = 'egi_egia'; - manufacturer = 'Electrical Geodesics Incorporated'; - content = 'averaged EEG data'; -elseif (filetype_check_extension(filename, '.egis') || filetype_check_extension(filename, '.ses') || filetype_check_extension(filename, '.raw')) && (filetype_check_header(filename, [char(1) char(2) char(3) char(4) char(0) char(3)]) || filetype_check_header(filename, [char(3) char(4) char(1) char(2) char(0) char(3)])) - ftype = 'egi_egis'; - manufacturer = 'Electrical Geodesics Incorporated'; - content = 'raw EEG data'; -elseif (filetype_check_extension(filename, '.sbin') || filetype_check_extension(filename, '.raw')) - ftype = 'egi_sbin'; - manufacturer = 'Electrical Geodesics Incorporated'; - content = 'averaged EEG data'; - - - % some other known file types -elseif length(filename)>4 && exist([filename(1:(end-4)) '.mat'], 'file') && exist([filename(1:(end-4)) '.bin'], 'file') - % this is a self-defined FCDC data format, consisting of two files - % there is a matlab V6 file with the header and a binary file with the data (multiplexed, ieee-le, double) - ftype = 'fcdc_matbin'; - manufacturer = 'F.C. Donders Centre'; - content = 'multiplexed electrophysiology data'; -elseif filetype_check_extension(filename, '.lay') - ftype = 'layout'; - manufacturer = 'Ole Jensen'; - content = 'layout of channels for plotting'; -elseif filetype_check_extension(filename, '.dcm') || filetype_check_extension(filename, '.ima') - ftype = 'dicom'; - manufacturer = 'Dicom'; - content = 'image data'; -elseif filetype_check_extension(filename, '.trl') - ftype = 'fcdc_trl'; - manufacturer = 'F.C.Donders'; - content = 'trial definitions'; -elseif filetype_check_header(filename, [255 'BIOSEMI']) % filetype_check_extension(filename, '.bdf') - ftype = 'biosemi_bdf'; - % ftype = 'bham_bdf'; - manufacturer = 'Biosemi Data Format'; - content = 'electrophysiological data'; -elseif filetype_check_extension(filename, '.edf') - ftype = 'edf'; - manufacturer = 'European Data Format'; - content = 'electrophysiological data'; -elseif filetype_check_extension(filename, '.mat') && filetype_check_header(filename, 'MATLAB') - ftype = 'matlab'; - manufacturer = 'Matlab'; - content = 'Matlab binary data'; -elseif filetype_check_header(filename, 'RIFF', 0) && filetype_check_header(filename, 'WAVE', 8) - ftype = 'riff_wave'; - manufacturer = 'Microsoft'; - content = 'audio'; -elseif filetype_check_extension(filename, '.txt') - ftype = 'ascii_txt'; - manufacturer = ''; - content = ''; -elseif filetype_check_extension(filename, '.pol') - ftype = 'polhemus_fil'; - manufacturer = 'Functional Imaging Lab, London, UK'; - content = 'headshape points'; -elseif filetype_check_extension(filename, '.set') - ftype = 'eeglab_set'; - manufacturer = 'Swartz Center for Computational Neuroscience, San Diego, USA'; - content = 'electrophysiological data'; -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% finished determining the filetype -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -if strcmp(ftype, 'unknown') - warning(sprintf('could not determine filetype of %s', filename)); -end - -% remember the details -detail.filetype = ftype; -detail.manufacturer = manufacturer; -detail.content = content; - -if ~isempty(desired) - % return a boolean value instead of a descriptive string - ftype = strcmp(ftype, desired); -end - -% SUBFUNCTION that helps in deciding whether a directory with files should -% be treated as a "dataset". This function returns a logical 1 (TRUE) if more -% than half of the element of a vector are nonzero number or are logical 1 (TRUE). -function y = most(x); -x = x(find(~isnan(x(:)))); -y = sum(x==0)char'); - fclose(fid); - for i=1:length(head) - val = strncmp(str, head{i}, len(i)); - if val - break - end - end - else - [str, siz] = fread(fid, length(head), 'char=>char'); - fclose(fid); - if siz~=length(head) - error('could not read the header from the file'); - end - val = all(str(:)==head(:)); - end - end -end -return - diff --git a/external/forwinv/private/filetype_check_uri.m b/external/forwinv/private/filetype_check_uri.m deleted file mode 100644 index 78cc383..0000000 --- a/external/forwinv/private/filetype_check_uri.m +++ /dev/null @@ -1,197 +0,0 @@ -function varargout = filetype_check_uri(filename, ftyp) - -% FILETYPE_CHECK_URI -% -% Supported URIs are -% shm:// -% fifo:// -% buffer://: -% mysql://:@: -% rfb://@: -% serial:?key1=value1&key2=value2&... -% -% The URI schemes supproted by these function are not the official schemes. -% See the documentation included inside this function for more details. -% RFC4395 defines an IANA-maintained registry of URI Schemes. See also -% http://www.iana.org/assignments/uri-schemes.html and -% http://en.wikipedia.org/wiki/URI_scheme#Generic_syntax. - -% Copyright (C) 2007, Robert Oostenveld -% -% $Log: filetype_check_uri.m,v $ -% Revision 1.6 2008/02/19 10:07:34 roboos -% replaced tcpsocket with buffer -% -% Revision 1.5 2007/11/07 10:45:56 roboos -% made port optional for mysql -% -% Revision 1.4 2007/10/15 16:02:46 roboos -% added rfb://@: -% -% Revision 1.3 2007/07/27 12:18:50 roboos -% added ctf_shm -% -% Revision 1.2 2007/06/19 11:13:59 chrhes -% small change in how the serial port case is processed to allow for the -% possibility of no options being passed -% -% Revision 1.1 2007/06/06 07:10:36 roboos -% initial implementation -% - -sep = find(filename==':'); -if ~isempty(sep) - scheme = filename(1:(sep(1)-1)); -else - scheme = []; -end - -if nargin>1 - % only return true or false - varargout{1} = strcmp(scheme, ftyp); -else - % return the full details of this URI scheme - switch scheme - case 'shm' - % shm:// - % the filename is optional, usually it can and will be read from shared memory - if length(filename)>6 - varargout{1} = filename(7:end); - else - varargout{1} = []; - end - - case 'fifo' - % fifo:// - varargout{1} = filename(8:end); - - case 'buffer' - % buffer://: - tok = tokenize(filename(10:end), ':'); - varargout{1} = tok{1}; - varargout{2} = str2num(tok{2}); - - case 'rfb' - % rfb://@: - tok0 = tokenize(filename(7:end), '@'); - tok1 = tokenize(tok0{2}, ':'); - varargout{1} = tok0{1}; - varargout{2} = tok1{1}; - varargout{3} = str2num(tok1{2}); - - case 'mysql' - % mysql://:@: - tok0 = tokenize(filename(9:end), '@'); - tok1 = tokenize(tok0{1}, ':'); - tok2 = tokenize(tok0{2}, ':'); - varargout{1} = tok1{1}; - varargout{2} = tok1{2}; - varargout{3} = tok2{1}; - if length(tok2)>1 - varargout{4} = str2num(tok2{2}); - else - varargout{4} = []; - end - - case 'serial' - % serial:?key1=value1&key2=value2&... - % the supported optional arguments are - % BaudRate - % DataBits - % DataTerminalReady - % FlowControl - % Parity - % Port - % ReadAsyncMode - % RequestToSend - % StopBits - % Terminator - tok0 = tokenize(filename(8:end), '?'); - varargout{1} = tok0{1}; - varargout{2} = []; - if length(tok0)>1 - tok1 = tokenize(tok0{2}, '&'); - for i=1:length(tok1) - tok2 = tokenize(tok1{i}, '='); - opt{(i-1)*2+1} = tok2{1}; - opt{(i-1)*2+2} = tok2{2}; - end - varargout{2} = opt; - end - - - otherwise - error('unsupported scheme in URI') - end -end - -% RFC4395 defines an IANA-maintained registry of URI Schemes. -% see also http://www.iana.org/assignments/uri-schemes.html -% and http://en.wikipedia.org/wiki/URI_scheme#Generic_syntax -% -% Scheme Description Reference -% ------------------------------------------------------------- -% aaa Diameter Protocol [RFC3588] -% aaas Diameter Protocol with Secure Transport [RFC3588] -% acap application configuration access protocol [RFC2244] -% cap Calendar Access Protocol [RFC4324] -% cid content identifier [RFC2392] -% crid TV-Anytime Content Reference Identifier [RFC4078] -% data data [RFC2397] -% dav dav [RFC-ietf-webdav-rfc2518bis-18.txt] -% dict dictionary service protocol [RFC2229] -% dns Domain Name System [RFC4501] -% fax fax [RFC3966] -% file Host-specific file names [RFC1738] -% ftp File Transfer Protocol [RFC1738] -% go go [RFC3368] -% gopher The Gopher Protocol [RFC4266] -% h323 H.323 [RFC3508] -% http Hypertext Transfer Protocol [RFC2616] -% https Hypertext Transfer Protocol Secure [RFC2818] -% icap Internet Content Adaptation Protocol [RFC3507] -% im Instant Messaging [RFC3860] -% imap internet message access protocol [RFC2192] -% info Information Assets with Identifiers in Public Namespaces [RFC4452] -% ipp Internet Printing Protocol [RFC3510] -% iris Internet Registry Information Service [RFC3981] -% iris.beep iris.beep [RFC3983] -% iris.xpc iris.xpc [RFC-ietf-crisp-iris-xpc-06.txt] -% iris.xpcs iris.xpcs [RFC-ietf-crisp-iris-xpc-06.txt] -% iris.lwz iris.lwz [RFC-ietf-crisp-iris-lwz-08.txt] -% ldap Lightweight Directory Access Protocol [RFC4516] -% mailto Electronic mail address [RFC2368] -% mid message identifier [RFC2392] -% modem modem [RFC3966] -% msrp Message Session Relay Protocol [RFC-ietf-simple-message-sessions-19.txt] -% msrps Message Session Relay Protocol Secure [RFC-ietf-simple-message-sessions-19.txt] -% mtqp Message Tracking Query Protocol [RFC3887] -% mupdate Mailbox Update (MUPDATE) Protocol [RFC3656] -% news USENET news [RFC1738] -% nfs network file system protocol [RFC2224] -% nntp USENET news using NNTP access [RFC1738] -% opaquelocktoken opaquelocktokent [RFC-ietf-webdav-rfc2518bis-18.txt] -% pop Post Office Protocol v3 [RFC2384] -% pres Presence [RFC3859] -% rtsp real time streaming protocol [RFC2326] -% service service location [RFC2609] -% shttp Secure Hypertext Transfer Protocol [RFC2660] -% sip session initiation protocol [RFC3261] -% sips secure session initiation protocol [RFC3261] -% snmp Simple Network Management Protocol [RFC4088] -% soap.beep soap.beep [RFC3288] -% soap.beeps soap.beeps [RFC3288] -% tag tag [RFC4151] -% tel telephone [RFC3966] -% telnet Reference to interactive sessions [RFC4248] -% tftp Trivial File Transfer Protocol [RFC3617] -% thismessage multipart/related relative reference resolution [RFC2557] -% tip Transaction Internet Protocol [RFC2371] -% tv TV Broadcasts [RFC2838] -% urn Uniform Resource Names (click for registry) [RFC2141] -% vemmi versatile multimedia interface [RFC2122] -% xmlrpc.beep xmlrpc.beep [RFC3529] -% xmlrpc.beeps xmlrpc.beeps [RFC3529] -% xmpp Extensible Messaging and Presence Protocol [RFC4622] -% z39.50r Z39.50 Retrieval [RFC2056] -% z39.50s Z39.50 Session [RFC2056] diff --git a/external/forwinv/private/find_innermost_boundary.m b/external/forwinv/private/find_innermost_boundary.m deleted file mode 100644 index 9ab5a96..0000000 --- a/external/forwinv/private/find_innermost_boundary.m +++ /dev/null @@ -1,47 +0,0 @@ -function [innermost, inside] = find_innermost_boundary(bnd) - -% FIND_INNERMOST_BOUNDARY locates innermost compartment of a BEM model -% by looking at the containment of the triangular meshes describing -% the surface boundaries -% -% [innermost] = find_innermost_boundary(bnd) -% -% with the boundaries described by a struct array bnd with -% bnd(i).pnt vertices of boundary i (matrix of size Nx3) -% bnd(i).tri triangles of boundary i (matrix of size Mx3) - -% Copyright (C) 2003, Robert Oostenveld -% -% $Log: find_innermost_boundary.m,v $ -% Revision 1.3 2009/09/23 13:16:27 roboos -% also support single boundary -% -% Revision 1.2 2003/03/04 21:46:18 roberto -% added CVS log entry and synchronized all copyright labels -% - -ncmp = length(bnd); - -if ncmp==1 - innermost = 1; - return -end - -% try to locate the innermost compartment -for i=1:ncmp -for j=1:ncmp - % determine for a single vertex on each surface if it is inside or outside the other surfaces - curpos = bnd(i).pnt(1,:); % any point on the boundary is ok - curpnt = bnd(j).pnt; - curtri = bnd(j).tri; - if i==j - inside(i,j) = 0; - else - inside(i,j) = bounding_mesh(curpos, curpnt, curtri); - end -end -end -% assume that the sources are in the innermost compartment -tmp = sum(inside, 2); -[i, innermost] = max(tmp); - diff --git a/external/forwinv/private/find_inside_vol.m b/external/forwinv/private/find_inside_vol.m deleted file mode 100644 index b79600f..0000000 --- a/external/forwinv/private/find_inside_vol.m +++ /dev/null @@ -1,26 +0,0 @@ -function [inside, outside] = find_inside_vol(pos, vol); - -% FIND_INSIDE_VOL locates dipole locations inside/outside the source -% compartment of a volume conductor model. -% -% [inside, outside] = find_inside_vol(pos, vol) -% -% This function is obsolete and its use in other functions should be replaced -% by inside_vol - -% Copyright (C) 2003-2007, Robert Oostenveld -% -% $Log: find_inside_vol.m,v $ -% Revision 1.1 2009/01/21 10:32:38 roboos -% moved from forwinv/* and forwinv/mex/* directory to forwinv/private/* to make the CVS layout consistent with the release version -% -% Revision 1.8 2008/09/20 13:41:35 roboos -% moved content of find_inside_vol to new inside_vol function with slightly different interface -% added wrapper for spm -% - - -inside = inside_vol(pos, vol); -% replace boolean vector with indexing vectors -outside = find(~inside); -inside = find(inside); diff --git a/external/forwinv/private/find_outermost_boundary.m b/external/forwinv/private/find_outermost_boundary.m deleted file mode 100644 index 28f9f85..0000000 --- a/external/forwinv/private/find_outermost_boundary.m +++ /dev/null @@ -1,39 +0,0 @@ -function [outermost, inside] = find_outermost_boundary(bnd) - -% FIND_OUTERMOST_BOUNDARY locates outermost compartment of a BEM model -% by looking at the containment of the triangular meshes describing -% the surface boundaries -% -% [outermost] = find_innermost_boundary(bnd) -% -% with the boundaries described by a struct array bnd with -% bnd(i).pnt vertices of boundary i (matrix of size Nx3) -% bnd(i).tri triangles of boundary i (matrix of size Mx3) - -% Copyright (C) 2003, Robert Oostenveld -% -% $Log: find_outermost_boundary.m,v $ -% Revision 1.2 2003/03/04 21:46:18 roberto -% added CVS log entry and synchronized all copyright labels -% - -ncmp = length(bnd); - -% try to locate the outermost compartment -for i=1:ncmp -for j=1:ncmp - % determine for a single vertex on each surface if it is inside or outside the other surfaces - curpos = bnd(i).pnt(1,:); % any point on the boundary is ok - curpnt = bnd(j).pnt; - curtri = bnd(j).tri; - if i==j - inside(i,j) = 0; - else - inside(i,j) = bounding_mesh(curpos, curpnt, curtri); - end -end -end -% assume that the sources are in the innermost compartment -tmp = sum(inside, 2); -[i, outermost] = min(tmp); - diff --git a/external/forwinv/private/fitsphere.m b/external/forwinv/private/fitsphere.m deleted file mode 100644 index e6c6df1..0000000 --- a/external/forwinv/private/fitsphere.m +++ /dev/null @@ -1,92 +0,0 @@ -function [C,R] = fitsphere(pnt) - -% FITSPHERE fits the centre and radius of a sphere to a set of points -% using Taubin's method. -% -% Use as -% [center,radius] = fitsphere(pnt) -% where -% pnt = Nx3 matrix with the Carthesian coordinates of the surface points -% and -% center = the center of the fitted sphere -% radius = the radius of the fitted sphere - -% Copyright (C) 2009, Jean Daunizeau (for SPM) -% -% $Log: fitsphere.m,v $ -% Revision 1.5 2009/05/05 10:02:42 vlalit -% Typo fix -% -% Revision 1.4 2009/05/01 07:32:27 roboos -% added another solution for the flat surface fitting: now the norm is being used consistently -% -% Revision 1.3 2009/04/30 16:59:36 vlalit -% Bug fix for the problem of too flat mesh surfaces as suggested by Christophe -% -% Revision 1.2 2009/04/01 12:37:12 roboos -% updated documentation -% -% Revision 1.1 2009/04/01 12:16:14 roboos -% new function, see email from Guillaume Flandin from 23 March -% - -x = pnt(:,1); -y = pnt(:,2); -z = pnt(:,3); - -% Make sugary one and zero vectors -l = ones(length(x),1); -O = zeros(length(x),1); - -% Make design mx -D = [(x.*x + y.*y + z.*z) x y z l]; - -Dx = [2*x l O O O]; -Dy = [2*y O l O O]; -Dz = [2*z O O l O]; - -% Create scatter matrices -M = D'*D; -N = Dx'*Dx + Dy'*Dy + Dz'*Dz; - -% Extract eigensystem -[v, evalues] = eig(M); -evalues = diag(evalues); -Mrank = sum(evalues > eps*5*norm(M)); - -if (Mrank == 5) - % Full rank -- min ev corresponds to solution - % Minverse = v'*diag(1./evalues)*v; - [v,evalues] = eig(inv(M)*N); - [dmin,dminindex] = max(diag(evalues)); - pvec = v(:,dminindex(1))'; -else - % Rank deficient -- just extract nullspace of M - % pvec = null(M)'; % this does not work reliably because of inconsistent rank definition - pvec = v(:,evalues <= eps*5*norm(M))'; - [m,n] = size(pvec); - if m > 1 - pvec = pvec(1,:); - end -end - -if isempty(pvec) - warning('was not able to fit a sphere to the surface points'); - C = [NaN NaN NaN]; - R = Inf; -else - % Convert to (R,C) - C = -0.5*pvec(2:4) / pvec(1); - R = sqrt(sum(C*C') - pvec(5)/pvec(1)); -end - - -% if nargout == 1, -% if pvec(1) < 0 -% pvec = -pvec; -% end -% C = pvec; -% else -% C = -0.5*pvec(2:4) / pvec(1); -% R = sqrt(sum(C*C') - pvec(5)/pvec(1)); -% end diff --git a/external/forwinv/private/fixdipole.m b/external/forwinv/private/fixdipole.m deleted file mode 100644 index 8a9de8c..0000000 --- a/external/forwinv/private/fixdipole.m +++ /dev/null @@ -1,39 +0,0 @@ -function dip = fixdipole(dip) - -% FIXDIPOLE ensures that the dipole position and moment are -% consistently represented throughout FieldTrip functions. - -% Copyright (C) 2009, Robert Oostenveld -% -% $Log: fixdipole.m,v $ -% Revision 1.1 2009/07/02 15:35:55 roboos -% helper function for consistent dipole representation -% - -[m, n] = size(dip.pos); - -if n==3 - % the input representation is Nx3, which is what we want -elseif m==3 - % it is possible to translate it into a Nx3 unambiguously - warning('input dipole positions should be specified as Nx3 matrix'); - dip.pos = dip.pos'; -elseif m==1 - % it is possible to translate it into a Nx3 unambiguously - warning('input dipole positions should be specified as Nx3 matrix'); - dip.pos = reshape(dip.pos, 3, n/3)'; -else - % it is not clear how to convert to a Nx3 matrix - error('input dipole positions should be specified as Nx3 matrix'); -end - -if isfield(dip, 'mom') - ndip = size(dip.pos,1); - if numel(dip.mom)==ndip*3 - ntime = 1; - else - ntime = numel(dip.mom)/(ndip*3); - end - dip.mom = reshape(dip.mom, ndip*3, ntime); -end - diff --git a/external/forwinv/private/getsubfield.m b/external/forwinv/private/getsubfield.m deleted file mode 100644 index b376a50..0000000 --- a/external/forwinv/private/getsubfield.m +++ /dev/null @@ -1,35 +0,0 @@ -function [s] = getsubfield(s, f); - -% GETSUBFIELD returns a field from a structure just like the standard -% Matlab GETFIELD function, except that you can also specify nested fields -% using a '.' in the fieldname. The nesting can be arbitrary deep. -% -% Use as -% f = getsubfield(s, 'fieldname') -% or as -% f = getsubfield(s, 'fieldname.subfieldname') -% -% See also GETFIELD, ISSUBFIELD, SETSUBFIELD - -% Copyright (C) 2005, Robert Oostenveld -% -% $Log: getsubfield.m,v $ -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.1 2005/02/08 09:30:18 roboos -% new implementations to make it easier to work with nested structures -% - -if ~isstr(f) - error('incorrect input argument for fieldname'); -end - -t = {}; -while (1) - [t{end+1}, f] = strtok(f, '.'); - if isempty(f) - break - end -end -s = getfield(s, t{:}); diff --git a/external/forwinv/private/hastoolbox.m b/external/forwinv/private/hastoolbox.m deleted file mode 100644 index a4ca969..0000000 --- a/external/forwinv/private/hastoolbox.m +++ /dev/null @@ -1,408 +0,0 @@ -function [status] = hastoolbox(toolbox, autoadd, silent) - -% HASTOOLBOX tests whether an external toolbox is installed. Optionally -% it will try to determine the path to the toolbox and install it -% automatically. -% -% Use as -% [status] = hastoolbox(toolbox, autoadd, silent) - -% Copyright (C) 2005-2008, Robert Oostenveld -% -% $Log: hastoolbox.m,v $ -% Revision 1.37 2009/10/13 10:11:06 roboos -% added lc-libs -% -% Revision 1.36 2009/09/08 14:34:01 roboos -% also detect 64 bit windows version (thanks to arno) -% -% Revision 1.35 2009/04/21 09:54:15 roboos -% added prtools -% -% Revision 1.34 2009/04/02 19:47:33 roboos -% added plotting module -% -% Revision 1.33 2009/03/30 15:06:14 roboos -% added the patch from Alexandre to support openmeeg -% -% Revision 1.32 2009/03/12 10:40:21 roboos -% added the splines toolbox (mainly for testing) and changed the warning message related to the license -% -% Revision 1.31 2009/03/12 10:33:35 roboos -% not only check that a function is available, also check whether a license for that function is available -% -% Revision 1.30 2009/03/11 21:26:27 roboos -% detect spm8b just as spm8 -% -% Revision 1.29 2009/03/11 10:35:19 roboos -% spm detection was confused with function and directory, explicitely check for "spm.m" which is the function -% -% Revision 1.28 2009/03/11 08:49:04 roboos -% improved the detection of the various spm versions -% -% Revision 1.27 2009/02/11 11:03:08 roboos -% changed naming of the functions of Chris in accordance with SPM8 -% -% Revision 1.26 2009/02/02 12:57:21 roboos -% added bemcp, image, tcp_udp_ip -% -% Revision 1.25 2009/01/19 15:02:21 roboos -% added mne for fiff access -% -% Revision 1.24 2009/01/08 17:00:02 roboos -% improved caching in case the toolbox is not present -% -% Revision 1.23 2008/12/24 09:10:46 roboos -% added dipoli -% -% Revision 1.22 2008/10/29 15:45:12 roboos -% fix dashes and spaces in directory names for caching -% -% Revision 1.21 2008/10/20 21:50:56 roboos -% added NlxNetCom -% -% Revision 1.20 2008/10/20 16:31:15 roboos -% fixed problem in case with dash "-" in the directory -% -% Revision 1.19 2008/09/29 09:00:19 roboos -% implemented smart handling of previously seen toolboxes using a persistent variable -% this should speed up fieldtrip and fileio (e.g. read_data checks the presence of ctf for every trial) -% -% Revision 1.18 2008/09/24 15:43:00 roboos -% added read_data and read_sens for fileio, should solve problem for MEEGfileio in spm5 -% -% Revision 1.17 2008/09/22 19:42:09 roboos -% added option for silent processing -% -% Revision 1.16 2008/08/11 16:11:19 roboos -% also automatically add to path for fieldtrip code and external modules -% -% Revision 1.15 2008/06/20 07:25:56 roboos -% added check for presence of BCI2000 load_bcidat mex file -% -% Revision 1.14 2008/05/15 10:52:29 roboos -% added ctf -% -% Revision 1.13 2008/03/17 08:29:40 roboos -% changed some contact addresses -% -% Revision 1.12 2008/03/14 10:20:29 roboos -% added denoise -% -% Revision 1.11 2008/03/05 10:59:14 roboos -% added fileio and forwinv -% -% Revision 1.10 2007/05/06 09:10:07 roboos -% added spm5 -% -% Revision 1.9 2007/02/26 13:41:07 roboos -% made small change to fastica detection (suggested by Sameer) -% -% Revision 1.8 2007/02/13 17:22:27 roboos -% added MRI from eeg.sf.net -% -% Revision 1.7 2007/02/13 14:01:26 roboos -% added brainstorm -% -% Revision 1.6 2007/02/12 19:43:23 roboos -% added fastica, optim -% -% Revision 1.5 2007/01/17 17:05:34 roboos -% added matlab signal processing toolbox -% -% Revision 1.4 2007/01/04 12:25:19 roboos -% added SON2 -% -% Revision 1.3 2007/01/03 17:01:15 roboos -% added 4d-version toolbox -% -% Revision 1.2 2006/06/07 10:48:02 roboos -% changed the "see xxx" string -% -% Revision 1.1 2006/06/07 09:28:41 roboos -% renamed fieldtrip/private/checktoolbox into misc/hastoolbox -% -% Revision 1.8 2006/06/06 14:18:22 roboos -% added neuroshare, eeprobe, yokogawa -% -% Revision 1.7 2006/05/31 08:56:24 roboos -% implemented detection of toolbox in users ~/matlab/toolboxname -% -% Revision 1.6 2006/05/23 10:20:46 roboos -% added beowulf and mentat toolboxes -% -% Revision 1.5 2006/04/26 11:37:22 roboos -% added besa toolbox -% -% Revision 1.4 2006/02/07 20:01:39 roboos -% aded biosig and meg-pd (neuromag) -% -% Revision 1.3 2006/01/17 14:05:54 roboos -% added GLNA64 for mentat000 -% -% Revision 1.2 2006/01/06 11:39:23 roboos -% added copyrigth and cvs logging, changed some comments -% - -% this function is called many times in FieldTrip and associated toolboxes -% use efficient handling if the same toolbox has been investigated before -persistent previous -if isempty(previous) - previous = struct; -elseif isfield(previous, fixname(toolbox)) - status = previous.(fixname(toolbox)); - return -end - -% this points the user to the website where he/she can download the toolbox -url = { - 'AFNI' 'see http://afni.nimh.nih.gov' - 'DSS' 'see http://www.cis.hut.fi/projects/dss' - 'EEGLAB' 'see http://www.sccn.ucsd.edu/eeglab' - 'NWAY' 'see http://www.models.kvl.dk/source/nwaytoolbox' - 'SPM99' 'see http://www.fil.ion.ucl.ac.uk/spm' - 'SPM2' 'see http://www.fil.ion.ucl.ac.uk/spm' - 'SPM5' 'see http://www.fil.ion.ucl.ac.uk/spm' - 'SPM8' 'see http://www.fil.ion.ucl.ac.uk/spm' - 'MEG-PD' 'see http://www.kolumbus.fi/kuutela/programs/meg-pd' - 'MEG-CALC' 'this is a commercial toolbox from Neuromag, see http://www.neuromag.com' - 'BIOSIG' 'see http://biosig.sourceforge.net' - 'EEG' 'see http://eeg.sourceforge.net' - 'EEGSF' 'see http://eeg.sourceforge.net' % alternative name - 'MRI' 'see http://eeg.sourceforge.net' % alternative name - 'NEUROSHARE' 'see http://www.neuroshare.org' - 'BESA' 'see http://www.megis.de, or contact Karsten Hoechstetter' - 'EEPROBE' 'see http://www.ant-neuro.com, or contact Maarten van der Velde' - 'YOKOGAWA' 'see http://www.yokogawa.co.jp, or contact Nobuhiko Takahashi' - 'BEOWULF' 'see http://oostenveld.net, or contact Robert Oostenveld' - 'MENTAT' 'see http://oostenveld.net, or contact Robert Oostenveld' - 'SON2' 'see http://www.kcl.ac.uk/depsta/biomedical/cfnr/lidierth.html, or contact Malcolm Lidierth' - '4D-VERSION' 'contact Christian Wienbruch' - 'SIGNAL' 'see http://www.mathworks.com/products/signal' - 'OPTIM' 'see http://www.mathworks.com/products/optim' - 'IMAGE' 'see http://www.mathworks.com/products/image' - 'SPLINES' 'see http://www.mathworks.com/products/splines' - 'FASTICA' 'see http://www.cis.hut.fi/projects/ica/fastica' - 'BRAINSTORM' 'see http://neuroimage.ucs.edu/brainstorm' - 'FILEIO' 'see http://www.ru.nl/neuroimaging/fieldtrip' - 'FORWINV' 'see http://www.ru.nl/neuroimaging/fieldtrip' - 'PLOTTING' 'see http://www.ru.nl/neuroimaging/fieldtrip' - 'DENOISE' 'see http://lumiere.ens.fr/Audition/adc/meg, or contact Alain de Cheveigne' - 'BCI2000' 'see http://bci2000.org' - 'NLXNETCOM' 'see http://www.neuralynx.com' - 'DIPOLI' 'see ftp://ftp.fcdonders.nl/pub/fieldtrip/external' - 'MNE' 'see http://www.nmr.mgh.harvard.edu/martinos/userInfo/data/sofMNE.php' - 'TCP_UDP_IP' 'see http://www.mathworks.com/matlabcentral/fileexchange/345, or contact Peter Rydes?ter' - 'BEMCP' 'contact Christophe Phillips' - 'OPENMEEG' 'see http://gforge.inria.fr/projects/openmeeg' - 'PRTOOLS' 'see http://www.prtools.org' - 'LC-LIBS' 'contact Stefania Della Penna' - }; - -if nargin<2 - % default is not to add the path automatically - autoadd = 0; -end - -if nargin<3 - % default is not to be silent - silent = 0; -end - -% determine whether the toolbox is installed -toolbox = upper(toolbox); -switch toolbox - case 'AFNI' - status = (exist('BrikLoad') && exist('BrikInfo')); - case 'DSS' - status = exist('dss', 'file') && exist('dss_create_state', 'file'); - case 'EEGLAB' - status = exist('runica', 'file'); - case 'NWAY' - status = exist('parafac', 'file'); - case 'SPM99' - status = exist('spm.m') && strcmp(spm('ver'),'SPM99'); - case 'SPM2' - status = exist('spm.m') && strcmp(spm('ver'),'SPM2'); - case 'SPM5' - status = exist('spm.m') && strcmp(spm('ver'),'SPM5'); - case 'SPM8' - status = exist('spm.m') && strncmp(spm('ver'),'SPM8', 3); - case 'MEG-PD' - status = (exist('rawdata') && exist('channames')); - case 'MEG-CALC' - status = (exist('megmodel') && exist('megfield') && exist('megtrans')); - case 'BIOSIG' - status = (exist('sopen') && exist('sread')); - case 'EEG' - status = (exist('ctf_read_res4') && exist('ctf_read_meg4')); - case 'EEGSF' % alternative name - status = (exist('ctf_read_res4') && exist('ctf_read_meg4')); - case 'MRI' % other functions in the mri section - status = (exist('avw_hdr_read') && exist('avw_img_read')); - case 'NEUROSHARE' - status = (exist('ns_OpenFile') && exist('ns_SetLibrary') && exist('ns_GetAnalogData')); - case 'BESA' - status = (exist('readBESAtfc') && exist('readBESAswf')); - case 'EEPROBE' - status = (exist('read_eep_avr') && exist('read_eep_cnt')); - case 'YOKOGAWA' - status = (exist('GetMeg160ChannelInfoM') && exist('GetMeg160ContinuousRawDataM')); - case 'BEOWULF' - status = (exist('evalwulf') && exist('evalwulf') && exist('evalwulf')); - case 'MENTAT' - status = (exist('pcompile') && exist('pfor') && exist('peval')); - case 'SON2' - status = (exist('SONFileHeader') && exist('SONChanList') && exist('SONGetChannel')); - case '4D-VERSION' - status = (exist('read4d') && exist('read4dhdr')); - case 'SIGNAL' - status = hasfunction('medfilt1', toolbox); % also check the availability of a toolbox license - case 'OPTIM' - status = hasfunction('fmincon', toolbox) && hasfunction('fminunc', toolbox); % also check the availability of a toolbox license - case 'SPLINES' - status = hasfunction('bspline', toolbox) && hasfunction('csape', toolbox); % also check the availability of a toolbox license - case 'IMAGE' - status = hasfunction('bwlabeln', toolbox); % also check the availability of a toolbox license - case 'FASTICA' - status = exist('fastica', 'file'); - case 'BRAINSTORM' - status = exist('bem_xfer'); - case 'FILEIO' - status = (exist('read_header') && exist('read_data') && exist('read_event') && exist('read_sens')); - case 'FORWINV' - status = (exist('compute_leadfield') && exist('prepare_vol_sens')); - case 'DENOISE' - status = (exist('tsr') && exist('sns')); - case 'CTF' - status = (exist('getCTFBalanceCoefs') && exist('getCTFdata')); - case 'BCI2000' - status = exist('load_bcidat'); - case 'NLXNETCOM' - status = (exist('MatlabNetComClient') && exist('NlxConnectToServer') && exist('NlxGetNewCSCData')); - case 'DIPOLI' - status = exist('dipoli.m', 'file'); - case 'MNE' - status = (exist('fiff_read_meas_info', 'file') && exist('fiff_setup_read_raw', 'file')); - case 'TCP_UDP_IP' - status = (exist('pnet', 'file') && exist('pnet_getvar', 'file') && exist('pnet_putvar', 'file')); - case 'BEMCP' - status = (exist('bem_Cij_cog', 'file') && exist('bem_Cij_lin', 'file') && exist('bem_Cij_cst', 'file')); - case 'OPENMEEG' - status = exist('openmeeg.m', 'file'); - case 'PLOTTING' - status = (exist('plot_topo', 'file') && exist('plot_mesh', 'file') && exist('plot_matrix', 'file')); - case 'PRTOOLS' - status = (exist('prversion', 'file') && exist('dataset', 'file') && exist('svc', 'file')); - case 'LC-LIBS' - status = (exist('lcReadHeader', 'file') && exist('lcReadData', 'file')); - otherwise - if ~silent, warning(sprintf('cannot determine whether the %s toolbox is present', toolbox)); end - status = 0; -end - -% it should be a boolean value -status = (status~=0); - -% try to determine the path of the requested toolbox -if autoadd && ~status - - % for core fieldtrip modules - prefix = fileparts(which('preprocessing')); - if ~status - status = myaddpath(fullfile(prefix, lower(toolbox)), silent); - end - - % for external fieldtrip modules - prefix = fullfile(fileparts(which('preprocessing')), 'external'); - if ~status - status = myaddpath(fullfile(prefix, lower(toolbox)), silent); - end - - % for linux computers in the F.C. Donders Centre - prefix = '/home/common/matlab'; - if ~status && (strcmp(computer, 'GLNX86') || strcmp(computer, 'GLNXA64')) - status = myaddpath(fullfile(prefix, lower(toolbox)), silent); - end - - % for windows computers in the F.C. Donders Centre - prefix = 'h:\common\matlab'; - if ~status && (strcmp(computer, 'PCWIN') || strcmp(computer, 'PCWIN64')) - status = myaddpath(fullfile(prefix, lower(toolbox)), silent); - end - - % use the matlab subdirectory in your homedirectory, this works on unix and mac - prefix = [getenv('HOME') '/matlab']; - if ~status - status = myaddpath(fullfile(prefix, lower(toolbox)), silent); - end - - if ~status - % the toolbox is not on the path and cannot be added - sel = find(strcmp(url(:,1), toolbox)); - if ~isempty(sel) - msg = sprintf('the %s toolbox is not installed, %s', toolbox, url{sel, 2}); - else - msg = sprintf('the %s toolbox is not installed', toolbox); - end - error(msg); - end -end - -% this function is called many times in FieldTrip and associated toolboxes -% use efficient handling if the same toolbox has been investigated before -if status - previous.(fixname(toolbox)) = status; -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% helper function -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function status = myaddpath(toolbox, silent) -if exist(toolbox, 'dir') - if ~silent, warning(sprintf('adding %s toolbox to your Matlab path', toolbox)); end - addpath(toolbox); - status = 1; -else - status = 0; -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% helper function -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function out = fixname(toolbox) -out = lower(toolbox); -out(out=='-') = '_'; % fix dashes -out(out==' ') = '_'; % fix spaces - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% helper function -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function status = hasfunction(funname, toolbox) -try - % call the function without any input arguments, which probably is inapropriate - feval(funname); - % it might be that the function without any input already works fine - status = true; -catch - % either the function returned an error, or the function is not available - % availability is influenced by the function being present and by having a - % license for the function, i.e. in a concurrent licensing setting it might - % be that all toolbox licenses are in use - m = lasterror; - if strcmp(m.identifier, 'MATLAB:license:checkouterror') - if nargin>1 - warning('the %s toolbox is available, but you don''t have a license for it', toolbox); - else - warning('the function ''%s'' is available, but you don''t have a license for it', funname); - end - status = false; - elseif strcmp(m.identifier, 'MATLAB:UndefinedFunction') - status = false; - else - % the function seems to be available and it gave an unknown error, - % which is to be expected with inappropriate input arguments - status = true; - end -end - diff --git a/external/forwinv/private/headsurface.m b/external/forwinv/private/headsurface.m deleted file mode 100644 index 29bba2c..0000000 --- a/external/forwinv/private/headsurface.m +++ /dev/null @@ -1,231 +0,0 @@ -function [pnt, tri] = headsurface(vol, sens, varargin); - -% HEADSURFACE constructs a triangulated description of the skin or brain -% surface from a volume conduction model, from a set of electrodes or -% gradiometers, or from a combination of the two. It returns a closed -% surface. -% -% Use as -% [pnt, tri] = headsurface(vol, sens, ...) -% where -% vol volume conduction model (structure) -% sens electrode or gradiometer array (structure) -% -% Optional arguments should be specified in key-value pairs: -% surface = 'skin' or 'brain' (default = 'skin') -% npnt = number of vertices (default is determined automatic) -% downwardshift = boolean, this will shift the lower rim of the helmet down with approximately 1/4th of its radius (default is 1) -% inwardshift = number (default = 0) -% headshape = string, file containing the head shape - -% Copyright (C) 2005-2006, Robert Oostenveld -% -% $Log: headsurface.m,v $ -% Revision 1.6 2007/05/16 12:02:57 roboos -% use a new subfunction for determining the surface orientation -% -% Revision 1.5 2007/05/08 07:35:24 roboos -% try to automatically correct the surface orientation -% -% Revision 1.4 2007/02/13 15:39:02 roboos -% fixed bug in inwardshift, it should be subtracted instead of added (the bug was causing an outwardshift for megrealign) -% -% Revision 1.3 2006/12/12 11:29:29 roboos -% moved projecttri subfunction into seperate function -% be flexible with headsurfaces specified as structure or filename/string -% -% Revision 1.2 2006/07/24 08:23:49 roboos -% removed default for inwardshift, apply inwardshift irrespective of surface type, improved documentation, some other small changes -% -% Revision 1.1 2005/12/13 16:28:34 roboos -% new implementation, should replace the head_surf function -% - -if nargin<1 - vol = []; -end - -if nargin<2 - sens = []; -end - -if nargin<3 - varargin = {}; -end - -% parse the optional input arguments -surface = keyval('surface', varargin); % skin or brain -downwardshift = keyval('downwardshift', varargin); % boolean (0 or 1) -inwardshift = keyval('inwardshift', varargin); % number -headshape = keyval('headshape', varargin); % CTF *.shape file -npnt = keyval('npnt', varargin); % number of vertices - -% set the defaults if neccessary -if isempty(surface), surface = 'skin'; end -if isempty(downwardshift), downwardshift = 1; end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if ~isempty(headshape) - if ischar(headshape) - % read the head surface from file - hs = read_ctf_shape(headshape); - pnt = hs.pnt; - tri = projecttri(pnt); - elseif isstruct(headshape) - pnt = headshape.pnt; - if isfield(headshape, 'tri') - tri = headshape.tri; - else - tri = projecttri(pnt); - end - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif ~isempty(vol) && isfield(vol, 'r') && length(vol.r)<5 - if length(vol.r)==1 - % single sphere model, cannot distinguish between skin and/or brain - radius = vol.r; - if isfield(vol, 'o') - origin = vol.o; - else - origin = [0 0 0]; - end - elseif length(vol.r)<5 - % multiple concentric sphere model - switch surface - case 'skin' - % using outermost sphere - radius = max(vol.r); - case 'brain' - % using innermost sphere - radius = min(vol.r); - otherwise - error('other surfaces cannot be constructed this way'); - end - if isfield(vol, 'o') - origin = vol.o; - else - origin = [0 0 0]; - end - end - % this requires a specification of the number of vertices - if isempty(npnt) - npnt = 642; - end - % construct an evenly tesselated unit sphere - switch npnt - case 2562 - [pnt, tri] = icosahedron2562; - case 642 - [pnt, tri] = icosahedron642; - case 162 - [pnt, tri] = icosahedron162; - case 42 - [pnt, tri] = icosahedron42; - case 12 - [pnt, tri] = icosahedron; - otherwise - [pnt, tri] = ksphere(npnt); - end - % scale and translate the vertices - pnt = pnt*radius; - pnt(:,1) = pnt(:,1) + origin(1); - pnt(:,2) = pnt(:,2) + origin(2); - pnt(:,3) = pnt(:,3) + origin(3); - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif ~isempty(vol) && isfield(vol, 'r') && length(vol.r)>=5 - % local spheres MEG model, this also requires a gradiometer structure - grad = sens; - if ~isfield(grad, 'tra') || ~isfield(grad, 'pnt') - error('incorrect specification for the gradiometer array'); - end - Nchans = size(grad.tra, 1); - Ncoils = size(grad.tra, 2); - Nspheres = size(vol.o, 1); - if Nspheres~=Ncoils - error('there should be just as many spheres as coils'); - end - % for each coil, determine a surface point using the corresponding sphere - vec = grad.pnt - vol.o; - nrm = sqrt(sum(vec.^2,2)); - vec = vec ./ [nrm nrm nrm]; - pnt = vol.o + vec .* [vol.r vol.r vol.r]; - % make a triangularization that is needed to find the rim of the helmet - prj = elproj(pnt); - tri = delaunay(prj(:,1),prj(:,2)); - % find the lower rim of the helmet shape - [pnt,line] = find_mesh_edge(pnt, tri); - edgeind = unique(line(:)); - % shift the lower rim of the helmet shape down with approximately 1/4th of its radius - if downwardshift - dist = mean(sqrt(sum((pnt - repmat(mean(pnt,1), Ncoils, 1)).^2, 2))); - dist = dist/4; - pnt(edgeind,3) = pnt(edgeind,3) - dist; - end - % construct the triangulation of the surface - tri = projecttri(pnt); - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -elseif ~isempty(vol) && isfield(vol, 'bnd') - % boundary element model - switch surface - case 'skin' - if ~isfield(vol, 'skin') - vol.skin = find_outermost_boundary(vol.bnd); - end - pnt = vol.bnd(vol.skin).pnt; - tri = vol.bnd(vol.skin).tri; - case 'brain' - if ~isfield(vol, 'source') - vol.source = find_innermost_boundary(vol.bnd); - end - pnt = vol.bnd(vol.source).pnt; - tri = vol.bnd(vol.source).tri; - otherwise - error('other surfaces cannot be constructed this way'); - end -end - -% retriangulate the skin/brain/cortex surface to the desired number of vertices -if ~isempty(npnt) && size(pnt,1)~=npnt - switch npnt - case 2562 - [pnt2, tri2] = icosahedron2562; - case 642 - [pnt2, tri2] = icosahedron642; - case 162 - [pnt2, tri2] = icosahedron162; - case 42 - [pnt2, tri2] = icosahedron42; - case 12 - [pnt2, tri2] = icosahedron; - otherwise - [pnt2, tri2] = ksphere(npnt); - end - [pnt, tri] = retriangulate(pnt, tri, pnt2, tri2, 2); -end - -% shift the surface inward with a certain amount -if ~isempty(inwardshift) && inwardshift~=0 - ori = normals(pnt, tri, 'vertex'); - tmp = surfaceorientation(pnt, tri, ori); - % the orientation of the normals should be pointing to the outside of the surface - if tmp==1 - % the normals are outward oriented - % nothing to do - elseif tmp==-1 - % the normals are inward oriented - warning('the normals of the surface triangulation are inward oriented'); - tri = tri(:, [3 2 1]); - ori = -ori; - else - warning('cannot determine the orientation of the vertex normals'); - % nothing to do - end - % the orientation is outward, hence shift with a negative amount - pnt = pnt - inwardshift * ori; -end - - -return diff --git a/external/forwinv/private/icosahedron.m b/external/forwinv/private/icosahedron.m deleted file mode 100644 index 659d82a..0000000 --- a/external/forwinv/private/icosahedron.m +++ /dev/null @@ -1,62 +0,0 @@ -function [pnt, dhk] = icosahedron(); - -% ICOSAHEDRON creates an icosahedron -% -% [pnt, dhk] = icosahedron -% creates an icosahedron with 12 vertices and 20 triangles -% -% See also OCTAHEDRON, ICOSAHEDRON42, ICOSAHEDRON162, ICOSAHEDRON642, ICOSAHEDRON2562 - -% Copyright (C) 2002, Robert Oostenveld -% -% $Log: icosahedron.m,v $ -% Revision 1.4 2006/07/26 11:03:38 roboos -% added "see also octahedron" -% -% Revision 1.3 2003/03/11 15:35:20 roberto -% converted all files from DOS to UNIX -% -% Revision 1.2 2003/03/04 21:46:18 roberto -% added CVS log entry and synchronized all copyright labels -% - -dhk = [ - 1 2 3 - 1 3 4 - 1 4 5 - 1 5 6 - 1 6 2 - 2 8 3 - 3 9 4 - 4 10 5 - 5 11 6 - 6 7 2 - 7 8 2 - 8 9 3 - 9 10 4 - 10 11 5 - 11 7 6 - 12 8 7 - 12 9 8 - 12 10 9 - 12 11 10 - 12 7 11 -]; - -pnt = zeros(12, 3); - -rho=0.4*sqrt(5); -phi=2*pi*(0:4)/5; - -pnt( 1, :) = [0 0 1]; % top point - -pnt(2:6, 1) = rho*cos(phi)'; -pnt(2:6, 2) = rho*sin(phi)'; -pnt(2:6, 3) = rho/2; - -pnt(7:11, 1) = rho*cos(phi - pi/5)'; -pnt(7:11, 2) = rho*sin(phi - pi/5)'; -pnt(7:11, 3) = -rho/2; - -pnt(12, :) = [0 0 -1]; % bottom point - diff --git a/external/forwinv/private/icosahedron162.m b/external/forwinv/private/icosahedron162.m deleted file mode 100644 index 45131cc..0000000 --- a/external/forwinv/private/icosahedron162.m +++ /dev/null @@ -1,19 +0,0 @@ -function [pnt, dhk] = icosahedron(); - -% ICOSAHEDRON162 creates a 2-fold refined icosahedron - -% Copyright (C) 2003, Robert Oostenveld -% -% $Log: icosahedron162.m,v $ -% Revision 1.3 2003/11/28 09:40:12 roberto -% added a single help line -% -% Revision 1.2 2003/03/04 21:46:18 roberto -% added CVS log entry and synchronized all copyright labels -% - -[pnt, dhk] = icosahedron; -[pnt, dhk] = refine(pnt, dhk); -[pnt, dhk] = refine(pnt, dhk); - -pnt = pnt ./ repmat(sqrt(sum(pnt.^2,2)), 1,3); diff --git a/external/forwinv/private/icosahedron2562.m b/external/forwinv/private/icosahedron2562.m deleted file mode 100644 index d9d2a1a..0000000 --- a/external/forwinv/private/icosahedron2562.m +++ /dev/null @@ -1,21 +0,0 @@ -function [pnt, dhk] = icosahedron(); - -% ICOSAHEDRON2562 creates a 4-fold refined icosahedron - -% Copyright (C) 2003, Robert Oostenveld -% -% $Log: icosahedron2562.m,v $ -% Revision 1.3 2003/11/28 09:40:12 roberto -% added a single help line -% -% Revision 1.2 2003/03/04 21:46:18 roberto -% added CVS log entry and synchronized all copyright labels -% - -[pnt, dhk] = icosahedron; -[pnt, dhk] = refine(pnt, dhk); -[pnt, dhk] = refine(pnt, dhk); -[pnt, dhk] = refine(pnt, dhk); -[pnt, dhk] = refine(pnt, dhk); - -pnt = pnt ./ repmat(sqrt(sum(pnt.^2,2)), 1,3); diff --git a/external/forwinv/private/icosahedron42.m b/external/forwinv/private/icosahedron42.m deleted file mode 100644 index 5af6f07..0000000 --- a/external/forwinv/private/icosahedron42.m +++ /dev/null @@ -1,18 +0,0 @@ -function [pnt, dhk] = icosahedron(); - -% ICOSAHEDRON42 creates a 1-fold refined icosahedron - -% Copyright (C) 2003, Robert Oostenveld -% -% $Log: icosahedron42.m,v $ -% Revision 1.3 2003/11/28 09:40:12 roberto -% added a single help line -% -% Revision 1.2 2003/03/04 21:46:18 roberto -% added CVS log entry and synchronized all copyright labels -% - -[pnt, dhk] = icosahedron; -[pnt, dhk] = refine(pnt, dhk); - -pnt = pnt ./ repmat(sqrt(sum(pnt.^2,2)), 1,3); diff --git a/external/forwinv/private/icosahedron642.m b/external/forwinv/private/icosahedron642.m deleted file mode 100644 index 2a053fa..0000000 --- a/external/forwinv/private/icosahedron642.m +++ /dev/null @@ -1,20 +0,0 @@ -function [pnt, dhk] = icosahedron(); - -% ICOSAHEDRON642 creates a 3-fold refined icosahedron - -% Copyright (C) 2003, Robert Oostenveld -% -% $Log: icosahedron642.m,v $ -% Revision 1.3 2003/11/28 09:40:12 roberto -% added a single help line -% -% Revision 1.2 2003/03/04 21:46:19 roberto -% added CVS log entry and synchronized all copyright labels -% - -[pnt, dhk] = icosahedron; -[pnt, dhk] = refine(pnt, dhk); -[pnt, dhk] = refine(pnt, dhk); -[pnt, dhk] = refine(pnt, dhk); - -pnt = pnt ./ repmat(sqrt(sum(pnt.^2,2)), 1,3); diff --git a/external/forwinv/private/inf_medium_leadfield.m b/external/forwinv/private/inf_medium_leadfield.m deleted file mode 100644 index 385276d..0000000 --- a/external/forwinv/private/inf_medium_leadfield.m +++ /dev/null @@ -1,57 +0,0 @@ -function [lf] = inf_medium_leadfield(rd, pnt, cond); - -% INF_MEDIUM_LEADFIELD calculate the infinite medium leadfield -% on positions pnt for dipole position R and conductivity cond -% -% [lf] = inf_medium_leadfield(R, pnt, cond) - -% Copyright (C) 1998, Robert Oostenveld -% -% $Log: inf_medium_leadfield.m,v $ -% Revision 1.1 2009/01/21 10:32:38 roboos -% moved from forwinv/* and forwinv/mex/* directory to forwinv/private/* to make the CVS layout consistent with the release version -% -% Revision 1.5 2005/02/23 14:31:19 roboos -% changed the detection of Ndipoles, added reshaping of Nx3 input -% -% Revision 1.4 2003/08/04 09:12:32 roberto -% added check for dipole on BEM model boundary, gives warning message -% -% Revision 1.3 2003/06/03 08:29:26 roberto -% fixed error affecting multiple dipole computations -% -% Revision 1.2 2003/03/11 14:45:36 roberto -% updated help and copyrights -% - -siz = size(rd); -if any(siz==1) - % positions are specified as a single vector - Ndipoles = prod(siz)/3; -elseif siz(2)==3 - % positions are specified as a Nx3 matrix -> reformat to a single vector - Ndipoles = siz(1); - rd = rd'; - rd = rd(:); -else - error('incorrect specification of dipole locations'); -end - -Npnt = size(pnt,1); -lf = zeros(Npnt,3*Ndipoles); -s1 = size(rd); - -if s1(1)>s1(2) - % make sure that the dipole position is a row-vector - rd = rd'; -end - -for i=1:Ndipoles - r = pnt - ones(Npnt,1) * rd((1:3) + 3*(i-1)); - R = (4*pi*cond) * (sum(r' .^2 ) .^ 1.5)'; - if any(R)==0 - warning('dipole lies on boundary of volume model'); - end - lf(:,(1:3) + 3*(i-1)) = r ./ [R R R]; -end - diff --git a/external/forwinv/private/inside_vol.m b/external/forwinv/private/inside_vol.m deleted file mode 100644 index 99007d8..0000000 --- a/external/forwinv/private/inside_vol.m +++ /dev/null @@ -1,138 +0,0 @@ -function [inside] = inside_vol(pos, vol) - -% INSIDE_VOL locates dipole locations inside/outside the source -% compartment of a volume conductor model. -% -% [inside] = inside_vol(pos, vol, ...) -% -% where the input should be -% pos Nx3 matrix with dipole positions -% vol structure with volume conductor model -% and the output is -% inside list of dipoles inside the brain compartment -% (1=inside, 0=outisde) -% -% Additional optional input arguments shoudl be given in key value pairs -% and can include -% - -% Copyright (C) 2003-2007, Robert Oostenveld -% -% $Log: inside_vol.m,v $ -% Revision 1.5 2009/02/05 10:20:35 roboos -% added bemcp as volume type -% -% Revision 1.4 2009/01/21 11:15:57 roboos -% moved function back from forwinv/private into public section, because it is part of the public API -% -% Revision 1.1 2009/01/21 10:46:10 roboos -% moved from forwinv/* and forwinv/mex/* directory to forwinv/private/* to make the CVS layout consistent with the release version -% -% Revision 1.2 2008/09/29 12:04:41 roboos -% use logical (built-in) instead of boolean (simulink) -% -% Revision 1.1 2008/09/20 13:41:35 roboos -% moved content of find_inside_vol to new inside_vol function with slightly different interface -% added wrapper for spm -% -% -% %%% -% Switch from find_inside_vol.m to inside_vol.m -% 2008/09/09 chrisp -% %%% -% -% Revision 1.7 2008/04/15 20:36:21 roboos -% added explicit handling of various BEM implementations, i.e. for all -% voltype variants -% -% Revision 1.6 2007/07/25 08:34:05 roboos -% switched to using voltype helper function -% also support N-shell concentric sphere model -% changed detection for single and concentric sphere model, now explicitely -% using distance and source compartment -% -% Revision 1.5 2004/09/06 08:46:27 roboos -% moved reading of neuromag BEM boundary into fieldtrip's prepare_vol_sens -% -% Revision 1.4 2004/09/03 09:07:17 roboos -% added support for finding dipoles in neuromag BEM model -% -% Revision 1.3 2003/08/04 09:19:30 roberto -% fixed bug for dipole on BEM volume boundary -% -% Revision 1.2 2003/03/24 12:30:06 roberto -% added support for multi-sphere volume conductor model -% - -% determine the type of volume conduction model -switch voltype(vol) - - % single-sphere or multiple concentric spheres - case {'singlesphere' 'concentric'} - if ~isfield(vol, 'source') - % locate the innermost compartment and remember it - [dum, vol.source] = min(vol.r); - end - if isfield(vol, 'o') - % shift dipole positions toward origin of sphere - tmp = pos - repmat(vol.o, size(pos,1), 1); - else - tmp = pos; - end - distance = sqrt(sum(tmp.^2, 2))-vol.r(vol.source); - % positive if outside, negative if inside - inside = distance<0; - - % multi-sphere volume conductor model - case 'multisphere' - - % nspheres = size(vol.r,1); - % ndipoles = size(pos,1); - % inside = zeros(ndipoles,1); - % for sph=1:nspheres - % for dip=1:ndipoles - % if inside(dip) - % % the dipole has already been detected in one of the other spheres - % continue - % end - % inside(dip) = (norm(pos(dip,:) - vol.o(sph,:)) <= vol.r(sph)); - % end - % end - % outside = find(inside==0); - % inside = find(inside==1); - - % this is a much faster implementation - nspheres = size(vol.r,1); - ndipoles = size(pos,1); - inside = zeros(ndipoles,1); - for sph=1:nspheres - % temporary shift dipole positions toward origin - if isfield(vol, 'o') - tmp = pos - repmat(vol.o(sph,:), [ndipoles 1]); - else - tmp = pos; - end - flag = (sqrt(sum(tmp.^2,2)) <= vol.r(sph)); - inside = inside + flag; - end - inside = inside>0; - - % realistic BEM volume conductor model - case {'bem', 'dipoli', 'bemcp', 'asa', 'avo', 'nolte', 'neuromag'} - if ~isfield(vol, 'source') - % locate the innermost compartment and remember it - vol.source = find_innermost_boundary(vol.bnd); - end - % use the specified source compartment - pnt = vol.bnd(vol.source).pnt; - tri = vol.bnd(vol.source).tri; - % determine the dipole positions that are inside the brain compartment - inside = bounding_mesh(pos, pnt, tri); - - % unrecognized volume conductor model - otherwise - error('unrecognized volume conductor model'); -end - -% ensure that these are column vectors -inside = logical(inside(:)); diff --git a/external/forwinv/private/issubfield.m b/external/forwinv/private/issubfield.m deleted file mode 100644 index 60d94f4..0000000 --- a/external/forwinv/private/issubfield.m +++ /dev/null @@ -1,35 +0,0 @@ -function [r] = issubfield(s, f) - -% ISSUBFIELD tests for the presence of a field in a structure just like the standard -% Matlab ISFIELD function, except that you can also specify nested fields -% using a '.' in the fieldname. The nesting can be arbitrary deep. -% -% Use as -% f = issubfield(s, 'fieldname') -% or as -% f = issubfield(s, 'fieldname.subfieldname') -% -% This function returns true if the field is present and false if the field -% is not present. -% -% See also ISFIELD, GETSUBFIELD, SETSUBFIELD - -% Copyright (C) 2005, Robert Oostenveld -% -% $Log: issubfield.m,v $ -% Revision 1.2 2009/07/30 20:11:44 ingnie -% made output boolian -% -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.1 2005/02/08 09:30:18 roboos -% new implementations to make it easier to work with nested structures -% - -try - getsubfield(s, f); % if this works, then the subfield must be present - r = true; -catch - r = false; % apparently the subfield is not present -end \ No newline at end of file diff --git a/external/forwinv/private/keyval.m b/external/forwinv/private/keyval.m deleted file mode 100644 index 106cf02..0000000 --- a/external/forwinv/private/keyval.m +++ /dev/null @@ -1,62 +0,0 @@ -function [val] = keyval(key, varargin) - -% KEYVAL returns the value that corresponds to the requested key in a -% key-value pair list of variable input arguments -% -% Use as -% [val] = keyval(key, varargin) -% -% See also VARARGIN - -% Copyright (C) 2005-2007, Robert Oostenveld -% -% $Log: keyval.m,v $ -% Revision 1.5 2009/08/04 11:58:28 roboos -% perform a case-insensitive string comparison for keys -% -% Revision 1.4 2009/07/14 16:11:02 roboos -% speed up the input checks -% -% Revision 1.3 2009/05/14 19:24:02 roboos -% removed ; at end of function declaration -% -% Revision 1.2 2009/01/06 09:05:26 roboos -% added additional check on optional input arguments: the 1st, 3rd, etc. should be strings (keys) -% -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.2 2007/07/18 12:43:53 roboos -% test for an even number of optional input arguments -% -% Revision 1.1 2005/11/04 10:24:46 roboos -% new implementation -% - -if length(varargin)==1 && iscell(varargin{1}) - varargin = varargin{1}; -end - -if mod(length(varargin),2) - error('optional input arguments should come in key-value pairs, i.e. there should be an even number'); -end - -% the 1st, 3rd, etc. contain the keys, the 2nd, 4th, etc. contain the values -keys = varargin(1:2:end); -vals = varargin(2:2:end); - -if ~all(cellfun(@ischar, keys)) - error('optional input arguments should come in key-value pairs, the optional input argument %d is invalid (should be a string)', i); -end - -hit = find(strcmpi(key, keys)); -if isempty(hit) - % the requested key was not found - val = []; -elseif length(hit)==1 - % the requested key was found - val = vals{hit}; -else - error('multiple input arguments with the same name'); -end - diff --git a/external/forwinv/private/leadsphere_all.m b/external/forwinv/private/leadsphere_all.m deleted file mode 100644 index 96b8c42..0000000 --- a/external/forwinv/private/leadsphere_all.m +++ /dev/null @@ -1,68 +0,0 @@ -function out=leadsphere_chans(xloc,sensorloc,sensorori) -% usage: out=leadsphere_chans(xloc,sensorloc,sensorori) - - -[n,nsens]=size(sensorloc); %n=3 m=? -[n,ndip]=size(xloc); - - -xlocrep=reshape(repmat(xloc,1,nsens),3,ndip,nsens); -sensorlocrep=reshape(repmat(sensorloc,ndip,1),3,ndip,nsens); -sensororirep=reshape(repmat(sensorori,ndip,1),3,ndip,nsens); - -r2=norms(sensorlocrep); -veca=sensorlocrep-xlocrep; -a=norms(veca); -adotr2=dotproduct(veca,sensorlocrep); - -gradf1=scal2vec(1./r2.*(a.^2)+adotr2./a+2*a+2*r2); -gradf2=scal2vec(a+2*r2+adotr2./a); -gradf=gradf1.*sensorlocrep-gradf2.*xlocrep; - -F=a.*(r2.*a+adotr2); - -A1=scal2vec(1./F); -A2=A1.^2; - -A3=crossproduct(xlocrep,sensororirep); -A4=scal2vec(dotproduct(gradf,sensororirep)); -A5=crossproduct(xlocrep,sensorlocrep); - -out=1000*(A3.*A1-(A4.*A2).*A5); - -return; - - - -function out=crossproduct(x,y) -[n,m,k]=size(x); -out=zeros(3,m,k); -out(1,:,:)=x(2,:,:).*y(3,:,:)-x(3,:,:).*y(2,:,:); -out(2,:,:)=x(3,:,:).*y(1,:,:)-x(1,:,:).*y(3,:,:); -out(3,:,:)=x(1,:,:).*y(2,:,:)-x(2,:,:).*y(1,:,:); -return; - - -function out=dotproduct(x,y) -[n,m,k]=size(x); -outb=x(1,:,:).*y(1,:,:)+x(2,:,:).*y(2,:,:)+x(3,:,:).*y(3,:,:); -out=reshape(outb,m,k); -return; - - -function result=norms(x) -[n,m,k]=size(x); -resultb=sqrt(x(1,:,:).^2+x(2,:,:).^2+x(3,:,:).^2); -result=reshape(resultb,m,k); -return; - - -function result=scal2vec(x) -[m,k]=size(x); -% result=zeros(3,m,k); -% for i=1:3 -% result(i,:,:)=x; -% end -result=reshape(repmat(x(:)', [3 1]), [3 m k]); -return - diff --git a/external/forwinv/private/lmoutr.m b/external/forwinv/private/lmoutr.m deleted file mode 100644 index 63af461..0000000 --- a/external/forwinv/private/lmoutr.m +++ /dev/null @@ -1,40 +0,0 @@ -function [la, mu, dist] = lmoutr(v1, v2, v3, r); - -% LMOUTR computes the la/mu parameters of a point projected to a triangle -% -% [la, mu, dist] = lmoutr(v1, v2, v3, r) -% -% where v1, v2 and v3 are three vertices of the triangle, and r is -% the point that is projected onto the plane spanned by the vertices -% -% also implemented as MEX file - -% Copyright (C) 2002, Robert Oostenveld -% -% $Log: lmoutr.m,v $ -% Revision 1.4 2007/01/03 17:02:26 roboos -% removed an incorrect statement from the help -% -% Revision 1.3 2003/03/11 15:35:20 roberto -% converted all files from DOS to UNIX -% -% Revision 1.2 2003/03/04 21:46:19 roberto -% added CVS log entry and synchronized all copyright labels -% - -% compute la/mu parameters -vec0 = r - v1; -vec1 = v2 - v1; -vec2 = v3 - v2; -vec3 = v3 - v1; - -tmp = [vec1' vec3'] \ (vec0'); -la = tmp(1); -mu = tmp(2); - -% determine the projection onto the plane of the triangle -proj = v1 + la*vec1 + mu*vec3; - -% determine the distance from the original point to its projection -dist = norm(r-proj); - diff --git a/external/forwinv/private/lmoutr.mexw32 b/external/forwinv/private/lmoutr.mexw32 deleted file mode 100644 index 459e464..0000000 Binary files a/external/forwinv/private/lmoutr.mexw32 and /dev/null differ diff --git a/external/forwinv/private/ltrisect.c b/external/forwinv/private/ltrisect.c deleted file mode 100644 index d85ef95..0000000 --- a/external/forwinv/private/ltrisect.c +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include "mex.h" -#include "matrix.h" -#include "geometry.h" - -void -mexFunction (int nlhs, mxArray * plhs[], int nrhs, const mxArray * prhs[]) -{ - char str[256]; - mxArray *sect; - double *v1, *v2, *v3, *l1, *l2, *sect_p; - - if (nrhs!=5) - mexErrMsgTxt ("Invalid number of input arguments"); - - if (mxGetM(prhs[0])!=1 || mxGetN(prhs[0])!=3) - mexErrMsgTxt ("Invalid dimension for input argument 1"); - if (mxGetM(prhs[1])!=1 || mxGetN(prhs[1])!=3) - mexErrMsgTxt ("Invalid dimension for input argument 2"); - if (mxGetM(prhs[2])!=1 || mxGetN(prhs[2])!=3) - mexErrMsgTxt ("Invalid dimension for input argument 3"); - if (mxGetM(prhs[3])!=1 || mxGetN(prhs[3])!=3) - mexErrMsgTxt ("Invalid dimension for input argument 4"); - if (mxGetM(prhs[4])!=1 || mxGetN(prhs[4])!=3) - mexErrMsgTxt ("Invalid dimension for input argument 5"); - - v1 = mxGetData (prhs[0]); - v2 = mxGetData (prhs[1]); - v3 = mxGetData (prhs[2]); - l1 = mxGetData (prhs[3]); - l2 = mxGetData (prhs[4]); - - sect = mxCreateDoubleMatrix (1, 3, mxREAL); - sect_p = mxGetData (sect); - - ltrisect(v1, v2, v3, l1, l2, sect_p); - - /* assign the output parameters */ - plhs[0] = sect; - - return; -} - diff --git a/external/forwinv/private/ltrisect.mexa64 b/external/forwinv/private/ltrisect.mexa64 deleted file mode 100755 index ca547af..0000000 Binary files a/external/forwinv/private/ltrisect.mexa64 and /dev/null differ diff --git a/external/forwinv/private/ltrisect.mexglx b/external/forwinv/private/ltrisect.mexglx deleted file mode 100755 index a659f93..0000000 Binary files a/external/forwinv/private/ltrisect.mexglx and /dev/null differ diff --git a/external/forwinv/private/ltrisect.mexmaci b/external/forwinv/private/ltrisect.mexmaci deleted file mode 100755 index 78b83fb..0000000 Binary files a/external/forwinv/private/ltrisect.mexmaci and /dev/null differ diff --git a/external/forwinv/private/ltrisect.mexmaci64 b/external/forwinv/private/ltrisect.mexmaci64 deleted file mode 100755 index 5bb017d..0000000 Binary files a/external/forwinv/private/ltrisect.mexmaci64 and /dev/null differ diff --git a/external/forwinv/private/ltrisect.mexw32 b/external/forwinv/private/ltrisect.mexw32 deleted file mode 100644 index b2493cc..0000000 Binary files a/external/forwinv/private/ltrisect.mexw32 and /dev/null differ diff --git a/external/forwinv/private/ltrisect.mexw64 b/external/forwinv/private/ltrisect.mexw64 deleted file mode 100644 index 730a92c..0000000 Binary files a/external/forwinv/private/ltrisect.mexw64 and /dev/null differ diff --git a/external/forwinv/private/magnetic_dipole.m b/external/forwinv/private/magnetic_dipole.m deleted file mode 100644 index e73f02c..0000000 --- a/external/forwinv/private/magnetic_dipole.m +++ /dev/null @@ -1,71 +0,0 @@ -function [lf] = magnetic_dipole(R, pos, ori) - -% MAGNETIC_DIPOLE leadfield for a magnetic dipole in an infinite medium -% -% [lf] = magnetic_dipole(R, pos, ori) -% -% with input arguments -% R position dipole -% pos position magnetometers -% ori orientation magnetometers - -% Copyright (C) 2003, Robert Oostenveld -% -% $Log: magnetic_dipole.m,v $ -% Revision 1.1 2009/01/21 10:32:38 roboos -% moved from forwinv/* and forwinv/mex/* directory to forwinv/private/* to make the CVS layout consistent with the release version -% -% Revision 1.1 2003/03/12 09:22:18 roberto -% new implementation, optimized for speed -% based on http://scienceworld.wolfram.com/physics/MagneticDipole.html -% - -u0 = 1e-7; -nchan = size(pos,1); - -% ensure that the dipole position is a row vector -R = reshape(R, [1 3]); - -% shift the magnetometers so that the dipole is in the origin -pos = pos - repmat(R, [nchan 1]); - -% change the variable names for convenience -% R position of magnetometer, relative to dipole -% r distance of magnetometer, relative to dipole -R = pos; -r = sqrt(sum(R.^2,2)); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% this is the original code, which follows the physical formulation closely -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% magnetic field on all magnetometer positions for an x-oriented dipole -% Bmx = u0/(4*pi) * (3 * repmat(R(:,1), [1 3]) .* R - repmat([1 0 0], [nchan 1]) .* repmat(r.^2, [1 3])) ./ repmat(r.^5, [1 3]); -% magnetic field on all magnetometer positions for an y-oriented dipole -% Bmy = u0/(4*pi) * (3 * repmat(R(:,2), [1 3]) .* R - repmat([0 1 0], [nchan 1]) .* repmat(r.^2, [1 3])) ./ repmat(r.^5, [1 3]); -% magnetic field on all magnetometer positions for an z-oriented dipole -% Bmz = u0/(4*pi) * (3 * repmat(R(:,3), [1 3]) .* R - repmat([0 0 1], [nchan 1]) .* repmat(r.^2, [1 3])) ./ repmat(r.^5, [1 3]); -% compute the field along the orientation of each magnetometer for an x/y/z oriented dipole -% lf(:,1) = dot(Bmx, ori, 2); -% lf(:,2) = dot(Bmy, ori, 2); -% lf(:,3) = dot(Bmz, ori, 2); - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% this is the optimized code, which make the previous computation approximately -% three times more efficent by introducing temporary variables -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -r2 = repmat(r.^2, [1 3]); -r5 = repmat(r.^5, [1 3]); -x = R(:,1); x = [x x x]; -y = R(:,2); y = [y y y]; -z = R(:,3); z = [z z z]; -mx = zeros(nchan,3); mx(:,1) = 1; -my = zeros(nchan,3); my(:,2) = 1; -mz = zeros(nchan,3); mz(:,3) = 1; -Tx = (3 * x .* R - mx .* r2); -Ty = (3 * y .* R - my .* r2); -Tz = (3 * z .* R - mz .* r2); -lf(:,1) = dot(Tx, ori, 2); -lf(:,2) = dot(Ty, ori, 2); -lf(:,3) = dot(Tz, ori, 2); -lf = u0/(4*pi) * lf ./ r5; - diff --git a/external/forwinv/private/match_str.m b/external/forwinv/private/match_str.m deleted file mode 100644 index 9903621..0000000 --- a/external/forwinv/private/match_str.m +++ /dev/null @@ -1,85 +0,0 @@ -function [sel1, sel2] = match_str(a, b); - -% MATCH_STR looks for matching labels in two listst of strings -% and returns the indices into both the 1st and 2nd list of the matches. -% They will be ordered according to the first input argument. -% -% [sel1, sel2] = match_str(strlist1, strlist2) -% -% The strings can be stored as a char matrix or as an vertical array of -% cells, the matching is done for each row. - -% Copyright (C) 2000, Robert Oostenveld -% -% $Log: match_str.m,v $ -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.7 2008/07/17 10:26:11 roboos -% cleaned up the code a little bit, no functional change -% -% Revision 1.6 2006/11/06 21:11:45 roboos -% also deal with empty [] input -% -% Revision 1.5 2004/11/10 17:11:40 roboos -% reverted to original implementation and reimplemented the speed up -% from scratch. The previous two revisions both were incompatible -% with the original implementation. -% -% Revision 1.4 2004/11/09 15:28:57 roboos -% fixed incompatibility that was introduced by previous speed increase: -% the original version gave back double occurences, and other fieldtrip -% functions (sourceanalysis) rely on this. The previously commited -% version only gave back one occurence of each hit, this is fixed by jansch -% in this version -% -% Revision 1.3 2004/10/22 15:59:41 roboos -% large speed increase by replacing 2 nested for loops by a standard matlab function (intersect) -% -% Revision 1.2 2003/03/17 10:37:28 roberto -% improved general help comments and added copyrights - -% ensure that both are cell-arrays -if isempty(a) - a = {}; -elseif ~iscell(a) - a = cellstr(a); -end -if isempty(b) - b = {}; -elseif ~iscell(b) - b = cellstr(b); -end - -% regardless of what optimizations are implemented, the code should remain -% functionally compatible to the original, which is -% for i=1:length(a) -% for j=1:length(b) -% if strcmp(a(i),b(j)) -% sel1 = [sel1; i]; -% sel2 = [sel2; j]; -% end -% end -% end - -% ensure that both are column vectors -a = a(:); -b = b(:); -Na = numel(a); -Nb = numel(b); - -% replace all unique strings by a unique number and use the fact that -% numeric comparisons are much faster than string comparisons -[dum1, dum2, c] = unique([a; b]); -a = c(1:Na); -b = c((Na+1):end); - -sel1 = []; -sel2 = []; -for i=1:length(a) - % s = find(strcmp(a(i), b)); % for string comparison - s = find(a(i)==b); % for numeric comparison - sel2 = [sel2; s]; - s(:) = i; - sel1 = [sel1; s]; -end diff --git a/external/forwinv/private/meg_leadfield1.c b/external/forwinv/private/meg_leadfield1.c deleted file mode 100755 index 41e7d44..0000000 --- a/external/forwinv/private/meg_leadfield1.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include -#include "mex.h" -#include "matrix.h" - -void -mexFunction (int nlhs, mxArray * plhs[], int nrhs, const mxArray * prhs[]) -{ - mxArray *lf; - double tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, eps, alpha, beta, A, B, C; - double r[3], u[3], d[3]; - double *lf_p, *rm_p, *um_p, *R; - int nchan, i; - char str[256]; - - if (nrhs<3) - mexErrMsgTxt("Not enough input arguments"); - if (nrhs>3) - mexErrMsgTxt("Too many input arguments"); - - if (mxGetM(prhs[0])!=1 || mxGetN(prhs[0])!=3) - mexErrMsgTxt ("Invalid dimension for input argument 1"); - if (mxGetN(prhs[1])!=3) - mexErrMsgTxt ("Invalid dimension for input argument 2"); - if (mxGetN(prhs[2])!=3) - mexErrMsgTxt ("Invalid dimension for input argument 3"); - nchan = mxGetM(prhs[1]); - if (mxGetM(prhs[2])!=nchan) - mexErrMsgTxt ("Number of channels does not match between argument 2 and 3"); - - lf = mxCreateDoubleMatrix(nchan, 3, mxREAL); - lf_p = mxGetData(lf); - R = mxGetData(prhs[0]); - rm_p = mxGetData(prhs[1]); - um_p = mxGetData(prhs[2]); - eps = mxGetEps(); - - tmp2 = sqrt(R[0]*R[0] + R[1]*R[1] + R[2]*R[2]); /* norm(R) */ - - for (i=0; i -#include "mex.h" -#include "matrix.h" -#include "geometry.h" - -void -mexFunction (int nlhs, mxArray * plhs[], int nrhs, const mxArray * prhs[]) -{ - char str[256]; - mxArray *proj, *dist; - double *l1, *l2, *r, *proj_p, *dist_p; - int flag; - - if (nrhs <3 || nrhs>4) - mexErrMsgTxt ("Invalid number of input arguments"); - - if (mxGetM(prhs[0])!=1 || mxGetN(prhs[0])!=3) - mexErrMsgTxt ("Invalid dimension for input argument 1"); - if (mxGetM(prhs[1])!=1 || mxGetN(prhs[1])!=3) - mexErrMsgTxt ("Invalid dimension for input argument 2"); - if (mxGetM(prhs[2])!=1 || mxGetN(prhs[2])!=3) - mexErrMsgTxt ("Invalid dimension for input argument 3"); - - l1 = mxGetData (prhs[0]); - l2 = mxGetData (prhs[1]); - r = mxGetData (prhs[2]); - - if (nrhs==4) - flag = (int)mxGetScalar (prhs[3]); - else - flag = 0; - - proj = mxCreateDoubleMatrix (1, 3, mxREAL); - dist = mxCreateDoubleMatrix (1, 1, mxREAL); - proj_p = mxGetData (proj); - dist_p = mxGetData (dist); - - (*dist_p) = plinproj(l1, l2, r, proj_p, flag); - - /* assign the output parameters */ - plhs[0] = proj; - if (nlhs>1) - plhs[1] = dist; - - return; -} - diff --git a/external/forwinv/private/plinproj.mexa64 b/external/forwinv/private/plinproj.mexa64 deleted file mode 100755 index f0f2458..0000000 Binary files a/external/forwinv/private/plinproj.mexa64 and /dev/null differ diff --git a/external/forwinv/private/plinproj.mexglx b/external/forwinv/private/plinproj.mexglx deleted file mode 100755 index a8bf9e3..0000000 Binary files a/external/forwinv/private/plinproj.mexglx and /dev/null differ diff --git a/external/forwinv/private/plinproj.mexmaci b/external/forwinv/private/plinproj.mexmaci deleted file mode 100755 index cfd2f64..0000000 Binary files a/external/forwinv/private/plinproj.mexmaci and /dev/null differ diff --git a/external/forwinv/private/plinproj.mexmaci64 b/external/forwinv/private/plinproj.mexmaci64 deleted file mode 100755 index 6be0b9c..0000000 Binary files a/external/forwinv/private/plinproj.mexmaci64 and /dev/null differ diff --git a/external/forwinv/private/plinproj.mexw32 b/external/forwinv/private/plinproj.mexw32 deleted file mode 100644 index eb0695b..0000000 Binary files a/external/forwinv/private/plinproj.mexw32 and /dev/null differ diff --git a/external/forwinv/private/plinproj.mexw64 b/external/forwinv/private/plinproj.mexw64 deleted file mode 100644 index c87c74b..0000000 Binary files a/external/forwinv/private/plinproj.mexw64 and /dev/null differ diff --git a/external/forwinv/private/prepare_vol_sens.m b/external/forwinv/private/prepare_vol_sens.m deleted file mode 100644 index f658297..0000000 --- a/external/forwinv/private/prepare_vol_sens.m +++ /dev/null @@ -1,419 +0,0 @@ -function [vol, sens] = prepare_vol_sens(vol, sens, varargin) - -% PREPARE_VOL_SENS does some bookkeeping to ensure that the volume -% conductor model and the sensor array are ready for subsequent forward -% leadfield computations. It takes care of some pre-computations that can -% be done efficiently prior to the leadfield calculations. -% -% Use as -% [vol, sens] = prepare_vol_sens(vol, sens, ...) -% with input arguments -% sens structure with gradiometer or electrode definition -% vol structure with volume conductor definition -% -% The vol structure represents a volume conductor model, its contents -% depend on the type of model. The sens structure represents a sensor -% array, i.e. EEG electrodes or MEG gradiometers. -% -% Additional options should be specified in key-value pairs and can be -% 'channel' cell-array with strings (default = 'all') -% 'order' number, for single shell "Nolte" model (default = 10) -% -% The detailled behaviour of this function depends on whether the input -% consists of EEG or MEG and furthermoree depends on the type of volume -% conductor model: -% - in case of EEG single and concentric sphere models, the electrodes are -% projected onto the skin surface. -% - in case of EEG boundary element models, the electrodes are projected on -% the surface and a blilinear interpoaltion matrix from vertices to -% electrodes is computed. -% - in case of MEG and a multispheres model, a local sphere is determined -% for each coil in the gradiometer definition. -% - in case of MEG with a singleshell Nolte model, the volume conduction -% model is initialized -% In any case channel selection and reordering will be done. The channel -% order returned by this function corresponds to the order in the 'channel' -% option, or if not specified, to the order in the input sensor array. -% -% See also READ_VOL, READ_SENS, TRANSFORM_VOL, TRANSFORM_SENS, COMPUTE_LEADFIELD - -% Copyright (C) 2004-2009, Robert Oostenveld -% -% $Log: prepare_vol_sens.m,v $ -% Revision 1.21 2009/09/27 19:12:38 crimic -% wrapper adapted for openmeeg forward solution -% -% Revision 1.20 2009/09/21 11:12:51 roboos -% added openmeeg as supported voltype, thanks to Cristiano -% -% Revision 1.19 2009/05/29 11:50:34 vlalit -% Fixed a bug with wrong kind of brackets -% -% Revision 1.18 2009/05/25 11:50:40 roboos -% consistent handling of multiple spheres in case of ctf localspheres.hdm and fieldtrip prepare_localspheres, also in case of synthetic gradients. -% -% Revision 1.17 2009/05/25 08:06:37 roboos -% don't assign the channel labels to each coil for multisphere -% handle the input situation of an already prepared vol and sens (for multisphere) -% -% Revision 1.16 2009/05/18 15:57:23 roboos -% added the label of each coil to the multisphere model output -% -% Revision 1.15 2009/04/01 12:36:52 roboos -% use Taubin's method for fitting the sphere instead of Guido's iterative sphfit function -% -% Revision 1.14 2009/03/26 16:44:03 roboos -% allow 3rd order gradients iduring the construction of the localspheres model, requires that the hdm file contains a global sphere -% -% Revision 1.13 2009/03/23 21:15:18 roboos -% fixed bug for empty vol (inf medium magnetic dipole) -% -% Revision 1.12 2009/03/11 11:29:26 roboos -% ensure that the channel order in the sens and in the vol is consistent with the user-specified channel-keyval argument -% -% Revision 1.11 2009/02/02 13:06:40 roboos -% added bemcp -% changed handling of vertex->electrode interpolation, now also possible if bem system matrix only describes the skin surface -% -% Revision 1.10 2009/01/19 12:13:49 roboos -% added code at the end to determine the brain and the skin compartment -% -% Revision 1.9 2008/12/24 10:34:15 roboos -% added two fprintf statements -% -% Revision 1.8 2008/09/29 09:56:04 release -% some spelling fixes, thanks to Karl -% -% Revision 1.7 2008/07/22 10:17:15 roboos -% replaced identical with strcmp -% -% Revision 1.6 2008/07/21 20:28:44 roboos -% added check on units (mm/cm/m) of the sensor array and volume conductor, give error if inconsistent -% -% Revision 1.5 2008/04/30 13:47:59 roboos -% project electrodes on scalp surface if sphere -% always ensure that grad.tra exists (not yet for elec) -% -% Revision 1.4 2008/04/15 20:36:21 roboos -% added explicit handling of various BEM implementations, i.e. for all voltype variants -% -% Revision 1.3 2008/04/10 11:00:29 roboos -% fixed some small but obvious bugs -% -% Revision 1.2 2008/04/09 20:37:32 roboos -% copied code over from ft version, not yet tested -% -% Revision 1.1 2008/03/06 09:30:36 roboos -% Created skeleton implementation according to how it should be for the forwinv toolbox, i.e. fieldtrip independent, so that it can be included in spm8. -% The functionality should be moved from the existing fieldtrip/private/prepare_vol_sens.m function into this new function. -% - -% get the options -% fileformat = keyval('fileformat', varargin); -channel = keyval('channel', varargin); % cell-array with channel labels -order = keyval('order', varargin); % order of expansion for Nolte method; 10 should be enough for real applications; in simulations it makes sense to go higher - -% set the defaults -if isempty(channel), channel = sens.label; end -if isempty(order), order = 10; end - -% determine whether the input contains EEG or MEG sensors -iseeg = senstype(sens, 'eeg'); -ismeg = senstype(sens, 'meg'); - -if isfield(vol, 'unit') && isfield(sens, 'unit') && ~strcmp(vol.unit, sens.unit) - error('inconsistency in the units of the volume conductor and the sensor array'); -end - -if ismeg && iseeg - % this is something that could be implemented relatively easily - error('simultaneous EEG and MEG not yet supported'); - -elseif ~ismeg && ~iseeg - error('the input does not look like EEG, nor like MEG'); - -elseif ismeg - % always ensure that there is a linear transfer matrix for combining the coils into gradiometers - if ~isfield(sens, 'tra'); - sens.tra = sparse(eye(length(sens.label))); - end - - % select the desired channels from the gradiometer array - % order them according to the users specification - [selchan, selsens] = match_str(channel, sens.label); - - % first only modify the linear combination of coils into channels - sens.label = sens.label(selsens); - sens.tra = sens.tra(selsens,:); - % subsequently remove the coils that do not contribute to any sensor output - selcoil = find(sum(sens.tra,1)~=0); - sens.pnt = sens.pnt(selcoil,:); - sens.ori = sens.ori(selcoil,:); - sens.tra = sens.tra(:,selcoil); - - switch voltype(vol) - case 'infinite' - % nothing to do - - case 'singlesphere' - % nothing to do - - case 'concentric' - % nothing to do - - case 'neuromag' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % if the forward model is computed using the external Neuromag toolbox, - % we have to add a selection of the channels so that the channels - % in the forward model correspond with those in the data. - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - [selchan, selsens] = match_str(channel, sens.label); - vol.chansel = selsens; - - case 'multisphere' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % If the volume conduction model consists of multiple spheres then we - % have to match the channels in the gradiometer array and the volume - % conduction model. - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - % the initial multisphere volume conductor has a single sphere per - % channel, whereas it should have a sphere for each coil - if size(vol.r,1)==size(sens.pnt,1) - % it appears that each coil already has a sphere, which suggests - % that the volume conductor already has been prepared to match the - % sensor array - if ~isfield(vol, 'label') - % this is ok, since coils should not have labels - else - % hmm, this only works if there is a one-to-one match between - % coils in the sensor array and coils in the volme conductor - if ~isequal(vol.label(:), sens.label(:)) - % the problem here is that each channel can have multiple coils - % in case of a gradiometer arrangement. The consequence is that - % the coil label is not unique, because the bottom and top - % coil will have the same label. That causes problems with the - % channel selection. - error('the coils in the volume conduction model do not correspond to the sensor array'); - else - % the coil-specific spheres in the volume conductor should not have a label - % because the label is already specified for the coils in the - % sensor array - vol = rmfield(vol, 'label'); - end - end - end - - % select the desired channels from the multisphere volume conductor - % order them according to the users specification - [selchan, selvol] = match_str(channel, vol.label); - vol.label = vol.label(selvol); - vol.r = vol.r(selvol); - vol.o = vol.o(selvol,:); - - % the CTF way of representing the headmodel is one-sphere-per-channel - % whereas the FieldTrip way of doing the forward computation is one-sphere-per-coil - Nchans = size(sens.tra,1); - Ncoils = size(sens.tra,2); - Nspheres = size(vol.label); - - if isfield(vol, 'orig') - % these are present in a CTF *.hdm file - singlesphere.o(1,1) = vol.orig.MEG_Sphere.ORIGIN_X; - singlesphere.o(1,2) = vol.orig.MEG_Sphere.ORIGIN_Y; - singlesphere.o(1,3) = vol.orig.MEG_Sphere.ORIGIN_Z; - singlesphere.r = vol.orig.MEG_Sphere.RADIUS; - % ensure consistent units - singlesphere = convert_units(singlesphere, vol.unit); - else - singlesphere = []; - end - - if ~isempty(singlesphere) - % determine the channels that do not have a corresponding sphere - % and use the globally fitted single sphere for those - missing = setdiff(sens.label, vol.label); - if ~isempty(missing) - warning('using the global fitted single sphere for %d channels that do not have a local sphere', length(missing)); - end - for i=1:length(missing) - vol.label(end+1) = missing(i); - vol.r(end+1,:) = singlesphere.r; - vol.o(end+1,:) = singlesphere.o; - end - end - - multisphere = []; - % for each coil in the MEG helmet, determine the corresponding local sphere - for i=1:Ncoils - coilindex = find(sens.tra(:,i)~=0); % to which channel does the coil belong - if length(coilindex)>1 - % this indicates that there are multiple channels to which this coil contributes, - % which happens if the sensor array represents a synthetic higher-order gradient. - [dum, coilindex] = max(abs(sens.tra(:,i))); - end - - coillabel = sens.label{coilindex}; % what is the label of the channel - chanindex = strmatch(coillabel, vol.label, 'exact'); - multisphere.r(i,:) = vol.r(chanindex); - multisphere.o(i,:) = vol.o(chanindex,:); - end - vol = multisphere; - - case 'nolte' - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % if the forward model is computed using the code from Guido Nolte, we - % have to initialize the volume model using the gradiometer coil - % locations - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - % compute the surface normals for each vertex point - if ~isfield(vol.bnd, 'nrm') - fprintf('computing surface normals\n'); - vol.bnd.nrm = normals(vol.bnd.pnt, vol.bnd.tri); - end - % estimate center and radius - [center,radius] = fitsphere(vol.bnd.pnt); - % initialize the forward calculation (only if gradiometer coils are available) - if size(sens.pnt,1)>0 - vol.forwpar = meg_ini([vol.bnd.pnt vol.bnd.nrm], center', order, [sens.pnt sens.ori]); - end - - otherwise - error('unsupported volume conductor model for MEG'); - end - -elseif iseeg - % select the desired channels from the electrode array - % order them according to the users specification - [selchan, selsens] = match_str(channel, sens.label); - sens.label = sens.label(selsens); - sens.pnt = sens.pnt(selsens,:); - - % create a 2D projection and triangulation - sens.prj = elproj(sens.pnt); - sens.tri = delaunay(sens.prj(:,1), sens.prj(:,2)); - - switch voltype(vol) - case 'infinite' - % nothing to do - - case {'singlesphere', 'concentric'} - % ensure that the electrodes ly on the skin surface - radius = max(vol.r); - pnt = sens.pnt; - if isfield(vol, 'o') - % shift the the centre of the sphere to the origin - pnt(:,1) = pnt(:,1) - vol.o(1); - pnt(:,2) = pnt(:,2) - vol.o(2); - pnt(:,3) = pnt(:,3) - vol.o(3); - end - distance = sqrt(sum(pnt.^2,2)); % to the center of the sphere - if any((abs(distance-radius)/radius)>0.005) - warning('electrodes do not lie on skin surface -> using radial projection') - end - pnt = pnt * radius ./ [distance distance distance]; - if isfield(vol, 'o') - % shift the center back to the original location - pnt(:,1) = pnt(:,1) + vol.o(1); - pnt(:,2) = pnt(:,2) + vol.o(2); - pnt(:,3) = pnt(:,3) + vol.o(3); - end - sens.pnt = pnt; - - case {'bem', 'dipoli', 'asa', 'avo', 'bemcp'} - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % do postprocessing of volume and electrodes in case of BEM model - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - % project the electrodes on the skin and determine the bilinear interpolation matrix - if ~isfield(vol, 'tra') - % determine boundary corresponding with skin and brain - if ~isfield(vol, 'skin') - vol.skin = find_outermost_boundary(vol.bnd); - fprintf('determining skin compartment (%d)\n', vol.skin); - end - if ~isfield(vol, 'source') - vol.source = find_innermost_boundary(vol.bnd); - fprintf('determining source compartment (%d)\n', vol.source); - end - if size(vol.mat,1)~=size(vol.mat,2) && size(vol.mat,1)==length(sens.pnt) - fprintf('electrode transfer and system matrix were already combined\n'); - else - fprintf('projecting electrodes on skin surface\n'); - % compute linear interpolation from triangle vertices towards electrodes - el = project_elec(sens.pnt, vol.bnd(vol.skin).pnt, vol.bnd(vol.skin).tri); - tra = transfer_elec(vol.bnd(vol.skin).pnt, vol.bnd(vol.skin).tri, el); - if size(vol.mat,1)==size(vol.bnd(vol.skin).pnt,1) - % construct the transfer from only the skin vertices towards electrodes - interp = tra; - else - % construct the transfer from all vertices (also brain/skull) towards electrodes - interp = []; - for i=1:length(vol.bnd) - if i==vol.skin - interp = [interp, tra]; - else - interp = [interp, zeros(size(el,1), size(vol.bnd(i).pnt,1))]; - end - end - end - % convert to sparse matrix to speed up the subsequent multiplication - interp = sparse(interp); - % incorporate the linear interpolation matrix and the system matrix into one matrix - % this speeds up the subsequent repeated leadfield computations - fprintf('combining electrode transfer and system matrix\n'); - vol.mat = interp * vol.mat; - % FIXME should I also add the electrode labels to the volume definition? - end - % ensure that the model potential will be average referenced - avg = mean(vol.mat, 1); - vol.mat = vol.mat - repmat(avg, size(vol.mat,1), 1); - end - - case {'openmeeg'} - % do nothing - % in case of openmeeg do nothing because electrodes projection is - % already performed in command line INRIA routines - % FIXME: to be checked the average referencing of the openmeeg tool - % vol.mat = vol.mat; - - otherwise - error('unsupported volume conductor model for EEG'); - end - - % FIXME this needs carefull thought to ensure that the average referencing which is now done here and there, and that the linear interpolation in case of BEM are all dealt with consistently - % % always ensure that there is a linear transfer matrix for - % % rereferencing the EEG potential - % if ~isfield(sens, 'tra'); - % sens.tra = sparse(eye(length(sens.label))); - % end - -end % if iseeg or ismeg - -% determine the skin compartment -if ~isfield(vol, 'skin') - if isfield(vol, 'bnd') - vol.skin = find_outermost_boundary(vol.bnd); - elseif isfield(vol, 'r') && length(vol.r)<=4 - [dum, vol.skin] = max(vol.r); - end -end - -% determine the brain compartment -if ~isfield(vol, 'brain') - if isfield(vol, 'bnd') - vol.brain = find_innermost_boundary(vol.bnd); - elseif isfield(vol, 'r') && length(vol.r)<=4 - [dum, vol.brain] = min(vol.r); - end -end - -% otherwise the voltype assignment to an empty struct below won't work -if isempty(vol) - vol = []; -end - -% this makes them easier to recognise -sens.type = senstype(sens); -vol.type = voltype(vol); diff --git a/external/forwinv/private/project_elec.m b/external/forwinv/private/project_elec.m deleted file mode 100644 index 43961b6..0000000 --- a/external/forwinv/private/project_elec.m +++ /dev/null @@ -1,45 +0,0 @@ -function [el] = project_elec(elc, pnt, tri) - -% PROJECT_ELEC projects electrodes on a triangulated surface -% and returns triangle index, la/mu parameters and distance -% -% [el] = project_elec(elc, pnt, tri) -% -% it returns a Nx4 matrix with [tri, la, mu, dist] for each electrode -% -% See also TRANSFER_ELEC - -% Copyright (C) 1999-2002, Robert Oostenveld -% -% $Log: project_elec.m,v $ -% Revision 1.1 2009/01/21 10:32:38 roboos -% moved from forwinv/* and forwinv/mex/* directory to forwinv/private/* to make the CVS layout consistent with the release version -% -% Revision 1.2 2003/03/11 14:45:37 roberto -% updated help and copyrights -% - -Nelc = size(elc,1); -Npnt = size(pnt,1); -Ntri = size(tri,1); -el = zeros(Nelc, 4); - -for i=1:Nelc - smallest_dist = Inf; - - for j=1:Ntri - [proj, dist] = ptriproj(pnt(tri(j,1),:), pnt(tri(j,2),:), pnt(tri(j,3),:), elc(i,:), 1); - if dist=1 - vol.bnd(1) = read_asa_bnd(fullfile(path, bnd1)); - end - if Nbnd>=2 - vol.bnd(2) = read_asa_bnd(fullfile(path, bnd2)); - end - if Nbnd>=3 - vol.bnd(3) = read_asa_bnd(fullfile(path, bnd3)); - end - if Nbnd>=4 - vol.bnd(4) = read_asa_bnd(fullfile(path, bnd4)); - end - if Nbnd>=5 - error('cannot read more than 4 boundaries'); - end - - % if there is a precomputed matrix, read it from an external file - mat_file = read_asa(fn, 'Matrix', '%s'); - if ~isempty(mat_file) - nr = read_asa(fullfile(path, mat_file), 'NumberRows=', '%d'); - nc = read_asa(fullfile(path, mat_file), 'NumberColumns=', '%d'); - mab_file = read_asa(fullfile(path, mat_file), 'Matrix', '%s'); - fid = fopen(fullfile(path, mab_file), 'rb', 'ieee-le'); - if fid==-1 - error(sprintf('could not open file %s', mab_file)); - else - vol.mat = fread(fid, [nr nc], 'float32'); - fclose(fid); - % remove the factor 2 that ASA assumes in the system matrix - vol.mat = vol.mat/2; - % scale the system matrix corresponding to vertex coordinates in mm - vol.mat = vol.mat*100; - end - end - - vol.cond = cond; -end - -% remove all empty fields -field=fieldnames(vol); -for i=1:length(field) - if isempty(getfield(vol, field{i})) - vol = rmfield(vol, field{i}); - end -end - diff --git a/external/forwinv/private/read_brainvision_pos.m b/external/forwinv/private/read_brainvision_pos.m deleted file mode 100644 index 0152b1f..0000000 --- a/external/forwinv/private/read_brainvision_pos.m +++ /dev/null @@ -1,54 +0,0 @@ -function [elec] = read_brainvision_pos(filename); - -% READ_BRAINVISION_POS reads electrode positions measured with the Polhemus -% tracker in one of the F.C. Donders EEG labs. The polhemus software is actually -% not from Brainvision. -% -% Use as: -% [elec] = read_brainvision_pos(filename) -% -% This returns an electrode structure with -% elec.label cell-array with electrode labels (strings) -% elec.pnt position of each electrode - -% Copyright (C) 2004, Robert Oostenveld -% -% $Log: read_brainvision_pos.m,v $ -% Revision 1.1 2004/03/18 09:34:34 roberto -% also read in the fiducials if present at the end of the file -% - -fid = fopen(filename, 'rt'); -line = fgetl(fid); -Nchan = str2double(line); - -for i=1:Nchan - line = fgetl(fid); - [t, r] = strtok(line); - elec.label{i} = char(t); - elec.pnt(i,:) = sscanf(r, '%f')'; -end -elec.label = elec.label(:); - -try - % read the fiducials - line = fgetl(fid); - [t, r] = strtok(line); - fiducial.label{1} = char(t); - fiducial.pnt(1,:) = sscanf(r, '%f')'; - line = fgetl(fid); - [t, r] = strtok(line); - fiducial.label{2} = char(t); - fiducial.pnt(2,:) = sscanf(r, '%f')'; - line = fgetl(fid); - [t, r] = strtok(line); - fiducial.label{3} = char(t); - fiducial.pnt(3,:) = sscanf(r, '%f')'; - % add the fiducials to the electrode array - elec.label = cat(1, elec.label(:), fiducial.label(:)); - elec.pnt = cat(1, elec.pnt, fiducial.pnt); -catch - % do nothing -end - -fclose(fid); \ No newline at end of file diff --git a/external/forwinv/private/read_bti_hs.m b/external/forwinv/private/read_bti_hs.m deleted file mode 100644 index 7d24bee..0000000 --- a/external/forwinv/private/read_bti_hs.m +++ /dev/null @@ -1,46 +0,0 @@ -function [ output ] = read_hs_file( filename, outfile ) - -%read_hs_file Reads in BTI-Headshape files -% filename: file with the headshape informations -% outfile: if present, a ctf ".shape" file is written -% output: if present, a 3xN matrix containing the headshape-points -% -% (C) 2007 by Thomas Hartmann - -% $Log: read_bti_hs.m,v $ -% Revision 1.2 2007/08/06 09:23:57 roboos -% removed debug output, transposed output to Nx3 -% -% Revision 1.1 2007/08/06 09:03:42 roboos -% version as obtained from Nathan Weisz on 1-Aug-2007 -% - -if nargin == 1 - outfile = []; -end %if - -fid = fopen(filename, 'r', 'b'); -version = fread(fid, 1, '*uint32'); -timestamp = fread(fid, 1, '*int32'); -checksum = fread(fid, 1, '*int32'); -nPoints = fread(fid, 1, '*int32'); - -firstIndexPoint = fread(fid, [3, 5], 'double'); - -points = fread(fid, [3, double(nPoints)], 'double'); - -fclose(fid); - -if(nargout == 1) - output = points'; -end %if - -if(nargin == 2) - fid = fopen(outfile, 'wt'); - fprintf(fid, '%d\n', nPoints); - for i = 1:size(points, 2) - fprintf(fid, '%.3f\t%.3f\t%.3f\n', points(1, i), points(2, i), points(3, i)); - end %for - fclose(fid); - -end %if diff --git a/external/forwinv/private/read_ctf_hdm.m b/external/forwinv/private/read_ctf_hdm.m deleted file mode 100644 index bd2e90a..0000000 --- a/external/forwinv/private/read_ctf_hdm.m +++ /dev/null @@ -1,51 +0,0 @@ -function [vol] = read_ctf_hdm(filename); - -% READ_CTF_HDM reads the head volume conductor model from a *.hdm file -% -% vol = read_ctf_hdm(filename) - -% Copyright (C) 2003, Robert Oostenveld -% -% $Log: read_ctf_hdm.m,v $ -% Revision 1.3 2006/02/09 08:37:23 roboos -% remove the fields SEARCH_RADIUS and HEADSHAPE_FILE regardless of where they are, do not assume that they are at location 1 and 2 (thanks to Tom) -% -% Revision 1.2 2004/06/28 07:32:55 roberto -% added units=cm for the volume model -% -% Revision 1.1 2003/03/24 12:30:42 roberto -% new implementation -% - -ascii = read_ctf_ascii(filename); - -if isfield(ascii, 'MultiSphere_Data') - chans = fieldnames(ascii.MultiSphere_Data); - % remove the fields SEARCH_RADIUS and HEADSHAPE_FILE - chans = chans(~(strcmp(chans, 'SEARCH_RADIUS') | strcmp(chans, 'HEADSHAPE_FILE'))); - for i=1:length(chans) - tmp = getfield(ascii.MultiSphere_Data, chans{i}); - vol.label{i} = chans{i}; - vol.r(i) = tmp(4); - vol.o(i, :) = tmp(1:3); - end - vol.r = vol.r(:); % ensure column vector -elseif isfield(ascii, 'MEG_Sphere') - vol.r = ascii.MEG_Sphere.RADIUS; - vol.o(1) = ascii.MEG_Sphere.ORIGIN_X; - vol.o(2) = ascii.MEG_Sphere.ORIGIN_Y; - vol.o(3) = ascii.MEG_Sphere.ORIGIN_Z; -else - error('no headmodel information found'); -end - -% add the fiducials, these are in raw MRI coordinates -if isfield(ascii, 'Fid_Points') - vol.mri.nas = ascii.Fid_Points.NASION; - vol.mri.lpa = ascii.Fid_Points.LEFT_EAR; - vol.mri.rpa = ascii.Fid_Points.RIGHT_EAR; -end - -% add the units in which the volume conductor is defined -vol.unit = 'cm'; - diff --git a/external/forwinv/private/read_ctf_shape.m b/external/forwinv/private/read_ctf_shape.m deleted file mode 100644 index 68d8702..0000000 --- a/external/forwinv/private/read_ctf_shape.m +++ /dev/null @@ -1,28 +0,0 @@ -function [shape] = read_ctf_shape(filename); - -% READ_CTF_SHAPE reads headshape points and header information -% from a CTF *.shape teh accompanying *.shape_info file. -% -% Use as -% [shape] = read_ctf_shape(filename) -% where filename should have the .shape extension - -% Copyright (C) 2003, Robert Oostenveld -% -% $Log: read_ctf_shape.m,v $ -% Revision 1.1 2003/10/08 15:28:03 roberto -% *** empty log message *** -% - -shape = read_ctf_ascii([filename '_info']); - -if ~strcmp(shape.MRI_Info.COORDINATES, 'HEAD') - warning('points on head shape are NOT in headcoordinates') -end - -fid = fopen(filename, 'rb'); -num = fscanf(fid, '%d', 1); -shape.pnt = fscanf(fid, '%f', inf); -shape.pnt = reshape(shape.pnt, [3 num])'; -fclose(fid); - diff --git a/external/forwinv/private/read_sens.m b/external/forwinv/private/read_sens.m deleted file mode 100644 index f3cb00d..0000000 --- a/external/forwinv/private/read_sens.m +++ /dev/null @@ -1,190 +0,0 @@ -function [sens] = read_sens(filename, varargin) - -% READ_SENS read sensor positions from various manufacturer specific files. -% Currently supported are ASA, BESA, Polhemus and Matlab for EEG -% electrodes and CTF and Neuromag for MEG gradiometers. -% -% Use as -% grad = read_sens(filename, ...) % for gradiometers -% elec = read_sens(filename, ...) % for electrodes -% -% Additional options should be specified in key-value pairs and can be -% 'fileformat' string -% -% An electrode definition contain the following fields -% elec.pnt Nx3 matrix with carthesian (x,y,z) coordinates of each electrodes -% elec.label cell-array of length N with the label of each electrode -% -% A gradiometer definition generally consists of multiple coils per -% channel, e.g.two coils for a 1st order gradiometer in which the -% orientation of the coils is opposite. Each coil is described -% separately and a large "tra" matrix (can be sparse) has to be -% given that defines how the forward computed field is combined over -% the coils to generate the output of each channel. The gradiometer -% definition constsis of the following fields -% grad.pnt Mx3 matrix with the position of each coil -% grad.ori Mx3 matrix with the orientation of each coil -% grad.tra NxM matrix with the weight of each coil into each channel -% grad.label cell-array of length N with the label of each of the channels -% -% See also TRANSFORM_SENS, PREPARE_VOL_SENS, COMPUTE_LEADFIELD - -% Copyright (C) 2005-2008, Robert Oostenveld -% -% $Log: read_sens.m,v $ -% Revision 1.8 2008/04/14 20:51:36 roboos -% added convert_units -% -% Revision 1.7 2008/04/11 16:17:22 roboos -% added polhemus_fil -% -% Revision 1.6 2008/03/20 13:43:14 roboos -% added support for besa_pos -% -% Revision 1.5 2008/03/18 12:34:30 roboos -% fixed bug: added varargin to input arguments, thanks to Juan -% -% Revision 1.4 2008/03/06 09:27:54 roboos -% updated documentation -% -% Revision 1.3 2008/03/05 11:06:11 roboos -% test the presence of the fileio toolbox, needed when this function is included in forwinv -% -% Revision 1.2 2008/03/05 10:54:05 roboos -% added optional argument for fileformat -% some documentation changes -% -% Revision 1.1 2008/01/28 20:10:11 roboos -% new functions based on existing fieldtrip code -% - -% test whether the file exists -if ~exist(filename) - error(sprintf('file ''%s'' does not exist', filename)); -end - -% get the options -fileformat = keyval('fileformat', varargin); - -% determine the filetype -if isempty(fileformat) - fileformat = filetype(filename); -end - -switch fileformat - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % read the content from various files that contain EEG electrode positions - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - case 'asa_elc' - sens = read_asa_elc(filename); - - case 'polhemus_pos' - sens = read_brainvision_pos(filename); - - case 'besa_pos' - tmp = importdata(filename); - if ~isnumeric(tmp) - error('unexpected file format for fileformat=besa_pos') - end - [nchan,nrow] = size(tmp); - if nrow==3 - sens.pnt = tmp; - elseif nrow==9 - pnt1 = tmp(:,1:3); % bottom coil - pnt2 = tmp(:,4:6); % top coil - ori = tmp(:,7:9); % orientation of bottom coil - sens.pnt = [pnt1; pnt2]; - sens.ori = [ori; ori]; - sens.tra = [eye(nchan) -eye(nchan)]; - else - error('unexpected file format for fileformat=besa_pos') - end - [p, f, x] = fileparts(filename); - elpfile = fullfile(p, [f '.elp']); - elafile = fullfile(p, [f '.ela']); - if exist(elpfile, 'file') - warning(sprintf('reading channel labels from %s', elpfile)); - % read the channel names from the accompanying ELP file - lbl = importdata(elpfile); - sens.label = strrep(lbl.textdata(:,2) ,'''', ''); - elseif exist(elafile, 'file') - warning(sprintf('reading channel labels from %s', elafile)); - % read the channel names from the accompanying ELA file - lbl = importdata(elafile); - lbl = strrep(lbl, 'MEG ', ''); % remove the channel type - lbl = strrep(lbl, 'EEG ', ''); % remove the channel type - sens.label = lbl; - else - % the file does not have channel labels in it - warning('creating fake channel names for besa_pos'); - for i=1:nchan - sens.label{i} = sprintf('%03d', i); - end - end - - case 'besa_sfp' - tmp = importdata(filename); - sens.label = tmp.textdata; - sens.pnt = tmp.data; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % gradiometer information is always stored in the header of the MEG dataset - % hence uses the standard fieldtrip/fileio read_header function - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - case {'ctf_ds', 'ctf_res4', 'neuromag_fif', 'yokogawa_ave', 'yokogawa_con', 'yokogawa_raw'} - % check the availability of the required low-level toolbox - % this is required because the read_sens function is also on itself included in the forwinv toolbox - hastoolbox('fileio'); - hdr = read_header(filename); - sens = hdr.grad; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % these are created at the FIL in London with a polhemus tracker - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - case 'polhemus_fil' - [sens.fid, sens.pnt] = read_polhemus_fil(filename, 0, 0); - - % the file does not have channel labels in it - warning('creating fake channel names for polhemus_fil'); - for i=1:nchan - sens.label{i} = sprintf('%03d', i); - end - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % matlab files can contain either electrodes or gradiometers - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - case 'matlab' - matfile = filename; % this solves a problem with the matlab compiler v3 - warning('off', 'MATLAB:load:variableNotFound'); - tmp = load(matfile, 'elec', 'grad', 'sens', 'elc'); - warning('on', 'MATLAB:load:variableNotFound'); - if isfield(tmp, 'grad') - sens = getfield(tmp, 'grad'); - elseif isfield(tmp, 'elec') - sens = getfield(tmp, 'elec'); - elseif isfield(tmp, 'sens') - sens = getfield(tmp, 'sens'); - elseif isfield(tmp, 'elc') - sens = getfield(tmp, 'elc'); - else - error('no electrodes or gradiometers found in Matlab file'); - end - - otherwise - error('unknown fileformat for electrodes or gradiometers'); -end - -if senstype(sens, 'eeg') - % only keep positions and labels in case of EEG electrodes - dum = sens; - sens = []; - sens.pnt = dum.pnt; - sens.label = dum.label; -end - -% this will add the units to the sensor array -sens = convert_units(sens); diff --git a/external/forwinv/private/read_vol.m b/external/forwinv/private/read_vol.m deleted file mode 100644 index 1e71eea..0000000 --- a/external/forwinv/private/read_vol.m +++ /dev/null @@ -1,85 +0,0 @@ -function [vol] = read_vol(filename, varargin) - -% READ_VOL reads a volume conduction model from various manufacturer -% specific files. Currently supported are ASA, CTF, Neuromag, MBFYS -% and Matlab. -% -% Use as -% vol = read_vol(filename, ...) -% -% Additional options should be specified in key-value pairs and can be -% 'fileformat' string -% -% The volume conduction model is represented as a structure, and its -% contents depend on the type of model. -% -% See also TRANSFORM_VOL, PREPARE_VOL_SENS, COMPUTE_LEADFIELD - -% Copyright (C) 2008, Robert Oostenveld -% -% $Log: read_vol.m,v $ -% Revision 1.4 2008/04/14 20:51:19 roboos -% fixed dependency for dipoli/ama -% added convert_units -% -% Revision 1.3 2008/03/06 09:27:54 roboos -% updated documentation -% -% Revision 1.2 2008/01/31 20:15:24 roboos -% added optional fileformat argument -% -% Revision 1.1 2008/01/28 20:10:11 roboos -% new functions based on existing fieldtrip code -% - -% test whether the file exists -if ~exist(filename) - error(sprintf('file ''%s'' does not exist', filename)); -end - -% get the options -fileformat = keyval('fileformat', varargin); - -% determine the filetype -if isempty(fileformat) - fileformat = filetype(filename); -end - -switch fileformat - case 'matlab' - matfile = filename; % this solves a problem with the matlab compiler v3 - warning('off', 'MATLAB:load:variableNotFound'); - tmp = load(matfile, 'vol'); - warning('on', 'MATLAB:load:variableNotFound'); - vol = getfield(tmp, 'vol'); - - case 'ctf_hdm' - vol = read_ctf_hdm(filename); - - case 'asa_vol' - vol = read_asa_vol(filename); - vol.type = 'asa'; - - case 'mbfys_ama' - ama = loadama(filename); - vol = ama2vol(ama); - - case 'neuromag_fif' - % do not read the volume into Matlab, but use external Neuromag toolbox - vol.type = 'neuromag'; - vol.filename = filename; - vol.chansel = []; % this is defined later based on the channels present in the data - % initialize the Neuromag toolbox, this requires a gradfile and hdmfile - fprintf('using Neuromag volume conductor from %s\n', filename); - fprintf('using Neuromag gradiometer definition from %s\n', cfg.gradfile); - megmodel('head', cfg.gradfile, filename); - % read the triangulated boundary from the neuromag BEM model - [vol.bnd.pnt, vol.bnd.tri, vol.bnd.nrm] = loadtri(vol.filename); - vol.bnd.pnt = vol.bnd.pnt*100; % convert to cm - - otherwise - error('unknown fileformat for volume conductor model'); -end - -% this will add the units to the volume conductor model -vol = convert_units(vol); diff --git a/external/forwinv/private/residualvariance.m b/external/forwinv/private/residualvariance.m deleted file mode 100644 index b2cb6f6..0000000 --- a/external/forwinv/private/residualvariance.m +++ /dev/null @@ -1,94 +0,0 @@ -function [dipout] = residualvariance(dip, grad, vol, dat, varargin); - -% RESIDUALVARIANCE scan with a single dipole and computes the RV -% at each grid location -% -% Use as -% [dipout] = residualvariance(dip, grad, vol, dat, ...) - -% Copyright (C) 2004-2006, Robert Oostenveld -% -% $Log: residualvariance.m,v $ -% Revision 1.5 2006/05/10 08:18:21 roboos -% swiched to using keyval() function for getting optional arguments instead of using eval() -% -% Revision 1.4 2005/10/25 08:55:24 roboos -% added some feedback for subspace projection -% changed indentation and some whitespace -% -% Revision 1.3 2004/10/27 16:16:37 roboos -% renamed grid.lbex matrix for subspace projection into grid.subspace (in correspondence with precompute_leadfield) -% transposed the subspace projection matrix -% renamed all occurences of "lbex" (as part of variable names) into "subspace" -% -% Revision 1.2 2004/10/25 16:22:21 roboos -% fixed parsing of optional arguments (key,value-pairs) -% -% Revision 1.1 2004/09/28 14:32:29 roboos -% initial version, implements LBEX -% - -% get the optional settings, or use default value -feedback = keyval('feedback', varargin); if isempty(feedback), feedback = 'text'; end - -% ensure that these are row-vectors -dip.inside = dip.inside(:)'; -dip.outside = dip.outside(:)'; - -Nchan = length(grad.label); -Ndip = length(dip.inside); - -if isfield(dip, 'subspace') - % remember the original data prior to the voxel dependant subspace projection - dat_pre_subspace = dat; - fprintf('using subspace projection\n'); -end - -progress('init', feedback, 'computing inverse'); -for i=1:length(dip.inside) - - progress(i/length(dip.inside), 'computing inverse %d/%d\n', i, length(dip.inside)); - i = dip.inside(i); - - if isfield(dip, 'leadfield') - % reuse the leadfield that was previously computed - lf = dip.leadfield{i}; - else - % compute the leadfield - lf = compute_leadfield(dip.pos(i,:), grad, vol); - end - - if isfield(dip, 'subspace') - % do subspace projection of the forward model - lf = dip.subspace{i} * lf; - % the data and the covariance become voxel dependent due to the projection - dat = dip.subspace{i} * dat_pre_subspace; - end - - % compute spatiotemporal inverse using regional source - lfi = pinv(lf); - mom{i} = lfi * dat; - rv(i) = sum(sum((dat - lf*mom{i}).^2, 1), 2)./sum(sum(dat.^2, 1), 2); - - % for plotting convenience also compute power at each location - % FIXME is this normalization correct? - pow(i) = mean(sum(mom{i}(:).^2, 1)); -end -progress('close'); - -% locations outside the head get assigned an -for i=dip.outside - mom{i} = []; - rv(i) = nan; - pow(i) = nan; -end - -% assign the output data -dipout.mom = mom(:); % ensure that it is a column vector -dipout.rv = rv(:); % ensure that it is a column vector -dipout.pow = pow(:); % ensure that it is a column vector - -% add other descriptive information to the output source model -dipout.pos = dip.pos; -dipout.inside = dip.inside; -dipout.outside = dip.outside; diff --git a/external/forwinv/private/rmsubfield.m b/external/forwinv/private/rmsubfield.m deleted file mode 100644 index f0dd5fc..0000000 --- a/external/forwinv/private/rmsubfield.m +++ /dev/null @@ -1,36 +0,0 @@ -function [s] = rmsubfield(s, f, v); - -% RMSUBFIELD removes the contents of the specified field from a structure -% just like the standard Matlab RMFIELD function, except that you can also -% specify nested fields using a '.' in the fieldname. The nesting can be -% arbitrary deep. -% -% Use as -% s = rmsubfield(s, 'fieldname') -% or as -% s = rmsubfield(s, 'fieldname.subfieldname') -% -% See also SETFIELD, GETSUBFIELD, ISSUBFIELD - -% Copyright (C) 2006, Robert Oostenveld -% -% $Log: rmsubfield.m,v $ -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.1 2006/11/27 15:38:45 roboos -% new implementation -% - -if ~isstr(f) - error('incorrect input argument for fieldname'); -end - -% remove the nested subfield using recursion -[t, f] = strtok(f, '.'); -if any(f=='.') - u = rmsubfield(getfield(s, t), f); - s = setfield(s, t, u); -else - s = rmfield(s, t); -end diff --git a/external/forwinv/private/routlm.c b/external/forwinv/private/routlm.c deleted file mode 100644 index b626284..0000000 --- a/external/forwinv/private/routlm.c +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include "mex.h" -#include "matrix.h" -#include "geometry.h" - -void -mexFunction (int nlhs, mxArray * plhs[], int nrhs, const mxArray * prhs[]) -{ - mxArray *proj; - double la, mu; - double *v1, *v2, *v3, *proj_p; - - if (nrhs != 5) - mexErrMsgTxt ("Invalid number of input arguments"); - - if (mxGetM(prhs[0])!=1 || mxGetN(prhs[0])!=3) - mexErrMsgTxt ("Invalid dimension for input argument 1"); - if (mxGetM(prhs[1])!=1 || mxGetN(prhs[1])!=3) - mexErrMsgTxt ("Invalid dimension for input argument 2"); - if (mxGetM(prhs[2])!=1 || mxGetN(prhs[2])!=3) - mexErrMsgTxt ("Invalid dimension for input argument 3"); - - v1 = mxGetData (prhs[0]); - v2 = mxGetData (prhs[1]); - v3 = mxGetData (prhs[2]); - la = mxGetScalar (prhs[3]); - mu = mxGetScalar (prhs[4]); - - proj = mxCreateDoubleMatrix (1, 3, mxREAL); - proj_p = mxGetData (proj); - - routlm(v1, v2, v3, la, mu, proj_p); - - /* assign the output parameters */ - plhs[0] = proj; - - return; -} - diff --git a/external/forwinv/private/routlm.mexa64 b/external/forwinv/private/routlm.mexa64 deleted file mode 100755 index 9c223ad..0000000 Binary files a/external/forwinv/private/routlm.mexa64 and /dev/null differ diff --git a/external/forwinv/private/routlm.mexglx b/external/forwinv/private/routlm.mexglx deleted file mode 100755 index 1b44201..0000000 Binary files a/external/forwinv/private/routlm.mexglx and /dev/null differ diff --git a/external/forwinv/private/routlm.mexmaci b/external/forwinv/private/routlm.mexmaci deleted file mode 100755 index 0d5e7a1..0000000 Binary files a/external/forwinv/private/routlm.mexmaci and /dev/null differ diff --git a/external/forwinv/private/routlm.mexmaci64 b/external/forwinv/private/routlm.mexmaci64 deleted file mode 100755 index 0c67fcd..0000000 Binary files a/external/forwinv/private/routlm.mexmaci64 and /dev/null differ diff --git a/external/forwinv/private/routlm.mexw32 b/external/forwinv/private/routlm.mexw32 deleted file mode 100644 index 70df638..0000000 Binary files a/external/forwinv/private/routlm.mexw32 and /dev/null differ diff --git a/external/forwinv/private/routlm.mexw64 b/external/forwinv/private/routlm.mexw64 deleted file mode 100644 index 2f997f0..0000000 Binary files a/external/forwinv/private/routlm.mexw64 and /dev/null differ diff --git a/external/forwinv/private/rv.m b/external/forwinv/private/rv.m deleted file mode 100644 index 35f9b3e..0000000 --- a/external/forwinv/private/rv.m +++ /dev/null @@ -1,15 +0,0 @@ -function [retval] = rv(d1, d2); - -% RV returns the relative residual variance between measured and simulated data -% -% rv = rv(measured, simulated) - -% Copyright (C) 1999, Robert Oostenveld -% -% $Log: rv.m,v $ -% Revision 1.2 2003/03/11 14:45:37 roberto -% updated help and copyrights -% - -retval = sum((d1-d2).^2) ./ sum(d1.^2); - diff --git a/external/forwinv/private/senslabel.m b/external/forwinv/private/senslabel.m deleted file mode 100644 index 45c59a5..0000000 --- a/external/forwinv/private/senslabel.m +++ /dev/null @@ -1,2018 +0,0 @@ -function label = senslabel(type) - -% SENLABEL returns a list of sensor labels given the MEEG system type -% -% Use as -% label = senslabel(type) -% -% The input type can be any of the following -% 'biosemi64' -% 'biosemi128' -% 'biosemi256' -% 'bti148' -% 'bti148_planar' -% 'bti248' -% 'bti248_planar' -% 'btiref' -% 'ctf151' -% 'ctf151_planar' -% 'ctf275' -% 'ctf275_planar' -% 'ctfheadloc' -% 'ctfref' -% 'eeg1005' -% 'eeg1010' -% 'eeg1020' -% 'egi128' -% 'egi256' -% 'egi32' -% 'egi64' -% 'ext1020' -% 'neuromag122' -% 'neuromag122alt' -% 'neuromag306' -% 'neuromag306alt' -% 'itab153' -% 'itab153_planar' -% -% See also SENSTYPE, CHANNELSELECTION - -% FIXME one channel is missing for ctf275 - -% Copyright (C) 2007-2008, Robert Oostenveld -% Copyright (C) 2008, Vladimir Litvak -% -% $Log: senslabel.m,v $ -% Revision 1.6 2009/10/16 12:27:53 roboos -% some small changes pertaining to the itab/chieti format -% -% Revision 1.4 2009/07/29 07:07:59 roboos -% use caching of input and output arguments to speed up the handling of multiple calls with the same input argument -% -% Revision 1.3 2009/06/19 16:51:50 vlalit -% Added biosemi64 system of Diane Whitmer, I don't know how generic it is. -% -% Revision 1.2 2009/05/07 13:34:09 roboos -% added ctf64 -% -% Revision 1.1 2009/01/21 10:32:38 roboos -% moved from forwinv/* and forwinv/mex/* directory to forwinv/private/* to make the CVS layout consistent with the release version -% -% Revision 1.4 2008/09/17 19:35:07 roboos -% ensure that it returns column array -% -% Revision 1.3 2008/09/10 09:12:11 roboos -% added alternative definition of channel names without a space in the label for neuromag 122 and 306 -% -% Revision 1.2 2008/09/10 08:33:36 roboos -% speeded up with factor 5 by performing an initial check on the desired type and subsequently only defining the related variables -% -% Revision 1.1 2008/09/10 07:53:27 roboos -% moved definition of channel label sets to seperate function -% - -% these are for remembering the type on subsequent calls with the same input arguments -persistent previous_argin previous_argout - -if nargin<1 - % ensure that all input arguments are defined - type = []; -end - -current_argin = {type}; -if isequal(current_argin, previous_argin) - % don't do the type detection again, but return the previous values from cache - label = previous_argout{1}; - return -end - -% prevent defining all possible labels if not needed -isbiosemi = ~isempty(regexp(type, '^biosemi', 'once')); -isbti = ~isempty(regexp(type, '^bti', 'once')); -isctf = ~isempty(regexp(type, '^ctf', 'once')); -iseeg = ~isempty(regexp(type, '^eeg', 'once')); -isext = ~isempty(regexp(type, '^ext', 'once')); -isegi = ~isempty(regexp(type, '^egi', 'once')); -isneuromag = ~isempty(regexp(type, '^neuromag', 'once')); -isitab = ~isempty(regexp(type, '^itab', 'once')); - -if isbti - btiref = { - 'MRxA' - 'MRyA' - 'MRzA' - 'MLxA' - 'MLyA' - 'MLzA' - 'MCxA' - 'MCyA' - 'MCzA' - 'MRxaA' - 'MRyaA' - 'MRzaA' - 'MLxaA' - 'MLyaA' - 'MLzaA' - 'MCxaA' - 'MCyaA' - 'MCzaA' - 'GxxA' - 'GyxA' - 'GzxA' - 'GyyA' - 'GzyA' - }; - - bti148 = cell(148,1); - for i=1:148 - bti148{i,1} = sprintf('A%d', i); - end - - bti148_planar = cell(148,1); - for i=1:148 - bti148_planar{i,1} = sprintf('A%d_dH', i); - bti148_planar{i,2} = sprintf('A%d_dV', i); - end - - bti248 = cell(248,1); - for i=1:248 - bti248{i,1} = sprintf('A%d', i); - end - - bti248_planar = cell(248,2); - for i=1:248 - bti248_planar{i,1} = sprintf('A%d_dH', i); - bti248_planar{i,2} = sprintf('A%d_dV', i); - end -end % if isbti - -if isctf - ctfref = { - 'BG1' - 'BG2' - 'BG3' - 'BP1' - 'BP2' - 'BP3' - 'BR1' - 'BR2' - 'BR3' - 'G11' - 'G12' - 'G13' - 'G22' - 'G23' - 'P11' - 'P12' - 'P13' - 'P22' - 'P23' - 'Q11' - 'Q12' - 'Q13' - 'Q22' - 'Q23' - 'R11' - 'R12' - 'R13' - 'R22' - 'R23' - }; - - ctfheadloc = { - 'HLC0011' - 'HLC0012' - 'HLC0013' - 'HLC0021' - 'HLC0022' - 'HLC0023' - 'HLC0031' - 'HLC0032' - 'HLC0033' - 'HLC0018' - 'HLC0028' - 'HLC0038' - 'HLC0014' - 'HLC0015' - 'HLC0016' - 'HLC0017' - 'HLC0024' - 'HLC0025' - 'HLC0026' - 'HLC0027' - 'HLC0034' - 'HLC0035' - 'HLC0036' - 'HLC0037' - }; - - ctf64 = { - 'SL11' - 'SL12' - 'SL13' - 'SL14' - 'SL15' - 'SL16' - 'SL17' - 'SL18' - 'SL19' - 'SL21' - 'SL22' - 'SL23' - 'SL24' - 'SL25' - 'SL26' - 'SL27' - 'SL28' - 'SL29' - 'SL31' - 'SL32' - 'SL33' - 'SL34' - 'SL35' - 'SL41' - 'SL42' - 'SL43' - 'SL44' - 'SL45' - 'SL46' - 'SL47' - 'SL51' - 'SL52' - 'SR11' - 'SR12' - 'SR13' - 'SR14' - 'SR15' - 'SR16' - 'SR17' - 'SR18' - 'SR19' - 'SR21' - 'SR22' - 'SR23' - 'SR24' - 'SR25' - 'SR26' - 'SR27' - 'SR28' - 'SR29' - 'SR31' - 'SR32' - 'SR33' - 'SR34' - 'SR35' - 'SR41' - 'SR42' - 'SR43' - 'SR44' - 'SR45' - 'SR46' - 'SR47' - 'SR51' - 'SR52' - }; - - ctf151 = { - 'MLC11' - 'MLC12' - 'MLC13' - 'MLC14' - 'MLC15' - 'MLC21' - 'MLC22' - 'MLC23' - 'MLC24' - 'MLC31' - 'MLC32' - 'MLC33' - 'MLC41' - 'MLC42' - 'MLC43' - 'MLF11' - 'MLF12' - 'MLF21' - 'MLF22' - 'MLF23' - 'MLF31' - 'MLF32' - 'MLF33' - 'MLF34' - 'MLF41' - 'MLF42' - 'MLF43' - 'MLF44' - 'MLF45' - 'MLF51' - 'MLF52' - 'MLO11' - 'MLO12' - 'MLO21' - 'MLO22' - 'MLO31' - 'MLO32' - 'MLO33' - 'MLO41' - 'MLO42' - 'MLO43' - 'MLP11' - 'MLP12' - 'MLP13' - 'MLP21' - 'MLP22' - 'MLP31' - 'MLP32' - 'MLP33' - 'MLP34' - 'MLT11' - 'MLT12' - 'MLT13' - 'MLT14' - 'MLT15' - 'MLT16' - 'MLT21' - 'MLT22' - 'MLT23' - 'MLT24' - 'MLT25' - 'MLT26' - 'MLT31' - 'MLT32' - 'MLT33' - 'MLT34' - 'MLT35' - 'MLT41' - 'MLT42' - 'MLT43' - 'MLT44' - 'MRC11' - 'MRC12' - 'MRC13' - 'MRC14' - 'MRC15' - 'MRC21' - 'MRC22' - 'MRC23' - 'MRC24' - 'MRC31' - 'MRC32' - 'MRC33' - 'MRC41' - 'MRC42' - 'MRC43' - 'MRF11' - 'MRF12' - 'MRF21' - 'MRF22' - 'MRF23' - 'MRF31' - 'MRF32' - 'MRF33' - 'MRF34' - 'MRF41' - 'MRF42' - 'MRF43' - 'MRF44' - 'MRF45' - 'MRF51' - 'MRF52' - 'MRO11' - 'MRO12' - 'MRO21' - 'MRO22' - 'MRO31' - 'MRO32' - 'MRO33' - 'MRO41' - 'MRO42' - 'MRO43' - 'MRP11' - 'MRP12' - 'MRP13' - 'MRP21' - 'MRP22' - 'MRP31' - 'MRP32' - 'MRP33' - 'MRP34' - 'MRT11' - 'MRT12' - 'MRT13' - 'MRT14' - 'MRT15' - 'MRT16' - 'MRT21' - 'MRT22' - 'MRT23' - 'MRT24' - 'MRT25' - 'MRT26' - 'MRT31' - 'MRT32' - 'MRT33' - 'MRT34' - 'MRT35' - 'MRT41' - 'MRT42' - 'MRT43' - 'MRT44' - 'MZC01' - 'MZC02' - 'MZF01' - 'MZF02' - 'MZF03' - 'MZO01' - 'MZO02' - 'MZP01' - 'MZP02' - }; - - ctf151_planar = cell(151, 2); - for i=1:151 - ctf151_planar{i,1} = sprintf('%s_dH', ctf151{i}); - ctf151_planar{i,2} = sprintf('%s_dV', ctf151{i}); - end - - ctf275 = { - 'MLC11' - 'MLC12' - 'MLC13' - 'MLC14' - 'MLC15' - 'MLC16' - 'MLC17' - 'MLC21' - 'MLC22' - 'MLC23' - 'MLC24' - 'MLC25' - 'MLC31' - 'MLC32' - 'MLC41' - 'MLC42' - 'MLC51' - 'MLC52' - 'MLC53' - 'MLC54' - 'MLC55' - 'MLC61' - 'MLC62' - 'MLC63' - 'MLF11' - 'MLF12' - 'MLF13' - 'MLF14' - 'MLF21' - 'MLF22' - 'MLF23' - 'MLF24' - 'MLF25' - 'MLF31' - 'MLF32' - 'MLF33' - 'MLF34' - 'MLF35' - 'MLF41' - 'MLF42' - 'MLF43' - 'MLF44' - 'MLF45' - 'MLF46' - 'MLF51' - 'MLF52' - 'MLF53' - 'MLF54' - 'MLF55' - 'MLF56' - 'MLF61' - 'MLF62' - 'MLF63' - 'MLF64' - 'MLF65' - 'MLF66' - 'MLF67' - 'MLO11' - 'MLO12' - 'MLO13' - 'MLO14' - 'MLO21' - 'MLO22' - 'MLO23' - 'MLO24' - 'MLO31' - 'MLO32' - 'MLO33' - 'MLO34' - 'MLO41' - 'MLO42' - 'MLO43' - 'MLO44' - 'MLO51' - 'MLO52' - 'MLO53' - 'MLP11' - 'MLP12' - 'MLP21' - 'MLP22' - 'MLP23' - 'MLP31' - 'MLP32' - 'MLP33' - 'MLP34' - 'MLP35' - 'MLP41' - 'MLP42' - 'MLP43' - 'MLP44' - 'MLP45' - 'MLP51' - 'MLP52' - 'MLP53' - 'MLP54' - 'MLP55' - 'MLP56' - 'MLP57' - 'MLT11' - 'MLT12' - 'MLT13' - 'MLT14' - 'MLT15' - 'MLT16' - 'MLT21' - 'MLT22' - 'MLT23' - 'MLT24' - 'MLT25' - 'MLT26' - 'MLT27' - 'MLT31' - 'MLT32' - 'MLT33' - 'MLT34' - 'MLT35' - 'MLT36' - 'MLT37' - 'MLT41' - 'MLT42' - 'MLT43' - 'MLT44' - 'MLT45' - 'MLT46' - 'MLT47' - 'MLT51' - 'MLT52' - 'MLT53' - 'MLT54' - 'MLT55' - 'MLT56' - 'MLT57' - 'MRC11' - 'MRC12' - 'MRC13' - 'MRC14' - 'MRC15' - 'MRC16' - 'MRC17' - 'MRC21' - 'MRC22' - 'MRC23' - 'MRC24' - 'MRC25' - 'MRC31' - 'MRC32' - 'MRC41' - 'MRC42' - 'MRC51' - 'MRC52' - 'MRC53' - 'MRC54' - 'MRC55' - 'MRC61' - 'MRC62' - 'MRC63' - 'MRF11' - 'MRF12' - 'MRF13' - 'MRF14' - 'MRF21' - 'MRF22' - 'MRF23' - 'MRF24' - 'MRF25' - 'MRF31' - 'MRF32' - 'MRF33' - 'MRF34' - 'MRF35' - 'MRF41' - 'MRF42' - 'MRF43' - 'MRF44' - 'MRF45' - 'MRF46' - 'MRF51' - 'MRF52' - 'MRF53' - 'MRF54' - 'MRF55' - 'MRF56' - 'MRF61' - 'MRF62' - 'MRF63' - 'MRF64' - 'MRF65' - 'MRF66' - 'MRF67' - 'MRO11' - 'MRO12' - 'MRO13' - 'MRO14' - 'MRO21' - 'MRO22' - 'MRO23' - 'MRO24' - 'MRO31' - 'MRO32' - 'MRO33' - 'MRO34' - 'MRO41' - 'MRO42' - 'MRO43' - 'MRO44' - 'MRO51' - 'MRO52' - 'MRO53' - 'MRP11' - 'MRP12' - 'MRP21' - 'MRP22' - 'MRP23' - 'MRP32' - 'MRP33' - 'MRP34' - 'MRP35' - 'MRP41' - 'MRP42' - 'MRP43' - 'MRP44' - 'MRP45' - 'MRP51' - 'MRP52' - 'MRP53' - 'MRP54' - 'MRP55' - 'MRP56' - 'MRP57' - 'MRT11' - 'MRT12' - 'MRT13' - 'MRT14' - 'MRT15' - 'MRT16' - 'MRT21' - 'MRT22' - 'MRT23' - 'MRT24' - 'MRT25' - 'MRT26' - 'MRT27' - 'MRT31' - 'MRT32' - 'MRT33' - 'MRT34' - 'MRT35' - 'MRT36' - 'MRT37' - 'MRT41' - 'MRT42' - 'MRT43' - 'MRT44' - 'MRT45' - 'MRT46' - 'MRT47' - 'MRT51' - 'MRT52' - 'MRT53' - 'MRT54' - 'MRT55' - 'MRT56' - 'MRT57' - 'MZC01' - 'MZC02' - 'MZC03' - 'MZC04' - 'MZF01' - 'MZF02' - 'MZF03' - 'MZO01' - 'MZO02' - 'MZO03' - 'MZP01' - }; - - % f.ck, apparently one channel is missing - ctf275_planar = cell(274,2); - for i=1:274 - ctf275_planar{i,1} = sprintf('%s_dH', ctf275{i}); - ctf275_planar{i,2} = sprintf('%s_dV', ctf275{i}); - end -end % if issctf - -if isneuromag - neuromag122 = { - 'MEG 001' 'MEG 002' - 'MEG 003' 'MEG 004' - 'MEG 005' 'MEG 006' - 'MEG 007' 'MEG 008' - 'MEG 009' 'MEG 010' - 'MEG 011' 'MEG 012' - 'MEG 013' 'MEG 014' - 'MEG 015' 'MEG 016' - 'MEG 017' 'MEG 018' - 'MEG 019' 'MEG 020' - 'MEG 021' 'MEG 022' - 'MEG 023' 'MEG 024' - 'MEG 025' 'MEG 026' - 'MEG 027' 'MEG 028' - 'MEG 029' 'MEG 030' - 'MEG 031' 'MEG 032' - 'MEG 033' 'MEG 034' - 'MEG 035' 'MEG 036' - 'MEG 037' 'MEG 038' - 'MEG 039' 'MEG 040' - 'MEG 041' 'MEG 042' - 'MEG 043' 'MEG 044' - 'MEG 045' 'MEG 046' - 'MEG 047' 'MEG 048' - 'MEG 049' 'MEG 050' - 'MEG 051' 'MEG 052' - 'MEG 053' 'MEG 054' - 'MEG 055' 'MEG 056' - 'MEG 057' 'MEG 058' - 'MEG 059' 'MEG 060' - 'MEG 061' 'MEG 062' - 'MEG 063' 'MEG 064' - 'MEG 065' 'MEG 066' - 'MEG 067' 'MEG 068' - 'MEG 069' 'MEG 070' - 'MEG 071' 'MEG 072' - 'MEG 073' 'MEG 074' - 'MEG 075' 'MEG 076' - 'MEG 077' 'MEG 078' - 'MEG 079' 'MEG 080' - 'MEG 081' 'MEG 082' - 'MEG 083' 'MEG 084' - 'MEG 085' 'MEG 086' - 'MEG 087' 'MEG 088' - 'MEG 089' 'MEG 090' - 'MEG 091' 'MEG 092' - 'MEG 093' 'MEG 094' - 'MEG 095' 'MEG 096' - 'MEG 097' 'MEG 098' - 'MEG 099' 'MEG 100' - 'MEG 101' 'MEG 102' - 'MEG 103' 'MEG 104' - 'MEG 105' 'MEG 106' - 'MEG 107' 'MEG 108' - 'MEG 109' 'MEG 110' - 'MEG 111' 'MEG 112' - 'MEG 113' 'MEG 114' - 'MEG 115' 'MEG 116' - 'MEG 117' 'MEG 118' - 'MEG 119' 'MEG 120' - 'MEG 121' 'MEG 122' - }; - - % this is an alternative set of labels without a space in them - neuromag122alt = { - 'MEG001' 'MEG002' - 'MEG003' 'MEG004' - 'MEG005' 'MEG006' - 'MEG007' 'MEG008' - 'MEG009' 'MEG010' - 'MEG011' 'MEG012' - 'MEG013' 'MEG014' - 'MEG015' 'MEG016' - 'MEG017' 'MEG018' - 'MEG019' 'MEG020' - 'MEG021' 'MEG022' - 'MEG023' 'MEG024' - 'MEG025' 'MEG026' - 'MEG027' 'MEG028' - 'MEG029' 'MEG030' - 'MEG031' 'MEG032' - 'MEG033' 'MEG034' - 'MEG035' 'MEG036' - 'MEG037' 'MEG038' - 'MEG039' 'MEG040' - 'MEG041' 'MEG042' - 'MEG043' 'MEG044' - 'MEG045' 'MEG046' - 'MEG047' 'MEG048' - 'MEG049' 'MEG050' - 'MEG051' 'MEG052' - 'MEG053' 'MEG054' - 'MEG055' 'MEG056' - 'MEG057' 'MEG058' - 'MEG059' 'MEG060' - 'MEG061' 'MEG062' - 'MEG063' 'MEG064' - 'MEG065' 'MEG066' - 'MEG067' 'MEG068' - 'MEG069' 'MEG070' - 'MEG071' 'MEG072' - 'MEG073' 'MEG074' - 'MEG075' 'MEG076' - 'MEG077' 'MEG078' - 'MEG079' 'MEG080' - 'MEG081' 'MEG082' - 'MEG083' 'MEG084' - 'MEG085' 'MEG086' - 'MEG087' 'MEG088' - 'MEG089' 'MEG090' - 'MEG091' 'MEG092' - 'MEG093' 'MEG094' - 'MEG095' 'MEG096' - 'MEG097' 'MEG098' - 'MEG099' 'MEG100' - 'MEG101' 'MEG102' - 'MEG103' 'MEG104' - 'MEG105' 'MEG106' - 'MEG107' 'MEG108' - 'MEG109' 'MEG110' - 'MEG111' 'MEG112' - 'MEG113' 'MEG114' - 'MEG115' 'MEG116' - 'MEG117' 'MEG118' - 'MEG119' 'MEG120' - 'MEG121' 'MEG122' - }; - - neuromag306 = { - 'MEG 0113' 'MEG 0112' 'MEG 0111' - 'MEG 0122' 'MEG 0123' 'MEG 0121' - 'MEG 0132' 'MEG 0133' 'MEG 0131' - 'MEG 0143' 'MEG 0142' 'MEG 0141' - 'MEG 0213' 'MEG 0212' 'MEG 0211' - 'MEG 0222' 'MEG 0223' 'MEG 0221' - 'MEG 0232' 'MEG 0233' 'MEG 0231' - 'MEG 0243' 'MEG 0242' 'MEG 0241' - 'MEG 0313' 'MEG 0312' 'MEG 0311' - 'MEG 0322' 'MEG 0323' 'MEG 0321' - 'MEG 0333' 'MEG 0332' 'MEG 0331' - 'MEG 0343' 'MEG 0342' 'MEG 0341' - 'MEG 0413' 'MEG 0412' 'MEG 0411' - 'MEG 0422' 'MEG 0423' 'MEG 0421' - 'MEG 0432' 'MEG 0433' 'MEG 0431' - 'MEG 0443' 'MEG 0442' 'MEG 0441' - 'MEG 0513' 'MEG 0512' 'MEG 0511' - 'MEG 0523' 'MEG 0522' 'MEG 0521' - 'MEG 0532' 'MEG 0533' 'MEG 0531' - 'MEG 0542' 'MEG 0543' 'MEG 0541' - 'MEG 0613' 'MEG 0612' 'MEG 0611' - 'MEG 0622' 'MEG 0623' 'MEG 0621' - 'MEG 0633' 'MEG 0632' 'MEG 0631' - 'MEG 0642' 'MEG 0643' 'MEG 0641' - 'MEG 0713' 'MEG 0712' 'MEG 0711' - 'MEG 0723' 'MEG 0722' 'MEG 0721' - 'MEG 0733' 'MEG 0732' 'MEG 0731' - 'MEG 0743' 'MEG 0742' 'MEG 0741' - 'MEG 0813' 'MEG 0812' 'MEG 0811' - 'MEG 0822' 'MEG 0823' 'MEG 0821' - 'MEG 0913' 'MEG 0912' 'MEG 0911' - 'MEG 0923' 'MEG 0922' 'MEG 0921' - 'MEG 0932' 'MEG 0933' 'MEG 0931' - 'MEG 0942' 'MEG 0943' 'MEG 0941' - 'MEG 1013' 'MEG 1012' 'MEG 1011' - 'MEG 1023' 'MEG 1022' 'MEG 1021' - 'MEG 1032' 'MEG 1033' 'MEG 1031' - 'MEG 1043' 'MEG 1042' 'MEG 1041' - 'MEG 1112' 'MEG 1113' 'MEG 1111' - 'MEG 1123' 'MEG 1122' 'MEG 1121' - 'MEG 1133' 'MEG 1132' 'MEG 1131' - 'MEG 1142' 'MEG 1143' 'MEG 1141' - 'MEG 1213' 'MEG 1212' 'MEG 1211' - 'MEG 1223' 'MEG 1222' 'MEG 1221' - 'MEG 1232' 'MEG 1233' 'MEG 1231' - 'MEG 1243' 'MEG 1242' 'MEG 1241' - 'MEG 1312' 'MEG 1313' 'MEG 1311' - 'MEG 1323' 'MEG 1322' 'MEG 1321' - 'MEG 1333' 'MEG 1332' 'MEG 1331' - 'MEG 1342' 'MEG 1343' 'MEG 1341' - 'MEG 1412' 'MEG 1413' 'MEG 1411' - 'MEG 1423' 'MEG 1422' 'MEG 1421' - 'MEG 1433' 'MEG 1432' 'MEG 1431' - 'MEG 1442' 'MEG 1443' 'MEG 1441' - 'MEG 1512' 'MEG 1513' 'MEG 1511' - 'MEG 1522' 'MEG 1523' 'MEG 1521' - 'MEG 1533' 'MEG 1532' 'MEG 1531' - 'MEG 1543' 'MEG 1542' 'MEG 1541' - 'MEG 1613' 'MEG 1612' 'MEG 1611' - 'MEG 1622' 'MEG 1623' 'MEG 1621' - 'MEG 1632' 'MEG 1633' 'MEG 1631' - 'MEG 1643' 'MEG 1642' 'MEG 1641' - 'MEG 1713' 'MEG 1712' 'MEG 1711' - 'MEG 1722' 'MEG 1723' 'MEG 1721' - 'MEG 1732' 'MEG 1733' 'MEG 1731' - 'MEG 1743' 'MEG 1742' 'MEG 1741' - 'MEG 1813' 'MEG 1812' 'MEG 1811' - 'MEG 1822' 'MEG 1823' 'MEG 1821' - 'MEG 1832' 'MEG 1833' 'MEG 1831' - 'MEG 1843' 'MEG 1842' 'MEG 1841' - 'MEG 1912' 'MEG 1913' 'MEG 1911' - 'MEG 1923' 'MEG 1922' 'MEG 1921' - 'MEG 1932' 'MEG 1933' 'MEG 1931' - 'MEG 1943' 'MEG 1942' 'MEG 1941' - 'MEG 2013' 'MEG 2012' 'MEG 2011' - 'MEG 2023' 'MEG 2022' 'MEG 2021' - 'MEG 2032' 'MEG 2033' 'MEG 2031' - 'MEG 2042' 'MEG 2043' 'MEG 2041' - 'MEG 2113' 'MEG 2112' 'MEG 2111' - 'MEG 2122' 'MEG 2123' 'MEG 2121' - 'MEG 2133' 'MEG 2132' 'MEG 2131' - 'MEG 2143' 'MEG 2142' 'MEG 2141' - 'MEG 2212' 'MEG 2213' 'MEG 2211' - 'MEG 2223' 'MEG 2222' 'MEG 2221' - 'MEG 2233' 'MEG 2232' 'MEG 2231' - 'MEG 2242' 'MEG 2243' 'MEG 2241' - 'MEG 2312' 'MEG 2313' 'MEG 2311' - 'MEG 2323' 'MEG 2322' 'MEG 2321' - 'MEG 2332' 'MEG 2333' 'MEG 2331' - 'MEG 2343' 'MEG 2342' 'MEG 2341' - 'MEG 2412' 'MEG 2413' 'MEG 2411' - 'MEG 2423' 'MEG 2422' 'MEG 2421' - 'MEG 2433' 'MEG 2432' 'MEG 2431' - 'MEG 2442' 'MEG 2443' 'MEG 2441' - 'MEG 2512' 'MEG 2513' 'MEG 2511' - 'MEG 2522' 'MEG 2523' 'MEG 2521' - 'MEG 2533' 'MEG 2532' 'MEG 2531' - 'MEG 2543' 'MEG 2542' 'MEG 2541' - 'MEG 2612' 'MEG 2613' 'MEG 2611' - 'MEG 2623' 'MEG 2622' 'MEG 2621' - 'MEG 2633' 'MEG 2632' 'MEG 2631' - 'MEG 2642' 'MEG 2643' 'MEG 2641' - }; - - % this is an alternative set of labels without a space in them - neuromag306alt = { - 'MEG0113' 'MEG0112' 'MEG0111' - 'MEG0122' 'MEG0123' 'MEG0121' - 'MEG0132' 'MEG0133' 'MEG0131' - 'MEG0143' 'MEG0142' 'MEG0141' - 'MEG0213' 'MEG0212' 'MEG0211' - 'MEG0222' 'MEG0223' 'MEG0221' - 'MEG0232' 'MEG0233' 'MEG0231' - 'MEG0243' 'MEG0242' 'MEG0241' - 'MEG0313' 'MEG0312' 'MEG0311' - 'MEG0322' 'MEG0323' 'MEG0321' - 'MEG0333' 'MEG0332' 'MEG0331' - 'MEG0343' 'MEG0342' 'MEG0341' - 'MEG0413' 'MEG0412' 'MEG0411' - 'MEG0422' 'MEG0423' 'MEG0421' - 'MEG0432' 'MEG0433' 'MEG0431' - 'MEG0443' 'MEG0442' 'MEG0441' - 'MEG0513' 'MEG0512' 'MEG0511' - 'MEG0523' 'MEG0522' 'MEG0521' - 'MEG0532' 'MEG0533' 'MEG0531' - 'MEG0542' 'MEG0543' 'MEG0541' - 'MEG0613' 'MEG0612' 'MEG0611' - 'MEG0622' 'MEG0623' 'MEG0621' - 'MEG0633' 'MEG0632' 'MEG0631' - 'MEG0642' 'MEG0643' 'MEG0641' - 'MEG0713' 'MEG0712' 'MEG0711' - 'MEG0723' 'MEG0722' 'MEG0721' - 'MEG0733' 'MEG0732' 'MEG0731' - 'MEG0743' 'MEG0742' 'MEG0741' - 'MEG0813' 'MEG0812' 'MEG0811' - 'MEG0822' 'MEG0823' 'MEG0821' - 'MEG0913' 'MEG0912' 'MEG0911' - 'MEG0923' 'MEG0922' 'MEG0921' - 'MEG0932' 'MEG0933' 'MEG0931' - 'MEG0942' 'MEG0943' 'MEG0941' - 'MEG1013' 'MEG1012' 'MEG1011' - 'MEG1023' 'MEG1022' 'MEG1021' - 'MEG1032' 'MEG1033' 'MEG1031' - 'MEG1043' 'MEG1042' 'MEG1041' - 'MEG1112' 'MEG1113' 'MEG1111' - 'MEG1123' 'MEG1122' 'MEG1121' - 'MEG1133' 'MEG1132' 'MEG1131' - 'MEG1142' 'MEG1143' 'MEG1141' - 'MEG1213' 'MEG1212' 'MEG1211' - 'MEG1223' 'MEG1222' 'MEG1221' - 'MEG1232' 'MEG1233' 'MEG1231' - 'MEG1243' 'MEG1242' 'MEG1241' - 'MEG1312' 'MEG1313' 'MEG1311' - 'MEG1323' 'MEG1322' 'MEG1321' - 'MEG1333' 'MEG1332' 'MEG1331' - 'MEG1342' 'MEG1343' 'MEG1341' - 'MEG1412' 'MEG1413' 'MEG1411' - 'MEG1423' 'MEG1422' 'MEG1421' - 'MEG1433' 'MEG1432' 'MEG1431' - 'MEG1442' 'MEG1443' 'MEG1441' - 'MEG1512' 'MEG1513' 'MEG1511' - 'MEG1522' 'MEG1523' 'MEG1521' - 'MEG1533' 'MEG1532' 'MEG1531' - 'MEG1543' 'MEG1542' 'MEG1541' - 'MEG1613' 'MEG1612' 'MEG1611' - 'MEG1622' 'MEG1623' 'MEG1621' - 'MEG1632' 'MEG1633' 'MEG1631' - 'MEG1643' 'MEG1642' 'MEG1641' - 'MEG1713' 'MEG1712' 'MEG1711' - 'MEG1722' 'MEG1723' 'MEG1721' - 'MEG1732' 'MEG1733' 'MEG1731' - 'MEG1743' 'MEG1742' 'MEG1741' - 'MEG1813' 'MEG1812' 'MEG1811' - 'MEG1822' 'MEG1823' 'MEG1821' - 'MEG1832' 'MEG1833' 'MEG1831' - 'MEG1843' 'MEG1842' 'MEG1841' - 'MEG1912' 'MEG1913' 'MEG1911' - 'MEG1923' 'MEG1922' 'MEG1921' - 'MEG1932' 'MEG1933' 'MEG1931' - 'MEG1943' 'MEG1942' 'MEG1941' - 'MEG2013' 'MEG2012' 'MEG2011' - 'MEG2023' 'MEG2022' 'MEG2021' - 'MEG2032' 'MEG2033' 'MEG2031' - 'MEG2042' 'MEG2043' 'MEG2041' - 'MEG2113' 'MEG2112' 'MEG2111' - 'MEG2122' 'MEG2123' 'MEG2121' - 'MEG2133' 'MEG2132' 'MEG2131' - 'MEG2143' 'MEG2142' 'MEG2141' - 'MEG2212' 'MEG2213' 'MEG2211' - 'MEG2223' 'MEG2222' 'MEG2221' - 'MEG2233' 'MEG2232' 'MEG2231' - 'MEG2242' 'MEG2243' 'MEG2241' - 'MEG2312' 'MEG2313' 'MEG2311' - 'MEG2323' 'MEG2322' 'MEG2321' - 'MEG2332' 'MEG2333' 'MEG2331' - 'MEG2343' 'MEG2342' 'MEG2341' - 'MEG2412' 'MEG2413' 'MEG2411' - 'MEG2423' 'MEG2422' 'MEG2421' - 'MEG2433' 'MEG2432' 'MEG2431' - 'MEG2442' 'MEG2443' 'MEG2441' - 'MEG2512' 'MEG2513' 'MEG2511' - 'MEG2522' 'MEG2523' 'MEG2521' - 'MEG2533' 'MEG2532' 'MEG2531' - 'MEG2543' 'MEG2542' 'MEG2541' - 'MEG2612' 'MEG2613' 'MEG2611' - 'MEG2623' 'MEG2622' 'MEG2621' - 'MEG2633' 'MEG2632' 'MEG2631' - 'MEG2642' 'MEG2643' 'MEG2641' - }; -end % if isneuromag - -if iseeg || isext - eeg1020 = { - 'Fp1' - 'Fpz' - 'Fp2' - 'F7' - 'F3' - 'Fz' - 'F4' - 'F8' - 'T7' - 'C3' - 'Cz' - 'C4' - 'T8' - 'P7' - 'P3' - 'Pz' - 'P4' - 'P8' - 'O1' - 'Oz' - 'O2'}; - - eeg1010 = { - 'Fp1' - 'Fpz' - 'Fp2' - 'AF9' - 'AF7' - 'AF5' - 'AF3' - 'AF1' - 'AFz' - 'AF2' - 'AF4' - 'AF6' - 'AF8' - 'AF10' - 'F9' - 'F7' - 'F5' - 'F3' - 'F1' - 'Fz' - 'F2' - 'F4' - 'F6' - 'F8' - 'F10' - 'FT9' - 'FT7' - 'FC5' - 'FC3' - 'FC1' - 'FCz' - 'FC2' - 'FC4' - 'FC6' - 'FT8' - 'FT10' - 'T9' - 'T7' - 'C5' - 'C3' - 'C1' - 'Cz' - 'C2' - 'C4' - 'C6' - 'T8' - 'T10' - 'TP9' - 'TP7' - 'CP5' - 'CP3' - 'CP1' - 'CPz' - 'CP2' - 'CP4' - 'CP6' - 'TP8' - 'TP10' - 'P9' - 'P7' - 'P5' - 'P3' - 'P1' - 'Pz' - 'P2' - 'P4' - 'P6' - 'P8' - 'P10' - 'PO9' - 'PO7' - 'PO5' - 'PO3' - 'PO1' - 'POz' - 'PO2' - 'PO4' - 'PO6' - 'PO8' - 'PO10' - 'O1' - 'Oz' - 'O2' - 'I1' - 'Iz' - 'I2' - }; - - eeg1005 = { - 'Fp1' - 'Fpz' - 'Fp2' - 'AF9' - 'AF7' - 'AF5' - 'AF3' - 'AF1' - 'AFz' - 'AF2' - 'AF4' - 'AF6' - 'AF8' - 'AF10' - 'F9' - 'F7' - 'F5' - 'F3' - 'F1' - 'Fz' - 'F2' - 'F4' - 'F6' - 'F8' - 'F10' - 'FT9' - 'FT7' - 'FC5' - 'FC3' - 'FC1' - 'FCz' - 'FC2' - 'FC4' - 'FC6' - 'FT8' - 'FT10' - 'T9' - 'T7' - 'C5' - 'C3' - 'C1' - 'Cz' - 'C2' - 'C4' - 'C6' - 'T8' - 'T10' - 'TP9' - 'TP7' - 'CP5' - 'CP3' - 'CP1' - 'CPz' - 'CP2' - 'CP4' - 'CP6' - 'TP8' - 'TP10' - 'P9' - 'P7' - 'P5' - 'P3' - 'P1' - 'Pz' - 'P2' - 'P4' - 'P6' - 'P8' - 'P10' - 'PO9' - 'PO7' - 'PO5' - 'PO3' - 'PO1' - 'POz' - 'PO2' - 'PO4' - 'PO6' - 'PO8' - 'PO10' - 'O1' - 'Oz' - 'O2' - 'I1' - 'Iz' - 'I2' - 'AFp9h' - 'AFp7h' - 'AFp5h' - 'AFp3h' - 'AFp1h' - 'AFp2h' - 'AFp4h' - 'AFp6h' - 'AFp8h' - 'AFp10h' - 'AFF9h' - 'AFF7h' - 'AFF5h' - 'AFF3h' - 'AFF1h' - 'AFF2h' - 'AFF4h' - 'AFF6h' - 'AFF8h' - 'AFF10h' - 'FFT9h' - 'FFT7h' - 'FFC5h' - 'FFC3h' - 'FFC1h' - 'FFC2h' - 'FFC4h' - 'FFC6h' - 'FFT8h' - 'FFT10h' - 'FTT9h' - 'FTT7h' - 'FCC5h' - 'FCC3h' - 'FCC1h' - 'FCC2h' - 'FCC4h' - 'FCC6h' - 'FTT8h' - 'FTT10h' - 'TTP9h' - 'TTP7h' - 'CCP5h' - 'CCP3h' - 'CCP1h' - 'CCP2h' - 'CCP4h' - 'CCP6h' - 'TTP8h' - 'TTP10h' - 'TPP9h' - 'TPP7h' - 'CPP5h' - 'CPP3h' - 'CPP1h' - 'CPP2h' - 'CPP4h' - 'CPP6h' - 'TPP8h' - 'TPP10h' - 'PPO9h' - 'PPO7h' - 'PPO5h' - 'PPO3h' - 'PPO1h' - 'PPO2h' - 'PPO4h' - 'PPO6h' - 'PPO8h' - 'PPO10h' - 'POO9h' - 'POO7h' - 'POO5h' - 'POO3h' - 'POO1h' - 'POO2h' - 'POO4h' - 'POO6h' - 'POO8h' - 'POO10h' - 'OI1h' - 'OI2h' - 'Fp1h' - 'Fp2h' - 'AF9h' - 'AF7h' - 'AF5h' - 'AF3h' - 'AF1h' - 'AF2h' - 'AF4h' - 'AF6h' - 'AF8h' - 'AF10h' - 'F9h' - 'F7h' - 'F5h' - 'F3h' - 'F1h' - 'F2h' - 'F4h' - 'F6h' - 'F8h' - 'F10h' - 'FT9h' - 'FT7h' - 'FC5h' - 'FC3h' - 'FC1h' - 'FC2h' - 'FC4h' - 'FC6h' - 'FT8h' - 'FT10h' - 'T9h' - 'T7h' - 'C5h' - 'C3h' - 'C1h' - 'C2h' - 'C4h' - 'C6h' - 'T8h' - 'T10h' - 'TP9h' - 'TP7h' - 'CP5h' - 'CP3h' - 'CP1h' - 'CP2h' - 'CP4h' - 'CP6h' - 'TP8h' - 'TP10h' - 'P9h' - 'P7h' - 'P5h' - 'P3h' - 'P1h' - 'P2h' - 'P4h' - 'P6h' - 'P8h' - 'P10h' - 'PO9h' - 'PO7h' - 'PO5h' - 'PO3h' - 'PO1h' - 'PO2h' - 'PO4h' - 'PO6h' - 'PO8h' - 'PO10h' - 'O1h' - 'O2h' - 'I1h' - 'I2h' - 'AFp9' - 'AFp7' - 'AFp5' - 'AFp3' - 'AFp1' - 'AFpz' - 'AFp2' - 'AFp4' - 'AFp6' - 'AFp8' - 'AFp10' - 'AFF9' - 'AFF7' - 'AFF5' - 'AFF3' - 'AFF1' - 'AFFz' - 'AFF2' - 'AFF4' - 'AFF6' - 'AFF8' - 'AFF10' - 'FFT9' - 'FFT7' - 'FFC5' - 'FFC3' - 'FFC1' - 'FFCz' - 'FFC2' - 'FFC4' - 'FFC6' - 'FFT8' - 'FFT10' - 'FTT9' - 'FTT7' - 'FCC5' - 'FCC3' - 'FCC1' - 'FCCz' - 'FCC2' - 'FCC4' - 'FCC6' - 'FTT8' - 'FTT10' - 'TTP9' - 'TTP7' - 'CCP5' - 'CCP3' - 'CCP1' - 'CCPz' - 'CCP2' - 'CCP4' - 'CCP6' - 'TTP8' - 'TTP10' - 'TPP9' - 'TPP7' - 'CPP5' - 'CPP3' - 'CPP1' - 'CPPz' - 'CPP2' - 'CPP4' - 'CPP6' - 'TPP8' - 'TPP10' - 'PPO9' - 'PPO7' - 'PPO5' - 'PPO3' - 'PPO1' - 'PPOz' - 'PPO2' - 'PPO4' - 'PPO6' - 'PPO8' - 'PPO10' - 'POO9' - 'POO7' - 'POO5' - 'POO3' - 'POO1' - 'POOz' - 'POO2' - 'POO4' - 'POO6' - 'POO8' - 'POO10' - 'OI1' - 'OIz' - 'OI2' - }; - - % Add also alternative labels that are used in some systems - ext1020 = cat(1, eeg1005, {'A1' 'A2' 'M1' 'M2' 'T3' 'T4' 'T5' 'T6'}'); - - % This is to account for all variants of case in 1020 systems - ext1020 = unique(cat(1, ext1020, upper(ext1020), lower(ext1020))); -end % if iseeg || isext - -if isbiosemi - biosemi64 = { - 'A1' - 'A2' - 'A3' - 'A4' - 'A5' - 'A6' - 'A7' - 'A8' - 'A9' - 'A10' - 'A11' - 'A12' - 'A13' - 'A14' - 'A15' - 'A16' - 'A17' - 'A18' - 'A19' - 'A20' - 'A21' - 'A22' - 'A23' - 'A24' - 'A25' - 'A26' - 'A27' - 'A28' - 'A29' - 'A30' - 'A31' - 'A32' - 'B1' - 'B2' - 'B3' - 'B4' - 'B5' - 'B6' - 'B7' - 'B8' - 'B9' - 'B10' - 'B11' - 'B12' - 'B13' - 'B14' - 'B15' - 'B16' - 'B17' - 'B18' - 'B19' - 'B20' - 'B21' - 'B22' - 'B23' - 'B24' - 'B25' - 'B26' - 'B27' - 'B28' - 'B29' - 'B30' - 'B31' - 'B32' - }; - - biosemi128 = { - 'A1' - 'A2' - 'A3' - 'A4' - 'A5' - 'A6' - 'A7' - 'A8' - 'A9' - 'A10' - 'A11' - 'A12' - 'A13' - 'A14' - 'A15' - 'A16' - 'A17' - 'A18' - 'A19' - 'A20' - 'A21' - 'A22' - 'A23' - 'A24' - 'A25' - 'A26' - 'A27' - 'A28' - 'A29' - 'A30' - 'A31' - 'A32' - 'B1' - 'B2' - 'B3' - 'B4' - 'B5' - 'B6' - 'B7' - 'B8' - 'B9' - 'B10' - 'B11' - 'B12' - 'B13' - 'B14' - 'B15' - 'B16' - 'B17' - 'B18' - 'B19' - 'B20' - 'B21' - 'B22' - 'B23' - 'B24' - 'B25' - 'B26' - 'B27' - 'B28' - 'B29' - 'B30' - 'B31' - 'B32' - 'C1' - 'C2' - 'C3' - 'C4' - 'C5' - 'C6' - 'C7' - 'C8' - 'C9' - 'C10' - 'C11' - 'C12' - 'C13' - 'C14' - 'C15' - 'C16' - 'C17' - 'C18' - 'C19' - 'C20' - 'C21' - 'C22' - 'C23' - 'C24' - 'C25' - 'C26' - 'C27' - 'C28' - 'C29' - 'C30' - 'C31' - 'C32' - 'D1' - 'D2' - 'D3' - 'D4' - 'D5' - 'D6' - 'D7' - 'D8' - 'D9' - 'D10' - 'D11' - 'D12' - 'D13' - 'D14' - 'D15' - 'D16' - 'D17' - 'D18' - 'D19' - 'D20' - 'D21' - 'D22' - 'D23' - 'D24' - 'D25' - 'D26' - 'D27' - 'D28' - 'D29' - 'D30' - 'D31' - 'D32' - }; - - biosemi256 = { - 'A1' - 'A2' - 'A3' - 'A4' - 'A5' - 'A6' - 'A7' - 'A8' - 'A9' - 'A10' - 'A11' - 'A12' - 'A13' - 'A14' - 'A15' - 'A16' - 'A17' - 'A18' - 'A19' - 'A20' - 'A21' - 'A22' - 'A23' - 'A24' - 'A25' - 'A26' - 'A27' - 'A28' - 'A29' - 'A30' - 'A31' - 'A32' - 'B1' - 'B2' - 'B3' - 'B4' - 'B5' - 'B6' - 'B7' - 'B8' - 'B9' - 'B10' - 'B11' - 'B12' - 'B13' - 'B14' - 'B15' - 'B16' - 'B17' - 'B18' - 'B19' - 'B20' - 'B21' - 'B22' - 'B23' - 'B24' - 'B25' - 'B26' - 'B27' - 'B28' - 'B29' - 'B30' - 'B31' - 'B32' - 'C1' - 'C2' - 'C3' - 'C4' - 'C5' - 'C6' - 'C7' - 'C8' - 'C9' - 'C10' - 'C11' - 'C12' - 'C13' - 'C14' - 'C15' - 'C16' - 'C17' - 'C18' - 'C19' - 'C20' - 'C21' - 'C22' - 'C23' - 'C24' - 'C25' - 'C26' - 'C27' - 'C28' - 'C29' - 'C30' - 'C31' - 'C32' - 'D1' - 'D2' - 'D3' - 'D4' - 'D5' - 'D6' - 'D7' - 'D8' - 'D9' - 'D10' - 'D11' - 'D12' - 'D13' - 'D14' - 'D15' - 'D16' - 'D17' - 'D18' - 'D19' - 'D20' - 'D21' - 'D22' - 'D23' - 'D24' - 'D25' - 'D26' - 'D27' - 'D28' - 'D29' - 'D30' - 'D31' - 'D32' - 'E1' - 'E2' - 'E3' - 'E4' - 'E5' - 'E6' - 'E7' - 'E8' - 'E9' - 'E10' - 'E11' - 'E12' - 'E13' - 'E14' - 'E15' - 'E16' - 'E17' - 'E18' - 'E19' - 'E20' - 'E21' - 'E22' - 'E23' - 'E24' - 'E25' - 'E26' - 'E27' - 'E28' - 'E29' - 'E30' - 'E31' - 'E32' - 'F1' - 'F2' - 'F3' - 'F4' - 'F5' - 'F6' - 'F7' - 'F8' - 'F9' - 'F10' - 'F11' - 'F12' - 'F13' - 'F14' - 'F15' - 'F16' - 'F17' - 'F18' - 'F19' - 'F20' - 'F21' - 'F22' - 'F23' - 'F24' - 'F25' - 'F26' - 'F27' - 'F28' - 'F29' - 'F30' - 'F31' - 'F32' - 'G1' - 'G2' - 'G3' - 'G4' - 'G5' - 'G6' - 'G7' - 'G8' - 'G9' - 'G10' - 'G11' - 'G12' - 'G13' - 'G14' - 'G15' - 'G16' - 'G17' - 'G18' - 'G19' - 'G20' - 'G21' - 'G22' - 'G23' - 'G24' - 'G25' - 'G26' - 'G27' - 'G28' - 'G29' - 'G30' - 'G31' - 'G32' - 'H1' - 'H2' - 'H3' - 'H4' - 'H5' - 'H6' - 'H7' - 'H8' - 'H9' - 'H10' - 'H11' - 'H12' - 'H13' - 'H14' - 'H15' - 'H16' - 'H17' - 'H18' - 'H19' - 'H20' - 'H21' - 'H22' - 'H23' - 'H24' - 'H25' - 'H26' - 'H27' - 'H28' - 'H29' - 'H30' - 'H31' - 'H32' - }; - -end % if isbiosemi - -if isegi - egi256 = cell(256, 1); - for i = 1:256 - egi256{i} = sprintf('e%d', i); - end - % the others are subsets - egi32 = egi256(1:32); - egi64 = egi256(1:64); - egi128 = egi256(1:128); -end % if isegi - -if isitab - itab153 = cell(153,1); - itab153_planar = cell(153,2); - for i=1:153 - % channel names start counting at zero - itab153{i} = sprintf('MAG_%03d', i-1); - itab153_planar{i,1} = sprintf('MAG_%03d_dH', i-1); - itab153_planar{i,2} = sprintf('MAG_%03d_dV', i-1); - end -end % if isitab - -% search for the requested definition of channel labels -if exist(type, 'var') - label = eval(type); - label = label(:); -else - error('the requested sensor type is not supported'); -end - -% remember the current input and output arguments, so that they can be -% reused on a subsequent call in case the same input argument is given -current_argout = {label}; -if isempty(previous_argin) - previous_argin = current_argin; - previous_argout = current_argout; -end - diff --git a/external/forwinv/private/senstype.m b/external/forwinv/private/senstype.m deleted file mode 100644 index c6ccaeb..0000000 --- a/external/forwinv/private/senstype.m +++ /dev/null @@ -1,368 +0,0 @@ -function [type] = senstype(input, desired) - -% SENSTYPE determines the type of sensors by looking at the channel names -% and comparing them with predefined lists. -% -% Use as -% [type] = senstype(sens) -% to get a string describing the type, or -% [flag] = senstype(sens, desired) -% to get a boolean value. -% -% The output type can be any of the following -% 'electrode' -% 'magnetometer' -% 'biosemi64' -% 'biosemi128' -% 'biosemi256' -% 'bti148' -% 'bti148_planar' -% 'bti248' -% 'bti248_planar' -% 'ctf151' -% 'ctf151_planar' -% 'ctf275' -% 'ctf275_planar' -% 'egi128' -% 'egi256' -% 'egi32' -% 'egi64' -% 'ext1020' -% 'neuromag122' -% 'neuromag306' -% 'yokogawa160' -% 'yokogawa160_planar' -% 'plexon' -% 'itab153' -% 'itab153_planar' -% -% The optional input argument for the desired type can be any of the above, -% or any of the following -% 'eeg' -% 'meg' -% 'meg_planar' -% 'meg_axial' -% 'ctf' -% 'bti' -% 'neuromag' -% 'yokogawa' -% -% Besides specifiying a grad or elec structure as input, also allowed is -% giving a data structure containing a grad or elec field, or giving a list -% of channel names (as cell-arrray). I.e. assuming a FieldTrip data -% structure, all of the following calls would be correct. -% senstype(data) -% senstype(data.label) -% senstype(data.grad) -% senstype(data.grad.label) -% -% See also READ_SENS, COMPUTE_LEADFIELD - -% Copyright (C) 2007-2008, Robert Oostenveld -% -% $Log: senstype.m,v $ -% Revision 1.22 2009/10/19 10:12:52 vlalit -% Fixed a bug that caused shape to be recognized as elec. -% -% Revision 1.21 2009/10/16 12:27:53 roboos -% some small changes pertaining to the itab/chieti format -% -% Revision 1.20 2009/10/13 10:39:19 roboos -% added support for 153 channel itab system -% -% Revision 1.19 2009/07/29 08:04:38 roboos -% cleaned up the code, no functional change -% -% Revision 1.18 2009/07/28 11:16:23 roboos -% removed keyboard statement, thanks to Jurrian -% -% Revision 1.17 2009/07/28 10:17:41 roboos -% make distinction between only label, label+pnt and label+pnt+ori -% -% Revision 1.16 2009/07/27 16:04:51 roboos -% improved distinction between eeg and meg, fixes problem with biosemi-eeg being detected as "ctf" due to reference channel match -% -% Revision 1.15 2009/06/19 16:51:50 vlalit -% Added biosemi64 system of Diane Whitmer, I don't know how generic it is. -% -% Revision 1.14 2009/05/07 13:34:09 roboos -% added ctf64 -% -% Revision 1.13 2009/04/01 06:51:43 roboos -% implemented caching for the type detection in case the same input is given multiple times -% this uses a persistent variable -% -% Revision 1.12 2009/03/06 08:50:23 roboos -% added handling of plexon header -% -% Revision 1.11 2009/02/02 16:27:41 roboos -% changed order of detecting sens.grad/elec on Vladimirs request, don't know why -% -% Revision 1.10 2008/09/10 09:12:11 roboos -% added alternative definition of channel names without a space in the label for neuromag 122 and 306 -% -% Revision 1.9 2008/09/10 07:53:27 roboos -% moved definition of channel label sets to seperate function -% -% Revision 1.8 2008/03/18 13:40:27 roboos -% added quick fix for ctf275_planar, the problem is that one channel is missing from the ctf275 list (i.e. it is only 274 long) -% -% Revision 1.7 2008/03/18 12:25:06 roboos -% use sens.type if available, this requires that the content of sens.type is consistent with the strings returned by this function -% preallocate cell-arrays -% -% Revision 1.6 2008/02/29 15:25:31 roboos -% fixed bug for eeg (thanks to Doug), updated documentation -% -% Revision 1.5 2008/02/29 14:04:42 roboos -% added gradiometers to btiref -% added general types to the checks at the end -% -% Revision 1.4 2008/02/29 13:52:12 roboos -% added bti248 and planar -% changed order of arguments for ismember, needed when a lot of EEG channels are present in ctf151 -% changed order in which checks are performed, first ctf275 and only then ctf151 -% -% Revision 1.3 2008/02/28 09:16:35 roboos -% fixed bug due to many trigger and headloc channels in ctf275 labels -% -% Revision 1.2 2008/02/27 17:01:54 roboos -% added a whole list of channel names, fixed some bugs -% -% Revision 1.1 2007/07/25 08:31:12 roboos -% implemented new helper function -% - -% these are for remembering the type on subsequent calls with the same input arguments -persistent previous_argin previous_argout - -if nargin<2 - % ensure that all input arguments are defined - desired = []; -end - -current_argin = {input, desired}; -if isequal(current_argin, previous_argin) - % don't do the type detection again, but return the previous values from cache - type = previous_argout{1}; - return -end - -isdata = isa(input, 'struct') && isfield(input, 'hdr') && isfield(input.hdr, 'label'); -isheader = isa(input, 'struct') && isfield(input, 'label') && isfield(input, 'Fs'); -isgrad = isa(input, 'struct') && isfield(input, 'pnt') && isfield(input, 'ori'); -iselec = isa(input, 'struct') && isfield(input, 'pnt') && isfield(input, 'label') && ~isfield(input, 'ori'); -islabel = isa(input, 'cell') && isa(input{1}, 'char'); - -% the input may be a data structure which then contains a grad/elec structure -if isdata - if isfield(input.hdr, 'grad') - sens = input.hdr.grad; - isgrad = true; - elseif isfield(input.hdr, 'elec') - sens = input.hdr.elec; - iselec = true; - else - sens.label = input.hdr.label; - islabel = true; - end -elseif isheader - if isfield(input, 'grad') - sens = input.grad; - isgrad = true; - elseif isfield(input, 'elec') - sens = input.elec; - iselec = true; - else - sens.label = input.label; - islabel = true; - end -elseif isgrad - sens = input; -elseif iselec - sens = input; -elseif islabel - sens.label = input; -else - sens = []; -end - -if isfield(sens, 'type') - % preferably the structure specifies its own type - type = sens.type; - -elseif issubfield(sens, 'orig.FileHeader') && issubfield(sens, 'orig.VarHeader') - % this is a complete header that was read from a Plexon *.nex file using read_plexon_nex - type = 'plexon'; - -else - % start with unknown, then try to determine the proper type by looking at the labels - type = 'unknown'; - - if isgrad - % probably this is MEG, determine the type of magnetometer/gradiometer system - % note that the order here is important: first check whether it matches a 275 channel system, then a 151 channel system, since the 151 channels are a subset of the 275 - if (mean(ismember(senslabel('ctf275'), sens.label)) > 0.8) - type = 'ctf275'; - elseif (mean(ismember(senslabel('ctfheadloc'), sens.label)) > 0.8) % look at the head localization channels - type = 'ctf275'; - elseif (mean(ismember(senslabel('ctf151'), sens.label)) > 0.8) - type = 'ctf151'; - elseif (mean(ismember(senslabel('ctf64'), sens.label)) > 0.8) - type = 'ctf64'; - elseif (mean(ismember(senslabel('ctf275_planar'), sens.label)) > 0.8) - type = 'ctf275_planar'; - elseif (mean(ismember(senslabel('ctf151_planar'), sens.label)) > 0.8) - type = 'ctf151_planar'; - elseif (mean(ismember(senslabel('bti248'), sens.label)) > 0.8) - type = 'bti248'; - elseif (mean(ismember(senslabel('bti148'), sens.label)) > 0.8) - type = 'bti148'; - elseif (mean(ismember(senslabel('bti248_planar'), sens.label)) > 0.8) - type = 'bti248_planar'; - elseif (mean(ismember(senslabel('bti148_planar'), sens.label)) > 0.8) - type = 'bti148_planar'; - elseif (mean(ismember(senslabel('itab153'), sens.label)) > 0.8) - type = 'itab153'; - elseif (mean(ismember(senslabel('itab153_planar'), sens.label)) > 0.8) - type = 'itab153_planar'; - elseif (mean(ismember(senslabel('neuromag306'), sens.label)) > 0.8) - type = 'neuromag306'; - elseif (mean(ismember(senslabel('neuromag306alt'),sens.label)) > 0.8) % an alternative set without spaces in the name - type = 'neuromag306'; - elseif (mean(ismember(senslabel('neuromag122'), sens.label)) > 0.8) - type = 'neuromag122'; - elseif (mean(ismember(senslabel('neuromag122alt'),sens.label)) > 0.8) % an alternative set without spaces in the name - type = 'neuromag122'; - elseif any(ismember(senslabel('btiref'), sens.label)) - type = 'bti'; % it might be 148 or 248 channels - elseif any(ismember(senslabel('ctfref'), sens.label)) - type = 'ctf'; % it might be 151 or 275 channels - elseif isfield(sens, 'pnt') && isfield(sens, 'ori') && numel(sens.label)==numel(sens.pnt) - type = 'magnetometer'; - else - type = 'meg'; - end - - elseif iselec - % probably this is EEG - if (mean(ismember(senslabel('biosemi256'), sens.label)) > 0.8) - type = 'biosemi256'; - elseif (mean(ismember(senslabel('biosemi128'), sens.label)) > 0.8) - type = 'biosemi128'; - elseif (mean(ismember(senslabel('biosemi64'), sens.label)) > 0.8) - type = 'biosemi64'; - elseif (mean(ismember(senslabel('egi256'), sens.label)) > 0.8) - type = 'egi256'; - elseif (mean(ismember(senslabel('egi128'), sens.label)) > 0.8) - type = 'egi128'; - elseif (mean(ismember(senslabel('egi64'), sens.label)) > 0.8) - type = 'egi64'; - elseif (mean(ismember(senslabel('egi32'), sens.label)) > 0.8) - type = 'egi32'; - elseif (sum(ismember(sens.label, senslabel('eeg1005'))) > 10) % Otherwise it's not even worth recognizing - type = 'ext1020'; - else - type = 'electrode'; - end - - elseif islabel - % look only at the channel labels - if (mean(ismember(senslabel('ctf275'), sens.label)) > 0.8) - type = 'ctf275'; - elseif (mean(ismember(senslabel('ctfheadloc'), sens.label)) > 0.8) % look at the head localization channels - type = 'ctf275'; - elseif (mean(ismember(senslabel('ctf151'), sens.label)) > 0.8) - type = 'ctf151'; - elseif (mean(ismember(senslabel('ctf64'), sens.label)) > 0.8) - type = 'ctf64'; - elseif (mean(ismember(senslabel('ctf275_planar'), sens.label)) > 0.8) - type = 'ctf275_planar'; - elseif (mean(ismember(senslabel('ctf151_planar'), sens.label)) > 0.8) - type = 'ctf151_planar'; - elseif (mean(ismember(senslabel('bti248'), sens.label)) > 0.8) - type = 'bti248'; - elseif (mean(ismember(senslabel('bti148'), sens.label)) > 0.8) - type = 'bti148'; - elseif (mean(ismember(senslabel('bti248_planar'), sens.label)) > 0.8) - type = 'bti248_planar'; - elseif (mean(ismember(senslabel('bti148_planar'), sens.label)) > 0.8) - type = 'bti148_planar'; - elseif (mean(ismember(senslabel('itab153'), sens.label)) > 0.8) - type = 'itab153'; - elseif (mean(ismember(senslabel('itab153_planar'), sens.label)) > 0.8) - type = 'itab153_planar'; - elseif (mean(ismember(senslabel('neuromag306'), sens.label)) > 0.8) - type = 'neuromag306'; - elseif (mean(ismember(senslabel('neuromag306alt'),sens.label)) > 0.8) % an alternative set without spaces in the name - type = 'neuromag306'; - elseif (mean(ismember(senslabel('neuromag122'), sens.label)) > 0.8) - type = 'neuromag122'; - elseif (mean(ismember(senslabel('neuromag122alt'),sens.label)) > 0.8) % an alternative set without spaces in the name - type = 'neuromag122'; - elseif (mean(ismember(senslabel('biosemi256'), sens.label)) > 0.8) - type = 'biosemi256'; - elseif (mean(ismember(senslabel('biosemi128'), sens.label)) > 0.8) - type = 'biosemi128'; - elseif (mean(ismember(senslabel('biosemi64'), sens.label)) > 0.8) - type = 'biosemi64'; - elseif (mean(ismember(senslabel('egi256'), sens.label)) > 0.8) - type = 'egi256'; - elseif (mean(ismember(senslabel('egi128'), sens.label)) > 0.8) - type = 'egi128'; - elseif (mean(ismember(senslabel('egi64'), sens.label)) > 0.8) - type = 'egi64'; - elseif (mean(ismember(senslabel('egi32'), sens.label)) > 0.8) - type = 'egi32'; - elseif (sum(ismember(sens.label, senslabel('eeg1005'))) > 10) % Otherwise it's not even worth recognizing - type = 'ext1020'; - elseif any(ismember(senslabel('btiref'), sens.label)) - type = 'bti'; % it might be 148 or 248 channels - elseif any(ismember(senslabel('ctfref'), sens.label)) - type = 'ctf'; % it might be 151 or 275 channels - end - - end % look at label, ori and/or pnt -end % if isfield(sens, 'type') - -if ~isempty(desired) - % return a boolean flag - switch desired - case 'eeg' - type = any(strcmp(type, {'eeg' 'electrode' 'biosemi64' 'biosemi128' 'biosemi256' 'egi32' 'egi64' 'egi128' 'egi256' 'ext1020'})); - case 'biosemi' - type = any(strcmp(type, {'biosemi64' 'biosemi128' 'biosemi256'})); - case 'egi' - type = any(strcmp(type, {'egi64' 'egi128' 'egi256'})); - case 'meg' - type = any(strcmp(type, {'meg' 'magnetometer' 'ctf' 'bti' 'ctf151' 'ctf275' 'ctf151_planar' 'ctf275_planar' 'neuromag122' 'neuromag306' 'bti148' 'bti148_planar' 'bti248' 'bti248_planar' 'yokogawa160' 'yokogawa160_planar'})); - case 'ctf' - type = any(strcmp(type, {'ctf' 'ctf151' 'ctf275' 'ctf151_planar' 'ctf275_planar'})); - case 'bti' - type = any(strcmp(type, {'bti' 'bti148' 'bti148_planar' 'bti248' 'bti248_planar'})); - case 'neuromag' - type = any(strcmp(type, {'neuromag122' 'neuromag306'})); - case 'yokogawa' - type = any(strcmp(type, {'yokogawa160' 'yokogawa160_planar'})); - case 'itab' - type = any(strcmp(type, {'itab153' 'itab153_planar'})); - case 'meg_axial' - % note that neuromag306 is mixed planar and axial - type = any(strcmp(type, {'magnetometer' 'neuromag306' 'ctf151' 'ctf275' 'bti148' 'bti248' 'yokogawa160'})); - case 'meg_planar' - % note that neuromag306 is mixed planar and axial - type = any(strcmp(type, {'neuromag122' 'neuromag306' 'ctf151_planar' 'ctf275_planar' 'bti148_planar' 'bti248_planar' 'yokogawa160_planar'})); - otherwise - type = any(strcmp(type, desired)); - end % switch desired -end % detemine the correspondence to the desired type - -% remember the current input and output arguments, so that they can be -% reused on a subsequent call in case the same input argument is given -current_argout = {type}; -if isempty(previous_argin) - previous_argin = current_argin; - previous_argout = current_argout; -end - -return % senstype main() diff --git a/external/forwinv/private/setsubfield.m b/external/forwinv/private/setsubfield.m deleted file mode 100644 index 8b53257..0000000 --- a/external/forwinv/private/setsubfield.m +++ /dev/null @@ -1,36 +0,0 @@ -function [s] = setsubfield(s, f, v); - -% SETSUBFIELD sets the contents of the specified field to a specified value -% just like the standard Matlab SETFIELD function, except that you can also -% specify nested fields using a '.' in the fieldname. The nesting can be -% arbitrary deep. -% -% Use as -% s = setsubfield(s, 'fieldname', value) -% or as -% s = setsubfield(s, 'fieldname.subfieldname', value) -% -% See also SETFIELD, GETSUBFIELD, ISSUBFIELD - -% Copyright (C) 2005, Robert Oostenveld -% -% $Log: setsubfield.m,v $ -% Revision 1.1 2008/11/13 09:55:36 roboos -% moved from fieldtrip/private, fileio or from roboos/misc to new location at fieldtrip/public -% -% Revision 1.1 2005/02/08 09:30:18 roboos -% new implementations to make it easier to work with nested structures -% - -if ~isstr(f) - error('incorrect input argument for fieldname'); -end - -t = {}; -while (1) - [t{end+1}, f] = strtok(f, '.'); - if isempty(f) - break - end -end -s = setfield(s, t{:}, v); diff --git a/external/forwinv/private/solid_angle.m b/external/forwinv/private/solid_angle.m deleted file mode 100644 index 0e506a0..0000000 --- a/external/forwinv/private/solid_angle.m +++ /dev/null @@ -1,68 +0,0 @@ -function [w] = solid_angle(r1, r2, r3); - -% SOLID_ANGLE of a planar triangle as seen from the origin -% -% The solid angle W subtended by a surface S is defined as the surface -% area W of a unit sphere covered by the surface's projection onto the -% sphere. Solid angle is measured in steradians, and the solid angle -% corresponding to all of space being subtended is 4*pi sterradians. -% -% Use: -% [w] = solid_angle(v1, v2, v3) or -% [w] = solid_angle(pnt, tri) -% where v1, v2 and v3 are the vertices of a single triangle in 3D or -% pnt and tri contain a description of a triangular mesh (this will -% compute the solid angle for each triangle) -% -% also implemented as MEX file - -% Copyright (C) 2003, Robert Oostenveld -% -% $Log: solid_angle.m,v $ -% Revision 1.3 2003/03/21 13:32:53 roberto -% created mex implementation -% -% Revision 1.2 2003/03/04 21:46:19 roberto -% added CVS log entry and synchronized all copyright labels -% - -if nargin==2 - % reassign the input arguments - pnt = r1; - tri = r2; - npnt = size(pnt,1); - ntri = size(tri,1); - w = zeros(ntri,1); - % compute solid angle for each triangle - for i=1:ntri - r1 = pnt(tri(i,1),:); - r2 = pnt(tri(i,2),:); - r3 = pnt(tri(i,3),:); - w(i) = solid_angle(r1, r2, r3); - end - return -elseif nargin==3 - % compute the solid angle for this triangle - cp23_x = r2(2) * r3(3) - r2(3) * r3(2); - cp23_y = r2(3) * r3(1) - r2(1) * r3(3); - cp23_z = r2(1) * r3(2) - r2(2) * r3(1); - nom = cp23_x * r1(1) + cp23_y * r1(2) + cp23_z * r1(3); - n1 = sqrt (r1(1) * r1(1) + r1(2) * r1(2) + r1(3) * r1(3)); - n2 = sqrt (r2(1) * r2(1) + r2(2) * r2(2) + r2(3) * r2(3)); - n3 = sqrt (r3(1) * r3(1) + r3(2) * r3(2) + r3(3) * r3(3)); - ip12 = r1(1) * r2(1) + r1(2) * r2(2) + r1(3) * r2(3); - ip23 = r2(1) * r3(1) + r2(2) * r3(2) + r2(3) * r3(3); - ip13 = r1(1) * r3(1) + r1(2) * r3(2) + r1(3) * r3(3); - den = n1 * n2 * n3 + ip12 * n3 + ip23 * n1 + ip13 * n2; - if (nom == 0) - if (den <= 0) - w = nan; - return - end - end - w = 2 * atan2 (nom, den); - return -else - error('invalid input'); -end - diff --git a/external/forwinv/private/solid_angle.mexmaci b/external/forwinv/private/solid_angle.mexmaci deleted file mode 100755 index f499b3f..0000000 Binary files a/external/forwinv/private/solid_angle.mexmaci and /dev/null differ diff --git a/external/forwinv/private/solid_angle.mexw32 b/external/forwinv/private/solid_angle.mexw32 deleted file mode 100644 index d576248..0000000 Binary files a/external/forwinv/private/solid_angle.mexw32 and /dev/null differ diff --git a/external/forwinv/private/solid_angle.mexw64 b/external/forwinv/private/solid_angle.mexw64 deleted file mode 100644 index 1f93f9e..0000000 Binary files a/external/forwinv/private/solid_angle.mexw64 and /dev/null differ diff --git a/external/forwinv/private/sourcedepth.m b/external/forwinv/private/sourcedepth.m deleted file mode 100644 index 01af870..0000000 --- a/external/forwinv/private/sourcedepth.m +++ /dev/null @@ -1,94 +0,0 @@ -function [depth] = sourcedepth(pos, vol) - -% SOURCEDEPTH computes the distance from the source to the surface of -% the source compartment (usually the brain). -% -% Use as -% depth = sourcedepth(pos, vol); -% where -% pos Nx3 matrix with the position of N sources -% vol structure describing volume condition model -% -% A negative depth indicates that the source is inside the source -% compartment, positive indicates outside. -% -% See also FIND_INSIDE_VOL - -% Copyright (C) 2007-2008, Robert Oostenveld -% -% $Log: sourcedepth.m,v $ -% Revision 1.5 2009/02/06 08:31:19 roboos -% added bemcp as volume type -% -% Revision 1.4 2008/04/21 12:09:47 roboos -% small change to documentation -% -% Revision 1.3 2008/04/15 20:36:21 roboos -% added explicit handling of various BEM implementations, i.e. for all voltype variants -% -% Revision 1.2 2007/11/05 12:02:28 roboos -% medged arno's changed into my copy -% -% Revision 1.2 2007/11/03 01:12:38 arno -% copying functions inline -% -% Revision 1.1 2007/09/24 23:40:28 nima -% Initial revision -% -% Revision 1.1 2007/07/25 08:34:48 roboos -% new implementation -% - -% determine the type of volume conduction model -switch voltype(vol) - -% single-sphere or multiple concentric spheres -case {'singlesphere', 'concentric'} - if ~isfield(vol, 'source') - % locate the innermost compartment and remember it - [dum, vol.source] = min(vol.r); - end - if isfield(vol, 'o') - % shift dipole positions toward origin of sphere - tmp = pos - repmat(vol.o, size(pos,1), 1); - else - tmp = pos; - end - depth = sqrt(sum(tmp.^2, 2))-vol.r(vol.source); % positive if outside, negative if inside - -% boundary element model -case {'bem' 'dipoli', 'bemcp', 'asa', 'avo', 'nolte', 'neuromag'} - if isfield(vol, 'source') - % use the specified source compartment - pnt = vol.bnd(vol.source).pnt; - tri = vol.bnd(vol.source).tri; - else - % locate the innermost compartment and remember it - vol.source = find_innermost_boundary(vol.bnd); - pnt = vol.bnd(vol.source).pnt; - tri = vol.bnd(vol.source).tri; - end - inside = bounding_mesh(pos, pnt, tri); - ntri = size(tri,1); - npos = size(pos,1); - dist = zeros(ntri, 1); - depth = zeros(npos, 1); - for i=1:npos - for j=1:ntri - v1 = pnt(tri(j,1),:); - v2 = pnt(tri(j,2),:); - v3 = pnt(tri(j,3),:); - [proj, dist(j)] = ptriproj(v1, v2, v3, pos(i,:), 1); - end - if inside(i) - depth(i) = -min(dist); - else - depth(i) = min(dist); - end - end - -% unsupported volume conductor model -otherwise - error('upsupported volume conductor model'); -end - diff --git a/external/forwinv/private/sphfit.m b/external/forwinv/private/sphfit.m deleted file mode 100644 index 3d68776..0000000 --- a/external/forwinv/private/sphfit.m +++ /dev/null @@ -1,95 +0,0 @@ -function [center,radius]=sphfit(vc,Ni,stopth) -% fits a sphere to a set of surface points -% usage: [center,radius]=sphfit(vc,Ni,stopth) -% -% input: -% vc nx3 matrix, where each row represents the location -% of one surface point. vc can have more than 3 columns -% (e.g. orientations) - then only the first 3 columns are used -% Ni number of iteration requested, 20 by default -% stopth stopping threshold used for the relative difference between 2 -% succeessive estimates of the radius. Fixed 10^-6 by default -% If stopth<0, then no stopping till the end of the Ni iterations -% -% center 1x3 vector denoting the center -% radius scalar denoting the radius -% -% written by Guido Nolte -% updated by Christophe Phillips, 2009/1/19 -% - add the number of iterations as input, use 5 as default -% - add a stopping criteria based on the relative difference between 2 -% successive estimates of the radius. -% If rel_diff<1e-6 (default of use fixed), then break out. - -if nargin<2 || isempty(Ni) - Ni = 20; -end - -if nargin<3 || isempty(stopth) - stopth = 1e-6; -end - -vc=vc(:,1:3); -[nvc,ndum]=size(vc); - -center_0=mean(vc); -vcx=vc-repmat(center_0,nvc,1); -radius_0=mean(sqrt(vcx(:,1).^2+vcx(:,2).^2+vcx(:,3).^2)); - -alpha=1; -rd = 1; -err_0=costfun(vc,center_0,radius_0); - -for k=1:Ni; - - [center_new,radius_new]=lm1step(vc,center_0,radius_0,alpha); - - err_new=costfun(vc,center_new,radius_new); - % disp([k,err_0,err_new,center_new,radius_new]); - - if err_new10*eps - error('only a rigid body transformation without rescaling is allowed for MEG sensors'); - end - % apply the rotation to the coil orientations - shape.ori = apply(rotation, sens.ori); -end - -if isfield(shape, 'fid') && isfield(shape.fid, 'pnt') - % apply the same transformation on the fiducials - shape.fid.pnt = apply(transform, shape.fid.pnt); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION that applies the homogenous transformation -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [new] = apply(transform, old) -old(:,4) = 1; -new = old * transform'; -new = new(:,1:3); diff --git a/external/forwinv/private/transform_sens.m b/external/forwinv/private/transform_sens.m deleted file mode 100644 index bb6808b..0000000 --- a/external/forwinv/private/transform_sens.m +++ /dev/null @@ -1,63 +0,0 @@ -function [sens] = transform_sens(transform, sens) - -% TRANSFORM_SENS applies a homogenous coordinate transformation to a -% structure with EEG electrodes or MEG gradiometers. For MEG gradiometers -% the homogenous transformation matrix should be limited to a rigid-body -% translation plus rotation. -% -% Use as -% sens = transform_sens(transform, sens) -% -% See also READ_SENS, PREPARE_VOL_SENS, COMPUTE_LEADFIELD - -% Copyright (C) 2008, Robert Oostenveld -% -% $Log: transform_sens.m,v $ -% Revision 1.4 2008/07/21 20:31:35 roboos -% updated documentation -% -% Revision 1.3 2008/03/06 09:27:30 roboos -% updated documentation -% -% Revision 1.2 2008/03/05 15:18:41 roboos -% the previous version was still empty, I now made a proper implementation for the translation of various objects -% -% Revision 1.1 2008/01/28 20:31:28 roboos -% initial implementation, empty stubs - -if any(transform(4,:) ~= [0 0 0 1]) - error('invalid transformation matrix'); -end - -if senstype(sens, 'eeg') - - % any normal coordinate transformation is in principle fine - % apply the translation, rotation and possibly scaling to the electrode positions - sens.pnt = apply(transform, sens.pnt); - -elseif senstype(sens, 'meg') - - % only a rigid body transformation (translation+rotation) without rescaling is allowed - rotation = eye(4); - rotation(1:3,1:3) = transform(1:3,1:3); - - if abs(det(rotation)-1)>10*eps - error('only a rigid body transformation without rescaling is allowed for MEG sensors'); - end - - % apply the translation and rotation to the coil positions - sens.pnt = apply(transform, sens.pnt); - % the sensor coil orientations should be rotated but not translated - sens.ori = apply(rotation, sens.ori); - -else - error('unsupported or unrecognized type of sensors'); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION that applies the homogenous transformation -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [new] = apply(transform, old) -old(:,4) = 1; -new = old * transform'; -new = new(:,1:3); diff --git a/external/forwinv/private/transform_vol.m b/external/forwinv/private/transform_vol.m deleted file mode 100644 index 90f345c..0000000 --- a/external/forwinv/private/transform_vol.m +++ /dev/null @@ -1,84 +0,0 @@ -function [vol] = transform_vol(transform, vol) - -% TRANSFORM_VOL applies a homogenous coordinate transformation to -% a structure with an EEG or MEG colume conduction model. The homogenous -% transformation matrix should be limited to a rigid-body translation -% plus rotation and a global rescaling. -% -% Use as -% vol = transform_vol(transform, vol) -% -% See also READ_VOL, PREPARE_VOL_SENS, COMPUTE_LEADFIELD - -% Copyright (C) 2008, Robert Oostenveld -% -% $Log: transform_vol.m,v $ -% Revision 1.6 2009/02/06 08:31:19 roboos -% added bemcp as volume type -% -% Revision 1.5 2008/04/18 13:16:25 roboos -% removed check for scaling -% -% Revision 1.4 2008/04/15 20:36:21 roboos -% added explicit handling of various BEM implementations, i.e. for all voltype variants -% -% Revision 1.3 2008/03/06 09:27:31 roboos -% updated documentation -% -% Revision 1.2 2008/03/05 15:18:41 roboos -% the previous version was still empty, I now made a proper implementation for the translation of various objects -% -% Revision 1.1 2008/01/28 20:31:28 roboos -% initial implementation, empty stubs -% - -if any(transform(4,:) ~= [0 0 0 1]) - error('invalid transformation matrix'); -end - -% only a rigid body transformation without rescaling is allowed -rotation = eye(4); -rotation(1:3,1:3) = transform(1:3,1:3); - -% FIXME insert check for nonuniform scaling, should give an error - -% if abs(det(rotation)-1)>10*eps -% error('only a rigid body transformation without rescaling is allowed'); -% end - -switch voltype(vol) - - case {'singlesphere' 'multisphere' 'concentric'} - if isfield(vol, 'o') - % shift the center of the spheres, an optional rotation does not affect them - vol.o = apply(transform, vol.o); - end - - case {'bem', 'dipoli', 'bemcp', 'asa', 'avo', 'nolte'} - for i=1:length(vol.bnd) - % apply the transformation to each of the triangulated surface descriptions - vol.bnd(i).pnt = apply(transform, vol.bnd(i).pnt); - if isfield(vol.bnd(i), 'nrm') - % also apply it to the surface normals - vol.bnd(i).nrm = apply(transform, vol.bnd(i).nrm); - end - end - - case 'infinite' - % nothing to do, since it is an infinite vacuum - - case 'neuromag' - error('not supported for neuromag forward model'); - - otherwise - error('unsupported or unrecognized type of volume conductor model'); -end % switch - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% SUBFUNCTION that applies the homogenous transformation -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [new] = apply(transform, old) -old(:,4) = 1; -new = old * transform'; -new = new(:,1:3); diff --git a/external/forwinv/private/voltype.m b/external/forwinv/private/voltype.m deleted file mode 100644 index c707aa6..0000000 --- a/external/forwinv/private/voltype.m +++ /dev/null @@ -1,115 +0,0 @@ -function [type] = voltype(vol, desired) - -% VOLTYPE determines the type of volume conduction model -% -% Use as -% [type] = voltype(vol) -% to get a string describing the type, or -% [flag] = voltype(vol, desired) -% to get a boolean value. -% -% See also READ_VOL, COMPUTE_LEADFIELD - -% Copyright (C) 2007-2008, Robert Oostenveld -% -% $Log: voltype.m,v $ -% Revision 1.4 2009/04/01 06:51:43 roboos -% implemented caching for the type detection in case the same input is given multiple times -% this uses a persistent variable -% -% Revision 1.3 2009/02/02 13:05:22 roboos -% small fix in cpbem->bemcp -% -% Revision 1.2 2009/02/02 12:58:27 roboos -% added bemcp implementation -% -% Revision 1.1 2009/01/21 10:32:38 roboos -% moved from forwinv/* and forwinv/mex/* directory to forwinv/private/* to make the CVS layout consistent with the release version -% -% Revision 1.7 2008/04/30 13:40:34 roboos -% improved detection concentric eeg -% -% Revision 1.6 2008/04/16 08:04:33 roboos -% be flexible in determining whether it is bem -% -% Revision 1.5 2008/04/14 19:31:05 roboos -% return 'unknown' if the type cannot be determined -% -% Revision 1.4 2008/04/10 10:59:38 roboos -% better detection of multisphere meg (after preparing) -% -% Revision 1.3 2008/03/18 12:39:24 roboos -% change in comment, nothing functional -% -% Revision 1.2 2008/03/05 15:24:44 roboos -% changed the detection of various spherical models, added infinite vacuum -% -% Revision 1.1 2007/07/25 08:31:12 roboos -% implemented new helper function -% - -% these are for remembering the type on subsequent calls with the same input arguments -persistent previous_argin previous_argout - -if nargin<2 - % ensure that all input arguments are defined - desired = []; -end - -current_argin = {vol, desired}; -if isequal(current_argin, previous_argin) - % don't do the type detection again, but return the previous values from cache - type = previous_argout{1}; - return -end - -if isfield(vol, 'type') - % preferably the structure specifies its own type - type = vol.type; - -elseif isfield(vol, 'r') && numel(vol.r)==1 && ~isfield(vol, 'label') - type = 'singlesphere'; - -elseif isfield(vol, 'r') && isfield(vol, 'o') && isfield(vol, 'label') - % this is before the spheres have been assigned to the coils - % and every sphere is still associated with a channel - type = 'multisphere'; - -elseif isfield(vol, 'r') && isfield(vol, 'o') && size(vol.r,1)==size(vol.o,1) && size(vol.r,1)>4 - % this is after the spheres have been assigned to the coils - % note that this one is easy to confuse with the concentric one - type = 'multisphere'; - -elseif isfield(vol, 'r') && numel(vol.r)>=2 && ~isfield(vol, 'label') - type = 'concentric'; - -elseif isfield(vol, 'bnd') - type = 'bem'; - -elseif isempty(vol) - type = 'infinite'; - -else - type = 'unknown'; - -end % if isfield(vol, 'type') - -if ~isempty(desired) - % return a boolean flag - switch desired - case 'bem' - type = any(strcmp(type, {'bem', 'dipoli', 'asa', 'avo', 'bemcp'})); - otherwise - type = any(strcmp(type, desired)); - end -end - -% remember the current input and output arguments, so that they can be -% reused on a subsequent call in case the same input argument is given -current_argout = {type}; -if isempty(previous_argin) - previous_argin = current_argin; - previous_argout = current_argout; -end - -return % voltype main() diff --git a/external/yokogawa/GetMeg160ADbitInfoM.m b/external/yokogawa/GetMeg160ADbitInfoM.m new file mode 100644 index 0000000..e0dc55d --- /dev/null +++ b/external/yokogawa/GetMeg160ADbitInfoM.m @@ -0,0 +1,13 @@ +% Copyright (C) 2004 Yokogawa Electric Corporation, All Rights Reserved. +% +% usage: +% AD_bit = GetMeg160ADbitInfoM( fid ) +% +% arguments: +% fid : file ID +% +% return values: +% AD_bit : AD_bit +% +% confirmation of revision: +% GetMeg160ADbitInfoM( Inf ) will show and return revision of this function. \ No newline at end of file diff --git a/external/yokogawa/GetMeg160ADbitInfoM.p b/external/yokogawa/GetMeg160ADbitInfoM.p new file mode 100644 index 0000000..caf06d7 Binary files /dev/null and b/external/yokogawa/GetMeg160ADbitInfoM.p differ diff --git a/external/yokogawa/GetMeg160AfaM.m b/external/yokogawa/GetMeg160AfaM.m new file mode 100644 index 0000000..bba5e4a --- /dev/null +++ b/external/yokogawa/GetMeg160AfaM.m @@ -0,0 +1,14 @@ +% Copyright (C) 2004 Yokogawa Electric Corporation, All Rights Reserved. +% +% usage: +% amp_gain = GetMeg160AfaM( fid ) +% +% arguments: +% fid : file ID +% +% return values: +% amp_gain : (m x 1) matrix of amp gain. (m: FLL count) +% +% confirmation of revision: +% GetMeg160AfaM( Inf ) will show and return revision of this function. +% diff --git a/external/yokogawa/GetMeg160AfaM.p b/external/yokogawa/GetMeg160AfaM.p new file mode 100644 index 0000000..026dfb5 Binary files /dev/null and b/external/yokogawa/GetMeg160AfaM.p differ diff --git a/external/yokogawa/GetMeg160AmpGainM.m b/external/yokogawa/GetMeg160AmpGainM.m new file mode 100644 index 0000000..2e594e9 --- /dev/null +++ b/external/yokogawa/GetMeg160AmpGainM.m @@ -0,0 +1,14 @@ +% Copyright (C) 2004 Yokogawa Electric Corporation, All Rights Reserved. +% +% usage: +% amp_gain = GetMeg160AmpGainM( fid ) +% +% arguments: +% fid : file ID +% +% return values: +% amp_gain : (m x 1) matrix of amp gain. (m: FLL count) +% +% confirmation of revision: +% GetMeg160AmpGainM( Inf ) will show and return revision of this function. +% diff --git a/external/yokogawa/GetMeg160AmpGainM.p b/external/yokogawa/GetMeg160AmpGainM.p new file mode 100644 index 0000000..6af8b38 Binary files /dev/null and b/external/yokogawa/GetMeg160AmpGainM.p differ diff --git a/external/yokogawa/GetMeg160CalibInfoM.m b/external/yokogawa/GetMeg160CalibInfoM.m new file mode 100644 index 0000000..1c7fb9a --- /dev/null +++ b/external/yokogawa/GetMeg160CalibInfoM.m @@ -0,0 +1,18 @@ +% Copyright (C) 2004 Yokogawa Electric Corporation, All Rights Reserved. +% +% usage: +% calib_info = GetMeg160CalibInfoM( fid ) +% +% arguments: +% fid : file ID +% +% return values: +% calib_info : (m x 3) matrix of calibration information. (m: channel_count) +% detail of n: (If the sensor doesn't have following item, the item's entry will be 'Inf'.) +% 1 : channel number in Meg160(zero start) +% 2 : gain [Tesla/V] +% 3 : offset voltage [V] +% +% confirmation of revision: +% GetMeg160CalibInfoM( Inf ) will show and return revision of this function. +% diff --git a/external/yokogawa/GetMeg160CalibInfoM.p b/external/yokogawa/GetMeg160CalibInfoM.p new file mode 100644 index 0000000..27026f4 Binary files /dev/null and b/external/yokogawa/GetMeg160CalibInfoM.p differ diff --git a/external/yokogawa/GetMeg160ChannelCountM.m b/external/yokogawa/GetMeg160ChannelCountM.m new file mode 100644 index 0000000..f920748 --- /dev/null +++ b/external/yokogawa/GetMeg160ChannelCountM.m @@ -0,0 +1,14 @@ +% Copyright (C) 2004 Yokogawa Electric Corporation, All Rights Reserved. +% +% usage: +% channel_count = GetMeg160ChannelCountM( fid ) +% +% arguments: +% fid : file ID +% +% return values: +% channel_count : channel count +% +% confirmation of revision: +% GetMeg160ChannelCountM( Inf ) will show and return revision of this function. +% diff --git a/external/yokogawa/GetMeg160ChannelCountM.p b/external/yokogawa/GetMeg160ChannelCountM.p new file mode 100644 index 0000000..c4a3f82 Binary files /dev/null and b/external/yokogawa/GetMeg160ChannelCountM.p differ diff --git a/external/yokogawa/GetMeg160ChannelInfoM.m b/external/yokogawa/GetMeg160ChannelInfoM.m new file mode 100644 index 0000000..48b1a0d --- /dev/null +++ b/external/yokogawa/GetMeg160ChannelInfoM.m @@ -0,0 +1,34 @@ +% Copyright (C) 2004 Yokogawa Electric Corporation, All Rights Reserved. +% +% usage: +% channel_info = GetMeg160ChannelInfoM( fid ) +% +% arguments: +% fid : file ID +% +% return values: +% channel_info : (m x n) matrix of channel information. (m: channel_count, n: 11) +% detail of n: (If the sensor doesn't have following item, the item's entry will be 'Inf'.) +% 1 : channel number in Meg160(zero start) +% 2 : sensor type ID (ref. table in below) +% 3-5 : sensor position(x,y,z) [m] +% 6-9 : sensor direction(zdir1, xdir1, zdir2, xdir2) [deg] +% 10 : coil size [m] +% 11 : baseline [m] +% +% < table: sensor type ID > +% NullChannel = 0; +% MagnetoMeter = 1; +% AxialGradioMeter = 2; +% PlannerGradioMeter = 3; +% RefferenceChannelMark = hex2dec('0100'); +% RefferenceMagnetoMeter = bitor( RefferenceChannelMark, MagnetoMeter ); +% RefferenceAxialGradioMeter = bitor( RefferenceChannelMark, AxialGradioMeter ); +% RefferencePlannerGradioMeter = bitor( RefferenceChannelMark, PlannerGradioMeter); +% TriggerChannel = -1; +% EegChannel = -2; +% EcgChannel = -3; +% EtcChannel = -4; +% +% confirmation of revision: +% GetMeg160ChannelInfoM( Inf ) will show and return revision of this function. diff --git a/external/yokogawa/GetMeg160ChannelInfoM.p b/external/yokogawa/GetMeg160ChannelInfoM.p new file mode 100644 index 0000000..a07bc37 Binary files /dev/null and b/external/yokogawa/GetMeg160ChannelInfoM.p differ diff --git a/external/yokogawa/GetMeg160ContinuousAcqCondM.m b/external/yokogawa/GetMeg160ContinuousAcqCondM.m new file mode 100644 index 0000000..ca56978 --- /dev/null +++ b/external/yokogawa/GetMeg160ContinuousAcqCondM.m @@ -0,0 +1,15 @@ +% Copyright (C) 2004 Yokogawa Electric Corporation, All Rights Reserved. +% +% usage: +% [sample_rate, sample_count] = GetMeg160ContinuousAcqCondM( fid ) +% +% arguments: +% fid : file ID +% +% return values: +% sample_rate : sample rate [Hz] +% sample_count : actual sampled count [sample] +% +% confirmation of revision: +% GetMeg160ContinuousAcqCondM( Inf ) will show and return revision of this function. +% diff --git a/external/yokogawa/GetMeg160ContinuousAcqCondM.p b/external/yokogawa/GetMeg160ContinuousAcqCondM.p new file mode 100644 index 0000000..1f96ac8 Binary files /dev/null and b/external/yokogawa/GetMeg160ContinuousAcqCondM.p differ diff --git a/external/yokogawa/GetMeg160ContinuousRawDataM.m b/external/yokogawa/GetMeg160ContinuousRawDataM.m new file mode 100644 index 0000000..1b78b5f --- /dev/null +++ b/external/yokogawa/GetMeg160ContinuousRawDataM.m @@ -0,0 +1,18 @@ +% Copyright (C) 2004 Yokogawa Electric Corporation, All Rights Reserved. +% +% usage: +% data = GetMeg160ContinuousRawDataM( fid, start_sample, sample_length ) +% +% arguments: +% fid : file ID +% start_sample : start sample number for retrieving data. (zero start) +% sample_length : sample length for retrieving data. +% +% return values: +% data : (m x n) matrix of measured data [AD] (class int16) +% m: channel_count +% n: 1+sample_length (n=1: channel number in Meg160(zero start) ) +% +% confirmation of revision: +% GetMeg160ContinuousRawDataM( Inf ) will show and return revision of this function. +% diff --git a/external/yokogawa/GetMeg160ContinuousRawDataM.p b/external/yokogawa/GetMeg160ContinuousRawDataM.p new file mode 100644 index 0000000..c20af86 Binary files /dev/null and b/external/yokogawa/GetMeg160ContinuousRawDataM.p differ diff --git a/external/yokogawa/GetMeg160DataAcqTypeM.m b/external/yokogawa/GetMeg160DataAcqTypeM.m new file mode 100644 index 0000000..967e78b --- /dev/null +++ b/external/yokogawa/GetMeg160DataAcqTypeM.m @@ -0,0 +1,17 @@ +% Copyright (C) 2004 Yokogawa Electric Corporation, All Rights Reserved. +% +% usage: +% acq_type = GetMeg160DataAcqTypeM( fid ) +% +% arguments: +% fid : file ID +% +% return values: +% acq_type : id number of data acquisition type +% 1: continuous raw data +% 2: evoked averaged data +% 3: evoked raw data +% +% confirmation of revision: +% GetMeg160DataAcqTypeM( Inf ) will show and return revision of this function. +% diff --git a/external/yokogawa/GetMeg160DataAcqTypeM.p b/external/yokogawa/GetMeg160DataAcqTypeM.p new file mode 100644 index 0000000..88e73c2 Binary files /dev/null and b/external/yokogawa/GetMeg160DataAcqTypeM.p differ diff --git a/external/yokogawa/GetMeg160EvokedAcqCondM.m b/external/yokogawa/GetMeg160EvokedAcqCondM.m new file mode 100644 index 0000000..47c99a0 --- /dev/null +++ b/external/yokogawa/GetMeg160EvokedAcqCondM.m @@ -0,0 +1,25 @@ +% Copyright (C) 2004 Yokogawa Electric Corporation, All Rights Reserved. +% +% usage: +% [sample_rate, frame_length, pretrigger_length, averaged_count, (multi_trigger_count), (multi_trigger_list)] = GetMeg160EvokedAcqCondM( fid ) +% +% arguments: +% fid : file ID +% +% return values: +% sample_rate : sample rate [Hz] +% frame_length : frame length [sample] +% pretrigger_length : pretrigger length [sample] +% averaged_count : actual averaged count +% multi_trigger_count : multi trigger count +% multi_trigger_list : Structures of each multi trigger information. +% .enable : flag of enable or diable (enable: true, diable: false) +% .attrib : (reserved for future) +% .status : (reserved for future) +% .event_code : code number of this trigger +% .name : trigger name +% .averaged_count : average count +% +% confirmation of revision: +% GetMeg160EvokedAcqCondM( Inf ) will show and return revision of this function. +% diff --git a/external/yokogawa/GetMeg160EvokedAcqCondM.p b/external/yokogawa/GetMeg160EvokedAcqCondM.p new file mode 100644 index 0000000..d9ccaea Binary files /dev/null and b/external/yokogawa/GetMeg160EvokedAcqCondM.p differ diff --git a/external/yokogawa/GetMeg160EvokedAverageDataM.m b/external/yokogawa/GetMeg160EvokedAverageDataM.m new file mode 100644 index 0000000..69f4b94 --- /dev/null +++ b/external/yokogawa/GetMeg160EvokedAverageDataM.m @@ -0,0 +1,18 @@ +% Copyright (C) 2004 Yokogawa Electric Corporation, All Rights Reserved. +% +% usage: +% data = GetMeg160EvokedAverageDataM( fid, start_sample, sample_length ) +% +% arguments: +% fid : file ID +% start_sample : start sample number for retrieving data. (zero start) +% sample_length : sample length for retrieving data. +% +% return values: +% data : (m x n) matrix of measured data [AD] +% m: channel_count +% n: 1+sample_length (n=1: channel number in Meg160(zero start) ) +% +% confirmation of revision: +% GetMeg160EvokedAverageDataM( Inf ) will show and return revision of this function. +% diff --git a/external/yokogawa/GetMeg160EvokedAverageDataM.p b/external/yokogawa/GetMeg160EvokedAverageDataM.p new file mode 100644 index 0000000..d610de6 Binary files /dev/null and b/external/yokogawa/GetMeg160EvokedAverageDataM.p differ diff --git a/external/yokogawa/GetMeg160EvokedRawDataM.m b/external/yokogawa/GetMeg160EvokedRawDataM.m new file mode 100644 index 0000000..96eb6bd --- /dev/null +++ b/external/yokogawa/GetMeg160EvokedRawDataM.m @@ -0,0 +1,18 @@ +% Copyright (C) 2004 Yokogawa Electric Corporation, All Rights Reserved. +% +% usage: +% data = GetMeg160EvokedRawDataM( fid, start_epoch, epoch_count ) +% +% arguments: +% fid : file ID +% start_epoch : start epoch number for retrieving data. (zero start) +% epoch_count : epoch count for retrieving data. +% +% return values: +% data : (m x n) matrix of measured data [AD] (class: int16) +% m: channel_count +% n: 1+sample_length (n=1: channel number in Meg160(zero start) ) +% +% confirmation of revision: +% GetMeg160EvokedRawDataM( Inf ) will show and return revision of this function. +% diff --git a/external/yokogawa/GetMeg160EvokedRawDataM.p b/external/yokogawa/GetMeg160EvokedRawDataM.p new file mode 100644 index 0000000..e25aa99 Binary files /dev/null and b/external/yokogawa/GetMeg160EvokedRawDataM.p differ diff --git a/external/yokogawa/GetMeg160MatchingInfoM.m b/external/yokogawa/GetMeg160MatchingInfoM.m new file mode 100644 index 0000000..181e9e3 --- /dev/null +++ b/external/yokogawa/GetMeg160MatchingInfoM.m @@ -0,0 +1,24 @@ +% Copyright (C) 2004 Yokogawa Electric Corporation, All Rights Reserved. +% +% usage: +% matching_info = GetMeg160MatchingInfoM( fid ) +% +% arguments: +% fid : file ID +% +% return values: +% matching_info : Structure of MRI-MEG matching information. +% .meg_to_mri : (4x4)transfer matrix of meg to mri +% [xmri ymri zmri 1]' = meg_to_mri * [xmeg ymeg zmeg 1]', unit:[m] +% .mri_to_meg : (4x4)transfer matrix of mri to meg +% [xmeg ymeg zmeg 1]' = meg_to_mri * [xmri ymri zmri 1]', unit:[m] +% .marker_count : marker_count +% .marker : 8 structures which has following infomation. +% .mri_type, meg_type +% .mri_done, meg_done +% .mri_pos, meg_pos +% .marker_file_name +% +% confirmation of revision: +% GetMeg160MatchingInfoM( Inf ) will show and return revision of this function. +% diff --git a/external/yokogawa/GetMeg160MatchingInfoM.p b/external/yokogawa/GetMeg160MatchingInfoM.p new file mode 100644 index 0000000..15ec411 Binary files /dev/null and b/external/yokogawa/GetMeg160MatchingInfoM.p differ diff --git a/external/yokogawa/GetMeg160MriFileHeaderInfoM.m b/external/yokogawa/GetMeg160MriFileHeaderInfoM.m new file mode 100644 index 0000000..3b9b010 --- /dev/null +++ b/external/yokogawa/GetMeg160MriFileHeaderInfoM.m @@ -0,0 +1,35 @@ +% Copyright (C) 2004 Yokogawa Electric Corporation, All Rights Reserved. +% +% usage: +% [data_style, model, marker, image_parameter, normalize, besa_fiducial_point] = GetMeg160MriFileHeaderInfoM( fid ) +% +% arguments: +% fid : MRI file ID +% +% return values: +% data_style : string ('DICOM' or 'NOT DICOM') +% model : When spherical conductor model is defined, following fields return. If not, empty will return. +% .cx, .cy, .cz: coordinate of sphere's center [meter] MRIcoordinate +% .r: radius of sphere [meter] MRIcoordinate +% marker : When pick-up of mri marker is done, following fields return. If not, empty will return. +% .count : count of picked up marker +% .pos(8) : Each structure has following fields. +% .done : Flag for whether picked up or not. +% .x, .y, .z : Coordinate of marker. If done is false, these are empty. [meter] +% image_parameter : This is mri imaging parameter which has following fields. +% .intensity : 1x2 matrix of min/max intensity of image. ([min max]) +% .initial_color : 1x2 matrix of min/max initial color. ([min max]) +% .color : 1x2 matrix of min/max color. ([min max]) +% normalize : When head coordinate is defined, following fields return. If not, empty will return. +% .mri_to_normalize : 4x4 matrix of affine transformation for mri to head coordinate. +% .normalize_data(3) : Normalize parameter includes following fields. +% .name : Normalize parameter name +% .done : Flag for whether normalize done or not. +% .x, .y, .z : Coordinate of normalize parameter. If done is false, these are empty. [meter] +% besa_fiducial_point(5) : These structures are besa fiducial points information which has following fields. +% .done : Flag for whether picked up or not. +% .x, .y, z : Coordinate of fiducial point. If done is false, these are empty. +% +% confirmation of revision: +% GetMeg160MriFileHeaderInfoM( Inf ) will show and return revision of this function. +% diff --git a/external/yokogawa/GetMeg160MriFileHeaderInfoM.p b/external/yokogawa/GetMeg160MriFileHeaderInfoM.p new file mode 100644 index 0000000..53c715e Binary files /dev/null and b/external/yokogawa/GetMeg160MriFileHeaderInfoM.p differ diff --git a/external/yokogawa/GetMeg160MriInfoM.m b/external/yokogawa/GetMeg160MriInfoM.m new file mode 100644 index 0000000..c0536d7 --- /dev/null +++ b/external/yokogawa/GetMeg160MriInfoM.m @@ -0,0 +1,19 @@ +% Copyright (C) 2004 Yokogawa Electric Corporation, All Rights Reserved. +% +% usage: +% mri_info = GetMeg160MriInfoM( fid ) +% +% arguments: +% fid : file ID +% +% return values: +% mri_info : Structure of MRI information. +% .type_name : MRI type name ('NoMriFile', 'NormalMriFile', 'VirtualMriFile') +% .file_name : MRI file name +% .model_name : conductor model type ('NoModel', 'SphericalModel') +% .cx, .cy, .cz : spherical center position for 'SphericalModel' [m] +% .r : spherical radius for 'SphericalModel' [m] +% +% confirmation of revision: +% GetMeg160MriInfoM( Inf ) will show and return revision of this function. +% diff --git a/external/yokogawa/GetMeg160MriInfoM.p b/external/yokogawa/GetMeg160MriInfoM.p new file mode 100644 index 0000000..26232fc Binary files /dev/null and b/external/yokogawa/GetMeg160MriInfoM.p differ diff --git a/external/yokogawa/GetMeg160PatientInfoFromMriFileM.m b/external/yokogawa/GetMeg160PatientInfoFromMriFileM.m new file mode 100644 index 0000000..885c77d --- /dev/null +++ b/external/yokogawa/GetMeg160PatientInfoFromMriFileM.m @@ -0,0 +1,18 @@ +% Copyright (C) 2004 Yokogawa Electric Corporation, All Rights Reserved. +% +% usage: +% patient_info = GetMeg160PatientInfoFromMriFileM( fid ) +% +% arguments: +% fid : MRI file ID +% +% return values: +% patient_info : structure of patient information. +% .patient_id : patient id +% .patient_name : patient name +% .patient_birthday : patient birthday +% .patient_sex : patient sex +% +% confirmation of revision: +% GetMeg160PatientInfoFromMriFileM( Inf ) will show and return revision of this function. +% diff --git a/external/yokogawa/GetMeg160PatientInfoFromMriFileM.p b/external/yokogawa/GetMeg160PatientInfoFromMriFileM.p new file mode 100644 index 0000000..268696f Binary files /dev/null and b/external/yokogawa/GetMeg160PatientInfoFromMriFileM.p differ diff --git a/external/yokogawa/GetMeg160PatientInfoM.m b/external/yokogawa/GetMeg160PatientInfoM.m new file mode 100644 index 0000000..31604cb --- /dev/null +++ b/external/yokogawa/GetMeg160PatientInfoM.m @@ -0,0 +1,19 @@ +% Copyright (C) 2004 Yokogawa Electric Corporation, All Rights Reserved. +% +% usage: +% patient_info = GetMeg160PatientInfoM( fid ) +% +% arguments: +% fid : file ID +% +% return values: +% patient_info : structure of patient information. +% .patient_id : patient id +% .patient_name : patient name +% .patient_birthday : patient birthday +% .patient_sex : patient sex +% .patient_handed : patient handed +% +% confirmation of revision: +% GetMeg160PatientInfoM( Inf ) will show and return revision of this function. +% diff --git a/external/yokogawa/GetMeg160PatientInfoM.p b/external/yokogawa/GetMeg160PatientInfoM.p new file mode 100644 index 0000000..9ad0fcf Binary files /dev/null and b/external/yokogawa/GetMeg160PatientInfoM.p differ diff --git a/external/yokogawa/GetMeg160SourceInfoM.m b/external/yokogawa/GetMeg160SourceInfoM.m new file mode 100644 index 0000000..870e528 --- /dev/null +++ b/external/yokogawa/GetMeg160SourceInfoM.m @@ -0,0 +1,22 @@ +% Copyright (C) 2004 Yokogawa Electric Corporation, All Rights Reserved. +% +% usage: +% source_info = GetMeg160SourceInfoM( fid ) +% +% arguments: +% fid : file ID +% +% return values: +% source_info : (N) structures of source information. (N: number of sample point when ECD is estimated) +% .sample_no : sample no when source is estimated +% .gof : GOF +% .correlation : correlation +% .dipole_count : dipole count at the sample_no +% .current_dipole : (dipole count) structures of estimated dipole infomation +% .x, .y, .z : dipole position [m] in MEG coordinate +% .zdir, xdir : dipole direction [deg] +% .intensity : dipole intensity [Am] +% +% confirmation of revision: +% GetMeg160SourceInfoM( Inf ) will show and return revision of this function. +% diff --git a/external/yokogawa/GetMeg160SourceInfoM.p b/external/yokogawa/GetMeg160SourceInfoM.p new file mode 100644 index 0000000..618a4d9 Binary files /dev/null and b/external/yokogawa/GetMeg160SourceInfoM.p differ diff --git a/external/yokogawa/GetMeg160SystemInfoM.m b/external/yokogawa/GetMeg160SystemInfoM.m new file mode 100644 index 0000000..2d07b37 --- /dev/null +++ b/external/yokogawa/GetMeg160SystemInfoM.m @@ -0,0 +1,17 @@ +% Copyright (C) 2004 Yokogawa Electric Corporation, All Rights Reserved. +% +% usage: +% [system_id ver_meg160 revision system_name] = GetMeg160SystemInfoM( fid ) +% +% arguments: +% fid : file ID +% +% return values: +% system_id : system id +% ver_meg160 : ver_meg160 +% revision : revision +% system_name : system name +% +% confirmation of revision: +% GetMeg160SystemInfoM( Inf ) will show and return revision of this function. +% diff --git a/external/yokogawa/GetMeg160SystemInfoM.p b/external/yokogawa/GetMeg160SystemInfoM.p new file mode 100644 index 0000000..c02e977 Binary files /dev/null and b/external/yokogawa/GetMeg160SystemInfoM.p differ diff --git a/external/yokogawa/GetMeg160TriggerEventM.m b/external/yokogawa/GetMeg160TriggerEventM.m new file mode 100644 index 0000000..05b7490 --- /dev/null +++ b/external/yokogawa/GetMeg160TriggerEventM.m @@ -0,0 +1,14 @@ +% Copyright (C) 2004 Yokogawa Electric Corporation, All Rights Reserved. +% +% usage: +% [trigger_event] = GetMeg160TriggerEventM( fid ) +% +% arguments: +% fid : file ID +% +% return values: +% trigger_event : n x 1 vector which include multi trigger code (n: epoch count of evoked raw data) +% +% confirmation of revision: +% GetMeg160TriggerEventM( Inf ) will show and return revision of this function. +% diff --git a/external/yokogawa/GetMeg160TriggerEventM.p b/external/yokogawa/GetMeg160TriggerEventM.p new file mode 100644 index 0000000..a975a0c Binary files /dev/null and b/external/yokogawa/GetMeg160TriggerEventM.p differ diff --git a/external/yokogawa/README b/external/yokogawa/README new file mode 100644 index 0000000..930dcd6 --- /dev/null +++ b/external/yokogawa/README @@ -0,0 +1,5 @@ +The MATLAB functions in this directory are provided courtesy of the +manufacturer. The precompiled/compiled functions are released in +combination with FieldTrip with explicit permission of the manufacturer. +The code is not part of FieldTrip and the copyrights belong to the +manufacturer. diff --git a/external/yokogawa/VERSION b/external/yokogawa/VERSION new file mode 100644 index 0000000..fcb7be4 --- /dev/null +++ b/external/yokogawa/VERSION @@ -0,0 +1,2 @@ +# Copyright (C) 2004 Yokogawa Electric Corporation, All Rights Reserved. +# Version: 16bitBeta6 diff --git a/man/auditory/auditory.tex b/man/auditory/auditory.tex index 94a0fc1..4741d6b 100644 --- a/man/auditory/auditory.tex +++ b/man/auditory/auditory.tex @@ -401,7 +401,7 @@ \subsection{Overlays} \item Saving the results using the default options (Rendering and Surface). \end{itemize} -SPM plots the rendered anatomical image in the graphics window and saves it as \texttt{render\_wc1sM00223\_002.mat}. The surface image is saved as \texttt{surf\_wc1sM00223\_002.mat}). +SPM plots the rendered anatomical image in the graphics window and saves it as \texttt{render\_\-wc1sM00223\_\-002.mat}. The surface image is saved as \texttt{surf\_wc1sM00223\_002.mat}). \begin{figure} \begin{center} @@ -410,6 +410,27 @@ \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}. + +\begin{figure} +\begin{center} +\includemovie[ + poster, + toolbar, + label=Render, + text=Render (Acrobat Reader required), + 3Droo=300, + 3Dcoo=0 -22.5 17.5, + 3Dc2c=1 0 0, + 3Daac=30, + 3Droll=0, + 3Dlights=Day, + 3Dbg=0 0 0, +]{\linewidth}{100mm}{auditory/render.u3d} +\caption{\emph{3D Rendering using canonical mesh.} \label{aud_render2}} +\end{center} +\end{figure} + \subsection{Miscellaneous} Other options (in the results controls panel): diff --git a/man/auditory/render.u3d b/man/auditory/render.u3d new file mode 100644 index 0000000..652dfad Binary files /dev/null and b/man/auditory/render.u3d differ diff --git a/man/batch/batch.tex b/man/batch/batch.tex index 120035a..1744e3a 100644 --- a/man/batch/batch.tex +++ b/man/batch/batch.tex @@ -544,6 +544,10 @@ \subsubsection{Complete and run a pre-specified job} MATLAB code which specifies the number of runs and the input data in the \verb|for| loop. +Another example script and batch is available for the multimodal +dataset, called \verb|multimodal_fmri_script.m| and +\verb|multimodal_fmri_template.m|. + \subsection{Modifying a saved job} In some cases, instead of using the serial interface it may be more diff --git a/man/batch/multimodal_fmri_script.m b/man/batch/multimodal_fmri_script.m new file mode 100644 index 0000000..ea14d58 --- /dev/null +++ b/man/batch/multimodal_fmri_script.m @@ -0,0 +1,36 @@ +% To use this example, please +% 1) place this file in your MATLAB path +% 2) place the 'multimodal_fmri_template.m' in the 'fMRI' folder of your +% copy of the multimodal dataset +% 3) edit the line PLEASE_ENTER_YOUR_PATH_TO_MULTIMODAL_DATASET below + +% Inputs per subject +% * subject dir +% * EPI images +% - session 1 +% - session 2 +% * Anatomy image +% * Multiple conditions +% - session 1 +% - session 2 +% Assumed data organisation +% multimodal/fMRI/{Session1,Session2} + +studydir = PLEASE_ENTER_YOUR_PATH_TO_MULTIMODAL_DATASET; +subjdirs = {'.'}; +jobs = cell(size(subjdirs)); +[jobs{:}] = deal(fullfile(studydir,'fMRI','multimodal_fmri_template.m')); + +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{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 diff --git a/man/batch/multimodal_fmri_template.m b/man/batch/multimodal_fmri_template.m new file mode 100644 index 0000000..672700a --- /dev/null +++ b/man/batch/multimodal_fmri_template.m @@ -0,0 +1,258 @@ +%----------------------------------------------------------------------- +% Job configuration created by cfg_util (rev $Rev: 3796 $) +%----------------------------------------------------------------------- +matlabbatch{1}.cfg_basicio.cfg_named_dir.name = 'Subject directory'; +matlabbatch{1}.cfg_basicio.cfg_named_dir.dirs = {''}; +matlabbatch{2}.cfg_basicio.cfg_named_file.name = 'EPI images'; +matlabbatch{2}.cfg_basicio.cfg_named_file.files = { + '' + '' + }'; +matlabbatch{3}.cfg_basicio.cfg_named_file.name = 'Anatomical image'; +matlabbatch{3}.cfg_basicio.cfg_named_file.files = {''}; +matlabbatch{4}.cfg_basicio.cfg_cd.dir(1) = cfg_dep; +matlabbatch{4}.cfg_basicio.cfg_cd.dir(1).tgt_spec = {}; +matlabbatch{4}.cfg_basicio.cfg_cd.dir(1).sname = 'Named Directory Selector: Subject directory(1)'; +matlabbatch{4}.cfg_basicio.cfg_cd.dir(1).src_exbranch = substruct('.','val', '{}',{1}, '.','val', '{}',{1}); +matlabbatch{4}.cfg_basicio.cfg_cd.dir(1).src_output = substruct('.','dirs', '{}',{1}); +matlabbatch{5}.cfg_basicio.cfg_mkdir.parent(1) = cfg_dep; +matlabbatch{5}.cfg_basicio.cfg_mkdir.parent(1).tgt_spec = {}; +matlabbatch{5}.cfg_basicio.cfg_mkdir.parent(1).sname = 'Named Directory Selector: Subject directory(1)'; +matlabbatch{5}.cfg_basicio.cfg_mkdir.parent(1).src_exbranch = substruct('.','val', '{}',{1}, '.','val', '{}',{1}); +matlabbatch{5}.cfg_basicio.cfg_mkdir.parent(1).src_output = substruct('.','dirs', '{}',{1}); +matlabbatch{5}.cfg_basicio.cfg_mkdir.name = 'Stats'; +matlabbatch{6}.spm.spatial.realign.estwrite.data{1}(1) = cfg_dep; +matlabbatch{6}.spm.spatial.realign.estwrite.data{1}(1).tgt_spec = {}; +matlabbatch{6}.spm.spatial.realign.estwrite.data{1}(1).sname = 'Named File Selector: EPI images(1) - Files'; +matlabbatch{6}.spm.spatial.realign.estwrite.data{1}(1).src_exbranch = substruct('.','val', '{}',{2}, '.','val', '{}',{1}); +matlabbatch{6}.spm.spatial.realign.estwrite.data{1}(1).src_output = substruct('.','files', '{}',{1}); +matlabbatch{6}.spm.spatial.realign.estwrite.data{2}(1) = cfg_dep; +matlabbatch{6}.spm.spatial.realign.estwrite.data{2}(1).tgt_spec = {}; +matlabbatch{6}.spm.spatial.realign.estwrite.data{2}(1).sname = 'Named File Selector: EPI images(2) - Files'; +matlabbatch{6}.spm.spatial.realign.estwrite.data{2}(1).src_exbranch = substruct('.','val', '{}',{2}, '.','val', '{}',{1}); +matlabbatch{6}.spm.spatial.realign.estwrite.data{2}(1).src_output = substruct('.','files', '{}',{2}); +matlabbatch{6}.spm.spatial.realign.estwrite.eoptions.quality = 0.9; +matlabbatch{6}.spm.spatial.realign.estwrite.eoptions.sep = 4; +matlabbatch{6}.spm.spatial.realign.estwrite.eoptions.fwhm = 5; +matlabbatch{6}.spm.spatial.realign.estwrite.eoptions.rtm = 1; +matlabbatch{6}.spm.spatial.realign.estwrite.eoptions.interp = 2; +matlabbatch{6}.spm.spatial.realign.estwrite.eoptions.wrap = [0 0 0]; +matlabbatch{6}.spm.spatial.realign.estwrite.eoptions.weight = {''}; +matlabbatch{6}.spm.spatial.realign.estwrite.roptions.which = [0 1]; +matlabbatch{6}.spm.spatial.realign.estwrite.roptions.interp = 4; +matlabbatch{6}.spm.spatial.realign.estwrite.roptions.wrap = [0 0 0]; +matlabbatch{6}.spm.spatial.realign.estwrite.roptions.mask = 1; +matlabbatch{6}.spm.spatial.realign.estwrite.roptions.prefix = 'r'; +matlabbatch{7}.spm.spatial.coreg.estimate.ref(1) = cfg_dep; +matlabbatch{7}.spm.spatial.coreg.estimate.ref(1).tgt_spec = {}; +matlabbatch{7}.spm.spatial.coreg.estimate.ref(1).sname = 'Named File Selector: Anatomical image(1) - Files'; +matlabbatch{7}.spm.spatial.coreg.estimate.ref(1).src_exbranch = substruct('.','val', '{}',{3}, '.','val', '{}',{1}); +matlabbatch{7}.spm.spatial.coreg.estimate.ref(1).src_output = substruct('.','files', '{}',{1}); +matlabbatch{7}.spm.spatial.coreg.estimate.source(1) = cfg_dep; +matlabbatch{7}.spm.spatial.coreg.estimate.source(1).tgt_spec = {}; +matlabbatch{7}.spm.spatial.coreg.estimate.source(1).sname = 'Realign: Estimate & Reslice: Mean Image'; +matlabbatch{7}.spm.spatial.coreg.estimate.source(1).src_exbranch = substruct('.','val', '{}',{6}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}); +matlabbatch{7}.spm.spatial.coreg.estimate.source(1).src_output = substruct('.','rmean'); +matlabbatch{7}.spm.spatial.coreg.estimate.other(1) = cfg_dep; +matlabbatch{7}.spm.spatial.coreg.estimate.other(1).tgt_spec = {}; +matlabbatch{7}.spm.spatial.coreg.estimate.other(1).sname = 'Realign: Estimate & Reslice: Realigned Images (Sess 1)'; +matlabbatch{7}.spm.spatial.coreg.estimate.other(1).src_exbranch = substruct('.','val', '{}',{6}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}); +matlabbatch{7}.spm.spatial.coreg.estimate.other(1).src_output = substruct('.','sess', '()',{1}, '.','cfiles'); +matlabbatch{7}.spm.spatial.coreg.estimate.other(2) = cfg_dep; +matlabbatch{7}.spm.spatial.coreg.estimate.other(2).tgt_spec = {}; +matlabbatch{7}.spm.spatial.coreg.estimate.other(2).sname = 'Realign: Estimate & Reslice: Realigned Images (Sess 2)'; +matlabbatch{7}.spm.spatial.coreg.estimate.other(2).src_exbranch = substruct('.','val', '{}',{6}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}); +matlabbatch{7}.spm.spatial.coreg.estimate.other(2).src_output = substruct('.','sess', '()',{2}, '.','cfiles'); +matlabbatch{7}.spm.spatial.coreg.estimate.eoptions.cost_fun = 'nmi'; +matlabbatch{7}.spm.spatial.coreg.estimate.eoptions.sep = [4 2]; +matlabbatch{7}.spm.spatial.coreg.estimate.eoptions.tol = [0.02 0.02 0.02 0.001 0.001 0.001 0.01 0.01 0.01 0.001 0.001 0.001]; +matlabbatch{7}.spm.spatial.coreg.estimate.eoptions.fwhm = [7 7]; +matlabbatch{8}.spm.spatial.preproc.data(1) = cfg_dep; +matlabbatch{8}.spm.spatial.preproc.data(1).tgt_spec = {}; +matlabbatch{8}.spm.spatial.preproc.data(1).sname = 'Named File Selector: Anatomical image(1) - Files'; +matlabbatch{8}.spm.spatial.preproc.data(1).src_exbranch = substruct('.','val', '{}',{3}, '.','val', '{}',{1}); +matlabbatch{8}.spm.spatial.preproc.data(1).src_output = substruct('.','files', '{}',{1}); +matlabbatch{8}.spm.spatial.preproc.output.GM = [0 0 1]; +matlabbatch{8}.spm.spatial.preproc.output.WM = [0 0 1]; +matlabbatch{8}.spm.spatial.preproc.output.CSF = [0 0 0]; +matlabbatch{8}.spm.spatial.preproc.output.biascor = 1; +matlabbatch{8}.spm.spatial.preproc.output.cleanup = 0; +matlabbatch{8}.spm.spatial.preproc.opts.tpm = { + '/export/spm8/tpm/grey.nii,1' + '/export/spm8/tpm/white.nii,1' + '/export/spm8/tpm/csf.nii,1' + }; +matlabbatch{8}.spm.spatial.preproc.opts.ngaus = [2 + 2 + 2 + 4]; +matlabbatch{8}.spm.spatial.preproc.opts.regtype = 'mni'; +matlabbatch{8}.spm.spatial.preproc.opts.warpreg = 1; +matlabbatch{8}.spm.spatial.preproc.opts.warpco = 25; +matlabbatch{8}.spm.spatial.preproc.opts.biasreg = 0.0001; +matlabbatch{8}.spm.spatial.preproc.opts.biasfwhm = 60; +matlabbatch{8}.spm.spatial.preproc.opts.samp = 3; +matlabbatch{8}.spm.spatial.preproc.opts.msk = {''}; +matlabbatch{9}.cfg_basicio.cfg_file_split.name = 'Coregistered images w/o mean'; +matlabbatch{9}.cfg_basicio.cfg_file_split.files(1) = cfg_dep; +matlabbatch{9}.cfg_basicio.cfg_file_split.files(1).tgt_spec = {}; +matlabbatch{9}.cfg_basicio.cfg_file_split.files(1).sname = 'Coreg: Estimate: Coregistered Images'; +matlabbatch{9}.cfg_basicio.cfg_file_split.files(1).src_exbranch = substruct('.','val', '{}',{7}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}); +matlabbatch{9}.cfg_basicio.cfg_file_split.files(1).src_output = substruct('.','cfiles'); +matlabbatch{9}.cfg_basicio.cfg_file_split.index = {1}; +matlabbatch{10}.spm.spatial.normalise.write.subj.matname(1) = cfg_dep; +matlabbatch{10}.spm.spatial.normalise.write.subj.matname(1).tgt_spec{1}(1).name = 'filter'; +matlabbatch{10}.spm.spatial.normalise.write.subj.matname(1).tgt_spec{1}(1).value = 'mat'; +matlabbatch{10}.spm.spatial.normalise.write.subj.matname(1).tgt_spec{1}(2).name = 'strtype'; +matlabbatch{10}.spm.spatial.normalise.write.subj.matname(1).tgt_spec{1}(2).value = 'e'; +matlabbatch{10}.spm.spatial.normalise.write.subj.matname(1).sname = 'Segment: Norm Params Subj->MNI'; +matlabbatch{10}.spm.spatial.normalise.write.subj.matname(1).src_exbranch = substruct('.','val', '{}',{8}, '.','val', '{}',{1}, '.','val', '{}',{1}); +matlabbatch{10}.spm.spatial.normalise.write.subj.matname(1).src_output = substruct('()',{1}, '.','snfile', '()',{':'}); +matlabbatch{10}.spm.spatial.normalise.write.subj.resample(1) = cfg_dep; +matlabbatch{10}.spm.spatial.normalise.write.subj.resample(1).tgt_spec{1}(1).name = 'class'; +matlabbatch{10}.spm.spatial.normalise.write.subj.resample(1).tgt_spec{1}(1).value = 'cfg_files'; +matlabbatch{10}.spm.spatial.normalise.write.subj.resample(1).tgt_spec{1}(2).name = 'strtype'; +matlabbatch{10}.spm.spatial.normalise.write.subj.resample(1).tgt_spec{1}(2).value = 'e'; +matlabbatch{10}.spm.spatial.normalise.write.subj.resample(1).sname = 'File Set Split: Coregistered images w/o mean (rem)'; +matlabbatch{10}.spm.spatial.normalise.write.subj.resample(1).src_exbranch = substruct('.','val', '{}',{9}, '.','val', '{}',{1}); +matlabbatch{10}.spm.spatial.normalise.write.subj.resample(1).src_output = substruct('{}',{2}); +matlabbatch{10}.spm.spatial.normalise.write.roptions.preserve = 0; +matlabbatch{10}.spm.spatial.normalise.write.roptions.bb = [-78 -112 -50 + 78 76 85]; +matlabbatch{10}.spm.spatial.normalise.write.roptions.vox = [3 3 3]; +matlabbatch{10}.spm.spatial.normalise.write.roptions.interp = 1; +matlabbatch{10}.spm.spatial.normalise.write.roptions.wrap = [0 0 0]; +matlabbatch{10}.spm.spatial.normalise.write.roptions.prefix = 'w'; +matlabbatch{11}.spm.spatial.smooth.data(1) = cfg_dep; +matlabbatch{11}.spm.spatial.smooth.data(1).tgt_spec = {}; +matlabbatch{11}.spm.spatial.smooth.data(1).sname = 'Normalise: Write: Normalised Images (Subj 1)'; +matlabbatch{11}.spm.spatial.smooth.data(1).src_exbranch = substruct('.','val', '{}',{10}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}); +matlabbatch{11}.spm.spatial.smooth.data(1).src_output = substruct('()',{1}, '.','files'); +matlabbatch{11}.spm.spatial.smooth.fwhm = [8 8 8]; +matlabbatch{11}.spm.spatial.smooth.dtype = 0; +matlabbatch{11}.spm.spatial.smooth.prefix = 's'; +matlabbatch{12}.cfg_basicio.cfg_file_split.name = 'Smoothed EPIs'; +matlabbatch{12}.cfg_basicio.cfg_file_split.files(1) = cfg_dep; +matlabbatch{12}.cfg_basicio.cfg_file_split.files(1).tgt_spec = {}; +matlabbatch{12}.cfg_basicio.cfg_file_split.files(1).sname = 'Smooth: Smoothed Images'; +matlabbatch{12}.cfg_basicio.cfg_file_split.files(1).src_exbranch = substruct('.','val', '{}',{11}, '.','val', '{}',{1}, '.','val', '{}',{1}); +matlabbatch{12}.cfg_basicio.cfg_file_split.files(1).src_output = substruct('.','files'); +matlabbatch{12}.cfg_basicio.cfg_file_split.index{1}(1) = cfg_dep; +matlabbatch{12}.cfg_basicio.cfg_file_split.index{1}(1).tgt_spec{1}(1).name = 'strtype'; +matlabbatch{12}.cfg_basicio.cfg_file_split.index{1}(1).tgt_spec{1}(1).value = 'n'; +matlabbatch{12}.cfg_basicio.cfg_file_split.index{1}(1).tgt_spec{1}(2).name = 'strtype'; +matlabbatch{12}.cfg_basicio.cfg_file_split.index{1}(1).tgt_spec{1}(2).value = 'w'; +matlabbatch{12}.cfg_basicio.cfg_file_split.index{1}(1).tgt_spec{1}(3).name = 'strtype'; +matlabbatch{12}.cfg_basicio.cfg_file_split.index{1}(1).tgt_spec{1}(3).value = 'i'; +matlabbatch{12}.cfg_basicio.cfg_file_split.index{1}(1).tgt_spec{1}(4).name = 'strtype'; +matlabbatch{12}.cfg_basicio.cfg_file_split.index{1}(1).tgt_spec{1}(4).value = 'r'; +matlabbatch{12}.cfg_basicio.cfg_file_split.index{1}(1).tgt_spec{1}(5).name = 'strtype'; +matlabbatch{12}.cfg_basicio.cfg_file_split.index{1}(1).tgt_spec{1}(5).value = 'e'; +matlabbatch{12}.cfg_basicio.cfg_file_split.index{1}(1).sname = 'Named File Selector: EPI images(1) - File index'; +matlabbatch{12}.cfg_basicio.cfg_file_split.index{1}(1).src_exbranch = substruct('.','val', '{}',{2}, '.','val', '{}',{1}); +matlabbatch{12}.cfg_basicio.cfg_file_split.index{1}(1).src_output = substruct('.','index', '{}',{1}); +matlabbatch{12}.cfg_basicio.cfg_file_split.index{2}(1) = cfg_dep; +matlabbatch{12}.cfg_basicio.cfg_file_split.index{2}(1).tgt_spec{1}(1).name = 'strtype'; +matlabbatch{12}.cfg_basicio.cfg_file_split.index{2}(1).tgt_spec{1}(1).value = 'n'; +matlabbatch{12}.cfg_basicio.cfg_file_split.index{2}(1).tgt_spec{1}(2).name = 'strtype'; +matlabbatch{12}.cfg_basicio.cfg_file_split.index{2}(1).tgt_spec{1}(2).value = 'w'; +matlabbatch{12}.cfg_basicio.cfg_file_split.index{2}(1).tgt_spec{1}(3).name = 'strtype'; +matlabbatch{12}.cfg_basicio.cfg_file_split.index{2}(1).tgt_spec{1}(3).value = 'i'; +matlabbatch{12}.cfg_basicio.cfg_file_split.index{2}(1).tgt_spec{1}(4).name = 'strtype'; +matlabbatch{12}.cfg_basicio.cfg_file_split.index{2}(1).tgt_spec{1}(4).value = 'r'; +matlabbatch{12}.cfg_basicio.cfg_file_split.index{2}(1).tgt_spec{1}(5).name = 'strtype'; +matlabbatch{12}.cfg_basicio.cfg_file_split.index{2}(1).tgt_spec{1}(5).value = 'e'; +matlabbatch{12}.cfg_basicio.cfg_file_split.index{2}(1).sname = 'Named File Selector: EPI images(2) - File index'; +matlabbatch{12}.cfg_basicio.cfg_file_split.index{2}(1).src_exbranch = substruct('.','val', '{}',{2}, '.','val', '{}',{1}); +matlabbatch{12}.cfg_basicio.cfg_file_split.index{2}(1).src_output = substruct('.','index', '{}',{2}); +matlabbatch{13}.spm.stats.fmri_spec.dir(1) = cfg_dep; +matlabbatch{13}.spm.stats.fmri_spec.dir(1).tgt_spec{1}(1).name = 'filter'; +matlabbatch{13}.spm.stats.fmri_spec.dir(1).tgt_spec{1}(1).value = 'dir'; +matlabbatch{13}.spm.stats.fmri_spec.dir(1).tgt_spec{1}(2).name = 'strtype'; +matlabbatch{13}.spm.stats.fmri_spec.dir(1).tgt_spec{1}(2).value = 'e'; +matlabbatch{13}.spm.stats.fmri_spec.dir(1).sname = 'Make Directory: Make Directory ''Stats'''; +matlabbatch{13}.spm.stats.fmri_spec.dir(1).src_exbranch = substruct('.','val', '{}',{5}, '.','val', '{}',{1}); +matlabbatch{13}.spm.stats.fmri_spec.dir(1).src_output = substruct('.','dir'); +matlabbatch{13}.spm.stats.fmri_spec.timing.units = 'scans'; +matlabbatch{13}.spm.stats.fmri_spec.timing.RT = 2; +matlabbatch{13}.spm.stats.fmri_spec.timing.fmri_t = 16; +matlabbatch{13}.spm.stats.fmri_spec.timing.fmri_t0 = 1; +matlabbatch{13}.spm.stats.fmri_spec.sess(1).scans(1) = cfg_dep; +matlabbatch{13}.spm.stats.fmri_spec.sess(1).scans(1).tgt_spec = {}; +matlabbatch{13}.spm.stats.fmri_spec.sess(1).scans(1).sname = 'File Set Split: Smoothed EPIs (1)'; +matlabbatch{13}.spm.stats.fmri_spec.sess(1).scans(1).src_exbranch = substruct('.','val', '{}',{12}, '.','val', '{}',{1}); +matlabbatch{13}.spm.stats.fmri_spec.sess(1).scans(1).src_output = substruct('{}',{1}); +matlabbatch{13}.spm.stats.fmri_spec.sess(1).cond = struct('name', {}, 'onset', {}, 'duration', {}, 'tmod', {}, 'pmod', {}); +matlabbatch{13}.spm.stats.fmri_spec.sess(1).multi = ''; +matlabbatch{13}.spm.stats.fmri_spec.sess(1).regress = struct('name', {}, 'val', {}); +matlabbatch{13}.spm.stats.fmri_spec.sess(1).multi_reg(1) = cfg_dep; +matlabbatch{13}.spm.stats.fmri_spec.sess(1).multi_reg(1).tgt_spec{1}(1).name = 'filter'; +matlabbatch{13}.spm.stats.fmri_spec.sess(1).multi_reg(1).tgt_spec{1}(1).value = 'mat'; +matlabbatch{13}.spm.stats.fmri_spec.sess(1).multi_reg(1).tgt_spec{1}(2).name = 'strtype'; +matlabbatch{13}.spm.stats.fmri_spec.sess(1).multi_reg(1).tgt_spec{1}(2).value = 'e'; +matlabbatch{13}.spm.stats.fmri_spec.sess(1).multi_reg(1).sname = 'Realign: Estimate & Reslice: Realignment Param File (Sess 1)'; +matlabbatch{13}.spm.stats.fmri_spec.sess(1).multi_reg(1).src_exbranch = substruct('.','val', '{}',{6}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}); +matlabbatch{13}.spm.stats.fmri_spec.sess(1).multi_reg(1).src_output = substruct('.','sess', '()',{1}, '.','rpfile'); +matlabbatch{13}.spm.stats.fmri_spec.sess(1).hpf = 128; +matlabbatch{13}.spm.stats.fmri_spec.sess(2).scans(1) = cfg_dep; +matlabbatch{13}.spm.stats.fmri_spec.sess(2).scans(1).tgt_spec = {}; +matlabbatch{13}.spm.stats.fmri_spec.sess(2).scans(1).sname = 'File Set Split: Smoothed EPIs (2)'; +matlabbatch{13}.spm.stats.fmri_spec.sess(2).scans(1).src_exbranch = substruct('.','val', '{}',{12}, '.','val', '{}',{1}); +matlabbatch{13}.spm.stats.fmri_spec.sess(2).scans(1).src_output = substruct('{}',{2}); +matlabbatch{13}.spm.stats.fmri_spec.sess(2).cond = struct('name', {}, 'onset', {}, 'duration', {}, 'tmod', {}, 'pmod', {}); +matlabbatch{13}.spm.stats.fmri_spec.sess(2).multi = ''; +matlabbatch{13}.spm.stats.fmri_spec.sess(2).regress = struct('name', {}, 'val', {}); +matlabbatch{13}.spm.stats.fmri_spec.sess(2).multi_reg(1) = cfg_dep; +matlabbatch{13}.spm.stats.fmri_spec.sess(2).multi_reg(1).tgt_spec{1}(1).name = 'filter'; +matlabbatch{13}.spm.stats.fmri_spec.sess(2).multi_reg(1).tgt_spec{1}(1).value = 'mat'; +matlabbatch{13}.spm.stats.fmri_spec.sess(2).multi_reg(1).tgt_spec{1}(2).name = 'strtype'; +matlabbatch{13}.spm.stats.fmri_spec.sess(2).multi_reg(1).tgt_spec{1}(2).value = 'e'; +matlabbatch{13}.spm.stats.fmri_spec.sess(2).multi_reg(1).sname = 'Realign: Estimate & Reslice: Realignment Param File (Sess 2)'; +matlabbatch{13}.spm.stats.fmri_spec.sess(2).multi_reg(1).src_exbranch = substruct('.','val', '{}',{6}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}); +matlabbatch{13}.spm.stats.fmri_spec.sess(2).multi_reg(1).src_output = substruct('.','sess', '()',{2}, '.','rpfile'); +matlabbatch{13}.spm.stats.fmri_spec.sess(2).hpf = 128; +matlabbatch{13}.spm.stats.fmri_spec.fact = struct('name', {}, 'levels', {}); +matlabbatch{13}.spm.stats.fmri_spec.bases.hrf.derivs = [1 1]; +matlabbatch{13}.spm.stats.fmri_spec.volt = 1; +matlabbatch{13}.spm.stats.fmri_spec.global = 'None'; +matlabbatch{13}.spm.stats.fmri_spec.mask = {''}; +matlabbatch{13}.spm.stats.fmri_spec.cvi = 'AR(1)'; +matlabbatch{14}.spm.stats.fmri_est.spmmat(1) = cfg_dep; +matlabbatch{14}.spm.stats.fmri_est.spmmat(1).tgt_spec = {}; +matlabbatch{14}.spm.stats.fmri_est.spmmat(1).sname = 'fMRI model specification: SPM.mat File'; +matlabbatch{14}.spm.stats.fmri_est.spmmat(1).src_exbranch = substruct('.','val', '{}',{13}, '.','val', '{}',{1}, '.','val', '{}',{1}); +matlabbatch{14}.spm.stats.fmri_est.spmmat(1).src_output = substruct('.','spmmat'); +matlabbatch{14}.spm.stats.fmri_est.method.Classical = 1; +matlabbatch{15}.spm.stats.con.spmmat(1) = cfg_dep; +matlabbatch{15}.spm.stats.con.spmmat(1).tgt_spec = {}; +matlabbatch{15}.spm.stats.con.spmmat(1).sname = 'Model estimation: SPM.mat File'; +matlabbatch{15}.spm.stats.con.spmmat(1).src_exbranch = substruct('.','val', '{}',{14}, '.','val', '{}',{1}, '.','val', '{}',{1}); +matlabbatch{15}.spm.stats.con.spmmat(1).src_output = substruct('.','spmmat'); +matlabbatch{15}.spm.stats.con.consess{1}.fcon.name = 'faces + scrambled vs Baseline (all BFs)'; +matlabbatch{15}.spm.stats.con.consess{1}.fcon.convec = { + [1 0 0 1 0 0 0 0 0 0 0 0 + 0 1 0 0 1 0 0 0 0 0 0 0 + 0 0 1 0 0 1 0 0 0 0 0 0] + }'; +matlabbatch{15}.spm.stats.con.consess{1}.fcon.sessrep = 'repl'; +matlabbatch{15}.spm.stats.con.consess{2}.fcon.name = 'faces vs scrambled (all BFs)'; +matlabbatch{15}.spm.stats.con.consess{2}.fcon.convec = { + [1 0 0 -1 0 0 0 0 0 0 0 0 + 0 1 0 0 -1 0 0 0 0 0 0 0 + 0 0 1 0 0 -1 0 0 0 0 0 0] + }'; +matlabbatch{15}.spm.stats.con.consess{2}.fcon.sessrep = 'repl'; +matlabbatch{15}.spm.stats.con.delete = 0; +matlabbatch{16}.spm.stats.results.spmmat(1) = cfg_dep; +matlabbatch{16}.spm.stats.results.spmmat(1).tgt_spec = {}; +matlabbatch{16}.spm.stats.results.spmmat(1).sname = 'Contrast Manager: SPM.mat File'; +matlabbatch{16}.spm.stats.results.spmmat(1).src_exbranch = substruct('.','val', '{}',{15}, '.','val', '{}',{1}, '.','val', '{}',{1}); +matlabbatch{16}.spm.stats.results.spmmat(1).src_output = substruct('.','spmmat'); +matlabbatch{16}.spm.stats.results.conspec.titlestr = ''; +matlabbatch{16}.spm.stats.results.conspec.contrasts = Inf; +matlabbatch{16}.spm.stats.results.conspec.threshdesc = 'FWE'; +matlabbatch{16}.spm.stats.results.conspec.thresh = 0.05; +matlabbatch{16}.spm.stats.results.conspec.extent = 0; +matlabbatch{16}.spm.stats.results.conspec.mask = struct('contrasts', {}, 'thresh', {}, 'mtype', {}); +matlabbatch{16}.spm.stats.results.units = 1; +matlabbatch{16}.spm.stats.results.print = true; diff --git a/man/biblio/external.bib b/man/biblio/external.bib index 207cb7b..58a0135 100644 --- a/man/biblio/external.bib +++ b/man/biblio/external.bib @@ -202,3 +202,14 @@ @Article{jbp_fiac year = {2006}, doi = {10.1002/hbm.20268} } + +@Article{leff_speech, + Author="Leff, A. P. and Schofield, T. M. and Stephan, K. E. and Crinion, J. T. and Friston, K. J. and Price, C. J. ", + Title="{{T}he cortical dynamics of intelligible speech}", + Journal="J. Neurosci.", + Year="2008", + Volume="28", + Pages="13209--13215", + Month="Dec" +} + diff --git a/man/biblio/methods_group.bib b/man/biblio/methods_group.bib index 70327af..42de7e4 100644 --- a/man/biblio/methods_group.bib +++ b/man/biblio/methods_group.bib @@ -2452,9 +2452,12 @@ @Article{justin_fdr author = jc # and # karl, title = {False Discovery Rate Revisited: FDR and Topological Inference Using Gaussian Random Fields}, journal = ni, - year = 2008, + year = 2009, + volume = 44, + number = {2}, + pages = {62--70}, doi = {10.1016/j.neuroimage.2008.05.021}, - keyword = {FDR,RFT} + keyword = {FDR,RFT,topological} } @Article{marta_mmndcm, @@ -2589,7 +2592,7 @@ @Article{mvb number = {1}, pages = {181--205}, doi = {10.1016/j.neuroimage.2007.08.013}, - keyword = {Bayesian} + keyword = {Bayesian,multivariate} } @Article{rm_massmodelspectral, @@ -3042,11 +3045,12 @@ @Article{jc_topoFDR author = jc # and # kjw # and # gf # and # karl, title = {Topological {FDR} for neuroimaging}, journal = ni, -year = {2009}, -volume = {}, -number = {}, -pages = {}, -doi = {10.1016/j.neuroimage.2009.10.090} +year = {2010}, +volume = {49}, +number = {4}, +pages = {3057--3064}, +doi = {10.1016/j.neuroimage.2009.10.090}, +keyword = {FDR,RFT,topological} } @Article{klaas_dcm_dwi, @@ -3134,10 +3138,12 @@ @Article{klaas_10rulesdcm title = {Ten simple rules for dynamic causal modelling}, journal = ni, year = {2010}, -volume = {in press}, -number = {}, -pages = {}, -doi = {10.1016/j.neuroimage.2009.11.015} +volume = {49}, +number = {4}, +pages = {3099--3109}, +doi = {10.1016/j.neuroimage.2009.11.015}, +keyword = {DCM}, +pdf = {/spm/doc/papers/Stephan_NeuroImage_49_3099_2010.pdf} } @Article{jean_dcmreview, @@ -3150,3 +3156,86 @@ @Article{jean_dcmreview pages = {}, doi = {10.1016/j.neuroimage.2009.11.062} } + +@Article{dcm_multi_subj, +author = {C.H. Kasess} # and # klaas # and # {A. Weissenbacher} # and # {L. Pezawas} # and # {E. Moser} # and # {C. Windischberger} , +title = {Multi-Subject Analyses with Dynamic Causal Modeling}, +journal = ni, +year = {2010}, +volume = {49}, +number = {4}, +pages = {3065--3074}, +doi = {10.1016/j.neuroimage.2009.11.037} +} + +@Article{dcm_families, +author = will # and # klaas # and # jean # and # mjr # and # karl # and # {T.M.Schofield} # and # {A.P. Leff}, +title = {Comparing Families of Dynamic Causal Models}, +journal = {PLoS Comput Biol}, +year = {2010}, +volume = {6}, +number = {3}, +pages = {e1000709}, +doi = {10.1371/journal.pcbi.1000709}, +pdf = {/spm/doc/papers/Penny_PLoSCompBiol_6_e1000709.pdf} +} + +@Article{hanneke_pe, +author = hdo # and # jean # and # {J. Roiser} # and # karl # and # klaas, +title = {Striatal Prediction Error Modulates Cortical Coupling}, +journal = jn, +year = {2010}, +volume = {30}, +number = {9}, +pages = {3210--3219}, +doi = {10.1523/JNEUROSCI.4458-09.2010}, +pdf = {/spm/doc/papers/DenOuden_JNeurosci_30_3210_2010.pdf} +} + +@Article{andre_neuropopdyn, +author = acm # and # sjk # and # karl, +title = {A dynamic causal model study of neuronal population dynamics}, +journal = ni, +year = {2010}, +volume = {51}, +number = {1}, +pages = {91--101}, +doi = {10.1016/j.neuroimage.2010.01.098} +} + +@Article{justin_poisson, +author = jc # and # gf # and # {M.H. Seghier} # and # karl, +title = {Multinomial inference on distributed responses in SPM}, +journal = ni, +year = {2010}, +volume = {in press}, +number = {}, +pages = {}, +doi = {10.1016/j.neuroimage.2010.05.076} +} + +@Article{klaas_effcon_fmri, +author = klaas # and # karl, +title = {Analyzing effective connectivity with functional magnetic resonance imaging}, +journal = {WIREs Cognitive Sience}, +year = {2010}, +volume = {1}, +number = {}, +pages = {446--459}, +doi = {10.1002/wcs.58}, +pdf = {/spm/doc/papers/Stephan_WIREsCognSci_1_446_2010.pdf}, +keyword = {DCM, fMRI} +} + +@Article{karl_generalised_filtering, +author = karl # and # klaas # and # bl # and # jean, +title = {Generalised Filtering}, +journal = {Mathematical Problems in Engineering}, +year = {2010}, +volume = {621670}, +number = {}, +pages = {}, +doi = {10.1155/2010/621670}, +pdf = {/spm/doc/papers/Friston_MathProblEngin_2010_621670.pdf}, +keyword = {} +} diff --git a/man/biblio/methods_macros.bib b/man/biblio/methods_macros.bib index d6c6f75..0b4b0d3 100644 --- a/man/biblio/methods_macros.bib +++ b/man/biblio/methods_macros.bib @@ -50,6 +50,7 @@ @string{oj @string{sjk = "S.J. Kiebel" } @string{jk = "J. Kilner" } @string{ll = "L. Lee" } +@string{bl = "Baojuan Li"} @string{vl = "V. Litvak" } @string{acm = "A.C. Marreiros" } @string{jm = "J. Mattout" } diff --git a/man/bms/Slide1.png b/man/bms/Slide1.png new file mode 100644 index 0000000..19b9913 Binary files /dev/null and b/man/bms/Slide1.png differ diff --git a/man/bms/Slide2.png b/man/bms/Slide2.png new file mode 100644 index 0000000..74b63a0 Binary files /dev/null and b/man/bms/Slide2.png differ diff --git a/man/bms/Slide3.png b/man/bms/Slide3.png new file mode 100644 index 0000000..08e4490 Binary files /dev/null and b/man/bms/Slide3.png differ diff --git a/man/bms/Slide4.png b/man/bms/Slide4.png new file mode 100644 index 0000000..9b7b660 Binary files /dev/null and b/man/bms/Slide4.png differ diff --git a/man/bms/Slide5.png b/man/bms/Slide5.png new file mode 100644 index 0000000..98e8fc4 Binary files /dev/null and b/man/bms/Slide5.png differ diff --git a/man/bms/Slide6.png b/man/bms/Slide6.png new file mode 100644 index 0000000..4561597 Binary files /dev/null and b/man/bms/Slide6.png differ diff --git a/man/bms/bms.tex b/man/bms/bms.tex new file mode 100644 index 0000000..8857b97 --- /dev/null +++ b/man/bms/bms.tex @@ -0,0 +1,220 @@ +\chapter{Bayesian Model Inference \label{Chap:data:dcm_bms}} + +This chapter describes the use of SPM's Bayesian Model Inference capabilities. +For a fuller background on this topic see \cite{dcm_families}. +We illustrate the methods using a DCM for fMRI study of the languange system. + +\section{Background} + +The neuroimaging data derive from an fMRI study on the cortical dynamics of intelligible speech \cite{leff_speech}. +This study applied dynamic causal modelling of fMRI responses to investigate activity among three key multimodal regions: the left posterior and anterior superior temporal sulcus (subsequently referred to as regions P and A respectively) and pars orbitalis of the inferior frontal gyrus (region F). +The aim of the study was to see how connections among regions depended on whether the auditory input was intelligible speech or time-reversed speech. + +The basic DCM, from which all other models were derived, is shown in figure~\ref{dcms}. Auditory input enters region P and the three areas have full intrinsic connectivity. The modulatory input, encoding whether or not the auditory stimulus was speech or reversed speech, was then allowed to modulate a +subset of connections in the model. These are the forward and backward connections between P and F, and the forward and backward connections between P and A. As these are either present or absent this results in $2^4=16$ different DCMs. + +\begin{figure} +\begin{center} +\includegraphics[width=100mm]{bms/Slide1.png} +\caption{All DCMs were fully connected ie. there were endogenous connections between all three regions (dotted lines) (i) left posterior temporal sulcus (region P), (ii) left anterior superior temporal sulcus (region A) and (iii) pars orbitalis of the inferior frontal gyrus (region F). Auditory input enters region P. The sixteen models differ in their modulatory connectivity (solid lines) \label{dcms}} +\end{center} +\end{figure} + +\section{Data} + +An archive containing 16 DCMs for each of 12 subjects can be downloaded from the +SPM web page. This archive is called \verb!dcm_bms.zip!. When you extract the data onto your computer a number of subdirectories will be created - one for each of the 12 subjects. The 16 DCMs for each subject are then available in these subject-specific directories. You can load one of these into SPM and examine the information contained therein. + +These DCM files contain the usual information eg. the original time series from each region of interest are available in +\verb!DCM.xY(1)! for region 1, wherein \verb!DCM.xY(1).name='PSTS_6'! indicates this is the posterior temporal region. The estimated parameter values are available in \verb!DCM.Ep!. You should note that these DCMs were specified and estimated using SPM revision 3894 (from May 2010) and that these DCM structures +differ from earlier SPM releases. + +Also in the Zip archive is a file called \verb!model_space.mat!. If you \verb!load model_space!, you will see that it contains a data structure called \verb!subj! with subfields 'sess' and then 'model'. If you type eg. \verb!subj(1).sess(1).model(1)! you will see four further subfields containing information about the first DCM for subject 1. This comprises the filename (fname), the free energy approximation to the model evidence (F), posterior mean parameters (Ep), and the posterior covariance of parameters (Cp). + +The use of a `model space' file makes use of SPMs Bayesian model comparison (BMC) routines much simpler. If this file is not specified it will be automatically generated (from the DCM files) the first time you use the BMC routines (see below). Alternatively, you can easily create your own model space file. To get the current file to work on your system you will need to change all of the filenames (fname) so that they correspond to the positions of the DCM files in your filespace. You can do this with the \verb!model_space_filenames! function (also provided in the Zip archive). + +\section{Analysis} + +After unzipping the archive, correct the model space filenames using the +command\newline \verb!subj=model_space_filenames(subj,new_base_dir)! where \verb!new_base_dir! is the name of the directory where you have unzipped the archive. This should be something like \newline \verb!'C:\blah\blah\blah\dcm-base-files'!. Then save \verb!subj! back in the model space file using \verb!save model_space subj!. + +\subsection{Single Family} + +Now open SPM and in the Menu window go to Batch, SPM, Stats, Bayesian Model Selection, BMS:DCM. This will open SPM's batch editor. Select an appropriate directory (eg. where you unzipped the archive), highlight Load model space and select the \verb!model_space.mat! file. +For inference method select 'FFX'. Save the batch job as \verb!ffx_all_models.mat!, then press the green play button to run the job. +This will produce the figure~\ref{ffx_model}, showing that model 6 is the best model. + +\begin{figure} +\begin{center} +\includegraphics[width=150mm]{bms/Slide2.png} +\caption{Fixed effects model inference\label{ffx_model}} +\end{center} +\end{figure} + +We can now go back and load the \verb!ffx_all_models.mat! job in the batch editor (press the Batch button) and change the inference methods to RFX. This will produce something like the results in figure~\ref{rfx_model} (note that the RFX approach uses a sampling procedure with a different random initial seed on each run, so the results can vary slighlty from run to run). Again, model 6 is the best model, but not by much. These RFX results will be stored in the same \verb!BMS.mat! file as the FFX results. + +\begin{figure} +\begin{center} +\includegraphics[width=150mm]{bms/Slide3.png} +\caption{Random effects model inference\label{rfx_model}} +\end{center} +\end{figure} + +\subsection{Bayesian Model Averaging} + +Now go back into the batch editor and reload the \verb!ffx_all_models.mat! job. +Highlight BMA, and select Choose family (instead of 'Do not compute'). Accept the 'Winning Family' option. The BMA results will be saved in the same BMS.mat file as the previous analyses. Now go ahead and press the green play button. +SPM will do the FFX model inference (again), but will also implement a weighted average of the model parameters where the weights are given by the evidence for each model, as described in \cite{dcm_families}. After the averaging is complete, SPM will report the number of models in Occams window. This should be 10 models (models 5,6,7,8,11,12,13,14,15,16). + +To look at the BMA results, go to the Menu window and press the Dynamic Causal Modelling button. Then select Average, select BMA, and then the BMS.mat file just created. Then select FFX for the inference method. If you then highlight the tab (top left) to select the modulatory variables you should get the plot shown in figure~\ref{bma}. + +\begin{figure} +\begin{center} +\includegraphics[width=150mm]{bms/Slide4.png} +\caption{Bayesian model averaging over all 16 models\label{bma}} +\end{center} +\end{figure} + +\subsection{Family level inference} + +The results so far have made no use of SPM's family inference procedure. +Or rather, they have, but have assumed that all models belong to the same family. + +Open the \verb!ffx_all_models.mat! batch file again, highlight Family inference and select Load family. Highlight Load family and select the \verb!pf_family.mat! file contained in the Zip archive. This comprises two families (i) those with a forward connection from P to F ('PF'), and (ii) those without it ('No PF'). Set the BMA option to Do not Compute. Select a new directory you have created for this analysis (eg pf-family) and run the job. +SPM will create the family level inference plot shown in figure~\ref{family}. +This gives a 90\% posterior probability to models with the P to F connection. + +We will now repeat the analysis but with RFX inference. You should see a result similar to that shown in +figure~\ref{rfx_family}. + +\subsection{Summary Statistics and Group Analyses} + +The group mean DCM parameters can be easily obtained from the \matlab\ command window by loading the \verb!BMS.mat! file and then typing: \verb!BMS.DCM.ffx.bma.Ep!. + +The subject specific mean DCM parameters can be obtained as follows: \verb!BMS.DCM.ffx.bma.Eps(n)!, where $n$ is the subject number. For random-effects change \verb!ffx! to \verb!rfx!. + +If we are interested in the modulatory connection from region 1 to region 3 (that is modulated by the second input), then the mean value of this for Subject 10 is given by\newline \verb!BMS.DCM.ffx.bma.Eps(10).B(3,1,2)! (which should be 0.7475). The mean connection values for all subjects (12) can be gotten with the \matlab\ syntax \newline \verb!for i=1:12, b(i) = BMS.DCM.ffx.bma.Eps(i).B(3,1,2); end!. + +These subject specific mean parameters can then act as summary statistics for a standard group analysis. For example to look for significant differences between eg. a control group and a patient group in a modulatory parameter one would implement a two-sample t-test on data from the appropriate entries in the \verb!mean_bs! matrices. Similarly, if one has 3 groups one would use a 3-level ANOVA. + +\begin{figure} +\begin{center} +\includegraphics[width=150mm]{bms/Slide5.png} +\caption{FFX family inference\label{family}} +\end{center} +\end{figure} + +\begin{figure} +\begin{center} +\includegraphics[width=150mm]{bms/Slide6.png} +\caption{RFX family inference\label{rfx_family}} +\end{center} +\end{figure} + +\section{BMS.mat file} + +The BMS structure saved in BMS.mat file contains the following variables\footnote{nm = number of models; nfam = number of families; nsub = number of subjects; nsamp = number of samples; dima/b/c/d = dimensions of a/b/c/d DCM parameters; np = number of model parameters; nsess = number of sessions.}: + +\paragraph{BMS.DCM.ffx/rfx} (fixed-effects (FFX) / random-effects (RFX) analysis)\\\\ + +\begin{tabular}{ l l } +\bf{.data} & path to model\_space.mat file (see below). \\ +\bf{.F\_fname} & path to file containing the log evidence matrix, F, (if this option is specified). \\ +\bf{.F} & matrix of log model evidences for all subjects and models, [nsub $\times$ nm]. \\ +\bf{.SF} & vector of summed log evidences over subjects [1 $\times$ nm]. \\ +\bf{.model} & results from model level inference (see below). \\ +\bf{.family} & results from family level inference (see below). \\ +\bf{.bma} & results from Bayesian model averaging (see below). \\ +\end{tabular} + +\subsection{Model level results} + +\hspace{4mm} Fixed-effects:\\ + +\begin{tabular}{ l l l } +\bf{model} & & \\ +& \bf{.prior} & model priors, $p(m)$, [1 $\times$ nm]. \\ +& \bf{.subj\_lme} & log model evidence matrix, [nsub $\times$ nm]. \\ +& \bf{.like} & model likelihoods, $p(Y|m)$, [1 $\times$ nm]. \\ +& \bf{.posts} & model posterior probabilities, $p(m|Y)$, [1 $\times$ nm]. \\ +\end{tabular}\\\\ + +Random-effects (different from fixed-effects):\\ + +\begin{tabular}{ l l l } +\bf{model} & & \\ +& \bf{.alpha0} & initial Dirichlet parameters (prior counts), $\alpha_0$, [1 $\times$ nm].\\ +& \bf{.exp\_r} & model posterior means, $$, [1 $\times$ nm].\\ +& \bf{.xp} & model exceedance probabilities, $\psi_m$ [1 $\times$ nm].\\ +& \bf{.r\_samp} & samples from the model posterior density, $p(r|Y)$, [nsamp $\times$ nm].\\ +& \bf{.g\_post} & posterior model probabilities for subject n and model m, $p(m_n|Y)$, [nsub $\times$ nm]. +\end{tabular}\\ + +\subsection{Family level results} + +\hspace{4mm} Fixed-effects:\\ + +\begin{tabular}{ l l l } +\bf{family} & & \\ +& \bf{.names} & family names, ex: $\{$`F1', `F2', `F3'$\}$.\\ +& \bf{.partition} & partition vector assigning each model to a family [1 $\times$ nm].\\ +& \bf{.infer } & inference method (`ffx' or `rfx').\\ +& \bf{.prior} & family priors, $p(f_k)$, [1 $\times$ nfam].\\ +& \bf{.post} & family posterior probabilities, $p(f_k|Y)$, [1 $\times$ nfam].\\ +& \bf{.like} & family likelihoods, $p(Y| f_k)$, [1 $\times$ nfam]. +\end{tabular}\\\\ + +Random-effects (different from fixed-effects):\\ + +\begin{tabular}{ l l l } +\bf{family} & & \\ +& \bf{.Nsamp} & number of samples used in GibbsÕ sampling (default = 20000).\\ +& \bf{.prior } & family type of priors (`F-unity', $\alpha_0=1$, for each family, is the default; \\ +& & other option, `M-unity', $\alpha_0=1$, for each model) .\\ +& \bf{.alpha0} & initial values of the Dirichlet parameters (prior counts), $\alpha_{prior}(m)$, [1 $\times$ nfam].\\ +& \bf{.s\_samp} & samples from family posterior density, $p(s|Y)$, [nsamp $\times$ nfam].\\ +& \bf{.exp\_r} & family posterior means, $$, [1 $\times$ nfam].\\ +& \bf{.xp} & family exceedance probabilities, $\psi_k$, [1 $\times$ nfam]. +\end{tabular}\\ + +\subsection{Bayesian model averaging (BMA)} + +\hspace{4mm} Fixed-effects:\\ + +\begin{tabular}{ l l l } +\bf{bma} & & \\ +& \bf{.nsamp} & number of samples used to average parameters (default = 10000). \\ +& \bf{.oddsr} & posterior odds ratio, $\pi_{OCC}$, (number of models in OccamÕs window, \\ +& & default = 0). \\ +& \bf{.Nocc} & number of models in Occam's window. \\ +& \bf{.Mocc} & index of models in Occam's window, [1 $\times$ nm]. \\ +& \bf{.indx} & index of models in Occam's window (different for each subject in RFX),\\ +& & [1 $\times$ nm]. \\ +& \bf{.a} & samples from posterior density over DCM.a parameters [dima $\times$ nsamp]. \\ +& \bf{.b} & samples from posterior density over DCM.b parameters [dimb $\times$ nsamp]. \\ +& \bf{.c} & samples from posterior density over DCM.c parameters [dimc $\times$ nsamp]. \\ +& \bf{.d} & samples from posterior density over DCM.d parameters [dimd $\times$ nsamp]. \\ +& \bf{.mEp} & mean DCM parameters [1 $\times$ 1 struct]. \\ +& \bf{.sEp} & standard deviation of DCM parameters [1 $\times$ 1 struct]. \\ +& \bf{.mEps} & mean DCM parameters per subject [1 $\times$ nsub struct]. \\ +& \bf{.sEps} & standard deviation DCM parameters per subject [1 $\times$ nsub struct]. \\ +\end{tabular}\\\\ + +Random-effects - same variables as in fixed-effects. + +\section{model\_space.mat file} + +This structure is created automatically if it doesn't exist in the chosen directory and can be loaded for subsequent analyses as a faster option to reading the DCM.mat files. The model\_space.mat file contains the following structure:\\\\ + +\begin{tabular}{ l l l } +\bf{subj(nsub).sess(nsess).model(nm)} & & \\ + & \bf{.fname} & path to DCM.mat file. \\ + & \bf{.F} & log-evidence (free energy). \\ + & \bf{.Ep} & parameter estimates: conditional expectation,\\ + & & [np $\times$ 1]. \\ +& \bf{.Cp} & parameter estimates: conditional covariance,\\ +& & [np $\times$ np]. +\end{tabular}\\\\ + +For a detailed description of all the variables and methods please see \cite{dcm_families} and \cite{klaas_bms}. + diff --git a/man/dartelguide/dartelguide.tex b/man/dartelguide/dartelguide.tex index 7c64d1b..7314116 100644 --- a/man/dartelguide/dartelguide.tex +++ b/man/dartelguide/dartelguide.tex @@ -23,6 +23,7 @@ \section{Using DARTEL for VBM \label{Sec:dartel_vbm}} Alternatively, the {\bf New Segment} procedure could be used. Although still at the slightly experimental stages of development, this procedure has been found to be generally more robust than the implementation of ``Unified Segmentation'' from SPM$\rightarrow$Spatial$\rightarrow$Segment (which is the version from the Segment button - the same as that in SPM5). +The new segmentation can require quite a lot of memory, so if you have large images (typically greater than about $256\times256\times150$) and trying to run it on a 32 bit computer or have relatively little memory installed, then it may throw up an out of memory error. The new segmentation procedure includes the option to generate DARTEL ``imported'' data, so the {\bf Initial Import} step is skipped. \begin{itemize} \item{{\bf Module List} diff --git a/man/dcm/Fig1.png b/man/dcm/Fig1.png index 4319e7d..9f5047f 100644 Binary files a/man/dcm/Fig1.png and b/man/dcm/Fig1.png differ diff --git a/man/dcm/Fig2.png b/man/dcm/Fig2.png index 4e5249d..40b50b5 100644 Binary files a/man/dcm/Fig2.png and b/man/dcm/Fig2.png differ diff --git a/man/dcm/Fig3.png b/man/dcm/Fig3.png index 250a475..c0a27f7 100644 Binary files a/man/dcm/Fig3.png and b/man/dcm/Fig3.png differ diff --git a/man/dcm/Fig4.png b/man/dcm/Fig4.png index 6344eab..662c387 100644 Binary files a/man/dcm/Fig4.png and b/man/dcm/Fig4.png differ diff --git a/man/dcm/Fig5.png b/man/dcm/Fig5.png index b744f66..b96ba83 100644 Binary files a/man/dcm/Fig5.png and b/man/dcm/Fig5.png differ diff --git a/man/dcm/Fig6.png b/man/dcm/Fig6.png index 5fb4cc7..37a9e88 100644 Binary files a/man/dcm/Fig6.png and b/man/dcm/Fig6.png differ diff --git a/man/dcm/Fig7.png b/man/dcm/Fig7.png index 2b91f31..65a9f78 100644 Binary files a/man/dcm/Fig7.png and b/man/dcm/Fig7.png differ diff --git a/man/dcm/Fig8.png b/man/dcm/Fig8.png index 64a4097..c67524b 100644 Binary files a/man/dcm/Fig8.png and b/man/dcm/Fig8.png differ diff --git a/man/dcm/Fig9.png b/man/dcm/Fig9.png new file mode 100644 index 0000000..79bbfde Binary files /dev/null and b/man/dcm/Fig9.png differ diff --git a/man/dcm/dcm.tex b/man/dcm/dcm.tex index ebc0e3c..bc7e354 100644 --- a/man/dcm/dcm.tex +++ b/man/dcm/dcm.tex @@ -2,16 +2,16 @@ \chapter{Dynamic Causal Modeling for fMRI \label{Chap:DCM_fmri}} \section{Theoretical background} -Dynamic Causal Modelling (DCM) is a method for making inferences about neural processes that underlie measured time series, e.g. fMRI data. The general idea is to estimate the parameters of a reasonably realistic neuronal system model such that the predicted blood oxygen level dependent (BOLD) signal, which results from converting the modeled neural dynamics into hemodynamic responses, corresponds as closely as possible to the observed BOLD time series. This section gives a short introduction to the theoretical background of DCM for fMRI; details can be found in \cite{dcm}. Note that DCMs can be formulated, in principle, for any measurement technique. Depending on the spatio-temporal properties of a given measurement technique, one needs to define an adequate state equation and an observation model. See Fig~\ref{fig1} for a summary of the differences between DCM implementations for fMRI and Event-Related Potentials (ERPs). +Dynamic Causal Modelling (DCM) is a method for making inferences about neural processes that underlie measured time series, e.g. fMRI data. The general idea is to estimate the parameters of a reasonably realistic neuronal system model such that the predicted blood oxygen level dependent (BOLD) signal, which results from converting the modeled neural dynamics into hemodynamic responses, corresponds as closely as possible to the observed BOLD time series. This section gives a short introduction to the theoretical background of DCM for fMRI; details can be found in \cite{dcm}. Note that DCMs can be formulated, in principle, for any measurement technique. Depending on the spatio-temporal properties of a given measurement technique, one needs to define an adequate state equation and an observation model. See Fig~\ref{dcm_fig1} for a summary of the differences between DCM implementations for fMRI and Event-Related Potentials (ERPs). \begin{figure}[ht] \begin{center} \includegraphics[width=100mm]{dcm/Fig1} -\caption{\em A schematic overview of the differences between between the DCM implementations for fMRI and ERPs (as measured by EEG or MEG). Whereas the state equation of DCM for fMRI is bilinear and uses only a single state variable per region, that for ERPs is more complex and requires 8 state variables per region. Moreover, DCM for ERPs models the delays of activity propagation between areas. At the level of the observation model, DCM for fMRI is more complex than DCM for ERPs. While the former uses a non-linear model of the hemodynamic response that contains a cascade of differential equations with five state variables per region, the latter uses a simple linear model for predicting observed scalp data.\label{fig1}} +\caption{\em A schematic overview of the differences between between the DCM implementations for fMRI and ERPs (as measured by EEG or MEG). Whereas the state equation of DCM for fMRI is bilinear and uses only a single state variable per region, that for ERPs is more complex and requires 8 state variables per region. Moreover, DCM for ERPs models the delays of activity propagation between areas. At the level of the observation model, DCM for fMRI is more complex than DCM for ERPs. While the former uses a non-linear model of the hemodynamic response that contains a cascade of differential equations with five state variables per region, the latter uses a simple linear model for predicting observed scalp data.\label{dcm_fig1}} \end{center} \end{figure} -As in state-space models, two distinct levels constitute a DCM (see Figure~\ref{fig2}). The hidden level, which cannot be directly observed using fMRI, represents a simple model of neural dynamics in a system of $k$ coupled brain regions. Each system element $i$ is represented by a single state variable $z_i$, and the dynamics of the system is described by the change of the neural state vector over time. +As in state-space models, two distinct levels constitute a DCM (see Figure~\ref{dcm_fig2}). The hidden level, which cannot be directly observed using fMRI, represents a simple model of neural dynamics in a system of $k$ coupled brain regions. Each system element $i$ is represented by a single state variable $z_i$, and the dynamics of the system is described by the change of the neural state vector over time. The neural state variables do not correspond directly to any common neurophysiological measurement (such as spiking rates or local field potentials) but represent a summary index of neural population dynamics in the respective regions. Importantly, DCM models how the neural dynamics are driven by external perturbations that result from experimentally controlled manipulations. These perturbations are described by means of external inputs $u$ that enter the model in two different ways: they can elicit responses through direct influences on specific regions (``driving'' inputs, e.g. evoked responses in early sensory areas) or they can change the strength of coupling among regions (``modulatory'' inputs, e.g. during learning or attention). @@ -23,7 +23,7 @@ \section{Theoretical background} .. \\ \dot{z}_k \\ \end{array} \right] = \dot{z}= \frac{dz}{dt} = F(z,u,\theta^n) \end{equation} -In this neural state equation, the state $z$ and the inputs $u$ are time-dependent whereas the parameters are time-invariant. In DCM, $F$ has the bilinear form +In this neural state equation, the state $z$ and the inputs $u$ are time-dependent whereas the parameters are time-invariant. In DCM, $F$ has the bilinear form \begin{equation} \dot{z}=Az+\sum_{j=1}^m u_j B_j z + Cu \end{equation} @@ -38,7 +38,7 @@ \section{Theoretical background} \begin{figure}[ht] \begin{center} \includegraphics[width=130mm]{dcm/Fig2} -\caption{\em Schematic summary of the conceptual basis of DCM. The dynamics in a system of interacting neuronal populations (orange boxes), which are not directly observable by fMRI, is modeled using a bilinear state equation (grey box). Integrating the state equation gives predicted neural dynamics ($z$) that enter a model of the hemodynamic response ($\lambda$) to give predicted BOLD responses ($y$) (green boxes). The parameters at both neural and hemodynamic levels are adjusted such that the differences between predicted and measured BOLD series are minimized. Critically, the neural dynamics are determined by experimental manipulations. These enter the model in the form of ``external'' or ``driving'' inputs. Driving inputs ($u_1$; e.g. sensory stimuli) elicit local responses directly that are propagated through the system according to the intrinsic connections. The strengths of these connections can be changed by modulatory inputs ($u_2$; e.g. changes in cognitive set, attention, or learning).\label{fig2}} +\caption{\em Schematic summary of the conceptual basis of DCM. The dynamics in a system of interacting neuronal populations (orange boxes), which are not directly observable by fMRI, is modeled using a bilinear state equation (grey box). Integrating the state equation gives predicted neural dynamics ($z$) that enter a model of the hemodynamic response ($\lambda$) to give predicted BOLD responses ($y$) (green boxes). The parameters at both neural and hemodynamic levels are adjusted such that the differences between predicted and measured BOLD series are minimized. Critically, the neural dynamics are determined by experimental manipulations. These enter the model in the form of ``external'' or ``driving'' inputs. Driving inputs ($u_1$; e.g. sensory stimuli) elicit local responses directly that are propagated through the system according to the intrinsic connections. The strengths of these connections can be changed by modulatory inputs ($u_2$; e.g. changes in cognitive set, attention, or learning).\label{dcm_fig2}} \end{center} \end{figure} @@ -56,18 +56,18 @@ \section{Theoretical background} Details of the parameter estimation scheme, which rests on a Fisher scoring gradient ascent scheme with Levenburg-Marquardt regularisation, embedded in an expectation maximization (EM) algorithm, can be found in the original DCM publication (Friston et al. 2003). In brief, under Gaussian assumptions about the posterior distributions, this scheme returns the posterior expectations $\eta_{\theta | y}$ and posterior covariance $C_{\theta | y}$ for the parameters as well as hyperparameters for the covariance of the observation noise, $C_e$. -After fitting the model to measured BOLD data, the posterior distributions of the parameters can be used to test hypotheses about the size and nature of effects at the neural level. Although inferences could be made about any of the parameters in the model, hypothesis testing usually concerns context-dependent changes in coupling (i.e. specific parameters from the $B$ matrices; see Fig.~\ref{fig6}). As will be demonstrated below, at the single-subject level, these inferences concern the question of how certain one can be that a particular parameter or, more generally, a contrast of parameters, $c^T \eta_{\theta | y}$, exceeds a particular threshold $\gamma$ (e.g. zero). +After fitting the model to measured BOLD data, the posterior distributions of the parameters can be used to test hypotheses about the size and nature of effects at the neural level. Although inferences could be made about any of the parameters in the model, hypothesis testing usually concerns context-dependent changes in coupling (i.e. specific parameters from the $B$ matrices; see Fig.~\ref{dcm_fig4}). As will be demonstrated below, at the single-subject level, these inferences concern the question of how certain one can be that a particular parameter or, more generally, a contrast of parameters, $c^T \eta_{\theta | y}$, exceeds a particular threshold $\gamma$ (e.g. zero). Under the assumptions of the Laplace approximation, this is easy to test ($\Phi_N$ denotes the cumulative normal distribution): \begin{equation} p(c^T \eta_{\theta | y} > \gamma) = \Phi_N \left(\frac{c^T \eta_{\theta | y} - \gamma}{c^T C_{\theta | y} c} \right) \end{equation} For example, for the special case $c^T \eta_{\theta | y} = \gamma$ the probability is $p(c^T \eta_{\theta | y} > \gamma)=0.5$, i.e. it is equally likely that the parameter is smaller or larger than the chosen threshold $\gamma$. -We conclude this section on the theoretical foundations of DCM by noting that the parameters can be understood as rate constants (units: $1/s = Hz$) of neural population responses that have an exponential nature. This is easily understood if one considers that the solution to a linear ordinary differential equation of the form $\dot{z}=Az$ is an exponential function (see Fig. ~\ref{fig3}). +We conclude this section on the theoretical foundations of DCM by noting that the parameters can be understood as rate constants (units: $1/s = Hz$) of neural population responses that have an exponential nature. This is easily understood if one considers that the solution to a linear ordinary differential equation of the form $\dot{z}=Az$ is an exponential function (see Fig. ~\ref{dcm_fig3}). \begin{figure}[ht] \begin{center} \includegraphics[width=120mm]{dcm/Fig3} -\caption{\em A short mathematical demonstration, using a simple linear first-order differential equation as an example, explaining why the coupling parameters in a DCM are inversely proportional to the half-life of the modelled neural responses and are therefore in units of 1/s = Hertz.\label{fig3}} +\caption{\em A short mathematical demonstration, using a simple linear first-order differential equation as an example, explaining why the coupling parameters in a DCM are inversely proportional to the half-life of the modelled neural responses and are therefore in units of 1/s = Hertz.\label{dcm_fig3}} \end{center} \end{figure} @@ -106,43 +106,106 @@ \section{Bayesian model selection \label{mc}} \section{Practical example} -The following example refers to the ``attention to visual motion'' data set available from the SPM web site\footnote{Attention to visual motion dataset: \url{http://www.fil.ion.ucl.ac.uk/spm/data/attention/}}. This data set was obtained by Christian Buchel and is described in \cite{buchel97}. Note that the data available from the web have been pre-processed using SPM99, therefore ensure \texttt{flip} is set to \texttt{1} in the \texttt{spm\_flip\_analyze\_images.m} file before proceeding further. +The following example refers to the ``attention to visual motion'' data set available from the SPM web site\footnote{Attention to visual motion dataset: \url{http://www.fil.ion.ucl.ac.uk/spm/data/attention/}}. This data set was obtained by Christian Buchel and is described in \cite{buchel97}. + +The archive contains the smoothed, spatially normalised, realigned, slice-time corrected images in the directory \texttt{functional}. The directory \texttt{structural} contains a spatially normalised structural image. All processing took place using SPM99, but the image files have been converted into NIfTI format. Making a DCM requires two ingredients: (i) a design matrix and (ii) the time series, stored in VOI files. The regressors of the design matrix define the inputs for the DCM. Note that this means that the design matrix that is optimal for a given DCM is often somewhat different than the one for the corresponding GLM. DCM does not require the design matrix to be part of an estimated model, however. It just needs to be defined. \subsection{Defining the GLM} The present experiment consisted of 4 conditions: (i) fixation (F), (ii) static (S, non-moving dots), (iii) no attention (N, moving dots but no attention required), (iv) attention (A). The GLM analyses by Christian showed that activity in area V5 was not only enhanced by moving stimuli, but also by attention to motion. In the following, we will try to model this effect in V5, and explain it as a context-dependent modulation or ``enabling'' of V5 afferents, using a DCM. First, we need to set up the GLM analysis and extract our time series from the results. In this example, we want to use the same design matrix for GLM and DCM, therefore we recombine the above regressors to get the following three conditions: \begin{enumerate} -\item{{\bf photic}: this comprises all conditions with visual input, i.e. S, N, and A.} -\item{{\bf motion}: this includes all conditions with moving dots, i.e. N and A.} -\item{{\bf attention}: this includes the attention-to-motion (A) condition only.} + \item \textbf{photic}: this comprises all conditions with visual input, i.e. S, N, and A. + \item \textbf{motion}: this includes all conditions with moving dots, i.e. N and A. + \item \textbf{attention}: this includes the attention-to-motion (A) condition only. \end{enumerate} -Now we need to define and estimate the GLM. See chapters \ref{Chap:fmri_spec} and \ref{Chap:fmri_est} on how to do this. Here are the relevant details for this data set that you need to set up the GLM (this information can also be found online\footnote{\url{ftp://ftp.fil.ion.ucl.ac.uk/spm/data/attention/README_GLM_DCM.txt}} -note this web site describes the analysis for SPM2). +Now we need to define and estimate the GLM. This is not the main topic of this chapter so you should already be familiar with these procedures, see \ref{Chap:fmri_spec} and \ref{Chap:fmri_est} for more information. Here are the relevant details for this data set that you need to set up the GLM: \begin{itemize} -\item{The onsets for the conditions can be found in the file factors.mat. They are named phot (photic), mot (motion) and att (attention) and are defined in scans (not seconds!). They are blocks of 10 TRs each.} -\item{The TR is 3.22 seconds.} -\item{There are 360 scans.} + \item The onsets for the conditions can be found in the file \texttt{factors.mat}. They are named \texttt{stat} (static), \texttt{natt} (no attention) and \texttt{att} (attention) and are defined in scans (not seconds). They are blocks of 10 TRs each. + \item The TR is 3.22 seconds. + \item There are 360 scans. \end{itemize} +Let's specify a batch that will specify the model and estimate it. + +\begin{enumerate} + \item The analysis directory should include + \begin{enumerate} + \item A directory named \texttt{functional}, which includes the preprocessed fMRI volumes. + \item A directory named \texttt{structural}, which includes a normalised T1 structural volume + \item File \texttt{factors.mat}. + \item You will also need to make a new directory called \texttt{GLM} that will contain the analysis. + \end{enumerate} + \item In \matlab\ type +\begin{verbatim} +>> cd GLM +>> spm fmri +\end{verbatim} + \item From the main SPM window, click on the \textsc{Batch} button. + \item From the SPM menu at the top of the Batch Editor, select ``Stats $>$ fMRI model specification''. + \item Click \textsc{Directory} and choose the \texttt{GLM} directory that you made above. + \item \textsc{Units for design} [\textsc{scans}] + \item \textsc{Interscan interval} [3.22] + \item Click \textsc{Data \& Design}, Choose \textsc{New "Subject/Session"} + \item Click \textsc{Scans} and choose all the functional scans \texttt{snffM00587\_00xx.img}. There should be 360 \texttt{*.img} files. + \item Load the MAT-file containing the individual conditions in \matlab\ workspace: +\begin{verbatim} +>> load factors.mat +\end{verbatim} +You can look at the loaded variables by typing the variable names. +(\texttt{stat} = stationary, \texttt{natt} = no attention, \texttt{att} = attention) +\begin{verbatim} +>> stat +>> natt +>> att +\end{verbatim} + \item Create 3 \textsc{New: Condition} under \textsc{Conditions} so that: + \begin{itemize} + \item Condition 1: \textsc{Name} = \texttt{Photic}, \textsc{Onsets} = \texttt{[att natt stat]} and \textsc{Durations} = \texttt{10}. + \item Condition 2: \textsc{Name} = \texttt{Motion}, \textsc{Onsets} = \texttt{[att natt]} and \textsc{Durations} = \texttt{10}. + \item Condition 3: \textsc{Name} = \texttt{Attention}, \textsc{Onsets} = \texttt{att} and \textsc{Durations} = \texttt{10}. + \end{itemize} + \item From the SPM menu at the top of the Batch Editor, select ``Stats $>$ model estimation''. + \item For \textsc{Select SPM.mat}, click on the \textsc{Dependency} button and choose the proposed item (the output from the previous module). + \item You should now be able to press the \textsc{Run} green arrow at the top of the Batch Editor window. This will specify and estimate the GLM. +\end{enumerate} + \subsection{Extracting time series} -Once you have specified and estimated the GLM, you should define t-contrasts that test for photic, motion, and attention, respectively. These serve to locate areas that show effects due to visual stimulation (e.g. in V1), motion (e.g. V5) and attention (e.g. V5 and superior parietal cortex, SPC). Because V5 shows both motion and attention effects, it is useful to mask the motion-contrast inclusively with the attention-contrast when extracting time series for V5. You should also compute the usual ``effects of interest'' F-contrast, this is needed for mean-correcting the extracted time series (see below). Here is a step-by-step example for extracting the V5 time series: +Once you have specified and estimated the GLM, you should define t-contrasts that test for photic, motion, and attention, respectively. These serve to locate areas that show effects due to visual stimulation (e.g. in V1), motion (e.g. V5) and attention (e.g. V5 and superior parietal cortex, SPC). Because V5 shows both motion and attention effects, it is useful to mask the motion-contrast inclusively with the attention-contrast when extracting time series for V5. You should also compute the usual ``effects of interest'' F-contrast, this is needed for mean-correcting the extracted time series (see below). + +\begin{enumerate} + \item From the main SPM window, click on the \textsc{Batch} button. + \item Add a module ``SPM $>$ Stats $>$ Contrast manager''. + \item For \textsc{Select SPM.mat}, enter the one that has been created in the previous step. + \item Under \textsc{Contrast Sessions}, choose one \textsc{New: F-contrast} and three \textsc{New: T-contrast} and enter + \begin{itemize} + \item F-contrast: \textsc{Name} = \texttt{Effects of interest}, \textsc{F contrast vector} = \texttt{eye(3)}. + \item T-contrast: \textsc{Name} = \texttt{Photic}, \textsc{T contrast vector} = \texttt{[1 0 0]}. + \item T-contrast: \textsc{Name} = \texttt{Motion}, \textsc{T contrast vector} = \texttt{[0 1 0]}. + \item T-contrast: \textsc{Name} = \texttt{Attention}, \textsc{T contrast vector} = \texttt{[0 0 1]}. + \end{itemize} + \item Press the \textsc{Run} green arrow at the top of the Batch Editor window. This will specify and estimate these 4 contrasts. +\end{enumerate} + +Here is now a step-by-step example for extracting the V5 time series: \begin{enumerate} -\item{Press ``Results''.} -\item{Select the \texttt{SPM.mat} file.} -\item{Choose the t-contrast for the motion condition.} -\item{Mask with other contrasts: Yes} -\item{Choose the t-contrast for the attention condition.} -\item{Mask inclusively and choose a threshold of $p \leq 0.05$ uncorrected.} -\item{Select the local maximum of a blob that looks V5-ish, e.g. -45/-81/-9 (by overlaying the activations onto the normalised structural image you should be able to identify V5 more easily).} -\item{Press the ``VOI'' button.} -\item{Name of region: V5} -\item{Adjust data for: effects of interest (this mean-corrects the time series)} -\item{VOI definition: sphere} -\item{VOI radius(mm): e.g. 8 mm} + \item Press \textsc{Results}. + \item Select the \texttt{SPM.mat} file. + \item Choose the t-contrast for the \texttt{Motion} condition. + \item Mask with other contrasts: Yes + \item Choose the t-contrast for the \texttt{Attention} condition. + \item Mask inclusively and choose a threshold of $p \leq 0.05$ uncorrected. + \item Select the global maxima that looks V5-ish, e.g. \texttt{[-36 -87 -3]} (by overlaying the activations onto the normalised structural image you should be able to identify V5 more easily). + \item Press the \textsc{eigenvariate} button. + \item Name of region: \texttt{V5} + \item Adjust data for: \texttt{Effects of interest} (this effectively mean-corrects the time series) + \item VOI definition: \texttt{sphere} + \item VOI radius(mm): e.g. \texttt{8} mm \end{enumerate} -SPM now computes the first principal component of the time series from all voxels included in the sphere. The result is stored (together with the original time series) in a file named \verb!VOI_V5_1.mat! in the working directory. You can now proceed to select time series for V1 (using the ``photic'' contrast) and SPC (using the ``attention'' contrast). For this example, we selected -6/-84/-6 for V1 and -18/-57/66 for SPC. +SPM now computes the first principal component of the time series from all voxels included in the sphere. The result is stored (together with the original time series) in a file named \texttt{VOI\_V5\_1.mat} in the working directory (the ``1'' refers to session 1). + +You can now proceed to select time series for V1 (using the \textsc{Photic} contrast) with an \texttt{8} mm sphere centered on the global maxima (\texttt{[0 -93 18]}). Same thing with SPC (using the \textsc{attention} contrast with a $p \leq 0.001$ uncorrected threshold) and a sphere centered on the local maxima around \texttt{[-27 -84 36]}. This will create files \texttt{VOI\_V1\_1.mat} and \texttt{VOI\_SPC\_1.mat}. \subsection{Specifying and estimating the DCM} @@ -155,83 +218,85 @@ \subsection{Specifying and estimating the DCM} \end{figure} as follows: \begin{enumerate} -\item{Press the \texttt{DCM} button.} -\item{Choose ``specify''.} -\item{Select the \texttt{SPM.mat} file you just created when specifying the GLM.} -\item{Name for \verb!DCM_???.mat!: e.g. \verb!mod_bwd! (for ``attentional modulation of backward connection'')} -\item{Select all VOIs in order \verb!VOI_V1_1, VOI_V5_1, VOI_SPC_1!} -\item{Include Photic: Yes} -\item{Include Motion: Yes} -\item{Include Attention: Yes} -\item{Define the following intrinsic connections: V1 to V5, V5 to V1, V5 to SPC, SPC to V5, i.e. a hierarchy with reciprocal connections between neighbouring areas. Note that the columns specify the source of the connection and the rows specify its target. Your connectivity matrix should look like the one in Fig.~\ref{fig4}.} -\item{Specify Photic as a driving input into V1. See Fig.~\ref{fig5}} -\item{Specify Motion to modulate the connection from V1 to V5. See Fig.~\ref{fig6}} -\item{Specify Attention to modulate the connection from SPC to V5. See Fig.~\ref{fig7}} -\item{Say No for ``Nonlinear DCM?''} -\item{Specify slice timings for each area. This is a new option described in \cite{sjk_dcm_slicetiming}. The default values are set to the last slice of the data, which was the default in the original DCM version. For sequential (as opposed to interleaved) data, this modelling option allows to use DCM in combination with any TR (slice timing differences). Here, we proceed with the default values.} -\item{Enter \texttt{0.04} for ``Echo Time, TE[s]''.} +\item Press the large \texttt{Dynamic Causal Modelling} button. +\item Choose \textsc{specify}. +\item Select the \texttt{SPM.mat} file you just created when specifying the GLM. +\item Name for \texttt{DCM\_???.mat}: e.g. \texttt{mod\_bwd} (for ``attentional modulation of backward connection''). +\item Select all VOIs in order \texttt{VOI\_V1\_1}, \texttt{VOI\_V5\_1}, \texttt{VOI\_SPC\_1}. +\item Include \texttt{Photic}: Yes +\item Include \texttt{Motion}: Yes +\item Include \texttt{Attention}: Yes +\item Specify slice timings for each area. The default values are set to the last slice of the data, which was the default in the original DCM version. For sequential (as opposed to interleaved) data, this modelling option allows to use DCM in combination with any TR (slice timing differences) \cite{sjk_dcm_slicetiming}. Here, we proceed with the default values. +\item Enter \texttt{0.04} for ``Echo Time, TE[s]''. +\item Modulatory effects: \texttt{bilinear} +\item States per region: \texttt{one} +\item Stochastic effects: \texttt{no} +\item Define the following intrinsic connections: V1 to V5, V5 to V1, V5 to SPC, SPC to V5, i.e. a hierarchy with reciprocal connections between neighbouring areas. Note that the columns specify the source of the connection and the rows specify its target. Your connectivity matrix should look like the one in Fig.~\ref{dcm_fig4}. +\item Specify Photic as a driving input into V1. See Fig.~\ref{dcm_fig4} +\item Specify Motion to modulate the connection from V1 to V5. See Fig.~\ref{dcm_fig4} +\item Specify Attention to modulate the connection from SPC to V5. See Fig.~\ref{dcm_fig4} \end{enumerate} -A polite ``Thank you'' completes the model specification process. +A polite ``Thank you'' completes the model specification process. A file called \texttt{DCM\_mod\_bwd.mat} will have been generated. -\begin{figure}[ht] +\begin{figure} \begin{center} \includegraphics[width=70mm]{dcm/Fig4} -\caption{\em Filled circles define the structure of the intrinsic connections $C$ such that eg. there are no connections from V1R to SPCR or from SPCR to V1R. See also Fig~\ref{bwd}.\label{fig4}} -\end{center} -\end{figure} -\begin{figure}[ht] -\begin{center} \includegraphics[width=70mm]{dcm/Fig5} -\caption{\em The filled circle specifies that the input `phot' connects to region V1R. See also Fig~\ref{bwd}.\label{fig5}} +\includegraphics[width=70mm]{dcm/Fig6} +\includegraphics[width=70mm]{dcm/Fig7} +\caption{\em Specification of model depicted in Fig~\ref{bwd}. \textbf{Top left:} Filled circles define the structure of the intrinsic connections $A$ such that eg. there are no connections from V1 to SPC or from SPC to V1. \textbf{Top right:} The filled circle specifies that the input \texttt{Photic} connects to region V1. \textbf{Bottom left:} The filled circle indicates that the input \texttt{Motion} can modulate the connection from V1 to V5. This specifies a ``modulatory'' connection. \textbf{Bottom right:} The filled circle indicates that \texttt{Attention} can modulate the connection from SPC to V5. \label{dcm_fig4}} \end{center} \end{figure} -\begin{figure}[ht] + +You can now estimate the model parameters, either by pressing the DCM button again and choosing \textsc{estimate}, or by typing +\begin{verbatim} +>> spm_dcm_estimate('DCM_mod_bwd'); +\end{verbatim} +from the \matlab\ command line. + +\begin{figure} \begin{center} -\includegraphics[width=70mm]{dcm/Fig6} -\caption{\em The filled circle indicates that the input variable `mot' can modulate the connection from V1R to V5R. This specifies a `modulatory' connection. See also Fig~\ref{bwd}.\label{fig6}} +\includegraphics[width=100mm]{dcm/dcm_mod_fwd} +\caption{\em DCM with attentional modulation of forwards connection. Dotted lines denote modulatory connections.\label{fwd}} \end{center} \end{figure} + \begin{figure}[ht] \begin{center} -\includegraphics[width=70mm]{dcm/Fig7} -\caption{\em The filled circle indicates that attention can modulate the connection from SPCR to V5R. See also Fig~\ref{bwd}.\label{fig7}} +\includegraphics[width=140mm]{dcm/Fig8} +\caption{\em Plot of predicted and observed response, after convergence and conditional expectation of the parameters.\label{dcm_fig8}} \end{center} \end{figure} -You can now estimate the model parameters, either by pressing the DCM button again and choosing ``estimate'', or by typing \verb!spm_dcm_estimate('DCM_mod_bwd')! from the \matlab\ command line. Once this is completed, you can review the results as follows: +Once this is completed, you can review the results as follows: \begin{enumerate} -\item{Press the DCM button.} -\item{Choose ``review''.} -\item{Select \verb!DCM_mod_bwd!} -\item{Threshold: 0} +\item Press the DCM button. +\item Choose \textsc{review}. +\item Select \texttt{DCM\_mod\_bwd.mat} +\item Threshold: \texttt{0} \end{enumerate} Now you have multiple options, e.g. you can revisit the fit of the model (``Outputs'') or look at the parameter estimates for the intrinsic connections (``Intrinsic connections'') or for the parameters associated with the driving or modulatory inputs (``Effects of Photic'', ``Effects of Motion'', ``Effects of Attention''). Also, you can use the ``Contrasts'' option to determine how confident you can be that a contrast of certain parameter estimates exceeds the threshold you chose in step 4. -Of course, you can also explore the model results at the level of the \matlab\ command line by loading the model and inspecting the parameter estimates directly. These can be found in \texttt{DCM.A} (intrinsic connections), \texttt{DCM.B} (modulatory inputs) and \texttt{DCM.C} (driving inputs). +Of course, you can also explore the model results at the level of the \matlab\ command line by loading the model and inspecting the parameter estimates directly. These can be found in \texttt{DCM.Ep.A} (intrinsic connections), \texttt{DCM.Ep.B} (modulatory inputs) and \texttt{DCM.Ep.C} (driving inputs). \subsection{Comparing models} Let us now specify an alternative model and compare it against the one that we defined and estimated above. The change that we are going to make is to assume that attention modulates the $V1 \rightarrow V5$ connection (as opposed to the $SPC \rightarrow V5$ connection in the previous model). For defining this model, you repeat all the steps from the above example, the only differences being that the model gets a new name (e.g. \verb!mod_fwd!) and that attention now acts on the forward connection. This DCM is shown schematically in Figure~\ref{fwd}. -\begin{figure}[ht] -\begin{center} -\includegraphics[width=100mm]{dcm/dcm_mod_fwd} -\caption{\em DCM with attentional modulation of forwards connection. Dotted lines denote modulatory connections.\label{fwd}} -\end{center} -\end{figure} + Once you have estimated this new model, you can perform a Bayesian model comparison as follows: \begin{enumerate} -\item{Press the ``DCM'' button.} -\item{Choose ``compare''.} -\item{Number of models to compare: 2} -\item{Select the two models, e.g. in the order \verb!DCM_mod_bwd! and \verb!DCM_mod_fwd!.} + \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}. \end{enumerate} -The Graphics window, Fig.~\ref{fig8}, now shows a bar plot of the model evidence. You can see that our second model is better than the first one. +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. \begin{figure}[ht] \begin{center} -\includegraphics[width=100mm]{dcm/Fig8} -\caption{\em Model 2 (shown in Fig~\ref{fwd}) is preferred to model 1 (shown in Fig~\ref{bwd}).\label{fig8}} +\includegraphics[width=140mm]{dcm/Fig9} +\caption{\em Model 2 (shown in Fig~\ref{fwd}) is preferred to model 1 (shown in Fig~\ref{bwd}).\label{dcm_fig9}} \end{center} \end{figure} diff --git a/man/dcm/dcm_mod_bwd.png b/man/dcm/dcm_mod_bwd.png index 1919093..ac76b3b 100644 Binary files a/man/dcm/dcm_mod_bwd.png and b/man/dcm/dcm_mod_bwd.png differ diff --git a/man/dcm/dcm_mod_fwd.png b/man/dcm/dcm_mod_fwd.png index cf362fe..ad25368 100644 Binary files a/man/dcm/dcm_mod_fwd.png and b/man/dcm/dcm_mod_fwd.png differ diff --git a/man/example_scripts/simmegdip_mult_subj.m b/man/example_scripts/simmegdip_mult_subj.m new file mode 100644 index 0000000..18fdf76 --- /dev/null +++ b/man/example_scripts/simmegdip_mult_subj.m @@ -0,0 +1,188 @@ +%% simulate data from multiple subjects. At the moment use the same dataset +%% template, +%% can vary source std in amplitude and/or location across subjects + +cd C:\users\gbarnes\documents\mv_multsubj + +Nsubj=10; +%% ORIGINAL FACES DATA FILE +origspmfilename='cdbespm8_SPM_CTF_MEG_example_faces1_3D.mat' +outpath='C:\users\gbarnes\documents\simdata_vlad'; +%% FOR SIMULATED NOISE- recording BW of 80Hz, white noise level 10ft/rtHz +noiselevel=10*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 + +%% set frequency and amplitude of the two dipoles defined above +%% for each condition (faces/scrambled) separately + %cond1 cond2 +dipfreq=[40 40;... %% dip 1 + 20 20 + 30 30 ]; %%% dip 2 + %cond1 cond2 +dipamp=[1 0;... % dip 1 + 0.5 0 + 1 0].*1e-1; % dip2 + + Ndips=size(dipfreq,1); + substr=sprintf('simdata_%ddip_%dmm_%dpcamp',Ndips,cross_subj_disp,cross_subj_sdamp_pc); +%% define period over which dipoles are active +startf1=0.1; % (sec) start time +duration=0.3;% duration + + + + +for s=1:Nsubj, + dipamp_subj=dipamp+dipamp.*randn(size(dipamp))*cross_subj_sdamp_pc./100;; + +%% OUTPUT SIMULATED DATA FILE +spmfilename=[outpath filesep sprintf('%s%d',substr,s)]; + + + +%% FOR SIMULATED DATA +start_dipolepositions=[ 52, -29, 13; -52, -29, 13;-48 -22 48]; % in mni space +dipolepositions=start_dipolepositions+randn(size(start_dipolepositions)).*cross_subj_disp; +subj_data(s).dipole_positions=dipolepositions; + + + +Ndips=size(dipolepositions,1); + +%%% LOAD IN ORGINAL FACE DATA +D = spm_eeg_load(origspmfilename); +modality='MEG'; +channel_labels = D.chanlabels(D.meegchannels(modality)); + +%%% GET LOCATION OF MESH Vertices in MNI and MEG/CTF space +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); + +%%% FORCE A SINGE SPHERE HEAD MODEL- simpler to compare inversions +headmodels = {'Single Sphere', 'MEG Local Spheres', 'Single Shell'}; + D.inv{1}.forward(1).voltype=headmodels{1}; + D = spm_eeg_inv_forward(D); + grad = D.sensors('meg'); + vol = D.inv{1}.forward.vol; + + Ntrials=D.ntrials; + +[condnames,ncond,trialtypes]=unique(D.conditions); +if length(condnames)~=size(dipamp_subj,2), + error('number trial types should equal number of columns in dipamp'); +end; % if + + +allavsignal=zeros(Ndips,length(D.time)); + +for dipind=1:Ndips, +cfg = []; +cfg.vol = vol; +cfg.grad = grad; + +%% SIMULATE DIPOLES ON THE CORTICAL SURFACE + + +%% find nearest dipole to location specified + [d meshind] = min(sum([allmeshvert_mni(:,1) - dipolepositions(dipind,1), ... + allmeshvert_mni(:,2) - dipolepositions(dipind,2), ... + allmeshvert_mni(:,3) - dipolepositions(dipind,3)].^2,2)); + meshdippos(dipind,:)=allmeshvert_ctf(meshind,:); + cfg.dip.pos = meshdippos(dipind,:); + t1=allmeshnorms_ctf(meshind,:); %% get dip orientation from mesh + meshsourceind(dipind)=meshind; % + + + + + +cfg.dip.mom =t1'; % note, it should be transposed +cfg.ntrials =Ntrials; + +endf1=duration+startf1; + +f1ind=intersect(find(D.time>startf1),find(D.time<=endf1)); + + +for i=1:cfg.ntrials + f1=dipfreq(dipind,trialtypes(i)); %% frequency depends on stim condition + amp1=dipamp_subj(dipind,trialtypes(i)); + phase1=pi/2; + signal=zeros(1,length(D.time)); + signal(f1ind)=signal(f1ind)+amp1*sin((D.time(f1ind)-D.time(min(f1ind)))*f1*2*pi+phase1); + cfg.dip.signal{i}=signal; + allavsignal(dipind,:)=allavsignal(dipind,:)+signal; +end; % for i + +cfg.triallength =max(D.time)-min(D.time); % seconds +cfg.fsample = D.fsample; % Hz +onesampletime=1/D.fsample; +cfg.absnoise=0; +cfg.relnoise=0; +cfg.channel=channel_labels; +raw1 = ft_dipolesimulation(cfg); +allraw(dipind)=raw1; +end; % for dipind + +%% MERGE N DIPOLES INTO ONE DATASET +for dipind=1:Ndips, + if dipind==1; + dipsum=allraw(dipind).trial; + else + for i=1:Ntrials, + newdata=cell2mat(allraw(dipind).trial(i)); + dataprev=cell2mat(dipsum(i)); + dataraw=newdata+dataprev; + dipsum(i)=mat2cell(dataraw,size(newdata,1),size(newdata,2)); + end; + + end; +end; +allraw=raw1; +allraw.trial=dipsum; +clear dipsum; + + %% NOW ADD WHITE NOISE + for i=1:Ntrials, + dataraw=cell2mat(allraw.trial(i)); + channoise=randn(size(dataraw)).*noiselevel*sqrt(BW); + dataraw=dataraw+channoise; + allraw.trial(i)=mat2cell(dataraw, size(dataraw,1),size(dataraw,2)); + allraw.time(i)=mat2cell(D.time,1); + epochdata=cell2mat(allraw.trial(i))'; + end; + + +avg1 = ft_timelockanalysis([], allraw); +plot(avg1.time, avg1.avg); % plot the average timecourse + +%%% now write out a new data set +D2=D; +D2=spm_eeg_ft2spm(allraw,spmfilename); +D2=sensors(D2,'MEG',raw1.grad); +D2=fiducials(D2,D.fiducials); +D2.inv=D.inv; +D2 = conditions(D2, [], D.conditions); +D2=coor2d(D2,'MEG',coor2d(D)); %% save projected 2d channel locations +D2.save; + +figure; +h=plot(D2.time,allavsignal); +set(h(1),'Linestyle',':'); +set(h,'LineWidth',4); +set(gca,'FontSize',18); +set(gcf,'color','w'); + +% %% write an averaged data set also +% S=[] +% S.D=D2; +% S.robust=0; +% D2av = spm_eeg_average(S); + +end; % for s + diff --git a/man/example_scripts/spm_eeg_convert_arbitrary_data.m b/man/example_scripts/spm_eeg_convert_arbitrary_data.m new file mode 100644 index 0000000..034baab --- /dev/null +++ b/man/example_scripts/spm_eeg_convert_arbitrary_data.m @@ -0,0 +1,86 @@ +% demo for creating an SPM M/EEG dataset from arbitrary data using +% conversion of simple Fieldtrip raw data struct. +% SPM8 internal format is quite complex but is transparent to the user +% as meeg object's methods take care of maintaining its consistency. +% The most straightforward way to convert arbitrary data that is available +% as an ASCII file or *.mat file with some variables to SPM8 is to create +% a quite simple Fieldtrip raw data struct and then use SPM's +% spm_eeg_ft2spm to convert this struct to SPM8 file. Missing information +% can then be supplemented using meeg methods and SPM functions. +% Fieldtrip raw struct must contain the following fields: +% .fsample - sampling rate (Hz) +% .trial - cell array of matrices with identical dimensions channels x time +% .time - cell array of time vectors (in sec), the same length as the +% second dimension of the data. For SPM8 they must be identical. +% .label - cell array of strings, list of channel labels. Same length as +% the first dimension of the data. +%__________________________________________________________________________ +% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging + +% Vladimir Litvak +% $Id: spm_eeg_convert_arbitrary_data.m 3841 2010-04-27 14:18:53Z vladimir $ + + +% Initialize SPM +%-------------------------------------------------------------------------- +spm('defaults','EEG'); + +% Some details about the data +%-------------------------------------------------------------------------- +Nchannels = 5; +Nsamples = 500; +Ntrials = 50; +TimeOnset = -0.1; % in sec +Fsample = 1000; + +chlabels = { + 'LFP1' + 'LFP2' + 'LFP3' + 'LFP4' + 'LFP5' + }; + +% define the output file name +%-------------------------------------------------------------------------- +fname = 'arbitrary_data_example'; + +% create data array +%-------------------------------------------------------------------------- +data = randn([Nchannels, Nsamples, Ntrials]); + +% create the time axis (should be the same for all trials) +%-------------------------------------------------------------------------- +timeaxis = [0:(Nsamples-1)]./Fsample + TimeOnset; + +% Create the Fieldtrip raw struct +%-------------------------------------------------------------------------- + +ftdata = []; + +for i = 1:Ntrials + ftdata.trial{i} = squeeze(data(:, :, i)); + ftdata.time{i} = timeaxis; +end + + +ftdata.fsample = Fsample; +ftdata.label = chlabels; +ftdata.label = ftdata.label(:); + +% Convert the ftdata struct to SPM M\EEG dataset +%-------------------------------------------------------------------------- +D = spm_eeg_ft2spm(ftdata, fname); + +% Examples of providing additional information in a script +% [] comes instead of an index vector and means that the command +% applies to all channels/all trials. +%-------------------------------------------------------------------------- +D = type(D, 'single'); % Sets the dataset type +D = chantype(D, [], 'LFP'); % Sets the channel type +D = conditions(D, 1:Ntrials, 'Condition 1'); % Sets the condition label + +% save +%-------------------------------------------------------------------------- +save(D); + diff --git a/man/example_scripts/spm_ft_multimodal_preprocessing.m b/man/example_scripts/spm_ft_multimodal_preprocessing.m index 12d88ec..11181e0 100644 --- a/man/example_scripts/spm_ft_multimodal_preprocessing.m +++ b/man/example_scripts/spm_ft_multimodal_preprocessing.m @@ -35,7 +35,7 @@ % adjust trigger latency (see the multimodal chapter) % here any other manipulation with the trl can be added - hdr = fileio_read_header(cfg.dataset); + hdr = ft_read_header(cfg.dataset); cfg.trl(:,1:2) = cfg.trl(:,1:2) + round(25*hdr.Fs/1000); cfg.channel = 'MEG'; @@ -66,8 +66,8 @@ %% Posp-processing of converted data % Read sensors and fiducials from the first dataset -D = sensors(D, 'MEG', forwinv_convert_units(fileio_read_sens(fullfile(root, datasets{1})), 'mm')); -D = fiducials(D, forwinv_convert_units(fileio_read_headshape(fullfile(root, datasets{1})), 'mm')); +D = sensors(D, 'MEG', ft_convert_units(ft_read_sens(fullfile(root, datasets{1})), 'mm')); +D = fiducials(D, ft_convert_units(ft_read_headshape(fullfile(root, datasets{1})), 'mm')); %% Set condition labels using the previously stored numbers of trials condtrials = cumsum([1 condtrials]); diff --git a/man/faces/plot_responses.tex b/man/faces/plot_responses.tex index 1cff403..1038bba 100644 --- a/man/faces/plot_responses.tex +++ b/man/faces/plot_responses.tex @@ -2,7 +2,7 @@ \subsection{Masking F-contrasts} To assess further the effects of stimulus repetition -\bi +\begin{itemize} \item{Press 'Results', select the SPM.mat file, and select contrast 3, `Main effect of Rep'. This contrast has been created automatically. Then press `Done'.} \item{\em Mask with other contrast ? [Yes/No]} \item{Specify Yes.} @@ -17,7 +17,7 @@ \subsection{Masking F-contrasts} \item{Accept the default value, 0.001} \item{\em Extent threshold \{voxels\} [0]} \item{Accept the default value, 0} -\ei +\end{itemize} Specify 'mask with another contrast' (yes), select the 'Canonical HRF: Faces $>$ Baseline' t-contrast, specify 'threshold for mask' (accept default of p=0.05 uncorrected), specify 'nature of mask' (inclusive), specify 'title for comparison' (accept default), specify 'corrected height threshold' (no), specify threshold (0.001). Again, when the MIP appears, press 'Volume'. @@ -27,20 +27,20 @@ \subsection{Plotting event-related responses} To plot repetition suppression effects for the R fusiform region, select the third cluster from the top (by clicking 48 60 -15; slightly more posterior to that identified above) and press 'plot'. Select 'event-related responses'. -\bi +\begin{itemize} \item{\em Which trials or conditions (1 to 6)} \item{Specify `1:4'} \item{\em Plot in terms of ...} \item{Select fitted response and PSTH} -\ei +\end{itemize} To adjust the scale of the x-axis (time), press 'attrib' from the plot controls panel. Select Xlim, and change the default (-4 32) to '0 10'. Note the signal decrease between first and second presentations of both famous and non-famous faces. Other options from the plot controls panel: -\bi +\begin{itemize} \item{Hold: allows overlaying of plots} \item{Grid: toggles between grid on/off} \item{Box: toggles between axes/box} \item{Text: allows editing of title and/or axis labels.} -\ei +\end{itemize} diff --git a/man/faces_group/face_group.tex b/man/faces_group/face_group.tex index 2490498..80cebfa 100644 --- a/man/faces_group/face_group.tex +++ b/man/faces_group/face_group.tex @@ -2,8 +2,8 @@ \chapter{Face group fMRI data \label{Chap:data:faces_group}} \section{Introduction} -These examples illustrate multisubject ``random effects'' analyses or ``second-level'' models of fMRI data \cite{will_hbf2_rfx}\footnote{This chapter has been largely cannibalised from an earlier document, available from \url{http://www.fil.ion.ucl.ac.uk/spm/data/face_rfx/spm2_face_rfx.doc}, which describes how to analyse this data using SPM2. That document additionally describes the analysis of differential effects, which we have omitted here.}. -The examples consist of three basic types of 2nd-level model +These examples illustrate multisubject ``random effects'' analyses or ``second-level'' models of fMRI data \cite{will_hbf2_rfx}\footnote{This chapter has been largely cannibalised from an earlier document, available from \url{http://www.fil.ion.ucl.ac.uk/spm/data/face_rfx/spm2_face_rfx.doc}, which describes how to analyse this data using SPM2. That document additionally describes the analysis of differential effects, which we have omitted here.}. +The examples consist of three basic types of 2nd-level model: \begin{enumerate} \item \textbf{M2c:} Using contrast images for the canonical HRF only. This uses a single observation (contrast image) per subject only and data are analysed using a ``One-sample t-test''. \item \textbf{M2i:} Using contrast images from an ``informed'' basis set, consisting of the canonical HRF and its two partial derivatives with respect to time (onset latency) and dispersion. This uses 3 observations (contrast images) per subject and data are analysed using a ``One-way ANOVA'' with 3 levels. @@ -14,7 +14,7 @@ \section{Data} The data come from the ``implicit'' condition of the Henson et al. study \cite{rnah_face_rep}. Although the 1st-level design matrices (and therefore resulting contrast images) used do not correspond exactly to those used in that study. -It is also the same study from which one subject is used to illustrate a single-subject fixed effects analysis (see earlier Chapter in this manual). +It is also the same study from which one subject is used to illustrate a single-subject fixed effects analysis (see chapter \ref{Chap:data:faces} in this manual). Unlike the single-subject fixed effects example dataset, only two event-types were modelled: famous and nonfamous faces (initial and repeated presentations were collapsed together, as were correct and incorrect responses). Briefly, greyscale photographs of 52 famous and 52 nonfamous face were presented for 0.5s for fame judgment task (one of two right finger key presses). The minimal SOA (SOAmin) was 4.5s, with all faces randomly intermixed together with a further 52 null events (ie 2/3 probability of a face every SOAmin). @@ -26,16 +26,22 @@ \section{Data} In both first-level models (\textbf{M1i} and \textbf{M1f}), the contrast images (\texttt{con*.img}'s) come from session-specific contrasts within a large (multisession) 1st-level Fixed Effects design matrix, with one session per subject. (Note that the resulting \texttt{con*.img}'s could equally well have been produced from 12 separate 1st-level models, one per subject.) -For each type of model, the main effect of faces versus baseline (eg, a [0.5 ... 0.5] contrast for each basis function, or \texttt{kron(eye(Nf),[0.5 0.5])} more generally) was examined. +For each type of model, the main effect of faces versus baseline (eg, a [0.5 ... 0.5] contrast for each basis function, or \texttt{kron([0.5 0.5],eye(Nf))} more generally) was examined. The 12 (subjects) \texttt{con*.img}s from the 1st-level model using the canonical HRF (\textbf{M1c}) are in the zipped file -\newline \url{http://www.fil.ion.ucl.ac.uk/spm/data/face_rfx/cons_can.zip}. +\begin{itemize} +\item \url{http://www.fil.ion.ucl.ac.uk/spm/data/face_rfx/cons_can.zip} +\end{itemize} The 12 (subjects) x 3 (basis functions) \texttt{con*.img}s from the 1st-level model using the informed basis (\textbf{M1i}) set are in the zipped file -\newline \url{http://www.fil.ion.ucl.ac.uk/spm/data/face_rfx/cons_informed.zip}. +\begin{itemize} +\item \url{http://www.fil.ion.ucl.ac.uk/spm/data/face_rfx/cons_informed.zip} +\end{itemize} -The 12 (subjects) x 12 (basis functions) x 2 (contrast-types) \texttt{con*.img}s from the 1st-level model using the FIR basis (\textbf{M1f}) set are in the zipped file -\newline \url{http://www.fil.ion.ucl.ac.uk/spm/data/face_rfx/cons_fir.zip}. +The 12 (subjects) x 12 (basis functions) x 2 (contrast-types) \texttt{con*.img}s from the 1st-level model using the FIR basis (\textbf{M1f}) set are in the zipped file +\begin{itemize} +\item \url{http://www.fil.ion.ucl.ac.uk/spm/data/face_rfx/cons_fir.zip} +\end{itemize} Each contrast-type is examined in a separate SPM analysis. This chapter just describes analysis of the main effect of faces versus baseline. To analyse the data, first create a new directory \texttt{DIR} eg. \texttt{c:$\backslash$data$\backslash$face\_group}, in which to place the results of your analysis. Then create 3 subdirectories (i) \texttt{Canonical}, (ii) \texttt{Informed}, and (iii) \texttt{FIR}. @@ -54,10 +60,10 @@ \section{Canonical HRF} These images comprise the data for \texttt{M2c}, which is simply a ``One-sample t-test''. This can be implemented as follows. \begin{itemize} \item Start up \matlab\ and type \texttt{spm fmri} at the prompt -\item Press the `Specify 2nd-level' button. This will open the batch editor. +\item Press the ``Specify 2nd-level'' button. This will open the batch editor. \item In the ``Design'', ``One-sample t-test'' option, select ``Scans''. \item Choose ``Select Files'' and use the SPM file selector to choose contrast images 6 to 17. -\item Highlight ``Directory'', ``Select files'' and select the subdirectory ``canonical'', to place the design matrix in. +\item Highlight ``Directory'', ``Select files'' and select the subdirectory \texttt{canonical}, to place the design matrix in. \item Save the job file as eg. \texttt{DIR/canonical.mat}. \item Press the \texttt{Run} button (green arrow). \end{itemize} @@ -65,7 +71,7 @@ \section{Canonical HRF} SPM will then show you the design matrix shown in Figure~\ref{t1}. This is simply a single column of 1's which will appear as a white box on a white background. This design is encoded in the \texttt{SPM.mat} file that is written to the output directory. \begin{figure} \begin{center} -\includegraphics[width=100mm]{faces_group/t1} +\includegraphics[width=140mm]{faces_group/t1} \caption{\em \textbf{Design matrix for canonical responses}. This corresponds to a one-sample t-test. \label{t1}} \end{center} \end{figure} @@ -88,7 +94,7 @@ \section{Canonical HRF} SPM will now display the thresholded F-statistic image. This shows voxels that are significantly active (correcting for multiple comparisons across all voxels) in the population from which the subjects were drawn. They include bilateral posterior fusiform, SMA, and, at a more liberal threshold, left motor cortex). \begin{figure} \begin{center} -\includegraphics[width=100mm]{faces_group/f1_res} +\includegraphics[width=140mm]{faces_group/f1_res} \caption{\em Main population effect of faces vs baseline, as characterised using the Canonical HRF. \label{f1_res}} \end{center} \end{figure} @@ -132,7 +138,7 @@ \section{Informed basis set} SPM will then show you the design matrix shown in Figure~\ref{informed_design}. This design is encoded in the \texttt{SPM.mat} file that is written to the output directory. \begin{figure} \begin{center} -\includegraphics[width=100mm]{faces_group/informed_design} +\includegraphics[width=140mm]{faces_group/informed_design} \caption{\em \textbf{Design matrix for informed basis set.} This corresponds to a one-way ANOVA with three levels (but no constant term, since we want to test whether the basis functions are different from zero, not whether they are different from each other). \label{informed_design}} \end{center} \end{figure} diff --git a/man/images/spm8.png b/man/images/spm8.png new file mode 100644 index 0000000..2c0ffba Binary files /dev/null and b/man/images/spm8.png differ diff --git a/man/manual.pdf b/man/manual.pdf index 9c680d6..6237aa1 100644 Binary files a/man/manual.pdf and b/man/manual.pdf differ diff --git a/man/manual.tex b/man/manual.tex index 3c668eb..a3d84a5 100644 --- a/man/manual.tex +++ b/man/manual.tex @@ -1,9 +1,10 @@ \documentclass[a4paper,titlepage]{book} -\usepackage{epsfig,amsmath,pifont,moreverb,minitoc} +\usepackage{epsfig,amsmath,pifont,moreverb,minitoc,multirow,multicol} +\usepackage[3D]{movie15} \usepackage[colorlinks=true, pdfpagemode=UseOutlines, pdftitle={SPM8 Manual}, -pdfauthor={The SPM Team}, +pdfauthor={The SPM Developers}, pdfsubject={Statistical Parametric Mapping}, pdfkeywords={neuroimaging, MRI, PET, EEG, MEG, SPM} ]{hyperref} @@ -23,9 +24,6 @@ \marginparwidth=21mm \footskip=10mm -\newcommand{\bi}{\begin{itemize}} -\newcommand{\ei}{\end{itemize}} - \newcommand{\matlab}{\textsc{Matlab}} \begin{document} @@ -54,6 +52,7 @@ Jean Daunizeau \\ Guillaume Flandin \\ Karl Friston \\ +Darren Gitelman \\ Stefan Kiebel \\ James Kilner \\ Vladimir Litvak \\ @@ -61,6 +60,7 @@ Will Penny \\ Klaas Stephan \\ \medskip +Darren Gitelman \\ Rik Henson \\ Chloe Hutton \\ Volkmar Glauche \\ @@ -160,6 +160,8 @@ \part{Data sets and examples} %\include{fiac} \include{pet/pet} \include{dcm/dcm} +\include{ppi/ppi} +\include{bms/bms} \include{meg_sloc/meg_sloc} \include{mmn/mmn} \include{multimodal/multimodal} diff --git a/man/meeg/eeg_imaging.tex b/man/meeg/eeg_imaging.tex index fd7f507..514413e 100644 --- a/man/meeg/eeg_imaging.tex +++ b/man/meeg/eeg_imaging.tex @@ -94,28 +94,26 @@ \section{Inverse reconstruction} If you have trials belonging to more than one condition in your dataset then the next choice you will have is whether to invert all the conditions together or to choose a subset. It is recommended to invert the conditions together if you are planning to later do a statistical comparison between them. If you have only one condition, or after choosing the conditions, you will get a choice between ``Standard'' and ``Custom'' inversion. If you choose ``Standard'' inversion, SPM will start the computation with default settings. These correspond to the multiple sparse priors (MSP) algorithm \cite{karl_msp} which is then applied to the whole input data segment. -If you want to fine-tune the parameters of the inversion, choose the ``Custom'' option. You will then have the possibility to choose between several types of inversion differing by their hyperprior models (IID - equivalent to classical minimum norm, COH - smoothness prior similar to methods such as LORETA) or optimization scheme for the MSP method (GS - greedy search, ARD - automatic relevance determination). +If you want to fine-tune the parameters of the inversion, choose the ``Custom'' option. You will then have the possibility to choose between several types of inversion differing by their hyperprior models (IID - equivalent to classical minimum norm, COH - smoothness prior similar to methods such as LORETA) or the MSP method . You can then choose the time window that will be available for inversion. Based on our experience, it is recommended to limit the time window to the activity of interest in cases when the amplitude of this activity is low compared to activity at other times. The reason is that if the irrelevant high-amplitude activity is included, the source reconstruction scheme will focus on reducing the error for reconstructing this activity and might ignore the activity of interest. In other cases, when the peak of interest is the strongest peak or is comparable to other peaks in its amplitude, it might be better not to limit the time window to let the algorithm model all the brain sources generating the response and then to focus on the sources of interest using the appropriate contrast (see below). There is also an option to apply a hanning taper to the channel time series in order to downweight the possible baseline noise at the beginning and end of the trial. There is also an option to pre-filter the data. Finally, you can restrict solutions to particular brain areas by loading a \texttt{*.mat} file with a $K \times 3$ matrix containing MNI coordinates of the areas of interest. This option may initially seem strange, as it may seem to overly bias the source reconstructions returned. However, in the Bayesian inversion framework you can compare different inversions of the same data using Bayesian model comparison. By limiting the solutions to particular brain areas you greatly simplify your model and if that simplification really captures the sources generating the response, then the restricted model will have much higher model evidence than the unrestricted one. If, however, the sources you suggested cannot account for the data, the restriction will result in a worse model fit and depending on how much worse it is, the unrestricted model might be better in the comparison. So using this option with subsequent model comparison is a way, for instance, to integrate prior knowledge from the literature or from fMRI/PET/DTI into your inversion. It also allows for comparison of alternative prior models. Note that for model comparison to be valid all the settings that affect the input data, like the time window, conditions used and filtering should be identical. -SPM8 imaging source reconstruction also supports multi-modal datasets. These are datasets that have both EEG and MEG data from a simultaneous recording. Datasets from the ''Neuromag'' MEG system which has two kinds of MEG sensors are also treated as multimodal. If your dataset is multimodal and additional question will appear asking whether to select one of the modalities or ''fuse'' them. The ''fuse'' option based on the paper by Henson et al. \cite{rnah_fusion} use a heuristic to rescale the data from different modalities so that they can be used together. Presently fusion cannot be used with ''group inversion'' (see below) but this possibility will be available in the future. +SPM8 imaging source reconstruction also supports multi-modal datasets. These are datasets that have both EEG and MEG data from a simultaneous recording. Datasets from the ''Neuromag'' MEG system which has two kinds of MEG sensors are also treated as multimodal. If your dataset is multimodal a dialogue box will appear asking to select the modalities for source reconstruction from a list. If you select more than one modality, multiomodal fusion will be performed. This option based on the paper by Henson et al. \cite{rnah_fusion} uses a heuristic to rescale the data from different modalities so that they can be used together. Once the inversion is completed you will see the time course of the region with maximal activity in the top plot of the graphics window. The bottom plot will show the maximal intensity projection (MIP) at the time of the maximal activation. You will also see the log-evidence value that can be used for model comparison, as explained above. Note that not all the output of the inversion is displayed. The full output consists of time courses for all the sources and conditions for the entire time window. You can view more of the results using the controls in the bottom right corner of the 3D GUI. These allow focusing on a particular time, brain area and condition. One can also display a movie of the evolution of neuronal activity. \section{Summarizing the results of inverse reconstruction as an image} SPM offers the possibility of writing the results as 3D NIfTI images, so that you can then proceed with GLM-based statistical analysis using Random Field theory. This is similar to the 2nd level analysis in fMRI for making inferences about region and trial-specific effects (at the between subject level). -This entails summarizing the trial- and subject-specific responses with a single 3-D image in source space. Critically this involves prompting for a time-frequency contrast window to create each contrast image. This is a flexible and generic way of specifying the data feature you want to make an inference about (e.g., gamma activity around 300 ms or average response between 80 and 120 ms). This kind of contrast is specified by pressing the \texttt{Window} button. You will then be asked about the time window of interest (in ms, peri-stimulus time). It is possible to specify either a single time value or a time segment. The next question is about the frequency band. If you just want to average the source time course leave that at the default, zero. In this case the window will be weighted by a Gaussian. In the case of a single time point this will be a Gaussian with 8 ms full width half maximum (FWHM). If you specify a particular frequency or a frequency band, then a series of Morlet wavelet projectors will be generated summarizing the energy in the time window and band of interest. +This entails summarizing the trial- and subject-specific responses with a single 3-D image in source space. Critically this involves prompting for a time-frequency contrast window to create each contrast image. This is a flexible and generic way of specifying the data feature you want to make an inference about (e.g., gamma activity around 300 ms or average response between 80 and 120 ms). This kind of contrast is specified by pressing the \texttt{Window} button. You will then be asked about the time window of interest (in ms, peri-stimulus time). It is possible to specify one or more time segments (separated by a semicolon). To specify a single time point repeat the same value twice. The next question is about the frequency band. If you just want to average the source time course leave that at the default, zero. In this case the window will be weighted by a Gaussian. In the case of a single time point this will be a Gaussian with 8 ms full width half maximum (FWHM). If you specify a particular frequency or a frequency band, then a series of Morlet wavelet projectors will be generated summarizing the energy in the time window and band of interest. There is a difference between specifying a frequency band of interest as zero, as opposed to specifying a wide band that covers the whole frequency range of your data. In the former case the time course of each dipole will be averaged, weighted by a gaussian. Therefore, if within your time window this time course changes polarity, the activity can average out and in an ideal case even a strong response can produce a value of zero. In the latter case the power is integrated over the whole spectrum ignoring phase, and this would be equivalent to computing the sum of squared amplitudes in the time domain. -Finally, you will have a choice between ``evoked'' and ``induced''. Here one can specify an epoched rather than an averaged file for the inversion. If you have multiple trials for certain conditions, the projectors generated at the previous step can either be applied to each trial and the results averaged (induced) or applied to the averaged trials (evoked). Thus it is possible to perform localization of induced activity that has no phase-locking to the stimulus. It is also possible to focus on frequency content of the ERP using the ``evoked'' option. Clearly the results will not be the same. The projectors you specified (bottom plot) and the resulting MIP (top plot) will be displayed when the operation is completed. +Finally, if the data file is epoched rather than averaged, you will have a choice between ``evoked'', ``induced'' and ``trials''. If you have multiple trials for certain conditions, the projectors generated at the previous step can either be applied to each trial and the results averaged (induced) or applied to the averaged trials (evoked). Thus it is possible to perform localization of induced activity that has no phase-locking to the stimulus. It is also possible to focus on frequency content of the ERP using the ``evoked'' option. Clearly the results will not be the same. The projectors you specified (bottom plot) and the resulting MIP (top plot) will be displayed when the operation is completed. ``trials'' option makes it possible to export an image per trial which might be useful fot doing within-subject statistics. -At this stage you have the possibility to export your image as NIfTI by pressing the ``Image'' button. You will be asked to specify the amount of smoothing. An unsmoothed image will be exported in any case. Smoothing can help to get better results in a between-subject statistical test. However, it compromises your spatial resolution. You should try different options to see what works for your data. When you use the group inversion (see below) you may not need smoothing at all. - -Note that the images are normalized so that mean power across all sources is 1. +The values of the exported images are normalized to reduce between-subject variance. Therefore, for best results it is recommended to export images for all the time windows and conditions that will be included in the same statistical analysis in one step. Note that the images exported from the source reconstruction are a little peculiar because of smoothing from a 2D cortical sheet into 3D volume. SPM statistical machinery has been optimized to deal with these peculiarities and get sensible results. This presently only works for T-contrasts but not for F. Also if you try to analyze the images with older versions of SPM or with a different software package you might get different (less focal) results. \section{Rendering interface} By pressing the \texttt{Render} button you can open a new GUI window which will show you a rendering of the inversion results on the brain surface. You can rotate the brain, focus on different time points, run a movie and compare the predicted and observed scalp topographies and time series. A useful option is ``virtual electrode'' which allows you to extract the time course from any point on the mesh and the MIP at the time of maximal activation at this point. Just press the button and click anywhere in the brain.\\ @@ -130,6 +128,9 @@ \section{Group inversion} Group inversion works very similarly to what was described above. You can start it by pressing the ``Group inversion'' button right after opening the 3D GUI. You will be asked to specify a list of M/EEG data sets to invert together. Then the routine will ask you to perform coregistration for each of the files and specify all the inversion parameters in advance. It is also possible to specify the contrast parameters in advance. Then the inversion will proceed by computing the inverse solution for all the files and will write out the output images. The results for each subject will also be saved in the header of the corresponding input file. It is possible to load this file into the 3D GUI after the inversion and explore the results as described above. +\section{Batching source reconstruction} +There is a possibility to run imaging source reconstruction using the SPM8 batch tool. It can be accessed by pressing the ``Batch'' button in the main SPM window and then going to ``M/EEG source reconstruction'' in the ``SPM'' under ``M/EEG''. There are three separate tools there: for building head models, computing the inverse solution and computing contrasts and generating images. This makes it possible for instance to generate images for several different contrasts from the same inversion. All the three tools support multiple datasets as inputs. In the case of the inversion tool group inversion will be done for multiple datasets. + \section{Appendix: Data structure} The \matlab\ object describing a given EEG/MEG dataset in SPM is denoted as \textit{D}. Within that structure, each new inverse analysis will be described by a new cell of sub-structure diff --git a/man/meeg/eeg_preprocessing.tex b/man/meeg/eeg_preprocessing.tex index 3c3345c..77e4036 100644 --- a/man/meeg/eeg_preprocessing.tex +++ b/man/meeg/eeg_preprocessing.tex @@ -100,7 +100,7 @@ \section{Preparing the data after conversion} Note that the channel template files and 3D coordinate files with labels (such as \texttt{*.sfp}) can contain many more channel labels than your data file. SPM searches, for each channel in the data, through the labels in the channel template file. If the labels match, the coordinate is used. \section{Integration of SPM and Fieldtrip} -The SPM8 distribution includes the latest version of the FieldTrip toolbox\footnote{FieldTrip: \url{http://fieldtrip.fcdonders.nl/}}. FieldTrip is a \matlab\ toolbox for MEG and EEG analysis that is being developed at the F.C. Donders Centre (FCDC) together with collaborating institutes. FieldTrip functions can be used for many kinds of analysis which are not supported in SPM proper. However, FieldTrip does not have extensive graphical user interface and its functionality should be accessed by writing scripts. Full reference documentation for FieldTrip including example scripts is available at the FieldTrip website. The SPM distribution also contains some documentation, contained as help comments in FieldTrip functions. These can be found in the directory \texttt{external$\backslash$fieldtrip$\backslash$private}. Note that in order to prevent function name clashes SPM calls its FieldTrip functions via intermediate or ``wrapper'' functions whose name always starts with \texttt{ft\_}. This has the advantage that even if there is a different FieldTrip version in the Matlab path from the one used by SPM, SPM will only use its own version and incompatibilities will be avoided. To adapt a standard FieldTrip script for use with SPM you must add the prefix \texttt{ft\_} to all FieldTrip function names in the script. +The SPM8 distribution includes the latest version of the FieldTrip toolbox\footnote{FieldTrip: \url{http://fieldtrip.fcdonders.nl/}}. FieldTrip is a \matlab\ toolbox for MEG and EEG analysis that is being developed at the F.C. Donders Centre (FCDC) together with collaborating institutes. FieldTrip functions can be used for many kinds of analysis which are not supported in SPM proper. However, FieldTrip does not have extensive graphical user interface and its functionality should be accessed by writing scripts. Full reference documentation for FieldTrip including example scripts is available at the FieldTrip website. The SPM distribution also contains some documentation, contained as help comments in FieldTrip functions. These can be found in the directory \texttt{external$\backslash$fieldtrip}. Fieldtrip data structures can be converted to SPM EEG files using the \texttt{spm\_eeg\_ft2spm} function. SPM M/EEG data, once loaded with the function \texttt{spm\_eeg\_load} can be converted to FieldTrip format using the methods \texttt{ftraw} (with syntax \texttt{D.ftraw} or \texttt{ftraw(D)}) and \texttt{fttimelock} (with syntax \texttt{D.fttimelock} or \texttt{fttimelock(D)}). For SPM time-frequency datasets \texttt{fttimelock} method converts the data to Fieldtrip time-frequency structure. @@ -300,7 +300,7 @@ \subsection{Downsampling: \texttt{spm\_eeg\_downsample}} Here, you choose the new sampling rate (Hz) which must be smaller than the old sampling rate. \subsection{Rereferencing: \texttt{spm\_eeg\_montage}} -Sometimes it is necessary to re-reference the data to a new reference. In SPM this is done by specifying a weight matrix, which pre-multiplies the data. This is a general approach which allows one to re-reference to the average over channels, to single channels, or any linear combination of channels, e.g. the average over a pair of channels. The prepended output letter is \textit{'M'}. Note that re-referencing should mainly affect the analysis you do at the channel level and should have little effect on 3D source reconstruction and DCM as long as it is not too noisy. +Sometimes it is necessary to re-reference the data to a new reference. For source analysis and DCM the data should be converted to average reference. For sensor level analysis it is sometimes useful to use a reference that emphasizes the effects of interest. In SPM this is done by specifying a weight matrix, which pre-multiplies the data. This is a general approach which allows one to re-reference to the average over channels, to single channels, or any linear combination of channels, e.g. the average over a pair of channels. The prepended output letter is \textit{'M'}. When you call the function, you will first be asked whether you want to use a GUI or read information from a file to specifying the montage. If you choose GUI, you will see, on the left hand side, the montage-matrix, where each row stands for a new channel. This means the labels in the left column describe the new labels. The old labels are on top, that means, each row contains weights for how the old channels must be weighted to produce new channels in the montage. On the right hand side, you see a graphical representation of the current matrix. The default is the identity matrix, i.e., the montage will not change anything. The concept is very general. For example, if you want to remove channels from the data, just delete the corresponding row from the montage matrix. To re-reference to a particular channel the column for this channel should be -1 for all rows, except the row corresponding to itself which should be 0, whereas the other channels should have 1 in the intersection of their column and row (the diagonal of the matrix) and 0 elsewhere. For average reference the matrix should have $(N-1)/N$ (where $N$ is number of channels) at the diagonal and $-1/N$ elsewhere. In principle, any montage can be represented this way. If you are not sure about how to represent a montage you need, ask an expert or write to the SPM mailing list. The specification will only need to be done once for your setup and then you can save the montage and use it routinely. After changing the weights of the matrix, you can check the montage by pressing the button in the lower right below the figure. @@ -322,9 +322,9 @@ \subsection{Multimodal fusion: \texttt{spm\_eeg\_fuse}} SPM supports datasets containing simultaneously recorded MEG and EEG. For imaging source reconstruction it is possible to use both modalities to inform the source solution. Usually combined MEG/EEG data is contained within the same raw dataset and can be pre-processed together from the beginning. If this is not the case \texttt{spm\_eeg\_fuse} makes it possible to combine two datasets with different channels into a single dataset given that the sets of channels do not overlap and the datasets are identical in the other dimensions (i.e. have the same sampling rate and time axis, the same number of trials and the same condition labels in the same order). This function can be used to create a multimodal dataset also from separately recorded MEG and EEG which is a valid thing to do in the case an experiment with highly reproducible ERP/ERF. \subsection{Time-frequency decomposition: \texttt{spm\_eeg\_tf}\label{sec:tf}} -The time-frequency decomposition uses a continuous Morlet wavelet transform. The result is written to one or two result files, one containing the instantaneous power and the other, optionally written, the phase estimates. One can select the channels and frequencies for which power and phase should be estimated. Optionally, one can apply a baseline correction to the power estimates, i.e. the mean power of a pre-stimulus interval is subtracted from the power estimates. For power, the prepended output letters are \textit{t1\_}, for phase \textit{t2\_}. +The time-frequency decomposition is extendable and can automatically detect and use plugin functions that implement particular spectral estimation algorithms. Algorithms presently implemented include continuous Morlet wavelet transform, Hilbert transorm and multitaper spectral estimation. The result is written to one or two result files, one containing the instantaneous power and the other, optionally written, the phase estimates (phase estimation is not possible for all algorithms). One can select the channels and frequencies for which power and phase should be estimated. For power, the prepended output letters are \textit{tf\_}, for phase \textit{tph\_}. -The function will first ask you, after selecting the M/EEG file, for a list of frequencies, which is a vector of numbers (Hz). For each of these frequencies, SPM will estimate the power and phase at each channel, time-point and trial. Next, SPM will ask you for the so-called ``Morlet Wavelet factor''. The default is 7. The greater this number, the less resolution you have over time, but the higher the resolution is in frequency. Then you can select the channels for which you want to compute the time-frequency decomposition. SPM will then ask you whether you also want to estimate the phase, in addition to power. +The function can be configured using the SPM batch interface. \subsection{Rescaling and baseline correction of time-frequency: \texttt{spm\_eeg\_tf\_rescale}\label{sec:tfrescale}} Usually raw event-related power is not the most informative thing to look at (although contrasts of raw power between conditions can be informative). To see the event-related effects better the power should be either transformed or baseline-corrected separately for each frequency. There are several different ways to do this and they are implemented in \texttt{spm\_eeg\_tf\_rescale} function. 'LogR' method first computes the log of power and then baseline-corrects and scales the result to produce values in dB. 'Diff' just does simple baseline subtraction. 'Rel' expresses the power in \% of the baseline units. Finally 'Log' and 'Sqrt' options just compute the respective functions without baseline-correction. If necessary, you will be asked to specify the baseline period. diff --git a/man/meg_sloc/meg_sloc.tex b/man/meg_sloc/meg_sloc.tex index 7ad21bd..6178578 100644 --- a/man/meg_sloc/meg_sloc.tex +++ b/man/meg_sloc/meg_sloc.tex @@ -58,7 +58,7 @@ \subsection{IID (minimum norm)} \end{figure} -It appears (\ref{meg_sloc:fig:2}) that the minimum norm solution has reconstructed only one of the sources. Note, however, the location of the dotted line in the upper time-series window. The source amplitude reconstruction is based on the location of this line (and conversely the time series shown taken from the maximum image voxel). In the \texttt{ms or mm} box fill in ``205'' then press \texttt{mip}. You should now see that the minimum norm solution is indeed bilateral, although rather diffuse (Figure~\ref{meg_sloc:fig:3}). Note the log-evidence 5263658. +It appears (\ref{meg_sloc:fig:2}) that the minimum norm solution has reconstructed only one of the sources. Note, however, the location of the dotted line in the upper time-series window. The source amplitude reconstruction is based on the location of this line (and conversely the time series shown taken from the maximum image voxel). In the \texttt{ms or mm} box fill in ``205'' then press \texttt{mip}. You should now see that the minimum norm solution is indeed bilateral, although rather diffuse (Figure~\ref{meg_sloc:fig:3}). Note the log-evidence 4620718 (in the most recent version of SPM the absolute value of the log evidence may have changed, but it is this value relative to those following which is important). \begin{figure} \begin{center} @@ -67,7 +67,7 @@ \subsection{IID (minimum norm)} \end{center} \end{figure} -The grey line in the time-series plot shows the amplitude of this voxel in the other ('scrambled') condition. To toggle between the conditions being viewed you can press the \texttt{condition 1/2} button. +The grey line in the time-series plot shows the amplitude of this voxel in the other ('scrambled') condition. To toggle between the conditions being viewed you can press the \texttt{condition 1/2} button. Then press the \texttt{mip} button to update the display. Often we will interested in the difference between conditions over a specific time-frequency window, rather than at a single latency. Press the \texttt{Window} button. At the \texttt{Time window (ms)} prompt type ``0 600''. For the \texttt{Frequency [band] of interest (Hz)} type ``1 40''. For \texttt{Power} select \texttt{induced} (although for these data \texttt{evoked} will work just as well). You will now see a glass brain showing a power plot for the current condition. You can convert this image and the corresponding image from the other condition into a volume by pressing \texttt{Image} (Figure~\ref{meg_sloc:fig:4}). \begin{figure} @@ -78,7 +78,7 @@ \subsection{IID (minimum norm)} \end{figure} \subsection{Smooth priors (COH)} -The COH option allows the mixture of two possible source covariance matrices: the minimum norm prior above and a much smoother source covariance matrix in which adjacent sources are correlated (over the scale of a few mm). Press \texttt{Invert}. Under reconstruction method press \texttt{Imaging}. For \texttt{All conditions or trials} press \texttt{Yes}. For model press \texttt{Custom}. Model inversion \texttt{COH}. Under Time-window ``0 600''. For \texttt{PST Hanning} select \texttt{Yes}. For High-pass (Hz) select \texttt{1} for Low-pass (Hz) select \texttt{48}. For \texttt{Source priors}, select \texttt{No}. Under \texttt{Restrict solutions} select \texttt{No}. You will see a plot similar to Figure~\ref{meg_sloc:fig:5} appear. The lower panel shows the glass brain in which bilateral sources are apparent. The upper panel shows the time-series of the source with the largest amplitude. In this case the peak activation is identified at location 59,-32 13. The 10Hz time-course (associated with this source) is also clearly visible in the top panel. Log evidence is 5272712. +The COH option allows the mixture of two possible source covariance matrices: the minimum norm prior above and a much smoother source covariance matrix in which adjacent sources are correlated (over the scale of a few mm). Press \texttt{Invert}. Under reconstruction method press \texttt{Imaging}. For \texttt{All conditions or trials} press \texttt{Yes}. For model press \texttt{Custom}. Model inversion \texttt{COH}. Under Time-window ``0 600''. For \texttt{PST Hanning} select \texttt{Yes}. For High-pass (Hz) select \texttt{1} for Low-pass (Hz) select \texttt{48}. For \texttt{Source priors}, select \texttt{No}. Under \texttt{Restrict solutions} select \texttt{No}. You will see a plot similar to Figure~\ref{meg_sloc:fig:5} appear. The lower panel shows the glass brain in which bilateral sources are apparent. The upper panel shows the time-series of the source with the largest amplitude. In this case the peak activation is identified at location 59,-32 13. The 10Hz time-course (associated with this source) is also clearly visible in the top panel. Log evidence is 5272712 (again this number may be different in your spm version). \begin{figure} \begin{center} @@ -87,44 +87,39 @@ \subsection{Smooth priors (COH)} \end{center} \end{figure} -\subsection{ARD} -ARD works by creating a basis set of many possible source configurations (e.g. many single sources and left-right symmetric correlated sources) or components. It then works through to eliminate those components which contribute the least (to the model evidence). -Press \texttt{Invert}. Under reconstruction method press \texttt{Imaging}. For \texttt{All conditions or trials} press \texttt{Yes}. For model press \texttt{Custom}. Model inversion \texttt{ARD}. Under Time-window ``0 600''. For \texttt{PST Hanning} select \texttt{Yes}. For \texttt{High-pass (Hz)} select ``1'' for \texttt{Low-pass (Hz)} select ``48''. For \texttt{Source priors}, select \texttt{No}. Under \texttt{Restrict solutions} select \texttt{No}. In Figure~\ref{meg_sloc:fig:6} the lower panel shows the glass brain in which bilateral sources are apparent and more focal than previously observed. This becomes more evident if you now work through to produce a contrast. Press the \texttt{Window}, \texttt{Time window (ms)} prompt type ``0 600''. \texttt{Frequency [band] of interest (Hz)} type ``1 40'', for \texttt{Power} select \texttt{induced}. Then press \texttt{Image} to see the result overlaid on an MNI brain (Figure~\ref{meg_sloc:fig:7}). Note the evidence 5470698. -\begin{figure} -\begin{center} -\includegraphics[width=100mm]{meg_sloc/slide6} -\caption{\em ARD imaging source reconstruction.\label{meg_sloc:fig:6}} -\end{center} -\end{figure} -We could now make a volume to compare with the minimum norm solution (Figure~\ref{meg_sloc:fig:4}) \footnote{Note that you need to copy the previously generated image files to a different directory to prevent them from being overwritten}. Press the \texttt{Window} button. At the \texttt{Time window (ms)} prompt type ``0 600''. For the \texttt{Frequency [band] of interest (Hz)} type ``1 40''. For \texttt{Power} select \texttt{induced} (although for these data \texttt{evoked} will work just as well). You will now see a glass brain showing a difference in power plot between the two conditions. You can convert this into a volume by pressing \texttt{Image} (Figure~\ref{meg_sloc:fig:7}). + +\subsection{MSP} +In contrast to IID or COH, the greedy search routine used in MSP builds up successive combinations of source configurations until the model evidence can no longer be improved. +Press \texttt{Invert}. Under reconstruction method press \texttt{Imaging}. For \texttt{All conditions or trials} press \texttt{Yes}. For model press \texttt{Custom}. Model inversion \texttt{MSP}. Under Time-window ``0-600''. For \texttt{PST Hanning} select \texttt{Yes}. \texttt{For High-pass (Hz)} select \texttt{1} for \texttt{Low-pass (Hz)} select ``48''. For \texttt{Source priors}, select \texttt{No}. Under \texttt{Restrict solutions} select \texttt{No}. Note again the more focal sources (Figure~\ref{meg_sloc:fig:7}) as compared to the minimum norm solution; although the time-series estimation seems to have suffered. Note the evidence 5464023. + + + + \begin{figure} \begin{center} \includegraphics[width=100mm]{meg_sloc/slide7} -\caption{\em Exported functional image from ARD source reconstruction overlayed on the template structural image.\label{meg_sloc:fig:7}} +\caption{\em MSP imaging source reconstruction.\label{meg_sloc:fig:7}} \end{center} \end{figure} - -\subsection{Greedy Search (GS)} -In contrast to ARD, the greedy search routine builds up successive combinations of source configurations until the model evidence can no longer be improved. -Press \texttt{Invert}. Under reconstruction method press \texttt{Imaging}. For \texttt{All conditions or trials} press \texttt{Yes}. For model press \texttt{Custom}. Model inversion \texttt{GS}. Under Time-window ``0-600''. For \texttt{PST Hanning} select \texttt{Yes}. \texttt{For High-pass (Hz)} select \texttt{1} for \texttt{Low-pass (Hz)} select ``48''. For \texttt{Source priors}, select \texttt{No}. Under \texttt{Restrict solutions} select \texttt{No}. Note again the more focal sources (Figure~\ref{meg_sloc:fig:8}) as compared to the minimum norm solution; although the time-series estimation seems to have suffered. Note the evidence 5464023. +We could now make a volume to compare with the minimum norm solution (Figure~\ref{meg_sloc:fig:4}) \footnote{Note that you need to copy the previously generated image files to a different directory to prevent them from being overwritten}. Press the \texttt{Window} button. At the \texttt{Time window (ms)} prompt type ``0 600''. For the \texttt{Frequency [band] of interest (Hz)} type ``1 40''. For \texttt{Power} select \texttt{induced} (although for these data \texttt{evoked} will work just as well). You will now see a glass brain showing a difference in power plot between the two conditions. You can convert this into a volume by pressing \texttt{Image} (Figure~\ref{meg_sloc:fig:8}). \begin{figure} \begin{center} \includegraphics[width=100mm]{meg_sloc/slide8} -\caption{\em GS imaging source reconstruction.\label{meg_sloc:fig:8}} +\caption{\em Exported functional image from MSP source reconstruction overlayed on the template structural image.\label{meg_sloc:fig:8}} \end{center} \end{figure} -\subsection{Multiple Sparse Priors (Standard)} -The standard button is simply the use of a greedy search using the whole time window available in a band of 2-128Hz. following default options: Greedy Search, all time, hanning windowed, filter 2-128Hz. +\subsection{Standard} +The standard button is simply the use of the MSP greedy search using the whole time window available in a band of 2-128Hz. following default options: MSP, all time, hanning windowed, filter 2-128Hz. \subsection{Model comparison} -As we tested all the above models on the same data we can make a model comparison. Figure~\ref{meg_sloc:fig:9} shows that the ARD model is marginally superior to the GS and both of these improve upon IID and COH solutions. +As we tested all the above models on the same data we can make a model comparison. Figure~\ref{meg_sloc:fig:9} shows that the MSP model improves upon IID and COH solutions. \begin{figure} \begin{center} @@ -142,7 +137,7 @@ \subsection{LCMV beamformer} On the main SPM menu select the Toolbox pull-down menu. Under \texttt{Beamforming} select \texttt{Volumetric LCMV beamformer}. Select file \texttt{sim\_data\_aud1020Hz.mat}. The first menu will ask you to select the active condition. Select 'faces' and click \texttt{OK}. You will then be asked at what time the condition 'faces' begins. At \texttt{Offset (ms) from faces}, type 0. At the duration prompt type 600. i.e. we are using the same 0-600ms window as before. At the baseline condition prompt select 'scrambled'. \texttt{Offset ms from scrambled} should be set to 0ms also. We will be comparing the same time window 0-600ms across epochs labelled either scrambled, or faces. At the number of frequency bands prompt type ``2''. The more frequency bands one computes at this stage the smaller the overhead in time. For the first band type ``15 25'', for the second try ``1 48''. For \texttt{gridstep} type ``10'' mm (number of voxels hence speed decreases by a factor of 8 each time this is halved). Leave regularization at 0. Select \texttt{yes} for preview results. -As you selected preview you will see an image similar to Figure~\ref{meg_sloc:fig:10}, in which we restricted our analyses to the frequency band around one source. This is a t-statistic image showing the difference between the two conditions (note in this image left is on right). You can navigate through the image using the mouse and need to press \texttt{q} to leave the window. The second figure produced Figure~\ref{meg_sloc:fig:11} should be comparable with the previous time-window analyses on the 1-48Hz band. +As you selected preview you will see an image similar to Figure~\ref{meg_sloc:fig:10}, in which we restricted our analyses to the frequency band around one source. This is a t-statistic image showing the difference between the two conditions. You can navigate through the image using the mouse and need to press any key to continue processing. The second figure produced Figure~\ref{meg_sloc:fig:11} should be comparable with the previous time-window analyses on the 1-48Hz band. \begin{figure} \begin{center} @@ -160,13 +155,13 @@ \subsection{LCMV beamformer} Now to compare the beamformer images with some of our other reconstructions: -You will find the volumetric images within the sub-directory \texttt{''tstatBf\_images}. You can use the \texttt{''checkReg} button to compare these images with other volumes (produced above using the \texttt{Window''/``Image} options. In Figure~\ref{meg_sloc:fig:12} the ARD and beamformer 0-600ms, 1-48Hz contrasts are shown alongside an anatomical image from the spm/templates directory. +You will find the volumetric images within the sub-directory \texttt{''tstatBf\_images}. You can use the \texttt{''checkReg} button to compare these images with other volumes (produced above using the \texttt{Window''/``Image} options. In Figure~\ref{meg_sloc:fig:12} the MSP and beamformer 0-600ms, 1-48Hz contrasts are shown alongside an anatomical image from the spm/templates directory. If you would like to observe the case where the beamformer breaks down due to correlated sources you could change the frequency of the two dipoles used in the simulation to be identical (e.g. dipfreq=[20 20;20 20]) and look at how the beamformer images degrade, whereas the MSP schemes (COH,ARD etc) should be relatively unaffected. \begin{figure} \begin{center} \includegraphics[width=100mm]{meg_sloc/slide12} -\caption{\em Comparison of ARD and LCMV beamformer results.\label{meg_sloc:fig:12}} +\caption{\em Comparison of MSP and LCMV beamformer results.\label{meg_sloc:fig:12}} \end{center} \end{figure} @@ -207,8 +202,8 @@ \subsection{Inversion} Proceed by pressing the \texttt{Invert} button. Select the \texttt{VB-ECD} button. \subsubsection{Fitting a single dipole with no priors} -At the \texttt{time\_bin or average\_win} prompt enter ``235''. For \texttt{Trial type number} choose ``1'' (we want to model the faces data). At the \texttt{Add dipoles to model} click \texttt{Single}. For \texttt{location prior} click \texttt{Non-info}. For \texttt{Moment prior} click \texttt{Non-info}. At the \texttt{Add dipoles to 1 or stop?} prompt click \texttt{stop}. Leave the default number of iterations at ``10''. -You will see the 10 successive fits of the same data using a random starting location and moment. At each fit maps of the predicted and simulated data along with free-energy values and percent variance explained are shown. The final plot will be similar to Figure~\ref{meg_sloc:fig:15} where the model (i.e. dipole) which maximised the evidence (the best iteration is shown with a red dot) is displayed. Note down the model evidence (in this case -4.3). The Bayesian dipole fit algorithm will be most useful when one has some prior knowledge of the sources (such as location, orientation or symmetry). Typical dipole fit algorithms fit 3 location parameters per dipole and then estimate the moment through a pseudo-inverse. The VB-ECD algorithm however fits 6 parameters per dipole as the moments are also allowed prior values. That is, if you have no prior knowledge then the Bayesian method will be generally less robust than such fitting methods (as more parameters are being fit). However it is when prior knowledge is supplied that the Bayesian methods become optimal. +At the \texttt{time\_bin or average\_win} prompt enter ``235''. For \texttt{Trial type number} choose ``1'' (we want to model the faces data). At the \texttt{Add dipoles to model} click \texttt{Single}. For \texttt{location prior} click \texttt{Non-info}. For \texttt{Moment prior} click \texttt{Non-info}. At the \texttt{Add dipoles to 1 or stop?} prompt click \texttt{stop}. At the \texttt{Data SNR (amp)} leave as default \texttt{5}. Leave the default number of iterations at ``10''. +You will see the 10 successive fits of the same data using a random starting location and moment. At each fit maps of the predicted and simulated data along with free-energy values and percent variance explained are shown. The final plot will be similar to Figure~\ref{meg_sloc:fig:15} where the model (i.e. dipole) which maximised the evidence (the best iteration is shown with a red dot) is displayed. Note down the model evidence (in this case -4.3, but the absolute value in your implementation may be different). The Bayesian dipole fit algorithm will be most useful when one has some prior knowledge of the sources (such as location, orientation or symmetry). Typical dipole fit algorithms fit 3 location parameters per dipole and then estimate the moment through a pseudo-inverse. The VB-ECD algorithm however fits 6 parameters per dipole as the moments are also allowed prior values. That is, if you have no prior knowledge then the Bayesian method will be generally less robust than such fitting methods (as more parameters are being fit). However it is when prior knowledge is supplied that the Bayesian methods become optimal. \begin{figure} \begin{center} @@ -220,15 +215,15 @@ \subsubsection{Fitting a single dipole with no priors} \subsubsection{Fitting a single dipole with reasonable and unreasonable priors} We will now provide some prior knowledge to the dipole fit perhaps led by the literature or a particular hypothesis. In this case we know the answer, but let us specify a location a couple of cm from where we know the source to be (at -52,-29,13mm) and try the fit again. -At the \texttt{time\_bin or average\_win} prompt enter ``235''. For \texttt{Trial type number} choose ``1'' (we want to model the faces data). At the \texttt{Add dipoles to model} click \texttt{Single}. For \texttt{location prior} click \texttt{Informative}. For the location enter ``-62 -20 10''. For prior location variance leave at ``100 100 100'' mm$^2$. This means that we are not sure about the source location to better than 10mm in each dimension. For \texttt{Moment prior} click \texttt{Non-info}. At the \texttt{Add dipoles to 1 or stop?} prompt click \texttt{stop}. Leave the default number of iterations at ``10''. Again you will get a final fit location and model evidence (-3.8), which should have improved (be more positive) on the evidence above. +At the \texttt{time\_bin or average\_win} prompt enter ``235''. For \texttt{Trial type number} choose ``1'' (we want to model the faces data). At the \texttt{Add dipoles to model} click \texttt{Single}. For \texttt{location prior} click \texttt{Informative}. For the location enter ``-62 -20 10''. For prior location variance leave at ``100 100 100'' mm$^2$. This means that we are not sure about the source location to better than 10mm in each dimension. For \texttt{Moment prior} click \texttt{Non-info}. At the \texttt{Add dipoles to 1 or stop?} prompt click \texttt{stop}. At the \texttt{Data SNR (amp)} leave as default \texttt{5}. Leave the default number of iterations at ``10''. Again you will get a final fit location and model evidence (-3.8), which should have improved (be more positive) on the evidence above. Now go through exactly the same procedure as above but for the prior location enter ``+62 -20 10'', i.e. on the wrong side of the head. You will note that the algorithm finds the correct location but the evidence for this model (with the incorrect prior) is much lower (-8.4). You could also try to fit a symmetric pair to this latency dataset (see below), model evidence -150. \subsubsection{Fitting more dipoles} We will start by examining the time instant at which we can clearly see a two-dipolar field pattern. -At the \texttt{time\_bin or average\_win} prompt enter ``205''. For \texttt{Trial type number} choose ``1''. At the \texttt{Add dipoles to model} click \texttt{Single}. For \texttt{location prior} click \texttt{Informative}. For the location enter ``62 -20 10''. For prior location variance enter ``400 400 400'' mm$^2$, that is, the prior standard deviation on the dipole location is 20mm in each direction. For \texttt{Moment prior} click \texttt{Non-info}. At the \texttt{Add dipoles to 1 or stop?} prompt click \texttt{Single}. For \texttt{location prior} click \texttt{Informative}. For the location enter ``-62 -20 10''. For prior location variance enter ``400 400 400'' mm$^2$. At the \texttt{Add dipoles to 1 or stop?} prompt click \texttt{stop}. Leave the default number of iterations at ``10''. Note down the final model evidence (570). +At the \texttt{time\_bin or average\_win} prompt enter ``205''. For \texttt{Trial type number} choose ``1''. At the \texttt{Add dipoles to model} click \texttt{Single}. For \texttt{location prior} click \texttt{Informative}. For the location enter ``62 -20 10''. For prior location variance enter ``400 400 400'' mm$^2$, that is, the prior standard deviation on the dipole location is 20mm in each direction. For \texttt{Moment prior} click \texttt{Non-info}. At the \texttt{Add dipoles to 1 or stop?} prompt click \texttt{Single}. For \texttt{location prior} click \texttt{Informative}. For the location enter ``-62 -20 10''. For prior location variance enter ``400 400 400'' mm$^2$. At the \texttt{Add dipoles to 1 or stop?} prompt click \texttt{stop}. At the \texttt{Data SNR (amp)} leave as default \texttt{5}. Leave the default number of iterations at ``10''. Note down the final model evidence (570). -Alternatively we can exploit the fact that we have prior knowledge that the dipoles will be approximately left-right symmetric in location and orientation. At the \texttt{time\_bin or average\_win} prompt enter ``205''. For \texttt{Trial type number} choose ``1''. At the \texttt{Add dipoles to model} click \texttt{Symmetric Pair}. For \texttt{location prior} click \texttt{Informative}. For the location enter \texttt{62 -20 10}. For prior location variance enter ``400 400 400'' mm$^2$. For \texttt{Moment prior} click \texttt{Non-info}. At the \texttt{Add dipoles to 2 or stop?} prompt click \texttt{stop}. Leave the default number of iterations at ``10''. Note that the final locations are approximately correct, but importantly the model evidence (-9.6) is much lower than previously. Given this information one would accept the two distinct dipole model over the symmetric pair. +Alternatively we can exploit the fact that we have prior knowledge that the dipoles will be approximately left-right symmetric in location and orientation. At the \texttt{time\_bin or average\_win} prompt enter ``205''. For \texttt{Trial type number} choose ``1''. At the \texttt{Add dipoles to model} click \texttt{Symmetric Pair}. For \texttt{location prior} click \texttt{Informative}. For the location enter \texttt{62 -20 10}. For prior location variance enter ``400 400 400'' mm$^2$. For \texttt{Moment prior} click \texttt{Non-info}. At the \texttt{Add dipoles to 2 or stop?} prompt click \texttt{stop}. At the \texttt{Data SNR (amp)} leave as default \texttt{5}. Leave the default number of iterations at ``10''. Note that the final locations are approximately correct, but importantly the model evidence (-9.6) is much lower than previously. Given this information one would accept the two distinct dipole model over the symmetric pair. Finally we can take our best model so far, and try adding in an extra source. -At the \texttt{time\_bin or average\_win} prompt enter ``205''. For \texttt{Trial type number} choose ``1''. At the \texttt{Add dipoles to model} click \texttt{Single}. For \texttt{location prior} click \texttt{Informative}. For the location enter ``62 -20 10''. For prior location variance enter ``400 400 400'' mm$^2$, that is, the prior standard deviation on the dipole location is 20mm in each direction. For \texttt{Moment prior} click \texttt{Non-info}. At the \texttt{Add dipoles to 1 or stop?} prompt click \texttt{Single}. For \texttt{location prior} click \texttt{Informative}. For the location enter ``-62 -20 10''. For prior location variance enter ``400 400 400'' mm$^2$. At the \texttt{Add dipoles to 2 or stop?} prompt click \texttt{Single}. We will add an extra dipole that can be anywhere in the head, so for \texttt{Location Prior} click \texttt{Non-info}. For \texttt{Moment Prior} click \texttt{non-info}. At the \texttt{Add dipoles to 2 or stop?} prompt click \texttt{Stop}. Leave the default number of iterations at ``10''. Note down the final model evidence (550). That is, the evidence has now begun to decrease once more suggesting that the two distinct dipole model is the best for these data. +At the \texttt{time\_bin or average\_win} prompt enter ``205''. For \texttt{Trial type number} choose ``1''. At the \texttt{Add dipoles to model} click \texttt{Single}. For \texttt{location prior} click \texttt{Informative}. For the location enter ``62 -20 10''. For prior location variance enter ``400 400 400'' mm$^2$, that is, the prior standard deviation on the dipole location is 20mm in each direction. For \texttt{Moment prior} click \texttt{Non-info}. At the \texttt{Add dipoles to 1 or stop?} prompt click \texttt{Single}. For \texttt{location prior} click \texttt{Informative}. For the location enter ``-62 -20 10''. For prior location variance enter ``400 400 400'' mm$^2$. At the \texttt{Add dipoles to 2 or stop?} prompt click \texttt{Single}. We will add an extra dipole that can be anywhere in the head, so for \texttt{Location Prior} click \texttt{Non-info}. For \texttt{Moment Prior} click \texttt{non-info}. At the \texttt{Add dipoles to 3 or stop?} prompt click \texttt{Stop}. At the \texttt{Data SNR (amp)} leave as default \texttt{5}. Leave the default number of iterations at ``10''. Note down the final model evidence (550). That is, the evidence has now begun to decrease once more suggesting that the two distinct dipole model is the best for these data. diff --git a/man/meg_sloc/slide10.png b/man/meg_sloc/slide10.png index 3dc1219..867eaed 100644 Binary files a/man/meg_sloc/slide10.png and b/man/meg_sloc/slide10.png differ diff --git a/man/meg_sloc/slide11.png b/man/meg_sloc/slide11.png index ca62713..9ed39a7 100644 Binary files a/man/meg_sloc/slide11.png and b/man/meg_sloc/slide11.png differ diff --git a/man/meg_sloc/slide12.png b/man/meg_sloc/slide12.png index 2e8d4e6..6238eca 100644 Binary files a/man/meg_sloc/slide12.png and b/man/meg_sloc/slide12.png differ diff --git a/man/meg_sloc/slide7.png b/man/meg_sloc/slide7.png index b5343c3..c196ff7 100644 Binary files a/man/meg_sloc/slide7.png and b/man/meg_sloc/slide7.png differ diff --git a/man/meg_sloc/slide8.png b/man/meg_sloc/slide8.png index c196ff7..0f50846 100644 Binary files a/man/meg_sloc/slide8.png and b/man/meg_sloc/slide8.png differ diff --git a/man/meg_sloc/slide9.png b/man/meg_sloc/slide9.png index b229433..f905a6b 100644 Binary files a/man/meg_sloc/slide9.png and b/man/meg_sloc/slide9.png differ diff --git a/man/mmn/mmn.tex b/man/mmn/mmn.tex index 7938885..4c30c66 100644 --- a/man/mmn/mmn.tex +++ b/man/mmn/mmn.tex @@ -21,38 +21,43 @@ \subsection{Convert} SPM will now read the original Biosemi format file and create an SPM compatible data file, called \texttt{spm8\_subject1.mat} and \texttt{spm8\_subject1.dat} in the directory containing the original data file (\texttt{DATA\_DIR}). -\subsection{Filter} -Filtering the data in time removes unwanted frequency bands from the data. Usually, for evoked response analysis, the low frequencies are kept, while the high frequencies are assumed to carry noise. Here, we will use a bandpass filter to remove ultra-low frequencies close to DC, and also remove high frequencies at the same time. We filter prior to downsampling because otherwise high-amplitude baseline shifts present in the data will generate filtering artefacts at the edges of the file. -\begin{itemize} -\item{Click on \textsc{Filter} and select the \texttt{spm8\_subject1.mat} file.} -\item{Select a ``bandpass'' filter with band 0.5 30 (Hz).} -\end{itemize} -The progress bar will appear and the resulting filtered data will be saved in files \texttt{fspm8\_subject1.mat} and \texttt{fspm8\_subject1.dat}. This step requires the Signal Processing Toolbox. - - -\subsection{Downsample} -Here, we will downsample the data in time. This is useful when the data were acquired like ours with a high sampling rate of 512 Hz. This is an unnecessarily high sampling rate for a simple evoked response analysis, and we will now decrease the sampling rate to 200 Hz, thereby reducing the file size by more than half. Select \textsc{Downsample} from the ``Other'' drop-down menu and select the \texttt{fspm8\_subject1.mat} file. Choose a new sampling rate of 200 (Hz). The progress bar will appear and the resulting data will be saved to files \texttt{dfspm8\_subject1.mat} and \texttt{dfspm8\_subject1.dat}. This step requires the Signal Processing Toolbox. - \subsection{Montage} -In this step, we will identify the VEOG and HEOG channels, and also remove several channels that don't carry EEG data and are of no importance to the following. We generally recommend to remove all data channels that are no longer needed because it will reduce the total file size. We will also convert the data to average reference montage by subtracting from each channel the mean of all EEG channels. To do so, we use the \textsc{montage} tool in SPM, which is a general approach for pre-multiplying the data matrix (channels $\times$ time) by another matrix that linearly weights all channel data. This provides a very general method for data transformation in M/EEG analysis. +In this step, we will identify the VEOG and HEOG channels, and also remove several channels that don't carry EEG data and are of no importance to the following. In this case we apply montage as the first processing step to set all the channel types correctly for subsequent processing. This is especially important for the EOG channels, which are derived from channels that would not normally be filtered because SPM does not recognize them as containing M/EEG data. We generally recommend to remove all data channels that are no longer needed because it will reduce the total file size. We will also convert the data to average reference montage by subtracting from each channel the mean of all EEG channels. To do so, we use the \textsc{montage} tool in SPM, which is a general approach for pre-multiplying the data matrix (channels $\times$ time) by another matrix that linearly weights all channel data. This provides a very general method for data transformation in M/EEG analysis. The appropriate montage-matrix can be derived as follows. In our case, we would like to only keep EEG channels 1 to 128 and subtract from each channel the average of all EEG channels. In addition, there were three EOG channels (129, 130, 131), where the HEOG is computed as the difference between channels 131 and 130, and the VEOG by the difference between channels 130 and 129. This matrix can be specified in SPM by either using a graphical interface, or by supplying the matrix saved in a file. We will do the latter. The script to generate this file can be found in the \texttt{example\_scripts} folder: \texttt{montage\_subject1.m}. Copy this script into \texttt{DATA\_DIR} and run it. This will generate a file named \texttt{MONT\_EXP.mat}. You now call the montage function by choosing \textsc{Montage} in the ``Other'' drop-down menu and: \begin{itemize} -\item{Select the M/EEG-file \texttt{dfspm8\_subject1.mat}} +\item{Select the M/EEG-file \texttt{spm8\_subject1.mat}} \item{`How to specify the montage ?' Answer ``file''.} \item{Then select the generated \texttt{MONT\_EXP.mat} file} \item{``Keep the other channels?'' : ``No''} \end{itemize} -This will remove the uninteresting channels from the data. The progress bar appears and SPM will generate two new files \texttt{Mdfspm8\_subject1.mat} and \texttt{Mdfspm8\_subject1.dat}. +This will remove the uninteresting channels from the data. The progress bar appears and SPM will generate two new files \texttt{Mspm8\_subject1.mat} and \texttt{Mspm8\_subject1.dat}. This step will also assign default locations to the sensors, as this information is not contained in the original Biosemi \texttt{*.bdf} file. It is usually the responsibility of the user to link the data to sensors which are located in a coordinate system. In our experience this is a critical step. SPM provide tools (\textsc{Prepare}) for linking data and location information, leaving it the responsibility of the user to verify the success of this process. Chapter \ref{Chap:eeg:preprocessing} describes in detail how you can use the \textsc{Prepare} tool from the ``Other'' drop-down menu to use digitized sensor location data. + +\subsection{Filter} +Filtering the data in time removes unwanted frequency bands from the data. Usually, for evoked response analysis, the low frequencies are kept, while the high frequencies are assumed to carry noise. Here, we will use a highpass filter to remove ultra-low frequencies close to DC, and a lowpass filter to remove high frequencies. We filter prior to downsampling because otherwise high-amplitude baseline shifts present in the data will generate filtering artefacts at the edges of the file. +\begin{itemize} +\item{Click on \textsc{Filter} and select the \texttt{Mspm8\_subject1.mat} file.} +\item{Select a ``highpass'' filter with cutoff of 0.5 (Hz).} +\end{itemize} +The progress bar will appear and the resulting filtered data will be saved in files \texttt{fMspm8\_subject1.mat} and \texttt{fMspm8\_subject1.dat}. +\begin{itemize} +\item{Click on \textsc{Filter} and select the \texttt{fMspm8\_subject1.mat} file.} +\item{Select a ``lowpass'' filter with cutoff of 30 (Hz).} +\end{itemize} +The progress bar will appear and the resulting filtered data will be saved in files \texttt{ffMspm8\_subject1.mat} and \texttt{ffMspm8\_subject1.dat}. + +\subsection{Downsample} +Here, we will downsample the data in time. This is useful when the data were acquired like ours with a high sampling rate of 512 Hz. This is an unnecessarily high sampling rate for a simple evoked response analysis, and we will now decrease the sampling rate to 200 Hz, thereby reducing the file size by more than half. Select \textsc{Downsample} from the ``Other'' drop-down menu and select the \texttt{ffMspm8\_subject1.mat} file. Choose a new sampling rate of 200 (Hz). The progress bar will appear and the resulting data will be saved to files \texttt{dffMspm8\_subject1.mat} and \texttt{dffMspm8\_subject1.dat}. This step requires the Signal Processing Toolbox. + \subsection{Epoch} -To epoch the data click on \textsc{Epoching}. Select the \texttt{Mdfspm8\_subject1.mat} file. Choose the peri-stimulus time window, first the start \texttt{-100}, then the end \texttt{400} ms. Choose 2 conditions. You can call the first condition ``standard''. A GUI pops up which gives you a complete list of all events in the EEG file. The standard condition had 480 trials, so select the type with value 1 and press OK. The second condition can be called ``rare''. The rare stimulus was given 120 times and has value 3 in the list. Select this trial type and press OK. Answer two times ``no'' to the questions ``review individual trials'', and ``save trial definitions''. The progress bar will appear and the epoched data will be saved to files \texttt{eMdfspm8\_subject1.mat} and \texttt{eMdfspm8\_subject1.dat}. +To epoch the data click on \textsc{Epoching}. Select the \texttt{dffMspm8\_subject1.mat} file. Choose the peri-stimulus time window, first the start \texttt{-100}, then the end \texttt{400} ms. Choose 2 conditions. You can call the first condition ``standard''. A GUI pops up which gives you a complete list of all events in the EEG file. The standard condition had 480 trials, so select the type with value 1 and press OK. The second condition can be called ``rare''. The rare stimulus was given 120 times and has value 3 in the list. Select this trial type and press OK. Answer two times ``no'' to the questions ``review individual trials'', and ``save trial definitions''. The progress bar will appear and the epoched data will be saved to files \texttt{edffMspm8\_subject1.mat} and \texttt{edffMspm8\_subject1.dat}. \begin{figure} \begin{center} \includegraphics[width=150mm]{mmn/topo1} @@ -65,7 +70,7 @@ \subsection{Artefacts} A number of different methods of artefact removal are implemented in SPM8. Here, we will demonstrate a simple thresholding method. However, before doing so, we will look at the data in the display: \begin{itemize} \item{Choose ``M/EEG'' from the ``Display'' dropdown menu.} -\item{Select the \texttt{eMdfspm8\_subject1.mat} file.} +\item{Select the \texttt{edffMspm8\_subject1.mat} file.} \item{Click on the ``EEG'' tab.} \item{Press the ``scalp'' radio button.} \end{itemize} @@ -75,23 +80,23 @@ \subsection{Artefacts} Right-click on the channel; this tells you that this channel is ``A14''. You will also see as an entry in this menu ``bad: 0''. Select this entry, and click the left button. This will make the menu disappear, but the channel now has a grey background. You have marked this channel as bad. Click on ``save''in the top-right corner. This channel will then be ignored in subsequent processing. In fact this channel probably doesn't need removing, but we do so for teaching purposes only. \\ \\ -Now, click on \textsc{Artefacts}. A window of SPM8 batch interface will open. You might be already familiar with this interface from other SPM8 functions. It is also possible to use the batch interface to run the preprocessing steps that we have performed until now, but for artefact detection this is the only graphical interface. Click on ``File name'' and select the \texttt{eMdfspm8\_subject1.mat} file. Double click ``How to look for artefacts'' and a new branch will appear. It is possible to define several sets of channels to scan and several different methods for artefact detection. We will use simple thresholding applied to all channels. Click on ``Detection algorithm'' and select ``Threshold channels'' in the small window below. Double click on ``Threshold'' and enter 80 (in this case $\mu V$). The batch is now fully configured. Run it by pressing the green button at the top of the batch window. +Now, click on \textsc{Artefacts}. A window of SPM8 batch interface will open. You might be already familiar with this interface from other SPM8 functions. It is also possible to use the batch interface to run the preprocessing steps that we have performed until now, but for artefact detection this is the only graphical interface. Click on ``File name'' and select the \texttt{edffMspm8\_subject1.mat} file. Double click ``How to look for artefacts'' and a new branch will appear. It is possible to define several sets of channels to scan and several different methods for artefact detection. We will use simple thresholding applied to all channels. Click on ``Detection algorithm'' and select ``Threshold channels'' in the small window below. Double click on ``Threshold'' and enter 80 (in this case $\mu V$). The batch is now fully configured. Run it by pressing the green button at the top of the batch window. This will detect trials in which the signal recorded at any of the channels exceeds 80 microvolts (relative to pre-stimulus baseline). These trials will be marked as artefacts. Most of these artefacts occur on the VEOG channel, and reflect blinks during the critical time window. The procedure will also detect channels in which there are a large number of artefacts (which may reflect problems specific to those electrodes, allowing them to be removed from subsequent analyses). In this case, the Matlab window will show: \begin{verbatim} - 1 bad channels: A14 -86 rejected trials: 3 4 5 24 25 26 28 29 30 31 88 98 [...] +1 bad channels: A14 +77 rejected trials: 3 4 5 7 8 9 10 12 28 29 88 [...] Done 'M/EEG Artefact detection' Done \end{verbatim} -A new file will also be created, \texttt{aeMdfspm8\_subject1.mat}. +A new file will also be created, \texttt{aedffMspm8\_subject1.mat}. There are also interactive artefact removal routines available from \texttt{Toolbox} $\rightarrow$ \texttt{MEEG tools} $\rightarrow$ \texttt{Fieldtrip visual artifact rejection}. \subsection{Averaging} -To produce an ERP click on \textsc{Averaging} and select the \texttt{aeMdfspm8\_subject1.mat} file. At this point you can perform either orinary averaging or ``robust averaging''. Robust averaging makes it possible to supress artefacts automatically without rejecting trials or channels compltely, but just the contaminated parts. For robust averaging answer ``yes'' to `Use robust averaging?''. Answer ``yes'' to ``Save weights'', and ``yes'' to ``Compute weights by condition'' \footnote{In this case we do not want to pool both conditions together because the number of standard and rare trials are quite different.} and press ``Enter'' to accept the default ``Offset of the weighting function''. A new dataset will be generated \texttt{maeMdfspm8\_subject1} and automatically opened in the reviewing tool so that you can examine the ERP. There will also be an additional dataset named \texttt{WaeMdfspm8\_subject1} this dataset will contain instead of EEG data the weights used by robust averaging. This is useful to see what was suppressed and whether there might be some condition-specific bias that could affect the results. +To produce an ERP click on \textsc{Averaging} and select the \texttt{aedffMspm8\_subject1.mat} file. At this point you can perform either ordinary averaging or ``robust averaging''. Robust averaging makes it possible to supress artefacts automatically without rejecting trials or channels compltely, but just the contaminated parts. For robust averaging answer ``yes'' to `Use robust averaging?''. Answer ``yes'' to ``Save weights'', and ``yes'' to ``Compute weights by condition'' \footnote{In this case we do not want to pool both conditions together because the number of standard and rare trials are quite different.} and press ``Enter'' to accept the default ``Offset of the weighting function''. A new dataset will be generated \texttt{maedffMspm8\_subject1} and automatically opened in the reviewing tool so that you can examine the ERP. There will also be an additional dataset named \texttt{WaedffMspm8\_subject1} this dataset will contain instead of EEG data the weights used by robust averaging. This is useful to see what was suppressed and whether there might be some condition-specific bias that could affect the results. The Graphics window will pop up and allow you to look at the averaged data. To look at the ERP, click on the EEG tab, and press the ``scalp'' radio button. Now hold the Shift button down on the keyboard whilst selecting trial 2 with the left mouse button in the upper right corner of the graphics window. This will overlay responses to standard and rare trials on the same figure axes. @@ -112,11 +117,11 @@ \section{Sensor space analysis} Here, we will consider a 3D example, where the third dimension is time, and test across trials within this single subject. We first create a 3D image for each trial of the two types, with dimensions M$\times$M$\times$S, where S=101 is the number of samples (time points). We then take these images into an unpaired t-test across trials (in a 2nd-level model) to compare ``standard'' and ``rare'' events. We can then use classical SPM to identify locations in space and time in which a reliable difference occurs, correcting across the multiple comparisons entailed. This would be appropriate if, for example, we had no a priori knowledge where or when the difference between standard and rare trials would emerge. The appropriate images are created as follows \begin{itemize} \item{Select the ``Convert to image'' option from the ``Other'' pulldown menu.} -\item{Select the \texttt{aeMdfspm8\_subject1.mat} file.} +\item{Select the \texttt{aedffMspm8\_subject1.mat} file.} \item{For ``output image dimensions'' accept the default of 32 (leading to a 32x32 pixel space).} \item{For ``interpolate' or ``mask out'' bad channels, select ``interpolate''.} \end{itemize} -SPM will take some time as it writes out a NIfTI image for each trial (except rejected trials), in a new directory called \texttt{aeMdfspm8\_subject1}, which will itself contain two subdirectories, one for each trialtype, called \texttt{type\_rare} and \texttt{type\_standard}. In each trialtype subdirectory there will be image and header files for each non-rejected trial of that type, e.g, trial0001.img/hdr. You can press ``Display: images'' to view one of these images - it will have dimensions 32$\times$32$\times$101. +SPM will take some time as it writes out a NIfTI image for each trial (except rejected trials), in a new directory called \texttt{aedffMspm8\_subject1}, which will itself contain two subdirectories, one for each trialtype, called \texttt{type\_rare} and \texttt{type\_standard}. In each trialtype subdirectory there will be image and header files for each non-rejected trial of that type, e.g, trial0001.img/hdr. You can press ``Display: images'' to view one of these images - it will have dimensions 32$\times$32$\times$101. To perform statistics on these images: \begin{itemize} @@ -143,7 +148,7 @@ \section{Sensor space analysis} \begin{itemize} \item{Press the right mouse button in the MIP} \item{Select ``display/hide channels''} -\item{Select the \texttt{maeMdfspm8\_subject1.mat} file.} +\item{Select the \texttt{maedffMspm8\_subject1.mat} file.} \end{itemize} This links the \texttt{SPM.mat} file with the M/EEG file from which the EEG images were created. It is now possible to superimpose the channel labels onto the spatial SPM, and also to ``goto the nearest channel'' (using options provided after a right mouse click, when navigating the MIP). @@ -168,7 +173,7 @@ \section{Source reconstruction} \subsection{Mesh} The first step is to load the data and create a cortical mesh upon which M/EEG data will be projected: \begin{itemize} -\item{Press the ``Load'' button in the souce localisation GUI and select the file \texttt{maeMdfspm8\_subject1.mat}.} +\item{Press the ``Load'' button in the souce localisation GUI and select the file \texttt{maedffMspm8\_subject1.mat}.} \item{Enter ``Standard'' under ``Comment/Label for this analysis'' and press OK.} \item{Now press the ``template'' button.} \item{For ``Cortical mesh'', select ``normal''.} @@ -217,7 +222,7 @@ \subsection{Invert} \item{Select ``Yes'' for ``All conditions or trials''.} \item{Select ``Standard'' for Model.} \end{itemize} -SPM will now compute a leadfield matrix and save it in the file \texttt{SPMgainmatrix.mat} placed in \texttt{DATA\_DIR}. This file can be replaced with one computed using other methods for computing the lead field (eg methods external to SPM). The forward model will then be inverted using the Multiple Sparse Priors (MSP) algorithm (the progress of which is outputted to the \matlab\ command window). SPM will produce, in the Graphics window, (i) a Maximum Intensity Projection (MIP) of activity in source space (lower panel) and (ii) a time series of activity for (upper panel) each condition. +SPM will now compute a leadfield matrix and save it in the file \texttt{SPMgainmatrix\_maedffMspm8\_subject1\_1.mat} placed in \texttt{DATA\_DIR}. This file can be replaced with one computed using other methods for computing the lead field (eg methods external to SPM). The forward model will then be inverted using the Multiple Sparse Priors (MSP) algorithm (the progress of which is outputted to the \matlab\ command window). SPM will produce, in the Graphics window, (i) a Maximum Intensity Projection (MIP) of activity in source space (lower panel) and (ii) a time series of activity for (upper panel) each condition. The ``ms or mm'' window has three functionalities (i) if you enter a single number this will be interpreted as ms, (ii) if you enter two numbers this will be interpreted as a time window for plotting movies (see below), (iii) if you enter 3 numbers this will be interpreted as MNI coordinates for a time series plot. @@ -258,7 +263,7 @@ \section{Dynamic Causal Modeling} \end{figure} We will now complete the three model specification entries shown in Figure~\ref{specify}: \begin{itemize} -\item{Press the ``new data'' button and select the \texttt{maeMdfspm8\_subject1.mat} file.} +\item{Press the ``new data'' button and select the \texttt{maedffMspm8\_subject1.mat} file.} \item{Enter the ``between-trial effects'' and design matrix information shown in Figure~\ref{specify}(a).} \item{Press the ``Display'' button.} \end{itemize} diff --git a/man/movie15.sty b/man/movie15.sty new file mode 100644 index 0000000..ab0b4b5 --- /dev/null +++ b/man/movie15.sty @@ -0,0 +1,4380 @@ +% Copyright 2004--2008 Alexander Grahn +% +% This material is subject to the LaTeX Project Public License. See +% http://www.ctan.org/tex-archive/help/Catalogue/licenses.lppl.html +% for the details of that license. +% +% This package allows inclusion of multimedia content into PDF files +% following Adobe's PDF-1.5 and 1.6 specifications. +% + +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{movie15}[2009/07/07] +\RequirePackage{keyval} +\RequirePackage{ifthen} +\RequirePackage{ifpdf} +\RequirePackage{ifdraft} + +\newboolean{@MXV@iiiDfeat} % enable 3D features from PDF-1.6 spec? +\setboolean{@MXV@iiiDfeat}{false}% +\newboolean{@MXV@iiid} %set to true if a 3D file is being embedded +\newboolean{@MXV@draft} %according to global setting +\newboolean{@MXV@@draft} %per inclusion setting + +\ifdraft{%globally set by document class + \setboolean{@MXV@draft}{true}% +}{% + \setboolean{@MXV@draft}{false}% +}% + +%override global setting +\DeclareOption{draft}{% + \setboolean{@MXV@draft}{true}% +} +\DeclareOption{final}{% + \setboolean{@MXV@draft}{false}% +} + +\DeclareOption{3D}{% + \setboolean{@MXV@iiiDfeat}{true}% +} + +\DeclareOption*{% + \PackageWarning{movie15}{Unknown option \CurrentOption} +} + +\ProcessOptions*\relax + +%testing for correct TeX version, +\ifpdf + \ifnum\pdftexversion<120 + \PackageError{movie15}{% + pdfeTeX, version >= 1.20, required + }{% + Install a more recent version! + }% + \fi +\fi + +\ifx\@undefined\pdfmdfivesum + \def\pdfmdfivesum file #1{#1} +\fi + +%for conditionals where \ifthenelse doesn't work +\gdef\@MXV@if#1{\csname if#1\endcsname}% + +\newboolean{@MXV@beamer} %set to true if beamer class has been loaded +%\newboolean{@MXV@powerdot} %the same for +\newboolean{@MXV@presentation} %used with presentation making package? +\newboolean{@MXV@hide} %contents hidden on the current slide? +\@ifclassloaded{beamer}{% + \setboolean{@MXV@beamer}{true}% + \setboolean{@MXV@presentation}{true}% +}{% + \setboolean{@MXV@beamer}{false}% + \setboolean{@MXV@presentation}{false}% +} +%\@ifclassloaded{powerdot}{% +% \setboolean{@MXV@powerdot}{true}% +% \setboolean{@MXV@presentation}{true}% +%}{% +% \setboolean{@MXV@powerdot}{false}% +% \setboolean{@MXV@presentation}{false}% +%} + +\AtBeginDocument{% + \@ifpackageloaded{hyperref}{}{\@MXV@missing{hyperref}}% +% \hypersetup{unicode} + \ifHy@colorlinks% coloured (movieref-)link text instead of link border + \gdef\@MXV@pdfborder{/Border [0 0 0]}% + \else% + \gdef\@MXV@pdfborder{}% + \fi% +} + +\RequirePackage{everyshi}% +\newcount\@MXV@page% counter for absolute page number +\EveryShipout{% + \global\advance\@MXV@page by 1% +} + +%define our own label making commands +\def\@MXV@newlabel#1#2{{% + \expandafter\xdef\csname#1\endcsname{#2}}}% + +\def\@MXV@getlabelvalue#1{% + \expandafter\ifx\csname#1\endcsname\relax% + undefined% + \else% + \csname#1\endcsname% + \fi% +}% + +%macro for writing labels to external *.aux file +\def\@MXV@labeltoaux#1#2{% + \@bsphack\protected@write\@auxout{}{% + \string\@MXV@newlabel{#1}{#2}% + \string\@MXV@newlabel{@#1@}{\@MXV@getlabelvalue{#1}}% + }\@esphack% + \ifthenelse{% + \equal{\@MXV@getlabelvalue{#1}}{undefined}\OR% + %double check that the value hasn't changed + \NOT\equal{\@MXV@getlabelvalue{#1}}{\@MXV@getlabelvalue{@#1@}}% + }{% + \ifthenelse{\isundefined{\@MXV@warning}}{% issue warning only once, at end + \gdef\@MXV@warning{}% of document + \AtEndDocument{% + \PackageWarningNoLine{movie15}{% + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\MessageBreak + @@ Rerun to get object references right! @@\MessageBreak + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}% + }% + }{}% + }{}% +}% +% +\ifpdf% + %for storing pdf object numbers (must be counters) + \newcount\@MXV@adict% + \newcount\@MXV@aadict% + % + %returns pdf page object number + \def\@MXV@pdfpageref#1{% + \expandafter\ifx\csname#1\endcsname\relax% + 0% + \else% + \expandafter\pdfpageref\csname#1\endcsname\space% + \fi% + }% +\fi + +%counter for absolute number of inclusions, +%used for labelling each annotation +\newcount\@MXV@includes + +%counter for absolute number of movie players +\newcount\@MXV@players + +%counter for absolute number of movierefs +\newcount\@MXV@links + +%measuring things +%textbox +\newdimen\@MXV@width +\newdimen\@MXV@height +\newdimen\@MXV@depth +\newdimen\@MXV@totalheight +\newdimen\@MXV@@boxdepth +%for centring the textbox within display box +\newdimen\@MXV@traiselen +\newdimen\@MXV@braiselen +%for compatibility options +\newdimen\@MXV@start +\newdimen\@MXV@end + +%stores textbox given as argument to text option +\newsavebox{\@MXV@textbox} + +%some booleans we need +\newboolean{@MXV@autoplay} +\newboolean{@MXV@autostop} +\newboolean{@MXV@autoresume} +\newboolean{@MXV@autoclose} +\newboolean{@MXV@autopause} +\newboolean{@MXV@mouse}%mouse interaction +\newboolean{@MXV@inline}%inline movie data +\newboolean{@MXV@attachment}%make embedded file extractable? +\newboolean{@MXV@externalviewer}%if true, screen annot will be removed +\newboolean{@MXV@url} +\newboolean{@MXV@boxopt}%true if text option is set +\newboolean{@MXV@textoverposter} +\newboolean{@MXV@runposter}% render poster from movie at runtime +\newboolean{@MXV@linkplay}% for \movieref command +\newboolean{@MXV@linkpause} +\newboolean{@MXV@linkresume} +\newboolean{@MXV@linkstop} +\newboolean{@MXV@linkclose} +\newboolean{@MXV@linkreset} +\newboolean{@MXV@issound} + +%macro to reset all macros and booleans +\def\@MXV@reset{% + \setboolean{@MXV@autoplay}{false}% + \setboolean{@MXV@autostop}{true}% + \setboolean{@MXV@autoresume}{false}% + \setboolean{@MXV@autopause}{false}% + \setboolean{@MXV@autoclose}{false}% + \setboolean{@MXV@mouse}{false}% + \setboolean{@MXV@inline}{true}% + \setboolean{@MXV@attachment}{true}% + \setboolean{@MXV@externalviewer}{false}% + \setboolean{@MXV@issound}{false}% + \setboolean{@MXV@url}{false}% + \setboolean{@MXV@boxopt}{false}% + \setboolean{@MXV@textoverposter}{true}% + \setboolean{@MXV@runposter}{false}% + \setboolean{@MXV@linkplay}{true}% + \setboolean{@MXV@linkpause}{false}% + \setboolean{@MXV@linkresume}{false}% + \setboolean{@MXV@linkstop}{false}% + \setboolean{@MXV@linkclose}{false}% + \setboolean{@MXV@linkreset}{false}% + \setboolean{@MXV@requirereopen}{false}% + \ifthenelse{\boolean{@MXV@draft}}{% + \setboolean{@MXV@@draft}{true}% + }{% + \setboolean{@MXV@@draft}{false}% + }% + % + \gdef\@MXV@label{}% for movieref + \gdef\@MXV@@label{}% for movieref + \gdef\@MXV@mime{@MXV@auto}% + \gdef\@MXV@player{}% + \gdef\@MXV@fsentry{}% + \gdef\@MXV@repeat{}% + \gdef\@MXV@@repeat{}% + \gdef\@MXV@volume{100}% + \gdef\@MXV@@volume{}% + \gdef\@MXV@ctrls{}% + \gdef\@MXV@@ctrls{}% + \gdef\@MXV@palindrome{}% + \gdef\@MXV@rate{}% + \gdef\@MXV@startat{}% + \gdef\@MXV@@startat{}% + \gdef\@MXV@endat{}% + \gdef\@MXV@poevent{}% + \gdef\@MXV@pcevent{}% + \gdef\@MXV@box##1##2##3{\raisebox{0pt}[##2][##3]{\makebox[##1]{}}}% + \setlength{\@MXV@depth}{0pt}% + \setlength{\@MXV@height}{0pt}% + \setlength{\@MXV@width}{0pt}% + \setlength{\@MXV@braiselen}{0pt}% + \setlength{\@MXV@traiselen}{0pt}% + \gdef\@MXV@boxdepth{}% + \gdef\@MXV@boxheight{}% + \gdef\@MXV@boxwidth{}% + % + \ifthenelse{\boolean{@MXV@iiiDfeat}}{% + \setboolean{@MXV@iiid}{false}% + \gdef\@MXV@aac{30}% aperture angle of camera + \gdef\@MXV@roll{0}% camera roll angle + \gdef\@MXV@defaultbg{1 1 1}% + \gdef\@MXV@background{/BG<>}% + \gdef\@MXV@defaultlights{}% + \gdef\@MXV@lights{}% + \gdef\@MXV@defaultrender{Solid}% + \gdef\@MXV@render{/RM <>}% + \gdef\@MXV@naentry{}% %takes array of Node dicts + \gdef\@MXV@saentry{}% %takes array of cross section dicts + \gdef\@MXV@jscriptiiidfile{}% + \gdef\@MXV@coo{0 0 0}% centre of orbit + \gdef\@MXV@ctoc{0 -1 0}% centre of orbit to camera vector + \gdef\@MXV@roo{0}% radius of orbit + \gdef\@MXV@viewsfile{}% file containing views of the 3D object + \gdef\@MXV@viewsfileii{}%file containing views of the 3D object (new format) + \setboolean{@MXV@viewsprovided}{false}% + \setboolean{@MXV@defaultviewprovided}{false}% + \gdef\@MXV@iiidview{}% + \gdef\@MXV@iiidtoolb{/TB false}% don't show toolbar by default + \gdef\@MXV@iiidia{}% 3D interactive by default + \gdef\@MXV@calc{}% camera aperture for coo and roo calculation + \setboolean{@MXV@iiidgetview}{false}% + \gdef\@MXV@iiidopt{}% option string to be passed to internal macro + \setboolean{@MXV@resource}{false}% + \gdef\@MXV@resourcetree{}% name tree of embedded 3D resources + \xdef\@MXV@animstyle{}% + \gdef\@MXV@iiidpalindrome{/Subtype/Linear}% forward + \gdef\@MXV@iiidrate{}% animation speed + \global\@MXV@iiidrepeat=-1% repeat count + }{}% +}% + +%missing package error message +\def\@MXV@missing#1{% + \PackageError{movie15}{% + Package `#1' has not been loaded yet + }{% + Put the line `\protect\usepackage{#1}' somewhere after + `\protect\usepackage{movie15}' to the preamble of your + document! + }% +} + +%3D-need-be-enabled error message +\def\@MXV@neediiiD{% + \PackageError{movie15}{% + If you wish to embed 3D objects, enable the\MessageBreak + 3D feature first by passing option `3D' to movie15!\MessageBreak + Make sure the `fp' package for fixed point calculus\MessageBreak + is installed in your TeX system + }{Package `fp' is available from CTAN.}% +} + +%macro to guess the mime type of the media file +\def\@MXV@guessmime#1#2{% + \ifthenelse{\equal{#2}{aiff}\OR\equal{#2}{AIFF}\OR% + \equal{#2}{aif}\OR\equal{#2}{AIF}\OR% + \equal{#2}{aifc}\OR\equal{#2}{AIFC}}{% + \gdef\@MXV@mime{audio/aiff}% + }{% + \ifthenelse{\equal{#2}{wav}\OR\equal{#2}{WAV}}{% + \gdef\@MXV@mime{audio/wav}% + }{% + \ifthenelse{\equal{#2}{wma}\OR\equal{#2}{WMA}}{% + \gdef\@MXV@mime{audio/x-ms-wma}% + }{% + \ifthenelse{\equal{#2}{wmv}\OR\equal{#2}{WMV}}{% + \gdef\@MXV@mime{video/x-ms-wmv}% + }{% + \ifthenelse{\equal{#2}{au}\OR\equal{#2}{AU}\OR% + \equal{#2}{snd}\OR\equal{#2}{SND}}{% + \gdef\@MXV@mime{audio/basic}% + }{% + \ifthenelse{\equal{#2}{mid}\OR\equal{#2}{MID}\OR% + \equal{#2}{rmi}\OR\equal{#2}{RMI}}{% + \gdef\@MXV@mime{audio/midi}% + }{% + \ifthenelse{\equal{#2}{mov}\OR\equal{#2}{MOV}\OR% + \equal{#2}{qt}\OR\equal{#2}{QT}}{% + \gdef\@MXV@mime{video/quicktime}% + }{% + \ifthenelse{\equal{#2}{mp3}\OR\equal{#2}{MP3}\OR% + \equal{#2}{m3u}\OR\equal{#2}{M3U}}{% + \gdef\@MXV@mime{audio/x-mp3}% + }{% + \ifthenelse{\equal{#2}{mp4}\OR\equal{#2}{MP4}}{% + \gdef\@MXV@mime{video/mp4}% + }{% + \ifthenelse{\equal{#2}{avi}\OR\equal{#2}{AVI}}{% + \gdef\@MXV@mime{video/avi}% + }{% + \ifthenelse{\equal{#2}{gif}\OR\equal{#2}{GIF}}{% + \gdef\@MXV@mime{image/gif}% + }{% + \ifthenelse{\equal{#2}{mpeg}\OR\equal{#2}{MPEG}\OR% + \equal{#2}{mpg}\OR\equal{#2}{MPG}}{% + \gdef\@MXV@mime{video/mpeg}% + }{% + \ifthenelse{\equal{#2}{smil}\OR\equal{#2}{SMIL}}{% + \gdef\@MXV@mime{application/smil}% + }{% + \ifthenelse{\equal{#2}{swf}\OR\equal{#2}{SWF}}{% + \gdef\@MXV@mime{application/x-shockwave-flash}% + }{% + \ifthenelse{\equal{#2}{prc}\OR\equal{#2}{PRC}}{% + \ifthenelse{\boolean{@MXV@iiiDfeat}}{% + \setboolean{@MXV@iiid}{true}% + \gdef\@MXV@mime{model/prc}% (unofficial) + \gdef\@MXV@iiidsubtype{PRC}% + }{% + \@MXV@neediiiD% + }% + }{% + \ifthenelse{\equal{#2}{u3d}\OR\equal{#2}{U3D}}{% + \ifthenelse{\boolean{@MXV@iiiDfeat}}{% + \setboolean{@MXV@iiid}{true}% + \gdef\@MXV@mime{model/u3d}% (unofficial) + \gdef\@MXV@iiidsubtype{U3D}% + }{% + \@MXV@neediiiD% + }% + }{% + \ifthenelse{\equal{#2}{ra}\OR\equal{#2}{RA}}{ + \gdef\@MXV@mime{audio/vnd.rn-realaudio}% + }{% + \ifthenelse{% + \equal{#2}{rv}\OR\equal{#2}{RV}\OR + \equal{#2}{rm}\OR\equal{#2}{RM}% + }{% + \gdef\@MXV@mime{application/vnd.rn-realmedia}% + }{% + \PackageError{movie15}{% + I couldn't determine MIME type of file:\MessageBreak`#1':\MessageBreak + Unknown file name extension: `#2' + }{% + When using media files of unknown type or with a\MessageBreak + non-standard file name extension, the MIME type must\MessageBreak + explicitly be specified. Try option `mimetype='! + }% + }}}}}}}}}}}}}}}}}}% +} + +%sets @MXV@issound boolean +\def\@MXV@@issound#1/#2:{% argument: \@MXV@mime. + \def\@MXV@firstarg{#1}% + \def\@MXV@audio{audio}% + \ifx\@MXV@firstarg\@MXV@audio% + \setboolean{@MXV@issound}{true}% + \fi% +} + +%draft box +\def\@MXV@draftbox#1#2#3#4{%width height depth filename + \edef\@MXV@oldfboxsep{\the\fboxsep}% + \setlength{\fboxsep}{-\fboxrule}% + \framebox[#1][l]{% + \vrule width 0pt height #2 depth #3% + \edef\@tempa{#4}% + \raisebox{\depth}[0pt][0pt]{ \ttfamily\expandafter\strip@prefix\meaning\@tempa}% + }% + \setlength{\fboxsep}{\@MXV@oldfboxsep}% +} + +\ifthenelse{\boolean{@MXV@iiiDfeat}}{% 3D related definitions and macros + \RequirePackage{fp}% needed for fixed point calculus + \newread\@MXV@@viewsfile% file handle for views file + \newboolean{@MXV@eof}% + \newcount\@MXV@viewscount%counter for number of 3D views per inclusion + \newboolean{@MXV@viewsprovided}%3d views file provided? + \newboolean{@MXV@iiidgetview}% print current 3D settings? + \newboolean{@MXV@defaultviewprovided}%default 3D view provided? + \newboolean{@MXV@resource}%3d resource file provided? + \ifpdf\else + \newcount\@MXV@rescount% number of embedded resource files + \newcount\@MXV@nodecount% number of node dicts + \newcount\@MXV@cscount% number of cross section dicts + \fi + \newcount\@MXV@iiidrepeat% play count + \newcount\@MXV@iiidoncurpage%index of 3D annot on current page + \global\@MXV@iiidoncurpage=0% + \gdef\@MXV@oldpage{0}% needed together with previous counter + + %macro for building the transformation matrix + \def\@MXV@ciiwmatrix#1 #2 #3 #4 #5 #6 #7 #8 {% + % #1,#2,#3 centre of orbit coordinates (coo) + % #4,#5,#6 centre of orbit to camera direction vector (c2c) + % #7 orbital radius (roo) + % #8 camera roll (roll) + %view vector (opposite to c2c) + \FPupn\@MXV@viewx{#4 neg}% + \FPupn\@MXV@viewy{#5 neg}% + \FPupn\@MXV@viewz{#6 neg}% + %normalize view vector + \FPupn\@MXV@modulo{\@MXV@viewx{} copy mul % + \@MXV@viewy{} copy mul + % + \@MXV@viewz{} copy mul + 2 swap root% + }% + \FPupn\@MXV@viewx{\@MXV@viewx{} \@MXV@modulo{} div}% + \FPupn\@MXV@viewy{\@MXV@viewy{} \@MXV@modulo{} div}% + \FPupn\@MXV@viewz{\@MXV@viewz{} \@MXV@modulo{} div}% + %camera roll + \FPupn\@MXV@sinroll{#8 180.0 div \FPpi{} mul sin}% + \FPupn\@MXV@cosroll{#8 180.0 div \FPpi{} mul cos}% + % + %top and bottom views + \FPupn\@MXV@leftx{-1.0}% + \FPupn\@MXV@lefty{0.0}% + \FPupn\@MXV@leftz{0.0}% + % + \FPifneg\@MXV@viewz% top view + %up-vector + \FPupn\@MXV@upx{0.0}% + \FPupn\@MXV@upy{1.0}% + \FPupn\@MXV@upz{0.0}% + \else% bottom view + %up-vector + \FPupn\@MXV@upx{0.0}% + \FPupn\@MXV@upy{-1.0}% + \FPupn\@MXV@upz{0.0}% + \fi% + \FPupn\@MXV@sumxy{\@MXV@viewx{} abs \@MXV@viewy{} abs add}% + \FPifeq\@MXV@sumxy{0}\else% other views than top and bottom + %up-vector = up_world - (up_world dot view) view + \FPupn\@MXV@upx{\@MXV@viewz{} \@MXV@viewx{} mul neg}% + \FPupn\@MXV@upy{\@MXV@viewz{} \@MXV@viewy{} mul neg}% + \FPupn\@MXV@upz{\@MXV@viewz{} \@MXV@viewz{} mul neg 1.0 add}% + %normalize up-vector + \FPupn\@MXV@modulo{\@MXV@upx{} copy mul \@MXV@upy{} copy % + mul + \@MXV@upz{} copy mul + 2 swap root}% + \FPupn\@MXV@upx{\@MXV@upx{} \@MXV@modulo{} div}% + \FPupn\@MXV@upy{\@MXV@upy{} \@MXV@modulo{} div}% + \FPupn\@MXV@upz{\@MXV@upz{} \@MXV@modulo{} div}% + %left vector = up x view + \FPupn\@MXV@leftx{\@MXV@viewz{} \@MXV@upy{} mul % + \@MXV@viewy{} \@MXV@upz{} mul sub}% + \FPupn\@MXV@lefty{\@MXV@viewx{} \@MXV@upz{} mul % + \@MXV@viewz{} \@MXV@upx{} mul sub}% + \FPupn\@MXV@leftz{\@MXV@viewy{} \@MXV@upx{} mul % + \@MXV@viewx{} \@MXV@upy{} mul sub}% + %normalize left vector + \FPupn\@MXV@modulo{\@MXV@leftx{} copy mul \@MXV@lefty{} % + copy mul + \@MXV@leftz{} copy mul + 2 swap root}% + \FPupn\@MXV@leftx{\@MXV@leftx{} \@MXV@modulo{} div}% + \FPupn\@MXV@lefty{\@MXV@lefty{} \@MXV@modulo{} div}% + \FPupn\@MXV@leftz{\@MXV@leftz{} \@MXV@modulo{} div}% + \fi% + %apply camera roll + \FPupn\@MXV@leftxprime{\@MXV@leftx{} \@MXV@cosroll{} mul \@MXV@upx{} \@MXV@sinroll{} mul +}% + \FPupn\@MXV@leftyprime{\@MXV@lefty{} \@MXV@cosroll{} mul \@MXV@upy{} \@MXV@sinroll{} mul +}% + \FPupn\@MXV@leftzprime{\@MXV@leftz{} \@MXV@cosroll{} mul \@MXV@upz{} \@MXV@sinroll{} mul +}% + \FPupn\@MXV@upxprime{\@MXV@upx{} \@MXV@cosroll{} mul \@MXV@leftx{} \@MXV@sinroll{} mul sub}% + \FPupn\@MXV@upyprime{\@MXV@upy{} \@MXV@cosroll{} mul \@MXV@lefty{} \@MXV@sinroll{} mul sub}% + \FPupn\@MXV@upzprime{\@MXV@upz{} \@MXV@cosroll{} mul \@MXV@leftz{} \@MXV@sinroll{} mul sub}% + \FPupn\@MXV@leftx{\@MXV@leftxprime}% + \FPupn\@MXV@lefty{\@MXV@leftyprime}% + \FPupn\@MXV@leftz{\@MXV@leftzprime}% + \FPupn\@MXV@upx{\@MXV@upxprime}% + \FPupn\@MXV@upy{\@MXV@upyprime}% + \FPupn\@MXV@upz{\@MXV@upzprime}% + %translation vector + \FPupn\@MXV@roo{#7 abs}% + \FPifeq\@MXV@roo{0}\FPupn\@MXV@roo{0.0000001}\fi% + \FPupn\@MXV@transx{#1 \@MXV@roo{} \@MXV@viewx{} mul sub}% + \FPupn\@MXV@transy{#2 \@MXV@roo{} \@MXV@viewy{} mul sub}% + \FPupn\@MXV@transz{#3 \@MXV@roo{} \@MXV@viewz{} mul sub}% + %rotation matrix + \xdef\@MXV@matrix{\@MXV@leftx\space\@MXV@lefty\space\@MXV@leftz\space% + \@MXV@upx\space\@MXV@upy\space\@MXV@upz\space% + \@MXV@viewx\space\@MXV@viewy\space\@MXV@viewz}% + %transformation matrix + \xdef\@MXV@matrix{% + \@MXV@matrix\space\@MXV@transx\space\@MXV@transy\space\@MXV@transz% + }% + } + + %macro for parsing one line of 3D views file (old format) + \newcommand{\@MXV@parseline}[6][]{% + \pdfstringdef\@MXV@xname{#1}% name of the view (optional) + \ifthenelse{\equal{#2}{}}{% + \xdef\@MXV@coo{0 0 0}% + }{% + \xdef\@MXV@coo{#2}% + }% + \ifthenelse{\equal{#3}{}}{% + \xdef\@MXV@ctoc{0 -1 0}% + }{% + \xdef\@MXV@ctoc{#3}% + }% + \ifthenelse{\equal{#4}{}}{% + \xdef\@MXV@roo{0}% + }{% + \xdef\@MXV@roo{#4}% + }% + \ifthenelse{\equal{#5}{}}{% + \xdef\@MXV@roll{0}% + }{% + \xdef\@MXV@roll{#5}% + }% + \ifthenelse{\equal{#6}{}}{% + \xdef\@MXV@aac{30}% + }{% + \xdef\@MXV@aac{#6}% + }% + } + %for parsing lines of views file (new format) + \define@key{MXV@view}{VIEW}[]{% + \ifnum\@MXV@cursection<\z@\else% + \PackageError{movie15}{% + File \@MXV@viewsfileii, line \the\@MXV@inputlineno: % + A VIEW section cannot be nested into another section% + }{}% + \fi% + \def\@MXV@cursection{0}% + \pdfstringdef\@MXV@xname{#1}% name of the view (optional) + %default camera settings + \gdef\@MXV@coo{0 0 0}% + \gdef\@MXV@ctoc{0 -1 0}% + \gdef\@MXV@roo{0}% + \gdef\@MXV@roll{0}% + \gdef\@MXV@aac{30}% + %default background, lights, render mode + \xdef\@MXV@background{/BG <>}% + \xdef\@MXV@lights{/LS <>}% + \gdef\@MXV@render{/RM <>}% + %initialise array of node dicts + \gdef\@MXV@naarray{}% + \ifpdf\else\global\@MXV@nodecount=\z@\fi% + %initialise array of crosssection dicts + \gdef\@MXV@saarray{}% + \ifpdf\else\global\@MXV@cscount=\z@\fi% + } + \define@key{MXV@view}{COO}{% + \ifnum\@MXV@cursection=\z@\else% + \PackageError{movie15}{% + File \@MXV@viewsfileii, line \the\@MXV@inputlineno: % + COO entry not allowed here; must go into a VIEW section% + }{}% + \fi% + \xdef\@MXV@coo{#1}% + } + \define@key{MXV@view}{C2C}{% + \ifnum\@MXV@cursection=\z@\else% + \PackageError{movie15}{% + File \@MXV@viewsfileii, line \the\@MXV@inputlineno: % + C2C entry not allowed here; must go into a VIEW section% + }{}% + \fi% + \xdef\@MXV@ctoc{#1}% + } + \define@key{MXV@view}{ROO}{% + \ifnum\@MXV@cursection=\z@\else% + \PackageError{movie15}{% + File \@MXV@viewsfileii, line \the\@MXV@inputlineno: % + ROO entry not allowed here; must go into a VIEW section% + }{}% + \fi% + \xdef\@MXV@roo{#1}% + } + \define@key{MXV@view}{AAC}{% + \ifnum\@MXV@cursection=\z@\else% + \PackageError{movie15}{% + File \@MXV@viewsfileii, line \the\@MXV@inputlineno: % + AAC entry not allowed here; must go into a VIEW section% + }{}% + \fi% + \xdef\@MXV@aac{#1}% + } + \define@key{MXV@view}{ROLL}{% + \ifnum\@MXV@cursection=\z@\else% + \PackageError{movie15}{% + File \@MXV@viewsfileii, line \the\@MXV@inputlineno: % + ROLL entry not allowed here; must go into a VIEW section% + }{}% + \fi% + \xdef\@MXV@roll{#1}% + } + \define@key{MXV@view}{BGCOLOR}{% + \ifnum\@MXV@cursection=\z@\else% + \PackageError{movie15}{% + File \@MXV@viewsfileii, line \the\@MXV@inputlineno: % + BGCOLOR entry not allowed here; must go into a VIEW section% + }{}% + \fi% + \def\@MXV@background{/BG<>}% + } + \define@key{MXV@view}{LIGHTS}{% + \ifnum\@MXV@cursection=\z@\else% + \PackageError{movie15}{% + File \@MXV@viewsfileii, line \the\@MXV@inputlineno: % + LIGHTS entry not allowed here; must go into a VIEW section% + }{}% + \fi% + \def\@MXV@lights{/LS <>}% + } + \define@key{MXV@view}{RENDERMODE}{% + \ifnum\@MXV@cursection=\z@ + \def\@MXV@render{/RM <>}% + \else% + \ifnum\@MXV@cursection=\@ne + \def\@MXV@nrender{/RM <>}% + \else% + \PackageError{movie15}{% + File \@MXV@viewsfileii, line \the\@MXV@inputlineno: % + RENDERMODE entry not allowed here; must go into either a VIEW % + or a PART section% + }{}% + \fi% + \fi% + } + \define@key{MXV@view}{PART}[]{% + \ifnum\@MXV@cursection=\z@\else% + \PackageError{movie15}{% + File \@MXV@viewsfileii, line \the\@MXV@inputlineno: % + PART not allowed here; must be a sub-section of a VIEW section% + }{}% + \fi% + \ifthenelse{\equal{#1}{}}{% + \PackageError{movie15}{% + File \@MXV@viewsfileii, line \the\@MXV@inputlineno: % + You must provide a valid PART name (PART=), as shown % + in the model tree of the 3D object (go to `View'->`Navigation % + Panels'->`Model Tree' in Adobe Reader)% + }{}% + }{}% + \def\@MXV@cursection{1}% + \pdfstringdef\@MXV@partname{#1}% name of the part + \gdef\@MXV@nopacity{}% + \gdef\@MXV@nvisibility{}% + \gdef\@MXV@nrender{}% + \gdef\@MXV@ntransform{}% + } + \define@key{MXV@view}{CROSSSECT}[]{% + \ifnum\@MXV@cursection=\z@\else% + \PackageError{movie15}{% + File \@MXV@viewsfileii, line \the\@MXV@inputlineno: % + CROSSSECT not allowed here; must be a sub-section of a VIEW section% + }{}% + \fi% + \ifthenelse{\equal{#1}{}}{}{% + \PackageWarning{movie15}{% + File \@MXV@viewsfileii, line \the\@MXV@inputlineno: % + CROSSECT does not take a value% + }% + }% + \def\@MXV@cursection{2}% + \gdef\@MXV@cscenter{0 0 0}% + \gdef\@MXV@csorient{null 0 0}% + } + \define@key{MXV@view}{OPACITY}{% + \ifnum\@MXV@cursection=\@ne\else% + \PackageError{movie15}{% + File \@MXV@viewsfileii, line \the\@MXV@inputlineno: % + OPACITY entry not allowed here; must go into a PART section% + }{}% + \fi% + \gdef\@MXV@nopacity{/O #1}% + } + \define@key{MXV@view}{VISIBLE}{% + \ifnum\@MXV@cursection=\@ne\else% + \PackageError{movie15}{% + File \@MXV@viewsfileii, line \the\@MXV@inputlineno: % + VISIBLE entry not allowed here; must go into a PART section% + }{}% + \fi% + \gdef\@MXV@nvisibility{/V #1}% + } + \define@key{MXV@view}{MATRIX}{% + \ifnum\@MXV@cursection=\@ne\else% + \PackageError{movie15}{% + File \@MXV@viewsfileii, line \the\@MXV@inputlineno: % + MATRIX entry not allowed here; must go into a PART section% + }{}% + \fi% + \gdef\@MXV@ntransform{/M [#1]}% + } + \define@key{MXV@view}{CENTER}{% + \ifnum\@MXV@cursection=2\relax\else% + \PackageError{movie15}{% + File \@MXV@viewsfileii, line \the\@MXV@inputlineno: % + CENTER entry not allowed here; must go into a CROSSECT section% + }{}% + \fi% + \gdef\@MXV@cscenter{#1}% + } + \define@key{MXV@view}{ORIENTATION}{% + \ifnum\@MXV@cursection=2\relax\else% + \PackageError{movie15}{% + File \@MXV@viewsfileii, line \the\@MXV@inputlineno: % + ORIENT entry not allowed here; must go into a CROSSECT section% + }{}% + \fi% + \gdef\@MXV@csorient{#1}% + } + \define@key{MXV@view}{END}[]{% + \ifcase\@MXV@cursection% + %END VIEW + \edef\@MXV@args{% + \@MXV@coo\space\@MXV@ctoc\space\@MXV@roo\space\@MXV@roll\space}% + \expandafter\@MXV@ciiwmatrix\@MXV@args% build C2W matrix + \global\advance\@MXV@viewscount by \@ne% + \ifthenelse{\equal{\@MXV@xname}{}}{% default view name + \pdfstringdef\@MXV@xname{View \the\@MXV@viewscount}% + }{}% + \ifthenelse{\equal{\@MXV@naarray}{}}{}{% + \gdef\@MXV@naentry{/NR true/NA [\@MXV@naarray]}% + }% + \ifthenelse{\equal{\@MXV@saarray}{}}{}{% + \gdef\@MXV@saentry{/SA [\@MXV@saarray]}% + }% + \@MXV@viewobj% create pdf object of 3D view + %append current view obj ref to VA array + \xdef\@MXV@varray{\@MXV@varray\space\@MXV@@viewobj}% + \global\@MXV@viewsprovidedtrue% + \def\@MXV@cursection{-1}% + \or% + %END PART + \ifpdf\else\global\advance\@MXV@nodecount by \@ne\fi% + \@MXV@nodeobj% create pdf object of 3D node dict + %append it to node array + \xdef\@MXV@naarray{\@MXV@naarray\space\@MXV@@nodeobj}% + \def\@MXV@cursection{0}% + \or% + %END CROSSSECT + \ifpdf\else\global\advance\@MXV@cscount by \@ne\fi% + \@MXV@csobj% create pdf object of 3D cross section dict + %append it to cross section array + \xdef\@MXV@saarray{\@MXV@saarray\space\@MXV@@csobj}% + \def\@MXV@cursection{0}% + \else% + \PackageError{movie15}{% + File \@MXV@viewsfileii, line \the\@MXV@inputlineno: % + There is nothing to be ENDed here% + }{}% + \fi% + }% + + %macro for generating an array of 3D views (varray) + \def\@MXV@procinputline#1{\setkeys{MXV@view}{#1}} + \newcount\@MXV@inputlineno + \def\@MXV@buildva{% + \global\@MXV@viewscount=0% + \xdef\@MXV@varray{}% empty varray + % + %default view (one of the command options 3Dcoo, 3Dc2c, etc. given) + \edef\@MXV@args{% + \@MXV@coo\space\@MXV@ctoc\space\@MXV@roo\space\@MXV@roll\space}% + \expandafter\@MXV@ciiwmatrix\@MXV@args% build C2W matrix + \pdfstringdef\@MXV@xname{Default}% + \if@MXV@defaultviewprovided% + \@MXV@viewobj% create pdf object of 3D view + \edef\@MXV@defaultview{/3DV \@MXV@@viewobj}% + \fi% + % + %read out 3D views file + \IfFileExists{\@MXV@viewsfile}{% + \edef\@MXV@endlinechar{\the\endlinechar}% + \endlinechar=-1% suppress trailing space at input line end + \openin\@MXV@@viewsfile=\@MXV@viewsfile% + \loop% + \read\@MXV@@viewsfile to \@MXV@inputline% + \if\@MXV@inputline\relax\else% + \expandafter\@MXV@parseline\@MXV@inputline% + \edef\@MXV@args{\@MXV@coo\space\@MXV@ctoc\space\@MXV@roo\space\@MXV@roll\space}% + \expandafter\@MXV@ciiwmatrix\@MXV@args% build C2W matrix + \global\advance\@MXV@viewscount by 1% + \ifthenelse{\equal{\@MXV@xname}{}}{% + \pdfstringdef\@MXV@xname{View \the\@MXV@viewscount}% + }{}% + \@MXV@viewobj% create pdf object of 3D view + %append current view obj ref to VA array + \xdef\@MXV@varray{\@MXV@varray\space\@MXV@@viewobj}% + \setboolean{@MXV@viewsprovided}{true}% + \repeat% + \closein\@MXV@@viewsfile% + \endlinechar=\@MXV@endlinechar% reset endlinechar + }{}% + %read out 3D views file (new version) + \def\@MXV@cursection{-1}% views file is devided in sections + \IfFileExists{\@MXV@viewsfileii}{% + \begingroup% + \endlinechar=-1% suppress trailing space at input line end +% \catcode`\#=14\relax% make `#' a comment char +% \catcode`\%=12\relax% make `%' an ordinary char + \@MXV@inputlineno=\z@% + \openin\@MXV@@viewsfile=\@MXV@viewsfileii% + \read\@MXV@@viewsfile to \@MXV@inputline% + \ifeof\@MXV@@viewsfile\setboolean{@MXV@eof}{true}\else% + \setboolean{@MXV@eof}{false}\fi% + \whiledo{\NOT\boolean{@MXV@eof}}{% + \advance\@MXV@inputlineno by \@ne% + %process input line + \edef\@MXV@@inputline{{\@MXV@inputline}}% + \expandafter\@MXV@procinputline\@MXV@@inputline% + \read\@MXV@@viewsfile to \@MXV@inputline% + \ifeof\@MXV@@viewsfile% + \setboolean{@MXV@eof}{true}% + \else% + \setboolean{@MXV@eof}{false}% + \fi% + }% + \closein\@MXV@@viewsfile% + \endgroup% + }{}% + % + %make the first view in the VA array the default view, if no default one has + %explicitly been provided, but if the VA array itself is empty too (no + %additional views provided) use our fallback view (c2c=0 -1 0) as default + \ifthenelse{\NOT\boolean{@MXV@defaultviewprovided}% + \AND\boolean{@MXV@viewsprovided}}{% + \xdef\@MXV@defaultview{/3DV /F}% + }{}% + \ifthenelse{\NOT\boolean{@MXV@defaultviewprovided}% + \AND\NOT\boolean{@MXV@viewsprovided}}{% + \@MXV@viewobj% create pdf object of 3D view + \edef\@MXV@defaultview{/3DV \@MXV@@viewobj}% + }{}% + } + + %following macros, including the 3D inclusion macro have driver specific + %implementations + \ifpdf% + %pdfLaTeX versions + %macro for creating 3D view object + \def\@MXV@viewobj{% + %projection dict + \pdfobj {<>}% + \pdfrefobj\pdflastobj% + % + \pdfobj {<<% + /MS/M% define the view as C2W matrix + /CO \@MXV@roo% orbital radius + /P \the\pdflastobj\space 0 R% + /C2W [\@MXV@matrix]% + /XN(\@MXV@xname)% name of the view appearing in the drop down list + \@MXV@background% + \@MXV@lights% + \@MXV@render% + \@MXV@naentry% node dictionaries + \@MXV@saentry% node dictionaries + >>}\pdfrefobj\pdflastobj% + \xdef\@MXV@@viewobj{\the\pdflastobj\space 0 R}% + }% + \def\@MXV@nodeobj{% + \pdfobj {<<% + /Type/3DNode% + /N (\@MXV@partname)% + \@MXV@nopacity\@MXV@nvisibility\@MXV@ntransform\@MXV@nrender% + >>}\pdfrefobj\pdflastobj% + \xdef\@MXV@@nodeobj{\the\pdflastobj\space 0 R}% + }% + \def\@MXV@csobj{% + \pdfobj {<<% + /Type/3DCrossSection% + /C [\@MXV@cscenter]% + /O [\@MXV@csorient]% + >>}\pdfrefobj\pdflastobj% + \xdef\@MXV@@csobj{\the\pdflastobj\space 0 R}% + }% + %macro for creating resource objects from 3D and image files, to be used + %in 3D JavaScript + \def\@MXV@addresource#1{% + %determine file type + \filename@parse{#1}% + \ifthenelse{% + \equal{\filename@ext}{u3d}\OR% + \equal{\filename@ext}{U3D}% + }{% + \def\@MXV@restype{U3D}% + }{% + \def\@MXV@restype{image}% + }% + \ifthenelse{\equal{\@MXV@restype}{image}}{% + %embed the same image file only once + \ifthenelse{\equal{\@MXV@getlabelvalue{\pdfmdfivesum file {#1}}}{undefined}}{% + \immediate\pdfximage {#1}% + \xdef\@MXV@resourcetree{% build name tree for embedded resources + \@MXV@resourcetree\space (#1) \the\pdflastximage\space 0 R% + }% + \@MXV@newlabel{\pdfmdfivesum file {#1}}{\the\pdflastximage}% + }{% + \xdef\@MXV@resourcetree{% + \@MXV@resourcetree\space (#1) \@MXV@getlabelvalue{\pdfmdfivesum file {#1}}\space 0 R% + }% + }% + }{% + %embed the same 3D file only once + \ifthenelse{\equal{\@MXV@getlabelvalue{\pdfmdfivesum file {#1}}}{undefined}}{% + \pdfobj stream % + attr {% + /Subtype/\@MXV@restype% + }% + file {#1}% + \pdfrefobj\pdflastobj% + \xdef\@MXV@resourcetree{% + \@MXV@resourcetree\space (#1) \the\pdflastobj\space 0 R% + }% + \@MXV@newlabel{\pdfmdfivesum file {#1}}{\the\pdflastobj}% + }{% + \xdef\@MXV@resourcetree{% + \@MXV@resourcetree\space (#1) \@MXV@getlabelvalue{\pdfmdfivesum file {#1}}\space 0 R% + }% + }% + }% + } + + %3D inclusion macro + \newcommand{\@MXV@includeiiid}[5][]{% + %insert box or poster + \@MXV@box{#2}{#3}{#4}% + % + \if@MXV@externalviewer\else% + \setkeys{MXV@iiid}{#1}%process deferred options + \ifnum\@MXV@iiidrepeat=0\else% + \edef\@MXV@animstyle{% animation style dict + /AN <<% + \@MXV@iiidpalindrome\@MXV@iiidrate/PC \the\@MXV@iiidrepeat% + >>% + }% + \fi% + %java script file, stream object + \IfFileExists{\@MXV@jscriptiiidfile}{% + \pdfobj stream file {\@MXV@jscriptiiidfile}% + \pdfrefobj\pdflastobj% + \xdef\@MXV@jscriptiiid{/OnInstantiate \the\pdflastobj\space 0 R}% + }{\xdef\@MXV@jscriptiiid{}}% + % + %build the array of 3D views + \@MXV@buildva% + \fi% + % + %3D stream object + \if@MXV@inline% + \ifthenelse{% + \NOT\boolean{@MXV@presentation}\OR% + \equal{\@MXV@getlabelvalue{\@MXV@label.3dstream}}{undefined}% + }{% + \pdfobj stream% + attr {% + /Subtype/\@MXV@iiidsubtype% + \if@MXV@externalviewer\else% + /VA [\@MXV@varray]% + /DV/F% use first entry in VA as default view + \@MXV@animstyle% + \@MXV@jscriptiiid% + \if@MXV@resource% + /Resources <<% + /Names [\@MXV@resourcetree]% + >>% + \fi% + \fi% + }% + file {#5}% + \pdfrefobj\pdflastobj% + \edef\@MXV@iiidstream{\the\pdflastobj}% + \if@MXV@presentation% + \@MXV@newlabel{\@MXV@label.3dstream}{\@MXV@iiidstream}% + \fi% + }{% + \edef\@MXV@iiidstream{\@MXV@getlabelvalue{\@MXV@label.3dstream}}% + }% + \fi% + % + \makebox[0pt][r]{\makebox[#2][l]{% + %insert FileAttachment annotation + \ifthenelse{\boolean{@MXV@inline}\AND\boolean{@MXV@externalviewer}% +% since Reader 7.0.7, we cannot place a file attachment annot behind +% the 3D annot :-( +% \OR\boolean{@MXV@attachment} + }{% + \pdfannot width #2 height #3 depth #4 {% + /Subtype /FileAttachment% + /F 0% + /T (\@MXV@filename)% + /Contents (3D Object (\@MXV@mime))% + \if@MXV@externalviewer% + /Name/Paperclip% + /C [1 1 1]% + \else% + /AP <>/R<<>>/D<<>>>>% + \fi% + /FS <<% + /F(#5)% + /Type/Filespec% + /EF << /F \@MXV@iiidstream\space 0 R >>% + >>% + }% + }{% + \if@MXV@url% + %insert Link annotation, if 3D file is a URL + \pdfannot width #2 height #3 depth #4 {% + /Subtype /Link% + /F 0% + \if@MXV@externalviewer% + \@MXV@urlattr% + \else% + /H /N% + /Border [0 0 0]% + \fi% + /A <>% + /Contents (3D Object (\@MXV@mime))% + }% + \else% + %else insert Launch action for local external 3D file + \if@MXV@inline\else% + \pdfannot width #2 height #3 depth #4 {% + /Subtype /Link% + /F 0% + \if@MXV@externalviewer% + \@MXV@runattr% + \else% + /H /N% + /Border [0 0 0]% + \fi% + /A <<% + /F (#5)% + /S /Launch% + >>% + /Contents (3D Object (\@MXV@mime))% + }% + \fi% + \fi% + }% + % + \if@MXV@externalviewer\else% + %appearance dict dummy, to be shared by all 3D annots + \ifthenelse{\isundefined{\@MXV@apdict}}{% + \pdfobj stream attr {/BBox [0 0 0.001 0.001]} {}\pdfrefobj\pdflastobj% + \xdef\@MXV@apdict{/AP << /N \the\pdflastobj\space 0 R >>}% + }{}% + %3D reference dict + \if@MXV@presentation% + \ifthenelse{% + \equal{\@MXV@getlabelvalue{\@MXV@label.3dref}}{undefined}% + }{% + \pdfobj {<<% + /Type/3DRef% + /3DD \@MXV@iiidstream\space 0 R% 3D stream object + >>}\pdfrefobj\pdflastobj% + \edef\@MXV@iiidstreamorref{\the\pdflastobj}% + \@MXV@newlabel{\@MXV@label.3dref}{\the\pdflastobj}% + }{% + \edef\@MXV@iiidstreamorref{\@MXV@getlabelvalue{\@MXV@label.3dref}}% + }% + \else% + \edef\@MXV@iiidstreamorref{\@MXV@iiidstream}% + \fi% + %annotation object of subtype `3D' + \pdfannot width #2 height #3 depth #4 {% + /Subtype/3D% + /F 4% we cannot put F 5 here; bug in Reader; 3D annot would be + /T (\@MXV@filename)% disabled even if plugin were available + /Contents (3D Object (\@MXV@mime))% + \ifx\@MXV@@label\@empty\else% + /NM (\@MXV@@label)% + \fi% + /P \@MXV@pdfpageref{@MXV@annot\the\@MXV@includes.page} 0 R% + \@MXV@apdict% /AP <>/R<<>>/D<<>>>> doesn't work here + \@MXV@defaultview% + \@MXV@iiidia% + /3DD \@MXV@iiidstreamorref\space 0 R% 3D stream or reference object + /3DA << \@MXV@activation\@MXV@deactivation\@MXV@iiidtoolb >>% + }% + %label for later annot obj number determination, to be used in + %movieref's + \ifx\@MXV@@label\@empty\else% + \@MXV@labeltoaux{@MXV@\@MXV@@label.annot}{\the\pdflastannot}% + \@MXV@newlabel{@MXV@\@MXV@@label.annot}{\the\pdflastannot}% + \fi% + \fi}}% + }% + \else% + %dvips versions + %macro for creating 3D view object and associated projection dict + \def\@MXV@viewobj{% + %projection dict + \pdfmark{% + pdfmark=/OBJ,% + Raw={% + /_objdef {pdict\the\@MXV@includes_\the\@MXV@viewscount}% + /type/dict% + }% + }% + \pdfmark{% + pdfmark=/PUT,% + Raw={% + {pdict\the\@MXV@includes_\the\@MXV@viewscount} <<% + /Subtype/P/FOV \@MXV@aac/PS/Min% + >>% + }% + }% + % + \pdfmark{% + pdfmark=/OBJ,% + Raw={% + /type/dict% + /_objdef {viewobj\the\@MXV@includes_\the\@MXV@viewscount}% + }% + }% + \pdfmark{% + pdfmark=/PUT,% + Raw={% + {viewobj\the\@MXV@includes_\the\@MXV@viewscount} <<% + /MS/M% + /CO \@MXV@roo% + /P {pdict\the\@MXV@includes_\the\@MXV@viewscount}% + /C2W[\@MXV@matrix]% + /XN(\@MXV@xname)% + \@MXV@background% + \@MXV@lights% + \@MXV@render% + \@MXV@naentry% + \@MXV@saentry% + >>% + }% + }% + \xdef\@MXV@@viewobj{{viewobj\the\@MXV@includes_\the\@MXV@viewscount}}% + }% + %3D node object + \def\@MXV@nodeobj{% + \pdfmark{% + pdfmark=/OBJ,% + Raw={% + /type/dict% + /_objdef {nodeobj\the\@MXV@includes_\the\@MXV@viewscount_% + \the\@MXV@nodecount}% + }% + }% + \pdfmark{% + pdfmark=/PUT,% + Raw={% + {nodeobj\the\@MXV@includes_\the\@MXV@viewscount_\the\@MXV@nodecount} + <<% + /Type/3DNode% + /N (\@MXV@partname)% + \@MXV@nopacity\@MXV@nvisibility\@MXV@ntransform% + >>% + }% + }% + \xdef\@MXV@@nodeobj{% + {nodeobj\the\@MXV@includes_\the\@MXV@viewscount_\the\@MXV@nodecount}}% + }% + %3D cross section object + \def\@MXV@csobj{% + \pdfmark{% + pdfmark=/OBJ,% + Raw={% + /type/dict% + /_objdef {csobj\the\@MXV@includes_\the\@MXV@viewscount_% + \the\@MXV@cscount}% + }% + }% + \pdfmark{% + pdfmark=/PUT,% + Raw={% + {csobj\the\@MXV@includes_\the\@MXV@viewscount_\the\@MXV@cscount} + <<% + /Type/3DCrossSection% + /C [\@MXV@cscenter]% + /O [\@MXV@csorient]% + >>% + }% + }% + \xdef\@MXV@@csobj{% + {csobj\the\@MXV@includes_\the\@MXV@viewscount_\the\@MXV@cscount}}% + }% + % + %macro for creating resource objects from 3D and image files + \def\@MXV@addresource#1{% + %determine file type + \filename@parse{#1}% + \ifthenelse{% + \equal{\filename@ext}{u3d}\OR% + \equal{\filename@ext}{U3D}% + }{% + \def\@MXV@restype{U3D}% + }{% + \def\@MXV@restype{image}% + }% + \ifthenelse{\equal{\@MXV@restype}{image}}{% + %embed the same image file only once + \ifthenelse{\equal{\@MXV@getlabelvalue{\pdfmdfivesum file {#1}}}{undefined}}{% + %increment counter of embedded resource files + \global\advance\@MXV@rescount by 1% + %create Image XObject from next raster image + \special{ps:% read image resource from file + [ /_objdef {resource\the\@MXV@rescount} /NI pdfmark + save gsave + { + /showpage {} def + /setpagedevice /pop load def + newpath clip + (#1) run + } ?pdfmark + 0 0 1 [1 0 0 1 0 0] {} image %empty dummy, in case #1 is not + grestore restore %a valid image file + }% + \xdef\@MXV@resourcetree{% build name tree for embedded resources + \@MXV@resourcetree\space (#1) {resource\the\@MXV@rescount}% + }% + \@MXV@newlabel{\pdfmdfivesum file {#1}}{resource\the\@MXV@rescount}% + }{% + \xdef\@MXV@resourcetree{% + \@MXV@resourcetree\space (#1) {\@MXV@getlabelvalue{\pdfmdfivesum file {#1}}}% + }% + }% + }{% + %embed the same 3D file only once + \ifthenelse{\equal{\@MXV@getlabelvalue{\pdfmdfivesum file {#1}}}{undefined}}{% + \global\advance\@MXV@rescount by 1% + \special{ps: + [ /_objdef {resource\the\@MXV@rescount} /type/stream /OBJ pdfmark + [ {resource\the\@MXV@rescount} <<% + /Subtype/\@MXV@restype% + >> /PUT pdfmark% + [ {resource\the\@MXV@rescount} (#1) (r) file /PUT pdfmark + }% + \xdef\@MXV@resourcetree{% + \@MXV@resourcetree\space (#1) {resource\the\@MXV@rescount}% + }% + \@MXV@newlabel{\pdfmdfivesum file {#1}}{resource\the\@MXV@rescount}% + }{% + \xdef\@MXV@resourcetree{% + \@MXV@resourcetree\space (#1) {\@MXV@getlabelvalue{\pdfmdfivesum file {#1}}}% + }% + }% + }% + } + % + %3D inclusion macro + \newcommand{\@MXV@includeiiid}[5][]{% + % + \if@MXV@externalviewer\else% + \setkeys{MXV@iiid}{#1}%process deferred options + \ifnum\@MXV@iiidrepeat=0\else% + \edef\@MXV@animstyle{% animation style dict + /AN <<% + \@MXV@iiidpalindrome\@MXV@iiidrate/PC \the\@MXV@iiidrepeat% + >>% + }% + \fi% + %java script file, stream object + \IfFileExists{\@MXV@jscriptiiidfile}{% + \pdfmark{% + pdfmark=/OBJ,% + Raw={% + /_objdef {jscriptiiid\the\@MXV@includes}% + /type/stream% + }% + }% + \pdfmark{% + pdfmark=/PUT,% + Raw={% + {jscriptiiid\the\@MXV@includes}% + (\@MXV@jscriptiiidfile) (r) file% + }% + }% + \xdef\@MXV@jscriptiiid{% + /OnInstantiate {jscriptiiid\the\@MXV@includes}% + }% + }{\def\@MXV@jscriptiiid{}}% + % + %build the array of 3D views + \@MXV@buildva% + \fi% + % + %3D stream object + \if@MXV@inline% + \ifthenelse{% + \NOT\boolean{@MXV@presentation}\OR% + \equal{\@MXV@getlabelvalue{\@MXV@label.3dstream}}{undefined}% + }{% + \pdfmark{% + pdfmark=/OBJ,% + Raw={% + /_objdef {iiiDfile\the\@MXV@includes}% + /type/stream% + }% + }% + \pdfmark{% + pdfmark=/PUT,% + Raw={% + {iiiDfile\the\@MXV@includes} <<% + /Subtype/\@MXV@iiidsubtype% + \if@MXV@externalviewer\else% + /VA [\@MXV@varray]% + /DV/F% use first entry in VA as default view + \@MXV@animstyle% + \if@MXV@resource% + /Resources <<% + /Names [\@MXV@resourcetree]% + >>% + \fi% + \@MXV@jscriptiiid% + \fi% + >>% + }% + }% + \pdfmark{% + pdfmark=/PUT,% + Raw={% + {iiiDfile\the\@MXV@includes}% + (#5) (r) file% + }% + }% + \edef\@MXV@iiidstream{iiiDfile\the\@MXV@includes}% + \if@MXV@presentation% + \@MXV@newlabel{\@MXV@label.3dstream}{\@MXV@iiidstream}% + \fi% + }{% + \edef\@MXV@iiidstream{\@MXV@getlabelvalue{\@MXV@label.3dstream}}% + }% + \fi% + % + %insert FileAttachment annotation + \ifthenelse{\boolean{@MXV@inline}\AND\boolean{@MXV@externalviewer}% +% \OR\boolean{@MXV@attachment} + }{% + \makebox[0pt][l]{% + \pdfmark[\phantom{\@MXV@box{#2}{#3}{#4}}]{% + pdfmark=/ANN,% + Subtype=/FileAttachment,% + Raw={% + /F 0% + /T (\@MXV@filename)% + /Contents (3D Object (\@MXV@mime))% + \if@MXV@externalviewer% + /Name/Paperclip% + /C [1 1 1]% + \else% + /AP <>/R<<>>/D<<>>>>% + \fi% + /FS <<% + /F(#5)% + /Type/Filespec% + /EF <>% + >>% + }% + }% + }% + }{% + \if@MXV@url% + %insert Link annotation, if 3D file is a URL + \makebox[0pt][l]{% + \pdfmark[\phantom{\@MXV@box{#2}{#3}{#4}}]{% + pdfmark=/ANN,% + Subtype=/Link,% + Raw={% + /F 0% + \if@MXV@externalviewer% + /C [\@urlbordercolor]% + /H \@pdfhighlight% + \else% + /H /N% + /Border [0 0 0]% + \fi% + /Action <>% + /Contents (3D Object (\@MXV@mime))% + }% + }% + }% + \else% + %else insert Launch action for local external 3D file + \if@MXV@inline\else% + \makebox[0pt][l]{% + \pdfmark[\phantom{\@MXV@box{#2}{#3}{#4}}]{% + pdfmark=/ANN,% + Subtype=/Link,% + Raw={% + /F 0% + \if@MXV@externalviewer% + /C [\@urlbordercolor]% + /H \@pdfhighlight% + \else% + /H /N% + /Border [0 0 0]% + \fi% + /Action <<% + /F (#5)% + /S /Launch% + >>% + /Contents (3D Object (\@MXV@mime))% + }% + }% + }% + \fi% + \fi% + }% + \if@MXV@externalviewer% + \phantom{\@MXV@box{#2}{#3}{#4}}% + \else% + %appearance dict dummy, to be shared by all 3D annots + \ifthenelse{\isundefined{\@MXV@apdict}}{% + \pdfmark{% + pdfmark=/OBJ,% + Raw={% + /_objdef {apdict}% + /type/stream% + }% + }% + \pdfmark{% + pdfmark=/PUT,% + Raw={% + {apdict}% + ()% + }% + }% + \pdfmark{% + pdfmark=/PUT,% + Raw={% + {apdict} + <> + }% + }% + \xdef\@MXV@apdict{/AP << /N {apdict}>>}% + }{}% + %3D reference dict + \if@MXV@presentation% + \ifthenelse{% + \equal{\@MXV@getlabelvalue{\@MXV@label.3dref}}{undefined}% + }{% + \pdfmark{% + pdfmark=/OBJ,% + Raw={% + /_objdef {iiiDref\the\@MXV@includes}% + /type/dict% + }% + }% + \pdfmark{% + pdfmark=/PUT,% + Raw={% + {iiiDref\the\@MXV@includes} <<% + /Type/3DRef% + /3DD {\@MXV@iiidstream}% 3D stream object + >>% + }% + }% + \edef\@MXV@iiidstreamorref{iiiDref\the\@MXV@includes}% + \@MXV@newlabel{\@MXV@label.3dref}{\@MXV@iiidstreamorref}% + }{% + \edef\@MXV@iiidstreamorref{\@MXV@getlabelvalue{\@MXV@label.3dref}}% + }% + \else% + \edef\@MXV@iiidstreamorref{\@MXV@iiidstream}% + \fi% + %annotation object of subtype `3D' + \pdfmark[\phantom{\@MXV@box{#2}{#3}{#4}}]{% + pdfmark=/ANN,% + Subtype=/3D,% + Raw={% + /_objdef {3Dannot\the\@MXV@includes}% + /F 4% + /T (\@MXV@filename)% + \ifx\@MXV@@label\@empty\else% + /NM (\@MXV@@label)% + \fi% + /Contents (3D Object (\@MXV@mime))% + /P {ThisPage}% + \@MXV@apdict% /AP <>/R<<>>/D<<>>>> doesn't work here + \@MXV@defaultview% + \@MXV@iiidia% + /3DD {\@MXV@iiidstreamorref}% 3D stream or reference object + /3DA <<\@MXV@activation\@MXV@deactivation\@MXV@iiidtoolb>>% + }% + }% + \ifx\@MXV@@label\@empty\else% + \@MXV@labeltoaux{@MXV@\@MXV@@label.annot}{\the\@MXV@includes}% + \@MXV@newlabel{@MXV@\@MXV@@label.annot}{\the\@MXV@includes}% + \fi% + \fi% + }% + \fi% +}{} + +%settings for newly opened media players +\def\@MXV@settings#1#2#3#4#5#6#7{% + var settings={% + privateData: {% + paused: false + }, + autoPlay: false, + visible: false, + volume: #7 + #1% showUI (controls) + #2% palindrome + #3% repeat + #4% rate + #5% startAt + #6% endAt + }; +} + +%JavaScript event handler routines for 2D media activation +\def\@MXV@events#1#2#3{% #1: playerid, #2: mouse?, #3: autoplay? + var events=new app.media.Events({% + %on focus change from one movie to another, events are fired in the + %following order: (1) onBlur, (2) onFocus, (3) afterBlur, (4) afterFocus + onBlur: function (e) {% + if(focusonplayer > 0){% + focusonplayer=0; + } + }, + afterBlur: function (e) {% + %only resume if we click outside of any media + if(focusonplayer==0){% + try{ + e.target.settings.privateData.paused=false; + e.target.play(); + }catch(e){} + } + }, + onFocus: function (e) {% + focusonplayer=#1; + }, + afterFocus: function (e) {% + if(!e.target.isPlaying){%play on click if paused + try{ + e.target.settings.privateData.paused=false; + e.target.play(); + if(!e.target.isPlaying){%still not playing?! + %sometimes play() fails, in particular if the movie has reached + %its end before getting the focus; but this works: + if( + e.target.settings.startAt.time + || e.target.settings.startAt.frame + || e.target.settings.startAt.marker + || e.target.id == 'vnd.adobe.swname:AAPL_QuickTime' + ){ + e.target.seek(e.target.settings.startAt); + }else{ + e.target.stop(); + } + e.target.play(); + } + } + catch (e){} + } + \@MXV@if{#2}% + else{% + %media can only be paused if mouse option is set + try{ + e.target.pause(); + e.target.settings.privateData.paused=true; + }catch (e){} + } + \fi% + \if@MXV@issound\else e.target.visible=true;\fi% + }, + onPlay: function (e) {% + e.target.settings.privateData.paused=false; + }, + onPause: function (e) {% + e.target.settings.privateData.paused=true; + }, + afterReady: function (e) {% + try{ + if( + e.target.settings.startAt.time + || e.target.settings.startAt.frame + || e.target.settings.startAt.marker + ){ + e.target.play(); + e.target.pause(); + e.target.stop(); + e.target.settings.privateData.paused=false; + e.target.seek(e.target.settings.startAt); + } + \if@MXV@issound\else e.target.visible=true;\fi% + \@MXV@if{#3} + e.target.settings.privateData.paused=false; + e.target.play(); + \fi + } + catch (e){} + } + }); +}% + +%output driver specific implementations of the 2D inclusion macro +\ifpdf% + %pdfLaTeX version + \def\@MXV@includemovie#1#2#3#4{% + %insert box or poster + \@MXV@box{#1}{#2}{#3}% + % + \if@MXV@externalviewer\else% + %new action dict + \pdfobj reserveobjnum% + \@MXV@adict=\pdflastobj% + % + %new additional actions dict + \pdfobj reserveobjnum% + \@MXV@aadict=\pdflastobj% + % + \fi% + %embedded file entry `/EF' + \if@MXV@inline% + %embed the same media file only once + \ifthenelse{\equal{\@MXV@getlabelvalue{\pdfmdfivesum file {#4}}}{undefined}}{% + \pdfobj stream % + attr {% + /Type/EmbeddedFile% + /Subtype (\@MXV@mime)% + }% + file {#4}% + \pdfrefobj\pdflastobj% + \edef\@MXV@efentry{% + /EF << /F \the\pdflastobj\space 0 R >>% + }% + \@MXV@newlabel{\pdfmdfivesum file {#4}}{\the\pdflastobj}% + }{% + \edef\@MXV@efentry{% + /EF << /F \@MXV@getlabelvalue{\pdfmdfivesum file {#4}}\space 0 R >>% + }% + }% + \else\def\@MXV@efentry{}\fi% + % + \ifthenelse{\boolean{@MXV@externalviewer}\AND\NOT\boolean{@MXV@inline}}{}{% + %new file specification object + \pdfobj {<<% + /F(#4)% + \@MXV@fsentry% + \@MXV@efentry% + /Type/Filespec% + >>}\pdfrefobj\pdflastobj% + \edef\@MXV@filespec{\the\pdflastobj}% + }% + % + \makebox[0pt][r]{\makebox[#1][l]{% + %insert FileAttachment annotation + \ifthenelse{\boolean{@MXV@inline}\AND\boolean{@MXV@externalviewer}\OR% + \boolean{@MXV@attachment}% + }{% + \pdfannot width #1 height #2 depth #3 {% + /Subtype /FileAttachment% + /F 0% + /T (\@MXV@filename)% + /Contents (Media File (\@MXV@mime))% + \if@MXV@externalviewer% + %a coloured border, as with external links, would be much nicer + /Name/Paperclip% + /C [1 1 1]% + \else% + /AP <>/R<<>>/D<<>>>>% + \fi% + /FS \@MXV@filespec\space 0 R% + }% + }{% + \if@MXV@url% + %insert Link annotation, if media file is a URL + \pdfannot width #1 height #2 depth #3 {% + /Subtype /Link% + /F 0% + \if@MXV@externalviewer% + \@MXV@urlattr% + \else% + /H /N% + /Border [0 0 0]% + \fi% + /A <>% + /Contents (Media File (\@MXV@mime))% + }% + \else% + %else insert Launch action for local external media file + \if@MXV@inline\else% + \pdfannot width #1 height #2 depth #3 {% + /Subtype /Link% + /F 0% + \if@MXV@externalviewer% + \@MXV@runattr% + \else% + /H /N% + /Border [0 0 0]% + \fi% + /A <<% + /F (#4)% + /S /Launch% + >>% + /Contents (Media File (\@MXV@mime))% + }% + \fi% + \fi% + }% + % + \if@MXV@externalviewer\else% + %annotation object of subtype `Screen' + \pdfannot width #1 height #2 depth #3 {% + /Subtype /Screen% + /Border [0 0 0]% no border (PDF-1.1) + /BS <>% no border (PDF-1.5) + /F 5% disable annot if multimedia is not available + /T (\@MXV@filename)% + /Contents (Media File (\@MXV@mime))% + /P \@MXV@pdfpageref{@MXV@annot\the\@MXV@includes.page} 0 R% + /A \the\@MXV@adict\space 0 R% + /AA \the\@MXV@aadict\space 0 R% + /AP <>/R<<>>/D<<>>>>% + }\edef\@MXV@screenannot{\the\pdflastannot}% + %label for later annot obj number determination, to be used in + %movieref's only + \ifx\@MXV@@label\@empty\else% + \@MXV@labeltoaux{@MXV@\@MXV@@label.annot}{\@MXV@screenannot}% + \@MXV@newlabel{@MXV@\@MXV@@label.annot}{\@MXV@screenannot}% + \fi% + % + %new media clip object of subtype `Media Clip Data' (/S/MCD) + \pdfobj {<<% + /D \@MXV@filespec\space 0 R% + /P <>% + /S/MCD% + /CT (\@MXV@mime)% + >>}\pdfrefobj\pdflastobj% + % + %new rendition object of subtype `Media Rendition' (/S/MR) + \pdfobj {<<% + /C \the\pdflastobj\space 0 R% + /S/MR% + /SP <>>>% + /P <<% + \@MXV@player% + /BE <<% + /F 2% + \@MXV@@repeat\@MXV@@volume\@MXV@@ctrls% + /D <>% + >>% + >>% + >>}\edef\@MXV@mediarendition{\the\pdflastobj}\pdfrefobj\pdflastobj% + %label for later rendition obj number determination + \ifx\@MXV@@label\@empty\else% + \@MXV@labeltoaux{@MXV@\@MXV@@label.rendition}{\@MXV@mediarendition}% + \@MXV@newlabel{@MXV@\@MXV@@label.rendition}{\@MXV@mediarendition}% + \fi% + % + %action dictionary + \pdfobj useobjnum \@MXV@adict {<<% + /R \@MXV@mediarendition\space 0 R% + /S/Rendition% + /OP 0% fallback if /JS doesn't work or is empty + \@MXV@activationjsentry% + /AN \@MXV@screenannot\space 0 R% + >>}\pdfrefobj\pdflastobj% + % + %create play/stop/resume/pause actions + \pdfobj {<<% + /R \@MXV@mediarendition\space 0 R% + /S/Rendition% + \@MXV@pageopenopentry% /OP fallback if /JS doesn't work + \@MXV@pageopenjsentry% + /AN \@MXV@screenannot\space 0 R% + >>}\edef\@MXV@pageopenaction{\the\pdflastobj}\pdfrefobj\pdflastobj% + % + \pdfobj {<<% + /R \@MXV@mediarendition\space 0 R% + /S/Rendition% + \@MXV@pagecloseopentry% + \@MXV@pageclosejsentry% + /AN \@MXV@screenannot\space 0 R% + >>}\edef\@MXV@pagecloseaction{\the\pdflastobj}\pdfrefobj\pdflastobj% + % + %populate additional actions dictionary + \pdfobj useobjnum \@MXV@aadict {<<% + /PO \@MXV@pageopenaction\space 0 R% + /PC \@MXV@pagecloseaction\space 0 R% + >>}\pdfrefobj\pdflastobj% + \fi}}% + }% +\else% + %dvips version + \def\@MXV@includemovie#1#2#3#4{% + %insert FileAttachment annotation + \ifthenelse{\boolean{@MXV@inline}\AND\boolean{@MXV@externalviewer}\OR% + \boolean{@MXV@attachment}% + }{% + \makebox[0pt][l]{% + \pdfmark[\phantom{\@MXV@box{#1}{#2}{#3}}]{% + pdfmark=/ANN,% + Subtype=/FileAttachment,% + Raw={% + /F 0% + /T (\@MXV@filename)% + /Contents (Media File (\@MXV@mime))% + \if@MXV@externalviewer% + /Name/Paperclip% + /C [1 1 1]% + \else% + /AP <>/R<<>>/D<<>>>>% + \fi% + /FS {filespec\the\@MXV@includes}% + }% + }% + }% + }{% + \if@MXV@url% + %insert Link annotation, if media file is a URL + \makebox[0pt][l]{% + \pdfmark[\phantom{\@MXV@box{#1}{#2}{#3}}]{% + pdfmark=/ANN,% + Subtype=/Link,% + Raw={% + /F 0% + \if@MXV@externalviewer% + /C [\@urlbordercolor]% + /H \@pdfhighlight% + \else% + /H /N% + /Border [0 0 0]% + \fi% + /Action <>% + /Contents (Media File (\@MXV@mime))% + }% + }% + }% + \else% + %else insert Launch action for local external media file + \if@MXV@inline\else% + \makebox[0pt][l]{% + \pdfmark[\phantom{\@MXV@box{#1}{#2}{#3}}]{% + pdfmark=/ANN,% + Subtype=/Link,% + Raw={% + /F 0% + \if@MXV@externalviewer% + /C [\@urlbordercolor]% + /H \@pdfhighlight% + \else% + /H /N% + /Border [0 0 0]% + \fi% + /Action <<% + /F (#4)% + /S /Launch% + >>% + /Contents (Media File (\@MXV@mime))% + }% + }% + }% + \fi% + \fi% + }% + % + \if@MXV@externalviewer% + \@MXV@box{#1}{#2}{#3}% + \else% + %annotation object of subtype `Screen' + \pdfmark[\@MXV@box{#1}{#2}{#3}]{% + pdfmark=/ANN,% + Subtype=/Screen,% + Border={0 0 0},% + Raw={% + /_objdef {screenannot\the\@MXV@includes}% + /F 5% + /T (\@MXV@filename)% + /Contents (Media File (\@MXV@mime))% + /BS <>% no border (PDF-1.5) + /P {ThisPage}% + /AA {aadict\the\@MXV@includes}% + /AP <>/R<<>>/D<<>>>>% + }% + }% + \ifx\@MXV@@label\@empty\else% + \@MXV@labeltoaux{@MXV@\@MXV@@label.annot}{\the\@MXV@includes}% + \@MXV@newlabel{@MXV@\@MXV@@label.annot}{\the\@MXV@includes}% + \fi% + % + %entire action entry moved outside screen annotation + \pdfmark{% + pdfmark=/PUT,% + Raw={% + {screenannot\the\@MXV@includes} <<% + /A <<% + /R {mediarendition\the\@MXV@includes}% + /S/Rendition% + /OP 0% fallback, if /JS doesn't work or is empty + \@MXV@activationjsentry% + /AN {screenannot\the\@MXV@includes}% + >>% + >>% + }% + }% + % + %new rendition object of subtype `Media Rendition' (/S/MR) + \pdfmark{% + pdfmark=/OBJ,% + Raw={% + /type/dict% + /_objdef {mediarendition\the\@MXV@includes}% + }% + }% + \pdfmark{% + pdfmark=/PUT,% + Raw={% + {mediarendition\the\@MXV@includes} <<% + /C {mediaclipdata\the\@MXV@includes}% + /S/MR% + %screen parameters: fully transparent, hidden if audio mime type + /SP <>>>% + /P <<%Media Play Parameters + \@MXV@player% + /BE <<%Parameters need only be honored by the player in + %the best effort sense + /F 2%scale media's width and height to fit the + %annotation rectangle + \@MXV@@repeat\@MXV@@volume\@MXV@@ctrls% + /D <>%movie remains opened + >>% + >>% + >>% + }% + }% + % + %new media clip object of subtype `Media Clip Data' (/S/MCD) + \pdfmark{% + pdfmark=/OBJ,% + Raw={% + /_objdef {mediaclipdata\the\@MXV@includes}% + /type/dict% + }% + }% + \pdfmark{% + pdfmark=/PUT,% + Raw={% + {mediaclipdata\the\@MXV@includes} <<% + /D {filespec\the\@MXV@includes}% + /P <>% + /S/MCD% + /CT (\@MXV@mime)% mime type + >>% + }% + }% + \fi% + % + %new file specification object + \ifthenelse{\boolean{@MXV@externalviewer}\AND\NOT\boolean{@MXV@inline}}{}{% + \pdfmark{% + pdfmark=/OBJ,% + Raw={% + /_objdef {filespec\the\@MXV@includes}% + /type/dict% + }% + }% + \pdfmark{% + pdfmark=/PUT,% + Raw={% + {filespec\the\@MXV@includes} <<% + \@MXV@fsentry + /F(#4)% file name + /Type/Filespec% + >>% + }% + }% + }% + % + %embedded file entry `/EF' + \if@MXV@inline% + %embed the same media file only once + \ifthenelse{\equal{\@MXV@getlabelvalue{\pdfmdfivesum file {#4}}}{undefined}}{% + %new stream object + \pdfmark{% + pdfmark=/OBJ,% + Raw={% + /_objdef {fstream\the\@MXV@includes}% + /type/stream% + }% + }% + \pdfmark{% + pdfmark=/PUT,% + Raw={% + {fstream\the\@MXV@includes}% + (#4) (r) file% read in file contents + }% + }% + \pdfmark{% + pdfmark=/PUT,% + Raw={% + {fstream\the\@MXV@includes} <<% + /Type/EmbeddedFile% + /Subtype(\@MXV@mime)% + >>% + }% + }% + \edef\@MXV@moviestream{fstream\the\@MXV@includes}% + \@MXV@newlabel{\pdfmdfivesum file {#4}}{fstream\the\@MXV@includes}% + }{% + \edef\@MXV@moviestream{\@MXV@getlabelvalue{\pdfmdfivesum file {#4}}}% + }% + % put the embedded file entry into file spec object + \pdfmark{% + pdfmark=/PUT,% + Raw={% + {filespec\the\@MXV@includes} <<% + /EF << /F {\@MXV@moviestream} >>% + >>% + }% + }% + \fi% + % + \if@MXV@externalviewer\else% + %create actions for page open/close events + \pdfmark{% + pdfmark=/OBJ,% + Raw={% + /_objdef {pageopenaction\the\@MXV@includes}% + /type/dict% + }% + }% + \pdfmark{% + pdfmark=/PUT,% + Raw={% + {pageopenaction\the\@MXV@includes} <<% + /R {mediarendition\the\@MXV@includes}% + /S/Rendition% + \@MXV@pageopenopentry% /OP fallback, if /JS doesn't work + \@MXV@pageopenjsentry% + /AN {screenannot\the\@MXV@includes}% + >>% + }% + }% + \pdfmark{% + pdfmark=/OBJ,% + Raw={% + /_objdef {pagecloseaction\the\@MXV@includes}% + /type/dict% + }% + }% + \pdfmark{% + pdfmark=/PUT,% + Raw={% + {pagecloseaction\the\@MXV@includes} <<% + /R {mediarendition\the\@MXV@includes}% + /S/Rendition% + \@MXV@pagecloseopentry% + \@MXV@pageclosejsentry% + /AN {screenannot\the\@MXV@includes}% + >>% + }% + }% + % + %create and populate additional actions dictionary, always add entries + %for page open/close events + \pdfmark{% + pdfmark=/OBJ,% + Raw={% + /type/dict% + /_objdef {aadict\the\@MXV@includes}% + }% + }% + % + \pdfmark{% + pdfmark=/PUT,% + Raw={% + {aadict\the\@MXV@includes} <<% + /PO {pageopenaction\the\@MXV@includes}% + /PC {pagecloseaction\the\@MXV@includes}% + >>% + }% + }% + \fi% + }% +\fi + +%definition of user command `\includemovie' +\newcommand{\includemovie}[4][]{% + \leavevmode% + \@MXV@reset% all macros and options + \setkeys{MXV@user}{#1}% parse options + % + %total height of text + \@MXV@totalheight=\@MXV@height% + \advance\@MXV@totalheight by \@MXV@depth% + %traiselen=distance at which text is to be raised to centre it vertically + %braiselen=vertical centre of media box (auxiliary measure) + \@MXV@traiselen=0.5\@MXV@height% + \advance\@MXV@traiselen by -0.5\@MXV@depth% + % + \ifthenelse{\equal{#3}{}}{% no height argument + \@MXV@braiselen=0.5\@MXV@height% + }{%override height of text, height argument given + \@MXV@braiselen=#3% + \@MXV@braiselen=0.5\@MXV@braiselen% + \setlength{\@MXV@height}{#3}% + }% + % + \ifthenelse{\equal{\@MXV@boxdepth}{}}{% no depth option given + \ifthenelse{\lengthtest{\@MXV@totalheight>\@MXV@height}}{% + %depth of text only taken into account, if the total height + %is smaller than the height of the display box + \advance\@MXV@braiselen by -0.5\@MXV@depth% + }{% + \@MXV@depth=0pt% + }% + }{%override depth of text, depth option given + \setlength{\@MXV@@boxdepth}{\@MXV@boxdepth}% + \advance\@MXV@braiselen by -0.5\@MXV@@boxdepth% + \setlength{\@MXV@depth}{\@MXV@boxdepth}% + }% + %finally centre text vertically + \ifthenelse{\NOT\equal{#3}{}\OR\NOT\equal{\@MXV@boxdepth}{}}{% + \advance\@MXV@traiselen by -\@MXV@braiselen% + \@MXV@traiselen=-\@MXV@traiselen% + \savebox{\@MXV@textbox}{\raisebox{\@MXV@traiselen}[0pt][0pt]{% + \usebox{\@MXV@textbox}}}% + }{}% + \ifthenelse{\equal{#2}{}}{}{%override horiz. dimension of text + \setlength{\@MXV@width}{#2}% + %centre text horizontally + \savebox{\@MXV@textbox}{\makebox[\@MXV@width][c]{\usebox{\@MXV@textbox}}}% + }% + % + %find out whether the contents should be hidden or not (for presentations) + \setboolean{@MXV@hide}{false}% +% \ifthenelse{\boolean{@MXV@powerdot}}{% +% \ifthenelse{\boolean{pd@overlay}}{}{% +% \ifthenelse{\pd@method=2}{}{% +% \setboolean{@MXV@hide}{true}% +% }% +% }% +% }{}% + \ifthenelse{\boolean{@MXV@beamer}}{% + \ifthenelse{\boolean{beamer@anotherslide}}{% + \setboolean{@MXV@hide}{true}% + }{}% + }{}% + % + \ifthenelse{\boolean{@MXV@hide}}{% + %insert whitespace instead of annot + \phantom{\vrule width \@MXV@width height \@MXV@height depth \@MXV@depth}% + }{% + \ifthenelse{\NOT\boolean{@MXV@url}\AND\boolean{@MXV@inline}}{% + \IfFileExists{#4}{}{% + \PackageError{movie15}{% + File `#4' cannot be opened for embedding.\MessageBreak + Did you forget to set option `url' or `inline=false'? + }{% + Try any of the options `url' or `inline=false'! + }% + }% + }{}% + % + %guess the mime type based on the filename extension + \filename@parse{#4}% + \ifthenelse{\equal{\@MXV@mime}{@MXV@auto}}{% + \@MXV@guessmime{#4}{\filename@ext}}{}% + \if\filename@ext\relax% + \xdef\@MXV@filename{\filename@base}% + \else% + \xdef\@MXV@filename{\filename@base.\filename@ext}% + \fi% + \expandafter\@MXV@@issound\@MXV@mime:% + % + %if 3D object is not embedded inline we must use some external player :( + \ifthenelse{% + \boolean{@MXV@iiid}% + \AND\NOT\boolean{@MXV@inline}% + }{% + \setboolean{@MXV@externalviewer}{true}% + }{}% + % + \edef\@MXV@urlattr{% + \if@MXV@beamer% + /Border [1 1 1]% + \else% + /Border [\@pdfborder]% + \fi% + /C [\@urlbordercolor]% + /H \@pdfhighlight% + }% + \edef\@MXV@runattr{% + \if@MXV@beamer% + /Border [1 1 1]% + \else% + /Border [\@pdfborder]% + \fi% + /C [\@runbordercolor]% + /H \@pdfhighlight% + }% + % + \global\advance\@MXV@includes by 1%increment counter + % + %label this annotation for later page number determination + \@MXV@labeltoaux{@MXV@annot\the\@MXV@includes.page}{% + \noexpand\the\@MXV@page}% + % + %label this annotation for later annot id number determination & + %check for multiply-defined labels + % \@MXV@label --> automatic (presentation mode) or user defined label + % \@MXV@@label = \@MXV@label (non presentation doc classes) + % \@MXV@@label = \@MXV@label + physical page No. (presentation mode) + \ifx\@MXV@label\@empty% + %when used with presentation packages, annots must be labelled, + %use the media file name, if no label provided + \ifthenelse{\boolean{@MXV@presentation}}{% + \xdef\@MXV@label{#4}% + }{}% + \fi% + \ifx\@MXV@label\@empty\else% + \ifthenelse{\boolean{@MXV@presentation}}{% + %in presentation mode, the label must be extended by the physical page No. + \xdef\@MXV@@label{\@MXV@label.\@MXV@getlabelvalue{@MXV@annot\the\@MXV@includes.page}}% + }{% + \xdef\@MXV@@label{\@MXV@label}% + }% + \fi% + \ifx\@MXV@@label\@empty\else% + \ifthenelse{% + \NOT\equal{\@MXV@getlabelvalue{@MXV@\@MXV@@label.annotid}}{undefined}% + \AND% + \NOT\equal{\@MXV@getlabelvalue{@MXV@\@MXV@@label.annotid}}{% + \the\@MXV@includes}% + }{% + \PackageWarning{movie15}{% + Label `\@MXV@label' multiply defined% + }% + \ifthenelse{\isundefined{\@MXV@multiwarning}}{% + \gdef\@MXV@multiwarning{}% + \AtEndDocument{% + \PackageWarningNoLine{movie15}{% + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\MessageBreak + @@ There were multiply-defined labels! @@\MessageBreak + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}% + }% + }{}% + }{}% + \if@MXV@@draft% + \@MXV@labeltoaux{@MXV@\@MXV@label.draft}{true}% + \else% + \@MXV@labeltoaux{@MXV@\@MXV@label.draft}{false}% + \fi% + \@MXV@labeltoaux{@MXV@\@MXV@@label.annotid}{\the\@MXV@includes}% + \if@MXV@presentation\else% + \@MXV@newlabel{@MXV@\@MXV@@label.annotid}{\the\@MXV@includes}% + \fi% + \fi% + % + \ifthenelse{\boolean{@MXV@@draft}}{}{% + \ifthenelse{\boolean{@MXV@externalviewer}}{% + \ifx\@MXV@label\@empty\else% + \@MXV@labeltoaux{@MXV@\@MXV@label.externalviewer}{true}% + \@MXV@newlabel{@MXV@\@MXV@label.externalviewer}{true}% + \fi% + }{% + %what is to be put into movie link annot depends on the following + \ifx\@MXV@label\@empty\else% + \@MXV@labeltoaux{@MXV@\@MXV@label.externalviewer}{false}% + \@MXV@newlabel{@MXV@\@MXV@label.externalviewer}{false}% + \fi% + % + %depending on options do content specific stuff + \ifthenelse{\boolean{@MXV@iiid}}{% + % #### 3D #### + \if@MXV@externalviewer\else% + \ifthenelse{\equal{\@MXV@iiidpalindrome}{/Subtype/Oscillating}}{% + \global\multiply\@MXV@iiidrepeat by 2% + }{}% + \ifthenelse{\boolean{@MXV@autoplay}\OR\boolean{@MXV@autoresume}}{% + \def\@MXV@activation{/A/PV/AIS/L}% open 3D object, run animation + }{% + \if@MXV@runposter% + \def\@MXV@activation{/A/PV/AIS/I}%open 3D obj but don't run animation + \else% + \def\@MXV@activation{/A/XA}% explicit activation by user + \fi% + }% + \if@MXV@autostop% + \def\@MXV@deactivation{/D/PI/DIS/I}% + \else% + \if@MXV@autopause% + \def\@MXV@deactivation{/D/PI/DIS/I}% + \else% + \if@MXV@autoclose% + \def\@MXV@deactivation{/D/PI/DIS/U}% + \else%@MXV@continue + \def\@MXV@deactivation{/D/PI/DIS/L}% + \fi% + \fi% + \fi% + %counter for 3D inclusion on current page + \ifthenelse{% + \equal{% + \@MXV@getlabelvalue{@MXV@annot\the\@MXV@includes.page}% + }{\@MXV@oldpage}% + }{% + \global\advance\@MXV@iiidoncurpage by 1% + }{% + \global\@MXV@iiidoncurpage=1% + }% + \xdef\@MXV@oldpage{\@MXV@getlabelvalue{% + @MXV@annot\the\@MXV@includes.page}}% + \fi% + \ifx\@MXV@label\@empty\else% + \@MXV@labeltoaux{@MXV@\@MXV@label.3D}{true}% + \@MXV@newlabel{@MXV@\@MXV@label.3D}{true}% + \@MXV@labeltoaux{@MXV@\@MXV@label.3Dbg}{\@MXV@defaultbg}% + \@MXV@newlabel{@MXV@\@MXV@label.3Dbg}{\@MXV@defaultbg}% + \@MXV@labeltoaux{@MXV@\@MXV@label.3Dlights}{\@MXV@defaultlights}% + \@MXV@newlabel{@MXV@\@MXV@label.3Dlights}{\@MXV@defaultlights}% + \@MXV@labeltoaux{@MXV@\@MXV@label.3Drender}{\@MXV@defaultrender}% + \@MXV@newlabel{@MXV@\@MXV@label.3Drender}{\@MXV@defaultrender}% + \fi% + \ifx\@MXV@@label\@empty\else% + \@MXV@labeltoaux{@MXV@\@MXV@@label.3Doncurpage}{\the\@MXV@iiidoncurpage}% + \@MXV@newlabel{@MXV@\@MXV@@label.3Doncurpage}{\the\@MXV@iiidoncurpage}% + \fi% + }{%#### 2D #### + %get the player ID + \if@MXV@presentation% + \ifthenelse{% + \equal{\@MXV@getlabelvalue{@MXV@\@MXV@label.playerid}}{undefined}% + }{% + \global\advance\@MXV@players by 1%increment counter + }{% + \global\@MXV@players=\@MXV@getlabelvalue{@MXV@\@MXV@label.playerid}% + }% + \@MXV@labeltoaux{@MXV@\@MXV@label.playerid}{\the\@MXV@players}% + \@MXV@newlabel{@MXV@\@MXV@label.playerid}{\the\@MXV@players}% + \edef\@MXV@currplayer{\the\@MXV@players}% + \else% + \ifx\@MXV@label\@empty\else% + \@MXV@labeltoaux{@MXV@\@MXV@label.playerid}{\the\@MXV@includes}% + \@MXV@newlabel{@MXV@\@MXV@label.playerid}{\the\@MXV@includes}% + \fi% + \edef\@MXV@currplayer{\the\@MXV@includes}% + \fi% + % + \ifx\@MXV@startat\@empty% default start position + \gdef\@MXV@startat{, startAt: 0}% + \fi% + %write player settings to aux file + \ifx\@MXV@label\@empty\else% + \@MXV@labeltoaux{@MXV@\@MXV@label.mouse}{% + \if@MXV@mouse true\else false\fi}% + \@MXV@labeltoaux{@MXV@\@MXV@label.showUI}{\@MXV@ctrls}% + \@MXV@labeltoaux{@MXV@\@MXV@label.palindrome}{\@MXV@palindrome}% + \@MXV@labeltoaux{@MXV@\@MXV@label.repeat}{\@MXV@repeat}% + \@MXV@labeltoaux{@MXV@\@MXV@label.rate}{\@MXV@rate}% + \@MXV@labeltoaux{@MXV@\@MXV@label.startAt}{\@MXV@startat}% + \@MXV@labeltoaux{@MXV@\@MXV@label.endAt}{\@MXV@endat}% + \@MXV@labeltoaux{@MXV@\@MXV@label.volume}{\@MXV@volume}% + \@MXV@labeltoaux{@MXV@\@MXV@label.autoplay}{% + \if@MXV@autoplay true\else false\fi}% + \@MXV@labeltoaux{@MXV@\@MXV@label.3D}{false}% + \@MXV@labeltoaux{@MXV@\@MXV@label.issound}{% + \if@MXV@issound true\else false\fi}% + % + \@MXV@newlabel{@MXV@\@MXV@label.mouse}{% + \if@MXV@mouse true\else false\fi}% + \@MXV@newlabel{@MXV@\@MXV@label.showUI}{\@MXV@ctrls}% + \@MXV@newlabel{@MXV@\@MXV@label.palindrome}{\@MXV@palindrome}% + \@MXV@newlabel{@MXV@\@MXV@label.repeat}{\@MXV@repeat}% + \@MXV@newlabel{@MXV@\@MXV@label.rate}{\@MXV@rate}% + \@MXV@newlabel{@MXV@\@MXV@label.startAt}{\@MXV@startat}% + \@MXV@newlabel{@MXV@\@MXV@label.endAt}{\@MXV@endat}% + \@MXV@newlabel{@MXV@\@MXV@label.volume}{\@MXV@volume}% + \@MXV@newlabel{@MXV@\@MXV@label.autoplay}{% + \if@MXV@autoplay true\else false\fi}% + \@MXV@newlabel{@MXV@\@MXV@label.3D}{false}% + \@MXV@newlabel{@MXV@\@MXV@label.issound}{% + \if@MXV@issound true\else false\fi}% + % + \fi% + % + \ifthenelse{\boolean{@MXV@autoplay}\OR\boolean{@MXV@runposter}}{% + \xdef\@MXV@pageopenopentry{/OP 4}% + }{% + \if@MXV@autoresume% + \xdef\@MXV@pageopenopentry{/OP 3}% + \else% + \xdef\@MXV@pageopenopentry{/OP 2}% + \fi% + }% + % + \if@MXV@autostop% + \xdef\@MXV@pagecloseopentry{/OP 1}% + \else% + \if@MXV@autopause% + \xdef\@MXV@pagecloseopentry{/OP 2}% + \else% + \if@MXV@autoclose% + \xdef\@MXV@pagecloseopentry{/OP 1}% + \else% @MXV@continue + \xdef\@MXV@pagecloseopentry{/OP 3}% + \fi% + \fi% + \fi% + % + %JavaScripts for playback control + %script for page invisible event + \if@MXV@autopause% + \xdef\@MXV@pageclosejsentry{% + /JS ( + try{% + if(player\@MXV@currplayer.isPlaying){% + player\@MXV@currplayer.pause(); + player\@MXV@currplayer.settings.privateData.paused=true; + } + focusonplayer=-1; %page change + player\@MXV@currplayer.visible=false; + } + catch(e){} + )% + }% + \else% + \if@MXV@autostop% + \xdef\@MXV@pageclosejsentry{% + /JS ( + try{% + player\@MXV@currplayer.settings.privateData.paused=false; + %players tend to be bugged, always stop from playing state + if(!player\@MXV@currplayer.isPlaying){ + player\@MXV@currplayer.play(); + } + player\@MXV@currplayer.stop(); + if( + player\@MXV@currplayer.settings.startAt.time + || player\@MXV@currplayer.settings.startAt.frame + || player\@MXV@currplayer.settings.startAt.marker + || player\@MXV@currplayer.id == + 'vnd.adobe.swname:AAPL_QuickTime' + ){ + player\@MXV@currplayer.seek(% + player\@MXV@currplayer.settings.startAt); + } + focusonplayer=-1; + player\@MXV@currplayer.visible=false; + } + catch(e){} + )% + }% + \else% + \if@MXV@autoclose% + \xdef\@MXV@pageclosejsentry{% + /JS ( + try{% + player\@MXV@currplayer.close(app.media.closeReason.general); + focusonplayer=-1; %page change + player\@MXV@currplayer.visible=false; + } + catch(e){} + )% + }% + \else% + \xdef\@MXV@pageclosejsentry{%@MXV@continue + /JS ( + try{% + focusonplayer=-1; %page change + player\@MXV@currplayer.visible=false; + } + catch(e){} + )% + }% + \fi% + \fi% + \fi% + % + %script for activation/resume on page open event + \xdef\@MXV@pageopenjsentry{% + /JS ( + try{% + if(player\@MXV@currplayer.isOpen){% + %drag the player on the current slide (presentation mode) + player\@MXV@currplayer.page=this.pageNum; + %... and make it visible + \if@MXV@issound\else player\@MXV@currplayer.visible=true;\fi% + % + %start or resume media which have autoplay option set; + %also resume paused media which have autoresume option set + \if@MXV@autoplay% + player\@MXV@currplayer.settings.privateData.paused=false; + player\@MXV@currplayer.play(); + if(!player\@MXV@currplayer.isPlaying){% still not playing?! + if( + player\@MXV@currplayer.settings.startAt.time + || player\@MXV@currplayer.settings.startAt.frame + || player\@MXV@currplayer.settings.startAt.marker + || player\@MXV@currplayer.id=='vnd.adobe.swname:AAPL_QuickTime' + ){ + player\@MXV@currplayer.seek( + player\@MXV@currplayer.settings.startAt); + }else{ + player\@MXV@currplayer.stop(); + } + player\@MXV@currplayer.play(); + } + \else% + \if@MXV@autoresume% + if(player\@MXV@currplayer.settings.privateData.paused){% + player\@MXV@currplayer.settings.privateData.paused=false; + player\@MXV@currplayer.play(); + if(!player\@MXV@currplayer.isPlaying){% + if( + player\@MXV@currplayer.settings.startAt.time + || player\@MXV@currplayer.settings.startAt.frame + || player\@MXV@currplayer.settings.startAt.marker + || player\@MXV@currplayer.id == + 'vnd.adobe.swname:AAPL_QuickTime' + ){ + player\@MXV@currplayer.seek(% + player\@MXV@currplayer.settings.startAt); + }else{ + player\@MXV@currplayer.stop();% + } + player\@MXV@currplayer.play(); + } + } + \fi% + \fi% + } + else{% + throw 'isClosed'; + } + } + catch(e){% + \@MXV@if{\if@MXV@autoplay true\else\if@MXV@runposter true\else % + false\fi\fi}% + if(focusonplayer==undefined){% + var focusonplayer=0; %shared by all annots + } + \@MXV@settings{\@MXV@ctrls}{\@MXV@palindrome}{\@MXV@repeat}% + {\@MXV@rate}{\@MXV@startat}{\@MXV@endat}{\@MXV@volume}% + \@MXV@events{\@MXV@currplayer}% + {\if@MXV@mouse true\else false\fi}% + {\if@MXV@autoplay true\else false\fi}% + var player\@MXV@currplayer=app.media.openPlayer({% + settings: settings, + events: events + }); + \fi% + }% + ) + }% + % + %script for normal activation by mouse click + \xdef\@MXV@activationjsentry{% + /JS ( + app.focusRect=true;% + if(focusonplayer==undefined){% + var focusonplayer=0; %shared by all annots + } + \@MXV@settings{\@MXV@ctrls}{\@MXV@palindrome}{\@MXV@repeat}% + {\@MXV@rate}{\@MXV@startat}{\@MXV@endat}{\@MXV@volume}% + \@MXV@events{\@MXV@currplayer}{\if@MXV@mouse true\else false\fi}% + {true}% + var player\@MXV@currplayer=app.media.openPlayer({% + settings: settings, + events: events + }); + ) + }% + }% + }% + }% draft? + % + %insert link target, if media has been labelled + \ifthenelse{\NOT\equal{\@MXV@@label}{}}{% + \raisebox{\@MXV@height}{% + \ifpdf% + \pdfdest name {@MXV@\@MXV@@label} xyz % + \else% + \hypertarget{@MXV@\@MXV@@label}{}% + \fi% + }% + }{}% + % + \ifthenelse{\boolean{@MXV@@draft}}{% + \makebox[0pt][l]{\usebox{\@MXV@textbox}}% + \@MXV@draftbox{\@MXV@width}{\@MXV@height}{\@MXV@depth}{#4}% + }{% + %insert textbox, obscured by poster + \ifthenelse{\boolean{@MXV@boxopt}\AND\NOT\boolean{@MXV@textoverposter}}{% + \makebox[0pt][l]{\usebox{\@MXV@textbox}}% + }{}% + % + %insert annotation + \ifthenelse{\boolean{@MXV@iiid}}{% + \edef\@MXV@iiidopt{[\@MXV@iiidopt]}% + \expandafter\@MXV@includeiiid\@MXV@iiidopt{\@MXV@width}{\@MXV@height}{\@MXV@depth}{#4}% + }{% + \@MXV@includemovie{\@MXV@width}{\@MXV@height}{\@MXV@depth}{#4}% + }% + % + %insert textbox, overprinting the poster + \ifthenelse{\boolean{@MXV@boxopt}\AND\boolean{@MXV@textoverposter}}{% + \makebox[0pt][r]{\usebox{\@MXV@textbox}}% + }{}% + }% + }% +} + +%for remote control of media +\newcommand\movieref[3][]{% + \leavevmode% + % save text argument + \savebox{\@MXV@textbox}{\ifHy@colorlinks\color{\@linkcolor}\fi#3}% + % + %find out whether the contents should be hidden or not (for presentations) + \setboolean{@MXV@hide}{false}% +% \ifthenelse{\boolean{@MXV@powerdot}}{% +% \ifthenelse{\boolean{pd@overlay}}{}{% +% \ifthenelse{\pd@method=2}{}{% +% \setboolean{@MXV@hide}{true}% +% }% +% }% +% }{}% + \ifthenelse{\boolean{@MXV@beamer}}{% + \ifthenelse{\boolean{beamer@anotherslide}}{% + \setboolean{@MXV@hide}{true}% + }{}% + }{}% + % + \ifthenelse{\boolean{@MXV@hide}}{% + %put whitespace instead of link annot + \phantom{\usebox{\@MXV@textbox}}% + }{% + \@MXV@reset% + % + \xdef\@MXV@label{#2}% + % + \global\advance\@MXV@links by 1%increment link counter + % + %label this link for later page number determination + \@MXV@labeltoaux{@MXV@link\the\@MXV@links.page}{\noexpand\the\@MXV@page}% + % + \ifthenelse{\boolean{@MXV@presentation}}{% + %in presentation mode the label must be extended by the physical page No. + \xdef\@MXV@@label{\@MXV@label.\@MXV@getlabelvalue{@MXV@link\the\@MXV@links.page}}% + }{% + \xdef\@MXV@@label{\@MXV@label}% + }% + % + %check if label is defined at all + \ifthenelse{\equal{\@MXV@getlabelvalue{@MXV@\@MXV@@label.annotid}}{undefined}}{% + \usebox{\@MXV@textbox}% write out text box + \PackageWarning{movie15}{% + Reference `\@MXV@label' on page \thepage \space undefined% + }% + \ifthenelse{\isundefined{\@MXV@undefwarning}}{% + \gdef\@MXV@undefwarning{}% + \AtEndDocument{% + \PackageWarningNoLine{movie15}{% + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\MessageBreak% + @@ There were undefined references! @@\MessageBreak% + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}% + }% + }{}% + }{% + \ifthenelse{\equal{\@MXV@getlabelvalue{@MXV@\@MXV@label.draft}}{true}}{% + \setboolean{@MXV@@draft}{true}% if the screen annotation is in draft mode + }{}% + \if@MXV@@draft\else% + \ifthenelse{\equal{\@MXV@getlabelvalue{@MXV@\@MXV@label.externalviewer}}{true}}{% + \setboolean{@MXV@externalviewer}{true}% + }{% + \setboolean{@MXV@externalviewer}{false}% + }% + \if@MXV@externalviewer\else% + %movieref used in 3D context? + \ifthenelse{\equal{\@MXV@getlabelvalue{@MXV@\@MXV@label.3D}}{true}}{% + \ifthenelse{\boolean{@MXV@iiiDfeat}}{% + \setboolean{@MXV@iiid}{true}% + }{% + \@MXV@neediiiD% + }% + }{}% + % + %actions completely different in 3D & 2D context + \ifthenelse{\boolean{@MXV@iiid}}{% #### 3D #### + %retrieve default background colour + \ifthenelse{\equal{\@MXV@getlabelvalue{@MXV@\@MXV@label.3Dbg}}{undefined}}{% + \gdef\@MXV@defaultbg{1 1 1}% + }{% + \xdef\@MXV@defaultbg{\@MXV@getlabelvalue{@MXV@\@MXV@label.3Dbg}}% + }% + %retrieve default lighting scheme + \ifthenelse{\equal{\@MXV@getlabelvalue{@MXV@\@MXV@label.3Dlights}}{undefined}}{% + \gdef\@MXV@defaultlights{}% + }{% + \xdef\@MXV@defaultlights{\@MXV@getlabelvalue{@MXV@\@MXV@label.3Dlights}}% + }% + %retrieve default render mode + \ifthenelse{\equal{\@MXV@getlabelvalue{@MXV@\@MXV@label.3Drender}}{undefined}}{% + \gdef\@MXV@defaultrender{Solid}% + }{% + \xdef\@MXV@defaultrender{\@MXV@getlabelvalue{@MXV@\@MXV@label.3Drender}}% + }% + \setkeys{MXV@user}{#1}% + \if@MXV@defaultviewprovided% define a new view, + %using any of the coo, c2c, roo, caa options + \pdfstringdef\@MXV@xname{}% + \edef\@MXV@args{\@MXV@coo\space\@MXV@ctoc\space\@MXV@roo\space\@MXV@roll\space}% + \expandafter\@MXV@ciiwmatrix\@MXV@args% build C2W matrix + \@MXV@viewobj% create pdf object of 3D view + \edef\@MXV@iiidview{\@MXV@@viewobj}% + %else use the indexed view specified by option `3Dviewindex' + \fi% + % + %create JavaScript (options 3Djscript, 3Dcalculate, 3Dgetview) + \ifthenelse{\NOT\equal{\@MXV@jscriptiiidfile}{}% + \OR\NOT\equal{\@MXV@calc}{}% + \OR\boolean{@MXV@iiidgetview}% + }{% + \edef\@MXV@linkjscriptiiid{% + try{% + %fill hash (annot3D) with refs to Annot3D objects + annot3D['\@MXV@label']=getAnnots3D(% + \@MXV@getlabelvalue{% + @MXV@annot\@MXV@getlabelvalue{@MXV@\@MXV@@label.annotid}.page% + }-1% + )[\@MXV@getlabelvalue{@MXV@\@MXV@@label.3Doncurpage}-1];% + annot3D['\@MXV@label'].activated=true;% + }catch(e){% + try{% + annot3D=new Array;% + annot3D['\@MXV@label']=getAnnots3D(% + \@MXV@getlabelvalue{% + @MXV@annot\@MXV@getlabelvalue{@MXV@\@MXV@@label.annotid}.page% + }-1% + )[\@MXV@getlabelvalue{@MXV@\@MXV@@label.3Doncurpage}-1];% + annot3D['\@MXV@label'].activated=true;% + }catch(e){% + var spc=String.fromCharCode(32);% + app.alert('3D' + spc + 'annotation' + spc + 'could' + spc +% + 'not' + spc + 'be' + spc + 'activated!');% + }% + }% + }% + \if@MXV@iiidgetview% + \edef\@MXV@linkjscriptiiid{% + \@MXV@linkjscriptiiid + try{ + %JavaScript to print the camera settings of the current view + var scene=annot3D['\@MXV@label'].context3D.scene;% + var camera=scene.cameras.getByIndex(0);% + var coo=camera.targetPosition;% + var c2c=camera.position.subtract(coo);% + var roo=c2c.length;% + c2c.normalize();% + % + %assemble result string + var spc=String.fromCharCode(32);% + var nl=String.fromCharCode(10);% + var charht=2;% + var res='VIEW\%={}'+nl;% + var x = (Math.abs(coo.x) < 1e-12 ? 0 : coo.x);% + var y = (Math.abs(coo.y) < 1e-12 ? 0 : coo.y);% + var z = (Math.abs(coo.z) < 1e-12 ? 0 : coo.z);% + if(Math.sqrt(x*x + y*y + z*z) > 0){% + res+=spc+spc;% + res+=util.printf('COO=\%s' + spc + '\%s' + spc + '\%s' +nl,% + (Math.abs(x) < 1.001e-6 && Math.abs(x) > 0 ?% + util.printf('\%.18f', x): x),% + (Math.abs(y) < 1.001e-6 && Math.abs(y) > 0 ?% + util.printf('\%.18f', y): y),% + (Math.abs(z) < 1.001e-6 && Math.abs(z) > 0 ?% + util.printf('\%.18f', z): z)% + );% + charht+=2;% + }% + x = (Math.abs(c2c.x) < 1e-12 ? 0 : c2c.x);% + y = (Math.abs(c2c.y) < 1e-12 ? 0 : c2c.y);% + z = (Math.abs(c2c.z) < 1e-12 ? 0 : c2c.z);% + if(!(x==0 && y==-1 && z==0)){% + res += spc + spc;% + res+=util.printf('C2C=\%s' + spc + '\%s' + spc + '\%s' +nl,% + (Math.abs(x) < 1.001e-6 && Math.abs(x) > 0 ?% + util.printf('\%.18f', x): x),% + (Math.abs(y) < 1.001e-6 && Math.abs(y) > 0 ?% + util.printf('\%.18f', y): y),% + (Math.abs(z) < 1.001e-6 && Math.abs(z) > 0 ?% + util.printf('\%.18f', z): z)% + );% + charht+=2;% + }% + if(roo > 0.11e-17){% + res+= spc + spc;% + res+=util.printf('ROO=\%s' + nl,% + (roo < 1.001e-6 ? util.printf('\%.12f', roo): roo)% + );% + charht+=2;% + }% + %determine the camera roll (camera.roll is bugged) + %%camera up-vector from camera.up, the latter being the positional vector + %%of the actual camera up-vector tip + %var up = camera.up.subtract(camera.position);% + %up.normalize();% + %%find the camera up-vector up0, that corresponds to zero roll + %%(Gram-Schmitt orthogonalisation) + %var worldup=new annot3D['\@MXV@label'].context3D.Vector3();% + %worldup.set(0,0,1);% + %var out=c2c.scale(-1);% + %var up0=worldup.subtract(out.scale(out.dot(worldup)));% + %up0.normalize();% + %var up0xup=up0.cross(up);% + %var roll=0;% + %if(up0xup.length>0){% + % up0xup.normalize();% + % var up0dotup=up.dot(up0);% + % up0dotup=(Math.abs(up0dotup) > 1 ? Math.round(up0dotup) : up0dotup);% + % %compute the angle between camera up and up0 vectors + % roll=Math.acos(up0dotup)*180/Math.PI*out.dot(up0xup);% + %}% + var roll = camera.roll*180/Math.PI;% + if(util.printf('\%.4f', roll)!=0){% + res+=util.printf(spc +spc + 'ROLL=\%s' + nl, roll);% + charht+=2;% + }% + aac=camera.fov * 180/Math.PI;% + if(util.printf('\%.5f', aac)!=30){% + res+=util.printf(spc + spc + 'AAC=\%s' + nl,% + (Math.abs(aac) < 1.001e-6 ? util.printf('\%.18f', aac): aac)% + );% + charht+=2;% + }% + rgb=scene.background.getColor();% + res+=spc + spc;% + res+=util.printf('BGCOLOR=\%f' + spc + '\%f' + spc + '\%f'% + + nl, rgb.r, rgb.g, rgb.b);% + charht+=2;% + switch(scene.lightScheme){% + case scene.LIGHT_MODE_FILE: + curlights='Artwork';break; + case scene.LIGHT_MODE_NONE: + curlights='None';break; + case scene.LIGHT_MODE_WHITE: + curlights='White';break; + case scene.LIGHT_MODE_DAY: + curlights='Day';break; + case scene.LIGHT_MODE_NIGHT: + curlights='Night';break; + case scene.LIGHT_MODE_BRIGHT: + curlights='Hard';break; + case scene.LIGHT_MODE_RGB: + curlights='Primary';break; + case scene.LIGHT_MODE_BLUE: + curlights='Blue';break; + case scene.LIGHT_MODE_RED: + curlights='Red';break; + case scene.LIGHT_MODE_CUBE: + curlights='Cube';break; + case scene.LIGHT_MODE_CAD: + curlights='CAD';break; + case scene.LIGHT_MODE_HEADLAMP: + curlights='Headlamp';break; + }% + res+=spc+spc+'LIGHTS='+curlights+nl;% + charht+=2;% + switch(scene.renderMode){% + case scene.RENDER_MODE_BOUNDING_BOX: + defaultrender='BoundingBox';break; + case scene.RENDER_MODE_TRANSPARENT_BOUNDING_BOX: + defaultrender='TransparentBoundingBox';break; + case scene.RENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE: + defaultrender='TransparentBoundingBoxOutline';break; + case scene.RENDER_MODE_VERTICES: + defaultrender='Vertices';break; + case scene.RENDER_MODE_SHADED_VERTICES: + defaultrender='ShadedVertices';break; + case scene.RENDER_MODE_WIREFRAME: + defaultrender='Wireframe';break; + case scene.RENDER_MODE_SHADED_WIREFRAME: + defaultrender='ShadedWireframe';break; + case scene.RENDER_MODE_SOLID: + defaultrender='Solid';break; + case scene.RENDER_MODE_TRANSPARENT: + defaultrender='Transparent';break; + case scene.RENDER_MODE_SOLID_WIREFRAME: + defaultrender='SolidWireframe';break; + case scene.RENDER_MODE_TRANSPARENT_WIREFRAME: + defaultrender='TransparentWireframe';break; + case scene.RENDER_MODE_ILLUSTRATION: + defaultrender='Illustration';break; + case scene.RENDER_MODE_SOLID_OUTLINE: + defaultrender='SolidOutline';break; + case scene.RENDER_MODE_SHADED_ILLUSTRATION: + defaultrender='ShadedIllustration';break; + case scene.RENDER_MODE_HIDDEN_WIREFRAME: + defaultrender='HiddenWireframe';break; + }% + res+=spc+spc+'RENDERMODE='+defaultrender+nl;% + charht+=2;% + for(var i=0;i40?40:charht);% + %open pop-up displaying the result string + var settings={% + initialize: function(dialog) {% + dialog.load({% + 'text': res% + });% + },% + description: {% + name: 'Current' + spc + '3D' + spc + 'Camera' + spc + 'Settings',% + elements: [% + {% + type: 'static_text',% + name: 'Add' + spc + 'the' + spc + 'following' + spc + 'VIEW' + spc + 'section' + spc + % + 'to' + spc + 'a' + spc + 'file' + spc + 'of' + spc +% + 'predefined' + spc + 'views.' + spc +% + '(See' + spc + 'option' + spc + '3Dviews2!)'% + },% + {% + type: 'edit_text',% + item_id: 'text',% + alignment: 'align_fill',% + multiline: true,% + char_width: 80,% + char_height: charht,% + readonly: true% + },% + {% + type: 'ok',% + ok_name: 'Close'% + }% + ]% + }% + };% + app.execDialog(settings);% + }catch(e){% + var spc=String.fromCharCode(32);% + app.alert('Error' + spc + 'while' + spc + 'executing' + spc +% + '3Dgetview:' + spc + e);% + }% + }% + \fi% + \ifx\@MXV@calc\@empty\else% + \edef\@MXV@linkjscriptiiid{% + \@MXV@linkjscriptiiid + try{ +% console.show(); +% console.clear(); + %constructor for doubly linked list + function List(){% + this.first_node=null;% + this.last_node=new Node(undefined);% + }% + List.prototype.push_back=function(x){% + var new_node=new Node(x);% + if(this.first_node==null){% + this.first_node=new_node;% + new_node.prev=null;% + }else{% + new_node.prev=this.last_node.prev;% + new_node.prev.next=new_node;% + }% + new_node.next=this.last_node;% + this.last_node.prev=new_node;% + };% + List.prototype.move_to_front=function(it){% + var node=it.get();% + if(node.next!=null && node.prev!=null){% + node.next.prev=node.prev;% + node.prev.next=node.next;% + node.prev=null;% + node.next=this.first_node;% + this.first_node.prev=node;% + this.first_node=node;% + }% + };% + List.prototype.begin=function(){% + var i=new Iterator();% + i.target=this.first_node;% + return(i);% + };% + List.prototype.end=function(){% + var i=new Iterator();% + i.target=this.last_node;% + return(i);% + };% + function Iterator(it){% + if( it!=undefined ){% + this.target=it.target;% + }else {% + this.target=null;% + }% + }% + Iterator.prototype.set=function(it){this.target=it.target;};% + Iterator.prototype.get=function(){return(this.target);};% + Iterator.prototype.deref=function(){return(this.target.data);};% + Iterator.prototype.incr=function(){% + if(this.target.next!=null){this.target=this.target.next;}% + };% + %constructor for node objects that populate the linked list + function Node(x){% + this.prev=null;% + this.next=null;% + this.data=x;% + }% + function sqr(r){return(r*r);}%helper function + %The following code borrows heavily from Bernd Gaertners `Miniball' software, + %originally written in C++, for computing the smallest enclosing ball of a + %set of points; see: http://www.inf.ethz.ch/personal/gaertner/miniball.html + function Basis(){% + this.m=0;% + this.q0=new Array(3);% + this.z=new Array(4);% + this.f=new Array(4);% + this.v=new Array(new Array(3), new Array(3), new Array(3), new Array(3));% + this.a=new Array(new Array(3), new Array(3), new Array(3), new Array(3));% + this.c=new Array(new Array(3), new Array(3), new Array(3), new Array(3));% + this.sqr_r=new Array(4);% + this.current_c=this.c[0];% + this.current_sqr_r=0;% + this.reset();% + }% + Basis.prototype.center=function(){return(this.current_c);};% + Basis.prototype.size=function(){return(this.m);};% + Basis.prototype.pop=function(){--this.m;};% + Basis.prototype.excess=function(p){% + var e=-this.current_sqr_r;% + for(var k=0;k<3;++k){% + e+=sqr(p[k]-this.current_c[k]);% + }% + return(e);% + };% + Basis.prototype.reset=function(){% + this.m=0;% + for(var j=0;j<3;++j){% + this.c[0][j]=0;% + }% + this.current_c=this.c[0];% + this.current_sqr_r=-1;% + };% + Basis.prototype.push=function(p){% + var i, j;% + var eps=1e-32;% + if(this.m==0){% + for(i=0;i<3;++i){% + this.q0[i]=p[i];% + }% + for(i=0;i<3;++i){% + this.c[0][i]=this.q0[i];% + }% + this.sqr_r[0]=0;% + }else {% + for(i=0;i<3;++i){% + this.v[this.m][i]=p[i]-this.q0[i];% + }% + for(i=1;i 0){% + if(this.B.push(j.deref())){% + this.mtf_mb(j);% + this.B.pop();% + if(this.support_end.get()==j.get()){% + this.support_end.incr();% + }% + this.L.move_to_front(j);% + }% + }% + }% + };% + Miniball.prototype.check_in=function(b){% + this.L.push_back(b);% + };% + Miniball.prototype.build=function(){% + this.B.reset();% + this.support_end.set(this.L.begin());% + this.mtf_mb(this.L.end());% + };% + Miniball.prototype.center=function(){% + return(this.B.center());% + };% + Miniball.prototype.radius=function(){% + return(Math.sqrt(this.B.current_sqr_r));% + };% + %create Miniball object + var mb=new Miniball();% + %scene object + var scene=annot3D['\@MXV@label'].context3D.scene;% + %aperture angle of the virtual camera + var camera=scene.cameras.getByIndex(0);% + if('\@MXV@calc'=='current'){% + var aac=camera.fov*180/Math.PI;% + }else{% + var aac=\@MXV@calc;% + }% + %auxiliary vectors + var dir=new annot3D['\@MXV@label'].context3D.Vector3();% + var up=new annot3D['\@MXV@label'].context3D.Vector3();% + var corner=new annot3D['\@MXV@label'].context3D.Vector3();% + %auxiliary 4x4 matrix + var bbox4x4=new annot3D['\@MXV@label'].context3D.Matrix4x4();% + %iterate over all visible mesh nodes in the scene + for(i=0;i) seems + %to be bugged, therefore we must resort to the + %multiply() method using an auxiliary matrix + %which contains the local bounding box corner coordinates + % + %auxiliary matrix from bbox.min coordinates + bbox4x4.setView(bbox.min, dir, up);% + %transform to world coordinates + bbox4x4=trans.multiply(bbox4x4.transpose);% + %extract the transformed coordinates + corner.set(bbox4x4.transpose.translation);% + %check-in corner position into Miniball + mb.check_in(new Array(corner.x, corner.y, corner.z));% + %the same procedure with bbox.max + bbox4x4.setView(bbox.max, dir, up);% + bbox4x4=trans.multiply(bbox4x4.transpose);% + corner.set(bbox4x4.transpose.translation);% + mb.check_in(new Array(corner.x, corner.y, corner.z));% + %and with all remaining 6 bbox corners + corner.set(bbox.min.x, bbox.max.y, bbox.max.z);% + bbox4x4.setView(corner, dir, up);% + bbox4x4=trans.multiply(bbox4x4.transpose);% + corner.set(bbox4x4.transpose.translation);% + mb.check_in(new Array(corner.x, corner.y, corner.z));% + corner.set(bbox.min.x, bbox.min.y, bbox.max.z);% + bbox4x4.setView(corner, dir, up);% + bbox4x4=trans.multiply(bbox4x4.transpose);% + corner.set(bbox4x4.transpose.translation);% + mb.check_in(new Array(corner.x, corner.y, corner.z));% + corner.set(bbox.min.x, bbox.max.y, bbox.min.z);% + bbox4x4.setView(corner, dir, up);% + bbox4x4=trans.multiply(bbox4x4.transpose);% + corner.set(bbox4x4.transpose.translation);% + mb.check_in(new Array(corner.x, corner.y, corner.z));% + corner.set(bbox.max.x, bbox.min.y, bbox.min.z);% + bbox4x4.setView(corner, dir, up);% + bbox4x4=trans.multiply(bbox4x4.transpose);% + corner.set(bbox4x4.transpose.translation);% + mb.check_in(new Array(corner.x, corner.y, corner.z));% + corner.set(bbox.max.x, bbox.min.y, bbox.max.z);% + bbox4x4.setView(corner, dir, up);% + bbox4x4=trans.multiply(bbox4x4.transpose);% + corner.set(bbox4x4.transpose.translation);% + mb.check_in(new Array(corner.x, corner.y, corner.z));% + corner.set(bbox.max.x, bbox.max.y, bbox.min.z);% + bbox4x4.setView(corner, dir, up);% + bbox4x4=trans.multiply(bbox4x4.transpose);% + corner.set(bbox4x4.transpose.translation);% + mb.check_in(new Array(corner.x, corner.y, corner.z));% + }% + %compute the smallest enclosing bounding sphere + mb.build();% + %bounding sphere centre + var coo=new annot3D['\@MXV@label'].context3D.Vector3();% + coo.set((mb.center())[0], (mb.center())[1], (mb.center())[2]);% + %radius of orbit + var roo=mb.radius()/ Math.sin(aac * Math.PI/ 360.);% + %result string + var res='';% + var spc=String.fromCharCode(32);% + var nl=String.fromCharCode(10);% + var charht=2;% + var multiln=false;% + res+=util.printf(% + '3Droo=\%s,',(roo < 1.001e-6 ? util.printf('\%.18f', roo): roo) + );% + if(util.printf('\%.5f', aac)!=30){% + charht+=2;multiln=true; + res+=util.printf(nl+'3Daac=\%s,',% + (Math.abs(aac) < 1.001e-6 && Math.abs(aac) > 0 ?% + util.printf('\%.18f', aac): aac)% + );% + }% + if(coo.length){% + charht+=2;multiln=true; + res+=util.printf(nl+'3Dcoo=\%s' + spc + '\%s' + spc + '\%s,',% + (Math.abs(coo.x) < 1.001e-6 && Math.abs(coo.x) > 0 ?% + util.printf('\%.18f', coo.x): coo.x),% + (Math.abs(coo.y) < 1.001e-6 && Math.abs(coo.y) > 0 ?% + util.printf('\%.18f', coo.y): coo.y),% + (Math.abs(coo.z) < 1.001e-6 && Math.abs(coo.z) > 0 ?% + util.printf('\%.18f', coo.z): coo.z)% + );% + }% + % change camera position and target accordingly + camera.fov=aac*Math.PI/180;% + camera.targetPosition.set(coo);% + var c2c=camera.position.subtract(coo);% + c2c.normalize();% + camera.position.set(coo.add(c2c.scale(roo)));% + %output settings + var x=(Math.abs(c2c.x) < 1e-12 ? 0 : c2c.x);% + var y=(Math.abs(c2c.y) < 1e-12 ? 0 : c2c.y);% + var z=(Math.abs(c2c.z) < 1e-12 ? 0 : c2c.z);% + if(!(x==0 && y==-1 && z==0)){% + charht+=2;multiln=true; + res+=util.printf(nl+'3Dc2c=\%s' + spc + '\%s' + spc + '\%s,',% + (Math.abs(x) < 1.001e-6 && Math.abs(x) > 0 ?% + util.printf('\%.18f', x): x),% + (Math.abs(y) < 1.001e-6 && Math.abs(y) > 0 ?% + util.printf('\%.18f', y): y),% + (Math.abs(z) < 1.001e-6 && Math.abs(z) > 0 ?% + util.printf('\%.18f', z): z)% + );% + }% + %determine the camera roll + var roll = camera.roll*180/Math.PI;% + if(util.printf('\%.4f', roll)!=0){% + charht+=2;multiln=true; + res+=util.printf(nl+'3Droll=\%s,',roll);% + }% + %determine background colour + rgb=scene.background.getColor();% + if(rgb.r!=1.0||rgb.g!=1.0||rgb.b!=1.0){% + charht+=2;multiln=true; + res+=util.printf(nl+'3Dbg=\%f' + spc + '\%f' + spc + '\%f,',% + rgb.r, rgb.g, rgb.b);% + }% + %determine lighting scheme + switch(scene.lightScheme){% + case scene.LIGHT_MODE_FILE: + curlights='Artwork';break; + case scene.LIGHT_MODE_NONE: + curlights='None';break; + case scene.LIGHT_MODE_WHITE: + curlights='White';break; + case scene.LIGHT_MODE_DAY: + curlights='Day';break; + case scene.LIGHT_MODE_NIGHT: + curlights='Night';break; + case scene.LIGHT_MODE_BRIGHT: + curlights='Hard';break; + case scene.LIGHT_MODE_RGB: + curlights='Primary';break; + case scene.LIGHT_MODE_BLUE: + curlights='Blue';break; + case scene.LIGHT_MODE_RED: + curlights='Red';break; + case scene.LIGHT_MODE_CUBE: + curlights='Cube';break; + case scene.LIGHT_MODE_CAD: + curlights='CAD';break; + case scene.LIGHT_MODE_HEADLAMP: + curlights='Headlamp';break; + }% + if(curlights!='Artwork'){% + charht+=2;multiln=true; + res+=util.printf(nl+'3Dlights=\%s,', curlights);% + }% + %determine global render mode + switch(scene.renderMode){% + case scene.RENDER_MODE_BOUNDING_BOX: + currender='BoundingBox';break; + case scene.RENDER_MODE_TRANSPARENT_BOUNDING_BOX: + currender='TransparentBoundingBox';break; + case scene.RENDER_MODE_TRANSPARENT_BOUNDING_BOX_OUTLINE: + currender='TransparentBoundingBoxOutline';break; + case scene.RENDER_MODE_VERTICES: + currender='Vertices';break; + case scene.RENDER_MODE_SHADED_VERTICES: + currender='ShadedVertices';break; + case scene.RENDER_MODE_WIREFRAME: + currender='Wireframe';break; + case scene.RENDER_MODE_SHADED_WIREFRAME: + currender='ShadedWireframe';break; + case scene.RENDER_MODE_SOLID: + currender='Solid';break; + case scene.RENDER_MODE_TRANSPARENT: + currender='Transparent';break; + case scene.RENDER_MODE_SOLID_WIREFRAME: + currender='SolidWireframe';break; + case scene.RENDER_MODE_TRANSPARENT_WIREFRAME: + currender='TransparentWireframe';break; + case scene.RENDER_MODE_ILLUSTRATION: + currender='Illustration';break; + case scene.RENDER_MODE_SOLID_OUTLINE: + currender='SolidOutline';break; + case scene.RENDER_MODE_SHADED_ILLUSTRATION: + currender='ShadedIllustration';break; + case scene.RENDER_MODE_HIDDEN_WIREFRAME: + currender='HiddenWireframe';break; + }% + if(currender!='Solid'){% + charht+=2;multiln=true; + res+=util.printf(nl+'3Drender=\%s,', currender);% + }% + var settings={% + initialize: function(dialog){% + dialog.load({% + 'text': res% + });% + },% + description: {% + name: '3D' + spc + 'Camera' + spc + 'Settings',% + elements: [% + {% + type: 'static_text',% + name: 'Copy' + spc + 'and' + spc + 'paste' + spc +% + 'the' + spc + 'following' + spc + 'to' + spc +% + 'the' + spc + 'option' + spc + 'list' + spc +% + 'of' + spc + spc + '\string\\\string\\includemovie!'% + },% + {% + type: 'edit_text',% + item_id: 'text',% + alignment: 'align_fill',% + multiline: multiln,% + char_width: 80,% + char_height: charht,% + readonly: true% + },% + {% + type: 'ok',% + ok_name: 'Close'% + }% + ]% + }% + };% + app.execDialog(settings);% + }catch(e){% + var spc=String.fromCharCode(32);% + app.alert('Error' + spc + 'while' + spc + 'executing' + spc +% + '3Dcalculate:' + spc + e);% + }% + }% + \fi% + %create stream from user provided JavaScript file + \ifx\@MXV@jscriptiiidfile\@empty\else% + \ifthenelse{% create only once + \equal{\@MXV@getlabelvalue{\pdfmdfivesum file {\@MXV@jscriptiiidfile}}}{undefined}% + }{% + \ifpdf% + \pdfobj stream file {\@MXV@jscriptiiidfile}% + \pdfrefobj\pdflastobj% + \edef\@MXV@userjscriptiiidstream{\the\pdflastobj\space 0 R}% + \@MXV@newlabel{\pdfmdfivesum file {\@MXV@jscriptiiidfile}}{\the\pdflastobj}% + \else% + \pdfmark{% + pdfmark=/OBJ,% + Raw={% + /_objdef {linkuserjscriptiiid\the\@MXV@links}% + /type/stream% + }% + }% + \pdfmark{% + pdfmark=/PUT,% + Raw={% + {linkuserjscriptiiid\the\@MXV@links}% + (\@MXV@jscriptiiidfile) (r) file% + }% + }% + \edef\@MXV@userjscriptiiidstream{% + {linkuserjscriptiiid\the\@MXV@links}% + }% + \@MXV@newlabel{\pdfmdfivesum file {\@MXV@jscriptiiidfile}}% + {linkuserjscriptiiid\the\@MXV@links}% + \fi% + }{% + \ifpdf% + \edef\@MXV@userjscriptiiidstream{% + \@MXV@getlabelvalue{\pdfmdfivesum file {\@MXV@jscriptiiidfile}}\space 0 R% + }% + \else% + \edef\@MXV@userjscriptiiidstream{% + {\@MXV@getlabelvalue{\pdfmdfivesum file {\@MXV@jscriptiiidfile}}}% + }% + \fi% + }% + \fi% + \edef\@MXV@jscriptiiidaction{% + /Next <<% + /S/JavaScript% + /JS (\@MXV@linkjscriptiiid)% + \ifx\@MXV@jscriptiiidfile\@empty\else% + /Next <<% + /S/JavaScript% + /JS \@MXV@userjscriptiiidstream% user provided script + >>% + \fi% + >>% + }% + }{\edef\@MXV@jscriptiiidaction{}}% + }{% #### 2D #### + \setkeys{MXV@user}{#1}% + %retrieve original settings + \ifthenelse{\equal{\@MXV@getlabelvalue{@MXV@\@MXV@label.mouse}}{true}}{% + \setboolean{@MXV@mouse}{true}% + }{% + \setboolean{@MXV@mouse}{false}% + }% + \edef\@MXV@ctrls{\@MXV@getlabelvalue{@MXV@\@MXV@label.showUI}}% + \edef\@MXV@palindrome{\@MXV@getlabelvalue{@MXV@\@MXV@label.palindrome}}% + \edef\@MXV@repeat{\@MXV@getlabelvalue{@MXV@\@MXV@label.repeat}}% + \edef\@MXV@rate{\@MXV@getlabelvalue{@MXV@\@MXV@label.rate}}% + \edef\@MXV@startat{\@MXV@getlabelvalue{@MXV@\@MXV@label.startAt}}% + \edef\@MXV@endat{\@MXV@getlabelvalue{@MXV@\@MXV@label.endAt}}% + \edef\@MXV@volume{\@MXV@getlabelvalue{@MXV@\@MXV@label.volume}}% + \if@MXV@linkreset\else% + \setkeys{MXV@user}{#1}%override with new settings + \fi% + % + \edef\@MXV@operation{}% + % + %get the player ID + \edef\@MXV@currplayer{\@MXV@getlabelvalue{@MXV@\@MXV@label.playerid}}% + % + %see whether a sound inclusion is being referenced + \ifthenelse{\equal{\@MXV@getlabelvalue{@MXV@\@MXV@label.issound}}{true}}{% + \setboolean{@MXV@issound}{true}% + }{% + \setboolean{@MXV@issound}{false}% + }% + % + %create /OP and /JS entries + \if@MXV@linkplay% + \edef\@MXV@operation{% + /OP 0% + /JS (% + if(focusonplayer==undefined){% + var focusonplayer=0; %shared by all annots + }% + \@MXV@settings{\@MXV@ctrls}{\@MXV@palindrome}{\@MXV@repeat}% + {\@MXV@rate}{\@MXV@startat}{\@MXV@endat}{\@MXV@volume}% + \@MXV@events{\@MXV@currplayer}% + {\if@MXV@mouse true\else false\fi}% + {true}% + \if@MXV@requirereopen\else + try{% + \ifx\@MXV@@startat\@empty + player\@MXV@currplayer.seek(% + player\@MXV@currplayer.settings.startAt% + ); + \else + player\@MXV@currplayer.seek(\@MXV@@startat); + \fi + player\@MXV@currplayer.play(); + \ifx\@MXV@@startat\@empty + player\@MXV@currplayer.seek(% + player\@MXV@currplayer.settings.startAt% + ); + \else + player\@MXV@currplayer.seek(\@MXV@@startat); + \fi + }% + catch(e)\@charlb% + \fi% + try{% + if(player\@MXV@currplayer.isOpen){% + player\@MXV@currplayer.close(% + app.media.closeReason.general); + player\@MXV@currplayer=null; + }% + }% + catch(e){}% + % + try{% + var player\@MXV@currplayer=app.media.openPlayer({% + settings: settings,% + events: events% + });% + }% + catch (e){}% + \if@MXV@requirereopen\else + \@charrb% + \fi% + )% + }% + \fi% + \if@MXV@linkresume% resume/pause + \edef\@MXV@operation{% + /OP 3% + /JS (% + try{% + \if@MXV@issound\else player\@MXV@currplayer.visible=true;\fi% + if(!player\@MXV@currplayer.isPlaying){% + player\@MXV@currplayer.settings.privateData.paused=false; + player\@MXV@currplayer.play(); + if(!player\@MXV@currplayer.isPlaying){% + %media at end will restart from beginning + if( + player\@MXV@currplayer.settings.startAt.time + || player\@MXV@currplayer.settings.startAt.frame + || player\@MXV@currplayer.settings.startAt.marker + || player\@MXV@currplayer.id == + 'vnd.adobe.swname:AAPL_QuickTime' + ){ + player\@MXV@currplayer.seek( + player\@MXV@currplayer.settings.startAt); + }else{ + player\@MXV@currplayer.stop(); + } + player\@MXV@currplayer.play(); + }% + }% + else{% + player\@MXV@currplayer.pause(); + player\@MXV@currplayer.settings.privateData.paused=true; + }% + }% + catch(e){% open new player if not yet open + if(focusonplayer==undefined){% + var focusonplayer=0; %shared by all annots + }% + \@MXV@settings{\@MXV@ctrls}{\@MXV@palindrome}{\@MXV@repeat}% + {\@MXV@rate}{\@MXV@startat}{\@MXV@endat}{\@MXV@volume}% + \@MXV@events{\@MXV@currplayer}% + {\if@MXV@mouse true\else false\fi}% + {true}% + try{% + var player\@MXV@currplayer=app.media.openPlayer({% + settings: settings,% + events: events% + }); + }% + catch (e){}% + }% + )% + }% + \fi% + \if@MXV@linkstop% + \edef\@MXV@operation{% + /OP 1% + /JS (% + try{% + if(!player\@MXV@currplayer.isPlaying){% + player\@MXV@currplayer.settings.privateData.paused=false; + player\@MXV@currplayer.play(); + }% + player\@MXV@currplayer.stop(); + if( + player\@MXV@currplayer.settings.startAt.time + || player\@MXV@currplayer.settings.startAt.frame + || player\@MXV@currplayer.settings.startAt.marker + || player\@MXV@currplayer.id == + 'vnd.adobe.swname:AAPL_QuickTime' + ){ + player\@MXV@currplayer.seek(% + player\@MXV@currplayer.settings.startAt); + } + }% + catch(e){}% + )% + }% + \fi% + \if@MXV@linkpause% pause/resume + \edef\@MXV@operation{% + /OP 2% + /JS (% + try{% + \if@MXV@issound\else player\@MXV@currplayer.visible=true;\fi% + if(!player\@MXV@currplayer.isPlaying){% + player\@MXV@currplayer.settings.privateData.paused=false; + player\@MXV@currplayer.play(); + if(!player\@MXV@currplayer.isPlaying){% + %media at end will restart from beginning + if( + player\@MXV@currplayer.settings.startAt.time + || player\@MXV@currplayer.settings.startAt.frame + || player\@MXV@currplayer.settings.startAt.marker + || player\@MXV@currplayer.id == + 'vnd.adobe.swname:AAPL_QuickTime' + ){ + player\@MXV@currplayer.seek( + player\@MXV@currplayer.settings.startAt); + }else{ + player\@MXV@currplayer.stop(); + } + player\@MXV@currplayer.play(); + }% + }% + else{% + player\@MXV@currplayer.pause(); + player\@MXV@currplayer.settings.privateData.paused=true; + }% + }% + catch(e){% open new player if not yet open + if(focusonplayer==undefined){% + var focusonplayer=0; %shared by all annots + }% + \@MXV@settings{\@MXV@ctrls}{\@MXV@palindrome}{\@MXV@repeat}% + {\@MXV@rate}{\@MXV@startat}{\@MXV@endat}{\@MXV@volume}% + \@MXV@events{\@MXV@currplayer}% + {\if@MXV@mouse true\else false\fi}% + {true}% + try{% + var player\@MXV@currplayer=app.media.openPlayer({% + settings: settings,% + events: events% + }); + }% + catch (e){}% + }% + )% + }% + \fi% + \if@MXV@linkclose% + \edef\@MXV@operation{% + /OP 1% + /JS (% + try{% + player\@MXV@currplayer.close(% + app.media.closeReason.general); + player\@MXV@currplayer=null; + }% + catch(e){}% + )% + }% + \fi% + }% + \fi% + \fi% + % + \ifpdf% + \ifthenelse{\isundefined{\@pdfborder}}{% + \def\@MXV@linkattr{}% + }{% + \edef\@MXV@linkattr{% + \if@MXV@beamer% + \@MXV@pdfborder% + \else% + /Border [\@pdfborder]% + \fi% + /C [\@linkbordercolor]% + /H \@pdfhighlight% + }% + }% + % + \pdfstartlink% + attr{\@MXV@linkattr}% + user{% + /Subtype /Link% + /A <<% + /S/GoTo% + /D (@MXV@\@MXV@@label)% + \if@MXV@@draft\else% + \if@MXV@externalviewer\else% + \if@MXV@iiid% + \ifx\@MXV@iiidview\@empty\else% + /Next <<% + /S/GoTo3DView% + /TA \@MXV@getlabelvalue{@MXV@\@MXV@@label.annot}\space 0 R% + /V \@MXV@iiidview% + \fi% + \@MXV@jscriptiiidaction% + \ifx\@MXV@iiidview\@empty\else% + >>% + \fi% + \else% + /Next <<% + /S/Rendition% + /R \@MXV@getlabelvalue{@MXV@\@MXV@@label.rendition}\space 0 R% + /AN \@MXV@getlabelvalue{@MXV@\@MXV@@label.annot}\space 0 R% + \@MXV@operation% + >>% + \fi% + \fi% + \fi% + >>% + }% + \usebox{\@MXV@textbox}% write out text box + \pdfendlink% + \else% + \pdfmark[{\usebox{\@MXV@textbox}}]{% + pdfmark=/ANN,% + Subtype=/Link,% + Color=\@linkbordercolor,% + AcroHighlight=\@pdfhighlight,% + Raw={% + \@MXV@pdfborder% + /_objdef {linkannot\the\@MXV@links}% + /Action <<% + /S/GoTo% + /D/@MXV@\@MXV@@label% + \if@MXV@@draft\else% + \if@MXV@externalviewer\else% + \if@MXV@iiid% + \ifx\@MXV@iiidview\@empty\else% + /Next <<% + /S/GoTo3DView% + /TA {3Dannot\@MXV@getlabelvalue{@MXV@\@MXV@@label.annot}}% + /V \@MXV@iiidview% + \fi% + \@MXV@jscriptiiidaction% + \ifx\@MXV@iiidview\@empty\else% + >>% + \fi% + \else% + /Next <<% + /S /Rendition% + /R {mediarendition\@MXV@getlabelvalue{@MXV@\@MXV@@label.annotid}}% + /AN {screenannot\@MXV@getlabelvalue{@MXV@\@MXV@@label.annot}}% + \@MXV@operation% + >>% + \fi% + \fi% + \fi% + >>% + }% + }% + \fi% + }% + }% +} + +%set to true for certain \movieref options, which require the media player to +%be re-opened +\newboolean{@MXV@requirereopen} + +%standard keys to be processed first +%key definitions for options to \includemovie +\define@key{MXV@user}{draft}[true]{% + \setboolean{@MXV@@draft}{#1}% +} +\define@key{MXV@user}{final}[true]{% + \ifthenelse{\equal{#1}{true}}{% + \setboolean{@MXV@@draft}{false}% + }{% + \setboolean{@MXV@@draft}{true}% + }% +} +\define@key{MXV@user}{label}{%for use with movieref + \gdef\@MXV@label{#1}% +} +\define@key{MXV@user}{controls}[true]{% + \setboolean{@MXV@requirereopen}{true}% + \xdef\@MXV@ctrls{, showUI: #1}% + \xdef\@MXV@@ctrls{/C #1}% + \ifthenelse{\boolean{@MXV@iiiDfeat}}{% + \gdef\@MXV@iiidtoolb{/TB #1}% + }{}% +} +\define@key{MXV@user}{toolbar}[true]{% + \xdef\@MXV@ctrls{, showUI: #1}% + \xdef\@MXV@@ctrls{/C #1}% + \ifthenelse{\boolean{@MXV@iiiDfeat}}{% + \gdef\@MXV@iiidtoolb{/TB #1}% + }{}% +} +\define@key{MXV@user}{volume}{% + \def\@MXV@@volume{/V #1}% + \def\@MXV@volume{#1}% + \setboolean{@MXV@requirereopen}{true}% +} +\define@key{MXV@user}{mimetype}{% + \ifthenelse{\equal{#1}{model/u3d}}{% + \ifthenelse{\boolean{@MXV@iiiDfeat}}{% + \setboolean{@MXV@iiid}{true}% + \xdef\@MXV@iiidsubtype{U3D}% + }{\@MXV@neediiiD}% + }{}% + \def\@MXV@mime{#1}% +} +\define@key{MXV@user}{playerid}{% + \def\@MXV@player{% + /PL<>>>]>>% + }% +} +\define@key{MXV@user}{autoplay}[true]{% + \setboolean{@MXV@autoplay}{#1}% + \if@MXV@autoplay% + \setboolean{@MXV@autoresume}{false}% + \fi% +} +\define@key{MXV@user}{autostop}[true]{% + \setboolean{@MXV@autostop}{#1}% + \if@MXV@autostop% + \setboolean{@MXV@autopause}{false}% + \fi% +} +\define@key{MXV@user}{autoresume}[true]{% + \setboolean{@MXV@autoresume}{#1}% + \if@MXV@autoresume% + \setboolean{@MXV@autoplay}{false}% + \setboolean{@MXV@autoclose}{false}% + \fi% +} +\define@key{MXV@user}{autopause}[true]{% + \setboolean{@MXV@autopause}{#1}% + \if@MXV@autopause% + \setboolean{@MXV@autostop}{false}% + \setboolean{@MXV@autoclose}{false}% + \fi% +} +\define@key{MXV@user}{autoclose}[true]{% + \setboolean{@MXV@autoclose}{#1}% + \if@MXV@autoclose% + \setboolean{@MXV@autostop}{false}% + \setboolean{@MXV@autopause}{false}% + \fi% +} +\define@key{MXV@user}{continue}[true]{% + \setboolean{@MXV@autostop}{false}% + \setboolean{@MXV@autopause}{false}% + \setboolean{@MXV@autoclose}{false}% +} +\define@key{MXV@user}{open}[true]{% + %no longer supported; once open, media remains loaded + %to avoid reloading when media is to be played again +} +\define@key{MXV@user}{mouse}[true]{% + \setboolean{@MXV@mouse}{#1}% + \setboolean{@MXV@requirereopen}{true}% + \ifthenelse{\equal{false}{#1}\AND\boolean{@MXV@iiiDfeat}}{% + \def\@MXV@iiidia{/3DI #1}% + }{}% +} +\define@key{MXV@user}{palindrome}[true]{% + \xdef\@MXV@palindrome{, palindrome: #1}% + \setboolean{@MXV@requirereopen}{true}% + \ifthenelse{\boolean{@MXV@iiiDfeat}}{% + \gdef\@MXV@iiidpalindrome{/Subtype/Oscillating}% + }{}% +} +\define@key{MXV@user}{rate}{% + \setboolean{@MXV@requirereopen}{true}% + \xdef\@MXV@rate{, rate: #1}% + \ifthenelse{\boolean{@MXV@iiiDfeat}}{% + \gdef\@MXV@iiidrate{/TM #1}% + }{}% +} +\define@key{MXV@user}{repeat}[Infinity]{% + \setboolean{@MXV@requirereopen}{true}% + \ifthenelse{% + \equal{#1}{Infinity}\OR% + \equal{#1}{0}% + }{% + \xdef\@MXV@repeat{, repeat: Infinity}% + \xdef\@MXV@@repeat{/RC 0}% + }{% + \xdef\@MXV@repeat{, repeat: #1}% + \xdef\@MXV@@repeat{/RC #1}% + }% + \ifthenelse{\boolean{@MXV@iiiDfeat}}{% + \ifthenelse{\equal{#1}{Infinity}}{% + \global\@MXV@iiidrepeat=-1% + }{% + \global\@MXV@iiidrepeat=#1% + }% + }{}% +} +\define@key{MXV@user}{startat}{% + \xdef\@MXV@startat{, startAt: {#1}}% + \xdef\@MXV@@startat{{#1}}% +} +\define@key{MXV@user}{endat}{% + \setboolean{@MXV@requirereopen}{true}% + \xdef\@MXV@endat{, endAt: {#1}}% +} +\define@key{MXV@user}{poster}[true]{% + \ifthenelse{\equal{#1}{true}}{% option without arg + \setboolean{@MXV@runposter}{true}% + }{% + \def\@MXV@box##1##2##3{% + \ifpdf% + \mbox{\pdfximage width ##1 height ##2 depth ##3 {#1}}% + \pdfrefximage\pdflastximage% + \else% + \ifthenelse{\isundefined{\includegraphics}}{\@MXV@missing{graphics}}{}% + \@MXV@totalheight=##2% + \advance\@MXV@totalheight by ##3% + \raisebox{-##3}[##2][##3]{% + \includegraphics[% + width=##1,height=##2,totalheight=\@MXV@totalheight,clip]{#1}% + }% + \fi% + }% + }% +} +\define@key{MXV@user}{externalviewer}[true]{% + \setboolean{@MXV@externalviewer}{#1}% +} +\define@key{MXV@user}{inline}[true]{% + \if@MXV@url% + \setboolean{@MXV@inline}{false}% + \else% + \setboolean{@MXV@inline}{#1}% + \fi% + \if@MXV@inline\else% + \setboolean{@MXV@attachment}{false}% + \fi% +} +\define@key{MXV@user}{url}[true]{% + \setboolean{@MXV@url}{#1}% + \if@MXV@url% + \setboolean{@MXV@inline}{false}% + \setboolean{@MXV@attachment}{false}% + \def\@MXV@fsentry{/FS /URL}% + \fi% +} +\define@key{MXV@user}{attach}[true]{% + \setboolean{@MXV@attachment}{#1}% + \if@MXV@attachment% + \setboolean{@MXV@inline}{true}% + \fi% +} +\define@key{MXV@user}{text}{% + \setboolean{@MXV@boxopt}{true}% + \savebox{\@MXV@textbox}{#1}% + \@MXV@width=\wd\@MXV@textbox% + \@MXV@height=\ht\@MXV@textbox% + \@MXV@depth=\dp\@MXV@textbox% +} +\define@key{MXV@user}{textoverposter}[true]{% + \setboolean{@MXV@textoverposter}{#1}% +} +\define@key{MXV@user}{depth}{%set depth of display area + \gdef\@MXV@boxdepth{#1}% +} +%3D specific options +\define@key{MXV@user}{3Dbg}{% + \ifthenelse{\boolean{@MXV@iiiDfeat}}{% + \def\@MXV@defaultbg{#1}% + \def\@MXV@background{/BG<>}% + }{\@MXV@neediiiD}% +} +\define@key{MXV@user}{3Djscript}{% + \ifthenelse{\boolean{@MXV@iiiDfeat}}{% + \IfFileExists{#1}{% + \def\@MXV@jscriptiiidfile{#1}% + }{% + \PackageError{movie15}{Script file `#1' cannot be opened for embedding% + }{% + Make sure file `#1' exists and is readable!% + }% + }% + }{\@MXV@neediiiD}% +} +\define@key{MXV@user}{3Dcoo}{% + \ifthenelse{\boolean{@MXV@iiiDfeat}}{% + \def\@MXV@coo{#1}% + \setboolean{@MXV@defaultviewprovided}{true}% + }{\@MXV@neediiiD}% +} +\define@key{MXV@user}{3Dc2c}{% + \ifthenelse{\boolean{@MXV@iiiDfeat}}{% + \def\@MXV@ctoc{#1}% + \setboolean{@MXV@defaultviewprovided}{true}% + }{\@MXV@neediiiD}% +} +\define@key{MXV@user}{3Droo}{% + \ifthenelse{\boolean{@MXV@iiiDfeat}}{% + \def\@MXV@roo{#1}% + \setboolean{@MXV@defaultviewprovided}{true}% + }{\@MXV@neediiiD}% +} +\define@key{MXV@user}{3Daac}{% + \ifthenelse{\boolean{@MXV@iiiDfeat}}{% + \def\@MXV@aac{#1}% + \setboolean{@MXV@defaultviewprovided}{true}% + }{\@MXV@neediiiD}% +} +\define@key{MXV@user}{3Droll}{% + \ifthenelse{\boolean{@MXV@iiiDfeat}}{% + \def\@MXV@roll{#1}% + \setboolean{@MXV@defaultviewprovided}{true}% + }{\@MXV@neediiiD}% +} +\define@key{MXV@user}{3Dviews}{% + \ifthenelse{\boolean{@MXV@iiiDfeat}}{% + \IfFileExists{#1}{% + \def\@MXV@viewsfileii{}% + \def\@MXV@viewsfile{#1}% + }{% + \PackageError{movie15}{3D views file `#1' cannot be opened% + }{% + Make sure file `#1' exists and is readable!% + }% + }% + }{\@MXV@neediiiD}% +} +\define@key{MXV@user}{3Dviews2}{% + \ifthenelse{\boolean{@MXV@iiiDfeat}}{% + \IfFileExists{#1}{% + \def\@MXV@viewsfile{}% + \def\@MXV@viewsfileii{#1}% + }{% + \PackageError{movie15}{3D views file `#1' cannot be opened% + }{% + Make sure file `#1' exists and is readable!% + }% + }% + }{\@MXV@neediiiD}% +} +\define@key{MXV@user}{3Dlights}{% + \ifthenelse{\boolean{@MXV@iiiDfeat}}{% + \gdef\@MXV@defaultlights{#1}% + \gdef\@MXV@lights{/LS <>}% + }{\@MXV@neediiiD}% +} +\define@key{MXV@user}{3Drender}{% + \ifthenelse{\boolean{@MXV@iiiDfeat}}{% + \gdef\@MXV@defaultrender{#1}% + \gdef\@MXV@render{/RM <>}% + }{\@MXV@neediiiD}% +} +%options for \movieref command +\define@key{MXV@user}{play}[true]{% + \setboolean{@MXV@linkplay}{#1}% + \if@MXV@linkplay% + \setboolean{@MXV@linkpause}{false}% + \setboolean{@MXV@linkresume}{false}% + \setboolean{@MXV@linkstop}{false}% + \setboolean{@MXV@linkclose}{false}% + \fi% +} +\define@key{MXV@user}{pause}[true]{% + \setboolean{@MXV@linkpause}{#1}% + \if@MXV@linkpause% + \setboolean{@MXV@linkresume}{false}% + \setboolean{@MXV@linkstop}{false}% + \setboolean{@MXV@linkclose}{false}% + \setboolean{@MXV@linkplay}{false}% + \fi% +} +\define@key{MXV@user}{resume}[true]{% + \setboolean{@MXV@linkresume}{#1}% + \if@MXV@linkresume% + \setboolean{@MXV@linkpause}{false}% + \setboolean{@MXV@linkstop}{false}% + \setboolean{@MXV@linkclose}{false}% + \setboolean{@MXV@linkplay}{false}% + \fi% +} +\define@key{MXV@user}{stop}[true]{% + \setboolean{@MXV@linkstop}{#1}% + \if@MXV@linkstop% + \setboolean{@MXV@linkpause}{false}% + \setboolean{@MXV@linkresume}{false}% + \setboolean{@MXV@linkclose}{false}% + \setboolean{@MXV@linkplay}{false}% + \fi% +} +\define@key{MXV@user}{close}[true]{% + \setboolean{@MXV@linkclose}{#1}% + \if@MXV@linkclose% + \setboolean{@MXV@linkpause}{false}% + \setboolean{@MXV@linkresume}{false}% + \setboolean{@MXV@linkstop}{false}% + \setboolean{@MXV@linkplay}{false}% + \fi% +} +\define@key{MXV@user}{reset}[true]{% + \setboolean{@MXV@linkreset}{#1}% + \if@MXV@linkreset% + \setboolean{@MXV@requirereopen}{true}% + \fi% +} +\define@key{MXV@user}{default}[true]{% synonyme for `reset' + \setboolean{@MXV@linkreset}{#1}% + \if@MXV@linkreset% + \setboolean{@MXV@requirereopen}{true}% + \fi% +} +\define@key{MXV@user}{3Dviewindex}{% + \ifthenelse{\boolean{@MXV@iiiDfeat}}{% + \ifthenelse{% + \equal{#1}{F}% + \OR\equal{#1}{L}% + \OR\equal{#1}{N}% + \OR\equal{#1}{P}% + \OR\equal{#1}{D}% + }{% + \gdef\@MXV@iiidview{/#1}% any of F, L, N, P, D + }{% + \gdef\@MXV@iiidview{#1}% number (index) + }% + \setboolean{@MXV@defaultviewprovided}{false}% + }{\@MXV@neediiiD}% +} +\define@key{MXV@user}{3Dcalculate}[current]{% + %calculate optimal 3D settings for roo and coo for a given aac + \ifthenelse{\boolean{@MXV@iiiDfeat}}{% + \gdef\@MXV@calc{#1}% + }{\@MXV@neediiiD}% +} +\define@key{MXV@user}{3Dgetview}[true]{% + %print current 3D camera settings + \ifthenelse{\boolean{@MXV@iiiDfeat}}{% + \setboolean{@MXV@iiidgetview}{#1}% + }{\@MXV@neediiiD}% +} +\define@key{MXV@user}{3Dresource}{% + \ifthenelse{\boolean{@MXV@iiiDfeat}}{% + \IfFileExists{#1}{% + \setboolean{@MXV@resource}{true}% + \xdef\@MXV@iiidopt{3Dresource=#1, \@MXV@iiidopt}% + }{% + \PackageError{movie15}{3D resource file `#1' cannot be opened% + }{% + Make sure file `#1' exists and is readable!% + }% + }% + }{\@MXV@neediiiD}% +} + +%compatibility options for \movie and \hyperlinkmovie commands +\define@key{MXV@user}{borderwidth}{% + %ignored; acroread doesn't draw borders around screen annots anyway +} +\define@key{MXV@user}{height}{%set height of display area + \gdef\@MXV@boxheight{#1}% +} +\define@key{MXV@user}{width}{%set width of display area + \gdef\@MXV@boxwidth{#1}% +} +\define@key{MXV@user}{autostart}[true]{% + \xdef\@MXV@autostart{, autoplay=#1}% +} +\define@key{MXV@user}{loop}[Infinity]{% + \xdef\@MXV@loop{, repeat=#1}% +} +\define@key{MXV@user}{once}[]{% + \xdef\@MXV@loop{, repeat=1}% +} +\define@key{MXV@user}{showcontrols}[true]{% + \xdef\@MXV@showcontrols{, controls=#1}% +} +\define@key{MXV@user}{start}{% + \gdef\@MXV@starttime##1s{% + \global\@MXV@start=##1pt% + }% + \@MXV@starttime #1% +} +\define@key{MXV@user}{duration}{% + \gdef\@MXV@durationtime##1s{% + \global\@MXV@end=##1pt% + }% + \@MXV@durationtime #1% +} + +%options to be passed to internal macro \@MXV@includeiiid +\define@key{MXV@iiid}{3Dresource}{% + \@MXV@addresource{#1}% +} + +%compatibility macros +\providecommand\movie[3][]{% + \leavevmode% + \@MXV@reset% + \def\@MXV@autostart{}\def\@MXV@loop{}\def\@MXV@showcontrols{}% + \def\@MXV@starttime{}\def\@MXV@durationtime{}% + \setkeys{MXV@user}{#1}% + % + %sanity checks + \if@MXV@boxopt% + \PackageError{movie15}{% + Option `text' cannot be used with command `\string\movie'.\MessageBreak + Instead, put text into the 1st argument of `\string\movie' + }{}% + \fi% + % + \ifx\@MXV@durationtime\@empty\else\ifx\@MXV@startat\@empty\else% + \PackageError{movie15}{% + Options `startat' and `duration' cannot be used\MessageBreak + together.\MessageBreak + Possible combinations are `startat'/`endat',\MessageBreak + `start'/`endat' or `start'/`duration' + }{}% + \fi\fi% + % + %option list + \edef\@MXV@movieoptions{#1\@MXV@autostart\@MXV@loop\@MXV@showcontrols}% + % + %determine playback section + \ifx\@MXV@starttime\@empty\else% + \edef\@MXV@movieoptions{\@MXV@movieoptions, % + startat=time:\strip@pt\@MXV@start}% + \fi% + \ifx\@MXV@durationtime\@empty\else% + \advance\@MXV@end by \@MXV@start% + \edef\@MXV@movieoptions{\@MXV@movieoptions, % + endat=time:\strip@pt\@MXV@end}% + \fi% + % + %text option from 2nd argument + \savebox{\@MXV@textbox}{#2}% + \edef\@MXV@movieoptions{[\@MXV@movieoptions, text={\noexpand\usebox{% + \noexpand\@MXV@textbox}}]}% + \expandafter% + \includemovie\@MXV@movieoptions{\@MXV@boxwidth}{\@MXV@boxheight}{#3}% +} + +\newcommand\hyperlinkmovie[3][]{% + \leavevmode% + \@MXV@reset% + \def\@MXV@autostart{}\def\@MXV@loop{}\def\@MXV@showcontrols{}% + \def\@MXV@starttime{}\def\@MXV@durationtime{}% + \setkeys{MXV@user}{#1}% + % + %sanity check + \ifx\@MXV@durationtime\@empty\else\ifx\@MXV@startat\@empty\else% + \PackageError{movie15}{% + Options `startat' and `duration' cannot be used\MessageBreak + together.\MessageBreak + Possible combinations are `startat'/`endat',\MessageBreak + `start'/`endat' or `start'/`duration' + }{}% + \fi\fi% + % + %option list + \edef\@MXV@movieoptions{#1\@MXV@autostart\@MXV@loop\@MXV@showcontrols}% + % + %determine playback section + \ifx\@MXV@starttime\@empty\else% + \edef\@MXV@movieoptions{\@MXV@movieoptions, % + startat=time:\strip@pt\@MXV@start}% + \fi% + \ifx\@MXV@durationtime\@empty\else% + \advance\@MXV@end by \@MXV@start% + \edef\@MXV@movieoptions{\@MXV@movieoptions, % + endat=time:\strip@pt\@MXV@end}% + \fi% + % + \edef\@MXV@movieoptions{[\@MXV@movieoptions]}% + \expandafter\movieref\@MXV@movieoptions{#2}{#3}% +} diff --git a/man/multimodal/eeg.tex b/man/multimodal/eeg.tex index 5222813..cc9af09 100644 --- a/man/multimodal/eeg.tex +++ b/man/multimodal/eeg.tex @@ -223,7 +223,7 @@ \subsection{3D ``imaging'' reconstruction \label{multimodal:eeg:3D}} Press ``Invert'', select ``Imaging'' (i.e, a distributed solution rather than DCM; Kiebel et al (2006)), select ``yes'' to include all conditions (i.e, both the differential and common effects of faces and scrambled faces) and then ``Standard'' to use the default settings. -By default the MSP method will be used. MSP stands for ``Multiple Sparse Priors'' (Friston et al. 2008a), and has been shown to be superior to standard minimum norm (the alternative IID option) or a maximal smoothness solution (like LORETA; the COH option) - see Henson et al (2009a). Note that by default, MSP uses a ``Greedy Search'' (GS) (Friston et al, 2008b), though the standard ReML (as used in Henson et al, 2007) can also be selected (this uses Automatic Relevance Determination - ARD). +By default the MSP method will be used. MSP stands for ``Multiple Sparse Priors'' (Friston et al. 2008a), and has been shown to be superior to standard minimum norm (the alternative IID option) or a maximal smoothness solution (like LORETA; the COH option) - see Henson et al (2009a). Note that by default, MSP uses a ``Greedy Search'' (GS) (Friston et al, 2008b), though the standard ReML (as used in Henson et al, 2007) can also be selected via the batch tool (this uses Automatic Relevance Determination - ARD). The ``Standard'' option uses default values for the MSP approach (to customise some of these parameters, press ``Custom'' instead). @@ -250,14 +250,12 @@ \subsection{3D ``imaging'' reconstruction \label{multimodal:eeg:3D}} Press the ``Window'' button in the reconstruction window, enter ``150 200'' as the timewindow of interest and keep ``0'' as the frequency band of interest (0 means all frequencies). The Graphics window will then show the mean activity for this time/frequency contrast (top plot) and the contrast itself (bottom plot; note additional use of a Hanning window). -Then press ``Image'', ``12'' for the smoothing kernel, and SPM will write 3D NIfTI images corresponding to the above contrast for each condition: +Then press ``Image'' and SPM will write 3D NIfTI images corresponding to the above contrast for each condition: \begin{verbatim} - w_wmaceMdspm8_faces_run1_1_1.nii - w_wmaceMdspm8_faces_run1_1_2.nii - sw_wmaceMdspm8_faces_run1_1_1.nii - sw_wmaceMdspm8_faces_run1_1_2.nii + wmaceMdspm8_faces_run1_1_t150_200_f_1.nii + wmaceMdspm8_faces_run1_1_t150_200_f_2.nii \end{verbatim} -Note that the first two images are unsmoothed (but normalised); the latter two are the result of smoothing the former two by a 12mm isotropic Gaussian kernel. The last number in the file name refers to the condition number; the penultimate number refers to the reconstruction number (i.e. the number in red in the reconstruction window, i.e, \texttt{D.val}, here 1). The reconstruction number will increase if you create a new inversion by pressing ``new''. +The last number in the file name refers to the condition number; the number following the dataset name refers to the reconstruction number (i.e. the number in red in the reconstruction window, i.e, \texttt{D.val}, here 1). The reconstruction number will increase if you create a new inversion by pressing ``new''. The smoothed results for Condition 1 (i.e, the differential evoked response for faces vs scrambled faces) will also be displayed in the Graphics window, see Figure~\ref{multimodal:fig:eegrecon} (after moving the cursor to the right posterior hotspot), together with the normalised structural. Note that the solution image is in MNI (normalised) space, because the use of a canonical mesh provides us with a mapping between the cortex mesh in native space and the corresponding MNI space. diff --git a/man/multimodal/meg.tex b/man/multimodal/meg.tex index e4aa59b..07b649e 100644 --- a/man/multimodal/meg.tex +++ b/man/multimodal/meg.tex @@ -118,19 +118,19 @@ \subsection{Basic ERFs} \subsection{Time-Frequency Analysis} -SPM uses Morlet wavelets to perform time-frequency analyses. +SPM can use several methods for time-frequency decomposition. We will use Morlet wavelets for our analyses. -Select the \textsc{time-frequency} option under the ``Other'' pull-down menu, and select the \texttt{cdbespm8\_\-SPM\_\-CTF\_\-MEG\_\-example\_\-faces1\_\-3D.mat} file. SPM will then prompt you for the frequencies you wish to analyse, for which you can type [5:40] (Hz). Change the default Morlet wavelet order (N) from 7 to 5. This factor effectively trades off frequency vs time resolution, with a lower order giving higher temporal resolution. You will then be prompted to select channels from a list. Select ``MLT34'' and press ``OK''\footnote{You can of course obtain time-frequency plots for every channel, but it will take much longer (and result in a large file).}. Answer ``yes'' to ``Compute phase?''. +Select the \textsc{time-frequency} option under the ``Other'' pull-down menu. SPM batch tool with time-frequency configuration options will apear. Double-click on ``File name'' and select the \texttt{cdbespm8\_\-SPM\_\-CTF\_\-MEG\_\-example\_\-faces1\_\-3D.mat} file. Then click on ``Channel selection'' and in the box below click on ``Delete: All(1)'' and then on ``New: Custom channel''. Double-click on ``Custom channel'' and enter ``MLT34''.\footnote{You can of course obtain time-frequency plots for every channel, but it will take much longer (and result in a large file).} Double-click on ``Frequencies of interest'' and type [5:40] (Hz). Click on ``Spectral estimation'' and select ``Morlet wavelet transform''. Change the number of wavelet cycles from 7 to 5. This factor effectively trades off frequency vs time resolution, with a lower order giving higher temporal resolution. Select ``yes'' for ``Save phase?''. -This will produce two new datasets, \texttt{tf1\_\-cdbespm8\_\-SPM\_\-CTF\_\-MEG\_\-example\_\-faces1\_3D.\{mat,dat\}} and \texttt{tf2\_\-cdbespm8\_\-SPM\_\-CTF\_\-MEG\_\-example\_\-faces1\_\-3D.\{mat,dat\}}. The former contains the power at each frequency, time and channel; the latter contains the corresponding phase angles. +This will produce two new datasets, \texttt{tf\_\-cdbespm8\_\-SPM\_\-CTF\_\-MEG\_\-example\_\-faces1\_3D.\{mat,dat\}} and \texttt{tph\_\-cdbespm8\_\-SPM\_\-CTF\_\-MEG\_\-example\_\-faces1\_\-3D.\{mat,dat\}}. The former contains the power at each frequency, time and channel; the latter contains the corresponding phase angles. Here we will not baseline correc the time-frequency data because for frequencies as low as 5Hz, one would need a longer pre-stimulus baseline, to avoid edge-effects\footnote{For example, for 5Hz, one would need at least N/2 x 1000ms/5, where N is the order of the Morlet wavelets (i.e, number of cycles per Gaussian window), e.g, 600ms for a 6th-order wavelet.}. Later, we will compare two trial-types directly, and hence any pre-stimulus differences will become apparent. -Press the \textsc{Averaging} button and select the \texttt{tf1\_\-cdbespm8\_\-SPM\_\-CTF\_\-MEG\_\-example\_\-faces1\_\-3D.mat} file. You can use straight (or robust if you prefer) averaging to compute the average time-frequency representation. A new file will be created in the MEG directory called \texttt{mtf1\_cdbespm8\_\-SPM\_\-CTF\_\-MEG\_\-example\_\-faces1\_\-3D.\{mat,dat\}}. Note that you can use the reviewing tool to review the time-frequency datasets. +Press the \textsc{Averaging} button and select the \texttt{tf\_\-cdbespm8\_\-SPM\_\-CTF\_\-MEG\_\-example\_\-faces1\_\-3D.mat} file. You can use straight (or robust if you prefer) averaging to compute the average time-frequency representation. A new file will be created in the MEG directory called \texttt{mtf\_cdbespm8\_\-SPM\_\-CTF\_\-MEG\_\-example\_\-faces1\_\-3D.\{mat,dat\}}. Note that you can use the reviewing tool to review the time-frequency datasets. This contains the power spectrum averaged over all trials, and will include both ``evoked'' and ``induced'' power. Induced power is (high-frequency) power that is not phase-locked to the stimulus onset, which is therefore removed when averaging the amplitude of responses across trials (i.e, would be absent from a time-frequency analysis of the \texttt{mcdbespm8\_SPM\_\-CTF\_\-MEG\_\-example\_\-faces1\_\-3D.mat} file). -The power spectra for each trial-type can be displayed using the usual Display button and selecting the \texttt{mtf1\_\-cdbespm8\_\-SPM\_\-CTF\_\-MEG\_\-example\_\-faces1\_3D.mat} file. This will produce a plot of power as a function of frequency (y-axis) and time (x-axis) for Channel MLT34. If you use the ``trial'' slider to switch between trial(types) 1 and 2, you will see the greater power around 150ms and 10Hz for faces than scrambled faces (click on the magnifying glass icon and on the single channel to get scales for the axes, as in Figure~\ref{multimodal:fig:13}). This corresponds to the M170 again. +The power spectra for each trial-type can be displayed using the usual Display button and selecting the \texttt{mtf\_\-cdbespm8\_\-SPM\_\-CTF\_\-MEG\_\-example\_\-faces1\_3D.mat} file. This will produce a plot of power as a function of frequency (y-axis) and time (x-axis) for Channel MLT34. If you use the ``trial'' slider to switch between trial(types) 1 and 2, you will see the greater power around 150ms and 10Hz for faces than scrambled faces (click on the magnifying glass icon and on the single channel to get scales for the axes, as in Figure~\ref{multimodal:fig:13}). This corresponds to the M170 again. \begin{figure} \begin{center} @@ -142,16 +142,16 @@ \subsection{Time-Frequency Analysis} We can also look at evidence of phase-locking of ongoing oscillatory activity by averaging the phase angle information. We compute the vector mean (by converting the angles to vectors in Argand space), which yelds complex numbers. We can generate two kinds of images from these numbers. The first is an image of the angles, which shows the mean phase of the oscillation (relative to the trial onset) at each time point. The second is an image of the absolute values (also called ``Phase-Locking Value'', PLV) which lie between 0 for no phase-locking across trials and 1 for perfect phase-locking. -Press the \textsc{Averaging} button and select the \texttt{tf2\_\-cdbespm8\_\-SPM\_\-CTF\_\-MEG\_\-example\_\-faces1\_\-3D.mat} file. This time you will be prompted for either ``angle'' or ``abs(PLV)'' average, for which you should select ``abs(PLV)''. The \matlab\ window will echo: +Press the \textsc{Averaging} button and select the \texttt{tph\_\-cdbespm8\_\-SPM\_\-CTF\_\-MEG\_\-example\_\-faces1\_\-3D.mat} file. This time you will be prompted for either ``angle'' or ``abs(PLV)'' average, for which you should select ``abs(PLV)''. The \matlab\ window will echo: \begin{verbatim} - mtf2_cdbespm8_SPM_CTF_MEG_example_faces1_3D.mat: Number of replications per contrast: + mtph_cdbespm8_SPM_CTF_MEG_example_faces1_3D.mat: Number of replications per contrast: average faces: 168 trials, average scrambled: 168 trials \end{verbatim} -and a new file will be created in the MEG directory called \texttt{mtf2\_\-cdbespm8\_\-SPM\_\-CTF\_\-MEG\_\-example\_\-faces1\_\-3D.mat}. +and a new file will be created in the MEG directory called \texttt{mtph\_\-cdbespm8\_\-SPM\_\-CTF\_\-MEG\_\-example\_\-faces1\_\-3D.mat}. -If you now display the file \texttt{mtf2\_\-cdbespm8\_\-SPM\_\-CTF\_\-MEG\_\-example\_\-faces1\_\-3D.mat} file, you will see PLV as a function of frequency (y-axis) and time (x-axis) for Channel MLT34. Again, if you use the ``trial'' slider to switch between trial(types) 1 and 2, you will see greater phase-locking around for faces than scrambled faces at lower frequencies, as in Figure~\ref{multimodal:fig:14}. Together with the above power analysis, these data suggest that the M170 includes an increase both in power and in phase-locking of ongoing oscillatory activity in the alpha range (Henson et al, 2005b). +If you now display the file \texttt{mtph\_\-cdbespm8\_\-SPM\_\-CTF\_\-MEG\_\-example\_\-faces1\_\-3D.mat} file, you will see PLV as a function of frequency (y-axis) and time (x-axis) for Channel MLT34. Again, if you use the ``trial'' slider to switch between trial(types) 1 and 2, you will see greater phase-locking around for faces than scrambled faces at lower frequencies, as in Figure~\ref{multimodal:fig:14}. Together with the above power analysis, these data suggest that the M170 includes an increase both in power and in phase-locking of ongoing oscillatory activity in the alpha range (Henson et al, 2005b). \begin{figure} \begin{center} @@ -165,9 +165,9 @@ \subsection{2D Time-Frequency SPMs} Analogous to Section~\ref{multimodal:eeg:3DSPM}, we can also use Random Field Theory to correct for multiple statistical comparisons across the 2-dimensional time-frequency space. -Select \textsc{Convert to images} in the ``Other'' pulldown menu, and select the \texttt{tf1\_cdbespm8\_\-SPM\_\-CTF\_\-MEG\_\-example\_\-faces1\_\-3D.mat} file. Usually you would be asked whether you want to average over channels or frequencies. In this case there is only one channel in this dataset, so the ``channels'' option will be selected automatically. +Select \textsc{Convert to images} in the ``Other'' pulldown menu, and select the \texttt{tf\_cdbespm8\_\-SPM\_\-CTF\_\-MEG\_\-example\_\-faces1\_\-3D.mat} file. Usually you would be asked whether you want to average over channels or frequencies. In this case there is only one channel in this dataset, so the ``channels'' option will be selected automatically. -This will create 2D time-frequency images for each trial of the two types with dimensions $36\times 161\times 1$, as for the example shown in Figure~\ref{multimodal:fig:15}. These images can be found in the subdirectories \texttt{1ROI\_TF\_\-trialtype\_\-faces} and \texttt{1ROI\_TF\_\-trialtype\_\-scrambled} of the new directory created \texttt{tf1\_\-cdbespm8\_\-SPM\_\-CTF\_\-MEG\_\-example\_\-faces1\_3D}, and examined by pressing ``Display: images'' on the main SPM window. +This will create 2D time-frequency images for each trial of the two types with dimensions $36\times 161\times 1$, as for the example shown in Figure~\ref{multimodal:fig:15}. These images can be found in the subdirectories \texttt{1ROI\_TF\_\-trialtype\_\-faces} and \texttt{1ROI\_TF\_\-trialtype\_\-scrambled} of the new directory created \texttt{tf\_\-cdbespm8\_\-SPM\_\-CTF\_\-MEG\_\-example\_\-faces1\_3D}, and examined by pressing ``Display: images'' on the main SPM window. \begin{figure} \begin{center} @@ -242,20 +242,18 @@ \subsection{``Imaging'' reconstruction of total power for each condition \label{ Press the ``Window'' button in the reconstruction window, enter ``150 200'' as the timewindow of interest and ``5 15'' as the frequency band of interest (from the SPM time-frequency analysis, at least from one channel). Then choose the ``induced'' option. After a delay (as SPM calculates the power across all trials) the Graphics window will show the mean activity for this time/frequency contrast (for faces alone, assuming the condition toggle is showing ``condition 1''). -If you then press ``Image'', press ``12'' for the smoothing kernel, and SPM will write 3D NIfTI images corresponding to the above contrast for each condition: +If you then press ``Image'', SPM will write 3D NIfTI images corresponding to the above contrast for each condition: \begin{verbatim} - w_cdbespm8_SPM_CTF_MEG_example_faces1_3D_1_1.nii - w_cdbespm8_SPM_CTF_MEG_example_faces1_3D_1_2.nii - sw_cdbespm8_SPM_CTF_MEG_example_faces1_3D_1_1.nii - sw_ecdbespm8_SPM_CTF_MEG_example_faces1_3D_1_2.nii + cdbespm8_SPM_CTF_MEG_example_faces1_3D_1_t150_200_f5_15_1.nii + cdbespm8_SPM_CTF_MEG_example_faces1_3D_1_t150_200_f5_15_2.nii \end{verbatim} -Note that the first two images are unsmoothed (but normalised); the latter two are smoothed by a 12mm isotropic Gaussian kernel. The last number in the file name refers to the condition number; the penultimate number refers to the reconstruction number (i.e. the number in red in the reconstruction window, i.e, \texttt{D.val}, here 1). +The last number in the file name refers to the condition number; the number following the dataset name refers to the reconstruction number (i.e. the number in red in the reconstruction window, i.e, \texttt{D.val}, here 1). The smoothed results for Condition 1 will also be displayed in the Graphics window, together with the normalised structural. Note that the solution image is in MNI (normalised) space, because the use of a canonical mesh provides us with a mapping between the cortex mesh in native space and the corresponding MNI space. You can also of course view the image with the normal SPM ``Display:image'' option, and locate the coordinates of the ``hotspots'' in MNI space. Note that these images contain RMS (unsigned) source estimates (see Henson et al, 2007). -If you want to see where activity (in this time/freq contrast) is greater for faces and scrambled faces, you can use SPM \texttt{ImCalc} facility to create a difference image of \texttt{sw\_\-cdbespm8\_\-SPM\_\-CTF\_\-MEG\_\-example\_\-faces1\_\-3D\_\-1\_\-1.nii} - \texttt{sw\_\-cdbespm8\_\-SPM\_\-CTF\_\-MEG\_\-example\_\-faces1\_\-3D\_\-1\_\-2.nii}: you should see bilateral fusiform. For further discussion of localising a differential effect (as in Section~\ref{multimodal:eeg:3D} with ERPs), vs taking the difference of two localisations, as here, see Henson et al (2007). The above images can then be used at the second level (assuming one also has data from other subjects) to look for effects that are consistent over a group of subjects. +If you want to see where activity (in this time/freq contrast) is greater for faces and scrambled faces, you can use SPM \texttt{ImCalc} facility to create a difference image of \texttt{cdbespm8\_\-SPM\_\-CTF\_\-MEG\_\-example\_\-faces1\_\-3D\_\-1\_\-t150\_\-200\_\-f5\_\-15\_\-1.nii} - \texttt{cdbespm8\_\-SPM\_\-CTF\_\-MEG\_\-example\_\-faces1\_\-3D\_\-1\_\-t150\_\-200\_\-f5\_\-15\_\-2.nii}: you should see bilateral fusiform. For further discussion of localising a differential effect (as in Section~\ref{multimodal:eeg:3D} with ERPs), vs taking the difference of two localisations, as here, see Henson et al (2007). The above images can then be used at the second level (assuming one also has data from other subjects) to look for effects that are consistent over a group of subjects. diff --git a/man/ppi/figures/Fig1.png b/man/ppi/figures/Fig1.png new file mode 100644 index 0000000..c8bc5b4 Binary files /dev/null and b/man/ppi/figures/Fig1.png differ diff --git a/man/ppi/figures/Fig10.png b/man/ppi/figures/Fig10.png new file mode 100644 index 0000000..ccf8503 Binary files /dev/null and b/man/ppi/figures/Fig10.png differ diff --git a/man/ppi/figures/Fig11.png b/man/ppi/figures/Fig11.png new file mode 100644 index 0000000..6d4ff16 Binary files /dev/null and b/man/ppi/figures/Fig11.png differ diff --git a/man/ppi/figures/Fig12.png b/man/ppi/figures/Fig12.png new file mode 100644 index 0000000..92870e1 Binary files /dev/null and b/man/ppi/figures/Fig12.png differ diff --git a/man/ppi/figures/Fig13.png b/man/ppi/figures/Fig13.png new file mode 100644 index 0000000..b996284 Binary files /dev/null and b/man/ppi/figures/Fig13.png differ diff --git a/man/ppi/figures/Fig14.png b/man/ppi/figures/Fig14.png new file mode 100644 index 0000000..8620f92 Binary files /dev/null and b/man/ppi/figures/Fig14.png differ diff --git a/man/ppi/figures/Fig15.png b/man/ppi/figures/Fig15.png new file mode 100644 index 0000000..52990b0 Binary files /dev/null and b/man/ppi/figures/Fig15.png differ diff --git a/man/ppi/figures/Fig16.png b/man/ppi/figures/Fig16.png new file mode 100644 index 0000000..b3bba5a Binary files /dev/null and b/man/ppi/figures/Fig16.png differ diff --git a/man/ppi/figures/Fig2.png b/man/ppi/figures/Fig2.png new file mode 100644 index 0000000..71d045b Binary files /dev/null and b/man/ppi/figures/Fig2.png differ diff --git a/man/ppi/figures/Fig3.png b/man/ppi/figures/Fig3.png new file mode 100644 index 0000000..828c04a Binary files /dev/null and b/man/ppi/figures/Fig3.png differ diff --git a/man/ppi/figures/Fig4.png b/man/ppi/figures/Fig4.png new file mode 100644 index 0000000..baba15f Binary files /dev/null and b/man/ppi/figures/Fig4.png differ diff --git a/man/ppi/figures/Fig5.png b/man/ppi/figures/Fig5.png new file mode 100644 index 0000000..103de3e Binary files /dev/null and b/man/ppi/figures/Fig5.png differ diff --git a/man/ppi/figures/Fig6.png b/man/ppi/figures/Fig6.png new file mode 100644 index 0000000..fc38609 Binary files /dev/null and b/man/ppi/figures/Fig6.png differ diff --git a/man/ppi/figures/Fig7.png b/man/ppi/figures/Fig7.png new file mode 100644 index 0000000..567dea0 Binary files /dev/null and b/man/ppi/figures/Fig7.png differ diff --git a/man/ppi/figures/Fig8.png b/man/ppi/figures/Fig8.png new file mode 100644 index 0000000..2df086d Binary files /dev/null and b/man/ppi/figures/Fig8.png differ diff --git a/man/ppi/figures/Fig9.png b/man/ppi/figures/Fig9.png new file mode 100644 index 0000000..fdc25b6 Binary files /dev/null and b/man/ppi/figures/Fig9.png differ diff --git a/man/ppi/ppi.tex b/man/ppi/ppi.tex new file mode 100644 index 0000000..487256c --- /dev/null +++ b/man/ppi/ppi.tex @@ -0,0 +1,483 @@ +\chapter{Psychophysiological Interactions (PPI)\label{Chap:data:ppi}} + +\section{Theoretical background} + +Psychophysiological interactions (PPI) and the related technique of physiophysiological interactions \((\Phi\)PI) are based on extensions to statistical models of factorial designs. Table 1 illustrates a classic \(2 \times 2\) factorial design. + +\begin{table}[h] +\makeatletter +\long\def\@makecaption#1#2{% +\vskip\abovecaptionskip +\sbox\@tempboxa{#1. #2}% +\ifdim \wd\@tempboxa >\hsize +#1. #2\par +\else +\global \@minipagefalse +\hb@xt@\hsize{\box\@tempboxa\hfil}% +\fi +\vskip\belowcaptionskip} +\makeatother + +\caption{2 x 2 factorial design in Table format} +\begin{tabular}{p{10pt}p{11pt}p{53pt}|p{58pt}} +\parbox{10pt}{\raggedright +} & \parbox{11pt}{\raggedright + +} & \multicolumn{2}{c}{\parbox{111pt}{\centering \textsf{Factor A} }} \\ +\parbox{10pt}{\raggedright +} & \parbox{11pt}{\raggedright + +} & \parbox{53pt}{\centering +\textsf{Level 1} +} & \parbox{58pt}{\centering +\textsf{Level 2} +} \\ +\cline{3-4} +\parbox{10pt}{\centering \multirow{2}{*}{ +\rotatebox{90}{\mbox{\textsf{Factor B}}} +}} & \parbox{11pt}{\centering +\rotatebox{90}{\mbox{\textsf{ Level 1 }}} +} & \parbox{53pt}{\centering +\textsf{A$_{1}$/B$_{1}$} +} & \parbox{58pt}{\centering +\textsf{A$_{2}$/B$_{1}$} +} \\ +\cline{3-4} + & \parbox{11pt}{\centering +\rotatebox{90}{\mbox{\textsf{ Level 2 }}} +} & \parbox{53pt}{\centering +\textsf{A$_{1}$/B$_{2}$} +} & \parbox{58pt}{\centering +\textsf{A$_{2}$/B$_{2}$} +} \\ +\cline{3-4} +\end{tabular} +\end{table} + +The equation for factorial design is given by \ref{eq:ppi1}. + +\begin{equation} + \mbox{$y=(A_{2}-A_{1})\beta_{1}+(B_{2}-B_{1})\beta_2+(A_{2}-A_{1})(B_{2}-B_{1})\beta_{3}+G\beta_{4} +\epsilon\quad$} + \label{eq:ppi1} +\end{equation} + +Notice that this equation includes both of the main effects terms $(A_{2}-A_{1})\beta_{1}$ for factor A, and $(B_{2}-B_{1})\beta_{2}$ for factor B, as well as the interaction term $(A_{2}-A_{1})(B_{2}-B_{1})\beta_{3}$. It also contains a term for the confounds $G\beta_{4}$ such as movement parameters, session effects, etc. The inclusion of main effects when estimating interactions is very important, and their inclusion in the design cannot be stressed enough. If the main effects are not included, then we cannot be sure that estimates of the interaction term are not confounded by main effects. + +To extend the concept of factorial designs to PPI's the basic idea is to substitute (neural) activity from one cerebral region for one of the factors. Equation~\ref{eq:ppi2} illustrates this concept after substituting activity in area V1 for factor A. + +\begin{equation} + \mbox{$y=V1\beta_{1}+(B_{2}-B_{1})\beta_2+(V1\times(B_{2}-B_{1}))\beta_3+G\beta_4 +\epsilon\quad$} + \label{eq:ppi2} +\end{equation} + +Similarly, for psychophysiological interactions activity from 2 cerebral regions (V1 and posterior parietal (PP)) are used as the main effects, as shown in equation \ref{eq:ppi3} + +\begin{equation} + \mbox{$y=V1\beta_{1}+PP\beta_2+(V1\times PP)\beta_3+G\beta_4 +\epsilon\quad$} + \label{eq:ppi3} +\end{equation} + +Again, notice that all 3 equations \ref{eq:ppi1}, \ref{eq:ppi2} and \ref{eq:ppi3} have 3 terms (aside from confounds and error) -- the two main effects and the interaction. Therefore, the design matrix must include at least 3 columns, one for each main effect and one for the interaction. A basic design matrix for PPI's is shown in Figure \ref{fig:ppi1}. + +\begin{figure}[h] + \centering\includegraphics[width=85mm]{ppi/figures/Fig1.png} + \caption{\em Example design matrix for a PPI (or \((\Phi\)PI)). The main effects are BOLD activity from area V1, in column 2, and a psychological vector, e.g., attention vs. no attention (P), in column 3. Inference would typically focus on the interaction term, in column 1, using a contrast vector of \textsc{[1 0 0 0]}. In \(\Phi\)PIs the third column would be BOLD activity from a second source region rather than the psychological factor.} + \label{fig:ppi1} +\end{figure} + +Both PPIs and $\Phi$PIs can be conceived of as models of ``contribution''. PPIs occupy middle-ground between between models of functional vs. effective connectivity \cite{ppi}. Functional connectivity (FC) is defined as the temporal correlation between spatially separated neurophysiological events \cite{ppi}. FC analyses are typically model-free and do not specify a direction of influence, i.e., the influence of A on B is indistinguishable from the influence of B on A. In contrast, PPI's are based on regression models, and therefore a direction of influence is chosen based on the model. Effective connectivity (EC) is defined as the influence one neural system has on another \cite{func1}. PPIs are closely related to EC models, but because PPIs are generally very simple (i.e., 1 source region and 1 experimental factor, or 2 source regions in the case of $\Phi$PIs) they are very limited models of EC. + +The interaction between the source region and experimental context (or two source regions) can be interpreted in 2 different ways: 1) as demonstrating how the contribution of one region to another is altered by the experimental context or task, or 2) as an example of how an area's response to an experimental context is modulated by input from another region, Figure~\ref{fig:ppi2}.\\ + +\begin{figure}[!h] + \includegraphics[width=120mm]{ppi/figures/Fig2.png} + \caption{Two alternative interpretations of PPI effects. A) The contribution of one area (k) to another (i) is altered by the experimental (psychological) context. B) The response of an area (i) to an experimental (psychological) context due to the contribution of region (k). (Adapted from \cite{ppi})} + \label{fig:ppi2} +\end{figure} + +\section{Psycho-Physiologic Interaction Analysis: Summary of Steps} +Mechanistically, a PPI analysis involves the following steps. +\begin{enumerate} +\item Performing a standard GLM analysis. +\item Extracting BOLD signal from a source region identified in the GLM analysis. +\item Forming the interaction term (source signal x experimental treatment) +\item Performing a second GLM analysis that includes the interaction term, the source region's extracted signal and the experimental vector in the design. The inclusion of the source region's signal and the experimental vector is analogous to including the main effects in an ANOVA in order to make an inference on the interaction. +\end{enumerate} + +Forming the proper interaction term turns out to be a challenge because of the unique characteristics of fMRI (BOLD) data in which the underlying neural signal is convolved with a hemodynamic response function. However, interactions in the brain take place at the neural and not the hemodynamic level. Therefore, appropriate models of the interactions require the neural signal, which is not measured directly, but instead must be derived by deconvolving the HRF. The PPI software (\texttt{spm\_peb\_ppi.m}) was developed in order to provide robust deconvolution of the HRF and the proper derivation of the interaction term \cite{gitelman_03}. + +\section{Practical example} + +The dataset in this exercise is from one subject who was studied in the \cite{buchel1998} report and refers to the ``attention to motion'' dataset available from the SPM website\footnote{\url{http://www.fil.ion.ucl.ac.uk/spm/data/attention/}}. It has already been described in the previous chapter for DCM. + +The goal is to use PPI to examine the change in effective connectivity between V2 and V5 while the subject observes visual motion (radially moving dots) under the experimental treatments of attending vs. not attending to the speed of the dots. The psychophysiologic interaction can be conceived of as looking for a significant difference in the regression slopes of V1 vs. V5 activity under the influence of the different attentional states \cite{ppi}. + +\subsection{GLM analysis - Design setup and estimation} + +This dataset has already been preprocessed (coregistered, normalised and smoothed) using an earlier version of SPM. + +\begin{enumerate} +\item The analysis directory should include +\begin{enumerate} +\item A directory named \texttt{functional}, which includes the preprocessed fMRI volumes. +\item A directory named \texttt{structural}, which includes a T1 structural volume +\item Files: \texttt{factors.mat}, \texttt{block\_regressors.mat}, \texttt{multi\_condition.mat} and \linebreak[4] \mbox{\texttt{multi\_\-block\_\-regressors.mat}}. +\item You will also need to make 2 empty directories called \texttt{GLM} and +\texttt{PPI} for performing the analyses. +\end{enumerate} + +\item In \matlab\ type +\begin{verbatim} +>> cd GLM +>> spm fmri +\end{verbatim} + +\item Start the Batch system by clicking the \textsc{Batch} button. +\item From the \textsc{SPM} menu in the Batch window, click \textsc{Stats} and then select the modules \textsc{fMRI Model Specification}, \textsc{Model Estimation} and \textsc{Contrast Manager}, Figure~\ref{fig:ppi3}. + +\begin{figure}[ht] +\centering\includegraphics[width=120mm]{ppi/figures/Fig3.png} +\caption{Batch Editor showing the \textsc{fMRI Model Specification}, \textsc{Model Estimation} and \textsc{Contrast Manager} modules.} +\label{fig:ppi3} +\end{figure} + +\textbf{Fill in the \textsc{fMRI Model Specification}} + +\item Click \textsc{Directory} and choose the \texttt{GLM} directory that you made above. +\item \textsc{Units for design} [\textsc{scans}] +\item \textsc{Interscan interval} [3.22] +\item \textsc{Microtime resolution} [16] +\item \textsc{Microtime onset} [1] +\item Click \textsc{Data \& Design}. Then in the \textsc{Current Item} box click \textsc{New: Subject/Session}, Figure~\ref{fig:ppi4}. + +\begin{figure}[!ht] +\centering\includegraphics[width=120mm]{ppi/figures/Fig4.png} +\caption{\em Fill in the Data \& Design} +\label{fig:ppi4} +\end{figure} + +\item Click \textsc{Scans} and choose all the functional scans \texttt{snffM00587\_00xx.img}. There should be 360 \texttt{*.img} files. +\item The experimental conditions can be defined either individually or using a multiple condition \texttt{mat}-file. This exercise shows both methods for educational purposes. When doing an actual analysis you can just follow one of the two approaches below.\\\\ + +\textbf{Define conditions individually} +\item Load the mat file containing the individual conditions: +\begin{verbatim} +>> load factors.mat +\end{verbatim} +You can look at the loaded variables by typing the variable names. +( \texttt{stat} = stationary, \texttt{natt} = no attention, \texttt{att} = attention) +\begin{verbatim} +>> stat +>> natt +>> att +\end{verbatim} +\item Click \textsc{Conditions} then in the \textsc{Current Item} box click \textsc{New: Condition} 3 times, Figure~\ref{fig:ppi5}. + +\begin{figure}[!ht] +\centering\includegraphics[width=120mm]{ppi/figures/Fig5.png} +\caption{\em \textsc{Current Module} section of the \textsc{Batch Editor} showing 3 Conditions to be filled in.} +\label{fig:ppi5} +\end{figure} + +\item Condition 1: Name = \texttt{Stationary}, \textsc{Onsets} = \texttt{stat}, \textsc{Durations} = 10. +\item Condition 2: Name = \texttt{No-attention}, \textsc{Onsets} = \texttt{natt}, \textsc{Durations} = 10. +\item Condition 3: Name = \texttt{Attention}, \textsc{Onsets} = \texttt{att}, \textsc{Durations} = 10. +\item Next you will enter 3 regressors to model block effects. This will account for the fact that the experiment took place over 4 runs that have been concatenated into a single session to make the PPI analysis easier. {\em Note: Only 3 of the 4 sessions need to be modeled by block regressors because the fourth one is modeled by the mean column of the design matrix.} + +First load the regressors: +\begin{verbatim} +>> load block_regressor.mat +\end{verbatim} +\item Click \textsc{Regressors} then click \textsc{New: Regressor} 3 times in the \textsc{Current Item} box, Figure~\ref{fig:ppi6}. + +\begin{figure}[!ht] +\centering\includegraphics[width=120mm]{ppi/figures/Fig6.png} +\caption{\em \textsc{Current Module} section of the \textsc{Batch Editor} showing 3 Regressors to be filled in.} +\label{fig:ppi6} +\end{figure} + +\item Regressor 1: \textsc{Name} = \texttt{Block 1}, \textsc{Value} = \texttt{block1} +\item Regressor 2: \textsc{Name} = \texttt{Block 2}, \textsc{Value} = \texttt{block2} +\item Regressor 3: \textsc{Name} = \texttt{Block 3}, \textsc{Value} = \texttt{block3}\\\\ + +\textbf{Define conditions using multiple condition and multiple regressor files} +\item If you would like to look at the organization of the variables in the multiple condition file, first load it. +\begin{verbatim} +>> load multi_condition.mat +>> names +>> onsets +>> durations +\end{verbatim} +The variables in a multiple condition file must always be named: 'names', 'onsets', and 'durations'. Notice that these three variables are cell arrays. +\textit{(Note: You only need to do this step if you want to look at the organization of the variables. In contrast to defining conditions individually, as shown above, when using a multiple condition file you do not have to load the file in order to enter it into the design.)}\\ +\item To use the multiple conditions file in the design, click \textsc{Multiple Conditions}, then \textsc{Specify Files} in the Options box and choose the \texttt{multi\_condition.mat} file. +\item Next you will enter the 3 regressors to model block effects by using a multiple regressor file. To look at the organization of the multiple regressor variable, first load it. \textit{(Again you do not have to load the multiple regressor file in order to use it. This step is just to allow you to examine the file and the variables it contains.)} +\begin{verbatim} +>> load multi_block_regressor.mat +>> R +\end{verbatim} +Notice that this file contains a single variable, \texttt{R}, which is a 360 x 3 matrix. The number of rows is equal to the number of scans, and each regressor is in a separate column. +\item To use the multiple regressor file, click \textsc{Multiple Regressors} then select the \texttt{multi\_\-block\_\-regressor.mat} file.\\\\ + +\textbf{Complete the design setup} +\item \textsc{High-pass filter} [192] (Note: most designs will use a high-pass filter value of 128. However, this dataset requires a longer high-pass filter in order not to lose the low frequency components of the design.) +\item \textsc{Factorial design} is not used +\item The \textsc{Basis function} is the \textsc{canonical HRF} as shown and \textsc{Model derivatives} [\textsc{No derivatives}] +\item \textsc{Model Interactions (Volterra)}: [\textsc{Do not model interactions}] +\item \textsc{Global normalisation} [\textsc{None}] +\item \textsc{Explicit mask} [\textsc{None}] +\item \textsc{Serial correlations} [\textsc{AR(1)}]\\\\ + +\textbf{Model Estimation} +\item Under \textsc{Model estimation} click \textsc{Select \texttt{SPM.mat}} then click the \textsc{Dependency} button and choose \textsc{fMRI model specification: SPM.mat File}. The \textsc{Method} should be left as Classical.\\\\ + +\textbf{Contrast Manager} +\item Under \textsc{Contrast Manager} click \textsc{Select \texttt{SPM.mat}} then click the \textsc{Dependency} button and choose \textsc{Model estimation: SPM.mat File} + +\item Click \textsc{Contrast Sessions} then click \textsc{New: F-contrast} once, and \textsc{New: T-contrast} twice from the \textsc{Current Item} box. +\item Click \textsc{Contrast vectors} and then \textsc{New: F contrast vector}. +\item The F contrast vector can be entered as [eye(3), zeros(3,4)], which will produce: +\begin{verbatim} +1 0 0 0 0 0 0 +0 1 0 0 0 0 0 +0 0 1 0 0 0 0 +\end{verbatim} + +\item For the first T-contrast, \textsc{Name} is \texttt{Attention}, and the \textsc{T contrast vector} is \texttt{~0~-1~1~0~0~0~0} (Note the order of the conditions in the design matrix is: Stationary, NoAttMot and AttMot). +\item For the second T-contrast \textsc{Name} is \texttt{Motion}, and the \textsc{T contrast vector} is: \texttt{-2~1~1~0~0~0~0}. + +\item Click the \textsc{Save} icon on the toolbar and save the batch file.\\ + +\textbf{Design estimation}\\ +\item If everything has been entered correctly the \textsc{Run} button should now be green. Click \textsc{Run} to estimate the design. +\item The design matrix should look as shown in Figure~\ref{fig:ppi7}, below. + +\begin{figure}[!ht] +\centering\includegraphics[width=85mm]{ppi/figures/Fig7.png} +\caption{\em Design matrix} +\label{fig:ppi7} +\end{figure} +\end{enumerate} + +\subsection{GLM analysis - Results} + +\begin{enumerate} +\item Click \textsc{Results} and select the \texttt{SPM.mat} file. +\item Choose the \texttt{Attention} contrast +\item Mask with other contrasts [No] +\item Title for comparison [Attention] +\item p value adjustment to control [None] +\item threshold {T or p value} [0.0001] +\item \& extent threshold {voxels} [10] +\item You should see an SPM that looks like the one shown below, Figure~\ref{fig:ppi8}. Note the Superior Parietal and Dorso-Lateral Prefrontal activations, among others. By selecting \textsc{overlays} $\rightarrow$ \textsc{sections}, and selecting the normalised structural image, you should be able to identify the anatomy more accurately. + +\begin{figure}[!ht] +\centering\includegraphics[width=85mm]{ppi/figures/Fig8.png} +\caption{\em Statistical parametric map for the \texttt{Attention} contrast} +\label{fig:ppi8} +\end{figure} + +\item To look at the \texttt{Motion} contrast where \texttt{Attention} is greater than \texttt{No Attention}, click \textsc{Results}, choose the \texttt{SPM.mat} file and choose the \texttt{Motion} contrast. +\item apply masking [Yes] +\item Select contrast for masking: Choose the \texttt{Attention} contrast +\item Uncorrected mask p-value [0.01] +\item Nature of Mask: [inclusive] +\item title for comparison: leave as the defaults, which is [Motion (masked [incl.] by Attention at p=0.01)] +\item p value adjustment to control [FWE] +\item threshold {T or p value} [0.05] +\item \& extent threshold {voxels} [3] +\item The masked \texttt{motion} contrast on the glass brain is shown below in Figure~\ref{fig:ppi9}. + +\begin{figure}[!ht] +\centering\includegraphics[width=85mm]{ppi/figures/Fig9.png} +\caption{\em Statistical parametric map for the \texttt{Motion} contrast inclusively masked by the Attention contrast} +\label{fig:ppi9} +\end{figure} +\end{enumerate} + +\section{GLM analysis - Extracting VOIs} + +\begin{enumerate} +\item First select the \texttt{Motion} contrast, but do not include masking. Use a p-value adjustment of FWE with height threshold of 0.05 and a cluster threshold of 3. +\item Go to point [15 -78 -9] +\item Press \texttt{eigenvariate} +\item Name of region [V2] +\item Adjust data for [effects of interest] +\item VOI definition [sphere] +\item VOI radius(mm) [6] +\end{enumerate} +This saves the extracted VOI data in the file \texttt{VOI\_V2\_1.mat} in the working directory, and displays Figure~\ref{fig:ppi10}, below. The left side shows the location on a standard brain. The right side shows the first eigenvariate of the extracted BOLD signal. + +\begin{figure}[!ht] +\centering\includegraphics[width=85mm]{ppi/figures/Fig10.png} +\caption{\em First eigenvariate of the extracted BOLD signal in V2} +\label{fig:ppi10} +\end{figure} + +\section{PPI analysis - Create PPI variable\label{create_ppi}} +\begin{enumerate} +\item PPIs can be calculated either by pressing the \textsc{PPIs} button in the \textsc{SPM Menu} window, or by selecting the \textsc{Physio/Psycho-Physiologic} menu item from the SPM $\rightarrow$ Stats menu of the \textsc{Batch Editor}. This example uses the \textsc{Batch Editor}, Figure~\ref{fig:ppi11}. + +\begin{figure}[!ht] +\centering\includegraphics[width=100mm]{ppi/figures/Fig11.png} +\caption{\em Physio/Psycho-Physiologic module in the Batch Editor} +\label{fig:ppi11} +\end{figure} + +\item Choose the \textsc{SPM.mat} file in the \texttt{GLM} directory. +\item Type of analysis: Choose \textsc{Psycho-Physiologic interaction}, Figure~\ref{fig:ppi12}. + +\begin{figure}[!ht] +\centering\includegraphics[width=100mm]{ppi/figures/Fig12.png} +\caption{\em Specifying a Psycho-Physiologic interaction.} +\label{fig:ppi12} +\end{figure} + +\item Select VOI: Choose \texttt{VOI\_V2\_1.mat} +\item Input variables and contrast weights: Must be specified as an n x 3 matrix, where n is the number of conditions included in the PPI. The first column of the matrix indexes SPM.Sess.U(i). The second column indexes SPM.Sess.U(i).name{ii}. It will generally be a 1 unless there are parametric effects. The third column is the contrast weight. In order to include Attention - No-attention in the PPI, recall that the conditions were entered as: Stationary, No-attention, Attention, therefore the matrix should be. +\begin{verbatim} +[2 1 -1; 3 1 1] +\end{verbatim} +\item Name of PPI [ V2x(Att-NoAtt) ] +\item Display results: Yes +\end{enumerate} + +After a few seconds the PPI will be calculated and a graphical window will appear, Figure~\ref{fig:ppi13}. In the upper left, the details of the PPI setup calculation are given including the name of the PPI, the chosen VOI file, and the included conditions and their contrast weights. The main central graph shows the original BOLD signal (actually the eigenvariate) in blue and the neuronal or deconvolved signal in green. These will look quite similar for block design data. The graph in the lower left shows the task condition plot, dotted green line, and the convolved task conditions (psych variable). In the lower right the PPI interaction term is plotted. + +\begin{figure}[!ht] +\centering\includegraphics[width=100mm]{ppi/figures/Fig13.png} +\caption{\em PPI output graphics} +\label{fig:ppi13} +\end{figure} + +The PPI calculation will create a file \texttt{PPI\_V2x(Att-NoAtt).mat} in the current working directory. It contains the variable \texttt{PPI.ppi} (the interaction term), \texttt{PPI.Y} (the original VOI eigenvariate) and \texttt{PPI.P} (the \texttt{Attention - No Attention} task vector). You will use these vectors in setting up your psychophysiologic interaction GLM analysis. See \texttt{spm\_peb\_ppi} for a full description of the \texttt{PPI} data structure. + +\subsection{PPI GLM analysis - Design setup and estimation} + +\begin{enumerate} +\item Copy the file \texttt{PPI\_V2x(Att-NoAtt)} \textsc{Mat}-file to the \texttt{PPI} directory that you created at the start of this exercise. +\item Change directory to the new one, i.e. \texttt{cd PPI} +\item At the \matlab\ prompt type +\begin{verbatim} +>> load PPI_V2x(Att-NoAtt) +\end{verbatim} + +\item In the \textsc{Batch Editor} setup another GLM analysis by choosing the modules \textsc{fMRI Model Specification}, \textsc{Model Estimation} and \textsc{Contrast Manager} as you did above, and fill it in as follows. +\item Directory: Choose the \texttt{PPI} directory +\item Units for design [scans] +\item Interscan interval [3.22] +\item Add a \textsc{New: Subject/Session} under \textsc{Data \& Design} +\item Click \textsc{Scans} and choose all the functional scans \texttt{snffM00587\_00xx.img}. There should be 360 \texttt{*.img} files. +\item Click \textsc{New: Regressor} and add 6 regressors. +\item Regressor 1: \textsc{Name} = \texttt{PPI-interaction}, \textsc{Value} = \texttt{PPI.ppi} +\item Regressor 2: \textsc{Name} = \texttt{V2-BOLD}, \textsc{Value} = \texttt{PPI.Y} +\item Regressor 3: \textsc{Name} = \texttt{Psych\_Att-NoAtt}, \textsc{Value} = \texttt{PPI.P} +\item Regressor 4: \textsc{Name} = \texttt{Block 1}, \textsc{Value} = \texttt{block1} +\item Regressor 5: \textsc{Name} = \texttt{Block 2}, \textsc{Value} = \texttt{block2} +\item Regressor 6: \textsc{Name} = \texttt{Block 3}, \textsc{Value} = \texttt{block3} +\item High Pass Filter [192]\\\\ + +\textbf{Model Estimation} +\item Under \textsc{Model estimation} click \textsc{Select \texttt{SPM.mat}} then click the \textsc{Dependency} button and choose \textsc{fMRI model specification: SPM.mat File}. The \textsc{Method} should be left as Classical.\\\\ + +\textbf{Contrast Manager} +\item Under \textsc{Contrast Manager} click \textsc{Select \texttt{SPM.mat}} then click the \textsc{Dependency} button and choose \textsc{Model estimation: SPM.mat File} +\item Click \textsc{Contrast Sessions} then click \textsc{New: T-contrast} +\item T-contrast, \textsc{Name}: \texttt{PPI-Interaction}, vector: \texttt{1~0~0~0~0~0~0} +\item Save the batch file. +\item Run +\end{enumerate} +The design matrix is shown below, Figure~\ref{fig:ppi14}. + +\begin{figure}[ht] +\centering\includegraphics[width=85mm]{ppi/figures/Fig14.png} +\caption{\em Design matrix for the PPI analysis} +\label{fig:ppi14} +\end{figure} + +\subsection{PPI analysis - Results} + +\begin{enumerate} +\item Press the \textsc{Results} button and select the \texttt{SPM.mat} file in the PPI directory. +\item Choose the \texttt{PPI-Interaction} contrast +\item apply masking [No] +\item title for comparison [PPI-Interaction] +\item p value adjustment to control [None] +\item threshold {T or p value} [0.01] +\item \& extent threshold {voxels} [10] +\item You should see an SPM that looks the same as the one shown below in the top part of Figure~\ref{fig:ppi15}. The resulting SPM shows areas showing differential connectivity to V2 due to the effect of attention vs. no attention conditions. The effect in this subject is weak. +\end{enumerate} + +\begin{figure}[!ht] +\centering\includegraphics[width=100mm]{ppi/figures/Fig15.png} +\caption{\em PPI results} +\label{fig:ppi15} +\end{figure} + +\subsection{PPI analysis - Plotting} +\begin{enumerate} +\item One region showing the psychophysiologic interaction is the V5region, which is located at [39~-72~0] in this subject. Move the cursor to this point to view the area of activation, as shown below, in the bottom half of Figure~\ref{fig:ppi15}. + +\item In order to plot the PPI graph showing the effect of attention, you need to extract a VOI from the V5 region. To do this, you will return to the original GLM analysis. +\item Click Results, then select the GLM analysis \texttt{SPM.mat} file and the \texttt{Motion} contrast. +\item apply masking [No] +\item title for comparison [Motion] +\item p value adjustment to control [None] +\item threshold {T or p value} [0.001] +\item \& extent threshold {voxels} [3] +\item Go to point [39~-72~0] +\item Press eigenvariate +\item Name of region [V5] +\item Adjust data for [effects of interest] +\item VOI definition [sphere] +\item VOI radius(mm) [6] +\item Now you will create 4 PPIs (Follow the steps under section~\ref{create_ppi}, Create PPI Variable, above). By using the PPI software machinery to create the interaction vectors, rather than just multiplying the extracted V2 and V5 eigenvariates by the behavioral vectors, the PPI vectors will be formed properly. + +\item \texttt{V2xNoAttention} (Use the V2 VOI and include \texttt{No-Attention} with a contrast weight of 1, do not include \texttt{Stationary}, \texttt{Attention}) +\item \texttt{V2xAttention} (Use the V2 VOI and include \texttt{Attention} with a contrast weight of 1, do not include \texttt{Stationary}, \texttt{No-Attention}) +\item \texttt{V5xNoAttention} (Use the V5 VOI and include \texttt{No-Attention} with a contrast weight of 1, do not include \texttt{Stationary}, \texttt{Attention}) +\item \texttt{V5xAttention} (Use the V5 VOI and include \texttt{Attention} with a contrast weight of 1, do not include \texttt{Stationary}, \texttt{No-Attention}) + +\item Load the PPIs you just created with the following commands at the \matlab\ prompt: +\begin{verbatim} +>> v2noatt = load('PPI_V2xNoAttention'); +>> v2att = load('PPI_V2xAttention.mat'); +>> v5noatt = load('PPI_V5xNoAttention.mat'); +>> v5att = load('PPI_V5xAttention.mat'); +\end{verbatim} +\item Plot the PPI datapoints with the following commands at the \matlab\ prompt: +\begin{verbatim} +>> figure +>> plot(v2noatt.PPI.ppi,v5noatt.PPI.ppi,'k.'); +>> hold on +>> plot(v2att.PPI.ppi,v5att.PPI.ppi,'r.'); +\end{verbatim} +\item To plot the best fit lines type the following first for \texttt{NoAttention} +\begin{verbatim} +>> x = v2noatt.PPI.ppi(:); +>> x = [x, ones(size(x))]; +>> y = v5noatt.PPI.ppi(:); +>> B = x\y; +>> y1 = B(1)*x(:,1)+B(2); +>> plot(x(:,1),y1,'k-'); +\end{verbatim} +\item Then for \texttt{Attention} +\begin{verbatim} +>> x = v2att.PPI.ppi(:); +>> x = [x, ones(size(x))]; +>> y = v5att.PPI.ppi(:); +>> B = x\y; +>> y1 = B(1)*x(:,1)+B(2); +>> plot(x(:,1),y1,'r-'); +>> legend('No Attention','Attention') +>> xlabel('V2 activity') +>> ylabel('V5 response') +>> title('Psychophysiologic Interaction') +\end{verbatim} +\end{enumerate} + +\begin{figure}[!ht] +\centering\includegraphics[width=85mm]{ppi/figures/Fig16.png} +\caption{\em Graph demonstrating PPI interaction.} +\label{fig:ppi16} +\end{figure} diff --git a/matlabbatch/@cfg_branch/cfg_branch.m b/matlabbatch/@cfg_branch/cfg_branch.m index f393358..e1a28ab 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 1862 2008-06-30 14:12:49Z volkmar $ +% $Id: cfg_branch.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 1862 $'; %#ok +rev = '$Rev: 3944 $'; %#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/list.m b/matlabbatch/@cfg_branch/list.m index 0eb7d2d..784232f 100644 --- a/matlabbatch/@cfg_branch/list.m +++ b/matlabbatch/@cfg_branch/list.m @@ -51,9 +51,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: list.m 2085 2008-09-12 10:26:59Z volkmar $ +% $Id: list.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 2085 $'; %#ok +rev = '$Rev: 3944 $'; %#ok if match(item, spec) id = {struct('type', {}, 'subs', {})}; @@ -105,7 +105,7 @@ case fieldnames(item) if nargin > 3 [id1 stop1 val1] = list(citems{k}, spec, tropts, fn); for l = 1:numel(fn) - val{l} = {val{l}{:} val1{l}{:}}; + val{l} = [val{l}(:); val1{l}(:)]'; end; else [id1 stop1] = list(citems{k}, spec, tropts); @@ -113,7 +113,7 @@ case fieldnames(item) if ~isempty(id1) idsubs(2).subs = {k}; for l = 1:numel(id1) - id = {id{:} [idsubs id1{l}]}; + id = [id(:); {[idsubs id1{l}]}]'; end; stop = [stop stop1]; tropts.cnt = tropts.cnt + numel(id1); diff --git a/matlabbatch/@cfg_branch/showdoc.m b/matlabbatch/@cfg_branch/showdoc.m index 8483467..e476648 100644 --- a/matlabbatch/@cfg_branch/showdoc.m +++ b/matlabbatch/@cfg_branch/showdoc.m @@ -10,9 +10,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: showdoc.m 2085 2008-09-12 10:26:59Z volkmar $ +% $Id: showdoc.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 2085 $'; %#ok +rev = '$Rev: 3944 $'; %#ok str = showmydoc(item, indent); str{end+1} = ''; @@ -20,6 +20,6 @@ citems = subsref(item, substruct('.','val')); for k = 1:numel(citems) str1 = showdoc(citems{k}, sprintf('%s%d.', indent, k)); - str = {str{:} str1{:}}; + str = [str(:); str1(:)]'; str{end+1} = ''; end; \ No newline at end of file diff --git a/matlabbatch/@cfg_branch/subsasgn.m b/matlabbatch/@cfg_branch/subsasgn.m index 695ca77..4424009 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 1973 2008-08-01 11:52:41Z volkmar $ +% $Id: subsasgn.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 1973 $'; %#ok +rev = '$Rev: 3944 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -47,7 +47,7 @@ par_class = 'cfg_branch'; pf1 = subs_fields(item.cfg_branch); pf2 = subs_fields(cfg_item); - par_fields = {pf1{:} pf2{:}}; + par_fields = [pf1(:); pf2(:)]'; case 'cfg_item', par_class = ''; par_fields = {}; diff --git a/matlabbatch/@cfg_branch/subsref.m b/matlabbatch/@cfg_branch/subsref.m index 9428eed..02c14bc 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 2512 2008-12-01 13:21:29Z volkmar $ +% $Id: subsref.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 2512 $'; %#ok +rev = '$Rev: 3944 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -38,7 +38,7 @@ par_class = 'cfg_branch'; pf1 = subs_fields(item.cfg_branch); pf2 = subs_fields(cfg_item); - par_fields = {pf1{:} pf2{:}}; + par_fields = [pf1(:); pf2(:)]'; case 'cfg_item', par_class = ''; par_fields = {}; diff --git a/matlabbatch/@cfg_choice/cfg_choice.m b/matlabbatch/@cfg_choice/cfg_choice.m index 77c1a2f..5a74817 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 1862 2008-06-30 14:12:49Z volkmar $ +% $Id: cfg_choice.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 1862 $'; %#ok +rev = '$Rev: 3944 $'; %#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/fieldnames.m b/matlabbatch/@cfg_choice/fieldnames.m index 93e3e59..00fe191 100644 --- a/matlabbatch/@cfg_choice/fieldnames.m +++ b/matlabbatch/@cfg_choice/fieldnames.m @@ -10,11 +10,11 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: fieldnames.m 1716 2008-05-23 08:18:45Z volkmar $ +% $Id: fieldnames.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 1716 $'; %#ok +rev = '$Rev: 3944 $'; %#ok fn1 = fieldnames(item.cfg_item); fn2 = mysubs_fields; -fn = {fn1{:} fn2{:}}; \ No newline at end of file +fn = [fn1(:); fn2(:)]'; \ No newline at end of file diff --git a/matlabbatch/@cfg_choice/list.m b/matlabbatch/@cfg_choice/list.m index 0eb7d2d..784232f 100644 --- a/matlabbatch/@cfg_choice/list.m +++ b/matlabbatch/@cfg_choice/list.m @@ -51,9 +51,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: list.m 2085 2008-09-12 10:26:59Z volkmar $ +% $Id: list.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 2085 $'; %#ok +rev = '$Rev: 3944 $'; %#ok if match(item, spec) id = {struct('type', {}, 'subs', {})}; @@ -105,7 +105,7 @@ case fieldnames(item) if nargin > 3 [id1 stop1 val1] = list(citems{k}, spec, tropts, fn); for l = 1:numel(fn) - val{l} = {val{l}{:} val1{l}{:}}; + val{l} = [val{l}(:); val1{l}(:)]'; end; else [id1 stop1] = list(citems{k}, spec, tropts); @@ -113,7 +113,7 @@ case fieldnames(item) if ~isempty(id1) idsubs(2).subs = {k}; for l = 1:numel(id1) - id = {id{:} [idsubs id1{l}]}; + id = [id(:); {[idsubs id1{l}]}]'; end; stop = [stop stop1]; tropts.cnt = tropts.cnt + numel(id1); diff --git a/matlabbatch/@cfg_choice/showdoc.m b/matlabbatch/@cfg_choice/showdoc.m index 266f6da..a99f736 100644 --- a/matlabbatch/@cfg_choice/showdoc.m +++ b/matlabbatch/@cfg_choice/showdoc.m @@ -10,9 +10,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: showdoc.m 2085 2008-09-12 10:26:59Z volkmar $ +% $Id: showdoc.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 2085 $'; %#ok +rev = '$Rev: 3944 $'; %#ok str = showmydoc(item, indent); str{end+1} = ''; @@ -20,6 +20,6 @@ citems = subsref(item, substruct('.','values')); for k = 1:numel(citems) str1 = showdoc(citems{k}, sprintf('%s%d.', indent, k)); - str = {str{:} str1{:}}; + str = [str(:); str1(:)]'; str{end+1} = ''; end; \ No newline at end of file diff --git a/matlabbatch/@cfg_choice/subsasgn.m b/matlabbatch/@cfg_choice/subsasgn.m index 695ca77..4424009 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 1973 2008-08-01 11:52:41Z volkmar $ +% $Id: subsasgn.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 1973 $'; %#ok +rev = '$Rev: 3944 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -47,7 +47,7 @@ par_class = 'cfg_branch'; pf1 = subs_fields(item.cfg_branch); pf2 = subs_fields(cfg_item); - par_fields = {pf1{:} pf2{:}}; + par_fields = [pf1(:); pf2(:)]'; case 'cfg_item', par_class = ''; par_fields = {}; diff --git a/matlabbatch/@cfg_choice/subsref.m b/matlabbatch/@cfg_choice/subsref.m index 9428eed..02c14bc 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 2512 2008-12-01 13:21:29Z volkmar $ +% $Id: subsref.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 2512 $'; %#ok +rev = '$Rev: 3944 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -38,7 +38,7 @@ par_class = 'cfg_branch'; pf1 = subs_fields(item.cfg_branch); pf2 = subs_fields(cfg_item); - par_fields = {pf1{:} pf2{:}}; + par_fields = [pf1(:); pf2(:)]'; case 'cfg_item', par_class = ''; par_fields = {}; diff --git a/matlabbatch/@cfg_const/cfg_const.m b/matlabbatch/@cfg_const/cfg_const.m index 7fb4765..2198cb6 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 1862 2008-06-30 14:12:49Z volkmar $ +% $Id: cfg_const.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 1862 $'; %#ok +rev = '$Rev: 3944 $'; %#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 695ca77..4424009 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 1973 2008-08-01 11:52:41Z volkmar $ +% $Id: subsasgn.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 1973 $'; %#ok +rev = '$Rev: 3944 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -47,7 +47,7 @@ par_class = 'cfg_branch'; pf1 = subs_fields(item.cfg_branch); pf2 = subs_fields(cfg_item); - par_fields = {pf1{:} pf2{:}}; + par_fields = [pf1(:); pf2(:)]'; case 'cfg_item', par_class = ''; par_fields = {}; diff --git a/matlabbatch/@cfg_const/subsref.m b/matlabbatch/@cfg_const/subsref.m index 9428eed..02c14bc 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 2512 2008-12-01 13:21:29Z volkmar $ +% $Id: subsref.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 2512 $'; %#ok +rev = '$Rev: 3944 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -38,7 +38,7 @@ par_class = 'cfg_branch'; pf1 = subs_fields(item.cfg_branch); pf2 = subs_fields(cfg_item); - par_fields = {pf1{:} pf2{:}}; + par_fields = [pf1(:); pf2(:)]'; case 'cfg_item', par_class = ''; par_fields = {}; diff --git a/matlabbatch/@cfg_dep/subsasgn.m b/matlabbatch/@cfg_dep/subsasgn.m index 1a6b3b5..3b46b57 100644 --- a/matlabbatch/@cfg_dep/subsasgn.m +++ b/matlabbatch/@cfg_dep/subsasgn.m @@ -20,9 +20,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: subsasgn.m 1862 2008-06-30 14:12:49Z volkmar $ +% $Id: subsasgn.m 3792 2010-03-22 13:11:36Z volkmar $ -rev = '$Rev: 1862 $'; %#ok +rev = '$Rev: 3792 $'; %#ok %% One-level subscripts %-------------------------------------------------------------------------- @@ -61,7 +61,9 @@ end end case subs_fields(dep), - if ~(isstruct(varargin{k}) && isfield(varargin{k},'type') && isfield(varargin{k},'subs')) + 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; diff --git a/matlabbatch/@cfg_entry/cfg_entry.m b/matlabbatch/@cfg_entry/cfg_entry.m index 5ff1845..ff5a7d9 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 1862 2008-06-30 14:12:49Z volkmar $ +% $Id: cfg_entry.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 1862 $'; %#ok +rev = '$Rev: 3944 $'; %#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/fieldnames.m b/matlabbatch/@cfg_entry/fieldnames.m index 93e3e59..00fe191 100644 --- a/matlabbatch/@cfg_entry/fieldnames.m +++ b/matlabbatch/@cfg_entry/fieldnames.m @@ -10,11 +10,11 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: fieldnames.m 1716 2008-05-23 08:18:45Z volkmar $ +% $Id: fieldnames.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 1716 $'; %#ok +rev = '$Rev: 3944 $'; %#ok fn1 = fieldnames(item.cfg_item); fn2 = mysubs_fields; -fn = {fn1{:} fn2{:}}; \ No newline at end of file +fn = [fn1(:); fn2(:)]'; \ No newline at end of file diff --git a/matlabbatch/@cfg_entry/subsasgn.m b/matlabbatch/@cfg_entry/subsasgn.m index 695ca77..4424009 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 1973 2008-08-01 11:52:41Z volkmar $ +% $Id: subsasgn.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 1973 $'; %#ok +rev = '$Rev: 3944 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -47,7 +47,7 @@ par_class = 'cfg_branch'; pf1 = subs_fields(item.cfg_branch); pf2 = subs_fields(cfg_item); - par_fields = {pf1{:} pf2{:}}; + par_fields = [pf1(:); pf2(:)]'; case 'cfg_item', par_class = ''; par_fields = {}; diff --git a/matlabbatch/@cfg_entry/subsref.m b/matlabbatch/@cfg_entry/subsref.m index 9428eed..02c14bc 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 2512 2008-12-01 13:21:29Z volkmar $ +% $Id: subsref.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 2512 $'; %#ok +rev = '$Rev: 3944 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -38,7 +38,7 @@ par_class = 'cfg_branch'; pf1 = subs_fields(item.cfg_branch); pf2 = subs_fields(cfg_item); - par_fields = {pf1{:} pf2{:}}; + par_fields = [pf1(:); pf2(:)]'; case 'cfg_item', par_class = ''; par_fields = {}; diff --git a/matlabbatch/@cfg_exbranch/cfg_exbranch.m b/matlabbatch/@cfg_exbranch/cfg_exbranch.m index 6de68bc..ea3f85f 100644 --- a/matlabbatch/@cfg_exbranch/cfg_exbranch.m +++ b/matlabbatch/@cfg_exbranch/cfg_exbranch.m @@ -53,9 +53,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: cfg_exbranch.m 1862 2008-06-30 14:12:49Z volkmar $ +% $Id: cfg_exbranch.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 1862 $'; %#ok +rev = '$Rev: 3944 $'; %#ok myclass = mfilename; % Get local fields and defaults from private/mysubs_fields @@ -66,7 +66,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)+1 && ... - all(isfield(varargin{1}, {fn{:} 'cfg_branch'})) + all(isfield(varargin{1}, [fn(:)' {'cfg_branch'}])) bitem = varargin{1}.cfg_branch; sitem = rmfield(varargin{1},{'cfg_branch'}); item = class(sitem, myclass, bitem); diff --git a/matlabbatch/@cfg_exbranch/fieldnames.m b/matlabbatch/@cfg_exbranch/fieldnames.m index 1acc1e4..af115e3 100644 --- a/matlabbatch/@cfg_exbranch/fieldnames.m +++ b/matlabbatch/@cfg_exbranch/fieldnames.m @@ -10,11 +10,11 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: fieldnames.m 1716 2008-05-23 08:18:45Z volkmar $ +% $Id: fieldnames.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 1716 $'; %#ok +rev = '$Rev: 3944 $'; %#ok fn1 = fieldnames(item.cfg_branch); fn2 = mysubs_fields; -fn = {fn1{:} fn2{:}}; \ No newline at end of file +fn = [fn1(:); fn2(:)]'; \ No newline at end of file diff --git a/matlabbatch/@cfg_exbranch/subsasgn.m b/matlabbatch/@cfg_exbranch/subsasgn.m index 695ca77..4424009 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 1973 2008-08-01 11:52:41Z volkmar $ +% $Id: subsasgn.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 1973 $'; %#ok +rev = '$Rev: 3944 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -47,7 +47,7 @@ par_class = 'cfg_branch'; pf1 = subs_fields(item.cfg_branch); pf2 = subs_fields(cfg_item); - par_fields = {pf1{:} pf2{:}}; + par_fields = [pf1(:); pf2(:)]'; case 'cfg_item', par_class = ''; par_fields = {}; diff --git a/matlabbatch/@cfg_exbranch/subsref.m b/matlabbatch/@cfg_exbranch/subsref.m index 9428eed..02c14bc 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 2512 2008-12-01 13:21:29Z volkmar $ +% $Id: subsref.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 2512 $'; %#ok +rev = '$Rev: 3944 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -38,7 +38,7 @@ par_class = 'cfg_branch'; pf1 = subs_fields(item.cfg_branch); pf2 = subs_fields(cfg_item); - par_fields = {pf1{:} pf2{:}}; + par_fields = [pf1(:); pf2(:)]'; case 'cfg_item', par_class = ''; par_fields = {}; diff --git a/matlabbatch/@cfg_files/cfg_files.m b/matlabbatch/@cfg_files/cfg_files.m index c049494..1095681 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 1862 2008-06-30 14:12:49Z volkmar $ +% $Id: cfg_files.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 1862 $'; %#ok +rev = '$Rev: 3944 $'; %#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/fieldnames.m b/matlabbatch/@cfg_files/fieldnames.m index 93e3e59..00fe191 100644 --- a/matlabbatch/@cfg_files/fieldnames.m +++ b/matlabbatch/@cfg_files/fieldnames.m @@ -10,11 +10,11 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: fieldnames.m 1716 2008-05-23 08:18:45Z volkmar $ +% $Id: fieldnames.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 1716 $'; %#ok +rev = '$Rev: 3944 $'; %#ok fn1 = fieldnames(item.cfg_item); fn2 = mysubs_fields; -fn = {fn1{:} fn2{:}}; \ No newline at end of file +fn = [fn1(:); fn2(:)]'; \ No newline at end of file diff --git a/matlabbatch/@cfg_files/subsasgn.m b/matlabbatch/@cfg_files/subsasgn.m index 695ca77..4424009 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 1973 2008-08-01 11:52:41Z volkmar $ +% $Id: subsasgn.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 1973 $'; %#ok +rev = '$Rev: 3944 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -47,7 +47,7 @@ par_class = 'cfg_branch'; pf1 = subs_fields(item.cfg_branch); pf2 = subs_fields(cfg_item); - par_fields = {pf1{:} pf2{:}}; + par_fields = [pf1(:); pf2(:)]'; case 'cfg_item', par_class = ''; par_fields = {}; diff --git a/matlabbatch/@cfg_files/subsref.m b/matlabbatch/@cfg_files/subsref.m index 9428eed..02c14bc 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 2512 2008-12-01 13:21:29Z volkmar $ +% $Id: subsref.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 2512 $'; %#ok +rev = '$Rev: 3944 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -38,7 +38,7 @@ par_class = 'cfg_branch'; pf1 = subs_fields(item.cfg_branch); pf2 = subs_fields(cfg_item); - par_fields = {pf1{:} pf2{:}}; + par_fields = [pf1(:); pf2(:)]'; case 'cfg_item', par_class = ''; par_fields = {}; diff --git a/matlabbatch/@cfg_item/cfg_item.m b/matlabbatch/@cfg_item/cfg_item.m index 582fe90..e444c38 100644 --- a/matlabbatch/@cfg_item/cfg_item.m +++ b/matlabbatch/@cfg_item/cfg_item.m @@ -78,9 +78,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: cfg_item.m 1862 2008-06-30 14:12:49Z volkmar $ +% $Id: cfg_item.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 1862 $'; %#ok +rev = '$Rev: 3944 $'; %#ok myclass = mfilename; % Get local fields and defaults from private/mysubs_fields @@ -118,7 +118,7 @@ item.name = varargin{1}; item.tag = varargin{2}; item.check = varargin{3}; - case 3 + case 4 item.name = varargin{1}; item.tag = varargin{2}; item.check = varargin{3}; diff --git a/matlabbatch/@cfg_item/resolve_deps.m b/matlabbatch/@cfg_item/resolve_deps.m index 6ab2367..6e3e499 100644 --- a/matlabbatch/@cfg_item/resolve_deps.m +++ b/matlabbatch/@cfg_item/resolve_deps.m @@ -18,9 +18,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: resolve_deps.m 2349 2008-10-17 10:36:17Z volkmar $ +% $Id: resolve_deps.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 2349 $'; %#ok +rev = '$Rev: 3944 $'; %#ok val1 = cell(size(item.val{1})); for k = 1:numel(item.val{1}) @@ -85,8 +85,8 @@ val = val{1}; else dstr = disp_deps(item, val1); - dstr = {'Dependencies resolved, but not suitable for this item.', ... - dstr{:}}; + dstr = [{'Dependencies resolved, but not suitable for this item.'}, ... + dstr(:)']; cfg_message('matlabbatch:subsasgn:val',... '%s\n', dstr{:}); return; diff --git a/matlabbatch/@cfg_item/showdoc.m b/matlabbatch/@cfg_item/showdoc.m index b13d06e..04a23b5 100644 --- a/matlabbatch/@cfg_item/showdoc.m +++ b/matlabbatch/@cfg_item/showdoc.m @@ -11,9 +11,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: showdoc.m 2085 2008-09-12 10:26:59Z volkmar $ +% $Id: showdoc.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 2085 $'; %#ok +rev = '$Rev: 3944 $'; %#ok if isempty(indent) str{1} = item.name; @@ -21,7 +21,7 @@ str = {sprintf('%s %s', indent, item.name)}; end if ~isempty(item.help) - str = {str{:} item.help{:}}; + str = [str(:); item.help(:)]'; end if ~isempty(item.def) str{end+1} = sprintf(['This item has a default value, set via a call ' ... diff --git a/matlabbatch/@cfg_item/subsasgn.m b/matlabbatch/@cfg_item/subsasgn.m index 695ca77..4424009 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 1973 2008-08-01 11:52:41Z volkmar $ +% $Id: subsasgn.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 1973 $'; %#ok +rev = '$Rev: 3944 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -47,7 +47,7 @@ par_class = 'cfg_branch'; pf1 = subs_fields(item.cfg_branch); pf2 = subs_fields(cfg_item); - par_fields = {pf1{:} pf2{:}}; + par_fields = [pf1(:); pf2(:)]'; case 'cfg_item', par_class = ''; par_fields = {}; diff --git a/matlabbatch/@cfg_item/subsref.m b/matlabbatch/@cfg_item/subsref.m index 9428eed..02c14bc 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 2512 2008-12-01 13:21:29Z volkmar $ +% $Id: subsref.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 2512 $'; %#ok +rev = '$Rev: 3944 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -38,7 +38,7 @@ par_class = 'cfg_branch'; pf1 = subs_fields(item.cfg_branch); pf2 = subs_fields(cfg_item); - par_fields = {pf1{:} pf2{:}}; + par_fields = [pf1(:); pf2(:)]'; case 'cfg_item', par_class = ''; par_fields = {}; diff --git a/matlabbatch/@cfg_menu/cfg_menu.m b/matlabbatch/@cfg_menu/cfg_menu.m index 31c69e4..9802deb 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 1862 2008-06-30 14:12:49Z volkmar $ +% $Id: cfg_menu.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 1862 $'; %#ok +rev = '$Rev: 3944 $'; %#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/fieldnames.m b/matlabbatch/@cfg_menu/fieldnames.m index 93e3e59..00fe191 100644 --- a/matlabbatch/@cfg_menu/fieldnames.m +++ b/matlabbatch/@cfg_menu/fieldnames.m @@ -10,11 +10,11 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: fieldnames.m 1716 2008-05-23 08:18:45Z volkmar $ +% $Id: fieldnames.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 1716 $'; %#ok +rev = '$Rev: 3944 $'; %#ok fn1 = fieldnames(item.cfg_item); fn2 = mysubs_fields; -fn = {fn1{:} fn2{:}}; \ No newline at end of file +fn = [fn1(:); fn2(:)]'; \ No newline at end of file diff --git a/matlabbatch/@cfg_menu/subsasgn.m b/matlabbatch/@cfg_menu/subsasgn.m index 695ca77..4424009 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 1973 2008-08-01 11:52:41Z volkmar $ +% $Id: subsasgn.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 1973 $'; %#ok +rev = '$Rev: 3944 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -47,7 +47,7 @@ par_class = 'cfg_branch'; pf1 = subs_fields(item.cfg_branch); pf2 = subs_fields(cfg_item); - par_fields = {pf1{:} pf2{:}}; + par_fields = [pf1(:); pf2(:)]'; case 'cfg_item', par_class = ''; par_fields = {}; diff --git a/matlabbatch/@cfg_menu/subsref.m b/matlabbatch/@cfg_menu/subsref.m index 9428eed..02c14bc 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 2512 2008-12-01 13:21:29Z volkmar $ +% $Id: subsref.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 2512 $'; %#ok +rev = '$Rev: 3944 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -38,7 +38,7 @@ par_class = 'cfg_branch'; pf1 = subs_fields(item.cfg_branch); pf2 = subs_fields(cfg_item); - par_fields = {pf1{:} pf2{:}}; + par_fields = [pf1(:); pf2(:)]'; case 'cfg_item', par_class = ''; par_fields = {}; diff --git a/matlabbatch/@cfg_repeat/cfg_repeat.m b/matlabbatch/@cfg_repeat/cfg_repeat.m index ce1c99f..9b3ad4c 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 1862 2008-06-30 14:12:49Z volkmar $ +% $Id: cfg_repeat.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 1862 $'; %#ok +rev = '$Rev: 3944 $'; %#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/fieldnames.m b/matlabbatch/@cfg_repeat/fieldnames.m index 93e3e59..00fe191 100644 --- a/matlabbatch/@cfg_repeat/fieldnames.m +++ b/matlabbatch/@cfg_repeat/fieldnames.m @@ -10,11 +10,11 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: fieldnames.m 1716 2008-05-23 08:18:45Z volkmar $ +% $Id: fieldnames.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 1716 $'; %#ok +rev = '$Rev: 3944 $'; %#ok fn1 = fieldnames(item.cfg_item); fn2 = mysubs_fields; -fn = {fn1{:} fn2{:}}; \ No newline at end of file +fn = [fn1(:); fn2(:)]'; \ No newline at end of file diff --git a/matlabbatch/@cfg_repeat/list.m b/matlabbatch/@cfg_repeat/list.m index 0eb7d2d..784232f 100644 --- a/matlabbatch/@cfg_repeat/list.m +++ b/matlabbatch/@cfg_repeat/list.m @@ -51,9 +51,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: list.m 2085 2008-09-12 10:26:59Z volkmar $ +% $Id: list.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 2085 $'; %#ok +rev = '$Rev: 3944 $'; %#ok if match(item, spec) id = {struct('type', {}, 'subs', {})}; @@ -105,7 +105,7 @@ case fieldnames(item) if nargin > 3 [id1 stop1 val1] = list(citems{k}, spec, tropts, fn); for l = 1:numel(fn) - val{l} = {val{l}{:} val1{l}{:}}; + val{l} = [val{l}(:); val1{l}(:)]'; end; else [id1 stop1] = list(citems{k}, spec, tropts); @@ -113,7 +113,7 @@ case fieldnames(item) if ~isempty(id1) idsubs(2).subs = {k}; for l = 1:numel(id1) - id = {id{:} [idsubs id1{l}]}; + id = [id(:); {[idsubs id1{l}]}]'; end; stop = [stop stop1]; tropts.cnt = tropts.cnt + numel(id1); diff --git a/matlabbatch/@cfg_repeat/showdoc.m b/matlabbatch/@cfg_repeat/showdoc.m index a6e301e..f9f71e5 100644 --- a/matlabbatch/@cfg_repeat/showdoc.m +++ b/matlabbatch/@cfg_repeat/showdoc.m @@ -10,9 +10,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: showdoc.m 2085 2008-09-12 10:26:59Z volkmar $ +% $Id: showdoc.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 2085 $'; %#ok +rev = '$Rev: 3944 $'; %#ok str = showmydoc(item,indent); str{end+1} = ''; @@ -20,6 +20,6 @@ citems = subsref(item, substruct('.','values')); for k = 1:numel(citems) str1 = showdoc(citems{k}, sprintf('%s%d.', indent, k)); - str = {str{:} str1{:}}; + str = [str(:); str1(:)]'; str{end+1} = ''; end; \ No newline at end of file diff --git a/matlabbatch/@cfg_repeat/subsasgn.m b/matlabbatch/@cfg_repeat/subsasgn.m index 695ca77..4424009 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 1973 2008-08-01 11:52:41Z volkmar $ +% $Id: subsasgn.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 1973 $'; %#ok +rev = '$Rev: 3944 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -47,7 +47,7 @@ par_class = 'cfg_branch'; pf1 = subs_fields(item.cfg_branch); pf2 = subs_fields(cfg_item); - par_fields = {pf1{:} pf2{:}}; + par_fields = [pf1(:); pf2(:)]'; case 'cfg_item', par_class = ''; par_fields = {}; diff --git a/matlabbatch/@cfg_repeat/subsref.m b/matlabbatch/@cfg_repeat/subsref.m index 9428eed..02c14bc 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 2512 2008-12-01 13:21:29Z volkmar $ +% $Id: subsref.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 2512 $'; %#ok +rev = '$Rev: 3944 $'; %#ok persistent local_mysubs_fields; persistent par_class; @@ -38,7 +38,7 @@ par_class = 'cfg_branch'; pf1 = subs_fields(item.cfg_branch); pf2 = subs_fields(cfg_item); - par_fields = {pf1{:} pf2{:}}; + par_fields = [pf1(:); pf2(:)]'; case 'cfg_item', par_class = ''; par_fields = {}; diff --git a/matlabbatch/cfg_basicio/cfg_cfg_basicio.m b/matlabbatch/cfg_basicio/cfg_cfg_basicio.m index 63a9e9f..381c9db 100644 --- a/matlabbatch/cfg_basicio/cfg_cfg_basicio.m +++ b/matlabbatch/cfg_basicio/cfg_cfg_basicio.m @@ -4,7 +4,7 @@ % by MATLABBATCH using ConfGUI. It describes menu structure, validity % constraints and links to run time code. % Changes to this file will be overwritten if the ConfGUI batch is executed again. -% Created at 2009-11-20 18:04:58. +% Created at 2010-06-11 13:56:06. % --------------------------------------------------------------------- % files Files to move/copy/delete % --------------------------------------------------------------------- @@ -355,11 +355,11 @@ rec.help = {'Files can be selected from the specified directory only or from the specified directory and all its subdirectories.'}; rec.labels = { 'Yes' - 'Yes' + 'No' }'; rec.values = { - true - false + 'FPListRec' + 'FPList' }'; % --------------------------------------------------------------------- % file_fplist File Selector (Batch Mode) @@ -642,7 +642,7 @@ input.name = 'Input variable'; input.help = {'Enter the input variable.'}; input.strtype = 'e'; -input.num = [1 1]; +input.num = [Inf Inf]; % --------------------------------------------------------------------- % subsfield Field reference % --------------------------------------------------------------------- @@ -703,12 +703,108 @@ subsreference.num = [1 Inf]; subsreference.forcestruct = true; % --------------------------------------------------------------------- +% s String +% --------------------------------------------------------------------- +s = cfg_const; +s.tag = 's'; +s.name = 'String'; +s.val{1}{1}.name = 'strtype'; +s.val{1}{1}.value = 's'; +% --------------------------------------------------------------------- +% n Natural Number +% --------------------------------------------------------------------- +n = cfg_const; +n.tag = 'n'; +n.name = 'Natural Number'; +n.val{1}{1}.name = 'strtype'; +n.val{1}{1}.value = 'n'; +% --------------------------------------------------------------------- +% w Whole Number +% --------------------------------------------------------------------- +w = cfg_const; +w.tag = 'w'; +w.name = 'Whole Number'; +w.val{1}{1}.name = 'strtype'; +w.val{1}{1}.value = 'w'; +% --------------------------------------------------------------------- +% i Integer +% --------------------------------------------------------------------- +i = cfg_const; +i.tag = 'i'; +i.name = 'Integer'; +i.val{1}{1}.name = 'strtype'; +i.val{1}{1}.value = 'i'; +% --------------------------------------------------------------------- +% r Real Number +% --------------------------------------------------------------------- +r = cfg_const; +r.tag = 'r'; +r.name = 'Real Number'; +r.val{1}{1}.name = 'strtype'; +r.val{1}{1}.value = 'r'; +% --------------------------------------------------------------------- +% f Function Handle +% --------------------------------------------------------------------- +f = cfg_const; +f.tag = 'f'; +f.name = 'Function Handle'; +f.val{1}{1}.name = 'strtype'; +f.val{1}{1}.value = 'f'; +% --------------------------------------------------------------------- +% e Other Variable +% --------------------------------------------------------------------- +e = cfg_const; +e.tag = 'e'; +e.name = 'Other Variable'; +e.val{1}{1}.name = 'strtype'; +e.val{1}{1}.value = 'e'; +% --------------------------------------------------------------------- +% nifti NIfTI Image File(s) +% --------------------------------------------------------------------- +nifti = cfg_const; +nifti.tag = 'nifti'; +nifti.name = 'NIfTI Image File(s)'; +nifti.val{1}{1}.name = 'filter'; +nifti.val{1}{1}.value = 'image'; +% --------------------------------------------------------------------- +% mat .mat File(s) +% --------------------------------------------------------------------- +mat = cfg_const; +mat.tag = 'mat'; +mat.name = '.mat File(s)'; +mat.val{1}{1}.name = 'filter'; +mat.val{1}{1}.value = 'mat'; +% --------------------------------------------------------------------- +% any Any File(s) +% --------------------------------------------------------------------- +any = cfg_const; +any.tag = 'any'; +any.name = 'Any File(s)'; +any.val{1}{1}.name = 'filter'; +any.val{1}{1}.value = 'any'; +% --------------------------------------------------------------------- +% dir Directories +% --------------------------------------------------------------------- +dir = cfg_const; +dir.tag = 'dir'; +dir.name = 'Directories'; +dir.val{1}{1}.name = 'filter'; +dir.val{1}{1}.value = 'dir'; +% --------------------------------------------------------------------- +% tgt_spec Type of referenced Variable +% --------------------------------------------------------------------- +tgt_spec = cfg_choice; +tgt_spec.tag = 'tgt_spec'; +tgt_spec.name = 'Type of referenced Variable'; +tgt_spec.help = {'This setting determines where the contents of the variable will be available as a dependency.'}; +tgt_spec.values = {s n w i r f e nifti mat any dir }; +% --------------------------------------------------------------------- % subsrefvar Access part of MATLAB variable % --------------------------------------------------------------------- subsrefvar = cfg_exbranch; subsrefvar.tag = 'subsrefvar'; subsrefvar.name = 'Access part of MATLAB variable'; -subsrefvar.val = {input subsreference }; +subsrefvar.val = {input subsreference tgt_spec }; subsrefvar.prog = @(job)cfg_run_subsrefvar('run',job); subsrefvar.vout = @(job)cfg_run_subsrefvar('vout',job); % --------------------------------------------------------------------- diff --git a/matlabbatch/cfg_basicio/cfg_cfg_basicio_def.m b/matlabbatch/cfg_basicio/cfg_cfg_basicio_def.m index ec59fdf..d524b3a 100644 --- a/matlabbatch/cfg_basicio/cfg_cfg_basicio_def.m +++ b/matlabbatch/cfg_basicio/cfg_cfg_basicio_def.m @@ -5,7 +5,7 @@ % menu items and provides a full documentation of all fields that may % be present in a job variable for this application. % Changes to this file will be overwritten if the ConfGUI batch is executed again. -% Created at 2009-11-20 18:04:58. +% Created at 2010-06-11 13:56:06. cfg_basicio_def.file_move.files = ''; cfg_basicio_def.file_move.action.moveto = ''; cfg_basicio_def.file_move.action.copyto = ''; @@ -49,6 +49,28 @@ cfg_basicio_def.subsrefvar.subsreference.subsfield = ''; cfg_basicio_def.subsrefvar.subsreference.subsindc = {''}; cfg_basicio_def.subsrefvar.subsreference.subsinda = {''}; +cfg_basicio_def.subsrefvar.tgt_spec.s{1}.name = 'strtype'; +cfg_basicio_def.subsrefvar.tgt_spec.s{1}.value = 's'; +cfg_basicio_def.subsrefvar.tgt_spec.n{1}.name = 'strtype'; +cfg_basicio_def.subsrefvar.tgt_spec.n{1}.value = 'n'; +cfg_basicio_def.subsrefvar.tgt_spec.w{1}.name = 'strtype'; +cfg_basicio_def.subsrefvar.tgt_spec.w{1}.value = 'w'; +cfg_basicio_def.subsrefvar.tgt_spec.i{1}.name = 'strtype'; +cfg_basicio_def.subsrefvar.tgt_spec.i{1}.value = 'i'; +cfg_basicio_def.subsrefvar.tgt_spec.r{1}.name = 'strtype'; +cfg_basicio_def.subsrefvar.tgt_spec.r{1}.value = 'r'; +cfg_basicio_def.subsrefvar.tgt_spec.f{1}.name = 'strtype'; +cfg_basicio_def.subsrefvar.tgt_spec.f{1}.value = 'f'; +cfg_basicio_def.subsrefvar.tgt_spec.e{1}.name = 'strtype'; +cfg_basicio_def.subsrefvar.tgt_spec.e{1}.value = 'e'; +cfg_basicio_def.subsrefvar.tgt_spec.nifti{1}.name = 'filter'; +cfg_basicio_def.subsrefvar.tgt_spec.nifti{1}.value = 'image'; +cfg_basicio_def.subsrefvar.tgt_spec.mat{1}.name = 'filter'; +cfg_basicio_def.subsrefvar.tgt_spec.mat{1}.value = 'mat'; +cfg_basicio_def.subsrefvar.tgt_spec.any{1}.name = 'filter'; +cfg_basicio_def.subsrefvar.tgt_spec.any{1}.value = 'any'; +cfg_basicio_def.subsrefvar.tgt_spec.dir{1}.name = 'filter'; +cfg_basicio_def.subsrefvar.tgt_spec.dir{1}.value = 'dir'; cfg_basicio_def.cfg_assignin.name = ''; cfg_basicio_def.cfg_assignin.output = ''; cfg_basicio_def.runjobs.jobs = ''; diff --git a/matlabbatch/cfg_basicio/cfg_load_vars.m b/matlabbatch/cfg_basicio/cfg_load_vars.m index 7dedcfe..d5d69c4 100644 --- a/matlabbatch/cfg_basicio/cfg_load_vars.m +++ b/matlabbatch/cfg_basicio/cfg_load_vars.m @@ -22,9 +22,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: cfg_load_vars.m 2787 2009-02-25 08:02:53Z volkmar $ +% $Id: cfg_load_vars.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 2787 $'; %#ok +rev = '$Rev: 3944 $'; %#ok if ischar(cmd) switch lower(cmd) @@ -35,6 +35,7 @@ if isfield(job.loadvars,'allvars') out{1} = var; else + out = cell(size(job.loadvars.varname)); for k = 1:numel(job.loadvars.varname) try out{k} = var.(job.loadvars.varname{k}); diff --git a/matlabbatch/cfg_basicio/cfg_run_call_matlab.m b/matlabbatch/cfg_basicio/cfg_run_call_matlab.m index c70304c..1523358 100644 --- a/matlabbatch/cfg_basicio/cfg_run_call_matlab.m +++ b/matlabbatch/cfg_basicio/cfg_run_call_matlab.m @@ -43,9 +43,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: cfg_run_call_matlab.m 3591 2009-11-23 10:19:57Z volkmar $ +% $Id: cfg_run_call_matlab.m 3810 2010-04-07 12:42:32Z volkmar $ -rev = '$Rev: 3591 $'; %#ok +rev = '$Rev: 3810 $'; %#ok if ischar(cmd) switch lower(cmd) @@ -78,7 +78,7 @@ dep(k) = cfg_dep; dep(k).sname = sprintf('Call MATLAB: output %d - %s %s', k, char(fieldnames(job.outputs{k})), char(fieldnames(job.outputs{k}.(char(fieldnames(job.outputs{k})))))); dep(k).src_output = substruct('.','outputs','{}',{k}); - dep(k).tgt_spec = cfg_findspec({{'strtype','e', char(fieldnames(job.outputs{k})), job.outputs{k}.(char(fieldnames(job.outputs{k})))}}); + dep(k).tgt_spec = cfg_findspec({{'strtype','e', char(fieldnames(job.outputs{k})), char(fieldnames(job.outputs{k}.(char(fieldnames(job.outputs{k})))))}}); end varargout{1} = dep; case 'check' diff --git a/matlabbatch/cfg_basicio/cfg_run_file_move.m b/matlabbatch/cfg_basicio/cfg_run_file_move.m index 6dd1938..4f7e8af 100644 --- a/matlabbatch/cfg_basicio/cfg_run_file_move.m +++ b/matlabbatch/cfg_basicio/cfg_run_file_move.m @@ -11,22 +11,23 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: cfg_run_file_move.m 2035 2008-09-03 15:48:30Z volkmar $ +% $Id: cfg_run_file_move.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 2035 $'; %#ok +rev = '$Rev: 3944 $'; %#ok action = fieldnames(job.action); action = action{1}; if strcmp(action, 'delete') for k = 1:numel(job.files) - [p n e v] = fileparts(job.files{k}); - delete(job.files{k}); - if strcmp(e,'.img') || strcmp(e,'.nii') + [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'])); end end + delete(fullfile(p, [n e])); end out = []; else @@ -54,23 +55,22 @@ end out.files = {}; for k = 1:numel(job.files) - [p n e v] = fileparts(job.files{k}); + [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}); - v = ''; end end if any(strcmp(action, {'copyren','moveren'})) - on = regexprep(n, patrep{1,:}, patrep{2,:}); + on = regexprep(n, patrep(1,:), patrep(2,:)); if job.action.(action).unique on = sprintf('%s_%0*d', on, nw, k); end else on = n; end - nam = {[n e v]}; - onam = {[on e v]}; + nam = {[n e]}; + onam = {[on e]}; if any(strcmp(e, {'.nii','.img'})) nam{2} = [n '.hdr']; onam{2} = [on '.hdr']; diff --git a/matlabbatch/cfg_basicio/cfg_run_runjobs.m b/matlabbatch/cfg_basicio/cfg_run_runjobs.m index b96f10c..582d2b8 100644 --- a/matlabbatch/cfg_basicio/cfg_run_runjobs.m +++ b/matlabbatch/cfg_basicio/cfg_run_runjobs.m @@ -12,12 +12,12 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: cfg_run_runjobs.m 3402 2009-09-15 12:08:33Z volkmar $ +% $Id: cfg_run_runjobs.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 3402 $'; %#ok +rev = '$Rev: 3944 $'; %#ok if isfield(job.save, 'savejobs') - [p n e v] = fileparts(job.save.savejobs.outstub); + [p n e] = fileparts(job.save.savejobs.outstub); outfmt = fullfile(job.save.savejobs.outdir{1}, sprintf('%s_%%0%dd.m', n, ceil(log10(numel(job.inputs))+1))); end; hjobs = cell(size(job.inputs)); @@ -52,7 +52,7 @@ cfg_util('run', cjob); out.jout = cfg_util('getalloutputs', cjob); % if isfield(job.save, 'savejobs') -% [p n e v] = fileparts(job.save.savejobs.outstub); +% [p n e] = fileparts(job.save.savejobs.outstub); % out.jobrun{1} = fullfile(p, [n '_run.m']); % cfg_util('saverun', cjob, out.jobrun{1}); % end; diff --git a/matlabbatch/cfg_basicio/cfg_run_save_vars.m b/matlabbatch/cfg_basicio/cfg_run_save_vars.m index 25de47a..de73b06 100644 --- a/matlabbatch/cfg_basicio/cfg_run_save_vars.m +++ b/matlabbatch/cfg_basicio/cfg_run_save_vars.m @@ -10,11 +10,11 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: cfg_run_save_vars.m 1716 2008-05-23 08:18:45Z volkmar $ +% $Id: cfg_run_save_vars.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 1716 $'; %#ok +rev = '$Rev: 3944 $'; %#ok -[p n e v] = fileparts(job.name); +[p n e] = fileparts(job.name); out.file{1} = fullfile(job.outdir{1}, [n '.mat']); for k = 1:numel(job.vars) svar.(job.vars(k).vname) = job.vars(k).vcont; diff --git a/matlabbatch/cfg_basicio/cfg_run_subsrefvar.m b/matlabbatch/cfg_basicio/cfg_run_subsrefvar.m index 14b5cf6..ddb8d5b 100644 --- a/matlabbatch/cfg_basicio/cfg_run_subsrefvar.m +++ b/matlabbatch/cfg_basicio/cfg_run_subsrefvar.m @@ -44,43 +44,36 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: cfg_run_subsrefvar.m 3591 2009-11-23 10:19:57Z volkmar $ +% $Id: cfg_run_subsrefvar.m 3948 2010-06-25 09:48:03Z volkmar $ -rev = '$Rev: 3591 $'; %#ok +rev = '$Rev: 3948 $'; %#ok if ischar(cmd) switch lower(cmd) case 'run' job = local_getjob(varargin{1}); % do computation, return results in variable out - for k = 1:numel(job.subsreference) - switch char(fieldnames(job.subsreference{k})) - case 'subsfield' - subs(k).type = '.'; - subs(k).subs = job.subsreference{k}.subsfield; - case 'subsinda' - subs(k).type = '()'; - subs(k).subs = job.subsreference{k}.subsinda; - case 'subsindc' - subs(k).type = '{}'; - subs(k).subs = job.subsreference{k}.subsindc; - if any(cellfun(@(x)(isequal(x,':')||numel(x)>1), ... - job.subsreference{k}.subsindc)) - cfg_message('cfg_basicio:subsrefvar', ... - 'Trying to access multiple cell elements - only returning first one.'); - end - end - end + subs = local_getsubs(job, true); out.output = subsref(job.input, subs); if nargout > 0 varargout{1} = out; end case 'vout' job = local_getjob(varargin{1}); + subscode = char(gencode_substruct(local_getsubs(job, false))); dep = cfg_dep; - dep.sname = 'Referenced part of variable'; + if isempty(subscode) + dep.sname = 'Referenced part of variable'; + else + dep.sname = sprintf('val%s', subscode); + end dep.src_output = substruct('.','output'); - dep.tgt_spec = cfg_findspec({{'strtype','e'}}); + if isequal(job.tgt_spec,'') + dep.tgt_spec = cfg_findspec({{'strtype','e'}}); + else + fn = fieldnames(job.tgt_spec); + dep.tgt_spec = job.tgt_spec.(fn{1}); + end varargout{1} = dep; case 'check' if ischar(varargin{1}) @@ -117,6 +110,30 @@ cfg_message('ischar:cmd', 'Cmd must be a string.'); end +function subs = local_getsubs(job, cwarn) +% generate subscript structure +% generate warning for cell references if requested +subs = struct('type',{},'subs',{}); +for k = 1:numel(job.subsreference) + switch char(fieldnames(job.subsreference{k})) + case 'subsfield' + subs(k).type = '.'; + subs(k).subs = job.subsreference{k}.subsfield; + case 'subsinda' + subs(k).type = '()'; + subs(k).subs = job.subsreference{k}.subsinda; + case 'subsindc' + subs(k).type = '{}'; + subs(k).subs = job.subsreference{k}.subsindc; + if cwarn && any(cellfun(@(x)(isequal(x,':')||numel(x)>1), ... + job.subsreference{k}.subsindc)) + cfg_message('cfg_basicio:subsrefvar', ... + 'Trying to access multiple cell elements - only returning first one.'); + end + end +end + + function varargout = local_defs(defstr, defval) persistent defs; if isempty(defs) diff --git a/matlabbatch/cfg_basicio/cfg_vout_file_fplist.m b/matlabbatch/cfg_basicio/cfg_vout_file_fplist.m index 91bb187..d377243 100644 --- a/matlabbatch/cfg_basicio/cfg_vout_file_fplist.m +++ b/matlabbatch/cfg_basicio/cfg_vout_file_fplist.m @@ -12,15 +12,19 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: cfg_vout_file_fplist.m 1716 2008-05-23 08:18:45Z volkmar $ +% $Id: cfg_vout_file_fplist.m 3990 2010-07-13 10:27:17Z volkmar $ -rev = '$Rev: 1716 $'; %#ok +rev = '$Rev: 3990 $'; %#ok dep(1) = cfg_dep; -dep(1).sname = 'Selected Files'; +if ~ischar(job.filter) || strcmp(job.filter,'') + dep(1).sname = 'Selected Files'; +else + dep(1).sname = sprintf('Selected Files (%s)', job.filter); +end dep(1).src_output = substruct('.','files'); -dep(1).tgt_spec = cfg_findspec({{'class','cfg_files','strtype','e'}}); +dep(1).tgt_spec = cfg_findspec({{'class','cfg_files','strtype','e'}}); % This will display for both file and dir inputs. There is no notion of "no directories" in matching. dep(2) = cfg_dep; dep(2).sname = 'Subdirectories'; dep(2).src_output = substruct('.','dirs'); -dep(2).tgt_spec = cfg_findspec({{'class','cfg_files','strtype','e'}}); +dep(2).tgt_spec = cfg_findspec({{'filter','dir','strtype','e'}}); diff --git a/matlabbatch/cfg_basicio/src/batch_basicio.m b/matlabbatch/cfg_basicio/src/batch_basicio.m deleted file mode 100644 index 33afd66..0000000 --- a/matlabbatch/cfg_basicio/src/batch_basicio.m +++ /dev/null @@ -1,1607 +0,0 @@ -%----------------------------------------------------------------------- -% Job configuration created by cfg_util (rev $Rev: 3591 $) -%----------------------------------------------------------------------- -matlabbatch{1}.menu_cfg.menu_entry.conf_files.type = 'cfg_files'; -matlabbatch{1}.menu_cfg.menu_entry.conf_files.name = 'Files to move/copy/delete'; -matlabbatch{1}.menu_cfg.menu_entry.conf_files.tag = 'files'; -matlabbatch{1}.menu_cfg.menu_entry.conf_files.filter = 'any'; -matlabbatch{1}.menu_cfg.menu_entry.conf_files.ufilter = '.*'; -matlabbatch{1}.menu_cfg.menu_entry.conf_files.dir = ''; -matlabbatch{1}.menu_cfg.menu_entry.conf_files.num = [0 Inf]; -matlabbatch{1}.menu_cfg.menu_entry.conf_files.check = []; -matlabbatch{1}.menu_cfg.menu_entry.conf_files.help = {'These files will be moved, copied or deleted.'}; -matlabbatch{1}.menu_cfg.menu_entry.conf_files.def = []; -matlabbatch{2}.menu_cfg.menu_entry.conf_files.type = 'cfg_files'; -matlabbatch{2}.menu_cfg.menu_entry.conf_files.name = 'Move to'; -matlabbatch{2}.menu_cfg.menu_entry.conf_files.tag = 'moveto'; -matlabbatch{2}.menu_cfg.menu_entry.conf_files.filter = 'dir'; -matlabbatch{2}.menu_cfg.menu_entry.conf_files.ufilter = '.*'; -matlabbatch{2}.menu_cfg.menu_entry.conf_files.dir = ''; -matlabbatch{2}.menu_cfg.menu_entry.conf_files.num = [1 1]; -matlabbatch{2}.menu_cfg.menu_entry.conf_files.check = []; -matlabbatch{2}.menu_cfg.menu_entry.conf_files.help = {'Files will be moved to the specified directory.'}; -matlabbatch{2}.menu_cfg.menu_entry.conf_files.def = []; -matlabbatch{3}.menu_cfg.menu_entry.conf_files.type = 'cfg_files'; -matlabbatch{3}.menu_cfg.menu_entry.conf_files.name = 'Copy to'; -matlabbatch{3}.menu_cfg.menu_entry.conf_files.tag = 'copyto'; -matlabbatch{3}.menu_cfg.menu_entry.conf_files.filter = 'dir'; -matlabbatch{3}.menu_cfg.menu_entry.conf_files.ufilter = '.*'; -matlabbatch{3}.menu_cfg.menu_entry.conf_files.dir = ''; -matlabbatch{3}.menu_cfg.menu_entry.conf_files.num = [1 1]; -matlabbatch{3}.menu_cfg.menu_entry.conf_files.check = []; -matlabbatch{3}.menu_cfg.menu_entry.conf_files.help = {'Files will be moved to the specified directory.'}; -matlabbatch{3}.menu_cfg.menu_entry.conf_files.def = []; -matlabbatch{4}.menu_cfg.menu_entry.conf_entry.type = 'cfg_entry'; -matlabbatch{4}.menu_cfg.menu_entry.conf_entry.name = 'Pattern'; -matlabbatch{4}.menu_cfg.menu_entry.conf_entry.tag = 'pattern'; -matlabbatch{4}.menu_cfg.menu_entry.conf_entry.strtype = 's'; -matlabbatch{4}.menu_cfg.menu_entry.conf_entry.extras = []; -matlabbatch{4}.menu_cfg.menu_entry.conf_entry.num = [1 Inf]; -matlabbatch{4}.menu_cfg.menu_entry.conf_entry.check = []; -matlabbatch{4}.menu_cfg.menu_entry.conf_entry.help = {'The regular expression pattern to look for.'}; -matlabbatch{4}.menu_cfg.menu_entry.conf_entry.def = []; -matlabbatch{5}.menu_cfg.menu_entry.conf_entry.type = 'cfg_entry'; -matlabbatch{5}.menu_cfg.menu_entry.conf_entry.name = 'Replacement'; -matlabbatch{5}.menu_cfg.menu_entry.conf_entry.tag = 'repl'; -matlabbatch{5}.menu_cfg.menu_entry.conf_entry.strtype = 's'; -matlabbatch{5}.menu_cfg.menu_entry.conf_entry.extras = []; -matlabbatch{5}.menu_cfg.menu_entry.conf_entry.num = [1 Inf]; -matlabbatch{5}.menu_cfg.menu_entry.conf_entry.check = []; -matlabbatch{5}.menu_cfg.menu_entry.conf_entry.help = {'This string (or pattern) will be inserted instead.'}; -matlabbatch{5}.menu_cfg.menu_entry.conf_entry.def = []; -matlabbatch{6}.menu_cfg.menu_struct.conf_branch.type = 'cfg_branch'; -matlabbatch{6}.menu_cfg.menu_struct.conf_branch.name = 'Pattern/Replacement Pair'; -matlabbatch{6}.menu_cfg.menu_struct.conf_branch.tag = 'patrep'; -matlabbatch{6}.menu_cfg.menu_struct.conf_branch.val{1}(1) = cfg_dep; -matlabbatch{6}.menu_cfg.menu_struct.conf_branch.val{1}(1).tname = 'Val Item'; -matlabbatch{6}.menu_cfg.menu_struct.conf_branch.val{1}(1).tgt_spec = {}; -matlabbatch{6}.menu_cfg.menu_struct.conf_branch.val{1}(1).sname = 'Entry: Pattern (cfg_entry)'; -matlabbatch{6}.menu_cfg.menu_struct.conf_branch.val{1}(1).src_exbranch = substruct('.','val', '{}',{4}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{6}.menu_cfg.menu_struct.conf_branch.val{1}(1).src_output = substruct('()',{1}); -matlabbatch{6}.menu_cfg.menu_struct.conf_branch.val{2}(1) = cfg_dep; -matlabbatch{6}.menu_cfg.menu_struct.conf_branch.val{2}(1).tname = 'Val Item'; -matlabbatch{6}.menu_cfg.menu_struct.conf_branch.val{2}(1).tgt_spec = {}; -matlabbatch{6}.menu_cfg.menu_struct.conf_branch.val{2}(1).sname = 'Entry: Replacement (cfg_entry)'; -matlabbatch{6}.menu_cfg.menu_struct.conf_branch.val{2}(1).src_exbranch = substruct('.','val', '{}',{5}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{6}.menu_cfg.menu_struct.conf_branch.val{2}(1).src_output = substruct('()',{1}); -matlabbatch{6}.menu_cfg.menu_struct.conf_branch.check = []; -matlabbatch{6}.menu_cfg.menu_struct.conf_branch.help = {}; -matlabbatch{7}.menu_cfg.menu_struct.conf_repeat.type = 'cfg_repeat'; -matlabbatch{7}.menu_cfg.menu_struct.conf_repeat.name = 'Pattern/Replacement List'; -matlabbatch{7}.menu_cfg.menu_struct.conf_repeat.tag = 'patreplist'; -matlabbatch{7}.menu_cfg.menu_struct.conf_repeat.values{1}(1) = cfg_dep; -matlabbatch{7}.menu_cfg.menu_struct.conf_repeat.values{1}(1).tname = 'Values Item'; -matlabbatch{7}.menu_cfg.menu_struct.conf_repeat.values{1}(1).tgt_spec = {}; -matlabbatch{7}.menu_cfg.menu_struct.conf_repeat.values{1}(1).sname = 'Branch: Pattern/Replacement Pair (cfg_branch)'; -matlabbatch{7}.menu_cfg.menu_struct.conf_repeat.values{1}(1).src_exbranch = substruct('.','val', '{}',{6}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{7}.menu_cfg.menu_struct.conf_repeat.values{1}(1).src_output = substruct('()',{1}); -matlabbatch{7}.menu_cfg.menu_struct.conf_repeat.num = [1 Inf]; -matlabbatch{7}.menu_cfg.menu_struct.conf_repeat.forcestruct = false; -matlabbatch{7}.menu_cfg.menu_struct.conf_repeat.check = []; -matlabbatch{7}.menu_cfg.menu_struct.conf_repeat.help = {'Regexprep supports a list of multiple patterns and corresponding replacements. These will be applied to the filename portion (without path, without extension) one after another. E.g., if your filename is ''testimage(.nii)'', and you replace ''test'' with ''xyz'' and ''xyzim'' with ''newtestim'', the final filename will be ''newtestimage.nii''.'}; -matlabbatch{8}.menu_cfg.menu_entry.conf_menu.type = 'cfg_menu'; -matlabbatch{8}.menu_cfg.menu_entry.conf_menu.name = 'Unique Filenames'; -matlabbatch{8}.menu_cfg.menu_entry.conf_menu.tag = 'unique'; -matlabbatch{8}.menu_cfg.menu_entry.conf_menu.labels = { - 'Don''t Care' - 'Append Index Number' - }'; -matlabbatch{8}.menu_cfg.menu_entry.conf_menu.values = { - false - true - }'; -matlabbatch{8}.menu_cfg.menu_entry.conf_menu.check = []; -matlabbatch{8}.menu_cfg.menu_entry.conf_menu.help = { - 'If the regexprep operation results in identical output filenames for two or more input files, these can not be written/renamed to their new location without loosing data. If you are sure that your regexprep patterns produce unique filenames, you do not need to care about this.' - 'If you choose to append a running number, it will be zero-padded to make sure alphabetical sort of filenames returns them in the same order as the input files are.' - }'; -matlabbatch{8}.menu_cfg.menu_entry.conf_menu.def = []; -matlabbatch{9}.menu_cfg.menu_struct.conf_branch.type = 'cfg_branch'; -matlabbatch{9}.menu_cfg.menu_struct.conf_branch.name = 'Move and Rename'; -matlabbatch{9}.menu_cfg.menu_struct.conf_branch.tag = 'moveren'; -matlabbatch{9}.menu_cfg.menu_struct.conf_branch.val{1}(1) = cfg_dep; -matlabbatch{9}.menu_cfg.menu_struct.conf_branch.val{1}(1).tname = 'Val Item'; -matlabbatch{9}.menu_cfg.menu_struct.conf_branch.val{1}(1).tgt_spec = {}; -matlabbatch{9}.menu_cfg.menu_struct.conf_branch.val{1}(1).sname = 'Files: Move to (cfg_files)'; -matlabbatch{9}.menu_cfg.menu_struct.conf_branch.val{1}(1).src_exbranch = substruct('.','val', '{}',{2}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{9}.menu_cfg.menu_struct.conf_branch.val{1}(1).src_output = substruct('()',{1}); -matlabbatch{9}.menu_cfg.menu_struct.conf_branch.val{2}(1) = cfg_dep; -matlabbatch{9}.menu_cfg.menu_struct.conf_branch.val{2}(1).tname = 'Val Item'; -matlabbatch{9}.menu_cfg.menu_struct.conf_branch.val{2}(1).tgt_spec = {}; -matlabbatch{9}.menu_cfg.menu_struct.conf_branch.val{2}(1).sname = 'Repeat: Pattern/Replacement List (cfg_repeat)'; -matlabbatch{9}.menu_cfg.menu_struct.conf_branch.val{2}(1).src_exbranch = substruct('.','val', '{}',{7}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{9}.menu_cfg.menu_struct.conf_branch.val{2}(1).src_output = substruct('()',{1}); -matlabbatch{9}.menu_cfg.menu_struct.conf_branch.val{3}(1) = cfg_dep; -matlabbatch{9}.menu_cfg.menu_struct.conf_branch.val{3}(1).tname = 'Val Item'; -matlabbatch{9}.menu_cfg.menu_struct.conf_branch.val{3}(1).tgt_spec = {}; -matlabbatch{9}.menu_cfg.menu_struct.conf_branch.val{3}(1).sname = 'Menu: Unique Filenames (cfg_menu)'; -matlabbatch{9}.menu_cfg.menu_struct.conf_branch.val{3}(1).src_exbranch = substruct('.','val', '{}',{8}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{9}.menu_cfg.menu_struct.conf_branch.val{3}(1).src_output = substruct('()',{1}); -matlabbatch{9}.menu_cfg.menu_struct.conf_branch.check = []; -matlabbatch{9}.menu_cfg.menu_struct.conf_branch.help = {'The input files will be moved to the specified target folder. In addition, their filenames (not paths, not extensions) will be changed by replacing regular expression patterns using MATLABs regexprep function. Please consult MATLAB help and HTML documentation for how to specify regular expressions.'}; -matlabbatch{10}.menu_cfg.menu_struct.conf_branch.type = 'cfg_branch'; -matlabbatch{10}.menu_cfg.menu_struct.conf_branch.name = 'Copy and Rename'; -matlabbatch{10}.menu_cfg.menu_struct.conf_branch.tag = 'copyren'; -matlabbatch{10}.menu_cfg.menu_struct.conf_branch.val{1}(1) = cfg_dep; -matlabbatch{10}.menu_cfg.menu_struct.conf_branch.val{1}(1).tname = 'Val Item'; -matlabbatch{10}.menu_cfg.menu_struct.conf_branch.val{1}(1).tgt_spec = {}; -matlabbatch{10}.menu_cfg.menu_struct.conf_branch.val{1}(1).sname = 'Files: Copy to (cfg_files)'; -matlabbatch{10}.menu_cfg.menu_struct.conf_branch.val{1}(1).src_exbranch = substruct('.','val', '{}',{3}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{10}.menu_cfg.menu_struct.conf_branch.val{1}(1).src_output = substruct('()',{1}); -matlabbatch{10}.menu_cfg.menu_struct.conf_branch.val{2}(1) = cfg_dep; -matlabbatch{10}.menu_cfg.menu_struct.conf_branch.val{2}(1).tname = 'Val Item'; -matlabbatch{10}.menu_cfg.menu_struct.conf_branch.val{2}(1).tgt_spec = {}; -matlabbatch{10}.menu_cfg.menu_struct.conf_branch.val{2}(1).sname = 'Repeat: Pattern/Replacement List (cfg_repeat)'; -matlabbatch{10}.menu_cfg.menu_struct.conf_branch.val{2}(1).src_exbranch = substruct('.','val', '{}',{7}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{10}.menu_cfg.menu_struct.conf_branch.val{2}(1).src_output = substruct('()',{1}); -matlabbatch{10}.menu_cfg.menu_struct.conf_branch.val{3}(1) = cfg_dep; -matlabbatch{10}.menu_cfg.menu_struct.conf_branch.val{3}(1).tname = 'Val Item'; -matlabbatch{10}.menu_cfg.menu_struct.conf_branch.val{3}(1).tgt_spec = {}; -matlabbatch{10}.menu_cfg.menu_struct.conf_branch.val{3}(1).sname = 'Menu: Unique Filenames (cfg_menu)'; -matlabbatch{10}.menu_cfg.menu_struct.conf_branch.val{3}(1).src_exbranch = substruct('.','val', '{}',{8}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{10}.menu_cfg.menu_struct.conf_branch.val{3}(1).src_output = substruct('()',{1}); -matlabbatch{10}.menu_cfg.menu_struct.conf_branch.check = []; -matlabbatch{10}.menu_cfg.menu_struct.conf_branch.help = {'The input files will be copied to the specified target folder. In addition, their filenames (not paths, not extensions) will be changed by replacing regular expression patterns using MATLABs regexprep function. Please consult MATLAB help and HTML documentation for how to specify regular expressions.'}; -matlabbatch{11}.menu_cfg.menu_entry.conf_const.type = 'cfg_const'; -matlabbatch{11}.menu_cfg.menu_entry.conf_const.name = 'Delete'; -matlabbatch{11}.menu_cfg.menu_entry.conf_const.tag = 'delete'; -matlabbatch{11}.menu_cfg.menu_entry.conf_const.val = {false}; -matlabbatch{11}.menu_cfg.menu_entry.conf_const.check = []; -matlabbatch{11}.menu_cfg.menu_entry.conf_const.help = {'The selected files will be deleted.'}; -matlabbatch{11}.menu_cfg.menu_entry.conf_const.def = []; -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.type = 'cfg_choice'; -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.name = 'Action'; -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.tag = 'action'; -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.values{1}(1) = cfg_dep; -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.values{1}(1).tname = 'Values Item'; -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.values{1}(1).tgt_spec = {}; -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.values{1}(1).sname = 'Files: Move to (cfg_files)'; -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.values{1}(1).src_exbranch = substruct('.','val', '{}',{2}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.values{1}(1).src_output = substruct('()',{1}); -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.values{2}(1) = cfg_dep; -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.values{2}(1).tname = 'Values Item'; -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.values{2}(1).tgt_spec = {}; -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.values{2}(1).sname = 'Files: Copy to (cfg_files)'; -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.values{2}(1).src_exbranch = substruct('.','val', '{}',{3}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.values{2}(1).src_output = substruct('()',{1}); -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.values{3}(1) = cfg_dep; -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.values{3}(1).tname = 'Values Item'; -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.values{3}(1).tgt_spec = {}; -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.values{3}(1).sname = 'Branch: Move and Rename (cfg_branch)'; -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.values{3}(1).src_exbranch = substruct('.','val', '{}',{9}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.values{3}(1).src_output = substruct('()',{1}); -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.values{4}(1) = cfg_dep; -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.values{4}(1).tname = 'Values Item'; -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.values{4}(1).tgt_spec = {}; -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.values{4}(1).sname = 'Branch: Copy and Rename (cfg_branch)'; -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.values{4}(1).src_exbranch = substruct('.','val', '{}',{10}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.values{4}(1).src_output = substruct('()',{1}); -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.values{5}(1) = cfg_dep; -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.values{5}(1).tname = 'Values Item'; -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.values{5}(1).tgt_spec = {}; -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.values{5}(1).sname = 'Const: Delete (cfg_const)'; -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.values{5}(1).src_exbranch = substruct('.','val', '{}',{11}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.values{5}(1).src_output = substruct('()',{1}); -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.check = []; -matlabbatch{12}.menu_cfg.menu_struct.conf_choice.help = {}; -matlabbatch{13}.menu_cfg.menu_struct.conf_exbranch.type = 'cfg_exbranch'; -matlabbatch{13}.menu_cfg.menu_struct.conf_exbranch.name = 'Move/Delete Files'; -matlabbatch{13}.menu_cfg.menu_struct.conf_exbranch.tag = 'file_move'; -matlabbatch{13}.menu_cfg.menu_struct.conf_exbranch.val{1}(1) = cfg_dep; -matlabbatch{13}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tname = 'Val Item'; -matlabbatch{13}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tgt_spec = {}; -matlabbatch{13}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).sname = 'Files: Files to move/copy/delete (cfg_files)'; -matlabbatch{13}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_exbranch = substruct('.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{13}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_output = substruct('()',{1}); -matlabbatch{13}.menu_cfg.menu_struct.conf_exbranch.val{2}(1) = cfg_dep; -matlabbatch{13}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tname = 'Val Item'; -matlabbatch{13}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tgt_spec = {}; -matlabbatch{13}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).sname = 'Choice: Action (cfg_choice)'; -matlabbatch{13}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_exbranch = substruct('.','val', '{}',{12}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{13}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_output = substruct('()',{1}); -matlabbatch{13}.menu_cfg.menu_struct.conf_exbranch.prog = @cfg_run_file_move; -matlabbatch{13}.menu_cfg.menu_struct.conf_exbranch.vout = @cfg_vout_file_move; -matlabbatch{13}.menu_cfg.menu_struct.conf_exbranch.check = []; -matlabbatch{13}.menu_cfg.menu_struct.conf_exbranch.help = {'Move or delete files.'}; -matlabbatch{14}.menu_cfg.menu_entry.conf_files.type = 'cfg_files'; -matlabbatch{14}.menu_cfg.menu_entry.conf_files.name = 'Directory'; -matlabbatch{14}.menu_cfg.menu_entry.conf_files.tag = 'dir'; -matlabbatch{14}.menu_cfg.menu_entry.conf_files.filter = 'dir'; -matlabbatch{14}.menu_cfg.menu_entry.conf_files.ufilter = '.*'; -matlabbatch{14}.menu_cfg.menu_entry.conf_files.dir = ''; -matlabbatch{14}.menu_cfg.menu_entry.conf_files.num = [1 1]; -matlabbatch{14}.menu_cfg.menu_entry.conf_files.check = []; -matlabbatch{14}.menu_cfg.menu_entry.conf_files.help = {'New working directory.'}; -matlabbatch{14}.menu_cfg.menu_entry.conf_files.def = []; -matlabbatch{15}.menu_cfg.menu_struct.conf_exbranch.type = 'cfg_exbranch'; -matlabbatch{15}.menu_cfg.menu_struct.conf_exbranch.name = 'Change Directory'; -matlabbatch{15}.menu_cfg.menu_struct.conf_exbranch.tag = 'cfg_cd'; -matlabbatch{15}.menu_cfg.menu_struct.conf_exbranch.val{1}(1) = cfg_dep; -matlabbatch{15}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tname = 'Val Item'; -matlabbatch{15}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tgt_spec = {}; -matlabbatch{15}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).sname = 'Directory (cfg_files)'; -matlabbatch{15}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_exbranch = substruct('.','val', '{}',{14}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{15}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_output = substruct('()',{1}); -matlabbatch{15}.menu_cfg.menu_struct.conf_exbranch.prog = @cfg_run_cd; -matlabbatch{15}.menu_cfg.menu_struct.conf_exbranch.vout = []; -matlabbatch{15}.menu_cfg.menu_struct.conf_exbranch.check = []; -matlabbatch{15}.menu_cfg.menu_struct.conf_exbranch.help = {'Change working directory.'}; -matlabbatch{16}.menu_cfg.menu_entry.conf_entry.type = 'cfg_entry'; -matlabbatch{16}.menu_cfg.menu_entry.conf_entry.name = 'New Directory Name'; -matlabbatch{16}.menu_cfg.menu_entry.conf_entry.tag = 'name'; -matlabbatch{16}.menu_cfg.menu_entry.conf_entry.strtype = 's'; -matlabbatch{16}.menu_cfg.menu_entry.conf_entry.extras = []; -matlabbatch{16}.menu_cfg.menu_entry.conf_entry.num = [1 Inf]; -matlabbatch{16}.menu_cfg.menu_entry.conf_entry.check = []; -matlabbatch{16}.menu_cfg.menu_entry.conf_entry.help = {'Name for the new directory.'}; -matlabbatch{16}.menu_cfg.menu_entry.conf_entry.def = []; -matlabbatch{17}.menu_cfg.menu_entry.conf_files.type = 'cfg_files'; -matlabbatch{17}.menu_cfg.menu_entry.conf_files.name = 'Parent Directory'; -matlabbatch{17}.menu_cfg.menu_entry.conf_files.tag = 'parent'; -matlabbatch{17}.menu_cfg.menu_entry.conf_files.filter = 'dir'; -matlabbatch{17}.menu_cfg.menu_entry.conf_files.ufilter = '.*'; -matlabbatch{17}.menu_cfg.menu_entry.conf_files.dir = ''; -matlabbatch{17}.menu_cfg.menu_entry.conf_files.num = [1 1]; -matlabbatch{17}.menu_cfg.menu_entry.conf_files.check = []; -matlabbatch{17}.menu_cfg.menu_entry.conf_files.help = {'Directory where the new directory will be created.'}; -matlabbatch{17}.menu_cfg.menu_entry.conf_files.def = []; -matlabbatch{18}.menu_cfg.menu_struct.conf_exbranch.type = 'cfg_exbranch'; -matlabbatch{18}.menu_cfg.menu_struct.conf_exbranch.name = 'Make Directory'; -matlabbatch{18}.menu_cfg.menu_struct.conf_exbranch.tag = 'cfg_mkdir'; -matlabbatch{18}.menu_cfg.menu_struct.conf_exbranch.val{1}(1) = cfg_dep; -matlabbatch{18}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tname = 'Val Item'; -matlabbatch{18}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tgt_spec = {}; -matlabbatch{18}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).sname = 'Parent Directory (cfg_files)'; -matlabbatch{18}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_exbranch = substruct('.','val', '{}',{17}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{18}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_output = substruct('()',{1}); -matlabbatch{18}.menu_cfg.menu_struct.conf_exbranch.val{2}(1) = cfg_dep; -matlabbatch{18}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tname = 'Val Item'; -matlabbatch{18}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tgt_spec = {}; -matlabbatch{18}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).sname = 'New Directory Name (cfg_entry)'; -matlabbatch{18}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_exbranch = substruct('.','val', '{}',{16}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{18}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_output = substruct('()',{1}); -matlabbatch{18}.menu_cfg.menu_struct.conf_exbranch.prog = @cfg_run_mkdir; -matlabbatch{18}.menu_cfg.menu_struct.conf_exbranch.vout = @cfg_vout_mkdir; -matlabbatch{18}.menu_cfg.menu_struct.conf_exbranch.check = []; -matlabbatch{18}.menu_cfg.menu_struct.conf_exbranch.help = {'Create a new directory.'}; -matlabbatch{19}.menu_cfg.menu_entry.conf_entry.type = 'cfg_entry'; -matlabbatch{19}.menu_cfg.menu_entry.conf_entry.name = 'Input Name'; -matlabbatch{19}.menu_cfg.menu_entry.conf_entry.tag = 'name'; -matlabbatch{19}.menu_cfg.menu_entry.conf_entry.strtype = 's'; -matlabbatch{19}.menu_cfg.menu_entry.conf_entry.extras = []; -matlabbatch{19}.menu_cfg.menu_entry.conf_entry.num = [1 Inf]; -matlabbatch{19}.menu_cfg.menu_entry.conf_entry.check = []; -matlabbatch{19}.menu_cfg.menu_entry.conf_entry.help = {'Enter a name for this directory selection. This name will be displayed in the ''Dependency'' listing as output name.'}; -matlabbatch{19}.menu_cfg.menu_entry.conf_entry.def = []; -matlabbatch{20}.menu_cfg.menu_entry.conf_files.type = 'cfg_files'; -matlabbatch{20}.menu_cfg.menu_entry.conf_files.name = 'Directory'; -matlabbatch{20}.menu_cfg.menu_entry.conf_files.tag = 'dirs'; -matlabbatch{20}.menu_cfg.menu_entry.conf_files.filter = 'dir'; -matlabbatch{20}.menu_cfg.menu_entry.conf_files.ufilter = '.*'; -matlabbatch{20}.menu_cfg.menu_entry.conf_files.dir = ''; -matlabbatch{20}.menu_cfg.menu_entry.conf_files.num = [1 1]; -matlabbatch{20}.menu_cfg.menu_entry.conf_files.check = []; -matlabbatch{20}.menu_cfg.menu_entry.conf_files.help = {'Select a directory.'}; -matlabbatch{20}.menu_cfg.menu_entry.conf_files.def = []; -matlabbatch{21}.menu_cfg.menu_struct.conf_repeat.type = 'cfg_repeat'; -matlabbatch{21}.menu_cfg.menu_struct.conf_repeat.name = 'Directories'; -matlabbatch{21}.menu_cfg.menu_struct.conf_repeat.tag = 'dirs'; -matlabbatch{21}.menu_cfg.menu_struct.conf_repeat.values{1}(1) = cfg_dep; -matlabbatch{21}.menu_cfg.menu_struct.conf_repeat.values{1}(1).tname = 'Values Item'; -matlabbatch{21}.menu_cfg.menu_struct.conf_repeat.values{1}(1).tgt_spec = {}; -matlabbatch{21}.menu_cfg.menu_struct.conf_repeat.values{1}(1).sname = 'Directory (cfg_files)'; -matlabbatch{21}.menu_cfg.menu_struct.conf_repeat.values{1}(1).src_exbranch = substruct('.','val', '{}',{20}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{21}.menu_cfg.menu_struct.conf_repeat.values{1}(1).src_output = substruct('()',{1}); -matlabbatch{21}.menu_cfg.menu_struct.conf_repeat.num = [1 Inf]; -matlabbatch{21}.menu_cfg.menu_struct.conf_repeat.forcestruct = false; -matlabbatch{21}.menu_cfg.menu_struct.conf_repeat.check = []; -matlabbatch{21}.menu_cfg.menu_struct.conf_repeat.help = {'Select one or more directories.'}; -matlabbatch{22}.menu_cfg.menu_struct.conf_exbranch.type = 'cfg_exbranch'; -matlabbatch{22}.menu_cfg.menu_struct.conf_exbranch.name = 'Named Directory Selector'; -matlabbatch{22}.menu_cfg.menu_struct.conf_exbranch.tag = 'cfg_named_dir'; -matlabbatch{22}.menu_cfg.menu_struct.conf_exbranch.val{1}(1) = cfg_dep; -matlabbatch{22}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tname = 'Val Item'; -matlabbatch{22}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tgt_spec = {}; -matlabbatch{22}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).sname = 'Input Name (cfg_entry)'; -matlabbatch{22}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_exbranch = substruct('.','val', '{}',{19}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{22}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_output = substruct('()',{1}); -matlabbatch{22}.menu_cfg.menu_struct.conf_exbranch.val{2}(1) = cfg_dep; -matlabbatch{22}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tname = 'Val Item'; -matlabbatch{22}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tgt_spec = {}; -matlabbatch{22}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).sname = 'Directories (cfg_repeat)'; -matlabbatch{22}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_exbranch = substruct('.','val', '{}',{21}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{22}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_output = substruct('()',{1}); -matlabbatch{22}.menu_cfg.menu_struct.conf_exbranch.prog = @cfg_run_named_dir; -matlabbatch{22}.menu_cfg.menu_struct.conf_exbranch.vout = @cfg_vout_named_dir; -matlabbatch{22}.menu_cfg.menu_struct.conf_exbranch.check = []; -matlabbatch{22}.menu_cfg.menu_struct.conf_exbranch.help = {'Named Directory Selector allows to select directories that can be referenced as common input by other modules.'}; -matlabbatch{23}.menu_cfg.menu_entry.conf_entry.type = 'cfg_entry'; -matlabbatch{23}.menu_cfg.menu_entry.conf_entry.name = 'Input Name'; -matlabbatch{23}.menu_cfg.menu_entry.conf_entry.tag = 'name'; -matlabbatch{23}.menu_cfg.menu_entry.conf_entry.strtype = 's'; -matlabbatch{23}.menu_cfg.menu_entry.conf_entry.extras = []; -matlabbatch{23}.menu_cfg.menu_entry.conf_entry.num = [1 Inf]; -matlabbatch{23}.menu_cfg.menu_entry.conf_entry.check = []; -matlabbatch{23}.menu_cfg.menu_entry.conf_entry.help = {'Enter a name for this file selection. This name will be displayed in the ''Dependency'' listing as output name.'}; -matlabbatch{23}.menu_cfg.menu_entry.conf_entry.def = []; -matlabbatch{24}.menu_cfg.menu_entry.conf_files.type = 'cfg_files'; -matlabbatch{24}.menu_cfg.menu_entry.conf_files.name = 'File Set'; -matlabbatch{24}.menu_cfg.menu_entry.conf_files.tag = 'files'; -matlabbatch{24}.menu_cfg.menu_entry.conf_files.filter = 'any'; -matlabbatch{24}.menu_cfg.menu_entry.conf_files.ufilter = '.*'; -matlabbatch{24}.menu_cfg.menu_entry.conf_files.dir = ''; -matlabbatch{24}.menu_cfg.menu_entry.conf_files.num = [0 Inf]; -matlabbatch{24}.menu_cfg.menu_entry.conf_files.check = []; -matlabbatch{24}.menu_cfg.menu_entry.conf_files.help = {'Select a set of files.'}; -matlabbatch{24}.menu_cfg.menu_entry.conf_files.def = []; -matlabbatch{25}.menu_cfg.menu_struct.conf_repeat.type = 'cfg_repeat'; -matlabbatch{25}.menu_cfg.menu_struct.conf_repeat.name = 'File Sets'; -matlabbatch{25}.menu_cfg.menu_struct.conf_repeat.tag = 'files'; -matlabbatch{25}.menu_cfg.menu_struct.conf_repeat.values{1}(1) = cfg_dep; -matlabbatch{25}.menu_cfg.menu_struct.conf_repeat.values{1}(1).tname = 'Values Item'; -matlabbatch{25}.menu_cfg.menu_struct.conf_repeat.values{1}(1).tgt_spec = {}; -matlabbatch{25}.menu_cfg.menu_struct.conf_repeat.values{1}(1).sname = 'File selection (cfg_files)'; -matlabbatch{25}.menu_cfg.menu_struct.conf_repeat.values{1}(1).src_exbranch = substruct('.','val', '{}',{24}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{25}.menu_cfg.menu_struct.conf_repeat.values{1}(1).src_output = substruct('()',{1}); -matlabbatch{25}.menu_cfg.menu_struct.conf_repeat.num = [1 Inf]; -matlabbatch{25}.menu_cfg.menu_struct.conf_repeat.forcestruct = false; -matlabbatch{25}.menu_cfg.menu_struct.conf_repeat.check = []; -matlabbatch{25}.menu_cfg.menu_struct.conf_repeat.help = {'Select one or more sets of files. Each set can be passed separately as a dependency to other modules.'}; -matlabbatch{26}.menu_cfg.menu_struct.conf_exbranch.type = 'cfg_exbranch'; -matlabbatch{26}.menu_cfg.menu_struct.conf_exbranch.name = 'Named File Selector'; -matlabbatch{26}.menu_cfg.menu_struct.conf_exbranch.tag = 'cfg_named_file'; -matlabbatch{26}.menu_cfg.menu_struct.conf_exbranch.val{1}(1) = cfg_dep; -matlabbatch{26}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tname = 'Val Item'; -matlabbatch{26}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tgt_spec = {}; -matlabbatch{26}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).sname = 'Input Name (cfg_entry)'; -matlabbatch{26}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_exbranch = substruct('.','val', '{}',{23}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{26}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_output = substruct('()',{1}); -matlabbatch{26}.menu_cfg.menu_struct.conf_exbranch.val{2}(1) = cfg_dep; -matlabbatch{26}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tname = 'Val Item'; -matlabbatch{26}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tgt_spec = {}; -matlabbatch{26}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).sname = 'File Sets (cfg_repeat)'; -matlabbatch{26}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_exbranch = substruct('.','val', '{}',{25}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{26}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_output = substruct('()',{1}); -matlabbatch{26}.menu_cfg.menu_struct.conf_exbranch.prog = @cfg_run_named_file; -matlabbatch{26}.menu_cfg.menu_struct.conf_exbranch.vout = @cfg_vout_named_file; -matlabbatch{26}.menu_cfg.menu_struct.conf_exbranch.check = []; -matlabbatch{26}.menu_cfg.menu_struct.conf_exbranch.help = { - 'Named File Selector allows to select sets of files that can be referenced as common input by other modules.' - 'In addition to file outputs, an index vector is provided that can be used to separate the files again using ''File Set Split'' module. This can be useful if the same sets of files have to be processed separately in one module and as a single set in another.' - }'; -matlabbatch{27}.menu_cfg.menu_entry.conf_files.type = 'cfg_files'; -matlabbatch{27}.menu_cfg.menu_entry.conf_files.name = 'Directory'; -matlabbatch{27}.menu_cfg.menu_entry.conf_files.tag = 'dir'; -matlabbatch{27}.menu_cfg.menu_entry.conf_files.filter = 'dir'; -matlabbatch{27}.menu_cfg.menu_entry.conf_files.ufilter = '.*'; -matlabbatch{27}.menu_cfg.menu_entry.conf_files.dir = ''; -matlabbatch{27}.menu_cfg.menu_entry.conf_files.num = [1 Inf]; -matlabbatch{27}.menu_cfg.menu_entry.conf_files.check = []; -matlabbatch{27}.menu_cfg.menu_entry.conf_files.help = {'Directory to select files from.'}; -matlabbatch{27}.menu_cfg.menu_entry.conf_files.def = []; -matlabbatch{28}.menu_cfg.menu_entry.conf_entry.type = 'cfg_entry'; -matlabbatch{28}.menu_cfg.menu_entry.conf_entry.name = 'Filter'; -matlabbatch{28}.menu_cfg.menu_entry.conf_entry.tag = 'filter'; -matlabbatch{28}.menu_cfg.menu_entry.conf_entry.strtype = 's'; -matlabbatch{28}.menu_cfg.menu_entry.conf_entry.extras = []; -matlabbatch{28}.menu_cfg.menu_entry.conf_entry.num = [1 Inf]; -matlabbatch{28}.menu_cfg.menu_entry.conf_entry.check = []; -matlabbatch{28}.menu_cfg.menu_entry.conf_entry.help = {'A regular expression to filter files.'}; -matlabbatch{28}.menu_cfg.menu_entry.conf_entry.def = []; -matlabbatch{29}.menu_cfg.menu_entry.conf_menu.type = 'cfg_menu'; -matlabbatch{29}.menu_cfg.menu_entry.conf_menu.name = 'Descend into subdirectories'; -matlabbatch{29}.menu_cfg.menu_entry.conf_menu.tag = 'rec'; -matlabbatch{29}.menu_cfg.menu_entry.conf_menu.labels = { - 'Yes' - 'Yes' - }'; -matlabbatch{29}.menu_cfg.menu_entry.conf_menu.values = { - true - false - }'; -matlabbatch{29}.menu_cfg.menu_entry.conf_menu.check = []; -matlabbatch{29}.menu_cfg.menu_entry.conf_menu.help = {'Files can be selected from the specified directory only or from the specified directory and all its subdirectories.'}; -matlabbatch{29}.menu_cfg.menu_entry.conf_menu.def = []; -matlabbatch{30}.menu_cfg.menu_struct.conf_exbranch.type = 'cfg_exbranch'; -matlabbatch{30}.menu_cfg.menu_struct.conf_exbranch.name = 'File Selector (Batch Mode)'; -matlabbatch{30}.menu_cfg.menu_struct.conf_exbranch.tag = 'file_fplist'; -matlabbatch{30}.menu_cfg.menu_struct.conf_exbranch.val{1}(1) = cfg_dep; -matlabbatch{30}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tname = 'Val Item'; -matlabbatch{30}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tgt_spec = {}; -matlabbatch{30}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).sname = 'Directory (cfg_files)'; -matlabbatch{30}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_exbranch = substruct('.','val', '{}',{27}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{30}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_output = substruct('()',{1}); -matlabbatch{30}.menu_cfg.menu_struct.conf_exbranch.val{2}(1) = cfg_dep; -matlabbatch{30}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tname = 'Val Item'; -matlabbatch{30}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tgt_spec = {}; -matlabbatch{30}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).sname = 'Filter (cfg_entry)'; -matlabbatch{30}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_exbranch = substruct('.','val', '{}',{28}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{30}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_output = substruct('()',{1}); -matlabbatch{30}.menu_cfg.menu_struct.conf_exbranch.val{3}(1) = cfg_dep; -matlabbatch{30}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).tname = 'Val Item'; -matlabbatch{30}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).tgt_spec = {}; -matlabbatch{30}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).sname = 'Menu: Descend into subdirectories (cfg_menu)'; -matlabbatch{30}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).src_exbranch = substruct('.','val', '{}',{29}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{30}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).src_output = substruct('()',{1}); -matlabbatch{30}.menu_cfg.menu_struct.conf_exbranch.prog = @cfg_run_file_fplist; -matlabbatch{30}.menu_cfg.menu_struct.conf_exbranch.vout = @cfg_vout_file_fplist; -matlabbatch{30}.menu_cfg.menu_struct.conf_exbranch.check = []; -matlabbatch{30}.menu_cfg.menu_struct.conf_exbranch.help = {'Select files from a directory using cfg_getfile(''FPList'',...).'}; -matlabbatch{31}.menu_cfg.menu_entry.conf_files.type = 'cfg_files'; -matlabbatch{31}.menu_cfg.menu_entry.conf_files.name = 'Files'; -matlabbatch{31}.menu_cfg.menu_entry.conf_files.tag = 'files'; -matlabbatch{31}.menu_cfg.menu_entry.conf_files.filter = 'any'; -matlabbatch{31}.menu_cfg.menu_entry.conf_files.ufilter = '.*'; -matlabbatch{31}.menu_cfg.menu_entry.conf_files.dir = ''; -matlabbatch{31}.menu_cfg.menu_entry.conf_files.num = [1 Inf]; -matlabbatch{31}.menu_cfg.menu_entry.conf_files.check = []; -matlabbatch{31}.menu_cfg.menu_entry.conf_files.help = {'Files to be filtered.'}; -matlabbatch{31}.menu_cfg.menu_entry.conf_files.def = []; -matlabbatch{32}.menu_cfg.menu_entry.conf_entry.type = 'cfg_entry'; -matlabbatch{32}.menu_cfg.menu_entry.conf_entry.name = 'Typ'; -matlabbatch{32}.menu_cfg.menu_entry.conf_entry.tag = 'typ'; -matlabbatch{32}.menu_cfg.menu_entry.conf_entry.strtype = 's'; -matlabbatch{32}.menu_cfg.menu_entry.conf_entry.extras = []; -matlabbatch{32}.menu_cfg.menu_entry.conf_entry.num = [1 Inf]; -matlabbatch{32}.menu_cfg.menu_entry.conf_entry.check = []; -matlabbatch{32}.menu_cfg.menu_entry.conf_entry.help = {'Allowed types are (see cfg_getfile): ''any'', ''image'', ''xml'', ''mat'', ''batch'', ''dir'' or a regular expression.'}; -matlabbatch{32}.menu_cfg.menu_entry.conf_entry.def = []; -matlabbatch{33}.menu_cfg.menu_entry.conf_entry.type = 'cfg_entry'; -matlabbatch{33}.menu_cfg.menu_entry.conf_entry.name = 'Filter'; -matlabbatch{33}.menu_cfg.menu_entry.conf_entry.tag = 'filter'; -matlabbatch{33}.menu_cfg.menu_entry.conf_entry.strtype = 's'; -matlabbatch{33}.menu_cfg.menu_entry.conf_entry.extras = []; -matlabbatch{33}.menu_cfg.menu_entry.conf_entry.num = [1 Inf]; -matlabbatch{33}.menu_cfg.menu_entry.conf_entry.check = []; -matlabbatch{33}.menu_cfg.menu_entry.conf_entry.help = {'A regular expression to filter files (applied after filtering for ''Typ'').'}; -matlabbatch{33}.menu_cfg.menu_entry.conf_entry.def = []; -matlabbatch{34}.menu_cfg.menu_entry.conf_entry.type = 'cfg_entry'; -matlabbatch{34}.menu_cfg.menu_entry.conf_entry.name = 'Frames'; -matlabbatch{34}.menu_cfg.menu_entry.conf_entry.tag = 'frames'; -matlabbatch{34}.menu_cfg.menu_entry.conf_entry.strtype = 's'; -matlabbatch{34}.menu_cfg.menu_entry.conf_entry.extras = []; -matlabbatch{34}.menu_cfg.menu_entry.conf_entry.num = [0 Inf]; -matlabbatch{34}.menu_cfg.menu_entry.conf_entry.check = []; -matlabbatch{34}.menu_cfg.menu_entry.conf_entry.help = {'This option is currently completely ignored!'}; -matlabbatch{34}.menu_cfg.menu_entry.conf_entry.def = []; -matlabbatch{35}.menu_cfg.menu_struct.conf_exbranch.type = 'cfg_exbranch'; -matlabbatch{35}.menu_cfg.menu_struct.conf_exbranch.name = 'File Filter'; -matlabbatch{35}.menu_cfg.menu_struct.conf_exbranch.tag = 'file_filter'; -matlabbatch{35}.menu_cfg.menu_struct.conf_exbranch.val{1}(1) = cfg_dep; -matlabbatch{35}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tname = 'Val Item'; -matlabbatch{35}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tgt_spec = {}; -matlabbatch{35}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).sname = 'Files (cfg_files)'; -matlabbatch{35}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_exbranch = substruct('.','val', '{}',{31}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{35}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_output = substruct('()',{1}); -matlabbatch{35}.menu_cfg.menu_struct.conf_exbranch.val{2}(1) = cfg_dep; -matlabbatch{35}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tname = 'Val Item'; -matlabbatch{35}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tgt_spec = {}; -matlabbatch{35}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).sname = 'Typ (cfg_entry)'; -matlabbatch{35}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_exbranch = substruct('.','val', '{}',{32}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{35}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_output = substruct('()',{1}); -matlabbatch{35}.menu_cfg.menu_struct.conf_exbranch.val{3}(1) = cfg_dep; -matlabbatch{35}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).tname = 'Val Item'; -matlabbatch{35}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).tgt_spec = {}; -matlabbatch{35}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).sname = 'Filter (cfg_entry)'; -matlabbatch{35}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).src_exbranch = substruct('.','val', '{}',{33}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{35}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).src_output = substruct('()',{1}); -matlabbatch{35}.menu_cfg.menu_struct.conf_exbranch.val{4}(1) = cfg_dep; -matlabbatch{35}.menu_cfg.menu_struct.conf_exbranch.val{4}(1).tname = 'Val Item'; -matlabbatch{35}.menu_cfg.menu_struct.conf_exbranch.val{4}(1).tgt_spec = {}; -matlabbatch{35}.menu_cfg.menu_struct.conf_exbranch.val{4}(1).sname = 'Frames (cfg_entry)'; -matlabbatch{35}.menu_cfg.menu_struct.conf_exbranch.val{4}(1).src_exbranch = substruct('.','val', '{}',{34}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{35}.menu_cfg.menu_struct.conf_exbranch.val{4}(1).src_output = substruct('()',{1}); -matlabbatch{35}.menu_cfg.menu_struct.conf_exbranch.prog = @cfg_run_file_filter; -matlabbatch{35}.menu_cfg.menu_struct.conf_exbranch.vout = @cfg_vout_file_filter; -matlabbatch{35}.menu_cfg.menu_struct.conf_exbranch.check = []; -matlabbatch{35}.menu_cfg.menu_struct.conf_exbranch.help = {'Filter a list of files using cfg_getfile.'}; -matlabbatch{36}.menu_cfg.menu_entry.conf_entry.type = 'cfg_entry'; -matlabbatch{36}.menu_cfg.menu_entry.conf_entry.name = 'File Set Name'; -matlabbatch{36}.menu_cfg.menu_entry.conf_entry.tag = 'name'; -matlabbatch{36}.menu_cfg.menu_entry.conf_entry.strtype = 's'; -matlabbatch{36}.menu_cfg.menu_entry.conf_entry.extras = []; -matlabbatch{36}.menu_cfg.menu_entry.conf_entry.num = [1 Inf]; -matlabbatch{36}.menu_cfg.menu_entry.conf_entry.check = []; -matlabbatch{36}.menu_cfg.menu_entry.conf_entry.help = {'Enter a name for this file selection. This name will be displayed in the ''Dependency'' listing as output name.'}; -matlabbatch{36}.menu_cfg.menu_entry.conf_entry.def = []; -matlabbatch{37}.menu_cfg.menu_entry.conf_entry.type = 'cfg_entry'; -matlabbatch{37}.menu_cfg.menu_entry.conf_entry.name = 'Selection Index'; -matlabbatch{37}.menu_cfg.menu_entry.conf_entry.tag = 'index'; -matlabbatch{37}.menu_cfg.menu_entry.conf_entry.strtype = 'n'; -matlabbatch{37}.menu_cfg.menu_entry.conf_entry.extras = []; -matlabbatch{37}.menu_cfg.menu_entry.conf_entry.num = [1 Inf]; -matlabbatch{37}.menu_cfg.menu_entry.conf_entry.check = []; -matlabbatch{37}.menu_cfg.menu_entry.conf_entry.help = { - 'Enter the index vector of files belonging to this set. E.g. to select files 1 to 10 from the input file set, enter [1:10].' - 'To split the combined list of all files selected by a "Named File Selector", enter the index vectors here as dependency.' - }'; -matlabbatch{37}.menu_cfg.menu_entry.conf_entry.def = []; -matlabbatch{38}.menu_cfg.menu_struct.conf_repeat.type = 'cfg_repeat'; -matlabbatch{38}.menu_cfg.menu_struct.conf_repeat.name = 'Output File Sets'; -matlabbatch{38}.menu_cfg.menu_struct.conf_repeat.tag = 'filesets'; -matlabbatch{38}.menu_cfg.menu_struct.conf_repeat.values{1}(1) = cfg_dep; -matlabbatch{38}.menu_cfg.menu_struct.conf_repeat.values{1}(1).tname = 'Values Item'; -matlabbatch{38}.menu_cfg.menu_struct.conf_repeat.values{1}(1).tgt_spec = {}; -matlabbatch{38}.menu_cfg.menu_struct.conf_repeat.values{1}(1).sname = 'Selection Index (cfg_entry)'; -matlabbatch{38}.menu_cfg.menu_struct.conf_repeat.values{1}(1).src_exbranch = substruct('.','val', '{}',{37}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{38}.menu_cfg.menu_struct.conf_repeat.values{1}(1).src_output = substruct('()',{1}); -matlabbatch{38}.menu_cfg.menu_struct.conf_repeat.num = [1 Inf]; -matlabbatch{38}.menu_cfg.menu_struct.conf_repeat.forcestruct = false; -matlabbatch{38}.menu_cfg.menu_struct.conf_repeat.check = []; -matlabbatch{38}.menu_cfg.menu_struct.conf_repeat.help = {'For each file set to be created, enter an index vector that selects files from the input list. An additional output file set will be created matching files not selected by any index.'}; -matlabbatch{39}.menu_cfg.menu_entry.conf_files.type = 'cfg_files'; -matlabbatch{39}.menu_cfg.menu_entry.conf_files.name = 'Input File Set'; -matlabbatch{39}.menu_cfg.menu_entry.conf_files.tag = 'files'; -matlabbatch{39}.menu_cfg.menu_entry.conf_files.filter = 'any'; -matlabbatch{39}.menu_cfg.menu_entry.conf_files.ufilter = '.*'; -matlabbatch{39}.menu_cfg.menu_entry.conf_files.dir = ''; -matlabbatch{39}.menu_cfg.menu_entry.conf_files.num = [1 Inf]; -matlabbatch{39}.menu_cfg.menu_entry.conf_files.check = []; -matlabbatch{39}.menu_cfg.menu_entry.conf_files.help = {'The input file set will be split at the indices given in the ''#files per set'' collection.'}; -matlabbatch{39}.menu_cfg.menu_entry.conf_files.def = []; -matlabbatch{40}.menu_cfg.menu_struct.conf_exbranch.type = 'cfg_exbranch'; -matlabbatch{40}.menu_cfg.menu_struct.conf_exbranch.name = 'File Set Split'; -matlabbatch{40}.menu_cfg.menu_struct.conf_exbranch.tag = 'cfg_file_split'; -matlabbatch{40}.menu_cfg.menu_struct.conf_exbranch.val{1}(1) = cfg_dep; -matlabbatch{40}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tname = 'Val Item'; -matlabbatch{40}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tgt_spec = {}; -matlabbatch{40}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).sname = 'File Set Name (cfg_entry)'; -matlabbatch{40}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_exbranch = substruct('.','val', '{}',{36}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{40}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_output = substruct('()',{1}); -matlabbatch{40}.menu_cfg.menu_struct.conf_exbranch.val{2}(1) = cfg_dep; -matlabbatch{40}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tname = 'Val Item'; -matlabbatch{40}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tgt_spec = {}; -matlabbatch{40}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).sname = 'Input File Set (cfg_files)'; -matlabbatch{40}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_exbranch = substruct('.','val', '{}',{39}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{40}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_output = substruct('()',{1}); -matlabbatch{40}.menu_cfg.menu_struct.conf_exbranch.val{3}(1) = cfg_dep; -matlabbatch{40}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).tname = 'Val Item'; -matlabbatch{40}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).tgt_spec = {}; -matlabbatch{40}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).sname = 'File Sets (cfg_repeat)'; -matlabbatch{40}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).src_exbranch = substruct('.','val', '{}',{38}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{40}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).src_output = substruct('()',{1}); -matlabbatch{40}.menu_cfg.menu_struct.conf_exbranch.prog = @cfg_run_file_split; -matlabbatch{40}.menu_cfg.menu_struct.conf_exbranch.vout = @cfg_vout_file_split; -matlabbatch{40}.menu_cfg.menu_struct.conf_exbranch.check = []; -matlabbatch{40}.menu_cfg.menu_struct.conf_exbranch.help = { - 'Split a list of files into multiple parts.' - 'With this utility, a list of files can be split into parts based on index vectors. Each index vector is a list of numbers where number N selects the Nth file from the input list. Index vectors may overlap, so files may belong to more than one part. Files not matching any index will be returned in a separate list. If an index is larger than the number of files passed it will be ignored.' - }'; -matlabbatch{41}.menu_cfg.menu_entry.conf_entry.type = 'cfg_entry'; -matlabbatch{41}.menu_cfg.menu_entry.conf_entry.name = 'Input Name'; -matlabbatch{41}.menu_cfg.menu_entry.conf_entry.tag = 'name'; -matlabbatch{41}.menu_cfg.menu_entry.conf_entry.strtype = 's'; -matlabbatch{41}.menu_cfg.menu_entry.conf_entry.extras = []; -matlabbatch{41}.menu_cfg.menu_entry.conf_entry.num = [1 Inf]; -matlabbatch{41}.menu_cfg.menu_entry.conf_entry.check = []; -matlabbatch{41}.menu_cfg.menu_entry.conf_entry.help = {'Enter a name for this variable. This name will be displayed in the ''Dependency'' listing as output name.'}; -matlabbatch{41}.menu_cfg.menu_entry.conf_entry.def = []; -matlabbatch{42}.menu_cfg.menu_entry.conf_entry.type = 'cfg_entry'; -matlabbatch{42}.menu_cfg.menu_entry.conf_entry.name = 'Input Variable'; -matlabbatch{42}.menu_cfg.menu_entry.conf_entry.tag = 'input'; -matlabbatch{42}.menu_cfg.menu_entry.conf_entry.strtype = 'e'; -matlabbatch{42}.menu_cfg.menu_entry.conf_entry.extras = []; -matlabbatch{42}.menu_cfg.menu_entry.conf_entry.num = []; -matlabbatch{42}.menu_cfg.menu_entry.conf_entry.check = []; -matlabbatch{42}.menu_cfg.menu_entry.conf_entry.help = {'Enter a MATLAB variable. This can be a variable in the MATLAB workspace, or any other valid MATLAB statement which evaluates to a single variable.'}; -matlabbatch{42}.menu_cfg.menu_entry.conf_entry.def = []; -matlabbatch{43}.menu_cfg.menu_struct.conf_exbranch.type = 'cfg_exbranch'; -matlabbatch{43}.menu_cfg.menu_struct.conf_exbranch.name = 'Named Input'; -matlabbatch{43}.menu_cfg.menu_struct.conf_exbranch.tag = 'cfg_named_input'; -matlabbatch{43}.menu_cfg.menu_struct.conf_exbranch.val{1}(1) = cfg_dep; -matlabbatch{43}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tname = 'Val Item'; -matlabbatch{43}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tgt_spec = {}; -matlabbatch{43}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).sname = 'Input Name (cfg_entry)'; -matlabbatch{43}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_exbranch = substruct('.','val', '{}',{41}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{43}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_output = substruct('()',{1}); -matlabbatch{43}.menu_cfg.menu_struct.conf_exbranch.val{2}(1) = cfg_dep; -matlabbatch{43}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tname = 'Val Item'; -matlabbatch{43}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tgt_spec = {}; -matlabbatch{43}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).sname = 'Input Variable (cfg_entry)'; -matlabbatch{43}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_exbranch = substruct('.','val', '{}',{42}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{43}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_output = substruct('()',{1}); -matlabbatch{43}.menu_cfg.menu_struct.conf_exbranch.prog = @cfg_run_named_input; -matlabbatch{43}.menu_cfg.menu_struct.conf_exbranch.vout = @cfg_vout_named_input; -matlabbatch{43}.menu_cfg.menu_struct.conf_exbranch.check = []; -matlabbatch{43}.menu_cfg.menu_struct.conf_exbranch.help = {'Named Input allows to enter any kind of MATLAB variable. This variable can be referenced as common input by other modules.'}; -matlabbatch{44}.menu_cfg.menu_entry.conf_files.type = 'cfg_files'; -matlabbatch{44}.menu_cfg.menu_entry.conf_files.name = '.mat Filename'; -matlabbatch{44}.menu_cfg.menu_entry.conf_files.tag = 'matname'; -matlabbatch{44}.menu_cfg.menu_entry.conf_files.filter = 'mat'; -matlabbatch{44}.menu_cfg.menu_entry.conf_files.ufilter = '.*'; -matlabbatch{44}.menu_cfg.menu_entry.conf_files.dir = ''; -matlabbatch{44}.menu_cfg.menu_entry.conf_files.num = [1 1]; -matlabbatch{44}.menu_cfg.menu_entry.conf_files.check = []; -matlabbatch{44}.menu_cfg.menu_entry.conf_files.help = {'The name of the .mat file to load.'}; -matlabbatch{44}.menu_cfg.menu_entry.conf_files.def = []; -matlabbatch{45}.menu_cfg.menu_entry.conf_const.type = 'cfg_const'; -matlabbatch{45}.menu_cfg.menu_entry.conf_const.name = 'All Variables'; -matlabbatch{45}.menu_cfg.menu_entry.conf_const.tag = 'allvars'; -matlabbatch{45}.menu_cfg.menu_entry.conf_const.val = {true}; -matlabbatch{45}.menu_cfg.menu_entry.conf_const.check = []; -matlabbatch{45}.menu_cfg.menu_entry.conf_const.help = {'Load all variables found in the .mat file.'}; -matlabbatch{45}.menu_cfg.menu_entry.conf_const.def = []; -matlabbatch{46}.menu_cfg.menu_entry.conf_entry.type = 'cfg_entry'; -matlabbatch{46}.menu_cfg.menu_entry.conf_entry.name = 'Variable Name'; -matlabbatch{46}.menu_cfg.menu_entry.conf_entry.tag = 'varname'; -matlabbatch{46}.menu_cfg.menu_entry.conf_entry.strtype = 's'; -matlabbatch{46}.menu_cfg.menu_entry.conf_entry.extras = []; -matlabbatch{46}.menu_cfg.menu_entry.conf_entry.num = [1 Inf]; -matlabbatch{46}.menu_cfg.menu_entry.conf_entry.check = @(job)cfg_load_vars('check','isvarname',job); -matlabbatch{46}.menu_cfg.menu_entry.conf_entry.help = {'Enter the name of the variable to be loaded from the .mat file.'}; -matlabbatch{46}.menu_cfg.menu_entry.conf_entry.def = []; -matlabbatch{47}.menu_cfg.menu_struct.conf_repeat.type = 'cfg_repeat'; -matlabbatch{47}.menu_cfg.menu_struct.conf_repeat.name = 'Specified Variables'; -matlabbatch{47}.menu_cfg.menu_struct.conf_repeat.tag = 'varnames'; -matlabbatch{47}.menu_cfg.menu_struct.conf_repeat.values{1}(1) = cfg_dep; -matlabbatch{47}.menu_cfg.menu_struct.conf_repeat.values{1}(1).tname = 'Values Item'; -matlabbatch{47}.menu_cfg.menu_struct.conf_repeat.values{1}(1).tgt_spec = {}; -matlabbatch{47}.menu_cfg.menu_struct.conf_repeat.values{1}(1).sname = 'Entry: Variable Name (cfg_entry)'; -matlabbatch{47}.menu_cfg.menu_struct.conf_repeat.values{1}(1).src_exbranch = substruct('.','val', '{}',{46}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{47}.menu_cfg.menu_struct.conf_repeat.values{1}(1).src_output = substruct('()',{1}); -matlabbatch{47}.menu_cfg.menu_struct.conf_repeat.num = [1 Inf]; -matlabbatch{47}.menu_cfg.menu_struct.conf_repeat.forcestruct = false; -matlabbatch{47}.menu_cfg.menu_struct.conf_repeat.check = []; -matlabbatch{47}.menu_cfg.menu_struct.conf_repeat.help = {'Enter a list of variable names to be loaded from the .mat file.'}; -matlabbatch{48}.menu_cfg.menu_struct.conf_choice.type = 'cfg_choice'; -matlabbatch{48}.menu_cfg.menu_struct.conf_choice.name = 'Variables to load'; -matlabbatch{48}.menu_cfg.menu_struct.conf_choice.tag = 'loadvars'; -matlabbatch{48}.menu_cfg.menu_struct.conf_choice.values{1}(1) = cfg_dep; -matlabbatch{48}.menu_cfg.menu_struct.conf_choice.values{1}(1).tname = 'Values Item'; -matlabbatch{48}.menu_cfg.menu_struct.conf_choice.values{1}(1).tgt_spec = {}; -matlabbatch{48}.menu_cfg.menu_struct.conf_choice.values{1}(1).sname = 'Const: All Variables (cfg_const)'; -matlabbatch{48}.menu_cfg.menu_struct.conf_choice.values{1}(1).src_exbranch = substruct('.','val', '{}',{45}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{48}.menu_cfg.menu_struct.conf_choice.values{1}(1).src_output = substruct('()',{1}); -matlabbatch{48}.menu_cfg.menu_struct.conf_choice.values{2}(1) = cfg_dep; -matlabbatch{48}.menu_cfg.menu_struct.conf_choice.values{2}(1).tname = 'Values Item'; -matlabbatch{48}.menu_cfg.menu_struct.conf_choice.values{2}(1).tgt_spec = {}; -matlabbatch{48}.menu_cfg.menu_struct.conf_choice.values{2}(1).sname = 'Repeat: Specified Variables (cfg_repeat)'; -matlabbatch{48}.menu_cfg.menu_struct.conf_choice.values{2}(1).src_exbranch = substruct('.','val', '{}',{47}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{48}.menu_cfg.menu_struct.conf_choice.values{2}(1).src_output = substruct('()',{1}); -matlabbatch{48}.menu_cfg.menu_struct.conf_choice.check = []; -matlabbatch{48}.menu_cfg.menu_struct.conf_choice.help = {'Choose whether all variables or a list of variables with specified names should be loaded.'}; -matlabbatch{49}.menu_cfg.menu_struct.conf_exbranch.type = 'cfg_exbranch'; -matlabbatch{49}.menu_cfg.menu_struct.conf_exbranch.name = 'Load Variables from .mat File'; -matlabbatch{49}.menu_cfg.menu_struct.conf_exbranch.tag = 'load_vars'; -matlabbatch{49}.menu_cfg.menu_struct.conf_exbranch.val{1}(1) = cfg_dep; -matlabbatch{49}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tname = 'Val Item'; -matlabbatch{49}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tgt_spec = {}; -matlabbatch{49}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).sname = 'Files: .mat Filename (cfg_files)'; -matlabbatch{49}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_exbranch = substruct('.','val', '{}',{44}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{49}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_output = substruct('()',{1}); -matlabbatch{49}.menu_cfg.menu_struct.conf_exbranch.val{2}(1) = cfg_dep; -matlabbatch{49}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tname = 'Val Item'; -matlabbatch{49}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tgt_spec = {}; -matlabbatch{49}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).sname = 'Choice: Variables to load (cfg_choice)'; -matlabbatch{49}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_exbranch = substruct('.','val', '{}',{48}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{49}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_output = substruct('()',{1}); -matlabbatch{49}.menu_cfg.menu_struct.conf_exbranch.prog = @(job)cfg_load_vars('run',job); -matlabbatch{49}.menu_cfg.menu_struct.conf_exbranch.vout = @(job)cfg_load_vars('vout',job); -matlabbatch{49}.menu_cfg.menu_struct.conf_exbranch.check = []; -matlabbatch{49}.menu_cfg.menu_struct.conf_exbranch.help = {'This function loads variables from a .mat file and passes them on as a dependency. It can load either all variables from a .mat file or a list of specified variables. In the first case, it will return a single struct variable. The variable names in the .mat file will become field names in this struct. If a list of variable names is given, each of them will be loaded into a separate variable.'}; -matlabbatch{50}.menu_cfg.menu_entry.conf_entry.type = 'cfg_entry'; -matlabbatch{50}.menu_cfg.menu_entry.conf_entry.name = 'Output Filename'; -matlabbatch{50}.menu_cfg.menu_entry.conf_entry.tag = 'name'; -matlabbatch{50}.menu_cfg.menu_entry.conf_entry.strtype = 's'; -matlabbatch{50}.menu_cfg.menu_entry.conf_entry.extras = []; -matlabbatch{50}.menu_cfg.menu_entry.conf_entry.num = [1 Inf]; -matlabbatch{50}.menu_cfg.menu_entry.conf_entry.check = []; -matlabbatch{50}.menu_cfg.menu_entry.conf_entry.help = {'Output filename without any directory names.'}; -matlabbatch{50}.menu_cfg.menu_entry.conf_entry.def = []; -matlabbatch{51}.menu_cfg.menu_entry.conf_files.type = 'cfg_files'; -matlabbatch{51}.menu_cfg.menu_entry.conf_files.name = 'Output Directory'; -matlabbatch{51}.menu_cfg.menu_entry.conf_files.tag = 'outdir'; -matlabbatch{51}.menu_cfg.menu_entry.conf_files.filter = 'dir'; -matlabbatch{51}.menu_cfg.menu_entry.conf_files.ufilter = '.*'; -matlabbatch{51}.menu_cfg.menu_entry.conf_files.dir = ''; -matlabbatch{51}.menu_cfg.menu_entry.conf_files.num = [1 1]; -matlabbatch{51}.menu_cfg.menu_entry.conf_files.check = []; -matlabbatch{51}.menu_cfg.menu_entry.conf_files.help = {'Directory where the file will be saved. Any directory components in the output filename will be stripped off and only this directory determines the path to the file.'}; -matlabbatch{51}.menu_cfg.menu_entry.conf_files.def = []; -matlabbatch{52}.menu_cfg.menu_entry.conf_entry.type = 'cfg_entry'; -matlabbatch{52}.menu_cfg.menu_entry.conf_entry.name = 'Variable Name'; -matlabbatch{52}.menu_cfg.menu_entry.conf_entry.tag = 'vname'; -matlabbatch{52}.menu_cfg.menu_entry.conf_entry.strtype = 's'; -matlabbatch{52}.menu_cfg.menu_entry.conf_entry.extras = []; -matlabbatch{52}.menu_cfg.menu_entry.conf_entry.num = [1 Inf]; -matlabbatch{52}.menu_cfg.menu_entry.conf_entry.check = @cfg_check_assignin; -matlabbatch{52}.menu_cfg.menu_entry.conf_entry.help = {'Name for the variable in output file/struct. This must be a valid MATLAB variable name.'}; -matlabbatch{52}.menu_cfg.menu_entry.conf_entry.def = []; -matlabbatch{53}.menu_cfg.menu_entry.conf_entry.type = 'cfg_entry'; -matlabbatch{53}.menu_cfg.menu_entry.conf_entry.name = 'Variable Contents'; -matlabbatch{53}.menu_cfg.menu_entry.conf_entry.tag = 'vcont'; -matlabbatch{53}.menu_cfg.menu_entry.conf_entry.strtype = 'e'; -matlabbatch{53}.menu_cfg.menu_entry.conf_entry.extras = []; -matlabbatch{53}.menu_cfg.menu_entry.conf_entry.num = []; -matlabbatch{53}.menu_cfg.menu_entry.conf_entry.check = []; -matlabbatch{53}.menu_cfg.menu_entry.conf_entry.help = {'Contents to be saved. This can be any MATLAB variable or an output from another module, passed as dependency.'}; -matlabbatch{53}.menu_cfg.menu_entry.conf_entry.def = []; -matlabbatch{54}.menu_cfg.menu_struct.conf_branch.type = 'cfg_branch'; -matlabbatch{54}.menu_cfg.menu_struct.conf_branch.name = 'Variable'; -matlabbatch{54}.menu_cfg.menu_struct.conf_branch.tag = 'vars'; -matlabbatch{54}.menu_cfg.menu_struct.conf_branch.val{1}(1) = cfg_dep; -matlabbatch{54}.menu_cfg.menu_struct.conf_branch.val{1}(1).tname = 'Val Item'; -matlabbatch{54}.menu_cfg.menu_struct.conf_branch.val{1}(1).tgt_spec = {}; -matlabbatch{54}.menu_cfg.menu_struct.conf_branch.val{1}(1).sname = 'Variable Name (cfg_entry)'; -matlabbatch{54}.menu_cfg.menu_struct.conf_branch.val{1}(1).src_exbranch = substruct('.','val', '{}',{52}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{54}.menu_cfg.menu_struct.conf_branch.val{1}(1).src_output = substruct('()',{1}); -matlabbatch{54}.menu_cfg.menu_struct.conf_branch.val{2}(1) = cfg_dep; -matlabbatch{54}.menu_cfg.menu_struct.conf_branch.val{2}(1).tname = 'Val Item'; -matlabbatch{54}.menu_cfg.menu_struct.conf_branch.val{2}(1).tgt_spec = {}; -matlabbatch{54}.menu_cfg.menu_struct.conf_branch.val{2}(1).sname = 'Variable Contents (cfg_entry)'; -matlabbatch{54}.menu_cfg.menu_struct.conf_branch.val{2}(1).src_exbranch = substruct('.','val', '{}',{53}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{54}.menu_cfg.menu_struct.conf_branch.val{2}(1).src_output = substruct('()',{1}); -matlabbatch{54}.menu_cfg.menu_struct.conf_branch.check = []; -matlabbatch{54}.menu_cfg.menu_struct.conf_branch.help = {'For each variable, a name and its contents has to be specified.'}; -matlabbatch{55}.menu_cfg.menu_struct.conf_repeat.type = 'cfg_repeat'; -matlabbatch{55}.menu_cfg.menu_struct.conf_repeat.name = 'Variables'; -matlabbatch{55}.menu_cfg.menu_struct.conf_repeat.tag = 'vars'; -matlabbatch{55}.menu_cfg.menu_struct.conf_repeat.values{1}(1) = cfg_dep; -matlabbatch{55}.menu_cfg.menu_struct.conf_repeat.values{1}(1).tname = 'Values Item'; -matlabbatch{55}.menu_cfg.menu_struct.conf_repeat.values{1}(1).tgt_spec = {}; -matlabbatch{55}.menu_cfg.menu_struct.conf_repeat.values{1}(1).sname = 'Variable (cfg_branch)'; -matlabbatch{55}.menu_cfg.menu_struct.conf_repeat.values{1}(1).src_exbranch = substruct('.','val', '{}',{54}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{55}.menu_cfg.menu_struct.conf_repeat.values{1}(1).src_output = substruct('()',{1}); -matlabbatch{55}.menu_cfg.menu_struct.conf_repeat.num = [1 Inf]; -matlabbatch{55}.menu_cfg.menu_struct.conf_repeat.forcestruct = false; -matlabbatch{55}.menu_cfg.menu_struct.conf_repeat.check = []; -matlabbatch{55}.menu_cfg.menu_struct.conf_repeat.help = {'Any number of variables can be saved in this file together.'}; -matlabbatch{56}.menu_cfg.menu_entry.conf_menu.type = 'cfg_menu'; -matlabbatch{56}.menu_cfg.menu_entry.conf_menu.name = 'Save as'; -matlabbatch{56}.menu_cfg.menu_entry.conf_menu.tag = 'saveasstruct'; -matlabbatch{56}.menu_cfg.menu_entry.conf_menu.labels = { - 'Individual Variables' - 'Struct Variable' - }'; -matlabbatch{56}.menu_cfg.menu_entry.conf_menu.values = { - false - true - }'; -matlabbatch{56}.menu_cfg.menu_entry.conf_menu.check = []; -matlabbatch{56}.menu_cfg.menu_entry.conf_menu.help = {'Variables can be saved into the file individually or as a single struct variable, with the names of the variables used as fieldnames.'}; -matlabbatch{56}.menu_cfg.menu_entry.conf_menu.def = []; -matlabbatch{57}.menu_cfg.menu_struct.conf_exbranch.type = 'cfg_exbranch'; -matlabbatch{57}.menu_cfg.menu_struct.conf_exbranch.name = 'Save Variables'; -matlabbatch{57}.menu_cfg.menu_struct.conf_exbranch.tag = 'cfg_save_vars'; -matlabbatch{57}.menu_cfg.menu_struct.conf_exbranch.val{1}(1) = cfg_dep; -matlabbatch{57}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tname = 'Val Item'; -matlabbatch{57}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tgt_spec = {}; -matlabbatch{57}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).sname = 'Output Filename (cfg_entry)'; -matlabbatch{57}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_exbranch = substruct('.','val', '{}',{50}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{57}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_output = substruct('()',{1}); -matlabbatch{57}.menu_cfg.menu_struct.conf_exbranch.val{2}(1) = cfg_dep; -matlabbatch{57}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tname = 'Val Item'; -matlabbatch{57}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tgt_spec = {}; -matlabbatch{57}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).sname = 'Output Directory (cfg_files)'; -matlabbatch{57}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_exbranch = substruct('.','val', '{}',{51}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{57}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_output = substruct('()',{1}); -matlabbatch{57}.menu_cfg.menu_struct.conf_exbranch.val{3}(1) = cfg_dep; -matlabbatch{57}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).tname = 'Val Item'; -matlabbatch{57}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).tgt_spec = {}; -matlabbatch{57}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).sname = 'Variables (cfg_repeat)'; -matlabbatch{57}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).src_exbranch = substruct('.','val', '{}',{55}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{57}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).src_output = substruct('()',{1}); -matlabbatch{57}.menu_cfg.menu_struct.conf_exbranch.val{4}(1) = cfg_dep; -matlabbatch{57}.menu_cfg.menu_struct.conf_exbranch.val{4}(1).tname = 'Val Item'; -matlabbatch{57}.menu_cfg.menu_struct.conf_exbranch.val{4}(1).tgt_spec = {}; -matlabbatch{57}.menu_cfg.menu_struct.conf_exbranch.val{4}(1).sname = 'Save as (cfg_menu)'; -matlabbatch{57}.menu_cfg.menu_struct.conf_exbranch.val{4}(1).src_exbranch = substruct('.','val', '{}',{56}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{57}.menu_cfg.menu_struct.conf_exbranch.val{4}(1).src_output = substruct('()',{1}); -matlabbatch{57}.menu_cfg.menu_struct.conf_exbranch.prog = @cfg_run_save_vars; -matlabbatch{57}.menu_cfg.menu_struct.conf_exbranch.vout = @cfg_vout_save_vars; -matlabbatch{57}.menu_cfg.menu_struct.conf_exbranch.check = []; -matlabbatch{57}.menu_cfg.menu_struct.conf_exbranch.help = {'Save a collection of variables to a .mat file.'}; -matlabbatch{58}.menu_cfg.menu_entry.conf_entry.type = 'cfg_entry'; -matlabbatch{58}.menu_cfg.menu_entry.conf_entry.name = 'Input variable'; -matlabbatch{58}.menu_cfg.menu_entry.conf_entry.tag = 'input'; -matlabbatch{58}.menu_cfg.menu_entry.conf_entry.strtype = 'e'; -matlabbatch{58}.menu_cfg.menu_entry.conf_entry.extras = []; -matlabbatch{58}.menu_cfg.menu_entry.conf_entry.num = [1 1]; -matlabbatch{58}.menu_cfg.menu_entry.conf_entry.check = []; -matlabbatch{58}.menu_cfg.menu_entry.conf_entry.help = {'Enter the input variable.'}; -matlabbatch{58}.menu_cfg.menu_entry.conf_entry.def = []; -matlabbatch{59}.menu_cfg.menu_entry.conf_entry.type = 'cfg_entry'; -matlabbatch{59}.menu_cfg.menu_entry.conf_entry.name = 'Field reference'; -matlabbatch{59}.menu_cfg.menu_entry.conf_entry.tag = 'subsfield'; -matlabbatch{59}.menu_cfg.menu_entry.conf_entry.strtype = 's'; -matlabbatch{59}.menu_cfg.menu_entry.conf_entry.extras = []; -matlabbatch{59}.menu_cfg.menu_entry.conf_entry.num = [1 Inf]; -matlabbatch{59}.menu_cfg.menu_entry.conf_entry.check = []; -matlabbatch{59}.menu_cfg.menu_entry.conf_entry.help = {}; -matlabbatch{59}.menu_cfg.menu_entry.conf_entry.def = []; -matlabbatch{60}.menu_cfg.menu_entry.conf_entry.type = 'cfg_entry'; -matlabbatch{60}.menu_cfg.menu_entry.conf_entry.name = 'Cell index'; -matlabbatch{60}.menu_cfg.menu_entry.conf_entry.tag = 'subsindc'; -matlabbatch{60}.menu_cfg.menu_entry.conf_entry.strtype = 'e'; -matlabbatch{60}.menu_cfg.menu_entry.conf_entry.extras = []; -matlabbatch{60}.menu_cfg.menu_entry.conf_entry.num = [1 Inf]; -matlabbatch{60}.menu_cfg.menu_entry.conf_entry.check = @(job)cfg_run_subsrefvar('check','subsind',job); -matlabbatch{60}.menu_cfg.menu_entry.conf_entry.help = {'Enter a range of positive numbers or the string '':'' to reference all items.'}; -matlabbatch{60}.menu_cfg.menu_entry.conf_entry.def = []; -matlabbatch{61}.menu_cfg.menu_entry.conf_entry.type = 'cfg_entry'; -matlabbatch{61}.menu_cfg.menu_entry.conf_entry.name = 'Array index'; -matlabbatch{61}.menu_cfg.menu_entry.conf_entry.tag = 'subsinda'; -matlabbatch{61}.menu_cfg.menu_entry.conf_entry.strtype = 'e'; -matlabbatch{61}.menu_cfg.menu_entry.conf_entry.extras = []; -matlabbatch{61}.menu_cfg.menu_entry.conf_entry.num = [1 Inf]; -matlabbatch{61}.menu_cfg.menu_entry.conf_entry.check = @(job)cfg_run_subsrefvar('check','subsind',job); -matlabbatch{61}.menu_cfg.menu_entry.conf_entry.help = {'Enter a range of positive numbers or the string '':'' to reference all items.'}; -matlabbatch{61}.menu_cfg.menu_entry.conf_entry.def = []; -matlabbatch{62}.menu_cfg.menu_struct.conf_repeat.type = 'cfg_repeat'; -matlabbatch{62}.menu_cfg.menu_struct.conf_repeat.name = 'Cell array reference'; -matlabbatch{62}.menu_cfg.menu_struct.conf_repeat.tag = 'subsindc'; -matlabbatch{62}.menu_cfg.menu_struct.conf_repeat.values{1}(1) = cfg_dep; -matlabbatch{62}.menu_cfg.menu_struct.conf_repeat.values{1}(1).tname = 'Values Item'; -matlabbatch{62}.menu_cfg.menu_struct.conf_repeat.values{1}(1).tgt_spec = {}; -matlabbatch{62}.menu_cfg.menu_struct.conf_repeat.values{1}(1).sname = 'Entry: Cell index (cfg_entry)'; -matlabbatch{62}.menu_cfg.menu_struct.conf_repeat.values{1}(1).src_exbranch = substruct('.','val', '{}',{60}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{62}.menu_cfg.menu_struct.conf_repeat.values{1}(1).src_output = substruct('()',{1}); -matlabbatch{62}.menu_cfg.menu_struct.conf_repeat.num = [1 Inf]; -matlabbatch{62}.menu_cfg.menu_struct.conf_repeat.forcestruct = false; -matlabbatch{62}.menu_cfg.menu_struct.conf_repeat.check = []; -matlabbatch{62}.menu_cfg.menu_struct.conf_repeat.help = {'For each dimension of an array, enter the subscripts to be indexed. Any multidimensional array can also be indexed by a single linear index.'}; -matlabbatch{63}.menu_cfg.menu_struct.conf_repeat.type = 'cfg_repeat'; -matlabbatch{63}.menu_cfg.menu_struct.conf_repeat.name = 'Array reference'; -matlabbatch{63}.menu_cfg.menu_struct.conf_repeat.tag = 'subsinda'; -matlabbatch{63}.menu_cfg.menu_struct.conf_repeat.values{1}(1) = cfg_dep; -matlabbatch{63}.menu_cfg.menu_struct.conf_repeat.values{1}(1).tname = 'Values Item'; -matlabbatch{63}.menu_cfg.menu_struct.conf_repeat.values{1}(1).tgt_spec = {}; -matlabbatch{63}.menu_cfg.menu_struct.conf_repeat.values{1}(1).sname = 'Entry: Array index (cfg_entry)'; -matlabbatch{63}.menu_cfg.menu_struct.conf_repeat.values{1}(1).src_exbranch = substruct('.','val', '{}',{61}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{63}.menu_cfg.menu_struct.conf_repeat.values{1}(1).src_output = substruct('()',{1}); -matlabbatch{63}.menu_cfg.menu_struct.conf_repeat.num = [1 Inf]; -matlabbatch{63}.menu_cfg.menu_struct.conf_repeat.forcestruct = false; -matlabbatch{63}.menu_cfg.menu_struct.conf_repeat.check = []; -matlabbatch{63}.menu_cfg.menu_struct.conf_repeat.help = {'For each dimension of an array, enter the subscripts to be indexed. Any multidimensional array can also be indexed by a single linear index.'}; -matlabbatch{64}.menu_cfg.menu_struct.conf_repeat.type = 'cfg_repeat'; -matlabbatch{64}.menu_cfg.menu_struct.conf_repeat.name = 'Part of variable to access'; -matlabbatch{64}.menu_cfg.menu_struct.conf_repeat.tag = 'subsreference'; -matlabbatch{64}.menu_cfg.menu_struct.conf_repeat.values{1}(1) = cfg_dep; -matlabbatch{64}.menu_cfg.menu_struct.conf_repeat.values{1}(1).tname = 'Values Item'; -matlabbatch{64}.menu_cfg.menu_struct.conf_repeat.values{1}(1).tgt_spec = {}; -matlabbatch{64}.menu_cfg.menu_struct.conf_repeat.values{1}(1).sname = 'Entry: Field reference (cfg_entry)'; -matlabbatch{64}.menu_cfg.menu_struct.conf_repeat.values{1}(1).src_exbranch = substruct('.','val', '{}',{59}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{64}.menu_cfg.menu_struct.conf_repeat.values{1}(1).src_output = substruct('()',{1}); -matlabbatch{64}.menu_cfg.menu_struct.conf_repeat.values{2}(1) = cfg_dep; -matlabbatch{64}.menu_cfg.menu_struct.conf_repeat.values{2}(1).tname = 'Values Item'; -matlabbatch{64}.menu_cfg.menu_struct.conf_repeat.values{2}(1).tgt_spec = {}; -matlabbatch{64}.menu_cfg.menu_struct.conf_repeat.values{2}(1).sname = 'Repeat: Cell array reference (cfg_repeat)'; -matlabbatch{64}.menu_cfg.menu_struct.conf_repeat.values{2}(1).src_exbranch = substruct('.','val', '{}',{62}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{64}.menu_cfg.menu_struct.conf_repeat.values{2}(1).src_output = substruct('()',{1}); -matlabbatch{64}.menu_cfg.menu_struct.conf_repeat.values{3}(1) = cfg_dep; -matlabbatch{64}.menu_cfg.menu_struct.conf_repeat.values{3}(1).tname = 'Values Item'; -matlabbatch{64}.menu_cfg.menu_struct.conf_repeat.values{3}(1).tgt_spec = {}; -matlabbatch{64}.menu_cfg.menu_struct.conf_repeat.values{3}(1).sname = 'Repeat: Array reference (cfg_repeat)'; -matlabbatch{64}.menu_cfg.menu_struct.conf_repeat.values{3}(1).src_exbranch = substruct('.','val', '{}',{63}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{64}.menu_cfg.menu_struct.conf_repeat.values{3}(1).src_output = substruct('()',{1}); -matlabbatch{64}.menu_cfg.menu_struct.conf_repeat.num = [1 Inf]; -matlabbatch{64}.menu_cfg.menu_struct.conf_repeat.forcestruct = true; -matlabbatch{64}.menu_cfg.menu_struct.conf_repeat.check = []; -matlabbatch{64}.menu_cfg.menu_struct.conf_repeat.help = { - 'Enter the sequence of subscript references. The leftmost reference is on the top of the list, the rightmost at the bottom.' - 'To reference e.g. the field ''xY'' in a SPM variable, enter ''xY'' as ''Field reference''. To reference SPM.xY(1), enter ''xY'' as field reference, followed by 1 as an ''Array reference''.' - }'; -matlabbatch{65}.menu_cfg.menu_struct.conf_exbranch.type = 'cfg_exbranch'; -matlabbatch{65}.menu_cfg.menu_struct.conf_exbranch.name = 'Access part of MATLAB variable'; -matlabbatch{65}.menu_cfg.menu_struct.conf_exbranch.tag = 'subsrefvar'; -matlabbatch{65}.menu_cfg.menu_struct.conf_exbranch.val{1}(1) = cfg_dep; -matlabbatch{65}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tname = 'Val Item'; -matlabbatch{65}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tgt_spec = {}; -matlabbatch{65}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).sname = 'Entry: Input variable (cfg_entry)'; -matlabbatch{65}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_exbranch = substruct('.','val', '{}',{58}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{65}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_output = substruct('()',{1}); -matlabbatch{65}.menu_cfg.menu_struct.conf_exbranch.val{2}(1) = cfg_dep; -matlabbatch{65}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tname = 'Val Item'; -matlabbatch{65}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tgt_spec = {}; -matlabbatch{65}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).sname = 'Repeat: Part of variable to access (cfg_repeat)'; -matlabbatch{65}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_exbranch = substruct('.','val', '{}',{64}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{65}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_output = substruct('()',{1}); -matlabbatch{65}.menu_cfg.menu_struct.conf_exbranch.prog = @(job)cfg_run_subsrefvar('run',job); -matlabbatch{65}.menu_cfg.menu_struct.conf_exbranch.vout = @(job)cfg_run_subsrefvar('vout',job); -matlabbatch{65}.menu_cfg.menu_struct.conf_exbranch.check = []; -matlabbatch{65}.menu_cfg.menu_struct.conf_exbranch.help = {}; -matlabbatch{66}.menu_cfg.menu_entry.conf_entry.type = 'cfg_entry'; -matlabbatch{66}.menu_cfg.menu_entry.conf_entry.name = 'Output Variable Name'; -matlabbatch{66}.menu_cfg.menu_entry.conf_entry.tag = 'name'; -matlabbatch{66}.menu_cfg.menu_entry.conf_entry.strtype = 's'; -matlabbatch{66}.menu_cfg.menu_entry.conf_entry.extras = []; -matlabbatch{66}.menu_cfg.menu_entry.conf_entry.num = [1 Inf]; -matlabbatch{66}.menu_cfg.menu_entry.conf_entry.check = @cfg_check_assignin; -matlabbatch{66}.menu_cfg.menu_entry.conf_entry.help = {'Enter a valid MATLAB variable name. The contents of the input to "Output Item" will be assigned to a variable of this name in MATLAB workspace.'}; -matlabbatch{66}.menu_cfg.menu_entry.conf_entry.def = []; -matlabbatch{67}.menu_cfg.menu_entry.conf_entry.type = 'cfg_entry'; -matlabbatch{67}.menu_cfg.menu_entry.conf_entry.name = 'Output Item'; -matlabbatch{67}.menu_cfg.menu_entry.conf_entry.tag = 'output'; -matlabbatch{67}.menu_cfg.menu_entry.conf_entry.strtype = 'e'; -matlabbatch{67}.menu_cfg.menu_entry.conf_entry.extras = []; -matlabbatch{67}.menu_cfg.menu_entry.conf_entry.num = []; -matlabbatch{67}.menu_cfg.menu_entry.conf_entry.check = []; -matlabbatch{67}.menu_cfg.menu_entry.conf_entry.help = {'The contents that is passed to this input that will be assigned to the workspace variable whose name is given in "Output Variable Name".'}; -matlabbatch{67}.menu_cfg.menu_entry.conf_entry.def = []; -matlabbatch{68}.menu_cfg.menu_struct.conf_exbranch.type = 'cfg_exbranch'; -matlabbatch{68}.menu_cfg.menu_struct.conf_exbranch.name = 'Pass Output to Workspace'; -matlabbatch{68}.menu_cfg.menu_struct.conf_exbranch.tag = 'cfg_assignin'; -matlabbatch{68}.menu_cfg.menu_struct.conf_exbranch.val{1}(1) = cfg_dep; -matlabbatch{68}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tname = 'Val Item'; -matlabbatch{68}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tgt_spec = {}; -matlabbatch{68}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).sname = 'Output Variable Name (cfg_entry)'; -matlabbatch{68}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_exbranch = substruct('.','val', '{}',{66}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{68}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_output = substruct('()',{1}); -matlabbatch{68}.menu_cfg.menu_struct.conf_exbranch.val{2}(1) = cfg_dep; -matlabbatch{68}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tname = 'Val Item'; -matlabbatch{68}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tgt_spec = {}; -matlabbatch{68}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).sname = 'Output Item (cfg_entry)'; -matlabbatch{68}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_exbranch = substruct('.','val', '{}',{67}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{68}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_output = substruct('()',{1}); -matlabbatch{68}.menu_cfg.menu_struct.conf_exbranch.prog = @cfg_run_assignin; -matlabbatch{68}.menu_cfg.menu_struct.conf_exbranch.vout = []; -matlabbatch{68}.menu_cfg.menu_struct.conf_exbranch.check = []; -matlabbatch{68}.menu_cfg.menu_struct.conf_exbranch.help = { - 'Assign a computation result to a workspace variable.' - 'The value entered into "Output Item" will be assigned to a MATLAB workspace variable whose name is specified in "Output Variable Name". If this variable already exists, a new variable name will be generated. This can be useful to assess the results of computations with other MATLAB routines or for debugging.' - }'; -matlabbatch{69}.menu_cfg.menu_entry.conf_entry.type = 'cfg_entry'; -matlabbatch{69}.menu_cfg.menu_entry.conf_entry.name = 'String'; -matlabbatch{69}.menu_cfg.menu_entry.conf_entry.tag = 'instr'; -matlabbatch{69}.menu_cfg.menu_entry.conf_entry.strtype = 's'; -matlabbatch{69}.menu_cfg.menu_entry.conf_entry.extras = []; -matlabbatch{69}.menu_cfg.menu_entry.conf_entry.num = [0 Inf]; -matlabbatch{69}.menu_cfg.menu_entry.conf_entry.check = []; -matlabbatch{69}.menu_cfg.menu_entry.conf_entry.help = {'Enter a string.'}; -matlabbatch{69}.menu_cfg.menu_entry.conf_entry.def = []; -matlabbatch{70}.menu_cfg.menu_entry.conf_entry.type = 'cfg_entry'; -matlabbatch{70}.menu_cfg.menu_entry.conf_entry.name = 'Evaluated Input'; -matlabbatch{70}.menu_cfg.menu_entry.conf_entry.tag = 'ineval'; -matlabbatch{70}.menu_cfg.menu_entry.conf_entry.strtype = 'e'; -matlabbatch{70}.menu_cfg.menu_entry.conf_entry.extras = []; -matlabbatch{70}.menu_cfg.menu_entry.conf_entry.num = []; -matlabbatch{70}.menu_cfg.menu_entry.conf_entry.check = []; -matlabbatch{70}.menu_cfg.menu_entry.conf_entry.help = {'Enter an evaluated input.'}; -matlabbatch{70}.menu_cfg.menu_entry.conf_entry.def = []; -matlabbatch{71}.menu_cfg.menu_entry.conf_files.type = 'cfg_files'; -matlabbatch{71}.menu_cfg.menu_entry.conf_files.name = 'NIfTI Images'; -matlabbatch{71}.menu_cfg.menu_entry.conf_files.tag = 'innifti'; -matlabbatch{71}.menu_cfg.menu_entry.conf_files.filter = 'image'; -matlabbatch{71}.menu_cfg.menu_entry.conf_files.ufilter = '.*'; -matlabbatch{71}.menu_cfg.menu_entry.conf_files.dir = ''; -matlabbatch{71}.menu_cfg.menu_entry.conf_files.num = [0 Inf]; -matlabbatch{71}.menu_cfg.menu_entry.conf_files.check = []; -matlabbatch{71}.menu_cfg.menu_entry.conf_files.help = {'Select NIfTI Images'}; -matlabbatch{71}.menu_cfg.menu_entry.conf_files.def = []; -matlabbatch{72}.menu_cfg.menu_entry.conf_files.type = 'cfg_files'; -matlabbatch{72}.menu_cfg.menu_entry.conf_files.name = 'MATLAB .mat Files'; -matlabbatch{72}.menu_cfg.menu_entry.conf_files.tag = 'inmat'; -matlabbatch{72}.menu_cfg.menu_entry.conf_files.filter = 'mat'; -matlabbatch{72}.menu_cfg.menu_entry.conf_files.ufilter = '.*'; -matlabbatch{72}.menu_cfg.menu_entry.conf_files.dir = ''; -matlabbatch{72}.menu_cfg.menu_entry.conf_files.num = [0 Inf]; -matlabbatch{72}.menu_cfg.menu_entry.conf_files.check = []; -matlabbatch{72}.menu_cfg.menu_entry.conf_files.help = {'Select MATLAB .mat files.'}; -matlabbatch{72}.menu_cfg.menu_entry.conf_files.def = []; -matlabbatch{73}.menu_cfg.menu_entry.conf_files.type = 'cfg_files'; -matlabbatch{73}.menu_cfg.menu_entry.conf_files.name = 'Any Files'; -matlabbatch{73}.menu_cfg.menu_entry.conf_files.tag = 'inany'; -matlabbatch{73}.menu_cfg.menu_entry.conf_files.filter = 'any'; -matlabbatch{73}.menu_cfg.menu_entry.conf_files.ufilter = '.*'; -matlabbatch{73}.menu_cfg.menu_entry.conf_files.dir = ''; -matlabbatch{73}.menu_cfg.menu_entry.conf_files.num = [0 Inf]; -matlabbatch{73}.menu_cfg.menu_entry.conf_files.check = []; -matlabbatch{73}.menu_cfg.menu_entry.conf_files.help = {'Select any kind of files.'}; -matlabbatch{73}.menu_cfg.menu_entry.conf_files.def = []; -matlabbatch{74}.menu_cfg.menu_entry.conf_files.type = 'cfg_files'; -matlabbatch{74}.menu_cfg.menu_entry.conf_files.name = 'Directory'; -matlabbatch{74}.menu_cfg.menu_entry.conf_files.tag = 'indir'; -matlabbatch{74}.menu_cfg.menu_entry.conf_files.filter = 'dir'; -matlabbatch{74}.menu_cfg.menu_entry.conf_files.ufilter = '.*'; -matlabbatch{74}.menu_cfg.menu_entry.conf_files.dir = ''; -matlabbatch{74}.menu_cfg.menu_entry.conf_files.num = [1 Inf]; -matlabbatch{74}.menu_cfg.menu_entry.conf_files.check = []; -matlabbatch{74}.menu_cfg.menu_entry.conf_files.help = {'Directory'}; -matlabbatch{74}.menu_cfg.menu_entry.conf_files.def = []; -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.type = 'cfg_repeat'; -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.name = 'Job Inputs'; -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.tag = 'inputs'; -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{1}(1) = cfg_dep; -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{1}(1).tname = 'Values Item'; -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{1}(1).tgt_spec = {}; -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{1}(1).sname = 'Entry: String (cfg_entry)'; -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{1}(1).src_exbranch = substruct('.','val', '{}',{69}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{1}(1).src_output = substruct('()',{1}); -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{2}(1) = cfg_dep; -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{2}(1).tname = 'Values Item'; -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{2}(1).tgt_spec = {}; -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{2}(1).sname = 'Entry: Evaluated Input (cfg_entry)'; -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{2}(1).src_exbranch = substruct('.','val', '{}',{70}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{2}(1).src_output = substruct('()',{1}); -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{3}(1) = cfg_dep; -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{3}(1).tname = 'Values Item'; -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{3}(1).tgt_spec = {}; -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{3}(1).sname = 'Files: NIfTI Images (cfg_files)'; -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{3}(1).src_exbranch = substruct('.','val', '{}',{71}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{3}(1).src_output = substruct('()',{1}); -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{4}(1) = cfg_dep; -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{4}(1).tname = 'Values Item'; -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{4}(1).tgt_spec = {}; -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{4}(1).sname = 'Files: MATLAB .mat Files (cfg_files)'; -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{4}(1).src_exbranch = substruct('.','val', '{}',{72}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{4}(1).src_output = substruct('()',{1}); -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{5}(1) = cfg_dep; -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{5}(1).tname = 'Values Item'; -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{5}(1).tgt_spec = {}; -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{5}(1).sname = 'Files: Any Files (cfg_files)'; -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{5}(1).src_exbranch = substruct('.','val', '{}',{73}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{5}(1).src_output = substruct('()',{1}); -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{6}(1) = cfg_dep; -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{6}(1).tname = 'Values Item'; -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{6}(1).tgt_spec = {}; -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{6}(1).sname = 'Files: Directory (cfg_files)'; -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{6}(1).src_exbranch = substruct('.','val', '{}',{74}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.values{6}(1).src_output = substruct('()',{1}); -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.num = [0 Inf]; -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.forcestruct = false; -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.check = []; -matlabbatch{75}.menu_cfg.menu_struct.conf_repeat.help = {'Assemble the set of input items for one run of the job.'}; -matlabbatch{76}.menu_cfg.menu_struct.conf_repeat.type = 'cfg_repeat'; -matlabbatch{76}.menu_cfg.menu_struct.conf_repeat.name = 'Runs'; -matlabbatch{76}.menu_cfg.menu_struct.conf_repeat.tag = 'runs'; -matlabbatch{76}.menu_cfg.menu_struct.conf_repeat.values{1}(1) = cfg_dep; -matlabbatch{76}.menu_cfg.menu_struct.conf_repeat.values{1}(1).tname = 'Values Item'; -matlabbatch{76}.menu_cfg.menu_struct.conf_repeat.values{1}(1).tgt_spec = {}; -matlabbatch{76}.menu_cfg.menu_struct.conf_repeat.values{1}(1).sname = 'Repeat: Job Inputs (cfg_repeat)'; -matlabbatch{76}.menu_cfg.menu_struct.conf_repeat.values{1}(1).src_exbranch = substruct('.','val', '{}',{75}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{76}.menu_cfg.menu_struct.conf_repeat.values{1}(1).src_output = substruct('()',{1}); -matlabbatch{76}.menu_cfg.menu_struct.conf_repeat.num = [1 Inf]; -matlabbatch{76}.menu_cfg.menu_struct.conf_repeat.forcestruct = false; -matlabbatch{76}.menu_cfg.menu_struct.conf_repeat.check = []; -matlabbatch{76}.menu_cfg.menu_struct.conf_repeat.help = {'Repeat "Job Inputs" for each run of the job, even if you want to specify no inputs in this batch itself. The number of "Job Inputs" items determines how often this job is run.'}; -matlabbatch{77}.menu_cfg.menu_entry.conf_files.type = 'cfg_files'; -matlabbatch{77}.menu_cfg.menu_entry.conf_files.name = 'Job File(s)'; -matlabbatch{77}.menu_cfg.menu_entry.conf_files.tag = 'jobs'; -matlabbatch{77}.menu_cfg.menu_entry.conf_files.filter = 'batch'; -matlabbatch{77}.menu_cfg.menu_entry.conf_files.ufilter = '.*'; -matlabbatch{77}.menu_cfg.menu_entry.conf_files.dir = ''; -matlabbatch{77}.menu_cfg.menu_entry.conf_files.num = [1 Inf]; -matlabbatch{77}.menu_cfg.menu_entry.conf_files.check = []; -matlabbatch{77}.menu_cfg.menu_entry.conf_files.help = {'Select the job template(s). If multiple files are selected, they will be concatenated in selection order to form one job.'}; -matlabbatch{77}.menu_cfg.menu_entry.conf_files.def = []; -matlabbatch{78}.menu_cfg.menu_entry.conf_const.type = 'cfg_const'; -matlabbatch{78}.menu_cfg.menu_entry.conf_const.name = 'Don''t Save'; -matlabbatch{78}.menu_cfg.menu_entry.conf_const.tag = 'dontsave'; -matlabbatch{78}.menu_cfg.menu_entry.conf_const.val = {false}; -matlabbatch{78}.menu_cfg.menu_entry.conf_const.check = []; -matlabbatch{78}.menu_cfg.menu_entry.conf_const.help = {'Do not save the generated jobs.'}; -matlabbatch{78}.menu_cfg.menu_entry.conf_const.def = []; -matlabbatch{79}.menu_cfg.menu_entry.conf_entry.type = 'cfg_entry'; -matlabbatch{79}.menu_cfg.menu_entry.conf_entry.name = 'Batch Filename Stub'; -matlabbatch{79}.menu_cfg.menu_entry.conf_entry.tag = 'outstub'; -matlabbatch{79}.menu_cfg.menu_entry.conf_entry.strtype = 's'; -matlabbatch{79}.menu_cfg.menu_entry.conf_entry.extras = []; -matlabbatch{79}.menu_cfg.menu_entry.conf_entry.num = [1 Inf]; -matlabbatch{79}.menu_cfg.menu_entry.conf_entry.check = []; -matlabbatch{79}.menu_cfg.menu_entry.conf_entry.help = {'The output filename will be generated by appending a job counter to this string.'}; -matlabbatch{79}.menu_cfg.menu_entry.conf_entry.def = []; -matlabbatch{80}.menu_cfg.menu_entry.conf_files.type = 'cfg_files'; -matlabbatch{80}.menu_cfg.menu_entry.conf_files.name = 'Batch Directory'; -matlabbatch{80}.menu_cfg.menu_entry.conf_files.tag = 'outdir'; -matlabbatch{80}.menu_cfg.menu_entry.conf_files.filter = 'dir'; -matlabbatch{80}.menu_cfg.menu_entry.conf_files.ufilter = '.*'; -matlabbatch{80}.menu_cfg.menu_entry.conf_files.dir = ''; -matlabbatch{80}.menu_cfg.menu_entry.conf_files.num = [1 1]; -matlabbatch{80}.menu_cfg.menu_entry.conf_files.check = []; -matlabbatch{80}.menu_cfg.menu_entry.conf_files.help = {'The generated batches will be saved into this folder.'}; -matlabbatch{80}.menu_cfg.menu_entry.conf_files.def = []; -matlabbatch{81}.menu_cfg.menu_struct.conf_branch.type = 'cfg_branch'; -matlabbatch{81}.menu_cfg.menu_struct.conf_branch.name = 'Save'; -matlabbatch{81}.menu_cfg.menu_struct.conf_branch.tag = 'savejobs'; -matlabbatch{81}.menu_cfg.menu_struct.conf_branch.val{1}(1) = cfg_dep; -matlabbatch{81}.menu_cfg.menu_struct.conf_branch.val{1}(1).tname = 'Val Item'; -matlabbatch{81}.menu_cfg.menu_struct.conf_branch.val{1}(1).tgt_spec = {}; -matlabbatch{81}.menu_cfg.menu_struct.conf_branch.val{1}(1).sname = 'Batch Filename Stub (cfg_entry)'; -matlabbatch{81}.menu_cfg.menu_struct.conf_branch.val{1}(1).src_exbranch = substruct('.','val', '{}',{79}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{81}.menu_cfg.menu_struct.conf_branch.val{1}(1).src_output = substruct('()',{1}); -matlabbatch{81}.menu_cfg.menu_struct.conf_branch.val{2}(1) = cfg_dep; -matlabbatch{81}.menu_cfg.menu_struct.conf_branch.val{2}(1).tname = 'Val Item'; -matlabbatch{81}.menu_cfg.menu_struct.conf_branch.val{2}(1).tgt_spec = {}; -matlabbatch{81}.menu_cfg.menu_struct.conf_branch.val{2}(1).sname = 'Batch Directory (cfg_files)'; -matlabbatch{81}.menu_cfg.menu_struct.conf_branch.val{2}(1).src_exbranch = substruct('.','val', '{}',{80}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{81}.menu_cfg.menu_struct.conf_branch.val{2}(1).src_output = substruct('()',{1}); -matlabbatch{81}.menu_cfg.menu_struct.conf_branch.check = []; -matlabbatch{81}.menu_cfg.menu_struct.conf_branch.help = {'Specify filename stub and output directory to save the generated files.'}; -matlabbatch{82}.menu_cfg.menu_struct.conf_choice.type = 'cfg_choice'; -matlabbatch{82}.menu_cfg.menu_struct.conf_choice.name = 'Save Generated Batch Jobs'; -matlabbatch{82}.menu_cfg.menu_struct.conf_choice.tag = 'save'; -matlabbatch{82}.menu_cfg.menu_struct.conf_choice.values{1}(1) = cfg_dep; -matlabbatch{82}.menu_cfg.menu_struct.conf_choice.values{1}(1).tname = 'Values Item'; -matlabbatch{82}.menu_cfg.menu_struct.conf_choice.values{1}(1).tgt_spec = {}; -matlabbatch{82}.menu_cfg.menu_struct.conf_choice.values{1}(1).sname = 'Save (cfg_branch)'; -matlabbatch{82}.menu_cfg.menu_struct.conf_choice.values{1}(1).src_exbranch = substruct('.','val', '{}',{81}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{82}.menu_cfg.menu_struct.conf_choice.values{1}(1).src_output = substruct('()',{1}); -matlabbatch{82}.menu_cfg.menu_struct.conf_choice.values{2}(1) = cfg_dep; -matlabbatch{82}.menu_cfg.menu_struct.conf_choice.values{2}(1).tname = 'Values Item'; -matlabbatch{82}.menu_cfg.menu_struct.conf_choice.values{2}(1).tgt_spec = {}; -matlabbatch{82}.menu_cfg.menu_struct.conf_choice.values{2}(1).sname = 'Don''t Save (cfg_const)'; -matlabbatch{82}.menu_cfg.menu_struct.conf_choice.values{2}(1).src_exbranch = substruct('.','val', '{}',{78}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{82}.menu_cfg.menu_struct.conf_choice.values{2}(1).src_output = substruct('()',{1}); -matlabbatch{82}.menu_cfg.menu_struct.conf_choice.check = []; -matlabbatch{82}.menu_cfg.menu_struct.conf_choice.help = {'The generated batch jobs can be saved for reference or debugging purposes.'}; -matlabbatch{83}.menu_cfg.menu_entry.conf_menu.type = 'cfg_menu'; -matlabbatch{83}.menu_cfg.menu_entry.conf_menu.name = 'Missing Inputs'; -matlabbatch{83}.menu_cfg.menu_entry.conf_menu.tag = 'missing'; -matlabbatch{83}.menu_cfg.menu_entry.conf_menu.labels = { - 'Skip jobs with missing inputs, run filled jobs' - 'Don''t run any jobs if missing inputs' - }'; -matlabbatch{83}.menu_cfg.menu_entry.conf_menu.values = { - 'skip' - 'error' - }'; -matlabbatch{83}.menu_cfg.menu_entry.conf_menu.check = []; -matlabbatch{83}.menu_cfg.menu_entry.conf_menu.help = {'Jobs with missing inputs (e.g. because of wrong input contents) can be skipped, while filled jobs are run. Alternatively, if any job has missing inputs, no jobs are run.'}; -matlabbatch{83}.menu_cfg.menu_entry.conf_menu.def = []; -matlabbatch{84}.menu_cfg.menu_struct.conf_exbranch.type = 'cfg_exbranch'; -matlabbatch{84}.menu_cfg.menu_struct.conf_exbranch.name = 'Run Batch Jobs'; -matlabbatch{84}.menu_cfg.menu_struct.conf_exbranch.tag = 'runjobs'; -matlabbatch{84}.menu_cfg.menu_struct.conf_exbranch.val{1}(1) = cfg_dep; -matlabbatch{84}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tname = 'Val Item'; -matlabbatch{84}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tgt_spec = {}; -matlabbatch{84}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).sname = 'Job File(s) (cfg_files)'; -matlabbatch{84}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_exbranch = substruct('.','val', '{}',{77}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{84}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_output = substruct('()',{1}); -matlabbatch{84}.menu_cfg.menu_struct.conf_exbranch.val{2}(1) = cfg_dep; -matlabbatch{84}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tname = 'Val Item'; -matlabbatch{84}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tgt_spec = {}; -matlabbatch{84}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).sname = 'Runs (cfg_repeat)'; -matlabbatch{84}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_exbranch = substruct('.','val', '{}',{76}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{84}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_output = substruct('()',{1}); -matlabbatch{84}.menu_cfg.menu_struct.conf_exbranch.val{3}(1) = cfg_dep; -matlabbatch{84}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).tname = 'Val Item'; -matlabbatch{84}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).tgt_spec = {}; -matlabbatch{84}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).sname = 'Save Generated Batch Jobs (cfg_choice)'; -matlabbatch{84}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).src_exbranch = substruct('.','val', '{}',{82}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{84}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).src_output = substruct('()',{1}); -matlabbatch{84}.menu_cfg.menu_struct.conf_exbranch.val{4}(1) = cfg_dep; -matlabbatch{84}.menu_cfg.menu_struct.conf_exbranch.val{4}(1).tname = 'Val Item'; -matlabbatch{84}.menu_cfg.menu_struct.conf_exbranch.val{4}(1).tgt_spec = {}; -matlabbatch{84}.menu_cfg.menu_struct.conf_exbranch.val{4}(1).sname = 'Missing Inputs (cfg_menu)'; -matlabbatch{84}.menu_cfg.menu_struct.conf_exbranch.val{4}(1).src_exbranch = substruct('.','val', '{}',{83}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{84}.menu_cfg.menu_struct.conf_exbranch.val{4}(1).src_output = substruct('()',{1}); -matlabbatch{84}.menu_cfg.menu_struct.conf_exbranch.prog = @cfg_run_runjobs; -matlabbatch{84}.menu_cfg.menu_struct.conf_exbranch.vout = @cfg_vout_runjobs; -matlabbatch{84}.menu_cfg.menu_struct.conf_exbranch.check = []; -matlabbatch{84}.menu_cfg.menu_struct.conf_exbranch.help = {'Load a set of job files, fill missing inputs and run the filled job. This automates the creation and execution of batch jobs for a large number of identical computations.'}; -matlabbatch{85}.menu_cfg.menu_entry.conf_entry.type = 'cfg_entry'; -matlabbatch{85}.menu_cfg.menu_entry.conf_entry.name = 'Evaluated Input'; -matlabbatch{85}.menu_cfg.menu_entry.conf_entry.tag = 'evaluated'; -matlabbatch{85}.menu_cfg.menu_entry.conf_entry.strtype = 'e'; -matlabbatch{85}.menu_cfg.menu_entry.conf_entry.extras = []; -matlabbatch{85}.menu_cfg.menu_entry.conf_entry.num = []; -matlabbatch{85}.menu_cfg.menu_entry.conf_entry.check = []; -matlabbatch{85}.menu_cfg.menu_entry.conf_entry.help = {}; -matlabbatch{85}.menu_cfg.menu_entry.conf_entry.def = []; -matlabbatch{86}.menu_cfg.menu_entry.conf_entry.type = 'cfg_entry'; -matlabbatch{86}.menu_cfg.menu_entry.conf_entry.name = 'String'; -matlabbatch{86}.menu_cfg.menu_entry.conf_entry.tag = 'string'; -matlabbatch{86}.menu_cfg.menu_entry.conf_entry.strtype = 's'; -matlabbatch{86}.menu_cfg.menu_entry.conf_entry.extras = []; -matlabbatch{86}.menu_cfg.menu_entry.conf_entry.num = []; -matlabbatch{86}.menu_cfg.menu_entry.conf_entry.check = []; -matlabbatch{86}.menu_cfg.menu_entry.conf_entry.help = {}; -matlabbatch{86}.menu_cfg.menu_entry.conf_entry.def = []; -matlabbatch{87}.menu_cfg.menu_entry.conf_files.type = 'cfg_files'; -matlabbatch{87}.menu_cfg.menu_entry.conf_files.name = 'Any File'; -matlabbatch{87}.menu_cfg.menu_entry.conf_files.tag = 'anyfile'; -matlabbatch{87}.menu_cfg.menu_entry.conf_files.filter = 'any'; -matlabbatch{87}.menu_cfg.menu_entry.conf_files.ufilter = '.*'; -matlabbatch{87}.menu_cfg.menu_entry.conf_files.dir = []; -matlabbatch{87}.menu_cfg.menu_entry.conf_files.num = [0 Inf]; -matlabbatch{87}.menu_cfg.menu_entry.conf_files.check = []; -matlabbatch{87}.menu_cfg.menu_entry.conf_files.help = {}; -matlabbatch{87}.menu_cfg.menu_entry.conf_files.def = []; -matlabbatch{88}.menu_cfg.menu_entry.conf_files.type = 'cfg_files'; -matlabbatch{88}.menu_cfg.menu_entry.conf_files.name = 'NIfTI Image(s)'; -matlabbatch{88}.menu_cfg.menu_entry.conf_files.tag = 'images'; -matlabbatch{88}.menu_cfg.menu_entry.conf_files.filter = 'image'; -matlabbatch{88}.menu_cfg.menu_entry.conf_files.ufilter = '.*'; -matlabbatch{88}.menu_cfg.menu_entry.conf_files.dir = []; -matlabbatch{88}.menu_cfg.menu_entry.conf_files.num = [0 Inf]; -matlabbatch{88}.menu_cfg.menu_entry.conf_files.check = []; -matlabbatch{88}.menu_cfg.menu_entry.conf_files.help = {}; -matlabbatch{88}.menu_cfg.menu_entry.conf_files.def = []; -matlabbatch{89}.menu_cfg.menu_entry.conf_files.type = 'cfg_files'; -matlabbatch{89}.menu_cfg.menu_entry.conf_files.name = 'Directory'; -matlabbatch{89}.menu_cfg.menu_entry.conf_files.tag = 'directory'; -matlabbatch{89}.menu_cfg.menu_entry.conf_files.filter = 'dir'; -matlabbatch{89}.menu_cfg.menu_entry.conf_files.ufilter = '.*'; -matlabbatch{89}.menu_cfg.menu_entry.conf_files.dir = []; -matlabbatch{89}.menu_cfg.menu_entry.conf_files.num = [0 Inf]; -matlabbatch{89}.menu_cfg.menu_entry.conf_files.check = []; -matlabbatch{89}.menu_cfg.menu_entry.conf_files.help = {}; -matlabbatch{89}.menu_cfg.menu_entry.conf_files.def = []; -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.type = 'cfg_repeat'; -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.name = 'Inputs'; -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.tag = 'inputs'; -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.values{1}(1) = cfg_dep; -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.values{1}(1).tname = 'Values Item'; -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.values{1}(1).tgt_spec = {}; -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.values{1}(1).sname = 'Entry: Evaluated Input (cfg_entry)'; -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.values{1}(1).src_exbranch = substruct('.','val', '{}',{85}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.values{1}(1).src_output = substruct('()',{1}); -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.values{2}(1) = cfg_dep; -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.values{2}(1).tname = 'Values Item'; -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.values{2}(1).tgt_spec = {}; -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.values{2}(1).sname = 'Entry: String (cfg_entry)'; -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.values{2}(1).src_exbranch = substruct('.','val', '{}',{86}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.values{2}(1).src_output = substruct('()',{1}); -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.values{3}(1) = cfg_dep; -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.values{3}(1).tname = 'Values Item'; -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.values{3}(1).tgt_spec = {}; -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.values{3}(1).sname = 'Files: Any File (cfg_files)'; -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.values{3}(1).src_exbranch = substruct('.','val', '{}',{87}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.values{3}(1).src_output = substruct('()',{1}); -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.values{4}(1) = cfg_dep; -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.values{4}(1).tname = 'Values Item'; -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.values{4}(1).tgt_spec = {}; -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.values{4}(1).sname = 'Files: NIfTI Image(s) (cfg_files)'; -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.values{4}(1).src_exbranch = substruct('.','val', '{}',{88}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.values{4}(1).src_output = substruct('()',{1}); -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.values{5}(1) = cfg_dep; -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.values{5}(1).tname = 'Values Item'; -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.values{5}(1).tgt_spec = {}; -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.values{5}(1).sname = 'Files: Directory (cfg_files)'; -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.values{5}(1).src_exbranch = substruct('.','val', '{}',{89}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.values{5}(1).src_output = substruct('()',{1}); -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.num = [0 Inf]; -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.forcestruct = true; -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.check = []; -matlabbatch{90}.menu_cfg.menu_struct.conf_repeat.help = {'Assemble the inputs to the called function in their correct order.'}; -matlabbatch{91}.menu_cfg.menu_entry.conf_const.type = 'cfg_const'; -matlabbatch{91}.menu_cfg.menu_entry.conf_const.name = 'String'; -matlabbatch{91}.menu_cfg.menu_entry.conf_const.tag = 's'; -matlabbatch{91}.menu_cfg.menu_entry.conf_const.val = {true}; -matlabbatch{91}.menu_cfg.menu_entry.conf_const.check = []; -matlabbatch{91}.menu_cfg.menu_entry.conf_const.help = {}; -matlabbatch{91}.menu_cfg.menu_entry.conf_const.def = []; -matlabbatch{92}.menu_cfg.menu_entry.conf_const.type = 'cfg_const'; -matlabbatch{92}.menu_cfg.menu_entry.conf_const.name = 'Evaluated'; -matlabbatch{92}.menu_cfg.menu_entry.conf_const.tag = 'e'; -matlabbatch{92}.menu_cfg.menu_entry.conf_const.val = {true}; -matlabbatch{92}.menu_cfg.menu_entry.conf_const.check = []; -matlabbatch{92}.menu_cfg.menu_entry.conf_const.help = {}; -matlabbatch{92}.menu_cfg.menu_entry.conf_const.def = []; -matlabbatch{93}.menu_cfg.menu_entry.conf_const.type = 'cfg_const'; -matlabbatch{93}.menu_cfg.menu_entry.conf_const.name = 'Natural number'; -matlabbatch{93}.menu_cfg.menu_entry.conf_const.tag = 'n'; -matlabbatch{93}.menu_cfg.menu_entry.conf_const.val = {true}; -matlabbatch{93}.menu_cfg.menu_entry.conf_const.check = []; -matlabbatch{93}.menu_cfg.menu_entry.conf_const.help = {}; -matlabbatch{93}.menu_cfg.menu_entry.conf_const.def = []; -matlabbatch{94}.menu_cfg.menu_entry.conf_const.type = 'cfg_const'; -matlabbatch{94}.menu_cfg.menu_entry.conf_const.name = 'Whole number'; -matlabbatch{94}.menu_cfg.menu_entry.conf_const.tag = 'w'; -matlabbatch{94}.menu_cfg.menu_entry.conf_const.val = {true}; -matlabbatch{94}.menu_cfg.menu_entry.conf_const.check = []; -matlabbatch{94}.menu_cfg.menu_entry.conf_const.help = {}; -matlabbatch{94}.menu_cfg.menu_entry.conf_const.def = []; -matlabbatch{95}.menu_cfg.menu_entry.conf_const.type = 'cfg_const'; -matlabbatch{95}.menu_cfg.menu_entry.conf_const.name = 'Integer'; -matlabbatch{95}.menu_cfg.menu_entry.conf_const.tag = 'i'; -matlabbatch{95}.menu_cfg.menu_entry.conf_const.val = {true}; -matlabbatch{95}.menu_cfg.menu_entry.conf_const.check = []; -matlabbatch{95}.menu_cfg.menu_entry.conf_const.help = {}; -matlabbatch{95}.menu_cfg.menu_entry.conf_const.def = []; -matlabbatch{96}.menu_cfg.menu_entry.conf_const.type = 'cfg_const'; -matlabbatch{96}.menu_cfg.menu_entry.conf_const.name = 'Real number'; -matlabbatch{96}.menu_cfg.menu_entry.conf_const.tag = 'r'; -matlabbatch{96}.menu_cfg.menu_entry.conf_const.val = {true}; -matlabbatch{96}.menu_cfg.menu_entry.conf_const.check = []; -matlabbatch{96}.menu_cfg.menu_entry.conf_const.help = {}; -matlabbatch{96}.menu_cfg.menu_entry.conf_const.def = []; -matlabbatch{97}.menu_cfg.menu_entry.conf_const.type = 'cfg_const'; -matlabbatch{97}.menu_cfg.menu_entry.conf_const.name = 'Any file'; -matlabbatch{97}.menu_cfg.menu_entry.conf_const.tag = 'any'; -matlabbatch{97}.menu_cfg.menu_entry.conf_const.val = {true}; -matlabbatch{97}.menu_cfg.menu_entry.conf_const.check = []; -matlabbatch{97}.menu_cfg.menu_entry.conf_const.help = {}; -matlabbatch{97}.menu_cfg.menu_entry.conf_const.def = []; -matlabbatch{98}.menu_cfg.menu_entry.conf_const.type = 'cfg_const'; -matlabbatch{98}.menu_cfg.menu_entry.conf_const.name = 'Batch file'; -matlabbatch{98}.menu_cfg.menu_entry.conf_const.tag = 'batch'; -matlabbatch{98}.menu_cfg.menu_entry.conf_const.val = {true}; -matlabbatch{98}.menu_cfg.menu_entry.conf_const.check = []; -matlabbatch{98}.menu_cfg.menu_entry.conf_const.help = {}; -matlabbatch{98}.menu_cfg.menu_entry.conf_const.def = []; -matlabbatch{99}.menu_cfg.menu_entry.conf_const.type = 'cfg_const'; -matlabbatch{99}.menu_cfg.menu_entry.conf_const.name = 'Directory'; -matlabbatch{99}.menu_cfg.menu_entry.conf_const.tag = 'dir'; -matlabbatch{99}.menu_cfg.menu_entry.conf_const.val = {true}; -matlabbatch{99}.menu_cfg.menu_entry.conf_const.check = []; -matlabbatch{99}.menu_cfg.menu_entry.conf_const.help = {}; -matlabbatch{99}.menu_cfg.menu_entry.conf_const.def = []; -matlabbatch{100}.menu_cfg.menu_entry.conf_const.type = 'cfg_const'; -matlabbatch{100}.menu_cfg.menu_entry.conf_const.name = 'Image(s)'; -matlabbatch{100}.menu_cfg.menu_entry.conf_const.tag = 'image'; -matlabbatch{100}.menu_cfg.menu_entry.conf_const.val = {true}; -matlabbatch{100}.menu_cfg.menu_entry.conf_const.check = []; -matlabbatch{100}.menu_cfg.menu_entry.conf_const.help = {}; -matlabbatch{100}.menu_cfg.menu_entry.conf_const.def = []; -matlabbatch{101}.menu_cfg.menu_entry.conf_const.type = 'cfg_const'; -matlabbatch{101}.menu_cfg.menu_entry.conf_const.name = 'MATLAB .mat file'; -matlabbatch{101}.menu_cfg.menu_entry.conf_const.tag = 'mat'; -matlabbatch{101}.menu_cfg.menu_entry.conf_const.val = {true}; -matlabbatch{101}.menu_cfg.menu_entry.conf_const.check = []; -matlabbatch{101}.menu_cfg.menu_entry.conf_const.help = {}; -matlabbatch{101}.menu_cfg.menu_entry.conf_const.def = []; -matlabbatch{102}.menu_cfg.menu_entry.conf_const.type = 'cfg_const'; -matlabbatch{102}.menu_cfg.menu_entry.conf_const.name = 'Mesh file'; -matlabbatch{102}.menu_cfg.menu_entry.conf_const.tag = 'mesh'; -matlabbatch{102}.menu_cfg.menu_entry.conf_const.val = {true}; -matlabbatch{102}.menu_cfg.menu_entry.conf_const.check = []; -matlabbatch{102}.menu_cfg.menu_entry.conf_const.help = {}; -matlabbatch{102}.menu_cfg.menu_entry.conf_const.def = []; -matlabbatch{103}.menu_cfg.menu_entry.conf_const.type = 'cfg_const'; -matlabbatch{103}.menu_cfg.menu_entry.conf_const.name = 'NIfTI file'; -matlabbatch{103}.menu_cfg.menu_entry.conf_const.tag = 'nifti'; -matlabbatch{103}.menu_cfg.menu_entry.conf_const.val = {true}; -matlabbatch{103}.menu_cfg.menu_entry.conf_const.check = []; -matlabbatch{103}.menu_cfg.menu_entry.conf_const.help = {}; -matlabbatch{103}.menu_cfg.menu_entry.conf_const.def = []; -matlabbatch{104}.menu_cfg.menu_entry.conf_const.type = 'cfg_const'; -matlabbatch{104}.menu_cfg.menu_entry.conf_const.name = 'XML File'; -matlabbatch{104}.menu_cfg.menu_entry.conf_const.tag = 'xml'; -matlabbatch{104}.menu_cfg.menu_entry.conf_const.val = {true}; -matlabbatch{104}.menu_cfg.menu_entry.conf_const.check = []; -matlabbatch{104}.menu_cfg.menu_entry.conf_const.help = {}; -matlabbatch{104}.menu_cfg.menu_entry.conf_const.def = []; -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.type = 'cfg_choice'; -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.name = 'Type of output variable'; -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.tag = 'strtype'; -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{1}(1) = cfg_dep; -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{1}(1).tname = 'Values Item'; -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{1}(1).tgt_spec = {}; -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{1}(1).sname = 'Const: String (cfg_const)'; -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{1}(1).src_exbranch = substruct('.','val', '{}',{91}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{1}(1).src_output = substruct('()',{1}); -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{2}(1) = cfg_dep; -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{2}(1).tname = 'Values Item'; -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{2}(1).tgt_spec = {}; -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{2}(1).sname = 'Const: Evaluated (cfg_const)'; -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{2}(1).src_exbranch = substruct('.','val', '{}',{92}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{2}(1).src_output = substruct('()',{1}); -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{3}(1) = cfg_dep; -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{3}(1).tname = 'Values Item'; -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{3}(1).tgt_spec = {}; -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{3}(1).sname = 'Const: Natural number (cfg_const)'; -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{3}(1).src_exbranch = substruct('.','val', '{}',{93}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{3}(1).src_output = substruct('()',{1}); -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{4}(1) = cfg_dep; -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{4}(1).tname = 'Values Item'; -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{4}(1).tgt_spec = {}; -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{4}(1).sname = 'Const: Whole number (cfg_const)'; -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{4}(1).src_exbranch = substruct('.','val', '{}',{94}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{4}(1).src_output = substruct('()',{1}); -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{5}(1) = cfg_dep; -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{5}(1).tname = 'Values Item'; -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{5}(1).tgt_spec = {}; -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{5}(1).sname = 'Const: Integer (cfg_const)'; -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{5}(1).src_exbranch = substruct('.','val', '{}',{95}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{5}(1).src_output = substruct('()',{1}); -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{6}(1) = cfg_dep; -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{6}(1).tname = 'Values Item'; -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{6}(1).tgt_spec = {}; -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{6}(1).sname = 'Const: Real number (cfg_const)'; -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{6}(1).src_exbranch = substruct('.','val', '{}',{96}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.values{6}(1).src_output = substruct('()',{1}); -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.check = []; -matlabbatch{105}.menu_cfg.menu_struct.conf_choice.help = {}; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.type = 'cfg_choice'; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.name = 'Type of output file'; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.tag = 'filter'; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{1}(1) = cfg_dep; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{1}(1).tname = 'Values Item'; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{1}(1).tgt_spec = {}; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{1}(1).sname = 'Const: Any file (cfg_const)'; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{1}(1).src_exbranch = substruct('.','val', '{}',{97}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{1}(1).src_output = substruct('()',{1}); -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{2}(1) = cfg_dep; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{2}(1).tname = 'Values Item'; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{2}(1).tgt_spec = {}; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{2}(1).sname = 'Const: Batch file (cfg_const)'; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{2}(1).src_exbranch = substruct('.','val', '{}',{98}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{2}(1).src_output = substruct('()',{1}); -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{3}(1) = cfg_dep; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{3}(1).tname = 'Values Item'; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{3}(1).tgt_spec = {}; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{3}(1).sname = 'Const: Directory (cfg_const)'; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{3}(1).src_exbranch = substruct('.','val', '{}',{99}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{3}(1).src_output = substruct('()',{1}); -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{4}(1) = cfg_dep; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{4}(1).tname = 'Values Item'; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{4}(1).tgt_spec = {}; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{4}(1).sname = 'Const: Image(s) (cfg_const)'; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{4}(1).src_exbranch = substruct('.','val', '{}',{100}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{4}(1).src_output = substruct('()',{1}); -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{5}(1) = cfg_dep; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{5}(1).tname = 'Values Item'; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{5}(1).tgt_spec = {}; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{5}(1).sname = 'Const: MATLAB .mat file (cfg_const)'; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{5}(1).src_exbranch = substruct('.','val', '{}',{101}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{5}(1).src_output = substruct('()',{1}); -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{6}(1) = cfg_dep; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{6}(1).tname = 'Values Item'; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{6}(1).tgt_spec = {}; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{6}(1).sname = 'Const: Mesh file (cfg_const)'; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{6}(1).src_exbranch = substruct('.','val', '{}',{102}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{6}(1).src_output = substruct('()',{1}); -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{7}(1) = cfg_dep; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{7}(1).tname = 'Values Item'; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{7}(1).tgt_spec = {}; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{7}(1).sname = 'Const: NIfTI file (cfg_const)'; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{7}(1).src_exbranch = substruct('.','val', '{}',{103}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{7}(1).src_output = substruct('()',{1}); -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{8}(1) = cfg_dep; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{8}(1).tname = 'Values Item'; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{8}(1).tgt_spec = {}; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{8}(1).sname = 'Const: XML File (cfg_const)'; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{8}(1).src_exbranch = substruct('.','val', '{}',{104}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.values{8}(1).src_output = substruct('()',{1}); -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.check = []; -matlabbatch{106}.menu_cfg.menu_struct.conf_choice.help = {}; -matlabbatch{107}.menu_cfg.menu_struct.conf_repeat.type = 'cfg_repeat'; -matlabbatch{107}.menu_cfg.menu_struct.conf_repeat.name = 'Outputs'; -matlabbatch{107}.menu_cfg.menu_struct.conf_repeat.tag = 'outputs'; -matlabbatch{107}.menu_cfg.menu_struct.conf_repeat.values{1}(1) = cfg_dep; -matlabbatch{107}.menu_cfg.menu_struct.conf_repeat.values{1}(1).tname = 'Values Item'; -matlabbatch{107}.menu_cfg.menu_struct.conf_repeat.values{1}(1).tgt_spec = {}; -matlabbatch{107}.menu_cfg.menu_struct.conf_repeat.values{1}(1).sname = 'Choice: Type of output variable (cfg_choice)'; -matlabbatch{107}.menu_cfg.menu_struct.conf_repeat.values{1}(1).src_exbranch = substruct('.','val', '{}',{105}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{107}.menu_cfg.menu_struct.conf_repeat.values{1}(1).src_output = substruct('()',{1}); -matlabbatch{107}.menu_cfg.menu_struct.conf_repeat.values{2}(1) = cfg_dep; -matlabbatch{107}.menu_cfg.menu_struct.conf_repeat.values{2}(1).tname = 'Values Item'; -matlabbatch{107}.menu_cfg.menu_struct.conf_repeat.values{2}(1).tgt_spec = {}; -matlabbatch{107}.menu_cfg.menu_struct.conf_repeat.values{2}(1).sname = 'Choice: Type of output file (cfg_choice)'; -matlabbatch{107}.menu_cfg.menu_struct.conf_repeat.values{2}(1).src_exbranch = substruct('.','val', '{}',{106}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{107}.menu_cfg.menu_struct.conf_repeat.values{2}(1).src_output = substruct('()',{1}); -matlabbatch{107}.menu_cfg.menu_struct.conf_repeat.num = [0 Inf]; -matlabbatch{107}.menu_cfg.menu_struct.conf_repeat.forcestruct = true; -matlabbatch{107}.menu_cfg.menu_struct.conf_repeat.check = []; -matlabbatch{107}.menu_cfg.menu_struct.conf_repeat.help = {}; -matlabbatch{108}.menu_cfg.menu_entry.conf_entry.type = 'cfg_entry'; -matlabbatch{108}.menu_cfg.menu_entry.conf_entry.name = 'Function to be called'; -matlabbatch{108}.menu_cfg.menu_entry.conf_entry.tag = 'fun'; -matlabbatch{108}.menu_cfg.menu_entry.conf_entry.strtype = 'f'; -matlabbatch{108}.menu_cfg.menu_entry.conf_entry.extras = []; -matlabbatch{108}.menu_cfg.menu_entry.conf_entry.num = [1 1]; -matlabbatch{108}.menu_cfg.menu_entry.conf_entry.check = []; -matlabbatch{108}.menu_cfg.menu_entry.conf_entry.help = {}; -matlabbatch{108}.menu_cfg.menu_entry.conf_entry.def = []; -matlabbatch{109}.menu_cfg.menu_struct.conf_exbranch.type = 'cfg_exbranch'; -matlabbatch{109}.menu_cfg.menu_struct.conf_exbranch.name = 'Call MATLAB function'; -matlabbatch{109}.menu_cfg.menu_struct.conf_exbranch.tag = 'call_matlab'; -matlabbatch{109}.menu_cfg.menu_struct.conf_exbranch.val{1}(1) = cfg_dep; -matlabbatch{109}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tname = 'Val Item'; -matlabbatch{109}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tgt_spec = {}; -matlabbatch{109}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).sname = 'Repeat: Inputs (cfg_repeat)'; -matlabbatch{109}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_exbranch = substruct('.','val', '{}',{90}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{109}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_output = substruct('()',{1}); -matlabbatch{109}.menu_cfg.menu_struct.conf_exbranch.val{2}(1) = cfg_dep; -matlabbatch{109}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tname = 'Val Item'; -matlabbatch{109}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tgt_spec = {}; -matlabbatch{109}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).sname = 'Repeat: Outputs (cfg_repeat)'; -matlabbatch{109}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_exbranch = substruct('.','val', '{}',{107}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{109}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_output = substruct('()',{1}); -matlabbatch{109}.menu_cfg.menu_struct.conf_exbranch.val{3}(1) = cfg_dep; -matlabbatch{109}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).tname = 'Val Item'; -matlabbatch{109}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).tgt_spec = {}; -matlabbatch{109}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).sname = 'Entry: Function to be called (cfg_entry)'; -matlabbatch{109}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).src_exbranch = substruct('.','val', '{}',{108}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{109}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).src_output = substruct('()',{1}); -matlabbatch{109}.menu_cfg.menu_struct.conf_exbranch.prog = @(job)cfg_run_call_matlab('run',job); -matlabbatch{109}.menu_cfg.menu_struct.conf_exbranch.vout = @(job)cfg_run_call_matlab('vout',job); -matlabbatch{109}.menu_cfg.menu_struct.conf_exbranch.check = []; -matlabbatch{109}.menu_cfg.menu_struct.conf_exbranch.help = {}; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.type = 'cfg_choice'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.name = 'BasicIO'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.tag = 'cfg_basicio'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{1}(1) = cfg_dep; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{1}(1).tname = 'Values Item'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{1}(1).tgt_spec = {}; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{1}(1).sname = 'Exbranch: Move/Delete Files (cfg_exbranch)'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{1}(1).src_exbranch = substruct('.','val', '{}',{13}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{1}(1).src_output = substruct('()',{1}); -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{2}(1) = cfg_dep; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{2}(1).tname = 'Values Item'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{2}(1).tgt_spec = {}; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{2}(1).sname = 'Exbranch: Change Directory (cfg_exbranch)'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{2}(1).src_exbranch = substruct('.','val', '{}',{15}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{2}(1).src_output = substruct('()',{1}); -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{3}(1) = cfg_dep; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{3}(1).tname = 'Values Item'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{3}(1).tgt_spec = {}; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{3}(1).sname = 'Exbranch: Make Directory (cfg_exbranch)'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{3}(1).src_exbranch = substruct('.','val', '{}',{18}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{3}(1).src_output = substruct('()',{1}); -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{4}(1) = cfg_dep; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{4}(1).tname = 'Values Item'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{4}(1).tgt_spec = {}; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{4}(1).sname = 'Exbranch: Named Directory Selector (cfg_exbranch)'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{4}(1).src_exbranch = substruct('.','val', '{}',{22}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{4}(1).src_output = substruct('()',{1}); -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{5}(1) = cfg_dep; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{5}(1).tname = 'Values Item'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{5}(1).tgt_spec = {}; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{5}(1).sname = 'Exbranch: Named File Selector (cfg_exbranch)'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{5}(1).src_exbranch = substruct('.','val', '{}',{26}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{5}(1).src_output = substruct('()',{1}); -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{6}(1) = cfg_dep; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{6}(1).tname = 'Values Item'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{6}(1).tgt_spec = {}; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{6}(1).sname = 'Exbranch: File Selector (Batch Mode) (cfg_exbranch)'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{6}(1).src_exbranch = substruct('.','val', '{}',{30}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{6}(1).src_output = substruct('()',{1}); -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{7}(1) = cfg_dep; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{7}(1).tname = 'Values Item'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{7}(1).tgt_spec = {}; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{7}(1).sname = 'Exbranch: File Filter (cfg_exbranch)'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{7}(1).src_exbranch = substruct('.','val', '{}',{35}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{7}(1).src_output = substruct('()',{1}); -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{8}(1) = cfg_dep; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{8}(1).tname = 'Values Item'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{8}(1).tgt_spec = {}; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{8}(1).sname = 'Exbranch: File Set Split (cfg_exbranch)'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{8}(1).src_exbranch = substruct('.','val', '{}',{40}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{8}(1).src_output = substruct('()',{1}); -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{9}(1) = cfg_dep; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{9}(1).tname = 'Values Item'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{9}(1).tgt_spec = {}; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{9}(1).sname = 'Exbranch: Named Input (cfg_exbranch)'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{9}(1).src_exbranch = substruct('.','val', '{}',{43}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{9}(1).src_output = substruct('()',{1}); -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{10}(1) = cfg_dep; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{10}(1).tname = 'Values Item'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{10}(1).tgt_spec = {}; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{10}(1).sname = 'Exbranch: Load Variables from .mat File (cfg_exbranch)'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{10}(1).src_exbranch = substruct('.','val', '{}',{49}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{10}(1).src_output = substruct('()',{1}); -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{11}(1) = cfg_dep; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{11}(1).tname = 'Values Item'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{11}(1).tgt_spec = {}; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{11}(1).sname = 'Exbranch: Save Variables (cfg_exbranch)'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{11}(1).src_exbranch = substruct('.','val', '{}',{57}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{11}(1).src_output = substruct('()',{1}); -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{12}(1) = cfg_dep; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{12}(1).tname = 'Values Item'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{12}(1).tgt_spec = {}; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{12}(1).sname = 'Exbranch: Access part of MATLAB variable (cfg_exbranch)'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{12}(1).src_exbranch = substruct('.','val', '{}',{65}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{12}(1).src_output = substruct('()',{1}); -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{13}(1) = cfg_dep; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{13}(1).tname = 'Values Item'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{13}(1).tgt_spec = {}; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{13}(1).sname = 'Exbranch: Pass Output to Workspace (cfg_exbranch)'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{13}(1).src_exbranch = substruct('.','val', '{}',{68}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{13}(1).src_output = substruct('()',{1}); -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{14}(1) = cfg_dep; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{14}(1).tname = 'Values Item'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{14}(1).tgt_spec = {}; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{14}(1).sname = 'Exbranch: Run Batch Jobs (cfg_exbranch)'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{14}(1).src_exbranch = substruct('.','val', '{}',{84}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{14}(1).src_output = substruct('()',{1}); -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{15}(1) = cfg_dep; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{15}(1).tname = 'Values Item'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{15}(1).tgt_spec = {}; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{15}(1).sname = 'Exbranch: Call MATLAB function (cfg_exbranch)'; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{15}(1).src_exbranch = substruct('.','val', '{}',{109}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.values{15}(1).src_output = substruct('()',{1}); -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.check = []; -matlabbatch{110}.menu_cfg.menu_struct.conf_choice.help = {'This toolbox contains basic input and output functions. The "Named Input" functions can be used to enter values or file names. These inputs can then be passed on to multiple modules, thereby ensuring all of them use the same input value. Some basic file manipulation is implemented in "Change Directory", "Make Directory", "Move Files". Lists of files can be filtered or splitted into parts using "File Set Filter" and "File Set Split". Output values from other modules can be written out to disk or assigned to MATLAB workspace.'}; -matlabbatch{111}.menu_cfg.gencode_gen.gencode_fname = 'cfg_cfg_basicio.m'; -matlabbatch{111}.menu_cfg.gencode_gen.gencode_dir = {'/export/spm-devel/matlabbatch/trunk/cfg_basicio/'}; -matlabbatch{111}.menu_cfg.gencode_gen.gencode_var(1) = cfg_dep; -matlabbatch{111}.menu_cfg.gencode_gen.gencode_var(1).tname = 'Root node of config'; -matlabbatch{111}.menu_cfg.gencode_gen.gencode_var(1).tgt_spec = {}; -matlabbatch{111}.menu_cfg.gencode_gen.gencode_var(1).sname = 'Choice: BasicIO (cfg_choice)'; -matlabbatch{111}.menu_cfg.gencode_gen.gencode_var(1).src_exbranch = substruct('.','val', '{}',{110}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{111}.menu_cfg.gencode_gen.gencode_var(1).src_output = substruct('()',{1}); -matlabbatch{111}.menu_cfg.gencode_gen.gencode_opts.gencode_o_def = true; -matlabbatch{111}.menu_cfg.gencode_gen.gencode_opts.gencode_o_mlb = false; -matlabbatch{111}.menu_cfg.gencode_gen.gencode_opts.gencode_o_path = false; diff --git a/matlabbatch/cfg_basicio/src/batch_basicio_06_file_fplist.m b/matlabbatch/cfg_basicio/src/batch_basicio_06_file_fplist.m index 375826a..87f5c1b 100644 --- a/matlabbatch/cfg_basicio/src/batch_basicio_06_file_fplist.m +++ b/matlabbatch/cfg_basicio/src/batch_basicio_06_file_fplist.m @@ -1,5 +1,5 @@ %----------------------------------------------------------------------- -% Job configuration created by cfg_util (rev $Rev: 3434 $) +% Job configuration created by cfg_util (rev $Rev: 3686 $) %----------------------------------------------------------------------- matlabbatch{1}.menu_cfg.menu_entry.conf_files.type = 'cfg_files'; matlabbatch{1}.menu_cfg.menu_entry.conf_files.name = 'Directory'; @@ -25,11 +25,11 @@ matlabbatch{3}.menu_cfg.menu_entry.conf_menu.tag = 'rec'; matlabbatch{3}.menu_cfg.menu_entry.conf_menu.labels = { 'Yes' - 'Yes' + 'No' }'; matlabbatch{3}.menu_cfg.menu_entry.conf_menu.values = { - true - false + 'FPListRec' + 'FPList' }'; matlabbatch{3}.menu_cfg.menu_entry.conf_menu.check = []; matlabbatch{3}.menu_cfg.menu_entry.conf_menu.help = {'Files can be selected from the specified directory only or from the specified directory and all its subdirectories.'}; diff --git a/matlabbatch/cfg_basicio/src/batch_basicio_12_subsrefvar.m b/matlabbatch/cfg_basicio/src/batch_basicio_12_subsrefvar.m index f52b01a..a613d0d 100644 --- a/matlabbatch/cfg_basicio/src/batch_basicio_12_subsrefvar.m +++ b/matlabbatch/cfg_basicio/src/batch_basicio_12_subsrefvar.m @@ -1,12 +1,12 @@ %----------------------------------------------------------------------- -% Job configuration created by cfg_util (rev $Rev: 3591 $) +% Job configuration created by cfg_util (rev $Rev: 3921 $) %----------------------------------------------------------------------- matlabbatch{1}.menu_cfg.menu_entry.conf_entry.type = 'cfg_entry'; matlabbatch{1}.menu_cfg.menu_entry.conf_entry.name = 'Input variable'; matlabbatch{1}.menu_cfg.menu_entry.conf_entry.tag = 'input'; matlabbatch{1}.menu_cfg.menu_entry.conf_entry.strtype = 'e'; matlabbatch{1}.menu_cfg.menu_entry.conf_entry.extras = []; -matlabbatch{1}.menu_cfg.menu_entry.conf_entry.num = [1 1]; +matlabbatch{1}.menu_cfg.menu_entry.conf_entry.num = [inf inf]; matlabbatch{1}.menu_cfg.menu_entry.conf_entry.check = []; matlabbatch{1}.menu_cfg.menu_entry.conf_entry.help = {'Enter the input variable.'}; matlabbatch{1}.menu_cfg.menu_entry.conf_entry.def = []; @@ -91,22 +91,187 @@ 'Enter the sequence of subscript references. The leftmost reference is on the top of the list, the rightmost at the bottom.' 'To reference e.g. the field ''xY'' in a SPM variable, enter ''xY'' as ''Field reference''. To reference SPM.xY(1), enter ''xY'' as field reference, followed by 1 as an ''Array reference''.' }'; -matlabbatch{8}.menu_cfg.menu_struct.conf_exbranch.type = 'cfg_exbranch'; -matlabbatch{8}.menu_cfg.menu_struct.conf_exbranch.name = 'Access part of MATLAB variable'; -matlabbatch{8}.menu_cfg.menu_struct.conf_exbranch.tag = 'subsrefvar'; -matlabbatch{8}.menu_cfg.menu_struct.conf_exbranch.val{1}(1) = cfg_dep; -matlabbatch{8}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tname = 'Val Item'; -matlabbatch{8}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tgt_spec = {}; -matlabbatch{8}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).sname = 'Entry: Input variable (cfg_entry)'; -matlabbatch{8}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_exbranch = substruct('.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{8}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_output = substruct('()',{1}); -matlabbatch{8}.menu_cfg.menu_struct.conf_exbranch.val{2}(1) = cfg_dep; -matlabbatch{8}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tname = 'Val Item'; -matlabbatch{8}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tgt_spec = {}; -matlabbatch{8}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).sname = 'Repeat: Part of variable to access (cfg_repeat)'; -matlabbatch{8}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_exbranch = substruct('.','val', '{}',{7}, '.','val', '{}',{1}, '.','val', '{}',{1}); -matlabbatch{8}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_output = substruct('()',{1}); -matlabbatch{8}.menu_cfg.menu_struct.conf_exbranch.prog = @(job)cfg_run_subsrefvar('run',job); -matlabbatch{8}.menu_cfg.menu_struct.conf_exbranch.vout = @(job)cfg_run_subsrefvar('vout',job); -matlabbatch{8}.menu_cfg.menu_struct.conf_exbranch.check = []; -matlabbatch{8}.menu_cfg.menu_struct.conf_exbranch.help = {}; +matlabbatch{8}.menu_cfg.menu_entry.conf_const.type = 'cfg_const'; +matlabbatch{8}.menu_cfg.menu_entry.conf_const.name = 'String'; +matlabbatch{8}.menu_cfg.menu_entry.conf_const.tag = 's'; +matlabbatch{8}.menu_cfg.menu_entry.conf_const.val{1}{1}.name = 'strtype'; +matlabbatch{8}.menu_cfg.menu_entry.conf_const.val{1}{1}.value = 's'; +matlabbatch{8}.menu_cfg.menu_entry.conf_const.check = []; +matlabbatch{8}.menu_cfg.menu_entry.conf_const.help = {}; +matlabbatch{8}.menu_cfg.menu_entry.conf_const.def = []; +matlabbatch{9}.menu_cfg.menu_entry.conf_const.type = 'cfg_const'; +matlabbatch{9}.menu_cfg.menu_entry.conf_const.name = 'Natural Number'; +matlabbatch{9}.menu_cfg.menu_entry.conf_const.tag = 'n'; +matlabbatch{9}.menu_cfg.menu_entry.conf_const.val{1}{1}.name = 'strtype'; +matlabbatch{9}.menu_cfg.menu_entry.conf_const.val{1}{1}.value = 'n'; +matlabbatch{9}.menu_cfg.menu_entry.conf_const.check = []; +matlabbatch{9}.menu_cfg.menu_entry.conf_const.help = {}; +matlabbatch{9}.menu_cfg.menu_entry.conf_const.def = []; +matlabbatch{10}.menu_cfg.menu_entry.conf_const.type = 'cfg_const'; +matlabbatch{10}.menu_cfg.menu_entry.conf_const.name = 'Whole Number'; +matlabbatch{10}.menu_cfg.menu_entry.conf_const.tag = 'w'; +matlabbatch{10}.menu_cfg.menu_entry.conf_const.val{1}{1}.name = 'strtype'; +matlabbatch{10}.menu_cfg.menu_entry.conf_const.val{1}{1}.value = 'w'; +matlabbatch{10}.menu_cfg.menu_entry.conf_const.check = []; +matlabbatch{10}.menu_cfg.menu_entry.conf_const.help = {}; +matlabbatch{10}.menu_cfg.menu_entry.conf_const.def = []; +matlabbatch{11}.menu_cfg.menu_entry.conf_const.type = 'cfg_const'; +matlabbatch{11}.menu_cfg.menu_entry.conf_const.name = 'Integer'; +matlabbatch{11}.menu_cfg.menu_entry.conf_const.tag = 'i'; +matlabbatch{11}.menu_cfg.menu_entry.conf_const.val{1}{1}.name = 'strtype'; +matlabbatch{11}.menu_cfg.menu_entry.conf_const.val{1}{1}.value = 'i'; +matlabbatch{11}.menu_cfg.menu_entry.conf_const.check = []; +matlabbatch{11}.menu_cfg.menu_entry.conf_const.help = {}; +matlabbatch{11}.menu_cfg.menu_entry.conf_const.def = []; +matlabbatch{12}.menu_cfg.menu_entry.conf_const.type = 'cfg_const'; +matlabbatch{12}.menu_cfg.menu_entry.conf_const.name = 'Real Number'; +matlabbatch{12}.menu_cfg.menu_entry.conf_const.tag = 'r'; +matlabbatch{12}.menu_cfg.menu_entry.conf_const.val{1}{1}.name = 'strtype'; +matlabbatch{12}.menu_cfg.menu_entry.conf_const.val{1}{1}.value = 'r'; +matlabbatch{12}.menu_cfg.menu_entry.conf_const.check = []; +matlabbatch{12}.menu_cfg.menu_entry.conf_const.help = {}; +matlabbatch{12}.menu_cfg.menu_entry.conf_const.def = []; +matlabbatch{13}.menu_cfg.menu_entry.conf_const.type = 'cfg_const'; +matlabbatch{13}.menu_cfg.menu_entry.conf_const.name = 'Function Handle'; +matlabbatch{13}.menu_cfg.menu_entry.conf_const.tag = 'f'; +matlabbatch{13}.menu_cfg.menu_entry.conf_const.val{1}{1}.name = 'strtype'; +matlabbatch{13}.menu_cfg.menu_entry.conf_const.val{1}{1}.value = 'f'; +matlabbatch{13}.menu_cfg.menu_entry.conf_const.check = []; +matlabbatch{13}.menu_cfg.menu_entry.conf_const.help = {}; +matlabbatch{13}.menu_cfg.menu_entry.conf_const.def = []; +matlabbatch{14}.menu_cfg.menu_entry.conf_const.type = 'cfg_const'; +matlabbatch{14}.menu_cfg.menu_entry.conf_const.name = 'Other Variable'; +matlabbatch{14}.menu_cfg.menu_entry.conf_const.tag = 'e'; +matlabbatch{14}.menu_cfg.menu_entry.conf_const.val{1}{1}.name = 'strtype'; +matlabbatch{14}.menu_cfg.menu_entry.conf_const.val{1}{1}.value = 'e'; +matlabbatch{14}.menu_cfg.menu_entry.conf_const.check = []; +matlabbatch{14}.menu_cfg.menu_entry.conf_const.help = {}; +matlabbatch{14}.menu_cfg.menu_entry.conf_const.def = []; +matlabbatch{15}.menu_cfg.menu_entry.conf_const.type = 'cfg_const'; +matlabbatch{15}.menu_cfg.menu_entry.conf_const.name = 'NIfTI Image File(s)'; +matlabbatch{15}.menu_cfg.menu_entry.conf_const.tag = 'nifti'; +matlabbatch{15}.menu_cfg.menu_entry.conf_const.val{1}{1}.name = 'filter'; +matlabbatch{15}.menu_cfg.menu_entry.conf_const.val{1}{1}.value = 'image'; +matlabbatch{15}.menu_cfg.menu_entry.conf_const.check = []; +matlabbatch{15}.menu_cfg.menu_entry.conf_const.help = {}; +matlabbatch{15}.menu_cfg.menu_entry.conf_const.def = []; +matlabbatch{16}.menu_cfg.menu_entry.conf_const.type = 'cfg_const'; +matlabbatch{16}.menu_cfg.menu_entry.conf_const.name = '.mat File(s)'; +matlabbatch{16}.menu_cfg.menu_entry.conf_const.tag = 'mat'; +matlabbatch{16}.menu_cfg.menu_entry.conf_const.val{1}{1}.name = 'filter'; +matlabbatch{16}.menu_cfg.menu_entry.conf_const.val{1}{1}.value = 'mat'; +matlabbatch{16}.menu_cfg.menu_entry.conf_const.check = []; +matlabbatch{16}.menu_cfg.menu_entry.conf_const.help = {}; +matlabbatch{16}.menu_cfg.menu_entry.conf_const.def = []; +matlabbatch{17}.menu_cfg.menu_entry.conf_const.type = 'cfg_const'; +matlabbatch{17}.menu_cfg.menu_entry.conf_const.name = 'Any File(s)'; +matlabbatch{17}.menu_cfg.menu_entry.conf_const.tag = 'any'; +matlabbatch{17}.menu_cfg.menu_entry.conf_const.val{1}{1}.name = 'filter'; +matlabbatch{17}.menu_cfg.menu_entry.conf_const.val{1}{1}.value = 'any'; +matlabbatch{17}.menu_cfg.menu_entry.conf_const.check = []; +matlabbatch{17}.menu_cfg.menu_entry.conf_const.help = {}; +matlabbatch{17}.menu_cfg.menu_entry.conf_const.def = []; +matlabbatch{18}.menu_cfg.menu_entry.conf_const.type = 'cfg_const'; +matlabbatch{18}.menu_cfg.menu_entry.conf_const.name = 'Directories'; +matlabbatch{18}.menu_cfg.menu_entry.conf_const.tag = 'dir'; +matlabbatch{18}.menu_cfg.menu_entry.conf_const.val{1}{1}.name = 'filter'; +matlabbatch{18}.menu_cfg.menu_entry.conf_const.val{1}{1}.value = 'dir'; +matlabbatch{18}.menu_cfg.menu_entry.conf_const.check = []; +matlabbatch{18}.menu_cfg.menu_entry.conf_const.help = {}; +matlabbatch{18}.menu_cfg.menu_entry.conf_const.def = []; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.type = 'cfg_choice'; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.name = 'Type of referenced Variable'; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.tag = 'tgt_spec'; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{1}(1) = cfg_dep; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{1}(1).tname = 'Values Item'; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{1}(1).tgt_spec = {}; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{1}(1).sname = 'Const: String (cfg_const)'; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{1}(1).src_exbranch = substruct('.','val', '{}',{8}, '.','val', '{}',{1}, '.','val', '{}',{1}); +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{1}(1).src_output = substruct('()',{1}); +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{2}(1) = cfg_dep; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{2}(1).tname = 'Values Item'; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{2}(1).tgt_spec = {}; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{2}(1).sname = 'Const: Natural Number (cfg_const)'; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{2}(1).src_exbranch = substruct('.','val', '{}',{9}, '.','val', '{}',{1}, '.','val', '{}',{1}); +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{2}(1).src_output = substruct('()',{1}); +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{3}(1) = cfg_dep; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{3}(1).tname = 'Values Item'; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{3}(1).tgt_spec = {}; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{3}(1).sname = 'Const: Whole Number (cfg_const)'; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{3}(1).src_exbranch = substruct('.','val', '{}',{10}, '.','val', '{}',{1}, '.','val', '{}',{1}); +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{3}(1).src_output = substruct('()',{1}); +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{4}(1) = cfg_dep; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{4}(1).tname = 'Values Item'; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{4}(1).tgt_spec = {}; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{4}(1).sname = 'Const: Integer (cfg_const)'; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{4}(1).src_exbranch = substruct('.','val', '{}',{11}, '.','val', '{}',{1}, '.','val', '{}',{1}); +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{4}(1).src_output = substruct('()',{1}); +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{5}(1) = cfg_dep; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{5}(1).tname = 'Values Item'; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{5}(1).tgt_spec = {}; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{5}(1).sname = 'Const: Real Number (cfg_const)'; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{5}(1).src_exbranch = substruct('.','val', '{}',{12}, '.','val', '{}',{1}, '.','val', '{}',{1}); +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{5}(1).src_output = substruct('()',{1}); +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{6}(1) = cfg_dep; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{6}(1).tname = 'Values Item'; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{6}(1).tgt_spec = {}; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{6}(1).sname = 'Const: Function Handle (cfg_const)'; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{6}(1).src_exbranch = substruct('.','val', '{}',{13}, '.','val', '{}',{1}, '.','val', '{}',{1}); +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{6}(1).src_output = substruct('()',{1}); +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{7}(1) = cfg_dep; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{7}(1).tname = 'Values Item'; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{7}(1).tgt_spec = {}; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{7}(1).sname = 'Const: Other Variable (cfg_const)'; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{7}(1).src_exbranch = substruct('.','val', '{}',{14}, '.','val', '{}',{1}, '.','val', '{}',{1}); +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{7}(1).src_output = substruct('()',{1}); +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{8}(1) = cfg_dep; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{8}(1).tname = 'Values Item'; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{8}(1).tgt_spec = {}; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{8}(1).sname = 'Const: NIfTI Image File(s) (cfg_const)'; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{8}(1).src_exbranch = substruct('.','val', '{}',{15}, '.','val', '{}',{1}, '.','val', '{}',{1}); +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{8}(1).src_output = substruct('()',{1}); +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{9}(1) = cfg_dep; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{9}(1).tname = 'Values Item'; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{9}(1).tgt_spec = {}; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{9}(1).sname = 'Const: .mat File(s) (cfg_const)'; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{9}(1).src_exbranch = substruct('.','val', '{}',{16}, '.','val', '{}',{1}, '.','val', '{}',{1}); +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{9}(1).src_output = substruct('()',{1}); +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{10}(1) = cfg_dep; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{10}(1).tname = 'Values Item'; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{10}(1).tgt_spec = {}; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{10}(1).sname = 'Const: Any File(s) (cfg_const)'; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{10}(1).src_exbranch = substruct('.','val', '{}',{17}, '.','val', '{}',{1}, '.','val', '{}',{1}); +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{10}(1).src_output = substruct('()',{1}); +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{11}(1) = cfg_dep; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{11}(1).tname = 'Values Item'; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{11}(1).tgt_spec = {}; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{11}(1).sname = 'Const: Directories (cfg_const)'; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{11}(1).src_exbranch = substruct('.','val', '{}',{18}, '.','val', '{}',{1}, '.','val', '{}',{1}); +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.values{11}(1).src_output = substruct('()',{1}); +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.check = []; +matlabbatch{19}.menu_cfg.menu_struct.conf_choice.help = {'This setting determines where the contents of the variable will be available as a dependency.'}; +matlabbatch{20}.menu_cfg.menu_struct.conf_exbranch.type = 'cfg_exbranch'; +matlabbatch{20}.menu_cfg.menu_struct.conf_exbranch.name = 'Access part of MATLAB variable'; +matlabbatch{20}.menu_cfg.menu_struct.conf_exbranch.tag = 'subsrefvar'; +matlabbatch{20}.menu_cfg.menu_struct.conf_exbranch.val{1}(1) = cfg_dep; +matlabbatch{20}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tname = 'Val Item'; +matlabbatch{20}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).tgt_spec = {}; +matlabbatch{20}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).sname = 'Entry: Input variable (cfg_entry)'; +matlabbatch{20}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_exbranch = substruct('.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}); +matlabbatch{20}.menu_cfg.menu_struct.conf_exbranch.val{1}(1).src_output = substruct('()',{1}); +matlabbatch{20}.menu_cfg.menu_struct.conf_exbranch.val{2}(1) = cfg_dep; +matlabbatch{20}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tname = 'Val Item'; +matlabbatch{20}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).tgt_spec = {}; +matlabbatch{20}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).sname = 'Repeat: Part of variable to access (cfg_repeat)'; +matlabbatch{20}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_exbranch = substruct('.','val', '{}',{7}, '.','val', '{}',{1}, '.','val', '{}',{1}); +matlabbatch{20}.menu_cfg.menu_struct.conf_exbranch.val{2}(1).src_output = substruct('()',{1}); +matlabbatch{20}.menu_cfg.menu_struct.conf_exbranch.val{3}(1) = cfg_dep; +matlabbatch{20}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).tname = 'Val Item'; +matlabbatch{20}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).tgt_spec = {}; +matlabbatch{20}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).sname = 'Choice: Type of referenced Variable (cfg_choice)'; +matlabbatch{20}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).src_exbranch = substruct('.','val', '{}',{19}, '.','val', '{}',{1}, '.','val', '{}',{1}); +matlabbatch{20}.menu_cfg.menu_struct.conf_exbranch.val{3}(1).src_output = substruct('()',{1}); +matlabbatch{20}.menu_cfg.menu_struct.conf_exbranch.prog = @(job)cfg_run_subsrefvar('run',job); +matlabbatch{20}.menu_cfg.menu_struct.conf_exbranch.vout = @(job)cfg_run_subsrefvar('vout',job); +matlabbatch{20}.menu_cfg.menu_struct.conf_exbranch.check = []; +matlabbatch{20}.menu_cfg.menu_struct.conf_exbranch.help = {}; diff --git a/matlabbatch/cfg_basicio/src/batch_basicio_toplevel.m b/matlabbatch/cfg_basicio/src/batch_basicio_toplevel.m index ccb7fdc..59a141b 100644 --- a/matlabbatch/cfg_basicio/src/batch_basicio_toplevel.m +++ b/matlabbatch/cfg_basicio/src/batch_basicio_toplevel.m @@ -1,5 +1,5 @@ %----------------------------------------------------------------------- -% Job configuration created by cfg_util (rev $Rev: 3591 $) +% Job configuration created by cfg_util (rev $Rev: 3921 $) %----------------------------------------------------------------------- matlabbatch{1}.menu_cfg.menu_struct.conf_choice.type = 'cfg_choice'; matlabbatch{1}.menu_cfg.menu_struct.conf_choice.name = 'BasicIO'; @@ -26,7 +26,7 @@ matlabbatch{1}.menu_cfg.menu_struct.conf_choice.check = []; matlabbatch{1}.menu_cfg.menu_struct.conf_choice.help = {'This toolbox contains basic input and output functions. The "Named Input" functions can be used to enter values or file names. These inputs can then be passed on to multiple modules, thereby ensuring all of them use the same input value. Some basic file manipulation is implemented in "Change Directory", "Make Directory", "Move Files". Lists of files can be filtered or splitted into parts using "File Set Filter" and "File Set Split". Output values from other modules can be written out to disk or assigned to MATLAB workspace.'}; matlabbatch{2}.menu_cfg.gencode_gen.gencode_fname = 'cfg_cfg_basicio.m'; -matlabbatch{2}.menu_cfg.gencode_gen.gencode_dir = {'/export/spm-devel/matlabbatch/trunk/cfg_basicio/'}; +matlabbatch{2}.menu_cfg.gencode_gen.gencode_dir = ''; matlabbatch{2}.menu_cfg.gencode_gen.gencode_var(1) = cfg_dep; matlabbatch{2}.menu_cfg.gencode_gen.gencode_var(1).tname = 'Root node of config'; matlabbatch{2}.menu_cfg.gencode_gen.gencode_var(1).tgt_spec = {}; diff --git a/matlabbatch/cfg_basicio/src/create_cfg_cfg_basicio.m b/matlabbatch/cfg_basicio/src/create_cfg_cfg_basicio.m new file mode 100644 index 0000000..6bd7da6 --- /dev/null +++ b/matlabbatch/cfg_basicio/src/create_cfg_cfg_basicio.m @@ -0,0 +1,24 @@ +%% List of modules +% Each module batch is assumed to contain exactly one cfg_exbranch, and +% this should be the last output of the batch +cfg_dir = '/data/projects/spm-devel/matlabbatch/branches/mlb_1/cfg_basicio'; +modules = cfg_getfile('fplist', fullfile(cfg_dir,'src'),'^batch_basicio_[0-9]*_.*\.m$'); +%% Top level batch +% This batch needs to be modified if the number of modules changes - the +% top level repeat will have to contain the correct number of value +% entries. +toplevel = fullfile(cfg_dir,'src','batch_basicio_toplevel.m'); +%% Get modules +exbranches = cell(size(modules)); +for cm = 1:numel(modules) + id = cfg_util('initjob',modules{cm}); + cfg_util('run',id); + o = cfg_util('getalloutputs',id); + exbranches{cm} = o{end}; + cfg_util('deljob',id); +end +%% Assemble top level +id = cfg_util('initjob',toplevel); +cfg_util('filljob',id,exbranches{:},{cfg_dir}); +cfg_util('run',id); +cfg_util('deljob',id); \ No newline at end of file diff --git a/matlabbatch/cfg_confgui/cfg_confgui.m b/matlabbatch/cfg_confgui/cfg_confgui.m index 3b9750a..2e3e513 100644 --- a/matlabbatch/cfg_confgui/cfg_confgui.m +++ b/matlabbatch/cfg_confgui/cfg_confgui.m @@ -12,9 +12,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: cfg_confgui.m 3567 2009-11-13 14:55:48Z volkmar $ +% $Id: cfg_confgui.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 3567 $'; %#ok +rev = '$Rev: 3944 $'; %#ok %% Declaration of fields @@ -584,7 +584,7 @@ end % Generate code [str tag] = gencode(out.c0,'',{}); -[p n e v] = fileparts(varargin{1}.gencode_fname); %#ok +[p n e] = fileparts(varargin{1}.gencode_fname); out.cfg_file{1} = fullfile(varargin{1}.gencode_dir{1}, [n '.m']); fid = fopen(out.cfg_file{1}, 'wt'); fprintf(fid, 'function %s = %s\n', tag, n); @@ -639,11 +639,13 @@ '%% Created at %s.\n\n'], ... out.c0.name, out.c0.name, n, datestr(now, 31)); - fprintf(fid, '%% Get path to this file and add it to MATLAB path.\n'); - fprintf(fid, ['%% If the configuration file is stored in another place, the ' ... + fprintf(fid, 'if ~isdeployed\n'); + fprintf(fid, ' %% Get path to this file and add it to MATLAB path.\n'); + fprintf(fid, [' %% If the configuration file is stored in another place, the ' ... 'path must be adjusted here.\n']); - fprintf(fid, 'p = fileparts(mfilename(''fullpath''));\n'); - fprintf(fid, 'addpath(p);\n'); + fprintf(fid, ' p = fileparts(mfilename(''fullpath''));\n'); + fprintf(fid, ' addpath(p);\n'); + fprintf(fid, 'end\n'); fprintf(fid, '%% run configuration main & def function, return output\n'); fprintf(fid, 'cfg = %s;\n', n); if varargin{1}.gencode_opts.gencode_o_def diff --git a/matlabbatch/cfg_confgui/cfg_run_template.m b/matlabbatch/cfg_confgui/cfg_run_template.m index 8e39b07..0dacfee 100644 --- a/matlabbatch/cfg_confgui/cfg_run_template.m +++ b/matlabbatch/cfg_confgui/cfg_run_template.m @@ -44,9 +44,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: cfg_run_template.m 3355 2009-09-04 09:37:35Z volkmar $ +% $Id: cfg_run_template.m 3785 2010-03-17 15:53:42Z volkmar $ -rev = '$Rev: 3355 $'; %#ok +rev = '$Rev: 3785 $'; %#ok if ischar(cmd) switch lower(cmd) @@ -101,7 +101,7 @@ tags = textscan(defstr,'%s', 'delimiter','.'); subs = struct('type','.','subs',tags{1}'); try - cdefval = subsref(local_def, subs); + cdefval = subsref(defs, subs); catch cdefval = []; cfg_message('defaults:noval', ... diff --git a/matlabbatch/cfg_findspec.m b/matlabbatch/cfg_findspec.m index 64cd7d0..1dd3ee1 100644 --- a/matlabbatch/cfg_findspec.m +++ b/matlabbatch/cfg_findspec.m @@ -29,14 +29,15 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: cfg_findspec.m 2131 2008-09-22 06:04:53Z volkmar $ +% $Id: cfg_findspec.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 2131 $'; %#ok +rev = '$Rev: 3944 $'; %#ok if nargin == 0 || isempty(cellspec) spec = {}; return; end; +spec = cell(size(cellspec)); for k = 1:numel(cellspec) spec{k} = struct('name',{}, 'value',{}); for l = 1:2:numel(cellspec{k}) diff --git a/matlabbatch/cfg_getfile.m b/matlabbatch/cfg_getfile.m index ed231ea..bc9a898 100644 --- a/matlabbatch/cfg_getfile.m +++ b/matlabbatch/cfg_getfile.m @@ -57,7 +57,9 @@ % dirs - subdirectories of 'direc' % FORMAT [files,dirs]=cfg_getfile('ExtList',direc,filt,frames) % As above, but for selecting frames of 4D NIfTI files -% frames - vector of frames to select (defaults to 1, if not specified) +% frames - vector of frames to select (defaults to 1, if not +% specified). If the frame number is Inf, all frames for the +% matching images are listed. % FORMAT [files,dirs]=cfg_getfile('FPList',direc,filt) % FORMAT [files,dirs]=cfg_getfile('ExtFPList',direc,filt,frames) % As above, but returns files with full paths (i.e. prefixes direc to each) @@ -83,7 +85,7 @@ % Copyright (C) 2007 Freiburg Brain Imaging % John Ashburner and Volkmar Glauche -% $Id: cfg_getfile.m 3621 2009-12-09 08:11:17Z volkmar $ +% $Id: cfg_getfile.m 3944 2010-06-23 08:53:40Z volkmar $ t = {}; sts = false; @@ -123,8 +125,8 @@ else % only filter filenames, not paths for k = 1:numel(t) - [p n e v] = fileparts(t{k}); - t1{k} = [n e v]; + [p n e] = fileparts(t{k}); + t1{k} = [n e]; end end [t1,sts1] = do_filter(t1,filt.ext); @@ -670,7 +672,7 @@ function resize_fun(fg,varargin) sel = cellfun(@isempty, mch); npd = numel(pd); pd = [pd(:);d(sel)]; - mch = [mch{:} npd+(1:nnz(sel))]; + mch = [mch{~sel} npd+(1:nnz(sel))]; d = pd; end return; @@ -786,7 +788,7 @@ function update(lb,dr) else dr = [dr filesep]; end; -dr(findstr([filesep filesep],dr)) = []; +dr(strfind(dr,[filesep filesep])) = []; [f,d] = listfiles(dr,getfilt(lb)); if isempty(d), dr = get(lb,'UserData'); @@ -947,8 +949,11 @@ function unselect_all(ob,varargin) %======================================================================= function [f,d] = listfiles(dr,filt) -ob = gco; -omsg = msg(ob,'Listing directory...'); +ob = sib(gco,'msg'); +domsg = ~isempty(ob); +if domsg + omsg = msg(ob,'Listing directory...'); +end if nargin<2, filt = ''; end; if nargin<1, dr = '.'; end; de = dir(dr); @@ -968,12 +973,16 @@ function unselect_all(ob,varargin) f = {}; end; -msg(ob,['Filtering ' num2str(numel(f)) ' files...']); +if domsg + msg(ob,['Filtering ' num2str(numel(f)) ' files...']); +end f = do_filter(f,filt.ext); f = do_filter(f,filt.filt); ii = cell(1,numel(f)); if filt.code==1 && (numel(filt.frames)~=1 || filt.frames(1)~=1), - msg(ob,['Reading headers of ' num2str(numel(f)) ' images...']); + if domsg + msg(ob,['Reading headers of ' num2str(numel(f)) ' images...']); + end for i=1:numel(f), try ni = nifti(fullfile(dr,f{i})); @@ -982,17 +991,23 @@ function unselect_all(ob,varargin) catch d4 = 1; end; - msk = false(size(filt.frames)); - for j=1:numel(msk), msk(j) = any(d4==filt.frames(j)); end; - ii{i} = filt.frames(msk); - end; + if all(isfinite(filt.frames)) + msk = false(size(filt.frames)); + for j=1:numel(msk), msk(j) = any(d4==filt.frames(j)); end; + ii{i} = filt.frames(msk); + else + ii{i} = d4; + end; + end elseif filt.code==1 && (numel(filt.frames)==1 && filt.frames(1)==1), for i=1:numel(f), ii{i} = 1; end; end; -msg(ob,['Listing ' num2str(numel(f)) ' files...']); +if domsg + msg(ob,['Listing ' num2str(numel(f)) ' files...']); +end [f,ind] = sortrows(f(:)); ii = ii(ind); @@ -1031,7 +1046,9 @@ function unselect_all(ob,varargin) end; f = f(:); d = unique(d(:)); -msg(ob,omsg); +if domsg + msg(ob,omsg); +end return; %======================================================================= @@ -1239,8 +1256,8 @@ function editdone(ob,varargin) end filt = getfilt(ob); if filt.code >= 0 % filter files, but not dirs - [p n e v] = cellfun(@fileparts, str, 'uniformoutput',false); - fstr = strcat(n, e, v); + [p n e] = cellfun(@fileparts, str, 'uniformoutput',false); + fstr = strcat(n, e); [fstr1 fsel] = do_filter(fstr, filt.ext); str = str(fsel); end @@ -1367,12 +1384,7 @@ function select_rec(ob, varargin) '.*\.IMG(,[0-9]*){0,2}$'}; case {'xml'}, code = 0; ext = {'.*\.xml$','.*\.XML$'}; case {'mat'}, code = 0; ext = {'.*\.mat$','.*\.MAT$','.*\.txt','.*\.TXT'}; -case {'batch'}, code = 0; - if isdeployed, - ext = {'.*\.mat$','.*\.MAT$','.*\.xml$','.*\.XML$'}; - else - ext = {'.*\.mat$','.*\.MAT$','.*\.m$','.*\.M$','.*\.xml$','.*\.XML$'}; - end +case {'batch'}, code = 0; ext = {'.*\.mat$','.*\.MAT$','.*\.m$','.*\.M$','.*\.xml$','.*\.XML$'}; case {'dir'}, code =-1; ext = {'.*'}; case {'extdir'}, code =-1; ext = {['.*' filesep '$']}; otherwise, code = 0; ext = {typ}; diff --git a/matlabbatch/private/cfg_load_jobs.m b/matlabbatch/cfg_load_jobs.m similarity index 81% rename from matlabbatch/private/cfg_load_jobs.m rename to matlabbatch/cfg_load_jobs.m index b0bc44a..72386b0 100644 --- a/matlabbatch/private/cfg_load_jobs.m +++ b/matlabbatch/cfg_load_jobs.m @@ -12,9 +12,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: cfg_load_jobs.m 2673 2009-01-30 13:34:53Z volkmar $ +% $Id: cfg_load_jobs.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 2673 $'; %#ok +rev = '$Rev: 3944 $'; %#ok if ischar(job) filenames = cellstr(job); @@ -39,18 +39,14 @@ cfg_message('matlabbatch:initialise:mat','Load failed: ''%s''',filenames{cf}); end; case '.m' - opwd = pwd; - cfg_validatejobname(nam, false); try - if ~isempty(p) - cd(p); - end; - clear(nam); - eval(nam); + fid = fopen(filenames{cf},'rt'); + str = fread(fid,'*char'); + fclose(fid); + eval(str); catch cfg_message('matlabbatch:initialise:m','Eval failed: ''%s''',filenames{cf}); end; - cd(opwd); if ~exist('matlabbatch','var') cfg_message('matlabbatch:initialise:m','No matlabbatch job found in ''%s''', filenames{cf}); end; @@ -58,7 +54,7 @@ cfg_message('matlabbatch:initialise:unknown','Unknown extension: ''%s''', filenames{cf}); end; if exist('matlabbatch','var') - newjobs = {newjobs{:} matlabbatch}; + newjobs = [newjobs(:); {matlabbatch}]; clear matlabbatch; end; end; diff --git a/matlabbatch/cfg_message.m b/matlabbatch/cfg_message.m index b6ee219..c668213 100644 --- a/matlabbatch/cfg_message.m +++ b/matlabbatch/cfg_message.m @@ -42,9 +42,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: cfg_message.m 2673 2009-01-30 13:34:53Z volkmar $ +% $Id: cfg_message.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 2673 $'; %#ok +rev = '$Rev: 3944 $'; %#ok if nargin < 1 || isempty(varargin{1}) return; @@ -132,8 +132,8 @@ end cfg_get_defaults('msgtpl',msgtpl); end - varargout{1} = {oldmsgprops{:} oldtplprops{:}}; - varargout{2} = {mchmsgids{:} mchtplids{:}}; + varargout{1} = [oldmsgprops(:); oldtplprops(:)]'; + varargout{2} = [mchmsgids(:); mchtplids(:)]'; else % Issue message if isstruct(varargin{1}) diff --git a/matlabbatch/cfg_ui.fig b/matlabbatch/cfg_ui.fig index 3119fb3..4d9758a 100644 Binary files a/matlabbatch/cfg_ui.fig and b/matlabbatch/cfg_ui.fig differ diff --git a/matlabbatch/cfg_ui.m b/matlabbatch/cfg_ui.m index 4e5d41a..6d641cd 100644 --- a/matlabbatch/cfg_ui.m +++ b/matlabbatch/cfg_ui.m @@ -27,13 +27,13 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: cfg_ui.m 3610 2009-12-03 13:18:26Z volkmar $ +% $Id: cfg_ui.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 3610 $'; %#ok +rev = '$Rev: 3944 $'; %#ok % edit the above text to modify the response to help cfg_ui -% Last Modified by GUIDE v2.5 08-Nov-2009 21:42:38 +% Last Modified by GUIDE v2.5 04-Mar-2010 16:09:52 % Begin initialization code - DO NOT EDIT gui_Singleton = 1; @@ -338,7 +338,7 @@ function local_showmod(obj) cfg_findspec({{'hidden',false}}), ... cfg_tropts({{'hidden', true}},1,Inf,1,Inf,dflag), ... {'name','val','labels','values','class','level', ... - 'all_set','all_set_item'}); + 'all_set','all_set_item','num'}); if isempty(id) || ~cfg_util('isitem_mod_id', id{1}) % Module not found without hidden flag % Try to list top level entry of module anyway, but not module items. @@ -565,56 +565,77 @@ function local_showvaledit(obj) if ~isfield(udmodlist, 'defid') udvalshow = local_init_udvalshow; udvalshow.cval = 1; - % Available items - naitems = numel(udmodule.contents{4}{citem}); - str1 = cell(naitems,1); - cmd1 = cell(naitems,1); - for k = 1:naitems - str1{k} = sprintf('New: %s', udmodule.contents{4}{citem}{k}.name); - cmd1{k} = [k Inf]; - uimenu(handles.MenuEditValAddItem, ... - 'Label',udmodule.contents{4}{citem}{k}.name, ... - 'Callback',@(ob,ev)local_setvaledit(ob,cmd1{k},ev), ... - 'Tag','MenuEditValAddItemDyn'); - uimenu(handles.CmValAddItem, ... - 'Label',udmodule.contents{4}{citem}{k}.name, ... - 'Callback',@(ob,ev)local_setvaledit(ob,cmd1{k},ev), ... - 'Tag','CmValAddItemDyn'); - end; % Already selected items ncitems = numel(udmodule.contents{2}{citem}); - str2 = cell(2*ncitems,1); - cmd2 = cell(2*ncitems,1); + str3 = cell(ncitems,1); + cmd3 = cell(ncitems,1); for k = 1:ncitems - str2{k} = sprintf('Replicate: %s (%d)',... - udmodule.contents{2}{citem}{k}.name, k); - cmd2{k} = [-1 k]; - uimenu(handles.MenuEditValReplItem, ... - 'Label',sprintf('%s (%d)', ... - udmodule.contents{2}{citem}{k}.name, k), ... - 'Callback',@(ob,ev)local_setvaledit(ob,cmd2{k},ev), ... - 'Tag','MenuEditValReplItemDyn'); - uimenu(handles.CmValReplItem, ... - 'Label',sprintf('%s (%d)', ... - udmodule.contents{2}{citem}{k}.name, k), ... - 'Callback',@(ob,ev)local_setvaledit(ob,cmd2{k},ev), ... - 'Tag','CmValReplItemDyn'); - str2{k+ncitems} = sprintf('Delete: %s (%d)',... - udmodule.contents{2}{citem}{k}.name, k); - cmd2{k+ncitems} = [Inf k]; + str3{k} = sprintf('Delete: %s (%d)',... + udmodule.contents{2}{citem}{k}.name, k); + cmd3{k} = [Inf k]; uimenu(handles.MenuEditValDelItem, ... - 'Label',sprintf('%s (%d)', ... - udmodule.contents{2}{citem}{k}.name, k), ... - 'Callback',@(ob,ev)local_setvaledit(ob,cmd2{k+ncitems},ev), ... - 'Tag','MenuEditValDelItemDyn'); + 'Label',sprintf('%s (%d)', ... + udmodule.contents{2}{citem}{k}.name, k), ... + 'Callback',@(ob,ev)local_setvaledit(ob,cmd3{k},ev), ... + 'Tag','MenuEditValDelItemDyn'); uimenu(handles.CmValDelItem, ... - 'Label',sprintf('%s (%d)', ... - udmodule.contents{2}{citem}{k}.name, k), ... - 'Callback',@(ob,ev)local_setvaledit(ob,cmd2{k+ncitems},ev), ... - 'Tag','CmValDelItemDyn'); + 'Label',sprintf('%s (%d)', ... + udmodule.contents{2}{citem}{k}.name, k), ... + 'Callback',@(ob,ev)local_setvaledit(ob,cmd3{k},ev), ... + 'Tag','CmValDelItemDyn'); + end + % Add/Replicate callbacks will be shown only if max number of + % items not yet reached + if ncitems < udmodule.contents{9}{citem}(2) + % Available items + naitems = numel(udmodule.contents{4}{citem}); + str1 = cell(naitems,1); + cmd1 = cell(naitems,1); + for k = 1:naitems + str1{k} = sprintf('New: %s', udmodule.contents{4}{citem}{k}.name); + cmd1{k} = [k Inf]; + uimenu(handles.MenuEditValAddItem, ... + 'Label',udmodule.contents{4}{citem}{k}.name, ... + 'Callback',@(ob,ev)local_setvaledit(ob,cmd1{k},ev), ... + 'Tag','MenuEditValAddItemDyn'); + uimenu(handles.CmValAddItem, ... + 'Label',udmodule.contents{4}{citem}{k}.name, ... + 'Callback',@(ob,ev)local_setvaledit(ob,cmd1{k},ev), ... + 'Tag','CmValAddItemDyn'); + end; + str2 = cell(ncitems,1); + cmd2 = cell(ncitems,1); + for k = 1:ncitems + str2{k} = sprintf('Replicate: %s (%d)',... + udmodule.contents{2}{citem}{k}.name, k); + cmd2{k} = [-1 k]; + uimenu(handles.MenuEditValReplItem, ... + 'Label',sprintf('%s (%d)', ... + udmodule.contents{2}{citem}{k}.name, k), ... + 'Callback',@(ob,ev)local_setvaledit(ob,cmd2{k},ev), ... + 'Tag','MenuEditValReplItemDyn'); + uimenu(handles.CmValReplItem, ... + 'Label',sprintf('%s (%d)', ... + udmodule.contents{2}{citem}{k}.name, k), ... + 'Callback',@(ob,ev)local_setvaledit(ob,cmd2{k},ev), ... + 'Tag','CmValReplItemDyn'); + end + set(findobj(handles.cfg_ui,'-regexp','Tag','.*AddItem$'), ... + 'Visible','on', 'Enable','on'); + if ncitems > 0 + set(findobj(handles.cfg_ui,'-regexp','Tag','.*ReplItem$'), ... + 'Visible','on', 'Enable','on'); + set(findobj(handles.cfg_ui,'-regexp','Tag','.*ReplItem$'), ... + 'Visible','on', 'Enable','on'); + end + else + str1 = {}; + str2 = {}; + cmd1 = {}; + cmd2 = {}; end - str = [str1(:); str2(:)]; - udvalshow.cmd = [cmd1(:); cmd2(:)]; + str = [str1(:); str2(:); str3(:)]; + udvalshow.cmd = [cmd1(:); cmd2(:); cmd3(:)]; set(handles.valshow,'String', str, 'Visible','on', 'Value',1, ... 'Callback',@local_valedit_repeat, ... 'KeyPressFcn', @local_valedit_key, ... @@ -622,13 +643,7 @@ function local_showvaledit(obj) set(handles.valshowLabel, 'Visible','on'); set(findobj(handles.cfg_ui,'-regexp','Tag','^Btn.*EditVal$'), ... 'Visible','on', 'Enable','on'); - set(findobj(handles.cfg_ui,'-regexp','Tag','.*AddItem$'), ... - 'Visible','on', 'Enable','on'); if ncitems > 0 - set(findobj(handles.cfg_ui,'-regexp','Tag','.*ReplItem$'), ... - 'Visible','on', 'Enable','on'); - set(findobj(handles.cfg_ui,'-regexp','Tag','.*ReplItem$'), ... - 'Visible','on', 'Enable','on'); set(findobj(handles.cfg_ui,'-regexp','Tag','.*DelItem$'), ... 'Visible','on', 'Enable','on'); end; @@ -637,7 +652,7 @@ function local_showvaledit(obj) end; end; if isfield(udmodlist, 'defid') - cmid = {udmodlist.defid{cmod}}; + cmid = udmodlist.defid(cmod); else cmid = {udmodlist.cjob udmodlist.id{cmod}}; end; @@ -676,7 +691,7 @@ function local_valedit_edit(hObject) udmodlist = get(handles.modlist, 'Userdata'); val = udmodule.contents{2}{value}; if isfield(udmodlist, 'defid') - cmid = {udmodlist.defid{cmod}}; + cmid = udmodlist.defid(cmod); else cmid = {udmodlist.cjob, udmodlist.id{cmod}}; end; @@ -704,7 +719,7 @@ function local_valedit_edit(hObject) else instr = {''}; end - hlptxt = strvcat('Enter a valid MATLAB expression.', ... + hlptxt = char({'Enter a valid MATLAB expression.', ... ' ', ... ['Strings must be enclosed in single quotes ' ... '(''A''), multiline arrays in brackets ([ ]).'], ... @@ -712,7 +727,7 @@ function local_valedit_edit(hObject) 'To clear a value, enter an empty cell ''{}''.', ... ' ', ... ['Accept input with CTRL-RETURN, cancel with ' ... - 'ESC.']); + 'ESC.']}); failtxt = {'Input could not be evaluated. Possible reasons are:',... '1) Input should be a vector or matrix, but is not enclosed in ''['' and '']'' brackets.',... '2) Input should be a character or string, but is not enclosed in '' single quotes.',... @@ -721,21 +736,21 @@ function local_valedit_edit(hObject) else if strtype{1}{1} == 's' instr = val; - encl = ''''''; + encl = {'''' ''''}; else try instr = {num2str(val{1})}; catch instr = {''}; end; - encl = '[]'; + encl = {'[' ']'}; end; - hlptxt = strvcat('Enter a value.', ... + hlptxt = char({'Enter a value.', ... ' ', ... 'To clear a value, clear the input field and accept.', ... ' ', ... ['Accept input with CTRL-RETURN, cancel with ' ... - 'ESC.']); + 'ESC.']}); failtxt = {'Input could not be evaluated.'}; end sts = false; @@ -778,9 +793,9 @@ function local_valedit_edit(hObject) delete(val); end % escape single quotes and place the whole string in single quotes - str = strcat({encl(1)}, strrep(cstr,'''',''''''), {encl(2)}, {char(10)}); + str = strcat(encl(1), strrep(cstr,'''',''''''), encl(2), {char(10)}); else - cestr = {encl(1) cstr{:} encl(2)}; + cestr = [encl(1); cstr(:); encl(2)]'; str = strcat(cestr, {char(10)}); end; str = cat(2, str{:}); @@ -961,7 +976,7 @@ function local_valedit_SelectFiles(hObject) udmodule = get(handles.module, 'Userdata'); citem = get(handles.module, 'Value'); if isfield(udmodlist,'defid') - cmid = {udmodlist.defid{cmod}}; + cmid = udmodlist.defid(cmod); else cmid = {udmodlist.cjob, udmodlist.id{cmod}}; end; @@ -1031,7 +1046,7 @@ function cfg_ui_OpeningFcn(hObject, eventdata, handles, varargin) local_setfont(hObject, fs); % set ExpertEdit checkbox -set(handles.MenuEditExpertEdit, ... +set(handles.MenuViewExpertEdit, ... 'checked',cfg_get_defaults([mfilename '.ExpertEdit'])); % show job @@ -1103,7 +1118,7 @@ function MenuFileLoad_Callback(hObject, eventdata, handles) cmd = 'Continue'; end; if strcmpi(cmd,'continue') - [files sts] = cfg_getfile([1 Inf], 'batch', 'Load Job File(s)'); + [files sts] = cfg_getfile([1 Inf], 'batch', 'Load Job File(s)', {}, udmodlist.wd); if sts local_pointer('watch'); cfg_util('deljob',udmodlist(1).cjob); @@ -1139,7 +1154,7 @@ function MenuFileSave_Callback(hObject, eventdata, handles) return; end; local_pointer('watch'); -[p n e v] = fileparts(file); +[p n e] = fileparts(file); if isempty(e) || ~any(strcmp(e,{'.mat','.m'})) e1 = {'.mat','.m'}; e2 = e1{idx}; @@ -1148,19 +1163,10 @@ function MenuFileSave_Callback(hObject, eventdata, handles) file = n; e2 = e; end -% Warn if saving as .m in a compiled version -if isdeployed && strcmp(e2,'.m') && ... - strcmp(questdlg({'This batch system will not load ".m" batch jobs.' ... - ['If you want to use your batch with this batch ' ... - 'system, you should save it as a ".mat" file.']}, ... - 'Format for Saved Job',... - 'Save as .mat','Save as .m', 'Save as .mat'), ... - 'Save as .mat') - e2 = '.mat'; -end try cfg_util('savejob', udmodlist.cjob, fullfile(pth, [file e2])); udmodlist.modified = false; + udmodlist.wd = pth; set(handles.modlist,'userdata',udmodlist); catch l = lasterror; @@ -1187,14 +1193,15 @@ function MenuFileScript_Callback(hObject, eventdata, handles) return; end; local_pointer('watch'); -[p n e v] = fileparts(file); -if isempty(e) || ~strcmp(e,'.m') - e = '.m'; -end +[p n e] = fileparts(file); try - cfg_util('genscript', udmodlist.cjob, pth, [n e]); + cfg_util('genscript', udmodlist.cjob, pth, [n '.m']); udmodlist.modified = false; + udmodlist.wd = pth; set(handles.modlist,'userdata',udmodlist); + if ~isdeployed + edit(fullfile(pth, [n '.m'])); + end catch l = lasterror; errordlg(l.message,'Error generating job script', 'modal'); @@ -1246,7 +1253,7 @@ function MenuFileAddApp_Callback(hObject, eventdata, handles) if ~isempty(udmodlist.cmod) cfg_util('deljob',udmodlist(1).cjob); end; - [p fun e v] = fileparts(file{1}); + [p fun e] = fileparts(file{1}); addpath(p); cfg_util('addapp', fun); local_setmenu(handles.cfg_ui, [], @local_addtojob, true); @@ -1272,8 +1279,8 @@ function MenuEdit_Callback(hObject, eventdata, handles) % handles structure with handles and user data (see GUIDATA) % -------------------------------------------------------------------- -function MenuEditUpdateView_Callback(hObject, eventdata, handles) -% hObject handle to MenuEditUpdateView (see GCBO) +function MenuViewUpdateView_Callback(hObject, eventdata, handles) +% hObject handle to MenuViewUpdateView (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) @@ -1338,8 +1345,8 @@ function MenuEditValAddDep_Callback(hObject, eventdata, handles) local_valedit_AddDep(hObject); % -------------------------------------------------------------------- -function MenuEditExpertEdit_Callback(hObject, eventdata, handles) -% hObject handle to MenuEditExpertEdit (see GCBO) +function MenuViewExpertEdit_Callback(hObject, eventdata, handles) +% hObject handle to MenuViewExpertEdit (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) @@ -1562,15 +1569,15 @@ function valshowBtnCancel_Callback(hObject, eventdata, handles) % -------------------------------------------------------------------- -function MenuEditFontSize_Callback(hObject, eventdata, handles) -% hObject handle to MenuEditFontSize (see GCBO) +function MenuViewFontSize_Callback(hObject, eventdata, handles) +% hObject handle to MenuViewFontSize (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) fs = uisetfont(cfg_get_defaults([mfilename '.lfont'])); if isstruct(fs) local_setfont(hObject,fs); - MenuEditUpdateView_Callback(hObject, eventdata, handles); + MenuViewUpdateView_Callback(hObject, eventdata, handles); end; % --- Executes when cfg_ui is resized. @@ -1580,7 +1587,7 @@ function cfg_ui_ResizeFcn(hObject, eventdata, handles) % handles structure with handles and user data (see GUIDATA) % this is just "Update View" -MenuEditUpdateView_Callback(hObject, eventdata, handles); +MenuViewUpdateView_Callback(hObject, eventdata, handles); % -------------------------------------------------------------------- function local_setfont(obj,fs) @@ -1635,3 +1642,46 @@ function CmValClearVal_Callback(hObject, eventdata, handles) % handles structure with handles and user data (see GUIDATA) local_valedit_ClearVal(hObject); + + +% -------------------------------------------------------------------- +function MenuView_Callback(hObject, eventdata, handles) +% hObject handle to MenuView (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + + +% -------------------------------------------------------------------- +function MenuViewShowCode_Callback(hObject, eventdata, handles) +% hObject handle to MenuViewShowCode (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +udmodlist = get(handles.modlist, 'userdata'); +[un matlabbatch] = cfg_util('harvest', udmodlist.cjob); +str = gencode(matlabbatch); +fg = findobj(0,'Type','figure','Tag',[mfilename 'ShowCode']); +if isempty(fg) + fg = figure('Menubar','none', 'Toolbar','none', 'Tag',[mfilename 'ShowCode'], 'Units','normalized', 'Name','Batch Code Browser', 'NumberTitle','off'); + ctxt = uicontrol('Parent',fg, 'Style','listbox', 'Units','normalized', 'Position',[0 0 1 1], 'FontName','FixedWidth','Tag',[mfilename 'ShowCodeList']); +else + figure(fg); + ctxt = findobj(fg,'Tag',[mfilename 'ShowCodeList']); +end +um = uicontextmenu; +um1 = uimenu('Label','Copy', 'Callback',@(ob,ev)ShowCode_Copy(ob,ev,ctxt), 'Parent',um); +um1 = uimenu('Label','Select all', 'Callback',@(ob,ev)ShowCode_SelAll(ob,ev,ctxt), 'Parent',um); +um1 = uimenu('Label','Unselect all', 'Callback',@(ob,ev)ShowCode_UnSelAll(ob,ev,ctxt), 'Parent',um); +set(ctxt, 'Max',numel(str), 'String',str, 'UIContextMenu',um); + +function ShowCode_Copy(ob, ev, ctxt) +str = get(ctxt,'String'); +sel = get(ctxt,'Value'); +str = str(sel); +clipboard('copy',sprintf('%s\n',str{:})); + +function ShowCode_SelAll(ob, ev, ctxt) +set(ctxt,'Value', 1:numel(get(ctxt, 'String'))); + +function ShowCode_UnSelAll(ob, ev, ctxt) +set(ctxt,'Value', []); \ No newline at end of file diff --git a/matlabbatch/cfg_util.m b/matlabbatch/cfg_util.m index a6a92ab..d5afb38 100644 --- a/matlabbatch/cfg_util.m +++ b/matlabbatch/cfg_util.m @@ -143,14 +143,6 @@ % modules with dependencies. % If the job has not been run yet, tag and val will be empty. % -% doc = cfg_util('showdoc', tagstr|cfg_id|(job_id, mod_job_id[, item_mod_id])) -% -% Return help text for specified item. Item can be either a tag string or -% a cfg_id in the default configuration tree, or a combination of job_id, -% mod_job_id and item_mod_id from the current job. -% The text returned will be a cell array of strings, each string -% containing one paragraph of the help text. -% % cfg_util('initcfg') % % Initialise cfg_util configuration. All currently added applications and @@ -381,9 +373,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: cfg_util.m 3599 2009-11-26 14:08:07Z volkmar $ +% $Id: cfg_util.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 3599 $'; +rev = '$Rev: 3944 $'; %% Initialisation of cfg variables % load persistent configuration data, initialise if necessary @@ -444,17 +436,46 @@ jobs(varargin{1}).cjrun = []; end end + case 'dumpcfg' + %-Locate batch configs and copy them + apps = which('cfg_mlbatch_appcfg','-all'); + appcfgs = cell(size(apps)); + p = fileparts(mfilename('fullpath')); + for k = 1:numel(apps) + appcfgs{k} = fullfile(p,'private',sprintf('cfg_mlbatch_appcfg_%d.m',k)); + copyfile(apps{k}, appcfgs{k}); + end + cmaster = fullfile(p, 'private', 'cfg_mlbatch_appcfg_master.m'); + fid = fopen(cmaster,'w'); + fprintf(fid,'function cfg_mlbatch_appcfg_master\n'); + for k = 1:numel(apps) + fprintf(fid,'[cfg, def] = cfg_mlbatch_appcfg_%d;\n', k); + fprintf(fid,'cfg_util(''addapp'', cfg, def);\n'); + end + fclose(fid); case 'filljob', cjob = varargin{1}; - jobs(cjob).cj = fillvals(jobs(cjob).cj, varargin(2:end), []); - sts = all_set(jobs(cjob).cj); - varargout{1} = sts; + if cfg_util('isjob_id', cjob) + try + jobs(cjob).cj = fillvals(jobs(cjob).cj, varargin(2:end), []); + sts = all_set(jobs(cjob).cj); + catch + sts = false; + end + else + sts = false; + end + varargout{1} = sts; case 'filljobui', - try - cjob = varargin{1}; - jobs(cjob).cj = fillvals(jobs(cjob).cj, varargin(3:end), varargin{2}); - sts = all_set(jobs(cjob).cj); - catch + cjob = varargin{1}; + if cfg_util('isjob_id', cjob) + try + jobs(cjob).cj = fillvals(jobs(cjob).cj, varargin(3:end), varargin{2}); + sts = all_set(jobs(cjob).cj); + catch + sts = false; + end + else sts = false; end varargout{1} = sts; @@ -533,12 +554,16 @@ cjob = varargin{1}; if cfg_util('isjob_id', cjob) && ~isempty(jobs(cjob).cjrun) varargout{1} = cellfun(@(cid)subsref(jobs(cjob).cjrun, [cid substruct('.','jout')]), jobs(cjob).cjid2subsrun, 'UniformOutput',false); + else + varargout{1} = {}; end case 'getallvoutputs', cjob = varargin{1}; if cfg_util('isjob_id', cjob) vmods = ~cellfun('isempty',jobs(cjob).cjid2subs); % Ignore deleted modules varargout{1} = cellfun(@(cid)subsref(jobs(cjob).cj, [cid substruct('.','sout')]), jobs(cjob).cjid2subs(vmods), 'UniformOutput',false); + else + varargout{1} = {}; end case 'harvest', tag = ''; @@ -576,7 +601,7 @@ tag = ''; val = []; cjob = varargin{1}; - if ~isempty(jobs(cjob).cjrun) + if cfg_util('isjob_id', cjob) && ~isempty(jobs(cjob).cjrun) [tag val] = harvest(jobs(cjob).cjrun, jobs(cjob).cjrun, false, ... true); end @@ -595,8 +620,8 @@ else cjob = numel(jobs)+1; end - jobs(cjob).c0 = c0; if nargin == 1 + jobs(cjob).c0 = c0; jobs(cjob).cj = jobs(cjob).c0; jobs(cjob).cjid2subs = {}; jobs(cjob).cjrun = []; @@ -606,22 +631,34 @@ return; elseif ischar(varargin{1}) || iscellstr(varargin{1}) job = cfg_load_jobs(varargin{1}); - elseif iscell(varargin{1}{1}) + elseif iscell(varargin{1}) && iscell(varargin{1}{1}) % try to initialise cell array of jobs job = varargin{1}; else % try to initialise single job job{1} = varargin{1}; end - [jobs(cjob) mod_job_idlist] = local_initjob(jobs(cjob), job); - varargout{1} = cjob; - varargout{2} = mod_job_idlist; + % job should be a cell array of job structures + isjob = true(size(job)); + for k = 1:numel(job) + isjob(k) = iscell(job{k}) && all(cellfun('isclass', job{k}, 'struct')); + end + job = job(isjob); + if isempty(job) + cfg_message('matlabbatch:initialise:invalid','No valid job.'); + else + jobs(cjob).c0 = c0; + [jobs(cjob) mod_job_idlist] = local_initjob(jobs(cjob), job); + varargout{1} = cjob; + varargout{2} = mod_job_idlist; + end case 'isitem_mod_id' varargout{1} = isempty(varargin{1}) || ... (isstruct(varargin{1}) && ... all(isfield(varargin{1}, {'type','subs'}))); case 'isjob_id' - varargout{1} = isnumeric(varargin{1}) && ... + varargout{1} = ~isempty(varargin{1}) && ... + isnumeric(varargin{1}) && ... varargin{1} <= numel(jobs) ... && (~isempty(jobs(varargin{1}).cjid2subs) ... || varargin{1} == numel(jobs)); @@ -763,10 +800,13 @@ else pflag = false; end - jobs(cjob) = local_runcj(jobs(cjob), cjob, pflag); + [jobs(cjob) err] = local_runcj(jobs(cjob), cjob, pflag); if dflag cfg_util('deljob', cjob); end + if ~isempty(err) + cfg_message(err); + end case {'savejob','savejobrun'} cjob = varargin{1}; if strcmpi(cmd,'savejob') @@ -778,16 +818,11 @@ cfg_message('matlabbatch:cfg_util:savejob:nojob', ... 'Nothing to save for job #%d', cjob); else - [p n e v] = fileparts(varargin{2}); + [p n e] = fileparts(varargin{2}); switch lower(e) case '.mat', save(varargin{2},'matlabbatch','-v6'); case '.m' - % check whether n is a valid MATLAB .m file - % name. Depending on the message settings for - % 'matlabbatch:validatejobname:soft' this will either - % throw an error, or a valid filename will be used. - n = cfg_validatejobname(n, false); jobstr = gencode(matlabbatch, tag); fid = fopen(fullfile(p, [n '.m']), 'wt'); fprintf(fid, '%%-----------------------------------------------------------------------\n'); @@ -1065,7 +1100,7 @@ function local_gencode(c0, fname, tropts, preamble) tropts(1).clvl = 1; tropts(1).mlvl = Inf; tropts(1).cnt = 1; - [p funcname e v] = fileparts(fname); + [p funcname e] = fileparts(fname); [cstr tag] = gencode_item(c0, '', {}, [funcname '_'], tropts); funcname = [funcname '_' tag]; fname = fullfile(p, [funcname '.m']); @@ -1086,7 +1121,7 @@ function local_gencode(c0, fname, tropts, preamble) fclose(fid); else % generate root level code - [p funcname e v] = fileparts(fname); + [p funcname e] = fileparts(fname); [cstr tag] = gencode_item(c0, 'jobs', {}, [funcname '_'], tropts); fname = fullfile(p, [funcname '.m']); if nargin < 4 || isempty(preamble) || ~iscellstr(preamble) @@ -1209,33 +1244,37 @@ function local_gencode(c0, fname, tropts, preamble) %----------------------------------------------------------------------- function local_initapps % add application data -appcfgs = which('cfg_mlbatch_appcfg','-all'); -cwd = pwd; -dirs = cell(size(appcfgs)); -for k = 1:numel(appcfgs) - % cd into directory containing config file - [p n e v] = fileparts(appcfgs{k}); - local_cd(p); - % try to work around MATLAB bug in symlink handling - % only add application if this directory has not been visited yet - dirs{k} = pwd; - if ~any(strcmp(dirs{k}, dirs(1:k-1))) - try - [cfg def] = feval('cfg_mlbatch_appcfg'); - ests = true; - catch - ests = false; - estr = cfg_disp_error(lasterror); - cfg_message('matlabbatch:cfg_util:eval_appcfg', ... - 'Failed to load %s', which('cfg_mlbatch_appcfg')); - cfg_message('matlabbatch:cfg_util:eval_appcfg', '%s\n', estr{:}); - end - if ests - cfg_util('addapp', cfg, def); +if isdeployed + cfg_mlbatch_appcfg_master; +else + appcfgs = which('cfg_mlbatch_appcfg','-all'); + cwd = pwd; + dirs = cell(size(appcfgs)); + for k = 1:numel(appcfgs) + % cd into directory containing config file + [p n e] = fileparts(appcfgs{k}); + local_cd(p); + % try to work around MATLAB bug in symlink handling + % only add application if this directory has not been visited yet + dirs{k} = pwd; + if ~any(strcmp(dirs{k}, dirs(1:k-1))) + try + [cfg def] = feval('cfg_mlbatch_appcfg'); + ests = true; + catch + ests = false; + estr = cfg_disp_error(lasterror); + cfg_message('matlabbatch:cfg_util:eval_appcfg', ... + 'Failed to load %s', which('cfg_mlbatch_appcfg')); + cfg_message('matlabbatch:cfg_util:eval_appcfg', '%s\n', estr{:}); + end + if ests + cfg_util('addapp', cfg, def); + end end end + local_cd(cwd); end -local_cd(cwd); %----------------------------------------------------------------------- %----------------------------------------------------------------------- @@ -1257,7 +1296,7 @@ function local_gencode(c0, fname, tropts, preamble) if subsasgn_check_funhandle(defspec) opwd = pwd; if ischar(defspec) - [p fn e v] = fileparts(defspec); + [p fn e] = fileparts(defspec); local_cd(p); defspec = fn; end @@ -1371,7 +1410,7 @@ function local_gencode(c0, fname, tropts, preamble) %----------------------------------------------------------------------- %----------------------------------------------------------------------- -function job = local_runcj(job, cjob, pflag) +function [job err] = local_runcj(job, cjob, pflag) % 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 @@ -1479,6 +1518,7 @@ function local_gencode(c0, fname, tropts, preamble) end if isempty(cjid2subsfailed) && isempty(cjid2subsskipped) cfg_message('matlabbatch:run:jobdone', 'Done\n'); + err = []; else str = cell(numel(cjid2subsfailed)+numel(cjid2subsskipped)+1,1); str{1} = 'The following modules did not run:'; @@ -1490,15 +1530,14 @@ function local_gencode(c0, fname, tropts, preamble) subsref(job.cjrun, [cjid2subsskipped{k} substruct('.','name')])); end cfg_message('matlabbatch:run:jobfailed', '%s\n', str{:}); - est.identifier = 'matlabbatch:run:jobfailederr'; - est.message = sprintf(['Job execution failed. The full log of this run can ' ... + err.identifier = 'matlabbatch:run:jobfailederr'; + err.message = sprintf(['Job execution failed. The full log of this run can ' ... 'be found in MATLAB command window, starting with ' ... 'the lines (look for the line showing the exact ' ... '#job as displayed in this error message)\n' ... '------------------ \nRunning job #%d' ... '\n------------------\n'], cjob); - est.stack = struct('file','','name','MATLABbatch system','line',0); - cfg_message(est); + err.stack = struct('file','','name','MATLABbatch system','line',0); end %----------------------------------------------------------------------- diff --git a/matlabbatch/hgsave_pre2008a.m b/matlabbatch/hgsave_pre2008a.m index 3c82578..b9a0ee1 100644 --- a/matlabbatch/hgsave_pre2008a.m +++ b/matlabbatch/hgsave_pre2008a.m @@ -57,15 +57,15 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: hgsave_pre2008a.m 3567 2009-11-13 14:55:48Z volkmar $ +% $Id: hgsave_pre2008a.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 3567 $'; %#ok +rev = '$Rev: 3944 $'; %#ok hvar = load(figname,'-mat'); hstr = gencode(hvar); -[p fign e v] = fileparts(figname); +[p fign e] = fileparts(figname); % save new figure under _R14SP3 -nfigname = fullfile(p, sprintf('%s_R14SP3%s%s', fign, e, v)); +nfigname = fullfile(p, sprintf('%s_R14SP3%s%s', fign, e)); % This regexp filters out automatically created/convertible code if doreplace re = sprintf('^([^=]*)= @\\(hObject,eventdata\\)%s\\(([^,]*),hObject,eventdata,guidata\\(hObject\\)\\)',fign); diff --git a/matlabbatch/private/cfg_justify.m b/matlabbatch/private/cfg_justify.m index d0757d3..af05e69 100644 --- a/matlabbatch/private/cfg_justify.m +++ b/matlabbatch/private/cfg_justify.m @@ -29,7 +29,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % John Ashburner -% $Id: cfg_justify.m 2131 2008-09-22 06:04:53Z volkmar $ +% $Id: cfg_justify.m 3944 2010-06-23 08:53:40Z volkmar $ out = {}; @@ -61,11 +61,11 @@ if iscell(varargin{i}), for j=1:numel(varargin{i}), para = justify_paragraph(TempObj,spext,swidth,varargin{i}{j}); - out = {out{:},para{:}}; + out = [out(:);para(:)]'; end else para = justify_paragraph(TempObj,spext,swidth,varargin{i}); - out = {out{:},para{:}}; + out = [out(:);para(:)]'; end end if ishandle(TempObj) @@ -76,8 +76,8 @@ txt = txt(2:end); end; %txt = regexprep(txt,'/\*([^(/\*)]*)\*/',''); -st1 = findstr(txt,'/*'); -en1 = findstr(txt,'*/'); +st1 = strfind(txt,'/*'); +en1 = strfind(txt,'*/'); st = []; en = []; for i=1:numel(st1), diff --git a/matlabbatch/private/cfg_mlbatch_defaults.m b/matlabbatch/private/cfg_mlbatch_defaults.m index 000d753..38107ca 100644 --- a/matlabbatch/private/cfg_mlbatch_defaults.m +++ b/matlabbatch/private/cfg_mlbatch_defaults.m @@ -11,9 +11,9 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: cfg_mlbatch_defaults.m 3599 2009-11-26 14:08:07Z volkmar $ +% $Id: cfg_mlbatch_defaults.m 3792 2010-03-22 13:11:36Z volkmar $ -rev = '$Rev: 3599 $'; %#ok +rev = '$Rev: 3792 $'; %#ok % Font definition for cfg_ui user interface % cfg_defaults.cfg_ui.Xfont is a font struct as returned by uisetfont @@ -70,11 +70,8 @@ cfg_defaults.msgcfg(2).identifier = 'matlabbatch:cfg_util:addapp:done'; cfg_defaults.msgcfg(2).destination = 'none'; cfg_defaults.msgcfg(3) = cfg_defaults.msgdef; -cfg_defaults.msgcfg(3).identifier = 'matlabbatch:validatejobname:hard'; +cfg_defaults.msgcfg(3).identifier = 'matlabbatch:initialise:invalid'; cfg_defaults.msgcfg(3).level = 'error'; -cfg_defaults.msgcfg(4) = cfg_defaults.msgdef; -cfg_defaults.msgcfg(4).identifier = 'matlabbatch:validatejobname:soft'; -cfg_defaults.msgcfg(4).level = 'warning'; cfg_defaults.msgtpl( 1) = cfg_defaults.msgdef; cfg_defaults.msgtpl( 1).identifier = '^matlabbatch:subsasgn'; diff --git a/matlabbatch/private/cfg_validatejobname.m b/matlabbatch/private/cfg_validatejobname.m deleted file mode 100644 index 31fe248..0000000 --- a/matlabbatch/private/cfg_validatejobname.m +++ /dev/null @@ -1,34 +0,0 @@ -function nname = cfg_validatejobname(name, cont) -% CFG_VALIDATEJOBNAME - validate the name of a job file -% -% See also GENVARNAME -% -% 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_validatejobname.m 2673 2009-01-30 13:34:53Z volkmar $ - -rev = '$Rev: 2673 $'; %#ok - -nname = genvarname(name); -if ~strcmp(nname, name) - if cont - cfg_message('matlabbatch:validatejobname:soft',... - '''%s'' is not a valid name for a MATLAB script file, using ''%s'' instead.',... - name, nname); - else - cfg_message('matlabbatch:validatejobname:hard',... - ['''%s'' is not a valid name for a MATLAB script file.\n',... - 'Allowed characters are\n',... - '* letters,\n',... - '* numbers and\n',... - '* underscores.\n',... - 'The first character must be a letter.\n',... - 'See MATLAB documentation for details.'],... - name); - end -end \ No newline at end of file diff --git a/matlabbatch/private/copyright_cfg.m b/matlabbatch/private/copyright_cfg.m index f5ce5ff..3b27fe4 100644 --- a/matlabbatch/private/copyright_cfg.m +++ b/matlabbatch/private/copyright_cfg.m @@ -6,6 +6,6 @@ % Copyright (C) 2007 Freiburg Brain Imaging % Volkmar Glauche -% $Id: copyright_cfg.m 1716 2008-05-23 08:18:45Z volkmar $ +% $Id: copyright_cfg.m 3944 2010-06-23 08:53:40Z volkmar $ -rev = '$Rev: 1716 $'; %#ok +rev = '$Rev: 3944 $'; diff --git a/spm.m b/spm.m index 281f9a4..9828cc1 100644 --- a/spm.m +++ b/spm.m @@ -63,7 +63,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Andrew Holmes -% $Id: spm.m 3659 2010-01-04 17:37:03Z guillaume $ +% $Id: spm.m 3958 2010-06-30 16:24:46Z guillaume $ %======================================================================= @@ -295,9 +295,11 @@ %======================================================================= % spm('Welcome') spm_check_installation('basic'); -spm_defaults; -global defaults -if isfield(defaults,'modality'), spm(defaults.modality); return; end +defaults = spm('GetGlobal','defaults'); +if isfield(defaults,'modality') + spm(defaults.modality); + return +end %-Open startup window, set window defaults %----------------------------------------------------------------------- @@ -333,7 +335,7 @@ case lower(Modalities) %-Initialise SPM in PET, fMRI, EEG modality local_clc; spm('AsciiWelcome'); fprintf('\n\nInitialising SPM'); Modality = upper(Action); fprintf('.'); -delete(get(0,'Children')); fprintf('.'); +spm_figure('close',allchild(0)); fprintf('.'); %-Load startup global defaults %----------------------------------------------------------------------- @@ -347,8 +349,8 @@ case lower(Modalities) %-Initialise SPM in PET, fMRI, EEG modality %-Draw SPM windows %----------------------------------------------------------------------- if ~spm('CmdLine') - Fmenu = spm('CreateMenuWin','off'); fprintf('.'); - Finter = spm('CreateIntWin','off'); fprintf('.'); + Fmenu = spm('CreateMenuWin','off'); fprintf('.'); + Finter = spm('CreateIntWin','off'); fprintf('.'); else Fmenu = []; Finter = []; @@ -416,49 +418,38 @@ case lower(Modalities) %-Initialise SPM in PET, fMRI, EEG modality end %======================================================================= -case 'defaults' %-Set SPM defaults (as global variables) +case 'defaults' %-Set SPM defaults (as global variable) %======================================================================= % spm('defaults',Modality) %----------------------------------------------------------------------- -global defaults -if isempty(defaults), spm_defaults; end - -%-Sort out arguments -%----------------------------------------------------------------------- if nargin<2, Modality=''; else Modality=varargin{2}; end -Modality = spm('CheckModality',Modality); -defaults.modality = Modality; -defaults.SWD = spm('Dir'); % SPM directory -defaults.TWD = spm_platform('tempdir'); % Temp directory +Modality = spm('CheckModality',Modality); -%-Set Modality specific default (global variables) +%-Re-initialise, load defaults (from spm_defaults.m) and store modality %----------------------------------------------------------------------- -global UFp -if strcmpi(defaults.modality,'pet') - UFp = defaults.stats.pet.ufp; % Upper tail F-prob -elseif strcmpi(defaults.modality,'fmri') - UFp = defaults.stats.fmri.ufp; % Upper tail F-prob -elseif strcmpi(defaults.modality,'eeg') - ; -elseif strcmpi(defaults.modality,'unknown') -else - error('Illegal Modality'); -end +clear global defaults +spm_get_defaults('modality',Modality); -%-Addpath (temporary solution) +%-Addpath modality-specific toolboxes %----------------------------------------------------------------------- -if strcmpi(defaults.modality,'EEG') && ~isdeployed +if strcmpi(Modality,'EEG') && ~isdeployed addpath(fullfile(spm('Dir'),'external','fieldtrip')); - addpath(fullfile(spm('Dir'),'external','fileio')); - addpath(fullfile(spm('Dir'),'external','forwinv')); + fieldtripdefs; addpath(fullfile(spm('Dir'),'external','bemcp')); addpath(fullfile(spm('Dir'),'external','ctf')); addpath(fullfile(spm('Dir'),'external','eeprobe')); + addpath(fullfile(spm('Dir'),'external','yokogawa')); addpath(fullfile(spm('Dir'),'toolbox', 'dcm_meeg')); + addpath(fullfile(spm('Dir'),'toolbox', 'spectral')); + addpath(fullfile(spm('Dir'),'toolbox', 'Neural_Models')); addpath(fullfile(spm('Dir'),'toolbox', 'Beamforming')); addpath(fullfile(spm('Dir'),'toolbox', 'MEEGtools')); end +%-Return defaults variable if asked +%----------------------------------------------------------------------- +if nargout, varargout = {spm_get_defaults}; end + %======================================================================= case 'checkmodality' %-Check & canonicalise modality string @@ -467,9 +458,9 @@ case lower(Modalities) %-Initialise SPM in PET, fMRI, EEG modality %----------------------------------------------------------------------- if nargin<2, Modality=''; else Modality=upper(varargin{2}); end if isempty(Modality) - global defaults - if isfield(defaults,'modality'), Modality = defaults.modality; - else Modality = 'UNKNOWN'; end + try + Modality = spm_get_defaults('modality'); + end end if ischar(Modality) ModNum = find(ismember(Modalities,Modality)); @@ -482,8 +473,13 @@ case lower(Modalities) %-Initialise SPM in PET, fMRI, EEG modality Modality = Modalities{ModNum}; end end - -if isempty(ModNum), error('Unknown Modality'), end +if isempty(ModNum) + if isempty(Modality) + fprintf('Modality is not set: use spm(''defaults'',''MOD''); '); + fprintf('where MOD is one of PET, FMRI, EEG.\n'); + end + error('Unknown Modality.'); +end varargout = {upper(Modality),ModNum}; @@ -607,9 +603,7 @@ case lower(Modalities) %-Initialise SPM in PET, fMRI, EEG modality if nargin<2, FS=1:36; else FS=varargin{2}; end offset = 1; -try - %if ismac, offset = 1.4; end -end +%try, if ismac, offset = 1.4; end; end sf = offset + 0.85*(min(spm('WinScale'))-1); @@ -692,12 +686,10 @@ case lower(Modalities) %-Initialise SPM in PET, fMRI, EEG modality %-Distribution livery varargout = {[0.8 0.8 1.0],'vile violet'}; -global defaults -if isempty(defaults), spm_defaults; end -if isfield(defaults,'ui') && isfield(defaults.ui,'colour2') - varargout{1} = defaults.ui.colour2; +try + varargout = {spm_get_defaults('ui.colour'),'bluish'}; end - + %======================================================================= case 'figname' %-Robust SPM figure naming @@ -725,9 +717,8 @@ case lower(Modalities) %-Initialise SPM in PET, fMRI, EEG modality cF = get(0,'CurrentFigure'); Fs = get(0,'Children'); Fs = findobj(Fs,'flat','Visible','on'); -for F=Fs', figure(F), end -set(0,'CurrentFigure',cF) -spm('FnBanner','GUI show'); +for F=Fs(:)', figure(F), end +try, figure(cF), set(0,'CurrentFigure',cF); end varargout={Fs}; @@ -804,13 +795,13 @@ case lower(Modalities) %-Initialise SPM in PET, fMRI, EEG modality end SPMdir = fileparts(SPMdir); -if isdeployed - ind = findstr(SPMdir,'_mcr')-1; - if ~isempty(ind) - % MATLAB 2008a/2009a doesn't need this - SPMdir = fileparts(SPMdir(1:ind(1))); - end -end +% if isdeployed +% ind = strfind(SPMdir,'_mcr')-1; +% if ~isempty(ind) +% % MATLAB 2008a/2009a doesn't need this +% SPMdir = fileparts(SPMdir(1:ind(1))); +% end +% end varargout = {SPMdir}; @@ -835,16 +826,18 @@ case lower(Modalities) %-Initialise SPM in PET, fMRI, EEG modality if isempty(Mfile) varargout = {v.Release v.Version}; else - fp = fopen(Mfile,'rt'); - if fp == -1, error('Can''t read %s.',Mfile); end - str = fread(fp,Inf,'*uchar'); - fclose(fp); - str = char(str(:)'); - r = regexp(str,['\$Id: (?\S+) (?[0-9]+) (?\S+) ' ... - '(\S+Z) (?\S+) \$'],'names','once'); - - if isempty(r) - r = struct('file',Mfile,'id','???','date','','author',''); + unknown = struct('file',Mfile,'id','???','date','','author',''); + if ~isdeployed + fp = fopen(Mfile,'rt'); + if fp == -1, error('Can''t read %s.',Mfile); end + str = fread(fp,Inf,'*uchar'); + fclose(fp); + str = char(str(:)'); + r = regexp(str,['\$Id: (?\S+) (?[0-9]+) (?\S+) ' ... + '(\S+Z) (?\S+) \$'],'names','once'); + if isempty(r), r = unknown; end + else + r = unknown; end varargout = {r(1).id v.Release}; end @@ -909,9 +902,9 @@ case lower(Modalities) %-Initialise SPM in PET, fMRI, EEG modality if i > 0 %-Addpath (& report) %------------------------------------------------------------------- - if isempty(findstr(xTB(i).dir,path)) + if isempty(strfind(path,xTB(i).dir)) if ~isdeployed, addpath(xTB(i).dir,'-begin'); end - spm('alert"',{'Toolbox directory prepended to Matlab path:',... + spm('alert"',{'Toolbox directory prepended to MATLAB path:',... xTB(i).dir},... [xTB(i).name,' toolbox'],1); end @@ -939,14 +932,14 @@ case lower(Modalities) %-Initialise SPM in PET, fMRI, EEG modality %======================================================================= -case {'cmdline'} %-SPM command line mode? +case 'cmdline' %-SPM command line mode? %======================================================================= % CmdLine = spm('CmdLine',CmdLine) %----------------------------------------------------------------------- -if nargin<2, CmdLine=[]; else CmdLine = varargin{2}; end +if nargin<2, CmdLine=[]; else CmdLine=varargin{2}; end if isempty(CmdLine) - global defaults - if ~isempty(defaults) && isfield(defaults,'cmdline') + defaults = spm('getglobal','defaults'); + if isfield(defaults,'cmdline') CmdLine = defaults.cmdline; else CmdLine = 0; @@ -1001,18 +994,12 @@ case lower(Modalities) %-Initialise SPM in PET, fMRI, EEG modality %======================================================================= % m = spm('Memory') %----------------------------------------------------------------------- -maxmemdef = 200*1024*1024; % 200 MB for all other platforms -if ispc - try - evalc('m=feature(''memstats'');'); - catch - m = maxmemdef; - end -else - m = maxmemdef; -end +maxmemdef = 200*1024*1024; % 200 MB +%m = spm_get_defaults('stats.maxmem'); +m = maxmemdef; varargout = {m}; + %======================================================================= case 'pointer' %-Set mouse pointer in all MATLAB windows %======================================================================= @@ -1022,8 +1009,6 @@ case lower(Modalities) %-Initialise SPM in PET, fMRI, EEG modality set(get(0,'Children'),'Pointer',Pointer) - - %======================================================================= case {'alert','alert"','alert*','alert!'} %-Alert dialogs %======================================================================= @@ -1133,7 +1118,7 @@ case lower(Modalities) %-Initialise SPM in PET, fMRI, EEG modality %======================================================================= % spm('Quit') %----------------------------------------------------------------------- -delete(get(0,'Children')); +spm_figure('close',allchild(0)); local_clc; fprintf('Bye for now...\n\n'); @@ -1160,29 +1145,27 @@ case lower(Modalities) %-Initialise SPM in PET, fMRI, EEG modality %======================================================================= persistent SPM_VER; v = SPM_VER; - -str = 'Can''t obtain SPM Revision information.'; - if isempty(SPM_VER) || (nargin > 0 && ReDo) - if isdeployed && ispc - % fake version (.m files compressed/pcoded/encrypted) - v.Name = 'Statistical Parametric Mapping'; - v.Version = '8'; - v.Release = 'SPM8'; - v.Date = date; - else - v = struct('Name','','Version','','Release','','Date',''); - try - fid = fopen(fullfile(spm('Dir'),'Contents.m'),'rt'); - if fid == -1, error(str); end - l1 = fgetl(fid); l2 = fgetl(fid); - fclose(fid); - l1 = strtrim(l1(2:end)); l2 = strtrim(l2(2:end)); - t = strread(l2,'%s','delimiter',' '); - v.Name = l1; v.Date = t{4}; - v.Version = t{2}; v.Release = t{3}(2:end-1); - catch - error(str); + v = struct('Name','','Version','','Release','','Date',''); + try + fid = fopen(fullfile(spm('Dir'),'Contents.m'),'rt'); + if fid == -1, error(str); end + l1 = fgetl(fid); l2 = fgetl(fid); + fclose(fid); + l1 = strtrim(l1(2:end)); l2 = strtrim(l2(2:end)); + t = textscan(l2,'%s','delimiter',' '); t = t{1}; + 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 end SPM_VER = v; diff --git a/spm_ADEM.m b/spm_ADEM.m index 1debcfd..2a7365c 100644 --- a/spm_ADEM.m +++ b/spm_ADEM.m @@ -37,6 +37,7 @@ % M(i).R = precision components (state noise) % M(i).V = fixed precision (input noise) % M(i).W = fixed precision (state noise) +% M(i).xP = precision (states) % % M(i).m = number of inputs v(i + 1); % M(i).n = number of states x(i) @@ -111,7 +112,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_ADEM.m 3655 2009-12-23 20:15:34Z karl $ +% $Id: spm_ADEM.m 3901 2010-05-27 16:14:36Z karl $ % check model, data, priors and unpack %-------------------------------------------------------------------------- @@ -140,8 +141,7 @@ %-------------------------------------------------------------------------- nY = size(C,2); % number of samples nl = size(M,2); % number of levels -nr = sum(spm_vec(M.l)); % number of v (outputs) -nv = sum(spm_vec(M.m)); % number of v (casual states) +nv = sum(spm_vec(M.m)); % number of v (causal states) nx = sum(spm_vec(M.n)); % number of x (hidden states) ny = M(1).l; % number of y (inputs) nc = M(end).l; % number of c (prior causes) @@ -149,14 +149,11 @@ % number of states and parameters - generative model %-------------------------------------------------------------------------- -gl = size(M,2); % number of levels gr = sum(spm_vec(G.l)); % number of v (outputs) gv = sum(spm_vec(G.m)); % number of v (causal states) ga = sum(spm_vec(G.k)); % number of a (active states) gx = sum(spm_vec(G.n)); % number of x (hidden states) gy = G(1).l; % number of y (inputs) -gc = G(end).l; % number of c (prior causes) -gu = gv*n + gx*n; % number of generalised states q(u) na = ga; % number of iterations @@ -203,14 +200,12 @@ Q0 = kron(iV,spm_cat(spm_diag({M.V}))); R0 = kron(iV,spm_cat(spm_diag({M.W}))); Qp = blkdiag(Q0,R0); -Q0 = kron(iV,speye(nv)); -R0 = kron(iV,speye(nx)); -Qu = blkdiag(Q0,R0); nh = length(Q); % number of hyperparameters % fixed priors on states (u) %-------------------------------------------------------------------------- -Px = kron(iV(1:n,1:n),speye(nx,nx)*exp(-8)); +xP = spm_cat(spm_diag({M.xP})); +Px = kron(iV(1:n,1:n),speye(nx,nx)*exp(-8) + xP); Pv = kron(iV(1:d,1:d),speye(nv,nv)*exp(-8)); Pa = kron(iV(1:1,1:1),speye(na,na)*exp(-8)); Pu = spm_cat(spm_diag({Px Pv})); @@ -218,10 +213,10 @@ % hyperpriors %-------------------------------------------------------------------------- ph.h = spm_vec({M.hE M.gE}); % prior expectation of h -ph.c = spm_cat(spm_diag({M.hC M.gC})); % prior covariances of h +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 = inv(ph.c); % prior precision +ph.ic = spm_inv(ph.c); % prior precision % priors on parameters (in reduced parameter space) %========================================================================== @@ -249,7 +244,7 @@ %-------------------------------------------------------------------------- np = sum(spm_vec(M.p)); % number of model parameters pp.c = spm_cat(pp.c); -pp.ic = inv(pp.c); +pp.ic = spm_inv(pp.c); % initialise conditional density q(p) (for D-Step) %-------------------------------------------------------------------------- @@ -301,6 +296,15 @@ Dp = spm_cat(spm_diag({Dv,Dx,Dv,Dx})); dfdw = kron(speye(n,n),speye(gx,gx)); dydv = kron(speye(n,n),speye(gy,gr)); + +% reistiction matrix, mapping prediction errors to action +%-------------------------------------------------------------------------- +try + Ra = M(1).Ra; +catch + Ra = 1:ny; +end +Ra = kron(speye(n,n),sparse(Ra,Ra,1,ny,ny)); % and null blocks %-------------------------------------------------------------------------- @@ -309,13 +313,11 @@ % gradients and curvatures for conditional uncertainty %-------------------------------------------------------------------------- dWdu = sparse(nu,1); -dWdp = sparse(np,1); dWduu = sparse(nu,nu); -dWdpp = sparse(np,np); - + % preclude unnecessary iterations %-------------------------------------------------------------------------- -if ~(np + nh), nE = 1; end +if ~np && ~nh, nE = 1; end % create innovations (and add causes) @@ -371,13 +373,13 @@ % derivatives of responses and inputs %------------------------------------------------------------------ - pu.z = spm_DEM_embed(Z,n,iY); - pu.w = spm_DEM_embed(W,n,iY); - qu.u = spm_DEM_embed(U,n,iY); + pu.z = spm_DEM_embed(Z,n,iY); + pu.w = spm_DEM_embed(W,n,iY); + qu.u = spm_DEM_embed(U,n,iY); % pass action to pu.a %------------------------------------------------------------------ - pu.a = qu.a; + pu.a = qu.a; % evaluate generative model %------------------------------------------------------------------ @@ -445,7 +447,9 @@ dyda = dyda + dydx*Dfdx*dfda; end - dE.da = dE.dy*dyda; + % dE/da with restriction + %------------------------------------------------------------------ + dE.da = dE.dy*Ra*dyda; dE.dv = dE.dy*dydv; % first-order derivatives @@ -474,7 +478,7 @@ %------------------------------------------------------------------ p = {pu.v{1:n} pu.x{1:n} pu.z{1:n} pu.w{1:n}}; q = {qu.x{1:n} qu.v{1:d} qu.u{1:d} qu.a{1:1}}; - u = {p{:} q{:}}; + u = [p q]; % gradient %------------------------------------------------------------------ @@ -514,8 +518,8 @@ CJu(:,i) = spm_vec(qu.c*dE.dup{i}'*iS); dEdup(:,i) = spm_vec(dE.dup{i}'); end - dWdp = CJu'*spm_vec(dE.du'); - dWdpp = CJu'*dEdup; + dWdp = CJu'*spm_vec(dE.du'); + dWdpp = CJu'*dEdup; % Accumulate; dF/dP =
, dF/dpp = ... %-------------------------------------------------------------- @@ -527,8 +531,8 @@ % and quantities for M-Step %------------------------------------------------------------------ - EE = E*E'+ EE; - ECE = ECE + ECEu + ECEp; + EE = E*E'+ EE; + ECE = ECE + ECEu + ECEp; end % sequence (nY) @@ -537,7 +541,7 @@ dFdp = dFdp - pp.ic*qp.e; dFdpp = dFdpp - pp.ic; qp.ic = qp.ic + pp.ic; - qp.c = inv(qp.ic); + qp.c = spm_inv(qp.ic); % E-step: update expectation (p) @@ -595,7 +599,7 @@ % conditional covariance of hyperparameters %------------------------------------------------------------------ - qh.c = -inv(dFdhh); + qh.c = -spm_inv(dFdhh); % convergence (M-Step) %------------------------------------------------------------------ @@ -648,22 +652,22 @@ %-------------------------------------------------------------- v = spm_unvec(qU(t).v{1},{M(1 + 1:end).v}); x = spm_unvec(qU(t).x{1},{M(1:end - 1).x}); - z = spm_unvec(qE{t},{M.v}); + 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) - QU.v{i + 1}(:,t) = spm_vec(v{i}); - try - QU.x{i}(:,t) = spm_vec(x{i}); - end - QU.z{i}(:,t) = spm_vec(z{i}); + if M(i).m, QU.v{i + 1}(:,t) = spm_vec(v{i}); end + if M(i).l, QU.z{i}(:,t) = spm_vec(z{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 end - QU.v{1}(:,t) = spm_vec(qU(t).y{1}) - spm_vec(z{1}); - QU.z{nl}(:,t) = spm_vec(z{nl}); + QU.v{1}(:,t) = spm_vec(qU(t).y{1}) - spm_vec(z{1}); + QU.z{nl}(:,t) = spm_vec(z{nl}); % and conditional covariances %-------------------------------------------------------------- - i = [1:nx]; + i = (1:nx); QU.S{t} = qC{t}(i,i); - i = [1:nv] + nx*n; + i = (1:nv) + nx*n; QU.C{t} = qC{t}(i,i); end diff --git a/spm_ADEM_set.m b/spm_ADEM_set.m index 3f55888..834fca3 100644 --- a/spm_ADEM_set.m +++ b/spm_ADEM_set.m @@ -4,13 +4,13 @@ % % DEM.G - generative model % DEM.M - recognition model -% DEM.C - causes -% DEM.U - explanatory variables, inputs or prior expectation of causes +% DEM.C - exogenous causes +% DEM.U - prior expectation of causes %__________________________________________________________________________ % Copyright (C) 2005 Wellcome Department of Imaging Neuroscience % Karl Friston -% $Id: spm_ADEM_set.m 2521 2008-12-02 19:49:39Z karl $ +% $Id: spm_ADEM_set.m 3893 2010-05-17 18:28:52Z karl $ % check recognition model % ------------------------------------------------------------------------- @@ -30,7 +30,7 @@ try N = length(DEM.C); catch - errordlg('please specify causes') + errordlg('please specify causes (e.g., sparse(1,N)') end try DEM.class; @@ -38,6 +38,11 @@ DEM.class = 'active'; end +% Default priors +% ------------------------------------------------------------------------- +if ~isfield(DEM,'U') + DEM.U = sparse(DEM.M(end).l,N); +end % transpose causes and confounds, if specified in conventional fashion %-------------------------------------------------------------------------- @@ -45,39 +50,25 @@ try, if size(DEM.C,2) < N, DEM.C = DEM.C'; end, end -% ensure model and data dimensions check +% ensure model and input dimensions check % ------------------------------------------------------------------------- -if DEM.G(1).l ~= DEM.M(1).l - errordlg('models are incompatible in terms of data') -end if size(DEM.C,1) ~= DEM.G(end).l - errordlg('DEM.G and causes (C) are incompatible') + errordlg('model (G) and causes (C) are incompatible') end - -% Default priors and confounds -% ------------------------------------------------------------------------- -n = DEM.M(end).l; -if ~isfield(DEM,'U') - DEM.U = sparse(n,N); +if size(DEM.U,1) ~= DEM.M(end).l + errordlg('model (M) and priors (U) are incompatible') end - - % check prior expectation of causes (at level n) and confounds %-------------------------------------------------------------------------- -if ~nnz(DEM.U), DEM.U = sparse(n,N); end -if ~nnz(DEM.C), DEM.C = sparse(n,N); end - -% ensure inputs and cause dimensions check -% ------------------------------------------------------------------------- -if size(DEM.U,1) ~= DEM.M(end).l - errordlg('DEM.M and priors (U) are incompatible') -end +if ~nnz(DEM.U), DEM.U = sparse(DEM.M(end).l,N); end +if ~nnz(DEM.C), DEM.C = sparse(DEM.G(end).l,N); end + % ensure causes and data dimensions check % ------------------------------------------------------------------------- if size(DEM.U,2) < N - errordlg('priors and data have different lengths') + errordlg('priors (U) and causes (C) have different lengths') end % check length of time-series diff --git a/spm_ADEM_update.m b/spm_ADEM_update.m new file mode 100644 index 0000000..565edad --- /dev/null +++ b/spm_ADEM_update.m @@ -0,0 +1,28 @@ +function [DEM] = spm_ADEM_update(DEM) +% Updates ADEM structure using conditional expectations +% FORMAT [DEM] = spm_ADEM_update(DEM) +%___________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: spm_ADEM_update.m 3758 2010-03-08 11:47:24Z guillaume $ + +% update states and action +%-------------------------------------------------------------------------- +n = length(DEM.M); +for i = 1:(n - 1) + DEM.M(i).x = spm_unvec(DEM.qU.x{i}(:,end),DEM.M(i).x); + DEM.M(i).pE = spm_unvec(DEM.qP.P{i},DEM.M(i).pE); +end +for i = 1:n + DEM.M(i).v = spm_unvec(DEM.qU.v{i}(:,end),DEM.M(i).v); +end + +n = length(DEM.G); +for i = 1:(n - 1) + DEM.G(i).x = spm_unvec(DEM.pU.x{i}(:,end),DEM.G(i).x); +end +for i = 1:n + DEM.G(i).v = spm_unvec(DEM.pU.v{i}(:,end),DEM.G(i).v); +end +DEM.G(n).a = spm_unvec(DEM.qU.a{n}(:,end),DEM.G(n).a); diff --git a/spm_DEM.m b/spm_DEM.m index a68334b..9960879 100644 --- a/spm_DEM.m +++ b/spm_DEM.m @@ -19,11 +19,11 @@ % M(i).hC = prior covariances of h log-precision (cause noise) % M(i).gE = prior expectation of g log-precision (state noise) % M(i).gC = prior covariances of g log-precision (state noise) -% M(i).xP = precision (states) % M(i).Q = precision components (input noise) % M(i).R = precision components (state noise) % M(i).V = fixed precision (input noise) % M(i).W = fixed precision (state noise) +% M(i).xP = precision (states) % % M(i).m = number of inputs v(i + 1); % M(i).n = number of states x(i); @@ -79,7 +79,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_DEM.m 3655 2009-12-23 20:15:34Z karl $ +% $Id: spm_DEM.m 3977 2010-07-08 14:14:35Z karl $ % check model, data, priors and confounds and unpack %-------------------------------------------------------------------------- @@ -189,8 +189,8 @@ % fixed priors on states (u) %-------------------------------------------------------------------------- xP = spm_cat(spm_diag({M.xP})); -Px = kron(spm_DEM_R(n,1),xP); -Pv = kron(spm_DEM_R(d,1),sparse(nv,nv)); +Px = kron(spm_DEM_R(n,0),xP); +Pv = kron(spm_DEM_R(d,0),sparse(nv,nv)); Pu = spm_cat(spm_diag({Px Pv})); Pu = Pu + speye(nu,nu)*nu*eps; @@ -210,7 +210,7 @@ % eigenvector reduction: p <- pE + qp.u*qp.p %---------------------------------------------------------------------- - qp.u{i} = spm_svd(M(i).pC); % basis for parameters + 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 @@ -227,7 +227,7 @@ ip = [1:np]; ib = [1:nn] + np; pp.c = spm_cat(pp.c); -pp.ic = spm_pinv(pp.c); +pp.ic = spm_inv(pp.c); % initialise conditional density q(p) (for D-Step) %-------------------------------------------------------------------------- @@ -309,7 +309,7 @@ % Iterate DEM %========================================================================== -Fm = -Inf; +Fi = -Inf; for iN = 1:nN % get time and celar persistent variables in evaluation routines @@ -325,14 +325,13 @@ % [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); - qu_c = speye(1); - - + % [re-]set precisions using ReML hyperparameter estimates %------------------------------------------------------------------ iS = Qp; @@ -371,9 +370,14 @@ % derivatives of responses and inputs %---------------------------------------------------------- - qu.y(1:n) = spm_DEM_embed(Y,n,ts); - qu.u(1:d) = spm_DEM_embed(U,d,ts); - + 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); @@ -391,8 +395,8 @@ %---------------------------------------------------------- qu.p = dE.du'*iS*dE.du + Pu; qu.c = spm_inv(qu.p); - qu_c = qu_c*qu.c; - + spm_logdet_qu_c = spm_logdet_qu_c + spm_logdet(qu.c); + % and conditional covariance [of parameters {P}] %---------------------------------------------------------- dE.dP = spm_cat({dE.dp dEdb}); @@ -409,7 +413,7 @@ % if F is increasing, save expansion point %------------------------------------------------------ if L > Fd - td = {min(td{1} + 1,16)}; + td = {min(td{1} + 1,+8)}; Fd = L; B.qu = qu; B.E = E; @@ -424,7 +428,7 @@ E = B.E; dE = B.dE; ECEp = B.ECEp; - td = {min(td{1} - 1,0)}; + td = {min(td{1} - 2,-4)}; end end @@ -475,11 +479,13 @@ dFduu = spm_cat({dVduu dVduy dVduc ; [] dVdyy [] ; [] [] dVdcc}); - - + + % update conditional modes of states %========================================================== - du = spm_dx(K*dFduu + D,K*dFdu + D*u,td); + f = K*dFdu + D*u; + dfdu = K*dFduu + D; + du = spm_dx(dfdu,f,td); q = spm_unvec(u + du,q); % and save them @@ -553,7 +559,7 @@ if L > Fe || iN == 1 Fe = L; - te = min(te + 1,8); + te = min(te + 1,+8); B.dFdp = dFdp; B.dFdpp = dFdpp; B.qp = qp; @@ -567,7 +573,7 @@ dFdpp = B.dFdpp; qp = B.qp; mp = B.mp; - te = min(te - 1,0); + te = min(te - 2,-4); end % E-step: update expectation (p) @@ -607,8 +613,8 @@ % 1st-order derivatives: dFdh = dF/dh %------------------------------------------------------------------ for i = 1:nh - dPdh{i} = Q{i}*exp(qh.h(i)); - dFdh(i,1) = -trace(dPdh{i}*dS)/2; + dPdh{i} = Q{i}*exp(qh.h(i)); + dFdh(i,1) = -trace(dPdh{i}*dS)/2; end % 2nd-order derivatives: dFdhh @@ -643,25 +649,35 @@ % evaluate objective function (F) %====================================================================== - L = - trace(iS*EE)/2 ... % states (u) - - trace(qp.e'*pp.ic*qp.e)/2 ... % parameters (p) - - trace(qh.e'*ph.ic*qh.e)/2 ... % hyperparameters (h) - + spm_logdet(qu_c)/(2*nD) ... % entropy q(u) - + 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 - + spm_logdet(iS)*nY/2 ... % entropy - error - - n*ny*nY*log(2*pi)/2; - + 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 %---------------------------------------------------------------------- - if L > (Fm + 1e-2) || mp'*mp > TOL || mh'*mh > TOL + if Li > Fi || iN < 3 - Fm = L; - F(iN) = Fm; + Fi = Li; + F(iN) = Fi; + A(iN) = Ai; % save model-states (for each time point) %================================================================== @@ -698,24 +714,27 @@ figure(Fdem) spm_DEM_qU(QU) if np - subplot(nl,4,4*nl) + subplot(2*nl,2,4*nl) bar(full(Up*qp.e)) - xlabel({'parameters';'{minus prior}'}) - axis square, grid on + 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(nl,4,4*nl - 1) + subplot(2*nl,4,8*nl - 5) plot(F - F(1)) xlabel('updates') - title('log-evidence') - axis square, grid on + title('free-energy') end drawnow % report (EM-Steps) %------------------------------------------------------------------ str{1} = sprintf('DEM: %i (%i:%i:%i)',iN,iD,iE,iM); - str{2} = sprintf('F:%.4e',full(Fm - F(1))); + 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)); @@ -763,3 +782,4 @@ DEM.qH = qH; % conditional moments of hyper-parameters DEM.F = F; % [-ve] Free energy +DEM.S = A; % [-ve] Free action diff --git a/spm_DEM_M_set.m b/spm_DEM_M_set.m index 825b766..19d4942 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 3655 2009-12-23 20:15:34Z karl $ +% $Id: spm_DEM_M_set.m 3733 2010-02-18 17:43:18Z karl $ % order %-------------------------------------------------------------------------- @@ -124,24 +124,34 @@ % check pC if user specified %-------------------------------------------------------------------------- for i = 1:g + + % number of parameters + %---------------------------------------------------------------------- + np = length(spm_vec(M(i).pE)); % Assume fixed parameters if not specified %---------------------------------------------------------------------- if isempty(M(i).pC) - p = length(spm_vec(M(i).pE)); - M(i).pC = sparse(p,p); + M(i).pC = sparse(np,np); end % convert variances to covariances if necessary %---------------------------------------------------------------------- - if length(M(i).pC) == 1 + if isvector(M(i).pC) M(i).pC = sparse(diag(M(i).pC)); end + + % convert variance to covariances if necessary + %---------------------------------------------------------------------- + if isscalar(M(i).pC) + M(i).pC = speye(np,np)*M(i).pC; + end % check size %---------------------------------------------------------------------- - if length(M(i).pC) ~= length(spm_vec(M(i).pE)) - errordlg(sprintf('please check: M(%i).pC',i)) + if length(M(i).pC) ~= np + warndlg(sprintf('please check: M(%i).pC',i)) + who,keyboard end end @@ -188,11 +198,13 @@ try f = feval(M(i).f,x,v,M(i).pE); if length(spm_vec(x)) ~= length(spm_vec(f)) - errordlg(sprintf('please check: M(%i).f(x,v,P)',i)); + warndlg(sprintf('please check: M(%i).f(x,v,P)',i)); + who,keyboard end catch - errordlg(sprintf('evaluation failure: M(%i).f(x,v,P)',i)) + 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 @@ -214,7 +226,8 @@ M(i).x = x; catch - errordlg(sprintf('evaluation failure: M(%i).g(x,v,P)',i)) + 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 @@ -224,18 +237,19 @@ % priors on states %-------------------------------------------------------------------------- +try + M.xP; +catch + M(1).xP = []; +end for i = 1:g - if isfield(M(i),'xP') - if size(M(i).xP) == [1 1]; - M(i).xP = speye(M(i).n,M(i).n)*M(i).xP; - elseif any(size(M(i).xP) ~= [M(i).n M(i).n]); - errordlg(sprintf('please Check: M(%i).xP',i)) - end - else - for j = 1:g - M(j).xP = sparse(M(j).n,M(j).n); - end - break + if size(M(i).xP) == [1 1]; + M(i).xP = speye(M(i).n,M(i).n)*M(i).xP; + elseif isempty(M(i).xP) + 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 @@ -252,6 +266,8 @@ try, M.W; catch, M(1).W = []; end try, M.hE; catch, M(1).hE = []; end try, M.gE; catch, M(1).gE = []; end +try, M.ph; catch, M(1).ph = []; end +try, M.pg; catch, M(1).pg = []; end % check hyperpriors hE - [log]hyper-parameters and components %-------------------------------------------------------------------------- @@ -278,11 +294,11 @@ % check hyperpriors (covariances) %---------------------------------------------------------------------- - try, M(i).hC*M(i).hE; catch, M(i).hC = speye(length(M(i).hE))*256; end - try, M(i).gC*M(i).gE; catch, M(i).gC = speye(length(M(i).gE))*256; end + 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 - if isempty(M(i).hC), M(i).hC = speye(length(M(i).hE))*256; end - if isempty(M(i).gC), M(i).gC = speye(length(M(i).gE))*256; 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 % check Q and R (precision components) %====================================================================== @@ -291,25 +307,32 @@ % check components and assume i.i.d if not specified %---------------------------------------------------------------------- if length(M(i).Q) > length(M(i).hE) - M(i).hE = sparse(length(M(i).Q),1); + M(i).hE = sparse(length(M(i).Q),1) + M(i).hE(1); end if length(M(i).Q) < length(M(i).hE) M(i).Q = {speye(M(i).l,M(i).l)}; M(i).hE = M(i).hE(1); end + if length(M(i).hE) > length(M(i).hC) + M(i).hC = speye(length(M(i).Q))*M(i).hC(1); + end if length(M(i).R) > length(M(i).gE) - M(i).gE = sparse(length(M(i).R),1); + M(i).gE = sparse(length(M(i).R),1) + M(i).gE(1); end if length(M(i).R) < length(M(i).gE) M(i).R = {speye(M(i).n,M(i).n)}; M(i).gE = M(i).gE(1); end + if length(M(i).gE) > length(M(i).gC) + M(i).gC = speye(length(M(i).R))*M(i).gC(1); + end % check consistency and sizes (Q) %---------------------------------------------------------------------- for j = 1:length(M(i).Q) if length(M(i).Q{j}) ~= M(i).l - errordlg(sprintf('wrong size; M(%d).Q{%d}',i,j)) + warndlg(sprintf('wrong size; M(%d).Q{%d}',i,j)) + who,keyboard end end @@ -317,7 +340,8 @@ %---------------------------------------------------------------------- for j = 1:length(M(i).R) if length(M(i).R{j}) ~= M(i).n - errordlg(sprintf('wrong size; M(%d).R{%d}',i,j)) + warndlg(sprintf('wrong size; M(%d).R{%d}',i,j)) + who,keyboard end end @@ -330,7 +354,7 @@ try M(i).V = speye(M(i).l,M(i).l)*M(i).V(1); catch - if isempty(M(i).hE) + if isempty(M(i).hE) && isempty(M(i).ph) M(i).V = speye(M(i).l,M(i).l); else M(i).V = sparse(M(i).l,M(i).l); @@ -345,7 +369,7 @@ try M(i).W = speye(M(i).n,M(i).n)*M(i).W(1); catch - if isempty(M(i).gE) + if isempty(M(i).gE) && isempty(M(i).pg) M(i).W = speye(M(i).n,M(i).n); else M(i).W = sparse(M(i).n,M(i).n); @@ -387,6 +411,8 @@ % checks on smoothness hyperparameter %========================================================================== +try, M = rmfield(M,'sv'); end +try, M = rmfield(M,'sw'); end for i = 1:g try, M(i).sv; catch, M(i).sv = M(1).E.s; end @@ -396,6 +422,13 @@ if ~isscalar(M(i).sw), M(i).sw = M(1).E.s; end end +% check on linear approximation scheme +%========================================================================== +try + M(1).E.linear; +catch + M(1).E.linear = 0; +end % checks on estimability %========================================================================== diff --git a/spm_DEM_R.m b/spm_DEM_R.m index 7654005..4b3a7ef 100644 --- a/spm_DEM_R.m +++ b/spm_DEM_R.m @@ -1,10 +1,9 @@ -function [R,V,D] = spm_DEM_R(n,s,dt,form) +function [R,V,D] = 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,dt,form) +% FORMAT [R,V,D] = spm_DEM_R(n,s,form) %__________________________________________________________________________ % n - truncation order % s - temporal smoothness - s.d. of kernel {bins} -% dt - bin interval (seconds) [default 1] % form - 'Gaussian', '1/f' [default: 'Gaussian'] % % e[:] <- E*e(0) @@ -20,13 +19,13 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_DEM_R.m 2921 2009-03-23 17:59:50Z guillaume $ +% $Id: spm_DEM_R.m 3878 2010-05-07 19:53:54Z karl $ % if no serial dependencies %-------------------------------------------------------------------------- if ~n, R = sparse(0,0); V = R; return, end if isempty(s), R = sparse(n,n); V = R; return, end -if ~s, s = exp(-16); end +if ~s, s = exp(-8); end @@ -53,7 +52,7 @@ end -% create coavraince matrix in generlised coordinates +% create covariance matrix in generalised coordinates %========================================================================== V = []; for i = 1:n; @@ -63,7 +62,7 @@ % and precision - R %-------------------------------------------------------------------------- -sw = warning('off','MATLAB:nearlySingularMatrix'); +sw = warning('off','MATLAB:nearlySingularMatrix'); R = inv(V); warning(sw); @@ -73,9 +72,9 @@ % Inverse embedding operator (D): c.f., a Taylor expansion Y(t) <- D*y[:] %-------------------------------------------------------------------------- -try, dt; catch, dt = 1; end - +dt = 1; x = fix((n + 1)/2); +t = ([1:n] - x)*dt; for i = 1:n for j = 1:n D(i,j) = ((i - x)*dt)^(j - 1)/prod(1:(j - 1)); @@ -84,27 +83,13 @@ % graphics %========================================================================== - -% embedding operator: y[:] <- E*Y(t): Graphics -%-------------------------------------------------------------------------- -t = ([1:n] - x)*dt; subplot(2,2,1) -imagesc(V) -axis square -title({'covariance';'derivatives'}) - -subplot(2,2,2) -imagesc(t,t,D*V*D') -axis square -title({'covariance';'time (secs)'}) - -subplot(2,2,3) imagesc(R) axis square title({'precision';'derivatives'}) -subplot(2,2,4) -imagesc(t,t,inv(D*V*D')) +subplot(2,2,2) +imagesc(t,t,spm_inv(D*V*D')) axis square title({'precision';'time (secs)'}) diff --git a/spm_DEM_embed.m b/spm_DEM_embed.m index d8632fa..6782fd1 100644 --- a/spm_DEM_embed.m +++ b/spm_DEM_embed.m @@ -1,22 +1,24 @@ -function [y] = spm_DEM_embed(Y,n,t,dt) +function [y] = spm_DEM_embed(Y,n,t,dt,d) % temporal embedding into derivatives -% FORMAT [y] = spm_DEM_embed(Y,n,t,dt) +% FORMAT [y] = spm_DEM_embed(Y,n,t,dt,d) %__________________________________________________________________________ % Y - (v x N) matrix of v time-series of length N % n - order of temporal embedding -% t - time {secs} at which to evaluate derivatives (starting at t = 1) +% t - time {bins} at which to evaluate derivatives (starting at t = 1) % dt - sampling interval {secs} [default = 1] +% d - delay (bins) for each row of Y % % y - {n,1}(v x 1) temporal derivatives y[:] <- E*Y(t) %========================================================================== % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_DEM_embed.m 1880 2008-07-02 12:41:41Z karl $ +% $Id: spm_DEM_embed.m 3695 2010-01-22 14:18:14Z karl $ % defaults %-------------------------------------------------------------------------- if nargin < 4, dt = 1; end +if nargin < 5, d = 0; end % get dimensions %-------------------------------------------------------------------------- @@ -27,32 +29,44 @@ % return if ~q %-------------------------------------------------------------------------- if ~q, return, end - -% boundary conditions + +% loop over channels %-------------------------------------------------------------------------- -t = t/dt; -k = [1:n] + fix(t - (n + 1)/2); -x = t - min(k) + 1; -i = k < 1; -k = k.*~i + i; -i = k > N; -k = k.*~i + i*N; +for p = 1:length(d) + % boundary conditions + %---------------------------------------------------------------------- + s = (t - d(p))/dt; + k = [1:n] + fix(s - (n + 1)/2); + x = s - min(k) + 1; + i = k < 1; + k = k.*~i + i; + i = k > N; + k = k.*~i + i*N; -% Inverse embedding operator (T): c.f., a Taylor expansion Y(t) <- T*y[:] -%-------------------------------------------------------------------------- -for i = 1:n - for j = 1:n - T(i,j) = ((i - x)*dt)^(j - 1)/prod(1:(j - 1)); + + % Inverse embedding operator (T): cf, Taylor expansion Y(t) <- T*y[:] + %---------------------------------------------------------------------- + for i = 1:n + for j = 1:n + T(i,j) = ((i - x)*dt)^(j - 1)/prod(1:(j - 1)); + end end -end -% embedding operator: y[:] <- E*Y(t) -%-------------------------------------------------------------------------- -E = inv(T); - -% embed -%-------------------------------------------------------------------------- -for i = 1:n - y{i} = Y(:,k)*E(i,:)'; + % embedding operator: y[:] <- E*Y(t) + %---------------------------------------------------------------------- + E = inv(T); + + % embed + %---------------------------------------------------------------------- + if length(d) == q + for i = 1:n + y{i}(p,:) = Y(p,k)*E(i,:)'; + end + else + for i = 1:n + y{i} = Y(:,k)*E(i,:)'; + end + return + end end diff --git a/spm_DEM_eval.m b/spm_DEM_eval.m index a02b7bb..4ea1bb4 100644 --- a/spm_DEM_eval.m +++ b/spm_DEM_eval.m @@ -28,7 +28,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_DEM_eval.m 3655 2009-12-23 20:15:34Z karl $ +% $Id: spm_DEM_eval.m 3695 2010-01-22 14:18:14Z karl $ % get dimensions @@ -40,12 +40,7 @@ np = sum(spm_vec(M.p)); % number of p (parameters) ny = M(1).l; % number of y (inputs) nc = M(end).l; % number of c (prior causes) - - -% order parameters (d = n = 1 for static models) -%-------------------------------------------------------------------------- -d = M(1).E.d + 1; % generalisation order of q(v) -n = M(1).E.n + 1; % embedding order (n >= d) + % evaluate functions at each hierarchical level %========================================================================== @@ -65,22 +60,16 @@ %========================================================================== persistent D try - if M(1).E.linear == 1 - method = 'linear'; - elseif M(1).E.linear == 2 - method = 'bilinear'; - else - method = 'full'; - end + method = M(1).E.linear; catch - method = 'full'; + method = 0; end - -switch lower(method) + +switch method - % get derivatives at each iteration of D-step + % get derivatives at each iteration of D-step - full evaluation %---------------------------------------------------------------------- - case{'full'} + case{0} D = spm_DEM_eval_diff(x,v,qp,M); @@ -104,8 +93,9 @@ dgdp = D.dgdp; dfdp = D.dfdp; - - case{'linear'} + % linear: assume equations are linear in x and v + %---------------------------------------------------------------------- + case{1} % get derivatives and store expansion point (states) %------------------------------------------------------------------ @@ -165,12 +155,109 @@ dfdp = D.dfdp; for p = 1:np dgdp(:,p) = D.dgdp(:,p) + D.dgdxp{p}*dx + D.dgdvp{p}*dv; - dfdp(:,p) = D.dfdp(:,p) + D.dfdxp{p}*dx + D.dfdvp{p}*dv; + if nx + dfdp(:,p) = D.dfdp(:,p) + D.dfdxp{p}*dx + D.dfdvp{p}*dv; + end + end + + end + + % bilinear: assume equations are linear in x and v and x*v + %---------------------------------------------------------------------- + case{2} + + % get derivatives and store expansion point (states) + %------------------------------------------------------------------ + if isempty(D) + + % get high-order derivatives + %-------------------------------------------------------------- + [Dv D] = spm_diff('spm_DEM_eval_diff',x,v,qp,M,2); + + for i = 1:nv, Dv{i} = spm_unvec(Dv{i},D); end + D.x = x; + D.v = v; + D.Dv = Dv; + + % gradients w.r.t. states + %-------------------------------------------------------------- + dedy = D.dedy; + dedc = D.dedc; + dfdy = D.dfdy; + dfdc = D.dfdc; + dgdx = D.dgdx; + dgdv = D.dgdv; + dfdv = D.dfdv; + dfdx = D.dfdx; + dgdxp = D.dgdxp; + dfdxp = D.dfdxp; + dgdvp = D.dgdvp; + dfdvp = D.dfdvp; + + % gradients w.r.t. parameters + %-------------------------------------------------------------- + dgdp = D.dgdp; + dfdp = D.dfdp; + + % linear expansion for derivatives w.r.t. parameters + %------------------------------------------------------------------ + else + + % gradients w.r.t. causes and data + %-------------------------------------------------------------- + dedy = D.dedy; + dedc = D.dedc; + dfdy = D.dfdy; + dfdc = D.dfdc; + + % states (relative to expansion point) + %-------------------------------------------------------------- + dv = spm_vec(qu.v{1}) - spm_vec(D.v); + + % gradients w.r.t. states + %-------------------------------------------------------------- + dgdx = D.dgdx; + dgdv = D.dgdv; + dfdx = D.dfdx; + dfdv = D.dfdv; + for i = 1:nv; dgdx = dgdx + D.Dv{i}.dgdx*dv(i); end + for i = 1:nv; dgdv = dgdv + D.Dv{i}.dgdv*dv(i); end + for i = 1:nv; dfdx = dfdx + D.Dv{i}.dfdx*dv(i); end + for i = 1:nv; dfdv = dfdv + D.Dv{i}.dfdv*dv(i); end + + + % second-order derivatives + %-------------------------------------------------------------- + dgdxp = D.dgdxp; + dgdvp = D.dgdvp; + dfdxp = D.dfdxp; + dfdvp = D.dfdvp; + for p = 1:np + for i = 1:nv; dgdxp{p} = dgdxp{p} + D.Dv{i}.dgdxp{p}*dv(i); end + for i = 1:nv; dgdvp{p} = dgdvp{p} + D.Dv{i}.dgdvp{p}*dv(i); end + for i = 1:nv; dfdxp{p} = dfdxp{p} + D.Dv{i}.dfdxp{p}*dv(i); end + for i = 1:nv; dfdvp{p} = dfdvp{p} + D.Dv{i}.dfdvp{p}*dv(i); end + end + + + % gradients w.r.t. parameters + %-------------------------------------------------------------- + dgdp = D.dgdp; + dfdp = D.dfdp; + for p = 1:np + Dgdxp = (D.dgdxp{p} + dgdxp{p})/2; + Dgdvp = (D.dgdvp{p} + dgdvp{p})/2; + Dfdxp = (D.dfdxp{p} + dfdxp{p})/2; + Dfdvp = (D.dfdvp{p} + dfdvp{p})/2; + dgdp(:,p) = dgdp(:,p) + Dgdvp*dv; + dfdp(:,p) = dfdp(:,p) + Dfdvp*dv; end end - case{'bilinear'} + % nonlinear: assume equations are bilinear in x and v + %---------------------------------------------------------------------- + case{3} % get derivatives and store expansion point (states) %------------------------------------------------------------------ @@ -272,13 +359,98 @@ end end + + % repeated evaluation of first order derivatives (for Laplace scheme) + %---------------------------------------------------------------------- + case{4} + + % get derivatives and store expansion point (states) + %------------------------------------------------------------------ + if isempty(D) + + D = spm_DEM_eval_diff(x,v,qp,M); + D.x = x; + D.v = v; + + % gradients w.r.t. states + %-------------------------------------------------------------- + dedy = D.dedy; + dedc = D.dedc; + dfdy = D.dfdy; + dfdc = D.dfdc; + dgdx = D.dgdx; + dgdv = D.dgdv; + dfdv = D.dfdv; + dfdx = D.dfdx; + + % gradients w.r.t. parameters (state-dependent) + %-------------------------------------------------------------- + dgdxp = D.dgdxp; + dfdxp = D.dfdxp; + dgdvp = D.dgdvp; + dfdvp = D.dfdvp; + + % gradients w.r.t. parameters + %-------------------------------------------------------------- + dgdp = D.dgdp; + dfdp = D.dfdp; + + % re-evaluate first-order derivatives + %------------------------------------------------------------------ + else + + % retain second-order gradients + %-------------------------------------------------------------- + dgdxp = D.dgdxp; + dfdxp = D.dfdxp; + dgdvp = D.dgdvp; + dfdvp = D.dfdvp; + + % re-evaluate first-order gradients + %-------------------------------------------------------------- + D = spm_DEM_eval_diff(x,v,qp,M,0); + dedy = D.dedy; + dedc = D.dedc; + dfdy = D.dfdy; + dfdc = D.dfdc; + dgdx = D.dgdx; + dgdv = D.dgdv; + dfdv = D.dfdv; + dfdx = D.dfdx; + + % replace second-order gradients + %-------------------------------------------------------------- + D.dgdxp = dgdxp; + D.dfdxp = dfdxp; + D.dgdvp = dgdvp; + D.dfdvp = dfdvp; + + % gradients w.r.t. parameters + %-------------------------------------------------------------- + dx = spm_vec(qu.x{1}) - spm_vec(x); + dv = spm_vec(qu.v{1}) - spm_vec(v); + dgdp = D.dgdp; + dfdp = D.dfdp; + for p = 1:np + dgdp(:,p) = D.dgdp(:,p) + D.dgdxp{p}*dx + D.dgdvp{p}*dv; + if nx + dfdp(:,p) = D.dfdp(:,p) + D.dfdxp{p}*dx + D.dfdvp{p}*dv; + end + end + end + otherwise disp('Unknown method') end - + +% order parameters (d = n = 1 for static models) +%-------------------------------------------------------------------------- +d = M(1).E.d + 1; % generalisation order of q(v) +n = M(1).E.n + 1; % embedding order (n >= d) + % Generalised prediction errors and derivatives %========================================================================== Ex = cell(n,1); @@ -314,11 +486,12 @@ % Kronecker forms of derivatives for generalised motion %========================================================================== +if nargout < 2, return, end % dE.dp (parameters) %-------------------------------------------------------------------------- -dgdp = {dgdp}; -dfdp = {dfdp}; +dgdp = {dgdp}; +dfdp = {dfdp}; for i = 2:n dgdp{i,1} = dgdp{1}; dfdp{i,1} = dfdp{1}; @@ -339,13 +512,6 @@ dfdv = kron(spm_speye(n,d),dfdv); dfdx = kron(spm_speye(n,n),dfdx) - kron(spm_speye(n,n,1),speye(nx,nx)); -for i = 1:np - dgdxp{i} = kron(spm_speye(n,n),dgdxp{i}); - dfdxp{i} = kron(spm_speye(n,n),dfdxp{i}); - dgdvp{i} = kron(spm_speye(n,d),dgdvp{i}); - dfdvp{i} = kron(spm_speye(n,d),dfdvp{i}); -end - % 1st error derivatives (states) %-------------------------------------------------------------------------- dE.dy = spm_cat({dedy; dfdy}); @@ -354,10 +520,14 @@ dE.du = -spm_cat({dgdx, dgdv ; dfdx, dfdv}); - -% 1st and 2nd error derivatives (parameters) + +% bilinear derivatives %-------------------------------------------------------------------------- for i = 1:np + dgdxp{i} = kron(spm_speye(n,n),dgdxp{i}); + dfdxp{i} = kron(spm_speye(n,n),dfdxp{i}); + dgdvp{i} = kron(spm_speye(n,d),dgdvp{i}); + dfdvp{i} = kron(spm_speye(n,d),dfdvp{i}); dE.dup{i} = -spm_cat({dgdxp{i}, dgdvp{i}; dfdxp{i}, dfdvp{i}}); end @@ -366,27 +536,3 @@ else dE.dpu = {}; end - -return - -% Notes -%========================================================================== - -% % use the opportunity to check this is not a linear system -% %------------------------------------------------------------ -% G = 0; -% for i = 1:length(D.Dx) -% G = G + max(spm_vec(D.Dx{i}.dgdxp)); -% G = G + max(spm_vec(D.Dx{i}.dgdvp)); -% G = G + max(spm_vec(D.Dx{i}.dfdxp)); -% G = G + max(spm_vec(D.Dx{i}.dfdvp)); -% end -% for i = 1:length(D.Dv) -% G = G + max(spm_vec(D.Dv{i}.dgdxp)); -% G = G + max(spm_vec(D.Dv{i}.dgdvp)); -% G = G + max(spm_vec(D.Dv{i}.dfdxp)); -% G = G + max(spm_vec(D.Dv{i}.dfdvp)); -% end -% if G < exp(-16) -% D.linear = 1; -% end diff --git a/spm_DEM_eval_diff.m b/spm_DEM_eval_diff.m index 2091b37..5533915 100644 --- a/spm_DEM_eval_diff.m +++ b/spm_DEM_eval_diff.m @@ -1,22 +1,32 @@ -function [D] = spm_DEM_eval_diff(x,v,qp,M) +function [D] = spm_DEM_eval_diff(x,v,qp,M,bilinear) % evaluates derivatives for DEM schemes -% FORMAT [D] = spm_DEM_eval_diff(x,v,qp,M) -% +% FORMAT [D] = spm_DEM_eval_diff(x,v,qp,M,bilinear) % v{i} - casual states % x(i) - hidden states % qp - conditional density of parameters % qp.p{i} - parameter deviates for i-th level % qp.u(i) - basis set % qp.x(i) - expansion point ( = prior expectation) -% M - model structure +% M - model structure +% bilinear - optional flag to suppress second-order derivatives % -% D.dgdv - derivatives -% ... +% D - derivatives +% D.dgdv +% ... %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_DEM_eval_diff.m 3655 2009-12-23 20:15:34Z karl $ +% $Id: spm_DEM_eval_diff.m 3695 2010-01-22 14:18:14Z karl $ + +% check for evaluation of bilinear terms +%-------------------------------------------------------------------------- +try + bilinear; +catch + bilinear = 1; +end + % get dimensions %========================================================================== @@ -31,40 +41,36 @@ %-------------------------------------------------------------------------- df.dv = cell(nl - 1,nl - 1); df.dx = cell(nl - 1,nl - 1); +df.dp = cell(nl - 1,nl - 1); dg.dv = cell(nl ,nl - 1); dg.dx = cell(nl ,nl - 1); -df.dp = cell(nl - 1,nl - 1); dg.dp = cell(nl ,nl - 1); -for i = 1:(nl - 1) - dg.dp{i + 1,i} = sparse(M(i).m,M(i).p); - dg.dp{i ,i} = sparse(M(i).l,M(i).p); - df.dp{i ,i} = sparse(M(i).n,M(i).p); -end - -% & fill in hierarchical forms -%-------------------------------------------------------------------------- for i = 1:(nl - 1) dg.dv{i + 1,i} = sparse(M(i).m,M(i).m); dg.dx{i + 1,i} = sparse(M(i).m,M(i).n); + dg.dp{i + 1,i} = sparse(M(i).m,M(i).p); dg.dv{i ,i} = sparse(M(i).l,M(i).m); dg.dx{i ,i} = sparse(M(i).l,M(i).n); + dg.dp{i ,i} = sparse(M(i).l,M(i).p); df.dv{i ,i} = sparse(M(i).n,M(i).m); df.dx{i ,i} = sparse(M(i).n,M(i).n); + df.dp{i ,i} = sparse(M(i).n,M(i).p); end -for i = 1:(nl - 1) - dg.dvp{i} = cell(M(i).p,1); - dg.dxp{i} = cell(M(i).p,1); - df.dvp{i} = cell(M(i).p,1); - df.dxp{i} = cell(M(i).p,1); - [dg.dvp{i}{:}] = deal(dg.dv); - [dg.dxp{i}{:}] = deal(dg.dx); - [df.dvp{i}{:}] = deal(df.dv); - [df.dxp{i}{:}] = deal(df.dx); +if bilinear + for i = 1:(nl - 1) + dg.dvp{i} = cell(M(i).p,1); + dg.dxp{i} = cell(M(i).p,1); + df.dvp{i} = cell(M(i).p,1); + df.dxp{i} = cell(M(i).p,1); + [dg.dvp{i}{:}] = deal(dg.dv); + [dg.dxp{i}{:}] = deal(dg.dx); + [df.dvp{i}{:}] = deal(df.dv); + [df.dxp{i}{:}] = deal(df.dx); + end end - % Derivatives at each hierarchical level %========================================================================== @@ -77,31 +83,36 @@ % states level i %---------------------------------------------------------------------- xvp = {x{i},v{i},qp.p{i},qp.u{i},M(i).pE}; - - % Constant terms (linking causes over levels) - %---------------------------------------------------------------------- - dg.dv{i + 1,i} = -speye(M(i).m,M(i).m); - + + % 1st and 2nd partial derivatives (states) %---------------------------------------------------------------------- - try - [dgdxp dgdx] = spm_diff(h,M(i).gx,xvp{:},4); - [dgdvp dgdv] = spm_diff(h,M(i).gv,xvp{:},4); - [dfdxp dfdx] = spm_diff(h,M(i).fx,xvp{:},4); - [dfdvp dfdv] = spm_diff(h,M(i).fv,xvp{:},4); - catch - [dgdxp dgdx] = spm_diff(h,M(i).g,xvp{:},[2 4]); - [dgdvp dgdv] = spm_diff(h,M(i).g,xvp{:},[3 4]); - [dfdxp dfdx] = spm_diff(h,M(i).f,xvp{:},[2 4]); - [dfdvp dfdv] = spm_diff(h,M(i).f,xvp{:},[3 4]); + if bilinear + try + [dgdxp dgdx] = spm_diff(h,M(i).gx,xvp{:},4,'q'); + [dgdvp dgdv] = spm_diff(h,M(i).gv,xvp{:},4,'q'); + [dfdxp dfdx] = spm_diff(h,M(i).fx,xvp{:},4,'q'); + [dfdvp dfdv] = spm_diff(h,M(i).fv,xvp{:},4,'q'); + catch + [dgdxp dgdx] = spm_diff(h,M(i).g,xvp{:},[2 4]); + [dgdvp dgdv] = spm_diff(h,M(i).g,xvp{:},[3 4]); + [dfdxp dfdx] = spm_diff(h,M(i).f,xvp{:},[2 4]); + [dfdvp dfdv] = spm_diff(h,M(i).f,xvp{:},[3 4]); + end + else + try + dgdx = h(M(i).gx,xvp{:}); + dgdv = h(M(i).gv,xvp{:}); + dfdx = h(M(i).fx,xvp{:}); + dfdv = h(M(i).fv,xvp{:}); + catch + dgdx = spm_diff(h,M(i).g,xvp{:},2); + dgdv = spm_diff(h,M(i).g,xvp{:},3); + dfdx = spm_diff(h,M(i).f,xvp{:},2); + dfdv = spm_diff(h,M(i).f,xvp{:},3); + end end - % place 1st derivatives in array - %---------------------------------------------------------------------- - dg.dx{i,i} = dgdx; - dg.dv{i,i} = dgdv; - df.dx{i,i} = dfdx; - df.dv{i,i} = dfdv; % 1st-order partial derivatives (parameters) %---------------------------------------------------------------------- @@ -112,19 +123,37 @@ dfdp = spm_diff(h,M(i).f,xvp{:},4); dgdp = spm_diff(h,M(i).g,xvp{:},4); end - - % and place in array + +% % check which dervatives need to be evaluated +% %==================================================================== +% D(i).dgdv = nnz(dgdv) + nnz(spm_vec(dgdvp)); +% D(i).dgdx = nnz(dgdx) + nnz(spm_vec(dgdxp)); +% D(i).dfdv = nnz(dfdv) + nnz(spm_vec(dfdvp)); +% D(i).dfdx = nnz(dfdx) + nnz(spm_vec(dfdxp)); + + + % Constant terms (linking causes over levels) + %---------------------------------------------------------------------- + dg.dv{i + 1,i} = -speye(M(i).m,M(i).m); + + % place 1st derivatives in array %---------------------------------------------------------------------- + dg.dx{i,i} = dgdx; + dg.dv{i,i} = dgdv; + df.dx{i,i} = dfdx; + df.dv{i,i} = dfdv; df.dp{i,i} = dfdp; dg.dp{i,i} = dgdp; % place 2nd derivatives in array %---------------------------------------------------------------------- - for j = 1:length(dgdxp) - dg.dxp{i}{j}{i,i} = dgdxp{j}; - dg.dvp{i}{j}{i,i} = dgdvp{j}; - df.dxp{i}{j}{i,i} = dfdxp{j}; - df.dvp{i}{j}{i,i} = dfdvp{j}; + if bilinear + for j = 1:length(dgdxp) + dg.dxp{i}{j}{i,i} = dgdxp{j}; + dg.dvp{i}{j}{i,i} = dgdvp{j}; + df.dxp{i}{j}{i,i} = dfdxp{j}; + df.dvp{i}{j}{i,i} = dfdvp{j}; + end end end @@ -137,25 +166,28 @@ D.dfdp = spm_cat(df.dp); D.dgdp = spm_cat(dg.dp); -D.dgdvp = {}; -D.dgdxp = {}; -D.dfdvp = {}; -D.dfdxp = {}; - -k = 1; -for i = 1:length(dg.dvp) - for j = 1:length(dg.dvp{i}) - D.dgdvp{k} = spm_cat(dg.dvp{i}{j}); - D.dgdxp{k} = spm_cat(dg.dxp{i}{j}); - D.dfdvp{k} = spm_cat(df.dvp{i}{j}); - D.dfdxp{k} = spm_cat(df.dxp{i}{j}); - k = k + 1; - end -end - % fixed derivatives w.r.t. prediction errors and states %-------------------------------------------------------------------------- D.dfdy = sparse(nx,ny); D.dfdc = sparse(nx,nc); D.dedy = spm_speye(ne,ny); D.dedc = -spm_speye(ne,nc,nc - ne); + +% bilinear terms if required +%-------------------------------------------------------------------------- +if bilinear + D.dgdvp = {}; + D.dgdxp = {}; + D.dfdvp = {}; + D.dfdxp = {}; + for i = 1:length(dg.dvp) + for j = 1:length(dg.dvp{i}) + D.dgdvp{end + 1} = spm_cat(dg.dvp{i}{j}); + D.dgdxp{end + 1} = spm_cat(dg.dxp{i}{j}); + D.dfdvp{end + 1} = spm_cat(df.dvp{i}{j}); + D.dfdxp{end + 1} = spm_cat(df.dxp{i}{j}); + end + end +end + + diff --git a/spm_DEM_generate.m b/spm_DEM_generate.m index d276196..fc07e4e 100644 --- a/spm_DEM_generate.m +++ b/spm_DEM_generate.m @@ -1,13 +1,13 @@ function [DEM] = spm_DEM_generate(M,U,P,h,g) -% Generates data for a HDM +% Generates data for a Hierarchical Dynamic Model (HDM) % FORMAT [DEM] = spm_DEM_generate(M,N,P,h,g): N-samples using z % FORMAT [DEM] = spm_DEM_generate(M,U,P,h,g): size(U,2) samples using U % % M(i) - HDM % U(n x N} - causes or N number of causes % P{i} - model-parameters for level i (defaults to M.pE) -% h{i} - hyper-parameters for level i (defaults to 32 - no noise) -% g{i} - hyper-parameters for level i (defaults to 32 - no noise) +% h{i} - log-precisions for level i (defaults to 32 - no noise) +% g{i} - log-precisions for level i (defaults to 32 - no noise) % % generates % DEM.M - hierarchical model (checked) @@ -23,7 +23,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_DEM_generate.m 1844 2008-06-20 20:14:05Z guillaume $ +% $Id: spm_DEM_generate.m 3703 2010-02-01 20:47:44Z karl $ % sequence length specified by priors on causes %-------------------------------------------------------------------------- @@ -34,13 +34,14 @@ N = size(U,2); else N = U; + U = sparse(M(end).l,N); end catch warndlg('Please specify model inputs U or number of samples') return end -% initialise model-parameters if specified +% initialize model-parameters if specified %-------------------------------------------------------------------------- try, P; if ~iscell(P), P = {P}; end, catch, P = {M.pE}; end try, h; if ~iscell(h), h = {h}; end, catch, h = {}; end @@ -73,36 +74,30 @@ end end -% create innovations +% re-set M and create innovations %-------------------------------------------------------------------------- -M = spm_DEM_M_set(M); -[z w] = spm_DEM_z(M,N); - -% and add exogenous input +M = spm_DEM_M_set(M); +[z w] = spm_DEM_z(M,N); + +% place exogenous causes in cell array %-------------------------------------------------------------------------- -if ~isscalar(U) - try - z{end} = U + z{end}; - catch - warndlg('input and model are inconsistent') - end +for i = 1:m + u{i} = sparse(M(i).l,N); end +u{m} = U; + % integrate HDM to obtain causal (v) and hidden states (x) %-------------------------------------------------------------------------- -[v,x] = spm_DEM_int(M,z,w); +[v,x,z,w] = spm_DEM_int(M,z,w,u); % Fill in DEM with response and its causes %-------------------------------------------------------------------------- -DEM.Y = v{1}; -DEM.pU.v = v; -DEM.pU.x = x; -DEM.pU.z = z; -DEM.pU.w = w; -DEM.pP.P = {M.pE}; -DEM.pH.h = {M.hE}; -DEM.pH.g = {M.gE}; - - - - +DEM.Y = v{1}; +DEM.pU.v = v; +DEM.pU.x = x; +DEM.pU.z = z; +DEM.pU.w = w; +DEM.pP.P = {M.pE}; +DEM.pH.h = {M.hE}; +DEM.pH.g = {M.gE}; diff --git a/spm_DEM_int.m b/spm_DEM_int.m index 7bf9735..19761d8 100644 --- a/spm_DEM_int.m +++ b/spm_DEM_int.m @@ -1,131 +1,174 @@ -function [V,X] = spm_DEM_int(M,Z,W) +function [V,X,Z,W] = spm_DEM_int(M,z,w,c) % Integrates/evaluates a hierarchical model given innovations z{i} and w{i} -% FORMAT [V,X] = spm_DEM_int(M,Z); +% FORMAT [V,X,Z,W] = spm_DEM_int(M,z,w,c); % % M{i} - model structure -% Z{i} - innovations (causes) -% W{i} - innovations (states) +% z{i} - innovations (causes) +% w{i} - innovations (states) +% c{i} - exogenous causes % % V{i} - causal states (V{1} = y = response) % X{i} - hidden states +% Z{i} - fluctuations (causes) +% W{i} - fluctuations (states) % % The system is evaluated at the prior expectation of the parameters %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging - + % Karl Friston -% $Id: spm_DEM_int.m 3655 2009-12-23 20:15:34Z karl $ - +% $Id: spm_DEM_int.m 3715 2010-02-08 13:57:26Z karl $ + % set model indices and missing fields %-------------------------------------------------------------------------- -M = spm_DEM_M_set(M); - +M = spm_DEM_M_set(M); + % innovations %-------------------------------------------------------------------------- -try, Z = spm_cat(Z(:)); end -try, W = spm_cat(W(:)); end - +try, z = spm_cat(z(:)); end +try, w = spm_cat(w(:)); end +try, c = spm_cat(c(:)); end + % number of states and parameters %-------------------------------------------------------------------------- -nt = size(Z,2); % number of time steps +nt = size(z,2); % number of time steps nl = size(M,2); % number of levels nv = sum(spm_vec(M.l)); % number of v (casual states) nx = sum(spm_vec(M.n)); % number of x (hidden states) - + % order parameters (n= 1 for static models) %========================================================================== dt = M(1).E.dt; % time step n = M(1).E.n + 1; % order of embedding nD = M(1).E.nD; % number of iterations per sample td = dt/nD; % integration time for D-Step - -% initialise cell arrays for derivatives z{i} = (d/dt)^i[z], ... + +% initialize cell arrays for derivatives z{i} = (d/dt)^i[z], ... +%-------------------------------------------------------------------------- +u.v = cell(n,1); +u.x = cell(n,1); +u.z = cell(n,1); +u.w = cell(n,1); +[u.v{:}] = deal(sparse(nv,1)); +[u.x{:}] = deal(sparse(nx,1)); +[u.z{:}] = deal(sparse(nv,1)); +[u.w{:}] = deal(sparse(nx,1)); + +% hyperparameters %-------------------------------------------------------------------------- -v = cell(n,1); -x = cell(n,1); -z = cell(n,1); -w = cell(n,1); -[v{:}] = deal(sparse(nv,1)); -[x{:}] = deal(sparse(nx,1)); -[z{:}] = deal(sparse(nv,1)); -[w{:}] = deal(sparse(nx,1)); - -% initialise with starting conditions +ph.h = {M.hE}; +ph.g = {M.gE}; + +% initialize with starting conditions %-------------------------------------------------------------------------- -v{1} = spm_vec({M.v}); -x{1} = spm_vec({M.x}); -u.v = v; -u.x = x; -u.z = z; -u.w = w; - +vi = {M.v}; +xi = {M.x}; +u.v{1} = spm_vec(vi); +u.x{1} = spm_vec(xi); + + % derivatives for Jacobian of D-step %-------------------------------------------------------------------------- Dx = kron(spm_speye(n,n,1),spm_speye(nx,nx,0)); Dv = kron(spm_speye(n,n,1),spm_speye(nv,nv,0)); D = spm_cat(spm_diag({Dv,Dx,Dv,Dx})); dfdw = kron(eye(n,n),eye(nx,nx)); - -% initialise conditional estimators of states to be saved (V and X) + +% initialize conditional estimators of states to be saved (V and X) %-------------------------------------------------------------------------- for i = 1:nl V{i} = sparse(M(i).l,nt); X{i} = sparse(M(i).n,nt); + Z{i} = sparse(M(i).l,nt); + W{i} = sparse(M(i).n,nt); +end + +% method for state-dependent precision +%------------------------------------------------------------------ +if isempty(spm_vec(M.ph)) && isempty(spm_vec(M.pg)) + state_dependent = 0; + Sz = 1; + Sw = 1; +else + state_dependent = 1; end - - + + + % iterate over sequence (t) and within for static models %========================================================================== for t = 1:nt for iD = 1:nD - + + + % Get generalised motion of random fluctuations + %================================================================== + % sampling time %------------------------------------------------------------------ - ts = (t + (iD - 1)/nD)*dt; - - % derivatives of innovations + ts = (t + (iD - 1)/nD)*dt; + + % evaluate state-dependent precision + %------------------------------------------------------------------ + if state_dependent + pu.x = {spm_vec(xi(1:end - 1))}; + pu.v = {spm_vec(vi(1 + 1:end))}; + p = spm_LAP_eval(M,pu,ph); + Sz = sparse(diag(exp(-p.h/2))); + Sw = sparse(diag(exp(-p.g/2))); + end + + % derivatives of innovations (and exogenous input) + %------------------------------------------------------------------ + u.z = spm_DEM_embed(Sz*z + c,n,ts,dt); + u.w = spm_DEM_embed(Sw*w, n,ts,dt); + + + % Evaluate and update states + %================================================================== + + % evaluate functions %------------------------------------------------------------------ - u.z = spm_DEM_embed(Z,n,ts,dt); - u.w = spm_DEM_embed(W,n,ts,dt); - - % evaluate - %------------------------------------------------------------------ [u dg df] = spm_DEM_diff(M,u); - - % tensor products for Jabobian + + % tensor products for Jacobian %------------------------------------------------------------------ dgdv = kron(spm_speye(n,n,1),dg.dv); dgdx = kron(spm_speye(n,n,1),dg.dx); dfdv = kron(spm_speye(n,n,0),df.dv); dfdx = kron(spm_speye(n,n,0),df.dx); - % Save realisation + % Save realization %================================================================== - vi = spm_unvec(u.v{1},{M.v}); - xi = spm_unvec(u.x{1},{M.x}); + vi = spm_unvec(u.v{1},{M.v}); + xi = spm_unvec(u.x{1},{M.x}); + zi = spm_unvec(u.z{1},{M.v}); + wi = spm_unvec(u.w{1},{M.x}); if iD == 1 for i = 1:nl if M(i).l, V{i}(:,t) = spm_vec(vi{i}); end if M(i).n, X{i}(:,t) = spm_vec(xi{i}); end - end + if M(i).l, Z{i}(:,t) = spm_vec(zi{i}); end + if M(i).n, W{i}(:,t) = spm_vec(wi{i}); end end - end - + end + + % Jacobian for update %------------------------------------------------------------------ J = spm_cat({dgdv dgdx Dv [] ; dfdv dfdx [] dfdw; [] [] Dv [] ; [] [] [] Dx}); - + % update states u = {x,v,z,w} %------------------------------------------------------------------ du = spm_dx(J,D*spm_vec(u),td); - + % and unpack %------------------------------------------------------------------ u = spm_unvec(spm_vec(u) + du,u); - + end % iterations over iD - + end % iterations over t diff --git a/spm_DEM_qH.m b/spm_DEM_qH.m index 97975d9..e34e85b 100644 --- a/spm_DEM_qH.m +++ b/spm_DEM_qH.m @@ -1,32 +1,40 @@ -function spm_DEM_qH(qH) +function spm_DEM_qH(qH,pH) % reports on conditional estimates of hyperparameters -% FORMAT spm_DEM_qH(qH); +% FORMAT spm_DEM_qH(qH,pH); % -% qH.h - ReML estimate of log precision (causes) -% qH.g - ReML estimate of log precision (state) +% qH.h - conditional estimate of log-precision (causes) +% qH.g - conditional of log-precision (state) % qH.V - conditional variance (causes) % qH.W - conditional (states) +% +% qH.p - time-dependent estimates from Laplace scheme +% qH.c - time-dependent covariances +% +% pH - option true log-precisions %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging - + % Karl Friston -% $Id: spm_DEM_qH.m 3655 2009-12-23 20:15:34Z karl $ - +% $Id: spm_DEM_qH.m 3878 2010-05-07 19:53:54Z karl $ + % unpack conditional covariances %-------------------------------------------------------------------------- try, qH = qH.qH; end +try, pH = pH.pH; end + % [Re]ML estimates - h -%-------------------------------------------------------------------------- -h = spm_vec(qH.h); -c = spm_vec(qH.V); -c = sqrt(c*spm_invNcdf(1 - 0.05)); +%========================================================================== +ci = spm_invNcdf(1 - 0.05); +h = spm_vec(qH.h); +c = spm_vec(qH.V); +c = sqrt(c)*ci; subplot(2,2,1) -bar(full(h),'c') +bar(full(h),'Edgecolor',[1 1 1]/2,'Facecolor',[1 1 1]*.8) title({'log-precision';'noise and causes'},'FontSize',16); axis square set(gca,'XLim',[0 length(c) + 1]) - + hlabel = {}; for i = 1:length(qH.h) for j = 1:length(qH.h{i}) @@ -34,30 +42,49 @@ function spm_DEM_qH(qH) end end set(gca,'XTickLabel',hlabel) - + % conditional covariances %-------------------------------------------------------------------------- for i = 1:length(c) line([i i],[-1 1]*c(i) + h(i),'LineWidth',4,'Color','r'); end -% [Re]ML estimates - g +% prior or true means %-------------------------------------------------------------------------- +try + p = spm_vec(pH.h); + for i = 1:length(h) + line([-1 1]/2 + i,[0 0] + p(i),'LineWidth',4,'Color','k'); + end +end + + +% [Re]ML estimates - g +%========================================================================== h = spm_vec(qH.g); c = spm_vec(qH.W); -c = sqrt(c*spm_invNcdf(1 - 0.05)); +c = sqrt(c)*spm_invNcdf(1 - 0.05); subplot(2,2,2) -bar(full(h),'c') +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'); + end +end + glabel = {}; for i = 1:length(qH.h) for j = 1:length(qH.h{i}) @@ -65,19 +92,49 @@ function spm_DEM_qH(qH) end end set(gca,'XTickLabel',glabel) - + % conditional covariance and correlations %-------------------------------------------------------------------------- -if length(qH.C) > 1 - subplot(2,2,3) - imagesc(qH.C) - title({'covariances among','ln(hyperparameters)'},'FontSize',16) +subplot(2,2,3) +imagesc(qH.C) +title({'covariances among','hyperparameters'},'FontSize',16) +axis square +set(gca,'YTickLabel',{hlabel{:} glabel{:}},'YTick',[1:length(qH.C)]) + +% plot evolution of hyperparameters if supplied +%========================================================================== +subplot(2,2,4) +try + + % confidence interval and expectations + %---------------------------------------------------------------------- + ns = length(qH.p); + t = 1:ns; + for i = 1:ns + v(:,i) = sqrt(diag(qH.c{i})); + end + c = ci*v; + h = spm_cat(qH.p); + + % plot + %---------------------------------------------------------------------- + hold on + nh = size(h,1); + for i = 1:nh + fill([t fliplr(t)],[(h(i,:) + c(i,:)) fliplr(h(i,:) - c(i,:))],... + [1 1 1]*.8,'EdgeColor',[1 1 1]/2) + plot(t,h(i,:)) + end + set(gca,'XLim',[1 ns]) + title({'dynamics of','hyperparameters'},'FontSize',16) + xlabel('time') axis square - set(gca,'YTickLabel',{hlabel{:} glabel{:}},'YTick',[1:length(qH.C)]) - - subplot(2,2,4) + hold off + +catch + imagesc(spm_cov2corr(qH.C)) - title({'correlations among','ln(hyperparameters)'},'FontSize',16) + title({'correlations among','hyperparameters'},'FontSize',16) axis square + end - diff --git a/spm_DEM_qP.m b/spm_DEM_qP.m index 1b2f337..b0aabd4 100644 --- a/spm_DEM_qP.m +++ b/spm_DEM_qP.m @@ -2,31 +2,30 @@ function spm_DEM_qP(qP,pP) % reports on conditional estimates of parameters % FORMAT spm_DEM_qP(qP,pP) % -% qP.P - conditional expectations +% qP.P - conditional expectations % qP.V - conditional variance % -% pP - optional priors +% pP - optional priors %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_DEM_qP.m 3655 2009-12-23 20:15:34Z karl $ +% $Id: spm_DEM_qP.m 3878 2010-05-07 19:53:54Z karl $ -% time-series specification -%-------------------------------------------------------------------------- -clf -g = length(qP.P); % depth of hierarchy - % unpack conditional covariances %-------------------------------------------------------------------------- -ci = spm_invNcdf(1 - 0.05); +g = length(qP.P); % depth of hierarchy +ci = spm_invNcdf(1 - 0.05); % loop over levels %-------------------------------------------------------------------------- Label = {}; -for i = 1:(g - 1) - +for i = 1:g + + % check for last level + %---------------------------------------------------------------------- + if isempty(qP.P{i}), break, end % get lablels %---------------------------------------------------------------------- @@ -40,41 +39,53 @@ function spm_DEM_qP(qP,pP) end end - % conditional expectations (with priors if specified) %---------------------------------------------------------------------- qi = spm_vec(qP.P{i}); - dk = 0; - try - qi = [qi spm_vec(pP.P{i})]; - dk = -1/8; - end - c = spm_vec(qP.V{i})*ci; + c = sqrt(spm_vec(qP.V{i}))*ci; j = find(c); qi = qi(j); c = c(j); - label = label(j); + try + label = label(j); + end + try + pi = spm_vec(pP.P{i}); + pi = pi(j); + end np = length(qi); if np - subplot(g,1,i) - bar(qi) - title(sprintf('parameters - level %i',i)); - grid on + + % use current axes if P = P{1} + %------------------------------------------------------------------ + if g > 1, subplot(g,1,i), end + + % conditional means + %------------------------------------------------------------------ + bar(qi,'Edgecolor',[1 1 1]/2,'Facecolor',[1 1 1]*.8) + title(sprintf('parameters - level %i',i),'FontSize',16); axis square + box off set(gca,'XLim',[0 np + 1]) % conditional variances %------------------------------------------------------------------ - c = spm_vec(qP.V{i})*ci; for k = 1:np - line([k k] + dk,[-1 1]*c(k) + qi(k),... - 'LineWidth',4,'Color','r'); + line([k k], [-1 1]*c(k) + qi(k),'LineWidth',4,'Color','r'); + end + + % prior or true means + %------------------------------------------------------------------ + try + for k = 1:np + line([-1 1]/2 + k,[0 0] + pi(k),'LineWidth',4,'Color','k'); + end end % labels %------------------------------------------------------------------ for k = 1:length(label) - text(k + dk,qi(k),label{k},'FontSize',14,'Color','r'); + text(k + 1/4,qi(k),label{k},'FontSize',12,'FontWeight','Bold','Color','g'); end Label = {Label{:}, label{:}}; end @@ -82,10 +93,14 @@ function spm_DEM_qP(qP,pP) % conditional (or prior) covariance %-------------------------------------------------------------------------- -if length(qP.C) == 1; +try + if length(qP.C) == 1; + return + else + i = find(diag(qP.C)); + end +catch return -else - i = find(diag(qP.C)); end subplot(g,2,g + g - 1) @@ -102,10 +117,50 @@ function spm_DEM_qP(qP,pP) axis square -% and correlations -%-------------------------------------------------------------------------- +% plot evolution of hyperparameters if supplied +%========================================================================== subplot(g,2,g + g) -imagesc(spm_cov2corr(qP.C(i,i))) -title({'conditional correlations','among parameters'},'FontSize',16) -axis square -drawnow +try + + % confidence interval and expectations + %---------------------------------------------------------------------- + ns = length(qP.p); + t = 1:ns; + for i = 1:ns + v(:,i) = sqrt(diag(qP.U*qP.c{i}*qP.U')); + end + c = ci*v; + p = qP.U*spm_cat(qP.p); + i = find(any(v,2)); + c = c(i,:); + p = p(i,:); + + + % plot + %---------------------------------------------------------------------- + hold on + np = size(p,1); + for i = 1:np + fill([t fliplr(t)],[(p(i,:) + c(i,:)) fliplr(p(i,:) - c(i,:))],... + [1 1 1]*.8,'EdgeColor',[1 1 1]/2) + plot(t,p(i,:)) + end + set(gca,'XLim',[1 ns]) + title({'dynamics of parameters','(minus prior)'},'FontSize',16) + xlabel('time') + axis square + hold off + +catch + + % or correlations + %---------------------------------------------------------------------- + imagesc(spm_cov2corr(qP.C(i,i))) + title({'conditional correlations','among parameters'},'FontSize',16) + axis square + drawnow + +end + + + diff --git a/spm_DEM_qU.m b/spm_DEM_qU.m index 539119a..526d053 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 3655 2009-12-23 20:15:34Z karl $ +% $Id: spm_DEM_qU.m 3878 2010-05-07 19:53:54Z karl $ % unpack %-------------------------------------------------------------------------- @@ -50,8 +50,8 @@ function spm_DEM_qU(qU,pU) c = []; try for i = 1:N - c = [c sqrt(diag(C{i}))]; - s = [s sqrt(diag(S{i}))]; + c = [c abs(sqrt(diag(C{i})))]; + s = [s abs(sqrt(diag(S{i})))]; end end @@ -66,6 +66,7 @@ function spm_DEM_qU(qU,pU) subplot(g,2,2*i - 1) t = 1:size(V{i},1); plot(t,full(E{i}),'r:',t,full(V{i})) + box off % conditional covariances @@ -76,17 +77,17 @@ 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]*.8) + [1 1 1]*.8,'EdgeColor',[1 1 1]*.6) plot(t,full(E{i}),'r:',t,full(V{i})) hold off end % title and grid %------------------------------------------------------------------ - title('causal states','FontSize',16); - grid on + title('hidden causes','FontSize',16); axis square set(gca,'XLim',[t(1) t(end)]) + box off else @@ -94,11 +95,13 @@ function spm_DEM_qU(qU,pU) %------------------------------------------------------------------ subplot(g,2,2*i - 1) try - plot(t,pV{i},':k','linewidth',1) - end, hold on + plot(t,pV{i},':k','linewidth',1),box off + end + hold on try - plot(t,full(E{i}(:,1:N)),'r:',t,full(V{i})) - end, hold off + plot(t,full(E{i}(:,1:N)),'r:',t,full(V{i})),box off + end + hold off set(gca,'XLim',[t(1) t(end)]) a = axis; @@ -110,28 +113,32 @@ 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]*.8) + [1 1 1]*.8,'EdgeColor',[1 1 1]*.6) try - plot(t,pV{i},':k','linewidth',1) + plot(t,pV{i},':k','linewidth',1),box off end plot(t,full(E{i}(:,1:N)),'r:',t,full(V{i})) hold off end - % title, action, grid and true causes (if available) + % title, action and true causes (if available) %------------------------------------------------------------------ if i == 1 title('prediction and error','FontSize',16); elseif ~size(V{i},1) title('no causes','FontSize',16); else - title('causal states','FontSize',16); - try, hold on - plot(t,pV{i},':k','linewidth',1) - end, hold off - try, hold on - plot(t,pA{i - 1},'linewidth',1,'color',[1 0 0]) - end, hold off + title('hidden causes','FontSize',16); + try + hold on + 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 @@ -142,10 +149,12 @@ function spm_DEM_qU(qU,pU) try subplot(g,2,2*i) - try, hold on - plot(t,pX{i},':k','linewidth',1) - end, hold off - plot(t,full(X{i})) + try + hold on + plot(t,pX{i},':k','linewidth',1),box off + end + hold off + plot(t,full(X{i})),box off set(gca,'XLim',[t(1) t(end)]) a = axis; @@ -157,9 +166,9 @@ function spm_DEM_qU(qU,pU) fill([t fliplr(t)],[full(X{i} + y) fliplr(full(X{i} - y))],... [1 1 1]*.8,'EdgeColor',[1 1 1]*.8) try - plot(t,pX{i},':k','linewidth',1) + plot(t,pX{i},':k','linewidth',1),box off end - plot(t,full(X{i})) + plot(t,full(X{i})),box off hold off end @@ -181,13 +190,16 @@ function spm_DEM_qU(qU,pU) if isfield(qU,'a') subplot(g,2,2*g) plot(t,qU.a{2}); - try, hold on - plot(t,pU.v{2},':b','Linewidth',2) - end,hold off + try + hold on + plot(t,pU.v{2},':b','Linewidth',2),box off + end + hold off xlabel('time','Fontsize',14) title('perturbation and action','Fontsize',16) axis square set(gca,'XLim',[t(1) t(end)]) + box off end hold off drawnow diff --git a/spm_DEM_set.m b/spm_DEM_set.m index 13bd408..8cea6a6 100644 --- a/spm_DEM_set.m +++ b/spm_DEM_set.m @@ -10,7 +10,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_DEM_set.m 3655 2009-12-23 20:15:34Z karl $ +% $Id: spm_DEM_set.m 3695 2010-01-22 14:18:14Z karl $ % check recognition model % ------------------------------------------------------------------------- @@ -104,7 +104,7 @@ % unpack DEM if necessary % ------------------------------------------------------------------------- -if nargout == 4 +if nargout > 1 varargout{1} = DEM.M; varargout{2} = DEM.Y; varargout{3} = DEM.U; diff --git a/spm_DEM_z.m b/spm_DEM_z.m index 807e5a8..dce6300 100644 --- a/spm_DEM_z.m +++ b/spm_DEM_z.m @@ -6,31 +6,35 @@ % % z{i} - innovations for level i (N.B. z{end} corresponds to causes) % w{i} - innovations for level i (state noise) +% +% If there is no fixed or hyper parameterized precision, then unit noise is +% created. It is assumed that this will be later modulated by state +% dependent terms, specified by M.ph and M.pg in spm_DEM_int %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging - + % Karl Friston -% $Id: spm_DEM_z.m 1703 2008-05-21 13:59:23Z karl $ +% $Id: spm_DEM_z.m 3878 2010-05-07 19:53:54Z karl $ % temporal convolution matrix (with unit variance) %-------------------------------------------------------------------------- s = M(1).E.s + exp(-16); dt = M(1).E.dt; -t = ([1:N] - 1)*dt; +t = ((1:N) - 1)*dt; K = toeplitz(exp(-t.^2/(2*s^2))); -C = inv(sqrt(diag(diag(K*K')))); -K = C*K; +K = diag(1./sqrt(diag(K*K')))*K; % create innovations z{i} and w{i} %-------------------------------------------------------------------------- for i = 1:length(M) - % causes + % causes: assume i.i.d. if precision (P) is zero %---------------------------------------------------------------------- P = M(i).V; for j = 1:length(M(i).Q) P = P + M(i).Q{j}*exp(M(i).hE(j)); end + if ~norm(P,1); P = 1; end z{i} = spm_sqrtm(inv(P))*randn(M(i).l,N)*K; % states @@ -39,13 +43,11 @@ for j = 1:length(M(i).R) P = P + M(i).R{j}*exp(M(i).gE(j)); end - if length(P) + if ~isempty(P) + if ~norm(P,1); P = 1; end w{i} = spm_sqrtm(inv(P))*randn(M(i).n,N)*K*dt; else w{i} = sparse(0,0); end end - - - diff --git a/spm_DFP.m b/spm_DFP.m index 4c5cc8c..588b937 100644 --- a/spm_DFP.m +++ b/spm_DFP.m @@ -53,8 +53,8 @@ % F = log evidence = marginal likelihood = negative free energy %__________________________________________________________________________ % -% spm_DEM implements a variational Bayes (VB) scheme under the Laplace -% approximation to the conditional densities of states (u), parameters (p) +% spm_DFP implements a variational Bayes (VB) scheme under the Laplace +% approximation to the conditional densities of the model's, parameters (p) % and hyperparameters (h) of any analytic nonlinear hierarchical dynamic % model, with additive Gaussian innovations. It comprises three % variational steps (D,E and M) that update the conditional moments of u, p @@ -67,20 +67,17 @@ % 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. +% L with respect to u, p and h. % -% The D-step is embedded in the E-step because q(u) changes with each -% sequential observation. The dynamical model is transformed into a static -% 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 generlised co-ordinates. This means DEM can deconvolve online and can -% represents an alternative to Kalman filtering or alternative Bayesian -% update procedures. +% The D-step is implemented with variational filtering, which does not +% assume a fixed form for the conditional density; it uses the sample +% density of an ensemble of particles that drift up free-energy gradients +% and 'explore' the local curvature though (Wiener) perturbations. %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_DFP.m 3655 2009-12-23 20:15:34Z karl $ +% $Id: spm_DFP.m 3878 2010-05-07 19:53:54Z karl $ % Check model, data, priros and confounds and unpack %-------------------------------------------------------------------------- diff --git a/spm_DesMtx.m b/spm_DesMtx.m index 607026e..d224f79 100644 --- a/spm_DesMtx.m +++ b/spm_DesMtx.m @@ -250,7 +250,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Andrew Holmes -% $Id: spm_DesMtx.m 1157 2008-02-19 11:34:58Z guillaume $ +% $Id: spm_DesMtx.m 3934 2010-06-17 14:58:25Z guillaume $ @@ -674,11 +674,11 @@ rX(:,1:t) = []; rPnames(1:t,:)=[]; - elseif size(rX,2)>1 & max([1,findstr(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... %=============================================================== - c1 = max(findstr(rPnames(1,:),'_{')); + c1 = max(strfind(rPnames(1,:),'_{')); d = any(diff(abs(rPnames(:,1:c1+1))),2)... | ~any(rPnames(2:end,c1+2:end)=='}',2); t = min(find([d;1])); @@ -716,7 +716,7 @@ % Fnames = spm_DesMtx('FNames',Pnames) if nargin<2, varargout={''}; return, end Fnames = varargin{2}; -for i=1:prod(size(Fnames)) +for i=1:numel(Fnames) str = Fnames{i}; str(str==',')='x'; %-',' to 'x' str(str=='*')='-'; %-'*' to '-' diff --git a/spm_LAP.m b/spm_LAP.m new file mode 100644 index 0000000..b0494a4 --- /dev/null +++ b/spm_LAP.m @@ -0,0 +1,859 @@ +function [DEM] = spm_LAP(DEM) +% Laplacian model inversion (see also spm_LAPS) +% FORMAT DEM = spm_LAP(DEM) +% +% DEM.M - hierarchical model +% DEM.Y - response variable, output or data +% DEM.U - explanatory variables, inputs or prior expectation of causes +%__________________________________________________________________________ +% +% generative model +%-------------------------------------------------------------------------- +% M(i).g = v = g(x,v,P) {inline function, string or m-file} +% M(i).f = dx/dt = f(x,v,P) {inline function, string or m-file} +% +% M(i).ph = pi(v) = ph(x,v,h,M) {inline function, string or m-file} +% M(i).pg = pi(x) = pg(x,v,g,M) {inline function, string or m-file} +% +% M(i).pE = prior expectation of p model-parameters +% M(i).pC = prior covariances of p model-parameters +% M(i).hE = prior expectation of h log-precision (cause noise) +% M(i).hC = prior covariances of h log-precision (cause noise) +% M(i).gE = prior expectation of g log-precision (state noise) +% M(i).gC = prior covariances of g log-precision (state noise) +% M(i).xP = precision (states) +% M(i).Q = precision components (input noise) +% M(i).R = precision components (state noise) +% M(i).V = fixed precision (input noise) +% M(i).W = fixed precision (state noise) +% +% M(i).m = number of inputs v(i + 1); +% M(i).n = number of states x(i); +% M(i).l = number of output v(i); +% +% conditional moments of model-states - q(u) +%-------------------------------------------------------------------------- +% qU.x = Conditional expectation of hidden states +% qU.v = Conditional expectation of causal states +% qU.w = Conditional prediction error (states) +% qU.z = Conditional prediction error (causes) +% qU.C = Conditional covariance: cov(v) +% qU.S = Conditional covariance: cov(x) +% +% conditional moments of model-parameters - q(p) +%-------------------------------------------------------------------------- +% qP.P = Conditional expectation +% qP.C = Conditional covariance +% +% conditional moments of hyper-parameters (log-transformed) - q(h) +%-------------------------------------------------------------------------- +% qH.h = Conditional expectation (cause noise) +% qH.g = Conditional expectation (state noise) +% qH.C = Conditional covariance +% +% F = log-evidence = log-marginal likelihood = negative free-energy +%__________________________________________________________________________ +% +% spm_LAP implements a variational scheme under the Laplace +% approximation to the conditional joint density q on states (u), parameters +% (p) and hyperparameters (h,g) of any analytic nonlinear hierarchical dynamic +% model, with additive Gaussian innovations. +% +% q(u,p,h,g) = max q +% +% L is the ln p(y,u,p,h,g|M) under the model M. The conditional covariances +% obtain analytically from the curvature of L with respect to the unknowns. +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: spm_LAP.m 3977 2010-07-08 14:14:35Z karl $ + + +% find or create a DEM figure +%-------------------------------------------------------------------------- +try + DEM.M(1).nograph; +catch + DEM.M(1).nograph = 0; +end +if ~DEM.M(1).nograph + Fdem = spm_figure('GetWin','DEM'); +end + + +% check model, data and priors +%========================================================================== +[M Y U] = spm_DEM_set(DEM); + + +% number of iterations +%-------------------------------------------------------------------------- +try, nD = M(1).E.nD; catch, nD = 1; end +try, nN = M(1).E.nN; catch, nN = 16; end + + +% ensure integration scheme evaluates gradients at each time-step +%-------------------------------------------------------------------------- +M(1).E.linear = 4; + +% assume precisions are a function of, and only of, hyperparameters +%-------------------------------------------------------------------------- +try + method = M(1).E.method; +catch + method.h = 1; + method.g = 1; + method.x = 0; + method.v = 0; +end +try method.h; catch, method.h = 0; end +try method.g; catch, method.g = 0; end +try method.x; catch, method.x = 0; end +try method.v; catch, method.v = 0; end + +M(1).E.method = method; + +% assume precisions are a function of, and only of, hyperparameters +%-------------------------------------------------------------------------- +try + form = M(1).E.form; +catch + form = 'Gaussian'; +end + +% checks for Laplace models (precision functions; ph and pg) +%-------------------------------------------------------------------------- +for i = 1:length(M) + try + feval(M(i).ph,M(i).x,M(i).v,M(i).hE,M(i)); + catch + M(i).ph = inline('spm_LAP_ph(x,v,h,M)','x','v','h','M'); + end + try + feval(M(i).pg,M(i).x,M(i).v,M(i).gE,M(i)); + catch + M(i).pg = inline('spm_LAP_pg(x,v,h,M)','x','v','h','M'); + end +end + + +% order parameters (d = n = 1 for static models) and checks +%========================================================================== +d = M(1).E.d + 1; % embedding order of q(v) +n = M(1).E.n + 1; % embedding order of q(x) + +% number of states and parameters +%-------------------------------------------------------------------------- +ns = size(Y,2); % number of samples +nl = size(M,2); % number of levels +nv = sum(spm_vec(M.m)); % number of v (casual states) +nx = sum(spm_vec(M.n)); % number of x (hidden states) +ny = M(1).l; % number of y (inputs) +nc = M(end).l; % number of c (prior causes) +nu = nv*d + nx*n; % number of generalised states +ne = nv*n + nx*n + ny*n; % number of generalised errors + + +% precision (R) of generalised errors and null matrices for concatenation +%========================================================================== +s = M(1).E.s; +Rh = spm_DEM_R(n,s,form); +Rg = spm_DEM_R(n,s,form); + +W = sparse(nx*n,nx*n); +V = sparse((ny + nv)*n,(ny + nv)*n); + + +% fixed priors on states (u) +%-------------------------------------------------------------------------- +Px = kron(sparse(1,1,1,n,n),spm_cat(spm_diag({M.xP}))); +Pv = kron(sparse(1,1,1,d,d),sparse(nv,nv)); +pu.ic = spm_cat(spm_diag({Px Pv})); + +% hyperpriors +%-------------------------------------------------------------------------- +ph.h = spm_vec({M.hE M.gE}); % prior expectation of h,g +ph.c = spm_cat(spm_diag({M.hC M.gC})); % prior covariances of h,g +ph.ic = spm_pinv(ph.c); % prior precision of h,g + +qh.h = {M.hE}; % conditional expectation h +qh.g = {M.gE}; % conditional expectation g +nh = length(spm_vec(qh.h)); % number of hyperparameters h +ng = length(spm_vec(qh.g)); % number of hyperparameters g +nb = nh + ng; % number of hyerparameters + + +% 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 deviates + pp.c{i,i} = qp.u{i}'*M(i).pC*qp.u{i}; % prior covariance + +end +Up = spm_cat(spm_diag(qp.u)); + +% priors on parameters +%-------------------------------------------------------------------------- +pp.p = spm_vec(M.pE); +pp.c = spm_cat(pp.c); +pp.ic = spm_inv(pp.c); + +% initialise conditional density q(p) +%-------------------------------------------------------------------------- +for i = 1:(nl - 1) + try + qp.p{i} = qp.p{i} + qp.u{i}'*(spm_vec(M(i).P) - spm_vec(M(i).pE)); + end +end +np = size(Up,2); + + +% initialise cell arrays for D-Step; e{i + 1} = (d/dt)^i[e] = e[i] +%========================================================================== +qu.x = cell(n,1); +qu.v = cell(n,1); +qu.y = cell(n,1); +qu.u = cell(n,1); +[qu.x{:}] = deal(sparse(nx,1)); +[qu.v{:}] = deal(sparse(nv,1)); +[qu.y{:}] = deal(sparse(ny,1)); +[qu.u{:}] = deal(sparse(nc,1)); + +% initialise cell arrays for hierarchical structure of x[0] and v[0] +%-------------------------------------------------------------------------- +x = {M(1:end - 1).x}; +v = {M(1 + 1:end).v}; +qu.x{1} = spm_vec(x); +qu.v{1} = spm_vec(v); + +% derivatives for Jacobian of D-step +%-------------------------------------------------------------------------- +Dx = kron(spm_speye(n,n,1),spm_speye(nx,nx)); +Dv = kron(spm_speye(d,d,1),spm_speye(nv,nv)); +Dy = kron(spm_speye(n,n,1),spm_speye(ny,ny)); +Dc = kron(spm_speye(d,d,1),spm_speye(nc,nc)); +Du = spm_cat(spm_diag({Dx,Dv})); +Ip = spm_speye(np,np); +Ih = spm_speye(nb,nb); +qp.dp = sparse(np,1); % conditional expectation of dp/dt +qh.dp = sparse(nb,1); % conditional expectation of dh/dt + + +% gradients of generalised weighted errors +%-------------------------------------------------------------------------- +dedh = sparse(nh,ne); +dedg = sparse(ng,ne); +dedv = sparse(nv,ne); +dedx = sparse(nx,ne); +dedhh = sparse(nh,nh); +dedgg = sparse(ng,ng); + +% curvatures of Gibb's energy w.r.t. hyperparameters +%-------------------------------------------------------------------------- +dHdh = sparse(nh, 1); +dHdg = sparse(ng, 1); +dHdp = sparse(np, 1); +dHdx = sparse(nx*n,1); +dHdv = sparse(nv*d,1); + +% preclude unnecessary iterations and set switchs +%-------------------------------------------------------------------------- +if ~np && ~nh && ~ng, nN = 1; end +mnx = nx*~~method.x; +mnv = nv*~~method.v; + + +% preclude very precise states from entering free-energy +%-------------------------------------------------------------------------- +[p dp] = spm_LAP_eval(M,qu,qh); +ih = p.h < 16; +ig = p.g < 16; +iv = kron(ones(d,1),ih([1:nv] + ny)); +ix = kron(ones(n,1),ig); +iu = logical([ix; iv]); +iup = logical([iu; ones(np,1)]); + +% Iterate Lapalace scheme +%========================================================================== +Fa = -Inf; +for iN = 1:nN + + % get time and clear persistent variables in evaluation routines + %---------------------------------------------------------------------- + tic; clear spm_DEM_eval + + % [re-]set states & their derivatives + %---------------------------------------------------------------------- + try, qu = Q(1).u; end + + + % D-Step: (nD D-Steps for each sample) + %====================================================================== + for is = 1:ns + + % D-Step: until convergence for static systems + %================================================================== + for iD = 1:nD + + % sampling time + %-------------------------------------------------------------- + ts = is + (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 + + + % evaluate functions and derivatives + %============================================================== + + % prediction errors (E) and precision vectors (p) + %-------------------------------------------------------------- + [E dE] = spm_DEM_eval(M,qu,qp); + [p dp] = spm_LAP_eval(M,qu,qh); + + + % gradients of log(det(iS)) dDd... + %============================================================== + + % get precision matrices (iSS is conditioned) + %-------------------------------------------------------------- + iSh = diag(exp(p.h)); + iSg = diag(exp(p.g)); + iS = blkdiag(kron(Rh,iSh),kron(Rg,iSg)); + iSh = diag(exp(p.h).*ih); + iSg = diag(exp(p.g).*ig); + iSS = blkdiag(kron(Rh,iSh),kron(Rg,iSg)); + + + % gradients of trace(diag(p)) = sum(p); p = precision vector + %-------------------------------------------------------------- + dpdx = n*sum(spm_cat({dp.h.dx; dp.g.dx})); + dpdv = n*sum(spm_cat({dp.h.dv; dp.g.dv})); + dpdh = n*sum(dp.h.dh); + dpdg = n*sum(dp.g.dg); + dpdx = kron(sparse(1,1,1,1,n),dpdx); + dpdv = kron(sparse(1,1,1,1,d),dpdv); + dDdu = [dpdx dpdv]'; + dDdh = [dpdh dpdg]'; + + + % gradients precision-weighted generalised error dSd.. + %============================================================== + + % gradients w.r.t. hyperparameters + %-------------------------------------------------------------- + for i = 1:nh + diS = diag(dp.h.dh(:,i).*exp(p.h)); + diSdh{i} = blkdiag(kron(Rh,diS),W); + dedh(i,:) = E'*diSdh{i}; + end + for i = 1:ng + diS = diag(dp.g.dg(:,i).*exp(p.g)); + diSdg{i} = blkdiag(V,kron(Rg,diS)); + dedg(i,:) = E'*diSdg{i}; + end + + % gradients w.r.t. hidden states + %-------------------------------------------------------------- + for i = 1:mnx + diV = diag(dp.h.dx(:,i).*exp(p.h)); + diW = diag(dp.g.dx(:,i).*exp(p.g)); + diSdx{i} = blkdiag(kron(Rh,diV),kron(Rg,diW)); + dedx(i,:) = E'*diSdx{i}; + end + + % gradients w.r.t. causal states + %-------------------------------------------------------------- + for i = 1:mnv + diV = diag(dp.h.dv(:,i).*exp(p.h)); + diW = diag(dp.g.dv(:,i).*exp(p.g)); + diSdv{i} = blkdiag(kron(Rh,diV),kron(Rg,diW)); + dedv(i,:) = E'*diSdv{i}; + end + + dSdx = kron(sparse(1,1,1,n,1),dedx); + dSdv = kron(sparse(1,1,1,d,1),dedv); + dSdu = [dSdx; dSdv]; + dEdh = [dedh; dedg]; + dEdp = dE.dp'*iS; + dEdu = dE.du'*iS; + + % curvatures w.r.t. hyperparameters + %-------------------------------------------------------------- + for i = 1:nh + for j = i:nh + diS = diag(dp.h.dh(:,i).*dp.h.dh(:,j).*exp(p.h)); + diS = blkdiag(kron(Rh,diS),W); + dedhh(i,j) = E'*diS*E; + dedhh(j,i) = dedhh(i,j); + end + end + for i = 1:ng + for j = i:ng + diS = diag(dp.g.dg(:,i).*dp.g.dg(:,j).*exp(p.g)); + diS = blkdiag(V,kron(Rg,diS)); + dedgg(i,j) = E'*diS*E; + dedgg(j,i) = dedgg(i,j); + end + end + + % combined curvature + %-------------------------------------------------------------- + dSdhh = spm_cat({dedhh [] ; + [] dedgg}); + + + % errors (from prior expectations) (NB pp.p = 0) + %-------------------------------------------------------------- + Eu = spm_vec(qu.x(1:n),qu.v(1:d)); + Ep = spm_vec(qp.p); + Eh = spm_vec(qh.h,qh.g) - ph.h; + + + % first-order derivatives of Gibb's Energy + %============================================================== + dLdu = dEdu*E + dSdu*E/2 - dDdu/2 + pu.ic*Eu; + dLdh = dEdh*E/2 - dDdh/2 + ph.ic*Eh; + dLdp = dEdp*E + pp.ic*Ep; + + + % and second-order derivatives of Gibb's Energy + %-------------------------------------------------------------- + dLduu = dEdu*dE.du + pu.ic; + dLdpp = dEdp*dE.dp + pp.ic; + dLdhh = dSdhh/2 + ph.ic; + dLdup = dEdu*dE.dp; + dLdhu = dEdh*dE.du; + dLduy = dEdu*dE.dy; + dLduc = dEdu*dE.dc; + dLdpy = dEdp*dE.dy; + dLdpc = dEdp*dE.dc; + dLdhy = dEdh*dE.dy; + dLdhc = dEdh*dE.dc; + dLdpu = dLdup'; + + + % precision and covariances + %-------------------------------------------------------------- + iC = spm_cat({dLduu dLdup; + dLdpu dLdpp}); + + C = spm_inv(iC); + iC = iC(iup,iup); + + % first-order derivatives of Entropy term + %============================================================== + + % log-precision + %-------------------------------------------------------------- + for i = 1:nh + Luub = dE.du'*diSdh{i}*dE.du; + Lpub = dE.dp'*diSdh{i}*dE.du; + Lppb = dE.dp'*diSdh{i}*dE.dp; + diCdh = spm_cat({Luub Lpub'; + Lpub Lppb}); + dHdh(i) = sum(sum(diCdh.*C))/2; + end + for i = 1:ng + Luub = dE.du'*diSdg{i}*dE.du; + Lpub = dE.dp'*diSdg{i}*dE.du; + Lppb = dE.dp'*diSdg{i}*dE.dp; + diCdg = spm_cat({Luub Lpub'; + Lpub Lppb}); + dHdg(i) = sum(sum(diCdg.*C))/2; + end + + % parameters + %-------------------------------------------------------------- + for i = 1:np + Luup = dE.dup{i}'*dEdu'; + Lpup = dEdp*dE.dup{i}; + Luup = Luup + Luup'; + diCdp = spm_cat({Luup Lpup'; + Lpup [] }); + dHdp(i) = sum(sum(diCdp.*C))/2; + end + + dHdb = [dHdh; dHdg]; + dHdu = [dHdx; dHdv]; + + + % save conditional moments (and prediction error) at Q{t} + %============================================================== + if iD == 1 + + % save means + %---------------------------------------------------------- + Q(is).e = E; + Q(is).E = iS*E; + Q(is).u = qu; + Q(is).p = qp; + Q(is).h = qh; + + % and conditional covariances + %---------------------------------------------------------- + Q(is).u.s = C((1:nx),(1:nx)); + Q(is).u.c = C((1:nv) + nx*n, (1:nv) + nx*n); + Q(is).p.c = C((1:np) + nu, (1:np) + nu); + Q(is).h.c = spm_inv(dLdhh); + Cu = C(iu,iu); + + + % Free-energy (components) + %---------------------------------------------------------- +% Fc(is,1) = - E'*iSS*E/2; +% Fc(is,2) = spm_logdet(iSS)/2; +% Fc(is,3) = - Eu'*pu.ic*Eu/2; +% Fc(is,4) = spm_logdet(pp.ic)/2; +% Fc(is,5) = - Ep'*pp.ic*Ep/2; +% Fc(is,6) = spm_logdet(pp.ic)/2; +% Fc(is,7) = - Eh'*ph.ic*Eh/2; +% Fc(is,8) = spm_logdet(ph.ic)/2; +% Fc(is,9) = - spm_logdet(iC)/2; +% Fc(is,10) = - spm_logdet(dLdhh)/2; + + + % Free-energy + %---------------------------------------------------------- + L(is) = - E'*iSS*E/2 + spm_logdet(iSS)/2 ... + - Eu'*pu.ic*Eu/2 + spm_logdet(pu.ic)/2 ... + - n*ny*log(2*pi)/2; + + % Free-energy (states and parameters) + %---------------------------------------------------------- + A(is) = L(is) ... + - Ep'*pp.ic*Ep/2 + spm_logdet(pp.ic)/2 ... + - Eh'*ph.ic*Eh/2 + spm_logdet(ph.ic)/2 ... + - spm_logdet(iC)/2 - spm_logdet(dLdhh)/2; + + % Free-energy (states) + %---------------------------------------------------------- + L(is) = L(is) + spm_logdet(Cu)/2; + + end + + % update conditional moments + %============================================================== + + % precision of fluctuations on parameters of hyperparameters + %-------------------------------------------------------------- + Kp = ns*Ip; + Kh = ns*Ih*2; + + % uopdate curvatures of [hyper]paramters + %-------------------------------------------------------------- + nk = 128; + try + dLdPP = dLdPP*(1 - 1/nk) + dLdpp/nk; + dLdHH = dLdHH*(1 - 1/nk) + dLdhh/nk; + catch + dLdPP = dLdpp*16; + dLdHH = dLdhh*16; + end + + % rotate and scale gradient (and curvatures) + %-------------------------------------------------------------- + [Vp Sp] = spm_svd(dLdPP,0); + [Vh Sh] = spm_svd(dLdHH,0); + Sp = diag(1./(diag(Sp))); + Sh = diag(1./(diag(Sh))); + + dLdp = Sp*Vp'*dLdp; + dHdp = Sp*Vp'*dHdp; + dLdpy = Sp*Vp'*dLdpy; + dLdpu = Sp*Vp'*dLdpu; + dLdpc = Sp*Vp'*dLdpc; + + dLdh = Sh*Vh'*dLdh; + dHdb = Sh*Vh'*dHdb; + dLdhy = Sh*Vh'*dLdhy; + dLdhu = Sh*Vh'*dLdhu; + dLdhc = Sh*Vh'*dLdhc; + + + + % assemble conditional means + %-------------------------------------------------------------- + q_p = spm_unvec(Vp'*spm_vec(qp.p),qp.p); + q_b = spm_unvec(Vh'*spm_vec({qh.h qh.g}),{qh.h qh.g}); + q{1} = qu.y(1:n); + q{2} = qu.x(1:n); + q{3} = qu.v(1:d); + q{4} = qu.u(1:d); + q{5} = q_p; + q{6} = q_b{1}; + q{7} = q_b{2}; + q{8} = Vp'*qp.dp; + q{9} = Vh'*qh.dp; + + + + % flow + %-------------------------------------------------------------- + f{1} = Dy*spm_vec(q{1}); + f{2} = Du*spm_vec(q{2:3}) - dLdu - dHdu; + f{3} = Dc*spm_vec(q{4}); + f{4} = spm_vec(q{8}); + f{5} = spm_vec(q{9}); + f{6} = -Kp*spm_vec(q{8}) - dLdp - dHdp; + f{7} = -Kh*spm_vec(q{9}) - dLdh - dHdb; + + + % and Jacobian + %-------------------------------------------------------------- + dfdq = spm_cat({Dy [] [] [] [] [] []; + -dLduy Du-dLduu -dLduc [] [] [] []; + [] [] Dc [] [] [] []; + [] [] [] [] [] Ip []; + [] [] [] [] [] [] Ih; + -dLdpy -dLdpu -dLdpc -Ip [] -Kp []; + -dLdhy -dLdhu -dLdhc [] -Ih [] -Kh}); + + + % update conditional modes of states + %============================================================== + dq = spm_dx(dfdq, spm_vec(f), 1/nD); + q = spm_unvec(spm_vec(q) + dq,q); + + % unpack conditional means + %-------------------------------------------------------------- + q_p = spm_unvec(Vp*spm_vec(q{5}),qp.p); + q_b = spm_unvec(Vh*spm_vec(q{6:7}),{qh.h qh.g}); + qu.x(1:n) = q{2}; + qu.v(1:d) = q{3}; + qp.p = q_p; + qh.h = q_b{1}; + qh.g = q_b{2}; + qp.dp = Vp*q{8}; + qh.dp = Vh*q{9}; + + + end % D-Step + + end % sequence (ns) + + + % Bayesian parameter averaging + %====================================================================== + + % Conditional moments of time-averaged parameters + %---------------------------------------------------------------------- + Pp = 0; + Ep = 0; + for i = 1:ns + P = spm_inv(Q(i).p.c); + Ep = Ep + P*spm_vec(Q(i).p.p); + Pp = Pp + P; + end + Cp = spm_inv(Pp); + Ep = Cp*Ep; + + % conditional moments of hyper-parameters + %---------------------------------------------------------------------- + Ph = 0; + Eh = 0; + for i = 1:ns + P = spm_inv(Q(i).h.c); + Ph = Ph + P; + Eh = Eh + P*spm_vec({Q(i).h.h Q(i).h.g}); + end + Ch = spm_inv(Ph); + Eh = Ch*Eh - ph.h; + + % Free-action of states plus free-energy of parameters + %====================================================================== + Fs = sum(A); + Fi = sum(L) ... + - Ep'*pp.ic*Ep/2 + spm_logdet(pp.ic)/2 - spm_logdet(Pp)/2 ... + - Eh'*ph.ic*Eh/2 + spm_logdet(ph.ic)/2 - spm_logdet(Ph)/2; + + try, disp(full(sum(Fc))), end + + % if F is increasing terminate + %---------------------------------------------------------------------- + if Fi < Fa && iN > 2 + break + else + Fa = Fi; + F(iN) = Fi; + S(iN) = Fs; + end + + % otherwise save conditional moments (for each time point) + %====================================================================== + for t = 1:length(Q) + + + % states and predictions + %------------------------------------------------------------------ + v = spm_unvec(Q(t).u.v{1},v); + x = spm_unvec(Q(t).u.x{1},x); + z = spm_unvec(Q(t).e(1:(ny + nv)),{M.v}); + Z = spm_unvec(Q(t).E(1:(ny + nv)),{M.v}); + w = spm_unvec(Q(t).e((1:nx) + (ny + nv)*n),{M.x}); + X = spm_unvec(Q(t).E((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 + if M(i).n, qU.W{i}(:,t) = spm_vec(X{i}); end + if M(i).l, qU.Z{i}(:,t) = spm_vec(Z{i}); end + end + if M(nl).l, qU.z{nl}(:,t) = spm_vec(z{nl}); end + if M(nl).l, qU.Z{nl}(:,t) = spm_vec(Z{nl}); end + + qU.v{1}(:,t) = spm_vec(Q(t).u.y{1}) - spm_vec(z{1}); + + % and conditional covariances + %------------------------------------------------------------------ + qU.S{t} = Q(t).u.s; + qU.C{t} = Q(t).u.c; + + % parameters + %------------------------------------------------------------------ + qP.p{t} = spm_vec(Q(t).p.p); + qP.c{t} = Q(t).p.c; + + % hyperparameters + %------------------------------------------------------------------ + qH.p{t} = spm_vec({Q(t).h.h Q(t).h.g}); + qH.c{t} = Q(t).h.c; + + end + + % graphics (states) + %---------------------------------------------------------------------- + figure(Fdem) + spm_DEM_qU(qU) + + % graphics (parameters and log-precisions) + %---------------------------------------------------------------------- + if np && nb + subplot(2*nl,2,4*nl - 2) + plot(1:ns,spm_cat(qP.p)) + set(gca,'XLim',[1 ns]) + title('parameters (modes)','FontSize',16) + + subplot(2*nl,2,4*nl) + plot(1:ns,spm_cat(qH.p)) + set(gca,'XLim',[1 ns]) + title('log-precision','FontSize',16) + + elseif nb + subplot(nl,2,2*nl) + plot(1:ns,spm_cat(qH.p)) + set(gca,'XLim',[1 ns]) + title('log-precision','FontSize',16) + + elseif np + subplot(nl,2,2*nl) + plot(1:ns,spm_cat(qP.p)) + set(gca,'XLim',[1 ns]) + title('parameters (modes)','FontSize',16) + + end + drawnow + + % report (EM-Steps) + %---------------------------------------------------------------------- + try + dF = F(end) - F(end - 1); + catch + dF = 0; + end + str{1} = sprintf('LAP: %i (%i)', iN,iD); + str{2} = sprintf('F:%.4e', full(F(iN) - F(1))); + str{3} = sprintf('dF:%.2e', full(dF)); + str{4} = sprintf('(%.2e sec)', full(toc)); + fprintf('%-16s%-16s%-14s%-16s\n',str{:}) + +end + + +% Place Bayesian parameter averages in output arguments +%========================================================================== + +% Conditional moments of time-averaged parameters +%-------------------------------------------------------------------------- +Pp = 0; +Ep = 0; +for i = 1:ns + + % weight in proportion to precisions + %---------------------------------------------------------------------- + P = spm_inv(qP.c{i}); + Ep = Ep + P*qP.p{i}; + Pp = Pp + P; + +end +Cp = spm_inv(Pp); +Ep = Cp*Ep; +P = {M.pE}; +qP.P = spm_unvec(Up*Ep + pp.p,P); +qP.C = Up*Cp*Up'; +qP.V = spm_unvec(diag(qP.C),P); +qP.U = Up; + +% conditional moments of hyper-parameters +%-------------------------------------------------------------------------- +Ph = 0; +Eh = 0; +for i = 1:ns + + % weight in proportion to precisions + %---------------------------------------------------------------------- + P = spm_inv(qH.c{i}); + Ph = Ph + P; + Eh = Eh + P*qH.p{i}; + +end +Ch = spm_inv(Ph); +Eh = Ch*Eh; +P = {qh.h qh.g}; +P = spm_unvec(Eh,P); +qH.h = P{1}; +qH.g = P{2}; +qH.C = Ch; +P = spm_unvec(diag(qH.C),P); +qH.V = P{1}; +qH.W = P{2}; + + + +% assign output variables +%-------------------------------------------------------------------------- +DEM.M = M; % model +DEM.U = U; % causes + +DEM.qU = qU; % conditional moments of model-states +DEM.qP = qP; % conditional moments of model-parameters +DEM.qH = qH; % conditional moments of hyper-parameters + +DEM.F = F; % [-ve] Free energy +DEM.S = S; % [-ve] Free action + +return + + + + + + + + diff --git a/spm_LAPF.m b/spm_LAPF.m new file mode 100644 index 0000000..affd5f4 --- /dev/null +++ b/spm_LAPF.m @@ -0,0 +1,905 @@ +function [DEM] = spm_LAP(DEM) +% Laplacian model inversion (see also spm_LAPS) +% FORMAT DEM = spm_LAP(DEM) +% +% DEM.M - hierarchical model +% DEM.Y - response variable, output or data +% DEM.U - explanatory variables, inputs or prior expectation of causes +%__________________________________________________________________________ +% +% generative model +%-------------------------------------------------------------------------- +% M(i).g = v = g(x,v,P) {inline function, string or m-file} +% M(i).f = dx/dt = f(x,v,P) {inline function, string or m-file} +% +% M(i).ph = pi(v) = ph(x,v,h,M) {inline function, string or m-file} +% M(i).pg = pi(x) = pg(x,v,g,M) {inline function, string or m-file} +% +% M(i).pE = prior expectation of p model-parameters +% M(i).pC = prior covariances of p model-parameters +% M(i).hE = prior expectation of h log-precision (cause noise) +% M(i).hC = prior covariances of h log-precision (cause noise) +% M(i).gE = prior expectation of g log-precision (state noise) +% M(i).gC = prior covariances of g log-precision (state noise) +% M(i).xP = precision (states) +% M(i).Q = precision components (input noise) +% M(i).R = precision components (state noise) +% M(i).V = fixed precision (input noise) +% M(i).W = fixed precision (state noise) +% +% M(i).m = number of inputs v(i + 1); +% M(i).n = number of states x(i); +% M(i).l = number of output v(i); +% +% conditional moments of model-states - q(u) +%-------------------------------------------------------------------------- +% qU.x = Conditional expectation of hidden states +% qU.v = Conditional expectation of causal states +% qU.w = Conditional prediction error (states) +% qU.z = Conditional prediction error (causes) +% qU.C = Conditional covariance: cov(v) +% qU.S = Conditional covariance: cov(x) +% +% conditional moments of model-parameters - q(p) +%-------------------------------------------------------------------------- +% qP.P = Conditional expectation +% qP.C = Conditional covariance +% +% conditional moments of hyper-parameters (log-transformed) - q(h) +%-------------------------------------------------------------------------- +% qH.h = Conditional expectation (cause noise) +% qH.g = Conditional expectation (state noise) +% qH.C = Conditional covariance +% +% F = log-evidence = log-marginal likelihood = negative free-energy +%__________________________________________________________________________ +% +% spm_LAP implements a variational scheme under the Laplace +% approximation to the conditional joint density q on states (u), parameters +% (p) and hyperparameters (h,g) of any analytic nonlinear hierarchical dynamic +% model, with additive Gaussian innovations. +% +% q(u,p,h,g) = max q +% +% L is the ln p(y,u,p,h,g|M) under the model M. The conditional covariances +% obtain analytically from the curvature of L with respect to the unknowns. +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: spm_LAPF.m 3888 2010-05-15 18:49:56Z karl $ + + +% find or create a DEM figure +%-------------------------------------------------------------------------- +try + DEM.M(1).nograph; +catch + DEM.M(1).nograph = 0; +end +if ~DEM.M(1).nograph + Fdem = spm_figure('GetWin','DEM'); +end + + +% check model, data and priors +%========================================================================== +[M Y U] = spm_DEM_set(DEM); + + +% number of iterations +%-------------------------------------------------------------------------- +try, nD = M(1).E.nD; catch, nD = 1; end +try, nN = M(1).E.nN; catch, nN = 16; end + + +% ensure integration scheme evaluates gradients at each time-step +%-------------------------------------------------------------------------- +M(1).E.linear = 4; + +% assume precisions are a function of, and only of, hyperparameters +%-------------------------------------------------------------------------- +try + method = M(1).E.method; +catch + method.h = 1; + method.g = 1; + method.x = 0; + method.v = 0; +end +try method.h; catch, method.h = 0; end +try method.g; catch, method.g = 0; end +try method.x; catch, method.x = 0; end +try method.v; catch, method.v = 0; end + +M(1).E.method = method; + +% assume precisions are a function of, and only of, hyperparameters +%-------------------------------------------------------------------------- +try + form = M(1).E.form; +catch + form = 'Gaussian'; +end + +% checks for Laplace models (precision functions; ph and pg) +%-------------------------------------------------------------------------- +for i = 1:length(M) + try + feval(M(i).ph,M(i).x,M(i).v,M(i).hE,M(i)); + catch + M(i).ph = inline('spm_LAP_ph(x,v,h,M)','x','v','h','M'); + end + try + feval(M(i).pg,M(i).x,M(i).v,M(i).gE,M(i)); + catch + M(i).pg = inline('spm_LAP_pg(x,v,h,M)','x','v','h','M'); + end +end + + +% order parameters (d = n = 1 for static models) and checks +%========================================================================== +d = M(1).E.d + 1; % embedding order of q(v) +n = M(1).E.n + 1; % embedding order of q(x) + +% number of states and parameters +%-------------------------------------------------------------------------- +ns = size(Y,2); % number of samples +nl = size(M,2); % number of levels +nv = sum(spm_vec(M.m)); % number of v (casual states) +nx = sum(spm_vec(M.n)); % number of x (hidden states) +ny = M(1).l; % number of y (inputs) +nc = M(end).l; % number of c (prior causes) +nu = nv*d + nx*n; % number of generalised states +ne = nv*n + nx*n + ny*n; % number of generalised errors + + +% precision (R) of generalised errors and null matrices for concatenation +%========================================================================== +s = M(1).E.s; +Rh = spm_DEM_R(n,s,form); +Rg = spm_DEM_R(n,s,form); + +W = sparse(nx*n,nx*n); +V = sparse((ny + nv)*n,(ny + nv)*n); + + +% fixed priors on states (u) +%-------------------------------------------------------------------------- +Px = kron(sparse(1,1,1,n,n),spm_cat(spm_diag({M.xP}))); +Pv = kron(sparse(1,1,1,d,d),sparse(nv,nv)); +pu.ic = spm_cat(spm_diag({Px Pv})); + +% hyperpriors +%-------------------------------------------------------------------------- +ph.h = spm_vec({M.hE M.gE}); % prior expectation of h,g +ph.c = spm_cat(spm_diag({M.hC M.gC})); % prior covariances of h,g +ph.ic = spm_pinv(ph.c); % prior precision of h,g + +qh.h = {M.hE}; % conditional expectation h +qh.g = {M.gE}; % conditional expectation g +nh = length(spm_vec(qh.h)); % number of hyperparameters h +ng = length(spm_vec(qh.g)); % number of hyperparameters g +nb = nh + ng; % number of hyerparameters + + +% 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); % basis for parameters + M(i).p = size(qp.u{i},2); % number of qp.p + qp.p{i} = sparse(M(i).p,1); % initial deviates + pp.c{i,i} = qp.u{i}'*M(i).pC*qp.u{i}; % prior covariance + +end +Up = spm_cat(spm_diag(qp.u)); + +% priors on parameters +%-------------------------------------------------------------------------- +pp.p = spm_vec(M.pE); +pp.c = spm_cat(pp.c); +pp.ic = spm_inv(pp.c); + +% initialise conditional density q(p) +%-------------------------------------------------------------------------- +for i = 1:(nl - 1) + try + qp.p{i} = qp.p{i} + qp.u{i}'*(spm_vec(M(i).P) - spm_vec(M(i).pE)); + end +end +np = size(Up,2); + + +% initialise cell arrays for D-Step; e{i + 1} = (d/dt)^i[e] = e[i] +%========================================================================== +qu.x = cell(n,1); +qu.v = cell(n,1); +qu.y = cell(n,1); +qu.u = cell(n,1); +[qu.x{:}] = deal(sparse(nx,1)); +[qu.v{:}] = deal(sparse(nv,1)); +[qu.y{:}] = deal(sparse(ny,1)); +[qu.u{:}] = deal(sparse(nc,1)); + +% initialise cell arrays for hierarchical structure of x[0] and v[0] +%-------------------------------------------------------------------------- +x = {M(1:end - 1).x}; +v = {M(1 + 1:end).v}; +qu.x{1} = spm_vec(x); +qu.v{1} = spm_vec(v); + +% derivatives for Jacobian of D-step +%-------------------------------------------------------------------------- +Dx = kron(spm_speye(n,n,1),spm_speye(nx,nx)); +Dv = kron(spm_speye(d,d,1),spm_speye(nv,nv)); +Dy = kron(spm_speye(n,n,1),spm_speye(ny,ny)); +Dc = kron(spm_speye(d,d,1),spm_speye(nc,nc)); +Du = spm_cat(spm_diag({Dx,Dv})); +Ip = spm_speye(np,np); +Ih = spm_speye(nb,nb); +qp.dp = sparse(np,1); % conditional expectation of dp/dt +qh.dp = sparse(nb,1); % conditional expectation of dh/dt + +% precision of fluctuations on parameters of hyperparameters +%-------------------------------------------------------------------------- +Kp = ns*Ip; +Kh = ns*Ih; + +% gradients of generalised weighted errors +%-------------------------------------------------------------------------- +dedh = sparse(nh,ne); +dedg = sparse(ng,ne); +dedv = sparse(nv,ne); +dedx = sparse(nx,ne); +dedhh = sparse(nh,nh); +dedgg = sparse(ng,ng); + +% curvatures of Gibb's energy w.r.t. hyperparameters +%-------------------------------------------------------------------------- +dHdh = sparse(nh, 1); +dHdg = sparse(ng, 1); +dHdp = sparse(np, 1); +dHdx = sparse(nx*n,1); +dHdv = sparse(nv*d,1); + +% preclude unnecessary iterations and set switchs +%-------------------------------------------------------------------------- +if ~np && ~nh && ~ng, nN = 1; end +mnx = nx*~~method.x; +mnv = nv*~~method.v; + + +% Iterate Lapalace scheme +%========================================================================== +Fa = -Inf; +for iN = 1:nN + + % get time and clear persistent variables in evaluation routines + %---------------------------------------------------------------------- + tic; clear spm_DEM_eval + + % [re-]set states & their derivatives + %---------------------------------------------------------------------- + try, qu = Q(1).u; end + + + % D-Step: (nD D-Steps for each sample) + %====================================================================== + for is = 1:ns + + % D-Step: until convergence for static systems + %================================================================== + for iD = 1:nD + + % sampling time + %-------------------------------------------------------------- + ts = is + (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 + + + % evaluate functions and derivatives + %============================================================== + + % prediction errors (E) and precision vectors (p) + %-------------------------------------------------------------- + [E dE] = spm_DEM_eval(M,qu,qp); + [p dp] = spm_LAP_eval(M,qu,qh); + + + % gradients of log(det(iS)) dDd... + %============================================================== + + % get precision matrices + %-------------------------------------------------------------- + iSh = diag(exp(p.h)); + iSg = diag(exp(p.g)); + iS = blkdiag(kron(Rh,iSh),kron(Rg,iSg)); + + + % gradients of trace(diag(p)) = sum(p); p = precision vector + %-------------------------------------------------------------- + dpdx = n*sum(spm_cat({dp.h.dx; dp.g.dx})); + dpdv = n*sum(spm_cat({dp.h.dv; dp.g.dv})); + dpdh = n*sum(dp.h.dh); + dpdg = n*sum(dp.g.dg); + dpdx = kron(sparse(1,1,1,1,n),dpdx); + dpdv = kron(sparse(1,1,1,1,d),dpdv); + dDdu = [dpdx dpdv]'; + dDdh = [dpdh dpdg]'; + + + % gradients precision-weighted generalised error dSd.. + %============================================================== + + % gradients w.r.t. hyperparameters + %-------------------------------------------------------------- + for i = 1:nh + diS = diag(dp.h.dh(:,i).*exp(p.h)); + diSdh{i} = blkdiag(kron(Rh,diS),W); + dedh(i,:) = E'*diSdh{i}; + end + for i = 1:ng + diS = diag(dp.g.dg(:,i).*exp(p.g)); + diSdg{i} = blkdiag(V,kron(Rg,diS)); + dedg(i,:) = E'*diSdg{i}; + end + + % gradients w.r.t. hidden states + %-------------------------------------------------------------- + for i = 1:mnx + diV = diag(dp.h.dx(:,i).*exp(p.h)); + diW = diag(dp.g.dx(:,i).*exp(p.g)); + diSdx{i} = blkdiag(kron(Rh,diV),kron(Rg,diW)); + dedx(i,:) = E'*diSdx{i}; + end + + % gradients w.r.t. causal states + %-------------------------------------------------------------- + for i = 1:mnv + diV = diag(dp.h.dv(:,i).*exp(p.h)); + diW = diag(dp.g.dv(:,i).*exp(p.g)); + diSdv{i} = blkdiag(kron(Rh,diV),kron(Rg,diW)); + dedv(i,:) = E'*diSdv{i}; + end + + dSdx = kron(sparse(1,1,1,n,1),dedx); + dSdv = kron(sparse(1,1,1,d,1),dedv); + dSdu = [dSdx; dSdv]; + dEdh = [dedh; dedg]; + dEdp = dE.dp'*iS; + dEdu = dE.du'*iS; + + % curvatures w.r.t. hyperparameters + %-------------------------------------------------------------- + for i = 1:nh + for j = i:nh + diS = diag(dp.h.dh(:,i).*dp.h.dh(:,j).*exp(p.h)); + diS = blkdiag(kron(Rh,diS),W); + dedhh(i,j) = E'*diS*E; + dedhh(j,i) = dedhh(i,j); + end + end + for i = 1:ng + for j = i:ng + diS = diag(dp.g.dg(:,i).*dp.g.dg(:,j).*exp(p.g)); + diS = blkdiag(V,kron(Rg,diS)); + dedgg(i,j) = E'*diS*E; + dedgg(j,i) = dedgg(i,j); + end + end + + % combined curvature + %-------------------------------------------------------------- + dSdhh = spm_cat({dedhh [] ; + [] dedgg}); + + + % errors (from prior expectations) (NB pp.p = 0) + %-------------------------------------------------------------- + Eu = spm_vec(qu.x(1:n),qu.v(1:d)); + Ep = spm_vec(qp.p); + Eh = spm_vec(qh.h,qh.g) - ph.h; + + + % first-order derivatives of Gibb's Energy + %============================================================== + dLdu = dEdu*E + dSdu*E/2 - dDdu/2 + pu.ic*Eu; + dLdh = dEdh*E/2 - dDdh/2 + ph.ic*Eh; + dLdp = dEdp*E + pp.ic*Ep; + + + % and second-order derivatives of Gibb's Energy + %-------------------------------------------------------------- + % dLduu = dEdu*dE.du + dSdu*dE.du + dE.du'*dSdu' + pu.ic; + % dLdup = dEdu*dE.dp + dSdu*dE.dp; + dLduu = dEdu*dE.du + pu.ic; + dLdpp = dEdp*dE.dp + pp.ic; + dLdhh = dSdhh/2 + ph.ic; + dLdup = dEdu*dE.dp; + dLdhu = dEdh*dE.du; + dLduy = dEdu*dE.dy; + dLduc = dEdu*dE.dc; + dLdpy = dEdp*dE.dy; + dLdpc = dEdp*dE.dc; + dLdhy = dEdh*dE.dy; + dLdhc = dEdh*dE.dc; + dLdhp = dEdh*dE.dp; + dLdpu = dLdup'; + dLdph = dLdhp'; + + % precision and covariances + %-------------------------------------------------------------- + iC = spm_cat({dLduu dLdup; + dLdpu dLdpp}); + + C = spm_inv(iC); + + % first-order derivatives of Entropy term + %============================================================== + + % log-precision + %-------------------------------------------------------------- + for i = 1:nh + Luub = dE.du'*diSdh{i}*dE.du; + Lpub = dE.dp'*diSdh{i}*dE.du; + Lppb = dE.dp'*diSdh{i}*dE.dp; + diCdh = spm_cat({Luub Lpub'; + Lpub Lppb}); + dHdh(i) = sum(sum(diCdh.*C))/2; + end + for i = 1:ng + Luub = dE.du'*diSdg{i}*dE.du; + Lpub = dE.dp'*diSdg{i}*dE.du; + Lppb = dE.dp'*diSdg{i}*dE.dp; + diCdg = spm_cat({Luub Lpub'; + Lpub Lppb}); + dHdg(i) = sum(sum(diCdg.*C))/2; + end + + % parameters + %-------------------------------------------------------------- + for i = 1:np + Luup = dE.dup{i}'*dEdu'; + Lpup = dEdp*dE.dup{i}; + Luup = Luup + Luup'; + diCdp = spm_cat({Luup Lpup'; + Lpup [] }); + dHdp(i) = sum(sum(diCdp.*C))/2; + end + +% % hidden and causal states +% %-------------------------------------------------------------- +% for i = 1:mnx +% Luux = dE.du'*diSdx{i}*dE.du; +% Lpux = dE.dp'*diSdx{i}*dE.du; +% Lppx = dE.dp'*diSdx{i}*dE.dp; +% diCdx = spm_cat({Luux Lpux'; +% Lpux Lppx}); +% dHdx(i) = sum(sum(diCdx.*C))/2; +% +% end +% for i = 1:mnv +% Luuv = dE.du'*diSdv{i}*dE.du; +% Lpuv = dE.dp'*diSdv{i}*dE.du; +% Lppv = dE.dp'*diSdv{i}*dE.dp; +% diCdv = spm_cat({Luuv Lpuv'; +% Lpuv Lppv}); +% dHdv(i) = sum(sum(diCdv.*C))/2; +% end + + dHdb = [dHdh; dHdg]; + dHdu = [dHdx; dHdv]; + + + % save conditional moments (and prediction error) at Q{t} + %============================================================== + if iD == 1 + + % save means + %---------------------------------------------------------- + Q(is).e = E; + Q(is).E = iS*E; + Q(is).u = qu; + Q(is).p = qp; + Q(is).h = qh; + + % and conditional covariances + %---------------------------------------------------------- + Q(is).u.s = C((1:nx),(1:nx)); + Q(is).u.c = C((1:nv) + nx*n, (1:nv) + nx*n); + Q(is).p.c = C((1:np) + nu, (1:np) + nu); + Q(is).h.c = spm_inv(dLdhh); + Cu = C(1:nu,1:nu); + + % Free-energy (states) + %---------------------------------------------------------- + L(is) = ... + - E'*iS*E/2 + spm_logdet(iS)/2 - n*ny*log(2*pi)/2 ... + - Eu'*pu.ic*Eu/2 + spm_logdet(pu.ic)/2 + spm_logdet(Cu)/2; + + % Free-energy (states and parameters) + %---------------------------------------------------------- + A(is) = - E'*iS*E/2 + spm_logdet(iS)/2 ... + - Eu'*pu.ic*Eu/2 + spm_logdet(pu.ic)/2 ... + - Ep'*pp.ic*Ep/2 + spm_logdet(pp.ic)/2 ... + - Eh'*ph.ic*Eh/2 + spm_logdet(ph.ic)/2 ... + - n*ny*log(2*pi)/2 - spm_logdet(iC)/2 - spm_logdet(dLdhh)/2; + end + + % update conditional moments + %============================================================== + + % uopdate curvatures of [hyper]paramters + %-------------------------------------------------------------- + try + dLdPP = dLdPP*(1 - 1/ns) + dLdpp/ns; + dLdHH = dLdHH*(1 - 1/ns) + dLdhh/ns; + catch + dLdPP = dLdpp; + dLdHH = dLdhh; + end + + % rotate and scale gradient (and curvatures) + %-------------------------------------------------------------- + [Vp Sp] = spm_svd(dLdPP,0); + [Vh Sh] = spm_svd(dLdHH,0); + Sp = diag(1./(diag(sqrt(Sp)))); + Sh = diag(1./(diag(sqrt(Sh)))); + + dLdp = Sp*Vp'*dLdp; + dHdp = Sp*Vp'*dHdp; + dLdpy = Sp*Vp'*dLdpy; + dLdpu = Sp*Vp'*dLdpu; + dLdpc = Sp*Vp'*dLdpc; + dLdph = Sp*Vp'*dLdph; + dLdpp = Sp*Vp'*dLdpp*Vp; + dLdhp = dLdhp*Vp; + + dLdh = Sh*Vh'*dLdh; + dHdb = Sh*Vh'*dHdb; + dLdhy = Sh*Vh'*dLdhy; + dLdhu = Sh*Vh'*dLdhu; + dLdhc = Sh*Vh'*dLdhc; + dLdhp = Sh*Vh'*dLdhp; + dLdhh = Sh*Vh'*dLdhh*Vh; + dLdph = dLdph*Vh; + + % assemble conditional means + %-------------------------------------------------------------- + q{1} = qu.y(1:n); + q{2} = qu.x(1:n); + q{3} = qu.v(1:d); + q{4} = qu.u(1:d); + q{5} = spm_unvec(Vp'*spm_vec(qp.p),qp.p); + qb = spm_unvec(Vh'*spm_vec({qh.h qh.g}),{qh.h qh.g}); + q{6} = qb{1}; + q{7} = qb{2}; + q{8} = Vp'*qp.dp; + q{9} = Vh'*qh.dp; + + + + % flow + %-------------------------------------------------------------- + f{1} = Dy*spm_vec(q{1}); + f{2} = Du*spm_vec(q{2:3}) - dLdu - dHdu; + f{3} = Dc*spm_vec(q{4}); + f{4} = spm_vec(q{8}); + f{5} = spm_vec(q{9}); + f{6} = -Kp*spm_vec(q{8}) - dLdp - dHdp; + f{7} = -Kh*spm_vec(q{9}) - dLdh - dHdb; + + + % and Jacobian + %-------------------------------------------------------------- + dfdq = spm_cat({Dy [] [] [] [] [] []; + -dLduy Du-dLduu -dLduc [] [] [] []; + [] [] Dc [] [] [] []; + [] [] [] [] [] Ip []; + [] [] [] [] [] [] Ih; + -dLdpy -dLdpu -dLdpc -dLdpp -dLdph -Kp []; + -dLdhy -dLdhu -dLdhc -dLdhp -dLdhh [] -Kh}); + + + % update conditional modes of states + %============================================================== + dq = spm_dx(dfdq, spm_vec(f), 1/nD); + q = spm_unvec(spm_vec(q) + dq,q); + + % unpack conditional means + %-------------------------------------------------------------- + qu.x(1:n) = q{2}; + qu.v(1:d) = q{3}; + qp.p = spm_unvec(Vp*spm_vec(q{5}),qp.p); + qb = spm_unvec(Vh*spm_vec(q{6:7}),{qh.h qh.g}); + qh.h = qb{1}; + qh.g = qb{2}; + qp.dp = Vp*q{8}; + qh.dp = Vh*q{9}; + + + end % D-Step + + end % sequence (ns) + + + % Bayesian parameter averaging + %====================================================================== + + % Conditional moments of time-averaged parameters + %---------------------------------------------------------------------- + Pp = 0; + Ep = 0; + for i = 1:ns + P = spm_inv(Q(i).p.c); + Ep = Ep + P*spm_vec(Q(i).p.p); + Pp = Pp + P; + end + Cp = spm_inv(Pp); + Ep = Cp*Ep; + + % conditional moments of hyper-parameters + %---------------------------------------------------------------------- + Ph = 0; + Eh = 0; + for i = 1:ns + P = spm_inv(Q(i).h.c); + Ph = Ph + P; + Eh = Eh + P*spm_vec({Q(i).h.h Q(i).h.g}); + end + Ch = spm_inv(Ph); + Eh = Ch*Eh - ph.h; + + % Free-action of states plus free-energy of parameters + %====================================================================== + Fs = sum(A); + Fi = sum(L) ... + - Ep'*pp.ic*Ep/2 + spm_logdet(pp.ic)/2 - spm_logdet(Pp)/2 ... + - Eh'*ph.ic*Eh/2 + spm_logdet(ph.ic)/2 - spm_logdet(Ph)/2; + + + % if F is increasing terminate + %---------------------------------------------------------------------- + if Fi < Fa && iN > 4 + break + else + Fa = Fi; + F(iN) = Fi; + S(iN) = Fs; + end + + % otherwise save conditional moments (for each time point) + %====================================================================== + for t = 1:length(Q) + + + % states and predictions + %------------------------------------------------------------------ + v = spm_unvec(Q(t).u.v{1},v); + x = spm_unvec(Q(t).u.x{1},x); + z = spm_unvec(Q(t).e(1:(ny + nv)),{M.v}); + Z = spm_unvec(Q(t).E(1:(ny + nv)),{M.v}); + w = spm_unvec(Q(t).e((1:nx) + (ny + nv)*n),{M.x}); + X = spm_unvec(Q(t).E((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 + if M(i).n, qU.W{i}(:,t) = spm_vec(X{i}); end + if M(i).l, qU.Z{i}(:,t) = spm_vec(Z{i}); end + end + if M(nl).l, qU.z{nl}(:,t) = spm_vec(z{nl}); end + if M(nl).l, qU.Z{nl}(:,t) = spm_vec(Z{nl}); end + + qU.v{1}(:,t) = spm_vec(Q(t).u.y{1}) - spm_vec(z{1}); + + % and conditional covariances + %------------------------------------------------------------------ + qU.S{t} = Q(t).u.s; + qU.C{t} = Q(t).u.c; + + % parameters + %------------------------------------------------------------------ + qP.p{t} = spm_vec(Q(t).p.p); + qP.c{t} = Q(t).p.c; + + % hyperparameters + %------------------------------------------------------------------ + qH.p{t} = spm_vec({Q(t).h.h Q(t).h.g}); + qH.c{t} = Q(t).h.c; + + end + + % graphics (states) + %---------------------------------------------------------------------- + figure(Fdem) + spm_DEM_qU(qU) + + % graphics (parameters and log-precisions) + %---------------------------------------------------------------------- + if np && nb + subplot(2*nl,2,4*nl - 2) + plot(1:ns,spm_cat(qP.p)) + set(gca,'XLim',[1 ns]) + title('parameters (modes)','FontSize',16) + + subplot(2*nl,2,4*nl) + plot(1:ns,spm_cat(qH.p)) + set(gca,'XLim',[1 ns]) + title('log-precision','FontSize',16) + + elseif nb + subplot(nl,2,2*nl) + plot(1:ns,spm_cat(qH.p)) + set(gca,'XLim',[1 ns]) + title('log-precision','FontSize',16) + + elseif np + subplot(nl,2,2*nl) + plot(1:ns,spm_cat(qP.p)) + set(gca,'XLim',[1 ns]) + title('parameters (modes)','FontSize',16) + + end + drawnow + + % report (EM-Steps) + %---------------------------------------------------------------------- + try + dF = F(end) - F(end - 1); + catch + dF = 0; + end + str{1} = sprintf('LAP: %i (%i)', iN,iD); + str{2} = sprintf('F:%.4e', full(F(iN) - F(1))); + str{3} = sprintf('dF:%.2e', full(dF)); + str{4} = sprintf('(%.2e sec)', full(toc)); + fprintf('%-16s%-16s%-14s%-16s\n',str{:}) + +end + + +% Place Bayesian parameter averages in output arguments +%========================================================================== + +% Conditional moments of time-averaged parameters +%-------------------------------------------------------------------------- +Pp = 0; +Ep = 0; +for i = 1:ns + + % weight in proportion to precisions + %---------------------------------------------------------------------- + P = spm_inv(qP.c{i}); + Ep = Ep + P*qP.p{i}; + Pp = Pp + P; + +end +Cp = spm_inv(Pp); +Ep = Cp*Ep; +P = {M.pE}; +qP.P = spm_unvec(Up*Ep + pp.p,P); +qP.C = Up*Cp*Up'; +qP.V = spm_unvec(diag(qP.C),P); +qP.U = Up; + +% conditional moments of hyper-parameters +%-------------------------------------------------------------------------- +Ph = 0; +Eh = 0; +for i = 1:ns + + % weight in proportion to precisions + %---------------------------------------------------------------------- + P = spm_inv(qH.c{i}); + Ph = Ph + P; + Eh = Eh + P*qH.p{i}; + +end +Ch = spm_inv(Ph); +Eh = Ch*Eh; +P = {qh.h qh.g}; +P = spm_unvec(Eh,P); +qH.h = P{1}; +qH.g = P{2}; +qH.C = Ch; +P = spm_unvec(diag(qH.C),P); +qH.V = P{1}; +qH.W = P{2}; + + + +% assign output variables +%-------------------------------------------------------------------------- +DEM.M = M; % model +DEM.U = U; % causes + +DEM.qU = qU; % conditional moments of model-states +DEM.qP = qP; % conditional moments of model-parameters +DEM.qH = qH; % conditional moments of hyper-parameters + +DEM.F = F; % [-ve] Free energy +DEM.S = S; % [-ve] Free action + +return + + + +% Notes (check on curvature) +%========================================================================== + + + % analytic form + %---------------------------------------------------------- + iC = spm_cat({dLduu dLdup dLduh; + dLdpu dLdpp dLdph; + dLdhu dLdhp dLdhh}); + + + % numerical approximations + %---------------------------------------------------------- + qq.x = qu.x(1:n); + qq.v = qu.v(1:d); + qq.p = qp.p; + qq.h = qh.h; + qq.g = qh.g; + + dLdqq = spm_diff('spm_LAP_F',qq,qu,qp,qh,pu,pp,ph,M,[1 1]); + dLdqq = spm_cat(dLdqq'); + + subplot(2,2,1);imagesc(dLdqq); axis square + subplot(2,2,2);imagesc(iC); axis square + subplot(2,2,3);imagesc(dLdqq - iC);axis square + subplot(2,2,4);plot(iC,':k');hold on; + plot(dLdqq - iC,'r');hold off; axis square + drawnow + +% Notes (descent on parameters +%========================================================================== +I = eye(length(dLdpp)); +k = kp; +Luu = dLdpp; +J = spm_cat({[] I; + -Luu -k*I}); +[u s] = eig(full(J)); +max(diag(s)) + +[uj sj] = eig(full(dLdpp)); +Luu = min(diag(sj)); +% Luu = max(diag(sj)); +k = kp; + +ss(1) = -(k + sqrt(k^2 - 4*Luu))/2; +ss(2) = -(k - sqrt(k^2 - 4*Luu))/2; +max(ss) + + +k = (1:128); +s = -(k - sqrt(k.^2 - 4*Luu))/2; + +plot(k,-1./real(s)) + + + + + + + + + diff --git a/spm_LAPS.m b/spm_LAPS.m new file mode 100644 index 0000000..c93da67 --- /dev/null +++ b/spm_LAPS.m @@ -0,0 +1,886 @@ +function [DEM] = spm_LAPS(DEM) +% Laplacian model inversion (with smoothness hyperparameter optimisation) +% FORMAT DEM = spm_LAPS(DEM) +% +% DEM.M - hierarchical model +% DEM.Y - response variable, output or data +% DEM.U - explanatory variables, inputs or prior expectation of causes +%__________________________________________________________________________ +% +% generative model +%-------------------------------------------------------------------------- +% M(i).g = v = g(x,v,P) {inline function, string or m-file} +% M(i).f = dx/dt = f(x,v,P) {inline function, string or m-file} +% +% M(i).ph = pi(v) = ph(x,v,h,M) {inline function, string or m-file} +% M(i).pg = pi(x) = pg(x,v,g,M) {inline function, string or m-file} +% +% M(i).pE = prior expectation of p model-parameters +% M(i).pC = prior covariances of p model-parameters +% M(i).hE = prior expectation of h log-precision (cause noise) +% M(i).hC = prior covariances of h log-precision (cause noise) +% M(i).gE = prior expectation of g log-precision (state noise) +% M(i).gC = prior covariances of g log-precision (state noise) +% M(i).xP = precision (states) +% M(i).Q = precision components (input noise) +% M(i).R = precision components (state noise) +% M(i).V = fixed precision (input noise) +% M(i).W = fixed precision (state noise) +% +% M(i).m = number of inputs v(i + 1); +% M(i).n = number of states x(i); +% M(i).l = number of output v(i); +% +% conditional moments of model-states - q(u) +%-------------------------------------------------------------------------- +% qU.x = Conditional expectation of hidden states +% qU.v = Conditional expectation of causal states +% qU.w = Conditional prediction error (states) +% qU.z = Conditional prediction error (causes) +% qU.C = Conditional covariance: cov(v) +% qU.S = Conditional covariance: cov(x) +% +% conditional moments of model-parameters - q(p) +%-------------------------------------------------------------------------- +% qP.P = Conditional expectation +% qP.C = Conditional covariance +% +% conditional moments of hyper-parameters (log-transformed) - q(h) +%-------------------------------------------------------------------------- +% qH.h = Conditional expectation (cause noise) +% qH.g = Conditional expectation (state noise) +% qH.C = Conditional covariance +% +% F = log-evidence = log-marginal likelihood = negative free-energy +%__________________________________________________________________________ +% +% spm_LAP implements a variational scheme under the Laplace +% approximation to the conditional joint density q on states (u), parameters +% (p) and hyperparameters (h,g) of any analytic nonlinear hierarchical dynamic +% model, with additive Gaussian innovations. +% +% q(u,p,h,g) = max q +% +% L is the ln p(y,u,p,h,g|M) under the model M. The conditional covariances +% obtain analytically from the curvature of L with respect to the unknowns. +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: spm_LAPS.m 3878 2010-05-07 19:53:54Z karl $ + + +% find or create a DEM figure +%-------------------------------------------------------------------------- +try + DEM.M(1).nograph; +catch + DEM.M(1).nograph = 0; +end +if ~DEM.M(1).nograph + Fdem = spm_figure('GetWin','DEM'); +end + + +% check model, data and priors +%========================================================================== +[M Y U] = spm_DEM_set(DEM); + + +% number of iterations +%-------------------------------------------------------------------------- +try, nD = M(1).E.nD; catch, nD = 1; end +try, nN = M(1).E.nN; catch, nN = 16; end + + +% ensure integration scheme evaluates gradients at each time-step +%-------------------------------------------------------------------------- +M(1).E.linear = 4; + +% assume precisions are a function of, and only of hyperparameters +%-------------------------------------------------------------------------- +try + method = M(1).E.method; +catch + method.h = 1; + method.g = 1; + method.x = 0; + method.v = 0; +end +try method.h; catch, method.h = 0; end +try method.g; catch, method.g = 0; end +try method.x; catch, method.x = 0; end +try method.v; catch, method.v = 0; end + +M(1).E.method = method; + +% precision of smoothness hyperparameters +%-------------------------------------------------------------------------- +try + sP = M(1).E.sP; +catch + sP = 256; + M(1).E.sP = sP; +end + + +% additional checks for Laplace models (precision functions; ph and pg) +%-------------------------------------------------------------------------- +for i = 1:length(M) + try + feval(M(i).ph,M(i).x,M(i).v,M(i).hE,M(i)); + catch + M(i).ph = inline('spm_LAP_ph(x,v,h,M)','x','v','h','M'); + end + try + feval(M(i).pg,M(i).x,M(i).v,M(i).gE,M(i)); + catch + M(i).pg = inline('spm_LAP_pg(x,v,h,M)','x','v','h','M'); + end +end + + +% order parameters (d = n = 1 for static models) and checks +%========================================================================== +d = M(1).E.d + 1; % embedding order of q(v) +n = M(1).E.n + 1; % embedding order of q(x) + +% number of states and parameters +%-------------------------------------------------------------------------- +ns = size(Y,2); % number of samples +nl = size(M,2); % number of levels +nv = sum(spm_vec(M.m)); % number of v (casual states) +nx = sum(spm_vec(M.n)); % number of x (hidden states) +ny = M(1).l; % number of y (inputs) +nc = M(end).l; % number of c (prior causes) +nu = nv*d + nx*n; % number of generalised states +ne = nv*n + nx*n + ny*n; % number of generalised errors + + +% precision (R) of generalised errors and null matrices for concatenation +%========================================================================== +W = sparse(nx*n,nx*n); +V = sparse((ny + nv)*n,(ny + nv)*n); + +% fixed priors on states (u) +%-------------------------------------------------------------------------- +Px = kron(sparse(1,1,1,n,n),spm_cat(spm_diag({M.xP}))); +Pv = kron(sparse(1,1,1,d,d),sparse(nv,nv)); +pu.ic = spm_cat(spm_diag({Px Pv})); + +% hyperpriors +%-------------------------------------------------------------------------- +s = M(1).E.s; +sh = log(s); +sg = log(s); +sC = speye(2,2)/sP; +ph.h = spm_vec({M.hE M.gE sh sg}); % prior expectation of h,g +ph.c = spm_cat(spm_diag({M.hC M.gC sC})); % prior covariances of h,g +ph.ic = spm_pinv(ph.c); % prior precision of h,g + +qh.h = {M.hE}; % conditional expectation h +qh.g = {M.gE}; % conditional expectation g +nh = length(spm_vec(qh.h)); % number of hyperparameters h +ng = length(spm_vec(qh.g)); % number of hyperparameters g +qh.sh = sh; % conditional expectation sh +qh.sg = sg; % conditional expectation sg +nb = nh + ng + 2; % number of hyerparameters + + +% 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); % basis for parameters + M(i).p = size(qp.u{i},2); % number of qp.p + qp.p{i} = sparse(M(i).p,1); % initial deviates + pp.c{i,i} = qp.u{i}'*M(i).pC*qp.u{i}; % prior covariance + +end +Up = spm_cat(spm_diag(qp.u)); + +% priors on parameters +%-------------------------------------------------------------------------- +pp.p = spm_vec(M.pE); +pp.c = spm_cat(pp.c); +pp.ic = spm_inv(pp.c); + +% initialise conditional density q(p) +%-------------------------------------------------------------------------- +for i = 1:(nl - 1) + try + qp.p{i} = qp.p{i} + qp.u{i}'*(spm_vec(M(i).P) - spm_vec(M(i).pE)); + end +end +np = size(Up,2); + + +% initialise cell arrays for D-Step; e{i + 1} = (d/dt)^i[e] = e[i] +%========================================================================== +qu.x = cell(n,1); +qu.v = cell(n,1); +qu.y = cell(n,1); +qu.u = cell(n,1); +[qu.x{:}] = deal(sparse(nx,1)); +[qu.v{:}] = deal(sparse(nv,1)); +[qu.y{:}] = deal(sparse(ny,1)); +[qu.u{:}] = deal(sparse(nc,1)); + +% initialise cell arrays for hierarchical structure of x[0] and v[0] +%-------------------------------------------------------------------------- +x = {M(1:end - 1).x}; +v = {M(1 + 1:end).v}; +qu.x{1} = spm_vec(x); +qu.v{1} = spm_vec(v); + +% derivatives for Jacobian of D-step +%-------------------------------------------------------------------------- +Dx = kron(spm_speye(n,n,1),spm_speye(nx,nx)); +Dv = kron(spm_speye(d,d,1),spm_speye(nv,nv)); +Dy = kron(spm_speye(n,n,1),spm_speye(ny,ny)); +Dc = kron(spm_speye(d,d,1),spm_speye(nc,nc)); +Du = spm_cat(spm_diag({Dx,Dv})); +Ip = spm_speye(np,np); +Ih = spm_speye(nb,nb); +qp.dp = sparse(np,1); % conditional expectation of dp/dt +qh.dp = sparse(nb,1); % conditional expectation of dh/dt + + +% gradients of generalised weighted errors +%-------------------------------------------------------------------------- +dedh = sparse(nh,ne); +dedg = sparse(ng,ne); +dedv = sparse(nv,ne); +dedx = sparse(nx,ne); +dedhh = sparse(nh,nh); +dedgg = sparse(ng,ng); +dedss = speye(2,2); + +% curvatures of Gibb's energy w.r.t. hyperparameters +%-------------------------------------------------------------------------- +dHdh = sparse(nh, 1); +dHdg = sparse(ng, 1); +dHdp = sparse(np, 1); +dHdx = sparse(nx*n,1); +dHdv = sparse(nv*d,1); + +% preclude unnecessary iterations and set switchs +%-------------------------------------------------------------------------- +if ~np && ~nh && ~ng, nN = 1; end +mnx = nx*~~method.x; +mnv = nv*~~method.v; + + +% precision on parameter fluctuations +%-------------------------------------------------------------------------- +kp = ns*8; +kh = ns*4; + + +% Iterate Lapalace scheme +%========================================================================== +Fa = -Inf; +for iN = 1:nN + + % get time and clear persistent variables in evaluation routines + %---------------------------------------------------------------------- + tic; clear spm_DEM_eval + + % [re-]set states & their derivatives + %---------------------------------------------------------------------- + try, qu = Q(1).u; end + + % increase precision on parameter fluctuations + %---------------------------------------------------------------------- + kp = kp + ns*2; + kh = kh + ns*2; + + + % D-Step: (nD D-Steps for each sample) + %====================================================================== + for is = 1:ns + + % D-Step: until convergence for static systems + %================================================================== + for iD = 1:nD + + % sampling time + %-------------------------------------------------------------- + ts = is + (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 + + + % evaluate functions and derivatives + %============================================================== + + % prediction errors (E) and precision vectors (p) + %-------------------------------------------------------------- + [E dE] = spm_DEM_eval(M,qu,qp); + [p dp] = spm_LAP_eval(M,qu,qh); + + + % gradients of log(det(iS)) dDd... + %============================================================== + + % get precision matrices + %-------------------------------------------------------------- + [Rh Vh] = spm_DEM_R(n,exp(qh.sh)); + [Rg Vg] = spm_DEM_R(n,exp(qh.sg)); + iSh = diag(exp(p.h)); + iSg = diag(exp(p.g)); + iS = blkdiag(kron(Rh,iSh),kron(Rg,iSg)); + + + % gradients of trace(diag(p)) = sum(p); p = precision vector + %-------------------------------------------------------------- + dpdx = n*sum(spm_cat({dp.h.dx; dp.g.dx})); + dpdv = n*sum(spm_cat({dp.h.dv; dp.g.dv})); + dpdh = n*sum(dp.h.dh); + dpdg = n*sum(dp.g.dg); + dpdx = kron(sparse(1,1,1,1,n),dpdx); + dpdv = kron(sparse(1,1,1,1,d),dpdv); + dDdu = [dpdx dpdv]'; + + + % gradients w.r.t. hyperparameters + %-------------------------------------------------------------- + dRdh = spm_diff('spm_DEM_R',n,exp(qh.sh),2); + dRdg = spm_diff('spm_DEM_R',n,exp(qh.sg),2); + dRdh = dRdh{1}*exp(qh.sh); + dRdg = dRdg{1}*exp(qh.sg); + dDdh = length(iSh)*trace(dRdh*Vh); + dDdg = length(iSg)*trace(dRdg*Vg); + dDdh = [dpdh dpdg dDdh dDdg]'; + + + % gradients precision-weighted generalised error dSd.. + %============================================================== + diSdsh = blkdiag(kron(dRdh, iSh),W); + dedsh = E'*diSdsh; + diSdsg = blkdiag(V,kron(dRdg, iSg)); + dedsg = E'*diSdsg; + + % gradients w.r.t. hyperparameters + %-------------------------------------------------------------- + for i = 1:nh + diS = diag(dp.h.dh(:,i).*exp(p.h)); + diSdh{i} = blkdiag(kron(Rh,diS),W); + dedh(i,:) = E'*diSdh{i}; + end + for i = 1:ng + diS = diag(dp.g.dg(:,i).*exp(p.g)); + diSdg{i} = blkdiag(V,kron(Rg,diS)); + dedg(i,:) = E'*diSdg{i}; + end + + % gradients w.r.t. hidden states + %-------------------------------------------------------------- + for i = 1:mnx + diV = diag(dp.h.dx(:,i).*exp(p.h)); + diW = diag(dp.g.dx(:,i).*exp(p.g)); + diSdx{i} = blkdiag(kron(Rh,diV),kron(Rg,diW)); + dedx(i,:) = E'*diSdx{i}; + end + + % gradients w.r.t. causal states + %-------------------------------------------------------------- + for i = 1:mnv + diV = diag(dp.h.dv(:,i).*exp(p.h)); + diW = diag(dp.g.dv(:,i).*exp(p.g)); + diSdv{i} = blkdiag(kron(Rh,diV),kron(Rg,diW)); + dedv(i,:) = E'*diSdv{i}; + end + + dSdx = kron(sparse(1,1,1,n,1),dedx); + dSdv = kron(sparse(1,1,1,d,1),dedv); + dSdu = [dSdx; dSdv]; + dEdh = [dedh; dedg; dedsh; dedsg]; + dEdp = dE.dp'*iS; + dEdu = dE.du'*iS; + + % curvatures w.r.t. hyperparameters + %-------------------------------------------------------------- + for i = 1:nh + for j = i:nh + diS = diag(dp.h.dh(:,i).*dp.h.dh(:,j).*exp(p.h)); + diS = blkdiag(kron(Rh,diS),W); + dedhh(i,j) = E'*diS*E; + dedhh(j,i) = dedhh(i,j); + end + end + for i = 1:ng + for j = i:ng + diS = diag(dp.g.dg(:,i).*dp.g.dg(:,j).*exp(p.g)); + diS = blkdiag(V,kron(Rg,diS)); + dedgg(i,j) = E'*diS*E; + dedgg(j,i) = dedgg(i,j); + end + end + + % combined curvature + %-------------------------------------------------------------- + dSdhh = spm_cat({dedhh [] []; + [] dedgg []; + [] [] dedss}); + + + % errors (from prior expectations) (NB pp.p = 0) + %-------------------------------------------------------------- + Eu = spm_vec(qu.x(1:n),qu.v(1:d)); + Ep = spm_vec(qp.p); + Eh = spm_vec(qh.h,qh.g,qh.sh,qh.sg) - ph.h; + + + % first-order derivatives of Gibb's Energy + %============================================================== + dLdu = dEdu*E + dSdu*E/2 - dDdu/2 + pu.ic*Eu; + dLdh = dEdh*E/2 - dDdh/2 + ph.ic*Eh; + dLdp = dEdp*E + pp.ic*Ep; + + + % and second-order derivatives of Gibb's Energy + %-------------------------------------------------------------- + % dLduu = dEdu*dE.du + dSdu*dE.du + dE.du'*dSdu' + pu.ic; + % dLdup = dEdu*dE.dp + dSdu*dE.dp; + dLduu = dEdu*dE.du + pu.ic; + dLdpp = dEdp*dE.dp + pp.ic; + dLdhh = dSdhh/2 + ph.ic; + dLdup = dEdu*dE.dp; + dLdhu = dEdh*dE.du; + dLduy = dEdu*dE.dy; + dLduc = dEdu*dE.dc; + dLdpy = dEdp*dE.dy; + dLdpc = dEdp*dE.dc; + dLdhy = dEdh*dE.dy; + dLdhc = dEdh*dE.dc; + dLdhp = dEdh*dE.dp; + dLdpu = dLdup'; + dLdph = dLdhp'; + + % precision and covariances + %-------------------------------------------------------------- + iC = spm_cat({dLduu dLdup; + dLdpu dLdpp}); + + C = spm_inv(iC); + + % first-order derivatives of Entropy term + %============================================================== + + % log-smoothness + %-------------------------------------------------------------- + Luub = dE.du'*diSdsh*dE.du; + Lpub = dE.dp'*diSdsh*dE.du; + Lppb = dE.dp'*diSdsh*dE.dp; + diCdsh = spm_cat({Luub Lpub'; + Lpub Lppb}); + + Luub = dE.du'*diSdsg*dE.du; + Lpub = dE.dp'*diSdsg*dE.du; + Lppb = dE.dp'*diSdsg*dE.dp; + diCdsg = spm_cat({Luub Lpub'; + Lpub Lppb}); + + dHdsh = sum(sum(diCdsh.*C))/2; + dHdsg = sum(sum(diCdsg.*C))/2; + + % log-precision + %-------------------------------------------------------------- + for i = 1:nh + Luub = dE.du'*diSdh{i}*dE.du; + Lpub = dE.dp'*diSdh{i}*dE.du; + Lppb = dE.dp'*diSdh{i}*dE.dp; + diCdh = spm_cat({Luub Lpub'; + Lpub Lppb}); + dHdh(i) = sum(sum(diCdh.*C))/2; + end + for i = 1:ng + Luub = dE.du'*diSdg{i}*dE.du; + Lpub = dE.dp'*diSdg{i}*dE.du; + Lppb = dE.dp'*diSdg{i}*dE.dp; + diCdg = spm_cat({Luub Lpub'; + Lpub Lppb}); + dHdg(i) = sum(sum(diCdg.*C))/2; + end + + % parameters + %-------------------------------------------------------------- + for i = 1:np + Luup = dE.dup{i}'*dEdu'; + Lpup = dEdp*dE.dup{i}; + Luup = Luup + Luup'; + diCdp = spm_cat({Luup Lpup'; + Lpup [] }); + dHdp(i) = sum(sum(diCdp.*C))/2; + end + +% % hidden and causal states +% %-------------------------------------------------------------- +% for i = 1:mnx +% Luux = dE.du'*diSdx{i}*dE.du; +% Lpux = dE.dp'*diSdx{i}*dE.du; +% Lppx = dE.dp'*diSdx{i}*dE.dp; +% diCdx = spm_cat({Luux Lpux'; +% Lpux Lppx}); +% dHdx(i) = sum(sum(diCdx.*C))/2; +% +% end +% for i = 1:mnv +% Luuv = dE.du'*diSdv{i}*dE.du; +% Lpuv = dE.dp'*diSdv{i}*dE.du; +% Lppv = dE.dp'*diSdv{i}*dE.dp; +% diCdv = spm_cat({Luuv Lpuv'; +% Lpuv Lppv}); +% dHdv(i) = sum(sum(diCdv.*C))/2; +% end + + dHdb = [dHdh; dHdg; dHdsh; dHdsg]; + dHdu = [dHdx; dHdv]; + + + % save conditional moments (and prediction error) at Q{t} + %============================================================== + if iD == 1 + + % save means + %---------------------------------------------------------- + Q(is).e = E; + Q(is).E = iS*E; + Q(is).u = qu; + Q(is).p = qp; + Q(is).h = qh; + + % and conditional covariances + %---------------------------------------------------------- + Q(is).u.s = C((1:nx),(1:nx)); + Q(is).u.c = C((1:nv) + nx*n, (1:nv) + nx*n); + Q(is).p.c = C((1:np) + nu, (1:np) + nu); + Q(is).h.c = inv(dLdhh); + Cu = C(1:nu,1:nu); + + % Free-energy (states) + %---------------------------------------------------------- + L(is) = ... + - E'*iS*E/2 + spm_logdet(iS)/2 - n*ny*log(2*pi)/2 ... + - Eu'*pu.ic*Eu/2 + spm_logdet(pu.ic)/2 + spm_logdet(Cu)/2; + + % Free-energy (states and parameters) + %---------------------------------------------------------- + A(is) = - E'*iS*E/2 + spm_logdet(iS)/2 ... + - Eu'*pu.ic*Eu/2 + spm_logdet(pu.ic)/2 ... + - Ep'*pp.ic*Ep/2 + spm_logdet(pp.ic)/2 ... + - Eh'*ph.ic*Eh/2 + spm_logdet(ph.ic)/2 ... + - n*ny*log(2*pi)/2 - spm_logdet(iC)/2 - spm_logdet(dLdhh)/2; + end + + % update conditional moments + %============================================================== + + % precision of fluctuations + %-------------------------------------------------------------- + Kp = kp*Ip; + Kh = kh*Ih; + + % assemble conditional means + %-------------------------------------------------------------- + q{1} = qu.y(1:n); + q{2} = qu.x(1:n); + q{3} = qu.v(1:d); + q{4} = qu.u(1:d); + q{5} = qp.p; + q{6} = qh.h; + q{7} = qh.g; + q{8} = qh.sh; + q{9} = qh.sg; + q{10} = qp.dp; + q{11} = qh.dp; + + + % flow + %-------------------------------------------------------------- + f{1} = Dy*spm_vec(q{1}); + f{2} = Du*spm_vec(q{2:3}) - dLdu - dHdu; + f{3} = Dc*spm_vec(q{4}); + f{4} = spm_vec(q{10}); + f{5} = spm_vec(q{11}); + f{6} = -kp*spm_vec(q{10}) - dLdp - dHdp; + f{7} = -kh*spm_vec(q{11}) - dLdh - dHdb; + + % and Jacobian + %-------------------------------------------------------------- + dfdq = spm_cat({Dy [] [] [] [] [] []; + -dLduy Du-dLduu -dLduc [] [] [] []; + [] [] Dc [] [] [] []; + [] [] [] [] [] Ip []; + [] [] [] [] [] [] Ih; + -dLdpy -dLdpu -dLdpc -dLdpp -dLdph -Kp []; + -dLdhy -dLdhu -dLdhc -dLdhp -dLdhh [] -Kh}); + + + % update conditional modes of states + %============================================================== + dq = spm_dx(dfdq, spm_vec(f), 1/nD); + q = spm_unvec(spm_vec(q) + dq,q); + + % unpack conditional means + %-------------------------------------------------------------- + qu.x(1:n) = q{2}; + qu.v(1:d) = q{3}; + qp.p = q{5}; + qh.h = q{6}; + qh.g = q{7}; + qh.sh = q{8}; + qh.sg = q{9}; + qp.dp = q{10}; + qh.dp = q{11}; + + + end % D-Step + + end % sequence (ns) + + + % Bayesian parameter averaging + %====================================================================== + + % Conditional moments of time-averaged parameters + %---------------------------------------------------------------------- + Pp = 0; + Ep = 0; + for i = 1:ns + P = spm_inv(Q(i).p.c); + Ep = Ep + P*spm_vec(Q(i).p.p); + Pp = Pp + P; + end + Cp = spm_inv(Pp); + Ep = Cp*Ep; + + % conditional moments of hyper-parameters + %---------------------------------------------------------------------- + Ph = 0; + Eh = 0; + for i = 1:ns + P = spm_inv(Q(i).h.c); + Ph = Ph + P; + Eh = Eh + P*spm_vec({Q(i).h.h Q(i).h.g Q(i).h.sh Q(i).h.sg}); + end + Ch = spm_inv(Ph); + Eh = Ch*Eh - ph.h; + + % Free-action of states plus free-energy of parameters + %====================================================================== + Fs = sum(A); + Fi = sum(L) ... + - Ep'*pp.ic*Ep/2 + spm_logdet(pp.ic)/2 - spm_logdet(Pp)/2 ... + - Eh'*ph.ic*Eh/2 + spm_logdet(ph.ic)/2 - spm_logdet(Ph)/2; + + + % if F is increasing terminate + %---------------------------------------------------------------------- + if Fi < Fa && iN > 3 + break + else + Fa = Fi; + F(iN) = Fi; + S(iN) = Fs; + end + + % otherwise save conditional moments (for each time point) + %====================================================================== + for t = 1:length(Q) + + + % states and predictions + %------------------------------------------------------------------ + v = spm_unvec(Q(t).u.v{1},v); + x = spm_unvec(Q(t).u.x{1},x); + z = spm_unvec(Q(t).e(1:(ny + nv)),{M.v}); + Z = spm_unvec(Q(t).E(1:(ny + nv)),{M.v}); + w = spm_unvec(Q(t).e((1:nx) + (ny + nv)*n),{M.x}); + X = spm_unvec(Q(t).E((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 + if M(i).n, qU.W{i}(:,t) = spm_vec(X{i}); end + if M(i).l, qU.Z{i}(:,t) = spm_vec(Z{i}); end + end + if M(nl).l, qU.z{nl}(:,t) = spm_vec(z{nl}); end + if M(nl).l, qU.Z{nl}(:,t) = spm_vec(Z{nl}); end + + qU.v{1}(:,t) = spm_vec(Q(t).u.y{1}) - spm_vec(z{1}); + + % and conditional covariances + %------------------------------------------------------------------ + qU.S{t} = Q(t).u.s; + qU.C{t} = Q(t).u.c; + + % parameters + %------------------------------------------------------------------ + qP.p{t} = spm_vec(Q(t).p.p); + qP.c{t} = Q(t).p.c; + + % hyperparameters + %------------------------------------------------------------------ + qH.p{t} = spm_vec({Q(t).h.h Q(t).h.g Q(t).h.sh Q(t).h.sg}); + qH.c{t} = Q(t).h.c; + + end + + % graphics (states) + %---------------------------------------------------------------------- + figure(Fdem) + spm_DEM_qU(qU) + + % graphics (parameters and log-precisions) + %---------------------------------------------------------------------- + if np + subplot(2*nl,2,4*nl - 2) + plot(1:ns,spm_cat(qP.p)) + set(gca,'XLim',[1 ns]) + title('parameters (modes)','FontSize',16) + + subplot(2*nl,2,4*nl) + plot(1:ns,spm_cat(qH.p)) + set(gca,'XLim',[1 ns]) + else + + subplot(nl,2,2*nl) + plot(1:ns,spm_cat(qH.p)) + set(gca,'XLim',[1 ns]) + end + if nh || ng + title('log-precision','FontSize',16) + else + title('log-smoothness','FontSize',16) + end + drawnow + + % report (EM-Steps) + %---------------------------------------------------------------------- + try + dF = F(end) - F(end - 1); + catch + dF = 0; + end + str{1} = sprintf('LAP: %i (%i)', iN,iD); + str{2} = sprintf('F:%.4e', full(F(iN) - F(1))); + str{3} = sprintf('dF:%.2e', full(dF)); + str{4} = sprintf('(%.2e sec)', full(toc)); + fprintf('%-16s%-16s%-14s%-16s\n',str{:}) + +end + + +% Place Bayesian parameter averages in output arguments +%========================================================================== + +% Conditional moments of time-averaged parameters +%-------------------------------------------------------------------------- +Pp = 0; +Ep = 0; +for i = 1:ns + + % weight in proportion to precisions + %---------------------------------------------------------------------- + P = spm_inv(qP.c{i}); + Ep = Ep + P*qP.p{i}; + Pp = Pp + P; + +end +Cp = spm_inv(Pp); +Ep = Cp*Ep; +P = {M.pE}; +qP.P = spm_unvec(Up*Ep + pp.p,P); +qP.C = Up*Cp*Up'; +qP.V = spm_unvec(diag(qP.C),P); +qP.U = Up; + +% conditional moments of hyper-parameters +%-------------------------------------------------------------------------- +Ph = 0; +Eh = 0; +for i = 1:ns + + % weight in proportion to precisions + %---------------------------------------------------------------------- + P = spm_inv(qH.c{i}); + Ph = Ph + P; + Eh = Eh + P*qH.p{i}; + +end +Ch = spm_inv(Ph); +Eh = Ch*Eh; +P = {qh.h qh.g qh.sh qh.sg}; +P = spm_unvec(Eh,P); +qH.h = P{1}; +qH.g = P{2}; +qH.sh = P{3}; +qH.sg = P{4}; +qH.C = Ch; +P = spm_unvec(diag(qH.C),P); +qH.V = P{1}; +qH.W = P{2}; + + + +% assign output variables +%-------------------------------------------------------------------------- +DEM.M = M; % model +DEM.U = U; % causes + +DEM.qU = qU; % conditional moments of model-states +DEM.qP = qP; % conditional moments of model-parameters +DEM.qH = qH; % conditional moments of hyper-parameters + +DEM.F = F; % [-ve] Free energy +DEM.S = S; % [-ve] Free action + +return + + + +% Notes +%========================================================================== + + + % analytic form + %---------------------------------------------------------- + iC = spm_cat({dLduu dLdup dLduh; + dLdpu dLdpp dLdph; + dLdhu dLdhp dLdhh}); + + + % numerical approximations + %---------------------------------------------------------- + qq.x = qu.x(1:n); + qq.v = qu.v(1:d); + qq.p = qp.p; + qq.h = qh.h; + qq.g = qh.g; + qq.sh = qh.sh; + qq.sg = qh.sg; + + dLdqq = spm_diff('spm_LAP_F',qq,qu,qp,qh,pu,pp,ph,M,[1 1]); + dLdqq = spm_cat(dLdqq'); + + subplot(2,2,1);imagesc(dLdqq); axis square + subplot(2,2,2);imagesc(iC); axis square + subplot(2,2,3);imagesc(dLdqq - iC);axis square + subplot(2,2,4);plot(iC,':k');hold on; + plot(dLdqq - iC,'r');hold off; axis square + drawnow diff --git a/spm_LAP_F.m b/spm_LAP_F.m new file mode 100644 index 0000000..7557886 --- /dev/null +++ b/spm_LAP_F.m @@ -0,0 +1,49 @@ +function [L] = spm_LAP_F(q,qu,qp,qh,pu,pp,ph,M) +% returns the Gibbs energy (L) as a function of contitional means +% FORMAT [L] = spm_LAP_F(q,qu,qp,qh,M) +% +% q.x: {nx1 cell} +% q.v: {dx1 cell} +% q.p: {mx1 cell} +% q.h: {mx1 cell} +% q.g: {mx1 cell} +% +% for an m-level hierarchy +% See spm_LAP +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: spm_LAP_F.m 3694 2010-01-22 14:16:51Z karl $ + +% Place conditional expecations in qu, qp, qh +%-------------------------------------------------------------------------- +n = length(q.x); +d = length(q.v); + +qu.x(1:n) = q.x; +qu.v(1:d) = q.v; +qp.p = q.p; +qh.h = q.h; +qh.g = q.g; + +% prediction errors +%-------------------------------------------------------------------------- +E = spm_DEM_eval(M,qu,qp); + +Eu = spm_vec(qu.x(1:n),qu.v(1:d)); +Ep = spm_vec(qp.p); +Eh = spm_vec(qh.h,qh.g) - ph.h; + +% precision and covariance matrices +%-------------------------------------------------------------------------- +p = spm_LAP_eval(M,qu,qh); +R = spm_DEM_R(n,M(1).E.s); +iS = spm_LAP_iS(p,R); + +% Free-energy +%-------------------------------------------------------------------------- +L = E'*iS*E/2 - spm_logdet(iS)/2 + ... + Eu'*pu.ic*Eu/2 - spm_logdet(pu.ic)/2 + ... + Ep'*pp.ic*Ep/2 - spm_logdet(pp.ic)/2 + ... + Eh'*ph.ic*Eh/2 - spm_logdet(ph.ic)/2; diff --git a/spm_LAP_eval.m b/spm_LAP_eval.m new file mode 100644 index 0000000..2cad54a --- /dev/null +++ b/spm_LAP_eval.m @@ -0,0 +1,154 @@ +function [p dp] = spm_LAP_eval(M,qu,qh) +% evaluates precisions for a LAP model +% FORMAT [p dp] = spm_LAP_eval(M,qu,qh) +% +% p.h - vector of precisions for causal states (v) +% p.g - vector of precisions for hidden states (v) +% +% dp.h.dx - dp.h/dx +% dp.h.dv - dp.h/dv +% dp.h.dh - dp.h/dh +% +% dp.g.dx - dp.g/dx +% dp.g.dv - dp.g/dv +% dp.g.dg - dp.g/dg +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: spm_LAP_eval.m 3715 2010-02-08 13:57:26Z karl $ + + +% Get states {qu.v{1},qu.x{1}} in hierarchical form (v{i},x{i}) +%-------------------------------------------------------------------------- +N = length(M); +v = cell(N,1); +x = cell(N,1); +v(1 + 1:N) = spm_unvec(qu.v{1},{M(1 + 1:N).v}); +x(1:N - 1) = spm_unvec(qu.x{1},{M(1:N - 1).x}); + + +% precisions +%========================================================================== +for i = 1:N + + % precision of causal and hidden states + %---------------------------------------------------------------------- + try + h{i,1} = feval(M(i).ph,x{i},v{i},qh.h{i},M(i)); + catch + h{i,1} = sparse(M(i).l,1); + end + try + g{i,1} = feval(M(i).pg,x{i},v{i},qh.g{i},M(i)); + catch + g{i,1} = sparse(M(i).n,1); + end + +end + +% Concatenate over hierarchical levels +%-------------------------------------------------------------------------- +p.h = spm_cat(h); +p.g = spm_cat(g); + +if nargout < 2, return, end + +% gradients +%========================================================================== + +% assume predicions are a function of, and only of hyperparameters +%-------------------------------------------------------------------------- +try + method = M(1).E.method; +catch + method.h = 1; + method.g = 1; + method.x = 0; + method.v = 0; +end + + +% number of variables +%-------------------------------------------------------------------------- +nx = numel(spm_vec(x)); +nv = numel(spm_vec(v)); +nh = size(p.h,1); +ng = size(p.g,1); + +dp.h.dh = sparse(nh,0); +dp.g.dg = sparse(ng,0); +dp.h.dx = sparse(nh,nx); +dp.h.dv = sparse(nh,nv); +dp.g.dx = sparse(ng,nx); +dp.g.dv = sparse(ng,nv); + + +% gradients w.r.t. h only (no state-dependent noise) +%---------------------------------------------------------------------- +if method.h || method.g + + for i = 1:N + + % precision of causal and hidden states + %-------------------------------------------------------------- + dhdh{i,i} = spm_diff(M(i).ph,x{i},v{i},qh.h{i},M(i),3); + dgdg{i,i} = spm_diff(M(i).pg,x{i},v{i},qh.g{i},M(i),3); + + end + + % Concatenate over hierarchical levels + %------------------------------------------------------------------ + dp.h.dh = spm_cat(dhdh); + dp.g.dg = spm_cat(dgdg); + +end + + +% gradients w.r.t. causal states +%---------------------------------------------------------------------- +if method.v + + for i = 1:N + + % precision of causal states + %-------------------------------------------------------------- + dhdv{i,i} = spm_diff(M(i).ph,x{i},v{i},qh.h{i},M(i),2); + + % precision of hidden states + %-------------------------------------------------------------- + dgdv{i,i} = spm_diff(M(i).pg,x{i},v{i},qh.g{i},M(i),2); + + end + + % Concatenate over hierarchical levels + %------------------------------------------------------------------ + dp.h.dv = spm_cat(dhdv); + dp.g.dv = spm_cat(dgdv); + +end + +% gradients w.r.t. hidden states +%---------------------------------------------------------------------- +if method.x + + for i = 1:N + + % precision of causal states + %-------------------------------------------------------------- + dhdx{i,i} = spm_diff(M(i).ph,x{i},v{i},qh.h{i},M(i),1); + + % precision of hidden states + %-------------------------------------------------------------- + dgdx{i,i} = spm_diff(M(i).pg,x{i},v{i},qh.g{i},M(i),1); + + end + + % Concatenate over hierarchical levels + %------------------------------------------------------------------ + dp.h.dx = spm_cat(dhdx); + dp.g.dx = spm_cat(dgdx); + +end + + diff --git a/spm_LAP_iS.m b/spm_LAP_iS.m new file mode 100644 index 0000000..725dcf4 --- /dev/null +++ b/spm_LAP_iS.m @@ -0,0 +1,20 @@ +function [iS] = spm_LAP_iS(p,R) +% default precision function for LAP models (hidden states) +% FORMAT [iS] = spm_LAP_iS(p,R) +% +% p{1} - vector of precisions for causal states (v) +% p{2} - vector of precisions for hidden states (v) +% R - generalised precision matrix +% +% iS - precision matrix for generalised states (causal and then hidden) +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: spm_LAP_iS.m 3694 2010-01-22 14:16:51Z karl $ + +% precisions for generalised errors on causal (V) and hidden states (W) +%========================================================================== +V = kron(R,diag(exp(p.h))); +W = kron(R,diag(exp(p.g))); +iS = blkdiag(V,W); diff --git a/spm_LAP_pg.m b/spm_LAP_pg.m new file mode 100644 index 0000000..1d75359 --- /dev/null +++ b/spm_LAP_pg.m @@ -0,0 +1,28 @@ +function p = spm_LAP_pg(x,v,h,M); +% default precision function for LAP models (hidden states) +% FORMAT p = spm_LAP_pg(x,v,h,M); +% +% x - hidden states +% v - causal states +% h - precision parameters +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: spm_LAP_pg.m 3694 2010-01-22 14:16:51Z karl $ + +% fixed components +%-------------------------------------------------------------------------- +p = sparse(M.n,1); +try + W = diag(M.W); + if all(W) + p = log(W); + end +end + +% free components +%-------------------------------------------------------------------------- +for i = 1:length(M.R) + p = p + h(i)*diag(M.R{i}); +end diff --git a/spm_LAP_ph.m b/spm_LAP_ph.m new file mode 100644 index 0000000..67ddd0c --- /dev/null +++ b/spm_LAP_ph.m @@ -0,0 +1,28 @@ +function p = spm_LAP_ph(x,v,h,M); +% default precision function for LAP models (causal states) +% FORMAT p = spm_LAP_ph(x,v,h,M); +% +% x - hidden states +% v - causal states +% h - precision parameters +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: spm_LAP_ph.m 3694 2010-01-22 14:16:51Z karl $ + +% fixed components +%-------------------------------------------------------------------------- +p = sparse(M.l,1); +try + V = diag(M.V); + if all(V) + p = log(V); + end +end + +% free components +%-------------------------------------------------------------------------- +for i = 1:length(M.Q) + p = p + h(i)*diag(M.Q{i}); +end diff --git a/spm_Menu.fig b/spm_Menu.fig index 19b8af8..6b19620 100644 Binary files a/spm_Menu.fig and b/spm_Menu.fig differ diff --git a/spm_NAP.m b/spm_NAP.m new file mode 100644 index 0000000..0ee81c5 --- /dev/null +++ b/spm_NAP.m @@ -0,0 +1,796 @@ +function [DEM] = spm_LAP(DEM) +% Laplacian model inversion +% FORMAT DEM = spm_LAP(DEM) +% +% DEM.M - hierarchical model +% DEM.Y - response variable, output or data +% DEM.U - explanatory variables, inputs or prior expectation of causes +%__________________________________________________________________________ +% +% generative model +%-------------------------------------------------------------------------- +% M(i).g = v = g(x,v,P) {inline function, string or m-file} +% M(i).f = dx/dt = f(x,v,P) {inline function, string or m-file} +% +% M(i).ph = pi(v) = ph(x,v,h,M) {inline function, string or m-file} +% M(i).pg = pi(x) = pg(x,v,g,M) {inline function, string or m-file} +% +% M(i).pE = prior expectation of p model-parameters +% M(i).pC = prior covariances of p model-parameters +% M(i).hE = prior expectation of h log-precision (cause noise) +% M(i).hC = prior covariances of h log-precision (cause noise) +% M(i).gE = prior expectation of g log-precision (state noise) +% M(i).gC = prior covariances of g log-precision (state noise) +% M(i).xP = precision (states) +% M(i).Q = precision components (input noise) +% M(i).R = precision components (state noise) +% M(i).V = fixed precision (input noise) +% M(i).W = fixed precision (state noise) +% +% M(i).m = number of inputs v(i + 1); +% M(i).n = number of states x(i); +% M(i).l = number of output v(i); +% +% conditional moments of model-states - q(u) +%-------------------------------------------------------------------------- +% qU.x = Conditional expectation of hidden states +% qU.v = Conditional expectation of causal states +% qU.w = Conditional prediction error (states) +% qU.z = Conditional prediction error (causes) +% qU.C = Conditional covariance: cov(v) +% qU.S = Conditional covariance: cov(x) +% +% conditional moments of model-parameters - q(p) +%-------------------------------------------------------------------------- +% qP.P = Conditional expectation +% qP.C = Conditional covariance +% +% conditional moments of hyper-parameters (log-transformed) - q(h) +%-------------------------------------------------------------------------- +% qH.h = Conditional expectation (cause noise) +% qH.g = Conditional expectation (state noise) +% qH.C = Conditional covariance +% +% F = log-evidence = log-marginal likelihood = negative free-energy +%__________________________________________________________________________ +% +% spm_LAP implements a variational scheme under the Laplace +% approximation to the conditional joint density q on states (u), parameters +% (p) and hyperparameters (h,g) of any analytic nonlinear hierarchical dynamic +% model, with additive Gaussian innovations. +% +% q(u,p,h,g) = max q +% +% L is the ln p(y,u,p,h,g|M) under the model M. The conditional covariances +% obtain analytically from the curvature of L with respect to the unknowns. +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: spm_NAP.m 3694 2010-01-22 14:16:51Z karl $ + + +% find or create a DEM figure +%-------------------------------------------------------------------------- +Fdem = spm_figure('GetWin','DEM'); + +% check model, data and priors +%========================================================================== +[M Y U] = spm_DEM_set(DEM); + + +% number of iterations +%-------------------------------------------------------------------------- +try nD = M(1).E.nD; catch nD = 1; end +try nN = M(1).E.nN; catch nN = 16; end + + +% ensure integration scheme evaluates gradients at each time-step +%-------------------------------------------------------------------------- +M(1).E.linear = 4; + +% assume predicions are a function of[f] hyperparameters +%-------------------------------------------------------------------------- +try + method = M(1).E.precision; +catch + method = 1; + M(1).E.precision = method; +end + +% additional checks for Laplace models (precision functions; ph and pg) +%-------------------------------------------------------------------------- +for i = 1:length(M) + try + feval(M(i).ph,M(i).x,M(i).v,M(i),hE,M(i)); + catch + M(i).ph = inline('spm_LAP_ph(x,v,h,M)','x','v','h','M'); + end + try + feval(M(i).pg,M(i).x,M(i).v,M(i),gE,M(i)); + catch + M(i).pg = inline('spm_LAP_pg(x,v,h,M)','x','v','h','M'); + end +end + + +% order parameters (d = n = 1 for static models) and checks +%========================================================================== +d = M(1).E.d + 1; % embedding order of q(v) +n = M(1).E.n + 1; % embedding order of q(x) + +% number of states and parameters +%-------------------------------------------------------------------------- +ns = size(Y,2); % number of samples +nl = size(M,2); % number of levels +nv = sum(spm_vec(M.m)); % number of v (casual states) +nx = sum(spm_vec(M.n)); % number of x (hidden states) +ny = M(1).l; % number of y (inputs) +nc = M(end).l; % number of c (prior causes) +nu = nv*d + nx*n; % number of generalised states +ne = nv*n + nx*n + ny*n; % number of generalised errors + + +% precision (R) of generalised errors and null matrices for concatenation +%========================================================================== +W = sparse(nx*n,nx*n); +V = sparse((ny + nv)*n,(ny + nv)*n); + +% fixed priors on states (u) +%-------------------------------------------------------------------------- +Px = kron(sparse(1,1,1,n,n),spm_cat(spm_diag({M.xP}))); +Pv = kron(sparse(1,1,1,d,d),sparse(nv,nv)); +pu.ic = spm_cat(spm_diag({Px Pv})); + +% hyperpriors +%-------------------------------------------------------------------------- +s = M(1).E.s; +sh = log(s); +sg = log(s); +sC = speye(2,2)/128; +ph.h = spm_vec({M.hE M.gE sh sg}); % prior expectation of h,g +ph.c = spm_cat(spm_diag({M.hC M.gC sC})); % prior covariances of h,g +ph.ic = spm_pinv(ph.c); % prior precision of h,g + +qh.h = {M.hE}; % conditional expectation h +qh.g = {M.gE}; % conditional expectation g +nh = length(spm_vec(qh.h)); % number of hyperparameters h +ng = length(spm_vec(qh.g)); % number of hyperparameters g +qh.sh = sh; % conditional expectation sh +qh.sg = sg; % conditional expectation sg +npp = nh + ng + 2; % number of hyerparameters + + +% 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); % basis for parameters + M(i).p = size(qp.u{i},2); % number of qp.p + qp.p{i} = sparse(M(i).p,1); % initial deviates + pp.c{i,i} = qp.u{i}'*M(i).pC*qp.u{i}; % prior covariance + +end +Up = spm_cat(spm_diag(qp.u)); + +% priors on parameters +%-------------------------------------------------------------------------- +pp.p = spm_vec(M.pE); +pp.c = spm_cat(pp.c); +pp.ic = spm_inv(pp.c); + +% initialise conditional density q(p) +%-------------------------------------------------------------------------- +for i = 1:(nl - 1) + try + qp.p{i} = qp.p{i} + qp.u{i}'*(spm_vec(M(i).P) - spm_vec(M(i).pE)); + end +end +np = size(Up,2); + + +% initialise cell arrays for D-Step; e{i + 1} = (d/dt)^i[e] = e[i] +%========================================================================== +qu.x = cell(n,1); +qu.v = cell(n,1); +qu.y = cell(n,1); +qu.u = cell(n,1); +[qu.x{:}] = deal(sparse(nx,1)); +[qu.v{:}] = deal(sparse(nv,1)); +[qu.y{:}] = deal(sparse(ny,1)); +[qu.u{:}] = deal(sparse(nc,1)); + +% initialise cell arrays for hierarchical structure of x[0] and v[0] +%-------------------------------------------------------------------------- +x = {M(1:end - 1).x}; +v = {M(1 + 1:end).v}; +qu.x{1} = spm_vec(x); +qu.v{1} = spm_vec(v); + +% derivatives for Jacobian of D-step +%-------------------------------------------------------------------------- +Dx = kron(spm_speye(n,n,1),spm_speye(nx,nx)); +Dv = kron(spm_speye(d,d,1),spm_speye(nv,nv)); +Dy = kron(spm_speye(n,n,1),spm_speye(ny,ny)); +Dc = kron(spm_speye(d,d,1),spm_speye(nc,nc)); +Du = spm_cat(spm_diag({Dx,Dv})); +Ip = spm_speye(np, np ); +Ih = spm_speye(npp,npp); +qp.dp = sparse(np,1); % conditional expectation of dp/dt +qh.dp = sparse(npp,1); % conditional expectation of dh/dt + + +% gradients of generalised weighted errors +%-------------------------------------------------------------------------- +dedh = sparse(nh,ne); +dedg = sparse(ng,ne); +dedv = sparse(nv,ne); +dedx = sparse(nx,ne); + +% curvatures of Gibb's energy w.r.t. hyperparameters +%-------------------------------------------------------------------------- +dedhh = sparse(nh,nh); +dedgg = sparse(ng,ng); +dedhsh = sparse(nh,1); +dedshh = sparse(1,nh); +dedgsg = sparse(ng,1); +dedsgg = sparse(1,ng); +dEdup = sparse(nu,np); + +% preclude unnecessary iterations +%-------------------------------------------------------------------------- +if ~np && ~npp, nN = 1; end +if ~npp, method = 0; end + +% precision on parameter fluctuations +%-------------------------------------------------------------------------- +kh = ns*16; +kp = ns*16; + +% Iterate Lapalace scheme +%========================================================================== +Fs = -Inf; +for iN = 1:nN + + % get time and clear persistent variables in evaluation routines + %---------------------------------------------------------------------- + tic; clear spm_DEM_eval + + % [re-]set states & their derivatives + %---------------------------------------------------------------------- + try, qu = Q(1).u; end + + % increase precision on parameter fluctuations + %---------------------------------------------------------------------- + kp = kp + 64; + kh = kh + 64; + + + % D-Step: (nD D-Steps for each sample) + %====================================================================== + for is = 1:ns + + % D-Step: until convergence for static systems + %================================================================== + for iD = 1:nD + + % sampling time + %-------------------------------------------------------------- + ts = is + (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 + + + % evaluate functions and derivatives + %============================================================== + + % prediction errors (E) and precision (p) + %-------------------------------------------------------------- + [E dE] = spm_DEM_eval(M,qu,qp); + [p dp] = spm_LAP_eval(M,qu,qh); + + + % gradients of log(det(iS)) dDd... + %============================================================== + + % get precision matrices + %-------------------------------------------------------------- + [Rh Vh] = spm_DEM_R(n,exp(qh.sh)); + [Rg Vg] = spm_DEM_R(n,exp(qh.sg)); + iSh = diag(exp(p.h)); + iSg = diag(exp(p.g)); + iS = blkdiag(kron(Rh,iSh),kron(Rg,iSg)); + + + % gradients of trace(diag(p)) = sum(p); p = precision vector + %-------------------------------------------------------------- + dpdx = n*sum(spm_cat({dp.h.dx; dp.g.dx})); + dpdv = n*sum(spm_cat({dp.h.dv; dp.g.dv})); + dpdh = n*sum(dp.h.dh); + dpdg = n*sum(dp.g.dg); + dpdx = kron(sparse(1,1,1,1,n),dpdx); + dpdv = kron(sparse(1,1,1,1,d),dpdv); + dDdu = [dpdx dpdv]'; + + + % gradients w.r.t. hyperparameters + %-------------------------------------------------------------- + [dRdhh dRdh] = spm_diff('spm_DEM_R',n,exp(qh.sh),[2 2]); + [dRdgg dRdg] = spm_diff('spm_DEM_R',n,exp(qh.sg),[2 2]); + dRdh = dRdh{1}*exp(qh.sh); + dRdg = dRdg{1}*exp(qh.sg); + dRdhh = dRdhh{1}{1}*exp(qh.sh) + dRdh; + dRdgg = dRdgg{1}{1}*exp(qh.sg) + dRdg; + dDdh = length(iSh)*trace(dRdh*Vh); + dDdg = length(iSg)*trace(dRdg*Vg); + dDdh = [dpdh dpdg dDdh dDdg]'; + + + % gradients precision-weighted generalised error dSd.. + %============================================================== + diS = blkdiag(kron(dRdh, iSh),W); + dedsh = E'*diS; + diS = blkdiag(kron(dRdhh,iSh),W); + dedshsh = E'*diS*E; + diS = blkdiag(V,kron(dRdg, iSg)); + dedsg = E'*diS; + diS = blkdiag(V,kron(dRdgg,iSg)); + dedsgsg = E'*diS*E; + + % gradients w.r.t. hyperparameters + %-------------------------------------------------------------- + if method > 0 + for i = 1:nh + diS = diag(dp.h.dh(:,i).*exp(p.h)); + diS = blkdiag(kron(Rh,diS),W); + dedh(i,:) = E'*diS; + end + for i = 1:ng + diS = diag(dp.g.dg(:,i).*exp(p.g)); + diS = blkdiag(V,kron(Rg,diS)); + dedg(i,:) = E'*diS; + end + end + + % gradients w.r.t. causal states + %-------------------------------------------------------------- + if method > 1 + for i = 1:nv + diV = diag(dp.h.dv(:,i).*exp(p.h)); + diW = diag(dp.g.dv(:,i).*exp(p.g)); + diS = blkdiag(kron(R,diV),kron(R,diW)); + dedv(i,:) = E'*diS; + end + end + + % gradients w.r.t. hidden states + %-------------------------------------------------------------- + if method > 2 + for i = 1:nx + diV = diag(dp.h.dx(:,i).*exp(p.h)); + diW = diag(dp.g.dx(:,i).*exp(p.g)); + diS = blkdiag(kron(R,diV),kron(R,diW)); + dedx(i,:) = E'*diS; + end + end + + dSdx = kron(sparse(1,1,1,n,1),dedx); + dSdv = kron(sparse(1,1,1,d,1),dedv); + dSdu = [dSdx; dSdv]; + dEdh = [dedh; dedg; dedsh; dedsg]; + dEdp = dE.dp'*iS; + dEdu = dE.du'*iS; + + % curvatures w.r.t. hyperparameters + %-------------------------------------------------------------- + for i = 1:nh + for j = i:nh + diS = diag(dp.h.dh(:,i).*dp.h.dh(:,j).*exp(p.h)); + diS = blkdiag(kron(Rh,diS),W); + dedhh(i,j) = E'*diS*E; + dedhh(j,i) = dedhh(i,j); + end + diS = diag(dp.h.dh(:,i).*exp(p.h)); + diS = blkdiag(kron(dRdh,diS),W); + dedhsh(i,1) = E'*diS*E; + dedshh(1,i) = dedhsh(i,1); + end + for i = 1:ng + for j = i:ng + diS = diag(dp.g.dg(:,i).*dp.g.dg(:,j).*exp(p.g)); + diS = blkdiag(V,kron(Rg,diS)); + dedgg(i,j) = E'*diS*E; + dedgg(j,i) = dedgg(i,j); + end + diS = diag(dp.g.dg(:,i).*exp(p.g)); + diS = blkdiag(V,kron(dRdg,diS)); + dedgsg(i,1) = E'*diS*E; + dedsgg(1,i) = dedgsg(i,1); + end + + % combined curvature + %-------------------------------------------------------------- + dSdhh = spm_cat({dedhh [] dedhsh []; + [] dedgg [] dedgsg; + dedshh [] dedshsh []; + [] dedsgg [] dedsgsg}); + + + % curvatures w.r.t. parameters and states + %-------------------------------------------------------------- + % for i = 1:np, dEdup(:,i) = dE.dup{i}'*iS*E; end + + % errors (from prior expectations) (NB pp.p = 0) + %-------------------------------------------------------------- + Eu = spm_vec(qu.x(1:n),qu.v(1:d)); + Ep = spm_vec(qp.p); + Eh = spm_vec(qh.h,qh.g,qh.sh,qh.sg) - ph.h; + + + % first-order derivatives of Gibb's Energy + %============================================================== + dLdu = dEdu*E + dSdu*E/2 - dDdu/2 + pu.ic*Eu; + dLdh = dEdh*E/2 - dDdh/2 + ph.ic*Eh; + dLdp = dEdp*E + pp.ic*Ep; + + + % and second-order derivatives of Gibb's Energy + %-------------------------------------------------------------- + dLduu = dEdu*dE.du + dSdu*dE.du*2 + pu.ic; + dLdup = dEdu*dE.dp + dSdu*dE.dp + dEdup; + dLdpp = dEdp*dE.dp + pp.ic; + dLdhh = dSdhh/2 + ph.ic; + dLdhu = dEdh*dE.du; + dLduy = dEdu*dE.dy; + dLduc = dEdu*dE.dc; + dLdpy = dEdp*dE.dy; + dLdpc = dEdp*dE.dc; + dLdhy = dEdh*dE.dy; + dLdhc = dEdh*dE.dc; + dLdhp = dEdh*dE.dp; + dLdpu = dLdup'; + dLduh = dLdhu'; + dLdph = dLdhp'; + + + % save conditional moments (and prediction error) at Q{t} + %============================================================== + if iD == 1 + + % means + %---------------------------------------------------------- + Q(is).e = E; + Q(is).u = qu; + Q(is).p = qp; + Q(is).h = qh; + + % precision and covariances + %---------------------------------------------------------- + iC = spm_cat({dLduu dLdup []; + dLdpu dLdpp []; + [] [] dLdhh}); + + C = spm_inv(iC); + + % save conditional covariances + %---------------------------------------------------------- + Q(is).u.s = C([1:nx],[1:nx]); + Q(is).u.c = C([1:nv] + nx*n, [1:nv] + nx*n); + Q(is).p.c = C([1:np] + nu, [1:np] + nu); + Q(is).h.c = C([1:npp] + nu + np,[1:npp] + nu + np); + + % Free-energy (states) + %---------------------------------------------------------- + L(is) = ... + - E'*iS*E/2 + spm_logdet(iS)/2 - n*ny*log(2*pi)/2 ... + - Eu'*pu.ic*Eu/2 + spm_logdet(pu.ic)/2 - spm_logdet(dLduu)/2; + + % Free-energy (parameters) + %---------------------------------------------------------- + A(is) = - E'*iS*E/2 + spm_logdet(iS)/2 ... + - Eu'*pu.ic*Eu/2 + spm_logdet(pu.ic)/2 ... + - Ep'*pp.ic*Ep/2 + spm_logdet(pp.ic)/2 ... + - Eh'*ph.ic*Eh/2 + spm_logdet(ph.ic)/2 ... + - n*ny*log(2*pi)/2 + spm_logdet(C)/2; + + + end + + % update conditional moments + %============================================================== + + % precision of fluctuations + %-------------------------------------------------------------- + Kp = kp*Ip; + Kh = kh*Ih; + + % assemble conditional means + %-------------------------------------------------------------- + q{1} = qu.y(1:n); + q{2} = qu.x(1:n); + q{3} = qu.v(1:d); + q{4} = qu.u(1:d); + q{5} = qp.p; + q{6} = qh.h; + q{7} = qh.g; + q{8} = qh.sh; + q{9} = qh.sg; + q{10} = qp.dp; + q{11} = qh.dp; + + % flow + %-------------------------------------------------------------- + f{1} = Dy*spm_vec(q{1}); + f{2} = Du*spm_vec(q{2:3}) - dLdu; + f{3} = Dc*spm_vec(q{4}); + f{4} = spm_vec(q{10}); + f{5} = spm_vec(q{11}); + f{6} = -kp*spm_vec(q{10}) - dLdp; + f{7} = -kh*spm_vec(q{11}) - dLdh; + + % and Jacobian + %-------------------------------------------------------------- + dfdq = spm_cat({Dy [] [] [] [] [] []; + -dLduy Du-dLduu -dLduc [] [] [] []; + [] [] Dc [] [] [] []; + [] [] [] [] [] Ip []; + [] [] [] [] [] [] Ih; + -dLdpy -dLdpu -dLdpc -dLdpp -dLdph -Kp []; + -dLdhy -dLdhu -dLdhc -dLdhp -dLdhh [] -Kh}); + + + % update conditional modes of states + %============================================================== + dq = spm_dx(dfdq, spm_vec(f), 1/nD); + q = spm_unvec(spm_vec(q) + dq,q); + + % unpack conditional means + %-------------------------------------------------------------- + qu.x(1:n) = q{2}; + qu.v(1:d) = q{3}; + qp.p = q{5}; + qh.h = q{6}; + qh.g = q{7}; + qp.sh = q{8}; + qh.sg = q{9}; + qp.dp = q{10}; + qh.dp = q{11}; + + + end % D-Step + + end % sequence (ns) + + + % Bayesian parameter averaging + %====================================================================== + + % Conditional moments of time-averaged parameters + %---------------------------------------------------------------------- + Pp = 0; + Ep = 0; + for i = 1:ns + P = spm_inv(Q(i).p.c); + Ep = Ep + P*spm_vec(Q(i).p.p); + Pp = Pp + P; + end + Cp = spm_inv(Pp); + Ep = Cp*Ep; + + % conditional moments of hyper-parameters + %---------------------------------------------------------------------- + Ph = 0; + Eh = 0; + for i = 1:ns + P = spm_inv(Q(i).h.c); + Ph = Ph + P; + Eh = Eh + P*spm_vec({Q(i).h.h Q(i).h.g Q(i).h.sh Q(i).h.sg}); + end + Ch = spm_inv(Ph); + Eh = Ch*Eh - ph.h; + + % Free-action of states plus free-energy of parameters + %====================================================================== + Fs = sum(A); + Fi = sum(L) ... + - Ep'*pp.ic*Ep/2 + spm_logdet(pp.ic)/2 - spm_logdet(Pp)/2 ... + - Eh'*ph.ic*Eh/2 + spm_logdet(ph.ic)/2 - spm_logdet(Ph)/2; + + + % if F is increasing terminate + %---------------------------------------------------------------------- + if Fi < Fa && iN > 16 + break + else + Fa = Fi; + F(iN) = Fi; + S(iN) = Fs; + end + + % otherwise save conditional moments (for each time point) + %====================================================================== + for t = 1:length(Q) + + + % states and predictions + %------------------------------------------------------------------ + v = spm_unvec(Q(t).u.v{1},v); + x = spm_unvec(Q(t).u.x{1},x); + z = spm_unvec(Q(t).e(1:(ny + nv)),{M.v}); + w = spm_unvec(Q(t).e([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 + if M(nl).l, qU.z{nl}(:,t) = spm_vec(z{nl}); end + qU.v{1}(:,t) = spm_vec(Q(t).u.y{1}) - spm_vec(z{1}); + + % and conditional covariances + %------------------------------------------------------------------ + qU.S{t} = Q(t).u.s; + qU.C{t} = Q(t).u.c; + + % parameters + %------------------------------------------------------------------ + qP.p{t} = spm_vec(Q(t).p.p); + qP.c{t} = Q(t).p.c; + + % hyperparameters + %------------------------------------------------------------------ + qH.p{t} = spm_vec({Q(t).h.h Q(t).h.g Q(t).h.sh Q(t).h.sg}); + qH.c{t} = Q(t).h.c; + + end + + % graphics (states) + %---------------------------------------------------------------------- + figure(Fdem) + spm_DEM_qU(qU) + + % determine graphs to plot + %---------------------------------------------------------------------- + if np && nh + ap = subplot(2*nl,2,4*nl - 2); + ah = subplot(2*nl,2,4*nl); + elseif np + ap = subplot(nl,2,2*nl); + elseif nh + ah = subplot(nl,2,2*nl); + end + + % graphics (parameters and log-precisions) + %---------------------------------------------------------------------- + if np + axes(ap) + plot([1:ns],spm_cat(qP.p)) + set(gca,'XLim',[1 ns]) + title('parameters','FontSize',16) + end + if nh + axes(ah) + plot([1:ns],spm_cat(qH.p)) + set(gca,'XLim',[1 ns]) + title('log-precision','FontSize',16) + end + drawnow + + % report (EM-Steps) + %---------------------------------------------------------------------- + try + dF = F(end) - F(end - 1); + catch + dF = 0; + end + str{1} = sprintf('LAP: %i (%i)', iN,iD); + str{2} = sprintf('F:%.4e', full(Fs - F(1))); + str{3} = sprintf('dF:%.2e', full(dF)); + str{4} = sprintf('(%.2e sec)', full(toc)); + fprintf('%-16s%-16s%-14s%-16s\n',str{:}) + +end + + +% Place Bayesian parameter averages in output arguments +%========================================================================== + +% Conditional moments of time-averaged parameters +%-------------------------------------------------------------------------- +Pp = 0; +Ep = 0; +for i = 1:ns + + % weight in proportion to precisions + %---------------------------------------------------------------------- + P = spm_inv(qP.c{i}); + Ep = Ep + P*qP.p{i}; + Pp = Pp + P; + +end +Cp = spm_inv(Pp); +Ep = Cp*Ep; +P = {M.pE}; +qP.P = spm_unvec(Up*Ep + pp.p,P); +qP.C = Up*Cp*Up'; +qP.V = spm_unvec(diag(qP.C),P); +qP.U = Up; + +% conditional moments of hyper-parameters +%-------------------------------------------------------------------------- +Ph = 0; +Eh = 0; +for i = 1:ns + + % weight in proportion to precisions + %---------------------------------------------------------------------- + P = spm_inv(qH.c{i}); + Ph = Ph + P; + Eh = Eh + P*qH.p{i}; + +end +Ch = spm_inv(Ph); +Eh = Ch*Eh; +P = {qh.h qh.g qh.sh qh.sg}; +P = spm_unvec(Eh,P); +qH.h = P{1}; +qH.g = P{2}; +qH.sh = P{3}; +qH.sg = P{4}; +qH.C = Ch; +P = spm_unvec(diag(qH.C),P); +qH.V = P{1}; +qH.W = P{2}; + + + +% assign output variables +%-------------------------------------------------------------------------- +DEM.M = M; % model +DEM.U = U; % causes + +DEM.qU = qU; % conditional moments of model-states +DEM.qP = qP; % conditional moments of model-parameters +DEM.qH = qH; % conditional moments of hyper-parameters + +DEM.F = F; % [-ve] Free energy +DEM.S = S; % [-ve] Free action + +return + + + +% Notes +%========================================================================== + + % numerical approximations + %---------------------------------------------------------- + qq.x = qu.x(1:n); + qq.v = qu.v(1:d); + qq.p = qp.p; + qq.h = qh.h; + qq.g = qh.g; + qq.sh = qh.sh; + qq.sg = qh.sg; + + dLdqq = spm_diff('spm_LAP_F',qq,qu,qp,qh,pu,pp,ph,M,[1 1]); + dLdqq = spm_cat(dLdqq'); + + subplot(2,2,1);imagesc(dLdqq); axis square + subplot(2,2,2);imagesc(iC); axis square + subplot(2,2,3);imagesc(dLdqq - iC);axis square + subplot(2,2,4);plot(iC,':k');hold on; + plot(dLdqq - iC,'r');hold off; axis square + drawnow diff --git a/spm_P.m b/spm_P.m index bf5283b..feb8ab4 100644 --- a/spm_P.m +++ b/spm_P.m @@ -1,6 +1,6 @@ -function [P,p,Em,En,EN] = spm_P(c,k,Z,df,STAT,R,n,S) +function [P,p,Ec,Ek] = spm_P(c,k,Z,df,STAT,R,n,S) % Returns the [un]corrected P value using unifed EC theory -% FORMAT [P p Em En EN] = spm_P(c,k,Z,df,STAT,R,n,S) +% FORMAT [P p Ec Ek] = spm_P(c,k,Z,df,STAT,R,n,S) % % c - cluster number % k - extent {RESELS} @@ -16,11 +16,10 @@ % n - number of component SPMs in conjunction % S - Voxel count % -% P - corrected P value - P(n > kmax} -% p - uncorrected P value - P(n > k} -% Em - expected total number of maxima {m} -% En - expected total number of resels per cluster {n} -% EN - expected total number of voxels {N} +% P - corrected P value - P(C >= c | K >= k} +% p - uncorrected P value +% Ec - expected total number of clusters +% Ek - expected total number of resels per cluster % %__________________________________________________________________________ % @@ -36,16 +35,16 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Thomas Nichols -% $Id: spm_P.m 2690 2009-02-04 21:44:28Z guillaume $ +% $Id: spm_P.m 3824 2010-04-19 19:23:35Z karl $ % set global var NOBONF to 1 to turn off Bonferroni %-------------------------------------------------------------------------- global NOBONF; if ~isempty(NOBONF) && NOBONF, S = []; end -if (nargin < 8), S = []; end +if nargin < 8, S = []; end -[P,p,Em,En,EN] = spm_P_RF(c,k,Z,df,STAT,R,n); +[P,p,Ec,Ek] = spm_P_RF(c,k,Z,df,STAT,R,n); % Use lower Bonferroni P value (if possible) %========================================================================== diff --git a/spm_P_FDR.m b/spm_P_FDR.m index aa3b572..0f15cbb 100644 --- a/spm_P_FDR.m +++ b/spm_P_FDR.m @@ -13,9 +13,9 @@ % n - Conjunction number % Ps - Vector of sorted (ascending) p-values in search volume % -% P - corrected FDR P value +% P - corrected FDR P value % -%___________________________________________________________________________ +%__________________________________________________________________________ % % The Benjamini & Hochberch (1995) False Discovery Rate (FDR) procedure % finds a threshold u such that the expected FDR is at most q. spm_P_FDR @@ -64,21 +64,20 @@ % Yekutieli & Benjamini (1999). "Resampling-based false discovery rate % controlling multiple test procedures for correlated test % statistics". J of Statistical Planning and Inference, 82:171-196. -%___________________________________________________________________________ +%__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Thomas Nichols -% $Id: spm_P_FDR.m 2690 2009-02-04 21:44:28Z guillaume $ +% $Id: spm_P_FDR.m 3982 2010-07-09 13:36:53Z guillaume $ - -% Set Benjamini & Yeuketeli cV for independence/PosRegDep case -%----------------------------------------------------------------------- +%-Set Benjamini & Yeuketeli cV for independence/PosRegDep case +%-------------------------------------------------------------------------- cV = 1; S = length(Ps); -% Calculate p value of Z -%----------------------------------------------------------------------- +%-Calculate p-value of Z +%-------------------------------------------------------------------------- if STAT == 'Z' PZ = (1 - spm_Ncdf(Z)).^n; elseif STAT == 'T' @@ -91,28 +90,28 @@ PZ = Z; end -%-Calculate FDR p values -%----------------------------------------------------------------------- +%-Calculate FDR p-values +%-------------------------------------------------------------------------- % If Z is a value in the statistic image, then the adjusted p-value % defined in Yekutieli & Benjamini (1999) (eqn 3) is obtained. If Z % isn't a value in the image, then the adjusted p-value for the next % smallest statistic value (next largest uncorrected p) is returned. %-"Corrected" p-values -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- Qs = Ps*S./(1:S)'*cV; -% -"Adjusted" p-values -%----------------------------------------------------------------------- -P = zeros(size(Z)); -for i = 1:length(Z) +%-"Adjusted" p-values +%-------------------------------------------------------------------------- +P = zeros(size(PZ)); +for i = 1:numel(PZ) - % Find PZ(i) in Ps, or smallest Ps(j) s.t. Ps(j) >= PZ(i) - %--------------------------------------------------------------- + %-Find PZ(i) in Ps, or smallest Ps(j) s.t. Ps(j) >= PZ(i) + %---------------------------------------------------------------------- I = find(Ps>=PZ(i), 1 ); - % -"Adjusted" p-values - %--------------------------------------------------------------- + %-"Adjusted" p-values + %---------------------------------------------------------------------- if isempty(I) P(i) = 1; else diff --git a/spm_P_RF.m b/spm_P_RF.m index 3d98301..2a6f32a 100644 --- a/spm_P_RF.m +++ b/spm_P_RF.m @@ -1,10 +1,10 @@ -function [P,p,Em,En,EN] = spm_P_RF(c,k,Z,df,STAT,R,n) +function [P,p,Ec,Ek] = spm_P_RF(c,k,Z,df,STAT,R,n) % Returns the [un]corrected P value using unifed EC theory -% FORMAT [P p Em En EN] = spm_P_RF(c,k,Z,df,STAT,R,n) +% FORMAT [P p Ec Ek] = spm_P_RF(c,k,z,df,STAT,R,n) % % c - cluster number % k - extent {RESELS} -% Z - height {minimum over n values} +% z - height {minimum over n values} % df - [df{interest} df{error}] % STAT - Statistical field % 'Z' - Gaussian field @@ -14,20 +14,19 @@ % R - RESEL Count {defining search volume} % n - number of component SPMs in conjunction % -% P - corrected P value - P(n > kmax} -% p - uncorrected P value - P(n > k} -% Em - expected total number of maxima {m} -% En - expected total number of resels per cluster {n} -% EN - expected total number of voxels {N} +% P - corrected P value - P(C >= c | K >= k} +% p - uncorrected P value +% Ec - expected number of clusters (maxima) +% Ek - expected number of resels per cluster % %__________________________________________________________________________ % % spm_P_RF returns the probability of c or more clusters with more than -% k voxels in volume process of R RESELS thresholded at u. All p values +% k resels in volume process of R RESELS thresholded at u. All p values % can be considered special cases: % -% spm_P_RF(1,0,Z,df,STAT,1,n) = uncorrected p value -% spm_P_RF(1,0,Z,df,STAT,R,n) = corrected p value {based on height Z) +% spm_P_RF(1,0,z,df,STAT,1,n) = uncorrected p value +% spm_P_RF(1,0,z,df,STAT,R,n) = corrected p value {based on height z) % spm_P_RF(1,k,u,df,STAT,R,n) = corrected p value {based on extent k at u) % spm_P_RF(c,k,u,df,STAT,R,n) = corrected p value {based on number c at k and u) % spm_P_RF(c,0,u,df,STAT,R,n) = omnibus p value {based on number c at u) @@ -50,7 +49,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_P_RF.m 3627 2009-12-09 18:41:01Z guillaume $ +% $Id: spm_P_RF.m 3994 2010-07-13 15:53:30Z guillaume $ % get expectations @@ -58,20 +57,20 @@ % get EC densities %-------------------------------------------------------------------------- -D = find(R, 1, 'last' ); -R = R(1:D); -G = sqrt(pi)./gamma(([1:D])/2); -EC = spm_ECdensity(STAT,Z,df); -EC = max(EC([1:D]), eps); +D = find(R,1,'last'); +R = R(1:D); +G = sqrt(pi)./gamma(([1:D])/2); +EC = spm_ECdensity(STAT,Z,df); +EC = max(EC(1:D),eps); % corrected p value %-------------------------------------------------------------------------- -P = triu(toeplitz(EC'.*G))^n; -P = P(1,:); -EM = (R./G).*P; % over D dimensions -Em = sum(EM); % -EN = P(1)*R(D); % -En = EN/EM(D); % En = EN/EM(D); +P = triu(toeplitz(EC'.*G))^n; +P = P(1,:); +EM = (R./G).*P; % over D dimensions +Ec = sum(EM); % +EN = P(1)*R(D); % +Ek = EN/EM(D); % Ek = EN/EM(D); % get P{n > k} %========================================================================== @@ -79,36 +78,36 @@ % assume a Gaussian form for P{n > k} ~ exp(-beta*k^(2/D)) % Appropriate for SPM{Z} and high d.f. SPM{T} %-------------------------------------------------------------------------- -D = D - 1; -if ~k || ~D +D = D - 1; +if ~k || ~D p = 1; elseif STAT == 'Z' - beta = (gamma(D/2 + 1)/En)^(2/D); + beta = (gamma(D/2 + 1)/Ek)^(2/D); p = exp(-beta*(k^(2/D))); elseif STAT == 'T' - beta = (gamma(D/2 + 1)/En)^(2/D); + beta = (gamma(D/2 + 1)/Ek)^(2/D); p = exp(-beta*(k^(2/D))); elseif STAT == 'X' - beta = (gamma(D/2 + 1)/En)^(2/D); + beta = (gamma(D/2 + 1)/Ek)^(2/D); p = exp(-beta*(k^(2/D))); elseif STAT == 'F' - beta = (gamma(D/2 + 1)/En)^(2/D); + beta = (gamma(D/2 + 1)/Ek)^(2/D); p = exp(-beta*(k^(2/D))); end % Poisson clumping heuristic {for multiple clusters} %========================================================================== -P = 1 - spm_Pcdf(c - 1,(Em + eps)*p); +P = 1 - spm_Pcdf(c - 1,(Ec + eps)*p); % set P and p = [] for non-implemented cases @@ -122,7 +121,6 @@ %++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - %========================================================================== % spm_ECdensity %========================================================================== @@ -187,10 +185,10 @@ EC(1,:) = 1 - spm_Fcdf(t,df); EC(2,:) = a^(1/2)*exp(gammaln((v+k-1)/2)-b)*2^(1/2)... - *(k*t/v).^(1/2*(k-1)).*(1+k*t/v).^(-1/2*(v+k-2)); + *(k*t/v).^(1/2*(k-1)).*(1+k*t/v).^(-1/2*(v+k-2)); EC(3,:) = a*exp(gammaln((v+k-2)/2)-b)*(k*t/v).^(1/2*(k-2))... - .*(1+k*t/v).^(-1/2*(v+k-2)).*((v-1)*k*t/v-(k-1)); + .*(1+k*t/v).^(-1/2*(v+k-2)).*((v-1)*k*t/v-(k-1)); EC(4,:) = a^(3/2)*exp(gammaln((v+k-3)/2)-b)... - *2^(-1/2)*(k*t/v).^(1/2*(k-3)).*(1+k*t/v).^(-1/2*(v+k-2))... - .*((v-1)*(v-2)*(k*t/v).^2-(2*v*k-v-k-1)*(k*t/v)+(k-1)*(k-2)); + *2^(-1/2)*(k*t/v).^(1/2*(k-3)).*(1+k*t/v).^(-1/2*(v+k-2))... + .*((v-1)*(v-2)*(k*t/v).^2-(2*v*k-v-k-1)*(k*t/v)+(k-1)*(k-2)); end diff --git a/spm_ROI.m b/spm_ROI.m index 915a4cc..ca294d1 100644 --- a/spm_ROI.m +++ b/spm_ROI.m @@ -2,7 +2,7 @@ % Region of Interest specification % FORMAT xY = spm_ROI(xY) % xY - VOI structure -% xY.def - VOI definition [sphere, box, mask, cluster, ...] +% xY.def - VOI definition [sphere, box, mask, cluster, all] % xY.rej - cell array of disabled VOI definition options % xY.xyz - centre of VOI {mm} % xY.spec - VOI definition parameters @@ -10,6 +10,9 @@ % % FORMAT [xY, XYZmm, j] = spm_ROI(xY, XYZmm) % XYZmm - [3xm] locations of voxels {mm} +% If an image filename, an spm_vol structure or a NIfTI object is +% given instead, XYZmm will be initialised to all voxels within +% the field of view of that image. % % XYZmm - [3xn] filtered locations of voxels {mm} (m>=n) within VOI xY % j - [1xn] indices of input locations XYZmm within VOI xY @@ -17,7 +20,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston, Guillaume Flandin -% $Id: spm_ROI.m 3465 2009-10-14 15:14:29Z guillaume $ +% $Id: spm_ROI.m 3960 2010-06-30 17:41:24Z ged $ if nargin < 2 && nargout > 1 error('Too many output arguments.'); @@ -31,7 +34,7 @@ def = {'sphere','box','cluster','mask'}; if isfield(xY,'rej') if ~isfield(xY,'M') - xY.rej = {xY.rej 'cluster'}; + xY.rej = {xY.rej{:} 'cluster'}; end else if isfield(xY,'M') @@ -84,9 +87,7 @@ xY.spec = spm_vol(xY.spec); end end - str = strrep(spm_str_manip(xY.spec.fname,'a30'),'\','\\'); - str = strrep(str,'^','\^'); str = strrep(str,'_','\_'); - str = strrep(str,'{','\{'); str = strrep(str,'}','\}'); + str = spm_str_manip(xY.spec.fname,'a30x'); xY.str = sprintf('image mask: %s',str); case 'cluster' @@ -102,6 +103,10 @@ xY.spec = []; xY.str = sprintf('cluster (seed voxel: %0.1f %0.1f %0.1f)',xY.xyz); + case 'all' + %---------------------------------------------------------------------- + xY.str = 'all'; + otherwise %---------------------------------------------------------------------- error('Unknown VOI type.'); @@ -112,6 +117,27 @@ %-'Estimate' ROI %========================================================================== + +%-Argument check +%-------------------------------------------------------------------------- +if ischar(XYZmm) && isempty(XYZmm) + XYZmm = spm_select(1,'image','Specify Image'); +end +if ischar(XYZmm), XYZmm = spm_vol(XYZmm); end +if isa(XYZmm,'nifti') + XYZmm = struct('dim',size(XYZmm.dat), 'mat',XYZmm.mat); +end +if isstruct(XYZmm) % spm_vol + [R,C,P] = ndgrid(1:XYZmm.dim(1),1:XYZmm.dim(2),1:XYZmm.dim(3)); + RCP = [R(:)';C(:)';P(:)']; + clear R C P + RCP(4,:) = 1; + XYZmm = XYZmm.mat(1:3,:)*RCP; +end +if isempty(XYZmm), XYZmm = zeros(3,0); end + +%-Filter location of voxels +%-------------------------------------------------------------------------- Q = ones(1,size(XYZmm,2)); switch lower(xY.def) @@ -136,6 +162,14 @@ A = spm_clusters(XYZ); j = find(A == A(i)); + case 'all' + %---------------------------------------------------------------------- + j = 1:size(XYZmm,2); + + otherwise + %---------------------------------------------------------------------- + error('Unknown VOI type.'); + end XYZmm = XYZmm(:,j); diff --git a/spm_VOI.m b/spm_VOI.m index e341321..551c4c8 100644 --- a/spm_VOI.m +++ b/spm_VOI.m @@ -54,7 +54,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_VOI.m 3450 2009-10-08 16:11:13Z guillaume $ +% $Id: spm_VOI.m 3950 2010-06-28 10:44:02Z guillaume $ %-Parse arguments @@ -112,9 +112,7 @@ %---------------------------------------------------------------------- Msk = spm_select(1,'image','Image defining search volume'); D = spm_vol(Msk); - str = strrep(spm_str_manip(Msk,'a30'),'\','\\'); - str = strrep(str,'^','\^'); str = strrep(str,'_','\_'); - str = strrep(str,'{','\{'); str = strrep(str,'}','\}'); + str = spm_str_manip(Msk,'a30x'); str = sprintf('image mask: %s',str); VOX = sqrt(sum(D.mat(1:3,1:3).^2)); FWHM = FWHM.*(xSPM.VOX./VOX); diff --git a/spm_ancova.m b/spm_ancova.m index 71eb40b..5d7285f 100644 --- a/spm_ancova.m +++ b/spm_ancova.m @@ -25,9 +25,13 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_ancova.m 1143 2008-02-07 19:33:33Z spm $ - +% $Id: spm_ancova.m 3696 2010-01-22 14:22:31Z karl $ +% assume V = I (i.i.d.) if empty +%-------------------------------------------------------------------------- +if isempty(V) + V = speye(size(Y,1)); +end % create design matrix structure if necessary %-------------------------------------------------------------------------- diff --git a/spm_api_bmc.m b/spm_api_bmc.m index 17d0f07..143d6d1 100644 --- a/spm_api_bmc.m +++ b/spm_api_bmc.m @@ -15,9 +15,9 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_api_bmc.m 3636 2009-12-11 14:31:26Z maria $ +% $Id: spm_api_bmc.m 3899 2010-05-25 15:36:40Z guillaume $ -if isempty(xp) +if ~exist('xp','var') | isempty(xp) inf_method = 'FFX'; else inf_method = 'RFX'; @@ -31,8 +31,8 @@ nm = length(N); -Fgraph = spm_figure('GetWin','Graphics','BMS: results'); -clf(Fgraph); +Fgraph = spm_figure('GetWin','Graphics'); +spm_clf(Fgraph); switch inf_method @@ -81,7 +81,7 @@ %-Display results - families %-------------------------------------------------------------- - F = spm_figure('CreateWin','Graphics','BMS: results'); + F = spm_figure('Create','Graphics','BMS: results'); figure(F); Nfam = length(family.post); @@ -119,6 +119,7 @@ %====================================================================== case ('RFX') + figure(Fgraph); %-Display results %------------------------------------------------------------------ @@ -148,11 +149,11 @@ %-Display results - families %-------------------------------------------------------------- - F = spm_figure('CreateWin','Graphics','BMS: results'); + F = spm_figure('Create','Graphics','BMS: results'); figure(F); %-Display results - families - %------------------------------------------------------------------ + %-------------------------------------------------------------- subplot(2,1,1) Nfam = length(family.exp_r); bar(1:Nfam,family.exp_r) @@ -176,8 +177,5 @@ out = []; - end - + end end - - diff --git a/spm_api_fmri.m b/spm_api_fmri.m deleted file mode 100644 index 9bd7dbe..0000000 --- a/spm_api_fmri.m +++ /dev/null @@ -1,535 +0,0 @@ -function varargout = spm_api_fmri(varargin) -% API for SPM.mat {fMRI} -% FORMAT spm_api_fmri(action,....) -%____________________________________________________________________________ -% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging - -% Karl Friston -% $Id: spm_api_fmri.m 1358 2008-04-10 11:20:26Z guillaume $ - - -% set action -%---------------------------------------------------------------------------- -global study -try - action = varargin{1}; -catch - action = 'initialise'; -end - -switch action - -% open level 1 figure: spm_api_fmri('initialise') -%---------------------------------------------------------------------------- -case {'initialise'} - - spm('defaults','FMRI'); - study = openfig('spm_study'); - global study - h = guihandles(study); - set(h.swd,'String',pwd); - -% delete subordinate figures: spm_api_fmri('delete',handle) -%---------------------------------------------------------------------------- -case {'delete'} - - switch lower(get(varargin{2},'Tag')) - - case {'session','trial','parameter'} - - spm_api_fmri('quit',varargin{2}); - - otherwise - - % remove from list and branch - %-------------------------------------------------------------------- - try - h = guihandles(varargin{2}); - i = get(h.branch,'Value'); - P = get(h.branch,'String'); - P(i) = []; - set(h.branch,'String',P) - set(h.branch,'Value',1) - branch = getappdata(h.branch,'branch'); - spm_api_fmri('delete',branch(i)) - branch(i) = []; - setappdata(h.branch,'branch',branch) - end - end - -% create a new figure: spm_api_fmri('new',handle,value) -%---------------------------------------------------------------------------- -case {'new'} - - % get level - %------------------------------------------------------------------------ - level = get(varargin{2},'Tag'); - h = guihandles(varargin{2}); - - switch level - - % new session - %------------------------------------------------------------------------ - case {'study'} - - P = get(h.branch,'String'); - P{end + 1} = sprintf('session %i',length(P) + 1); - set(h.branch,'String',P) - fig = openfig('spm_session'); - set(fig,'name',P{end}); - branch = getappdata(h.branch,'branch'); - branch(end + 1) = fig; - setappdata(h.branch,'branch',branch); - - % new trial - %------------------------------------------------------------------------ - case {'session'} - - P = get(h.branch,'String'); - P{end + 1} = sprintf('trial %i',length(P) + 1); - set(h.branch,'String',P) - fig = openfig('spm_trial'); - set(fig,'name',P{end}); - branch = getappdata(h.branch,'branch'); - branch(end + 1) = fig; - setappdata(h.branch,'branch',branch); - - % new parameter - %------------------------------------------------------------------------ - case {'trial'} - - P = get(h.branch,'String'); - P{end + 1} = sprintf('parameter %i',length(P) + 1); - set(h.branch,'String',P) - fig = openfig('spm_parameter'); - set(fig,'name',P{end}); - branch = getappdata(h.branch,'branch'); - branch(end + 1) = fig; - setappdata(h.branch,'branch',branch); - hp = guihandles(fig); - set(hp.P,'Userdata',get(h.ons,'Userdata')); - spm_api_fmri('P',hp.P) - - end - -% set values of SPM into figure: spm_api_fmri('set',handle,value) -%---------------------------------------------------------------------------- -case {'set'} - - level = get(varargin{2},'Tag'); - h = guihandles(varargin{2}); - - switch level - - % level 1 - set entire study - %--------------------------------------------------------------------- - case {'study'} - - SPM = varargin{3}; - try, set(h.name, 'String', SPM.name), end - try, set(h.study,'Name', SPM.name), end - try, set(h.SPMid,'String', SPM.SPMid),end - - % set level 1 values - %--------------------------------------------------------------------- - set(h.RT, 'String', sprintf('%.2f',SPM.xY.RT)) - set(h.RT, 'UserData',SPM.xY.RT) - set(h.iGXcalc,'Value', ~strcmp(lower(SPM.xGX.iGXcalc),'none')) - set(h.form, 'Value', ~strcmp(lower(SPM.xVi.form),'none')) - set(h.HParam, 'Value', isfinite(SPM.xX.K(1).HParam)) - - set(h.UNITS, 'Value', strcmp(SPM.xBF.UNITS,'secs') + 1) - set(h.bf_name, 'Value', SPM.xBF.order) - set(h.order, 'Value', SPM.xBF.order) - set(h.length, 'Value', fix(SPM.xBF.length/4)) - set(h.Volterra,'Value', SPM.xBF.Volterra - 1) - - % set level subordinate levels - %--------------------------------------------------------------------- - for i = 1:length(SPM.Sess) - try - name{i} = SPM.Sess(i).name; - catch - name{i} = sprintf('session %i',i); - end - - % open, name and set children - %----------------------------------------------------------------- - fig(i) = openfig('spm_session'); - set(fig(i),'Name',name{i}) - spm_api_fmri('set',fig(i),SPM.Sess(i),SPM.xY.P(SPM.Sess(i).row,:)) - end - - % save handles of children in branch - %--------------------------------------------------------------------- - branch = getappdata(h.branch,'branch'); - branch = [branch fig]; - setappdata(h.branch,'branch',branch) - P = get(h.branch,'String'); - if ~length(P), P = {}; end - P = {P{:}; name{:}}; - set(h.branch,'String',P) - - case {'session'} - - % set level 2 data (filenames) - %--------------------------------------------------------------------- - Sess = varargin{3}; - P = varargin{4}; - set(h.P,'String', P) - set(h.n,'String', num2str(size(P,1))) - - % covariates - %--------------------------------------------------------------------- - C = []; - Cname = {}; - for i = 1:length(Sess.C) - C = [C Sess.C(i).C]; - Cname = {Cname{:} Sess.C(i).name{:}}; - end - - set(h.C, 'UserData', C) - set(h.Cname,'String', Cname) - spm_api_fmri('C',h.P) - - % set subordinate levels - trials - %--------------------------------------------------------------------- - for i = 1:length(Sess.U) - try - name(i) = Sess.U(i).name; - catch - name{i} = sprintf('trial %i',i); - end - - % open, name and set children - %----------------------------------------------------------------- - branch(i) = openfig('spm_trial'); - set(branch(i),'Name',name{i}) - spm_api_fmri('set',branch(i),Sess.U(i)) - end - - % save handles of children in branch - %--------------------------------------------------------------------- - setappdata(h.branch,'branch',branch) - set(h.branch,'String',name) - - case {'trial'} - - % set level 3 data - %--------------------------------------------------------------------- - U = varargin{3}; - set(h.ons,'UserData',U.ons); - set(h.ons,'String',sprintf('%0.2f ',U.ons)); - set(h.dur,'UserData',U.dur); - set(h.dur,'String',sprintf('%0.2f ',U.dur)); - spm_api_fmri('u',h.u) - - % subordinate levels - trials - %--------------------------------------------------------------------- - for i = 1:length(U.P) - - try - name{i} = U.P(i).name; - catch - name{i} = sprintf('parameter %i',i); - end - - % open, name and set children - %----------------------------------------------------------------- - branch(i) = openfig('spm_parameter'); - set(branch(i),'Name',name{i}) - spm_api_fmri('set',branch(i),U.P(i)) - end - - % save handles of children in branch - %--------------------------------------------------------------------- - setappdata(h.branch,'branch',branch) - set(h.branch,'String',name) - - case {'parameter'} - - % set level 4 data - %--------------------------------------------------------------------- - P = varargin{3}; - try - set(h.P,'UserData',P.P) - catch - set(h.P,'UserData',[]) - end - try - set(h.h,'Value',P.h + 1) - catch - set(h.h,'Value',1) - end - spm_api_fmri('P',h.P) - if strcmp(get(h.parameter,'Name'),'none'), set(h.parameter,'Visible','off'),end - - end - -case {'C'} - - % get covariates - %--------------------------------------------------------------------- - h = guihandles(varargin{2}); - C = get(h.C,'UserData'); - axes(h.C);cla - - % image covariates - %--------------------------------------------------------------------- - n = size(C,2); - if n > 1 - imagesc(C) - colormap(gray) - end - if n == 1 - plot(C) - end - axis off - - % check names - %--------------------------------------------------------------------- - Cname = get(h.Cname,'String'); - m = length(Cname); - if m > n - Cname = Cname(1:n); - elseif m < n - for i = (m + 1):n - Cname{end + 1} = sprintf('cov %i',i); - end - end - set(h.Cname,'String',Cname) - -case {'P'} - - % get covariates - %--------------------------------------------------------------------- - h = guihandles(varargin{2}); - P = get(h.P,'UserData'); - P = P(:); - set(h.P,'UserData',P); - axes(h.P);cla - - % image covariates - %--------------------------------------------------------------------- - n = length(P); - if n > 1 - plot(P) - end - axis off - -case {'u'} - - % get stimulus function - %--------------------------------------------------------------------- - h = guihandles(varargin{2}); - axes(h.u);cla - ons = fix(get(h.ons,'Userdata')*16); - dur = fix(get(h.dur,'Userdata')*16); - ons = ons(:); - if ~length(dur), dur = 0; end - n = length(ons); - ons = ons - min(ons) + 1; - - if length(dur) < n - dur = sparse(1:n,1,dur(1),n,1); - end - dur = dur(1:n); - m = ons(end) + dur(end) + 16; - u = sparse(ons,1,1,m,1) - sparse(ons + dur + 1,1,1,m,1); - u = cumsum(u); - plot(full(u)) - axis off - - % number of trails - %------------------------------------------------------------------------ - str = sprintf('%i onsets',n); - set(h.n,'String',str) - -% set values of SPM into figure: spm_api_fmri('get') -%---------------------------------------------------------------------------- -case {'get'} - - global study - h = guihandles(study); - SPM.name = get(h.study,'name'); - - SPM.SPMid = get(h.SPMid,'String'); - SPM.swd = get(h.swd,'String'); - SPM.xY.RT = get(h.RT, 'Userdata'); - SPM.xGX.iGXcalc = {'none'}; - SPM.xVi.form = 'none'; - SPM.xX.K.HParam = Inf; - if get(h.iGXcalc,'Value'), SPM.xGX.iGXcalc = {'Scaling'}; end - if get(h.form, 'Value'), SPM.xVi.form = 'AR(1)'; end - if get(h.HParam, 'Value'), SPM.xX.K.HParam = 128; end - str = get(h.UNITS, 'String'); - SPM.xBF.UNITS = str{get(h.UNITS, 'Value')}; - str = get(h.bf_name, 'String'); - SPM.xBF.name = str{get(h.bf_name,'Value')}; - SPM.xBF.Volterra = get(h.Volterra, 'Value') + 1; - SPM.xBF.order = get(h.order, 'Value'); - SPM.xBF.length = get(h.length, 'Value')*4; - - % get handles of children in branch (sessions) - %------------------------------------------------------------------------- - hsession = getappdata(h.branch,'branch'); - for s = 1:length(hsession) - - h = guihandles(hsession(s)); - SPM.Sess(s).name = get(h.session,'name'); - - P = get(h.P,'String'); - C = get(h.C,'UserData'); - Cname = get(h.Cname,'String'); - nscan = length(P); - - try - for i = 1:size(P,1) - c{i,1} = P(i,:); - end - P = c; - end - - if size(C,1) ~= length(P) & size(C,1) - figure(hsession(s)) - warndlg('check number of filenames and covariates') - return - end - - - % filemames - %--------------------------------------------------------------------- - try - SPM.xY.P = cat(1,SPM.xY.P,P); - SPM.nscan = [SPM.nscan nscan]; - catch - SPM.xY.P = P; - SPM.nscan = nscan; - end - - % covariates - %--------------------------------------------------------------------- - SPM.Sess(s).C.C = C; - SPM.Sess(s).C.name = Cname; - - % get handles of children in branch (trials) - %--------------------------------------------------------------------- - htrial = getappdata(h.branch,'branch'); - for t = 1:length(htrial) - h = guihandles(htrial(t)); - SPM.Sess(s).U(t).name = {get(h.trial,'name')}; - ons = get(h.ons,'Userdata'); - dur = get(h.dur,'Userdata'); - - if length(dur) ~= 1 & length(dur) ~= length(ons) - figure(htrial(t)) - warndlg('please check durations') - return - end - - % set onsets and durations - %----------------------------------------------------------------- - SPM.Sess(s).U(t).ons = ons(:); - SPM.Sess(s).U(t).dur = dur(:); - - % get handles of children in branch (parameters) - %----------------------------------------------------------------- - hparam = getappdata(h.branch,'branch'); - if length(hparam) - for p = 1:length(hparam) - h = guihandles(hparam(p)); - SPM.Sess(s).U(t).P(p).name = get(h.parameter,'name'); - P = get(h.P,'Userdata'); - - if length(P) & (length(P) ~= length(SPM.Sess(s).U(t).ons)) - figure(hparam(p)) - warndlg('please check parameter vector') - return - end - - SPM.Sess(s).U(t).P(p).P = P; - SPM.Sess(s).U(t).P(p).h = get(h.h,'Value') - 1; - end - else - SPM.Sess(s).U(t).P.name = 'none'; - SPM.Sess(s).U(t).P.P = []; - SPM.Sess(s).U(t).P.h = 0; - end - end - end - - % assign output argument - %------------------------------------------------------------------------ - try - SPM.xY.P = strvcat(SPM.xY.P); - end - varargout{1} = spm_fMRI_design(SPM); - - -% delete figure and children: spm_api_fmri('quit',handle) -%---------------------------------------------------------------------------- -case {'quit'} - - f = varargin{2}; - h = guihandles(f); - try - b = getappdata(h.branch,'branch'); - catch - b = []; - end - for i = 1:length(b) - spm_api_fmri('quit',b(i)) - end - delete(f) - -% re-set names: spm_api_fmri('refresh',handle) -%---------------------------------------------------------------------------- -case {'refresh'} - - try - f = varargin{2}; - catch - global study, f = study; - end - - h = guihandles(f); - try - b = getappdata(h.branch,'branch'); - catch - return - end - name = {}; - for i = 1:length(b) - name{i} = get(b(i),'Name'); - spm_api_fmri('refresh',b(i)) - end - set(h.branch,'String',name) - -% load a variable: x = spm_api_fmri('load') -%---------------------------------------------------------------------------- -case {'load'} - - f = spm_select(1,'.*t$','select MAT or text file'); - try - x = load(f,'-ascii'); - catch - x = load(f,'-mat'); - s = fieldnames(x); - x = getfield(x,s{1}); - end - varargout{1} = x; - -% evalue string and place in UserData -%---------------------------------------------------------------------------- -case {'eval'} - - h = varargin{2}; - str = get(h,'String'); - try, x = eval(['[' str ']']); end - try, x = eval(['[' str{:} ']']); end - try - set(h,'UserData',x) - set(h,'String',sprintf('%.2f ',x)); - end - -end diff --git a/spm_bias_apply.m b/spm_bias_apply.m index 22fee18..d0c5d15 100644 --- a/spm_bias_apply.m +++ b/spm_bias_apply.m @@ -13,7 +13,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % John Ashburner -% $Id: spm_bias_apply.m 1143 2008-02-07 19:33:33Z spm $ +% $Id: spm_bias_apply.m 3756 2010-03-05 18:43:37Z guillaume $ if ischar(V), @@ -34,7 +34,7 @@ VO.dt = [spm_type('float32') spm_platform('bigend')]; if nargout==0, - [pth,nm,xt,vr] = fileparts(deblank(V.fname)); + [pth,nm,xt,vr] = spm_fileparts(deblank(V.fname)); VO.fname = fullfile(pth,['m' nm xt vr]); %VO.fname = ['m' nm xt vr]; VO.pinfo = [1 0 0]'; diff --git a/spm_bias_ui.m b/spm_bias_ui.m index e8c2ea9..2570999 100644 --- a/spm_bias_ui.m +++ b/spm_bias_ui.m @@ -65,7 +65,7 @@ function spm_bias_ui(P) % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % John Ashburner -% $Id: spm_bias_ui.m 1143 2008-02-07 19:33:33Z spm $ +% $Id: spm_bias_ui.m 3756 2010-03-05 18:43:37Z guillaume $ global defaults @@ -81,7 +81,7 @@ function spm_bias_ui(P) %======================================================================= function bias_ui(flags) % User interface for nonuniformity correction -spm('FnBanner',mfilename,'$Rev: 1143 $'); +spm('FnBanner',mfilename,'$Rev: 3756 $'); [Finter,unused,CmdLine] = spm('FnUIsetup','Flatten'); spm_help('!ContextHelp',mfilename); PP = spm_select(Inf, 'image', 'Scans to correct'); @@ -91,7 +91,7 @@ function bias_ui(flags) drawnow; P = deblank(PP(i,:)); T = spm_bias_estimate(P,flags); - [pth,nm,xt,vr] = fileparts(P); + [pth,nm,xt,vr] = spm_fileparts(P); S = fullfile(pth,['bias_' nm '.mat']); %S = ['bias_' nm '.mat']; spm_bias_apply(P,S); diff --git a/spm_bireduce.m b/spm_bireduce.m index 9323423..00c9482 100644 --- a/spm_bireduce.m +++ b/spm_bireduce.m @@ -4,9 +4,9 @@ % % M - model specification structure % Required fields: -% M.f - dx/dt = f(x,u,P,M) {function string or m-file} -% M.g - y(t) = l(x,u,P,M) {function string or m-file} -% M.bi - bilinear form [M0,M1,L1,L2] = bi(M,P) {function string or m-file} +% M.f - dx/dt = f(x,u,P,M) {function string or m-file} +% M.g - y(t) = g(x,u,P,M) {function string or m-file} +% M.bi - bilinear form [M0,M1,L1,L2] = bi(M,P) {function string or m-file} % M.m - m inputs % M.n - n states % M.l - l outputs @@ -36,7 +36,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_bireduce.m 3517 2009-10-29 15:11:56Z guillaume $ +% $Id: spm_bireduce.m 3696 2010-01-22 14:22:31Z karl $ % set up @@ -58,16 +58,6 @@ funx = fcnchk(M.f,'x','u','P','M'); end -% add observer if not specified -%-------------------------------------------------------------------------- -try - funl = fcnchk(M.g,'x','u','P','M'); -catch - M.g = inline('spm_vec(x)','x','u','P','M'); - M.l = M.n; - funl = fcnchk(M.g,'x','u','P','M'); -end - % expansion pointt %-------------------------------------------------------------------------- x = M.x; @@ -77,18 +67,14 @@ u = sparse(M.m,1); end - % Partial derivatives for 1st order Bilinear operators %========================================================================== -% l(x(0),0) -%-------------------------------------------------------------------------- -l0 = spm_vec(feval(funl,x,u,P,M)); - % f(x(0),0) and derivatives %-------------------------------------------------------------------------- [dfdxu dfdx] = spm_diff(funx,x,u,P,M,[1 2]); [dfdu f0] = spm_diff(funx,x,u,P,M,2); +f0 = spm_vec(f0); % delay operator %-------------------------------------------------------------------------- @@ -98,11 +84,8 @@ for i = length(dfdxu) dfdxu{i} = Q*dfdxu{i}; end - m = length(dfdxu); % m inputs n = length(f0); % n states -l = length(l0); % l ouputs - % Bilinear operators %========================================================================== @@ -121,19 +104,39 @@ if nargout < 3, return, end + +% Output operators +%========================================================================== + +% add observer if not specified +%-------------------------------------------------------------------------- +try + fung = fcnchk(M.g,'x','u','P','M'); +catch + M.g = inline('spm_vec(x)','x','u','P','M'); + M.l = M.n; + fung = fcnchk(M.g,'x','u','P','M'); +end + +% g(x(0),0) +%-------------------------------------------------------------------------- +[dgdx g0] = spm_diff(fung,x,u,P,M,1); +g0 = spm_vec(g0); +l = length(g0); + % Output matrices - L1 %-------------------------------------------------------------------------- -dldx = spm_diff(funl,x,u,P,M,1); -L1 = spm_cat({(l0 - dldx*spm_vec(x)), dldx}); +L1 = spm_cat({(spm_vec(g0) - dgdx*spm_vec(x)), dgdx}); + if nargout < 4, return, end % Output matrices - L2 %-------------------------------------------------------------------------- -dldxx = spm_diff(funl,x,u,P,M,[1 1]); +dgdxx = spm_diff(fung,x,u,P,M,[1 1]); for i = 1:l for j = 1:n - D{i}(j,:) = dldxx{j}(i,:); + D{i}(j,:) = dgdxx{j}(i,:); end end for i = 1:l diff --git a/spm_bwlabel.m b/spm_bwlabel.m index 9f868a1..9b6ad87 100644 --- a/spm_bwlabel.m +++ b/spm_bwlabel.m @@ -21,7 +21,7 @@ % NUM : Number of connected components in L. % % -% The implementation is not recursive (i.e. will no crash for +% The implementation is not recursive (i.e. will not crash for % large connected components) and is losely based on % Thurfjell et al. 1992, A new three-dimensional connected % components labeling algorithm with simultaneous object @@ -31,7 +31,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Jesper Andersson -% $Id: spm_bwlabel.m 2696 2009-02-05 20:29:48Z guillaume $ +% $Id: spm_bwlabel.m 3822 2010-04-16 18:43:08Z karl $ %-This is merely the help file for the compiled routine error('spm_bwlabel.c not compiled - see Makefile'); diff --git a/spm_cell_swap.m b/spm_cell_swap.m index 9a3bb0b..5eb8def 100644 --- a/spm_cell_swap.m +++ b/spm_cell_swap.m @@ -6,7 +6,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_cell_swap.m 1172 2008-02-27 20:14:47Z karl $ +% $Id: spm_cell_swap.m 3703 2010-02-01 20:47:44Z karl $ % return if empty %-------------------------------------------------------------------------- @@ -20,10 +20,10 @@ [m n] = size(x{1}); [k l] = size(x); y = cell(k,n); -[y{:}] = deal(sparse(m,l)); -for r = 1:k +[y{:}] = deal(zeros(m,l)); +for r = 1:k for j = 1:l - for i = 1:n + for i = 1:n y{r,i}(:,j) = x{r,j}(:,i); end end diff --git a/spm_check_filename.m b/spm_check_filename.m index 51289fc..00e3656 100644 --- a/spm_check_filename.m +++ b/spm_check_filename.m @@ -7,7 +7,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_check_filename.m 2976 2009-03-26 22:07:06Z guillaume $ +% $Id: spm_check_filename.m 3934 2010-06-17 14:58:25Z guillaume $ if isdeployed, return; end @@ -70,7 +70,7 @@ try % get relative path (directory and filename) and find in children %------------------------------------------------------------------ - j = findstr(V(i).fname,filesep); + j = strfind(V(i).fname,filesep); fname = which(fname(j(end - 1):end)); if ~isempty(fname) V(i).fname = fname; diff --git a/spm_check_installation.m b/spm_check_installation.m index 9691c7a..531584b 100644 --- a/spm_check_installation.m +++ b/spm_check_installation.m @@ -13,7 +13,7 @@ function spm_check_installation(action) % Copyright (C) 2009 Wellcome Trust Centre for Neuroimaging % Guillaume Flandin -% $Id: spm_check_installation.m 3662 2010-01-05 17:58:31Z guillaume $ +% $Id: spm_check_installation.m 3913 2010-06-02 15:25:23Z guillaume $ if isdeployed, return; end @@ -56,7 +56,8 @@ function spm_check_installation(action) %-Check the search path %-------------------------------------------------------------------------- -if ~ismember(lower(d),lower(strread(path,'%s','delimiter',pathsep))) +p = textscan(path,'%s','delimiter',pathsep); p = p{1}; +if ~ismember(lower(d),lower(p)) error(sprintf([... 'You do not appear to have the MATLAB search path set up\n'... 'to include your SPM8 distribution. This means that you\n'... @@ -139,6 +140,7 @@ function spm_check_installation(action) %-Say Hello %-------------------------------------------------------------------------- +fprintf('\n'); disp( ' ___ ____ __ __ ' ); disp( '/ __)( _ \( \/ ) ' ); disp( '\__ \ )___/ ) ( Statistical Parametric Mapping ' ); @@ -175,7 +177,7 @@ function spm_check_installation(action) l1 = fgetl(fid); l2 = fgetl(fid); fclose(fid); l1 = strtrim(l1(2:end)); l2 = strtrim(l2(2:end)); - t = strread(l2,'%s','delimiter',' '); + t = textscan(l2,'%s','delimiter',' '); t = t{1}; v.Name = l1; v.Date = t{4}; v.Version = t{2}; v.Release = t{3}(2:end-1); catch @@ -245,7 +247,7 @@ function spm_check_installation(action) %-Detect Java %-------------------------------------------------------------------------- -fprintf('%s\n', char(strread(version('-java'),'%s',1,'delimiter','\n'))); +fprintf('%s\n', version('-java')); fprintf('Java support: '); level = {'jvm', 'awt', 'swing', 'desktop'}; for i=1:numel(level) @@ -512,7 +514,7 @@ function compare_versions(l,r) % FUNCTION extract_info %========================================================================== function svnprops = extract_info(f) -%Extract Subversion properties ($Id: spm_check_installation.m 3662 2010-01-05 17:58:31Z guillaume $ tag) +%Extract Subversion properties ($Id: spm_check_installation.m 3913 2010-06-02 15:25:23Z guillaume $ tag) svnprops = struct('file',f, 'id',[], 'date','', 'md5',''); diff --git a/spm_clf.m b/spm_clf.m index e0ebb60..5551a3a 100644 --- a/spm_clf.m +++ b/spm_clf.m @@ -2,11 +2,10 @@ function spm_clf(F) % Clear specified figure of objects with visible handles % FORMAT spm_clf(F) % F - Figure number, or 'Tag' string of figure(s) to clear -%___________________________________________________________________________ +%__________________________________________________________________________ % % Clears the specified figure, deleting all objects with visible -% handles. ('HandleVisibility'=='on'). This is the same as MatLab5's -% clf, except that the figure can be specified. +% handles ('HandleVisibility'=='on'). % % If the current window is 'Tag'ged interactive, then the figures name % is cleared and the pointer reset. @@ -18,11 +17,11 @@ function spm_clf(F) % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Andrew Holmes -% $Id: spm_clf.m 1143 2008-02-07 19:33:33Z spm $ +% $Id: spm_clf.m 3899 2010-05-25 15:36:40Z guillaume $ %-Call spm_figure -%--------------------------------------------------------------------------- +%-------------------------------------------------------------------------- if nargin==0 spm_figure('Clear') else diff --git a/spm_clusters.m b/spm_clusters.m index 9a1560d..47a6730 100644 --- a/spm_clusters.m +++ b/spm_clusters.m @@ -14,7 +14,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Jesper Andersson -% $Id: spm_clusters.m 3630 2009-12-10 16:51:08Z guillaume $ +% $Id: spm_clusters.m 3822 2010-04-16 18:43:08Z karl $ if isempty(L), A = []; return; end @@ -22,9 +22,9 @@ % Turn location list to binary 3D volume %-------------------------------------------------------------------------- -dim = [max(L(1,:)) max(L(2,:)) max(L(3,:))]; -vol = zeros(dim(1),dim(2),dim(3)); -indx = sub2ind(dim,L(1,:)',L(2,:)',L(3,:)'); +dim = [max(L(1,:)) max(L(2,:)) max(L(3,:))]; +vol = zeros(dim(1),dim(2),dim(3)); +indx = sub2ind(dim,L(1,:)',L(2,:)',L(3,:)'); vol(indx) = 1; diff --git a/spm_compact_svd.m b/spm_compact_svd.m new file mode 100644 index 0000000..ebd1550 --- /dev/null +++ b/spm_compact_svd.m @@ -0,0 +1,51 @@ +function U = spm_compact_svd(Y,xyz,nu) +% local SVD with compact support for large matrices +% FORMAT U = spm_compact_svd(Y,xyz,nu) +% Y - matrix +% xyz - location +% nu - number of vectors +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: spm_compact_svd.m 3743 2010-03-02 18:59:21Z karl $ + + +% get orders +%-------------------------------------------------------------------------- +ns = size(Y,1); % number of samples +nv = size(Y,2); % number of components (voxels/vertices) + +% get kernel (compact vectors) +%------------------------------------------------------------------ +nc = max(fix(nv/nu),1); % voxels in compact support +C = sum(Y.^2); % variance of Y +U = spalloc(nv,nu,nc*nu); +J = 1:nv; +for i = 1:nu + + % find maximum variance voxel + %-------------------------------------------------------------- + [v j] = max(C); + d = 0; + for k = 1:size(xyz,1) + d = d + (xyz(k,:) - xyz(k,j)).^2; + end + [d j] = sort(d); + try + j = j(1:nc); + end + + % save principal eigenvector + %-------------------------------------------------------------- + k = J(j); + u = spm_svd(Y(:,k)'); + U(k,i) = u(:,1); + + % remove compact support voxels and start again + %-------------------------------------------------------------- + J(j) = []; + C(j) = []; + xyz(:,j) = []; + +end diff --git a/spm_con.man b/spm_con.man new file mode 100644 index 0000000..51980f0 --- /dev/null +++ b/spm_con.man @@ -0,0 +1,335 @@ +%======================================================================= +% C o n t r a s t s +%======================================================================= +% +% For general linear model Y = XB + E with data Y, desgin matrix X, +% parameter vector B, and (independent) errors E, a contrast is a +% linear combination of the parameters c'B. Usually c is a column +% vector, defining a simple contrast of the parameters, assessed via an +% SPM{T}. More generally, c can be a matrix (a linear constraining +% matrix), defining an "F-contrast" assessed via an SPM{F}. +% +% The vector/matrix c contains the contrast weights. It is this +% contrast weights vector/matrix that must be specified to define the +% contrast. The null hypothesis is that the linear combination c'B is +% zero. The order of the parameters in the parameter (column) vector B, +% and hence the order to which parameters are referenced in the +% contrast weights vector c, is determined by the construction of the +% design matrix. +% +% There are two types of contrast in SPM: simple contrasts for SPM{T}, +% and "F-contrasts" for SPM{F}. +% +% For a thorough theoretical treatment, see the SPM course notes (Ch3) +% and the statistical literature referenced therein. +% +%_______________________________________________________________________ +% Contrasts: Simple one-dimensional contrasts for an SPM{T} +% +% A simple contrast for an SPM{T} tests the null hypothesis c'B=0 +% against the one-sided alternative c'B>0, where c is a column vector. +% +% ( Note that throughout SPM, the transpose of the contrast weights is ) +% ( used for display and input. That is, you'll enter and visualise c'. ) +% ( For an SPM{T} this will be a row vector. ) +% +% For example, if you have a design in which the first two columns of +% the design matrix correspond to the effects for "baseline" and +% "active" conditions respectively, then a contrast with weights +% c'=[-1,+1,0,...] (with zero weights for any other parameters) tests +% the hypothesis that there is no "activation" (the parameters for both +% conditions are the same), against the alternative that there is some +% activation (i.e. the parameter for the "active" condition is greater +% than that for the "baseline" condition). The resulting SPM{T} +% (created by spm_getSPM.m) is a statistic image, with voxel values the +% value of the t-statistic for the specified contrast at that location. +% Areas of the SPM{T} with high voxel values indicate evidence for +% "activation". To look for areas of relative "de-activation", the +% inverse contrast could be used c'=[+1,-1,0,...]. +% +% Similarly, if you have a design where the third column in the design +% matrix is a covariate, then the corresponding parameter is +% essentially a regression slope, and a contrast with weights +% c'=[0,0,1,0,...] (with zero weights for all parameters but the third) +% tests the hypothesis of zero regression slope, against the +% alternative of a positive slope. This is equivalent to a test no +% correlation, against the alternative of positive correlation. If +% there are other terms in the model beyond a constant term and the +% covariate, then this correlation is apartial correlation, the +% correlation between the data Y and the covariate, after accounting +% for the other effects. +% +%_______________________________________________________________________ +% Contrasts: Linear constraining matrices for an SPM{F} +% +% The null hypothesis c'B=0 can be thought of as a (linear) constraint +% on the full model under consideration, yielding a reduced model. +% Taken from the viewpoint of two designs, with the full model an +% extension of the reduced model, the null hypothesis is that the +% additional terms in the full model are redundent. +% +% Statistical inference proceeds by comparing the additional variance +% explained by full design over and above the reduced design to the +% error variance (of the full design), an "Extra Sum-of-Squares" +% approach yielding an F-statistic for each voxel, whence an SPM{F}. +% +% This is useful in a number of situations : +% +% ---------------- +% +% 1: Two sided tests +% +% The simplest use of F-contrasts is to effect a two-sided test of a +% simple linear contrast c'B, where c is a column vector. The SPM{F} is +% the square of the corresponding SPM{T}. High values of the SPM{F} +% therefore indicate evidence against the null hypothesis c'B=0 in +% favour of the two-sided alternative c'B~=0. +% +% ---------------- +% +% 2: General linear hypotheses +% +% Where the contrast weights is a matrix, the rows of the (transposed) +% contrast weights matrix c' must define contrasts in their own right, +% and the test is effectively simultaneously testing the null +% hypotheses associated with the individual component contrasts with +% weights defined in the rows. The null hypothesis is still c'B=0, but +% since c is a matrix, 0 here is a zero vector rather than a scalar +% zero, asserting that under the null hypothesis all the component +% hypotheses are true. +% +% For example: Suppose you have a language study with 3 word categories +% (A,B & C), and would like to test whether there is any difference +% at all between the three levels of the "word category" factor. +% +% The design matrix might look something like: +% +% [ 1 0 0 ..] +% [ : : : ..] +% [ 1 0 0 ..] +% [ 0 1 0 ..] +% X = [ : : : ..] +% [ 0 1 0 ..] +% [ 0 0 1 ..] +% [ : : : ..] +% [ 0 0 1 ..] +% [ 0 0 0 ..] +% [ : : : ..] +% +% ...with the three levels of the "word category" factor modelled in the +% first three columns of the design matrix +% +% The matrix of contrast weights will look like: +% +% c' = [1 -1 0 ...; +% 0 1 -1 ...] +% +% Reading the contrasts weights in each row of c', we see that row 1 +% states that category A elicits the same response as category B, row 2 +% that category B elicits the same response as category C, and hence +% together than categories A, B & C all elicit the same response. +% +% The alternative hypothesis is simply that the three levels are not +% all the same, i.e. that there is some difference in the paraeters for +% the three levels of the factor: The first and the second categories +% produce different brain responses, OR the second and third +% categories, or both. +% +% In other words, under the null hypothesis (the categories produce the +% same brain responses), the model reduces to one in which the three +% level "word category" factor can be replaced by a single "word" +% effect, since there is no difference in the parameters for each +% category. The corresponding design matrix would have the first three +% columns replaced by a single column that is the sum (across rows) of +% the first three columns in the design matric above, modelling the +% brain response to a word, whatever is the category. The F-contrast +% above is in fact testing the hypothesis that this reduced design +% doesn't account for significantly less variance than the full design +% with an effect for each word category. +% +% Another way of seeing that, is to consider a reparameterisation of +% the model, where the first column models effects common to all three +% categories, with the second and third columns modelling the +% differences between the three conditions, for example: +% +% [ 1 1 0 ..] +% [ : : : ..] +% [ 1 1 0 ..] +% [ 1 0 1 ..] +% X = [ : : : ..] +% [ 1 0 1 ..] +% [ 1 -1 -1 ..] +% [ : : : ..] +% [ 1 -1 -1 ..] +% [ 0 0 0 ..] +% [ : : : ..] +% +% In this case, an equivalent F contrast is of the form +% c' = [ 0 1 0 ...; +% 0 0 1 ...] +% and would be exatly equivalent to the previous contrast applied to +% the previous design. In this latter formulation, you are asking +% whewher the two columns modelling the "interaction space" account for +% a significant amount of variation (variance) of the data. Here the +% coomponent contrasts in the rows of c' are simply specifying that the +% parameters for the corresponding rows are are zero, and it is clear +% that the F-test is comparing this full model with a reduced model in +% which the second and third columns of X are omitted. +% +% ( Note the difference between the following two F-contrasts: ) +% ( c' = [ 0 1 0 ...; (1) ) +% ( 0 0 1 ...] ) +% ( and ) +% ( c' = [ 0 1 1 ...] (2) ) +% ( ) +% ( The first is an F-contrast, testing whether either of the ) +% ( parameters for the effects modelled in the 2nd & 3rd columns of the ) +% ( design matrix are significantly different from zero. Under the null ) +% ( hypothesis c'B=0, the first contrast imposes a two-dimensional ) +% ( constraint on the design. The second contrast tests whether the SUM ) +% ( of the parameters for the 2nd & 3rd columns is significantly ) +% ( different from zero. Under the null hypothesis c'B=0, this second ) +% ( contrast only imposes a one dimensional constraint on the design. ) +% ( ) +% ( An example of the difference between the two is that the first ) +% ( contrast would be sensitive to the situation where the 2nd & 3rd ) +% ( parameters were +a and -a, for some constant a, wheras the second ) +% ( contrast would not detect this, since the parameters sum to zero. ) +% +% The test for an effect of the factor "word category" is an F-test +% with 3-1=2 "dimensions", or degrees of freedom. +% +% ---------------- +% +% 3: Testing the significance of effects modelled by multiple columns +% +% A conceptually similar situation arises when one wonders whether a +% set of confound effects are explaining any variance in the data. One +% important advantage of testing this with F contrasts rather than +% T contrasts is the following. Say you have two covariates +% that you would like to know whether they can "predict" the brain +% responses, and these two are correlated (even a small correlation +% would be important in this instance). Testing one and then the other +% may lead you to conclude that there is no effect. However, testing +% with an F test the two covariates may very well show a not suspected +% effect. This is because by testing one covariate after the other, one +% never tests for what is COMMON to these covariates (see Andrade et +% al, Ambiguous results in functional neuroimaging, NeuroImage, 1999). +% +%_______________________________________________________________________ +% +% More generally, F-tests reflect the usual analysis of variance, while +% t-tests are traditionally post hoc tests, useful to see in which +% direction is an effect going (positive or negative). The introduction +% of F-tests can also be viewed as a first means to do model selection. +% +%_______________________________________________________________________ +% +% Technically speaking, an F-contrast defines a number of directions +% (as many as the rank of the contrast) in the space spanned by the +% column vectors of the design matrix. These directions are simply +% given by X*c if the vectors of X are orthogonal, if not, the space +% define by c is a bit more complex and takes care of the correlation +% within the design matrix. In essence, an F-contrast is defining a +% reduced model by imposing some linear constraints (that have to be +% estimable, see below) on the parameters estimates. Sometimes, this +% reduced model is simply made of a subset of the column of the +% original design matrix but generally, it is defined by a combination +% of those columns. (see spm_FcUtil for what (I hope) is an efficient +% handling of F-contrats computation). +% +%_______________________________________________________________________ +% +% Contrasts: Non-orthogonal designs +% +% Note that parameters zero-weighted in the contrast are still included +% in the model. This is particularly important if the design is not +% orthogonal (i.e. the columns of the design matrix are not +% orthogonal). In effect, the significance of the contrast is assessed +% *after* accounting for the other effects in the design matrix. Thus, +% if two covariates are correlated, testing the significance of the +% parameter associated with one will only test for the part that is not +% present in the second covariate. This is a general point that is also +% true for F-contrasts. See Andrade et al, Ambiguous results in +% functional neuroimaging, NeuroImage, 1999, for a full description of +% the effect of non othogonal design testing. +% +%_______________________________________________________________________ +% Contrasts: Estimability +% +% The contrast c'B is estimated by c'b, where b are the parameter +% estimates given by b=pinv(X)*Y. +% +% However, if a design is rank-deficient (i.e. the columns of the +% design matrix are not linearly independent), then the parameters are +% not unique, and not all linear combinations of the parameter are +% valid contrasts, since contrasts must be uniquely estimable. +% +% A weights vector defines a valid contrast if and only if it can be +% constructed as a linear combination of the rows of the design matrix. +% That is c' (the transposed contrast vector - a row vector) is in the +% row-space of the design matrix. +% +% Usually, a valid contrast will have weights that sum to zero over the +% levels of a factor (such as condition). +% +% A simple example is a simple two condition design including a +% constant, with design matrix +% +% [ 1 0 1 ] +% [ : : : ] +% X = [ 1 0 1 ] +% [ 0 1 1 ] +% [ : : : ] +% [ 0 1 1 ] +% +% The first column corresponds to condition 1, the second to condition +% 2, and the third to a constant (mean) term. Although there are three +% columns to the design matrix, the design only has two degrees of +% freedom, since any one column can be derived from the other two (for +% instance, the third column is the sum of the first two). There is no +% unique set of parameters for this model, since for any set of +% parameters adding a constant to the two condition effects and +% subtracting it from the constant effect yields another set of viable +% parameters. However, the difference between the two condition effects +% is uniquely estimated, so c'=[-1,+1,0] does define a contrast. +% +% If a parameter is estimable, then the weights vector with a single +% "1" corresponding to that parameter (and zero's elsewhere) defines a +% valid contrast. +% +%_______________________________________________________________________ +% Contrasts: Multiple comparisons +% +% Note that SPM implements no corrections to account for you looking at +% multiple contrasts. +% +% If you are interested in a set of hypotheses that together define a +% consistent question, then you should account for this when assessing +% the individual contrasts. A simple Bonferroni approach would assess N +% simultaneouls contrasts at significance level alpha/N, where alpha is +% the chosen significance level (usually 0.05). +% +% For two sided t-tests using SPM{T}'s, the significance level should +% be halved. When considering both SPM{T}'s produced by a contrast and +% it's inverse (the contrast with negative weights), to effect a +% two-sided test to look for both "increases" and "decreases", you +% should review each SPM{T} at at level 0.05/2 rather than 0.05. (Or +% consider an F-contrast!) +% +%_______________________________________________________________________ +% Contrasts: Contrast images and ESS images +% +% For a simple contrast, SPM (spm_getSPM.m) writes a contrast image: +% con_????.{img,hdr}, with voxel values c'b. (The ???? in the image +% names are replaced with the contrast number.) These contrast images +% (for appropriate contrasts) are suitable summary images of an effect +% at this level, and can be used as input at a higher level when +% effecting a random effects analysis. See spm_RandFX.man for further +% details. +% +% For an F-contrast, SPM (spm_getSPM.m) writes the Extra Sum-of-Squares +% (the difference in the residual sums of squares for the full and +% reduced model) as ess_????.{img,hdr}. (Note that the +% ess_????.{img,hdr} and SPM{T,F}_????.{img,hdr} images are not +% suitable input for a higher level analysis.) diff --git a/spm_conman.m b/spm_conman.m index 1bd9d06..d07ea81 100644 --- a/spm_conman.m +++ b/spm_conman.m @@ -4,367 +4,25 @@ % - An embedded callback, multi-function function % - For detailed programmers comments, % see format specifications in main body of program (below user help) -%_______________________________________________________________________ -% -% The contrast manager is a user interface for the selection and -% definition of contrasts for a given SPM design. -% -% At present, the contrast manager provides only interactive GUI facilities. -% -% This help is divided into two sections. First, the fundamentals of -% contrasts are discussed, secondly, the contrast manager interface is -% described. -% -% See also: spm_getSPM.m (contrast evaluation) -% spm_RandFX.man (random effects analyses) -% -%======================================================================= -% C o n t r a s t s -%======================================================================= -% -% For general linear model Y = XB + E with data Y, desgin matrix X, -% parameter vector B, and (independent) errors E, a contrast is a -% linear combination of the parameters c'B. Usually c is a column -% vector, defining a simple contrast of the parameters, assessed via an -% SPM{T}. More generally, c can be a matrix (a linear constraining -% matrix), defining an "F-contrast" assessed via an SPM{F}. -% -% The vector/matrix c contains the contrast weights. It is this -% contrast weights vector/matrix that must be specified to define the -% contrast. The null hypothesis is that the linear combination c'B is -% zero. The order of the parameters in the parameter (column) vector B, -% and hence the order to which parameters are referenced in the -% contrast weights vector c, is determined by the construction of the -% design matrix. -% -% There are two types of contrast in SPM: simple contrasts for SPM{T}, -% and "F-contrasts" for SPM{F}. -% -% For a thorough theoretical treatment, see the SPM course notes (Ch3) -% and the statistical literature referenced therein. -% -%_______________________________________________________________________ -% Contrasts: Simple one-dimensional contrasts for an SPM{T} -% -% A simple contrast for an SPM{T} tests the null hypothesis c'B=0 -% against the one-sided alternative c'B>0, where c is a column vector. -% -% ( Note that throughout SPM, the transpose of the contrast weights is ) -% ( used for display and input. That is, you'll enter and visualise c'. ) -% ( For an SPM{T} this will be a row vector. ) -% -% For example, if you have a design in which the first two columns of -% the design matrix correspond to the effects for "baseline" and -% "active" conditions respectively, then a contrast with weights -% c'=[-1,+1,0,...] (with zero weights for any other parameters) tests -% the hypothesis that there is no "activation" (the parameters for both -% conditions are the same), against the alternative that there is some -% activation (i.e. the parameter for the "active" condition is greater -% than that for the "baseline" condition). The resulting SPM{T} -% (created by spm_getSPM.m) is a statistic image, with voxel values the -% value of the t-statistic for the specified contrast at that location. -% Areas of the SPM{T} with high voxel values indicate evidence for -% "activation". To look for areas of relative "de-activation", the -% inverse contrast could be used c'=[+1,-1,0,...]. -% -% Similarly, if you have a design where the third column in the design -% matrix is a covariate, then the corresponding parameter is -% essentially a regression slope, and a contrast with weights -% c'=[0,0,1,0,...] (with zero weights for all parameters but the third) -% tests the hypothesis of zero regression slope, against the -% alternative of a positive slope. This is equivalent to a test no -% correlation, against the alternative of positive correlation. If -% there are other terms in the model beyond a constant term and the -% covariate, then this correlation is apartial correlation, the -% correlation between the data Y and the covariate, after accounting -% for the other effects. -% -%_______________________________________________________________________ -% Contrasts: Linear constraining matrices for an SPM{F} -% -% The null hypothesis c'B=0 can be thought of as a (linear) constraint -% on the full model under consideration, yielding a reduced model. -% Taken from the viewpoint of two designs, with the full model an -% extension of the reduced model, the null hypothesis is that the -% additional terms in the full model are redundent. -% -% Statistical inference proceeds by comparing the additional variance -% explained by full design over and above the reduced design to the -% error variance (of the full design), an "Extra Sum-of-Squares" -% approach yielding an F-statistic for each voxel, whence an SPM{F}. -% -% This is useful in a number of situations : +%__________________________________________________________________________ % -% ---------------- -% -% 1: Two sided tests +% The contrast manager is a user interface for the selection and definition +% of contrasts for a given SPM design. At present, the contrast manager +% provides only interactive GUI facilities. % -% The simplest use of F-contrasts is to effect a two-sided test of a -% simple linear contrast c'B, where c is a column vector. The SPM{F} is -% the square of the corresponding SPM{T}. High values of the SPM{F} -% therefore indicate evidence against the null hypothesis c'B=0 in -% favour of the two-sided alternative c'B~=0. -% -% ---------------- -% -% 2: General linear hypotheses -% -% Where the contrast weights is a matrix, the rows of the (transposed) -% contrast weights matrix c' must define contrasts in their own right, -% and the test is effectively simultaneously testing the null -% hypotheses associated with the individual component contrasts with -% weights defined in the rows. The null hypothesis is still c'B=0, but -% since c is a matrix, 0 here is a zero vector rather than a scalar -% zero, asserting that under the null hypothesis all the component -% hypotheses are true. -% -% For example: Suppose you have a language study with 3 word categories -% (A,B & C), and would like to test whether there is any difference -% at all between the three levels of the "word category" factor. -% -% The design matrix might look something like: -% -% [ 1 0 0 ..] -% [ : : : ..] -% [ 1 0 0 ..] -% [ 0 1 0 ..] -% X = [ : : : ..] -% [ 0 1 0 ..] -% [ 0 0 1 ..] -% [ : : : ..] -% [ 0 0 1 ..] -% [ 0 0 0 ..] -% [ : : : ..] -% -% ...with the three levels of the "word category" factor modelled in the -% first three columns of the design matrix -% -% The matrix of contrast weights will look like: -% -% c' = [1 -1 0 ...; -% 0 1 -1 ...] -% -% Reading the contrasts weights in each row of c', we see that row 1 -% states that category A elicits the same response as category B, row 2 -% that category B elicits the same response as category C, and hence -% together than categories A, B & C all elicit the same response. -% -% The alternative hypothesis is simply that the three levels are not -% all the same, i.e. that there is some difference in the paraeters for -% the three levels of the factor: The first and the second categories -% produce different brain responses, OR the second and third -% categories, or both. -% -% In other words, under the null hypothesis (the categories produce the -% same brain responses), the model reduces to one in which the three -% level "word category" factor can be replaced by a single "word" -% effect, since there is no difference in the parameters for each -% category. The corresponding design matrix would have the first three -% columns replaced by a single column that is the sum (across rows) of -% the first three columns in the design matric above, modelling the -% brain response to a word, whatever is the category. The F-contrast -% above is in fact testing the hypothesis that this reduced design -% doesn't account for significantly less variance than the full design -% with an effect for each word category. -% -% Another way of seeing that, is to consider a reparameterisation of -% the model, where the first column models effects common to all three -% categories, with the second and third columns modelling the -% differences between the three conditions, for example: -% -% [ 1 1 0 ..] -% [ : : : ..] -% [ 1 1 0 ..] -% [ 1 0 1 ..] -% X = [ : : : ..] -% [ 1 0 1 ..] -% [ 1 -1 -1 ..] -% [ : : : ..] -% [ 1 -1 -1 ..] -% [ 0 0 0 ..] -% [ : : : ..] -% -% In this case, an equivalent F contrast is of the form -% c' = [ 0 1 0 ...; -% 0 0 1 ...] -% and would be exatly equivalent to the previous contrast applied to -% the previous design. In this latter formulation, you are asking -% whewher the two columns modelling the "interaction space" account for -% a significant amount of variation (variance) of the data. Here the -% coomponent contrasts in the rows of c' are simply specifying that the -% parameters for the corresponding rows are are zero, and it is clear -% that the F-test is comparing this full model with a reduced model in -% which the second and third columns of X are omitted. -% -% ( Note the difference between the following two F-contrasts: ) -% ( c' = [ 0 1 0 ...; (1) ) -% ( 0 0 1 ...] ) -% ( and ) -% ( c' = [ 0 1 1 ...] (2) ) -% ( ) -% ( The first is an F-contrast, testing whether either of the ) -% ( parameters for the effects modelled in the 2nd & 3rd columns of the ) -% ( design matrix are significantly different from zero. Under the null ) -% ( hypothesis c'B=0, the first contrast imposes a two-dimensional ) -% ( constraint on the design. The second contrast tests whether the SUM ) -% ( of the parameters for the 2nd & 3rd columns is significantly ) -% ( different from zero. Under the null hypothesis c'B=0, this second ) -% ( contrast only imposes a one dimensional constraint on the design. ) -% ( ) -% ( An example of the difference between the two is that the first ) -% ( contrast would be sensitive to the situation where the 2nd & 3rd ) -% ( parameters were +a and -a, for some constant a, wheras the second ) -% ( contrast would not detect this, since the parameters sum to zero. ) -% -% The test for an effect of the factor "word category" is an F-test -% with 3-1=2 "dimensions", or degrees of freedom. -% -% ---------------- +% See also: spm_getSPM.m, spm_contrasts.m % -% 3: Testing the significance of effects modelled by multiple columns -% -% A conceptually similar situation arises when one wonders whether a -% set of confound effects are explaining any variance in the data. One -% important advantage of testing this with F contrasts rather than -% T contrasts is the following. Say you have two covariates -% that you would like to know whether they can "predict" the brain -% responses, and these two are correlated (even a small correlation -% would be important in this instance). Testing one and then the other -% may lead you to conclude that there is no effect. However, testing -% with an F test the two covariates may very well show a not suspected -% effect. This is because by testing one covariate after the other, one -% never tests for what is COMMON to these covariates (see Andrade et -% al, Ambiguous results in functional neuroimaging, NeuroImage, 1999). -% -%_______________________________________________________________________ -% -% More generally, F-tests reflect the usual analysis of variance, while -% t-tests are traditionally post hoc tests, useful to see in which -% direction is an effect going (positive or negative). The introduction -% of F-tests can also be viewed as a first means to do model selection. -% -%_______________________________________________________________________ -% -% Technically speaking, an F-contrast defines a number of directions -% (as many as the rank of the contrast) in the space spanned by the -% column vectors of the design matrix. These directions are simply -% given by X*c if the vectors of X are orthogonal, if not, the space -% define by c is a bit more complex and takes care of the correlation -% within the design matrix. In essence, an F-contrast is defining a -% reduced model by imposing some linear constraints (that have to be -% estimable, see below) on the parameters estimates. Sometimes, this -% reduced model is simply made of a subset of the column of the -% original design matrix but generally, it is defined by a combination -% of those columns. (see spm_FcUtil for what (I hope) is an efficient -% handling of F-contrats computation). -% -%_______________________________________________________________________ -% -% Contrasts: Non-orthogonal designs -% -% Note that parameters zero-weighted in the contrast are still included -% in the model. This is particularly important if the design is not -% orthogonal (i.e. the columns of the design matrix are not -% orthogonal). In effect, the significance of the contrast is assessed -% *after* accounting for the other effects in the design matrix. Thus, -% if two covariates are correlated, testing the significance of the -% parameter associated with one will only test for the part that is not -% present in the second covariate. This is a general point that is also -% true for F-contrasts. See Andrade et al, Ambiguous results in -% functional neuroimaging, NeuroImage, 1999, for a full description of -% the effect of non othogonal design testing. -% -%_______________________________________________________________________ -% Contrasts: Estimability -% -% The contrast c'B is estimated by c'b, where b are the parameter -% estimates given by b=pinv(X)*Y. -% -% However, if a design is rank-deficient (i.e. the columns of the -% design matrix are not linearly independent), then the parameters are -% not unique, and not all linear combinations of the parameter are -% valid contrasts, since contrasts must be uniquely estimable. -% -% A weights vector defines a valid contrast if and only if it can be -% constructed as a linear combination of the rows of the design matrix. -% That is c' (the transposed contrast vector - a row vector) is in the -% row-space of the design matrix. -% -% Usually, a valid contrast will have weights that sum to zero over the -% levels of a factor (such as condition). -% -% A simple example is a simple two condition design including a -% constant, with design matrix -% -% [ 1 0 1 ] -% [ : : : ] -% X = [ 1 0 1 ] -% [ 0 1 1 ] -% [ : : : ] -% [ 0 1 1 ] -% -% The first column corresponds to condition 1, the second to condition -% 2, and the third to a constant (mean) term. Although there are three -% columns to the design matrix, the design only has two degrees of -% freedom, since any one column can be derived from the other two (for -% instance, the third column is the sum of the first two). There is no -% unique set of parameters for this model, since for any set of -% parameters adding a constant to the two condition effects and -% subtracting it from the constant effect yields another set of viable -% parameters. However, the difference between the two condition effects -% is uniquely estimated, so c'=[-1,+1,0] does define a contrast. -% -% If a parameter is estimable, then the weights vector with a single -% "1" corresponding to that parameter (and zero's elsewhere) defines a -% valid contrast. -% -%_______________________________________________________________________ -% Contrasts: Multiple comparisons -% -% Note that SPM implements no corrections to account for you looking at -% multiple contrasts. -% -% If you are interested in a set of hypotheses that together define a -% consistent question, then you should account for this when assessing -% the individual contrasts. A simple Bonferroni approach would assess N -% simultaneouls contrasts at significance level alpha/N, where alpha is -% the chosen significance level (usually 0.05). -% -% For two sided t-tests using SPM{T}'s, the significance level should -% be halved. When considering both SPM{T}'s produced by a contrast and -% it's inverse (the contrast with negative weights), to effect a -% two-sided test to look for both "increases" and "decreases", you -% should review each SPM{T} at at level 0.05/2 rather than 0.05. (Or -% consider an F-contrast!) -% -%_______________________________________________________________________ -% Contrasts: Contrast images and ESS images -% -% For a simple contrast, SPM (spm_getSPM.m) writes a contrast image: -% con_????.{img,hdr}, with voxel values c'b. (The ???? in the image -% names are replaced with the contrast number.) These contrast images -% (for appropriate contrasts) are suitable summary images of an effect -% at this level, and can be used as input at a higher level when -% effecting a random effects analysis. See spm_RandFX.man for further -% details. -% -% For an F-contrast, SPM (spm_getSPM.m) writes the Extra Sum-of-Squares -% (the difference in the residual sums of squares for the full and -% reduced model) as ess_????.{img,hdr}. (Note that the -% ess_????.{img,hdr} and SPM{T,F}_????.{img,hdr} images are not -% suitable input for a higher level analysis.) -% -%======================================================================= +%========================================================================== % U s i n g t h e S P M C o n t r a s t M a n a g e r G U I -%======================================================================= +%========================================================================== % -% The contrast manager graphicsl user interface (GUI) is a dialog box -% for the specification and selection of contrasts. The contrast -% selection interface is presented initially, pressing the "Define new -% contrast..." button pops up the contrast definition interface: +% The contrast manager graphicsl user interface (GUI) is a dialog box for +% the specification and selection of contrasts. The contrast selection +% interface is presented initially, pressing the "Define new contrast..." +% button pops up the contrast definition interface: % -%_______________________________________________________________________ -% ConMan: Contrast selection interface +%__________________________________________________________________________ +% ConMan: Contrast selection interface % % The contrast selection interface consists of: % @@ -385,15 +43,15 @@ % Selected contrasts are highlit in black. % % * Image of the design matrix: -% A gre-scale representation of the design matrix, to aid -% interpretation of the contrasts. +% A grey-scale representation of the design matrix, to aid interpretation +% of the contrasts. % % The design matrix is "surfable": Clicking (and holding or dragging) % around the design matrix image reports the corresponding value of the % design matrix ('normal' click - "left" mouse button usually), the % image filename ('extend' mouse click - "middle" mouse), or parameter % name ('alt' click - "right" mouse). Double clicking the design matrix -% image extracts the design matrix into the base MatLab workspace. +% image extracts the design matrix into the base MATLAB workspace. % (Surfing is handled by spm_DesRep.m) % % * Parameter estimability bar @@ -418,7 +76,6 @@ % dragging over the contrast image reports the contrast name, type and % number, and the value of the contrast at the mouse location. % -% % * "Define new contrast..." button: % Pops up the contrast definition interface (described below) % @@ -447,8 +104,8 @@ % must select the contrast to be renamed before pulling % up the context menu for this option to be available. % -%_______________________________________________________________________ -% ConMan: Contrast definition interface +%__________________________________________________________________________ +% ConMan: Contrast definition interface % % To define a contrast, you must specify: % 1) a name @@ -563,9 +220,9 @@ % (As described above for the contrast selection interface) % % -%======================================================================= +%========================================================================== % S P M C o n t r a s t m a n a g e m e n t -%======================================================================= +%========================================================================== % % Contrasts are stored by SPM in a single structure (See spm_FcUtil.m % for the definition and handling of the contrast structure.) @@ -580,77 +237,77 @@ % spm_getSPM.m) by their contrast number, which indexes them in the % order in which they were created. Because of this, it can be rather % involved to delete any but the most recently defined contrast: All -% file references and indices would have to be canonicalised! THus, no +% file references and indices would have to be canonicalised! Thus, no % "delete" function is provided (as yet). % -%_______________________________________________________________________ +%__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Andrew Holmes -% $Id: spm_conman.m 2021 2008-08-27 10:05:32Z volkmar $ +% $Id: spm_conman.m 3933 2010-06-17 14:19:08Z guillaume $ -%======================================================================= +%========================================================================== % - FORMAT specifications -%======================================================================= +%========================================================================== %( This is a multi function function: If the first argument is a string,) %( then this is the action string, specifying the particular action ) %( function to take. ) % -% FORMAT [I,xCon] = spm_conman(xX,xCon,STATmode,n,Prompt,Mcstr,OK2chg) +% FORMAT [I,xCon] = spm_conman(SPM,STATmode,n,Prompt,Mcstr,OK2chg) % -% xX - Design Matrix structure -% - (see spm_spm.m for structure) -% - fields used directly are: -% .xKXs - space structure of smoothed design matrix -% .name - cellstr of parameter names -% -% xCon (in) - Contrast definitions structure array -% (see spm_FcUtil.m for structure, rules & handling) -% - defaults to empty contrast structure -% - fields used directly are: -% .name - contrast name string -% .STAT - character describing statistic required: 'T' or 'F' -% .c - contrast weights (column) vector / matrix +% SPM.xX - Design Matrix structure +% - (see spm_spm.m for structure) +% - fields used directly are: +% .xKXs - space structure of smoothed design matrix +% .name - cellstr of parameter names % -% STATmode - string indicating STAT modes to allow contrast -% selection/definition for: -% - 'T' to limit to (1-dimensional) contrasts defined for SPM{t} -% - 'F' to limit to contrasts defined for SPM{F} -% - 'T|F' to allow either contrasts for SPM{t} or SPM{F} -% (both may be defined, but only one type may be selected) -% - 'T&F' to allow both contrasts for SPM{t} and SPM{F} -% - defaults to 'T|F' +% SPM.xCon (in) - Contrast definitions structure array +% (see spm_FcUtil.m for structure, rules & handling) +% - defaults to empty contrast structure +% - fields used directly are: +% .name - contrast name string +% .STAT - character describing statistic required: 'T' or 'F' +% .c - contrast weights (column) vector / matrix % -% n - Number of contrasts to select, Inf for unlimited +% STATmode - string indicating STAT modes to allow contrast +% selection/definition for: +% - 'T' to limit to contrasts defined for SPM{t} +% - 'F' to limit to contrasts defined for SPM{F} +% - 'T|F' to allow either contrasts for SPM{t} or SPM{F} +% (both may be defined, but only one type may be selected) +% - 'T&F' to allow both contrasts for SPM{t} and SPM{F} +% - defaults to 'T|F' % -% Prompt - Prompt string +% n - Number of contrasts to select, Inf for unlimited % -% Mcstr - string to describe multiple contrast selection -% E.g. ' for conjunction' will result in the status message -% reading 'Selected 2 contrasts for conjunction' when -% two contrasts are selected. +% Prompt - Prompt string +% +% Mcstr - string to describe multiple contrast selection +% E.g. ' for conjunction' will result in the status message +% reading 'Selected 2 contrasts for conjunction' when +% two contrasts are selected. % -% OK2chg - logical, specifying whether the contrast structure can be -% changed. If false, then new contrasts cannot be defined, and -% existing contrasts cannot be renamed. +% OK2chg - logical, specifying whether the contrast structure can be +% changed. If false, then new contrasts cannot be defined, and +% existing contrasts cannot be renamed. % -% I - Index (or indices) of contrasts selected +% I - Index (or indices) of contrasts selected % -% xCon (out) - Contrast definitions structure array (updated) +% xCon (out) - Contrast definitions structure array (updated) % % ---------------- % % [F,cF] = spm_conman('Initialise',... -% Vis,xX,xCon,STATmode,n,Prompt,Mcstr,OK2chg) +% Vis,SPM,STATmode,n,Prompt,Mcstr,OK2chg) % Initialise ConMan GUI for contrast selection/definition % Vis - Initialisation action: % 'close' - closes ConMan window % 'off' - hides ConMan window % 'reset' - hides and resets ConMan window % 'on' - initialises ConMan window using arguments given -% xX - design matrix structure -% xCon - contrast definitions structure array +% SPM.xX - design matrix structure +% SPM.xCon - contrast definitions structure array % STATmode - string indicating STAT modes to allow contrast % n - number of contrasts to select, Inf for unlimited % Prompt - Prompt string @@ -776,35 +433,33 @@ % .hSTATmode - handle of frame containing "T/F/All" radio buttons % .hStatLin - handle of status line text object (in selection interface) % .hNew - handle of "Define new contrast" pushbutton -%_______________________________________________________________________ -% Andrew Holmes +%__________________________________________________________________________ %-Parameters -%======================================================================= +%========================================================================== COLOUR = [.8,.8,1]; %-Question background colour -PJump = 1; %-Jumping of pointer to ConMan window +PJump = 1; %-Jumping of pointer to ConMan window -if (nargin==0) | ~ischar(varargin{1}) - %======================================================================= - % [I,xCon] = spm_conman(xX,xCon,STATmode,n,Prompt,Mcstr,OK2chg) +%========================================================================== +% [I,xCon] = spm_conman(SPM,STATmode,n,Prompt,Mcstr,OK2chg) +%========================================================================== +if (nargin==0) || ~ischar(varargin{1}) %-Condition arguments - %----------------------------------------------------------------------- - if nargin<6, OK2chg = 0; else, OK2chg=varargin{6}; end - if nargin<5, Mcstr = ''; else, Mcstr=varargin{5}; end - if nargin<4, Prompt='Select contrast(s)...'; else, Prompt=varargin{4}; end - if nargin<3, n=1; else, n=varargin{3}; end - if nargin<2, STATmode='T|F'; else, STATmode=varargin{2}; end + %---------------------------------------------------------------------- + if nargin<6, OK2chg = 0; else OK2chg=varargin{6}; end + if nargin<5, Mcstr = ''; else Mcstr=varargin{5}; end + if nargin<4, Prompt='Select contrast(s)...'; else Prompt=varargin{4}; end + if nargin<3, n=1; else n=varargin{3}; end + if nargin<2, STATmode='T|F'; else STATmode=varargin{2}; end if nargin<1, error('no SPM struct specified'); else SPM = varargin{1};end - %----------------------------------------------------------------------- - xX = SPM.xX; + %---------------------------------------------------------------------- try - xCon = SPM.xCon; + SPM.xCon; catch - xCon = {}; SPM.xCon = {}; end @@ -817,9 +472,7 @@ set(0,'PointerLocation',[FRec(1)+FRec(3)/2, FRec(2)+FRec(2)/2]) end - % setup tmpSPM for checking if SPM has changed upon returning from - % conman. This might happen if contrasts are renamed, for example. - %----------------------------------------------------------------------- + %-Copy SPM structure for later change detecton, eg renamed contrasts tmpSPM = SPM; %-Wait until filenames have been selected @@ -837,8 +490,7 @@ SPM = get(F,'UserData'); xCon = SPM.xCon; - % Check if SPM has changed. Save only if it has. - %----------------------------------------------------------------------- + %-Save SPM.mat only if SPM structure as changed if ~isequal(tmpSPM,SPM) if spm_matlab_version_chk('7') >=0 save('SPM', 'SPM', '-V6'); @@ -850,7 +502,6 @@ %-Reset and hide SelFileWin spm_conman('Initialise','off'); - %-Return focus to previous figure (if any) set(0,'CurrentFigure',cF) @@ -866,53 +517,61 @@ return end -%======================================================================= +%========================================================================== % - Callbacks & Utility embedded functions -%======================================================================= +%========================================================================== -%======================================================================= -switch lower(varargin{1}), case 'initialise' - %======================================================================= - % [F,cF] = spm_conman('Initialise',Vis,xX,xCon,STATmode,n,Prompt,Mcstr,OK2chg) +switch lower(varargin{1}) + %====================================================================== + case 'initialise' + %====================================================================== + % [F,cF] = spm_conman('Initialise',Vis,SPM,STATmode,n,Prompt,Mcstr,OK2chg) - if nargin<2, Vis='on'; else, Vis=varargin{2}; end + if nargin<2, Vis='on'; else Vis=varargin{2}; end - %-Recover ConMan figure number (if it exists) + %-Recover ConMan figure handle (if it exists) F = findobj(get(0,'Children'),'Flat','Tag','ConMan'); - cF = get(0,'CurrentFigure'); %-Save current figure + cF = get(0,'CurrentFigure'); %-Save current figure - switch lower(Vis), case 'close' - close(F) - varargout = {[],cF}; - return + switch lower(Vis) + %------------------------------------------------------------------ + case 'close' + %------------------------------------------------------------------ + close(F) + varargout = {[],cF}; + return + + %------------------------------------------------------------------ case {'off','reset'} - varargout = {F,cF}; %-Return figure handles - if isempty(F), return, end %-Return if no ConMan win - set(F,'Visible','off') %-Make window Invisible - if strcmp(lower(Vis),'reset') + %------------------------------------------------------------------ + varargout = {F,cF}; %-Return figure handles + if isempty(F), return, end %-Return if no ConMan win + set(F,'Visible','off') %-Make window Invisible + if strcmpi(Vis,'reset') set(findobj(F,'Tag','Done'),'UserData',-1) end return + + %------------------------------------------------------------------ case 'on' + %------------------------------------------------------------------ %-Sort out arguments - %--------------------------------------------------------------- - if nargin<8, OK2chg = 0; else, OK2chg=varargin{8}; end - if nargin<7, Mcstr = ''; else, Mcstr=varargin{7}; end + %-------------------------------------------------------------- + if nargin<8, OK2chg = 0; else OK2chg=varargin{8}; end + if nargin<7, Mcstr = ''; else Mcstr=varargin{7}; end Mcstr = cellstr(Mcstr); if length(Mcstr)<2, Mcstr{2}=''; end - if nargin<6, Prompt='Select contrast(s)'; else, Prompt=varargin{6}; end - if nargin<5, n=Inf; else, n=varargin{5}; end - if nargin<4, STATmode='T&F'; else, STATmode=varargin{4}; end + if nargin<6, Prompt='Select contrast(s)'; else Prompt=varargin{6}; end + if nargin<5, n=Inf; else n=varargin{5}; end + if nargin<4, STATmode='T&F'; else STATmode=varargin{4}; end if nargin<3, error('insufficient arguments'), end - SPM = varargin{3}; + SPM = varargin{3}; xCon = SPM.xCon; xX = SPM.xX; - - %-Create/find ConMan window - %--------------------------------------------------------------- - if isempty(F) %-Create ConMan win + %-------------------------------------------------------------- + if isempty(F) %-Create ConMan win [F,H] = spm_conman('CreateFig'); else %-Get handles H.hDesMtxAx = findobj(F,'Tag','DesMtxAx'); @@ -924,36 +583,32 @@ H.hStatLin = findobj(F,'Tag','StatusLine'); H.hNew = findobj(F,'Tag','New'); end - if ~isfield(SPM, 'eeg') - set(findobj('Tag', 'components'), 'Visible', 'off'); - end - varargout = {F,cF}; %-Return figure handles + varargout = {F,cF}; %-Return figure handles - %-Store required parameters in UserData of various objects - %--------------------------------------------------------------- + %-------------------------------------------------------------- set(F, 'UserData',SPM) - set(H.hStatLin, 'UserData',Mcstr) %-** + set(H.hStatLin, 'UserData',Mcstr) %-Initialise interface - %--------------------------------------------------------------- + %-------------------------------------------------------------- set(findobj(F,'Tag','Done'),'UserData',0) %-Init. Done UserData STAT = spm_conman('TFA',F,'',STATmode); %-Init. TFA buttons set(H.hPrompt,'String',Prompt,'UserData',n) %-Set prompt spm_conman('ImDesMtx',xX,H.hDesMtxAx) %-Depict DesMtx spm_conman('ImParEst',xX,H.hParEstAx) %-Parameter estimability - spm_conman('ListCon',H.hConList,xCon,STAT,[]) %-List contrasts - if OK2chg, tmp='on'; else, tmp='off'; end %-OK to change xCon? - set(H.hNew,'Enable',tmp) %-En/dis-able change UI - %-**** if isempty(xCon), spm_conman(); end %-Go straight to DNewUI + spm_conman('ListCon',H.hConList,xCon,STAT,[]) %-List contrasts + if OK2chg, tmp='on'; else tmp='off'; end %-OK to change xCon? + set(H.hNew,'Enable',tmp) %-En/dis-able change UI + %-**** if isempty(xCon), spm_conman(); end %-Go straight to DNewUI %-Popup figure, retaining CurrentFigure - %--------------------------------------------------------------- + %-------------------------------------------------------------- set(get(findobj(F,'Tag','DefineNew'),'UserData'),'Visible','off') %-Hide define UI - figure(F) %-PopUp figure - set(0,'CurrentFigure',cF) %-Return to prev. figure + figure(F) %-PopUp figure + set(0,'CurrentFigure',cF) %-Return to prev. figure return otherwise @@ -961,23 +616,23 @@ end - %======================================================================= + %====================================================================== case 'imdesmtx' - %======================================================================= + %====================================================================== % spm_conman('ImDesMtx',xX,h) h = varargin{3}; %-Picture design matrix - %----------------------------------------------------------------------- + %------------------------------------------------------------------ axes(h) - if isfield(varargin{2},'nKX') & ~isempty(varargin{2}.nKX) + if isfield(varargin{2},'nKX') && ~isempty(varargin{2}.nKX) hDesMtxIm = image((varargin{2}.nKX+1)*32); else hDesMtxIm = image(... (spm_DesMtx('sca',varargin{2}.xKXs.X,varargin{2}.name)+1)*32); end - set(h,'YTick',[],'XTick',[]) %-No Tick marks + set(h,'YTick',[],'XTick',[]) %-No Tick marks set(h,'Tag','DesMtxAx','UserData',varargin{2}) %-Reset axis UserData after image xlabel('Design matrix') set(hDesMtxIm,'UserData',... @@ -985,16 +640,16 @@ set(hDesMtxIm,'ButtonDownFcn','spm_DesRep(''SurfDesMtx_CB'')') - %======================================================================= + %====================================================================== case 'imparest' - %======================================================================= + %====================================================================== % spm_conman('ImParEst',xX,h) xX = varargin{2}; h = varargin{3}; %-Picture design parameter estimability - %----------------------------------------------------------------------- + %------------------------------------------------------------------ axes(h) est = spm_SpUtil('IsCon',xX.xKXs); nPar = length(est); @@ -1009,23 +664,23 @@ set(hParEstIm,'ButtonDownFcn','spm_DesRep(''SurfEstIm_CB'')') - %======================================================================= + %====================================================================== case 'listcon' - %======================================================================= + %====================================================================== % spm_conman('ListCon',hConList,xCon,STAT,I) hConList = varargin{2}; xCon = varargin{3}; STAT = varargin{4}; if nargin<5 - Q = get(hConList,'UserData'); - I = Q(get(hConList,'Value')); + Q = get(hConList,'UserData'); + I = Q(get(hConList,'Value')); else - I = varargin{5}; + I = varargin{5}; end %-Sort out list, filtering by STAT, and display - %----------------------------------------------------------------------- + %------------------------------------------------------------------ if isempty(xCon) Q = []; elseif isempty(STAT) @@ -1062,26 +717,26 @@ spm_conman('StatusLine',get(hConList,'Parent')) - %======================================================================= + %====================================================================== case 'graphcons' - %======================================================================= + %====================================================================== % spm_conman('GraphCons',xCon,I,F) if nargin<2, error('insufficient arguments'), end xCon = varargin{2}; - if nargin<3, I=[1:length(xCon)]; else, I=varargin{3}; end - if nargin<4, F=[]; else, F=varargin{4}; end + if nargin<3, I=[1:length(xCon)]; else I=varargin{3}; end + if nargin<4, F=[]; else F=varargin{4}; end if isempty(F), F=spm_figure('FindWin','ConMan'); end if isempty(F), error('can''t find ConMan win'), end cF = get(0,'CurrentFigure'); %-Save current figure - set(0,'CurrentFigure',F); %-Make F current + set(0,'CurrentFigure',F); %-Make F current delete(findobj(F,'Tag','ConGrphAx')); %-Display contrasts - %----------------------------------------------------------------------- + %------------------------------------------------------------------ if isempty(I) axes('Position',[0.65 (0.7 + .1*(1-0.9)) 0.3 .1*.9],... 'Tag','ConGrphAx','Visible','off') @@ -1090,9 +745,7 @@ 'FontAngle','Italic',... 'HorizontalAlignment','Center',... 'VerticalAlignment','Middle') - else - nPar = size(xCon(1).c,1); xx = [repmat([0:nPar-1],2,1);repmat([1:nPar],2,1)]; nCon = length(I); @@ -1105,7 +758,7 @@ for ii = nCon:-1:1 i = abs(I(ii)); axes('Position',[0.65 (0.7 + dy*(nCon-ii+.1)) 0.3 dy*.9]) - if xCon(i).STAT == 'T' & size(xCon(i).c,2)==1 + if xCon(i).STAT == 'T' && size(xCon(i).c,2)==1 %-Single vector contrast for SPM{t} - bar yy = [zeros(1,nPar);repmat(xCon(i).c',2,1);zeros(1,nPar)]; h = patch(xx,yy,[1,1,1]*.5); @@ -1134,16 +787,16 @@ end end - set(0,'CurrentFigure',cF) %-Reset CurrentFigure to previous figure + set(0,'CurrentFigure',cF) %-Reset CurrentFigure to previous figure - %======================================================================= + %====================================================================== case 'statusline' - %======================================================================= + %====================================================================== % spm_conman('StatusLine',F,str,col) - if nargin<2, F = findobj(get(0,'Children'),'Flat','Tag','ConMan'); - else, F = varargin{2}; end + if nargin<2, F = findobj(get(0,'Children'),'Flat','Tag','ConMan'); + else F = varargin{2}; end if nargin<3 n = get(findobj(F,'Tag','Prompt'),'UserData'); @@ -1153,7 +806,7 @@ if m~=1, str=[str,'s']; end Mcstr = get(findobj(F,'Tag','StatusLine'),'UserData'); - if m>1, str=[str,Mcstr{1}]; else, str=[str,Mcstr{2}]; end + if m>1, str=[str,Mcstr{1}]; else str=[str,Mcstr{2}]; end if m==0 if n<0 @@ -1172,14 +825,14 @@ str = varargin{3}; end - if nargin<4, col='w'; else, col=varargin{4}; end + if nargin<4, col='w'; else col=varargin{4}; end set(findobj(F,'Tag','StatusLine'),'String',str,'ForegroundColor',col) - %======================================================================= + %====================================================================== case 'done_cb' - %======================================================================= + %====================================================================== % spm_conman('Done_CB') F = gcbf; @@ -1187,37 +840,36 @@ n = get(findobj(F,'Tag','Prompt'),'UserData'); q = get(findobj(F,'Tag','ConList'),'Value'); - - if n>0 & isempty(q) %-Contrast(s) required, but none selected + if n>0 && isempty(q) %-Contrast(s) required, but none selected if n==1, str = 'Select a contrast!'; elseif isfinite(n), str = sprintf('Select %d contrasts!',n); - else, str = 'Select at least one contrast!'; + else str = 'Select at least one contrast!'; end - elseif length(q)>abs(n) %-Too many contrasts selected - if n<0, tstr='at most'; else, tstr='only'; end + elseif length(q)>abs(n) %-Too many contrasts selected + if n<0, tstr='at most'; else tstr='only'; end if abs(n)==1, str = ['Select',tstr,' one contrast!']; - else, str = sprintf('Select %s %d contrasts!',tstr,abs(n)); + else str = sprintf('Select %s %d contrasts!',tstr,abs(n)); end - elseif n>0 & isfinite(n) & length(q)0 && isfinite(n) && length(q)2, error('matrices only!'), end c = num2cell(cstr,2); cstr = cell(size(c)); - for i=1:prod(size(c)), cstr{i}=num2str(c{i}); end + for i=1:numel(c), cstr{i}=num2str(c{i}); end else error('contrast input must be string or number') end - %-Evaluate individual lines of contrast matrix input - %----------------------------------------------------------------------- + %------------------------------------------------------------------ I = zeros(size(c,1),1); msg = cell(size(c)); [msg{:}] = deal(' (OK)'); for i=1:size(c,1) @@ -1469,9 +1115,9 @@ if isempty(c{i}) msg{i}=' (empty line - ignored)'; elseif all(c{i}(:)==0) - if size(c{i},1)==1, str='vector'; else, str='matrix'; end + if size(c{i},1)==1, str='vector'; else str='matrix'; end c{i}=[]; msg{i}=[' (zero ',str,' - ignored)']; - elseif STAT=='T' & size(c{i},1)>1 + elseif STAT=='T' && size(c{i},1)>1 c{i}='!'; msg{i}='!vector required'; elseif size(c{i},2)>p c{i}='!'; msg{i}=sprintf('!too long - only %d prams',p); @@ -1479,7 +1125,7 @@ if size(c{i},2)

1, str=' column'; else, str=''; end + if size(c{i},1)>1, str=' column'; else str=''; end if tmp>1, str=[str,'s']; end msg{i} = sprintf(' (right padded with %d zero%s)',tmp,str); end @@ -1492,37 +1138,35 @@ end %-Construct contrast matrix, validity indicator, and collate parsing messages - %----------------------------------------------------------------------- + %------------------------------------------------------------------ c = cat(1,c{find(I)}); msg = [char(cstr), repmat(' <- ',size(msg,1),1), char(msg)]; emsg = msg(find(~I),:); imsg = msg(find( I),:); - if all(I) & STAT=='T' & size(c,1)>1 %-Check for vector t-contrasts! + if all(I) && STAT=='T' && size(c,1)>1 %-Check for vector t-contrasts! I=zeros(size(I)); emsg={'!vector required'}; imsg={}; end %-Return arguments - %----------------------------------------------------------------------- + %------------------------------------------------------------------ varargout = {c',I,emsg,imsg,msg}; - %======================================================================= - case 'parseistr' %-Parse index string - %======================================================================= + %====================================================================== + case 'parseistr' %-Parse index string + %====================================================================== % [iX0,I,emsg,imsg] = spm_conman('ParseIStr',str,max) % str should be a string (row)vector - %-Sort out parameters - %----------------------------------------------------------------------- + %------------------------------------------------------------------ str = varargin{2}; mx = varargin{3}; - %-Process input string - %----------------------------------------------------------------------- + %------------------------------------------------------------------ I = evalin('base',['[',str,']'],'''!'''); if ischar(I) @@ -1531,36 +1175,36 @@ end %-Construct list of valid indicies - %----------------------------------------------------------------------- - ok = ismember(I(:)',[1:mx]); + %------------------------------------------------------------------ + ok = ismember(I(:)', 1:mx); iX0 = I(ok); %-Construct diagnostic info messages - %----------------------------------------------------------------------- - str = ''; msg=''; + %------------------------------------------------------------------ + str = {}; msg={}; if any(ok) - str = strvcat(str,num2str(I(ok))); - msg = strvcat(msg,' <- (OK)'); + str = [str; num2str(I(ok))]; + msg = [msg; ' <- (OK)']; end tmp = ( I<1 | I>mx ); %-Out of range if any(tmp) - str = strvcat(str,num2str(I(tmp))); - msg = strvcat(msg,sprintf(' <- (ignored - not in [1:%d]',mx)); + str = [str; num2str(I(tmp))]; + msg = [msg; sprintf(' <- (ignored - not in [1:%d]',mx)]; end tmp = ( ~tmp & ~ok ); %-Non integer in range if any(tmp) - str = strvcat(str,num2str(I(tmp))); - msg = strvcat(msg,' <- (ignored - non-integer)'); + str = [str; num2str(I(tmp))]; + msg = [msg; ' <- (ignored - non-integer)']; end %-Return arguments - %----------------------------------------------------------------------- - varargout = {iX0,1,'',cellstr([str,msg])}; + %------------------------------------------------------------------ + varargout = {iX0,1,'',cellstr([char(str),char(msg)])}; - %======================================================================= + %====================================================================== case 'reset_cb' - %======================================================================= + %====================================================================== % spm_conman('Reset_CB') hConList = findobj(gcbf,'Tag','ConList'); @@ -1571,35 +1215,32 @@ spm_conman('ListCon',hConList,xCon,STAT,[]) - %======================================================================= + %====================================================================== case 'd_setup_cb' - %======================================================================= + %====================================================================== % spm_conman('D_Setup_CB') F = gcbf; STAT = get(findobj(F,'Tag','TFA','Value',1),'UserData'); STATmode = get(findobj(F,'Tag','STATmode'),'UserData'); - set(F,'UIContextMenu',[]) %-Disable Fig ContextMenu + set(F,'UIContextMenu',[]) %-Disable Fig ContextMenu H = get(findobj(F,'Tag','DefineNew'),'UserData'); %-Get define UI handles set(findobj(H,'flat','Tag','D_name'),'String','') %-Clear name %set(findobj(H,'flat','Tag','D_ConMtx'),'UserData',[]) %-Clear con definition - set(H,'Visible','on') %-Show UI + set(H,'Visible','on') %-Show UI SPM = get(F, 'UserData'); - if ~isfield(SPM, 'eeg') - set(findobj('Tag', 'components'), 'Visible', 'off'); - end - spm_conman('D_TF',F,STAT,STATmode); %-Setup rest of define UI + spm_conman('D_TF',F,STAT,STATmode); %-Setup rest of define UI - %======================================================================= + %====================================================================== case {'d_conmtx_cb','d_x1cols_cb'} - %======================================================================= + %====================================================================== % spm_conman('D_ConMtx_CB') % spm_conman('D_X1cols_CB') - fcn = find(strcmp(lower(varargin{1}),{'d_conmtx_cb','d_x1cols_cb'})); + fcn = find(strcmpi(varargin{1},{'d_conmtx_cb','d_x1cols_cb'})); F = findobj('Tag', 'ConMan'); hD_ConMtx = findobj(F,'Tag','D_ConMtx'); @@ -1614,20 +1255,19 @@ % This shouldn't happen end else - % i.e. compute button on components was used to get here - str = getappdata(findobj('Tag', 'conman_eeg'), 'c'); + % This shouldn't happen end %-Extract info from holding objects - %----------------------------------------------------------------------- + %------------------------------------------------------------------ xX = get(findobj(F,'Tag','DesMtxAx'),'UserData'); STAT = get(findobj(F,'Tag','D_TF','Value',1),'UserData'); - if fcn==1 %-Parse string from ConMtx widget - %----------------------------------------------------------------------- - + if fcn==1 %-Parse string from ConMtx widget + %------------------------------------------------------------------ set(hD_X1cols,'String','') + [c,I,emsg,imsg] = spm_conman('ParseCon',str,xX.xKXs,STAT); if all(I) DxCon = spm_FcUtil('Set','',STAT,'c',c,xX.xKXs); @@ -1635,8 +1275,8 @@ DxCon = []; end - elseif fcn==2 %-Process column indicies from X1cols widget - %----------------------------------------------------------------------- + elseif fcn==2 %-Process column indicies from X1cols widget + %------------------------------------------------------------------ set(hD_ConMtx,'String','') nPar = spm_SpUtil('size',xX.xKXs,2); @@ -1645,7 +1285,7 @@ if I try %-try-catch block for any errors in spm_FcUtil! DxCon = spm_FcUtil('Set','',STAT,'iX0',iX0,xX.xKXs); - if STAT=='T' & size(DxCon.c,2)>1 + if STAT=='T' && size(DxCon.c,2)>1 I = 0; emsg = {'! t-contrasts must be vectors'}; end catch @@ -1655,9 +1295,8 @@ end end - %-Define the contrast or report errors... - %----------------------------------------------------------------------- + %------------------------------------------------------------------ set(findobj(F,'Tag','D_ConErrs'),'String',emsg,'Value',[]) set(findobj(F,'Tag','D_ConInfo'),'String',imsg,'Value',[]) if all(I) @@ -1667,34 +1306,33 @@ set(hD_ConMtx,'UserData',[]); %-Clear contrast store spm_conman('GraphCons',[],[],F) %-Clear contrast plot end - spm_conman('D_Status',F) %-Set StatusLine + spm_conman('D_Status',F) %-Set StatusLine - %======================================================================= + %====================================================================== case 'd_reset_cb' - %======================================================================= + %====================================================================== % spm_conman('D_Reset_CB') STAT = get(findobj(gcbf,'Tag','TFA','Value',1),'UserData'); - set(findobj(gcbf,'Tag','D_name'),'String','') %-Clear name - set(findobj(gcbf,'Tag','D_ConMtx'),'UserData',[]) %-Contrast definition + set(findobj(gcbf,'Tag','D_name'),'String','') %-Clear name + set(findobj(gcbf,'Tag','D_ConMtx'),'UserData',[]) %-Contrast definition spm_conman('D_TF',gcbf,STAT); %-Setup rest of define UI - %======================================================================= + %====================================================================== case 'd_cancel_cb' - %======================================================================= + %====================================================================== % spm_conman('D_Cancel_CB') set(get(findobj(gcbf,'Tag','DefineNew'),'UserData'),'Visible','off') set(gcbf,'UIContextMenu',findobj(gcbf,'Tag','ConMan_ConMen')) - delete(findobj('Tag', 'conman_eeg')); spm_conman('StatusLine') - %======================================================================= + %====================================================================== case 'd_ok_cb' - %======================================================================= + %====================================================================== % spm_conman('D_OK_CB') F = gcbf; @@ -1706,7 +1344,7 @@ dNam = ~isempty(name); dCon = ~isempty(DxCon); - if ~(dNam & dCon) + if ~(dNam && dCon) spm('Beep') str = { 'contrast name not defined!','',... 'no valid contrast defined!',''}; @@ -1716,9 +1354,8 @@ return end - %-Append new contrast to xCon structure of ConMan figure 'UserData' - %----------------------------------------------------------------------- + %------------------------------------------------------------------ DxCon.name = name; if ~strcmp(DxCon.STAT,STAT), error('STAT & DxCon.STAT mismatch!'), end SPM = get(F,'UserData'); @@ -1741,15 +1378,15 @@ % For contrasts with Bayesian estimated models if isfield(SPM,'PPM') if isfield(SPM.PPM,'xCon') - Nc=length(SPM.PPM.xCon); - SPM.PPM.xCon(Nc+1).PSTAT=STAT; + Nc = length(SPM.PPM.xCon); + SPM.PPM.xCon(Nc+1).PSTAT = STAT; else - SPM.PPM.xCon(1).PSTAT=STAT; + SPM.PPM.xCon(1).PSTAT = STAT; end end %-Redisplay the new list of contrasts, with the new one selected - %----------------------------------------------------------------------- + %------------------------------------------------------------------ hConList = findobj(F,'Tag','ConList'); I = length(xCon); @@ -1759,43 +1396,41 @@ % n = get(findobj(F,'Tag','Prompt'),'UserData'); % if abs(n)>1, I=[I,length(xCon)]; else, I=length(xCon); end - spm_conman('TFA',F,xCon(end).STAT); %-Set STAT + spm_conman('TFA',F,xCon(end).STAT); %-Set STAT spm_conman('ListCon',hConList,xCon,xCon(end).STAT,I) %-ListCon %-Hide the DefineNew UI - %----------------------------------------------------------------------- + %------------------------------------------------------------------ set(get(findobj(gcbf,'Tag','DefineNew'),'UserData'),'Visible','off') set(gcbf,'UIContextMenu',findobj(gcbf,'Tag','ConMan_ConMen')) - % delete components window - delete(findobj('Tag', 'conman_eeg')); - - %======================================================================= + + %====================================================================== case 'd_status' - %======================================================================= + %====================================================================== % spm_conman('D_Status',F) - if nargin<2, F=gcbf; else, F=varargin{2}; end + if nargin<2, F=gcbf; else F=varargin{2}; end str = {' not',''}; dNam = ~isempty(get(findobj(F,'Tag','D_name'),'String')); dCon = ~isempty(get(findobj(F,'Tag','D_ConMtx'),'UserData')); - if dNam & dCon, ok='on'; col='g'; else, ok='off'; col='w'; end + if dNam && dCon, ok='on'; col='g'; else ok='off'; col='w'; end spm_conman('StatusLine',F,... sprintf('name%s defined, contrast%s defined',str{dNam+1},str{dCon+1}),... col) - %set(findobj(F,'Tag','D_OK'),'Enable',ok) %-Enable "OK" button? + %set(findobj(F,'Tag','D_OK'),'Enable',ok) %-Enable "OK" button? - %======================================================================= + %====================================================================== case 'createfig' - %======================================================================= + %====================================================================== % [F,H] = spm_conman('CreateFig') % Handle Structure - H.{hConList,hDesMtxAx,hPrompt,hSTATmode,hStatLin,hNew} cF = get(0,'CurrentFigure'); %-Save current figure %-Create window, compute scaling for screen size - %----------------------------------------------------------------------- + %------------------------------------------------------------------ WS = spm('WinScale'); %-Window scaling factors FS = spm('FontSizes'); %-Scaled font sizes PF = spm_platform('fonts'); %-Font names (for this platform) @@ -1822,7 +1457,7 @@ %-Draw GUI objects - %----------------------------------------------------------------------- + %------------------------------------------------------------------ hPrompt = uicontrol(F,'Style','Text','Tag','Prompt','UserData',[],... 'String','',... 'FontName',PF.times,... @@ -1874,13 +1509,22 @@ 'HorizontalAlignment','Left',... 'BackgroundColor','w',... 'Position',[042 320 256 016].*WS); - + + hh = uicontextmenu('Tag','ConMan_ConMenu'); + uimenu(hh,'Label','Rename selected contrast...',... + 'Tag','CM_Ren',... + 'CallBack', 'spm_conman(''Rename_CB'')',... + 'Interruptible','off','BusyAction','Cancel'); + set(hh,'CallBack','spm_conman(''FConMenu_CB'')',... + 'Interruptible','off','BusyAction','Cancel'); + hConList = uicontrol(F,'Style','ListBox','Tag','ConList',... 'ToolTipString',['Select contrast(s) - drag/shift-click',... '/ctrl-click to select multiple contrasts'],... 'String',{'list','not','set','yet'},... 'Max',2,... - 'CallBack','spm_conman(''ConList_CB'')',... + 'CallBack','spm_conman(''ConList_CB'')',... + 'UIContextMenu',hh,... 'Interruptible','off','BusyAction','Queue',... 'BackgroundColor','w',... 'Position',[040 080 260 240].*WS); @@ -1913,13 +1557,11 @@ uicontrol(F,'Style','Frame','Tag','StatusArea',... 'Position',[010 010 480 030].*WS); - if exist('spm_help.m')==2 - uicontrol(F,'Style','Pushbutton','String','?',... - 'ToolTipString','help on contrasts and the contrast manager',... - 'ForegroundColor','g',... - 'Callback','spm_help(''spm_conman.m'')',... - 'Position',[460 015 020 020].*WS); - end + uicontrol(F,'Style','Pushbutton','String','?',... + 'ToolTipString','help on contrasts and the contrast manager',... + 'ForegroundColor','g',... + 'Callback','spm_help(''spm_con.man'')',... + 'Position',[460 015 020 020].*WS); hStatLin = uicontrol(F,'Style','Text','Tag','StatusLine',... 'String','',... @@ -1971,8 +1613,8 @@ %-Draw contrast definition GUI - %----------------------------------------------------------------------- - H = []; %-Save handles for visibility switching + %------------------------------------------------------------------ + H = []; %-Save handles for visibility switching h = uicontrol(F,'Style','Frame','Tag','DefineNew',... 'Position',[010 045 300 350].*WS); @@ -2108,6 +1750,7 @@ 'Position',[245 180 050 020].*WS); H = [H,h]; + % ---------------- %-Errors & info boxes... h = uicontrol(F,'Style','ListBox','Tag','D_ConErrs',... 'ToolTipString','contrast parsing errors',... @@ -2156,7 +1799,7 @@ set(findobj(H,'flat','Tag','DefineNew'),'UserData',H) %-Finish up - %----------------------------------------------------------------------- + %------------------------------------------------------------------ set(0,'CurrentFigure',cF) varargout = {F,struct( 'hConList', hConList,... 'hDesMtxAx', hDesMtxAx,... @@ -2167,12 +1810,12 @@ 'hNew', hNew )}; - %======================================================================= - otherwise %-unknown action - %======================================================================= + %====================================================================== + otherwise %-unknown action + %====================================================================== error(['Illegal Action string: ',varargin{1}]) - %======================================================================= -end % - E N D -%======================================================================= +%========================================================================== +end % - E N D +%========================================================================== diff --git a/spm_contrasts.m b/spm_contrasts.m index 38761ae..20a71fd 100644 --- a/spm_contrasts.m +++ b/spm_contrasts.m @@ -8,7 +8,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Andrew Holmes, Karl Friston & Jean-Baptiste Poline -% $Id: spm_contrasts.m 3465 2009-10-14 15:14:29Z guillaume $ +% $Id: spm_contrasts.m 3995 2010-07-13 17:19:49Z karl $ % Temporary SPM variable to check for any changes to SPM. We want to avoid % always having to save SPM.mat unless it has changed, because this is @@ -79,6 +79,7 @@ case {'T','P'} if strcmp(xCon(ic).STAT,'P') && strcmp(SPM.PPM.xCon(ic).PSTAT,'F') + % Chi^2 Bayesian inference for compound contrast %------------------------------------------------------ disp('Chi^2 Bayesian inference for compound contrast'); @@ -87,7 +88,8 @@ xCon = spm_vb_x2(SPM,XYZ,xCon,ic); - else %-Implement contrast as sum of scaled beta images + else + %-Implement contrast as sum of scaled beta images %------------------------------------------------------ fprintf('\t%-32s: %-10s%20s',sprintf('contrast image %2d',ic),... '(spm_add)','...initialising'); %-# @@ -158,10 +160,10 @@ %-Write inference SPM/PPM %====================================================================== - if isempty(xCon(ic).Vspm) || xCon(ic).STAT=='P' - % As PPM effect size threshold, gamma, may have changed - % always update PPM file + if isempty(xCon(ic).Vspm) || xCon(ic).STAT == 'P' + % Always update PPM as size threshold, gamma, may have changed + %------------------------------------------------------------------ fprintf('\t%-32s: %30s',sprintf('spm{%c} image %2d',xCon(ic).STAT,ic),... '...computing'); %-# @@ -170,9 +172,10 @@ case 'T' %-Compute SPM{t} image %---------------------------------------------------------- cB = spm_get_data(xCon(ic).Vcon,XYZ); - l = spm_get_data(VHp,XYZ); - VcB = xCon(ic).c'*SPM.xX.Bcov*xCon(ic).c; - Z = cB./sqrt(l*VcB); + l = spm_get_data(VHp,XYZ); % get hyperparamters + Vc = xCon(ic).c'*SPM.xX.Bcov*xCon(ic).c; + SE = sqrt(l*Vc); % and standard error + Z = cB./(SE + exp(-8)*max(SE)); str = sprintf('[%.1f]',SPM.xX.erdf); @@ -263,6 +266,7 @@ end % (if isempty(xCon(ic)...) end % (for i = 1:length(Ic)) +spm('Pointer','Arrow') % place xCon back in SPM %-------------------------------------------------------------------------- diff --git a/spm_cva.m b/spm_cva.m index 34012af..0f2bbd1 100644 --- a/spm_cva.m +++ b/spm_cva.m @@ -53,7 +53,7 @@ % chi-squared distribution and allow one to test the null hypothesis that % the mapping is D or more dimensional. This inference is shown as a bar % plot of p-values. The first p-value is formally identical to that -% obtained using Wilk's Lambda and tests for the significance of any +% obtained using Wilks' Lambda and tests for the significance of any % mapping. % % This routine uses the current contrast to define the subspace of interest @@ -81,7 +81,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_cva.m 3354 2009-09-03 15:25:12Z guillaume $ +% $Id: spm_cva.m 3710 2010-02-03 19:11:26Z guillaume $ % get figure handles @@ -218,7 +218,7 @@ w = X*W; % canonical variates (design) C = c*W; % canonical contrast (design) -% inference on dimensionality - p(i) test of D >= i; Wilk's Lambda := p(1) +% inference on dimensionality - p(i) test of D >= i; Wilks' Lambda := p(1) %-------------------------------------------------------------------------- cval = log(diag(d) + 1); for i = 1:h diff --git a/spm_cva_results.m b/spm_cva_results.m index 8b28fa0..566d47a 100644 --- a/spm_cva_results.m +++ b/spm_cva_results.m @@ -29,13 +29,15 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_cva_results.m 2662 2009-01-28 20:23:11Z karl $ +% $Id: spm_cva_results.m 3717 2010-02-08 16:44:42Z guillaume $ % get CVA if necessary %-------------------------------------------------------------------------- if nargin<1 - [file,pth] = uigetfile('CVA*.mat', 'Select CVA to display'); + [file,sts] = spm_select(1,'mat',... + 'Select CVA to display',[],[],'^CVA.*\.mat$'); + if ~sts, CVA = []; return; end file = load(file); CVA = file.CVA; end diff --git a/spm_dcm_U.m b/spm_dcm_U.m index da07795..1140191 100644 --- a/spm_dcm_U.m +++ b/spm_dcm_U.m @@ -1,6 +1,6 @@ -function [] = spm_dcm_U (DCM_filename,SPM_filename,session,input_nos) +function spm_dcm_U(DCM_filename,SPM_filename,session,input_nos) % Insert new inputs into a DCM model -% FORMAT [] = spm_dcm_U (DCM_filename,SPM_filename,session,input_nos) +% FORMAT spm_dcm_U(DCM_filename,SPM_filename,session,input_nos) % % DCM_filename Name of DCM file % SPM_filename Name of SPM file (eg. 'SPM') @@ -16,12 +16,11 @@ % This function can be used, for example, to replace subject X's inputs by subject Y's. % The model can then be re-estimated without having to go through % model specification again. -% -%_______________________________________________________________________ +%__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Will Penny & Klaas Enno Stephan -% $Id: spm_dcm_U.m 1440 2008-04-18 10:00:22Z klaas $ +% $Id: spm_dcm_U.m 3691 2010-01-20 17:08:30Z guillaume $ load(DCM_filename); @@ -35,7 +34,7 @@ % Check numbers of inputs match -%------------------------------------------------------------------------ +%-------------------------------------------------------------------------- % Number of selected inputs from SPM file m_sel = length(find(cell2mat(input_nos))); @@ -51,7 +50,7 @@ % Replace inputs -%------------------------------------------------------------------------ +%-------------------------------------------------------------------------- % Number of inputs in SPM file u = length(Sess.U); @@ -112,6 +111,4 @@ save(DCM_filename, 'DCM','-V6'); else save(DCM_filename, 'DCM'); -end; - -return +end diff --git a/spm_dcm_average.m b/spm_dcm_average.m index 1cb773c..0deed0b 100644 --- a/spm_dcm_average.m +++ b/spm_dcm_average.m @@ -1,247 +1,129 @@ -function spm_dcm_average (mtype,P,name,Nowarning) -% Produce an aggregate DCM model using Bayesian averaging -% FORMAT spm_dcm_average (mtype,P,name,Nowarning) +function spm_dcm_average (P,name) +% Produce an aggregate DCM model using Bayesian FFX averaging +% FORMAT spm_dcm_average (P,name) % -% mtype - ERP: mtype =0; fMRI: mtype > 0 -% P - Array of DCM filenames eg. P(1,:)='DCM1', P(2,:)='DCM2' -% name - Name of DCM output file. This is prefixed by 'DCM_avg_'. -% Nowarning - Send warning to user (default) or not +% P - character/cell array of DCM filenames +% name - name of DCM output file (will be prefixed by 'DCM_avg_') % % This routine creates a new DCM model in which the parameters are averaged -% over a number of fitted DCM models. These can be over sessions or over -% subjects. This average model can then be interrogated using the standard -% DCM 'review' options to look at contrasts of parameters. The resulting +% over a number of fitted DCM models. These can be over sessions or over +% subjects. This average model can then be interrogated using the standard +% DCM 'review' options to look at contrasts of parameters. The resulting % inferences correspond to a Bayesian Fixed Effects analysis. % -% Note that the Bayesian averaging is only applied to the A, B and C +% Note that the Bayesian averaging is only applied to the A, B and C % matrices (and matrix D if a nonlinear model is used). -% All other quantities in the average model are initially simply copied from -% the first DCM in the list. Subsequently, they are deleted before saving -% the average DCM in order to avoid any false impression that averaged -% models could be used for model comparison or contained averaged timeseries. +% All other quantities in the average model are initially simply copied from +% the first DCM in the list. Subsequently, they are deleted before saving +% the average DCM in order to avoid any false impression that averaged +% models could be used for model comparison or contained averaged time series. % Neither operation is valid and will be prevented by the DCM interface. -% Finally, note that only models with exactly the same A,B,C(,D) structure +% Finally, note that only models with exactly the same A,B,C(,D) structure % and the same brain regions can be averaged. % -% A Bayesian random effects analysis can be implemented for a -% particular contrast using the spm_dcm_sessions.m function +% A Bayesian random effects analysis can be implemented for a particular +% contrast using the spm_dcm_sessions.m function. %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Will Penny & Klaas Enno Stephan -% $Id: spm_dcm_average.m 3672 2010-01-12 12:27:38Z guillaume $ +% $Id: spm_dcm_average.m 3723 2010-02-12 15:15:18Z guillaume $ - -if nargin <= 1 - % Function called without parameters (e.g. via GUI) - %---------------------------------------------------------------------- - Finter = spm_figure('GetWin','Interactive'); - set(Finter,'name','Dynamic Causal Modeling') - header = get(Finter,'Name'); - WS = spm('WinScale'); - num_models = spm_input('How many DCM models to average ? ','+1','r',[],1); - P = spm_select(num_models,'^DCM.*\.mat$','Select DCM*.mat files'); - name = spm_input('Name for DCM_avg_???.mat','+1','s'); - if nargin < 1 - mtype = spm_input('fMRI or ERP?',1,'b',{'fMRI','ERP'},[1 0]); - end -else - num_models = size(P,1); +try + P; +catch + [P, sts] = spm_select([2 Inf],'^DCM.*\.mat$','Select DCM*.mat files'); + if ~sts, return; end end -if nargin<4 - Nowarning = 0; +try + name; +catch + name = spm_input('Name for DCM_avg_???.mat','+1','s'); end -% Loop through all selected models and get posterior means and variances -% ------------------------------------------------------------------------- -for model = 1:num_models, - load(P(model,:),'-mat'); - - % Only look at those parameters with non-zero prior covariance +if ischar(P), P = cellstr(P); end +N = numel(P); + +%-Loop through all selected models and get posterior means and precisions +%========================================================================== +for model = 1:N + + load(P{model}); + + % Only look at those parameters with non-zero prior variance + %---------------------------------------------------------------------- pCdiag = diag(DCM.M.pC); - wsel = find(~(pCdiag==0)); - + wsel = find(pCdiag); + if model == 1 wsel_first = wsel; - DCM_first = DCM; - % determine number of inputs and regions - if mtype - % DCM for fMRI - if isfield(DCM,'D') - nonLin = 1; - else - nonLin = 0; - end - - m = DCM.M.m; % number of inputs - n = DCM.n; % number of regions - % Only look at A,B,C values - % & ignore hemodynamics (last 6*n parameters, if lin model) - if nonLin - % but keep the D values if present ! - npABC = n*n + n*n*m + n*m + 1 ; % nr of parameters in A,B,C+1 - cwsel = wsel; cwsel(max(find(wsel<=npABC))+(1:6*n))=[]; - else - cwsel = wsel(1:end-6*n); - end - else - % DCM for ERP - m = size(DCM.Qp.C,2); % number of inputs - n = size(DCM.Qp.C,1); % number of sources - cwsel = wsel(1:end); - end + DCM_first = DCM; else - if ~(length(wsel)==length(wsel_first)) - disp('Error in spm_dcm_average: DCM models must have same input, intrinsic and modulatory structure'); - return - end - if ~(wsel==wsel_first) - disp('Error in spm_dcm_average: DCM models must have same input, intrinsic and modulatory structure'); - return + if length(wsel) ~= length(wsel_first) || any(wsel ~= wsel_first) + error('DCMs must have same structure.'); end end - - % Get posterior precision matrix from model - miCp(:,:,model) = inv(full(DCM.Cp(cwsel,cwsel))); - % Get posterior mean from model - mEp(:,model) = full(DCM.Ep(cwsel)); + + % Get posterior precision matrix and mean + %------------------------------------------------------------------- + Cp = DCM.Cp; + Ep = spm_vec(DCM.Ep); + miCp(:,:,model) = inv(full(Cp(wsel,wsel))); + mEp(:,model) = full(Ep(wsel)); + end -% Average models using Bayesian fixed effects analysis -> average Ep,Cp -%-------------------------------------------------------------------------- +%-Average models using Bayesian fixed-effects analysis -> average Ep,Cp +%========================================================================== + % averaged posterior covariance -final_iCp = sum(miCp,3); -Cp = inv(final_iCp); +%-------------------------------------------------------------------------- +Cp(wsel,wsel) = inv(sum(miCp,3)); + % averaged posterior mean -weighted_Ep = zeros(length(cwsel),1); -for model = 1:num_models, - weighted_Ep = weighted_Ep + miCp(:,:,model)*mEp(:,model); -end -Ep = Cp*weighted_Ep; - -% Copy contents of first DCM into the output DCM and insert averaged values into parameter & covariance vectors -DCM = DCM_first; -DCM.models = P; -DCM.Ep(cwsel) = Ep; -DCM.Cp(cwsel,cwsel) = Cp; - -% Now reshape into parameters, variances and probabilities -if mtype - % DCM for fMRI - if nonLin - [A, B, C, H, D] = spm_dcm_reshape(DCM.Ep,m,n,1); - else - [A, B, C] = spm_dcm_reshape(DCM.Ep,m,n,1); - end - T = 0; - sw = warning('off','SPM:negativeVariance'); - pp = 1 - spm_Ncdf(T,abs(DCM.Ep),diag(DCM.Cp)); - warning(sw); - if nonLin - [pA pB pC pH pD] = spm_dcm_reshape(pp,m,n,1); - else - [pA pB pC] = spm_dcm_reshape(pp,m,n,1); - end - vv = diag(DCM.Cp); - if nonLin - [vA vB vC vH vD] = spm_dcm_reshape(vv,m,n,1); - else - [vA vB vC] = spm_dcm_reshape(vv,m,n,1); - end - % store in DCM data structure - DCM.A = A; - DCM.B = B; - DCM.C = C; - DCM.pA = pA; - DCM.pB = pB; - DCM.pC = pC; - DCM.vA = vA; - DCM.vB = vB; - DCM.vC = vC; - if nonLin - DCM.D = D; - DCM.pD = pD; - DCM.vD = vD; - end -else - % DCM for ERP - % get priors (note: these are the priors of the first model) - if isfield(M, 'dipfit') - % model with parameterised leadfield - [pE,pC] = spm_erp_priors(DCM.A,DCM.B,DCM.C,M.dipfit,DCM.xU.dur); - else - % model w/ static leadfield - L = xY.S'*DCM.L; - [pE,pC] = spm_erp_priors(DCM.A,DCM.B,DCM.C,M.dipfit,DCM.xU.dur); - end - % store in DCM data structure - sw = warning('off','SPM:negativeVariance'); - Pp = 1 - spm_Ncdf(0,abs(spm_vec(DCM.Ep) - spm_vec(pE)),diag(DCM.Cp)); - warning(sw); - DCM.Pp = spm_unvec(Pp,pE); - DCM.Qp = DCM.Ep; - DCM.averaged = 1; +%-------------------------------------------------------------------------- +pE = DCM.Ep; +wEp = 0; +for model=1:N + wEp = wEp + miCp(:,:,model) * mEp(:,model); end +Ep(wsel) = Cp(wsel,wsel) * wEp; +Ep = spm_unvec(Ep,pE); -% Remove or rename fields with subject-specific information (e.g. predicted/observed data) -% to prevent the impression that these have also been averaged and set a flag -% indicating that this is an averaged DCM. -if mtype - % DCM for fMRI - try - % DCMs computed with SPM5 - DCM.Y = rmfield (DCM.Y,{'y','X0','Ce'}); - DCM.U = rmfield (DCM.U,{'u'}); - DCM = rmfield (DCM,{'y','xY','F','AIC','BIC','R','H1','H2','K1','K2','Ce','T'}); - catch - % minimum: remove time series - Y = rmfield(DCM.Y,{'dt','X0','y','Q'}); - DCM = rmfield (DCM,{'y','Y'}); - DCM.Y = Y; - end -else - % DCM for ERPs - try - DCM = rmfield (DCM,{'options','Y','U','L','xY','xU','H','Hc','K','R','Rc','Ce','F'}); - catch % cp: to be checked !!! - Y = rmfield(DCM.Y,{'dt','X0','y','Q'}); - DCM = rmfield (DCM,{'Y','xY'}); - DCM.Y = Y; - end -end -DCM.averaged = 1; - - -% Save new DCM +%-Copy contents of first DCM into the output DCM and add BPA +%========================================================================== +DCM = DCM_first; +DCM.models = char(P); +DCM.averaged = true; + +% compute posterior probabilities and variance %-------------------------------------------------------------------------- +sw = warning('off','SPM:negativeVariance'); +Vp = diag(Cp); +Pp = 1 - spm_Ncdf(0,abs(spm_vec(Ep) - spm_vec(pE)),Vp); +warning(sw); + +DCM.Ep = Ep; +DCM.Cp = Cp; +DCM.Vp = spm_unvec(Vp,pE); +DCM.Pp = spm_unvec(Pp,pE); + + +%-Save new DCM +%========================================================================== DCM.name = [name ' (Bayesian FFX average)']; if spm_matlab_version_chk('7') >= 0 save(['DCM_avg_' name], 'DCM', '-V6'); else save(['DCM_avg_' name], 'DCM'); -end; - -% If called through GUI, prompt user that averaging is finished -%-------------------------------------------------------------------------- -if nargin <= 1 - spm_clf - spm('FigName',header); - spm('Pointer','Arrow') - spm_input(['Results of averaging DCMs were saved in DCM_avg_' name],1,'d') end % Warn the user how this average DCM should NOT be used %-------------------------------------------------------------------------- -if ~Nowarning - str = {['Results of averaging DCMs were saved in DCM_avg_' name '.'], ... - ' ', ... - 'Please note that this file only contains average parameter estimates and their post. probabilities, but NOT averaged time series.', ... - ' ', ... - 'Also, note that this file can NOT be used for model comparisons.'}; - % spm_input(str,1,'bd','OK',[1],1); - spm('alert!',str,'DCM average warning') -end - +disp(['Results of averaging DCMs were saved in DCM_avg_' name '.mat.']); +disp('Please note that this file only contains average parameter estimates'); +disp('and their posterior probabilities, but NOT averaged time series.'); +disp('Also, note that this file can NOT be used for model comparisons.'); diff --git a/spm_dcm_bma.m b/spm_dcm_bma.m index 5b642aa..19ef94e 100644 --- a/spm_dcm_bma.m +++ b/spm_dcm_bma.m @@ -1,6 +1,6 @@ -function [theta, theta_sbj, Nocc] = spm_dcm_bma(post,post_indx,subj,Nsamp,oddsr) +function bma = spm_dcm_bma(post,post_indx,subj,Nsamp,oddsr) % Model-independent samples from DCM posterior -% FORMAT [theta, Nocc] = spm_dcm_bma (post,post_indx,subj,Nsamp,oddsr) +% FORMAT bma = spm_dcm_bma (post,post_indx,subj,Nsamp,oddsr) % % post [Ni x M] vector of posterior model probabilities % If Ni>1 then inference is based on subject-specific RFX posterior @@ -10,7 +10,7 @@ % oddsr posterior odds ratio for defining Occam's window (default=0, ie % all models used in average) % -% theta [Np x Nsamp] posterior density matrix. Parameter vector is of +% Ep [Np x Nsamp] posterior density matrix. Parameter vector is of % dimension Np and there are Nsamp samples % Nocc Number of models in Occam's window % @@ -23,128 +23,145 @@ % Copyright (C) 2009 Wellcome Trust Centre for Neuroimaging % Will Penny -% $Id: spm_dcm_bma.m 3669 2010-01-11 11:17:20Z maria $ +% $Id: spm_dcm_bma.m 3966 2010-07-02 11:54:42Z maria $ if nargin < 4 || isempty(Nsamp) - Nsamp=1e3; + Nsamp = 1e3; end if nargin < 5 || isempty(oddsr) - oddsr=0; + oddsr = 0; end -Nsub=length(subj); -Nses=length(subj(1).sess); +Nsub = length(subj); +Nses = length(subj(1).sess); % Number of regions load(subj(1).sess(1).model(1).fname); -nreg = DCM.n; -m = DCM.M.m; +if isfield(DCM,'a') + dcm_fmri = 1; + nreg = DCM.n; + min = DCM.M.m; +else + dcm_fmri = 0; +end -theta=[]; +Ep = []; +[Ni M] = size(post); -[Ni M]=size(post); if Ni > 1 - rfx=1; + rfx = 1; else - rfx=0; + rfx = 0; end if rfx - for i=1:Ni, - mp=max(post(i,:)); - post_ind{i}=find(post(i,:)>mp*oddsr); - Nocc(i)=length(post_ind{i}); + + for i = 1:Ni, + + mp = max(post(i,:)); + post_ind{i} = find(post(i,:)>mp*oddsr); + Nocc(i) = length(post_ind{i}); disp(' '); disp(sprintf('Subject %d has %d models in Occams window',i,Nocc(i))); - if Nocc(i)==0, + + if Nocc(i) == 0, return; end - for occ=1:Nocc(i), - m=post_ind{i}(occ); + for occ = 1:Nocc(i), + m = post_ind{i}(occ); disp(sprintf('Model %d, =%1.2f',m,post(i,m))); end % Renormalise post prob to Occam group - renorm(i).post=post(i,post_ind{i}); - sp=sum(renorm(i).post,2); - renorm(i).post=renorm(i).post./(sp*ones(1,Nocc(i))); + renorm(i).post = post(i,post_ind{i}); + sp = sum(renorm(i).post,2); + renorm(i).post = renorm(i).post./(sp*ones(1,Nocc(i))); % Load DCM posteriors for models in Occam's window - for kk=1:Nocc(i), + for kk = 1:Nocc(i), - sel=post_indx(post_ind{i}(kk)); - - if ~exist('max_Ep_length','var') - max_Ep_length = length(subj(i).sess(1).model(sel).Ep); - elseif (max_Ep_length 1 - - for ss=1:Nses - clear miCp mEp - - sess_model.Ep=subj(i).sess(ss).model(sel).Ep; - sess_model.Cp=full(subj(i).sess(ss).model(sel).Cp); - - pCdiag = diag(sess_model.Cp); - wsel = find(~(pCdiag==0)); + + clear miCp mEp + disp('Averaging sessions...') + + for ss = 1:Nses - if subj(i).sess(ss).model(sel).nonLin - % but keep the D values if present ! - npABC = n*n + n*n*m + n*m + 1 ; % nr of parameters in A,B,C+1 - cwsel = wsel; cwsel(max(find(wsel<=npABC))+(1:6*n))=[]; + % Only parameters with non-zero prior variance + %------------------------------------------------------ + sess_model.Cp = full(subj(i).sess(ss).model(sel).Cp); + pCdiag = diag(full(sess_model.Cp)); + wsel = find(pCdiag); + + if ss == 1 + wsel_first = wsel; else - cwsel = wsel(1:end-6*nreg); + if ~(length(wsel) == length(wsel_first)) + disp('Error: DCMs must have same structure'); + return + end + if ~(wsel == wsel_first) + disp('Error: DCMs must have same structure'); + return + end end - - % Get posterior precision matrix from model - miCp(:,:,ss) = inv(full(sess_model.Cp(cwsel,cwsel))); - % Get posterior mean from model - mEp(:,ss) = full(sess_model.Ep(cwsel)); - + + % Get posterior precision matrix and mean + %------------------------------------------------------ + Cp = sess_model.Cp; + Ep = spm_vec(subj(i).sess(ss).model(sel).Ep); + miCp(:,:,ss) = inv(full(Cp(wsel,wsel))); + mEp(:,ss) = full(Ep(wsel)); + end - % Average models using Bayesian fixed effects analysis -> average Ep,Cp - % averaged posterior covariance - final_iCp = sum(miCp,3); - Cp = inv(final_iCp); - % averaged posterior mean - weighted_Ep = zeros(length(cwsel),1); - for ss = 1:Nses, - weighted_Ep = weighted_Ep + miCp(:,:,ss)*mEp(:,ss); + % Average models using Bayesian fixed-effects analysis + %========================================================== + Cp(wsel,wsel) = inv(sum(miCp,3)); + + pE = subj(i).sess(ss).model(sel).Ep; + weighted_Ep = 0; + for s = 1:Nses + weighted_Ep = weighted_Ep + miCp(:,:,s)*mEp(:,s); end - Ep = Cp*weighted_Ep; - - params(i).model(kk).Ep(cwsel)=Ep; - params(i).model(kk).Cp(cwsel,cwsel)=Cp; + Ep(wsel) = Cp(wsel,wsel)*weighted_Ep; + vEp = Ep; + Ep = spm_unvec(Ep,pE); + params(i).model(kk).Ep = Ep; + params(i).model(kk).vEp = vEp; + params(i).model(kk).Cp = Cp; + end [evec, eval] = eig(params(i).model(kk).Cp); - deig=diag(eval); + deig = diag(eval); - params(i).model(kk).dCp=deig; - params(i).model(kk).vCp=evec; + params(i).model(kk).dCp = deig; + params(i).model(kk).vCp = evec; end end else % Find models in Occam's window - mp=max(post); - post_ind=find(post>mp*oddsr); - Nocc=length(post_ind); + mp = max(post); + post_ind = find(post>mp*oddsr); + Nocc = length(post_ind); disp(' '); disp(sprintf('%d models in Occams window',Nocc)); - if Nocc==0, return; end - for occ=1:Nocc, - m=post_ind(occ); + + if Nocc == 0, return; end + + for occ = 1:Nocc, + m = post_ind(occ); disp(sprintf('Model %d, p(m|Y)=%1.2f',m,post(m))); end @@ -154,74 +171,102 @@ % Load DCM posteriors for models in Occam's window for n=1:Nsub, + for kk=1:Nocc, - sel=post_indx(post_ind(kk)); - if ~exist('max_Ep_length','var') - max_Ep_length = length(subj(n).sess(1).model(sel).Ep); - elseif (max_Ep_length 1 - for ss=1:Nses - clear miCp mEp + clear miCp mEp + disp('Averaging sessions...') + + % Average sessions + for ss = 1:Nses - sess_model.Ep=subj(n).sess(ss).model(sel).Ep; - sess_model.Cp=full(subj(n).sess(ss).model(sel).Cp); - - pCdiag = diag(sess_model.Cp); - wsel = find(~(pCdiag==0)); + % Only parameters with non-zero prior variance + %------------------------------------------------------ + sess_model.Cp = full(subj(n).sess(ss).model(sel).Cp); + pCdiag = diag(full(sess_model.Cp)); + wsel = find(pCdiag); - if subj(n).sess(ss).model(sel).nonLin - % but keep the D values if present ! - npABC = n*n + n*n*m + n*m + 1 ; % nr of parameters in A,B,C+1 - cwsel = wsel; cwsel(max(find(wsel<=npABC))+(1:6*n))=[]; + if ss == 1 + wsel_first = wsel; else - cwsel = wsel(1:end-6*nreg); + if ~(length(wsel) == length(wsel_first)) + disp('Error: DCMs must have same structure'); + return + end + if ~(wsel == wsel_first) + disp('Error: DCMs must have same structure'); + return + end end - - % Get posterior precision matrix from model - miCp(:,:,ss) = inv(full(sess_model.Cp(cwsel,cwsel))); - % Get posterior mean from model - mEp(:,ss) = full(sess_model.Ep(cwsel)); - + + % Get posterior precision matrix and mean + %------------------------------------------------------ + Cp = sess_model.Cp; + Ep = spm_vec(subj(n).sess(ss).model(sel).Ep); + miCp(:,:,ss) = inv(full(Cp(wsel,wsel))); + mEp(:,ss) = full(Ep(wsel)); + end - % Average models using Bayesian fixed effects analysis -> average Ep,Cp - % averaged posterior covariance - final_iCp = sum(miCp,3); - Cp = inv(final_iCp); - % averaged posterior mean - weighted_Ep = zeros(length(cwsel),1); - for ss = 1:Nses, - weighted_Ep = weighted_Ep + miCp(:,:,ss)*mEp(:,ss); + % Average models using Bayesian fixed-effects analysis + %========================================================== + Cp(wsel,wsel) = inv(sum(miCp,3)); + + pE = subj(n).sess(ss).model(sel).Ep; + weighted_Ep = 0; + for s = 1:Nses + weighted_Ep = weighted_Ep + miCp(:,:,s)*mEp(:,s); end - Ep = Cp*weighted_Ep; - - params(n).model(kk).Ep(cwsel)=Ep; - params(n).model(kk).Cp(cwsel,cwsel)=Cp; + Ep(wsel) = Cp(wsel,wsel)*weighted_Ep; + vEp = Ep; + Ep = spm_unvec(Ep,pE); + + params(n).model(kk).Ep = Ep; + params(n).model(kk).vEp = vEp; + params(n).model(kk).Cp = Cp; - end + end [evec, eval] = eig(params(n).model(kk).Cp); - deig=diag(eval); + deig = diag(eval); - params(n).model(kk).dCp=deig; - params(n).model(kk).vCp=evec; + params(n).model(kk).dCp = deig; + params(n).model(kk).vCp = evec; end end + end % Pre-allocate sample arrays -Np = max_Ep_length; -theta_all = zeros(Np,Nsub); +Np = length(params(1).model(1).vEp); +% get dimensions of a b c d parameters +if dcm_fmri + + Nr = nreg*nreg; + dimd = size(params(1).model(1).Ep.D,3); + Np = Nr + Nr*min + nreg*min + Nr*dimd; + + Etmp.A = zeros(nreg,nreg,Nsamp); + Etmp.B = zeros(nreg,nreg,min,Nsamp); + Etmp.C = zeros(nreg,min,Nsamp); + Etmp.D = zeros(nreg,nreg,dimd,Nsamp); + + dima = Nr; + dimb = Nr+Nr*min; + dimc = Nr+Nr*min+nreg*min; + +end + +clear Ep disp('') disp('Averaging models in Occams window...') for i=1:Nsamp @@ -231,34 +276,52 @@ end % Pick parameters from model for each subject for n=1:Nsub + if rfx m = spm_multrnd(renorm(n).post,1); end - mu = params(n).model(m).Ep; - mu(end:max_Ep_length) = 0; - mu = spm_vec(mu); - - dim1 = size(params(n).model(m).dCp); - dsig = zeros(max_Ep_length,1); - dsig(1:dim1,1) = params(n).model(m).dCp; + mu = params(n).model(m).vEp; + dsig = params(n).model(m).dCp(:,1); + vsig(:,:) = params(n).model(m).vCp(:,:); - [dim1,dim2] = size(params(n).model(m).vCp); - vsig = zeros(max_Ep_length,max_Ep_length); - vsig(1:dim1,1:dim2) = params(n).model(m).vCp; - tmp = spm_normrnd(mu,{dsig,vsig},1); - theta_all(:,n) = tmp(:); - + Ep_all(:,n) = tmp(:); + Ep_sbj(:,n,i) = Ep_all(:,n); + end % Average over subjects - if Nsub>1 - theta(:,i) = mean(theta_all,2); - theta_sbj(:,:,i) = theta_all; - else - theta(:,i) = theta_all; - theta_sbj(:,i) = theta_all; - end + Ep(:,i) = mean(Ep_all,2); + +end + +% save mean parameters +Ep_avg = mean(Ep,2); +Ep_std = std(Ep,0,2); +Ep_avg = spm_unvec(Ep_avg,params(1).model(1).Ep); +Ep_std = spm_unvec(Ep_std,params(1).model(1).Ep); +bma.mEp = Ep_avg; +bma.sEp = Ep_std; + +Ep_avgsbj = mean(Ep_sbj,3); +Ep_stdsbj = std(Ep_sbj,0,3); + +for is=1:Nsub + bma.mEps(is)=spm_unvec(Ep_avgsbj(:,is),params(1).model(1).Ep); + bma.sEps(is)=spm_unvec(Ep_stdsbj(:,is),params(1).model(1).Ep); +end + +if dcm_fmri + bma.a = spm_unvec(Ep(1:dima,:),Etmp.A); + bma.b = spm_unvec(Ep(dima+1:dimb,:),Etmp.B); + bma.c = spm_unvec(Ep(dimb+1:dimc,:),Etmp.C); + bma.d = spm_unvec(Ep(dimc+1:Np,:),Etmp.D); end +% storing parameters +% ------------------------------------------------------------------------- +bma.nsamp = Nsamp; +bma.oddsr = oddsr; +bma.Nocc = Nocc; +bma.Mocc = post_ind; diff --git a/spm_dcm_bma_results.m b/spm_dcm_bma_results.m index 91a251e..d3ffcd1 100644 --- a/spm_dcm_bma_results.m +++ b/spm_dcm_bma_results.m @@ -1,86 +1,69 @@ -function spm_dcm_bma_results (BMS,mod_in,drive_in,method) +function spm_dcm_bma_results(BMS,method) % Plot histograms from BMA for selected modulatory and driving input -% FORMAT spm_dcm_bma_results (BMS,mod_in,drive_in,method) +% FORMAT spm_dcm_bma_results(BMS,mod_in,drive_in,method) % % Input: -% BMS - BMS.mat file -% mod_in - modulatory input -% drive_in - driving input +% BMS - BMS.mat file % method - inference method (FFX or RFX) -%_______________________________________________________________________ +%__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Maria Joao -% $Id: spm_dcm_bma_results.m 3636 2009-12-11 14:31:26Z maria $ - -if nargin < 6 - % function called without parameters (e.g. via GUI) - %---------------------------------------------------------------------- - Finter = spm_figure('GetWin','Interactive'); - spm_clf(Finter); - set(Finter,'name','Dynamic Causal Modeling'); - - header = get(Finter,'Name'); - WS = spm('WinScale'); - fname = spm_select([1 1],'^BMS.mat$','select BMS.mat file'); - - mod_input = spm_input('Select modulatory input ? ',1,'r',[],1); - drive_input = spm_input('Select driving input ? ','+1','r',[],1); - method = spm_input('Inference method','+1','b','FFX|RFX',['ffx';'rfx']); +% $Id: spm_dcm_bma_results.m 3853 2010-04-29 14:54:43Z christophe $ + +if nargin < 1 + fname = spm_select(1,'^BMS.mat$','select BMS.mat file'); else - % use function arguments - %---------------------------------------------------------------------- - mod_input = mod_in; - drive_input = drive_in; - fname = BMS; + fname = BMS; end - % load BMS file %-------------------------------------------------------------------------- load(fname) -nonLin = 0; +% Check BMS/BMA method used +%-------------------------------------------------------------------------- +if nargin < 2 + ff = fieldnames(BMS.DCM); + Nff = numel(ff); + if Nff==2 + method = spm_input('Inference method','+1','b','FFX|RFX',['ffx';'rfx']); + else % pick the one available if only one method + method = char(ff); + end +end + % select method %-------------------------------------------------------------------------- if isfield(BMS.DCM,method) switch method case 'ffx' - if isempty(BMS.DCM.ffx.bma) - error('No BMA analysis for FFX in BMS file!'); - else - Nsamp = BMS.DCM.ffx.bma.nsamp; - amat = BMS.DCM.ffx.bma.a; - bmat = BMS.DCM.ffx.bma.b; - cmat = BMS.DCM.ffx.bma.c; - if isfield(BMS.DCM.ffx.bma,'d') - dmat = BMS.DCM.ffx.bma.d; - mod_reg = spm_input('Select modulating region ? ','+1','r',[],1); - nonLin = 1; - end - - end - disp('Loading model space...') - load(BMS.DCM.ffx.data) - load(subj(1).sess(1).model(1).fname) - + if isempty(BMS.DCM.ffx.bma) + error('No BMA analysis for FFX in BMS file!'); + else + + Nsamp = BMS.DCM.ffx.bma.nsamp; + amat = BMS.DCM.ffx.bma.a; + bmat = BMS.DCM.ffx.bma.b; + cmat = BMS.DCM.ffx.bma.c; + dmat = BMS.DCM.ffx.bma.d; + end + disp('Loading model space...') + load(BMS.DCM.ffx.data) + load(subj(1).sess(1).model(1).fname) + case 'rfx' - if isempty(BMS.DCM.rfx.bma) - error('No BMA analysis for RFX in BMS file!'); - else - Nsamp = BMS.DCM.rfx.bma.nsamp; - amat = BMS.DCM.rfx.bma.a; - bmat = BMS.DCM.rfx.bma.b; - cmat = BMS.DCM.rfx.bma.c; - if isfield(BMS.DCM.rfx.bma,'d') - dmat = BMS.DCM.rfx.bma.d; - mod_reg = spm_input('Select modulating region ? ','+1','r',[],1); - nonLin = 1; - end - - end - disp('Loading model space...') - load(BMS.DCM.rfx.data) - load(subj(1).sess(1).model(1).fname) + if isempty(BMS.DCM.rfx.bma) + error('No BMA analysis for RFX in BMS file!'); + else + Nsamp = BMS.DCM.rfx.bma.nsamp; + amat = BMS.DCM.rfx.bma.a; + bmat = BMS.DCM.rfx.bma.b; + cmat = BMS.DCM.rfx.bma.c; + dmat = BMS.DCM.rfx.bma.d; + end + disp('Loading model space...') + load(BMS.DCM.rfx.data) + load(subj(1).sess(1).model(1).fname) end else msgbox(sprintf('No %s analysis in current BMS.mat file!',method)) @@ -89,13 +72,43 @@ function spm_dcm_bma_results (BMS,mod_in,drive_in,method) % number of regions, mod. inputs and names %-------------------------------------------------------------------------- -n = size(amat,2); -m = size(bmat,3); +n = size(amat,2); % #region +m = size(bmat,3); % #drv/mod inputs mi = size(cmat,2); -% check if input is correct -if mod_input > m || drive_input > mi - error('Incorrect choice for driving or modulatory input!'); +% Look for modulatory inputs +mod_input = []; +for ii=1:m + % look for bits of B not full of zeros + tmp = squeeze(bmat(:,:,ii,:)); + if any(tmp(:)) + mod_input = [mod_input ii]; + end +end +% Look for effective driving inputs +drive_input = []; +for ii=1:m + % look for bits of not full of zeros + tmp = any(cmat(:,ii,:)); + if sum(tmp) + drive_input = [drive_input ii]; + end +end + +% Non linear model ? If so find the driving regions +if ~isempty(dmat) + nonLin = 1; + mod_reg = []; + for ii=1:n + % look for bits of D not full of zeros + tmp = squeeze(dmat(:,:,ii,:)); + if any(tmp(:)) + mod_reg = [mod_reg ii]; + end + end +else + nonLin = 0; + mod_reg = []; end if isfield(DCM.Y,'name') @@ -109,7 +122,7 @@ function spm_dcm_bma_results (BMS,mod_in,drive_in,method) end end -bins = Nsamp/100; +bins = Nsamp/100; % intrinsic connection density %-------------------------------------------------------------------------- @@ -120,10 +133,8 @@ function spm_dcm_bma_results (BMS,mod_in,drive_in,method) usd.amat = amat; usd.bmat = bmat; usd.cmat = cmat; -if nonLin - usd.dmat = dmat; - usd.mod_reg = drive_input; -end +usd.dmat = dmat; + usd.region = region; usd.n = n; usd.m = m; @@ -131,20 +142,33 @@ function spm_dcm_bma_results (BMS,mod_in,drive_in,method) usd.FS = FS; usd.drive_input = drive_input; usd.mod_input = mod_input; +if nonLin + usd.mod_reg = mod_reg; +end usd.bins = bins; usd.Nsamp = Nsamp; set(F,'userdata',usd); clf(F); -if nonLin - labels = {'a: int.','b: mod.','c: inp.', 'd: non.'}; - callbacks = {@plot_a,@plot_b,@plot_c,@plot_d}; -else - labels = {'a: int.','b: mod.','c: inp.'}; - callbacks = {@plot_a,@plot_b,@plot_c}; +labels = {'a: int.'}; +callbacks = {@plot_a}; +for ii = mod_input + labels{end+1} = ['b: mod. i#',num2str(ii)]; + callbacks{end+1} = @plot_b; +end +for ii = drive_input + labels{end+1} = ['c: drv. i#',num2str(ii)]; + callbacks{end+1} = @plot_c; end +if nonLin + for ii = mod_reg + labels{end+1} = ['d: mod. r#',num2str(ii)]; + callbacks{end+1} = @plot_d; + end +end + [handles] = spm_uitab(F,labels,callbacks,'BMA_parameters',1); set(handles.htab,'backgroundcolor',[1 1 1]) @@ -154,8 +178,7 @@ function spm_dcm_bma_results (BMS,mod_in,drive_in,method) feval(@plot_a,F) -end - +%========================================================================== function plot_a(F) try @@ -185,16 +208,11 @@ function plot_a(F) axis off else hist(ud.amat(i,j,:),ud.bins,'r'); - amax = max(ud.amat(i,j,:)); + amax = max(abs(ud.amat(i,j,:)))*1.05; % enlarge scale by 5% if amax > 0 xlim([-amax amax]) - else - if amax < 0 - amin = min(ud.amat(i,j,:)); - xlim([amin amax]) - else - xlim([-10 10]) - end + else % case where parameter is constrained to be 0. + xlim([-10 10]) end set(gca,'YTickLabel',[]); set(gca,'FontSize',12); @@ -203,9 +221,8 @@ function plot_a(F) end end -end - -function plot_b() +%========================================================================== +function plot_b hf = get(gco,'parent'); ud = get(hf,'userdata'); @@ -215,7 +232,14 @@ function plot_b() delete(hc) end -titlewin = 'BMA: modulatory connections (b)'; +% spot the bmod input index from the fig name +ht = intersect(findobj('style','pushbutton'),get(hf,'children')); +it = strmatch('bold',get(ht,'Fontweight')); +t_str = get(ht(it),'string'); +b_ind = str2num(t_str(strfind(t_str,'#')+1:end)); +i_mod = find(ud.mod_input==b_ind); + +titlewin = ['BMA: modulatory connections (b',num2str(b_ind),')']; hTitAx = axes('Parent',hf,'Position',[0.2,0.04,0.6,0.02],... 'Visible','off','tag','bma_results'); text(0.55,0,titlewin,'Parent',hTitAx,'HorizontalAlignment','center',... @@ -228,17 +252,12 @@ function plot_b() if (i==j) axis off else - hist(ud.bmat(i,j,ud.mod_input,:),ud.bins,'r'); - bmax = max(ud.bmat(i,j,ud.mod_input,:)); + hist(ud.bmat(i,j,ud.mod_input(i_mod),:),ud.bins,'r'); + bmax = max(abs(ud.bmat(i,j,ud.mod_input(i_mod),:)))*1.05; % enlarge scale by 5% if bmax > 0 xlim([-bmax bmax]) - else - if bmax < 0 - bmin = min(ud.bmat(i,j,ud.mod_input,:)); - xlim([bmin bmax]) - else - xlim([-10 10]) - end + else % case where parameter is constrained to be 0. + xlim([-10 10]) end set(gca,'YTickLabel',[]); set(gca,'FontSize',12); @@ -247,10 +266,8 @@ function plot_b() end end - -end - -function plot_c() +%========================================================================== +function plot_c hf = get(gco,'parent'); ud = get(hf,'userdata'); @@ -260,7 +277,14 @@ function plot_c() delete(hc) end -titlewin = 'BMA: input connections (c)'; +% spot the c_drv input index from the fig name +ht = intersect(findobj('style','pushbutton'),get(hf,'children')); +it = strmatch('bold',get(ht,'Fontweight')); +t_str = get(ht(it),'string'); +c_ind = str2num(t_str(strfind(t_str,'#')+1:end)); +i_drv = find(ud.drive_input==c_ind); + +titlewin = ['BMA: input connections (c',num2str(c_ind),')']; hTitAx = axes('Parent',hf,'Position',[0.2,0.04,0.6,0.02],... 'Visible','off','tag','bma_results'); text(0.55,0,titlewin,'Parent',hTitAx,'HorizontalAlignment','center',... @@ -268,20 +292,15 @@ function plot_c() for j=1:ud.n, subplot(1,ud.n,j); - if length(find(ud.cmat(j,ud.drive_input,:)==0))==ud.Nsamp + if length(find(ud.cmat(j,ud.drive_input(i_drv),:)==0))==ud.Nsamp plot([0 0],[0 1],'k'); else - hist(ud.cmat(j,ud.drive_input,:),ud.bins,'r'); - cmax = max(ud.cmat(j,ud.drive_input,:)); + hist(ud.cmat(j,ud.drive_input(i_drv),:),ud.bins,'r'); + cmax = max(abs(ud.cmat(j,ud.drive_input(i_drv),:)))*1.05; % enlarge scale by 5% if cmax > 0 - xlim([-cmax cmax]) - else - if cmax < 0 - cmin = min(ud.cmat(j,ud.drive_input,:)); - xlim([cmin cmax]) - else - xlim([-10 10]) - end + xlim([-cmax cmax]) + else % case where parameter is constrained to be 0. + xlim([-10 10]) end end set(gca,'YTickLabel',[]); @@ -289,9 +308,8 @@ function plot_c() title(sprintf('%s ',ud.region(j).name)); end -end - -function plot_d() +%========================================================================== +function plot_d hf = get(gco,'parent'); ud = get(hf,'userdata'); @@ -301,7 +319,14 @@ function plot_d() delete(hc) end -titlewin = 'BMA: non-linear connections (d)'; +% spot the d_reg input index from the fig name +ht = intersect(findobj('style','pushbutton'),get(hf,'children')); +it = strmatch('bold',get(ht,'Fontweight')); +t_str = get(ht(it),'string'); +d_ind = str2num(t_str(strfind(t_str,'#')+1:end)); +i_mreg = find(ud.mod_reg==d_ind); + +titlewin = ['BMA: non-linear connections (d',num2str(d_ind),')']; hTitAx = axes('Parent',hf,'Position',[0.2,0.04,0.6,0.02],... 'Visible','off','tag','bma_results'); text(0.55,0,titlewin,'Parent',hTitAx,'HorizontalAlignment','center',... @@ -314,17 +339,12 @@ function plot_d() if (i==j) axis off else - hist(ud.bmat(i,j,ud.mod_input,:),ud.bins,'r'); - bmax = max(ud.dmat(i,j,ud.mod_input,:)); - if bmax > 0 - xlim([-bmax bmax]) - else - if bmax < 0 - bmin = min(ud.dmat(i,j,ud.mod_reg,:)); - xlim([bmin bmax]) - else - xlim([-10 10]) - end + hist(ud.dmat(i,j,ud.mod_reg(i_mreg),:),ud.bins,'r'); + dmax = max(abs(ud.dmat(i,j,ud.mod_reg(i_mreg),:)))*1.05; % enlarge scale by 5% + if dmax > 0 + xlim([-dmax dmax]) + else % case where parameter is constrained to be 0. + xlim([-10 10]) end set(gca,'YTickLabel',[]); set(gca,'FontSize',12); @@ -332,5 +352,3 @@ function plot_d() end end end - -end \ No newline at end of file diff --git a/spm_dcm_contrasts.m b/spm_dcm_contrasts.m index 7ce79f1..3716287 100644 --- a/spm_dcm_contrasts.m +++ b/spm_dcm_contrasts.m @@ -1,56 +1,62 @@ -function [con_vec,con_mat] = spm_dcm_contrasts (DCM_filename,D) -% Make contrast vector for a DCM model -% FORMAT [con_vec,con_mat] = spm_dcm_contrasts (DCM_filename,D) +function [con] = spm_dcm_contrasts(DCM_filename,D) +% Make contrast vector for a DCM model +% FORMAT [con] = spm_dcm_contrasts(DCM_filename,D) % % DCM_filename DCM file name -% D 'A','B' or 'C' ie. contrast for which connectivity matrix +% D 'A','B' or 'C' i.e. connectivity matrix of interest % -% con_vec Column vector specifying contrast of parameters -% con_mat The same contrast but in matrix format -% -% The contrasts are also saved in the DCM structure -% -% DCM.contrast().con_vec -% DCM.contrast().con_mat -% DCM.contrast().con_type ('A', 'B' or 'C') +% con Column vector specifying contrast weights %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging - + % Will Penny -% $Id: spm_dcm_contrasts.m 3654 2009-12-23 20:09:54Z karl $ - - -Finter = spm_figure('GetWin','Interactive'); -header = get(Finter,'Name'); +% $Id: spm_dcm_contrasts.m 3705 2010-02-01 20:51:28Z karl $ + +% Set-up +%-------------------------------------------------------------------------- +Finter = spm_figure('GetWin','Interactive'); +header = get(Finter,'Name'); set(Finter,'Name','Dynamic Causal Modelling') -WS = spm('WinScale'); - -P = DCM_filename; -load(P); - -Y.name = DCM.Y.name; -U.name = DCM.U.name; -n = DCM.n; % number of regions -m = length(U.name); % number of inputs -a = zeros(n,n); -c = zeros(n,m); -b = zeros(n,n,m); - +WS = spm('WinScale'); + +% load DCM if necessary +%-------------------------------------------------------------------------- +try + P = DCM_filename; + load(P); +catch + DCM = DCM_filename; +end + +Y.name = DCM.Y.name; +U.name = DCM.U.name; +Ep = DCM.Ep; % MAP estimates +n = DCM.n; % number of regions +m = length(U.name); % number of inputs +a = zeros(n,n); +c = zeros(n,m); +b = zeros(n,n,m); + + +% prompt for contrast if necessary +%-------------------------------------------------------------------------- if (nargin < 2) | isempty(D) - str = 'contrast for'; - D = spm_input(str,1,'b',{'A','B','C'}); + str = 'contrast for'; + D = spm_input(str,1,'b',{'A','B','C'}); end - - + +% set object sizes +%-------------------------------------------------------------------------- dx = 35; wx = 30; wy = 20; d = uicontrol(Finter,'String','done','Position',[300 50 060 020].*WS); - + % Define left edge dialogue -% itext_left=080; -% inum_left=180; - +% itext_left = 080; +% inum_left = 180; +%-------------------------------------------------------------------------- +BackgroundColor = get(get(d,'Parent'),'Color'); itext_left = 030; inum_left = 80; name_length = 8; % number of characters in short names @@ -61,189 +67,175 @@ short_name(i).str = Y.name{i}; end end -text_top=336; - -switch D, - -case 'A' % intrinsic - - str = sprintf(... - 'Enter contrast for A: '); +text_top = 336; + +switch D + + % Get contrast weights + %====================================================================== + case 'A' % intrinsic + + str = sprintf('Enter contrast for A: '); spm_input(str,1,'d'); - - % Print names and numbers of regions - for i = 1:n - str = sprintf('%s %i',short_name(i).str,i); - h1(i) = uicontrol(Finter,'String',str,... - 'Style','text',... - 'HorizontalAlignment','right',... - 'Position',[itext_left text_top-dx*i 080 020].*WS); - h2(i) = uicontrol(Finter,'String',sprintf('%i',i),... - 'Style','text',... - 'Position',[inum_left+dx*i text_top 020 020].*WS); - end - - % Set contrast values to zero and display - for i = 1:n - for j = 1:n - cc=ceil([inum_left+dx*j text_top+4-dx*i wx wy].*WS); - h3(i,j) = uicontrol(Finter,... - 'Position',cc,... - 'Style','edit'); - set(h3(i,j),'String','0'); - - end - end - drawnow - - % wait for use to i/p contrast and press 'done' - %----------------------------------------------------------- - while(1) - pause(0.01) - if strcmp(get(gco,'Type'),'uicontrol') - if strcmp(get(gco,'String'),'done') - for i = 1:n - for j = 1:n - a(i,j) = str2num(get(h3(i,j),'string')); - end - end - delete([h1(:); h2(:); h3(:)]) - spm_input(' ',1,'d') - break - end - end - end - con_mat = a; - -case 'B' % modulatory - %--------------------------------------------------- - - for k = 1:m, - str = sprintf(... - 'Enter contrast for B: effects of input %-12s',... - U.name{k}); - spm_input(str,1,'d') - + + % Print names and numbers of regions + %------------------------------------------------------------------ for i = 1:n str = sprintf('%s %i',short_name(i).str,i); h1(i) = uicontrol(Finter,'String',str,... 'Style','text',... + 'HorizontalAlignment','right',... + 'BackgroundColor',BackgroundColor,... 'Position',[itext_left text_top-dx*i 080 020].*WS); h2(i) = uicontrol(Finter,'String',sprintf('%i',i),... - 'Style','text',... - 'Position',[inum_left+dx*i text_top 020 020].*WS); + 'Style','text',... + 'BackgroundColor',BackgroundColor,... + 'Position',[inum_left+dx*i text_top 020 020].*WS); end + + % Set contrast values to zero and display + %------------------------------------------------------------------ for i = 1:n for j = 1:n cc=ceil([inum_left+dx*j text_top+4-dx*i wx wy].*WS); h3(i,j) = uicontrol(Finter,... 'Position',cc,... + 'BackgroundColor',BackgroundColor,... 'Style','edit'); set(h3(i,j),'String','0'); + end end drawnow - - % wait for 'done' - %----------------------------------------------------------- - set(gcf,'CurrentObject',h3(1)) + + % wait for user to specify contrast weights and press 'done' + %------------------------------------------------------------------ while(1) pause(0.01) if strcmp(get(gco,'Type'),'uicontrol') if strcmp(get(gco,'String'),'done') for i = 1:n for j = 1:n - b(i,j,k) = str2num(get(h3(i,j),'string')); + a(i,j) = str2num(get(h3(i,j),'string')); end end delete([h1(:); h2(:); h3(:)]) spm_input(' ',1,'d') break - end end end - - end - con_mat = b; - -case 'C' % input - %--------------------------------------------------- - - for k = 1:m, - str = sprintf(... - 'Enter contrast for C: Effects of input %-12s',... - U.name{k}); - spm_input(str,1,'d'); - - for i = 1:n - str = sprintf('%s %i',short_name(i).str,i); - h1(i) = uicontrol(Finter,'String',str,... - 'Style','text',... - 'Position',[itext_left text_top-dx*i 080 020].*WS); - h2(i) = uicontrol(Finter,... - 'Position',[inum_left+dx text_top+4-dx*i wx wy].*WS,... - 'Style','edit'); - set(h2(i),'String','0'); + con = spm_unvec(spm_vec(Ep)*0,Ep); + con.A = a; + con = spm_vec(con); + + case 'B' % modulatory + %------------------------------------------------------------------ + for k = 1:m, + str = sprintf(... + 'Enter contrast for B: effects of input %-12s',... + U.name{k}); + spm_input(str,1,'d') + + for i = 1:n + str = sprintf('%s %i',short_name(i).str,i); + h1(i) = uicontrol(Finter,'String',str,... + 'Style','text',... + 'BackgroundColor',BackgroundColor,... + 'Position',[itext_left text_top-dx*i 080 020].*WS); + h2(i) = uicontrol(Finter,'String',sprintf('%i',i),... + 'Style','text',... + 'BackgroundColor',BackgroundColor,... + 'Position',[inum_left+dx*i text_top 020 020].*WS); + end + for i = 1:n + for j = 1:n + cc=ceil([inum_left+dx*j text_top+4-dx*i wx wy].*WS); + h3(i,j) = uicontrol(Finter,... + 'Position',cc,... + 'BackgroundColor',BackgroundColor,... + 'Style','edit'); + set(h3(i,j),'String','0'); + end + end + drawnow + + % wait for 'done' + %-------------------------------------------------------------- + set(gcf,'CurrentObject',h3(1)) + while(1) + pause(0.01) + if strcmp(get(gco,'Type'),'uicontrol') + if strcmp(get(gco,'String'),'done') + for i = 1:n + for j = 1:n + b(i,j,k) = str2num(get(h3(i,j),'string')); + end + end + delete([h1(:); h2(:); h3(:)]) + spm_input(' ',1,'d') + break + + end + end + end + end - drawnow - - % wait for 'done' - %----------------------------------------------------------- - set(gcf,'CurrentObject',h2(1)) - while(1) - pause(0.01) - if strcmp(get(gco,'Type'),'uicontrol') - if strcmp(get(gco,'String'),'done') - - % get c - %-------------------------------------------------- - for i = 1:n - c(i,k) = str2num(get(h2(i),'string')); + con = spm_unvec(spm_vec(Ep)*0,Ep); + con.B = b; + con = spm_vec(con); + + case 'C' % input + %------------------------------------------------------------------ + for k = 1:m + str = sprintf(... + 'Enter contrast for C: Effects of input %-12s',... + U.name{k}); + spm_input(str,1,'d'); + + for i = 1:n + str = sprintf('%s %i',short_name(i).str,i); + h1(i) = uicontrol(Finter,'String',str,... + 'Style','text',... + 'BackgroundColor',BackgroundColor,... + 'Position',[itext_left text_top-dx*i 080 020].*WS); + h2(i) = uicontrol(Finter,... + 'Position',[inum_left+dx text_top+4-dx*i wx wy].*WS,... + 'BackgroundColor',BackgroundColor,... + 'Style','edit'); + set(h2(i),'String','0'); + end + drawnow + + % wait for 'done' + %-------------------------------------------------------------- + set(gcf,'CurrentObject',h2(1)) + while(1) + pause(0.01) + if strcmp(get(gco,'Type'),'uicontrol') + if strcmp(get(gco,'String'),'done') + + % get c + %-------------------------------------------------- + for i = 1:n + c(i,k) = str2num(get(h2(i),'string')); + end + + delete([h1(:); h2(:)]) + spm_input(' ',1,'d') + break + end - - delete([h1(:); h2(:)]) - spm_input(' ',1,'d') - break - end end end - end - con_mat=c; - - -otherwise, - disp('Error in spm_dcm_contrasts: contrast must be for A, B or C'); - close - return + con = spm_unvec(spm_vec(Ep)*0,Ep); + con.C = c; + con = spm_vec(con); + + otherwise + disp('Error in spm_dcm_contrasts: contrast must be for A, B or C'); + close + return end - delete(d); - -% disp('Contrast:'); -% disp(con_mat); -con_vec=con_mat(:); - - -% Save contrast in DCM file -if isfield(DCM,'contrast') - num_contrast=length(DCM.contrast)+1; -else - num_contrast=1; -end -DCM.contrast(num_contrast).con_vec = con_vec; -DCM.contrast(num_contrast).con_mat = con_mat; -DCM.contrast(num_contrast).con_type = D; - -if spm_matlab_version_chk('7') >= 0 - save(P(:),'-V6','DCM'); -else - save(P(:),'DCM'); -end; - -if nargin < 2 - close -end - - diff --git a/spm_dcm_create.m b/spm_dcm_create.m index df90d45..a5805c2 100644 --- a/spm_dcm_create.m +++ b/spm_dcm_create.m @@ -1,28 +1,29 @@ -function [] = spm_dcm_create (syn_model, source_model, SNR) +function spm_dcm_create(syn_model, source_model, SNR) % Specify a DCM model without having to use an SPM.mat file -% FORMAT [] = spm_dcm_create (syn_model, source_model, SNR) +% FORMAT spm_dcm_create(syn_model, source_model, SNR) % -% syn_model name of the synthetic DCM to be created -% source_model - define new model ('GUI') or -% - import existing model via file selector ('import') -% - import existing model (directly specified by directory & -% name) -% [default: 'GUI'] -% SNR signal-to-noise ratio [default: 1] +% syn_model - name of the synthetic DCM to be created +% source_model - define new model ('GUI') +% or import existing model via file selector ('import') +% or import existing model (directly specified by directory +% and name) +% [default: 'GUI'] +% SNR - signal-to-noise ratio [default: 1] % % This function allows to create DCM networks with known connectivity -% parameters from which synthetic data are then generated by calling spm_dcm_generate. +% parameters from which synthetic data are then generated by calling +% spm_dcm_generate. % -% This function is very much like spm_dcm_ui('specify') -% but inputs etc. are specified either via the user interface or from an -% existing model. Currently, the interface provided by this function does -% not allow for manual specification of nonlinear DCMs; however, these can -% be imported from existing files. +% This function is very much like spm_dcm_specify but inputs etc. are +% specified either via the user interface or from an existing model. +% Currently, the interface provided by this function does not allow for +% manual specification of nonlinear DCMs; however, these can be imported +% from existing files. %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Will Penny & Klaas Enno Stephan -% $Id: spm_dcm_create.m 3363 2009-09-04 15:11:19Z christophe $ +% $Id: spm_dcm_create.m 3741 2010-03-01 15:35:30Z guillaume $ Finter = spm_figure('GetWin','Interactive'); @@ -31,31 +32,24 @@ WS = spm('WinScale'); % check parameters and insert default values, if necessary -%=================================================================== +%========================================================================== if nargin == 0 - syn_model = spm_input('Name for target DCM_???.mat','+1','s'); - SNR = spm_input('Signal-to-noise ratio (SNR)? ','+1','r',[],1); - source_model = 'GUI'; + syn_model = spm_input('Name for target DCM_???.mat','+1','s'); + SNR = spm_input('Signal-to-noise ratio (SNR)? ','+1','r',[],1); + source_model = 'GUI'; else - if nargin == 1 - source_model = 'GUI' - SNR = 1; - else - if nargin == 2 - SNR = 1; - end - end + try, source_model; catch source_model = 'GUI'; end + try, SNR; catch SNR = 1; end end % outputs -%=================================================================== - +%========================================================================== switch upper(source_model) case 'GUI' % Define model by GUI - %==================== + %================================================================== % get cell array of region structures %------------------------------------------------------------------ @@ -72,13 +66,12 @@ end % inputs - %=================================================================== + %================================================================== % global parameters - global defaults try - fMRI_T = defaults.stats.fmri.t; - fMRI_T0 = defaults.stats.fmri.t0; + fMRI_T = spm_get_defaults('stats.fmri.t'); + fMRI_T0 = spm_get_defaults('stats.fmri.t0'); catch fMRI_T = 16; fMRI_T0 = 1; @@ -96,13 +89,13 @@ Ui = spm_get_ons(SPM,1); - % Change input format to DCM input format and correct 32 bin offset that is inserted by spm_get_ons - % (NB: for "normal" DCMs this is corrected for in spm_dcm_ui) + % Change input format to DCM input format and correct 32 bin offset + % that is inserted by spm_get_ons + % (NB: for "normal" DCMs this is corrected for in spm_dcm_specify) U.name = {}; U.u = []; - ii = 0; for i = 1:length(Ui) - U.u = [U.u Ui(i).u(33:end,1)]; % correct 32 bin offset that is inserted (as hard coded value!) by spm_get_ons + U.u = [U.u Ui(i).u(33:end,1)]; U.name{end + 1} = Ui(i).name{1}; % any parametric modulators? if size(Ui(i).u,2) > 1 @@ -115,7 +108,7 @@ U.dt = Ui(1).dt; % graph connections - %=================================================================== + %================================================================== m = size(U.u,2); a = zeros(n,n); c = zeros(n,m); @@ -123,11 +116,11 @@ d = uicontrol(Finter,'String','done',... 'Position',[200 050 060 020].*WS); dx = 35; - wx=30; - wy=20; + wx = 30; + wy = 20; %-intrinsic connections - %------------------------------------------------------------------- + %------------------------------------------------------------------ spm_input('Specify intrinsic connections from',1,'d') spm_input('to',3,'d') @@ -158,7 +151,7 @@ drawnow % wait for 'done' - %----------------------------------------------------------- + %------------------------------------------------------------------ while(1) pause(0.01) if strcmp(get(gco,'Type'),'uicontrol') @@ -176,11 +169,11 @@ %-effects of causes - %------------------------------------------------------------------- + %------------------------------------------------------------------ for k = 1:m % buttons and labels - %----------------------------------------------------------- + %-------------------------------------------------------------- str = sprintf(... 'Effects of %-12s on regions... and connections',... U.name{k}); @@ -208,7 +201,7 @@ drawnow % wait for 'done' - %----------------------------------------------------------- + %-------------------------------------------------------------- set(gcf,'CurrentObject',h2(1)) while(1) pause(0.01) @@ -218,15 +211,15 @@ % get c %-------------------------------------------------- for i = 1:n - c(i,k) = str2num(get(h2(i),'string')); + c(i,k) = str2double(get(h2(i),'string')); end % get b ensuring 2nd order effects are allowed %-------------------------------------------------- for i = 1:n for j = 1:n - b(i,j,k) = str2num(get(h3(i,j),'string')); - if i == j & ~c(i,k) + b(i,j,k) = str2double(get(h3(i,j),'string')); + if i == j && ~c(i,k) b(i,j,k) = 0; end end @@ -257,40 +250,32 @@ case 'IMPORT' % Import existing model - prompt user to choose it - %================================================= + %================================================================== P = spm_select(1,'^DCM.*\.mat$','Select source DCM_???.mat'); load(P) otherwise % Import existing model (directly specified by directory & name) - %============================================================== + %================================================================== try load(source_model) catch - disp('Source model does not exist - wrong directory or file name?'); - return; + error('Cannot load source model'); end - -end % end of switch statement - - -% Assume default hemodynamics -%------------------------------------------------------------------ -[pE,pC,qE] = spm_dcm_priors(DCM.a,DCM.b,DCM.c); -DCM.H = qE; +end % Now set up output structure -%------------------------------------------------------------------- +%-------------------------------------------------------------------------- X0 = ones(DCM.v,1); switch upper(source_model) case 'GUI' Y.dt = SPM.xY.RT; otherwise try - Y.dt = DCM.Y.dt; + Y.dt = DCM.Y.dt; catch Y.dt = DCM.delays(1); end @@ -304,18 +289,15 @@ %-Save and reset title -%------------------------------------------------------------------- +%-------------------------------------------------------------------------- if spm_matlab_version_chk('7') >= 0 save(['DCM_',syn_model],'-V6','DCM'); else save(['DCM_',syn_model],'DCM'); -end; +end % Now generate synthetic output data +%========================================================================== spm_dcm_generate(['DCM_' syn_model],source_model,SNR); spm('FigName',header); -spm('Pointer','Arrow') - - -return diff --git a/spm_dcm_display.m b/spm_dcm_display.m index be9aaa8..f020706 100644 --- a/spm_dcm_display.m +++ b/spm_dcm_display.m @@ -1,65 +1,75 @@ function spm_dcm_display(varargin) % Region and anatomical graph display -% FORMAT spm_dcm_display(xY,a,c,u,M,U) +% FORMAT spm_dcm_display(xY,a,c) % xY - cell of region structures (see spm_regions) -% a - connections of directed graph a(i,j,1) = p value +% a - connections of directed graph a(i,j,1) = p value; +% a(i,j,2) = MAP estimate +% value % c - node-specific inputs -% u - (3 x 2) projection matrix [default = [] ] -% M - margin (mm) [default = 24 ] -% U - theshold for plotting connections [default = 0.9] +% M - margin (mm) [default = 32 ] +% U - threshold for plotting connections [default = 0.9] %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging - + % Karl Friston -% $Id: spm_dcm_display.m 3465 2009-10-14 15:14:29Z guillaume $ - - -% null input arguments +% $Id: spm_dcm_display.m 3900 2010-05-25 16:17:13Z guillaume $ + + +% input arguments %-------------------------------------------------------------------------- -Fgraph = spm_figure('GetWin','Graphics'); n = length(varargin); - + +% get dimensions +%-------------------------------------------------------------------------- if n < 1; xY = []; else, xY = varargin{1}; end if n < 2; a = []; else, a = varargin{2}; end if n < 3; c = []; else, c = varargin{3}; end -if n < 4; u = []; else, u = varargin{4}; end -if n < 5; M = 16; else, M = varargin{5}; end -if n < 6; U = .9; else, U = varargin{6}; end - -col = [0 0 0]; -rad = 6; -w = 2; +if n < 4 + Fgraph = spm_figure('GetWin','Graphics'); + ha = gca; +else + ha = varargin{4}; + Fgraph = get(ha,'parent'); +end -% enforce orientation for 1 or 2 regions +% graphics parameters %-------------------------------------------------------------------------- -if length(xY) < 3 - u = [[1 0 0];[0 1 0]]'; -end +col = {'r','g','b','c','y','m','r','g','b','c','y','m'}; +rad = 16; % radius of self-connections +w = 4; % line width +M = 32; % MarkerSize for regions +U = 0.9; % Display threshold on p-value -% get dimensions +% get dimensions, locations and names %-------------------------------------------------------------------------- -m = size(xY,2); -L = []; +m = size(xY,2); +L = []; for i = 1:m L = [L xY(i).xyz]; - name{i} = xY(i).name; + name{i} = xY(i).name(1:min(end,3)); end -L = [L; ones(1,m)]; -o = mean(L,2); -M1 = spm_matrix(-o(1:3)'); - -% compute projection matrix for 'principal' plane +L = [L; ones(1,m)]; +o = mean(L,2); +M1 = spm_matrix(-o(1:3)'); + + +% get orientation with the greatest dispersion %-------------------------------------------------------------------------- -if isempty(u) - [u s v] = svd(M1*L); - u = u(:,[2 1]); - [i j] = max(abs(u)); - u = u*diag(sign([u(j(1),1) u(j(2),2)])); +for i = 1:3 + u{i} = eye(4,3); + u{i}(:,i) = []; + s(i) = det(u{i}'*M1*L*L'*M'*u{i}); end +[i j] = max(s); +u = u{j}; + +% compute projection matrix for 'principal' plane +%-------------------------------------------------------------------------- M2 = u'; M2(4,4) = 1; +M1(j,4) = 0; L = M2*M1*L; - + % coordinates %-------------------------------------------------------------------------- i = (min(L(1,:)) - M):(max(L(1,:)) + M); @@ -68,174 +78,142 @@ function spm_dcm_display(varargin) y = kron(j,ones(size(i))); xyz = [x; y; zeros(1,length(x)); ones(1,length(x))]; xyz = pinv(M1)*pinv(M2)*xyz; -M3 = [1 0 0 -min(i); 0 -1 0 -min(j); 0 0 0 0; 0 0 0 1]; +M3 = [1 0 0 -min(i); 0 -1 0 max(j); 0 0 0 0; 0 0 0 1]; L = M3*L; - - + + % get T1 background %-------------------------------------------------------------------------- V = spm_vol(fullfile(spm('Dir'),'canonical','single_subj_T1.nii')); ijk = inv(V.mat)*xyz; t1 = spm_sample_vol(V,ijk(1,:),ijk(2,:),ijk(3,:),2); t1 = (64 - 16) + 16*t1/max(t1(:)); - - + + % Watermark and regions %-------------------------------------------------------------------------- -str = get(get(gca,'Title'),'String'); -image(rot90(reshape(t1,length(i),length(j)))) -axis image off -title(str) - - +str = get(get(ha,'Title'),'String'); +image(rot90(reshape(t1,length(i),length(j))),'parent',ha) +axis(ha,'image','off') +title(ha,str) + + % Connections %-------------------------------------------------------------------------- Q = [-pi:pi/32:pi]; Q = rad*[sin(Q); cos(Q)]; -x = mean(L(1,:)); -y = mean(L(2,:)); q = 1/3; for i = 1:length(a) -for j = 1:length(a) - if ~isnan(a(i,j,1)) - - % show connection - %------------------------------------------------------------------ - if i ~= j - - % line - %-------------------------------------------------------------- - h = line(L(1,[i j]),L(2,[i j]),... - 'Color',col,... - 'LineStyle',':',... - 'LineWidth',w); - - % if significant + for j = 1:length(a) + if ~isnan(a(i,j,1)) + + % show connections %-------------------------------------------------------------- - if a(i,j,1) > U - set(h,'LineStyle','-','LineWidth',w) - - % text + if i ~= j + + % line %---------------------------------------------------------- - u = q*(L(1,j) - L(1,i)) + L(1,i); - v = q*(L(2,j) - L(2,i)) + L(2,i); - str = {}; - for k = 1:size(a,3) - str{k} = sprintf('%0.2f ',a(i,j,k)); - end - h = text(u,v,1,str(:),'FontSize',10,... - 'HorizontalAlignment','Center'); - if a(i,j,2) < 0 - set(h, 'Color','r') + h = line(L(1,[i j]),L(2,[i j]),'Color',col{j},... + 'LineStyle',':',... + 'LineWidth',w); + + % if significant + %---------------------------------------------------------- + if a(i,j,1) > U + set(h,'LineStyle','-','LineWidth',w) + + % text + %------------------------------------------------------ + u = q*(L(1,j) - L(1,i)) + L(1,i); + v = q*(L(2,j) - L(2,i)) + L(2,i); + str = {}; + for k = 1:size(a,3) + str{k} = sprintf('%0.2f ',a(i,j,k)); + end + h = text(u,v,1,str(:),'FontSize',12,... + 'HorizontalAlignment','Center'); end - end - - % self connection - %------------------------------------------------------------------ - else - - % line + + % self-connection %-------------------------------------------------------------- - u = (L(1,i) - x); - v = (L(2,i) - y); - l = sqrt(u^2 + v^2); - l = (l + rad)/l; - u = Q(1,:) + x + l*u; - v = Q(2,:) + y + l*v; - h = line(u,v,... - 'Color',col,... - 'LineStyle',':',... - 'LineWidth',w); - - % if significant - %-------------------------------------------------------------- - if a(i,j,1) > U - set(h,'LineStyle','-','LineWidth',w) - - % text + else + + % line %---------------------------------------------------------- - u = u(48); - v = v(48); - str = {}; - for k = 1:size(a,3) - str{k} = sprintf('%0.2f ',a(i,j,k)); - end - h = text(u,v,1,str(:),'FontSize',10,... - 'HorizontalAlignment','Center'); - if a(i,j,2) < 0 - set(h, 'Color','r') + u = L(1,i); + v = L(2,i); + u = Q(1,:) + u; + v = Q(2,:) + v; + h = line(u,v,'Color',col{i},'LineStyle',':','LineWidth',w); + + % if significant + %---------------------------------------------------------- + if a(i,j,1) > U + set(h,'LineStyle','-','LineWidth',w) + + % text + %------------------------------------------------------ + u = u(48); + v = v(48); + str = {}; + for k = 1:size(a,3) + str{k} = sprintf('%0.2f ',a(i,j,k)); + end + h = text(u,v,1,str(:),'FontSize',12,... + 'HorizontalAlignment','Center'); end end end end end -end - -% Extrinsic influences + +% Exogenous inputs %-------------------------------------------------------------------------- for i = 1:size(c,1) if ~isnan(c(i,1)) - + % line %------------------------------------------------------------------ - u = (L(1,i) - x); - v = (L(2,i) - y); - l = sqrt(u^2 + v^2); - l = (l + rad)/l; - u = [u l*u] + x; - v = [v l*v] + y; - h = line(u,v,... - 'Color',col,... - 'LineStyle',':',... - 'LineWidth',w); - + u = L(1,i); + v = L(2,i); + u = [u (rad + u)]; + v = [v v]; + h = line(u,v,'Color',col{i},'LineStyle',':','LineWidth',w); + % if significant %------------------------------------------------------------------ if c(i,1) > U set(h,'LineStyle','-','LineWidth',w) - + % patch %-------------------------------------------------------------- u = u(2); v = v(2); - - % text - %-------------------------------------------------------------- str = {}; for k = 1:size(c,2) - str{k} = sprintf('%0.2f ',c(i,k)); - end - h = text(u,v,str(:),'FontSize',10,... - 'HorizontalAlignment','Center'); - if c(i,2) < 0 - set(h, 'Color','r') + str{k} = sprintf('%0.2f ',c(i,k)); end - + h = text(u,v,str(:),'FontSize',12,... + 'HorizontalAlignment','Center'); end end end - - + + % projected coordinates of voxels within region[s] %-------------------------------------------------------------------------- hold on for i = 1:m - l = xY(i).XYZmm; - n = size(l,2); - l = [l; ones(1,n)]; - l = M3*M2*M1*l; - plot(l(1,:),l(2,:),'.r','MarkerSize',4) -end - -line(L(1,:),L(2,:),... - 'Color',[0 0 0],... + + line(L(1,i),L(2,i),... + 'Color',col{i},... 'Marker','.',... 'LineStyle','none',... - 'MarkerSize',64); - -text(L(1,:),L(2,:),name,'FontSize',8,... - 'FontWeight','Bold',... - 'Color','w',... - 'HorizontalAlignment','center',... - 'FontAngle','italic') + 'MarkerSize',98); + + text(L(1,i),L(2,i),name{i},'FontSize',16,... + 'FontWeight','Bold',... + 'Color','w',... + 'HorizontalAlignment','center') +end hold off diff --git a/spm_dcm_estimate.m b/spm_dcm_estimate.m index 7390730..3160575 100644 --- a/spm_dcm_estimate.m +++ b/spm_dcm_estimate.m @@ -1,31 +1,73 @@ -function [DCM] = spm_dcm_estimate(P) -% Estimate parameters of a DCM (bilinear or nonlinear) for fMRI data -% FORMAT [DCM] = spm_dcm_estimate(DCM) +function [DCM] = spm_dcm_estimate(P) +% Estimates parameters of a DCM (bilinear or nonlinear) for fMRI data +% FORMAT [DCM] = spm_dcm_estimate(DCM) +% DCM - the DCM or its filename +% +% Expects +%-------------------------------------------------------------------------- +% DCM.a; % switch on endogenous connections +% DCM.b; % switch on bilinear modulations +% DCM.c; % switch on exogenous connections +% DCM.U; % exogenous inputs +% DCM.Y; % responses +% DCM.Y.X0; % confounds +% DCM.n; % number of regions +% DCM.v; % number of scans +% +% Options +%-------------------------------------------------------------------------- +% DCM.options.two_state % two regional populations (E and I) +% DCM.options.stochastic % fluctuations on hidden states +% DCM.options.nonlinear % interactions among hidden states +% DCM.options.nograph % graphical display +% DCM.options.P % Starting estimates for parameters +% DCM.options.W % noise log-precicion (hidden-states) +% DCM.options.V % noise log-precicion (hidden-causes) +% DCM.options.s % smoothness of random fluctuations +% +% Evaluates: +%-------------------------------------------------------------------------- +% DCM.M % Model structure +% DCM.Ep % Condition means (parameter structure) +% DCM.Cp % Conditional covariances +% DCM.Vp % Conditional variances +% DCM.Pp % Conditional probabilities +% DCM.H1 % 1st order hemodynamic kernels +% DCM.H2 % 2nd order hemodynamic kernels +% DCM.K1 % 1st order neuronal kernels +% DCM.K2 % 2nd order neuronal kernels +% DCM.R % residuals +% DCM.y % predicted data +% DCM.T % Threshold for Posterior inference +% DCM.Ce % Error variance for each region +% DCM.F % Free-energy bound on log evidence +% DCM.ID % Data ID +% DCM.AIC % Akaike Information criterion +% DCM.BIC % Bayesian Information criterion % -% DCM - the DCM or its filename %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging - -% Will Penny -% $Id: spm_dcm_estimate.m 3177 2009-06-03 08:47:41Z vladimir $ - + +% Karl Friston +% $Id: spm_dcm_estimate.m 3888 2010-05-15 18:49:56Z karl $ + % load DCM structure %-------------------------------------------------------------------------- if ~nargin - + %-display model details %---------------------------------------------------------------------- Finter = spm_figure('GetWin','Interactive'); set(Finter,'name','Dynamic Causal Modeling') - + %-get DCM %---------------------------------------------------------------------- - P = spm_select(1,'^DCM.*\.mat$','select DCM_???.mat'); - + [P, sts] = spm_select(1,'^DCM.*\.mat$','select DCM_???.mat'); + if ~sts, DCM = []; return; end spm('Pointer','Watch') spm('FigName','Estimation in progress'); - + end if isstruct(P) DCM = P; @@ -33,227 +75,272 @@ else load(P) end + +% check options +%========================================================================== +try, DCM.options.two_state; catch, DCM.options.two_state = 0; end +try, DCM.options.stochastic; catch, DCM.options.stochastic = 0; end +try, DCM.options.nonlinear; catch, DCM.options.nonlinear = 0; end +try, DCM.options.form; catch, DCM.options.form = 'Gaussian'; end +try, DCM.options.W; catch, DCM.options.W = 9; end +try, DCM.options.V; catch, DCM.options.V = 4; end +try, DCM.options.s; catch, DCM.options.s = 1/4; end - + +try, M.nograph = DCM.options.nograph; catch, M.nograph = spm('CmdLine');end +try, M.P = DCM.options.P ;end + % unpack %-------------------------------------------------------------------------- -a = DCM.a; % switch on endogenous connections -b = DCM.b; % switch on bilinear modulations -c = DCM.c; % switch on exogenous connections -U = DCM.U; % exogenous inpurs +U = DCM.U; % exogenous inputs Y = DCM.Y; % responses -X0 = DCM.Y.X0; % confounds -n = DCM.n; -v = DCM.v; - - -% adopt model specification M if it already exists +n = DCM.n; % number of regions +v = DCM.v; % number of scans + + +% check scaling of Y (enforcing a maximum change of 4% %-------------------------------------------------------------------------- -if isfield(DCM,'M') - M = DCM.M; -end +scale = max(max((Y.y))) - min(min((Y.y))); +scale = 4/max(scale,4); +Y.y = Y.y*scale; +Y.scale = scale; - -% check whether this is a nonlinear DCM +% normalise inputs %-------------------------------------------------------------------------- -if isfield(DCM,'d') && any(any(DCM.d(:))) - % nonlinear DCM - M.nlDCM = 1; - d = DCM.d; % switch on nonlinear modulations - fprintf('\n\n%s %s\n','Nonlinear DCM:',P); - fprintf('%s\n\n','--------------------------------------------------------------------------------------'); - fprintf('%s\n\n','Please note that this computation will be considerably slower than for a bilinear DCM.'); - fprintf('%s\n','If you want to speed up computation, you can use fewer microtime bins per TR when defining your design matrix'); - fprintf('%s\n','(the size of a microtime bin defines the dt for integration of the DCM state equations).'); - fprintf('%s\n','We found microtime bins of 0.2 s to give stable results; longer time bins may well still work, but you would need to check.'); - fprintf('%s %1.3f seconds.\n\n','You are currently using microtimebins of',DCM.U.dt); -else - % bilinear DCM - M.nlDCM = 0; -end - - -% check integrator +U.u = spm_detrend(U.u); + +% check DCM.d (for nonlinear DCMs) %-------------------------------------------------------------------------- -if ~isfield(M,'IS') - if M.nlDCM - % nonlinear DCM - M.IS = 'spm_int_B_nlDCM_fMRI'; - else - % bilinear DCM - M.IS = 'spm_int'; - end -end - -% prevent mismatch between DCM structure and integration scheme -if M.nlDCM && (length(M.IS) == length('spm_int')) - fprintf('\n\n%s\n','WARNING: You are trying to run a nonlinear DCM with a bilinear integration scheme (spm_int).'); - fprintf('%s\n\n','A nonlinear integration scheme (spm_int_B_nlDCM_fMRI) is used instead.'); - M.IS = 'spm_int_B_nlDCM_fMRI'; +try + DCM.d; +catch + DCM.d = zeros(n,n,0); + DCM.options.nonlinear = 0; end - - -% check whether TE of acquisition has been defined -% (if not, default to 0.04 s) + +% check confounds (add constant if necessary) +%-------------------------------------------------------------------------- +if ~size(Y.X0,2), Y.X0 = ones(v,1); end + + +% specify parameters for spm_int_D (ensuring updates every second or so) %-------------------------------------------------------------------------- -if ~isfield(DCM,'TE') - DCM.TE = 0.04; +if DCM.options.nonlinear + M.IS = 'spm_int_D'; + M.nsteps = round(max(Y.dt,1)); + M.states = 1:n; else - if (DCM.TE < 0) || (DCM.TE > 0.1) - disp('spm_dcm_estimate: Extreme TE value found.') - disp('Please check and adjust DCM.TE - note this value must be in seconds!') - return - end + M.IS = 'spm_int'; end -TE = DCM.TE; - - -% priors - expectations + +% priors %-------------------------------------------------------------------------- -if ~M.nlDCM - % bilinear DCM - [pE,pC,qE,qC] = spm_dcm_priors(a,b,c); +if DCM.options.two_state + [pE,pC] = spm_dcm_fmri_priors(DCM.a,DCM.b,DCM.c,DCM.d,'2s'); + x = sparse(n,6); else - % nonlinear DCM - [pE,pC,qE,qC] = spm_dcm_priors(a,b,c,d); + [pE,pC] = spm_dcm_fmri_priors(DCM.a,DCM.b,DCM.c,DCM.d); + x = sparse(n,5); end - - -% complete model specification -%-------------------------------------------------------------------------- -M.f = 'spm_fx_dcm'; -M.g = 'spm_gx_dcm'; -M.x = sparse(n*5,1); -M.pE = pE; -M.pC = pC; -M.m = size(U.u,2); -M.n = size(M.x,1); -M.l = n; -M.N = 32; -M.dt = 16/M.N; -M.ns = size(Y.y,1); -M.TE = TE; - - + % fMRI slice time sampling %-------------------------------------------------------------------------- try, M.delays = DCM.delays; end - - +try, M.TE = DCM.TE; end + + +% complete model specification +%-------------------------------------------------------------------------- +M.f = 'spm_fx_fmri'; +M.g = 'spm_gx_fmri'; +M.x = x; +M.pE = pE; +M.pC = pC; +M.m = size(U.u,2); +M.n = size(x(:),1); +M.l = size(x,1); +M.N = 32; +M.dt = 16/M.N; +M.ns = v; + + % nonlinear system identification (nlsi) +%========================================================================== + +% nonlinear system identification (Variational EM) - deterministic DCM %-------------------------------------------------------------------------- -[Ep,Cp,Ce,H0,H1,H2,M0,M1,L1,L2,F] = spm_nlsi(M,U,Y); - +[Ep,Cp,Eh,F] = spm_nlsi_GN(M,U,Y); + +% proceed to stochastic (initialising with deterministic estimates) +%-------------------------------------------------------------------------- +if DCM.options.stochastic + + + % specify bilinear approximation scheme for spm_DEM_eval + %---------------------------------------------------------------------- + if size(pE.A,3), M.E.linear = 1; end % linear model + if size(pE.B,3), M.E.linear = 2; end % bilinear model + if size(pE.D,3), M.E.linear = 3; end % nonlinear models + + % Decimate U.u from micro-time + % --------------------------------------------------------------------- + u = U.u; + y = Y.y; + Dy = spm_dctmtx(size(y,1),size(y,1)); + Du = spm_dctmtx(size(u,1),size(y,1)); + Dy = Dy*sqrt(size(y,1)/size(u,1)); + u = Dy*(Du'*u); + + % DEM Structure: place model, data, input and confounds in DEM + % --------------------------------------------------------------------- + DEM.M = M; + DEM.Y = y'; + DEM.U = u'; + DEM.X = Y.X0'; + + % set inversion parameters + % --------------------------------------------------------------------- + form = DCM.options.form; + s = DCM.options.s; + DEM.M(1).E.form = form; % form of random fluctuations + DEM.M(1).E.s = s; % smoothness of random fluctuations + DEM.M(1).E.d = 2; % embedding dimension + DEM.M(1).E.n = 4; % embedding dimension + DEM.M(1).E.nN = 8; % maximum number of DEM iterations -% Data ID -%========================================================================== -if isfield(M,'FS') - try - ID = spm_data_id(feval(M.FS,Y.y,M)); - catch - ID = spm_data_id(feval(M.FS,Y.y)); + + % adjust M.f (DEM works in time bins not seconds) and initialize M.P + % --------------------------------------------------------------------- + DEM.M(1).f = inline([M.f '(x,v,P)*' num2str(Y.dt)],'x','v','P'); + DEM.M(1).P = Ep; + DEM.M(1).pC = pC; + + % delays (DEM works in time bins not seconds) + % --------------------------------------------------------------------- + DEM.M(1).delays = M.delays/Y.dt; + + % Precision on hidden states (s.d. of about 10%) + % --------------------------------------------------------------------- + DEM.M(1).xP = 128; + + % Specify hyper-priors on precisions + % --------------------------------------------------------------------- + DEM.M(1).Q = spm_Ce(ones(1,n)); + DEM.M(1).hE = Eh + 1; % prior expectation of log-precision (noise) + DEM.M(1).hC = 1/8; % prior covariance of log-precision (noise) + + DEM.M(1).W = exp(DCM.options.W); % fixed precision (hidden-state) + DEM.M(2).V = exp(DCM.options.V); % fixed precision (hidden-cause) + + + % Generalised filtering (under the Laplace assumption) + % ===================================================================== + if DCM.options.stochastic == 1 + + DEM = spm_LAP(DEM); % no mean-field assumption + else + DEM = spm_DEM(DEM); % mean-field assumption (DEM) end + + % Save DEM estimates + %---------------------------------------------------------------------- + DCM.qU = DEM.qU; + DCM.qP = DEM.qP; + DCM.qH = DEM.qH; + DCM.Fd = F; + + % unpack results + % --------------------------------------------------------------------- + F = DEM.F(end); + Ep = DEM.qP.P{1}; + Cp = DEM.qP.C; + + % predicted responses (y) and residuals (R) from DEM + %---------------------------------------------------------------------- + y = DEM.qU.v{1}'; + R = DEM.qU.z{1}'; + R = R - Y.X0*inv(Y.X0'*Y.X0)*(Y.X0'*R); + Ce = exp(-DEM.qH.h{1}); + else - ID = spm_data_id(Y.y); + + % predicted responses (y) and residuals (R) from EM + %---------------------------------------------------------------------- + y = feval(M.IS,Ep,M,U); + R = Y.y - y; + R = R - Y.X0*inv(Y.X0'*Y.X0)*(Y.X0'*R); + Ce = exp(-Eh); + end - - -% predicted responses and residuals + + +% Bilinear representation and first-order hemodynamic kernel %-------------------------------------------------------------------------- -y = feval(M.IS,Ep,M,U); -R = Y.y - y; -R = R - X0*inv(X0'*X0)*(X0'*R); - - -% neuronal kernels +[M0,M1,L1,L2] = spm_bireduce(M,Ep); +[H0,H1] = spm_kernels(M0,M1,L1,L2,M.N,M.dt); + +% and neuronal kernels %-------------------------------------------------------------------------- -L = sparse(1:n,[1:n] + 1,1,n,length(M0)); -[K0,K1,K2] = spm_kernels(M0,M1,L,M.N,M.dt); - - -% Bayesian inference and reshape {default threshold T = 0} +L = sparse(1:n,[1:n] + 1,1,n,length(M0)); +[K0,K1] = spm_kernels(M0,M1,L,M.N,M.dt); + + +% Bayesian inference and variance {threshold T = 0} %-------------------------------------------------------------------------- -T = 0; -sw = warning('off','SPM:negativeVariance'); % switch off NaN-related warning of spm_Ncdf -pp = 1 - spm_Ncdf(T,abs(Ep),diag(Cp)); +T = 0; +sw = warning('off','SPM:negativeVariance'); +Pp = spm_unvec(1 - spm_Ncdf(T,abs(spm_vec(Ep)),diag(Cp)),Ep); +Vp = spm_unvec(diag(Cp),Ep); warning(sw); -if ~M.nlDCM - % bilinear DCM - [ A B C] = spm_dcm_reshape(Ep,M.m,n,1); - [pA pB pC] = spm_dcm_reshape(pp,M.m,n,1); -else - % nonlinear DCM - % NB: order of parameter vector is: - % bilinear neural params -> hemodynamic params -> nonlinear neural params - [ A B C H D] = spm_dcm_reshape(Ep,M.m,n,1); - [pA pB pC pH pD] = spm_dcm_reshape(pp,M.m,n,1); -end - - -% Also record variances - this helps Bayesian inference, e.g. across sessions -%-------------------------------------------------------------------------- -vv = diag(Cp); -if ~M.nlDCM - % bilinear DCM - [vA vB vC] = spm_dcm_reshape(vv,M.m,n,1); -else - % nonlinear DCM - [vA vB vC vH vD] = spm_dcm_reshape(vv,M.m,n,1); -end - + +try, M = rmfield(M,'nograph'); end % Store parameter estimates %-------------------------------------------------------------------------- -DCM.M = M; -DCM.Y = Y; -DCM.U = U; -DCM.Ep = Ep; -DCM.Cp = Cp; -DCM.A = A; -DCM.B = B; -DCM.C = C; -DCM.pA = pA; -DCM.pB = pB; -DCM.pC = pC; -DCM.vA = vA; -DCM.vB = vB; -DCM.vC = vC; -DCM.H1 = H1; -DCM.H2 = H2; -DCM.K1 = K1; -DCM.K2 = K2; -DCM.R = R; -DCM.y = y; -DCM.T = T; -DCM.Ce = Ce; -if M.nlDCM - % nonlinear DCM - DCM.D = D; - DCM.pD = pD; - DCM.vD = vD; +DCM.M = M; +DCM.Y = Y; +DCM.U = U; +DCM.Ce = Ce; +DCM.Ep = Ep; +DCM.Cp = Cp; +DCM.Pp = Pp; +DCM.Vp = Vp; +DCM.H1 = H1; +DCM.K1 = K1; +DCM.R = R; +DCM.y = y; +DCM.T = T; + + +% Data ID and log-evidence +%========================================================================== +if isfield(M,'FS') + try + ID = spm_data_id(feval(M.FS,Y.y,M)); + catch + ID = spm_data_id(feval(M.FS,Y.y)); + end +else + ID = spm_data_id(Y.y); end - - + % Save approximations to model evidence: negative free energy, AIC, BIC %-------------------------------------------------------------------------- evidence = spm_dcm_evidence(DCM); DCM.F = F; -DCM.ID = ID; % data ID +DCM.ID = ID; DCM.AIC = evidence.aic_overall; DCM.BIC = evidence.bic_overall; - - + %-Save DCM %-------------------------------------------------------------------------- if spm_matlab_version_chk('7') >= 0 - save(P,'-V6','DCM'); + save(P,'-V6','DCM','F','Ep','Cp'); else - save(P,'DCM'); + save(P,'DCM','F','Ep','Cp'); end - + if ~nargin spm('Pointer','Arrow'); spm('FigName','Done'); end - -return diff --git a/spm_dcm_evidence.m b/spm_dcm_evidence.m index 8c6f25b..cd0250a 100644 --- a/spm_dcm_evidence.m +++ b/spm_dcm_evidence.m @@ -1,69 +1,45 @@ -function [evidence] = spm_dcm_evidence (DCM) +function evidence = spm_dcm_evidence(DCM) % Compute evidence of DCM model -% FORMAT [evidence] = spm_dcm_evidence (DCM) -% -% DCM DCM data structure +% FORMAT evidence = spm_dcm_evidence(DCM) % -% evidence Contains the following fields: +% DCM - DCM data structure % -% .region_cost(i) The cost of prediction errors in region i -% .bic_penalty Bayesian information criterion penalty -% .bic_overall The overall BIC value -% .aic_penalty Akaike's information criterion penalty -% .aic_overall The overall AIC value +% evidence - structure with the following fields +% .region_cost(i) - The cost of prediction errors in region i +% .bic_penalty - Bayesian information criterion penalty +% .bic_overall - The overall BIC value +% .aic_penalty - Akaike's information criterion penalty +% .aic_overall - The overall AIC value % -% All of the above are in units of NATS (not bits) +% All of the above are in units of NATS (not bits). %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Will Penny -% $Id: spm_dcm_evidence.m 1143 2008-02-07 19:33:33Z spm $ +% $Id: spm_dcm_evidence.m 3741 2010-03-01 15:35:30Z guillaume $ -v=DCM.v; - % Only look at those parameters with non-zero prior covariance -pCdiag=diag(DCM.M.pC); -wsel=find(~(pCdiag==0)); - -% Ensure residuals have been estimated correctly -if length(isnan(DCM.R))>0, - % Assume that reason for incorrect R was zero columns in X0 - - % 1. Remove zero columns from X0 if there are any - X0=DCM.Y.X0; - ncol_X0=size(X0,2); - new_X0=[]; - for col_X0=1:ncol_X0, - if ~(length(find(X0(:,col_X0)==0))==DCM.v) - new_X0=[new_X0 X0(:,col_X0)]; - end - end - X0=new_X0; - - % 2. Recompute residuals - R = DCM.Y.y - DCM.y; - R = R - X0*inv(X0'*X0)*(X0'*R); - DCM.R = R; - - % Note DCM.R not saved to file -end +%-------------------------------------------------------------------------- +v = DCM.v; % number of samples +n = DCM.n; % number of regions +wsel = find(diag(DCM.M.pC)); % Look at costs of coding prediction errors by region -n=size(DCM.A,1); -for i=1:n, - lambda_i=DCM.Ce(i*v,i*v); - evidence.region_cost(i)=-0.5*v*log(lambda_i); - evidence.region_cost(i)=evidence.region_cost(i)-0.5*DCM.R(:,i)'*(1/lambda_i)*eye(v)*DCM.R(:,i); +%-------------------------------------------------------------------------- +for i = 1:n + try + lambda_i = DCM.Ce(i*v,i*v); % old format + catch + lambda_i = DCM.Ce(i); % new format + end + evidence.region_cost(i) = -0.5*v*log(lambda_i) ... + - 0.5*DCM.R(:,i)'*(1/lambda_i)*eye(v)*DCM.R(:,i); end -evidence.aic_penalty=length(wsel); -evidence.bic_penalty=0.5*length(wsel)*log(v); - -evidence.aic_overall=sum(evidence.region_cost)-evidence.aic_penalty; -evidence.bic_overall=sum(evidence.region_cost)-evidence.bic_penalty; - - - - - +% Results +%-------------------------------------------------------------------------- +evidence.aic_penalty = length(wsel); +evidence.bic_penalty = 0.5*length(wsel)*log(v); +evidence.aic_overall = sum(evidence.region_cost) - evidence.aic_penalty; +evidence.bic_overall = sum(evidence.region_cost) - evidence.bic_penalty; diff --git a/spm_dcm_fmri_priors.m b/spm_dcm_fmri_priors.m new file mode 100644 index 0000000..56b29e5 --- /dev/null +++ b/spm_dcm_fmri_priors.m @@ -0,0 +1,99 @@ +function [pE,pC] = spm_dcm_fmri_priors(A,B,C,varargin) +% Returns the priors for a two-state DCM for fMRI. +% FORMAT: +% for bi-linear DCM: [pE,pC] = spm_dcm_fmri_priors(A,B,C) +% for nonlinear DCM: [pE,pC] = spm_dcm_fmri_priors(A,B,C,D) +% for two-state DCM: [pE,pC] = spm_dcm_fmri_priors(A,B,C,D,'2s') +% +% INPUT: +% A,B,C,D - constraints on connections (1 - present, 0 - absent) +% +% OUTPUT: +% pE - prior expectations (connections and hemodynamic) +% pC - prior covariances (connections and hemodynamic) +%__________________________________________________________________________ +% +% References for state equations: +% 1. Marreiros AC, Kiebel SJ, Friston KJ. Dynamic causal modelling for +% fMRI: a two-state model. +% Neuroimage. 2008 Jan 1;39(1):269-78. +% +% 2. Stephan KE, Kasper L, Harrison LM, Daunizeau J, den Ouden HE, +% Breakspear M, Friston KJ. Nonlinear dynamic causal models for fMRI. +% Neuroimage 42:649-662, 2008. +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: spm_dcm_fmri_priors.m 3888 2010-05-15 18:49:56Z karl $ + + + +% number of regions +%-------------------------------------------------------------------------- +n = length(A); % number of regions + +% varargin (D for nonlinear coupling) +%-------------------------------------------------------------------------- +if nargin > 3, D = varargin{1}; else, D = zeros(n,n,0); end +if nargin > 4, two_states = 1; else, two_states = 0; end + +% connectivity priors +%========================================================================== + +if two_states + + % enforce optimisation of intrinsic (I to E) connections + %---------------------------------------------------------------------- + A = (A + eye(n,n)) > 0; + + % prior expectations and variances + %---------------------------------------------------------------------- + pE.A = A*32 - 32; + pE.B = B*0; + pE.C = C*0; + pE.D = D*0; + + % prior covariances + %---------------------------------------------------------------------- + pC.A = A/4; + pC.B = B/4; + pC.C = C*4; + pC.D = D/4; + +else + + % enforce self-inhibition + %---------------------------------------------------------------------- + A = A > 0; + A = A - diag(diag(A)); + + % prior expectations + %---------------------------------------------------------------------- + pE.A = A/64 - eye(n,n); + pE.B = B*0; + pE.C = C*0; + pE.D = D*0; + + % prior covariances + %---------------------------------------------------------------------- + pC.A = A/4 + eye(n,n)/16; + pC.B = B*4; + pC.C = C*4; + pC.D = D*4; + +end + +% and add hemodynamic priors +%========================================================================== +pE.transit = sparse(n,1); +pE.decay = sparse(n,1); +pE.epsilon = sparse(1,1); + +pC.transit = sparse(n,1) + exp(-4); +pC.decay = sparse(n,1) + exp(-4); +pC.epsilon = sparse(1,1) + exp(-4); + +pC = diag(spm_vec(pC)); + +return diff --git a/spm_dcm_generate.m b/spm_dcm_generate.m index 5589c97..36b0991 100644 --- a/spm_dcm_generate.m +++ b/spm_dcm_generate.m @@ -1,6 +1,6 @@ -function [] = spm_dcm_generate(syn_model,source_model,SNR) -% Generate synthetic data from a DCM model specification -% FORMAT [] = spm_dcm_generate(syn_model,source_model,SNR) +function varargout = spm_dcm_generate(syn_model,source_model,SNR) +% Generate synthetic data from a DCM specification +% FORMAT spm_dcm_generate(syn_model,source_model,SNR) % % syn_model Name of synthetic DCM file % source_model Type of souce model specification (see spm_dcm_create) @@ -15,137 +15,124 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Will Penny & Klaas Enno Stephan -% $Id: spm_dcm_generate.m 3363 2009-09-04 15:11:19Z christophe $ +% $Id: spm_dcm_generate.m 3899 2010-05-25 15:36:40Z guillaume $ % Check parameters and load specified DCM %-------------------------------------------------------------------------- -if (nargin <3 ) | isempty(SNR) +if isstruct(syn_model) + DCM = syn_model; + syn_model = ['DCM-' date]; +else + load(syn_model) +end +if nargin <3 || isempty(SNR) SNR = 1; end -load(syn_model) -U = DCM.U; -v = DCM.v; % number of scans -n = DCM.n; % number of regions -m = size(U.u,2); % number of inputs +% Unpack +%-------------------------------------------------------------------------- +U = DCM.U; % inputs +v = DCM.v; % number of scans +n = DCM.n; % number of regions +m = size(U.u,2); % number of inputs % Check whether the model is stable by examining the eigenvalue % spectrum for the intrinsic connectivity matrix %-------------------------------------------------------------------------- -eigval = eig(DCM.A); -% display stability warning if necessary +eigval = eig(DCM.Ep.A); if max(eigval) >= 0 - disp (['Modelled system is potentially unstable: Lyapunov exponent of combined connectivity matrix is ' num2str(max(eigval))]); - disp ('Check the output to ensure that values are in a normal range.') + fprintf('Modelled system is potentially unstable:\n'); + fprintf('Lyapunov exponent of combined connectivity matrix is %f\n',max(eigval)); + fprintf('Check the output to ensure that values are in a normal range.\n') end -% Create model specification (if it does not yet exist) +% check whether this is a nonlinear DCM %-------------------------------------------------------------------------- -try - M = DCM.M; -catch - M.f = 'spm_fx_dcm'; - M.g = 'spm_gx_dcm'; - M.x = sparse(n*5,1); - M.m = size(U.u,2); - M.n = size(M.x,1); - M.l = n; - M.ns = v; - try - M.TE = DCM.TE; - catch - M.TE = 0.04; - end -end - -if ~isfield(M,'nlDCM') - if isfield(DCM,'d') && any(any(DCM.d(:))) - % nonlinear DCM - M.nlDCM = 1; - else - % bilinear DCM - M.nlDCM = 0; - end +if ~isfield(DCM,'d') || isempty(DCM.d) + DCM.d = zeros(n,n,0); + M.IS = 'spm_int'; else - M.nlDCM = DCM.M.nlDCM; + M.IS = 'spm_int_D'; end -if ~isfield(M,'IS') - if M.nlDCM - % nonlinear DCM - M.IS = 'spm_int_B_nlDCM_fMRI'; - else - % bilinear DCM - M.IS = 'spm_int'; - end -else - M.IS = M.IS; -end + +% priors +%-------------------------------------------------------------------------- +[pE,pC] = spm_dcm_fmri_priors(DCM.a,DCM.b,DCM.c,DCM.d); -% Create parameter vector for integration +% complete model specification %-------------------------------------------------------------------------- -if ~M.nlDCM - P=[0; DCM.A(:); DCM.B(:); DCM.C(:); DCM.H(:)]; -else - P=[0; DCM.A(:); DCM.B(:); DCM.C(:); DCM.H(:); DCM.D(:)]; -end +M.f = 'spm_fx_fmri'; +M.g = 'spm_gx_fmri'; +M.x = sparse(n,5); +M.pE = pE; +M.pC = pC; +M.m = size(U.u,2); +M.n = size(M.x(:),1); +M.l = size(M.x,1); +M.N = 32; +M.dt = 16/M.N; +M.ns = v; + + +% fMRI slice time sampling +%-------------------------------------------------------------------------- +try, M.delays = DCM.delays; end +try, M.TE = DCM.TE; end + % Integrate and compute hemodynamic response at v sample points %-------------------------------------------------------------------------- -y = feval (M.IS,P,M,U); +y = feval(M.IS,DCM.Ep,M,U); + % Compute required r: standard deviation of additive noise, for all areas %-------------------------------------------------------------------------- -r = diag(std(y)/SNR); +r = diag(std(y)/SNR); + % Add noise %-------------------------------------------------------------------------- -p = 1; -a = 0; % AR(1) coefficient set to zero -a = [1 -a]; -K = inv(spdiags(ones(v,1)*a,-[0:p],v,v)); -K = K*sqrt(v/trace(K*K')); -z = randn(v,n); -e = K*z; -Y = DCM.Y; -Y.Q = spm_Ce(v*ones(1,n)); -Y.y = y + e*r; -Y.secs = Y.dt*v; - -% Now orthogonalise data with respect to effects of no interest -% If X0 is just a vector of 1s this amounts to making the data zero mean -%-------------------------------------------------------------------------- -X0 = Y.X0; -Xp = X0*inv(X0'*X0)*X0'; -for i = 1:n, - Y.y(:,i) = Y.y(:,i)-Xp*Y.y(:,i); -end -DCM.Y = Y; -DCM.y = Y.y; +p = 1; +a = 1/16; +a = [1 -a]; +K = inv(spdiags(ones(v,1)*a,-[0:p],v,v)); +K = K*sqrt(v/trace(K*K')); +z = randn(v,n); +e = K*z; +Y = DCM.Y; +Y.Q = spm_Ce(v*ones(1,n)); +Y.y = y + e*r; +Y.secs = Y.dt*v; + % Save synthetic DCM %-------------------------------------------------------------------------- -DCM.M = M; +DCM.Y = Y; % simulated data +DCM.y = y; % simulated signal +DCM.M = M; % model if spm_matlab_version_chk('7') >= 0 save(syn_model, 'DCM', '-V6'); else save(syn_model, 'DCM'); -end; +end + +if nargout==1 + varargout{1} = DCM; +end % Display the time series generated %-------------------------------------------------------------------------- -F = spm_figure('CreateWin','Simulated BOLD time series'); -t = Y.dt*[1:1:v]; -for i=1:n, +spm_figure('Create','Graphics','Simulated BOLD time series'); +t = Y.dt*[1:1:v]; +for i = 1:n, subplot(n,1,i); plot(t,Y.y(:,i)); title(sprintf('Region %s', Y.name{i})); if i hemodynamic params -> nonlinear neural params -%__________________________________________________________________________ -% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging - -% Karl Friston -% $Id: spm_dcm_priors.m 2661 2009-01-28 20:21:42Z karl $ - - -% nonlinear DCM? -%-------------------------------------------------------------------------- -if nargin > 3 - nlDCM = 1; - D = varargin{1}; -else - nlDCM = 0; -end - -% number of regions -%-------------------------------------------------------------------------- -n = length(A); - - -% CONNECTIVITY PRIORS -%========================================================================== -% covariances pC = 1/((n - 1)*q) - if A == 1 -% pC = 0 if A == 0 -% -% where, for aij = aji = 1/(n - 1) => max(eig(J(0))) = 0 -% and q is the Chi-squared threshold with n*(n - 1) df - -% log(2)/b = half-life {b = self inhibition} - log-normal distribution -%-------------------------------------------------------------------------- -p = 1e-3; -b = 1; -s = spm_invNcdf(1 - p); -q = spm_invXcdf(1 - p,n*(n - 1)); -q = n/((n - 1)*q); - -% intrinsic connections A {additional priors from eigenvalues} -%-------------------------------------------------------------------------- -A = A - diag(diag(A)); -pC = diag([1/16; A(:)*q; B(:)*q; C(:)]); -if ~nlDCM - % bilinear DCM - pC_D = []; -else - % nonlinear DCM - pC_D = diag(D(:)*1); -end - -% define prior expectations and combine with hemodynamic priors -%-------------------------------------------------------------------------- -A = -speye(n,n); -B = B*0; -C = C*0; -pE = [log(b); A(:); B(:); C(:)]; -if ~nlDCM - % bilinear DCM - pE_D = []; -else - % nonlinear DCM - D = D*0; - pE_D = [D(:)]; -end - - -% HEMODYNAMIC PRIORS -%========================================================================== -% P(1) - signal decay - d(ds/dt)/ds) half-life = log(2)/P(1) ~ 1sec -% P(2) - auto-regulation - d(ds/dt)/df) 2*pi*sqrt(1/P(2)) ~ 10 sec -% P(3) - transit time (t0) ~ 1 sec -% P(4) - exponent for Fout(v) (alpha) c.f. Grubb's exponent (~ 0.38) -% P(5) - resting oxygen extraction (E0) ~ range 20 - 50% -% P(6) - ratio: intra- to extravascular components of gradient echo signal: -% epsilon (prior mean = 1, log-normally distributed scaling factor) -[qE,qC] = spm_hdm_priors(0); - - -% combine connectivity and hemodynamic priors -%========================================================================== -qC = kron(qC,eye(n,n)); -qE = kron(qE,ones(n,1)); -pE = [pE; qE; pE_D]; -pC = blkdiag(pC,qC,pC_D); - - -return diff --git a/spm_dcm_reshape.m b/spm_dcm_reshape.m deleted file mode 100644 index 79afb75..0000000 --- a/spm_dcm_reshape.m +++ /dev/null @@ -1,57 +0,0 @@ -function [A,B,C,H,D] = spm_dcm_reshape(P,m,n,r) -% Converts free parameter vector to matrices -% FORMAT [A,B,C,H,[D]] = spm_dcm_reshape(P,m,n,[r]) -% -% P - parameter vector -% m - number of inputs -% n - number of regions -% [r] - returns relative connections {without scaling by P(1)} -% -% A - intrinsic connections -% B - modulatory connections -% C - direct connections -% H - hemodynamic parameters -% [D] - nonlinear connections -% -% NB: order of parameter vector is: -% bilinear neural params -> hemodynamic params -> nonlinear neural params -%__________________________________________________________________________ -% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging - -% Karl Friston -% $Id: spm_dcm_reshape.m 3547 2009-11-09 18:29:59Z guillaume $ - - P = full(P); - i = cumsum([1 n*n n*n*m n*m n*6 n*n*n]); - -% scaling factor (relative connections) [1] -%-------------------------------------------------------------------------- -if nargin == 4 - q = 1; -else - q = exp(P(1)); -end - -% fill in intrinsic connections {A} [n x n] -%-------------------------------------------------------------------------- -A = reshape(P((i(1)+1):i(2)),n,n) * q; - -% fill in modulatory connections {B} [n x n x m] -%-------------------------------------------------------------------------- -B = reshape(P((i(2)+1):i(3)),n,n,m) * q; - -% fill in direct connections {C} [n x m] -%-------------------------------------------------------------------------- -C = reshape(P((i(3)+1):i(4)),n,m); - -% fill in 6 hemodynamic parameters {H} [n x 6] -%-------------------------------------------------------------------------- -H = reshape(P((i(4)+1):i(5)),n,6); - -% fill in nonlinear connections {D} [n x n x n] -%-------------------------------------------------------------------------- -if nargout > 4 - % NB: there is one D matrix for each region, and each D matrix is - % normalized in the same way as the A and B matrices - D = reshape(P((i(5)+1):i(6)),n,n,n) * q; -end diff --git a/spm_dcm_review.m b/spm_dcm_review.m index 36f7122..262bd9a 100644 --- a/spm_dcm_review.m +++ b/spm_dcm_review.m @@ -1,268 +1,256 @@ -function spm_dcm_review(DCM) -% Review a previously estimated DCM -% FORMAT spm_dcm_review(DCM) +function spm_dcm_review(DCM,action) +% Review an estimated DCM +% FORMAT spm_dcm_review(DCM,action) % -% DCM - DCM filename +% DCM - DCM filename +% +% action - +% 'fixed connections' +% [' effects of ' DCM.U.name{i}]; +% 'contrast of connections' +% 'location of regions' +% 'inputs' +% 'outputs' +% 'kernels' +% 'estimates of states' +% 'estimates of parameters' +% 'estimates of precisions' +% [' hidden states: ' DCM.Y.name{i}] %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_dcm_review.m 1900 2008-07-09 14:57:34Z guillaume $ - - -% Get figure handles -%-------------------------------------------------------------------------- -Fgraph = spm_figure('GetWin','Graphics'); +% $Id: spm_dcm_review.m 3888 2010-05-15 18:49:56Z karl $ -% Get results -%-------------------------------------------------------------------------- +%-Get DCM structure +%========================================================================== if ~nargin [DCM, sts] = spm_select(1,'^DCM.*\.mat$','select DCM_???.mat'); if ~sts, return; end end if ~isstruct(DCM) - P = DCM; - try - load(DCM); - catch - error('Cannot load DCM file "%s".',P); - end -else - % DCM can't be a structure as requires filename. + load(DCM); end -% Get model specification structure (see spm_nlsi) +%-Get model specification structure (see spm_nlsi) %-------------------------------------------------------------------------- try - m = DCM.M.m; - n = DCM.M.n; - l = DCM.M.l; + m = DCM.M.m; % number of inputs + n = DCM.M.n; % number of hidden states + l = DCM.M.l; % number of regions (responses) + U = 0.9; % p-value threshold for display catch - error('This model has not been estimated yet.'); + m = size(DCM.U.u,2); + l = DCM.n; end -% Check whether the model is an averaged DCM -%-------------------------------------------------------------------------- -try - averaged = DCM.averaged; -catch - averaged = false; -end -if averaged - str = {... - 'This model is an "averaged" DCM, containing the results of a Bayesian fixed effects analysis.', ... - 'It only contains averaged parameter estimates and their posterior probabilities.', ... - ' ', ... - ' functions are disabled except for computing contrasts.'}; - spm('alert!',str,'DCM ',spm('Cmdline')); +% experimental input specific reports +%---------------------------------------------------------------------- +for i = 1:m + str{i} = [' effects of ' DCM.U.name{i}]; end +% connectivity and kernels +%---------------------------------------------------------------------- +str{end + 1} = 'fixed connections'; -% Get threshold and recompute posterior probabilities -%-------------------------------------------------------------------------- -str = 'Threshold {Hz}'; -DCM.T = spm_input(str,1,'e',0,[1 1]); -sw = warning('off','SPM:negativeVariance'); -pp = 1 - spm_Ncdf(DCM.T,abs(DCM.Ep),diag(DCM.Cp)); -warning(sw); -[pA pB pC] = spm_dcm_reshape(pp,m,l,1); -DCM.pA = pA; -DCM.pB = pB; -DCM.pC = pC; - - -% Menu -%-------------------------------------------------------------------------- -str = {}; -if averaged - % averaged DCM: only allow for 'contrast' option - str = {'Contrast of connections', 'Quit'}; +if isfield(DCM,'averaged') + str = {str{:},'contrast of connections'}; else - % normal (non-averaged DCMs) - for i = 1:m - str{i} = [' Effects of ' DCM.U.name{i} ' ']; + str = {str{:} ,... + 'contrast of connections',... + 'location of regions',... + 'inputs',... + 'outputs',... + 'kernels'}; + if isfield(DCM,'qP') + str = {str{:} ,... + 'estimates of states',... + 'estimates of parameters',... + 'estimates of precisions'}; + + % region specific reports + %------------------------------------------------------------------ + for i = 1:l + str{end + 1} = [' hidden states: ' DCM.Y.name{i}]; + end end - str{m + 1} = ' Intrinsic connections'; - str = {str{:} ,... - 'Contrast of connections',... - 'Location of regions',... - 'Inputs',... - 'Outputs',... - '1st order Kernels',... - 'Quit'}; end +str{end + 1} = 'quit'; -while true +%-Get action +%========================================================================== +try + action; +catch - %-get options + %-Get action %---------------------------------------------------------------------- - OPT = spm_input('display',2,'m',str); - figure(Fgraph); - spm_figure('Clear',Fgraph); + if isfield(DCM,'M') + action = str{spm_input('review',1,'m',str)}; + else + str2 = str([m+3 m+4 end]); + action = str2{spm_input('review',1,'m',str2)}; + end +end + + +%-Exponentiate coupling parameters if a two-state model +%-------------------------------------------------------------------------- +try + if DCM.options.two_state + Ep.A = exp(DCM.Ep.A); + Ep.B = exp(DCM.Ep.B); + Ep.D = exp(DCM.Ep.D); + Ep.C = DCM.Ep.C; + disp('NB: The (A,B,D) parameters are scale parameters') + else + Ep.A = DCM.Ep.A; + Ep.B = DCM.Ep.B; + Ep.D = DCM.Ep.D; + Ep.C = DCM.Ep.C; + end +end + +%-Set up Graphics window +%-------------------------------------------------------------------------- +if nargin < 2 + Fgraph = spm_figure('GetWin','Graphics'); + figure(Fgraph); spm_figure('Clear',Fgraph); +end + +switch action %====================================================================== % Inputs %====================================================================== - if (OPT <= m) && ~averaged + case str(1:m) %-input effects %------------------------------------------------------------------ subplot(2,1,1) - i = OPT; - b = DCM.pB(:,:,i); - b(:,:,2) = DCM.B(:,:,i); - c = DCM.pC(:,i); - c(:,2) = DCM.C(:,i); + i = find(strcmp(action,str)); + b(:,:,1) = DCM.Pp.B(:,:,i); + b(:,:,2) = Ep.B(:,:,i); + c(:,1) = DCM.Pp.C(:,i); + c(:,2) = Ep.C(:,i); spm_dcm_display(DCM.xY,b,c) - title({ str{OPT};... - sprintf('P(|connection| > %0.2f)',DCM.T);... - 'connection strength'},'FontSize',12) + title(sprintf('%s P(coupling > %0.2f)',action,DCM.T),'FontSize',16) %-direct effects - connections %------------------------------------------------------------------ subplot(4,2,5) - bar(DCM.C(:,i)) - title('C - direct effects {Hz}','FontSize',12) + bar(c(:,2)) + title('C - direct effects (Hz)','FontSize',14) set(gca,'XTick',[1:l],'XTickLabel',DCM.Y.name) axis square - grid on + %-direct effects - probabilities %------------------------------------------------------------------ subplot(4,2,6) - bar(DCM.pC(:,i)) - title('C {probabilities}','FontSize',12) + P = c(:,1); + bar(P), hold on, plot([0 (length(P) + 1)],[U U],'-.r'), hold off + title('C - probability','FontSize',14) set(gca,'XTick',[1:l],'XTickLabel',DCM.Y.name) - ylabel(sprintf('P(A > %0.2f)',DCM.T)) + ylabel(sprintf('P(C > %0.2f)',DCM.T)) axis square - grid on + %-modulatory effects - connections %------------------------------------------------------------------ subplot(4,2,7) - bar3(DCM.B(:,:,i),0.4) - set(gca,'YTick',[1:l],'YTickLabel',DCM.Y.name) + bar(b(:,:,2)) + title('B - modulatory effects {Hz}','FontSize',14) set(gca,'XTick',[1:l],'XTickLabel',DCM.Y.name) - title('B - modulatory effects {Hz}','FontSize',12) - xlabel('from') - ylabel('to') - axis square + xlabel('target region') + ylabel('strength (Hz)') + %-modulatory effects - probabilities %------------------------------------------------------------------ subplot(4,2,8) - bar3(DCM.pB(:,:,i),0.4) - title('B {probabilities}','FontSize',12) + P = b(:,:,1); + bar(P), hold on, plot([0 (length(P) + 1)],[U U],'-.r'), hold off + title('B - probability','FontSize',14) set(gca,'XTick',[1:l],'XTickLabel',DCM.Y.name) - set(gca,'YTick',[1:l],'YTickLabel',DCM.Y.name) - xlabel('from') - ylabel('to') - zlabel(sprintf('P(A > %0.2f)',DCM.T)) - axis square - grid on + xlabel('target region') + ylabel(sprintf('P(B > %0.2f)',DCM.T)) + legend(DCM.Y.name) %====================================================================== - % Intrinsic connections + % Fixed connections %====================================================================== - elseif (OPT == 1 + m) && ~averaged + case {'fixed connections'} % Intrinsic effects %------------------------------------------------------------------ subplot(2,1,1) - a = DCM.pA; - a(:,:,2) = DCM.A; + a(:,:,1) = DCM.Pp.A; + a(:,:,2) = Ep.A; spm_dcm_display(DCM.xY,a) - title({ str{OPT};... - sprintf('P(|connection| > %0.2f)',DCM.T);... - 'connection strength'},'FontSize',10) + title(sprintf('%s P(coupling > %0.2f)','fixed',DCM.T),'FontSize',16) + % intrinsic interactions %------------------------------------------------------------------ subplot(2,2,3) - bar3(DCM.A,0.4) - title('A - Intrinsic connections','FontSize',12) + bar(a(:,:,2)) + title('A - fixed effects','FontSize',16) set(gca,'XTick',[1:l],'XTickLabel',DCM.Y.name) - set(gca,'YTick',[1:l],'YTickLabel',DCM.Y.name) - xlabel('from') - ylabel('to') - grid on - axis square + xlabel('target region') + ylabel('strength (Hz)') + legend(DCM.Y.name) + % intrinsic interactions - probabilities %------------------------------------------------------------------ subplot(2,2,4) - bar3(DCM.pA,0.4) - title('A {probabilities}','FontSize',12) + P = a(:,:,1); + bar(P), hold on, plot([0 (length(P) + 1)],[U U],'-.r'), hold off + title('A - probability','FontSize',16) set(gca,'XTick',[1:l],'XTickLabel',DCM.Y.name) - set(gca,'YTick',[1:l],'YTickLabel',DCM.Y.name) - xlabel('from') - ylabel('to') - zlabel(sprintf('P(A > %0.2f)',DCM.T)) - grid on - axis square + xlabel('target region') + ylabel(sprintf('P(A > %0.2f)',DCM.T)) %====================================================================== % Contrast %====================================================================== - elseif ((OPT == 2 + m) && ~averaged) || ((OPT == 1) && averaged) + case {'contrast of connections'} %-get contrast %------------------------------------------------------------------ - D = spm_input('contrast for',1,'b',{'A','B','C'}); + T = spm_input('Threshold (Hz)',1,'r',0); + D = spm_input('contrast for',2,'b',{'A','B','C'}); + C = spm_dcm_contrasts(DCM,D); - switch D - - % intrinsic connections - %-------------------------------------------------------------- - case 'A' - C = spm_dcm_contrasts(P,'A'); - i = find(C); j = 1; - C = sparse(i + j,1,C(i),length(DCM.Ep),1); - - % modulatory inputs - %-------------------------------------------------------------- - case 'B' % modulatory inputs - C = spm_dcm_contrasts(P,'B'); - i = find(C); j = 1 + l*l; - C = sparse(i + j,1,C(i),length(DCM.Ep),1); - - % direct (driving) inputs - %-------------------------------------------------------------- - case 'C' - C = spm_dcm_contrasts(P,'C'); - i = find(C); j = 1 + l*l + l*l*m; - C = sparse(i + j,1,C(i),length(DCM.Ep),1); - - end %-posterior density and inference %------------------------------------------------------------------ - c = C'*DCM.Ep; + c = C'*spm_vec(DCM.Ep); v = C'*DCM.Cp*C; x = c + [-512:512]*sqrt(v)*6/512; p = full(1/sqrt(2*pi*v)*exp(-[x - c].^2/(2*v))); - % conversion to full necessary to account for sparse matrices bug in MATLAB 6.5.0 R13 - sw = warning('off','SPM:negativeVariance'); - PP = 1 - spm_Ncdf(DCM.T,c,v); + sw = warning('off','SPM:negativeVariance'); + PP = 1 - spm_Ncdf(T,c,v); warning(sw); figure(Fgraph) subplot(2,1,1) - plot(x,p,[1 1]*DCM.T,[0 max(p)],'-.'); - title({'Posterior density of contrast',... - sprintf('P(contrast > %0.2f) = %.1f%s',DCM.T,PP*100,'%')},... - 'FontSize',12) - xlabel('contrast') + plot(x,p,[1 1]*T,[0 max(p)],'-.'); + str = sprintf('%s P(contrast > %0.2f) = %.1f%s','Posterior density',T,PP*100,'%'); + title(str,'FontSize',16) + xlabel('contrast of parameter estimates') ylabel('probability density') - i = find(x >= DCM.T); + i = find(x >= T); hold on fill([x(i) fliplr(x(i))],[i*0 fliplr(p(i))],[1 1 1]*.8) axis square, grid on @@ -270,16 +258,16 @@ function spm_dcm_review(DCM) %-contrast %------------------------------------------------------------------ - [A B C] = spm_dcm_reshape(C,m,l,1); + C = spm_unvec(C,DCM.Ep); subplot(4,2,5) - imagesc(A) + imagesc(C.A) title('contrast {A}','FontSize',12) set(gca,'YTick',[1:l],'YTickLabel',DCM.Y.name) set(gca,'XTick',[1:l],'XTickLabel',DCM.Y.name) axis image subplot(4,2,6) - imagesc(C) + imagesc(C.C) title('contrast {C}','FontSize',12) set(gca,'XTick',[1:m],'XTickLabel',DCM.U.name) set(gca,'YTick',[1:l],'YTickLabel',DCM.Y.name) @@ -287,7 +275,7 @@ function spm_dcm_review(DCM) for i = 1:m subplot(4,m,i + 3*m) - imagesc(B(:,:,i)) + imagesc(C.B(:,:,i)) title(['contrast {B}-' DCM.U.name{i}],'FontSize',12) set(gca,'XTick',[1:l],'XTickLabel',DCM.Y.name) set(gca,'YTick',[1:l],'YTickLabel',DCM.Y.name) @@ -298,39 +286,24 @@ function spm_dcm_review(DCM) %====================================================================== % Location of regions %====================================================================== - elseif (OPT == 3 + m) && ~averaged + case {'location of regions'} % transverse %------------------------------------------------------------------ - subplot(2,2,3) - title('transverse') - u = [[0 1 0];[-1 0 0]]'; - spm_dcm_display(DCM.xY,[],[],u,32); - - % sagittal - %------------------------------------------------------------------ - subplot(2,2,1) - title('sagittal') - u = [[0 1 0];[0 0 1]]'; - spm_dcm_display(DCM.xY,[],[],u,32); + subplot(2,1,1) + spm_dcm_display(DCM.xY); + title('Regional locations','FontSize',16) - % coronal - %------------------------------------------------------------------ - subplot(2,2,2) - title('coronal') - u = [[1 0 0];[0 0 1]]'; - spm_dcm_display(DCM.xY,[],[],u,32); % table %------------------------------------------------------------------ - subplot(2,2,4) - title(str{OPT},'FontSize',12) + subplot(2,1,2) y = 0; line([0 4],[y y]) y = y - 1; - text(0.0,y,'Name', 'FontSize',10) - text(1.0,y,'Voxels', 'FontSize',10) - text(2.0,y,'Location (mm)','FontSize',10) + text(0.0,y,'Name', 'FontSize',14) + text(1.0,y,'Voxels', 'FontSize',14) + text(2.0,y,'Location (mm)','FontSize',14) y = y - 1; line([0 4],[y y],'LineWidth',4) y = y - 1; @@ -339,85 +312,74 @@ function spm_dcm_review(DCM) N = length(DCM.xY(i).s); L = DCM.xY(i).xyz; r = DCM.xY(i).spec; - text(0,y,name, 'FontSize',8) - text(1,y,sprintf('%0.0f',N), 'FontSize',8) - text(2,y,sprintf('%-4.0f %-4.0f %-4.0f',L),'FontSize',8) + text(0,y,name, 'FontWeight','bold', 'FontSize',12) + text(1,y,sprintf('%0.0f',N), 'FontSize',12) + text(2,y,sprintf('%-4.0f %-4.0f %-4.0f',L),'FontSize',12) y = y - 1; end line([0 4],[y y]) axis off square - + %====================================================================== % Inputs %====================================================================== - elseif (OPT == 4 + m) && ~averaged + case {'inputs'} - % graph + % priors %------------------------------------------------------------------ - x = [1:length(full(DCM.U.u))]*DCM.U.dt; + x = (1:length(DCM.U.u))*DCM.U.dt; + t = (1:length(DCM.Y.y))*DCM.Y.dt; for i = 1:m + subplot(m,1,i) plot(x,full(DCM.U.u(:,i))) - title(['Input - ' DCM.U.name{i}],'FontSize',12) - %axis tight - ylabel('event density {Hz}') - if i==m - xlabel('time {seconds}') + + % posteriors (if stochastic DCM) + %-------------------------------------------------------------- + if DCM.options.stochastic + hold on + plot(t,DCM.qU.v{2}(i,:),':') + hold off end - %axis square tight - grid on - % Change axis so we can see boxcars properly - u_min=min(full(DCM.U.u(:,i))); - u_max=max(full(DCM.U.u(:,i))); - u_range=u_max-u_min; - axis([0 max(x) u_min-0.1*u_range u_max*1.1]); + + title(['Input - ' DCM.U.name{i}],'FontSize',16) + ylabel('event density {Hz}') + a = axis; + axis([0 max(x) (a(3) - 1/8) (a(4) + 1/8)]); + end + xlabel('time {seconds}') + if DCM.options.stochastic + legend({'prior','posterior'}) end %====================================================================== % Outputs %====================================================================== - elseif (OPT == 5 + m) && ~averaged + case {'outputs'} % graph %------------------------------------------------------------------ x = [1:length(DCM.y)]*DCM.Y.dt; for i = 1:l subplot(l,1,i); - plot(x,DCM.Y.y(:,i)); - if i==l - xlabel('time {seconds}'); - end - grid on - hold on - - % Remove zero columns from X0 if there are any - % (although there should'nt be !) - % Otherwise we won't be able to evaluate inv(X0'X0) - X0 = DCM.Y.X0; - X0 = X0(:,any(X0)); - - % Note: adding on X0*beta to DCM prediction y - % is equivalent to orthogonalising y WRT X0 - % because data have already been orth wrt X0 - % (overall_prediction=DCM.y(:,i)+X0*beta;) - overall_prediction=DCM.y(:,i)-X0*inv(X0'*X0)*X0'*DCM.y(:,i); - plot(x,overall_prediction,'r'); - title([DCM.Y.name{i} ': data and model predictions' ],'FontSize',12); - axis normal + plot(x,DCM.y(:,i),x,DCM.y(:,i) + DCM.R(:,i),':'); + title([DCM.Y.name{i} ': responses and predictions' ],'FontSize',16); end + xlabel('time {seconds}'); + legend('predicted', 'observed') %====================================================================== % Kernels %====================================================================== - elseif (OPT == 6 + m) && ~averaged + case {'kernels'} % input effects %------------------------------------------------------------------ - x = [1:DCM.M.N] * DCM.M.dt; - d = 2 / DCM.M.dt; + x = (1:DCM.M.N)*DCM.M.dt; + d = 2/DCM.M.dt; for i = 1:m % input effects - neuronal @@ -427,12 +389,11 @@ function spm_dcm_review(DCM) plot(x,y) set(gca,'XLim',[0 16]) axis square - title(['neuronal responses to ' DCM.U.name{i}]) - grid on + title(['neuronal responses to ' DCM.U.name{i}],'FontSize',12) xlabel('time {seconds}') for j = 1:l text(x(j*d),y(j*d,j),DCM.Y.name{j},... - 'FontSize',8,... + 'FontWeight','bold','FontSize',12,... 'HorizontalAlignment','Center') end @@ -444,25 +405,108 @@ function spm_dcm_review(DCM) plot(x,k,x,y,':') set(gca,'XLim',[0 16]) axis square - title('hemodynamic responses') - grid on + title('hemodynamic responses','FontSize',12) xlabel('time {seconds}') for j = 1:l text(x(j*d),k(j*d,j),DCM.Y.name{j},... - 'FontSize',8,... + 'FontWeight','bold','FontSize',12,... 'HorizontalAlignment','Center') end - + end - %====================================================================== - % Quit + % DEM estimates (using standard format) %====================================================================== - elseif ((OPT == 7 + m) && ~averaged) || ((OPT == 2) && averaged) + case {'estimates of states'} + spm_DEM_qU(DCM.qU) - return + case {'estimates of parameters'} + spm_DEM_qP(DCM.qP) - end + case {'estimates of precisions'} + spm_DEM_qH(DCM.qH) + + case {str{end - l:end - 1}} + + + % get region + %------------------------------------------------------------------ + i = find(strcmp(action,str)) + m - length(str) + 1; + t = [1:length(DCM.Y.y)]*DCM.Y.dt; -end \ No newline at end of file + + % hidden states - causes + %------------------------------------------------------------------ + subplot(4,1,1) + j = find(DCM.c(i,:)); + if isempty(j) + x = DCM.qU.v{2}; + else + x = DCM.qU.v{2}(j,:); + end + plot(t,x) + title(['inputs or causes - ' DCM.Y.name{i}],'FontSize',16) + + + % hidden states - neuronal + %------------------------------------------------------------------ + subplot(4,1,2) + j = DCM.M.x; + if DCM.options.two_state + j(i,[1 2 6]) = 1; + else + j(i,[1 2]) = 1; + end + j = find(j(:)); + x = DCM.qU.x{1}(j,:); + plot(t,x) + title('hidden states - neuronal', 'FontSize',16) + if DCM.options.two_state + legend({'excitatory','signal','inhibitory'}) + else + legend({'excitatory','signal'}) + end + + + % hidden states - hemodynamic + %------------------------------------------------------------------ + subplot(4,1,3) + j = DCM.M.x; + j(i,[3 4 5]) = 1; + j = find(j(:)); + x = DCM.qU.x{1}(j,:); + plot(t,exp(x)) + title('hidden states - hemodynamic', 'FontSize',16) + legend({'flow','volume','dHb'}) + + + % response + %------------------------------------------------------------------ + subplot(4,1,4) + y = DCM.qU.v{1}(i,:); + x = DCM.qU.v{1}(i,:) + DCM.qU.z{1}(i,:); + plot(t,x,t,y) + title('predicted BOLD signal', 'FontSize',16) + xlabel('time (seconds)') + legend({'observed','predicted'}) + + + %====================================================================== + % Quit + %====================================================================== + case {'quit'} + return; + + %====================================================================== + % Unknown action + %====================================================================== + otherwise + disp('unknown option') +end + +% retutn to menu +%-------------------------------------------------------------------------- +if nargin < 2 + spm_dcm_review(DCM); +end diff --git a/spm_dcm_sessions.m b/spm_dcm_sessions.m index 5d7eaf6..916bd81 100644 --- a/spm_dcm_sessions.m +++ b/spm_dcm_sessions.m @@ -26,67 +26,54 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Will Penny -% $Id: spm_dcm_sessions.m 1711 2008-05-22 11:09:13Z guillaume $ +% $Id: spm_dcm_sessions.m 3705 2010-02-01 20:51:28Z karl $ Finter = spm_figure('GetWin','Interactive'); Fgraph = spm_figure('GetWin','Graphics'); num_models = spm_input('Apply contrast to how many DCM models ? ','+1','r',[],1); -P = spm_select(num_models,'^DCM.*\.mat$','select DCM*.mat files'); +P = spm_select(num_models,'^DCM.*\.mat$','select DCM*.mat files'); % Get contrast -str = 'contrast for'; -D = spm_input(str,1,'b',{'A','B','C'}); +str = 'contrast for'; +D = spm_input(str,1,'b',{'A','B','C'}); load(deblank(P(1,:))); -con=spm_dcm_contrasts(deblank(P(1,:)),D); +con = spm_dcm_contrasts(deblank(P(1,:)),D); % Get threshold -str = 'Threshold'; -DCM.T = spm_input(str,1,'e',0,[1 1]); -T=DCM.T; +str = 'Threshold'; +DCM.T = spm_input(str,1,'e',0,[1 1]); +T = DCM.T; % Get mean and variance of effect in each model -con_error=0; -for model=1:num_models, +con_error = 0; +for model = 1:num_models, load(deblank(P(model,:))); - drawnow; - - l = DCM.M.l; - m = DCM.M.m; - i = find(con); - switch D, - case 'A', - j = 1; - case 'B', - j = 1 + l*l; - case 'C', - j = 1 + l*l + l*l*m; - end - C = sparse(i + j,1,con(i),length(DCM.Ep),1); - mean_con(model) = full(C')*full(DCM.Ep); - var_con(model) = full(C')*full(DCM.Cp)*full(C); + mean_con(model) = full(con')*full(spm_vec(DCM.Ep)); + var_con(model) = full(con')*full(DCM.Cp)*full(con); disp(sprintf('Model %d, Contrast Mean=%1.4f, Contrast Variance=%1.4f',model,mean_con(model),var_con(model))); - if var_con(model)==0 + if var_con(model) == 0 disp(sprintf('Error in spm_dcm_sessions: this contrast not valid for model %d',model)); con_error=1; end end +% Invalid contrast specified +%-------------------------------------------------------------------------- if con_error - % Invalid contrast specified return end %- Bayesian fixed effects analysis -%----------------------------------------------------------- -precision_con=1./var_con; -precision=sum(precision_con); -v=1/precision; +%-------------------------------------------------------------------------- +precision_con = 1./var_con; +precision = sum(precision_con); +v = 1/precision; c = sum((precision_con.*mean_con)/precision); -x = c + [-32:32]*sqrt(v)*6/32; -p = 1/sqrt(2*pi*v)*exp(-[x - c].^2/(2*v)); -PP = 1 - spm_Ncdf(T,c,v); +x = c + [-32:32]*sqrt(v)*6/32; +p = 1/sqrt(2*pi*v)*exp(-[x - c].^2/(2*v)); +PP = 1 - spm_Ncdf(T,c,v); disp(' '); disp(sprintf('Bayesian Fixed Effect Mean = %1.4f', full(c))); disp(sprintf('Bayesian Fixed Effect Variance = %1.4f', full(v))); @@ -96,7 +83,7 @@ plot(x,p,[1 1]*T,[0 max(p)],'-.'); title({'Bayesian Fixed Effects: Posterior density of contrast',... sprintf('P(contrast > %0.2f) = %.1f%s',T,PP*100,'%')},... - 'FontSize',12) + 'FontSize',12) xlabel('contrast'); ylabel('probability density'); @@ -109,12 +96,11 @@ % Random effects analysis % - assuming an inverse gamma prior on the variance % the posterior is a t-distribution - +%-------------------------------------------------------------------------- v = std(mean_con)^2; c = mean(mean_con); t = (sqrt(num_models)*(c-T))/sqrt(v); x = c + [-32:32]*sqrt(v)*6/32; -% p = 1/sqrt(2*pi*v)*exp(-[x - c].^2/(2*v)); p = spm_Tpdf((sqrt(num_models)*(x-c))/sqrt(v),num_models-1); PP = spm_Tcdf(t,num_models-1); disp(' '); @@ -125,7 +111,7 @@ plot(x,p,[1 1]*T,[0 max(p)],'-.'); title({'Bayesian Random Effects: Posterior density of contrast',... sprintf('P(contrast > %0.2f) = %.1f%s',T,PP*100,'%')},... - 'FontSize',12) + 'FontSize',12) xlabel('contrast'); ylabel('probability density'); @@ -137,8 +123,9 @@ % Get Classical RFX p-value % Note: 1-p is equal to Bayesian RFX if T=0 -t=(sqrt(num_models)*c)/sqrt(v); -p= 1 - spm_Tcdf(t,num_models-1); +%-------------------------------------------------------------------------- +t = (sqrt(num_models)*c)/sqrt(v); +p = 1 - spm_Tcdf(t,num_models - 1); disp(sprintf('Classical Random Effects p-value = %1.4f', p)); disp('Note: 1-p is equal to Bayesian RFX if threshold is zero'); spm_input('Thank you',1,'d'); diff --git a/spm_dcm_specify.m b/spm_dcm_specify.m index ae83400..7a01a39 100644 --- a/spm_dcm_specify.m +++ b/spm_dcm_specify.m @@ -7,10 +7,17 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_dcm_specify.m 2671 2009-01-29 19:37:36Z klaas $ +% $Id: spm_dcm_specify.m 3710 2010-02-03 19:11:26Z guillaume $ + +%-Interactive window +%-------------------------------------------------------------------------- Finter = spm_figure('GetWin','Interactive'); +bcolor = get(Finter,'color'); WS = spm('WinScale'); +dx = 20; + +spm_input('Specify DCM:... ',1,'d'); %========================================================================== % Get design and directory @@ -23,12 +30,14 @@ catch error(['Cannot read ' fullfile(swd,'SPM.mat')]); end - + + %========================================================================== % Name %========================================================================== name = spm_input('name for DCM_???.mat','+1','s'); + %========================================================================== % Outputs %========================================================================== @@ -38,10 +47,11 @@ P = cellstr(spm_select([2 8],'^VOI.*\.mat$',{'select VOIs'},'',swd)); m = numel(P); for i = 1:m - p = load(P{i},'xY','-mat'); + p = load(P{i},'xY'); xY(i) = p.xY; end + %========================================================================== % Inputs %========================================================================== @@ -55,74 +65,117 @@ U.name = {}; U.u = []; for i = 1:u - for j = 1:length(Sess.U(i).name) - str = ['include ' Sess.U(i).name{j} '?']; - if spm_input(str,2,'y/n',[1 0]) + for j = 1:length(Sess.U(i).name) + str = ['include ' Sess.U(i).name{j} '?']; + if spm_input(str,'+1','y/n',[1 0],1) U.u = [U.u Sess.U(i).u(33:end,j)]; U.name{end + 1} = Sess.U(i).name{j}; end end end + +%========================================================================== +% Timings +%========================================================================== + +spm_input('Timing information:... ',-1,'d'); + +%-Slice timings +%-------------------------------------------------------------------------- +RT = SPM.xY.RT; +delays = spm_input('Slice timings [s]','+1','r', repmat(RT,1,m),m,[0 RT]); + +%-Echo time (TE) of data acquisition +%-------------------------------------------------------------------------- +TE = 0.04; +TE_ok = 0; +while ~TE_ok + TE = spm_input('Echo time, TE [s]', '+1', 'r', TE); + if ~TE || (TE < 0) || (TE > 0.1) + str = { 'Extreme value for TE or TE undefined.',... + 'Please re-enter TE (in seconds!)'}; + spm_input(str,'+1','bd','OK',[1],1); + else + TE_ok = 1; + end +end + + +%========================================================================== +% Model options +%========================================================================== +spm_input('Model options:... ',-1,'d'); +options.nonlinear = spm_input('modulatory effects','+1','b',{'bilinear','nonlinear'},[0 1],1); +options.two_state = spm_input('states per region', '+1','b',{'one','two'},[0 1],1); +options.stochastic = spm_input('stochastic effects','+1','b',{'no','yes'},[0 1],1); + + %========================================================================== % Graph connections %========================================================================== n = size(U.u,2); a = zeros(m,m); -c = zeros(m,n); b = zeros(m,m,n); -q = uicontrol(Finter,'String','done','Position',[300 100 060 020].*WS); -dx = 20; +c = zeros(m,n); +d = zeros(m,m,0); %-Intrinsic connections (A matrix) +%========================================================================== + +%-Buttons and labels %-------------------------------------------------------------------------- spm_input('Specify intrinsic connections from',1,'d') spm_input('to',3,'d') - for i = 1:m str = sprintf('%s %i',xY(i).name,i); h1(i) = uicontrol(Finter,'String',str,... 'Style','text',... + 'FontSize',10,... + 'BackgroundColor',bcolor,... 'HorizontalAlignment','right',... - 'Position',[080 356-dx*i 080 020].*WS); + 'Position',[080 350-dx*i 080 020].*WS); h2(i) = uicontrol(Finter,'String',sprintf('%i',i),... 'Style','text',... - 'Position',[180+dx*i 356 020 020].*WS); + 'FontSize',10,... + 'BackgroundColor',bcolor,... + 'Position',[180+dx*i 350 010 020].*WS); end for i = 1:m for j = 1:m h3(i,j) = uicontrol(Finter,... - 'Position',[180+dx*j 360-dx*i 020 020].*WS,... + 'Position',[180+dx*j 350-dx*i 020 020].*WS,... + 'BackgroundColor',bcolor,... 'Style','radiobutton'); if i == j set(h3(i,j),'Value',1,... - 'enable','off',... - 'BackgroundColor',[0.5 0.5 0.5]); + 'enable','off'); + else + set(h3(i,j),'TooltipString', ... + sprintf('from %s to %s',xY(j).name,xY(i).name)); end end end -drawnow +uicontrol(Finter,'String','done','Position', [300 100 060 020].*WS,... + 'Callback', 'uiresume(gcbf)'); + +uiwait(Finter); -%-Wait for 'done' +%-Get a %-------------------------------------------------------------------------- -while true - pause(0.01); - if strcmp(get(gco,'Type'),'uicontrol') - if strcmp(get(gco,'String'),'done') - for i = 1:m - for j = 1:m - a(i,j) = get(h3(i,j),'Value'); - end - end - delete([h1(:); h2(:); h3(:)]); - break - end +for i = 1:m + for j = 1:m + a(i,j) = get(h3(i,j),'Value'); end end +delete(findobj(get(Finter,'Children'),'flat')); + %-Effects of causes (B and C matrices) -%-------------------------------------------------------------------------- +%========================================================================== +uicontrol(Finter,'String','done','Position', [300 100 060 020].*WS,... + 'Callback', 'uiresume(gcbf)'); for k = 1:n %-Buttons and labels @@ -132,13 +185,15 @@ U.name{k}); spm_input(str,1,'d'); - dx = 20; for i = 1:m h1(i) = uicontrol(Finter,'String',xY(i).name,... 'Style','text',... - 'Position',[080 356-dx*i 080 020].*WS); + 'BackgroundColor',bcolor,... + 'FontSize',10,... + 'Position',[080 350-dx*i 080 020].*WS); h2(i) = uicontrol(Finter,... 'Position',[160 360-dx*i 020 020].*WS,... + 'BackgroundColor',bcolor,... 'Style','radiobutton'); end for i = 1:m @@ -148,61 +203,49 @@ % allow it to be modulated h3(i,j) = uicontrol(Finter,... 'Position',[220+dx*j 360-dx*i 020 020].*WS,... + 'BackgroundColor',bcolor,... 'Style','radiobutton'); + set(h3(i,j),'TooltipString', ... + sprintf('from %s to %s',xY(j).name,xY(i).name)); end end end - drawnow - - %-Wait for 'done' + + uiwait(Finter); + + %-Get c %---------------------------------------------------------------------- - set(gcf,'CurrentObject',h2(1)) - while(1) - pause(0.01) - if strcmp(get(gco,'Type'),'uicontrol') - if strcmp(get(gco,'String'),'done') - - %-Get c - %---------------------------------------------------------- - for i = 1:m - c(i,k) = get(h2(i) ,'Value'); - end - - %-Get b allowing any 2nd order effects - %---------------------------------------------------------- - for i = 1:m - for j = 1:m - if a(i,j)==1 - b(i,j,k) = get(h3(i,j),'Value'); - end - end - end - delete([h1(:); h2(:); h3(find(a==1))]) - break + for i = 1:m + c(i,k) = get(h2(i) ,'Value'); + end + %-Get b allowing any 2nd order effects + %---------------------------------------------------------------------- + for i = 1:m + for j = 1:m + if a(i,j)==1 + b(i,j,k) = get(h3(i,j),'Value'); end end end + delete([h1(:); h2(:); h3(a==1)]) + end -delete(q) +delete(findobj(get(Finter,'Children'),'flat')); %-Effects of nonlinear modulations (D matrices) -%-------------------------------------------------------------------------- -str = ['Nonlinear DCM ?']; -if spm_input(str,2,'y/n',[1 0]) - nlDCM = 1; - q = uicontrol(Finter,'String','done','Position',[300 100 060 020].*WS); +%========================================================================== +if options.nonlinear + uicontrol(Finter,'String','done','Position', [300 100 060 020].*WS,... + 'Callback', 'uiresume(gcbf)'); for k = 1:m %-Buttons and labels - %---------------------------------------------------------------------- - str = sprintf(... - 'Effects of %-12s activity on connections',... - xY(k).name); + %------------------------------------------------------------------ + str = sprintf('Effects of %-12s activity on connections',xY(k).name); spm_input(str,1,'d'); - dx = 20; for i = 1:m for j = 1:m if a(i,j)==1 @@ -210,80 +253,43 @@ % allow it to be modulated h4(i,j) = uicontrol(Finter,... 'Position',[220+dx*j 360-dx*i 020 020].*WS,... + 'BackgroundColor',bcolor,... 'Style','radiobutton'); end end end - drawnow - - %-Wait for 'done' - %---------------------------------------------------------------------- - set(gcf,'CurrentObject',h4(1)) - while(1) - pause(0.01) - if strcmp(get(gco,'Type'),'uicontrol') - if strcmp(get(gco,'String'),'done') - - %-Get d allowing any 2nd order effects - %---------------------------------------------------------- - for i = 1:m - for j = 1:m - if a(i,j)==1 - d(i,j,k) = get(h4(i,j),'Value'); - end - end - end - delete([h4(find(a==1))]) - break + uiwait(Finter); + + %-Get d allowing any 2nd order effects + %------------------------------------------------------------------ + for i = 1:m + for j = 1:m + if a(i,j)==1 + d(i,j,k) = get(h4(i,j),'Value'); end end end - end - delete(q) -else - nlDCM = 0; -end - - -%========================================================================== -% slice timing -%========================================================================== -delays = spm_input('Slice timings [s]', -1, 'r', SPM.xY.RT*ones(1, m), m, [0 SPM.xY.RT]); - + delete(h4(a==1)) -%========================================================================== -% echo time (TE) of data acquisition -%========================================================================== -TE = 0; -TE_ok = 0; -while ~TE_ok - TE = spm_input('Echo time, TE [s]'); - if ~TE || (TE < 0) || (TE > 0.1) - str = { 'Extreme value for TE or TE undefined.',... - 'Please re-enter TE (note this value must be in seconds!).'}; - spm_input(str,1,'bd','OK',[1],1); - else - TE_ok = 1; end end - +delete(findobj(get(Finter,'Children'),'flat')); spm_input('Thank you',1,'d') -%-Confounds (NB: the data have been filtered and whitened) -%-------------------------------------------------------------------------- -v = size(xY(1).u,1); -X0 = xY(1).X0; +%========================================================================== +% Response +%========================================================================== -%-Response variables +%-Response variables & confounds (NB: the data have been whitened) %-------------------------------------------------------------------------- -n = length(xY); +n = length(xY); % number of regions +v = length(xY(1).u); % number of time points Y.dt = SPM.xY.RT; -Y.X0 = X0; +Y.X0 = xY(1).X0; for i = 1:n - % regional responses Y.y(:,i) = xY(i).u; Y.name{i} = xY(i).name; end @@ -292,21 +298,25 @@ %-------------------------------------------------------------------------- Y.Q = spm_Ce(ones(1,n)*v); + +%========================================================================== +% DCM structure +%========================================================================== + %-Store all variables in DCM structure %-------------------------------------------------------------------------- -DCM.a = a; -DCM.b = b; -DCM.c = c; -if nlDCM - DCM.d = d; -end -DCM.U = U; -DCM.Y = Y; -DCM.xY = xY; -DCM.v = v; -DCM.n = n; -DCM.delays = delays; -DCM.TE = TE; +DCM.a = a; +DCM.b = b; +DCM.c = c; +DCM.d = d; +DCM.U = U; +DCM.Y = Y; +DCM.xY = xY; +DCM.v = v; +DCM.n = n; +DCM.TE = TE; +DCM.delays = delays; +DCM.options = options; %-Save %-------------------------------------------------------------------------- @@ -314,5 +324,4 @@ save(fullfile(swd,['DCM_' name]),'-V6','DCM'); else save(fullfile(swd,['DCM_' name]),'DCM'); -end; -return +end diff --git a/spm_dcm_ui.m b/spm_dcm_ui.m index e2d6924..f9f414c 100644 --- a/spm_dcm_ui.m +++ b/spm_dcm_ui.m @@ -23,21 +23,14 @@ function spm_dcm_ui(Action) % DCM.a - intrinsic connection matrix % DCM.b - input-dependent connection matrix % DCM.c - input connection matrix -% DCM.pA - pA - posterior probabilities -% DCM.pB - pB - posterior probabilities -% DCM.pC - pC - posterior probabilities -% DCM.vA - vA - variance of parameter estimates -% DCM.vB - vB - variance of parameter estimates -% DCM.vC - vC - variance of parameter estimates +% DCM.Pp - posterior probabilities +% DCM.Vp - variance of parameter estimates % DCM.H1 - 1st order Volterra Kernels - hemodynamic -% DCM.H2 - 1st order Volterra Kernels - hemodynamic -% DCM.K1 - 1st order Volterra Kernels - neuronal % DCM.K1 - 1st order Volterra Kernels - neuronal % DCM.R - residuals % DCM.y - predicted responses % DCM.xY - original response variable structures % DCM.T - threshold for inference based on posterior p.d.f -% DCM.Ce - Estimated observation noise covariance % DCM.v - Number of scans % DCM.n - Number of regions % @@ -72,7 +65,7 @@ function spm_dcm_ui(Action) % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_dcm_ui.m 3479 2009-10-19 10:10:55Z maria $ +% $Id: spm_dcm_ui.m 3958 2010-06-30 16:24:46Z guillaume $ % Get figure handles @@ -83,12 +76,15 @@ function spm_dcm_ui(Action) set(Finter,'Name','Dynamic Causal Modelling'); spm('Pointer','Arrow'); +% Temporary welcome message +%-------------------------------------------------------------------------- +disp('Please refer to this version as DCM10 in papers and publications.'); % Options, using pull-down menu %-------------------------------------------------------------------------- if ~nargin str = 'Action: '; - Actions = {'specify','estimate','review','compare','average (BPA)','average (BMA)','quit'}; + Actions = {'specify','estimate','review','compare','average','quit'}; selected = spm_input(str,1,'m',Actions); Action = Actions{selected}; end @@ -117,7 +113,8 @@ function spm_dcm_ui(Action) %-select DCM models %---------------------------------------------------------------------- - P = cellstr(spm_select(Inf,'^DCM.*\.mat$','select DCM_???.mat')); + [P, sts] = spm_select(Inf,'^DCM.*\.mat$','select DCM_???.mat'); + if ~sts, return; else P = cellstr(P); end spm('Pointer','Watch'); spm('FigName','Estimation in progress'); @@ -139,7 +136,7 @@ function spm_dcm_ui(Action) spm_dcm_review; - + %========================================================================== % Compare different models %========================================================================== @@ -149,25 +146,25 @@ function spm_dcm_ui(Action) spm_jobman('Interactive','','spm.stats.bms.bms_dcm'); - -%========================================================================== -% Average several models (Bayesian FFX) -%========================================================================== -case 'average (bpa)', - - spm('FnBanner','spm_dcm_average'); - - spm_dcm_average(1); % ERP: 0; fMRI: any value > 0 - + %========================================================================== -% Average model parameters from BMS (BMA) +% Average %========================================================================== -case 'average (bma)', +case 'average', + + if spm_input('Average',1,'b',{'BPA','BMA'},[1 0]) + + spm('FnBanner','spm_dcm_average'); + spm_dcm_average; % Average several models (Bayesian FFX) + + else + + spm('FnBanner','spm_dcm_bma_results'); + spm_dcm_bma_results; % Average model parameters from BMS (BMA) + + end - spm('FnBanner','spm_dcm_average'); - spm_dcm_bma_results; - %========================================================================== % Quit DCM GUI %========================================================================== diff --git a/spm_defaults.m b/spm_defaults.m index fd6bddf..cb7b979 100644 --- a/spm_defaults.m +++ b/spm_defaults.m @@ -1,7 +1,5 @@ function spm_defaults % Sets the defaults which are used by SPM -% -% FORMAT spm_defaults %_______________________________________________________________________ % % This file is intended to be customised for the site. @@ -9,85 +7,77 @@ % matlab subdirectories. If ~/matlab is ahead of the SPM directory % in the MATLABPATH, then the users own personal defaults are used. % -% Care must be taken when modifying this file +% This function should not be called directly in any script or function +% (apart from SPM internals). +% To load the defaults, use spm('Defaults',modality). +% To get/set the defaults, use spm_get_defaults. +% +% Care must be taken when modifying this file. %_______________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% John Ashburner, Andrew Holmes -% $Id: spm_defaults.m 3299 2009-07-30 18:21:53Z guillaume $ - +% +% $Id: spm_defaults.m 3953 2010-06-28 16:58:48Z guillaume $ + +%-Prevent users from making direct calls to this function +%----------------------------------------------------------------------- +persistent runonce +try + if ~isdeployed && isempty(runonce) + d = dbstack; + if isempty(intersect({'spm','spm_get_defaults'},{d.name})) + fprintf(['Direct calls to spm_defauts are deprecated.\n' ... + 'Please use spm(''Defaults'',modality) ' ... + 'or spm_get_defaults instead.\n']); + runonce = 1; + end + end +end global defaults -% Misc +% Command Line Usage default %======================================================================= -defaults.grid = 0.4; defaults.cmdline = 0; -defaults.renderer = 'zbuffer'; + +% User Interface defaults +%======================================================================= +defaults.ui.print = struct('opt',{{'-dpsc2','-append'}},'append',true,'ext','.ps'); +defaults.ui.colour = [0.73 0.78 0.96]; +defaults.renderer = 'zbuffer'; +defaults.ui.fs = 14; % unused % File format specific %======================================================================= % Note that defaults.analyze.flip is no longer used. Specifying the % left/right handedness of the voxel indices is now done entirely by % spm_flip_analyze_images.m +defaults.images.format = 'img'; % used for DICOM, ECAT and MINC import - -% Stats defaults -%======================================================================= -defaults.stats.maxmem = 2^26; -defaults.stats.maxres = 64; -defaults.stats.fmri.ufp = 0.001; -defaults.stats.pet.ufp = 0.05; -defaults.stats.eeg.ufp = 1; -defaults.stats.topoFDR = 1; - -% fMRI design defaults -%======================================================================= -defaults.stats.fmri.fmri_t = 16; -defaults.stats.fmri.fmri_t0 = 1; -defaults.stats.fmri.cond.tmod = 0; -defaults.stats.fmri.hpf = 128; -defaults.stats.fmri.hrf.derivs = [0 0]; -defaults.stats.fmri.volt = 1; -defaults.stats.fmri.global = 'None'; -defaults.stats.fmri.cvi = 'AR(1)'; - -% Factorial design defaults -%======================================================================= -defaults.stats.fact.dept = 0; -defaults.stats.fact.variance = 1; -defaults.stats.fact.t2.gmsca = 0; -defaults.stats.fact.ancova = 0; -defaults.stats.fact.mcov.iCC = 1; -defaults.stats.fact.iCFI = 1; -defaults.stats.fact.iCC = 1; -defaults.stats.fact.athresh = 100; -defaults.stats.fact.rthresh = .8; -defaults.stats.fact.imask = 1; -defaults.stats.fact.gmsca = 50; -defaults.stats.fact.glonorm = 1; -defaults.stats.fact.mreg_int = 1; - -% Model estimation defaults +% DICOM Import defaults %======================================================================= -defaults.stats.est.signal = 'UGL'; -defaults.stats.est.ARP = 3; +defaults.dicom.root = 'flat'; % Folder hierarchy -% Contrast manager batch defaults +% Stats defaults %======================================================================= -defaults.stats.con.delete = 0; +defaults.stats.maxmem = 2^26; +defaults.stats.maxres = 64; +defaults.stats.fmri.ufp = 0.001; % Upper tail F-probability +defaults.stats.pet.ufp = 0.05; +defaults.stats.eeg.ufp = 1; +defaults.stats.topoFDR = 1; +defaults.stats.rft.nonstat = 0; -% Results report batch defaults +% Mask defaults %======================================================================= -defaults.stats.results.threshtype = 'FWE'; % Threshold type -defaults.stats.results.thresh = 0.05; % Threshold value -defaults.stats.results.extent = 0; % Spatial extent -defaults.stats.results.maskthresh = 0.05; % (Uncorrected) Threshold for masking -defaults.stats.results.print = true; % Print report to file +defaults.mask.thresh = 0.8; -% Mask defaults +% fMRI design defaults %======================================================================= -defaults.mask.thresh = 0.8; +defaults.stats.fmri.fmri_t = 16; +defaults.stats.fmri.fmri_t0 = 1; +defaults.stats.fmri.hpf = 128; +defaults.stats.fmri.cvi = 'AR(1)'; % Filename prefix defaults %======================================================================= @@ -101,30 +91,30 @@ % Realignment defaults %======================================================================= defaults.realign.estimate.quality = 0.9; -defaults.realign.estimate.weight = {''}; -defaults.realign.estimate.interp = 2; -defaults.realign.estimate.wrap = [0 0 0]; -defaults.realign.estimate.sep = 4; -defaults.realign.estimate.fwhm = 5; -defaults.realign.estimate.rtm = 1; -defaults.realign.write.mask = 1; -defaults.realign.write.interp = 4; -defaults.realign.write.wrap = [0 0 0]; -defaults.realign.write.which = [2 1]; +defaults.realign.estimate.weight = {''}; +defaults.realign.estimate.interp = 2; +defaults.realign.estimate.wrap = [0 0 0]; +defaults.realign.estimate.sep = 4; +defaults.realign.estimate.fwhm = 5; +defaults.realign.estimate.rtm = 1; +defaults.realign.write.mask = 1; +defaults.realign.write.interp = 4; +defaults.realign.write.wrap = [0 0 0]; +defaults.realign.write.which = [2 1]; % Unwarp defaults %======================================================================= -defaults.unwarp.estimate.rtm = 0; -defaults.unwarp.estimate.fwhm = 4; -defaults.unwarp.estimate.basfcn = [12 12]; -defaults.unwarp.estimate.regorder= 1; -defaults.unwarp.estimate.regwgt = 1e5; -defaults.unwarp.estimate.foe = [4 5]; -defaults.unwarp.estimate.soe = 1; -defaults.unwarp.estimate.rem = 1; -defaults.unwarp.estimate.jm = 0; -defaults.unwarp.estimate.noi = 5; -defaults.unwarp.estimate.expround= 'Average'; +defaults.unwarp.estimate.rtm = 0; +defaults.unwarp.estimate.fwhm = 4; +defaults.unwarp.estimate.basfcn = [12 12]; +defaults.unwarp.estimate.regorder = 1; +defaults.unwarp.estimate.regwgt = 1e5; +defaults.unwarp.estimate.foe = [4 5]; +defaults.unwarp.estimate.soe = []; +defaults.unwarp.estimate.rem = 1; +defaults.unwarp.estimate.jm = 0; +defaults.unwarp.estimate.noi = 5; +defaults.unwarp.estimate.expround = 'Average'; % % Unwarp uses defaults.realign.write % defaults for writing. @@ -156,93 +146,25 @@ defaults.normalise.write.interp = 1; defaults.normalise.write.wrap = [0 0 0]; -% Segmentation defaults -%======================================================================= -defaults.segment.estimate.priors = char(... - fullfile(spm('Dir'),'apriori','grey.nii'),... - fullfile(spm('Dir'),'apriori','white.nii'),... - fullfile(spm('Dir'),'apriori','csf.nii')); -defaults.segment.estimate.reg = 0.01; -defaults.segment.estimate.cutoff = 30; -defaults.segment.estimate.samp = 3; -defaults.segment.estimate.bb = [[-88 88]' [-122 86]' [-60 95]']; -defaults.segment.estimate.affreg.smosrc = 8; -defaults.segment.estimate.affreg.regtype = 'mni'; -%defaults.segment.estimate.affreg.weight = fullfile(spm('Dir'),'apriori','brainmask.nii'); -defaults.segment.estimate.affreg.weight = ''; -defaults.segment.write.cleanup = 1; -defaults.segment.write.wrt_cor = 1; -defaults.segment.write.wrt_brV = 1; - -% Bias field estimation defaults (UNUSED) -%======================================================================= -defaults.bias.nbins = 256; % Number of histogram bins -defaults.bias.reg = 0.01; % Regularisation -defaults.bias.cutoff = 30; % DCT frequency cutoff (mm) - % VBM Preprocessing defaults %======================================================================= defaults.preproc.tpm = cellstr(char(... fullfile(spm('Dir'),'tpm','grey.nii'),... fullfile(spm('Dir'),'tpm','white.nii'),... - fullfile(spm('Dir'),'tpm','csf.nii'))); % Prior probability maps -defaults.preproc.ngaus = [2 2 2 4]'; % Gaussians per class -defaults.preproc.warpreg = 1; % Warping Regularisation -defaults.preproc.warpco = 25; % Warp Frequency Cutoff -defaults.preproc.biasreg = 0.0001; % Bias regularisation -defaults.preproc.biasfwhm = 60; % Bias FWHM -defaults.preproc.regtype = 'mni'; % Affine Regularisation -defaults.preproc.samp = 3; % Sampling distance -defaults.preproc.output.GM = [0 0 1]; -defaults.preproc.output.WM = [0 0 1]; -defaults.preproc.output.CSF = [0 0 0]; + fullfile(spm('Dir'),'tpm','csf.nii'))); % Prior probability maps +defaults.preproc.ngaus = [2 2 2 4]'; % Gaussians per class +defaults.preproc.warpreg = 1; % Warping Regularisation +defaults.preproc.warpco = 25; % Warp Frequency Cutoff +defaults.preproc.biasreg = 0.0001; % Bias regularisation +defaults.preproc.biasfwhm = 60; % Bias FWHM +defaults.preproc.regtype = 'mni'; % Affine Regularisation +defaults.preproc.samp = 3; % Sampling distance +defaults.preproc.output.GM = [0 0 1]; +defaults.preproc.output.WM = [0 0 1]; +defaults.preproc.output.CSF = [0 0 0]; defaults.preproc.output.biascor = 1; defaults.preproc.output.cleanup = 0; % Smooth defaults %======================================================================= defaults.smooth.fwhm = [8 8 8]; -defaults.smooth.dtype = 0; - -% ImCalc defaults -%======================================================================= -defaults.imcalc.output = 'output.img'; % Output Filename -defaults.imcalc.dmtx = 0; % Data Matrix -defaults.imcalc.mask = 0; % Masking -defaults.imcalc.interp = 1; % Interpolation -defaults.imcalc.dtype = spm_type('int16'); % Data Type - -% Deformation utility defaults -%======================================================================= -defaults.defs.vox = [NaN NaN NaN]; -defaults.defs.bb = [NaN NaN NaN - NaN NaN NaN]; -defaults.defs.K = 6; - -% DICOM Import defaults -%======================================================================= -defaults.dicom.root = 'flat'; -defaults.dicom.format = 'img'; -defaults.dicom.icedims = 0; - -% MINC Import defaults -%======================================================================= -defaults.minc.dtype = spm_type('int16'); -defaults.minc.ext = '.img'; - -% ECAT Import defaults -%======================================================================= -defaults.ecat.ext = '.img'; - -% User Interface Defaults -%======================================================================= -defaults.ui.print = struct('opt',{{'-dpsc2','-append'}},'append',true,'ext','.ps'); -defaults.ui.colour1 = [0.8 0.8 1.0]; -defaults.ui.colour2 = [0.73 0.78 0.96]; -defaults.ui.colour3 = [0.0 0.0 0.0]; -defaults.ui.fs = 14; - -% EEG specific -%======================================================================= -defaults.eeg.dtype = 'float'; - diff --git a/spm_defs.m b/spm_defs.m index 63a7c73..df0da03 100644 --- a/spm_defs.m +++ b/spm_defs.m @@ -11,7 +11,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % John Ashburner -% $Id: spm_defs.m 3392 2009-09-11 14:13:38Z guillaume $ +% $Id: spm_defs.m 3755 2010-03-05 14:14:36Z volkmar $ [Def,mat] = get_comp(job.comp); [dpath ipath] = get_paths(job); @@ -65,6 +65,8 @@ [Def,mat] = get_inv(job.(fn)); case {'id'} [Def,mat] = get_id(job.(fn)); +case {'idbbvox'} + [Def,mat] = get_idbbvox(job.(fn)); otherwise error('Unrecognised job type'); end; @@ -219,6 +221,20 @@ Def{3} = single(y1*mat(3,1) + y2*mat(3,2) + y3*mat(3,3) + mat(3,4)); %_______________________________________________________________________ +%_______________________________________________________________________ +function [Def,mat] = get_idbbvox(job) +% Get an identity transform based on bounding box and voxel size. +% This will produce a transversal image. +d = floor(diff(job.bb)./job.vox); +d(d == 0) = 1; +mat = diag([-1 1 1 1])*spm_matrix([job.bb(1,:) 0 0 0 job.vox]); +Def = cell(3,1); +[y1,y2,y3] = ndgrid(1:d(1),1:d(2),1:d(3)); +Def{1} = single(y1*mat(1,1) + y2*mat(1,2) + y3*mat(1,3) + mat(1,4)); +Def{2} = single(y1*mat(2,1) + y2*mat(2,2) + y3*mat(2,3) + mat(2,4)); +Def{3} = single(y1*mat(3,1) + y2*mat(3,2) + y3*mat(3,3) + mat(3,4)); +%_______________________________________________________________________ + %_______________________________________________________________________ function [Def,mat] = get_inv(job) % Invert a deformation field (derived from a composition of deformations) diff --git a/spm_design_factorial.m b/spm_design_factorial.m new file mode 100644 index 0000000..0c1d4a0 --- /dev/null +++ b/spm_design_factorial.m @@ -0,0 +1,48 @@ +function [I,P,H,Hnames] = spm_design_factorial(fd) +% Extract factorial matrix, file list and H partition of design matrix +% FORMAT [I,P,H,Hnames] = spm_design_factorial(fd) +% +% fd - structure defined in spm_cfg_factorial_design +% with fields fact and icell +% +% I - Nscan x 4 factor matrix +% P - List of scans +% H - Component of design matrix describing conditions +% Hnames - Condition names +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Will Penny, Guillaume Flandin +% $Id: spm_design_factorial.m 3860 2010-05-04 15:59:25Z guillaume $ + +% Get number of factors, levels and cells +%-------------------------------------------------------------------------- +Nfactors = numel(fd.fact); +Nlevels = [fd.fact.levels]; +Ncells = numel(fd.icell); + +% Get file list and scan x factor matrix I +%-------------------------------------------------------------------------- +I = []; +P = {}; +for i=1:Ncells + nc = numel(fd.icell(i).scans); + I = [I; [[1:nc]', repmat(fd.icell(i).levels(:)',nc,1)]]; + P = {P{:}, fd.icell(i).scans{:}}'; +end +[I, A] = sortrows(I,2:Nfactors+1); +P = P(A); +I = [I ones(size(I,1),4-size(I,2))]; + +% Create H partition of design matrix +%-------------------------------------------------------------------------- +[H,Hnames] = spm_DesMtx(I(:,2:Nfactors+1),'-',{fd.fact(:).name}); + +% Display some warnings +%-------------------------------------------------------------------------- +if Ncells ~= prod(Nlevels) + disp('Some cell(s) are missing.'); +end +if size(I,1) ~= size(unique(I,'rows'),1) + disp('Some cell(s) are defined several times.'); +end diff --git a/spm_design_flexible.m b/spm_design_flexible.m new file mode 100644 index 0000000..7fe0331 --- /dev/null +++ b/spm_design_flexible.m @@ -0,0 +1,64 @@ +function [H,Hnames] = spm_design_flexible(fblock,I) +% Create H partition of design matrix +% FORMAT [H,Hnames] = spm_design_flexible(fblock,I) +% +% fblock - Part of job structure containing within-subject design info +% I - Nscan x 4 factor matrix +% +% H - Component of design matrix describing conditions +% Hnames - Condition names +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Will Penny +% $Id: spm_design_flexible.m 3860 2010-05-04 15:59:25Z guillaume $ + +% Sort main effects and interactions +%-------------------------------------------------------------------------- +fmain = struct('fnum',{}); +inter = struct('fnums',{}); +for k=1:numel(fblock.maininters) + if isfield(fblock.maininters{k},'fmain') + fmain(end+1)=fblock.maininters{k}.fmain; + elseif isfield(fblock.maininters{k},'inter') + inter(end+1)=fblock.maininters{k}.inter; + end +end + +% Create main effects +%-------------------------------------------------------------------------- +H=[];Hnames=[]; +nmain=length(fmain); +for f=1:nmain + fcol=fmain(f).fnum; + fname=fblock.fac(fcol).name; + + % Augment H partition - explicit factor numbers are 1 lower than in I matrix + [Hf,Hfnames]=spm_DesMtx(I(:,fcol+1),'-',fname); + H=[H,Hf]; + Hnames=[Hnames;Hfnames]; +end + +% Create interactions +%-------------------------------------------------------------------------- +ni=length(inter); +for i=1:ni + % Get the two factors for this interaction + fnums=inter(i).fnums; + f1=fnums(1);f2=fnums(2); + + % Names + iname{1} = fblock.fac(f1).name; + iname{2} = fblock.fac(f2).name; + + % Augment H partition - explicit factor numbers are 1 lower than in I matrix + Isub = [I(:,f1+1),I(:,f2+1)]; + [Hf,Hfnames] = spm_DesMtx(Isub,'-',iname); + H = [H,Hf]; + Hnames = [Hnames;Hfnames]; + +end + +if nmain==0 && ni==0 + error('You have not specified any main effects or interactions'); +end diff --git a/spm_design_within_subject.m b/spm_design_within_subject.m new file mode 100644 index 0000000..d75fcce --- /dev/null +++ b/spm_design_within_subject.m @@ -0,0 +1,95 @@ +function [I,P,cov] = spm_design_within_subject(fblock,cov) +% Set up within-subject design when specified subject by subject +% FORMAT [I,P,cov] = spm_design_within_subject(fblock,cov) +% +% fblock - Part of job structure containing within-subject design info +% cov - Part of job structure containing covariate info +% +% I - Nscan x 4 factor matrix +% P - List of scans +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Will Penny +% $Id: spm_design_within_subject.m 3860 2010-05-04 15:59:25Z guillaume $ + +nsub=length(fblock.fsuball.fsubject); +% Specify design subject-by-subject +P=[];I=[]; +subj=[]; +for s=1:nsub, + P = [P; fblock.fsuball.fsubject(s).scans]; + ns = length(fblock.fsuball.fsubject(s).scans); + cc = fblock.fsuball.fsubject(s).conds; + + [ccr,ccc] = size(cc); + if ~(ccr==ns) && ~(ccc==ns) + disp(sprintf('Error for subject %d: conditions not specified for each scan',s)); + return + elseif ~(ccr==ccc) && (ccc==ns) + %warning('spm:transposingConditions',['Condition matrix ',... + % 'appears to be transposed. Transposing back to fix.\n',... + % 'Alert developers if it is not actually transposed.']) + cc=cc'; + end + subj=[subj;s*ones(ns,1)]; + % get real replications within each subject cell + [unused cci ccj] = unique(cc,'rows'); + repl = zeros(ns, 1); + for k=1:max(ccj) + repl(ccj==k) = 1:sum(ccj==k); + end; + I = [I; [repl cc]]; +end + +nf=length(fblock.fac); +subject_factor=0; +for i=1:nf, + if strcmpi(fblock.fac(i).name,'repl') + % Copy `replications' column to create explicit `replications' factor + nI=I(:,1:i); + nI=[nI,I(:,1)]; + nI=[nI,I(:,i+1:end)]; + I=nI; + end + if strcmpi(fblock.fac(i).name,'subject') + % Create explicit `subject' factor + nI=I(:,1:i); + nI=[nI,subj]; + nI=[nI,I(:,i+1:end)]; + I=nI; + subject_factor=1; + end + +end + +% Re-order scans conditions and covariates into standard format +% This is to ensure compatibility with how variance components are created +if subject_factor + U=unique(I(:,2:nf+1),'rows'); + Un=length(U); + Uc=zeros(Un,1); + r=1;rj=[]; + for k=1:Un, + for j=1:size(I,1), + match=sum(I(j,2:nf+1)==U(k,:))==nf; + if match + Uc(k)=Uc(k)+1; + Ir(r,:)=[Uc(k),I(j,2:end)]; + r=r+1; + rj=[rj;j]; + end + end + end + P=P(rj); % -scans + I=Ir; % -conditions + for k=1:numel(cov) % -covariates + cov(k).c = cov(k).c(rj); + end; +end + +% Pad out factorial matrix to cover the four canonical factors +[ns,nI]=size(I); +if nI < 4 + I = [I, ones(ns,4-nI)]; +end diff --git a/spm_detrend.m b/spm_detrend.m index bc501ec..132a516 100644 --- a/spm_detrend.m +++ b/spm_detrend.m @@ -13,13 +13,13 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_detrend.m 1143 2008-02-07 19:33:33Z spm $ +% $Id: spm_detrend.m 3717 2010-02-08 16:44:42Z guillaume $ % defaults -%--------------------------------------------------------------------------- +%-------------------------------------------------------------------------- [m n] = size(x); -if ~n +if ~m || ~n y = []; return end @@ -28,17 +28,19 @@ end % centre columns -%--------------------------------------------------------------------------- +%-------------------------------------------------------------------------- if ~p - y = x - ones(m,1)*mean(x); + for i = 1:n + y(:,i) = x(:,i) - mean(x(:,i)); + end return end % polynomial adjustment -%--------------------------------------------------------------------------- -G = []; +%-------------------------------------------------------------------------- +G = zeros(m,p+1); for i = 0:p d = (1:m).^i; - G = [G d(:)]; + G(:,i+1) = d(:); end -y = x - G*(pinv(G)*x); +y = x - G*(pinv(full(G))*x); diff --git a/spm_dicom_convert.m b/spm_dicom_convert.m index 3c701ba..c2a9e31 100644 --- a/spm_dicom_convert.m +++ b/spm_dicom_convert.m @@ -31,7 +31,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % John Ashburner & Jesper Andersson -% $Id: spm_dicom_convert.m 3307 2009-08-06 11:16:09Z volkmar $ +% $Id: spm_dicom_convert.m 3934 2010-06-17 14:58:25Z guillaume $ if nargin<2, opts = 'all'; end @@ -129,8 +129,8 @@ analyze_to_dicom = [diag([1 -1 1]) [0 (dim(2)-1) 0]'; 0 0 0 1]*[eye(4,3) [-1 -1 -1 1]']; - vox = [hdr{i}.PixelSpacing hdr{i}.SpacingBetweenSlices]; - pos = hdr{i}.ImagePositionPatient'; + vox = [hdr{i}.PixelSpacing(:); hdr{i}.SpacingBetweenSlices]; + pos = hdr{i}.ImagePositionPatient(:); orient = reshape(hdr{i}.ImageOrientationPatient,[3 2]); orient(:,3) = null(orient'); if det(orient)<0, orient(:,3) = -orient(:,3); end; @@ -235,7 +235,7 @@ vol{1}{1} = hdr{1}; for i=2:length(hdr), %orient = reshape(hdr{i}.ImageOrientationPatient,[3 2]); - %xy1 = hdr{i}.ImagePositionPatient*orient; + %xy1 = hdr{i}.ImagePositionPatient(:)*orient; match = 0; if isfield(hdr{i},'CSAImageHeaderInfo') && isfield(hdr{i}.CSAImageHeaderInfo,'name') ice1 = sscanf( ... @@ -247,7 +247,7 @@ end; for j=1:length(vol), %orient = reshape(vol{j}{1}.ImageOrientationPatient,[3 2]); - %xy2 = vol{j}{1}.ImagePositionPatient*orient; + %xy2 = vol{j}{1}.ImagePositionPatient(:)*orient; % This line is a fudge because of some problematic data that Bogdan, % Cynthia and Stefan were trying to convert. I hope it won't cause @@ -326,7 +326,7 @@ z = zeros(length(vol{j}),1); for i=1:length(vol{j}), - z(i) = vol{j}{i}.ImagePositionPatient*proj; + z(i) = vol{j}{i}.ImagePositionPatient(:)'*proj; end; [z,index] = sort(z); vol{j} = vol{j}(index); @@ -347,7 +347,7 @@ if det([orient proj])<0, proj = -proj; end; z = zeros(length(vol{j}),1); for i=1:length(vol{j}), - z(i) = vol{j}{i}.ImagePositionPatient*proj; + z(i) = vol{j}{i}.ImagePositionPatient(:)'*proj; end; dist = diff(sort(z)); if sum((dist-mean(dist)).^2)/length(dist)>1e-4, @@ -404,7 +404,7 @@ if det([orient proj])<0, proj = -proj; end; for i=1:length(volj), - z(i) = volj{i}.ImagePositionPatient*proj; + z(i) = volj{i}.ImagePositionPatient(:)'*proj; t(i) = volj{i}.InstanceNumber; end; % msg = 0; @@ -508,11 +508,11 @@ R = [reshape(hdr{1}.ImageOrientationPatient,3,2)*diag(hdr{1}.PixelSpacing); 0 0]; x1 = [1;1;1;1]; -y1 = [hdr{1}.ImagePositionPatient'; 1]; +y1 = [hdr{1}.ImagePositionPatient(:); 1]; if length(hdr)>1, x2 = [1;1;dim(3); 1]; - y2 = [hdr{end}.ImagePositionPatient'; 1]; + y2 = [hdr{end}.ImagePositionPatient(:); 1]; else orient = reshape(hdr{1}.ImageOrientationPatient,[3 2]); orient(:,3) = null(orient'); @@ -1062,7 +1062,7 @@ % works on full pathnames only opwd=pwd; if str(end) ~= filesep, str = [str filesep];end; -pos = findstr(str,filesep); +pos = strfind(str,filesep); suc = zeros(1,length(pos)); for g=2:length(pos) if ~exist(str(1:pos(g)-1),'dir'), @@ -1097,8 +1097,8 @@ X=get_numaris4_val(hdr.CSASeriesHeaderInfo,'MrProtocol'); end -ascstart = findstr(X,'### ASCCONV BEGIN ###'); -ascend = findstr(X,'### ASCCONV END ###'); +ascstart = strfind(X,'### ASCCONV BEGIN ###'); +ascend = strfind(X,'### ASCCONV END ###'); if ~isempty(ascstart) && ~isempty(ascend) tokens = textscan(char(X((ascstart+22):(ascend-1))),'%s', ... diff --git a/spm_dicom_dict.mat b/spm_dicom_dict.mat index 0cc7edb..669378d 100644 Binary files a/spm_dicom_dict.mat and b/spm_dicom_dict.mat differ diff --git a/spm_dicom_dict.txt b/spm_dicom_dict.txt index 8147cde..cc36fdb 100644 --- a/spm_dicom_dict.txt +++ b/spm_dicom_dict.txt @@ -1590,3 +1590,4 @@ FFFE E0DD SequenceDelimitationItem UN 1 0029 1134 PMTFInformation4 CS 1 0031 1009 NumberRawDataChannels UL 1 7fe1 1010 CSAData OB 1 +0029 1140 SiemensMedcomHeader SQ 1 diff --git a/spm_dicom_headers.m b/spm_dicom_headers.m index d03b55a..a2e06de 100644 --- a/spm_dicom_headers.m +++ b/spm_dicom_headers.m @@ -15,7 +15,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % John Ashburner -% $Id: spm_dicom_headers.m 3224 2009-06-25 17:28:21Z volkmar $ +% $Id: spm_dicom_headers.m 3992 2010-07-13 11:57:17Z volkmar $ if nargin<2, essentials = false; end @@ -102,7 +102,7 @@ ret.StartOfCSAData = ftell(fp); ret.SizeOfCSAData = tag.length; fseek(fp,tag.length,'cof'); - case {'CSAImageHeaderInfo', 'CSASeriesHeaderInfo','Private_0029_1110','Private_0029_1210','Private_0029_1220'}, + case {'CSAImageHeaderInfo', 'CSASeriesHeaderInfo','Private_0029_1110','Private_0029_1120','Private_0029_1210','Private_0029_1220'}, dat = decode_csa(fp,tag.length); ret.(tag.name) = dat; case {'TransferSyntaxUID'}, @@ -143,22 +143,32 @@ dat = deblank(dat); case {'DS'}, try - dat = strread(dat,'%f','delimiter','\\')'; + dat = textscan(dat,'%f','delimiter','\\')'; + dat = dat{1}; catch - dat = strread(dat,'%f','delimiter','/')'; + dat = textscan(dat,'%f','delimiter','/')'; + dat = dat{1}; end case {'IS'}, - dat = strread(dat,'%d','delimiter','\\')'; + dat = textscan(dat,'%d','delimiter','\\')'; + dat = double(dat{1}); case {'DA'}, dat = strrep(dat,'.',' '); - [y,m,d] = strread(dat,'%4d%2d%2d'); - dat = datenum(y,m,d); + dat = textscan(dat,'%4d%2d%2d'); + [y,m,d] = deal(dat{:}); + dat = datenum(double(y),double(m),double(d)); case {'TM'}, if any(dat==':'), - [h,m,s] = strread(dat,'%d:%d:%f'); + dat = textscan(dat,'%d:%d:%f'); + [h,m,s] = deal(dat{:}); + h = double(h); + m = double(m); else - [h,m,s] = strread(dat,'%2d%2d%f'); - end; + dat = textscan(dat,'%2d%2d%f'); + [h,m,s] = deal(dat{:}); + h = double(h); + m = double(m); + end if isempty(h), h = 0; end; if isempty(m), m = 0; end; if isempty(s), s = 0; end; @@ -356,28 +366,20 @@ case char([0 0]) dict = load(P); catch fprintf('\nUnable to load the file "%s".\n', P); - if strcmp(computer,'PCWIN') || strcmp(computer,'PCWIN64'), - fprintf('This may be because of the way that the .tar.gz files\n'); - fprintf('were unpacked when the SPM software was installed.\n'); - fprintf('If installing on a Windows platform, then the software\n'); - fprintf('used for unpacking may try to be clever and insert\n'); - fprintf('additional unwanted control characters. If you use\n'); - fprintf('WinZip, then you should ensure that TAR file smart\n'); - fprintf('CR/LF conversion is disabled (under the Miscellaneous\n'); - fprintf('Configuration Options).\n\n'); - end; - rethrow(lasterr); + rethrow(lasterror); end; return; %_______________________________________________________________________ %_______________________________________________________________________ function dict = readdict_txt -file = textread('spm_dicom_dict.txt','%s','delimiter','\n','whitespace',''); +fid = fopen('spm_dicom_dict.txt','rt'); +file = textscan(fid,'%s','delimiter','\n','whitespace',''); file = file{1}; +fclose(fid); clear values i = 0; for i0=1:length(file), - words = strread(file{i0},'%s','delimiter','\t'); + words = textscan(file{i0},'%s','delimiter','\t'); words = words{1}; if length(words)>=5 && ~strcmp(words{1}(3:4),'xx'), grp = sscanf(words{1},'%x'); ele = sscanf(words{2},'%x'); @@ -536,7 +538,7 @@ case char([0 0]) %_______________________________________________________________________ function str_out = uscore_subst(str_in) str_out = str_in; -pos = findstr(str_in,'+AF8-'); +pos = strfind(str_in,'+AF8-'); if ~isempty(pos), str_out(pos) = '_'; str_out(repmat(pos,4,1)+repmat((1:4)',1,numel(pos))) = []; diff --git a/spm_diff.m b/spm_diff.m index b3f194a..a47c53e 100644 --- a/spm_diff.m +++ b/spm_diff.m @@ -1,25 +1,30 @@ function [varargout] = spm_diff(varargin) % matrix high-order numerical differentiation -% FORMAT [dfdx] = spm_diff(f,x,...,n,[V]) +% FORMAT [dfdx] = spm_diff(f,x,...,n) +% FORMAT [dfdx] = spm_diff(f,x,...,n,V) +% FORMAT [dfdx] = spm_diff(f,x,...,n,'q') % % f - [inline] function f(x{1},...) % x - input argument[s] % n - arguments to differentiate w.r.t. % -% dfdx - df/dx{i} ; n = i -% dfdx{p}...{q} - df/dx{i}dx{j}(q)...dx{k}(p) ; n = [i j ... k] -% % V - cell array of matrices that allow for differentiation w.r.t. % to a linear transformation of the parameters: i.e., returns % % df/dy{i}; x = V{i}y{i}; V = dx(i)/dy(i) % +% q - flag to preclude default concatenation of dfdx +% +% dfdx - df/dx{i} ; n = i +% dfdx{p}...{q} - df/dx{i}dx{j}(q)...dx{k}(p) ; n = [i j ... k] +% +% % - a cunning recursive routine %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_diff.m 2905 2009-03-20 13:00:15Z karl $ +% $Id: spm_diff.m 3696 2010-01-22 14:22:31Z karl $ % create inline object %-------------------------------------------------------------------------- @@ -31,10 +36,17 @@ x = varargin(2:(end - 2)); n = varargin{end - 1}; V = varargin{end}; + q = 1; elseif isnumeric(varargin{end}) x = varargin(2:(end - 1)); n = varargin{end}; V = cell(1,length(x)); + q = 1; +elseif ischar(varargin{end}) + x = varargin(2:(end - 2)); + n = varargin{end - 1}; + V = cell(1,length(x)); + q = 0; else error('improper call') end @@ -74,7 +86,7 @@ J{i} = spm_dfdx(fi,f0,dx); end - % return numeric array for first order derivatives + % return numeric array for first-order derivatives %====================================================================== % vectorise f @@ -94,7 +106,7 @@ % or differentiation of a vector %---------------------------------------------------------------------- - if isvec(f0) + if isvec(f0) && q % concatenate into a matrix %------------------------------------------------------------------ diff --git a/spm_ecat2nifti.m b/spm_ecat2nifti.m index 9585bca..f1280d9 100644 --- a/spm_ecat2nifti.m +++ b/spm_ecat2nifti.m @@ -6,12 +6,14 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % John Ashburner & Roger Gunn -% $Id: spm_ecat2nifti.m 1143 2008-02-07 19:33:33Z spm $ +% $Id: spm_ecat2nifti.m 3691 2010-01-20 17:08:30Z guillaume $ -if nargin==1, +if nargin==1 opts = struct('ext','.nii'); -end; +else + if opts.ext(1) ~= '.', opts.ext = ['.' opts.ext]; end +end fp = fopen(fname,'r','ieee-be'); if fp == -1, diff --git a/spm_eeg_artefact.m b/spm_eeg_artefact.m index 845d90c..9119087 100644 --- a/spm_eeg_artefact.m +++ b/spm_eeg_artefact.m @@ -31,9 +31,9 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Vladimir Litvak -% $Id: spm_eeg_artefact.m 3384 2009-09-10 18:36:56Z vladimir $ +% $Id: spm_eeg_artefact.m 3798 2010-03-24 12:00:07Z vladimir $ -SVNrev = '$Rev: 3384 $'; +SVNrev = '$Rev: 3798 $'; %-Startup %-------------------------------------------------------------------------- @@ -86,24 +86,7 @@ bad = zeros(D.nchannels, D.ntrials); for i = 1:numel(S.methods) - if iscell(S.methods(i).channels) - chanind = indchannel(D, S.methods(i).channels); - else - switch upper(S.methods(i).channels) - case 'ALL' - chanind = 1:D.nchannels; - case 'EOG' - chanind = eogchannels(D); - case 'ECG' - chanind = ecgchannels(D); - case 'EMG' - chanind = emgchannels(D); - otherwise - chanind = meegchannels(D, S.methods(i).channels); - end - end - - chanind = setdiff(chanind, D.badchannels); + chanind = setdiff(D.selectchannels(S.methods(i).channels), D.badchannels); if ~isempty(chanind) S1 = S.methods(i).settings; diff --git a/spm_eeg_channelselection.m b/spm_eeg_channelselection.m index dd1b441..1fbb7f7 100644 --- a/spm_eeg_channelselection.m +++ b/spm_eeg_channelselection.m @@ -15,9 +15,9 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Vladimir Litvak -% $Id: spm_eeg_channelselection.m 2866 2009-03-11 21:56:29Z guillaume $ +% $Id: spm_eeg_channelselection.m 3833 2010-04-22 14:49:48Z vladimir $ -SVNrev = '$Rev: 2866 $'; +SVNrev = '$Rev: 3833 $'; %-Startup %-------------------------------------------------------------------------- @@ -45,7 +45,7 @@ S.inputformat = []; end -hdr = fileio_read_header(S.dataset, 'fallback', 'biosig', 'headerformat', S.inputformat); +hdr = ft_read_header(S.dataset, 'fallback', 'biosig', 'headerformat', S.inputformat); if strcmp(S.channels, 'file') if ~isfield(S, 'chanfile') diff --git a/spm_eeg_compatibility.m b/spm_eeg_compatibility.m new file mode 100644 index 0000000..7360b18 --- /dev/null +++ b/spm_eeg_compatibility.m @@ -0,0 +1,62 @@ +function Sout = spm_eeg_compatibility(S, caller) +% Keep compatibility for scripts by translating from old to new configuration +% FORMAT Sout = spm_eeg_compatibility(S, caller) +% +% Input: +% S - configuration struct +% caller - calling function +% +% Output: +% Sout - updated configuration struct +%__________________________________________________________________________ +% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging + +% Vladimir Litvak +% $Id: spm_eeg_compatibility.m 3833 2010-04-22 14:49:48Z vladimir $ + +switch caller + case 'spm_eeg_tf' + if isfield(S, 'tf') + warning('The provided configuration of spm_eeg_tf is obsolete. Trying to update.'); + + D = spm_eeg_load(S.D); + + Sout = []; + + Sout.D = S.D; + + Sout.frequencies = S.tf.frequencies; + Sout.channels = D.chanlabels(S.tf.channels); + + if isfield(S.tf, 'pow') + warning('''pow'' option is deprecated'); + end + + if isfield(S.tf, 'collchans') + warning('''collchans'' option is deprecated'); + end + + Sout.timewin = [-Inf Inf]; + Sout.phase = S.tf.phase; + Sout.method = 'morlet'; + + Sout.settings.subsample = 1; + Sout.settings.ncycles = S.tf.Mfactor; + else + Sout = S; + end + case 'spm_eeg_filter' + Sout = S; + if isfield(S, 'filter') && isfield(S.filter, 'para') + if ~isempty(S.filter.para) + warning('The ''filter.para'' for spm_eeg_filter field is deprecated.'); + end + Sout.filter = rmfield(S.filter, 'para'); + end + otherwise + Sout = S; +end + + + + diff --git a/spm_eeg_convert.m b/spm_eeg_convert.m index 150b1b9..c10f434 100644 --- a/spm_eeg_convert.m +++ b/spm_eeg_convert.m @@ -10,7 +10,7 @@ % already epoched or a trial definition file). % S.timewindow - [start end] in sec. Boundaries for a sub-segment of % continuous data [default: all] -% S.outfile - name base for the output files [default - same as input] +% S.outfile - output file name (default 'spm8_' + input) % S.channels - 'all' - convert all channels % or cell array of labels % S.usetrials - 1 - take the trials as defined in the data [default] @@ -39,7 +39,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Vladimir Litvak -% $Id: spm_eeg_convert.m 3432 2009-09-29 23:37:45Z vladimir $ +% $Id: spm_eeg_convert.m 3986 2010-07-12 16:04:56Z vladimir $ if ischar(S) temp = S; @@ -69,7 +69,7 @@ %--------- Read and check header -hdr = fileio_read_header(S.dataset, 'fallback', 'biosig', 'headerformat', S.inputformat); +hdr = ft_read_header(S.dataset, 'fallback', 'biosig', 'headerformat', S.inputformat); if isfield(hdr, 'label') [unique_label junk ind]=unique(hdr.label); @@ -91,13 +91,13 @@ %--------- Read and prepare events try - event = fileio_read_event(S.dataset, 'detectflank', 'both', 'eventformat', S.inputformat); + event = ft_read_event(S.dataset, 'detectflank', 'both', 'eventformat', S.inputformat); if ~isempty(strmatch('UPPT001', hdr.label)) % This is s somewhat ugly fix to the specific problem with event % coding in FIL CTF. It can also be useful for other CTF systems where the % pulses in the event channel go downwards. - fil_ctf_events = fileio_read_event(S.dataset, 'detectflank', 'down', 'type', 'UPPT001', 'trigshift', -1, 'eventformat', S.inputformat); + fil_ctf_events = ft_read_event(S.dataset, 'detectflank', 'down', 'type', 'UPPT001', 'trigshift', -1, 'eventformat', S.inputformat); if ~isempty(fil_ctf_events) [fil_ctf_events(:).type] = deal('FIL_UPPT001_down'); event = cat(1, event(:), fil_ctf_events(:)); @@ -109,7 +109,7 @@ % This is s somewhat ugly fix to the specific problem with event % coding in FIL CTF. It can also be useful for other CTF systems where the % pulses in the event channel go downwards. - fil_ctf_events = fileio_read_event(S.dataset, 'detectflank', 'down', 'type', 'UPPT002', 'trigshift', -1, 'eventformat', S.inputformat); + fil_ctf_events = ft_read_event(S.dataset, 'detectflank', 'down', 'type', 'UPPT002', 'trigshift', -1, 'eventformat', S.inputformat); if ~isempty(fil_ctf_events) [fil_ctf_events(:).type] = deal('FIL_UPPT002_down'); event = cat(1, event(:), fil_ctf_events(:)); @@ -191,11 +191,6 @@ event = rmfield(event, {'offset', 'sample'}); event = select_events(event, ... [S.timewindow(1)-S.eventpadding S.timewindow(2)+S.eventpadding]); - if hdr.nSamplesPre>0 - for i = 1:numel(event) - event(i).time = event(i).time - (hdr.nSamplesPre+1)./hdr.Fs; - end - end end D.trials.label = S.conditionlabel{1}; @@ -218,7 +213,7 @@ readbytrials = 0; - D.timeOnset = (-hdr.nSamplesPre+trl(1,1)-1)./hdr.Fs; + D.timeOnset = (trl(1,1)-1)./hdr.Fs; D.Nsamples = nsampl; else % Read by trials if ~S.usetrials @@ -339,13 +334,24 @@ end %--------- Prepare for reading the data -D.data.fnamedat = [S.outfile '.dat']; + +[outpath, outfile] = fileparts(S.outfile); +if isempty(outpath) + outpath = pwd; +end +if isempty(outfile) + outfile = 'spm8'; +end + +D.path = outpath; +D.fname = [outfile '.mat']; +D.data.fnamedat = [outfile '.dat']; D.data.datatype = S.datatype; if S.continuous - datafile = file_array(D.data.fnamedat, [nchan nsampl], S.datatype); + datafile = file_array(fullfile(D.path, D.data.fnamedat), [nchan nsampl], S.datatype); else - datafile = file_array(D.data.fnamedat, [nchan nsampl ntrial], S.datatype); + datafile = file_array(fullfile(D.path, D.data.fnamedat), [nchan nsampl ntrial], S.datatype); end % physically initialise file @@ -360,14 +366,14 @@ offset = 1; for i = 1:ntrial if readbytrials - dat = fileio_read_data(S.dataset,'header', hdr, 'begtrial', i, 'endtrial', i,... + dat = ft_read_data(S.dataset,'header', hdr, 'begtrial', i, 'endtrial', i,... 'chanindx', chansel, 'checkboundary', S.checkboundary, 'fallback', 'biosig', 'dataformat', S.inputformat); else - dat = fileio_read_data(S.dataset,'header', hdr, 'begsample', trl(i, 1), 'endsample', trl(i, 2),... + dat = ft_read_data(S.dataset,'header', hdr, 'begsample', trl(i, 1), 'endsample', trl(i, 2),... 'chanindx', chansel, 'checkboundary', S.checkboundary, 'fallback', 'biosig', 'dataformat', S.inputformat); end - % Sometimes fileio_read_data returns sparse output + % Sometimes ft_read_data returns sparse output dat = full(dat); if S.continuous @@ -394,13 +400,13 @@ % Specify sensor positions and fiducials if isfield(hdr, 'grad') - D.sensors.meg = forwinv_convert_units(hdr.grad, 'mm'); + D.sensors.meg = ft_convert_units(hdr.grad, 'mm'); end if isfield(hdr, 'elec') - D.sensors.eeg = forwinv_convert_units(hdr.elec, 'mm'); + D.sensors.eeg = ft_convert_units(hdr.elec, 'mm'); else try - D.sensors.eeg = forwinv_convert_units(fileio_read_sens(S.dataset, 'fileformat', S.inputformat), 'mm'); + D.sensors.eeg = ft_convert_units(ft_read_sens(S.dataset, 'fileformat', S.inputformat), 'mm'); % It might be that read_sens will return the grad for MEG datasets if isfield(D.sensors.eeg, 'ori') D.sensors.eeg = []; @@ -411,14 +417,12 @@ end try - D.fiducials = forwinv_convert_units(fileio_read_headshape(S.dataset, 'fileformat', S.inputformat), 'mm'); + D.fiducials = ft_convert_units(ft_read_headshape(S.dataset, 'fileformat', S.inputformat), 'mm'); catch warning('Could not obtain fiducials automatically.'); end %--------- Create meeg object -D.fname = [S.outfile '.mat']; - D = meeg(D); % history @@ -432,7 +436,7 @@ % Uses fileio function to get the information about channel types stored in % the original header. This is now mainly useful for Neuromag support but might % have other functions in the future. - origchantypes = fileio_chantype(hdr); + origchantypes = ft_chantype(hdr); [sel1, sel2] = spm_match_str(D.chanlabels, hdr.label); origchantypes = origchantypes(sel2); if length(strmatch('unknown', origchantypes, 'exact')) ~= numel(origchantypes) diff --git a/spm_eeg_convert2images.m b/spm_eeg_convert2images.m index ea3d555..d8745a7 100644 --- a/spm_eeg_convert2images.m +++ b/spm_eeg_convert2images.m @@ -37,9 +37,9 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % James Kilner, Stefan Kiebel -% $Id: spm_eeg_convert2images.m 3612 2009-12-03 23:45:55Z vladimir $ +% $Id: spm_eeg_convert2images.m 3724 2010-02-16 12:16:57Z vladimir $ -SVNrev = '$Rev: 3612 $'; +SVNrev = '$Rev: 3724 $'; %-Startup %-------------------------------------------------------------------------- @@ -68,9 +68,7 @@ %-If it's clear what to average over, assign automatically %---------------------------------------------------------------------- - if D.nchannels == 1 - S.images.fmt = 'channels'; - elseif D.nfrequencies == 1 + if D.nfrequencies == 1 S.images.fmt = 'frequency'; end @@ -190,7 +188,7 @@ scale = 1; end - N.dat(:, :) = scale*squeeze(mean(D(images.channels_of_interest, :, :, l), 1)); + N.dat(:, :) = scale*spm_squeeze(mean(D(images.channels_of_interest, :, :, l), 1), 1); end Pout{i} = char(Pout{i}); @@ -243,11 +241,11 @@ if ~isempty(megchanind) Dnew(megchanind, 1:Dnew.nsamples, 1:Dnew.ntrials) = ... - 1e30*squeeze(mean(D(megchanind, inds, tind(1):tind(end), :), 2)); + 1e30*spm_squeeze(mean(D(megchanind, inds, tind(1):tind(end), :), 2), 2); end if ~isempty(nonmegchanind) Dnew(nonmegchanind, 1:Dnew.nsamples, 1:Dnew.ntrials) = ... - squeeze(mean(D(nonmegchanind, inds, tind(1):tind(end), :), 2)); + spm_squeeze(mean(D(nonmegchanind, inds, tind(1):tind(end), :), 2), 2); end Dnew = timeonset(Dnew, tims(tind(1))); @@ -255,11 +253,11 @@ Dnew = clone(D, fnamedat, [D.nchannels D.nsamples D.ntrials]); if ~isempty(megchanind) Dnew(megchanind, 1:Dnew.nsamples, 1:Dnew.ntrials) = ... - 1e30*squeeze(mean(D(megchanind, inds, :, :), 2)); + 1e30*spm_squeeze(mean(D(megchanind, inds, :, :), 2), 2); end if ~isempty(nonmegchanind) Dnew(nonmegchanind, 1:Dnew.nsamples, 1:Dnew.ntrials) = ... - squeeze(mean(D(nonmegchanind, inds, :, :), 2)); + spm_squeeze(mean(D(nonmegchanind, inds, :, :), 2), 2); end end diff --git a/spm_eeg_definetrial.m b/spm_eeg_definetrial.m index 7dc51fb..be31a6e 100644 --- a/spm_eeg_definetrial.m +++ b/spm_eeg_definetrial.m @@ -24,10 +24,10 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Vladimir Litvak, Robert Oostenveld -% $Id: spm_eeg_definetrial.m 3647 2009-12-16 18:55:59Z rik $ +% $Id: spm_eeg_definetrial.m 3833 2010-04-22 14:49:48Z vladimir $ -SVNrev = '$Rev: 3647 $'; +SVNrev = '$Rev: 3833 $'; %-Startup %-------------------------------------------------------------------------- @@ -47,16 +47,16 @@ S.dataset = spm_select(1, '\.*', 'Select M/EEG data file'); end - hdr = fileio_read_header(S.dataset, 'fallback', 'biosig', 'headerformat', S.inputformat); + hdr = ft_read_header(S.dataset, 'fallback', 'biosig', 'headerformat', S.inputformat); S.fsample = hdr.Fs; - event = fileio_read_event(S.dataset, 'detectflank', 'both', 'eventformat', S.inputformat); + event = ft_read_event(S.dataset, 'detectflank', 'both', 'eventformat', S.inputformat); if ~isempty(strmatch('UPPT001', hdr.label)) % This is s somewhat ugly fix to the specific problem with event % coding in FIL CTF. It can also be useful for other CTF systems where the % pulses in the event channel go downwards. - fil_ctf_events = fileio_read_event(S.dataset, 'detectflank', 'down', 'type', 'UPPT001', 'trigshift', -1, 'eventformat', S.inputformat); + fil_ctf_events = ft_read_event(S.dataset, 'detectflank', 'down', 'type', 'UPPT001', 'trigshift', -1, 'eventformat', S.inputformat); if ~isempty(fil_ctf_events) [fil_ctf_events(:).type] = deal('FIL_UPPT001_down'); event = cat(1, event(:), fil_ctf_events(:)); @@ -68,7 +68,7 @@ % This is s somewhat ugly fix to the specific problem with event % coding in FIL CTF. It can also be useful for other CTF systems where the % pulses in the event channel go downwards. - fil_ctf_events = fileio_read_event(S.dataset, 'detectflank', 'down', 'type', 'UPPT002', 'trigshift', -1, 'eventformat', S.inputformat); + fil_ctf_events = ft_read_event(S.dataset, 'detectflank', 'down', 'type', 'UPPT002', 'trigshift', -1, 'eventformat', S.inputformat); if ~isempty(fil_ctf_events) [fil_ctf_events(:).type] = deal('FIL_UPPT002_down'); event = cat(1, event(:), fil_ctf_events(:)); diff --git a/spm_eeg_downsample.m b/spm_eeg_downsample.m index ccccbb7..06a55a8 100644 --- a/spm_eeg_downsample.m +++ b/spm_eeg_downsample.m @@ -10,26 +10,28 @@ % D - MEEG object (also written on disk) %__________________________________________________________________________ % -% This function requires the Signal Processing toolbox from The MathWorks: +% This function uses the Signal Processing toolbox from The MathWorks: % http://www.mathworks.com/products/signal/ -% (function resample.m) +% (function resample.m) if present and an homebrew version otherwise %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Stefan Kiebel -% $Id: spm_eeg_downsample.m 3401 2009-09-14 18:33:23Z guillaume $ +% $Id: spm_eeg_downsample.m 3958 2010-06-30 16:24:46Z guillaume $ -SVNrev = '$Rev: 3401 $'; +SVNrev = '$Rev: 3958 $'; %-Startup %-------------------------------------------------------------------------- spm('FnBanner', mfilename, SVNrev); spm('FigName','M/EEG downsampling'); spm('Pointer','Watch'); -%-Test for the presence of required Matlab toolbox +%-Test for the presence of Signal Processing Matlab toolbox %-------------------------------------------------------------------------- -if ~license('test','signal_toolbox') - error('M/EEG dowsampling requires the Signal Processing Toolbox.'); +flag_TBX = license('checkout','signal_toolbox'); +if ~flag_TBX + disp(['warning: using homemade resampling routine ' ... + 'as signal toolbox is not available.']); end %-Get MEEG object @@ -67,23 +69,33 @@ Q = round(10*D.fsample); %-First pass: Determine new D.nsamples -%-------------------------------------------------------------------------- -d = double(squeeze(D(1, :, 1))); -d2 = resample(d', P, Q)'; -nsamples_new = size(d2, 2); +%========================================================================== +if flag_TBX % Signal Proc. Toolbox + nsamples_new = ceil(nsamples(D)*P/Q); +else + d = double(squeeze(D(1, :, 1))); + [d2,alpha] = spm_resample(d,P/Q); + fsample_new = D.fsample*alpha; + S.fsample_new = fsample_new; + disp(['Resampling frequency is ',num2str(fsample_new), 'Hz']) + nsamples_new = size(d2, 2); +end -% generate new meeg object with new filenames +%-Generate new meeg object with new filenames +%-------------------------------------------------------------------------- Dnew = clone(D, ['d' fnamedat(D)], [D.nchannels nsamples_new D.ntrials]); t0 = clock; %-Second pass: resample all -%-------------------------------------------------------------------------- +%========================================================================== if strcmp(D.type, 'continuous') + %-Continuous + %---------------------------------------------------------------------- spm_progress_bar('Init', D.nchannels, 'Channels downsampled'); % work on blocks of channels % determine block size, dependent on memory - memsz = 2/3*spm('Memory'); + memsz = spm('Memory'); datasz = nchannels(D)*nsamples(D)*8; % datapoints x 8 bytes per double value blknum = ceil(datasz/memsz); blksz = ceil(nchannels(D)/blknum); @@ -95,11 +107,16 @@ blkchan=chncnt:(min(nchannels(D), chncnt+blksz-1)); Dtemp=D(blkchan,:,1); chncnt=chncnt+blksz; + %loop through channels for j = 1:numel(blkchan) d = Dtemp(j,:); Dtemp(j,:)=0; % overwrite Dtemp to save memory - Dtemp(j,1:nsamples_new) = resample(d', P, Q)'; + if flag_TBX % Signal Proc. Toolbox + Dtemp(j,1:nsamples_new) = resample(d', P, Q)'; + else + Dtemp(j,1:nsamples_new) = spm_resample(d,P/Q); + end spm_progress_bar('Set', blkchan(j)); end @@ -110,6 +127,8 @@ end else + %-Epoched + %---------------------------------------------------------------------- spm_progress_bar('Init', D.ntrials, 'Trials downsampled'); drawnow; if D.ntrials > 100, Ibar = floor(linspace(1, D.ntrials,100)); else Ibar = [1:D.ntrials]; end @@ -117,10 +136,12 @@ for i = 1:D.ntrials for j = 1:D.nchannels d = double(squeeze(D(j, :, i))); - d2 = resample(d', P, Q)'; - + if flag_TBX % Signal Proc. Toolbox + d2 = resample(d', P, Q)'; + else + d2 = spm_resample(d,P/Q); + end Dnew(j, 1:nsamples_new, i) = d2; - end if ismember(i, Ibar), spm_progress_bar('Set', i); end end @@ -142,3 +163,36 @@ %-Cleanup %-------------------------------------------------------------------------- spm('FigName','M/EEG downsampling: done'); spm('Pointer','Arrow'); + + +%========================================================================== +function [Y,alpha] = spm_resample(X,alpha) +% [Jean:] Basic resample function (when no Signal Proc. Toolbox) +% FORMAT Y = spm_resample(X,alpha) +% IN: +% - X: a nXm matrix of n time series +% - alpha: the ration of input versus output sampling frequencies. If +% alpha>1, rs(X,alpha) performs upsampling of the time series. +% OUT: +% - Y: nX[alpha*m] matrix of resampled time series +% - alpha: true alpha used (due to rational rounding) +% This function operates on rows of a signal matrix. This means it can be +% used on a block of channels. + +N0 = size(X,2); +N = floor(N0*alpha); +alpha = N/N0; +Y = fftshift(fft(X,[],2),2); +sy = size(Y,2); +middle = floor(sy./2)+1; +if alpha>1 % upsample + N2 = floor((N-N0)./2); + if N0/2 == floor(N0/2) + Y(:,1) = []; % throw away non symmetric DFT coef + end + Y = [zeros(size(Y,1),N2),Y,zeros(size(Y,1),N2)]; +else % downsample + N2 = floor(N./2); + Y = Y(:,middle-N2:middle+N2); +end +Y = alpha*ifft(ifftshift(Y,2),[],2); diff --git a/spm_eeg_filter.m b/spm_eeg_filter.m index 0cc2cdb..7c299ff 100644 --- a/spm_eeg_filter.m +++ b/spm_eeg_filter.m @@ -6,37 +6,39 @@ % (optional) fields of S: % S.D - MEEG object or filename of M/EEG mat-file % S.filter - struct with the following fields: -% type - type of filter, currently only 'butterworth' +% type - optional filter type, can be +% 'but' Butterworth IIR filter (default) +% 'fir' FIR filter using Matlab fir1 function +% order - filter order (default - 5 for Butterworth) % band - filterband [low|high|bandpass|stop] % PHz - cutoff frequency [Hz] -% parameter - filter coefficients -% +% dir - optional filter direction, can be +% 'onepass' forward filter only +% 'onepass-reverse' reverse filter only, i.e. backward in time +% 'twopass' zero-phase forward and reverse filter +% % D - MEEG object (also written to disk) %__________________________________________________________________________ -% -% This function filters M/EEG data and requires the signal processing -% toolbox from The MathWorks: -% http://www.mathworks.com/products/signal/ -% (function butter.m) -%__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Stefan Kiebel -% $Id: spm_eeg_filter.m 3541 2009-11-06 17:34:40Z guillaume $ +% $Id: spm_eeg_filter.m 3958 2010-06-30 16:24:46Z guillaume $ -SVNrev = '$Rev: 3541 $'; +SVNrev = '$Rev: 3958 $'; %-Startup %-------------------------------------------------------------------------- spm('FnBanner', mfilename, SVNrev); spm('FigName','M/EEG filter'); spm('Pointer', 'Watch'); -%-Test for the presence of required Matlab toolbox -%-------------------------------------------------------------------------- -if ~license('test','signal_toolbox') - error('M/EEG filtering requires the Signal Processing Toolbox.'); +if nargin == 0 + S = []; end +%-Ensure backward compatibility +%-------------------------------------------------------------------------- +S = spm_eeg_compatibility(S, mfilename); + %-Get MEEG object %-------------------------------------------------------------------------- try @@ -51,45 +53,36 @@ %-Get parameters %-------------------------------------------------------------------------- -try - filter.type = S.filter.type; -catch - filter.type = spm_input('filter type', '+1', 'b', 'butterworth'); - S.filter.type = filter.type; +if ~isfield(S, 'filter') + S.filter = []; end -switch filter.type - case 'butterworth' - try - filter.order = S.filter.order; - catch - filter.order = 5; - S.filter.order = filter.order; - end - try - filter.para = S.filter.para; - catch - filter.para = []; - S.filter.para = filter.para; - end - otherwise - error('Unknown filter type.'); -end - -try - filter.band = S.filter.band; -catch - filter.band = cell2mat(... +if ~isfield(S.filter, 'band') + S.filter.band = cell2mat(... spm_input('filterband', '+1', 'm',... 'lowpass|highpass|bandpass|stopband',... {'low','high','bandpass','stop'})); - S.filter.band = filter.band; end -try - filter.PHz = S.filter.PHz; -catch - switch lower(filter.band) +if ~isfield(S.filter, 'type') + S.filter.type = 'butterworth'; +end + +if ~isfield(S.filter, 'order') + if strcmp(S.filter.type, 'butterworth') + S.filter.order = 5; + else + S.filter.order = []; + end +end + +if ~isfield(S.filter, 'dir') + S.filter.dir = 'twopass'; +end + + +if ~isfield(S.filter, 'PHz') + switch lower(S.filter.band) case {'low','high'} str = 'Cutoff [Hz]'; YPos = -1; @@ -115,19 +108,7 @@ otherwise error('unknown filter band.') end - filter.PHz = PHz; - S.filter.PHz = filter.PHz; -end - -switch filter.type - case 'butterworth' - if isempty(filter.para) - [B, A] = butter(filter.order, filter.PHz/(D.fsample/2), filter.band); - filter.para{1} = B; - filter.para{2} = A; - end - otherwise - error('Unknown filter type.'); + S.filter.PHz = PHz; end %- @@ -139,9 +120,11 @@ % determine channels for filtering Fchannels = unique([D.meegchannels, D.eogchannels]); +Fs = D.fsample; + if strcmp(D.type, 'continuous') - % continouous data + % continuous data spm_progress_bar('Init', nchannels(D), 'Channels filtered'); drawnow; if nchannels(D) > 100, Ibar = floor(linspace(1, nchannels(D),100)); else Ibar = [1:nchannels(D)]; end @@ -149,7 +132,7 @@ % work on blocks of channels % determine blocksize % determine block size, dependent on memory - memsz = 2/3*spm('Memory'); + memsz = spm('Memory'); datasz = nchannels(D)*nsamples(D)*8; % datapoints x 8 bytes per double value blknum = ceil(datasz/memsz); blksz = ceil(nchannels(D)/blknum); @@ -166,7 +149,7 @@ for j = 1:numel(blkchan) if ismember(blkchan(j), Fchannels) - Dtemp(j, :) = spm_filtfilt(filter.para{1}, filter.para{2}, Dtemp(j,:)); + Dtemp(j, :) = spm_eeg_preproc_filter(S.filter, Dtemp(j,:), Fs); end if ismember(j, Ibar), spm_progress_bar('Set', blkchan(j)); end @@ -189,10 +172,10 @@ for i = 1:D.ntrials d = squeeze(D(:, :, i)); - + for j = 1:nchannels(D) if ismember(j, Fchannels) - d(j,:) = spm_filtfilt(filter.para{1}, filter.para{2}, double(d(j,:))); + d(j,:) = spm_eeg_preproc_filter(S.filter, double(d(j,:)), Fs); end end @@ -216,3 +199,29 @@ %-Cleanup %-------------------------------------------------------------------------- spm('FigName','M/EEG filter: done'); spm('Pointer', 'Arrow'); + + +%========================================================================== +function dat = spm_eeg_preproc_filter(filter, dat, Fs) + +Fp = filter.PHz; + +if isequal(filter.type, 'fir') + type = 'fir'; +else + type = 'but'; +end + +N = filter.order; +dir = filter.dir; + +switch filter.band + case 'low' + dat = ft_preproc_lowpassfilter(dat,Fs,Fp,N,type,dir); + case 'high' + dat = ft_preproc_highpassfilter(dat,Fs,Fp,N,type,dir); + case 'bandpass' + dat = ft_preproc_bandpassfilter(dat, Fs, Fp, N, type, dir); + case 'stop' + dat = ft_preproc_bandstopfilter(dat,Fs,Fp,N,type,dir); +end diff --git a/spm_eeg_ft2spm.m b/spm_eeg_ft2spm.m index a96f9b6..5cd0c04 100644 --- a/spm_eeg_ft2spm.m +++ b/spm_eeg_ft2spm.m @@ -5,7 +5,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Vladimir Litvak -% $Id: spm_eeg_ft2spm.m 3525 2009-10-30 13:37:07Z vladimir $ +% $Id: spm_eeg_ft2spm.m 3833 2010-04-22 14:49:48Z vladimir $ isTF = 0; @@ -151,7 +151,7 @@ end if isfield(ftdata, 'hdr') && isfield(ftdata.hdr, 'grad') - D = sensors(D, 'MEG', forwinv_convert_units(ftdata.hdr.grad, 'mm')); + D = sensors(D, 'MEG', ft_convert_units(ftdata.hdr.grad, 'mm')); S = []; S.task = 'project3D'; diff --git a/spm_eeg_fuse.m b/spm_eeg_fuse.m index f8cd7b8..1a106c0 100644 --- a/spm_eeg_fuse.m +++ b/spm_eeg_fuse.m @@ -5,15 +5,15 @@ % S - input structure (optional) % (optional) fields of S: % S.D - character array containing filenames of M/EEG mat-files -% +% % D - MEEG object (also written to disk, with a 'u' prefix) %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % % Vladimir Litvak -% $Id: spm_eeg_fuse.m 3540 2009-11-06 12:10:43Z guillaume $ +% $Id: spm_eeg_fuse.m 3937 2010-06-18 14:41:43Z vladimir $ -SVNrev = '$Rev: 3540 $'; +SVNrev = '$Rev: 3937 $'; %-Startup %-------------------------------------------------------------------------- @@ -57,44 +57,44 @@ for i = 1:Nfiles if ~isequal(D{i}.transformtype, D{1}.transformtype) error(['The datasets do not contain the same kind of data.\n'... - 'There is a difference between files\n\t%s\nand\n\t%s.'], ... - D{1}.fname, D{i}.fname); + 'There is a difference between files\n\t%s\nand\n\t%s.'], ... + D{1}.fname, D{i}.fname); end - + if D{1}.ntrials ~= D{i}.ntrials error(['Data don''t have the same number of trials.\n' ... - 'There is a difference between files\n\t%s\nand\n\t%s.'], ... - D{1}.fname, D{i}.fname); + 'There is a difference between files\n\t%s\nand\n\t%s.'], ... + D{1}.fname, D{i}.fname); end if ~isequal(D{1}.conditions, D{i}.conditions) error(['Data don''t have the same condition labels.\n' ... - 'There is a difference between files\n\t%s\nand\n\t%s.'], ... - D{1}.fname, D{i}.fname); + 'There is a difference between files\n\t%s\nand\n\t%s.'], ... + D{1}.fname, D{i}.fname); end - + if D{1}.nsamples ~= D{i}.nsamples error(['Data don''t have the same number of time points.\n' ... - 'There is a difference between files\n\t%s\nand\n\t%s.'], ... - D{1}.fname, D{i}.fname); + 'There is a difference between files\n\t%s\nand\n\t%s.'], ... + D{1}.fname, D{i}.fname); end - + if D{1}.fsample ~= D{i}.fsample error(['Data don''t have the same sampling rate.\n' ... - 'There is a difference between files\n\t%s\nand\n\t%s.'], ... - D{1}.fname, D{i}.fname); + 'There is a difference between files\n\t%s\nand\n\t%s.'], ... + D{1}.fname, D{i}.fname); end - + if isTF && ~isequal(D{1}.frequencies, D{i}.frequencies) error(['Data don''t have the same frequencies.\n' ... - 'There is a difference between files\n\t%s\nand\n\t%s.'], ... - D{1}.fname, D{i}.fname); + 'There is a difference between files\n\t%s\nand\n\t%s.'], ... + D{1}.fname, D{i}.fname); end - + if ~isempty(intersect(channels, D{i}.chanlabels)) error(['Files to be fused should not have overlapping channel sets.\n' ... - 'There is an overlap in channel sets between files\n\t%s\nand\n\t%s.'], ... - D{1}.fname, D{i}.fname); + 'There is an overlap in channel sets between files\n\t%s\nand\n\t%s.'], ... + D{1}.fname, D{i}.fname); else channels = [channels, D{i}.chanlabels]; end @@ -124,34 +124,45 @@ %-Write files %-------------------------------------------------------------------------- -spm_progress_bar('Init', Nchannels, 'Channels written'); -if Nchannels > 100, Ibar = floor(linspace(1, Nchannels,100)); -else Ibar = [1:Nchannels]; end - -k = 0; -for i = 1:Nfiles - rejected = Dout.reject | D{i}.reject; - if any(rejected) - Dout = reject(Dout, [], rejected); - end - - % write channel-wise to avoid memory mapping error - for j = 1:D{i}.nchannels - k = k + 1; + +spm_progress_bar('Init', Dout.ntrials, 'Trials written'); +if Dout.ntrials > 100, Ibar = floor(linspace(1, Dout.ntrials, 100)); +else Ibar = [1:Dout.ntrials]; end + +for t = 1:Dout.ntrials + k = 1; + for i = 1:Nfiles if ~isTF - Dout(k, :, :) = D{i}(j, :, :); + Dout(k:(k+D{i}.nchannels-1), :, t) = D{i}(:, :, t); else - Dout(k, :, :, :) = D{i}(j, :, :, :); + Dout(k:(k+D{i}.nchannels-1), :, :, t) = D{i}(:, :, :, t); end - - Dout = chanlabels(Dout, k, chanlabels(D{i}, j)); - Dout = chantype(Dout, k, chantype(D{i}, j)); - Dout = badchannels(Dout, k, badchannels(D{i}, j)); - Dout = units(Dout, k, units(D{i}, j)); - Dout = coor2D(Dout, k, coor2D(D{i}, j)); - - if ismember(k, Ibar), spm_progress_bar('Set', k); end + k = k + D{i}.nchannels; + end + if ismember(t, Ibar), spm_progress_bar('Set', t); end +end + +spm_progress_bar('Clear'); + +% Update the header data separately to only do it once +k = 1; +rejected = Dout.reject; +for i = 1:Nfiles + rejected = rejected | D{i}.reject; + + Dout = chanlabels(Dout, k:(k+D{i}.nchannels-1), chanlabels(D{i})); + Dout = chantype(Dout, k:(k+D{i}.nchannels-1), chantype(D{i})); + if ~isempty(badchannels(D{i})) + Dout = badchannels(Dout, k+badchannels(D{i})-1, 1); end + Dout = units(Dout, k:(k+D{i}.nchannels-1), units(D{i})); + Dout = coor2D(Dout, k:(k+D{i}.nchannels-1), coor2D(D{i})); + + k = k + D{i}.nchannels; +end + +if any(rejected) + Dout = reject(Dout, [], rejected); end %-Set sensor locations @@ -174,7 +185,7 @@ S1.task = 'defaulteegsens'; S1.updatehistory = 0; Dout = spm_eeg_prep(S1); -end +end %-Remove previous inversions. %-------------------------------------------------------------------------- diff --git a/spm_eeg_grandmean.m b/spm_eeg_grandmean.m index 5626a0c..7d6da04 100644 --- a/spm_eeg_grandmean.m +++ b/spm_eeg_grandmean.m @@ -26,9 +26,9 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Stefan Kiebel -% $Id: spm_eeg_grandmean.m 3532 2009-11-04 16:57:51Z vladimir $ +% $Id: spm_eeg_grandmean.m 3897 2010-05-21 15:06:50Z vladimir $ -SVNrev = '$Rev: 3532 $'; +SVNrev = '$Rev: 3897 $'; %-Startup %-------------------------------------------------------------------------- @@ -312,7 +312,7 @@ %-Save Grand Mean to disk %-------------------------------------------------------------------------- -Do = type(Do, 'grandmean'); +Do = type(Do, 'evoked'); bads = find(~any(w')); if ~isempty(bads) diff --git a/spm_eeg_inv_Mesh2Voxels.m b/spm_eeg_inv_Mesh2Voxels.m index 19ef690..51b300c 100644 --- a/spm_eeg_inv_Mesh2Voxels.m +++ b/spm_eeg_inv_Mesh2Voxels.m @@ -4,12 +4,10 @@ % Input: % D - input data struct (optional) % -% D.inv{val}.contrast.smooth = smoothing in mm [8] % D.inv{val}.contrast.display = display (spm_image) flag [0] % % Output: % D - data struct including the new files and parameters and -% D.inv{val}.contrast.scalefactor; % %-------------------------------------------------------------------------- % Non-linear interpolation of a Mesh contrast into MNI Voxel space @@ -23,146 +21,175 @@ % Gaussian filter. %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging - + % Karl Friston -% $Id: spm_eeg_inv_Mesh2Voxels.m 3648 2009-12-17 15:49:52Z guillaume $ - +% $Id: spm_eeg_inv_Mesh2Voxels.m 3996 2010-07-13 22:20:40Z vladimir $ + % checks %-------------------------------------------------------------------------- [D,val] = spm_eeg_inv_check(varargin{:}); -% display flag +% Switches %-------------------------------------------------------------------------- -try - Disp = D.inv{val}.contrast.display; -catch - Disp = 0; -end +try, Disp = D.inv{val}.contrast.display; catch, Disp = 0; end +try, space = D.inv{val}.contrast.space; catch, space = 1; end +try, smooth = D.inv{val}.contrast.smoothing; catch, smooth = 8; end -% MNI [1] or native [0] output image space -%-------------------------------------------------------------------------- -try - space = D.inv{val}.contrast.space; -catch - space = 1; % MNI - %space = spm_input('Image space','+1','b',{'Native|MNI'},[0 1],1); - %D.inv{val}.contrast.space = space; -end % smoothing FWHM (mm) %-------------------------------------------------------------------------- fprintf('writing and smoothing image - please wait\n'); %-# -try - smoothparam = D.inv{val}.contrast.smooth; -catch - smoothparam = 8; - D.inv{val}.contrast.smooth = smoothparam; -end -% Get volume +% Get volume (MNI [1] or native [0] output image space) %-------------------------------------------------------------------------- if space sMRIfile = fullfile(spm('dir'),'templates','T2.nii'); else sMRIfile = D.inv{val}.mesh.sMRI; end -Vin = spm_vol(sMRIfile); +Vin = spm_vol(sMRIfile); + +% Tag (to identify particular contrast settings) +%-------------------------------------------------------------------------- +woi = D.inv{val}.contrast.woi; +foi = D.inv{val}.contrast.fboi; +Nw = size(woi,1); +for i = 1:Nw + tag{i} = ['t' sprintf('%d_', woi(i,:)) 'f' sprintf('%d_', foi)]; +end % Get mesh %-------------------------------------------------------------------------- if space - m = D.inv{val}.mesh.tess_mni; + m = D.inv{val}.mesh.tess_mni; else - m = export(gifti(D.inv{val}.mesh.tess_ctx),'spm'); + m = export(gifti(D.inv{val}.mesh.tess_ctx),'spm'); end -vert = m.vert; -face = m.face; -nd = D.inv{val}.inverse.Nd; -nv = size(vert,1); -nf = size(face,1); +vert = m.vert; +face = m.face; +nd = D.inv{val}.inverse.Nd; +nv = size(vert,1); +nf = size(face,1); % Compute a densely sampled triangular mask %-------------------------------------------------------------------------- -[tx, ty] = meshgrid(0.05:0.1:0.95, 0.05:0.1:0.95); -tx = tx(:); -ty = ty(:); -ti = find(sum([tx ty]') <= 0.9); -t = [tx(ti) ty(ti)]; -np = length(t); - +[tx ty] = meshgrid(0.05:0.1:0.95, 0.05:0.1:0.95); +tx = tx(:); +ty = ty(:); +ti = find(sum([tx ty],2) <= 0.9); +t = [tx(ti) ty(ti)]; +np = length(t); + % Map the template (square) triangle onto each face of the Cortical Mesh %-------------------------------------------------------------------------- -P1 = vert(face(:,1),:); -P2 = vert(face(:,2),:); -P3 = vert(face(:,3),:); - -If = speye(nf); -alpha = t(:,1); -beta = t(:,2); -teta = ones(np,1) - alpha - beta; +P1 = vert(face(:,1),:); +P2 = vert(face(:,2),:); +P3 = vert(face(:,3),:); + +If = speye(nf); +alpha = t(:,1); +beta = t(:,2); +teta = ones(np,1) - alpha - beta; clear t tx ty ti - + DenseCortex = kron(If,alpha)*P2 + kron(If,beta)*P3 + kron(If,teta)*P1; clear P1 P2 P3 - + % Transform the sampling point coordinates from mm to voxels %-------------------------------------------------------------------------- VoxelCoord = Vin.mat\[DenseCortex';ones(1,size(DenseCortex,1))]; VoxelCoord = round(VoxelCoord(1:3,:)'); clear DenseCortex - + % Get Graph Laplacian for smoothing on the cortical surface %-------------------------------------------------------------------------- -A = spm_eeg_inv_meshdist(vert,face,0); +A = spm_mesh_distmtx(struct('vertices',vert,'faces',face),0); GL = speye(nd,nd) + (A - spdiags(sum(A,2),0,nd,nd))/16; -% Interpolate the values in each vertex to compute the values at each -% sampling point of the triangles (cycle over conditions) +% normalize and embed in 3-space %========================================================================== [PTH,NAME,EXT] = fileparts(D.fname); -GW = D.inv{val}.contrast.GW; -for c = 1:length(GW) - - Contrast = GW{c}; +% accumulate mean of log-contrasts (over trials) +%-------------------------------------------------------------------------- +GW = D.inv{val}.contrast.GW; + +bytrial = iscell(GW{1}); + +Ne = []; +if bytrial + for c = 1:numel(GW) + Ne(c) = numel(GW{c}); + end +else + Ne = ones(1, numel(GW)); +end + +Nj = numel(GW)/Nw; + +k = 1; +iw = []; +ie = []; +for c = 1:length(GW) + if bytrial + cGW = GW{c}; + else + cGW = GW(c); + end - % Scale to mean power (%) - %---------------------------------------------------------------------- - Contrast = spm_vec(Contrast); - try - scale = D.inv{val}.contrast.scalefactor(c); - catch - scale = 1/mean(Contrast); + for t = 1:Ne(c) + % Smooth on the cortical surface + %---------------------------------------------------------------------- + ssq{k} = full(sparse(D.inv{val}.inverse.Is,1,cGW{t},nd,1)); + for i = 1:smooth + ssq{k} = GL*ssq{k}; + end + + % compute (truncated) moment + %---------------------------------------------------------------------- + lss = log(ssq{k} + eps); + i = lss > (max(lss) - log(32)); + meanlss(k) = mean(lss(i)); + + iw(k) = c; + ie(k) = t; + + k = k+1; end +end + +scale = exp(mean(meanlss)); +for c = 1:numel(ssq) - Contrast = spm_unvec(Contrast*scale, GW{c}); - D.inv{val}.contrast.scalefactor(c) = scale; + % Normalise + %---------------------------------------------------------------------- + Contrast = ssq{c}/scale; - % Smooth on the cortical surface + % Initialise image %---------------------------------------------------------------------- - Contrast = sparse(D.inv{val}.inverse.Is,1,Contrast,nd,1); - for i = 1:32 - Contrast = GL*Contrast; + con = mod(iw(c) - 1, Nj) + 1; + str = tag{ceil(iw(c)/Nj)}; + if bytrial + fname = fullfile(D.path,sprintf('%s_%.0f_%s%.0f_%.0f.nii',NAME,val,str,con, ie(c))); + else + fname = fullfile(D.path,sprintf('%s_%.0f_%s%.0f.nii',NAME,val,str,con)); end - - Outputfilename = fullfile(D.path,sprintf( 'w_%s_%.0f_%.0f.nii',NAME,val,c)); - Outputsmoothed = fullfile(D.path,sprintf( 'sw_%s_%.0f_%.0f.nii',NAME,val,c)); - Vout = struct(... - 'fname', Outputfilename,... + 'fname', fname,... 'dim', Vin.dim,... 'dt', [spm_type('float32') spm_platform('bigend')],... 'mat', Vin.mat,... 'pinfo', [1 0 0]',... 'descrip', ''); - InterpOp = [teta alpha beta]; - SPvalues = zeros(nf*np,1); - RECimage = zeros(Vout.dim); - + InterpOp = [teta alpha beta]; + SPvalues = zeros(nf*np,1); + RECimage = zeros(Vout.dim); + + % And interpolate those values into voxels %---------------------------------------------------------------------- for i = 1:nf @@ -178,39 +205,31 @@ MatV = zeros(max(J),length(J)); IndK = sub2ind(size(MatV),J,K'); MatV(IndK) = Val; - SV = sum(MatV')'; + SV = sum(MatV,2); RECimage(IndV) = RECimage(IndV) + SV; end end - - % Write (scaled) image + + % 3D smoothing and thresholding %---------------------------------------------------------------------- - Vout = spm_write_vol(Vout,RECimage); + spm_smooth(RECimage,RECimage,1); + RECimage = RECimage.*(RECimage > exp(-8)); - % Smoothing & Masking + % Write (smoothed and scaled) image %---------------------------------------------------------------------- - spm_smooth(Vout,Outputsmoothed,smoothparam); + Vout = spm_write_vol(Vout,RECimage); - RECimage = spm_read_vols(spm_vol(Outputsmoothed)); - vc = Vout.mat\[vert';ones(1,size(vert,1))]; - vc = round(vc(1:3,:)'); - msk = zeros(Vout.dim); - IndV = sub2ind(Vout.dim,vc(:,1),vc(:,2),vc(:,3)); - msk(IndV) = 1; - spm_smooth(msk,msk,8); - msk = msk > max(msk(:))/8; - Vout.fname = Outputsmoothed; - Vout = rmfield(Vout,'pinfo'); - Vout = spm_write_vol(Vout,RECimage .* msk); + % save and report + %---------------------------------------------------------------------- + str = 'Summary-statistic image written:\n %s\n'; + fprintf(str,fname); - str = 'Summary-statistic image written:\n %s\n %s (smoothed)\n'; - fprintf(str,Outputfilename,Outputsmoothed); %-# D.inv{val}.contrast.Vout{c} = Vout; - D.inv{val}.contrast.fname{c} = Outputsmoothed; - + D.inv{val}.contrast.fname{c} = fname; + end - + % display %========================================================================== if Disp, spm_eeg_inv_image_display(D); end diff --git a/spm_eeg_inv_checkdatareg.m b/spm_eeg_inv_checkdatareg.m index 24bbef4..72f80be 100644 --- a/spm_eeg_inv_checkdatareg.m +++ b/spm_eeg_inv_checkdatareg.m @@ -3,12 +3,12 @@ function spm_eeg_inv_checkdatareg(varargin) % quality check by eye. % Fiducials which were used for rigid registration are also displayed % -% FORMAT spm_eeg_inv_checkdatareg(mesh, sensors) +% FORMAT spm_eeg_inv_checkdatareg(D, val, ind) %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Jeremie Mattout -% $Id: spm_eeg_inv_checkdatareg.m 3388 2009-09-11 08:44:35Z vladimir $ +% $Id: spm_eeg_inv_checkdatareg.m 3731 2010-02-17 14:45:18Z vladimir $ % SPM graphics figure %-------------------------------------------------------------------------- @@ -19,11 +19,13 @@ function spm_eeg_inv_checkdatareg(varargin) datareg = D.inv{val}.datareg; -str = sprintf('%s|', datareg(:).modality); -str = str(1:(end-1)); - -ind = spm_input('What to display?','+1', 'b', str, 1:numel(D.inv{val}.datareg), 1); - +if nargin < 3 + str = sprintf('%s|', datareg(:).modality); + str = str(1:(end-1)); + ind = spm_input('What to display?','+1', 'b', str, 1:numel(D.inv{val}.datareg), 1); +else + ind = varargin{3}; +end % --- Set up variables --- %========================================================================== diff --git a/spm_eeg_inv_checkforward.m b/spm_eeg_inv_checkforward.m index 2a7ef1a..0c1b09e 100644 --- a/spm_eeg_inv_checkforward.m +++ b/spm_eeg_inv_checkforward.m @@ -1,11 +1,11 @@ function spm_eeg_inv_checkforward(varargin) % checks forward model -% FORMAT spm_eeg_inv_checkforward(D) +% FORMAT spm_eeg_inv_checkforward(D, val , ind) %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Vladimir Litvak -% $Id: spm_eeg_inv_checkforward.m 3145 2009-05-25 16:00:43Z vladimir $ +% $Id: spm_eeg_inv_checkforward.m 3833 2010-04-22 14:49:48Z vladimir $ % SPM data structure %========================================================================== @@ -13,10 +13,14 @@ function spm_eeg_inv_checkforward(varargin) forward = D.inv{val}.forward; -str = sprintf('%s|', forward(:).modality); -str = str(1:(end-1)); - -ind = spm_input('What to display?','+1', 'b', str, 1:numel(forward), 1); +if nargin < 3 + str = sprintf('%s|', forward(:).modality); + str = str(1:(end-1)); + + ind = spm_input('What to display?','+1', 'b', str, 1:numel(forward), 1); +else + ind = varargin{3}; +end try vol = forward(ind).vol; @@ -38,7 +42,7 @@ function spm_eeg_inv_checkforward(varargin) end if ischar(vol) - vol = fileio_read_vol(vol); + vol = ft_read_vol(vol); end %-------------------------------------------------------------------------- diff --git a/spm_eeg_inv_custom_ui.m b/spm_eeg_inv_custom_ui.m index 4610f2b..d582216 100644 --- a/spm_eeg_inv_custom_ui.m +++ b/spm_eeg_inv_custom_ui.m @@ -21,7 +21,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_eeg_inv_custom_ui.m 3618 2009-12-08 16:05:15Z vladimir $ +% $Id: spm_eeg_inv_custom_ui.m 3903 2010-05-28 09:39:13Z vladimir $ % defaults from D is specified %========================================================================== @@ -44,7 +44,7 @@ % Search strategy %-------------------------------------------------------------------------- - type = spm_input('Model inversion','+1','GS|ARD|COH|IID',{'GS','ARD','LOR','IID'},1); + type = spm_input('Model inversion','+1','GS|COH|IID',{'GS','LOR','IID'},1); inverse.type = type{1}; % Time window of interest diff --git a/spm_eeg_inv_datareg.m b/spm_eeg_inv_datareg.m index b782a4b..a8424f6 100644 --- a/spm_eeg_inv_datareg.m +++ b/spm_eeg_inv_datareg.m @@ -33,7 +33,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Jeremie Mattout -% $Id: spm_eeg_inv_datareg.m 2320 2008-10-09 10:01:22Z vladimir $ +% $Id: spm_eeg_inv_datareg.m 3833 2010-04-22 14:49:48Z vladimir $ if nargin == 0 || ~isstruct(S) @@ -43,13 +43,13 @@ if ~isfield(S, 'targetfid') error('Target fiducials are missing'); else - targetfid = forwinv_convert_units(S.targetfid, 'mm'); + targetfid = ft_convert_units(S.targetfid, 'mm'); end if ~isfield(S, 'sourcefid') error('Source are missing'); else - sourcefid = forwinv_convert_units(S.sourcefid, 'mm'); + sourcefid = ft_convert_units(S.sourcefid, 'mm'); [sel1, sel2] = spm_match_str(targetfid.fid.label, sourcefid.fid.label); sourcefid.fid.pnt = sourcefid.fid.pnt(sel2, :); sourcefid.fid.label = sourcefid.fid.label(sel2); @@ -67,7 +67,7 @@ %-------------------------------------------------------------------------- M1 = spm_eeg_inv_rigidreg(targetfid.fid.pnt', sourcefid.fid.pnt'); -sourcefid = forwinv_transform_headshape(M1, sourcefid); +sourcefid = ft_transform_headshape(M1, sourcefid); if S.template @@ -81,7 +81,7 @@ M = pinv(sourcefid.fid.pnt(:))*targetfid.fid.pnt(:); M = sparse(1:4,1:4,[M M M 1]); - sourcefid = forwinv_transform_headshape(M, sourcefid); + sourcefid = ft_transform_headshape(M, sourcefid); M1 = M*M1; @@ -89,7 +89,7 @@ %---------------------------------------------------------------------- M = spm_eeg_inv_rigidreg(targetfid.fid.pnt', sourcefid.fid.pnt'); - sourcefid = forwinv_transform_headshape(M, sourcefid); + sourcefid = ft_transform_headshape(M, sourcefid); M1 = M*M1; @@ -136,6 +136,6 @@ % transform headshape and eeg fiducials %---------------------------------------------------------------------- - sourcefid = forwinv_transform_headshape(M, sourcefid); + sourcefid = ft_transform_headshape(M, sourcefid); M1 = M*M1; end diff --git a/spm_eeg_inv_datareg_ui.m b/spm_eeg_inv_datareg_ui.m index db73ffb..6c0023a 100644 --- a/spm_eeg_inv_datareg_ui.m +++ b/spm_eeg_inv_datareg_ui.m @@ -2,15 +2,21 @@ % Data registration user-interface routine % commands the EEG/MEG data co-registration within original sMRI space % -% FORMAT D = spm_eeg_inv_datareg_ui(D,[val]) +% FORMAT D = spm_eeg_inv_datareg_ui(D,[val], [meegfid, newmrifid, useheadshape]) % Input: +% D - M/EEG dataset +% +% meegfid - M/EEG fiducials +% mrifid - MRI fiducials +% useheadshape - use headshape points (1) +% % Output: % D - same data struct including the new required files and variables %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Vladimir Litvak -% $Id: spm_eeg_inv_datareg_ui.m 2819 2009-03-03 13:15:42Z vladimir $ +% $Id: spm_eeg_inv_datareg_ui.m 3833 2010-04-22 14:49:48Z vladimir $ % initialise %-------------------------------------------------------------------------- @@ -18,60 +24,67 @@ [D,val] = spm_eeg_inv_check(varargin{:}); -try - D.inv{val}.mesh.template; -catch - D.inv{val}.mesh.template = 0; -end - -meegfid = D.fiducials; mrifid = D.inv{val}.mesh.fid; - -meeglbl = meegfid.fid.label; mrilbl = mrifid.fid.label; -newmrifid = mrifid; -newmrifid.fid.pnt = []; -newmrifid.fid.label = {}; - -if numel(meeglbl)> 3 - [selection ok]= listdlg('ListString', meeglbl, 'SelectionMode', 'multiple',... - 'InitialValue', spm_match_str(upper(meeglbl), upper(mrilbl)), ... - 'Name', 'Select at least 3 fiducials', 'ListSize', [400 300]); - - if ~ok || length(selection) < 3 - error('At least 3 M/EEG fiducials are required for coregistration'); +if nargin>=3 + meegfid = varargin{3}; + interactive = 0; +else + interactive = 1; + meegfid = D.fiducials; + meeglbl = meegfid.fid.label; + + if numel(meeglbl)> 3 + [selection ok]= listdlg('ListString', meeglbl, 'SelectionMode', 'multiple',... + 'InitialValue', spm_match_str(upper(meeglbl), upper(mrilbl)), ... + 'Name', 'Select at least 3 fiducials', 'ListSize', [400 300]); + + if ~ok || length(selection) < 3 + error('At least 3 M/EEG fiducials are required for coregistration'); + end + + meegfid.fid.pnt = meegfid.fid.pnt(selection, :); + meegfid.fid.label = meegfid.fid.label(selection); end - - meegfid.fid.pnt = meegfid.fid.pnt(selection, :); - meegfid.fid.label = meegfid.fid.label(selection); - meeglbl = meeglbl(selection); end +meeglbl = meegfid.fid.label; + if numel(meeglbl)<3 error('At least 3 M/EEG fiducials are required for coregistration'); end if all(ismember({'spmnas', 'spmlpa', 'spmrpa'}, meegfid.fid.label)) && isempty(D.sensors('MEG')) - - S =[]; S.sourcefid = meegfid; S.targetfid = mrifid; - if D.inv{val}.mesh.template + if D.inv{val}.mesh.template M1 = eye(4); S.targetfid.fid = S.sourcefid.fid; - else + S.useheadshape = 0; + else M1 = []; S.sourcefid.fid.label{strmatch('spmnas', S.sourcefid.fid.label, 'exact')} = 'nas'; S.sourcefid.fid.label{strmatch('spmlpa', S.sourcefid.fid.label, 'exact')} = 'lpa'; S.sourcefid.fid.label{strmatch('spmrpa', S.sourcefid.fid.label, 'exact')} = 'rpa'; S.targetfid.fid.pnt = S.targetfid.fid.pnt(1:3, :); - S.targetfid.fod.label = S.targetfid.fid.label(1:3, :); + S.targetfid.fid.label = S.targetfid.fid.label(1:3, :); S.useheadshape = 1; - end -else + end +elseif nargin>=4 + M1 = []; + S.sourcefid = meegfid; + S.targetfid = varargin{4}; + + if nargin >= 5 + S.useheadshape = varargin{5}; + end +else + newmrifid = mrifid; + newmrifid.fid.pnt = []; + newmrifid.fid.label = {}; M1 = []; for i = 1:length(meeglbl) switch spm_input(['How to specify ' meeglbl{i} ' position?'] , 1, 'select|type|click|skip') @@ -82,7 +95,7 @@ if ~ok continue end - + newmrifid.fid.pnt = [newmrifid.fid.pnt; mrifid.fid.pnt(selection, :)]; case 'type' pnt = spm_input('Input MNI coordinates', '+1', 'r', '', 3); @@ -110,22 +123,22 @@ end newmrifid.fid.label = [newmrifid.fid.label meeglbl{i}]; end - + if size(newmrifid.fid.label) < 3 error('At least 3 M/EEG fiducials are required for coregistration'); end - + % register %========================================================================== S =[]; S.sourcefid = meegfid; - S.targetfid = newmrifid; + S.targetfid = newmrifid; +end - if ~isempty(S.sourcefid.pnt) - S.useheadshape = spm_input('Use headshape points?' , '+1','yes|no', [1,0], 1); - else - S.useheadshape = 0; - end +if ~isempty(S.sourcefid.pnt) && ~isfield(S, 'useheadshape') + S.useheadshape = spm_input('Use headshape points?' , '+1','yes|no', [1,0], 1); +else + S.useheadshape = 0; end ind = 1; @@ -137,8 +150,8 @@ M1 = spm_eeg_inv_datareg(S); end - D.inv{val}.datareg(ind).sensors = forwinv_transform_sens(M1, D.sensors('EEG')); - D.inv{val}.datareg(ind).fid_eeg = forwinv_transform_headshape(M1, S.sourcefid); + D.inv{val}.datareg(ind).sensors = ft_transform_sens(M1, D.sensors('EEG')); + D.inv{val}.datareg(ind).fid_eeg = ft_transform_headshape(M1, S.sourcefid); D.inv{val}.datareg(ind).fid_mri = S.targetfid; D.inv{val}.datareg(ind).toMNI = D.inv{val}.mesh.Affine; D.inv{val}.datareg(ind).fromMNI = inv(D.inv{val}.datareg(ind).toMNI); @@ -152,12 +165,12 @@ else S.template = 0; end - + M1 = spm_eeg_inv_datareg(S); - + D.inv{val}.datareg(ind).sensors = D.sensors('MEG'); D.inv{val}.datareg(ind).fid_eeg = S.sourcefid; - D.inv{val}.datareg(ind).fid_mri = forwinv_transform_headshape(inv(M1), S.targetfid); + D.inv{val}.datareg(ind).fid_mri = ft_transform_headshape(inv(M1), S.targetfid); D.inv{val}.datareg(ind).toMNI = D.inv{val}.mesh.Affine*M1; D.inv{val}.datareg(ind).fromMNI = inv(D.inv{val}.datareg(ind).toMNI); D.inv{val}.datareg(ind).modality = 'MEG'; @@ -165,6 +178,12 @@ % check and display registration %-------------------------------------------------------------------------- -spm_eeg_inv_checkdatareg(D); +if interactive + spm_eeg_inv_checkdatareg(D); +else + for i = 1:numel(D.inv{val}.datareg) + spm_eeg_inv_checkdatareg(D, val, i); + end +end diff --git a/spm_eeg_inv_forward.m b/spm_eeg_inv_forward.m index 0cf6933..0f1ca09 100644 --- a/spm_eeg_inv_forward.m +++ b/spm_eeg_inv_forward.m @@ -13,7 +13,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Jeremie Mattout & Christophe Phillips -% $Id: spm_eeg_inv_forward.m 3161 2009-05-29 12:20:50Z vladimir $ +% $Id: spm_eeg_inv_forward.m 3965 2010-07-01 17:16:17Z vladimir $ % initialise %-------------------------------------------------------------------------- @@ -85,6 +85,22 @@ end vol = volfile; modality = 'EEG'; + case 'OpenMEEG BEM' + vol = []; + vol.cond = [0.3300 0.0041 0.3300]; + vol.source = 1; % index of source compartment + vol.skin = 3; % index of skin surface + % brain + vol.bnd(1) = export(gifti(D.inv{val}.mesh.tess_iskull), 'ft'); + % skull + vol.bnd(2) = export(gifti(D.inv{val}.mesh.tess_oskull), 'ft'); + % skin + vol.bnd(3) = export(gifti(D.inv{val}.mesh.tess_scalp), 'ft'); + + cfg = []; + cfg.method = 'openmeeg'; + vol = ft_prepare_bemmodel(cfg, vol); + modality = 'EEG'; case 'Single Sphere' cfg = []; cfg.feedback = 'yes'; @@ -106,7 +122,7 @@ vol = []; vol.bnd = export(gifti(mesh.tess_iskull), 'ft'); vol.type = 'nolte'; - vol = forwinv_convert_units(vol, 'mm'); + vol = ft_convert_units(vol, 'mm'); modality = 'MEG'; otherwise error('Unsupported volume model type'); diff --git a/spm_eeg_inv_forward_ui.m b/spm_eeg_inv_forward_ui.m index 81a4b41..feae988 100644 --- a/spm_eeg_inv_forward_ui.m +++ b/spm_eeg_inv_forward_ui.m @@ -13,7 +13,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Jeremie Mattout & Christophe Phillips -% $Id: spm_eeg_inv_forward_ui.m 2914 2009-03-20 18:30:31Z guillaume $ +% $Id: spm_eeg_inv_forward_ui.m 3731 2010-02-17 14:45:18Z vladimir $ %-Initialisation %-------------------------------------------------------------------------- @@ -24,11 +24,7 @@ for i = 1:numel(D.inv{val}.datareg) switch D.inv{val}.datareg(i).modality case 'EEG' - if D.inv{val}.mesh.template - models = {'EEG BEM', '3-Shell Sphere (experimental)'}; - else - models = {'EEG BEM', '3-Shell Sphere (experimental)'}; - end + models = {'EEG BEM', '3-Shell Sphere (experimental)'}; case 'MEG' models = {'Single Sphere', 'MEG Local Spheres', 'Single Shell'}; otherwise diff --git a/spm_eeg_inv_group.m b/spm_eeg_inv_group.m index 68dea58..08476ba 100644 --- a/spm_eeg_inv_group.m +++ b/spm_eeg_inv_group.m @@ -28,9 +28,9 @@ function spm_eeg_inv_group(S) % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_eeg_inv_group.m 3564 2009-11-12 18:46:17Z vladimir $ +% $Id: spm_eeg_inv_group.m 3979 2010-07-08 14:53:46Z vladimir $ -SVNrev = '$Rev: 3564 $'; +SVNrev = '$Rev: 3979 $'; %-Startup %-------------------------------------------------------------------------- @@ -189,12 +189,12 @@ function spm_eeg_inv_group(S) % Forward model %---------------------------------------------------------------------- D{i} = spm_eeg_inv_datareg_ui(D{i}, 1); - if i == 1 - D{i} = spm_eeg_inv_forward_ui(D{i}); - voltype = D{i}.inv{1}.forward.voltype; - else + try D{i}.inv{1}.forward.voltype = voltype; D{i} = spm_eeg_inv_forward(D{i}); + catch + D{i} = spm_eeg_inv_forward_ui(D{i}); + voltype = D{i}.inv{1}.forward.voltype; end % save forward model diff --git a/spm_eeg_inv_imag_api.m b/spm_eeg_inv_imag_api.m index ad419ff..997746f 100644 --- a/spm_eeg_inv_imag_api.m +++ b/spm_eeg_inv_imag_api.m @@ -7,7 +7,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Jeremie Mattout -% $Id: spm_eeg_inv_imag_api.m 3679 2010-01-14 10:49:35Z vladimir $ +% $Id: spm_eeg_inv_imag_api.m 3996 2010-07-13 22:20:40Z vladimir $ spm('Clear'); @@ -105,9 +105,6 @@ function contrast_Callback(hObject, eventdata, handles) % --- Executes on button press in Image. %-------------------------------------------------------------------------- function Image_Callback(hObject, eventdata,handles) -Qstr = 'Please choose'; -Tstr = 'Smoothing in mm'; -handles.D.inv{handles.D.val}.contrast.smooth = str2num(questdlg(Qstr,Tstr,'8','12','16','12')); handles.D.inv{handles.D.val}.contrast.display = 1; handles.D = spm_eeg_inv_Mesh2Voxels(handles.D); Reset(hObject, eventdata, handles); @@ -161,7 +158,7 @@ function new_Callback(hObject, eventdata, handles) D = handles.D; if ~isfield(D,'inv') val = 1; -elseif ~length(D.inv) +elseif isempty(D.inv) val = 1; else val = length(D.inv) + 1; diff --git a/spm_eeg_inv_mesh.m b/spm_eeg_inv_mesh.m index fc3ef96..e133d46 100644 --- a/spm_eeg_inv_mesh.m +++ b/spm_eeg_inv_mesh.m @@ -1,20 +1,19 @@ function mesh = spm_eeg_inv_mesh(sMRI, Msize) % Apply the inverse spatial deformation to the template mesh % to obtain the individual cortical mesh -% save the individual .mat tesselation of the chosen size +% save the individual GIFTI meshes % -% FORMAT [fid, mesh] = spm_eeg_inv_meshing(filename, Msize) +% FORMAT mesh = spm_eeg_inv_mesh(sMRI, Msize) % Input: -% sMRI - name of the sMRI file -% Msize - size of the mesh (1-3) +% sMRI - name of the sMRI file +% Msize - size of the mesh (1-3) % Output: -% fid - fiducials (head surface + points inverse normalized from the template) -% mesh - inverse - normalized canonical mesh +% mesh - inverse - normalized canonical mesh %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Jeremie Mattout & Christophe Phillips -% $Id: spm_eeg_inv_mesh.m 2763 2009-02-19 14:50:58Z guillaume $ +% $Id: spm_eeg_inv_mesh.m 3833 2010-04-22 14:49:48Z vladimir $ % SPM directory of canonical anatomy @@ -109,14 +108,11 @@ % datareg %-------------------------------------------------------------------------- +fid = ft_read_headshape(fullfile(spm('dir'), 'EEGtemplates', 'fiducials.sfp')); + mesh.fid = export(gifti(mesh.tess_scalp), 'ft'); mesh.fid.unit = 'mm'; -mesh.fid.fid = struct('pnt', [ 1 85 -41; ... - -83 -20 -65; ... - 83 -20 -65; ... - -87 -11 -62; ... - 87 -11 -62], ... - 'label', {{'nas'; 'lpa'; 'rpa'; 'FIL_CTF_L'; 'FIL_CTF_R'}}); +mesh.fid.fid = fid.fid; if ~mesh.template fidpnt = mesh.fid.fid; diff --git a/spm_eeg_inv_mesh_ui.m b/spm_eeg_inv_mesh_ui.m index 19091e7..36103a4 100644 --- a/spm_eeg_inv_mesh_ui.m +++ b/spm_eeg_inv_mesh_ui.m @@ -1,10 +1,10 @@ function D = spm_eeg_inv_mesh_ui(varargin) % Cortical Mesh user interface -% FORMAT D = spm_eeg_inv_mesh_ui(D, val, template, Msize) +% FORMAT D = spm_eeg_inv_mesh_ui(D, val, sMRI, Msize) % % D - input data struct (optional) % val - -% template - +% sMRI - 0 - use template (default), or string with image file name % Msize - % % D - same data struct including the meshing files and variables @@ -16,9 +16,9 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Jeremie Mattout & Christophe Phillips -% $Id: spm_eeg_inv_mesh_ui.m 2914 2009-03-20 18:30:31Z guillaume $ +% $Id: spm_eeg_inv_mesh_ui.m 3731 2010-02-17 14:45:18Z vladimir $ -SVNrev = '$Rev: 2914 $'; +SVNrev = '$Rev: 3731 $'; %-Startup %-------------------------------------------------------------------------- @@ -45,25 +45,29 @@ end if nargin > 2 - template = varargin{3}; + sMRI = varargin{3}; else - template = []; + sMRI = []; end -if isempty(template) +if isempty(sMRI) template = spm_input('Select head model', '+1','template|individual', [1 0]); +elseif ~ischar(sMRI) + template = sMRI; % for backward compatibility +else + template = 1; end if template sMRI = []; -else +elseif ~ischar(sMRI) % get sMRI file name sMRI = spm_select([0 1],'image','Select subject''s structural MRI (Press Done if none)'); if isempty(sMRI) error('No structural MRI selected.'); end end - + if nargin>3 Msize = varargin{4}; else diff --git a/spm_eeg_inv_meshdist.m b/spm_eeg_inv_meshdist.m deleted file mode 100644 index aea777b..0000000 --- a/spm_eeg_inv_meshdist.m +++ /dev/null @@ -1,66 +0,0 @@ -function [Mdist] = spm_eeg_inv_meshdist(vert,face,order) -% Efficient computation of the 2nd order distance matrix of a triangulated -% irregular mesh, based on the cortical neighbourhoud (geodesic distance) -% vert - locations of vertices -% face - indices of faces -% order - 0; Adjacency matrix -% 1: 1st order distance matrix -% 2: 2nd order distance matrix -% Inspired by function mesh_laplacian.m by Darren Weber -% from the bioelectromagnetism matlab toolbox -% see http://eeg.sourceforge.net/ -%__________________________________________________________________________ -% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging - -% Jeremie Mattout -% $Id: spm_eeg_inv_meshdist.m 3173 2009-06-02 14:50:19Z karl $ - -% default order is 2nd -%-------------------------------------------------------------------------- -if nargin < 3 - order = 2; -end - -Nv = length(vert); -Nf = length(face); - -edge = sparse(Nv,Nv); -EuclD = ones(3,1); -for i = 1:Nf; - - % 1st order: compute Euclidean distances - %---------------------------------------------------------------------- - if order - Diff = [vert(face(i,[1 2 3]),:) - vert(face(i,[2 3 1]),:)]; - EuclD = sqrt( sum(Diff.^2, 2) ); - end - - edge(face(i,1),face(i,2)) = EuclD(1); - edge(face(i,2),face(i,3)) = EuclD(2); - edge(face(i,3),face(i,1)) = EuclD(3); - - edge(face(i,2),face(i,1)) = EuclD(1); - edge(face(i,3),face(i,2)) = EuclD(2); - edge(face(i,1),face(i,3)) = EuclD(3); -end - -% 0th order connectivity (Adjacency matrix) -%-------------------------------------------------------------------------- -Mdist = edge; -if ~order - Mdist = Mdist > 0; -end - -% 2nd order connectivity -%-------------------------------------------------------------------------- -if order == 2; - for i = 1:Nv - a = find(edge(i,:)); - [b,c] = find(edge(a,:)); - Mdist(i,c) = Mdist(i,a(b)) + diag(Mdist(a(b),c))'; - Mdist(c,i) = Mdist(i,c)'; - end -end - -return -%========================================================================== diff --git a/spm_eeg_inv_results.m b/spm_eeg_inv_results.m index 66ad0d5..5c8ce30 100644 --- a/spm_eeg_inv_results.m +++ b/spm_eeg_inv_results.m @@ -3,7 +3,7 @@ % FORMAT [D] = spm_eeg_inv_results(D) % Requires: % -% D.inv{i}.contrast.woi - time (ms) window of interest +% D.inv{i}.contrast.woi - (n x 2) time (ms) window[s] of interest % D.inv{i}.contrast.fboi - frequency window of interest % D.inv{i}.contrast.type - 'evoked' or 'induced' % @@ -14,7 +14,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_eeg_inv_results.m 3651 2009-12-18 16:53:52Z guillaume $ +% $Id: spm_eeg_inv_results.m 3976 2010-07-08 14:12:31Z karl $ % SPM data structure %========================================================================== @@ -32,11 +32,11 @@ try, type = model.contrast.type; catch, type = 'evoked'; end -% Check contrast woi is within inversion woi +% Ensure contrast woi is within inversion woi %-------------------------------------------------------------------------- -if woi(1) < model.inverse.woi(1) || woi(2) > model.inverse.woi(2) - error(sprintf('Contrast, %s, must be within inversion time-window, %s',mat2str(woi),mat2str(D.inv{D.val}.inverse.woi))) -end +woi(:,1) = max(woi(:,1),model.inverse.woi(1)); +woi(:,2) = min(woi(:,2),model.inverse.woi(2)); + if ~any(foi) foi = []; end @@ -55,126 +55,175 @@ Nd = model.inverse.Nd; % number of mesh dipoles Nb = size(T,1); % number of time bins Nc = size(U,1); % number of channels +Nw = size(woi,1); % number of contrast windows +Nj = numel(J); % number of conditions try - scale = model.inverse.scale; % Trial average MAP estimate + scale = model.inverse.scale; % Trial average MAP estimate catch scale = 1; end + % time-frequency contrast %========================================================================== - -% get [Gaussian] time window -%-------------------------------------------------------------------------- -fwhm = max(diff(woi),8); -t = exp(-4*log(2)*(pst(:) - mean(woi)).^2/(fwhm^2)); -t = t/sum(t); - - -% get frequency space and put PST subspace into contrast (W -> T*T'*W) -%-------------------------------------------------------------------------- -if ~isempty(foi) - wt = 2*pi*pst(:)/1000; - W = []; - for f = foi(1):foi(end) - W = [W sin(f*wt) cos(f*wt)]; +model.contrast.W = {}; +model.contrast.JW = {}; +model.contrast.GW = {}; + +for w = 1:Nw; + + % get [Gaussian] time window + %-------------------------------------------------------------------------- + fwhm = max(diff(woi(w,:)),8); + t = exp(-4*log(2)*(pst(:) - mean(woi(w,:))).^2/(fwhm^2)); + t = t/sum(t); + + + % get frequency space and put PST subspace into contrast (W -> T*T'*W) + %-------------------------------------------------------------------------- + if ~isempty(foi) + wt = 2*pi*pst(:)/1000; + W = []; + for f = foi(1):foi(end) + W = [W sin(f*wt) cos(f*wt)]; + end + W = diag(t)*W; + W = spm_svd(W,1); + else + W = t(:); end - W = diag(t)*W; - W = spm_svd(W,1); -else - W = t(:); -end -TW = T'*W; -TTW = T*TW; - -% MAP projector and conditional covariance -%========================================================================== -M = model.inverse.M; -V = model.inverse.qV; -qC = model.inverse.qC*trace(TTW'*V*TTW); -qC = max(qC,0); - - -% cycle over trial types -%========================================================================== -try - trial = model.inverse.trials; -catch - trial = D.condlist; -end -for i = 1:length(J) - - % induced or evoked - %---------------------------------------------------------------------- - switch(type) - - % energy of conditional mean - %------------------------------------------------------------------ - case{'evoked'} - - JW{i} = J{i}*TW(:,1); - GW{i} = sum((J{i}*TW).^2,2) + qC; - - % mean energy over trials + TW = T'*W; + TTW = T*TW; + + % MAP projector and conditional covariance + %========================================================================== + qC = model.inverse.qC*trace(TTW'*model.inverse.qV*TTW); + qC = max(qC,0); + + + % cycle over trial types + %========================================================================== + try + trial = model.inverse.trials; + catch + trial = D.condlist; + end + for i = 1:Nj + + % induced or evoked %------------------------------------------------------------------ - case{'induced'} - - JW{i} = sparse(0); - JWWJ = sparse(0); - - c = D.pickconditions(trial{i}); - - % conditional expectation of contrast (J*W) and its energy + iw = (w - 1)*Nj + i; + CW{iw} = W; + + switch(type) + + % energy of conditional mean %-------------------------------------------------------------- - Nt = length(c); - spm_progress_bar('Init',Nt,sprintf('condition %d',i),'trials'); - for j = 1:Nt - try - - % unimodal data - %------------------------------------------------------ - Y = D(Ic{1},It,c(j))*TTW; - Y = U{1}*Y*scale; + case{'evoked'} + + JW{iw} = J{i}*TW(:,1); + GW{iw} = sum((J{i}*TW).^2,2) + qC; + + % mean energy over trials + %-------------------------------------------------------------- + case{'induced'} + + JW{iw} = sparse(0); + JWWJ = sparse(0); + + c = D.pickconditions(trial{i}); + + % conditional expectation of contrast (J*W) and its energy + %---------------------------------------------------------- + Nt = length(c); + spm_progress_bar('Init',Nt,sprintf('condition %d',i),'trials'); + for j = 1:Nt + if ~strcmp(D.modality(1,1), 'Multimodal') + + % unimodal data + %-------------------------------------------------- + Y = D(Ic{1},It,c(j))*TTW; + Y = U{1}*Y*scale; + + else + + % multimodal data + %-------------------------------------------------- + for k = 1:length(U) + Y = D(Ic{k},It,c(j))*TTW; + UY{k,1} = U{k}*Y*scale(k); + end + Y = spm_cat(UY); + end - catch + MYW = model.inverse.M*Y; + JW{iw} = JW{iw} + MYW(:,1); + JWWJ = JWWJ + sum(MYW.^2,2); + spm_progress_bar('Set',j) - % multimodal data - %------------------------------------------------------ - for k = 1:length(U) - Y = D(Ic{k},It,c(j))*TTW; - UY{k,1} = U{k}*Y*scale(k); - end - Y = spm_cat(UY); end + spm_progress_bar('Clear') - MYW = M*Y; - JW{i} = JW{i} + MYW(:,1); - JWWJ = JWWJ + sum(MYW.^2,2); - spm_progress_bar('Set',j) - end - spm_progress_bar('Clear') - - % conditional expectation of total energy (source space GW) - %-------------------------------------------------------------- - JW{i} = JW{i}/Nt; - GW{i} = JWWJ/Nt + qC; + % conditional expectation of total energy (source space GW) + %---------------------------------------------------------- + JW{iw} = JW{iw}/Nt; + GW{iw} = JWWJ/Nt + qC; + + case 'trials' + + JW{iw} = {}; + JWWJ = {}; + + c = D.pickconditions(trial{i}); + + % conditional expectation of contrast (J*W) and its energy + %---------------------------------------------------------- + Nt = length(c); + spm_progress_bar('Init',Nt,sprintf('condition %d',i),'trials'); + for j = 1:Nt + if ~strcmp(D.modality(1,1), 'Multimodal') + + % unimodal data + %-------------------------------------------------- + Y = D(Ic{1},It,c(j))*TTW; + Y = U{1}*Y*scale; + + else + + % multimodal data + %-------------------------------------------------- + for k = 1:length(U) + Y = D(Ic{k},It,c(j))*TTW; + UY{k,1} = U{k}*Y*scale(k); + end + Y = spm_cat(UY); + end + + MYW = model.inverse.M*Y; + JW{iw}{j} = MYW(:,1); + GW{iw}{j} = sum(MYW.^2,2) + qC; + spm_progress_bar('Set',j) + end + spm_progress_bar('Clear') + end + end - -end - - -% Save results -%========================================================================== -model.contrast.woi = woi; -model.contrast.fboi = foi; - -model.contrast.W = W; -model.contrast.JW = JW; -model.contrast.GW = GW; - -D.inv{D.val} = model; + + + % Save results + %====================================================================== + model.contrast.woi = woi; + model.contrast.fboi = foi; + + model.contrast.W = CW; + model.contrast.JW = JW; + model.contrast.GW = GW; + +end % window + +D.inv{D.val} = model; % Display diff --git a/spm_eeg_inv_results_display.m b/spm_eeg_inv_results_display.m index d7cf157..b6bd28e 100644 --- a/spm_eeg_inv_results_display.m +++ b/spm_eeg_inv_results_display.m @@ -5,7 +5,7 @@ function spm_eeg_inv_results_display(D) % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_eeg_inv_results_display.m 2822 2009-03-04 10:39:53Z vladimir $ +% $Id: spm_eeg_inv_results_display.m 3976 2010-07-08 14:12:31Z karl $ %========================================================================== Ndip = 256; % Number of dipoles to display @@ -21,10 +21,8 @@ function spm_eeg_inv_results_display(D) end model = D.inv{D.val}; - -con = min(con,length(model.inverse.J)); try - disp(model.contrast); + con = min(con,length(model.contrast.GW)); catch warndlg('please specify a [time-frequency] contrast') return @@ -32,14 +30,24 @@ function spm_eeg_inv_results_display(D) % inversion parameters %-------------------------------------------------------------------------- -Is = model.inverse.Is; % Indices of ARD vertices -pst = model.inverse.pst; % preistimulus tim (ms) -Nd = model.inverse.Nd; % number of mesh dipoles -Ndip = min(Ndip,length(Is)); +Is = model.inverse.Is; % Indices of ARD vertices +pst = model.inverse.pst; % preistimulus tim (ms) +Nd = model.inverse.Nd; % number of mesh dipoles +Ndip = min(Ndip,length(Is)); -W = model.contrast.W; -JW = model.contrast.JW{con}; -GW = model.contrast.GW{con}; +try + W = model.contrast.W{con}; +catch + W = model.contrast.W; +end +JW = model.contrast.JW{con}; +GW = model.contrast.GW{con}; + +% just display the first trial (for trial-specific contrasts) +%-------------------------------------------------------------------------- +if iscell(GW) + GW = GW{1}; +end % sqrt(energy) (G) = abs(JW) for single trials %-------------------------------------------------------------------------- @@ -64,7 +72,11 @@ function spm_eeg_inv_results_display(D) axis image try - str = sprintf('Energy (%s)',model.contrast.type); + if strcmp(model.contrast.type, 'trials') + str = sprintf('Energy (%s)', 'first trial'); + else + str = sprintf('Energy (%s)', model.contrast.type); + end catch str = 'Energy'; end diff --git a/spm_eeg_inv_results_ui.m b/spm_eeg_inv_results_ui.m index afb6ec7..e343318 100644 --- a/spm_eeg_inv_results_ui.m +++ b/spm_eeg_inv_results_ui.m @@ -9,13 +9,14 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_eeg_inv_results_ui.m 3558 2009-11-11 20:23:05Z karl $ +% $Id: spm_eeg_inv_results_ui.m 3987 2010-07-12 17:01:04Z vladimir $ % initialise %-------------------------------------------------------------------------- [D,val] = spm_eeg_inv_check(varargin{:}); try - woi = round(D.inv{val}.inverse.woi); + woi = D.inv{val}.inverse.woi; + woi = [ceil(min(woi)) floor(max(woi))]; catch warndlg('Please invert this model first'); return @@ -23,9 +24,8 @@ % get time window %-------------------------------------------------------------------------- - -woi = spm_input('Time window (ms)','+1','r',woi); -D.inv{val}.contrast.woi = round([min(woi) max(woi)]); +woi = spm_input('Time window(s) (ms)','+1','r', woi, [Inf, 2]); +D.inv{val}.contrast.woi = sort([ceil(woi(:,1)) floor(woi(:,2))],2); % get frequency window %-------------------------------------------------------------------------- @@ -35,7 +35,7 @@ % induced or evoked? (not for fusion) %-------------------------------------------------------------------------- if strcmp(D.type, 'single') - str = {'evoked','induced'}; + str = {'evoked','induced','trials'}; type = spm_input('Power','+1','b',str,[],1); else type = 'evoked'; diff --git a/spm_eeg_inv_vbecd.m b/spm_eeg_inv_vbecd.m index 1cfc4a4..aacc50c 100644 --- a/spm_eeg_inv_vbecd.m +++ b/spm_eeg_inv_vbecd.m @@ -1,5 +1,5 @@ function P = spm_eeg_inv_vbecd(P) -% Model inversion routine for ECDs using variational Bayesian approach +% Model inversion routine for ECDs using variational Bayesian approach % % FORMAT P = spm_eeg_inv_vbecd(P) % @@ -29,86 +29,94 @@ % a non-linear model - see spm_nlsi_gn) %__________________________________________________________________________ % Copyright (C) 2009 Wellcome Trust Centre for Neuroimaging -% Gareth Barnes -% $Id: spm_eeg_inv_vbecd.m 3514 2009-10-28 14:37:09Z gareth $ +% Gareth Barnes +% $Id: spm_eeg_inv_vbecd.m 3906 2010-06-01 10:48:32Z gareth $ -% unpack model, priors, data - -Nd = length(P.priors.mu_w0)/3; +% unpack model, priors, data +%-------------------------------------------------------------------------- +Nd = length(P.priors.mu_w0)/3; mu_w0 = P.priors.mu_w0; mu_s0 = P.priors.mu_s0; -S_w0 = P.priors.S_w0; -S_s0 = P.priors.S_s0; - -if strcmp(upper(P.modality),'EEG'), - P.y=P.y-mean(P.y); %% subtracting mean level from eeg data -end; % if - -y = P.y; -sc_y=10000/std(y); %% rescale data to fit into minimisation routine (same magnitude for EEG and MEG means same threshold and exit criteria) -y = y*sc_y; - - - - - - -Y.y=y; -U.u=1; - - outsideflag=1; - while outsideflag==1, %% don't use sources which end up outside the head - - - [u,s,v] = svd(S_w0); -%% set random moment, scaled by prior variances - mu_w = mu_w0 + u*diag(sqrt(diag(s+eps)))*v'*randn(size(mu_w0)); %% source units - - [u,s,v] = svd(S_s0); %% - %% a random guess for the location, based on variance of the prior - - outside=1; - while (outside), - outside=0; - mu_s = mu_s0 + u*diag(sqrt(diag(s+eps)))*v'*randn(size(mu_s0)); % +S_w0 = P.priors.S_w0; +S_s0 = P.priors.S_s0; + +% subtracting mean level from eeg data +%-------------------------------------------------------------------------- +if strcmp(upper(P.modality),'EEG') + P.y = P.y-mean(P.y); +end + +% rescale data to fit into minimisation routine (same magnitude for EEG and +% MEG means same threshold and exit criteria) +%-------------------------------------------------------------------------- + +y = P.y; +sc_y = 1/std(y); +y = y*sc_y; +Y.y = y; +U.u = 1; + +outsideflag=1; +while outsideflag==1, %% don't use sources which end up outside the head + + % set random moment, scaled by prior variances + %---------------------------------------------------------------------- + [u,s,v] = svd(S_w0); + mu_w = mu_w0 + u*diag(sqrt(diag(s+eps)))*v'*randn(size(mu_w0)); + + % a random guess for the location, based on variance of the prior + %---------------------------------------------------------------------- + [u,s,v] = svd(S_s0); + outside = 1; + while(outside) + outside = 0; + mu_s = mu_s0 + u*diag(sqrt(diag(s+eps)))*v'*randn(size(mu_s0)); % for i=1:3:length(mu_s), %% check each dipole is inside the head - pos=mu_s(i:i+2); - outside = outside+ ~forwinv_inside_vol(pos',P.forward.vol); - end; + pos = mu_s(i:i+2); + outside = outside+ ~ft_inside_vol(pos',P.forward.vol); + end; end; - - -% get lead fields - - - M.pE = [mu_s;mu_w]; %% prior parameter estimate - M.pC = blkdiag(S_s0,S_w0); % %% prior covariance estimate - M.IS='spm_eeg_wrap_dipfit_vbecd'; + % get lead fields + %---------------------------------------------------------------------- + M.pE = [mu_s;mu_w]; % prior parameter estimate + + + + M.pC = blkdiag(S_s0,S_w0); % prior covariance estimate + M.hE=P.priors.hE; + + M.hC=P.priors.hC; + + + M.IS = 'spm_eeg_wrap_dipfit_vbecd'; startguess=M.pE; - M.Setup=P; %% pass volume conductor and sensor locations on - M.sc_y=sc_y; %% pass on scaling factor - + M.Setup =P; % pass volume conductor and sensor locations on + M.sc_y =sc_y; % pass on scaling factor + + %% startguess=[-0.3553 -69.8440 1.0484 0.2545 0.3428 1.8526]' + [starty]=spm_eeg_wrap_dipfit_vbecd(startguess,M,U); - [Ep,Cp,S,F] = spm_nlsi_GN(M,U,Y); - P.Ep=Ep; - P.Cp=Cp; - P.S=S; - P.F=F; - [P.ypost,outsideflag]=spm_eeg_wrap_dipfit_vbecd(P.Ep,M,U); - P.ypost=P.ypost./sc_y; %% scale it back + [Ep,Cp,S,F] = spm_nlsi_GN(M,U,Y); + P.Ep = Ep; + P.Cp = Cp; + P.S = S; + P.F = F; + [P.ypost,outsideflag]=spm_eeg_wrap_dipfit_vbecd(P.Ep,M,U); + P.ypost = P.ypost./sc_y; %% scale it back + if outsideflag disp('running again, one or more dipoles outside head.'); - end; - - end; % while -P.post_mu_s=Ep(1:length(mu_s)); -P.post_mu_w=Ep(length(mu_s)+1:end); -P.post_S_s=Cp(1:length(mu_s),1:length(mu_s)); -P.post_S_w=Cp(length(mu_s)+1:end,length(mu_s)+1:end); + end; + +end; % while +P.post_mu_s = Ep(1:length(mu_s)); +P.post_mu_w = Ep(length(mu_s)+1:end); +P.post_S_s = Cp(1:length(mu_s),1:length(mu_s)); +P.post_S_w = Cp(length(mu_s)+1:end,length(mu_s)+1:end); diff --git a/spm_eeg_inv_vbecd_disp.m b/spm_eeg_inv_vbecd_disp.m index a78d645..d7f0e4c 100644 --- a/spm_eeg_inv_vbecd_disp.m +++ b/spm_eeg_inv_vbecd_disp.m @@ -12,15 +12,13 @@ function spm_eeg_inv_vbecd_disp(action,varargin) % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Christophe Phillips -% $Id: spm_eeg_inv_vbecd_disp.m 2921 2009-03-23 17:59:50Z guillaume $ +% $Id: spm_eeg_inv_vbecd_disp.m 3951 2010-06-28 15:09:36Z gareth $ % Note: % unfortunately I cannot see how to ensure that when zooming in the image % the dipole location stays in place... global st -% global defaults -% sw = warning('off'); Fig = spm_figure('GetWin','Graphics'); colors = {'y','b','g','r','c','m'}; % 6 possible colors @@ -74,7 +72,9 @@ function spm_eeg_inv_vbecd_disp(action,varargin) end try + error('crap'); Pimg = spm_vol(D.inv{ind}.mesh.sMRI); + catch Pimg = spm_vol(fullfile(spm('dir'), 'canonical', 'single_subj_T1.nii')); end @@ -219,11 +219,11 @@ function spm_eeg_inv_vbecd_disp(action,varargin) % Display business %-------------------------------------------------------------------------- -loc_mm = sdip.loc{i_seed(1)}(:,i_dip); +loc_mm = sdip.mniloc{i_seed(1)}(:,i_dip); if length(i_seed)>1 % unit = ones(1,sdip.n_dip); for ii = i_seed(2:end) - loc_mm = loc_mm + sdip.loc{ii}(:,i_dip); + loc_mm = loc_mm + sdip.mniloc{ii}(:,i_dip); end loc_mm = loc_mm/length(i_seed); end @@ -247,7 +247,7 @@ function spm_eeg_inv_vbecd_disp(action,varargin) l3 = -2:0; for ii = 1:length(i_seed) for jj = 1:sdip.n_dip - Mn_j = max([Mn_j sqrt(sum(sdip.j{ii}(jj*3+l3,sdip.Mtb).^2))]); + Mn_j = max([Mn_j sqrt(sum(sdip.jmni{ii}(jj*3+l3,sdip.Mtb).^2))]); end end st.vols{1}.sdip.tabl_seed_dip = tabl_seed_dip; @@ -276,8 +276,8 @@ function spm_eeg_inv_vbecd_disp(action,varargin) ic = mod(ind-1,Ncolors)+1; im = fix(ind/Ncolors)+1; - loc_pl = sdip.loc{tabl_seed_dip(ii,1)}(:,tabl_seed_dip(ii,2)); - js = sdip.j{tabl_seed_dip(ii,1)}(tabl_seed_dip(ii,2)*3+l3,sdip.Mtb); + loc_pl = sdip.mniloc{tabl_seed_dip(ii,1)}(:,tabl_seed_dip(ii,2)); + js = sdip.jmni{tabl_seed_dip(ii,1)}(tabl_seed_dip(ii,2)*3+l3,sdip.Mtb); vloc = sdip.cov_loc{tabl_seed_dip(ii,1)}(tabl_seed_dip(ii,2)*3+l3,tabl_seed_dip(ii,2)*3+l3); dip_h(:,ii) = add1dip(loc_pl,js/Mn_j*20,vloc, ... marker{im},colors{ic},st.vols{1}.ax,Fig,st.bb); @@ -294,8 +294,8 @@ function spm_eeg_inv_vbecd_disp(action,varargin) for jj=1:sdip.n_dip im = mod(jj-1,Nmarker)+1; - loc_pl = sdip.loc{tabl_seed_dip(ii,1)}(:,jj); - js = sdip.j{tabl_seed_dip(ii,1)}(jj*3+l3,sdip.Mtb); + loc_pl = sdip.mniloc{tabl_seed_dip(ii,1)}(:,jj); + js = sdip.jmni{tabl_seed_dip(ii,1)}(jj*3+l3,sdip.Mtb); vloc = sdip.cov_loc{tabl_seed_dip(ii,1)}(jj*3+l3,jj*3+l3); js_m = js_m+js; dip_h(:,ii+(jj-1)*pi_dip(1)) = ... diff --git a/spm_eeg_inv_vbecd_getLF.m b/spm_eeg_inv_vbecd_getLF.m index df300d0..5c7fda1 100644 --- a/spm_eeg_inv_vbecd_getLF.m +++ b/spm_eeg_inv_vbecd_getLF.m @@ -18,7 +18,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Christophe Phillips & Stefan Kiebel -% $Id: spm_eeg_inv_vbecd_getLF.m 3222 2009-06-25 14:09:48Z gareth $ +% $Id: spm_eeg_inv_vbecd_getLF.m 3833 2010-04-22 14:49:48Z vladimir $ %%% now does rank reduction (to 2) for non eeg data @@ -35,11 +35,11 @@ % mean correction of LF, only for EEG data. - if forwinv_senstype(sens, 'eeg') - [tmp] = forwinv_compute_leadfield(s(1+(i-1)*3:i*3)', sens, vol); + if ft_senstype(sens, 'eeg') + [tmp] = ft_compute_leadfield(s(1+(i-1)*3:i*3)', sens, vol); tmp = tmp - repmat(mean(tmp), size(tmp,1), 1); else %% reduce rank of leadfield for MEG- assume one direction (radial) is silent - [tmp] = forwinv_compute_leadfield(s(1+(i-1)*3:i*3)', sens, vol,'reducerank',MEGRANK); + [tmp] = ft_compute_leadfield(s(1+(i-1)*3:i*3)', sens, vol,'reducerank',MEGRANK); tmp=tmp.*MEGSCALE; end gm = [gm tmp]; @@ -66,11 +66,11 @@ if ceil(j/3) == i % mean correction of LF, only for EEG data. - if forwinv_senstype(sens, 'eeg') - [tmp] = forwinv_compute_leadfield(ds(1+(i-1)*3:i*3)', sens, vol); + if ft_senstype(sens, 'eeg') + [tmp] = ft_compute_leadfield(ds(1+(i-1)*3:i*3)', sens, vol); tmp = tmp - repmat(mean(tmp), size(tmp,1), 1); else % MEG - [tmp] = forwinv_compute_leadfield(ds(1+(i-1)*3:i*3)', sens, vol,'reducerank',MEGRANK); + [tmp] = ft_compute_leadfield(ds(1+(i-1)*3:i*3)', sens, vol,'reducerank',MEGRANK); tmp=tmp.*MEGSCALE; end dtmp = [dtmp tmp]; diff --git a/spm_eeg_inv_vbecd_gui.m b/spm_eeg_inv_vbecd_gui.m index 2278286..8628c8e 100644 --- a/spm_eeg_inv_vbecd_gui.m +++ b/spm_eeg_inv_vbecd_gui.m @@ -7,7 +7,7 @@ %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % -% $Id: spm_eeg_inv_vbecd_gui.m 3492 2009-10-21 13:52:31Z gareth $ +% $Id: spm_eeg_inv_vbecd_gui.m 3951 2010-06-28 15:09:36Z gareth $ %% % Load data, if necessary @@ -82,7 +82,7 @@ if strncmp(P.modality, D.inv{val}.forward(m).modality, 3) P.forward.vol = D.inv{val}.forward(m).vol; if ischar(P.forward.vol) - P.forward.vol = fileio_read_vol(P.forward.vol); + P.forward.vol = ft_read_vol(P.forward.vol); end P.forward.sens = D.inv{val}.datareg(m).sensors; % Channels to use @@ -90,15 +90,16 @@ M1 = D.inv{val}.datareg.toMNI; - if ~isequal(P.modality,'EEG') - [U, L, V] = svd(M1(1:3, 1:3)); - M1(1:3,1:3) =U*V'; - end - % disp('Undoing transformation to Tal space !'); - % M1=eye(4) - - P.forward.sens = forwinv_transform_sens(M1, P.forward.sens); - P.forward.vol = forwinv_transform_vol(M1, P.forward.vol); + + [U, L, V] = svd(M1(1:3, 1:3)); + orM1(1:3,1:3) =U*V'; %% for switching orientation between meg and mni space + + % disp('Undoing transformation to Tal space !'); + + %disp('Fixing sphere centre !'); + %P.forward.vol.o=[0 0 28]; P.forward.vol.r=100; + mnivol = ft_transform_vol(M1, P.forward.vol); %% used for inside head calculation + end end @@ -111,7 +112,7 @@ end -[P.forward.vol, P.forward.sens] = forwinv_prepare_vol_sens( ... +[P.forward.vol, P.forward.sens] = ft_prepare_vol_sens( ... P.forward.vol, P.forward.sens, 'channel', P.channels); if ~isfield(P.forward.sens,'prj') @@ -253,10 +254,15 @@ % informative location prior str = 'Location prior'; while 1 - s0 = spm_input(str, 1+tr_q+dip_q+2,'e',[0 0 0])'; - outside = ~forwinv_inside_vol(s0',P.forward.vol); + s0mni = spm_input(str, 1+tr_q+dip_q+2,'e',[0 0 0])'; + + outside = ~ft_inside_vol(s0mni',mnivol); + s0=D.inv{val}.datareg.fromMNI*[s0mni' 1]'; + s0=s0(1:3); + str2='Prior location variance (mm2)'; - diags_s0 = spm_input(str2, 1+tr_q+dip_q+2,'e',priorlocvardefault)'; + diags_s0_mni = spm_input(str2, 1+tr_q+dip_q+2,'e',priorlocvardefault)'; + diags_s0=(orM1*sqrt(diags_s0_mni)).^2; if all(~outside), break, end str = 'Prior location must be inside head'; @@ -275,11 +281,12 @@ 'Informative|Non-info',[1,0],2); if wpr_q % informative moment prior - w0= spm_input('Moment prior', ... + w0_mni= spm_input('Moment prior', ... 1+tr_q+dip_q+spr_q+3,'e',[0 0 0])'; str2='Prior moment variance (nAm2)'; - diags_w0 = spm_input(str2, 1+tr_q+dip_q+2,'e',priormomvardefault)'; - dip_pr(dip_q).mu_w0 =w0; + diags_w0_mni = spm_input(str2, 1+tr_q+dip_q+2,'e',priormomvardefault)'; + dip_pr(dip_q).mu_w0 =orM1*w0_mni; + diags_w0=(orM1*sqrt(diags_w0_mni)).^2; else % no location prior @@ -302,37 +309,46 @@ 'Informative|Non-info',[1,0],2); if spr_q % informative location prior - str = 'Location prior (right only)'; + str = 'Location prior (one side only)'; while 1 - tmp_s0 = spm_input(str, 1+tr_q+dip_q+2,'e',[0 0 0])'; + s0mni = spm_input(str, 1+tr_q+dip_q+2,'e',[0 0 0])'; + syms0mni=s0mni; + syms0mni(1)=-syms0mni(1); + outside = ~ft_inside_vol(s0mni',mnivol); + s0=D.inv{val}.datareg.fromMNI*[s0mni' 1]'; + + s0sym=D.inv{val}.datareg.fromMNI*[syms0mni' 1]'; + + str2='Prior location variance (mm2)'; - tmp_diags_s0 = spm_input(str2, 1+tr_q+dip_q+2,'e',priorlocvardefault)'; + tmp_diags_s0_mni = spm_input(str2, 1+tr_q+dip_q+2,'e',priorlocvardefault)'; + tmp_diags_s0_mni= [tmp_diags_s0_mni ; tmp_diags_s0_mni ]; - outside = ~forwinv_inside_vol(tmp_s0',P.forward.vol); if all(~outside), break, end - str = 'Prior location must be inside head'; - end - tmp_s0 = [tmp_s0 ; tmp_s0] ; tmp_s0(4) = -tmp_s0(4); - tmp_diags_s0 = [tmp_diags_s0 ; tmp_diags_s0] ; + str = 'Prior location must be inside head'; + end - dip_pr(dip_q).mu_s0 = tmp_s0 ; - - else + dip_pr(dip_q).mu_s0 = [s0(1:3);s0sym(1:3)]; + else % no location prior dip_pr(dip_q).mu_s0 = zeros(6,1); tmp_diags_s0 = [nopriorlocvardefault';nopriorlocvardefault']; end %% end of if informative prior %% setting up a covariance matrix where there is covariance between %% the x parameters negatively coupled, y,z positively. - dip_pr(dip_q).S_s0 = eye(length(tmp_diags_s0)).*repmat(tmp_diags_s0,1,length(tmp_diags_s0)); - dip_pr(dip_q).S_s0(4,1)=-dip_pr(dip_q).S_s0(4,4); % reflect in x - dip_pr(dip_q).S_s0(5,2)=dip_pr(dip_q).S_s0(5,5); % maintain y and z - dip_pr(dip_q).S_s0(6,3)=dip_pr(dip_q).S_s0(6,6); + mni_dip_pr(dip_q).S_s0 = eye(length(tmp_diags_s0_mni)).*repmat(tmp_diags_s0_mni,1,length(tmp_diags_s0_mni)); + mni_dip_pr(dip_q).S_s0(4,1)=-mni_dip_pr(dip_q).S_s0(4,4); % reflect in x + mni_dip_pr(dip_q).S_s0(5,2)=mni_dip_pr(dip_q).S_s0(5,5); % maintain y and z + mni_dip_pr(dip_q).S_s0(6,3)=mni_dip_pr(dip_q).S_s0(6,6); + + mni_dip_pr(dip_q).S_s0(1,4)=mni_dip_pr(dip_q).S_s0(4,1); + mni_dip_pr(dip_q).S_s0(2,5)=mni_dip_pr(dip_q).S_s0(5,2); + mni_dip_pr(dip_q).S_s0(3,6)=mni_dip_pr(dip_q).S_s0(6,3); + %% transform to MEG space + + dip_pr(dip_q).S_s0(:,1:3)=mni_dip_pr(dip_q).S_s0(:,1:3)*orM1; %% NEED TO LOOK AT THIS + dip_pr(dip_q).S_s0(:,4:6)=mni_dip_pr(dip_q).S_s0(:,4:6)*orM1; - dip_pr(dip_q).S_s0(1,4)=dip_pr(dip_q).S_s0(4,1); - dip_pr(dip_q).S_s0(2,5)=dip_pr(dip_q).S_s0(5,2); - dip_pr(dip_q).S_s0(3,6)=dip_pr(dip_q).S_s0(6,3); - % Moment prior wpr_q = spm_input('Moment prior ?',1+tr_q+dip_q+spr_q+2,'b', ... 'Informative|Non-info',[1,0],2); @@ -354,22 +370,29 @@ end %dip_pr(dip_q).S_w0=eye(length(diags_w0)).*repmat(diags_w0,1,length(diags_w0)); %% couple all orientations, except x, positively or leave for now... - dip_pr(dip_q).S_w0 = eye(length(tmp_diags_w0)).*repmat(tmp_diags_w0,1,length(tmp_diags_w0)); - dip_pr(dip_q).S_w0(4,1)=-dip_pr(dip_q).S_w0(4,4); % - dip_pr(dip_q).S_w0(5,2)=dip_pr(dip_q).S_w0(5,5); % - dip_pr(dip_q).S_w0(6,3)=dip_pr(dip_q).S_w0(6,6); % - dip_pr(dip_q).S_w0(1,4)=-dip_pr(dip_q).S_w0(4,1); % - dip_pr(dip_q).S_w0(2,5)=dip_pr(dip_q).S_w0(5,2); % - dip_pr(dip_q).S_w0(3,6)=dip_pr(dip_q).S_w0(6,3); % - + mni_dip_pr(dip_q).S_w0 = eye(length(tmp_diags_w0)).*repmat(tmp_diags_w0,1,length(tmp_diags_w0)); + mni_dip_pr(dip_q).S_w0(4,1)=-mni_dip_pr(dip_q).S_w0(4,4); % + mni_dip_pr(dip_q).S_w0(5,2)=mni_dip_pr(dip_q).S_w0(5,5); % + mni_dip_pr(dip_q).S_w0(6,3)=mni_dip_pr(dip_q).S_w0(6,6); % + mni_dip_pr(dip_q).S_w0(1,4)=-mni_dip_pr(dip_q).S_w0(4,1); % + mni_dip_pr(dip_q).S_w0(2,5)=mni_dip_pr(dip_q).S_w0(5,2); % + mni_dip_pr(dip_q).S_w0(3,6)=mni_dip_pr(dip_q).S_w0(6,3); % + dip_pr(dip_q).S_w0(:,1:3)=mni_dip_pr(dip_q).S_w0(:,1:3)*orM1; + dip_pr(dip_q).S_w0(:,4:6)=mni_dip_pr(dip_q).S_w0(:,4:6)*orM1; + dip_c = dip_c+2; end end - str2='Number of iterations'; - Niter = spm_input(str2, 1+tr_q+dip_q+2+1,'e',10)'; +str2='Data SNR (amp)'; + SNRamp = spm_input(str2, 1+tr_q+dip_q+2+1,'e',5)'; + hE=log(SNRamp^2); %% expected log precision of data + hC=0.0000001; % Have to tie the expected precision down for the moment (nlsi_gn can become unstable) + +str2='Number of iterations'; + Niter = spm_input(str2, 1+tr_q+dip_q+2+2,'e',10)'; %% % Get all the priors together and build structure to pass to inv_becd @@ -378,7 +401,7 @@ priors = struct('mu_w0',cat(1,dip_pr(:).mu_w0), ... 'mu_s0',cat(1,dip_pr(:).mu_s0), ... - 'S_w0',blkdiag(dip_pr(:).S_w0),'S_s0',blkdiag(dip_pr(:).S_s0)); + 'S_w0',blkdiag(dip_pr(:).S_w0),'S_s0',blkdiag(dip_pr(:).S_s0),'hE',hE,'hC',hC); P.priors = priors; @@ -414,7 +437,7 @@ P.handles.SPMdefaults.col = get(P.handles.hfig,'colormap'); P.handles.SPMdefaults.renderer = get(P.handles.hfig,'renderer'); set(P.handles.hfig,'userdata',P) - + dip_amp=[]; for j=1:Niter, Pout(j) = spm_eeg_inv_vbecd(P); close(gcf); @@ -424,8 +447,15 @@ dip_mom=reshape(Pout(j).post_mu_w,3,length(Pout(j).post_mu_w)/3); dip_amp(j,:)=sqrt(dot(dip_mom,dip_mom)); % display - displayVBupdate2(Pout(j).y,pov,allF,Niter,dip_amp,Pout(j).post_mu_w,Pout(j).post_mu_s,Pout(j).post_S_s,Pout(j).post_S_w,P,j,[],Pout(j).F,Pout(j).ypost,[]); - + megloc=reshape(Pout(j).post_mu_s,3,length(Pout(j).post_mu_s)/3); % loc of dip (3 x n_dip) + mniloc=D.inv{val}.datareg.toMNI*[megloc;ones(1,size(megloc,2))]; %% actual MNI location (with scaling) + megmom=reshape(Pout(j).post_mu_w,3,length(Pout(j).post_mu_w)/3); % moments of dip (3 x n_dip) + megposvar=reshape(diag(Pout(j).post_S_s),3,length(Pout(j).post_mu_s)/3); %% estimate of positional uncertainty in three principal axes + mnimom=orM1*megmom; %% convert moments into mni coordinates through a rotation (no scaling or translation) + mniposvar=(orM1*sqrt(megposvar)).^2; %% convert pos variance into approx mni space by switching axes + + displayVBupdate2(Pout(j).y,pov,allF,Niter,dip_amp,mnimom,mniloc(1:3,:),mniposvar,P,j,[],Pout(j).F,Pout(j).ypost,[]); + end; % for j allF=[Pout.F]; [maxFvals,maxind]=max(allF); @@ -435,8 +465,17 @@ % Get the results out. inverse.pst = tb*1e3; inverse.F(ii) = P.F; % free energy - inverse.loc{ii} = reshape(P.post_mu_s,3,length(P.post_mu_s)/3); % loc of dip (3 x n_dip) - inverse.j{ii} = P.post_mu_w; % dipole(s) orient/ampl, in 1 column + + megloc=reshape(P.post_mu_s,3,length(P.post_mu_s)/3); % loc of dip (3 x n_dip) + mniloc=D.inv{val}.datareg.toMNI*[megloc;ones(1,size(megloc,2))]; %% actual MNI location (with scaling) + inverse.mniloc{ii}=mniloc(1:3,:); + inverse.loc{ii} = megloc; + + + + + inverse.j{ii} = P.post_mu_w; % dipole(s) orient/ampl, in 1 column in meg space + inverse.jmni{ii} = orM1*P.post_mu_w; % dipole(s) orient/ampl in mni space inverse.cov_loc{ii} = P.post_S_s; % cov matrix of source location inverse.cov_j{ii} = P.post_S_w; % cov matrix of source orient/ampl inverse.exitflag(ii) = 1; % Converged (1) or not (0) @@ -446,9 +485,19 @@ spm_clf(P.handles.hfig) - displayVBupdate2(Pout(maxind).y,pov,allF,Niter,dip_amp,Pout(maxind).post_mu_w,Pout(maxind).post_mu_s,Pout(maxind).post_S_s,Pout(maxind).post_S_w,P,j,[],Pout(maxind).F,Pout(maxind).ypost,maxind); + + megmom=reshape(Pout(maxind).post_mu_w,3,length(Pout(maxind).post_mu_w)/3); % moments of dip (3 x n_dip) + megposvar=reshape(diag(Pout(maxind).post_S_s),3,length(Pout(maxind).post_mu_s)/3); %% estimate of positional uncertainty in three principal axes + mnimom=orM1*megmom; %% convert moments into mni coordinates through a rotation (no scaling or translation) + mniposvar=(orM1*sqrt(megposvar)).^2; %% convert pos variance into approx mni space by switching axes + + + displayVBupdate2(Pout(j).y,pov,allF,Niter,dip_amp,mnimom,mniloc(1:3,:),mniposvar,P,j,[],Pout(j).F,Pout(j).ypost,maxind); + + %displayVBupdate2(Pout(maxind).y,pov,allF,Niter,dip_amp,mniloc,Pout(maxind).post_mu_s,Pout(maxind).post_S_s,P,j,[],Pout(maxind).F,Pout(maxind).ypost,maxind,D); % end + D.inv{val}.inverse = inverse; %% @@ -463,7 +512,8 @@ -function [P] = displayVBupdate2(y,pov_iter,F_iter,maxit,dipamp_iter,mu_w,mu_s,S_s,S_w,P,it,flag,F,yHat,maxind) +function [P] = displayVBupdate2(y,pov_iter,F_iter,maxit,dipamp_iter,mu_w,mu_s,diagS_s,P,it,flag,F,yHat,maxind) + %% yHat is estimate of y based on dipole position if ~exist('flag','var') @@ -495,12 +545,18 @@ end w = reshape(mu_w,3,[]); s = reshape(mu_s, 3, []); - [out] = spm_eeg_displayECD(... - s,w,reshape(diag(S_s),3,[]),[],opt); +% mesh.faces=D.inv{D.val}.forward.mesh.face; %% in ctf space +% mesh.vertices=D.inv{D.val}.forward.mesh.vert; %% in ctf space +% [out] = spm_eeg_displayECD_ctf(... +% s,w,reshape(diag(S_s),3,[]),[],mesh,opt); + [out] = spm_eeg_displayECD(... + s,w,diagS_s,[],opt); + P.handles.hp = out.handles.hp; P.handles.hq = out.handles.hq; P.handles.hs = out.handles.hs; P.handles.ht = out.handles.ht; + end % plot data and predicted data diff --git a/spm_eeg_inv_visu3D_api.m b/spm_eeg_inv_visu3D_api.m index e8ea1e1..31c152b 100644 --- a/spm_eeg_inv_visu3D_api.m +++ b/spm_eeg_inv_visu3D_api.m @@ -10,12 +10,12 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Jeremie Mattout -% $Id: spm_eeg_inv_visu3D_api.m 3558 2009-11-11 20:23:05Z karl $ +% $Id: spm_eeg_inv_visu3D_api.m 4004 2010-07-20 15:45:39Z vladimir $ % INITIALISATION CODE %-------------------------------------------------------------------------- if nargin == 0 || nargin == 1 % LAUNCH GUI - + % open new api %---------------------------------------------------------------------- @@ -29,11 +29,11 @@ % load D if possible and try to open %---------------------------------------------------------------------- try - handles.D = spm_eeg_inv_check(varargin{1}); - set(handles.DataFile,'String',handles.D.fname) - spm_eeg_inv_visu3D_api_OpeningFcn(fig, [], handles) + handles.D = spm_eeg_inv_check(varargin{1}); + set(handles.DataFile,'String',handles.D.fname) + spm_eeg_inv_visu3D_api_OpeningFcn(fig, [], handles) end - + % return figure handle if necessary %---------------------------------------------------------------------- if nargout > 0 @@ -41,7 +41,7 @@ end elseif ischar(varargin{1}) - + try if (nargout) [varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard @@ -49,7 +49,7 @@ feval(varargin{:}); % FEVAL switchyard end catch - disp(lasterr); + disp(lasterror); end end @@ -129,18 +129,18 @@ function spm_eeg_inv_visu3D_api_OpeningFcn(hObject, eventdata, handles) handles.pst = D.inv{val}.inverse.pst(Ts); handles.srcs_data = J; handles.Nmax = max(abs(J(:))); - + % sensor data %---------------------------------------------------------------------- A = pinv(full(spm_cat(spm_diag(U)))); handles.sens_data = A*Y*T(Ts,:)'; handles.pred_data = A*L*J(Is,:); - + catch warndlg({'Please invert your model';'inverse solution not valid'}); return end - + % case 'windowed response' or contrast' %-------------------------------------------------------------------------- try @@ -288,7 +288,7 @@ function UpDate_Display_SRCS(hObject,handles) % case 1: response (J) %------------------------------------------------------------------ case 1 - TS = fix(get(handles.slider_time,'Value')); + TS = fix(get(handles.slider_time,'Value')); if A srcs_disp = abs(handles.srcs_data(:,TS)); else @@ -306,28 +306,28 @@ function UpDate_Display_SRCS(hObject,handles) handles.Vmin = min(srcs_disp); handles.Vmax = max(srcs_disp); end - - % case 2: Windowed response (JW) - %------------------------------------------------------------------ + + % case 2: Windowed response (JW) + %------------------------------------------------------------------ case 2 - handles.Vmin = min(handles.srcs_data_w); - handles.Vmax = max(handles.srcs_data_w); - srcs_disp = handles.srcs_data_w; - - % case 3: Evoked power (JWWJ) - %------------------------------------------------------------------ + handles.Vmin = min(handles.srcs_data_w); + handles.Vmax = max(handles.srcs_data_w); + srcs_disp = handles.srcs_data_w; + + % case 3: Evoked power (JWWJ) + %------------------------------------------------------------------ case 3 - handles.Vmin = min(handles.srcs_data_ev); - handles.Vmax = max(handles.srcs_data_ev); - srcs_disp = handles.srcs_data_ev; - - % case 4: Induced power (JWWJ) - %------------------------------------------------------------------ + handles.Vmin = min(handles.srcs_data_ev); + handles.Vmax = max(handles.srcs_data_ev); + srcs_disp = handles.srcs_data_ev; + + % case 4: Induced power (JWWJ) + %------------------------------------------------------------------ case 4 - handles.Vmin = min(handles.srcs_data_ind); - handles.Vmax = max(handles.srcs_data_ind); - srcs_disp = handles.srcs_data_ind; + handles.Vmin = min(handles.srcs_data_ind); + handles.Vmax = max(handles.srcs_data_ind); + srcs_disp = handles.srcs_data_ind; end set(handles.fig1,'FaceVertexCData',full(srcs_disp)); set(handles.sources_axes,'CLim',[handles.Vmin handles.Vmax]); @@ -352,34 +352,34 @@ function UpDate_Display_SENS(hObject,handles) % topography %-------------------------------------------------------------------------- if TypOfDisp == 1 - + % responses at one pst %---------------------------------------------------------------------- if ActToDisp == 1 - + TS = fix(get(handles.slider_time,'Value')); sens_disp = handles.sens_data(ic,TS); pred_disp = handles.pred_data(ic,TS); - % contrast - %---------------------------------------------------------------------- + % contrast + %---------------------------------------------------------------------- elseif ActToDisp == 2 sens_disp = handles.sens_data_w; pred_disp = handles.pred_data_w; - - % power - %---------------------------------------------------------------------- + + % power + %---------------------------------------------------------------------- elseif ActToDisp == 3 sens_disp = handles.sens_data_ev; pred_disp = handles.pred_data_ev; end - + axes(handles.sensors_axes); disp = griddata(handles.sens_coord(:,1),handles.sens_coord(:,2),full(sens_disp),handles.sens_coord2D_X,handles.sens_coord2D_Y); imagesc(handles.sens_coord_x,handles.sens_coord_y,disp); axis image xy off - + % add sensor locations %---------------------------------------------------------------------- try, delete(handles.sensor_loc); end @@ -387,16 +387,16 @@ function UpDate_Display_SENS(hObject,handles) handles.sensor_loc = plot(handles.sensors_axes,... handles.sens_coord(:,1),handles.sens_coord(:,2),'o','MarkerFaceColor',[1 1 1]/2,'MarkerSize',6); hold(handles.sensors_axes, 'off'); - + axes(handles.pred_axes); disp = griddata(handles.sens_coord(:,1),handles.sens_coord(:,2),full(pred_disp),handles.sens_coord2D_X,handles.sens_coord2D_Y); imagesc(handles.sens_coord_x,handles.sens_coord_y,disp); axis image xy off; - + checkbox_sensloc_Callback(hObject, [], handles); -% time series -%-------------------------------------------------------------------------- + % time series + %-------------------------------------------------------------------------- elseif TypOfDisp == 2 axes(handles.sensors_axes) daspect('auto') @@ -612,7 +612,7 @@ function movie_sens_Callback(hObject, eventdata, handles) filename = fullfile(handles.D.path,'SensorMovie'); movie2avi(M,filename,'compression','Indeo3','FPS',24) end - + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % TYPE OF SENSOR LEVEL DISPLAY %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -675,10 +675,10 @@ function Set_colormap(hObject, eventdata, handles) i = [ones(Low,1); [1:Hig]'*N/Hig]; NewMap = NewMap(fix(i),:); -% signed values -%-------------------------------------------------------------------------- + % signed values + %-------------------------------------------------------------------------- else - + UpTh = get(handles.slider_srcs_up, 'Value'); DoTh = 1 - get(handles.slider_srcs_down,'Value'); N = length(NewMap)/2; @@ -686,7 +686,7 @@ function Set_colormap(hObject, eventdata, handles) Hig = fix(N - N*UpTh); i = [[1:Low]'*N/Low; ones(N + N - Hig - Low,1)*N; [1:Hig]'*N/Hig + N]; NewMap = NewMap(fix(i),:); - + end colormap(NewMap); drawnow @@ -722,25 +722,20 @@ function con_Callback(hObject, eventdata, handles) set(handles.con,'String',sprintf('condition %d',handles.D.con),'Value',0); spm_eeg_inv_visu3D_api_OpeningFcn(hObject, eventdata, handles) - + % --- Executes on button press in VDE. %-------------------------------------------------------------------------- function Velec_Callback(hObject, eventdata, handles) axes(handles.sources_axes); try vde = getCursorInfo(handles.location); + spm_eeg_invert_display(handles.D,vde.Position) + datacursormode(handles.fig, 'off'); catch vde = []; + handles.location = datacursormode(handles.fig, 'on'); + set(handles.location,'Enable','on','DisplayStyle','datatip','SnapToDataVertex','on', 'UpdateFcn', {@CursorUpdate_Callback, handles}); end -if isempty(vde) - handles.location = datacursormode(handles.fig); - set(handles.location,'Enable','on','DisplayStyle','datatip','SnapToDataVertex','on'); - waitforbuttonpress - datacursormode off -end -vde = getCursorInfo(handles.location); -spm_eeg_invert_display(handles.D,vde.Position) -guidata(hObject,handles); % --- Executes on button press in Rot. @@ -749,3 +744,8 @@ function Rot_Callback(hObject, eventdata, handles) rotate3d(handles.sources_axes) return + +function text = CursorUpdate_Callback(hObject, eventdata, handles) +pos = get(eventdata,'Position'); +text = num2str(pos); +spm_eeg_invert_display(handles.D, get(eventdata, 'Position')); diff --git a/spm_eeg_invert.m b/spm_eeg_invert.m index f986016..3f3171a 100644 --- a/spm_eeg_invert.m +++ b/spm_eeg_invert.m @@ -30,10 +30,11 @@ % inverse.sdv - standard deviations of Gaussian temporal correlation % inverse.pQ - any source priors (eg from fMRI); vector or matrix % inverse.Qe - any sensor error components (eg empty-room data) +% inverse.dplot - make diagnostocs plots (0 or 1) % % Evaluates: % -% inverse.M - MAP projector (reduced) +% inverse.M - MAP projector (reduced) % inverse.J{i} - Conditional expectation (i conditions) J = M*U*Y % inverse.L - Lead field (reduced UL := U*L) % inverse.qC - spatial covariance @@ -72,7 +73,7 @@ % = L(1}*J{i} % % Potential scaling differences between the lead-fields are handled by -% scaling L{1} such that trace(L{1}*L{1}') = constant (number of spatial +% scaling L{1} such that trace(L{1}*L{1}') = constant (number of spatial % modes or channels), while scaling the data such that trace(AY{n}*AY{n}') = % constant over subjects (and modalities; see below). % @@ -101,7 +102,7 @@ %__________________________________________________________________________ % % 3. It also allows incorporation of spatial source priors, eg, from fMRI -% (see spm_eeg_inv_fmripriors.m). Note that if a vector is passed in +% (see spm_eeg_inv_fmripriors.m). Note that if a vector is passed in % inverse.pQ, then variance components used (pass a matrix if a covariance % component is desired). % @@ -117,16 +118,16 @@ % 2. Re-inversion of each subject, fusing across all modalities %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging - + % Karl Friston -% $Id: spm_eeg_invert.m 3635 2009-12-11 12:56:18Z guillaume $ - -% check whether this is a group inversion +% $Id: spm_eeg_invert.m 3983 2010-07-09 13:56:01Z vladimir $ + +% check whether this is a group inversion for (Nl) number of subjects %-------------------------------------------------------------------------- if ~iscell(D), D = {D}; end -Nl = length(D); % number of subjects - - +Nl = length(D); + + % D - SPM data structure %========================================================================== if nargin > 1 @@ -138,26 +139,25 @@ D{i}.val = D{1}.val; end -inverse = D{1}.inv{D{1}.val}.inverse; - +inverse = D{1}.inv{D{1}.val}.inverse; + % defaults %-------------------------------------------------------------------------- -try, type = inverse.type; catch, type = 'GS'; end -try, s = inverse.smooth; catch, s = 0.6; end -try, Np = inverse.Np; catch, Np = 256; end -try, Nm = inverse.Nm; catch, Nm = 128; end -try, Nr = inverse.Nr; catch, Nr = 16; end -try, xyz = inverse.xyz; catch, xyz = [0 0 0]; end -try, rad = inverse.rad; catch, rad = 128; end -try, lpf = inverse.lpf; catch, lpf = 0; end -try, hpf = inverse.hpf; catch, hpf = 48; end -try, sdv = inverse.sdv; catch, sdv = 4; end -try, Han = inverse.Han; catch, Han = 1; end -try, Na = inverse.Na; catch, Na = 1024; end -try, woi = inverse.woi; catch, woi = []; end -try, pQ = inverse.pQ; catch, pQ = []; end - - +try, type = inverse.type; catch, type = 'GS'; end +try, s = inverse.smooth; catch, s = 0.6; end +try, Np = inverse.Np; catch, Np = 256; end +try, Nr = inverse.Nr; catch, Nr = 16; end +try, xyz = inverse.xyz; catch, xyz = [0 0 0]; end +try, rad = inverse.rad; catch, rad = 128; end +try, lpf = inverse.lpf; catch, lpf = 0; end +try, hpf = inverse.hpf; catch, hpf = 48; end +try, sdv = inverse.sdv; catch, sdv = 4; end +try, Han = inverse.Han; catch, Han = 1; end +try, Na = inverse.Na; catch, Na = 1024; end +try, woi = inverse.woi; catch, woi = []; end +try, pQ = inverse.pQ; catch, pQ = []; end +try, dplot= inverse.dplot; catch, dplot= 0; end + % get specified modalities to invert (default to all) %-------------------------------------------------------------------------- try @@ -170,13 +170,14 @@ modalities{m} = D{1}.inv{D{1}.val}.forward(m).modality; end end -Nmod = numel(modalities); % number of modalities -Nmmax = Nm; % max number of spatial modes -Nrmax = Nr; % max number of temporal modes +Nmod = numel(modalities); % number of modalities +Nmax = Nr; % max number of temporal modes + - +% check lead fields and get number of dipoles (Nd) and channels (Nc) %========================================================================== for i = 1:Nl + fprintf('Checking leadfields for subject %i\n',i) [L D{i}] = spm_eeg_lgainmat(D{i}); @@ -185,42 +186,41 @@ % Check gain or lead-field matrices %------------------------------------------------------------------ Ic{i,m} = setdiff(meegchannels(D{i}, modalities{m}), badchannels(D{i})); - Nd(i) = size(L,2); % number of dipoles - Nc(i,m) = length(Ic{i,m}); % number of channels - + Nd(i) = size(L,2); + Nc(i,m) = length(Ic{i,m}); + if isempty(Ic{i,m}) errordlg(['Modality ' modalities{m} 'is missing from file ' D{i}.fname]); return end - + if any(diff(Nd)) errordlg('Please ensure subjects have the same number of dipoles') return end - - % Check for null space over sensors and remove it + + % Check for null space over sensors (SX) and remove it %------------------------------------------------------------------ try SX = D{i}.sconfounds{m}; - R{i,m} = speye(Nc(i,m),Nc(i,m)) - SX*pinv(SX); + R{i,m} = speye(Nc(i,m),Nc(i,m)) - SX*spm_pinv(SX); catch R{i,m} = speye(Nc(i,m),Nc(i,m)); end end end fprintf(' - done\n') - - + + % Compute spatial coherence: Diffusion on a normalised graph Laplacian GL %========================================================================== - - + fprintf('Computing Green function from graph Laplacian:') %-------------------------------------------------------------------------- Nd = Nd(1); % number of dipoles vert = D{1}.inv{D{1}.val}.mesh.tess_mni.vert; face = D{1}.inv{D{1}.val}.mesh.tess_mni.face; -A = spm_eeg_inv_meshdist(vert,face,0); +A = spm_mesh_distmtx(struct('vertices',vert,'faces',face),0); GL = A - spdiags(sum(A,2),0,Nd,Nd); GL = GL*s/2; Qi = speye(Nd,Nd); @@ -233,101 +233,158 @@ QG = QG*QG; clear Qi A GL fprintf(' - done\n') - - -% check restriction (assume radii are the same for all VOI) -%========================================================================== -Nv = size(xyz,1); % number of VOI -if length(rad) ~= Nv - rad = rad(1)*ones(Nv,1); -else - rad = rad(:); -end - -% Restrict source space by eliminating dipoles -%-------------------------------------------------------------------------- -Is = sparse(Nd,1); -for i = 1:Nv - Iv = sum([vert(:,1) - xyz(i,1), ... - vert(:,2) - xyz(i,2), ... - vert(:,3) - xyz(i,3)].^2,2) < rad(i)^2; - Is = Is | Iv; -end -Is = find(Is); -vert = vert(Is,:); -QG = QG(Is,Is); -Ns = length(Is); % number of sources - - + + % check for (e.g., empty-room) sensor components (in Qe{1}) %========================================================================== +QE = cell(Nl,Nmod); for i = 1:Nl for m = 1:Nmod try - Qe = D{i}.inv{D{i}.val}.inverse.Qe{m}; - QE{i,m} = Nc(i,m)*Qe/trace(Qe); + QE{i,m} = D{i}.inv{D{i}.val}.inverse.Qe{m}; + QE{i,m} = Nc(i,m)*QE{i,m}/trace(QE{i,m}); if length(QE{i,m}) ~= Nc(i,m) errordlg('error component (modality %s; subject %d) does not match number of channels (%d)\n',modalities{m},i,Nc(i,m)) return end + fprintf('Using sensor error component provided...\n'); - % assume i.i.d. if not specified - %------------------------------------------------------------------ + % assume i.i.d. if not specified + %------------------------------------------------------------------ catch - Qe = []; + QE{i,m} = 1; + end end end -if ~isempty(Qe) - fprintf('Using sensor error component provided...\n'); -end - - + + %========================================================================== % Spatial projectors (adjusting for different Lead-fields) %========================================================================== - + +fprintf('Optimising and aligning spatial modes ...\n') + +% Use recursive (regularised) least squares to find average lead-field +%-------------------------------------------------------------------------- +Is = 1:Nd; +UL = cell(Nmod,1); for m = 1:Nmod - - % Project to channel modes (U := A{1,m}) (with null space over sensors) - %---------------------------------------------------------------------- - L = R{1,m}*spm_eeg_lgainmat(D{1},Is,D{1}.chanlabels(Ic{1,m})); - U = spm_svd(L*L',exp(-16)); - Nm(m) = min(size(U,2),Nmmax); - A{1,m} = U(:,1:Nm(m))'; - UL{m} = A{1,m}*L; - - % Scale projected lead-field + + % Initialise average lead-field with L{1} %---------------------------------------------------------------------- - UL{m} = UL{m}/sqrt(trace(UL{m}*UL{m}')/Nm(m)); - - % Spatial projectors A{i,m) for subsequent subjects (i) + UL{m} = R{1,m}*spm_eeg_lgainmat(D{1},Is,D{1}.chanlabels(Ic{1,m})); + AA = 1; + + % pre-compute regularised inverses (for speed) %---------------------------------------------------------------------- - for i = 2:Nl + for i = 1:Nl L = R{i,m}*spm_eeg_lgainmat(D{i},Is,D{i}.chanlabels(Ic{i,m})); - A{i,m} = UL{m}*pinv(full(L)); + iL{i} = spm_inv(L*L' + speye(Nc(i, m))*norm(L,'inf')*exp(-16)); + end + + % Optimise alignment matrices A such that A{m}*L{m} = m + %---------------------------------------------------------------------- + for j = 1:8 + + % eliminate redundant virtual channels + %------------------------------------------------------------------ + fprintf('Aligning - iteration: %i\n',j) + UL{m} = spm_sqrtm(spm_inv(AA))*UL{m}; + + % eliminate low SNR spatial modes + %------------------------------------------------------------------ + U = spm_svd((UL{m}*UL{m}'),exp(-16)); + UL{m} = U'*UL{m}; + Nm(m) = size(UL{m},1); + + % normalise lead-field + %------------------------------------------------------------------ + Scale = sqrt(trace(UL{m}*UL{m}')/Nm(m)); + UL{m} = UL{m}/Scale; + + % spatial projectors A{i,m) for i = 1,...,Nl subjects + %------------------------------------------------------------------ + AL = 0; + AA = 0; + for i = 1:Nl + L = R{i,m}*spm_eeg_lgainmat(D{i},Is,D{i}.chanlabels(Ic{i,m})); + A{i,m} = UL{m}*L'*iL{i}; + AL = AL + A{i,m}*L; + AA = AA + A{i,m}*A{i,m}'; + end + + % re-compute average + %------------------------------------------------------------------ + UL{m} = AL/Nl; + if Nl == 1, break, end + end - + % Report %---------------------------------------------------------------------- fprintf('Using %d spatial modes for modality %s\n',Nm(m),modalities{m}) + + if dplot + spm_figure('GetWin','Lead fields'); + for i = 1:Nl + + L = R{i,m}*spm_eeg_lgainmat(D{i},Is(1:8:end),D{i}.chanlabels(Ic{i,m})); + subplot(Nl,4,(i - 1)*4 + 1) + imagesc(A{i,m}*A{i,m}'), axis square + subplot(Nl,4,(i - 1)*4 + 2) + imagesc(A{i,m}'*A{i,m}), axis square + subplot(Nl,4,(i - 1)*4 + 3) + plot(sum(A{i,m}.^2,2)), axis square + subplot(Nl,4,(i - 1)*4 + 4) + plot(L'*A{i,m}'), axis square tight + end + drawnow + end end - - - + + +% check restriction: assume radii are the same for all (Nv) VOI +%========================================================================== +Nv = size(xyz,1); +if length(rad) ~= Nv + rad = rad(1)*ones(Nv,1); +else + rad = rad(:); +end + +% Restrict source space to Ns sources by eliminating dipoles +%-------------------------------------------------------------------------- +Is = sparse(Nd,1); +for i = 1:Nv + Iv = sum([vert(:,1) - xyz(i,1), ... + vert(:,2) - xyz(i,2), ... + vert(:,3) - xyz(i,3)].^2,2) < rad(i)^2; + Is = Is | Iv; +end +Is = find(Is); +vert = vert(Is,:); +QG = QG(Is,Is); +for m = 1:Nmod + UL{m} = UL{m}(:,Is); +end +Ns = length(Is); + + + + %========================================================================== % Temporal projector %========================================================================== - -Nn = sparse(1,Nl); % total number of samples -AY = {}; % group response for MVB -AYYA = sparse(0); % group response for ReML - + % loop over Nl lead-fields (subjects) -%---------------------------------------------------------------------- +%-------------------------------------------------------------------------- +Nn = zeros(1,Nl); % number of samples +AY = {}; % pooled response for MVB +AYYA = 0; % pooled response for ReML for i = 1:Nl - + % Time-window of interest %---------------------------------------------------------------------- if isempty(woi) @@ -338,186 +395,196 @@ It{i} = (w{i}/1000 - D{i}.timeonset)*D{i}.fsample + 1; It{i} = max(1,It{i}(1)):min(It{i}(end), length(D{i}.time)); It{i} = fix(It{i}); - + % Peristimulus time %---------------------------------------------------------------------- - pst{i} = 1000*D{i}.time; % peristimulus time (ms) - pst{i} = pst{i}(It{i}); % windowed time (ms) - dur = (pst{i}(end) - pst{i}(1))/1000; % duration (s) - dct{i} = (It{i} - It{i}(1))/2/dur; % DCT frequencies (Hz) - Nb(i) = length(It{i}); % number of time bins - + pst{i} = 1000*D{i}.time; % peristimulus time (ms) + pst{i} = pst{i}(It{i}); % windowed time (ms) + dur = (pst{i}(end) - pst{i}(1))/1000; % duration (s) + dct{i} = (It{i} - It{i}(1))/2/dur; % DCT frequencies (Hz) + Nb(i) = length(It{i}); % number of time bins + % Serial correlations %---------------------------------------------------------------------- K = exp(-(pst{i} - pst{i}(1)).^2/(2*sdv^2)); K = toeplitz(K); qV{i} = sparse(K*K'); - + % Confounds and temporal subspace %---------------------------------------------------------------------- T = spm_dctmtx(Nb(i),Nb(i)); j = find( (dct{i} >= lpf) & (dct{i} <= hpf) ); T = T(:,j); dct{i} = dct{i}(j); - - + + % Hanning operator (if requested) %---------------------------------------------------------------------- if Han - W = sparse(1:Nb(i),1:Nb(i),spm_hanning(Nb(i))); + W = sparse(1:Nb(i),1:Nb(i),spm_hanning(Nb(i))); else - W = 1; + W = 1; end - + % get trials or conditions %---------------------------------------------------------------------- try trial = D{i}.inv{D{i}.val}.inverse.trials; catch - trial = unique(D{i}.conditions); + trial = D{i}.condlist; end Nt(i) = length(trial); - + % get temporal covariance (Y'*Y) to find temporal modes %====================================================================== - Ay = cell(Nmod,1); % modality-specifc + MY = cell(Nmod,1); % mean response YTY = sparse(0); % accumulator for m = 1:Nmod % loop over modalities - + % get (spatially aligned) data %------------------------------------------------------------------ + N = 0; YY = 0; - Ay{m} = 0; - for j = 1:Nt(i) % pool over conditions - c = D{i}.pickconditions(trial{j}); % and trials - for k = 1:length(c) - y = A{i,m}*D{i}(Ic{i,m},It{i},c(k)); - Ay{m} = Ay{m} + y; - YY = YY + y'*y; + MY{m} = 0; + for j = 1:Nt(i) % pool over conditions + c = D{i}.pickconditions(trial{j}); % and trials + Nk = length(c); + for k = 1:Nk + Y = A{i,m}*D{i}(Ic{i,m},It{i},c(k)); + MY{m} = MY{m} + Y; + YY = YY + Y'*Y; + N = N + Nb(i); end end - % Scale data (in case fusing multiple modalities) + % Apply any Hanning and filtering + %------------------------------------------------------------------ + YY = W'*YY*W; + YY = T'*YY*T; + + % Scale data (to remove subject and modality scaling differences) %------------------------------------------------------------------ - scale(i,m) = sign(trace(Ay{m}'*(UL{m}*UL{1}')*Ay{1})); - scale(i,m) = scale(i,m)/sqrt(trace(YY)/Nm(m)); + scale(i,m) = sign(trace(MY{m}'*(UL{m}*UL{1}')*MY{1})); + scale(i,m) = scale(i,m)/sqrt(trace(YY)/(Nm(m)*N)); YTY = YTY + YY*(scale(i,m)^2); end - + % temporal projector (at most Nrmax modes) S = T*V %====================================================================== - YTY = W'*YTY*W; % Apply any Hanning - YTY = T'*YTY*T; % Apply filtering - [VT E] = spm_svd(YTY,exp(-8)); % get temporal modes - E = diag(E)/trace(YTY); % normalise variance - Nr(i) = min(length(E),Nrmax); % number of temporal modes - V{i} = VT(:,1:Nr(i)); % temporal modes - VE(i) = sum(E(1:Nr(i))); % variance explained - + [U E] = spm_svd(YTY,exp(-8)); % get temporal modes + E = diag(E)/trace(YTY); % normalise variance + Nr(i) = min(length(E),Nmax); % number of temporal modes + V{i} = U(:,1:Nr(i)); % temporal modes + VE(i) = sum(E(1:Nr(i))); % variance explained + fprintf('Using %i temporal modes for subject %i, ',Nr(i),i) fprintf('accounting for %0.2f percent average variance\n',full(100*VE(i))) - + % projection and whitening %---------------------------------------------------------------------- - S{i} = T*V{i}; % temporal projector - qP = inv(S{i}'*qV{i}*S{i}); % precision (mode) - Vq{i} = S{i}*qP*S{i}'; % precision (time) - - + S{i} = T*V{i}; % temporal projector + Vq{i} = S{i}*inv(S{i}'*qV{i}*S{i})*S{i}'; % temporal precision + + % get spatial covariance (Y*Y') for Gaussian process model. %====================================================================== - UYYU{i} = sparse(0); - + % loop over Nt trial types %---------------------------------------------------------------------- + UYYU{i} = 0; for j = 1:Nt(i) - + UY{i,j} = sparse(0); - c = D{i}.pickconditions(trial{j}); - for k = 1:length(c) - + c = D{i}.pickconditions(trial{j}); + Nk = length(c); + + % loop over epochs + %------------------------------------------------------------------ + for k = 1:Nk + % stack (scaled aligned data) over modalities %-------------------------------------------------------------- - Ay = cell(Nmod,1); % modality accumulator for m = 1:Nmod - y = D{i}(Ic{i,m},It{i},c(k))*S{i}; - Ay{m} = A{i,m}*y*scale(i,m); + Y = D{i}(Ic{i,m},It{i},c(k))*S{i}; + MY{m} = A{i,m}*Y*scale(i,m)/Nk; end - Ay = spm_cat(Ay)/length(c); % contribution to ERP - AyyA = Ay*Ay'; % and covariance + + % accumulate first & second-order responses + %-------------------------------------------------------------- Nn(i) = Nn(i) + Nr(i); % number of samples - - % accumulate first & second-order statistics (subject-specific) + Y = spm_cat(MY); % contribution to ERP + YY = Y*Y'; % and covariance + + % accumulate statistics (subject-specific) %-------------------------------------------------------------- - UY{i,j} = UY{i,j} + Ay; % condition-specific ERP - UYYU{i} = UYYU{i} + AyyA; % subject-specific covariance - + UY{i,j} = UY{i,j} + Y; % condition-specific ERP + UYYU{i} = UYYU{i} + YY; % subject-specific covariance + % and pool for optimisation of spatial priors over subjects %-------------------------------------------------------------- - AY{end + 1} = Ay; % pooled response for MVB - AYYA = AYYA + AyyA; % pooled response for ReML - + AY{end + 1} = Y; % pooled response for MVB + AYYA = AYYA + YY; % pooled response for ReML + end end - end - -% concatenate responses over realisations and lead fields over modalities + +% and concatenate for optimisation of spatial priors over subjects %-------------------------------------------------------------------------- -AY = spm_cat(AY); -UL = spm_cat(UL(:)); - - +AY = spm_cat(AY); % pooled response for MVB +UL = spm_cat(UL); % pooled lead fields + + % generate sensor error components (Qe) %========================================================================== -AQe = {sparse(0)}; +AQ{1} = sparse(0); for m = 1:Nmod Qe{m} = sparse(0); end - -% assuming equal noise over subjects (Qe{m}) and modalities AQe -%---------------------------------------------------------------------- + +% assuming equal noise over subjects (Qe{m}) and modalities AQ +%-------------------------------------------------------------------------- +N = cell(Nmod,Nmod); for i = 1:Nl for m = 1:Nmod - N{m,m} = sparse(Nm(m),Nm(m)); + N{m,m} = sparse(Nm(m),Nm(m)); end for m = 1:Nmod - Q = N; - Q{m,m} = A{i,m}*QE{i,m}*A{i,m}'; - Qe{m} = Qe{m} + spm_cat(Q); - AQe{1} = AQe{1} + Qe{m}; + Q = N; + AQeA = A{i,m}*QE{i,m}*A{i,m}'; + Q{m,m} = AQeA/(trace(AQeA)/Nm(m)); + Q = spm_cat(Q)/Nl; + Qe{m} = Qe{m} + Q; + AQ{1} = AQ{1} + Q; end end - - - - + + %========================================================================== % Step 1: Optimise spatial priors over subjects %========================================================================== - - + % create source components (Qp) %========================================================================== switch(type) - + case {'MSP','GS','ARD'} - + % create MSP spatial basis set in source space %------------------------------------------------------------------ Qp = {}; LQpL = {}; Ip = ceil([1:Np]*Ns/Np); for i = 1:Np - + % left hemisphere %-------------------------------------------------------------- q = QG(:,Ip(i)); Qp{end + 1}.q = q; LQpL{end + 1}.q = UL*q; - + % right hemisphere %-------------------------------------------------------------- [d j] = min(sum([vert(:,1) + vert(Ip(i),1), ... @@ -526,63 +593,69 @@ q = QG(:,j); Qp{end + 1}.q = q; LQpL{end + 1}.q = UL*q; - + % bilateral %-------------------------------------------------------------- q = QG(:,Ip(i)) + QG(:,j); Qp{end + 1}.q = q; LQpL{end + 1}.q = UL*q; - + end - + case {'LOR','COH'} - + % create minimum norm prior %------------------------------------------------------------------ Qp{1} = speye(Ns,Ns); LQpL{1} = UL*UL'; - + % add smoothness component in source space %------------------------------------------------------------------ Qp{2} = QG; LQpL{2} = UL*Qp{2}*UL'; - - + + case {'IID','MMN'} - + % create minimum norm prior %------------------------------------------------------------------ Qp{1} = speye(Ns,Ns); LQpL{1} = UL*UL'; - + end - - + + % augment with exogenous (e.g., fMRI) source priors in pQ %========================================================================== for i = 1:length(pQ) - + switch(type) - + case {'MSP','GS','ARD'} %-------------------------------------------------------------- if isvector(pQ{i}) && length(pQ{i}) == Ns + Qp{end + 1}.q = pQ{i}(:); LQpL{end + 1}.q = UL*Qp{end}.q; + else errordlg('Using MSP(GS/ARD) please supply spatial priors as vectors') return end - + case {'LOR','COH','IID','MMN'} %-------------------------------------------------------------- if isvector(pQ{i}) && length(pQ{i}) == Ns + pQ{i} = pQ{i}(:); Qp{end + 1} = sparse(diag(pQ{i}.^2)); LQpL{end + 1} = UL*Qp{end}*UL'; + elseif size(pQ{i},1) == Ns && size(pQ{i},2) == Ns + Qp{end + 1} = pQ{i}; LQpL{end + 1} = UL*Qp{end}*UL'; + else errordlg('spatial priors are the wrong size') return @@ -592,20 +665,20 @@ if ~isempty(pQ) fprintf('Using %d spatial source priors provided...\n',length(pQ)); end - - + + % Inverse solution %========================================================================== QP = {}; LQP = {}; LQPL = {}; - + % Get source-level priors (using all subjects) %-------------------------------------------------------------------------- switch(type) - + case {'MSP','GS'} - + % Greedy search over MSPs %------------------------------------------------------------------ Np = length(Qp); @@ -613,157 +686,159 @@ for i = 1:Np Q(:,i) = Qp{i}.q; end - + % Multivariate Bayes %------------------------------------------------------------------ - MVB = spm_mvb(AY,UL,[],Q,AQe,16); - + MVB = spm_mvb(AY,UL,[],Q,AQ,16); + % Accumulate empirical priors %------------------------------------------------------------------ Qcp = Q*MVB.cp; QP{end + 1} = sum(Qcp.*Q,2); LQP{end + 1} = (UL*Qcp)*Q'; LQPL{end + 1} = LQP{end}*UL'; - + end - - + + switch(type) - + case {'MSP','ARD'} - - % or ReML - ARD + + % ReML - ARD %------------------------------------------------------------------ - qp = sparse(0); - Q = {Qe{:} LQpL{:}}; - [Cy,h,Ph,F] = spm_sp_reml(AYYA,[],Q,sum(Nn)); - + [Cy,h,Ph,F] = spm_sp_reml(AYYA,[],[Qe LQpL],sum(Nn)); + % Spatial priors (QP) %------------------------------------------------------------------ Ne = length(Qe); Np = length(Qp); hp = h([1:Np] + Ne); + qp = sparse(0); for i = 1:Np if hp(i) > max(hp)/128; qp = qp + hp(i)*Qp{i}.q*Qp{i}.q'; end end - + % Accumulate empirical priors %------------------------------------------------------------------ QP{end + 1} = diag(qp); LQP{end + 1} = UL*qp; LQPL{end + 1} = LQP{end}*UL'; - + end - + switch(type) - + case {'IID','MMN','LOR','COH'} - + % or ReML - ARD %------------------------------------------------------------------ - qp = sparse(0); - Q = {Qe{:} LQpL{:}}; - [Cy,h,Ph,F] = spm_reml_sc(AYYA,[],Q,sum(Nn)); - + Q0 = exp(-2)*trace(AYYA)/sum(Nn)*AQ{1}/trace(AQ{1}); + [Cy,h,Ph,F] = spm_reml_sc(AYYA,[],[Qe LQpL],sum(Nn),-4,16,Q0); + % Spatial priors (QP) %------------------------------------------------------------------ Ne = length(Qe); Np = length(Qp); hp = h([1:Np] + Ne); + qp = sparse(0); for i = 1:Np qp = qp + hp(i)*Qp{i}; end - + % Accumulate empirical priors %------------------------------------------------------------------ QP{end + 1} = diag(qp); LQP{end + 1} = UL*qp; LQPL{end + 1} = LQP{end}*UL'; - + end - - - + + + %========================================================================== % Step 2: Re-estimate for each subject separately (fusing all modalities) %========================================================================== - + for i = 1:Nl - + fprintf('Inverting subject %i\n',i) % generate sensor component (Qe) per modality %---------------------------------------------------------------------- + AQ = 0; Qe = {}; for m = 1:Nmod - N{m,m} = sparse(Nm(m),Nm(m)); + N{m,m} = sparse(Nm(m),Nm(m)); end for m = 1:Nmod - Q = N; - Q{m,m} = A{i,m}*QE{i,m}*A{i,m}'; - Qe{m} = spm_cat(Q); + Q = N; + AQeA = A{i,m}*QE{i,m}*A{i,m}'; + Q{m,m} = AQeA/(trace(AQeA)/Nm(m)); + Qe{m} = spm_cat(Q); + AQ = AQ + Qe{m}; end % using spatial priors from group analysis %---------------------------------------------------------------------- Np = length(LQPL); Ne = length(Qe); - Q = {Qe{:} LQPL{:}}; - - % re-do ReML - %---------------------------------------------------------------------- - [Cy,h,Ph,F] = spm_reml_sc(UYYU{i},[],Q,Nn(i)); - + Q = [Qe LQPL]; + + % re-do ReML (with informative hyperpriors) + %====================================================================== + Q0 = exp(-2)*trace(UYYU{i})/Nn(i)*AQ/trace(AQ); + [Cy,h,Ph,F] = spm_reml_sc(UYYU{i},[],Q,Nn(i),-4,16,Q0); + % Data ID - %========================================================================== - ID = spm_data_id(UYYU{i}); - - + %---------------------------------------------------------------------- + ID = spm_data_id(AYYA); + + % Covariance: sensor space - Ce and source space - L*Cp - %-------------------------------------------------------------------------- + %---------------------------------------------------------------------- Cp = sparse(0); LCp = sparse(0); - hp = h([1:Np] + Ne); + hp = h(Ne + (1:Np)); for j = 1:Np Cp = Cp + hp(j)*QP{j}; LCp = LCp + hp(j)*LQP{j}; end - + % MAP estimates of instantaneous sources %====================================================================== - iC = inv(Cy); - M = LCp'*iC; - + M = LCp'/Cy; + % conditional variance (leading diagonal) % Cq = Cp - Cp*L'*iC*L*Cp; %---------------------------------------------------------------------- Cq = Cp - sum(LCp.*M')'; - + % evaluate conditional expectation (of the sum over trials) %---------------------------------------------------------------------- SSR = 0; SST = 0; J = {}; for j = 1:Nt(i) - + % trial-type specific source reconstruction %------------------------------------------------------------------ J{j} = M*UY{i,j}; - + % sum of squares %------------------------------------------------------------------ SSR = SSR + sum(var((UY{i,j} - UL*J{j}),0,2)); SST = SST + sum(var( UY{i,j},0,2)); - + end - + % accuracy; signal to noise (over sources) %====================================================================== R2 = 100*(SST - SSR)/SST; - fprintf('Percent variance explained %.2f (%.2f)\n',R2,R2*VE(i)) - + fprintf('Percent variance explained %.2f (%.2f)\n',full(R2),full(R2*VE(i))); + % Save results (for first modality) %====================================================================== inverse.type = type; % inverse model @@ -787,29 +862,29 @@ inverse.dct = dct{i}; % frequency range inverse.F = F; % log-evidence inverse.ID = ID; % data ID - inverse.R2 = R2; % variance accounted for (%) - inverse.VE = VE(i); % variance explained + inverse.R2 = R2; % variance explained (reduced) + inverse.VE = R2*VE(i); % variance explained inverse.woi = w{i}; % time-window inverted - + inverse.modality = modalities; % modalities inverted - + % save in struct %---------------------------------------------------------------------- D{i}.inv{D{i}.val}.inverse = inverse; D{i}.inv{D{i}.val}.method = 'Imaging'; - + % and delete old contrasts %---------------------------------------------------------------------- try D{i}.inv{D{i}.val} = rmfield(D{i}.inv{D{i}.val},'contrast'); end - + % display %====================================================================== spm_eeg_invert_display(D{i}); drawnow - + end - + if length(D) == 1, D = D{1}; end return diff --git a/spm_eeg_invert_display.m b/spm_eeg_invert_display.m index 6a1cb4c..50f9276 100644 --- a/spm_eeg_invert_display.m +++ b/spm_eeg_invert_display.m @@ -12,7 +12,7 @@ function spm_eeg_invert_display(D,PST,Ndip) % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_eeg_invert_display.m 2822 2009-03-04 10:39:53Z vladimir $ +% $Id: spm_eeg_invert_display.m 3813 2010-04-07 19:21:49Z karl $ % Number of dipoles to display %========================================================================== @@ -45,17 +45,14 @@ function spm_eeg_invert_display(D,PST,Ndip) J = model.inverse.J; T = model.inverse.T; Is = model.inverse.Is; -Nd = model.inverse.Nd; pst = model.inverse.pst; R2 = model.inverse.R2; +VE = model.inverse.VE; F = model.inverse.F; -Ndip = min(Ndip,length(Is)); - -try - VE = model.inverse.VE; -catch - VE =1 ; -end + +Nd = length(Is); +Ndip = min(Ndip,Nd); + % - project J onto pst %-------------------------------------------------------------------------- @@ -127,8 +124,8 @@ function spm_eeg_invert_display(D,PST,Ndip) end Jt = J(js,:); % over time Js = J(:,jt); % over sources -PST = fix(pst(jt)); -XYZ = fix(vert(Is(js),:)); +PST = round(pst(jt)); +XYZ = round(vert(Is(js),:)); Jmax = abs(sparse(Is,1,Js,Nd,1)); % plot responses over time @@ -151,7 +148,7 @@ function spm_eeg_invert_display(D,PST,Ndip) %---------------------------------------------------------------------- try qC = model.inverse.qC(js).*diag(model.inverse.qV)'; - ci = 1.64*sqrt(qC); + ci = 1.64*sqrt(abs(qC)); plot(pst,Jt,pst,Jt + ci,':',pst,Jt - ci,':',... [PST PST],[-1 1]*maxJ,':',... 'Color',Color) @@ -184,7 +181,7 @@ function spm_eeg_invert_display(D,PST,Ndip) PP = fix(100*(spm_Ncdf(Z))); title({sprintf('PPM at %i ms (%i percent confidence)',PST,PP), ... sprintf('%i dipoles',length(i)), ... - sprintf('Percent variance explained %.2f (%.2f)',full(R2),full(R2*VE)), ... + sprintf('Percent variance explained %.2f (%.2f)',full(R2),full(VE)), ... sprintf('log-evidence = %.1f',full(F))}) catch title({sprintf('Responses at %i dipoles',length(i)), ... diff --git a/spm_eeg_lgainmat.m b/spm_eeg_lgainmat.m index e03167b..13b0907 100644 --- a/spm_eeg_lgainmat.m +++ b/spm_eeg_lgainmat.m @@ -9,7 +9,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_eeg_lgainmat.m 3558 2009-11-11 20:23:05Z karl $ +% $Id: spm_eeg_lgainmat.m 3877 2010-05-07 19:49:35Z karl $ % get gain or lead-feild matrix @@ -39,26 +39,10 @@ try fname = D.inv{val}.gainmat; - try - G = load(fname); % Absolute path - catch - try - G = load(fullfile(D.path, fname)); % Relative path - catch - [p f x] = fileparts(fname); - try - fname = fullfile(D.path, [f x]); % Try D's directory - G = load(fname); - catch - try - fname = fullfile(pwd, [f x]); % Try current directory - G = load(fname); - end - end - end - end + G = load(fullfile(D.path, fname)); % Relative path + label = G.label; - G = G.G; + G = G.G; if numel(label) ~= size(G, 1) ||... ~all(ismember(channels, label)) error('Gain matrix has an incorrect number of channels'); @@ -81,7 +65,7 @@ vol = forward(ind).vol; if ischar(vol) - vol = fileio_read_vol(vol); + vol = ft_read_vol(vol); end sens = D.inv{val}.datareg(ind).sensors; @@ -89,7 +73,7 @@ % Forward computation %-------------------------------------------------------------------------- - [vol, sens] = forwinv_prepare_vol_sens(vol, sens, 'channel', forward(ind).channels); + [vol, sens] = ft_prepare_vol_sens(vol, sens, 'channel', forward(ind).channels); nvert = size(vert, 1); spm('Pointer', 'Watch');drawnow; @@ -100,7 +84,7 @@ Gxyz = zeros(length(forward(ind).channels), 3*nvert); for i = 1:nvert - Gxyz(:, (3*i- 2):(3*i)) = forwinv_compute_leadfield(vert(i, :), sens, vol); + Gxyz(:, (3*i- 2):(3*i)) = ft_compute_leadfield(vert(i, :), sens, vol); if ismember(i, Ibar) spm_progress_bar('Set', i); drawnow; @@ -151,7 +135,8 @@ % condition the scaling of the lead-field %-------------------------------------------------------------------------- -L = spm_cond_units(sparse(G(sel2, :))); +L = spm_cond_units(sparse(G(sel2, :))); + % retain selected sources if necessary %-------------------------------------------------------------------------- diff --git a/spm_eeg_load.m b/spm_eeg_load.m index ad1c7ed..4c7f99e 100644 --- a/spm_eeg_load.m +++ b/spm_eeg_load.m @@ -12,7 +12,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Stefan Kiebel -% $Id: spm_eeg_load.m 2889 2009-03-17 12:02:04Z vladimir $ +% $Id: spm_eeg_load.m 3879 2010-05-07 20:03:34Z vladimir $ % bypass if the input is already an MEEG object %-------------------------------------------------------------------------- diff --git a/spm_eeg_montage.m b/spm_eeg_montage.m index f0fb5f0..2feb7eb 100644 --- a/spm_eeg_montage.m +++ b/spm_eeg_montage.m @@ -31,9 +31,9 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Vladimir Litvak, Robert Oostenveld, Stefan Kiebel -% $Id: spm_eeg_montage.m 3382 2009-09-10 15:46:31Z vladimir $ +% $Id: spm_eeg_montage.m 3970 2010-07-05 17:26:16Z vladimir $ -SVNrev = '$Rev: 3382 $'; +SVNrev = '$Rev: 3970 $'; %-Startup %-------------------------------------------------------------------------- @@ -52,6 +52,10 @@ D = spm_eeg_load(D); +if strncmp(D.transformtype, 'TF', 2) + error('Montage cannot be applied to time-frequency data'); +end + %-Get size of blocks used internally to split large continuous files %-------------------------------------------------------------------------- try @@ -224,10 +228,10 @@ selempty = find(all(sensmontage.tra == 0, 2)); sensmontage.tra(selempty, :) = []; sensmontage.labelnew(selempty) = []; - sens = forwinv_apply_montage(sens, sensmontage, 'keepunused', S.keepothers); + sens = ft_apply_montage(sens, sensmontage, 'keepunused', S.keepothers); if isfield(sens, 'balance') && ~isequal(sens.balance.current, 'none') - balance = forwinv_apply_montage(getfield(sens.balance, sens.balance.current), sensmontage, 'keepunused', S.keepothers); + balance = ft_apply_montage(getfield(sens.balance, sens.balance.current), sensmontage, 'keepunused', S.keepothers); else balance = sensmontage; end @@ -287,6 +291,16 @@ Dnew = spm_eeg_prep(S1); end +%-Transfer the properties of channels not involved in the montage +%-------------------------------------------------------------------------- +if ~isempty(add) && strcmp(S.keepothers, 'yes') + old_add_ind = D.indchannel(add); + new_add_ind = Dnew.indchannel(add); + + Dnew = badchannels(Dnew, new_add_ind, badchannels(D, old_add_ind)); + Dnew = chantype(Dnew, new_add_ind, chantype(D, old_add_ind)); +end + [ok, Dnew] = check(Dnew, 'basic'); %-Save new evoked M/EEG dataset diff --git a/spm_eeg_prep.m b/spm_eeg_prep.m index 3df37cb..f293133 100644 --- a/spm_eeg_prep.m +++ b/spm_eeg_prep.m @@ -15,7 +15,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Vladimir Litvak -% $Id: spm_eeg_prep.m 3484 2009-10-19 10:17:40Z vladimir $ +% $Id: spm_eeg_prep.m 3833 2010-04-22 14:49:48Z vladimir $ if ~nargin spm_eeg_prep_ui; @@ -57,7 +57,7 @@ D = chantype(D, ind, 'Other'); - type = fileio_chantype(D.chanlabels); + type = ft_chantype(D.chanlabels); % If there is useful information in the original types it % overwrites the default assignment @@ -168,7 +168,7 @@ case 'locfile' label = chanlabels(D, D.meegchannels('EEG')); - elec = fileio_read_sens(S.sensfile); + elec = ft_read_sens(S.sensfile); % Remove headshape points hspind = strmatch('headshape', elec.label); @@ -186,7 +186,7 @@ end end - shape = fileio_read_headshape(S.sensfile); + shape = ft_read_headshape(S.sensfile); % In case electrode file is used for fiducials, the % electrodes can be used as headshape @@ -197,13 +197,13 @@ end - elec = forwinv_convert_units(elec, 'mm'); - shape= forwinv_convert_units(shape, 'mm'); + elec = ft_convert_units(elec, 'mm'); + shape= ft_convert_units(shape, 'mm'); if isequal(D.modality(1, 0), 'Multimodal') if ~isempty(D.fiducials) && isfield(S, 'regfid') && ~isempty(S.regfid) M1 = coreg(D.fiducials, shape, S.regfid); - elec = forwinv_transform_sens(M1, elec); + elec = ft_transform_sens(M1, elec); else error(['MEG fiducials matched to EEG fiducials are required '... 'to add EEG sensors to a multimodal dataset.']); @@ -221,7 +221,7 @@ template_sfp = dir(fullfile(spm('dir'), 'EEGtemplates', '*.sfp')); template_sfp = {template_sfp.name}; - ind = strmatch([forwinv_senstype(D.chanlabels(D.meegchannels('EEG'))) '.sfp'], template_sfp, 'exact'); + ind = strmatch([ft_senstype(D.chanlabels(D.meegchannels('EEG'))) '.sfp'], template_sfp, 'exact'); if ~isempty(ind) fid = D.fiducials; @@ -261,7 +261,7 @@ S1.updatehistory = 0; D = spm_eeg_prep(S1); else - elec = fileio_read_sens(fullfile(spm('dir'), 'EEGtemplates', template_sfp{ind})); + elec = ft_read_sens(fullfile(spm('dir'), 'EEGtemplates', template_sfp{ind})); [sel1, sel2] = spm_match_str(lower(D.chanlabels), lower(elec.label)); @@ -303,7 +303,7 @@ if ~isempty(D.fiducials) && isfield(S, 'regfid') && ~isempty(S.regfid) M1 = coreg(D.fiducials, fid, S.regfid); - D = sensors(D, 'EEG', forwinv_transform_sens(M1, D.sensors('EEG'))); + D = sensors(D, 'EEG', ft_transform_sens(M1, D.sensors('EEG'))); else D = fiducials(D, fid); end @@ -323,14 +323,14 @@ if isempty(sens) error('The montage cannod be applied - no EEG sensors specified'); end - sens = forwinv_apply_montage(sens, montage, 'keepunused', 'no'); + sens = ft_apply_montage(sens, montage, 'keepunused', 'no'); D = sensors(D, 'EEG', sens); elseif ~isempty(intersect(meglabel, montage.labelnew)) sens = sensors(D, 'MEG'); if isempty(sens) error('The montage cannod be applied - no MEG sensors specified'); end - sens = forwinv_apply_montage(sens, montage, 'keepunused', 'no'); + sens = ft_apply_montage(sens, montage, 'keepunused', 'no'); D = sensors(D, 'MEG', sens); else error('The montage cannot be applied to the sensors'); @@ -365,7 +365,7 @@ shape.pnt = []; end otherwise - shape = fileio_read_headshape(S.headshapefile); + shape = ft_read_headshape(S.headshapefile); % In case electrode file is used for fiducials, the % electrodes can be used as headshape @@ -375,13 +375,13 @@ end end - shape = forwinv_convert_units(shape, 'mm'); + shape = ft_convert_units(shape, 'mm'); fid = D.fiducials; if ~isempty(fid) && isfield(S, 'regfid') && ~isempty(S.regfid) M1 = coreg(fid, shape, S.regfid); - shape = forwinv_transform_headshape(M1, shape); + shape = ft_transform_headshape(M1, shape); end D = fiducials(D, shape); diff --git a/spm_eeg_prep_ui.m b/spm_eeg_prep_ui.m index 3274f0e..f48f307 100644 --- a/spm_eeg_prep_ui.m +++ b/spm_eeg_prep_ui.m @@ -6,7 +6,7 @@ function spm_eeg_prep_ui(callback) % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Vladimir Litvak -% $Id: spm_eeg_prep_ui.m 3601 2009-11-27 18:20:31Z vladimir $ +% $Id: spm_eeg_prep_ui.m 3833 2010-04-22 14:49:48Z vladimir $ spm('Pointer','Watch'); @@ -23,7 +23,7 @@ function spm_eeg_prep_ui(callback) %========================================================================== function CreateMenu -SVNrev = '$Rev: 3601 $'; +SVNrev = '$Rev: 3833 $'; spm('FnBanner', 'spm_eeg_prep_ui', SVNrev); Finter = spm('FnUIsetup', 'M/EEG prepare', 0); @@ -408,7 +408,7 @@ function spm_eeg_prep_ui(callback) error('At least 3 labeled fiducials are necessary'); end else - shape = fileio_read_headshape(S.sensfile); + shape = ft_read_headshape(S.sensfile); lblshape = shape.fid.label; end @@ -465,7 +465,7 @@ function spm_eeg_prep_ui(callback) if ~sts, return, end S.source = 'convert'; -shape = fileio_read_headshape(S.headshapefile); +shape = ft_read_headshape(S.headshapefile); lblshape = shape.fid.label; fid = fiducials(S.D); @@ -675,7 +675,7 @@ function spm_eeg_prep_ui(callback) IsMEG = 'on'; end - if forwinv_senstype(D.chanlabels, 'neuromag') &&... + if ft_senstype(D.chanlabels, 'neuromag') &&... isfield(D, 'origchantypes') IsNeuromag = 'on'; end @@ -702,7 +702,7 @@ function spm_eeg_prep_ui(callback) template_sfp = dir(fullfile(spm('dir'), 'EEGtemplates', '*.sfp')); template_sfp = {template_sfp.name}; - ind = strmatch([forwinv_senstype(D.chanlabels) '.sfp'], template_sfp, 'exact'); + ind = strmatch([ft_senstype(D.chanlabels) '.sfp'], template_sfp, 'exact'); if ~isempty(ind) HasDefaultLocs = 'on'; diff --git a/spm_eeg_review.m b/spm_eeg_review.m index a89f23a..4747de0 100644 --- a/spm_eeg_review.m +++ b/spm_eeg_review.m @@ -11,7 +11,7 @@ function spm_eeg_review(D,flag,inv) % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Jean Daunizeau -% $Id: spm_eeg_review.m 3177 2009-06-03 08:47:41Z vladimir $ +% $Id: spm_eeg_review.m 3725 2010-02-16 12:26:24Z vladimir $ if nargin == 0 [D, sts] = spm_select(1, 'mat$', 'Select M/EEG mat file'); @@ -260,10 +260,18 @@ function back2defaults(e1,e2) end labels{i} = [D.other.inv{isInv(i)}.comment{1}]; callbacks{i} = ['spm_eeg_review_callbacks(''visu'',''inv'',',num2str(i),')']; - F(i) = D.other.inv{isInv(i)}.inverse.F; - pst = [pst;D.other.inv{isInv(i)}.inverse.pst(:)]; + try + F(i) = D.other.inv{isInv(i)}.inverse.F; + pst = [pst;D.other.inv{isInv(i)}.inverse.pst(:)]; + catch + continue + end + end + if isempty(pst) + Ninv = 0; + else + pst = unique(pst); end - pst = unique(pst); end else Ninv = 0; diff --git a/spm_eeg_specest_ft_mtmconvol.m b/spm_eeg_specest_ft_mtmconvol.m new file mode 100644 index 0000000..ad1a8b5 --- /dev/null +++ b/spm_eeg_specest_ft_mtmconvol.m @@ -0,0 +1,178 @@ +function res = spm_eeg_specest_ft_mtmconvol(S, data, time) +% Plugin for spm_eeg_tf implementing spectral estimation using Fieldtrip's freqanalysis_mtmconvol +% FORMAT res = spm_eeg_specest_ft_mtmconvol(S, data, time) +% +% S - input structure +% fields of S: +% S.taper - taper to use ('hanning', 'rectwin', 'dpss', 'sine' or +% other possible inputs of 'window' +% S.freqres - frequency resolutions (plus-minus for each frequency, can +% be a vector with a value per frequency) +% S.frequencies - vector of frequencies +% S.timeres - time resolution in ms (length of the sliding time-window) +% S.timestep - time step (in ms) to slide the time-window by. +% +% Output: +% res - +% If no input is provided the plugin returns a cfg branch for itself +% +% If input is provided: +% res.fourier - the complex output of wavelet transform (in the case +% of single taper) +% res.pow - power (in case of multiple tapers, phase is not computed) +% res.time - time axis +% res.freq - frequency axis +%______________________________________________________________________________________ +% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging + +% Vladimir Litvak based on the code contributed by Krish Singh +% $Id: spm_eeg_specest_ft_mtmconvol.m 3876 2010-05-07 18:51:03Z vladimir $ + + +%-This part if for creating a config branch that plugs into spm_cfg_eeg_tf +% Any parameters can be specified and they are then passed to the plugin +% when it's called. +%-------------------------------------------------------------------------- +if nargin == 0 + timeres = cfg_entry; + timeres.tag = 'timeres'; + timeres.name = 'Time resolution'; + timeres.strtype = 'r'; + timeres.num = [1 1]; + timeres.val = {400}; + timeres.help = {'Length of the sliding time window (in ms)'}; + + timestep = cfg_entry; + timestep.tag = 'timestep'; + timestep.name = 'Time step'; + timestep.strtype = 'r'; + timestep.num = [1 1]; + timestep.val = {50}; + timestep.help = {'Step to slide the time window by (in ms)'}; + + freqres = cfg_entry; + freqres.tag = 'freqres'; + freqres.name = 'Frequency resolution'; + freqres.strtype = 'r'; + freqres.num = [1 Inf]; + freqres.val = {2}; + freqres.help = {'Frequency resolution.',... + 'Note: 1 Hz resolution means plus-minus 1 Hz, i.e. 2 Hz badwidth',... + 'Either a single value or a vector of the same length as frequencies can be input'}; + + taper = cfg_menu; + taper.tag = 'taper'; + taper.name = 'Taper'; + taper.help = {'Save taper as well as power'}; + taper.labels = {'Hanning', 'Rectangular', 'DPSS', 'Sine'}; + taper.values = {'hanning', 'rectwin', 'dpss', 'sine'}; + taper.val = {'sine'}; + + ft_mtmconvol = cfg_branch; + ft_mtmconvol.tag = 'ft_mtmconvol'; + ft_mtmconvol.name = 'Fieldtrip multi-taper'; + ft_mtmconvol.val = {taper, timeres, timestep, freqres}; + + res = ft_mtmconvol; + + return +elseif nargin < 3 + error('Three input arguments are required'); +end + +%-Defaults +%-------------------------------------------------------------------------- +if ~isfield(S, 'taper') + S.taper = 'dpss'; +end + +if ~isfield(S, 'timeres') + S.timeres = 400; +end + +timeres = 1e-3*S.timeres; + +if ~isfield(S, 'timestep') + S.timestep = 50; +end +timestep = 1e-3*S.timestep; + +dt = time(end) - time(1); + +if ~isfield(S, 'frequencies') || isempty(S.frequencies) + S.frequencies = (1/dt):max(1/dt, floor(dt)/dt):48; +end + +if ~isfield(S, 'freqres') + S.freqres = max(1/timeres, floor(timeres)/timeres); +end + +if length(S.freqres) == 1 + freqres = S.freqres*ones(1, length(S.frequencies)); +elseif length(S.freqres) == length(S.frequencies) + freqres = S.freqres; +else + error('Frequency resolution should be either a scalar or a vector the same length as the number of frequencies.') +end + +%-Data dimensions +%-------------------------------------------------------------------------- +Nchannels = size(data, 1); +Nsamples = size(data, 2); +Nfrequencies = length(S.frequencies); + +fsample = 1./diff(time(1:2)); + +%-Do the spectral analysis +%-------------------------------------------------------------------------- +% This is a temporary solution to get the functionality that will soon +% be replaced by a low level specest function + +ftraw = []; +ftraw.trial = {data}; +ftraw.time = {time}; +ftraw.fsample = fsample; + +for i = 1:Nchannels + ftraw.label{i, 1} = ['Ch' num2str(i)]; +end + +cfg = []; +cfg.output ='fourier'; +cfg.taper = S.taper; +cfg.method = 'mtmconvol'; + +% This sets the centers of frequency bins at the optimal locations based on +% the time window. +cfg.foi = S.frequencies; % Frequency axis +numfoi = length(cfg.foi); + +% This means that the time resolution is the same for all frequencies +cfg.t_ftimwin = zeros(1,numfoi); +cfg.t_ftimwin(:) = timeres; % Time resolution + +cfg.tapsmofrq = freqres; + +cfg.toi=(time(1)+(timeres/2)):timestep:(time(end)-(timeres/2)-1/fsample); % Time axis + +if ismember(cfg.taper, {'dpss', 'sine'}) && ~(all(cfg.tapsmofrq==cfg.tapsmofrq(1)) && all(cfg.t_ftimwin==cfg.t_ftimwin(1))) + cfg.output ='pow'; +end + +freq = ft_freqanalysis(cfg, ftraw); + +res = []; +res.freq = freq.freq; +res.time = freq.time; + +if isfield(freq, 'fourierspctrm') + if ndims(freq.fourierspctrm) == 4 && size(freq.fourierspctrm, 1)>1 + res.pow = spm_squeeze(mean(freq.fourierspctrm.*conj(freq.fourierspctrm), 1), 1); + elseif ndims(freq.fourierspctrm) == 4 + res.fourier = spm_squeeze(freq.fourierspctrm, 1); + else + res.fourier = freq.fourierspctrm; + end +else + res.pow = freq.powspctrm; +end \ No newline at end of file diff --git a/spm_eeg_specest_hilbert.m b/spm_eeg_specest_hilbert.m new file mode 100644 index 0000000..bcb7088 --- /dev/null +++ b/spm_eeg_specest_hilbert.m @@ -0,0 +1,158 @@ +function res = spm_eeg_specest_hilbert(S, data, time) +% Plugin for spm_eeg_tf implementing spectral estimation using Hilbert transform +% FORMAT res = spm_eeg_specest_hilbert(S, data, time) +% +% S - input structure +% fields of S: +% S.subsample - factor by which to subsample the time axis (default - 1) +% S.freqres - frequency resolutions (plus-minus for each frequency, can +% be a vector with a value per frequency) +% S.frequencies - vector of frequencies +% S.order - butterworth filter order (can be a vector with a value +% per frequency) +% +% Output: +% res - +% If no input is provided the plugin returns a cfg branch for itself +% +% If input is provided: +% res.fourier - the complex output of wavelet transform +% res.time - time axis +% res.freq - frequency axis +%______________________________________________________________________________________ +% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging + +% Vladimir Litvak based on the code contributed by Krish Singh +% $Id: spm_eeg_specest_hilbert.m 3742 2010-03-02 15:15:43Z vladimir $ + + +%-This part if for creating a config branch that plugs into spm_cfg_eeg_tf +% Any parameters can be specified and they are then passed to the plugin +% when it's called. +%-------------------------------------------------------------------------- +if nargin == 0 + subsample = cfg_entry; + subsample.tag = 'subsample'; + subsample.name = 'Subsample'; + subsample.strtype = 'n'; + subsample.num = [1 1]; + subsample.val = {1}; + subsample.help = {'Set to N to subsample the time axis to every Nth sample (to reduce the dataset size).'}; + + freqres = cfg_entry; + freqres.tag = 'freqres'; + freqres.name = 'Frequency resolution'; + freqres.strtype = 'r'; + freqres.num = [1 Inf]; + freqres.val = {0.5}; + freqres.help = {'Frequency resolution.',... + 'Note: 1 Hz resolution means plus-minus 1 Hz, i.e. 2 Hz badwidth',... + 'Either a single value or a vector of the same length as frequencies can be input'}; + + order = cfg_entry; + order.tag = 'order'; + order.name = 'Filter order'; + order.strtype = 'n'; + order.num = [1 Inf]; + order.val = {3}; + order.help = {'Butterworth filter order',... + 'Either a single value or a vector of the same length as frequencies can be input'}; + + hilbert = cfg_branch; + hilbert.tag = 'hilbert'; + hilbert.name = 'Hilbert transform'; + hilbert.val = {freqres, order, subsample}; + + res = hilbert; + + return +elseif nargin < 3 + error('Three input arguments are required'); +end + +%-Defaults +%-------------------------------------------------------------------------- +if ~isfield(S, 'subsample') + S.subsample = 1; +end + +dt = time(end) - time(1); + +if ~isfield(S, 'frequencies') || isempty(S.frequencies) + S.frequencies = (1/dt):max(1/dt, floor(dt)/dt):48; +end + +if ~isfield(S, 'freqres') + S.freqres = max(1/dt, floor(dt)/dt); +end + +if length(S.freqres) == 1 + freqres = S.freqres*ones(1, length(S.frequencies)); +elseif length(S.freqres) == length(S.frequencies) + freqres = S.freqres; +else + error('Frequency resolution should be either a scalar or a vector the same length as the number of frequencies.') +end + +if ~isfield(S, 'order') + S.order = 3; +end + +if length(S.order) == 1 + order = S.order*ones(1, length(S.frequencies)); +elseif length(S.order) == length(S.frequencies) + order = S.order; +else + error('Filter order should be either a scalar or a vector the same length as the number of frequencies.') +end + +%-Data dimensions +%-------------------------------------------------------------------------- +Nchannels = size(data, 1); +Nsamples = size(data, 2); +Nfrequencies = length(S.frequencies); + +fsample = 1./diff(time(1:2)); + +%-Initialize output struct +%-------------------------------------------------------------------------- +res = []; +res.freq = S.frequencies; +res.time = time(1:S.subsample:end); +res.fourier = zeros(Nchannels, Nfrequencies, length(res.time)); + +%-Compute wavelet transform +%-------------------------------------------------------------------------- +for j = 1:Nchannels + for i = 1:Nfrequencies + highpass = S.frequencies(i) + freqres(i); + lowpass = S.frequencies(i) - freqres(i); + + if highpass < 1/dt + error(sprintf('Frequency %f.2 Hz is too low to be estimated from data segment of %f.3 sec.', S.frequencies(i), dt)); + elseif lowpass < 1/dt + padding = floor(fsample./highpass); + else + padding = floor(fsample./lowpass); + end + + ind = [padding:-1:2 1:Nsamples (Nsamples-1):-1:(Nsamples-padding)]; + + tmp = data(j, ind); + + if lowpass < 1/dt + tmp = ft_preproc_lowpassfilter(tmp, fsample, highpass, order(i)); + else + tmp = ft_preproc_bandpassfilter(tmp, fsample, [lowpass highpass], order(i)); + end + + tmp = spm_hilbert(tmp); + + % remove padding + tmp = tmp(padding:(padding+Nsamples-1)); + + tmp = tmp(1:S.subsample:end); + + res.fourier(j, i, :) = tmp; + end +end diff --git a/spm_eeg_specest_morlet.m b/spm_eeg_specest_morlet.m new file mode 100644 index 0000000..2cb7e63 --- /dev/null +++ b/spm_eeg_specest_morlet.m @@ -0,0 +1,126 @@ +function res = spm_eeg_specest_morlet(S, data, time) +% Plugin for spm_eeg_tf implementing Morlet wavelet transform +% FORMAT res = spm_eeg_specest_morlet(S, data, time) +% +% S - input structure +% fields of S: +% S.subsample - factor by which to subsample the time axis (default - 1) +% either +% S.ncycles - Morlet wavelet factor (default - 7) +% or +% S.timeres - Fixed time window length in ms +% +% S.frequencies - vector of frequencies (default - 0-48) at optimal frequency bins +% +% Output: +% res - +% If no input is provided the plugin returns a cfg branch for itself +% +% If input is provided: +% res.fourier - the complex output of wavelet transform +% res.time - time axis +% res.freq - frequency axis +%______________________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Vladimir Litvak based on the code from Stefan Kiebel and Will Penny +% $Id: spm_eeg_specest_morlet.m 3749 2010-03-04 13:17:17Z vladimir $ + + +%-This part if for creating a config branch that plugs into spm_cfg_eeg_tf +% Any parameters can be specified and they are then passed to the plugin +% when it's called. +%-------------------------------------------------------------------------- +if nargin == 0 + subsample = cfg_entry; + subsample.tag = 'subsample'; + subsample.name = 'Subsample'; + subsample.strtype = 'n'; + subsample.num = [1 1]; + subsample.val = {1}; + subsample.help = {'Set to N to subsample the time axis to every Nth sample (to reduce the dataset size).'}; + + ncycles = cfg_entry; + ncycles.tag = 'ncycles'; + ncycles.name = 'Number of wavelet cycles'; + ncycles.strtype = 'n'; + ncycles.num = [1 1]; + ncycles.val = {7}; + ncycles.help = {'Number of wavelet cycles (a.k.a. Morlet wavelet factor)',... + 'This parameter controls the time-frequency trade-off',... + 'Increasing it increases the frequency resolution at the expense of time resolution.'}; + + timeres = cfg_entry; + timeres.tag = 'timeres'; + timeres.name = 'Fixed time window length'; + timeres.strtype = 'r'; + timeres.num = [1 1]; + timeres.val = {0}; + timeres.help = {'Fixed time window for all frequencies.',... + 'Specify time window length in ms.',... + 'Default valued of 0 specifies variable time window length'}; + + + morlet = cfg_branch; + morlet.tag = 'morlet'; + morlet.name = 'Morlet wavelet transform'; + morlet.val = {ncycles, timeres, subsample}; + + res = morlet; + + return +elseif nargin < 3 + error('Three input arguments are required'); +end + +%-Defaults +%-------------------------------------------------------------------------- +if ~isfield(S, 'subsample') + S.subsample = 1; +end + +if ~isfield(S, 'ncycles') + S.ncycles = 7; +end + +dt = time(end) - time(1); + +if ~isfield(S, 'frequencies') || isempty(S.frequencies) + S.frequencies = (1/dt):max(1/dt, floor(dt)/dt):48; +end + +%-Generate wavelets +%-------------------------------------------------------------------------- +if ~isfield(S, 'timeres') || (S.timeres == 0) + M = spm_eeg_morlet(S.ncycles, 1000*diff(time(1:2)), S.frequencies); +else + M = spm_eeg_morlet(S.ncycles, 1000*diff(time(1:2)), S.frequencies, 1000./S.timeres); +end + +%-Data dimensions +%-------------------------------------------------------------------------- +Nchannels = size(data, 1); +Nsamples = size(data, 2); +Nfrequencies = numel(M); + +%-Initialize output struct +%-------------------------------------------------------------------------- +res = []; +res.freq = S.frequencies; +res.time = time(1:S.subsample:end); +res.fourier = zeros(Nchannels, Nfrequencies, length(res.time)); + +%-Compute wavelet transform +%-------------------------------------------------------------------------- +for j = 1:Nchannels + for i = 1:Nfrequencies + tmp = conv(data(j, :), M{i}); + + % time shift to remove delay + tmp = tmp([1:Nsamples] + (length(M{i})-1)/2); + + tmp = tmp(1:S.subsample:end); + + res.fourier(j, i, :) = tmp; + end +end diff --git a/spm_eeg_specest_mtmspec.m b/spm_eeg_specest_mtmspec.m new file mode 100644 index 0000000..26ffe8b --- /dev/null +++ b/spm_eeg_specest_mtmspec.m @@ -0,0 +1,114 @@ +function res = spm_eeg_specest_mtmspec(S, data, time) +% Plugin for spm_eeg_tf using SPM implementation of multitaper method +% FORMAT res = spm_eeg_specest_mtmspec(S, data, time) +% +% S - input structure +% fields of S: +% S.taper - taper to use ('hanning', 'rectwin', 'dpss', 'sine' or +% other possible inputs of 'window' +% S.freqres - frequency resolutions (plus-minus for each frequency, can +% be a vector with a value per frequency) +% S.frequencies - vector of frequencies +% S.timeres - time resolution in ms (length of the sliding time-window) +% S.timestep - time step (in ms) to slide the time-window by. +% +% Output: +% res - +% If no input is provided the plugin returns a cfg branch for itself +% +% If input is provided: +% res.fourier - the complex output of wavelet transform (in the case +% of single taper) +% res.pow - power (in case of multiple tapers, phase is not computed) +% res.time - time axis +% res.freq - frequency axis +%______________________________________________________________________________________ +% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging + +% Vladimir Litvak based on the code contributed by Krish Singh +% $Id: spm_eeg_specest_mtmspec.m 3876 2010-05-07 18:51:03Z vladimir $ + + +%-This part if for creating a config branch that plugs into spm_cfg_eeg_tf +% Any parameters can be specified and they are then passed to the plugin +% when it's called. +%-------------------------------------------------------------------------- +if nargin == 0 + timeres = cfg_entry; + timeres.tag = 'timeres'; + timeres.name = 'Time resolution'; + timeres.strtype = 'r'; + timeres.num = [1 1]; + timeres.val = {400}; + timeres.help = {'Length of the sliding time window (in ms)'}; + + timestep = cfg_entry; + timestep.tag = 'timestep'; + timestep.name = 'Time step'; + timestep.strtype = 'r'; + timestep.num = [1 1]; + timestep.val = {50}; + timestep.help = {'Step to slide the time window by (in ms)'}; + + bandwidth = cfg_entry; + bandwidth.tag = 'bandwidth'; + bandwidth.name = 'Time bandwidth'; + bandwidth.strtype = 'n'; + bandwidth.num = [1 1]; + bandwidth.val = {3}; + bandwidth.help = {'Time bandwidth parameter (e.g. 3 or 4)'}; + + mtmspec = cfg_branch; + mtmspec.tag = 'mtmspec'; + mtmspec.name = 'SPM multitaper'; + mtmspec.val = {timeres, timestep, bandwidth}; + + res = mtmspec; + + return +elseif nargin < 3 + error('Three input arguments are required'); +end + +%-Defaults +%-------------------------------------------------------------------------- +if ~isfield(S, 'timeres') + S.timeres = 400; +end + +if ~isfield(S, 'timestep') + S.timestep = 50; +end + +if ~isfield(S, 'bandwidth') + S.bandwidth = 3; +end + +%-Data dimensions +%-------------------------------------------------------------------------- +fsample = 1./diff(time(1:2)); + +timeres = 1e-3*S.timeres; +timestep = 1e-3*S.timestep; + +if timestep>timeres + error('Time resolution should exceed time step'); +end + +%-Do the spectral analysis +%-------------------------------------------------------------------------- +res = []; +[p, f, t] = spm_mmtspec(data', fsample, S.frequencies, timeres, timestep, S.bandwidth); + +if size(data, 1) == 1 + res.pow = shiftdim(p, -1); +else + res.pow = permute(p, [3 1 2]); +end + +res.freq = f; + +dt = (time(end)-time(1))./length(t); + +res.time = (time(1)+dt/2):dt:time(end); + diff --git a/spm_eeg_tf.m b/spm_eeg_tf.m index 1e947d1..2f34ec9 100644 --- a/spm_eeg_tf.m +++ b/spm_eeg_tf.m @@ -1,235 +1,190 @@ -function [Dtf, Dtf2] = spm_eeg_tf(S) +function [Dtf, Dtph] = spm_eeg_tf(S) % Compute instantaneous power and phase in peri-stimulus time and frequency -% FORMAT [Dtf, Dtf2] = spm_eeg_tf(S) +% FORMAT [Dtf, Dtph] = spm_eeg_tf(S) % -% S - input structure (optional) -% (optional) fields of S: -% S.D - MEEG object or filename of M/EEG mat-file -% S.tf - structure with (optional) fields: -% S.tf.frequencies - vector of frequencies (Hz) -% S.tf.Mfactor - Morlet wavelet factor -% S.tf.channels - vector of channel indices for which to compute TF -% S.tf.phase - compute phase (yes/no: 1/0) -% S.tf.pow - compute power/magnitude: 1/0 [default: power] -% S.tf.collchans - collapse channels (yes/no: 1/0). Will average -% power over channels after power estimation. -% THIS OPTION HAS BEEN TEMPORARILY SWITCHED OFF. -% -% Dtf - MEEG object with power data (also written to disk) -% Dtf2 - MEEG object with phase data (also written to disk) -% if S.tf.phase == 1, empty array if not +% S - input structure +% +% fields of S: +% S.D - MEEG object or filename of M/EEG mat-file with +% +% S.channels - cell array of channel names. Can include generic +% wildcards: 'All', 'EEG', 'MEG' etc. +% +% S.frequencies - vector of frequencies of interest +% +% S.timewin - time window of interest in PST in ms. +% +% S.method - name for the spectral estimation to use. This +% corresponds to the name of a plug-in function that comes +% after 'spm_eeg_specest_' prefix. +% S.settings - plug-in specific settings +% +% S.phase - also save phase dataset (1) or not (0) +% phase dataset cannot be computed for some +% spectral estimation methods +% Output: +% Dtf - M/EEG object with power (also written on disk) +% Dtph - M/EEG object with phase (also written on disk) %__________________________________________________________________________ +% This is a modular function for which plugins can be developed implementing +% specific spectral estimation methods. There are 3 basic plugins presently +% implemented and they can be used as templates for new plugins. +% The name of a plugin function should start with 'spm_eeg_specest_' +% +% morlet (spm_eeg_specest_morlet) - Morlet wavelet transform +% +% hilbert (spm_eeg_specest_hilbert) - filtering + Hilbert transform % -% spm_eeg_tf estimates instantaneous power and phase of data using the -% continuous Morlet wavelet transform. +% ft_mtmconvol (spm_eeg_specest_ft_mtmconvol) - Fieldtrip implementation +% of multi-taper spectral +% analysis %__________________________________________________________________________ -% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging +% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging -% Stefan Kiebel -% $Id: spm_eeg_tf.m 3497 2009-10-21 21:54:28Z vladimir $ +% Vladimir Litvak +% $Id: spm_eeg_tf.m 3842 2010-04-27 15:09:48Z vladimir $ -SVNrev = '$Rev: 3497 $'; +SVNrev = '$Rev: 3842 $'; %-Startup %-------------------------------------------------------------------------- spm('FnBanner', mfilename, SVNrev); spm('FigName','M/EEG Time-Frequency'); spm('Pointer','Watch'); +if nargin == 0 + S = []; +end + +%-Ensure backward compatibility +%-------------------------------------------------------------------------- +S = spm_eeg_compatibility(S, mfilename); + %-Get MEEG object %-------------------------------------------------------------------------- try D = S.D; catch [D, sts] = spm_select(1, 'mat', 'Select M/EEG mat file'); - if ~sts, Dtf = []; Dtf2 = []; return; end + if ~sts, D = []; return; end S.D = D; end D = spm_eeg_load(D); -%-Get parameters -%-------------------------------------------------------------------------- -try - tf.frequencies = S.tf.frequencies; -catch - tf.frequencies = ... - spm_input('Frequencies (Hz)', '+1', 'r', '', [1, inf]); - S.tf.frequencies = tf.frequencies; +if isequal(D.type, 'continuous') + error('Time-frequency analysis can only be applied to epoched data'); end -try - tf.Mfactor = S.tf.Mfactor; -catch - tf.Mfactor = ... - spm_input('Which Morlet wavelet factor?', '+1', 'r', '7', 1); - S.tf.Mfactor = tf.Mfactor; +%-Configure the analysis +%-------------------------------------------------------------------------- +if ~isfield(S, 'channels') + S.channels = 'all'; end -try - tf.channels = S.tf.channels; -catch - meegchan = D.meegchannels; - [selection, ok]= listdlg('ListString', D.chanlabels(meegchan), 'SelectionMode', 'multiple' ,'Name', 'Select channels' , 'ListSize', [400 300]); - if ~ok - return; - end - - tf.channels = meegchan(selection); - S.tf.channels = tf.channels; -end +chanind = D.selectchannels(S.channels); -try - tf.phase = S.tf.phase; -catch - tf.phase = ... - spm_input('Compute phase?', '+1', 'y/n', [1,0], 2); - S.tf.phase = tf.phase; +if isempty(chanind) + error('No channels selected.'); end -try - tf.pow = S.tf.pow; -catch - tf.pow = 1; - S.tf.pow = tf.pow; +if ~isfield(S, 'frequencies') + S.frequencies = 1:48; end -% if length(tf.channels) > 1 -% try -% tf.collchans = S.tf.collchans; % 1 = collapse across channels, 0 = do not -% catch -% tf.collchans = spm_input('Collapse channels?', '+1', 'y/n', [1,0], 2); -% S.tf.collchans = tf.collchans; -% end -% else -% tf.collchans = 0; -% end - -%-Generate Morlet wavelets -%-------------------------------------------------------------------------- -M = spm_eeg_morlet(tf.Mfactor, 1000/D.fsample, tf.frequencies); - -% if tf.collchans -% Nchannels = 1; -% else - Nchannels = length(tf.channels); -% end - -Nfrequencies = length(tf.frequencies); - -Dtf = clone(D, ['tf1_' D.fnamedat], [Nchannels Nfrequencies D.nsamples D.ntrials]); -Dtf = Dtf.frequencies(:, tf.frequencies); +if ~isfield(S, 'timewin') + S.timewin = 1e3*[D.time(1) D.time(end)]; +end -% fix all channels -sD = struct(Dtf); +timeind = D.indsample(1e-3*min(S.timewin)):D.indsample(1e-3*max(S.timewin)); -for i = 1:length(tf.channels) - lbl = D.chanlabels(tf.channels(i)); - sD.channels(i).label = lbl{1}; - - if D.badchannels(tf.channels(i)) - sD.channels(i).bad = 1; - end - ctype = D.chantype(tf.channels(i)); - sD.channels(i).type = ctype{1}; - % units? +if ~isfield(S, 'method') + S.method = 'morlet'; + S.settings = []; +end +if ~isfield(S, 'phase') + S.phase = 0; end -Dtf = meeg(sD); -Dtf = coor2D(Dtf, [1:length(tf.channels)], coor2D(D,tf.channels)); -if tf.phase == 1 - Dtf2 = clone(D, ['tf2_' D.fnamedat], [Nchannels Nfrequencies D.nsamples D.ntrials]); - Dtf2 = Dtf2.frequencies(:, tf.frequencies); - Dtf2 = transformtype(Dtf2, 'TFphase'); - - % fix all channels - sD = struct(Dtf2); - - for i = 1:length(tf.channels) - lbl = D.chanlabels(tf.channels(i)); - sD.channels(i).label = lbl{1}; - if D.badchannels(tf.channels(i)) - sD.channels(i).bad = 1; - end - ctype = D.chantype(tf.channels(i)); - sD.channels(i).type = ctype{1}; - % units? - end - Dtf2 = meeg(sD); - Dtf2 = coor2D(Dtf2, [1:length(tf.channels)], coor2D(D,tf.channels)); +if isfield(S, 'settings') + S1 = S.settings; else - Dtf2 = []; + S1 = []; end +S1.frequencies = S.frequencies; +%-Run the analysis on all trials +%-------------------------------------------------------------------------- spm_progress_bar('Init', D.ntrials, 'trials done'); if D.ntrials > 100, Ibar = floor(linspace(1, D.ntrials, 100)); -else Ibar = [1:D.ntrials]; end +else Ibar = 1:D.ntrials; end for k = 1:D.ntrials - - d = zeros(length(tf.channels), Nfrequencies, D.nsamples); - - if tf.phase - d2 = zeros(length(tf.channels), Nfrequencies, D.nsamples); - end - - indat = squeeze(D(:, :, k)); - for j = 1:length(tf.channels) - for i = 1 : Nfrequencies - tmp = conv(indat(tf.channels(j), :), M{i}); - - % time shift to remove delay - tmp = tmp([1:D.nsamples] + (length(M{i})-1)/2); - - % power - if tf.pow - d(j, i, :) = tmp.*conj(tmp); - else - d(j, i, :) = abs(tmp); - end - - % phase - if tf.phase - d2(j, i, :) = angle(tmp); + trial = feval(['spm_eeg_specest_' S.method], S1, D(chanind, timeind, k), D.time(timeind)); + + if k == 1 + + if isfield(trial, 'fourier') + outdata = trial.fourier; + else + outdata = trial.pow; + end + + Nchannels = size(outdata, 1); + Nfrequencies = size(outdata, 2); + Nsamples = size(outdata, 3); + + %-Generate output datasets + %-------------------------------------------------------------------------- + Dtf = clone(D, ['tf_' D.fnamedat], [Nchannels Nfrequencies Nsamples D.ntrials]); + Dtf = Dtf.frequencies(:, trial.freq); + Dtf = timeonset(Dtf, trial.time(1)); + Dtf = fsample(Dtf, 1/diff(trial.time(1:2))); + Dtf = transformtype(Dtf, 'TF'); + + Dtf = chanlabels(Dtf, 1:Nchannels, D.chanlabels(chanind)); + Dtf = badchannels(Dtf, 1:Nchannels, D.badchannels(chanind)); + Dtf = chantype(Dtf, 1:Nchannels, D.chantype(chanind)); + Dtf = coor2D(Dtf, 1:Nchannels, coor2D(D,chanind)); + + if S.phase && isfield(trial, 'fourier') + Dtph = clone(Dtf, ['tph_' D.fnamedat]); + Dtph = transformtype(Dtph, 'TFphase'); + else + if ~isfield(trial, 'fourier') + warning('Phase cannot be estimated with the requested method. Estimating power only.'); end - + + Dtph = []; end + end - -% if tf.collchans -% d = mean(d, 1); -% -% if tf.phase -% if tf.circularise -% tmp = cos(d2) + sqrt(-1)*sin(d2); -% d2 = double(abs(mean(tmp,1))./mean(abs(tmp),1)); -% else -% d2 = mean(d2,1); -% end -% end -% end - - Dtf(:, :, :, k) = d; - - if tf.phase - Dtf2(:, :, :, k) = d2; + + if isfield(trial, 'fourier') + Dtf(:, :, :, k) = trial.fourier.*conj(trial.fourier); + + if S.phase + Dtph(:, :, :, k) = angle(trial.fourier); + end + elseif isfield(trial, 'pow') + Dtf(:, :, :, k) = trial.pow; + else + error('The plug-in returned unexpected output'); end - + if ismember(k, Ibar), spm_progress_bar('Set', k); end - end spm_progress_bar('Clear'); - -%-Save new M/EEG dataset +%-Save new M/EEG dataset(s) %-------------------------------------------------------------------------- Dtf = Dtf.history('spm_eeg_tf', S); save(Dtf); -if tf.phase - Dtf2 = Dtf2.history('spm_eeg_tf', S); - save(Dtf2); +if ~isempty(Dtph) + Dtph = Dtph.history('spm_eeg_tf', S); + save(Dtph); end %-Cleanup diff --git a/spm_eeg_tf5.m b/spm_eeg_tf5.m new file mode 100644 index 0000000..fb14a31 --- /dev/null +++ b/spm_eeg_tf5.m @@ -0,0 +1,214 @@ +function [Dtf, Dtf2] = spm_eeg_tf(S) +% Compute instantaneous power and phase in peri-stimulus time and frequency +% FORMAT [Dtf, Dtf2] = spm_eeg_tf(S) +% +% S - input structure (optional) +% (optional) fields of S: +% S.D - MEEG object or filename of M/EEG mat-file +% S.tf - structure with (optional) fields: +% S.tf.frequencies - vector of frequencies (Hz) +% S.tf.Mfactor - Morlet wavelet factor +% S.tf.channels - vector of channel indices for which to compute TF +% S.tf.phase - compute phase (yes/no: 1/0) +% S.tf.pow - compute power/magnitude: 1/0 [default: power] +% S.tf.collchans - collapse channels (yes/no: 1/0). Will average +% power over channels after power estimation. +% THIS OPTION HAS BEEN TEMPORARILY SWITCHED OFF. +% +% Dtf - MEEG object with power data (also written to disk) +% Dtf2 - MEEG object with phase data (also written to disk) +% if S.tf.phase == 1, empty array if not +%__________________________________________________________________________ +% +% spm_eeg_tf estimates instantaneous power and phase of data using the +% continuous Morlet wavelet transform. +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Stefan Kiebel +% $Id: spm_eeg_tf5.m 3742 2010-03-02 15:15:43Z vladimir $ + +SVNrev = '$Rev: 3742 $'; + +%-Startup +%-------------------------------------------------------------------------- +spm('FnBanner', mfilename, SVNrev); +spm('FigName','M/EEG Time-Frequency'); spm('Pointer','Watch'); + +%-Get MEEG object +%-------------------------------------------------------------------------- +try + D = S.D; +catch + [D, sts] = spm_select(1, 'mat', 'Select M/EEG mat file'); + if ~sts, Dtf = []; Dtf2 = []; return; end + S.D = D; +end + +D = spm_eeg_load(D); + +%-Get parameters +%-------------------------------------------------------------------------- +try + tf.frequencies = S.tf.frequencies; +catch + tf.frequencies = ... + spm_input('Frequencies (Hz)', '+1', 'r', '', [1, inf]); + S.tf.frequencies = tf.frequencies; +end + +try + tf.Mfactor = S.tf.Mfactor; +catch + tf.Mfactor = ... + spm_input('Which Morlet wavelet factor?', '+1', 'r', '7', 1); + S.tf.Mfactor = tf.Mfactor; +end + +try + tf.channels = S.tf.channels; +catch + meegchan = D.meegchannels; + [selection, ok]= listdlg('ListString', D.chanlabels(meegchan), 'SelectionMode', 'multiple' ,'Name', 'Select channels' , 'ListSize', [400 300]); + if ~ok + return; + end + + tf.channels = meegchan(selection); + S.tf.channels = tf.channels; +end + +try + tf.phase = S.tf.phase; +catch + tf.phase = ... + spm_input('Compute phase?', '+1', 'y/n', [1,0], 2); + S.tf.phase = tf.phase; +end + +try + tf.pow = S.tf.pow; +catch + tf.pow = 1; + S.tf.pow = tf.pow; +end + +% if length(tf.channels) > 1 +% try +% tf.collchans = S.tf.collchans; % 1 = collapse across channels, 0 = do not +% catch +% tf.collchans = spm_input('Collapse channels?', '+1', 'y/n', [1,0], 2); +% S.tf.collchans = tf.collchans; +% end +% else +% tf.collchans = 0; +% end + +%-Generate Morlet wavelets +%-------------------------------------------------------------------------- +M = spm_eeg_morlet(tf.Mfactor, 1000/D.fsample, tf.frequencies); + +% if tf.collchans +% Nchannels = 1; +% else + Nchannels = length(tf.channels); +% end + +Nfrequencies = length(tf.frequencies); + +Dtf = clone(D, ['tf1_' D.fnamedat], [Nchannels Nfrequencies D.nsamples D.ntrials]); +Dtf = Dtf.frequencies(:, tf.frequencies); +Dtf = transformtype(Dtf, 'TF'); + +Dtf = chanlabels(Dtf, [1:length(tf.channels)], D.chanlabels(tf.channels)); +Dtf = badchannels(Dtf, [1:length(tf.channels)], D.badchannels(tf.channels)); +Dtf = chantype(Dtf, [1:length(tf.channels)], D.chantype(tf.channels)); +Dtf = coor2D(Dtf, [1:length(tf.channels)], coor2D(D,tf.channels)); + +if tf.phase == 1 + Dtf2 = clone(D, ['tf2_' D.fnamedat], [Nchannels Nfrequencies D.nsamples D.ntrials]); + Dtf2 = Dtf2.frequencies(:, tf.frequencies); + Dtf2 = transformtype(Dtf2, 'TFphase'); + + Dtf2 = chanlabels(Dtf2, [1:length(tf.channels)], D.chanlabels(tf.channels)); + Dtf2 = badchannels(Dtf2, [1:length(tf.channels)], D.badchannels(tf.channels)); + Dtf2 = chantype(Dtf2, [1:length(tf.channels)], D.chantype(tf.channels)); + Dtf2 = coor2D(Dtf2, [1:length(tf.channels)], coor2D(D,tf.channels)); +else + Dtf2 = []; +end + + +spm_progress_bar('Init', D.ntrials, 'trials done'); +if D.ntrials > 100, Ibar = floor(linspace(1, D.ntrials, 100)); +else Ibar = [1:D.ntrials]; end + +for k = 1:D.ntrials + + d = zeros(length(tf.channels), Nfrequencies, D.nsamples); + + if tf.phase + d2 = zeros(length(tf.channels), Nfrequencies, D.nsamples); + end + + indat = squeeze(D(:, :, k)); + for j = 1:length(tf.channels) + for i = 1 : Nfrequencies + tmp = conv(indat(tf.channels(j), :), M{i}); + + % time shift to remove delay + tmp = tmp([1:D.nsamples] + (length(M{i})-1)/2); + + % power + if tf.pow + d(j, i, :) = tmp.*conj(tmp); + else + d(j, i, :) = abs(tmp); + end + + % phase + if tf.phase + d2(j, i, :) = angle(tmp); + end + + end + end + +% if tf.collchans +% d = mean(d, 1); +% +% if tf.phase +% if tf.circularise +% tmp = cos(d2) + sqrt(-1)*sin(d2); +% d2 = double(abs(mean(tmp,1))./mean(abs(tmp),1)); +% else +% d2 = mean(d2,1); +% end +% end +% end + + Dtf(:, :, :, k) = d; + + if tf.phase + Dtf2(:, :, :, k) = d2; + end + + if ismember(k, Ibar), spm_progress_bar('Set', k); end + +end + +spm_progress_bar('Clear'); + + +%-Save new M/EEG dataset +%-------------------------------------------------------------------------- +Dtf = Dtf.history('spm_eeg_tf', S); +save(Dtf); +if tf.phase + Dtf2 = Dtf2.history('spm_eeg_tf', S); + save(Dtf2); +end + +%-Cleanup +%-------------------------------------------------------------------------- +spm('FigName','M/EEG Time Frequency: done'); spm('Pointer','Arrow'); diff --git a/spm_eeg_tf_rescale.m b/spm_eeg_tf_rescale.m index 8d6c1f5..46e65f1 100644 --- a/spm_eeg_tf_rescale.m +++ b/spm_eeg_tf_rescale.m @@ -9,6 +9,8 @@ % S.tf.method - 'LogR', 'Diff', 'Rel', 'Log', 'Sqrt' % S.tf.Sbaseline - 2-element vector: start and stop of baseline % (need to specify this for LogR and Diff) +% S.tf.Db - MEEG object or filename of M/EEG mat-file to use +% for the baseline (if different from the input dataset). % % D - MEEG object with rescaled power data (also % written to disk with prefix r) @@ -21,9 +23,9 @@ % Copyright (C) 2009 Wellcome Trust Centre for Neuroimaging % Will Penny -% $Id: spm_eeg_tf_rescale.m 3622 2009-12-09 09:36:39Z vladimir $ +% $Id: spm_eeg_tf_rescale.m 3938 2010-06-18 15:03:28Z vladimir $ -SVNrev = '$Rev: 3622 $'; +SVNrev = '$Rev: 3938 $'; %-Startup %-------------------------------------------------------------------------- @@ -58,16 +60,39 @@ case {'logr','diff', 'rel'} try S.tf.Sbaseline; - catch + catch + if spm_input('Baseline dataset','+1','b',{'Same|Different'},[0 1],0) + [Db, sts] = spm_select(1, 'mat', 'Select baseline M/EEG mat file'); + if ~sts, return; end + S.tf.Db = Db; + else + S.tf.Db = []; + end + tmp_base = spm_input('Start and stop of baseline [ms]', '+1', 'i', '', 2); S.tf.Sbaseline = tmp_base/1000; end + + if isfield(S.tf, 'Db') && ~isempty(S.tf.Db) + Db = spm_eeg_load(S.tf.Db); + else + Db = Din; + end + + if any(abs(Din.frequencies-Db.frequencies)>0.1) || ~isequal(Db.chanlabels, Din.chanlabels) ||... + (Db.ntrials>1 && (Db.ntrials~=Din.ntrials)) + error('The input dataset and the baseline dataset should have the same frequencies, channels and trial numbers'); + end + for c=1:D.ntrials inds=find(tims>=S.tf.Sbaseline(1) & tims<=S.tf.Sbaseline(2)); - % reshape instead of squeeze as there may be other singleton - % dimensions - x=reshape(Din(:,:,:,c), size(Din, [1:3])); - xbase=mean(x(:,:,inds),3); + x=spm_squeeze(Din(:,:,:,c), 4); + if Db.ntrials > 1 + xbase=spm_squeeze(Db(:,:,:,c), 4); + else + xbase=spm_squeeze(Db(:,:,:,1), 4); + end + xbase=mean(xbase(:,:,inds),3); switch lower(S.tf.method) case 'logr' x=log10(x); diff --git a/spm_eeg_weight_epochs.m b/spm_eeg_weight_epochs.m index 5b52654..4430869 100644 --- a/spm_eeg_weight_epochs.m +++ b/spm_eeg_weight_epochs.m @@ -28,9 +28,9 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Stefan Kiebel, Rik Henson -% $Id: spm_eeg_weight_epochs.m 3209 2009-06-17 11:07:47Z vladimir $ +% $Id: spm_eeg_weight_epochs.m 3895 2010-05-20 11:43:57Z vladimir $ -SVNrev = '$Rev: 3209 $'; +SVNrev = '$Rev: 3895 $'; %-Startup %-------------------------------------------------------------------------- @@ -69,6 +69,11 @@ c = S.c; Ncontrasts = size(c, 1); +% Pad with zeros as in the contrast manager +if size(c, 2) < D.ntrials + c = [c zeros(Ncontrasts, D.ntrials - size(c, 2))]; +end + if ~isempty(D.repl) try WeightAve = S.WeightAve; diff --git a/spm_eeg_wrap_dipfit_vbecd.m b/spm_eeg_wrap_dipfit_vbecd.m index dd1a4ee..044eaaa 100644 --- a/spm_eeg_wrap_dipfit_vbecd.m +++ b/spm_eeg_wrap_dipfit_vbecd.m @@ -7,13 +7,13 @@ % P contains a list of the free parameters (assuming all position % parameters come first (in triplets) followed by all moment paameters % (also in triplets) -% U is unused +% U is unused % At the moment this removes the mean level from EEG data -% and reduces the rank of the MEG leadfield 2 dimensions. +% and reduces the rank of the MEG leadfield 2 dimensions. % Copyright (C) 2009 Wellcome Trust Centre for Neuroimaging -% -% $Id: spm_eeg_wrap_dipfit_vbecd.m 3372 2009-09-08 14:33:45Z gareth $ +% +% $Id: spm_eeg_wrap_dipfit_vbecd.m 3908 2010-06-01 11:06:53Z gareth $ x=U.u; %% input , unused @@ -39,25 +39,30 @@ for i=1:Ndips, pos=allpos(i,:); - mom=allmom(i,:); + mom=allmom(i,:)./1000; %% SCALE BACK FROM SIMILAR UNITS TO LOCATION; % mean correction of LF, only for EEG data. - if forwinv_senstype(sens, 'eeg') - [tmp] = forwinv_compute_leadfield(pos, sens, vol); + if ft_senstype(sens, 'eeg') + [tmp] = ft_compute_leadfield(pos, sens, vol); tmp = tmp - repmat(mean(tmp), size(tmp,1), 1); %% should this be here ? else %% reduce rank of leadfield for MEG- assume one direction (radial) is silent - [tmp] = forwinv_compute_leadfield(pos, sens, vol,'reducerank',MEGRANK); + [tmp] = ft_compute_leadfield(pos, sens, vol,'reducerank',MEGRANK); + if isfield(vol, 'type') && strcmp(vol.type,'nolte'), + %% this is a temp fix to make up for scaling changes in nolte + %% model + tmp=tmp.*1e-10; + end; end - gmn=tmp; + gmn=tmp; y=y+gmn*mom'; - outside = outside+ ~forwinv_inside_vol(pos,vol); + outside = outside+ ~ft_inside_vol(pos,vol); end; % for i y=y*M.sc_y; %% scale data appropriately if outside y=y.^2; - end; % penalise sources outside head +end; % penalise sources outside head diff --git a/spm_eeval.m b/spm_eeval.m index 0d08c87..0647d18 100644 --- a/spm_eeval.m +++ b/spm_eeval.m @@ -52,7 +52,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Andrew Holmes -% $Id: spm_eeval.m 2696 2009-02-05 20:29:48Z guillaume $ +% $Id: spm_eeval.m 3756 2010-03-05 18:43:37Z guillaume $ if nargin<4, m=[]; end @@ -143,7 +143,7 @@ msg = ''; i=i(:)'; if ischar(i) - if i(1)=='0' & all(ismember(unique(i(:)),setstr(abs('0'):abs('9')))) + if i(1)=='0' & all(ismember(unique(i(:)),char(abs('0'):abs('9')))) %-Leading zeros in a digit list msg = sprintf('%s expanded',i); z = min(find([diff(i=='0'),1])); @@ -157,7 +157,7 @@ if ischar(i) %-Evaluation error from above: see if it's an 'abab' or 'a b a b' type: [c,null,i] = unique(lower(i(~isspace(i)))); - if all(ismember(c,setstr(abs('a'):abs('z')))) + if all(ismember(c,char(abs('a'):abs('z')))) %-Map characters a-z to 1-26, but let 'r' be zero (rest) tmp = c-'a'+1; tmp(tmp=='r'-'a'+1)=0; i = tmp(i); diff --git a/spm_en.m b/spm_en.m index 6dacdb1..cc3f578 100644 --- a/spm_en.m +++ b/spm_en.m @@ -1,7 +1,8 @@ -function [X] = spm_en(X) +function [X] = spm_en(X,p) % Euclidean normalization -% FORMAT [X] = spm_en(X); +% FORMAT [X] = spm_en(X,[p]); % X - matrix +% p - optional polynomial detrend [default = []] %__________________________________________________________________________ % % spm_en performs a Euclidean normalization setting the column-wise sum of @@ -10,7 +11,14 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_en.m 3113 2009-05-11 15:25:13Z karl $ +% $Id: spm_en.m 3901 2010-05-27 16:14:36Z karl $ + + +% detrend +%-------------------------------------------------------------------------- +if nargin > 1 + X = spm_detrend(X,p); +end % Euclidean normalization %-------------------------------------------------------------------------- diff --git a/spm_est_smoothness.m b/spm_est_smoothness.m index fe140a6..aa47255 100644 --- a/spm_est_smoothness.m +++ b/spm_est_smoothness.m @@ -1,15 +1,16 @@ -function [fwhm,VRpv] = spm_est_smoothness(varargin) +function [FWHM,VRpv,R] = spm_est_smoothness(V,VM,ndf) % Estimation of smoothness based on [residual] images -% FORMAT [fwhm,VRpv] = spm_est_smoothness(VResI,[VM,ndf]); +% FORMAT [FWHM,VRpv,R] = spm_est_smoothness(V,VM,[ndf]); % -% VResI - Filenames or mapped standardized residual images +% V - Filenames or mapped standardized residual images % VM - Filename of mapped mask image % ndf - A 2-vector, [n df], the original n & dof of the linear model % -% fwhm - estimated FWHM in all image directions +% FWHM - estimated FWHM in all image directions % VRpv - handle of Resels per Voxel image -%_______________________________________________________________________ -% +% R - vector of resel counts +%__________________________________________________________________________ +% % spm_est_smoothness returns a spatial smoothness estimator based on the % variances of the normalized spatial derivatives as described in K. % Worsley, (1996). Inputs are a mask image and a number of standardized @@ -17,7 +18,7 @@ % is a global estimate of the smoothness expressed as the FWHM of an % equivalent Gaussian point spread function. An estimate of resels per % voxels (see spm_spm) is written as an image file ('RPV.img') to the -% current directory. +% current directory. % % To improve the accuracy of the smoothness estimation the error degrees % of freedom can be supplied. Since it is not assumed that all residual @@ -25,41 +26,38 @@ % must be supplied as well. % % The mask image specifies voxels, used in smoothness estimation, by -% assigning them non-zero values. The dimensions, voxel sizes, orientation +% assigning them non-zero values. The dimensions, voxel sizes, orientation % of all images must be the same. The dimensions of the images can be of % dimensions 0, 1, 2 and 3. -% +% % Note that 1-dim images (lines) must exist in the 1st dimension and % 2-dim images (slices) in the first two dimensions. The estimated fwhm % for any non-existing dimension is infinity. -%_______________________________________________________________________ -% +%__________________________________________________________________________ +% % Refs: -% +% % K.J. Worsley (1996). An unbiased estimator for the roughness of a % multivariate Gaussian random field. Technical Report, Department of % Mathematics and Statistics, McGill University % % S.J. Kiebel, J.B. Poline, K.J. Friston, A.P. Holmes, and K.J. Worsley. -% Robust Smoothness Estimation in Statistical Parametric Maps Using -% Standardized Residuals from the General Linear Model. NeuroImage, +% Robust Smoothness Estimation in Statistical Parametric Maps Using +% Standardized Residuals from the General Linear Model. NeuroImage, % 10:756-766, 1999. % -% S. Hayasaka, K. Phan, I. Liberzon, K.J. Worsley, T.E .Nichols (2004). +% S. Hayasaka, K. Phan, I. Liberzon, K.J. Worsley, T.E. Nichols (2004). % Nonstationary cluster-size inference with random field and permutation % methods. NeuroImage, 22:676-687, 2004. -%_______________________________________________________________________ +%__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Stefan Kiebel, Tom Nichols -% $Id: spm_est_smoothness.m 3643 2009-12-15 16:53:34Z guillaume $ +% $Id: spm_est_smoothness.m 3960 2010-06-30 17:41:24Z ged $ %-Assign input arguments -%----------------------------------------------------------------------- -if nargin > 0, V = varargin{1}; end -if nargin > 1, VM = varargin{2}; end -if nargin > 2, ndf = varargin{3}; end +%-------------------------------------------------------------------------- if nargin > 3 spm('alert!', 'spm_est_smoothness: Wrong number of arguments'); return; @@ -72,150 +70,201 @@ end if nargin < 3, ndf = [NaN NaN]; end if length(ndf) ~= 2 - error('ndf argument must be of length 2 ([n df])') + error('ndf argument must be of length 2 ([n df])') end %-Initialise -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- if ~isstruct(V) - V = spm_vol(V); + V = spm_vol(V); end if ~isstruct(VM) - VM = spm_vol(VM); + VM = spm_vol(VM); end if any(isnan(ndf)) - ndf = [length(V) length(V)]; % Assume full df + ndf = [length(V) length(V)]; % Assume full df end -n_full = ndf(1); -edf = ndf(2); +n_full = ndf(1); +edf = ndf(2); %-Initialise RESELS per voxel image -%----------------------------------------------------------------------- -VRpv = struct('fname','RPV.img',... - 'dim', VM.dim(1:3),... - 'dt', [spm_type('float64') spm_platform('bigend')],... - 'mat', VM.mat,... - 'pinfo', [1 0 0]',... - 'descrip', 'spm_spm: resels per voxel'); -VRpv = spm_create_vol(VRpv); - +%-------------------------------------------------------------------------- +VRpv = struct( 'fname','RPV.img',... + 'dim', VM.dim(1:3),... + 'dt', [spm_type('float64') spm_platform('bigend')],... + 'mat', VM.mat,... + 'pinfo', [1 0 0]',... + 'descrip', 'spm_spm: resels per voxel'); +VRpv = spm_create_vol(VRpv); %-Dimensionality of image -%----------------------------------------------------------------------- -N = 3 - sum(VM.dim(1:3) == 1); -if N == 0 - fwhm = [Inf Inf Inf]; - return +%-------------------------------------------------------------------------- +D = 3 - sum(VM.dim(1:3) == 1); +if D == 0 + FWHM = [Inf Inf Inf]; + R = [0 0 0]; + return; end %-Find voxels within mask -%----------------------------------------------------------------------- -[x,y] = ndgrid(1:VM.dim(1), 1:VM.dim(2)); -I = []; Ix = []; Iy = []; Iz = []; -for i = 1:VM.dim(3) - z = i*ones(size(x)); - d = spm_sample_vol(VM, x, y, z, 0); - I = find(d); - Ix = [Ix; x(I)]; - Iy = [Iy; y(I)]; - Iz = [Iz; z(I)]; -end +%-------------------------------------------------------------------------- +d = spm_read_vols(VM); +[Ix,Iy,Iz] = ndgrid(1:VM.dim(1),1:VM.dim(2),1:VM.dim(3)); +Ix = Ix(d~=0); Iy = Iy(d~=0); Iz = Iz(d~=0); -%-Compute variance of derivatives in all directions -%----------------------------------------------------------------------- +%-Compute covariance of derivatives +%-------------------------------------------------------------------------- str = 'Spatial non-sphericity (over scans)'; -fprintf('%-40s: %30s',str,'...estimating derivatives'); %-# +fprintf('%-40s: %30s',str,'...estimating derivatives'); %-# spm_progress_bar('Init',100,'smoothness estimation',''); -v = zeros(size(Ix,1),N); +L = zeros(size(Ix,1),D,D); ssq = zeros(size(Ix,1),1); -for i = 1:length(V) % for all residual images +for i = 1:length(V) - [d, dx, dy, dz] = spm_sample_vol(V(i), Ix, Iy, Iz, 1); + [d,dx,dy,dz] = spm_sample_vol(V(i),Ix,Iy,Iz,1); - if N >= 1, v(:, 1) = v(:, 1) + dx.^2; end - if N >= 2, v(:, 2) = v(:, 2) + dy.^2; end - if N >= 3, v(:, 3) = v(:, 3) + dz.^2; end - + % sum of squares + %---------------------------------------------------------------------- ssq = ssq + d.^2; - + + % covariance of finite differences + %---------------------------------------------------------------------- + if D >= 1 + L(:,1,1) = L(:,1,1) + dx.*dx; + end + if D >= 2 + L(:,1,2) = L(:,1,2) + dx.*dy; + L(:,2,2) = L(:,2,2) + dy.*dy; + end + if D >= 3 + L(:,1,3) = L(:,1,3) + dx.*dz; + L(:,2,3) = L(:,2,3) + dy.*dz; + L(:,3,3) = L(:,3,3) + dz.*dz; + end + spm_progress_bar('Set',100*i/length(V)); - + end spm_progress_bar('Clear') %-Scale sum into an average (and account for DF) -% % The standard result uses normalised residuals e/sqrt(RSS) and % -% \hat\Lambda = grad(e/sqrt(RSS))' * grad(e/sqrt(RSS)) -% -% Note this function (for now) neglects the off diagonals of \Lambda. +% \hat\Lambda = grad(e/sqrt(RSS))' * grad(e/sqrt(RSS)) % % In terms of standardized residuals e/sqrt(RMS) this is % -% \hat\Lambda = (1/DF) * grad(e/sqrt(RMS))' * grad(e/sqrt(RMS)) +% \hat\Lambda = (1/DF) * grad(e/sqrt(RMS))' * grad(e/sqrt(RMS)) % % but both of these expressions assume that the RSS or RMS correspond to % the full set of residuals considered. However, spm_spm only considers % upto MAXRES residual images. To adapt, re-write the above as a scaled % average over n scans % -% \hat\Lambda = (n/DF) * ( (1/n) * grad(e/sqrt(RMS))' * grad(e/sqrt(RMS)) ) +% \hat\Lambda = (n/DF) * ( (1/n) * grad(e/sqrt(RMS))' * grad(e/sqrt(RMS)) ) % % I.e. the roughness estimate \hat\Lambda is an average of outer products % of standardized residuals (where the average is over scans), scaled by -% n/DF. +% n/DF. Hence, we can use only a subset of scans simply by replacing this +% last average term with an average over the subset. % -% Hence, we can use only a subset of scans simply by replacing this last -% average term with an average over the subset. -% % See Hayasaka et al, p. 678, for more on estimating roughness with % standardized residuals (e/sqrt(RMS)) instead of normalised residuals -% (e/sqrt(RSS)). -%----------------------------------------------------------------------- -v = v / length(V); % Average +% (e/sqrt(RSS)). Note that the names arise from the fact that +% sqrt(RSS) = sqrt(r'*r) is norm(r), while sqrt(RMS) = sqrt(r'*r/edf) +% is the unbiased (ReML) estimate of the standard deviation. +%-------------------------------------------------------------------------- +L = L/length(V); % Average +L = L*(n_full/edf); % Scale -v = v * (n_full/edf); % Scale +%-Evaluate determinant (and xyz components for FWHM) +%-------------------------------------------------------------------------- +if D == 1 + resel_xyz = L; + resel_img = L; +end +if D == 2 + resel_xyz = [L(:,1,1) L(:,2,2)]; + resel_img = L(:,1,1).*L(:,2,2) - ...... + L(:,1,2).*L(:,1,2); +end +if D == 3 + resel_xyz = [L(:,1,1) L(:,2,2) L(:,3,3)]; + resel_img = L(:,1,1).*L(:,2,2).*L(:,3,3) + ... + L(:,1,2).*L(:,2,3).*L(:,1,3)*2 - ... + L(:,1,1).*L(:,2,3).*L(:,2,3) - ... + L(:,1,2).*L(:,1,2).*L(:,3,3) - ... + L(:,1,3).*L(:,2,2).*L(:,1,3); +end +resel_img(resel_img<0) = 0; +% Convert det(Lambda) and diag(Lambda) to units of resels +resel_img = sqrt(resel_img/(4*log(2))^D); +resel_xyz = sqrt(resel_xyz/(4*log(2))); -%-Eliminate NaN / zero variance voxels -%----------------------------------------------------------------------- -I = find(any(isnan(v),2) | ssq 0; + RPV = zeros(size(mask)); + RPV(mask) = resel_img; + + % Remove invalid mask voxels, i.e. edge voxels with missing derivatives + smask = double(mask & isfinite(RPV)); % leaves mask for resel_img below + + % Smooth RPV volume (note that NaNs are treated as zeros in spm_smooth) + spm_smooth(RPV, RPV, fwhm_vox); + + % Smooth mask and decide how far to trust smoothing-based extrapolation + spm_smooth(smask, smask, fwhm_vox); + infer = smask > 1e-3; % require sum of voxel's in-mask weights > 1e-3 + + % Normalise smoothed RPV by smoothed mask + RPV( infer) = RPV(infer) ./ smask(infer); + RPV(~infer) = NaN; % spm_list handles remaining (unlikely) in-mask NaNs + + % Get data at in-mask voxels; smoothed resel_img conforms with original + resel_img = RPV(mask); +end %-Write Resels Per Voxel image -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- fprintf('%s%30s',repmat(sprintf('\b'),1,30),'...writing resels/voxel image');%-# -resel_img_3 = sqrt(v./(4*log(2))); -resel_img = prod(resel_img_3,2); -for i = 1:VM.dim(3) - d = NaN(VM.dim(1:2)); - I = find(Iz == i); +for i = 1:VM.dim(3) + d = NaN(VM.dim(1:2)); + I = find(Iz == i); if ~isempty(I) d(sub2ind(VM.dim(1:2), Ix(I), Iy(I))) = resel_img(I); end VRpv = spm_write_plane(VRpv, d, i); end -%-Global equivalent FWHM -%----------------------------------------------------------------------- -resel = mean(resel_img); -resel_3 = mean(resel_img_3); -FWHM = 1 ./ resel_3; - -%-Bias correction {prod(1/FWHM) = (unbiased) RESEL estimator} -%----------------------------------------------------------------------- -% Variable 'resel' is unbiased and is actual quantity that determines -% RFT P-values (see spm_resels_vol and use of SPM.xVol.R), but only FWHM -% gets returned from this function. Hence the following bias correction -% ensures that prod(1./FWHM) equals resel. -FWHM = FWHM / prod(FWHM)^(1/N) * (1/resel).^(1/N); - -%-Carefully fill-in accounting for dimension -fwhm = [Inf Inf Inf]; -fwhm(1:length(FWHM)) = FWHM; + +%-(unbiased) RESEL estimator and Global equivalent FWHM +% where we desire FWHM with components proportional to 1./mean(resel_xyz), +% but scaled so prod(1./FWHM) agrees with (the unbiased) mean(resel_img). +%-------------------------------------------------------------------------- +i = isnan(ssq) | ssq < sqrt(eps); +resel_img = mean(resel_img(~i,:)); +resel_xyz = mean(resel_xyz(~i,:)); + +RESEL = resel_img^(1/D)*(resel_xyz/prod(resel_xyz)^(1/D)); +FWHM = full(sparse(1,1:D,1./RESEL,1,3)); +FWHM(~FWHM) = 1; + +%-resel counts for search volume (defined by mask) +%-------------------------------------------------------------------------- +% R0 = spm_resels_vol(VM,[1 1 1])'; +% R = R0.*(resel.^([0:3]/3)); +% OR +R = spm_resels_vol(VM,FWHM)'; + fprintf('%s%30s\n',repmat(sprintf('\b'),1,30),'...done'); %-# diff --git a/spm_expm.m b/spm_expm.m index fe70d04..3b6df14 100644 --- a/spm_expm.m +++ b/spm_expm.m @@ -9,25 +9,27 @@ % comoutationally expedient approximation that can handle sparse % matrices when dealing with the special case of expm(J)*x, where x % is a vector, in an efficient fashion -%___________________________________________________________________________ +%__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_expm.m 3649 2009-12-17 16:57:24Z guillaume $ +% $Id: spm_expm.m 3813 2010-04-07 19:21:49Z karl $ -% expm(J) use Pade approximation -%--------------------------------------------------------------------------- -if nargin == 1 + +if nargin == 1 || nargin == 2 + + % expm(J) use Pade approximation + %====================================================================== % ensure norm is < 1/2 by scaling by power of 2 - %------------------------------------------------------------------- + %---------------------------------------------------------------------- J = full(J); I = eye(size(J)); [f,e] = log2(norm(J,'inf')); - s = max(0,e+1); + s = max(0,e + 1); J = J/2^s; - X = J; + X = J; c = 1/2; E = I + c*J; D = I - c*J; @@ -45,39 +47,60 @@ end p = ~p; end - E = D\E; + + E = D\E; % E = inv(D)*E - % Undo scaling by repeated squaring - %------------------------------------------------------------------- + % Undo scaling by repeated squaring E = E^(2^s) + %---------------------------------------------------------------------- for k = 1:s E = E*E; end - x = E; - + + % Multiply by x if necessary + %---------------------------------------------------------------------- + if nargin > 1 + x = E*x; + else + x = E; + end + return + + +% Alternative evaluation of exp(J)*x for large matrices +%========================================================================== else % compute y = expm(J)*x = (1 + J + J*J/2! + J*J*J/3! + ...)*x - %------------------------------------------------------------------- - J = full(J); - x = full(x); - x0 = x; + %---------------------------------------------------------------------- fx = J*x; - j = 1; - - while norm(fx,1) > 1e-16 + s = 0; + for i = 2:64 % accumulate high-order terms until convergence %----------------------------------------------------------- - j = j + 1; - x = x + fx; - fx = J*fx/j; + nx = norm(fx,1); + if ~nx + return + end + fx = fx/nx; - % revert to Pade approximation if numerical overflow - %----------------------------------------------------------- - if norm(x,1) > 1e16 - %fprintf('Reverting to Pade approximation') - x = spm_expm(J)*x0; + % take care to accumulate scaling in log-space + %------------------------------------------------------------------ + s(i,1) = s(i - 1) + log(nx) - log(i - 1); + x(:,i) = fx; + fx = J*fx; + + % add expansion terms if convergence + %------------------------------------------------------------------ + if s(i) < -16 + x = x*exp(s); return end end + + % If no convergence + %---------------------------------------------------------------------- + disp('reverting to full pade') + x = spm_expm(J)*x(:,1); + end diff --git a/spm_fMRI_design.m b/spm_fMRI_design.m index ca64419..3b49dc6 100644 --- a/spm_fMRI_design.m +++ b/spm_fMRI_design.m @@ -5,7 +5,6 @@ % 1st level %-------------------------------------------------------------------------- % SPM. -% % xY: [1x1 struct] - data structure % nscan: [1xs double] - nscan(s) = number of scans in session s % xBF: [1x1 struct] - Basis function structure @@ -165,16 +164,14 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_fMRI_design.m 2496 2008-11-27 13:40:32Z karl $ +% $Id: spm_fMRI_design.m 3691 2010-01-20 17:08:30Z guillaume $ -SCCSid = '$Rev: 2496 $'; +SVNid = '$Rev: 3691 $'; %-GUI setup %-------------------------------------------------------------------------- -SPMid = spm('SFnBanner',mfilename,SCCSid); -[Finter,Fgraph,CmdLine] = spm('FnUIsetup','fMRI stats model setup',0); -spm_help('!ContextHelp',mfilename) +spm('FnBanner',mfilename,SVNid); if nargin == 1 save_SPM = 1; @@ -187,49 +184,45 @@ % global parameters %-------------------------------------------------------------------------- try - fMRI_T = SPM.xBF.T; - fMRI_T0 = SPM.xBF.T0; + fMRI_T = SPM.xBF.T; + fMRI_T0 = SPM.xBF.T0; catch - fMRI_T = 16; - fMRI_T0 = 1; + fMRI_T = spm_get_defaults('stats.fmri.fmri_t'); + fMRI_T0 = spm_get_defaults('stats.fmri.fmri_t0'); SPM.xBF.T = fMRI_T; SPM.xBF.T0 = fMRI_T0; end - -% get nscan and RT if not in SPM +% get nscan and RT %-------------------------------------------------------------------------- try SPM.xY.RT; catch - spm_input('Basic parameters...',1,'d',mfilename) - SPM.xY.RT = spm_input('Interscan interval {secs}','+1','r',[],1); + SPM.xY.RT = spm_input('Interscan interval {secs}','+1','r',[],1); end try SPM.nscan; catch - SPM.nscan = spm_input('scans per session e.g. 64 64 64','+1'); + SPM.nscan = spm_input('scans per session e.g. 64 64 64','+1'); end % time units, dt = time bin {secs} %-------------------------------------------------------------------------- -SPM.xBF.dt = SPM.xY.RT/SPM.xBF.T; +SPM.xBF.dt = SPM.xY.RT/SPM.xBF.T; try SPM.xBF.UNITS; catch - str = 'specify design in'; - SPM.xBF.UNITS = spm_input(str,'+1','scans|secs'); + SPM.xBF.UNITS = spm_input('specify design in','+1','scans|secs'); end % separate specifications for non-replicated sessions %-------------------------------------------------------------------------- rep = 0; if length(SPM.nscan) > 1 && ~any(diff(SPM.nscan)) && ~isfield(SPM,'Sess') - str = 'are sessions replications'; - rep = spm_input(str,'+1','yes|no',[1 0]); + rep = spm_input('are sessions replications','+1','yes|no',[1 0]); end -% Get basis functions +% get basis functions %-------------------------------------------------------------------------- try bf = SPM.xBF.bf; @@ -243,8 +236,7 @@ try V = SPM.xBF.Volterra; catch - str = 'model interactions (Volterra)'; - V = spm_input(str,'+1','y/n',[2 1]); + V = spm_input('model interactions (Volterra)','+1','y/n',[2 1]); SPM.xBF.Volterra = V; end @@ -259,7 +251,7 @@ % number of scans for this session %---------------------------------------------------------------------- - k = SPM.nscan(s); + k = SPM.nscan(s); if (s == 1) || ~rep @@ -357,7 +349,7 @@ Xx = blkdiag(Xx,X); Xb = blkdiag(Xb,B); -end %- for s +end % finished @@ -372,13 +364,12 @@ if save_SPM %-End: Save SPM.mat %---------------------------------------------------------------------- - fprintf('\t%-32s:\n ','Saving fMRI design') %-# + fprintf('%-40s: ','Saving fMRI design') %-# if spm_matlab_version_chk('7') >= 0, save('SPM', 'SPM', '-V6'); else save('SPM', 'SPM'); - end; + end fprintf('%30s\n','...SPM.mat saved'); end spm_input('!DeleteInputObj') - diff --git a/spm_figure.m b/spm_figure.m index b7126d2..834cd6e 100644 --- a/spm_figure.m +++ b/spm_figure.m @@ -1,88 +1,66 @@ function varargout=spm_figure(varargin) % Setup and callback functions for Graphics window % FORMAT varargout=spm_figure(varargin) -% - An embedded callback, multi-function function -% - For detailed programmers comments, see format specifications -% in main body of code -%_______________________________________________________________________ +% +% spm_figure provides utility routines for using the SPM Graphics +% interface. Most used syntaxes are listed here, see the embedded callback +% reference in the main body of this function, below the help text. +% +% FORMAT F = spm_figure('Create',Tag,Name,Visible) +% FORMAT F = spm_figure('FindWin',Tag) +% FORMAT F = spm_figure('GetWin',Tag) +% FORMAT spm_figure('Clear',F,Tags) +% FORMAT spm_figure('Close',F) +% FORMAT spm_figure('Print',F) +% FORMAT spm_figure('WaterMark',F,str,Tag,Angle,Perm) +% +% FORMAT spm_figure('NewPage',hPage) +% FORMAT spm_figure('TurnPage',move,F) +% FORMAT spm_figure('DeletePageControls',F) +% FORMAT n = spm_figure('#page') +% FORMAT n = spm_figure('CurrentPage') +%__________________________________________________________________________ % % spm_figure creates and manages the 'Graphics' window. This window and % these facilities may be used independently of SPM, and any number of % Graphics windows my be used within the same MATLAB session. (Though -% only one SPM 'Graphics' 'Tag'ed window is permitted. +% only one SPM 'Graphics' 'Tag'ed window is permitted). % % The Graphics window is provided with a menu bar at the top that -% facilitates editing and printing of the current graphic display, -% enabling interactive editing of graphic output prior to printing -% (e.g. selection of color maps, deleting, moving and editing graphics -% objects or adding text). (This menu is also provided as a figure -% background "ContextMenu" - right-clicking on the figure background -% should bring up the menu.) +% facilitates editing and printing of the current graphic display. +% (This menu is also provided as a figure background "ContextMenu" - +% right-clicking on the figure background should bring up the menu). % -% Print: Graphics windows with multi-page axes are printed page by page. +% "Print": Graphics windows with multi-page axes are printed page by page. % -% Clear: Clears the Graphics window. If in SPM usage (figure 'Tag'ed as +% "Clear": Clears the Graphics window. If in SPM usage (figure 'Tag'ed as % 'Graphics') then all SPM windows are cleared and reset. % -% Colormap options: -% * gray, hot, pink: Sets the colormap to its default values and loads -% either a grayscale, 'hot metal' or color map. +% "Colours": +% * gray, hot, pink, jet: Sets the colormap to selected item. % * gray-hot, etc: Creates a 'split' colormap {128 x 3 matrix}. -% The lower half is a gray scale and the upper half -% is 'hot metal' or 'pink'. This color map is used for -% viewing 'rendered' SPMs on a PET, MRI or other background images -% +% The lower half is a gray scale and the upper half is selected +% colormap This colormap is used for viewing 'rendered' SPMs on a +% PET, MRI or other background images. % Colormap effects: % * Invert: Inverts (flips) the current color map. % * Brighten and Darken: Brighten and Darken the current colourmap % using the MATLAB BRIGHTEN command, with beta's of +0.2 and -0.2 % respectively. % -% Editing: Right button ('alt' button) cancels operations -% * Cut : Deletes the graphics object next selected (if deletable) -% Select with middle mouse button to delete blocks of text, -% or to delete individual elements from a plot. -% * Move : To re-position a text, uicontrol or axis object using a -% 'drag and drop' implementation (i.e. depress - move - release) -% Using the middle 'extend' mouse button on a text object moves -% the axes containing the text - i.e. blocks of text. -% * Size : Re-sizes the text, uicontrol or axis object next selected -% {left button - decrease, middle button - increase} by a factor -% of 1.24 (or increase/decrease FontSize by 2 dpi) -% * Text : Creates an editable text widget that produces a text object as -% its CallBack. -% The text object is provided with a ContextMenu, obtained by -% right-clicking ('alt') on the text, allowing text attributes -% to be changed. Alternatively, the edit facilities on the window -% menu bar or ContextMenu can be used. -% * Edit : To edit text, select a text object with the circle cursor, -% and edit the text in the editable text widget that appears. -% A middle 'extend' mouse click places a context menu on the text -% object, facilitating easy modification of text atributes. -% % For SPM usage, the figure should be 'Tag'ed as 'Graphics'. % -% For SPM power users, and programmers, spm_figure provides utility -% routines for using the SPM graphics interface. Of particular use are -% the GetWin, FindWin and Clear functions See the embedded callback -% reference in the main body of spm_figure, below the help text. -% % See also: spm_print, spm_clf -% -%_______________________________________________________________________ +%__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Andrew Holmes -% $Id: spm_figure.m 3643 2009-12-15 16:53:34Z guillaume $ +% $Id: spm_figure.m 3953 2010-06-28 16:58:48Z guillaume $ -%======================================================================= +%========================================================================== % - FORMAT specifications for embedded CallBack functions -%======================================================================= -%( This is a multi function function, the first argument is an action ) -%( string, specifying the particular action function to take. Recall ) -%( MATLAB's command-function duality: `spm_figure Create` is ) -%( equivalent to `spm_figure('Create')`. ) +%========================================================================== % % FORMAT F = spm_figure % [ShortCut] Defaults to Action 'Create' @@ -112,12 +90,6 @@ % Tag - Figure 'Tag' to get, defaults to 'Graphics' % F - Figure number (if found/created) or empty (if not). % -% FORMAT F = spm_figure('ParentFig',h) -% Finds window containing the object whose handle is specified -% h - Handle of object whose parent figure is required -% - If a vector, then first object handle is used -% F - Number or parent figure -% % FORMAT spm_figure('Clear',F,Tags) % Clears figure, leaving ToolBar (& other objects with invisible handles) % Optional third argument specifies 'Tag's of objects to delete. @@ -128,7 +100,11 @@ % *regardless* of 'HandleVisibility'. Only these objects are deleted. % '!all' denotes all objects % -% +% FORMAT spm_figure('Close',F) +% Closes figures (deletion without confirmation) +% Also closes the docking container if empty. +% F - 'Tag' string or figure number of figure to clear, defaults to gcf +% % FORMAT spm_figure('Print',F) % F - [Optional] Figure to print. ('Tag' or figure number) % Defaults to figure 'Tag'ed as 'Graphics'. @@ -175,42 +151,25 @@ % Name - Name for window % Visible - 'on' or 'off' % -% FORMAT WS = spm_figure('GetWinScale') -% Returns ratios of current display dimensions to that of a 1152 x 900 -% Sun display. WS=[Xratio,Yratio,Xratio,Yratio]. Used for scaling other -% GUI elements. -% (Function duplicated in spm.m, repeated to reduce inter-dependencies.) -% -% FORMAT FS = spm_figure('FontSizes',FS) -% Returns fontsizes FS scaled for the current display. -% FS - (vector of) Font sizes to scale -% [default [08,09,11,13,14,6:36]] -% % FORMAT spm_figure('CreateBar',F) % Creates toolbar in figure F (defaults to gcf). F can be a 'Tag' -% If the figure is 'Tag'ed as 'Graphics' (SPM usage), then the Print button -% callback is set to attempt to clear an 'Interactive' figure too. % % FORMAT spm_figure('ColorMap') % Callback for "ColorMap" buttons -% -% FORMAT h = spm_figure('GraphicsHandle',F) -% GUI choose object for handle identification. LeftMouse 'normal' returns -% handle, MiddleMouse 'extend' returns parents handle, RightMouse 'alt' cancels. -% F - figure to do a GUI "handle ID" in [Default gcbf] -%_______________________________________________________________________ +%__________________________________________________________________________ %-Condition arguments -%----------------------------------------------------------------------- -if (nargin==0), Action = 'Create'; else Action = varargin{1}; end +%-------------------------------------------------------------------------- +if ~nargin, Action = 'Create'; else Action = varargin{1}; end +%========================================================================== switch lower(Action), case 'create' -%======================================================================= +%========================================================================== % F = spm_figure('Create',Tag,Name,Visible) -%-Condition arguments + if nargin<4, Visible='on'; else Visible=varargin{4}; end -if nargin<3, Name=''; else, Name=varargin{3}; end +if nargin<3, Name=''; else Name=varargin{3}; end if nargin<2, Tag=''; else Tag=varargin{2}; end F = spm_figure('CreateWin',Tag,Name,Visible); @@ -218,9 +177,9 @@ spm_figure('FigContextMenu',F); varargout = {F}; - +%========================================================================== case 'findwin' -%======================================================================= +%========================================================================== % F=spm_figure('FindWin',F) % F=spm_figure('FindWin',Tag) %-Find window: Find window with FigureNumber# / 'Tag' attribute @@ -228,15 +187,12 @@ if nargin<2, F='Graphics'; else F=varargin{2}; end -shh = get(0,'showhiddenhandles'); -set(0,'showhiddenhandles','on'); - if isempty(F) % Leave F empty elseif ischar(F) % Finds Graphics window with 'Tag' string - delete multiples - Tag=F; - F = findobj(get(0,'Children'),'Flat','Tag',Tag); + Tag = F; + F = findall(allchild(0),'Flat','Tag',Tag); if length(F) > 1 % Multiple Graphics windows - close all but most recent close(F(2:end)) @@ -244,15 +200,16 @@ end else % F is supposed to be a figure number - check it - if ~any(F==get(0,'Children')), F=[]; end + if ~any(F==allchild(0)), F=[]; end end -set(0,'showhiddenhandles',shh); varargout = {F}; - +%========================================================================== case 'getwin' -%======================================================================= +%========================================================================== % F=spm_figure('GetWin',Tag) +%-Like spm_figure('FindWin',Tag), except that if no such 'Tag'ged figure +% is found and 'Tag' is recognized, one is created. if nargin<2, Tag='Graphics'; else Tag=varargin{2}; end F = spm_figure('FindWin',Tag); @@ -260,25 +217,26 @@ if isempty(F) if ischar(Tag) switch Tag - - case 'Graphics' - F = spm_figure('Create','Graphics','Graphics'); - case 'DEM' - F = spm_figure('Create','DEM','Dynamic Expectation Maximisation'); - case 'DFP' - F = spm_figure('Create','DFP','Variational filtering'); - case 'FMIN' - F = spm_figure('Create','FMIN','Function minimisation'); - case 'MFM' - F = spm_figure('Create','MFM','Mean-field and neural mass models'); - case 'MVB' - F = spm_figure('Create','MVB','Multivariate Bayes'); - case 'SI' - F = spm_figure('Create','SI','System Identification'); - case 'PPI' - F = spm_figure('Create','PPI','Physio/Psycho-Physiologic Interaction'); - case 'Interactive' - F = spm('CreateIntWin'); + case 'Graphics' + F = spm_figure('Create','Graphics','Graphics'); + case 'DEM' + F = spm_figure('Create','DEM','Dynamic Expectation Maximisation'); + case 'DFP' + F = spm_figure('Create','DFP','Variational filtering'); + case 'FMIN' + F = spm_figure('Create','FMIN','Function minimisation'); + case 'MFM' + F = spm_figure('Create','MFM','Mean-field and neural mass models'); + case 'MVB' + F = spm_figure('Create','MVB','Multivariate Bayes'); + case 'SI' + F = spm_figure('Create','SI','System Identification'); + case 'PPI' + F = spm_figure('Create','PPI','Physio/Psycho-Physiologic Interaction'); + case 'Interactive' + F = spm('CreateIntWin'); + otherwise + F = spm_figure('Create',Tag,Tag); end end else @@ -287,35 +245,35 @@ end varargout = {F}; +%========================================================================== case 'parentfig' -%======================================================================= +%========================================================================== % F=spm_figure('ParentFig',h) + +warning('spm_figure(''ParentFig'',h) is deprecated. Use ANCESTOR instead.'); if nargin<2, error('No object specified'), else h=varargin{2}; end -F = get(h(1),'Parent'); -while ~strcmp(get(F,'Type'),'figure'), F=get(F,'Parent'); end +F = ancestor(h,'figure'); varargout = {F}; - +%========================================================================== case 'clear' -%======================================================================= +%========================================================================== % spm_figure('Clear',F,Tags) %-Sort out arguments -%----------------------------------------------------------------------- if nargin<3, Tags=[]; else Tags=varargin{3}; end if nargin<2, F=get(0,'CurrentFigure'); else F=varargin{2}; end F = spm_figure('FindWin',F); if isempty(F), return, end %-Clear figure -%----------------------------------------------------------------------- +isdocked = strcmp(get(F,'WindowStyle'),'docked'); if isempty(Tags) %-Clear figure of objects with 'HandleVisibility' 'on' pos = get(F,'Position'); - delete(findobj(get(F,'Children'),'flat','HandleVisibility','on')); + delete(findall(allchild(F),'flat','HandleVisibility','on')); drawnow - set(F,'Position',pos); - + if ~isdocked, set(F,'Position',pos); end %-Reset figures callback functions zoom(F,'off'); rotate3d(F,'off'); @@ -328,24 +286,48 @@ set(F,'Name','','UserData',[]), end else %-Clear specified objects from figure - cSHH = get(0,'ShowHiddenHandles'); - set(0,'ShowHiddenHandles','on') if ischar(Tags); Tags=cellstr(Tags); end if any(strcmp(Tags(:),'!all')) - delete(get(F,'Children')) + delete(allchild(F)) else for tag = Tags(:)' - delete(findobj(get(F,'Children'),'flat','Tag',tag{:})); + delete(findall(allchild(F),'flat','Tag',tag{:})); end end - set(0,'ShowHiddenHandles',cSHH) end set(F,'Pointer','Arrow') -movegui(F); +if ~isdocked, movegui(F); end + +%========================================================================== +case 'close' +%========================================================================== +% spm_figure('Close',F) + +%-Sort out arguments +if nargin < 2, F = gcf; else F = varargin{2}; end +F = spm_figure('FindWin',F); +if isempty(F), return, end + +%-Detect if SPM windows are in docked mode +hMenu = spm_figure('FindWin','Menu'); +isdocked = strcmp(get(hMenu,'WindowStyle'),'docked'); +%-Close figures (and deleted without confirmation) +delete(F); +%-If in docked mode and closing SPM, close the container as well +if isdocked && ismember(hMenu,F) + try + desktop = com.mathworks.mde.desk.MLDesktop.getInstance; + group = ['Statistical Parametric Mapping (' spm('Ver') ')']; + hContainer = desktop.getGroupContainer(group); + hContainer.getTopLevelAncestor.hide; + end +end + +%========================================================================== case 'print' -%======================================================================= +%========================================================================== % spm_figure('Print',F,fname) %-Arguments & defaults @@ -363,31 +345,25 @@ set(0,'CurrentFigure',F) %-See if window has paging controls -hNextPage = findobj(F,'Tag','NextPage'); -hPrevPage = findobj(F,'Tag','PrevPage'); -hPageNo = findobj(F,'Tag','PageNo'); +hNextPage = findall(F,'Tag','NextPage'); +hPrevPage = findall(F,'Tag','PrevPage'); +hPageNo = findall(F,'Tag','PageNo'); iPaged = ~isempty(hNextPage); -%-Construct print command -%----------------------------------------------------------------------- - %-Temporarily change all units to normalized prior to printing -% (Fixes bizzarre problem with stuff jumping around!) -%----------------------------------------------------------------------- -H = findobj(get(F,'Children'),'flat','Type','axes'); -if ~isempty(H), +H = findall(allchild(F),'flat','Type','axes'); +if ~isempty(H) un = cellstr(get(H,'Units')); - set(H,'Units','normalized') -end; + set(H,'Units','normalized'); +end %-Print -%----------------------------------------------------------------------- if ~iPaged spm_print(fname) else - hPg = get(hNextPage,'UserData'); - Cpage = get(hPageNo, 'UserData'); - nPages = size(hPg,1); + hPg = get(hNextPage,'UserData'); + Cpage = get(hPageNo, 'UserData'); + nPages = size(hPg,1); set([hNextPage,hPrevPage,hPageNo],'Visible','off') if Cpage~=1 @@ -403,9 +379,9 @@ if ~isempty(H), set(H,{'Units'},un); end; set(0,'CurrentFigure',cF) - +%========================================================================== case 'printto' -%======================================================================= +%========================================================================== %spm_figure('PrintTo',F) %-Arguments & defaults @@ -417,33 +393,33 @@ if isempty(F), F = get(0,'CurrentFigure'); end if isempty(F), return, end -[fn pn] = uiputfile('*.ps', 'Print to File'); -if fn == 0 - return; -end; +[fn, pn, fi] = uiputfile({'*.ps','PostScript file (*.ps)'},'Print to File'); +if isequal(fn,0) || isequal(pn,0), return, end psname = fullfile(pn, fn); spm_figure('Print',F,psname); +%========================================================================== case 'newpage' -%======================================================================= +%========================================================================== % [hNextPage, hPrevPage, hPageNo] = spm_figure('NewPage',h) -if nargin<2 || isempty(varargin{2}) error('No handles to paginate') + +if nargin<2 || isempty(varargin{2}), error('No handles to paginate') else h=varargin{2}(:)'; end %-Work out which figure we're in -F = spm_figure('ParentFig',h(1)); +F = ancestor(h(1),'figure'); -hNextPage = findobj(F,'Tag','NextPage'); -hPrevPage = findobj(F,'Tag','PrevPage'); -hPageNo = findobj(F,'Tag','PageNo'); +hNextPage = findall(F,'Tag','NextPage'); +hPrevPage = findall(F,'Tag','PrevPage'); +hPageNo = findall(F,'Tag','PageNo'); %-Create pagination widgets if required -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- if isempty(hNextPage) WS = spm('WinScale'); FS = spm('FontSizes'); - SatFig = findobj('Tag','Satellite'); + SatFig = findall(0,'Tag','Satellite'); if ~isempty(SatFig) SatFigPos = get(SatFig,'Position'); hNextPagePos = [SatFigPos(3)-25 15 15 15]; @@ -486,7 +462,7 @@ %-Add handles for this page to UserData of hNextPage %-Make handles for this page invisible if PageNo>1 -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- mVis = strcmp('on',get(h,'Visible')); mHit = strcmp('on',get(h,'HitTest')); hPg = get(hNextPage,'UserData'); @@ -502,18 +478,19 @@ %-Return handles to pagination controls if requested if nargout>0, varargout = {[hNextPage, hPrevPage, hPageNo]}; end - +%========================================================================== case 'turnpage' -%======================================================================= +%========================================================================== % spm_figure('TurnPage',move,F) + if nargin<3, F='Graphics'; else F=varargin{3}; end if nargin<2, move=1; else move=varargin{2}; end F = spm_figure('FindWin',F); if isempty(F), error('No Graphics window'), end -hNextPage = findobj(F,'Tag','NextPage'); -hPrevPage = findobj(F,'Tag','PrevPage'); -hPageNo = findobj(F,'Tag','PageNo'); +hNextPage = findall(F,'Tag','NextPage'); +hPrevPage = findall(F,'Tag','PrevPage'); +hPageNo = findall(F,'Tag','PageNo'); if isempty(hNextPage), return, end hPg = get(hNextPage,'UserData'); Cpage = get(hPageNo, 'UserData'); @@ -530,42 +507,43 @@ set(hPg{Npage,3},'HitTest','on'); set(hPageNo,'UserData',Npage,'String',sprintf('%d / %d',Npage,nPages)) -for k = 1:length(hPg{Npage,1}) % VG +for k = 1:length(hPg{Npage,1}) if strcmp(get(hPg{Npage,1}(k),'Type'),'axes') axes(hPg{Npage,1}(k)); - end; -end; + end +end -%-Disable appropriate page turning control if on first/last page (for neatness) +%-Disable appropriate page turning control if on first/last page if Npage==1, set(hPrevPage,'Enable','off') else set(hPrevPage,'Enable','on'), end if Npage==nPages, set(hNextPage,'Enable','off') else set(hNextPage,'Enable','on'), end - - +%========================================================================== case 'deletepagecontrols' -%======================================================================= +%========================================================================== % spm_figure('DeletePageControls',F) + if nargin<2, F='Graphics'; else F=varargin{2}; end F = spm_figure('FindWin',F); if isempty(F), error('No Graphics window'), end -hNextPage = findobj(F,'Tag','NextPage'); -hPrevPage = findobj(F,'Tag','PrevPage'); -hPageNo = findobj(F,'Tag','PageNo'); +hNextPage = findall(F,'Tag','NextPage'); +hPrevPage = findall(F,'Tag','PrevPage'); +hPageNo = findall(F,'Tag','PageNo'); delete([hNextPage hPrevPage hPageNo]) - +%========================================================================== case '#page' -%======================================================================= +%========================================================================== % n = spm_figure('#Page',F) + if nargin<2, F='Graphics'; else F=varargin{2}; end F = spm_figure('FindWin',F); if isempty(F), error('No Graphics window'), end -hNextPage = findobj(F,'Tag','NextPage'); +hNextPage = findall(F,'Tag','NextPage'); if isempty(hNextPage) n = 1; else @@ -573,32 +551,35 @@ end varargout = {n}; +%========================================================================== case 'currentpage' -%======================================================================= +%========================================================================== % n = spm_figure('CurrentPage', F) + if nargin<2, F='Graphics'; else F=varargin{2}; end F = spm_figure('FindWin',F); if isempty(F), error('No Graphics window'), end -hPageNo = findobj(F,'Tag','PageNo'); +hPageNo = findall(F,'Tag','PageNo'); Cpage = get(hPageNo, 'UserData'); varargout = {Cpage}; +%========================================================================== case 'watermark' -%======================================================================= +%========================================================================== % spm_figure('WaterMark',F,str,Tag,Angle,Perm) + if nargin<6, HVis='on'; else HVis='off'; end if nargin<5, Angle=-45; else Angle=varargin{5}; end if nargin<4 || isempty(varargin{4}), Tag = 'WaterMark'; else Tag=varargin{4}; end if nargin<3 || isempty(varargin{3}), str = 'SPM'; else str=varargin{3}; end -if nargin<2, if any(get(0,'Children')), F=gcf; else F=''; end +if nargin<2, if any(allchild(0)), F=gcf; else F=''; end else F=varargin{2}; end F = spm_figure('FindWin',F); if isempty(F), return, end %-Specify watermark color from background colour -%----------------------------------------------------------------------- Colour = get(F,'Color'); %-Only mess with grayscale backgrounds if ~all(Colour==Colour(1)), return, end @@ -630,18 +611,15 @@ set(h,'HandleVisibility',HVis) set(0,'CurrentFigure',cF) - +%========================================================================== case 'createwin' -%======================================================================= +%========================================================================== % F=spm_figure('CreateWin',Tag,Name,Visible) -%-Condition arguments -%----------------------------------------------------------------------- if nargin<4 || isempty(varargin{4}), Visible='on'; else Visible=varargin{4}; end if nargin<3, Name=''; else Name = varargin{3}; end if nargin<2, Tag=''; else Tag = varargin{2}; end -WS = spm('WinScale'); %-Window scaling factors FS = spm('FontSizes'); %-Scaled font sizes PF = spm_platform('fonts'); %-Font names (for this platform) Rect = spm('WinSize','Graphics'); %-Graphics window rectangle @@ -678,104 +656,117 @@ 'Toolbar','none'); if ~isempty(Name) set(F,'Name',sprintf('%s%s: %s',spm('ver'),... - spm('GetUser',' (%s)'),Name),'NumberTitle','off') + spm('getUser',' (%s)'),Name),'NumberTitle','off') end set(F,'Visible',Visible) varargout = {F}; +isdocked = strcmp(get(spm_figure('FindWin','Menu'),'WindowStyle'),'docked'); +if isdocked + try + desktop = com.mathworks.mde.desk.MLDesktop.getInstance; + group = ['Statistical Parametric Mapping (' spm('Ver') ')']; + set(getJFrame(F),'GroupName',group); + set(F,'WindowStyle','docked'); + end +end -case 'getwinscale' -%======================================================================= -% WS = spm_figure('GetWinScale') -warning('spm_figure(''GetWinScale''... is Grandfathered: use spm(''WinScale''') -varargout = {spm('WinScale')}; - - -case 'fontsizes' -%======================================================================= -% FS = spm_figure('FontSizes',FS) -warning('spm_figure(''FontSizes''... is Grandfathered: use spm(''FontSizes''') -if nargin<2, FS=[08,09,11,13,14,6:36]; else FS=varargin{2}; end -varargout = {round(FS*min(spm('WinScale')))}; - - -%======================================================================= +%========================================================================== case 'createbar' -%======================================================================= +%========================================================================== % spm_figure('CreateBar',F) -if nargin<2, if any(get(0,'Children')), F=gcf; else F=''; end + +if nargin<2, if any(allchild(0)), F=gcf; else F=''; end else F=varargin{2}; end F = spm_figure('FindWin',F); if isempty(F), return, end -cSHH = get(0,'ShowHiddenHandles'); -set(0,'ShowHiddenHandles','on') - -t0 = findobj(get(F,'Children'),'Flat','Label','&Help'); +%-Help Menu +t0 = findall(allchild(F),'Flat','Label','&Help'); +delete(allchild(t0)); set(t0,'Callback',''); if isempty(t0), t0 = uimenu( F,'Label','&Help'); end; - -set(findobj(t0,'Position',1),'Separator','on'); -uimenu(t0,'Position',1,... - 'Label','SPM web',... +pos = get(t0,'Position'); +uimenu(t0,'Label','SPM Help','CallBack','spm_help'); +uimenu(t0,'Label','SPM Manual (PDF)',... + 'CallBack','try,open(fullfile(spm(''dir''),''man'',''manual.pdf''));end'); +t1=uimenu(t0,'Label','SPM &Web Resources'); +uimenu(t1,'Label','SPM Web &Site',... 'CallBack','web(''http://www.fil.ion.ucl.ac.uk/spm/'');'); -uimenu(t0,'Position',1,... - 'Label','SPM help','ForegroundColor',[0 1 0],... - 'CallBack','spm_help'); - -t0=uimenu( F,'Label','Colours','HandleVisibility','off'); -t1=uimenu(t0,'Label','ColorMap'); -uimenu(t1,'Label','Gray', 'CallBack','spm_figure(''ColorMap'',''gray'')'); -uimenu(t1,'Label','Hot', 'CallBack','spm_figure(''ColorMap'',''hot'')'); -uimenu(t1,'Label','Pink', 'CallBack','spm_figure(''ColorMap'',''pink'')'); -uimenu(t1,'Label','Jet','CallBack','spm_figure(''ColorMap'',''jet'')'); -uimenu(t1,'Label','Gray-Hot', 'CallBack','spm_figure(''ColorMap'',''gray-hot'')'); -uimenu(t1,'Label','Gray-Cool','CallBack','spm_figure(''ColorMap'',''gray-cool'')'); -uimenu(t1,'Label','Gray-Pink','CallBack','spm_figure(''ColorMap'',''gray-pink'')'); -uimenu(t1,'Label','Gray-Jet', 'CallBack','spm_figure(''ColorMap'',''gray-jet'')'); -t1=uimenu(t0,'Label','Effects'); -uimenu(t1,'Label','Invert','CallBack','spm_figure(''ColorMap'',''invert'')'); -uimenu(t1,'Label','Brighten','CallBack','spm_figure(''ColorMap'',''brighten'')'); -uimenu(t1,'Label','Darken','CallBack','spm_figure(''ColorMap'',''darken'')'); -uimenu( F,'Label','Clear','HandleVisibility','off','CallBack','spm_figure(''Clear'',gcbf)'); -t0=uimenu( F,'Label','SPM-Print','HandleVisibility','off'); -%uimenu( F,'Label','SPM-Print','HandleVisibility','off','CallBack','spm_figure(''Print'',gcbf)'); -t1=uimenu(t0,'Label','default print file','HandleVisibility','off','CallBack','spm_figure(''Print'',gcbf)'); -t1=uimenu(t0,'Label','other print file','HandleVisibility','off','CallBack','spm_figure(''PrintTo'',spm_figure(''FindWin'',''Graphics''))'); - - -% ### CODE FOR SATELLITE FIGURE ### -% Code checks if there is a satellite window and if results are currently displayed -% It assumes that if hReg is invalid then there are no results currently displayed -% Modified by DRG to display a satellite figure 02/14/01. -cb = ['global SatWindow,',... - 'try,',... - 'tmp = get(hReg);,',... - 'ResFlag = 1;',... - 'catch,',... - 'ResFlag = 0;',... - 'end,',... - 'if SatWindow,',... - 'figure(SatWindow),',... - 'else,',... - 'if ResFlag,',... - 'spm_setup_satfig,',... - 'end,',... - 'end']; -uimenu( F,'Label','Results-Fig','HandleVisibility','off','Callback',cb); -% ### END NEW CODE ### - - -set(0,'ShowHiddenHandles',cSHH) -try - spm_jobman('pulldown'); +uimenu(t1,'Label','SPM &WikiBook',... + 'CallBack','web(''http://en.wikibooks.org/wiki/SPM'');'); +uimenu(t1,'Separator','on','Label','SPM &Extensions',... + 'CallBack','web(''http://www.fil.ion.ucl.ac.uk/spm/ext/'');'); + +%-Check Menu +if ~isdeployed + uimenu(t0,'Separator','on','Label','SPM Check Installation',... + 'CallBack','spm_check_installation(''full'')'); + uimenu(t0,'Label','SPM Check for Updates',... + 'CallBack','spm(''alert"'',evalc(''spm_update''),''SPM Update'');'); end -%======================================================================= +%- About Menu +uimenu(t0,'Separator','on','Label',['&About ' spm('Ver')],... + 'CallBack',@spm_about); +uimenu(t0,'Label','&About MATLAB',... + 'CallBack','helpmenufcn(gcbf,''HelpAbout'')'); + +%-Figure Menu +t0=uimenu(F, 'Position',pos, 'Label','&SPM Figure', 'HandleVisibility','off', 'Callback',@myisresults); + +%-Show All Figures +uimenu(t0, 'Label','Show All &Windows', 'HandleVisibility','off',... + 'CallBack','spm(''Show'');'); + +%-Dock SPM Figures +uimenu(t0, 'Label','&Dock SPM Windows', 'HandleVisibility','off',... + 'CallBack',@mydockspm); + +%-Print Menu +t1=uimenu(t0, 'Label','&Save Figure', 'HandleVisibility','off','Separator','on'); +uimenu(t1, 'Label','&Default File', 'HandleVisibility','off', ... + 'CallBack','spm_figure(''Print'',gcf)'); +uimenu(t1, 'Label','&Specify File...', 'HandleVisibility','off', ... + 'CallBack','spm_figure(''PrintTo'',spm_figure(''FindWin'',''Graphics''))'); + +%-Copy Figure +if ispc + uimenu(t0, 'Label','&Copy Figure', 'HandleVisibility','off',... + 'CallBack','editmenufcn(gcbf,''EditCopyFigure'')'); +end +%-Clear Menu +uimenu(t0, 'Label','C&lear Figure', 'HandleVisibility','off', ... + 'CallBack','spm_figure(''Clear'',gcbf)'); + +%-Colour Menu +t1=uimenu(t0, 'Label','C&olours', 'HandleVisibility','off','Separator','on'); +t2=uimenu(t1, 'Label','Colormap'); +uimenu(t2, 'Label','Gray', 'CallBack','spm_figure(''ColorMap'',''gray'')'); +uimenu(t2, 'Label','Hot', 'CallBack','spm_figure(''ColorMap'',''hot'')'); +uimenu(t2, 'Label','Pink', 'CallBack','spm_figure(''ColorMap'',''pink'')'); +uimenu(t2, 'Label','Jet', 'CallBack','spm_figure(''ColorMap'',''jet'')'); +uimenu(t2, 'Label','Gray-Hot', 'CallBack','spm_figure(''ColorMap'',''gray-hot'')'); +uimenu(t2, 'Label','Gray-Cool', 'CallBack','spm_figure(''ColorMap'',''gray-cool'')'); +uimenu(t2, 'Label','Gray-Pink', 'CallBack','spm_figure(''ColorMap'',''gray-pink'')'); +uimenu(t2, 'Label','Gray-Jet', 'CallBack','spm_figure(''ColorMap'',''gray-jet'')'); +t2=uimenu(t1, 'Label','Effects'); +uimenu(t2, 'Label','Invert', 'CallBack','spm_figure(''ColorMap'',''invert'')'); +uimenu(t2, 'Label','Brighten', 'CallBack','spm_figure(''ColorMap'',''brighten'')'); +uimenu(t2, 'Label','Darken', 'CallBack','spm_figure(''ColorMap'',''darken'')'); + +%-Satellite Table +uimenu(t0, 'Label','&Results Table', 'HandleVisibility','off', ... + 'Separator','on', 'Callback',@mysatfig); + +% Tasks Menu +%try, spm_jobman('pulldown'); end +%========================================================================== case 'figcontextmenu' -%======================================================================= +%========================================================================== % h = spm_figure('FigContextMenu',F) + if nargin<2 F = get(0,'CurrentFigure'); if isempty(F), error('no figure'), end @@ -783,19 +774,16 @@ F = spm_figure('FindWin',varargin{2}); if isempty(F), error('no such figure'), end end -h = uicontextmenu('Parent',F,'HandleVisibility','CallBack'); -cSHH = get(0,'ShowHiddenHandles'); -set(0,'ShowHiddenHandles','on') +h = uicontextmenu('Parent',F,'HandleVisibility','CallBack'); copy_menu(F,h); -set(0,'ShowHiddenHandles',cSHH) set(F,'UIContextMenu',h) varargout = {h}; - +%========================================================================== case 'colormap' -%======================================================================= -% spm_figure('ColorMap',ColAction,h) -if nargin<3, h=[]; else h=varargin{3}; end +%========================================================================== +% spm_figure('ColorMap',ColAction) + if nargin<2, ColAction='gray'; else ColAction=varargin{2}; end switch lower(ColAction), case 'gray' @@ -829,64 +817,259 @@ error('Illegal ColAction specification'); end -case 'graphicshandle' -%======================================================================= -% h = spm_figure('GraphicsHandle',F) -if nargin<2, F=gcbf; else F=spm_figure('FindWin',varargin{2}); end -if isempty(F), return, end - -tmp = get(F,'Name'); -set(F,'Name',... - 'Handle: Select item to identify, MiddleMouse=parent, RightMouse=cancel...'); -set(F,'Pointer','CrossHair') -waitforbuttonpress; -h = gco(F); -hType = get(h,'Type'); -SelnType = get(gcf,'SelectionType'); -set(F,'Pointer','Arrow','Name',tmp) - -if ~strcmp(SelnType,'alt') && ~isempty(h) && gcf==F - str = sprintf('Selected (%s) object',get(h,'Type')); - if strcmp(SelnType,'normal') - str = sprintf('%s: handle',str); - else - h = get(h,'Parent'); - str = sprintf('%s: handle of parent (%s) object',str,get(h,'Type')); - end - if nargout==0 - assignin('base','ans',h) - fprintf('\n%s: \n',str) - ans = h - else - varargout={h}; - end -else - varargout={[]}; +%========================================================================== +otherwise +%========================================================================== +warning(['Illegal Action string: ',Action]) end +return; +%========================================================================== +function myisresults(obj,evt) +%========================================================================== +hr = findall(obj,'Label','&Results Table'); +try + evalin('base','xSPM;'); + set(hr,'Enable','on'); +catch + set(hr,'Enable','off'); +end +SatWindow = spm_figure('FindWin','Satellite'); +if ~isempty(SatWindow) + set(hr,'Checked','on'); +else + set(hr,'Checked','off'); +end -otherwise -%======================================================================= -warning(['Illegal Action string: ',Action]) +%========================================================================== +function mysatfig(obj,evt) +%========================================================================== +SatWindow = spm_figure('FindWin','Satellite'); +if ~isempty(SatWindow) + figure(SatWindow) +else + FS = spm('FontSizes'); %-Scaled font sizes + PF = spm_platform('fonts'); %-Font names + WS = spm('WinSize','0','raw'); %-Screen size (of current monitor) + Rect = [WS(1)+5 WS(4)*.40 WS(3)*.49 WS(4)*.57]; + figure(... + 'Tag','Satellite',... + 'Position',Rect,... + 'Resize','off',... + 'MenuBar','none',... + 'Name','SPM: Satellite Results Table',... + 'Numbertitle','off',... + 'Color','w',... + 'ColorMap',gray(64),... + 'DefaultTextColor','k',... + 'DefaultTextInterpreter','none',... + 'DefaultTextFontName',PF.helvetica,... + 'DefaultTextFontSize',FS(10),... + 'DefaultAxesColor','w',... + 'DefaultAxesXColor','k',... + 'DefaultAxesYColor','k',... + 'DefaultAxesZColor','k',... + 'DefaultAxesFontName',PF.helvetica,... + 'DefaultPatchFaceColor','k',... + 'DefaultPatchEdgeColor','k',... + 'DefaultSurfaceEdgeColor','k',... + 'DefaultLineColor','k',... + 'DefaultUicontrolFontName',PF.helvetica,... + 'DefaultUicontrolFontSize',FS(10),... + 'DefaultUicontrolInterruptible','on',... + 'PaperType','A4',... + 'PaperUnits','normalized',... + 'PaperPosition',[.0726 .0644 .854 .870],... + 'InvertHardcopy','off',... + 'Renderer',spm_get_defaults('renderer'),... + 'Visible','on'); end -return; -%======================================================================= +%========================================================================== +function mydockspm(obj,evt) +%========================================================================== +% Largely inspired by setFigDockGroup from Yair Altman +% http://www.mathworks.com/matlabcentral/fileexchange/16650 +hMenu = spm_figure('FindWin','Menu'); +hInt = spm_figure('FindWin','Interactive'); +hGra = spm_figure('FindWin','Graphics'); +h = [hMenu hInt hGra]; +group = ['Statistical Parametric Mapping (' spm('Ver') ')']; +try + desktop = com.mathworks.mde.desk.MLDesktop.getInstance; + if ~ismember(group,cell(desktop.getGroupTitles)) + desktop.addGroup(group); + end + for i=1:length(h) + set(getJFrame(h(i)),'GroupName',group); + end + hContainer = desktop.getGroupContainer(group); + set(hContainer,'userdata',group); +end +set(h,'WindowStyle','docked'); +try, pause(0.5), desktop.setGroupDocked(group,false); end -%======================================================================= +%========================================================================== function copy_menu(F,G) -%======================================================================= -handles = findobj(get(F,'Children'),'Flat','Type','uimenu','Visible','on'); +%========================================================================== +handles = findall(allchild(F),'Flat','Type','uimenu','Visible','on'); if isempty(handles), return; end; -for F1=handles', - if ~strcmp(get(F1,'Label'),'&Window'), +for F1=handles(:)' + if ~ismember(get(F1,'Label'),{'&Window' '&Desktop'}) G1 = uimenu(G,'Label',get(F1,'Label'),... 'CallBack',get(F1,'CallBack'),... 'Position',get(F1,'Position'),... 'Separator',get(F1,'Separator')); copy_menu(F1,G1); - end; -end; -return; -%======================================================================= + end +end + +%========================================================================== +function jframe = getJFrame(h) +%========================================================================== +warning('off','MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame'); +hhFig = handle(h); +jframe = []; +maxTries = 16; +while maxTries > 0 + try + jframe = get(hhFig,'javaframe'); + if ~isempty(jframe) + break; + else + maxTries = maxTries - 1; + drawnow; pause(0.1); + end + catch + maxTries = maxTries - 1; + drawnow; pause(0.1); + end +end +if isempty(jframe) + error('Cannot retrieve the java frame from handle.'); +end + +%========================================================================== +function spm_about(obj,evt) +%========================================================================== +[v,r] = spm('Ver'); +h = figure('MenuBar','none',... + 'NumberTitle','off',... + 'Name',['About ' v],... + 'Resize','off',... + 'Toolbar','none',... + 'Tag','AboutSPM',... + 'WindowStyle','Modal',... + 'Color',[0 0 0],... + 'Visible','off',... + 'DoubleBuffer','on'); +pos = get(h,'Position'); +pos([3 4]) = [300 400]; +set(h,'Position',pos); +set(h,'Visible','on'); + +a = axes('Parent',h, 'Units','pixels', 'Position',[50 201 200 200],... + 'Visible','off'); +IMG = imread(fullfile(spm('Dir'),'man','images','spm8.png')); +image(IMG,'Parent',a); set(a,'Visible','off'); + +a = axes('Parent',h,'Units','pixels','Position',[0 0 300 400],... + 'Visible','off','Tag','textcont'); +text(0.5,0.45,'Statistical Parametric Mapping','Parent',a,... + 'HorizontalAlignment','center','Color',[1 1 1],'FontWeight','Bold'); +text(0.5,0.40,[v ' (v' r ')'],'Parent',a,'HorizontalAlignment','center',... + 'Color',[1 1 1]); +text(0.5,0.30,'Wellcome Trust Centre for Neuroimaging','Parent',a,... + 'HorizontalAlignment','center','Color',[1 1 1],'FontWeight','Bold'); +text(0.5,0.25,['Copyright (C) 1991,1994-2003, 2005-' datestr(now,'yyyy')],... + 'Parent',a,'HorizontalAlignment','center','Color',[1 1 1]); +text(0.5,0.20,'http://www.fil.ion.ucl.ac.uk/spm/','Parent',a,... + 'HorizontalAlignment','center','Color',[1 1 1],... + 'ButtonDownFcn','web(''http://www.fil.ion.ucl.ac.uk/spm/'');'); + +uicontrol('Style','pushbutton','String','Credits','Position',[40 25 60 25],... + 'Callback',@myscroll,'BusyAction','Cancel'); +uicontrol('Style','pushbutton','String','OK','Position',[200 25 60 25],... + 'Callback','close(gcf)','BusyAction','Cancel'); + +%========================================================================== +function myscroll(obj,evt) +%========================================================================== +ax = findobj(gcf,'Tag','textcont'); +cla(ax); +authors = spm_authors; +x = 0.2; +h = []; +for i=1:numel(authors) + h(i) = text(0.5,x,authors{i},'Parent',ax,... + 'HorizontalAlignment','center','Color',col(x)); + if any(authors{i} == '*') + set(h(i),'String',strrep(authors{i},'*',''),'FontWeight','Bold'); + end + x = x - 0.05; +end +pause(0.5); +try + for j=1:fix((0.5-(0.2-numel(authors)*0.05))/0.01) + for i=1:numel(h) + p = get(h(i),'Position'); + p2 = p(2)+0.01; + set(h(i),'Position',[p(1) p2 p(3)],'Color',col(p2)); + if p2 > 0.5, set(h(i),'Visible','off'); end + end + pause(0.1) + end +end + +%========================================================================== +function c = col(x) +%========================================================================== +if x < 0.4 && x > 0.3 + c = [1 1 1]; +elseif x <= 0.3 + c = [1 1 1] - 6*abs(0.3-x); +else + c = [1 1 1] - 6*abs(0.4-x); +end +c(c<0) = 0; c(c>1) = 1; + +%========================================================================== +function authors = spm_authors +%========================================================================== +authors = {... +'*SPM8*' +'John Ashburner' +'Gareth Barnes' +'Chun-Chuan Chen' +'Justin Chumbley' +'Jean Daunizeau' +'Guillaume Flandin' +'Karl Friston' +'Darren Gitelman' +'Volkmar Glauche' +'Lee Harrison' +'Rik Henson' +'Chloe Hutton' +'Maria Joao Rosa' +'Stefan Kiebel' +'James Kilner' +'Vladimir Litvak' +'Rosalyn Moran' +'Tom Nichols' +'Robert Oostenveld' +'Will Penny' +'Christophe Phillips' +'Klaas Enno Stephan' +'' +'*Previous versions*' +'Matthew Brett' +'Christian Buechel' +'Jon Heather' +'Andrew Holmes' +'Jeremie Mattout' +'Jean-Baptiste Poline' +'Keith Worsley' +'' +'*Thanks to the SPM community*' +}; diff --git a/spm_filtfilt.m b/spm_filtfilt.m deleted file mode 100644 index c57c65c..0000000 --- a/spm_filtfilt.m +++ /dev/null @@ -1,91 +0,0 @@ -function y = spm_filtfilt(b,a,x) -% Zero-phase forward and reverse digital filtering -% FORMAT y = spm_filtfilt(b,a,x) -% -% b - filter parameters (numerator) -% a - filter parameters (denominator) -% x - input data vector (if matrix, filter over columns) -% -% y - filtered data -%__________________________________________________________________________ -% -% The filter is described by the difference equation: -% -% y(n) = b(1)*x(n) + b(2)*x(n-1) + ... + b(nb+1)*x(n-nb) -% - a(2)*y(n-1) - ... - a(na+1)*y(n-na) -% -% After filtering in the forward direction, the filtered sequence is then -% reversed and run back through the filter; Y is the time reverse of the -% output of the second filtering operation. The result has precisely zero -% phase distortion and magnitude modified by the square of the filter's -% magnitude response. Care is taken to minimize startup and ending -% transients by matching initial conditions. -% -% The length of the input x must be more than three times -% the filter order, defined as max(length(b)-1,length(a)-1). -% -% References: -% [1] Sanjit K. Mitra, Digital Signal Processing, 2nd ed, McGraw-Hill, 2001 -% [2] Fredrik Gustafsson, Determining the initial states in forward-backward -% filtering, IEEE Transactions on Signal Processing, pp. 988--992, -% April 1996, Volume 44, Issue 4 -%__________________________________________________________________________ -% Copyright (C) 2009 Wellcome Trust Centre for Neuroimaging - -% L. Shure, T. Krauss, F. Gustafsson -% Copyright 1988-2004 The MathWorks, Inc. -% $Id: spm_filtfilt.m 3541 2009-11-06 17:34:40Z guillaume $ - -% Check input data -%-------------------------------------------------------------------------- -[m,n] = size(x); -if n>1 && m>1 - y = zeros(size(x)); - for i=1:n - y(:,i) = spm_filtfilt(b,a,x(:,i)); - end - return -end -if m==1, x = x(:); end -len = size(x,1); - -% Check filter parameters -%-------------------------------------------------------------------------- -b = b(:).'; a = a(:).'; -nb = length(b); na = length(a); -nfilt = max(nb,na); -if nb < nfilt, b(nfilt)=0; end -if na < nfilt, a(nfilt)=0; end - -nfact = 3*(nfilt-1); -if len <= nfact - error('Data must have length more than 3 times filter order.'); -end - -% Use sparse matrix to solve system of linear equations for initial -% conditions zi are the steady-state states of the filter b(z)/a(z) in the -% state-space implementation of the 'filter' command -%-------------------------------------------------------------------------- -rows = [1:nfilt-1 2:nfilt-1 1:nfilt-2]; -cols = [ones(1,nfilt-1) 2:nfilt-1 2:nfilt-1]; -data = [1+a(2) a(3:nfilt) ones(1,nfilt-2) -ones(1,nfilt-2)]; -sp = sparse(rows,cols,data); -zi = sp \ (b(2:nfilt).' - a(2:nfilt).'*b(1)); - -% Extrapolate beginning and end of data sequence using a "reflection -% method". Slopes of original and extrapolated sequences match at the end -% points. This reduces end effects -%-------------------------------------------------------------------------- -y = [2*x(1)-x((nfact+1):-1:2);x;2*x(len)-x((len-1):-1:len-nfact)]; - -% Filter, reverse data, filter again, and reverse data again -%-------------------------------------------------------------------------- -y = filter(b,a,y,zi*y(1)); -y = y(end:-1:1); -y = filter(b,a,y,zi*y(1)); -y = y(end:-1:1); - -% Reformat y -%-------------------------------------------------------------------------- -y([1:nfact len+nfact+(1:nfact)]) = []; -if m == 1, y = y.'; end diff --git a/spm_fmri_spm_ui.m b/spm_fmri_spm_ui.m index f4d3fa4..9c9917c 100644 --- a/spm_fmri_spm_ui.m +++ b/spm_fmri_spm_ui.m @@ -16,8 +16,8 @@ % % % SPM.xY -% P: [n x ? char] - filenames -% VY: [n x 1 struct] - filehandles +% P: [n x ? char] - filenames +% VY: [n x 1 struct] - filehandles % RT: Repeat time % % SPM.xGX @@ -30,15 +30,15 @@ % gSF: [n x 1 double] - Global scaling factor % % SPM.xVi -% Vi: {[n x n sparse]..} - covariance components -% form: {'none'|'AR(1)'} - form of non-sphericity +% Vi: {[n x n sparse]..} - covariance components +% form: {'none'|'AR(1)'} - form of non-sphericity % % SPM.xM -% T: [n x 1 double] - Masking index -% TH: [n x 1 double] - Threshold +% T: [n x 1 double] - Masking index +% TH: [n x 1 double] - Threshold % I: 0 -% VM: - Mask filehandles -% xs: [1x1 struct] - cellstr description +% VM: - Mask filehandles +% xs: [1x1 struct] - cellstr description % % (see also spm_spm_ui) % @@ -172,17 +172,14 @@ %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -% Karl Friston, Jean-Baptiste Poline & Christian Büchel -% $Id: spm_fmri_spm_ui.m 3468 2009-10-15 18:59:38Z karl $ +% Karl Friston, Jean-Baptiste Poline & Christian Buchel +% $Id: spm_fmri_spm_ui.m 3691 2010-01-20 17:08:30Z guillaume $ -SCCSid = '$Rev: 3468 $'; +SVNid = '$Rev: 3691 $'; %-GUI setup %-------------------------------------------------------------------------- [Finter,Fgraph,CmdLine] = spm('FnUIsetup','fMRI stats model setup',0); -spm_help('!ContextHelp',mfilename) - -global defaults % get design matrix and/or data %========================================================================== @@ -194,7 +191,7 @@ % specify a design %------------------------------------------------------------------ if sf_abort, spm_clf(Finter), return, end - SPM = spm_fMRI_design; + SPM = spm_fMRI_design; spm_fMRI_design_show(SPM); return @@ -217,17 +214,15 @@ % get Repeat time %-------------------------------------------------------------------------- try - RT = SPM.xY.RT; + SPM.xY.RT; catch - RT = spm_input('Interscan interval {secs}','+1'); - SPM.xY.RT = RT; + SPM.xY.RT = spm_input('Interscan interval {secs}','+1'); end - % session and scan number %-------------------------------------------------------------------------- -nscan = SPM.nscan; -nsess = length(nscan); +nscan = SPM.nscan; +nsess = length(nscan); % check data are specified %-------------------------------------------------------------------------- @@ -237,30 +232,27 @@ % get filenames %---------------------------------------------------------------------- - P = []; + P = []; for i = 1:nsess - str = sprintf('select scans for session %0.0f',i); - q = spm_select(nscan(i),'image',str); - P = strvcat(P,q); + str = sprintf('select scans for session %0.0f',i); + q = spm_select(nscan(i),'image',str); + P = strvcat(P,q); end % place in data field %---------------------------------------------------------------------- - SPM.xY.P = P; + SPM.xY.P = P; end - % Assemble remaining design parameters %========================================================================== -spm_help('!ContextHelp',mfilename) -SPM.SPMid = spm('FnBanner',mfilename,SCCSid); +SPM.SPMid = spm('FnBanner',mfilename,SVNid); % Global normalization %-------------------------------------------------------------------------- -nsess = length(SPM.nscan); try SPM.xGX.iGXcalc; catch @@ -280,35 +272,28 @@ try myLastWarn = 0; HParam = [SPM.xX.K(:).HParam]; - if ( length(HParam) == 1 ) + if length(HParam) == 1 HParam = HParam*ones(1,nsess); - elseif ( length(HParam) ~= nsess ) - - % The number of specified HParam values and sessions do not match. - % Throw an error, continue with manual HPF specification, and go to - % the catch block + elseif length(HParam) ~= nsess myLastWarn = 1; - error; + error('Continue with manual HPF specification in the catch block'); end catch - % specify low frequency confounds %---------------------------------------------------------------------- spm_input('Temporal autocorrelation options','+1','d',mfilename) switch spm_input('High-pass filter?','+1','b','none|specify'); - case 'specify' % default 128 seconds + case 'specify' % default in seconds %-------------------------------------------------------------- - HParam = 128*ones(1,nsess); + HParam = spm_get_defaults('stats.fmri.hpf')*ones(1,nsess); str = 'cutoff period (secs)'; HParam = spm_input(str,'+1','e',HParam,[1 nsess]); case 'none' % Inf seconds (i.e. constant term only) %-------------------------------------------------------------- - HParam = Inf*ones(1,nsess); + HParam = Inf(1,nsess); end - % This avoids displaying the warning if we had exited the try block - % at the level of accessing HParam. if myLastWarn warning('SPM:InvalidHighPassFilterSpec',... ['Different number of High-pass filter values and sessions.\n',... @@ -320,20 +305,19 @@ % create and set filter struct %-------------------------------------------------------------------------- for i = 1:nsess - K(i) = struct( 'HParam', HParam(i),... - 'row', SPM.Sess(i).row,... - 'RT', SPM.xY.RT); + K(i) = struct('HParam', HParam(i),... + 'row', SPM.Sess(i).row,... + 'RT', SPM.xY.RT); end SPM.xX.K = spm_filter(K); - % intrinsic autocorrelations (Vi) %-------------------------------------------------------------------------- try cVi = SPM.xVi.form; catch % Construct Vi structure for non-sphericity ReML estimation - %====================================================================== + %---------------------------------------------------------------------- str = 'Correct for serial correlations?'; cVi = {'none','AR(1)'}; cVi = spm_input(str,'+1','b',cVi); @@ -367,7 +351,6 @@ SPM.xVi.form = cVi; - %========================================================================== % - C O N F I G U R E D E S I G N %========================================================================== @@ -381,10 +364,9 @@ %-Map files %-------------------------------------------------------------------------- -fprintf('%-40s: ','Mapping files') %-# +fprintf('%-40s: ','Mapping files') %-# VY = spm_vol(SPM.xY.P); -fprintf('%30s\n','...done') %-# - +fprintf('%30s\n','...done') %-# %-check internal consistency of images %-------------------------------------------------------------------------- @@ -400,17 +382,17 @@ GM = 100; q = length(VY); g = zeros(q,1); -fprintf('%-40s: %30s','Calculating globals',' ') %-# +fprintf('%-40s: %30s','Calculating globals',' ') %-# for i = 1:q - fprintf('%s%30s',repmat(sprintf('\b'),1,30),sprintf('%4d/%-4d',i,q)) %-# + fprintf('%s%30s',repmat(sprintf('\b'),1,30),sprintf('%4d/%-4d',i,q))%-# g(i) = spm_global(VY(i)); end -fprintf('%s%30s\n',repmat(sprintf('\b'),1,30),'...done') %-# +fprintf('%s%30s\n',repmat(sprintf('\b'),1,30),'...done') %-# % scale if specified (otherwise session specific grand mean scaling) %-------------------------------------------------------------------------- gSF = GM./g; -if strcmp(lower(SPM.xGX.iGXcalc),'none') +if strcmpi(SPM.xGX.iGXcalc,'none') for i = 1:nsess gSF(SPM.Sess(i).row) = GM./mean(g(SPM.Sess(i).row)); end @@ -432,21 +414,21 @@ %-Masking structure automatically set to 80% of mean %========================================================================== try - TH = g.*gSF*defaults.mask.thresh; + TH = g.*gSF*spm_get_defaults('mask.thresh'); catch TH = g.*gSF*0.8; end -SPM.xM = struct( 'T', ones(q,1),... - 'TH', TH,... - 'I', 0,... - 'VM', {[]},... - 'xs', struct('Masking','analysis threshold')); +SPM.xM = struct('T', ones(q,1),... + 'TH', TH,... + 'I', 0,... + 'VM', {[]},... + 'xs', struct('Masking','analysis threshold')); %-Design description - for saving and display %========================================================================== for i = 1:nsess, ntr(i) = length(SPM.Sess(i).U); end -Fstr = sprintf('[min] Cutoff period %d seconds',min(HParam)); +Fstr = sprintf('[min] Cutoff: %d {s}',min([SPM.xX.K(:).HParam])); SPM.xsDes = struct(... 'Basis_functions', SPM.xBF.name,... 'Number_of_sessions', sprintf('%d',nsess),... @@ -459,22 +441,24 @@ %-Save SPM.mat -%-------------------------------------------------------------------------- -fprintf('%-40s: ','Saving SPM configuration') %-# +%========================================================================== +fprintf('%-40s: ','Saving SPM configuration') %-# if spm_matlab_version_chk('7') >= 0, save('SPM', 'SPM', '-V6'); else save('SPM', 'SPM'); -end; -fprintf('%30s\n','...SPM.mat saved') %-# +end +fprintf('%30s\n','...SPM.mat saved') %-# %-Display Design report %========================================================================== -fprintf('%-40s: ','Design reporting') %-# -fname = cat(1,{SPM.xY.VY.fname}'); -spm_DesRep('DesMtx',SPM.xX,fname,SPM.xsDes) -fprintf('%30s\n','...done') %-# +if ~CmdLine + fprintf('%-40s: ','Design reporting') %-# + fname = cat(1,{SPM.xY.VY.fname}'); + spm_DesRep('DesMtx',SPM.xX,fname,SPM.xsDes) + fprintf('%30s\n','...done') %-# +end %-End: Cleanup GUI @@ -482,7 +466,6 @@ spm_clf(Finter) spm('FigName','Stats: configured',Finter,CmdLine); spm('Pointer','Arrow') -fprintf('\n\n') %========================================================================== @@ -491,7 +474,7 @@ function abort = sf_abort %========================================================================== -if exist(fullfile('.','SPM.mat')) +if exist(fullfile(pwd,'SPM.mat'),'file') str = { 'Current directory contains existing SPM file:',... 'Continuing will overwrite existing file!'}; diff --git a/spm_fx_dcm.m b/spm_fx_dcm.m index d5081e8..a186747 100644 --- a/spm_fx_dcm.m +++ b/spm_fx_dcm.m @@ -1,5 +1,5 @@ function [y] = spm_fx_dcm(x,u,P,M) -% state equation for a dynamic [bilinear/nonlinear/Balloon] model of fMRI +% state equation for a dynamic [bilinear/nonlinear/Balloon] model of fMRI % responses % FORMAT [y] = spm_fx_dcm(x,u,P,M) % x - state vector @@ -13,98 +13,71 @@ % % References for hemodynamic & neuronal state equations: % 1. Buxton RB, Wong EC & Frank LR. Dynamics of blood flow and oxygenation -% changes during brain activation: The Balloon model. MRM 39:855-864, +% changes during brain activation: The Balloon model. MRM 39:855-864, % 1998. -% 2. Friston KJ, Mechelli A, Turner R, Price CJ. Nonlinear responses in -% fMRI: the Balloon model, Volterra kernels, and other hemodynamics. +% 2. Friston KJ, Mechelli A, Turner R, Price CJ. Nonlinear responses in +% fMRI: the Balloon model, Volterra kernels, and other hemodynamics. % Neuroimage 12:466-477, 2000. -% 3. Stephan KE, Kasper L, Harrison LM, Daunizeau J, den Ouden HE, -% Breakspear M, Friston KJ. Nonlinear dynamic causal models for fMRI. -% Neuroimage 42:649-662, 2008. -%___________________________________________________________________________ +% 3. Stephan KE, Kasper L, Harrison LM, Daunizeau J, den Ouden HE, +% Breakspear M, Friston KJ. Nonlinear dynamic causal models for fMRI. +% Neuroimage 42:649-662, 2008. +%__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston & Klaas Enno Stephan -% $Id: spm_fx_dcm.m 2517 2008-12-02 10:36:11Z klaas $ +% $Id: spm_fx_dcm.m 3705 2010-02-01 20:51:28Z karl $ % hemodynamic parameters -%--------------------------------------------------------------------------- +%-------------------------------------------------------------------------- % H(1) - signal decay d(ds/dt)/ds) % H(2) - autoregulation d(ds/dt)/df) % H(3) - transit time (t0) % H(4) - exponent for Fout(v) (alpha) % H(5) - resting oxygen extraction (E0) % H(6) - ratio of intra- to extra-vascular components (epsilon) -% of the gradient echo signal +% of the gradient echo signal -% get dimensions -%--------------------------------------------------------------------------- -if size(u,2) > size(u,1) % make sure u is a column vector - u = u'; -end -if size(x,2) > size(x,1) % make sure x is a column vector - x = x'; -end -m = size(u,1); % number of inputs -n = size(x,1)/5; % number of regions +% Neuronal motion +%========================================================================== -% reshape parameters -%--------------------------------------------------------------------------- -if ~M.nlDCM - % bilinear DCM - [A B C H] = spm_dcm_reshape(P,m,n); -else - % nonlinear DCM - [A B C H D] = spm_dcm_reshape(P,m,n); +% effective intrinsic connectivity with bilinear (input) terms +%-------------------------------------------------------------------------- +for i = 1:size(P.B,3) + P.A = P.A + u(i)*P.B(:,:,i); end -% effective intrinsic connectivity -%--------------------------------------------------------------------------- -for i = 1:m - A = A + u(i)*B(:,:,i); +% and nonlinear (state) terms +%-------------------------------------------------------------------------- +for i = 1:size(P.D,3) + P.A = P.A + x(i,1)*P.D(:,:,i); end -% configure state variables -%--------------------------------------------------------------------------- -x = reshape(x,n,5); +% implement differential state equation y = dx/dt (neuronal) +%-------------------------------------------------------------------------- +y = x; +y(:,1) = exp(P.b)*(P.A*x(:,1) + P.C*u); + -% modulatory (2nd order) terms -%--------------------------------------------------------------------------- -if M.nlDCM - % nonlinear DCM - xD = zeros(size(A,1),size(A,1)); - for j = 1:n, - xD = xD + x(j,1)*D(:,:,j); - end -end +% Hemodynamic motion +%========================================================================== % exponentiation of hemodynamic state variables %-------------------------------------------------------------------------- -x(:,3:5) = exp(x(:,3:5)); +x(:,3:5) = exp(x(:,3:5)); % Fout = f(v) - outflow -%--------------------------------------------------------------------------- -fv = x(:,4).^(1./H(:,4)); +%-------------------------------------------------------------------------- +fv = x(:,4).^(1./P.H(:,4)); % e = f(f) - oxygen extraction -%--------------------------------------------------------------------------- -ff = (1 - (1 - H(:,5)).^(1./x(:,3)))./H(:,5); +%-------------------------------------------------------------------------- +ff = (1 - (1 - P.H(:,5)).^(1./x(:,3)))./P.H(:,5); -% implement differential state equation y = dx/dt -%--------------------------------------------------------------------------- -y = zeros(n,5); -if ~M.nlDCM - % bilinear DCM - y(:,1) = A*x(:,1) + C*u; -else - % nonlinear DCM - y(:,1) = A*x(:,1) + C*u + xD*x(:,1); -end -y(:,2) = x(:,1) - H(:,1).*x(:,2) - H(:,2).*(x(:,3) - 1); +% implement differential state equation y = dx/dt (hemodynamic) +%-------------------------------------------------------------------------- +y(:,2) = x(:,1) - P.H(:,1).*x(:,2) - P.H(:,2).*(x(:,3) - 1); y(:,3) = x(:,2)./x(:,3); -y(:,4) = (x(:,3) - fv)./(H(:,3).*x(:,4)); -y(:,5) = (ff.*x(:,3) - fv.*x(:,5)./x(:,4))./(H(:,3).*x(:,5)); +y(:,4) = (x(:,3) - fv)./(P.H(:,3).*x(:,4)); +y(:,5) = (ff.*x(:,3) - fv.*x(:,5)./x(:,4))./(P.H(:,3).*x(:,5)); y = y(:); - -return diff --git a/spm_fx_fmri.m b/spm_fx_fmri.m new file mode 100644 index 0000000..12432bf --- /dev/null +++ b/spm_fx_fmri.m @@ -0,0 +1,128 @@ +function [y] = spm_fx_fmri(x,u,P,M) +% state equation for a dynamic [bilinear/nonlinear/Balloon] model of fMRI +% responses +% FORMAT [y] = spm_fx_fmri(x,u,P,M) + +% x - state vector +% x(:,1) - excitatory neuronal activity ue +% x(:,2) - vascular signal s +% x(:,3) - rCBF ln(f) +% x(:,4) - venous volume ln(v) +% x(:,5) - deoyxHb ln(q) +% [x(:,6) - inhibitory neuronal activity ui] +% +% y - dx/dt +% +%___________________________________________________________________________ +% +% References for hemodynamic & neuronal state equations: +% 1. Buxton RB, Wong EC & Frank LR. Dynamics of blood flow and oxygenation +% changes during brain activation: The Balloon model. MRM 39:855-864, +% 1998. +% 2. Friston KJ, Mechelli A, Turner R, Price CJ. Nonlinear responses in +% fMRI: the Balloon model, Volterra kernels, and other hemodynamics. +% Neuroimage 12:466-477, 2000. +% 3. Stephan KE, Kasper L, Harrison LM, Daunizeau J, den Ouden HE, +% Breakspear M, Friston KJ. Nonlinear dynamic causal models for fMRI. +% Neuroimage 42:649-662, 2008. +% 4. Marreiros AC, Kiebel SJ, Friston KJ. Dynamic causal modelling for +% fMRI: a two-state model. +% Neuroimage. 2008 Jan 1;39(1):269-78. +%__________________________________________________________________________ + +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston & Klaas Enno Stephan +% $Id: spm_fx_fmri.m 3888 2010-05-15 18:49:56Z karl $ + + +% Neuronal motion +%========================================================================== +P.B = full(P.B); % bi-linear parameters +P.C = P.C/16; % exogenous parameters +P.D = full(P.D); % nonlinear parameters + +% excitatory connections +%-------------------------------------------------------------------------- +for i = 1:size(P.B,3) + P.A = P.A + u(i)*P.B(:,:,i); +end + +% and nonlinear (state) terms +%-------------------------------------------------------------------------- +for i = 1:size(P.D,3) + P.A = P.A + x(i,1)*P.D(:,:,i); +end + +% implement differential state equation y = dx/dt (neuronal) +%-------------------------------------------------------------------------- +y = x; +if size(x,2) == 5 + + % one neuronal state per region + %---------------------------------------------------------------------- + y(:,1) = P.A*x(:,1) + P.C*u(:); + +else + + % extrinsic (two neuronal states) + %---------------------------------------------------------------------- + A = exp(P.A)/8; % enforce positivity + IE = diag(diag(A)); % inhibitory to excitatory + EE = A - IE; % excitatory to excitatory + EI = 1; % excitatory to inhibitory + SE = 1; % self-inhibition (excitatory) + SI = 2; % self-inhibition (inhibitory) + + % motion - excitatory and inhibitory: y = dx/dt + %---------------------------------------------------------------------- + y(:,1) = EE*x(:,1) - SE*x(:,1) - IE*x(:,6) + P.C*u(:); + y(:,6) = EI*x(:,1) - SI*x(:,6); + +end + +% Hemodynamic motion +%========================================================================== + +% hemodynamic parameters +%-------------------------------------------------------------------------- +% H(1) - signal decay d(ds/dt)/ds) +% H(2) - autoregulation d(ds/dt)/df) +% H(3) - transit time (t0) +% H(4) - exponent for Fout(v) (alpha) +% H(5) - resting oxygen extraction (E0) +% H(6) - ratio of intra- to extra-vascular components (epsilon) +% of the gradient echo signal +%-------------------------------------------------------------------------- +H = [0.65 0.41 2.00 0.32 0.34]; +H = [0.64 0.32 2.00 0.32 0.32]; + + +% exponentiation of hemodynamic state variables +%-------------------------------------------------------------------------- +x(:,3:5) = exp(x(:,3:5)); + +% signal decay +%-------------------------------------------------------------------------- +sd = H(1)*exp(P.decay); + +% transit time +%-------------------------------------------------------------------------- +tt = H(3)*exp(P.transit); + +% Fout = f(v) - outflow +%-------------------------------------------------------------------------- +fv = x(:,4).^(1/H(4)); + +% e = f(f) - oxygen extraction +%-------------------------------------------------------------------------- +ff = (1 - (1 - H(5)).^(1./x(:,3)))/H(5); + + +% implement differential state equation y = dx/dt (hemodynamic) +%-------------------------------------------------------------------------- +y(:,2) = x(:,1) - sd.*x(:,2) - H(2)*(x(:,3) - 1); +y(:,3) = x(:,2)./x(:,3); +y(:,4) = (x(:,3) - fv)./(tt.*x(:,4)); +y(:,5) = (ff.*x(:,3) - fv.*x(:,5)./x(:,4))./(tt.*x(:,5)); +y = y(:); diff --git a/spm_fx_fmri_dcm.m b/spm_fx_fmri_dcm.m new file mode 100644 index 0000000..be555e7 --- /dev/null +++ b/spm_fx_fmri_dcm.m @@ -0,0 +1,97 @@ +function [y] = spm_fx_fmri_dcm(x,u,P,M) +% state equation for a two state DCM of fMRI +% responses +% FORMAT [y] = spm_fx_dcm(x,u,P,M) +% x - state vector +% x(:,1) - excitatory neuronal activity ue +% x(:,2) - vascular signal s +% x(:,3) - rCBF ln(f) +% x(:,4) - venous volume ln(v) +% x(:,5) - deoyxHb ln(q) +% x(:,6) - inhibitory neuronal activity ui +% +% y - dx/dt +%__________________________________________________________________________ +% +% References for state equations: +% 1. Marreiros AC, Kiebel SJ, Friston KJ. Dynamic causal modelling for +% fMRI: a two-state model. +% Neuroimage. 2008 Jan 1;39(1):269-78. +% +% 2. Stephan KE, Kasper L, Harrison LM, Daunizeau J, den Ouden HE, +% Breakspear M, Friston KJ. Nonlinear dynamic causal models for fMRI. +% Neuroimage 42:649-662, 2008. +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: spm_fx_fmri_dcm.m 3705 2010-02-01 20:51:28Z karl $ + + +% hemodynamic parameters +%-------------------------------------------------------------------------- +% H(1) - signal decay d(ds/dt)/ds) +% H(2) – auto-regulation d(ds/dt)/df) +% H(3) - transit time (t0) +% H(4) - exponent for Fout(v) (alpha) +% H(5) - resting oxygen extraction (E0) +% H(6) - ratio of intra- to extra-vascular components (epsilon) +% of the gradient echo signal + + +% neuronal states +%========================================================================== + +% excitatory connections +%-------------------------------------------------------------------------- +for i = 1:size(P.B,3) + P.A = P.A + u(i)*P.B(:,:,i); +end + +% and nonlinear (state) terms +%-------------------------------------------------------------------------- +for i = 1:size(P.D,3) + P.A = P.A + x(i,1)*P.D(:,:,i); +end + +% extrinsic +%-------------------------------------------------------------------------- +A = exp(P.A)/8; % enforce positivity +IE = diag(diag(A)); % inhibitory to excitatory +EE = A - IE; % excitatory to excitatory +EI = 1; % excitatory to inhibitory +SE = 1; % self-inhibition (excitatory) +SI = 2; % self-inhibition (inhibitory) + +% motion - excitatory and inhibitory: y = dx/dt +%-------------------------------------------------------------------------- +y = x; +y(:,1) = EE*x(:,1) - SE*x(:,1) - IE*x(:,6) + P.C*u; +y(:,6) = EI*x(:,1) - SI*x(:,6); + + +% hemodynamic states +%========================================================================== + +% exponentiation of hemodynamic state variables +%-------------------------------------------------------------------------- +x(:,3:5) = exp(x(:,3:5)); + +% Fout = f(v) - outflow +%-------------------------------------------------------------------------- +fv = x(:,4).^(1./P.H(:,4)); + +% e = f(f) - oxygen extraction +%-------------------------------------------------------------------------- +ff = (1 - (1 - P.H(:,5)).^(1./x(:,3)))./P.H(:,5); + +% implement differential state equation y = dx/dt +%-------------------------------------------------------------------------- +y(:,2) = x(:,1) - P.H(:,1).*x(:,2) - P.H(:,2).*(x(:,3) - 1); +y(:,3) = x(:,2)./x(:,3); +y(:,4) = (x(:,3) - fv)./(P.H(:,3).*x(:,4)); +y(:,5) = (ff.*x(:,3) - fv.*x(:,5)./x(:,4))./(P.H(:,3).*x(:,5)); +y = y(:); + + +return diff --git a/spm_fx_poly.m b/spm_fx_poly.m new file mode 100644 index 0000000..bf4193c --- /dev/null +++ b/spm_fx_poly.m @@ -0,0 +1,26 @@ +function [f] = spm_fx_poly(x,v,P) +% Normal (bilinear) form equation of motion +% FORMAT [f] = spm_fx_poly(x,v,P) +% x - state vector +% v - exogenous cause +% P - free parameters +% +% f - dx/dt +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: spm_fx_poly.m 3878 2010-05-07 19:53:54Z karl $ + +% compute Jacobian from blinear terms +%-------------------------------------------------------------------------- +x = spm_vec(x); +J = P.A; +for i = 1:length(P.B) + J = J + P.B{i}*x(i); +end +for i = 1:length(P.C) + J = J + P.C{i}*v(i); +end +f = J*x; + diff --git a/spm_getSPM.m b/spm_getSPM.m index 410e54a..d2019a7 100644 --- a/spm_getSPM.m +++ b/spm_getSPM.m @@ -1,5 +1,5 @@ function [SPM,xSPM] = spm_getSPM(varargin) -% Compute a specified and thresholded SPM/PPM following parameter estimation +% Compute a specified and thresholded SPM/PPM following estimation % FORMAT [SPM,xSPM] = spm_getSPM; % Query SPM in interactive mode. % @@ -52,14 +52,14 @@ % .c - Contrast weights (column vector contrasts) % .X0 - Reduced design matrix data (spans design space under Ho) % Stored as coordinates in the orthogonal basis of xX.X from spm_sp -% (Matrix in SPM99b) Extract using X0 = spm_FcUtil('X0',... +% Extract using X0 = spm_FcUtil('X0',... % .iX0 - Indicates how contrast was specified: % If by columns for reduced design matrix then iX0 contains the % column indices. Otherwise, it's a string containing the % spm_FcUtil 'Set' action: Usually one of {'c','c+','X0'} % .X1o - Remaining design space data (X1o is orthogonal to X0) % Stored as coordinates in the orthogonal basis of xX.X from spm_sp -% (Matrix in SPM99b) Extract using X1o = spm_FcUtil('X1o',... +% Extract using X1o = spm_FcUtil('X1o',... % .eidf - Effective interest degrees of freedom (numerator df) % - Or effect-size threshold for Posterior probability % .Vcon - Name of contrast (for 'T's) or ESS (for 'F's) image @@ -71,6 +71,7 @@ % .swd - SPM working directory - directory containing current SPM.mat % .title - title for comparison (string) % .Ic - indices of contrasts (in SPM.xCon) +% .n - conjunction number <= number of contrasts % .Im - indices of masking contrasts (in xCon) % .pm - p-value for masking (uncorrected) % .Ex - flag for exclusive or inclusive masking @@ -82,7 +83,7 @@ % contrasts, SPM images (spmT_????.{img,hdr}) are written, along with % contrast (con_????.{img,hdr}) images for SPM{T}'s, or Extra % Sum-of-Squares images (ess_????.{img,hdr}) for SPM{F}'s. -% +% % The contrast images are the weighted sum of the parameter images, % where the weights are the contrast weights, and are uniquely % estimable since contrasts are checked for estimability by the @@ -97,14 +98,14 @@ % % spm_getSPM prompts for an SPM and applies thresholds {u & k} % to a point list of voxel values (specified with their locations {XYZ}) -% This allows the SPM be displayed and characterized in terms of regionally +% This allows the SPM be displayed and characterized in terms of regionally % significant effects by subsequent routines. -% +% % For general linear model Y = XB + E with data Y, design matrix X, % parameter vector B, and (independent) errors E, a contrast c'B of the % parameters (with contrast weights c) is estimated by c'b, where b are % the parameter estimates given by b=pinv(X)*Y. -% +% % Either single contrasts can be examined or conjunctions of different % contrasts. Contrasts are estimable linear combinations of the % parameters, and are specified using the SPM contrast manager @@ -112,7 +113,7 @@ % that the contrast is zero (or zero vector in the case of % F-contrasts). See the help for the contrast manager [spm_conman.m] % for a further details on contrasts and contrast specification. -% +% % A conjunction assesses the conjoint expression of multiple effects. The % conjunction SPM is the minimum of the component SPMs defined by the % multiple contrasts. Inference on the minimum statistics can be @@ -128,8 +129,8 @@ % alternative that k>0, that one or more effects are real. A third % Intermediate approach, is to use a null hypothesis of no more than u % effects are real. Rejecting the intermediate null that k<=u implies an -% alternative that k>u, that more than u of the effects are real. -% +% alternative that k>u, that more than u of the effects are real. +% % The Global and Intermediate nulls use results for minimum fields which % require the SPMs to be identically distributed and independent. Thus, % all component SPMs must be either SPM{t}'s, or SPM{F}'s with the same @@ -140,7 +141,7 @@ % the data space implied by the null hypotheses defined by the contrasts % (c'pinv(X)). Furthermore, this assumes that the errors are % i.i.d. (i.e. the estimates are maximum likelihood or Gauss-Markov. This -% is the default in spm_spm). +% is the default in spm_spm). % % To ensure approximate independence of the component SPMs in the case of % the global or intermediate null, non-orthogonal contrasts are serially @@ -155,7 +156,7 @@ % do not survive an uncorrected p value (based on height) in one or % more further contrasts. No account is taken of this masking in the % statistical inference pertaining to the masked contrast. -% +% % The SPM is subject to thresholding on the basis of height (u) and the % number of voxels comprising its clusters {k}. The height threshold is % specified as above in terms of an [un]corrected p value or @@ -174,32 +175,33 @@ % contrast exceeds a specified threshold. This threshold is stored in % the xCon.eidf. Subsequent plotting and tables will use the conditional % estimates and associated posterior or conditional probabilities. -% +% % see spm_results_ui.m for further details of the SPM results section. % see also spm_contrasts.m %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Andrew Holmes, Karl Friston & Jean-Baptiste Poline -% $Id: spm_getSPM.m 3465 2009-10-14 15:14:29Z guillaume $ +% $Id: spm_getSPM.m 3980 2010-07-08 15:55:37Z karl $ %-GUI setup %-------------------------------------------------------------------------- spm_help('!ContextHelp',mfilename) +spm('Pointer','Arrow') %-Select SPM.mat & note SPM results directory %-------------------------------------------------------------------------- -if (nargin > 0) +if nargin xSPM = varargin{1}; end try - swd = xSPM.swd; - sts = 1; + swd = xSPM.swd; + sts = 1; catch [spmmatfile, sts] = spm_select(1,'^SPM\.mat$','Select SPM.mat'); swd = spm_str_manip(spmmatfile,'H'); -end; +end if ~sts, SPM = []; xSPM = []; return; end %-Preliminaries... @@ -222,7 +224,7 @@ %-Check the model has been estimated %-------------------------------------------------------------------------- try - XYZ = SPM.xVol.XYZ; + SPM.xVol.XYZ; catch %-Check the model has been estimated @@ -230,7 +232,7 @@ str = { 'This model has not been estimated.';... 'Would you like to estimate it now?'}; if spm_input(str,1,'bd','yes|no',[1,0],1) - SPM = spm_spm(SPM); + SPM = spm_spm(SPM); else SPM = []; xSPM = []; return @@ -245,24 +247,13 @@ VOX = sqrt(diag(M'*M))'; %-voxel dimensions % check the data and other files have valid filenames -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- try, SPM.xY.VY = spm_check_filename(SPM.xY.VY); end try, SPM.xVol.VRpv = spm_check_filename(SPM.xVol.VRpv); end try, SPM.Vbeta = spm_check_filename(SPM.Vbeta); end try, SPM.VResMS = spm_check_filename(SPM.VResMS); end try, SPM.VM = spm_check_filename(SPM.VM); end -%-Contrast definitions -%========================================================================== - -%-Load contrast definitions (if available) -%-------------------------------------------------------------------------- -try - xCon = SPM.xCon; -catch - xCon = {}; -end - %========================================================================== % - C O N T R A S T S , S P M C O M P U T A T I O N , M A S K I N G @@ -270,11 +261,13 @@ %-Get contrasts %-------------------------------------------------------------------------- +try, xCon = SPM.xCon; catch, xCon = {}; end + try - Ic = xSPM.Ic; + Ic = xSPM.Ic; catch [Ic,xCon] = spm_conman(SPM,'T&F',Inf,... - ' Select contrasts...',' for conjunction',1); + ' Select contrasts...',' for conjunction',1); end if isempty(xCon) % figure out whether new contrasts were defined, but not selected @@ -295,112 +288,112 @@ %-Allow user to extend the null hypothesis for conjunctions % % n: conjunction number -% u: Null hyp is k<=u effects real; Alt hyp is k>u effects real +% u: Null hyp is k<=u effects real; Alt hyp is k>u effects real % (NB Here u is from Friston et al 2004 paper, not statistic thresh). -% u n +% u n % Conjunction Null nc-1 1 | u = nc-n % Intermediate 1..nc-2 nc-u | #effects under null <= u % Global Null 0 nc | #effects under alt > u, >= u+1 %----------------------------------+--------------------------------------- -if (nc > 1) - if nc==2 - But = 'Conjunction|Global'; Val=[1 nc]; - else - But = 'Conj''n|Intermed|Global'; Val=[1 NaN nc]; - end - n = spm_input('Null hyp. to assess?','+1','b',But,Val,1); - if isnan(n) - if nc==3, - n = nc - 1; +if nc > 1 + try + n = xSPM.n; + catch + if nc==2 + But = 'Conjunction|Global'; Val=[1 nc]; else - n = nc - spm_input('Effects under null ','0','n1','1',nc-1); + But = 'Conj''n|Intermed|Global'; Val=[1 NaN nc]; + end + n = spm_input('Null hyp. to assess?','+1','b',But,Val,1); + if isnan(n) + if nc == 3, + n = nc - 1; + else + n = nc - spm_input('Effects under null ','0','n1','1',nc-1); + end end end else n = 1; end - %-Enforce orthogonality of multiple contrasts for conjunction % (Orthogonality within subspace spanned by contrasts) %-------------------------------------------------------------------------- -if nc>1 && n>1 && ~spm_FcUtil('|_?',xCon(Ic), xX.xKXs) - +if nc > 1 && n > 1 && ~spm_FcUtil('|_?',xCon(Ic), xX.xKXs) + OrthWarn = 0; - + %-Successively orthogonalise %-NB: This loop is peculiarly controlled to account for the % possibility that Ic may shrink if some contrasts disappear % on orthogonalisation (i.e. if there are colinearities) %---------------------------------------------------------------------- - i = 1; + i = 1; while(i < nc), i = i + 1; - + %-Orthogonalise (subspace spanned by) contrast i w.r.t. previous %------------------------------------------------------------------ oxCon = spm_FcUtil('|_',xCon(Ic(i)), xX.xKXs, xCon(Ic(1:i-1))); - + %-See if this orthogonalised contrast has already been entered % or is colinear with a previous one. Define a new contrast if % neither is the case. %------------------------------------------------------------------ d = spm_FcUtil('In',oxCon,xX.xKXs,xCon); - + if spm_FcUtil('0|[]',oxCon,xX.xKXs) - + %-Contrast was colinear with a previous one - drop it %-------------------------------------------------------------- Ic(i) = []; i = i - 1; - + elseif any(d) - + %-Contrast unchanged or already defined - note index %-------------------------------------------------------------- Ic(i) = min(d); - + else - - OrthWarn = OrthWarn + 1; - + %-Define orthogonalised contrast as new contrast %-------------------------------------------------------------- + OrthWarn = OrthWarn + 1; conlst = sprintf('%d,',Ic(1:i-1)); oxCon.name = sprintf('%s (orth. w.r.t {%s})', xCon(Ic(i)).name,... - conlst(1:end-1)); - xCon = [xCon, oxCon]; - Ic(i) = length(xCon); + conlst(1:end-1)); + xCon = [xCon, oxCon]; + Ic(i) = length(xCon); end - + end % while... if OrthWarn - warning(sprintf(['Contrasts changed! %d contrasts orthogonalized ',... - 'to allow conjunction inf.'], OrthWarn)) + warning('SPM:ConChange','%d contrasts orthogonalized',OrthWarn) end - + SPM.xCon = xCon; end % if nc>1... SPM.xCon = xCon; -%-Get contrasts for masking +%-Apply masking %-------------------------------------------------------------------------- try - Im = xSPM.Im; - if ~isempty(Im) - maskCon = 1; - else - maskCon = 0; - end + Mask = ~isempty(xSPM.Im) * (isnumeric(xSPM.Im) + 2*iscellstr(xSPM.Im)); catch - maskCon = spm_input('mask with other contrast(s)','+1','y/n',[1,0],2); + % Mask = spm_input('mask with other contrast(s)','+1','y/n',[1,0],2); + Mask = spm_input('apply masking','+1','b','none|contrast|image',[0,1,2],1); end -if maskCon +if Mask == 1 + + %-Get contrasts for masking + %---------------------------------------------------------------------- try - Im = xSPM.Im; + Im = xSPM.Im; catch [Im,xCon] = spm_conman(SPM,'T&F',-Inf,... - 'Select contrasts for masking...',' for masking',1); + 'Select contrasts for masking...',' for masking',1); end %-Threshold for mask (uncorrected p-value) @@ -416,8 +409,29 @@ try Ex = xSPM.Ex; catch - Ex = spm_input('nature of mask','+1','b','inclusive|exclusive',[0,1]); + Ex = spm_input('nature of mask','+1','b','inclusive|exclusive',[0,1],1); + end + +elseif Mask == 2 + + %-Get mask images + %---------------------------------------------------------------------- + try + Im = xSPM.Im; + catch + Im = cellstr(spm_select([1 Inf],'image','Select mask image(s)')); + end + + %-Inclusive or exclusive masking + %---------------------------------------------------------------------- + try + Ex = xSPM.Ex; + catch + Ex = spm_input('nature of mask','+1','b','inclusive|exclusive',[0,1],1); end + + pm = []; + else Im = []; pm = []; @@ -444,13 +458,22 @@ else mstr = 'masked [incl.] by'; end -if length(Im) == 1 - str = sprintf('%s (%s %s at p=%g)',str,mstr,xCon(Im).name,pm); - -elseif ~isempty(Im) - str = [sprintf('%s (%s {%d',str,mstr,Im(1)),... - sprintf(',%d',Im(2:end)),... - sprintf('} at p=%g)',pm)]; +if isnumeric(Im) + if length(Im) == 1 + str = sprintf('%s (%s %s at p=%g)',str,mstr,xCon(Im).name,pm); + elseif ~isempty(Im) + str = [sprintf('%s (%s {%d',str,mstr,Im(1)),... + sprintf(',%d',Im(2:end)),... + sprintf('} at p=%g)',pm)]; + end +elseif iscellstr(Im) && numel(Im) > 0 + [pf,nf,ef] = spm_fileparts(Im{1}); + str = sprintf('%s (%s %s',str,mstr,[nf ef]); + for i=2:numel(Im) + [pf,nf,ef] = spm_fileparts(Im{i}); + str =[str sprintf(', %s',[nf ef])]; + end + str = [str ')']; end try titlestr = xSPM.title; @@ -458,43 +481,53 @@ titlestr = str; end catch - titlestr = spm_input('title for comparison','+1','s',str); + titlestr = spm_input('title for comparison','+1','s',str); end %-Bayesian or classical Inference? -%-------------------------------------------------------------------------- -if isfield(SPM,'PPM') +%========================================================================== +if isfield(SPM,'PPM') % Make sure SPM.PPM.xCon field exists + %---------------------------------------------------------------------- if ~isfield(SPM.PPM,'xCon') SPM.PPM.xCon = []; end % Set Bayesian con type - if length(SPM.PPM.xCon) < Ic - SPM.PPM.xCon(Ic).PSTAT = xCon(Ic).STAT; + %---------------------------------------------------------------------- + if length(SPM.PPM.xCon) < Ic + SPM.PPM.xCon(Ic).PSTAT = xCon(Ic).STAT; end % Make this one a Bayesian contrast - if first level + %---------------------------------------------------------------------- if isfield(SPM.PPM,'VB') [xCon(Ic).STAT] = deal('P'); end if all(strcmp([SPM.PPM.xCon(Ic).PSTAT],'T')) + % Simple contrast + %------------------------------------------------------------------ str = 'Effect size threshold for PPM'; if isfield(SPM.PPM,'VB') % 1st level Bayes + % For VB - set default effect size to zero + %-------------------------------------------------------------- Gamma = 0; xCon(Ic).eidf = spm_input(str,'+1','e',sprintf('%0.2f',Gamma)); elseif nc == 1 && isempty(xCon(Ic).Vcon) % 2nd level Bayes % con image not yet written + %-------------------------------------------------------------- if spm_input('Inference',1,'b',{'Bayesian','classical'},[1 0]); + %-Get Bayesian threshold (Gamma) stored in xCon(Ic).eidf % The default is one conditional s.d. of the contrast + %---------------------------------------------------------- Gamma = sqrt(xCon(Ic).c'*SPM.PPM.Cb*xCon(Ic).c); xCon(Ic).eidf = spm_input(str,'+1','e',sprintf('%0.2f',Gamma)); xCon(Ic).STAT = 'P'; @@ -502,6 +535,7 @@ end else % Compound contrast using Chi^2 statistic + %------------------------------------------------------------------ if ~isfield(xCon(Ic),'eidf') || isempty(xCon(Ic).eidf) xCon(Ic).eidf = 0; % temporarily end @@ -512,7 +546,11 @@ %-Compute & store contrast parameters, contrast/ESS images, & SPM images %========================================================================== SPM.xCon = xCon; -SPM = spm_contrasts(SPM, unique([Ic, Im, IcAdd])); +if isnumeric(Im) + SPM = spm_contrasts(SPM, unique([Ic, Im, IcAdd])); +else + SPM = spm_contrasts(SPM, unique([Ic, IcAdd])); +end xCon = SPM.xCon; STAT = xCon(Ic(1)).STAT; VspmSv = cat(1,xCon(Ic).Vspm); @@ -520,16 +558,16 @@ %-Check conjunctions - Must be same STAT w/ same df %-------------------------------------------------------------------------- if (nc > 1) && (any(diff(double(cat(1,xCon(Ic).STAT)))) || ... - any(abs(diff(cat(1,xCon(Ic).eidf))) > 1)) + any(abs(diff(cat(1,xCon(Ic).eidf))) > 1)) error('illegal conjunction: can only conjoin SPMs of same STAT & df'); end %-Degrees of Freedom and STAT string describing marginal distribution %-------------------------------------------------------------------------- -df = [xCon(Ic(1)).eidf xX.erdf]; -if nc>1 - if n>1 +df = [xCon(Ic(1)).eidf xX.erdf]; +if nc > 1 + if n > 1 str = sprintf('^{%d \\{Ha:k\\geq%d\\}}',nc,(nc-n)+1); else str = sprintf('^{%d \\{Ha:k=%d\\}}',nc,(nc-n)+1); @@ -555,8 +593,8 @@ %-Compute conjunction as minimum of SPMs %-------------------------------------------------------------------------- -Z = Inf; -for i = Ic +Z = Inf; +for i = Ic Z = min(Z,spm_get_data(xCon(i).Vspm,XYZ)); end @@ -568,21 +606,28 @@ %-Compute mask and eliminate masked voxels %-------------------------------------------------------------------------- -for i = Im +for i = 1:numel(Im) + fprintf('%s%30s',repmat(sprintf('\b'),1,30),'...masking') %-# - - Mask = spm_get_data(xCon(i).Vspm,XYZ); - um = spm_u(pm,[xCon(i).eidf,xX.erdf],xCon(i).STAT); - if Ex - Q = Mask <= um; + if isnumeric(Im) + Mask = spm_get_data(xCon(Im(i)).Vspm,XYZ); + um = spm_u(pm,[xCon(Im(i)).eidf,xX.erdf],xCon(Im(i)).STAT); + if Ex + Q = Mask <= um; + else + Q = Mask > um; + end else - Q = Mask > um; + v = spm_vol(Im{i}); + Mask = spm_get_data(v,v.mat\SPM.xVol.M*[XYZ; ones(1,size(XYZ,2))]); + Q = Mask ~= 0 & ~isnan(Mask); + if Ex, Q = ~Q; end end XYZ = XYZ(:,Q); Z = Z(Q); if isempty(Q) fprintf('\n') %-# - warning(sprintf('No voxels survive masking at p=%4.2f',pm)); + warning('SPM:NoVoxels','No voxels survive masking at p=%4.2f',pm); break end end @@ -597,23 +642,21 @@ %-Get FDR mode %-------------------------------------------------------------------------- -defaults = spm('GetGlobal','defaults'); try - topoFDR = defaults.stats.topoFDR; + topoFDR = spm_get_defaults('stats.topoFDR'); catch topoFDR = true; end - + %-Height threshold - classical inference %-------------------------------------------------------------------------- if STAT ~= 'P' - - fprintf('%s%30s',repmat(sprintf('\b'),1,30),'...height threshold') %-# %-Get height threshold %---------------------------------------------------------------------- + fprintf('%s%30s',repmat(sprintf('\b'),1,30),'...height threshold') %-# try - thresDesc = xSPM.thresDesc; + thresDesc = xSPM.thresDesc; catch if topoFDR str = 'FWE|none'; @@ -626,96 +669,98 @@ switch thresDesc case 'FWE' % Family-wise false positive rate - %------------------------------------------------------------------ - try - u = xSPM.u; - catch - u = spm_input('p value (FWE)','+0','r',0.05,1,[0,1]); - end - thresDesc = ['p<' num2str(u) ' (' thresDesc ')']; - u = spm_uc(u,df,STAT,R,n,S); - - + %-------------------------------------------------------------- + try + u = xSPM.u; + catch + u = spm_input('p value (FWE)','+0','r',0.05,1,[0,1]); + end + thresDesc = ['p<' num2str(u) ' (' thresDesc ')']; + u = spm_uc(u,df,STAT,R,n,S); + + case 'FDR' % False discovery rate - %------------------------------------------------------------------ - if topoFDR, - fprintf('\n'); %-# - error('Change defaults.stats.topoFDR to use voxel FDR.'); - end - try - u = xSPM.u; - catch - u = spm_input('p value (FDR)','+0','r',0.05,1,[0,1]); - end - thresDesc = ['p<' num2str(u) ' (' thresDesc ')']; - u = spm_uc_FDR(u,df,STAT,n,VspmSv,0); - - case 'none' % No adjustment - % p for conjunctions is p of the conjunction SPM - %------------------------------------------------------------------ - try - u = xSPM.u; - catch - u = spm_input(['threshold {',STAT,' or p value}'],'+0','r',0.001,1); - end - if u <= 1 - thresDesc = ['p<' num2str(u) ' (unc.)']; - u = spm_u(u^(1/n),df,STAT); - else - thresDesc = [STAT '=' num2str(u) ]; - end - - + %-------------------------------------------------------------- + if topoFDR, + fprintf('\n'); %-# + error('Change defaults.stats.topoFDR to use voxel FDR'); + end + try + u = xSPM.u; + catch + u = spm_input('p value (FDR)','+0','r',0.05,1,[0,1]); + end + thresDesc = ['p<' num2str(u) ' (' thresDesc ')']; + u = spm_uc_FDR(u,df,STAT,n,VspmSv,0); + + case 'none' % No adjustment: p for conjunctions is p of the conjunction SPM + %-------------------------------------------------------------- + try + u = xSPM.u; + catch + u = spm_input(['threshold {',STAT,' or p value}'],'+0','r',0.001,1); + end + if u <= 1 + thresDesc = ['p<' num2str(u) ' (unc.)']; + u = spm_u(u^(1/n),df,STAT); + else + thresDesc = [STAT '=' num2str(u) ]; + end + + otherwise - %------------------------------------------------------------------ - fprintf('\n'); %-# - error(sprintf('Unknown control method "%s".',thresDesc)); - + %-------------------------------------------------------------- + fprintf('\n'); %-# + error('Unknown control method "%s".',thresDesc); + end % switch thresDesc %-Compute p-values for topological and voxel-wise FDR (all search voxels) %---------------------------------------------------------------------- if ~topoFDR - %-Voxel-wise FDR fprintf('%s%30s',repmat(sprintf('\b'),1,30),'...for voxelFDR') %-# switch STAT case 'Z' - Ps = (1-spm_Ncdf(Zum)).^n; + Ps = (1-spm_Ncdf(Zum)).^n; case 'T' - Ps = (1 - spm_Tcdf(Zum,df(2))).^n; + Ps = (1 - spm_Tcdf(Zum,df(2))).^n; case 'X' - Ps = (1-spm_Xcdf(Zum,df(2))).^n; + Ps = (1-spm_Xcdf(Zum,df(2))).^n; case 'F' - Ps = (1 - spm_Fcdf(Zum,df)).^n; + Ps = (1 - spm_Fcdf(Zum,df)).^n; end Ps = sort(Ps); - %uv = spm_uc_FDR(0.05,df,STAT,n,VspmSv,0); end %-Peak FDR - [up, Pp] = spm_uc_peakFDR(0.05,df,STAT,R,n,Zum,XYZum,u); - + %---------------------------------------------------------------------- + [up,Pp] = spm_uc_peakFDR(0.05,df,STAT,R,n,Zum,XYZum,u); + %-Cluster FDR + %---------------------------------------------------------------------- if STAT == 'T' && n == 1 - V2R = 1/prod(SPM.xVol.FWHM(SPM.xVol.DIM>1)); - [uc, Pc, ue] = spm_uc_clusterFDR(0.05,df,STAT,R,n,Zum,XYZum,V2R,u); + V2R = 1/prod(SPM.xVol.FWHM(SPM.xVol.DIM > 1)); + [uc,Pc,ue] = spm_uc_clusterFDR(0.05,df,STAT,R,n,Zum,XYZum,V2R,u); else - uc = NaN; - ue = NaN; - Pc = []; + uc = NaN; + ue = NaN; + Pc = []; end - + %-Peak FWE - uu = spm_uc(0.05,df,STAT,R,n,S); + %---------------------------------------------------------------------- + uu = spm_uc(0.05,df,STAT,R,n,S); + %-Height threshold - Bayesian inference %-------------------------------------------------------------------------- elseif STAT == 'P' - + u_default = 1 - 1/SPM.xVol.S; - u = spm_input(['Posterior probability threshold for PPM'],'+0','r',u_default,1); + str = 'Posterior probability threshold for PPM'; + u = spm_input(str,'+0','r',u_default,1); thresDesc = ['P>' num2str(u) ' (PPM)']; - + end % (if STAT) %-Calculate height threshold filtering @@ -728,14 +773,14 @@ XYZ = XYZ(:,Q); if isempty(Q) fprintf('\n'); %-# - warning(sprintf('No voxels survive height threshold u=%0.2g',u)) + warning('SPM:NoVoxels','No voxels survive masking at p=%4.2f',pm); end %-Extent threshold (disallowed for conjunctions) %-------------------------------------------------------------------------- if ~isempty(XYZ) && nc == 1 - + fprintf('%s%30s',repmat(sprintf('\b'),1,30),'...extent threshold') %-# %-Get extent threshold [default = 0] @@ -754,20 +799,20 @@ j = find(A == i); if length(j) >= k; Q = [Q j]; end end - + % ...eliminate voxels %---------------------------------------------------------------------- Z = Z(:,Q); XYZ = XYZ(:,Q); if isempty(Q) fprintf('\n'); %-# - warning(sprintf('No voxels survive extent threshold k=%0.2g',k)) + warning('SPM:NoVoxels','No voxels survive masking at p=%4.2f',pm); end - + else - + k = 0; - + end % (if ~isempty(XYZ)) %-For Bayesian inference provide (default) option to display contrast values @@ -781,52 +826,52 @@ %========================================================================== % - E N D %========================================================================== -fprintf('%s%30s\n',repmat(sprintf('\b'),1,30),'...done') %-# +fprintf('%s%30s\n',repmat(sprintf('\b'),1,30),'...done') %-# spm('Pointer','Arrow') %-Assemble output structures of unfiltered data %========================================================================== xSPM = struct( ... - 'swd', swd,... - 'title', titlestr,... - 'Z', Z,... - 'n', n,... - 'STAT', STAT,... - 'df', df,... - 'STATstr', STATstr,... - 'Ic', Ic,... - 'Im', Im,... - 'pm', pm,... - 'Ex', Ex,... - 'u', u,... - 'k', k,... - 'XYZ', XYZ,... - 'XYZmm', SPM.xVol.M(1:3,:)*[XYZ; ones(1,size(XYZ,2))],... - 'S', SPM.xVol.S,... - 'R', SPM.xVol.R,... - 'FWHM', SPM.xVol.FWHM,... - 'M', SPM.xVol.M,... - 'iM', SPM.xVol.iM,... - 'DIM', SPM.xVol.DIM,... - 'VOX', VOX,... - 'Vspm', VspmSv,... - 'thresDesc',thresDesc); - -% RESELS per voxel (density) if it exists + 'swd', swd,... + 'title', titlestr,... + 'Z', Z,... + 'n', n,... + 'STAT', STAT,... + 'df', df,... + 'STATstr', STATstr,... + 'Ic', Ic,... + 'Im', {Im},... + 'pm', pm,... + 'Ex', Ex,... + 'u', u,... + 'k', k,... + 'XYZ', XYZ,... + 'XYZmm', SPM.xVol.M(1:3,:)*[XYZ; ones(1,size(XYZ,2))],... + 'S', SPM.xVol.S,... + 'R', SPM.xVol.R,... + 'FWHM', SPM.xVol.FWHM,... + 'M', SPM.xVol.M,... + 'iM', SPM.xVol.iM,... + 'DIM', SPM.xVol.DIM,... + 'VOX', VOX,... + 'Vspm', VspmSv,... + 'thresDesc',thresDesc); + +%-RESELS per voxel (density) if it exists %-------------------------------------------------------------------------- -try, xSPM.VRpv = SPM.VRpv; end +try, xSPM.VRpv = SPM.xVol.VRpv; end try - xSPM.units = SPM.xVol.units; + xSPM.units = SPM.xVol.units; catch - try, xSPM.units = varargin{1}.units; end; + try, xSPM.units = varargin{1}.units; end end -% p-values for topological and voxel-wise FDR +%-p-values for topological and voxel-wise FDR %-------------------------------------------------------------------------- -try, xSPM.Ps = Ps; end % voxel FDR -try, xSPM.Pp = Pp; end % peak FDR +try, xSPM.Ps = Ps; end % voxel FDR +try, xSPM.Pp = Pp; end % peak FDR try, xSPM.Pc = Pc; end % cluster FDR -% 0.05 critical thresholds for FWEp, FDRp, FWEc, FDRc +%-0.05 critical thresholds for FWEp, FDRp, FWEc, FDRc %-------------------------------------------------------------------------- try, xSPM.uc = [uu up ue uc]; end diff --git a/spm_get_bf.m b/spm_get_bf.m index d3603da..e2a5a15 100644 --- a/spm_get_bf.m +++ b/spm_get_bf.m @@ -4,7 +4,7 @@ % % xBF.dt - time bin length {seconds} % xBF.name - description of basis functions specified -% xBF.length - window length (secs) +% xBF.length - window length (seconds) % xBF.order - order % xBF.bf - Matrix of basis functions % @@ -16,39 +16,35 @@ % 'Gamma functions' % 'Finite Impulse Response'}; % -% (any other specifiaction will default to hrf) -%_______________________________________________________________________ +% (any other specification will default to hrf) +%__________________________________________________________________________ % % spm_get_bf prompts for basis functions to model event or epoch-related % responses. The basis functions returned are unitary and orthonormal % when defined as a function of peri-stimulus time in time-bins. % It is at this point that the distinction between event and epoch-related % responses enters. -%_______________________________________________________________________ +%__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging - + % Karl Friston -% $Id: spm_get_bf.m 1143 2008-02-07 19:33:33Z spm $ - - -%-GUI setup -%----------------------------------------------------------------------- -spm_help('!ContextHelp',mfilename) - +% $Id: spm_get_bf.m 3934 2010-06-17 14:58:25Z guillaume $ + + % length of time bin -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- if ~nargin str = 'time bin for basis functions {secs}'; xBF.dt = spm_input(str,'+1','r',1/16,1); end dt = xBF.dt; - - + + % assemble basis functions -%======================================================================= - +%========================================================================== + % model event-related responses -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- if ~isfield(xBF,'name') spm_input('Hemodynamic Basis functions...',1,'d') Ctype = { @@ -63,14 +59,14 @@ Sel = spm_input(str,2,'m',Ctype); xBF.name = Ctype{Sel}; end - + % get order and length parameters -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- switch xBF.name - + case { 'Fourier set','Fourier set (Hanning)',... 'Gamma functions','Finite Impulse Response'} - %--------------------------------------------------------------- + %---------------------------------------------------------------------- try, l = xBF.length; catch, l = spm_input('window length {secs}',3,'e',32); xBF.length = l; @@ -80,101 +76,101 @@ xBF.order = h; end end - - - + + + % create basis functions -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- switch xBF.name - + case {'Fourier set','Fourier set (Hanning)'} - %--------------------------------------------------------------- + %---------------------------------------------------------------------- pst = [0:dt:l]'; pst = pst/max(pst); - + % hanning window - %--------------------------------------------------------------- + %---------------------------------------------------------------------- if strcmp(xBF.name,'Fourier set (Hanning)') g = (1 - cos(2*pi*pst))/2; else g = ones(size(pst)); end - + % zeroth and higher Fourier terms - %--------------------------------------------------------------- + %---------------------------------------------------------------------- bf = g; for i = 1:h bf = [bf g.*sin(i*2*pi*pst)]; bf = [bf g.*cos(i*2*pi*pst)]; end - + case {'Gamma functions'} - %--------------------------------------------------------------- + %---------------------------------------------------------------------- pst = [0:dt:l]'; bf = spm_gamma_bf(pst,h); - + case {'Finite Impulse Response'} - %--------------------------------------------------------------- + %---------------------------------------------------------------------- bin = l/h; bf = kron(eye(h),ones(round(bin/dt),1)); - + case {'NONE'} - %--------------------------------------------------------------- + %---------------------------------------------------------------------- bf = 1; - + otherwise - - % canonical hemodynaic response function - %--------------------------------------------------------------- + + % canonical hemodynamic response function + %---------------------------------------------------------------------- [bf p] = spm_hrf(dt); - + % add time derivative - %--------------------------------------------------------------- - if findstr(xBF.name,'time') - + %---------------------------------------------------------------------- + if strfind(xBF.name,'time') + dp = 1; p(6) = p(6) + dp; D = (bf(:,1) - spm_hrf(dt,p))/dp; bf = [bf D(:)]; p(6) = p(6) - dp; - + % add dispersion derivative - %-------------------------------------------------------- - if findstr(xBF.name,'dispersion') - + %------------------------------------------------------------------ + if strfind(xBF.name,'dispersion') + dp = 0.01; p(3) = p(3) + dp; D = (bf(:,1) - spm_hrf(dt,p))/dp; bf = [bf D(:)]; end end - + % length and order - %--------------------------------------------------------------- + %---------------------------------------------------------------------- xBF.length = size(bf,1)*dt; xBF.order = size(bf,2); - + end - - -% Orthogonalize and fill in basis function structure -%------------------------------------------------------------------------ + + +% Orthogonalise and fill in basis function structure +%-------------------------------------------------------------------------- xBF.bf = spm_orth(bf); - - -%======================================================================= + + +%========================================================================== %- S U B - F U N C T I O N S -%======================================================================= - -% compute Gamma functions functions -%----------------------------------------------------------------------- +%========================================================================== + +% compute Gamma functions +%-------------------------------------------------------------------------- function bf = spm_gamma_bf(u,h) % returns basis functions used for Volterra expansion % FORMAT bf = spm_gamma_bf(u,h); % u - times {seconds} % h - order % bf - basis functions (mixture of Gammas) -%_______________________________________________________________________ +%__________________________________________________________________________ u = u(:); bf = []; for i = 2:(1 + h) diff --git a/spm_get_data.m b/spm_get_data.m index 84ea357..51e564a 100644 --- a/spm_get_data.m +++ b/spm_get_data.m @@ -3,7 +3,7 @@ % FORMAT [Y] = spm_get_data(V,XYZ); % % V - [1 x n] struct array of file handles (or filename matrix) -% XYZ - [4 x m] or [3 x m]location matrix (voxel) +% XYZ - [4 x m] or [3 x m] location matrix (voxel) % check - check validity of input parameters [default: true] % % Y - (n x m) double values @@ -13,11 +13,11 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_get_data.m 3297 2009-07-29 17:20:19Z guillaume $ +% $Id: spm_get_data.m 3950 2010-06-28 10:44:02Z guillaume $ if nargin < 3, check = true; end -% ensure V is an array of handle structures +%-Ensure V is an array of handle structures %-------------------------------------------------------------------------- if check && ~isstruct(V) V = spm_vol(V); @@ -26,12 +26,12 @@ end end -% get data +%-Get data %-------------------------------------------------------------------------- Y = zeros(length(V),size(XYZ,2)); for i = 1:length(V) - % check files exists and try pwd + %-Check files exists and try current directory otherwise %---------------------------------------------------------------------- if check && ~spm_existfile(V(i).fname) [p,n,e] = fileparts(V(i).fname); @@ -40,6 +40,11 @@ %-Load data %---------------------------------------------------------------------- - Y(i,:) = spm_sample_vol(V(i),XYZ(1,:),XYZ(2,:),XYZ(3,:),0); + try + Y(i,:) = spm_sample_vol(V(i),XYZ(1,:),XYZ(2,:),XYZ(3,:),0); + catch + fprintf('Error with file %s\n',V(i).fname); + rethrow(lasterror); + end end diff --git a/spm_get_defaults.m b/spm_get_defaults.m index 46e15ea..c58390b 100644 --- a/spm_get_defaults.m +++ b/spm_get_defaults.m @@ -1,5 +1,8 @@ function varargout = spm_get_defaults(defstr, varargin) % Get/set the defaults values associated with an identifier +% FORMAT defaults = spm_get_defaults +% Return the global "defaults" variable defined in spm_defaults.m. +% % FORMAT defval = spm_get_defaults(defstr) % Return the defaults value associated with identifier "defstr". % Currently, this is a '.' subscript reference into the global @@ -16,13 +19,18 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Volkmar Glauche -% $Id: spm_get_defaults.m 2696 2009-02-05 20:29:48Z guillaume $ +% $Id: spm_get_defaults.m 3692 2010-01-21 21:43:31Z guillaume $ global defaults; if isempty(defaults) spm_defaults; end +if nargin == 0 + varargout{1} = defaults; + return +end + % construct subscript reference struct from dot delimited tag string tags = textscan(defstr,'%s', 'delimiter','.'); subs = struct('type','.','subs',tags{1}'); diff --git a/spm_get_ons.m b/spm_get_ons.m index 7b013c1..f867116 100644 --- a/spm_get_ons.m +++ b/spm_get_ons.m @@ -42,13 +42,9 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_get_ons.m 3677 2010-01-14 04:46:29Z Darren $ +% $Id: spm_get_ons.m 3691 2010-01-20 17:08:30Z guillaume $ -%-GUI setup -%-------------------------------------------------------------------------- -spm_help('!ContextHelp',mfilename) - % time units %-------------------------------------------------------------------------- k = SPM.nscan(s); diff --git a/spm_grid.m b/spm_grid.m index 71e7ad4..d79fcdd 100644 --- a/spm_grid.m +++ b/spm_grid.m @@ -6,29 +6,18 @@ %___________________________________________________________________________ % % spm_grid adds a grid to the input argument. The grid is scaled -% to defaults.grid times the imput's maximum, where defaults.grid is a user -% specified global variable -% +% to 10% of the iuput's maximum. %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_grid.m 1143 2008-02-07 19:33:33Z spm $ - +% $Id: spm_grid.m 3691 2010-01-20 17:08:30Z guillaume $ -%--------------------------------------------------------------------------- -global defaults -if ~isempty(defaults) & isfield(defaults,'grid'), - GRID = defaults.grid/4; -else, - return; -end; +GRID = 0.1; -if GRID - load('Grid.mat','i','j'); - [x y] = size(I); - i = round(1 + (i - 1)*(x - 1)/64); - j = round(1 + (j - 1)*(y - 1)/86); - G = full(sparse(i,j,max(I(:))*GRID*ones(length(i),1))); - I = max(I,G); -end +load('Grid.mat','i','j'); +[x y] = size(I); +i = round(1 + (i - 1)*(x - 1)/64); +j = round(1 + (j - 1)*(y - 1)/86); +G = full(sparse(i,j,max(I(:))*GRID*ones(length(i),1))); +I = max(I,G); diff --git a/spm_gx_dcm.m b/spm_gx_dcm.m index 5283060..b48e19b 100644 --- a/spm_gx_dcm.m +++ b/spm_gx_dcm.m @@ -4,7 +4,7 @@ % y - BOLD response (%) % x - state vector (see spm_fx_dcm) % P - Parameter vector (see spm_fx_dcm) -% M - model specification structure (see spm_nlsi) +% M - model specification structure (see spm_nlsi) %__________________________________________________________________________ % % This function implements the BOLD signal model described in: @@ -13,70 +13,49 @@ % Comparing hemodynamic models with DCM. NeuroImage 38: 387-401. %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging - + % Karl Friston & Klaas Enno Stephan -% $Id: spm_gx_dcm.m 3547 2009-11-09 18:29:59Z guillaume $ - - +% $Id: spm_gx_dcm.m 3705 2010-02-01 20:51:28Z karl $ + + % Biophysical constants for 1.5T %========================================================================== - -% time to echo (TE) + +% time to echo (TE) (default 0.04 sec) %-------------------------------------------------------------------------- -try - TE = M.TE; -catch - TE = 0.04; -end - +try, TE = M.TE; catch, TE = 0.04; end + % resting venous volume %-------------------------------------------------------------------------- -V0 = 100*0.04; - +V0 = 100*0.04; + % slope r0 of intravascular relaxation rate R_iv as a function of oxygen % saturation Y: R_iv = r0*[(1-Y)-(1-Y0)] %-------------------------------------------------------------------------- -r0 = 25; % [Hz] - +r0 = 25; % [Hz] + % frequency offset at the outer surface of magnetized vessels %-------------------------------------------------------------------------- -nu0 = 40.3; % [Hz] - - -% Get estimates of hemodynamic parameters -%========================================================================== -m = max(size(u)); % number of inputs -n = max(size(x)/5); % number of regions -[A B C H] = spm_dcm_reshape(P,m,n); -%H = reshape(p(end-n*6+1:end),n,6); % faster direct access to parameters - +nu0 = 40.3; % [Hz] + % estimated region-specific resting oxygen extraction fractions %-------------------------------------------------------------------------- -E0 = H(:,5); - -% estimated region-specific ratios of intra- to extravascular components of +E0 = P.H(:,5); + +% estimated region-specific ratios of intra- to extra-vascular components of % the gradient echo signal (prior mean = 1, log-normally distributed % scaling factor) %-------------------------------------------------------------------------- -epsilon = exp(H(:,6)); - - +ep = exp(P.H(:,6)); + %-Coefficients in BOLD signal model %========================================================================== -k1 = 4.3.*nu0.*E0.*TE; -k2 = epsilon.*r0.*E0.*TE; -k3 = 1 - epsilon; - - -%-Exponentiation of hemodynamic state variables -%========================================================================== -x = reshape(x,n,5); -x(:,2:5) = exp(x(:,2:5)); - - +k1 = 4.3.*nu0.*E0.*TE; +k2 = ep.*r0.*E0.*TE; +k3 = 1 - ep; + %-Output equation of BOLD signal model %========================================================================== -v = x(:,4); -q = x(:,5); -% predicted BOLD response -y = V0*(k1.*(1-q) + k2.*(1-(q./v)) + k3.*(1-v)); +v = exp(x(:,4)); +q = exp(x(:,5)); +y = V0*(k1.*(1 - q) + k2.*(1 - q./v) + k3.*(1 - v)); diff --git a/spm_gx_fmri.m b/spm_gx_fmri.m new file mode 100644 index 0000000..69567b9 --- /dev/null +++ b/spm_gx_fmri.m @@ -0,0 +1,59 @@ +function [y] = spm_gx_fmri(x,u,P,M) +% Simulated BOLD response to input +% FORMAT [y] = spm_gx_fmri(x,u,P,M) +% y - BOLD response (%) +% x - state vector (see spm_fx_dcm) +% P - Parameter vector (see spm_fx_dcm) +% M - model specification structure (see spm_nlsi) +%__________________________________________________________________________ +% +% This function implements the BOLD signal model described in: +% +% Stephan KE, Weiskopf N, Drysdale PM, Robinson PA, Friston KJ (2007) +% Comparing hemodynamic models with DCM. NeuroImage 38: 387-401. +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston & Klaas Enno Stephan +% $Id: spm_gx_fmri.m 3888 2010-05-15 18:49:56Z karl $ + + +% Biophysical constants for 1.5T +%========================================================================== + +% time to echo (TE) (default 0.04 sec) +%-------------------------------------------------------------------------- +try, TE = M.TE; catch, TE = 0.04; end + +% resting venous volume (%) +%-------------------------------------------------------------------------- +V0 = 4; + +% estimated region-specific ratios of intra- to extra-vascular signal +%-------------------------------------------------------------------------- +ep = 1*exp(P.epsilon); + +% slope r0 of intravascular relaxation rate R_iv as a function of oxygen +% saturation S: R_iv = r0*[(1 - S)-(1 - S0)] (Hz) +%-------------------------------------------------------------------------- +r0 = 25; + +% frequency offset at the outer surface of magnetized vessels (Hz) +%-------------------------------------------------------------------------- +nu0 = 40.3; + +% resting oxygen extraction fraction +%-------------------------------------------------------------------------- +E0 = 0.4; + +%-Coefficients in BOLD signal model +%========================================================================== +k1 = 4.3*nu0*E0*TE; +k2 = ep*r0*E0*TE; +k3 = 1 - ep; + +%-Output equation of BOLD signal model +%========================================================================== +v = exp(x(:,4)); +q = exp(x(:,5)); +y = V0*(k1.*(1 - q) + k2.*(1 - q./v) + k3.*(1 - v)); diff --git a/spm_gx_hdm.m b/spm_gx_hdm.m index 7790336..8ba8934 100644 --- a/spm_gx_hdm.m +++ b/spm_gx_hdm.m @@ -14,7 +14,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston & Klaas Enno Stephan -% $Id: spm_gx_hdm.m 3666 2010-01-10 17:54:31Z klaas $ +% $Id: spm_gx_hdm.m 3812 2010-04-07 16:52:05Z karl $ % biophysical constants for 1.5 T: @@ -28,9 +28,9 @@ TE = 0.04; end -%resting venous volume +% resting venous volume %-------------------------------------------------------------------------- -V0 = 100*0.04; +V0 = 100*0.08; % slope r0 of intravascular relaxation rate R_iv as a function of oxygen % saturation Y: R_iv = r0*[(1-Y)-(1-Y0)] diff --git a/spm_hdm_priors.m b/spm_hdm_priors.m index 8c7003c..5cc53ca 100644 --- a/spm_hdm_priors.m +++ b/spm_hdm_priors.m @@ -24,7 +24,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_hdm_priors.m 2050 2008-09-05 19:15:50Z klaas $ +% $Id: spm_hdm_priors.m 3888 2010-05-15 18:49:56Z karl $ @@ -63,7 +63,7 @@ % append m efficacy priors %--------------------------------------------------------------------------- pE = [pE(:); zeros(m,1)]; -pC = blkdiag(pC,eye(m)); +pC = blkdiag(pC,eye(m,m)*32); return diff --git a/spm_hdm_ui.m b/spm_hdm_ui.m index c369232..b931427 100644 --- a/spm_hdm_ui.m +++ b/spm_hdm_ui.m @@ -15,7 +15,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_hdm_ui.m 3666 2010-01-10 17:54:31Z klaas $ +% $Id: spm_hdm_ui.m 3812 2010-04-07 16:52:05Z karl $ % get figure handles @@ -40,7 +40,7 @@ spm_input('Input specification:... ',1,'d'); U.dt = Sess.U(1).dt; u = length(Sess.U); -if u == 1 & length(Sess.U(1).name) == 1 +if u == 1 && length(Sess.U(1).name) == 1 U.name = Sess.U(1).name; U.u = Sess.U(1).u(33:end,1); else @@ -57,42 +57,44 @@ end end -% echo time (TE) of data acquisition -%------------------------------------------------------------------- -TE = 0; +%-Echo time (TE) of data acquisition +%-------------------------------------------------------------------------- +TE = 0.04; TE_ok = 0; while ~TE_ok - TE = spm_input('Echo time, TE [s]'); - if ~TE | (TE < 0) | (TE > 0.1) + TE = spm_input('Echo time, TE [s]', '+1', 'r', TE); + if ~TE || (TE < 0) || (TE > 0.1) str = { 'Extreme value for TE or TE undefined.',... - 'Please re-enter TE (note this value must be in seconds!).'}; - spm_input(str,1,'bd','OK',[1],1); + 'Please re-enter TE (in seconds!)'}; + spm_input(str,'+1','bd','OK',[1],1); else TE_ok = 1; end end + -% system outputs +%-System outputs %=========================================================================== % enforce adjustment w.r.t. all effects %--------------------------------------------------------------------------- -xY = struct( 'Ic' ,1,... - 'name' ,'HDM',... - 'Sess' ,s); +xY = struct( 'Ic' ,0,... + 'name' ,'HDM',... + 'Sess' ,s); % get region stucture %--------------------------------------------------------------------------- +xY = struct('name', 'HDM', 'Sess', s); [y xY] = spm_regions(xSPM,SPM,hReg,xY); -%-place response and confounds in response structure +% place response and confounds in response structure %--------------------------------------------------------------------------- y = xY.u; Y.y = y; Y.dt = SPM.xY.RT; Y.X0 = xY.X0; -% estimate +%-Estimate %=========================================================================== spm('Pointer','Watch') spm('FigName','Estimation in progress'); @@ -131,8 +133,6 @@ M.f = 'spm_fx_hdm'; M.g = 'spm_gx_hdm'; M.x = [0 0 0 0]'; -% NB: resting value/expansion point of x(1) is -Inf in log space; this is -% taken into account in spm_fx_hdm. M.pE = pE; M.pC = pC; M.m = m; @@ -218,16 +218,16 @@ subplot(3,2,4) plot(t,K1(:,:,j)) axis square -title({ '1st order kernel';... - 'output: BOLD'},'FontSize',9) +title({'1st order kernel';... + 'output: BOLD'},'FontSize',9) ylabel('normalized flow signal') grid on subplot(3,2,6) imagesc(t,t,K2(:,:,1,j,j)) axis square -title({ '2nd order kernel';... - 'output: BOLD'},'FontSize',9) +title({'2nd order kernel';... + 'output: BOLD'},'FontSize',9) xlabel({'time {seconds} for'; U.name{j}}) grid on diff --git a/spm_help.m b/spm_help.m index 450d1f0..6aac766 100644 --- a/spm_help.m +++ b/spm_help.m @@ -118,7 +118,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Andrew Holmes, Karl Friston -% $Id: spm_help.m 2272 2008-09-30 21:21:24Z guillaume $ +% $Id: spm_help.m 3934 2010-06-17 14:58:25Z guillaume $ %======================================================================= @@ -265,7 +265,7 @@ %----------------------------------------------------------------------- Fmenu = spm_figure('Findwin','Menu'); C = get(Fmenu,'Children'); -modality = spm('CheckModality'); +if ~isempty(Fmenu), modality = spm('CheckModality'); end for i = length(C):-1:1 units = get(C(i),'Units'); funits = get(C(i),'FontUnits'); @@ -372,11 +372,10 @@ 'Position',[-133 090 110 30].*WS+O,... 'CallBack','spm_help(''spm_RandFX.man'')',... 'Tag','HelpMenu','Interruptible','on') -uicontrol(Fhelp,'String','','ForegroundColor','b',... - 'ToolTipString','',... +uicontrol(Fhelp,'String','Contrasts','ForegroundColor','b',... + 'ToolTipString','Contrasts',... 'Position',[-133 050 110 30].*WS+O,... - 'CallBack','',... - 'Enable','off',... + 'CallBack','spm_help(''spm_con.man'')',... 'Tag','HelpMenu','Interruptible','on') uicontrol(Fhelp,'String','SPM motd','ForegroundColor','b',... 'ToolTipString','SPM startup "message of the day"',... @@ -666,7 +665,7 @@ %----------------------------------------------------------------------- RefdTopics = cellstr(get(HD.hRefdTopics,'String')); RefdTopics = {RefdTopics{1};Topic}; %-Add current topic at top of references -q = findstr(S,'spm_'); %-Find 'spm_' strings +q = strfind(S,'spm_'); %-Find 'spm_' strings for i = 1:length(q) d = (0:31) + q(i); %-32 is max "spm_*" length considered Q = S(d(d <= length(S))); %-string (len<=32) starting "spm_" @@ -728,7 +727,7 @@ fclose(fid); end end -q = min([length(S),findstr(S,char([10 10]))]); % find empty lines +q = min([length(S),strfind(S,char([10 10]))]); % find empty lines q = find(S(1:q(1)) == 10); % find line breaks figure(Fhelp) diff --git a/spm_hrf.m b/spm_hrf.m index 99960d9..1a27ae0 100644 --- a/spm_hrf.m +++ b/spm_hrf.m @@ -16,31 +16,30 @@ % % hrf - hemodynamic response function % p - parameters of the response function -%_______________________________________________________________________ +%__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_hrf.m 2765 2009-02-19 15:30:54Z guillaume $ +% $Id: spm_hrf.m 3716 2010-02-08 13:58:09Z karl $ % global parameter -%----------------------------------------------------------------------- -global defaults +%-------------------------------------------------------------------------- try - fMRI_T = defaults.stats.fmri.t; + fMRI_T = spm_get_defaults('stats.fmri.t'); catch fMRI_T = 16; end % default parameters -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- p = [6 16 1 1 6 0 32]; if nargin > 1 p(1:length(P)) = P; end % modelled hemodynamic response function - {mixture of Gammas} -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- dt = RT/fMRI_T; u = [0:(p(7)/dt)] - p(6)/dt; hrf = spm_Gpdf(u,p(1)/p(3),dt/p(3)) - spm_Gpdf(u,p(2)/p(4),dt/p(4))/p(5); diff --git a/spm_image.m b/spm_image.m index 81ea25a..2492bc8 100644 --- a/spm_image.m +++ b/spm_image.m @@ -53,18 +53,17 @@ function spm_image(op,varargin) % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % John Ashburner -% $Id: spm_image.m 1912 2008-07-11 18:02:03Z guillaume $ +% $Id: spm_image.m 3691 2010-01-20 17:08:30Z guillaume $ global st if nargin == 0, spm('FnUIsetup','Display',0); - spm('FnBanner',mfilename,'$Rev: 1912 $'); - spm_help('!ContextHelp',[mfilename,'.m']); + spm('FnBanner',mfilename,'$Rev: 3691 $'); % get the image's filename {P} - %----------------------------------------------------------------------- + %---------------------------------------------------------------------- P = spm_select(1,'image','Select image'); spm_image('init',P); return; diff --git a/spm_imcalc_ui.m b/spm_imcalc_ui.m index ffe80e9..c7dc91c 100644 --- a/spm_imcalc_ui.m +++ b/spm_imcalc_ui.m @@ -86,51 +86,20 @@ % Q = spm_imcalc(Vi,Vo,'c*X',{1},c) % Here we've pre-specified the expression and passed the vector c as an % additional variable (you'll be prompted to select the n images). -% -% FORMAT out = spm_imcalc_ui(job) -% Input: -% job - a job structure. -% Output: -% out.files{1} - file name of output image. -%_______________________________________________________________________ +%__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % John Ashburner & Andrew Holmes -% $Id: spm_imcalc_ui.m 2535 2008-12-08 14:12:20Z volkmar $ - -%-Decompose job structure and run with arguments -%----------------------------------------------------------------------- -if nargin == 1 && isstruct(P) && isfield(P, 'input') - job = P; - flags = {job.options.dmtx, job.options.mask, job.options.dtype, job.options.interp}; - [p,nam,ext,num] = spm_fileparts(job.output); - if isempty(p) - if isempty(job.outdir{1}) - p=pwd; - else - p = job.outdir{1}; - end; - end; - if isempty(strfind(ext,',')) - ext=[ext ',1']; - end; - out.files{1} = fullfile(p,[nam ext num]); - spm_imcalc_ui(strvcat(job.input{:}),out.files{1},job.expression, ... - flags); - % return out as 1st output argument - Q = out; - return; -end; +% $Id: spm_imcalc_ui.m 3691 2010-01-20 17:08:30Z guillaume $ %-GUI setup -%----------------------------------------------------------------------- -SCCSid = '$Rev: 2535 $'; +%-------------------------------------------------------------------------- +SVNid = '$Rev: 3691 $'; [Finter,Fgraph,CmdLine] = spm('FnUIsetup','ImCalc',0); -spm('FnBanner',mfilename,SCCSid); -spm_help('!ContextHelp',[mfilename,'.m']) +spm('FnBanner',mfilename,SVNid); %-Condition arguments -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- if nargin<4, flags={}; end if nargin<3, f=''; end if nargin<2, Q=''; end @@ -154,12 +123,12 @@ spm('Pointer','Watch') %-Map input files -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- Vi = spm_vol(char(P)); if isempty(Vi), error('no input images specified'), end %-Check for consistency of image dimensions and orientation / voxel size -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- if length(Vi)>1 && any(any(diff(cat(1,Vi.dim),1,1),1)) warning(['images don''t all have same dimensions',... ' - using those of 1st image']); @@ -169,29 +138,27 @@ ' - using 1st image']); end - %-Work out filename for output image -%------------------------------------------------------------------ -[p n e v] = spm_fileparts(Q); -e = spm_str_manip(e,'ev'); % Canonicalise extension +%-------------------------------------------------------------------------- +[p n e] = spm_fileparts(Q); +if isempty(p), p = pwd; end if ~exist(p,'dir') warning('Invalid directory: writing to current directory') - p = '.'; + p = pwd; end -Vo = struct( 'fname', fullfile(p, [n, '.', e]),... - 'dim', Vi(1).dim(1:3),... - 'dt', [type spm_platform('bigend')],... - 'mat', Vi(1).mat,... - 'descrip', 'spm - algebra'); - +Vo = struct('fname', fullfile(p, [n, e]),... + 'dim', Vi(1).dim(1:3),... + 'dt', [type spm_platform('bigend')],... + 'mat', Vi(1).mat,... + 'descrip', 'spm - algebra'); %-Call spm_imcalc to handle computations -%------------------------------------------------------------------ +%-------------------------------------------------------------------------- args = {dmtx,mask,hold}; Vo = spm_imcalc(Vi,Vo,f,args); %-End -%------------------------------------------------------------------ +%-------------------------------------------------------------------------- spm('Pointer'); spm('FigName','ImCalc: done',Finter,CmdLine); diff --git a/spm_input.m b/spm_input.m index 080d167..8d4fbf5 100644 --- a/spm_input.m +++ b/spm_input.m @@ -171,7 +171,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Andrew Holmes -% $Id: spm_input.m 2817 2009-03-03 11:03:30Z guillaume $ +% $Id: spm_input.m 3756 2010-03-05 18:43:37Z guillaume $ %======================================================================= @@ -1675,7 +1675,7 @@ msg = ''; i=i(:)'; if ischar(i) - if i(1)=='0' & all(ismember(unique(i(:)),setstr(abs('0'):abs('9')))) + if i(1)=='0' & all(ismember(unique(i(:)),char(abs('0'):abs('9')))) %-Leading zeros in a digit list msg = sprintf('%s expanded',i); z = min(find([diff(i=='0'),1])); @@ -1689,7 +1689,7 @@ if ischar(i) %-Evaluation error from above: see if it's an 'abab' or 'a b a b' type: [c,null,i] = unique(lower(i(~isspace(i)))); - if all(ismember(c,setstr(abs('a'):abs('z')))) + if all(ismember(c,char(abs('a'):abs('z')))) %-Map characters a-z to 1-26, but let 'r' be zero (rest) tmp = c-'a'+1; tmp(tmp=='r'-'a'+1)=0; i = tmp(i); diff --git a/spm_int.m b/spm_int.m index 98152e8..d0c7902 100644 --- a/spm_int.m +++ b/spm_int.m @@ -3,9 +3,11 @@ % FORMAT [y] = spm_int(P,M,U) % P - model parameters % M - model structure +% M.delays - sampling delays (s); a vector with a delay for each output +% % U - input structure or matrix % -% y - (v x l) response y = g(x,u,P) +% y - response y = g(x,u,P) %__________________________________________________________________________ % Integrates the bilinear approximation to the MIMO system described by % @@ -45,23 +47,23 @@ % This can be useful if input changes are sparse (e.g., boxcar functions). % It is used primarily for integrating EEG models % -% spm_int: Fast integrator that uses a bilinear approximation to the +% spm_int: Fast integrator that uses a bilinear approximation to the % Jacobian evaluated using spm_bireduce. This routine will also allow for % sparse sampling of the solution and delays in observing outputs. It is -% used primarily for integrating fMRI models +% used primarily for integrating fMRI models (see also spm_int_D) %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_int.m 3605 2009-12-01 13:29:43Z karl $ +% $Id: spm_int.m 3812 2010-04-07 16:52:05Z karl $ % convert U to U.u if necessary %-------------------------------------------------------------------------- if ~isstruct(U), u.u = U; U = u; end try, dt = U.dt; catch, U.dt = 1; end - - + + % get expansion point %-------------------------------------------------------------------------- x = [1; spm_vec(M.x)]; @@ -74,8 +76,9 @@ M.x = sparse(0,0); end -% number of times to sample +% number of times to sample (v) and number of microtime bins (u) %-------------------------------------------------------------------------- +u = size(U.u,1); try v = M.ns; catch @@ -93,88 +96,76 @@ % Bilinear approximation (1st order) %-------------------------------------------------------------------------- -[M0,M1,L] = spm_bireduce(M,P); -n = size(L,2) - 1; % n states -m = size(U.u,2); % m inputs -l = size(L,1); % l outputs -u = size(U.u,1); % input times +[M0,M1] = spm_bireduce(M,P); +m = length(M1); % m inputs -% evaluation time points (when response is sampled or input changes) +% delays %-------------------------------------------------------------------------- -if isfield(M, 'delays') - - % when delays have been specified transform delays to time bins - %---------------------------------------------------------------------- - delays = max(1, round(M.delays/U.dt)); - s = []; - for j = 1:M.l - s = [s ceil([0:v-1]*u/v) + delays(j)]; - end - s = unique(s); - s_ind(s) = [1:length(s)]; % index vector from oversampled time to scans - Nu = length(s); -else - s = ceil([1:v]*u/v); % 'original' output times (last time bin) - Nu = v; +try + D = round(M.delays/U.dt); +catch + D = ones(M.l,1)*round(u/v); end + + +% Evaluation times (t) and indicator array for inputs (su) and output (sy) +%========================================================================== -t = [1 (1 + find(any(diff(U.u),2))')]; % input times -[T s] = sort([s t]); % update (input & output) times -dt = [U.dt*diff(T) 0]; % update intervals +% get times that the input changes +%-------------------------------------------------------------------------- +i = [1 (1 + find(any(diff(U.u),2))')]; +su = sparse(1,i,1,1,u); -% Integrate +% get times that the response is sampled %-------------------------------------------------------------------------- -y = zeros(l,Nu); -dy = zeros(l,Nu); -J = M0; -U.u = full(U.u); -for i = 1:length(T) +s = ceil([0:v - 1]*u/v); +for j = 1:M.l + i = s + D(j); + sy(j,:) = sparse(1,i,[1:v],1,u); +end - % input - %---------------------------------------------------------------------- - u = U.u(T(i),:); +% time in seconds +%-------------------------------------------------------------------------- +t = find(su | any(sy)); +su = full(su(:,t)); +sy = full(sy(:,t)); +dt = [diff(t) 0]*U.dt; - % change in input - update J - %---------------------------------------------------------------------- - if s(i) > Nu +% Integrate +%-------------------------------------------------------------------------- +y = zeros(M.l,v); +J = M0; +U.u = full(U.u); +for i = 1:length(t) + + % input dependent changes in Jacobian + %---------------------------------------------------------------------- + if su(:,i) + u = U.u(t(i),:); J = M0; for j = 1:m J = J + u(j)*M1{j}; end + end - % output sampled - implement l(x) + % output sampled %---------------------------------------------------------------------- - else - if isfield(M,'g') - q = spm_unvec(x([1:n] + 1),M.x); - y(:,s(i)) = spm_vec(feval(g,q,u,P,M)); - else - y(:,s(i)) = L*x; - end + if any(sy(:,i)) + q = spm_unvec(x(2:end),M.x); + q = spm_vec(feval(g,q,u,P,M)); + j = find(sy(:,i)); + s = sy(j(1),i); + y(j,s) = q(j); end % compute updated states x = expm(J*dt)*x; %---------------------------------------------------------------------- x = spm_expm(J*dt(i),x); - -end - -y = real(y'); - -% down-sample delays -%---------------------------------------------------------------------- -if isfield(M, 'delays') - u = size(U.u,1); - tmp = zeros(v, M.l); - dtmp = zeros(v, M.l); - - % output times for j-th area + % check for convergence %---------------------------------------------------------------------- - for j = 1:M.l - s = ceil([0:v-1]*u/v) + delays(j); - tmp(:,j) = y(s_ind(s), j); - end - y = tmp; + if norm(x,1) > 1e6, break, end + end +y = real(y'); diff --git a/spm_int_B_nlDCM_fMRI.m b/spm_int_B_nlDCM_fMRI.m deleted file mode 100644 index 712ab70..0000000 --- a/spm_int_B_nlDCM_fMRI.m +++ /dev/null @@ -1,257 +0,0 @@ -function [y] = spm_int_B_nlDCM_fMRI(P,M,U) -% integrates a MIMO nonlinear system using a bilinear Jacobian -% FORMAT [y] = spm_int_B_nlDCM_fMRI(P,M,U) -% P - model parameters -% M - model structure -% U - input structure or matrix -% -% y - (v x l) response y = g(x,u,P) -%__________________________________________________________________________ -% -% This function is a variant of spm_int_B which is specifically designed -% for nonlinear DCM for fMRI. As in spm_int_B, the Jacobian is recomputed -% at every time bin (as defined by U.dt); however, it samples predicted -% responses only at specified time points (i.e. every TR, accounting for -% slice-timing). This function is the default integrator for nonlinear -% DCMs for fMRI. -% -% This function integrates the MIMO system described by -% -% dx/dt = f(x,u,P,M) -% y = g(x,u,P,M) -% -% using the update scheme: -% -% x(t + dt) = x(t) + U*dx(t)/dt -% -% U = (expm(dt*J) - I)*inv(J) -% J = df/dx -% -% at input times. This integration scheme evaluates the update matrix (Q) -% at each time point -% -%-------------------------------------------------------------------------- -% -% SPM solvers or integrators -% -% spm_int_ode: uses ode45 (or ode113) which are one and multi-step solvers -% respectively. They can be used for any ODEs, where the Jacobian is -% unknown or difficult to compute; however, they may be slow. -% -% spm_int_J: uses an explicit Jacobian-based update scheme that preserves -% nonlinearities in the ODE: dx = (expm(dt*J) - I)*inv(J)*f. If the -% equations of motion return J = df/dx, it will be used; otherwise it is -% evaluated numerically, using spm_diff at each time point. This scheme is -% infallible but potentially slow, if the Jacobian is not available (calls -% spm_dx). -% -% spm_int_E: As for spm_int_J but uses the eigensystem of J(x(0)) to eschew -% matrix exponentials and inversion during the integration. It is probably -% the best compromise, if the Jacobian is not available explicitly. -% -% spm_int_J_nlDCM_fMRI: Identical to spm_int_J, except that it samples -% predicted responses only at specified time points (i.e. every TR, -% accounting for slice-timing). It is an alternative integrator for -% nonlinear DCM for fMRI (marginally more accurate, but considerably slower -% than spm_int_B_nlDCM_fMRI). -% -% spm_int_B: As for spm_int_J but uses a first-order approximation to J -% based on J(x(t)) = J(x(0)) + dJdx*x(t). -% -% spm_int_B_nlDCM_fMRI: Identical to spm_int_B, except that it samples -% predicted responses only at specified time points (i.e. every TR, -% accounting for slice-timing). It is the default integrator for nonlinear -% DCM for fMRI. -% -% spm_int_ode: uses ode45 (or ode113) which are one and multi-step solvers -% respectively. They can be used for any ODEs, where the Jacobian is -% unknown or difficult to compute; however, they may be slow. -% -% spm_int_J: uses an explicit Jacobian-based update scheme that preserves -% nonlinearities in the ODE: dx = (expm(dt*J) - I)*inv(J)*f. If the -% equations of motion return J = df/dx, it will be used; otherwise it is -% evaluated numerically, using spm_diff at each time point. This scheme is -% infallible but potentially slow, if the Jacobian is not available (calls -% spm_dx). -% -% spm_int_E: As for spm_int_J but uses the eigensystem of J(x(0)) to eschew -% matrix exponentials and inversion during the integration. It is probably -% the best compromise, if the Jacobian is not available explicitly. -% -% spm_int_J_nlDCM_fMRI: Identical to spm_int_J, except that it samples -% predicted responses only at specified time points (i.e. every TR, -% accounting for slice-timing). It is an alternative integrator for -% nonlinear DCM for fMRI (marginally more accurate, but considerably slower -% than spm_int_B_nlDCM_fMRI). -% -% spm_int_B: As for spm_int_J but uses a first-order approximation to J -% based on J(x(t)) = J(x(0)) + dJdx*x(t). -% -% spm_int_B_nlDCM_fMRI: Identical to spm_int_B, except that it samples -% predicted responses only at specified time points (i.e. every TR, -% accounting for slice-timing). It is the default integrator for nonlinear -% DCM for fMRI. -% -% spm_int_L: As for spm_int_B but uses J(x(0)). -% -% spm_int_U: like spm_int_J but only evaluates J when the input changes. -% This can be useful if input changes are sparse (e.g., boxcar functions). -% It is used primarily for integrating EEG models -% -% spm_int: Fast integrator that uses a bilinear approximation to the -% Jacobian evaluated using spm_bireduce. This routine will also allow for -% sparse sampling of the solution and delays in observing outputs. It is -% used primarily for integrating fMRI models -%___________________________________________________________________________ -% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging - -% Karl Friston & Klaas Enno Stephan -% $Id: spm_int_B_nlDCM_fMRI.m 3039 2009-04-01 17:59:45Z klaas $ - - -% convert U to U.u if necessary -%-------------------------------------------------------------------------- -if ~isstruct(U), U.u = U; end -try, dt = U.dt; catch, dt = 1; end -try, ns = M.ns; catch, ns = length(U.u); end - - -% state equation; add [0] states if not specified -%-------------------------------------------------------------------------- -try - f = fcnchk(M.f,'x','u','P','M'); -catch - f = inline('sparse(0,1)','x','u','P','M'); - M.n = 0; - M.x = sparse(0,0); -end - - -% and output nonlinearity -%-------------------------------------------------------------------------- -try - g = fcnchk(M.g,'x','u','P','M'); -end - - -% Initial states and inputs -%-------------------------------------------------------------------------- -u = U.u(1,:); -try - x = M.x; -catch - x = sparse(0,1); - M.x = x; -end - - -% check for delay operator -%-------------------------------------------------------------------------- -try - [fx dfdx D] = f(x,u,P,M); -catch - D = 1; -end - - -% get Jacobian and its derivatives -%-------------------------------------------------------------------------- -[dJdx J] = spm_diff(f,x,u,P,M,[1 1]); -[dJdu J] = spm_diff(f,x,u,P,M,[1 2]); - - -% Determine sampling time points -%---------------------------------------------------------------------- -nt = size(U.u,1); % no. of time bins -sample = 0; - -if isfield(M, 'delays') - % if slice timing delays specified, transform delays to time bins - %------------------------------------------------------------------ - delays = max(1, round(M.delays/U.dt)); - s = []; - for j = 1:M.l - s = [s ceil([0:ns-1]*nt/ns) + delays(j)]; - end - s = unique(s); - % index vector from oversampled time to scans: this marks at which time - % bin a measurement was obtained (across all areas) - s_ind(s) = [1:length(s)]; -else - % no slice timing delays specified: keep 'original' output times - % i.e. last time bin (NB: 32 bin offset has already been corrected - % by spm_dcm_ui/spm_dcm_create) - s = ceil([1:ns]*nt/ns); -end - - -% integrate -%========================================================================== -y = zeros(M.l,ns); % note the dimensions: areas x scans -x0 = spm_vec(M.x); -for i = 1:nt - - % input - %---------------------------------------------------------------------- - u = U.u(i,:); - - % motion - %---------------------------------------------------------------------- - fx = f(x,u,P,M); - - % dx(t)/dt and Jacobian df/dx - %---------------------------------------------------------------------- - dx = spm_vec(x) - x0; - dfdx = J; - for j = 1:length(dJdx) - dfdx = dfdx + dJdx{j}*dx(j); - end - for j = 1:length(dJdu) - dfdx = dfdx + dJdu{j}*u(j); - end - - % update dx = (expm(dt*J) - I)*inv(J)*fx - %---------------------------------------------------------------------- - x = spm_unvec(spm_vec(x) + spm_dx(D*dfdx,D*fx,dt),x); - - % output - implement g(x) - %---------------------------------------------------------------------- - % check whether response is sampled at present time - if find(s==i) - sample = sample + 1; - - if length(g) - y(:,sample) = spm_vec(g(x,u,P,M)); - else - y(:,sample) = spm_vec(x); - end - - end - -end - - -% transpose -%-------------------------------------------------------------------------- -y = real(y'); - - -% down-sample time series -%---------------------------------------------------------------------- -if isfield(M, 'delays') - - tmp = zeros(ns, M.l); - - % output times for j-th area - %---------------------------------------------------------------------- - for j = 1:M.l - s = ceil([0:ns-1]*nt/ns) + delays(j); - tmp(:,j) = y(s_ind(s), j); - end - - y = tmp; - -end - - -return diff --git a/spm_int_D.m b/spm_int_D.m new file mode 100644 index 0000000..c54d15b --- /dev/null +++ b/spm_int_D.m @@ -0,0 +1,199 @@ +function [y] = spm_int_D(P,M,U) +% integrates a MIMO bilinear system dx/dt = f(x,u) = A*x + B*x*u + Cu + D; +% FORMAT [y] = spm_int_D(P,M,U) +% P - model parameters +% M - model structure +% M.delays - sampling delays (s); a vector with a delay for each output +% M.states - a vector of indices if M.x(:) to be used in updating df/dx +% M.nsteps - increase number of time steps by this number (default = 1) +% +% U - input structure or matrix +% +% y - response y = g(x,u,P) +%__________________________________________________________________________ +% Integrates the bilinear approximation to the MIMO system described by +% +% dx/dt = f(x,u,P) = A*x + u*B*x + C*u + D +% y = g(x,u,P) = L*x; +% +% at v = M.ns is the number of samples [default v = size(U.u,1)] +% +% spm_int will also handle static observation models by evaluating +% g(x,u,P). It will also handle timing delays if specified in M.delays +% +%-------------------------------------------------------------------------- +% +% SPM solvers or integrators +% +% spm_int_ode: uses ode45 (or ode113) which are one and multi-step solvers +% respectively. They can be used for any ODEs, where the Jacobian is +% unknown or difficult to compute; however, they may be slow. +% +% spm_int_J: uses an explicit Jacobian-based update scheme that preserves +% nonlinearities in the ODE: dx = (expm(dt*J) - I)*inv(J)*f. If the +% equations of motion return J = df/dx, it will be used; otherwise it is +% evaluated numerically, using spm_diff at each time point. This scheme is +% infallible but potentially slow, if the Jacobian is not available (calls +% spm_dx). +% +% spm_int_E: As for spm_int_J but uses the eigensystem of J(x(0)) to eschew +% matrix exponentials and inversion during the integration. It is probably +% the best compromise, if the Jacobian is not available explicitly. +% +% spm_int_B: As for spm_int_J but uses a first-order approximation to J +% based on J(x(t)) = J(x(0)) + dJdx*x(t). +% +% spm_int_L: As for spm_int_B but uses J(x(0)). +% +% spm_int_U: like spm_int_J but only evaluates J when the input changes. +% This can be useful if input changes are sparse (e.g., boxcar functions). +% It is used primarily for integrating EEG models +% +% spm_int_D: Fast integrator that uses a bilinear approximation to the +% Jacobian evaluated using spm_soreduce. This routine will also allow for +% sparse sampling of the solution and delays in observing outputs. It is +% used primarily for integrating fMRI models +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: spm_int_D.m 3739 2010-02-26 13:12:44Z karl $ + + +% convert U to U.u if necessary +%-------------------------------------------------------------------------- +if ~isstruct(U), u.u = U; U = u; end +try, dt = U.dt; catch, U.dt = 1; end + + +% get expansion point +%-------------------------------------------------------------------------- +x = [1; spm_vec(M.x)]; + +% add [0] states if not specified +%-------------------------------------------------------------------------- +if ~isfield(M,'f') + M.f = inline('sparse(0,1)','x','u','P','M'); + M.n = 0; + M.x = sparse(0,0); +end + +% number of times to sample (v) and number of microtime bins (u) +%-------------------------------------------------------------------------- +u = size(U.u,1); +try + v = M.ns; +catch + v = size(U.u,1); +end + +% output nonlinearity, if specified +%-------------------------------------------------------------------------- +try + g = fcnchk(M.g,'x','u','P','M'); +catch + g = inline('x','x','u','P','M'); + M.g = g; +end + +% Bilinear approximation (1st order) +%-------------------------------------------------------------------------- +[M0,M1,M2] = spm_soreduce(M,P); +n = length(M2); % n states +m = length(M1); % m inputs + + +% delays +%-------------------------------------------------------------------------- +try + D = round(M.delays/U.dt); +catch + D = ones(l,1)*round(u/v); +end + +% state-dependent effects to include during integration +%-------------------------------------------------------------------------- +try + M2 = M2(M.states); + n = length(M2); +end + +% decrease integration time steps +%-------------------------------------------------------------------------- +try + N = max(M.nsteps,1); +catch + N = 1; +end + + +% Evaluation times (t) and indicator array for inputs (su) and output (sy) +%========================================================================== + +% get times that the input changes +%-------------------------------------------------------------------------- +i = [1 (1 + find(any(diff(U.u),2))')]; +su = sparse(1,i,1,1,u); + +% get times that the response is sampled +%-------------------------------------------------------------------------- +s = ceil([0:v - 1]*u/v); +for j = 1:M.l + i = s + D(j); + sy(j,:) = sparse(1,i,[1:v],1,u); +end + +% get (N) intervening times to evaluate +%-------------------------------------------------------------------------- +i = ceil([0:(v - 1)*N]*u/v/N) + D(1); +sx = sparse(1,i,1,1,u); + +% time in seconds +%-------------------------------------------------------------------------- +t = find(su | any(sy) | sx); +su = full(su(:,t)); +sy = full(sy(:,t)); +dt = [diff(t) 0]*U.dt; + + +% Integrate +%-------------------------------------------------------------------------- +y = zeros(M.l,v); +J = M0; +U.u = full(U.u); +for i = 1:length(t) + + % input dependent changes in Jacobian + %---------------------------------------------------------------------- + u = U.u(t(i),:); + J = M0; + for j = 1:m + J = J + u(j)*M1{j}; + end + + % state dependent changes in Jacobian + %---------------------------------------------------------------------- + for j = 1:n + J = J + (x(j + 1) - M.x(j))*M2{j}; + end + + % output sampled + %---------------------------------------------------------------------- + if any(sy(:,i)) + q = spm_unvec(x(2:end),M.x); + q = spm_vec(feval(g,q,u,P,M)); + j = find(sy(:,i)); + s = sy(j(1),i); + y(j,s) = q(j); + end + + % compute updated states x = expm(J*dt)*x; + %---------------------------------------------------------------------- + x = spm_expm(J*dt(i),x); + + % check for convergence + %---------------------------------------------------------------------- + if norm(x,1) > 1e6, break, end + +end +y = real(y'); diff --git a/spm_int_J_nlDCM_fMRI.m b/spm_int_J_nlDCM_fMRI.m deleted file mode 100644 index de39c6c..0000000 --- a/spm_int_J_nlDCM_fMRI.m +++ /dev/null @@ -1,235 +0,0 @@ -function [y] = spm_int_J_nlDCM_fMRI (P,M,U) -% integrates a MIMO nonlinear system using the Jacobian -% FORMAT [y] = spm_int_J_nlDCM_fMRI (P,M,U) -% P - model parameters -% M - model structure -% U - input structure or matrix -% -% y - (v x l) response y = g(x,u,P) -%__________________________________________________________________________ -% This function is a variant of spm_int_J which is specifically designed -% for nonlinear DCM for fMRI. As in spm_int_J, the Jacobian is recomputed -% at every time bin (as defined by U.dt); however, it samples predicted -% responses only at specified time points (i.e. every TR, accounting for -% slice-timing). -% -% This function integrates the MIMO system described by -% -% dx/dt = f(x,u,P,M) -% y = g(x,u,P,M) -% or -% dx/dt = f(x,u,P) -% y = g(x,u,P) -% -% using the update scheme: -% -% x(t + dt) = x(t) + U*dx(t)/dt -% -% U = (expm(dt*J) - I)*inv(J) -% J = df/dx -% -% at input times. This integration scheme evaluates the update matrix (Q) -% at each time point. -% -% -%-------------------------------------------------------------------------- -% -% SPM solvers or integrators -% -% spm_int_ode: uses ode45 (or ode113) which are one and multi-step solvers -% respectively. They can be used for any ODEs, where the Jacobian is -% unknown or difficult to compute; however, they may be slow. -% -% spm_int_J: uses an explicit Jacobian-based update scheme that preserves -% nonlinearities in the ODE: dx = (expm(dt*J) - I)*inv(J)*f. If the -% equations of motion return J = df/dx, it will be used; otherwise it is -% evaluated numerically, using spm_diff at each time point. This scheme is -% infallible but potentially slow, if the Jacobian is not available (calls -% spm_dx). -% -% spm_int_E: As for spm_int_J but uses the eigensystem of J(x(0)) to eschew -% matrix exponentials and inversion during the integration. It is probably -% the best compromise, if the Jacobian is not available explicitly. -% -% spm_int_J_nlDCM_fMRI: Identical to spm_int_J, except that it samples -% predicted responses only at specified time points (i.e. every TR, -% accounting for slice-timing). It is an alternative integrator for -% nonlinear DCM for fMRI (marginally more accurate, but considerably slower -% than spm_int_B_nlDCM_fMRI). -% -% spm_int_B: As for spm_int_J but uses a first-order approximation to J -% based on J(x(t)) = J(x(0)) + dJdx*x(t). -% -% spm_int_B_nlDCM_fMRI: Identical to spm_int_B, except that it samples -% predicted responses only at specified time points (i.e. every TR, -% accounting for slice-timing). It is the default integrator for nonlinear -% DCM for fMRI. -% -% spm_int_L: As for spm_int_B but uses J(x(0)). -% -% spm_int_U: like spm_int_J but only evaluates J when the input changes. -% This can be useful if input changes are sparse (e.g., boxcar functions). -% It is used primarily for integrating EEG models -% -% spm_int: Fast integrator that uses a bilinear approximation to the -% Jacobian evaluated using spm_bireduce. This routine will also allow for -% sparse sampling of the solution and delays in observing outputs. It is -% used primarily for integrating fMRI models -%__________________________________________________________________________ -% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging - -% Karl Friston & Klaas Enno Stephan -% $Id: spm_int_J_nlDCM_fMRI.m 3039 2009-04-01 17:59:45Z klaas $ - - -% convert U to U.u if necessary and M(1) to M -%-------------------------------------------------------------------------- -if ~isstruct(U), u.u = U; U = u; end -M = M(1); -try, dt = U.dt; catch, dt = 1; end -try, ns = M.ns; catch, ns = length(U.u); end - -% state equation; add [0] states if not specified -%-------------------------------------------------------------------------- -try - f = fcnchk(M.f,'x','u','P','M'); -catch - f = inline('sparse(0,1)','x','u','P','M'); - M.n = 0; - M.x = sparse(0,0); -end - -% and output nonlinearity -%-------------------------------------------------------------------------- -try - g = fcnchk(M.g,'x','u','P','M'); -catch - g = []; -end - -% Initial states and inputs -%-------------------------------------------------------------------------- -try - u = U.u(1,:); -catch - u = sparse(1,M.m); -end -try - x = M.x; -catch - x = sparse(0,1); - M.x = x; -end - -% check function format -%-------------------------------------------------------------------------- -try - f(x,u,P,M); -catch - f = inline(char(f),'x','v','P','M'); -end -try - g(x,u,P,M); -catch - g = inline(char(g),'x','v','P','M'); -end - -% check for delay operator -%-------------------------------------------------------------------------- -try - [fx dfdx D] = f(x,u,P,M); -catch - D = 1; -end - - -% integrate (nonlinear DCM for fMRI) -%====================================================================== - -% Determine sampling time points -%---------------------------------------------------------------------- -nt = size(U.u,1); % no. of time bins -sample = 0; - -if isfield(M, 'delays') - % if slice timing delays specified, transform delays to time bins - %------------------------------------------------------------------ - delays = max(1, round(M.delays/U.dt)); - s = []; - for j = 1:M.l - s = [s ceil([0:ns-1]*nt/ns) + delays(j)]; - end - s = unique(s); - % index vector from oversampled time to scans: this marks at which time - % bin a measurement was obtained (across all areas) - s_ind(s) = [1:length(s)]; -else - % no slice timing delays specified: keep 'original' output times - % i.e. last time bin (NB: 32 bin offset has already been corrected - % by spm_dcm_ui/spm_dcm_create) - s = ceil([1:ns]*nt/ns); -end - -y = zeros(M.l,ns); % note the dimensions: areas x scans -for i = 1:nt - - % input - %---------------------------------------------------------------------- - try - u = U.u(i,:); - end - - % dx(t)/dt and Jacobian df/dx - %---------------------------------------------------------------------- - try - [fx dfdx] = f(x,u,P,M); - catch - fx = f(x,u,P,M); - dfdx = spm_diff(f,x,u,P,M,1); - end - - % update dx = (expm(dt*J) - I)*inv(J)*fx - %------------------------------------------------------------------ - x = spm_unvec(spm_vec(x) + spm_dx(D*dfdx,D*fx,dt),x); - - % output - implement g(x) - %---------------------------------------------------------------------- - % check whether response is sampled at present time - if find(s==i) - sample = sample + 1; - - if length(g) - y(:,sample) = spm_vec(g(x,u,P,M)); - else - y(:,sample) = spm_vec(x); - end - - end - -end - - -% transpose -%-------------------------------------------------------------------------- -y = real(y'); - - -% down-sample time series -%---------------------------------------------------------------------- -if isfield(M, 'delays') - - tmp = zeros(ns, M.l); - - % output times for j-th area - %---------------------------------------------------------------------- - for j = 1:M.l - s = ceil([0:ns-1]*nt/ns) + delays(j); - tmp(:,j) = y(s_ind(s), j); - end - - y = tmp; - -end - - -return diff --git a/spm_int_L.m b/spm_int_L.m index ddccadb..5a5cf65 100644 --- a/spm_int_L.m +++ b/spm_int_L.m @@ -54,11 +54,11 @@ % Jacobian evaluated using spm_bireduce. This routine will also allow for % sparse sampling of the solution and delays in observing outputs. It is % used primarily for integrating fMRI models -%___________________________________________________________________________ +%__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_int_L.m 3657 2009-12-23 20:22:10Z karl $ +% $Id: spm_int_L.m 3705 2010-02-01 20:51:28Z karl $ % convert U to U.u if necessary @@ -66,7 +66,7 @@ if ~isstruct(U), u.u = U; U = u; end try, dt = U.dt; catch, dt = 1; end try, ns = size(U.u,1); catch, ns = M.ns; end - + % state equation; add [0] states if not specified %-------------------------------------------------------------------------- diff --git a/spm_interp.m b/spm_interp.m index 07fe41d..e6a8479 100644 --- a/spm_interp.m +++ b/spm_interp.m @@ -1,5 +1,5 @@ function [x] = spm_interp(x,r) -% 2-D array interpolation +% 1 or 2-D array interpolation % FORMAT [x] = spm_interp(x,r) % x - array % r - interpolation rate @@ -7,21 +7,42 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_interp.m 2271 2008-09-30 21:19:47Z guillaume $ +% $Id: spm_interp.m 3733 2010-02-18 17:43:18Z karl $ % interpolate %--------------------------------------------------------------------------- [n m] = size(x); -X = zeros(r*n,m); -L = floor((n - 1)/2); -L = min([L 4]); -for i = 1:m - X(:,i) = interp(x(:,i),r,L); -end -L = floor((m - 1)/2); -L = min([L 4]); -x = zeros(r*n,r*m); -for i = 1:r*n - x(i,:) = interp(X(i,:),r,L); + +if n > 1 && m > 1 % matrix + + X = zeros(r*n,m); + for i = 1:m + X(:,i) = interpolate(x(:,i),r); + end + x = zeros(r*n,r*m); + for i = 1:r*n + x(i,:) = interpolate(X(i,:),r)'; + end + +elseif n == 1 % row vector + x = interpolate(x',r)'; + +elseif m == 1 % column vector + x = interpolate(x,r); + end +% Interpolate using DCT +% ------------------------------------------------------------------------- +function [u] = interpolate(y,r) + +if r == 1; + u = y; +else + y = y(:); + n = size(y,1); + Dy = spm_dctmtx(r*n,n); + Du = spm_dctmtx(n,n); + Dy = Dy*sqrt(r); + u = Dy*(Du'*y); +end diff --git a/spm_inv.m b/spm_inv.m index ec98aba..96ba287 100644 --- a/spm_inv.m +++ b/spm_inv.m @@ -9,7 +9,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_inv.m 3657 2009-12-23 20:22:10Z karl $ +% $Id: spm_inv.m 3877 2010-05-07 19:49:35Z karl $ % check A %-------------------------------------------------------------------------- @@ -18,4 +18,5 @@ % inverse %-------------------------------------------------------------------------- -X = inv(A + speye(m,n)*eps(norm(A,1))); +TOL = eps(norm(A,'inf'))*max(m,n); +X = inv(A + speye(m,n)*TOL); diff --git a/spm_jobman.m b/spm_jobman.m index 2a9635c..80f6896 100644 --- a/spm_jobman.m +++ b/spm_jobman.m @@ -92,11 +92,12 @@ % Copyright (C) 2008 Freiburg Brain Imaging % Volkmar Glauche -% $Id: spm_jobman.m 3599 2009-11-26 14:08:07Z volkmar $ +% $Id: spm_jobman.m 3916 2010-06-03 11:12:34Z guillaume $ if nargin==0 - cfg_ui; + h = cfg_ui; + if nargout > 0, varargout = {h}; end else cmd = lower(varargin{1}); if any(strcmp(cmd, {'serial','interactive','run','run_nogui'})) @@ -147,9 +148,6 @@ end cfg_get_defaults('cfg_util.genscript_run', @genscript_run); cfg_util('initcfg'); % This must be the first call to cfg_util - if isdeployed - cfg_master; - end if ~spm('cmdline') f = cfg_ui('Visible','off'); % Create invisible batch ui f0 = findobj(f, 'Tag','MenuFile'); % Add entries to file menu @@ -356,46 +354,44 @@ function load_job(varargin) try loadxml(filenames{cf},'matlabbatch'); catch - warning('LoadXML failed: ''%s''',filenames{cf}); + warning('spm:spm_jobman:LoadFailed','LoadXML failed: ''%s''',filenames{cf}); end; end; spm('Pointer'); case '.mat' try S=load(filenames{cf}); - jobs = S.jobs; - catch - try + if isfield(S,'matlabbatch') matlabbatch = S.matlabbatch; - catch - warning('Load failed: ''%s''',filenames{cf}); - end; + elseif isfield(S,'jobs') + jobs = S.jobs; + else + warning('spm:spm_jobman:JobNotFound','No SPM5/SPM8 job found in ''%s''', filenames{cf}); + end + catch + warning('spm:spm_jobman:LoadFailed','Load failed: ''%s''',filenames{cf}); end; case '.m' - opwd = pwd; try - if ~isempty(p) - cd(p); - end; - eval(nam); + fid = fopen(filenames{cf},'rt'); + str = fread(fid,'*char'); + fclose(fid); + eval(str); catch - warning('Eval failed: ''%s''',filenames{cf}); + warning('spm:spm_jobman:LoadFailed','Load failed: ''%s''',filenames{cf}); end; - cd(opwd); if ~(exist('jobs','var') || exist('matlabbatch','var')) - warning('No SPM5/SPM8 job found in ''%s''', filenames{cf}); + warning('spm:spm_jobman:JobNotFound','No SPM5/SPM8 job found in ''%s''', filenames{cf}); end; otherwise warning('Unknown extension: ''%s''', filenames{cf}); end; if exist('jobs','var') - newjobs = {newjobs{:} jobs}; + newjobs = [newjobs(:); {jobs}]; clear jobs; elseif exist('matlabbatch','var') - newjobs = {newjobs{:} matlabbatch}; - clear jobs; - else - newjobs = {newjobs{:} {}}; + newjobs = [newjobs(:); {matlabbatch}]; + clear matlabbatch; end; end; return; @@ -439,9 +435,7 @@ function load_job(varargin) function pulldown fg = spm_figure('findwin','Graphics'); if isempty(fg), return; end; -set(0,'ShowHiddenHandles','on'); -delete(findobj(fg,'tag','jobs')); -set(0,'ShowHiddenHandles','off'); +delete(findall(fg,'tag','jobs')); f0 = uimenu(fg,'Label','TASKS', ... 'HandleVisibility','off', 'tag','jobs'); f1 = uimenu(f0,'Label','BATCH', 'Callback',@cfg_ui, ... @@ -540,4 +534,4 @@ function local_init_serial(varargin) modality = spm('CheckModality'); code{1} = sprintf('spm(''defaults'', ''%s'');', modality); code{2} = 'spm_jobman(''serial'', jobs, '''', inputs{:});'; -cont = false; \ No newline at end of file +cont = false; diff --git a/spm_list.m b/spm_list.m index 611492c..2ff9a38 100644 --- a/spm_list.m +++ b/spm_list.m @@ -115,24 +115,19 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston & Andrew Holmes -% $Id: spm_list.m 3450 2009-10-08 16:11:13Z guillaume $ +% $Id: spm_list.m 3953 2010-06-28 16:58:48Z guillaume $ -% satellite figure global variable -%-------------------------------------------------------------------------- -global SatWindow - % Choose between voxel-wise and topological FDR %-------------------------------------------------------------------------- -defaults = spm('GetGlobal','defaults'); try - topoFDR = defaults.stats.topoFDR; + topoFDR = spm_get_defaults('stats.topoFDR'); catch topoFDR = true; end %========================================================================== -switch lower(varargin{1}), case 'list' %-List +switch lower(varargin{1}), case 'list' %-List %========================================================================== % FORMAT TabDat = spm_list('list',SPM,hReg) @@ -171,8 +166,8 @@ end if STAT~='P' - R = varargin{2}.R; - FWHM = varargin{2}.FWHM; + R = full(varargin{2}.R); + FWHM = full(varargin{2}.FWHM); end try units = varargin{2}.units; @@ -182,21 +177,22 @@ units{1} = [units{1} ' ']; units{2} = [units{2} ' ']; - DIM = DIM > 1; % dimensions + DIM = DIM > 1; % non-empty dimensions + D = sum(DIM); % highest dimension VOX = VOX(DIM); % scaling - if STAT~='P' + if STAT ~= 'P' FWHM = FWHM(DIM); % Full width at max/2 FWmm = FWHM.*VOX; % FWHM {units} - v2r = 1/prod(FWHM); % voxels to resels - k = k*v2r; % extent threshold in resels - R(find(~DIM) + 1) = []; % eliminate null resel counts - try, QPs = sort(QPs(:)); end % Needed for voxel FDR - try, QPp = sort(QPp(:)); end % Needed for peak FDR + V2R = 1/prod(FWHM); % voxels to resels + k = k*V2R; % extent threshold in resels + R = R(1:(D + 1)); % eliminate null resel counts + try, QPs = sort(QPs(:)); end % Needed for voxel FDR + try, QPp = sort(QPp(:)); end % Needed for peak FDR try, QPc = sort(QPc(:)); end % Needed for cluster FDR end - %-get number and separation for maxima to be reported + %-Get number and separation for maxima to be reported %---------------------------------------------------------------------- if length(varargin) > 3 Num = varargin{4}; % number of maxima per cluster @@ -211,37 +207,37 @@ Title = 'p-values adjusted for search volume'; end + %-Table header & footer + %====================================================================== + %-Setup graphics panel %---------------------------------------------------------------------- spm('Pointer','Watch') - if SatWindow - Fgraph = SatWindow; + Fgraph = spm_figure('FindWin','Satellite'); + if Fgraph figure(Fgraph); + ht = 0.85; bot = 0.14; else Fgraph = spm_figure('GetWin','Graphics'); + ht = 0.4; bot = 0.1; end spm_results_ui('Clear',Fgraph) FS = spm('FontSizes'); %-Scaled font sizes PF = spm_platform('fonts'); %-Font names (for this platform) - - - %-Table header & footer - %====================================================================== - + %-Table axes & Title %---------------------------------------------------------------------- - if SatWindow, ht = 0.85; bot = 0.14; else ht = 0.4; bot = 0.1; end - if STAT == 'P' Title = 'Posterior Probabilities'; end hAx = axes('Position',[0.025 bot 0.9 ht],... - 'DefaultTextFontSize',FS(8),... - 'DefaultTextInterpreter','Tex',... - 'DefaultTextVerticalAlignment','Baseline',... - 'Units','points',... - 'Visible','off'); + 'DefaultTextFontSize',FS(8),... + 'DefaultTextInterpreter','Tex',... + 'DefaultTextVerticalAlignment','Baseline',... + 'Tag','SPMList',... + 'Units','points',... + 'Visible','off'); AxPos = get(hAx,'Position'); set(hAx,'YLim',[0,AxPos(4)]) dy = FS(9); @@ -272,7 +268,7 @@ text(0.64,y, 'peak-level','FontSize',FS(9)); line([0.48,0.88],[1,1]*(y-dy/4),'LineWidth',0.5,'Color','r'); h = text(0.49,y-9*dy/8, '\itp\rm_{FWE-corr}'); Hp = [Hp,h]; - h = text(0.58,y-9*dy/8, '\itq\rm_{FDR-corr}'); Hp = [Hp,h]; + h = text(0.58,y-9*dy/8, '\itq\rm_{FDR-corr}'); Hp = [Hp,h]; h = text(0.82,y-9*dy/8, '\itp\rm_{uncorr}'); Hp = [Hp,h]; h = text(0.67,y-9*dy/8, sprintf('\\it%c',STAT)); h = text(0.75,y-9*dy/8, '(\itZ\rm_\equiv)'); @@ -280,11 +276,12 @@ text(0.92,y - dy/2,[units{:}],'Fontsize',FS(8)); - %-Headers for text table... - %----------------------------------------------------------------------- + %-Headers for text table + %---------------------------------------------------------------------- TabDat.tit = Title; - TabDat.hdr = { 'set', 'c';... + TabDat.hdr = {... 'set', 'p';... + 'set', 'c';... 'cluster', 'p(FWE-cor)';... 'cluster', 'p(FDR-cor)';... 'cluster', 'equivk';... @@ -331,12 +328,12 @@ %-Volume, resels and smoothness (if classical inference) %---------------------------------------------------------------------- line([0 1],[0 0],'LineWidth',1,'Color','r') + if STAT ~= 'P' %------------------------------------------------------------------ - Pz = spm_P(1,0,u,df,STAT,1,n,S); - Pu = spm_P(1,0,u,df,STAT,R,n,S); - %Qu = spm_P_FDR(u,df,STAT,n,QPs); - [P Pn Em En EN] = spm_P(1,k,u,df,STAT,R,n,S); + Pz = spm_P(1,0,u,df,STAT,1,n,S); + Pu = spm_P(1,0,u,df,STAT,R,n,S); + [P Pn Ec Ek] = spm_P(1,k,u,df,STAT,R,n,S); %-Footnote with SPM parameters %------------------------------------------------------------------ @@ -348,11 +345,11 @@ STAT,u,Pz,Pu); TabDat.ftr{2} = ... sprintf('Extent threshold: k = %0.0f voxels, p = %0.3f (%0.3f)',... - k/v2r,Pn,P); + k/V2R,Pn,P); TabDat.ftr{3} = ... - sprintf('Expected voxels per cluster, = %0.3f',En/v2r); + sprintf('Expected voxels per cluster, = %0.3f',Ek/V2R); TabDat.ftr{4} = ... - sprintf('Expected number of clusters, = %0.2f',Em*Pn); + sprintf('Expected number of clusters, = %0.2f',Ec*Pn); if any(isnan(varargin{2}.uc)) TabDat.ftr{5} = ... sprintf('FWEp: %0.3f, FDRp: %0.3f',varargin{2}.uc(1:2)); @@ -376,11 +373,11 @@ text(0.0,-1*dy,TabDat.ftr{1},... 'UserData',[u,Pz,Pu],'ButtonDownFcn','get(gcbo,''UserData'')') text(0.0,-2*dy,TabDat.ftr{2},... - 'UserData',[k/v2r,Pn,P],'ButtonDownFcn','get(gcbo,''UserData'')') + 'UserData',[k/V2R,Pn,P],'ButtonDownFcn','get(gcbo,''UserData'')') text(0.0,-3*dy,TabDat.ftr{3},... - 'UserData',En/v2r,'ButtonDownFcn','get(gcbo,''UserData'')') + 'UserData',Ek/V2R,'ButtonDownFcn','get(gcbo,''UserData'')') text(0.0,-4*dy,TabDat.ftr{4},... - 'UserData',Em*Pn,'ButtonDownFcn','get(gcbo,''UserData'')') + 'UserData',Ec*Pn,'ButtonDownFcn','get(gcbo,''UserData'')') text(0.0,-5*dy,TabDat.ftr{5},... 'UserData',varargin{2}.uc,'ButtonDownFcn','get(gcbo,''UserData'')') text(0.5,-1*dy,TabDat.ftr{6},... @@ -412,23 +409,51 @@ return end - % Includes Darren Gitelman's code for working around - % spm_max for conjunctions with negative thresholds + %-Workaround in spm_max for conjunctions with negative thresholds %---------------------------------------------------------------------- - minz = abs(min(min(varargin{2}.Z))); - zscores = 1 + minz + varargin{2}.Z; - [N Z XYZ A] = spm_max(zscores,varargin{2}.XYZ); - Z = Z - minz - 1; + minz = abs(min(min(varargin{2}.Z))); + zscores = 1 + minz + varargin{2}.Z; + [N Z XYZ A L] = spm_max(zscores,varargin{2}.XYZ); + Z = Z - minz - 1; - %-Convert cluster sizes from voxels to resels + + %-Convert cluster sizes from voxels (N) to resels (K) %---------------------------------------------------------------------- - if STAT~='P' - if isfield(varargin{2},'VRvp') - V2R = spm_get_data(varargin{2}.VRvp,XYZ); + c = max(A); %-Number of clusters + try + NONSTAT = spm_get_defaults('stats.rft.nonstat'); + catch + NONSTAT = 0; + end + if STAT ~= 'P' + if NONSTAT + K = zeros(c,1); + for i = 1:c + + %-Get LKC for voxels in i-th region + %---------------------------------------------------------- + LKC = spm_get_data(varargin{2}.VRpv,L{i}); + + %-Compute average of valid LKC measures for i-th region + %---------------------------------------------------------- + valid = ~isnan(LKC); + if any(valid) + LKC = sum(LKC(valid)) / sum(valid); + else + LKC = V2R; % fall back to whole-brain resel density + end + + %-Intrinsic volume (with surface correction) + %---------------------------------------------------------- + IV = spm_resels([1 1 1],L{i},'V'); + IV = IV*[1/2 2/3 2/3 1]'; + K(i) = IV*LKC; + + end + K = K(A); else - V2R = v2r; + K = N*V2R; end - N = N.*V2R; end %-Convert maxima locations from voxels to mm @@ -436,7 +461,6 @@ XYZmm = M(1:3,:)*[XYZ; ones(1,size(XYZ,2))]; - %-Table proper (& note all data in cell array) %====================================================================== @@ -448,7 +472,6 @@ %-Set-level p values {c} - do not display if reporting a single cluster %---------------------------------------------------------------------- - c = max(A); %-Number of clusters if STAT ~= 'P' Pc = spm_P(c,k,u,df,STAT,R,n,S); %-Set-level p-value else @@ -458,10 +481,10 @@ if c > 1; h = text(tCol(1),y,sprintf(TabDat.fmt{1},Pc),'FontWeight','Bold',... - 'UserData',Pc,'ButtonDownFcn','get(gcbo,''UserData'')'); + 'UserData',Pc,'ButtonDownFcn','get(gcbo,''UserData'')'); hPage = [hPage, h]; h = text(tCol(2),y,sprintf(TabDat.fmt{2},c),'FontWeight','Bold',... - 'UserData',c,'ButtonDownFcn','get(gcbo,''UserData'')'); + 'UserData',c,'ButtonDownFcn','get(gcbo,''UserData'')'); hPage = [hPage, h]; else set(Hc,'Visible','off') @@ -476,16 +499,14 @@ HlistXYZ = []; while numel(find(isfinite(Z))) - % Paginate if necessary + %-Paginate if necessary %------------------------------------------------------------------ if y < min(Num + 1,3)*dy - % added Fgraph term to paginate on Satellite window - %-------------------------------------------------------------- h = text(0.5,-5*dy,... sprintf('Page %d',spm_figure('#page',Fgraph)),... - 'FontName',PF.helvetica,'FontAngle','Italic',... - 'FontSize',FS(8)); + 'FontName',PF.helvetica,'FontAngle','Italic',... + 'FontSize',FS(8)); spm_figure('NewPage',[hPage,h]) hPage = []; @@ -501,29 +522,33 @@ %-Compute cluster {k} and peak-level {u} p values for this cluster %------------------------------------------------------------------ if STAT ~= 'P' - Nv = N(i)/v2r; % extent {voxels} + % p-values (FWE) + %-------------------------------------------------------------- Pz = spm_P(1,0, U,df,STAT,1,n,S); % uncorrected p value Pu = spm_P(1,0, U,df,STAT,R,n,S); % FWE-corrected {based on Z} - [Pk Pn] = spm_P(1,N(i),u,df,STAT,R,n,S); % [un]corrected {based on k} + [Pk Pn] = spm_P(1,K(i),u,df,STAT,R,n,S); % [un]corrected {based on K} + + % q-values (FDR) + %-------------------------------------------------------------- if topoFDR - Qc = spm_P_clusterFDR(N(i),df,STAT,R,n,u,QPc); % cluster FDR-corrected {based on k} - Qp = spm_P_peakFDR(U,df,STAT,R,n,u,QPp); % peak FDR-corrected {based on Z} + Qc = spm_P_clusterFDR(K(i),df,STAT,R,n,u,QPc); % based on K + Qp = spm_P_peakFDR(U,df,STAT,R,n,u,QPp); % based on Z Qu = []; else - Qu = spm_P_FDR( U,df,STAT,n,QPs); % voxel FDR-corrected {based on Z} + Qu = spm_P_FDR(U,df,STAT,n,QPs); % voxel FDR-corrected Qc = []; Qp = []; end - if Pz < tol % Equivalent Z-variate - Ze = Inf; % (underflow => can't compute) + % Equivalent Z-variate + %-------------------------------------------------------------- + if Pz < tol + Ze = Inf; else Ze = spm_invNcdf(1 - Pz); end else - Nv = N(i); - Pz = []; Pu = []; Qu = []; @@ -545,8 +570,8 @@ h = text(tCol(4),y,sprintf(TabDat.fmt{4},Qc),'FontWeight','Bold',... 'UserData',Qc,'ButtonDownFcn','get(gcbo,''UserData'')'); hPage = [hPage, h]; - h = text(tCol(5),y,sprintf(TabDat.fmt{5},Nv),'FontWeight','Bold',... - 'UserData',Nv,'ButtonDownFcn','get(gcbo,''UserData'')'); + h = text(tCol(5),y,sprintf(TabDat.fmt{5},N(i)),'FontWeight','Bold',... + 'UserData',N(i),'ButtonDownFcn','get(gcbo,''UserData'')'); hPage = [hPage, h]; h = text(tCol(6),y,sprintf(TabDat.fmt{6},Pn),'FontWeight','Bold',... 'UserData',Pn,'ButtonDownFcn','get(gcbo,''UserData'')'); @@ -563,7 +588,7 @@ 'UserData',Qu,'ButtonDownFcn','get(gcbo,''UserData'')'); end hPage = [hPage, h]; - h = text(tCol(9),y,sprintf(TabDat.fmt{9},U),'FontWeight','Bold',... + h = text(tCol(9),y,sprintf(TabDat.fmt{9},U), 'FontWeight','Bold',... 'UserData',U,'ButtonDownFcn','get(gcbo,''UserData'')'); hPage = [hPage, h]; h = text(tCol(10),y,sprintf(TabDat.fmt{10},Ze),'FontWeight','Bold',... @@ -577,7 +602,7 @@ % Specifically changed so it properly finds hMIPax %------------------------------------------------------------------ tXYZmm = XYZmm(DIM,i); - h = text(tCol(12),y,sprintf(TabDat.fmt{12},tXYZmm),... + h = text(tCol(12),y,sprintf(TabDat.fmt{12},tXYZmm),... 'FontWeight','Bold',... 'Tag','ListXYZ',... 'ButtonDownFcn',[... @@ -595,9 +620,9 @@ y = y - dy; if topoFDR - [TabDat.dat{TabLin,3:12}] = deal(Pk,Qc,Nv,Pn,Pu,Qp,U,Ze,Pz,XYZmm(:,i)); + [TabDat.dat{TabLin,3:12}] = deal(Pk,Qc,N(i),Pn,Pu,Qp,U,Ze,Pz,XYZmm(:,i)); else - [TabDat.dat{TabLin,3:12}] = deal(Pk,Qc,Nv,Pn,Pu,Qu,U,Ze,Pz,XYZmm(:,i)); + [TabDat.dat{TabLin,3:12}] = deal(Pk,Qc,N(i),Pn,Pu,Qu,U,Ze,Pz,XYZmm(:,i)); end TabLin = TabLin + 1; @@ -616,9 +641,9 @@ if y < dy h = text(0.5,-5*dy,sprintf('Page %d',... spm_figure('#page',Fgraph)),... - 'FontName',PF.helvetica,... - 'FontAngle','Italic',... - 'FontSize',FS(8)); + 'FontName',PF.helvetica,... + 'FontAngle','Italic',... + 'FontSize',FS(8)); spm_figure('NewPage',[hPage,h]) hPage = []; @@ -694,7 +719,7 @@ 'UserData',XYZmm(:,d)); HlistXYZ = [HlistXYZ, h]; - if spm_XYZreg('Edist',xyzmm,XYZmm(:,d))1 h = text(0.5,-5*dy,sprintf('Page %d/%d',spm_figure('#page',Fgraph)*[1,1]),... @@ -727,22 +751,27 @@ %-End: Store TabDat in UserData of axes & reset pointer %====================================================================== - h = uicontextmenu('Tag','TabDat',... + h = uicontextmenu('Tag','TabDat',... 'UserData',TabDat); set(gca,'UIContextMenu',h,... 'Visible','on',... 'XColor','w','YColor','w') - uimenu(h,'Label','Table') - uimenu(h,'Separator','on','Label','Print text table',... + uimenu(h,'Label','Print text table',... 'Tag','TD_TxtTab',... 'CallBack',... 'spm_list(''txtlist'',get(get(gcbo,''Parent''),''UserData''),3)',... 'Interruptible','off','BusyAction','Cancel'); uimenu(h,'Separator','off','Label','Extract table data structure',... 'Tag','TD_Xdat',... - 'CallBack','get(get(gcbo,''Parent''),''UserData'')',... + 'CallBack','TabDat=get(get(gcbo,''Parent''),''UserData'')',... 'Interruptible','off','BusyAction','Cancel'); - uimenu(h,'Separator','on','Label','help',... + if ispc + uimenu(h,'Separator','off','Label','Export to Excel',... + 'Tag','TD_Xdat',... + 'CallBack',@export2excel,... + 'Interruptible','off','BusyAction','Cancel'); + end + uimenu(h,'Separator','on','Label','Help',... 'Tag','TD_Xdat',... 'CallBack','spm_help(''spm_list'')',... 'Interruptible','off','BusyAction','Cancel'); @@ -771,7 +800,7 @@ if nargin < 3, hReg = []; else hReg = varargin{3}; end SPM = varargin{2}; - %-get number and separation for maxima to be reported + %-Get number and separation for maxima to be reported %------------------------------------------------------------------ if length(varargin) > 3 @@ -782,15 +811,14 @@ Dis = 4; end - - %-if there are suprathreshold voxels, filter out all but current cluster + %-If there are suprathreshold voxels, filter out all but current cluster %------------------------------------------------------------------ if ~isempty(SPM.Z) %-Jump to voxel nearest current location %-------------------------------------------------------------- [xyzmm,i] = spm_XYZreg('NearestXYZ',... - spm_results_ui('GetCoords'),SPM.XYZmm); + spm_results_ui('GetCoords'),SPM.XYZmm); spm_results_ui('SetCoords',SPM.XYZmm(:,i)); %-Find selected cluster @@ -848,10 +876,10 @@ - %================================================================== + %====================================================================== case 'setcoords' %-Co-ordinate change - %================================================================== - % FORMAT spm_list('SetCoords',xyz,hAx,hReg) + %====================================================================== + % FORMAT spm_list('SetCoords',xyz,hAx,hReg) if nargin<3, error('Insufficient arguments'), end hAx = varargin{3}; xyz = varargin{2}; @@ -871,9 +899,21 @@ set(HlistXYZ(i),'Color','r') end - %================================================================== + %====================================================================== otherwise %-Unknown action string - %================================================================== + %====================================================================== error('Unknown action string') end + %========================================================================== +function export2excel(obj,evd,h) +TabDat = get(get(obj,'Parent'),'UserData'); +d = [TabDat.hdr;TabDat.dat]; +xyz = d(3:end,end); +xyz = num2cell([xyz{:}]'); +d(:,end+1) = d(:,end); +d(:,end+1) = d(:,end); +d(3:end,end-2:end) = xyz; +tmpfile = [tempname '.xls']; +xlswrite(tmpfile, d); +winopen(tmpfile); diff --git a/spm_logdet.m b/spm_logdet.m index fd39349..aece139 100644 --- a/spm_logdet.m +++ b/spm_logdet.m @@ -9,7 +9,9 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_logdet.m 3661 2010-01-05 17:00:47Z guillaume $ +% $Id: spm_logdet.m 3707 2010-02-02 19:01:59Z guillaume $ + +sw = warning('off','MATLAB:log:logOfZero'); % assume diagonal form %-------------------------------------------------------------------------- @@ -22,14 +24,12 @@ % invoke det if non-diagonal %-------------------------------------------------------------------------- -sw = warning('off','all'); [i j] = find(C); if any(i ~= j) n = length(C); a = exp(H/n); H = H + log(det(C/a)); end -warning(sw) % invoke svd is rank deficient %-------------------------------------------------------------------------- @@ -37,3 +37,5 @@ s = svd(full(C)); H = sum(log(s(s > TOL & s < 1/TOL))); end + +warning(sw) diff --git a/spm_lorenz_k.m b/spm_lorenz_k.m new file mode 100644 index 0000000..37313d2 --- /dev/null +++ b/spm_lorenz_k.m @@ -0,0 +1,29 @@ +function [f] = spm_lorenz_k(x,v,P) +% Equations of motion for coupled Lorenz attractors +% FORMAT [f] = spm_lorenz_k(x,v,P) +% x - hidden states (3 x N) +% v - exogenous input +% P - parameters +% P.t = N x 1 +% P.k = 1 x 1 +%__________________________________________________________________________ + +% take expectations and unpack +%-------------------------------------------------------------------------- +X = mean(x,2); % order parameters (mean-field) +N = size(x,2); % number of oscillators + +% p(1): Prandtl number +% p(2): 8/3 +% p(3): Rayleigh number +%-------------------------------------------------------------------------- +p = [10; -8/3; 32]; +f = x; +for i = 1:N + f(:,i) = [-p(1) p(1) 0; p(3) -1 -x(1,i); x(2,i) 0 p(2)]*x(:,i); + f(:,i) = (f(:,i) + P.k*X)*exp(P.t(i)); +end + +% vectorised flow +%-------------------------------------------------------------------------- +f = spm_vec(f); diff --git a/spm_make_contrasts.m b/spm_make_contrasts.m index e9a1b1c..aa5220c 100644 --- a/spm_make_contrasts.m +++ b/spm_make_contrasts.m @@ -1,30 +1,32 @@ -function [Con] = spm_make_contrasts (k) +function Con = spm_make_contrasts(k) % Make contrasts for one, two or three-way ANOVAs -% FORMAT [Con] = spm_make_contrasts (k) +% FORMAT Con = spm_make_contrasts(k) % -% k A vector where the ith entry is the number of levels of factor i +% k - vector where the ith entry is the number of levels of factor i +% +% Con - struct array with fields: +% Con(c).c - Contrast matrix +% .name - Name +% +% This function computes contrasts for a generic k(1)-by-k(2)-by-k(3) design. +% It is assumed that the levels of the first factor change slowest. % -% This function computes contrasts for a generic k(1)-by-k(2)-by-k(3) design. -% It is assumed that the levels of the first factor -% change slowest. -% % For one-way ANOVAs set k=L, where L is the number of % levels, for two-way ANOVAs set k=[L1 L2], for three way set k=[L1 L2 L3] % % This function generates (transposed) contrast matrices to test % average effect, main effect of each factor and interactions +%__________________________________________________________________________ +% +% Reference: % -% Con(c).c Contrast matrix -% .name Name -%_______________________________________________________________________ +% For details of Kronecker operations, see section 5 of +% http://www.fil.ion.ucl.ac.uk/~wpenny/publications/rik_anova.pdf +%__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Will Penny -% $Id: spm_make_contrasts.m 3249 2009-07-03 16:43:55Z guillaume $ - -% See section 5 of -% http://www.fil.ion.ucl.ac.uk/~wpenny/publications/rik_anova.pdf -% for details of kronecker operations +% $Id: spm_make_contrasts.m 3723 2010-02-12 15:15:18Z guillaume $ % Number of factors nf=length(k); diff --git a/spm_matlab_version_chk.m b/spm_matlab_version_chk.m index a55dc78..cdfc952 100644 --- a/spm_matlab_version_chk.m +++ b/spm_matlab_version_chk.m @@ -56,7 +56,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Darren Gitelman -% $Id: spm_matlab_version_chk.m 2696 2009-02-05 20:29:48Z guillaume $ +% $Id: spm_matlab_version_chk.m 3934 2010-06-17 14:58:25Z guillaume $ % output variable %-------------------------------------------------------------------------- @@ -82,19 +82,13 @@ % If too many fields in input then error %------------------------------------------------------- -if numel(findstr(chk,'.')) > 3 +if numel(strfind(chk,'.')) > 3 error('Input string has too many fields. Only major.minor.release.build fields are supported.'); end % parse the input string into a cell array of strings %-------------------------------------------------------------------------- -try - vCHK = textscan(chk,'%s %s %s %s','delimiter','.'); -catch - % version 6.5 does not have textscan function. - % This code will be deprecated eventually. - [ vCHK{1:4} ] = strread(chk,'%s %s %s %s','delimiter','.'); -end +vCHK = textscan(chk,'%s %s %s %s','delimiter','.'); % find empty cells. These will be set to 0 in both cell arrays so that the % same revision fields are compared @@ -117,12 +111,7 @@ % parse the requested toolbox version string into a cell array of strings. %-------------------------------------------------------------------------- -try - vTBX = textscan(tbxVer,'%s %s %s %s','delimiter','.'); -catch - % This code will be deprecated eventually. - [ vTBX{1:4} ] = strread(tbxVer,'%s %s %s %s','delimiter','.'); -end +vTBX = textscan(tbxVer,'%s %s %s %s','delimiter','.'); % find empty cells. These will be removed from the cell array so that the % same revision fields are compared diff --git a/spm_matx.m b/spm_matx.m deleted file mode 100644 index 4ee0c2c..0000000 --- a/spm_matx.m +++ /dev/null @@ -1,60 +0,0 @@ -function varargout = spm_matx(matfile,varargin) -% Utility to extract variables from a mat-file -% FORMAT [v1,v2,...] = spm_matx(matfile,n1,n2,n3,...) -% -% matfile - name of Matlab mat-file -% n1,n2,n3,... - names of variables to be extracted from mat-file (strings) -% v2,v3,v3,... - variables extracted from mat-file -%_______________________________________________________________________ -% -% This utility enables limited extraction (and renaming) of variables -% from a Matlab mat-file. It works by loading the mat-file in the -% functions workspace, and sending the named variables back as output -% arguments. -% -% E.g. : Matlab mat-file 'test.mat' in the current workign directory -% contains variables X, Y and Z, amongst other things. You already have -% an X, Y and Z variable, and don't wish to load the other variables -% from the mat-file. Using spm_matx, you can obtain X Y and Z as 'X1', -% 'Y1', and 'Z1' by: -% [X1,Y1,Z1] = spm_matx('test','X','Y','Z') -% -% -% NB: Unfortunately this function has to load the *entire* mat-file -% into memory. To load individual data structures from mat-files -% requires an external C routine using the mat* functions of the mat.h -% Matlab C API. (See the MatLab Application Program Interface Guide", -% section 5 for details.) Since this is rather involved, and this -% functionality is intended for small mat-files, this m-file function -% implementation is more practicable. -%_______________________________________________________________________ -% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging - -% Andrew Holmes -% $Id: spm_matx.m 1143 2008-02-07 19:33:33Z spm $ - - - -%-Check arguments -%----------------------------------------------------------------------- -if nargin<2, varargout={}; return, end -matfile = [spm_str_manip(matfile,'s'),'.mat']; -if exist(matfile,'file')~=2, error(['invalid mat-file: ',matfile]), end - - -%-Note mat-file variables into structure M (feature introduced in v5.2) -%----------------------------------------------------------------------- -M = load(matfile); - - -%-Loop through varargin putting named variables into output arguments -%----------------------------------------------------------------------- -varargout = cell(1,nargout); -for i=1:min(max(1,nargout),nargin-1) - if isfield(M,varargin{i}) - varargout{i} = getfield(M,varargin{i}); - else - warning(['variable "',varargin{i},'" not found in mat-file: ',... - matfile]) - end -end diff --git a/spm_max.m b/spm_max.m index 37bf88c..8b11e60 100644 --- a/spm_max.m +++ b/spm_max.m @@ -1,26 +1,29 @@ -function [N,Z,M,A] = spm_max(X,L) +function [N,Z,M,A,XYZ] = spm_max(X,L) % Sizes, maxima and locations of local excursion sets -% FORMAT [N Z M A] = spm_max(X,L) +% FORMAT [N Z M A XYZ] = spm_max(X,L) % X - values of 3-D field -% L - locations [x y x]' {in voxels} +% L - locations [x y z]' {in voxels} +% % N - size of region {in voxels) % Z - Z values of maxima % M - location of maxima {in voxels} % A - region number +% XYZ - cell array of voxel locations %__________________________________________________________________________ % % spm_max characterizes a point list of voxel values (X) and their % locations (L) in terms of edge, face and vertex connected subsets, % returning a maxima- orientated list: The value of the ith maximum is % Z(i) and its location is given by M(:,i). A(i) identifies the ith -% maximum with a region. Region A(i) contains N(i) voxels. +% maximum with a region. Region A(i) contains N(i) voxels, whose +% coordinates are in a 3-by-N(i) array in XYZ{i}. % % See also: spm_bwlabel.c and spm_clusters.m %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Jesper Andersson -% $Id: spm_max.m 2690 2009-02-04 21:44:28Z guillaume $ +% $Id: spm_max.m 3826 2010-04-21 18:36:44Z ged $ if isempty(L) N = []; Z = []; M = []; A = []; @@ -46,7 +49,7 @@ % Get size (in no. of voxels) for each connected component % ccs = connected component size %-------------------------------------------------------------------------- -ccs = histc(cci(:),[0:max(cci(:))]+0.5); +ccs = histc(cci(:),(0:num) + 0.5); ccs = ccs(1:end-1); % Get indices into L for voxels that are indeed local maxima (using an 18 @@ -60,3 +63,14 @@ mindex = sub2ind(dim,L(1,Lindex)',L(2,Lindex)',L(3,Lindex)'); A = cci(mindex); N = ccs(A); + +% Cell array of XYZ locations of voxels in each cluster +%-------------------------------------------------------------------------- +if nargout > 4 + xyz(:,index) = sparse(L); + cci = sparse(cci(:)); + XYZ = cell(1, max(A)); + for i = 1:max(A) + XYZ{i} = full(xyz(:,cci == i)); + end +end diff --git a/spm_mesh_clusters.m b/spm_mesh_clusters.m new file mode 100644 index 0000000..105b494 --- /dev/null +++ b/spm_mesh_clusters.m @@ -0,0 +1,46 @@ +function [C, N] = spm_mesh_clusters(M,T) +% Label connected components of surface mesh data +% FORMAT [C, N] = spm_mesh_clusters(M,T) +% M - a [mx3] faces array or a patch structure +% T - a [nx1] data vector (using NaNs or logicals), n = #vertices +% +% C - a [nx1] vector of cluster indices +% N - a [px1] size of connected components {in vertices} +%__________________________________________________________________________ +% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging + +% Guillaume Flandin +% $Id: spm_mesh_clusters.m 4003 2010-07-19 18:22:38Z guillaume $ + + +%-Input parameters +%-------------------------------------------------------------------------- +if isnumeric(M) + F = M; +else + F = M.faces; +end + +%-Compute a reduced mesh corresponding to the data +%-------------------------------------------------------------------------- +B = NaN(size(T)); +if islogical(T) + i = find(T); +else + i = find(~isnan(T)); +end +B(i) = 1:length(i); +F = B(F); +F(any(isnan(F),2),:) = []; + +%-Label connected components +%-------------------------------------------------------------------------- +[CC,N] = spm_mesh_label(F, 'vertices'); +C = NaN(numel(T),1); +C(i) = CC; + +%-Sort connected component labels according to their size +%-------------------------------------------------------------------------- +[N,ni] = sort(N(:), 1, 'descend'); +[ni,ni] = sort(ni); +C(i) = ni(C(i)); diff --git a/spm_mesh_get_lm.m b/spm_mesh_get_lm.m new file mode 100644 index 0000000..739cba5 --- /dev/null +++ b/spm_mesh_get_lm.m @@ -0,0 +1,35 @@ +function L = spm_mesh_get_lm(M,T) +% Identification of local maxima on a textured surface mesh +% FORMAT L = spm_mesh_get_lm(M,T) +% M - a [nx3] faces array or a patch structure or a [nxn] adjacency +% matrix +% T - a [nx1] texture vector +% +% L - indices of vertices that are local maxima +%__________________________________________________________________________ +% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging + +% Guillaume Flandin +% $Id: spm_mesh_get_lm.m 3982 2010-07-09 13:36:53Z guillaume $ + +%-Obtain the adjacency matrix +%-------------------------------------------------------------------------- +if ~isnumeric(M) || size(M,1) ~= size(M,2) + A = spm_mesh_adjacency(M); +else + A = M; +end + +%-Restrict it to vertices that actually have data (~= NaN) +%-------------------------------------------------------------------------- +out = isnan(T(:)'); +A(:,out) = 0; % A(out,:) is not necessary for usage below + +%-Loop over vertices and identify local maxima +%-------------------------------------------------------------------------- +L = []; + +for i=find(~out) + v = T(find(A(i,:))); + if all(v 0; + setappdata(H.patch,'curvature',curv); + + %-Apply texture to mesh + %------------------------------------------------------------------ + updateTexture(H,[]); + + %-Set viewpoint, light and manipulation options + %------------------------------------------------------------------ + axis(H.axis,'image'); + axis(H.axis,'off'); + view(H.axis,[-90 0]); + material(H.figure,'dull'); + H.light = camlight; set(H.light,'Parent',H.axis); + + H.rotate3d = rotate3d(H.axis); + set(H.rotate3d,'Enable','on'); + set(H.rotate3d,'ActionPostCallback',{@myPostCallback, H}); + %try + % setAllowAxesRotate(H.rotate3d, ... + % setxor(findobj(H.figure,'Type','axes'),H.axis), false); + %end + + %-Store handles + %------------------------------------------------------------------ + setappdata(H.axis,'handles',H); + set(H.patch,'Visible','on'); + + %-Add context menu + %------------------------------------------------------------------ + spm_mesh_render('ContextMenu',H); + + %-Context Menu + %====================================================================== + case 'contextmenu' + if isempty(varargin), varargin{1} = gca; end + H = getHandles(varargin{1}); + if ~isempty(get(H.patch,'UIContextMenu')), return; end + + cmenu = uicontextmenu('Callback',{@myMenuCallback}); + + c1 = uimenu(cmenu, 'Label','Inflate', 'Interruptible','off', ... + 'Callback',{@myInflate, H}); + + c1 = uimenu(cmenu, 'Label','Overlay...', 'Interruptible','off', ... + 'Callback',{@myOverlay, H}); + + c2 = uimenu(cmenu, 'Label', 'Connected Components', 'Interruptible','off'); + C=getappdata(H.patch,'cclabel'); + for i=1:length(unique(C)) + uimenu(c2, 'Label',sprintf('Component %d',i), 'Checked','on', ... + 'Callback',{@myCCLabel, H}); + end + + c3 = uimenu(cmenu, 'Label','Rotate', 'Checked','on', 'Separator','on', ... + 'Callback',{@mySwitchRotate, H}); + + c3 = uimenu(cmenu, 'Label','Synchronise Views', 'Visible','off', ... + 'Checked','off', 'Tag','SynchroMenu', 'Callback',{@mySynchroniseViews, H}); + + c4 = uimenu(cmenu, 'Label','View'); + uimenu(c4, 'Label','Go to Y-Z view (right)', 'Callback', {@myView, H, [90 0]}); + uimenu(c4, 'Label','Go to Y-Z view (left)', 'Callback', {@myView, H, [-90 0]}); + uimenu(c4, 'Label','Go to X-Y view (top)', 'Callback', {@myView, H, [0 90]}); + uimenu(c4, 'Label','Go to X-Y view (bottom)', 'Callback', {@myView, H, [-180 -90]}); + uimenu(c4, 'Label','Go to X-Z view (front)', 'Callback', {@myView, H, [-180 0]}); + uimenu(c4, 'Label','Go to X-Z view (back)', 'Callback', {@myView, H, [0 0]}); + + c5 = uimenu(cmenu, 'Label','Transparency'); + uimenu(c5, 'Label','0%', 'Checked','on', 'Callback', {@myTransparency, H}); + uimenu(c5, 'Label','20%', 'Checked','off', 'Callback', {@myTransparency, H}); + uimenu(c5, 'Label','40%', 'Checked','off', 'Callback', {@myTransparency, H}); + uimenu(c5, 'Label','60%', 'Checked','off', 'Callback', {@myTransparency, H}); + uimenu(c5, 'Label','80%', 'Checked','off', 'Callback', {@myTransparency, H}); + + c6 = uimenu(cmenu, 'Label','Background Color'); + uimenu(c6, 'Label','White', 'Callback', {@myBackgroundColor, H, [1 1 1]}); + uimenu(c6, 'Label','Black', 'Callback', {@myBackgroundColor, H, [0 0 0]}); + uimenu(c6, 'Label','Custom...', 'Callback', {@myBackgroundColor, H, []}); + + c7 = uimenu(cmenu, 'Label','Save As...', 'Separator', 'on', ... + 'Callback', {@mySave, H}); + + try, set(H.rotate3d,'uicontextmenu',cmenu); end + try, set(H.patch, 'uicontextmenu',cmenu); end + + %-AddOverlay + %====================================================================== + case 'addoverlay' + if isempty(varargin), varargin{1} = gca; end + H = getHandles(varargin{1}); + if nargin < 3, varargin{2} = []; end + if nargin < 4, varargin{3} = []; end + updateTexture(H,varargin{2},varargin{3}); + + %-AddColourBar + %====================================================================== + case 'addcolourbar' + if isempty(varargin), varargin{1} = gca; end + H = getHandles(varargin{1}); + d = getappdata(H.patch,'data'); + col = getappdata(H.patch,'colourmap'); + if isempty(d) || ~any(d(:)), return; end + if isempty(col), col = hot(256); end + H.colourbar = colorbar('peer',H.axis); + c(1:size(col,1),1,1:size(col,2)) = col; + set(get(H.colourbar,'child'),'CData',c); + set(get(H.colourbar,'child'),'YData',[min(d) max(d)]); + set(H.colourbar,'YLim',[min(d) max(d)]); + set(H.colourbar,'Tag',''); + set(get(H.colourbar,'child'),'Tag',''); + setappdata(H.axis,'handles',H); + + %-Otherwise... + %====================================================================== + otherwise + try + spm_mesh_render('Disp',action,varargin{:}); + catch + error('Unknown action.'); + end +end + +varargout = {H}; + + +%========================================================================== +function O = getOptions(varargin) +O = []; +if ~nargin + return; +elseif nargin == 1 && isstruct(varargin{1}) + for i=fieldnames(varargin{1}) + O.(lower(i{1})) = varargin{1}.(i{1}); + end +elseif mod(nargin,2) == 0 + for i=1:2:numel(varargin) + O.(lower(varargin{i})) = varargin{i+1}; + end +else + error('Invalid list of property/value pairs.'); +end + +%========================================================================== +function H = getHandles(H) +if ishandle(H) && ~isappdata(H,'handles') + H.axis = H; + H.figure = ancestor(H.axis,'figure'); + H.patch = findobj(H.axis,'type','patch'); + H.light = findobj(H.axis,'type','light'); + H.rotate3d = rotate3d(H.figure); + setappdata(H.axis,'handles',H); +elseif ishandle(H) + H = getappdata(H,'handles'); +else + %H = H; +end + +%========================================================================== +function myPostCallback(obj,evt,H) +P = findobj('Tag','SPMMeshRender','Type','Patch'); +if numel(P) == 1 + camlight(H.light); +else + for i=1:numel(P) + H = getappdata(ancestor(P(i),'axes'),'handles'); + camlight(H.light); + end +end + +%========================================================================== +function myMenuCallback(obj,evt) +if numel(findobj('Tag','SPMMeshRender','Type','Patch')) > 1 + h = findobj(obj,'Tag','SynchroMenu'); + if ~isempty(h) + set(h,'Visible','on'); + end +end + +%========================================================================== +function myInflate(obj,evt,H) +spm_mesh_inflate(H.patch,Inf,1); +axis(H.axis,'image'); + +%========================================================================== +function myCCLabel(obj,evt,H) +C = getappdata(H.patch,'cclabel'); +F = get(H.patch,'Faces'); +ind = sscanf(get(obj,'Label'),'Component %d'); +V = get(H.patch,'FaceVertexAlphaData'); +Fa = get(H.patch,'FaceAlpha'); +if ~isnumeric(Fa) + if ~isempty(V), Fa = max(V); else Fa = 1; end + if Fa == 0, Fa = 1; end +end +if isempty(V) || numel(V) == 1 + Ve = get(H.patch,'Vertices'); + if isempty(V) || V == 1 + V = Fa * ones(size(Ve,1),1); + else + V = zeros(size(Ve,1),1); + end +end +if strcmpi(get(obj,'Checked'),'on') + V(reshape(F(C==ind,:),[],1)) = 0; + set(obj,'Checked','off'); +else + V(reshape(F(C==ind,:),[],1)) = Fa; + set(obj,'Checked','on'); +end +set(H.patch, 'FaceVertexAlphaData', V); +if all(V) + set(H.patch, 'FaceAlpha', Fa); +else + set(H.patch, 'FaceAlpha', 'interp'); +end + +%========================================================================== +function mySwitchRotate(obj,evt,H) +if strcmpi(get(H.rotate3d,'enable'),'on') + set(H.rotate3d,'enable','off'); + set(obj,'Checked','off'); +else + set(H.rotate3d,'enable','on'); + set(obj,'Checked','on'); +end + +%========================================================================== +function myView(obj,evt,H,varargin) +view(H.axis,varargin{1}); +axis(H.axis,'image'); +camlight(H.light); + +%========================================================================== +function mySynchroniseViews(obj,evt,H,varargin) +P = findobj('Tag','SPMMeshRender','Type','Patch'); +v = get(H.axis,'cameraposition'); +for i=1:numel(P) + H = getappdata(ancestor(P(i),'axes'),'handles'); + set(H.axis,'cameraposition',v); + axis(H.axis,'image'); + camlight(H.light); +end + +%========================================================================== +function myTransparency(obj,evt,H) +t = 1 - sscanf(get(obj,'Label'),'%d%%') / 100; +set(H.patch,'FaceAlpha',t); +set(get(get(obj,'parent'),'children'),'Checked','off'); +set(obj,'Checked','on'); + +%========================================================================== +function myBackgroundColor(obj,evt,H,varargin) +if isempty(varargin{1}) + c = uisetcolor(H.figure, ... + 'Pick a background color...'); + if numel(c) == 1, return; end +else + c = varargin{1}; +end +h = findobj(H.figure,'Tag','SPMMeshRenderBackground'); +if isempty(h) + set(H.figure,'Color',c); +else + set(h,'Color',c); +end + +%========================================================================== +function mySave(obj,evt,H) +[filename, pathname, filterindex] = uiputfile({... + '*.gii' 'GIfTI files (*.gii)'; ... + '*.png' 'PNG files (*.png)';... + '*.dae' 'Collada files (*.dae)';... + '*.idtf' 'IDTF files (*.idtf)'}, 'Save as'); +if ~isequal(filename,0) && ~isequal(pathname,0) + [pth,nam,ext] = fileparts(filename); + switch ext + case '.gii' + filterindex = 1; + case '.png' + filterindex = 2; + case '.dae' + filterindex = 3; + case '.idtf' + filterindex = 4; + otherwise + switch filterindex + case 1 + filename = [filename '.gii']; + case 2 + filename = [filename '.png']; + case 3 + filename = [filename '.dae']; + end + end + switch filterindex + case 1 + save(gifti(H.patch),fullfile(pathname, filename)); + case 2 + u = get(H.axis,'units'); + set(H.axis,'units','pixels'); + p = get(H.axis,'Position'); + r = get(getappdata(obj,'fig'),'Renderer'); + h = figure('Position',p+[0 0 10 10], ... + 'InvertHardcopy','off', ... + 'Color',get(H.figure,'Color'), ... + 'Renderer',r); + copyobj(H.axis,h); + set(H.axis,'units',u); + set(get(h,'children'),'visible','off'); + %a = get(h,'children'); + %set(a,'Position',get(a,'Position').*[0 0 1 1]+[10 10 0 0]); + if isdeployed + deployprint(h, '-dpng', '-opengl', fullfile(pathname, filename)); + else + print(h, '-dpng', '-opengl', fullfile(pathname, filename)); + end + close(h); + set(getappdata(obj,'fig'),'renderer',r); + case 3 + save(gifti(H.patch),fullfile(pathname, filename),'collada'); + case 4 + save(gifti(H.patch),fullfile(pathname, filename),'idtf'); + end +end + +%========================================================================== +function myDeleteFcn(obj,evt,renderer) +try, rotate3d(get(obj,'parent'),'off'); end +set(ancestor(obj,'figure'),'Renderer',renderer); + +%========================================================================== +function myOverlay(obj,evt,H) +[P, sts] = spm_select(1,'image','Select image to overlay'); +if ~sts, return; end +spm_mesh_render('AddOverlay',H,P); + +%========================================================================== +function C = updateTexture(H,v,col) + +if nargin <3 || isempty(col), col = hot(256); end +setappdata(H.patch,'colourmap',col); + +%-Get curvature +%-------------------------------------------------------------------------- +curv = getappdata(H.patch,'curvature'); +if size(curv,2) == 1 + curv = 0.5 * repmat(curv,1,3) + 0.3 * repmat(~curv,1,3); +end + +%-Project data onto surface mesh +%-------------------------------------------------------------------------- +if isstruct(v) && isfield(v,'FWHM') %-xSPM structure + v = struct('XYZ',v.XYZ, 't',v.Z, 'mat',v.M, 'dim',v.DIM); +end +if isempty(v) + v = zeros(size(curv))'; +elseif ischar(v) || iscellstr(v) || isstruct(v) + v = spm_mesh_project(H.patch,v); +end + +setappdata(H.patch,'data',v); + +%-Build texture by merging curvature and data +%-------------------------------------------------------------------------- +C = zeros(size(v,2),3); +if any(v(:)) + if size(col,1)>3 + if size(v,1) == 1 + C = squeeze(ind2rgb(floor(v(:)/max(v(:))*size(col,1)),col)); + else + C = v; v = v'; + end + else + m = max(v(:)); + for i=1:size(v,1) + C = C + v(i,:)'/m * col(i,:); + end + end +end +C = repmat(~any(v,1),3,1)' .* curv + repmat(any(v,1),3,1)' .* C; + +set(H.patch, 'FaceVertexCData',C, 'FaceColor','interp'); + +% if isfield(M,'cdata') && ~isempty(M.cdata) +% if any(size(M.cdata)==1), M.cdata = M.cdata(:); end +% if size(M.cdata,1)==3, M.cdata = M.cdata'; end +% set(H.patch, 'FaceVertexCData',M.cdata, 'FaceColor','interp'); +% else +% set(H.patch, 'FaceVertexCData',curv, 'FaceColor','interp'); +% end diff --git a/spm_mip.m b/spm_mip.m index 91054e8..dcb6fa2 100644 --- a/spm_mip.m +++ b/spm_mip.m @@ -20,8 +20,7 @@ function spm_mip(Z,XYZ,M,units) % This routine loads a mip putline from MIP.mat. This is an image with % contours and grids defining the space of Talairach & Tournoux (1988). % mip05 corresponds to the Talairach atlas, mip96 to the MNI templates. -% The outline and grid are superimposed at intensity defaults.grid, -% defaulting to 0.4. +% The outline and grid are superimposed at intensity 0.4. % % A default colormap of 64 levels is assumed. The pointlist image is % scaled to fit in the interval [0.25,1]*64 for display. Flat images @@ -34,14 +33,13 @@ function spm_mip(Z,XYZ,M,units) % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston et al. -% $Id: spm_mip.m 3348 2009-09-03 10:32:01Z guillaume $ +% $Id: spm_mip.m 3691 2010-01-20 17:08:30Z guillaume $ %-Get units and grid scaling %-------------------------------------------------------------------------- -global defaults -try, Grid = defaults.grid; catch, Grid = 0.4; end try, units; catch, units = {'mm' 'mm' 'mm'}; end try, M; catch, M = 1; end +Grid = 0.4; % transpose locations if necessary %-------------------------------------------------------------------------- diff --git a/spm_mvb_G.m b/spm_mvb_G.m index 83eaaec..0300c4a 100644 --- a/spm_mvb_G.m +++ b/spm_mvb_G.m @@ -38,7 +38,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_mvb_G.m 3337 2009-08-27 14:53:32Z karl $ +% $Id: spm_mvb_G.m 3813 2010-04-07 19:21:49Z karl $ % defaults %-------------------------------------------------------------------------- @@ -54,8 +54,7 @@ R = spm_svd(speye(size(X0,1)) - X0*pinv(X0)); L = R'*L; X = R'*X; -Nx = size(X,1); - + % random effects (and serial correlations) %-------------------------------------------------------------------------- if iscell(V) @@ -87,36 +86,31 @@ % Covariance components (with the first error Qe{1} fixed) %-------------------------------------------------------------------------- if size(L,2) > 0 - Q = {Qe{1} Qe{:} LQpL{:}}; + Q = [Qe LQpL]; else - Q = {Qe{1} Qe{:}}; + Q = Qe; end -% Lower bound on noise Qe{1} relative to signal (of about 2%) +% ReML (with mildly informative hyperpriors) and a lower bound on error %-------------------------------------------------------------------------- -m = length(Q); -hE = -32*ones(m,1); -hC = 256*speye(m,m); -hE(1) = -4; -hC(1) = 0; - -% ReML -%-------------------------------------------------------------------------- -[Cy,h,P,F,Fa,Fc] = spm_reml_sc(X*X',[],Q,size(X,2),hE,hC); - -h(2) = h(2) + h(1); -h = h(2:end); +N = size(X,2); +YY = X*X'; +Qe = exp(-2)*trace(YY)*Q{1}/trace(Q{1})/N; +hE = -4; +hC = 16; +[Cy,h,P,F] = spm_reml_sc(YY,[],Q,N,hE,hC,Qe); + % prior covariance: source space %-------------------------------------------------------------------------- Cp = sparse(Nk,Nk); for i = 1:Np - Cp = Cp + h(i + Ne)*Qp{i}; + Cp = Cp + h(i + Ne)*Qp{i}; end % MAP estimates of instantaneous sources %========================================================================== -MAP = Cp*L'*inv(Cy)*R'; +MAP = Cp*L'/Cy*R'; qE = MAP*R*X; diff --git a/spm_mvb_U.m b/spm_mvb_U.m index 463c311..bcc1643 100644 --- a/spm_mvb_U.m +++ b/spm_mvb_U.m @@ -1,9 +1,9 @@ function U = spm_mvb_U(Y,priors,X0,xyz,vox) % Constructs patterns U for Multivariate Bayesian inversion of a linear model % FORMAT U = spm_mvb_U(Y,priors,X0,xyz,vox) -% Y - date filature matrix +% Y - data-feature matrix % priors - 'null' % no patterns -% - 'compact' % reduced (ns/2); using SVD on local compact support +% - 'compact' % reduced (ns/3); using SVD on local compact support % - 'sparse' % a pattern is a voxel % - 'smooth' % patterns are local Gaussian kernels % - 'singular' % patterns are global singular vectors @@ -16,7 +16,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_mvb_U.m 3139 2009-05-21 18:37:29Z karl $ +% $Id: spm_mvb_U.m 3751 2010-03-04 20:21:08Z karl $ % defaults %-------------------------------------------------------------------------- @@ -30,7 +30,7 @@ % confounds %-------------------------------------------------------------------------- -if isempty(X0); X0 = sparse(ns,1); end +if isempty(X0); X0 = zeros(ns,1); end % get U: X = Y*P + X0*Q + R % P = U*E; diff --git a/spm_mvb_cvk.m b/spm_mvb_cvk.m index cf0f7e8..1da60d6 100644 --- a/spm_mvb_cvk.m +++ b/spm_mvb_cvk.m @@ -16,7 +16,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_mvb_cvk.m 2559 2008-12-12 17:10:23Z karl $ +% $Id: spm_mvb_cvk.m 3806 2010-04-06 14:42:32Z ged $ %-partition order @@ -124,46 +124,8 @@ R2 = corrcoef(pX,qX); R2 = 100*(R2(1,2)^2); - -% plot validation -%-------------------------------------------------------------------------- -subplot(2,2,1) -s = 1:length(pX); -plot(s,pX,s,qX,'-.') -xlabel('sample') -ylabel('response (adjusted)') -title('cross-validation') -axis square - -subplot(2,2,2) -plot(pX,qX,'.') -xlabel('true') -ylabel('predicted') -title(sprintf('p-value (parametric) = %.5f',p)) -axis square -abc = axis; -hold on -plot([max(abc([1 3])) min(abc([2 4]))],[max(abc([1 3])) min(abc([2 4]))],'k') - -% plot feature weights +% assign in base memory %-------------------------------------------------------------------------- -subplot(2,2,3) -imagesc(corrcoef(qE)) -colorbar -caxis([0 1]) -xlabel('biparititon (k)') -title({'correlations among';'k-fold feature weights'}) -axis square - -subplot(2,2,4) -spm_mip(prod(P,2),MVB.XYZ(1:3,:),MVB.VOX) -title({[MVB.name ' (' MVB.contrast ')'];'prod( P(|weights| > 0) )'}) -axis square - - -% display and assign in base memory -%-------------------------------------------------------------------------- -fprintf('\np-value = %.4f; classification: %.1f%s; R-squared %.1f%s\n',p,pc,'%',R2,'%') MVB.p_value = p; MVB.percent = pc; MVB.R2 = R2; @@ -173,3 +135,7 @@ %-------------------------------------------------------------------------- save(MVB.name,'MVB') assignin('base','MVB',MVB) + +% display and plot validation +%-------------------------------------------------------------------------- +spm_mvb_cvk_display(MVB) diff --git a/spm_mvb_cvk2.m b/spm_mvb_cvk2.m index d921ba9..573a940 100644 --- a/spm_mvb_cvk2.m +++ b/spm_mvb_cvk2.m @@ -2,7 +2,7 @@ % k-fold cross validation of a multivariate Bayesian model % FORMAT [p_value,percent,R2] = spm_mvb_cvk(MVB,k) % -% MVB - Multivariate Bays structure +% MVB - Multivariate Bayes structure % k - k-fold cross-validation ('0' implies a leave-one-out scheme) % % p - p-value: under a null GLM @@ -17,7 +17,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_mvb_cvk2.m 2559 2008-12-12 17:10:23Z karl $ +% $Id: spm_mvb_cvk2.m 3806 2010-04-06 14:42:32Z ged $ %-partition order @@ -93,57 +93,21 @@ R2 = corrcoef(pX,qX); R2 = 100*(R2(1,2)^2); - -% plot validation -%-------------------------------------------------------------------------- -subplot(2,2,1) -s = 1:length(pX); -plot(s,pX,s,qX,'-.') -xlabel('sample') -ylabel('response (adjusted)') -title('cross-validation') -axis square - -subplot(2,2,2) -plot(pX,qX,'.',[min(pX) max(pX)],[min(pX) max(pX)],'-.') -xlabel('true') -ylabel('predicted') -title(sprintf('p-value (parametric) = %.3e',p)) -axis square - - -% plot feature weights +% assign in base memory %-------------------------------------------------------------------------- -subplot(2,2,3) -imagesc(corrcoef(qE)) -colorbar -caxis([0 1]) -xlabel('bipartition (k)') -title({'correlations among';'k-fold feature weights'}) -axis square - -subplot(2,2,4) -qe = mean(qE,2); -qe = qe.*(qe > 0); -spm_mip(qe,MVB.XYZ(1:3,:),MVB.VOX) -title({[MVB.name ' (' MVB.contrast ')'];'mean (positive) weights'}) -axis square - - -% display and assign in base memory -%-------------------------------------------------------------------------- -fprintf('\np-value = %.4f; classification: %.1f%s; R-squared %.1f%s\n',p,pc,'%',R2,'%') MVB.p_value = p; MVB.percent = pc; MVB.R2 = R2; MVB.cvk = struct('qX',qX,'qE',qE); - + % save results %-------------------------------------------------------------------------- save(MVB.name,'MVB') assignin('base','MVB',MVB) - +% display and plot validation +%-------------------------------------------------------------------------- +spm_mvb_cvk_display(MVB) return diff --git a/spm_mvb_cvk_display.m b/spm_mvb_cvk_display.m index 5c835bb..a24571a 100644 --- a/spm_mvb_cvk_display.m +++ b/spm_mvb_cvk_display.m @@ -6,13 +6,14 @@ function spm_mvb_cvk_display(MVB) % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Christophe Phillips -% $Id: spm_mvb_cvk_display.m 2356 2008-10-17 15:08:19Z christophe $ +% $Id: spm_mvb_cvk_display.m 3806 2010-04-06 14:42:32Z ged $ if nargin<1 load(spm_select(1,'^MVB.*\.mat','Select MVB to display')) end if ~isfield(MVB,'cvk') - error('No crossvalidation data available. Select another file or perform the crossvalidation'); + error(['No crossvalidation data available. ' ... + 'Select another file or perform the crossvalidation']); end %-Get figure handles and set title @@ -55,14 +56,26 @@ function spm_mvb_cvk_display(MVB) imagesc(corrcoef(MVB.cvk.qE)) colorbar caxis([0 1]) -xlabel('biparititon (k)') +xlabel('bipartition (k)') title({'correlations among';'k-fold feature weights'}) axis square subplot(2,2,4) -spm_mip(prod(MVB.cvk.P,2),MVB.XYZ(1:3,:),MVB.VOX) -title({[MVB.name ' (' MVB.contrast ')'];'prod( P(|weights| > 0) )'}) +if ~isempty(MVB.XYZ) && ~isempty(MVB.VOX) + if isfield(MVB.cvk, 'P') + spm_mip(prod(MVB.cvk.P,2),MVB.XYZ(1:3,:),MVB.VOX) + title({[MVB.name ' (' MVB.contrast ')'];'prod( P(|weights| > 0) )'}) + else % reproduce plot from original spm_mvb_cvk2 + qe = mean(MVB.cvk.qE,2); + qe = qe.*(qe > 0); + spm_mip(qe,MVB.XYZ(1:3,:),MVB.VOX) + title({[MVB.name ' (' MVB.contrast ')'];'mean (positive) weights'}) + end +else + % (Allows MVB for non-spatial data, excluding smooth or compact priors) + title('No spatial info in MVB') +end axis square -fprintf('\np-value = %.4f; classification: %.1f%s; R-squared %.1f%s\n', ... - MVB.p_value,MVB.percent,'%',MVB.R2,'%') \ No newline at end of file +fprintf('\np-value = %.4f; classification: %.1f%%; R-squared %.1f%%\n', ... + MVB.p_value,MVB.percent,MVB.R2) diff --git a/spm_nlsi.m b/spm_nlsi.m index 49ab01f..a10809e 100644 --- a/spm_nlsi.m +++ b/spm_nlsi.m @@ -1,6 +1,6 @@ function varargout = spm_nlsi(M,U,Y) % nonlinear system identification of a MIMO system -% FORMAT [Ep,Cp,Ce,K0,K1,K2,M0,M1,L1,L2] = spm_nlsi(M,U,Y) +% FORMAT [Ep,Cp,Eh,K0,K1,K2,M0,M1,L1,L2] = spm_nlsi(M,U,Y) % FORMAT [K0,K1,K2,M0,M1,L1,L2] = spm_nlsi(M) % % Model specification @@ -34,7 +34,7 @@ %-------------------------------------------------------------------------- % Ep - (p x 1) conditional expectation E{P|y} % Cp - (p x p) conditional covariance Cov{P|y} -% Ce - (v x v) ReML estimate of Cov{e} +% Eh - (v x v) conditional log-precision % % System identification - Volterra kernels %-------------------------------------------------------------------------- @@ -89,7 +89,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_nlsi.m 3134 2009-05-19 11:08:45Z guillaume $ +% $Id: spm_nlsi.m 3764 2010-03-08 20:18:10Z guillaume $ % check integrator %-------------------------------------------------------------------------- @@ -105,9 +105,9 @@ % Gauss-Newton/Bayesian/EM estimation %====================================================================== - [Ep,Cp,Ce,F] = spm_nlsi_GN(M,U,Y); + [Ep,Cp,Eh,F] = spm_nlsi_GN(M,U,Y); - if nargout < 4, varargout = {Ep,Cp,Ce}; return, end + if nargout < 4, varargout = {Ep,Cp,Eh}; return, end else % Use prior expectation to expand around @@ -145,7 +145,7 @@ % graphics %========================================================================== -if length(dbstack) < 2 +if ~isdeployed && length(dbstack) < 2 subplot(2,1,1) plot([1:N]*dt,K1(:,:,1)) @@ -168,7 +168,7 @@ % output arguments %-------------------------------------------------------------------------- if nargin == 3 - varargout = {Ep,Cp,Ce,K0,K1,K2,M0,M1,L1,L2,F}; + varargout = {Ep,Cp,Eh,K0,K1,K2,M0,M1,L1,L2,F}; else varargout = {K0,K1,K2,M0,M1,L1,L2}; end @@ -189,11 +189,11 @@ M.f = inline('1./(1 + exp(-P*x)) + [u; 0]','x','u','P','M'); M.g = inline('x','x','u','P','M'); M.pE = [-1 .3;.5 -1]; % Prior expectation of parameters -M.pC = speye(4,4); % Prior covariance for parameters -M.x = zeros(2,1) % intial state x(0) -M.m = 1; % number of inputs -M.n = 2; % number of states -M.l = 2; % number of outputs +M.pC = speye(4,4); % Prior covariance for parameters +M.x = zeros(2,1) % intial state x(0) +M.m = 1; % number of inputs +M.n = 2; % number of states +M.l = 2; % number of outputs % characterise M in terms of Volterra kernels and Bilinear matrices: %-------------------------------------------------------------------------- @@ -212,10 +212,10 @@ % outputs %-------------------------------------------------------------------------- Y.name = 'response'; -y = spm_int(M.pE,M,U); +y = spm_int_D(M.pE,M,U); Y.y = y + randn(size(y))/32; Y.dt = U.dt*length(U.u)/length(Y.y); % estimate %-------------------------------------------------------------------------- -[Ep,Cp,Ce,K0,K1,K2,M0,M1,L1,L2,F] = spm_nlsi(M,U,Y); +[Ep,Cp,Eh,K0,K1,K2,M0,M1,L1,L2,F] = spm_nlsi(M,U,Y); diff --git a/spm_nlsi_GN.m b/spm_nlsi_GN.m index 5be2455..b457d9f 100644 --- a/spm_nlsi_GN.m +++ b/spm_nlsi_GN.m @@ -1,6 +1,6 @@ -function [Ep,Cp,S,F] = spm_nlsi_GN(M,U,Y) +function [Ep,Cp,Eh,F] = spm_nlsi_GN(M,U,Y) % Bayesian inversion of a nonlinear model using a Gauss-Newton/EM algorithm -% FORMAT [Ep,Cp,S,F] = spm_nlsi_GN(M,U,Y) +% FORMAT [Ep,Cp,Eh,F] = spm_nlsi_GN(M,U,Y) % % Dynamical MIMO models %__________________________________________________________________________ @@ -35,15 +35,15 @@ % % Y.y - outputs % Y.dt - sampling interval for outputs -% Y.X0 - Confounds or null space (over size(y,1) bins or all vec(y)) -% Y.Q - error precision components (over size(y,1) bins or all vec(y)) +% Y.X0 - Confounds or null space (over size(y,1) bins or all vec(y)) +% Y.Q - q error precision components (over size(y,1) bins or all vec(y)) % % % Parameter estimates %-------------------------------------------------------------------------- -% Ep - (p x 1) conditional expectation E{P|y} -% Cp - (p x p) conditional covariance Cov{P|y} -% S - (v x v) [Re]ML estimate of Cov{e} +% Ep - (p x 1) conditional expectation E{P|y} +% Cp - (p x p) conditional covariance Cov{P|y} +% Eh - (q x 1) conditional log-precisions E{h|y} % % log evidence %-------------------------------------------------------------------------- @@ -78,17 +78,19 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_nlsi_GN.m 3605 2009-12-01 13:29:43Z karl $ +% $Id: spm_nlsi_GN.m 3812 2010-04-07 16:52:05Z karl $ % figure (unless disabled) %-------------------------------------------------------------------------- -sw = warning('off','all'); try M.nograph; catch + M.nograph = 0; +end +if ~M.nograph Fsi = spm_figure('GetWin','SI'); end - + % check integrator %-------------------------------------------------------------------------- try @@ -229,8 +231,7 @@ Eu = spm_pinv(dfdu)*spm_vec(y); p = [V'*(spm_vec(M.P) - spm_vec(M.pE)); Eu]; Ep = spm_unvec(spm_vec(pE) + V*p(ip),pE); -Cp = pC; - + % EM %========================================================================== @@ -242,7 +243,7 @@ % time %---------------------------------------------------------------------- - Ti = clock; + tic; % M-Step: ReML estimator of variance components: h = max{F(p,h)} %====================================================================== @@ -261,17 +262,21 @@ % M-step; Fisher scoring scheme to find h = max{F(p,h)} %====================================================================== - for m = 1:16 + for m = 1:8 + % check for stability + %------------------------------------------------------------------ + if norm(J,'inf') > exp(32), break, end + % precision and conditional covariance %------------------------------------------------------------------ - iS = speye(nt,nt)*1e-8; + iS = 0; for i = 1:nh iS = iS + Q{i}*exp(h(i)); end S = inv(iS); iS = kron(speye(nq),iS); - Cp = inv(J'*iS*J + ipC); + Cp = spm_inv(J'*iS*J + ipC); % precision operators for M-Step @@ -303,13 +308,9 @@ % update ReML estimate %------------------------------------------------------------------ - dh = spm_dx(dFdhh,dFdh); + dh = spm_dx(dFdhh,dFdh,{8}); h = h + dh; - % prevent overflow - %------------------------------------------------------------------ - h = min(max(h,-16),16); - % convergence %------------------------------------------------------------------ dF = dFdh'*dh; @@ -334,7 +335,7 @@ %---------------------------------------------------------------------- try F0; - fprintf(' actual: %.3e (%.2f sec)\n',full(F - C.F),etime(clock,Ti)) + fprintf(' actual: %.3e (%.2f sec)\n',full(F - C.F),toc) catch F0 = F; end @@ -357,7 +358,7 @@ % decrease regularization %------------------------------------------------------------------ - v = min(v + 1/2,8); + v = min(v + 1/2,4); str = 'EM:(+)'; else @@ -370,8 +371,8 @@ % and increase regularization %------------------------------------------------------------------ - v = min(v - 1,0); - str = 'EM:(-)'; + v = min(v - 2,-4); + str = 'EM:(-)'; end @@ -402,7 +403,8 @@ end subplot(2,1,1) - plot(x,f,x,f + spm_unvec(e,f),':') + plot(x,f), hold on + plot(x,f + spm_unvec(e,f),':'), hold off xlabel(xLab) title(sprintf('%s: %i','prediction and response: E-Step',k)) grid on @@ -431,8 +433,8 @@ % outputs %-------------------------------------------------------------------------- -warning(sw); - -Ep = spm_unvec(spm_vec(pE) + V*p(ip),pE); -Cp = V*Cp(ip,ip)*V'; +Ep = spm_unvec(spm_vec(pE) + V*C.p(ip),pE); +Cp = V*C.Cp(ip,ip)*V'; +Eh = C.h; F = C.F; + diff --git a/spm_nlsi_N.m b/spm_nlsi_N.m index ccea2b0..bc9ab95 100644 --- a/spm_nlsi_N.m +++ b/spm_nlsi_N.m @@ -83,7 +83,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_nlsi_N.m 3657 2009-12-23 20:22:10Z karl $ +% $Id: spm_nlsi_N.m 3696 2010-01-22 14:22:31Z karl $ % figure (unless disabled) %-------------------------------------------------------------------------- @@ -139,10 +139,9 @@ %-------------------------------------------------------------------------- if iscell(y) - ns = size(y{1},1); - % concatenate samples over cell, ensuring the same for predictions %---------------------------------------------------------------------- + ns = size(y{1},1); y = spm_cat(y(:)); IS = inline(['spm_cat(' IS '(P,M,U))'],'P','M','U'); @@ -372,7 +371,7 @@ % M-Step: update ReML estimate of h %-------------------------------------------------------------- - dh = spm_dx(dFdhh,dFdh,{4}); + dh = spm_dx(dFdhh,dFdh,{8}); h = h + dh; % convergence @@ -388,7 +387,7 @@ %------------------------------------------------------------------ dFdu = dgdu'*iS*ey - iuC*eu; dFduu = -dgdu'*iS*dgdu - iuC; - + % Conditional updates of confounds (u) %------------------------------------------------------------------ du = spm_dx(dFduu,dFdu,{4}); @@ -401,7 +400,7 @@ % Conditional updates of parameters (g) %------------------------------------------------------------------ - dg = spm_dx(dFdgg,dFdg,{4}); + dg = spm_dx(dFdgg,dFdg,{8}); Eg = spm_unvec(spm_vec(Eg) + Vg*dg,Eg); % convergence @@ -413,15 +412,15 @@ % optimise objective function: F(p) = log-evidence - divergence %====================================================================== - L(1) = - ey'*iS*ey/2; - L(2) = - ep'*ipC*ep/2; - L(3) = - eg'*igC*eg/2; - L(4) = - eu'*iuC*eu/2; - L(5) = - eh'*ihC*eh/2; - L(6) = - ns*nr*log(8*atan(1))/2; - L(7) = - nq*spm_logdet(S)/2; - L(8) = spm_logdet(ibC*Cb)/2; - L(9) = spm_logdet(ihC*Ch)/2; + L(1) = - ey'*iS*ey/2; % accuracy + L(2) = - ep'*ipC*ep/2; % complexity + L(3) = - eg'*igC*eg/2; % complexity + L(4) = - eu'*iuC*eu/2; % complexity + L(5) = - eh'*ihC*eh/2; % complexity + L(6) = - ns*nr*log(8*atan(1))/2; % accuracy + L(7) = - nq*spm_logdet(S)/2; % accuracy + L(8) = spm_logdet(ibC*Cb)/2; % complexity + L(9) = spm_logdet(ihC*Ch)/2; % complexity F = sum(L); % record increases and reference log-evidence for reporting @@ -435,7 +434,7 @@ % if F has increased, update gradients and curvatures for E-Step %---------------------------------------------------------------------- - if F > C.F || ip < 3 + if F > C.F % update gradients and curvature %------------------------------------------------------------------ @@ -444,12 +443,12 @@ % decrease regularization %------------------------------------------------------------------ - v = min(v + 1,4); + v = min(v + 1/2,4); str = 'EM(+)'; % accept current estimates %------------------------------------------------------------------ - C.Cb = Cb; % conditional covaraince + C.Cb = Cb; % conditional covariance C.Ep = Ep; % and expectations C.Eg = Eg; C.Eu = Eu; @@ -461,7 +460,7 @@ % reset expansion point %------------------------------------------------------------------ - Cb = C.Cb; % conditional covaraince + Cb = C.Cb; % conditional covariance Ep = C.Ep; % and expectations Eg = C.Eg; Eu = C.Eu; diff --git a/spm_normalise.m b/spm_normalise.m index 9dd816e..1013955 100644 --- a/spm_normalise.m +++ b/spm_normalise.m @@ -120,7 +120,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % John Ashburner -% $Id: spm_normalise.m 1143 2008-02-07 19:33:33Z spm $ +% $Id: spm_normalise.m 3756 2010-03-05 18:43:37Z guillaume $ if nargin<2, error('Incorrect usage.'); end; @@ -128,7 +128,7 @@ if ischar(VG), VG = spm_vol(VG); end; if nargin<3, if nargout==0, - [pth,nm,xt,vr] = fileparts(deblank(VF(1).fname)); + [pth,nm,xt,vr] = spm_fileparts(deblank(VF(1).fname)); matname = fullfile(pth,[nm '_sn.mat']); else matname = ''; diff --git a/spm_orthviews.m b/spm_orthviews.m index 1961eb3..1527357 100644 --- a/spm_orthviews.m +++ b/spm_orthviews.m @@ -113,7 +113,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % John Ashburner, Matthew Brett, Tom Nichols and Volkmar Glauche -% $Id: spm_orthviews.m 3639 2009-12-14 16:36:39Z guillaume $ +% $Id: spm_orthviews.m 3756 2010-03-05 18:43:37Z guillaume $ @@ -631,6 +631,9 @@ function xhairs(arg1) %_______________________________________________________________________ function my_delete(arg1) global st +% remove blobs (and colourbars, if any) +rmblobs(arg1); +% remove displayed axes for i=valid_handles(arg1), kids = get(st.fig,'Children'); for j=1:3, @@ -1335,7 +1338,7 @@ function redraw_colourbar(vh,bh,interval,cdata) if ~isdeployed, addpath(pluginpath); end % fprintf('spm_orthviews: Using Plugins in %s\n', pluginpath); for l = 1:numel(pluginfiles) - [p, pluginname, e, v] = fileparts(pluginfiles(l).name); + [p, pluginname, e, v] = spm_fileparts(pluginfiles(l).name); st.plugins{end+1} = strrep(pluginname, 'spm_ov_',''); % fprintf('%s\n',st.plugins{k}); end; diff --git a/spm_orthviews/spm_ov_reorient.m b/spm_orthviews/spm_ov_reorient.m index e593120..31b9549 100644 --- a/spm_orthviews/spm_ov_reorient.m +++ b/spm_orthviews/spm_ov_reorient.m @@ -14,9 +14,9 @@ % help spm_orthviews % at the matlab prompt. %_____________________________________________________________________________ -% $Id: spm_ov_reorient.m 3625 2009-12-09 13:33:41Z volkmar $ +% $Id: spm_ov_reorient.m 3756 2010-03-05 18:43:37Z guillaume $ -rev = '$Revision: 3625 $'; +rev = '$Revision: 3756 $'; global st; if isempty(st) @@ -164,7 +164,7 @@ return; end if strcmpi(qu, 'add other images') - [p n e v] = fileparts(st.vols{volhandle}.fname); + [p n e v] = spm_fileparts(st.vols{volhandle}.fname); P = cellstr(spm_select(Inf, 'image', {'Image(s) to reorient'}, P, p)); if isempty(P) || isempty(P{1}) disp('''Set origin to Xhairs'' cancelled.'); @@ -192,7 +192,7 @@ % Interaction callbacks case 'apply' - [p n e v] = fileparts(st.vols{volhandle}.fname); + [p n e v] = spm_fileparts(st.vols{volhandle}.fname); P = cellstr(spm_select(Inf, 'image', {'Image(s) to reorient'}, '', p)); if ~isempty(P) && ~isempty(P{1}) spm_progress_bar('Init', numel(P), 'Reorient', 'Images completed'); diff --git a/spm_orthviews/spm_ov_roi.m b/spm_orthviews/spm_ov_roi.m index 6b26300..c4a3c1d 100644 --- a/spm_orthviews/spm_ov_roi.m +++ b/spm_orthviews/spm_ov_roi.m @@ -87,14 +87,14 @@ % help spm_orthviews % at the matlab prompt. %_____________________________________________________________________________ -% $Id: spm_ov_roi.m 2672 2009-01-30 13:32:08Z volkmar $ +% $Id: spm_ov_roi.m 3920 2010-06-11 12:08:13Z volkmar $ % Note: This plugin depends on the blobs set by spm_orthviews('addblobs',...) % They should not be removed while ROI tool is active and no other blobs be % added. This restriction may be removed when using the 'alpha' property % to overlay blobs onto images. -rev = '$Revision: 2672 $'; +rev = '$Revision: 3920 $'; global st; if isempty(st) @@ -115,6 +115,7 @@ switch cmd case 'init' + % spm_ov_roi('init', volhandle, Vroi, loadasroi, xyz) spm('pointer','watch'); Vroi = spm_vol(varargin{3}); switch varargin{4} % loadasroi @@ -186,6 +187,10 @@ st.vols{volhandle}.blobs{st.vols{volhandle}.roi.hframe}.max=1.3; end; update_roi=1; + obj = findobj(0, 'Tag', sprintf('ROI_1_%d', volhandle)); + set(obj, 'Visible', 'on'); + obj = findobj(0, 'Tag', sprintf('ROI_0_%d', volhandle)); + set(obj, 'Visible', 'off'); case 'edit' switch st.vols{volhandle}.roi.tool @@ -202,6 +207,9 @@ sel(3,:)<=st.vols{volhandle}.roi.Vroi.dim(3))); update_roi = 1; + case 'connect' + spm_ov_roi('connect', volhandle) + case 'poly' % @COPYRIGHT : @@ -521,12 +529,12 @@ item7_1b = uimenu(item7, 'Label', 'Polygon tool', 'Callback', ... sprintf('%s(''context_edit'', %d,''poly'');', mfilename, volhandle), ... 'Tag',sprintf('ROI_EDIT_%d', volhandle)); + item7_1c = uimenu(item7, 'Label', 'Connected cluster', 'Callback', ... + sprintf('%s(''context_edit'', %d,''connect'');', mfilename, volhandle), ... + 'Tag',sprintf('ROI_EDIT_%d', volhandle)); item8 = uimenu(item0, 'Label', 'Threshold', 'Callback', ... sprintf('%s(''context_thresh'', %d);', mfilename, volhandle), ... 'Visible','off', 'Tag',sprintf('ROI_1_%d', volhandle)); - item9 = uimenu(item0, 'Label', 'Connected cluster', 'Callback', ... - sprintf('%s(''connect'', %d);', mfilename, volhandle), ... - 'Visible','off', 'Tag', sprintf('ROI_1_%d', volhandle)); item10 = uimenu(item0, 'Label', 'Cleanup clusters', 'Callback', ... sprintf('%s(''cleanup'', %d);', mfilename, volhandle), ... 'Visible','off', 'Tag',sprintf('ROI_1_%d', volhandle)); @@ -577,12 +585,8 @@ xyz = xSPM.XYZ; imfname = SPM.Vbeta(1).fname; end; - feval('spm_ov_roi','init',volhandle,imfname,loadasroi,xyz); - obj = findobj(0, 'Tag', sprintf('ROI_1_%d', volhandle)); - set(obj, 'Visible', 'on'); - obj = findobj(0, 'Tag', sprintf('ROI_0_%d', volhandle)); - set(obj, 'Visible', 'off'); spm_input('!DeleteInputObj',Finter); + feval('spm_ov_roi','init',volhandle,imfname,loadasroi,xyz); return; case 'context_selection' diff --git a/spm_orthviews/spm_ovhelper_3Dreg.m b/spm_orthviews/spm_ovhelper_3Dreg.m index 992f276..c5f1ceb 100644 --- a/spm_orthviews/spm_ovhelper_3Dreg.m +++ b/spm_orthviews/spm_ovhelper_3Dreg.m @@ -21,7 +21,7 @@ function spm_ovhelper_3Dreg(cmd, varargin) % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Volkmar Glauche -% $Id: spm_ovhelper_3Dreg.m 2536 2008-12-08 14:14:20Z volkmar $ +% $Id: spm_ovhelper_3Dreg.m 3756 2010-03-05 18:43:37Z guillaume $ if ishandle(varargin{1}) h = varargin{1}; @@ -74,7 +74,7 @@ function register(h,V,varargin) catch warning([mfilename ':XYZreg'],... 'Unable to register to spm_orthviews display'); - disp(lasterr); + disp(lasterror); end; return; @@ -123,6 +123,6 @@ function unregister(h,varargin) catch warning([mfilename ':XYZreg'],... 'Unable to unregister'); - disp(lasterr); + disp(lasterror); end; return; diff --git a/spm_parameter.fig b/spm_parameter.fig deleted file mode 100644 index 01b46fc..0000000 Binary files a/spm_parameter.fig and /dev/null differ diff --git a/spm_percentile.m b/spm_percentile.m new file mode 100644 index 0000000..bd12347 --- /dev/null +++ b/spm_percentile.m @@ -0,0 +1,60 @@ +function [y] = spm_percentile(data, p) +% Compute one or more percentiles from data +% FUNCTION [y] = spm_percentile(data, p) +% data - arbirarily sized input data (from which NaNs will be excluded) +% p - scalar or n-vector of percentage values (from 0 to 100) +% if not specified, p defaults to all quartiles: [0 25 50 75 100] +% +% y - scalar or n-vector of corresponding percentiles +% +% Note that percentiles are computed over all data, not along the first or +% specified dimension (unlike prctile from the MATLAB Statistics Toolbox). +% +% Example: +% spm_summarise(vols, 'all', @spm_percentile) % quartiles of images +% +% The algorithm used is that described by NIST, with x = k+d = 1+p(N-1)/100 +% http://www.itl.nist.gov/div898/handbook/prc/section2/prc252.htm +% +% This choice apparently matches Excel, but not MATLAB's prctile, though +% the differences are typically small (and are zero for min, median, max). + +% For the curious, I [Ged] chose this algorithm because it requires no +% special handling of 0 or 100, and lets 0 and 1 percentiles differ even +% with less than 100 samples. It also has the appealing (though perhaps +% totally inconsequential!) property of returning uniformly spaced values +% for uniformly spaced percentiles of uniformly spaced data. For example: +% x = 1:11; +% p = 0:25:100; +% diff([prctile(x, p(:)) spm_percentile(x, p) spm_percentile_nist(x, p)]) +% gives constant differences only for spm_percentile. + +% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging + +% Ged Ridgway +% $Id: spm_percentile.m 3960 2010-06-30 17:41:24Z ged $ + +if nargin < 2 + p = 0:25:100; +end +if any(p < 0 | p > 100) + error('Percentage values outside 0 <= p <= 100 are not allowed') +end +if all(p < 1) && any(p > 0) + warning('spm_percentile:fractions', ... + 'Percentage values are below 1, but values up to 100 are expected') +end + +p = p(:); +data = data(:); + +data = sort(data(~isnan(data))); +N = length(data); +data(end+1) = data(end); % to handle special case of 100th percentile below + +x = 1 + p * (N - 1) / 100; +k = floor(x); +d = x - k; + +y = (1 - d) .* data(k) + d .* data(k + 1); + diff --git a/spm_plot_ci.m b/spm_plot_ci.m index 3fa08cf..37ad813 100644 --- a/spm_plot_ci.m +++ b/spm_plot_ci.m @@ -1,61 +1,106 @@ function spm_plot_ci(varargin) % plots mean and conditional confidence intervals +% FORMAT spm_plot_ci(t,E,C,j,s) +% FORMAT spm_plot_ci(t,E,C,j) % FORMAT spm_plot_ci(t,E,C) % FORMAT spm_plot_ci(E,C) % % t - domain % E - expectation % C - variance or covariance +% j - indices of spm_cat(E(:)) to plot +% s - string to specify plot type %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging - + % Karl Friston -% $Id: spm_plot_ci.m 1704 2008-05-21 14:00:09Z karl $ - +% $Id: spm_plot_ci.m 3739 2010-02-26 13:12:44Z karl $ + % unpack %-------------------------------------------------------------------------- -try +if nargin == 5 t = varargin{1}; E = varargin{2}; C = varargin{3}; -catch + j = varargin{4}; + s = varargin{5}; +elseif nargin == 4 + t = varargin{1}; + E = varargin{2}; + C = varargin{3}; + j = varargin{4}; +elseif nargin == 3 + t = varargin{1}; + E = varargin{2}; + C = varargin{3}; +else E = varargin{1}; C = varargin{2}; - t = [1:size(E,2)]; end - - + +if iscell(E), E = spm_cat(E(:)); end +if ~exist('j','var'), j = 1:size(E,1); end +if ~exist('t','var'), t = 1:size(E,2); end +if ~exist('s','var'), s = ''; end + + % order and length of sequence %-------------------------------------------------------------------------- +E = E(j,:); [n N] = size(E); - + % unpack conditional covariances %-------------------------------------------------------------------------- ci = spm_invNcdf(1 - 0.05); -try +if iscell(C) for i = 1:N - c(:,i) = ci*sqrt(diag(C{i})); + c(:,i) = ci*sqrt(diag(C{i}(j,j))); + end +else + if isvector(C) + c = ci*sqrt(C(j)); + else + C = diag(C); + c = ci*sqrt(C(j)); end -catch - c = ci*sqrt(C); end - + + % conditional covariances %-------------------------------------------------------------------------- if N > 1 + + % time-series plot + %====================================================================== fill([t fliplr(t)],[full(E + c) fliplr(full(E - c))],... - [1 1 1]*.8,'EdgeColor',[1 1 1]*.8),hold on - plot(t,E) -else + [1 1 1]*.8,'EdgeColor',[1 1 1]*.5),hold on + plot(t,E,s) + +elseif n == 2 % plot in state-space - %-------------------------------------------------------------------- - try, C = C{1}; end - + %====================================================================== try, C = C{1}; end [x y] = ellipsoid(E(1),E(2),0,c(1),c(2),0,32); - fill(x',y',[1 1 1]*.8,'EdgeColor',[1 1 1]*.8),hold on + fill(x',y',[1 1 1]*.8,'EdgeColor',[1 1 1]*.5),hold on plot(E(1,1),E(2,1),'.','MarkerSize',16) - + +else + + % bar + %====================================================================== + + % conditional means + %------------------------------------------------------------------ + bar(E,'Edgecolor',[1 1 1]/2,'Facecolor',[1 1 1]*.8), hold on + axis square + box off + set(gca,'XLim',[0 n + 1]) + + % conditional variances + %------------------------------------------------------------------ + for k = 1:n + line([k k], [-1 1]*c(k) + E(k),'LineWidth',4,'Color','r'); + end end hold off drawnow diff --git a/spm_print.m b/spm_print.m index cc5e202..df7e9d5 100644 --- a/spm_print.m +++ b/spm_print.m @@ -1,64 +1,82 @@ function spm_print(job) -% Print the graphics window -%____________________________________________________________________________ +% Print the Graphics window +%__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % John Ashburner -% $Id: spm_print.m 2283 2008-10-01 14:25:09Z john $ +% $Id: spm_print.m 3933 2010-06-17 14:19:08Z guillaume $ -% Run spm_print always as job to get configured print options -if nargin == 0 +%-Run spm_print through the Batch System to get configured print options +%========================================================================== +if ~nargin spm_jobman('serial','','spm.util.print',''); return; elseif ischar(job) spm_jobman('serial','','spm.util.print',job); return; -end; - +end +%-Print the Graphics window +%========================================================================== try - mon = {'Jan','Feb','Mar','Apr','May','Jun',... - 'Jul','Aug','Sep','Oct','Nov','Dec'}; - t = clock; - nam = ['spm_' num2str(t(1)) mon{t(2)} sprintf('%.2d',t(3))]; - + %-Get output filename + %---------------------------------------------------------------------- if isempty(job.fname) - if job.opts.append, + nam = ['spm_' datestr(now,'yyyymmmdd')]; + if job.opts.append nam1 = fullfile(pwd,[nam job.opts.ext]); else - nam1 = sprintf('%s_%3d',nam,1); - for i=1:100000, + nam1=''; i=1; + while isempty(nam1) nam1 = fullfile(pwd,sprintf('%s_%.3d%s',nam,i,job.opts.ext)); - if ~exist(nam1,'file'), break; end; - end; - end; + if ~exist(nam1,'file'), break; else nam1='';i=i+1; end; + end + end else nam1 = job.fname; - end; + end + + %-Get print options + %---------------------------------------------------------------------- opts = {nam1,'-noui','-painters',job.opts.opt{:}}; - if strcmp(get(gcf,'Tag'),'Help'), + + %-Get figure handle + %---------------------------------------------------------------------- + if strcmp(get(gcf,'Tag'),'Help') fg = gcf; else fg = spm_figure('FindWin','Graphics'); - end; - print(fg,opts{:}); + end + if isempty(fg) + fprintf('\nGraphics window not found: nothing has been printed.\n'); + return; + end + + %-Print + %---------------------------------------------------------------------- + if isdeployed + deployprint(fg,opts{:}); + else + print(fg,opts{:}); + end + + %-Report + %---------------------------------------------------------------------- if isempty(strfind(nam1,filesep)) - fprintf('\nPrinting Graphics Windows to\n%s%s%s\n',pwd,filesep,nam1); + fprintf('\nPrinting Graphics Windows to\n%s%s%s\n',pwd,filesep,nam1); else - fprintf('\nPrinting Graphics Windows to\n%s\n',nam1); + fprintf('\nPrinting Graphics Windows to\n%s\n',nam1); end + +%-Report errors +%========================================================================== catch - errstr = lasterr; - tmp = [find(abs(errstr)==10),length(errstr)+1]; - str = {errstr(1:tmp(1)-1)}; - for i = 1:length(tmp)-1 - if tmp(i)+1 < tmp(i+1) - str = [str, {errstr(tmp(i)+1:tmp(i+1)-1)}]; - end - end - str = {str{:}, '','- Print options are:', opts{:},... - '','- Current directory is:',[' ',pwd],... - '',' * nothing has been printed *'}; + errstr = lasterror; + errstr = errstr.message; + str = textscan(errstr,'%s','delimiter',sprintf('\n')); + str = str{1}; + str = {str{:},'','- Print options are:', opts{:},... + '','- Current directory is:',[' ',pwd],... + '',' * nothing has been printed *'}; spm('alert!',str,'printing problem...',sqrt(-1)); -end; - +end diff --git a/spm_read_hdr.m b/spm_read_hdr.m index 3542a48..8f33280 100644 --- a/spm_read_hdr.m +++ b/spm_read_hdr.m @@ -8,7 +8,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % John Ashburner -% $Id: spm_read_hdr.m 1143 2008-02-07 19:33:33Z spm $ +% $Id: spm_read_hdr.m 3756 2010-03-05 18:43:37Z guillaume $ fid = fopen(fname,'r','native'); @@ -135,7 +135,7 @@ function out = mysetstr(in) tmp = find(in == 0); tmp = min([min(tmp) length(in)]); -out = setstr([in(1:tmp)' zeros(1,length(in)-(tmp))])'; +out = char([in(1:tmp)' zeros(1,length(in)-(tmp))])'; return; %_______________________________________________________________________ %_______________________________________________________________________ diff --git a/spm_realign.m b/spm_realign.m index 63d08c2..b9a0091 100644 --- a/spm_realign.m +++ b/spm_realign.m @@ -80,7 +80,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % John Ashburner -% $Id: spm_realign.m 1265 2008-03-28 11:45:04Z john $ +% $Id: spm_realign.m 3756 2010-03-05 18:43:37Z guillaume $ if nargin==0, return; end; @@ -503,7 +503,7 @@ function save_parameters(V) %_______________________________________________________________________ function PO = prepend(PI,pre) -[pth,nm,xt,vr] = fileparts(deblank(PI)); +[pth,nm,xt,vr] = spm_fileparts(deblank(PI)); PO = fullfile(pth,[pre nm xt vr]); return; %_______________________________________________________________________ diff --git a/spm_regions.m b/spm_regions.m index 3ae9c99..a6ff2aa 100644 --- a/spm_regions.m +++ b/spm_regions.m @@ -45,7 +45,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_regions.m 3569 2009-11-13 15:51:07Z guillaume $ +% $Id: spm_regions.m 3812 2010-04-07 16:52:05Z karl $ if nargin < 4, xY = []; end @@ -68,7 +68,7 @@ xyz = xY.xyz; catch xyz = spm_XYZreg('NearestXYZ',... - spm_XYZreg('GetCoords',hReg),xSPM.XYZmm); + spm_XYZreg('GetCoords',hReg),xSPM.XYZmm); xY.xyz = xyz; end @@ -207,12 +207,13 @@ %-Display VOI weighting and eigenvariate %========================================================================== if ~noGraph + % show position %---------------------------------------------------------------------- spm_results_ui('Clear',Fgraph); figure(Fgraph); subplot(2,2,3) - spm_dcm_display(xY,[],[],[[1 0 0];[0 1 0]]',64) + spm_dcm_display(xY) % show dynamics %---------------------------------------------------------------------- diff --git a/spm_reml.m b/spm_reml.m index 739319d..cb6bc94 100644 --- a/spm_reml.m +++ b/spm_reml.m @@ -35,7 +35,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % John Ashburner & Karl Friston -% $Id: spm_reml.m 3658 2010-01-04 12:32:42Z guillaume $ +% $Id: spm_reml.m 3791 2010-03-19 17:52:12Z karl $ % check defaults @@ -64,7 +64,7 @@ if isempty(X) X = sparse(n,0); else - X = spm_svd(X(q,:)); + X = spm_svd(X(q,:),0); end % initialise h and specify hyperpriors @@ -93,7 +93,7 @@ % positive [semi]-definite check %---------------------------------------------------------------------- for i = 1:D - if min(eig(C)) < 0 + if min(real(eig(full(C)))) < 0 % increase regularisation and re-evaluate C %-------------------------------------------------------------- @@ -116,7 +116,7 @@ iC = spm_inv(C); iCX = iC*X; if ~isempty(X) - Cq = inv(X'*iCX); + Cq = spm_inv(X'*iCX); else Cq = sparse(0); end @@ -169,7 +169,15 @@ else t = t + 1/4; end - dF = pF; + + % revert to SPD checking, if near phase-transition + %---------------------------------------------------------------------- + if abs(pF) > 1e6 + [V,h,Ph,F,Fa,Fc] = spm_reml(YY,X,Q,N,1,t - 2); + return + else + dF = pF; + end % Convergence (1% change in log-evidence) %====================================================================== @@ -192,7 +200,7 @@ %========================================================================== if ~D if min(eig(V)) < 0 - [V,h,Ph,F,Fa,Fc] = spm_reml(YY,X,Q,N,1); + [V,h,Ph,F,Fa,Fc] = spm_reml(YY,X,Q,N,1,2); return end end diff --git a/spm_reml_sc.m b/spm_reml_sc.m index c093895..f782335 100644 --- a/spm_reml_sc.m +++ b/spm_reml_sc.m @@ -1,6 +1,6 @@ -function [C,h,Ph,F,Fa,Fc,k] = spm_reml_sc(YY,X,Q,N,hE,hC,A,K) +function [C,h,Ph,F,Fa,Fc] = spm_reml_sc(YY,X,Q,N,hE,hC,V) % ReML estimation of covariance components from y*y' - proper components -% FORMAT [C,h,Ph,F,Fa,Fc,k] = spm_reml_sc(YY,X,Q,N,[hE,hC,A,K]); +% FORMAT [C,h,Ph,F,Fa,Fc] = spm_reml_sc(YY,X,Q,N,[hE,hC,V]); % % YY - (m x m) sample covariance matrix Y*Y' {Y = (m x N) data matrix} % X - (m x p) design matrix @@ -9,8 +9,7 @@ % % hE - hyperprior expectation in log-space [default = -32] % hC - hyperprior covariance in log-space [default = 256] -% A - proportional hyperpriors [default = 1, yes] -% K - number of iterations [default = 32] +% V - fixed covariance component % % C - (m x m) estimated errors = h(1)*Q{1} + h(2)*Q{2} + ... % h - (q x 1) ReML hyperparameters h @@ -21,8 +20,6 @@ % Fa - accuracy % Fc - complexity (F = Fa - Fc) % -% k - number of iterations required -% % Performs a Fisher-Scoring ascent on F to find MAP variance parameter % estimates. NB: uses weakly informative log-normal hyperpriors. % See also spm_reml for an unconstrained version that allows for negative @@ -40,26 +37,19 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_reml_sc.m 3264 2009-07-10 14:01:31Z karl $ +% $Id: spm_reml_sc.m 3813 2010-04-07 19:21:49Z karl $ -% assume proportional hyperpriors not specified -%-------------------------------------------------------------------------- -try, A; catch, A = 1; end % assume a single sample if not specified %-------------------------------------------------------------------------- try, N; catch, N = 1; end - -% default number of iterations -%-------------------------------------------------------------------------- -try, K; catch, K = 64; end - +try, V; catch, V = 0; end + % initialise h %-------------------------------------------------------------------------- n = length(Q{1}); m = length(Q); h = zeros(m,1); -dh = zeros(m,1); dFdh = zeros(m,1); dFdhh = zeros(m,m); @@ -69,32 +59,35 @@ X = sparse(n,0); R = speye(n,n); else - X = orth(full(X)); + X = spm_svd(X,0); R = speye(n,n) - X*X'; end - + +% check fixed component +%-------------------------------------------------------------------------- +if length(V) == 1 + V = V*speye(n,n); +end + % initialise and specify hyperpriors %========================================================================== % scale Q and YY %-------------------------------------------------------------------------- -if A - sY = trace(R*YY)/N/n; - YY = YY/sY; - for i = 1:m - sh(i,1) = trace(R*Q{i})/n; - Q{i} = Q{i}/sh(i); - end -else - sY = 1; - sh = 1; +sY = trace(R*YY)/(N*n); +YY = YY/sY; +V = V/sY; +for i = 1:m + sh(i,1) = trace(R*Q{i})/n; + Q{i} = Q{i}/sh(i); end + % hyperpriors %-------------------------------------------------------------------------- -try, hE = hE(:); catch, hE = -32; end -try, hP = inv(hC + speye(length(hC))/exp(16)); catch, hP = 1/256; end +try, hE = hE(:); catch, hE = -32; end +try, hP = spm_inv(hC); catch, hP = 1/256; end % check sise %-------------------------------------------------------------------------- @@ -103,7 +96,7 @@ % intialise h: so that sum(exp(h)) = 1 %-------------------------------------------------------------------------- -if any(diag(hP) > exp(16)) +if any(diag(hP) > exp(16)) h = hE; end @@ -111,16 +104,16 @@ %-------------------------------------------------------------------------- dF = Inf; as = 1:m; -ds = 1:m; -for k = 1:K +t = 4; +for k = 1:32 % compute current estimate of covariance %---------------------------------------------------------------------- - C = sparse(n,n); + C = V; for i = as C = C + Q{i}*exp(h(i)); end - iC = inv(C + speye(n,n)/exp(32)); + iC = spm_inv(C); % E-step: conditional covariance cov(B|y) {Cq} %====================================================================== @@ -173,17 +166,23 @@ % Fisher scoring: update dh = -inv(ddF/dhh)*dF/dh %---------------------------------------------------------------------- - dh = spm_dx(dFdhh(as,as),dFdh(as))*exp(-k/(K/2)); + dh = spm_dx(dFdhh(as,as),dFdh(as),{t}); h(as) = h(as) + dh; - % Convergence (1% change in log-evidence) - %====================================================================== - % bar(h);drawnow + + % predicted change in F - increase regularisation if increasing + %---------------------------------------------------------------------- + pF = dFdh(as)'*dh; + if pF > dF + t = t - 1; + else + t = t + 1/8; + end + dF = pF; % convergence %---------------------------------------------------------------------- - dF = dFdh(as)'*dh; - fprintf('%-30s: %i %30s%e\n',' ReML Iteration',k,'...',full(dF)); + fprintf('%s %-23d: %10s%e [%+3.2f]\n',' ReML Iteration',k,'...',full(dF),t); if dF < 1e-2 break else @@ -201,11 +200,11 @@ % tr(hP*inv(Ph)) - nh + tr(pP*inv(Pp)) - np (pP = 0) %---------------------------------------------------------------------- - Ft = trace(hP*inv(Ph)) - length(Ph) - length(Cq); + Ft = trace(hP/Ph) - length(Ph) - length(Cq); % complexity - KL(Ph,hP) %---------------------------------------------------------------------- - Fc = Ft/2 + e'*hP*e/2 + spm_logdet(Ph*inv(hP))/2 - N*spm_logdet(Cq)/2; + Fc = Ft/2 + e'*hP*e/2 + spm_logdet(Ph/hP)/2 - N*spm_logdet(Cq)/2; % Accuracy - ln p(Y|h) %---------------------------------------------------------------------- diff --git a/spm_render.m b/spm_render.m index dd8c973..a5152dc 100644 --- a/spm_render.m +++ b/spm_render.m @@ -33,9 +33,9 @@ function spm_render(dat,brt,rendfile) % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % John Ashburner -% $Id: spm_render.m 3289 2009-07-27 15:28:24Z guillaume $ +% $Id: spm_render.m 3975 2010-07-08 11:31:35Z guillaume $ -SVNrev = '$Rev: 3289 $'; +SVNrev = '$Rev: 3975 $'; global prevrend if ~isstruct(prevrend) @@ -199,12 +199,16 @@ function spm_render(dat,brt,rendfile) % Calculate 'depth' of values %------------------------------------------------------------------ - dep = spm_slice_vol(rend{i}.dep,spm_matrix([0 0 1])*inv(M2),d2,1); - z1 = dep(round(xyz(1,:))+round(xyz(2,:)-1)*size(dep,1)); - - if ~isfinite(brt), msk = find(xyz(3,:) < (z1+20) & xyz(3,:) > (z1-5)); - else, msk = find(xyz(3,:) < (z1+60) & xyz(3,:) > (z1-5)); end + if ~isempty(d2) + dep = spm_slice_vol(rend{i}.dep,spm_matrix([0 0 1])*inv(M2),d2,1); + z1 = dep(round(xyz(1,:))+round(xyz(2,:)-1)*size(dep,1)); + if ~isfinite(brt), msk = find(xyz(3,:) < (z1+20) & xyz(3,:) > (z1-5)); + else, msk = find(xyz(3,:) < (z1+60) & xyz(3,:) > (z1-5)); end + else + msk = []; + end + if ~isempty(msk), % Generate an image of the integral of the blob values. @@ -509,7 +513,8 @@ function mysave(obj,evd) [filename, pathname, filterindex] = uiputfile({... '*.gii' 'GIfTI files (*.gii)'; ... '*.png' 'PNG files (*.png)';... - '*.dae' 'Collada files (*.dae)'}, 'Save as'); + '*.dae' 'Collada files (*.dae)';... + '*.idtf' 'IDTF files (*.idtf)'}, 'Save as'); if ~isequal(filename,0) && ~isequal(pathname,0) [pth,nam,ext] = fileparts(filename); switch ext @@ -519,6 +524,8 @@ function mysave(obj,evd) filterindex = 2; case '.dae' filterindex = 3; + case '.idtf' + filterindex = 4; otherwise switch filterindex case 1 @@ -551,7 +558,11 @@ function mysave(obj,evd) set(get(h,'children'),'visible','off'); %a = get(h,'children'); %set(a,'Position',get(a,'Position').*[0 0 1 1]+[10 10 0 0]); - print(h, '-dpng', '-opengl', fullfile(pathname, filename)); + if isdeployed + deployprint(h, '-dpng', '-opengl', fullfile(pathname, filename)); + else + print(h, '-dpng', '-opengl', fullfile(pathname, filename)); + end close(h); set(getappdata(obj,'fig'),'renderer',r); case 3 @@ -560,6 +571,12 @@ function mysave(obj,evd) g.faces = get(getappdata(obj,'patch'),'Faces'); g.cdata = get(getappdata(obj,'patch'),'FaceVertexCData'); save(g,fullfile(pathname, filename),'collada'); + case 4 + g = gifti; + g.vertices = get(getappdata(obj,'patch'),'Vertices'); + g.faces = get(getappdata(obj,'patch'),'Faces'); + g.cdata = get(getappdata(obj,'patch'),'FaceVertexCData'); + save(g,fullfile(pathname, filename),'idtf'); end end diff --git a/spm_resels.m b/spm_resels.m index 6e643aa..1c8d018 100644 --- a/spm_resels.m +++ b/spm_resels.m @@ -25,7 +25,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston & Matthew Brett -% $Id: spm_resels.m 2783 2009-02-24 19:10:08Z guillaume $ +% $Id: spm_resels.m 3899 2010-05-25 15:36:40Z guillaume $ % Dimensionality @@ -85,10 +85,14 @@ case 'V' % Voxels %---------------------------------------------------------------------- - R = spm_Pec_resels(L,FWHM); + %R = spm_Pec_resels(L,FWHM); + V = zeros(max(L,[],2)'); + LL = mat2cell(L,ones(1,size(L,1)),size(L,2)); + V(sub2ind(size(V),LL{:})) = 1; + R = spm_resels_vol(V,FWHM)'; case 'I' % Image %---------------------------------------------------------------------- - R = spm_resels_vol(L,FWHM); - R = R' .* [1 2/3 2/3 1]; %-KJW "knobliness" correction + R = spm_resels_vol(L,FWHM)'; + end diff --git a/spm_reslice.m b/spm_reslice.m index 308130e..f46e55c 100644 --- a/spm_reslice.m +++ b/spm_reslice.m @@ -92,7 +92,7 @@ function spm_reslice(P,flags) % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % John Ashburner -% $Id: spm_reslice.m 1143 2008-02-07 19:33:33Z spm $ +% $Id: spm_reslice.m 3756 2010-03-05 18:43:37Z guillaume $ @@ -240,7 +240,7 @@ function reslice_images(P,flags) end; if write_vol, VO = P(i); - [pth,nm,xt,vr] = fileparts(deblank(P(i).fname)); + [pth,nm,xt,vr] = spm_fileparts(deblank(P(i).fname)); VO.fname = fullfile(pth,[flags.prefix nm xt vr]); VO.dim = P(1).dim(1:3); VO.dt = P(i).dt; @@ -261,7 +261,7 @@ function reslice_images(P,flags) Integral = Integral./Count; PO = P(1); PO = rmfield(PO,'pinfo'); - [pth,nm,xt,vr] = fileparts(deblank(P(1).fname)); + [pth,nm,xt,vr] = spm_fileparts(deblank(P(1).fname)); PO.fname = fullfile(pth,['mean' nm xt]); PO.pinfo = [max(max(max(Integral)))/32767 0 0]'; PO.descrip = 'spm - mean image'; diff --git a/spm_resss.m b/spm_resss.m index b69039c..58cedfc 100644 --- a/spm_resss.m +++ b/spm_resss.m @@ -6,17 +6,17 @@ % R - residual forming matrix % flags - 'm' for implicit zero masking % Vo (output) - handle structure of output image volume after modifications -% for writing +% for writing % % Note that spm_create_vol needs to be called external to this function - -% the header is not created! -%_______________________________________________________________________ +% the header is not created. +%__________________________________________________________________________ % % Residuals are computed as R*Y, where Y is the data vector read from % images mapped as Vi. The residual sum of squares image (mapped as Vo) % is written. % -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- % % For a simple linear model Y = X*B * E, with design matrix X, % (unknown) parameter vector(s) B, and data matrix Y, the least squares @@ -58,58 +58,58 @@ % R = (K - KX*inv(KX'*KX)*KX'*K) % or R = (K - KX*pinv(KX)*K) when using a pseudoinverse % -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- % % This function can also be used when the b's are images. The residuals % are then e = Y - X*b, so let Vi refer to the vector of images and % parameter estimates ([Y;b]), and then R is ([eye(n),-X]), where n is % the number of Y images. % -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- % % Don't forget to either apply any image scaling (grand mean or % proportional scaling global normalisation) to the image scalefactors, % or to combine the global scaling factors in the residual forming % matrix. -%_______________________________________________________________________ +%__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Andrew Holmes & John Ashburner -% $Id: spm_resss.m 3152 2009-05-27 10:54:49Z guillaume $ - - +% $Id: spm_resss.m 3723 2010-02-12 15:15:18Z guillaume $ %-Argument checks -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- if nargin<4, flags=''; end, if isempty(flags), flags='-'; end mask = any(flags=='m'); if nargin<3, error('insufficient arguments'); end -ni = size(R,2); %-ni = #images -if ni~=prod(size(Vi)), error('incompatible dimensions'); end -if Vo.dt(1)~=16, error('only float output images supported'), end +ni = size(R,2); %-ni = #images +if ni~=numel(Vi), error('incompatible dimensions'); end +if Vo.dt(1)~=spm_type('float32') + error('only float output images supported'); +end %-Image dimension, orientation and voxel size checks -%----------------------------------------------------------------------- -[samef msg] = spm_vol_check(Vi, Vo); -if ~samef, disp(char(msg)),error('Cannot use images'),end; +%-------------------------------------------------------------------------- +spm_check_orientations([Vi Vo]); - -%======================================================================= +%========================================================================== % - C O M P U T A T I O N -%======================================================================= -fprintf('%-14s%16s',['(',mfilename,')'],'...initialising') %-# +%========================================================================== +fprintf('%-14s%16s',['(',mfilename,')'],'...initialising'); %-# -Y = zeros([Vo.dim(1:2),ni]); %-PlaneStack data +Y = zeros([Vo.dim(1:2),ni]); %-PlaneStack data -im = logical(zeros(ni,1)); -for j=1:ni, im(j)=~spm_type(Vi(j).dt(1),'NaNrep'); end %-Images without NaNrep +im = false(ni,1); +for j=1:ni + im(j)=~spm_type(Vi(j).dt(1),'NaNrep'); %-Images without NaNrep +end %-Loop over planes computing ResSS for p=1:Vo.dim(3) fprintf('%s%16s',repmat(sprintf('\b'),1,16),... - sprintf('...plane %3d/%-3d',p,Vo.dim(3))) %-# + sprintf('...plane %3d/%-3d',p,Vo.dim(3))) %-# - M = spm_matrix([0 0 p]); %-Sampling matrix + M = spm_matrix([0 0 p]); %-Sampling matrix %-Read plane data for j=1:ni, Y(:,:,j) = spm_slice_vol(Vi(j),M,Vi(j).dim(1:2),0); end @@ -117,13 +117,13 @@ %-Apply implicit zero mask for image types without a NaNrep if mask, Y(Y(:,:,im)==0)=NaN; end - e = R*reshape(Y,prod(Vi(1).dim(1:2)),ni)'; %-residuals as DataMtx - ss = reshape(sum(e.^2,1),Vi(1).dim(1:2)); %-ResSS plane - Vo = spm_write_plane(Vo,ss,p); %-Write plane + e = R*reshape(Y,prod(Vi(1).dim(1:2)),ni)'; %-residuals as DataMtx + ss = reshape(sum(e.^2,1),Vi(1).dim(1:2)); %-ResSS plane + Vo = spm_write_plane(Vo,ss,p); %-Write plane end %-End -%----------------------------------------------------------------------- +%-------------------------------------------------------------------------- fprintf('%s%30s\n',repmat(sprintf('\b'),1,30),... - sprintf('...written %s',spm_str_manip(Vo.fname,'t'))) %-# + sprintf('...written %s',spm_str_manip(Vo.fname,'t'))) %-# diff --git a/spm_results_ui.m b/spm_results_ui.m index 037b10f..4d0f75f 100644 --- a/spm_results_ui.m +++ b/spm_results_ui.m @@ -1,16 +1,16 @@ function varargout = spm_results_ui(varargin) % User interface for SPM/PPM results: Display and analysis of regional effects -% FORMAT [hReg,xSPM,SPM] = spm_results_ui +% FORMAT [hReg,xSPM,SPM] = spm_results_ui('Setup',[xSPM]) % % hReg - handle of MIP XYZ registry object -% (see spm_XYZreg for details) +% (see spm_XYZreg.m for details) % xSPM - structure containing specific SPM, distribution & filtering details % (see spm_getSPM.m for contents) % SPM - SPM structure containing generic parameters -% (see spm_spm.m for contents... +% (see spm_spm.m for contents) % -% NB: Results section GUI CallBacks use these data structures by name, which -% therefore *must* be assigned to the correctly named variables. +% NB: Results section GUI CallBacks use these data structures by name, +% which therefore *must* be assigned to the correctly named variables. %__________________________________________________________________________ % % The SPM results section is for the interactive exploration and @@ -35,16 +35,16 @@ % drag over the images to report associated data. Clicking with % different buttons produces different results. Double-clicking % extracts the underlying data into the base workspace. -% See spm_DesRep for further details. +% See spm_DesRep.m for further details. % % The current voxel specifies the voxel, suprathreshold cluster, or % orthogonal planes (planes passing through that voxel) for subsequent % localised utilities. % -% A control panel in the interactive window enables interactive +% A control panel in the Interactive window enables interactive % exploration of the results. % -% p-value buttons: +% p-values buttons: % (i) volume - Tabulates p-values and statistics for entire volume. % - see spm_list.m % (ii) cluster - Tabulates p-values and statistics for nearest cluster @@ -52,11 +52,7 @@ % suprathreshold voxel, if it is not already at a % location with suprathreshold statistic. % - see spm_list.m -% (iii) voxel - (not implemented yet) -% - see spm_****.m -% -% p-values for VOI button: -% S.V.C - Small Volume Correction: +% (iii) S.V.C - Small Volume Correction: % Tabulates p-values corrected for a small specified % volume of interest. (Tabulation by spm_list.m) % - see spm_VOI.m @@ -66,8 +62,8 @@ % - Extracts the principal eigenvariate for small volumes % of interest; or CVA of data within a specified volume % - Data can be adjusted or not for eigenvariate summaries -% - If temporal filtering was specified (fMRI), then it is the -% filtered data that is returned. +% - If temporal filtering was specified (fMRI), then it is +% the filtered data that is returned. % - Choose a VOI of radius 0 to extract the (filtered &) % adjusted data for a single voxel. Note that this vector % will be scaled to have a 2-norm of 1. (See spm_regions.m @@ -85,7 +81,7 @@ % suprathreshold voxel, if it is not already at a % location with suprathreshold statistic. % - Additionally, returns fitted and adjusted data to the -% MatLab base workspace. +% MATLAB base workspace. % - see spm_graph.m % (ii) overlays - Popup menu: Overlays of filtered SPM on a structural image % - slices - Slices of the thresholded statistic image overlaid @@ -99,10 +95,9 @@ % - see spm_sections.m % - render - Render blobs on previously extracted cortical surface % - see spm_render.m -% (iii) write filtered - Write out thresholded SPM as image +% (iii) save - Write out thresholded SPM as image % - see spm_write_filtered.m % -% % The current cursor location can be set by editing the co-ordinate % widgets at the bottom of the interactive window. (Note that many of the % results section facilities are "linked" and can update co-ordinates. E.g. @@ -113,17 +108,12 @@ % % ---------------- % -% The MIP uses a template outline in Talairach space. Consequently for +% The MIP uses a template outline in MNI space. Consequently for % the results section to display properly the input images to the -% statistics section should either be in Talairach space (with the -% ORIGIN correctly specified), or the ORIGIN header fields should be -% set to the voxel coordinates of the anterior commissure in the input -% images. See spm_format.man ("Data Format" in the help facility) for -% further details of the Analyze image format used by SPM. +% statistics section should be in MNI space. % % Similarly, secondary images should be aligned with the input images -% used for the statistical analysis. In particular the ORIGIN must -% correspond to (0,0,0) in XYZ, the vector of locations. +% used for the statistical analysis. % % ---------------- % @@ -135,9 +125,8 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston & Andrew Holmes -% $Id: spm_results_ui.m 3656 2009-12-23 20:17:30Z karl $ +% $Id: spm_results_ui.m 3928 2010-06-16 12:09:22Z guillaume $ -SCCSid = '$Rev: 3656 $'; %========================================================================== % - FORMAT specifications for embedded CallBack functions @@ -245,10 +234,11 @@ % % FORMAT spm_results_ui('Delete',h) % deletes HandleGraphics objects, but only if they're valid, thus avoiding -% warning statements from MatLab! +% warning statements from MATLAB. %__________________________________________________________________________ - +SVNid = '$Rev: 3928 $'; + %-Condition arguments %-------------------------------------------------------------------------- if nargin == 0, Action='SetUp'; else Action=varargin{1}; end @@ -260,14 +250,10 @@ %-Initialise %---------------------------------------------------------------------- - SPMid = spm('FnBanner',mfilename,SCCSid); + SPMid = spm('FnBanner',mfilename,SVNid); [Finter,Fgraph,CmdLine] = spm('FnUIsetup','Stats: Results'); - FS = spm('FontSizes'); - - % clear satfig if it exists - %---------------------------------------------------------------------- - hSat = findobj('tag','Satellite'); - spm_figure('clear',hSat); + spm_clf('Satellite') + FS = spm('FontSizes'); %-Get thresholded xSPM data and parameters of design %====================================================================== @@ -342,7 +328,7 @@ %-Setup results GUI %---------------------------------------------------------------------- - spm_figure('Clear',Finter); + spm_clf(Finter); spm('FigName',['SPM{',xSPM.STAT,'}: Results'],Finter,CmdLine); hReg = spm_results_ui('SetupGUI',M,DIM,xSPM,Finter); @@ -351,6 +337,44 @@ hDesRepUI = spm_DesRep('DesRepUI',SPM); figure(Finter) + %-Setup contrast menu + %---------------------------------------------------------------------- + hC = uimenu(Finter,'Label','Contrasts', 'Tag','ContrastsUI'); + hC1 = uimenu(hC,'Label','New Contrast...',... + 'UserData',struct('Ic',0),... + 'Callback',{@mychgcon,xSPM}); + hC1 = uimenu(hC,'Label','Change Contrast'); + for i=1:numel(SPM.xCon) + hC2 = uimenu(hC1,'Label',[SPM.xCon(i).STAT, ': ', SPM.xCon(i).name], ... + 'UserData',struct('Ic',i),... + 'Callback',{@mychgcon,xSPM}); + if any(xSPM.Ic == i) + set(hC2,'ForegroundColor',[0 0 1],'Checked','on'); + end + end + hC1 = uimenu(hC,'Label','Previous Contrast',... + 'Accelerator','P',... + 'UserData',struct('Ic',xSPM.Ic-1),... + 'Callback',{@mychgcon,xSPM}); + if xSPM.Ic-1<1, set(hC1,'Enable','off'); end + hC1 = uimenu(hC,'Label','Next Contrast',... + 'Accelerator','N',... + 'UserData',struct('Ic',xSPM.Ic+1),... + 'Callback',{@mychgcon,xSPM}); + if xSPM.Ic+1>numel(SPM.xCon), set(hC1,'Enable','off'); end + hC1 = uimenu(hC,'Label','Significance level','Separator','on'); + xSPMtmp = xSPM; xSPMtmp.thresDesc = ''; + uimenu(hC1,'Label','Change...','UserData',struct('Ic',xSPM.Ic),... + 'Callback',{@mychgcon,xSPMtmp}); + xSPMtmp = xSPM; xSPMtmp.thresDesc = 'p<0.05 (FWE)'; + uimenu(hC1,'Label','Set to 0.05 (FWE)','UserData',struct('Ic',xSPM.Ic),... + 'Callback',{@mychgcon,xSPMtmp}); + xSPMtmp = xSPM; xSPMtmp.thresDesc = 'p<0.001 (unc.)'; + uimenu(hC1,'Label','Set to 0.001 (unc.)','UserData',struct('Ic',xSPM.Ic),... + 'Callback',{@mychgcon,xSPMtmp}); + uimenu(hC1,'Label',[xSPM.thresDesc ', k=' num2str(xSPM.k)],... + 'Enable','off','Separator','on'); + %-Setup Maximum intensity projection (MIP) & register %---------------------------------------------------------------------- hMIPax = axes('Parent',Fgraph,'Position',[0.05 0.60 0.55 0.36],'Visible','off'); @@ -474,7 +498,6 @@ Hv = get(H,'Visible'); set(hResAx,'Tag','PermRes','UserData',struct('H',H,'Hv',{Hv})) - %-Finished results setup %---------------------------------------------------------------------- varargout = {hReg,xSPM,SPM}; @@ -485,7 +508,7 @@ case 'setupgui' %-Set up results section GUI %====================================================================== % hReg = spm_results_ui('SetupGUI',M,DIM,xSPM,Finter) - if nargin < 5, Finter='Interactive'; else, Finter = varargin{5}; end + if nargin < 5, Finter='Interactive'; else Finter = varargin{5}; end if nargin < 4, error('Insufficient arguments'), end M = varargin{2}; DIM = varargin{3}; @@ -528,10 +551,9 @@ hReg = varargin{2}; DIM = varargin{3}; if nargin<4, Finter = spm_figure('FindWin','Interactive'); - else, Finter = varargin{4}; end - if nargin < 5, WS = spm('WinScale'); else, WS = varargin{5}; end - if nargin < 6, FS = spm('FontSizes'); else, FS = varargin{6}; end - PF = spm_platform('fonts'); + else Finter = varargin{4}; end + if nargin < 5, WS = spm('WinScale'); else WS = varargin{5}; end + if nargin < 6, FS = spm('FontSizes'); else FS = varargin{6}; end %-p-values %------------------------------------------------------------------ @@ -619,15 +641,12 @@ %-Not currently used %------------------------------------------------------------------ - if 0 - uicontrol(Finter,'Style','PushButton','String','Global','FontSize',FS(10),... - 'ToolTipString','perfoms a simple ANCOVA of gloabl activity',... - 'Callback','spm_global_ancova',... - 'Interruptible','on','Enable','on',... - 'Position',[015 055 100 020].*WS) + %uicontrol(Finter,'Style','PushButton','String','','FontSize',FS(10),... + % 'ToolTipString','',... + % 'Callback','',... + % 'Interruptible','on','Enable','on',... + % 'Position',[015 055 100 020].*WS) - end - %-Visualisation %------------------------------------------------------------------ uicontrol(Finter,'Style','Text','String','Display',... @@ -671,8 +690,8 @@ uicontrol(Finter,'Style','PushButton','String','save','FontSize',FS(10),... 'ToolTipString','save thresholded SPM as image',... 'Callback',['spm_write_filtered(xSPM.Z,xSPM.XYZ,xSPM.DIM,xSPM.M,',... - 'sprintf(''SPM{%c}-filtered: u = %5.3f, k = %d'',',... - 'xSPM.STAT,xSPM.u,xSPM.k));'],... + 'sprintf(''SPM{%c}-filtered: u = %5.3f, k = %d'',',... + 'xSPM.STAT,xSPM.u,xSPM.k));'],... 'Interruptible','on','Enable','on',... 'Position',[285 095 100 020].*WS) @@ -682,8 +701,8 @@ 'ToolTipString','clears results subpane',... 'FontSize',FS(9),'ForegroundColor','b',... 'Callback',['spm_results_ui(''Clear''); ',... - 'spm_input(''!DeleteInputObj''),',... - 'spm_clf(''Satellite'')'],... + 'spm_input(''!DeleteInputObj''),',... + 'spm_clf(''Satellite'')'],... 'Interruptible','on','Enable','on',... 'DeleteFcn','spm_clf(''Graphics'')',... 'Position',[285 055 035 018].*WS); @@ -692,8 +711,8 @@ 'ToolTipString','exit the results section',... 'FontSize',FS(9),'ForegroundColor','r',... 'Callback',['spm_clf(''Interactive''), spm_clf(''Graphics''),'... - 'close(spm_figure(''FindWin'',''Satellite'')),'... - 'clear'],... + 'close(spm_figure(''FindWin'',''Satellite'')),'... + 'clear'],... 'Interruptible','on','Enable','on',... 'Position',[325 055 035 018].*WS); @@ -710,14 +729,14 @@ %====================================================================== % hFxyz = spm_results_ui('DrawXYZgui',M,DIM,xSPM,xyz,Finter) if nargin<6, Finter=spm_figure('FindWin','Interactive'); - else, Finter=varargin{6}; end - if nargin < 5, xyz=[0;0;0]; else, xyz=varargin{5}; end + else Finter=varargin{6}; end + if nargin < 5, xyz=[0;0;0]; else xyz=varargin{5}; end if nargin < 4, error('Insufficient arguments'), end DIM = varargin{3}; M = varargin{2}; xyz = spm_XYZreg('RoundCoords',xyz,M,DIM); - %-Locate windows etc... + %-Font details %------------------------------------------------------------------ WS = spm('WinScale'); FS = spm('FontSizes'); @@ -834,15 +853,16 @@ spm_results_ui('UpdateSPMval',UD) end + %====================================================================== case 'updatespmval' %-Update SPM value in GUI %====================================================================== % spm_results_ui('UpdateSPMval',hFxyz) % spm_results_ui('UpdateSPMval',UD) if nargin<2, error('insufficient arguments'), end - if isstruct(varargin{2}), UD=varargin{2}; else, UD = get(varargin{2},'UserData'); end + if isstruct(varargin{2}), UD=varargin{2}; else UD = get(varargin{2},'UserData'); end i = spm_XYZreg('FindXYZ',UD.xyz,UD.XYZ); - if isempty(i), str = ''; else, str = sprintf('%6.2f',UD.Z(i)); end + if isempty(i), str = ''; else str = sprintf('%6.2f',UD.Z(i)); end set(UD.hSPM,'String',str); @@ -850,19 +870,18 @@ case 'getcoords' % Get current co-ordinates from XYZ widget %====================================================================== % xyz = spm_results_ui('GetCoords',hFxyz) - if nargin<2, hFxyz='Interactive'; else, hFxyz=varargin{2}; end + if nargin<2, hFxyz='Interactive'; else hFxyz=varargin{2}; end hFxyz = spm_results_ui('FindXYZframe',hFxyz); varargout = {getfield(get(hFxyz,'UserData'),'xyz')}; - %====================================================================== case 'setcoords' % Set co-ordinates to XYZ widget %====================================================================== % [xyz,d] = spm_results_ui('SetCoords',xyz,hFxyz,hC) - if nargin<4, hC=0; else, hC=varargin{4}; end - if nargin<3, hFxyz=spm_results_ui('FindXYZframe'); else, hFxyz=varargin{3}; end - if nargin<2, error('Set co-ords to what!'), else, xyz=varargin{2}; end + if nargin<4, hC=0; else hC=varargin{4}; end + if nargin<3, hFxyz=spm_results_ui('FindXYZframe'); else hFxyz=varargin{3}; end + if nargin<2, error('Set co-ords to what!'); else xyz=varargin{2}; end %-If this is an internal call, then don't do anything if hFxyz==hC, return, end @@ -899,8 +918,7 @@ %------------------------------------------------------------------ varargout = {xyz,d}; - - + %====================================================================== case 'findxyzframe' % Find hFxyz frame %====================================================================== @@ -913,14 +931,13 @@ if isempty(h), error('XYZ frame not found'), end if length(h)>1, error('Multiple XYZ frames found'), end varargout = {h}; - - - + + %====================================================================== case 'plotui' %-GUI for plot manipulation %====================================================================== % spm_results_ui('PlotUi',hAx) - if nargin<2, hAx=gca; else, hAx=varargin{2}; end + if nargin<2, hAx=gca; else hAx=varargin{2}; end WS = spm('WinScale'); FS = spm('FontSizes'); @@ -1023,10 +1040,8 @@ 'DeleteFcn','spm_results_ui(''Delete'',get(gcbo,''UserData''))') set(hAx,'UserData',hGraphUIbg,... 'DeleteFcn','spm_results_ui(''Delete'',get(gcbo,''UserData''))') - - - - + + %====================================================================== case 'plotuicb' %====================================================================== @@ -1067,13 +1082,10 @@ %====================================================================== - case {'clear','clearpane'} %-Clear results subpane + case 'clear' %-Clear results subpane %====================================================================== % Fgraph = spm_results_ui('Clear',F,mode) % mode 1 [default] usual, mode 0 - clear & hide Res stuff, 2 - RNP - if strcmpi(Action,'clearpane') - warning('''ClearPane'' action is grandfathered, use ''Clear'' instead') - end if nargin<3, mode=1; else, mode=varargin{3}; end if nargin<2, F='Graphics'; else, F=varargin{2}; end @@ -1123,7 +1135,7 @@ case 'launchmp' %-Launch multiplanar toolbox %====================================================================== % hMP = spm_results_ui('LaunchMP',M,DIM,hReg,hBmp) - if nargin<5, hBmp = gcbo; else, hBmp = varargin{5}; end + if nargin<5, hBmp = gcbo; else hBmp = varargin{5}; end hReg = varargin{4}; DIM = varargin{3}; M = varargin{2}; @@ -1131,7 +1143,7 @@ %-Check for existing MultiPlanar toolbox hMP = get(hBmp,'UserData'); if ishandle(hMP) - figure(spm_figure('ParentFig',hMP)) + figure(ancestor(hMP,'figure')); varargout = {hMP}; return end @@ -1147,7 +1159,6 @@ varargout = {hMP}; - %====================================================================== case 'delete' %-Delete HandleGraphics objects %====================================================================== @@ -1161,5 +1172,35 @@ %====================================================================== error('Unknown action string') - %====================================================================== end + +%========================================================================== +function mychgcon(obj,evt,xSPM) +%========================================================================== +xSPM2.swd = xSPM.swd; +try, xSPM2.units = xSPM.units; end +xSPM2.Ic = getfield(get(obj,'UserData'),'Ic'); +if isempty(xSPM2.Ic) || all(xSPM2.Ic == 0), xSPM2 = rmfield(xSPM2,'Ic'); end +xSPM2.Im = xSPM.Im; +xSPM2.pm = xSPM.pm; +xSPM2.Ex = xSPM.Ex; +xSPM2.title = ''; +if ~isempty(xSPM.thresDesc) + td = regexp(xSPM.thresDesc,'p\D?(?[\.\d]+) \((?\S+)\)','names'); + if isempty(td) + td = regexp(xSPM.thresDesc,'\w=(?[\.\d]+)','names'); + td.thresDesc = 'none'; + end + if strcmp(td.thresDesc,'unc.'), td.thresDesc = 'none'; end + xSPM2.thresDesc = td.thresDesc; + xSPM2.u = str2double(td.u); + xSPM2.k = xSPM.k; +end +hReg = spm_XYZreg('FindReg',spm_figure('GetWin','Interactive')); +xyz = spm_XYZreg('GetCoords',hReg); +[hReg,xSPM,SPM] = spm_results_ui('setup',xSPM2); +spm_XYZreg('SetCoords',xyz,hReg); +assignin('base','hReg',hReg); +assignin('base','xSPM',xSPM); +assignin('base','SPM',SPM); +figure(spm_figure('GetWin','Interactive')); diff --git a/spm_rmpath.m b/spm_rmpath.m index 4f0224e..46db594 100644 --- a/spm_rmpath.m +++ b/spm_rmpath.m @@ -17,7 +17,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Darren Gitelman & Guillaume Flandin -% $Id: spm_rmpath.m 2696 2009-02-05 20:29:48Z guillaume $ +% $Id: spm_rmpath.m 3756 2010-03-05 18:43:37Z guillaume $ varargout = {}; if ~nargin @@ -27,7 +27,7 @@ end % Recursively remove directories in the MATLAB path -p = strread(path,'%s','delimiter',pathsep); +p = textscan(path,'%s','delimiter',pathsep); p = p{1}; i = strmatch(d,p); P = p(i); p(i) = []; if ~nargin && ~isempty(P) fprintf('Removed %s paths starting from base path: "%s"\n',spm('ver','',1),d); diff --git a/spm_searchlight.m b/spm_searchlight.m new file mode 100644 index 0000000..302ef6d --- /dev/null +++ b/spm_searchlight.m @@ -0,0 +1,260 @@ +function R = spm_searchlight(SPM,searchopt,fun,varargin) +% Local mass-multivariate (c.f., searchlight) facility +% FORMAT R = spm_searchlight(SPM,searchopt,fun,varargin) +% SPM - structure with fields: +% .xY.VY - filenames char array or spm_vol struct array of images +% .VM - filename or spm_vol structure to a mask (binary) image +% Mask image can have any orientation, voxel size or data type. +% It is interpolated using nearest neighbour interpolation to +% the voxel locations of the data. +% If empty, all voxels are used. +% searchopt - searchlight options using VOI structure (xY) from spm_ROI +% .def - searchlight definition {['sphere'] 'box'} +% .spec - searchlight parameters [sphere radius {mm}] +% fun - function handle to a function that takes three input arguments: +% a [n x v] matrix (nb images x nb voxels within searchlight) +% a [3 x v] matrix of voxels location within searchlight {vox} +% a list of parameters provided in varargin +% and returns a vector value [1 x N] +% varargin - list of parameters sent to fun +% +% R - a [N x 1] cell array with each output (fun nargout) reshaped +% to a volume or directly a volume if N == 1 +% Values outside the mask are attributed NaN. +%__________________________________________________________________________ +% +% References: +% +% [1] Adaptive Analysis of fMRI Data. Friman O, Borga M, Lundberg P and +% Knutsson H. (2003) NeuroImage 19(3):837-845. +% +% [2] Information-based functional brain mapping. Kriegeskorte N, Goebel R, +% Bandettini P. (2006) PNAS 103: 3863-3868. +%__________________________________________________________________________ +% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging + +% Guillaume Flandin +% $Id: spm_searchlight.m 3900 2010-05-25 16:17:13Z guillaume $ + +spm('FnBanner',mfilename); %-# + +%-Get input images +%-------------------------------------------------------------------------- +try + VY = SPM.xY.VY; +catch + [VY, sts] = spm_select([1 Inf],'image','Select images'); + if ~sts, R = {}; return; end +end +if iscellstr(VY), VY = char(VY); end +if ~isstruct(VY) + VY = spm_vol(VY); +end + +%-Check dimensions and orientations of all images +%-------------------------------------------------------------------------- +spm_check_orientations(VY); + +%-Get mask image +%-------------------------------------------------------------------------- +try + VM = SPM.VM; +catch + [VM, sts] = spm_select([0 1],'image','Select mask'); + if ~sts, VM = []; end +end +if ~isstruct(VM) && ~isempty(VM) + VM = spm_vol(VM); +end + +%-Get space details +%-------------------------------------------------------------------------- +N = numel(VY); %-number of images +M = VY(1).mat; %-voxels to mm matrix +iM = inv(M); %-mm to voxels matrix +DIM = VY(1).dim; %-image dimensions +NDIM = prod([DIM N]); %-overall dimension +[x,y,z] = ndgrid(1:DIM(1),1:DIM(2),1:DIM(3)); +XYZ = [x(:)';y(:)';z(:)']; clear x y z %-voxel coordinates {vx} +XYZmm = M(1:3,:)*[XYZ; ones(1,size(XYZ,2))];%-voxel coordinates {mm} +XYZmm_cpy = XYZmm; %-copy without masking + +%-Strategy for reading data: memory [1] / block [2] / disk [3] +%-------------------------------------------------------------------------- +fprintf('%-40s: ','Read data'); %-# +try + ds = NDIM*8; %-data size {bytes} + MAXMEM = spm('memory'); %-max amnt usable memory + if ds > MAXMEM + YY = struct('y',[], 'i',[Inf Inf]); + blk = floor(MAXMEM/(prod([DIM(1:2) N])*8));%-blk size {# slices} + if blk == 0, error('revert to disk.'); end + Ystrtg = 2; + fprintf('%30s\n','...per block'); %-# + else + YY = spm_read_vols(VY); + Ystrtg = 1; + fprintf('%30s\n','...in memory'); %-# + end +catch + Ystrtg = 3; + fprintf('%30s\n','...from disk'); %-# +end + +%-Search volume (from mask) +%-------------------------------------------------------------------------- +fprintf('%-40s: ','Read mask'); %-# +if ~isempty(VM) + if any(DIM-VM.dim) || any(any(abs(VM.mat-M)>1e-4)) + MM = spm_get_data(VM,VM.mat\[XYZmm;ones(1,size(XYZmm,2))],false); + else + MM = spm_read_vols(VM); + end + MM = logical(MM); + XYZmm = XYZmm(:,MM(:)); + XYZ = XYZ(:,MM(:)); + fprintf('%30s\n','...done'); %-# +else + MM = true(DIM); + fprintf('%30s\n', '...none'); %-# +end + +%-Searchlight options (clique definition) +%-------------------------------------------------------------------------- +try, xY = searchopt; end +xY.xyz = [NaN NaN NaN]; +xY.rej = {'cluster','mask'}; +xY = spm_ROI(xY); + +%-Evaluated function +%-------------------------------------------------------------------------- +if ischar(fun) + fun = str2func(fun); +end +if ~isa(fun, 'function_handle') + error('''fun'' must be a function handle with two input parameters.'); +end + +%-Get local clique and perform searchlight over voxels +%========================================================================== + +%-Build local clique +%-------------------------------------------------------------------------- +fprintf('%-40s: ','Construct clique'); %-# +c = round(DIM(:)/2); +xY.xyz = M(1:3,:) * [c;1]; +[xY, clique] = spm_ROI(xY,XYZmm_cpy); +clique = round(iM(1:3,:) * [clique;ones(1,size(clique,2))]); +clique = bsxfun(@minus, clique, c); +dc = (max(clique,[],2) - min(clique,[],2) + 1)'; +fprintf('%30s\n',sprintf('%d voxels - [%dx%dx%d]',size(clique,2),dc)); %-# +if Ystrtg == 2 && blk < dc(3) + fprintf('%-40s: %30s\n','Read data','revert to disk'); %-# + Ystrtg = 3; +end + +%-Initialise progress bar +%-------------------------------------------------------------------------- +spm_figure('GetWin','Interactive'); +spm_progress_bar('Init',size(XYZ,2)); +Ibar = floor(linspace(1,size(XYZ,2), 100)); +fprintf('%-40s: %30s','Searchlight','...computing'); %-# + +SLR = []; + +%-Searchlight +%-------------------------------------------------------------------------- +for i=1:size(XYZ,2) + + %-Local clique (handle image boundaries and mask) + %---------------------------------------------------------------------- + xyz = bsxfun(@plus,XYZ(:,i),clique); + xyz(:,any(bsxfun(@lt,xyz,[1 1 1]') | bsxfun(@gt,xyz,DIM'))) = []; + idx = sub2ind(DIM,xyz(1,:),xyz(2,:),xyz(3,:)); + j = MM(idx); + idx = idx(j); + xyz = xyz(:,j); + + %-Read data + %---------------------------------------------------------------------- + if Ystrtg == 3 + Y = spm_get_data(VY,xyz,false); + elseif Ystrtg == 2 + if min(xyz(3,:)) < min(YY.i) || max(xyz(3,:)) > max(YY.i) + YY.i = min(xyz(3,:)):min(xyz(3,:))+blk; + YY.i(YY.i>DIM(3)) = []; + YY.y = zeros(DIM(1),DIM(2),numel(YY.i),N); + for v=1:N + for p=1:numel(YY.i) + YY.y(:,:,p,v) = ... + spm_slice_vol(VY(v), ... + spm_matrix([0 0 YY.i(p)]), ... + VY(v).dim(1:2),0); + end + end + end + idx = idx - (min(YY.i)-1) * prod(DIM(1:2)); + k = prod(DIM(1:2))*numel(YY.i); + idx = bsxfun(@plus, idx(:), 0:k:k*N-1); + Y = YY.y(idx)'; + elseif Ystrtg == 1 + idx = bsxfun(@plus, idx(:), 0:prod(DIM):NDIM-1); + Y = YY(idx)'; + end + + %-Call user-specified function + %---------------------------------------------------------------------- + if isempty(SLR) + t = fun(Y,xyz,varargin{:}); + SLR = zeros(size(XYZ,2),length(t)); + SLR(1,:) = t; + else + SLR(i,:) = fun(Y,xyz,varargin{:}); + end + + %-Update progress bar + %---------------------------------------------------------------------- + if any(Ibar == i), spm_progress_bar('Set', i); end + +end + +%-Clear progress bar +%-------------------------------------------------------------------------- +fprintf('%s%30s\n',repmat(sprintf('\b'),1,30),'...done'); %-# +spm_progress_bar('Clear'); + +%-Return computations - reshaped as volumes in a cell array +%-------------------------------------------------------------------------- +R = cell(size(SLR,2),1); +for i=1:size(SLR,2) + MV = NaN(DIM); + MV(sub2ind(DIM,XYZ(1,:),XYZ(2,:),XYZ(3,:))) = SLR(:,i); + R{i} = MV; +end + +%-Write images if required +%-------------------------------------------------------------------------- +fprintf('%-40s: %30s','Output images','...writing'); %-# +VO(1:size(SLR,2)) = deal(struct(... + 'fname', [],... + 'dim', DIM,... + 'dt', [spm_type('float64') spm_platform('bigend')],... + 'mat', M,... + 'pinfo', [1 0 0]',... + 'descrip', ['spm_searchlight: ' func2str(fun)])); + +for i=1:size(SLR,2) + VO(i).fname = sprintf('%s_%04d.%s', ... + 'searchlight',i,spm_get_defaults('images.format')); + VO(i).descrip = sprintf('%s (%04d)',VO(i).descrip,i); +end +for i=1:size(SLR,2) + spm_write_vol(VO(i),R{i}); +end +fprintf('%s%30s\n',repmat(sprintf('\b'),1,30),'...done'); %-# + +%-And exit +%-------------------------------------------------------------------------- +if size(SLR,2) == 1, R = R{1}; end + +fprintf('%-40s: %30s\n','Completed',spm('time')); %-# diff --git a/spm_select.m b/spm_select.m index 575a10d..86f02ae 100644 --- a/spm_select.m +++ b/spm_select.m @@ -56,7 +56,9 @@ % % FORMAT [files,dirs] = spm_select('ExtList',direc,filt,frames) % As above, but for selecting frames of 4D NIfTI files -% frames - vector of frames to select (defaults to 1, if not specified) +% frames - vector of frames to select (defaults to 1, if not +% specified). If the frame number is Inf, all frames for the +% matching images are listed. % % FORMAT [files,dirs] = spm_select('FPList',direc,filt) % FORMAT [files,dirs] = spm_select('ExtFPList',direc,filt,frames) @@ -74,9 +76,9 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % John Ashburner -% $Id: spm_select.m 3560 2009-11-12 10:02:32Z volkmar $ +% $Id: spm_select.m 3948 2010-06-25 09:48:03Z volkmar $ -if ~exist('cfg_getfile','file') && ~isdeployed +if ~isdeployed && ~exist('cfg_getfile','file') addpath(fullfile(spm('dir'),'matlabbatch')); end; % cfg_getfile expects and returns cellstr arguments for multi-line strings diff --git a/spm_session.fig b/spm_session.fig deleted file mode 100644 index c8d0f61..0000000 Binary files a/spm_session.fig and /dev/null differ diff --git a/spm_set_factorial_design.m b/spm_set_factorial_design.m deleted file mode 100644 index 6579fb3..0000000 --- a/spm_set_factorial_design.m +++ /dev/null @@ -1,140 +0,0 @@ -function [I,P,H,Hnames] = spm_set_factorial_design (job) -% Extract factorial matrix, file list and H partition of design matrix -% FORMAT [I,P,H,Hnames] = spm_set_factorial_design (job) -% -% job job structure defined in spm_config_factorial_design -% -% I Nscan x 4 factor matrix -% P List of scans -% H Component of design matrix describing conditions -% Hnames Condition names -%__________________________________________________________________________ -% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging - -% Will Penny -% $Id: spm_set_factorial_design.m 1131 2008-02-06 11:17:09Z spm $ - -% Get number of factors, names and levels -sF{1}='Repl'; % - first `factor' (for I) is always replication -Nfactors=length(job.des.fd.fact); -for i=1:Nfactors, - % For creating design matrix and nonsphericity matrix - sF{i+1}=job.des.fd.fact(i).name; -end - -% Get number of scans in each cell, get names and create file list -P=[]; -Ncells=length(job.des.fd.icell); % Assume all cells defined for now ! -switch Nfactors, - case 1, - % One-way designs - cc=1; - for i=1:job.des.fd.fact(1).levels, - % Find corresponding cell and augment file list - cell_num=0; - for c=1:Ncells, - levs=job.des.fd.icell(c).levels; - if i==levs(1) - cell_num=c; - end - end - if cell_num==0 - disp(sprintf('Error: cell %d not defined',i)); - else - P=[P;job.des.fd.icell(cell_num).scans]; - ns(cc)=length(job.des.fd.icell(cell_num).scans); - cc=cc+1; - end - end - - case 2, - % Two-way designs - cc=1; - for i=1:job.des.fd.fact(1).levels, - for j=1:job.des.fd.fact(2).levels, - % Find corresponding cell and augment file list - cell_num=0; - for c=1:Ncells, - levs=job.des.fd.icell(c).levels; - if i==levs(1) & j==levs(2) - cell_num=c; - end - end - if cell_num==0 - disp(sprintf('Error: cell %d %d not defined',i,j)); - else - P=[P;job.des.fd.icell(cell_num).scans]; - ns(cc)=length(job.des.fd.icell(cell_num).scans); - cc=cc+1; - end - end - end - case 3, - % Three-way designs - cc=1; - for i=1:job.des.fd.fact(1).levels, - for j=1:job.des.fd.fact(2).levels, - for k=1:job.des.fd.fact(3).levels, - % Find corresponding cell and augment file list - cell_num=0; - for c=1:Ncells, - levs=job.des.fd.icell(c).levels; - if i==levs(1) & j==levs(2) & k==levs(3) - cell_num=c; - end - end - if cell_num==0 - disp(sprintf('Error: cell %d %d %d not defined',i,j,k)); - else - P=[P;job.des.fd.icell(cell_num).scans]; - ns(cc)=length(job.des.fd.icell(cell_num).scans); - cc=cc+1; - end - end - end - end - otherwise, - disp(sprintf('%d-way full-factoral designs are not supported',Nfactors)); -end - -% Create scan x factor matrix I -I=[]; -switch Nfactors, - case 1, - % One-way designs - c=1; - for i=1:job.des.fd.fact(1).levels, - I=[I;[1:ns(c)]',repmat(i,[ns(c) 1]),ones(ns(c),2)]; - c=c+1; - end - % Create H partition of design matrix - [H,Hnames]=spm_DesMtx(I(:,2),'-',sF{2}); - case 2, - % Two-way designs - c=1; - for i=1:job.des.fd.fact(1).levels, - for j=1:job.des.fd.fact(2).levels, - I=[I;[1:ns(c)]',repmat([i j],[ns(c) 1]),ones(ns(c),1)]; - c=c+1; - end - end - % Create H partition of design matrix - F2names={sF{2},sF{3}}; - [H,Hnames]=spm_DesMtx(I(:,2:3),'-',F2names); - case 3, - % Three-way designs - c=1; - for i=1:job.des.fd.fact(1).levels, - for j=1:job.des.fd.fact(2).levels, - for k=1:job.des.fd.fact(3).levels, - I=[I;[1:ns(c)]',repmat([i j k],[ns(c) 1])]; - c=c+1; - end - end - end - % Create H partition of design matrix - F2names={sF{2},sF{3},sF{4}}; - [H,Hnames]=spm_DesMtx(I(:,2:4),'-',F2names); - otherwise, - disp(sprintf('%d-way full-factoral designs are not supported',Nfactors)); -end diff --git a/spm_setup_satfig.m b/spm_setup_satfig.m deleted file mode 100644 index 6a2a348..0000000 --- a/spm_setup_satfig.m +++ /dev/null @@ -1,57 +0,0 @@ -% Satellite figure for SPM Results table - -% spm_setup_satfig sets up a satellite figure to allow simultaneous display -% of table values and overlays. -%__________________________________________________________________________ -% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging - -% Darren R Gitelman -% $Id: spm_setup_satfig.m 2696 2009-02-05 20:29:48Z guillaume $ - - -global SatWindow - -FS = spm('FontSizes'); %-Scaled font sizes -PF = spm_platform('fonts'); %-Font names (for this platform) -WS = spm('WinSize','0','raw'); %-Graphics window rectangle -Rect = [WS(1)+5 WS(4)*.40 WS(3)*.49 WS(4)*.57]; - -SatWindow = figure(... - 'Tag','Satellite',... - 'Position',Rect,... - 'Resize','off',... - 'MenuBar','none',... - 'Name','SPM: Satellite Results Table',... - 'Numbertitle','off',... - 'Color','w',... - 'ColorMap',gray(64),... - 'DefaultTextColor','k',... - 'DefaultTextInterpreter','none',... - 'DefaultTextFontName',PF.helvetica,... - 'DefaultTextFontSize',FS(10),... - 'DefaultAxesColor','w',... - 'DefaultAxesXColor','k',... - 'DefaultAxesYColor','k',... - 'DefaultAxesZColor','k',... - 'DefaultAxesFontName',PF.helvetica,... - 'DefaultPatchFaceColor','k',... - 'DefaultPatchEdgeColor','k',... - 'DefaultSurfaceEdgeColor','k',... - 'DefaultLineColor','k',... - 'DefaultUicontrolFontName',PF.helvetica,... - 'DefaultUicontrolFontSize',FS(10),... - 'DefaultUicontrolInterruptible','on',... - 'PaperType','A4',... - 'PaperUnits','normalized',... - 'PaperPosition',[.0726 .0644 .854 .870],... - 'InvertHardcopy','off',... - 'Renderer',spm_get_defaults('renderer'),... - 'Visible','on',... - 'DeleteFcn',[... - 'global SatWindow,',... - 'if SatWindow,',... - 'delete(SatWindow),',... - 'SatWindow = 0;',... - 'end']); - - diff --git a/spm_slice_timing.m b/spm_slice_timing.m index e401a57..304ff5c 100644 --- a/spm_slice_timing.m +++ b/spm_slice_timing.m @@ -98,12 +98,11 @@ function spm_slice_timing(P, sliceorder, refslice, timing, prefix) % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Darren Gitelman -% $Id: spm_slice_timing.m 2696 2009-02-05 20:29:48Z guillaume $ +% $Id: spm_slice_timing.m 3756 2010-03-05 18:43:37Z guillaume $ -SPMid = spm('FnBanner',mfilename,'$Rev: 2696 $'); -[Finter,Fgraph,CmdLine] = spm('FnUIsetup','Slice timing'); -spm_help('!ContextHelp',mfilename); +SPMid = spm('FnBanner',mfilename,'$Rev: 3756 $'); +[Finter,Fgraph,CmdLine] = spm('FnUIsetup','Slice timing',0); if nargin < 1, % get number of subjects @@ -185,7 +184,7 @@ function spm_slice_timing(P, sliceorder, refslice, timing, prefix) % create new header files Vout = Vin; for k=1:nimgo, - [pth,nm,xt,vr] = fileparts(deblank(Vin(k).fname)); + [pth,nm,xt,vr] = spm_fileparts(deblank(Vin(k).fname)); Vout(k).fname = fullfile(pth,[prefix nm xt vr]); if isfield(Vout(k),'descrip'), desc = [Vout(k).descrip ' ']; diff --git a/spm_smooth.m b/spm_smooth.m index ed581d7..d6386db 100644 --- a/spm_smooth.m +++ b/spm_smooth.m @@ -1,9 +1,9 @@ function spm_smooth(P,Q,s,dtype) % 3 dimensional convolution of an image % FORMAT spm_smooth(P,Q,S,dtype) -% P - image to be smoothed -% Q - filename for smoothed image -% S - [sx sy sz] Gaussian filter width {FWHM} in mm +% P - image to be smoothed (or 3D array) +% Q - filename for smoothed image (or 3D array) +% S - [sx sy sz] Gaussian filter width {FWHM} in mm (or edges) % dtype - datatype [default: 0 == same datatype as P] %____________________________________________________________________________ % @@ -23,17 +23,17 @@ function spm_smooth(P,Q,s,dtype) % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % John Ashburner & Tom Nichols -% $Id: spm_smooth.m 2794 2009-02-26 20:07:38Z john $ +% $Id: spm_smooth.m 3976 2010-07-08 14:12:31Z karl $ %----------------------------------------------------------------------- if length(s) == 1; s = [s s s]; end -if nargin<4, dtype = 0; end; +if nargin < 4, dtype = 0; end; if ischar(P), P = spm_vol(P); end; if isstruct(P), - for i=1:numel(P), + for i= 1:numel(P), smooth1(P(i),Q,s,dtype); end else diff --git a/spm_softmax.m b/spm_softmax.m new file mode 100644 index 0000000..31b1044 --- /dev/null +++ b/spm_softmax.m @@ -0,0 +1,23 @@ +function [y] = spm_softmax(x,k) +% softmax (neural transfer) function +% FORMAT [y] = spm_softmax(x) +% +% x - vector of activity +% k - temperature or inverse sensitivity parameter (default k = 1) +% +% y = exp(k*x)/sum(exp(k*x)) + +%___________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: spm_softmax.m 3757 2010-03-08 11:41:53Z guillaume $ + +% apply +%-------------------------------------------------------------------------- +if nargin == 1 + k = 1; +end +x = x - max(x); +y = exp(k*x)/sum(exp(k*x)); + diff --git a/spm_soreduce.m b/spm_soreduce.m new file mode 100644 index 0000000..97b9f30 --- /dev/null +++ b/spm_soreduce.m @@ -0,0 +1,133 @@ +function [M0,M1,M2,L1,L2] = spm_soreduce(M,P) +% reduction of a fully nonlinear MIMO system to second-order form +% FORMAT [M0,M1,M2,L1,L2] = spm_soreduce(M,P); +% +% M - model specification structure +% Required fields: +% M.f - dx/dt = f(x,u,P,M) {function string or m-file} +% M.g - y(t) = g(x,u,P,M) {function string or m-file} +% M.x - (n x 1) = x(0) = expansion point: defaults to x = 0; +% M.u - (m x 1) = u = expansion point: defaults to u = 0; +% +% P - model parameters +% +% A second order approximation is returned where the states are +% +% q(t) = [1; x(t) - x(0)] +% +%___________________________________________________________________________ +% Returns Matrix operators for the Bilinear approximation to the MIMO +% system described by +% +% dx/dt = f(x,u,P) +% y(t) = g(x,u,P) +% +% evaluated at x(0) = x and u = 0 +% +% dq/dt = M0*q + +% u(1)*M1{1}*q + u(2)*M1{2}*q + .... +% x(1)*M2{1}*q + x(2)*M2{2}*q + .... +% y(i) = L(i,:)*q + ... +% +%-------------------------------------------------------------------------- +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: spm_soreduce.m 3696 2010-01-22 14:22:31Z karl $ + + +% set up +%========================================================================== + +% create inline functions +%-------------------------------------------------------------------------- +try + funx = fcnchk(M.f,'x','u','P','M'); +catch + M.f = inline('sparse(0,1)','x','u','P','M'); + M.n = 0; + M.x = sparse(0,0); + funx = fcnchk(M.f,'x','u','P','M'); +end + +% add observer if not specified +%-------------------------------------------------------------------------- +try + fung = fcnchk(M.g,'x','u','P','M'); +catch + M.g = inline('spm_vec(x)','x','u','P','M'); + M.l = M.n; + fung = fcnchk(M.g,'x','u','P','M'); +end + +% expansion pointt +%-------------------------------------------------------------------------- +x = M.x; +try + u = spm_vec(M.u); +catch + u = sparse(M.m,1); +end + + +% Partial derivatives for 1st order Bilinear operators +%========================================================================== + +% f(x(0),0) and derivatives +%-------------------------------------------------------------------------- +[dfdxx dfdx f0] = spm_diff(funx,x,u,P,M,[1 1]); +[dfdxu dfdx f0] = spm_diff(funx,x,u,P,M,[1 2]); +dfdu = spm_diff(funx,x,u,P,M,2); +m = length(dfdxu); % m inputs +n = length(f0); % n states + + + +% Bilinear operators +%========================================================================== + +% Bilinear operator - M0 +%-------------------------------------------------------------------------- +M0 = spm_cat({0 [] ; + (f0 - dfdx*spm_vec(x)) dfdx}); + +% Bilinear operator - M1 = dM0/du +%-------------------------------------------------------------------------- +for i = 1:m + M1{i} = spm_cat({0, [] ; + (dfdu(:,i) - dfdxu{i}*spm_vec(x)), dfdxu{i}}); +end + +% Bilinear operator - M2 = dM0/dx +%-------------------------------------------------------------------------- +for i = 1:n + M2{i} = spm_cat({0, [] ; + (dfdx(:,i) - dfdxx{i}*spm_vec(x)), dfdxx{i}}); +end + +if nargout < 4, return, end + + +% Output matrices - L1 +%========================================================================== + +% l(x(0),0) +%-------------------------------------------------------------------------- +[dgdx g0] = spm_diff(fung,x,u,P,M,1); +L1 = spm_cat({(g0 - dgdx*spm_vec(x)), dgdx}); +l = length(g0); + +if nargout < 5, return, end + +% Output matrices - L2 +%-------------------------------------------------------------------------- +dgdxx = spm_diff(fung,x,u,P,M,[1 1]); +for i = 1:l + for j = 1:n + D{i}(j,:) = dgdxx{j}(i,:); + end +end +for i = 1:l + L2{i} = spm_cat(spm_diag({0, D{i}})); +end + diff --git a/spm_spm.m b/spm_spm.m index 31a6c84..ef2ef02 100644 --- a/spm_spm.m +++ b/spm_spm.m @@ -131,17 +131,14 @@ % model contains the appropriate variance components from lower levels. % See spm_RandFX.man for further details and below. % -% Under the additional assumption that the standardised residual images +% Under the additional assumption that the standardised error fields % are non-stationary standard Gaussian random fields, results from % Random field theory can be applied to estimate the significance % statistic images (SPM's) adjusting p values for the multiple tests % at all voxels in the search volume. The parameters required for % this random field correction are the volume, and Lambda, the covariance -% matrix of partial derivatives of the standardised error fields. -% -% spm_est_smoothness estimates the variances of the partial derivatives -% in the axis directions (the diagonal of Lambda). The covariances (off -% diagonal elements of Lambda) are assumed to be zero. +% matrix of partial derivatives of the standardised error fields, estimated +% by spm_est_smoothness. % % ---------------- % @@ -284,9 +281,9 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Andrew Holmes, Jean-Baptiste Poline & Karl Friston -% $Id: spm_spm.m 3468 2009-10-15 18:59:38Z karl $ +% $Id: spm_spm.m 3960 2010-06-30 17:41:24Z ged $ -SVNid = '$Rev: 3468 $'; +SVNid = '$Rev: 3960 $'; %-Say hello %-------------------------------------------------------------------------- @@ -344,9 +341,9 @@ '^beta_.{4}\..{3}$','^con_.{4}\..{3}$','^ResI_.{4}\..{3}$',... '^ess_.{4}\..{3}$', '^spm\w{1}_.{4}\..{3}$'}; -for i=1:length(files) +for i = 1:length(files) j = spm_select('List',SPM.swd,files{i}); - for k=1:size(j,1) + for k = 1:size(j,1) spm_unlink(deblank(j(k,:))); end end @@ -392,7 +389,7 @@ %-otherwise assume i.i.d. %---------------------------------------------------------------------- xVi = struct( 'form', 'i.i.d.',... - 'V', speye(nScan,nScan)); + 'V', speye(nScan,nScan)); end @@ -404,8 +401,8 @@ V = xVi.V; str = 'parameter estimation'; - catch + % otherwise invoke ReML selecting voxels under i.i.d assumptions %---------------------------------------------------------------------- V = speye(nScan,nScan); @@ -419,15 +416,15 @@ %---------------------------------------------------------------------- W = xX.W; catch + if isfield(xVi,'V') % otherwise make W a whitening filter W*W' = inv(V) %------------------------------------------------------------------ - [u s] = spm_svd(xVi.V); - s = spdiags(1./sqrt(diag(s)),0,length(s),length(s)); - W = u*s*u'; + W = spm_sqrtm(spm_inv(xVi.V)); W = W.*(abs(W) > 1e-6); xX.W = sparse(W); + else % unless xVi.V has not been estimated - requiring 2 passes %------------------------------------------------------------------ @@ -447,6 +444,7 @@ %-If xVi.V is not defined compute Hsqr and F-threshold under i.i.d. %-------------------------------------------------------------------------- if ~isfield(xVi,'V') + Fcname = 'effects of interest'; iX0 = [SPM.xX.iB SPM.xX.iG]; xCon = spm_FcUtil('Set',Fcname,'F','iX0',iX0,xX.xKXs); @@ -471,9 +469,9 @@ VY = SPM.xY.VY; spm_check_orientations(VY); +% check files exists and try pwd +%-------------------------------------------------------------------------- for i = 1:numel(VY) - % check files exists and try pwd - %---------------------------------------------------------------------- if ~spm_existfile(VY(i).fname) [p,n,e] = fileparts(VY(i).fname); VY(i).fname = [n,e]; @@ -520,6 +518,7 @@ 'mat', M,... 'pinfo', [1 0 0]',... 'descrip', '')); + for i = 1:nBeta Vbeta(i).fname = sprintf('beta_%04d.img',i); Vbeta(i).descrip = sprintf('spm_spm:beta (%04d) - %s',i,xX.name{i}); @@ -596,7 +595,7 @@ CrPl = z:min(z+nbz-1,zdim); %-plane list zords = CrPl(:)*ones(1,xdim*ydim); %-plane Z coordinates CrBl = []; %-parameter estimates - CrResI = []; %-normalized residuals + CrResI = []; %-residuals CrResSS = []; %-residual sum of squares Q = []; %-in mask indices for this plane @@ -610,8 +609,12 @@ else str = sprintf('Planes %3d-%-3d/%-3d',z,CrPl(end),zdim); end - if z==1&&bch==1, str2=''; else str2=repmat(sprintf('\b'),1,72); end - fprintf('%s%-40s: %30s',str2,str,' '); %-# + if z == 1 && bch == 1 + str2 = ''; + else + str2 = repmat(sprintf('\b'),1,72); + end + fprintf('%s%-40s: %30s',str2,str,' '); %-construct list of voxels in this block %------------------------------------------------------------------ @@ -706,7 +709,7 @@ end % (xVi,'V') - %-if we are saving the WLS parameters + %-if we are saving the WLS (ML) parameters %-------------------------------------------------------------- if isfield(xX,'W') @@ -755,7 +758,7 @@ Vbeta(i) = spm_write_plane(Vbeta(i), jj, CrPl); end - %-Write residual images + %-Write standardised residual images %------------------------------------------------------------------ for i = 1:nSres if ~isempty(Q), jj(Q) = CrResI(i,:)./sqrt(CrResSS/erdf); end @@ -903,8 +906,7 @@ VRpv = SPM.xVol.VRpv; R = SPM.xVol.R; catch - [FWHM,VRpv] = spm_est_smoothness(VResI,VM,[nScan erdf]); - R = spm_resels_vol(VM,FWHM)'; + [FWHM,VRpv,R] = spm_est_smoothness(VResI,VM,[nScan erdf]); end %-Delete the residuals images diff --git a/spm_spm_Bayes.m b/spm_spm_Bayes.m index 30fe20e..e227ba3 100644 --- a/spm_spm_Bayes.m +++ b/spm_spm_Bayes.m @@ -68,7 +68,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_spm_Bayes.m 3310 2009-08-07 13:33:41Z guillaume $ +% $Id: spm_spm_Bayes.m 3692 2010-01-21 21:43:31Z guillaume $ %-Say hello @@ -236,8 +236,7 @@ %-maxMem is the maximum amount of data processed at a time (bytes) %----------------------------------------------------------------------- -global defaults -MAXMEM = defaults.stats.maxmem; +MAXMEM = spm_get_defaults('stats.maxmem'); blksz = ceil(MAXMEM/8/nScan); SHp = 0; % sum of hyperparameters for z = 1:zdim diff --git a/spm_squeeze.m b/spm_squeeze.m new file mode 100644 index 0000000..226fdca --- /dev/null +++ b/spm_squeeze.m @@ -0,0 +1,22 @@ +function B = spm_squeeze(A, dim) +% version of squeeze with the possibility to select the dimensions to remove +% FORMAT B = spm_squeeze(A, dim) +% +%__________________________________________________________________________ +% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging + +% Vladimir Litvak +% $Id: spm_squeeze.m 3722 2010-02-11 16:23:28Z vladimir $ + +if nargin == 1 + B = squeeze(A); +else + siz = size(A); + dim = intersect(dim, find(siz == 1)); + if ~isempty(dim) + siz(dim) = []; + B = reshape(A, siz); + else + B = A; + end +end diff --git a/spm_str_manip.m b/spm_str_manip.m index ac88a5a..922237a 100644 --- a/spm_str_manip.m +++ b/spm_str_manip.m @@ -1,10 +1,12 @@ function [strout,R2] = spm_str_manip(strin,options) % miscellaneous string manipulation options % FORMAT string_out = spm_str_manip(string_in,options) -% string_in - input string, string matrix, or cell array of strings -% string_out - output sring, string matrix, or cell array of strings -% options - a string of options flags -%_______________________________________________________________________ +% string_in - input string, string matrix, or cell array of strings +% options - a string of options flags, see below + +% string_out - output string, string matrix, or cell array of strings +% R2 - extra output for 'c' and 'C' options +%__________________________________________________________________________ % Each of the options is performed from left to right. % The options are: % 'r' - remove trailing suffix @@ -13,8 +15,8 @@ % 'e' - remove everything except the suffix % 'h' - remove trailing pathname component % 'H' - always remove trailing pathname component -% (returns '.' for straight filenames like 'test.img' ) -% (wheras 'h' option mimics csh & returns 'test.img' ) +% (returns '.' for straight filenames like 'test.img') +% (wheras 'h' option mimics csh & returns 'test.img' ) % 't' - remove leading pathname component % ['f' num2str(n)] - remove all except first n characters % ['l' num2str(n)] - remove all except last n characters @@ -28,6 +30,7 @@ % produce '../dir2/file.img'. % 'v' - delete non valid filename characters % Valid are '.a..zA..Z01..9_-: ' & filesep +% 'x' - escape TeX special characters % 'p' - canonicalise pathname (see spm_select('CPath',strin)) % 'c' - remove leading components common to all strings % returns leading component as a second output argument @@ -39,11 +42,11 @@ % .e - end string (E.g. '.img') % 'd' - deblank - this is always done! % -%_______________________________________________________________________ +%__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % John Ashburner -% $Id: spm_str_manip.m 1143 2008-02-07 19:33:33Z spm $ +% $Id: spm_str_manip.m 3950 2010-06-28 10:44:02Z guillaume $ if nargin<2, options=''; end @@ -59,11 +62,11 @@ o = 2; % Read in optional numeric argument c - %--------------------------------------------------------------- + %====================================================================== opt = options(2:length(options)); c = 0; - if (~isempty(opt)), b = opt(1); else, b = '-'; end - while(b >= '0'+0 & b <= '9'+0) + if (~isempty(opt)), b = opt(1); else b = '-'; end + while (b >= '0'+0 && b <= '9'+0) c = c * 10 + opt(1)-'0'; opt = opt(2:length(opt)); if (isempty(opt)) @@ -76,18 +79,21 @@ %-Process option - string by string processing options - %--------------------------------------------------------------- - for i=1:prod(size(strout)) + %====================================================================== + for i=1:numel(strout) str = deblank(strout{i}); switch options(1) - case 'r' % Remove a trailing suffix of the form `.xxx', - % leaving the basename. + case 'r' + %-Remove a trailing suffix of the form `.xxx', leaving the basename + %------------------------------------------------------------------ d1 = max([find(str == sep) 0]); d2 = max([find(str == '.') 0]); if (d2>d1), str = str(1:(d2-1)); end - case 'e' % Remove all but the suffix. + case 'e' + %-Remove all but the suffix + %------------------------------------------------------------------ d1 = max([find(str == sep) 0]); d2 = max([find(str == '.') 0]); if (d2>d1) @@ -96,15 +102,17 @@ str = ''; end - case 'h' % Remove a trailing pathname component, - % leaving the head. + case 'h' + %-Remove a trailing pathname component, leaving the head + %------------------------------------------------------------------ d1 = max([find(str == sep) 0]); if (d1>0) str = str(1:(d1-1)); end - case 'H' % Remove a trailing pathname component, - % leaving the head. + case 'H' + %-Remove a trailing pathname component, leaving the head + %------------------------------------------------------------------ d1 = max([find(str == sep) 0]); if (d1>0) str = str(1:(d1-1)); @@ -112,27 +120,36 @@ str = '.'; end - case 't' % Remove all leading pathname components, - % leaving the tail. + case 't' + %-Remove all leading pathname components, leaving the tail + %------------------------------------------------------------------ d1 = max([find(str == sep) 0]); if (d1>0) str = str((d1+1):length(str)); end - case 'f' % First few characters + case 'f' + %-First few characters + %------------------------------------------------------------------ str = str(1:min([length(str) c])); - case 'l' % Last few characters + case 'l' + %-Last few characters + %------------------------------------------------------------------ l = length(str); str = str(l-min([length(str) c])+1:l); - case 'k' % Last few characters + case 'k' + %-Last few characters, prefixed with '..' + %------------------------------------------------------------------ l = length(str); if (l>c) str = ['..' str(l-c+2:l)]; end - case 'a' % Last few characters + case 'a' + %-Last few characters + %------------------------------------------------------------------ m1 = find(str == sep); l = length(str); if (c < l) @@ -144,61 +161,77 @@ end end - case 's' % Strip off '.img', '.hdr' or '.mat' suffixes + case 's' + %-Strip off '.img', '.hdr', '.nii' or '.mat' suffixes + %------------------------------------------------------------------ l = length(str); if (l > 4) - if (strcmp(str((l-3):l),'.img') | ... - strcmp(str((l-3):l),'.hdr') | ... - strcmp(str((l-3):l),'.nii') | ... - strcmp(str((l-3):l),'.mat')) + if ismember(str((l-3):l),{'.img','.hdr','.nii','.mat'}) str = spm_str_manip(str, 'r'); end end case 'v' - tmp = find(... - ( str>='a' & str<='z' ) | ... - ( str>='A' & str<='Z' ) | ... - ( str>='0' & str<='9' ) | ... - str==',' | ... - str=='-' | str=='_' | ... - str=='.' | str==' ' | ... - str=='(' | str==')' | ... - str==sep | str==':'); + %-Delete non valid filename characters + %------------------------------------------------------------------ + tmp = ( str>='a' & str<='z' ) | ... + ( str>='A' & str<='Z' ) | ... + ( str>='0' & str<='9' ) | ... + str==',' | ... + str=='-' | str=='_' | ... + str=='.' | str==' ' | ... + str=='(' | str==')' | ... + str==sep | str==':' ; str = str(tmp); + case 'x' + %-Escape TeX special characters + %------------------------------------------------------------------ + str = strrep(str,'\','\\'); + str = strrep(str,'^','\^'); str = strrep(str,'_','\_'); + str = strrep(str,'{','\{'); str = strrep(str,'}','\}'); + case 'p' + %-Canonicalise pathname + %------------------------------------------------------------------ str = strvcat(spm_select('CPath',cellstr(str))); case {'c','C','d'} - %-Allow these options (implemented below) + %-Allow these options (implemented below) + %------------------------------------------------------------------ + otherwise + %------------------------------------------------------------------ warning(['ignoring unrecognised option: ',options(1)]) - end % (case) + end strout{i} = str; end %-Process option - all strings options - %--------------------------------------------------------------- - if options(1)=='c' % Remove common path components + %====================================================================== + if options(1)=='c' + %-Remove common path components + %---------------------------------------------------------------------- if length(strout)>1 tmp = size(strout); strout = char(strout(:)); msk = diff(strout+0)~=0; - d1 = min(find(sum(msk,1))); + d1 = find(sum(msk,1), 1 ); d1 = max([find(strout(1,1:d1) == sep) 0]); R2 = strout(1,1:d1); strout = reshape(cellstr(strout(:,d1+1:end)),tmp); end - elseif options(1)=='C' %-Common path components + elseif options(1)=='C' + %-Common path components + %---------------------------------------------------------------------- if length(strout)>1 tmp = size(strout); str = char(strout); msk = diff(str+0)~=0; - d1 = min(find(sum(msk,1))); + d1 = find(sum(msk,1), 1 ); if isempty(d1) R2.s = str(1,:); R2.e = ''; @@ -210,7 +243,7 @@ for i=1:length(str), str{i}=fliplr(str{i}); end str = char(str); msk = diff(str+0)~=0; - d1 = max([1,min(find(sum(msk,1)))]); + d1 = max([1,find(sum(msk,1), 1 )]); R2.e = fliplr(str(1,1:d1-1)); str = cellstr(str(:,d1:end)); for i=1:length(str), str{i}=fliplr(str{i}); end @@ -222,7 +255,9 @@ end bSStrOut = 1; - elseif options(1)=='d' % Deblanking is always done by cellstr above + elseif options(1)=='d' + % Deblanking is always done by cellstr above + %---------------------------------------------------------------------- % strout = deblank(strout); end diff --git a/spm_study.fig b/spm_study.fig deleted file mode 100644 index cd81e63..0000000 Binary files a/spm_study.fig and /dev/null differ diff --git a/spm_summarise.m b/spm_summarise.m new file mode 100644 index 0000000..2f1f29f --- /dev/null +++ b/spm_summarise.m @@ -0,0 +1,87 @@ +function [Y, xY] = spm_summarise(V,xY,fhandle,keepNaNs) +% Summarise data within a Region of Interest +% FUNCTION [Y, xY] = spm_summarise(V,xY,fhandle) +% V - [1 x n] vector of mapped image volumes to read (from spm_vol) +% xY - VOI structure (from spm_ROI) +% Or a VOI_*.mat (from spm_regions) or a mask image filename +% Or the keyword 'all' to summarise all voxels in the images +% Or a [3 x m] matrix of voxel coordinates {mm} +% fhandle - function handle to be applied on image data within VOI +% Must transform a [1 x m] array into a [1 x p] array +% Default is Identity (returns raw data, vectorised intro rows) +% +% Y - [n x p] data summary +% xY - (updated) VOI structure +%__________________________________________________________________________ +% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging + +% Guillaume Flandin, Ged Ridgway +% $Id: spm_summarise.m 3960 2010-06-30 17:41:24Z ged $ + +%-Argument checks +%-------------------------------------------------------------------------- +if nargin < 1 || isempty(V) + [V ok] = spm_select([1 Inf], 'image', 'Specify Images'); + if ~ok, error('Must select 1 or more images'), end +end +if ischar(V), V = spm_vol(V); end +spm_check_orientations(V); + +if nargin < 2 || isempty(xY), xY = struct; end +if ischar(xY) + if strcmpi(xY, 'all') + xY = struct('def', 'all'); + elseif any(regexpi(xY, '\.mat$')) + try + load(xY,'xY'); % VOI_*.mat file. Warns if .mat has no xY ... + xY = rmfield(xY,'XYZmm'); % ... error if .mat has no xY + catch + xY = struct; % GUI specification in spm_ROI + end + else % assume mask image filename + xY = struct('def','mask', 'spec',xY); + end +elseif isnumeric(xY) && any(size(xY, 1) == [3 4]) + xY = struct('XYZmm', xY(1:3, :)); +elseif ~isstruct(xY) + error('Incorrect xY specified') +end +if ~isfield(xY,'XYZmm'), [xY xY.XYZmm] = spm_ROI(xY,V(1)); end + +if nargin < 3 || isempty(fhandle), fhandle = @(x) x; end +if ischar(fhandle) && strcmp(fhandle,'summl') + vsz = abs(det(V(1).mat)); % voxel size in mm^3 + fhandle = @(x) sum(x) * vsz / 1000; +end +if ischar(fhandle), fhandle = str2func(fhandle); end + +% Undocumented option in case anyone wants to keep (e.g. to check for) NaNs +if nargin < 4, keepNaNs = false; end +if keepNaNs + dropNaNs = @(x) x; +else + dropNaNs = @(x) x(~isnan(x)); +end + +%-Summarise data +%-------------------------------------------------------------------------- +XYZ = round(V(1).mat \ [xY.XYZmm; ones(1, size(xY.XYZmm, 2))]); + +% Run on first volume to determine p, and transpose if column vector +Y = fhandle(dropNaNs(spm_get_data(V(1), XYZ))); +if ndims(Y) > 2 + error('Function must return a [1 x p] array') +elseif size(Y, 1) ~= 1 + if size(Y, 2) == 1 + Y = Y'; + else + error('Function returned a [%d x %d] array instead of [1 x p]', ... + size(Y, 1), size(Y, 2)) + end +end + +% Preallocate space and then run on remaining volumes +Y(2:numel(V), :) = 0; +for i = 2:numel(V) + Y(i, :) = fhandle(dropNaNs(spm_get_data(V(i), XYZ))); +end diff --git a/spm_trial.fig b/spm_trial.fig deleted file mode 100644 index ef54b9d..0000000 Binary files a/spm_trial.fig and /dev/null differ diff --git a/spm_update.m b/spm_update.m new file mode 100644 index 0000000..4b597fc --- /dev/null +++ b/spm_update.m @@ -0,0 +1,69 @@ +function spm_update(update) +% Check (and install) SPM8 updates from the FIL FTP server +% FORMAT spm_update +% This function will connect itself to the FIL FTP server, compare the +% version number of the updates with the one of the SPM installation +% currently in the MATLAB path and will display the outcome. +% +% FORMAT spm_update(update) +% Invoking this function with any input parameter will do the same as +% above but will also attempt to download and install the updates. +%__________________________________________________________________________ +% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging + +% Guillaume Flandin +% $Id: spm_update.m 4009 2010-07-21 13:36:20Z guillaume $ + +url = 'ftp://ftp.fil.ion.ucl.ac.uk/spm/spm8_updates/'; + +if ~nargin + update = false; +else + update = true; +end + +[s,sts] = urlread(url); +if ~sts, error('Cannot access the FIL FTP server.'); end +n = regexp(s,'spm8_updates_r(\d.*?)\.zip','tokens','once'); +if isempty(n) + fprintf(' There are no updates available yet.\n'); + return; +else + n = str2double(n{1}); +end + +try + [v,r] = spm('Ver','',1); r = str2double(r); +catch + error('SPM cannot be found in MATLAB path.'); +end +if ~strcmp(v,'SPM8'), error('Your SPM version is %s and not SPM8',v); end +rs = [3042 3164 3408 3684 4010]; +if isnan(r), r = rs(1); end +if floor(r) == 8 + try + r = rs(round((r-floor(r))*10)+1); + catch + r = rs(end); + end +end + +if n > r + fprintf(' A new version of SPM is available on:\n'); + fprintf(' %s\n',url); + fprintf(' (Your version: %d - New version: %d)\n',r,n); + + if update + d = spm('Dir'); + delete(get(0,'Children')); spm('clean'); evalc('spm_rmpath'); + try + s = unzip([url sprintf('spm8_updates_r%d.zip',n)], d); + fprintf(' %d files have been updated.\n',numel(s)); + catch + fprintf(' Update failed: check file permissions.\n'); + end + addpath(d); + end +else + fprintf(' Your version of SPM is up to date.\n'); +end diff --git a/spm_uw_apply.m b/spm_uw_apply.m index 686af13..c07f2d6 100644 --- a/spm_uw_apply.m +++ b/spm_uw_apply.m @@ -120,12 +120,10 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Jesper Andersson -% $Id: spm_uw_apply.m 1358 2008-04-10 11:20:26Z guillaume $ +% $Id: spm_uw_apply.m 3756 2010-03-05 18:43:37Z guillaume $ tiny = 5e-2; -defaults = spm('GetGlobal','defaults'); - def_flags = struct('mask', 1,... 'mean', 1,... 'interp', 4,... @@ -140,7 +138,8 @@ % Replace hardcoded defaults with spm_defaults % when exist and defined. % -if exist('defaults','var') && isfield(defaults,'realign') && isfield(defaults.realign,'write') +defaults = spm_get_defaults; +if isfield(defaults,'realign') && isfield(defaults.realign,'write') wd = defaults.realign.write; if isfield(wd,'interp'), def_flags.interp = wd.interp; end if isfield(wd,'wrap'), def_flags.wrap = wd.wrap; end @@ -392,7 +391,7 @@ %_______________________________________________________________________ function PO = prepend(PI,pre) -[pth,nm,xt,vr] = fileparts(deblank(PI)); +[pth,nm,xt,vr] = spm_fileparts(deblank(PI)); PO = fullfile(pth,[pre nm xt vr]); return; %_______________________________________________________________________ diff --git a/spm_uw_estimate.m b/spm_uw_estimate.m index e3d36c2..f4e598d 100644 --- a/spm_uw_estimate.m +++ b/spm_uw_estimate.m @@ -169,10 +169,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Jesper Andersson -% $Id: spm_uw_estimate.m 2696 2009-02-05 20:29:48Z guillaume $ - - -global defaults +% $Id: spm_uw_estimate.m 3770 2010-03-10 10:36:55Z chloe $ if nargin < 1 | isempty(P), P = spm_select(Inf,'image'); end if ~isstruct(P), P = spm_vol(P); end @@ -200,7 +197,8 @@ % Replace hardcoded defaults with spm_defaults % when exist and defined. % -if exist('defaults','var') & isfield(defaults,'unwarp') & isfield(defaults.unwarp,'estimate') +defaults = spm_get_defaults; +if isfield(defaults,'unwarp') && isfield(defaults.unwarp,'estimate') ud = defaults.unwarp.estimate; if isfield(ud,'basfcn'), defpar.order = ud.basfcn; end if isfield(ud,'regorder'), defpar.regorder = ud.regorder; end @@ -901,9 +899,9 @@ function cleanup(P,ds) % if isfield(ds,'sfP') && ~isempty(ds.sfP) txyz = xyz * (ds.sfP.mat\ds.M)'; - tmsk = (txyz(:,1)>=1 & txyz(:,1)<=P(1).dim(1) &... - txyz(:,2)>=1 & txyz(:,2)<=P(1).dim(2) &... - txyz(:,3)>=1 & txyz(:,3)<=P(1).dim(3)); + tmsk = (txyz(:,1)>=1 & txyz(:,1)<=ds.sfP.dim(1) &... + txyz(:,2)>=1 & txyz(:,2)<=ds.sfP.dim(2) &... + txyz(:,3)>=1 & txyz(:,3)<=ds.sfP.dim(3)); msk = msk & tmsk; end msk = erode_msk(msk,dm); diff --git a/spm_vol_check.m b/spm_vol_check.m deleted file mode 100644 index ba04451..0000000 --- a/spm_vol_check.m +++ /dev/null @@ -1,70 +0,0 @@ -function [samef, msg, chgf] = spm_vol_check(varargin) -% Check spm_vol structs are in same space -% FORMAT [samef, msg, chgf] = spm_vol_check(V1, V2, ...) -% -% V1, V2, etc - arrays of spm_vol structs -% -% samef - true if images have same dims, mats -% msg - cell array containing helpful message if not -% chgf - logical Nx2 array of difference flags -%_______________________________________________________________________ -% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging - -% Matthew Brett -% $Id: spm_vol_check.m 2696 2009-02-05 20:29:48Z guillaume $ - - -[fnames samef msg] = deal({},1,{}); - -if nargin < 1, - return; -end - -for i = 1:numel(varargin), - vols = varargin{i}; - if ~isempty(vols), - if i == 1, - dims = cat(3,vols(:).dim); - mats = cat(3,vols(:).mat); - else - dims = cat(3,dims,vols(:).dim); - mats = cat(3,mats,vols(:).mat); - end - fnames = {fnames{:}, vols(:).fname}; - end -end - -nimgs = size(dims, 3); -if nimgs < 2, - return; -end - -labs = {'dimensions', 'orientation & voxel size'}; - -dimf = any(diff(dims(:,1:3,:),1,3)); -matf = any(any(diff(mats,1,3))); -chgf = logical([dimf(:) matf(:)]); -chgi = find(any(chgf, 2)); -if ~isempty(chgi), - samef = 0; - e1 = chgi(1); - msg = {['Images don''t all have the same ' ... - sepcat(labs(chgf(e1,:)),', ')],... - 'First difference between image pair:',... - fnames{e1},... - fnames{e1+1}}; -end - -function s = sepcat(strs, sep) -% returns cell array of strings as one char string, separated by sep -if nargin < 2, - sep = ';'; -end -if isempty(strs), - s = ''; - return -end -strs = strs(:)'; -strs = [strs; repmat({sep}, 1, length(strs))]; -s = [strs{1:end-1}]; - diff --git a/src/Makefile.var b/src/Makefile.var index f836789..6886805 100644 --- a/src/Makefile.var +++ b/src/Makefile.var @@ -2,7 +2,7 @@ # # Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging # -# $Id: Makefile.var 3297 2009-07-29 17:20:19Z guillaume $ +# $Id: Makefile.var 3775 2010-03-11 19:26:20Z guillaume $ # ############################################################################### # @@ -22,6 +22,8 @@ # http://en.wikibooks.org/wiki/SPM/Installation_on_64bit_Windows # MinGW: http://www.mingw.org/ # Gnumex: http://gnumex.sourceforge.net/ +# MinGW-w64: http://mingw-w64.sourceforge.net/ +# WPG System64: http://www.horizonchess.com/wpg64/ # * MacOS: # http://en.wikibooks.org/wiki/SPM/Installation_on_Mac_OS # http://en.wikibooks.org/wiki/SPM/Installation_on_Mac_OS_(Intel) @@ -93,6 +95,13 @@ ifndef SUF MEXEND = " MOSUF = obj endif + ifeq (WPGSystem64,$(word 2,$(subst _, ,$(PLATFORM)))) + SUF = mexw64 + MEXBIN = cmd /c "mex.bat + MEXOPTS = -O -DSPM_WIN32 + MEXEND = " + MOSUF = obj + endif ifeq (win64,$(PLATFORM)) SUF = mexw64 MEXBIN = cmd /c "mex.bat diff --git a/toolbox/Beamforming/spm_eeg_ft_beamformer_freq.m b/toolbox/Beamforming/spm_eeg_ft_beamformer_freq.m index 8b8bb7e..96c9fff 100644 --- a/toolbox/Beamforming/spm_eeg_ft_beamformer_freq.m +++ b/toolbox/Beamforming/spm_eeg_ft_beamformer_freq.m @@ -10,7 +10,7 @@ function spm_eeg_ft_beamformer_freq(S) % Copyright (C) 2009 Wellcome Trust Centre for Neuroimaging % Vladimir Litvak -% $Id: spm_eeg_ft_beamformer_freq.m 3652 2009-12-18 18:54:43Z guillaume $ +% $Id: spm_eeg_ft_beamformer_freq.m 3949 2010-06-25 14:33:57Z vladimir $ [Finter,Fgraph] = spm('FnUIsetup','Fieldtrip beamformer for power', 0); %% @@ -74,7 +74,7 @@ function spm_eeg_ft_beamformer_freq(S) if strncmp(modality, D.inv{D.val}.forward(m).modality, 3) vol = D.inv{D.val}.forward(m).vol; if isa(vol, 'char') - vol = fileio_read_vol(vol); + vol = ft_read_vol(vol); end datareg = D.inv{D.val}.datareg(m); end @@ -91,8 +91,8 @@ function spm_eeg_ft_beamformer_freq(S) [U, L, V] = svd(M1(1:3, 1:3)); M1(1:3,1:3) =U*V'; -vol = forwinv_transform_vol(M1, vol); -sens = forwinv_transform_sens(M1, sens); +vol = ft_transform_vol(M1, vol); +sens = ft_transform_sens(M1, sens); %% ============ Select the data and convert to Fieldtrip struct @@ -299,13 +299,18 @@ function spm_eeg_ft_beamformer_freq(S) end end + + if isfield(S, 'normalize') && S.normalize + pow = pow./mean(pow(~isnan(pow))); + end + csource = source{1}; csource.pow = (pow*S.contrast(:)); cfg1 = []; cfg1.sourceunits = 'mm'; cfg1.parameter = 'pow'; - cfg.downsample = 1; + cfg1.downsample = 1; sourceint = ft_sourceinterpolate(cfg1, csource, sMRI); %% @@ -356,7 +361,11 @@ function spm_eeg_ft_beamformer_freq(S) for j = 1:length(ind) pow(:, j) = source.trial(ind(j)).pow(:); end - + + if isfield(S, 'normalize') && S.normalize + pow = pow./mean(pow(~isnan(pow))); + end + source.pow = (pow*S.contrast(:)); sourceint = ft_sourceinterpolate(cfg, source, sMRI); diff --git a/toolbox/Beamforming/spm_eeg_ft_beamformer_gui.m b/toolbox/Beamforming/spm_eeg_ft_beamformer_gui.m index 13dfc4c..b37aef2 100644 --- a/toolbox/Beamforming/spm_eeg_ft_beamformer_gui.m +++ b/toolbox/Beamforming/spm_eeg_ft_beamformer_gui.m @@ -10,7 +10,7 @@ % Copyright (C) 2009 Wellcome Trust Centre for Neuroimaging % Gareth Barnes -% $Id: spm_eeg_ft_beamformer_gui.m 3652 2009-12-18 18:54:43Z guillaume $ +% $Id: spm_eeg_ft_beamformer_gui.m 3971 2010-07-06 09:53:38Z gareth $ [Finter,Fgraph] = spm('FnUIsetup','LCMV beamformer for power', 0); %% @@ -64,24 +64,24 @@ -for m = 1:numel(D.inv{D.val}.forward) - if strncmp(modality, D.inv{D.val}.forward(m).modality, 3) - vol = D.inv{D.val}.forward(m).vol; - if isa(vol, 'char') - vol = fileio_read_vol(vol); - end - datareg = D.inv{D.val}.datareg(m); +[ok, D] = check(D, 'sensfid'); + +if ~ok + if check(D, 'basic') + errordlg(['The requested file is not ready for source reconstruction.'... + 'Use prep to specify sensors and fiducials.']); + else + errordlg('The meeg file is corrupt or incomplete'); end + return end - try - vol = D.inv{D.val}.forward.vol; - datareg = D.inv{D.val}.datareg; - catch - D = spm_eeg_inv_mesh_ui(D, D.val, [], 1); - D = spm_eeg_inv_datareg_ui(D, D.val); - datareg = D.inv{D.val}.datareg; - end + + if ~isfield(D,'inv') + errordlg('Need to set up a forward model before you start'); + return; + end; + clb = D.condlist; @@ -146,13 +146,32 @@ Nconditions=numel(S.timewindows); +type1ind=find(trialtypes==1); +type2ind=find(trialtypes==2); + +if 2*abs((length(type1ind)-length(type2ind)))./(length(type1ind)+length(type2ind))>0.1, + + balance = spm_input('trial numbers diffe (>10%). Randomly resample ?','+1', 'yes|no', [1, 0]); + minlen=min(length(type1ind),length(type2ind)); + m1=randperm(length(type1ind)); + type1ind=sort(type1ind(m1(1:minlen))); + m1=randperm(length(type2ind)); + type2ind=sort(type2ind(m1(1:minlen))); + disp(sprintf('Now both conditions have %d trials',minlen)); +end; + + + %% Set up design matrix for a t test S.design.X=size(latencies,1); -S.design.X(find(trialtypes==1),1)=1; -S.design.X(find(trialtypes==2),1)=-1; +S.design.X(type1ind,1)=1; +S.design.X(type2ind,2)=1; +S.design.X(:,3)=1; + + - contrast=[1]; + contrast=[1 -1 0]; S.design.contrast=contrast; S.design.Xwindowduration=duration/1000; %% in seconds S.design.Xtrials=triallist'; % correspond to the trials diff --git a/toolbox/Beamforming/spm_eeg_ft_beamformer_lcmv.m b/toolbox/Beamforming/spm_eeg_ft_beamformer_lcmv.m index f8abd65..b86d599 100644 --- a/toolbox/Beamforming/spm_eeg_ft_beamformer_lcmv.m +++ b/toolbox/Beamforming/spm_eeg_ft_beamformer_lcmv.m @@ -1,14 +1,15 @@ -function [stats,talpositions]=spm_eeg_ft_beamformer_lcmv(S) +function [stats,mnipositions]=spm_eeg_ft_beamformer_lcmv(S) % Compute power-based beamformer image -% FORMAT [stats,talpositions]=spm_eeg_ft_beamformer_lcmv(S) +% FORMAT [stats,mnipositions]=spm_eeg_ft_beamformer_lcmv(S) % -% returns a stats structure containing univariate t test on power +% returns a stats structure containing univariate t test on power (based +% purely on sign in first column of design matrix S.design.X) % and a list of the image files produced %__________________________________________________________________________ % Copyright (C) 2009 Wellcome Trust Centre for Neuroimaging % Gareth Barnes -% $Id: spm_eeg_ft_beamformer_lcmv.m 3652 2009-12-18 18:54:43Z guillaume $ +% $Id: spm_eeg_ft_beamformer_lcmv.m 3969 2010-07-05 09:26:46Z gareth $ [Finter,Fgraph] = spm('FnUIsetup','univariate LCMV beamformer for power', 0); %% @@ -24,6 +25,7 @@ end; if ~isfield(S,'maskgrid'), + %% S.maskgrid=[]; end; @@ -45,10 +47,6 @@ S.Niter=1; end; % if -% if ~isfield(S,'weightspect'), -% S.weightspect=[]; -% end; -% if ~isfield(S,'weightttest'), S.weightttest=[]; end; @@ -129,8 +127,16 @@ modality = spm_eeg_modality_ui(D, 1, 1); - channel_labels = D.chanlabels(strmatch(modality, D.chantype))'; +chanind=strmatch(modality, D.chantype); +chanind = setdiff(chanind,D.badchannels); + channel_labels = D.chanlabels(chanind)'; + %chan_ind = setdiff(D.meegchannels('MEG'),D.badchannels) + + if ~isfield(D,'inv') + errordlg('Need to set up a forward model before you start'); + end; + if isfield(S, 'refchan') && ~isempty(S.refchan) refchan = S.refchan; else @@ -152,26 +158,47 @@ if strncmp(modality, D.inv{D.val}.forward(m).modality, 3) vol = D.inv{D.val}.forward(m).vol; if isa(vol, 'char') - vol = fileio_read_vol(vol); + vol = ft_read_vol(vol); end datareg = D.inv{D.val}.datareg(m); end end - try - vol = D.inv{D.val}.forward.vol; - datareg = D.inv{D.val}.datareg; - catch - D = spm_eeg_inv_mesh_ui(D, D.val, [], 1); - D = spm_eeg_inv_datareg_ui(D, D.val); - datareg = D.inv{D.val}.datareg; - end -% Return beamformer weights +def_colormap=colormap; +jetmap=colormap('jet'); +colormap(def_colormap); +% +% try +% vol = D.inv{D.val}.forward.vol; +% datareg = D.inv{D.val}.datareg; +% catch +% D = spm_eeg_inv_mesh_ui(D, D.val, [], 1); +% D = spm_eeg_inv_datareg_ui(D, D.val); +% datareg = D.inv{D.val}.datareg; +% end + +if strcmp('EEG', modality) + sens = datareg.sensors; + +else + sens = D.sensors('MEG'); + +end + + + +%% transform to mni space +% M1 = datareg.toMNI; +% [U, L, V] = svd(M1(1:3, 1:3)); +% M1(1:3,1:3) =U*V'; +% +% vol = ft_transform_vol(M1, vol); +% sens = ft_transform_sens(M1, sens); -X=S.design.X; +Xdesign =S.design.X; c=S.design.contrast; %% c is contrast eg [ 0 1 -1] compare columns 2,3 of X @@ -181,9 +208,9 @@ error('Design windows missepcified'); end; -X0 = X - X*c*pinv(c); -Xdesign = full(X*c); -X0 = spm_svd(X0); %% X0 is null space i.e. everything that is happening in other columns of X +%X0 = X - X*c*pinv(c); + +%X0 = spm_svd(X0); %% X0 is null space i.e. everything that is happening in other columns of X outfilenames=''; @@ -245,6 +272,9 @@ allfftwindow=repmat(fftwindow,1,Nchans); NumUniquePts = ceil((Nsamples+1)/2); %% data is real so fft is symmetric +if NumUniquePts<=2, + error('Need to have more than 2 samples of data'); +end; fftnewdata=zeros(Ntrials,NumUniquePts,Nchans); allepochdata=zeros(Ntrials,Nchans,Nsamples); %% for loading in data quickly @@ -283,8 +313,7 @@ else dtepochdata=epochdata; %% no dc removal, no detrend : this will have effect on accuracy of fourier estimate at non dc bins end; % detrend - wdtepochfft=dtepochdata.*allfftwindow; %% windowed - + wdtepochfft=dtepochdata.*allfftwindow; %% windowed epochfft=fft(wdtepochfft); fftnewdata(i,:,:)=epochfft(1:NumUniquePts,:); % .*filtervect'; end; @@ -302,16 +331,12 @@ % %% cfg = []; -if strcmp('EEG', modality) - cfg.elec = D.inv{D.val}.datareg.sensors; - cfg.reducerank=3; -else - cfg.grad = D.sensors('MEG'); - cfg.reducerank=2; - disp('Reducing possible source orientations to a tangential plane for MEG'); -end - +if ismember(modality, {'MEG', 'MEGPLANAR'}) + disp('Reducing possible source orientations to a tangential plane for MEG'); + cfg.reducerank = 2; +end; +cfg.grad=sens; cfg.channel = channel_labels; cfg.vol = vol; @@ -349,7 +374,7 @@ - + %% Now have all lead fields and all data %% Now do actual beamforming %% decide on the covariance matrix we need @@ -405,6 +430,7 @@ disp(sprintf('largest/smallest eigenvalue=%3.2f',allsvd(1)/allsvd(end))); disp(sprintf('\nFrequency resolution %3.2fHz',mean(diff(fHz)))); noise = allsvd(end); %% use smallest eigenvalue + noise_id=eye(size(covtrial)).*noise; redNfeatures=Nfeatures; @@ -415,7 +441,7 @@ lambda = (S.regpc/100) * sum(allsvd)/size(covtrial,1); %% scale lambda relative mean eigenvalue disp(sprintf('regularisation =%3.2f percent',S.regpc)); - cinv=inv(covtrial+eye(size(covtrial,1))*lambda); %% get inverse + cinv=pinv(covtrial+eye(size(covtrial,1))*lambda); %% get inverse @@ -435,7 +461,8 @@ end; end; - + dfe=Ntrials-rank(Xdesign); % df test + for i=1:length(maskedgrid_inside_ind), %% 81 lf=cell2mat(grid.leadfield(grid.inside(maskedgrid_inside_ind(i)))); @@ -444,7 +471,7 @@ [u, s, v] = svd(real(projpower_vect)); eta = u(:,1); lf = lf * eta; %% now have got the lead field at this voxel, compute some contrast - weights=(lf'*cinv*lf)*lf'*cinv; %% + weights=lf'*cinv/(lf'*cinv*lf); %% CORRECT WEIGHTS CALC if S.return_weights stats(fband).ctf_weights(i,:)=weights; @@ -470,29 +497,45 @@ else Yfull=evoked_trial; end; % if power_flag - %Yfull=power_trial; - %Y = Yfull - X0*(X0'*Yfull); %% eg remove DC level or drift terms from all of Y %% Now permute the rows of X if necessary for iter=1:S.Niter, +% + X=Xdesign(randind(iter,:),:); %% randind(1,:)=1, i.e. unpermuted +% cond1_ind=find(X(:,1)>0); +% cond2_ind=find(X(:,1)<=0); +% nx=length(cond1_ind); +% ny=length(cond2_ind); +% dfe = nx + ny - 2; +% xba_epochs=Yfull(cond1_ind,:)*tfiltervect; %% for univariate tfiltervect is all ones (i.e. sum) +% yba_epochs=Yfull(cond2_ind,:)*tfiltervect; %% +% pdiff=mean(xba_epochs)-mean(yba_epochs); +% s2x=var(xba_epochs); +% s2y=var(yba_epochs); +% sPooled = sqrt(((nx-1) .* s2x + (ny-1) .* s2y) ./ dfe); +% se = sPooled .* sqrt(1./nx + 1./ny); +% tstat(maskedgrid_inside_ind(i),iter) = pdiff ./ se; % +% normdiff(maskedgrid_inside_ind(i),iter)=pdiff/(weights*noise_id*weights'); +% + + % Contrast + + + Yvals=mean(Yfull')'; + + B = pinv(X)*Yvals; + +% t statistic and significance test + RSS = sum((Yvals - X*B).^2); + MRSS = RSS / dfe; + SE = sqrt(MRSS*(c*pinv(X'*X)*c')); - X=Xdesign(randind(iter,:),:); %% randind(1,:)=1, i.e. unpermuted - cond1_ind=find(X(:,1)>0); - cond2_ind=find(X(:,1)<=0); - nx=length(cond1_ind); - ny=length(cond2_ind); - dfe = nx + ny - 2; - xba_epochs=Yfull(cond1_ind,:)*tfiltervect; %% for univariate tfiltervect is all ones (i.e. sum) - yba_epochs=Yfull(cond2_ind,:)*tfiltervect; %% - pdiff=mean(xba_epochs)-mean(yba_epochs); - s2x=var(xba_epochs); - s2y=var(yba_epochs); - sPooled = sqrt(((nx-1) .* s2x + (ny-1) .* s2y) ./ dfe); - se = sPooled .* sqrt(1./nx + 1./ny); - tstat(maskedgrid_inside_ind(i),iter) = pdiff ./ se; % - normdiff(maskedgrid_inside_ind(i),iter)=pdiff/(weights*weights'); + tstat(maskedgrid_inside_ind(i),iter)=c*B./SE; + normdiff(maskedgrid_inside_ind(i),iter)=c*B/(weights*noise_id*weights'); %% maybe a factor missing here + + end; % for Niter @@ -510,6 +553,8 @@ stats(fband).tstat=tstat; + maxt=max(tstat(:,TrueIter)); + mint=min(tstat(:,TrueIter)); stats(fband).fHz=fHz; dispthresh_uv=max(stats(fband).tstat)/2; @@ -524,7 +569,7 @@ end; % if - talpositions = spm_eeg_inv_transform_points(D.inv{D.val}.datareg.toMNI, grid.pos(grid.inside(maskedgrid_inside_ind),:)); + mnipositions = spm_eeg_inv_transform_points(D.inv{D.val}.datareg.toMNI, grid.pos(grid.inside(maskedgrid_inside_ind),:)); gridpositions=grid.pos(grid.inside(maskedgrid_inside_ind),:); @@ -537,7 +582,14 @@ csource.pow_tstat(csource.outside)=0; csource.pos = spm_eeg_inv_transform_points(D.inv{D.val}.datareg.toMNI, csource.pos); - csource.normdiff(csource.inside) =normdiff(:,TrueIter); + zeromean_images=0; %% leave this off for now. + if zeromean_images==1, + imgmean=mean(normdiff(:,TrueIter)); + imgstd=mean(normdiff(:,TrueIter)); + disp(sprintf('Removing mean value %3.2f from normdiff image (std=%3.2f)!',imgmean,imgstd)); + normdiff(:,TrueIter)=normdiff(:,TrueIter)-imgmean; + end; + csource.normdiff(csource.inside) =normdiff(:,TrueIter); csource.normdiff(csource.outside)=0; @@ -563,26 +615,6 @@ - if (isfield(S, 'preview') && S.preview) - - - cfg1 = []; - cfg1.funparameter = 'pow_tstat'; - cfg1.funcolorlim = [min(csource.pow_tstat) max(csource.pow_tstat)]; - cfg1.interactive = 'yes'; - figure - ft_sourceplot(cfg1,sourceint_pow_tstat); - - -% cfg1 = []; -% cfg1.funparameter = 'evoked_tstat2'; -% cfg1.funcolorlim = [min(csource.evoked_tstat2) max(csource.evoked_tstat2)]; -% cfg1.interactive = 'yes'; -% figure -% ft_sourceplot(cfg1,sourceint_evoked_tstat2); - - - end; % if preview %% else %% write out the data sets @@ -601,47 +633,33 @@ res = mkdir(D.path, dirname); outvol = spm_vol(sMRI); outvol.dt(1) = spm_type('float32'); -% featurestr=[S.filenamestr 'Nf' num2str(redNfeatures)] ; -% outvol.fname= fullfile(D.path, dirname, ['chi_pw_' spm_str_manip(D.fname, 'r') '_' num2str(freqbands(fband,1)) '-' num2str(freqbands(fband,2)) 'Hz' featurestr '.nii']); -% stats(fband).outfile_chi_pw=outvol.fname; -% outvol = spm_create_vol(outvol); -% spm_write_vol(outvol, sourceint_pow_maxchi.pow_maxchi); -% -% outvol.fname= fullfile(D.path, dirname, ['chi_ev_' spm_str_manip(D.fname, 'r') '_' num2str(freqbands(fband,1)) '-' num2str(freqbands(fband,2)) 'Hz' featurestr '.nii']); -% stats(fband).outfile_chi_ev=outvol.fname; -% outvol = spm_create_vol(outvol); -% spm_write_vol(outvol, sourceint_evoked_maxchi.evoked_maxchi); - - outvol.fname= fullfile(D.path, dirname, ['tstat_pow_' spm_str_manip(D.fname, 'r') '_' num2str(S.freqbands{fband}(1)) '-' num2str(S.freqbands{fband}(2)) 'Hz' S.filenamestr '.nii']); + outvol.fname= fullfile(D.path, dirname, ['spmT_' spm_str_manip(D.fname, 'r') '_' num2str(S.freqbands{fband}(1)) '-' num2str(S.freqbands{fband}(2)) 'Hz' S.filenamestr '.nii']); + stats(fband).outfile_pow_tstat=outvol.fname; outvol = spm_create_vol(outvol); spm_write_vol(outvol, sourceint_pow_tstat.pow_tstat); - outvol.fname= fullfile(D.path, dirname, ['normdiff_pow_' spm_str_manip(D.fname, 'r') '_' num2str(S.freqbands{fband}(1)) '-' num2str(S.freqbands{fband}(2)) 'Hz' S.filenamestr '.nii']); + jetmap=colormap('jet'); + if (isfield(S, 'preview') && S.preview) + spm_check_registration(sMRI) + prop=0.4; + colourmap=jetmap; + spm_orthviews('Addtruecolourimage',1,outvol.fname,colourmap,prop,maxt,mint); + disp('Press any key to continue'); + pause; + end; % if preview + outvol.fname= fullfile(D.path, dirname, ['spmNdiff_' spm_str_manip(D.fname, 'r') '_' num2str(S.freqbands{fband}(1)) '-' num2str(S.freqbands{fband}(2)) 'Hz' S.filenamestr '.nii']); + stats(fband).outfile_normdiff=outvol.fname; outvol = spm_create_vol(outvol); spm_write_vol(outvol, sourceint_normdiff.normdiff); -% + end; % if ~S.gridpos end; % for fband=1:Nbands - %% Set t tstat thresholds based on F test for this many degrees of - %% freedom. Not using Hotellings threshold for now.. -% Nfeatures=Nchans; -% Ht_toF=(Ntrials-Nfeatures)/((Nfeatures-1)*Ntrials); %% factor that relates hotellings T threshold to an F threshold -% Fthresh_alyt=spm_invFcdf(1-0.05,Nfeatures,Ntrials-Nfeatures); -% T2thresh=Fthresh_alyt.^2; -% plotT=tstat; -% plotind=find(tstat.^2>=T2thresh); -% -% Fgraph = spm_figure('GetWin','Graphics'); -% figure(Fgraph);clf -% -% spm_mip(plotT(plotind),talpositions(plotind,:),S.gridstep); -% drawnow -% + end % function diff --git a/toolbox/Beamforming/spm_eeg_ft_beamformer_mult.m b/toolbox/Beamforming/spm_eeg_ft_beamformer_mult.m index f092cb5..123502f 100644 --- a/toolbox/Beamforming/spm_eeg_ft_beamformer_mult.m +++ b/toolbox/Beamforming/spm_eeg_ft_beamformer_mult.m @@ -1,4 +1,4 @@ -function [outfilenames,ctf_inside,ctf_weights]=spm_eeg_ft_beamformer_mult(S) +function [outfilenames,ctf_inside,ctf_weights,fftnewdata]=spm_eeg_ft_beamformer_mult(S) % Compute power-based beamformer image % FORMAT [outfilenames,ctf_inside,ctf_weights]=spm_eeg_ft_beamformer_mult(S) % @@ -21,7 +21,7 @@ % Copyright (C) 2009 Wellcome Trust Centre for Neuroimaging % Gareth Barnes -% $Id: spm_eeg_ft_beamformer_mult.m 3652 2009-12-18 18:54:43Z guillaume $ +% $Id: spm_eeg_ft_beamformer_mult.m 3833 2010-04-22 14:49:48Z vladimir $ [Finter,Fgraph] = spm('FnUIsetup','Multivariate LCMV beamformer for power', 0); %% @@ -79,7 +79,7 @@ if strncmp(modality, D.inv{D.val}.forward(m).modality, 3) vol = D.inv{D.val}.forward(m).vol; if isa(vol, 'char') - vol = fileio_read_vol(vol); + vol = ft_read_vol(vol); end datareg = D.inv{D.val}.datareg(m); end @@ -314,7 +314,7 @@ [u, s, v] = svd(real(projpower_vect)); eta = u(:,1); lf = lf * eta; %% now have got the lead field at this voxel, compute some contrast - weights=(lf'*cinv*lf)*lf'*cinv; %% no regularisation for now + weights=lf'*cinv/(lf'*cinv*lf); %% Corrected weights calc if S.return_weights ctf_weights(i,:)=weights; diff --git a/toolbox/Beamforming/spm_eeg_ft_beamformer_source.m b/toolbox/Beamforming/spm_eeg_ft_beamformer_source.m index 02f91df..e834611 100644 --- a/toolbox/Beamforming/spm_eeg_ft_beamformer_source.m +++ b/toolbox/Beamforming/spm_eeg_ft_beamformer_source.m @@ -23,7 +23,7 @@ % Copyright (C) 2009 Wellcome Trust Centre for Neuroimaging % Vladimir Litvak, Robert Oostenveld -% $Id: spm_eeg_ft_beamformer_source.m 3652 2009-12-18 18:54:43Z guillaume $ +% $Id: spm_eeg_ft_beamformer_source.m 3833 2010-04-22 14:49:48Z vladimir $ [Finter,Fgraph,CmdLine] = spm('FnUIsetup', 'Beamformer source activity extraction',0); @@ -148,7 +148,7 @@ if strncmp(modality, D.inv{D.val}.forward(m).modality, 3) vol = D.inv{D.val}.forward(m).vol; if isa(vol, 'char') - vol = fileio_read_vol(vol); + vol = ft_read_vol(vol); end datareg = D.inv{D.val}.datareg(m); end @@ -165,12 +165,12 @@ [U, L, V] = svd(M1(1:3, 1:3)); M1(1:3,1:3) =U*V'; -vol = forwinv_transform_vol(M1, vol); -sens = forwinv_transform_sens(M1, sens); +vol = ft_transform_vol(M1, vol); +sens = ft_transform_sens(M1, sens); channel = D.chanlabels(setdiff(meegchannels(D, modality), D.badchannels)); -[vol, sens] = forwinv_prepare_vol_sens(vol, sens, 'channel', channel); +[vol, sens] = ft_prepare_vol_sens(vol, sens, 'channel', channel); %% spm('Pointer', 'Watch');drawnow; @@ -233,7 +233,7 @@ cfg.inwardshift = -30; cfg.vol = vol; cfg.grad = sens; -cfg.grid = ft_source2grid(source1); +cfg.grid = source2grid(source1); cfg.channel = modality; cfg.lambda = S.lambda; cfg.rawtrial = 'yes'; diff --git a/toolbox/DARTEL/dartel3.c b/toolbox/DARTEL/dartel3.c index d3e19d0..15ffd50 100644 --- a/toolbox/DARTEL/dartel3.c +++ b/toolbox/DARTEL/dartel3.c @@ -1,4 +1,4 @@ -/* $Id: dartel3.c 3548 2009-11-09 21:25:10Z john $ */ +/* $Id: dartel3.c 3805 2010-04-01 15:34:54Z john $ */ /* (c) John Ashburner (2007) */ #include "mex.h" @@ -789,6 +789,55 @@ static void exp_mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray * mxFree((void *)t1); } +static void smalldef_mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) +{ + int nd; + const int *dm; + float *v, *t; + double sc = 1.0; + + if (((nrhs != 1) && (nrhs != 2)) || (nlhs>2)) mexErrMsgTxt("Incorrect usage."); + if (!mxIsNumeric(prhs[0]) || mxIsComplex(prhs[0]) || mxIsSparse(prhs[0]) || !mxIsSingle(prhs[0])) + mexErrMsgTxt("Data must be numeric, real, full and single"); + nd = mxGetNumberOfDimensions(prhs[0]); + if (nd!=4) mexErrMsgTxt("Wrong number of dimensions."); + dm = mxGetDimensions(prhs[0]); + if (dm[3]!=3) + mexErrMsgTxt("4th dimension must be 3."); + + if (nrhs>1) + { + if (!mxIsNumeric(prhs[1]) || mxIsComplex(prhs[1]) || mxIsSparse(prhs[1]) || !mxIsDouble(prhs[1])) + mexErrMsgTxt("Data must be numeric, real, full and double"); + if (mxGetNumberOfElements(prhs[1]) > 1) + mexErrMsgTxt("Params must contain one element"); + if (mxGetNumberOfElements(prhs[1]) >= 1) sc = (float)(mxGetPr(prhs[1])[0]); + } + + v = (float *)mxGetPr(prhs[0]); + + plhs[0] = mxCreateNumericArray(nd,dm, mxSINGLE_CLASS, mxREAL); + t = (float *)mxGetPr(plhs[0]); + + if (nlhs < 2) + { + smalldef((int *)dm, sc, v, t); + } + else + { + float *J, *J1; + int dmj[5]; + dmj[0] = dm[0]; + dmj[1] = dm[1]; + dmj[2] = dm[2]; + dmj[3] = 3; + dmj[4] = 3; + plhs[1] = mxCreateNumericArray(5,dmj, mxSINGLE_CLASS, mxREAL); + J = (float *)mxGetPr(plhs[1]); + smalldef_jac1((int *)dm, sc, v, t, J); + } +} + static void det_mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { int nd; @@ -891,6 +940,11 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) mxFree(fnc_str); exp_mexFunction(nlhs, plhs, nrhs-1, &prhs[1]); } + else if (!strcmp(fnc_str,"smalldef")) + { + mxFree(fnc_str); + smalldef_mexFunction(nlhs, plhs, nrhs-1, &prhs[1]); + } else if (!strcmp(fnc_str,"samp")) { mxFree(fnc_str); diff --git a/toolbox/DARTEL/dartel3.mexa64 b/toolbox/DARTEL/dartel3.mexa64 index 74d00ea..39f8ac9 100644 Binary files a/toolbox/DARTEL/dartel3.mexa64 and b/toolbox/DARTEL/dartel3.mexa64 differ diff --git a/toolbox/DARTEL/dartel3.mexglx b/toolbox/DARTEL/dartel3.mexglx index 6c3b99f..0bfa6ff 100644 Binary files a/toolbox/DARTEL/dartel3.mexglx and b/toolbox/DARTEL/dartel3.mexglx differ diff --git a/toolbox/DARTEL/dartel3.mexmaci b/toolbox/DARTEL/dartel3.mexmaci index 9589eff..5894682 100644 Binary files a/toolbox/DARTEL/dartel3.mexmaci and b/toolbox/DARTEL/dartel3.mexmaci differ diff --git a/toolbox/DARTEL/dartel3.mexmaci64 b/toolbox/DARTEL/dartel3.mexmaci64 index f07c624..8af8989 100755 Binary files a/toolbox/DARTEL/dartel3.mexmaci64 and b/toolbox/DARTEL/dartel3.mexmaci64 differ diff --git a/toolbox/DARTEL/dartel3.mexw32 b/toolbox/DARTEL/dartel3.mexw32 index b9ef3d1..c214564 100755 Binary files a/toolbox/DARTEL/dartel3.mexw32 and b/toolbox/DARTEL/dartel3.mexw32 differ diff --git a/toolbox/DARTEL/dartel3.mexw64 b/toolbox/DARTEL/dartel3.mexw64 index 9a4078a..bcf540a 100644 Binary files a/toolbox/DARTEL/dartel3.mexw64 and b/toolbox/DARTEL/dartel3.mexw64 differ diff --git a/toolbox/DARTEL/diffeo3d.c b/toolbox/DARTEL/diffeo3d.c index 7ee0bcf..24a642d 100644 --- a/toolbox/DARTEL/diffeo3d.c +++ b/toolbox/DARTEL/diffeo3d.c @@ -1,4 +1,4 @@ -/* $Id: diffeo3d.c 3548 2009-11-09 21:25:10Z john $ */ +/* $Id: diffeo3d.c 3802 2010-03-29 13:07:15Z john $ */ /* (c) John Ashburner (2007) */ #include @@ -1018,7 +1018,7 @@ void pushc_grads(int dm[], int m, float def[], float J[], float pf[], float po[] ij12 = j13*j32-j12*j33; ij13 = j12*j23-j13*j22; dj = j11*ij11 + j21*ij12 + j31*ij13; - if (dj<0.01) dj = 0.01; + dj = (dj*0.99+0.01); dj = 1.0/dj; ij11*= dj; @@ -1106,7 +1106,7 @@ static int pow2(int k) /* * t0 = Id + v0*sc */ -static void smalldef(int dm[], double sc, float v0[], float t0[]) +void smalldef(int dm[], double sc, float v0[], float t0[]) { int j0, j1, j2; int m = dm[0]*dm[1]*dm[2]; @@ -1218,6 +1218,246 @@ static void smalldef_jac(int dm[], double sc, float v0[], float t0[], float J0[] } } +/* syms a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] + syms b[0] b[1] b[2] b[3] b[4] b[5] b[6] b[7] b[8] + A = [a[0] a[1] a[2]; a[3] a[4] a[5]; a[6] a[7] a[8]].'; + B = [b[0] b[1] b[2]; b[3] b[4] b[5]; b[6] b[7] b[8]].'; + C = A*B; + C = C(:) + + C = A\B; + C = C(:) +*/ +float *sub33(float *a, float *b, float *c) +{ + int i; + for(i=0; i<9; i++) + c[i] = a[i] - b[i]; + return(c); +} + +float *add33(float *a, float *b, float *c) +{ + int i; + for(i=0; i<9; i++) + c[i] = a[i] + b[i]; + return(c); +} + +float *scale33(float *a, float s, float *b) +{ + int i; + for(i=0; i<9; i++) + b[i] = a[i]*s; + return(b); +} + +float *eye33(float *a) +{ + a[0] = 1.0; + a[1] = 0.0; + a[2] = 0.0; + a[3] = 0.0; + a[4] = 1.0; + a[5] = 0.0; + a[6] = 0.0; + a[7] = 0.0; + a[8] = 1.0; + return(a); +} + +float *mul33(float *a, float *b, float *c) +{ + c[0] = a[0]*b[0] + a[3]*b[1] + a[6]*b[2]; + c[1] = a[1]*b[0] + a[4]*b[1] + a[7]*b[2]; + c[2] = a[2]*b[0] + a[5]*b[1] + a[8]*b[2]; + c[3] = a[0]*b[3] + a[3]*b[4] + a[6]*b[5]; + c[4] = a[1]*b[3] + a[4]*b[4] + a[7]*b[5]; + c[5] = a[2]*b[3] + a[5]*b[4] + a[8]*b[5]; + c[6] = a[0]*b[6] + a[3]*b[7] + a[6]*b[8]; + c[7] = a[1]*b[6] + a[4]*b[7] + a[7]*b[8]; + c[8] = a[2]*b[6] + a[5]*b[7] + a[8]*b[8]; + return(c); +} + +float *div33(float *a, float *b, float *c) +{ + float d = a[0]*(a[4]*a[8] - a[5]*a[7]) + a[1]*(a[5]*a[6] - a[3]*a[8]) + a[2]*(a[3]*a[7] - a[4]*a[6]); + c[0] = (a[3]*(a[7]*b[2] - a[8]*b[1]) + a[4]*(a[8]*b[0] - a[6]*b[2]) + a[5]*(a[6]*b[1] - a[7]*b[0]))/d; + c[1] = -(a[0]*(a[7]*b[2] - a[8]*b[1]) + a[1]*(a[8]*b[0] - a[6]*b[2]) + a[2]*(a[6]*b[1] - a[7]*b[0]))/d; + c[2] = (a[0]*(a[4]*b[2] - a[5]*b[1]) + a[1]*(a[5]*b[0] - a[3]*b[2]) + a[2]*(a[3]*b[1] - a[4]*b[0]))/d; + c[3] = (a[3]*(a[7]*b[5] - a[8]*b[4]) + a[4]*(a[8]*b[3] - a[6]*b[5]) + a[5]*(a[6]*b[4] - a[7]*b[3]))/d; + c[4] = -(a[0]*(a[7]*b[5] - a[8]*b[4]) + a[1]*(a[8]*b[3] - a[6]*b[5]) + a[2]*(a[6]*b[4] - a[7]*b[3]))/d; + c[5] = (a[0]*(a[4]*b[5] - a[5]*b[4]) + a[1]*(a[5]*b[3] - a[3]*b[5]) + a[2]*(a[3]*b[4] - a[4]*b[3]))/d; + c[6] = (a[3]*(a[7]*b[8] - a[8]*b[7]) + a[4]*(a[8]*b[6] - a[6]*b[8]) + a[5]*(a[6]*b[7] - a[7]*b[6]))/d; + c[7] = -(a[0]*(a[7]*b[8] - a[8]*b[7]) + a[1]*(a[8]*b[6] - a[6]*b[8]) + a[2]*(a[6]*b[7] - a[7]*b[6]))/d; + c[8] = (a[0]*(a[4]*b[8] - a[5]*b[7]) + a[1]*(a[5]*b[6] - a[3]*b[8]) + a[2]*(a[3]*b[7] - a[4]*b[6]))/d; + return(c); +} + +void pade33(float *a, float *l) +{ + float u[9], v[9], num[9], den[9], a0[9], a2[9], a3[9]; + + eye33(a0); + mul33(a,a,a2); + mul33(a2,a,a3); + scale33(a0,120.0,a0); + scale33(a2, 12.0,a2); + add33(a0,a2,u); + scale33(a,60.0,v); + add33(v,a3,v); + + add33(u,v,num); + sub33(u,v,den); + div33(den,num,l); +} + +void pade22(float *a, float *l) +{ + float u[9], v[9], num[9], den[9], a0[9], a2[9]; + + eye33(a0); + mul33(a,a,a2); + scale33(a0,12.0,a0); + add33(a0,a2,u); + scale33(a,6.0,v); + + add33(u,v,num); + sub33(u,v,den); + div33(den,num,l); +} + +float norm1(float *a) +{ + float r, rm; + rm = fabs(a[0]) + fabs(a[1]) + fabs(a[2]); + r = fabs(a[3]) + fabs(a[4]) + fabs(a[5]); + if (r>rm) rm = r; + r = fabs(a[6]) + fabs(a[7]) + fabs(a[8]); + if (r>rm) rm = r; + return(rm); +} + +float *assign33(float *a, float *b) +{ + int i; + for(i=0; i<9; i++) + b[i] = a[i]; + return(b); +} + +void expm33(float *a, float *l) +{ + /* See expm.m in MATLAB or http://mathworld.wolfram.com/PadeApproximant.html */ + int K; + K = (int)ceil(log((double)(norm1(a)*2.3481))*1.44269504088896); + if (K>0) + { + float b[9]; + float s = 1.0/pow2(K); + int i; + scale33(a,s,b); + pade33(b, l); + for(i=0; i0) + { + float b[9]; + float s = 1.0/pow2(K); + int i; + scale33(a,s,b); + pade22(b, l); + for(i=0; i'}; -dartel.warp.settings.template = 'Template'; -dartel.warp.settings.rform = double(0); -dartel.warp.settings.param.its = double(3); -dartel.warp.settings.param.rparam = double([0.100000000000000006 0.0100000000000000002 0.00100000000000000002]); -dartel.warp.settings.param.K = double(6); -dartel.warp.settings.param.slam = double(1); -dartel.warp.settings.optim.lmreg = double(0.0100000000000000002); -dartel.warp.settings.optim.cyc = double(3); -dartel.warp.settings.optim.its = double(3); -dartel.warp1.images = {''}; -dartel.warp1.settings.rform = double(0); -dartel.warp1.settings.param.its = double(3); -dartel.warp1.settings.param.rparam = double([0.100000000000000006 0.0100000000000000002 0.00100000000000000002]); -dartel.warp1.settings.param.K = double(6); -dartel.warp1.settings.param.template = ''; -dartel.warp1.settings.optim.lmreg = double(0.0100000000000000002); -dartel.warp1.settings.optim.cyc = double(3); -dartel.warp1.settings.optim.its = double(3); -dartel.crt_warped.flowfields = ''; -dartel.crt_warped.images = {''}; -dartel.crt_warped.jactransf = double(0); -dartel.crt_warped.K = double(6); -dartel.crt_warped.interp = double(1); -dartel.jacdet.flowfields = ''; -dartel.jacdet.K = double(6); -dartel.crt_iwarped.flowfields = ''; -dartel.crt_iwarped.images = ''; -dartel.crt_iwarped.K = double(6); -dartel.crt_iwarped.interp = double(1); -dartel.kernfun.resids.images = {''}; -dartel.kernfun.resids.flowfields = ''; -dartel.kernfun.resids.template = ''; -dartel.kernfun.resids.K = double(6); -dartel.kernfun.resids.fwhm = double(4); -dartel.kernfun.reskern.images = ''; -dartel.kernfun.reskern.weight = ''; -dartel.kernfun.reskern.dotprod = ''; -dartel.kernfun.flokern.flowfields = ''; -dartel.kernfun.flokern.rform = double(0); -dartel.kernfun.flokern.rparam = double([0.25 0.125 1e-06]); -dartel.kernfun.flokern.dotprod = ''; -varargout{1} = dartel; -varargout{2} = 'dartel'; diff --git a/toolbox/DEM/ADEM_SHC_demo.m b/toolbox/DEM/ADEM_SHC_demo.m index e725d56..286be2d 100644 --- a/toolbox/DEM/ADEM_SHC_demo.m +++ b/toolbox/DEM/ADEM_SHC_demo.m @@ -1,9 +1,12 @@ -% This demo ... +% This demo illustrates the use of Lotka-Volterra form SHCs (Stable +% heteroclinic channel) to prescribe active sampling (inference). In this +% example each (unstable) fixed point in the SHC attracts the agent to +% points on the circumference of a circle. %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: ADEM_SHC_demo.m 3113 2009-05-11 15:25:13Z karl $ +% $Id: ADEM_SHC_demo.m 3901 2010-05-27 16:14:36Z karl $ % generative process %========================================================================== % switch for demo @@ -32,24 +35,19 @@ fx = inline('spm_lotka_volterra(x,v,P)','x','v','P'); gx = inline('spm_gx_SHC(x,v,P)','x','v','P'); gx = inline('x.v','x','v','P'); - -% positions associated with each states (on unit circle) + +% positions associated with each state (on unit circle) %-------------------------------------------------------------------------- nx = 8; P.g(1,:) = cos(2*pi*([1:nx]' - 1)/nx); P.g(2,:) = sin(2*pi*([1:nx]' - 1)/nx); - + % parameters of succession %-------------------------------------------------------------------------- -R = randn(nx,nx); -R = (R - R')/8 - (1 - speye(nx)); - -P.f = spm_speye(nx,nx, 1)*1 - spm_speye(nx,nx,-1)*1; -P.f(nx,1) = 1; -P.f(1,nx) = -1; +P.f = spm_speye(nx,nx,-1) - spm_speye(nx,nx,+1); +P.f(nx,1) = -1; +P.f(1,nx) = +1; P.f = P.f/2 - 1 + speye(nx); -P.k = 1; - % level 1 %-------------------------------------------------------------------------- diff --git a/toolbox/DEM/ADEM_cost.m b/toolbox/DEM/ADEM_cost.m new file mode 100644 index 0000000..20b7d3a --- /dev/null +++ b/toolbox/DEM/ADEM_cost.m @@ -0,0 +1,183 @@ +% This demo re-visits the mountain car problem to show that adaptive +% (desired) behaviour can be prescribed in terms of loss-functions (i.e. +% reward functions of state-space). +% It exploits the fact that under the free-energy formulation, loss is +% divergence. This means that priors can be used to make certain parts of +% state-space costly (i.e. with high divergence) and others rewarding (low +% divergence). Active inference under these priors will lead to sampling of +% low cost states and (apparent) attractiveness of those states. +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: ADEM_cost.m 3757 2010-03-08 11:41:53Z guillaume $ + +% generative process (mountain car terrain) +%========================================================================== +% switch for demo +clear + +% parameters of generative process +%-------------------------------------------------------------------------- +P.p = [1; + 2]; + +x0.x = [0;-1]; +x0.v = [1;0]; +x0.q = 0; +x0.p = 0; + + +% level 1 +%-------------------------------------------------------------------------- +G(1).x = x0; +G(1).f = inline('spm_cost_fxa(x,v,a,P)','x','v','a','P'); +G(1).g = inline('[x.x; x.v; x.q; x.p]','x','v','a','P'); +G(1).pE = P; +G(1).V = exp(16); % error precision +G(1).W = exp(16); % error precision + +% level 2 +%-------------------------------------------------------------------------- +G(2).a = [0;0]; % action +G(2).v = 0; % inputs +G(2).V = exp(16); +G = spm_ADEM_M_set(G); + + +% generative model +%========================================================================== + +% parameters and equations of motion +%-------------------------------------------------------------------------- +P.p = [0; + 0]; + +x0.x = [0;0]; +x0.v = [0;0]; +x0.q = 0; +x0.p = 0; + + +% level 1 +%-------------------------------------------------------------------------- +M(1).x = x0; +M(1).f = inline('spm_cost_fx(x,v,P)','x','v','P'); +M(1).g = inline('[x.x; x.v; x.q; x.p]','x','v','P'); +M(1).pE = P; +M(1).V = exp(8); % error precision +M(1).W = exp(4); % error precision +M(1).xP = 1/8; + +% level 2 +%-------------------------------------------------------------------------- +M(2).v = 0; % inputs +M(2).V = exp(16); +M = spm_DEM_M_set(M); + + +% learn gradients with a flat loss-functions (priors on divergence) +%========================================================================== +N = 72; +U = sparse(N,M(1).m); +DEM.U = U; +DEM.C = U; +DEM.G = G; +DEM.M = M; +DEM = spm_ADEM(DEM); + + +% show dynamics +%========================================================================== + +% inference +%-------------------------------------------------------------------------- +spm_figure('GetWin','DEM'); +spm_DEM_qU(DEM.qU) + +subplot(2,2,1) +plot(DEM.pU.v{1}(1,:),DEM.pU.v{1}(2,:)); hold on +plot(DEM.pU.v{1}(1,:),DEM.pU.v{1}(2,:),'.','MarkerSize',8); +plot(DEM.qU.v{1}(1,:),DEM.qU.v{1}(2,:),':') +d = 1/2; +[X Y Z] = sphere; +x = G(1).pE.p(1,:); +y = G(1).pE.p(2,:); +surf(X*d + x,Y*d + y,Z*d - 8) +shading interp + +axis([-3 3 -3 3]) +axis square +title('trajectory','FontSize',16),hold off + +return + + +% true and inferred position +%-------------------------------------------------------------------------- +subplot(2,2,3) +plot(DEM.pU.x{1}(1,:),DEM.pU.x{1}(2,:)),hold on +plot( 1,0,'r.','Markersize',32), hold on +plot(-1/2,0,'g.','Markersize',16), hold off +xlabel('position','Fontsize',14) +ylabel('velcitiy','Fontsize',14) +title('trajectories','Fontsize',16) +axis([-1 1 -1 1]*3) +axis square + +% true position +%-------------------------------------------------------------------------- +subplot(2,2,3) +plot3(DEM.pU.x{1}(1,:),DEM.pU.x{1}(2,:),1:N), hold on +plot3( 1,0,1:64:N,'r.','Markersize',8), hold on +plot3(-1/2,0,1:64:N,'g.','Markersize',8), hold off +xlabel('position','Fontsize',14) +ylabel('velocity','Fontsize',14) +zlabel('time','Fontsize',14) +title('trajectories','Fontsize',16) +axis([-2 2 -2 2 0 N]) +axis square + + +% real states +%========================================================================== +spm_figure('GetWin','DEM'); +spm_DEM_qU(DEM.pU) + + +subplot(2,2,1) +plot3( 1,0,1:1/8:2,'r.'), hold on +plot3(-1/2,0,1:1/8:2,'g.'), hold on +plot3(DEM.pU.x{1}(1,:),DEM.pU.x{1}(2,:),DEM.pU.x{1}(4,:)), hold off +xlabel('position','Fontsize',14) +ylabel('velocity','Fontsize',14) +zlabel('satiety','Fontsize',14) +title('trajectories','Fontsize',16) +axis([-2 2 -2 2 0 8]) + + + +% cost function (see spm_mc_fx_4.m) +%-------------------------------------------------------------------------- +subplot(2,1,2) +x = -2:1/64:2; +d = 0:1/64:2; +for i = 1:length(x) + for j = 1:length(d) + D = spm_phi((1 - d(j))*8); + A = 2 - 32*exp(-(x(i) - 1).^2*32); + C(i,j) = A*D - 1; + end +end + +surf(d,x,C) +shading interp +xlabel('drive','Fontsize',14) +ylabel('position','Fontsize',14) +title('cost-function','Fontsize',16) +axis square + + +return + + diff --git a/toolbox/DEM/ADEM_cost_SHC.m b/toolbox/DEM/ADEM_cost_SHC.m new file mode 100644 index 0000000..c75bd33 --- /dev/null +++ b/toolbox/DEM/ADEM_cost_SHC.m @@ -0,0 +1,318 @@ +% This demo illustrates the use of priors on the motion of hidden states as +% polices. It simulates exploration and exploitation using radial basis +% function attractors and auto-vitiative (self-destroying) attractors +% as the basis of the prior. These dynamics enforce exploration, under +% active inference. In turn, this exploration enables perceptual learning +% to associate attractors with changes in physiological states (cf, +% rewards). This can be exploited to by formal priors to ensure regions of +% physiological state-space are avoided. +% We look at this scheme using simulated pathology; first, we simulate a +% (neurodegenerative) reduction in log-precision (cf Parkinson’s disease) on +% the motion of physical states. This results in active inference with +% a loss of precise volitional movement and subsequent failure to optimise +% physiological states. Second, we look at the effects of precision on +% learning by increasing log-precision (cf, Addition) on the motion of +% physiological states. This results in a failure to learn and, again, +% subsequent failure to optimise physiological states. +%__________________________________________________________________________ +% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: ADEM_cost_SHC.m 3757 2010-03-08 11:41:53Z guillaume $ + + +% switch for demo +%-------------------------------------------------------------------------- +clear +DEMO = 1; + +% location and radius of attractors (A) +%-------------------------------------------------------------------------- +global A +A.x = [1 -1 -1 1; + 2 -2 2 -2]; +A.d = 1/4; % s.d. of Gaussian radial basis function +A.u = 1/8; % threshold to induce rapid decay of x.a +A.q = [1 2]; % indices of locations that increase x.q + +% generative process +%========================================================================== + +% level 1 +%-------------------------------------------------------------------------- +G(1).x.x = [0;0]; +G(1).x.v = [1;0]; +G(1).x.q = [1;1/2]; + +G(1).f = inline('spm_cost_SHC_fxa(x,v,a,P)','x','v','a','P'); +G(1).g = inline('[x.x; x.v; x.q]','x','v','a','P'); +G(1).V = exp(16); % error precision +G(1).W = exp(16); % error precision + +% level 2 +%-------------------------------------------------------------------------- +G(2).a = sparse(2,1); % action +G(2).v = 0; % inputs +G(2).V = exp(16); +G = spm_ADEM_M_set(G); + + +% generative model +%========================================================================== + +% level 1 +%-------------------------------------------------------------------------- +M(1).x.x = G(1).x.x; +M(1).x.v = G(1).x.v; +M(1).x.q = G(1).x.q; +M(1).x.a = randn(4,1)/8; + +M(1).f = inline('spm_cost_SHC_fx(x,v,P)','x','v','P'); +M(1).g = inline('[x.x; x.v; x.q]','x','v','P'); +M(1).pE = speye(4,2); + +M(1).V = exp(8); +M(1).W = diag(exp([[1 1 1 1]*4 [1 1]*6 [1 1 1 1]*4])); + +% level 2 (no exogenous inputs in this simulation) +%-------------------------------------------------------------------------- +M(2).v = 0; +M(2).V = exp(16); + +% Integrate: active inference +%========================================================================== +M(1).E.nE = 1; +M(1).E.n = 4; + +N = 128; +DEM.U = sparse(N,1); +DEM.C = sparse(N,1); +DEM.G = G; +DEM.M = M; + +if DEMO + load DEM_addiction +else + DEM = spm_ADEM(DEM); +end + + +% show behavior +%========================================================================== + +% overview +%-------------------------------------------------------------------------- +spm_figure('GetWin','Figure 1'); +spm_DEM_qU(DEM.qU) + +subplot(2,2,3) +spm_cost_SHC_path(DEM.pU,A) + + +% a closer look at physiology +%-------------------------------------------------------------------------- +spm_figure('GetWin','Figure 2'); clf + +subplot(2,1,1) +t = 1:N; +plot(t,DEM.qU.x{1}(5:6,:)',t,t*0 + A.u,':'), hold on +plot(t,DEM.qU.x{1}(7:10,:)','-.'), hold off +xlabel('time','Fontsize',14) +title('internal states','FontSize',16) +axis square, box off, set(gca,'XLim',[1 N]) + +subplot(2,2,3) +plot(t,DEM.qU.x{1}(5:6,:)',t,t*0 + A.u,':') +xlabel('time','Fontsize',14) +title('physiological states','FontSize',16) +axis square, box off, set(gca,'XLim',[1 N]) + +subplot(2,2,4) +plot(DEM.pU.x{1}(5,:),DEM.pU.x{1}(6,:)), hold on +plot([A.u 1],[A.u A.u],'-.r',[A.u A.u],[A.u 1],'-.r'), hold off +xlabel('time','Fontsize',14) +title('physiological states','FontSize',16) +axis square, box off, axis([-.1 1.2 -.1 1.2]) + + + +% look at the effect of precision on inference (cf Parkinson’s disease) +%========================================================================== + +% initialize states +%-------------------------------------------------------------------------- +DEM = spm_ADEM_update(DEM); + +% simulate exposure with different log-precisions on physical motion +%-------------------------------------------------------------------------- +WP = [4 2 0]; +if ~DEMO + for i = 1:length(WP) + DEM_P{i} = DEM; + W = [[1 1 1 1]*WP(i) [1 1]*6 [1 1 1 1]*4]; + DEM_P{i}.M(1).W = diag(exp(W)); + DEM_P{i} = spm_ADEM(DEM_P{i}); + end +end + +% Graphics - path and physiology +%-------------------------------------------------------------------------- +spm_figure('GetWin','Figure 3'); clf +for i = 1:3 + + % path + %---------------------------------------------------------------------- + spm_figure('GetWin','Figure 3'); + subplot(3,2,i*2 - 1) + spm_cost_SHC_path(DEM_P{i}.pU,A) + + % and physiology + %---------------------------------------------------------------------- + subplot(3,2,i*2) + plot(t,DEM_P{i}.pU.x{1}(5:6,:)',t,t*0 + A.u,':'), hold on + plot(t,sum(DEM_P{i}.pU.x{1}(1:2,:).^2)/8,'m:'), hold off + xlabel('time','Fontsize',12) + title(sprintf('%s (%1.0f)','physiological states',WP(i)),'FontSize',16) + axis square, box off, set(gca,'XLim',[1 N]) + drawnow + +end + +% Graphics - action and prediction error +%-------------------------------------------------------------------------- +spm_figure('GetWin','Figure 4'); clf +for i = 1:3 + + % path + %---------------------------------------------------------------------- + subplot(3,2,2*i - 1) + plot(t,DEM_P{i}.qU.a{2}) + xlabel('time','FontSize',12) + title('action','FontSize',16) + axis square, box off, set(gca,'XLim',[1 N]) + if i == 1; a = axis; end, axis(a) + + % and prediction error + %---------------------------------------------------------------------- + subplot(3,2,2*i) + plot(t,DEM_P{i}.qU.z{1}(1:4,:)) + xlabel('time','FontSize',12) + title('sensory error','FontSize',16) + axis square, box off, set(gca,'XLim',[1 N]) + if i == 1; aa = axis; end, axis(aa) + drawnow +end + +% Learning (at different levels of precision on physiological motion) +%========================================================================== + +% Switch attractor for second physiological state and log-precision levels +%-------------------------------------------------------------------------- +spm_figure('GetWin','DEM'); clf +A.q = [1 3]; +WA = [4 8 12]; + +if ~DEMO + + for i = 1:length(WA) + + % Enable learning + %------------------------------------------------------------------ + A.u = 0; + DEM_L{i} = DEM; + DEM_L{i}.M(1).pC = exp(8); + W = [[1 1 1 1]*4 [1 1]*WA(i) [1 1 1 1]*4]; + DEM_L{i}.M(1).W = diag(exp(W)); + DEM_L{i} = spm_ADEM(DEM_L{i}); + + + % replace prior with posterior and re-expose + %------------------------------------------------------------------ + A.u = 1/8; + DEM_D{i} = DEM_L{i}; + DEM_D{i}.M(1).pE = DEM_D{i}.qP.P{1}; + DEM_D{i}.M(1).pC = []; + DEM_D{i} = spm_ADEM(DEM_D{i}); + + end + + % save DEM structures for future demonstrations + %---------------------------------------------------------------------- + try + save -v7 DEM_addiction DEM DEM_P DEM_L DEM_D + catch + save DEM_addiction DEM DEM_P DEM_L DEM_D + end + +end + + +% Graphics - optimal learning +%-------------------------------------------------------------------------- +spm_figure('GetWin','Figure 5'); clf +spm_DEM_qP(DEM_L{1}.qP) + +spm_figure('GetWin','Figure 5'); +subplot(2,2,3) +spm_cost_SHC_path(DEM.pU,A) +title('Before','Fontsize',16) +subplot(2,2,4) +spm_cost_SHC_path(DEM_D{1}.pU,A) +title('After','Fontsize',16) +drawnow + + +% Comparison of learning over levels of log-precisions (cf. Addiction) +%========================================================================== +spm_figure('GetWin','Figure 6'); clf + +for i = 1:3 + + % path + %---------------------------------------------------------------------- + subplot(3,2,i*2 - 1) + spm_cost_SHC_path(DEM_D{i}.pU,A) + title('After','FontSize',16) + + % and physiology + %---------------------------------------------------------------------- + subplot(3,2,i*2) + spm_plot_ci(DEM_L{i}.qP.P{1}(:),DEM_L{i}.qP.C) + xlabel('parameter','FontSize',12) + title(sprintf('%s (%1.0f)','learning',WA(i)),'FontSize',16) + axis square, box off + +end +drawnow + +% and physiology +%-------------------------------------------------------------------------- +spm_figure('GetWin','Figure 7'); clf +for i = 1:3 + + % predicted motion of second physiological state + %---------------------------------------------------------------------- + for j = 1:N + x = DEM_L{i}.qU.x{1}(:,j); + f = spm_cost_SHC_fx(spm_unvec(x,M(1).x),M(2).v,M(1).pE); + p(j) = DEM_L{i}.qU.w{1}(6,j) + f.q(2); + x = DEM_L{i}.pU.x{1}(:,j); + f = spm_cost_SHC_fxa(spm_unvec(x,G(1).x),M(2).v,G(2).a,G(1).pE); + q(j) = f.q(2); + end + subplot(3,2,2*i - 1) + plot(t,p,t,q,'b:') + xlabel('time','FontSize',12) + title(sprintf('%s (%1.0f)','predicted motion',WA(i)),'FontSize',16) + axis square, box off, set(gca,'XLim',[1 N]) + if i == 1; a = axis; end, axis(a) + + subplot(3,2,2*i) + plot(t,DEM_L{i}.qU.w{1}(6,:)) + xlabel('time','FontSize',12) + title('prediction error','FontSize',16) + axis square, box off, set(gca,'XLim',[1 N]) + if i == 1; aa = axis; end, axis(aa) + +end +drawnow \ No newline at end of file diff --git a/toolbox/DEM/ADEM_learning.m b/toolbox/DEM/ADEM_learning.m index 76fddc3..da2a783 100644 --- a/toolbox/DEM/ADEM_learning.m +++ b/toolbox/DEM/ADEM_learning.m @@ -12,12 +12,13 @@ % The result is a behavioural policy that reproduces exactly the policies % that are optimised by reinforcement learning and dynamic programming. % Critically, at no point do we need to invoke the notion of reward, value -% or utility. We illustrate these points by solving a benchmark problem in -% dynamic programming; namely the mountain-car problem using just the -% free-energy principle. The ensuing proof of concept is important because -% the free-energy formulation also provides a principled account of -% perceptual inference in the brain and furnishes a unified framework for -% action and perception. +% or utility. + +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: ADEM_learning.m 3901 2010-05-27 16:14:36Z karl $ % generative model @@ -167,14 +168,8 @@ DEM = spm_ADEM(DEM); save mountaincar_model G DEM end - load mountaincar_model -spm_figure('GetWin','DEM'); -spm_DEM_qP(DEM.qP,DEM.pP) -spm_DEM_qU(DEM.qU) - - % replace priors with learned conditional expectation %-------------------------------------------------------------------------- @@ -247,7 +242,7 @@ title('learnt','Fontsize',16) -spm_figure('GetWin','FMIN'); +spm_figure('GetWin','Movie'); clf, subplot(3,1,2) drawnow spm_mountaincar_movie(DEM) diff --git a/toolbox/DEM/ADEM_lorenz.m b/toolbox/DEM/ADEM_lorenz.m index 7a22537..ea334ca 100644 --- a/toolbox/DEM/ADEM_lorenz.m +++ b/toolbox/DEM/ADEM_lorenz.m @@ -13,7 +13,7 @@ G(1).E.s = 1/4; % smoothness G(1).E.n = 6; % smoothness G(1).E.d = 2; % smoothness -G(1).E.linear = 2; % bilinear +G(1).E.linear = 3; % nonlinear % dynamics @@ -142,10 +142,15 @@ save DEM_lorenz G DEM else + try load DEM_lorenz + catch + disp({'sorry; the previously prepared .mat file is not compatible'; + 'with your version of matlab - run this routine with DEMO = 1'}) + return + end end - spm_figure('GetWin','DEM'); spm_DEM_qP(DEM.qP,DEM.pP) spm_DEM_qU(DEM.qU) @@ -154,7 +159,7 @@ % replace priors with learned conditional expectation and plot %-------------------------------------------------------------------------- M = DEM.M; -M(1).E.linear = 2; % bilinear +M(1).E.linear = 3; % nonlinear spm_figure('GetWin','Graphics'); subplot(3,2,5) diff --git a/toolbox/DEM/ADEM_lorenz_entropy.m b/toolbox/DEM/ADEM_lorenz_entropy.m index 27bee20..a814a5d 100644 --- a/toolbox/DEM/ADEM_lorenz_entropy.m +++ b/toolbox/DEM/ADEM_lorenz_entropy.m @@ -6,16 +6,18 @@ % predict them and act to oppose the random effect. The result is that it % is more robust to random forces and therefore exhibits states with lower % entropy. +% +% THIS ROUTINE IS NOT RUN IN DEMO MODE AND WILL TAKE A CONSIDEABLE TIME. %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: ADEM_lorenz_entropy.m 3054 2009-04-07 19:22:49Z karl $ +% $Id: ADEM_lorenz_entropy.m 3977 2010-07-08 14:14:35Z karl $ % generative process (environment) %========================================================================== clear -DEMO = 0; +DEMO = 1; G(1).E.s = 1/4; % smoothness G(1).E.n = 6; % smoothness G(1).E.d = 2; % smoothness diff --git a/toolbox/DEM/ADEM_lorenz_surprise.m b/toolbox/DEM/ADEM_lorenz_surprise.m index 498e7f1..810a997 100644 --- a/toolbox/DEM/ADEM_lorenz_surprise.m +++ b/toolbox/DEM/ADEM_lorenz_surprise.m @@ -1,13 +1,19 @@ -% This demo computes the loss-function (negative reward) for a Lorenz -% system; to show reward can be computed easily from value (expected -% reward) +% This demo computes the cost-function (negative reward) for a Lorenz +% system; to show cost can be computed easily from value (negative +% surprise or sojourn time). However, value is not a Lyapunov function +% because the flow is not curl-free (i.e., is not irrotational). %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: ADEM_lorenz_surprise.m 3655 2009-12-23 20:15:34Z karl $ +% $Id: ADEM_lorenz_surprise.m 3884 2010-05-11 19:43:53Z karl $ + +% dynamics and parameters +%------------------------------------------------------------------------- +spm_figure('GetWin','Cost and surprise'); clear + DEMO = 0; % switch for demo LOR = 1; % Lorenz vs a linear system @@ -30,7 +36,7 @@ x0 = [-16; 16; 0]; W = diag([32; 32; exp(8)]); end - + % P(1): Prandtl number % P(2): 8/3 % P(3): Rayleigh number @@ -53,14 +59,15 @@ % space %-------------------------------------------------------------------------- +N = 66; if LOR - x{1} = linspace(-32,32,64); - x{2} = linspace(-32,32,64); - x{3} = linspace( 4,64,64); + x{1} = linspace(-32,32,N); + x{2} = linspace(-32,32,N); + x{3} = linspace( 4,64,N); else - x{1} = linspace(-8,8,64); - x{2} = linspace(-8,8,64); - x{3} = linspace(-1,1,3); + x{1} = linspace(-8,8,N); + x{2} = linspace(-8,8,N); + x{3} = linspace(-1,1,3); end % equilibrium density (q0), loss (L) and value (V) functions @@ -70,12 +77,12 @@ % Fokker-Planck operator and equilibrium density %---------------------------------------------------------------------- [M0,q0] = spm_fp(G,x); - + % loss-function and negative surprise (value) %---------------------------------------------------------------------- - L = -spm_unvec(spm_vec(log(q0))'*M0,q0); V = log(q0); - + L = spm_unvec(spm_vec(V)'*M0,q0); + % trim %---------------------------------------------------------------------- q0 = q0(2:end - 1,2:end - 1,2:end - 1); @@ -84,18 +91,17 @@ x{1} = x{1}(2:end - 1); x{2} = x{2}(2:end - 1); x{3} = x{3}(2:end - 1); - + if LOR save DEM_lorenz_suprise q0 L V x end else load DEM_lorenz_suprise end - - + + % axes and trajectory %-------------------------------------------------------------------------- -spm_figure('GetWin','Graphics'); clf if LOR z = 24; else @@ -104,7 +110,8 @@ i = 3; j = 1:3; j(i) = []; -U.u = sparse(1024,G(1).m); +T = 1024; +U.u = sparse(T,G(1).m); t = spm_int_J(G(1).pE,G,U); % surprise @@ -115,7 +122,7 @@ hold on, plot(t(:,j(2)),t(:,j(1)),'r'), hold off axis(a) axis square xy -title('surprise','Fontsize',16) +title('value','Fontsize',16) % cost function %-------------------------------------------------------------------------- @@ -124,7 +131,7 @@ hold on, plot(t(:,j(2)),t(:,j(1)),'r'), hold off axis(a) axis square xy -title('loss','Fontsize',16) +title('cost','Fontsize',16) % equilibrium density %-------------------------------------------------------------------------- @@ -142,3 +149,22 @@ axis(a) axis square xy title('trajectory','Fontsize',16) + +% evaluate V(t) +%-------------------------------------------------------------------------- +for i = 1:T + [q ii] = min(abs(t(i,1) - x{1})); + [q ij] = min(abs(t(i,2) - x{2})); + [q ik] = min(abs(t(i,3) - x{3})); + v(i) = V(ii,ij,ik); +end + +% and plot +%-------------------------------------------------------------------------- +maxV = max(V(:)); +subplot(3,1,3) +plot(v,'k'), hold on +plot([1 T],[maxV maxV],'r:'), hold off +title('value','Fontsize',16) +set(gca,'XLim',[1 T]); +box off diff --git a/toolbox/DEM/ADEM_mountaincar_loss.m b/toolbox/DEM/ADEM_mountaincar_loss.m new file mode 100644 index 0000000..aad45d0 --- /dev/null +++ b/toolbox/DEM/ADEM_mountaincar_loss.m @@ -0,0 +1,269 @@ +% This demo re-visits the mountain car problem to show that adaptive +% (desired) behaviour can be prescribed in terms of loss-functions (i.e. +% reward functions of state-space). +% It exploits the fact that under the free-energy formulation, loss is +% divergence. This means that priors can be used to make certain parts of +% state-space costly (i.e. with high divergence) and others rewarding (low +% divergence). Active inference under these priors will lead to sampling of +% low cost states and (apparent) attractiveness of those states. +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: ADEM_mountaincar_loss.m 3757 2010-03-08 11:41:53Z guillaume $ + +% generative process (mountain car terrain) +%========================================================================== % switch for demo +clear +DEMO = 0; + +% range of position for later plotting +%-------------------------------------------------------------------------- +dx = 1/64; +x = linspace(-2,2,1/dx); +xx = x.^2; + +% parameters of generative process +%-------------------------------------------------------------------------- +P.a = 0; +P.b = [0 0]; +P.c = [0 0 0 0]; +P.d = 0; % action off + +% level 1 +%-------------------------------------------------------------------------- +G(1).x = [0; 0]; +G(1).f = inline('spm_fx_mountaincar(x,v,a,P)/2','x','v','a','P'); +G(1).g = inline('x','x','v','a','P'); +G(1).pE = P; +G(1).V = exp(16); % error precision +G(1).W = exp(16); % error precision + +% level 2 +%-------------------------------------------------------------------------- +G(2).a = 0; % action +G(2).v = 0; % inputs +G(2).V = exp(16); +G = spm_ADEM_M_set(G); + + +% generative model +%========================================================================== +clear P + +% parameters and equations of motion +%-------------------------------------------------------------------------- +P.x = 0; +P.k = 1; +P.p = -1/2; +P.q = 0; + +% level 1 +%-------------------------------------------------------------------------- +M(1).x = [0; 0]; +M(1).f = inline('spm_mc_fx(x,v,P)/2','x','v','P'); +M(1).g = inline('x','x','v','P'); +M(1).pE = P; +M(1).V = exp(8); % error precision +M(1).W = exp(6); % error precision + +% level 2 +%-------------------------------------------------------------------------- +M(2).v = 0; % inputs +M(2).V = exp(16); +M = spm_DEM_M_set(M); + + +% learn gradients with a flat loss-functions (priors on divergence) +%========================================================================== +DEM.U = sparse(128,1); +DEM.C = sparse(128,1); +DEM.G = G; +DEM.M = M; + +if DEMO + + % enable learning by relaxing priors on parameters + %---------------------------------------------------------------------- + DEM.M(1).pC = diag([ones(1,2) zeros(1,2)])/128; + + % initialise states (randomly) and integrate + %---------------------------------------------------------------------- + for i = 1:8 + DEM.G(1).x = 4*rand(2,1) - 2; + DEM.M(1).x = DEM.G(1).x; + + DEM = spm_ADEM(DEM); + DEM.M(1).pE = DEM.qP.P{1}; + end +else + + % use previously optimised parameters + %---------------------------------------------------------------------- + DEM.M(1).pE.x = -0.2; + DEM.M(1).pE.k = 0.6; + +end + + +% plot results +%========================================================================== +DEM.G(1).x = [0; 1/2]; +DEM.M(1).x = DEM.G(1).x; +DEM = spm_ADEM(DEM); + +spm_figure('GetWin','Figure 1'); +spm_DEM_qU(DEM.qU) + +% true and inferred position +%-------------------------------------------------------------------------- +subplot(2,2,3) +plot(DEM.pU.x{1}(1,:),DEM.pU.x{1}(2,:)), hold on +plot(DEM.qU.x{1}(1,:),DEM.qU.x{1}(2,:),':'),hold off +xlabel('position','Fontsize',14) +ylabel('velocity','Fontsize',14) +title('trajectories','Fontsize',16) +axis([-1 1 -1 1]*2) +axis square + +% inferred potential +%-------------------------------------------------------------------------- +dGdx = spm_mc_loss_G(x,DEM.qP.P{1}); + +% real potential +%-------------------------------------------------------------------------- +dHdx = (x < 0).*(2*x + 1); +dHdx = (x > 0).*(1./(1 + 5*xx).^(1/2) - 5*xx./(1 + 5*xx).^(3/2) + (x/2).^4) + dHdx; +H = cumsum(dHdx)*dx; +G = cumsum(dGdx)*dx; +H = H - min(H); +G = G - min(G); + +subplot(2,2,4) +plot(x,H,x,G,'-.') +xlabel('position','FontSize',14) +ylabel('height','FontSize',14) +title('implicit potential','FontSize',16) +axis square +drawnow + + +% enable action and cost-priors +%========================================================================== + + +% enable action (disable learning) and integrate +%-------------------------------------------------------------------------- +DEM.G(1).pE.d = 1; +DEM.M(1).pE.p = 1/4; +DEM.M(1).pE.q = 32; +DEM.M(1).pC = []; +DEM = spm_ADEM(DEM); + + +% show trajectories +%========================================================================== + +% loss-functions or priors +%-------------------------------------------------------------------------- +c = spm_mc_loss_C(x,DEM.M(1).pE); +C = DEM.M(1).pE.p - DEM.M(1).pE.q*(1 - c); + +% for plotting +%-------------------------------------------------------------------------- +[Sx Sy Sz] = sphere; +S{1} = Sx/4 + 1; +S{2} = Sy/4 + 0; +S{3} = Sz/4 - 1; + +% inference +%-------------------------------------------------------------------------- +spm_figure('GetWin','Figure 2'); +spm_DEM_qU(DEM.qU) +subplot(2,2,4), hold on +plot(DEM.U,':'), hold off + +% true and inferred position +%-------------------------------------------------------------------------- +subplot(2,2,1) +% surf(S{1},S{2},S{3}), hold on +plot(1,0,'c.','MarkerSize',64), hold on +plot(DEM.pU.x{1}(1,:),DEM.pU.x{1}(2,:)) +plot(DEM.qU.x{1}(1,:),DEM.qU.x{1}(2,:),':'),hold off +xlabel('position','Fontsize',14) +ylabel('velocity','Fontsize',14) +title('trajectories','Fontsize',16) +axis([-1 1 -1 1]*2), shading interp +axis square + +% cost-functions +%-------------------------------------------------------------------------- +subplot(2,2,3) +plot(x,C) +xlabel('position','FontSize',14) +ylabel('force','FontSize',14) +title('priors (cost-function)','FontSize',16) +axis square +drawnow + + +% and a few more examples +%-------------------------------------------------------------------------- +for i = 1:4 + + % active inference + %---------------------------------------------------------------------- + DEM.G(1).x = rand(2,1) - 1/2; + DEM.M(1).x = DEM.G(1).x; + DEM = spm_ADEM(DEM); + + + % true and inferred position + %---------------------------------------------------------------------- + spm_figure('GetWin','Figure 2'); + subplot(2,2,1), hold on + plot(DEM.pU.x{1}(1,:),DEM.pU.x{1}(2,:),'Color',[0.8 0.8 1]) + + +end + +xlabel('position','Fontsize',14) +ylabel('velocity','Fontsize',14) +title('trajectories','Fontsize',16) +axis([-1 1 -1 1]*2) +axis square + +% illustrate different behaviours under different precisions +%========================================================================== + +% high and low exploration - attractiveness +%-------------------------------------------------------------------------- +spm_figure('GetWin','Figure 3'); clf +DEM.G(1).x = [0; -1/2]; +DEM.M(1).x = DEM.G(1).x; + +W = [2 4 6 8]; +for i = 1:4 + + % active inference + %---------------------------------------------------------------------- + DEM.M(1).W = exp(W(i)); + DEM = spm_ADEM(DEM); + + % true and inferred position + %---------------------------------------------------------------------- + spm_figure('GetWin','Figure 3'); + subplot(2,2,i) + + % surf(S{1},S{2},S{3}), hold on + plot(1,0,'c.','MarkerSize',64), hold on + plot(DEM.pU.x{1}(1,:),DEM.pU.x{1}(2,:)) + plot(DEM.qU.x{1}(1,:),DEM.qU.x{1}(2,:),':'),hold off + xlabel('position','Fontsize',14) + ylabel('velocity','Fontsize',14) + title(sprintf('%s (%i)','trajectories',W(i)),'Fontsize',16) + axis([-1 1 -1 1]*2), shading interp + axis square + +end + diff --git a/toolbox/DEM/ADEM_observe.m b/toolbox/DEM/ADEM_observe.m new file mode 100644 index 0000000..ea6f0d9 --- /dev/null +++ b/toolbox/DEM/ADEM_observe.m @@ -0,0 +1,382 @@ +% This demo illustrates action-observation using synthetics writing under +% active inference. It shows how expectations about hidden states can be +% both cause and consequence of observed action (of self and others +% respectively). We first illustrate the generation of behaviour using a +% Lotka-Volterra form stable heteroclinic orbit. We then reproduce the +% same forces on the agent’s arm but switching off the precision of +% proprioceptive inputs. This can be seen as attending selectively to +% visual inputs. The resulting inference calls upon the same hidden-states +% and implicit predictions (in a generalised or dynamic sense). These +% simulations can be regarded as simulations of mirror neuron responses. +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: ADEM_observe.m 3977 2010-07-08 14:14:35Z karl $ + + +% hidden causes and states +%========================================================================== +% x - hidden states +% x.x(1) - joint angle +% x.x(2) - joint angle +% x.x(3) - angular velocity +% x.x(4) - angular velocity +% +% x.a(1) - attraction (location 1) +% x.a(2) - attraction (location 2) +% x.a(3) - attraction (location 3) +% ... +% +% v - causal states +% v(1) - not used +% +%-------------------------------------------------------------------------- + + +% parameters mapping from (unstable) point attractors to visual space +%-------------------------------------------------------------------------- +P = [1.0 1.0; + 1.1 1.2; + 1.0 0.4; + 1.0 1.0; + 1.4 0.9; + 0.9 1.0]'; +n = size(P,2); % number of attractors + + + +% Recognition model (linear for expediency) +%========================================================================== +M(1).E.s = 1/2; % smoothness +M(1).E.n = 4; % order of +M(1).E.d = 2; % generalised motion + +% level 1: Displacement dynamics and mapping to sensory/proprioception +%-------------------------------------------------------------------------- +M(1).f = 'spm_fx_dem_observe'; % plant dynamics +M(1).g = 'spm_gx_dem_write'; % prediction + +M(1).x.x = [pi/2; pi/2; 0; 0]; % physical states +M(1).x.a = sparse(1,1,3,n,1) - 4; % attractor states +M(1).V = exp(4); % error precision +M(1).W = exp(8); % error precision +M(1).Ra = 1:4; % restriction +M(1).pE = P; + + +% level 2: not used +%-------------------------------------------------------------------------- +M(2).v = [0]; % inputs +M(2).V = exp(8); + +% generative model +%========================================================================== + +% first level +%-------------------------------------------------------------------------- +G(1).f = 'spm_fx_adem_write'; +G(1).g = 'spm_gx_adem_write'; +G(1).x = [pi/2; pi/2; 0; 0]; % physical states +G(1).V = exp(16); % error precision +G(1).W = exp(16); % error precision + +% second level +%-------------------------------------------------------------------------- +G(2).v = [0; 0]; % exogenous forces +G(2).a = [0; 0]; % action forces +G(2).V = exp(16); + + +% generate and invert +%========================================================================== +N = 256; % length of data sequence +t = [1:N]*8; +DEM.G = G; +DEM.M = M; +DEM.C = sparse(2,N); +DEM = spm_ADEM(DEM); + +% overlay true values +%-------------------------------------------------------------------------- +spm_figure('GetWin','Figure 1'); +spm_DEM_qU(DEM.qU,DEM.pU) + +subplot(2,2,3) +spm_dem_reach_movie(DEM) +title('click on finger for movie','FontSize',16) + + +% Action-observation +%========================================================================== +ADEM = DEM; +ADEM.C = DEM.qU.a{2}; +ADEM.M(1).V = diag(exp([-8 -8 -8 -8 8 8 8 8])); +ADEM.M(1).x.x = DEM.M(1).x.x; +ADEM.M(1).x.a = DEM.M(1).x.a*0; +ADEM = spm_ADEM(ADEM); + +spm_figure('GetWin','Figure 2'); +spm_DEM_qU(ADEM.qU,ADEM.pU) + +subplot(2,2,3) +spm_dem_reach_movie(ADEM) +title('click on finger for movie','FontSize',16) + + +% Hidden (intended) states lead actual states +%========================================================================== +spm_figure('GetWin','Figure 3'); + +n = 64; +p = exp(DEM.qU.x{1}(5:end,:)); +qx = P(end,:)*(p*diag(1./sum(p))); +px = DEM.pU.v{1}(end,:); + +subplot(2,1,1) +plot(t,px,t,qx,'-.') +legend({'attained','intended'}) +title('intended and attained position','FontSize',16) +xlabel('time') +ylabel('vertical displacement') +box off + +qx = qx - mean(qx); +px = px - mean(px); + +subplot(2,2,3) +xc = xcorr(qx,px,n,'coef'); +plot([0:(n + n)] - n,xc,[0 0],[-1 1],'k-.') +title('action','FontSize',16) +xlabel('time') +ylabel('cross-correlation') +axis square tight + + +% repeat for inferred hidden (intended) states +%-------------------------------------------------------------------------- +p = exp(ADEM.qU.x{1}(5:end,:)); +qx = P(end,:)*(p*diag(1./sum(p))); +px = ADEM.pU.v{1}(end,:); + +qx = qx - mean(qx); +px = px - mean(px); + +subplot(2,2,4) +xca = xcorr(qx,px,n,'coef'); +plot([0:(n + n)] - n,xca,[0:(n + n)] - n,xc,':',[0 0],[-1 1],'k-.') +title('observation','FontSize',16) +xlabel('time') +ylabel('cross-correlation') +axis square tight + + + +% coherence analysis +%========================================================================== +spm_figure('GetWin','Figure 4') + +T = 16; +xe = DEM.qU.w{1}(5:end,T:end); % prediction error on attractor states +ve = DEM.qU.z{1}(4:8,T:end); % prediction error on visual states +qx = full(sum(xe)); % synthetic LFP +qv = full(sum(ve)); % synthetic LFP +px = DEM.pU.v{1}(1,T:end); % peripheral (plant motion) + +% coherence analysis +%-------------------------------------------------------------------------- +qx = spm_detrend(qx',2); +px = spm_detrend(px',2); + +[Cqp,Hz] = mscohere(qx,px,64,48,[],1/0.008); +[Cxv,Hz] = mscohere(qx,qv,64,48,[],1/0.008); + + +subplot(2,1,1) +plot(t(T:end),xe,'r',t(T:end),ve,'b'); hold on +plot(t(T:end),px/8,'g','LineWidth',4); hold off +title('central and peripheral responses','FontSize',16) +xlabel('time (ms)') +ylabel('activity (au)') +axis tight + +subplot(2,2,3) +plot(Hz,Cqp) +title('central-peripheral coherence','FontSize',16) +xlabel('frequency (Hz)') +ylabel('coherence') +axis square +axis([0 32 0 1]) + +subplot(2,2,4) +plot(Hz,Cxv) +title('central-central coherence','FontSize',16) +xlabel('frequency (Hz)') +ylabel('coherence') +axis square +axis([0 32 0 1]) + + +% functional correlates +%========================================================================== +spm_figure('GetWin','Figure 5'); + +% under action +%-------------------------------------------------------------------------- +x = DEM.pU.v{1}(7,:); +y = DEM.pU.v{1}(8,:); + +u = DEM.qU.x{1}(8,:); +i = find(u > 2); + +subplot(2,2,1) +plot(x,y,'LineWidth',4,'Color',[1 1 1]*.8), hold on +plot(x(i),y(i),'r.','MarkerSize',24), hold off +title('action','FontSize',16) +xlabel('position (x)') +ylabel('position (y)') +axis square + +x = x + ([1:N] - N)/N; + +subplot(2,2,3) +plot(x,y,'LineWidth',4,'Color',[1 1 1]*.8), hold on +plot(x(i),y(i),'r.','MarkerSize',24), hold off +title('action','FontSize',16) +xlabel('position (x)') +ylabel('position (y)') +axis square ij + + +% and observation +%-------------------------------------------------------------------------- +x = ADEM.pU.v{1}(7,:); +y = ADEM.pU.v{1}(8,:); + +u = ADEM.qU.x{1}(8,:); +i = find(u > 2); + +subplot(2,2,2) +plot(x,y,'LineWidth',4,'Color',[1 1 1]*.8), hold on +plot(x(i),y(i),'r.','MarkerSize',24), hold off +title('observation','FontSize',16) +xlabel('position (x)') +ylabel('position (y)') +axis square + +x = x + ([1:N] - N)/N; + +subplot(2,2,4) +plot(x,y,'LineWidth',4,'Color',[1 1 1]*.8), hold on +plot(x(i),y(i),'r.','MarkerSize',24), hold off +title('observation','FontSize',16) +xlabel('position (x)') +ylabel('position (y)') +axis square ij + + +% Correlations between action and observation responses +%========================================================================== +spm_figure('GetWin','Figure 6'); + +qx = DEM.qU.x{1}; +px = ADEM.qU.x{1}; + +subplot(2,1,1) +bar3(spm_en(px',0)'*spm_en(qx',0)) +title('correlations','FontSize',16) +xlabel('hidden unit (observation)') +ylabel('hidden unit (action)') +grid off + +% last hidden state +%-------------------------------------------------------------------------- +qx = DEM.qU.x{1}(end,:); +px = ADEM.qU.x{1}(end,:); + +subplot(2,2,3) +plot(px,qx,'.') +title('correlations','FontSize',16) +xlabel('hidden unit (observation)') +ylabel('hidden unit (action)') +box off +axis square + +qx = spm_en(qx',0); +px = spm_en(px',0); + +subplot(2,2,4) +xc = xcorr(qx,px,n,'coef'); +plot([0:(n + n)] - n,xc,[0 0],[-1 1],'k-.') +title('action','FontSize',16) +xlabel('time') +ylabel('cross-correlation') +axis square tight + + + +% Simulated ERP +%========================================================================== + +% simulate omission +%-------------------------------------------------------------------------- +T = 132; +C = DEM.qU.a{2}; +C(:,T:end) = -C(:,T:end); +NDEM = ADEM; +NDEM.C = C; +NDEM = spm_ADEM(NDEM); + + +% Graphics +%-------------------------------------------------------------------------- +spm_figure('GetWin','Figure 7'); +t = ([1:N] - T)*8; +i = find(t > -256 & t < 512); + +subplot(3,2,1) +spm_dem_reach_movie(ADEM) +title('observation','FontSize',16) + +subplot(3,2,2) +spm_dem_reach_movie(NDEM) +title('violation','FontSize',16) + + +% Proprioceptive prediction error +%-------------------------------------------------------------------------- +subplot(3,2,4) +plot(t(i),NDEM.qU.z{1}(1:4,i)'), hold on +plot(t(i),ADEM.qU.z{1}(1:4,i)',':'), hold off +title('proprioceptive error','FontSize',16) +xlabel('time') +ylabel('prediction error') +axis square +a = axis; + +subplot(3,2,3) +plot(t(i),ADEM.qU.z{1}(1:4,i)') +title('proprioceptive error','FontSize',16) +xlabel('time') +ylabel('prediction error') +axis square +axis(a); + +% Hidden state prediction error +%-------------------------------------------------------------------------- +subplot(3,2,6) +plot(t(i),NDEM.qU.w{1}(:,i)'), hold on +plot(t(i),ADEM.qU.w{1}(:,i)',':'), hold off +title('error on hidden states','FontSize',16) +xlabel('time') +ylabel('prediction error') +axis square +a = axis; + +subplot(3,2,5) +plot(t(i),ADEM.qU.w{1}(:,i)') +title('error on hidden states','FontSize',16) +xlabel('time') +ylabel('prediction error') +axis square +axis(a); diff --git a/toolbox/DEM/ADEM_reaching.m b/toolbox/DEM/ADEM_reaching.m index d91573d..edd3fff 100644 --- a/toolbox/DEM/ADEM_reaching.m +++ b/toolbox/DEM/ADEM_reaching.m @@ -6,14 +6,27 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: ADEM_reaching.m 3058 2009-04-09 18:17:53Z karl $ - +% $Id: ADEM_reaching.m 3893 2010-05-17 18:28:52Z karl $ + +% hidden causes and states +%========================================================================== +% x - hidden states +% x(1) - joint angle +% x(2) - joint angle +% x(3) - angular velocity +% x(4) - angular velocity +% v - causal states +% v(1) - target location (x) +% v(2) - target location (y) +% v(3) - force (cue strength) +%-------------------------------------------------------------------------- + clear % Recognition model (linear for expediency) %========================================================================== M(1).E.s = 1/2; % smoothness -M(1).E.n = 6; % order of +M(1).E.n = 4; % order of M(1).E.d = 2; % generalised motion % level 1: Displacement dynamics and mapping to sensory/proprioception @@ -52,9 +65,9 @@ %========================================================================== N = 64; % length of data sequence C = sparse(3,N); -C(1,:) = C(1,:) + .6; -C(2,:) = C(2,:) + .6; -C(3,:) = exp(-([1:N] - 32).^2/(8.^2)); % this is the prior cause +C(1,:) = C(1,:) + .6; % desired x +C(2,:) = C(2,:) + .6; % desired y +C(3,:) = exp(-([1:N] - 32).^2/(8.^2)); % cue strength M(2).v = C(:,1); diff --git a/toolbox/DEM/ADEM_visual.m b/toolbox/DEM/ADEM_visual.m index ee86c3f..e358110 100644 --- a/toolbox/DEM/ADEM_visual.m +++ b/toolbox/DEM/ADEM_visual.m @@ -12,13 +12,13 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: ADEM_visual.m 3655 2009-12-23 20:15:34Z karl $ +% $Id: ADEM_visual.m 3695 2010-01-22 14:18:14Z karl $ % recognition model (M) %========================================================================== clear -M(1).E.s = 1/4; % smoothness +M(1).E.s = 1/2; % smoothness M(1).E.n = 6; % smoothness M(1).E.d = 2; % smoothness diff --git a/toolbox/DEM/ADEM_writing.m b/toolbox/DEM/ADEM_writing.m new file mode 100644 index 0000000..e59bb80 --- /dev/null +++ b/toolbox/DEM/ADEM_writing.m @@ -0,0 +1,114 @@ +% This demo illustrates how action can fulfill prior expectations by +% explaining away sensory prediction errors prescribed by desired movement +% trajectories. In this example a two-joint arm follows a stable +% heteroclinic channel, prescribed by a set of fixed point attractors. The +% locations of the successive (autovitiated) attractors are defined by +% parameters. The ensuing trajectories are illustrated here in terms of +% synthetic writing. +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: ADEM_writing.m 3901 2010-05-27 16:14:36Z karl $ + + +% hidden causes and states +%========================================================================== +% x - hidden states +% x.x(1) - joint angle +% x.x(2) - joint angle +% x.x(3) - angular velocity +% x.x(4) - angular velocity +% +% x.a(1) - attraction (location 1) +% x.a(2) - attraction (location 2) +% x.a(3) - attraction (location 3) +% ... +% +% v - causal states +% v(1) - not used +% +%-------------------------------------------------------------------------- +clear DEM + +% parameters (locations) of trajectory +%-------------------------------------------------------------------------- +P = [1.0 1.0; + 1.1 1.2; + 1.0 0.4; + 1.0 1.0; + 1.2 0.9; + 1.0 0.7; + 0.9 0.8; + 1.3 1.0]'; +n = size(P,2); + + +% Recognition model (linear for expediency) +%========================================================================== +M(1).E.s = 1/2; % smoothness +M(1).E.n = 4; % order of +M(1).E.d = 2; % generalised motion + +% level 1: Displacement dynamics and mapping to sensory/proprioception +%-------------------------------------------------------------------------- +M(1).f = 'spm_fx_dem_write'; % plant dynamics +M(1).g = 'spm_gx_dem_write'; % prediction + +M(1).x.x = [pi/2; pi/2; 0; 0]; % physical states +M(1).x.a = -[1:n]'/64; % attractor states +M(1).pE = P; % parameters of trajectory +M(1).V = exp(8); % error precision +M(1).W = exp(8); % error precision + + +% level 2: not used +%-------------------------------------------------------------------------- +M(2).v = [0]; % inputs +M(2).V = exp(8); + +% generative model +%========================================================================== + +% first level +%-------------------------------------------------------------------------- +G(1).f = 'spm_fx_adem_write'; +G(1).g = 'spm_gx_adem_write'; +G(1).x = [pi/2; pi/2; 0; 0;]; % physical states +G(1).V = exp(16); % error precision +G(1).W = exp(16); % error precision + +% second level +%-------------------------------------------------------------------------- +G(2).v = [0; 0]; % exogenous forces +G(2).a = [0; 0]; % action forces +G(2).V = exp(16); + + +% generate and invert +%========================================================================== +N = 64; % length of data sequence +DEM.G = G; +DEM.M = M; +DEM.C = sparse(2,N); +DEM = spm_ADEM(DEM); + +% overlay true values +%-------------------------------------------------------------------------- +spm_DEM_qU(DEM.qU,DEM.pU) + + +% Graphics +%========================================================================== +spm_figure('GetWin','Graphics'); +clf + +subplot(2,1,1) +spm_dem_reach_plot(DEM) +title('trajectory','FontSize',16) + +subplot(2,1,2) +spm_dem_reach_movie(DEM) +title('click on finger for movie','FontSize',16) + + diff --git a/toolbox/DEM/DEM_addiction.mat b/toolbox/DEM/DEM_addiction.mat new file mode 100644 index 0000000..ed4c900 Binary files /dev/null and b/toolbox/DEM/DEM_addiction.mat differ diff --git a/toolbox/DEM/DEM_demo.fig b/toolbox/DEM/DEM_demo.fig index b447981..85be7ca 100644 Binary files a/toolbox/DEM/DEM_demo.fig and b/toolbox/DEM/DEM_demo.fig differ diff --git a/toolbox/DEM/DEM_demo.m b/toolbox/DEM/DEM_demo.m index 6dc1889..377fe1a 100644 --- a/toolbox/DEM/DEM_demo.m +++ b/toolbox/DEM/DEM_demo.m @@ -22,7 +22,7 @@ % Edit the above text to modify the response to help DEM_demo -% Last Modified by GUIDE v2.5 13-May-2009 17:43:40 +% Last Modified by GUIDE v2.5 26-May-2010 19:20:30 % Begin initialization code - DO NOT EDIT gui_Singleton = 1; @@ -102,6 +102,11 @@ function pushbutton51_Callback(hObject, eventdata, handles) handles = guidata(1); set(handles.pushbutton51,'String','run demo') +% --- Executes on button press in pushbutton93. +function pushbutton93_Callback(hObject, eventdata, handles) +try + edit(handles.file); +end % --- Executes on button press in pushbutton1. function pushbutton1_Callback(hObject, eventdata, handles) @@ -205,7 +210,7 @@ function pushbutton49_Callback(hObject, eventdata, handles) % --- Executes on button press in pushbutton50. function pushbutton50_Callback(hObject, eventdata, handles) -run_demo_Callback(hObject, handles, 'ADEM_mountaincar_loss_3') +run_demo_Callback(hObject, handles, 'ADEM_mountaincar_loss') % --- Executes on button press in pushbutton80. function pushbutton80_Callback(hObject, eventdata, handles) @@ -215,3 +220,31 @@ function pushbutton80_Callback(hObject, eventdata, handles) function pushbutton81_Callback(hObject, eventdata, handles) run_demo_Callback(hObject, handles, 'ADEM_lorenz_surprise') +% --- Executes on button press in pushbutton83. +function pushbutton83_Callback(hObject, eventdata, handles) +run_demo_Callback(hObject, handles, 'DEM_demo_LAP') + +% --- Executes on button press in pushbutton84. +function pushbutton84_Callback(hObject, eventdata, handles) +run_demo_Callback(hObject, handles, 'DEM_demo_hdm_LAP') + +% --- Executes on button press in pushbutton91. +function pushbutton91_Callback(hObject, eventdata, handles) +run_demo_Callback(hObject, handles, 'DEM_demo_Posner') + +% --- Executes on button press in pushbutton92. +function pushbutton92_Callback(hObject, eventdata, handles) +run_demo_Callback(hObject, handles, 'ADEM_cost_SHC') + +% --- Executes on button press in pushbutton94. +function pushbutton94_Callback(hObject, eventdata, handles) +run_demo_Callback(hObject, handles, 'DEM_demo_CM_Lorenz') + +% --- Executes on button press in pushbutton95. +function pushbutton95_Callback(hObject, eventdata, handles) +run_demo_Callback(hObject, handles, 'ADEM_writing') + +% --- Executes on button press in pushbutton96. +function pushbutton96_Callback(hObject, eventdata, handles) +run_demo_Callback(hObject, handles, 'ADEM_observe') + diff --git a/toolbox/DEM/DEM_demo_CM_Lorenz.m b/toolbox/DEM/DEM_demo_CM_Lorenz.m new file mode 100644 index 0000000..a121a15 --- /dev/null +++ b/toolbox/DEM/DEM_demo_CM_Lorenz.m @@ -0,0 +1,180 @@ +% Demo for phase-space reduction (cf. Centre-Manifold theory): In this +% example we show that Generalised filtering can be used to approximate the +% dynamics on the Centre-Manifold of a chaotic system. This example uses a +% nominal polynomial for the reduced dynamics (cf, order parameters) and +% exploits parameter optimisation to learn their coefficients. The approach +% appeals to Centre Manifold Theory and the enslaving principle by assuming +% that stable modes collapse sufficiently quickly to be treated as random +% fluctuations. This means that the unstable (slow modes or patterns) +% dynamics are sufficient to characterise the emergent order (e.g. pattern +% formation) and can be accessed using a generative model that tries to +% explain observed motion in terms of a few hidden states (i.e. order +% parameters) that implicitly enslave random fluctuations. +% +% THIS DEMO IS UNDER CONSTRUCTION + + +% non-hierarchical non-linear generative model (dynamic & chaotic) +%========================================================================== +Fgraph = spm_figure('GetWin','Graphics'); +clear M + +% get model parameters and initial states +%-------------------------------------------------------------------------- +x = [4 4 28]'; +P.A = [-10 10 0; + 32 -1 0; + 0 0 -8/3]; +P.B{1} = [ 0 0 0; + 0 0 -1; + 0 1 0]; +P.B{2} = [ 0 0 0; + 0 0 0; + 0 0 0]; +P.B{3} = [ 0 0 0; + 0 0 0; + 0 0 0]; +P.C = {}; + +V.A = [ 1 1 1; + 1 1 1; + 1 1 1]; +V.B{1} = [ 1 1 1; + 1 1 1; + 1 1 1]; +V.B{2} = [ 0 1 1; + 0 1 1; + 0 1 1]; +V.B{3} = [ 0 0 1; + 0 0 1; + 0 0 1]; +V.C = {}; +pE = spm_unvec(spm_vec(P)/2,P); +pC = diag(spm_vec(V)); + +% level 1 +%-------------------------------------------------------------------------- +M(1).f = inline('spm_fx_poly(x,v,P)/32','x','v','P'); +M(1).g = inline('x','x','v','P'); +M(1).x = x; +M(1).pE = P; +M(1).V = exp(8); +M(1).W = exp(8); + +% level 2 +%-------------------------------------------------------------------------- +M(2).v = 0; +M(2).V = exp(16); + +% create data +%========================================================================== + +% create innovations & add causes +%-------------------------------------------------------------------------- +N = 128; +U = sparse(1,N); +DEM = spm_DEM_generate(M,U); +spm_DEM_qU(DEM.pU) + + +% DEM estimation +%========================================================================== +DEM.M(1).E.n = 4; +DEM.M(1).E.s = 1/8; +DEM.M(1).pE = pE; +DEM.M(1).pC = pC*exp(0); +DEM = spm_DEM(DEM); + +M(1).pE = DEM.qP.P{1}; +SIM = spm_DEM_generate(M,U); + + +% graphics +%-------------------------------------------------------------------------- +figure(Fgraph) + +spm_DEM_qU(SIM.pU) + +subplot(2,2,3) +x = DEM.pU.x{1}; +plot(x(1,:),x(2,:)) +title('true manifold dynamics') +xlabel('time') +axis square + +subplot(2,2,4) +x = SIM.pU.x{1}; +plot(x(1,:),x(2,:)) +title('estimated dynamics') +xlabel('time') +axis square + + +return + +% Notes for creation of a globally coupled map +%========================================================================== + + +% Demo of synchronization manifold using coupled Lorenz attractors +%-------------------------------------------------------------------------- +clear + +W = 2; % amplitude of random fluctuations +N = 16; % number of (Lorenz) oscillators +T = 512; % number of time bins +dt = 1/32; % time interval + +% parameters (set s.d. P.t to 1/4 to see oscillator death) +%-------------------------------------------------------------------------- +P.t = randn(N,1)/16; % variations in log-rate constants +P.k = 2; % global coupling parameter + +% states +%-------------------------------------------------------------------------- +x = randn(3,N)*8; % microstates +x(1,:) = x(1,:) + 0; +x(2,:) = x(2,:) + 0; +x(3,:) = x(3,:) + 28; +v = 0; + + +% integrate +%-------------------------------------------------------------------------- +for i = 1:T + + [dfdx f] = spm_diff('spm_lorenz_k',x,v,P,1); + f = f + randn(N*3,1)*W; + dx = spm_dx(dfdx,f,dt); + x = x + spm_unvec(dx,x); + y(:,i) = x(:); % microstates + X(:,i) = mean(x,2); % macrostates + +end + +% plot +%-------------------------------------------------------------------------- +subplot(2,1,1) +plot(y',':'), hold on +plot(X','k'), hold off +axis tight + +t = T/4:T; +subplot(2,1,2) +plot(X(1,t),X(2,t),'k') +axis square +axis([-16 16 -16 16]) + +return + +% plot synchronisation manifold +%-------------------------------------------------------------------------- +clf +subplot(2,1,1) +for i = 1:12 + plot(y(i*3 - 2,t),y(i*3 + 1,t),'.','Color',[1 1/2 1/2]),hold on +end +plot(X(1,t),X(1,t),'.k'),hold off +axis square +axis([-16 16 -16 16]) + \ No newline at end of file diff --git a/toolbox/DEM/DEM_demo_DEM.m b/toolbox/DEM/DEM_demo_DEM.m index 5f4661e..841db5c 100644 --- a/toolbox/DEM/DEM_demo_DEM.m +++ b/toolbox/DEM/DEM_demo_DEM.m @@ -27,7 +27,7 @@ % generate data and invert %========================================================================== -M(1).E.nN = 32; % DEM-steps +M(1).E.nN = 16; % DEM-steps N = 32; % length of data sequence U = exp(-([1:N] - 12).^2/(2.^2)); % this is the Gaussian cause DEM = spm_DEM_generate(M,U,{P},{8,32},{32}); diff --git a/toolbox/DEM/DEM_demo_EM.m b/toolbox/DEM/DEM_demo_EM.m index 3489952..ef730a9 100644 --- a/toolbox/DEM/DEM_demo_EM.m +++ b/toolbox/DEM/DEM_demo_EM.m @@ -148,7 +148,7 @@ EP(:,i) = eP; QH(i) = DEM.qH.h{1}(1); - EH(i) = S(1); + EH(i) = -exp(S(1)); end clf diff --git a/toolbox/DEM/DEM_demo_LAP.m b/toolbox/DEM/DEM_demo_LAP.m new file mode 100644 index 0000000..4b9a26f --- /dev/null +++ b/toolbox/DEM/DEM_demo_LAP.m @@ -0,0 +1,160 @@ +% This demonstration compares Generalised filtering under the Laplace +% assumption (spm_LAP) with variational filtering under the same fixed form +% approximation (i.e. DEM). We use a simple linear convolution model to +% illustrate the differences and similarities. The key difference between +% the two schemes lies (in this example) lies in estimates of conditional +% uncertainty. spm_LAP is must less over-confident because it eschews the +% means-field approximation implicit in DEM. The demonstration addresses +% quadruple estimation of hidden states, exogenous input, parameters and +% log-precisions (and, for spm_LAP, log-smoothness) +%__________________________________________________________________________ +% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: DEM_demo_LAP.m 3878 2010-05-07 19:53:54Z karl $ + +% get basic convolution model +%========================================================================== +M = spm_DEM_M('convolution model'); + +% gradient functions for speed (not implemented here) +%-------------------------------------------------------------------------- +% M(1).fx = inline('P.f','x','v','P'); +% M(1).fv = inline('P.h','x','v','P'); +% M(1).gx = inline('P.g','x','v','P'); +% M(1).gv = inline('sparse(4,1)','x','v','P'); + +% free parameters +%-------------------------------------------------------------------------- +P = M(1).pE; % true parameters +ip = [1 2 5 9]; % free parameters +pE = spm_vec(P); +np = length(pE); +pE(ip) = 0; +pE = spm_unvec(pE,P); +pC = sparse(ip,ip,32,np,np); +M(1).pE = pE; +M(1).pC = pC; + +% free hyperparameters +%-------------------------------------------------------------------------- +M(1).Q = {speye(M(1).l,M(1).l)}; +M(1).R = {speye(M(1).n,M(1).n)}; +M(1).hE = 4; +M(1).gE = 4; +M(1).hC = 1/2; +M(1).gC = 1/2; +M(1).V = 0; +M(1).W = 0; + +% generate data and invert +%========================================================================== +M(1).E.nN = 24; % number of time steps +M(1).E.nD = 1; % number of time steps +M(1).E.s = 1/4; % smoothness +M(1).E.d = 2; % order +M(1).E.n = 4; % order + +N = 32; % length of data sequence +U = exp(-([1:N] - 12).^2/(2.^2)); % this is the Gaussian cause +DEM = spm_DEM_generate(M,U,{P},{8,16},{6}); + + +% invert +%========================================================================== +spm_figure('GetWin','DEM'); +LAP = spm_LAP(DEM); +DEM = spm_DEM(DEM); + +% Show results for DEM +%========================================================================== +spm_figure('GetWin','Figure 1: DEM - mean-field assumption'); + +% overlay true values +%-------------------------------------------------------------------------- +spm_DEM_qU(DEM.qU,DEM.pU) + +% parameters +%-------------------------------------------------------------------------- +qP = spm_vec(DEM.qP.P); +qP = qP(ip); +tP = spm_vec(DEM.pP.P); +tP = tP(ip); + +subplot(2,2,4) +bar([tP qP]) +axis square +legend('true','DEM') +title('parameters','FontSize',16) + +cq = 1.64*sqrt(diag(DEM.qP.C(ip,ip))); +for i = 1:length(qP),hold on + plot([i i] + 1/8,qP(i) + [-1 1]*cq(i),'LineWidth',4,'color','r') +end, hold off + + +% Show results for LAP +%========================================================================== +spm_figure('GetWin','Figure 2: Generalised filtering (GF)'); + +% overlay true values +%-------------------------------------------------------------------------- +spm_DEM_qU(LAP.qU,LAP.pU) + +% parameters +%-------------------------------------------------------------------------- +qP = spm_vec(LAP.qP.P); +qP = qP(ip); +tP = spm_vec(LAP.pP.P); +tP = tP(ip); + +subplot(2,2,4) +bar([tP qP]) +axis square +legend('true','GF') +title('parameters','FontSize',16) + +cq = 1.64*sqrt(diag(LAP.qP.C(ip,ip))); +for i = 1:length(qP),hold on + plot([i i] + 1/8,qP(i) + [-1 1]*cq(i),'LineWidth',4,'color','r') +end, hold off + +% Compare +%========================================================================== +spm_figure('GetWin','Figure 3: Comparison of DEM and GF'); + +% hyperparameters +%-------------------------------------------------------------------------- +qL = spm_vec({LAP.qH.h LAP.qH.g}); +qD = spm_vec({DEM.qH.h DEM.qH.g}); +vL = spm_vec({LAP.qH.V LAP.qH.W}); +vD = spm_vec({DEM.qH.V DEM.qH.W}); +qh = spm_vec({DEM.pH.h{1} DEM.pH.g{1}}); + + +subplot(2,2,1) +bar([qh qL qD]) +axis square +legend('true','GF','DEM') +title('log-precisions','FontSize',16) + +cq = 1.64*sqrt(vL); +for i = 1:length(qL),hold on + plot([i i] + 0,qL(i) + [-1 1]*cq(i),'LineWidth',4,'color','r') +end, hold off + +cq = 1.64*sqrt(vD); +for i = 1:length(qD),hold on + plot([i i] + 1/4,qD(i) + [-1 1]*cq(i),'LineWidth',4,'color','r') +end, hold off + +% Log-evidence +%-------------------------------------------------------------------------- +subplot(2,2,2) +nL = length(LAP.F); +nD = length(DEM.F); +plot(1:nL,LAP.F,1:nD,DEM.F,1:nL,LAP.S,1:nD,DEM.S) +axis square +legend('GF (F)','DEM (F)','GF (S)','DEM(S)') +title('log-evidence ','FontSize',16) +xlabel('iteration','FontSize',12) diff --git a/toolbox/DEM/DEM_demo_Laplace.m b/toolbox/DEM/DEM_demo_Laplace.m new file mode 100644 index 0000000..47188ad --- /dev/null +++ b/toolbox/DEM/DEM_demo_Laplace.m @@ -0,0 +1,61 @@ + +% Notes for Laplace scheme and dynamic updating of parameters +%========================================================================== +n = 128; % number of samples (time bins) +P = 4; % true parameter +k = n; % precision on fluctuations +pp = 2; % prior on parameter +m = 8; % number of data +iS = eye(m,m)*2; % error precision +s = sqrtm(inv(iS)); + +p = [0;0]; % initial parameter estimates +for i = 1:n + + x = 4 + randn(m,1); % exogenous input + z = s*randn(m,1); % error + y = P*x + z; % response + e = y - p(1)*x; % prediction error + Lp = -e'*iS*x + pp*p(1); + Lpp = x'*iS*x + pp; + f = [p(2); (-Lp -k*p(2))]; + dfdx = [0 1; -Lpp -k]; + p = p + spm_dx(dfdx,f,1); + X(:,i) = p; + LP(i) = Lp; +end + +% results +%-------------------------------------------------------------------------- +subplot(2,1,1) +plot(1:n,X) +title('generalised parameter estimates','FontSize',16) + +subplot(2,1,2) +plot(1:n,LP) +title('energy gradient','FontSize',16) + + +return + +% Notes +%========================================================================== +M.f = inline('[x(2); (u - K(1)*x(2))]','x','u','K','M'); +M.m = 1; +M.n = 2; +M.l = 2; +M.x = [0;0]; +M.u = 0; + +N = 128; +dt = 1/64; +K = 4; +[K0,K1,K2] = spm_kernels(M,K,N,dt); + +subplot(2,1,1) +plot([1:N]*dt,K1); +xlabel('time (s)') +title('Kernels','FontSize',16) +legend('drive','trace') +axis square + diff --git a/toolbox/DEM/DEM_demo_MMN.m b/toolbox/DEM/DEM_demo_MMN.m index 45870f9..6146736 100644 --- a/toolbox/DEM/DEM_demo_MMN.m +++ b/toolbox/DEM/DEM_demo_MMN.m @@ -13,14 +13,9 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: DEM_demo_MMN.m 3655 2009-12-23 20:15:34Z karl $ - -% figure -%-------------------------------------------------------------------------- -spm_figure('GetWin','Graphics'); -clear; clf -colormap('pink') +% $Id: DEM_demo_MMN.m 3740 2010-02-26 13:13:14Z karl $ + % level 1 %-------------------------------------------------------------------------- M(1).m = 1; % 1 input or cause @@ -112,7 +107,7 @@ % gather trial specific parameters and precisions changes %---------------------------------------------------------------------- - spm_figure('GetWin','Graphics'); + spm_figure('GetWin','Figure 1'); subplot(n + 1,3,(i - 1)*3 + 3) dP{i} = spm_vec(DEM{i}.M(1).pE) - spm_vec(DEM{end}.M(1).pE); @@ -120,6 +115,7 @@ qR{i} = spm_DEM_EEG(DEM{i},dt,[1 2],1); % prediction error (LFP) qH(i) = DEM{i}.M(1).hE; % and precision drawnow + if i == 2, a = axis; end % plot recognition density and prediction %---------------------------------------------------------------------- @@ -134,11 +130,17 @@ axis square end - + +% scale axes and title +%-------------------------------------------------------------------------- +for i = 1:(n + 1) + subplot(n + 1,3,(i - 1)*3 + 3) + axis(a); + axis square +end subplot(n + 1,3,1),title('Hidden states','FontSize',16) subplot(n + 1,3,2),title('percept','FontSize',16) subplot(n + 1,3,3),title('prediction error','FontSize',16) - % Show song in DEM window %-------------------------------------------------------------------------- @@ -150,7 +152,7 @@ % Repetition effects %========================================================================== -spm_figure('GetWin','MFM'); +spm_figure('GetWin','Figure 2'); t = [1:N]*dt*1000; % Changes in Parameters @@ -174,6 +176,7 @@ % ERPs (precision weighted) prediction error %-------------------------------------------------------------------------- +spm_figure('GetWin','Figure 2'); for i = 1:n subplot(6,n,i + 2*n) @@ -205,16 +208,6 @@ xlabel('peristimulus time (ms)','FontSize',12) ylabel('Difference waveform','FontSize',12) axis square - -spm_figure('GetWin','Graphics'); -for i = 1:(n + 1) - - % gather trial specific parameters and precisions changes - %---------------------------------------------------------------------- - subplot(n + 1,3,(i - 1)*3 + 3) - axis(a); - axis square - -end + drawnow, disp(' '),disp('Click sonograms to play songs'),disp(' ') diff --git a/toolbox/DEM/DEM_demo_Posner.m b/toolbox/DEM/DEM_demo_Posner.m new file mode 100644 index 0000000..f4a181c --- /dev/null +++ b/toolbox/DEM/DEM_demo_Posner.m @@ -0,0 +1,305 @@ +% This demonstration routine simulates the Posner paradigm to show that +% some of the characteristic speed-accuracy trade-offs associated with +% valid and invalid cueing can be explained easily in terms of optimizing +% precisions during hierarchical inference. This demonstration uses +% generalised filtering and state-space model that includes state-dependent +% noise. Here, this dependency is used to set the attentional gain or bias +% using a cue, which modulates the prediction errors induced by subsequent +% targets. The phenomena that emerge from this scheme include a competition +% for attentional resources; given that only one context can exist at any +% time and this probabilistic context is encoded by state-dependent +% precisions on the causes of sensory input. Attended stimuli have greater +% precision and greater penetration of their prediction errors in the +% hierarchy. We will also see characteristic differences between perceptual +% inference, under valid and invalid cues. This is illustrated using +% simulated psychophysical and electrophysiological responses. Biased +% competition is simulated by presenting both valid and invalid targets +% simultaneously. + +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: DEM_demo_Posner.m 3740 2010-02-26 13:13:14Z karl $ +clear + + +% Create a generative model: To keep thing simple we will model just 2 +% target locations; on the left (invalid) and the right (valid). +%========================================================================== + +% set dimensions for generalised coordinates +%-------------------------------------------------------------------------- +G(1).E.d = 2; % approximation order +G(1).E.n = 4; % embedding order +G(1).E.s = 1/2; % temporal smoothness +G(1).E.method.x = 1; % state-dependent noise +G(1).E.sP = 1e6; % smoothness precision +N = 2; % number of stimuli (locations) + + +% level 1; with state-dependent variance +%-------------------------------------------------------------------------- +G(1).m = N + 1; % causes (inputs) +G(1).n = 2; % hidden states (context) +G(1).l = N + 1; % output channels (stimuli) +G(1).xP = 1/32; % prior precision on hidden state + + +G(1).f = inline('[1 -1 -2;-1 1 2]*v/4 - x/32','x','v','P'); +G(1).g = inline('v','x','v','P'); +G(1).V = exp(16); % error variances (noise) +G(1).W = exp(8); % error variances (states) + + +% level 2; causes +%-------------------------------------------------------------------------- +G(2).l = N + 1; % output channels (locations) +G(2).V = exp(16); + + +% state-dependent precision (attentional bias) in generative model (M): +%-------------------------------------------------------------------------- +M = G; +M(1).ph = inline('[2 + [1 -1;-1 1]*x; 4]','x','v','h','M'); +M(1).W = exp(4); % error variances (states) +M(1).V = []; +M(2).V = 0; + + +% Data (stimuli] are created by integrating the model for some input. The +% input here comprises cue and target stimuli modeled with bump (Gaussian) +% functions. +%========================================================================== + +% create inputs and cue +%-------------------------------------------------------------------------- +T = 64; % length of data sequence +dt = 640/T; % ms time bins; 512 ms trials +pst = [1:T]*dt; % peristimulus time (ms bins) +TS = spm_Npdf([1:T + 1],2*T/3,T/8); % this is the Gaussian target +CS = spm_Npdf([1:T],T/4,T/16); % this is the Gaussian cue +TS = diff(TS); +TS = TS/max(TS); +CS = CS/max(CS); + +% valid target (right) +%-------------------------------------------------------------------------- +V(N, :) = TS; +V(N + 1,:) = CS; + +% invalid target (left) +%-------------------------------------------------------------------------- +U(1, :) = TS; +U(N + 1,:) = CS; + +% both targets +%-------------------------------------------------------------------------- +B(1, :) = TS; +B(N, :) = TS; +B(N + 1,:) = CS; + + +% integrate G to obtain stimuli (DEM.Y) +%-------------------------------------------------------------------------- +LAPV = spm_DEM_generate(G,V); +LAPU = spm_DEM_generate(G,U); +LAPB = spm_DEM_generate(G,B); + + +% Filtering: Here. we expose the model M to the data and record the +% responses. The scheme is essentially a form of Variational Learning +% that provides an upper bound on perceptual inference and learning. +% We use this bound to simulate neuronal responses, under the assumption +% they are near-optimal. +%========================================================================== + +% place the generative model in LAP +%-------------------------------------------------------------------------- +LAPV.M = M; +LAPU.M = M; +LAPB.M = M; + +% simulate a valid trial +%========================================================================== +spm_figure('GetWin','DEM'); + +LAPV = spm_LAP(LAPV); + +spm_figure('GetWin','Figure 1'); +spm_DEM_qU(LAPV.qU,LAPV.pU) + + +% show stimulus and percept +%-------------------------------------------------------------------------- +subplot(2,2,4) +load Posner + +qU = LAPV.qU.v{2}; +for i = 1:length(qU) + image(64*spm_unvec(S.V*qU(:,i),S.F)) + axis image off + mov(i) = getframe; +end + +% set ButtonDownFcn for movie of perceived (inferred) stimuli +%-------------------------------------------------------------------------- +h = get(gca,'Children'); +set(h(1),'Userdata',{mov,T}) +set(h(1),'ButtonDownFcn','spm_DEM_ButtonDownFcn') +title({'conditional percept','click on image'},'FontSize',16) + + + +% simulate an invalid trial +%========================================================================== +spm_figure('GetWin','DEM'); + +LAPU = spm_LAP(LAPU); + +spm_figure('GetWin','Figure 2'); +spm_DEM_qU(LAPU.qU,LAPU.pU) + + +% compare targets with and without valid cues +%-------------------------------------------------------------------------- +subplot(2,2,4) + +spm_plot_ci(pst,LAPV.qU.v{2},LAPV.qU.C,2,'g'), hold on +spm_plot_ci(pst,LAPU.qU.v{2},LAPU.qU.C,1,'b'), hold off + +set(gca,'XLim',[pst(1) pst(end)]) +xlabel('time (ms)','FontSize',12) +title({'target responses with','valid and invalid cues'},'FontSize',16) +axis square +box off +drawnow + + +% Psychophysics - speed accuracy trade-off +%========================================================================== +spm_figure('GetWin','Figure 3'); + +% valid trial - evaluate p(v > q,t|Y,M) using conditional density +%-------------------------------------------------------------------------- +q = 1/4; % threshold +c = [0 1 0]; % contrast (valid target) +E = LAPV.qU.v{2}; % conditional expectations +C = LAPV.qU.C; % conditional covariance + +% Conditional moments of time-averaged parameters +%-------------------------------------------------------------------------- +for i = 1:T + Ec = c*E(:,i); % Expectation of contrast + Cc = c*C{i}*c'; % Covariance of contra + PV(i) = 1 - spm_Ncdf(q,Ec,Cc); % Posterior p(Ec > q) +end + +% Repeat for invalid trial +%-------------------------------------------------------------------------- +c = [1 0 0]; % contrast (invalid target) +E = LAPU.qU.v{2}; % conditional expectations +C = LAPU.qU.C; % conditional covariance +for i = 1:T + Ec = c*E(:,i); % Expectation of contrast + Cc = c*C{i}*c'; % Covariance of contra + PU(i) = 1 - spm_Ncdf(q,Ec,Cc); % Posterior p(Ec > q) +end + +% Graphics +%-------------------------------------------------------------------------- +subplot(2,1,1) +plot(pst,100*PV,pst,100*PU,'-.',pst,TS*100,':') + +[m i] = max(PU); +set(gca,'XLim',[pst(T/2) pst(i)]) +xlabel('peristimulus time (ms)','FontSize',12) +ylabel('posterior confidence that target is present','FontSize',12) +title({'speed-accuracy trade-off'},'FontSize',16) +axis square +box off +legend('valid','invalid','true intensity') +drawnow + +% Biased competition +%========================================================================== +spm_figure('GetWin','DEM'); + +% simulate dual presentation +%-------------------------------------------------------------------------- +LAPB = spm_LAP(LAPB); + +spm_figure('GetWin','Figure 4'); +spm_DEM_qU(LAPB.qU,LAPB.pU) + + +% compare non-attended stimulus with and without attended stimulus +%-------------------------------------------------------------------------- +subplot(2,2,4) + +spm_plot_ci(pst,LAPB.qU.v{2},LAPB.qU.C,1,'b-.'), hold on +spm_plot_ci(pst,LAPU.qU.v{2},LAPU.qU.C,1,'b'), hold off + +set(gca,'XLim',[pst(1) pst(end)]) +xlabel('time (ms)','FontSize',12) +title({'unattended stimulus','with and without attended'},'FontSize',16) +axis square +box off +drawnow + +% Electrophysiology +%========================================================================== + +% plot the simulated ERPs (see spm_DEM_ERP) +%-------------------------------------------------------------------------- +spm_figure('GetWin','Figure 5'); clf +color = {'r','b'}; +qU = {LAPU.qU,LAPV.qU}; +PST = pst - T*dt/3; +for i = 1:length(qU) + + + % loop over levels + %---------------------------------------------------------------------- + for j = 1:2 + + % PST (assuming 32 ms times bins) + %------------------------------------------------------------------ + try + EEG = qU{i}.Z{j}(1:2,:); + catch + EEG = qU{i}.z{j}(1:2,:); + end + + % ERPs + %------------------------------------------------------------------ + subplot(2,2,1) + plot(PST,EEG,'Color',color{i}),hold on + end + title('LFPs (Causal) Content','FontSize',16) + xlabel('pst (ms)') + axis square + set(gca,'XLim',[PST(1) PST(end)]) + + % Hidden states + %------------------------------------------------------------------ + j = 1; + try + EEG = qU{i}.W{j}(2,:); + catch + EEG = qU{i}.w{j}(2,:); + end + + % ERPs + %------------------------------------------------------------------ + subplot(2,2,2) + plot(PST,EEG,'Color',color{i}),hold on + title('LFPs (Hidden) Context','FontSize',16) + xlabel('pst (ms)') + axis square + set(gca,'XLim',[PST(1) PST(end)]) + +end + +legend('invalid','valid') +drawnow diff --git a/toolbox/DEM/DEM_demo_filtering.m b/toolbox/DEM/DEM_demo_filtering.m index cdab8f5..00716dd 100644 --- a/toolbox/DEM/DEM_demo_filtering.m +++ b/toolbox/DEM/DEM_demo_filtering.m @@ -13,7 +13,7 @@ %-------------------------------------------------------------------------- M(1).E.s = 1/32; M(1).E.nD = 4; -M(1).E.linear = 2; +M(1).E.linear = 3; % model specification - 1st level %-------------------------------------------------------------------------- diff --git a/toolbox/DEM/DEM_demo_hdm_LAP.m b/toolbox/DEM/DEM_demo_hdm_LAP.m new file mode 100644 index 0000000..06e5709 --- /dev/null +++ b/toolbox/DEM/DEM_demo_hdm_LAP.m @@ -0,0 +1,220 @@ +% Demo for Hemodynamic deconvolution: Cross-validation of Laplace scheme +%__________________________________________________________________________ +% This demonstration compares generalised filtering and DEM in the context +% of a nonlinear convolution model using empirical data. These are the data +% used to illustrate hemodynamic deconvolution. We have deliberately made +% the problem difficult here to highlight the ability of Generalised +% filtering to accumulate evidence to optimise in parameters and hyper- +% parameters, which allows it to outperform DEM (although it does not +% find visual motion effects with 90% confidence) +%__________________________________________________________________________ +% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: DEM_demo_hdm_LAP.m 3901 2010-05-27 16:14:36Z karl $ + +% set-up +%-------------------------------------------------------------------------- +clear +DEMO = 1; + +if DEMO + + spm_figure('GetWin','DEM'); + load HDM + + % level 1 + %---------------------------------------------------------------------- + + % generative [likelihood] model 'HDM' + %====================================================================== + dt = Y.dt; + T = 1:256; + + % level 1 + %---------------------------------------------------------------------- + [pE pC] = spm_hdm_priors(3,1); + P = pE; + P(7:9) = 1/8; + M(1).x = [0 0 0 0]'; + M(1).g = 'spm_gx_hdm'; + M(1).f = 'spm_fx_hdm'; + M(1).pE = pE; + M(1).pC = pC; + M(1).gE = 7; + M(1).gC = 1/2; + M(1).V = exp(4); + + % level 2 + %---------------------------------------------------------------------- + M(2).v = [0 0 0]'; + M(2).V = exp(4); + + M(1).E.linear = 1; + M(1).E.n = 4; + M(1).E.nD = 1; + M(1).E.nN = 8; + M(1).E.s = 1/4; + + % get causes (i.e. experimental inputs) + %---------------------------------------------------------------------- + t = fix(linspace(1,length(U.u),360)); + U = U.u(t(T),:)'; + + % Emprical data + %---------------------------------------------------------------------- + DEM.M = M; + DEM.U = U; + DEM.Y = 1/2 + Y.y(T,:)'/8; + + % DEM estimation + %====================================================================== + LAP = spm_LAP(DEM); + DEM = spm_DEM(DEM); + + save LAP_HDM LAP DEM + +else % load pre-computed LAP and DEM structures + + load LAP_HDM +end + + + +% report states and parameter estimates +%========================================================================== + +% LAP +%-------------------------------------------------------------------------- +spm_figure('GetWin','Figure 2: Generalised filtering (Laplace) '); + +spm_DEM_qU(LAP.qU) + +% Coupling parameters of interest +%-------------------------------------------------------------------------- +subplot(2,2,4) + +qP = LAP.qP.P{1}(7:end); +bar(qP,'Edgecolor',[1 1 1]/2,'Facecolor',[1 1 1]*.8) +cq = 1.64*sqrt(diag(LAP.qP.C(7:end,7:end))); +hold on +for i = 1:length(qP) + plot([i i], qP(i) + [-1 1]*cq(i),'LineWidth',8,'color','r') +end +hold off +axis square +set(gca,'XTickLabel',{'vision','motion','attention'}) +title('parameters','Fontsize',16) +a = axis; + +% DEM +%-------------------------------------------------------------------------- +spm_figure('GetWin','Figure 1: With mean-field approximation (DEM) '); + +spm_DEM_qU(DEM.qU) + + +% Coupling parameters of interest +%-------------------------------------------------------------------------- +subplot(2,2,4) + +qP = DEM.qP.P{1}(7:end); +bar(qP,'Edgecolor',[1 1 1]/2,'Facecolor',[1 1 1]*.8) +cq = 1.64*sqrt(diag(DEM.qP.C(7:end,7:end))); +hold on +for i = 1:length(qP) + plot([i i], qP(i) + [-1 1]*cq(i),'LineWidth',8,'color','r') +end +hold off +axis square +set(gca,'XTickLabel',{'vision','motion','attention'}) +title('parameters','Fontsize',16) +axis(a) + + +% Log-evidence +%-------------------------------------------------------------------------- +spm_figure('GetWin','Figure 3: log-evidence'); + +subplot(2,1,1) +nL = length(LAP.F); +nD = length(DEM.F); +plot(1:nL,LAP.F,1:nD,DEM.F) +axis square +legend('LAP (F)','DEM(F)') +title('log-evidence','FontSize',16) + + +return + + +% and a more detailed look +%-------------------------------------------------------------------------- +spm_figure('GetWin','Figure 4: Hemodynamics'); + + +t = 1:128; +subplot(2,1,1) +hold on +bar(full(LAP.U(2,t)*8),'FaceColor',[1 1 1]*.8,'EdgeColor',[1 1 1]*.8) +plot(t,exp(LAP.qU.x{1}(:,t))) +set(gca,'YLim',[-0.1 1.6]) +xlabel('time (bins)','Fontsize',12) +title('hidden states','Fontsize',16) +legend({'visual stimulation','signal','flow','volume','dHb'}) +hold off + +% (mixture of) causes +%-------------------------------------------------------------------------- +qP = LAP.qP.P{1}(7:end); + +subplot(2,1,2) +hold on +plot(t,qP'*LAP.qU.v{2}(:,t)) +a = axis; +bar(full(LAP.U(2,t)),'FaceColor',[1 1 1]*.8,'EdgeColor',[1 1 1]*.8) +plot(t,qP'*LAP.qU.v{2}(:,t)) +axis(a) +xlabel('time (bins)','Fontsize',12) +title('neuronal causes','Fontsize',16) +hold off + + +return + + +% Notes for simulating responses (to examine dependency on +% hemodynamic parameters quantitatively) +%========================================================================== + +% get causes (i.e. experimental inputs) +%-------------------------------------------------------------------------- +T = 128; +P = [ + 0.9874 + 0.3501 + 1.6845 + 0.3452 + 0.3564 + -0.1719 + 0.0000 + 0.2 + 0.0000]; + +P = [ + 0.6500 + 0.4100 + 2.0000 + 0.3200 + 0.3400 + -.0 + 0 + .16 + 0]; + + +% Simulate data +%-------------------------------------------------------------------------- +DEM = spm_DEM_generate(M,U(:,1:T),{P},{4,8},{6}); +spm_DEM_qU(DEM.pU) + diff --git a/toolbox/DEM/DEM_lorenz_entropy.mat b/toolbox/DEM/DEM_lorenz_entropy.mat deleted file mode 100644 index 4c3806c..0000000 Binary files a/toolbox/DEM/DEM_lorenz_entropy.mat and /dev/null differ diff --git a/toolbox/DEM/DFP_demo_hdm.m b/toolbox/DEM/DFP_demo_hdm.m index 48c3f47..7af6687 100644 --- a/toolbox/DEM/DFP_demo_hdm.m +++ b/toolbox/DEM/DFP_demo_hdm.m @@ -11,7 +11,7 @@ % generative [likelihood] model 'HDM' %========================================================================== -G(1).E.linear = 0; +G(1).E.linear = 1; G(1).E.s = 1/2; dt = Y.dt; T = 1:128; diff --git a/toolbox/DEM/LAP_DEM.mat b/toolbox/DEM/LAP_DEM.mat new file mode 100644 index 0000000..56fa08f Binary files /dev/null and b/toolbox/DEM/LAP_DEM.mat differ diff --git a/toolbox/DEM/LAP_HDM.mat b/toolbox/DEM/LAP_HDM.mat new file mode 100644 index 0000000..0f28ee7 Binary files /dev/null and b/toolbox/DEM/LAP_HDM.mat differ diff --git a/toolbox/DEM/Posner.mat b/toolbox/DEM/Posner.mat new file mode 100644 index 0000000..612365d Binary files /dev/null and b/toolbox/DEM/Posner.mat differ diff --git a/toolbox/DEM/mountaincar_model.mat b/toolbox/DEM/mountaincar_model.mat index b94ee79..57823ea 100644 Binary files a/toolbox/DEM/mountaincar_model.mat and b/toolbox/DEM/mountaincar_model.mat differ diff --git a/toolbox/DEM/spm_DEM_ButtonDownFcn.m b/toolbox/DEM/spm_DEM_ButtonDownFcn.m index 6cd30e4..e853310 100644 --- a/toolbox/DEM/spm_DEM_ButtonDownFcn.m +++ b/toolbox/DEM/spm_DEM_ButtonDownFcn.m @@ -8,7 +8,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_DEM_ButtonDownFcn.m 1861 2008-06-27 13:28:10Z karl $ +% $Id: spm_DEM_ButtonDownFcn.m 3774 2010-03-11 19:20:11Z karl $ % default %-------------------------------------------------------------------------- @@ -18,27 +18,34 @@ % play movie %---------------------------------------------------------------------- movie(S{1},1,S{2}); - return - % save avi file - %---------------------------------------------------------------------- - [FILENAME, PATHNAME] = uiputfile('*.avi','movie file'); - NAME = fullfile(PATHNAME,FILENAME); - movie2avi(S{1},NAME,'compression','none') + if strcmp(get(gcf,'SelectionType'),'normal') + return + else + % save avi file + %------------------------------------------------------------------ + [FILENAME, PATHNAME] = uiputfile('*.avi','movie file'); + NAME = fullfile(PATHNAME,FILENAME); + movie2avi(S{1},NAME,'compression','none') + end else % play sound %---------------------------------------------------------------------- soundsc(S{1},S{2}); - return - % save wav file - %---------------------------------------------------------------------- - [FILENAME, PATHNAME] = uiputfile('*.wav','wave file'); - NAME = fullfile(PATHNAME,FILENAME); - S{1} = S{1}/max(S{1}(:)); - wavwrite(S{1},S{2},16,NAME) + if strcmp(get(gcf,'SelectionType'),'normal') + return + else + + % save wav file + %------------------------------------------------------------------ + [FILENAME, PATHNAME] = uiputfile('*.wav','wave file'); + NAME = fullfile(PATHNAME,FILENAME); + S{1} = S{1}/max(S{1}(:)); + wavwrite(S{1},S{2},16,NAME) + end end diff --git a/toolbox/DEM/spm_DEM_ERP_demo.m b/toolbox/DEM/spm_DEM_ERP_demo.m index bc8718f..9db6bf3 100644 --- a/toolbox/DEM/spm_DEM_ERP_demo.m +++ b/toolbox/DEM/spm_DEM_ERP_demo.m @@ -110,15 +110,16 @@ F(i) = DEM.F; % record the free energy attained end -% plot the simulated ERPs (see spm_DEM_ERP) +% plot the simulated ERPs (see spm_dem_ERP) %-------------------------------------------------------------------------- -spm_figure -R = spm_DEM_ERP(qU{:}); +spm_figure('GetWin','Figure 1'); +R = spm_dem_ERP(qU{:}); % plot the mean responses, (over time bins) over repetitions and both % cortical levels %-------------------------------------------------------------------------- -spm_figure +spm_figure('GetWin','Figure 2'); + subplot(3,1,1),bar(-F), title('Free Energy'),axis square subplot(3,1,2),bar(R{1} - 1),title('Lower area'), axis square subplot(3,1,3),bar(R{2} - 1),title('Higher area'),axis square @@ -127,7 +128,8 @@ % plot the stimulus and the percept (i.e. prediction at the lowest level) % before and after learning (i.e., for the first and last presentation) %-------------------------------------------------------------------------- -spm_figure +spm_figure('GetWin','Figure 3'); + Y = qU{1}.v{1} + qU{1}.z{1}; subplot(3,1,1),imagesc(Y),title('Sensation'), axis image subplot(3,1,2),imagesc(qU{1}.v{1}), title('First percept'),axis image diff --git a/toolbox/DEM/spm_DEM_M.m b/toolbox/DEM/spm_DEM_M.m index b0fdb9d..9289733 100644 --- a/toolbox/DEM/spm_DEM_M.m +++ b/toolbox/DEM/spm_DEM_M.m @@ -257,8 +257,8 @@ % correlations %-------------------------------------------------------------------------- - M(1).E.linear = 2; - M(1).E.s = 1/8; + M(1).E.linear = 3; + M(1).E.s = 1/8; % level 1 %-------------------------------------------------------------------------- diff --git a/toolbox/DEM/spm_DEM_movie.m b/toolbox/DEM/spm_DEM_movie.m index 882aa7b..0f9127b 100644 --- a/toolbox/DEM/spm_DEM_movie.m +++ b/toolbox/DEM/spm_DEM_movie.m @@ -5,7 +5,7 @@ % qU - conditional moments of states (see spm_DEM) or v % S - .mat file or structure containing % S.V - image modes (V) -% S.F - image template (format) +% S.F - image template (format, for spm_unvec) % % M - movie array % FPS - Frames per second (Hz) @@ -15,7 +15,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_DEM_movie.m 2921 2009-03-23 17:59:50Z guillaume $ +% $Id: spm_DEM_movie.m 3715 2010-02-08 13:57:26Z karl $ % load image modes %-------------------------------------------------------------------------- @@ -25,7 +25,7 @@ FPS = 32; end try - S.P; + S.F; catch try S = load(file); @@ -41,7 +41,6 @@ % get parameters %========================================================================== -Np = size(S.U,2); % order of basis set Nc = size(S.V,1); % number of channels Nm = size(S.V,2); % number of modes Nf = size(U,2); % number of frames @@ -62,8 +61,8 @@ %========================================================================== set(gca,'units','pixels') position = get(gca,'position'); -position(3) = size(S.F,2); -position(4) = size(S.F,1); +position(3) = size(S.F,2)*.8; +position(4) = size(S.F,1)*.8; set(gca,'position',position); set(gca,'units','normalized'); imagesc(M(1).cdata); @@ -74,5 +73,3 @@ h = get(gca,'Children'); set(h(1),'Userdata',{M,FPS}) set(h(1),'ButtonDownFcn','spm_DEM_ButtonDownFcn') - - diff --git a/toolbox/DEM/spm_DEM_play_song.m b/toolbox/DEM/spm_DEM_play_song.m index 3818771..e1892fe 100644 --- a/toolbox/DEM/spm_DEM_play_song.m +++ b/toolbox/DEM/spm_DEM_play_song.m @@ -13,7 +13,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_DEM_play_song.m 1703 2008-05-21 13:59:23Z karl $ +% $Id: spm_DEM_play_song.m 3715 2010-02-08 13:57:26Z karl $ % load frequency modes %-------------------------------------------------------------------------- @@ -48,7 +48,7 @@ % resample temporal modes %-------------------------------------------------------------------------- for i = 1:Nm - V(i,:) = interp(v(i,:),R); + V(i,:) = spm_interp(v(i,:),R); end % create sonogram sound diff --git a/toolbox/DEM/spm_cost_SHC_fx.m b/toolbox/DEM/spm_cost_SHC_fx.m new file mode 100644 index 0000000..c79b9e8 --- /dev/null +++ b/toolbox/DEM/spm_cost_SHC_fx.m @@ -0,0 +1,50 @@ +function [f] = spm_cost_SHC_fx(x,v,P) +% equations of motion for foraging problem using SHCs +% problem +% FORMAT [f] = spm_cost_SHC_fx(x,v,P) +% +% x - hidden states (x.x, x.v x.q and x.a) +% v - exogenous inputs +% P - parameters +% +% The parameters associate increases in some physiological states x.q with +% positions in physical space, encoded by radial basis functions x.a +%__________________________________________________________________________ +% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: spm_cost_SHC_fx.m 3757 2010-03-08 11:41:53Z guillaume $ + + + +% location and radius of attractors A +%-------------------------------------------------------------------------- +global A; X = A.x; + +% gradient of Hamiltonian (G) is determined by the attractor state x.a +%-------------------------------------------------------------------------- +[m,i] = max(x.a); +G = x.x - X(:,i); + +% motion of physical states +%-------------------------------------------------------------------------- +f = x; +f.x = x.v; +f.v = -G*8 - x.v*4; + +% motion of physiological states (using basis functions of position) +%-------------------------------------------------------------------------- +for i = 1:size(X,2) + b(i,1) = norm(x.x - X(:,i)) < A.d; +end + +f.q = P'*b - x.q/2; +f.a = P*(x.q < A.u) - b*4 - sum(x.a); + +% flow +%-------------------------------------------------------------------------- +dt = 1/8; +f.x = f.x*dt; +f.v = f.v*dt; +f.q = f.q*dt; +f.a = f.a*dt; diff --git a/toolbox/DEM/spm_cost_SHC_fxa.m b/toolbox/DEM/spm_cost_SHC_fxa.m new file mode 100644 index 0000000..6384362 --- /dev/null +++ b/toolbox/DEM/spm_cost_SHC_fxa.m @@ -0,0 +1,43 @@ +function [f] = spm_cost_SHC_fxa(x,v,a,P) +% equations of motion for a foraging problem +% FORMAT [f] = spm_cost_SHC_fxa(x,v,a,P) +% +% x - hidden states +% v - exogenous inputs +% a - action +% P - parameters for mountain car +% +% returns f = dx/dt (see spm_cost_SHC_fx) +% These equations of motion model dissipative flow x.x and x.v on a flat +% potential and increases in physiological states x.q as radial basis +% functions of secrete locations. The agent has to discover these +% locations % using an appropriate policy. This generative process would +% also substitute for Morris water-maze simulations or unbounded saccades. +%__________________________________________________________________________ +% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: spm_cost_SHC_fxa.m 3757 2010-03-08 11:41:53Z guillaume $ + +% location and radius of attractors A (only A.q attractors deliver reward) +%-------------------------------------------------------------------------- +global A; X = A.x(:,A.q); + +% physical flow +%-------------------------------------------------------------------------- +f = x; +f.x = x.v; +f.v = a - x.x*2 - x.v*4; + +% physiological flow +%-------------------------------------------------------------------------- +for i = 1:size(X,2) + f.q(i) = (norm(x.x - X(:,i)) < A.d) - x.q(i)/2; +end + +% flow +%-------------------------------------------------------------------------- +dt = 1/8; +f.x = f.x*dt; +f.v = f.v*dt; +f.q = f.q*dt; diff --git a/toolbox/DEM/spm_cost_SHC_path.m b/toolbox/DEM/spm_cost_SHC_path.m new file mode 100644 index 0000000..a78f3fd --- /dev/null +++ b/toolbox/DEM/spm_cost_SHC_path.m @@ -0,0 +1,54 @@ +function spm_cost_SHC_path(qU,A) +% plots path for cost_SHC demo's +% FORMAT spm_cost_SHC_path(qU,A) +% +% qU - DEM condotioal esimates of states +% A.x - locations of attrcuor +% A.d - radius +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: spm_cost_SHC_path.m 3757 2010-03-08 11:41:53Z guillaume $ + +% plot +%========================================================================== +[X Y Z] = sphere; + +% plot path +%-------------------------------------------------------------------------- +x = qU.v{1}(1:2,:); +plot(A.x(1,:),A.x(2,:),'c.','MarkerSize',64), hold on +plot(x(1,:),x(2,:)); +plot(x(1,:),x(2,:),'.','MarkerSize',8); + +% plot locations +%-------------------------------------------------------------------------- +% for i = 1:size(A.x,2) +% surf(X*A.d + A.x(1,i),Y*A.d + A.x(2,i),Z*A.d - 8) +% end +% shading interp + + +axis([-4 4 -4 4]) +axis square +title('trajectory','FontSize',16),hold off + +% occupancy +%-------------------------------------------------------------------------- +for i = 1:size(A.x,2) + for j = 1:2 + d(j,:) = x(j,:) - A.x(j,i); + end + b(i,:) = sqrt(sum(d.^2)) < 2*A.d; +end + +% plot precent occupancy +%-------------------------------------------------------------------------- +p = 100*sum(b,2)/length(b); +for i = 1:length(p) + text(A.x(1,i)*2,A.x(2,i)*1.4,sprintf('%2.0f%%',p(i)),'Fontsize',12) +end +hold off + + diff --git a/toolbox/DEM/spm_cost_fx.m b/toolbox/DEM/spm_cost_fx.m new file mode 100644 index 0000000..70af6ad --- /dev/null +++ b/toolbox/DEM/spm_cost_fx.m @@ -0,0 +1,67 @@ +function [f] = spm_cost_fx(x,v,P) +% equations of motion for foragaing problem +% problem +% FORMAT [f] = spm_cost_fx(x,v,P) +% +% x - hidden states +% v - exogenous inputs +% P.p - parameters for gradient function: G(x(1),P.p) +% +% returns f = dx/dt = f = [x(2); +% G - x(2)*C]*dt; +% +% where C determines divergence of flow x(2) at any position x(1). +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: spm_cost_fx.m 3757 2010-03-08 11:41:53Z guillaume $ + + +% dominant physiological state +%-------------------------------------------------------------------------- +f = x; +[p i] = min([x.p; 1]); + +if i > length(x.p) + + A = [0;0]; + C = -1; + +else + + A = P.p(:,i); + q = x.q(i); + + % cost function + %---------------------------------------------------------------------- + u = 1/16; + C = (q < u)*1/8 - (q > u)*8; + +end + +% gradient of Hamiltonian (G) +%-------------------------------------------------------------------------- +k = 2; +G = (x.x - A)*k; + +% flow +%-------------------------------------------------------------------------- +f.x = x.v; +f.v = x.v*C - G; + +% physiological flow +%-------------------------------------------------------------------------- +d = 1/2; +for i = 1:size(P.p,2) + f.q(i) = (norm(x.x - P.p(:,i),'fro') < d) - x.q(i); + f.p(i) = x.q(i) - x.p(i)/8; +end + +dt = 1/8; +f.x = f.x*dt; +f.v = f.v*dt; +f.q = f.q*dt; +f.p = f.p*dt; + + diff --git a/toolbox/DEM/spm_cost_fxa.m b/toolbox/DEM/spm_cost_fxa.m new file mode 100644 index 0000000..69c5d38 --- /dev/null +++ b/toolbox/DEM/spm_cost_fxa.m @@ -0,0 +1,39 @@ +function [f] = spm_cost_fxa(x,v,a,P) +% equations of motion for a foraging problem +% problem +% FORMAT [f] = spm_cost_fxa(x,v,a,P) +% +% x - hidden states +% v - exogenous inputs +% a - action +% P - parameters for mountain car +% +% returns f = dx/dt +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: spm_cost_fxa.m 3757 2010-03-08 11:41:53Z guillaume $ + +% physical flow +%-------------------------------------------------------------------------- +dt = 1/8; +f = x; +f.x = x.v; +f.v = a - x.v/8; + +% physiological flow +%-------------------------------------------------------------------------- +d = 1/2; +for i = 1:size(P.p,2) + n = norm(x.x - P.p(:,i),'fro') < d; + f.q(i) = n - x.q(i)/2; + f.p(i) = x.q(i) - x.p(i)/8; +end + +f.x = f.x*dt; +f.v = f.v*dt; +f.q = f.q*dt; +f.p = f.p*dt; + + diff --git a/toolbox/DEM/spm_dem_ERP.m b/toolbox/DEM/spm_dem_ERP.m index 6e0548e..2209765 100644 --- a/toolbox/DEM/spm_dem_ERP.m +++ b/toolbox/DEM/spm_dem_ERP.m @@ -1,6 +1,6 @@ -function [R] = spm_DEM_ERP(varargin) +function [R] = spm_dem_ERP(varargin) % simulated electrophysiological response based on conditional estimates -% FORMAT [R] = spm_DEM_ERP(qU,qU,...) +% FORMAT [R] = spm_dem_ERP(qU,qU,...) % qU - conditional estimates of states % R - summed response over peri-stimulus time % @@ -16,34 +16,67 @@ %-------------------------------------------------------------------------- clf N = length(varargin); +color = {'r','b','g','y','c','m'}; for i = 1:N - qU = varargin{i}; - U = qU.z; % loop over ERPs %---------------------------------------------------------------------- - n = length(U); + qU = varargin{i}; + n = length(qU.z); for j = 1:n + % PST (assuming 8ms times bins) + %------------------------------------------------------------------ + try + EEG = qU.Z{j}; + catch + EEG = qU.z{j}; + end + T = (1:length(EEG))*32; + % ERPs %------------------------------------------------------------------ subplot(n,2,2*(j - 1) + 1) - plot(mean(U{j},1),'Color',[1 1 1]*(1 - 1/i)) - title(sprintf('LFPs: level %i',j)) + plot(T,mean(EEG,1),'Color',color{i}),hold on + plot(T,EEG,':','Color',color{i}) + title(sprintf('LFPs (Causal): level %i',j),'FontSize',16) + xlabel('pst (ms)') axis square - grid on - hold on + % PSTH %------------------------------------------------------------------ - subplot(n,2,2*j) - PSTH = mean(exp(U{j}) + exp(-U{j}),1)/2; + PSTH = mean(exp(EEG) + exp(-EEG),1)/2; R{j}(i) = mean(PSTH); - plot(PSTH,'Color',[1 1 1]*(1 - 1/i),'LineWidth',3) - title(sprintf('PSTH: level %i',j)) + + % subplot(n,2,2*j) + % plot(T,PSTH,color{i},'LineWidth',1) + % title(sprintf('PSTH: level %i',j),'FontSize',16) + % xlabel('pst (ms)') + % axis square + % hold on + + end + for j = 1:(n - 1) + + % PST (assuming 8ms times bins) + %------------------------------------------------------------------ + try + EEG = qU.W{j}; + catch + EEG = qU.w{j}; + end + T = (1:length(EEG))*32; + + % ERPs + %------------------------------------------------------------------ + subplot(n,2,2*(j - 1) + 2) + plot(T,mean(EEG,1),'Color',color{i}),hold on + plot(T,EEG,':','Color',color{i}) + title(sprintf('LFPs (Hidden): level %i',j),'FontSize',16) + xlabel('pst (ms)') axis square - hold on end diff --git a/toolbox/DEM/spm_dem_reach_movie.m b/toolbox/DEM/spm_dem_reach_movie.m index 452bc43..2f72c86 100644 --- a/toolbox/DEM/spm_dem_reach_movie.m +++ b/toolbox/DEM/spm_dem_reach_movie.m @@ -5,39 +5,53 @@ function spm_dem_reach_movie(DEM) % DEM - DEM structure from reaching simulations %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging - -% Karl Friston -% $Id: spm_dem_reach_movie.m 3113 2009-05-11 15:25:13Z karl $ -% evaluate positions -%-------------------------------------------------------------------------- -x = DEM.pU.x{1}; -v = DEM.pU.v{2}; +% Karl Friston +% $Id: spm_dem_reach_movie.m 3901 2010-05-27 16:14:36Z karl $ -C = v(3,:); % target color -T = [v(1,end); v(2,end)]; % target location -J = spm_dem_reach_x2J(x); % joint location -J{2} = J{1} + J{2}; % finger location -C = C - min(C); -C = C/max(C); +% evaluate positions (target) +%-------------------------------------------------------------------------- +try + v = DEM.pU.v{2}; + C = v(3,:); % target color + T = [v(1,end); v(2,end)]; % target location + C = C - min(C); + C = C/max(C); +end +% evaluate positions (motor plant) +%-------------------------------------------------------------------------- +x = DEM.pU.x{1}; % angular position +J = spm_dem_reach_x2J(x); % joint location +J{2} = J{1} + J{2}; % finger location fin = imread('finger.jpg'); N = size(x,2); % movie %-------------------------------------------------------------------------- s = 1/4; - for i = 1:N - + cla axis image ij hold on + + % arm + %---------------------------------------------------------------------- imagesc(([-2 0] + 1/3)*s + J{2}(1,i),([-1 0] + 1/2)*s + J{2}(2,i),fin); plot([0 J{1}(1,i)],[0 J{1}(2,i)],'color',[1 .8 .7]*.8) plot([J{1}(1,i) J{2}(1,i)],[J{1}(2,i) J{2}(2,i)],'color',[1 .8 .7]*.8) - plot(T(1),T(2),'.','MarkerSize',32,'color',[C(i) (1 - C(i)) 0]) + + % target (T) or scribe (moving trajectory) + %---------------------------------------------------------------------- + try + plot(T(1),T(2),'.','MarkerSize',32,'color',[C(i) (1 - C(i)) 0]) + catch + x = J{2}(1,1:i) + ([1:i] - i)/N; + y = J{2}(2,1:i); + plot(x,y,'color',[1 1 1]*.8,'Linewidth',4) + end axis([-0.5 1.5 0 2]) hold off drawnow @@ -45,7 +59,7 @@ function spm_dem_reach_movie(DEM) % save %---------------------------------------------------------------------- M(i) = getframe(gca); - + end % set ButtonDownFcn diff --git a/toolbox/DEM/spm_dem_reach_plot.m b/toolbox/DEM/spm_dem_reach_plot.m index 688adab..b21f685 100644 --- a/toolbox/DEM/spm_dem_reach_plot.m +++ b/toolbox/DEM/spm_dem_reach_plot.m @@ -7,7 +7,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_dem_reach_plot.m 3058 2009-04-09 18:17:53Z karl $ +% $Id: spm_dem_reach_plot.m 3901 2010-05-27 16:14:36Z karl $ % evaluate positions %-------------------------------------------------------------------------- @@ -23,14 +23,13 @@ % plot %-------------------------------------------------------------------------- hold on - +g = [1 1 1]*.8; for i = 1:N c = [1 .8 .7]*(1 - 0.2*i/N); plot([0 J{1}(1,i)],[0 J{1}(2,i)],'color',c) plot([J{1}(1,i) J{2}(1,i)],[J{1}(2,i) J{2}(2,i)],'color',c) end -plot(J{2}(1,:),J{2}(2,:),'k') -plot(J{1}(1,:),J{1}(2,:),'k') +plot(J{2}(1,:),J{2}(2,:),'LineWidth',2,'color',c/2) plot(J{2}(1,1),J{2}(2,1),'.r','MarkerSize',32) plot(J{2}(1,end),J{2}(2,end),'.g','MarkerSize',32) plot(T(1),T(2),'.r','MarkerSize',32) diff --git a/toolbox/DEM/spm_dem_reach_x2J.m b/toolbox/DEM/spm_dem_reach_x2J.m index c2c12df..bf5e293 100644 --- a/toolbox/DEM/spm_dem_reach_x2J.m +++ b/toolbox/DEM/spm_dem_reach_x2J.m @@ -3,13 +3,17 @@ % FORMAT [J] = spm_dem_reach_x2J(x) % % x - hidden states (joint angles) +% x - hidden states +% x(1) - joint angle +% x(2) - joint angle +% % J1 - position of 1st joint -% J2 - position of 2nd joint (relative to first +% J2 - position of 2nd joint (relative to first) %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_dem_reach_x2J.m 3054 2009-04-07 19:22:49Z karl $ +% $Id: spm_dem_reach_x2J.m 3893 2010-05-17 18:28:52Z karl $ % evaluate positions %-------------------------------------------------------------------------- diff --git a/toolbox/DEM/spm_fx_adem_reach.m b/toolbox/DEM/spm_fx_adem_reach.m index 2e4343f..350a72f 100644 --- a/toolbox/DEM/spm_fx_adem_reach.m +++ b/toolbox/DEM/spm_fx_adem_reach.m @@ -3,14 +3,18 @@ % FORMAT [f]= spm_fx_adem_reach(x,v,a,P) % % x - hidden states -% v - causal states -% a - action +% x(1) - joint angle +% x(2) - joint angle +% x(3) - angular velocity +% x(4) - angular velocity +% v - cue locations and strength +% a - action (forces) (x,y) % P - parameters %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_fx_adem_reach.m 3058 2009-04-09 18:17:53Z karl $ +% $Id: spm_fx_adem_reach.m 3893 2010-05-17 18:28:52Z karl $ % evaluate positions %-------------------------------------------------------------------------- diff --git a/toolbox/DEM/spm_fx_adem_write.m b/toolbox/DEM/spm_fx_adem_write.m new file mode 100644 index 0000000..0d8161d --- /dev/null +++ b/toolbox/DEM/spm_fx_adem_write.m @@ -0,0 +1,29 @@ +function [f]= spm_fx_adem_write(x,v,a,P) +% returns the flow for a two-joint arm (with action) +% FORMAT [f]= spm_fx_adem_reach(x,v,a,P) +% +% x - hidden states +% x(1) - joint angle +% x(2) - joint angle +% x(3) - angular velocity +% x(4) - angular velocity +% v - exogenous forces (x,y) +% a - action (forces) (x,y) +% P - parameters +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: spm_fx_adem_write.m 3893 2010-05-17 18:28:52Z karl $ + +% evaluate positions +%-------------------------------------------------------------------------- +m = [2 1]*2; % mass +k = [2 1]*4; % viscosity + +% flow +%========================================================================== +f = [x(3); + x(4); + (-k(1)*x(3) + a(1) + v(1) - (x(1) - pi/2)/4)/m(1); + (-k(2)*x(4) + a(2) + v(2) - (x(2) - pi/2)/4)/m(2)]; diff --git a/toolbox/DEM/spm_fx_dem_observe.m b/toolbox/DEM/spm_fx_dem_observe.m new file mode 100644 index 0000000..f7e101b --- /dev/null +++ b/toolbox/DEM/spm_fx_dem_observe.m @@ -0,0 +1,62 @@ +function [f]= spm_fx_dem_observe(x,v,P) +% returns the flow for a two-joint arm (writing with SHC) +% FORMAT [f]= spm_fx_dem_observe(x,v,P) +% +% x.x(1) - joint angle +% x.x(2) - joint angle +% x.x(3) - angular velocity +% x.x(4) - angular velocity +% +% x.a(1) - attraction (location 1) +% x.a(2) - attraction (location 2) +% x.a(3) - attraction (location 3) +% ... +% +% v - hidden states +% v(1) - not used +% P - parameters (locations of point attratcors in state-space) +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: spm_fx_dem_observe.m 3901 2010-05-27 16:14:36Z karl $ + +% motion of physical states +%========================================================================== + +% desired location (v) is determined by the attractor state x.a +%-------------------------------------------------------------------------- +n = length(x.a); +p = exp(2*x.a); +v = P*p/sum(p); + +% evaluate positions +%-------------------------------------------------------------------------- +J = spm_dem_reach_x2J(x.x); % joint location +F = (v - J{1} - J{2})/2; % force + + +% flow +%========================================================================== +m = [2 1]*2; % mass +k = [2 1]*4; % viscosity +e = 1/16; % elasticity +O = [0 -1 ; % orthogonal projector + 1 0]; +f.x = [x.x(3); + x.x(4); + (F'*J{2}*J{2}'*O*J{1} - k(1)*x.x(3) - (x.x(1) - pi/2)*e)/m(1); + ( F'*O*J{2} - k(2)*x.x(4) - (x.x(2) - pi/2)*e)/m(2)]; + + +% motion of (Lorenz) attractor states +%========================================================================== +T.f = spm_speye(n,n,-1) - spm_speye(n,n,+1) + 2*spm_speye(n,n,0); +T.f(n,1) = -1; +T.f(1,n) = +1; +T.f = T.f/2 - 1; + +f.a = spm_lotka_volterra(x.a,[],T)*.8; + + + diff --git a/toolbox/DEM/spm_fx_dem_reach.m b/toolbox/DEM/spm_fx_dem_reach.m index 7bfccd9..02a6e93 100644 --- a/toolbox/DEM/spm_fx_dem_reach.m +++ b/toolbox/DEM/spm_fx_dem_reach.m @@ -3,13 +3,21 @@ % FORMAT [f]= spm_fx_dem_reach(x,v,P) % % x - hidden states +% x(1) - joint angle +% x(2) - joint angle +% x(3) - angular velocity +% x(4) - angular velocity % v - causal states +% v(1) - target location (x) +% v(2) - target location (y) +% v(3) - cue strength % P - parameters %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_fx_dem_reach.m 3058 2009-04-09 18:17:53Z karl $ +% $Id: spm_fx_dem_reach.m 3901 2010-05-27 16:14:36Z karl $ + % evaluate positions %-------------------------------------------------------------------------- @@ -20,7 +28,7 @@ T = [v(1); v(2)]; % target location J = spm_dem_reach_x2J(x); % joint location -F = 2*v(3)*(T - J{1} - J{2}); % force +F = v(3)*(T - J{1} - J{2})*2; % force % flow diff --git a/toolbox/DEM/spm_fx_dem_write.m b/toolbox/DEM/spm_fx_dem_write.m new file mode 100644 index 0000000..be0125d --- /dev/null +++ b/toolbox/DEM/spm_fx_dem_write.m @@ -0,0 +1,55 @@ +function [f]= spm_fx_dem_write(x,v,P) +% returns the flow for a two-joint arm (writing with SHC) +% FORMAT [f]= spm_fx_dem_write(x,v,P) +% +% x.x(1) - joint angle +% x.x(2) - joint angle +% x.x(3) - angular velocity +% x.x(4) - angular velocity +% +% x.a(1) - attraction (location 1) +% x.a(2) - attraction (location 2) +% x.a(3) - attraction (location 3) +% ... +% +% v - hidden states +% v(1) - not used +% P - parameters (locations of point attratcors in state-space) +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: spm_fx_dem_write.m 3901 2010-05-27 16:14:36Z karl $ + + +% diameter of radial basis function (for autovitiation) +%-------------------------------------------------------------------------- +d = 1/8; +n = length(x.a); + +% location in state-space +%-------------------------------------------------------------------------- +J = spm_dem_reach_x2J(x.x); +X = J{1} + J{2}; + +% transition matrix +%-------------------------------------------------------------------------- +T = spm_speye(n,n,-1)/16 - spm_speye(n,n,0); + + +% motion of physical states +%========================================================================== + +% desired location (P(:,i)) is determined by the attractor state x.a +%-------------------------------------------------------------------------- +[m,i] = max(x.a); +f.x = spm_fx_dem_reach(x.x,[P(:,i); 1],P); + +% motion of attractor states (using basis functions of position) +%========================================================================== +T = T(:,i)*(norm(X - P(:,i)) < d); +f.a = (T*6 - sum(x.a))/4; + + + + diff --git a/toolbox/DEM/spm_fx_mountaincar.m b/toolbox/DEM/spm_fx_mountaincar.m index 8339f2a..e61aa23 100644 --- a/toolbox/DEM/spm_fx_mountaincar.m +++ b/toolbox/DEM/spm_fx_mountaincar.m @@ -26,7 +26,7 @@ % Copyright (C) 2005 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_fx_mountaincar.m 3333 2009-08-25 16:12:44Z karl $ +% $Id: spm_fx_mountaincar.m 3733 2010-02-18 17:43:18Z karl $ % determine controlled forces (a) @@ -69,7 +69,7 @@ dHdx = 2*x(1) + 1; else xx = x(1)^2; - dHdx = (1 + 5*xx)^(-1/2) - 5*xx/(1 + 5*xx)^(3/2) + (x(1)/2)^4; + dHdx = (5*xx + 1).^(-3/2) + (x(1)/2).^4; end f = [x(2); a + v - dHdx - x(2)/8]*dt; @@ -82,7 +82,7 @@ x = linspace(-2,2,1/dx); xx = x.^2; dHdx = (x < 0).*(2*x + 1); -dHdx = (x > 0).*(1./(1 + 5*xx).^(1/2) - 5*xx./(1 + 5*xx).^(3/2) + (x/2).^4) + dHdx; +dHdx = (x > 0).*((5*xx + 1).^(-3/2) + (x/2).^4) + dHdx; H = cumsum(dHdx)*dx; H = H - min(H); diff --git a/toolbox/DEM/spm_gx_adem_reach.m b/toolbox/DEM/spm_gx_adem_reach.m index 5ccbec5..5361b15 100644 --- a/toolbox/DEM/spm_gx_adem_reach.m +++ b/toolbox/DEM/spm_gx_adem_reach.m @@ -3,15 +3,23 @@ % FORMAT [g] = spm_gx_adem_reach(x,v,a,P) % % x - hidden states +% x(1) - joint angle +% x(2) - joint angle +% x(3) - angular velocity +% x(4) - angular velocity % v - causal states +% v(1) - target location (x) +% v(2) - target location (y) +% v(3) - force (cue strength) +% P - parameters % a - action % P - parameters %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_gx_adem_reach.m 3054 2009-04-07 19:22:49Z karl $ +% $Id: spm_gx_adem_reach.m 3893 2010-05-17 18:28:52Z karl $ -% stretch (positional) and visual (positional) information +% stretch (angular) and visual (positional) information (target & arm) %========================================================================== g = spm_gx_dem_reach(x,v,P); \ No newline at end of file diff --git a/toolbox/DEM/spm_gx_adem_write.m b/toolbox/DEM/spm_gx_adem_write.m new file mode 100644 index 0000000..8dda41a --- /dev/null +++ b/toolbox/DEM/spm_gx_adem_write.m @@ -0,0 +1,36 @@ +function [g]= spm_gx_adem_write(x,v,a,P) +% returns the prediction for a two-joint arm (proprioception and vision) +% FORMAT [g]= spm_gx_adem_write(x,v,a,P) +% +% x - hidden states: +% x(1) - joint angle +% x(2) - joint angle +% x(3) - angular velocity +% x(4) - angular velocity +% v - causal states{ +% v(1) - exogenous force (x) +% v(2) - exogenous force (y) +% a - action +% P - parameters +% +% g - sensations: +% g(1) - joint angle (proprioception) +% g(2) - joint angle (proprioception) +% g(3) - arm location (visual) +% g(4) - arm location (visual) +% +% As for spm_dem_reach but with no visual target +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: spm_gx_adem_write.m 3901 2010-05-27 16:14:36Z karl $ + +% evaluate positions +%-------------------------------------------------------------------------- +J = spm_dem_reach_x2J(x); + +% stretch (angular) and visual (positional) information about motor plant +%========================================================================== +g = [x; J{1}; J{1} + J{2}]; + diff --git a/toolbox/DEM/spm_gx_dem_reach.m b/toolbox/DEM/spm_gx_dem_reach.m index 31d72fc..f91c69c 100644 --- a/toolbox/DEM/spm_gx_dem_reach.m +++ b/toolbox/DEM/spm_gx_dem_reach.m @@ -3,19 +3,26 @@ % FORMAT [g]= spm_gx_dem_reach(x,v,P) % % x - hidden states +% x(1) - joint angle +% x(2) - joint angle +% x(3) - angular velocity +% x(4) - angular velocity % v - causal states +% v(1) - target location (x) +% v(2) - target location (y) +% v(3) - force (cue strength) % P - parameters %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_gx_dem_reach.m 3054 2009-04-07 19:22:49Z karl $ +% $Id: spm_gx_dem_reach.m 3893 2010-05-17 18:28:52Z karl $ % evaluate positions %-------------------------------------------------------------------------- J = spm_dem_reach_x2J(x); -% stretch (positional) and visual (positional) information +% stretch (angular) and visual (positional) information (target & arm) %========================================================================== g = [x(1:2); v; J{1} + J{2}]; diff --git a/toolbox/DEM/spm_gx_dem_write.m b/toolbox/DEM/spm_gx_dem_write.m new file mode 100644 index 0000000..fbe77df --- /dev/null +++ b/toolbox/DEM/spm_gx_dem_write.m @@ -0,0 +1,34 @@ +function [g]= spm_gx_dem_write(x,v,P) +% returns the prediction for a two-joint arm (writing example) +% FORMAT [g]= spm_gx_dem_write(x,v,P) +% +% x - hidden states: +% x(1) - joint angle +% x(2) - joint angle +% x(3) - angular velocity +% x(4) - angular velocity +% +% v - hidden causes +% P - parameters +% +% g - sensations: +% g(1) - joint angle (proprioception) +% g(2) - joint angle (proprioception) +% g(3) - arm location (visual) +% g(4) - arm location (visual) +% +% As for spm_dem_reach but with no visual target +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: spm_gx_dem_write.m 3901 2010-05-27 16:14:36Z karl $ + +% evaluate positions +%-------------------------------------------------------------------------- +J = spm_dem_reach_x2J(x.x); + +% stretch (angular) and visual (positional) information about motor plant +%========================================================================== +g = [x.x; J{1}; J{1} + J{2}]; + diff --git a/toolbox/DEM/spm_mc_fx.m b/toolbox/DEM/spm_mc_fx.m new file mode 100644 index 0000000..3f204cd --- /dev/null +++ b/toolbox/DEM/spm_mc_fx.m @@ -0,0 +1,36 @@ +function [f] = spm_mc_fx(x,v,P) +% equations of motion for the mountain car problem using basis functions +% problem +% FORMAT [f] = spm_mc_fx(x,v,P) +% +% x - hidden states +% v - exogenous inputs +% P.x,k - parameters for gradient function: G(x(1),P.p) +% P.q - parameters for cost or loss-function: C(x(1),P.q) +% +% returns f = dx/dt = f = [x(2); +% G - x(2)*C(x(1))]*dt; +% +% where C determines divergence of flow x(2) at any position x(1). +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: spm_mc_fx.m 3757 2010-03-08 11:41:53Z guillaume $ + + +% gradient (G) +%-------------------------------------------------------------------------- +G = spm_mc_loss_G(x(1),P); + +% cost function (C) +%-------------------------------------------------------------------------- +c = spm_mc_loss_C(x(1),P); + +% flow +%-------------------------------------------------------------------------- +dt = 1/4; +C = P.p - P.q*(1 - c); +f = [x(2); -G*c + x(2)*C]*dt; + + diff --git a/toolbox/DEM/spm_mc_loss_C.m b/toolbox/DEM/spm_mc_loss_C.m new file mode 100644 index 0000000..169088b --- /dev/null +++ b/toolbox/DEM/spm_mc_loss_C.m @@ -0,0 +1,21 @@ +function [C] = spm_mc_loss_C(x,P) +% cost function for the mountain car problem +% problem +% FORMAT [C] = spm_mc_loss_C(x,P) +% +% x - hidden states +% v - exogenous inputs +% P.x,k - parameters for gradient function: G(x(1),P.p) +% P.q,p - parameters for cost or loss-function: C(x(1),P.q) +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: spm_mc_loss_C.m 3757 2010-03-08 11:41:53Z guillaume $ + + +% gradient (G) (quadratic potential = (x(1) - P.x)^2*P.k/2) +%-------------------------------------------------------------------------- +C = abs(x(1,:) - 1) > 1/4; + + diff --git a/toolbox/DEM/spm_mc_loss_G.m b/toolbox/DEM/spm_mc_loss_G.m new file mode 100644 index 0000000..87f1f17 --- /dev/null +++ b/toolbox/DEM/spm_mc_loss_G.m @@ -0,0 +1,21 @@ +function [G] = spm_mc_loss_G(x,P) +% assumed potential gradient for the mountain car problem +% problem +% FORMAT [G] = spm_mc_loss_G(x,P) +% +% x - hidden states +% v - exogenous inputs +% P.x,k - parameters for gradient function: G(x(1),P.p) +% P.q,q - parameters for cost or loss-function: C(x(1),P.q) +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Karl Friston +% $Id: spm_mc_loss_G.m 3757 2010-03-08 11:41:53Z guillaume $ + + +% gradient (G) (quadratic potential = (x(1) - P.x)^2*P.k/2) +%-------------------------------------------------------------------------- +G = (x(1,:) - P.x)*P.k; + + diff --git a/toolbox/FieldMap/FieldMap.m b/toolbox/FieldMap/FieldMap.m index 5cc0514..4a5d47c 100644 --- a/toolbox/FieldMap/FieldMap.m +++ b/toolbox/FieldMap/FieldMap.m @@ -114,7 +114,7 @@ % Copyright (C) 2006 Wellcome Department of Imaging Neuroscience % Jesper Andersson and Chloe Hutton -% $Id: FieldMap.m 3016 2009-03-31 15:43:45Z chloe $ +% $Id: FieldMap.m 3756 2010-03-05 18:43:37Z guillaume $ %_______________________________________________________________________ persistent PF FS WS PM % GUI related constants @@ -123,10 +123,6 @@ persistent DGW % Delete Graphics Window (if we created it) global st % Global for spm_orthviews -% SPM5 Update -global defaults -spm_defaults - if nargin == 0 Action = 'welcome'; else @@ -703,7 +699,7 @@ % Toggle relevant buttons FieldMap('ToggleGUI','Off','CreateFieldMap'); - FieldMap('ToggleGUI','On',str2mat('LoadFieldMap','WriteFieldMap')); + FieldMap('ToggleGUI','On',char('LoadFieldMap','WriteFieldMap')); % % Check that have correct parameters ready before allowing % an image to be loaded for unwarping and hence conversion of @@ -711,7 +707,7 @@ % if (FieldMap('GatherVDMData')) FieldMap('FM2VDM',IP); - FieldMap('ToggleGUI','On',str2mat('LoadEpi','EPI',... + FieldMap('ToggleGUI','On',char('LoadEpi','EPI',... 'BlipDir','Jacobian','ReadTime')); end end @@ -741,7 +737,7 @@ 'FontSize',FS(8)); FieldMap('DisplayImage',FieldMap('MakedP'),[.05 .75 .95 .2],1); - FieldMap('ToggleGUI','Off',str2mat('CreateFieldMap','WriteFieldMap',... + FieldMap('ToggleGUI','Off',char('CreateFieldMap','WriteFieldMap',... 'MatchVDM','WriteUnwarped',... 'LoadStructural', 'MatchStructural')); @@ -751,7 +747,7 @@ % if (FieldMap('GatherVDMData')) FieldMap('FM2VDM',IP); - FieldMap('ToggleGUI','On',str2mat('LoadEpi','EPI',... + FieldMap('ToggleGUI','On',char('LoadEpi','EPI',... 'BlipDir','Jacobian','ReadTime')); end @@ -789,7 +785,7 @@ FieldMap('DisplayImage',IP.uepiP,[.05 .25 .95 .2],3); % Once EPI has been unwarped can enable unwarp checks and structural stuff - FieldMap('ToggleGUI','On',str2mat('MatchVDM','WriteUnwarped','LoadStructural')); + FieldMap('ToggleGUI','On',char('MatchVDM','WriteUnwarped','LoadStructural')); end % @@ -814,7 +810,7 @@ FieldMap('DisplayImage',IP.epiP,[.05 .5 .95 .2],2); FieldMap('DisplayImage',IP.uepiP,[.05 .25 .95 .2],3); % Once EPI has been unwarped can enable unwarp checks - FieldMap('ToggleGUI','On',str2mat('MatchVDM','WriteUnwarped','LoadStructural')); + FieldMap('ToggleGUI','On',char('MatchVDM','WriteUnwarped','LoadStructural')); end %======================================================================= @@ -923,7 +919,7 @@ % Disable input routes to make sure % a new fieldmap is calculated. % - FieldMap('ToggleGUI','Off',str2mat('CreateFieldMap','WriteFieldMap',... + FieldMap('ToggleGUI','Off',char('CreateFieldMap','WriteFieldMap',... 'LoadEpi','WriteUnwarped','MatchVDM',... 'LoadStructural','MatchStructural',... 'EPI','BlipDir',... @@ -1140,7 +1136,7 @@ if ~isempty(IP.epiP) IP.uepiP = FieldMap('UnwarpEPI',IP); FieldMap('DisplayImage',IP.uepiP,[.05 .25 .95 .2],3); - FieldMap('ToggleGUI','On',str2mat('WriteUnwarped')); + FieldMap('ToggleGUI','On',char('WriteUnwarped')); end end @@ -1185,14 +1181,14 @@ if ~isempty(IP.epiP) IP.uepiP = FieldMap('UnwarpEPI',IP); FieldMap('DisplayImage',IP.uepiP,[.05 .25 .95 .2],3); - FieldMap('ToggleGUI','On',str2mat('WriteUnwarped',... + FieldMap('ToggleGUI','On',char('WriteUnwarped',... 'LoadStructural')); end - FieldMap('ToggleGUI','On',str2mat('LoadEpi','EPI','BlipDir',... + FieldMap('ToggleGUI','On',char('LoadEpi','EPI','BlipDir',... 'Jacobian','ReadTime')); else % If readtime is missing switch everything off... - FieldMap('ToggleGUI','Off',str2mat('LoadEpi','EPI',... + FieldMap('ToggleGUI','Off',char('LoadEpi','EPI',... 'BlipDir','Jacobian',... 'WriteUnwarped','LoadStructural',... 'MatchStructural', 'MatchVDM')); @@ -2177,10 +2173,10 @@ VF = varargin{3}; % Define flags for coregistration... - IP.cflags.cost_fun = defaults.coreg.estimate.cost_fun; - IP.cflags.sep = defaults.coreg.estimate.sep; - IP.cflags.tol = defaults.coreg.estimate.tol; - IP.cflags.fwhm = defaults.coreg.estimate.fwhm; + IP.cflags.cost_fun = spm_get_defaults('coreg.estimate.cost_fun'); + IP.cflags.sep = spm_get_defaults('coreg.estimate.sep'); + IP.cflags.tol = spm_get_defaults('coreg.estimate.tol'); + IP.cflags.fwhm = spm_get_defaults('coreg.estimate.fwhm'); IP.cflags.graphics = 0; % Voxel sizes (mm) diff --git a/toolbox/FieldMap/FieldMap_Run.m b/toolbox/FieldMap/FieldMap_Run.m index 91f5899..ef8cf3b 100644 --- a/toolbox/FieldMap/FieldMap_Run.m +++ b/toolbox/FieldMap/FieldMap_Run.m @@ -34,14 +34,13 @@ % Copyright (C) 2007 Wellcome Department of Imaging Neuroscience % Chloe Hutton & Jesper Andersson -% $Id: FieldMap_Run.m 3085 2009-04-24 20:09:58Z chloe $ +% $Id: FieldMap_Run.m 3710 2010-02-03 19:11:26Z guillaume $ %_________________________________________________________________ % %---------------------------------------------------------------------- % Set up default parameters and structures %---------------------------------------------------------------------- -spm_defaults % Open the FieldMap control window with visibility off. This allows the % graphics display to work. diff --git a/toolbox/FieldMap/FieldMap_preprocess.m b/toolbox/FieldMap/FieldMap_preprocess.m index 592f000..f4107ef 100644 --- a/toolbox/FieldMap/FieldMap_preprocess.m +++ b/toolbox/FieldMap/FieldMap_preprocess.m @@ -67,7 +67,7 @@ % Copyright (C) 2006 Wellcome Department of Imaging Neuroscience % Chloe Hutton -% $Id: FieldMap_preprocess.m 2613 2009-01-16 19:38:14Z chloe $ +% $Id: FieldMap_preprocess.m 3756 2010-03-05 18:43:37Z guillaume $ %_______________________________________________________________________ @@ -142,7 +142,7 @@ epi_all = strvcat(spm_select('List',epi_dir{sessnum},'^f.*\.nii$'),spm_select('List',epi_dir{sessnum},'^f.*\.img$')); epi_img{sessnum}=fullfile(epi_dir{sessnum},epi_all(1,:)); end -elseif isstr(epi_dir) +elseif ischar(epi_dir) nsessions=1; sessnum=1; epi_all = strvcat(spm_select('List',epi_dir,'^f.*\.nii$'),spm_select('List',epi_dir,'^f.*\.img$')); @@ -184,7 +184,7 @@ phase=fullfile(fm_dir,fm_imgs(3,:)); end scphase=FieldMap('Scale',phase); - fm_imgs=str2mat(scphase.fname,mag); + fm_imgs=char(scphase.fname,mag); end else msg=sprintf('Sorry. I cannot find the fieldmap files in %s',fm_dir); diff --git a/toolbox/FieldMap/Unwarp_batch.m b/toolbox/FieldMap/Unwarp_batch.m index d8102b1..c94929e 100644 --- a/toolbox/FieldMap/Unwarp_batch.m +++ b/toolbox/FieldMap/Unwarp_batch.m @@ -8,7 +8,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Chloe Hutton -% $Id: Unwarp_batch.m 1533 2008-05-01 14:29:03Z spm $ +% $Id: Unwarp_batch.m 3692 2010-01-21 21:43:31Z guillaume $ which spm @@ -16,11 +16,10 @@ % % Enter the name of the directory that contains data/subjects % -owd = '/data/FieldMap_examples/sonata_subject' +owd = '/data/FieldMap_examples/sonata_subject'; cd(owd); -spm('defaults','FMRI'); -defaults = spm('GetGlobal','defaults'); +defaults = spm('defaults','FMRI'); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/toolbox/FieldMap/pm_defaults_Trio_eFoV.m b/toolbox/FieldMap/pm_defaults_Trio_eFoV.m index aff8c63..3d8822e 100644 --- a/toolbox/FieldMap/pm_defaults_Trio_eFoV.m +++ b/toolbox/FieldMap/pm_defaults_Trio_eFoV.m @@ -12,7 +12,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Chloe Hutton and Jesper Andersson -% $Id: pm_defaults_Trio_eFoV.m 2616 2009-01-19 16:49:42Z chloe $ +% $Id: pm_defaults_Trio_eFoV.m 3706 2010-02-02 12:21:08Z chloe $ global pm_def @@ -54,7 +54,7 @@ %======================================================================= pm_def.EPI_BASED_FIELDMAPS = 0; % EPI=1, other=0. pm_def.K_SPACE_TRAVERSAL_BLIP_DIR = -1; % +ve k-space = 1, -ve = -1. -pm_def.TOTAL_EPI_READOUT_TIME = 36.0; % Trio eFoV EPI RO time +pm_def.TOTAL_EPI_READOUT_TIME = 37.0; % Trio eFoV EPI RO time % Defaults for Unwarping. %======================================================================= diff --git a/toolbox/FieldMap/pm_defaults_Trio_eFoV_dn.m b/toolbox/FieldMap/pm_defaults_Trio_eFoV_dn.m index d02cb00..f968c50 100644 --- a/toolbox/FieldMap/pm_defaults_Trio_eFoV_dn.m +++ b/toolbox/FieldMap/pm_defaults_Trio_eFoV_dn.m @@ -12,7 +12,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Chloe Hutton and Jesper Andersson -% $Id: pm_defaults_Trio_eFoV_dn.m 2616 2009-01-19 16:49:42Z chloe $ +% $Id: pm_defaults_Trio_eFoV_dn.m 3706 2010-02-02 12:21:08Z chloe $ global pm_def @@ -54,7 +54,7 @@ %======================================================================= pm_def.EPI_BASED_FIELDMAPS = 0; % EPI=1, other=0. pm_def.K_SPACE_TRAVERSAL_BLIP_DIR = +1; % +ve k-space = 1, -ve = -1. -pm_def.TOTAL_EPI_READOUT_TIME = 36.0; % Trio eFoV EPI RO time +pm_def.TOTAL_EPI_READOUT_TIME = 37.0; % Trio eFoV EPI RO time % Defaults for Unwarping. %======================================================================= diff --git a/toolbox/FieldMap/pm_segment.m b/toolbox/FieldMap/pm_segment.m index 3844c6c..233b65d 100644 --- a/toolbox/FieldMap/pm_segment.m +++ b/toolbox/FieldMap/pm_segment.m @@ -52,7 +52,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % John Ashburner -% $Id: pm_segment.m 1353 2008-04-10 10:34:22Z guillaume $ +% $Id: pm_segment.m 3756 2010-03-05 18:43:37Z guillaume $ % Create some suitable default values %----------------------------------------------------------------------- @@ -620,7 +620,7 @@ function display_graphics(VF,VS,mn,cv,mg) if wc, VC = VF; for j=1:length(VF), - [pth,nm,xt,vr] = fileparts(deblank(VF(j).fname)); + [pth,nm,xt,vr] = spm_fileparts(deblank(VF(j).fname)); VC(j).fname = fullfile(pth,['m' nm xt vr]); VC(j).descrip = 'Bias corrected image'; end; diff --git a/toolbox/HDW/spm_config_hdw.m b/toolbox/HDW/spm_config_hdw.m deleted file mode 100644 index bf8e702..0000000 --- a/toolbox/HDW/spm_config_hdw.m +++ /dev/null @@ -1,140 +0,0 @@ -function job = spm_config_hdw -% Configuration file for specification of fMRI model -%_______________________________________________________________________ -% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging - -% John Ashburner -% $Id: spm_config_hdw.m 1167 2008-02-24 19:51:13Z volkmar $ - -% Define inline types. -%----------------------------------------------------------------------- -entry = inline(['struct(''type'',''entry'',''name'',name,'... - '''tag'',tag,''strtype'',strtype,''num'',num)'],... - 'name','tag','strtype','num'); - -files = inline(['struct(''type'',''files'',''name'',name,'... - '''tag'',tag,''filter'',fltr,''num'',num)'],... - 'name','tag','fltr','num'); - -mnu = inline(['struct(''type'',''menu'',''name'',name,'... - '''tag'',tag,''labels'',{labels},''values'',{values})'],... - 'name','tag','labels','values'); - -branch = inline(['struct(''type'',''branch'',''name'',name,'... - '''tag'',tag,''val'',{val})'],... - 'name','tag','val'); - -repeat = inline(['struct(''type'',''repeat'',''name'',name,'... - '''tag'',tag,''values'',{values})'],... - 'name','tag','values'); - -choice = inline(['struct(''type'',''choice'',''name'',name,'... - '''tag'',tag,''values'',{values})'],... - 'name','tag','values'); -%----------------------------------------------------------------------- - -addpath(fullfile(spm('dir'),'toolbox','HDW')); - -ref = files('Reference Image','ref','image',[1 1]); -ref.help = {'This is the reference image, which remains stationary.'}; - -mov = files('Moved Image','mov','image',[1 1]); -mov.help = {'This is the moved image, which is warped to match the reference.'}; -fles = branch('Subject','data',{ref,mov}); -fles.help = {[... -'Two images of the same subject, which are to be registered together. ',... -'Prior to nonlinear high-dimensional warping, the images should be rigidly registered with each other.']}; - -fles = repeat('Subjects','data',{fles}); -fles.help = {[... -'Specify pairs of images to match together.']}; - -nits = entry('Iterations','nits','n',[1 1]); -nits.help = {'Number of iterations for the bias correction'}; -nits.val = {8}; - -biasfwhm = mnu('Bias FWHM','fwhm',{... -'30mm cutoff','40mm cutoff','50mm cutoff','60mm cutoff','70mm cutoff',... -'80mm cutoff','90mm cutoff','100mm cutoff','110mm cutoff','120mm cutoff',... -'130mm cutoff','140mm cutoff','150mm cutoff','No correction'},... -{30,40,50,60,70,80,90,100,110,120,130,140,150,Inf}); -biasfwhm.val = {60}; -biasfwhm.help = {[... -'FWHM of Gaussian smoothness of bias. ',... -'If your intensity nonuniformity is very smooth, then choose a large ',... -'FWHM. This will prevent the algorithm from trying to model out intensity variation ',... -'due to different tissue types. The model for intensity nonuniformity is one ',... -'of i.i.d. Gaussian noise that has been smoothed by some amount, ',... -'before taking the exponential. ',... -'Note also that smoother bias fields need fewer parameters to describe them. ',... -'This means that the algorithm is faster for smoother intensity nonuniformities.']}; - -biasreg = mnu('Bias regularisation','reg',{... -'no regularisation','extremely light regularisation',... -'very light regularisation','light regularisation',... -'medium regularisation','heavy regularisation',... -'very heavy regularisation','extremely heavy regularisation'},... -{0, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3}); -biasreg.val = {1e-6}; -biasreg.help = {[... -'We know a priori that intensity variations due to MR physics tend to be spatially smooth, ',... -'whereas those due to different tissue types tend to contain more high frequency information. ',... -'A more accurate estimate of a bias field can be obtained by including prior knowledge about ',... -'the distribution of the fields likely to be encountered by the correction algorithm. ',... -'For example, if it is known that there is little or no intensity non-uniformity, then it would be wise ',... -'to penalise large values for the intensity nonuniformity parameters. ',... -'This regularisation can be placed within a Bayesian context, whereby the penalty incurred is the negative ',... -'logarithm of a prior probability for any particular pattern of nonuniformity.']}; - -lmreg = mnu('Levenberg-Marquardt regularisation','lmreg',{... -'no regularisation','extremely light regularisation',... -'very light regularisation','light regularisation',... -'medium regularisation','heavy regularisation',... -'very heavy regularisation','extremely heavy regularisation'},... -{0, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3}); -lmreg.val = {1e-6}; -lmreg.help = {[... -'Levenberg-Marquardt regularisation keeps the bias correction part stable. ',... -'Higher values means more stability, but slower convergence.']}; - -bias_opts = branch('Bias Correction Options','bias_opts',{nits,biasfwhm,biasreg,lmreg}); -bias_opts.help = {[... -'MR images are usually corrupted by a smooth, spatially varying artifact that modulates the intensity ',... -'of the image (bias). ',... -'These artifacts, although not usually a problem for visual inspection, can impede automated ',... -'processing of the images.'],... -[... -'Before registering the images, an approximate bias correction is estimated for the moved image. ',... -'This is based on minimising the difference between the images an a symmetric way. ',... -'Prior to registering the images, they should be rigidly aligned together. ',... -'The bias correction is estimated once for these aligned images.']}; - -warpreg = entry('Warping regularisation','reg','e',[1 1]); -warpreg.val = {4}; -warpreg.help = {[... -'There is a tradeoff between the smoothness of the estimated warps, and the difference ',... -'between the registered images. Higher values mean smoother warps, at the expense of ',... -'a lower mean squared difference between the images.']}; - -nits = entry('Iterations','nits','n',[1 1]); -nits.help = {'Number of iterations for the warping.'}; -nits.val = {8}; - -warp_opts = branch('Warping Options','warp_opts',{nits,warpreg}); -warp_opts.help = {'There are a couple of user-customisable warping options.'}; - -job = branch('High-Dimensional Warping','hdw',{fles,bias_opts,warp_opts}); -job.prog = @spm_hdw; -job.help = {[... -'This toolbox is a Bayesian method for three dimensional registration of brain images/* \cite{ashburner00a} */. ',... -'A finite element approach is used to obtain a maximum a posteriori (MAP) estimate of ',... -'the deformation field at every voxel of a template volume. ',... -'The priors used by the MAP estimate penalize unlikely deformations and enforce a ',... -'continuous one-to-one mapping. ',... -'The deformations are assumed to have some form of symmetry, in that priors describing ',... -'the probability distribution of the deformations should be identical to those for the ',... -'inverses (i.e., warping brain A to brain B should not be different probablistically ',... -'from warping B to A). ',... -'A gradient descent algorithm is used to estimate the optimum deformations.'],... -['Deformation fields are written with the same name as the moved image, but with "y_" prefixed ',... -'on to the filename. Jacobian determinant images are also written (prefixed by "jy_").']}; diff --git a/toolbox/HDW/tbx_cfg_hdw.m b/toolbox/HDW/tbx_cfg_hdw.m new file mode 100644 index 0000000..5b66076 --- /dev/null +++ b/toolbox/HDW/tbx_cfg_hdw.m @@ -0,0 +1,166 @@ +function hdw = tbx_cfg_hdw +% Configuration file for toolbox 'High-Dimensional Warping' +%_______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% John Ashburner +% $Id: tbx_cfg_hdw.m 3960 2010-06-30 17:41:24Z ged $ + +% --------------------------------------------------------------------- +% ref Reference Image +% --------------------------------------------------------------------- +ref = cfg_files; +ref.tag = 'ref'; +ref.name = 'Reference Image'; +ref.help = {'This is the reference image, which remains stationary.'}; +ref.filter = 'image'; +ref.ufilter = '.*'; +ref.num = [1 1]; +% --------------------------------------------------------------------- +% mov Moved Image +% --------------------------------------------------------------------- +mov = cfg_files; +mov.tag = 'mov'; +mov.name = 'Moved Image'; +mov.help = {'This is the moved image, which is warped to match the reference.'}; +mov.filter = 'image'; +mov.ufilter = '.*'; +mov.num = [1 1]; +% --------------------------------------------------------------------- +% data Subject +% --------------------------------------------------------------------- +data1 = cfg_branch; +data1.tag = 'data'; +data1.name = 'Subject'; +data1.val = {ref mov}; +data1.help = {'Two images of the same subject, which are to be registered together. Prior to nonlinear high-dimensional warping, the images should be rigidly registered with each other.'}; +% --------------------------------------------------------------------- +% data Subjects +% --------------------------------------------------------------------- +data = cfg_repeat; +data.tag = 'data'; +data.name = 'Subjects'; +data.help = {'Specify pairs of images to match together.'}; +data.values = {data1}; +data.num = [0 Inf]; +% --------------------------------------------------------------------- +% nits Iterations +% --------------------------------------------------------------------- +nits = cfg_entry; +nits.tag = 'nits'; +nits.name = 'Iterations'; +nits.help = {'Number of iterations for the bias correction'}; +nits.val = {8}; +nits.strtype = 'n'; +nits.num = [1 1]; +% --------------------------------------------------------------------- +% fwhm Bias FWHM +% --------------------------------------------------------------------- +fwhm = cfg_menu; +fwhm.tag = 'fwhm'; +fwhm.name = 'Bias FWHM'; +fwhm.help = {'FWHM of Gaussian smoothness of bias. If your intensity nonuniformity is very smooth, then choose a large FWHM. This will prevent the algorithm from trying to model out intensity variation due to different tissue types. The model for intensity nonuniformity is one of i.i.d. Gaussian noise that has been smoothed by some amount, before taking the exponential. Note also that smoother bias fields need fewer parameters to describe them. This means that the algorithm is faster for smoother intensity nonuniformities.'}; +fwhm.val = {60}; +fwhm.labels = {'30mm cutoff' + '40mm cutoff' + '50mm cutoff' + '60mm cutoff' + '70mm cutoff' + '80mm cutoff' + '90mm cutoff' + '100mm cutoff' + '110mm cutoff' + '120mm cutoff' + '130mm cutoff' + '140mm cutoff' + '150mm cutoff' + 'No correction'}'; +fwhm.values = {30 40 50 60 70 80 90 100 110 120 130 140 150 Inf}; +% --------------------------------------------------------------------- +% reg Bias regularisation +% --------------------------------------------------------------------- +reg = cfg_menu; +reg.tag = 'reg'; +reg.name = 'Bias regularisation'; +reg.help = {'We know a priori that intensity variations due to MR physics tend to be spatially smooth, whereas those due to different tissue types tend to contain more high frequency information. A more accurate estimate of a bias field can be obtained by including prior knowledge about the distribution of the fields likely to be encountered by the correction algorithm. For example, if it is known that there is little or no intensity non-uniformity, then it would be wise to penalise large values for the intensity nonuniformity parameters. This regularisation can be placed within a Bayesian context, whereby the penalty incurred is the negative logarithm of a prior probability for any particular pattern of nonuniformity.'}; +reg.val = {1e-6}; +reg.labels = {'no regularisation' + 'extremely light regularisation' + 'very light regularisation' + 'light regularisation' + 'medium regularisation' + 'heavy regularisation' + 'very heavy regularisation' + 'extremely heavy regularisation'}'; +reg.values = {0, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3}; +% --------------------------------------------------------------------- +% lmreg Levenberg-Marquardt regularisation +% --------------------------------------------------------------------- +lmreg = cfg_menu; +lmreg.tag = 'lmreg'; +lmreg.name = 'Levenberg-Marquardt regularisation'; +lmreg.help = {'Levenberg-Marquardt regularisation keeps the bias correction part stable. Higher values means more stability, but slower convergence.'}; +lmreg.val = {1e-6}; +lmreg.labels ={'no regularisation' + 'extremely light regularisation' + 'very light regularisation' + 'light regularisation' + 'medium regularisation' + 'heavy regularisation' + 'very heavy regularisation' + 'extremely heavy regularisation' + }'; +lmreg.values = {0, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3}; +% --------------------------------------------------------------------- +% bias_opts Bias Correction Options +% --------------------------------------------------------------------- +bias_opts = cfg_branch; +bias_opts.tag = 'bias_opts'; +bias_opts.name = 'Bias Correction Options'; +bias_opts.val = {nits fwhm reg lmreg }; +bias_opts.help = {'MR images are usually corrupted by a smooth, spatially varying artifact that modulates the intensity of the image (bias). These artifacts, although not usually a problem for visual inspection, can impede automated processing of the images.' + 'Before registering the images, an approximate bias correction is estimated for the moved image. This is based on minimising the difference between the images an a symmetric way. Prior to registering the images, they should be rigidly aligned together. The bias correction is estimated once for these aligned images.'}'; +% --------------------------------------------------------------------- +% nits Iterations +% --------------------------------------------------------------------- +nitsw = cfg_entry; +nitsw.tag = 'nits'; +nitsw.name = 'Iterations'; +nitsw.help = {'Number of iterations for the warping.'}; +nitsw.val = {8}; +nitsw.strtype = 'n'; +nitsw.num = [1 1]; +% --------------------------------------------------------------------- +% reg Warping regularisation +% --------------------------------------------------------------------- +regw = cfg_entry; +regw.tag = 'reg'; +regw.name = 'Warping regularisation'; +regw.help = {'There is a tradeoff between the smoothness of the estimated warps, and the difference between the registered images. Higher values mean smoother warps, at the expense of a lower mean squared difference between the images.'}; +regw.val = {4}; +regw.strtype = 'e'; +regw.num = [1 1]; +% --------------------------------------------------------------------- +% warp_opts Warping Options +% --------------------------------------------------------------------- +warp_opts = cfg_branch; +warp_opts.tag = 'warp_opts'; +warp_opts.name = 'Warping Options'; +warp_opts.val = {nitsw regw}; +warp_opts.help = {'There are a couple of user-customisable warping options.'}; +% --------------------------------------------------------------------- +% hdw High-Dimensional Warping +% --------------------------------------------------------------------- +hdw = cfg_exbranch; +hdw.tag = 'hdw'; +hdw.name = 'High-Dimensional Warping'; +hdw.val = {data bias_opts warp_opts}; +hdw.help = {'This toolbox is a Bayesian method for three dimensional registration of brain images/* \cite{ashburner00a} */. A finite element approach is used to obtain a maximum a posteriori (MAP) estimate of the deformation field at every voxel of a template volume. The priors used by the MAP estimate penalize unlikely deformations and enforce a continuous one-to-one mapping. The deformations are assumed to have some form of symmetry, in that priors describing the probability distribution of the deformations should be identical to those for the inverses (i.e., warping brain A to brain B should not be different probablistically from warping B to A). A gradient descent algorithm is used to estimate the optimum deformations.' + 'Deformation fields are written with the same name as the moved image, but with "y_" prefixed on to the filename. Jacobian determinant images are also written (prefixed by "jy_").'}'; +hdw.prog = @spm_local_hdw; + +%====================================================================== +function spm_local_hdw(job) + +if ~isdeployed, addpath(fullfile(spm('Dir'),'toolbox','HDW')); end +spm_hdw(job); \ No newline at end of file diff --git a/toolbox/MEEGtools/spm_MEEGtools.m b/toolbox/MEEGtools/spm_MEEGtools.m index a9b49c7..84761f3 100644 --- a/toolbox/MEEGtools/spm_MEEGtools.m +++ b/toolbox/MEEGtools/spm_MEEGtools.m @@ -4,12 +4,13 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Vladimir Litvak -% $Id: spm_MEEGtools.m 3608 2009-12-03 11:49:46Z vladimir $ +% $Id: spm_MEEGtools.m 3767 2010-03-09 22:49:30Z vladimir $ funlist = { 'Copy MEG sensors', 'spm_eeg_copygrad'; 'Re-reference EEG', 'spm_eeg_reref_eeg'; + 'Split conditions into separate datasets', 'spm_eeg_split_conditions'; 'Fieldtrip interactive plotting', 'spm_eeg_plot_interactive'; 'Fieldtrip visual artefact rejection', 'spm_eeg_ft_artefact_visual'; 'Fieldtrip dipole fitting', 'spm_eeg_ft_dipolefitting'; @@ -20,6 +21,7 @@ 'Fieldtrip manual coregistration' , 'spm_eeg_ft_datareg_manual' 'Remove spikes from EEG' , 'spm_eeg_remove_spikes' 'Reduce jumps in MEG data' , 'spm_eeg_remove_jumps' + 'Detrending and Hanning for ERPs', 'spm_eeg_erp_correction' 'Extract dipole waveforms', 'spm_eeg_dipole_waveforms' 'Fieldtrip multitaper TF', 'spm_eeg_ft_multitaper_tf' 'Fieldtrip-SPM robust multitaper coherence', 'spm_eeg_ft_multitaper_coherence' diff --git a/toolbox/MEEGtools/spm_eeg_copygrad.m b/toolbox/MEEGtools/spm_eeg_copygrad.m index 2b76d1b..4fa055a 100644 --- a/toolbox/MEEGtools/spm_eeg_copygrad.m +++ b/toolbox/MEEGtools/spm_eeg_copygrad.m @@ -3,18 +3,18 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Vladimir Litvak -% $Id: spm_eeg_copygrad.m 2351 2008-10-17 11:50:35Z vladimir $ +% $Id: spm_eeg_copygrad.m 3833 2010-04-22 14:49:48Z vladimir $ spmfile = spm_select(1, '\.mat$', 'Select an SPM8 EEG file'); ctffile = spm_select(1, '\.*', 'Select a raw MEG data file'); -hdr = fileio_read_header(ctffile); +hdr = ft_read_header(ctffile); D = spm_eeg_load(spmfile); -D = sensors(D, 'MEG', forwinv_convert_units(hdr.grad, 'mm')); -D = fiducials(D, forwinv_convert_units(fileio_read_headshape(ctffile), 'mm')); +D = sensors(D, 'MEG', ft_convert_units(hdr.grad, 'mm')); +D = fiducials(D, ft_convert_units(ft_read_headshape(ctffile), 'mm')); % Create 2D positions for MEG (when there are no EEG sensors) % by projecting the 3D positions to 2D diff --git a/toolbox/MEEGtools/spm_eeg_detect_eyeblinks.m b/toolbox/MEEGtools/spm_eeg_detect_eyeblinks.m index 27baf36..7e80793 100644 --- a/toolbox/MEEGtools/spm_eeg_detect_eyeblinks.m +++ b/toolbox/MEEGtools/spm_eeg_detect_eyeblinks.m @@ -6,6 +6,8 @@ % (optional) fields of S: % .stdthresh - threshold to reject things that look like % eye-blinks but probably aren't (default: 3) +% .overwrite - 1 - replace previous eybelink events (default) +% 0 - append % Output: % D - MEEG object with added eyeblink events(also % written on disk) @@ -13,9 +15,9 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Laurence Hunt -% $Id: spm_eeg_detect_eyeblinks.m 3541 2009-11-06 17:34:40Z guillaume $ +% $Id: spm_eeg_detect_eyeblinks.m 3858 2010-04-30 20:56:20Z vladimir $ -SVNrev = '$Rev: 3541 $'; +SVNrev = '$Rev: 3858 $'; %-Startup %-------------------------------------------------------------------------- @@ -74,6 +76,10 @@ stdthresh = 3; end +if ~isfield(S, 'overwrite') + S.overwrite = spm_input('Overwrite previous?','+1','yes|no',[1 0], 1); +end + %% get EOG data if length(eogchan)~=1 error('More than one EOG channel - not currently supported') @@ -82,11 +88,7 @@ eog_data = D(eogchan,:,:); %% filter data at 1-15Hz (eyeblink duration typically 100-300ms) and demean -lp = 2*1./D.fsample; -hp = 2*15./D.fsample; -h1=fir1(1001,[lp hp]); -%to view filter properties can use: fvtool(h1,1,'Fs',D.fsample) -eog_filt = detrend(spm_filtfilt(h1,1,eog_data), 'constant'); +eog_filt = detrend(ft_preproc_bandpassfilter(eog_data, D.fsample, [1 15], 1001, 'fir'), 'constant'); %% find eye-movements @@ -154,6 +156,17 @@ ev = ev{1}; end + + if ~isempty(ev) && S.overwrite + ind1 = strmatch('artefact', {ev.type}, 'exact'); + if ~isempty(ind1) + ind2 = strmatch('eyeblink', {ev(ind1).value}, 'exact'); + if ~isempty(ind2) + ev(ind1(ind2)) = []; + end + end + end + Nevents = numel(ev); for i=1:numel(ctime) ev(Nevents+i).type = 'artefact'; diff --git a/toolbox/MEEGtools/spm_eeg_dipole_waveforms.m b/toolbox/MEEGtools/spm_eeg_dipole_waveforms.m index d9284c7..72a7f00 100644 --- a/toolbox/MEEGtools/spm_eeg_dipole_waveforms.m +++ b/toolbox/MEEGtools/spm_eeg_dipole_waveforms.m @@ -23,7 +23,7 @@ % % Vladimir Litvak -% $Id: spm_eeg_dipole_waveforms.m 3120 2009-05-13 13:01:03Z vladimir $ +% $Id: spm_eeg_dipole_waveforms.m 3833 2010-04-22 14:49:48Z vladimir $ [Finter,Fgraph] = spm('FnUIsetup','Dipole waveform extraction', 0); %% @@ -90,7 +90,7 @@ if strncmp(modality, D.inv{D.val}.forward(m).modality, 3) vol = D.inv{D.val}.forward(m).vol; if isa(vol, 'char') - vol = fileio_read_vol(vol); + vol = ft_read_vol(vol); end datareg = D.inv{D.val}.datareg(m); end @@ -102,12 +102,12 @@ [U, L, V] = svd(M1(1:3, 1:3)); M1(1:3,1:3) =U*V'; -vol = forwinv_transform_vol(M1, vol); -sens = forwinv_transform_sens(M1, sens); +vol = ft_transform_vol(M1, vol); +sens = ft_transform_sens(M1, sens); chanind = setdiff(meegchannels(D, modality), badchannels(D)); -[vol, sens] = forwinv_prepare_vol_sens(vol, sens, 'channel', D.chanlabels(chanind)); +[vol, sens] = ft_prepare_vol_sens(vol, sens, 'channel', D.chanlabels(chanind)); %% ============ Compute lead fields for the dipoles @@ -121,7 +121,7 @@ Gxyz = zeros(length(chanind), 3*nvert); for i = 1:nvert - Gxyz(:, (3*i- 2):(3*i)) = forwinv_compute_leadfield(pnt(i, :), sens, vol, 'reducerank', reducerank); + Gxyz(:, (3*i- 2):(3*i)) = ft_compute_leadfield(pnt(i, :), sens, vol, 'reducerank', reducerank); if ismember(i, Ibar) spm_progress_bar('Set', i); drawnow; diff --git a/toolbox/MEEGtools/spm_eeg_erp_correction.m b/toolbox/MEEGtools/spm_eeg_erp_correction.m new file mode 100644 index 0000000..80b6065 --- /dev/null +++ b/toolbox/MEEGtools/spm_eeg_erp_correction.m @@ -0,0 +1,104 @@ +function D = spm_eeg_erp_correction(S) +% Applies corrections to ERPs or single trials as in DCM-ERP +% This can be used to make a sensor level analysis or source reconstruction +% consistent with DCM. +% FORMAT D = spm_eeg_erp_correction(S) +% +% S - optional input struct +% (optional) fields of S: +% S.D - MEEG object or filename of M/EEG mat-file with epoched data +% S.detrend - detrending order (0 for no detrending) +% S.hanning - apply Hanning window (true or false) +% +% Output: +% D - MEEG object (also written on disk) +%__________________________________________________________________________ +% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging + +% Melanie Boly +% $Id: spm_eeg_erp_correction.m 3771 2010-03-10 11:41:11Z guillaume $ + +SVNrev = '$Rev: 3771 $'; + +%-Startup +%-------------------------------------------------------------------------- +spm('FnBanner', mfilename, SVNrev); +spm('FigName','Correct ERPs'); spm('Pointer','Arrow'); + +if nargin == 0 + S = []; +end + +%-Get MEEG object +%-------------------------------------------------------------------------- +try + D = S.D; +catch + [D, sts] = spm_select(1, 'mat', 'Select M/EEG mat file'); + if ~sts, D = []; return; end + S.D = D; +end + +D = spm_eeg_load(D); + + +if isequal(D.type, 'continuous') + error('Corrections can only be applied to epoched or averaged datasets.'); +end + + +%-Get parameters +%-------------------------------------------------------------------------- +if ~isfield(S, 'detrend') + S.detrend = spm_input('Detrend order', '+1', 'n', '2', 1); +end + +if ~isfield(S, 'hanning') + S.hanning = spm_input('Apply Hanning?','+1','yes|no',[1 0], 0); +end + +Ns = D.nsamples; + +%-Confounds - DCT: +%-------------------------------------------------------------------------- +if S.detrend == 0 + X0 = sparse(Ns, 1); +else + X0 = spm_dctmtx(Ns, S.detrend); +end +R = speye(Ns) - X0*X0'; + +%-Hanning +%-------------------------------------------------------------------------- +if S.hanning + R = R*diag(spm_hanning(Ns))*R; +end + +Dnew = clone(D, ['C' D.fnamedat]); + + +spm_progress_bar('Init', D.ntrials, 'Trials filtered'); drawnow; +if D.ntrials > 100, Ibar = floor(linspace(1, D.ntrials,100)); +else Ibar = [1:D.ntrials]; end + +spm('Pointer','Watch'); + +%-Adjust data +%-------------------------------------------------------------------------- +for i = 1:D.ntrials + Dnew(Dnew.meegchannels,:,i) = (R*spm_squeeze(D(D.meegchannels,:,i), 3)')'; + + if ismember(i, Ibar), spm_progress_bar('Set', i); end +end + +spm_progress_bar('Clear'); + +D = Dnew; + +D = D.history(mfilename, S); + +save(D); + +%-Cleanup +%-------------------------------------------------------------------------- +spm('FigName','Correct ERPs: done'); spm('Pointer','Arrow'); diff --git a/toolbox/MEEGtools/spm_eeg_ft_artefact_visual.m b/toolbox/MEEGtools/spm_eeg_ft_artefact_visual.m index 359ab48..9f02f28 100644 --- a/toolbox/MEEGtools/spm_eeg_ft_artefact_visual.m +++ b/toolbox/MEEGtools/spm_eeg_ft_artefact_visual.m @@ -10,7 +10,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Vladimir Litvak -% $Id: spm_eeg_ft_artefact_visual.m 3384 2009-09-10 18:36:56Z vladimir $ +% $Id: spm_eeg_ft_artefact_visual.m 4001 2010-07-19 12:23:23Z vladimir $ [Finter,Fgraph,CmdLine] = spm('FnUIsetup', 'Fieldtrip visual artefact rejection',0); @@ -43,7 +43,7 @@ data.trial = data.trial(trlind); data.time = data.time(trlind); -data.cfg.trl(:, 4) = 1:length(trlind); +data.trialinfo = [1:length(trlind)]'; cfg=[]; @@ -73,7 +73,7 @@ % Figure out based on the output of FT function what trials and channels to % reject trlsel = ones(1, length(trlind)); -trlsel(data.cfg.trl(:, 4)) = 0; +trlsel(data.trialinfo (:, 1)) = 0; D = reject(D, trlind, trlsel); diff --git a/toolbox/MEEGtools/spm_eeg_ft_datareg_manual.m b/toolbox/MEEGtools/spm_eeg_ft_datareg_manual.m index 537dd98..e7cb531 100644 --- a/toolbox/MEEGtools/spm_eeg_ft_datareg_manual.m +++ b/toolbox/MEEGtools/spm_eeg_ft_datareg_manual.m @@ -10,7 +10,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Vladimir Litvak -% $Id: spm_eeg_ft_datareg_manual.m 3183 2009-06-04 15:16:41Z vladimir $ +% $Id: spm_eeg_ft_datareg_manual.m 3833 2010-04-22 14:49:48Z vladimir $ % initialise %-------------------------------------------------------------------------- @@ -38,8 +38,8 @@ usepolhemus = spm_input('Use polhemus?', 1, 'yes|no', [1, 0]); if usepolhemus - meegfid = fileio_read_headshape(spm_select(1, '\.*', 'Select polhemus file')); - meegfid = forwinv_convert_units(meegfid, 'mm'); + meegfid = ft_read_headshape(spm_select(1, '\.*', 'Select polhemus file')); + meegfid = ft_convert_units(meegfid, 'mm'); else meegfid = D.fiducials; end @@ -120,7 +120,7 @@ M1 = inv(M) * M1; case 'align2' M1 = spm_eeg_inv_rigidreg(newmrifid.fid.pnt', meegfid.fid.pnt'); - tempfid = forwinv_transform_headshape(M1, meegfid); + tempfid = ft_transform_headshape(M1, meegfid); tempfid.fid.pnt(:, 2) = tempfid.fid.pnt(:, 2)- tempfid.fid.pnt(1, 2)+ newmrifid.fid.pnt(1, 2); tempfid.fid.pnt(:, 3) = tempfid.fid.pnt(:, 3)- mean(tempfid.fid.pnt(2:3, 3))+ mean(newmrifid.fid.pnt(2:3, 3)); M1 = spm_eeg_inv_rigidreg(tempfid.fid.pnt', meegfid.fid.pnt'); @@ -134,7 +134,7 @@ S.useheadshape = ~isempty(S.sourcefid.pnt); M1 = spm_eeg_inv_datareg(S); end - meegfid = forwinv_transform_headshape(M1, meegfid); + meegfid = ft_transform_headshape(M1, meegfid); end %% cfg = []; @@ -142,7 +142,7 @@ cfg.template.headshape = newmrifid; cfg = ft_interactiverealign(cfg); -meegfid = forwinv_transform_headshape(cfg.m, meegfid); +meegfid = ft_transform_headshape(cfg.m, meegfid); M1 = cfg.m * M1; @@ -159,7 +159,7 @@ D.inv{val}.datareg = struct([]); if ~isempty(D.sensors('EEG')) - D.inv{val}.datareg(ind).sensors = forwinv_transform_sens(M1, D.sensors('EEG')); + D.inv{val}.datareg(ind).sensors = ft_transform_sens(M1, D.sensors('EEG')); D.inv{val}.datareg(ind).fid_eeg = D.inv{val}.datareg(ind).sensors; D.inv{val}.datareg(ind).fid_mri = newmrifid; D.inv{val}.datareg(ind).toMNI = D.inv{val}.mesh.Affine; @@ -170,8 +170,8 @@ if ~isempty(D.sensors('MEG')) D.inv{val}.datareg(ind).sensors = D.sensors('MEG'); - D.inv{val}.datareg(ind).fid_eeg = forwinv_transform_headshape(inv(M1), meegfid); - D.inv{val}.datareg(ind).fid_mri = forwinv_transform_headshape(inv(M1), newmrifid); + D.inv{val}.datareg(ind).fid_eeg = ft_transform_headshape(inv(M1), meegfid); + D.inv{val}.datareg(ind).fid_mri = ft_transform_headshape(inv(M1), newmrifid); D.inv{val}.datareg(ind).toMNI = D.inv{val}.mesh.Affine*M1; D.inv{val}.datareg(ind).fromMNI = inv(D.inv{val}.datareg(ind).toMNI); D.inv{val}.datareg(ind).modality = 'MEG'; diff --git a/toolbox/MEEGtools/spm_eeg_ft_dipolefitting.m b/toolbox/MEEGtools/spm_eeg_ft_dipolefitting.m index c91e0e3..9737c8b 100644 --- a/toolbox/MEEGtools/spm_eeg_ft_dipolefitting.m +++ b/toolbox/MEEGtools/spm_eeg_ft_dipolefitting.m @@ -9,7 +9,7 @@ % % Vladimir Litvak -% $Id: spm_eeg_ft_dipolefitting.m 3390 2009-09-11 10:58:17Z vladimir $ +% $Id: spm_eeg_ft_dipolefitting.m 3833 2010-04-22 14:49:48Z vladimir $ [Finter,Fgraph] = spm('FnUIsetup','Fieldtrip dipole fitting', 0); %% @@ -51,7 +51,7 @@ if strncmp(modality, D.inv{D.val}.forward(m).modality, 3) vol = D.inv{D.val}.forward(m).vol; if isa(vol, 'char') - vol = fileio_read_vol(vol); + vol = ft_read_vol(vol); end datareg = D.inv{D.val}.datareg(m); end @@ -63,12 +63,12 @@ [U, L, V] = svd(M1(1:3, 1:3)); M1(1:3,1:3) =U*V'; -vol = forwinv_transform_vol(M1, vol); -sens = forwinv_transform_sens(M1, sens); +vol = ft_transform_vol(M1, vol); +sens = ft_transform_sens(M1, sens); chanind = setdiff(meegchannels(D, modality), D.badchannels); -%[vol, sens] = forwinv_prepare_vol_sens(vol, sens, 'channel', D.chanlabels(chanind)); +%[vol, sens] = ft_prepare_vol_sens(vol, sens, 'channel', D.chanlabels(chanind)); %% ============ Select the data and convert to Fieldtrip struct diff --git a/toolbox/MEEGtools/spm_eeg_ft_multitaper_coherence.m b/toolbox/MEEGtools/spm_eeg_ft_multitaper_coherence.m index eb1fdea..094b983 100644 --- a/toolbox/MEEGtools/spm_eeg_ft_multitaper_coherence.m +++ b/toolbox/MEEGtools/spm_eeg_ft_multitaper_coherence.m @@ -32,10 +32,10 @@ % Copyright (C) 2008 Institute of Neurology, UCL % Vladimir Litvak -% $Id: spm_eeg_ft_multitaper_coherence.m 3435 2009-10-01 10:24:08Z vladimir $ +% $Id: spm_eeg_ft_multitaper_coherence.m 3761 2010-03-08 17:01:49Z vladimir $ %% -SVNrev = '$Rev: 3435 $'; +SVNrev = '$Rev: 3761 $'; %-Startup %-------------------------------------------------------------------------- @@ -263,12 +263,22 @@ [Y, W] = spm_robust_average(permute(cat(4, squeeze(abs(freq.crsspctrm(w, crossind , :, :))),... squeeze(freq.powspctrm(w, powind(1), :, :)), squeeze(freq.powspctrm(w, powind(2), :, :))), ... [2 3 1 4]), 3, ks); - cross =abs(sum(squeeze(permute(freq.crsspctrm(w, crossind, :, :), [2 3 4 1])).*squeeze(W(:, :, :, 1)), 3))./... - squeeze(sum(W(:, :, :, 1), 3)); - pow1 = sum(squeeze(permute(freq.powspctrm(w, powind(1), :, :), [2 3 4 1])).*squeeze(W(:, :, :, 2)), 3)./... - squeeze(sum(W(:, :, :, 2), 3)); - pow2 = sum(squeeze(permute(freq.powspctrm(w, powind(2), :, :), [2 3 4 1])).*squeeze(W(:, :, :, 3)), 3)./... - squeeze(sum(W(:, :, :, 3), 3)); + + cross = squeeze(permute(freq.crsspctrm(w, crossind, :, :), [2 3 4 1])); + WW = squeeze(W(:, :, :, 1)); + cross(WW == 0) = 0; % This is to get rid of NaNs because NaN*0 == NaN + cross = abs(sum(cross.*WW, 3))./squeeze(sum(WW, 3)); + + pow1 = squeeze(permute(freq.powspctrm(w, powind(1), :, :), [2 3 4 1])); + WW = squeeze(W(:, :, :, 2)); + pow1(WW == 0) = 0; + pow1 = sum(pow1.*WW, 3)./squeeze(sum(WW, 3)); + + pow2 = squeeze(permute(freq.powspctrm(w, powind(2), :, :), [2 3 4 1])); + WW = squeeze(W(:, :, :, 3)); + pow2(WW == 0) = 0; + pow2 = sum(pow2.*WW, 3)./squeeze(sum(WW, 3)); + Dcoh(j, :, :, i) = shiftdim(cross./sqrt(pow1.*pow2), -1); if savew @@ -276,12 +286,22 @@ shiftdim(cat(2, W(:, :, :, 1), W(:, :, :, 2), W(:, :, :, 3)), -1); end else - cross =abs(sum(squeeze(permute(freq.crsspctrm(w, crossind, :, :), [2 3 4 1])).*squeeze(W(:, :, w, 1)), 3))./... - squeeze(sum(W(:, :, w, 1), 3)); - pow1 = sum(squeeze(permute(freq.powspctrm(w, powind(1), :, :), [2 3 4 1])).*squeeze(W(:, :, w, 2)), 3)./... - squeeze(sum(W(:, :, w, 2), 3)); - pow2 = sum(squeeze(permute(freq.powspctrm(w, powind(2), :, :), [2 3 4 1])).*squeeze(W(:, :, w, 3)), 3)./... - squeeze(sum(W(:, :, w, 3), 3)); + + cross = squeeze(permute(freq.crsspctrm(w, crossind, :, :), [2 3 4 1])); + WW = squeeze(W(:, :, w, 1)); + cross(WW == 0) = 0; + cross = abs(sum(cross.*WW, 3))./squeeze(sum(WW, 3)); + + pow1 = squeeze(permute(freq.powspctrm(w, powind(1), :, :), [2 3 4 1])); + WW = squeeze(W(:, :, w, 2)); + pow1(WW == 0) = 0; + pow1 = sum(pow1.*WW, 3)./squeeze(sum(WW, 3)); + + pow2 = squeeze(permute(freq.powspctrm(w, powind(2), :, :), [2 3 4 1])); + WW = squeeze(W(:, :, w, 3)); + pow2(WW == 0) = 0; + pow2 = sum(pow2.*WW, 3)./squeeze(sum(WW, 3)); + Dcoh(j, :, :, i) = shiftdim(cross./sqrt(pow1.*pow2), -1); end end diff --git a/toolbox/MEEGtools/spm_eeg_ft_multitaper_powermap.m b/toolbox/MEEGtools/spm_eeg_ft_multitaper_powermap.m index c98483b..7127386 100644 --- a/toolbox/MEEGtools/spm_eeg_ft_multitaper_powermap.m +++ b/toolbox/MEEGtools/spm_eeg_ft_multitaper_powermap.m @@ -22,10 +22,10 @@ % Copyright (C) 2009 Institute of Neurology, UCL % Vladimir Litvak -% $Id: spm_eeg_ft_multitaper_powermap.m 3612 2009-12-03 23:45:55Z vladimir $ +% $Id: spm_eeg_ft_multitaper_powermap.m 3729 2010-02-17 12:47:21Z vladimir $ %% -SVNrev = '$Rev: 3612 $'; +SVNrev = '$Rev: 3729 $'; %-Startup %-------------------------------------------------------------------------- @@ -61,6 +61,10 @@ %-Configure the spectral analysis %-------------------------------------------------------------------------- +if ~isfield(S, 'timewin') + S.timewin = spm_input('Time window (ms)', '+1', 'r', num2str(1000*[D.time(1) D.time(end)]), 2); +end + if ~isfield(S, 'freqwin') S.freqwin = spm_input('Frequency window (Hz)', '+1', 'r', '0 90', 2); end @@ -78,6 +82,12 @@ %-Run the Fieldtrip code %-------------------------------------------------------------------------- +cfg = []; +cfg.latency = 1e-3*S.timewin; +cfg.keeptrials = 'yes'; + +data = ft_timelockanalysis(cfg, data); + cfg = []; cfg.output ='pow'; diff --git a/toolbox/MEEGtools/spm_eeg_megheadloc.m b/toolbox/MEEGtools/spm_eeg_megheadloc.m index 5cd302f..381649c 100644 --- a/toolbox/MEEGtools/spm_eeg_megheadloc.m +++ b/toolbox/MEEGtools/spm_eeg_megheadloc.m @@ -46,7 +46,7 @@ % Copyright (C) 2008 Institute of Neurology, UCL % Vladimir Litvak, Robert Oostenveld -% $Id: spm_eeg_megheadloc.m 3341 2009-09-01 14:23:49Z vladimir $ +% $Id: spm_eeg_megheadloc.m 3833 2010-04-22 14:49:48Z vladimir $ [Finter,Fgraph,CmdLine] = spm('FnUIsetup','MEG head locations',0); @@ -67,7 +67,7 @@ try for i = 1:size(D, 1) F{i} = spm_eeg_load(deblank(D(i, :))); - if ~forwinv_senstype(chanlabels(F{i}), 'ctf') + if ~ft_senstype(chanlabels(F{i}), 'ctf') warning('Head localization is not supported for this data') iswork =0; end @@ -176,21 +176,27 @@ utmpdat = unique(tmpdat', 'rows')'; if S.rejectwithin && ~tracking_lost - try - pdist([0;1]); - pdistworks = 1; - catch - pdistworks = 0; - end - - if pdistworks - dN=max(pdist(utmpdat(1:3, :)')); - dL=max(pdist(utmpdat(4:6, :)')); - dR=max(pdist(utmpdat(7:9, :)')); + if size(utmpdat, 2) == 1 + dN = 0; + dL = 0; + dR = 0; else - dN=max(slowpdist(utmpdat(1:3, :)')); - dL=max(slowpdist(utmpdat(4:6, :)')); - dR=max(slowpdist(utmpdat(7:9, :)')); + try + pdist([0;1]); + pdistworks = 1; + catch + pdistworks = 0; + end + + if pdistworks + dN=max(pdist(utmpdat(1:3, :)')); + dL=max(pdist(utmpdat(4:6, :)')); + dR=max(pdist(utmpdat(7:9, :)')); + else + dN=max(slowpdist(utmpdat(1:3, :)')); + dL=max(slowpdist(utmpdat(4:6, :)')); + dR=max(slowpdist(utmpdat(7:9, :)')); + end end end @@ -202,7 +208,7 @@ dat = [dat nan(9, 1)]; trlind = [trlind k]; fileind= [fileind f]; - else + else D{f} = reject(D{f}, k, 1); end end @@ -267,11 +273,11 @@ if S.rejectbetween && length(trlind)>1 && ~all(all(isnan(dat))) % If there was loss of tracking for just some of the trials, reject - % them and continue with the rest. + % them and continue with the rest. nanind = find(any(isnan(dat))); if ~isempty(nanind) for i = length(nanind) - D{fileind(nanind)} = reject(D{fileind(nanind)}, trlind(nanind), 1); + D{fileind(nanind(i))} = reject(D{fileind(nanind(i))}, trlind(nanind(i)), 1); end dat(:, nanind) = []; trlind(nanind) = []; @@ -386,7 +392,7 @@ grad = sensors(D{1}, 'MEG'); - newgrad = forwinv_transform_sens(M*inv(M1), grad); + newgrad = ft_transform_sens(M*inv(M1), grad); if S.toplot figure(pntfig); @@ -413,7 +419,7 @@ axis equal off end - newfid = forwinv_transform_headshape(M*inv(M1), fiducials(D{1})); + newfid = ft_transform_headshape(M*inv(M1), fiducials(D{1})); for f = 1:numel(D) D{f} = sensors(D{f}, 'MEG', newgrad); diff --git a/toolbox/MEEGtools/spm_eeg_reref_eeg.m b/toolbox/MEEGtools/spm_eeg_reref_eeg.m index 7346f20..7e34411 100644 --- a/toolbox/MEEGtools/spm_eeg_reref_eeg.m +++ b/toolbox/MEEGtools/spm_eeg_reref_eeg.m @@ -19,9 +19,9 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Rik Henson -% $Id: spm_eeg_reref_eeg.m 3539 2009-11-05 22:40:56Z vladimir $ +% $Id: spm_eeg_reref_eeg.m 3701 2010-01-28 13:01:40Z rik $ -SVNrev = '$Rev: 3539 $'; +SVNrev = '$Rev: 3701 $'; %-Startup %-------------------------------------------------------------------------- @@ -71,18 +71,19 @@ refchan = S.refchan; end -if ~all(ismember(refchan, eegchan)) +refind = find(ismember(eegchan, refchan)); + +if length(refind) ~= length(refchan) error('Not all S.refchan are valid indices for (non-bad) EEG channels') end -tra = eye(D.nchannels); - -tra(eegchan,refchan) = tra(eegchan,refchan) - 1/length(refchan); +tra = eye(length(eegchan)); +tra(:,refind) = tra(:,refind) - 1/length(refchan); S1=[]; S1.D = D; -S1.montage.labelorg = D.chanlabels; -S1.montage.labelnew = D.chanlabels; +S1.montage.labelorg = D.chanlabels(eegchan); +S1.montage.labelnew = D.chanlabels(eegchan); S1.montage.tra = tra; S1.keepothers = 'yes'; S1.updatehistory = 0; diff --git a/toolbox/MEEGtools/spm_eeg_spatial_confounds.m b/toolbox/MEEGtools/spm_eeg_spatial_confounds.m index f587f8d..3509c9e 100644 --- a/toolbox/MEEGtools/spm_eeg_spatial_confounds.m +++ b/toolbox/MEEGtools/spm_eeg_spatial_confounds.m @@ -10,10 +10,10 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Vladimir Litvak -% $Id: spm_eeg_spatial_confounds.m 3429 2009-09-29 09:41:36Z vladimir $ +% $Id: spm_eeg_spatial_confounds.m 3833 2010-04-22 14:49:48Z vladimir $ -SVNrev = '$Rev: 3429 $'; +SVNrev = '$Rev: 3833 $'; %-Startup %-------------------------------------------------------------------------- @@ -88,7 +88,7 @@ vol = D.inv{D.val}.forward(m).vol; if isa(vol, 'char') - vol = fileio_read_vol(vol); + vol = ft_read_vol(vol); end datareg = D.inv{D.val}.datareg(m); @@ -98,8 +98,8 @@ [U, L, V] = svd(M1(1:3, 1:3)); M1(1:3,1:3) =U*V'; - vol = forwinv_transform_vol(M1, vol); - sens = forwinv_transform_sens(M1, sens); + vol = ft_transform_vol(M1, vol); + sens = ft_transform_sens(M1, sens); chanind = setdiff(meegchannels(D, modalities{k}), badchannels(D)); @@ -107,7 +107,7 @@ continue; end - [vol, sens] = forwinv_prepare_vol_sens(vol, sens, 'channel', D.chanlabels(chanind)); + [vol, sens] = ft_prepare_vol_sens(vol, sens, 'channel', D.chanlabels(chanind)); if strncmp(modalities{k}, 'MEG', 3) @@ -116,7 +116,7 @@ reducerank = 3; end - L = forwinv_compute_leadfield(eyes.vertices, sens, vol, 'reducerank', reducerank); + L = ft_compute_leadfield(eyes.vertices, sens, vol, 'reducerank', reducerank); [sel1, sel2] = spm_match_str(sconf.label, D.chanlabels(chanind)); diff --git a/toolbox/MEEGtools/spm_eeg_split_conditions.m b/toolbox/MEEGtools/spm_eeg_split_conditions.m new file mode 100644 index 0000000..4918587 --- /dev/null +++ b/toolbox/MEEGtools/spm_eeg_split_conditions.m @@ -0,0 +1,104 @@ +function D = spm_eeg_split_conditions(S) +% Splits a file into different conditions in order to facilitate TF +% processing. The idea is to create several smaller files, run TF, then +% aveage within the condition files using spm_eeg_average_tf and lastly, +% merge again. +% FORMAT D = spm_eeg_split_conditions(S) +% +% S - optional input struct +% (optional) fields of S: +% D - MEEG object or filename of M/EEG mat-file with epoched data +% +% Output: +% D - MEEG object (also written on disk) +% +% The function also physically removes bad trials. +% +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Dominik R Bach +% based on spm_eeg_remove_bad_trials + +SVNrev = '$Rev: 3745 $'; + +%-Startup +%-------------------------------------------------------------------------- +spm('FnBanner', mfilename, SVNrev); +spm('FigName','Remove bad trials'); spm('Pointer','Watch'); + +%-Get MEEG object +%-------------------------------------------------------------------------- +try + D = S.D; +catch + [D, sts] = spm_select(1, 'mat', 'Select M/EEG mat file'); + if ~sts, D = []; return; end +end + +D = spm_eeg_load(D); + +%-Check that there is any good data available +%-------------------------------------------------------------------------- +if ntrials(D)==0 || all(reject(D)) + warning('No good trials were found. Nothing to do.'); + return; +end + +%-select trials +%-------------------------------------------------------------------------- +cl = D.condlist; + +goodtrials = []; +for i = 1:numel(cl) + goodtrials{i} = [pickconditions(D, cl{i}, 1)]; +end + +%-Generate new files & copy data +%-------------------------------------------------------------------------- + +for i = 1:length(goodtrials) + spm_progress_bar('Init', length(goodtrials{i}), 'Trials copied'); + if length(goodtrials{i}) > 100, Ibar = floor(linspace(1, length(goodtrials{i}), 100)); + else Ibar = [1:length(goodtrials{i})]; end + + fn = fname(D); + fn = ['r', fn(1:(end-4)), sprintf('_%02.0f.dat', i)]; + if strncmpi(D.transformtype,'TF',2) % TF and TFphase + Dnew = clone(D, fn, [D.nchannels D.nfrequencies D.nsamples numel(goodtrials{i})]); + else + Dnew = clone(D, fn, [D.nchannels D.nsamples numel(goodtrials{i})]); + end + + for trl = 1:numel(goodtrials{i}) + if strncmpi(D.transformtype,'TF',2) % TF and TFphase + Dnew(:, :, :, trl) = D(:, :, :, goodtrials{i}(trl)); + else + Dnew(:, :, trl) = D(:, :, goodtrials{i}(trl)); + end + end; + + if ismember(i, Ibar), spm_progress_bar('Set', i); end + + %-Copy trial-specific data. + %-------------------------------------------------------------------------- + Dnew = conditions(Dnew, [], conditions(D, goodtrials{i})); + Dnew = repl(Dnew, [], repl(D, goodtrials{i})); + Dnew = events(Dnew, [], events(D, goodtrials{i})); + Dnew = trialonset(Dnew, [], trialonset(D, goodtrials{i})); + + %-Save the new M/EEG dataset + %-------------------------------------------------------------------------- + Dnew = Dnew.history(mfilename, S); + save(Dnew); + + DD{i} = Dnew; +end % + +spm_progress_bar('Clear'); + +D = DD; + +%-Cleanup +%-------------------------------------------------------------------------- +spm('FigName','Split conditions: done'); spm('Pointer','Arrow'); diff --git a/toolbox/MEEGtools/spm_eeg_var_measures.m b/toolbox/MEEGtools/spm_eeg_var_measures.m index 876a3a4..b4d46a7 100644 --- a/toolbox/MEEGtools/spm_eeg_var_measures.m +++ b/toolbox/MEEGtools/spm_eeg_var_measures.m @@ -11,12 +11,14 @@ % Copyright (C) 2008 Institute of Neurology, UCL % Vladimir Litvak -% $Id: spm_eeg_var_measures.m 3673 2010-01-12 17:49:34Z vladimir $ +% $Id: spm_eeg_var_measures.m 3914 2010-06-02 15:32:58Z vladimir $ [Finter,Fgraph] = spm('FnUIsetup','MEEGtoools VAR measures', 0); -addpath(fullfile(spm('Dir'),'toolbox','spectral')); -addpath(fullfile(spm('Dir'),'toolbox','mixture')); +if ~isdeployed + addpath(fullfile(spm('Dir'),'toolbox','spectral')); + addpath(fullfile(spm('Dir'),'toolbox','mixture')); +end D = spm_eeg_load; @@ -101,7 +103,10 @@ cfg.tapsmofrq = 1; % Frequency resolution % inp = ft_freqanalysis(cfg, data); -coh = ft_freqdescriptives([], inp); + +cfg1 = []; +cfg1.method = 'coh'; +coh = ft_connectivityanalysis(cfg1, inp); %% % Defines how trials are shifted for shift-predictors shift=[2:Ntrials 1]; @@ -114,7 +119,7 @@ sdata.trial(:,c,:)=data.trial(shift,c,:); cfg.channelcmb = {data.label{c}, 'all'}; inp = ft_freqanalysis(cfg, sdata); - sscoh = ft_freqdescriptives([], inp); + sscoh = ft_connectivityanalysis(cfg1, inp); for i=1:size(sscoh.labelcmb, 1) ind=[intersect(strmatch(sscoh.labelcmb(i,1),scoh.labelcmb(:,1),'exact'), ... strmatch(sscoh.labelcmb(i,2),scoh.labelcmb(:,2),'exact'))... diff --git a/toolbox/SRender/spm_config_srender.m b/toolbox/SRender/spm_config_srender.m deleted file mode 100644 index 2da8fd8..0000000 --- a/toolbox/SRender/spm_config_srender.m +++ /dev/null @@ -1,219 +0,0 @@ -function c = spm_config_srender -% Configuration file for surface visualisation -%_______________________________________________________________________ -% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging - -% John Ashburner -% $Id: spm_config_srender.m 2736 2009-02-12 12:23:21Z john $ - -entry = inline(['struct(''type'',''entry'',''name'',name,'... - '''tag'',tag,''strtype'',strtype,''num'',num,''help'',{{}})'],... - 'name','tag','strtype','num'); - -files = inline(['struct(''type'',''files'',''name'',name,'... - '''tag'',tag,''filter'',fltr,''num'',num,''help'',{{}})'],... - 'name','tag','fltr','num'); - -mnu = inline(['struct(''type'',''menu'',''name'',name,'... - '''tag'',tag,''labels'',{labels},''values'',{values},''help'',{{}})'],... - 'name','tag','labels','values'); - -branch = inline(['struct(''type'',''branch'',''name'',name,'... - '''tag'',tag,''val'',{val},''help'',{{}})'],... - 'name','tag','val'); -repeat = inline(['struct(''type'',''repeat'',''name'',name,''tag'',tag,'... - '''values'',{values})'],'name','tag','values'); - -Red = mnu('Red','Red',... - {'0.0','0.2','0.4','0.6','0.8','1.0'},... - {0,0.2,0.4,0.6,0.8,1}); -Red.val = {1}; -Red.help = {['The intensity of the red colouring (0 to 1).']}; - -Green = mnu('Green','Green',... - {'0.0','0.2','0.4','0.6','0.8','1.0'},... - {0,0.2,0.4,0.6,0.8,1}); -Green.val = {1}; -Green.help = {['The intensity of the green colouring (0 to 1).']}; - -Blue = mnu('Blue','Blue',... - {'0.0','0.2','0.4','0.6','0.8','1.0'},... - {0,0.2,0.4,0.6,0.8,1}); -Blue.val = {1}; -Blue.help = {['The intensity of the blue colouring (0 to 1).']}; - -Color = branch('Color','Color',{Red,Green,Blue}); -Color.help = {[... -'Specify the colour using a mixture of red, green and blue. '... -'For example, white is specified by 1,1,1, black is by 0,0,0 and '... -'purple by 1,0,1.']}; - -AmbientStrength = mnu('Ambient Strength','AmbientStrength',... - {'0.0','0.2','0.4','0.6','0.8','1.0'},... - {0,0.2,0.4,0.6,0.8,1}); -AmbientStrength.val = {0.2}; -AmbientStrength.help = {[... -'The strength with which the object reflects ambient '... -'(non-directional) lighting.']}; - -DiffuseStrength = mnu('Diffuse Strength','DiffuseStrength',... - {'0.0','0.2','0.4','0.6','0.8','1.0'},... - {0,0.2,0.4,0.6,0.8,1}); -DiffuseStrength.val = {0.8}; -DiffuseStrength.help = {[... -'The strength with which the object diffusely reflects '... -'light. Mat surfaces reflect light diffusely, whereas '... -'shiny surfaces reflect speculatively.']}; - -SpecularStrength = mnu('Specular Strength','SpecularStrength',... - {'0.0','0.2','0.4','0.6','0.8','1.0'},... - {0,0.2,0.4,0.6,0.8,1}); -SpecularStrength.val = {0.2}; -SpecularStrength.help = {[... -'The strength with which the object specularly reflects '... -'light (i.e. how shiny it is). '... -'Mat surfaces reflect light diffusely, whereas '... -'shiny surfaces reflect speculatively.']}; - -SpecularExponent = mnu('Specular Exponent','SpecularExponent',... - {'0.01','0.1','10','100'},{0.01,0.1,10,100}); -SpecularExponent.val = {10}; -SpecularExponent.help = {[... -'A parameter describing the specular reflectance behaviour. '... -'It relates to the size of the high-lights.']}; - -SpecularColorReflectance = mnu('Specular Color Reflectance',... - 'SpecularColorReflectance',... - {'0.0','0.2','0.4','0.6','0.8','1.0'},... - {0,0.2,0.4,0.6,0.8,1}); -SpecularColorReflectance.val = {0.8}; -SpecularColorReflectance.help = {[... -'Another parameter describing the specular reflectance behaviour.']}; - -FaceAlpha = mnu('Face Alpha','FaceAlpha',... - {'0.0','0.2','0.4','0.6','0.8','1.0'},... - {0,0.2,0.4,0.6,0.8,1}); -FaceAlpha.val = {1}; -FaceAlpha.help = {[... -'The opaqueness of the surface. A value of 1 means it is '... -'opaque, whereas a value of 0 means it is transparent.']}; - -fname = files('Surface File','SurfaceFile','mat',[1 1]); -fname.ufilter = '.*\.gii$'; -fname.help = {[... -'Filename of the surf_*.mat file containing the rendering information. '... -'This can be generated via the surface extraction routine in SPM. '... -'Normally, a surface is extracted from grey and white matter tissue class '... -'images, but it is also possible to threshold e.g. an spmT image so that '... -'activations can be displayed.']}; - -Object = branch('Object','Object',... -{fname,Color,DiffuseStrength,AmbientStrength,SpecularStrength,SpecularExponent,SpecularColorReflectance,FaceAlpha}); -Object.help = {[... -'Each object is a surface (from a surf_*.mat file), which may have a '... -'number of light-reflecting qualities, such as colour and shinyness.']}; - -Objects = repeat('Objects','Objects',{Object}); -Objects.help = {[... -'Several surface objects can be displayed together in different colours '... -'and with different reflective properties.']}; - - - -Position = entry('Position','Position','e',[1 3]); -Position.val = {[100 100 100]}; -Position.help = {'The position of the light in 3D.'}; - -Light = branch('Light','Light',{Position,Color}); -Light.help = {'Specification of a light source in terms of position and colour.'}; - -Lights = repeat('Lights','Lights',{Light}); -Lights.help = {[... -'There should be at least one light specified so that the objects '... -'can be clearly seen.']}; - -sren = branch('Surface Rendering','SRender',{Objects,Lights}); -sren.prog = @spm_srender; -sren.help = {[... -'This utility is for visualising surfaces. Surfaces first need to be '... -'extracted and saved in surf_*.mat files using the surface extraction '... -'routine.']}; - -expr.type = 'entry'; -expr.name = 'Expression'; -expr.tag = 'expression'; -expr.strtype = 's'; -expr.num = [2 Inf]; -expr.val = {'i1'}; -expr.help = {... -'Example expressions (f):',... -' * Mean of six images (select six images)',... -' f = ''(i1+i2+i3+i4+i5+i6)/6''',... -' * Make a binary mask image at threshold of 100',... -' f = ''i1>100''',... -' * Make a mask from one image and apply to another',... -' f = ''i2.*(i1>100)''',[... -' - here the first image is used to make the mask, which is applied to the second image'],... -' * Sum of n images',... -' f = ''i1 + i2 + i3 + i4 + i5 + ...'''}; - -thresh.type = 'entry'; -thresh.name = 'Surface isovalue(s)'; -thresh.tag = 'thresh'; -thresh.num = [1 1]; -thresh.val = {.5}; -thresh.strtype = 'e'; -thresh.help = {['Enter the value at which isosurfaces through ' ... - 'the resulting image is to be computed.']}; - -surf = branch('Surface','surface',{expr,thresh}); -surf.help = {[... -'An expression and threshold for each of the surfaces to be generated.']}; - -surfaces = repeat('Surfaces','Surfaces',{surf}); -surfaces.help = {'Multiple surfaces can be created from the same image data.'}; - -inpt.type = 'files'; -inpt.name = 'Input Images'; -inpt.tag = 'images'; -inpt.filter = 'image'; -inpt.num = [1 Inf]; -inpt.help = {[... -'These are the images that are used by the calculator. They ',... -'are referred to as i1, i2, i3, etc in the order that they are ',... -'specified.']}; - -opts.type = 'branch'; -opts.name = 'Surface Extraction'; -opts.tag = 'SExtract'; -opts.val = {inpt,surfaces}; -opts.prog = @spm_sextract; -opts.vfiles = @filessurf; -opts.help = {[... -'User-specified ',... -'algebraic manipulations are performed on a set of images, with the result being ',... -'used to generate a surface file. The user is prompted to supply images to ',... -'work on and a number of expressions to ',... -'evaluate, along with some thresholds. The expression should be a standard matlab expression, ',... -'within which the images should be referred to as i1, i2, i3,... etc. '... -'An isosurface file is created from the results at the user-specified threshold.']}; - -c = repeat('Rendering','render',{opts,sren}); -c.help = {[... -'This is a toolbox that provides a limited range '... -'of surface rendering options. The idea is to first extract surfaces from '... -'image data, which are saved in rend_*.mat files. '... -'These can then be loaded and displayed as surfaces. '... -'Note that OpenGL rendering is used, which can be problematic '... -'on some computers. The tools are limited - and they do what they do.']}; -return; - - -function vfiles=filessurf(job) -vfiles={}; -[pth,nam,ext] = fileparts(job.images{1}); -for k=1:numel(job.surface), - vfiles{k} = fullfile(pth,sprintf('surf_%s_%.3d.mat',nam,k)); -end; -return; - diff --git a/toolbox/SRender/tbx_cfg_render.m b/toolbox/SRender/tbx_cfg_render.m index 6d70c7b..1b5f52c 100644 --- a/toolbox/SRender/tbx_cfg_render.m +++ b/toolbox/SRender/tbx_cfg_render.m @@ -1,7 +1,10 @@ function render = tbx_cfg_render -% MATLABBATCH Configuration file for toolbox 'Rendering' +% Configuration file for toolbox 'Rendering' +%_______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging -addpath(fullfile(spm('dir'),'toolbox','SRender')); +% John Ashburner +% $Id: tbx_cfg_render.m 3802 2010-03-29 13:07:15Z john $ % --------------------------------------------------------------------- % images Input Images @@ -10,7 +13,7 @@ images.tag = 'images'; images.name = 'Input Images'; images.help = {'These are the images that are used by the calculator. They are referred to as i1, i2, i3, etc in the order that they are specified.'}; -images.filter = 'image'; +images.filter = 'image'; images.ufilter = '.*'; images.num = [1 Inf]; % --------------------------------------------------------------------- @@ -19,7 +22,6 @@ expression = cfg_entry; expression.tag = 'expression'; expression.name = 'Expression'; -%% expression.help = { 'Example expressions (f):' ' * Mean of six images (select six images)' @@ -32,7 +34,6 @@ ' * Sum of n images' ' f = ''i1 + i2 + i3 + i4 + i5 + ...''' }'; -%% expression.strtype = 's'; expression.num = [2 Inf]; expression.val = {'i1'}; @@ -71,9 +72,10 @@ SExtract.name = 'Surface Extraction'; SExtract.val = {images Surfaces }; SExtract.help = {'User-specified algebraic manipulations are performed on a set of images, with the result being used to generate a surface file. The user is prompted to supply images to work on and a number of expressions to evaluate, along with some thresholds. The expression should be a standard matlab expression, within which the images should be referred to as i1, i2, i3,... etc. An isosurface file is created from the results at the user-specified threshold.'}; -SExtract.prog = @spm_sextract; +SExtract.prog = @spm_local_sextract; %SExtract.vfiles = @filessurf; SExtract.vout = @vout_sextract; + % --------------------------------------------------------------------- % SurfaceFile Surface File % --------------------------------------------------------------------- @@ -81,8 +83,8 @@ SurfaceFile.tag = 'SurfaceFile'; SurfaceFile.name = 'Surface File'; SurfaceFile.help = {'Filename of the surf_*.gii file containing the rendering information. This can be generated via the surface extraction routine in SPM. Normally, a surface is extracted from grey and white matter tissue class images, but it is also possible to threshold e.g. an spmT image so that activations can be displayed.'}; -SurfaceFile.filter = 'any'; -SurfaceFile.ufilter = '.*\.gii$'; +SurfaceFile.filter = 'mesh'; +SurfaceFile.ufilter = '.*'; SurfaceFile.num = [1 1]; % --------------------------------------------------------------------- % Red Red @@ -436,7 +438,7 @@ SRender.name = 'Surface Rendering'; SRender.val = {Objects Lights }; SRender.help = {'This utility is for visualising surfaces. Surfaces first need to be extracted and saved in surf_*.gii files using the surface extraction routine.'}; -SRender.prog = @spm_srender; +SRender.prog = @spm_local_srender; % --------------------------------------------------------------------- % render Rendering % --------------------------------------------------------------------- @@ -447,6 +449,17 @@ render.values = {SExtract SRender }; %render.num = [0 Inf]; +%====================================================================== +function spm_local_srender(job) +if ~isdeployed, addpath(fullfile(spm('dir'),'toolbox','SRender')); end +spm_srender(job); + +%====================================================================== +function out=spm_local_sextract(job) +if ~isdeployed, addpath(fullfile(spm('dir'),'toolbox','SRender')); end +out=spm_sextract(job); + +%====================================================================== function dep = vout_sextract(job) dep = cfg_dep; for k=1:numel(job.surface), @@ -456,4 +469,3 @@ % dep(k).tgt_spec = cfg_findspec({{'filter','.*\.gii$'}}); dep(k).tgt_spec = cfg_findspec({{'filter','any'}}); end - diff --git a/toolbox/SRender/tbx_def_render.m b/toolbox/SRender/tbx_def_render.m deleted file mode 100644 index 2cb2e2b..0000000 --- a/toolbox/SRender/tbx_def_render.m +++ /dev/null @@ -1,22 +0,0 @@ -function varargout = tbx_def_render -% MATLABBATCH Defaults file for toolbox 'Rendering' -% This code has been automatically generated. -render.SExtract.images = ''; -render.SExtract.surface.expression = 'i1'; -render.SExtract.surface.thresh = 0.5; -render.SRender.Object.SurfaceFile = ''; -render.SRender.Object.Color.Red = 1; -render.SRender.Object.Color.Green = 1; -render.SRender.Object.Color.Blue = 1; -render.SRender.Object.DiffuseStrength = 0.8; -render.SRender.Object.AmbientStrength = 0.2; -render.SRender.Object.SpecularStrength = 0.2; -render.SRender.Object.SpecularExponent = 10; -render.SRender.Object.SpecularColorReflectance = 0.8; -render.SRender.Object.FaceAlpha = 1; -render.SRender.Light.Position = [100 100 100]; -render.SRender.Light.Color.Red = 1; -render.SRender.Light.Color.Green = 1; -render.SRender.Light.Color.Blue = 1; -varargout{1} = render; -varargout{2} = 'render'; diff --git a/toolbox/Seg/spm_config_preproc8.m b/toolbox/Seg/spm_config_preproc8.m deleted file mode 100644 index cc1bd33..0000000 --- a/toolbox/Seg/spm_config_preproc8.m +++ /dev/null @@ -1,464 +0,0 @@ -function job = spm_config_preproc8 -% Configuration file for Segment jobs -%_______________________________________________________________________ -% Copyright (C) 2008 Wellcome Department of Imaging Neuroscience - -% John Ashburner -% $Id: spm_config_preproc8.m 2264 2008-09-30 18:48:59Z john $ - -addpath(fullfile(spm('dir'),'toolbox','Seg')); -%_______________________________________________________________________ - -entry = inline(['struct(''type'',''entry'',''name'',name,'... - '''tag'',tag,''strtype'',strtype,''num'',num,''help'',{{}})'],... - 'name','tag','strtype','num'); - -files = inline(['struct(''type'',''files'',''name'',name,'... - '''tag'',tag,''filter'',fltr,''num'',num,''help'',{{}})'],... - 'name','tag','fltr','num'); - -mnu = inline(['struct(''type'',''menu'',''name'',name,'... - '''tag'',tag,''labels'',{labels},''values'',{values},''help'',{{}})'],... - 'name','tag','labels','values'); - -branch = inline(['struct(''type'',''branch'',''name'',name,'... - '''tag'',tag,''val'',{val},''help'',{{}})'],... - 'name','tag','val'); - -repeat = inline(['struct(''type'',''repeat'',''name'',name,'... - '''tag'',tag,''values'',{values})'],... - 'name','tag','values'); - -%_______________________________________________________________________ - -vols = files('Volumes','vols','image',[1 Inf]); -vols.help = {[... -'Select scans from this channel for processing. ',... -'If multiple channels are used (eg T1 & T2), then the same order ',... -'of subjects must be specified for each channel and they must be ',... -'in register (same position, size, voxel dims etc..).']}; - -%------------------------------------------------------------------------ - -biasreg = mnu('Bias regularisation','biasreg',{... -'no regularisation (0)','extremely light regularisation (0.00001)',... -'very light regularisation (0.0001)','light regularisation (0.001)',... -'medium regularisation (0.01)','heavy regularisation (0.1)',... -'very heavy regularisation (1)','extremely heavy regularisation (10)'},... -{0, 0.00001, 0.0001, 0.001, 0.01, 0.1, 1.0, 10}); -biasreg.val = {0.0001}; -biasreg.help = {[... -'MR images are usually corrupted by a smooth, spatially varying artifact that modulates the intensity ',... -'of the image (bias). ',... -'These artifacts, although not usually a problem for visual inspection, can impede automated ',... -'processing of the images.'],... -'',... -[... -'An important issue relates to the distinction between intensity variations that arise because of ',... -'bias artifact due to the physics of MR scanning, and those that arise due to different tissue ',... -'properties. The objective is to model the latter by different tissue classes, while modelling the ',... -'former with a bias field. ',... -'We know a priori that intensity variations due to MR physics tend to be spatially smooth, ',... -'whereas those due to different tissue types tend to contain more high frequency information. ',... -'A more accurate estimate of a bias field can be obtained by including prior knowledge about ',... -'the distribution of the fields likely to be encountered by the correction algorithm. ',... -'For example, if it is known that there is little or no intensity non-uniformity, then it would be wise ',... -'to penalise large values for the intensity non-uniformity parameters. ',... -'This regularisation can be placed within a Bayesian context, whereby the penalty incurred is the negative ',... -'logarithm of a prior probability for any particular pattern of non-uniformity.'],... -['Knowing what works best should be a matter '... -'of empirical exploration. For example, if your data has very little '... -'intensity non-uniformity artifact, then the bias regularisation should '... -'be increased. This effectively tells the algorithm that there is very little '... -'bias in your data, so it does not try to model it.']}; - -%------------------------------------------------------------------------ - -biasfwhm = mnu('Bias FWHM','biasfwhm',{... -'30mm cutoff','40mm cutoff','50mm cutoff','60mm cutoff','70mm cutoff',... -'80mm cutoff','90mm cutoff','100mm cutoff','110mm cutoff','120mm cutoff',... -'130mm cutoff','140mm cutoff','150mm cutoff','No correction'},... -{30,40,50,60,70,80,90,100,110,120,130,140,150,Inf}); -biasfwhm.val = {60}; -biasfwhm.help = {[... -'FWHM of Gaussian smoothness of bias. ',... -'If your intensity non-uniformity is very smooth, then choose a large ',... -'FWHM. This will prevent the algorithm from trying to model out intensity variation ',... -'due to different tissue types. The model for intensity non-uniformity is one ',... -'of i.i.d. Gaussian noise that has been smoothed by some amount, ',... -'before taking the exponential. ',... -'Note also that smoother bias fields need fewer parameters to describe them. ',... -'This means that the algorithm is faster for smoother intensity non-uniformities.']}; - -%------------------------------------------------------------------------ - -biascor = mnu('Save Bias Corrected','write',... - {'Save Nothing','Save Bias Corrected',... - 'Save Bias Field','Save Field and Corrected'},{[0 0],[0 1],[1 0],[1 1]}); -biascor.val = {[0 0]}; -biascor.help = {[... -'This is the option to save a bias corrected version of your images from this channel, or/and ',... -'the estimated bias field. ',... -'MR images are usually corrupted by a smooth, spatially varying artifact that modulates the intensity ',... -'of the image (bias). ',... -'These artifacts, although not usually a problem for visual inspection, can impede automated ',... -'processing of the images. The bias corrected version should have more uniform intensities within ',... -'the different types of tissues.']}; - -%------------------------------------------------------------------------ - -channel = branch('Channel','channel',{vols,biasreg,biasfwhm,biascor}); -channel.help = {[... -'A channel for processing. ',... -'If multiple channels are used (eg T1 & T2), then the same order ',... -'of subjects must be specified for each channel and they must be ',... -'in register (same position, size, voxel dims etc..).']}; - -%------------------------------------------------------------------------ - -data = repeat('Data','data',{channel}); -data.num = [1 Inf]; -data.val = {channel}; -data.help = {[... -'Specify the number of different channels (for multi-spectral classification). ',... -'If you have scans of different contrasts for each of the subjects, then it is ',... -'possible to combine the information from them in order to improve the ',... -'segmentation accuracy. Note that only the first channel of data is used for the ',... -'initial affine registration with the tissue probability maps.']}; - -%------------------------------------------------------------------------ - -tpm = files('Tissue probability map','tpm','image',[1 1]); -tpm.help = {... -[... -'Select the tissue probability image for this class. '... -'These should be maps of eg grey matter, white matter ',... -'or cerebro-spinal fluid probability. '... -'A nonlinear deformation field is estimated that best overlays the '... -'tissue probability maps on the individual subjects'' image. '... -'The default tissue probability maps are modified versions of the '... -'ICBM Tissue Probabilistic Atlases.',... -'These tissue probability maps are kindly provided by the ',... -'International Consortium for Brain ',... -'Mapping, John C. Mazziotta and Arthur W. Toga. ',... -'http://www.loni.ucla.edu/ICBM/ICBM_TissueProb.html. ',... -'The original data are derived from 452 T1-weighted scans, ',... -'which were aligned with an atlas space, corrected for scan ',... -'inhomogeneities, and classified ',... -'into grey matter, white matter and cerebrospinal fluid. ',... -'These data were then affine registered to the MNI space and ',... -'down-sampled to 2mm resolution.'],... -'',... -[... -'Rather than assuming stationary prior probabilities based upon mixing '... -'proportions, additional information is used, based on other subjects'' brain '... -'images. Priors are usually generated by registering a large number of '... -'subjects together, assigning voxels to different tissue types and averaging '... -'tissue classes over subjects. '... -'Three tissue classes are used: grey matter, white matter and cerebro-spinal fluid. '... -'A fourth class is also used, which is simply one minus the sum of the first three. '... -'These maps give the prior probability of any voxel in a registered image '... -'being of any of the tissue classes - irrespective of its intensity.'],... -'',... -[... -'The model is refined further by allowing the tissue probability maps to be '... -'deformed according to a set of estimated parameters. '... -'This allows spatial normalisation and segmentation to be combined into '... -'the same model.']}; - -%------------------------------------------------------------------------ - -ngaus = mnu('Num. Gaussians','ngaus',... - {'1','2','3','4','5','6','7','8','Nonparametric'},... - { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ,Inf}); -ngaus.val = {2}; -ngaus.help = {[... -'The number of Gaussians used to represent the intensity distribution '... -'for each tissue class can be greater than one. '... -'In other words, a tissue probability map may be shared by several clusters. '... -'The assumption of a single Gaussian distribution for each class does not '... -'hold for a number of reasons. '... -'In particular, a voxel may not be purely of one tissue type, and instead '... -'contain signal from a number of different tissues (partial volume effects). '... -'Some partial volume voxels could fall at the interface between different '... -'classes, or they may fall in the middle of structures such as the thalamus, '... -'which may be considered as being either grey or white matter. '... -'Various other image segmentation approaches use additional clusters to '... -'model such partial volume effects. '... -'These generally assume that a pure tissue class has a Gaussian intensity '... -'distribution, whereas intensity distributions for partial volume voxels '... -'are broader, falling between the intensities of the pure classes. '... -'Unlike these partial volume segmentation approaches, the model adopted '... -'here simply assumes that the intensity distribution of each class may '... -'not be Gaussian, and assigns belonging probabilities according to these '... -'non-Gaussian distributions. '... -'Typical numbers of Gaussians could be two for grey matter, two for white '... -'matter, two for CSF, three for bone, four for other soft tissues and ',... -'two for air (background).'],[... -'Note that if any of the Num. Gaussians is set to non-parametric, '... -'then a non-parametric approach will be used to model the tissue intensities. '... -'This may work for some images (eg CT), but not others - '... -'and it has not been optimised for multi-channel data. Note that it is likely to ',... -'be especially problematic for images with poorly behaved intensity histograms ',... -'due to aliasing effects that arise from having discrete values on the images.']}; - -%------------------------------------------------------------------------ -% SOME OPTIONS ARE UNUSED -native = mnu('Native Tissue','native',{... - 'None',... - 'Native Space',... - 'DARTEL Imported',... - 'Native + DARTEL Imported'},... - {[0 0],[1 0],[0 1],[1 1]}); -native.val = {[1 0]}; - -%native = mnu('Native Tissue','native',{... -% 'None',... -% 'Native Space'},... -% {[0 0],[1 0]}); -%native.val = {[1 0]}; - -native.help = {[... -'The native space option allows you to produce a tissue class image (c*) that ',... -'is in alignment with the original/* (see Figure \ref{seg1})*/. ',... -'It can also be used for "importing" into a form that can be used with DARTEL (rc*)']}; - -%------------------------------------------------------------------------ - -warped = mnu('Warped Tissue','warped',{... - 'None',... - 'Modulated',... - 'Unmodulated',... - 'Modulated + Unmodulated'},... - {[0 0],[0 1],[1 0],[1 1]}); -warped.val = {[0 0]}; -warped.help = {[... -'You can produce spatially normalised versions of the tissue class - ',... -'both with (mwc*) and without (wc*) modulation (see below). ',... -'These can be used for voxel-based morphometry. ',... -'All you need to do is smooth them and do the stats.'],... -'',... -[... -'Modulation is to compensate for the effect of spatial normalisation. When warping a series ',... -'of images to match a template, it is inevitable that volumetric differences will be introduced ',... -'into the warped images. For example, if one subject''s temporal lobe has half the volume of that of ',... -'the template, then its volume will be doubled during spatial normalisation. This will also ',... -'result in a doubling of the voxels labelled grey matter. In order to remove this confound, the ',... -'spatially normalised grey matter (or other tissue class) is adjusted by multiplying by its relative ',... -'volume before and after warping. If warping results in a region doubling its volume, then the ',... -'correction will halve the intensity of the tissue label. This whole procedure has the effect of preserving ',... -'the total amount of grey matter signal in the normalised partitions. Actually, in this version of SPM the warped data are not scaled ',... -'by the Jacobian determinants when generating the "modulated" data. Instead, the original voxels are ',... -'projected into their new location in the warped images. This exactly preserves the tissue count, but ',... -'has the effect of introducing aliasing artifacts - especially if the original data are at a lower resolution than ',... -'the warped images. Smoothing should reduce this artifact though.'],... -['Note also that the "unmodulated" data are generated slightly differently in this version of SPM. ',... -'In this version, the projected data are corrected using a kind of smoothing procedure. ',... -'This is not done exactly as it should be done (to save computational time), but it does a reasonable job. ',... -'It also has the effect of extrapolating the warped tissue class images beyond the range of the original ',... -'data. This extrapolation is not perfect, as it is only an estimate, but it may still be a good thing to do.']}; -%------------------------------------------------------------------------ - -tissue = branch('Tissue','tissue',{tpm,ngaus,native,warped}); -tissues = repeat('Tissues','tissues',{tissue}); - -tpm_nam = fullfile(fileparts(which(mfilename)),'TPM.nii'); -ngaus = [2 2 2 3 4 2]; -nval = {[1 0],[1 0],[1 0],[1 0],[1 0],[0 0]}; -for k=1:numel(ngaus), - tissue.val{1}.val{1} = {[tpm_nam ',' num2str(k)]}; - tissue.val{2}.val = {ngaus(k)}; - tissue.val{3}.val = {nval{k}}; - tissues.val{k} = tissue; -end - -%------------------------------------------------------------------------ - -warpreg = entry('Warping Regularisation','reg','e',[1 1]); -warpreg.val = {4}; -warpreg.help = {[... -'The objective function for registering the tissue probability maps to the ',... -'image to process, involves minimising the sum of two terms. ',... -'One term gives a function of how probable the data is given the warping parameters. ',... -'The other is a function of how probable the parameters are, and provides a ',... -'penalty for unlikely deformations. ',... -'Smoother deformations are deemed to be more probable. ',... -'The amount of regularisation determines the tradeoff between the terms. ',... -'Pick a value around one. However, if your normalised images appear ',... -'distorted, then it may be an idea to increase the amount of ',... -'regularisation (by an order of magnitude). ',... -'More regularisation gives smoother deformations, ',... -'where the smoothness measure is determined by the bending energy of the deformations. ']}; -%------------------------------------------------------------------------ - -affreg = mnu('Affine Regularisation','affreg',... - {'No Affine Registration','ICBM space template - European brains',... - 'ICBM space template - East Asian brains', 'Average sized template','No regularisation'},... - {'','mni','eastern','subj','none'}); -affreg.val = {'mni'}; -affreg.help = {[... -'The procedure is a local optimisation, so it needs reasonable initial '... -'starting estimates. Images should be placed in approximate alignment '... -'using the Display function of SPM before beginning. '... -'A Mutual Information affine registration with the tissue '... -'probability maps (D''Agostino et al, 2004) is used to achieve '... -'approximate alignment. '... -'Note that this step does not include any model for intensity non-uniformity. '... -'This means that if the procedure is to be initialised with the affine '... -'registration, then the data should not be too corrupted with this artifact.'... -'If there is a lot of intensity non-uniformity, then manually position your '... -'image in order to achieve closer starting estimates, and turn off the '... -'affine registration.'],... -'',... -[... -'Affine registration into a standard space can be made more robust by ',... -'regularisation (penalising excessive stretching or shrinking). The ',... -'best solutions can be obtained by knowing the approximate amount of ',... -'stretching that is needed (e.g. ICBM templates are slightly bigger ',... -'than typical brains, so greater zooms are likely to be needed). ',... -'For example, if registering to an image in ICBM/MNI space, then choose this ',... -'option. If registering to a template that is close in size, then ',... -'select the appropriate option for this.']}; - -%------------------------------------------------------------------------ - -samp = entry('Sampling distance','samp','e',[1 1]); -samp.val = {3}; -samp.help = {[... -'The approximate distance between sampled points when estimating the ',... -'model parameters. Smaller values use more of the data, but the procedure ',... -'is slower.']}; - -%------------------------------------------------------------------------ - -warps = mnu('Deformation Fields','write',{... - 'None',... - 'Inverse',... - 'Forward',... - 'Inverse + Forward'},... - {[0 0],[1 0],[0 1],[1 1]}); -warps.val = {[0 0]}; -warps.help = {'Deformation fields can be written.'}; - -%------------------------------------------------------------------------ - -bb = entry('Bounding box','bb','e',[2 3]); -bb.val = {ones(2,3)*NaN}; -bb.help = {[... -'The bounding box (in mm) of any spatially normalised volumes to be written ',... -'(relative to the anterior commissure). '... -'Non-finite values will be replaced by the bounding box of the tissue '... -'probability maps used in the segmentation.']}; - -%------------------------------------------------------------------------ - -vox = entry('Voxel size','vox','e',[1 1]); -vox.val = {1.5}; -vox.help = {... -['The (isotropic) voxel sizes of any spatially normalised written images. '... - 'A non-finite value will be replaced by the average voxel size of '... - 'the tissue probability maps used by the segmentation.']}; - -%------------------------------------------------------------------------ -% SOME OPTIONS ARE NOT READY -%warping = branch('Warping','warp',{warpreg,affreg,samp,warps,bb,vox}); -warping = branch('Warping','warp',{warpreg,affreg,samp,warps}); - -%------------------------------------------------------------------------ -% UNUSED -msk = files('Masking image','msk','image',[0 1]); -msk.val = {''}; -msk.help = {[... -'The segmentation can be masked by an image that conforms to ',... -'the same space as the images to be segmented. If an image is selected, then ',... -'it must match the image(s) voxel-for voxel, and have the same ',... -'voxel-to-world mapping. Regions containing a value of zero in this image ',... -'do not contribute when estimating the various parameters. ']}; - -%------------------------------------------------------------------------ - -%------------------------------------------------------------------------ -% UNUSED -cleanup.tag = 'cleanup'; -cleanup.type = 'menu'; -cleanup.name = 'Clean up any partitions'; -cleanup.help = {[... -'This uses a crude routine for extracting the brain from segmented',... -'images. It begins by taking the white matter, and eroding it a',... -'couple of times to get rid of any odd voxels. The algorithm',... -'continues on to do conditional dilations for several iterations,',... -'where the condition is based upon gray or white matter being present.',... -'This identified region is then used to clean up the grey and white',... -'matter partitions, and has a slight influences on the CSF partition.'],'',[... -'If you find pieces of brain being chopped out in your data, then you ',... -'may wish to disable or tone down the cleanup procedure.']}; -cleanup.labels = {'Dont do cleanup','Light Clean','Thorough Clean'}; -cleanup.values = {0 1 2}; -cleanup.val = {0}; - -%------------------------------------------------------------------------ - -job = branch('New Segment','preproc8',{data,tissues,warping}); -job.prog = @execute; -%job.vfiles = @vfiles; -%job.check = @check; -job.help = {[... -'This toolbox is currently only work in progress, and is an extension of the default ',... -'unified segmentation. The algorithm is essentially the same as that described in the ',... -'Unified Segmentation paper, except for (i) a slightly different treatment of the mixing ',... -'proportions, (ii) the use of an improved registration model, ',... -'(iii) the ability to use multi-spectral data, (iv) an extended set of ',... -'tissue probability maps, which allows a different treatment of voxels outside the brain. ',... -'Some of the options in the toolbox do not yet work, and it has not yet been seamlessly integrated ',... -'into the SPM8 software. Also, the extended tissue probability maps need further refinement. ',... -'The current versions were crudely generated (by JA) using data that was kindly provided by ',... -'Cynthia Jongen of the Imaging Sciences Institute at Utrecht, NL.'],... -'',[... -'Segment, bias correct and spatially normalise - all in the same model/* \cite{ashburner05}*/. ',... -'This function can be used for bias correcting, spatially normalising ',... -'or segmenting your data.'],... -'',... -[... -'Many investigators use tools within older versions of SPM for '... -'a technique that has become known as "optimised" voxel-based '... -'morphometry (VBM). '... -'VBM performs region-wise volumetric comparisons among populations of subjects. '... -'It requires the images to be spatially normalised, segmented into '... -'different tissue classes, and smoothed, prior to performing '... -'statistical tests/* \cite{wright_vbm,am_vbmreview,ashburner00b,john_should}*/. The "optimised" pre-processing strategy '... -'involved spatially normalising subjects'' brain images to a '... -'standard space, by matching grey matter in these images, to '... -'a grey matter reference. The historical motivation behind this '... -'approach was to reduce the confounding effects of non-brain (e.g. scalp) '... -'structural variability on the registration. '... -'Tissue classification in older versions of SPM required the images to be registered '... -'with tissue probability maps. After registration, these '... -'maps represented the prior probability of different tissue classes '... -'being found at each location in an image. Bayes rule can '... -'then be used to combine these priors with tissue type probabilities '... -'derived from voxel intensities, to provide the posterior probability.'],... -'',... -[... -'This procedure was inherently circular, because the '... -'registration required an initial tissue classification, and the '... -'tissue classification requires an initial registration. This circularity '... -'is resolved here by combining both components into a single '... -'generative model. This model also includes parameters that account '... -'for image intensity non-uniformity. '... -'Estimating the model parameters (for a maximum a posteriori solution) '... -'involves alternating among classification, bias correction and registration steps. '... -'This approach provides better results than simple serial applications of each component.']}; - -return; -%------------------------------------------------------------------------ - -%------------------------------------------------------------------------ -function execute(job) -spm_preproc_run(job); - -function vf = vfiles(job) -vf = spm_preproc_run(job,'vfiles'); - -function msg = check(job) -msg = spm_preproc_run(job,'check'); - diff --git a/toolbox/Seg/spm_preproc8.m b/toolbox/Seg/spm_preproc8.m index f69b43a..0847901 100644 --- a/toolbox/Seg/spm_preproc8.m +++ b/toolbox/Seg/spm_preproc8.m @@ -72,7 +72,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % John Ashburner -% $Id: spm_preproc8.m 3172 2009-06-02 11:40:42Z john $ +% $Id: spm_preproc8.m 3864 2010-05-05 17:21:20Z john $ Affine = obj.Affine; tpm = obj.tpm; @@ -99,6 +99,12 @@ kron = inline('spm_krutil(a,b)','a','b'); +% Some random numbers are used, so initialise random number generators to +% give the same results each time. These will eventually need changing +% because using character strings to control RAND and RANDN is deprecated. +randn('state',0); +rand('state',0); + % Fudge Factor - to (approximately) account for % non-independence of voxels ff = obj.fudge; @@ -178,7 +184,6 @@ for n=1:N, if spm_type(V(n).dt(1),'intt'), scrand(n) = V(n).pinfo(1); - rand('seed',1); end end cl = cell(length(z0),1); @@ -434,8 +439,8 @@ for n=1:N, x = (1:K)'; for k1=1:Kb, - mom0 = sum(chan(n).hist(:,k1)); - mom1 = sum(chan(n).hist(:,k1).*x); + mom0 = sum(chan(n).hist(:,k1)) + eps; + mom1 = sum(chan(n).hist(:,k1).*x) + eps; chan(n).lam(k1) = sum(chan(n).hist(:,k1).*(x-mom1./mom0).^2+1)/(mom0+1)+1; end end @@ -680,7 +685,6 @@ % Use moments to compute means and variances, and then use these % to initialise the Gaussians - rand('state',0); % give same results each time mg = ones(K,1)/K; mn = ones(N,K); vr = zeros(N,N,K); diff --git a/toolbox/Seg/spm_preproc_run.m b/toolbox/Seg/spm_preproc_run.m index 1fe3d85..9c0af3b 100644 --- a/toolbox/Seg/spm_preproc_run.m +++ b/toolbox/Seg/spm_preproc_run.m @@ -21,7 +21,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % John Ashburner -% $Id: spm_preproc_run.m 3585 2009-11-19 16:24:22Z john $ +% $Id: spm_preproc_run.m 3859 2010-05-04 13:43:41Z john $ if nargin==1, varargout{:} = run_job(job); @@ -130,7 +130,7 @@ for k=1:K, SS(:,:,:,k) = SS(:,:,:,k) + spm_bsplinc(tpm.V(k),[0 0 0 0 0 0])*alpha + eps; end -save SS.mat SS + %save SS.mat SS s = sum(SS,4); for k=1:K, tmp = SS(:,:,:,k)./s; diff --git a/toolbox/Seg/spm_smohist.m b/toolbox/Seg/spm_smohist.m index 22619d2..ca31948 100644 --- a/toolbox/Seg/spm_smohist.m +++ b/toolbox/Seg/spm_smohist.m @@ -17,7 +17,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % John Ashburner -% $Id: spm_smohist.m 2231 2008-09-29 15:01:05Z guillaume $ +% $Id: spm_smohist.m 3864 2010-05-05 17:21:20Z john $ sig0 = zeros(size(t0)); n = size(t0,1); @@ -25,7 +25,7 @@ lam = zeros(size(t0,2),1); x = (1:n)'; for k=1:size(t0,2), - t = t0(:,k); + t = t0(:,k)+eps; mu = sum(t.*x)./sum(t); vr = sum(t.*(x-mu).^2)/sum(t); lam(k) = vr; @@ -44,7 +44,7 @@ constr = log(realmax)-1; for k=1:size(t0,2), - t = t0(:,k) + 2*sum(t0(:,k))/realmax; + t = t0(:,k) + 2*sum(t0(:,k))/realmax + eps; G = G0*lam(k); am = alph(:,k); sig = exp(am); diff --git a/toolbox/Seg/tbx_cfg_preproc8.m b/toolbox/Seg/tbx_cfg_preproc8.m index 79eec13..401fde7 100644 --- a/toolbox/Seg/tbx_cfg_preproc8.m +++ b/toolbox/Seg/tbx_cfg_preproc8.m @@ -1,7 +1,13 @@ function preproc8 = tbx_cfg_preproc8 % MATLABBATCH Configuration file for toolbox 'Segment' +%_______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% John Ashburner +% $Id: tbx_cfg_preproc8.m 3910 2010-06-01 14:58:20Z guillaume $ + +if ~isdeployed, addpath(fullfile(spm('Dir'),'toolbox','Seg')); end -addpath(fileparts(which(mfilename))); % --------------------------------------------------------------------- % vols Volumes % --------------------------------------------------------------------- @@ -52,7 +58,6 @@ biasfwhm.tag = 'biasfwhm'; biasfwhm.name = 'Bias FWHM'; biasfwhm.help = {'FWHM of Gaussian smoothness of bias. If your intensity non-uniformity is very smooth, then choose a large FWHM. This will prevent the algorithm from trying to model out intensity variation due to different tissue types. The model for intensity non-uniformity is one of i.i.d. Gaussian noise that has been smoothed by some amount, before taking the exponential. Note also that smoother bias fields need fewer parameters to describe them. This means that the algorithm is faster for smoother intensity non-uniformities.'}; -%% biasfwhm.labels = { '30mm cutoff' '40mm cutoff' @@ -69,8 +74,6 @@ '150mm cutoff' 'No correction' }'; -%% -%% biasfwhm.values = { 30 40 @@ -88,7 +91,6 @@ Inf }'; biasfwhm.val = {60}; -%% % --------------------------------------------------------------------- % write Save Bias Corrected % --------------------------------------------------------------------- @@ -153,7 +155,6 @@ 'The number of Gaussians used to represent the intensity distribution for each tissue class can be greater than one. In other words, a tissue probability map may be shared by several clusters. The assumption of a single Gaussian distribution for each class does not hold for a number of reasons. In particular, a voxel may not be purely of one tissue type, and instead contain signal from a number of different tissues (partial volume effects). Some partial volume voxels could fall at the interface between different classes, or they may fall in the middle of structures such as the thalamus, which may be considered as being either grey or white matter. Various other image segmentation approaches use additional clusters to model such partial volume effects. These generally assume that a pure tissue class has a Gaussian intensity distribution, whereas intensity distributions for partial volume voxels are broader, falling between the intensities of the pure classes. Unlike these partial volume segmentation approaches, the model adopted here simply assumes that the intensity distribution of each class may not be Gaussian, and assigns belonging probabilities according to these non-Gaussian distributions. Typical numbers of Gaussians could be two for grey matter, two for white matter, two for CSF, three for bone, four for other soft tissues and two for air (background).' 'Note that if any of the Num. Gaussians is set to non-parametric, then a non-parametric approach will be used to model the tissue intensities. This may work for some images (eg CT), but not others - and it has not been optimised for multi-channel data. Note that it is likely to be especially problematic for images with poorly behaved intensity histograms due to aliasing effects that arise from having discrete values on the images.' }'; -%% ngaus.labels = { '1' '2' @@ -165,8 +166,6 @@ '8' 'Nonparametric' }'; -%% -%% ngaus.values = { 1 2 @@ -179,7 +178,6 @@ Inf }'; ngaus.val = {Inf}; -%% % --------------------------------------------------------------------- % native Native Tissue % --------------------------------------------------------------------- @@ -343,12 +341,18 @@ 'This function segments, bias corrects and spatially normalises - all in the same model/* \cite{ashburner05}*/. Many investigators use tools within older versions of SPM for a technique that has become known as "optimised" voxel-based morphometry (VBM). VBM performs region-wise volumetric comparisons among populations of subjects. It requires the images to be spatially normalised, segmented into different tissue classes, and smoothed, prior to performing statistical tests/* \cite{wright_vbm,am_vbmreview,ashburner00b,john_should}*/. The "optimised" pre-processing strategy involved spatially normalising subjects'' brain images to a standard space, by matching grey matter in these images, to a grey matter reference. The historical motivation behind this approach was to reduce the confounding effects of non-brain (e.g. scalp) structural variability on the registration. Tissue classification in older versions of SPM required the images to be registered with tissue probability maps. After registration, these maps represented the prior probability of different tissue classes being found at each location in an image. Bayes rule can then be used to combine these priors with tissue type probabilities derived from voxel intensities, to provide the posterior probability.' '' 'This procedure was inherently circular, because the registration required an initial tissue classification, and the tissue classification requires an initial registration. This circularity is resolved here by combining both components into a single generative model. This model also includes parameters that account for image intensity non-uniformity. Estimating the model parameters (for a maximum a posteriori solution) involves alternating among classification, bias correction and registration steps. This approach provides better results than simple serial applications of each component.' + '' + 'Note that on a 32 bit computer, the most memory that SPM or any other program can use at any time is 4Gbytes (or sometimes only 2Gbytes). This is because the largest number that can be represented with 32 bits is 4,294,967,295, which limits how much memory may be addressed by any one process. Out of memory errors may occasionally be experienced when trying to work with large images. 64-bit computers can usually handle such cases.' }'; -preproc8.prog = @spm_preproc_run; +preproc8.prog = @spm_local_preproc_run; preproc8.vout = @vout; -%------------------------------------------------------------------------ +%---------------------------------------------------------------------- + +%====================================================================== +function varargout = spm_local_preproc_run(job) +varargout{:} = spm_preproc_run(job); -%------------------------------------------------------------------------ +%====================================================================== function dep = vout(job) % This depends on job contents, which may not be present when virtual % outputs are calculated. diff --git a/toolbox/dcm_meeg/spm_L_priors.m b/toolbox/dcm_meeg/spm_L_priors.m index 819995a..b00f1f3 100644 --- a/toolbox/dcm_meeg/spm_L_priors.m +++ b/toolbox/dcm_meeg/spm_L_priors.m @@ -10,7 +10,7 @@ % dipfit.Lpos - x,y,z source positions (mm) (ECD) % dipfit.Nm - number of modes (IMG) % dipfit.Ns - number of sources -% dipfit.Nc - number of channels +% dipfit.Nc - number of channels % % pE - prior expectation % pC - prior covariance @@ -29,10 +29,10 @@ % neuronal dynamics. NeuroImage 20: 1743-1755 %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging - + % Karl Friston -% $Id: spm_L_priors.m 3517 2009-10-29 15:11:56Z guillaume $ - +% $Id: spm_L_priors.m 3738 2010-02-25 13:19:07Z vladimir $ + % defaults %-------------------------------------------------------------------------- try, model = dipfit.model; catch, model = 'LFP'; end @@ -40,7 +40,7 @@ try, location = dipfit.location; catch, location = 0; end try, symmetry = dipfit.symmetry; catch, symmetry = 0; end try, pC; catch, pC = []; end - + % number of sources %-------------------------------------------------------------------------- @@ -55,22 +55,22 @@ % location priors (4 mm) %-------------------------------------------------------------------------- if location, V = 2^2; else, V = 0; end - + % parameters for electromagnetic forward model %========================================================================== switch type - + case{'ECD'} % mean and variance %------------------------------------------------------------------ pE.Lpos = dipfit.Lpos; Lpos = V*eye(3*n); % positions pE.L = sparse(3,n); L = eye(3*n); % orientations - + case{'IMG'} %------------------------------------------------------------------ m = dipfit.Nm; % number of modes pE.Lpos = sparse(3,0); Lpos = eye(0,0); % positions pE.L = sparse(m,n); L = eye(m*n); % modes - + case{'LFP'} %------------------------------------------------------------------ pE.Lpos = sparse(3,0); Lpos = eye(0,0); % positions @@ -78,23 +78,23 @@ otherwise warndlg('Unknown spatial model') - + end - + % contributing states (encoded in J) %========================================================================== switch model - + case{'ERP','SEP'} %------------------------------------------------------------------ pE.J = sparse(1,[1 7 9],[0.2 0.2 0.6],1,9); % 9 states J = diag(pE.J/64); - + case{'LFP'} %------------------------------------------------------------------ pE.J = sparse(1,[1 7 9],[0.2 0.2 0.6],1,13); % 13 states - J = diag(pE.J/64); - + J = diag(pE.J/64); + case{'NMM'} %------------------------------------------------------------------ pE.J = sparse(1,[1,2,3],[0.1 0.1 1],1,9); % 9 states @@ -112,34 +112,45 @@ otherwise warndlg('Unknown neural model') - + end - + % Distance between homolgous sources (16mm) %-------------------------------------------------------------------------- -if symmetry, V = 16; else, V = 0; end +if symmetry, V = 16; else V = 0; end % symmetry constraints (based on Euclidean distance from mirror image) %========================================================================== switch type - + case{'ECD'} - - % correlation - %------------------------------------------------------------------ - Mpos = [-pE.Lpos(1,:); pE.Lpos(2,:); pE.Lpos(3,:)]; - for i = 1:n - for j = 1:n - D(i,j) = sqrt(sum(pE.Lpos(:,i) - Mpos(:,j)).^2); + if symmetry + + % correlation + %------------------------------------------------------------------ + Mpos = [-pE.Lpos(1,:); pE.Lpos(2,:); pE.Lpos(3,:)]; + D = Inf*ones(n); + for i = 1:n + for j = 1:n + if sign(pE.Lpos(1,i)) == sign(Mpos(1, j)) + D(i,j) = sqrt(sum(pE.Lpos(:,i) - Mpos(:,j)).^2); + end + end end + D = (D + D')/2; + DD = zeros(n); + for i = 1:n + [M, I] = min(D(i, :)); + if M2 + set(handles.Spatial, 'Value', 2); + end set(handles.Spatial, 'String',{'ECD','LFP'}); set(handles.Wavelet, 'Enable','on','String','Wavelet transform'); set(handles.Imaging, 'Enable','off' ) @@ -1250,7 +1251,9 @@ function BMS_Callback(hObject, eventdata, handles) set(handles.text20, 'String', 'sub-trials'); set(handles.model, 'Enable','off'); - set(handles.Spatial, 'Value', 1); + if get(handles.Spatial, 'Value')>2 + set(handles.Spatial, 'Value', 2); + end set(handles.Spatial, 'String',{'ECD','LFP'}); set(handles.Wavelet, 'Enable','on','String','Hilbert transform'); set(handles.Imaging, 'Enable','off' ) diff --git a/toolbox/dcm_meeg/spm_dcm_erp_dipfit.m b/toolbox/dcm_meeg/spm_dcm_erp_dipfit.m index b002671..0e70b14 100644 --- a/toolbox/dcm_meeg/spm_dcm_erp_dipfit.m +++ b/toolbox/dcm_meeg/spm_dcm_erp_dipfit.m @@ -35,7 +35,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_dcm_erp_dipfit.m 3653 2009-12-23 20:06:48Z karl $ +% $Id: spm_dcm_erp_dipfit.m 3833 2010-04-22 14:49:48Z vladimir $ % Get data filename and good channels %-------------------------------------------------------------------------- @@ -133,10 +133,10 @@ %-------------------------------------------------------------------------- if save_vol_sens if ischar(DCM.M.dipfit.vol) - DCM.M.dipfit.vol = fileio_read_vol(DCM.M.dipfit.vol); + DCM.M.dipfit.vol = ft_read_vol(DCM.M.dipfit.vol); end - [DCM.M.dipfit.vol, DCM.M.dipfit.sens] = forwinv_prepare_vol_sens(DCM.M.dipfit.vol, ... + [DCM.M.dipfit.vol, DCM.M.dipfit.sens] = ft_prepare_vol_sens(DCM.M.dipfit.vol, ... DCM.M.dipfit.datareg.sensors, 'channel', D.chanlabels(DCM.xY.Ic)); end diff --git a/toolbox/dcm_meeg/spm_dcm_ind_data.m b/toolbox/dcm_meeg/spm_dcm_ind_data.m index 71bc8ee..70e1e31 100644 --- a/toolbox/dcm_meeg/spm_dcm_ind_data.m +++ b/toolbox/dcm_meeg/spm_dcm_ind_data.m @@ -41,7 +41,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_dcm_ind_data.m 2720 2009-02-09 19:50:46Z vladimir $ +% $Id: spm_dcm_ind_data.m 3954 2010-06-29 15:50:23Z vladimir $ % Set defaults and Get D filename %------------------------------------------------------------------------- @@ -64,7 +64,7 @@ %-------------------------------------------------------------------------- if ~isfield(DCM.xY, 'modality') [mod, list] = modality(D, 0, 1); - + if isequal(mod, 'Multimodal') qstr = 'Only one modality can be modelled at a time. Please select.'; if numel(list) < 4 @@ -85,23 +85,21 @@ if ~isfield(DCM.xY, 'Ic') Ic = setdiff(D.meegchannels(DCM.xY.modality), D.badchannels); - DCM.xY.Ic = Ic; + DCM.xY.Ic = Ic; end - -Ic = DCM.xY.Ic; - -Nc = length(DCM.xY.Ic); +Ic = DCM.xY.Ic; +Nc = length(DCM.xY.Ic); % options %-------------------------------------------------------------------------- try - Nm = DCM.options.Nmodes; + Nm = DCM.options.Nmodes; catch errordlg('Please specify number of frequency modes'); error('') end try - h = DCM.options.h; + h = DCM.options.h; catch errordlg('Please number of DCT components'); error('') @@ -137,7 +135,7 @@ % get peristimulus times %-------------------------------------------------------------------------- try - + % time window and bins for modelling %---------------------------------------------------------------------- DCM.xY.Time = 1000*D.time; % ms @@ -145,7 +143,7 @@ T2 = DCM.options.Tdcm(2); [i, T1] = min(abs(DCM.xY.Time - T1)); [i, T2] = min(abs(DCM.xY.Time - T2)); - + % Time [ms] of downsampled data %---------------------------------------------------------------------- Ns = length(DCM.xY.Time); % number of bins @@ -153,9 +151,9 @@ Is = [1:Ns]'; % indices - samples DCM.xY.pst = DCM.xY.Time(It); % PST DCM.xY.It = It; % Indices of time bins - DCM.xY.dt = DT/D.fsample; % sampling in seconds + DCM.xY.dt = DT/D.fsample; % sampling in seconds Nb = length(It); % number of bins - + catch errordlg('Please specify time window'); error('') @@ -182,7 +180,7 @@ %-------------------------------------------------------------------------- DCM.xY.Hz = Hz1:HzD:Hz2; % Frequencies DCM.xY.Nm = Nm; % number of frequency modes -dt = 1000/D.fsample; % sampling interval (ms) +dt = 1000/D.fsample; % sampling interval (ms) Nf = length(DCM.xY.Hz); % number of frequencies Nr = size(DCM.C,1); % number of sources Ne = length(trial); % number of ERPs @@ -218,14 +216,14 @@ %-------------------------------------------------------------------------- for i = 1:Nf fprintf('\nCreating wavelet projector (%i Hz),',DCM.xY.Hz(i)) - + W = spm_eeg_morlet(DCM.xY.Rft, dt, DCM.xY.Hz(i)); N = fix(length(W{1})/2); W = W{1}.*(abs(W{1}) > exp(-8)); W = spm_convmtx(W',Ns); W = W(It + N,:); M{i} = W*T; - + end % get MAP projector matrix for source components @@ -234,16 +232,14 @@ % parameterised lead field ECD given positions (or LFP data) %-------------------------------------------------------------------------- clear spm_erp_L -switch DCM.xY.modality - - case{'EEG', 'MEG'} - +if strcmp(DCM.options.spatial, 'ECD') + if ismember(DCM.xY.modality, {'EEG', 'MEG', 'MEGPLANAR'}) try pos = DCM.Lpos; catch pos = DCM.M.dipfit.Lpos; end - + % number of moments per source %------------------------------------------------------------------ Ng = 3; @@ -251,20 +247,27 @@ G.Lpos = kron(pos,ones(1,Ng)); L = spm_erp_L(G,DCM.M); MAP = pinv(L); - - + + % add (spatial filtering) re-referencing to MAP projector %-------------------------------------------------------------------------- R = speye(Nc,Nc) - ones(Nc,1)*pinv(ones(Nc,1)); MAP = MAP*R; - - case{'LFP'} + else + warndlg('ECD option can only be used with EEG/MEG/MEGPLANAR channels'); + return; + end +elseif strcmp(DCM.options.spatial, 'LFP') + if strcmp(DCM.xY.modality, 'LFP') Ng = 1; MAP = speye(Nr,Nr); - - otherwise - warndlg('DCM for induced responses requires an ECD model') - return + else + warndlg('LFP option can only be used with datasets of LFP modality'); + return; + end +else + warndlg('Invalid spatial model specification.') + return; end @@ -272,20 +275,20 @@ %========================================================================== condlabels = D.condlist; for i = 1:Ne; - + % trial indices %---------------------------------------------------------------------- c = D.pickconditions(condlabels{trial(i)}); - + % use only the first 512 trials %---------------------------------------------------------------------- try c = c(1:512); end Nt = length(c); - - + + % Get data: log(spectral magnitude) %---------------------------------------------------------------------- - Ny = Nb*Nr*Ng; + Ny = Nb*Ng*Nr; Y = zeros(Ny*Nf,Nt); for j = 1:Nf f = [1:Ny] + (j - 1)*Ny; @@ -295,20 +298,17 @@ end fprintf('\nevaluating %i Hz, condition %i (%i trials)',DCM.xY.Hz(j),i,Nt) end - + % weight with principal eigenvariate over trials (c.f., averaging) %---------------------------------------------------------------------- u = spm_svd(Y'*Y); u = full(u(:,1)*sign(max(u(:,1)))); - Y = reshape(Y*u,Nb,Nr*Ng,Nf); - + Y = reshape(Y*u,Nb,Ng,Nr,Nf); + % sum time-frequency response over moments and remove baseline %---------------------------------------------------------------------- for j = 1:Nr - Yk = zeros(Nb,Nf); - for k = 1:Ng - Yk = Yk + squeeze(Y(:,j + k - 1,:))/Nt; - end + Yk = squeeze(sum(Y(:,:,j,:),2))/Nt; Yz{i,j} = Yk - ones(Nb,1)*Yk(1,:); end end diff --git a/toolbox/dcm_meeg/spm_dcm_phase_data.m b/toolbox/dcm_meeg/spm_dcm_phase_data.m index 1afa2aa..a92e93c 100644 --- a/toolbox/dcm_meeg/spm_dcm_phase_data.m +++ b/toolbox/dcm_meeg/spm_dcm_phase_data.m @@ -26,7 +26,7 @@ % Copyright (C) 2009 Wellcome Trust Centre for Neuroimaging % Will Penny -% $Id: spm_dcm_phase_data.m 3541 2009-11-06 17:34:40Z guillaume $ +% $Id: spm_dcm_phase_data.m 3847 2010-04-28 11:27:20Z vladimir $ % Get data filename %------------------------------------------------------------------------- @@ -149,8 +149,7 @@ xr=region{n}(:,c); % Filtering - [B, A] = butter(5, 2*DCM.options.Fdcm/fsample(D)); - xr = spm_filtfilt(B, A, xr); + xr = ft_preproc_bandpassfilter(xr, fsample(D), DCM.options.Fdcm, 5); hx=spm_hilbert(xr); DCM.xY.y{n}(:,c)=double(angle(hx)); diff --git a/toolbox/dcm_meeg/spm_eeg_inv_ecd_DrawDip.m b/toolbox/dcm_meeg/spm_eeg_inv_ecd_DrawDip.m index 653bb7d..ab3eea4 100644 --- a/toolbox/dcm_meeg/spm_eeg_inv_ecd_DrawDip.m +++ b/toolbox/dcm_meeg/spm_eeg_inv_ecd_DrawDip.m @@ -40,10 +40,9 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Christophe Phillips, -% $Id: spm_eeg_inv_ecd_DrawDip.m 3182 2009-06-04 09:08:10Z vladimir $ +% $Id: spm_eeg_inv_ecd_DrawDip.m 3692 2010-01-21 21:43:31Z guillaume $ global st -global defaults Fig = spm_figure('FindWin'); colors = strvcat('y','b','g','r','c','m'); % 6 possible colors diff --git a/toolbox/dcm_meeg/spm_erp_L.m b/toolbox/dcm_meeg/spm_erp_L.m index ca538cc..106a7f0 100644 --- a/toolbox/dcm_meeg/spm_erp_L.m +++ b/toolbox/dcm_meeg/spm_erp_L.m @@ -25,7 +25,7 @@ % Copyright (C) 2005 Wellcome Trust Centre for Neuroimaging % Karl Friston -% $Id: spm_erp_L.m 2330 2008-10-10 18:23:42Z karl $ +% $Id: spm_erp_L.m 3833 2010-04-22 14:49:48Z vladimir $ % Create a persient variable that rembers the last locations %-------------------------------------------------------------------------- @@ -58,7 +58,7 @@ %---------------------------------------------------------- LastLpos = P.Lpos; for i = Id - Lf = forwinv_compute_leadfield(transform_points(M.dipfit.datareg.fromMNI, P.Lpos(:,i)'), M.dipfit.sens, M.dipfit.vol); + Lf = ft_compute_leadfield(transform_points(M.dipfit.datareg.fromMNI, P.Lpos(:,i)'), M.dipfit.sens, M.dipfit.vol); LastL(:,:,i) = Lf; end G = spm_cond_units(LastL); diff --git a/toolbox/mixture/spm_MNpdf.m b/toolbox/mixture/spm_MNpdf.m index 3fe758c..4fd7a36 100644 --- a/toolbox/mixture/spm_MNpdf.m +++ b/toolbox/mixture/spm_MNpdf.m @@ -11,14 +11,13 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Will Penny -% $Id: spm_MNpdf.m 1143 2008-02-07 19:33:33Z spm $ +% $Id: spm_MNpdf.m 3995 2010-07-13 17:19:49Z karl $ -ic = inv(C); +ic = inv(C); [n, d] = size(x); -m = reshape(m, 1, d); % Ensure that mu is a row vector -x = x - ones(n, 1)*m; +x = x - ones(n, 1)*m(:)'; fact = sum(((x*ic).*x), 2); -y = exp(-0.5*fact); -y = y./sqrt((2*pi)^d*det(C)); +y = exp(-0.5*fact); +y = y./sqrt((2*pi)^d*det(C)); diff --git a/toolbox/mixture/spm_mix.m b/toolbox/mixture/spm_mix.m index d69b94f..eee2a25 100644 --- a/toolbox/mixture/spm_mix.m +++ b/toolbox/mixture/spm_mix.m @@ -36,7 +36,7 @@ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Will Penny -% $Id: spm_mix.m 3072 2009-04-21 15:17:09Z will $ +% $Id: spm_mix.m 3857 2010-04-30 13:11:03Z will $ % This code implements the algorithm in: % @@ -156,9 +156,10 @@ for n=1:N, gamma(s,n)=tilde_pi(s)*tilde_gamma(s)^0.5; dy=(y(n,:)-state(s).m); - gamma(s,n)=gamma(s,n)*exp(-0.5*dy*state(s).bar_gamma*dy')*exp(-d/(2*state(s).beta)); + gamma(s,n)=gamma(s,n)*(exp(-0.5*dy*state(s).bar_gamma*dy')+eps)*exp(-d/(2*state(s).beta)); end end + gamma_n=sum(gamma); for s=1:m, if mean(gamma_n) > eps @@ -174,6 +175,7 @@ pi_bar(s)=mean(gamma(s,:))+eps; N_bar(s)=N*pi_bar(s)+eps; bar_mu(s,:)=(1/N_bar(s))*sum(gamma(s,:)'*ones(1,d).*y); + end % get weighted means and covariances @@ -184,6 +186,10 @@ state(s).bar_sigma=state(s).bar_sigma+gamma(s,n).*(dy'*dy); end state(s).bar_sigma=(state(s).bar_sigma)/N_bar(s); + + if isnan(state(s).bar_sigma) + state(s).bar_sigma + end end % Now compute the free energy @@ -222,13 +228,7 @@ oldlik=lik; lik=fm; if (loops>1) - if (oldlik-lik)/abs(lik) > tol - disp('Evidence Violation'); - disp('This is a numerical problem sometimes encountered'); - disp('for high-dimensional data'); - disp('Try changing the prior B_0 to a more suitable value.'); - break; - elseif abs((lik-oldlik)/lik) < tol + if abs((lik-oldlik)/lik) < tol break; end end; diff --git a/toolbox/mixture/spm_mix_demo.m b/toolbox/mixture/spm_mix_demo.m index de7eb20..9cb54b3 100644 --- a/toolbox/mixture/spm_mix_demo.m +++ b/toolbox/mixture/spm_mix_demo.m @@ -1,26 +1,10 @@ +%% Demonstrate use of spm_mix +% Best viewed with MATLAB's "publish" functionality. -% Demonstrate use of spm_mix -m_true=3; -m_model=5; -d=2; -N=200; - -disp('2-dimensional data;'); -disp(sprintf('%d-cluster data and %d-cluster model',m_true,m_model)); - -% Use data from file -load yrep -figure -plot(y(:,1),y(:,2),'x'); -hold on - -vbmix=spm_mix(y,m_model); - -for i=1:m_model, - plot(vbmix.state(i).m(1),vbmix.state(i).m(2),'rx'); -end -hold on -spm_mix_plot(vbmix,[-2 12 -2 12],1,'r',0.4,0.5); -set(gca,'FontSize',18); - +%% One-dimensional data, simulated from a three-component mixture +% Fitted with mixtures containing from 1 to 5 components +spm_mix_demo1d(3, 5); +%% Two-dimensional data, simulated from a three-component mixture +% Fitted with a mixture containing 5 components +spm_mix_demo2d diff --git a/toolbox/mixture/spm_mix_demo1d.m b/toolbox/mixture/spm_mix_demo1d.m index 4b9bc54..f98be82 100644 --- a/toolbox/mixture/spm_mix_demo1d.m +++ b/toolbox/mixture/spm_mix_demo1d.m @@ -1,63 +1,76 @@ - +function [vbmix logev mix] = spm_mix_demo1d (data, maxcomps, verbosity) % Demonstrate use of spm_mix on 1D data +% FORMAT [vbmix logev mixdata] = spm_mix_demo1d (data, maxcomps, plotfits) +% +% data - either scalar number of clusters to simulate or your own data +% maxcomps - maximum number of components in mixture model to consider +% verbosity - 0 = silent, 1 = basic output (with figures), 2 = full output +% +% vbmix - cell array of fitted mixtures for all numbers of components +% logev - log evidence for each number of components +% mix - mix structure for simulated mixtures if scalar data given +%_______________________________________________________________________ +% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging -% Number of data points -N=100; - -% Single cluster data -disp('Data set 1: single cluster data'); -y=randn(N,1); +% Will Penny & Ged Ridgway +% $Id: spm_mix_demo1d.m 3997 2010-07-15 12:38:24Z ged $ -logev=[]; -for m=1:5, - disp(sprintf('Fitting mixture model with %d components',m)); - vbmix=spm_mix(y,m,0); - logev=[logev; vbmix.fm]; +if nargin < 3 + verbosity = 1; end -logev=logev-min(logev); - -figure -subplot(2,1,1); -hist(y); -title('Data set 1: Data histogram'); -subplot(2,1,2); -bar(logev); -xlabel('Number of mixture components'); -ylabel('Log Evidence'); -drawnow; - -% Three cluster data -disp('Data set 2: three cluster data'); -mix.m=3; -mix.state(1).prior=0.3; -mix.state(1).m=-5; -mix.state(1).C=1; - -mix.state(2).prior=0.3; -mix.state(2).m=0; -mix.state(2).C=1; - -mix.state(3).prior=0.4; -mix.state(3).m=5; -mix.state(3).C=1; - -y=spm_samp_mix(mix,N); -logev=[]; -for m=1:5, - disp(sprintf('Fitting mixture model with %d components',m)); - vbmix=spm_mix(y,m,0); - logev=[logev; vbmix.fm]; +if nargin < 2 + maxcomps = 5; +end +if nargin < 1 + data = 3; end -logev=logev-min(logev); -figure -subplot(2,1,1); -hist(y); -title('Data set 2: Data histogram'); -subplot(2,1,2); -bar(logev); -xlabel('Number of mixture components'); -ylabel('Log Evidence'); +if isscalar(data) + mix.m = data; + if verbosity > 0 + fprintf('Simulating data with %d clusters\n', mix.m) + end + means = 0:5:5*(mix.m - 1); + for m = 1:mix.m + mix.state(m).prior = 1 / mix.m; + mix.state(m).m = means(m); + mix.state(m).C = 1; + end + N = 50 * mix.m; % Number of data points + data = spm_samp_mix(mix, N); +else + data = data(isfinite(data)); + mix = 'Own data given'; +end +logev = nan(maxcomps, 1); +vbmix = cell(maxcomps, 1); +for m = 1:maxcomps + if verbosity > 0 + fprintf('Fitting mixture model with %d components\n', m); + end + vbmix{m} = spm_mix(data, m, verbosity > 1); + if verbosity > 0 + figure + spm_mix_plot1d (data, vbmix{m}) + title('Fitted model') + end + logev(m) = vbmix{m}.fm; +end +logev = logev-min(logev); +if verbosity > 0 + if isstruct(mix) + figure; + spm_mix_plot1d (data, mix); + title('True generative model') + end + figure + bar(logev); + xlabel('Number of mixture components'); + ylabel('Log Evidence'); +end +if nargout == 0 && verbosity > 0 % assume wanted plots without other output + clear vbmix +end diff --git a/toolbox/mixture/spm_mix_demo2d.m b/toolbox/mixture/spm_mix_demo2d.m index de7eb20..f00a2d1 100644 --- a/toolbox/mixture/spm_mix_demo2d.m +++ b/toolbox/mixture/spm_mix_demo2d.m @@ -20,7 +20,7 @@ plot(vbmix.state(i).m(1),vbmix.state(i).m(2),'rx'); end hold on -spm_mix_plot(vbmix,[-2 12 -2 12],1,'r',0.4,0.5); +spm_mix_plot2d(vbmix,[-2 12 -2 12],1,'r',0.4,0.5); set(gca,'FontSize',18); diff --git a/toolbox/mixture/spm_mix_plot.m b/toolbox/mixture/spm_mix_plot.m deleted file mode 100644 index 28118c8..0000000 --- a/toolbox/mixture/spm_mix_plot.m +++ /dev/null @@ -1,55 +0,0 @@ -function [] = spm_mix_plot (mix,area,nContLines,LineType,min_p,max_p) -% Plot component density contours for 2D mixture model -% FORMAT [] = spm_mix_plot (mix,area,nContLines,LineType,min_p,max_p) -% -% mix Mixture model data structure -% area [xmin,xmax,ymin,ymax] -% nContLines Number of contour lines; default=10 -% LineType Plot line type; default='-' -% min_p/max_p Values of min and max probability contours -%_______________________________________________________________________ -% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging - -% Will Penny -% $Id: spm_mix_plot.m 1143 2008-02-07 19:33:33Z spm $ - -if nargin < 2 | isempty(area), area=[0 10 0 10]; end -if nargin < 3 | isempty(nContLines), nContLines=10; end -if nargin < 4 | isempty(LineType), LineType='-'; end -if nargin < 5 | isempty(min_p), min_p=0.005; end -if nargin < 6 | isempty(max_p), max_p=0.1; end - -xmin=area(1); -xmax=area(2); -ymin=area(3); -ymax=area(4); - -% Number of data points per dimension -d=100; - -% Generate X -dx1=(xmax-xmin)/d; -dx2=(ymax-ymin)/d; - -x1=[xmin:dx1:xmax]; -y1=[ymin:dx2:ymax]; -[g1,g2]=meshgrid(x1,y1); - -xplot = [reshape(g1,(d+1)^2,1), reshape(g2,(d+1)^2,1)]; - -% Get proby density of points -for j=1:mix.m, - y = spm_MNpdf(mix.state(j).m, mix.state(j).C, xplot); - - % Plot proby contours - yplot = reshape(y,d+1,d+1); - dp=(max_p-min_p)/nContLines; - clevels=[min_p:dp:max_p]*max(y); - - clevels=clevels(1:nContLines); - if nContLines==1 - contour(g1,g2,yplot,[clevels, clevels],LineType); - else - contour(g1,g2,yplot,clevels,LineType); - end -end diff --git a/toolbox/mixture/spm_mix_plot1d.m b/toolbox/mixture/spm_mix_plot1d.m new file mode 100644 index 0000000..4c7c0a6 --- /dev/null +++ b/toolbox/mixture/spm_mix_plot1d.m @@ -0,0 +1,59 @@ +function [] = spm_mix_plot1d (data, mix, rng, nPoints) +% Plot component densities and mixture density for 1D mixture model +% FORMAT [] = spm_mix_plot1d (data, mix, rng, nPoints) +% +% data - Optional original data, from which histogram is plotted, or [] +% mix - Mixture model data structure from spm_mix +% rng - [xmin xmax], defaulting to [min(data) max(data)] if data given +% nPoints - Number of points covering rng; default=100 +%_______________________________________________________________________ +% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging + +% Will Penny & Ged Ridgway +% $Id: spm_mix_plot1d.m 3997 2010-07-15 12:38:24Z ged $ + +if nargin < 4 || isempty(nPoints), nPoints = 100; end +if nargin < 3 || isempty(rng) + if ~isempty(data) + rng = [min(data) max(data)]; + else + error('Please either specify range or give data to derive it from') + end +end + +x = linspace(min(rng), max(rng), nPoints); +M = mix.m; +pat = sprintf('Comp. %%0%dd', 1+floor(log10(M))); +pdfs = zeros(M + 1, nPoints); +legs = cell(M+1, 1); +if M == 1 + mix.state(1).prior = 1; +end +for m = 1:M + pdfs(m, :) = mix.state(m).prior * ... + spm_Npdf(x, mix.state(m).m, mix.state(m).C); + legs{m} = sprintf(pat, m); +end +pdfs(M+1, :) = sum(pdfs); +legs{M+1} = 'Mixture PDF'; + +if ~isempty(data) + subplot(2,1,1) +end +plh = plot(x, pdfs); +mixcol = get(plh(end), 'Color'); +set(plh(end), 'LineStyle', '--') +legend(legs, 'Location', 'BestOutside'); + +if ~isempty(data) + subplot(2,1,2) + [c b] = hist(data, round(sqrt(numel(data)))); + bar(b, c / sum(c) / mean(diff(b)), 'k'); + if exist('ksdensity', 'file') + hold on; + f = ksdensity(data, x); + plot(x, f, '--', 'Color', mixcol); + legend('Histogram', 'Parzen PDF', 'Location', 'BestOutside'); + end + subplot(2,1,1); % (so any subsequent title command goes over this plot) +end diff --git a/toolbox/mixture/spm_mix_plot2d.m b/toolbox/mixture/spm_mix_plot2d.m new file mode 100644 index 0000000..29f8a27 --- /dev/null +++ b/toolbox/mixture/spm_mix_plot2d.m @@ -0,0 +1,55 @@ +function [] = spm_mix_plot2d (mix,area,nContLines,LineType,min_p,max_p) +% Plot component density contours for 2D mixture model +% FORMAT [] = spm_mix_plot2d (mix,area,nContLines,LineType,min_p,max_p) +% +% mix Mixture model data structure +% area [xmin,xmax,ymin,ymax] +% nContLines Number of contour lines; default=10 +% LineType Plot line type; default='-' +% min_p/max_p Values of min and max probability contours +%_______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Will Penny +% $Id: spm_mix_plot2d.m 3997 2010-07-15 12:38:24Z ged $ + +if nargin < 2 | isempty(area), area=[0 10 0 10]; end +if nargin < 3 | isempty(nContLines), nContLines=10; end +if nargin < 4 | isempty(LineType), LineType='-'; end +if nargin < 5 | isempty(min_p), min_p=0.005; end +if nargin < 6 | isempty(max_p), max_p=0.1; end + +xmin=area(1); +xmax=area(2); +ymin=area(3); +ymax=area(4); + +% Number of data points per dimension +d=100; + +% Generate X +dx1=(xmax-xmin)/d; +dx2=(ymax-ymin)/d; + +x1=[xmin:dx1:xmax]; +y1=[ymin:dx2:ymax]; +[g1,g2]=meshgrid(x1,y1); + +xplot = [reshape(g1,(d+1)^2,1), reshape(g2,(d+1)^2,1)]; + +% Get proby density of points +for j=1:mix.m, + y = spm_MNpdf(mix.state(j).m, mix.state(j).C, xplot); + + % Plot proby contours + yplot = reshape(y,d+1,d+1); + dp=(max_p-min_p)/nContLines; + clevels=[min_p:dp:max_p]*max(y); + + clevels=clevels(1:nContLines); + if nContLines==1 + contour(g1,g2,yplot,[clevels, clevels],LineType); + else + contour(g1,g2,yplot,clevels,LineType); + end +end diff --git a/toolbox/spectral/spm_dpss.m b/toolbox/spectral/spm_dpss.m new file mode 100644 index 0000000..6211c4b --- /dev/null +++ b/toolbox/spectral/spm_dpss.m @@ -0,0 +1,163 @@ +function [E] = spm_dpss (N,NW) +% Compute discrete prolate spheroidal sequences +% FORMAT [E] = spm_dpss (N,NW) +% +% N Length of taper +% NW Product of N and W +% +% E [N x 2NW] matrix containing dpss sequences +% The kth column contains the sequence which +% comprises the length N signal that is kth most +% concentrated in the frequency band |w|<=2*pi*W radians +% +% See Section 8.3 in +% Percival, D.B. and Walden, A.T., "Spectral Analysis For Physical +% Applications", Cambridge University Press, 1993. +%__________________________________________________________________________ +% Copyright (C) 2009 Wellcome Trust Centre for Neuroimaging + +% Eric Breitenberger, 10/3/95 +% Copyright 1988-2004 The MathWorks, Inc. +% $Id: spm_dpss.m 3821 2010-04-15 14:26:34Z will $ + +W=NW/N; + +k = min(round(2*N*W),N); +k = max(k,1); +k = [1 k]; + +% Generate first and second diagonals +d=((N-1-2*(0:N-1)').^2)*.25*cos(2*pi*W); +ee=(1:N-1)'.*(N-1:-1:1)'/2; + +% Get the eigenvalues of B - see page 382 Percival and Walden +v = tridieig(d,[0; ee],N-k(2)+1,N-k(1)+1); +v = v(end:-1:1); +Lv = length(v); + +% Compute the eigenvectors by inverse iteration with +% starting vectors of roughly the right shape. +E = zeros(N,k(2)-k(1)+1); +t = (0:N-1)'/(N-1)*pi; +for j = 1:Lv + e = sin((j+k(1)-1)*t); + + e = tridisolve(ee,d-v(j),ee,e); + e = tridisolve(ee,d-v(j),ee,e/norm(e)); + e = tridisolve(ee,d-v(j),ee,e/norm(e)); + + E(:,j) = e/norm(e); +end + +d=mean(E); +for i=k(1):k(2) + if rem(i,2) % i is odd + % Polarize symmetric dpss + if d(i-k(1)+1)<0, E(:,i-k(1)+1)=-E(:,i-k(1)+1); end + else % i is even + % Polarize anti-symmetric dpss + if E(2,i-k(1)+1)<0, E(:,i-k(1)+1)=-E(:,i-k(1)+1); end + end +end + + +function x = tridieig(c,b,m1,m2,eps1); +%TRIDIEIG Find a few eigenvalues of a tridiagonal matrix. +% LAMBDA = TRIDIEIG(D,E,M1,M2). D and E, two vectors of length N, +% define a symmetric, tridiagonal matrix: +% A = diag(E(2:N),-1) + diag(D,0) + diag(E(2:N),1) +% E(1) is ignored. +% TRIDIEIG(D,E,M1,M2) computes the eigenvalues of A with indices +% M1 <= K <= M2. +% TRIDIEIG(D,E,M1,M2,TOL) uses TOL as a tolerance. +% +% C. Moler +% Copyright 1988-2002 The MathWorks, Inc. + +if nargin < 5, eps1 = 0; end +n = length(c); +b(1) = 0; +beta = b.*b; +xmin = min(c(n) - abs(b(n)),min(c(1:n-1) - abs(b(1:n-1)) - abs(b(2:n)))); +xmax = max(c(n) + abs(b(n)),max(c(1:n-1) + abs(b(1:n-1)) + abs(b(2:n)))); +eps2 = eps*max(xmax,-xmin); +if eps1 <= 0, eps1 = eps2; end +eps2 = 0.5*eps1 + 7*eps2; + +x0 = xmax; +x = zeros(n,1); +wu = zeros(n,1); +x(m1:m2) = xmax(ones(m2-m1+1,1)); +wu(m1:m2) = xmin(ones(m2-m1+1,1)); +z = 0; +for k = m2:-1:m1 + xu = xmin; + for i = k:-1:m1 + if xu < wu(i) + xu = wu(i); + break + end + end + if x0 > x(k), x0 = x(k); end + while 1 + x1 = (xu + x0)/2; + if x0 - xu <= 2*eps*(abs(xu)+abs(x0)) + eps1 + break + end + z = z + 1; + a = 0; + q = 1; + for i = 1:n + if q ~= 0 + s = beta(i)/q; + else + s = abs(b(i))/eps; + end + q = c(i) - x1 - s; + a = a + (q < 0); + end + if a < k + if a < m1 + xu = x1; + wu(m1) = x1; + else + xu = x1; + wu(a+1) = x1; + if x(a) > x1, x(a) = x1; end + end + else + x0 = x1; + end + end + x(k) = (x0 + xu)/2; +end +x = x(m1:m2)'; + +function x = tridisolve(a,b,c,d) +% TRIDISOLVE Solve tridiagonal system of equations. +% x = TRIDISOLVE(a,b,c,d) solves the system of linear equations +% b(1)*x(1) + c(1)*x(2) = d(1), +% a(j-1)*x(j-1) + b(j)*x(j) + c(j)*x(j+1) = d(j), j = 2:n-1, +% a(n-1)*x(n-1) + b(n)*x(n) = d(n). +% +% The algorithm does not use pivoting, so the results might +% be inaccurate if abs(b) is much smaller than abs(a)+abs(c). +% More robust, but slower, alternatives with pivoting are: +% x = T\d where T = diag(a,-1) + diag(b,0) + diag(c,1) +% x = S\d where S = spdiags([[a; 0] b [0; c]],[-1 0 1],n,n) + +x = d; +n = length(x); + +for j = 1:n-1 + mu = a(j)/b(j); + b(j+1) = b(j+1) - mu*c(j); + x(j+1) = x(j+1) - mu*x(j); +end + +x(n) = x(n)/b(n); +for j = n-1:-1:1 + x(j) = (x(j)-c(j)*x(j+1))/b(j); +end + + diff --git a/toolbox/spectral/spm_mmtspec.m b/toolbox/spectral/spm_mmtspec.m new file mode 100644 index 0000000..9ad2c2c --- /dev/null +++ b/toolbox/spectral/spm_mmtspec.m @@ -0,0 +1,136 @@ +function [p, f, t] = spm_mmtspec (x,Fs, freqs,timeres, timestep, NW) +% Moving multitaper based spectrogram +% FORMAT [p, f, t] = spm_mmtspec (x,Fs,freqs,timeres) +% +% x input time series +% Fs sampling frequency of input time series +% freqs desired vector of frequencies for spectrogram eg. [6:1:30] +% timeres desired time resolution for spectrogram, default T/16 +% where T is duration of x +% +% p p(f, t) is estimate of power at freq f and time t +% +% Time series is split into a series of overlapping windows with 5% overlap. +% Desired frequency resolution is attained by zero padding +% as/if necessary. The taper approach is applied to each padded sample. +% +% Plot spectrogram using imagesc(t,f,p); axis xy +%___________________________________________________________________________ +% Copyright (C) 2009 Wellcome Trust Centre for Neuroimaging + +% Partha Mitra, Ken Harris and Will Penny +% $Id: spm_mmtspec.m 3994 2010-07-13 15:53:30Z guillaume $ + +nChannels = size(x, 2); +nSamples = size(x,1); + +if (nargin<4 || isempty(timeres)) + C=16; +else + C=round(nSamples/(Fs*timeres)); +end + +if (nargin<5 || isempty(timestep)) + percent_overlap=0.05; +else + percent_overlap= 1-timestep/timeres; +end + +if (nargin<6 || isempty(NW)) + NW=3; +end + +if length(unique(diff(freqs))) > 1 + error('Varying frequency resolution is not supported.'); +end + +df=freqs(2)-freqs(1); +nFFT=round(Fs/df); + +WinLength=round(nSamples/C); +nOverlap=ceil(percent_overlap*WinLength); + +nTapers = 2*NW -1; + +% Now do some computations that are common to all spectrogram functions + +winstep = WinLength - nOverlap; + + +% check for column vector input +if nSamples == 1 + x = x'; + nSamples = size(x,1); + nChannels = 1; +end; + +if nSamples < WinLength + disp('Error in spm_mmtspec: win length must be less than number of samples'); + return; +end + +% calculate number of FFTChunks per channel +nFFTChunks = round(((nSamples-WinLength)/winstep)); +% turn this into time, using the sample frequency +t = winstep*(0:(nFFTChunks-1))'/Fs; + +% set up f and t arrays +if ~any(any(imag(x))) % x purely real + if rem(nFFT,2), % nfft odd + select = [1:(nFFT+1)/2]; + else + select = [1:nFFT/2+1]; + end + nFreqBins = length(select); +else + select = 1:nFFT; +end +f = (select - 1)'*Fs/nFFT; + + +% allocate memory now to avoid nasty surprises later +y=complex(zeros(nFreqBins, nFFTChunks, nChannels, nChannels)); % output array +Periodogram = complex(zeros(nFreqBins, nTapers, nChannels, nFFTChunks)); % intermediate FFTs +Temp1 = complex(zeros(nFFT, nTapers, nFFTChunks)); +Temp2 = complex(zeros(nFFT, nTapers, nFFTChunks)); +Temp3 = complex(zeros(nFFT, nTapers, nFFTChunks)); +eJ = complex(zeros(nFFT, nFFTChunks)); + +% calculate Slepian sequences. +%Tapers=spm_dpss(WinLength,NW); +Tapers=spm_dpss(max(nFFT,WinLength),NW); +Tapers=Tapers(:,1:nTapers); + +% Vectorized alogrithm for computing tapered periodogram with FFT +TaperingArray = repmat(Tapers, [1 1 nChannels]); +for j=1:nFFTChunks + Segment = x((j-1)*winstep+[1:WinLength], :); + + if WinLength=(freqs(1)-0.1) & f <=(freqs(end)+0.1)); +f=f(ind); +p= p(ind,:, :); +